From 482840e61f86ca321838a91e902c41d40c098bbb Mon Sep 17 00:00:00 2001 From: Lorry Tar Creator Date: Wed, 24 Dec 2014 07:38:37 +0000 Subject: Imported from /home/lorry/working-area/delta_gettext-tarball/gettext-0.19.4.tar.xz. --- gettext-tools/gnulib-lib/Makefile.am | 75 + gettext-tools/gnulib-lib/Makefile.gnulib | 4301 ++ gettext-tools/gnulib-lib/Makefile.in | 5013 ++ gettext-tools/gnulib-lib/acl-errno-valid.c | 52 + gettext-tools/gnulib-lib/acl-internal.h | 253 + gettext-tools/gnulib-lib/acl.h | 35 + gettext-tools/gnulib-lib/acl_entries.c | 75 + gettext-tools/gnulib-lib/addext.c | 97 + gettext-tools/gnulib-lib/alignof.h | 50 + gettext-tools/gnulib-lib/alloca.in.h | 68 + gettext-tools/gnulib-lib/allocator.c | 5 + gettext-tools/gnulib-lib/allocator.h | 58 + gettext-tools/gnulib-lib/areadlink.c | 56 + gettext-tools/gnulib-lib/areadlink.h | 33 + gettext-tools/gnulib-lib/argmatch.c | 277 + gettext-tools/gnulib-lib/argmatch.h | 111 + gettext-tools/gnulib-lib/asnprintf.c | 34 + gettext-tools/gnulib-lib/asprintf.c | 39 + gettext-tools/gnulib-lib/atexit.c | 13 + gettext-tools/gnulib-lib/backupfile.c | 235 + gettext-tools/gnulib-lib/backupfile.h | 61 + gettext-tools/gnulib-lib/basename.c | 84 + gettext-tools/gnulib-lib/basename.h | 43 + gettext-tools/gnulib-lib/binary-io.c | 3 + gettext-tools/gnulib-lib/binary-io.h | 75 + gettext-tools/gnulib-lib/byteswap.in.h | 44 + gettext-tools/gnulib-lib/c-ctype.c | 395 + gettext-tools/gnulib-lib/c-ctype.h | 295 + gettext-tools/gnulib-lib/c-strcase.h | 56 + gettext-tools/gnulib-lib/c-strcasecmp.c | 56 + gettext-tools/gnulib-lib/c-strcaseeq.h | 184 + gettext-tools/gnulib-lib/c-strcasestr.c | 77 + gettext-tools/gnulib-lib/c-strcasestr.h | 36 + gettext-tools/gnulib-lib/c-strncasecmp.c | 56 + gettext-tools/gnulib-lib/c-strstr.c | 32 + gettext-tools/gnulib-lib/c-strstr.h | 44 + gettext-tools/gnulib-lib/canonicalize-lgpl.c | 411 + gettext-tools/gnulib-lib/careadlinkat.c | 160 + gettext-tools/gnulib-lib/careadlinkat.h | 67 + gettext-tools/gnulib-lib/classpath.c | 122 + gettext-tools/gnulib-lib/classpath.h | 33 + gettext-tools/gnulib-lib/clean-temp.c | 783 + gettext-tools/gnulib-lib/clean-temp.h | 142 + gettext-tools/gnulib-lib/cloexec.c | 83 + gettext-tools/gnulib-lib/cloexec.h | 38 + gettext-tools/gnulib-lib/close.c | 69 + gettext-tools/gnulib-lib/closedir.c | 67 + gettext-tools/gnulib-lib/closeout.c | 87 + gettext-tools/gnulib-lib/closeout.h | 30 + gettext-tools/gnulib-lib/concat-filename.c | 73 + gettext-tools/gnulib-lib/concat-filename.h | 41 + gettext-tools/gnulib-lib/config.charset | 684 + gettext-tools/gnulib-lib/copy-acl.c | 61 + gettext-tools/gnulib-lib/copy-file.c | 218 + gettext-tools/gnulib-lib/copy-file.h | 54 + gettext-tools/gnulib-lib/csharpcomp.c | 573 + gettext-tools/gnulib-lib/csharpcomp.h | 40 + gettext-tools/gnulib-lib/csharpexec.c | 345 + gettext-tools/gnulib-lib/csharpexec.h | 43 + gettext-tools/gnulib-lib/diffseq.h | 425 + gettext-tools/gnulib-lib/dirent-private.h | 40 + gettext-tools/gnulib-lib/dirent.in.h | 258 + gettext-tools/gnulib-lib/dosname.h | 53 + gettext-tools/gnulib-lib/dup-safer-flag.c | 38 + gettext-tools/gnulib-lib/dup-safer.c | 34 + gettext-tools/gnulib-lib/dup2.c | 164 + gettext-tools/gnulib-lib/errno.in.h | 279 + gettext-tools/gnulib-lib/error-progname.c | 40 + gettext-tools/gnulib-lib/error-progname.h | 52 + gettext-tools/gnulib-lib/error.c | 406 + gettext-tools/gnulib-lib/error.h | 74 + gettext-tools/gnulib-lib/execute.c | 280 + gettext-tools/gnulib-lib/execute.h | 44 + gettext-tools/gnulib-lib/exitfail.c | 24 + gettext-tools/gnulib-lib/exitfail.h | 18 + gettext-tools/gnulib-lib/fatal-signal.c | 286 + gettext-tools/gnulib-lib/fatal-signal.h | 76 + gettext-tools/gnulib-lib/fcntl.c | 327 + gettext-tools/gnulib-lib/fcntl.in.h | 363 + gettext-tools/gnulib-lib/fd-hook.c | 116 + gettext-tools/gnulib-lib/fd-hook.h | 119 + gettext-tools/gnulib-lib/fd-ostream.c | 219 + gettext-tools/gnulib-lib/fd-ostream.h | 137 + gettext-tools/gnulib-lib/fd-ostream.oo.c | 168 + gettext-tools/gnulib-lib/fd-ostream.oo.h | 48 + gettext-tools/gnulib-lib/fd-safer-flag.c | 52 + gettext-tools/gnulib-lib/fd-safer.c | 49 + gettext-tools/gnulib-lib/fd_ostream.priv.h | 14 + gettext-tools/gnulib-lib/fd_ostream.vt.h | 6 + gettext-tools/gnulib-lib/file-has-acl.c | 919 + gettext-tools/gnulib-lib/file-ostream.c | 120 + gettext-tools/gnulib-lib/file-ostream.h | 135 + gettext-tools/gnulib-lib/file-ostream.oo.c | 66 + gettext-tools/gnulib-lib/file-ostream.oo.h | 46 + gettext-tools/gnulib-lib/file_ostream.priv.h | 11 + gettext-tools/gnulib-lib/file_ostream.vt.h | 6 + gettext-tools/gnulib-lib/filename.h | 54 + gettext-tools/gnulib-lib/findprog.c | 138 + gettext-tools/gnulib-lib/findprog.h | 37 + gettext-tools/gnulib-lib/float+.h | 147 + gettext-tools/gnulib-lib/float.c | 33 + gettext-tools/gnulib-lib/float.in.h | 188 + gettext-tools/gnulib-lib/fnmatch.c | 354 + gettext-tools/gnulib-lib/fnmatch.in.h | 67 + gettext-tools/gnulib-lib/fnmatch_loop.c | 1278 + gettext-tools/gnulib-lib/fopen.c | 110 + gettext-tools/gnulib-lib/fstat.c | 88 + gettext-tools/gnulib-lib/fstrcmp.c | 237 + gettext-tools/gnulib-lib/fstrcmp.h | 45 + gettext-tools/gnulib-lib/full-write.c | 79 + gettext-tools/gnulib-lib/full-write.h | 34 + gettext-tools/gnulib-lib/fwriteerror.c | 181 + gettext-tools/gnulib-lib/fwriteerror.h | 62 + gettext-tools/gnulib-lib/gcd.c | 87 + gettext-tools/gnulib-lib/gcd.h | 34 + gettext-tools/gnulib-lib/getdelim.c | 135 + gettext-tools/gnulib-lib/getdtablesize.c | 115 + gettext-tools/gnulib-lib/getline.c | 27 + gettext-tools/gnulib-lib/getopt.c | 1245 + gettext-tools/gnulib-lib/getopt.in.h | 263 + gettext-tools/gnulib-lib/getopt1.c | 170 + gettext-tools/gnulib-lib/getopt_int.h | 135 + gettext-tools/gnulib-lib/gettext.h | 287 + gettext-tools/gnulib-lib/gettimeofday.c | 154 + gettext-tools/gnulib-lib/gl_anyhash_list1.h | 27 + gettext-tools/gnulib-lib/gl_anyhash_list2.h | 138 + gettext-tools/gnulib-lib/gl_anylinked_list1.h | 48 + gettext-tools/gnulib-lib/gl_anylinked_list2.h | 1195 + gettext-tools/gnulib-lib/gl_array_list.c | 680 + gettext-tools/gnulib-lib/gl_array_list.h | 34 + gettext-tools/gnulib-lib/gl_linkedhash_list.c | 124 + gettext-tools/gnulib-lib/gl_linkedhash_list.h | 34 + gettext-tools/gnulib-lib/gl_list.c | 3 + gettext-tools/gnulib-lib/gl_list.h | 841 + gettext-tools/gnulib-lib/gl_xlist.c | 3 + gettext-tools/gnulib-lib/gl_xlist.h | 177 + gettext-tools/gnulib-lib/glib.in.h | 98 + gettext-tools/gnulib-lib/glib/ghash.c | 816 + gettext-tools/gnulib-lib/glib/ghash.in.h | 132 + gettext-tools/gnulib-lib/glib/glist.c | 688 + gettext-tools/gnulib-lib/glib/glist.in.h | 136 + gettext-tools/gnulib-lib/glib/gmessages.c | 68 + gettext-tools/gnulib-lib/glib/gprimes.c | 98 + gettext-tools/gnulib-lib/glib/gprimes.in.h | 51 + gettext-tools/gnulib-lib/glib/gstrfuncs.c | 2848 + gettext-tools/gnulib-lib/glib/gstrfuncs.in.h | 269 + gettext-tools/gnulib-lib/glib/gstring.c | 958 + gettext-tools/gnulib-lib/glib/gstring.in.h | 179 + gettext-tools/gnulib-lib/glib/gtypes.in.h | 430 + gettext-tools/gnulib-lib/glibconfig.in.h | 189 + gettext-tools/gnulib-lib/glthread/lock.c | 1057 + gettext-tools/gnulib-lib/glthread/lock.h | 927 + gettext-tools/gnulib-lib/glthread/threadlib.c | 73 + gettext-tools/gnulib-lib/glthread/tls.c | 61 + gettext-tools/gnulib-lib/glthread/tls.h | 299 + gettext-tools/gnulib-lib/hash.c | 383 + gettext-tools/gnulib-lib/hash.h | 90 + gettext-tools/gnulib-lib/html-ostream.c | 338 + gettext-tools/gnulib-lib/html-ostream.h | 158 + gettext-tools/gnulib-lib/html-ostream.oo.c | 277 + gettext-tools/gnulib-lib/html-ostream.oo.h | 58 + gettext-tools/gnulib-lib/html-styled-ostream.c | 227 + gettext-tools/gnulib-lib/html-styled-ostream.h | 160 + gettext-tools/gnulib-lib/html-styled-ostream.oo.c | 158 + gettext-tools/gnulib-lib/html-styled-ostream.oo.h | 48 + gettext-tools/gnulib-lib/html_ostream.priv.h | 21 + gettext-tools/gnulib-lib/html_ostream.vt.h | 8 + .../gnulib-lib/html_styled_ostream.priv.h | 14 + gettext-tools/gnulib-lib/html_styled_ostream.vt.h | 6 + gettext-tools/gnulib-lib/iconv.c | 449 + gettext-tools/gnulib-lib/iconv.in.h | 110 + gettext-tools/gnulib-lib/iconv_close.c | 46 + gettext-tools/gnulib-lib/iconv_open-aix.gperf | 44 + gettext-tools/gnulib-lib/iconv_open-aix.h | 256 + gettext-tools/gnulib-lib/iconv_open-hpux.gperf | 56 + gettext-tools/gnulib-lib/iconv_open-hpux.h | 299 + gettext-tools/gnulib-lib/iconv_open-irix.gperf | 31 + gettext-tools/gnulib-lib/iconv_open-irix.h | 199 + gettext-tools/gnulib-lib/iconv_open-osf.gperf | 50 + gettext-tools/gnulib-lib/iconv_open-osf.h | 278 + gettext-tools/gnulib-lib/iconv_open-solaris.gperf | 30 + gettext-tools/gnulib-lib/iconv_open-solaris.h | 190 + gettext-tools/gnulib-lib/iconv_open.c | 172 + gettext-tools/gnulib-lib/iconveh.h | 41 + gettext-tools/gnulib-lib/ignore-value.h | 50 + gettext-tools/gnulib-lib/intprops.h | 320 + gettext-tools/gnulib-lib/iswblank.c | 26 + gettext-tools/gnulib-lib/itold.c | 28 + gettext-tools/gnulib-lib/javacomp.c | 2350 + gettext-tools/gnulib-lib/javacomp.h | 75 + gettext-tools/gnulib-lib/javaexec.c | 429 + gettext-tools/gnulib-lib/javaexec.h | 50 + gettext-tools/gnulib-lib/javaversion.c | 119 + gettext-tools/gnulib-lib/javaversion.class | Bin 0 -> 510 bytes gettext-tools/gnulib-lib/javaversion.h | 39 + gettext-tools/gnulib-lib/javaversion.java | 31 + .../gnulib-lib/libcroco/cr-additional-sel.c | 501 + .../gnulib-lib/libcroco/cr-additional-sel.h | 98 + gettext-tools/gnulib-lib/libcroco/cr-attr-sel.c | 236 + gettext-tools/gnulib-lib/libcroco/cr-attr-sel.h | 74 + gettext-tools/gnulib-lib/libcroco/cr-cascade.c | 215 + gettext-tools/gnulib-lib/libcroco/cr-cascade.h | 74 + gettext-tools/gnulib-lib/libcroco/cr-declaration.c | 823 + gettext-tools/gnulib-lib/libcroco/cr-declaration.h | 136 + gettext-tools/gnulib-lib/libcroco/cr-doc-handler.c | 275 + gettext-tools/gnulib-lib/libcroco/cr-doc-handler.h | 298 + gettext-tools/gnulib-lib/libcroco/cr-enc-handler.c | 187 + gettext-tools/gnulib-lib/libcroco/cr-enc-handler.h | 94 + gettext-tools/gnulib-lib/libcroco/cr-fonts.c | 947 + gettext-tools/gnulib-lib/libcroco/cr-fonts.h | 315 + gettext-tools/gnulib-lib/libcroco/cr-input.c | 1183 + gettext-tools/gnulib-lib/libcroco/cr-input.h | 174 + gettext-tools/gnulib-lib/libcroco/cr-num.c | 312 + gettext-tools/gnulib-lib/libcroco/cr-num.h | 127 + gettext-tools/gnulib-lib/libcroco/cr-om-parser.c | 1122 + gettext-tools/gnulib-lib/libcroco/cr-om-parser.h | 98 + gettext-tools/gnulib-lib/libcroco/cr-parser.c | 4524 ++ gettext-tools/gnulib-lib/libcroco/cr-parser.h | 128 + .../gnulib-lib/libcroco/cr-parsing-location.c | 173 + .../gnulib-lib/libcroco/cr-parsing-location.h | 70 + gettext-tools/gnulib-lib/libcroco/cr-prop-list.c | 402 + gettext-tools/gnulib-lib/libcroco/cr-prop-list.h | 80 + gettext-tools/gnulib-lib/libcroco/cr-pseudo.c | 167 + gettext-tools/gnulib-lib/libcroco/cr-pseudo.h | 64 + gettext-tools/gnulib-lib/libcroco/cr-rgb.c | 678 + gettext-tools/gnulib-lib/libcroco/cr-rgb.h | 94 + gettext-tools/gnulib-lib/libcroco/cr-sel-eng.c | 1572 + gettext-tools/gnulib-lib/libcroco/cr-sel-eng.h | 114 + gettext-tools/gnulib-lib/libcroco/cr-selector.c | 307 + gettext-tools/gnulib-lib/libcroco/cr-selector.h | 95 + gettext-tools/gnulib-lib/libcroco/cr-simple-sel.c | 325 + gettext-tools/gnulib-lib/libcroco/cr-simple-sel.h | 130 + gettext-tools/gnulib-lib/libcroco/cr-statement.c | 2791 + gettext-tools/gnulib-lib/libcroco/cr-statement.h | 440 + gettext-tools/gnulib-lib/libcroco/cr-string.c | 169 + gettext-tools/gnulib-lib/libcroco/cr-string.h | 76 + gettext-tools/gnulib-lib/libcroco/cr-style.c | 2852 + gettext-tools/gnulib-lib/libcroco/cr-style.h | 339 + gettext-tools/gnulib-lib/libcroco/cr-stylesheet.c | 179 + gettext-tools/gnulib-lib/libcroco/cr-stylesheet.h | 102 + gettext-tools/gnulib-lib/libcroco/cr-term.c | 792 + gettext-tools/gnulib-lib/libcroco/cr-term.h | 190 + gettext-tools/gnulib-lib/libcroco/cr-tknzr.c | 2764 + gettext-tools/gnulib-lib/libcroco/cr-tknzr.h | 115 + gettext-tools/gnulib-lib/libcroco/cr-token.c | 637 + gettext-tools/gnulib-lib/libcroco/cr-token.h | 212 + gettext-tools/gnulib-lib/libcroco/cr-utils.c | 1357 + gettext-tools/gnulib-lib/libcroco/cr-utils.h | 249 + .../gnulib-lib/libcroco/libcroco-config.h | 18 + gettext-tools/gnulib-lib/libcroco/libcroco.h | 44 + gettext-tools/gnulib-lib/libunistring.valgrind | 9 + gettext-tools/gnulib-lib/libxml/COPYING | 27 + gettext-tools/gnulib-lib/libxml/DOCBparser.c | 305 + gettext-tools/gnulib-lib/libxml/DOCBparser.in.h | 96 + gettext-tools/gnulib-lib/libxml/HTMLparser.c | 6276 ++ gettext-tools/gnulib-lib/libxml/HTMLparser.in.h | 303 + gettext-tools/gnulib-lib/libxml/HTMLtree.c | 1213 + gettext-tools/gnulib-lib/libxml/HTMLtree.in.h | 147 + gettext-tools/gnulib-lib/libxml/SAX.c | 180 + gettext-tools/gnulib-lib/libxml/SAX.in.h | 173 + gettext-tools/gnulib-lib/libxml/SAX2.c | 2891 + gettext-tools/gnulib-lib/libxml/SAX2.in.h | 176 + gettext-tools/gnulib-lib/libxml/c14n.c | 1928 + gettext-tools/gnulib-lib/libxml/c14n.in.h | 105 + gettext-tools/gnulib-lib/libxml/catalog.c | 3788 ++ gettext-tools/gnulib-lib/libxml/catalog.in.h | 182 + gettext-tools/gnulib-lib/libxml/chvalid.c | 336 + gettext-tools/gnulib-lib/libxml/chvalid.in.h | 230 + gettext-tools/gnulib-lib/libxml/debugXML.c | 3264 + gettext-tools/gnulib-lib/libxml/debugXML.in.h | 217 + gettext-tools/gnulib-lib/libxml/dict.c | 901 + gettext-tools/gnulib-lib/libxml/dict.in.h | 69 + gettext-tools/gnulib-lib/libxml/elfgcchack.h | 0 gettext-tools/gnulib-lib/libxml/encoding.c | 3295 + gettext-tools/gnulib-lib/libxml/encoding.in.h | 226 + gettext-tools/gnulib-lib/libxml/entities.c | 966 + gettext-tools/gnulib-lib/libxml/entities.in.h | 140 + gettext-tools/gnulib-lib/libxml/error.c | 986 + gettext-tools/gnulib-lib/libxml/globals.c | 1094 + gettext-tools/gnulib-lib/libxml/globals.in.h | 455 + gettext-tools/gnulib-lib/libxml/hash.c | 1079 + gettext-tools/gnulib-lib/libxml/hash.in.h | 233 + gettext-tools/gnulib-lib/libxml/legacy.c | 1343 + gettext-tools/gnulib-lib/libxml/libxml.h | 79 + gettext-tools/gnulib-lib/libxml/list.c | 779 + gettext-tools/gnulib-lib/libxml/list.in.h | 137 + gettext-tools/gnulib-lib/libxml/nanoftp.c | 2109 + gettext-tools/gnulib-lib/libxml/nanoftp.in.h | 143 + gettext-tools/gnulib-lib/libxml/nanohttp.c | 1791 + gettext-tools/gnulib-lib/libxml/nanohttp.in.h | 81 + gettext-tools/gnulib-lib/libxml/parser.c | 13614 ++++ gettext-tools/gnulib-lib/libxml/parser.in.h | 1220 + gettext-tools/gnulib-lib/libxml/parserInternals.c | 2061 + .../gnulib-lib/libxml/parserInternals.in.h | 602 + gettext-tools/gnulib-lib/libxml/pattern.c | 2607 + gettext-tools/gnulib-lib/libxml/pattern.in.h | 100 + gettext-tools/gnulib-lib/libxml/relaxng.c | 10815 ++++ gettext-tools/gnulib-lib/libxml/relaxng.in.h | 196 + .../gnulib-lib/libxml/schemasInternals.in.h | 958 + gettext-tools/gnulib-lib/libxml/schematron.c | 1730 + gettext-tools/gnulib-lib/libxml/schematron.in.h | 124 + gettext-tools/gnulib-lib/libxml/threads.c | 867 + gettext-tools/gnulib-lib/libxml/threads.in.h | 80 + gettext-tools/gnulib-lib/libxml/tree.c | 9537 +++ gettext-tools/gnulib-lib/libxml/tree.in.h | 1208 + gettext-tools/gnulib-lib/libxml/uri.c | 2483 + gettext-tools/gnulib-lib/libxml/uri.in.h | 89 + gettext-tools/gnulib-lib/libxml/valid.c | 6955 +++ gettext-tools/gnulib-lib/libxml/valid.in.h | 458 + gettext-tools/gnulib-lib/libxml/xinclude.c | 2555 + gettext-tools/gnulib-lib/libxml/xinclude.in.h | 125 + gettext-tools/gnulib-lib/libxml/xlink.c | 183 + gettext-tools/gnulib-lib/libxml/xlink.in.h | 189 + gettext-tools/gnulib-lib/libxml/xmlIO.c | 3850 ++ gettext-tools/gnulib-lib/libxml/xmlIO.in.h | 360 + gettext-tools/gnulib-lib/libxml/xmlautomata.in.h | 146 + gettext-tools/gnulib-lib/libxml/xmlerror.in.h | 936 + gettext-tools/gnulib-lib/libxml/xmlexports.in.h | 157 + gettext-tools/gnulib-lib/libxml/xmlmemory.c | 1044 + gettext-tools/gnulib-lib/libxml/xmlmemory.in.h | 222 + gettext-tools/gnulib-lib/libxml/xmlmodule.c | 445 + gettext-tools/gnulib-lib/libxml/xmlmodule.in.h | 57 + gettext-tools/gnulib-lib/libxml/xmlreader.c | 5659 ++ gettext-tools/gnulib-lib/libxml/xmlreader.in.h | 408 + gettext-tools/gnulib-lib/libxml/xmlregexp.c | 7959 +++ gettext-tools/gnulib-lib/libxml/xmlregexp.in.h | 216 + gettext-tools/gnulib-lib/libxml/xmlsave.c | 2406 + gettext-tools/gnulib-lib/libxml/xmlsave.in.h | 84 + gettext-tools/gnulib-lib/libxml/xmlschemas.c | 28654 +++++++++ gettext-tools/gnulib-lib/libxml/xmlschemas.in.h | 198 + gettext-tools/gnulib-lib/libxml/xmlschemastypes.c | 6113 ++ .../gnulib-lib/libxml/xmlschemastypes.in.h | 151 + gettext-tools/gnulib-lib/libxml/xmlstring.c | 984 + gettext-tools/gnulib-lib/libxml/xmlstring.in.h | 140 + gettext-tools/gnulib-lib/libxml/xmlunicode.c | 3179 + gettext-tools/gnulib-lib/libxml/xmlunicode.in.h | 202 + gettext-tools/gnulib-lib/libxml/xmlversion.in.h | 405 + gettext-tools/gnulib-lib/libxml/xmlwriter.c | 4615 ++ gettext-tools/gnulib-lib/libxml/xmlwriter.in.h | 459 + gettext-tools/gnulib-lib/libxml/xpath.c | 15066 +++++ gettext-tools/gnulib-lib/libxml/xpath.in.h | 543 + .../gnulib-lib/libxml/xpathInternals.in.h | 630 + gettext-tools/gnulib-lib/libxml/xpointer.c | 3003 + gettext-tools/gnulib-lib/libxml/xpointer.in.h | 114 + gettext-tools/gnulib-lib/localcharset.c | 579 + gettext-tools/gnulib-lib/localcharset.h | 40 + gettext-tools/gnulib-lib/locale.in.h | 216 + gettext-tools/gnulib-lib/localename.c | 2958 + gettext-tools/gnulib-lib/localename.h | 99 + gettext-tools/gnulib-lib/lstat.c | 97 + gettext-tools/gnulib-lib/malloc.c | 56 + gettext-tools/gnulib-lib/malloca.c | 149 + gettext-tools/gnulib-lib/malloca.h | 133 + gettext-tools/gnulib-lib/malloca.valgrind | 7 + gettext-tools/gnulib-lib/mbchar.c | 37 + gettext-tools/gnulib-lib/mbchar.h | 360 + gettext-tools/gnulib-lib/mbiter.c | 3 + gettext-tools/gnulib-lib/mbiter.h | 225 + gettext-tools/gnulib-lib/mbrtowc.c | 407 + gettext-tools/gnulib-lib/mbsinit.c | 61 + gettext-tools/gnulib-lib/mbslen.c | 44 + gettext-tools/gnulib-lib/mbsrtowcs-impl.h | 122 + gettext-tools/gnulib-lib/mbsrtowcs-state.c | 37 + gettext-tools/gnulib-lib/mbsrtowcs.c | 32 + gettext-tools/gnulib-lib/mbsstr.c | 384 + gettext-tools/gnulib-lib/mbswidth.c | 193 + gettext-tools/gnulib-lib/mbswidth.h | 60 + gettext-tools/gnulib-lib/mbuiter.c | 3 + gettext-tools/gnulib-lib/mbuiter.h | 232 + gettext-tools/gnulib-lib/memchr.c | 172 + gettext-tools/gnulib-lib/memchr.valgrind | 14 + gettext-tools/gnulib-lib/memmove.c | 26 + gettext-tools/gnulib-lib/memset.c | 29 + gettext-tools/gnulib-lib/minmax.h | 60 + gettext-tools/gnulib-lib/mkdtemp.c | 39 + gettext-tools/gnulib-lib/moo.h | 248 + gettext-tools/gnulib-lib/msvc-inval.c | 129 + gettext-tools/gnulib-lib/msvc-inval.h | 222 + gettext-tools/gnulib-lib/msvc-nothrow.c | 49 + gettext-tools/gnulib-lib/msvc-nothrow.h | 43 + gettext-tools/gnulib-lib/obstack.c | 353 + gettext-tools/gnulib-lib/obstack.h | 531 + gettext-tools/gnulib-lib/open.c | 181 + gettext-tools/gnulib-lib/opendir.c | 148 + gettext-tools/gnulib-lib/ostream.c | 122 + gettext-tools/gnulib-lib/ostream.h | 141 + gettext-tools/gnulib-lib/ostream.oo.c | 36 + gettext-tools/gnulib-lib/ostream.oo.h | 64 + gettext-tools/gnulib-lib/ostream.priv.h | 7 + gettext-tools/gnulib-lib/ostream.vt.h | 6 + gettext-tools/gnulib-lib/pathmax.h | 83 + gettext-tools/gnulib-lib/pipe-filter-aux.c | 43 + gettext-tools/gnulib-lib/pipe-filter-aux.h | 103 + gettext-tools/gnulib-lib/pipe-filter-ii.c | 474 + gettext-tools/gnulib-lib/pipe-filter.h | 237 + gettext-tools/gnulib-lib/pipe-safer.c | 56 + gettext-tools/gnulib-lib/pipe2-safer.c | 52 + gettext-tools/gnulib-lib/pipe2.c | 168 + gettext-tools/gnulib-lib/printf-args.c | 187 + gettext-tools/gnulib-lib/printf-args.h | 158 + gettext-tools/gnulib-lib/printf-parse.c | 638 + gettext-tools/gnulib-lib/printf-parse.h | 193 + gettext-tools/gnulib-lib/progname.c | 92 + gettext-tools/gnulib-lib/progname.h | 62 + gettext-tools/gnulib-lib/progreloc.c | 372 + gettext-tools/gnulib-lib/propername.c | 318 + gettext-tools/gnulib-lib/propername.h | 106 + gettext-tools/gnulib-lib/qcopy-acl.c | 583 + gettext-tools/gnulib-lib/qset-acl.c | 676 + gettext-tools/gnulib-lib/quote.h | 46 + gettext-tools/gnulib-lib/quotearg.c | 968 + gettext-tools/gnulib-lib/quotearg.h | 391 + gettext-tools/gnulib-lib/raise.c | 79 + gettext-tools/gnulib-lib/rawmemchr.c | 136 + gettext-tools/gnulib-lib/rawmemchr.valgrind | 12 + gettext-tools/gnulib-lib/read.c | 85 + gettext-tools/gnulib-lib/readdir.c | 98 + gettext-tools/gnulib-lib/readlink.c | 74 + gettext-tools/gnulib-lib/realloc.c | 79 + gettext-tools/gnulib-lib/ref-add.sin | 29 + gettext-tools/gnulib-lib/ref-del.sin | 24 + gettext-tools/gnulib-lib/relocatable.c | 496 + gettext-tools/gnulib-lib/relocatable.h | 81 + gettext-tools/gnulib-lib/relocwrapper.c | 198 + gettext-tools/gnulib-lib/rmdir.c | 53 + gettext-tools/gnulib-lib/safe-read.c | 77 + gettext-tools/gnulib-lib/safe-read.h | 47 + gettext-tools/gnulib-lib/safe-write.c | 18 + gettext-tools/gnulib-lib/safe-write.h | 37 + gettext-tools/gnulib-lib/sched.in.h | 57 + gettext-tools/gnulib-lib/secure_getenv.c | 41 + gettext-tools/gnulib-lib/set-acl.c | 48 + gettext-tools/gnulib-lib/setenv.c | 390 + gettext-tools/gnulib-lib/setlocale.c | 938 + gettext-tools/gnulib-lib/sh-quote.c | 107 + gettext-tools/gnulib-lib/sh-quote.h | 49 + gettext-tools/gnulib-lib/sig-handler.c | 3 + gettext-tools/gnulib-lib/sig-handler.h | 54 + gettext-tools/gnulib-lib/sigaction.c | 204 + gettext-tools/gnulib-lib/signal.in.h | 461 + gettext-tools/gnulib-lib/sigprocmask.c | 349 + gettext-tools/gnulib-lib/size_max.h | 30 + gettext-tools/gnulib-lib/snprintf.c | 71 + gettext-tools/gnulib-lib/spawn-pipe.c | 454 + gettext-tools/gnulib-lib/spawn-pipe.h | 147 + gettext-tools/gnulib-lib/spawn.in.h | 881 + gettext-tools/gnulib-lib/spawn_faction_addclose.c | 69 + gettext-tools/gnulib-lib/spawn_faction_adddup2.c | 70 + gettext-tools/gnulib-lib/spawn_faction_addopen.c | 73 + gettext-tools/gnulib-lib/spawn_faction_destroy.c | 31 + gettext-tools/gnulib-lib/spawn_faction_init.c | 56 + gettext-tools/gnulib-lib/spawn_int.h | 62 + gettext-tools/gnulib-lib/spawnattr_destroy.c | 28 + gettext-tools/gnulib-lib/spawnattr_init.c | 33 + gettext-tools/gnulib-lib/spawnattr_setflags.c | 45 + gettext-tools/gnulib-lib/spawnattr_setsigmask.c | 33 + gettext-tools/gnulib-lib/spawni.c | 374 + gettext-tools/gnulib-lib/spawnp.c | 33 + gettext-tools/gnulib-lib/stat.c | 138 + gettext-tools/gnulib-lib/stdarg.in.h | 35 + gettext-tools/gnulib-lib/stdbool.in.h | 132 + gettext-tools/gnulib-lib/stddef.in.h | 86 + gettext-tools/gnulib-lib/stdint.in.h | 635 + gettext-tools/gnulib-lib/stdio-write.c | 198 + gettext-tools/gnulib-lib/stdio.in.h | 1353 + gettext-tools/gnulib-lib/stdlib.in.h | 977 + gettext-tools/gnulib-lib/stpcpy.c | 49 + gettext-tools/gnulib-lib/stpncpy.c | 92 + gettext-tools/gnulib-lib/str-kmp.h | 153 + gettext-tools/gnulib-lib/str-two-way.h | 452 + gettext-tools/gnulib-lib/strchrnul.c | 142 + gettext-tools/gnulib-lib/strchrnul.valgrind | 12 + gettext-tools/gnulib-lib/strcspn.c | 41 + gettext-tools/gnulib-lib/streq.h | 176 + gettext-tools/gnulib-lib/strerror-override.c | 302 + gettext-tools/gnulib-lib/strerror-override.h | 56 + gettext-tools/gnulib-lib/strerror.c | 70 + gettext-tools/gnulib-lib/striconv.c | 463 + gettext-tools/gnulib-lib/striconv.h | 75 + gettext-tools/gnulib-lib/striconveh.c | 1199 + gettext-tools/gnulib-lib/striconveh.h | 140 + gettext-tools/gnulib-lib/striconveha.c | 352 + gettext-tools/gnulib-lib/striconveha.h | 95 + gettext-tools/gnulib-lib/string.in.h | 1029 + gettext-tools/gnulib-lib/strnlen.c | 30 + gettext-tools/gnulib-lib/strnlen1.c | 35 + gettext-tools/gnulib-lib/strnlen1.h | 40 + gettext-tools/gnulib-lib/strpbrk.c | 41 + gettext-tools/gnulib-lib/strstr.c | 82 + gettext-tools/gnulib-lib/strtol.c | 433 + gettext-tools/gnulib-lib/strtoul.c | 19 + gettext-tools/gnulib-lib/styled-ostream.c | 143 + gettext-tools/gnulib-lib/styled-ostream.h | 144 + gettext-tools/gnulib-lib/styled-ostream.oo.c | 27 + gettext-tools/gnulib-lib/styled-ostream.oo.h | 44 + gettext-tools/gnulib-lib/styled_ostream.priv.h | 10 + gettext-tools/gnulib-lib/styled_ostream.vt.h | 8 + gettext-tools/gnulib-lib/sys_select.in.h | 314 + gettext-tools/gnulib-lib/sys_stat.in.h | 732 + gettext-tools/gnulib-lib/sys_time.in.h | 213 + gettext-tools/gnulib-lib/sys_types.in.h | 53 + gettext-tools/gnulib-lib/sys_wait.in.h | 129 + gettext-tools/gnulib-lib/tempname.c | 306 + gettext-tools/gnulib-lib/tempname.h | 50 + gettext-tools/gnulib-lib/term-ostream.c | 2043 + gettext-tools/gnulib-lib/term-ostream.h | 282 + gettext-tools/gnulib-lib/term-ostream.oo.c | 1925 + gettext-tools/gnulib-lib/term-ostream.oo.h | 109 + gettext-tools/gnulib-lib/term-styled-ostream.c | 688 + gettext-tools/gnulib-lib/term-styled-ostream.h | 161 + gettext-tools/gnulib-lib/term-styled-ostream.oo.c | 631 + gettext-tools/gnulib-lib/term-styled-ostream.oo.h | 49 + gettext-tools/gnulib-lib/term_ostream.priv.h | 42 + gettext-tools/gnulib-lib/term_ostream.vt.h | 17 + .../gnulib-lib/term_styled_ostream.priv.h | 24 + gettext-tools/gnulib-lib/term_styled_ostream.vt.h | 6 + gettext-tools/gnulib-lib/terminfo.h | 114 + gettext-tools/gnulib-lib/time.in.h | 274 + gettext-tools/gnulib-lib/tmpdir.c | 159 + gettext-tools/gnulib-lib/tmpdir.h | 26 + gettext-tools/gnulib-lib/tparm.c | 896 + gettext-tools/gnulib-lib/tputs.c | 41 + gettext-tools/gnulib-lib/trim.c | 129 + gettext-tools/gnulib-lib/trim.h | 33 + gettext-tools/gnulib-lib/uniconv.in.h | 172 + .../gnulib-lib/uniconv/u8-conv-from-enc.c | 105 + gettext-tools/gnulib-lib/unilbrk.in.h | 110 + gettext-tools/gnulib-lib/unilbrk/lbrkprop1.h | 33 + gettext-tools/gnulib-lib/unilbrk/lbrkprop2.h | 2942 + gettext-tools/gnulib-lib/unilbrk/lbrktables.c | 64 + gettext-tools/gnulib-lib/unilbrk/lbrktables.h | 95 + .../gnulib-lib/unilbrk/u8-possible-linebreaks.c | 261 + .../gnulib-lib/unilbrk/u8-width-linebreaks.c | 204 + gettext-tools/gnulib-lib/unilbrk/ulc-common.c | 51 + gettext-tools/gnulib-lib/unilbrk/ulc-common.h | 31 + .../gnulib-lib/unilbrk/ulc-width-linebreaks.c | 231 + gettext-tools/gnulib-lib/uniname.in.h | 46 + gettext-tools/gnulib-lib/uniname/gen-uninames.lisp | 301 + gettext-tools/gnulib-lib/uniname/uniname.c | 516 + gettext-tools/gnulib-lib/uniname/uninames.h | 61495 +++++++++++++++++++ gettext-tools/gnulib-lib/unistd--.h | 32 + gettext-tools/gnulib-lib/unistd-safer.h | 31 + gettext-tools/gnulib-lib/unistd.c | 3 + gettext-tools/gnulib-lib/unistd.in.h | 1590 + gettext-tools/gnulib-lib/unistr.in.h | 750 + gettext-tools/gnulib-lib/unistr/u16-mbtouc-aux.c | 51 + gettext-tools/gnulib-lib/unistr/u16-mbtouc.c | 61 + gettext-tools/gnulib-lib/unistr/u8-check.c | 105 + gettext-tools/gnulib-lib/unistr/u8-mblen.c | 99 + gettext-tools/gnulib-lib/unistr/u8-mbtouc-aux.c | 240 + .../gnulib-lib/unistr/u8-mbtouc-unsafe-aux.c | 260 + gettext-tools/gnulib-lib/unistr/u8-mbtouc-unsafe.c | 271 + gettext-tools/gnulib-lib/unistr/u8-mbtouc.c | 250 + gettext-tools/gnulib-lib/unistr/u8-mbtoucr.c | 285 + gettext-tools/gnulib-lib/unistr/u8-prev.c | 93 + gettext-tools/gnulib-lib/unistr/u8-uctomb-aux.c | 69 + gettext-tools/gnulib-lib/unistr/u8-uctomb.c | 88 + gettext-tools/gnulib-lib/unitypes.in.h | 46 + gettext-tools/gnulib-lib/uniwidth.in.h | 72 + gettext-tools/gnulib-lib/uniwidth/cjk.h | 37 + gettext-tools/gnulib-lib/uniwidth/width.c | 368 + gettext-tools/gnulib-lib/unlocked-io.h | 136 + gettext-tools/gnulib-lib/unsetenv.c | 127 + gettext-tools/gnulib-lib/vasnprintf.c | 5595 ++ gettext-tools/gnulib-lib/vasnprintf.h | 79 + gettext-tools/gnulib-lib/vasprintf.c | 50 + gettext-tools/gnulib-lib/verify.h | 279 + gettext-tools/gnulib-lib/vsnprintf.c | 70 + gettext-tools/gnulib-lib/w32spawn.h | 222 + gettext-tools/gnulib-lib/wait-process.c | 361 + gettext-tools/gnulib-lib/wait-process.h | 74 + gettext-tools/gnulib-lib/waitpid.c | 30 + gettext-tools/gnulib-lib/wchar.in.h | 1028 + gettext-tools/gnulib-lib/wctype-h.c | 4 + gettext-tools/gnulib-lib/wctype.in.h | 514 + gettext-tools/gnulib-lib/wcwidth.c | 50 + gettext-tools/gnulib-lib/write.c | 145 + gettext-tools/gnulib-lib/xalloc.h | 158 + gettext-tools/gnulib-lib/xasprintf.c | 34 + gettext-tools/gnulib-lib/xconcat-filename.c | 41 + gettext-tools/gnulib-lib/xerror.c | 96 + gettext-tools/gnulib-lib/xerror.h | 45 + gettext-tools/gnulib-lib/xmalloc.c | 128 + gettext-tools/gnulib-lib/xmalloca.c | 38 + gettext-tools/gnulib-lib/xmalloca.h | 64 + gettext-tools/gnulib-lib/xreadlink.c | 44 + gettext-tools/gnulib-lib/xreadlink.h | 25 + gettext-tools/gnulib-lib/xsetenv.c | 38 + gettext-tools/gnulib-lib/xsetenv.h | 31 + gettext-tools/gnulib-lib/xsize.c | 3 + gettext-tools/gnulib-lib/xsize.h | 117 + gettext-tools/gnulib-lib/xstrdup.c | 40 + gettext-tools/gnulib-lib/xstriconv.c | 62 + gettext-tools/gnulib-lib/xstriconv.h | 78 + gettext-tools/gnulib-lib/xstriconveh.c | 86 + gettext-tools/gnulib-lib/xstriconveh.h | 115 + gettext-tools/gnulib-lib/xvasprintf.c | 110 + gettext-tools/gnulib-lib/xvasprintf.h | 55 + 598 files changed, 385345 insertions(+) create mode 100644 gettext-tools/gnulib-lib/Makefile.am create mode 100644 gettext-tools/gnulib-lib/Makefile.gnulib create mode 100644 gettext-tools/gnulib-lib/Makefile.in create mode 100644 gettext-tools/gnulib-lib/acl-errno-valid.c create mode 100644 gettext-tools/gnulib-lib/acl-internal.h create mode 100644 gettext-tools/gnulib-lib/acl.h create mode 100644 gettext-tools/gnulib-lib/acl_entries.c create mode 100644 gettext-tools/gnulib-lib/addext.c create mode 100644 gettext-tools/gnulib-lib/alignof.h create mode 100644 gettext-tools/gnulib-lib/alloca.in.h create mode 100644 gettext-tools/gnulib-lib/allocator.c create mode 100644 gettext-tools/gnulib-lib/allocator.h create mode 100644 gettext-tools/gnulib-lib/areadlink.c create mode 100644 gettext-tools/gnulib-lib/areadlink.h create mode 100644 gettext-tools/gnulib-lib/argmatch.c create mode 100644 gettext-tools/gnulib-lib/argmatch.h create mode 100644 gettext-tools/gnulib-lib/asnprintf.c create mode 100644 gettext-tools/gnulib-lib/asprintf.c create mode 100644 gettext-tools/gnulib-lib/atexit.c create mode 100644 gettext-tools/gnulib-lib/backupfile.c create mode 100644 gettext-tools/gnulib-lib/backupfile.h create mode 100644 gettext-tools/gnulib-lib/basename.c create mode 100644 gettext-tools/gnulib-lib/basename.h create mode 100644 gettext-tools/gnulib-lib/binary-io.c create mode 100644 gettext-tools/gnulib-lib/binary-io.h create mode 100644 gettext-tools/gnulib-lib/byteswap.in.h create mode 100644 gettext-tools/gnulib-lib/c-ctype.c create mode 100644 gettext-tools/gnulib-lib/c-ctype.h create mode 100644 gettext-tools/gnulib-lib/c-strcase.h create mode 100644 gettext-tools/gnulib-lib/c-strcasecmp.c create mode 100644 gettext-tools/gnulib-lib/c-strcaseeq.h create mode 100644 gettext-tools/gnulib-lib/c-strcasestr.c create mode 100644 gettext-tools/gnulib-lib/c-strcasestr.h create mode 100644 gettext-tools/gnulib-lib/c-strncasecmp.c create mode 100644 gettext-tools/gnulib-lib/c-strstr.c create mode 100644 gettext-tools/gnulib-lib/c-strstr.h create mode 100644 gettext-tools/gnulib-lib/canonicalize-lgpl.c create mode 100644 gettext-tools/gnulib-lib/careadlinkat.c create mode 100644 gettext-tools/gnulib-lib/careadlinkat.h create mode 100644 gettext-tools/gnulib-lib/classpath.c create mode 100644 gettext-tools/gnulib-lib/classpath.h create mode 100644 gettext-tools/gnulib-lib/clean-temp.c create mode 100644 gettext-tools/gnulib-lib/clean-temp.h create mode 100644 gettext-tools/gnulib-lib/cloexec.c create mode 100644 gettext-tools/gnulib-lib/cloexec.h create mode 100644 gettext-tools/gnulib-lib/close.c create mode 100644 gettext-tools/gnulib-lib/closedir.c create mode 100644 gettext-tools/gnulib-lib/closeout.c create mode 100644 gettext-tools/gnulib-lib/closeout.h create mode 100644 gettext-tools/gnulib-lib/concat-filename.c create mode 100644 gettext-tools/gnulib-lib/concat-filename.h create mode 100644 gettext-tools/gnulib-lib/config.charset create mode 100644 gettext-tools/gnulib-lib/copy-acl.c create mode 100644 gettext-tools/gnulib-lib/copy-file.c create mode 100644 gettext-tools/gnulib-lib/copy-file.h create mode 100644 gettext-tools/gnulib-lib/csharpcomp.c create mode 100644 gettext-tools/gnulib-lib/csharpcomp.h create mode 100644 gettext-tools/gnulib-lib/csharpexec.c create mode 100644 gettext-tools/gnulib-lib/csharpexec.h create mode 100644 gettext-tools/gnulib-lib/diffseq.h create mode 100644 gettext-tools/gnulib-lib/dirent-private.h create mode 100644 gettext-tools/gnulib-lib/dirent.in.h create mode 100644 gettext-tools/gnulib-lib/dosname.h create mode 100644 gettext-tools/gnulib-lib/dup-safer-flag.c create mode 100644 gettext-tools/gnulib-lib/dup-safer.c create mode 100644 gettext-tools/gnulib-lib/dup2.c create mode 100644 gettext-tools/gnulib-lib/errno.in.h create mode 100644 gettext-tools/gnulib-lib/error-progname.c create mode 100644 gettext-tools/gnulib-lib/error-progname.h create mode 100644 gettext-tools/gnulib-lib/error.c create mode 100644 gettext-tools/gnulib-lib/error.h create mode 100644 gettext-tools/gnulib-lib/execute.c create mode 100644 gettext-tools/gnulib-lib/execute.h create mode 100644 gettext-tools/gnulib-lib/exitfail.c create mode 100644 gettext-tools/gnulib-lib/exitfail.h create mode 100644 gettext-tools/gnulib-lib/fatal-signal.c create mode 100644 gettext-tools/gnulib-lib/fatal-signal.h create mode 100644 gettext-tools/gnulib-lib/fcntl.c create mode 100644 gettext-tools/gnulib-lib/fcntl.in.h create mode 100644 gettext-tools/gnulib-lib/fd-hook.c create mode 100644 gettext-tools/gnulib-lib/fd-hook.h create mode 100644 gettext-tools/gnulib-lib/fd-ostream.c create mode 100644 gettext-tools/gnulib-lib/fd-ostream.h create mode 100644 gettext-tools/gnulib-lib/fd-ostream.oo.c create mode 100644 gettext-tools/gnulib-lib/fd-ostream.oo.h create mode 100644 gettext-tools/gnulib-lib/fd-safer-flag.c create mode 100644 gettext-tools/gnulib-lib/fd-safer.c create mode 100644 gettext-tools/gnulib-lib/fd_ostream.priv.h create mode 100644 gettext-tools/gnulib-lib/fd_ostream.vt.h create mode 100644 gettext-tools/gnulib-lib/file-has-acl.c create mode 100644 gettext-tools/gnulib-lib/file-ostream.c create mode 100644 gettext-tools/gnulib-lib/file-ostream.h create mode 100644 gettext-tools/gnulib-lib/file-ostream.oo.c create mode 100644 gettext-tools/gnulib-lib/file-ostream.oo.h create mode 100644 gettext-tools/gnulib-lib/file_ostream.priv.h create mode 100644 gettext-tools/gnulib-lib/file_ostream.vt.h create mode 100644 gettext-tools/gnulib-lib/filename.h create mode 100644 gettext-tools/gnulib-lib/findprog.c create mode 100644 gettext-tools/gnulib-lib/findprog.h create mode 100644 gettext-tools/gnulib-lib/float+.h create mode 100644 gettext-tools/gnulib-lib/float.c create mode 100644 gettext-tools/gnulib-lib/float.in.h create mode 100644 gettext-tools/gnulib-lib/fnmatch.c create mode 100644 gettext-tools/gnulib-lib/fnmatch.in.h create mode 100644 gettext-tools/gnulib-lib/fnmatch_loop.c create mode 100644 gettext-tools/gnulib-lib/fopen.c create mode 100644 gettext-tools/gnulib-lib/fstat.c create mode 100644 gettext-tools/gnulib-lib/fstrcmp.c create mode 100644 gettext-tools/gnulib-lib/fstrcmp.h create mode 100644 gettext-tools/gnulib-lib/full-write.c create mode 100644 gettext-tools/gnulib-lib/full-write.h create mode 100644 gettext-tools/gnulib-lib/fwriteerror.c create mode 100644 gettext-tools/gnulib-lib/fwriteerror.h create mode 100644 gettext-tools/gnulib-lib/gcd.c create mode 100644 gettext-tools/gnulib-lib/gcd.h create mode 100644 gettext-tools/gnulib-lib/getdelim.c create mode 100644 gettext-tools/gnulib-lib/getdtablesize.c create mode 100644 gettext-tools/gnulib-lib/getline.c create mode 100644 gettext-tools/gnulib-lib/getopt.c create mode 100644 gettext-tools/gnulib-lib/getopt.in.h create mode 100644 gettext-tools/gnulib-lib/getopt1.c create mode 100644 gettext-tools/gnulib-lib/getopt_int.h create mode 100644 gettext-tools/gnulib-lib/gettext.h create mode 100644 gettext-tools/gnulib-lib/gettimeofday.c create mode 100644 gettext-tools/gnulib-lib/gl_anyhash_list1.h create mode 100644 gettext-tools/gnulib-lib/gl_anyhash_list2.h create mode 100644 gettext-tools/gnulib-lib/gl_anylinked_list1.h create mode 100644 gettext-tools/gnulib-lib/gl_anylinked_list2.h create mode 100644 gettext-tools/gnulib-lib/gl_array_list.c create mode 100644 gettext-tools/gnulib-lib/gl_array_list.h create mode 100644 gettext-tools/gnulib-lib/gl_linkedhash_list.c create mode 100644 gettext-tools/gnulib-lib/gl_linkedhash_list.h create mode 100644 gettext-tools/gnulib-lib/gl_list.c create mode 100644 gettext-tools/gnulib-lib/gl_list.h create mode 100644 gettext-tools/gnulib-lib/gl_xlist.c create mode 100644 gettext-tools/gnulib-lib/gl_xlist.h create mode 100644 gettext-tools/gnulib-lib/glib.in.h create mode 100644 gettext-tools/gnulib-lib/glib/ghash.c create mode 100644 gettext-tools/gnulib-lib/glib/ghash.in.h create mode 100644 gettext-tools/gnulib-lib/glib/glist.c create mode 100644 gettext-tools/gnulib-lib/glib/glist.in.h create mode 100644 gettext-tools/gnulib-lib/glib/gmessages.c create mode 100644 gettext-tools/gnulib-lib/glib/gprimes.c create mode 100644 gettext-tools/gnulib-lib/glib/gprimes.in.h create mode 100644 gettext-tools/gnulib-lib/glib/gstrfuncs.c create mode 100644 gettext-tools/gnulib-lib/glib/gstrfuncs.in.h create mode 100644 gettext-tools/gnulib-lib/glib/gstring.c create mode 100644 gettext-tools/gnulib-lib/glib/gstring.in.h create mode 100644 gettext-tools/gnulib-lib/glib/gtypes.in.h create mode 100644 gettext-tools/gnulib-lib/glibconfig.in.h create mode 100644 gettext-tools/gnulib-lib/glthread/lock.c create mode 100644 gettext-tools/gnulib-lib/glthread/lock.h create mode 100644 gettext-tools/gnulib-lib/glthread/threadlib.c create mode 100644 gettext-tools/gnulib-lib/glthread/tls.c create mode 100644 gettext-tools/gnulib-lib/glthread/tls.h create mode 100644 gettext-tools/gnulib-lib/hash.c create mode 100644 gettext-tools/gnulib-lib/hash.h create mode 100644 gettext-tools/gnulib-lib/html-ostream.c create mode 100644 gettext-tools/gnulib-lib/html-ostream.h create mode 100644 gettext-tools/gnulib-lib/html-ostream.oo.c create mode 100644 gettext-tools/gnulib-lib/html-ostream.oo.h create mode 100644 gettext-tools/gnulib-lib/html-styled-ostream.c create mode 100644 gettext-tools/gnulib-lib/html-styled-ostream.h create mode 100644 gettext-tools/gnulib-lib/html-styled-ostream.oo.c create mode 100644 gettext-tools/gnulib-lib/html-styled-ostream.oo.h create mode 100644 gettext-tools/gnulib-lib/html_ostream.priv.h create mode 100644 gettext-tools/gnulib-lib/html_ostream.vt.h create mode 100644 gettext-tools/gnulib-lib/html_styled_ostream.priv.h create mode 100644 gettext-tools/gnulib-lib/html_styled_ostream.vt.h create mode 100644 gettext-tools/gnulib-lib/iconv.c create mode 100644 gettext-tools/gnulib-lib/iconv.in.h create mode 100644 gettext-tools/gnulib-lib/iconv_close.c create mode 100644 gettext-tools/gnulib-lib/iconv_open-aix.gperf create mode 100644 gettext-tools/gnulib-lib/iconv_open-aix.h create mode 100644 gettext-tools/gnulib-lib/iconv_open-hpux.gperf create mode 100644 gettext-tools/gnulib-lib/iconv_open-hpux.h create mode 100644 gettext-tools/gnulib-lib/iconv_open-irix.gperf create mode 100644 gettext-tools/gnulib-lib/iconv_open-irix.h create mode 100644 gettext-tools/gnulib-lib/iconv_open-osf.gperf create mode 100644 gettext-tools/gnulib-lib/iconv_open-osf.h create mode 100644 gettext-tools/gnulib-lib/iconv_open-solaris.gperf create mode 100644 gettext-tools/gnulib-lib/iconv_open-solaris.h create mode 100644 gettext-tools/gnulib-lib/iconv_open.c create mode 100644 gettext-tools/gnulib-lib/iconveh.h create mode 100644 gettext-tools/gnulib-lib/ignore-value.h create mode 100644 gettext-tools/gnulib-lib/intprops.h create mode 100644 gettext-tools/gnulib-lib/iswblank.c create mode 100644 gettext-tools/gnulib-lib/itold.c create mode 100644 gettext-tools/gnulib-lib/javacomp.c create mode 100644 gettext-tools/gnulib-lib/javacomp.h create mode 100644 gettext-tools/gnulib-lib/javaexec.c create mode 100644 gettext-tools/gnulib-lib/javaexec.h create mode 100644 gettext-tools/gnulib-lib/javaversion.c create mode 100644 gettext-tools/gnulib-lib/javaversion.class create mode 100644 gettext-tools/gnulib-lib/javaversion.h create mode 100644 gettext-tools/gnulib-lib/javaversion.java create mode 100644 gettext-tools/gnulib-lib/libcroco/cr-additional-sel.c create mode 100644 gettext-tools/gnulib-lib/libcroco/cr-additional-sel.h create mode 100644 gettext-tools/gnulib-lib/libcroco/cr-attr-sel.c create mode 100644 gettext-tools/gnulib-lib/libcroco/cr-attr-sel.h create mode 100644 gettext-tools/gnulib-lib/libcroco/cr-cascade.c create mode 100644 gettext-tools/gnulib-lib/libcroco/cr-cascade.h create mode 100644 gettext-tools/gnulib-lib/libcroco/cr-declaration.c create mode 100644 gettext-tools/gnulib-lib/libcroco/cr-declaration.h create mode 100644 gettext-tools/gnulib-lib/libcroco/cr-doc-handler.c create mode 100644 gettext-tools/gnulib-lib/libcroco/cr-doc-handler.h create mode 100644 gettext-tools/gnulib-lib/libcroco/cr-enc-handler.c create mode 100644 gettext-tools/gnulib-lib/libcroco/cr-enc-handler.h create mode 100644 gettext-tools/gnulib-lib/libcroco/cr-fonts.c create mode 100644 gettext-tools/gnulib-lib/libcroco/cr-fonts.h create mode 100644 gettext-tools/gnulib-lib/libcroco/cr-input.c create mode 100644 gettext-tools/gnulib-lib/libcroco/cr-input.h create mode 100644 gettext-tools/gnulib-lib/libcroco/cr-num.c create mode 100644 gettext-tools/gnulib-lib/libcroco/cr-num.h create mode 100644 gettext-tools/gnulib-lib/libcroco/cr-om-parser.c create mode 100644 gettext-tools/gnulib-lib/libcroco/cr-om-parser.h create mode 100644 gettext-tools/gnulib-lib/libcroco/cr-parser.c create mode 100644 gettext-tools/gnulib-lib/libcroco/cr-parser.h create mode 100644 gettext-tools/gnulib-lib/libcroco/cr-parsing-location.c create mode 100644 gettext-tools/gnulib-lib/libcroco/cr-parsing-location.h create mode 100644 gettext-tools/gnulib-lib/libcroco/cr-prop-list.c create mode 100644 gettext-tools/gnulib-lib/libcroco/cr-prop-list.h create mode 100644 gettext-tools/gnulib-lib/libcroco/cr-pseudo.c create mode 100644 gettext-tools/gnulib-lib/libcroco/cr-pseudo.h create mode 100644 gettext-tools/gnulib-lib/libcroco/cr-rgb.c create mode 100644 gettext-tools/gnulib-lib/libcroco/cr-rgb.h create mode 100644 gettext-tools/gnulib-lib/libcroco/cr-sel-eng.c create mode 100644 gettext-tools/gnulib-lib/libcroco/cr-sel-eng.h create mode 100644 gettext-tools/gnulib-lib/libcroco/cr-selector.c create mode 100644 gettext-tools/gnulib-lib/libcroco/cr-selector.h create mode 100644 gettext-tools/gnulib-lib/libcroco/cr-simple-sel.c create mode 100644 gettext-tools/gnulib-lib/libcroco/cr-simple-sel.h create mode 100644 gettext-tools/gnulib-lib/libcroco/cr-statement.c create mode 100644 gettext-tools/gnulib-lib/libcroco/cr-statement.h create mode 100644 gettext-tools/gnulib-lib/libcroco/cr-string.c create mode 100644 gettext-tools/gnulib-lib/libcroco/cr-string.h create mode 100644 gettext-tools/gnulib-lib/libcroco/cr-style.c create mode 100644 gettext-tools/gnulib-lib/libcroco/cr-style.h create mode 100644 gettext-tools/gnulib-lib/libcroco/cr-stylesheet.c create mode 100644 gettext-tools/gnulib-lib/libcroco/cr-stylesheet.h create mode 100644 gettext-tools/gnulib-lib/libcroco/cr-term.c create mode 100644 gettext-tools/gnulib-lib/libcroco/cr-term.h create mode 100644 gettext-tools/gnulib-lib/libcroco/cr-tknzr.c create mode 100644 gettext-tools/gnulib-lib/libcroco/cr-tknzr.h create mode 100644 gettext-tools/gnulib-lib/libcroco/cr-token.c create mode 100644 gettext-tools/gnulib-lib/libcroco/cr-token.h create mode 100644 gettext-tools/gnulib-lib/libcroco/cr-utils.c create mode 100644 gettext-tools/gnulib-lib/libcroco/cr-utils.h create mode 100644 gettext-tools/gnulib-lib/libcroco/libcroco-config.h create mode 100644 gettext-tools/gnulib-lib/libcroco/libcroco.h create mode 100644 gettext-tools/gnulib-lib/libunistring.valgrind create mode 100644 gettext-tools/gnulib-lib/libxml/COPYING create mode 100644 gettext-tools/gnulib-lib/libxml/DOCBparser.c create mode 100644 gettext-tools/gnulib-lib/libxml/DOCBparser.in.h create mode 100644 gettext-tools/gnulib-lib/libxml/HTMLparser.c create mode 100644 gettext-tools/gnulib-lib/libxml/HTMLparser.in.h create mode 100644 gettext-tools/gnulib-lib/libxml/HTMLtree.c create mode 100644 gettext-tools/gnulib-lib/libxml/HTMLtree.in.h create mode 100644 gettext-tools/gnulib-lib/libxml/SAX.c create mode 100644 gettext-tools/gnulib-lib/libxml/SAX.in.h create mode 100644 gettext-tools/gnulib-lib/libxml/SAX2.c create mode 100644 gettext-tools/gnulib-lib/libxml/SAX2.in.h create mode 100644 gettext-tools/gnulib-lib/libxml/c14n.c create mode 100644 gettext-tools/gnulib-lib/libxml/c14n.in.h create mode 100644 gettext-tools/gnulib-lib/libxml/catalog.c create mode 100644 gettext-tools/gnulib-lib/libxml/catalog.in.h create mode 100644 gettext-tools/gnulib-lib/libxml/chvalid.c create mode 100644 gettext-tools/gnulib-lib/libxml/chvalid.in.h create mode 100644 gettext-tools/gnulib-lib/libxml/debugXML.c create mode 100644 gettext-tools/gnulib-lib/libxml/debugXML.in.h create mode 100644 gettext-tools/gnulib-lib/libxml/dict.c create mode 100644 gettext-tools/gnulib-lib/libxml/dict.in.h create mode 100644 gettext-tools/gnulib-lib/libxml/elfgcchack.h create mode 100644 gettext-tools/gnulib-lib/libxml/encoding.c create mode 100644 gettext-tools/gnulib-lib/libxml/encoding.in.h create mode 100644 gettext-tools/gnulib-lib/libxml/entities.c create mode 100644 gettext-tools/gnulib-lib/libxml/entities.in.h create mode 100644 gettext-tools/gnulib-lib/libxml/error.c create mode 100644 gettext-tools/gnulib-lib/libxml/globals.c create mode 100644 gettext-tools/gnulib-lib/libxml/globals.in.h create mode 100644 gettext-tools/gnulib-lib/libxml/hash.c create mode 100644 gettext-tools/gnulib-lib/libxml/hash.in.h create mode 100644 gettext-tools/gnulib-lib/libxml/legacy.c create mode 100644 gettext-tools/gnulib-lib/libxml/libxml.h create mode 100644 gettext-tools/gnulib-lib/libxml/list.c create mode 100644 gettext-tools/gnulib-lib/libxml/list.in.h create mode 100644 gettext-tools/gnulib-lib/libxml/nanoftp.c create mode 100644 gettext-tools/gnulib-lib/libxml/nanoftp.in.h create mode 100644 gettext-tools/gnulib-lib/libxml/nanohttp.c create mode 100644 gettext-tools/gnulib-lib/libxml/nanohttp.in.h create mode 100644 gettext-tools/gnulib-lib/libxml/parser.c create mode 100644 gettext-tools/gnulib-lib/libxml/parser.in.h create mode 100644 gettext-tools/gnulib-lib/libxml/parserInternals.c create mode 100644 gettext-tools/gnulib-lib/libxml/parserInternals.in.h create mode 100644 gettext-tools/gnulib-lib/libxml/pattern.c create mode 100644 gettext-tools/gnulib-lib/libxml/pattern.in.h create mode 100644 gettext-tools/gnulib-lib/libxml/relaxng.c create mode 100644 gettext-tools/gnulib-lib/libxml/relaxng.in.h create mode 100644 gettext-tools/gnulib-lib/libxml/schemasInternals.in.h create mode 100644 gettext-tools/gnulib-lib/libxml/schematron.c create mode 100644 gettext-tools/gnulib-lib/libxml/schematron.in.h create mode 100644 gettext-tools/gnulib-lib/libxml/threads.c create mode 100644 gettext-tools/gnulib-lib/libxml/threads.in.h create mode 100644 gettext-tools/gnulib-lib/libxml/tree.c create mode 100644 gettext-tools/gnulib-lib/libxml/tree.in.h create mode 100644 gettext-tools/gnulib-lib/libxml/uri.c create mode 100644 gettext-tools/gnulib-lib/libxml/uri.in.h create mode 100644 gettext-tools/gnulib-lib/libxml/valid.c create mode 100644 gettext-tools/gnulib-lib/libxml/valid.in.h create mode 100644 gettext-tools/gnulib-lib/libxml/xinclude.c create mode 100644 gettext-tools/gnulib-lib/libxml/xinclude.in.h create mode 100644 gettext-tools/gnulib-lib/libxml/xlink.c create mode 100644 gettext-tools/gnulib-lib/libxml/xlink.in.h create mode 100644 gettext-tools/gnulib-lib/libxml/xmlIO.c create mode 100644 gettext-tools/gnulib-lib/libxml/xmlIO.in.h create mode 100644 gettext-tools/gnulib-lib/libxml/xmlautomata.in.h create mode 100644 gettext-tools/gnulib-lib/libxml/xmlerror.in.h create mode 100644 gettext-tools/gnulib-lib/libxml/xmlexports.in.h create mode 100644 gettext-tools/gnulib-lib/libxml/xmlmemory.c create mode 100644 gettext-tools/gnulib-lib/libxml/xmlmemory.in.h create mode 100644 gettext-tools/gnulib-lib/libxml/xmlmodule.c create mode 100644 gettext-tools/gnulib-lib/libxml/xmlmodule.in.h create mode 100644 gettext-tools/gnulib-lib/libxml/xmlreader.c create mode 100644 gettext-tools/gnulib-lib/libxml/xmlreader.in.h create mode 100644 gettext-tools/gnulib-lib/libxml/xmlregexp.c create mode 100644 gettext-tools/gnulib-lib/libxml/xmlregexp.in.h create mode 100644 gettext-tools/gnulib-lib/libxml/xmlsave.c create mode 100644 gettext-tools/gnulib-lib/libxml/xmlsave.in.h create mode 100644 gettext-tools/gnulib-lib/libxml/xmlschemas.c create mode 100644 gettext-tools/gnulib-lib/libxml/xmlschemas.in.h create mode 100644 gettext-tools/gnulib-lib/libxml/xmlschemastypes.c create mode 100644 gettext-tools/gnulib-lib/libxml/xmlschemastypes.in.h create mode 100644 gettext-tools/gnulib-lib/libxml/xmlstring.c create mode 100644 gettext-tools/gnulib-lib/libxml/xmlstring.in.h create mode 100644 gettext-tools/gnulib-lib/libxml/xmlunicode.c create mode 100644 gettext-tools/gnulib-lib/libxml/xmlunicode.in.h create mode 100644 gettext-tools/gnulib-lib/libxml/xmlversion.in.h create mode 100644 gettext-tools/gnulib-lib/libxml/xmlwriter.c create mode 100644 gettext-tools/gnulib-lib/libxml/xmlwriter.in.h create mode 100644 gettext-tools/gnulib-lib/libxml/xpath.c create mode 100644 gettext-tools/gnulib-lib/libxml/xpath.in.h create mode 100644 gettext-tools/gnulib-lib/libxml/xpathInternals.in.h create mode 100644 gettext-tools/gnulib-lib/libxml/xpointer.c create mode 100644 gettext-tools/gnulib-lib/libxml/xpointer.in.h create mode 100644 gettext-tools/gnulib-lib/localcharset.c create mode 100644 gettext-tools/gnulib-lib/localcharset.h create mode 100644 gettext-tools/gnulib-lib/locale.in.h create mode 100644 gettext-tools/gnulib-lib/localename.c create mode 100644 gettext-tools/gnulib-lib/localename.h create mode 100644 gettext-tools/gnulib-lib/lstat.c create mode 100644 gettext-tools/gnulib-lib/malloc.c create mode 100644 gettext-tools/gnulib-lib/malloca.c create mode 100644 gettext-tools/gnulib-lib/malloca.h create mode 100644 gettext-tools/gnulib-lib/malloca.valgrind create mode 100644 gettext-tools/gnulib-lib/mbchar.c create mode 100644 gettext-tools/gnulib-lib/mbchar.h create mode 100644 gettext-tools/gnulib-lib/mbiter.c create mode 100644 gettext-tools/gnulib-lib/mbiter.h create mode 100644 gettext-tools/gnulib-lib/mbrtowc.c create mode 100644 gettext-tools/gnulib-lib/mbsinit.c create mode 100644 gettext-tools/gnulib-lib/mbslen.c create mode 100644 gettext-tools/gnulib-lib/mbsrtowcs-impl.h create mode 100644 gettext-tools/gnulib-lib/mbsrtowcs-state.c create mode 100644 gettext-tools/gnulib-lib/mbsrtowcs.c create mode 100644 gettext-tools/gnulib-lib/mbsstr.c create mode 100644 gettext-tools/gnulib-lib/mbswidth.c create mode 100644 gettext-tools/gnulib-lib/mbswidth.h create mode 100644 gettext-tools/gnulib-lib/mbuiter.c create mode 100644 gettext-tools/gnulib-lib/mbuiter.h create mode 100644 gettext-tools/gnulib-lib/memchr.c create mode 100644 gettext-tools/gnulib-lib/memchr.valgrind create mode 100644 gettext-tools/gnulib-lib/memmove.c create mode 100644 gettext-tools/gnulib-lib/memset.c create mode 100644 gettext-tools/gnulib-lib/minmax.h create mode 100644 gettext-tools/gnulib-lib/mkdtemp.c create mode 100644 gettext-tools/gnulib-lib/moo.h create mode 100644 gettext-tools/gnulib-lib/msvc-inval.c create mode 100644 gettext-tools/gnulib-lib/msvc-inval.h create mode 100644 gettext-tools/gnulib-lib/msvc-nothrow.c create mode 100644 gettext-tools/gnulib-lib/msvc-nothrow.h create mode 100644 gettext-tools/gnulib-lib/obstack.c create mode 100644 gettext-tools/gnulib-lib/obstack.h create mode 100644 gettext-tools/gnulib-lib/open.c create mode 100644 gettext-tools/gnulib-lib/opendir.c create mode 100644 gettext-tools/gnulib-lib/ostream.c create mode 100644 gettext-tools/gnulib-lib/ostream.h create mode 100644 gettext-tools/gnulib-lib/ostream.oo.c create mode 100644 gettext-tools/gnulib-lib/ostream.oo.h create mode 100644 gettext-tools/gnulib-lib/ostream.priv.h create mode 100644 gettext-tools/gnulib-lib/ostream.vt.h create mode 100644 gettext-tools/gnulib-lib/pathmax.h create mode 100644 gettext-tools/gnulib-lib/pipe-filter-aux.c create mode 100644 gettext-tools/gnulib-lib/pipe-filter-aux.h create mode 100644 gettext-tools/gnulib-lib/pipe-filter-ii.c create mode 100644 gettext-tools/gnulib-lib/pipe-filter.h create mode 100644 gettext-tools/gnulib-lib/pipe-safer.c create mode 100644 gettext-tools/gnulib-lib/pipe2-safer.c create mode 100644 gettext-tools/gnulib-lib/pipe2.c create mode 100644 gettext-tools/gnulib-lib/printf-args.c create mode 100644 gettext-tools/gnulib-lib/printf-args.h create mode 100644 gettext-tools/gnulib-lib/printf-parse.c create mode 100644 gettext-tools/gnulib-lib/printf-parse.h create mode 100644 gettext-tools/gnulib-lib/progname.c create mode 100644 gettext-tools/gnulib-lib/progname.h create mode 100644 gettext-tools/gnulib-lib/progreloc.c create mode 100644 gettext-tools/gnulib-lib/propername.c create mode 100644 gettext-tools/gnulib-lib/propername.h create mode 100644 gettext-tools/gnulib-lib/qcopy-acl.c create mode 100644 gettext-tools/gnulib-lib/qset-acl.c create mode 100644 gettext-tools/gnulib-lib/quote.h create mode 100644 gettext-tools/gnulib-lib/quotearg.c create mode 100644 gettext-tools/gnulib-lib/quotearg.h create mode 100644 gettext-tools/gnulib-lib/raise.c create mode 100644 gettext-tools/gnulib-lib/rawmemchr.c create mode 100644 gettext-tools/gnulib-lib/rawmemchr.valgrind create mode 100644 gettext-tools/gnulib-lib/read.c create mode 100644 gettext-tools/gnulib-lib/readdir.c create mode 100644 gettext-tools/gnulib-lib/readlink.c create mode 100644 gettext-tools/gnulib-lib/realloc.c create mode 100644 gettext-tools/gnulib-lib/ref-add.sin create mode 100644 gettext-tools/gnulib-lib/ref-del.sin create mode 100644 gettext-tools/gnulib-lib/relocatable.c create mode 100644 gettext-tools/gnulib-lib/relocatable.h create mode 100644 gettext-tools/gnulib-lib/relocwrapper.c create mode 100644 gettext-tools/gnulib-lib/rmdir.c create mode 100644 gettext-tools/gnulib-lib/safe-read.c create mode 100644 gettext-tools/gnulib-lib/safe-read.h create mode 100644 gettext-tools/gnulib-lib/safe-write.c create mode 100644 gettext-tools/gnulib-lib/safe-write.h create mode 100644 gettext-tools/gnulib-lib/sched.in.h create mode 100644 gettext-tools/gnulib-lib/secure_getenv.c create mode 100644 gettext-tools/gnulib-lib/set-acl.c create mode 100644 gettext-tools/gnulib-lib/setenv.c create mode 100644 gettext-tools/gnulib-lib/setlocale.c create mode 100644 gettext-tools/gnulib-lib/sh-quote.c create mode 100644 gettext-tools/gnulib-lib/sh-quote.h create mode 100644 gettext-tools/gnulib-lib/sig-handler.c create mode 100644 gettext-tools/gnulib-lib/sig-handler.h create mode 100644 gettext-tools/gnulib-lib/sigaction.c create mode 100644 gettext-tools/gnulib-lib/signal.in.h create mode 100644 gettext-tools/gnulib-lib/sigprocmask.c create mode 100644 gettext-tools/gnulib-lib/size_max.h create mode 100644 gettext-tools/gnulib-lib/snprintf.c create mode 100644 gettext-tools/gnulib-lib/spawn-pipe.c create mode 100644 gettext-tools/gnulib-lib/spawn-pipe.h create mode 100644 gettext-tools/gnulib-lib/spawn.in.h create mode 100644 gettext-tools/gnulib-lib/spawn_faction_addclose.c create mode 100644 gettext-tools/gnulib-lib/spawn_faction_adddup2.c create mode 100644 gettext-tools/gnulib-lib/spawn_faction_addopen.c create mode 100644 gettext-tools/gnulib-lib/spawn_faction_destroy.c create mode 100644 gettext-tools/gnulib-lib/spawn_faction_init.c create mode 100644 gettext-tools/gnulib-lib/spawn_int.h create mode 100644 gettext-tools/gnulib-lib/spawnattr_destroy.c create mode 100644 gettext-tools/gnulib-lib/spawnattr_init.c create mode 100644 gettext-tools/gnulib-lib/spawnattr_setflags.c create mode 100644 gettext-tools/gnulib-lib/spawnattr_setsigmask.c create mode 100644 gettext-tools/gnulib-lib/spawni.c create mode 100644 gettext-tools/gnulib-lib/spawnp.c create mode 100644 gettext-tools/gnulib-lib/stat.c create mode 100644 gettext-tools/gnulib-lib/stdarg.in.h create mode 100644 gettext-tools/gnulib-lib/stdbool.in.h create mode 100644 gettext-tools/gnulib-lib/stddef.in.h create mode 100644 gettext-tools/gnulib-lib/stdint.in.h create mode 100644 gettext-tools/gnulib-lib/stdio-write.c create mode 100644 gettext-tools/gnulib-lib/stdio.in.h create mode 100644 gettext-tools/gnulib-lib/stdlib.in.h create mode 100644 gettext-tools/gnulib-lib/stpcpy.c create mode 100644 gettext-tools/gnulib-lib/stpncpy.c create mode 100644 gettext-tools/gnulib-lib/str-kmp.h create mode 100644 gettext-tools/gnulib-lib/str-two-way.h create mode 100644 gettext-tools/gnulib-lib/strchrnul.c create mode 100644 gettext-tools/gnulib-lib/strchrnul.valgrind create mode 100644 gettext-tools/gnulib-lib/strcspn.c create mode 100644 gettext-tools/gnulib-lib/streq.h create mode 100644 gettext-tools/gnulib-lib/strerror-override.c create mode 100644 gettext-tools/gnulib-lib/strerror-override.h create mode 100644 gettext-tools/gnulib-lib/strerror.c create mode 100644 gettext-tools/gnulib-lib/striconv.c create mode 100644 gettext-tools/gnulib-lib/striconv.h create mode 100644 gettext-tools/gnulib-lib/striconveh.c create mode 100644 gettext-tools/gnulib-lib/striconveh.h create mode 100644 gettext-tools/gnulib-lib/striconveha.c create mode 100644 gettext-tools/gnulib-lib/striconveha.h create mode 100644 gettext-tools/gnulib-lib/string.in.h create mode 100644 gettext-tools/gnulib-lib/strnlen.c create mode 100644 gettext-tools/gnulib-lib/strnlen1.c create mode 100644 gettext-tools/gnulib-lib/strnlen1.h create mode 100644 gettext-tools/gnulib-lib/strpbrk.c create mode 100644 gettext-tools/gnulib-lib/strstr.c create mode 100644 gettext-tools/gnulib-lib/strtol.c create mode 100644 gettext-tools/gnulib-lib/strtoul.c create mode 100644 gettext-tools/gnulib-lib/styled-ostream.c create mode 100644 gettext-tools/gnulib-lib/styled-ostream.h create mode 100644 gettext-tools/gnulib-lib/styled-ostream.oo.c create mode 100644 gettext-tools/gnulib-lib/styled-ostream.oo.h create mode 100644 gettext-tools/gnulib-lib/styled_ostream.priv.h create mode 100644 gettext-tools/gnulib-lib/styled_ostream.vt.h create mode 100644 gettext-tools/gnulib-lib/sys_select.in.h create mode 100644 gettext-tools/gnulib-lib/sys_stat.in.h create mode 100644 gettext-tools/gnulib-lib/sys_time.in.h create mode 100644 gettext-tools/gnulib-lib/sys_types.in.h create mode 100644 gettext-tools/gnulib-lib/sys_wait.in.h create mode 100644 gettext-tools/gnulib-lib/tempname.c create mode 100644 gettext-tools/gnulib-lib/tempname.h create mode 100644 gettext-tools/gnulib-lib/term-ostream.c create mode 100644 gettext-tools/gnulib-lib/term-ostream.h create mode 100644 gettext-tools/gnulib-lib/term-ostream.oo.c create mode 100644 gettext-tools/gnulib-lib/term-ostream.oo.h create mode 100644 gettext-tools/gnulib-lib/term-styled-ostream.c create mode 100644 gettext-tools/gnulib-lib/term-styled-ostream.h create mode 100644 gettext-tools/gnulib-lib/term-styled-ostream.oo.c create mode 100644 gettext-tools/gnulib-lib/term-styled-ostream.oo.h create mode 100644 gettext-tools/gnulib-lib/term_ostream.priv.h create mode 100644 gettext-tools/gnulib-lib/term_ostream.vt.h create mode 100644 gettext-tools/gnulib-lib/term_styled_ostream.priv.h create mode 100644 gettext-tools/gnulib-lib/term_styled_ostream.vt.h create mode 100644 gettext-tools/gnulib-lib/terminfo.h create mode 100644 gettext-tools/gnulib-lib/time.in.h create mode 100644 gettext-tools/gnulib-lib/tmpdir.c create mode 100644 gettext-tools/gnulib-lib/tmpdir.h create mode 100644 gettext-tools/gnulib-lib/tparm.c create mode 100644 gettext-tools/gnulib-lib/tputs.c create mode 100644 gettext-tools/gnulib-lib/trim.c create mode 100644 gettext-tools/gnulib-lib/trim.h create mode 100644 gettext-tools/gnulib-lib/uniconv.in.h create mode 100644 gettext-tools/gnulib-lib/uniconv/u8-conv-from-enc.c create mode 100644 gettext-tools/gnulib-lib/unilbrk.in.h create mode 100644 gettext-tools/gnulib-lib/unilbrk/lbrkprop1.h create mode 100644 gettext-tools/gnulib-lib/unilbrk/lbrkprop2.h create mode 100644 gettext-tools/gnulib-lib/unilbrk/lbrktables.c create mode 100644 gettext-tools/gnulib-lib/unilbrk/lbrktables.h create mode 100644 gettext-tools/gnulib-lib/unilbrk/u8-possible-linebreaks.c create mode 100644 gettext-tools/gnulib-lib/unilbrk/u8-width-linebreaks.c create mode 100644 gettext-tools/gnulib-lib/unilbrk/ulc-common.c create mode 100644 gettext-tools/gnulib-lib/unilbrk/ulc-common.h create mode 100644 gettext-tools/gnulib-lib/unilbrk/ulc-width-linebreaks.c create mode 100644 gettext-tools/gnulib-lib/uniname.in.h create mode 100755 gettext-tools/gnulib-lib/uniname/gen-uninames.lisp create mode 100644 gettext-tools/gnulib-lib/uniname/uniname.c create mode 100644 gettext-tools/gnulib-lib/uniname/uninames.h create mode 100644 gettext-tools/gnulib-lib/unistd--.h create mode 100644 gettext-tools/gnulib-lib/unistd-safer.h create mode 100644 gettext-tools/gnulib-lib/unistd.c create mode 100644 gettext-tools/gnulib-lib/unistd.in.h create mode 100644 gettext-tools/gnulib-lib/unistr.in.h create mode 100644 gettext-tools/gnulib-lib/unistr/u16-mbtouc-aux.c create mode 100644 gettext-tools/gnulib-lib/unistr/u16-mbtouc.c create mode 100644 gettext-tools/gnulib-lib/unistr/u8-check.c create mode 100644 gettext-tools/gnulib-lib/unistr/u8-mblen.c create mode 100644 gettext-tools/gnulib-lib/unistr/u8-mbtouc-aux.c create mode 100644 gettext-tools/gnulib-lib/unistr/u8-mbtouc-unsafe-aux.c create mode 100644 gettext-tools/gnulib-lib/unistr/u8-mbtouc-unsafe.c create mode 100644 gettext-tools/gnulib-lib/unistr/u8-mbtouc.c create mode 100644 gettext-tools/gnulib-lib/unistr/u8-mbtoucr.c create mode 100644 gettext-tools/gnulib-lib/unistr/u8-prev.c create mode 100644 gettext-tools/gnulib-lib/unistr/u8-uctomb-aux.c create mode 100644 gettext-tools/gnulib-lib/unistr/u8-uctomb.c create mode 100644 gettext-tools/gnulib-lib/unitypes.in.h create mode 100644 gettext-tools/gnulib-lib/uniwidth.in.h create mode 100644 gettext-tools/gnulib-lib/uniwidth/cjk.h create mode 100644 gettext-tools/gnulib-lib/uniwidth/width.c create mode 100644 gettext-tools/gnulib-lib/unlocked-io.h create mode 100644 gettext-tools/gnulib-lib/unsetenv.c create mode 100644 gettext-tools/gnulib-lib/vasnprintf.c create mode 100644 gettext-tools/gnulib-lib/vasnprintf.h create mode 100644 gettext-tools/gnulib-lib/vasprintf.c create mode 100644 gettext-tools/gnulib-lib/verify.h create mode 100644 gettext-tools/gnulib-lib/vsnprintf.c create mode 100644 gettext-tools/gnulib-lib/w32spawn.h create mode 100644 gettext-tools/gnulib-lib/wait-process.c create mode 100644 gettext-tools/gnulib-lib/wait-process.h create mode 100644 gettext-tools/gnulib-lib/waitpid.c create mode 100644 gettext-tools/gnulib-lib/wchar.in.h create mode 100644 gettext-tools/gnulib-lib/wctype-h.c create mode 100644 gettext-tools/gnulib-lib/wctype.in.h create mode 100644 gettext-tools/gnulib-lib/wcwidth.c create mode 100644 gettext-tools/gnulib-lib/write.c create mode 100644 gettext-tools/gnulib-lib/xalloc.h create mode 100644 gettext-tools/gnulib-lib/xasprintf.c create mode 100644 gettext-tools/gnulib-lib/xconcat-filename.c create mode 100644 gettext-tools/gnulib-lib/xerror.c create mode 100644 gettext-tools/gnulib-lib/xerror.h create mode 100644 gettext-tools/gnulib-lib/xmalloc.c create mode 100644 gettext-tools/gnulib-lib/xmalloca.c create mode 100644 gettext-tools/gnulib-lib/xmalloca.h create mode 100644 gettext-tools/gnulib-lib/xreadlink.c create mode 100644 gettext-tools/gnulib-lib/xreadlink.h create mode 100644 gettext-tools/gnulib-lib/xsetenv.c create mode 100644 gettext-tools/gnulib-lib/xsetenv.h create mode 100644 gettext-tools/gnulib-lib/xsize.c create mode 100644 gettext-tools/gnulib-lib/xsize.h create mode 100644 gettext-tools/gnulib-lib/xstrdup.c create mode 100644 gettext-tools/gnulib-lib/xstriconv.c create mode 100644 gettext-tools/gnulib-lib/xstriconv.h create mode 100644 gettext-tools/gnulib-lib/xstriconveh.c create mode 100644 gettext-tools/gnulib-lib/xstriconveh.h create mode 100644 gettext-tools/gnulib-lib/xvasprintf.c create mode 100644 gettext-tools/gnulib-lib/xvasprintf.h (limited to 'gettext-tools/gnulib-lib') diff --git a/gettext-tools/gnulib-lib/Makefile.am b/gettext-tools/gnulib-lib/Makefile.am new file mode 100644 index 0000000..86106b8 --- /dev/null +++ b/gettext-tools/gnulib-lib/Makefile.am @@ -0,0 +1,75 @@ +## Makefile for the gettext-tools/gnulib-lib subdirectory of GNU gettext +## Copyright (C) 1995-1998, 2000-2006, 2009 Free Software Foundation, Inc. +## +## This program is free software: you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program. If not, see . + +## Process this file with automake to produce Makefile.in. + +AUTOMAKE_OPTIONS = 1.5 gnits subdir-objects no-dependencies +EXTRA_DIST = +BUILT_SOURCES = +MOSTLYCLEANFILES = core *.stackdump +MOSTLYCLEANDIRS = +CLEANFILES = +DISTCLEANFILES = +MAINTAINERCLEANFILES = +SUFFIXES = + +noinst_LTLIBRARIES = + +# Extra files to be installed. + +gettextsrcdir = $(datadir)/gettext +gettextsrc_DATA = gettext.h + +# Where to install javaversion.class. +pkgdatadir = $(datadir)/gettext +pkgdata_DATA = + +AM_CPPFLAGS = + +# Hmm... is this still necessary? +AM_CPPFLAGS += -I$(top_builddir)/intl -I$(top_srcdir)/intl +# Needed so that config.h and woe32dll/export.h are found. +AM_CPPFLAGS += -I$(top_builddir) -I$(top_srcdir) + +# Parametrization of the 'relocatable' module. +AM_CPPFLAGS += -DDEPENDS_ON_LIBICONV=1 -DDEPENDS_ON_LIBINTL=1 + +# Parametrization of the 'libxml' module: +# When building a shared library, don't export the variables +# xmlMalloc, xmlMallocAtomic, xmlRealloc, xmlFree, xmlMemStrdup. +if INCLUDED_LIBXML +AM_CPPFLAGS += -DLIBXML_STATIC +endif + +# Rules generated and collected by gnulib-tool. +include Makefile.gnulib + +# Which classes to export from the shared library. +MOOPPFLAGS += --dllexport=styled_ostream + +# Linking with C++ libraries is needed _only_ on mingw and Cygwin. +if !WOE32DLL +libgettextlib_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ + $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(libgettextlib_la_LDFLAGS) $(LDFLAGS) \ + -o $@ +else +libgettextlib_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ + $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(libgettextlib_la_LDFLAGS) $(LDFLAGS) \ + -o $@ +endif + diff --git a/gettext-tools/gnulib-lib/Makefile.gnulib b/gettext-tools/gnulib-lib/Makefile.gnulib new file mode 100644 index 0000000..80d77a4 --- /dev/null +++ b/gettext-tools/gnulib-lib/Makefile.gnulib @@ -0,0 +1,4301 @@ +## DO NOT EDIT! GENERATED AUTOMATICALLY! +## Process this file with automake to produce Makefile.in. +# Copyright (C) 2002-2014 Free Software Foundation, Inc. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This file is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this file. If not, see . +# +# As a special exception to the GNU General Public License, +# this file may be distributed as part of a program that +# contains a configuration script generated by Autoconf, under +# the same distribution terms as the rest of that program. +# +# Generated by gnulib-tool. +# Reproduce by: gnulib-tool --import --dir=gettext-tools --local-dir=gnulib-local --lib=libgettextlib --source-base=gnulib-lib --m4-base=gnulib-m4 --doc-base=doc --tests-base=gnulib-tests --aux-dir=../build-aux --with-tests --avoid=hash-tests --avoid=unilbrk/u8-possible-linebreaks-tests --avoid=unilbrk/ulc-width-linebreaks-tests --avoid=unistr/u8-mbtouc-tests --avoid=unistr/u8-mbtouc-unsafe-tests --avoid=uniwidth/width-tests --makefile-name=Makefile.gnulib --no-conditional-dependencies --libtool --macro-prefix=gl alloca-opt ansi-c++-opt atexit backupfile basename binary-io bison-i18n byteswap c-ctype c-strcase c-strcasestr c-strstr clean-temp closedir closeout copy-file csharpcomp csharpcomp-script csharpexec csharpexec-script error error-progname execute extensions fd-ostream file-ostream filename findprog fnmatch fopen fstrcmp full-write fwriteerror gcd gcj getline getopt-gnu gettext-h gettext-tools-misc hash html-styled-ostream iconv include_next java javacomp javacomp-script javaexec javaexec-script libunistring-optional localcharset locale localename lock malloc-posix mbrtowc mbsinit memmove memset minmax multiarch obstack open opendir openmp ostream pipe-filter-ii progname propername readdir relocatable-prog relocatable-script setlocale sh-quote sigpipe sigprocmask snippet/arg-nonnull snippet/c++defs snippet/warn-on-use spawn-pipe ssize_t stdbool stddef stdint stdio stdlib stpcpy stpncpy strcspn streq strerror strpbrk strtol strtoul styled-ostream sys_select sys_stat sys_time term-styled-ostream unilbrk/ulc-width-linebreaks uniname/uniname unistd unistr/u16-mbtouc unistr/u8-mbtouc unistr/u8-mbtoucr unistr/u8-uctomb uniwidth/width unlocked-io vasprintf verify wait-process wchar wctype-h write xalloc xconcat-filename xerror xmalloca xsetenv xstriconv xstriconveh xvasprintf + + +MOSTLYCLEANFILES += core *.stackdump + + +libgettextlib_la_SOURCES = +libgettextlib_la_LIBADD = $(gl_LTLIBOBJS) +libgettextlib_la_DEPENDENCIES = $(gl_LTLIBOBJS) +EXTRA_libgettextlib_la_SOURCES = +libgettextlib_la_LDFLAGS = $(AM_LDFLAGS) +libgettextlib_la_LDFLAGS += -no-undefined +libgettextlib_la_LDFLAGS += $(LIB_ACL) +libgettextlib_la_LDFLAGS += $(LTLIBICONV) +libgettextlib_la_LDFLAGS += $(LTLIBINTL) +libgettextlib_la_LDFLAGS += $(LTLIBTHREAD) +libgettextlib_la_LDFLAGS += $(LTLIBUNISTRING) +libgettextlib_la_LDFLAGS += $(OPENMP_CFLAGS) +libgettextlib_la_LDFLAGS += @INTL_MACOSX_LIBS@ + +## begin gnulib module absolute-header + +# Use this preprocessor expression to decide whether #include_next works. +# Do not rely on a 'configure'-time test for this, since the expression +# might appear in an installed header, which is used by some other compiler. +HAVE_INCLUDE_NEXT = (__GNUC__ || 60000000 <= __DECC_VER) + +## end gnulib module absolute-header + +## begin gnulib module acl + +libgettextlib_la_SOURCES += copy-acl.c set-acl.c + +## end gnulib module acl + +## begin gnulib module alignof + + +EXTRA_DIST += alignof.h + +## end gnulib module alignof + +## begin gnulib module alloca-opt + +BUILT_SOURCES += $(ALLOCA_H) + +# We need the following in order to create when the system +# doesn't have one that works with the given compiler. +if GL_GENERATE_ALLOCA_H +alloca.h: alloca.in.h $(top_builddir)/config.status + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/alloca.in.h; \ + } > $@-t && \ + mv -f $@-t $@ +else +alloca.h: $(top_builddir)/config.status + rm -f $@ +endif +MOSTLYCLEANFILES += alloca.h alloca.h-t + +EXTRA_DIST += alloca.in.h + +## end gnulib module alloca-opt + +## begin gnulib module allocator + +libgettextlib_la_SOURCES += allocator.c + +EXTRA_DIST += allocator.h + +## end gnulib module allocator + +## begin gnulib module areadlink + +libgettextlib_la_SOURCES += areadlink.c + +EXTRA_DIST += areadlink.h + +## end gnulib module areadlink + +## begin gnulib module argmatch + +libgettextlib_la_SOURCES += argmatch.c + +EXTRA_DIST += argmatch.h + +## end gnulib module argmatch + +## begin gnulib module array-list + +libgettextlib_la_SOURCES += gl_array_list.h gl_array_list.c + +## end gnulib module array-list + +## begin gnulib module atexit + + +EXTRA_DIST += atexit.c + +EXTRA_libgettextlib_la_SOURCES += atexit.c + +## end gnulib module atexit + +## begin gnulib module backupfile + +libgettextlib_la_SOURCES += backupfile.h backupfile.c addext.c + +## end gnulib module backupfile + +## begin gnulib module basename + +libgettextlib_la_SOURCES += basename.h basename.c + +## end gnulib module basename + +## begin gnulib module binary-io + +libgettextlib_la_SOURCES += binary-io.h binary-io.c + +## end gnulib module binary-io + +## begin gnulib module byteswap + +BUILT_SOURCES += $(BYTESWAP_H) + +# We need the following in order to create when the system +# doesn't have one. +if GL_GENERATE_BYTESWAP_H +byteswap.h: byteswap.in.h $(top_builddir)/config.status + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/byteswap.in.h; \ + } > $@-t && \ + mv -f $@-t $@ +else +byteswap.h: $(top_builddir)/config.status + rm -f $@ +endif +MOSTLYCLEANFILES += byteswap.h byteswap.h-t + +EXTRA_DIST += byteswap.in.h + +## end gnulib module byteswap + +## begin gnulib module c-ctype + +libgettextlib_la_SOURCES += c-ctype.h c-ctype.c + +## end gnulib module c-ctype + +## begin gnulib module c-strcase + +libgettextlib_la_SOURCES += c-strcase.h c-strcasecmp.c c-strncasecmp.c + +## end gnulib module c-strcase + +## begin gnulib module c-strcaseeq + + +EXTRA_DIST += c-strcaseeq.h + +## end gnulib module c-strcaseeq + +## begin gnulib module c-strcasestr + +libgettextlib_la_SOURCES += c-strcasestr.h c-strcasestr.c + +EXTRA_DIST += str-two-way.h + +## end gnulib module c-strcasestr + +## begin gnulib module c-strstr + +libgettextlib_la_SOURCES += c-strstr.h c-strstr.c + +## end gnulib module c-strstr + +## begin gnulib module canonicalize-lgpl + + +EXTRA_DIST += canonicalize-lgpl.c + +EXTRA_libgettextlib_la_SOURCES += canonicalize-lgpl.c + +## end gnulib module canonicalize-lgpl + +## begin gnulib module careadlinkat + +libgettextlib_la_SOURCES += careadlinkat.c + +EXTRA_DIST += careadlinkat.h + +## end gnulib module careadlinkat + +## begin gnulib module classpath + +libgettextlib_la_SOURCES += classpath.h classpath.c + +## end gnulib module classpath + +## begin gnulib module clean-temp + +libgettextlib_la_SOURCES += clean-temp.h clean-temp.c + +## end gnulib module clean-temp + +## begin gnulib module cloexec + +libgettextlib_la_SOURCES += cloexec.c + +EXTRA_DIST += cloexec.h + +## end gnulib module cloexec + +## begin gnulib module close + + +EXTRA_DIST += close.c + +EXTRA_libgettextlib_la_SOURCES += close.c + +## end gnulib module close + +## begin gnulib module closedir + + +EXTRA_DIST += closedir.c dirent-private.h + +EXTRA_libgettextlib_la_SOURCES += closedir.c + +## end gnulib module closedir + +## begin gnulib module closeout + +libgettextlib_la_SOURCES += closeout.h closeout.c + +## end gnulib module closeout + +## begin gnulib module concat-filename + +libgettextlib_la_SOURCES += concat-filename.c + +EXTRA_DIST += concat-filename.h + +## end gnulib module concat-filename + +## begin gnulib module configmake + +# Listed in the same order as the GNU makefile conventions, and +# provided by autoconf 2.59c+ or 2.70. +# The Automake-defined pkg* macros are appended, in the order +# listed in the Automake 1.10a+ documentation. +configmake.h: Makefile + $(AM_V_GEN)rm -f $@-t && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + echo '#define PREFIX "$(prefix)"'; \ + echo '#define EXEC_PREFIX "$(exec_prefix)"'; \ + echo '#define BINDIR "$(bindir)"'; \ + echo '#define SBINDIR "$(sbindir)"'; \ + echo '#define LIBEXECDIR "$(libexecdir)"'; \ + echo '#define DATAROOTDIR "$(datarootdir)"'; \ + echo '#define DATADIR "$(datadir)"'; \ + echo '#define SYSCONFDIR "$(sysconfdir)"'; \ + echo '#define SHAREDSTATEDIR "$(sharedstatedir)"'; \ + echo '#define LOCALSTATEDIR "$(localstatedir)"'; \ + echo '#define RUNSTATEDIR "$(runstatedir)"'; \ + echo '#define INCLUDEDIR "$(includedir)"'; \ + echo '#define OLDINCLUDEDIR "$(oldincludedir)"'; \ + echo '#define DOCDIR "$(docdir)"'; \ + echo '#define INFODIR "$(infodir)"'; \ + echo '#define HTMLDIR "$(htmldir)"'; \ + echo '#define DVIDIR "$(dvidir)"'; \ + echo '#define PDFDIR "$(pdfdir)"'; \ + echo '#define PSDIR "$(psdir)"'; \ + echo '#define LIBDIR "$(libdir)"'; \ + echo '#define LISPDIR "$(lispdir)"'; \ + echo '#define LOCALEDIR "$(localedir)"'; \ + echo '#define MANDIR "$(mandir)"'; \ + echo '#define MANEXT "$(manext)"'; \ + echo '#define PKGDATADIR "$(pkgdatadir)"'; \ + echo '#define PKGINCLUDEDIR "$(pkgincludedir)"'; \ + echo '#define PKGLIBDIR "$(pkglibdir)"'; \ + echo '#define PKGLIBEXECDIR "$(pkglibexecdir)"'; \ + } | sed '/""/d' > $@-t && \ + mv -f $@-t $@ + +BUILT_SOURCES += configmake.h +CLEANFILES += configmake.h configmake.h-t + +## end gnulib module configmake + +## begin gnulib module copy-file + +libgettextlib_la_SOURCES += copy-file.h copy-file.c + +## end gnulib module copy-file + +## begin gnulib module csharpcomp + +libgettextlib_la_SOURCES += csharpcomp.h csharpcomp.c + +## end gnulib module csharpcomp + +## begin gnulib module csharpcomp-script + + +EXTRA_DIST += $(top_srcdir)/../build-aux/csharpcomp.sh.in + +## end gnulib module csharpcomp-script + +## begin gnulib module csharpexec + +DEFS += -DEXEEXT=\"@EXEEXT@\" +libgettextlib_la_SOURCES += csharpexec.h csharpexec.c + +EXTRA_DIST += classpath.c classpath.h + +EXTRA_libgettextlib_la_SOURCES += classpath.c + +## end gnulib module csharpexec + +## begin gnulib module csharpexec-script + + +EXTRA_DIST += $(top_srcdir)/../build-aux/csharpexec.sh.in + +## end gnulib module csharpexec-script + +## begin gnulib module diffseq + +libgettextlib_la_SOURCES += diffseq.h + +## end gnulib module diffseq + +## begin gnulib module dirent + +BUILT_SOURCES += dirent.h + +# We need the following in order to create when the system +# doesn't have one that works with the given compiler. +dirent.h: dirent.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''HAVE_DIRENT_H''@|$(HAVE_DIRENT_H)|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_DIRENT_H''@|$(NEXT_DIRENT_H)|g' \ + -e 's/@''GNULIB_OPENDIR''@/$(GNULIB_OPENDIR)/g' \ + -e 's/@''GNULIB_READDIR''@/$(GNULIB_READDIR)/g' \ + -e 's/@''GNULIB_REWINDDIR''@/$(GNULIB_REWINDDIR)/g' \ + -e 's/@''GNULIB_CLOSEDIR''@/$(GNULIB_CLOSEDIR)/g' \ + -e 's/@''GNULIB_DIRFD''@/$(GNULIB_DIRFD)/g' \ + -e 's/@''GNULIB_FDOPENDIR''@/$(GNULIB_FDOPENDIR)/g' \ + -e 's/@''GNULIB_SCANDIR''@/$(GNULIB_SCANDIR)/g' \ + -e 's/@''GNULIB_ALPHASORT''@/$(GNULIB_ALPHASORT)/g' \ + -e 's/@''HAVE_OPENDIR''@/$(HAVE_OPENDIR)/g' \ + -e 's/@''HAVE_READDIR''@/$(HAVE_READDIR)/g' \ + -e 's/@''HAVE_REWINDDIR''@/$(HAVE_REWINDDIR)/g' \ + -e 's/@''HAVE_CLOSEDIR''@/$(HAVE_CLOSEDIR)/g' \ + -e 's|@''HAVE_DECL_DIRFD''@|$(HAVE_DECL_DIRFD)|g' \ + -e 's|@''HAVE_DECL_FDOPENDIR''@|$(HAVE_DECL_FDOPENDIR)|g' \ + -e 's|@''HAVE_FDOPENDIR''@|$(HAVE_FDOPENDIR)|g' \ + -e 's|@''HAVE_SCANDIR''@|$(HAVE_SCANDIR)|g' \ + -e 's|@''HAVE_ALPHASORT''@|$(HAVE_ALPHASORT)|g' \ + -e 's|@''REPLACE_OPENDIR''@|$(REPLACE_OPENDIR)|g' \ + -e 's|@''REPLACE_CLOSEDIR''@|$(REPLACE_CLOSEDIR)|g' \ + -e 's|@''REPLACE_DIRFD''@|$(REPLACE_DIRFD)|g' \ + -e 's|@''REPLACE_FDOPENDIR''@|$(REPLACE_FDOPENDIR)|g' \ + -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ + < $(srcdir)/dirent.in.h; \ + } > $@-t && \ + mv $@-t $@ +MOSTLYCLEANFILES += dirent.h dirent.h-t + +EXTRA_DIST += dirent.in.h + +## end gnulib module dirent + +## begin gnulib module dosname + + +EXTRA_DIST += dosname.h + +## end gnulib module dosname + +## begin gnulib module dup2 + + +EXTRA_DIST += dup2.c + +EXTRA_libgettextlib_la_SOURCES += dup2.c + +## end gnulib module dup2 + +## begin gnulib module errno + +BUILT_SOURCES += $(ERRNO_H) + +# We need the following in order to create when the system +# doesn't have one that is POSIX compliant. +if GL_GENERATE_ERRNO_H +errno.h: errno.in.h $(top_builddir)/config.status + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_ERRNO_H''@|$(NEXT_ERRNO_H)|g' \ + -e 's|@''EMULTIHOP_HIDDEN''@|$(EMULTIHOP_HIDDEN)|g' \ + -e 's|@''EMULTIHOP_VALUE''@|$(EMULTIHOP_VALUE)|g' \ + -e 's|@''ENOLINK_HIDDEN''@|$(ENOLINK_HIDDEN)|g' \ + -e 's|@''ENOLINK_VALUE''@|$(ENOLINK_VALUE)|g' \ + -e 's|@''EOVERFLOW_HIDDEN''@|$(EOVERFLOW_HIDDEN)|g' \ + -e 's|@''EOVERFLOW_VALUE''@|$(EOVERFLOW_VALUE)|g' \ + < $(srcdir)/errno.in.h; \ + } > $@-t && \ + mv $@-t $@ +else +errno.h: $(top_builddir)/config.status + rm -f $@ +endif +MOSTLYCLEANFILES += errno.h errno.h-t + +EXTRA_DIST += errno.in.h + +## end gnulib module errno + +## begin gnulib module error + + +EXTRA_DIST += error.c error.h + +EXTRA_libgettextlib_la_SOURCES += error.c + +## end gnulib module error + +## begin gnulib module error-progname + +libgettextlib_la_SOURCES += error-progname.h error-progname.c + +## end gnulib module error-progname + +## begin gnulib module execute + +libgettextlib_la_SOURCES += execute.h execute.c w32spawn.h + +## end gnulib module execute + +## begin gnulib module exitfail + +libgettextlib_la_SOURCES += exitfail.c + +EXTRA_DIST += exitfail.h + +## end gnulib module exitfail + +## begin gnulib module fatal-signal + +libgettextlib_la_SOURCES += fatal-signal.h fatal-signal.c + +## end gnulib module fatal-signal + +## begin gnulib module fcntl + + +EXTRA_DIST += fcntl.c + +EXTRA_libgettextlib_la_SOURCES += fcntl.c + +## end gnulib module fcntl + +## begin gnulib module fcntl-h + +BUILT_SOURCES += fcntl.h + +# We need the following in order to create when the system +# doesn't have one that works with the given compiler. +fcntl.h: fcntl.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_FCNTL_H''@|$(NEXT_FCNTL_H)|g' \ + -e 's/@''GNULIB_FCNTL''@/$(GNULIB_FCNTL)/g' \ + -e 's/@''GNULIB_NONBLOCKING''@/$(GNULIB_NONBLOCKING)/g' \ + -e 's/@''GNULIB_OPEN''@/$(GNULIB_OPEN)/g' \ + -e 's/@''GNULIB_OPENAT''@/$(GNULIB_OPENAT)/g' \ + -e 's|@''HAVE_FCNTL''@|$(HAVE_FCNTL)|g' \ + -e 's|@''HAVE_OPENAT''@|$(HAVE_OPENAT)|g' \ + -e 's|@''REPLACE_FCNTL''@|$(REPLACE_FCNTL)|g' \ + -e 's|@''REPLACE_OPEN''@|$(REPLACE_OPEN)|g' \ + -e 's|@''REPLACE_OPENAT''@|$(REPLACE_OPENAT)|g' \ + -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ + < $(srcdir)/fcntl.in.h; \ + } > $@-t && \ + mv $@-t $@ +MOSTLYCLEANFILES += fcntl.h fcntl.h-t + +EXTRA_DIST += fcntl.in.h + +## end gnulib module fcntl-h + +## begin gnulib module fd-hook + +libgettextlib_la_SOURCES += fd-hook.c + +EXTRA_DIST += fd-hook.h + +## end gnulib module fd-hook + +## begin gnulib module fd-ostream + +libgettextlib_la_SOURCES += fd-ostream.c +# This is a Makefile rule that generates multiple files at once; see the +# automake documentation, node "Multiple Outputs", for details. +fd-ostream.h : $(top_srcdir)/../build-aux/moopp fd-ostream.oo.h fd-ostream.oo.c ostream.oo.h + $(top_srcdir)/../build-aux/moopp $(MOOPPFLAGS) $(srcdir)/fd-ostream.oo.c $(srcdir)/fd-ostream.oo.h $(srcdir)/ostream.oo.h +fd-ostream.c fd_ostream.priv.h fd_ostream.vt.h : fd-ostream.h + @test -f $@ || { \ + trap 'rm -rf fd-ostream.lock' 1 2 13 15; \ + if mkdir fd-ostream.lock 2>/dev/null; then \ + echo "$(top_srcdir)/../build-aux/moopp $(MOOPPFLAGS) $(srcdir)/fd-ostream.oo.c $(srcdir)/fd-ostream.oo.h $(srcdir)/ostream.oo.h"; \ + $(top_srcdir)/../build-aux/moopp $(MOOPPFLAGS) $(srcdir)/fd-ostream.oo.c $(srcdir)/fd-ostream.oo.h $(srcdir)/ostream.oo.h; \ + result=$$?; rm -rf fd-ostream.lock; exit $$result; \ + else \ + while test -d fd-ostream.lock; do sleep 1; done; \ + test -f $(srcdir)/fd-ostream.h; \ + fi; \ + } +BUILT_SOURCES += fd-ostream.h fd-ostream.c fd_ostream.priv.h fd_ostream.vt.h +MAINTAINERCLEANFILES += fd-ostream.h fd-ostream.c fd_ostream.priv.h fd_ostream.vt.h +EXTRA_DIST += fd-ostream.h fd-ostream.c fd_ostream.priv.h fd_ostream.vt.h + +EXTRA_DIST += fd-ostream.oo.c fd-ostream.oo.h + +EXTRA_libgettextlib_la_SOURCES += fd-ostream.oo.c + +## end gnulib module fd-ostream + +## begin gnulib module fd-safer-flag + +libgettextlib_la_SOURCES += fd-safer-flag.c dup-safer-flag.c + +## end gnulib module fd-safer-flag + +## begin gnulib module file-ostream + +libgettextlib_la_SOURCES += file-ostream.c +# This is a Makefile rule that generates multiple files at once; see the +# automake documentation, node "Multiple Outputs", for details. +file-ostream.h : $(top_srcdir)/../build-aux/moopp file-ostream.oo.h file-ostream.oo.c ostream.oo.h + $(top_srcdir)/../build-aux/moopp $(MOOPPFLAGS) $(srcdir)/file-ostream.oo.c $(srcdir)/file-ostream.oo.h $(srcdir)/ostream.oo.h +file-ostream.c file_ostream.priv.h file_ostream.vt.h : file-ostream.h + @test -f $@ || { \ + trap 'rm -rf file-ostream.lock' 1 2 13 15; \ + if mkdir file-ostream.lock 2>/dev/null; then \ + echo "$(top_srcdir)/../build-aux/moopp $(MOOPPFLAGS) $(srcdir)/file-ostream.oo.c $(srcdir)/file-ostream.oo.h $(srcdir)/ostream.oo.h"; \ + $(top_srcdir)/../build-aux/moopp $(MOOPPFLAGS) $(srcdir)/file-ostream.oo.c $(srcdir)/file-ostream.oo.h $(srcdir)/ostream.oo.h; \ + result=$$?; rm -rf file-ostream.lock; exit $$result; \ + else \ + while test -d file-ostream.lock; do sleep 1; done; \ + test -f $(srcdir)/file-ostream.h; \ + fi; \ + } +BUILT_SOURCES += file-ostream.h file-ostream.c file_ostream.priv.h file_ostream.vt.h +MAINTAINERCLEANFILES += file-ostream.h file-ostream.c file_ostream.priv.h file_ostream.vt.h +EXTRA_DIST += file-ostream.h file-ostream.c file_ostream.priv.h file_ostream.vt.h + +EXTRA_DIST += file-ostream.oo.c file-ostream.oo.h + +EXTRA_libgettextlib_la_SOURCES += file-ostream.oo.c + +## end gnulib module file-ostream + +## begin gnulib module filename + + +EXTRA_DIST += filename.h + +## end gnulib module filename + +## begin gnulib module findprog + +libgettextlib_la_SOURCES += findprog.h findprog.c + +## end gnulib module findprog + +## begin gnulib module float + +BUILT_SOURCES += $(FLOAT_H) + +# We need the following in order to create when the system +# doesn't have one that works with the given compiler. +if GL_GENERATE_FLOAT_H +float.h: float.in.h $(top_builddir)/config.status + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_FLOAT_H''@|$(NEXT_FLOAT_H)|g' \ + -e 's|@''REPLACE_ITOLD''@|$(REPLACE_ITOLD)|g' \ + < $(srcdir)/float.in.h; \ + } > $@-t && \ + mv $@-t $@ +else +float.h: $(top_builddir)/config.status + rm -f $@ +endif +MOSTLYCLEANFILES += float.h float.h-t + +EXTRA_DIST += float.c float.in.h itold.c + +EXTRA_libgettextlib_la_SOURCES += float.c itold.c + +## end gnulib module float + +## begin gnulib module fnmatch + +BUILT_SOURCES += $(FNMATCH_H) + +# We need the following in order to create when the system +# doesn't have one that supports the required API. +if GL_GENERATE_FNMATCH_H +fnmatch.h: fnmatch.in.h $(top_builddir)/config.status $(ARG_NONNULL_H) + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + sed -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ + < $(srcdir)/fnmatch.in.h; \ + } > $@-t && \ + mv -f $@-t $@ +else +fnmatch.h: $(top_builddir)/config.status + rm -f $@ +endif +MOSTLYCLEANFILES += fnmatch.h fnmatch.h-t + +EXTRA_DIST += fnmatch.c fnmatch.in.h fnmatch_loop.c + +EXTRA_libgettextlib_la_SOURCES += fnmatch.c fnmatch_loop.c + +## end gnulib module fnmatch + +## begin gnulib module fopen + + +EXTRA_DIST += fopen.c + +EXTRA_libgettextlib_la_SOURCES += fopen.c + +## end gnulib module fopen + +## begin gnulib module fstat + + +EXTRA_DIST += fstat.c + +EXTRA_libgettextlib_la_SOURCES += fstat.c + +## end gnulib module fstat + +## begin gnulib module fstrcmp + +libgettextlib_la_SOURCES += fstrcmp.h fstrcmp.c + +## end gnulib module fstrcmp + +## begin gnulib module full-write + +libgettextlib_la_SOURCES += full-write.h full-write.c + +## end gnulib module full-write + +## begin gnulib module fwriteerror + +libgettextlib_la_SOURCES += fwriteerror.h fwriteerror.c + +## end gnulib module fwriteerror + +## begin gnulib module gcd + +libgettextlib_la_SOURCES += gcd.h gcd.c + +## end gnulib module gcd + +## begin gnulib module getdelim + + +EXTRA_DIST += getdelim.c + +EXTRA_libgettextlib_la_SOURCES += getdelim.c + +## end gnulib module getdelim + +## begin gnulib module getdtablesize + + +EXTRA_DIST += getdtablesize.c + +EXTRA_libgettextlib_la_SOURCES += getdtablesize.c + +## end gnulib module getdtablesize + +## begin gnulib module getline + + +EXTRA_DIST += getline.c + +EXTRA_libgettextlib_la_SOURCES += getline.c + +## end gnulib module getline + +## begin gnulib module getopt-posix + +BUILT_SOURCES += $(GETOPT_H) + +# We need the following in order to create when the system +# doesn't have one that works with the given compiler. +getopt.h: getopt.in.h $(top_builddir)/config.status $(ARG_NONNULL_H) + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''HAVE_GETOPT_H''@|$(HAVE_GETOPT_H)|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_GETOPT_H''@|$(NEXT_GETOPT_H)|g' \ + -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ + < $(srcdir)/getopt.in.h; \ + } > $@-t && \ + mv -f $@-t $@ +MOSTLYCLEANFILES += getopt.h getopt.h-t + +EXTRA_DIST += getopt.c getopt.in.h getopt1.c getopt_int.h + +EXTRA_libgettextlib_la_SOURCES += getopt.c getopt1.c + +## end gnulib module getopt-posix + +## begin gnulib module gettext + +# If your project uses "gettextize --intl" to put a source-code +# copy of libintl into the package, every Makefile.am needs +# -I$(top_builddir)/intl, so that can be found in this directory. +# Here's one way to do this: +#AM_CPPFLAGS += -I$(top_builddir)/intl +# This option has no effect when the user disables NLS (because then +# the intl directory contains no libintl.h file). This option is not +# enabled by default because the intl directory might not exist if +# your project does not use "gettext --intl", and some compilers +# complain about -I options applied to nonexistent directories. + +EXTRA_DIST += $(top_srcdir)/../build-aux/config.rpath + +## end gnulib module gettext + +## begin gnulib module gettext-h + +libgettextlib_la_SOURCES += gettext.h + +## end gnulib module gettext-h + +## begin gnulib module gettext-tools-misc + + +# Specify that libgettextlib should installed in $(libdir). +lib_LTLIBRARIES = libgettextlib.la + +# Need $(LTLIBUNISTRING) because ulc_width_linebreaks, uc_width, etc. may be +# taken from libunistring, when the configure option --with-libunistring-prefix +# was given. +# Need @LTLIBINTL@ because many source files use gettext(). +# Need @LTLIBICONV@ because linebreak.c and striconv.c use iconv(). +# Need @LIB_ACL@ because copy-file.c uses acl.h. +# As of 2010-10-04, these are all added by gnulib-tool automatically. +#libgettextlib_la_LDFLAGS += $(LTLIBUNISTRING) @LTLIBINTL@ @LTLIBICONV@ @LIB_ACL@ + +libgettextlib_la_LDFLAGS += -release @VERSION@ + +# Tell the mingw or Cygwin linker which symbols to export. +if WOE32DLL +libgettextlib_la_SOURCES += ../woe32dll/gettextlib-exports.c +libgettextlib_la_LDFLAGS += -Wl,--export-all-symbols +AM_CPPFLAGS += @GETTEXTLIB_EXPORTS_FLAGS@ +endif + +# No need to install libgettextlib.a, except on AIX. +install-exec-local: install-libLTLIBRARIES install-exec-clean +install-exec-clean: + case "@host_os@" in \ + aix*) ;; \ + *) rm -f $(DESTDIR)$(libdir)/libgettextlib.a ;; \ + esac + +## end gnulib module gettext-tools-misc + +## begin gnulib module gettimeofday + + +EXTRA_DIST += gettimeofday.c + +EXTRA_libgettextlib_la_SOURCES += gettimeofday.c + +## end gnulib module gettimeofday + +## begin gnulib module gperf + +GPERF = gperf + +## end gnulib module gperf + +## begin gnulib module hash + +libgettextlib_la_SOURCES += hash.h hash.c + +## end gnulib module hash + +## begin gnulib module havelib + + +EXTRA_DIST += $(top_srcdir)/../build-aux/config.rpath + +## end gnulib module havelib + +## begin gnulib module html-ostream + +libgettextlib_la_SOURCES += html-ostream.c +# This is a Makefile rule that generates multiple files at once; see the +# automake documentation, node "Multiple Outputs", for details. +html-ostream.h : $(top_srcdir)/../build-aux/moopp html-ostream.oo.h html-ostream.oo.c ostream.oo.h + $(top_srcdir)/../build-aux/moopp $(MOOPPFLAGS) $(srcdir)/html-ostream.oo.c $(srcdir)/html-ostream.oo.h $(srcdir)/ostream.oo.h +html-ostream.c html_ostream.priv.h html_ostream.vt.h : html-ostream.h + @test -f $@ || { \ + trap 'rm -rf html-ostream.lock' 1 2 13 15; \ + if mkdir html-ostream.lock 2>/dev/null; then \ + echo "$(top_srcdir)/../build-aux/moopp $(MOOPPFLAGS) $(srcdir)/html-ostream.oo.c $(srcdir)/html-ostream.oo.h $(srcdir)/ostream.oo.h"; \ + $(top_srcdir)/../build-aux/moopp $(MOOPPFLAGS) $(srcdir)/html-ostream.oo.c $(srcdir)/html-ostream.oo.h $(srcdir)/ostream.oo.h; \ + result=$$?; rm -rf html-ostream.lock; exit $$result; \ + else \ + while test -d html-ostream.lock; do sleep 1; done; \ + test -f $(srcdir)/html-ostream.h; \ + fi; \ + } +BUILT_SOURCES += html-ostream.h html-ostream.c html_ostream.priv.h html_ostream.vt.h +MAINTAINERCLEANFILES += html-ostream.h html-ostream.c html_ostream.priv.h html_ostream.vt.h +EXTRA_DIST += html-ostream.h html-ostream.c html_ostream.priv.h html_ostream.vt.h + +EXTRA_DIST += html-ostream.oo.c html-ostream.oo.h + +EXTRA_libgettextlib_la_SOURCES += html-ostream.oo.c + +## end gnulib module html-ostream + +## begin gnulib module html-styled-ostream + +if !WOE32DLL +libgettextlib_la_SOURCES += html-styled-ostream.c +else +libgettextlib_la_SOURCES += ../woe32dll/c++html-styled-ostream.cc +endif +# This is a Makefile rule that generates multiple files at once; see the +# automake documentation, node "Multiple Outputs", for details. +html-styled-ostream.h : $(top_srcdir)/../build-aux/moopp html-styled-ostream.oo.h html-styled-ostream.oo.c styled-ostream.oo.h ostream.oo.h + $(top_srcdir)/../build-aux/moopp $(MOOPPFLAGS) $(srcdir)/html-styled-ostream.oo.c $(srcdir)/html-styled-ostream.oo.h $(srcdir)/styled-ostream.oo.h $(srcdir)/ostream.oo.h +html-styled-ostream.c html_styled_ostream.priv.h html_styled_ostream.vt.h : html-styled-ostream.h + @test -f $@ || { \ + trap 'rm -rf html-styled-ostream.lock' 1 2 13 15; \ + if mkdir html-styled-ostream.lock 2>/dev/null; then \ + echo "$(top_srcdir)/../build-aux/moopp $(MOOPPFLAGS) $(srcdir)/html-styled-ostream.oo.c $(srcdir)/html-styled-ostream.oo.h $(srcdir)/styled-ostream.oo.h $(srcdir)/ostream.oo.h"; \ + $(top_srcdir)/../build-aux/moopp $(MOOPPFLAGS) $(srcdir)/html-styled-ostream.oo.c $(srcdir)/html-styled-ostream.oo.h $(srcdir)/styled-ostream.oo.h $(srcdir)/ostream.oo.h; \ + result=$$?; rm -rf html-styled-ostream.lock; exit $$result; \ + else \ + while test -d html-styled-ostream.lock; do sleep 1; done; \ + test -f $(srcdir)/html-styled-ostream.h; \ + fi; \ + } +BUILT_SOURCES += html-styled-ostream.h html-styled-ostream.c html_styled_ostream.priv.h html_styled_ostream.vt.h +MAINTAINERCLEANFILES += html-styled-ostream.h html-styled-ostream.c html_styled_ostream.priv.h html_styled_ostream.vt.h +EXTRA_DIST += html-styled-ostream.h html-styled-ostream.c html_styled_ostream.priv.h html_styled_ostream.vt.h + +EXTRA_DIST += html-styled-ostream.oo.c html-styled-ostream.oo.h + +EXTRA_libgettextlib_la_SOURCES += html-styled-ostream.oo.c + +## end gnulib module html-styled-ostream + +## begin gnulib module iconv-h + +BUILT_SOURCES += $(ICONV_H) + +# We need the following in order to create when the system +# doesn't have one that works with the given compiler. +if GL_GENERATE_ICONV_H +iconv.h: iconv.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_ICONV_H''@|$(NEXT_ICONV_H)|g' \ + -e 's/@''GNULIB_ICONV''@/$(GNULIB_ICONV)/g' \ + -e 's|@''ICONV_CONST''@|$(ICONV_CONST)|g' \ + -e 's|@''REPLACE_ICONV''@|$(REPLACE_ICONV)|g' \ + -e 's|@''REPLACE_ICONV_OPEN''@|$(REPLACE_ICONV_OPEN)|g' \ + -e 's|@''REPLACE_ICONV_UTF''@|$(REPLACE_ICONV_UTF)|g' \ + -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ + < $(srcdir)/iconv.in.h; \ + } > $@-t && \ + mv $@-t $@ +else +iconv.h: $(top_builddir)/config.status + rm -f $@ +endif +MOSTLYCLEANFILES += iconv.h iconv.h-t + +EXTRA_DIST += iconv.in.h + +## end gnulib module iconv-h + +## begin gnulib module iconv_open + +iconv_open-aix.h: iconv_open-aix.gperf + $(GPERF) -m 10 $(srcdir)/iconv_open-aix.gperf > $(srcdir)/iconv_open-aix.h-t + mv $(srcdir)/iconv_open-aix.h-t $(srcdir)/iconv_open-aix.h +iconv_open-hpux.h: iconv_open-hpux.gperf + $(GPERF) -m 10 $(srcdir)/iconv_open-hpux.gperf > $(srcdir)/iconv_open-hpux.h-t + mv $(srcdir)/iconv_open-hpux.h-t $(srcdir)/iconv_open-hpux.h +iconv_open-irix.h: iconv_open-irix.gperf + $(GPERF) -m 10 $(srcdir)/iconv_open-irix.gperf > $(srcdir)/iconv_open-irix.h-t + mv $(srcdir)/iconv_open-irix.h-t $(srcdir)/iconv_open-irix.h +iconv_open-osf.h: iconv_open-osf.gperf + $(GPERF) -m 10 $(srcdir)/iconv_open-osf.gperf > $(srcdir)/iconv_open-osf.h-t + mv $(srcdir)/iconv_open-osf.h-t $(srcdir)/iconv_open-osf.h +iconv_open-solaris.h: iconv_open-solaris.gperf + $(GPERF) -m 10 $(srcdir)/iconv_open-solaris.gperf > $(srcdir)/iconv_open-solaris.h-t + mv $(srcdir)/iconv_open-solaris.h-t $(srcdir)/iconv_open-solaris.h +BUILT_SOURCES += iconv_open-aix.h iconv_open-hpux.h iconv_open-irix.h iconv_open-osf.h iconv_open-solaris.h +MOSTLYCLEANFILES += iconv_open-aix.h-t iconv_open-hpux.h-t iconv_open-irix.h-t iconv_open-osf.h-t iconv_open-solaris.h-t +MAINTAINERCLEANFILES += iconv_open-aix.h iconv_open-hpux.h iconv_open-irix.h iconv_open-osf.h iconv_open-solaris.h +EXTRA_DIST += iconv_open-aix.h iconv_open-hpux.h iconv_open-irix.h iconv_open-osf.h iconv_open-solaris.h + +EXTRA_DIST += iconv.c iconv_close.c iconv_open-aix.gperf iconv_open-hpux.gperf iconv_open-irix.gperf iconv_open-osf.gperf iconv_open-solaris.gperf iconv_open.c + +EXTRA_libgettextlib_la_SOURCES += iconv.c iconv_close.c iconv_open.c + +## end gnulib module iconv_open + +## begin gnulib module ignore-value + + +EXTRA_DIST += ignore-value.h + +## end gnulib module ignore-value + +## begin gnulib module intprops + + +EXTRA_DIST += intprops.h + +## end gnulib module intprops + +## begin gnulib module iswblank + + +EXTRA_DIST += iswblank.c + +EXTRA_libgettextlib_la_SOURCES += iswblank.c + +## end gnulib module iswblank + +## begin gnulib module javacomp + +libgettextlib_la_SOURCES += javacomp.h javacomp.c + +## end gnulib module javacomp + +## begin gnulib module javacomp-script + + +EXTRA_DIST += $(top_srcdir)/../build-aux/javacomp.sh.in + +## end gnulib module javacomp-script + +## begin gnulib module javaexec + +DEFS += -DEXEEXT=\"@EXEEXT@\" +libgettextlib_la_SOURCES += javaexec.h javaexec.c + +## end gnulib module javaexec + +## begin gnulib module javaexec-script + + +EXTRA_DIST += $(top_srcdir)/../build-aux/javaexec.sh.in + +## end gnulib module javaexec-script + +## begin gnulib module javaversion + +libgettextlib_la_SOURCES += javaversion.h javaversion.c +pkgdata_DATA += javaversion.class + +EXTRA_DIST += javaversion.class javaversion.java + +## end gnulib module javaversion + +## begin gnulib module libcroco + +AM_CPPFLAGS += $(INCGLIB) +AM_CPPFLAGS += $(INCXML) +if INCLUDED_LIBCROCO +AM_CPPFLAGS += -I$(srcdir)/libcroco +libgettextlib_la_LIBADD += libcroco_rpl.la +libgettextlib_la_DEPENDENCIES += libcroco_rpl.la +noinst_LTLIBRARIES += libcroco_rpl.la +else +AM_CPPFLAGS += $(INCCROCO) +endif + +libcroco_rpl_la_SOURCES = \ + libcroco/cr-additional-sel.c \ + libcroco/cr-attr-sel.c \ + libcroco/cr-cascade.c \ + libcroco/cr-declaration.c \ + libcroco/cr-doc-handler.c \ + libcroco/cr-enc-handler.c \ + libcroco/cr-fonts.c \ + libcroco/cr-input.c \ + libcroco/cr-num.c \ + libcroco/cr-om-parser.c \ + libcroco/cr-parser.c \ + libcroco/cr-parsing-location.c \ + libcroco/cr-prop-list.c \ + libcroco/cr-pseudo.c \ + libcroco/cr-rgb.c \ + libcroco/cr-sel-eng.c \ + libcroco/cr-selector.c \ + libcroco/cr-simple-sel.c \ + libcroco/cr-statement.c \ + libcroco/cr-string.c \ + libcroco/cr-style.c \ + libcroco/cr-stylesheet.c \ + libcroco/cr-term.c \ + libcroco/cr-tknzr.c \ + libcroco/cr-token.c \ + libcroco/cr-utils.c +libcroco_rpl_la_CPPFLAGS = $(AM_CPPFLAGS) $(NO_CXX) + +if GL_COND_LIBTOOL +libgettextlib_la_LDFLAGS += $(LTLIBCROCO) +endif + +EXTRA_DIST += libcroco/cr-additional-sel.c libcroco/cr-additional-sel.h libcroco/cr-attr-sel.c libcroco/cr-attr-sel.h libcroco/cr-cascade.c libcroco/cr-cascade.h libcroco/cr-declaration.c libcroco/cr-declaration.h libcroco/cr-doc-handler.c libcroco/cr-doc-handler.h libcroco/cr-enc-handler.c libcroco/cr-enc-handler.h libcroco/cr-fonts.c libcroco/cr-fonts.h libcroco/cr-input.c libcroco/cr-input.h libcroco/cr-num.c libcroco/cr-num.h libcroco/cr-om-parser.c libcroco/cr-om-parser.h libcroco/cr-parser.c libcroco/cr-parser.h libcroco/cr-parsing-location.c libcroco/cr-parsing-location.h libcroco/cr-prop-list.c libcroco/cr-prop-list.h libcroco/cr-pseudo.c libcroco/cr-pseudo.h libcroco/cr-rgb.c libcroco/cr-rgb.h libcroco/cr-sel-eng.c libcroco/cr-sel-eng.h libcroco/cr-selector.c libcroco/cr-selector.h libcroco/cr-simple-sel.c libcroco/cr-simple-sel.h libcroco/cr-statement.c libcroco/cr-statement.h libcroco/cr-string.c libcroco/cr-string.h libcroco/cr-style.c libcroco/cr-style.h libcroco/cr-stylesheet.c libcroco/cr-stylesheet.h libcroco/cr-term.c libcroco/cr-term.h libcroco/cr-tknzr.c libcroco/cr-tknzr.h libcroco/cr-token.c libcroco/cr-token.h libcroco/cr-utils.c libcroco/cr-utils.h libcroco/libcroco-config.h libcroco/libcroco.h + +EXTRA_libgettextlib_la_SOURCES += libcroco/cr-additional-sel.c libcroco/cr-attr-sel.c libcroco/cr-cascade.c libcroco/cr-declaration.c libcroco/cr-doc-handler.c libcroco/cr-enc-handler.c libcroco/cr-fonts.c libcroco/cr-input.c libcroco/cr-num.c libcroco/cr-om-parser.c libcroco/cr-parser.c libcroco/cr-parsing-location.c libcroco/cr-prop-list.c libcroco/cr-pseudo.c libcroco/cr-rgb.c libcroco/cr-sel-eng.c libcroco/cr-selector.c libcroco/cr-simple-sel.c libcroco/cr-statement.c libcroco/cr-string.c libcroco/cr-style.c libcroco/cr-stylesheet.c libcroco/cr-term.c libcroco/cr-tknzr.c libcroco/cr-token.c libcroco/cr-utils.c + +## end gnulib module libcroco + +## begin gnulib module libglib + +if INCLUDED_LIBGLIB +libgettextlib_la_LIBADD += libglib_rpl.la +libgettextlib_la_DEPENDENCIES += libglib_rpl.la +noinst_LTLIBRARIES += libglib_rpl.la +endif + +libglib_rpl_la_SOURCES = \ + glib/ghash.c \ + glib/glist.c \ + glib/gmessages.c \ + glib/gprimes.c \ + glib/gstrfuncs.c \ + glib/gstring.c +libglib_rpl_la_CPPFLAGS = $(AM_CPPFLAGS) $(NO_CXX) + +BUILT_SOURCES += $(LIBGLIB_H) + +glib.h: glib.in.h + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/glib.in.h; \ + } > $@-t + mv -f $@-t $@ + +glibconfig.h: glibconfig.in.h + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/glibconfig.in.h; \ + } > $@-t + mv -f $@-t $@ + +glib/ghash.h: glib/ghash.in.h + test -d glib || $(MKDIR_P) glib + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/glib/ghash.in.h; \ + } > $@-t + mv -f $@-t $@ + +glib/glist.h: glib/glist.in.h + test -d glib || $(MKDIR_P) glib + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/glib/glist.in.h; \ + } > $@-t + mv -f $@-t $@ + +glib/gprimes.h: glib/gprimes.in.h + test -d glib || $(MKDIR_P) glib + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/glib/gprimes.in.h; \ + } > $@-t + mv -f $@-t $@ + +glib/gstrfuncs.h: glib/gstrfuncs.in.h + test -d glib || $(MKDIR_P) glib + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/glib/gstrfuncs.in.h; \ + } > $@-t + mv -f $@-t $@ + +glib/gstring.h: glib/gstring.in.h + test -d glib || $(MKDIR_P) glib + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/glib/gstring.in.h; \ + } > $@-t + mv -f $@-t $@ + +glib/gtypes.h: glib/gtypes.in.h + test -d glib || $(MKDIR_P) glib + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/glib/gtypes.in.h; \ + } > $@-t + mv -f $@-t $@ + +MOSTLYCLEANFILES += \ + glib.h \ + glibconfig.h \ + glib/ghash.h \ + glib/glist.h \ + glib/gprimes.h \ + glib/gstrfuncs.h \ + glib/gstring.h \ + glib/gtypes.h +MOSTLYCLEANFILES += glib/*.h-t + +if GL_COND_LIBTOOL +libgettextlib_la_LDFLAGS += $(LTLIBGLIB) +endif + +EXTRA_DIST += glib.in.h glib/ghash.c glib/ghash.in.h glib/glist.c glib/glist.in.h glib/gmessages.c glib/gprimes.c glib/gprimes.in.h glib/gstrfuncs.c glib/gstrfuncs.in.h glib/gstring.c glib/gstring.in.h glib/gtypes.in.h glibconfig.in.h + +EXTRA_libgettextlib_la_SOURCES += glib/ghash.c glib/glist.c glib/gmessages.c glib/gprimes.c glib/gstrfuncs.c glib/gstring.c + +## end gnulib module libglib + +## begin gnulib module libunistring-optional + + +EXTRA_DIST += libunistring.valgrind + +## end gnulib module libunistring-optional + +## begin gnulib module libxml + +if INCLUDED_LIBXML +libgettextlib_la_LIBADD += libxml_rpl.la +libgettextlib_la_DEPENDENCIES += libxml_rpl.la +noinst_LTLIBRARIES += libxml_rpl.la +endif + +libxml_rpl_la_SOURCES = \ + libxml/DOCBparser.c \ + libxml/HTMLparser.c \ + libxml/HTMLtree.c \ + libxml/SAX.c \ + libxml/SAX2.c \ + libxml/c14n.c \ + libxml/catalog.c \ + libxml/chvalid.c \ + libxml/debugXML.c \ + libxml/dict.c \ + libxml/encoding.c \ + libxml/entities.c \ + libxml/error.c \ + libxml/globals.c \ + libxml/hash.c \ + libxml/legacy.c \ + libxml/list.c \ + libxml/nanoftp.c \ + libxml/nanohttp.c \ + libxml/parser.c \ + libxml/parserInternals.c \ + libxml/pattern.c \ + libxml/relaxng.c \ + libxml/schematron.c \ + libxml/threads.c \ + libxml/tree.c \ + libxml/uri.c \ + libxml/valid.c \ + libxml/xinclude.c \ + libxml/xlink.c \ + libxml/xmlIO.c \ + libxml/xmlmemory.c \ + libxml/xmlmodule.c \ + libxml/xmlreader.c \ + libxml/xmlregexp.c \ + libxml/xmlsave.c \ + libxml/xmlschemas.c \ + libxml/xmlschemastypes.c \ + libxml/xmlstring.c \ + libxml/xmlunicode.c \ + libxml/xmlwriter.c \ + libxml/xpath.c \ + libxml/xpointer.c +libxml_rpl_la_CPPFLAGS = $(AM_CPPFLAGS) $(NO_CXX) + +BUILT_SOURCES += $(LIBXML_H) + +libxml/DOCBparser.h: libxml/DOCBparser.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/DOCBparser.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/HTMLparser.h: libxml/HTMLparser.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/HTMLparser.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/HTMLtree.h: libxml/HTMLtree.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/HTMLtree.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/SAX.h: libxml/SAX.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/SAX.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/SAX2.h: libxml/SAX2.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/SAX2.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/c14n.h: libxml/c14n.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/c14n.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/catalog.h: libxml/catalog.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/catalog.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/chvalid.h: libxml/chvalid.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/chvalid.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/debugXML.h: libxml/debugXML.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/debugXML.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/dict.h: libxml/dict.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/dict.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/encoding.h: libxml/encoding.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/encoding.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/entities.h: libxml/entities.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/entities.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/globals.h: libxml/globals.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/globals.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/hash.h: libxml/hash.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/hash.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/list.h: libxml/list.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/list.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/nanoftp.h: libxml/nanoftp.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/nanoftp.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/nanohttp.h: libxml/nanohttp.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/nanohttp.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/parser.h: libxml/parser.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/parser.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/parserInternals.h: libxml/parserInternals.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/parserInternals.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/pattern.h: libxml/pattern.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/pattern.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/relaxng.h: libxml/relaxng.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/relaxng.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/schemasInternals.h: libxml/schemasInternals.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/schemasInternals.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/schematron.h: libxml/schematron.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/schematron.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/threads.h: libxml/threads.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/threads.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/tree.h: libxml/tree.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/tree.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/uri.h: libxml/uri.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/uri.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/valid.h: libxml/valid.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/valid.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/xinclude.h: libxml/xinclude.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/xinclude.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/xlink.h: libxml/xlink.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/xlink.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/xmlIO.h: libxml/xmlIO.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/xmlIO.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/xmlautomata.h: libxml/xmlautomata.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/xmlautomata.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/xmlerror.h: libxml/xmlerror.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/xmlerror.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/xmlexports.h: libxml/xmlexports.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/xmlexports.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/xmlmemory.h: libxml/xmlmemory.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/xmlmemory.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/xmlmodule.h: libxml/xmlmodule.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/xmlmodule.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/xmlreader.h: libxml/xmlreader.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/xmlreader.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/xmlregexp.h: libxml/xmlregexp.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/xmlregexp.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/xmlsave.h: libxml/xmlsave.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/xmlsave.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/xmlschemas.h: libxml/xmlschemas.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/xmlschemas.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/xmlschemastypes.h: libxml/xmlschemastypes.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/xmlschemastypes.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/xmlstring.h: libxml/xmlstring.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/xmlstring.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/xmlunicode.h: libxml/xmlunicode.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/xmlunicode.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/xmlversion.h: libxml/xmlversion.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/xmlversion.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/xmlwriter.h: libxml/xmlwriter.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/xmlwriter.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/xpath.h: libxml/xpath.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/xpath.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/xpathInternals.h: libxml/xpathInternals.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/xpathInternals.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/xpointer.h: libxml/xpointer.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/xpointer.in.h; \ + } > $@-t + mv -f $@-t $@ + +MOSTLYCLEANFILES += \ + libxml/DOCBparser.h \ + libxml/HTMLparser.h \ + libxml/HTMLtree.h \ + libxml/SAX.h \ + libxml/SAX2.h \ + libxml/c14n.h \ + libxml/catalog.h \ + libxml/chvalid.h \ + libxml/debugXML.h \ + libxml/dict.h \ + libxml/encoding.h \ + libxml/entities.h \ + libxml/globals.h \ + libxml/hash.h \ + libxml/list.h \ + libxml/nanoftp.h \ + libxml/nanohttp.h \ + libxml/parser.h \ + libxml/parserInternals.h \ + libxml/pattern.h \ + libxml/relaxng.h \ + libxml/schemasInternals.h \ + libxml/schematron.h \ + libxml/threads.h \ + libxml/tree.h \ + libxml/uri.h \ + libxml/valid.h \ + libxml/xinclude.h \ + libxml/xlink.h \ + libxml/xmlIO.h \ + libxml/xmlautomata.h \ + libxml/xmlerror.h \ + libxml/xmlexports.h \ + libxml/xmlmemory.h \ + libxml/xmlmodule.h \ + libxml/xmlreader.h \ + libxml/xmlregexp.h \ + libxml/xmlsave.h \ + libxml/xmlschemas.h \ + libxml/xmlschemastypes.h \ + libxml/xmlstring.h \ + libxml/xmlunicode.h \ + libxml/xmlversion.h \ + libxml/xmlwriter.h \ + libxml/xpath.h \ + libxml/xpathInternals.h \ + libxml/xpointer.h +MOSTLYCLEANFILES += libxml/*.h-t + +if GL_COND_LIBTOOL +libgettextlib_la_LDFLAGS += $(LTLIBXML) +endif + +EXTRA_DIST += libxml/COPYING libxml/DOCBparser.c libxml/DOCBparser.in.h libxml/HTMLparser.c libxml/HTMLparser.in.h libxml/HTMLtree.c libxml/HTMLtree.in.h libxml/SAX.c libxml/SAX.in.h libxml/SAX2.c libxml/SAX2.in.h libxml/c14n.c libxml/c14n.in.h libxml/catalog.c libxml/catalog.in.h libxml/chvalid.c libxml/chvalid.in.h libxml/debugXML.c libxml/debugXML.in.h libxml/dict.c libxml/dict.in.h libxml/elfgcchack.h libxml/encoding.c libxml/encoding.in.h libxml/entities.c libxml/entities.in.h libxml/error.c libxml/globals.c libxml/globals.in.h libxml/hash.c libxml/hash.in.h libxml/legacy.c libxml/libxml.h libxml/list.c libxml/list.in.h libxml/nanoftp.c libxml/nanoftp.in.h libxml/nanohttp.c libxml/nanohttp.in.h libxml/parser.c libxml/parser.in.h libxml/parserInternals.c libxml/parserInternals.in.h libxml/pattern.c libxml/pattern.in.h libxml/relaxng.c libxml/relaxng.in.h libxml/schemasInternals.in.h libxml/schematron.c libxml/schematron.in.h libxml/threads.c libxml/threads.in.h libxml/tree.c libxml/tree.in.h libxml/uri.c libxml/uri.in.h libxml/valid.c libxml/valid.in.h libxml/xinclude.c libxml/xinclude.in.h libxml/xlink.c libxml/xlink.in.h libxml/xmlIO.c libxml/xmlIO.in.h libxml/xmlautomata.in.h libxml/xmlerror.in.h libxml/xmlexports.in.h libxml/xmlmemory.c libxml/xmlmemory.in.h libxml/xmlmodule.c libxml/xmlmodule.in.h libxml/xmlreader.c libxml/xmlreader.in.h libxml/xmlregexp.c libxml/xmlregexp.in.h libxml/xmlsave.c libxml/xmlsave.in.h libxml/xmlschemas.c libxml/xmlschemas.in.h libxml/xmlschemastypes.c libxml/xmlschemastypes.in.h libxml/xmlstring.c libxml/xmlstring.in.h libxml/xmlunicode.c libxml/xmlunicode.in.h libxml/xmlversion.in.h libxml/xmlwriter.c libxml/xmlwriter.in.h libxml/xpath.c libxml/xpath.in.h libxml/xpathInternals.in.h libxml/xpointer.c libxml/xpointer.in.h + +EXTRA_libgettextlib_la_SOURCES += libxml/DOCBparser.c libxml/HTMLparser.c libxml/HTMLtree.c libxml/SAX.c libxml/SAX2.c libxml/c14n.c libxml/catalog.c libxml/chvalid.c libxml/debugXML.c libxml/dict.c libxml/encoding.c libxml/entities.c libxml/error.c libxml/globals.c libxml/hash.c libxml/legacy.c libxml/list.c libxml/nanoftp.c libxml/nanohttp.c libxml/parser.c libxml/parserInternals.c libxml/pattern.c libxml/relaxng.c libxml/schematron.c libxml/threads.c libxml/tree.c libxml/uri.c libxml/valid.c libxml/xinclude.c libxml/xlink.c libxml/xmlIO.c libxml/xmlmemory.c libxml/xmlmodule.c libxml/xmlreader.c libxml/xmlregexp.c libxml/xmlsave.c libxml/xmlschemas.c libxml/xmlschemastypes.c libxml/xmlstring.c libxml/xmlunicode.c libxml/xmlwriter.c libxml/xpath.c libxml/xpointer.c + +## end gnulib module libxml + +## begin gnulib module linkedhash-list + +libgettextlib_la_SOURCES += gl_linkedhash_list.h gl_linkedhash_list.c gl_anyhash_list1.h gl_anyhash_list2.h gl_anylinked_list1.h gl_anylinked_list2.h + +## end gnulib module linkedhash-list + +## begin gnulib module list + +libgettextlib_la_SOURCES += gl_list.h gl_list.c + +## end gnulib module list + +## begin gnulib module localcharset + +libgettextlib_la_SOURCES += localcharset.h localcharset.c + +# We need the following in order to install a simple file in $(libdir) +# which is shared with other installed packages. We use a list of referencing +# packages so that "make uninstall" will remove the file if and only if it +# is not used by another installed package. +# On systems with glibc-2.1 or newer, the file is redundant, therefore we +# avoid installing it. + +all-local: charset.alias ref-add.sed ref-del.sed + +charset_alias = $(DESTDIR)$(libdir)/charset.alias +charset_tmp = $(DESTDIR)$(libdir)/charset.tmp +install-exec-local: install-exec-localcharset +install-exec-localcharset: all-local + if test $(GLIBC21) = no; then \ + case '$(host_os)' in \ + darwin[56]*) \ + need_charset_alias=true ;; \ + darwin* | cygwin* | mingw* | pw32* | cegcc*) \ + need_charset_alias=false ;; \ + *) \ + need_charset_alias=true ;; \ + esac ; \ + else \ + need_charset_alias=false ; \ + fi ; \ + if $$need_charset_alias; then \ + $(mkinstalldirs) $(DESTDIR)$(libdir) ; \ + fi ; \ + if test -f $(charset_alias); then \ + sed -f ref-add.sed $(charset_alias) > $(charset_tmp) ; \ + $(INSTALL_DATA) $(charset_tmp) $(charset_alias) ; \ + rm -f $(charset_tmp) ; \ + else \ + if $$need_charset_alias; then \ + sed -f ref-add.sed charset.alias > $(charset_tmp) ; \ + $(INSTALL_DATA) $(charset_tmp) $(charset_alias) ; \ + rm -f $(charset_tmp) ; \ + fi ; \ + fi + +uninstall-local: uninstall-localcharset +uninstall-localcharset: all-local + if test -f $(charset_alias); then \ + sed -f ref-del.sed $(charset_alias) > $(charset_tmp); \ + if grep '^# Packages using this file: $$' $(charset_tmp) \ + > /dev/null; then \ + rm -f $(charset_alias); \ + else \ + $(INSTALL_DATA) $(charset_tmp) $(charset_alias); \ + fi; \ + rm -f $(charset_tmp); \ + fi + +charset.alias: config.charset + $(AM_V_GEN)rm -f t-$@ $@ && \ + $(SHELL) $(srcdir)/config.charset '$(host)' > t-$@ && \ + mv t-$@ $@ + +SUFFIXES += .sed .sin +.sin.sed: + $(AM_V_GEN)rm -f t-$@ $@ && \ + sed -e '/^#/d' -e 's/@''PACKAGE''@/$(PACKAGE)/g' $< > t-$@ && \ + mv t-$@ $@ + +CLEANFILES += charset.alias ref-add.sed ref-del.sed + +EXTRA_DIST += config.charset ref-add.sin ref-del.sin + +## end gnulib module localcharset + +## begin gnulib module locale + +BUILT_SOURCES += locale.h + +# We need the following in order to create when the system +# doesn't have one that provides all definitions. +locale.h: locale.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_LOCALE_H''@|$(NEXT_LOCALE_H)|g' \ + -e 's/@''GNULIB_LOCALECONV''@/$(GNULIB_LOCALECONV)/g' \ + -e 's/@''GNULIB_SETLOCALE''@/$(GNULIB_SETLOCALE)/g' \ + -e 's/@''GNULIB_DUPLOCALE''@/$(GNULIB_DUPLOCALE)/g' \ + -e 's|@''HAVE_DUPLOCALE''@|$(HAVE_DUPLOCALE)|g' \ + -e 's|@''HAVE_XLOCALE_H''@|$(HAVE_XLOCALE_H)|g' \ + -e 's|@''REPLACE_LOCALECONV''@|$(REPLACE_LOCALECONV)|g' \ + -e 's|@''REPLACE_SETLOCALE''@|$(REPLACE_SETLOCALE)|g' \ + -e 's|@''REPLACE_DUPLOCALE''@|$(REPLACE_DUPLOCALE)|g' \ + -e 's|@''REPLACE_STRUCT_LCONV''@|$(REPLACE_STRUCT_LCONV)|g' \ + -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ + < $(srcdir)/locale.in.h; \ + } > $@-t && \ + mv $@-t $@ +MOSTLYCLEANFILES += locale.h locale.h-t + +EXTRA_DIST += locale.in.h + +## end gnulib module locale + +## begin gnulib module localename + +libgettextlib_la_SOURCES += localename.c + +EXTRA_DIST += localename.h + +## end gnulib module localename + +## begin gnulib module lock + +libgettextlib_la_SOURCES += glthread/lock.h glthread/lock.c + +## end gnulib module lock + +## begin gnulib module lstat + + +EXTRA_DIST += lstat.c + +EXTRA_libgettextlib_la_SOURCES += lstat.c + +## end gnulib module lstat + +## begin gnulib module malloc-posix + + +EXTRA_DIST += malloc.c + +EXTRA_libgettextlib_la_SOURCES += malloc.c + +## end gnulib module malloc-posix + +## begin gnulib module malloca + +libgettextlib_la_SOURCES += malloca.c + +EXTRA_DIST += malloca.h malloca.valgrind + +## end gnulib module malloca + +## begin gnulib module mbchar + +libgettextlib_la_SOURCES += mbchar.c + +EXTRA_DIST += mbchar.h + +## end gnulib module mbchar + +## begin gnulib module mbiter + +libgettextlib_la_SOURCES += mbiter.h mbiter.c + +## end gnulib module mbiter + +## begin gnulib module mbrtowc + + +EXTRA_DIST += mbrtowc.c + +EXTRA_libgettextlib_la_SOURCES += mbrtowc.c + +## end gnulib module mbrtowc + +## begin gnulib module mbsinit + + +EXTRA_DIST += mbsinit.c + +EXTRA_libgettextlib_la_SOURCES += mbsinit.c + +## end gnulib module mbsinit + +## begin gnulib module mbslen + +libgettextlib_la_SOURCES += mbslen.c + +## end gnulib module mbslen + +## begin gnulib module mbsrtowcs + + +EXTRA_DIST += mbsrtowcs-impl.h mbsrtowcs-state.c mbsrtowcs.c + +EXTRA_libgettextlib_la_SOURCES += mbsrtowcs-state.c mbsrtowcs.c + +## end gnulib module mbsrtowcs + +## begin gnulib module mbsstr + +libgettextlib_la_SOURCES += mbsstr.c + +EXTRA_DIST += str-kmp.h + +## end gnulib module mbsstr + +## begin gnulib module mbswidth + +libgettextlib_la_SOURCES += mbswidth.h mbswidth.c + +## end gnulib module mbswidth + +## begin gnulib module mbuiter + +libgettextlib_la_SOURCES += mbuiter.h mbuiter.c + +## end gnulib module mbuiter + +## begin gnulib module memchr + + +EXTRA_DIST += memchr.c memchr.valgrind + +EXTRA_libgettextlib_la_SOURCES += memchr.c + +## end gnulib module memchr + +## begin gnulib module memmove + + +EXTRA_DIST += memmove.c + +EXTRA_libgettextlib_la_SOURCES += memmove.c + +## end gnulib module memmove + +## begin gnulib module memset + + +EXTRA_DIST += memset.c + +EXTRA_libgettextlib_la_SOURCES += memset.c + +## end gnulib module memset + +## begin gnulib module minmax + +libgettextlib_la_SOURCES += minmax.h + +## end gnulib module minmax + +## begin gnulib module mkdtemp + + +EXTRA_DIST += mkdtemp.c + +EXTRA_libgettextlib_la_SOURCES += mkdtemp.c + +## end gnulib module mkdtemp + +## begin gnulib module moo + +MOOPPFLAGS = + +EXTRA_DIST += moo.h + +EXTRA_DIST += $(top_srcdir)/../build-aux/moopp + +## end gnulib module moo + +## begin gnulib module msvc-inval + + +EXTRA_DIST += msvc-inval.c msvc-inval.h + +EXTRA_libgettextlib_la_SOURCES += msvc-inval.c + +## end gnulib module msvc-inval + +## begin gnulib module msvc-nothrow + + +EXTRA_DIST += msvc-nothrow.c msvc-nothrow.h + +EXTRA_libgettextlib_la_SOURCES += msvc-nothrow.c + +## end gnulib module msvc-nothrow + +## begin gnulib module obstack + + +EXTRA_DIST += obstack.c obstack.h + +EXTRA_libgettextlib_la_SOURCES += obstack.c + +## end gnulib module obstack + +## begin gnulib module open + + +EXTRA_DIST += open.c + +EXTRA_libgettextlib_la_SOURCES += open.c + +## end gnulib module open + +## begin gnulib module opendir + + +EXTRA_DIST += dirent-private.h opendir.c + +EXTRA_libgettextlib_la_SOURCES += opendir.c + +## end gnulib module opendir + +## begin gnulib module ostream + +libgettextlib_la_SOURCES += ostream.c +# This is a Makefile rule that generates multiple files at once; see the +# automake documentation, node "Multiple Outputs", for details. +ostream.h : $(top_srcdir)/../build-aux/moopp ostream.oo.h ostream.oo.c + $(top_srcdir)/../build-aux/moopp $(MOOPPFLAGS) $(srcdir)/ostream.oo.c $(srcdir)/ostream.oo.h +ostream.c ostream.priv.h ostream.vt.h : ostream.h + @test -f $@ || { \ + trap 'rm -rf ostream.lock' 1 2 13 15; \ + if mkdir ostream.lock 2>/dev/null; then \ + echo "$(top_srcdir)/../build-aux/moopp $(MOOPPFLAGS) $(srcdir)/ostream.oo.c $(srcdir)/ostream.oo.h"; \ + $(top_srcdir)/../build-aux/moopp $(MOOPPFLAGS) $(srcdir)/ostream.oo.c $(srcdir)/ostream.oo.h; \ + result=$$?; rm -rf ostream.lock; exit $$result; \ + else \ + while test -d ostream.lock; do sleep 1; done; \ + test -f $(srcdir)/ostream.h; \ + fi; \ + } +BUILT_SOURCES += ostream.h ostream.c ostream.priv.h ostream.vt.h +MAINTAINERCLEANFILES += ostream.h ostream.c ostream.priv.h ostream.vt.h +EXTRA_DIST += ostream.h ostream.c ostream.priv.h ostream.vt.h + +EXTRA_DIST += ostream.oo.c ostream.oo.h + +EXTRA_libgettextlib_la_SOURCES += ostream.oo.c + +## end gnulib module ostream + +## begin gnulib module pathmax + + +EXTRA_DIST += pathmax.h + +## end gnulib module pathmax + +## begin gnulib module pipe-filter-ii + +libgettextlib_la_SOURCES += pipe-filter-ii.c pipe-filter-aux.c + +EXTRA_DIST += pipe-filter-aux.h pipe-filter.h + +## end gnulib module pipe-filter-ii + +## begin gnulib module pipe2 + +libgettextlib_la_SOURCES += pipe2.c + +## end gnulib module pipe2 + +## begin gnulib module pipe2-safer + +libgettextlib_la_SOURCES += pipe2-safer.c + +## end gnulib module pipe2-safer + +## begin gnulib module posix_spawn-internal + + +EXTRA_DIST += spawn_int.h spawni.c + +EXTRA_libgettextlib_la_SOURCES += spawni.c + +## end gnulib module posix_spawn-internal + +## begin gnulib module posix_spawn_file_actions_addclose + + +EXTRA_DIST += spawn_faction_addclose.c spawn_int.h + +EXTRA_libgettextlib_la_SOURCES += spawn_faction_addclose.c + +## end gnulib module posix_spawn_file_actions_addclose + +## begin gnulib module posix_spawn_file_actions_adddup2 + + +EXTRA_DIST += spawn_faction_adddup2.c spawn_int.h + +EXTRA_libgettextlib_la_SOURCES += spawn_faction_adddup2.c + +## end gnulib module posix_spawn_file_actions_adddup2 + +## begin gnulib module posix_spawn_file_actions_addopen + + +EXTRA_DIST += spawn_faction_addopen.c spawn_int.h + +EXTRA_libgettextlib_la_SOURCES += spawn_faction_addopen.c + +## end gnulib module posix_spawn_file_actions_addopen + +## begin gnulib module posix_spawn_file_actions_destroy + + +EXTRA_DIST += spawn_faction_destroy.c + +EXTRA_libgettextlib_la_SOURCES += spawn_faction_destroy.c + +## end gnulib module posix_spawn_file_actions_destroy + +## begin gnulib module posix_spawn_file_actions_init + + +EXTRA_DIST += spawn_faction_init.c spawn_int.h + +EXTRA_libgettextlib_la_SOURCES += spawn_faction_init.c + +## end gnulib module posix_spawn_file_actions_init + +## begin gnulib module posix_spawnattr_destroy + + +EXTRA_DIST += spawnattr_destroy.c + +EXTRA_libgettextlib_la_SOURCES += spawnattr_destroy.c + +## end gnulib module posix_spawnattr_destroy + +## begin gnulib module posix_spawnattr_init + + +EXTRA_DIST += spawnattr_init.c + +EXTRA_libgettextlib_la_SOURCES += spawnattr_init.c + +## end gnulib module posix_spawnattr_init + +## begin gnulib module posix_spawnattr_setflags + + +EXTRA_DIST += spawnattr_setflags.c + +EXTRA_libgettextlib_la_SOURCES += spawnattr_setflags.c + +## end gnulib module posix_spawnattr_setflags + +## begin gnulib module posix_spawnattr_setsigmask + + +EXTRA_DIST += spawnattr_setsigmask.c + +EXTRA_libgettextlib_la_SOURCES += spawnattr_setsigmask.c + +## end gnulib module posix_spawnattr_setsigmask + +## begin gnulib module posix_spawnp + + +EXTRA_DIST += spawnp.c + +EXTRA_libgettextlib_la_SOURCES += spawnp.c + +## end gnulib module posix_spawnp + +## begin gnulib module progname + +libgettextlib_la_SOURCES += progname.h progname.c + +## end gnulib module progname + +## begin gnulib module propername + +libgettextlib_la_SOURCES += propername.h propername.c + +## end gnulib module propername + +## begin gnulib module qacl + +libgettextlib_la_SOURCES += acl-errno-valid.c file-has-acl.c qcopy-acl.c qset-acl.c + +EXTRA_DIST += acl-internal.h acl.h acl_entries.c + +EXTRA_libgettextlib_la_SOURCES += acl_entries.c + +## end gnulib module qacl + +## begin gnulib module quote + + +EXTRA_DIST += quote.h + +## end gnulib module quote + +## begin gnulib module quotearg + +libgettextlib_la_SOURCES += quotearg.c + +EXTRA_DIST += quote.h quotearg.h + +## end gnulib module quotearg + +## begin gnulib module raise + + +EXTRA_DIST += raise.c + +EXTRA_libgettextlib_la_SOURCES += raise.c + +## end gnulib module raise + +## begin gnulib module rawmemchr + + +EXTRA_DIST += rawmemchr.c rawmemchr.valgrind + +EXTRA_libgettextlib_la_SOURCES += rawmemchr.c + +## end gnulib module rawmemchr + +## begin gnulib module read + + +EXTRA_DIST += read.c + +EXTRA_libgettextlib_la_SOURCES += read.c + +## end gnulib module read + +## begin gnulib module readdir + + +EXTRA_DIST += dirent-private.h readdir.c + +EXTRA_libgettextlib_la_SOURCES += readdir.c + +## end gnulib module readdir + +## begin gnulib module readlink + + +EXTRA_DIST += readlink.c + +EXTRA_libgettextlib_la_SOURCES += readlink.c + +## end gnulib module readlink + +## begin gnulib module realloc-posix + + +EXTRA_DIST += realloc.c + +EXTRA_libgettextlib_la_SOURCES += realloc.c + +## end gnulib module realloc-posix + +## begin gnulib module relocatable-prog + +DEFS += -DEXEEXT=\"@EXEEXT@\" +if RELOCATABLE_VIA_WRAPPER +uninstall-hook: uninstall-relocwrapper +uninstall-relocwrapper: + if test $(RELOCATABLE) = yes; then \ + case '$(EXEEXT)' in \ + .bin*) ;; \ + *) cd $(top_builddir) && \ + $(MAKE) $(AM_MAKEFLAGS) EXEEXT=.bin$(EXEEXT) \ + AM_MAKEFLAGS='$(AM_MAKEFLAGS) EXEEXT=.bin$(EXEEXT)' \ + uninstall ;; \ + esac; \ + fi +.PHONY: uninstall-relocwrapper +endif + +EXTRA_DIST += progreloc.c relocatable.c relocatable.h + +EXTRA_libgettextlib_la_SOURCES += progreloc.c relocatable.c + +EXTRA_DIST += $(top_srcdir)/../build-aux/config.libpath $(top_srcdir)/../build-aux/reloc-ldflags + +## end gnulib module relocatable-prog + +## begin gnulib module relocatable-prog-wrapper + + +EXTRA_DIST += allocator.c allocator.h areadlink.c areadlink.h c-ctype.c c-ctype.h canonicalize-lgpl.c careadlinkat.c careadlinkat.h malloca.c malloca.h progname.c progname.h progreloc.c readlink.c relocatable.c relocatable.h relocwrapper.c setenv.c + +EXTRA_DIST += $(top_srcdir)/../build-aux/install-reloc + +## end gnulib module relocatable-prog-wrapper + +## begin gnulib module relocatable-script + + +EXTRA_DIST += $(top_srcdir)/../build-aux/relocatable.sh.in + +## end gnulib module relocatable-script + +## begin gnulib module rmdir + + +EXTRA_DIST += rmdir.c + +EXTRA_libgettextlib_la_SOURCES += rmdir.c + +## end gnulib module rmdir + +## begin gnulib module safe-read + +libgettextlib_la_SOURCES += safe-read.c + +EXTRA_DIST += safe-read.h + +## end gnulib module safe-read + +## begin gnulib module safe-write + +libgettextlib_la_SOURCES += safe-write.c + +EXTRA_DIST += safe-read.c safe-write.h + +EXTRA_libgettextlib_la_SOURCES += safe-read.c + +## end gnulib module safe-write + +## begin gnulib module sched + +BUILT_SOURCES += $(SCHED_H) + +# We need the following in order to create a replacement for when +# the system doesn't have one. +if GL_GENERATE_SCHED_H +sched.h: sched.in.h $(top_builddir)/config.status + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''HAVE_SCHED_H''@|$(HAVE_SCHED_H)|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_SCHED_H''@|$(NEXT_SCHED_H)|g' \ + -e 's|@''HAVE_STRUCT_SCHED_PARAM''@|$(HAVE_STRUCT_SCHED_PARAM)|g' \ + < $(srcdir)/sched.in.h; \ + } > $@-t && \ + mv $@-t $@ +else +sched.h: $(top_builddir)/config.status + rm -f $@ +endif +MOSTLYCLEANFILES += sched.h sched.h-t + +EXTRA_DIST += sched.in.h + +## end gnulib module sched + +## begin gnulib module secure_getenv + + +EXTRA_DIST += secure_getenv.c + +EXTRA_libgettextlib_la_SOURCES += secure_getenv.c + +## end gnulib module secure_getenv + +## begin gnulib module setenv + + +EXTRA_DIST += setenv.c + +EXTRA_libgettextlib_la_SOURCES += setenv.c + +## end gnulib module setenv + +## begin gnulib module setlocale + + +EXTRA_DIST += setlocale.c + +EXTRA_libgettextlib_la_SOURCES += setlocale.c + +## end gnulib module setlocale + +## begin gnulib module sh-quote + +libgettextlib_la_SOURCES += sh-quote.h sh-quote.c + +## end gnulib module sh-quote + +## begin gnulib module sigaction + +libgettextlib_la_SOURCES += sig-handler.c + +EXTRA_DIST += sig-handler.h sigaction.c + +EXTRA_libgettextlib_la_SOURCES += sigaction.c + +## end gnulib module sigaction + +## begin gnulib module signal-h + +BUILT_SOURCES += signal.h + +# We need the following in order to create when the system +# doesn't have a complete one. +signal.h: signal.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_SIGNAL_H''@|$(NEXT_SIGNAL_H)|g' \ + -e 's|@''GNULIB_PTHREAD_SIGMASK''@|$(GNULIB_PTHREAD_SIGMASK)|g' \ + -e 's|@''GNULIB_RAISE''@|$(GNULIB_RAISE)|g' \ + -e 's/@''GNULIB_SIGNAL_H_SIGPIPE''@/$(GNULIB_SIGNAL_H_SIGPIPE)/g' \ + -e 's/@''GNULIB_SIGPROCMASK''@/$(GNULIB_SIGPROCMASK)/g' \ + -e 's/@''GNULIB_SIGACTION''@/$(GNULIB_SIGACTION)/g' \ + -e 's|@''HAVE_POSIX_SIGNALBLOCKING''@|$(HAVE_POSIX_SIGNALBLOCKING)|g' \ + -e 's|@''HAVE_PTHREAD_SIGMASK''@|$(HAVE_PTHREAD_SIGMASK)|g' \ + -e 's|@''HAVE_RAISE''@|$(HAVE_RAISE)|g' \ + -e 's|@''HAVE_SIGSET_T''@|$(HAVE_SIGSET_T)|g' \ + -e 's|@''HAVE_SIGINFO_T''@|$(HAVE_SIGINFO_T)|g' \ + -e 's|@''HAVE_SIGACTION''@|$(HAVE_SIGACTION)|g' \ + -e 's|@''HAVE_STRUCT_SIGACTION_SA_SIGACTION''@|$(HAVE_STRUCT_SIGACTION_SA_SIGACTION)|g' \ + -e 's|@''HAVE_TYPE_VOLATILE_SIG_ATOMIC_T''@|$(HAVE_TYPE_VOLATILE_SIG_ATOMIC_T)|g' \ + -e 's|@''HAVE_SIGHANDLER_T''@|$(HAVE_SIGHANDLER_T)|g' \ + -e 's|@''REPLACE_PTHREAD_SIGMASK''@|$(REPLACE_PTHREAD_SIGMASK)|g' \ + -e 's|@''REPLACE_RAISE''@|$(REPLACE_RAISE)|g' \ + -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ + < $(srcdir)/signal.in.h; \ + } > $@-t && \ + mv $@-t $@ +MOSTLYCLEANFILES += signal.h signal.h-t + +EXTRA_DIST += signal.in.h + +## end gnulib module signal-h + +## begin gnulib module sigpipe + + +EXTRA_DIST += stdio-write.c + +EXTRA_libgettextlib_la_SOURCES += stdio-write.c + +## end gnulib module sigpipe + +## begin gnulib module sigprocmask + + +EXTRA_DIST += sigprocmask.c + +EXTRA_libgettextlib_la_SOURCES += sigprocmask.c + +## end gnulib module sigprocmask + +## begin gnulib module size_max + +libgettextlib_la_SOURCES += size_max.h + +## end gnulib module size_max + +## begin gnulib module snippet/_Noreturn + +# Because this Makefile snippet defines a variable used by other +# gnulib Makefile snippets, it must be present in all Makefile.am that +# need it. This is ensured by the applicability 'all' defined above. + +_NORETURN_H=$(top_srcdir)/../build-aux/snippet/_Noreturn.h + +EXTRA_DIST += $(top_srcdir)/../build-aux/snippet/_Noreturn.h + +## end gnulib module snippet/_Noreturn + +## begin gnulib module snippet/arg-nonnull + +# The BUILT_SOURCES created by this Makefile snippet are not used via #include +# statements but through direct file reference. Therefore this snippet must be +# present in all Makefile.am that need it. This is ensured by the applicability +# 'all' defined above. + +BUILT_SOURCES += arg-nonnull.h +# The arg-nonnull.h that gets inserted into generated .h files is the same as +# build-aux/snippet/arg-nonnull.h, except that it has the copyright header cut +# off. +arg-nonnull.h: $(top_srcdir)/../build-aux/snippet/arg-nonnull.h + $(AM_V_GEN)rm -f $@-t $@ && \ + sed -n -e '/GL_ARG_NONNULL/,$$p' \ + < $(top_srcdir)/../build-aux/snippet/arg-nonnull.h \ + > $@-t && \ + mv $@-t $@ +MOSTLYCLEANFILES += arg-nonnull.h arg-nonnull.h-t + +ARG_NONNULL_H=arg-nonnull.h + +EXTRA_DIST += $(top_srcdir)/../build-aux/snippet/arg-nonnull.h + +## end gnulib module snippet/arg-nonnull + +## begin gnulib module snippet/c++defs + +# The BUILT_SOURCES created by this Makefile snippet are not used via #include +# statements but through direct file reference. Therefore this snippet must be +# present in all Makefile.am that need it. This is ensured by the applicability +# 'all' defined above. + +BUILT_SOURCES += c++defs.h +# The c++defs.h that gets inserted into generated .h files is the same as +# build-aux/snippet/c++defs.h, except that it has the copyright header cut off. +c++defs.h: $(top_srcdir)/../build-aux/snippet/c++defs.h + $(AM_V_GEN)rm -f $@-t $@ && \ + sed -n -e '/_GL_CXXDEFS/,$$p' \ + < $(top_srcdir)/../build-aux/snippet/c++defs.h \ + > $@-t && \ + mv $@-t $@ +MOSTLYCLEANFILES += c++defs.h c++defs.h-t + +CXXDEFS_H=c++defs.h + +EXTRA_DIST += $(top_srcdir)/../build-aux/snippet/c++defs.h + +## end gnulib module snippet/c++defs + +## begin gnulib module snippet/unused-parameter + +# The BUILT_SOURCES created by this Makefile snippet are not used via #include +# statements but through direct file reference. Therefore this snippet must be +# present in all Makefile.am that need it. This is ensured by the applicability +# 'all' defined above. + +BUILT_SOURCES += unused-parameter.h +# The unused-parameter.h that gets inserted into generated .h files is the same +# as build-aux/snippet/unused-parameter.h, except that it has the copyright +# header cut off. +unused-parameter.h: $(top_srcdir)/../build-aux/snippet/unused-parameter.h + $(AM_V_GEN)rm -f $@-t $@ && \ + sed -n -e '/GL_UNUSED_PARAMETER/,$$p' \ + < $(top_srcdir)/../build-aux/snippet/unused-parameter.h \ + > $@-t && \ + mv $@-t $@ +MOSTLYCLEANFILES += unused-parameter.h unused-parameter.h-t + +UNUSED_PARAMETER_H=unused-parameter.h + +EXTRA_DIST += $(top_srcdir)/../build-aux/snippet/unused-parameter.h + +## end gnulib module snippet/unused-parameter + +## begin gnulib module snippet/warn-on-use + +BUILT_SOURCES += warn-on-use.h +# The warn-on-use.h that gets inserted into generated .h files is the same as +# build-aux/snippet/warn-on-use.h, except that it has the copyright header cut +# off. +warn-on-use.h: $(top_srcdir)/../build-aux/snippet/warn-on-use.h + $(AM_V_GEN)rm -f $@-t $@ && \ + sed -n -e '/^.ifndef/,$$p' \ + < $(top_srcdir)/../build-aux/snippet/warn-on-use.h \ + > $@-t && \ + mv $@-t $@ +MOSTLYCLEANFILES += warn-on-use.h warn-on-use.h-t + +WARN_ON_USE_H=warn-on-use.h + +EXTRA_DIST += $(top_srcdir)/../build-aux/snippet/warn-on-use.h + +## end gnulib module snippet/warn-on-use + +## begin gnulib module snprintf + + +EXTRA_DIST += snprintf.c + +EXTRA_libgettextlib_la_SOURCES += snprintf.c + +## end gnulib module snprintf + +## begin gnulib module spawn + +BUILT_SOURCES += spawn.h + +# We need the following in order to create a replacement for when +# the system doesn't have one. +spawn.h: spawn.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''HAVE_SPAWN_H''@|$(HAVE_SPAWN_H)|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_SPAWN_H''@|$(NEXT_SPAWN_H)|g' \ + -e 's/@''GNULIB_POSIX_SPAWN''@/$(GNULIB_POSIX_SPAWN)/g' \ + -e 's/@''GNULIB_POSIX_SPAWNP''@/$(GNULIB_POSIX_SPAWNP)/g' \ + -e 's/@''GNULIB_POSIX_SPAWN_FILE_ACTIONS_INIT''@/$(GNULIB_POSIX_SPAWN_FILE_ACTIONS_INIT)/g' \ + -e 's/@''GNULIB_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSE''@/$(GNULIB_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSE)/g' \ + -e 's/@''GNULIB_POSIX_SPAWN_FILE_ACTIONS_ADDDUP2''@/$(GNULIB_POSIX_SPAWN_FILE_ACTIONS_ADDDUP2)/g' \ + -e 's/@''GNULIB_POSIX_SPAWN_FILE_ACTIONS_ADDOPEN''@/$(GNULIB_POSIX_SPAWN_FILE_ACTIONS_ADDOPEN)/g' \ + -e 's/@''GNULIB_POSIX_SPAWN_FILE_ACTIONS_DESTROY''@/$(GNULIB_POSIX_SPAWN_FILE_ACTIONS_DESTROY)/g' \ + -e 's/@''GNULIB_POSIX_SPAWNATTR_INIT''@/$(GNULIB_POSIX_SPAWNATTR_INIT)/g' \ + -e 's/@''GNULIB_POSIX_SPAWNATTR_GETFLAGS''@/$(GNULIB_POSIX_SPAWNATTR_GETFLAGS)/g' \ + -e 's/@''GNULIB_POSIX_SPAWNATTR_SETFLAGS''@/$(GNULIB_POSIX_SPAWNATTR_SETFLAGS)/g' \ + -e 's/@''GNULIB_POSIX_SPAWNATTR_GETPGROUP''@/$(GNULIB_POSIX_SPAWNATTR_GETPGROUP)/g' \ + -e 's/@''GNULIB_POSIX_SPAWNATTR_SETPGROUP''@/$(GNULIB_POSIX_SPAWNATTR_SETPGROUP)/g' \ + -e 's/@''GNULIB_POSIX_SPAWNATTR_GETSCHEDPARAM''@/$(GNULIB_POSIX_SPAWNATTR_GETSCHEDPARAM)/g' \ + -e 's/@''GNULIB_POSIX_SPAWNATTR_SETSCHEDPARAM''@/$(GNULIB_POSIX_SPAWNATTR_SETSCHEDPARAM)/g' \ + -e 's/@''GNULIB_POSIX_SPAWNATTR_GETSCHEDPOLICY''@/$(GNULIB_POSIX_SPAWNATTR_GETSCHEDPOLICY)/g' \ + -e 's/@''GNULIB_POSIX_SPAWNATTR_SETSCHEDPOLICY''@/$(GNULIB_POSIX_SPAWNATTR_SETSCHEDPOLICY)/g' \ + -e 's/@''GNULIB_POSIX_SPAWNATTR_GETSIGDEFAULT''@/$(GNULIB_POSIX_SPAWNATTR_GETSIGDEFAULT)/g' \ + -e 's/@''GNULIB_POSIX_SPAWNATTR_SETSIGDEFAULT''@/$(GNULIB_POSIX_SPAWNATTR_SETSIGDEFAULT)/g' \ + -e 's/@''GNULIB_POSIX_SPAWNATTR_GETSIGMASK''@/$(GNULIB_POSIX_SPAWNATTR_GETSIGMASK)/g' \ + -e 's/@''GNULIB_POSIX_SPAWNATTR_SETSIGMASK''@/$(GNULIB_POSIX_SPAWNATTR_SETSIGMASK)/g' \ + -e 's/@''GNULIB_POSIX_SPAWNATTR_DESTROY''@/$(GNULIB_POSIX_SPAWNATTR_DESTROY)/g' \ + -e 's|@''HAVE_POSIX_SPAWN''@|$(HAVE_POSIX_SPAWN)|g' \ + -e 's|@''HAVE_POSIX_SPAWNATTR_T''@|$(HAVE_POSIX_SPAWNATTR_T)|g' \ + -e 's|@''HAVE_POSIX_SPAWN_FILE_ACTIONS_T''@|$(HAVE_POSIX_SPAWN_FILE_ACTIONS_T)|g' \ + -e 's|@''REPLACE_POSIX_SPAWN''@|$(REPLACE_POSIX_SPAWN)|g' \ + -e 's|@''REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSE''@|$(REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSE)|g' \ + -e 's|@''REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDDUP2''@|$(REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDDUP2)|g' \ + -e 's|@''REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDOPEN''@|$(REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDOPEN)|g' \ + -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ + < $(srcdir)/spawn.in.h; \ + } > $@-t && \ + mv $@-t $@ +MOSTLYCLEANFILES += spawn.h spawn.h-t + +EXTRA_DIST += spawn.in.h + +## end gnulib module spawn + +## begin gnulib module spawn-pipe + +libgettextlib_la_SOURCES += spawn-pipe.h spawn-pipe.c w32spawn.h + +## end gnulib module spawn-pipe + +## begin gnulib module stat + + +EXTRA_DIST += stat.c + +EXTRA_libgettextlib_la_SOURCES += stat.c + +## end gnulib module stat + +## begin gnulib module stdarg + +BUILT_SOURCES += $(STDARG_H) + +# We need the following in order to create when the system +# doesn't have one that works with the given compiler. +if GL_GENERATE_STDARG_H +stdarg.h: stdarg.in.h $(top_builddir)/config.status + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_STDARG_H''@|$(NEXT_STDARG_H)|g' \ + < $(srcdir)/stdarg.in.h; \ + } > $@-t && \ + mv $@-t $@ +else +stdarg.h: $(top_builddir)/config.status + rm -f $@ +endif +MOSTLYCLEANFILES += stdarg.h stdarg.h-t + +EXTRA_DIST += stdarg.in.h + +## end gnulib module stdarg + +## begin gnulib module stdbool + +BUILT_SOURCES += $(STDBOOL_H) + +# We need the following in order to create when the system +# doesn't have one that works. +if GL_GENERATE_STDBOOL_H +stdbool.h: stdbool.in.h $(top_builddir)/config.status + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + sed -e 's/@''HAVE__BOOL''@/$(HAVE__BOOL)/g' < $(srcdir)/stdbool.in.h; \ + } > $@-t && \ + mv $@-t $@ +else +stdbool.h: $(top_builddir)/config.status + rm -f $@ +endif +MOSTLYCLEANFILES += stdbool.h stdbool.h-t + +EXTRA_DIST += stdbool.in.h + +## end gnulib module stdbool + +## begin gnulib module stddef + +BUILT_SOURCES += $(STDDEF_H) + +# We need the following in order to create when the system +# doesn't have one that works with the given compiler. +if GL_GENERATE_STDDEF_H +stddef.h: stddef.in.h $(top_builddir)/config.status + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_STDDEF_H''@|$(NEXT_STDDEF_H)|g' \ + -e 's|@''HAVE_WCHAR_T''@|$(HAVE_WCHAR_T)|g' \ + -e 's|@''REPLACE_NULL''@|$(REPLACE_NULL)|g' \ + < $(srcdir)/stddef.in.h; \ + } > $@-t && \ + mv $@-t $@ +else +stddef.h: $(top_builddir)/config.status + rm -f $@ +endif +MOSTLYCLEANFILES += stddef.h stddef.h-t + +EXTRA_DIST += stddef.in.h + +## end gnulib module stddef + +## begin gnulib module stdint + +BUILT_SOURCES += $(STDINT_H) + +# We need the following in order to create when the system +# doesn't have one that works with the given compiler. +if GL_GENERATE_STDINT_H +stdint.h: stdint.in.h $(top_builddir)/config.status + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's/@''HAVE_STDINT_H''@/$(HAVE_STDINT_H)/g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_STDINT_H''@|$(NEXT_STDINT_H)|g' \ + -e 's/@''HAVE_SYS_TYPES_H''@/$(HAVE_SYS_TYPES_H)/g' \ + -e 's/@''HAVE_INTTYPES_H''@/$(HAVE_INTTYPES_H)/g' \ + -e 's/@''HAVE_SYS_INTTYPES_H''@/$(HAVE_SYS_INTTYPES_H)/g' \ + -e 's/@''HAVE_SYS_BITYPES_H''@/$(HAVE_SYS_BITYPES_H)/g' \ + -e 's/@''HAVE_WCHAR_H''@/$(HAVE_WCHAR_H)/g' \ + -e 's/@''HAVE_LONG_LONG_INT''@/$(HAVE_LONG_LONG_INT)/g' \ + -e 's/@''HAVE_UNSIGNED_LONG_LONG_INT''@/$(HAVE_UNSIGNED_LONG_LONG_INT)/g' \ + -e 's/@''APPLE_UNIVERSAL_BUILD''@/$(APPLE_UNIVERSAL_BUILD)/g' \ + -e 's/@''BITSIZEOF_PTRDIFF_T''@/$(BITSIZEOF_PTRDIFF_T)/g' \ + -e 's/@''PTRDIFF_T_SUFFIX''@/$(PTRDIFF_T_SUFFIX)/g' \ + -e 's/@''BITSIZEOF_SIG_ATOMIC_T''@/$(BITSIZEOF_SIG_ATOMIC_T)/g' \ + -e 's/@''HAVE_SIGNED_SIG_ATOMIC_T''@/$(HAVE_SIGNED_SIG_ATOMIC_T)/g' \ + -e 's/@''SIG_ATOMIC_T_SUFFIX''@/$(SIG_ATOMIC_T_SUFFIX)/g' \ + -e 's/@''BITSIZEOF_SIZE_T''@/$(BITSIZEOF_SIZE_T)/g' \ + -e 's/@''SIZE_T_SUFFIX''@/$(SIZE_T_SUFFIX)/g' \ + -e 's/@''BITSIZEOF_WCHAR_T''@/$(BITSIZEOF_WCHAR_T)/g' \ + -e 's/@''HAVE_SIGNED_WCHAR_T''@/$(HAVE_SIGNED_WCHAR_T)/g' \ + -e 's/@''WCHAR_T_SUFFIX''@/$(WCHAR_T_SUFFIX)/g' \ + -e 's/@''BITSIZEOF_WINT_T''@/$(BITSIZEOF_WINT_T)/g' \ + -e 's/@''HAVE_SIGNED_WINT_T''@/$(HAVE_SIGNED_WINT_T)/g' \ + -e 's/@''WINT_T_SUFFIX''@/$(WINT_T_SUFFIX)/g' \ + < $(srcdir)/stdint.in.h; \ + } > $@-t && \ + mv $@-t $@ +else +stdint.h: $(top_builddir)/config.status + rm -f $@ +endif +MOSTLYCLEANFILES += stdint.h stdint.h-t + +EXTRA_DIST += stdint.in.h + +## end gnulib module stdint + +## begin gnulib module stdio + +BUILT_SOURCES += stdio.h + +# We need the following in order to create when the system +# doesn't have one that works with the given compiler. +stdio.h: stdio.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_STDIO_H''@|$(NEXT_STDIO_H)|g' \ + -e 's/@''GNULIB_DPRINTF''@/$(GNULIB_DPRINTF)/g' \ + -e 's/@''GNULIB_FCLOSE''@/$(GNULIB_FCLOSE)/g' \ + -e 's/@''GNULIB_FDOPEN''@/$(GNULIB_FDOPEN)/g' \ + -e 's/@''GNULIB_FFLUSH''@/$(GNULIB_FFLUSH)/g' \ + -e 's/@''GNULIB_FGETC''@/$(GNULIB_FGETC)/g' \ + -e 's/@''GNULIB_FGETS''@/$(GNULIB_FGETS)/g' \ + -e 's/@''GNULIB_FOPEN''@/$(GNULIB_FOPEN)/g' \ + -e 's/@''GNULIB_FPRINTF''@/$(GNULIB_FPRINTF)/g' \ + -e 's/@''GNULIB_FPRINTF_POSIX''@/$(GNULIB_FPRINTF_POSIX)/g' \ + -e 's/@''GNULIB_FPURGE''@/$(GNULIB_FPURGE)/g' \ + -e 's/@''GNULIB_FPUTC''@/$(GNULIB_FPUTC)/g' \ + -e 's/@''GNULIB_FPUTS''@/$(GNULIB_FPUTS)/g' \ + -e 's/@''GNULIB_FREAD''@/$(GNULIB_FREAD)/g' \ + -e 's/@''GNULIB_FREOPEN''@/$(GNULIB_FREOPEN)/g' \ + -e 's/@''GNULIB_FSCANF''@/$(GNULIB_FSCANF)/g' \ + -e 's/@''GNULIB_FSEEK''@/$(GNULIB_FSEEK)/g' \ + -e 's/@''GNULIB_FSEEKO''@/$(GNULIB_FSEEKO)/g' \ + -e 's/@''GNULIB_FTELL''@/$(GNULIB_FTELL)/g' \ + -e 's/@''GNULIB_FTELLO''@/$(GNULIB_FTELLO)/g' \ + -e 's/@''GNULIB_FWRITE''@/$(GNULIB_FWRITE)/g' \ + -e 's/@''GNULIB_GETC''@/$(GNULIB_GETC)/g' \ + -e 's/@''GNULIB_GETCHAR''@/$(GNULIB_GETCHAR)/g' \ + -e 's/@''GNULIB_GETDELIM''@/$(GNULIB_GETDELIM)/g' \ + -e 's/@''GNULIB_GETLINE''@/$(GNULIB_GETLINE)/g' \ + -e 's/@''GNULIB_OBSTACK_PRINTF''@/$(GNULIB_OBSTACK_PRINTF)/g' \ + -e 's/@''GNULIB_OBSTACK_PRINTF_POSIX''@/$(GNULIB_OBSTACK_PRINTF_POSIX)/g' \ + -e 's/@''GNULIB_PCLOSE''@/$(GNULIB_PCLOSE)/g' \ + -e 's/@''GNULIB_PERROR''@/$(GNULIB_PERROR)/g' \ + -e 's/@''GNULIB_POPEN''@/$(GNULIB_POPEN)/g' \ + -e 's/@''GNULIB_PRINTF''@/$(GNULIB_PRINTF)/g' \ + -e 's/@''GNULIB_PRINTF_POSIX''@/$(GNULIB_PRINTF_POSIX)/g' \ + -e 's/@''GNULIB_PUTC''@/$(GNULIB_PUTC)/g' \ + -e 's/@''GNULIB_PUTCHAR''@/$(GNULIB_PUTCHAR)/g' \ + -e 's/@''GNULIB_PUTS''@/$(GNULIB_PUTS)/g' \ + -e 's/@''GNULIB_REMOVE''@/$(GNULIB_REMOVE)/g' \ + -e 's/@''GNULIB_RENAME''@/$(GNULIB_RENAME)/g' \ + -e 's/@''GNULIB_RENAMEAT''@/$(GNULIB_RENAMEAT)/g' \ + -e 's/@''GNULIB_SCANF''@/$(GNULIB_SCANF)/g' \ + -e 's/@''GNULIB_SNPRINTF''@/$(GNULIB_SNPRINTF)/g' \ + -e 's/@''GNULIB_SPRINTF_POSIX''@/$(GNULIB_SPRINTF_POSIX)/g' \ + -e 's/@''GNULIB_STDIO_H_NONBLOCKING''@/$(GNULIB_STDIO_H_NONBLOCKING)/g' \ + -e 's/@''GNULIB_STDIO_H_SIGPIPE''@/$(GNULIB_STDIO_H_SIGPIPE)/g' \ + -e 's/@''GNULIB_TMPFILE''@/$(GNULIB_TMPFILE)/g' \ + -e 's/@''GNULIB_VASPRINTF''@/$(GNULIB_VASPRINTF)/g' \ + -e 's/@''GNULIB_VDPRINTF''@/$(GNULIB_VDPRINTF)/g' \ + -e 's/@''GNULIB_VFPRINTF''@/$(GNULIB_VFPRINTF)/g' \ + -e 's/@''GNULIB_VFPRINTF_POSIX''@/$(GNULIB_VFPRINTF_POSIX)/g' \ + -e 's/@''GNULIB_VFSCANF''@/$(GNULIB_VFSCANF)/g' \ + -e 's/@''GNULIB_VSCANF''@/$(GNULIB_VSCANF)/g' \ + -e 's/@''GNULIB_VPRINTF''@/$(GNULIB_VPRINTF)/g' \ + -e 's/@''GNULIB_VPRINTF_POSIX''@/$(GNULIB_VPRINTF_POSIX)/g' \ + -e 's/@''GNULIB_VSNPRINTF''@/$(GNULIB_VSNPRINTF)/g' \ + -e 's/@''GNULIB_VSPRINTF_POSIX''@/$(GNULIB_VSPRINTF_POSIX)/g' \ + < $(srcdir)/stdio.in.h | \ + sed -e 's|@''HAVE_DECL_FPURGE''@|$(HAVE_DECL_FPURGE)|g' \ + -e 's|@''HAVE_DECL_FSEEKO''@|$(HAVE_DECL_FSEEKO)|g' \ + -e 's|@''HAVE_DECL_FTELLO''@|$(HAVE_DECL_FTELLO)|g' \ + -e 's|@''HAVE_DECL_GETDELIM''@|$(HAVE_DECL_GETDELIM)|g' \ + -e 's|@''HAVE_DECL_GETLINE''@|$(HAVE_DECL_GETLINE)|g' \ + -e 's|@''HAVE_DECL_OBSTACK_PRINTF''@|$(HAVE_DECL_OBSTACK_PRINTF)|g' \ + -e 's|@''HAVE_DECL_SNPRINTF''@|$(HAVE_DECL_SNPRINTF)|g' \ + -e 's|@''HAVE_DECL_VSNPRINTF''@|$(HAVE_DECL_VSNPRINTF)|g' \ + -e 's|@''HAVE_DPRINTF''@|$(HAVE_DPRINTF)|g' \ + -e 's|@''HAVE_FSEEKO''@|$(HAVE_FSEEKO)|g' \ + -e 's|@''HAVE_FTELLO''@|$(HAVE_FTELLO)|g' \ + -e 's|@''HAVE_PCLOSE''@|$(HAVE_PCLOSE)|g' \ + -e 's|@''HAVE_POPEN''@|$(HAVE_POPEN)|g' \ + -e 's|@''HAVE_RENAMEAT''@|$(HAVE_RENAMEAT)|g' \ + -e 's|@''HAVE_VASPRINTF''@|$(HAVE_VASPRINTF)|g' \ + -e 's|@''HAVE_VDPRINTF''@|$(HAVE_VDPRINTF)|g' \ + -e 's|@''REPLACE_DPRINTF''@|$(REPLACE_DPRINTF)|g' \ + -e 's|@''REPLACE_FCLOSE''@|$(REPLACE_FCLOSE)|g' \ + -e 's|@''REPLACE_FDOPEN''@|$(REPLACE_FDOPEN)|g' \ + -e 's|@''REPLACE_FFLUSH''@|$(REPLACE_FFLUSH)|g' \ + -e 's|@''REPLACE_FOPEN''@|$(REPLACE_FOPEN)|g' \ + -e 's|@''REPLACE_FPRINTF''@|$(REPLACE_FPRINTF)|g' \ + -e 's|@''REPLACE_FPURGE''@|$(REPLACE_FPURGE)|g' \ + -e 's|@''REPLACE_FREOPEN''@|$(REPLACE_FREOPEN)|g' \ + -e 's|@''REPLACE_FSEEK''@|$(REPLACE_FSEEK)|g' \ + -e 's|@''REPLACE_FSEEKO''@|$(REPLACE_FSEEKO)|g' \ + -e 's|@''REPLACE_FTELL''@|$(REPLACE_FTELL)|g' \ + -e 's|@''REPLACE_FTELLO''@|$(REPLACE_FTELLO)|g' \ + -e 's|@''REPLACE_GETDELIM''@|$(REPLACE_GETDELIM)|g' \ + -e 's|@''REPLACE_GETLINE''@|$(REPLACE_GETLINE)|g' \ + -e 's|@''REPLACE_OBSTACK_PRINTF''@|$(REPLACE_OBSTACK_PRINTF)|g' \ + -e 's|@''REPLACE_PERROR''@|$(REPLACE_PERROR)|g' \ + -e 's|@''REPLACE_POPEN''@|$(REPLACE_POPEN)|g' \ + -e 's|@''REPLACE_PRINTF''@|$(REPLACE_PRINTF)|g' \ + -e 's|@''REPLACE_REMOVE''@|$(REPLACE_REMOVE)|g' \ + -e 's|@''REPLACE_RENAME''@|$(REPLACE_RENAME)|g' \ + -e 's|@''REPLACE_RENAMEAT''@|$(REPLACE_RENAMEAT)|g' \ + -e 's|@''REPLACE_SNPRINTF''@|$(REPLACE_SNPRINTF)|g' \ + -e 's|@''REPLACE_SPRINTF''@|$(REPLACE_SPRINTF)|g' \ + -e 's|@''REPLACE_STDIO_READ_FUNCS''@|$(REPLACE_STDIO_READ_FUNCS)|g' \ + -e 's|@''REPLACE_STDIO_WRITE_FUNCS''@|$(REPLACE_STDIO_WRITE_FUNCS)|g' \ + -e 's|@''REPLACE_TMPFILE''@|$(REPLACE_TMPFILE)|g' \ + -e 's|@''REPLACE_VASPRINTF''@|$(REPLACE_VASPRINTF)|g' \ + -e 's|@''REPLACE_VDPRINTF''@|$(REPLACE_VDPRINTF)|g' \ + -e 's|@''REPLACE_VFPRINTF''@|$(REPLACE_VFPRINTF)|g' \ + -e 's|@''REPLACE_VPRINTF''@|$(REPLACE_VPRINTF)|g' \ + -e 's|@''REPLACE_VSNPRINTF''@|$(REPLACE_VSNPRINTF)|g' \ + -e 's|@''REPLACE_VSPRINTF''@|$(REPLACE_VSPRINTF)|g' \ + -e 's|@''ASM_SYMBOL_PREFIX''@|$(ASM_SYMBOL_PREFIX)|g' \ + -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)'; \ + } > $@-t && \ + mv $@-t $@ +MOSTLYCLEANFILES += stdio.h stdio.h-t + +EXTRA_DIST += stdio.in.h + +## end gnulib module stdio + +## begin gnulib module stdlib + +BUILT_SOURCES += stdlib.h + +# We need the following in order to create when the system +# doesn't have one that works with the given compiler. +stdlib.h: stdlib.in.h $(top_builddir)/config.status $(CXXDEFS_H) \ + $(_NORETURN_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_STDLIB_H''@|$(NEXT_STDLIB_H)|g' \ + -e 's/@''GNULIB__EXIT''@/$(GNULIB__EXIT)/g' \ + -e 's/@''GNULIB_ATOLL''@/$(GNULIB_ATOLL)/g' \ + -e 's/@''GNULIB_CALLOC_POSIX''@/$(GNULIB_CALLOC_POSIX)/g' \ + -e 's/@''GNULIB_CANONICALIZE_FILE_NAME''@/$(GNULIB_CANONICALIZE_FILE_NAME)/g' \ + -e 's/@''GNULIB_GETLOADAVG''@/$(GNULIB_GETLOADAVG)/g' \ + -e 's/@''GNULIB_GETSUBOPT''@/$(GNULIB_GETSUBOPT)/g' \ + -e 's/@''GNULIB_GRANTPT''@/$(GNULIB_GRANTPT)/g' \ + -e 's/@''GNULIB_MALLOC_POSIX''@/$(GNULIB_MALLOC_POSIX)/g' \ + -e 's/@''GNULIB_MBTOWC''@/$(GNULIB_MBTOWC)/g' \ + -e 's/@''GNULIB_MKDTEMP''@/$(GNULIB_MKDTEMP)/g' \ + -e 's/@''GNULIB_MKOSTEMP''@/$(GNULIB_MKOSTEMP)/g' \ + -e 's/@''GNULIB_MKOSTEMPS''@/$(GNULIB_MKOSTEMPS)/g' \ + -e 's/@''GNULIB_MKSTEMP''@/$(GNULIB_MKSTEMP)/g' \ + -e 's/@''GNULIB_MKSTEMPS''@/$(GNULIB_MKSTEMPS)/g' \ + -e 's/@''GNULIB_POSIX_OPENPT''@/$(GNULIB_POSIX_OPENPT)/g' \ + -e 's/@''GNULIB_PTSNAME''@/$(GNULIB_PTSNAME)/g' \ + -e 's/@''GNULIB_PTSNAME_R''@/$(GNULIB_PTSNAME_R)/g' \ + -e 's/@''GNULIB_PUTENV''@/$(GNULIB_PUTENV)/g' \ + -e 's/@''GNULIB_QSORT_R''@/$(GNULIB_QSORT_R)/g' \ + -e 's/@''GNULIB_RANDOM''@/$(GNULIB_RANDOM)/g' \ + -e 's/@''GNULIB_RANDOM_R''@/$(GNULIB_RANDOM_R)/g' \ + -e 's/@''GNULIB_REALLOC_POSIX''@/$(GNULIB_REALLOC_POSIX)/g' \ + -e 's/@''GNULIB_REALPATH''@/$(GNULIB_REALPATH)/g' \ + -e 's/@''GNULIB_RPMATCH''@/$(GNULIB_RPMATCH)/g' \ + -e 's/@''GNULIB_SECURE_GETENV''@/$(GNULIB_SECURE_GETENV)/g' \ + -e 's/@''GNULIB_SETENV''@/$(GNULIB_SETENV)/g' \ + -e 's/@''GNULIB_STRTOD''@/$(GNULIB_STRTOD)/g' \ + -e 's/@''GNULIB_STRTOLL''@/$(GNULIB_STRTOLL)/g' \ + -e 's/@''GNULIB_STRTOULL''@/$(GNULIB_STRTOULL)/g' \ + -e 's/@''GNULIB_SYSTEM_POSIX''@/$(GNULIB_SYSTEM_POSIX)/g' \ + -e 's/@''GNULIB_UNLOCKPT''@/$(GNULIB_UNLOCKPT)/g' \ + -e 's/@''GNULIB_UNSETENV''@/$(GNULIB_UNSETENV)/g' \ + -e 's/@''GNULIB_WCTOMB''@/$(GNULIB_WCTOMB)/g' \ + < $(srcdir)/stdlib.in.h | \ + sed -e 's|@''HAVE__EXIT''@|$(HAVE__EXIT)|g' \ + -e 's|@''HAVE_ATOLL''@|$(HAVE_ATOLL)|g' \ + -e 's|@''HAVE_CANONICALIZE_FILE_NAME''@|$(HAVE_CANONICALIZE_FILE_NAME)|g' \ + -e 's|@''HAVE_DECL_GETLOADAVG''@|$(HAVE_DECL_GETLOADAVG)|g' \ + -e 's|@''HAVE_GETSUBOPT''@|$(HAVE_GETSUBOPT)|g' \ + -e 's|@''HAVE_GRANTPT''@|$(HAVE_GRANTPT)|g' \ + -e 's|@''HAVE_MKDTEMP''@|$(HAVE_MKDTEMP)|g' \ + -e 's|@''HAVE_MKOSTEMP''@|$(HAVE_MKOSTEMP)|g' \ + -e 's|@''HAVE_MKOSTEMPS''@|$(HAVE_MKOSTEMPS)|g' \ + -e 's|@''HAVE_MKSTEMP''@|$(HAVE_MKSTEMP)|g' \ + -e 's|@''HAVE_MKSTEMPS''@|$(HAVE_MKSTEMPS)|g' \ + -e 's|@''HAVE_POSIX_OPENPT''@|$(HAVE_POSIX_OPENPT)|g' \ + -e 's|@''HAVE_PTSNAME''@|$(HAVE_PTSNAME)|g' \ + -e 's|@''HAVE_PTSNAME_R''@|$(HAVE_PTSNAME_R)|g' \ + -e 's|@''HAVE_RANDOM''@|$(HAVE_RANDOM)|g' \ + -e 's|@''HAVE_RANDOM_H''@|$(HAVE_RANDOM_H)|g' \ + -e 's|@''HAVE_RANDOM_R''@|$(HAVE_RANDOM_R)|g' \ + -e 's|@''HAVE_REALPATH''@|$(HAVE_REALPATH)|g' \ + -e 's|@''HAVE_RPMATCH''@|$(HAVE_RPMATCH)|g' \ + -e 's|@''HAVE_SECURE_GETENV''@|$(HAVE_SECURE_GETENV)|g' \ + -e 's|@''HAVE_DECL_SETENV''@|$(HAVE_DECL_SETENV)|g' \ + -e 's|@''HAVE_STRTOD''@|$(HAVE_STRTOD)|g' \ + -e 's|@''HAVE_STRTOLL''@|$(HAVE_STRTOLL)|g' \ + -e 's|@''HAVE_STRTOULL''@|$(HAVE_STRTOULL)|g' \ + -e 's|@''HAVE_STRUCT_RANDOM_DATA''@|$(HAVE_STRUCT_RANDOM_DATA)|g' \ + -e 's|@''HAVE_SYS_LOADAVG_H''@|$(HAVE_SYS_LOADAVG_H)|g' \ + -e 's|@''HAVE_UNLOCKPT''@|$(HAVE_UNLOCKPT)|g' \ + -e 's|@''HAVE_DECL_UNSETENV''@|$(HAVE_DECL_UNSETENV)|g' \ + -e 's|@''REPLACE_CALLOC''@|$(REPLACE_CALLOC)|g' \ + -e 's|@''REPLACE_CANONICALIZE_FILE_NAME''@|$(REPLACE_CANONICALIZE_FILE_NAME)|g' \ + -e 's|@''REPLACE_MALLOC''@|$(REPLACE_MALLOC)|g' \ + -e 's|@''REPLACE_MBTOWC''@|$(REPLACE_MBTOWC)|g' \ + -e 's|@''REPLACE_MKSTEMP''@|$(REPLACE_MKSTEMP)|g' \ + -e 's|@''REPLACE_PTSNAME''@|$(REPLACE_PTSNAME)|g' \ + -e 's|@''REPLACE_PTSNAME_R''@|$(REPLACE_PTSNAME_R)|g' \ + -e 's|@''REPLACE_PUTENV''@|$(REPLACE_PUTENV)|g' \ + -e 's|@''REPLACE_QSORT_R''@|$(REPLACE_QSORT_R)|g' \ + -e 's|@''REPLACE_RANDOM_R''@|$(REPLACE_RANDOM_R)|g' \ + -e 's|@''REPLACE_REALLOC''@|$(REPLACE_REALLOC)|g' \ + -e 's|@''REPLACE_REALPATH''@|$(REPLACE_REALPATH)|g' \ + -e 's|@''REPLACE_SETENV''@|$(REPLACE_SETENV)|g' \ + -e 's|@''REPLACE_STRTOD''@|$(REPLACE_STRTOD)|g' \ + -e 's|@''REPLACE_UNSETENV''@|$(REPLACE_UNSETENV)|g' \ + -e 's|@''REPLACE_WCTOMB''@|$(REPLACE_WCTOMB)|g' \ + -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _Noreturn/r $(_NORETURN_H)' \ + -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)'; \ + } > $@-t && \ + mv $@-t $@ +MOSTLYCLEANFILES += stdlib.h stdlib.h-t + +EXTRA_DIST += stdlib.in.h + +## end gnulib module stdlib + +## begin gnulib module stpcpy + + +EXTRA_DIST += stpcpy.c + +EXTRA_libgettextlib_la_SOURCES += stpcpy.c + +## end gnulib module stpcpy + +## begin gnulib module stpncpy + + +EXTRA_DIST += stpncpy.c + +EXTRA_libgettextlib_la_SOURCES += stpncpy.c + +## end gnulib module stpncpy + +## begin gnulib module strchrnul + + +EXTRA_DIST += strchrnul.c strchrnul.valgrind + +EXTRA_libgettextlib_la_SOURCES += strchrnul.c + +## end gnulib module strchrnul + +## begin gnulib module strcspn + + +EXTRA_DIST += strcspn.c + +EXTRA_libgettextlib_la_SOURCES += strcspn.c + +## end gnulib module strcspn + +## begin gnulib module streq + + +EXTRA_DIST += streq.h + +## end gnulib module streq + +## begin gnulib module strerror + + +EXTRA_DIST += strerror.c + +EXTRA_libgettextlib_la_SOURCES += strerror.c + +## end gnulib module strerror + +## begin gnulib module strerror-override + + +EXTRA_DIST += strerror-override.c strerror-override.h + +EXTRA_libgettextlib_la_SOURCES += strerror-override.c + +## end gnulib module strerror-override + +## begin gnulib module striconv + +libgettextlib_la_SOURCES += striconv.h striconv.c +if GL_COND_LIBTOOL +libgettextlib_la_LDFLAGS += $(LTLIBICONV) +endif + +## end gnulib module striconv + +## begin gnulib module striconveh + +libgettextlib_la_SOURCES += striconveh.h striconveh.c +if GL_COND_LIBTOOL +libgettextlib_la_LDFLAGS += $(LTLIBICONV) +endif + +EXTRA_DIST += iconveh.h + +## end gnulib module striconveh + +## begin gnulib module striconveha + +libgettextlib_la_SOURCES += striconveha.h striconveha.c + +## end gnulib module striconveha + +## begin gnulib module string + +BUILT_SOURCES += string.h + +# We need the following in order to create when the system +# doesn't have one that works with the given compiler. +string.h: string.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_STRING_H''@|$(NEXT_STRING_H)|g' \ + -e 's/@''GNULIB_FFSL''@/$(GNULIB_FFSL)/g' \ + -e 's/@''GNULIB_FFSLL''@/$(GNULIB_FFSLL)/g' \ + -e 's/@''GNULIB_MBSLEN''@/$(GNULIB_MBSLEN)/g' \ + -e 's/@''GNULIB_MBSNLEN''@/$(GNULIB_MBSNLEN)/g' \ + -e 's/@''GNULIB_MBSCHR''@/$(GNULIB_MBSCHR)/g' \ + -e 's/@''GNULIB_MBSRCHR''@/$(GNULIB_MBSRCHR)/g' \ + -e 's/@''GNULIB_MBSSTR''@/$(GNULIB_MBSSTR)/g' \ + -e 's/@''GNULIB_MBSCASECMP''@/$(GNULIB_MBSCASECMP)/g' \ + -e 's/@''GNULIB_MBSNCASECMP''@/$(GNULIB_MBSNCASECMP)/g' \ + -e 's/@''GNULIB_MBSPCASECMP''@/$(GNULIB_MBSPCASECMP)/g' \ + -e 's/@''GNULIB_MBSCASESTR''@/$(GNULIB_MBSCASESTR)/g' \ + -e 's/@''GNULIB_MBSCSPN''@/$(GNULIB_MBSCSPN)/g' \ + -e 's/@''GNULIB_MBSPBRK''@/$(GNULIB_MBSPBRK)/g' \ + -e 's/@''GNULIB_MBSSPN''@/$(GNULIB_MBSSPN)/g' \ + -e 's/@''GNULIB_MBSSEP''@/$(GNULIB_MBSSEP)/g' \ + -e 's/@''GNULIB_MBSTOK_R''@/$(GNULIB_MBSTOK_R)/g' \ + -e 's/@''GNULIB_MEMCHR''@/$(GNULIB_MEMCHR)/g' \ + -e 's/@''GNULIB_MEMMEM''@/$(GNULIB_MEMMEM)/g' \ + -e 's/@''GNULIB_MEMPCPY''@/$(GNULIB_MEMPCPY)/g' \ + -e 's/@''GNULIB_MEMRCHR''@/$(GNULIB_MEMRCHR)/g' \ + -e 's/@''GNULIB_RAWMEMCHR''@/$(GNULIB_RAWMEMCHR)/g' \ + -e 's/@''GNULIB_STPCPY''@/$(GNULIB_STPCPY)/g' \ + -e 's/@''GNULIB_STPNCPY''@/$(GNULIB_STPNCPY)/g' \ + -e 's/@''GNULIB_STRCHRNUL''@/$(GNULIB_STRCHRNUL)/g' \ + -e 's/@''GNULIB_STRDUP''@/$(GNULIB_STRDUP)/g' \ + -e 's/@''GNULIB_STRNCAT''@/$(GNULIB_STRNCAT)/g' \ + -e 's/@''GNULIB_STRNDUP''@/$(GNULIB_STRNDUP)/g' \ + -e 's/@''GNULIB_STRNLEN''@/$(GNULIB_STRNLEN)/g' \ + -e 's/@''GNULIB_STRPBRK''@/$(GNULIB_STRPBRK)/g' \ + -e 's/@''GNULIB_STRSEP''@/$(GNULIB_STRSEP)/g' \ + -e 's/@''GNULIB_STRSTR''@/$(GNULIB_STRSTR)/g' \ + -e 's/@''GNULIB_STRCASESTR''@/$(GNULIB_STRCASESTR)/g' \ + -e 's/@''GNULIB_STRTOK_R''@/$(GNULIB_STRTOK_R)/g' \ + -e 's/@''GNULIB_STRERROR''@/$(GNULIB_STRERROR)/g' \ + -e 's/@''GNULIB_STRERROR_R''@/$(GNULIB_STRERROR_R)/g' \ + -e 's/@''GNULIB_STRSIGNAL''@/$(GNULIB_STRSIGNAL)/g' \ + -e 's/@''GNULIB_STRVERSCMP''@/$(GNULIB_STRVERSCMP)/g' \ + < $(srcdir)/string.in.h | \ + sed -e 's|@''HAVE_FFSL''@|$(HAVE_FFSL)|g' \ + -e 's|@''HAVE_FFSLL''@|$(HAVE_FFSLL)|g' \ + -e 's|@''HAVE_MBSLEN''@|$(HAVE_MBSLEN)|g' \ + -e 's|@''HAVE_MEMCHR''@|$(HAVE_MEMCHR)|g' \ + -e 's|@''HAVE_DECL_MEMMEM''@|$(HAVE_DECL_MEMMEM)|g' \ + -e 's|@''HAVE_MEMPCPY''@|$(HAVE_MEMPCPY)|g' \ + -e 's|@''HAVE_DECL_MEMRCHR''@|$(HAVE_DECL_MEMRCHR)|g' \ + -e 's|@''HAVE_RAWMEMCHR''@|$(HAVE_RAWMEMCHR)|g' \ + -e 's|@''HAVE_STPCPY''@|$(HAVE_STPCPY)|g' \ + -e 's|@''HAVE_STPNCPY''@|$(HAVE_STPNCPY)|g' \ + -e 's|@''HAVE_STRCHRNUL''@|$(HAVE_STRCHRNUL)|g' \ + -e 's|@''HAVE_DECL_STRDUP''@|$(HAVE_DECL_STRDUP)|g' \ + -e 's|@''HAVE_DECL_STRNDUP''@|$(HAVE_DECL_STRNDUP)|g' \ + -e 's|@''HAVE_DECL_STRNLEN''@|$(HAVE_DECL_STRNLEN)|g' \ + -e 's|@''HAVE_STRPBRK''@|$(HAVE_STRPBRK)|g' \ + -e 's|@''HAVE_STRSEP''@|$(HAVE_STRSEP)|g' \ + -e 's|@''HAVE_STRCASESTR''@|$(HAVE_STRCASESTR)|g' \ + -e 's|@''HAVE_DECL_STRTOK_R''@|$(HAVE_DECL_STRTOK_R)|g' \ + -e 's|@''HAVE_DECL_STRERROR_R''@|$(HAVE_DECL_STRERROR_R)|g' \ + -e 's|@''HAVE_DECL_STRSIGNAL''@|$(HAVE_DECL_STRSIGNAL)|g' \ + -e 's|@''HAVE_STRVERSCMP''@|$(HAVE_STRVERSCMP)|g' \ + -e 's|@''REPLACE_STPNCPY''@|$(REPLACE_STPNCPY)|g' \ + -e 's|@''REPLACE_MEMCHR''@|$(REPLACE_MEMCHR)|g' \ + -e 's|@''REPLACE_MEMMEM''@|$(REPLACE_MEMMEM)|g' \ + -e 's|@''REPLACE_STRCASESTR''@|$(REPLACE_STRCASESTR)|g' \ + -e 's|@''REPLACE_STRCHRNUL''@|$(REPLACE_STRCHRNUL)|g' \ + -e 's|@''REPLACE_STRDUP''@|$(REPLACE_STRDUP)|g' \ + -e 's|@''REPLACE_STRSTR''@|$(REPLACE_STRSTR)|g' \ + -e 's|@''REPLACE_STRERROR''@|$(REPLACE_STRERROR)|g' \ + -e 's|@''REPLACE_STRERROR_R''@|$(REPLACE_STRERROR_R)|g' \ + -e 's|@''REPLACE_STRNCAT''@|$(REPLACE_STRNCAT)|g' \ + -e 's|@''REPLACE_STRNDUP''@|$(REPLACE_STRNDUP)|g' \ + -e 's|@''REPLACE_STRNLEN''@|$(REPLACE_STRNLEN)|g' \ + -e 's|@''REPLACE_STRSIGNAL''@|$(REPLACE_STRSIGNAL)|g' \ + -e 's|@''REPLACE_STRTOK_R''@|$(REPLACE_STRTOK_R)|g' \ + -e 's|@''UNDEFINE_STRTOK_R''@|$(UNDEFINE_STRTOK_R)|g' \ + -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)'; \ + < $(srcdir)/string.in.h; \ + } > $@-t && \ + mv $@-t $@ +MOSTLYCLEANFILES += string.h string.h-t + +EXTRA_DIST += string.in.h + +## end gnulib module string + +## begin gnulib module strnlen + + +EXTRA_DIST += strnlen.c + +EXTRA_libgettextlib_la_SOURCES += strnlen.c + +## end gnulib module strnlen + +## begin gnulib module strnlen1 + +libgettextlib_la_SOURCES += strnlen1.h strnlen1.c + +## end gnulib module strnlen1 + +## begin gnulib module strpbrk + + +EXTRA_DIST += strpbrk.c + +EXTRA_libgettextlib_la_SOURCES += strpbrk.c + +## end gnulib module strpbrk + +## begin gnulib module strstr-simple + + +EXTRA_DIST += str-two-way.h strstr.c + +EXTRA_libgettextlib_la_SOURCES += strstr.c + +## end gnulib module strstr-simple + +## begin gnulib module strtol + + +EXTRA_DIST += strtol.c + +EXTRA_libgettextlib_la_SOURCES += strtol.c + +## end gnulib module strtol + +## begin gnulib module strtoul + + +EXTRA_DIST += strtol.c strtoul.c + +EXTRA_libgettextlib_la_SOURCES += strtol.c strtoul.c + +## end gnulib module strtoul + +## begin gnulib module styled-ostream + +libgettextlib_la_SOURCES += styled-ostream.c +# This is a Makefile rule that generates multiple files at once; see the +# automake documentation, node "Multiple Outputs", for details. +styled-ostream.h : $(top_srcdir)/../build-aux/moopp styled-ostream.oo.h styled-ostream.oo.c ostream.oo.h + $(top_srcdir)/../build-aux/moopp $(MOOPPFLAGS) $(srcdir)/styled-ostream.oo.c $(srcdir)/styled-ostream.oo.h $(srcdir)/ostream.oo.h +styled-ostream.c styled_ostream.priv.h styled_ostream.vt.h : styled-ostream.h + @test -f $@ || { \ + trap 'rm -rf styled-ostream.lock' 1 2 13 15; \ + if mkdir styled-ostream.lock 2>/dev/null; then \ + echo "$(top_srcdir)/../build-aux/moopp $(MOOPPFLAGS) $(srcdir)/styled-ostream.oo.c $(srcdir)/styled-ostream.oo.h $(srcdir)/ostream.oo.h"; \ + $(top_srcdir)/../build-aux/moopp $(MOOPPFLAGS) $(srcdir)/styled-ostream.oo.c $(srcdir)/styled-ostream.oo.h $(srcdir)/ostream.oo.h; \ + result=$$?; rm -rf styled-ostream.lock; exit $$result; \ + else \ + while test -d styled-ostream.lock; do sleep 1; done; \ + test -f $(srcdir)/styled-ostream.h; \ + fi; \ + } +BUILT_SOURCES += styled-ostream.h styled-ostream.c styled_ostream.priv.h styled_ostream.vt.h +MAINTAINERCLEANFILES += styled-ostream.h styled-ostream.c styled_ostream.priv.h styled_ostream.vt.h +EXTRA_DIST += styled-ostream.h styled-ostream.c styled_ostream.priv.h styled_ostream.vt.h + +EXTRA_DIST += styled-ostream.oo.c styled-ostream.oo.h + +EXTRA_libgettextlib_la_SOURCES += styled-ostream.oo.c + +## end gnulib module styled-ostream + +## begin gnulib module sys_select + +BUILT_SOURCES += sys/select.h + +# We need the following in order to create when the system +# doesn't have one that works with the given compiler. +sys/select.h: sys_select.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(WARN_ON_USE_H) + $(AM_V_at)$(MKDIR_P) sys + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_SYS_SELECT_H''@|$(NEXT_SYS_SELECT_H)|g' \ + -e 's|@''HAVE_SYS_SELECT_H''@|$(HAVE_SYS_SELECT_H)|g' \ + -e 's/@''GNULIB_PSELECT''@/$(GNULIB_PSELECT)/g' \ + -e 's/@''GNULIB_SELECT''@/$(GNULIB_SELECT)/g' \ + -e 's|@''HAVE_WINSOCK2_H''@|$(HAVE_WINSOCK2_H)|g' \ + -e 's|@''HAVE_PSELECT''@|$(HAVE_PSELECT)|g' \ + -e 's|@''REPLACE_PSELECT''@|$(REPLACE_PSELECT)|g' \ + -e 's|@''REPLACE_SELECT''@|$(REPLACE_SELECT)|g' \ + -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ + < $(srcdir)/sys_select.in.h; \ + } > $@-t && \ + mv $@-t $@ +MOSTLYCLEANFILES += sys/select.h sys/select.h-t +MOSTLYCLEANDIRS += sys + +EXTRA_DIST += sys_select.in.h + +## end gnulib module sys_select + +## begin gnulib module sys_stat + +BUILT_SOURCES += sys/stat.h + +# We need the following in order to create when the system +# has one that is incomplete. +sys/stat.h: sys_stat.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) + $(AM_V_at)$(MKDIR_P) sys + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_SYS_STAT_H''@|$(NEXT_SYS_STAT_H)|g' \ + -e 's|@''WINDOWS_64_BIT_ST_SIZE''@|$(WINDOWS_64_BIT_ST_SIZE)|g' \ + -e 's/@''GNULIB_FCHMODAT''@/$(GNULIB_FCHMODAT)/g' \ + -e 's/@''GNULIB_FSTAT''@/$(GNULIB_FSTAT)/g' \ + -e 's/@''GNULIB_FSTATAT''@/$(GNULIB_FSTATAT)/g' \ + -e 's/@''GNULIB_FUTIMENS''@/$(GNULIB_FUTIMENS)/g' \ + -e 's/@''GNULIB_LCHMOD''@/$(GNULIB_LCHMOD)/g' \ + -e 's/@''GNULIB_LSTAT''@/$(GNULIB_LSTAT)/g' \ + -e 's/@''GNULIB_MKDIRAT''@/$(GNULIB_MKDIRAT)/g' \ + -e 's/@''GNULIB_MKFIFO''@/$(GNULIB_MKFIFO)/g' \ + -e 's/@''GNULIB_MKFIFOAT''@/$(GNULIB_MKFIFOAT)/g' \ + -e 's/@''GNULIB_MKNOD''@/$(GNULIB_MKNOD)/g' \ + -e 's/@''GNULIB_MKNODAT''@/$(GNULIB_MKNODAT)/g' \ + -e 's/@''GNULIB_STAT''@/$(GNULIB_STAT)/g' \ + -e 's/@''GNULIB_UTIMENSAT''@/$(GNULIB_UTIMENSAT)/g' \ + -e 's|@''HAVE_FCHMODAT''@|$(HAVE_FCHMODAT)|g' \ + -e 's|@''HAVE_FSTATAT''@|$(HAVE_FSTATAT)|g' \ + -e 's|@''HAVE_FUTIMENS''@|$(HAVE_FUTIMENS)|g' \ + -e 's|@''HAVE_LCHMOD''@|$(HAVE_LCHMOD)|g' \ + -e 's|@''HAVE_LSTAT''@|$(HAVE_LSTAT)|g' \ + -e 's|@''HAVE_MKDIRAT''@|$(HAVE_MKDIRAT)|g' \ + -e 's|@''HAVE_MKFIFO''@|$(HAVE_MKFIFO)|g' \ + -e 's|@''HAVE_MKFIFOAT''@|$(HAVE_MKFIFOAT)|g' \ + -e 's|@''HAVE_MKNOD''@|$(HAVE_MKNOD)|g' \ + -e 's|@''HAVE_MKNODAT''@|$(HAVE_MKNODAT)|g' \ + -e 's|@''HAVE_UTIMENSAT''@|$(HAVE_UTIMENSAT)|g' \ + -e 's|@''REPLACE_FSTAT''@|$(REPLACE_FSTAT)|g' \ + -e 's|@''REPLACE_FSTATAT''@|$(REPLACE_FSTATAT)|g' \ + -e 's|@''REPLACE_FUTIMENS''@|$(REPLACE_FUTIMENS)|g' \ + -e 's|@''REPLACE_LSTAT''@|$(REPLACE_LSTAT)|g' \ + -e 's|@''REPLACE_MKDIR''@|$(REPLACE_MKDIR)|g' \ + -e 's|@''REPLACE_MKFIFO''@|$(REPLACE_MKFIFO)|g' \ + -e 's|@''REPLACE_MKNOD''@|$(REPLACE_MKNOD)|g' \ + -e 's|@''REPLACE_STAT''@|$(REPLACE_STAT)|g' \ + -e 's|@''REPLACE_UTIMENSAT''@|$(REPLACE_UTIMENSAT)|g' \ + -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ + < $(srcdir)/sys_stat.in.h; \ + } > $@-t && \ + mv $@-t $@ +MOSTLYCLEANFILES += sys/stat.h sys/stat.h-t +MOSTLYCLEANDIRS += sys + +EXTRA_DIST += sys_stat.in.h + +## end gnulib module sys_stat + +## begin gnulib module sys_time + +BUILT_SOURCES += sys/time.h + +# We need the following in order to create when the system +# doesn't have one that works with the given compiler. +sys/time.h: sys_time.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) + $(AM_V_at)$(MKDIR_P) sys + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's/@''HAVE_SYS_TIME_H''@/$(HAVE_SYS_TIME_H)/g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_SYS_TIME_H''@|$(NEXT_SYS_TIME_H)|g' \ + -e 's/@''GNULIB_GETTIMEOFDAY''@/$(GNULIB_GETTIMEOFDAY)/g' \ + -e 's|@''HAVE_WINSOCK2_H''@|$(HAVE_WINSOCK2_H)|g' \ + -e 's/@''HAVE_GETTIMEOFDAY''@/$(HAVE_GETTIMEOFDAY)/g' \ + -e 's/@''HAVE_STRUCT_TIMEVAL''@/$(HAVE_STRUCT_TIMEVAL)/g' \ + -e 's/@''REPLACE_GETTIMEOFDAY''@/$(REPLACE_GETTIMEOFDAY)/g' \ + -e 's/@''REPLACE_STRUCT_TIMEVAL''@/$(REPLACE_STRUCT_TIMEVAL)/g' \ + -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ + < $(srcdir)/sys_time.in.h; \ + } > $@-t && \ + mv $@-t $@ +MOSTLYCLEANFILES += sys/time.h sys/time.h-t + +EXTRA_DIST += sys_time.in.h + +## end gnulib module sys_time + +## begin gnulib module sys_types + +BUILT_SOURCES += sys/types.h + +# We need the following in order to create when the system +# doesn't have one that works with the given compiler. +sys/types.h: sys_types.in.h $(top_builddir)/config.status + $(AM_V_at)$(MKDIR_P) sys + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_SYS_TYPES_H''@|$(NEXT_SYS_TYPES_H)|g' \ + -e 's|@''WINDOWS_64_BIT_OFF_T''@|$(WINDOWS_64_BIT_OFF_T)|g' \ + < $(srcdir)/sys_types.in.h; \ + } > $@-t && \ + mv $@-t $@ +MOSTLYCLEANFILES += sys/types.h sys/types.h-t + +EXTRA_DIST += sys_types.in.h + +## end gnulib module sys_types + +## begin gnulib module sys_wait + +BUILT_SOURCES += sys/wait.h + +# We need the following in order to create when the system +# has one that is incomplete. +sys/wait.h: sys_wait.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(WARN_ON_USE_H) + $(AM_V_at)$(MKDIR_P) sys + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_SYS_WAIT_H''@|$(NEXT_SYS_WAIT_H)|g' \ + -e 's/@''GNULIB_WAITPID''@/$(GNULIB_WAITPID)/g' \ + -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ + < $(srcdir)/sys_wait.in.h; \ + } > $@-t && \ + mv $@-t $@ +MOSTLYCLEANFILES += sys/wait.h sys/wait.h-t +MOSTLYCLEANDIRS += sys + +EXTRA_DIST += sys_wait.in.h + +## end gnulib module sys_wait + +## begin gnulib module tempname + +libgettextlib_la_SOURCES += tempname.c + +EXTRA_DIST += tempname.h + +## end gnulib module tempname + +## begin gnulib module term-ostream + +libgettextlib_la_SOURCES += term-ostream.c +# This is a Makefile rule that generates multiple files at once; see the +# automake documentation, node "Multiple Outputs", for details. +term-ostream.h : $(top_srcdir)/../build-aux/moopp term-ostream.oo.h term-ostream.oo.c ostream.oo.h + $(top_srcdir)/../build-aux/moopp $(MOOPPFLAGS) $(srcdir)/term-ostream.oo.c $(srcdir)/term-ostream.oo.h $(srcdir)/ostream.oo.h +term-ostream.c term_ostream.priv.h term_ostream.vt.h : term-ostream.h + @test -f $@ || { \ + trap 'rm -rf term-ostream.lock' 1 2 13 15; \ + if mkdir term-ostream.lock 2>/dev/null; then \ + echo "$(top_srcdir)/../build-aux/moopp $(MOOPPFLAGS) $(srcdir)/term-ostream.oo.c $(srcdir)/term-ostream.oo.h $(srcdir)/ostream.oo.h"; \ + $(top_srcdir)/../build-aux/moopp $(MOOPPFLAGS) $(srcdir)/term-ostream.oo.c $(srcdir)/term-ostream.oo.h $(srcdir)/ostream.oo.h; \ + result=$$?; rm -rf term-ostream.lock; exit $$result; \ + else \ + while test -d term-ostream.lock; do sleep 1; done; \ + test -f $(srcdir)/term-ostream.h; \ + fi; \ + } +BUILT_SOURCES += term-ostream.h term-ostream.c term_ostream.priv.h term_ostream.vt.h +MAINTAINERCLEANFILES += term-ostream.h term-ostream.c term_ostream.priv.h term_ostream.vt.h +EXTRA_DIST += term-ostream.h term-ostream.c term_ostream.priv.h term_ostream.vt.h + +EXTRA_DIST += term-ostream.oo.c term-ostream.oo.h + +EXTRA_libgettextlib_la_SOURCES += term-ostream.oo.c + +## end gnulib module term-ostream + +## begin gnulib module term-styled-ostream + +if !WOE32DLL +libgettextlib_la_SOURCES += term-styled-ostream.c +else +libgettextlib_la_SOURCES += ../woe32dll/c++term-styled-ostream.cc +endif +# This is a Makefile rule that generates multiple files at once; see the +# automake documentation, node "Multiple Outputs", for details. +term-styled-ostream.h : $(top_srcdir)/../build-aux/moopp term-styled-ostream.oo.h term-styled-ostream.oo.c styled-ostream.oo.h ostream.oo.h + $(top_srcdir)/../build-aux/moopp $(MOOPPFLAGS) $(srcdir)/term-styled-ostream.oo.c $(srcdir)/term-styled-ostream.oo.h $(srcdir)/styled-ostream.oo.h $(srcdir)/ostream.oo.h +term-styled-ostream.c term_styled_ostream.priv.h term_styled_ostream.vt.h : term-styled-ostream.h + @test -f $@ || { \ + trap 'rm -rf term-styled-ostream.lock' 1 2 13 15; \ + if mkdir term-styled-ostream.lock 2>/dev/null; then \ + echo "$(top_srcdir)/../build-aux/moopp $(MOOPPFLAGS) $(srcdir)/term-styled-ostream.oo.c $(srcdir)/term-styled-ostream.oo.h $(srcdir)/styled-ostream.oo.h $(srcdir)/ostream.oo.h"; \ + $(top_srcdir)/../build-aux/moopp $(MOOPPFLAGS) $(srcdir)/term-styled-ostream.oo.c $(srcdir)/term-styled-ostream.oo.h $(srcdir)/styled-ostream.oo.h $(srcdir)/ostream.oo.h; \ + result=$$?; rm -rf term-styled-ostream.lock; exit $$result; \ + else \ + while test -d term-styled-ostream.lock; do sleep 1; done; \ + test -f $(srcdir)/term-styled-ostream.h; \ + fi; \ + } +BUILT_SOURCES += term-styled-ostream.h term-styled-ostream.c term_styled_ostream.priv.h term_styled_ostream.vt.h +MAINTAINERCLEANFILES += term-styled-ostream.h term-styled-ostream.c term_styled_ostream.priv.h term_styled_ostream.vt.h +EXTRA_DIST += term-styled-ostream.h term-styled-ostream.c term_styled_ostream.priv.h term_styled_ostream.vt.h + +EXTRA_DIST += term-styled-ostream.oo.c term-styled-ostream.oo.h + +EXTRA_libgettextlib_la_SOURCES += term-styled-ostream.oo.c + +## end gnulib module term-styled-ostream + +## begin gnulib module terminfo + +if GL_COND_LIBTOOL +libgettextlib_la_LDFLAGS += $(LTLIBTERMINFO) +endif + +EXTRA_DIST += tparm.c tputs.c + +EXTRA_libgettextlib_la_SOURCES += tparm.c tputs.c + +## end gnulib module terminfo + +## begin gnulib module terminfo-h + + +EXTRA_DIST += terminfo.h + +## end gnulib module terminfo-h + +## begin gnulib module threadlib + +libgettextlib_la_SOURCES += glthread/threadlib.c + +EXTRA_DIST += $(top_srcdir)/../build-aux/config.rpath + +## end gnulib module threadlib + +## begin gnulib module time + +BUILT_SOURCES += time.h + +# We need the following in order to create when the system +# doesn't have one that works with the given compiler. +time.h: time.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_TIME_H''@|$(NEXT_TIME_H)|g' \ + -e 's/@''GNULIB_GETTIMEOFDAY''@/$(GNULIB_GETTIMEOFDAY)/g' \ + -e 's/@''GNULIB_MKTIME''@/$(GNULIB_MKTIME)/g' \ + -e 's/@''GNULIB_NANOSLEEP''@/$(GNULIB_NANOSLEEP)/g' \ + -e 's/@''GNULIB_STRPTIME''@/$(GNULIB_STRPTIME)/g' \ + -e 's/@''GNULIB_TIMEGM''@/$(GNULIB_TIMEGM)/g' \ + -e 's/@''GNULIB_TIME_R''@/$(GNULIB_TIME_R)/g' \ + -e 's|@''HAVE_DECL_LOCALTIME_R''@|$(HAVE_DECL_LOCALTIME_R)|g' \ + -e 's|@''HAVE_NANOSLEEP''@|$(HAVE_NANOSLEEP)|g' \ + -e 's|@''HAVE_STRPTIME''@|$(HAVE_STRPTIME)|g' \ + -e 's|@''HAVE_TIMEGM''@|$(HAVE_TIMEGM)|g' \ + -e 's|@''REPLACE_GMTIME''@|$(REPLACE_GMTIME)|g' \ + -e 's|@''REPLACE_LOCALTIME''@|$(REPLACE_LOCALTIME)|g' \ + -e 's|@''REPLACE_LOCALTIME_R''@|$(REPLACE_LOCALTIME_R)|g' \ + -e 's|@''REPLACE_MKTIME''@|$(REPLACE_MKTIME)|g' \ + -e 's|@''REPLACE_NANOSLEEP''@|$(REPLACE_NANOSLEEP)|g' \ + -e 's|@''REPLACE_TIMEGM''@|$(REPLACE_TIMEGM)|g' \ + -e 's|@''PTHREAD_H_DEFINES_STRUCT_TIMESPEC''@|$(PTHREAD_H_DEFINES_STRUCT_TIMESPEC)|g' \ + -e 's|@''SYS_TIME_H_DEFINES_STRUCT_TIMESPEC''@|$(SYS_TIME_H_DEFINES_STRUCT_TIMESPEC)|g' \ + -e 's|@''TIME_H_DEFINES_STRUCT_TIMESPEC''@|$(TIME_H_DEFINES_STRUCT_TIMESPEC)|g' \ + -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ + < $(srcdir)/time.in.h; \ + } > $@-t && \ + mv $@-t $@ +MOSTLYCLEANFILES += time.h time.h-t + +EXTRA_DIST += time.in.h + +## end gnulib module time + +## begin gnulib module tls + +libgettextlib_la_SOURCES += glthread/tls.h glthread/tls.c + +## end gnulib module tls + +## begin gnulib module tmpdir + +libgettextlib_la_SOURCES += tmpdir.h tmpdir.c + +## end gnulib module tmpdir + +## begin gnulib module trim + +libgettextlib_la_SOURCES += trim.c + +EXTRA_DIST += trim.h + +## end gnulib module trim + +## begin gnulib module uniconv/base + +BUILT_SOURCES += $(LIBUNISTRING_UNICONV_H) + +uniconv.h: uniconv.in.h + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/uniconv.in.h; \ + } > $@-t && \ + mv -f $@-t $@ +MOSTLYCLEANFILES += uniconv.h uniconv.h-t + +EXTRA_DIST += iconveh.h localcharset.h striconveha.h uniconv.in.h + +## end gnulib module uniconv/base + +## begin gnulib module uniconv/u8-conv-from-enc + +if LIBUNISTRING_COMPILE_UNICONV_U8_CONV_FROM_ENC +libgettextlib_la_SOURCES += uniconv/u8-conv-from-enc.c +endif + +## end gnulib module uniconv/u8-conv-from-enc + +## begin gnulib module unilbrk/base + +BUILT_SOURCES += $(LIBUNISTRING_UNILBRK_H) + +unilbrk.h: unilbrk.in.h + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/unilbrk.in.h; \ + } > $@-t && \ + mv -f $@-t $@ +MOSTLYCLEANFILES += unilbrk.h unilbrk.h-t + +EXTRA_DIST += unilbrk.in.h + +## end gnulib module unilbrk/base + +## begin gnulib module unilbrk/tables + +libgettextlib_la_SOURCES += unilbrk/lbrktables.c + +EXTRA_DIST += unilbrk/lbrkprop1.h unilbrk/lbrkprop2.h unilbrk/lbrktables.h + +## end gnulib module unilbrk/tables + +## begin gnulib module unilbrk/u8-possible-linebreaks + +if LIBUNISTRING_COMPILE_UNILBRK_U8_POSSIBLE_LINEBREAKS +libgettextlib_la_SOURCES += unilbrk/u8-possible-linebreaks.c +endif + +EXTRA_DIST += uniwidth/cjk.h + +## end gnulib module unilbrk/u8-possible-linebreaks + +## begin gnulib module unilbrk/u8-width-linebreaks + +if LIBUNISTRING_COMPILE_UNILBRK_U8_WIDTH_LINEBREAKS +libgettextlib_la_SOURCES += unilbrk/u8-width-linebreaks.c +endif + +## end gnulib module unilbrk/u8-width-linebreaks + +## begin gnulib module unilbrk/ulc-common + +libgettextlib_la_SOURCES += unilbrk/ulc-common.c + +EXTRA_DIST += unilbrk/ulc-common.h + +## end gnulib module unilbrk/ulc-common + +## begin gnulib module unilbrk/ulc-width-linebreaks + +if LIBUNISTRING_COMPILE_UNILBRK_ULC_WIDTH_LINEBREAKS +libgettextlib_la_SOURCES += unilbrk/ulc-width-linebreaks.c +endif + +## end gnulib module unilbrk/ulc-width-linebreaks + +## begin gnulib module uniname/base + +BUILT_SOURCES += $(LIBUNISTRING_UNINAME_H) + +uniname.h: uniname.in.h + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/uniname.in.h; \ + } > $@-t && \ + mv -f $@-t $@ +MOSTLYCLEANFILES += uniname.h uniname.h-t + +EXTRA_DIST += uniname.in.h + +## end gnulib module uniname/base + +## begin gnulib module uniname/uniname + +if LIBUNISTRING_COMPILE_UNINAME_UNINAME +libgettextlib_la_SOURCES += uniname/uniname.c +endif + +EXTRA_DIST += uniname/gen-uninames.lisp uniname/uninames.h + +## end gnulib module uniname/uniname + +## begin gnulib module unistd + +BUILT_SOURCES += unistd.h +libgettextlib_la_SOURCES += unistd.c + +# We need the following in order to create an empty placeholder for +# when the system doesn't have one. +unistd.h: unistd.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''HAVE_UNISTD_H''@|$(HAVE_UNISTD_H)|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_UNISTD_H''@|$(NEXT_UNISTD_H)|g' \ + -e 's|@''WINDOWS_64_BIT_OFF_T''@|$(WINDOWS_64_BIT_OFF_T)|g' \ + -e 's/@''GNULIB_CHDIR''@/$(GNULIB_CHDIR)/g' \ + -e 's/@''GNULIB_CHOWN''@/$(GNULIB_CHOWN)/g' \ + -e 's/@''GNULIB_CLOSE''@/$(GNULIB_CLOSE)/g' \ + -e 's/@''GNULIB_DUP''@/$(GNULIB_DUP)/g' \ + -e 's/@''GNULIB_DUP2''@/$(GNULIB_DUP2)/g' \ + -e 's/@''GNULIB_DUP3''@/$(GNULIB_DUP3)/g' \ + -e 's/@''GNULIB_ENVIRON''@/$(GNULIB_ENVIRON)/g' \ + -e 's/@''GNULIB_EUIDACCESS''@/$(GNULIB_EUIDACCESS)/g' \ + -e 's/@''GNULIB_FACCESSAT''@/$(GNULIB_FACCESSAT)/g' \ + -e 's/@''GNULIB_FCHDIR''@/$(GNULIB_FCHDIR)/g' \ + -e 's/@''GNULIB_FCHOWNAT''@/$(GNULIB_FCHOWNAT)/g' \ + -e 's/@''GNULIB_FDATASYNC''@/$(GNULIB_FDATASYNC)/g' \ + -e 's/@''GNULIB_FSYNC''@/$(GNULIB_FSYNC)/g' \ + -e 's/@''GNULIB_FTRUNCATE''@/$(GNULIB_FTRUNCATE)/g' \ + -e 's/@''GNULIB_GETCWD''@/$(GNULIB_GETCWD)/g' \ + -e 's/@''GNULIB_GETDOMAINNAME''@/$(GNULIB_GETDOMAINNAME)/g' \ + -e 's/@''GNULIB_GETDTABLESIZE''@/$(GNULIB_GETDTABLESIZE)/g' \ + -e 's/@''GNULIB_GETGROUPS''@/$(GNULIB_GETGROUPS)/g' \ + -e 's/@''GNULIB_GETHOSTNAME''@/$(GNULIB_GETHOSTNAME)/g' \ + -e 's/@''GNULIB_GETLOGIN''@/$(GNULIB_GETLOGIN)/g' \ + -e 's/@''GNULIB_GETLOGIN_R''@/$(GNULIB_GETLOGIN_R)/g' \ + -e 's/@''GNULIB_GETPAGESIZE''@/$(GNULIB_GETPAGESIZE)/g' \ + -e 's/@''GNULIB_GETUSERSHELL''@/$(GNULIB_GETUSERSHELL)/g' \ + -e 's/@''GNULIB_GROUP_MEMBER''@/$(GNULIB_GROUP_MEMBER)/g' \ + -e 's/@''GNULIB_ISATTY''@/$(GNULIB_ISATTY)/g' \ + -e 's/@''GNULIB_LCHOWN''@/$(GNULIB_LCHOWN)/g' \ + -e 's/@''GNULIB_LINK''@/$(GNULIB_LINK)/g' \ + -e 's/@''GNULIB_LINKAT''@/$(GNULIB_LINKAT)/g' \ + -e 's/@''GNULIB_LSEEK''@/$(GNULIB_LSEEK)/g' \ + -e 's/@''GNULIB_PIPE''@/$(GNULIB_PIPE)/g' \ + -e 's/@''GNULIB_PIPE2''@/$(GNULIB_PIPE2)/g' \ + -e 's/@''GNULIB_PREAD''@/$(GNULIB_PREAD)/g' \ + -e 's/@''GNULIB_PWRITE''@/$(GNULIB_PWRITE)/g' \ + -e 's/@''GNULIB_READ''@/$(GNULIB_READ)/g' \ + -e 's/@''GNULIB_READLINK''@/$(GNULIB_READLINK)/g' \ + -e 's/@''GNULIB_READLINKAT''@/$(GNULIB_READLINKAT)/g' \ + -e 's/@''GNULIB_RMDIR''@/$(GNULIB_RMDIR)/g' \ + -e 's/@''GNULIB_SETHOSTNAME''@/$(GNULIB_SETHOSTNAME)/g' \ + -e 's/@''GNULIB_SLEEP''@/$(GNULIB_SLEEP)/g' \ + -e 's/@''GNULIB_SYMLINK''@/$(GNULIB_SYMLINK)/g' \ + -e 's/@''GNULIB_SYMLINKAT''@/$(GNULIB_SYMLINKAT)/g' \ + -e 's/@''GNULIB_TTYNAME_R''@/$(GNULIB_TTYNAME_R)/g' \ + -e 's/@''GNULIB_UNISTD_H_GETOPT''@/0$(GNULIB_GL_UNISTD_H_GETOPT)/g' \ + -e 's/@''GNULIB_UNISTD_H_NONBLOCKING''@/$(GNULIB_UNISTD_H_NONBLOCKING)/g' \ + -e 's/@''GNULIB_UNISTD_H_SIGPIPE''@/$(GNULIB_UNISTD_H_SIGPIPE)/g' \ + -e 's/@''GNULIB_UNLINK''@/$(GNULIB_UNLINK)/g' \ + -e 's/@''GNULIB_UNLINKAT''@/$(GNULIB_UNLINKAT)/g' \ + -e 's/@''GNULIB_USLEEP''@/$(GNULIB_USLEEP)/g' \ + -e 's/@''GNULIB_WRITE''@/$(GNULIB_WRITE)/g' \ + < $(srcdir)/unistd.in.h | \ + sed -e 's|@''HAVE_CHOWN''@|$(HAVE_CHOWN)|g' \ + -e 's|@''HAVE_DUP2''@|$(HAVE_DUP2)|g' \ + -e 's|@''HAVE_DUP3''@|$(HAVE_DUP3)|g' \ + -e 's|@''HAVE_EUIDACCESS''@|$(HAVE_EUIDACCESS)|g' \ + -e 's|@''HAVE_FACCESSAT''@|$(HAVE_FACCESSAT)|g' \ + -e 's|@''HAVE_FCHDIR''@|$(HAVE_FCHDIR)|g' \ + -e 's|@''HAVE_FCHOWNAT''@|$(HAVE_FCHOWNAT)|g' \ + -e 's|@''HAVE_FDATASYNC''@|$(HAVE_FDATASYNC)|g' \ + -e 's|@''HAVE_FSYNC''@|$(HAVE_FSYNC)|g' \ + -e 's|@''HAVE_FTRUNCATE''@|$(HAVE_FTRUNCATE)|g' \ + -e 's|@''HAVE_GETDTABLESIZE''@|$(HAVE_GETDTABLESIZE)|g' \ + -e 's|@''HAVE_GETGROUPS''@|$(HAVE_GETGROUPS)|g' \ + -e 's|@''HAVE_GETHOSTNAME''@|$(HAVE_GETHOSTNAME)|g' \ + -e 's|@''HAVE_GETLOGIN''@|$(HAVE_GETLOGIN)|g' \ + -e 's|@''HAVE_GETPAGESIZE''@|$(HAVE_GETPAGESIZE)|g' \ + -e 's|@''HAVE_GROUP_MEMBER''@|$(HAVE_GROUP_MEMBER)|g' \ + -e 's|@''HAVE_LCHOWN''@|$(HAVE_LCHOWN)|g' \ + -e 's|@''HAVE_LINK''@|$(HAVE_LINK)|g' \ + -e 's|@''HAVE_LINKAT''@|$(HAVE_LINKAT)|g' \ + -e 's|@''HAVE_PIPE''@|$(HAVE_PIPE)|g' \ + -e 's|@''HAVE_PIPE2''@|$(HAVE_PIPE2)|g' \ + -e 's|@''HAVE_PREAD''@|$(HAVE_PREAD)|g' \ + -e 's|@''HAVE_PWRITE''@|$(HAVE_PWRITE)|g' \ + -e 's|@''HAVE_READLINK''@|$(HAVE_READLINK)|g' \ + -e 's|@''HAVE_READLINKAT''@|$(HAVE_READLINKAT)|g' \ + -e 's|@''HAVE_SETHOSTNAME''@|$(HAVE_SETHOSTNAME)|g' \ + -e 's|@''HAVE_SLEEP''@|$(HAVE_SLEEP)|g' \ + -e 's|@''HAVE_SYMLINK''@|$(HAVE_SYMLINK)|g' \ + -e 's|@''HAVE_SYMLINKAT''@|$(HAVE_SYMLINKAT)|g' \ + -e 's|@''HAVE_UNLINKAT''@|$(HAVE_UNLINKAT)|g' \ + -e 's|@''HAVE_USLEEP''@|$(HAVE_USLEEP)|g' \ + -e 's|@''HAVE_DECL_ENVIRON''@|$(HAVE_DECL_ENVIRON)|g' \ + -e 's|@''HAVE_DECL_FCHDIR''@|$(HAVE_DECL_FCHDIR)|g' \ + -e 's|@''HAVE_DECL_FDATASYNC''@|$(HAVE_DECL_FDATASYNC)|g' \ + -e 's|@''HAVE_DECL_GETDOMAINNAME''@|$(HAVE_DECL_GETDOMAINNAME)|g' \ + -e 's|@''HAVE_DECL_GETLOGIN_R''@|$(HAVE_DECL_GETLOGIN_R)|g' \ + -e 's|@''HAVE_DECL_GETPAGESIZE''@|$(HAVE_DECL_GETPAGESIZE)|g' \ + -e 's|@''HAVE_DECL_GETUSERSHELL''@|$(HAVE_DECL_GETUSERSHELL)|g' \ + -e 's|@''HAVE_DECL_SETHOSTNAME''@|$(HAVE_DECL_SETHOSTNAME)|g' \ + -e 's|@''HAVE_DECL_TTYNAME_R''@|$(HAVE_DECL_TTYNAME_R)|g' \ + -e 's|@''HAVE_OS_H''@|$(HAVE_OS_H)|g' \ + -e 's|@''HAVE_SYS_PARAM_H''@|$(HAVE_SYS_PARAM_H)|g' \ + | \ + sed -e 's|@''REPLACE_CHOWN''@|$(REPLACE_CHOWN)|g' \ + -e 's|@''REPLACE_CLOSE''@|$(REPLACE_CLOSE)|g' \ + -e 's|@''REPLACE_DUP''@|$(REPLACE_DUP)|g' \ + -e 's|@''REPLACE_DUP2''@|$(REPLACE_DUP2)|g' \ + -e 's|@''REPLACE_FCHOWNAT''@|$(REPLACE_FCHOWNAT)|g' \ + -e 's|@''REPLACE_FTRUNCATE''@|$(REPLACE_FTRUNCATE)|g' \ + -e 's|@''REPLACE_GETCWD''@|$(REPLACE_GETCWD)|g' \ + -e 's|@''REPLACE_GETDOMAINNAME''@|$(REPLACE_GETDOMAINNAME)|g' \ + -e 's|@''REPLACE_GETDTABLESIZE''@|$(REPLACE_GETDTABLESIZE)|g' \ + -e 's|@''REPLACE_GETLOGIN_R''@|$(REPLACE_GETLOGIN_R)|g' \ + -e 's|@''REPLACE_GETGROUPS''@|$(REPLACE_GETGROUPS)|g' \ + -e 's|@''REPLACE_GETPAGESIZE''@|$(REPLACE_GETPAGESIZE)|g' \ + -e 's|@''REPLACE_ISATTY''@|$(REPLACE_ISATTY)|g' \ + -e 's|@''REPLACE_LCHOWN''@|$(REPLACE_LCHOWN)|g' \ + -e 's|@''REPLACE_LINK''@|$(REPLACE_LINK)|g' \ + -e 's|@''REPLACE_LINKAT''@|$(REPLACE_LINKAT)|g' \ + -e 's|@''REPLACE_LSEEK''@|$(REPLACE_LSEEK)|g' \ + -e 's|@''REPLACE_PREAD''@|$(REPLACE_PREAD)|g' \ + -e 's|@''REPLACE_PWRITE''@|$(REPLACE_PWRITE)|g' \ + -e 's|@''REPLACE_READ''@|$(REPLACE_READ)|g' \ + -e 's|@''REPLACE_READLINK''@|$(REPLACE_READLINK)|g' \ + -e 's|@''REPLACE_READLINKAT''@|$(REPLACE_READLINKAT)|g' \ + -e 's|@''REPLACE_RMDIR''@|$(REPLACE_RMDIR)|g' \ + -e 's|@''REPLACE_SLEEP''@|$(REPLACE_SLEEP)|g' \ + -e 's|@''REPLACE_SYMLINK''@|$(REPLACE_SYMLINK)|g' \ + -e 's|@''REPLACE_SYMLINKAT''@|$(REPLACE_SYMLINKAT)|g' \ + -e 's|@''REPLACE_TTYNAME_R''@|$(REPLACE_TTYNAME_R)|g' \ + -e 's|@''REPLACE_UNLINK''@|$(REPLACE_UNLINK)|g' \ + -e 's|@''REPLACE_UNLINKAT''@|$(REPLACE_UNLINKAT)|g' \ + -e 's|@''REPLACE_USLEEP''@|$(REPLACE_USLEEP)|g' \ + -e 's|@''REPLACE_WRITE''@|$(REPLACE_WRITE)|g' \ + -e 's|@''UNISTD_H_HAVE_WINSOCK2_H''@|$(UNISTD_H_HAVE_WINSOCK2_H)|g' \ + -e 's|@''UNISTD_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS''@|$(UNISTD_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS)|g' \ + -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)'; \ + } > $@-t && \ + mv $@-t $@ +MOSTLYCLEANFILES += unistd.h unistd.h-t + +EXTRA_DIST += unistd.in.h + +## end gnulib module unistd + +## begin gnulib module unistd-safer + +libgettextlib_la_SOURCES += dup-safer.c fd-safer.c pipe-safer.c + +EXTRA_DIST += unistd--.h unistd-safer.h + +## end gnulib module unistd-safer + +## begin gnulib module unistr/base + +BUILT_SOURCES += $(LIBUNISTRING_UNISTR_H) + +unistr.h: unistr.in.h + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/unistr.in.h; \ + } > $@-t && \ + mv -f $@-t $@ +MOSTLYCLEANFILES += unistr.h unistr.h-t + +EXTRA_DIST += unistr.in.h + +## end gnulib module unistr/base + +## begin gnulib module unistr/u16-mbtouc + +if LIBUNISTRING_COMPILE_UNISTR_U16_MBTOUC +libgettextlib_la_SOURCES += unistr/u16-mbtouc.c unistr/u16-mbtouc-aux.c +endif + +## end gnulib module unistr/u16-mbtouc + +## begin gnulib module unistr/u8-check + +if LIBUNISTRING_COMPILE_UNISTR_U8_CHECK +libgettextlib_la_SOURCES += unistr/u8-check.c +endif + +## end gnulib module unistr/u8-check + +## begin gnulib module unistr/u8-mblen + +if LIBUNISTRING_COMPILE_UNISTR_U8_MBLEN +libgettextlib_la_SOURCES += unistr/u8-mblen.c +endif + +## end gnulib module unistr/u8-mblen + +## begin gnulib module unistr/u8-mbtouc + +if LIBUNISTRING_COMPILE_UNISTR_U8_MBTOUC +libgettextlib_la_SOURCES += unistr/u8-mbtouc.c unistr/u8-mbtouc-aux.c +endif + +## end gnulib module unistr/u8-mbtouc + +## begin gnulib module unistr/u8-mbtouc-unsafe + +if LIBUNISTRING_COMPILE_UNISTR_U8_MBTOUC_UNSAFE +libgettextlib_la_SOURCES += unistr/u8-mbtouc-unsafe.c unistr/u8-mbtouc-unsafe-aux.c +endif + +## end gnulib module unistr/u8-mbtouc-unsafe + +## begin gnulib module unistr/u8-mbtoucr + +if LIBUNISTRING_COMPILE_UNISTR_U8_MBTOUCR +libgettextlib_la_SOURCES += unistr/u8-mbtoucr.c +endif + +## end gnulib module unistr/u8-mbtoucr + +## begin gnulib module unistr/u8-prev + +if LIBUNISTRING_COMPILE_UNISTR_U8_PREV +libgettextlib_la_SOURCES += unistr/u8-prev.c +endif + +## end gnulib module unistr/u8-prev + +## begin gnulib module unistr/u8-uctomb + +if LIBUNISTRING_COMPILE_UNISTR_U8_UCTOMB +libgettextlib_la_SOURCES += unistr/u8-uctomb.c unistr/u8-uctomb-aux.c +endif + +## end gnulib module unistr/u8-uctomb + +## begin gnulib module unitypes + +BUILT_SOURCES += $(LIBUNISTRING_UNITYPES_H) + +unitypes.h: unitypes.in.h + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/unitypes.in.h; \ + } > $@-t && \ + mv -f $@-t $@ +MOSTLYCLEANFILES += unitypes.h unitypes.h-t + +EXTRA_DIST += unitypes.in.h + +## end gnulib module unitypes + +## begin gnulib module uniwidth/base + +BUILT_SOURCES += $(LIBUNISTRING_UNIWIDTH_H) + +uniwidth.h: uniwidth.in.h + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/uniwidth.in.h; \ + } > $@-t && \ + mv -f $@-t $@ +MOSTLYCLEANFILES += uniwidth.h uniwidth.h-t + +EXTRA_DIST += localcharset.h uniwidth.in.h + +## end gnulib module uniwidth/base + +## begin gnulib module uniwidth/width + +if LIBUNISTRING_COMPILE_UNIWIDTH_WIDTH +libgettextlib_la_SOURCES += uniwidth/width.c +endif + +EXTRA_DIST += uniwidth/cjk.h + +## end gnulib module uniwidth/width + +## begin gnulib module unlocked-io + + +EXTRA_DIST += unlocked-io.h + +## end gnulib module unlocked-io + +## begin gnulib module unsetenv + + +EXTRA_DIST += unsetenv.c + +EXTRA_libgettextlib_la_SOURCES += unsetenv.c + +## end gnulib module unsetenv + +## begin gnulib module vasnprintf + + +EXTRA_DIST += asnprintf.c float+.h printf-args.c printf-args.h printf-parse.c printf-parse.h vasnprintf.c vasnprintf.h + +EXTRA_libgettextlib_la_SOURCES += asnprintf.c printf-args.c printf-parse.c vasnprintf.c + +## end gnulib module vasnprintf + +## begin gnulib module vasprintf + + +EXTRA_DIST += asprintf.c vasprintf.c + +EXTRA_libgettextlib_la_SOURCES += asprintf.c vasprintf.c + +## end gnulib module vasprintf + +## begin gnulib module verify + + +EXTRA_DIST += verify.h + +## end gnulib module verify + +## begin gnulib module vsnprintf + + +EXTRA_DIST += vsnprintf.c + +EXTRA_libgettextlib_la_SOURCES += vsnprintf.c + +## end gnulib module vsnprintf + +## begin gnulib module wait-process + +libgettextlib_la_SOURCES += wait-process.h wait-process.c + +## end gnulib module wait-process + +## begin gnulib module waitpid + + +EXTRA_DIST += waitpid.c + +EXTRA_libgettextlib_la_SOURCES += waitpid.c + +## end gnulib module waitpid + +## begin gnulib module wchar + +BUILT_SOURCES += wchar.h + +# We need the following in order to create when the system +# version does not work standalone. +wchar.h: wchar.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''HAVE_FEATURES_H''@|$(HAVE_FEATURES_H)|g' \ + -e 's|@''NEXT_WCHAR_H''@|$(NEXT_WCHAR_H)|g' \ + -e 's|@''HAVE_WCHAR_H''@|$(HAVE_WCHAR_H)|g' \ + -e 's/@''GNULIB_BTOWC''@/$(GNULIB_BTOWC)/g' \ + -e 's/@''GNULIB_WCTOB''@/$(GNULIB_WCTOB)/g' \ + -e 's/@''GNULIB_MBSINIT''@/$(GNULIB_MBSINIT)/g' \ + -e 's/@''GNULIB_MBRTOWC''@/$(GNULIB_MBRTOWC)/g' \ + -e 's/@''GNULIB_MBRLEN''@/$(GNULIB_MBRLEN)/g' \ + -e 's/@''GNULIB_MBSRTOWCS''@/$(GNULIB_MBSRTOWCS)/g' \ + -e 's/@''GNULIB_MBSNRTOWCS''@/$(GNULIB_MBSNRTOWCS)/g' \ + -e 's/@''GNULIB_WCRTOMB''@/$(GNULIB_WCRTOMB)/g' \ + -e 's/@''GNULIB_WCSRTOMBS''@/$(GNULIB_WCSRTOMBS)/g' \ + -e 's/@''GNULIB_WCSNRTOMBS''@/$(GNULIB_WCSNRTOMBS)/g' \ + -e 's/@''GNULIB_WCWIDTH''@/$(GNULIB_WCWIDTH)/g' \ + -e 's/@''GNULIB_WMEMCHR''@/$(GNULIB_WMEMCHR)/g' \ + -e 's/@''GNULIB_WMEMCMP''@/$(GNULIB_WMEMCMP)/g' \ + -e 's/@''GNULIB_WMEMCPY''@/$(GNULIB_WMEMCPY)/g' \ + -e 's/@''GNULIB_WMEMMOVE''@/$(GNULIB_WMEMMOVE)/g' \ + -e 's/@''GNULIB_WMEMSET''@/$(GNULIB_WMEMSET)/g' \ + -e 's/@''GNULIB_WCSLEN''@/$(GNULIB_WCSLEN)/g' \ + -e 's/@''GNULIB_WCSNLEN''@/$(GNULIB_WCSNLEN)/g' \ + -e 's/@''GNULIB_WCSCPY''@/$(GNULIB_WCSCPY)/g' \ + -e 's/@''GNULIB_WCPCPY''@/$(GNULIB_WCPCPY)/g' \ + -e 's/@''GNULIB_WCSNCPY''@/$(GNULIB_WCSNCPY)/g' \ + -e 's/@''GNULIB_WCPNCPY''@/$(GNULIB_WCPNCPY)/g' \ + -e 's/@''GNULIB_WCSCAT''@/$(GNULIB_WCSCAT)/g' \ + -e 's/@''GNULIB_WCSNCAT''@/$(GNULIB_WCSNCAT)/g' \ + -e 's/@''GNULIB_WCSCMP''@/$(GNULIB_WCSCMP)/g' \ + -e 's/@''GNULIB_WCSNCMP''@/$(GNULIB_WCSNCMP)/g' \ + -e 's/@''GNULIB_WCSCASECMP''@/$(GNULIB_WCSCASECMP)/g' \ + -e 's/@''GNULIB_WCSNCASECMP''@/$(GNULIB_WCSNCASECMP)/g' \ + -e 's/@''GNULIB_WCSCOLL''@/$(GNULIB_WCSCOLL)/g' \ + -e 's/@''GNULIB_WCSXFRM''@/$(GNULIB_WCSXFRM)/g' \ + -e 's/@''GNULIB_WCSDUP''@/$(GNULIB_WCSDUP)/g' \ + -e 's/@''GNULIB_WCSCHR''@/$(GNULIB_WCSCHR)/g' \ + -e 's/@''GNULIB_WCSRCHR''@/$(GNULIB_WCSRCHR)/g' \ + -e 's/@''GNULIB_WCSCSPN''@/$(GNULIB_WCSCSPN)/g' \ + -e 's/@''GNULIB_WCSSPN''@/$(GNULIB_WCSSPN)/g' \ + -e 's/@''GNULIB_WCSPBRK''@/$(GNULIB_WCSPBRK)/g' \ + -e 's/@''GNULIB_WCSSTR''@/$(GNULIB_WCSSTR)/g' \ + -e 's/@''GNULIB_WCSTOK''@/$(GNULIB_WCSTOK)/g' \ + -e 's/@''GNULIB_WCSWIDTH''@/$(GNULIB_WCSWIDTH)/g' \ + < $(srcdir)/wchar.in.h | \ + sed -e 's|@''HAVE_WINT_T''@|$(HAVE_WINT_T)|g' \ + -e 's|@''HAVE_BTOWC''@|$(HAVE_BTOWC)|g' \ + -e 's|@''HAVE_MBSINIT''@|$(HAVE_MBSINIT)|g' \ + -e 's|@''HAVE_MBRTOWC''@|$(HAVE_MBRTOWC)|g' \ + -e 's|@''HAVE_MBRLEN''@|$(HAVE_MBRLEN)|g' \ + -e 's|@''HAVE_MBSRTOWCS''@|$(HAVE_MBSRTOWCS)|g' \ + -e 's|@''HAVE_MBSNRTOWCS''@|$(HAVE_MBSNRTOWCS)|g' \ + -e 's|@''HAVE_WCRTOMB''@|$(HAVE_WCRTOMB)|g' \ + -e 's|@''HAVE_WCSRTOMBS''@|$(HAVE_WCSRTOMBS)|g' \ + -e 's|@''HAVE_WCSNRTOMBS''@|$(HAVE_WCSNRTOMBS)|g' \ + -e 's|@''HAVE_WMEMCHR''@|$(HAVE_WMEMCHR)|g' \ + -e 's|@''HAVE_WMEMCMP''@|$(HAVE_WMEMCMP)|g' \ + -e 's|@''HAVE_WMEMCPY''@|$(HAVE_WMEMCPY)|g' \ + -e 's|@''HAVE_WMEMMOVE''@|$(HAVE_WMEMMOVE)|g' \ + -e 's|@''HAVE_WMEMSET''@|$(HAVE_WMEMSET)|g' \ + -e 's|@''HAVE_WCSLEN''@|$(HAVE_WCSLEN)|g' \ + -e 's|@''HAVE_WCSNLEN''@|$(HAVE_WCSNLEN)|g' \ + -e 's|@''HAVE_WCSCPY''@|$(HAVE_WCSCPY)|g' \ + -e 's|@''HAVE_WCPCPY''@|$(HAVE_WCPCPY)|g' \ + -e 's|@''HAVE_WCSNCPY''@|$(HAVE_WCSNCPY)|g' \ + -e 's|@''HAVE_WCPNCPY''@|$(HAVE_WCPNCPY)|g' \ + -e 's|@''HAVE_WCSCAT''@|$(HAVE_WCSCAT)|g' \ + -e 's|@''HAVE_WCSNCAT''@|$(HAVE_WCSNCAT)|g' \ + -e 's|@''HAVE_WCSCMP''@|$(HAVE_WCSCMP)|g' \ + -e 's|@''HAVE_WCSNCMP''@|$(HAVE_WCSNCMP)|g' \ + -e 's|@''HAVE_WCSCASECMP''@|$(HAVE_WCSCASECMP)|g' \ + -e 's|@''HAVE_WCSNCASECMP''@|$(HAVE_WCSNCASECMP)|g' \ + -e 's|@''HAVE_WCSCOLL''@|$(HAVE_WCSCOLL)|g' \ + -e 's|@''HAVE_WCSXFRM''@|$(HAVE_WCSXFRM)|g' \ + -e 's|@''HAVE_WCSDUP''@|$(HAVE_WCSDUP)|g' \ + -e 's|@''HAVE_WCSCHR''@|$(HAVE_WCSCHR)|g' \ + -e 's|@''HAVE_WCSRCHR''@|$(HAVE_WCSRCHR)|g' \ + -e 's|@''HAVE_WCSCSPN''@|$(HAVE_WCSCSPN)|g' \ + -e 's|@''HAVE_WCSSPN''@|$(HAVE_WCSSPN)|g' \ + -e 's|@''HAVE_WCSPBRK''@|$(HAVE_WCSPBRK)|g' \ + -e 's|@''HAVE_WCSSTR''@|$(HAVE_WCSSTR)|g' \ + -e 's|@''HAVE_WCSTOK''@|$(HAVE_WCSTOK)|g' \ + -e 's|@''HAVE_WCSWIDTH''@|$(HAVE_WCSWIDTH)|g' \ + -e 's|@''HAVE_DECL_WCTOB''@|$(HAVE_DECL_WCTOB)|g' \ + -e 's|@''HAVE_DECL_WCWIDTH''@|$(HAVE_DECL_WCWIDTH)|g' \ + | \ + sed -e 's|@''REPLACE_MBSTATE_T''@|$(REPLACE_MBSTATE_T)|g' \ + -e 's|@''REPLACE_BTOWC''@|$(REPLACE_BTOWC)|g' \ + -e 's|@''REPLACE_WCTOB''@|$(REPLACE_WCTOB)|g' \ + -e 's|@''REPLACE_MBSINIT''@|$(REPLACE_MBSINIT)|g' \ + -e 's|@''REPLACE_MBRTOWC''@|$(REPLACE_MBRTOWC)|g' \ + -e 's|@''REPLACE_MBRLEN''@|$(REPLACE_MBRLEN)|g' \ + -e 's|@''REPLACE_MBSRTOWCS''@|$(REPLACE_MBSRTOWCS)|g' \ + -e 's|@''REPLACE_MBSNRTOWCS''@|$(REPLACE_MBSNRTOWCS)|g' \ + -e 's|@''REPLACE_WCRTOMB''@|$(REPLACE_WCRTOMB)|g' \ + -e 's|@''REPLACE_WCSRTOMBS''@|$(REPLACE_WCSRTOMBS)|g' \ + -e 's|@''REPLACE_WCSNRTOMBS''@|$(REPLACE_WCSNRTOMBS)|g' \ + -e 's|@''REPLACE_WCWIDTH''@|$(REPLACE_WCWIDTH)|g' \ + -e 's|@''REPLACE_WCSWIDTH''@|$(REPLACE_WCSWIDTH)|g' \ + -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)'; \ + } > $@-t && \ + mv $@-t $@ +MOSTLYCLEANFILES += wchar.h wchar.h-t + +EXTRA_DIST += wchar.in.h + +## end gnulib module wchar + +## begin gnulib module wctype-h + +BUILT_SOURCES += wctype.h +libgettextlib_la_SOURCES += wctype-h.c + +# We need the following in order to create when the system +# doesn't have one that works with the given compiler. +wctype.h: wctype.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(WARN_ON_USE_H) + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's/@''HAVE_WCTYPE_H''@/$(HAVE_WCTYPE_H)/g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_WCTYPE_H''@|$(NEXT_WCTYPE_H)|g' \ + -e 's/@''GNULIB_ISWBLANK''@/$(GNULIB_ISWBLANK)/g' \ + -e 's/@''GNULIB_WCTYPE''@/$(GNULIB_WCTYPE)/g' \ + -e 's/@''GNULIB_ISWCTYPE''@/$(GNULIB_ISWCTYPE)/g' \ + -e 's/@''GNULIB_WCTRANS''@/$(GNULIB_WCTRANS)/g' \ + -e 's/@''GNULIB_TOWCTRANS''@/$(GNULIB_TOWCTRANS)/g' \ + -e 's/@''HAVE_ISWBLANK''@/$(HAVE_ISWBLANK)/g' \ + -e 's/@''HAVE_ISWCNTRL''@/$(HAVE_ISWCNTRL)/g' \ + -e 's/@''HAVE_WCTYPE_T''@/$(HAVE_WCTYPE_T)/g' \ + -e 's/@''HAVE_WCTRANS_T''@/$(HAVE_WCTRANS_T)/g' \ + -e 's/@''HAVE_WINT_T''@/$(HAVE_WINT_T)/g' \ + -e 's/@''REPLACE_ISWBLANK''@/$(REPLACE_ISWBLANK)/g' \ + -e 's/@''REPLACE_ISWCNTRL''@/$(REPLACE_ISWCNTRL)/g' \ + -e 's/@''REPLACE_TOWLOWER''@/$(REPLACE_TOWLOWER)/g' \ + -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ + < $(srcdir)/wctype.in.h; \ + } > $@-t && \ + mv $@-t $@ +MOSTLYCLEANFILES += wctype.h wctype.h-t + +EXTRA_DIST += wctype.in.h + +## end gnulib module wctype-h + +## begin gnulib module wcwidth + + +EXTRA_DIST += wcwidth.c + +EXTRA_libgettextlib_la_SOURCES += wcwidth.c + +## end gnulib module wcwidth + +## begin gnulib module write + + +EXTRA_DIST += write.c + +EXTRA_libgettextlib_la_SOURCES += write.c + +## end gnulib module write + +## begin gnulib module xalloc + +libgettextlib_la_SOURCES += xalloc.h xmalloc.c xstrdup.c + +## end gnulib module xalloc + +## begin gnulib module xconcat-filename + +libgettextlib_la_SOURCES += xconcat-filename.c + +EXTRA_DIST += concat-filename.h + +## end gnulib module xconcat-filename + +## begin gnulib module xerror + +libgettextlib_la_SOURCES += xerror.h xerror.c + +## end gnulib module xerror + +## begin gnulib module xlist + +libgettextlib_la_SOURCES += gl_xlist.h gl_xlist.c + +## end gnulib module xlist + +## begin gnulib module xmalloca + +libgettextlib_la_SOURCES += xmalloca.c + +EXTRA_DIST += xmalloca.h + +## end gnulib module xmalloca + +## begin gnulib module xreadlink + +libgettextlib_la_SOURCES += xreadlink.c + +EXTRA_DIST += xreadlink.h + +## end gnulib module xreadlink + +## begin gnulib module xsetenv + +libgettextlib_la_SOURCES += xsetenv.h xsetenv.c + +## end gnulib module xsetenv + +## begin gnulib module xsize + +libgettextlib_la_SOURCES += xsize.h xsize.c + +## end gnulib module xsize + +## begin gnulib module xstriconv + +libgettextlib_la_SOURCES += xstriconv.h xstriconv.c + +## end gnulib module xstriconv + +## begin gnulib module xstriconveh + +libgettextlib_la_SOURCES += xstriconveh.c + +EXTRA_DIST += xstriconveh.h + +## end gnulib module xstriconveh + +## begin gnulib module xvasprintf + +libgettextlib_la_SOURCES += xvasprintf.h xvasprintf.c xasprintf.c + +EXTRA_DIST += xalloc.h + +## end gnulib module xvasprintf + + +mostlyclean-local: mostlyclean-generic + @for dir in '' $(MOSTLYCLEANDIRS); do \ + if test -n "$$dir" && test -d $$dir; then \ + echo "rmdir $$dir"; rmdir $$dir; \ + fi; \ + done; \ + : diff --git a/gettext-tools/gnulib-lib/Makefile.in b/gettext-tools/gnulib-lib/Makefile.in new file mode 100644 index 0000000..df82ec7 --- /dev/null +++ b/gettext-tools/gnulib-lib/Makefile.in @@ -0,0 +1,5013 @@ +# Makefile.in generated by automake 1.14.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2013 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Copyright (C) 2002-2014 Free Software Foundation, Inc. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This file is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this file. If not, see . +# +# As a special exception to the GNU General Public License, +# this file may be distributed as part of a program that +# contains a configuration script generated by Autoconf, under +# the same distribution terms as the rest of that program. +# +# Generated by gnulib-tool. +# Reproduce by: gnulib-tool --import --dir=gettext-tools --local-dir=gnulib-local --lib=libgettextlib --source-base=gnulib-lib --m4-base=gnulib-m4 --doc-base=doc --tests-base=gnulib-tests --aux-dir=../build-aux --with-tests --avoid=hash-tests --avoid=unilbrk/u8-possible-linebreaks-tests --avoid=unilbrk/ulc-width-linebreaks-tests --avoid=unistr/u8-mbtouc-tests --avoid=unistr/u8-mbtouc-unsafe-tests --avoid=uniwidth/width-tests --makefile-name=Makefile.gnulib --no-conditional-dependencies --libtool --macro-prefix=gl alloca-opt ansi-c++-opt atexit backupfile basename binary-io bison-i18n byteswap c-ctype c-strcase c-strcasestr c-strstr clean-temp closedir closeout copy-file csharpcomp csharpcomp-script csharpexec csharpexec-script error error-progname execute extensions fd-ostream file-ostream filename findprog fnmatch fopen fstrcmp full-write fwriteerror gcd gcj getline getopt-gnu gettext-h gettext-tools-misc hash html-styled-ostream iconv include_next java javacomp javacomp-script javaexec javaexec-script libunistring-optional localcharset locale localename lock malloc-posix mbrtowc mbsinit memmove memset minmax multiarch obstack open opendir openmp ostream pipe-filter-ii progname propername readdir relocatable-prog relocatable-script setlocale sh-quote sigpipe sigprocmask snippet/arg-nonnull snippet/c++defs snippet/warn-on-use spawn-pipe ssize_t stdbool stddef stdint stdio stdlib stpcpy stpncpy strcspn streq strerror strpbrk strtol strtoul styled-ostream sys_select sys_stat sys_time term-styled-ostream unilbrk/ulc-width-linebreaks uniname/uniname unistd unistr/u16-mbtouc unistr/u8-mbtouc unistr/u8-mbtoucr unistr/u8-uctomb uniwidth/width unlocked-io vasprintf verify wait-process wchar wctype-h write xalloc xconcat-filename xerror xmalloca xsetenv xstriconv xstriconveh xvasprintf + + +VPATH = @srcdir@ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ + +# Parametrization of the 'libxml' module: +# When building a shared library, don't export the variables +# xmlMalloc, xmlMallocAtomic, xmlRealloc, xmlFree, xmlMemStrdup. +@INCLUDED_LIBXML_TRUE@am__append_1 = -DLIBXML_STATIC +DIST_COMMON = $(srcdir)/Makefile.gnulib $(srcdir)/Makefile.in \ + $(srcdir)/Makefile.am $(top_srcdir)/../build-aux/mkinstalldirs + +# Tell the mingw or Cygwin linker which symbols to export. +@WOE32DLL_TRUE@am__append_2 = ../woe32dll/gettextlib-exports.c +@WOE32DLL_TRUE@am__append_3 = -Wl,--export-all-symbols +@WOE32DLL_TRUE@am__append_4 = @GETTEXTLIB_EXPORTS_FLAGS@ +@WOE32DLL_FALSE@am__append_5 = html-styled-ostream.c +@WOE32DLL_TRUE@am__append_6 = ../woe32dll/c++html-styled-ostream.cc +@INCLUDED_LIBCROCO_TRUE@am__append_7 = -I$(srcdir)/libcroco +@INCLUDED_LIBCROCO_TRUE@am__append_8 = libcroco_rpl.la +@INCLUDED_LIBCROCO_TRUE@am__append_9 = libcroco_rpl.la +@INCLUDED_LIBCROCO_TRUE@am__append_10 = libcroco_rpl.la +@INCLUDED_LIBCROCO_FALSE@am__append_11 = $(INCCROCO) +@GL_COND_LIBTOOL_TRUE@am__append_12 = $(LTLIBCROCO) $(LTLIBGLIB) \ +@GL_COND_LIBTOOL_TRUE@ $(LTLIBXML) $(LTLIBICONV) $(LTLIBICONV) \ +@GL_COND_LIBTOOL_TRUE@ $(LTLIBTERMINFO) +@INCLUDED_LIBGLIB_TRUE@am__append_13 = libglib_rpl.la +@INCLUDED_LIBGLIB_TRUE@am__append_14 = libglib_rpl.la +@INCLUDED_LIBGLIB_TRUE@am__append_15 = libglib_rpl.la +@INCLUDED_LIBXML_TRUE@am__append_16 = libxml_rpl.la +@INCLUDED_LIBXML_TRUE@am__append_17 = libxml_rpl.la +@INCLUDED_LIBXML_TRUE@am__append_18 = libxml_rpl.la +@WOE32DLL_FALSE@am__append_19 = term-styled-ostream.c +@WOE32DLL_TRUE@am__append_20 = ../woe32dll/c++term-styled-ostream.cc +@LIBUNISTRING_COMPILE_UNICONV_U8_CONV_FROM_ENC_TRUE@am__append_21 = uniconv/u8-conv-from-enc.c +@LIBUNISTRING_COMPILE_UNILBRK_U8_POSSIBLE_LINEBREAKS_TRUE@am__append_22 = unilbrk/u8-possible-linebreaks.c +@LIBUNISTRING_COMPILE_UNILBRK_U8_WIDTH_LINEBREAKS_TRUE@am__append_23 = unilbrk/u8-width-linebreaks.c +@LIBUNISTRING_COMPILE_UNILBRK_ULC_WIDTH_LINEBREAKS_TRUE@am__append_24 = unilbrk/ulc-width-linebreaks.c +@LIBUNISTRING_COMPILE_UNINAME_UNINAME_TRUE@am__append_25 = uniname/uniname.c +@LIBUNISTRING_COMPILE_UNISTR_U16_MBTOUC_TRUE@am__append_26 = unistr/u16-mbtouc.c unistr/u16-mbtouc-aux.c +@LIBUNISTRING_COMPILE_UNISTR_U8_CHECK_TRUE@am__append_27 = unistr/u8-check.c +@LIBUNISTRING_COMPILE_UNISTR_U8_MBLEN_TRUE@am__append_28 = unistr/u8-mblen.c +@LIBUNISTRING_COMPILE_UNISTR_U8_MBTOUC_TRUE@am__append_29 = unistr/u8-mbtouc.c unistr/u8-mbtouc-aux.c +@LIBUNISTRING_COMPILE_UNISTR_U8_MBTOUC_UNSAFE_TRUE@am__append_30 = unistr/u8-mbtouc-unsafe.c unistr/u8-mbtouc-unsafe-aux.c +@LIBUNISTRING_COMPILE_UNISTR_U8_MBTOUCR_TRUE@am__append_31 = unistr/u8-mbtoucr.c +@LIBUNISTRING_COMPILE_UNISTR_U8_PREV_TRUE@am__append_32 = unistr/u8-prev.c +@LIBUNISTRING_COMPILE_UNISTR_U8_UCTOMB_TRUE@am__append_33 = unistr/u8-uctomb.c unistr/u8-uctomb-aux.c +@LIBUNISTRING_COMPILE_UNIWIDTH_WIDTH_TRUE@am__append_34 = uniwidth/width.c +subdir = gnulib-lib +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = \ + $(top_srcdir)/libgettextpo/gnulib-m4/gnulib-comp.m4 \ + $(top_srcdir)/libgrep/gnulib-m4/gnulib-comp.m4 \ + $(top_srcdir)/libgrep/gnulib-m4/langinfo_h.m4 \ + $(top_srcdir)/libgrep/gnulib-m4/localeconv.m4 \ + $(top_srcdir)/libgrep/gnulib-m4/mbrlen.m4 \ + $(top_srcdir)/libgrep/gnulib-m4/nl_langinfo.m4 \ + $(top_srcdir)/libgrep/gnulib-m4/regex.m4 \ + $(top_srcdir)/gnulib-m4/00gnulib.m4 \ + $(top_srcdir)/gnulib-m4/absolute-header.m4 \ + $(top_srcdir)/gnulib-m4/acl.m4 \ + $(top_srcdir)/gnulib-m4/alloca.m4 \ + $(top_srcdir)/gnulib-m4/ansi-c++.m4 \ + $(top_srcdir)/gnulib-m4/asm-underscore.m4 \ + $(top_srcdir)/gnulib-m4/atexit.m4 \ + $(top_srcdir)/gnulib-m4/backupfile.m4 \ + $(top_srcdir)/gnulib-m4/bison-i18n.m4 \ + $(top_srcdir)/gnulib-m4/btowc.m4 \ + $(top_srcdir)/gnulib-m4/byteswap.m4 \ + $(top_srcdir)/gnulib-m4/canonicalize.m4 \ + $(top_srcdir)/gnulib-m4/close.m4 \ + $(top_srcdir)/gnulib-m4/closedir.m4 \ + $(top_srcdir)/gnulib-m4/configmake.m4 \ + $(top_srcdir)/gnulib-m4/copy-file.m4 \ + $(top_srcdir)/gnulib-m4/csharp.m4 \ + $(top_srcdir)/gnulib-m4/csharpcomp.m4 \ + $(top_srcdir)/gnulib-m4/csharpexec.m4 \ + $(top_srcdir)/gnulib-m4/curses.m4 \ + $(top_srcdir)/gnulib-m4/dirent_h.m4 \ + $(top_srcdir)/gnulib-m4/double-slash-root.m4 \ + $(top_srcdir)/gnulib-m4/dup.m4 $(top_srcdir)/gnulib-m4/dup2.m4 \ + $(top_srcdir)/gnulib-m4/eaccess.m4 \ + $(top_srcdir)/gnulib-m4/eealloc.m4 \ + $(top_srcdir)/gnulib-m4/environ.m4 \ + $(top_srcdir)/gnulib-m4/errno_h.m4 \ + $(top_srcdir)/gnulib-m4/error.m4 \ + $(top_srcdir)/gnulib-m4/execute.m4 \ + $(top_srcdir)/gnulib-m4/exponentd.m4 \ + $(top_srcdir)/gnulib-m4/extensions.m4 \ + $(top_srcdir)/gnulib-m4/fatal-signal.m4 \ + $(top_srcdir)/gnulib-m4/fcntl.m4 \ + $(top_srcdir)/gnulib-m4/fcntl_h.m4 \ + $(top_srcdir)/gnulib-m4/fdopen.m4 \ + $(top_srcdir)/gnulib-m4/findprog.m4 \ + $(top_srcdir)/gnulib-m4/float_h.m4 \ + $(top_srcdir)/gnulib-m4/fnmatch.m4 \ + $(top_srcdir)/gnulib-m4/fopen.m4 \ + $(top_srcdir)/gnulib-m4/fpieee.m4 \ + $(top_srcdir)/gnulib-m4/fseeko.m4 \ + $(top_srcdir)/gnulib-m4/fstat.m4 \ + $(top_srcdir)/gnulib-m4/ftell.m4 \ + $(top_srcdir)/gnulib-m4/ftello.m4 \ + $(top_srcdir)/gnulib-m4/gcj.m4 \ + $(top_srcdir)/gnulib-m4/getcwd.m4 \ + $(top_srcdir)/gnulib-m4/getdelim.m4 \ + $(top_srcdir)/gnulib-m4/getdtablesize.m4 \ + $(top_srcdir)/gnulib-m4/getline.m4 \ + $(top_srcdir)/gnulib-m4/getopt.m4 \ + $(top_srcdir)/gnulib-m4/getpagesize.m4 \ + $(top_srcdir)/gnulib-m4/gettimeofday.m4 \ + $(top_srcdir)/gnulib-m4/gnulib-common.m4 \ + $(top_srcdir)/gnulib-m4/gnulib-comp.m4 \ + $(top_srcdir)/gnulib-m4/iconv_h.m4 \ + $(top_srcdir)/gnulib-m4/iconv_open.m4 \ + $(top_srcdir)/gnulib-m4/include_next.m4 \ + $(top_srcdir)/gnulib-m4/inline.m4 \ + $(top_srcdir)/gnulib-m4/intmax_t.m4 \ + $(top_srcdir)/gnulib-m4/inttypes.m4 \ + $(top_srcdir)/gnulib-m4/iswblank.m4 \ + $(top_srcdir)/gnulib-m4/java.m4 \ + $(top_srcdir)/gnulib-m4/javacomp.m4 \ + $(top_srcdir)/gnulib-m4/javaexec.m4 \ + $(top_srcdir)/gnulib-m4/largefile.m4 \ + $(top_srcdir)/gnulib-m4/lib-ld.m4 \ + $(top_srcdir)/gnulib-m4/lib-link.m4 \ + $(top_srcdir)/gnulib-m4/lib-prefix.m4 \ + $(top_srcdir)/gnulib-m4/libcroco.m4 \ + $(top_srcdir)/gnulib-m4/libglib.m4 \ + $(top_srcdir)/gnulib-m4/libunistring-base.m4 \ + $(top_srcdir)/gnulib-m4/libunistring-optional.m4 \ + $(top_srcdir)/gnulib-m4/libunistring.m4 \ + $(top_srcdir)/gnulib-m4/libxml.m4 \ + $(top_srcdir)/gnulib-m4/localcharset.m4 \ + $(top_srcdir)/gnulib-m4/locale-fr.m4 \ + $(top_srcdir)/gnulib-m4/locale-ja.m4 \ + $(top_srcdir)/gnulib-m4/locale-tr.m4 \ + $(top_srcdir)/gnulib-m4/locale-zh.m4 \ + $(top_srcdir)/gnulib-m4/locale_h.m4 \ + $(top_srcdir)/gnulib-m4/localename.m4 \ + $(top_srcdir)/gnulib-m4/lseek.m4 \ + $(top_srcdir)/gnulib-m4/lstat.m4 \ + $(top_srcdir)/gnulib-m4/malloc.m4 \ + $(top_srcdir)/gnulib-m4/malloca.m4 \ + $(top_srcdir)/gnulib-m4/mbchar.m4 \ + $(top_srcdir)/gnulib-m4/mbiter.m4 \ + $(top_srcdir)/gnulib-m4/mbrtowc.m4 \ + $(top_srcdir)/gnulib-m4/mbsinit.m4 \ + $(top_srcdir)/gnulib-m4/mbslen.m4 \ + $(top_srcdir)/gnulib-m4/mbsrtowcs.m4 \ + $(top_srcdir)/gnulib-m4/mbstate_t.m4 \ + $(top_srcdir)/gnulib-m4/mbswidth.m4 \ + $(top_srcdir)/gnulib-m4/mbtowc.m4 \ + $(top_srcdir)/gnulib-m4/memchr.m4 \ + $(top_srcdir)/gnulib-m4/memmove.m4 \ + $(top_srcdir)/gnulib-m4/memset.m4 \ + $(top_srcdir)/gnulib-m4/minmax.m4 \ + $(top_srcdir)/gnulib-m4/mkdtemp.m4 \ + $(top_srcdir)/gnulib-m4/mmap-anon.m4 \ + $(top_srcdir)/gnulib-m4/mode_t.m4 \ + $(top_srcdir)/gnulib-m4/moo.m4 \ + $(top_srcdir)/gnulib-m4/msvc-inval.m4 \ + $(top_srcdir)/gnulib-m4/msvc-nothrow.m4 \ + $(top_srcdir)/gnulib-m4/multiarch.m4 \ + $(top_srcdir)/gnulib-m4/no-c++.m4 \ + $(top_srcdir)/gnulib-m4/nocrash.m4 \ + $(top_srcdir)/gnulib-m4/obstack.m4 \ + $(top_srcdir)/gnulib-m4/off_t.m4 \ + $(top_srcdir)/gnulib-m4/open.m4 \ + $(top_srcdir)/gnulib-m4/opendir.m4 \ + $(top_srcdir)/gnulib-m4/pathmax.m4 \ + $(top_srcdir)/gnulib-m4/pipe2.m4 \ + $(top_srcdir)/gnulib-m4/posix_spawn.m4 \ + $(top_srcdir)/gnulib-m4/printf.m4 \ + $(top_srcdir)/gnulib-m4/putenv.m4 \ + $(top_srcdir)/gnulib-m4/quote.m4 \ + $(top_srcdir)/gnulib-m4/quotearg.m4 \ + $(top_srcdir)/gnulib-m4/raise.m4 \ + $(top_srcdir)/gnulib-m4/rawmemchr.m4 \ + $(top_srcdir)/gnulib-m4/read-file.m4 \ + $(top_srcdir)/gnulib-m4/read.m4 \ + $(top_srcdir)/gnulib-m4/readdir.m4 \ + $(top_srcdir)/gnulib-m4/readlink.m4 \ + $(top_srcdir)/gnulib-m4/realloc.m4 \ + $(top_srcdir)/gnulib-m4/relocatable-lib.m4 \ + $(top_srcdir)/gnulib-m4/relocatable.m4 \ + $(top_srcdir)/gnulib-m4/rmdir.m4 \ + $(top_srcdir)/gnulib-m4/safe-read.m4 \ + $(top_srcdir)/gnulib-m4/safe-write.m4 \ + $(top_srcdir)/gnulib-m4/sched_h.m4 \ + $(top_srcdir)/gnulib-m4/secure_getenv.m4 \ + $(top_srcdir)/gnulib-m4/setenv.m4 \ + $(top_srcdir)/gnulib-m4/setlocale.m4 \ + $(top_srcdir)/gnulib-m4/sig_atomic_t.m4 \ + $(top_srcdir)/gnulib-m4/sigaction.m4 \ + $(top_srcdir)/gnulib-m4/signal_h.m4 \ + $(top_srcdir)/gnulib-m4/signalblocking.m4 \ + $(top_srcdir)/gnulib-m4/sigpipe.m4 \ + $(top_srcdir)/gnulib-m4/sleep.m4 \ + $(top_srcdir)/gnulib-m4/snprintf.m4 \ + $(top_srcdir)/gnulib-m4/spawn-pipe.m4 \ + $(top_srcdir)/gnulib-m4/spawn_h.m4 \ + $(top_srcdir)/gnulib-m4/ssize_t.m4 \ + $(top_srcdir)/gnulib-m4/stat.m4 \ + $(top_srcdir)/gnulib-m4/stdarg.m4 \ + $(top_srcdir)/gnulib-m4/stdbool.m4 \ + $(top_srcdir)/gnulib-m4/stddef_h.m4 \ + $(top_srcdir)/gnulib-m4/stdint.m4 \ + $(top_srcdir)/gnulib-m4/stdio_h.m4 \ + $(top_srcdir)/gnulib-m4/stdlib_h.m4 \ + $(top_srcdir)/gnulib-m4/stpcpy.m4 \ + $(top_srcdir)/gnulib-m4/stpncpy.m4 \ + $(top_srcdir)/gnulib-m4/strchrnul.m4 \ + $(top_srcdir)/gnulib-m4/strcspn.m4 \ + $(top_srcdir)/gnulib-m4/strerror.m4 \ + $(top_srcdir)/gnulib-m4/string_h.m4 \ + $(top_srcdir)/gnulib-m4/strnlen.m4 \ + $(top_srcdir)/gnulib-m4/strpbrk.m4 \ + $(top_srcdir)/gnulib-m4/strstr.m4 \ + $(top_srcdir)/gnulib-m4/strtol.m4 \ + $(top_srcdir)/gnulib-m4/strtoul.m4 \ + $(top_srcdir)/gnulib-m4/symlink.m4 \ + $(top_srcdir)/gnulib-m4/sys_select_h.m4 \ + $(top_srcdir)/gnulib-m4/sys_socket_h.m4 \ + $(top_srcdir)/gnulib-m4/sys_stat_h.m4 \ + $(top_srcdir)/gnulib-m4/sys_time_h.m4 \ + $(top_srcdir)/gnulib-m4/sys_types_h.m4 \ + $(top_srcdir)/gnulib-m4/sys_wait_h.m4 \ + $(top_srcdir)/gnulib-m4/tempname.m4 \ + $(top_srcdir)/gnulib-m4/term-ostream.m4 \ + $(top_srcdir)/gnulib-m4/terminfo.m4 \ + $(top_srcdir)/gnulib-m4/thread.m4 \ + $(top_srcdir)/gnulib-m4/time_h.m4 \ + $(top_srcdir)/gnulib-m4/tls.m4 \ + $(top_srcdir)/gnulib-m4/tmpdir.m4 \ + $(top_srcdir)/gnulib-m4/ungetc.m4 \ + $(top_srcdir)/gnulib-m4/unionwait.m4 \ + $(top_srcdir)/gnulib-m4/unistd-safer.m4 \ + $(top_srcdir)/gnulib-m4/unistd_h.m4 \ + $(top_srcdir)/gnulib-m4/unlocked-io.m4 \ + $(top_srcdir)/gnulib-m4/vasnprintf.m4 \ + $(top_srcdir)/gnulib-m4/vasprintf.m4 \ + $(top_srcdir)/gnulib-m4/vsnprintf.m4 \ + $(top_srcdir)/gnulib-m4/wait-process.m4 \ + $(top_srcdir)/gnulib-m4/waitpid.m4 \ + $(top_srcdir)/gnulib-m4/warn-on-use.m4 \ + $(top_srcdir)/gnulib-m4/wchar_h.m4 \ + $(top_srcdir)/gnulib-m4/wcrtomb.m4 \ + $(top_srcdir)/gnulib-m4/wctob.m4 \ + $(top_srcdir)/gnulib-m4/wctomb.m4 \ + $(top_srcdir)/gnulib-m4/wctype_h.m4 \ + $(top_srcdir)/gnulib-m4/wcwidth.m4 \ + $(top_srcdir)/gnulib-m4/write.m4 \ + $(top_srcdir)/gnulib-m4/xvasprintf.m4 \ + $(top_srcdir)/gnulib-m4/yield.m4 \ + $(top_srcdir)/../m4/fixautomake.m4 \ + $(top_srcdir)/../m4/libtool.m4 \ + $(top_srcdir)/../m4/ltoptions.m4 \ + $(top_srcdir)/../m4/ltsugar.m4 \ + $(top_srcdir)/../m4/ltversion.m4 \ + $(top_srcdir)/../m4/lt~obsolete.m4 \ + $(top_srcdir)/../m4/woe32-dll.m4 \ + $(top_srcdir)/../gettext-runtime/m4/codeset.m4 \ + $(top_srcdir)/../gettext-runtime/m4/extern-inline.m4 \ + $(top_srcdir)/../gettext-runtime/m4/fcntl-o.m4 \ + $(top_srcdir)/../gettext-runtime/m4/gettext.m4 \ + $(top_srcdir)/../gettext-runtime/m4/glibc2.m4 \ + $(top_srcdir)/../gettext-runtime/m4/glibc21.m4 \ + $(top_srcdir)/../gettext-runtime/m4/iconv.m4 \ + $(top_srcdir)/../gettext-runtime/m4/intdiv0.m4 \ + $(top_srcdir)/../gettext-runtime/m4/intl.m4 \ + $(top_srcdir)/../gettext-runtime/m4/intlmacosx.m4 \ + $(top_srcdir)/../gettext-runtime/m4/intmax.m4 \ + $(top_srcdir)/../gettext-runtime/m4/inttypes-pri.m4 \ + $(top_srcdir)/../gettext-runtime/m4/inttypes_h.m4 \ + $(top_srcdir)/../gettext-runtime/m4/lcmessage.m4 \ + $(top_srcdir)/../gettext-runtime/m4/lock.m4 \ + $(top_srcdir)/../gettext-runtime/m4/longlong.m4 \ + $(top_srcdir)/../gettext-runtime/m4/nls.m4 \ + $(top_srcdir)/../gettext-runtime/m4/po.m4 \ + $(top_srcdir)/../gettext-runtime/m4/printf-posix.m4 \ + $(top_srcdir)/../gettext-runtime/m4/progtest.m4 \ + $(top_srcdir)/../gettext-runtime/m4/size_max.m4 \ + $(top_srcdir)/../gettext-runtime/m4/stdint_h.m4 \ + $(top_srcdir)/../gettext-runtime/m4/threadlib.m4 \ + $(top_srcdir)/../gettext-runtime/m4/uintmax_t.m4 \ + $(top_srcdir)/../gettext-runtime/m4/visibility.m4 \ + $(top_srcdir)/../gettext-runtime/m4/wchar_t.m4 \ + $(top_srcdir)/../gettext-runtime/m4/wint_t.m4 \ + $(top_srcdir)/../gettext-runtime/m4/xsize.m4 \ + $(top_srcdir)/m4/exported.m4 $(top_srcdir)/m4/hostname.m4 \ + $(top_srcdir)/m4/setlocale.m4 $(top_srcdir)/m4/siginfo.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/../build-aux/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(gettextsrcdir)" \ + "$(DESTDIR)$(pkgdatadir)" +LTLIBRARIES = $(lib_LTLIBRARIES) $(noinst_LTLIBRARIES) +libcroco_rpl_la_LIBADD = +am__dirstamp = $(am__leading_dot)dirstamp +am_libcroco_rpl_la_OBJECTS = \ + libcroco/libcroco_rpl_la-cr-additional-sel.lo \ + libcroco/libcroco_rpl_la-cr-attr-sel.lo \ + libcroco/libcroco_rpl_la-cr-cascade.lo \ + libcroco/libcroco_rpl_la-cr-declaration.lo \ + libcroco/libcroco_rpl_la-cr-doc-handler.lo \ + libcroco/libcroco_rpl_la-cr-enc-handler.lo \ + libcroco/libcroco_rpl_la-cr-fonts.lo \ + libcroco/libcroco_rpl_la-cr-input.lo \ + libcroco/libcroco_rpl_la-cr-num.lo \ + libcroco/libcroco_rpl_la-cr-om-parser.lo \ + libcroco/libcroco_rpl_la-cr-parser.lo \ + libcroco/libcroco_rpl_la-cr-parsing-location.lo \ + libcroco/libcroco_rpl_la-cr-prop-list.lo \ + libcroco/libcroco_rpl_la-cr-pseudo.lo \ + libcroco/libcroco_rpl_la-cr-rgb.lo \ + libcroco/libcroco_rpl_la-cr-sel-eng.lo \ + libcroco/libcroco_rpl_la-cr-selector.lo \ + libcroco/libcroco_rpl_la-cr-simple-sel.lo \ + libcroco/libcroco_rpl_la-cr-statement.lo \ + libcroco/libcroco_rpl_la-cr-string.lo \ + libcroco/libcroco_rpl_la-cr-style.lo \ + libcroco/libcroco_rpl_la-cr-stylesheet.lo \ + libcroco/libcroco_rpl_la-cr-term.lo \ + libcroco/libcroco_rpl_la-cr-tknzr.lo \ + libcroco/libcroco_rpl_la-cr-token.lo \ + libcroco/libcroco_rpl_la-cr-utils.lo +libcroco_rpl_la_OBJECTS = $(am_libcroco_rpl_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +@INCLUDED_LIBCROCO_TRUE@am_libcroco_rpl_la_rpath = +am__DEPENDENCIES_1 = +am__libgettextlib_la_SOURCES_DIST = copy-acl.c set-acl.c allocator.c \ + areadlink.c argmatch.c gl_array_list.h gl_array_list.c \ + backupfile.h backupfile.c addext.c basename.h basename.c \ + binary-io.h binary-io.c c-ctype.h c-ctype.c c-strcase.h \ + c-strcasecmp.c c-strncasecmp.c c-strcasestr.h c-strcasestr.c \ + c-strstr.h c-strstr.c careadlinkat.c classpath.h classpath.c \ + clean-temp.h clean-temp.c cloexec.c closeout.h closeout.c \ + concat-filename.c copy-file.h copy-file.c csharpcomp.h \ + csharpcomp.c csharpexec.h csharpexec.c diffseq.h \ + error-progname.h error-progname.c execute.h execute.c \ + w32spawn.h exitfail.c fatal-signal.h fatal-signal.c fd-hook.c \ + fd-ostream.c fd-safer-flag.c dup-safer-flag.c file-ostream.c \ + findprog.h findprog.c fstrcmp.h fstrcmp.c full-write.h \ + full-write.c fwriteerror.h fwriteerror.c gcd.h gcd.c gettext.h \ + ../woe32dll/gettextlib-exports.c hash.h hash.c html-ostream.c \ + html-styled-ostream.c ../woe32dll/c++html-styled-ostream.cc \ + javacomp.h javacomp.c javaexec.h javaexec.c javaversion.h \ + javaversion.c gl_linkedhash_list.h gl_linkedhash_list.c \ + gl_anyhash_list1.h gl_anyhash_list2.h gl_anylinked_list1.h \ + gl_anylinked_list2.h gl_list.h gl_list.c localcharset.h \ + localcharset.c localename.c glthread/lock.h glthread/lock.c \ + malloca.c mbchar.c mbiter.h mbiter.c mbslen.c mbsstr.c \ + mbswidth.h mbswidth.c mbuiter.h mbuiter.c minmax.h ostream.c \ + pipe-filter-ii.c pipe-filter-aux.c pipe2.c pipe2-safer.c \ + progname.h progname.c propername.h propername.c \ + acl-errno-valid.c file-has-acl.c qcopy-acl.c qset-acl.c \ + quotearg.c safe-read.c safe-write.c sh-quote.h sh-quote.c \ + sig-handler.c size_max.h spawn-pipe.h spawn-pipe.c striconv.h \ + striconv.c striconveh.h striconveh.c striconveha.h \ + striconveha.c strnlen1.h strnlen1.c styled-ostream.c \ + tempname.c term-ostream.c term-styled-ostream.c \ + ../woe32dll/c++term-styled-ostream.cc glthread/threadlib.c \ + glthread/tls.h glthread/tls.c tmpdir.h tmpdir.c trim.c \ + uniconv/u8-conv-from-enc.c unilbrk/lbrktables.c \ + unilbrk/u8-possible-linebreaks.c unilbrk/u8-width-linebreaks.c \ + unilbrk/ulc-common.c unilbrk/ulc-width-linebreaks.c \ + uniname/uniname.c unistd.c dup-safer.c fd-safer.c pipe-safer.c \ + unistr/u16-mbtouc.c unistr/u16-mbtouc-aux.c unistr/u8-check.c \ + unistr/u8-mblen.c unistr/u8-mbtouc.c unistr/u8-mbtouc-aux.c \ + unistr/u8-mbtouc-unsafe.c unistr/u8-mbtouc-unsafe-aux.c \ + unistr/u8-mbtoucr.c unistr/u8-prev.c unistr/u8-uctomb.c \ + unistr/u8-uctomb-aux.c uniwidth/width.c wait-process.h \ + wait-process.c wctype-h.c xalloc.h xmalloc.c xstrdup.c \ + xconcat-filename.c xerror.h xerror.c gl_xlist.h gl_xlist.c \ + xmalloca.c xreadlink.c xsetenv.h xsetenv.c xsize.h xsize.c \ + xstriconv.h xstriconv.c xstriconveh.c xvasprintf.h \ + xvasprintf.c xasprintf.c +@WOE32DLL_TRUE@am__objects_1 = ../woe32dll/gettextlib-exports.lo +@WOE32DLL_FALSE@am__objects_2 = html-styled-ostream.lo +@WOE32DLL_TRUE@am__objects_3 = ../woe32dll/c++html-styled-ostream.lo +@WOE32DLL_FALSE@am__objects_4 = term-styled-ostream.lo +@WOE32DLL_TRUE@am__objects_5 = ../woe32dll/c++term-styled-ostream.lo +@LIBUNISTRING_COMPILE_UNICONV_U8_CONV_FROM_ENC_TRUE@am__objects_6 = uniconv/u8-conv-from-enc.lo +@LIBUNISTRING_COMPILE_UNILBRK_U8_POSSIBLE_LINEBREAKS_TRUE@am__objects_7 = unilbrk/u8-possible-linebreaks.lo +@LIBUNISTRING_COMPILE_UNILBRK_U8_WIDTH_LINEBREAKS_TRUE@am__objects_8 = unilbrk/u8-width-linebreaks.lo +@LIBUNISTRING_COMPILE_UNILBRK_ULC_WIDTH_LINEBREAKS_TRUE@am__objects_9 = unilbrk/ulc-width-linebreaks.lo +@LIBUNISTRING_COMPILE_UNINAME_UNINAME_TRUE@am__objects_10 = \ +@LIBUNISTRING_COMPILE_UNINAME_UNINAME_TRUE@ uniname/uniname.lo +@LIBUNISTRING_COMPILE_UNISTR_U16_MBTOUC_TRUE@am__objects_11 = unistr/u16-mbtouc.lo \ +@LIBUNISTRING_COMPILE_UNISTR_U16_MBTOUC_TRUE@ unistr/u16-mbtouc-aux.lo +@LIBUNISTRING_COMPILE_UNISTR_U8_CHECK_TRUE@am__objects_12 = \ +@LIBUNISTRING_COMPILE_UNISTR_U8_CHECK_TRUE@ unistr/u8-check.lo +@LIBUNISTRING_COMPILE_UNISTR_U8_MBLEN_TRUE@am__objects_13 = \ +@LIBUNISTRING_COMPILE_UNISTR_U8_MBLEN_TRUE@ unistr/u8-mblen.lo +@LIBUNISTRING_COMPILE_UNISTR_U8_MBTOUC_TRUE@am__objects_14 = unistr/u8-mbtouc.lo \ +@LIBUNISTRING_COMPILE_UNISTR_U8_MBTOUC_TRUE@ unistr/u8-mbtouc-aux.lo +@LIBUNISTRING_COMPILE_UNISTR_U8_MBTOUC_UNSAFE_TRUE@am__objects_15 = unistr/u8-mbtouc-unsafe.lo \ +@LIBUNISTRING_COMPILE_UNISTR_U8_MBTOUC_UNSAFE_TRUE@ unistr/u8-mbtouc-unsafe-aux.lo +@LIBUNISTRING_COMPILE_UNISTR_U8_MBTOUCR_TRUE@am__objects_16 = unistr/u8-mbtoucr.lo +@LIBUNISTRING_COMPILE_UNISTR_U8_PREV_TRUE@am__objects_17 = \ +@LIBUNISTRING_COMPILE_UNISTR_U8_PREV_TRUE@ unistr/u8-prev.lo +@LIBUNISTRING_COMPILE_UNISTR_U8_UCTOMB_TRUE@am__objects_18 = unistr/u8-uctomb.lo \ +@LIBUNISTRING_COMPILE_UNISTR_U8_UCTOMB_TRUE@ unistr/u8-uctomb-aux.lo +@LIBUNISTRING_COMPILE_UNIWIDTH_WIDTH_TRUE@am__objects_19 = \ +@LIBUNISTRING_COMPILE_UNIWIDTH_WIDTH_TRUE@ uniwidth/width.lo +am_libgettextlib_la_OBJECTS = copy-acl.lo set-acl.lo allocator.lo \ + areadlink.lo argmatch.lo gl_array_list.lo backupfile.lo \ + addext.lo basename.lo binary-io.lo c-ctype.lo c-strcasecmp.lo \ + c-strncasecmp.lo c-strcasestr.lo c-strstr.lo careadlinkat.lo \ + classpath.lo clean-temp.lo cloexec.lo closeout.lo \ + concat-filename.lo copy-file.lo csharpcomp.lo csharpexec.lo \ + error-progname.lo execute.lo exitfail.lo fatal-signal.lo \ + fd-hook.lo fd-ostream.lo fd-safer-flag.lo dup-safer-flag.lo \ + file-ostream.lo findprog.lo fstrcmp.lo full-write.lo \ + fwriteerror.lo gcd.lo $(am__objects_1) hash.lo html-ostream.lo \ + $(am__objects_2) $(am__objects_3) javacomp.lo javaexec.lo \ + javaversion.lo gl_linkedhash_list.lo gl_list.lo \ + localcharset.lo localename.lo glthread/lock.lo malloca.lo \ + mbchar.lo mbiter.lo mbslen.lo mbsstr.lo mbswidth.lo mbuiter.lo \ + ostream.lo pipe-filter-ii.lo pipe-filter-aux.lo pipe2.lo \ + pipe2-safer.lo progname.lo propername.lo acl-errno-valid.lo \ + file-has-acl.lo qcopy-acl.lo qset-acl.lo quotearg.lo \ + safe-read.lo safe-write.lo sh-quote.lo sig-handler.lo \ + spawn-pipe.lo striconv.lo striconveh.lo striconveha.lo \ + strnlen1.lo styled-ostream.lo tempname.lo term-ostream.lo \ + $(am__objects_4) $(am__objects_5) glthread/threadlib.lo \ + glthread/tls.lo tmpdir.lo trim.lo $(am__objects_6) \ + unilbrk/lbrktables.lo $(am__objects_7) $(am__objects_8) \ + unilbrk/ulc-common.lo $(am__objects_9) $(am__objects_10) \ + unistd.lo dup-safer.lo fd-safer.lo pipe-safer.lo \ + $(am__objects_11) $(am__objects_12) $(am__objects_13) \ + $(am__objects_14) $(am__objects_15) $(am__objects_16) \ + $(am__objects_17) $(am__objects_18) $(am__objects_19) \ + wait-process.lo wctype-h.lo xmalloc.lo xstrdup.lo \ + xconcat-filename.lo xerror.lo gl_xlist.lo xmalloca.lo \ + xreadlink.lo xsetenv.lo xsize.lo xstriconv.lo xstriconveh.lo \ + xvasprintf.lo xasprintf.lo +libgettextlib_la_OBJECTS = $(am_libgettextlib_la_OBJECTS) +libglib_rpl_la_LIBADD = +am_libglib_rpl_la_OBJECTS = glib/libglib_rpl_la-ghash.lo \ + glib/libglib_rpl_la-glist.lo glib/libglib_rpl_la-gmessages.lo \ + glib/libglib_rpl_la-gprimes.lo \ + glib/libglib_rpl_la-gstrfuncs.lo \ + glib/libglib_rpl_la-gstring.lo +libglib_rpl_la_OBJECTS = $(am_libglib_rpl_la_OBJECTS) +@INCLUDED_LIBGLIB_TRUE@am_libglib_rpl_la_rpath = +libxml_rpl_la_LIBADD = +am_libxml_rpl_la_OBJECTS = libxml/libxml_rpl_la-DOCBparser.lo \ + libxml/libxml_rpl_la-HTMLparser.lo \ + libxml/libxml_rpl_la-HTMLtree.lo libxml/libxml_rpl_la-SAX.lo \ + libxml/libxml_rpl_la-SAX2.lo libxml/libxml_rpl_la-c14n.lo \ + libxml/libxml_rpl_la-catalog.lo \ + libxml/libxml_rpl_la-chvalid.lo \ + libxml/libxml_rpl_la-debugXML.lo libxml/libxml_rpl_la-dict.lo \ + libxml/libxml_rpl_la-encoding.lo \ + libxml/libxml_rpl_la-entities.lo libxml/libxml_rpl_la-error.lo \ + libxml/libxml_rpl_la-globals.lo libxml/libxml_rpl_la-hash.lo \ + libxml/libxml_rpl_la-legacy.lo libxml/libxml_rpl_la-list.lo \ + libxml/libxml_rpl_la-nanoftp.lo \ + libxml/libxml_rpl_la-nanohttp.lo \ + libxml/libxml_rpl_la-parser.lo \ + libxml/libxml_rpl_la-parserInternals.lo \ + libxml/libxml_rpl_la-pattern.lo \ + libxml/libxml_rpl_la-relaxng.lo \ + libxml/libxml_rpl_la-schematron.lo \ + libxml/libxml_rpl_la-threads.lo libxml/libxml_rpl_la-tree.lo \ + libxml/libxml_rpl_la-uri.lo libxml/libxml_rpl_la-valid.lo \ + libxml/libxml_rpl_la-xinclude.lo libxml/libxml_rpl_la-xlink.lo \ + libxml/libxml_rpl_la-xmlIO.lo \ + libxml/libxml_rpl_la-xmlmemory.lo \ + libxml/libxml_rpl_la-xmlmodule.lo \ + libxml/libxml_rpl_la-xmlreader.lo \ + libxml/libxml_rpl_la-xmlregexp.lo \ + libxml/libxml_rpl_la-xmlsave.lo \ + libxml/libxml_rpl_la-xmlschemas.lo \ + libxml/libxml_rpl_la-xmlschemastypes.lo \ + libxml/libxml_rpl_la-xmlstring.lo \ + libxml/libxml_rpl_la-xmlunicode.lo \ + libxml/libxml_rpl_la-xmlwriter.lo \ + libxml/libxml_rpl_la-xpath.lo libxml/libxml_rpl_la-xpointer.lo +libxml_rpl_la_OBJECTS = $(am_libxml_rpl_la_OBJECTS) +@INCLUDED_LIBXML_TRUE@am_libxml_rpl_la_rpath = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = +am__depfiles_maybe = +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_CXX = $(am__v_CXX_@AM_V@) +am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) +am__v_CXX_0 = @echo " CXX " $@; +am__v_CXX_1 = +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) +am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) +am__v_CXXLD_0 = @echo " CXXLD " $@; +am__v_CXXLD_1 = +SOURCES = $(libcroco_rpl_la_SOURCES) $(libgettextlib_la_SOURCES) \ + $(EXTRA_libgettextlib_la_SOURCES) $(libglib_rpl_la_SOURCES) \ + $(libxml_rpl_la_SOURCES) +DIST_SOURCES = $(libcroco_rpl_la_SOURCES) \ + $(am__libgettextlib_la_SOURCES_DIST) \ + $(EXTRA_libgettextlib_la_SOURCES) $(libglib_rpl_la_SOURCES) \ + $(libxml_rpl_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +DATA = $(gettextsrc_DATA) $(pkgdata_DATA) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +# Where to install javaversion.class. +pkgdatadir = $(datadir)/gettext +pkglibexecdir = @pkglibexecdir@ +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +ALLOCA_H = @ALLOCA_H@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +APPLE_UNIVERSAL_BUILD = @APPLE_UNIVERSAL_BUILD@ +AR = @AR@ +ARCHIVE_FORMAT = @ARCHIVE_FORMAT@ +ARFLAGS = @ARFLAGS@ +AS = @AS@ +ASM_SYMBOL_PREFIX = @ASM_SYMBOL_PREFIX@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BISON_LOCALEDIR = @BISON_LOCALEDIR@ +BITSIZEOF_PTRDIFF_T = @BITSIZEOF_PTRDIFF_T@ +BITSIZEOF_SIG_ATOMIC_T = @BITSIZEOF_SIG_ATOMIC_T@ +BITSIZEOF_SIZE_T = @BITSIZEOF_SIZE_T@ +BITSIZEOF_WCHAR_T = @BITSIZEOF_WCHAR_T@ +BITSIZEOF_WINT_T = @BITSIZEOF_WINT_T@ +BUILDCSHARP = @BUILDCSHARP@ +BUILDJAVA = @BUILDJAVA@ +BUILDJAVAEXE = @BUILDJAVAEXE@ +BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@ +BYTESWAP_H = @BYTESWAP_H@ +CATOBJEXT = @CATOBJEXT@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CFLAG_VISIBILITY = @CFLAG_VISIBILITY@ +CLASSPATH = @CLASSPATH@ +CLASSPATH_SEPARATOR = @CLASSPATH_SEPARATOR@ +CLIX_PATH = @CLIX_PATH@ +CLIX_PATH_VAR = @CLIX_PATH_VAR@ +CONF_JAVA = @CONF_JAVA@ +CONF_JAVAC = @CONF_JAVAC@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CROSS_COMPILING = @CROSS_COMPILING@ +CSHARPCOMPFLAGS = @CSHARPCOMPFLAGS@ +CSHARP_CHOICE = @CSHARP_CHOICE@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CXX_CHOICE = @CXX_CHOICE@ +CYGPATH_W = @CYGPATH_W@ +DATADIRNAME = @DATADIRNAME@ +DEFS = @DEFS@ -DEXEEXT=\"@EXEEXT@\" -DEXEEXT=\"@EXEEXT@\" \ + -DEXEEXT=\"@EXEEXT@\" +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DVIPS = @DVIPS@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EMACS = @EMACS@ +EMACSLOADPATH = @EMACSLOADPATH@ +EMULTIHOP_HIDDEN = @EMULTIHOP_HIDDEN@ +EMULTIHOP_VALUE = @EMULTIHOP_VALUE@ +ENOLINK_HIDDEN = @ENOLINK_HIDDEN@ +ENOLINK_VALUE = @ENOLINK_VALUE@ +EOVERFLOW_HIDDEN = @EOVERFLOW_HIDDEN@ +EOVERFLOW_VALUE = @EOVERFLOW_VALUE@ +ERRNO_H = @ERRNO_H@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FLOAT_H = @FLOAT_H@ +FNMATCH_H = @FNMATCH_H@ +GCJ = @GCJ@ +GCJFLAGS = @GCJFLAGS@ +GENCAT = @GENCAT@ +GETOPT_H = @GETOPT_H@ +GETTEXTLIB_EXPORTS_FLAGS = @GETTEXTLIB_EXPORTS_FLAGS@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GLIBC2 = @GLIBC2@ +GLIBC21 = @GLIBC21@ +GLOBAL_SYMBOL_PIPE = @GLOBAL_SYMBOL_PIPE@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GNULIB_ALPHASORT = @GNULIB_ALPHASORT@ +GNULIB_ATOLL = @GNULIB_ATOLL@ +GNULIB_BTOWC = @GNULIB_BTOWC@ +GNULIB_CALLOC_POSIX = @GNULIB_CALLOC_POSIX@ +GNULIB_CANONICALIZE_FILE_NAME = @GNULIB_CANONICALIZE_FILE_NAME@ +GNULIB_CHDIR = @GNULIB_CHDIR@ +GNULIB_CHOWN = @GNULIB_CHOWN@ +GNULIB_CLOSE = @GNULIB_CLOSE@ +GNULIB_CLOSEDIR = @GNULIB_CLOSEDIR@ +GNULIB_DIRFD = @GNULIB_DIRFD@ +GNULIB_DPRINTF = @GNULIB_DPRINTF@ +GNULIB_DUP = @GNULIB_DUP@ +GNULIB_DUP2 = @GNULIB_DUP2@ +GNULIB_DUP3 = @GNULIB_DUP3@ +GNULIB_DUPLOCALE = @GNULIB_DUPLOCALE@ +GNULIB_ENVIRON = @GNULIB_ENVIRON@ +GNULIB_EUIDACCESS = @GNULIB_EUIDACCESS@ +GNULIB_FACCESSAT = @GNULIB_FACCESSAT@ +GNULIB_FCHDIR = @GNULIB_FCHDIR@ +GNULIB_FCHMODAT = @GNULIB_FCHMODAT@ +GNULIB_FCHOWNAT = @GNULIB_FCHOWNAT@ +GNULIB_FCLOSE = @GNULIB_FCLOSE@ +GNULIB_FCNTL = @GNULIB_FCNTL@ +GNULIB_FDATASYNC = @GNULIB_FDATASYNC@ +GNULIB_FDOPEN = @GNULIB_FDOPEN@ +GNULIB_FDOPENDIR = @GNULIB_FDOPENDIR@ +GNULIB_FFLUSH = @GNULIB_FFLUSH@ +GNULIB_FFSL = @GNULIB_FFSL@ +GNULIB_FFSLL = @GNULIB_FFSLL@ +GNULIB_FGETC = @GNULIB_FGETC@ +GNULIB_FGETS = @GNULIB_FGETS@ +GNULIB_FOPEN = @GNULIB_FOPEN@ +GNULIB_FPRINTF = @GNULIB_FPRINTF@ +GNULIB_FPRINTF_POSIX = @GNULIB_FPRINTF_POSIX@ +GNULIB_FPURGE = @GNULIB_FPURGE@ +GNULIB_FPUTC = @GNULIB_FPUTC@ +GNULIB_FPUTS = @GNULIB_FPUTS@ +GNULIB_FREAD = @GNULIB_FREAD@ +GNULIB_FREOPEN = @GNULIB_FREOPEN@ +GNULIB_FSCANF = @GNULIB_FSCANF@ +GNULIB_FSEEK = @GNULIB_FSEEK@ +GNULIB_FSEEKO = @GNULIB_FSEEKO@ +GNULIB_FSTAT = @GNULIB_FSTAT@ +GNULIB_FSTATAT = @GNULIB_FSTATAT@ +GNULIB_FSYNC = @GNULIB_FSYNC@ +GNULIB_FTELL = @GNULIB_FTELL@ +GNULIB_FTELLO = @GNULIB_FTELLO@ +GNULIB_FTRUNCATE = @GNULIB_FTRUNCATE@ +GNULIB_FUTIMENS = @GNULIB_FUTIMENS@ +GNULIB_FWRITE = @GNULIB_FWRITE@ +GNULIB_GETC = @GNULIB_GETC@ +GNULIB_GETCHAR = @GNULIB_GETCHAR@ +GNULIB_GETCWD = @GNULIB_GETCWD@ +GNULIB_GETDELIM = @GNULIB_GETDELIM@ +GNULIB_GETDOMAINNAME = @GNULIB_GETDOMAINNAME@ +GNULIB_GETDTABLESIZE = @GNULIB_GETDTABLESIZE@ +GNULIB_GETGROUPS = @GNULIB_GETGROUPS@ +GNULIB_GETHOSTNAME = @GNULIB_GETHOSTNAME@ +GNULIB_GETLINE = @GNULIB_GETLINE@ +GNULIB_GETLOADAVG = @GNULIB_GETLOADAVG@ +GNULIB_GETLOGIN = @GNULIB_GETLOGIN@ +GNULIB_GETLOGIN_R = @GNULIB_GETLOGIN_R@ +GNULIB_GETPAGESIZE = @GNULIB_GETPAGESIZE@ +GNULIB_GETSUBOPT = @GNULIB_GETSUBOPT@ +GNULIB_GETTIMEOFDAY = @GNULIB_GETTIMEOFDAY@ +GNULIB_GETUSERSHELL = @GNULIB_GETUSERSHELL@ +GNULIB_GL_UNISTD_H_GETOPT = @GNULIB_GL_UNISTD_H_GETOPT@ +GNULIB_GRANTPT = @GNULIB_GRANTPT@ +GNULIB_GROUP_MEMBER = @GNULIB_GROUP_MEMBER@ +GNULIB_ICONV = @GNULIB_ICONV@ +GNULIB_IMAXABS = @GNULIB_IMAXABS@ +GNULIB_IMAXDIV = @GNULIB_IMAXDIV@ +GNULIB_ISATTY = @GNULIB_ISATTY@ +GNULIB_ISWBLANK = @GNULIB_ISWBLANK@ +GNULIB_ISWCTYPE = @GNULIB_ISWCTYPE@ +GNULIB_LCHMOD = @GNULIB_LCHMOD@ +GNULIB_LCHOWN = @GNULIB_LCHOWN@ +GNULIB_LINK = @GNULIB_LINK@ +GNULIB_LINKAT = @GNULIB_LINKAT@ +GNULIB_LOCALECONV = @GNULIB_LOCALECONV@ +GNULIB_LSEEK = @GNULIB_LSEEK@ +GNULIB_LSTAT = @GNULIB_LSTAT@ +GNULIB_MALLOC_POSIX = @GNULIB_MALLOC_POSIX@ +GNULIB_MBRLEN = @GNULIB_MBRLEN@ +GNULIB_MBRTOWC = @GNULIB_MBRTOWC@ +GNULIB_MBSCASECMP = @GNULIB_MBSCASECMP@ +GNULIB_MBSCASESTR = @GNULIB_MBSCASESTR@ +GNULIB_MBSCHR = @GNULIB_MBSCHR@ +GNULIB_MBSCSPN = @GNULIB_MBSCSPN@ +GNULIB_MBSINIT = @GNULIB_MBSINIT@ +GNULIB_MBSLEN = @GNULIB_MBSLEN@ +GNULIB_MBSNCASECMP = @GNULIB_MBSNCASECMP@ +GNULIB_MBSNLEN = @GNULIB_MBSNLEN@ +GNULIB_MBSNRTOWCS = @GNULIB_MBSNRTOWCS@ +GNULIB_MBSPBRK = @GNULIB_MBSPBRK@ +GNULIB_MBSPCASECMP = @GNULIB_MBSPCASECMP@ +GNULIB_MBSRCHR = @GNULIB_MBSRCHR@ +GNULIB_MBSRTOWCS = @GNULIB_MBSRTOWCS@ +GNULIB_MBSSEP = @GNULIB_MBSSEP@ +GNULIB_MBSSPN = @GNULIB_MBSSPN@ +GNULIB_MBSSTR = @GNULIB_MBSSTR@ +GNULIB_MBSTOK_R = @GNULIB_MBSTOK_R@ +GNULIB_MBTOWC = @GNULIB_MBTOWC@ +GNULIB_MEMCHR = @GNULIB_MEMCHR@ +GNULIB_MEMMEM = @GNULIB_MEMMEM@ +GNULIB_MEMPCPY = @GNULIB_MEMPCPY@ +GNULIB_MEMRCHR = @GNULIB_MEMRCHR@ +GNULIB_MKDIRAT = @GNULIB_MKDIRAT@ +GNULIB_MKDTEMP = @GNULIB_MKDTEMP@ +GNULIB_MKFIFO = @GNULIB_MKFIFO@ +GNULIB_MKFIFOAT = @GNULIB_MKFIFOAT@ +GNULIB_MKNOD = @GNULIB_MKNOD@ +GNULIB_MKNODAT = @GNULIB_MKNODAT@ +GNULIB_MKOSTEMP = @GNULIB_MKOSTEMP@ +GNULIB_MKOSTEMPS = @GNULIB_MKOSTEMPS@ +GNULIB_MKSTEMP = @GNULIB_MKSTEMP@ +GNULIB_MKSTEMPS = @GNULIB_MKSTEMPS@ +GNULIB_MKTIME = @GNULIB_MKTIME@ +GNULIB_NANOSLEEP = @GNULIB_NANOSLEEP@ +GNULIB_NL_LANGINFO = @GNULIB_NL_LANGINFO@ +GNULIB_NONBLOCKING = @GNULIB_NONBLOCKING@ +GNULIB_OBSTACK_PRINTF = @GNULIB_OBSTACK_PRINTF@ +GNULIB_OBSTACK_PRINTF_POSIX = @GNULIB_OBSTACK_PRINTF_POSIX@ +GNULIB_OPEN = @GNULIB_OPEN@ +GNULIB_OPENAT = @GNULIB_OPENAT@ +GNULIB_OPENDIR = @GNULIB_OPENDIR@ +GNULIB_PCLOSE = @GNULIB_PCLOSE@ +GNULIB_PERROR = @GNULIB_PERROR@ +GNULIB_PIPE = @GNULIB_PIPE@ +GNULIB_PIPE2 = @GNULIB_PIPE2@ +GNULIB_POPEN = @GNULIB_POPEN@ +GNULIB_POSIX_OPENPT = @GNULIB_POSIX_OPENPT@ +GNULIB_POSIX_SPAWN = @GNULIB_POSIX_SPAWN@ +GNULIB_POSIX_SPAWNATTR_DESTROY = @GNULIB_POSIX_SPAWNATTR_DESTROY@ +GNULIB_POSIX_SPAWNATTR_GETFLAGS = @GNULIB_POSIX_SPAWNATTR_GETFLAGS@ +GNULIB_POSIX_SPAWNATTR_GETPGROUP = @GNULIB_POSIX_SPAWNATTR_GETPGROUP@ +GNULIB_POSIX_SPAWNATTR_GETSCHEDPARAM = @GNULIB_POSIX_SPAWNATTR_GETSCHEDPARAM@ +GNULIB_POSIX_SPAWNATTR_GETSCHEDPOLICY = @GNULIB_POSIX_SPAWNATTR_GETSCHEDPOLICY@ +GNULIB_POSIX_SPAWNATTR_GETSIGDEFAULT = @GNULIB_POSIX_SPAWNATTR_GETSIGDEFAULT@ +GNULIB_POSIX_SPAWNATTR_GETSIGMASK = @GNULIB_POSIX_SPAWNATTR_GETSIGMASK@ +GNULIB_POSIX_SPAWNATTR_INIT = @GNULIB_POSIX_SPAWNATTR_INIT@ +GNULIB_POSIX_SPAWNATTR_SETFLAGS = @GNULIB_POSIX_SPAWNATTR_SETFLAGS@ +GNULIB_POSIX_SPAWNATTR_SETPGROUP = @GNULIB_POSIX_SPAWNATTR_SETPGROUP@ +GNULIB_POSIX_SPAWNATTR_SETSCHEDPARAM = @GNULIB_POSIX_SPAWNATTR_SETSCHEDPARAM@ +GNULIB_POSIX_SPAWNATTR_SETSCHEDPOLICY = @GNULIB_POSIX_SPAWNATTR_SETSCHEDPOLICY@ +GNULIB_POSIX_SPAWNATTR_SETSIGDEFAULT = @GNULIB_POSIX_SPAWNATTR_SETSIGDEFAULT@ +GNULIB_POSIX_SPAWNATTR_SETSIGMASK = @GNULIB_POSIX_SPAWNATTR_SETSIGMASK@ +GNULIB_POSIX_SPAWNP = @GNULIB_POSIX_SPAWNP@ +GNULIB_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSE = @GNULIB_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSE@ +GNULIB_POSIX_SPAWN_FILE_ACTIONS_ADDDUP2 = @GNULIB_POSIX_SPAWN_FILE_ACTIONS_ADDDUP2@ +GNULIB_POSIX_SPAWN_FILE_ACTIONS_ADDOPEN = @GNULIB_POSIX_SPAWN_FILE_ACTIONS_ADDOPEN@ +GNULIB_POSIX_SPAWN_FILE_ACTIONS_DESTROY = @GNULIB_POSIX_SPAWN_FILE_ACTIONS_DESTROY@ +GNULIB_POSIX_SPAWN_FILE_ACTIONS_INIT = @GNULIB_POSIX_SPAWN_FILE_ACTIONS_INIT@ +GNULIB_PREAD = @GNULIB_PREAD@ +GNULIB_PRINTF = @GNULIB_PRINTF@ +GNULIB_PRINTF_POSIX = @GNULIB_PRINTF_POSIX@ +GNULIB_PSELECT = @GNULIB_PSELECT@ +GNULIB_PTHREAD_SIGMASK = @GNULIB_PTHREAD_SIGMASK@ +GNULIB_PTSNAME = @GNULIB_PTSNAME@ +GNULIB_PTSNAME_R = @GNULIB_PTSNAME_R@ +GNULIB_PUTC = @GNULIB_PUTC@ +GNULIB_PUTCHAR = @GNULIB_PUTCHAR@ +GNULIB_PUTENV = @GNULIB_PUTENV@ +GNULIB_PUTS = @GNULIB_PUTS@ +GNULIB_PWRITE = @GNULIB_PWRITE@ +GNULIB_QSORT_R = @GNULIB_QSORT_R@ +GNULIB_RAISE = @GNULIB_RAISE@ +GNULIB_RANDOM = @GNULIB_RANDOM@ +GNULIB_RANDOM_R = @GNULIB_RANDOM_R@ +GNULIB_RAWMEMCHR = @GNULIB_RAWMEMCHR@ +GNULIB_READ = @GNULIB_READ@ +GNULIB_READDIR = @GNULIB_READDIR@ +GNULIB_READLINK = @GNULIB_READLINK@ +GNULIB_READLINKAT = @GNULIB_READLINKAT@ +GNULIB_REALLOC_POSIX = @GNULIB_REALLOC_POSIX@ +GNULIB_REALPATH = @GNULIB_REALPATH@ +GNULIB_REMOVE = @GNULIB_REMOVE@ +GNULIB_RENAME = @GNULIB_RENAME@ +GNULIB_RENAMEAT = @GNULIB_RENAMEAT@ +GNULIB_REWINDDIR = @GNULIB_REWINDDIR@ +GNULIB_RMDIR = @GNULIB_RMDIR@ +GNULIB_RPMATCH = @GNULIB_RPMATCH@ +GNULIB_SCANDIR = @GNULIB_SCANDIR@ +GNULIB_SCANF = @GNULIB_SCANF@ +GNULIB_SECURE_GETENV = @GNULIB_SECURE_GETENV@ +GNULIB_SELECT = @GNULIB_SELECT@ +GNULIB_SETENV = @GNULIB_SETENV@ +GNULIB_SETHOSTNAME = @GNULIB_SETHOSTNAME@ +GNULIB_SETLOCALE = @GNULIB_SETLOCALE@ +GNULIB_SIGACTION = @GNULIB_SIGACTION@ +GNULIB_SIGNAL_H_SIGPIPE = @GNULIB_SIGNAL_H_SIGPIPE@ +GNULIB_SIGPROCMASK = @GNULIB_SIGPROCMASK@ +GNULIB_SLEEP = @GNULIB_SLEEP@ +GNULIB_SNPRINTF = @GNULIB_SNPRINTF@ +GNULIB_SPRINTF_POSIX = @GNULIB_SPRINTF_POSIX@ +GNULIB_STAT = @GNULIB_STAT@ +GNULIB_STDIO_H_NONBLOCKING = @GNULIB_STDIO_H_NONBLOCKING@ +GNULIB_STDIO_H_SIGPIPE = @GNULIB_STDIO_H_SIGPIPE@ +GNULIB_STPCPY = @GNULIB_STPCPY@ +GNULIB_STPNCPY = @GNULIB_STPNCPY@ +GNULIB_STRCASESTR = @GNULIB_STRCASESTR@ +GNULIB_STRCHRNUL = @GNULIB_STRCHRNUL@ +GNULIB_STRDUP = @GNULIB_STRDUP@ +GNULIB_STRERROR = @GNULIB_STRERROR@ +GNULIB_STRERROR_R = @GNULIB_STRERROR_R@ +GNULIB_STRNCAT = @GNULIB_STRNCAT@ +GNULIB_STRNDUP = @GNULIB_STRNDUP@ +GNULIB_STRNLEN = @GNULIB_STRNLEN@ +GNULIB_STRPBRK = @GNULIB_STRPBRK@ +GNULIB_STRPTIME = @GNULIB_STRPTIME@ +GNULIB_STRSEP = @GNULIB_STRSEP@ +GNULIB_STRSIGNAL = @GNULIB_STRSIGNAL@ +GNULIB_STRSTR = @GNULIB_STRSTR@ +GNULIB_STRTOD = @GNULIB_STRTOD@ +GNULIB_STRTOIMAX = @GNULIB_STRTOIMAX@ +GNULIB_STRTOK_R = @GNULIB_STRTOK_R@ +GNULIB_STRTOLL = @GNULIB_STRTOLL@ +GNULIB_STRTOULL = @GNULIB_STRTOULL@ +GNULIB_STRTOUMAX = @GNULIB_STRTOUMAX@ +GNULIB_STRVERSCMP = @GNULIB_STRVERSCMP@ +GNULIB_SYMLINK = @GNULIB_SYMLINK@ +GNULIB_SYMLINKAT = @GNULIB_SYMLINKAT@ +GNULIB_SYSTEM_POSIX = @GNULIB_SYSTEM_POSIX@ +GNULIB_TIMEGM = @GNULIB_TIMEGM@ +GNULIB_TIME_R = @GNULIB_TIME_R@ +GNULIB_TMPFILE = @GNULIB_TMPFILE@ +GNULIB_TOWCTRANS = @GNULIB_TOWCTRANS@ +GNULIB_TTYNAME_R = @GNULIB_TTYNAME_R@ +GNULIB_UNISTD_H_NONBLOCKING = @GNULIB_UNISTD_H_NONBLOCKING@ +GNULIB_UNISTD_H_SIGPIPE = @GNULIB_UNISTD_H_SIGPIPE@ +GNULIB_UNLINK = @GNULIB_UNLINK@ +GNULIB_UNLINKAT = @GNULIB_UNLINKAT@ +GNULIB_UNLOCKPT = @GNULIB_UNLOCKPT@ +GNULIB_UNSETENV = @GNULIB_UNSETENV@ +GNULIB_USLEEP = @GNULIB_USLEEP@ +GNULIB_UTIMENSAT = @GNULIB_UTIMENSAT@ +GNULIB_VASPRINTF = @GNULIB_VASPRINTF@ +GNULIB_VDPRINTF = @GNULIB_VDPRINTF@ +GNULIB_VFPRINTF = @GNULIB_VFPRINTF@ +GNULIB_VFPRINTF_POSIX = @GNULIB_VFPRINTF_POSIX@ +GNULIB_VFSCANF = @GNULIB_VFSCANF@ +GNULIB_VPRINTF = @GNULIB_VPRINTF@ +GNULIB_VPRINTF_POSIX = @GNULIB_VPRINTF_POSIX@ +GNULIB_VSCANF = @GNULIB_VSCANF@ +GNULIB_VSNPRINTF = @GNULIB_VSNPRINTF@ +GNULIB_VSPRINTF_POSIX = @GNULIB_VSPRINTF_POSIX@ +GNULIB_WAITPID = @GNULIB_WAITPID@ +GNULIB_WCPCPY = @GNULIB_WCPCPY@ +GNULIB_WCPNCPY = @GNULIB_WCPNCPY@ +GNULIB_WCRTOMB = @GNULIB_WCRTOMB@ +GNULIB_WCSCASECMP = @GNULIB_WCSCASECMP@ +GNULIB_WCSCAT = @GNULIB_WCSCAT@ +GNULIB_WCSCHR = @GNULIB_WCSCHR@ +GNULIB_WCSCMP = @GNULIB_WCSCMP@ +GNULIB_WCSCOLL = @GNULIB_WCSCOLL@ +GNULIB_WCSCPY = @GNULIB_WCSCPY@ +GNULIB_WCSCSPN = @GNULIB_WCSCSPN@ +GNULIB_WCSDUP = @GNULIB_WCSDUP@ +GNULIB_WCSLEN = @GNULIB_WCSLEN@ +GNULIB_WCSNCASECMP = @GNULIB_WCSNCASECMP@ +GNULIB_WCSNCAT = @GNULIB_WCSNCAT@ +GNULIB_WCSNCMP = @GNULIB_WCSNCMP@ +GNULIB_WCSNCPY = @GNULIB_WCSNCPY@ +GNULIB_WCSNLEN = @GNULIB_WCSNLEN@ +GNULIB_WCSNRTOMBS = @GNULIB_WCSNRTOMBS@ +GNULIB_WCSPBRK = @GNULIB_WCSPBRK@ +GNULIB_WCSRCHR = @GNULIB_WCSRCHR@ +GNULIB_WCSRTOMBS = @GNULIB_WCSRTOMBS@ +GNULIB_WCSSPN = @GNULIB_WCSSPN@ +GNULIB_WCSSTR = @GNULIB_WCSSTR@ +GNULIB_WCSTOK = @GNULIB_WCSTOK@ +GNULIB_WCSWIDTH = @GNULIB_WCSWIDTH@ +GNULIB_WCSXFRM = @GNULIB_WCSXFRM@ +GNULIB_WCTOB = @GNULIB_WCTOB@ +GNULIB_WCTOMB = @GNULIB_WCTOMB@ +GNULIB_WCTRANS = @GNULIB_WCTRANS@ +GNULIB_WCTYPE = @GNULIB_WCTYPE@ +GNULIB_WCWIDTH = @GNULIB_WCWIDTH@ +GNULIB_WMEMCHR = @GNULIB_WMEMCHR@ +GNULIB_WMEMCMP = @GNULIB_WMEMCMP@ +GNULIB_WMEMCPY = @GNULIB_WMEMCPY@ +GNULIB_WMEMMOVE = @GNULIB_WMEMMOVE@ +GNULIB_WMEMSET = @GNULIB_WMEMSET@ +GNULIB_WRITE = @GNULIB_WRITE@ +GNULIB__EXIT = @GNULIB__EXIT@ +GREP = @GREP@ +HAVE_ALPHASORT = @HAVE_ALPHASORT@ +HAVE_ASPRINTF = @HAVE_ASPRINTF@ +HAVE_ATOLL = @HAVE_ATOLL@ +HAVE_BTOWC = @HAVE_BTOWC@ +HAVE_CANONICALIZE_FILE_NAME = @HAVE_CANONICALIZE_FILE_NAME@ +HAVE_CHOWN = @HAVE_CHOWN@ +HAVE_CLIX = @HAVE_CLIX@ +HAVE_CLIX_IN_PATH = @HAVE_CLIX_IN_PATH@ +HAVE_CLOSEDIR = @HAVE_CLOSEDIR@ +HAVE_CSC = @HAVE_CSC@ +HAVE_CSCC = @HAVE_CSCC@ +HAVE_CSCC_IN_PATH = @HAVE_CSCC_IN_PATH@ +HAVE_CSC_IN_PATH = @HAVE_CSC_IN_PATH@ +HAVE_DECL_DIRFD = @HAVE_DECL_DIRFD@ +HAVE_DECL_ENVIRON = @HAVE_DECL_ENVIRON@ +HAVE_DECL_FCHDIR = @HAVE_DECL_FCHDIR@ +HAVE_DECL_FDATASYNC = @HAVE_DECL_FDATASYNC@ +HAVE_DECL_FDOPENDIR = @HAVE_DECL_FDOPENDIR@ +HAVE_DECL_FPURGE = @HAVE_DECL_FPURGE@ +HAVE_DECL_FSEEKO = @HAVE_DECL_FSEEKO@ +HAVE_DECL_FTELLO = @HAVE_DECL_FTELLO@ +HAVE_DECL_GETDELIM = @HAVE_DECL_GETDELIM@ +HAVE_DECL_GETDOMAINNAME = @HAVE_DECL_GETDOMAINNAME@ +HAVE_DECL_GETLINE = @HAVE_DECL_GETLINE@ +HAVE_DECL_GETLOADAVG = @HAVE_DECL_GETLOADAVG@ +HAVE_DECL_GETLOGIN_R = @HAVE_DECL_GETLOGIN_R@ +HAVE_DECL_GETPAGESIZE = @HAVE_DECL_GETPAGESIZE@ +HAVE_DECL_GETUSERSHELL = @HAVE_DECL_GETUSERSHELL@ +HAVE_DECL_IMAXABS = @HAVE_DECL_IMAXABS@ +HAVE_DECL_IMAXDIV = @HAVE_DECL_IMAXDIV@ +HAVE_DECL_LOCALTIME_R = @HAVE_DECL_LOCALTIME_R@ +HAVE_DECL_MEMMEM = @HAVE_DECL_MEMMEM@ +HAVE_DECL_MEMRCHR = @HAVE_DECL_MEMRCHR@ +HAVE_DECL_OBSTACK_PRINTF = @HAVE_DECL_OBSTACK_PRINTF@ +HAVE_DECL_SETENV = @HAVE_DECL_SETENV@ +HAVE_DECL_SETHOSTNAME = @HAVE_DECL_SETHOSTNAME@ +HAVE_DECL_SNPRINTF = @HAVE_DECL_SNPRINTF@ +HAVE_DECL_STRDUP = @HAVE_DECL_STRDUP@ +HAVE_DECL_STRERROR_R = @HAVE_DECL_STRERROR_R@ +HAVE_DECL_STRNDUP = @HAVE_DECL_STRNDUP@ +HAVE_DECL_STRNLEN = @HAVE_DECL_STRNLEN@ +HAVE_DECL_STRSIGNAL = @HAVE_DECL_STRSIGNAL@ +HAVE_DECL_STRTOIMAX = @HAVE_DECL_STRTOIMAX@ +HAVE_DECL_STRTOK_R = @HAVE_DECL_STRTOK_R@ +HAVE_DECL_STRTOUMAX = @HAVE_DECL_STRTOUMAX@ +HAVE_DECL_TTYNAME_R = @HAVE_DECL_TTYNAME_R@ +HAVE_DECL_UNSETENV = @HAVE_DECL_UNSETENV@ +HAVE_DECL_VSNPRINTF = @HAVE_DECL_VSNPRINTF@ +HAVE_DECL_WCTOB = @HAVE_DECL_WCTOB@ +HAVE_DECL_WCWIDTH = @HAVE_DECL_WCWIDTH@ +HAVE_DIRENT_H = @HAVE_DIRENT_H@ +HAVE_DPRINTF = @HAVE_DPRINTF@ +HAVE_DUP2 = @HAVE_DUP2@ +HAVE_DUP3 = @HAVE_DUP3@ +HAVE_DUPLOCALE = @HAVE_DUPLOCALE@ +HAVE_EUIDACCESS = @HAVE_EUIDACCESS@ +HAVE_FACCESSAT = @HAVE_FACCESSAT@ +HAVE_FCHDIR = @HAVE_FCHDIR@ +HAVE_FCHMODAT = @HAVE_FCHMODAT@ +HAVE_FCHOWNAT = @HAVE_FCHOWNAT@ +HAVE_FCNTL = @HAVE_FCNTL@ +HAVE_FDATASYNC = @HAVE_FDATASYNC@ +HAVE_FDOPENDIR = @HAVE_FDOPENDIR@ +HAVE_FEATURES_H = @HAVE_FEATURES_H@ +HAVE_FFSL = @HAVE_FFSL@ +HAVE_FFSLL = @HAVE_FFSLL@ +HAVE_FSEEKO = @HAVE_FSEEKO@ +HAVE_FSTATAT = @HAVE_FSTATAT@ +HAVE_FSYNC = @HAVE_FSYNC@ +HAVE_FTELLO = @HAVE_FTELLO@ +HAVE_FTRUNCATE = @HAVE_FTRUNCATE@ +HAVE_FUTIMENS = @HAVE_FUTIMENS@ +HAVE_GCJ = @HAVE_GCJ@ +HAVE_GCJ_C = @HAVE_GCJ_C@ +HAVE_GCJ_IN_PATH = @HAVE_GCJ_IN_PATH@ +HAVE_GETDTABLESIZE = @HAVE_GETDTABLESIZE@ +HAVE_GETGROUPS = @HAVE_GETGROUPS@ +HAVE_GETHOSTNAME = @HAVE_GETHOSTNAME@ +HAVE_GETLOGIN = @HAVE_GETLOGIN@ +HAVE_GETOPT_H = @HAVE_GETOPT_H@ +HAVE_GETPAGESIZE = @HAVE_GETPAGESIZE@ +HAVE_GETSUBOPT = @HAVE_GETSUBOPT@ +HAVE_GETTIMEOFDAY = @HAVE_GETTIMEOFDAY@ +HAVE_GIJ = @HAVE_GIJ@ +HAVE_GIJ_IN_PATH = @HAVE_GIJ_IN_PATH@ +HAVE_GLOBAL_SYMBOL_PIPE = @HAVE_GLOBAL_SYMBOL_PIPE@ +HAVE_GRANTPT = @HAVE_GRANTPT@ +HAVE_GROUP_MEMBER = @HAVE_GROUP_MEMBER@ +HAVE_ILRUN = @HAVE_ILRUN@ +HAVE_ILRUN_IN_PATH = @HAVE_ILRUN_IN_PATH@ +HAVE_INTTYPES_H = @HAVE_INTTYPES_H@ +HAVE_ISWBLANK = @HAVE_ISWBLANK@ +HAVE_ISWCNTRL = @HAVE_ISWCNTRL@ +HAVE_JAVA = @HAVE_JAVA@ +HAVE_JAVAC = @HAVE_JAVAC@ +HAVE_JAVAC_ENVVAR = @HAVE_JAVAC_ENVVAR@ +HAVE_JAVAC_IN_PATH = @HAVE_JAVAC_IN_PATH@ +HAVE_JAVA_ENVVAR = @HAVE_JAVA_ENVVAR@ +HAVE_JAVA_IN_PATH = @HAVE_JAVA_IN_PATH@ +HAVE_JIKES = @HAVE_JIKES@ +HAVE_JIKES_IN_PATH = @HAVE_JIKES_IN_PATH@ +HAVE_JRE = @HAVE_JRE@ +HAVE_JRE_IN_PATH = @HAVE_JRE_IN_PATH@ +HAVE_JVIEW = @HAVE_JVIEW@ +HAVE_JVIEW_IN_PATH = @HAVE_JVIEW_IN_PATH@ +HAVE_LANGINFO_CODESET = @HAVE_LANGINFO_CODESET@ +HAVE_LANGINFO_ERA = @HAVE_LANGINFO_ERA@ +HAVE_LANGINFO_H = @HAVE_LANGINFO_H@ +HAVE_LANGINFO_T_FMT_AMPM = @HAVE_LANGINFO_T_FMT_AMPM@ +HAVE_LANGINFO_YESEXPR = @HAVE_LANGINFO_YESEXPR@ +HAVE_LCHMOD = @HAVE_LCHMOD@ +HAVE_LCHOWN = @HAVE_LCHOWN@ +HAVE_LIBEXPAT = @HAVE_LIBEXPAT@ +HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ +HAVE_LINK = @HAVE_LINK@ +HAVE_LINKAT = @HAVE_LINKAT@ +HAVE_LONG_LONG_INT = @HAVE_LONG_LONG_INT@ +HAVE_LSTAT = @HAVE_LSTAT@ +HAVE_MBRLEN = @HAVE_MBRLEN@ +HAVE_MBRTOWC = @HAVE_MBRTOWC@ +HAVE_MBSINIT = @HAVE_MBSINIT@ +HAVE_MBSLEN = @HAVE_MBSLEN@ +HAVE_MBSNRTOWCS = @HAVE_MBSNRTOWCS@ +HAVE_MBSRTOWCS = @HAVE_MBSRTOWCS@ +HAVE_MCS = @HAVE_MCS@ +HAVE_MCS_IN_PATH = @HAVE_MCS_IN_PATH@ +HAVE_MEMCHR = @HAVE_MEMCHR@ +HAVE_MEMPCPY = @HAVE_MEMPCPY@ +HAVE_MKDIRAT = @HAVE_MKDIRAT@ +HAVE_MKDTEMP = @HAVE_MKDTEMP@ +HAVE_MKFIFO = @HAVE_MKFIFO@ +HAVE_MKFIFOAT = @HAVE_MKFIFOAT@ +HAVE_MKNOD = @HAVE_MKNOD@ +HAVE_MKNODAT = @HAVE_MKNODAT@ +HAVE_MKOSTEMP = @HAVE_MKOSTEMP@ +HAVE_MKOSTEMPS = @HAVE_MKOSTEMPS@ +HAVE_MKSTEMP = @HAVE_MKSTEMP@ +HAVE_MKSTEMPS = @HAVE_MKSTEMPS@ +HAVE_MONO = @HAVE_MONO@ +HAVE_MONO_IN_PATH = @HAVE_MONO_IN_PATH@ +HAVE_MSVC_INVALID_PARAMETER_HANDLER = @HAVE_MSVC_INVALID_PARAMETER_HANDLER@ +HAVE_NANOSLEEP = @HAVE_NANOSLEEP@ +HAVE_NEWLOCALE = @HAVE_NEWLOCALE@ +HAVE_NL_LANGINFO = @HAVE_NL_LANGINFO@ +HAVE_OPENAT = @HAVE_OPENAT@ +HAVE_OPENDIR = @HAVE_OPENDIR@ +HAVE_OS_H = @HAVE_OS_H@ +HAVE_PCLOSE = @HAVE_PCLOSE@ +HAVE_PIPE = @HAVE_PIPE@ +HAVE_PIPE2 = @HAVE_PIPE2@ +HAVE_POPEN = @HAVE_POPEN@ +HAVE_POSIX_OPENPT = @HAVE_POSIX_OPENPT@ +HAVE_POSIX_PRINTF = @HAVE_POSIX_PRINTF@ +HAVE_POSIX_SIGNALBLOCKING = @HAVE_POSIX_SIGNALBLOCKING@ +HAVE_POSIX_SPAWN = @HAVE_POSIX_SPAWN@ +HAVE_POSIX_SPAWNATTR_T = @HAVE_POSIX_SPAWNATTR_T@ +HAVE_POSIX_SPAWN_FILE_ACTIONS_T = @HAVE_POSIX_SPAWN_FILE_ACTIONS_T@ +HAVE_PREAD = @HAVE_PREAD@ +HAVE_PSELECT = @HAVE_PSELECT@ +HAVE_PTHREAD_SIGMASK = @HAVE_PTHREAD_SIGMASK@ +HAVE_PTSNAME = @HAVE_PTSNAME@ +HAVE_PTSNAME_R = @HAVE_PTSNAME_R@ +HAVE_PWRITE = @HAVE_PWRITE@ +HAVE_RAISE = @HAVE_RAISE@ +HAVE_RANDOM = @HAVE_RANDOM@ +HAVE_RANDOM_H = @HAVE_RANDOM_H@ +HAVE_RANDOM_R = @HAVE_RANDOM_R@ +HAVE_RAWMEMCHR = @HAVE_RAWMEMCHR@ +HAVE_READDIR = @HAVE_READDIR@ +HAVE_READLINK = @HAVE_READLINK@ +HAVE_READLINKAT = @HAVE_READLINKAT@ +HAVE_REALPATH = @HAVE_REALPATH@ +HAVE_RENAMEAT = @HAVE_RENAMEAT@ +HAVE_REWINDDIR = @HAVE_REWINDDIR@ +HAVE_RPMATCH = @HAVE_RPMATCH@ +HAVE_SCANDIR = @HAVE_SCANDIR@ +HAVE_SCHED_H = @HAVE_SCHED_H@ +HAVE_SECURE_GETENV = @HAVE_SECURE_GETENV@ +HAVE_SETENV = @HAVE_SETENV@ +HAVE_SETHOSTNAME = @HAVE_SETHOSTNAME@ +HAVE_SIGACTION = @HAVE_SIGACTION@ +HAVE_SIGHANDLER_T = @HAVE_SIGHANDLER_T@ +HAVE_SIGINFO_T = @HAVE_SIGINFO_T@ +HAVE_SIGNED_SIG_ATOMIC_T = @HAVE_SIGNED_SIG_ATOMIC_T@ +HAVE_SIGNED_WCHAR_T = @HAVE_SIGNED_WCHAR_T@ +HAVE_SIGNED_WINT_T = @HAVE_SIGNED_WINT_T@ +HAVE_SIGSET_T = @HAVE_SIGSET_T@ +HAVE_SLEEP = @HAVE_SLEEP@ +HAVE_SNPRINTF = @HAVE_SNPRINTF@ +HAVE_SPAWN_H = @HAVE_SPAWN_H@ +HAVE_STDINT_H = @HAVE_STDINT_H@ +HAVE_STPCPY = @HAVE_STPCPY@ +HAVE_STPNCPY = @HAVE_STPNCPY@ +HAVE_STRCASESTR = @HAVE_STRCASESTR@ +HAVE_STRCHRNUL = @HAVE_STRCHRNUL@ +HAVE_STRPBRK = @HAVE_STRPBRK@ +HAVE_STRPTIME = @HAVE_STRPTIME@ +HAVE_STRSEP = @HAVE_STRSEP@ +HAVE_STRTOD = @HAVE_STRTOD@ +HAVE_STRTOLL = @HAVE_STRTOLL@ +HAVE_STRTOULL = @HAVE_STRTOULL@ +HAVE_STRUCT_RANDOM_DATA = @HAVE_STRUCT_RANDOM_DATA@ +HAVE_STRUCT_SCHED_PARAM = @HAVE_STRUCT_SCHED_PARAM@ +HAVE_STRUCT_SIGACTION_SA_SIGACTION = @HAVE_STRUCT_SIGACTION_SA_SIGACTION@ +HAVE_STRUCT_TIMEVAL = @HAVE_STRUCT_TIMEVAL@ +HAVE_STRVERSCMP = @HAVE_STRVERSCMP@ +HAVE_SYMLINK = @HAVE_SYMLINK@ +HAVE_SYMLINKAT = @HAVE_SYMLINKAT@ +HAVE_SYS_BITYPES_H = @HAVE_SYS_BITYPES_H@ +HAVE_SYS_INTTYPES_H = @HAVE_SYS_INTTYPES_H@ +HAVE_SYS_LOADAVG_H = @HAVE_SYS_LOADAVG_H@ +HAVE_SYS_PARAM_H = @HAVE_SYS_PARAM_H@ +HAVE_SYS_SELECT_H = @HAVE_SYS_SELECT_H@ +HAVE_SYS_TIME_H = @HAVE_SYS_TIME_H@ +HAVE_SYS_TYPES_H = @HAVE_SYS_TYPES_H@ +HAVE_TIMEGM = @HAVE_TIMEGM@ +HAVE_TYPE_VOLATILE_SIG_ATOMIC_T = @HAVE_TYPE_VOLATILE_SIG_ATOMIC_T@ +HAVE_UNISTD_H = @HAVE_UNISTD_H@ +HAVE_UNLINKAT = @HAVE_UNLINKAT@ +HAVE_UNLOCKPT = @HAVE_UNLOCKPT@ +HAVE_UNSIGNED_LONG_LONG_INT = @HAVE_UNSIGNED_LONG_LONG_INT@ +HAVE_USLEEP = @HAVE_USLEEP@ +HAVE_UTIMENSAT = @HAVE_UTIMENSAT@ +HAVE_VASPRINTF = @HAVE_VASPRINTF@ +HAVE_VDPRINTF = @HAVE_VDPRINTF@ +HAVE_VISIBILITY = @HAVE_VISIBILITY@ +HAVE_WCHAR_H = @HAVE_WCHAR_H@ +HAVE_WCHAR_T = @HAVE_WCHAR_T@ +HAVE_WCPCPY = @HAVE_WCPCPY@ +HAVE_WCPNCPY = @HAVE_WCPNCPY@ +HAVE_WCRTOMB = @HAVE_WCRTOMB@ +HAVE_WCSCASECMP = @HAVE_WCSCASECMP@ +HAVE_WCSCAT = @HAVE_WCSCAT@ +HAVE_WCSCHR = @HAVE_WCSCHR@ +HAVE_WCSCMP = @HAVE_WCSCMP@ +HAVE_WCSCOLL = @HAVE_WCSCOLL@ +HAVE_WCSCPY = @HAVE_WCSCPY@ +HAVE_WCSCSPN = @HAVE_WCSCSPN@ +HAVE_WCSDUP = @HAVE_WCSDUP@ +HAVE_WCSLEN = @HAVE_WCSLEN@ +HAVE_WCSNCASECMP = @HAVE_WCSNCASECMP@ +HAVE_WCSNCAT = @HAVE_WCSNCAT@ +HAVE_WCSNCMP = @HAVE_WCSNCMP@ +HAVE_WCSNCPY = @HAVE_WCSNCPY@ +HAVE_WCSNLEN = @HAVE_WCSNLEN@ +HAVE_WCSNRTOMBS = @HAVE_WCSNRTOMBS@ +HAVE_WCSPBRK = @HAVE_WCSPBRK@ +HAVE_WCSRCHR = @HAVE_WCSRCHR@ +HAVE_WCSRTOMBS = @HAVE_WCSRTOMBS@ +HAVE_WCSSPN = @HAVE_WCSSPN@ +HAVE_WCSSTR = @HAVE_WCSSTR@ +HAVE_WCSTOK = @HAVE_WCSTOK@ +HAVE_WCSWIDTH = @HAVE_WCSWIDTH@ +HAVE_WCSXFRM = @HAVE_WCSXFRM@ +HAVE_WCTRANS_T = @HAVE_WCTRANS_T@ +HAVE_WCTYPE_H = @HAVE_WCTYPE_H@ +HAVE_WCTYPE_T = @HAVE_WCTYPE_T@ +HAVE_WINSOCK2_H = @HAVE_WINSOCK2_H@ +HAVE_WINT_T = @HAVE_WINT_T@ +HAVE_WMEMCHR = @HAVE_WMEMCHR@ +HAVE_WMEMCMP = @HAVE_WMEMCMP@ +HAVE_WMEMCPY = @HAVE_WMEMCPY@ +HAVE_WMEMMOVE = @HAVE_WMEMMOVE@ +HAVE_WMEMSET = @HAVE_WMEMSET@ +HAVE_WPRINTF = @HAVE_WPRINTF@ +HAVE_XLOCALE_H = @HAVE_XLOCALE_H@ +HAVE__BOOL = @HAVE__BOOL@ +HAVE__EXIT = @HAVE__EXIT@ +ICONV_CONST = @ICONV_CONST@ +ICONV_H = @ICONV_H@ +INCCROCO = @INCCROCO@ +INCGLIB = @INCGLIB@ +INCLUDE_NEXT = @INCLUDE_NEXT@ +INCLUDE_NEXT_AS_FIRST_DIRECTIVE = @INCLUDE_NEXT_AS_FIRST_DIRECTIVE@ +INCTERMINFO = @INCTERMINFO@ +INCXML = @INCXML@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_PROGRAM_ENV = @INSTALL_PROGRAM_ENV@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INSTOBJEXT = @INSTOBJEXT@ +INT32_MAX_LT_INTMAX_MAX = @INT32_MAX_LT_INTMAX_MAX@ +INT64_MAX_EQ_LONG_MAX = @INT64_MAX_EQ_LONG_MAX@ +INTLBISON = @INTLBISON@ +INTLLIBS = @INTLLIBS@ +INTLOBJS = @INTLOBJS@ +INTL_DEFAULT_VERBOSITY = @INTL_DEFAULT_VERBOSITY@ +INTL_LIBTOOL_SUFFIX_PREFIX = @INTL_LIBTOOL_SUFFIX_PREFIX@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +JAR = @JAR@ +JAVA_CHOICE = @JAVA_CHOICE@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBCROCO = @LIBCROCO@ +LIBEXPAT = @LIBEXPAT@ +LIBEXPAT_PREFIX = @LIBEXPAT_PREFIX@ +LIBGLIB = @LIBGLIB@ +LIBGLIB_H = @LIBGLIB_H@ +LIBGREP_LIBDEPS = @LIBGREP_LIBDEPS@ +LIBGREP_LTLIBDEPS = @LIBGREP_LTLIBDEPS@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBMULTITHREAD = @LIBMULTITHREAD@ +LIBOBJS = @LIBOBJS@ +LIBPTH = @LIBPTH@ +LIBPTH_PREFIX = @LIBPTH_PREFIX@ +LIBS = @LIBS@ +LIBTERMINFO = @LIBTERMINFO@ +LIBTESTS_LIBDEPS = @LIBTESTS_LIBDEPS@ +LIBTHREAD = @LIBTHREAD@ +LIBTOOL = @LIBTOOL@ +LIBUNISTRING = @LIBUNISTRING@ +LIBUNISTRING_PREFIX = @LIBUNISTRING_PREFIX@ +LIBUNISTRING_UNICONV_H = @LIBUNISTRING_UNICONV_H@ +LIBUNISTRING_UNILBRK_H = @LIBUNISTRING_UNILBRK_H@ +LIBUNISTRING_UNINAME_H = @LIBUNISTRING_UNINAME_H@ +LIBUNISTRING_UNISTR_H = @LIBUNISTRING_UNISTR_H@ +LIBUNISTRING_UNITYPES_H = @LIBUNISTRING_UNITYPES_H@ +LIBUNISTRING_UNIWIDTH_H = @LIBUNISTRING_UNIWIDTH_H@ +LIBXML = @LIBXML@ +LIBXML_H = @LIBXML_H@ +LIB_ACL = @LIB_ACL@ +LIB_POSIX_SPAWN = @LIB_POSIX_SPAWN@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LOCALCHARSET_TESTS_ENVIRONMENT = @LOCALCHARSET_TESTS_ENVIRONMENT@ +LOCALE_FR = @LOCALE_FR@ +LOCALE_FR_UTF8 = @LOCALE_FR_UTF8@ +LOCALE_JA = @LOCALE_JA@ +LOCALE_TR_UTF8 = @LOCALE_TR_UTF8@ +LOCALE_ZH_CN = @LOCALE_ZH_CN@ +LTLIBC = @LTLIBC@ +LTLIBCROCO = @LTLIBCROCO@ +LTLIBEXPAT = @LTLIBEXPAT@ +LTLIBGLIB = @LTLIBGLIB@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBMULTITHREAD = @LTLIBMULTITHREAD@ +LTLIBOBJS = @LTLIBOBJS@ +LTLIBPTH = @LTLIBPTH@ +LTLIBTERMINFO = @LTLIBTERMINFO@ +LTLIBTHREAD = @LTLIBTHREAD@ +LTLIBUNISTRING = @LTLIBUNISTRING@ +LTLIBXML = @LTLIBXML@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MONO_PATH = @MONO_PATH@ +MONO_PATH_SEPARATOR = @MONO_PATH_SEPARATOR@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +MSGMERGE_LIBM = @MSGMERGE_LIBM@ +NEXT_AS_FIRST_DIRECTIVE_DIRENT_H = @NEXT_AS_FIRST_DIRECTIVE_DIRENT_H@ +NEXT_AS_FIRST_DIRECTIVE_ERRNO_H = @NEXT_AS_FIRST_DIRECTIVE_ERRNO_H@ +NEXT_AS_FIRST_DIRECTIVE_FCNTL_H = @NEXT_AS_FIRST_DIRECTIVE_FCNTL_H@ +NEXT_AS_FIRST_DIRECTIVE_FLOAT_H = @NEXT_AS_FIRST_DIRECTIVE_FLOAT_H@ +NEXT_AS_FIRST_DIRECTIVE_GETOPT_H = @NEXT_AS_FIRST_DIRECTIVE_GETOPT_H@ +NEXT_AS_FIRST_DIRECTIVE_ICONV_H = @NEXT_AS_FIRST_DIRECTIVE_ICONV_H@ +NEXT_AS_FIRST_DIRECTIVE_INTTYPES_H = @NEXT_AS_FIRST_DIRECTIVE_INTTYPES_H@ +NEXT_AS_FIRST_DIRECTIVE_LANGINFO_H = @NEXT_AS_FIRST_DIRECTIVE_LANGINFO_H@ +NEXT_AS_FIRST_DIRECTIVE_LOCALE_H = @NEXT_AS_FIRST_DIRECTIVE_LOCALE_H@ +NEXT_AS_FIRST_DIRECTIVE_SCHED_H = @NEXT_AS_FIRST_DIRECTIVE_SCHED_H@ +NEXT_AS_FIRST_DIRECTIVE_SIGNAL_H = @NEXT_AS_FIRST_DIRECTIVE_SIGNAL_H@ +NEXT_AS_FIRST_DIRECTIVE_SPAWN_H = @NEXT_AS_FIRST_DIRECTIVE_SPAWN_H@ +NEXT_AS_FIRST_DIRECTIVE_STDARG_H = @NEXT_AS_FIRST_DIRECTIVE_STDARG_H@ +NEXT_AS_FIRST_DIRECTIVE_STDDEF_H = @NEXT_AS_FIRST_DIRECTIVE_STDDEF_H@ +NEXT_AS_FIRST_DIRECTIVE_STDINT_H = @NEXT_AS_FIRST_DIRECTIVE_STDINT_H@ +NEXT_AS_FIRST_DIRECTIVE_STDIO_H = @NEXT_AS_FIRST_DIRECTIVE_STDIO_H@ +NEXT_AS_FIRST_DIRECTIVE_STDLIB_H = @NEXT_AS_FIRST_DIRECTIVE_STDLIB_H@ +NEXT_AS_FIRST_DIRECTIVE_STRING_H = @NEXT_AS_FIRST_DIRECTIVE_STRING_H@ +NEXT_AS_FIRST_DIRECTIVE_SYS_SELECT_H = @NEXT_AS_FIRST_DIRECTIVE_SYS_SELECT_H@ +NEXT_AS_FIRST_DIRECTIVE_SYS_STAT_H = @NEXT_AS_FIRST_DIRECTIVE_SYS_STAT_H@ +NEXT_AS_FIRST_DIRECTIVE_SYS_TIME_H = @NEXT_AS_FIRST_DIRECTIVE_SYS_TIME_H@ +NEXT_AS_FIRST_DIRECTIVE_SYS_TYPES_H = @NEXT_AS_FIRST_DIRECTIVE_SYS_TYPES_H@ +NEXT_AS_FIRST_DIRECTIVE_SYS_WAIT_H = @NEXT_AS_FIRST_DIRECTIVE_SYS_WAIT_H@ +NEXT_AS_FIRST_DIRECTIVE_TIME_H = @NEXT_AS_FIRST_DIRECTIVE_TIME_H@ +NEXT_AS_FIRST_DIRECTIVE_UNISTD_H = @NEXT_AS_FIRST_DIRECTIVE_UNISTD_H@ +NEXT_AS_FIRST_DIRECTIVE_WCHAR_H = @NEXT_AS_FIRST_DIRECTIVE_WCHAR_H@ +NEXT_AS_FIRST_DIRECTIVE_WCTYPE_H = @NEXT_AS_FIRST_DIRECTIVE_WCTYPE_H@ +NEXT_DIRENT_H = @NEXT_DIRENT_H@ +NEXT_ERRNO_H = @NEXT_ERRNO_H@ +NEXT_FCNTL_H = @NEXT_FCNTL_H@ +NEXT_FLOAT_H = @NEXT_FLOAT_H@ +NEXT_GETOPT_H = @NEXT_GETOPT_H@ +NEXT_ICONV_H = @NEXT_ICONV_H@ +NEXT_INTTYPES_H = @NEXT_INTTYPES_H@ +NEXT_LANGINFO_H = @NEXT_LANGINFO_H@ +NEXT_LOCALE_H = @NEXT_LOCALE_H@ +NEXT_SCHED_H = @NEXT_SCHED_H@ +NEXT_SIGNAL_H = @NEXT_SIGNAL_H@ +NEXT_SPAWN_H = @NEXT_SPAWN_H@ +NEXT_STDARG_H = @NEXT_STDARG_H@ +NEXT_STDDEF_H = @NEXT_STDDEF_H@ +NEXT_STDINT_H = @NEXT_STDINT_H@ +NEXT_STDIO_H = @NEXT_STDIO_H@ +NEXT_STDLIB_H = @NEXT_STDLIB_H@ +NEXT_STRING_H = @NEXT_STRING_H@ +NEXT_SYS_SELECT_H = @NEXT_SYS_SELECT_H@ +NEXT_SYS_STAT_H = @NEXT_SYS_STAT_H@ +NEXT_SYS_TIME_H = @NEXT_SYS_TIME_H@ +NEXT_SYS_TYPES_H = @NEXT_SYS_TYPES_H@ +NEXT_SYS_WAIT_H = @NEXT_SYS_WAIT_H@ +NEXT_TIME_H = @NEXT_TIME_H@ +NEXT_UNISTD_H = @NEXT_UNISTD_H@ +NEXT_WCHAR_H = @NEXT_WCHAR_H@ +NEXT_WCTYPE_H = @NEXT_WCTYPE_H@ +NM = @NM@ +NMEDIT = @NMEDIT@ +NO_CXX = @NO_CXX@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENMP_CFLAGS = @OPENMP_CFLAGS@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +POSUB = @POSUB@ +PRAGMA_COLUMNS = @PRAGMA_COLUMNS@ +PRAGMA_SYSTEM_HEADER = @PRAGMA_SYSTEM_HEADER@ +PRIPTR_PREFIX = @PRIPTR_PREFIX@ +PRI_MACROS_BROKEN = @PRI_MACROS_BROKEN@ +PTHREAD_H_DEFINES_STRUCT_TIMESPEC = @PTHREAD_H_DEFINES_STRUCT_TIMESPEC@ +PTRDIFF_T_SUFFIX = @PTRDIFF_T_SUFFIX@ +RANLIB = @RANLIB@ +RC = @RC@ +RELOCATABLE = @RELOCATABLE@ +RELOCATABLE_BUILD_DIR = @RELOCATABLE_BUILD_DIR@ +RELOCATABLE_CONFIG_H_DIR = @RELOCATABLE_CONFIG_H_DIR@ +RELOCATABLE_LDFLAGS = @RELOCATABLE_LDFLAGS@ +RELOCATABLE_LIBRARY_PATH = @RELOCATABLE_LIBRARY_PATH@ +RELOCATABLE_SRC_DIR = @RELOCATABLE_SRC_DIR@ +RELOCATABLE_STRIP = @RELOCATABLE_STRIP@ +REPLACE_BTOWC = @REPLACE_BTOWC@ +REPLACE_CALLOC = @REPLACE_CALLOC@ +REPLACE_CANONICALIZE_FILE_NAME = @REPLACE_CANONICALIZE_FILE_NAME@ +REPLACE_CHOWN = @REPLACE_CHOWN@ +REPLACE_CLOSE = @REPLACE_CLOSE@ +REPLACE_CLOSEDIR = @REPLACE_CLOSEDIR@ +REPLACE_DIRFD = @REPLACE_DIRFD@ +REPLACE_DPRINTF = @REPLACE_DPRINTF@ +REPLACE_DUP = @REPLACE_DUP@ +REPLACE_DUP2 = @REPLACE_DUP2@ +REPLACE_DUPLOCALE = @REPLACE_DUPLOCALE@ +REPLACE_FCHOWNAT = @REPLACE_FCHOWNAT@ +REPLACE_FCLOSE = @REPLACE_FCLOSE@ +REPLACE_FCNTL = @REPLACE_FCNTL@ +REPLACE_FDOPEN = @REPLACE_FDOPEN@ +REPLACE_FDOPENDIR = @REPLACE_FDOPENDIR@ +REPLACE_FFLUSH = @REPLACE_FFLUSH@ +REPLACE_FOPEN = @REPLACE_FOPEN@ +REPLACE_FPRINTF = @REPLACE_FPRINTF@ +REPLACE_FPURGE = @REPLACE_FPURGE@ +REPLACE_FREOPEN = @REPLACE_FREOPEN@ +REPLACE_FSEEK = @REPLACE_FSEEK@ +REPLACE_FSEEKO = @REPLACE_FSEEKO@ +REPLACE_FSTAT = @REPLACE_FSTAT@ +REPLACE_FSTATAT = @REPLACE_FSTATAT@ +REPLACE_FTELL = @REPLACE_FTELL@ +REPLACE_FTELLO = @REPLACE_FTELLO@ +REPLACE_FTRUNCATE = @REPLACE_FTRUNCATE@ +REPLACE_FUTIMENS = @REPLACE_FUTIMENS@ +REPLACE_GETCWD = @REPLACE_GETCWD@ +REPLACE_GETDELIM = @REPLACE_GETDELIM@ +REPLACE_GETDOMAINNAME = @REPLACE_GETDOMAINNAME@ +REPLACE_GETDTABLESIZE = @REPLACE_GETDTABLESIZE@ +REPLACE_GETGROUPS = @REPLACE_GETGROUPS@ +REPLACE_GETLINE = @REPLACE_GETLINE@ +REPLACE_GETLOGIN_R = @REPLACE_GETLOGIN_R@ +REPLACE_GETPAGESIZE = @REPLACE_GETPAGESIZE@ +REPLACE_GETTIMEOFDAY = @REPLACE_GETTIMEOFDAY@ +REPLACE_GMTIME = @REPLACE_GMTIME@ +REPLACE_ICONV = @REPLACE_ICONV@ +REPLACE_ICONV_OPEN = @REPLACE_ICONV_OPEN@ +REPLACE_ICONV_UTF = @REPLACE_ICONV_UTF@ +REPLACE_ISATTY = @REPLACE_ISATTY@ +REPLACE_ISWBLANK = @REPLACE_ISWBLANK@ +REPLACE_ISWCNTRL = @REPLACE_ISWCNTRL@ +REPLACE_ITOLD = @REPLACE_ITOLD@ +REPLACE_LCHOWN = @REPLACE_LCHOWN@ +REPLACE_LINK = @REPLACE_LINK@ +REPLACE_LINKAT = @REPLACE_LINKAT@ +REPLACE_LOCALECONV = @REPLACE_LOCALECONV@ +REPLACE_LOCALTIME = @REPLACE_LOCALTIME@ +REPLACE_LOCALTIME_R = @REPLACE_LOCALTIME_R@ +REPLACE_LSEEK = @REPLACE_LSEEK@ +REPLACE_LSTAT = @REPLACE_LSTAT@ +REPLACE_MALLOC = @REPLACE_MALLOC@ +REPLACE_MBRLEN = @REPLACE_MBRLEN@ +REPLACE_MBRTOWC = @REPLACE_MBRTOWC@ +REPLACE_MBSINIT = @REPLACE_MBSINIT@ +REPLACE_MBSNRTOWCS = @REPLACE_MBSNRTOWCS@ +REPLACE_MBSRTOWCS = @REPLACE_MBSRTOWCS@ +REPLACE_MBSTATE_T = @REPLACE_MBSTATE_T@ +REPLACE_MBTOWC = @REPLACE_MBTOWC@ +REPLACE_MEMCHR = @REPLACE_MEMCHR@ +REPLACE_MEMMEM = @REPLACE_MEMMEM@ +REPLACE_MKDIR = @REPLACE_MKDIR@ +REPLACE_MKFIFO = @REPLACE_MKFIFO@ +REPLACE_MKNOD = @REPLACE_MKNOD@ +REPLACE_MKSTEMP = @REPLACE_MKSTEMP@ +REPLACE_MKTIME = @REPLACE_MKTIME@ +REPLACE_NANOSLEEP = @REPLACE_NANOSLEEP@ +REPLACE_NL_LANGINFO = @REPLACE_NL_LANGINFO@ +REPLACE_NULL = @REPLACE_NULL@ +REPLACE_OBSTACK_PRINTF = @REPLACE_OBSTACK_PRINTF@ +REPLACE_OPEN = @REPLACE_OPEN@ +REPLACE_OPENAT = @REPLACE_OPENAT@ +REPLACE_OPENDIR = @REPLACE_OPENDIR@ +REPLACE_PERROR = @REPLACE_PERROR@ +REPLACE_POPEN = @REPLACE_POPEN@ +REPLACE_POSIX_SPAWN = @REPLACE_POSIX_SPAWN@ +REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSE = @REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSE@ +REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDDUP2 = @REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDDUP2@ +REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDOPEN = @REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDOPEN@ +REPLACE_PREAD = @REPLACE_PREAD@ +REPLACE_PRINTF = @REPLACE_PRINTF@ +REPLACE_PSELECT = @REPLACE_PSELECT@ +REPLACE_PTHREAD_SIGMASK = @REPLACE_PTHREAD_SIGMASK@ +REPLACE_PTSNAME = @REPLACE_PTSNAME@ +REPLACE_PTSNAME_R = @REPLACE_PTSNAME_R@ +REPLACE_PUTENV = @REPLACE_PUTENV@ +REPLACE_PWRITE = @REPLACE_PWRITE@ +REPLACE_QSORT_R = @REPLACE_QSORT_R@ +REPLACE_RAISE = @REPLACE_RAISE@ +REPLACE_RANDOM_R = @REPLACE_RANDOM_R@ +REPLACE_READ = @REPLACE_READ@ +REPLACE_READLINK = @REPLACE_READLINK@ +REPLACE_READLINKAT = @REPLACE_READLINKAT@ +REPLACE_REALLOC = @REPLACE_REALLOC@ +REPLACE_REALPATH = @REPLACE_REALPATH@ +REPLACE_REMOVE = @REPLACE_REMOVE@ +REPLACE_RENAME = @REPLACE_RENAME@ +REPLACE_RENAMEAT = @REPLACE_RENAMEAT@ +REPLACE_RMDIR = @REPLACE_RMDIR@ +REPLACE_SELECT = @REPLACE_SELECT@ +REPLACE_SETENV = @REPLACE_SETENV@ +REPLACE_SETLOCALE = @REPLACE_SETLOCALE@ +REPLACE_SLEEP = @REPLACE_SLEEP@ +REPLACE_SNPRINTF = @REPLACE_SNPRINTF@ +REPLACE_SPRINTF = @REPLACE_SPRINTF@ +REPLACE_STAT = @REPLACE_STAT@ +REPLACE_STDIO_READ_FUNCS = @REPLACE_STDIO_READ_FUNCS@ +REPLACE_STDIO_WRITE_FUNCS = @REPLACE_STDIO_WRITE_FUNCS@ +REPLACE_STPNCPY = @REPLACE_STPNCPY@ +REPLACE_STRCASESTR = @REPLACE_STRCASESTR@ +REPLACE_STRCHRNUL = @REPLACE_STRCHRNUL@ +REPLACE_STRDUP = @REPLACE_STRDUP@ +REPLACE_STRERROR = @REPLACE_STRERROR@ +REPLACE_STRERROR_R = @REPLACE_STRERROR_R@ +REPLACE_STRNCAT = @REPLACE_STRNCAT@ +REPLACE_STRNDUP = @REPLACE_STRNDUP@ +REPLACE_STRNLEN = @REPLACE_STRNLEN@ +REPLACE_STRSIGNAL = @REPLACE_STRSIGNAL@ +REPLACE_STRSTR = @REPLACE_STRSTR@ +REPLACE_STRTOD = @REPLACE_STRTOD@ +REPLACE_STRTOIMAX = @REPLACE_STRTOIMAX@ +REPLACE_STRTOK_R = @REPLACE_STRTOK_R@ +REPLACE_STRTOUMAX = @REPLACE_STRTOUMAX@ +REPLACE_STRUCT_LCONV = @REPLACE_STRUCT_LCONV@ +REPLACE_STRUCT_TIMEVAL = @REPLACE_STRUCT_TIMEVAL@ +REPLACE_SYMLINK = @REPLACE_SYMLINK@ +REPLACE_SYMLINKAT = @REPLACE_SYMLINKAT@ +REPLACE_TIMEGM = @REPLACE_TIMEGM@ +REPLACE_TMPFILE = @REPLACE_TMPFILE@ +REPLACE_TOWLOWER = @REPLACE_TOWLOWER@ +REPLACE_TTYNAME_R = @REPLACE_TTYNAME_R@ +REPLACE_UNLINK = @REPLACE_UNLINK@ +REPLACE_UNLINKAT = @REPLACE_UNLINKAT@ +REPLACE_UNSETENV = @REPLACE_UNSETENV@ +REPLACE_USLEEP = @REPLACE_USLEEP@ +REPLACE_UTIMENSAT = @REPLACE_UTIMENSAT@ +REPLACE_VASPRINTF = @REPLACE_VASPRINTF@ +REPLACE_VDPRINTF = @REPLACE_VDPRINTF@ +REPLACE_VFPRINTF = @REPLACE_VFPRINTF@ +REPLACE_VPRINTF = @REPLACE_VPRINTF@ +REPLACE_VSNPRINTF = @REPLACE_VSNPRINTF@ +REPLACE_VSPRINTF = @REPLACE_VSPRINTF@ +REPLACE_WCRTOMB = @REPLACE_WCRTOMB@ +REPLACE_WCSNRTOMBS = @REPLACE_WCSNRTOMBS@ +REPLACE_WCSRTOMBS = @REPLACE_WCSRTOMBS@ +REPLACE_WCSWIDTH = @REPLACE_WCSWIDTH@ +REPLACE_WCTOB = @REPLACE_WCTOB@ +REPLACE_WCTOMB = @REPLACE_WCTOMB@ +REPLACE_WCWIDTH = @REPLACE_WCWIDTH@ +REPLACE_WRITE = @REPLACE_WRITE@ +SCHED_H = @SCHED_H@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SIG_ATOMIC_T_SUFFIX = @SIG_ATOMIC_T_SUFFIX@ +SIZE_T_SUFFIX = @SIZE_T_SUFFIX@ +STDARG_H = @STDARG_H@ +STDBOOL_H = @STDBOOL_H@ +STDDEF_H = @STDDEF_H@ +STDINT_H = @STDINT_H@ +STRIP = @STRIP@ +SYS_TIME_H_DEFINES_STRUCT_TIMESPEC = @SYS_TIME_H_DEFINES_STRUCT_TIMESPEC@ +TESTCSHARP = @TESTCSHARP@ +TESTJAVA = @TESTJAVA@ +TESTLIBASPRINTF = @TESTLIBASPRINTF@ +TEXI2PDF = @TEXI2PDF@ +TIME_H_DEFINES_STRUCT_TIMESPEC = @TIME_H_DEFINES_STRUCT_TIMESPEC@ +UINT32_MAX_LT_UINTMAX_MAX = @UINT32_MAX_LT_UINTMAX_MAX@ +UINT64_MAX_EQ_ULONG_MAX = @UINT64_MAX_EQ_ULONG_MAX@ +UNDEFINE_STRTOK_R = @UNDEFINE_STRTOK_R@ +UNISTD_H_HAVE_WINSOCK2_H = @UNISTD_H_HAVE_WINSOCK2_H@ +UNISTD_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS = @UNISTD_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS@ +USE_ACL = @USE_ACL@ +USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +WCHAR_T_SUFFIX = @WCHAR_T_SUFFIX@ +WINDOWS_64_BIT_OFF_T = @WINDOWS_64_BIT_OFF_T@ +WINDOWS_64_BIT_ST_SIZE = @WINDOWS_64_BIT_ST_SIZE@ +WINDRES = @WINDRES@ +WINT_T_SUFFIX = @WINT_T_SUFFIX@ +WOE32 = @WOE32@ +WOE32DLL = @WOE32DLL@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +YIELD_LIB = @YIELD_LIB@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +aclocaldir = @aclocaldir@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +gl_LIBOBJS = @gl_LIBOBJS@ +gl_LTLIBOBJS = @gl_LTLIBOBJS@ +gltests_LIBOBJS = @gltests_LIBOBJS@ +gltests_LTLIBOBJS = @gltests_LTLIBOBJS@ +gltests_WITNESS = @gltests_WITNESS@ +grgl_LIBOBJS = @grgl_LIBOBJS@ +grgl_LTLIBOBJS = @grgl_LTLIBOBJS@ +grgltests_LIBOBJS = @grgltests_LIBOBJS@ +grgltests_LTLIBOBJS = @grgltests_LTLIBOBJS@ +grgltests_WITNESS = @grgltests_WITNESS@ +gtpo_LIBOBJS = @gtpo_LIBOBJS@ +gtpo_LTLIBOBJS = @gtpo_LTLIBOBJS@ +gtpotests_LIBOBJS = @gtpotests_LIBOBJS@ +gtpotests_LTLIBOBJS = @gtpotests_LTLIBOBJS@ +gtpotests_WITNESS = @gtpotests_WITNESS@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +lispdir = @lispdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AUTOMAKE_OPTIONS = 1.5 gnits subdir-objects no-dependencies + +# If your project uses "gettextize --intl" to put a source-code +# copy of libintl into the package, every Makefile.am needs +# -I$(top_builddir)/intl, so that can be found in this directory. +# Here's one way to do this: +#AM_CPPFLAGS += -I$(top_builddir)/intl +# This option has no effect when the user disables NLS (because then +# the intl directory contains no libintl.h file). This option is not +# enabled by default because the intl directory might not exist if +# your project does not use "gettext --intl", and some compilers +# complain about -I options applied to nonexistent directories. +EXTRA_DIST = alignof.h alloca.in.h allocator.h areadlink.h argmatch.h \ + atexit.c byteswap.in.h c-strcaseeq.h str-two-way.h \ + canonicalize-lgpl.c careadlinkat.h cloexec.h close.c \ + closedir.c dirent-private.h concat-filename.h \ + $(top_srcdir)/../build-aux/csharpcomp.sh.in classpath.c \ + classpath.h $(top_srcdir)/../build-aux/csharpexec.sh.in \ + dirent.in.h dosname.h dup2.c errno.in.h error.c error.h \ + exitfail.h fcntl.c fcntl.in.h fd-hook.h fd-ostream.h \ + fd-ostream.c fd_ostream.priv.h fd_ostream.vt.h fd-ostream.oo.c \ + fd-ostream.oo.h file-ostream.h file-ostream.c \ + file_ostream.priv.h file_ostream.vt.h file-ostream.oo.c \ + file-ostream.oo.h filename.h float.c float.in.h itold.c \ + fnmatch.c fnmatch.in.h fnmatch_loop.c fopen.c fstat.c \ + getdelim.c getdtablesize.c getline.c getopt.c getopt.in.h \ + getopt1.c getopt_int.h $(top_srcdir)/../build-aux/config.rpath \ + gettimeofday.c $(top_srcdir)/../build-aux/config.rpath \ + html-ostream.h html-ostream.c html_ostream.priv.h \ + html_ostream.vt.h html-ostream.oo.c html-ostream.oo.h \ + html-styled-ostream.h html-styled-ostream.c \ + html_styled_ostream.priv.h html_styled_ostream.vt.h \ + html-styled-ostream.oo.c html-styled-ostream.oo.h iconv.in.h \ + iconv_open-aix.h iconv_open-hpux.h iconv_open-irix.h \ + iconv_open-osf.h iconv_open-solaris.h iconv.c iconv_close.c \ + iconv_open-aix.gperf iconv_open-hpux.gperf \ + iconv_open-irix.gperf iconv_open-osf.gperf \ + iconv_open-solaris.gperf iconv_open.c ignore-value.h \ + intprops.h iswblank.c \ + $(top_srcdir)/../build-aux/javacomp.sh.in \ + $(top_srcdir)/../build-aux/javaexec.sh.in javaversion.class \ + javaversion.java libcroco/cr-additional-sel.c \ + libcroco/cr-additional-sel.h libcroco/cr-attr-sel.c \ + libcroco/cr-attr-sel.h libcroco/cr-cascade.c \ + libcroco/cr-cascade.h libcroco/cr-declaration.c \ + libcroco/cr-declaration.h libcroco/cr-doc-handler.c \ + libcroco/cr-doc-handler.h libcroco/cr-enc-handler.c \ + libcroco/cr-enc-handler.h libcroco/cr-fonts.c \ + libcroco/cr-fonts.h libcroco/cr-input.c libcroco/cr-input.h \ + libcroco/cr-num.c libcroco/cr-num.h libcroco/cr-om-parser.c \ + libcroco/cr-om-parser.h libcroco/cr-parser.c \ + libcroco/cr-parser.h libcroco/cr-parsing-location.c \ + libcroco/cr-parsing-location.h libcroco/cr-prop-list.c \ + libcroco/cr-prop-list.h libcroco/cr-pseudo.c \ + libcroco/cr-pseudo.h libcroco/cr-rgb.c libcroco/cr-rgb.h \ + libcroco/cr-sel-eng.c libcroco/cr-sel-eng.h \ + libcroco/cr-selector.c libcroco/cr-selector.h \ + libcroco/cr-simple-sel.c libcroco/cr-simple-sel.h \ + libcroco/cr-statement.c libcroco/cr-statement.h \ + libcroco/cr-string.c libcroco/cr-string.h libcroco/cr-style.c \ + libcroco/cr-style.h libcroco/cr-stylesheet.c \ + libcroco/cr-stylesheet.h libcroco/cr-term.c libcroco/cr-term.h \ + libcroco/cr-tknzr.c libcroco/cr-tknzr.h libcroco/cr-token.c \ + libcroco/cr-token.h libcroco/cr-utils.c libcroco/cr-utils.h \ + libcroco/libcroco-config.h libcroco/libcroco.h glib.in.h \ + glib/ghash.c glib/ghash.in.h glib/glist.c glib/glist.in.h \ + glib/gmessages.c glib/gprimes.c glib/gprimes.in.h \ + glib/gstrfuncs.c glib/gstrfuncs.in.h glib/gstring.c \ + glib/gstring.in.h glib/gtypes.in.h glibconfig.in.h \ + libunistring.valgrind libxml/COPYING libxml/DOCBparser.c \ + libxml/DOCBparser.in.h libxml/HTMLparser.c \ + libxml/HTMLparser.in.h libxml/HTMLtree.c libxml/HTMLtree.in.h \ + libxml/SAX.c libxml/SAX.in.h libxml/SAX2.c libxml/SAX2.in.h \ + libxml/c14n.c libxml/c14n.in.h libxml/catalog.c \ + libxml/catalog.in.h libxml/chvalid.c libxml/chvalid.in.h \ + libxml/debugXML.c libxml/debugXML.in.h libxml/dict.c \ + libxml/dict.in.h libxml/elfgcchack.h libxml/encoding.c \ + libxml/encoding.in.h libxml/entities.c libxml/entities.in.h \ + libxml/error.c libxml/globals.c libxml/globals.in.h \ + libxml/hash.c libxml/hash.in.h libxml/legacy.c libxml/libxml.h \ + libxml/list.c libxml/list.in.h libxml/nanoftp.c \ + libxml/nanoftp.in.h libxml/nanohttp.c libxml/nanohttp.in.h \ + libxml/parser.c libxml/parser.in.h libxml/parserInternals.c \ + libxml/parserInternals.in.h libxml/pattern.c \ + libxml/pattern.in.h libxml/relaxng.c libxml/relaxng.in.h \ + libxml/schemasInternals.in.h libxml/schematron.c \ + libxml/schematron.in.h libxml/threads.c libxml/threads.in.h \ + libxml/tree.c libxml/tree.in.h libxml/uri.c libxml/uri.in.h \ + libxml/valid.c libxml/valid.in.h libxml/xinclude.c \ + libxml/xinclude.in.h libxml/xlink.c libxml/xlink.in.h \ + libxml/xmlIO.c libxml/xmlIO.in.h libxml/xmlautomata.in.h \ + libxml/xmlerror.in.h libxml/xmlexports.in.h libxml/xmlmemory.c \ + libxml/xmlmemory.in.h libxml/xmlmodule.c libxml/xmlmodule.in.h \ + libxml/xmlreader.c libxml/xmlreader.in.h libxml/xmlregexp.c \ + libxml/xmlregexp.in.h libxml/xmlsave.c libxml/xmlsave.in.h \ + libxml/xmlschemas.c libxml/xmlschemas.in.h \ + libxml/xmlschemastypes.c libxml/xmlschemastypes.in.h \ + libxml/xmlstring.c libxml/xmlstring.in.h libxml/xmlunicode.c \ + libxml/xmlunicode.in.h libxml/xmlversion.in.h \ + libxml/xmlwriter.c libxml/xmlwriter.in.h libxml/xpath.c \ + libxml/xpath.in.h libxml/xpathInternals.in.h libxml/xpointer.c \ + libxml/xpointer.in.h config.charset ref-add.sin ref-del.sin \ + locale.in.h localename.h lstat.c malloc.c malloca.h \ + malloca.valgrind mbchar.h mbrtowc.c mbsinit.c mbsrtowcs-impl.h \ + mbsrtowcs-state.c mbsrtowcs.c str-kmp.h memchr.c \ + memchr.valgrind memmove.c memset.c mkdtemp.c moo.h \ + $(top_srcdir)/../build-aux/moopp msvc-inval.c msvc-inval.h \ + msvc-nothrow.c msvc-nothrow.h obstack.c obstack.h open.c \ + dirent-private.h opendir.c ostream.h ostream.c ostream.priv.h \ + ostream.vt.h ostream.oo.c ostream.oo.h pathmax.h \ + pipe-filter-aux.h pipe-filter.h spawn_int.h spawni.c \ + spawn_faction_addclose.c spawn_int.h spawn_faction_adddup2.c \ + spawn_int.h spawn_faction_addopen.c spawn_int.h \ + spawn_faction_destroy.c spawn_faction_init.c spawn_int.h \ + spawnattr_destroy.c spawnattr_init.c spawnattr_setflags.c \ + spawnattr_setsigmask.c spawnp.c acl-internal.h acl.h \ + acl_entries.c quote.h quote.h quotearg.h raise.c rawmemchr.c \ + rawmemchr.valgrind read.c dirent-private.h readdir.c \ + readlink.c realloc.c progreloc.c relocatable.c relocatable.h \ + $(top_srcdir)/../build-aux/config.libpath \ + $(top_srcdir)/../build-aux/reloc-ldflags allocator.c \ + allocator.h areadlink.c areadlink.h c-ctype.c c-ctype.h \ + canonicalize-lgpl.c careadlinkat.c careadlinkat.h malloca.c \ + malloca.h progname.c progname.h progreloc.c readlink.c \ + relocatable.c relocatable.h relocwrapper.c setenv.c \ + $(top_srcdir)/../build-aux/install-reloc \ + $(top_srcdir)/../build-aux/relocatable.sh.in rmdir.c \ + safe-read.h safe-read.c safe-write.h sched.in.h \ + secure_getenv.c setenv.c setlocale.c sig-handler.h sigaction.c \ + signal.in.h stdio-write.c sigprocmask.c \ + $(top_srcdir)/../build-aux/snippet/_Noreturn.h \ + $(top_srcdir)/../build-aux/snippet/arg-nonnull.h \ + $(top_srcdir)/../build-aux/snippet/c++defs.h \ + $(top_srcdir)/../build-aux/snippet/unused-parameter.h \ + $(top_srcdir)/../build-aux/snippet/warn-on-use.h snprintf.c \ + spawn.in.h stat.c stdarg.in.h stdbool.in.h stddef.in.h \ + stdint.in.h stdio.in.h stdlib.in.h stpcpy.c stpncpy.c \ + strchrnul.c strchrnul.valgrind strcspn.c streq.h strerror.c \ + strerror-override.c strerror-override.h iconveh.h string.in.h \ + strnlen.c strpbrk.c str-two-way.h strstr.c strtol.c strtol.c \ + strtoul.c styled-ostream.h styled-ostream.c \ + styled_ostream.priv.h styled_ostream.vt.h styled-ostream.oo.c \ + styled-ostream.oo.h sys_select.in.h sys_stat.in.h \ + sys_time.in.h sys_types.in.h sys_wait.in.h tempname.h \ + term-ostream.h term-ostream.c term_ostream.priv.h \ + term_ostream.vt.h term-ostream.oo.c term-ostream.oo.h \ + term-styled-ostream.h term-styled-ostream.c \ + term_styled_ostream.priv.h term_styled_ostream.vt.h \ + term-styled-ostream.oo.c term-styled-ostream.oo.h tparm.c \ + tputs.c terminfo.h $(top_srcdir)/../build-aux/config.rpath \ + time.in.h trim.h iconveh.h localcharset.h striconveha.h \ + uniconv.in.h unilbrk.in.h unilbrk/lbrkprop1.h \ + unilbrk/lbrkprop2.h unilbrk/lbrktables.h uniwidth/cjk.h \ + unilbrk/ulc-common.h uniname.in.h uniname/gen-uninames.lisp \ + uniname/uninames.h unistd.in.h unistd--.h unistd-safer.h \ + unistr.in.h unitypes.in.h localcharset.h uniwidth.in.h \ + uniwidth/cjk.h unlocked-io.h unsetenv.c asnprintf.c float+.h \ + printf-args.c printf-args.h printf-parse.c printf-parse.h \ + vasnprintf.c vasnprintf.h asprintf.c vasprintf.c verify.h \ + vsnprintf.c waitpid.c wchar.in.h wctype.in.h wcwidth.c write.c \ + concat-filename.h xmalloca.h xreadlink.h xstriconveh.h \ + xalloc.h + +# The BUILT_SOURCES created by this Makefile snippet are not used via #include +# statements but through direct file reference. Therefore this snippet must be +# present in all Makefile.am that need it. This is ensured by the applicability +# 'all' defined above. + +# The BUILT_SOURCES created by this Makefile snippet are not used via #include +# statements but through direct file reference. Therefore this snippet must be +# present in all Makefile.am that need it. This is ensured by the applicability +# 'all' defined above. + +# The BUILT_SOURCES created by this Makefile snippet are not used via #include +# statements but through direct file reference. Therefore this snippet must be +# present in all Makefile.am that need it. This is ensured by the applicability +# 'all' defined above. +BUILT_SOURCES = $(ALLOCA_H) $(BYTESWAP_H) configmake.h dirent.h \ + $(ERRNO_H) fcntl.h fd-ostream.h fd-ostream.c fd_ostream.priv.h \ + fd_ostream.vt.h file-ostream.h file-ostream.c \ + file_ostream.priv.h file_ostream.vt.h $(FLOAT_H) $(FNMATCH_H) \ + $(GETOPT_H) html-ostream.h html-ostream.c html_ostream.priv.h \ + html_ostream.vt.h html-styled-ostream.h html-styled-ostream.c \ + html_styled_ostream.priv.h html_styled_ostream.vt.h $(ICONV_H) \ + iconv_open-aix.h iconv_open-hpux.h iconv_open-irix.h \ + iconv_open-osf.h iconv_open-solaris.h $(LIBGLIB_H) $(LIBXML_H) \ + locale.h ostream.h ostream.c ostream.priv.h ostream.vt.h \ + $(SCHED_H) signal.h arg-nonnull.h c++defs.h unused-parameter.h \ + warn-on-use.h spawn.h $(STDARG_H) $(STDBOOL_H) $(STDDEF_H) \ + $(STDINT_H) stdio.h stdlib.h string.h styled-ostream.h \ + styled-ostream.c styled_ostream.priv.h styled_ostream.vt.h \ + sys/select.h sys/stat.h sys/time.h sys/types.h sys/wait.h \ + term-ostream.h term-ostream.c term_ostream.priv.h \ + term_ostream.vt.h term-styled-ostream.h term-styled-ostream.c \ + term_styled_ostream.priv.h term_styled_ostream.vt.h time.h \ + $(LIBUNISTRING_UNICONV_H) $(LIBUNISTRING_UNILBRK_H) \ + $(LIBUNISTRING_UNINAME_H) unistd.h $(LIBUNISTRING_UNISTR_H) \ + $(LIBUNISTRING_UNITYPES_H) $(LIBUNISTRING_UNIWIDTH_H) wchar.h \ + wctype.h +MOSTLYCLEANFILES = core *.stackdump core *.stackdump alloca.h \ + alloca.h-t byteswap.h byteswap.h-t dirent.h dirent.h-t errno.h \ + errno.h-t fcntl.h fcntl.h-t float.h float.h-t fnmatch.h \ + fnmatch.h-t getopt.h getopt.h-t iconv.h iconv.h-t \ + iconv_open-aix.h-t iconv_open-hpux.h-t iconv_open-irix.h-t \ + iconv_open-osf.h-t iconv_open-solaris.h-t glib.h glibconfig.h \ + glib/ghash.h glib/glist.h glib/gprimes.h glib/gstrfuncs.h \ + glib/gstring.h glib/gtypes.h glib/*.h-t libxml/DOCBparser.h \ + libxml/HTMLparser.h libxml/HTMLtree.h libxml/SAX.h \ + libxml/SAX2.h libxml/c14n.h libxml/catalog.h libxml/chvalid.h \ + libxml/debugXML.h libxml/dict.h libxml/encoding.h \ + libxml/entities.h libxml/globals.h libxml/hash.h libxml/list.h \ + libxml/nanoftp.h libxml/nanohttp.h libxml/parser.h \ + libxml/parserInternals.h libxml/pattern.h libxml/relaxng.h \ + libxml/schemasInternals.h libxml/schematron.h libxml/threads.h \ + libxml/tree.h libxml/uri.h libxml/valid.h libxml/xinclude.h \ + libxml/xlink.h libxml/xmlIO.h libxml/xmlautomata.h \ + libxml/xmlerror.h libxml/xmlexports.h libxml/xmlmemory.h \ + libxml/xmlmodule.h libxml/xmlreader.h libxml/xmlregexp.h \ + libxml/xmlsave.h libxml/xmlschemas.h libxml/xmlschemastypes.h \ + libxml/xmlstring.h libxml/xmlunicode.h libxml/xmlversion.h \ + libxml/xmlwriter.h libxml/xpath.h libxml/xpathInternals.h \ + libxml/xpointer.h libxml/*.h-t locale.h locale.h-t sched.h \ + sched.h-t signal.h signal.h-t arg-nonnull.h arg-nonnull.h-t \ + c++defs.h c++defs.h-t unused-parameter.h unused-parameter.h-t \ + warn-on-use.h warn-on-use.h-t spawn.h spawn.h-t stdarg.h \ + stdarg.h-t stdbool.h stdbool.h-t stddef.h stddef.h-t stdint.h \ + stdint.h-t stdio.h stdio.h-t stdlib.h stdlib.h-t string.h \ + string.h-t sys/select.h sys/select.h-t sys/stat.h sys/stat.h-t \ + sys/time.h sys/time.h-t sys/types.h sys/types.h-t sys/wait.h \ + sys/wait.h-t time.h time.h-t uniconv.h uniconv.h-t unilbrk.h \ + unilbrk.h-t uniname.h uniname.h-t unistd.h unistd.h-t unistr.h \ + unistr.h-t unitypes.h unitypes.h-t uniwidth.h uniwidth.h-t \ + wchar.h wchar.h-t wctype.h wctype.h-t +MOSTLYCLEANDIRS = sys sys sys +CLEANFILES = configmake.h configmake.h-t charset.alias ref-add.sed \ + ref-del.sed +DISTCLEANFILES = +MAINTAINERCLEANFILES = fd-ostream.h fd-ostream.c fd_ostream.priv.h \ + fd_ostream.vt.h file-ostream.h file-ostream.c \ + file_ostream.priv.h file_ostream.vt.h html-ostream.h \ + html-ostream.c html_ostream.priv.h html_ostream.vt.h \ + html-styled-ostream.h html-styled-ostream.c \ + html_styled_ostream.priv.h html_styled_ostream.vt.h \ + iconv_open-aix.h iconv_open-hpux.h iconv_open-irix.h \ + iconv_open-osf.h iconv_open-solaris.h ostream.h ostream.c \ + ostream.priv.h ostream.vt.h styled-ostream.h styled-ostream.c \ + styled_ostream.priv.h styled_ostream.vt.h term-ostream.h \ + term-ostream.c term_ostream.priv.h term_ostream.vt.h \ + term-styled-ostream.h term-styled-ostream.c \ + term_styled_ostream.priv.h term_styled_ostream.vt.h +SUFFIXES = .sed .sin +noinst_LTLIBRARIES = $(am__append_10) $(am__append_15) \ + $(am__append_18) + +# Extra files to be installed. +gettextsrcdir = $(datadir)/gettext +gettextsrc_DATA = gettext.h +pkgdata_DATA = javaversion.class + +# Hmm... is this still necessary? +# Needed so that config.h and woe32dll/export.h are found. + +# Parametrization of the 'relocatable' module. +AM_CPPFLAGS = -I$(top_builddir)/intl -I$(top_srcdir)/intl \ + -I$(top_builddir) -I$(top_srcdir) -DDEPENDS_ON_LIBICONV=1 \ + -DDEPENDS_ON_LIBINTL=1 $(am__append_1) $(am__append_4) \ + $(INCGLIB) $(INCXML) $(am__append_7) $(am__append_11) +libgettextlib_la_SOURCES = copy-acl.c set-acl.c allocator.c \ + areadlink.c argmatch.c gl_array_list.h gl_array_list.c \ + backupfile.h backupfile.c addext.c basename.h basename.c \ + binary-io.h binary-io.c c-ctype.h c-ctype.c c-strcase.h \ + c-strcasecmp.c c-strncasecmp.c c-strcasestr.h c-strcasestr.c \ + c-strstr.h c-strstr.c careadlinkat.c classpath.h classpath.c \ + clean-temp.h clean-temp.c cloexec.c closeout.h closeout.c \ + concat-filename.c copy-file.h copy-file.c csharpcomp.h \ + csharpcomp.c csharpexec.h csharpexec.c diffseq.h \ + error-progname.h error-progname.c execute.h execute.c \ + w32spawn.h exitfail.c fatal-signal.h fatal-signal.c fd-hook.c \ + fd-ostream.c fd-safer-flag.c dup-safer-flag.c file-ostream.c \ + findprog.h findprog.c fstrcmp.h fstrcmp.c full-write.h \ + full-write.c fwriteerror.h fwriteerror.c gcd.h gcd.c gettext.h \ + $(am__append_2) hash.h hash.c html-ostream.c $(am__append_5) \ + $(am__append_6) javacomp.h javacomp.c javaexec.h javaexec.c \ + javaversion.h javaversion.c gl_linkedhash_list.h \ + gl_linkedhash_list.c gl_anyhash_list1.h gl_anyhash_list2.h \ + gl_anylinked_list1.h gl_anylinked_list2.h gl_list.h gl_list.c \ + localcharset.h localcharset.c localename.c glthread/lock.h \ + glthread/lock.c malloca.c mbchar.c mbiter.h mbiter.c mbslen.c \ + mbsstr.c mbswidth.h mbswidth.c mbuiter.h mbuiter.c minmax.h \ + ostream.c pipe-filter-ii.c pipe-filter-aux.c pipe2.c \ + pipe2-safer.c progname.h progname.c propername.h propername.c \ + acl-errno-valid.c file-has-acl.c qcopy-acl.c qset-acl.c \ + quotearg.c safe-read.c safe-write.c sh-quote.h sh-quote.c \ + sig-handler.c size_max.h spawn-pipe.h spawn-pipe.c w32spawn.h \ + striconv.h striconv.c striconveh.h striconveh.c striconveha.h \ + striconveha.c strnlen1.h strnlen1.c styled-ostream.c \ + tempname.c term-ostream.c $(am__append_19) $(am__append_20) \ + glthread/threadlib.c glthread/tls.h glthread/tls.c tmpdir.h \ + tmpdir.c trim.c $(am__append_21) unilbrk/lbrktables.c \ + $(am__append_22) $(am__append_23) unilbrk/ulc-common.c \ + $(am__append_24) $(am__append_25) unistd.c dup-safer.c \ + fd-safer.c pipe-safer.c $(am__append_26) $(am__append_27) \ + $(am__append_28) $(am__append_29) $(am__append_30) \ + $(am__append_31) $(am__append_32) $(am__append_33) \ + $(am__append_34) wait-process.h wait-process.c wctype-h.c \ + xalloc.h xmalloc.c xstrdup.c xconcat-filename.c xerror.h \ + xerror.c gl_xlist.h gl_xlist.c xmalloca.c xreadlink.c \ + xsetenv.h xsetenv.c xsize.h xsize.c xstriconv.h xstriconv.c \ + xstriconveh.c xvasprintf.h xvasprintf.c xasprintf.c +libgettextlib_la_LIBADD = $(gl_LTLIBOBJS) $(am__append_8) \ + $(am__append_13) $(am__append_16) +libgettextlib_la_DEPENDENCIES = $(gl_LTLIBOBJS) $(am__append_9) \ + $(am__append_14) $(am__append_17) +EXTRA_libgettextlib_la_SOURCES = atexit.c canonicalize-lgpl.c close.c \ + closedir.c classpath.c dup2.c error.c fcntl.c fd-ostream.oo.c \ + file-ostream.oo.c float.c itold.c fnmatch.c fnmatch_loop.c \ + fopen.c fstat.c getdelim.c getdtablesize.c getline.c getopt.c \ + getopt1.c gettimeofday.c html-ostream.oo.c \ + html-styled-ostream.oo.c iconv.c iconv_close.c iconv_open.c \ + iswblank.c libcroco/cr-additional-sel.c libcroco/cr-attr-sel.c \ + libcroco/cr-cascade.c libcroco/cr-declaration.c \ + libcroco/cr-doc-handler.c libcroco/cr-enc-handler.c \ + libcroco/cr-fonts.c libcroco/cr-input.c libcroco/cr-num.c \ + libcroco/cr-om-parser.c libcroco/cr-parser.c \ + libcroco/cr-parsing-location.c libcroco/cr-prop-list.c \ + libcroco/cr-pseudo.c libcroco/cr-rgb.c libcroco/cr-sel-eng.c \ + libcroco/cr-selector.c libcroco/cr-simple-sel.c \ + libcroco/cr-statement.c libcroco/cr-string.c \ + libcroco/cr-style.c libcroco/cr-stylesheet.c \ + libcroco/cr-term.c libcroco/cr-tknzr.c libcroco/cr-token.c \ + libcroco/cr-utils.c glib/ghash.c glib/glist.c glib/gmessages.c \ + glib/gprimes.c glib/gstrfuncs.c glib/gstring.c \ + libxml/DOCBparser.c libxml/HTMLparser.c libxml/HTMLtree.c \ + libxml/SAX.c libxml/SAX2.c libxml/c14n.c libxml/catalog.c \ + libxml/chvalid.c libxml/debugXML.c libxml/dict.c \ + libxml/encoding.c libxml/entities.c libxml/error.c \ + libxml/globals.c libxml/hash.c libxml/legacy.c libxml/list.c \ + libxml/nanoftp.c libxml/nanohttp.c libxml/parser.c \ + libxml/parserInternals.c libxml/pattern.c libxml/relaxng.c \ + libxml/schematron.c libxml/threads.c libxml/tree.c \ + libxml/uri.c libxml/valid.c libxml/xinclude.c libxml/xlink.c \ + libxml/xmlIO.c libxml/xmlmemory.c libxml/xmlmodule.c \ + libxml/xmlreader.c libxml/xmlregexp.c libxml/xmlsave.c \ + libxml/xmlschemas.c libxml/xmlschemastypes.c \ + libxml/xmlstring.c libxml/xmlunicode.c libxml/xmlwriter.c \ + libxml/xpath.c libxml/xpointer.c lstat.c malloc.c mbrtowc.c \ + mbsinit.c mbsrtowcs-state.c mbsrtowcs.c memchr.c memmove.c \ + memset.c mkdtemp.c msvc-inval.c msvc-nothrow.c obstack.c \ + open.c opendir.c ostream.oo.c spawni.c \ + spawn_faction_addclose.c spawn_faction_adddup2.c \ + spawn_faction_addopen.c spawn_faction_destroy.c \ + spawn_faction_init.c spawnattr_destroy.c spawnattr_init.c \ + spawnattr_setflags.c spawnattr_setsigmask.c spawnp.c \ + acl_entries.c raise.c rawmemchr.c read.c readdir.c readlink.c \ + realloc.c progreloc.c relocatable.c rmdir.c safe-read.c \ + secure_getenv.c setenv.c setlocale.c sigaction.c stdio-write.c \ + sigprocmask.c snprintf.c stat.c stpcpy.c stpncpy.c strchrnul.c \ + strcspn.c strerror.c strerror-override.c strnlen.c strpbrk.c \ + strstr.c strtol.c strtol.c strtoul.c styled-ostream.oo.c \ + term-ostream.oo.c term-styled-ostream.oo.c tparm.c tputs.c \ + unsetenv.c asnprintf.c printf-args.c printf-parse.c \ + vasnprintf.c asprintf.c vasprintf.c vsnprintf.c waitpid.c \ + wcwidth.c write.c + +# Need $(LTLIBUNISTRING) because ulc_width_linebreaks, uc_width, etc. may be +# taken from libunistring, when the configure option --with-libunistring-prefix +# was given. +# Need @LTLIBINTL@ because many source files use gettext(). +# Need @LTLIBICONV@ because linebreak.c and striconv.c use iconv(). +# Need @LIB_ACL@ because copy-file.c uses acl.h. +# As of 2010-10-04, these are all added by gnulib-tool automatically. +#libgettextlib_la_LDFLAGS += $(LTLIBUNISTRING) @LTLIBINTL@ @LTLIBICONV@ @LIB_ACL@ +libgettextlib_la_LDFLAGS = $(AM_LDFLAGS) -no-undefined $(LIB_ACL) \ + $(LTLIBICONV) $(LTLIBINTL) $(LTLIBTHREAD) $(LTLIBUNISTRING) \ + $(OPENMP_CFLAGS) @INTL_MACOSX_LIBS@ -release @VERSION@ \ + $(am__append_3) $(am__append_12) + +# Use this preprocessor expression to decide whether #include_next works. +# Do not rely on a 'configure'-time test for this, since the expression +# might appear in an installed header, which is used by some other compiler. +HAVE_INCLUDE_NEXT = (__GNUC__ || 60000000 <= __DECC_VER) + +# Specify that libgettextlib should installed in $(libdir). +lib_LTLIBRARIES = libgettextlib.la +GPERF = gperf +libcroco_rpl_la_SOURCES = \ + libcroco/cr-additional-sel.c \ + libcroco/cr-attr-sel.c \ + libcroco/cr-cascade.c \ + libcroco/cr-declaration.c \ + libcroco/cr-doc-handler.c \ + libcroco/cr-enc-handler.c \ + libcroco/cr-fonts.c \ + libcroco/cr-input.c \ + libcroco/cr-num.c \ + libcroco/cr-om-parser.c \ + libcroco/cr-parser.c \ + libcroco/cr-parsing-location.c \ + libcroco/cr-prop-list.c \ + libcroco/cr-pseudo.c \ + libcroco/cr-rgb.c \ + libcroco/cr-sel-eng.c \ + libcroco/cr-selector.c \ + libcroco/cr-simple-sel.c \ + libcroco/cr-statement.c \ + libcroco/cr-string.c \ + libcroco/cr-style.c \ + libcroco/cr-stylesheet.c \ + libcroco/cr-term.c \ + libcroco/cr-tknzr.c \ + libcroco/cr-token.c \ + libcroco/cr-utils.c + +libcroco_rpl_la_CPPFLAGS = $(AM_CPPFLAGS) $(NO_CXX) +libglib_rpl_la_SOURCES = \ + glib/ghash.c \ + glib/glist.c \ + glib/gmessages.c \ + glib/gprimes.c \ + glib/gstrfuncs.c \ + glib/gstring.c + +libglib_rpl_la_CPPFLAGS = $(AM_CPPFLAGS) $(NO_CXX) +libxml_rpl_la_SOURCES = \ + libxml/DOCBparser.c \ + libxml/HTMLparser.c \ + libxml/HTMLtree.c \ + libxml/SAX.c \ + libxml/SAX2.c \ + libxml/c14n.c \ + libxml/catalog.c \ + libxml/chvalid.c \ + libxml/debugXML.c \ + libxml/dict.c \ + libxml/encoding.c \ + libxml/entities.c \ + libxml/error.c \ + libxml/globals.c \ + libxml/hash.c \ + libxml/legacy.c \ + libxml/list.c \ + libxml/nanoftp.c \ + libxml/nanohttp.c \ + libxml/parser.c \ + libxml/parserInternals.c \ + libxml/pattern.c \ + libxml/relaxng.c \ + libxml/schematron.c \ + libxml/threads.c \ + libxml/tree.c \ + libxml/uri.c \ + libxml/valid.c \ + libxml/xinclude.c \ + libxml/xlink.c \ + libxml/xmlIO.c \ + libxml/xmlmemory.c \ + libxml/xmlmodule.c \ + libxml/xmlreader.c \ + libxml/xmlregexp.c \ + libxml/xmlsave.c \ + libxml/xmlschemas.c \ + libxml/xmlschemastypes.c \ + libxml/xmlstring.c \ + libxml/xmlunicode.c \ + libxml/xmlwriter.c \ + libxml/xpath.c \ + libxml/xpointer.c + +libxml_rpl_la_CPPFLAGS = $(AM_CPPFLAGS) $(NO_CXX) +charset_alias = $(DESTDIR)$(libdir)/charset.alias +charset_tmp = $(DESTDIR)$(libdir)/charset.tmp + +# Rules generated and collected by gnulib-tool. + +# Which classes to export from the shared library. +MOOPPFLAGS = --dllexport=styled_ostream + +# Because this Makefile snippet defines a variable used by other +# gnulib Makefile snippets, it must be present in all Makefile.am that +# need it. This is ensured by the applicability 'all' defined above. +_NORETURN_H = $(top_srcdir)/../build-aux/snippet/_Noreturn.h +ARG_NONNULL_H = arg-nonnull.h +CXXDEFS_H = c++defs.h +UNUSED_PARAMETER_H = unused-parameter.h +WARN_ON_USE_H = warn-on-use.h + +# Linking with C++ libraries is needed _only_ on mingw and Cygwin. +@WOE32DLL_FALSE@libgettextlib_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ +@WOE32DLL_FALSE@ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ +@WOE32DLL_FALSE@ $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(libgettextlib_la_LDFLAGS) $(LDFLAGS) \ +@WOE32DLL_FALSE@ -o $@ + +@WOE32DLL_TRUE@libgettextlib_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ +@WOE32DLL_TRUE@ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ +@WOE32DLL_TRUE@ $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(libgettextlib_la_LDFLAGS) $(LDFLAGS) \ +@WOE32DLL_TRUE@ -o $@ + +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .sed .sin .c .cc .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(srcdir)/Makefile.gnulib $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnits gnulib-lib/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnits gnulib-lib/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; +$(srcdir)/Makefile.gnulib: + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ + } + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } +libcroco/$(am__dirstamp): + @$(MKDIR_P) libcroco + @: > libcroco/$(am__dirstamp) +libcroco/libcroco_rpl_la-cr-additional-sel.lo: \ + libcroco/$(am__dirstamp) +libcroco/libcroco_rpl_la-cr-attr-sel.lo: libcroco/$(am__dirstamp) +libcroco/libcroco_rpl_la-cr-cascade.lo: libcroco/$(am__dirstamp) +libcroco/libcroco_rpl_la-cr-declaration.lo: libcroco/$(am__dirstamp) +libcroco/libcroco_rpl_la-cr-doc-handler.lo: libcroco/$(am__dirstamp) +libcroco/libcroco_rpl_la-cr-enc-handler.lo: libcroco/$(am__dirstamp) +libcroco/libcroco_rpl_la-cr-fonts.lo: libcroco/$(am__dirstamp) +libcroco/libcroco_rpl_la-cr-input.lo: libcroco/$(am__dirstamp) +libcroco/libcroco_rpl_la-cr-num.lo: libcroco/$(am__dirstamp) +libcroco/libcroco_rpl_la-cr-om-parser.lo: libcroco/$(am__dirstamp) +libcroco/libcroco_rpl_la-cr-parser.lo: libcroco/$(am__dirstamp) +libcroco/libcroco_rpl_la-cr-parsing-location.lo: \ + libcroco/$(am__dirstamp) +libcroco/libcroco_rpl_la-cr-prop-list.lo: libcroco/$(am__dirstamp) +libcroco/libcroco_rpl_la-cr-pseudo.lo: libcroco/$(am__dirstamp) +libcroco/libcroco_rpl_la-cr-rgb.lo: libcroco/$(am__dirstamp) +libcroco/libcroco_rpl_la-cr-sel-eng.lo: libcroco/$(am__dirstamp) +libcroco/libcroco_rpl_la-cr-selector.lo: libcroco/$(am__dirstamp) +libcroco/libcroco_rpl_la-cr-simple-sel.lo: libcroco/$(am__dirstamp) +libcroco/libcroco_rpl_la-cr-statement.lo: libcroco/$(am__dirstamp) +libcroco/libcroco_rpl_la-cr-string.lo: libcroco/$(am__dirstamp) +libcroco/libcroco_rpl_la-cr-style.lo: libcroco/$(am__dirstamp) +libcroco/libcroco_rpl_la-cr-stylesheet.lo: libcroco/$(am__dirstamp) +libcroco/libcroco_rpl_la-cr-term.lo: libcroco/$(am__dirstamp) +libcroco/libcroco_rpl_la-cr-tknzr.lo: libcroco/$(am__dirstamp) +libcroco/libcroco_rpl_la-cr-token.lo: libcroco/$(am__dirstamp) +libcroco/libcroco_rpl_la-cr-utils.lo: libcroco/$(am__dirstamp) + +libcroco_rpl.la: $(libcroco_rpl_la_OBJECTS) $(libcroco_rpl_la_DEPENDENCIES) $(EXTRA_libcroco_rpl_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(am_libcroco_rpl_la_rpath) $(libcroco_rpl_la_OBJECTS) $(libcroco_rpl_la_LIBADD) $(LIBS) +../woe32dll/$(am__dirstamp): + @$(MKDIR_P) ../woe32dll + @: > ../woe32dll/$(am__dirstamp) +../woe32dll/gettextlib-exports.lo: ../woe32dll/$(am__dirstamp) +../woe32dll/c++html-styled-ostream.lo: ../woe32dll/$(am__dirstamp) +glthread/$(am__dirstamp): + @$(MKDIR_P) glthread + @: > glthread/$(am__dirstamp) +glthread/lock.lo: glthread/$(am__dirstamp) +../woe32dll/c++term-styled-ostream.lo: ../woe32dll/$(am__dirstamp) +glthread/threadlib.lo: glthread/$(am__dirstamp) +glthread/tls.lo: glthread/$(am__dirstamp) +uniconv/$(am__dirstamp): + @$(MKDIR_P) uniconv + @: > uniconv/$(am__dirstamp) +uniconv/u8-conv-from-enc.lo: uniconv/$(am__dirstamp) +unilbrk/$(am__dirstamp): + @$(MKDIR_P) unilbrk + @: > unilbrk/$(am__dirstamp) +unilbrk/lbrktables.lo: unilbrk/$(am__dirstamp) +unilbrk/u8-possible-linebreaks.lo: unilbrk/$(am__dirstamp) +unilbrk/u8-width-linebreaks.lo: unilbrk/$(am__dirstamp) +unilbrk/ulc-common.lo: unilbrk/$(am__dirstamp) +unilbrk/ulc-width-linebreaks.lo: unilbrk/$(am__dirstamp) +uniname/$(am__dirstamp): + @$(MKDIR_P) uniname + @: > uniname/$(am__dirstamp) +uniname/uniname.lo: uniname/$(am__dirstamp) +unistr/$(am__dirstamp): + @$(MKDIR_P) unistr + @: > unistr/$(am__dirstamp) +unistr/u16-mbtouc.lo: unistr/$(am__dirstamp) +unistr/u16-mbtouc-aux.lo: unistr/$(am__dirstamp) +unistr/u8-check.lo: unistr/$(am__dirstamp) +unistr/u8-mblen.lo: unistr/$(am__dirstamp) +unistr/u8-mbtouc.lo: unistr/$(am__dirstamp) +unistr/u8-mbtouc-aux.lo: unistr/$(am__dirstamp) +unistr/u8-mbtouc-unsafe.lo: unistr/$(am__dirstamp) +unistr/u8-mbtouc-unsafe-aux.lo: unistr/$(am__dirstamp) +unistr/u8-mbtoucr.lo: unistr/$(am__dirstamp) +unistr/u8-prev.lo: unistr/$(am__dirstamp) +unistr/u8-uctomb.lo: unistr/$(am__dirstamp) +unistr/u8-uctomb-aux.lo: unistr/$(am__dirstamp) +uniwidth/$(am__dirstamp): + @$(MKDIR_P) uniwidth + @: > uniwidth/$(am__dirstamp) +uniwidth/width.lo: uniwidth/$(am__dirstamp) +libcroco/cr-additional-sel.lo: libcroco/$(am__dirstamp) +libcroco/cr-attr-sel.lo: libcroco/$(am__dirstamp) +libcroco/cr-cascade.lo: libcroco/$(am__dirstamp) +libcroco/cr-declaration.lo: libcroco/$(am__dirstamp) +libcroco/cr-doc-handler.lo: libcroco/$(am__dirstamp) +libcroco/cr-enc-handler.lo: libcroco/$(am__dirstamp) +libcroco/cr-fonts.lo: libcroco/$(am__dirstamp) +libcroco/cr-input.lo: libcroco/$(am__dirstamp) +libcroco/cr-num.lo: libcroco/$(am__dirstamp) +libcroco/cr-om-parser.lo: libcroco/$(am__dirstamp) +libcroco/cr-parser.lo: libcroco/$(am__dirstamp) +libcroco/cr-parsing-location.lo: libcroco/$(am__dirstamp) +libcroco/cr-prop-list.lo: libcroco/$(am__dirstamp) +libcroco/cr-pseudo.lo: libcroco/$(am__dirstamp) +libcroco/cr-rgb.lo: libcroco/$(am__dirstamp) +libcroco/cr-sel-eng.lo: libcroco/$(am__dirstamp) +libcroco/cr-selector.lo: libcroco/$(am__dirstamp) +libcroco/cr-simple-sel.lo: libcroco/$(am__dirstamp) +libcroco/cr-statement.lo: libcroco/$(am__dirstamp) +libcroco/cr-string.lo: libcroco/$(am__dirstamp) +libcroco/cr-style.lo: libcroco/$(am__dirstamp) +libcroco/cr-stylesheet.lo: libcroco/$(am__dirstamp) +libcroco/cr-term.lo: libcroco/$(am__dirstamp) +libcroco/cr-tknzr.lo: libcroco/$(am__dirstamp) +libcroco/cr-token.lo: libcroco/$(am__dirstamp) +libcroco/cr-utils.lo: libcroco/$(am__dirstamp) +glib/$(am__dirstamp): + @$(MKDIR_P) glib + @: > glib/$(am__dirstamp) +glib/ghash.lo: glib/$(am__dirstamp) +glib/glist.lo: glib/$(am__dirstamp) +glib/gmessages.lo: glib/$(am__dirstamp) +glib/gprimes.lo: glib/$(am__dirstamp) +glib/gstrfuncs.lo: glib/$(am__dirstamp) +glib/gstring.lo: glib/$(am__dirstamp) +libxml/$(am__dirstamp): + @$(MKDIR_P) libxml + @: > libxml/$(am__dirstamp) +libxml/DOCBparser.lo: libxml/$(am__dirstamp) +libxml/HTMLparser.lo: libxml/$(am__dirstamp) +libxml/HTMLtree.lo: libxml/$(am__dirstamp) +libxml/SAX.lo: libxml/$(am__dirstamp) +libxml/SAX2.lo: libxml/$(am__dirstamp) +libxml/c14n.lo: libxml/$(am__dirstamp) +libxml/catalog.lo: libxml/$(am__dirstamp) +libxml/chvalid.lo: libxml/$(am__dirstamp) +libxml/debugXML.lo: libxml/$(am__dirstamp) +libxml/dict.lo: libxml/$(am__dirstamp) +libxml/encoding.lo: libxml/$(am__dirstamp) +libxml/entities.lo: libxml/$(am__dirstamp) +libxml/error.lo: libxml/$(am__dirstamp) +libxml/globals.lo: libxml/$(am__dirstamp) +libxml/hash.lo: libxml/$(am__dirstamp) +libxml/legacy.lo: libxml/$(am__dirstamp) +libxml/list.lo: libxml/$(am__dirstamp) +libxml/nanoftp.lo: libxml/$(am__dirstamp) +libxml/nanohttp.lo: libxml/$(am__dirstamp) +libxml/parser.lo: libxml/$(am__dirstamp) +libxml/parserInternals.lo: libxml/$(am__dirstamp) +libxml/pattern.lo: libxml/$(am__dirstamp) +libxml/relaxng.lo: libxml/$(am__dirstamp) +libxml/schematron.lo: libxml/$(am__dirstamp) +libxml/threads.lo: libxml/$(am__dirstamp) +libxml/tree.lo: libxml/$(am__dirstamp) +libxml/uri.lo: libxml/$(am__dirstamp) +libxml/valid.lo: libxml/$(am__dirstamp) +libxml/xinclude.lo: libxml/$(am__dirstamp) +libxml/xlink.lo: libxml/$(am__dirstamp) +libxml/xmlIO.lo: libxml/$(am__dirstamp) +libxml/xmlmemory.lo: libxml/$(am__dirstamp) +libxml/xmlmodule.lo: libxml/$(am__dirstamp) +libxml/xmlreader.lo: libxml/$(am__dirstamp) +libxml/xmlregexp.lo: libxml/$(am__dirstamp) +libxml/xmlsave.lo: libxml/$(am__dirstamp) +libxml/xmlschemas.lo: libxml/$(am__dirstamp) +libxml/xmlschemastypes.lo: libxml/$(am__dirstamp) +libxml/xmlstring.lo: libxml/$(am__dirstamp) +libxml/xmlunicode.lo: libxml/$(am__dirstamp) +libxml/xmlwriter.lo: libxml/$(am__dirstamp) +libxml/xpath.lo: libxml/$(am__dirstamp) +libxml/xpointer.lo: libxml/$(am__dirstamp) + +libgettextlib.la: $(libgettextlib_la_OBJECTS) $(libgettextlib_la_DEPENDENCIES) $(EXTRA_libgettextlib_la_DEPENDENCIES) + $(AM_V_GEN)$(libgettextlib_la_LINK) -rpath $(libdir) $(libgettextlib_la_OBJECTS) $(libgettextlib_la_LIBADD) $(LIBS) +glib/libglib_rpl_la-ghash.lo: glib/$(am__dirstamp) +glib/libglib_rpl_la-glist.lo: glib/$(am__dirstamp) +glib/libglib_rpl_la-gmessages.lo: glib/$(am__dirstamp) +glib/libglib_rpl_la-gprimes.lo: glib/$(am__dirstamp) +glib/libglib_rpl_la-gstrfuncs.lo: glib/$(am__dirstamp) +glib/libglib_rpl_la-gstring.lo: glib/$(am__dirstamp) + +libglib_rpl.la: $(libglib_rpl_la_OBJECTS) $(libglib_rpl_la_DEPENDENCIES) $(EXTRA_libglib_rpl_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(am_libglib_rpl_la_rpath) $(libglib_rpl_la_OBJECTS) $(libglib_rpl_la_LIBADD) $(LIBS) +libxml/libxml_rpl_la-DOCBparser.lo: libxml/$(am__dirstamp) +libxml/libxml_rpl_la-HTMLparser.lo: libxml/$(am__dirstamp) +libxml/libxml_rpl_la-HTMLtree.lo: libxml/$(am__dirstamp) +libxml/libxml_rpl_la-SAX.lo: libxml/$(am__dirstamp) +libxml/libxml_rpl_la-SAX2.lo: libxml/$(am__dirstamp) +libxml/libxml_rpl_la-c14n.lo: libxml/$(am__dirstamp) +libxml/libxml_rpl_la-catalog.lo: libxml/$(am__dirstamp) +libxml/libxml_rpl_la-chvalid.lo: libxml/$(am__dirstamp) +libxml/libxml_rpl_la-debugXML.lo: libxml/$(am__dirstamp) +libxml/libxml_rpl_la-dict.lo: libxml/$(am__dirstamp) +libxml/libxml_rpl_la-encoding.lo: libxml/$(am__dirstamp) +libxml/libxml_rpl_la-entities.lo: libxml/$(am__dirstamp) +libxml/libxml_rpl_la-error.lo: libxml/$(am__dirstamp) +libxml/libxml_rpl_la-globals.lo: libxml/$(am__dirstamp) +libxml/libxml_rpl_la-hash.lo: libxml/$(am__dirstamp) +libxml/libxml_rpl_la-legacy.lo: libxml/$(am__dirstamp) +libxml/libxml_rpl_la-list.lo: libxml/$(am__dirstamp) +libxml/libxml_rpl_la-nanoftp.lo: libxml/$(am__dirstamp) +libxml/libxml_rpl_la-nanohttp.lo: libxml/$(am__dirstamp) +libxml/libxml_rpl_la-parser.lo: libxml/$(am__dirstamp) +libxml/libxml_rpl_la-parserInternals.lo: libxml/$(am__dirstamp) +libxml/libxml_rpl_la-pattern.lo: libxml/$(am__dirstamp) +libxml/libxml_rpl_la-relaxng.lo: libxml/$(am__dirstamp) +libxml/libxml_rpl_la-schematron.lo: libxml/$(am__dirstamp) +libxml/libxml_rpl_la-threads.lo: libxml/$(am__dirstamp) +libxml/libxml_rpl_la-tree.lo: libxml/$(am__dirstamp) +libxml/libxml_rpl_la-uri.lo: libxml/$(am__dirstamp) +libxml/libxml_rpl_la-valid.lo: libxml/$(am__dirstamp) +libxml/libxml_rpl_la-xinclude.lo: libxml/$(am__dirstamp) +libxml/libxml_rpl_la-xlink.lo: libxml/$(am__dirstamp) +libxml/libxml_rpl_la-xmlIO.lo: libxml/$(am__dirstamp) +libxml/libxml_rpl_la-xmlmemory.lo: libxml/$(am__dirstamp) +libxml/libxml_rpl_la-xmlmodule.lo: libxml/$(am__dirstamp) +libxml/libxml_rpl_la-xmlreader.lo: libxml/$(am__dirstamp) +libxml/libxml_rpl_la-xmlregexp.lo: libxml/$(am__dirstamp) +libxml/libxml_rpl_la-xmlsave.lo: libxml/$(am__dirstamp) +libxml/libxml_rpl_la-xmlschemas.lo: libxml/$(am__dirstamp) +libxml/libxml_rpl_la-xmlschemastypes.lo: libxml/$(am__dirstamp) +libxml/libxml_rpl_la-xmlstring.lo: libxml/$(am__dirstamp) +libxml/libxml_rpl_la-xmlunicode.lo: libxml/$(am__dirstamp) +libxml/libxml_rpl_la-xmlwriter.lo: libxml/$(am__dirstamp) +libxml/libxml_rpl_la-xpath.lo: libxml/$(am__dirstamp) +libxml/libxml_rpl_la-xpointer.lo: libxml/$(am__dirstamp) + +libxml_rpl.la: $(libxml_rpl_la_OBJECTS) $(libxml_rpl_la_DEPENDENCIES) $(EXTRA_libxml_rpl_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(am_libxml_rpl_la_rpath) $(libxml_rpl_la_OBJECTS) $(libxml_rpl_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + -rm -f ../woe32dll/*.$(OBJEXT) + -rm -f ../woe32dll/*.lo + -rm -f glib/*.$(OBJEXT) + -rm -f glib/*.lo + -rm -f glthread/*.$(OBJEXT) + -rm -f glthread/*.lo + -rm -f libcroco/*.$(OBJEXT) + -rm -f libcroco/*.lo + -rm -f libxml/*.$(OBJEXT) + -rm -f libxml/*.lo + -rm -f uniconv/*.$(OBJEXT) + -rm -f uniconv/*.lo + -rm -f unilbrk/*.$(OBJEXT) + -rm -f unilbrk/*.lo + -rm -f uniname/*.$(OBJEXT) + -rm -f uniname/*.lo + -rm -f unistr/*.$(OBJEXT) + -rm -f unistr/*.lo + -rm -f uniwidth/*.$(OBJEXT) + -rm -f uniwidth/*.lo + +distclean-compile: + -rm -f *.tab.c + +.c.o: + $(AM_V_CC)$(COMPILE) -c -o $@ $< + +.c.obj: + $(AM_V_CC)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: + $(AM_V_CC)$(LTCOMPILE) -c -o $@ $< + +libcroco/libcroco_rpl_la-cr-additional-sel.lo: libcroco/cr-additional-sel.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcroco_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libcroco/libcroco_rpl_la-cr-additional-sel.lo `test -f 'libcroco/cr-additional-sel.c' || echo '$(srcdir)/'`libcroco/cr-additional-sel.c + +libcroco/libcroco_rpl_la-cr-attr-sel.lo: libcroco/cr-attr-sel.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcroco_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libcroco/libcroco_rpl_la-cr-attr-sel.lo `test -f 'libcroco/cr-attr-sel.c' || echo '$(srcdir)/'`libcroco/cr-attr-sel.c + +libcroco/libcroco_rpl_la-cr-cascade.lo: libcroco/cr-cascade.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcroco_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libcroco/libcroco_rpl_la-cr-cascade.lo `test -f 'libcroco/cr-cascade.c' || echo '$(srcdir)/'`libcroco/cr-cascade.c + +libcroco/libcroco_rpl_la-cr-declaration.lo: libcroco/cr-declaration.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcroco_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libcroco/libcroco_rpl_la-cr-declaration.lo `test -f 'libcroco/cr-declaration.c' || echo '$(srcdir)/'`libcroco/cr-declaration.c + +libcroco/libcroco_rpl_la-cr-doc-handler.lo: libcroco/cr-doc-handler.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcroco_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libcroco/libcroco_rpl_la-cr-doc-handler.lo `test -f 'libcroco/cr-doc-handler.c' || echo '$(srcdir)/'`libcroco/cr-doc-handler.c + +libcroco/libcroco_rpl_la-cr-enc-handler.lo: libcroco/cr-enc-handler.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcroco_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libcroco/libcroco_rpl_la-cr-enc-handler.lo `test -f 'libcroco/cr-enc-handler.c' || echo '$(srcdir)/'`libcroco/cr-enc-handler.c + +libcroco/libcroco_rpl_la-cr-fonts.lo: libcroco/cr-fonts.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcroco_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libcroco/libcroco_rpl_la-cr-fonts.lo `test -f 'libcroco/cr-fonts.c' || echo '$(srcdir)/'`libcroco/cr-fonts.c + +libcroco/libcroco_rpl_la-cr-input.lo: libcroco/cr-input.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcroco_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libcroco/libcroco_rpl_la-cr-input.lo `test -f 'libcroco/cr-input.c' || echo '$(srcdir)/'`libcroco/cr-input.c + +libcroco/libcroco_rpl_la-cr-num.lo: libcroco/cr-num.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcroco_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libcroco/libcroco_rpl_la-cr-num.lo `test -f 'libcroco/cr-num.c' || echo '$(srcdir)/'`libcroco/cr-num.c + +libcroco/libcroco_rpl_la-cr-om-parser.lo: libcroco/cr-om-parser.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcroco_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libcroco/libcroco_rpl_la-cr-om-parser.lo `test -f 'libcroco/cr-om-parser.c' || echo '$(srcdir)/'`libcroco/cr-om-parser.c + +libcroco/libcroco_rpl_la-cr-parser.lo: libcroco/cr-parser.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcroco_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libcroco/libcroco_rpl_la-cr-parser.lo `test -f 'libcroco/cr-parser.c' || echo '$(srcdir)/'`libcroco/cr-parser.c + +libcroco/libcroco_rpl_la-cr-parsing-location.lo: libcroco/cr-parsing-location.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcroco_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libcroco/libcroco_rpl_la-cr-parsing-location.lo `test -f 'libcroco/cr-parsing-location.c' || echo '$(srcdir)/'`libcroco/cr-parsing-location.c + +libcroco/libcroco_rpl_la-cr-prop-list.lo: libcroco/cr-prop-list.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcroco_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libcroco/libcroco_rpl_la-cr-prop-list.lo `test -f 'libcroco/cr-prop-list.c' || echo '$(srcdir)/'`libcroco/cr-prop-list.c + +libcroco/libcroco_rpl_la-cr-pseudo.lo: libcroco/cr-pseudo.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcroco_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libcroco/libcroco_rpl_la-cr-pseudo.lo `test -f 'libcroco/cr-pseudo.c' || echo '$(srcdir)/'`libcroco/cr-pseudo.c + +libcroco/libcroco_rpl_la-cr-rgb.lo: libcroco/cr-rgb.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcroco_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libcroco/libcroco_rpl_la-cr-rgb.lo `test -f 'libcroco/cr-rgb.c' || echo '$(srcdir)/'`libcroco/cr-rgb.c + +libcroco/libcroco_rpl_la-cr-sel-eng.lo: libcroco/cr-sel-eng.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcroco_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libcroco/libcroco_rpl_la-cr-sel-eng.lo `test -f 'libcroco/cr-sel-eng.c' || echo '$(srcdir)/'`libcroco/cr-sel-eng.c + +libcroco/libcroco_rpl_la-cr-selector.lo: libcroco/cr-selector.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcroco_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libcroco/libcroco_rpl_la-cr-selector.lo `test -f 'libcroco/cr-selector.c' || echo '$(srcdir)/'`libcroco/cr-selector.c + +libcroco/libcroco_rpl_la-cr-simple-sel.lo: libcroco/cr-simple-sel.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcroco_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libcroco/libcroco_rpl_la-cr-simple-sel.lo `test -f 'libcroco/cr-simple-sel.c' || echo '$(srcdir)/'`libcroco/cr-simple-sel.c + +libcroco/libcroco_rpl_la-cr-statement.lo: libcroco/cr-statement.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcroco_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libcroco/libcroco_rpl_la-cr-statement.lo `test -f 'libcroco/cr-statement.c' || echo '$(srcdir)/'`libcroco/cr-statement.c + +libcroco/libcroco_rpl_la-cr-string.lo: libcroco/cr-string.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcroco_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libcroco/libcroco_rpl_la-cr-string.lo `test -f 'libcroco/cr-string.c' || echo '$(srcdir)/'`libcroco/cr-string.c + +libcroco/libcroco_rpl_la-cr-style.lo: libcroco/cr-style.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcroco_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libcroco/libcroco_rpl_la-cr-style.lo `test -f 'libcroco/cr-style.c' || echo '$(srcdir)/'`libcroco/cr-style.c + +libcroco/libcroco_rpl_la-cr-stylesheet.lo: libcroco/cr-stylesheet.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcroco_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libcroco/libcroco_rpl_la-cr-stylesheet.lo `test -f 'libcroco/cr-stylesheet.c' || echo '$(srcdir)/'`libcroco/cr-stylesheet.c + +libcroco/libcroco_rpl_la-cr-term.lo: libcroco/cr-term.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcroco_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libcroco/libcroco_rpl_la-cr-term.lo `test -f 'libcroco/cr-term.c' || echo '$(srcdir)/'`libcroco/cr-term.c + +libcroco/libcroco_rpl_la-cr-tknzr.lo: libcroco/cr-tknzr.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcroco_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libcroco/libcroco_rpl_la-cr-tknzr.lo `test -f 'libcroco/cr-tknzr.c' || echo '$(srcdir)/'`libcroco/cr-tknzr.c + +libcroco/libcroco_rpl_la-cr-token.lo: libcroco/cr-token.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcroco_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libcroco/libcroco_rpl_la-cr-token.lo `test -f 'libcroco/cr-token.c' || echo '$(srcdir)/'`libcroco/cr-token.c + +libcroco/libcroco_rpl_la-cr-utils.lo: libcroco/cr-utils.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcroco_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libcroco/libcroco_rpl_la-cr-utils.lo `test -f 'libcroco/cr-utils.c' || echo '$(srcdir)/'`libcroco/cr-utils.c + +glib/libglib_rpl_la-ghash.lo: glib/ghash.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglib_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o glib/libglib_rpl_la-ghash.lo `test -f 'glib/ghash.c' || echo '$(srcdir)/'`glib/ghash.c + +glib/libglib_rpl_la-glist.lo: glib/glist.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglib_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o glib/libglib_rpl_la-glist.lo `test -f 'glib/glist.c' || echo '$(srcdir)/'`glib/glist.c + +glib/libglib_rpl_la-gmessages.lo: glib/gmessages.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglib_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o glib/libglib_rpl_la-gmessages.lo `test -f 'glib/gmessages.c' || echo '$(srcdir)/'`glib/gmessages.c + +glib/libglib_rpl_la-gprimes.lo: glib/gprimes.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglib_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o glib/libglib_rpl_la-gprimes.lo `test -f 'glib/gprimes.c' || echo '$(srcdir)/'`glib/gprimes.c + +glib/libglib_rpl_la-gstrfuncs.lo: glib/gstrfuncs.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglib_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o glib/libglib_rpl_la-gstrfuncs.lo `test -f 'glib/gstrfuncs.c' || echo '$(srcdir)/'`glib/gstrfuncs.c + +glib/libglib_rpl_la-gstring.lo: glib/gstring.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglib_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o glib/libglib_rpl_la-gstring.lo `test -f 'glib/gstring.c' || echo '$(srcdir)/'`glib/gstring.c + +libxml/libxml_rpl_la-DOCBparser.lo: libxml/DOCBparser.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxml_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxml/libxml_rpl_la-DOCBparser.lo `test -f 'libxml/DOCBparser.c' || echo '$(srcdir)/'`libxml/DOCBparser.c + +libxml/libxml_rpl_la-HTMLparser.lo: libxml/HTMLparser.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxml_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxml/libxml_rpl_la-HTMLparser.lo `test -f 'libxml/HTMLparser.c' || echo '$(srcdir)/'`libxml/HTMLparser.c + +libxml/libxml_rpl_la-HTMLtree.lo: libxml/HTMLtree.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxml_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxml/libxml_rpl_la-HTMLtree.lo `test -f 'libxml/HTMLtree.c' || echo '$(srcdir)/'`libxml/HTMLtree.c + +libxml/libxml_rpl_la-SAX.lo: libxml/SAX.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxml_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxml/libxml_rpl_la-SAX.lo `test -f 'libxml/SAX.c' || echo '$(srcdir)/'`libxml/SAX.c + +libxml/libxml_rpl_la-SAX2.lo: libxml/SAX2.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxml_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxml/libxml_rpl_la-SAX2.lo `test -f 'libxml/SAX2.c' || echo '$(srcdir)/'`libxml/SAX2.c + +libxml/libxml_rpl_la-c14n.lo: libxml/c14n.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxml_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxml/libxml_rpl_la-c14n.lo `test -f 'libxml/c14n.c' || echo '$(srcdir)/'`libxml/c14n.c + +libxml/libxml_rpl_la-catalog.lo: libxml/catalog.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxml_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxml/libxml_rpl_la-catalog.lo `test -f 'libxml/catalog.c' || echo '$(srcdir)/'`libxml/catalog.c + +libxml/libxml_rpl_la-chvalid.lo: libxml/chvalid.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxml_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxml/libxml_rpl_la-chvalid.lo `test -f 'libxml/chvalid.c' || echo '$(srcdir)/'`libxml/chvalid.c + +libxml/libxml_rpl_la-debugXML.lo: libxml/debugXML.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxml_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxml/libxml_rpl_la-debugXML.lo `test -f 'libxml/debugXML.c' || echo '$(srcdir)/'`libxml/debugXML.c + +libxml/libxml_rpl_la-dict.lo: libxml/dict.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxml_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxml/libxml_rpl_la-dict.lo `test -f 'libxml/dict.c' || echo '$(srcdir)/'`libxml/dict.c + +libxml/libxml_rpl_la-encoding.lo: libxml/encoding.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxml_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxml/libxml_rpl_la-encoding.lo `test -f 'libxml/encoding.c' || echo '$(srcdir)/'`libxml/encoding.c + +libxml/libxml_rpl_la-entities.lo: libxml/entities.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxml_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxml/libxml_rpl_la-entities.lo `test -f 'libxml/entities.c' || echo '$(srcdir)/'`libxml/entities.c + +libxml/libxml_rpl_la-error.lo: libxml/error.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxml_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxml/libxml_rpl_la-error.lo `test -f 'libxml/error.c' || echo '$(srcdir)/'`libxml/error.c + +libxml/libxml_rpl_la-globals.lo: libxml/globals.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxml_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxml/libxml_rpl_la-globals.lo `test -f 'libxml/globals.c' || echo '$(srcdir)/'`libxml/globals.c + +libxml/libxml_rpl_la-hash.lo: libxml/hash.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxml_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxml/libxml_rpl_la-hash.lo `test -f 'libxml/hash.c' || echo '$(srcdir)/'`libxml/hash.c + +libxml/libxml_rpl_la-legacy.lo: libxml/legacy.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxml_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxml/libxml_rpl_la-legacy.lo `test -f 'libxml/legacy.c' || echo '$(srcdir)/'`libxml/legacy.c + +libxml/libxml_rpl_la-list.lo: libxml/list.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxml_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxml/libxml_rpl_la-list.lo `test -f 'libxml/list.c' || echo '$(srcdir)/'`libxml/list.c + +libxml/libxml_rpl_la-nanoftp.lo: libxml/nanoftp.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxml_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxml/libxml_rpl_la-nanoftp.lo `test -f 'libxml/nanoftp.c' || echo '$(srcdir)/'`libxml/nanoftp.c + +libxml/libxml_rpl_la-nanohttp.lo: libxml/nanohttp.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxml_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxml/libxml_rpl_la-nanohttp.lo `test -f 'libxml/nanohttp.c' || echo '$(srcdir)/'`libxml/nanohttp.c + +libxml/libxml_rpl_la-parser.lo: libxml/parser.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxml_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxml/libxml_rpl_la-parser.lo `test -f 'libxml/parser.c' || echo '$(srcdir)/'`libxml/parser.c + +libxml/libxml_rpl_la-parserInternals.lo: libxml/parserInternals.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxml_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxml/libxml_rpl_la-parserInternals.lo `test -f 'libxml/parserInternals.c' || echo '$(srcdir)/'`libxml/parserInternals.c + +libxml/libxml_rpl_la-pattern.lo: libxml/pattern.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxml_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxml/libxml_rpl_la-pattern.lo `test -f 'libxml/pattern.c' || echo '$(srcdir)/'`libxml/pattern.c + +libxml/libxml_rpl_la-relaxng.lo: libxml/relaxng.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxml_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxml/libxml_rpl_la-relaxng.lo `test -f 'libxml/relaxng.c' || echo '$(srcdir)/'`libxml/relaxng.c + +libxml/libxml_rpl_la-schematron.lo: libxml/schematron.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxml_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxml/libxml_rpl_la-schematron.lo `test -f 'libxml/schematron.c' || echo '$(srcdir)/'`libxml/schematron.c + +libxml/libxml_rpl_la-threads.lo: libxml/threads.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxml_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxml/libxml_rpl_la-threads.lo `test -f 'libxml/threads.c' || echo '$(srcdir)/'`libxml/threads.c + +libxml/libxml_rpl_la-tree.lo: libxml/tree.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxml_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxml/libxml_rpl_la-tree.lo `test -f 'libxml/tree.c' || echo '$(srcdir)/'`libxml/tree.c + +libxml/libxml_rpl_la-uri.lo: libxml/uri.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxml_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxml/libxml_rpl_la-uri.lo `test -f 'libxml/uri.c' || echo '$(srcdir)/'`libxml/uri.c + +libxml/libxml_rpl_la-valid.lo: libxml/valid.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxml_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxml/libxml_rpl_la-valid.lo `test -f 'libxml/valid.c' || echo '$(srcdir)/'`libxml/valid.c + +libxml/libxml_rpl_la-xinclude.lo: libxml/xinclude.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxml_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxml/libxml_rpl_la-xinclude.lo `test -f 'libxml/xinclude.c' || echo '$(srcdir)/'`libxml/xinclude.c + +libxml/libxml_rpl_la-xlink.lo: libxml/xlink.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxml_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxml/libxml_rpl_la-xlink.lo `test -f 'libxml/xlink.c' || echo '$(srcdir)/'`libxml/xlink.c + +libxml/libxml_rpl_la-xmlIO.lo: libxml/xmlIO.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxml_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxml/libxml_rpl_la-xmlIO.lo `test -f 'libxml/xmlIO.c' || echo '$(srcdir)/'`libxml/xmlIO.c + +libxml/libxml_rpl_la-xmlmemory.lo: libxml/xmlmemory.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxml_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxml/libxml_rpl_la-xmlmemory.lo `test -f 'libxml/xmlmemory.c' || echo '$(srcdir)/'`libxml/xmlmemory.c + +libxml/libxml_rpl_la-xmlmodule.lo: libxml/xmlmodule.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxml_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxml/libxml_rpl_la-xmlmodule.lo `test -f 'libxml/xmlmodule.c' || echo '$(srcdir)/'`libxml/xmlmodule.c + +libxml/libxml_rpl_la-xmlreader.lo: libxml/xmlreader.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxml_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxml/libxml_rpl_la-xmlreader.lo `test -f 'libxml/xmlreader.c' || echo '$(srcdir)/'`libxml/xmlreader.c + +libxml/libxml_rpl_la-xmlregexp.lo: libxml/xmlregexp.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxml_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxml/libxml_rpl_la-xmlregexp.lo `test -f 'libxml/xmlregexp.c' || echo '$(srcdir)/'`libxml/xmlregexp.c + +libxml/libxml_rpl_la-xmlsave.lo: libxml/xmlsave.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxml_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxml/libxml_rpl_la-xmlsave.lo `test -f 'libxml/xmlsave.c' || echo '$(srcdir)/'`libxml/xmlsave.c + +libxml/libxml_rpl_la-xmlschemas.lo: libxml/xmlschemas.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxml_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxml/libxml_rpl_la-xmlschemas.lo `test -f 'libxml/xmlschemas.c' || echo '$(srcdir)/'`libxml/xmlschemas.c + +libxml/libxml_rpl_la-xmlschemastypes.lo: libxml/xmlschemastypes.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxml_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxml/libxml_rpl_la-xmlschemastypes.lo `test -f 'libxml/xmlschemastypes.c' || echo '$(srcdir)/'`libxml/xmlschemastypes.c + +libxml/libxml_rpl_la-xmlstring.lo: libxml/xmlstring.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxml_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxml/libxml_rpl_la-xmlstring.lo `test -f 'libxml/xmlstring.c' || echo '$(srcdir)/'`libxml/xmlstring.c + +libxml/libxml_rpl_la-xmlunicode.lo: libxml/xmlunicode.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxml_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxml/libxml_rpl_la-xmlunicode.lo `test -f 'libxml/xmlunicode.c' || echo '$(srcdir)/'`libxml/xmlunicode.c + +libxml/libxml_rpl_la-xmlwriter.lo: libxml/xmlwriter.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxml_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxml/libxml_rpl_la-xmlwriter.lo `test -f 'libxml/xmlwriter.c' || echo '$(srcdir)/'`libxml/xmlwriter.c + +libxml/libxml_rpl_la-xpath.lo: libxml/xpath.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxml_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxml/libxml_rpl_la-xpath.lo `test -f 'libxml/xpath.c' || echo '$(srcdir)/'`libxml/xpath.c + +libxml/libxml_rpl_la-xpointer.lo: libxml/xpointer.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxml_rpl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxml/libxml_rpl_la-xpointer.lo `test -f 'libxml/xpointer.c' || echo '$(srcdir)/'`libxml/xpointer.c + +.cc.o: + $(AM_V_CXX)$(CXXCOMPILE) -c -o $@ $< + +.cc.obj: + $(AM_V_CXX)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cc.lo: + $(AM_V_CXX)$(LTCXXCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + -rm -rf ../woe32dll/.libs ../woe32dll/_libs + -rm -rf glib/.libs glib/_libs + -rm -rf glthread/.libs glthread/_libs + -rm -rf libcroco/.libs libcroco/_libs + -rm -rf libxml/.libs libxml/_libs + -rm -rf uniconv/.libs uniconv/_libs + -rm -rf unilbrk/.libs unilbrk/_libs + -rm -rf uniname/.libs uniname/_libs + -rm -rf unistr/.libs unistr/_libs + -rm -rf uniwidth/.libs uniwidth/_libs +install-gettextsrcDATA: $(gettextsrc_DATA) + @$(NORMAL_INSTALL) + @list='$(gettextsrc_DATA)'; test -n "$(gettextsrcdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(gettextsrcdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(gettextsrcdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(gettextsrcdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(gettextsrcdir)" || exit $$?; \ + done + +uninstall-gettextsrcDATA: + @$(NORMAL_UNINSTALL) + @list='$(gettextsrc_DATA)'; test -n "$(gettextsrcdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(gettextsrcdir)'; $(am__uninstall_files_from_dir) +install-pkgdataDATA: $(pkgdata_DATA) + @$(NORMAL_INSTALL) + @list='$(pkgdata_DATA)'; test -n "$(pkgdatadir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkgdatadir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkgdatadir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgdatadir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgdatadir)" || exit $$?; \ + done + +uninstall-pkgdataDATA: + @$(NORMAL_UNINSTALL) + @list='$(pkgdata_DATA)'; test -n "$(pkgdatadir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(pkgdatadir)'; $(am__uninstall_files_from_dir) + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-am +all-am: Makefile $(LTLIBRARIES) $(DATA) all-local +installdirs: + for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(gettextsrcdir)" "$(DESTDIR)$(pkgdatadir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -rm -f ../woe32dll/$(am__dirstamp) + -rm -f glib/$(am__dirstamp) + -rm -f glthread/$(am__dirstamp) + -rm -f libcroco/$(am__dirstamp) + -rm -f libxml/$(am__dirstamp) + -rm -f uniconv/$(am__dirstamp) + -rm -f unilbrk/$(am__dirstamp) + -rm -f uniname/$(am__dirstamp) + -rm -f unistr/$(am__dirstamp) + -rm -f uniwidth/$(am__dirstamp) + -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) + -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) +@RELOCATABLE_VIA_WRAPPER_FALSE@uninstall-hook: +clean: clean-am + +clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ + clean-noinstLTLIBRARIES mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-gettextsrcDATA install-pkgdataDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-exec-local install-libLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool mostlyclean-local + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-gettextsrcDATA uninstall-libLTLIBRARIES \ + uninstall-local uninstall-pkgdataDATA + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) uninstall-hook +.MAKE: all check install install-am install-strip uninstall-am + +.PHONY: CTAGS GTAGS TAGS all all-am all-local check check-am clean \ + clean-generic clean-libLTLIBRARIES clean-libtool \ + clean-noinstLTLIBRARIES cscopelist-am ctags ctags-am distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-exec-local \ + install-gettextsrcDATA install-html install-html-am \ + install-info install-info-am install-libLTLIBRARIES \ + install-man install-pdf install-pdf-am install-pkgdataDATA \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool mostlyclean-local pdf \ + pdf-am ps ps-am tags tags-am uninstall uninstall-am \ + uninstall-gettextsrcDATA uninstall-hook \ + uninstall-libLTLIBRARIES uninstall-local uninstall-pkgdataDATA + + +# We need the following in order to create when the system +# doesn't have one that works with the given compiler. +@GL_GENERATE_ALLOCA_H_TRUE@alloca.h: alloca.in.h $(top_builddir)/config.status +@GL_GENERATE_ALLOCA_H_TRUE@ $(AM_V_GEN)rm -f $@-t $@ && \ +@GL_GENERATE_ALLOCA_H_TRUE@ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ +@GL_GENERATE_ALLOCA_H_TRUE@ cat $(srcdir)/alloca.in.h; \ +@GL_GENERATE_ALLOCA_H_TRUE@ } > $@-t && \ +@GL_GENERATE_ALLOCA_H_TRUE@ mv -f $@-t $@ +@GL_GENERATE_ALLOCA_H_FALSE@alloca.h: $(top_builddir)/config.status +@GL_GENERATE_ALLOCA_H_FALSE@ rm -f $@ + +# We need the following in order to create when the system +# doesn't have one. +@GL_GENERATE_BYTESWAP_H_TRUE@byteswap.h: byteswap.in.h $(top_builddir)/config.status +@GL_GENERATE_BYTESWAP_H_TRUE@ $(AM_V_GEN)rm -f $@-t $@ && \ +@GL_GENERATE_BYTESWAP_H_TRUE@ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ +@GL_GENERATE_BYTESWAP_H_TRUE@ cat $(srcdir)/byteswap.in.h; \ +@GL_GENERATE_BYTESWAP_H_TRUE@ } > $@-t && \ +@GL_GENERATE_BYTESWAP_H_TRUE@ mv -f $@-t $@ +@GL_GENERATE_BYTESWAP_H_FALSE@byteswap.h: $(top_builddir)/config.status +@GL_GENERATE_BYTESWAP_H_FALSE@ rm -f $@ + +# Listed in the same order as the GNU makefile conventions, and +# provided by autoconf 2.59c+ or 2.70. +# The Automake-defined pkg* macros are appended, in the order +# listed in the Automake 1.10a+ documentation. +configmake.h: Makefile + $(AM_V_GEN)rm -f $@-t && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + echo '#define PREFIX "$(prefix)"'; \ + echo '#define EXEC_PREFIX "$(exec_prefix)"'; \ + echo '#define BINDIR "$(bindir)"'; \ + echo '#define SBINDIR "$(sbindir)"'; \ + echo '#define LIBEXECDIR "$(libexecdir)"'; \ + echo '#define DATAROOTDIR "$(datarootdir)"'; \ + echo '#define DATADIR "$(datadir)"'; \ + echo '#define SYSCONFDIR "$(sysconfdir)"'; \ + echo '#define SHAREDSTATEDIR "$(sharedstatedir)"'; \ + echo '#define LOCALSTATEDIR "$(localstatedir)"'; \ + echo '#define RUNSTATEDIR "$(runstatedir)"'; \ + echo '#define INCLUDEDIR "$(includedir)"'; \ + echo '#define OLDINCLUDEDIR "$(oldincludedir)"'; \ + echo '#define DOCDIR "$(docdir)"'; \ + echo '#define INFODIR "$(infodir)"'; \ + echo '#define HTMLDIR "$(htmldir)"'; \ + echo '#define DVIDIR "$(dvidir)"'; \ + echo '#define PDFDIR "$(pdfdir)"'; \ + echo '#define PSDIR "$(psdir)"'; \ + echo '#define LIBDIR "$(libdir)"'; \ + echo '#define LISPDIR "$(lispdir)"'; \ + echo '#define LOCALEDIR "$(localedir)"'; \ + echo '#define MANDIR "$(mandir)"'; \ + echo '#define MANEXT "$(manext)"'; \ + echo '#define PKGDATADIR "$(pkgdatadir)"'; \ + echo '#define PKGINCLUDEDIR "$(pkgincludedir)"'; \ + echo '#define PKGLIBDIR "$(pkglibdir)"'; \ + echo '#define PKGLIBEXECDIR "$(pkglibexecdir)"'; \ + } | sed '/""/d' > $@-t && \ + mv -f $@-t $@ + +# We need the following in order to create when the system +# doesn't have one that works with the given compiler. +dirent.h: dirent.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''HAVE_DIRENT_H''@|$(HAVE_DIRENT_H)|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_DIRENT_H''@|$(NEXT_DIRENT_H)|g' \ + -e 's/@''GNULIB_OPENDIR''@/$(GNULIB_OPENDIR)/g' \ + -e 's/@''GNULIB_READDIR''@/$(GNULIB_READDIR)/g' \ + -e 's/@''GNULIB_REWINDDIR''@/$(GNULIB_REWINDDIR)/g' \ + -e 's/@''GNULIB_CLOSEDIR''@/$(GNULIB_CLOSEDIR)/g' \ + -e 's/@''GNULIB_DIRFD''@/$(GNULIB_DIRFD)/g' \ + -e 's/@''GNULIB_FDOPENDIR''@/$(GNULIB_FDOPENDIR)/g' \ + -e 's/@''GNULIB_SCANDIR''@/$(GNULIB_SCANDIR)/g' \ + -e 's/@''GNULIB_ALPHASORT''@/$(GNULIB_ALPHASORT)/g' \ + -e 's/@''HAVE_OPENDIR''@/$(HAVE_OPENDIR)/g' \ + -e 's/@''HAVE_READDIR''@/$(HAVE_READDIR)/g' \ + -e 's/@''HAVE_REWINDDIR''@/$(HAVE_REWINDDIR)/g' \ + -e 's/@''HAVE_CLOSEDIR''@/$(HAVE_CLOSEDIR)/g' \ + -e 's|@''HAVE_DECL_DIRFD''@|$(HAVE_DECL_DIRFD)|g' \ + -e 's|@''HAVE_DECL_FDOPENDIR''@|$(HAVE_DECL_FDOPENDIR)|g' \ + -e 's|@''HAVE_FDOPENDIR''@|$(HAVE_FDOPENDIR)|g' \ + -e 's|@''HAVE_SCANDIR''@|$(HAVE_SCANDIR)|g' \ + -e 's|@''HAVE_ALPHASORT''@|$(HAVE_ALPHASORT)|g' \ + -e 's|@''REPLACE_OPENDIR''@|$(REPLACE_OPENDIR)|g' \ + -e 's|@''REPLACE_CLOSEDIR''@|$(REPLACE_CLOSEDIR)|g' \ + -e 's|@''REPLACE_DIRFD''@|$(REPLACE_DIRFD)|g' \ + -e 's|@''REPLACE_FDOPENDIR''@|$(REPLACE_FDOPENDIR)|g' \ + -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ + < $(srcdir)/dirent.in.h; \ + } > $@-t && \ + mv $@-t $@ + +# We need the following in order to create when the system +# doesn't have one that is POSIX compliant. +@GL_GENERATE_ERRNO_H_TRUE@errno.h: errno.in.h $(top_builddir)/config.status +@GL_GENERATE_ERRNO_H_TRUE@ $(AM_V_GEN)rm -f $@-t $@ && \ +@GL_GENERATE_ERRNO_H_TRUE@ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ +@GL_GENERATE_ERRNO_H_TRUE@ sed -e 's|@''GUARD_PREFIX''@|GL|g' \ +@GL_GENERATE_ERRNO_H_TRUE@ -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ +@GL_GENERATE_ERRNO_H_TRUE@ -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ +@GL_GENERATE_ERRNO_H_TRUE@ -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ +@GL_GENERATE_ERRNO_H_TRUE@ -e 's|@''NEXT_ERRNO_H''@|$(NEXT_ERRNO_H)|g' \ +@GL_GENERATE_ERRNO_H_TRUE@ -e 's|@''EMULTIHOP_HIDDEN''@|$(EMULTIHOP_HIDDEN)|g' \ +@GL_GENERATE_ERRNO_H_TRUE@ -e 's|@''EMULTIHOP_VALUE''@|$(EMULTIHOP_VALUE)|g' \ +@GL_GENERATE_ERRNO_H_TRUE@ -e 's|@''ENOLINK_HIDDEN''@|$(ENOLINK_HIDDEN)|g' \ +@GL_GENERATE_ERRNO_H_TRUE@ -e 's|@''ENOLINK_VALUE''@|$(ENOLINK_VALUE)|g' \ +@GL_GENERATE_ERRNO_H_TRUE@ -e 's|@''EOVERFLOW_HIDDEN''@|$(EOVERFLOW_HIDDEN)|g' \ +@GL_GENERATE_ERRNO_H_TRUE@ -e 's|@''EOVERFLOW_VALUE''@|$(EOVERFLOW_VALUE)|g' \ +@GL_GENERATE_ERRNO_H_TRUE@ < $(srcdir)/errno.in.h; \ +@GL_GENERATE_ERRNO_H_TRUE@ } > $@-t && \ +@GL_GENERATE_ERRNO_H_TRUE@ mv $@-t $@ +@GL_GENERATE_ERRNO_H_FALSE@errno.h: $(top_builddir)/config.status +@GL_GENERATE_ERRNO_H_FALSE@ rm -f $@ + +# We need the following in order to create when the system +# doesn't have one that works with the given compiler. +fcntl.h: fcntl.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_FCNTL_H''@|$(NEXT_FCNTL_H)|g' \ + -e 's/@''GNULIB_FCNTL''@/$(GNULIB_FCNTL)/g' \ + -e 's/@''GNULIB_NONBLOCKING''@/$(GNULIB_NONBLOCKING)/g' \ + -e 's/@''GNULIB_OPEN''@/$(GNULIB_OPEN)/g' \ + -e 's/@''GNULIB_OPENAT''@/$(GNULIB_OPENAT)/g' \ + -e 's|@''HAVE_FCNTL''@|$(HAVE_FCNTL)|g' \ + -e 's|@''HAVE_OPENAT''@|$(HAVE_OPENAT)|g' \ + -e 's|@''REPLACE_FCNTL''@|$(REPLACE_FCNTL)|g' \ + -e 's|@''REPLACE_OPEN''@|$(REPLACE_OPEN)|g' \ + -e 's|@''REPLACE_OPENAT''@|$(REPLACE_OPENAT)|g' \ + -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ + < $(srcdir)/fcntl.in.h; \ + } > $@-t && \ + mv $@-t $@ +# This is a Makefile rule that generates multiple files at once; see the +# automake documentation, node "Multiple Outputs", for details. +fd-ostream.h : $(top_srcdir)/../build-aux/moopp fd-ostream.oo.h fd-ostream.oo.c ostream.oo.h + $(top_srcdir)/../build-aux/moopp $(MOOPPFLAGS) $(srcdir)/fd-ostream.oo.c $(srcdir)/fd-ostream.oo.h $(srcdir)/ostream.oo.h +fd-ostream.c fd_ostream.priv.h fd_ostream.vt.h : fd-ostream.h + @test -f $@ || { \ + trap 'rm -rf fd-ostream.lock' 1 2 13 15; \ + if mkdir fd-ostream.lock 2>/dev/null; then \ + echo "$(top_srcdir)/../build-aux/moopp $(MOOPPFLAGS) $(srcdir)/fd-ostream.oo.c $(srcdir)/fd-ostream.oo.h $(srcdir)/ostream.oo.h"; \ + $(top_srcdir)/../build-aux/moopp $(MOOPPFLAGS) $(srcdir)/fd-ostream.oo.c $(srcdir)/fd-ostream.oo.h $(srcdir)/ostream.oo.h; \ + result=$$?; rm -rf fd-ostream.lock; exit $$result; \ + else \ + while test -d fd-ostream.lock; do sleep 1; done; \ + test -f $(srcdir)/fd-ostream.h; \ + fi; \ + } +# This is a Makefile rule that generates multiple files at once; see the +# automake documentation, node "Multiple Outputs", for details. +file-ostream.h : $(top_srcdir)/../build-aux/moopp file-ostream.oo.h file-ostream.oo.c ostream.oo.h + $(top_srcdir)/../build-aux/moopp $(MOOPPFLAGS) $(srcdir)/file-ostream.oo.c $(srcdir)/file-ostream.oo.h $(srcdir)/ostream.oo.h +file-ostream.c file_ostream.priv.h file_ostream.vt.h : file-ostream.h + @test -f $@ || { \ + trap 'rm -rf file-ostream.lock' 1 2 13 15; \ + if mkdir file-ostream.lock 2>/dev/null; then \ + echo "$(top_srcdir)/../build-aux/moopp $(MOOPPFLAGS) $(srcdir)/file-ostream.oo.c $(srcdir)/file-ostream.oo.h $(srcdir)/ostream.oo.h"; \ + $(top_srcdir)/../build-aux/moopp $(MOOPPFLAGS) $(srcdir)/file-ostream.oo.c $(srcdir)/file-ostream.oo.h $(srcdir)/ostream.oo.h; \ + result=$$?; rm -rf file-ostream.lock; exit $$result; \ + else \ + while test -d file-ostream.lock; do sleep 1; done; \ + test -f $(srcdir)/file-ostream.h; \ + fi; \ + } + +# We need the following in order to create when the system +# doesn't have one that works with the given compiler. +@GL_GENERATE_FLOAT_H_TRUE@float.h: float.in.h $(top_builddir)/config.status +@GL_GENERATE_FLOAT_H_TRUE@ $(AM_V_GEN)rm -f $@-t $@ && \ +@GL_GENERATE_FLOAT_H_TRUE@ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ +@GL_GENERATE_FLOAT_H_TRUE@ sed -e 's|@''GUARD_PREFIX''@|GL|g' \ +@GL_GENERATE_FLOAT_H_TRUE@ -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ +@GL_GENERATE_FLOAT_H_TRUE@ -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ +@GL_GENERATE_FLOAT_H_TRUE@ -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ +@GL_GENERATE_FLOAT_H_TRUE@ -e 's|@''NEXT_FLOAT_H''@|$(NEXT_FLOAT_H)|g' \ +@GL_GENERATE_FLOAT_H_TRUE@ -e 's|@''REPLACE_ITOLD''@|$(REPLACE_ITOLD)|g' \ +@GL_GENERATE_FLOAT_H_TRUE@ < $(srcdir)/float.in.h; \ +@GL_GENERATE_FLOAT_H_TRUE@ } > $@-t && \ +@GL_GENERATE_FLOAT_H_TRUE@ mv $@-t $@ +@GL_GENERATE_FLOAT_H_FALSE@float.h: $(top_builddir)/config.status +@GL_GENERATE_FLOAT_H_FALSE@ rm -f $@ + +# We need the following in order to create when the system +# doesn't have one that supports the required API. +@GL_GENERATE_FNMATCH_H_TRUE@fnmatch.h: fnmatch.in.h $(top_builddir)/config.status $(ARG_NONNULL_H) +@GL_GENERATE_FNMATCH_H_TRUE@ $(AM_V_GEN)rm -f $@-t $@ && \ +@GL_GENERATE_FNMATCH_H_TRUE@ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ +@GL_GENERATE_FNMATCH_H_TRUE@ sed -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ +@GL_GENERATE_FNMATCH_H_TRUE@ < $(srcdir)/fnmatch.in.h; \ +@GL_GENERATE_FNMATCH_H_TRUE@ } > $@-t && \ +@GL_GENERATE_FNMATCH_H_TRUE@ mv -f $@-t $@ +@GL_GENERATE_FNMATCH_H_FALSE@fnmatch.h: $(top_builddir)/config.status +@GL_GENERATE_FNMATCH_H_FALSE@ rm -f $@ + +# We need the following in order to create when the system +# doesn't have one that works with the given compiler. +getopt.h: getopt.in.h $(top_builddir)/config.status $(ARG_NONNULL_H) + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''HAVE_GETOPT_H''@|$(HAVE_GETOPT_H)|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_GETOPT_H''@|$(NEXT_GETOPT_H)|g' \ + -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ + < $(srcdir)/getopt.in.h; \ + } > $@-t && \ + mv -f $@-t $@ + +# No need to install libgettextlib.a, except on AIX. +install-exec-local: install-libLTLIBRARIES install-exec-clean +install-exec-clean: + case "@host_os@" in \ + aix*) ;; \ + *) rm -f $(DESTDIR)$(libdir)/libgettextlib.a ;; \ + esac +# This is a Makefile rule that generates multiple files at once; see the +# automake documentation, node "Multiple Outputs", for details. +html-ostream.h : $(top_srcdir)/../build-aux/moopp html-ostream.oo.h html-ostream.oo.c ostream.oo.h + $(top_srcdir)/../build-aux/moopp $(MOOPPFLAGS) $(srcdir)/html-ostream.oo.c $(srcdir)/html-ostream.oo.h $(srcdir)/ostream.oo.h +html-ostream.c html_ostream.priv.h html_ostream.vt.h : html-ostream.h + @test -f $@ || { \ + trap 'rm -rf html-ostream.lock' 1 2 13 15; \ + if mkdir html-ostream.lock 2>/dev/null; then \ + echo "$(top_srcdir)/../build-aux/moopp $(MOOPPFLAGS) $(srcdir)/html-ostream.oo.c $(srcdir)/html-ostream.oo.h $(srcdir)/ostream.oo.h"; \ + $(top_srcdir)/../build-aux/moopp $(MOOPPFLAGS) $(srcdir)/html-ostream.oo.c $(srcdir)/html-ostream.oo.h $(srcdir)/ostream.oo.h; \ + result=$$?; rm -rf html-ostream.lock; exit $$result; \ + else \ + while test -d html-ostream.lock; do sleep 1; done; \ + test -f $(srcdir)/html-ostream.h; \ + fi; \ + } +# This is a Makefile rule that generates multiple files at once; see the +# automake documentation, node "Multiple Outputs", for details. +html-styled-ostream.h : $(top_srcdir)/../build-aux/moopp html-styled-ostream.oo.h html-styled-ostream.oo.c styled-ostream.oo.h ostream.oo.h + $(top_srcdir)/../build-aux/moopp $(MOOPPFLAGS) $(srcdir)/html-styled-ostream.oo.c $(srcdir)/html-styled-ostream.oo.h $(srcdir)/styled-ostream.oo.h $(srcdir)/ostream.oo.h +html-styled-ostream.c html_styled_ostream.priv.h html_styled_ostream.vt.h : html-styled-ostream.h + @test -f $@ || { \ + trap 'rm -rf html-styled-ostream.lock' 1 2 13 15; \ + if mkdir html-styled-ostream.lock 2>/dev/null; then \ + echo "$(top_srcdir)/../build-aux/moopp $(MOOPPFLAGS) $(srcdir)/html-styled-ostream.oo.c $(srcdir)/html-styled-ostream.oo.h $(srcdir)/styled-ostream.oo.h $(srcdir)/ostream.oo.h"; \ + $(top_srcdir)/../build-aux/moopp $(MOOPPFLAGS) $(srcdir)/html-styled-ostream.oo.c $(srcdir)/html-styled-ostream.oo.h $(srcdir)/styled-ostream.oo.h $(srcdir)/ostream.oo.h; \ + result=$$?; rm -rf html-styled-ostream.lock; exit $$result; \ + else \ + while test -d html-styled-ostream.lock; do sleep 1; done; \ + test -f $(srcdir)/html-styled-ostream.h; \ + fi; \ + } + +# We need the following in order to create when the system +# doesn't have one that works with the given compiler. +@GL_GENERATE_ICONV_H_TRUE@iconv.h: iconv.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) +@GL_GENERATE_ICONV_H_TRUE@ $(AM_V_GEN)rm -f $@-t $@ && \ +@GL_GENERATE_ICONV_H_TRUE@ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ +@GL_GENERATE_ICONV_H_TRUE@ sed -e 's|@''GUARD_PREFIX''@|GL|g' \ +@GL_GENERATE_ICONV_H_TRUE@ -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ +@GL_GENERATE_ICONV_H_TRUE@ -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ +@GL_GENERATE_ICONV_H_TRUE@ -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ +@GL_GENERATE_ICONV_H_TRUE@ -e 's|@''NEXT_ICONV_H''@|$(NEXT_ICONV_H)|g' \ +@GL_GENERATE_ICONV_H_TRUE@ -e 's/@''GNULIB_ICONV''@/$(GNULIB_ICONV)/g' \ +@GL_GENERATE_ICONV_H_TRUE@ -e 's|@''ICONV_CONST''@|$(ICONV_CONST)|g' \ +@GL_GENERATE_ICONV_H_TRUE@ -e 's|@''REPLACE_ICONV''@|$(REPLACE_ICONV)|g' \ +@GL_GENERATE_ICONV_H_TRUE@ -e 's|@''REPLACE_ICONV_OPEN''@|$(REPLACE_ICONV_OPEN)|g' \ +@GL_GENERATE_ICONV_H_TRUE@ -e 's|@''REPLACE_ICONV_UTF''@|$(REPLACE_ICONV_UTF)|g' \ +@GL_GENERATE_ICONV_H_TRUE@ -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ +@GL_GENERATE_ICONV_H_TRUE@ -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ +@GL_GENERATE_ICONV_H_TRUE@ -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ +@GL_GENERATE_ICONV_H_TRUE@ < $(srcdir)/iconv.in.h; \ +@GL_GENERATE_ICONV_H_TRUE@ } > $@-t && \ +@GL_GENERATE_ICONV_H_TRUE@ mv $@-t $@ +@GL_GENERATE_ICONV_H_FALSE@iconv.h: $(top_builddir)/config.status +@GL_GENERATE_ICONV_H_FALSE@ rm -f $@ + +iconv_open-aix.h: iconv_open-aix.gperf + $(GPERF) -m 10 $(srcdir)/iconv_open-aix.gperf > $(srcdir)/iconv_open-aix.h-t + mv $(srcdir)/iconv_open-aix.h-t $(srcdir)/iconv_open-aix.h +iconv_open-hpux.h: iconv_open-hpux.gperf + $(GPERF) -m 10 $(srcdir)/iconv_open-hpux.gperf > $(srcdir)/iconv_open-hpux.h-t + mv $(srcdir)/iconv_open-hpux.h-t $(srcdir)/iconv_open-hpux.h +iconv_open-irix.h: iconv_open-irix.gperf + $(GPERF) -m 10 $(srcdir)/iconv_open-irix.gperf > $(srcdir)/iconv_open-irix.h-t + mv $(srcdir)/iconv_open-irix.h-t $(srcdir)/iconv_open-irix.h +iconv_open-osf.h: iconv_open-osf.gperf + $(GPERF) -m 10 $(srcdir)/iconv_open-osf.gperf > $(srcdir)/iconv_open-osf.h-t + mv $(srcdir)/iconv_open-osf.h-t $(srcdir)/iconv_open-osf.h +iconv_open-solaris.h: iconv_open-solaris.gperf + $(GPERF) -m 10 $(srcdir)/iconv_open-solaris.gperf > $(srcdir)/iconv_open-solaris.h-t + mv $(srcdir)/iconv_open-solaris.h-t $(srcdir)/iconv_open-solaris.h + +glib.h: glib.in.h + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/glib.in.h; \ + } > $@-t + mv -f $@-t $@ + +glibconfig.h: glibconfig.in.h + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/glibconfig.in.h; \ + } > $@-t + mv -f $@-t $@ + +glib/ghash.h: glib/ghash.in.h + test -d glib || $(MKDIR_P) glib + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/glib/ghash.in.h; \ + } > $@-t + mv -f $@-t $@ + +glib/glist.h: glib/glist.in.h + test -d glib || $(MKDIR_P) glib + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/glib/glist.in.h; \ + } > $@-t + mv -f $@-t $@ + +glib/gprimes.h: glib/gprimes.in.h + test -d glib || $(MKDIR_P) glib + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/glib/gprimes.in.h; \ + } > $@-t + mv -f $@-t $@ + +glib/gstrfuncs.h: glib/gstrfuncs.in.h + test -d glib || $(MKDIR_P) glib + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/glib/gstrfuncs.in.h; \ + } > $@-t + mv -f $@-t $@ + +glib/gstring.h: glib/gstring.in.h + test -d glib || $(MKDIR_P) glib + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/glib/gstring.in.h; \ + } > $@-t + mv -f $@-t $@ + +glib/gtypes.h: glib/gtypes.in.h + test -d glib || $(MKDIR_P) glib + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/glib/gtypes.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/DOCBparser.h: libxml/DOCBparser.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/DOCBparser.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/HTMLparser.h: libxml/HTMLparser.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/HTMLparser.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/HTMLtree.h: libxml/HTMLtree.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/HTMLtree.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/SAX.h: libxml/SAX.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/SAX.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/SAX2.h: libxml/SAX2.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/SAX2.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/c14n.h: libxml/c14n.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/c14n.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/catalog.h: libxml/catalog.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/catalog.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/chvalid.h: libxml/chvalid.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/chvalid.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/debugXML.h: libxml/debugXML.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/debugXML.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/dict.h: libxml/dict.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/dict.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/encoding.h: libxml/encoding.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/encoding.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/entities.h: libxml/entities.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/entities.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/globals.h: libxml/globals.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/globals.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/hash.h: libxml/hash.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/hash.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/list.h: libxml/list.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/list.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/nanoftp.h: libxml/nanoftp.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/nanoftp.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/nanohttp.h: libxml/nanohttp.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/nanohttp.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/parser.h: libxml/parser.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/parser.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/parserInternals.h: libxml/parserInternals.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/parserInternals.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/pattern.h: libxml/pattern.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/pattern.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/relaxng.h: libxml/relaxng.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/relaxng.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/schemasInternals.h: libxml/schemasInternals.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/schemasInternals.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/schematron.h: libxml/schematron.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/schematron.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/threads.h: libxml/threads.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/threads.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/tree.h: libxml/tree.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/tree.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/uri.h: libxml/uri.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/uri.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/valid.h: libxml/valid.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/valid.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/xinclude.h: libxml/xinclude.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/xinclude.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/xlink.h: libxml/xlink.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/xlink.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/xmlIO.h: libxml/xmlIO.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/xmlIO.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/xmlautomata.h: libxml/xmlautomata.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/xmlautomata.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/xmlerror.h: libxml/xmlerror.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/xmlerror.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/xmlexports.h: libxml/xmlexports.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/xmlexports.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/xmlmemory.h: libxml/xmlmemory.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/xmlmemory.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/xmlmodule.h: libxml/xmlmodule.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/xmlmodule.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/xmlreader.h: libxml/xmlreader.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/xmlreader.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/xmlregexp.h: libxml/xmlregexp.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/xmlregexp.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/xmlsave.h: libxml/xmlsave.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/xmlsave.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/xmlschemas.h: libxml/xmlschemas.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/xmlschemas.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/xmlschemastypes.h: libxml/xmlschemastypes.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/xmlschemastypes.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/xmlstring.h: libxml/xmlstring.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/xmlstring.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/xmlunicode.h: libxml/xmlunicode.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/xmlunicode.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/xmlversion.h: libxml/xmlversion.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/xmlversion.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/xmlwriter.h: libxml/xmlwriter.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/xmlwriter.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/xpath.h: libxml/xpath.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/xpath.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/xpathInternals.h: libxml/xpathInternals.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/xpathInternals.in.h; \ + } > $@-t + mv -f $@-t $@ + +libxml/xpointer.h: libxml/xpointer.in.h + test -d libxml || $(MKDIR_P) libxml + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/libxml/xpointer.in.h; \ + } > $@-t + mv -f $@-t $@ + +# We need the following in order to install a simple file in $(libdir) +# which is shared with other installed packages. We use a list of referencing +# packages so that "make uninstall" will remove the file if and only if it +# is not used by another installed package. +# On systems with glibc-2.1 or newer, the file is redundant, therefore we +# avoid installing it. + +all-local: charset.alias ref-add.sed ref-del.sed +install-exec-local: install-exec-localcharset +install-exec-localcharset: all-local + if test $(GLIBC21) = no; then \ + case '$(host_os)' in \ + darwin[56]*) \ + need_charset_alias=true ;; \ + darwin* | cygwin* | mingw* | pw32* | cegcc*) \ + need_charset_alias=false ;; \ + *) \ + need_charset_alias=true ;; \ + esac ; \ + else \ + need_charset_alias=false ; \ + fi ; \ + if $$need_charset_alias; then \ + $(mkinstalldirs) $(DESTDIR)$(libdir) ; \ + fi ; \ + if test -f $(charset_alias); then \ + sed -f ref-add.sed $(charset_alias) > $(charset_tmp) ; \ + $(INSTALL_DATA) $(charset_tmp) $(charset_alias) ; \ + rm -f $(charset_tmp) ; \ + else \ + if $$need_charset_alias; then \ + sed -f ref-add.sed charset.alias > $(charset_tmp) ; \ + $(INSTALL_DATA) $(charset_tmp) $(charset_alias) ; \ + rm -f $(charset_tmp) ; \ + fi ; \ + fi + +uninstall-local: uninstall-localcharset +uninstall-localcharset: all-local + if test -f $(charset_alias); then \ + sed -f ref-del.sed $(charset_alias) > $(charset_tmp); \ + if grep '^# Packages using this file: $$' $(charset_tmp) \ + > /dev/null; then \ + rm -f $(charset_alias); \ + else \ + $(INSTALL_DATA) $(charset_tmp) $(charset_alias); \ + fi; \ + rm -f $(charset_tmp); \ + fi + +charset.alias: config.charset + $(AM_V_GEN)rm -f t-$@ $@ && \ + $(SHELL) $(srcdir)/config.charset '$(host)' > t-$@ && \ + mv t-$@ $@ +.sin.sed: + $(AM_V_GEN)rm -f t-$@ $@ && \ + sed -e '/^#/d' -e 's/@''PACKAGE''@/$(PACKAGE)/g' $< > t-$@ && \ + mv t-$@ $@ + +# We need the following in order to create when the system +# doesn't have one that provides all definitions. +locale.h: locale.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_LOCALE_H''@|$(NEXT_LOCALE_H)|g' \ + -e 's/@''GNULIB_LOCALECONV''@/$(GNULIB_LOCALECONV)/g' \ + -e 's/@''GNULIB_SETLOCALE''@/$(GNULIB_SETLOCALE)/g' \ + -e 's/@''GNULIB_DUPLOCALE''@/$(GNULIB_DUPLOCALE)/g' \ + -e 's|@''HAVE_DUPLOCALE''@|$(HAVE_DUPLOCALE)|g' \ + -e 's|@''HAVE_XLOCALE_H''@|$(HAVE_XLOCALE_H)|g' \ + -e 's|@''REPLACE_LOCALECONV''@|$(REPLACE_LOCALECONV)|g' \ + -e 's|@''REPLACE_SETLOCALE''@|$(REPLACE_SETLOCALE)|g' \ + -e 's|@''REPLACE_DUPLOCALE''@|$(REPLACE_DUPLOCALE)|g' \ + -e 's|@''REPLACE_STRUCT_LCONV''@|$(REPLACE_STRUCT_LCONV)|g' \ + -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ + < $(srcdir)/locale.in.h; \ + } > $@-t && \ + mv $@-t $@ +# This is a Makefile rule that generates multiple files at once; see the +# automake documentation, node "Multiple Outputs", for details. +ostream.h : $(top_srcdir)/../build-aux/moopp ostream.oo.h ostream.oo.c + $(top_srcdir)/../build-aux/moopp $(MOOPPFLAGS) $(srcdir)/ostream.oo.c $(srcdir)/ostream.oo.h +ostream.c ostream.priv.h ostream.vt.h : ostream.h + @test -f $@ || { \ + trap 'rm -rf ostream.lock' 1 2 13 15; \ + if mkdir ostream.lock 2>/dev/null; then \ + echo "$(top_srcdir)/../build-aux/moopp $(MOOPPFLAGS) $(srcdir)/ostream.oo.c $(srcdir)/ostream.oo.h"; \ + $(top_srcdir)/../build-aux/moopp $(MOOPPFLAGS) $(srcdir)/ostream.oo.c $(srcdir)/ostream.oo.h; \ + result=$$?; rm -rf ostream.lock; exit $$result; \ + else \ + while test -d ostream.lock; do sleep 1; done; \ + test -f $(srcdir)/ostream.h; \ + fi; \ + } +@RELOCATABLE_VIA_WRAPPER_TRUE@uninstall-hook: uninstall-relocwrapper +@RELOCATABLE_VIA_WRAPPER_TRUE@uninstall-relocwrapper: +@RELOCATABLE_VIA_WRAPPER_TRUE@ if test $(RELOCATABLE) = yes; then \ +@RELOCATABLE_VIA_WRAPPER_TRUE@ case '$(EXEEXT)' in \ +@RELOCATABLE_VIA_WRAPPER_TRUE@ .bin*) ;; \ +@RELOCATABLE_VIA_WRAPPER_TRUE@ *) cd $(top_builddir) && \ +@RELOCATABLE_VIA_WRAPPER_TRUE@ $(MAKE) $(AM_MAKEFLAGS) EXEEXT=.bin$(EXEEXT) \ +@RELOCATABLE_VIA_WRAPPER_TRUE@ AM_MAKEFLAGS='$(AM_MAKEFLAGS) EXEEXT=.bin$(EXEEXT)' \ +@RELOCATABLE_VIA_WRAPPER_TRUE@ uninstall ;; \ +@RELOCATABLE_VIA_WRAPPER_TRUE@ esac; \ +@RELOCATABLE_VIA_WRAPPER_TRUE@ fi +@RELOCATABLE_VIA_WRAPPER_TRUE@.PHONY: uninstall-relocwrapper + +# We need the following in order to create a replacement for when +# the system doesn't have one. +@GL_GENERATE_SCHED_H_TRUE@sched.h: sched.in.h $(top_builddir)/config.status +@GL_GENERATE_SCHED_H_TRUE@ $(AM_V_GEN)rm -f $@-t $@ && \ +@GL_GENERATE_SCHED_H_TRUE@ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ +@GL_GENERATE_SCHED_H_TRUE@ sed -e 's|@''GUARD_PREFIX''@|GL|g' \ +@GL_GENERATE_SCHED_H_TRUE@ -e 's|@''HAVE_SCHED_H''@|$(HAVE_SCHED_H)|g' \ +@GL_GENERATE_SCHED_H_TRUE@ -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ +@GL_GENERATE_SCHED_H_TRUE@ -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ +@GL_GENERATE_SCHED_H_TRUE@ -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ +@GL_GENERATE_SCHED_H_TRUE@ -e 's|@''NEXT_SCHED_H''@|$(NEXT_SCHED_H)|g' \ +@GL_GENERATE_SCHED_H_TRUE@ -e 's|@''HAVE_STRUCT_SCHED_PARAM''@|$(HAVE_STRUCT_SCHED_PARAM)|g' \ +@GL_GENERATE_SCHED_H_TRUE@ < $(srcdir)/sched.in.h; \ +@GL_GENERATE_SCHED_H_TRUE@ } > $@-t && \ +@GL_GENERATE_SCHED_H_TRUE@ mv $@-t $@ +@GL_GENERATE_SCHED_H_FALSE@sched.h: $(top_builddir)/config.status +@GL_GENERATE_SCHED_H_FALSE@ rm -f $@ + +# We need the following in order to create when the system +# doesn't have a complete one. +signal.h: signal.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_SIGNAL_H''@|$(NEXT_SIGNAL_H)|g' \ + -e 's|@''GNULIB_PTHREAD_SIGMASK''@|$(GNULIB_PTHREAD_SIGMASK)|g' \ + -e 's|@''GNULIB_RAISE''@|$(GNULIB_RAISE)|g' \ + -e 's/@''GNULIB_SIGNAL_H_SIGPIPE''@/$(GNULIB_SIGNAL_H_SIGPIPE)/g' \ + -e 's/@''GNULIB_SIGPROCMASK''@/$(GNULIB_SIGPROCMASK)/g' \ + -e 's/@''GNULIB_SIGACTION''@/$(GNULIB_SIGACTION)/g' \ + -e 's|@''HAVE_POSIX_SIGNALBLOCKING''@|$(HAVE_POSIX_SIGNALBLOCKING)|g' \ + -e 's|@''HAVE_PTHREAD_SIGMASK''@|$(HAVE_PTHREAD_SIGMASK)|g' \ + -e 's|@''HAVE_RAISE''@|$(HAVE_RAISE)|g' \ + -e 's|@''HAVE_SIGSET_T''@|$(HAVE_SIGSET_T)|g' \ + -e 's|@''HAVE_SIGINFO_T''@|$(HAVE_SIGINFO_T)|g' \ + -e 's|@''HAVE_SIGACTION''@|$(HAVE_SIGACTION)|g' \ + -e 's|@''HAVE_STRUCT_SIGACTION_SA_SIGACTION''@|$(HAVE_STRUCT_SIGACTION_SA_SIGACTION)|g' \ + -e 's|@''HAVE_TYPE_VOLATILE_SIG_ATOMIC_T''@|$(HAVE_TYPE_VOLATILE_SIG_ATOMIC_T)|g' \ + -e 's|@''HAVE_SIGHANDLER_T''@|$(HAVE_SIGHANDLER_T)|g' \ + -e 's|@''REPLACE_PTHREAD_SIGMASK''@|$(REPLACE_PTHREAD_SIGMASK)|g' \ + -e 's|@''REPLACE_RAISE''@|$(REPLACE_RAISE)|g' \ + -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ + < $(srcdir)/signal.in.h; \ + } > $@-t && \ + mv $@-t $@ +# The arg-nonnull.h that gets inserted into generated .h files is the same as +# build-aux/snippet/arg-nonnull.h, except that it has the copyright header cut +# off. +arg-nonnull.h: $(top_srcdir)/../build-aux/snippet/arg-nonnull.h + $(AM_V_GEN)rm -f $@-t $@ && \ + sed -n -e '/GL_ARG_NONNULL/,$$p' \ + < $(top_srcdir)/../build-aux/snippet/arg-nonnull.h \ + > $@-t && \ + mv $@-t $@ +# The c++defs.h that gets inserted into generated .h files is the same as +# build-aux/snippet/c++defs.h, except that it has the copyright header cut off. +c++defs.h: $(top_srcdir)/../build-aux/snippet/c++defs.h + $(AM_V_GEN)rm -f $@-t $@ && \ + sed -n -e '/_GL_CXXDEFS/,$$p' \ + < $(top_srcdir)/../build-aux/snippet/c++defs.h \ + > $@-t && \ + mv $@-t $@ +# The unused-parameter.h that gets inserted into generated .h files is the same +# as build-aux/snippet/unused-parameter.h, except that it has the copyright +# header cut off. +unused-parameter.h: $(top_srcdir)/../build-aux/snippet/unused-parameter.h + $(AM_V_GEN)rm -f $@-t $@ && \ + sed -n -e '/GL_UNUSED_PARAMETER/,$$p' \ + < $(top_srcdir)/../build-aux/snippet/unused-parameter.h \ + > $@-t && \ + mv $@-t $@ +# The warn-on-use.h that gets inserted into generated .h files is the same as +# build-aux/snippet/warn-on-use.h, except that it has the copyright header cut +# off. +warn-on-use.h: $(top_srcdir)/../build-aux/snippet/warn-on-use.h + $(AM_V_GEN)rm -f $@-t $@ && \ + sed -n -e '/^.ifndef/,$$p' \ + < $(top_srcdir)/../build-aux/snippet/warn-on-use.h \ + > $@-t && \ + mv $@-t $@ + +# We need the following in order to create a replacement for when +# the system doesn't have one. +spawn.h: spawn.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''HAVE_SPAWN_H''@|$(HAVE_SPAWN_H)|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_SPAWN_H''@|$(NEXT_SPAWN_H)|g' \ + -e 's/@''GNULIB_POSIX_SPAWN''@/$(GNULIB_POSIX_SPAWN)/g' \ + -e 's/@''GNULIB_POSIX_SPAWNP''@/$(GNULIB_POSIX_SPAWNP)/g' \ + -e 's/@''GNULIB_POSIX_SPAWN_FILE_ACTIONS_INIT''@/$(GNULIB_POSIX_SPAWN_FILE_ACTIONS_INIT)/g' \ + -e 's/@''GNULIB_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSE''@/$(GNULIB_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSE)/g' \ + -e 's/@''GNULIB_POSIX_SPAWN_FILE_ACTIONS_ADDDUP2''@/$(GNULIB_POSIX_SPAWN_FILE_ACTIONS_ADDDUP2)/g' \ + -e 's/@''GNULIB_POSIX_SPAWN_FILE_ACTIONS_ADDOPEN''@/$(GNULIB_POSIX_SPAWN_FILE_ACTIONS_ADDOPEN)/g' \ + -e 's/@''GNULIB_POSIX_SPAWN_FILE_ACTIONS_DESTROY''@/$(GNULIB_POSIX_SPAWN_FILE_ACTIONS_DESTROY)/g' \ + -e 's/@''GNULIB_POSIX_SPAWNATTR_INIT''@/$(GNULIB_POSIX_SPAWNATTR_INIT)/g' \ + -e 's/@''GNULIB_POSIX_SPAWNATTR_GETFLAGS''@/$(GNULIB_POSIX_SPAWNATTR_GETFLAGS)/g' \ + -e 's/@''GNULIB_POSIX_SPAWNATTR_SETFLAGS''@/$(GNULIB_POSIX_SPAWNATTR_SETFLAGS)/g' \ + -e 's/@''GNULIB_POSIX_SPAWNATTR_GETPGROUP''@/$(GNULIB_POSIX_SPAWNATTR_GETPGROUP)/g' \ + -e 's/@''GNULIB_POSIX_SPAWNATTR_SETPGROUP''@/$(GNULIB_POSIX_SPAWNATTR_SETPGROUP)/g' \ + -e 's/@''GNULIB_POSIX_SPAWNATTR_GETSCHEDPARAM''@/$(GNULIB_POSIX_SPAWNATTR_GETSCHEDPARAM)/g' \ + -e 's/@''GNULIB_POSIX_SPAWNATTR_SETSCHEDPARAM''@/$(GNULIB_POSIX_SPAWNATTR_SETSCHEDPARAM)/g' \ + -e 's/@''GNULIB_POSIX_SPAWNATTR_GETSCHEDPOLICY''@/$(GNULIB_POSIX_SPAWNATTR_GETSCHEDPOLICY)/g' \ + -e 's/@''GNULIB_POSIX_SPAWNATTR_SETSCHEDPOLICY''@/$(GNULIB_POSIX_SPAWNATTR_SETSCHEDPOLICY)/g' \ + -e 's/@''GNULIB_POSIX_SPAWNATTR_GETSIGDEFAULT''@/$(GNULIB_POSIX_SPAWNATTR_GETSIGDEFAULT)/g' \ + -e 's/@''GNULIB_POSIX_SPAWNATTR_SETSIGDEFAULT''@/$(GNULIB_POSIX_SPAWNATTR_SETSIGDEFAULT)/g' \ + -e 's/@''GNULIB_POSIX_SPAWNATTR_GETSIGMASK''@/$(GNULIB_POSIX_SPAWNATTR_GETSIGMASK)/g' \ + -e 's/@''GNULIB_POSIX_SPAWNATTR_SETSIGMASK''@/$(GNULIB_POSIX_SPAWNATTR_SETSIGMASK)/g' \ + -e 's/@''GNULIB_POSIX_SPAWNATTR_DESTROY''@/$(GNULIB_POSIX_SPAWNATTR_DESTROY)/g' \ + -e 's|@''HAVE_POSIX_SPAWN''@|$(HAVE_POSIX_SPAWN)|g' \ + -e 's|@''HAVE_POSIX_SPAWNATTR_T''@|$(HAVE_POSIX_SPAWNATTR_T)|g' \ + -e 's|@''HAVE_POSIX_SPAWN_FILE_ACTIONS_T''@|$(HAVE_POSIX_SPAWN_FILE_ACTIONS_T)|g' \ + -e 's|@''REPLACE_POSIX_SPAWN''@|$(REPLACE_POSIX_SPAWN)|g' \ + -e 's|@''REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSE''@|$(REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSE)|g' \ + -e 's|@''REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDDUP2''@|$(REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDDUP2)|g' \ + -e 's|@''REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDOPEN''@|$(REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDOPEN)|g' \ + -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ + < $(srcdir)/spawn.in.h; \ + } > $@-t && \ + mv $@-t $@ + +# We need the following in order to create when the system +# doesn't have one that works with the given compiler. +@GL_GENERATE_STDARG_H_TRUE@stdarg.h: stdarg.in.h $(top_builddir)/config.status +@GL_GENERATE_STDARG_H_TRUE@ $(AM_V_GEN)rm -f $@-t $@ && \ +@GL_GENERATE_STDARG_H_TRUE@ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ +@GL_GENERATE_STDARG_H_TRUE@ sed -e 's|@''GUARD_PREFIX''@|GL|g' \ +@GL_GENERATE_STDARG_H_TRUE@ -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ +@GL_GENERATE_STDARG_H_TRUE@ -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ +@GL_GENERATE_STDARG_H_TRUE@ -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ +@GL_GENERATE_STDARG_H_TRUE@ -e 's|@''NEXT_STDARG_H''@|$(NEXT_STDARG_H)|g' \ +@GL_GENERATE_STDARG_H_TRUE@ < $(srcdir)/stdarg.in.h; \ +@GL_GENERATE_STDARG_H_TRUE@ } > $@-t && \ +@GL_GENERATE_STDARG_H_TRUE@ mv $@-t $@ +@GL_GENERATE_STDARG_H_FALSE@stdarg.h: $(top_builddir)/config.status +@GL_GENERATE_STDARG_H_FALSE@ rm -f $@ + +# We need the following in order to create when the system +# doesn't have one that works. +@GL_GENERATE_STDBOOL_H_TRUE@stdbool.h: stdbool.in.h $(top_builddir)/config.status +@GL_GENERATE_STDBOOL_H_TRUE@ $(AM_V_GEN)rm -f $@-t $@ && \ +@GL_GENERATE_STDBOOL_H_TRUE@ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ +@GL_GENERATE_STDBOOL_H_TRUE@ sed -e 's/@''HAVE__BOOL''@/$(HAVE__BOOL)/g' < $(srcdir)/stdbool.in.h; \ +@GL_GENERATE_STDBOOL_H_TRUE@ } > $@-t && \ +@GL_GENERATE_STDBOOL_H_TRUE@ mv $@-t $@ +@GL_GENERATE_STDBOOL_H_FALSE@stdbool.h: $(top_builddir)/config.status +@GL_GENERATE_STDBOOL_H_FALSE@ rm -f $@ + +# We need the following in order to create when the system +# doesn't have one that works with the given compiler. +@GL_GENERATE_STDDEF_H_TRUE@stddef.h: stddef.in.h $(top_builddir)/config.status +@GL_GENERATE_STDDEF_H_TRUE@ $(AM_V_GEN)rm -f $@-t $@ && \ +@GL_GENERATE_STDDEF_H_TRUE@ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ +@GL_GENERATE_STDDEF_H_TRUE@ sed -e 's|@''GUARD_PREFIX''@|GL|g' \ +@GL_GENERATE_STDDEF_H_TRUE@ -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ +@GL_GENERATE_STDDEF_H_TRUE@ -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ +@GL_GENERATE_STDDEF_H_TRUE@ -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ +@GL_GENERATE_STDDEF_H_TRUE@ -e 's|@''NEXT_STDDEF_H''@|$(NEXT_STDDEF_H)|g' \ +@GL_GENERATE_STDDEF_H_TRUE@ -e 's|@''HAVE_WCHAR_T''@|$(HAVE_WCHAR_T)|g' \ +@GL_GENERATE_STDDEF_H_TRUE@ -e 's|@''REPLACE_NULL''@|$(REPLACE_NULL)|g' \ +@GL_GENERATE_STDDEF_H_TRUE@ < $(srcdir)/stddef.in.h; \ +@GL_GENERATE_STDDEF_H_TRUE@ } > $@-t && \ +@GL_GENERATE_STDDEF_H_TRUE@ mv $@-t $@ +@GL_GENERATE_STDDEF_H_FALSE@stddef.h: $(top_builddir)/config.status +@GL_GENERATE_STDDEF_H_FALSE@ rm -f $@ + +# We need the following in order to create when the system +# doesn't have one that works with the given compiler. +@GL_GENERATE_STDINT_H_TRUE@stdint.h: stdint.in.h $(top_builddir)/config.status +@GL_GENERATE_STDINT_H_TRUE@ $(AM_V_GEN)rm -f $@-t $@ && \ +@GL_GENERATE_STDINT_H_TRUE@ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ +@GL_GENERATE_STDINT_H_TRUE@ sed -e 's|@''GUARD_PREFIX''@|GL|g' \ +@GL_GENERATE_STDINT_H_TRUE@ -e 's/@''HAVE_STDINT_H''@/$(HAVE_STDINT_H)/g' \ +@GL_GENERATE_STDINT_H_TRUE@ -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ +@GL_GENERATE_STDINT_H_TRUE@ -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ +@GL_GENERATE_STDINT_H_TRUE@ -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ +@GL_GENERATE_STDINT_H_TRUE@ -e 's|@''NEXT_STDINT_H''@|$(NEXT_STDINT_H)|g' \ +@GL_GENERATE_STDINT_H_TRUE@ -e 's/@''HAVE_SYS_TYPES_H''@/$(HAVE_SYS_TYPES_H)/g' \ +@GL_GENERATE_STDINT_H_TRUE@ -e 's/@''HAVE_INTTYPES_H''@/$(HAVE_INTTYPES_H)/g' \ +@GL_GENERATE_STDINT_H_TRUE@ -e 's/@''HAVE_SYS_INTTYPES_H''@/$(HAVE_SYS_INTTYPES_H)/g' \ +@GL_GENERATE_STDINT_H_TRUE@ -e 's/@''HAVE_SYS_BITYPES_H''@/$(HAVE_SYS_BITYPES_H)/g' \ +@GL_GENERATE_STDINT_H_TRUE@ -e 's/@''HAVE_WCHAR_H''@/$(HAVE_WCHAR_H)/g' \ +@GL_GENERATE_STDINT_H_TRUE@ -e 's/@''HAVE_LONG_LONG_INT''@/$(HAVE_LONG_LONG_INT)/g' \ +@GL_GENERATE_STDINT_H_TRUE@ -e 's/@''HAVE_UNSIGNED_LONG_LONG_INT''@/$(HAVE_UNSIGNED_LONG_LONG_INT)/g' \ +@GL_GENERATE_STDINT_H_TRUE@ -e 's/@''APPLE_UNIVERSAL_BUILD''@/$(APPLE_UNIVERSAL_BUILD)/g' \ +@GL_GENERATE_STDINT_H_TRUE@ -e 's/@''BITSIZEOF_PTRDIFF_T''@/$(BITSIZEOF_PTRDIFF_T)/g' \ +@GL_GENERATE_STDINT_H_TRUE@ -e 's/@''PTRDIFF_T_SUFFIX''@/$(PTRDIFF_T_SUFFIX)/g' \ +@GL_GENERATE_STDINT_H_TRUE@ -e 's/@''BITSIZEOF_SIG_ATOMIC_T''@/$(BITSIZEOF_SIG_ATOMIC_T)/g' \ +@GL_GENERATE_STDINT_H_TRUE@ -e 's/@''HAVE_SIGNED_SIG_ATOMIC_T''@/$(HAVE_SIGNED_SIG_ATOMIC_T)/g' \ +@GL_GENERATE_STDINT_H_TRUE@ -e 's/@''SIG_ATOMIC_T_SUFFIX''@/$(SIG_ATOMIC_T_SUFFIX)/g' \ +@GL_GENERATE_STDINT_H_TRUE@ -e 's/@''BITSIZEOF_SIZE_T''@/$(BITSIZEOF_SIZE_T)/g' \ +@GL_GENERATE_STDINT_H_TRUE@ -e 's/@''SIZE_T_SUFFIX''@/$(SIZE_T_SUFFIX)/g' \ +@GL_GENERATE_STDINT_H_TRUE@ -e 's/@''BITSIZEOF_WCHAR_T''@/$(BITSIZEOF_WCHAR_T)/g' \ +@GL_GENERATE_STDINT_H_TRUE@ -e 's/@''HAVE_SIGNED_WCHAR_T''@/$(HAVE_SIGNED_WCHAR_T)/g' \ +@GL_GENERATE_STDINT_H_TRUE@ -e 's/@''WCHAR_T_SUFFIX''@/$(WCHAR_T_SUFFIX)/g' \ +@GL_GENERATE_STDINT_H_TRUE@ -e 's/@''BITSIZEOF_WINT_T''@/$(BITSIZEOF_WINT_T)/g' \ +@GL_GENERATE_STDINT_H_TRUE@ -e 's/@''HAVE_SIGNED_WINT_T''@/$(HAVE_SIGNED_WINT_T)/g' \ +@GL_GENERATE_STDINT_H_TRUE@ -e 's/@''WINT_T_SUFFIX''@/$(WINT_T_SUFFIX)/g' \ +@GL_GENERATE_STDINT_H_TRUE@ < $(srcdir)/stdint.in.h; \ +@GL_GENERATE_STDINT_H_TRUE@ } > $@-t && \ +@GL_GENERATE_STDINT_H_TRUE@ mv $@-t $@ +@GL_GENERATE_STDINT_H_FALSE@stdint.h: $(top_builddir)/config.status +@GL_GENERATE_STDINT_H_FALSE@ rm -f $@ + +# We need the following in order to create when the system +# doesn't have one that works with the given compiler. +stdio.h: stdio.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_STDIO_H''@|$(NEXT_STDIO_H)|g' \ + -e 's/@''GNULIB_DPRINTF''@/$(GNULIB_DPRINTF)/g' \ + -e 's/@''GNULIB_FCLOSE''@/$(GNULIB_FCLOSE)/g' \ + -e 's/@''GNULIB_FDOPEN''@/$(GNULIB_FDOPEN)/g' \ + -e 's/@''GNULIB_FFLUSH''@/$(GNULIB_FFLUSH)/g' \ + -e 's/@''GNULIB_FGETC''@/$(GNULIB_FGETC)/g' \ + -e 's/@''GNULIB_FGETS''@/$(GNULIB_FGETS)/g' \ + -e 's/@''GNULIB_FOPEN''@/$(GNULIB_FOPEN)/g' \ + -e 's/@''GNULIB_FPRINTF''@/$(GNULIB_FPRINTF)/g' \ + -e 's/@''GNULIB_FPRINTF_POSIX''@/$(GNULIB_FPRINTF_POSIX)/g' \ + -e 's/@''GNULIB_FPURGE''@/$(GNULIB_FPURGE)/g' \ + -e 's/@''GNULIB_FPUTC''@/$(GNULIB_FPUTC)/g' \ + -e 's/@''GNULIB_FPUTS''@/$(GNULIB_FPUTS)/g' \ + -e 's/@''GNULIB_FREAD''@/$(GNULIB_FREAD)/g' \ + -e 's/@''GNULIB_FREOPEN''@/$(GNULIB_FREOPEN)/g' \ + -e 's/@''GNULIB_FSCANF''@/$(GNULIB_FSCANF)/g' \ + -e 's/@''GNULIB_FSEEK''@/$(GNULIB_FSEEK)/g' \ + -e 's/@''GNULIB_FSEEKO''@/$(GNULIB_FSEEKO)/g' \ + -e 's/@''GNULIB_FTELL''@/$(GNULIB_FTELL)/g' \ + -e 's/@''GNULIB_FTELLO''@/$(GNULIB_FTELLO)/g' \ + -e 's/@''GNULIB_FWRITE''@/$(GNULIB_FWRITE)/g' \ + -e 's/@''GNULIB_GETC''@/$(GNULIB_GETC)/g' \ + -e 's/@''GNULIB_GETCHAR''@/$(GNULIB_GETCHAR)/g' \ + -e 's/@''GNULIB_GETDELIM''@/$(GNULIB_GETDELIM)/g' \ + -e 's/@''GNULIB_GETLINE''@/$(GNULIB_GETLINE)/g' \ + -e 's/@''GNULIB_OBSTACK_PRINTF''@/$(GNULIB_OBSTACK_PRINTF)/g' \ + -e 's/@''GNULIB_OBSTACK_PRINTF_POSIX''@/$(GNULIB_OBSTACK_PRINTF_POSIX)/g' \ + -e 's/@''GNULIB_PCLOSE''@/$(GNULIB_PCLOSE)/g' \ + -e 's/@''GNULIB_PERROR''@/$(GNULIB_PERROR)/g' \ + -e 's/@''GNULIB_POPEN''@/$(GNULIB_POPEN)/g' \ + -e 's/@''GNULIB_PRINTF''@/$(GNULIB_PRINTF)/g' \ + -e 's/@''GNULIB_PRINTF_POSIX''@/$(GNULIB_PRINTF_POSIX)/g' \ + -e 's/@''GNULIB_PUTC''@/$(GNULIB_PUTC)/g' \ + -e 's/@''GNULIB_PUTCHAR''@/$(GNULIB_PUTCHAR)/g' \ + -e 's/@''GNULIB_PUTS''@/$(GNULIB_PUTS)/g' \ + -e 's/@''GNULIB_REMOVE''@/$(GNULIB_REMOVE)/g' \ + -e 's/@''GNULIB_RENAME''@/$(GNULIB_RENAME)/g' \ + -e 's/@''GNULIB_RENAMEAT''@/$(GNULIB_RENAMEAT)/g' \ + -e 's/@''GNULIB_SCANF''@/$(GNULIB_SCANF)/g' \ + -e 's/@''GNULIB_SNPRINTF''@/$(GNULIB_SNPRINTF)/g' \ + -e 's/@''GNULIB_SPRINTF_POSIX''@/$(GNULIB_SPRINTF_POSIX)/g' \ + -e 's/@''GNULIB_STDIO_H_NONBLOCKING''@/$(GNULIB_STDIO_H_NONBLOCKING)/g' \ + -e 's/@''GNULIB_STDIO_H_SIGPIPE''@/$(GNULIB_STDIO_H_SIGPIPE)/g' \ + -e 's/@''GNULIB_TMPFILE''@/$(GNULIB_TMPFILE)/g' \ + -e 's/@''GNULIB_VASPRINTF''@/$(GNULIB_VASPRINTF)/g' \ + -e 's/@''GNULIB_VDPRINTF''@/$(GNULIB_VDPRINTF)/g' \ + -e 's/@''GNULIB_VFPRINTF''@/$(GNULIB_VFPRINTF)/g' \ + -e 's/@''GNULIB_VFPRINTF_POSIX''@/$(GNULIB_VFPRINTF_POSIX)/g' \ + -e 's/@''GNULIB_VFSCANF''@/$(GNULIB_VFSCANF)/g' \ + -e 's/@''GNULIB_VSCANF''@/$(GNULIB_VSCANF)/g' \ + -e 's/@''GNULIB_VPRINTF''@/$(GNULIB_VPRINTF)/g' \ + -e 's/@''GNULIB_VPRINTF_POSIX''@/$(GNULIB_VPRINTF_POSIX)/g' \ + -e 's/@''GNULIB_VSNPRINTF''@/$(GNULIB_VSNPRINTF)/g' \ + -e 's/@''GNULIB_VSPRINTF_POSIX''@/$(GNULIB_VSPRINTF_POSIX)/g' \ + < $(srcdir)/stdio.in.h | \ + sed -e 's|@''HAVE_DECL_FPURGE''@|$(HAVE_DECL_FPURGE)|g' \ + -e 's|@''HAVE_DECL_FSEEKO''@|$(HAVE_DECL_FSEEKO)|g' \ + -e 's|@''HAVE_DECL_FTELLO''@|$(HAVE_DECL_FTELLO)|g' \ + -e 's|@''HAVE_DECL_GETDELIM''@|$(HAVE_DECL_GETDELIM)|g' \ + -e 's|@''HAVE_DECL_GETLINE''@|$(HAVE_DECL_GETLINE)|g' \ + -e 's|@''HAVE_DECL_OBSTACK_PRINTF''@|$(HAVE_DECL_OBSTACK_PRINTF)|g' \ + -e 's|@''HAVE_DECL_SNPRINTF''@|$(HAVE_DECL_SNPRINTF)|g' \ + -e 's|@''HAVE_DECL_VSNPRINTF''@|$(HAVE_DECL_VSNPRINTF)|g' \ + -e 's|@''HAVE_DPRINTF''@|$(HAVE_DPRINTF)|g' \ + -e 's|@''HAVE_FSEEKO''@|$(HAVE_FSEEKO)|g' \ + -e 's|@''HAVE_FTELLO''@|$(HAVE_FTELLO)|g' \ + -e 's|@''HAVE_PCLOSE''@|$(HAVE_PCLOSE)|g' \ + -e 's|@''HAVE_POPEN''@|$(HAVE_POPEN)|g' \ + -e 's|@''HAVE_RENAMEAT''@|$(HAVE_RENAMEAT)|g' \ + -e 's|@''HAVE_VASPRINTF''@|$(HAVE_VASPRINTF)|g' \ + -e 's|@''HAVE_VDPRINTF''@|$(HAVE_VDPRINTF)|g' \ + -e 's|@''REPLACE_DPRINTF''@|$(REPLACE_DPRINTF)|g' \ + -e 's|@''REPLACE_FCLOSE''@|$(REPLACE_FCLOSE)|g' \ + -e 's|@''REPLACE_FDOPEN''@|$(REPLACE_FDOPEN)|g' \ + -e 's|@''REPLACE_FFLUSH''@|$(REPLACE_FFLUSH)|g' \ + -e 's|@''REPLACE_FOPEN''@|$(REPLACE_FOPEN)|g' \ + -e 's|@''REPLACE_FPRINTF''@|$(REPLACE_FPRINTF)|g' \ + -e 's|@''REPLACE_FPURGE''@|$(REPLACE_FPURGE)|g' \ + -e 's|@''REPLACE_FREOPEN''@|$(REPLACE_FREOPEN)|g' \ + -e 's|@''REPLACE_FSEEK''@|$(REPLACE_FSEEK)|g' \ + -e 's|@''REPLACE_FSEEKO''@|$(REPLACE_FSEEKO)|g' \ + -e 's|@''REPLACE_FTELL''@|$(REPLACE_FTELL)|g' \ + -e 's|@''REPLACE_FTELLO''@|$(REPLACE_FTELLO)|g' \ + -e 's|@''REPLACE_GETDELIM''@|$(REPLACE_GETDELIM)|g' \ + -e 's|@''REPLACE_GETLINE''@|$(REPLACE_GETLINE)|g' \ + -e 's|@''REPLACE_OBSTACK_PRINTF''@|$(REPLACE_OBSTACK_PRINTF)|g' \ + -e 's|@''REPLACE_PERROR''@|$(REPLACE_PERROR)|g' \ + -e 's|@''REPLACE_POPEN''@|$(REPLACE_POPEN)|g' \ + -e 's|@''REPLACE_PRINTF''@|$(REPLACE_PRINTF)|g' \ + -e 's|@''REPLACE_REMOVE''@|$(REPLACE_REMOVE)|g' \ + -e 's|@''REPLACE_RENAME''@|$(REPLACE_RENAME)|g' \ + -e 's|@''REPLACE_RENAMEAT''@|$(REPLACE_RENAMEAT)|g' \ + -e 's|@''REPLACE_SNPRINTF''@|$(REPLACE_SNPRINTF)|g' \ + -e 's|@''REPLACE_SPRINTF''@|$(REPLACE_SPRINTF)|g' \ + -e 's|@''REPLACE_STDIO_READ_FUNCS''@|$(REPLACE_STDIO_READ_FUNCS)|g' \ + -e 's|@''REPLACE_STDIO_WRITE_FUNCS''@|$(REPLACE_STDIO_WRITE_FUNCS)|g' \ + -e 's|@''REPLACE_TMPFILE''@|$(REPLACE_TMPFILE)|g' \ + -e 's|@''REPLACE_VASPRINTF''@|$(REPLACE_VASPRINTF)|g' \ + -e 's|@''REPLACE_VDPRINTF''@|$(REPLACE_VDPRINTF)|g' \ + -e 's|@''REPLACE_VFPRINTF''@|$(REPLACE_VFPRINTF)|g' \ + -e 's|@''REPLACE_VPRINTF''@|$(REPLACE_VPRINTF)|g' \ + -e 's|@''REPLACE_VSNPRINTF''@|$(REPLACE_VSNPRINTF)|g' \ + -e 's|@''REPLACE_VSPRINTF''@|$(REPLACE_VSPRINTF)|g' \ + -e 's|@''ASM_SYMBOL_PREFIX''@|$(ASM_SYMBOL_PREFIX)|g' \ + -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)'; \ + } > $@-t && \ + mv $@-t $@ + +# We need the following in order to create when the system +# doesn't have one that works with the given compiler. +stdlib.h: stdlib.in.h $(top_builddir)/config.status $(CXXDEFS_H) \ + $(_NORETURN_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_STDLIB_H''@|$(NEXT_STDLIB_H)|g' \ + -e 's/@''GNULIB__EXIT''@/$(GNULIB__EXIT)/g' \ + -e 's/@''GNULIB_ATOLL''@/$(GNULIB_ATOLL)/g' \ + -e 's/@''GNULIB_CALLOC_POSIX''@/$(GNULIB_CALLOC_POSIX)/g' \ + -e 's/@''GNULIB_CANONICALIZE_FILE_NAME''@/$(GNULIB_CANONICALIZE_FILE_NAME)/g' \ + -e 's/@''GNULIB_GETLOADAVG''@/$(GNULIB_GETLOADAVG)/g' \ + -e 's/@''GNULIB_GETSUBOPT''@/$(GNULIB_GETSUBOPT)/g' \ + -e 's/@''GNULIB_GRANTPT''@/$(GNULIB_GRANTPT)/g' \ + -e 's/@''GNULIB_MALLOC_POSIX''@/$(GNULIB_MALLOC_POSIX)/g' \ + -e 's/@''GNULIB_MBTOWC''@/$(GNULIB_MBTOWC)/g' \ + -e 's/@''GNULIB_MKDTEMP''@/$(GNULIB_MKDTEMP)/g' \ + -e 's/@''GNULIB_MKOSTEMP''@/$(GNULIB_MKOSTEMP)/g' \ + -e 's/@''GNULIB_MKOSTEMPS''@/$(GNULIB_MKOSTEMPS)/g' \ + -e 's/@''GNULIB_MKSTEMP''@/$(GNULIB_MKSTEMP)/g' \ + -e 's/@''GNULIB_MKSTEMPS''@/$(GNULIB_MKSTEMPS)/g' \ + -e 's/@''GNULIB_POSIX_OPENPT''@/$(GNULIB_POSIX_OPENPT)/g' \ + -e 's/@''GNULIB_PTSNAME''@/$(GNULIB_PTSNAME)/g' \ + -e 's/@''GNULIB_PTSNAME_R''@/$(GNULIB_PTSNAME_R)/g' \ + -e 's/@''GNULIB_PUTENV''@/$(GNULIB_PUTENV)/g' \ + -e 's/@''GNULIB_QSORT_R''@/$(GNULIB_QSORT_R)/g' \ + -e 's/@''GNULIB_RANDOM''@/$(GNULIB_RANDOM)/g' \ + -e 's/@''GNULIB_RANDOM_R''@/$(GNULIB_RANDOM_R)/g' \ + -e 's/@''GNULIB_REALLOC_POSIX''@/$(GNULIB_REALLOC_POSIX)/g' \ + -e 's/@''GNULIB_REALPATH''@/$(GNULIB_REALPATH)/g' \ + -e 's/@''GNULIB_RPMATCH''@/$(GNULIB_RPMATCH)/g' \ + -e 's/@''GNULIB_SECURE_GETENV''@/$(GNULIB_SECURE_GETENV)/g' \ + -e 's/@''GNULIB_SETENV''@/$(GNULIB_SETENV)/g' \ + -e 's/@''GNULIB_STRTOD''@/$(GNULIB_STRTOD)/g' \ + -e 's/@''GNULIB_STRTOLL''@/$(GNULIB_STRTOLL)/g' \ + -e 's/@''GNULIB_STRTOULL''@/$(GNULIB_STRTOULL)/g' \ + -e 's/@''GNULIB_SYSTEM_POSIX''@/$(GNULIB_SYSTEM_POSIX)/g' \ + -e 's/@''GNULIB_UNLOCKPT''@/$(GNULIB_UNLOCKPT)/g' \ + -e 's/@''GNULIB_UNSETENV''@/$(GNULIB_UNSETENV)/g' \ + -e 's/@''GNULIB_WCTOMB''@/$(GNULIB_WCTOMB)/g' \ + < $(srcdir)/stdlib.in.h | \ + sed -e 's|@''HAVE__EXIT''@|$(HAVE__EXIT)|g' \ + -e 's|@''HAVE_ATOLL''@|$(HAVE_ATOLL)|g' \ + -e 's|@''HAVE_CANONICALIZE_FILE_NAME''@|$(HAVE_CANONICALIZE_FILE_NAME)|g' \ + -e 's|@''HAVE_DECL_GETLOADAVG''@|$(HAVE_DECL_GETLOADAVG)|g' \ + -e 's|@''HAVE_GETSUBOPT''@|$(HAVE_GETSUBOPT)|g' \ + -e 's|@''HAVE_GRANTPT''@|$(HAVE_GRANTPT)|g' \ + -e 's|@''HAVE_MKDTEMP''@|$(HAVE_MKDTEMP)|g' \ + -e 's|@''HAVE_MKOSTEMP''@|$(HAVE_MKOSTEMP)|g' \ + -e 's|@''HAVE_MKOSTEMPS''@|$(HAVE_MKOSTEMPS)|g' \ + -e 's|@''HAVE_MKSTEMP''@|$(HAVE_MKSTEMP)|g' \ + -e 's|@''HAVE_MKSTEMPS''@|$(HAVE_MKSTEMPS)|g' \ + -e 's|@''HAVE_POSIX_OPENPT''@|$(HAVE_POSIX_OPENPT)|g' \ + -e 's|@''HAVE_PTSNAME''@|$(HAVE_PTSNAME)|g' \ + -e 's|@''HAVE_PTSNAME_R''@|$(HAVE_PTSNAME_R)|g' \ + -e 's|@''HAVE_RANDOM''@|$(HAVE_RANDOM)|g' \ + -e 's|@''HAVE_RANDOM_H''@|$(HAVE_RANDOM_H)|g' \ + -e 's|@''HAVE_RANDOM_R''@|$(HAVE_RANDOM_R)|g' \ + -e 's|@''HAVE_REALPATH''@|$(HAVE_REALPATH)|g' \ + -e 's|@''HAVE_RPMATCH''@|$(HAVE_RPMATCH)|g' \ + -e 's|@''HAVE_SECURE_GETENV''@|$(HAVE_SECURE_GETENV)|g' \ + -e 's|@''HAVE_DECL_SETENV''@|$(HAVE_DECL_SETENV)|g' \ + -e 's|@''HAVE_STRTOD''@|$(HAVE_STRTOD)|g' \ + -e 's|@''HAVE_STRTOLL''@|$(HAVE_STRTOLL)|g' \ + -e 's|@''HAVE_STRTOULL''@|$(HAVE_STRTOULL)|g' \ + -e 's|@''HAVE_STRUCT_RANDOM_DATA''@|$(HAVE_STRUCT_RANDOM_DATA)|g' \ + -e 's|@''HAVE_SYS_LOADAVG_H''@|$(HAVE_SYS_LOADAVG_H)|g' \ + -e 's|@''HAVE_UNLOCKPT''@|$(HAVE_UNLOCKPT)|g' \ + -e 's|@''HAVE_DECL_UNSETENV''@|$(HAVE_DECL_UNSETENV)|g' \ + -e 's|@''REPLACE_CALLOC''@|$(REPLACE_CALLOC)|g' \ + -e 's|@''REPLACE_CANONICALIZE_FILE_NAME''@|$(REPLACE_CANONICALIZE_FILE_NAME)|g' \ + -e 's|@''REPLACE_MALLOC''@|$(REPLACE_MALLOC)|g' \ + -e 's|@''REPLACE_MBTOWC''@|$(REPLACE_MBTOWC)|g' \ + -e 's|@''REPLACE_MKSTEMP''@|$(REPLACE_MKSTEMP)|g' \ + -e 's|@''REPLACE_PTSNAME''@|$(REPLACE_PTSNAME)|g' \ + -e 's|@''REPLACE_PTSNAME_R''@|$(REPLACE_PTSNAME_R)|g' \ + -e 's|@''REPLACE_PUTENV''@|$(REPLACE_PUTENV)|g' \ + -e 's|@''REPLACE_QSORT_R''@|$(REPLACE_QSORT_R)|g' \ + -e 's|@''REPLACE_RANDOM_R''@|$(REPLACE_RANDOM_R)|g' \ + -e 's|@''REPLACE_REALLOC''@|$(REPLACE_REALLOC)|g' \ + -e 's|@''REPLACE_REALPATH''@|$(REPLACE_REALPATH)|g' \ + -e 's|@''REPLACE_SETENV''@|$(REPLACE_SETENV)|g' \ + -e 's|@''REPLACE_STRTOD''@|$(REPLACE_STRTOD)|g' \ + -e 's|@''REPLACE_UNSETENV''@|$(REPLACE_UNSETENV)|g' \ + -e 's|@''REPLACE_WCTOMB''@|$(REPLACE_WCTOMB)|g' \ + -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _Noreturn/r $(_NORETURN_H)' \ + -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)'; \ + } > $@-t && \ + mv $@-t $@ + +# We need the following in order to create when the system +# doesn't have one that works with the given compiler. +string.h: string.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_STRING_H''@|$(NEXT_STRING_H)|g' \ + -e 's/@''GNULIB_FFSL''@/$(GNULIB_FFSL)/g' \ + -e 's/@''GNULIB_FFSLL''@/$(GNULIB_FFSLL)/g' \ + -e 's/@''GNULIB_MBSLEN''@/$(GNULIB_MBSLEN)/g' \ + -e 's/@''GNULIB_MBSNLEN''@/$(GNULIB_MBSNLEN)/g' \ + -e 's/@''GNULIB_MBSCHR''@/$(GNULIB_MBSCHR)/g' \ + -e 's/@''GNULIB_MBSRCHR''@/$(GNULIB_MBSRCHR)/g' \ + -e 's/@''GNULIB_MBSSTR''@/$(GNULIB_MBSSTR)/g' \ + -e 's/@''GNULIB_MBSCASECMP''@/$(GNULIB_MBSCASECMP)/g' \ + -e 's/@''GNULIB_MBSNCASECMP''@/$(GNULIB_MBSNCASECMP)/g' \ + -e 's/@''GNULIB_MBSPCASECMP''@/$(GNULIB_MBSPCASECMP)/g' \ + -e 's/@''GNULIB_MBSCASESTR''@/$(GNULIB_MBSCASESTR)/g' \ + -e 's/@''GNULIB_MBSCSPN''@/$(GNULIB_MBSCSPN)/g' \ + -e 's/@''GNULIB_MBSPBRK''@/$(GNULIB_MBSPBRK)/g' \ + -e 's/@''GNULIB_MBSSPN''@/$(GNULIB_MBSSPN)/g' \ + -e 's/@''GNULIB_MBSSEP''@/$(GNULIB_MBSSEP)/g' \ + -e 's/@''GNULIB_MBSTOK_R''@/$(GNULIB_MBSTOK_R)/g' \ + -e 's/@''GNULIB_MEMCHR''@/$(GNULIB_MEMCHR)/g' \ + -e 's/@''GNULIB_MEMMEM''@/$(GNULIB_MEMMEM)/g' \ + -e 's/@''GNULIB_MEMPCPY''@/$(GNULIB_MEMPCPY)/g' \ + -e 's/@''GNULIB_MEMRCHR''@/$(GNULIB_MEMRCHR)/g' \ + -e 's/@''GNULIB_RAWMEMCHR''@/$(GNULIB_RAWMEMCHR)/g' \ + -e 's/@''GNULIB_STPCPY''@/$(GNULIB_STPCPY)/g' \ + -e 's/@''GNULIB_STPNCPY''@/$(GNULIB_STPNCPY)/g' \ + -e 's/@''GNULIB_STRCHRNUL''@/$(GNULIB_STRCHRNUL)/g' \ + -e 's/@''GNULIB_STRDUP''@/$(GNULIB_STRDUP)/g' \ + -e 's/@''GNULIB_STRNCAT''@/$(GNULIB_STRNCAT)/g' \ + -e 's/@''GNULIB_STRNDUP''@/$(GNULIB_STRNDUP)/g' \ + -e 's/@''GNULIB_STRNLEN''@/$(GNULIB_STRNLEN)/g' \ + -e 's/@''GNULIB_STRPBRK''@/$(GNULIB_STRPBRK)/g' \ + -e 's/@''GNULIB_STRSEP''@/$(GNULIB_STRSEP)/g' \ + -e 's/@''GNULIB_STRSTR''@/$(GNULIB_STRSTR)/g' \ + -e 's/@''GNULIB_STRCASESTR''@/$(GNULIB_STRCASESTR)/g' \ + -e 's/@''GNULIB_STRTOK_R''@/$(GNULIB_STRTOK_R)/g' \ + -e 's/@''GNULIB_STRERROR''@/$(GNULIB_STRERROR)/g' \ + -e 's/@''GNULIB_STRERROR_R''@/$(GNULIB_STRERROR_R)/g' \ + -e 's/@''GNULIB_STRSIGNAL''@/$(GNULIB_STRSIGNAL)/g' \ + -e 's/@''GNULIB_STRVERSCMP''@/$(GNULIB_STRVERSCMP)/g' \ + < $(srcdir)/string.in.h | \ + sed -e 's|@''HAVE_FFSL''@|$(HAVE_FFSL)|g' \ + -e 's|@''HAVE_FFSLL''@|$(HAVE_FFSLL)|g' \ + -e 's|@''HAVE_MBSLEN''@|$(HAVE_MBSLEN)|g' \ + -e 's|@''HAVE_MEMCHR''@|$(HAVE_MEMCHR)|g' \ + -e 's|@''HAVE_DECL_MEMMEM''@|$(HAVE_DECL_MEMMEM)|g' \ + -e 's|@''HAVE_MEMPCPY''@|$(HAVE_MEMPCPY)|g' \ + -e 's|@''HAVE_DECL_MEMRCHR''@|$(HAVE_DECL_MEMRCHR)|g' \ + -e 's|@''HAVE_RAWMEMCHR''@|$(HAVE_RAWMEMCHR)|g' \ + -e 's|@''HAVE_STPCPY''@|$(HAVE_STPCPY)|g' \ + -e 's|@''HAVE_STPNCPY''@|$(HAVE_STPNCPY)|g' \ + -e 's|@''HAVE_STRCHRNUL''@|$(HAVE_STRCHRNUL)|g' \ + -e 's|@''HAVE_DECL_STRDUP''@|$(HAVE_DECL_STRDUP)|g' \ + -e 's|@''HAVE_DECL_STRNDUP''@|$(HAVE_DECL_STRNDUP)|g' \ + -e 's|@''HAVE_DECL_STRNLEN''@|$(HAVE_DECL_STRNLEN)|g' \ + -e 's|@''HAVE_STRPBRK''@|$(HAVE_STRPBRK)|g' \ + -e 's|@''HAVE_STRSEP''@|$(HAVE_STRSEP)|g' \ + -e 's|@''HAVE_STRCASESTR''@|$(HAVE_STRCASESTR)|g' \ + -e 's|@''HAVE_DECL_STRTOK_R''@|$(HAVE_DECL_STRTOK_R)|g' \ + -e 's|@''HAVE_DECL_STRERROR_R''@|$(HAVE_DECL_STRERROR_R)|g' \ + -e 's|@''HAVE_DECL_STRSIGNAL''@|$(HAVE_DECL_STRSIGNAL)|g' \ + -e 's|@''HAVE_STRVERSCMP''@|$(HAVE_STRVERSCMP)|g' \ + -e 's|@''REPLACE_STPNCPY''@|$(REPLACE_STPNCPY)|g' \ + -e 's|@''REPLACE_MEMCHR''@|$(REPLACE_MEMCHR)|g' \ + -e 's|@''REPLACE_MEMMEM''@|$(REPLACE_MEMMEM)|g' \ + -e 's|@''REPLACE_STRCASESTR''@|$(REPLACE_STRCASESTR)|g' \ + -e 's|@''REPLACE_STRCHRNUL''@|$(REPLACE_STRCHRNUL)|g' \ + -e 's|@''REPLACE_STRDUP''@|$(REPLACE_STRDUP)|g' \ + -e 's|@''REPLACE_STRSTR''@|$(REPLACE_STRSTR)|g' \ + -e 's|@''REPLACE_STRERROR''@|$(REPLACE_STRERROR)|g' \ + -e 's|@''REPLACE_STRERROR_R''@|$(REPLACE_STRERROR_R)|g' \ + -e 's|@''REPLACE_STRNCAT''@|$(REPLACE_STRNCAT)|g' \ + -e 's|@''REPLACE_STRNDUP''@|$(REPLACE_STRNDUP)|g' \ + -e 's|@''REPLACE_STRNLEN''@|$(REPLACE_STRNLEN)|g' \ + -e 's|@''REPLACE_STRSIGNAL''@|$(REPLACE_STRSIGNAL)|g' \ + -e 's|@''REPLACE_STRTOK_R''@|$(REPLACE_STRTOK_R)|g' \ + -e 's|@''UNDEFINE_STRTOK_R''@|$(UNDEFINE_STRTOK_R)|g' \ + -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)'; \ + < $(srcdir)/string.in.h; \ + } > $@-t && \ + mv $@-t $@ +# This is a Makefile rule that generates multiple files at once; see the +# automake documentation, node "Multiple Outputs", for details. +styled-ostream.h : $(top_srcdir)/../build-aux/moopp styled-ostream.oo.h styled-ostream.oo.c ostream.oo.h + $(top_srcdir)/../build-aux/moopp $(MOOPPFLAGS) $(srcdir)/styled-ostream.oo.c $(srcdir)/styled-ostream.oo.h $(srcdir)/ostream.oo.h +styled-ostream.c styled_ostream.priv.h styled_ostream.vt.h : styled-ostream.h + @test -f $@ || { \ + trap 'rm -rf styled-ostream.lock' 1 2 13 15; \ + if mkdir styled-ostream.lock 2>/dev/null; then \ + echo "$(top_srcdir)/../build-aux/moopp $(MOOPPFLAGS) $(srcdir)/styled-ostream.oo.c $(srcdir)/styled-ostream.oo.h $(srcdir)/ostream.oo.h"; \ + $(top_srcdir)/../build-aux/moopp $(MOOPPFLAGS) $(srcdir)/styled-ostream.oo.c $(srcdir)/styled-ostream.oo.h $(srcdir)/ostream.oo.h; \ + result=$$?; rm -rf styled-ostream.lock; exit $$result; \ + else \ + while test -d styled-ostream.lock; do sleep 1; done; \ + test -f $(srcdir)/styled-ostream.h; \ + fi; \ + } + +# We need the following in order to create when the system +# doesn't have one that works with the given compiler. +sys/select.h: sys_select.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(WARN_ON_USE_H) + $(AM_V_at)$(MKDIR_P) sys + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_SYS_SELECT_H''@|$(NEXT_SYS_SELECT_H)|g' \ + -e 's|@''HAVE_SYS_SELECT_H''@|$(HAVE_SYS_SELECT_H)|g' \ + -e 's/@''GNULIB_PSELECT''@/$(GNULIB_PSELECT)/g' \ + -e 's/@''GNULIB_SELECT''@/$(GNULIB_SELECT)/g' \ + -e 's|@''HAVE_WINSOCK2_H''@|$(HAVE_WINSOCK2_H)|g' \ + -e 's|@''HAVE_PSELECT''@|$(HAVE_PSELECT)|g' \ + -e 's|@''REPLACE_PSELECT''@|$(REPLACE_PSELECT)|g' \ + -e 's|@''REPLACE_SELECT''@|$(REPLACE_SELECT)|g' \ + -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ + < $(srcdir)/sys_select.in.h; \ + } > $@-t && \ + mv $@-t $@ + +# We need the following in order to create when the system +# has one that is incomplete. +sys/stat.h: sys_stat.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) + $(AM_V_at)$(MKDIR_P) sys + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_SYS_STAT_H''@|$(NEXT_SYS_STAT_H)|g' \ + -e 's|@''WINDOWS_64_BIT_ST_SIZE''@|$(WINDOWS_64_BIT_ST_SIZE)|g' \ + -e 's/@''GNULIB_FCHMODAT''@/$(GNULIB_FCHMODAT)/g' \ + -e 's/@''GNULIB_FSTAT''@/$(GNULIB_FSTAT)/g' \ + -e 's/@''GNULIB_FSTATAT''@/$(GNULIB_FSTATAT)/g' \ + -e 's/@''GNULIB_FUTIMENS''@/$(GNULIB_FUTIMENS)/g' \ + -e 's/@''GNULIB_LCHMOD''@/$(GNULIB_LCHMOD)/g' \ + -e 's/@''GNULIB_LSTAT''@/$(GNULIB_LSTAT)/g' \ + -e 's/@''GNULIB_MKDIRAT''@/$(GNULIB_MKDIRAT)/g' \ + -e 's/@''GNULIB_MKFIFO''@/$(GNULIB_MKFIFO)/g' \ + -e 's/@''GNULIB_MKFIFOAT''@/$(GNULIB_MKFIFOAT)/g' \ + -e 's/@''GNULIB_MKNOD''@/$(GNULIB_MKNOD)/g' \ + -e 's/@''GNULIB_MKNODAT''@/$(GNULIB_MKNODAT)/g' \ + -e 's/@''GNULIB_STAT''@/$(GNULIB_STAT)/g' \ + -e 's/@''GNULIB_UTIMENSAT''@/$(GNULIB_UTIMENSAT)/g' \ + -e 's|@''HAVE_FCHMODAT''@|$(HAVE_FCHMODAT)|g' \ + -e 's|@''HAVE_FSTATAT''@|$(HAVE_FSTATAT)|g' \ + -e 's|@''HAVE_FUTIMENS''@|$(HAVE_FUTIMENS)|g' \ + -e 's|@''HAVE_LCHMOD''@|$(HAVE_LCHMOD)|g' \ + -e 's|@''HAVE_LSTAT''@|$(HAVE_LSTAT)|g' \ + -e 's|@''HAVE_MKDIRAT''@|$(HAVE_MKDIRAT)|g' \ + -e 's|@''HAVE_MKFIFO''@|$(HAVE_MKFIFO)|g' \ + -e 's|@''HAVE_MKFIFOAT''@|$(HAVE_MKFIFOAT)|g' \ + -e 's|@''HAVE_MKNOD''@|$(HAVE_MKNOD)|g' \ + -e 's|@''HAVE_MKNODAT''@|$(HAVE_MKNODAT)|g' \ + -e 's|@''HAVE_UTIMENSAT''@|$(HAVE_UTIMENSAT)|g' \ + -e 's|@''REPLACE_FSTAT''@|$(REPLACE_FSTAT)|g' \ + -e 's|@''REPLACE_FSTATAT''@|$(REPLACE_FSTATAT)|g' \ + -e 's|@''REPLACE_FUTIMENS''@|$(REPLACE_FUTIMENS)|g' \ + -e 's|@''REPLACE_LSTAT''@|$(REPLACE_LSTAT)|g' \ + -e 's|@''REPLACE_MKDIR''@|$(REPLACE_MKDIR)|g' \ + -e 's|@''REPLACE_MKFIFO''@|$(REPLACE_MKFIFO)|g' \ + -e 's|@''REPLACE_MKNOD''@|$(REPLACE_MKNOD)|g' \ + -e 's|@''REPLACE_STAT''@|$(REPLACE_STAT)|g' \ + -e 's|@''REPLACE_UTIMENSAT''@|$(REPLACE_UTIMENSAT)|g' \ + -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ + < $(srcdir)/sys_stat.in.h; \ + } > $@-t && \ + mv $@-t $@ + +# We need the following in order to create when the system +# doesn't have one that works with the given compiler. +sys/time.h: sys_time.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) + $(AM_V_at)$(MKDIR_P) sys + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's/@''HAVE_SYS_TIME_H''@/$(HAVE_SYS_TIME_H)/g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_SYS_TIME_H''@|$(NEXT_SYS_TIME_H)|g' \ + -e 's/@''GNULIB_GETTIMEOFDAY''@/$(GNULIB_GETTIMEOFDAY)/g' \ + -e 's|@''HAVE_WINSOCK2_H''@|$(HAVE_WINSOCK2_H)|g' \ + -e 's/@''HAVE_GETTIMEOFDAY''@/$(HAVE_GETTIMEOFDAY)/g' \ + -e 's/@''HAVE_STRUCT_TIMEVAL''@/$(HAVE_STRUCT_TIMEVAL)/g' \ + -e 's/@''REPLACE_GETTIMEOFDAY''@/$(REPLACE_GETTIMEOFDAY)/g' \ + -e 's/@''REPLACE_STRUCT_TIMEVAL''@/$(REPLACE_STRUCT_TIMEVAL)/g' \ + -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ + < $(srcdir)/sys_time.in.h; \ + } > $@-t && \ + mv $@-t $@ + +# We need the following in order to create when the system +# doesn't have one that works with the given compiler. +sys/types.h: sys_types.in.h $(top_builddir)/config.status + $(AM_V_at)$(MKDIR_P) sys + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_SYS_TYPES_H''@|$(NEXT_SYS_TYPES_H)|g' \ + -e 's|@''WINDOWS_64_BIT_OFF_T''@|$(WINDOWS_64_BIT_OFF_T)|g' \ + < $(srcdir)/sys_types.in.h; \ + } > $@-t && \ + mv $@-t $@ + +# We need the following in order to create when the system +# has one that is incomplete. +sys/wait.h: sys_wait.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(WARN_ON_USE_H) + $(AM_V_at)$(MKDIR_P) sys + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_SYS_WAIT_H''@|$(NEXT_SYS_WAIT_H)|g' \ + -e 's/@''GNULIB_WAITPID''@/$(GNULIB_WAITPID)/g' \ + -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ + < $(srcdir)/sys_wait.in.h; \ + } > $@-t && \ + mv $@-t $@ +# This is a Makefile rule that generates multiple files at once; see the +# automake documentation, node "Multiple Outputs", for details. +term-ostream.h : $(top_srcdir)/../build-aux/moopp term-ostream.oo.h term-ostream.oo.c ostream.oo.h + $(top_srcdir)/../build-aux/moopp $(MOOPPFLAGS) $(srcdir)/term-ostream.oo.c $(srcdir)/term-ostream.oo.h $(srcdir)/ostream.oo.h +term-ostream.c term_ostream.priv.h term_ostream.vt.h : term-ostream.h + @test -f $@ || { \ + trap 'rm -rf term-ostream.lock' 1 2 13 15; \ + if mkdir term-ostream.lock 2>/dev/null; then \ + echo "$(top_srcdir)/../build-aux/moopp $(MOOPPFLAGS) $(srcdir)/term-ostream.oo.c $(srcdir)/term-ostream.oo.h $(srcdir)/ostream.oo.h"; \ + $(top_srcdir)/../build-aux/moopp $(MOOPPFLAGS) $(srcdir)/term-ostream.oo.c $(srcdir)/term-ostream.oo.h $(srcdir)/ostream.oo.h; \ + result=$$?; rm -rf term-ostream.lock; exit $$result; \ + else \ + while test -d term-ostream.lock; do sleep 1; done; \ + test -f $(srcdir)/term-ostream.h; \ + fi; \ + } +# This is a Makefile rule that generates multiple files at once; see the +# automake documentation, node "Multiple Outputs", for details. +term-styled-ostream.h : $(top_srcdir)/../build-aux/moopp term-styled-ostream.oo.h term-styled-ostream.oo.c styled-ostream.oo.h ostream.oo.h + $(top_srcdir)/../build-aux/moopp $(MOOPPFLAGS) $(srcdir)/term-styled-ostream.oo.c $(srcdir)/term-styled-ostream.oo.h $(srcdir)/styled-ostream.oo.h $(srcdir)/ostream.oo.h +term-styled-ostream.c term_styled_ostream.priv.h term_styled_ostream.vt.h : term-styled-ostream.h + @test -f $@ || { \ + trap 'rm -rf term-styled-ostream.lock' 1 2 13 15; \ + if mkdir term-styled-ostream.lock 2>/dev/null; then \ + echo "$(top_srcdir)/../build-aux/moopp $(MOOPPFLAGS) $(srcdir)/term-styled-ostream.oo.c $(srcdir)/term-styled-ostream.oo.h $(srcdir)/styled-ostream.oo.h $(srcdir)/ostream.oo.h"; \ + $(top_srcdir)/../build-aux/moopp $(MOOPPFLAGS) $(srcdir)/term-styled-ostream.oo.c $(srcdir)/term-styled-ostream.oo.h $(srcdir)/styled-ostream.oo.h $(srcdir)/ostream.oo.h; \ + result=$$?; rm -rf term-styled-ostream.lock; exit $$result; \ + else \ + while test -d term-styled-ostream.lock; do sleep 1; done; \ + test -f $(srcdir)/term-styled-ostream.h; \ + fi; \ + } + +# We need the following in order to create when the system +# doesn't have one that works with the given compiler. +time.h: time.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_TIME_H''@|$(NEXT_TIME_H)|g' \ + -e 's/@''GNULIB_GETTIMEOFDAY''@/$(GNULIB_GETTIMEOFDAY)/g' \ + -e 's/@''GNULIB_MKTIME''@/$(GNULIB_MKTIME)/g' \ + -e 's/@''GNULIB_NANOSLEEP''@/$(GNULIB_NANOSLEEP)/g' \ + -e 's/@''GNULIB_STRPTIME''@/$(GNULIB_STRPTIME)/g' \ + -e 's/@''GNULIB_TIMEGM''@/$(GNULIB_TIMEGM)/g' \ + -e 's/@''GNULIB_TIME_R''@/$(GNULIB_TIME_R)/g' \ + -e 's|@''HAVE_DECL_LOCALTIME_R''@|$(HAVE_DECL_LOCALTIME_R)|g' \ + -e 's|@''HAVE_NANOSLEEP''@|$(HAVE_NANOSLEEP)|g' \ + -e 's|@''HAVE_STRPTIME''@|$(HAVE_STRPTIME)|g' \ + -e 's|@''HAVE_TIMEGM''@|$(HAVE_TIMEGM)|g' \ + -e 's|@''REPLACE_GMTIME''@|$(REPLACE_GMTIME)|g' \ + -e 's|@''REPLACE_LOCALTIME''@|$(REPLACE_LOCALTIME)|g' \ + -e 's|@''REPLACE_LOCALTIME_R''@|$(REPLACE_LOCALTIME_R)|g' \ + -e 's|@''REPLACE_MKTIME''@|$(REPLACE_MKTIME)|g' \ + -e 's|@''REPLACE_NANOSLEEP''@|$(REPLACE_NANOSLEEP)|g' \ + -e 's|@''REPLACE_TIMEGM''@|$(REPLACE_TIMEGM)|g' \ + -e 's|@''PTHREAD_H_DEFINES_STRUCT_TIMESPEC''@|$(PTHREAD_H_DEFINES_STRUCT_TIMESPEC)|g' \ + -e 's|@''SYS_TIME_H_DEFINES_STRUCT_TIMESPEC''@|$(SYS_TIME_H_DEFINES_STRUCT_TIMESPEC)|g' \ + -e 's|@''TIME_H_DEFINES_STRUCT_TIMESPEC''@|$(TIME_H_DEFINES_STRUCT_TIMESPEC)|g' \ + -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ + < $(srcdir)/time.in.h; \ + } > $@-t && \ + mv $@-t $@ + +uniconv.h: uniconv.in.h + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/uniconv.in.h; \ + } > $@-t && \ + mv -f $@-t $@ + +unilbrk.h: unilbrk.in.h + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/unilbrk.in.h; \ + } > $@-t && \ + mv -f $@-t $@ + +uniname.h: uniname.in.h + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/uniname.in.h; \ + } > $@-t && \ + mv -f $@-t $@ + +# We need the following in order to create an empty placeholder for +# when the system doesn't have one. +unistd.h: unistd.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''HAVE_UNISTD_H''@|$(HAVE_UNISTD_H)|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_UNISTD_H''@|$(NEXT_UNISTD_H)|g' \ + -e 's|@''WINDOWS_64_BIT_OFF_T''@|$(WINDOWS_64_BIT_OFF_T)|g' \ + -e 's/@''GNULIB_CHDIR''@/$(GNULIB_CHDIR)/g' \ + -e 's/@''GNULIB_CHOWN''@/$(GNULIB_CHOWN)/g' \ + -e 's/@''GNULIB_CLOSE''@/$(GNULIB_CLOSE)/g' \ + -e 's/@''GNULIB_DUP''@/$(GNULIB_DUP)/g' \ + -e 's/@''GNULIB_DUP2''@/$(GNULIB_DUP2)/g' \ + -e 's/@''GNULIB_DUP3''@/$(GNULIB_DUP3)/g' \ + -e 's/@''GNULIB_ENVIRON''@/$(GNULIB_ENVIRON)/g' \ + -e 's/@''GNULIB_EUIDACCESS''@/$(GNULIB_EUIDACCESS)/g' \ + -e 's/@''GNULIB_FACCESSAT''@/$(GNULIB_FACCESSAT)/g' \ + -e 's/@''GNULIB_FCHDIR''@/$(GNULIB_FCHDIR)/g' \ + -e 's/@''GNULIB_FCHOWNAT''@/$(GNULIB_FCHOWNAT)/g' \ + -e 's/@''GNULIB_FDATASYNC''@/$(GNULIB_FDATASYNC)/g' \ + -e 's/@''GNULIB_FSYNC''@/$(GNULIB_FSYNC)/g' \ + -e 's/@''GNULIB_FTRUNCATE''@/$(GNULIB_FTRUNCATE)/g' \ + -e 's/@''GNULIB_GETCWD''@/$(GNULIB_GETCWD)/g' \ + -e 's/@''GNULIB_GETDOMAINNAME''@/$(GNULIB_GETDOMAINNAME)/g' \ + -e 's/@''GNULIB_GETDTABLESIZE''@/$(GNULIB_GETDTABLESIZE)/g' \ + -e 's/@''GNULIB_GETGROUPS''@/$(GNULIB_GETGROUPS)/g' \ + -e 's/@''GNULIB_GETHOSTNAME''@/$(GNULIB_GETHOSTNAME)/g' \ + -e 's/@''GNULIB_GETLOGIN''@/$(GNULIB_GETLOGIN)/g' \ + -e 's/@''GNULIB_GETLOGIN_R''@/$(GNULIB_GETLOGIN_R)/g' \ + -e 's/@''GNULIB_GETPAGESIZE''@/$(GNULIB_GETPAGESIZE)/g' \ + -e 's/@''GNULIB_GETUSERSHELL''@/$(GNULIB_GETUSERSHELL)/g' \ + -e 's/@''GNULIB_GROUP_MEMBER''@/$(GNULIB_GROUP_MEMBER)/g' \ + -e 's/@''GNULIB_ISATTY''@/$(GNULIB_ISATTY)/g' \ + -e 's/@''GNULIB_LCHOWN''@/$(GNULIB_LCHOWN)/g' \ + -e 's/@''GNULIB_LINK''@/$(GNULIB_LINK)/g' \ + -e 's/@''GNULIB_LINKAT''@/$(GNULIB_LINKAT)/g' \ + -e 's/@''GNULIB_LSEEK''@/$(GNULIB_LSEEK)/g' \ + -e 's/@''GNULIB_PIPE''@/$(GNULIB_PIPE)/g' \ + -e 's/@''GNULIB_PIPE2''@/$(GNULIB_PIPE2)/g' \ + -e 's/@''GNULIB_PREAD''@/$(GNULIB_PREAD)/g' \ + -e 's/@''GNULIB_PWRITE''@/$(GNULIB_PWRITE)/g' \ + -e 's/@''GNULIB_READ''@/$(GNULIB_READ)/g' \ + -e 's/@''GNULIB_READLINK''@/$(GNULIB_READLINK)/g' \ + -e 's/@''GNULIB_READLINKAT''@/$(GNULIB_READLINKAT)/g' \ + -e 's/@''GNULIB_RMDIR''@/$(GNULIB_RMDIR)/g' \ + -e 's/@''GNULIB_SETHOSTNAME''@/$(GNULIB_SETHOSTNAME)/g' \ + -e 's/@''GNULIB_SLEEP''@/$(GNULIB_SLEEP)/g' \ + -e 's/@''GNULIB_SYMLINK''@/$(GNULIB_SYMLINK)/g' \ + -e 's/@''GNULIB_SYMLINKAT''@/$(GNULIB_SYMLINKAT)/g' \ + -e 's/@''GNULIB_TTYNAME_R''@/$(GNULIB_TTYNAME_R)/g' \ + -e 's/@''GNULIB_UNISTD_H_GETOPT''@/0$(GNULIB_GL_UNISTD_H_GETOPT)/g' \ + -e 's/@''GNULIB_UNISTD_H_NONBLOCKING''@/$(GNULIB_UNISTD_H_NONBLOCKING)/g' \ + -e 's/@''GNULIB_UNISTD_H_SIGPIPE''@/$(GNULIB_UNISTD_H_SIGPIPE)/g' \ + -e 's/@''GNULIB_UNLINK''@/$(GNULIB_UNLINK)/g' \ + -e 's/@''GNULIB_UNLINKAT''@/$(GNULIB_UNLINKAT)/g' \ + -e 's/@''GNULIB_USLEEP''@/$(GNULIB_USLEEP)/g' \ + -e 's/@''GNULIB_WRITE''@/$(GNULIB_WRITE)/g' \ + < $(srcdir)/unistd.in.h | \ + sed -e 's|@''HAVE_CHOWN''@|$(HAVE_CHOWN)|g' \ + -e 's|@''HAVE_DUP2''@|$(HAVE_DUP2)|g' \ + -e 's|@''HAVE_DUP3''@|$(HAVE_DUP3)|g' \ + -e 's|@''HAVE_EUIDACCESS''@|$(HAVE_EUIDACCESS)|g' \ + -e 's|@''HAVE_FACCESSAT''@|$(HAVE_FACCESSAT)|g' \ + -e 's|@''HAVE_FCHDIR''@|$(HAVE_FCHDIR)|g' \ + -e 's|@''HAVE_FCHOWNAT''@|$(HAVE_FCHOWNAT)|g' \ + -e 's|@''HAVE_FDATASYNC''@|$(HAVE_FDATASYNC)|g' \ + -e 's|@''HAVE_FSYNC''@|$(HAVE_FSYNC)|g' \ + -e 's|@''HAVE_FTRUNCATE''@|$(HAVE_FTRUNCATE)|g' \ + -e 's|@''HAVE_GETDTABLESIZE''@|$(HAVE_GETDTABLESIZE)|g' \ + -e 's|@''HAVE_GETGROUPS''@|$(HAVE_GETGROUPS)|g' \ + -e 's|@''HAVE_GETHOSTNAME''@|$(HAVE_GETHOSTNAME)|g' \ + -e 's|@''HAVE_GETLOGIN''@|$(HAVE_GETLOGIN)|g' \ + -e 's|@''HAVE_GETPAGESIZE''@|$(HAVE_GETPAGESIZE)|g' \ + -e 's|@''HAVE_GROUP_MEMBER''@|$(HAVE_GROUP_MEMBER)|g' \ + -e 's|@''HAVE_LCHOWN''@|$(HAVE_LCHOWN)|g' \ + -e 's|@''HAVE_LINK''@|$(HAVE_LINK)|g' \ + -e 's|@''HAVE_LINKAT''@|$(HAVE_LINKAT)|g' \ + -e 's|@''HAVE_PIPE''@|$(HAVE_PIPE)|g' \ + -e 's|@''HAVE_PIPE2''@|$(HAVE_PIPE2)|g' \ + -e 's|@''HAVE_PREAD''@|$(HAVE_PREAD)|g' \ + -e 's|@''HAVE_PWRITE''@|$(HAVE_PWRITE)|g' \ + -e 's|@''HAVE_READLINK''@|$(HAVE_READLINK)|g' \ + -e 's|@''HAVE_READLINKAT''@|$(HAVE_READLINKAT)|g' \ + -e 's|@''HAVE_SETHOSTNAME''@|$(HAVE_SETHOSTNAME)|g' \ + -e 's|@''HAVE_SLEEP''@|$(HAVE_SLEEP)|g' \ + -e 's|@''HAVE_SYMLINK''@|$(HAVE_SYMLINK)|g' \ + -e 's|@''HAVE_SYMLINKAT''@|$(HAVE_SYMLINKAT)|g' \ + -e 's|@''HAVE_UNLINKAT''@|$(HAVE_UNLINKAT)|g' \ + -e 's|@''HAVE_USLEEP''@|$(HAVE_USLEEP)|g' \ + -e 's|@''HAVE_DECL_ENVIRON''@|$(HAVE_DECL_ENVIRON)|g' \ + -e 's|@''HAVE_DECL_FCHDIR''@|$(HAVE_DECL_FCHDIR)|g' \ + -e 's|@''HAVE_DECL_FDATASYNC''@|$(HAVE_DECL_FDATASYNC)|g' \ + -e 's|@''HAVE_DECL_GETDOMAINNAME''@|$(HAVE_DECL_GETDOMAINNAME)|g' \ + -e 's|@''HAVE_DECL_GETLOGIN_R''@|$(HAVE_DECL_GETLOGIN_R)|g' \ + -e 's|@''HAVE_DECL_GETPAGESIZE''@|$(HAVE_DECL_GETPAGESIZE)|g' \ + -e 's|@''HAVE_DECL_GETUSERSHELL''@|$(HAVE_DECL_GETUSERSHELL)|g' \ + -e 's|@''HAVE_DECL_SETHOSTNAME''@|$(HAVE_DECL_SETHOSTNAME)|g' \ + -e 's|@''HAVE_DECL_TTYNAME_R''@|$(HAVE_DECL_TTYNAME_R)|g' \ + -e 's|@''HAVE_OS_H''@|$(HAVE_OS_H)|g' \ + -e 's|@''HAVE_SYS_PARAM_H''@|$(HAVE_SYS_PARAM_H)|g' \ + | \ + sed -e 's|@''REPLACE_CHOWN''@|$(REPLACE_CHOWN)|g' \ + -e 's|@''REPLACE_CLOSE''@|$(REPLACE_CLOSE)|g' \ + -e 's|@''REPLACE_DUP''@|$(REPLACE_DUP)|g' \ + -e 's|@''REPLACE_DUP2''@|$(REPLACE_DUP2)|g' \ + -e 's|@''REPLACE_FCHOWNAT''@|$(REPLACE_FCHOWNAT)|g' \ + -e 's|@''REPLACE_FTRUNCATE''@|$(REPLACE_FTRUNCATE)|g' \ + -e 's|@''REPLACE_GETCWD''@|$(REPLACE_GETCWD)|g' \ + -e 's|@''REPLACE_GETDOMAINNAME''@|$(REPLACE_GETDOMAINNAME)|g' \ + -e 's|@''REPLACE_GETDTABLESIZE''@|$(REPLACE_GETDTABLESIZE)|g' \ + -e 's|@''REPLACE_GETLOGIN_R''@|$(REPLACE_GETLOGIN_R)|g' \ + -e 's|@''REPLACE_GETGROUPS''@|$(REPLACE_GETGROUPS)|g' \ + -e 's|@''REPLACE_GETPAGESIZE''@|$(REPLACE_GETPAGESIZE)|g' \ + -e 's|@''REPLACE_ISATTY''@|$(REPLACE_ISATTY)|g' \ + -e 's|@''REPLACE_LCHOWN''@|$(REPLACE_LCHOWN)|g' \ + -e 's|@''REPLACE_LINK''@|$(REPLACE_LINK)|g' \ + -e 's|@''REPLACE_LINKAT''@|$(REPLACE_LINKAT)|g' \ + -e 's|@''REPLACE_LSEEK''@|$(REPLACE_LSEEK)|g' \ + -e 's|@''REPLACE_PREAD''@|$(REPLACE_PREAD)|g' \ + -e 's|@''REPLACE_PWRITE''@|$(REPLACE_PWRITE)|g' \ + -e 's|@''REPLACE_READ''@|$(REPLACE_READ)|g' \ + -e 's|@''REPLACE_READLINK''@|$(REPLACE_READLINK)|g' \ + -e 's|@''REPLACE_READLINKAT''@|$(REPLACE_READLINKAT)|g' \ + -e 's|@''REPLACE_RMDIR''@|$(REPLACE_RMDIR)|g' \ + -e 's|@''REPLACE_SLEEP''@|$(REPLACE_SLEEP)|g' \ + -e 's|@''REPLACE_SYMLINK''@|$(REPLACE_SYMLINK)|g' \ + -e 's|@''REPLACE_SYMLINKAT''@|$(REPLACE_SYMLINKAT)|g' \ + -e 's|@''REPLACE_TTYNAME_R''@|$(REPLACE_TTYNAME_R)|g' \ + -e 's|@''REPLACE_UNLINK''@|$(REPLACE_UNLINK)|g' \ + -e 's|@''REPLACE_UNLINKAT''@|$(REPLACE_UNLINKAT)|g' \ + -e 's|@''REPLACE_USLEEP''@|$(REPLACE_USLEEP)|g' \ + -e 's|@''REPLACE_WRITE''@|$(REPLACE_WRITE)|g' \ + -e 's|@''UNISTD_H_HAVE_WINSOCK2_H''@|$(UNISTD_H_HAVE_WINSOCK2_H)|g' \ + -e 's|@''UNISTD_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS''@|$(UNISTD_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS)|g' \ + -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)'; \ + } > $@-t && \ + mv $@-t $@ + +unistr.h: unistr.in.h + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/unistr.in.h; \ + } > $@-t && \ + mv -f $@-t $@ + +unitypes.h: unitypes.in.h + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/unitypes.in.h; \ + } > $@-t && \ + mv -f $@-t $@ + +uniwidth.h: uniwidth.in.h + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/uniwidth.in.h; \ + } > $@-t && \ + mv -f $@-t $@ + +# We need the following in order to create when the system +# version does not work standalone. +wchar.h: wchar.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''HAVE_FEATURES_H''@|$(HAVE_FEATURES_H)|g' \ + -e 's|@''NEXT_WCHAR_H''@|$(NEXT_WCHAR_H)|g' \ + -e 's|@''HAVE_WCHAR_H''@|$(HAVE_WCHAR_H)|g' \ + -e 's/@''GNULIB_BTOWC''@/$(GNULIB_BTOWC)/g' \ + -e 's/@''GNULIB_WCTOB''@/$(GNULIB_WCTOB)/g' \ + -e 's/@''GNULIB_MBSINIT''@/$(GNULIB_MBSINIT)/g' \ + -e 's/@''GNULIB_MBRTOWC''@/$(GNULIB_MBRTOWC)/g' \ + -e 's/@''GNULIB_MBRLEN''@/$(GNULIB_MBRLEN)/g' \ + -e 's/@''GNULIB_MBSRTOWCS''@/$(GNULIB_MBSRTOWCS)/g' \ + -e 's/@''GNULIB_MBSNRTOWCS''@/$(GNULIB_MBSNRTOWCS)/g' \ + -e 's/@''GNULIB_WCRTOMB''@/$(GNULIB_WCRTOMB)/g' \ + -e 's/@''GNULIB_WCSRTOMBS''@/$(GNULIB_WCSRTOMBS)/g' \ + -e 's/@''GNULIB_WCSNRTOMBS''@/$(GNULIB_WCSNRTOMBS)/g' \ + -e 's/@''GNULIB_WCWIDTH''@/$(GNULIB_WCWIDTH)/g' \ + -e 's/@''GNULIB_WMEMCHR''@/$(GNULIB_WMEMCHR)/g' \ + -e 's/@''GNULIB_WMEMCMP''@/$(GNULIB_WMEMCMP)/g' \ + -e 's/@''GNULIB_WMEMCPY''@/$(GNULIB_WMEMCPY)/g' \ + -e 's/@''GNULIB_WMEMMOVE''@/$(GNULIB_WMEMMOVE)/g' \ + -e 's/@''GNULIB_WMEMSET''@/$(GNULIB_WMEMSET)/g' \ + -e 's/@''GNULIB_WCSLEN''@/$(GNULIB_WCSLEN)/g' \ + -e 's/@''GNULIB_WCSNLEN''@/$(GNULIB_WCSNLEN)/g' \ + -e 's/@''GNULIB_WCSCPY''@/$(GNULIB_WCSCPY)/g' \ + -e 's/@''GNULIB_WCPCPY''@/$(GNULIB_WCPCPY)/g' \ + -e 's/@''GNULIB_WCSNCPY''@/$(GNULIB_WCSNCPY)/g' \ + -e 's/@''GNULIB_WCPNCPY''@/$(GNULIB_WCPNCPY)/g' \ + -e 's/@''GNULIB_WCSCAT''@/$(GNULIB_WCSCAT)/g' \ + -e 's/@''GNULIB_WCSNCAT''@/$(GNULIB_WCSNCAT)/g' \ + -e 's/@''GNULIB_WCSCMP''@/$(GNULIB_WCSCMP)/g' \ + -e 's/@''GNULIB_WCSNCMP''@/$(GNULIB_WCSNCMP)/g' \ + -e 's/@''GNULIB_WCSCASECMP''@/$(GNULIB_WCSCASECMP)/g' \ + -e 's/@''GNULIB_WCSNCASECMP''@/$(GNULIB_WCSNCASECMP)/g' \ + -e 's/@''GNULIB_WCSCOLL''@/$(GNULIB_WCSCOLL)/g' \ + -e 's/@''GNULIB_WCSXFRM''@/$(GNULIB_WCSXFRM)/g' \ + -e 's/@''GNULIB_WCSDUP''@/$(GNULIB_WCSDUP)/g' \ + -e 's/@''GNULIB_WCSCHR''@/$(GNULIB_WCSCHR)/g' \ + -e 's/@''GNULIB_WCSRCHR''@/$(GNULIB_WCSRCHR)/g' \ + -e 's/@''GNULIB_WCSCSPN''@/$(GNULIB_WCSCSPN)/g' \ + -e 's/@''GNULIB_WCSSPN''@/$(GNULIB_WCSSPN)/g' \ + -e 's/@''GNULIB_WCSPBRK''@/$(GNULIB_WCSPBRK)/g' \ + -e 's/@''GNULIB_WCSSTR''@/$(GNULIB_WCSSTR)/g' \ + -e 's/@''GNULIB_WCSTOK''@/$(GNULIB_WCSTOK)/g' \ + -e 's/@''GNULIB_WCSWIDTH''@/$(GNULIB_WCSWIDTH)/g' \ + < $(srcdir)/wchar.in.h | \ + sed -e 's|@''HAVE_WINT_T''@|$(HAVE_WINT_T)|g' \ + -e 's|@''HAVE_BTOWC''@|$(HAVE_BTOWC)|g' \ + -e 's|@''HAVE_MBSINIT''@|$(HAVE_MBSINIT)|g' \ + -e 's|@''HAVE_MBRTOWC''@|$(HAVE_MBRTOWC)|g' \ + -e 's|@''HAVE_MBRLEN''@|$(HAVE_MBRLEN)|g' \ + -e 's|@''HAVE_MBSRTOWCS''@|$(HAVE_MBSRTOWCS)|g' \ + -e 's|@''HAVE_MBSNRTOWCS''@|$(HAVE_MBSNRTOWCS)|g' \ + -e 's|@''HAVE_WCRTOMB''@|$(HAVE_WCRTOMB)|g' \ + -e 's|@''HAVE_WCSRTOMBS''@|$(HAVE_WCSRTOMBS)|g' \ + -e 's|@''HAVE_WCSNRTOMBS''@|$(HAVE_WCSNRTOMBS)|g' \ + -e 's|@''HAVE_WMEMCHR''@|$(HAVE_WMEMCHR)|g' \ + -e 's|@''HAVE_WMEMCMP''@|$(HAVE_WMEMCMP)|g' \ + -e 's|@''HAVE_WMEMCPY''@|$(HAVE_WMEMCPY)|g' \ + -e 's|@''HAVE_WMEMMOVE''@|$(HAVE_WMEMMOVE)|g' \ + -e 's|@''HAVE_WMEMSET''@|$(HAVE_WMEMSET)|g' \ + -e 's|@''HAVE_WCSLEN''@|$(HAVE_WCSLEN)|g' \ + -e 's|@''HAVE_WCSNLEN''@|$(HAVE_WCSNLEN)|g' \ + -e 's|@''HAVE_WCSCPY''@|$(HAVE_WCSCPY)|g' \ + -e 's|@''HAVE_WCPCPY''@|$(HAVE_WCPCPY)|g' \ + -e 's|@''HAVE_WCSNCPY''@|$(HAVE_WCSNCPY)|g' \ + -e 's|@''HAVE_WCPNCPY''@|$(HAVE_WCPNCPY)|g' \ + -e 's|@''HAVE_WCSCAT''@|$(HAVE_WCSCAT)|g' \ + -e 's|@''HAVE_WCSNCAT''@|$(HAVE_WCSNCAT)|g' \ + -e 's|@''HAVE_WCSCMP''@|$(HAVE_WCSCMP)|g' \ + -e 's|@''HAVE_WCSNCMP''@|$(HAVE_WCSNCMP)|g' \ + -e 's|@''HAVE_WCSCASECMP''@|$(HAVE_WCSCASECMP)|g' \ + -e 's|@''HAVE_WCSNCASECMP''@|$(HAVE_WCSNCASECMP)|g' \ + -e 's|@''HAVE_WCSCOLL''@|$(HAVE_WCSCOLL)|g' \ + -e 's|@''HAVE_WCSXFRM''@|$(HAVE_WCSXFRM)|g' \ + -e 's|@''HAVE_WCSDUP''@|$(HAVE_WCSDUP)|g' \ + -e 's|@''HAVE_WCSCHR''@|$(HAVE_WCSCHR)|g' \ + -e 's|@''HAVE_WCSRCHR''@|$(HAVE_WCSRCHR)|g' \ + -e 's|@''HAVE_WCSCSPN''@|$(HAVE_WCSCSPN)|g' \ + -e 's|@''HAVE_WCSSPN''@|$(HAVE_WCSSPN)|g' \ + -e 's|@''HAVE_WCSPBRK''@|$(HAVE_WCSPBRK)|g' \ + -e 's|@''HAVE_WCSSTR''@|$(HAVE_WCSSTR)|g' \ + -e 's|@''HAVE_WCSTOK''@|$(HAVE_WCSTOK)|g' \ + -e 's|@''HAVE_WCSWIDTH''@|$(HAVE_WCSWIDTH)|g' \ + -e 's|@''HAVE_DECL_WCTOB''@|$(HAVE_DECL_WCTOB)|g' \ + -e 's|@''HAVE_DECL_WCWIDTH''@|$(HAVE_DECL_WCWIDTH)|g' \ + | \ + sed -e 's|@''REPLACE_MBSTATE_T''@|$(REPLACE_MBSTATE_T)|g' \ + -e 's|@''REPLACE_BTOWC''@|$(REPLACE_BTOWC)|g' \ + -e 's|@''REPLACE_WCTOB''@|$(REPLACE_WCTOB)|g' \ + -e 's|@''REPLACE_MBSINIT''@|$(REPLACE_MBSINIT)|g' \ + -e 's|@''REPLACE_MBRTOWC''@|$(REPLACE_MBRTOWC)|g' \ + -e 's|@''REPLACE_MBRLEN''@|$(REPLACE_MBRLEN)|g' \ + -e 's|@''REPLACE_MBSRTOWCS''@|$(REPLACE_MBSRTOWCS)|g' \ + -e 's|@''REPLACE_MBSNRTOWCS''@|$(REPLACE_MBSNRTOWCS)|g' \ + -e 's|@''REPLACE_WCRTOMB''@|$(REPLACE_WCRTOMB)|g' \ + -e 's|@''REPLACE_WCSRTOMBS''@|$(REPLACE_WCSRTOMBS)|g' \ + -e 's|@''REPLACE_WCSNRTOMBS''@|$(REPLACE_WCSNRTOMBS)|g' \ + -e 's|@''REPLACE_WCWIDTH''@|$(REPLACE_WCWIDTH)|g' \ + -e 's|@''REPLACE_WCSWIDTH''@|$(REPLACE_WCSWIDTH)|g' \ + -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)'; \ + } > $@-t && \ + mv $@-t $@ + +# We need the following in order to create when the system +# doesn't have one that works with the given compiler. +wctype.h: wctype.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(WARN_ON_USE_H) + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's/@''HAVE_WCTYPE_H''@/$(HAVE_WCTYPE_H)/g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_WCTYPE_H''@|$(NEXT_WCTYPE_H)|g' \ + -e 's/@''GNULIB_ISWBLANK''@/$(GNULIB_ISWBLANK)/g' \ + -e 's/@''GNULIB_WCTYPE''@/$(GNULIB_WCTYPE)/g' \ + -e 's/@''GNULIB_ISWCTYPE''@/$(GNULIB_ISWCTYPE)/g' \ + -e 's/@''GNULIB_WCTRANS''@/$(GNULIB_WCTRANS)/g' \ + -e 's/@''GNULIB_TOWCTRANS''@/$(GNULIB_TOWCTRANS)/g' \ + -e 's/@''HAVE_ISWBLANK''@/$(HAVE_ISWBLANK)/g' \ + -e 's/@''HAVE_ISWCNTRL''@/$(HAVE_ISWCNTRL)/g' \ + -e 's/@''HAVE_WCTYPE_T''@/$(HAVE_WCTYPE_T)/g' \ + -e 's/@''HAVE_WCTRANS_T''@/$(HAVE_WCTRANS_T)/g' \ + -e 's/@''HAVE_WINT_T''@/$(HAVE_WINT_T)/g' \ + -e 's/@''REPLACE_ISWBLANK''@/$(REPLACE_ISWBLANK)/g' \ + -e 's/@''REPLACE_ISWCNTRL''@/$(REPLACE_ISWCNTRL)/g' \ + -e 's/@''REPLACE_TOWLOWER''@/$(REPLACE_TOWLOWER)/g' \ + -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ + < $(srcdir)/wctype.in.h; \ + } > $@-t && \ + mv $@-t $@ + +mostlyclean-local: mostlyclean-generic + @for dir in '' $(MOSTLYCLEANDIRS); do \ + if test -n "$$dir" && test -d $$dir; then \ + echo "rmdir $$dir"; rmdir $$dir; \ + fi; \ + done; \ + : + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/gettext-tools/gnulib-lib/acl-errno-valid.c b/gettext-tools/gnulib-lib/acl-errno-valid.c new file mode 100644 index 0000000..3287382 --- /dev/null +++ b/gettext-tools/gnulib-lib/acl-errno-valid.c @@ -0,0 +1,52 @@ +/* Test whether ACLs are well supported on this system. + + Copyright 2013-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + Written by Paul Eggert. */ + +#include + +#include + +#include + +/* Return true if errno value ERRNUM indicates that ACLs are well + supported on this system. ERRNUM should be an errno value obtained + after an ACL-related system call fails. */ +bool +acl_errno_valid (int errnum) +{ + /* Recognize some common errors such as from an NFS mount that does + not support ACLs, even when local drives do. */ + switch (errnum) + { + case EBUSY: return false; + case EINVAL: return false; +#if defined __APPLE__ && defined __MACH__ + case ENOENT: return false; +#endif + case ENOSYS: return false; + +#if defined ENOTSUP && ENOTSUP != EOPNOTSUPP +# if ENOTSUP != ENOSYS /* Needed for the MS-Windows port of GNU Emacs. */ + case ENOTSUP: return false; +# endif +#endif + + case EOPNOTSUPP: return false; + default: return true; + } +} diff --git a/gettext-tools/gnulib-lib/acl-internal.h b/gettext-tools/gnulib-lib/acl-internal.h new file mode 100644 index 0000000..b238006 --- /dev/null +++ b/gettext-tools/gnulib-lib/acl-internal.h @@ -0,0 +1,253 @@ +/* Internal implementation of access control lists. + + Copyright (C) 2002-2003, 2005-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + Written by Paul Eggert, Andreas Grünbacher, and Bruno Haible. */ + +#include "acl.h" + +#include +#include + +/* All systems define the ACL related API in . */ +#if HAVE_SYS_ACL_H +# include +#endif +#if defined HAVE_FACL && ! defined GETACLCNT && defined ACL_CNT +# define GETACLCNT ACL_CNT +#endif + +/* On Linux, additional ACL related API is available in . */ +#ifdef HAVE_ACL_LIBACL_H +# include +#endif + +/* On HP-UX >= 11.11, additional ACL API is available in . */ +#if HAVE_ACLV_H +# include +# include +/* HP-UX 11.11 lacks these declarations. */ +extern int acl (char *, int, int, struct acl *); +extern int aclsort (int, int, struct acl *); +#endif + +#include + +#include +#ifndef MIN +# define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif + +#ifndef SIZE_MAX +# define SIZE_MAX ((size_t) -1) +#endif + +#ifndef HAVE_FCHMOD +# define HAVE_FCHMOD false +# define fchmod(fd, mode) (-1) +#endif + +#ifndef _GL_INLINE_HEADER_BEGIN + #error "Please include config.h first." +#endif +_GL_INLINE_HEADER_BEGIN +#ifndef ACL_INTERNAL_INLINE +# define ACL_INTERNAL_INLINE _GL_INLINE +#endif + +#if USE_ACL + +# if HAVE_ACL_GET_FILE +/* POSIX 1003.1e (draft 17 -- abandoned) specific version. */ +/* Linux, FreeBSD, Mac OS X, IRIX, Tru64 */ + +# ifndef MIN_ACL_ENTRIES +# define MIN_ACL_ENTRIES 4 +# endif + +/* POSIX 1003.1e (draft 17) */ +# ifdef HAVE_ACL_GET_FD +/* Most platforms have a 1-argument acl_get_fd, only OSF/1 has a 2-argument + macro(!). */ +# if HAVE_ACL_FREE_TEXT /* OSF/1 */ +ACL_INTERNAL_INLINE acl_t +rpl_acl_get_fd (int fd) +{ + return acl_get_fd (fd, ACL_TYPE_ACCESS); +} +# undef acl_get_fd +# define acl_get_fd rpl_acl_get_fd +# endif +# else +# define HAVE_ACL_GET_FD false +# undef acl_get_fd +# define acl_get_fd(fd) (NULL) +# endif + +/* POSIX 1003.1e (draft 17) */ +# ifdef HAVE_ACL_SET_FD +/* Most platforms have a 2-argument acl_set_fd, only OSF/1 has a 3-argument + macro(!). */ +# if HAVE_ACL_FREE_TEXT /* OSF/1 */ +ACL_INTERNAL_INLINE int +rpl_acl_set_fd (int fd, acl_t acl) +{ + return acl_set_fd (fd, ACL_TYPE_ACCESS, acl); +} +# undef acl_set_fd +# define acl_set_fd rpl_acl_set_fd +# endif +# else +# define HAVE_ACL_SET_FD false +# undef acl_set_fd +# define acl_set_fd(fd, acl) (-1) +# endif + +/* POSIX 1003.1e (draft 13) */ +# if ! HAVE_ACL_FREE_TEXT +# define acl_free_text(buf) acl_free (buf) +# endif + +/* Linux-specific */ +# ifndef HAVE_ACL_EXTENDED_FILE +# define HAVE_ACL_EXTENDED_FILE false +# define acl_extended_file(name) (-1) +# endif + +/* Linux-specific */ +# ifndef HAVE_ACL_FROM_MODE +# define HAVE_ACL_FROM_MODE false +# define acl_from_mode(mode) (NULL) +# endif + +/* Set to 1 if a file's mode is implicit by the ACL. + Set to 0 if a file's mode is stored independently from the ACL. */ +# if (HAVE_ACL_COPY_EXT_NATIVE && HAVE_ACL_CREATE_ENTRY_NP) || defined __sgi /* Mac OS X, IRIX */ +# define MODE_INSIDE_ACL 0 +# else +# define MODE_INSIDE_ACL 1 +# endif + +/* Return the number of entries in ACL. + Return -1 and set errno upon failure to determine it. */ +/* Define a replacement for acl_entries if needed. (Only Linux has it.) */ +# if !HAVE_ACL_ENTRIES +# define acl_entries rpl_acl_entries +extern int acl_entries (acl_t); +# endif + +# if HAVE_ACL_TYPE_EXTENDED /* Mac OS X */ +/* ACL is an ACL, from a file, stored as type ACL_TYPE_EXTENDED. + Return 1 if the given ACL is non-trivial. + Return 0 if it is trivial. */ +extern int acl_extended_nontrivial (acl_t); +# else +/* ACL is an ACL, from a file, stored as type ACL_TYPE_ACCESS. + Return 1 if the given ACL is non-trivial. + Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. + Return -1 and set errno upon failure to determine it. */ +extern int acl_access_nontrivial (acl_t); +# endif + +# elif HAVE_FACL && defined GETACL /* Solaris, Cygwin, not HP-UX */ + +/* Set to 1 if a file's mode is implicit by the ACL. + Set to 0 if a file's mode is stored independently from the ACL. */ +# if defined __CYGWIN__ /* Cygwin */ +# define MODE_INSIDE_ACL 0 +# else /* Solaris */ +# define MODE_INSIDE_ACL 1 +# endif + +/* Return 1 if the given ACL is non-trivial. + Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */ +extern int acl_nontrivial (int count, aclent_t *entries) _GL_ATTRIBUTE_PURE; + +# ifdef ACE_GETACL /* Solaris 10 */ + +/* Test an ACL retrieved with ACE_GETACL. + Return 1 if the given ACL, consisting of COUNT entries, is non-trivial. + Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */ +extern int acl_ace_nontrivial (int count, ace_t *entries) _GL_ATTRIBUTE_PURE; + +/* Definitions for when the built executable is executed on Solaris 10 + (newer version) or Solaris 11. */ +/* For a_type. */ +# define OLD_ALLOW 0 +# define OLD_DENY 1 +# define NEW_ACE_ACCESS_ALLOWED_ACE_TYPE 0 /* replaces ALLOW */ +# define NEW_ACE_ACCESS_DENIED_ACE_TYPE 1 /* replaces DENY */ +/* For a_flags. */ +# define OLD_ACE_OWNER 0x0100 +# define OLD_ACE_GROUP 0x0200 +# define OLD_ACE_OTHER 0x0400 +# define NEW_ACE_OWNER 0x1000 +# define NEW_ACE_GROUP 0x2000 +# define NEW_ACE_IDENTIFIER_GROUP 0x0040 +# define NEW_ACE_EVERYONE 0x4000 +/* For a_access_mask. */ +# define NEW_ACE_READ_DATA 0x001 /* corresponds to 'r' */ +# define NEW_ACE_WRITE_DATA 0x002 /* corresponds to 'w' */ +# define NEW_ACE_APPEND_DATA 0x004 +# define NEW_ACE_READ_NAMED_ATTRS 0x008 +# define NEW_ACE_WRITE_NAMED_ATTRS 0x010 +# define NEW_ACE_EXECUTE 0x020 +# define NEW_ACE_DELETE_CHILD 0x040 +# define NEW_ACE_READ_ATTRIBUTES 0x080 +# define NEW_ACE_WRITE_ATTRIBUTES 0x100 +# define NEW_ACE_DELETE 0x10000 +# define NEW_ACE_READ_ACL 0x20000 +# define NEW_ACE_WRITE_ACL 0x40000 +# define NEW_ACE_WRITE_OWNER 0x80000 +# define NEW_ACE_SYNCHRONIZE 0x100000 + +# endif + +# elif HAVE_GETACL /* HP-UX */ + +/* Return 1 if the given ACL is non-trivial. + Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */ +extern int acl_nontrivial (int count, struct acl_entry *entries, struct stat *sb); + +# if HAVE_ACLV_H /* HP-UX >= 11.11 */ + +/* Return 1 if the given ACL is non-trivial. + Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */ +extern int aclv_nontrivial (int count, struct acl *entries); + +# endif + +# elif HAVE_ACLX_GET && 0 /* AIX */ + +/* TODO */ + +# elif HAVE_STATACL /* older AIX */ + +/* Return 1 if the given ACL is non-trivial. + Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */ +extern int acl_nontrivial (struct acl *a); + +# elif HAVE_ACLSORT /* NonStop Kernel */ + +/* Return 1 if the given ACL is non-trivial. + Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */ +extern int acl_nontrivial (int count, struct acl *entries); + +# endif + +#endif + +_GL_INLINE_HEADER_END diff --git a/gettext-tools/gnulib-lib/acl.h b/gettext-tools/gnulib-lib/acl.h new file mode 100644 index 0000000..f67e350 --- /dev/null +++ b/gettext-tools/gnulib-lib/acl.h @@ -0,0 +1,35 @@ +/* acl.c - access control lists + + Copyright (C) 2002, 2008-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + Written by Paul Eggert. */ + +#ifndef _GL_ACL_H +#define _GL_ACL_H 1 + +#include +#include +#include + +bool acl_errno_valid (int) _GL_ATTRIBUTE_CONST; +int file_has_acl (char const *, struct stat const *); +int qset_acl (char const *, int, mode_t); +int set_acl (char const *, int, mode_t); +int qcopy_acl (char const *, int, char const *, int, mode_t); +int copy_acl (char const *, int, char const *, int, mode_t); +int chmod_or_fchmod (char const *, int, mode_t); + +#endif diff --git a/gettext-tools/gnulib-lib/acl_entries.c b/gettext-tools/gnulib-lib/acl_entries.c new file mode 100644 index 0000000..39d6b28 --- /dev/null +++ b/gettext-tools/gnulib-lib/acl_entries.c @@ -0,0 +1,75 @@ +/* Return the number of entries in an ACL. + + Copyright (C) 2002-2003, 2005-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + Written by Paul Eggert and Andreas Gruenbacher. */ + +#include + +#include "acl-internal.h" + +/* This file assumes POSIX-draft like ACLs + (Linux, FreeBSD, Mac OS X, IRIX, Tru64). */ + +/* Return the number of entries in ACL. + Return -1 and set errno upon failure to determine it. */ + +int +acl_entries (acl_t acl) +{ + int count = 0; + + if (acl != NULL) + { +#if HAVE_ACL_FIRST_ENTRY /* Linux, FreeBSD, Mac OS X */ +# if HAVE_ACL_TYPE_EXTENDED /* Mac OS X */ + /* acl_get_entry returns 0 when it successfully fetches an entry, + and -1/EINVAL at the end. */ + acl_entry_t ace; + int got_one; + + for (got_one = acl_get_entry (acl, ACL_FIRST_ENTRY, &ace); + got_one >= 0; + got_one = acl_get_entry (acl, ACL_NEXT_ENTRY, &ace)) + count++; +# else /* Linux, FreeBSD */ + /* acl_get_entry returns 1 when it successfully fetches an entry, + and 0 at the end. */ + acl_entry_t ace; + int got_one; + + for (got_one = acl_get_entry (acl, ACL_FIRST_ENTRY, &ace); + got_one > 0; + got_one = acl_get_entry (acl, ACL_NEXT_ENTRY, &ace)) + count++; + if (got_one < 0) + return -1; +# endif +#else /* IRIX, Tru64 */ +# if HAVE_ACL_TO_SHORT_TEXT /* IRIX */ + /* Don't use acl_get_entry: it is undocumented. */ + count = acl->acl_cnt; +# endif +# if HAVE_ACL_FREE_TEXT /* Tru64 */ + /* Don't use acl_get_entry: it takes only one argument and does not + work. */ + count = acl->acl_num; +# endif +#endif + } + + return count; +} diff --git a/gettext-tools/gnulib-lib/addext.c b/gettext-tools/gnulib-lib/addext.c new file mode 100644 index 0000000..fef2b9b --- /dev/null +++ b/gettext-tools/gnulib-lib/addext.c @@ -0,0 +1,97 @@ +/* addext.c -- add an extension to a file name + Copyright (C) 1990, 1997-1999, 2001-2003, 2005-2006 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Written by David MacKenzie and Paul Eggert */ + +#include + +#ifndef HAVE_DOS_FILE_NAMES +# define HAVE_DOS_FILE_NAMES 0 +#endif +#ifndef HAVE_LONG_FILE_NAMES +# define HAVE_LONG_FILE_NAMES 0 +#endif + +#include "backupfile.h" + +#include +#ifndef _POSIX_NAME_MAX +# define _POSIX_NAME_MAX 14 +#endif + +#include +#if HAVE_STRING_H +# include +#else +# include +#endif + +#include + +#include "basename.h" + +/* Append to FILENAME the extension EXT, unless the result would be too long, + in which case just append the character E. */ + +void +addext (char *filename, char const *ext, char e) +{ + char *s = basename (filename); + size_t slen = strlen (s), extlen = strlen (ext); + long slen_max = -1; + +#if HAVE_PATHCONF && defined _PC_NAME_MAX + if (slen + extlen <= _POSIX_NAME_MAX && ! HAVE_DOS_FILE_NAMES) + /* The file name is so short there's no need to call pathconf. */ + slen_max = _POSIX_NAME_MAX; + else if (s == filename) + slen_max = pathconf (".", _PC_NAME_MAX); + else + { + char c = *s; + *s = 0; + slen_max = pathconf (filename, _PC_NAME_MAX); + *s = c; + } +#endif + if (slen_max < 0) + slen_max = HAVE_LONG_FILE_NAMES ? 255 : 14; + + if (HAVE_DOS_FILE_NAMES && slen_max <= 12) + { + /* Live within DOS's 8.3 limit. */ + char *dot = strchr (s, '.'); + if (dot) + { + slen -= dot + 1 - s; + s = dot + 1; + slen_max = 3; + } + else + slen_max = 8; + extlen = 9; /* Don't use EXT. */ + } + + if (slen + extlen <= slen_max) + strcpy (s + slen, ext); + else + { + if (slen_max <= slen) + slen = slen_max - 1; + s[slen] = e; + s[slen + 1] = 0; + } +} diff --git a/gettext-tools/gnulib-lib/alignof.h b/gettext-tools/gnulib-lib/alignof.h new file mode 100644 index 0000000..9d161df --- /dev/null +++ b/gettext-tools/gnulib-lib/alignof.h @@ -0,0 +1,50 @@ +/* Determine alignment of types. + Copyright (C) 2003-2004, 2006, 2009-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . */ + +#ifndef _ALIGNOF_H +#define _ALIGNOF_H + +#include + +/* alignof_slot (TYPE) + Determine the alignment of a structure slot (field) of a given type, + at compile time. Note that the result depends on the ABI. + This is the same as alignof (TYPE) and _Alignof (TYPE), defined in + if __alignof_is_defined is 1. + Note: The result cannot be used as a value for an 'enum' constant, + due to bugs in HP-UX 10.20 cc and AIX 3.2.5 xlc. */ +#if defined __cplusplus + template struct alignof_helper { char __slot1; type __slot2; }; +# define alignof_slot(type) offsetof (alignof_helper, __slot2) +#else +# define alignof_slot(type) offsetof (struct { char __slot1; type __slot2; }, __slot2) +#endif + +/* alignof_type (TYPE) + Determine the good alignment of an object of the given type at compile time. + Note that this is not necessarily the same as alignof_slot(type). + For example, with GNU C on x86 platforms: alignof_type(double) = 8, but + - when -malign-double is not specified: alignof_slot(double) = 4, + - when -malign-double is specified: alignof_slot(double) = 8. + Note: The result cannot be used as a value for an 'enum' constant, + due to bugs in HP-UX 10.20 cc and AIX 3.2.5 xlc. */ +#if defined __GNUC__ || defined __IBM__ALIGNOF__ +# define alignof_type __alignof__ +#else +# define alignof_type alignof_slot +#endif + +#endif /* _ALIGNOF_H */ diff --git a/gettext-tools/gnulib-lib/alloca.in.h b/gettext-tools/gnulib-lib/alloca.in.h new file mode 100644 index 0000000..964cb8d --- /dev/null +++ b/gettext-tools/gnulib-lib/alloca.in.h @@ -0,0 +1,68 @@ +/* Memory allocation on the stack. + Copyright (C) 1995, 1999, 2001-2007 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* When this file is included, it may be preceded only by preprocessor + declarations. Thanks to AIX. Therefore we include it right after + "config.h", not later. */ + +/* Avoid using the symbol _ALLOCA_H here, as Bison assumes _ALLOCA_H + means there is a real alloca function. */ +#ifndef _GL_ALLOCA_H +#define _GL_ALLOCA_H + +/* alloca(N) returns a pointer (void* or char*) to N bytes of memory + allocated on the stack, and which will last until the function returns. + Use of alloca should be avoided: + - inside arguments of function calls - undefined behaviour, + - in inline functions - the allocation may actually last until the + calling function returns, + - for huge N (say, N >= 65536) - you never know how large (or small) + the stack is, and when the stack cannot fulfill the memory allocation + request, the program just crashes. + */ + +#ifndef alloca +# ifdef __GNUC__ +# define alloca __builtin_alloca +# else +# ifdef _MSC_VER +# include +# define alloca _alloca +# else +# if HAVE_ALLOCA_H +# include +# else +# ifdef _AIX + #pragma alloca +# else +# ifdef __hpux /* This section must match that of bison generated files. */ +# ifdef __cplusplus +extern "C" void *alloca (unsigned int); +# else /* not __cplusplus */ +extern void *alloca (); +# endif /* not __cplusplus */ +# else /* not __hpux */ +# ifndef alloca +extern char *alloca (); +# endif +# endif /* __hpux */ +# endif +# endif +# endif +# endif +#endif + +#endif /* _GL_ALLOCA_H */ diff --git a/gettext-tools/gnulib-lib/allocator.c b/gettext-tools/gnulib-lib/allocator.c new file mode 100644 index 0000000..2c1a3da --- /dev/null +++ b/gettext-tools/gnulib-lib/allocator.c @@ -0,0 +1,5 @@ +#define _GL_USE_STDLIB_ALLOC 1 +#include +#include "allocator.h" +#include +struct allocator const stdlib_allocator = { malloc, realloc, free, NULL }; diff --git a/gettext-tools/gnulib-lib/allocator.h b/gettext-tools/gnulib-lib/allocator.h new file mode 100644 index 0000000..0904b32 --- /dev/null +++ b/gettext-tools/gnulib-lib/allocator.h @@ -0,0 +1,58 @@ +/* Memory allocators such as malloc+free. + + Copyright (C) 2011-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Written by Paul Eggert. */ + +#ifndef _GL_ALLOCATOR_H +#define _GL_ALLOCATOR_H + +#include + +/* An object describing a memory allocator family. */ + +struct allocator +{ + /* Do not use GCC attributes such as __attribute__ ((malloc)) with + the function types pointed at by these members, because these + attributes do not work with pointers to functions. See + . */ + + /* Call ALLOCATE to allocate memory, like 'malloc'. On failure ALLOCATE + should return NULL, though not necessarily set errno. When given + a zero size it may return NULL even if successful. */ + void *(*allocate) (size_t); + + /* If nonnull, call REALLOCATE to reallocate memory, like 'realloc'. + On failure REALLOCATE should return NULL, though not necessarily set + errno. When given a zero size it may return NULL even if + successful. */ + void *(*reallocate) (void *, size_t); + + /* Call FREE to free memory, like 'free'. */ + void (*free) (void *); + + /* If nonnull, call DIE (SIZE) if MALLOC (SIZE) or REALLOC (..., + SIZE) fails. DIE should not return. SIZE should equal SIZE_MAX + if size_t overflow was detected while calculating sizes to be + passed to MALLOC or REALLOC. */ + void (*die) (size_t); +}; + +/* An allocator using the stdlib functions and a null DIE function. */ +extern struct allocator const stdlib_allocator; + +#endif /* _GL_ALLOCATOR_H */ diff --git a/gettext-tools/gnulib-lib/areadlink.c b/gettext-tools/gnulib-lib/areadlink.c new file mode 100644 index 0000000..b4b856c --- /dev/null +++ b/gettext-tools/gnulib-lib/areadlink.c @@ -0,0 +1,56 @@ +/* areadlink.c -- readlink wrapper to return the link name in malloc'd storage + Unlike xreadlink and xreadlink_with_size, don't ever call exit. + + Copyright (C) 2001, 2003-2007, 2009-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Written by Jim Meyering + and Bruno Haible . */ + +#include + +/* Specification. */ +#include "areadlink.h" + +#include "careadlinkat.h" + +#include +#include + +/* Get the symbolic link value of FILENAME and put it into BUFFER, with + size BUFFER_SIZE. This function acts like readlink but has + readlinkat's signature. */ +static ssize_t +careadlinkatcwd (int fd, char const *filename, char *buffer, + size_t buffer_size) +{ + /* FD must be AT_FDCWD here, otherwise the caller is using this + function in contexts it was not meant for. */ + if (fd != AT_FDCWD) + abort (); + return readlink (filename, buffer, buffer_size); +} + +/* Call readlink to get the symbolic link value of FILENAME. + Return a pointer to that NUL-terminated string in malloc'd storage. + If readlink fails, return NULL and set errno. + If allocation fails, or if the link value is longer than SIZE_MAX :-), + return NULL and set errno to ENOMEM. */ + +char * +areadlink (char const *filename) +{ + return careadlinkat (AT_FDCWD, filename, NULL, 0, NULL, careadlinkatcwd); +} diff --git a/gettext-tools/gnulib-lib/areadlink.h b/gettext-tools/gnulib-lib/areadlink.h new file mode 100644 index 0000000..59abb37 --- /dev/null +++ b/gettext-tools/gnulib-lib/areadlink.h @@ -0,0 +1,33 @@ +/* Read symbolic links without size limitation. + + Copyright (C) 2001, 2003-2004, 2007, 2009-2014 Free Software Foundation, + Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Written by Jim Meyering */ + +#include + +extern char *areadlink (char const *filename); +extern char *areadlink_with_size (char const *filename, size_t size_hint); + +#if GNULIB_AREADLINKAT +extern char *areadlinkat (int fd, char const *filename); +#endif + +#if GNULIB_AREADLINKAT_WITH_SIZE +extern char *areadlinkat_with_size (int fd, char const *filename, + size_t size_hint); +#endif diff --git a/gettext-tools/gnulib-lib/argmatch.c b/gettext-tools/gnulib-lib/argmatch.c new file mode 100644 index 0000000..f56ab55 --- /dev/null +++ b/gettext-tools/gnulib-lib/argmatch.c @@ -0,0 +1,277 @@ +/* argmatch.c -- find a match for a string in an array + + Copyright (C) 1990, 1998-1999, 2001-2007, 2009-2014 Free Software + Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Written by David MacKenzie + Modified by Akim Demaille */ + +#include + +/* Specification. */ +#include "argmatch.h" + +#include +#include +#include +#include + +#include "gettext.h" +#define _(msgid) gettext (msgid) + +#include "error.h" +#include "quotearg.h" +#include "quote.h" + +#if USE_UNLOCKED_IO +# include "unlocked-io.h" +#endif + +/* When reporting an invalid argument, show nonprinting characters + by using the quoting style ARGMATCH_QUOTING_STYLE. Do not use + literal_quoting_style. */ +#ifndef ARGMATCH_QUOTING_STYLE +# define ARGMATCH_QUOTING_STYLE locale_quoting_style +#endif + +/* Non failing version of argmatch call this function after failing. */ +#ifndef ARGMATCH_DIE +# include "exitfail.h" +# define ARGMATCH_DIE exit (exit_failure) +#endif + +#ifdef ARGMATCH_DIE_DECL +ARGMATCH_DIE_DECL; +#endif + +static void +__argmatch_die (void) +{ + ARGMATCH_DIE; +} + +/* Used by XARGMATCH and XARGCASEMATCH. See description in argmatch.h. + Default to __argmatch_die, but allow caller to change this at run-time. */ +argmatch_exit_fn argmatch_die = __argmatch_die; + + +/* If ARG is an unambiguous match for an element of the + NULL-terminated array ARGLIST, return the index in ARGLIST + of the matched element, else -1 if it does not match any element + or -2 if it is ambiguous (is a prefix of more than one element). + + If VALLIST is none null, use it to resolve ambiguities limited to + synonyms, i.e., for + "yes", "yop" -> 0 + "no", "nope" -> 1 + "y" is a valid argument, for 0, and "n" for 1. */ + +ptrdiff_t +argmatch (const char *arg, const char *const *arglist, + const char *vallist, size_t valsize) +{ + size_t i; /* Temporary index in ARGLIST. */ + size_t arglen; /* Length of ARG. */ + ptrdiff_t matchind = -1; /* Index of first nonexact match. */ + bool ambiguous = false; /* If true, multiple nonexact match(es). */ + + arglen = strlen (arg); + + /* Test all elements for either exact match or abbreviated matches. */ + for (i = 0; arglist[i]; i++) + { + if (!strncmp (arglist[i], arg, arglen)) + { + if (strlen (arglist[i]) == arglen) + /* Exact match found. */ + return i; + else if (matchind == -1) + /* First nonexact match found. */ + matchind = i; + else + { + /* Second nonexact match found. */ + if (vallist == NULL + || memcmp (vallist + valsize * matchind, + vallist + valsize * i, valsize)) + { + /* There is a real ambiguity, or we could not + disambiguate. */ + ambiguous = true; + } + } + } + } + if (ambiguous) + return -2; + else + return matchind; +} + +/* Error reporting for argmatch. + CONTEXT is a description of the type of entity that was being matched. + VALUE is the invalid value that was given. + PROBLEM is the return value from argmatch. */ + +void +argmatch_invalid (const char *context, const char *value, ptrdiff_t problem) +{ + char const *format = (problem == -1 + ? _("invalid argument %s for %s") + : _("ambiguous argument %s for %s")); + + error (0, 0, format, quotearg_n_style (0, ARGMATCH_QUOTING_STYLE, value), + quote_n (1, context)); +} + +/* List the valid arguments for argmatch. + ARGLIST is the same as in argmatch. + VALLIST is a pointer to an array of values. + VALSIZE is the size of the elements of VALLIST */ +void +argmatch_valid (const char *const *arglist, + const char *vallist, size_t valsize) +{ + size_t i; + const char *last_val = NULL; + + /* We try to put synonyms on the same line. The assumption is that + synonyms follow each other */ + fputs (_("Valid arguments are:"), stderr); + for (i = 0; arglist[i]; i++) + if ((i == 0) + || memcmp (last_val, vallist + valsize * i, valsize)) + { + fprintf (stderr, "\n - %s", quote (arglist[i])); + last_val = vallist + valsize * i; + } + else + { + fprintf (stderr, ", %s", quote (arglist[i])); + } + putc ('\n', stderr); +} + +/* Never failing versions of the previous functions. + + CONTEXT is the context for which argmatch is called (e.g., + "--version-control", or "$VERSION_CONTROL" etc.). Upon failure, + calls the (supposed never to return) function EXIT_FN. */ + +ptrdiff_t +__xargmatch_internal (const char *context, + const char *arg, const char *const *arglist, + const char *vallist, size_t valsize, + argmatch_exit_fn exit_fn) +{ + ptrdiff_t res = argmatch (arg, arglist, vallist, valsize); + if (res >= 0) + /* Success. */ + return res; + + /* We failed. Explain why. */ + argmatch_invalid (context, arg, res); + argmatch_valid (arglist, vallist, valsize); + (*exit_fn) (); + + return -1; /* To please the compilers. */ +} + +/* Look for VALUE in VALLIST, an array of objects of size VALSIZE and + return the first corresponding argument in ARGLIST */ +const char * +argmatch_to_argument (const char *value, + const char *const *arglist, + const char *vallist, size_t valsize) +{ + size_t i; + + for (i = 0; arglist[i]; i++) + if (!memcmp (value, vallist + valsize * i, valsize)) + return arglist[i]; + return NULL; +} + +#ifdef TEST +/* + * Based on "getversion.c" by David MacKenzie + */ +char *program_name; + +/* When to make backup files. */ +enum backup_type +{ + /* Never make backups. */ + no_backups, + + /* Make simple backups of every file. */ + simple_backups, + + /* Make numbered backups of files that already have numbered backups, + and simple backups of the others. */ + numbered_existing_backups, + + /* Make numbered backups of every file. */ + numbered_backups +}; + +/* Two tables describing arguments (keys) and their corresponding + values */ +static const char *const backup_args[] = +{ + "no", "none", "off", + "simple", "never", + "existing", "nil", + "numbered", "t", + 0 +}; + +static const enum backup_type backup_vals[] = +{ + no_backups, no_backups, no_backups, + simple_backups, simple_backups, + numbered_existing_backups, numbered_existing_backups, + numbered_backups, numbered_backups +}; + +int +main (int argc, const char *const *argv) +{ + const char *cp; + enum backup_type backup_type = no_backups; + + program_name = (char *) argv[0]; + + if (argc > 2) + { + fprintf (stderr, "Usage: %s [VERSION_CONTROL]\n", program_name); + exit (1); + } + + if ((cp = getenv ("VERSION_CONTROL"))) + backup_type = XARGMATCH ("$VERSION_CONTROL", cp, + backup_args, backup_vals); + + if (argc == 2) + backup_type = XARGMATCH (program_name, argv[1], + backup_args, backup_vals); + + printf ("The version control is '%s'\n", + ARGMATCH_TO_ARGUMENT (backup_type, backup_args, backup_vals)); + + return 0; +} +#endif diff --git a/gettext-tools/gnulib-lib/argmatch.h b/gettext-tools/gnulib-lib/argmatch.h new file mode 100644 index 0000000..8296aad --- /dev/null +++ b/gettext-tools/gnulib-lib/argmatch.h @@ -0,0 +1,111 @@ +/* argmatch.h -- definitions and prototypes for argmatch.c + + Copyright (C) 1990, 1998-1999, 2001-2002, 2004-2005, 2009-2014 Free Software + Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Written by David MacKenzie + Modified by Akim Demaille */ + +#ifndef ARGMATCH_H_ +# define ARGMATCH_H_ 1 + +# include + +# include "verify.h" + +#ifdef __cplusplus +extern "C" { +#endif + +# define ARRAY_CARDINALITY(Array) (sizeof (Array) / sizeof *(Array)) + +/* Assert there are as many real arguments as there are values + (argument list ends with a NULL guard). */ + +# define ARGMATCH_VERIFY(Arglist, Vallist) \ + verify (ARRAY_CARDINALITY (Arglist) == ARRAY_CARDINALITY (Vallist) + 1) + +/* Return the index of the element of ARGLIST (NULL terminated) that + matches with ARG. If VALLIST is not NULL, then use it to resolve + false ambiguities (i.e., different matches of ARG but corresponding + to the same values in VALLIST). */ + +ptrdiff_t argmatch (char const *arg, char const *const *arglist, + char const *vallist, size_t valsize) _GL_ATTRIBUTE_PURE; + +# define ARGMATCH(Arg, Arglist, Vallist) \ + argmatch (Arg, Arglist, (char const *) (Vallist), sizeof *(Vallist)) + +/* xargmatch calls this function when it fails. This function should not + return. By default, this is a function that calls ARGMATCH_DIE which + in turn defaults to 'exit (exit_failure)'. */ +typedef void (*argmatch_exit_fn) (void); +extern DLL_VARIABLE argmatch_exit_fn argmatch_die; + +/* Report on stderr why argmatch failed. Report correct values. */ + +void argmatch_invalid (char const *context, char const *value, + ptrdiff_t problem); + +/* Left for compatibility with the old name invalid_arg */ + +# define invalid_arg(Context, Value, Problem) \ + argmatch_invalid (Context, Value, Problem) + + + +/* Report on stderr the list of possible arguments. */ + +void argmatch_valid (char const *const *arglist, + char const *vallist, size_t valsize); + +# define ARGMATCH_VALID(Arglist, Vallist) \ + argmatch_valid (Arglist, (char const *) (Vallist), sizeof *(Vallist)) + + + +/* Same as argmatch, but upon failure, report an explanation of the + failure, and exit using the function EXIT_FN. */ + +ptrdiff_t __xargmatch_internal (char const *context, + char const *arg, char const *const *arglist, + char const *vallist, size_t valsize, + argmatch_exit_fn exit_fn); + +/* Programmer friendly interface to __xargmatch_internal. */ + +# define XARGMATCH(Context, Arg, Arglist, Vallist) \ + ((Vallist) [__xargmatch_internal (Context, Arg, Arglist, \ + (char const *) (Vallist), \ + sizeof *(Vallist), \ + argmatch_die)]) + +/* Convert a value into a corresponding argument. */ + +char const *argmatch_to_argument (char const *value, + char const *const *arglist, + char const *vallist, size_t valsize) + _GL_ATTRIBUTE_PURE; + +# define ARGMATCH_TO_ARGUMENT(Value, Arglist, Vallist) \ + argmatch_to_argument (Value, Arglist, \ + (char const *) (Vallist), sizeof *(Vallist)) + +#ifdef __cplusplus +} +#endif + +#endif /* ARGMATCH_H_ */ diff --git a/gettext-tools/gnulib-lib/asnprintf.c b/gettext-tools/gnulib-lib/asnprintf.c new file mode 100644 index 0000000..0c62197 --- /dev/null +++ b/gettext-tools/gnulib-lib/asnprintf.c @@ -0,0 +1,34 @@ +/* Formatted output to strings. + Copyright (C) 1999, 2002, 2006, 2009-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, see . */ + +#include + +/* Specification. */ +#include "vasnprintf.h" + +#include + +char * +asnprintf (char *resultbuf, size_t *lengthp, const char *format, ...) +{ + va_list args; + char *result; + + va_start (args, format); + result = vasnprintf (resultbuf, lengthp, format, args); + va_end (args); + return result; +} diff --git a/gettext-tools/gnulib-lib/asprintf.c b/gettext-tools/gnulib-lib/asprintf.c new file mode 100644 index 0000000..9a69ac4 --- /dev/null +++ b/gettext-tools/gnulib-lib/asprintf.c @@ -0,0 +1,39 @@ +/* Formatted output to strings. + Copyright (C) 1999, 2002, 2006-2007, 2009-2014 Free Software Foundation, + Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, see . */ + +#include + +/* Specification. */ +#ifdef IN_LIBASPRINTF +# include "vasprintf.h" +#else +# include +#endif + +#include + +int +asprintf (char **resultp, const char *format, ...) +{ + va_list args; + int result; + + va_start (args, format); + result = vasprintf (resultp, format, args); + va_end (args); + return result; +} diff --git a/gettext-tools/gnulib-lib/atexit.c b/gettext-tools/gnulib-lib/atexit.c new file mode 100644 index 0000000..5ef33e5 --- /dev/null +++ b/gettext-tools/gnulib-lib/atexit.c @@ -0,0 +1,13 @@ +/* Wrapper to implement ANSI C's atexit using SunOS's on_exit. */ +/* This function is in the public domain. --Mike Stump. */ + +#include + +int +atexit (void (*f) (void)) +{ + /* If the system doesn't provide a definition for atexit, use on_exit + if the system provides that. */ + on_exit (f, 0); + return 0; +} diff --git a/gettext-tools/gnulib-lib/backupfile.c b/gettext-tools/gnulib-lib/backupfile.c new file mode 100644 index 0000000..9d75b02 --- /dev/null +++ b/gettext-tools/gnulib-lib/backupfile.c @@ -0,0 +1,235 @@ +/* backupfile.c -- make Emacs style backup file names + Copyright (C) 1990-1999, 2000-2003, 2005-2006, 2012 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Written by David MacKenzie . + Some algorithms adapted from GNU Emacs. */ + +#include + +#include "argmatch.h" +#include "backupfile.h" + +#include +#include +#if HAVE_STRING_H +# include +#else +# include +#endif + +#if HAVE_DIRENT_H +# include +#endif + +#include + +#include "basename.h" + +#if HAVE_DIRENT_H +# define HAVE_DIR 1 +#else +# define HAVE_DIR 0 +#endif + +#include + +/* Upper bound on the string length of an integer converted to string. + 302 / 1000 is ceil (log10 (2.0)). Subtract 1 for the sign bit; + add 1 for integer division truncation; add 1 more for a minus sign. */ +#define INT_STRLEN_BOUND(t) ((sizeof (t) * CHAR_BIT - 1) * 302 / 1000 + 2) + +/* ISDIGIT differs from isdigit, as follows: + - Its arg may be any int or unsigned int; it need not be an unsigned char. + - It's guaranteed to evaluate its argument exactly once. + - It's typically faster. + Posix 1003.2-1992 section 2.5.2.1 page 50 lines 1556-1558 says that + only '0' through '9' are digits. Prefer ISDIGIT to isdigit unless + it's important to use the locale's definition of 'digit' even when the + host does not conform to Posix. */ +#define ISDIGIT(c) ((unsigned) (c) - '0' <= 9) + +#if D_INO_IN_DIRENT +# define REAL_DIR_ENTRY(dp) ((dp)->d_ino != 0) +#else +# define REAL_DIR_ENTRY(dp) 1 +#endif + +/* The extension added to file names to produce a simple (as opposed + to numbered) backup file name. */ +const char *simple_backup_suffix = "~"; + +#if HAVE_DIR +static int max_backup_version (const char *, const char *); +static int version_number (const char *, const char *, size_t); +#endif + +/* Return the name of the new backup file for file FILE, + allocated with malloc. Return 0 if out of memory. + FILE must not end with a '/' unless it is the root directory. + Do not call this function if backup_type == none. */ + +char * +find_backup_file_name (const char *file, enum backup_type backup_type) +{ + size_t backup_suffix_size_max; + size_t file_len = strlen (file); + size_t numbered_suffix_size_max = INT_STRLEN_BOUND (int) + 4; + char *s; + const char *suffix = simple_backup_suffix; + + /* Allow room for simple or '.~N~' backups. */ + backup_suffix_size_max = strlen (simple_backup_suffix) + 1; + if (HAVE_DIR && backup_suffix_size_max < numbered_suffix_size_max) + backup_suffix_size_max = numbered_suffix_size_max; + + s = (char *) malloc (file_len + backup_suffix_size_max + + numbered_suffix_size_max); + if (s) + { + strcpy (s, file); + +#if HAVE_DIR + if (backup_type != simple) + { + int highest_backup; + size_t dir_len = basename (s) - s; + + strcpy (s + dir_len, "."); + highest_backup = max_backup_version (file + dir_len, s); + if (! (backup_type == numbered_existing && highest_backup == 0)) + { + char *numbered_suffix = s + (file_len + backup_suffix_size_max); + sprintf (numbered_suffix, ".~%d~", highest_backup + 1); + suffix = numbered_suffix; + } + strcpy (s, file); + } +#endif /* HAVE_DIR */ + + addext (s, suffix, '~'); + } + return s; +} + +#if HAVE_DIR + +/* Return the number of the highest-numbered backup file for file + FILE in directory DIR. If there are no numbered backups + of FILE in DIR, or an error occurs reading DIR, return 0. + */ + +static int +max_backup_version (const char *file, const char *dir) +{ + DIR *dirp; + struct dirent *dp; + int highest_version; + int this_version; + size_t file_name_length; + + dirp = opendir (dir); + if (!dirp) + return 0; + + highest_version = 0; + file_name_length = strlen (file); + + while ((dp = readdir (dirp)) != 0) + { + if (!REAL_DIR_ENTRY (dp) || strlen (dp->d_name) < file_name_length + 4) + continue; + + this_version = version_number (file, dp->d_name, file_name_length); + if (this_version > highest_version) + highest_version = this_version; + } + if (closedir (dirp)) + return 0; + return highest_version; +} + +/* If BACKUP is a numbered backup of BASE, return its version number; + otherwise return 0. BASE_LENGTH is the length of BASE. + */ + +static int +version_number (const char *base, const char *backup, size_t base_length) +{ + int version; + const char *p; + + version = 0; + if (strncmp (base, backup, base_length) == 0 + && backup[base_length] == '.' + && backup[base_length + 1] == '~') + { + for (p = &backup[base_length + 2]; ISDIGIT (*p); ++p) + version = version * 10 + *p - '0'; + if (p[0] != '~' || p[1]) + version = 0; + } + return version; +} +#endif /* HAVE_DIR */ + +static const char * const backup_args[] = +{ + /* In a series of synonyms, present the most meaning full first, so + that argmatch_valid be more readable. */ + "none", "off", + "simple", "never", + "existing", "nil", + "numbered", "t", + 0 +}; + +static const enum backup_type backup_types[] = +{ + none, none, + simple, simple, + numbered_existing, numbered_existing, + numbered, numbered +}; + +/* Return the type of backup specified by VERSION. + If VERSION is NULL or the empty string, return numbered_existing. + If VERSION is invalid or ambiguous, fail with a diagnostic appropriate + for the specified CONTEXT. Unambiguous abbreviations are accepted. */ + +enum backup_type +get_version (const char *context, const char *version) +{ + if (version == 0 || *version == 0) + return numbered_existing; + else + return XARGMATCH (context, version, backup_args, backup_types); +} + + +/* Return the type of backup specified by VERSION. + If VERSION is NULL, use the value of the envvar VERSION_CONTROL. + If the specified string is invalid or ambiguous, fail with a diagnostic + appropriate for the specified CONTEXT. + Unambiguous abbreviations are accepted. */ + +enum backup_type +xget_version (const char *context, const char *version) +{ + if (version && *version) + return get_version (context, version); + else + return get_version ("$VERSION_CONTROL", getenv ("VERSION_CONTROL")); +} diff --git a/gettext-tools/gnulib-lib/backupfile.h b/gettext-tools/gnulib-lib/backupfile.h new file mode 100644 index 0000000..e2c8743 --- /dev/null +++ b/gettext-tools/gnulib-lib/backupfile.h @@ -0,0 +1,61 @@ +/* backupfile.h -- declarations for making Emacs style backup file names + Copyright (C) 1990-1992, 1997-1999, 2001-2003 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef BACKUPFILE_H_ +# define BACKUPFILE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + + +/* When to make backup files. */ +enum backup_type +{ + /* Never make backups. */ + none, + + /* Make simple backups of every file. */ + simple, + + /* Make numbered backups of files that already have numbered backups, + and simple backups of the others. */ + numbered_existing, + + /* Make numbered backups of every file. */ + numbered +}; + +# define VALID_BACKUP_TYPE(Type) \ + ((Type) == none \ + || (Type) == simple \ + || (Type) == numbered_existing \ + || (Type) == numbered) + +extern DLL_VARIABLE char const *simple_backup_suffix; + +extern char *find_backup_file_name (char const *file, + enum backup_type backup_type); +extern enum backup_type get_version (char const *context, char const *arg); +extern enum backup_type xget_version (char const *context, char const *arg); +extern void addext (char *filename, char const *ext, char e); + + +#ifdef __cplusplus +} +#endif + +#endif /* ! BACKUPFILE_H_ */ diff --git a/gettext-tools/gnulib-lib/basename.c b/gettext-tools/gnulib-lib/basename.c new file mode 100644 index 0000000..5874420 --- /dev/null +++ b/gettext-tools/gnulib-lib/basename.c @@ -0,0 +1,84 @@ +/* Return the name-within-directory of a file name. + Copyright (C) 1996-1999, 2000-2002, 2004, 2006, 2010, 2012 Free Software Foundation, Inc. + + NOTE: The canonical source of this file is maintained with the GNU C Library. + Bugs can be reported to bug-glibc@gnu.org. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 3 of the License, or any + later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include "basename.h" + +#if !(__GLIBC__ >= 2 || defined __UCLIBC__) + +#include +#include + +#if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__ + /* Win32, Cygwin, OS/2, DOS */ +# define HAS_DEVICE(P) \ + ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) \ + && (P)[1] == ':') +# define FILE_SYSTEM_PREFIX_LEN(P) (HAS_DEVICE (P) ? 2 : 0) +# define ISSLASH(C) ((C) == '/' || (C) == '\\') +#endif + +#ifndef FILE_SYSTEM_PREFIX_LEN +# define FILE_SYSTEM_PREFIX_LEN(Filename) 0 +#endif + +#ifndef ISSLASH +# define ISSLASH(C) ((C) == '/') +#endif + +#ifndef _LIBC +/* We cannot generally use the name 'basename' since XPG defines an unusable + variant of the function but we cannot use it. */ +# undef basename +# define basename gnu_basename +#endif + +/* In general, we can't use the builtin 'basename' function if available, + since it has different meanings in different environments. + In some environments the builtin 'basename' modifies its argument. + If NAME is all slashes, be sure to return '/'. */ + +char * +basename (char const *name) +{ + char const *base = name += FILE_SYSTEM_PREFIX_LEN (name); + int all_slashes = 1; + char const *p; + + for (p = name; *p; p++) + { + if (ISSLASH (*p)) + base = p + 1; + else + all_slashes = 0; + } + + /* If NAME is all slashes, arrange to return '/'. */ + if (*base == '\0' && ISSLASH (*name) && all_slashes) + --base; + + /* Make sure the last byte is not a slash. */ + assert (all_slashes || !ISSLASH (*(p - 1))); + + return (char *) base; +} + +#endif diff --git a/gettext-tools/gnulib-lib/basename.h b/gettext-tools/gnulib-lib/basename.h new file mode 100644 index 0000000..908cc3e --- /dev/null +++ b/gettext-tools/gnulib-lib/basename.h @@ -0,0 +1,43 @@ +/* Pathname hacking. + Copyright (C) 2001-2003, 2010 Free Software Foundation, Inc. + Written by Bruno Haible , 2001. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _BASENAME_H +#define _BASENAME_H + +/* This is where basename() is declared. */ +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +#if !(__GLIBC__ >= 2 || defined __UCLIBC__) +/* When not using the GNU libc we use the basename implementation we + provide here. */ +extern char *gnu_basename (const char *); +#define basename(Arg) gnu_basename (Arg) +#endif + + +#ifdef __cplusplus +} +#endif + + +#endif /* _BASENAME_H */ diff --git a/gettext-tools/gnulib-lib/binary-io.c b/gettext-tools/gnulib-lib/binary-io.c new file mode 100644 index 0000000..8bbdb44 --- /dev/null +++ b/gettext-tools/gnulib-lib/binary-io.c @@ -0,0 +1,3 @@ +#include +#define BINARY_IO_INLINE _GL_EXTERN_INLINE +#include "binary-io.h" diff --git a/gettext-tools/gnulib-lib/binary-io.h b/gettext-tools/gnulib-lib/binary-io.h new file mode 100644 index 0000000..7928f8c --- /dev/null +++ b/gettext-tools/gnulib-lib/binary-io.h @@ -0,0 +1,75 @@ +/* Binary mode I/O. + Copyright (C) 2001, 2003, 2005, 2008-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _BINARY_H +#define _BINARY_H + +/* For systems that distinguish between text and binary I/O. + O_BINARY is guaranteed by the gnulib . */ +#include + +/* The MSVC7 doesn't like to be included after '#define fileno ...', + so we include it here first. */ +#include + +#ifndef _GL_INLINE_HEADER_BEGIN + #error "Please include config.h first." +#endif +_GL_INLINE_HEADER_BEGIN +#ifndef BINARY_IO_INLINE +# define BINARY_IO_INLINE _GL_INLINE +#endif + +/* set_binary_mode (fd, mode) + sets the binary/text I/O mode of file descriptor fd to the given mode + (must be O_BINARY or O_TEXT) and returns the previous mode. */ +#if O_BINARY +# if defined __EMX__ || defined __DJGPP__ || defined __CYGWIN__ +# include /* declares setmode() */ +# define set_binary_mode setmode +# else +# define set_binary_mode _setmode +# undef fileno +# define fileno _fileno +# endif +#else + /* On reasonable systems, binary I/O is the only choice. */ + /* Use a function rather than a macro, to avoid gcc warnings + "warning: statement with no effect". */ +BINARY_IO_INLINE int +set_binary_mode (int fd, int mode) +{ + (void) fd; + (void) mode; + return O_BINARY; +} +#endif + +/* SET_BINARY (fd); + changes the file descriptor fd to perform binary I/O. */ +#ifdef __DJGPP__ +# include /* declares isatty() */ + /* Avoid putting stdin/stdout in binary mode if it is connected to + the console, because that would make it impossible for the user + to interrupt the program through Ctrl-C or Ctrl-Break. */ +# define SET_BINARY(fd) ((void) (!isatty (fd) ? (set_binary_mode (fd, O_BINARY), 0) : 0)) +#else +# define SET_BINARY(fd) ((void) set_binary_mode (fd, O_BINARY)) +#endif + +_GL_INLINE_HEADER_END + +#endif /* _BINARY_H */ diff --git a/gettext-tools/gnulib-lib/byteswap.in.h b/gettext-tools/gnulib-lib/byteswap.in.h new file mode 100644 index 0000000..5d1592a --- /dev/null +++ b/gettext-tools/gnulib-lib/byteswap.in.h @@ -0,0 +1,44 @@ +/* byteswap.h - Byte swapping + Copyright (C) 2005, 2007, 2009-2014 Free Software Foundation, Inc. + Written by Oskar Liljeblad , 2005. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _GL_BYTESWAP_H +#define _GL_BYTESWAP_H + +/* Given an unsigned 16-bit argument X, return the value corresponding to + X with reversed byte order. */ +#define bswap_16(x) ((((x) & 0x00FF) << 8) | \ + (((x) & 0xFF00) >> 8)) + +/* Given an unsigned 32-bit argument X, return the value corresponding to + X with reversed byte order. */ +#define bswap_32(x) ((((x) & 0x000000FF) << 24) | \ + (((x) & 0x0000FF00) << 8) | \ + (((x) & 0x00FF0000) >> 8) | \ + (((x) & 0xFF000000) >> 24)) + +/* Given an unsigned 64-bit argument X, return the value corresponding to + X with reversed byte order. */ +#define bswap_64(x) ((((x) & 0x00000000000000FFULL) << 56) | \ + (((x) & 0x000000000000FF00ULL) << 40) | \ + (((x) & 0x0000000000FF0000ULL) << 24) | \ + (((x) & 0x00000000FF000000ULL) << 8) | \ + (((x) & 0x000000FF00000000ULL) >> 8) | \ + (((x) & 0x0000FF0000000000ULL) >> 24) | \ + (((x) & 0x00FF000000000000ULL) >> 40) | \ + (((x) & 0xFF00000000000000ULL) >> 56)) + +#endif /* _GL_BYTESWAP_H */ diff --git a/gettext-tools/gnulib-lib/c-ctype.c b/gettext-tools/gnulib-lib/c-ctype.c new file mode 100644 index 0000000..48c6478 --- /dev/null +++ b/gettext-tools/gnulib-lib/c-ctype.c @@ -0,0 +1,395 @@ +/* Character handling in C locale. + + Copyright 2000-2003, 2006, 2009-2014 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, see . */ + +#include + +/* Specification. */ +#define NO_C_CTYPE_MACROS +#include "c-ctype.h" + +/* The function isascii is not locale dependent. Its use in EBCDIC is + questionable. */ +bool +c_isascii (int c) +{ + return (c >= 0x00 && c <= 0x7f); +} + +bool +c_isalnum (int c) +{ +#if C_CTYPE_CONSECUTIVE_DIGITS \ + && C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE +#if C_CTYPE_ASCII + return ((c >= '0' && c <= '9') + || ((c & ~0x20) >= 'A' && (c & ~0x20) <= 'Z')); +#else + return ((c >= '0' && c <= '9') + || (c >= 'A' && c <= 'Z') + || (c >= 'a' && c <= 'z')); +#endif +#else + switch (c) + { + case '0': case '1': case '2': case '3': case '4': case '5': + case '6': case '7': case '8': case '9': + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': + case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': + case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': + case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': + case 'Y': case 'Z': + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': + case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': + case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': + case 's': case 't': case 'u': case 'v': case 'w': case 'x': + case 'y': case 'z': + return 1; + default: + return 0; + } +#endif +} + +bool +c_isalpha (int c) +{ +#if C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE +#if C_CTYPE_ASCII + return ((c & ~0x20) >= 'A' && (c & ~0x20) <= 'Z'); +#else + return ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')); +#endif +#else + switch (c) + { + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': + case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': + case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': + case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': + case 'Y': case 'Z': + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': + case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': + case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': + case 's': case 't': case 'u': case 'v': case 'w': case 'x': + case 'y': case 'z': + return 1; + default: + return 0; + } +#endif +} + +bool +c_isblank (int c) +{ + return (c == ' ' || c == '\t'); +} + +bool +c_iscntrl (int c) +{ +#if C_CTYPE_ASCII + return ((c & ~0x1f) == 0 || c == 0x7f); +#else + switch (c) + { + case ' ': case '!': case '"': case '#': case '$': case '%': + case '&': case '\'': case '(': case ')': case '*': case '+': + case ',': case '-': case '.': case '/': + case '0': case '1': case '2': case '3': case '4': case '5': + case '6': case '7': case '8': case '9': + case ':': case ';': case '<': case '=': case '>': case '?': + case '@': + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': + case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': + case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': + case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': + case 'Y': case 'Z': + case '[': case '\\': case ']': case '^': case '_': case '`': + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': + case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': + case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': + case 's': case 't': case 'u': case 'v': case 'w': case 'x': + case 'y': case 'z': + case '{': case '|': case '}': case '~': + return 0; + default: + return 1; + } +#endif +} + +bool +c_isdigit (int c) +{ +#if C_CTYPE_CONSECUTIVE_DIGITS + return (c >= '0' && c <= '9'); +#else + switch (c) + { + case '0': case '1': case '2': case '3': case '4': case '5': + case '6': case '7': case '8': case '9': + return 1; + default: + return 0; + } +#endif +} + +bool +c_islower (int c) +{ +#if C_CTYPE_CONSECUTIVE_LOWERCASE + return (c >= 'a' && c <= 'z'); +#else + switch (c) + { + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': + case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': + case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': + case 's': case 't': case 'u': case 'v': case 'w': case 'x': + case 'y': case 'z': + return 1; + default: + return 0; + } +#endif +} + +bool +c_isgraph (int c) +{ +#if C_CTYPE_ASCII + return (c >= '!' && c <= '~'); +#else + switch (c) + { + case '!': case '"': case '#': case '$': case '%': case '&': + case '\'': case '(': case ')': case '*': case '+': case ',': + case '-': case '.': case '/': + case '0': case '1': case '2': case '3': case '4': case '5': + case '6': case '7': case '8': case '9': + case ':': case ';': case '<': case '=': case '>': case '?': + case '@': + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': + case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': + case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': + case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': + case 'Y': case 'Z': + case '[': case '\\': case ']': case '^': case '_': case '`': + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': + case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': + case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': + case 's': case 't': case 'u': case 'v': case 'w': case 'x': + case 'y': case 'z': + case '{': case '|': case '}': case '~': + return 1; + default: + return 0; + } +#endif +} + +bool +c_isprint (int c) +{ +#if C_CTYPE_ASCII + return (c >= ' ' && c <= '~'); +#else + switch (c) + { + case ' ': case '!': case '"': case '#': case '$': case '%': + case '&': case '\'': case '(': case ')': case '*': case '+': + case ',': case '-': case '.': case '/': + case '0': case '1': case '2': case '3': case '4': case '5': + case '6': case '7': case '8': case '9': + case ':': case ';': case '<': case '=': case '>': case '?': + case '@': + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': + case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': + case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': + case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': + case 'Y': case 'Z': + case '[': case '\\': case ']': case '^': case '_': case '`': + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': + case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': + case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': + case 's': case 't': case 'u': case 'v': case 'w': case 'x': + case 'y': case 'z': + case '{': case '|': case '}': case '~': + return 1; + default: + return 0; + } +#endif +} + +bool +c_ispunct (int c) +{ +#if C_CTYPE_ASCII + return ((c >= '!' && c <= '~') + && !((c >= '0' && c <= '9') + || ((c & ~0x20) >= 'A' && (c & ~0x20) <= 'Z'))); +#else + switch (c) + { + case '!': case '"': case '#': case '$': case '%': case '&': + case '\'': case '(': case ')': case '*': case '+': case ',': + case '-': case '.': case '/': + case ':': case ';': case '<': case '=': case '>': case '?': + case '@': + case '[': case '\\': case ']': case '^': case '_': case '`': + case '{': case '|': case '}': case '~': + return 1; + default: + return 0; + } +#endif +} + +bool +c_isspace (int c) +{ + return (c == ' ' || c == '\t' + || c == '\n' || c == '\v' || c == '\f' || c == '\r'); +} + +bool +c_isupper (int c) +{ +#if C_CTYPE_CONSECUTIVE_UPPERCASE + return (c >= 'A' && c <= 'Z'); +#else + switch (c) + { + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': + case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': + case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': + case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': + case 'Y': case 'Z': + return 1; + default: + return 0; + } +#endif +} + +bool +c_isxdigit (int c) +{ +#if C_CTYPE_CONSECUTIVE_DIGITS \ + && C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE +#if C_CTYPE_ASCII + return ((c >= '0' && c <= '9') + || ((c & ~0x20) >= 'A' && (c & ~0x20) <= 'F')); +#else + return ((c >= '0' && c <= '9') + || (c >= 'A' && c <= 'F') + || (c >= 'a' && c <= 'f')); +#endif +#else + switch (c) + { + case '0': case '1': case '2': case '3': case '4': case '5': + case '6': case '7': case '8': case '9': + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': + return 1; + default: + return 0; + } +#endif +} + +int +c_tolower (int c) +{ +#if C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE + return (c >= 'A' && c <= 'Z' ? c - 'A' + 'a' : c); +#else + switch (c) + { + case 'A': return 'a'; + case 'B': return 'b'; + case 'C': return 'c'; + case 'D': return 'd'; + case 'E': return 'e'; + case 'F': return 'f'; + case 'G': return 'g'; + case 'H': return 'h'; + case 'I': return 'i'; + case 'J': return 'j'; + case 'K': return 'k'; + case 'L': return 'l'; + case 'M': return 'm'; + case 'N': return 'n'; + case 'O': return 'o'; + case 'P': return 'p'; + case 'Q': return 'q'; + case 'R': return 'r'; + case 'S': return 's'; + case 'T': return 't'; + case 'U': return 'u'; + case 'V': return 'v'; + case 'W': return 'w'; + case 'X': return 'x'; + case 'Y': return 'y'; + case 'Z': return 'z'; + default: return c; + } +#endif +} + +int +c_toupper (int c) +{ +#if C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE + return (c >= 'a' && c <= 'z' ? c - 'a' + 'A' : c); +#else + switch (c) + { + case 'a': return 'A'; + case 'b': return 'B'; + case 'c': return 'C'; + case 'd': return 'D'; + case 'e': return 'E'; + case 'f': return 'F'; + case 'g': return 'G'; + case 'h': return 'H'; + case 'i': return 'I'; + case 'j': return 'J'; + case 'k': return 'K'; + case 'l': return 'L'; + case 'm': return 'M'; + case 'n': return 'N'; + case 'o': return 'O'; + case 'p': return 'P'; + case 'q': return 'Q'; + case 'r': return 'R'; + case 's': return 'S'; + case 't': return 'T'; + case 'u': return 'U'; + case 'v': return 'V'; + case 'w': return 'W'; + case 'x': return 'X'; + case 'y': return 'Y'; + case 'z': return 'Z'; + default: return c; + } +#endif +} diff --git a/gettext-tools/gnulib-lib/c-ctype.h b/gettext-tools/gnulib-lib/c-ctype.h new file mode 100644 index 0000000..b465277 --- /dev/null +++ b/gettext-tools/gnulib-lib/c-ctype.h @@ -0,0 +1,295 @@ +/* Character handling in C locale. + + These functions work like the corresponding functions in , + except that they have the C (POSIX) locale hardwired, whereas the + functions' behaviour depends on the current locale set via + setlocale. + + Copyright (C) 2000-2003, 2006, 2008-2014 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, see . */ + +#ifndef C_CTYPE_H +#define C_CTYPE_H + +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* The functions defined in this file assume the "C" locale and a character + set without diacritics (ASCII-US or EBCDIC-US or something like that). + Even if the "C" locale on a particular system is an extension of the ASCII + character set (like on BeOS, where it is UTF-8, or on AmigaOS, where it + is ISO-8859-1), the functions in this file recognize only the ASCII + characters. */ + + +/* Check whether the ASCII optimizations apply. */ + +/* ANSI C89 (and ISO C99 5.2.1.3 too) already guarantees that + '0', '1', ..., '9' have consecutive integer values. */ +#define C_CTYPE_CONSECUTIVE_DIGITS 1 + +#if ('A' <= 'Z') \ + && ('A' + 1 == 'B') && ('B' + 1 == 'C') && ('C' + 1 == 'D') \ + && ('D' + 1 == 'E') && ('E' + 1 == 'F') && ('F' + 1 == 'G') \ + && ('G' + 1 == 'H') && ('H' + 1 == 'I') && ('I' + 1 == 'J') \ + && ('J' + 1 == 'K') && ('K' + 1 == 'L') && ('L' + 1 == 'M') \ + && ('M' + 1 == 'N') && ('N' + 1 == 'O') && ('O' + 1 == 'P') \ + && ('P' + 1 == 'Q') && ('Q' + 1 == 'R') && ('R' + 1 == 'S') \ + && ('S' + 1 == 'T') && ('T' + 1 == 'U') && ('U' + 1 == 'V') \ + && ('V' + 1 == 'W') && ('W' + 1 == 'X') && ('X' + 1 == 'Y') \ + && ('Y' + 1 == 'Z') +#define C_CTYPE_CONSECUTIVE_UPPERCASE 1 +#endif + +#if ('a' <= 'z') \ + && ('a' + 1 == 'b') && ('b' + 1 == 'c') && ('c' + 1 == 'd') \ + && ('d' + 1 == 'e') && ('e' + 1 == 'f') && ('f' + 1 == 'g') \ + && ('g' + 1 == 'h') && ('h' + 1 == 'i') && ('i' + 1 == 'j') \ + && ('j' + 1 == 'k') && ('k' + 1 == 'l') && ('l' + 1 == 'm') \ + && ('m' + 1 == 'n') && ('n' + 1 == 'o') && ('o' + 1 == 'p') \ + && ('p' + 1 == 'q') && ('q' + 1 == 'r') && ('r' + 1 == 's') \ + && ('s' + 1 == 't') && ('t' + 1 == 'u') && ('u' + 1 == 'v') \ + && ('v' + 1 == 'w') && ('w' + 1 == 'x') && ('x' + 1 == 'y') \ + && ('y' + 1 == 'z') +#define C_CTYPE_CONSECUTIVE_LOWERCASE 1 +#endif + +#if (' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ + && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \ + && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \ + && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \ + && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \ + && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \ + && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \ + && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \ + && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \ + && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \ + && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \ + && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \ + && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \ + && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \ + && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \ + && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \ + && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \ + && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \ + && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \ + && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \ + && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \ + && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \ + && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126) +/* The character set is ASCII or one of its variants or extensions, not EBCDIC. + Testing the value of '\n' and '\r' is not relevant. */ +#define C_CTYPE_ASCII 1 +#endif + + +/* Function declarations. */ + +/* Unlike the functions in , which require an argument in the range + of the 'unsigned char' type, the functions here operate on values that are + in the 'unsigned char' range or in the 'char' range. In other words, + when you have a 'char' value, you need to cast it before using it as + argument to a function: + + const char *s = ...; + if (isalpha ((unsigned char) *s)) ... + + but you don't need to cast it for the functions defined in this file: + + const char *s = ...; + if (c_isalpha (*s)) ... + */ + +extern bool c_isascii (int c) _GL_ATTRIBUTE_CONST; /* not locale dependent */ + +extern bool c_isalnum (int c) _GL_ATTRIBUTE_CONST; +extern bool c_isalpha (int c) _GL_ATTRIBUTE_CONST; +extern bool c_isblank (int c) _GL_ATTRIBUTE_CONST; +extern bool c_iscntrl (int c) _GL_ATTRIBUTE_CONST; +extern bool c_isdigit (int c) _GL_ATTRIBUTE_CONST; +extern bool c_islower (int c) _GL_ATTRIBUTE_CONST; +extern bool c_isgraph (int c) _GL_ATTRIBUTE_CONST; +extern bool c_isprint (int c) _GL_ATTRIBUTE_CONST; +extern bool c_ispunct (int c) _GL_ATTRIBUTE_CONST; +extern bool c_isspace (int c) _GL_ATTRIBUTE_CONST; +extern bool c_isupper (int c) _GL_ATTRIBUTE_CONST; +extern bool c_isxdigit (int c) _GL_ATTRIBUTE_CONST; + +extern int c_tolower (int c) _GL_ATTRIBUTE_CONST; +extern int c_toupper (int c) _GL_ATTRIBUTE_CONST; + + +#if (defined __GNUC__ && !defined __STRICT_ANSI__ && defined __OPTIMIZE__ \ + && !defined __OPTIMIZE_SIZE__ && !defined NO_C_CTYPE_MACROS) + +/* ASCII optimizations. */ + +#undef c_isascii +#define c_isascii(c) \ + ({ int __c = (c); \ + (__c >= 0x00 && __c <= 0x7f); \ + }) + +#if C_CTYPE_CONSECUTIVE_DIGITS \ + && C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE +#if C_CTYPE_ASCII +#undef c_isalnum +#define c_isalnum(c) \ + ({ int __c = (c); \ + ((__c >= '0' && __c <= '9') \ + || ((__c & ~0x20) >= 'A' && (__c & ~0x20) <= 'Z')); \ + }) +#else +#undef c_isalnum +#define c_isalnum(c) \ + ({ int __c = (c); \ + ((__c >= '0' && __c <= '9') \ + || (__c >= 'A' && __c <= 'Z') \ + || (__c >= 'a' && __c <= 'z')); \ + }) +#endif +#endif + +#if C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE +#if C_CTYPE_ASCII +#undef c_isalpha +#define c_isalpha(c) \ + ({ int __c = (c); \ + ((__c & ~0x20) >= 'A' && (__c & ~0x20) <= 'Z'); \ + }) +#else +#undef c_isalpha +#define c_isalpha(c) \ + ({ int __c = (c); \ + ((__c >= 'A' && __c <= 'Z') || (__c >= 'a' && __c <= 'z')); \ + }) +#endif +#endif + +#undef c_isblank +#define c_isblank(c) \ + ({ int __c = (c); \ + (__c == ' ' || __c == '\t'); \ + }) + +#if C_CTYPE_ASCII +#undef c_iscntrl +#define c_iscntrl(c) \ + ({ int __c = (c); \ + ((__c & ~0x1f) == 0 || __c == 0x7f); \ + }) +#endif + +#if C_CTYPE_CONSECUTIVE_DIGITS +#undef c_isdigit +#define c_isdigit(c) \ + ({ int __c = (c); \ + (__c >= '0' && __c <= '9'); \ + }) +#endif + +#if C_CTYPE_CONSECUTIVE_LOWERCASE +#undef c_islower +#define c_islower(c) \ + ({ int __c = (c); \ + (__c >= 'a' && __c <= 'z'); \ + }) +#endif + +#if C_CTYPE_ASCII +#undef c_isgraph +#define c_isgraph(c) \ + ({ int __c = (c); \ + (__c >= '!' && __c <= '~'); \ + }) +#endif + +#if C_CTYPE_ASCII +#undef c_isprint +#define c_isprint(c) \ + ({ int __c = (c); \ + (__c >= ' ' && __c <= '~'); \ + }) +#endif + +#if C_CTYPE_ASCII +#undef c_ispunct +#define c_ispunct(c) \ + ({ int _c = (c); \ + (c_isgraph (_c) && ! c_isalnum (_c)); \ + }) +#endif + +#undef c_isspace +#define c_isspace(c) \ + ({ int __c = (c); \ + (__c == ' ' || __c == '\t' \ + || __c == '\n' || __c == '\v' || __c == '\f' || __c == '\r'); \ + }) + +#if C_CTYPE_CONSECUTIVE_UPPERCASE +#undef c_isupper +#define c_isupper(c) \ + ({ int __c = (c); \ + (__c >= 'A' && __c <= 'Z'); \ + }) +#endif + +#if C_CTYPE_CONSECUTIVE_DIGITS \ + && C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE +#if C_CTYPE_ASCII +#undef c_isxdigit +#define c_isxdigit(c) \ + ({ int __c = (c); \ + ((__c >= '0' && __c <= '9') \ + || ((__c & ~0x20) >= 'A' && (__c & ~0x20) <= 'F')); \ + }) +#else +#undef c_isxdigit +#define c_isxdigit(c) \ + ({ int __c = (c); \ + ((__c >= '0' && __c <= '9') \ + || (__c >= 'A' && __c <= 'F') \ + || (__c >= 'a' && __c <= 'f')); \ + }) +#endif +#endif + +#if C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE +#undef c_tolower +#define c_tolower(c) \ + ({ int __c = (c); \ + (__c >= 'A' && __c <= 'Z' ? __c - 'A' + 'a' : __c); \ + }) +#undef c_toupper +#define c_toupper(c) \ + ({ int __c = (c); \ + (__c >= 'a' && __c <= 'z' ? __c - 'a' + 'A' : __c); \ + }) +#endif + +#endif /* optimizing for speed */ + + +#ifdef __cplusplus +} +#endif + +#endif /* C_CTYPE_H */ diff --git a/gettext-tools/gnulib-lib/c-strcase.h b/gettext-tools/gnulib-lib/c-strcase.h new file mode 100644 index 0000000..8e66044 --- /dev/null +++ b/gettext-tools/gnulib-lib/c-strcase.h @@ -0,0 +1,56 @@ +/* Case-insensitive string comparison functions in C locale. + Copyright (C) 1995-1996, 2001, 2003, 2005, 2009-2014 Free Software + Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . */ + +#ifndef C_STRCASE_H +#define C_STRCASE_H + +#include + + +/* The functions defined in this file assume the "C" locale and a character + set without diacritics (ASCII-US or EBCDIC-US or something like that). + Even if the "C" locale on a particular system is an extension of the ASCII + character set (like on BeOS, where it is UTF-8, or on AmigaOS, where it + is ISO-8859-1), the functions in this file recognize only the ASCII + characters. More precisely, one of the string arguments must be an ASCII + string; the other one can also contain non-ASCII characters (but then + the comparison result will be nonzero). */ + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Compare strings S1 and S2, ignoring case, returning less than, equal to or + greater than zero if S1 is lexicographically less than, equal to or greater + than S2. */ +extern int c_strcasecmp (const char *s1, const char *s2) _GL_ATTRIBUTE_PURE; + +/* Compare no more than N characters of strings S1 and S2, ignoring case, + returning less than, equal to or greater than zero if S1 is + lexicographically less than, equal to or greater than S2. */ +extern int c_strncasecmp (const char *s1, const char *s2, size_t n) + _GL_ATTRIBUTE_PURE; + + +#ifdef __cplusplus +} +#endif + + +#endif /* C_STRCASE_H */ diff --git a/gettext-tools/gnulib-lib/c-strcasecmp.c b/gettext-tools/gnulib-lib/c-strcasecmp.c new file mode 100644 index 0000000..b9b26a4 --- /dev/null +++ b/gettext-tools/gnulib-lib/c-strcasecmp.c @@ -0,0 +1,56 @@ +/* c-strcasecmp.c -- case insensitive string comparator in C locale + Copyright (C) 1998-1999, 2005-2006, 2009-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . */ + +#include + +/* Specification. */ +#include "c-strcase.h" + +#include + +#include "c-ctype.h" + +int +c_strcasecmp (const char *s1, const char *s2) +{ + register const unsigned char *p1 = (const unsigned char *) s1; + register const unsigned char *p2 = (const unsigned char *) s2; + unsigned char c1, c2; + + if (p1 == p2) + return 0; + + do + { + c1 = c_tolower (*p1); + c2 = c_tolower (*p2); + + if (c1 == '\0') + break; + + ++p1; + ++p2; + } + while (c1 == c2); + + if (UCHAR_MAX <= INT_MAX) + return c1 - c2; + else + /* On machines where 'char' and 'int' are types of the same size, the + difference of two 'unsigned char' values - including the sign bit - + doesn't fit in an 'int'. */ + return (c1 > c2 ? 1 : c1 < c2 ? -1 : 0); +} diff --git a/gettext-tools/gnulib-lib/c-strcaseeq.h b/gettext-tools/gnulib-lib/c-strcaseeq.h new file mode 100644 index 0000000..5139a30 --- /dev/null +++ b/gettext-tools/gnulib-lib/c-strcaseeq.h @@ -0,0 +1,184 @@ +/* Optimized case-insensitive string comparison in C locale. + Copyright (C) 2001-2002, 2007, 2009-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Written by Bruno Haible . */ + +#include "c-strcase.h" +#include "c-ctype.h" + +/* STRCASEEQ allows to optimize string comparison with a small literal string. + STRCASEEQ (s, "UTF-8", 'U','T','F','-','8',0,0,0,0) + is semantically equivalent to + c_strcasecmp (s, "UTF-8") == 0 + just faster. */ + +/* Help GCC to generate good code for string comparisons with + immediate strings. */ +#if defined (__GNUC__) && defined (__OPTIMIZE__) + +/* Case insensitive comparison of ASCII characters. */ +# if C_CTYPE_ASCII +# define CASEEQ(other,upper) \ + (c_isupper (upper) ? ((other) & ~0x20) == (upper) : (other) == (upper)) +# elif C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE +# define CASEEQ(other,upper) \ + (c_isupper (upper) ? (other) == (upper) || (other) == (upper) - 'A' + 'a' : (other) == (upper)) +# else +# define CASEEQ(other,upper) \ + (c_toupper (other) == (upper)) +# endif + +static inline int +strcaseeq9 (const char *s1, const char *s2) +{ + return c_strcasecmp (s1 + 9, s2 + 9) == 0; +} + +static inline int +strcaseeq8 (const char *s1, const char *s2, char s28) +{ + if (CASEEQ (s1[8], s28)) + { + if (s28 == 0) + return 1; + else + return strcaseeq9 (s1, s2); + } + else + return 0; +} + +static inline int +strcaseeq7 (const char *s1, const char *s2, char s27, char s28) +{ + if (CASEEQ (s1[7], s27)) + { + if (s27 == 0) + return 1; + else + return strcaseeq8 (s1, s2, s28); + } + else + return 0; +} + +static inline int +strcaseeq6 (const char *s1, const char *s2, char s26, char s27, char s28) +{ + if (CASEEQ (s1[6], s26)) + { + if (s26 == 0) + return 1; + else + return strcaseeq7 (s1, s2, s27, s28); + } + else + return 0; +} + +static inline int +strcaseeq5 (const char *s1, const char *s2, char s25, char s26, char s27, char s28) +{ + if (CASEEQ (s1[5], s25)) + { + if (s25 == 0) + return 1; + else + return strcaseeq6 (s1, s2, s26, s27, s28); + } + else + return 0; +} + +static inline int +strcaseeq4 (const char *s1, const char *s2, char s24, char s25, char s26, char s27, char s28) +{ + if (CASEEQ (s1[4], s24)) + { + if (s24 == 0) + return 1; + else + return strcaseeq5 (s1, s2, s25, s26, s27, s28); + } + else + return 0; +} + +static inline int +strcaseeq3 (const char *s1, const char *s2, char s23, char s24, char s25, char s26, char s27, char s28) +{ + if (CASEEQ (s1[3], s23)) + { + if (s23 == 0) + return 1; + else + return strcaseeq4 (s1, s2, s24, s25, s26, s27, s28); + } + else + return 0; +} + +static inline int +strcaseeq2 (const char *s1, const char *s2, char s22, char s23, char s24, char s25, char s26, char s27, char s28) +{ + if (CASEEQ (s1[2], s22)) + { + if (s22 == 0) + return 1; + else + return strcaseeq3 (s1, s2, s23, s24, s25, s26, s27, s28); + } + else + return 0; +} + +static inline int +strcaseeq1 (const char *s1, const char *s2, char s21, char s22, char s23, char s24, char s25, char s26, char s27, char s28) +{ + if (CASEEQ (s1[1], s21)) + { + if (s21 == 0) + return 1; + else + return strcaseeq2 (s1, s2, s22, s23, s24, s25, s26, s27, s28); + } + else + return 0; +} + +static inline int +strcaseeq0 (const char *s1, const char *s2, char s20, char s21, char s22, char s23, char s24, char s25, char s26, char s27, char s28) +{ + if (CASEEQ (s1[0], s20)) + { + if (s20 == 0) + return 1; + else + return strcaseeq1 (s1, s2, s21, s22, s23, s24, s25, s26, s27, s28); + } + else + return 0; +} + +#define STRCASEEQ(s1,s2,s20,s21,s22,s23,s24,s25,s26,s27,s28) \ + strcaseeq0 (s1, s2, s20, s21, s22, s23, s24, s25, s26, s27, s28) + +#else + +#define STRCASEEQ(s1,s2,s20,s21,s22,s23,s24,s25,s26,s27,s28) \ + (c_strcasecmp (s1, s2) == 0) + +#endif diff --git a/gettext-tools/gnulib-lib/c-strcasestr.c b/gettext-tools/gnulib-lib/c-strcasestr.c new file mode 100644 index 0000000..12e5503 --- /dev/null +++ b/gettext-tools/gnulib-lib/c-strcasestr.c @@ -0,0 +1,77 @@ +/* c-strcasestr.c -- case insensitive substring search in C locale + Copyright (C) 2005-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2005. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include "c-strcasestr.h" + +#include +#include + +#include "c-ctype.h" +#include "c-strcase.h" + +/* Two-Way algorithm. */ +#define RETURN_TYPE char * +#define AVAILABLE(h, h_l, j, n_l) \ + (!memchr ((h) + (h_l), '\0', (j) + (n_l) - (h_l)) \ + && ((h_l) = (j) + (n_l))) +#define CANON_ELEMENT c_tolower +#define CMP_FUNC(p1, p2, l) \ + c_strncasecmp ((const char *) (p1), (const char *) (p2), l) +#include "str-two-way.h" + +/* Find the first occurrence of NEEDLE in HAYSTACK, using case-insensitive + comparison from the C locale, regardless of the current locale. */ +char * +c_strcasestr (const char *haystack_start, const char *needle_start) +{ + const char *haystack = haystack_start; + const char *needle = needle_start; + size_t needle_len; /* Length of NEEDLE. */ + size_t haystack_len; /* Known minimum length of HAYSTACK. */ + bool ok = true; /* True if NEEDLE is prefix of HAYSTACK. */ + + /* Determine length of NEEDLE, and in the process, make sure + HAYSTACK is at least as long (no point processing all of a long + NEEDLE if HAYSTACK is too short). */ + while (*haystack && *needle) + ok &= (c_tolower ((unsigned char) *haystack++) + == c_tolower ((unsigned char) *needle++)); + if (*needle) + return NULL; + if (ok) + return (char *) haystack_start; + needle_len = needle - needle_start; + haystack = haystack_start + 1; + haystack_len = needle_len - 1; + + /* Perform the search. Abstract memory is considered to be an array + of 'unsigned char' values, not an array of 'char' values. See + ISO C 99 section 6.2.6.1. */ + if (needle_len < LONG_NEEDLE_THRESHOLD) + return two_way_short_needle ((const unsigned char *) haystack, + haystack_len, + (const unsigned char *) needle_start, + needle_len); + return two_way_long_needle ((const unsigned char *) haystack, haystack_len, + (const unsigned char *) needle_start, + needle_len); +} + +#undef LONG_NEEDLE_THRESHOLD diff --git a/gettext-tools/gnulib-lib/c-strcasestr.h b/gettext-tools/gnulib-lib/c-strcasestr.h new file mode 100644 index 0000000..3b6ceb9 --- /dev/null +++ b/gettext-tools/gnulib-lib/c-strcasestr.h @@ -0,0 +1,36 @@ +/* Case-insensitive searching in a string in C locale. + Copyright (C) 2005, 2009-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef C_STRCASESTR_H +#define C_STRCASESTR_H + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Find the first occurrence of NEEDLE in HAYSTACK, using case-insensitive + comparison. */ +extern char *c_strcasestr (const char *haystack, const char *needle); + + +#ifdef __cplusplus +} +#endif + + +#endif /* C_STRCASESTR_H */ diff --git a/gettext-tools/gnulib-lib/c-strncasecmp.c b/gettext-tools/gnulib-lib/c-strncasecmp.c new file mode 100644 index 0000000..972eb80 --- /dev/null +++ b/gettext-tools/gnulib-lib/c-strncasecmp.c @@ -0,0 +1,56 @@ +/* c-strncasecmp.c -- case insensitive string comparator in C locale + Copyright (C) 1998-1999, 2005-2006, 2009-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . */ + +#include + +/* Specification. */ +#include "c-strcase.h" + +#include + +#include "c-ctype.h" + +int +c_strncasecmp (const char *s1, const char *s2, size_t n) +{ + register const unsigned char *p1 = (const unsigned char *) s1; + register const unsigned char *p2 = (const unsigned char *) s2; + unsigned char c1, c2; + + if (p1 == p2 || n == 0) + return 0; + + do + { + c1 = c_tolower (*p1); + c2 = c_tolower (*p2); + + if (--n == 0 || c1 == '\0') + break; + + ++p1; + ++p2; + } + while (c1 == c2); + + if (UCHAR_MAX <= INT_MAX) + return c1 - c2; + else + /* On machines where 'char' and 'int' are types of the same size, the + difference of two 'unsigned char' values - including the sign bit - + doesn't fit in an 'int'. */ + return (c1 > c2 ? 1 : c1 < c2 ? -1 : 0); +} diff --git a/gettext-tools/gnulib-lib/c-strstr.c b/gettext-tools/gnulib-lib/c-strstr.c new file mode 100644 index 0000000..c13cde2 --- /dev/null +++ b/gettext-tools/gnulib-lib/c-strstr.c @@ -0,0 +1,32 @@ +/* c-strstr.c -- substring search in C locale + Copyright (C) 2005-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2005, 2007. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include "c-strstr.h" + +#include + +/* Find the first occurrence of NEEDLE in HAYSTACK. */ +char * +c_strstr (const char *haystack, const char *needle) +{ + /* POSIX says that strstr() interprets the strings as byte sequences, not + as character sequences in the current locale. */ + return strstr (haystack, needle); +} diff --git a/gettext-tools/gnulib-lib/c-strstr.h b/gettext-tools/gnulib-lib/c-strstr.h new file mode 100644 index 0000000..bc7378b --- /dev/null +++ b/gettext-tools/gnulib-lib/c-strstr.h @@ -0,0 +1,44 @@ +/* Searching in a string. + Copyright (C) 2001-2003, 2006, 2009-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + + +/* The functions defined in this file assume a nearly ASCII compatible + character set. */ + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Find the first occurrence of NEEDLE in HAYSTACK. + This function is safe to be called, even in a multibyte locale, if NEEDLE + 1. consists solely of printable ASCII characters excluding '\\' and '~' + [this restriction is needed because of Shift_JIS and JOHAB] + or of the control ASCII characters '\a' '\b' '\f' '\n' '\r' '\t' '\v' + [this restriction is needed because of VISCII], and + 2. has at least length 2 + [this restriction is needed because of BIG5, BIG5-HKSCS, GBK, GB18030, + Shift_JIS, JOHAB], and + 3. does not consist entirely of decimal digits, or has at least length 4 + [this restriction is needed because of GB18030]. + This function is also safe to be called, even in a multibyte locale, if + HAYSTACK and NEEDLE are known to both consist solely of printable ASCII + characters excluding '\\' and '~'. */ +extern char *c_strstr (const char *haystack, const char *needle); + +#ifdef __cplusplus +} +#endif diff --git a/gettext-tools/gnulib-lib/canonicalize-lgpl.c b/gettext-tools/gnulib-lib/canonicalize-lgpl.c new file mode 100644 index 0000000..902380f --- /dev/null +++ b/gettext-tools/gnulib-lib/canonicalize-lgpl.c @@ -0,0 +1,411 @@ +/* Return the canonical absolute name of a given file. + Copyright (C) 1996-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _LIBC +/* Don't use __attribute__ __nonnull__ in this compilation unit. Otherwise gcc + optimizes away the name == NULL test below. */ +# define _GL_ARG_NONNULL(params) + +# define _GL_USE_STDLIB_ALLOC 1 +# include +#endif + +#if !HAVE_CANONICALIZE_FILE_NAME || !FUNC_REALPATH_WORKS || defined _LIBC + +/* Specification. */ +#include + +#include +#include +#include +#include +#if HAVE_SYS_PARAM_H || defined _LIBC +# include +#endif +#include +#include +#include + +#ifdef _LIBC +# include +#else +# define SHLIB_COMPAT(lib, introduced, obsoleted) 0 +# define versioned_symbol(lib, local, symbol, version) extern int dummy +# define compat_symbol(lib, local, symbol, version) +# define weak_alias(local, symbol) +# define __canonicalize_file_name canonicalize_file_name +# define __realpath realpath +# include "pathmax.h" +# include "malloca.h" +# include "dosname.h" +# if HAVE_GETCWD +# if IN_RELOCWRAPPER + /* When building the relocatable program wrapper, use the system's getcwd + function, not the gnulib override, otherwise we would get a link error. + */ +# undef getcwd +# endif +# ifdef VMS + /* We want the directory in Unix syntax, not in VMS syntax. */ +# define __getcwd(buf, max) getcwd (buf, max, 0) +# else +# define __getcwd getcwd +# endif +# else +# define __getcwd(buf, max) getwd (buf) +# endif +# define __readlink readlink +# define __set_errno(e) errno = (e) +# ifndef MAXSYMLINKS +# ifdef SYMLOOP_MAX +# define MAXSYMLINKS SYMLOOP_MAX +# else +# define MAXSYMLINKS 20 +# endif +# endif +#endif + +#ifndef DOUBLE_SLASH_IS_DISTINCT_ROOT +# define DOUBLE_SLASH_IS_DISTINCT_ROOT 0 +#endif + +#if !FUNC_REALPATH_WORKS || defined _LIBC +/* Return the canonical absolute name of file NAME. A canonical name + does not contain any ".", ".." components nor any repeated path + separators ('/') or symlinks. All path components must exist. If + RESOLVED is null, the result is malloc'd; otherwise, if the + canonical name is PATH_MAX chars or more, returns null with 'errno' + set to ENAMETOOLONG; if the name fits in fewer than PATH_MAX chars, + returns the name in RESOLVED. If the name cannot be resolved and + RESOLVED is non-NULL, it contains the path of the first component + that cannot be resolved. If the path can be resolved, RESOLVED + holds the same value as the value returned. */ + +char * +__realpath (const char *name, char *resolved) +{ + char *rpath, *dest, *extra_buf = NULL; + const char *start, *end, *rpath_limit; + long int path_max; + int num_links = 0; + size_t prefix_len; + + if (name == NULL) + { + /* As per Single Unix Specification V2 we must return an error if + either parameter is a null pointer. We extend this to allow + the RESOLVED parameter to be NULL in case the we are expected to + allocate the room for the return value. */ + __set_errno (EINVAL); + return NULL; + } + + if (name[0] == '\0') + { + /* As per Single Unix Specification V2 we must return an error if + the name argument points to an empty string. */ + __set_errno (ENOENT); + return NULL; + } + +#ifdef PATH_MAX + path_max = PATH_MAX; +#else + path_max = pathconf (name, _PC_PATH_MAX); + if (path_max <= 0) + path_max = 8192; +#endif + + if (resolved == NULL) + { + rpath = malloc (path_max); + if (rpath == NULL) + { + /* It's easier to set errno to ENOMEM than to rely on the + 'malloc-posix' gnulib module. */ + errno = ENOMEM; + return NULL; + } + } + else + rpath = resolved; + rpath_limit = rpath + path_max; + + /* This is always zero for Posix hosts, but can be 2 for MS-Windows + and MS-DOS X:/foo/bar file names. */ + prefix_len = FILE_SYSTEM_PREFIX_LEN (name); + + if (!IS_ABSOLUTE_FILE_NAME (name)) + { + if (!__getcwd (rpath, path_max)) + { + rpath[0] = '\0'; + goto error; + } + dest = strchr (rpath, '\0'); + start = name; + prefix_len = FILE_SYSTEM_PREFIX_LEN (rpath); + } + else + { + dest = rpath; + if (prefix_len) + { + memcpy (rpath, name, prefix_len); + dest += prefix_len; + } + *dest++ = '/'; + if (DOUBLE_SLASH_IS_DISTINCT_ROOT) + { + if (ISSLASH (name[1]) && !ISSLASH (name[2]) && !prefix_len) + *dest++ = '/'; + *dest = '\0'; + } + start = name + prefix_len; + } + + for (end = start; *start; start = end) + { +#ifdef _LIBC + struct stat64 st; +#else + struct stat st; +#endif + int n; + + /* Skip sequence of multiple path-separators. */ + while (ISSLASH (*start)) + ++start; + + /* Find end of path component. */ + for (end = start; *end && !ISSLASH (*end); ++end) + /* Nothing. */; + + if (end - start == 0) + break; + else if (end - start == 1 && start[0] == '.') + /* nothing */; + else if (end - start == 2 && start[0] == '.' && start[1] == '.') + { + /* Back up to previous component, ignore if at root already. */ + if (dest > rpath + prefix_len + 1) + for (--dest; dest > rpath && !ISSLASH (dest[-1]); --dest) + continue; + if (DOUBLE_SLASH_IS_DISTINCT_ROOT + && dest == rpath + 1 && !prefix_len + && ISSLASH (*dest) && !ISSLASH (dest[1])) + dest++; + } + else + { + size_t new_size; + + if (!ISSLASH (dest[-1])) + *dest++ = '/'; + + if (dest + (end - start) >= rpath_limit) + { + ptrdiff_t dest_offset = dest - rpath; + char *new_rpath; + + if (resolved) + { + __set_errno (ENAMETOOLONG); + if (dest > rpath + prefix_len + 1) + dest--; + *dest = '\0'; + goto error; + } + new_size = rpath_limit - rpath; + if (end - start + 1 > path_max) + new_size += end - start + 1; + else + new_size += path_max; + new_rpath = (char *) realloc (rpath, new_size); + if (new_rpath == NULL) + { + /* It's easier to set errno to ENOMEM than to rely on the + 'realloc-posix' gnulib module. */ + errno = ENOMEM; + goto error; + } + rpath = new_rpath; + rpath_limit = rpath + new_size; + + dest = rpath + dest_offset; + } + +#ifdef _LIBC + dest = __mempcpy (dest, start, end - start); +#else + memcpy (dest, start, end - start); + dest += end - start; +#endif + *dest = '\0'; + +#ifdef _LIBC + if (__lxstat64 (_STAT_VER, rpath, &st) < 0) +#else + if (lstat (rpath, &st) < 0) +#endif + goto error; + + if (S_ISLNK (st.st_mode)) + { + char *buf; + size_t len; + + if (++num_links > MAXSYMLINKS) + { + __set_errno (ELOOP); + goto error; + } + + buf = malloca (path_max); + if (!buf) + { + errno = ENOMEM; + goto error; + } + + n = __readlink (rpath, buf, path_max - 1); + if (n < 0) + { + int saved_errno = errno; + freea (buf); + errno = saved_errno; + goto error; + } + buf[n] = '\0'; + + if (!extra_buf) + { + extra_buf = malloca (path_max); + if (!extra_buf) + { + freea (buf); + errno = ENOMEM; + goto error; + } + } + + len = strlen (end); + if ((long int) (n + len) >= path_max) + { + freea (buf); + __set_errno (ENAMETOOLONG); + goto error; + } + + /* Careful here, end may be a pointer into extra_buf... */ + memmove (&extra_buf[n], end, len + 1); + name = end = memcpy (extra_buf, buf, n); + + if (IS_ABSOLUTE_FILE_NAME (buf)) + { + size_t pfxlen = FILE_SYSTEM_PREFIX_LEN (buf); + + if (pfxlen) + memcpy (rpath, buf, pfxlen); + dest = rpath + pfxlen; + *dest++ = '/'; /* It's an absolute symlink */ + if (DOUBLE_SLASH_IS_DISTINCT_ROOT) + { + if (ISSLASH (buf[1]) && !ISSLASH (buf[2]) && !pfxlen) + *dest++ = '/'; + *dest = '\0'; + } + /* Install the new prefix to be in effect hereafter. */ + prefix_len = pfxlen; + } + else + { + /* Back up to previous component, ignore if at root + already: */ + if (dest > rpath + prefix_len + 1) + for (--dest; dest > rpath && !ISSLASH (dest[-1]); --dest) + continue; + if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rpath + 1 + && ISSLASH (*dest) && !ISSLASH (dest[1]) && !prefix_len) + dest++; + } + } + else if (!S_ISDIR (st.st_mode) && *end != '\0') + { + __set_errno (ENOTDIR); + goto error; + } + } + } + if (dest > rpath + prefix_len + 1 && ISSLASH (dest[-1])) + --dest; + if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rpath + 1 && !prefix_len + && ISSLASH (*dest) && !ISSLASH (dest[1])) + dest++; + *dest = '\0'; + + if (extra_buf) + freea (extra_buf); + + return rpath; + +error: + { + int saved_errno = errno; + if (extra_buf) + freea (extra_buf); + if (resolved == NULL) + free (rpath); + errno = saved_errno; + } + return NULL; +} +versioned_symbol (libc, __realpath, realpath, GLIBC_2_3); +#endif /* !FUNC_REALPATH_WORKS || defined _LIBC */ + + +#if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_3) +char * +attribute_compat_text_section +__old_realpath (const char *name, char *resolved) +{ + if (resolved == NULL) + { + __set_errno (EINVAL); + return NULL; + } + + return __realpath (name, resolved); +} +compat_symbol (libc, __old_realpath, realpath, GLIBC_2_0); +#endif + + +char * +__canonicalize_file_name (const char *name) +{ + return __realpath (name, NULL); +} +weak_alias (__canonicalize_file_name, canonicalize_file_name) + +#else + +/* This declaration is solely to ensure that after preprocessing + this file is never empty. */ +typedef int dummy; + +#endif diff --git a/gettext-tools/gnulib-lib/careadlinkat.c b/gettext-tools/gnulib-lib/careadlinkat.c new file mode 100644 index 0000000..b36fea2 --- /dev/null +++ b/gettext-tools/gnulib-lib/careadlinkat.c @@ -0,0 +1,160 @@ +/* Read symbolic links into a buffer without size limitation, relative to fd. + + Copyright (C) 2001, 2003-2004, 2007, 2009-2014 Free Software Foundation, + Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Written by Paul Eggert, Bruno Haible, and Jim Meyering. */ + +#include + +#include "careadlinkat.h" + +#include +#include +#include +#include + +/* Define this independently so that stdint.h is not a prerequisite. */ +#ifndef SIZE_MAX +# define SIZE_MAX ((size_t) -1) +#endif + +#ifndef SSIZE_MAX +# define SSIZE_MAX ((ssize_t) (SIZE_MAX / 2)) +#endif + +#include "allocator.h" + +/* Assuming the current directory is FD, get the symbolic link value + of FILENAME as a null-terminated string and put it into a buffer. + If FD is AT_FDCWD, FILENAME is interpreted relative to the current + working directory, as in openat. + + If the link is small enough to fit into BUFFER put it there. + BUFFER's size is BUFFER_SIZE, and BUFFER can be null + if BUFFER_SIZE is zero. + + If the link is not small, put it into a dynamically allocated + buffer managed by ALLOC. It is the caller's responsibility to free + the returned value if it is nonnull and is not BUFFER. A null + ALLOC stands for the standard allocator. + + The PREADLINKAT function specifies how to read links. It operates + like POSIX readlinkat() + + but can assume that its first argument is the same as FD. + + If successful, return the buffer address; otherwise return NULL and + set errno. */ + +char * +careadlinkat (int fd, char const *filename, + char *buffer, size_t buffer_size, + struct allocator const *alloc, + ssize_t (*preadlinkat) (int, char const *, char *, size_t)) +{ + char *buf; + size_t buf_size; + size_t buf_size_max = + SSIZE_MAX < SIZE_MAX ? (size_t) SSIZE_MAX + 1 : SIZE_MAX; + char stack_buf[1024]; + + if (! alloc) + alloc = &stdlib_allocator; + + if (! buffer_size) + { + /* Allocate the initial buffer on the stack. This way, in the + common case of a symlink of small size, we get away with a + single small malloc() instead of a big malloc() followed by a + shrinking realloc(). */ + buffer = stack_buf; + buffer_size = sizeof stack_buf; + } + + buf = buffer; + buf_size = buffer_size; + + do + { + /* Attempt to read the link into the current buffer. */ + ssize_t link_length = preadlinkat (fd, filename, buf, buf_size); + size_t link_size; + if (link_length < 0) + { + /* On AIX 5L v5.3 and HP-UX 11i v2 04/09, readlink returns -1 + with errno == ERANGE if the buffer is too small. */ + int readlinkat_errno = errno; + if (readlinkat_errno != ERANGE) + { + if (buf != buffer) + { + alloc->free (buf); + errno = readlinkat_errno; + } + return NULL; + } + } + + link_size = link_length; + + if (link_size < buf_size) + { + buf[link_size++] = '\0'; + + if (buf == stack_buf) + { + char *b = (char *) alloc->allocate (link_size); + buf_size = link_size; + if (! b) + break; + memcpy (b, buf, link_size); + buf = b; + } + else if (link_size < buf_size && buf != buffer && alloc->reallocate) + { + /* Shrink BUF before returning it. */ + char *b = (char *) alloc->reallocate (buf, link_size); + if (b) + buf = b; + } + + return buf; + } + + if (buf != buffer) + alloc->free (buf); + + if (buf_size <= buf_size_max / 2) + buf_size *= 2; + else if (buf_size < buf_size_max) + buf_size = buf_size_max; + else if (buf_size_max < SIZE_MAX) + { + errno = ENAMETOOLONG; + return NULL; + } + else + break; + buf = (char *) alloc->allocate (buf_size); + } + while (buf); + + if (alloc->die) + alloc->die (buf_size); + errno = ENOMEM; + return NULL; +} diff --git a/gettext-tools/gnulib-lib/careadlinkat.h b/gettext-tools/gnulib-lib/careadlinkat.h new file mode 100644 index 0000000..704f815 --- /dev/null +++ b/gettext-tools/gnulib-lib/careadlinkat.h @@ -0,0 +1,67 @@ +/* Read symbolic links into a buffer without size limitation, relative to fd. + + Copyright (C) 2011-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Written by Paul Eggert, Bruno Haible, and Jim Meyering. */ + +#ifndef _GL_CAREADLINKAT_H +#define _GL_CAREADLINKAT_H + +#include +#include + +struct allocator; + +/* Assuming the current directory is FD, get the symbolic link value + of FILENAME as a null-terminated string and put it into a buffer. + If FD is AT_FDCWD, FILENAME is interpreted relative to the current + working directory, as in openat. + + If the link is small enough to fit into BUFFER put it there. + BUFFER's size is BUFFER_SIZE, and BUFFER can be null + if BUFFER_SIZE is zero. + + If the link is not small, put it into a dynamically allocated + buffer managed by ALLOC. It is the caller's responsibility to free + the returned value if it is nonnull and is not BUFFER. + + The PREADLINKAT function specifies how to read links. It operates + like POSIX readlinkat() + + but can assume that its first argument is the same as FD. + + If successful, return the buffer address; otherwise return NULL and + set errno. */ + +char *careadlinkat (int fd, char const *filename, + char *buffer, size_t buffer_size, + struct allocator const *alloc, + ssize_t (*preadlinkat) (int, char const *, + char *, size_t)); + +/* Suitable value for careadlinkat's FD argument. */ +#if HAVE_READLINKAT +/* AT_FDCWD is declared in . */ +#else +/* Define AT_FDCWD independently, so that the careadlinkat module does + not depend on the fcntl-h module. We might as well use the same value + as fcntl-h. */ +# ifndef AT_FDCWD +# define AT_FDCWD (-3041965) +# endif +#endif + +#endif /* _GL_CAREADLINKAT_H */ diff --git a/gettext-tools/gnulib-lib/classpath.c b/gettext-tools/gnulib-lib/classpath.c new file mode 100644 index 0000000..0d18bf5 --- /dev/null +++ b/gettext-tools/gnulib-lib/classpath.c @@ -0,0 +1,122 @@ +/* Java CLASSPATH handling. + Copyright (C) 2001-2003, 2006, 2009-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2001. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include "classpath.h" + +#include +#include +#include + +#include "xsetenv.h" +#include "xalloc.h" + +/* Name of environment variable. */ +#ifndef CLASSPATHVAR +# define CLASSPATHVAR "CLASSPATH" +#endif + +/* Separator in PATH like lists of pathnames. */ +#if ((defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__) || defined __EMX__ || defined __DJGPP__ + /* Native Windows, OS/2, DOS */ +# define PATH_SEPARATOR ';' +#else + /* Unix */ +# define PATH_SEPARATOR ':' +#endif + +/* Return the new CLASSPATH value. The given classpaths are prepended to + the current CLASSPATH value. If use_minimal_classpath, the current + CLASSPATH is ignored. */ +char * +new_classpath (const char * const *classpaths, unsigned int classpaths_count, + bool use_minimal_classpath) +{ + const char *old_classpath; + unsigned int length; + unsigned int i; + char *result; + char *p; + + old_classpath = (use_minimal_classpath ? NULL : getenv (CLASSPATHVAR)); + if (old_classpath == NULL) + old_classpath = ""; + + length = 0; + for (i = 0; i < classpaths_count; i++) + length += strlen (classpaths[i]) + 1; + length += strlen (old_classpath); + if (classpaths_count > 0 && old_classpath[0] == '\0') + length--; + + result = XNMALLOC (length + 1, char); + p = result; + for (i = 0; i < classpaths_count; i++) + { + memcpy (p, classpaths[i], strlen (classpaths[i])); + p += strlen (classpaths[i]); + *p++ = PATH_SEPARATOR; + } + if (old_classpath[0] != '\0') + { + memcpy (p, old_classpath, strlen (old_classpath)); + p += strlen (old_classpath); + } + else + { + if (classpaths_count > 0) + p--; + } + *p = '\0'; + + return result; +} + +/* Set CLASSPATH and returns a safe copy of its old value. */ +char * +set_classpath (const char * const *classpaths, unsigned int classpaths_count, + bool use_minimal_classpath, bool verbose) +{ + const char *old_CLASSPATH = getenv (CLASSPATHVAR); + char *result = (old_CLASSPATH != NULL ? xstrdup (old_CLASSPATH) : NULL); + char *new_CLASSPATH = + new_classpath (classpaths, classpaths_count, use_minimal_classpath); + + if (verbose) + printf (CLASSPATHVAR "=%s ", new_CLASSPATH); + + xsetenv (CLASSPATHVAR, new_CLASSPATH, 1); + + free (new_CLASSPATH); + + return result; +} + +/* Restore CLASSPATH to its previous value. */ +void +reset_classpath (char *old_classpath) +{ + if (old_classpath != NULL) + { + xsetenv (CLASSPATHVAR, old_classpath, 1); + free (old_classpath); + } + else + unsetenv (CLASSPATHVAR); +} diff --git a/gettext-tools/gnulib-lib/classpath.h b/gettext-tools/gnulib-lib/classpath.h new file mode 100644 index 0000000..ae8b0cf --- /dev/null +++ b/gettext-tools/gnulib-lib/classpath.h @@ -0,0 +1,33 @@ +/* Java CLASSPATH handling. + Copyright (C) 2003, 2009-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2003. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Return the new CLASSPATH value. The given classpaths are prepended to + the current CLASSPATH value. If use_minimal_classpath, the current + CLASSPATH is ignored. */ +extern char * new_classpath (const char * const *classpaths, + unsigned int classpaths_count, + bool use_minimal_classpath); + +/* Set CLASSPATH and returns a safe copy of its old value. */ +extern char * set_classpath (const char * const *classpaths, + unsigned int classpaths_count, + bool use_minimal_classpath, bool verbose); + +/* Restore CLASSPATH to its previous value. */ +extern void reset_classpath (char *old_classpath); diff --git a/gettext-tools/gnulib-lib/clean-temp.c b/gettext-tools/gnulib-lib/clean-temp.c new file mode 100644 index 0000000..057700a --- /dev/null +++ b/gettext-tools/gnulib-lib/clean-temp.c @@ -0,0 +1,783 @@ +/* Temporary directories and temporary files with automatic cleanup. + Copyright (C) 2001, 2003, 2006-2007, 2009-2014 Free Software Foundation, + Inc. + Written by Bruno Haible , 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + + +#include + +/* Specification. */ +#include "clean-temp.h" + +#include +#include +#include +#include +#include +#include +#include + +#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ +# define WIN32_LEAN_AND_MEAN /* avoid including junk */ +# include +#endif + +#include "error.h" +#include "fatal-signal.h" +#include "pathmax.h" +#include "tmpdir.h" +#include "xalloc.h" +#include "xmalloca.h" +#include "gl_xlist.h" +#include "gl_linkedhash_list.h" +#include "gettext.h" +#if GNULIB_FWRITEERROR +# include "fwriteerror.h" +#endif +#if GNULIB_CLOSE_STREAM +# include "close-stream.h" +#endif +#if GNULIB_FCNTL_SAFER +# include "fcntl--.h" +#endif +#if GNULIB_FOPEN_SAFER +# include "stdio--.h" +#endif + +#define _(str) gettext (str) + +/* GNU Hurd doesn't have PATH_MAX. Use a fallback. + Temporary directory names are usually not that long. */ +#ifndef PATH_MAX +# define PATH_MAX 1024 +#endif + +#ifndef uintptr_t +# define uintptr_t unsigned long +#endif + + +/* The use of 'volatile' in the types below (and ISO C 99 section 5.1.2.3.(5)) + ensure that while constructing or modifying the data structures, the field + values are written to memory in the order of the C statements. So the + signal handler can rely on these field values to be up to date. */ + + +/* Registry for a single temporary directory. + 'struct temp_dir' from the public header file overlaps with this. */ +struct tempdir +{ + /* The absolute pathname of the directory. */ + char * volatile dirname; + /* Whether errors during explicit cleanup are reported to standard error. */ + bool cleanup_verbose; + /* Absolute pathnames of subdirectories. */ + gl_list_t /* */ volatile subdirs; + /* Absolute pathnames of files. */ + gl_list_t /* */ volatile files; +}; + +/* List of all temporary directories. */ +static struct +{ + struct tempdir * volatile * volatile tempdir_list; + size_t volatile tempdir_count; + size_t tempdir_allocated; +} cleanup_list /* = { NULL, 0, 0 } */; + +/* List of all open file descriptors to temporary files. */ +static gl_list_t /* */ volatile descriptors; + + +/* For the subdirs and for the files, we use a gl_list_t of type LINKEDHASH. + Why? We need a data structure that + + 1) Can contain an arbitrary number of 'char *' values. The strings + are compared via strcmp, not pointer comparison. + 2) Has insertion and deletion operations that are fast: ideally O(1), + or possibly O(log n). This is important for GNU sort, which may + create a large number of temporary files. + 3) Allows iteration through all elements from within a signal handler. + 4) May or may not allow duplicates. It doesn't matter here, since + any file or subdir can only be removed once. + + Criterion 1) would allow any gl_list_t or gl_oset_t implementation. + + Criterion 2) leaves only GL_LINKEDHASH_LIST, GL_TREEHASH_LIST, or + GL_TREE_OSET. + + Criterion 3) puts at disadvantage GL_TREEHASH_LIST and GL_TREE_OSET. + Namely, iteration through the elements of a binary tree requires access + to many ->left, ->right, ->parent pointers. However, the rebalancing + code for insertion and deletion in an AVL or red-black tree is so + complicated that we cannot assume that >left, ->right, ->parent pointers + are in a consistent state throughout these operations. Therefore, to + avoid a crash in the signal handler, all destructive operations to the + lists would have to be protected by a + block_fatal_signals (); + ... + unblock_fatal_signals (); + pair. Which causes extra system calls. + + Criterion 3) would also discourage GL_ARRAY_LIST and GL_CARRAY_LIST, + if they were not already excluded. Namely, these implementations use + xrealloc(), leaving a time window in which in the list->elements pointer + points to already deallocated memory. To avoid a crash in the signal + handler at such a moment, all destructive operations would have to + protected by block/unblock_fatal_signals (), in this case too. + + A list of type GL_LINKEDHASH_LIST without duplicates fulfills all + requirements: + 2) Insertion and deletion are O(1) on average. + 3) The gl_list_iterator, gl_list_iterator_next implementations do + not trigger memory allocations, nor other system calls, and are + therefore safe to be called from a signal handler. + Furthermore, since SIGNAL_SAFE_LIST is defined, the implementation + of the destructive functions ensures that the list structure is + safe to be traversed at any moment, even when interrupted by an + asynchronous signal. + */ + +/* String equality and hash code functions used by the lists. */ + +static bool +string_equals (const void *x1, const void *x2) +{ + const char *s1 = (const char *) x1; + const char *s2 = (const char *) x2; + return strcmp (s1, s2) == 0; +} + +#define SIZE_BITS (sizeof (size_t) * CHAR_BIT) + +/* A hash function for NUL-terminated char* strings using + the method described by Bruno Haible. + See http://www.haible.de/bruno/hashfunc.html. */ +static size_t +string_hash (const void *x) +{ + const char *s = (const char *) x; + size_t h = 0; + + for (; *s; s++) + h = *s + ((h << 9) | (h >> (SIZE_BITS - 9))); + + return h; +} + + +/* The signal handler. It gets called asynchronously. */ +static void +cleanup () +{ + size_t i; + + /* First close all file descriptors to temporary files. */ + { + gl_list_t fds = descriptors; + + if (fds != NULL) + { + gl_list_iterator_t iter; + const void *element; + + iter = gl_list_iterator (fds); + while (gl_list_iterator_next (&iter, &element, NULL)) + { + int fd = (int) (uintptr_t) element; + close (fd); + } + gl_list_iterator_free (&iter); + } + } + + for (i = 0; i < cleanup_list.tempdir_count; i++) + { + struct tempdir *dir = cleanup_list.tempdir_list[i]; + + if (dir != NULL) + { + gl_list_iterator_t iter; + const void *element; + + /* First cleanup the files in the subdirectories. */ + iter = gl_list_iterator (dir->files); + while (gl_list_iterator_next (&iter, &element, NULL)) + { + const char *file = (const char *) element; + unlink (file); + } + gl_list_iterator_free (&iter); + + /* Then cleanup the subdirectories. */ + iter = gl_list_iterator (dir->subdirs); + while (gl_list_iterator_next (&iter, &element, NULL)) + { + const char *subdir = (const char *) element; + rmdir (subdir); + } + gl_list_iterator_free (&iter); + + /* Then cleanup the temporary directory itself. */ + rmdir (dir->dirname); + } + } +} + +/* Create a temporary directory. + PREFIX is used as a prefix for the name of the temporary directory. It + should be short and still give an indication about the program. + PARENTDIR can be used to specify the parent directory; if NULL, a default + parent directory is used (either $TMPDIR or /tmp or similar). + CLEANUP_VERBOSE determines whether errors during explicit cleanup are + reported to standard error. + Return a fresh 'struct temp_dir' on success. Upon error, an error message + is shown and NULL is returned. */ +struct temp_dir * +create_temp_dir (const char *prefix, const char *parentdir, + bool cleanup_verbose) +{ + struct tempdir * volatile *tmpdirp = NULL; + struct tempdir *tmpdir; + size_t i; + char *xtemplate; + char *tmpdirname; + + /* See whether it can take the slot of an earlier temporary directory + already cleaned up. */ + for (i = 0; i < cleanup_list.tempdir_count; i++) + if (cleanup_list.tempdir_list[i] == NULL) + { + tmpdirp = &cleanup_list.tempdir_list[i]; + break; + } + if (tmpdirp == NULL) + { + /* See whether the array needs to be extended. */ + if (cleanup_list.tempdir_count == cleanup_list.tempdir_allocated) + { + /* Note that we cannot use xrealloc(), because then the cleanup() + function could access an already deallocated array. */ + struct tempdir * volatile *old_array = cleanup_list.tempdir_list; + size_t old_allocated = cleanup_list.tempdir_allocated; + size_t new_allocated = 2 * cleanup_list.tempdir_allocated + 1; + struct tempdir * volatile *new_array = + XNMALLOC (new_allocated, struct tempdir * volatile); + + if (old_allocated == 0) + /* First use of this facility. Register the cleanup handler. */ + at_fatal_signal (&cleanup); + else + { + /* Don't use memcpy() here, because memcpy takes non-volatile + arguments and is therefore not guaranteed to complete all + memory stores before the next statement. */ + size_t k; + + for (k = 0; k < old_allocated; k++) + new_array[k] = old_array[k]; + } + + cleanup_list.tempdir_list = new_array; + cleanup_list.tempdir_allocated = new_allocated; + + /* Now we can free the old array. */ + if (old_array != NULL) + free ((struct tempdir **) old_array); + } + + tmpdirp = &cleanup_list.tempdir_list[cleanup_list.tempdir_count]; + /* Initialize *tmpdirp before incrementing tempdir_count, so that + cleanup() will skip this entry before it is fully initialized. */ + *tmpdirp = NULL; + cleanup_list.tempdir_count++; + } + + /* Initialize a 'struct tempdir'. */ + tmpdir = XMALLOC (struct tempdir); + tmpdir->dirname = NULL; + tmpdir->cleanup_verbose = cleanup_verbose; + tmpdir->subdirs = gl_list_create_empty (GL_LINKEDHASH_LIST, + string_equals, string_hash, NULL, + false); + tmpdir->files = gl_list_create_empty (GL_LINKEDHASH_LIST, + string_equals, string_hash, NULL, + false); + + /* Create the temporary directory. */ + xtemplate = (char *) xmalloca (PATH_MAX); + if (path_search (xtemplate, PATH_MAX, parentdir, prefix, parentdir == NULL)) + { + error (0, errno, + _("cannot find a temporary directory, try setting $TMPDIR")); + goto quit; + } + block_fatal_signals (); + tmpdirname = mkdtemp (xtemplate); + if (tmpdirname != NULL) + { + tmpdir->dirname = tmpdirname; + *tmpdirp = tmpdir; + } + unblock_fatal_signals (); + if (tmpdirname == NULL) + { + error (0, errno, + _("cannot create a temporary directory using template \"%s\""), + xtemplate); + goto quit; + } + /* Replace tmpdir->dirname with a copy that has indefinite extent. + We cannot do this inside the block_fatal_signals/unblock_fatal_signals + block because then the cleanup handler would not remove the directory + if xstrdup fails. */ + tmpdir->dirname = xstrdup (tmpdirname); + freea (xtemplate); + return (struct temp_dir *) tmpdir; + + quit: + freea (xtemplate); + return NULL; +} + +/* Register the given ABSOLUTE_FILE_NAME as being a file inside DIR, that + needs to be removed before DIR can be removed. + Should be called before the file ABSOLUTE_FILE_NAME is created. */ +void +register_temp_file (struct temp_dir *dir, + const char *absolute_file_name) +{ + struct tempdir *tmpdir = (struct tempdir *)dir; + + /* Add absolute_file_name to tmpdir->files, without duplicates. */ + if (gl_list_search (tmpdir->files, absolute_file_name) == NULL) + gl_list_add_first (tmpdir->files, xstrdup (absolute_file_name)); +} + +/* Unregister the given ABSOLUTE_FILE_NAME as being a file inside DIR, that + needs to be removed before DIR can be removed. + Should be called when the file ABSOLUTE_FILE_NAME could not be created. */ +void +unregister_temp_file (struct temp_dir *dir, + const char *absolute_file_name) +{ + struct tempdir *tmpdir = (struct tempdir *)dir; + gl_list_t list = tmpdir->files; + gl_list_node_t node; + + node = gl_list_search (list, absolute_file_name); + if (node != NULL) + { + char *old_string = (char *) gl_list_node_value (list, node); + + gl_list_remove_node (list, node); + free (old_string); + } +} + +/* Register the given ABSOLUTE_DIR_NAME as being a subdirectory inside DIR, + that needs to be removed before DIR can be removed. + Should be called before the subdirectory ABSOLUTE_DIR_NAME is created. */ +void +register_temp_subdir (struct temp_dir *dir, + const char *absolute_dir_name) +{ + struct tempdir *tmpdir = (struct tempdir *)dir; + + /* Add absolute_dir_name to tmpdir->subdirs, without duplicates. */ + if (gl_list_search (tmpdir->subdirs, absolute_dir_name) == NULL) + gl_list_add_first (tmpdir->subdirs, xstrdup (absolute_dir_name)); +} + +/* Unregister the given ABSOLUTE_DIR_NAME as being a subdirectory inside DIR, + that needs to be removed before DIR can be removed. + Should be called when the subdirectory ABSOLUTE_DIR_NAME could not be + created. */ +void +unregister_temp_subdir (struct temp_dir *dir, + const char *absolute_dir_name) +{ + struct tempdir *tmpdir = (struct tempdir *)dir; + gl_list_t list = tmpdir->subdirs; + gl_list_node_t node; + + node = gl_list_search (list, absolute_dir_name); + if (node != NULL) + { + char *old_string = (char *) gl_list_node_value (list, node); + + gl_list_remove_node (list, node); + free (old_string); + } +} + +/* Remove a file, with optional error message. + Return 0 upon success, or -1 if there was some problem. */ +static int +do_unlink (struct temp_dir *dir, const char *absolute_file_name) +{ + if (unlink (absolute_file_name) < 0 && dir->cleanup_verbose + && errno != ENOENT) + { + error (0, errno, _("cannot remove temporary file %s"), absolute_file_name); + return -1; + } + return 0; +} + +/* Remove a directory, with optional error message. + Return 0 upon success, or -1 if there was some problem. */ +static int +do_rmdir (struct temp_dir *dir, const char *absolute_dir_name) +{ + if (rmdir (absolute_dir_name) < 0 && dir->cleanup_verbose + && errno != ENOENT) + { + error (0, errno, + _("cannot remove temporary directory %s"), absolute_dir_name); + return -1; + } + return 0; +} + +/* Remove the given ABSOLUTE_FILE_NAME and unregister it. + Return 0 upon success, or -1 if there was some problem. */ +int +cleanup_temp_file (struct temp_dir *dir, + const char *absolute_file_name) +{ + int err; + + err = do_unlink (dir, absolute_file_name); + unregister_temp_file (dir, absolute_file_name); + + return err; +} + +/* Remove the given ABSOLUTE_DIR_NAME and unregister it. + Return 0 upon success, or -1 if there was some problem. */ +int +cleanup_temp_subdir (struct temp_dir *dir, + const char *absolute_dir_name) +{ + int err; + + err = do_rmdir (dir, absolute_dir_name); + unregister_temp_subdir (dir, absolute_dir_name); + + return err; +} + +/* Remove all registered files and subdirectories inside DIR. + Return 0 upon success, or -1 if there was some problem. */ +int +cleanup_temp_dir_contents (struct temp_dir *dir) +{ + struct tempdir *tmpdir = (struct tempdir *)dir; + int err = 0; + gl_list_t list; + gl_list_iterator_t iter; + const void *element; + gl_list_node_t node; + + /* First cleanup the files in the subdirectories. */ + list = tmpdir->files; + iter = gl_list_iterator (list); + while (gl_list_iterator_next (&iter, &element, &node)) + { + char *file = (char *) element; + + err |= do_unlink (dir, file); + gl_list_remove_node (list, node); + /* Now only we can free file. */ + free (file); + } + gl_list_iterator_free (&iter); + + /* Then cleanup the subdirectories. */ + list = tmpdir->subdirs; + iter = gl_list_iterator (list); + while (gl_list_iterator_next (&iter, &element, &node)) + { + char *subdir = (char *) element; + + err |= do_rmdir (dir, subdir); + gl_list_remove_node (list, node); + /* Now only we can free subdir. */ + free (subdir); + } + gl_list_iterator_free (&iter); + + return err; +} + +/* Remove all registered files and subdirectories inside DIR and DIR itself. + DIR cannot be used any more after this call. + Return 0 upon success, or -1 if there was some problem. */ +int +cleanup_temp_dir (struct temp_dir *dir) +{ + struct tempdir *tmpdir = (struct tempdir *)dir; + int err = 0; + size_t i; + + err |= cleanup_temp_dir_contents (dir); + err |= do_rmdir (dir, tmpdir->dirname); + + for (i = 0; i < cleanup_list.tempdir_count; i++) + if (cleanup_list.tempdir_list[i] == tmpdir) + { + /* Remove cleanup_list.tempdir_list[i]. */ + if (i + 1 == cleanup_list.tempdir_count) + { + while (i > 0 && cleanup_list.tempdir_list[i - 1] == NULL) + i--; + cleanup_list.tempdir_count = i; + } + else + cleanup_list.tempdir_list[i] = NULL; + /* Now only we can free the tmpdir->dirname, tmpdir->subdirs, + tmpdir->files, and tmpdir itself. */ + gl_list_free (tmpdir->files); + gl_list_free (tmpdir->subdirs); + free (tmpdir->dirname); + free (tmpdir); + return err; + } + + /* The user passed an invalid DIR argument. */ + abort (); +} + + +#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ + +/* On Windows, opening a file with _O_TEMPORARY has the effect of passing + the FILE_FLAG_DELETE_ON_CLOSE flag to CreateFile(), which has the effect + of deleting the file when it is closed - even when the program crashes. + But (according to the Cygwin sources) it works only on Windows NT or newer. + So we cache the info whether we are running on Windows NT or newer. */ + +static bool +supports_delete_on_close () +{ + static int known; /* 1 = yes, -1 = no, 0 = unknown */ + if (!known) + { + OSVERSIONINFO v; + + /* According to + + this structure must be initialised as follows: */ + v.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); + + if (GetVersionEx (&v)) + known = (v.dwPlatformId == VER_PLATFORM_WIN32_NT ? 1 : -1); + else + known = -1; + } + return (known > 0); +} + +#endif + + +/* Register a file descriptor to be closed. */ +static void +register_fd (int fd) +{ + if (descriptors == NULL) + descriptors = gl_list_create_empty (GL_LINKEDHASH_LIST, NULL, NULL, NULL, + false); + gl_list_add_first (descriptors, (void *) (uintptr_t) fd); +} + +/* Unregister a file descriptor to be closed. */ +static void +unregister_fd (int fd) +{ + gl_list_t fds = descriptors; + gl_list_node_t node; + + if (fds == NULL) + /* descriptors should already contain fd. */ + abort (); + node = gl_list_search (fds, (void *) (uintptr_t) fd); + if (node == NULL) + /* descriptors should already contain fd. */ + abort (); + gl_list_remove_node (fds, node); +} + +/* Open a temporary file in a temporary directory. + Registers the resulting file descriptor to be closed. */ +int +open_temp (const char *file_name, int flags, mode_t mode) +{ + int fd; + int saved_errno; + + block_fatal_signals (); + /* Note: 'open' here is actually open() or open_safer(). */ +#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ + /* Use _O_TEMPORARY when possible, to increase the chances that the + temporary file is removed when the process crashes. */ + if (supports_delete_on_close ()) + fd = open (file_name, flags | _O_TEMPORARY, mode); + else +#endif + fd = open (file_name, flags, mode); + saved_errno = errno; + if (fd >= 0) + register_fd (fd); + unblock_fatal_signals (); + errno = saved_errno; + return fd; +} + +/* Open a temporary file in a temporary directory. + Registers the resulting file descriptor to be closed. */ +FILE * +fopen_temp (const char *file_name, const char *mode) +{ + FILE *fp; + int saved_errno; + + block_fatal_signals (); + /* Note: 'fopen' here is actually fopen() or fopen_safer(). */ +#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ + /* Use _O_TEMPORARY when possible, to increase the chances that the + temporary file is removed when the process crashes. */ + if (supports_delete_on_close ()) + { + size_t mode_len = strlen (mode); + char *augmented_mode = (char *) xmalloca (mode_len + 2); + memcpy (augmented_mode, mode, mode_len); + memcpy (augmented_mode + mode_len, "D", 2); + + fp = fopen (file_name, augmented_mode); + saved_errno = errno; + + freea (augmented_mode); + } + else +#endif + { + fp = fopen (file_name, mode); + saved_errno = errno; + } + if (fp != NULL) + { + /* It is sufficient to register fileno (fp) instead of the entire fp, + because at cleanup time there is no need to do an fflush (fp); a + close (fileno (fp)) will be enough. */ + int fd = fileno (fp); + if (!(fd >= 0)) + abort (); + register_fd (fd); + } + unblock_fatal_signals (); + errno = saved_errno; + return fp; +} + +/* Close a temporary file in a temporary directory. + Unregisters the previously registered file descriptor. */ +int +close_temp (int fd) +{ + if (fd >= 0) + { + /* No blocking of signals is needed here, since a double close of a + file descriptor is harmless. */ + int result = close (fd); + int saved_errno = errno; + + /* No race condition here: we assume a single-threaded program, hence + fd cannot be re-opened here. */ + + unregister_fd (fd); + + errno = saved_errno; + return result; + } + else + return close (fd); +} + +/* Close a temporary file in a temporary directory. + Unregisters the previously registered file descriptor. */ +int +fclose_temp (FILE *fp) +{ + int fd = fileno (fp); + /* No blocking of signals is needed here, since a double close of a + file descriptor is harmless. */ + int result = fclose (fp); + int saved_errno = errno; + + /* No race condition here: we assume a single-threaded program, hence + fd cannot be re-opened here. */ + + unregister_fd (fd); + + errno = saved_errno; + return result; +} + +#if GNULIB_FWRITEERROR +/* Like fwriteerror. + Unregisters the previously registered file descriptor. */ +int +fwriteerror_temp (FILE *fp) +{ + int fd = fileno (fp); + /* No blocking of signals is needed here, since a double close of a + file descriptor is harmless. */ + int result = fwriteerror (fp); + int saved_errno = errno; + + /* No race condition here: we assume a single-threaded program, hence + fd cannot be re-opened here. */ + + unregister_fd (fd); + + errno = saved_errno; + return result; +} +#endif + +#if GNULIB_CLOSE_STREAM +/* Like close_stream. + Unregisters the previously registered file descriptor. */ +int +close_stream_temp (FILE *fp) +{ + int fd = fileno (fp); + /* No blocking of signals is needed here, since a double close of a + file descriptor is harmless. */ + int result = close_stream (fp); + int saved_errno = errno; + + /* No race condition here: we assume a single-threaded program, hence + fd cannot be re-opened here. */ + + unregister_fd (fd); + + errno = saved_errno; + return result; +} +#endif diff --git a/gettext-tools/gnulib-lib/clean-temp.h b/gettext-tools/gnulib-lib/clean-temp.h new file mode 100644 index 0000000..2e01dd7 --- /dev/null +++ b/gettext-tools/gnulib-lib/clean-temp.h @@ -0,0 +1,142 @@ +/* Temporary directories and temporary files with automatic cleanup. + Copyright (C) 2006, 2011-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _CLEAN_TEMP_H +#define _CLEAN_TEMP_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Temporary directories and temporary files should be automatically removed + when the program exits either normally or through a fatal signal. We can't + rely on the "unlink before close" idiom, because it works only on Unix and + also - if no signal blocking is used - leaves a time window where a fatal + signal would not clean up the temporary file. + + Also, open file descriptors need to be closed before the temporary files + and the temporary directories can be removed, because only on Unix + (excluding Cygwin) can one remove directories containing open files. + + This module provides support for temporary directories and temporary files + inside these temporary directories. Temporary files without temporary + directories are not supported here. The temporary directories and files + are automatically cleaned up (at the latest) when the program exits or + dies from a fatal signal such as SIGINT, SIGTERM, SIGHUP, but not if it + dies from a fatal signal such as SIGQUIT, SIGKILL, or SIGABRT, SIGSEGV, + SIGBUS, SIGILL, SIGFPE. + + For the cleanup in the normal case, programs that use this module need to + call 'cleanup_temp_dir' for each successful return of 'create_temp_dir'. + The cleanup in the case of a fatal signal such as SIGINT, SIGTERM, SIGHUP, + is done entirely automatically by the functions of this module. */ + +struct temp_dir +{ + /* The absolute pathname of the directory. */ + const char * const dir_name; + /* Whether errors during explicit cleanup are reported to standard error. */ + bool cleanup_verbose; + /* More fields are present here, but not public. */ +}; + +/* Create a temporary directory. + PREFIX is used as a prefix for the name of the temporary directory. It + should be short and still give an indication about the program. + PARENTDIR can be used to specify the parent directory; if NULL, a default + parent directory is used (either $TMPDIR or /tmp or similar). + CLEANUP_VERBOSE determines whether errors during explicit cleanup are + reported to standard error. + Return a fresh 'struct temp_dir' on success. Upon error, an error message + is shown and NULL is returned. */ +extern struct temp_dir * create_temp_dir (const char *prefix, + const char *parentdir, + bool cleanup_verbose); + +/* Register the given ABSOLUTE_FILE_NAME as being a file inside DIR, that + needs to be removed before DIR can be removed. + Should be called before the file ABSOLUTE_FILE_NAME is created. */ +extern void register_temp_file (struct temp_dir *dir, + const char *absolute_file_name); + +/* Unregister the given ABSOLUTE_FILE_NAME as being a file inside DIR, that + needs to be removed before DIR can be removed. + Should be called when the file ABSOLUTE_FILE_NAME could not be created. */ +extern void unregister_temp_file (struct temp_dir *dir, + const char *absolute_file_name); + +/* Register the given ABSOLUTE_DIR_NAME as being a subdirectory inside DIR, + that needs to be removed before DIR can be removed. + Should be called before the subdirectory ABSOLUTE_DIR_NAME is created. */ +extern void register_temp_subdir (struct temp_dir *dir, + const char *absolute_dir_name); + +/* Unregister the given ABSOLUTE_DIR_NAME as being a subdirectory inside DIR, + that needs to be removed before DIR can be removed. + Should be called when the subdirectory ABSOLUTE_DIR_NAME could not be + created. */ +extern void unregister_temp_subdir (struct temp_dir *dir, + const char *absolute_dir_name); + +/* Remove the given ABSOLUTE_FILE_NAME and unregister it. + Return 0 upon success, or -1 if there was some problem. */ +extern int cleanup_temp_file (struct temp_dir *dir, + const char *absolute_file_name); + +/* Remove the given ABSOLUTE_DIR_NAME and unregister it. + Return 0 upon success, or -1 if there was some problem. */ +extern int cleanup_temp_subdir (struct temp_dir *dir, + const char *absolute_dir_name); + +/* Remove all registered files and subdirectories inside DIR. + Return 0 upon success, or -1 if there was some problem. */ +extern int cleanup_temp_dir_contents (struct temp_dir *dir); + +/* Remove all registered files and subdirectories inside DIR and DIR itself. + DIR cannot be used any more after this call. + Return 0 upon success, or -1 if there was some problem. */ +extern int cleanup_temp_dir (struct temp_dir *dir); + +/* Open a temporary file in a temporary directory. + Registers the resulting file descriptor to be closed. */ +extern int open_temp (const char *file_name, int flags, mode_t mode); +extern FILE * fopen_temp (const char *file_name, const char *mode); + +/* Close a temporary file in a temporary directory. + Unregisters the previously registered file descriptor. */ +extern int close_temp (int fd); +extern int fclose_temp (FILE *fp); + +/* Like fwriteerror. + Unregisters the previously registered file descriptor. */ +extern int fwriteerror_temp (FILE *fp); + +/* Like close_stream. + Unregisters the previously registered file descriptor. */ +extern int close_stream_temp (FILE *fp); + + +#ifdef __cplusplus +} +#endif + +#endif /* _CLEAN_TEMP_H */ diff --git a/gettext-tools/gnulib-lib/cloexec.c b/gettext-tools/gnulib-lib/cloexec.c new file mode 100644 index 0000000..48a0c97 --- /dev/null +++ b/gettext-tools/gnulib-lib/cloexec.c @@ -0,0 +1,83 @@ +/* closexec.c - set or clear the close-on-exec descriptor flag + + Copyright (C) 1991, 2004-2006, 2009-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + The code is taken from glibc/manual/llio.texi */ + +#include + +#include "cloexec.h" + +#include +#include +#include + +/* Set the 'FD_CLOEXEC' flag of DESC if VALUE is true, + or clear the flag if VALUE is false. + Return 0 on success, or -1 on error with 'errno' set. + + Note that on MingW, this function does NOT protect DESC from being + inherited into spawned children. Instead, either use dup_cloexec + followed by closing the original DESC, or use interfaces such as + open or pipe2 that accept flags like O_CLOEXEC to create DESC + non-inheritable in the first place. */ + +int +set_cloexec_flag (int desc, bool value) +{ +#ifdef F_SETFD + + int flags = fcntl (desc, F_GETFD, 0); + + if (0 <= flags) + { + int newflags = (value ? flags | FD_CLOEXEC : flags & ~FD_CLOEXEC); + + if (flags == newflags + || fcntl (desc, F_SETFD, newflags) != -1) + return 0; + } + + return -1; + +#else /* !F_SETFD */ + + /* Use dup2 to reject invalid file descriptors; the cloexec flag + will be unaffected. */ + if (desc < 0) + { + errno = EBADF; + return -1; + } + if (dup2 (desc, desc) < 0) + /* errno is EBADF here. */ + return -1; + + /* There is nothing we can do on this kind of platform. Punt. */ + return 0; +#endif /* !F_SETFD */ +} + + +/* Duplicates a file handle FD, while marking the copy to be closed + prior to exec or spawn. Returns -1 and sets errno if FD could not + be duplicated. */ + +int +dup_cloexec (int fd) +{ + return fcntl (fd, F_DUPFD_CLOEXEC, 0); +} diff --git a/gettext-tools/gnulib-lib/cloexec.h b/gettext-tools/gnulib-lib/cloexec.h new file mode 100644 index 0000000..6c442dc --- /dev/null +++ b/gettext-tools/gnulib-lib/cloexec.h @@ -0,0 +1,38 @@ +/* closexec.c - set or clear the close-on-exec descriptor flag + + Copyright (C) 2004, 2009-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +*/ + +#include + +/* Set the 'FD_CLOEXEC' flag of DESC if VALUE is true, + or clear the flag if VALUE is false. + Return 0 on success, or -1 on error with 'errno' set. + + Note that on MingW, this function does NOT protect DESC from being + inherited into spawned children. Instead, either use dup_cloexec + followed by closing the original DESC, or use interfaces such as + open or pipe2 that accept flags like O_CLOEXEC to create DESC + non-inheritable in the first place. */ + +int set_cloexec_flag (int desc, bool value); + +/* Duplicates a file handle FD, while marking the copy to be closed + prior to exec or spawn. Returns -1 and sets errno if FD could not + be duplicated. */ + +int dup_cloexec (int fd); diff --git a/gettext-tools/gnulib-lib/close.c b/gettext-tools/gnulib-lib/close.c new file mode 100644 index 0000000..d7dcb3f --- /dev/null +++ b/gettext-tools/gnulib-lib/close.c @@ -0,0 +1,69 @@ +/* close replacement. + Copyright (C) 2008-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include + +#include + +#include "fd-hook.h" +#include "msvc-inval.h" + +#undef close + +#if HAVE_MSVC_INVALID_PARAMETER_HANDLER +static int +close_nothrow (int fd) +{ + int result; + + TRY_MSVC_INVAL + { + result = close (fd); + } + CATCH_MSVC_INVAL + { + result = -1; + errno = EBADF; + } + DONE_MSVC_INVAL; + + return result; +} +#else +# define close_nothrow close +#endif + +/* Override close() to call into other gnulib modules. */ + +int +rpl_close (int fd) +{ +#if WINDOWS_SOCKETS + int retval = execute_all_close_hooks (close_nothrow, fd); +#else + int retval = close_nothrow (fd); +#endif + +#if REPLACE_FCHDIR + if (retval >= 0) + _gl_unregister_fd (fd); +#endif + + return retval; +} diff --git a/gettext-tools/gnulib-lib/closedir.c b/gettext-tools/gnulib-lib/closedir.c new file mode 100644 index 0000000..940c6f9 --- /dev/null +++ b/gettext-tools/gnulib-lib/closedir.c @@ -0,0 +1,67 @@ +/* Stop reading the entries of a directory. + Copyright (C) 2006-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include + +#if REPLACE_FCHDIR +# include +#endif + +#if HAVE_CLOSEDIR + +/* Override closedir(), to keep track of the open file descriptors. + Needed because there is a function dirfd(). */ + +#else + +# include + +# include "dirent-private.h" + +#endif + +int +closedir (DIR *dirp) +{ +# if REPLACE_FCHDIR + int fd = dirfd (dirp); +# endif + int retval; + +#if HAVE_CLOSEDIR +# undef closedir + + retval = closedir (dirp); + +#else + + if (dirp->current != INVALID_HANDLE_VALUE) + FindClose (dirp->current); + free (dirp); + + retval = 0; + +#endif + +#if REPLACE_FCHDIR + if (retval >= 0) + _gl_unregister_fd (fd); +#endif + return retval; +} diff --git a/gettext-tools/gnulib-lib/closeout.c b/gettext-tools/gnulib-lib/closeout.c new file mode 100644 index 0000000..20b021d --- /dev/null +++ b/gettext-tools/gnulib-lib/closeout.c @@ -0,0 +1,87 @@ +/* closeout.c - close standard output and standard error + Copyright (C) 1998-2007, 2012 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include "closeout.h" + +#include +#include +#include + +#include "error.h" +#include "fwriteerror.h" +#include "gettext.h" + +#define _(msgid) gettext (msgid) + +/* Close standard output, exiting with status STATUS on failure. + If a program writes *anything* to stdout, that program should close + stdout and make sure that it succeeds before exiting. Otherwise, + suppose that you go to the extreme of checking the return status + of every function that does an explicit write to stdout. The last + printf can succeed in writing to the internal stream buffer, and yet + the fclose(stdout) could still fail (due e.g., to a disk full error) + when it tries to write out that buffered data. Thus, you would be + left with an incomplete output file and the offending program would + exit successfully. Even calling fflush is not always sufficient, + since some file systems (NFS and CODA) buffer written/flushed data + until an actual close call. + + Besides, it's wasteful to check the return value from every call + that writes to stdout -- just let the internal stream state record + the failure. That's what the ferror test is checking below. + + If the stdout file descriptor was initially closed (such as when executing + a program through "program 1>&-"), it is a failure if and only if some + output was made to stdout. + + Likewise for standard error. + + It's important to detect such failures and exit nonzero because many + tools (most notably 'make' and other build-management systems) depend + on being able to detect failure in other tools via their exit status. */ + +/* Close standard output and standard error, exiting with status EXIT_FAILURE + on failure. */ +void +close_stdout (void) +{ + /* Close standard output. */ + if (fwriteerror_no_ebadf (stdout)) + error (EXIT_FAILURE, errno, "%s", _("write error")); + + /* Close standard error. This is simpler than fwriteerror_no_ebadf, because + upon failure we don't need an errno - all we can do at this point is to + set an exit status. */ + errno = 0; + if (ferror (stderr) || fflush (stderr)) + { + fclose (stderr); + exit (EXIT_FAILURE); + } + if (fclose (stderr) && errno != EBADF) + exit (EXIT_FAILURE); +} + +/* Note: When exit (...) calls the atexit-registered + close_stdout (), which calls + error (status, ...), which calls + exit (status), + we have undefined behaviour according to ISO C 99 section 7.20.4.3.(2). + But in practice there is no problem: The second exit call is executed + at a moment when the atexit handlers are no longer active. */ diff --git a/gettext-tools/gnulib-lib/closeout.h b/gettext-tools/gnulib-lib/closeout.h new file mode 100644 index 0000000..33e309e --- /dev/null +++ b/gettext-tools/gnulib-lib/closeout.h @@ -0,0 +1,30 @@ +/* Close standard output and standard error. + Copyright (C) 1998-2003, 2006 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef CLOSEOUT_H +#define CLOSEOUT_H 1 + +#ifdef __cplusplus +extern "C" { +#endif + +extern void close_stdout (void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/gettext-tools/gnulib-lib/concat-filename.c b/gettext-tools/gnulib-lib/concat-filename.c new file mode 100644 index 0000000..661312a --- /dev/null +++ b/gettext-tools/gnulib-lib/concat-filename.c @@ -0,0 +1,73 @@ +/* Construct a full filename from a directory and a relative filename. + Copyright (C) 2001-2004, 2006-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 3 of the License, or any + later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Written by Bruno Haible . */ + +#include + +/* Specification. */ +#include "concat-filename.h" + +#include +#include +#include + +#include "filename.h" + +/* Concatenate a directory filename, a relative filename and an optional + suffix. The directory may end with the directory separator. The second + argument may not start with the directory separator (it is relative). + Return a freshly allocated filename. Return NULL and set errno + upon memory allocation failure. */ +char * +concatenated_filename (const char *directory, const char *filename, + const char *suffix) +{ + char *result; + char *p; + + if (strcmp (directory, ".") == 0) + { + /* No need to prepend the directory. */ + result = (char *) malloc (strlen (filename) + + (suffix != NULL ? strlen (suffix) : 0) + + 1); + if (result == NULL) + return NULL; /* errno is set here */ + p = result; + } + else + { + size_t directory_len = strlen (directory); + int need_slash = + (directory_len > FILE_SYSTEM_PREFIX_LEN (directory) + && !ISSLASH (directory[directory_len - 1])); + result = (char *) malloc (directory_len + need_slash + + strlen (filename) + + (suffix != NULL ? strlen (suffix) : 0) + + 1); + if (result == NULL) + return NULL; /* errno is set here */ + memcpy (result, directory, directory_len); + p = result + directory_len; + if (need_slash) + *p++ = '/'; + } + p = stpcpy (p, filename); + if (suffix != NULL) + stpcpy (p, suffix); + return result; +} diff --git a/gettext-tools/gnulib-lib/concat-filename.h b/gettext-tools/gnulib-lib/concat-filename.h new file mode 100644 index 0000000..88f1cf7 --- /dev/null +++ b/gettext-tools/gnulib-lib/concat-filename.h @@ -0,0 +1,41 @@ +/* Construct a full filename from a directory and a relative filename. + Copyright (C) 2001-2004, 2007-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _CONCAT_FILENAME_H +#define _CONCAT_FILENAME_H + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Concatenate a directory filename, a relative filename and an optional + suffix. Return a freshly allocated filename. Return NULL and set errno + upon memory allocation failure. */ +extern char *concatenated_filename (const char *directory, + const char *filename, const char *suffix); + +/* Concatenate a directory filename, a relative filename and an optional + suffix. Return a freshly allocated filename. */ +extern char *xconcatenated_filename (const char *directory, + const char *filename, const char *suffix); + + +#ifdef __cplusplus +} +#endif + +#endif /* _CONCAT_FILENAME_H */ diff --git a/gettext-tools/gnulib-lib/config.charset b/gettext-tools/gnulib-lib/config.charset new file mode 100644 index 0000000..289bc44 --- /dev/null +++ b/gettext-tools/gnulib-lib/config.charset @@ -0,0 +1,684 @@ +#! /bin/sh +# Output a system dependent table of character encoding aliases. +# +# Copyright (C) 2000-2004, 2006-2014 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, see . +# +# The table consists of lines of the form +# ALIAS CANONICAL +# +# ALIAS is the (system dependent) result of "nl_langinfo (CODESET)". +# ALIAS is compared in a case sensitive way. +# +# CANONICAL is the GNU canonical name for this character encoding. +# It must be an encoding supported by libiconv. Support by GNU libc is +# also desirable. CANONICAL is case insensitive. Usually an upper case +# MIME charset name is preferred. +# The current list of GNU canonical charset names is as follows. +# +# name MIME? used by which systems +# (darwin = Mac OS X, woe32 = native Windows) +# +# ASCII, ANSI_X3.4-1968 glibc solaris freebsd netbsd darwin cygwin +# ISO-8859-1 Y glibc aix hpux irix osf solaris freebsd netbsd openbsd darwin cygwin +# ISO-8859-2 Y glibc aix hpux irix osf solaris freebsd netbsd openbsd darwin cygwin +# ISO-8859-3 Y glibc solaris cygwin +# ISO-8859-4 Y osf solaris freebsd netbsd openbsd darwin +# ISO-8859-5 Y glibc aix hpux irix osf solaris freebsd netbsd openbsd darwin cygwin +# ISO-8859-6 Y glibc aix hpux solaris cygwin +# ISO-8859-7 Y glibc aix hpux irix osf solaris netbsd openbsd darwin cygwin +# ISO-8859-8 Y glibc aix hpux osf solaris cygwin +# ISO-8859-9 Y glibc aix hpux irix osf solaris darwin cygwin +# ISO-8859-13 glibc netbsd openbsd darwin cygwin +# ISO-8859-14 glibc cygwin +# ISO-8859-15 glibc aix osf solaris freebsd netbsd openbsd darwin cygwin +# KOI8-R Y glibc solaris freebsd netbsd openbsd darwin +# KOI8-U Y glibc freebsd netbsd openbsd darwin cygwin +# KOI8-T glibc +# CP437 dos +# CP775 dos +# CP850 aix osf dos +# CP852 dos +# CP855 dos +# CP856 aix +# CP857 dos +# CP861 dos +# CP862 dos +# CP864 dos +# CP865 dos +# CP866 freebsd netbsd openbsd darwin dos +# CP869 dos +# CP874 woe32 dos +# CP922 aix +# CP932 aix cygwin woe32 dos +# CP943 aix +# CP949 osf darwin woe32 dos +# CP950 woe32 dos +# CP1046 aix +# CP1124 aix +# CP1125 dos +# CP1129 aix +# CP1131 darwin +# CP1250 woe32 +# CP1251 glibc solaris netbsd openbsd darwin cygwin woe32 +# CP1252 aix woe32 +# CP1253 woe32 +# CP1254 woe32 +# CP1255 glibc woe32 +# CP1256 woe32 +# CP1257 woe32 +# GB2312 Y glibc aix hpux irix solaris freebsd netbsd darwin +# EUC-JP Y glibc aix hpux irix osf solaris freebsd netbsd darwin +# EUC-KR Y glibc aix hpux irix osf solaris freebsd netbsd darwin cygwin +# EUC-TW glibc aix hpux irix osf solaris netbsd +# BIG5 Y glibc aix hpux osf solaris freebsd netbsd darwin cygwin +# BIG5-HKSCS glibc solaris darwin +# GBK glibc aix osf solaris darwin cygwin woe32 dos +# GB18030 glibc solaris netbsd darwin +# SHIFT_JIS Y hpux osf solaris freebsd netbsd darwin +# JOHAB glibc solaris woe32 +# TIS-620 glibc aix hpux osf solaris cygwin +# VISCII Y glibc +# TCVN5712-1 glibc +# ARMSCII-8 glibc darwin +# GEORGIAN-PS glibc cygwin +# PT154 glibc +# HP-ROMAN8 hpux +# HP-ARABIC8 hpux +# HP-GREEK8 hpux +# HP-HEBREW8 hpux +# HP-TURKISH8 hpux +# HP-KANA8 hpux +# DEC-KANJI osf +# DEC-HANYU osf +# UTF-8 Y glibc aix hpux osf solaris netbsd darwin cygwin +# +# Note: Names which are not marked as being a MIME name should not be used in +# Internet protocols for information interchange (mail, news, etc.). +# +# Note: ASCII and ANSI_X3.4-1968 are synonymous canonical names. Applications +# must understand both names and treat them as equivalent. +# +# The first argument passed to this file is the canonical host specification, +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM + +host="$1" +os=`echo "$host" | sed -e 's/^[^-]*-[^-]*-\(.*\)$/\1/'` +echo "# This file contains a table of character encoding aliases," +echo "# suitable for operating system '${os}'." +echo "# It was automatically generated from config.charset." +# List of references, updated during installation: +echo "# Packages using this file: " +case "$os" in + linux-gnulibc1*) + # Linux libc5 doesn't have nl_langinfo(CODESET); therefore + # localcharset.c falls back to using the full locale name + # from the environment variables. + echo "C ASCII" + echo "POSIX ASCII" + for l in af af_ZA ca ca_ES da da_DK de de_AT de_BE de_CH de_DE de_LU \ + en en_AU en_BW en_CA en_DK en_GB en_IE en_NZ en_US en_ZA \ + en_ZW es es_AR es_BO es_CL es_CO es_DO es_EC es_ES es_GT \ + es_HN es_MX es_PA es_PE es_PY es_SV es_US es_UY es_VE et \ + et_EE eu eu_ES fi fi_FI fo fo_FO fr fr_BE fr_CA fr_CH fr_FR \ + fr_LU ga ga_IE gl gl_ES id id_ID in in_ID is is_IS it it_CH \ + it_IT kl kl_GL nl nl_BE nl_NL no no_NO pt pt_BR pt_PT sv \ + sv_FI sv_SE; do + echo "$l ISO-8859-1" + echo "$l.iso-8859-1 ISO-8859-1" + echo "$l.iso-8859-15 ISO-8859-15" + echo "$l.iso-8859-15@euro ISO-8859-15" + echo "$l@euro ISO-8859-15" + echo "$l.cp-437 CP437" + echo "$l.cp-850 CP850" + echo "$l.cp-1252 CP1252" + echo "$l.cp-1252@euro CP1252" + #echo "$l.atari-st ATARI-ST" # not a commonly used encoding + echo "$l.utf-8 UTF-8" + echo "$l.utf-8@euro UTF-8" + done + for l in cs cs_CZ hr hr_HR hu hu_HU pl pl_PL ro ro_RO sk sk_SK sl \ + sl_SI sr sr_CS sr_YU; do + echo "$l ISO-8859-2" + echo "$l.iso-8859-2 ISO-8859-2" + echo "$l.cp-852 CP852" + echo "$l.cp-1250 CP1250" + echo "$l.utf-8 UTF-8" + done + for l in mk mk_MK ru ru_RU; do + echo "$l ISO-8859-5" + echo "$l.iso-8859-5 ISO-8859-5" + echo "$l.koi8-r KOI8-R" + echo "$l.cp-866 CP866" + echo "$l.cp-1251 CP1251" + echo "$l.utf-8 UTF-8" + done + for l in ar ar_SA; do + echo "$l ISO-8859-6" + echo "$l.iso-8859-6 ISO-8859-6" + echo "$l.cp-864 CP864" + #echo "$l.cp-868 CP868" # not a commonly used encoding + echo "$l.cp-1256 CP1256" + echo "$l.utf-8 UTF-8" + done + for l in el el_GR gr gr_GR; do + echo "$l ISO-8859-7" + echo "$l.iso-8859-7 ISO-8859-7" + echo "$l.cp-869 CP869" + echo "$l.cp-1253 CP1253" + echo "$l.cp-1253@euro CP1253" + echo "$l.utf-8 UTF-8" + echo "$l.utf-8@euro UTF-8" + done + for l in he he_IL iw iw_IL; do + echo "$l ISO-8859-8" + echo "$l.iso-8859-8 ISO-8859-8" + echo "$l.cp-862 CP862" + echo "$l.cp-1255 CP1255" + echo "$l.utf-8 UTF-8" + done + for l in tr tr_TR; do + echo "$l ISO-8859-9" + echo "$l.iso-8859-9 ISO-8859-9" + echo "$l.cp-857 CP857" + echo "$l.cp-1254 CP1254" + echo "$l.utf-8 UTF-8" + done + for l in lt lt_LT lv lv_LV; do + #echo "$l BALTIC" # not a commonly used encoding, wrong encoding name + echo "$l ISO-8859-13" + done + for l in ru_UA uk uk_UA; do + echo "$l KOI8-U" + done + for l in zh zh_CN; do + #echo "$l GB_2312-80" # not a commonly used encoding, wrong encoding name + echo "$l GB2312" + done + for l in ja ja_JP ja_JP.EUC; do + echo "$l EUC-JP" + done + for l in ko ko_KR; do + echo "$l EUC-KR" + done + for l in th th_TH; do + echo "$l TIS-620" + done + for l in fa fa_IR; do + #echo "$l ISIRI-3342" # a broken encoding + echo "$l.utf-8 UTF-8" + done + ;; + linux* | *-gnu*) + # With glibc-2.1 or newer, we don't need any canonicalization, + # because glibc has iconv and both glibc and libiconv support all + # GNU canonical names directly. Therefore, the Makefile does not + # need to install the alias file at all. + # The following applies only to glibc-2.0.x and older libcs. + echo "ISO_646.IRV:1983 ASCII" + ;; + aix*) + echo "ISO8859-1 ISO-8859-1" + echo "ISO8859-2 ISO-8859-2" + echo "ISO8859-5 ISO-8859-5" + echo "ISO8859-6 ISO-8859-6" + echo "ISO8859-7 ISO-8859-7" + echo "ISO8859-8 ISO-8859-8" + echo "ISO8859-9 ISO-8859-9" + echo "ISO8859-15 ISO-8859-15" + echo "IBM-850 CP850" + echo "IBM-856 CP856" + echo "IBM-921 ISO-8859-13" + echo "IBM-922 CP922" + echo "IBM-932 CP932" + echo "IBM-943 CP943" + echo "IBM-1046 CP1046" + echo "IBM-1124 CP1124" + echo "IBM-1129 CP1129" + echo "IBM-1252 CP1252" + echo "IBM-eucCN GB2312" + echo "IBM-eucJP EUC-JP" + echo "IBM-eucKR EUC-KR" + echo "IBM-eucTW EUC-TW" + echo "big5 BIG5" + echo "GBK GBK" + echo "TIS-620 TIS-620" + echo "UTF-8 UTF-8" + ;; + hpux*) + echo "iso88591 ISO-8859-1" + echo "iso88592 ISO-8859-2" + echo "iso88595 ISO-8859-5" + echo "iso88596 ISO-8859-6" + echo "iso88597 ISO-8859-7" + echo "iso88598 ISO-8859-8" + echo "iso88599 ISO-8859-9" + echo "iso885915 ISO-8859-15" + echo "roman8 HP-ROMAN8" + echo "arabic8 HP-ARABIC8" + echo "greek8 HP-GREEK8" + echo "hebrew8 HP-HEBREW8" + echo "turkish8 HP-TURKISH8" + echo "kana8 HP-KANA8" + echo "tis620 TIS-620" + echo "big5 BIG5" + echo "eucJP EUC-JP" + echo "eucKR EUC-KR" + echo "eucTW EUC-TW" + echo "hp15CN GB2312" + #echo "ccdc ?" # what is this? + echo "SJIS SHIFT_JIS" + echo "utf8 UTF-8" + ;; + irix*) + echo "ISO8859-1 ISO-8859-1" + echo "ISO8859-2 ISO-8859-2" + echo "ISO8859-5 ISO-8859-5" + echo "ISO8859-7 ISO-8859-7" + echo "ISO8859-9 ISO-8859-9" + echo "eucCN GB2312" + echo "eucJP EUC-JP" + echo "eucKR EUC-KR" + echo "eucTW EUC-TW" + ;; + osf*) + echo "ISO8859-1 ISO-8859-1" + echo "ISO8859-2 ISO-8859-2" + echo "ISO8859-4 ISO-8859-4" + echo "ISO8859-5 ISO-8859-5" + echo "ISO8859-7 ISO-8859-7" + echo "ISO8859-8 ISO-8859-8" + echo "ISO8859-9 ISO-8859-9" + echo "ISO8859-15 ISO-8859-15" + echo "cp850 CP850" + echo "big5 BIG5" + echo "dechanyu DEC-HANYU" + echo "dechanzi GB2312" + echo "deckanji DEC-KANJI" + echo "deckorean EUC-KR" + echo "eucJP EUC-JP" + echo "eucKR EUC-KR" + echo "eucTW EUC-TW" + echo "GBK GBK" + echo "KSC5601 CP949" + echo "sdeckanji EUC-JP" + echo "SJIS SHIFT_JIS" + echo "TACTIS TIS-620" + echo "UTF-8 UTF-8" + ;; + solaris*) + echo "646 ASCII" + echo "ISO8859-1 ISO-8859-1" + echo "ISO8859-2 ISO-8859-2" + echo "ISO8859-3 ISO-8859-3" + echo "ISO8859-4 ISO-8859-4" + echo "ISO8859-5 ISO-8859-5" + echo "ISO8859-6 ISO-8859-6" + echo "ISO8859-7 ISO-8859-7" + echo "ISO8859-8 ISO-8859-8" + echo "ISO8859-9 ISO-8859-9" + echo "ISO8859-15 ISO-8859-15" + echo "koi8-r KOI8-R" + echo "ansi-1251 CP1251" + echo "BIG5 BIG5" + echo "Big5-HKSCS BIG5-HKSCS" + echo "gb2312 GB2312" + echo "GBK GBK" + echo "GB18030 GB18030" + echo "cns11643 EUC-TW" + echo "5601 EUC-KR" + echo "ko_KR.johap92 JOHAB" + echo "eucJP EUC-JP" + echo "PCK SHIFT_JIS" + echo "TIS620.2533 TIS-620" + #echo "sun_eu_greek ?" # what is this? + echo "UTF-8 UTF-8" + ;; + freebsd* | os2*) + # FreeBSD 4.2 doesn't have nl_langinfo(CODESET); therefore + # localcharset.c falls back to using the full locale name + # from the environment variables. + # Likewise for OS/2. OS/2 has XFree86 just like FreeBSD. Just + # reuse FreeBSD's locale data for OS/2. + echo "C ASCII" + echo "US-ASCII ASCII" + for l in la_LN lt_LN; do + echo "$l.ASCII ASCII" + done + for l in da_DK de_AT de_CH de_DE en_AU en_CA en_GB en_US es_ES \ + fi_FI fr_BE fr_CA fr_CH fr_FR is_IS it_CH it_IT la_LN \ + lt_LN nl_BE nl_NL no_NO pt_PT sv_SE; do + echo "$l.ISO_8859-1 ISO-8859-1" + echo "$l.DIS_8859-15 ISO-8859-15" + done + for l in cs_CZ hr_HR hu_HU la_LN lt_LN pl_PL sl_SI; do + echo "$l.ISO_8859-2 ISO-8859-2" + done + for l in la_LN lt_LT; do + echo "$l.ISO_8859-4 ISO-8859-4" + done + for l in ru_RU ru_SU; do + echo "$l.KOI8-R KOI8-R" + echo "$l.ISO_8859-5 ISO-8859-5" + echo "$l.CP866 CP866" + done + echo "uk_UA.KOI8-U KOI8-U" + echo "zh_TW.BIG5 BIG5" + echo "zh_TW.Big5 BIG5" + echo "zh_CN.EUC GB2312" + echo "ja_JP.EUC EUC-JP" + echo "ja_JP.SJIS SHIFT_JIS" + echo "ja_JP.Shift_JIS SHIFT_JIS" + echo "ko_KR.EUC EUC-KR" + ;; + netbsd*) + echo "646 ASCII" + echo "ISO8859-1 ISO-8859-1" + echo "ISO8859-2 ISO-8859-2" + echo "ISO8859-4 ISO-8859-4" + echo "ISO8859-5 ISO-8859-5" + echo "ISO8859-7 ISO-8859-7" + echo "ISO8859-13 ISO-8859-13" + echo "ISO8859-15 ISO-8859-15" + echo "eucCN GB2312" + echo "eucJP EUC-JP" + echo "eucKR EUC-KR" + echo "eucTW EUC-TW" + echo "BIG5 BIG5" + echo "SJIS SHIFT_JIS" + ;; + openbsd*) + echo "646 ASCII" + echo "ISO8859-1 ISO-8859-1" + echo "ISO8859-2 ISO-8859-2" + echo "ISO8859-4 ISO-8859-4" + echo "ISO8859-5 ISO-8859-5" + echo "ISO8859-7 ISO-8859-7" + echo "ISO8859-13 ISO-8859-13" + echo "ISO8859-15 ISO-8859-15" + ;; + darwin[56]*) + # Darwin 6.8 doesn't have nl_langinfo(CODESET); therefore + # localcharset.c falls back to using the full locale name + # from the environment variables. + echo "C ASCII" + for l in en_AU en_CA en_GB en_US la_LN; do + echo "$l.US-ASCII ASCII" + done + for l in da_DK de_AT de_CH de_DE en_AU en_CA en_GB en_US es_ES \ + fi_FI fr_BE fr_CA fr_CH fr_FR is_IS it_CH it_IT nl_BE \ + nl_NL no_NO pt_PT sv_SE; do + echo "$l ISO-8859-1" + echo "$l.ISO8859-1 ISO-8859-1" + echo "$l.ISO8859-15 ISO-8859-15" + done + for l in la_LN; do + echo "$l.ISO8859-1 ISO-8859-1" + echo "$l.ISO8859-15 ISO-8859-15" + done + for l in cs_CZ hr_HR hu_HU la_LN pl_PL sl_SI; do + echo "$l.ISO8859-2 ISO-8859-2" + done + for l in la_LN lt_LT; do + echo "$l.ISO8859-4 ISO-8859-4" + done + for l in ru_RU; do + echo "$l.KOI8-R KOI8-R" + echo "$l.ISO8859-5 ISO-8859-5" + echo "$l.CP866 CP866" + done + for l in bg_BG; do + echo "$l.CP1251 CP1251" + done + echo "uk_UA.KOI8-U KOI8-U" + echo "zh_TW.BIG5 BIG5" + echo "zh_TW.Big5 BIG5" + echo "zh_CN.EUC GB2312" + echo "ja_JP.EUC EUC-JP" + echo "ja_JP.SJIS SHIFT_JIS" + echo "ko_KR.EUC EUC-KR" + ;; + darwin*) + # Darwin 7.5 has nl_langinfo(CODESET), but sometimes its value is + # useless: + # - It returns the empty string when LANG is set to a locale of the + # form ll_CC, although ll_CC/LC_CTYPE is a symlink to an UTF-8 + # LC_CTYPE file. + # - The environment variables LANG, LC_CTYPE, LC_ALL are not set by + # the system; nl_langinfo(CODESET) returns "US-ASCII" in this case. + # - The documentation says: + # "... all code that calls BSD system routines should ensure + # that the const *char parameters of these routines are in UTF-8 + # encoding. All BSD system functions expect their string + # parameters to be in UTF-8 encoding and nothing else." + # It also says + # "An additional caveat is that string parameters for files, + # paths, and other file-system entities must be in canonical + # UTF-8. In a canonical UTF-8 Unicode string, all decomposable + # characters are decomposed ..." + # but this is not true: You can pass non-decomposed UTF-8 strings + # to file system functions, and it is the OS which will convert + # them to decomposed UTF-8 before accessing the file system. + # - The Apple Terminal application displays UTF-8 by default. + # - However, other applications are free to use different encodings: + # - xterm uses ISO-8859-1 by default. + # - TextEdit uses MacRoman by default. + # We prefer UTF-8 over decomposed UTF-8-MAC because one should + # minimize the use of decomposed Unicode. Unfortunately, through the + # Darwin file system, decomposed UTF-8 strings are leaked into user + # space nevertheless. + # Then there are also the locales with encodings other than US-ASCII + # and UTF-8. These locales can be occasionally useful to users (e.g. + # when grepping through ISO-8859-1 encoded text files), when all their + # file names are in US-ASCII. + echo "ISO8859-1 ISO-8859-1" + echo "ISO8859-2 ISO-8859-2" + echo "ISO8859-4 ISO-8859-4" + echo "ISO8859-5 ISO-8859-5" + echo "ISO8859-7 ISO-8859-7" + echo "ISO8859-9 ISO-8859-9" + echo "ISO8859-13 ISO-8859-13" + echo "ISO8859-15 ISO-8859-15" + echo "KOI8-R KOI8-R" + echo "KOI8-U KOI8-U" + echo "CP866 CP866" + echo "CP949 CP949" + echo "CP1131 CP1131" + echo "CP1251 CP1251" + echo "eucCN GB2312" + echo "GB2312 GB2312" + echo "eucJP EUC-JP" + echo "eucKR EUC-KR" + echo "Big5 BIG5" + echo "Big5HKSCS BIG5-HKSCS" + echo "GBK GBK" + echo "GB18030 GB18030" + echo "SJIS SHIFT_JIS" + echo "ARMSCII-8 ARMSCII-8" + echo "PT154 PT154" + #echo "ISCII-DEV ?" + echo "* UTF-8" + ;; + beos* | haiku*) + # BeOS and Haiku have a single locale, and it has UTF-8 encoding. + echo "* UTF-8" + ;; + msdosdjgpp*) + # DJGPP 2.03 doesn't have nl_langinfo(CODESET); therefore + # localcharset.c falls back to using the full locale name + # from the environment variables. + echo "#" + echo "# The encodings given here may not all be correct." + echo "# If you find that the encoding given for your language and" + echo "# country is not the one your DOS machine actually uses, just" + echo "# correct it in this file, and send a mail to" + echo "# Juan Manuel Guerrero " + echo "# and Bruno Haible ." + echo "#" + echo "C ASCII" + # ISO-8859-1 languages + echo "ca CP850" + echo "ca_ES CP850" + echo "da CP865" # not CP850 ?? + echo "da_DK CP865" # not CP850 ?? + echo "de CP850" + echo "de_AT CP850" + echo "de_CH CP850" + echo "de_DE CP850" + echo "en CP850" + echo "en_AU CP850" # not CP437 ?? + echo "en_CA CP850" + echo "en_GB CP850" + echo "en_NZ CP437" + echo "en_US CP437" + echo "en_ZA CP850" # not CP437 ?? + echo "es CP850" + echo "es_AR CP850" + echo "es_BO CP850" + echo "es_CL CP850" + echo "es_CO CP850" + echo "es_CR CP850" + echo "es_CU CP850" + echo "es_DO CP850" + echo "es_EC CP850" + echo "es_ES CP850" + echo "es_GT CP850" + echo "es_HN CP850" + echo "es_MX CP850" + echo "es_NI CP850" + echo "es_PA CP850" + echo "es_PY CP850" + echo "es_PE CP850" + echo "es_SV CP850" + echo "es_UY CP850" + echo "es_VE CP850" + echo "et CP850" + echo "et_EE CP850" + echo "eu CP850" + echo "eu_ES CP850" + echo "fi CP850" + echo "fi_FI CP850" + echo "fr CP850" + echo "fr_BE CP850" + echo "fr_CA CP850" + echo "fr_CH CP850" + echo "fr_FR CP850" + echo "ga CP850" + echo "ga_IE CP850" + echo "gd CP850" + echo "gd_GB CP850" + echo "gl CP850" + echo "gl_ES CP850" + echo "id CP850" # not CP437 ?? + echo "id_ID CP850" # not CP437 ?? + echo "is CP861" # not CP850 ?? + echo "is_IS CP861" # not CP850 ?? + echo "it CP850" + echo "it_CH CP850" + echo "it_IT CP850" + echo "lt CP775" + echo "lt_LT CP775" + echo "lv CP775" + echo "lv_LV CP775" + echo "nb CP865" # not CP850 ?? + echo "nb_NO CP865" # not CP850 ?? + echo "nl CP850" + echo "nl_BE CP850" + echo "nl_NL CP850" + echo "nn CP865" # not CP850 ?? + echo "nn_NO CP865" # not CP850 ?? + echo "no CP865" # not CP850 ?? + echo "no_NO CP865" # not CP850 ?? + echo "pt CP850" + echo "pt_BR CP850" + echo "pt_PT CP850" + echo "sv CP850" + echo "sv_SE CP850" + # ISO-8859-2 languages + echo "cs CP852" + echo "cs_CZ CP852" + echo "hr CP852" + echo "hr_HR CP852" + echo "hu CP852" + echo "hu_HU CP852" + echo "pl CP852" + echo "pl_PL CP852" + echo "ro CP852" + echo "ro_RO CP852" + echo "sk CP852" + echo "sk_SK CP852" + echo "sl CP852" + echo "sl_SI CP852" + echo "sq CP852" + echo "sq_AL CP852" + echo "sr CP852" # CP852 or CP866 or CP855 ?? + echo "sr_CS CP852" # CP852 or CP866 or CP855 ?? + echo "sr_YU CP852" # CP852 or CP866 or CP855 ?? + # ISO-8859-3 languages + echo "mt CP850" + echo "mt_MT CP850" + # ISO-8859-5 languages + echo "be CP866" + echo "be_BE CP866" + echo "bg CP866" # not CP855 ?? + echo "bg_BG CP866" # not CP855 ?? + echo "mk CP866" # not CP855 ?? + echo "mk_MK CP866" # not CP855 ?? + echo "ru CP866" + echo "ru_RU CP866" + echo "uk CP1125" + echo "uk_UA CP1125" + # ISO-8859-6 languages + echo "ar CP864" + echo "ar_AE CP864" + echo "ar_DZ CP864" + echo "ar_EG CP864" + echo "ar_IQ CP864" + echo "ar_IR CP864" + echo "ar_JO CP864" + echo "ar_KW CP864" + echo "ar_MA CP864" + echo "ar_OM CP864" + echo "ar_QA CP864" + echo "ar_SA CP864" + echo "ar_SY CP864" + # ISO-8859-7 languages + echo "el CP869" + echo "el_GR CP869" + # ISO-8859-8 languages + echo "he CP862" + echo "he_IL CP862" + # ISO-8859-9 languages + echo "tr CP857" + echo "tr_TR CP857" + # Japanese + echo "ja CP932" + echo "ja_JP CP932" + # Chinese + echo "zh_CN GBK" + echo "zh_TW CP950" # not CP938 ?? + # Korean + echo "kr CP949" # not CP934 ?? + echo "kr_KR CP949" # not CP934 ?? + # Thai + echo "th CP874" + echo "th_TH CP874" + # Other + echo "eo CP850" + echo "eo_EO CP850" + ;; +esac diff --git a/gettext-tools/gnulib-lib/copy-acl.c b/gettext-tools/gnulib-lib/copy-acl.c new file mode 100644 index 0000000..eebb359 --- /dev/null +++ b/gettext-tools/gnulib-lib/copy-acl.c @@ -0,0 +1,61 @@ +/* copy-acl.c - copy access control list from one file to another file + + Copyright (C) 2002-2003, 2005-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + Written by Paul Eggert, Andreas Grünbacher, and Bruno Haible. */ + +#include + +#include "acl.h" + +#include + +#include "quote.h" +#include "error.h" +#include "gettext.h" +#define _(msgid) gettext (msgid) + + +/* Copy access control lists from one file to another. If SOURCE_DESC is + a valid file descriptor, use file descriptor operations, else use + filename based operations on SRC_NAME. Likewise for DEST_DESC and + DST_NAME. + If access control lists are not available, fchmod the target file to + MODE. Also sets the non-permission bits of the destination file + (S_ISUID, S_ISGID, S_ISVTX) to those from MODE if any are set. + Return 0 if successful, otherwise output a diagnostic and return a + negative error code. */ + +int +copy_acl (const char *src_name, int source_desc, const char *dst_name, + int dest_desc, mode_t mode) +{ + int ret = qcopy_acl (src_name, source_desc, dst_name, dest_desc, mode); + switch (ret) + { + case -2: + error (0, errno, "%s", quote (src_name)); + break; + + case -1: + error (0, errno, _("preserving permissions for %s"), quote (dst_name)); + break; + + default: + break; + } + return ret; +} diff --git a/gettext-tools/gnulib-lib/copy-file.c b/gettext-tools/gnulib-lib/copy-file.c new file mode 100644 index 0000000..488cc94 --- /dev/null +++ b/gettext-tools/gnulib-lib/copy-file.c @@ -0,0 +1,218 @@ +/* Copying of files. + Copyright (C) 2001-2003, 2006-2007, 2009-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2001. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + + +#include + +/* Specification. */ +#include "copy-file.h" + +#include +#include +#include +#include +#include +#include + +#if HAVE_UTIME || HAVE_UTIMES +# if HAVE_UTIME_H +# include +# else +# include +# endif +#endif + +#include "error.h" +#include "ignore-value.h" +#include "safe-read.h" +#include "full-write.h" +#include "acl.h" +#include "binary-io.h" +#include "quote.h" +#include "gettext.h" +#include "xalloc.h" + +#define _(str) gettext (str) + +enum { IO_SIZE = 32 * 1024 }; + +int +qcopy_file_preserving (const char *src_filename, const char *dest_filename) +{ + int err = 0; + int src_fd; + struct stat statbuf; + int mode; + int dest_fd; + char *buf = xmalloc (IO_SIZE); + + src_fd = open (src_filename, O_RDONLY | O_BINARY); + if (src_fd < 0) + { + err = GL_COPY_ERR_OPEN_READ; + goto error; + } + if (fstat (src_fd, &statbuf) < 0) + { + err = GL_COPY_ERR_OPEN_READ; + goto error_src; + } + + mode = statbuf.st_mode & 07777; + + dest_fd = open (dest_filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0600); + if (dest_fd < 0) + { + err = GL_COPY_ERR_OPEN_BACKUP_WRITE; + goto error_src; + } + + /* Copy the file contents. */ + for (;;) + { + size_t n_read = safe_read (src_fd, buf, IO_SIZE); + if (n_read == SAFE_READ_ERROR) + { + err = GL_COPY_ERR_READ; + goto error_src_dest; + } + if (n_read == 0) + break; + + if (full_write (dest_fd, buf, n_read) < n_read) + { + err = GL_COPY_ERR_WRITE; + goto error_src_dest; + } + } + + free (buf); + +#if !USE_ACL + if (close (dest_fd) < 0) + { + err = GL_COPY_ERR_WRITE; + goto error_src; + } + if (close (src_fd) < 0) + { + err = GL_COPY_ERR_AFTER_READ; + goto error; + } +#endif + + /* Preserve the access and modification times. */ +#if HAVE_UTIME + { + struct utimbuf ut; + + ut.actime = statbuf.st_atime; + ut.modtime = statbuf.st_mtime; + utime (dest_filename, &ut); + } +#elif HAVE_UTIMES + { + struct timeval ut[2]; + + ut[0].tv_sec = statbuf.st_atime; ut[0].tv_usec = 0; + ut[1].tv_sec = statbuf.st_mtime; ut[1].tv_usec = 0; + utimes (dest_filename, &ut); + } +#endif + +#if HAVE_CHOWN + /* Preserve the owner and group. */ + ignore_value (chown (dest_filename, statbuf.st_uid, statbuf.st_gid)); +#endif + + /* Preserve the access permissions. */ +#if USE_ACL + switch (qcopy_acl (src_filename, src_fd, dest_filename, dest_fd, mode)) + { + case -2: + err = GL_COPY_ERR_GET_ACL; + goto error_src_dest; + case -1: + err = GL_COPY_ERR_SET_ACL; + goto error_src_dest; + } +#else + chmod (dest_filename, mode); +#endif + +#if USE_ACL + if (close (dest_fd) < 0) + { + err = GL_COPY_ERR_WRITE; + goto error_src; + } + if (close (src_fd) < 0) + { + err = GL_COPY_ERR_AFTER_READ; + goto error; + } +#endif + + return 0; + + error_src_dest: + close (dest_fd); + error_src: + close (src_fd); + error: + return err; +} + +void +copy_file_preserving (const char *src_filename, const char *dest_filename) +{ + switch (qcopy_file_preserving (src_filename, dest_filename)) + { + case 0: + return; + + case GL_COPY_ERR_OPEN_READ: + error (EXIT_FAILURE, errno, _("error while opening %s for reading"), + quote (src_filename)); + + case GL_COPY_ERR_OPEN_BACKUP_WRITE: + error (EXIT_FAILURE, errno, _("cannot open backup file %s for writing"), + quote (dest_filename)); + + case GL_COPY_ERR_READ: + error (EXIT_FAILURE, errno, _("error reading %s"), + quote (src_filename)); + + case GL_COPY_ERR_WRITE: + error (EXIT_FAILURE, errno, _("error writing %s"), + quote (dest_filename)); + + case GL_COPY_ERR_AFTER_READ: + error (EXIT_FAILURE, errno, _("error after reading %s"), + quote (src_filename)); + + case GL_COPY_ERR_GET_ACL: + error (EXIT_FAILURE, errno, "%s", quote (src_filename)); + + case GL_COPY_ERR_SET_ACL: + error (EXIT_FAILURE, errno, _("preserving permissions for %s"), + quote (dest_filename)); + + default: + abort (); + } +} diff --git a/gettext-tools/gnulib-lib/copy-file.h b/gettext-tools/gnulib-lib/copy-file.h new file mode 100644 index 0000000..0fa24be --- /dev/null +++ b/gettext-tools/gnulib-lib/copy-file.h @@ -0,0 +1,54 @@ +/* Copying of files. + Copyright (C) 2001-2003, 2009-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2001. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Error codes returned by qcopy_file_preserving. */ +enum +{ + GL_COPY_ERR_OPEN_READ = -1, + GL_COPY_ERR_OPEN_BACKUP_WRITE = -2, + GL_COPY_ERR_READ = -3, + GL_COPY_ERR_WRITE = -4, + GL_COPY_ERR_AFTER_READ = -5, + GL_COPY_ERR_GET_ACL = -6, + GL_COPY_ERR_SET_ACL = -7 +}; + +/* Copy a regular file: from src_filename to dest_filename. + The destination file is assumed to be a backup file. + Modification times, owner, group and access permissions are preserved as + far as possible. + Return 0 if successful, otherwise set errno and return one of the error + codes above. */ +extern int qcopy_file_preserving (const char *src_filename, const char *dest_filename); + +/* Copy a regular file: from src_filename to dest_filename. + The destination file is assumed to be a backup file. + Modification times, owner, group and access permissions are preserved as + far as possible. + Exit upon failure. */ +extern void copy_file_preserving (const char *src_filename, const char *dest_filename); + + +#ifdef __cplusplus +} +#endif diff --git a/gettext-tools/gnulib-lib/csharpcomp.c b/gettext-tools/gnulib-lib/csharpcomp.c new file mode 100644 index 0000000..42d34fa --- /dev/null +++ b/gettext-tools/gnulib-lib/csharpcomp.c @@ -0,0 +1,573 @@ +/* Compile a C# program. + Copyright (C) 2003-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2003. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include +#include + +/* Specification. */ +#include "csharpcomp.h" + +#include +#include +#include +#include + +#include "execute.h" +#include "spawn-pipe.h" +#include "wait-process.h" +#include "sh-quote.h" +#include "safe-read.h" +#include "xmalloca.h" +#include "error.h" +#include "gettext.h" + +#define _(str) gettext (str) + + +/* Survey of C# compilers. + + Program from + + cscc pnet + mcs mono + csc sscli + + We try the CIL interpreters in the following order: + 1. "cscc", because it is a completely free system. + 2. "mcs", because it is a free system but doesn't integrate so well + with Unix. (Command line options start with / instead of -. Errors go + to stdout instead of stderr. Source references are printed as + "file(lineno)" instead of "file:lineno:".) + 3. "csc", although it is not free, because it is a kind of "reference + implementation" of C#. + But the order can be changed through the --enable-csharp configuration + option. + */ + +static int +compile_csharp_using_pnet (const char * const *sources, + unsigned int sources_count, + const char * const *libdirs, + unsigned int libdirs_count, + const char * const *libraries, + unsigned int libraries_count, + const char *output_file, bool output_is_library, + bool optimize, bool debug, + bool verbose) +{ + static bool cscc_tested; + static bool cscc_present; + + if (!cscc_tested) + { + /* Test for presence of cscc: + "cscc --version >/dev/null 2>/dev/null" */ + char *argv[3]; + int exitstatus; + + argv[0] = "cscc"; + argv[1] = "--version"; + argv[2] = NULL; + exitstatus = execute ("cscc", "cscc", argv, false, false, true, true, + true, false, NULL); + cscc_present = (exitstatus == 0); + cscc_tested = true; + } + + if (cscc_present) + { + unsigned int argc; + char **argv; + char **argp; + int exitstatus; + unsigned int i; + + argc = + 1 + (output_is_library ? 1 : 0) + 2 + 2 * libdirs_count + + 2 * libraries_count + (optimize ? 1 : 0) + (debug ? 1 : 0) + + sources_count; + argv = (char **) xmalloca ((argc + 1) * sizeof (char *)); + + argp = argv; + *argp++ = "cscc"; + if (output_is_library) + *argp++ = "-shared"; + *argp++ = "-o"; + *argp++ = (char *) output_file; + for (i = 0; i < libdirs_count; i++) + { + *argp++ = "-L"; + *argp++ = (char *) libdirs[i]; + } + for (i = 0; i < libraries_count; i++) + { + *argp++ = "-l"; + *argp++ = (char *) libraries[i]; + } + if (optimize) + *argp++ = "-O"; + if (debug) + *argp++ = "-g"; + for (i = 0; i < sources_count; i++) + { + const char *source_file = sources[i]; + if (strlen (source_file) >= 10 + && memcmp (source_file + strlen (source_file) - 10, ".resources", + 10) == 0) + { + char *option = (char *) xmalloca (12 + strlen (source_file) + 1); + + memcpy (option, "-fresources=", 12); + strcpy (option + 12, source_file); + *argp++ = option; + } + else + *argp++ = (char *) source_file; + } + *argp = NULL; + /* Ensure argv length was correctly calculated. */ + if (argp - argv != argc) + abort (); + + if (verbose) + { + char *command = shell_quote_argv (argv); + printf ("%s\n", command); + free (command); + } + + exitstatus = execute ("cscc", "cscc", argv, false, false, false, false, + true, true, NULL); + + for (i = 0; i < sources_count; i++) + if (argv[argc - sources_count + i] != sources[i]) + freea (argv[argc - sources_count + i]); + freea (argv); + + return (exitstatus != 0); + } + else + return -1; +} + +static int +compile_csharp_using_mono (const char * const *sources, + unsigned int sources_count, + const char * const *libdirs, + unsigned int libdirs_count, + const char * const *libraries, + unsigned int libraries_count, + const char *output_file, bool output_is_library, + bool optimize, bool debug, + bool verbose) +{ + static bool mcs_tested; + static bool mcs_present; + + if (!mcs_tested) + { + /* Test for presence of mcs: + "mcs --version >/dev/null 2>/dev/null" + and (to exclude an unrelated 'mcs' program on QNX 6) + "mcs --version 2>/dev/null | grep Mono >/dev/null" */ + char *argv[3]; + pid_t child; + int fd[1]; + int exitstatus; + + argv[0] = "mcs"; + argv[1] = "--version"; + argv[2] = NULL; + child = create_pipe_in ("mcs", "mcs", argv, DEV_NULL, true, true, false, + fd); + mcs_present = false; + if (child != -1) + { + /* Read the subprocess output, and test whether it contains the + string "Mono". */ + char c[4]; + size_t count = 0; + + while (safe_read (fd[0], &c[count], 1) > 0) + { + count++; + if (count == 4) + { + if (memcmp (c, "Mono", 4) == 0) + mcs_present = true; + c[0] = c[1]; c[1] = c[2]; c[2] = c[3]; + count--; + } + } + + close (fd[0]); + + /* Remove zombie process from process list, and retrieve exit + status. */ + exitstatus = + wait_subprocess (child, "mcs", false, true, true, false, NULL); + if (exitstatus != 0) + mcs_present = false; + } + mcs_tested = true; + } + + if (mcs_present) + { + unsigned int argc; + char **argv; + char **argp; + pid_t child; + int fd[1]; + FILE *fp; + char *line[2]; + size_t linesize[2]; + size_t linelen[2]; + unsigned int l; + int exitstatus; + unsigned int i; + + argc = + 1 + (output_is_library ? 1 : 0) + 1 + libdirs_count + libraries_count + + (debug ? 1 : 0) + sources_count; + argv = (char **) xmalloca ((argc + 1) * sizeof (char *)); + + argp = argv; + *argp++ = "mcs"; + if (output_is_library) + *argp++ = "-target:library"; + { + char *option = (char *) xmalloca (5 + strlen (output_file) + 1); + memcpy (option, "-out:", 5); + strcpy (option + 5, output_file); + *argp++ = option; + } + for (i = 0; i < libdirs_count; i++) + { + char *option = (char *) xmalloca (5 + strlen (libdirs[i]) + 1); + memcpy (option, "-lib:", 5); + strcpy (option + 5, libdirs[i]); + *argp++ = option; + } + for (i = 0; i < libraries_count; i++) + { + char *option = (char *) xmalloca (11 + strlen (libraries[i]) + 4 + 1); + memcpy (option, "-reference:", 11); + memcpy (option + 11, libraries[i], strlen (libraries[i])); + strcpy (option + 11 + strlen (libraries[i]), ".dll"); + *argp++ = option; + } + if (debug) + *argp++ = "-debug"; + for (i = 0; i < sources_count; i++) + { + const char *source_file = sources[i]; + if (strlen (source_file) >= 10 + && memcmp (source_file + strlen (source_file) - 10, ".resources", + 10) == 0) + { + char *option = (char *) xmalloca (10 + strlen (source_file) + 1); + + memcpy (option, "-resource:", 10); + strcpy (option + 10, source_file); + *argp++ = option; + } + else + *argp++ = (char *) source_file; + } + *argp = NULL; + /* Ensure argv length was correctly calculated. */ + if (argp - argv != argc) + abort (); + + if (verbose) + { + char *command = shell_quote_argv (argv); + printf ("%s\n", command); + free (command); + } + + child = create_pipe_in ("mcs", "mcs", argv, NULL, false, true, true, fd); + + /* Read the subprocess output, copying it to stderr. Drop the last + line if it starts with "Compilation succeeded". */ + fp = fdopen (fd[0], "r"); + if (fp == NULL) + error (EXIT_FAILURE, errno, _("fdopen() failed")); + line[0] = NULL; linesize[0] = 0; + line[1] = NULL; linesize[1] = 0; + l = 0; + for (;;) + { + linelen[l] = getline (&line[l], &linesize[l], fp); + if (linelen[l] == (size_t)(-1)) + break; + l = (l + 1) % 2; + if (line[l] != NULL) + fwrite (line[l], 1, linelen[l], stderr); + } + l = (l + 1) % 2; + if (line[l] != NULL + && !(linelen[l] >= 21 + && memcmp (line[l], "Compilation succeeded", 21) == 0)) + fwrite (line[l], 1, linelen[l], stderr); + if (line[0] != NULL) + free (line[0]); + if (line[1] != NULL) + free (line[1]); + fclose (fp); + + /* Remove zombie process from process list, and retrieve exit status. */ + exitstatus = + wait_subprocess (child, "mcs", false, false, true, true, NULL); + + for (i = 1 + (output_is_library ? 1 : 0); + i < 1 + (output_is_library ? 1 : 0) + + 1 + libdirs_count + libraries_count; + i++) + freea (argv[i]); + for (i = 0; i < sources_count; i++) + if (argv[argc - sources_count + i] != sources[i]) + freea (argv[argc - sources_count + i]); + freea (argv); + + return (exitstatus != 0); + } + else + return -1; +} + +static int +compile_csharp_using_sscli (const char * const *sources, + unsigned int sources_count, + const char * const *libdirs, + unsigned int libdirs_count, + const char * const *libraries, + unsigned int libraries_count, + const char *output_file, bool output_is_library, + bool optimize, bool debug, + bool verbose) +{ + static bool csc_tested; + static bool csc_present; + + if (!csc_tested) + { + /* Test for presence of csc: + "csc -help >/dev/null 2>/dev/null \ + && ! { csc -help 2>/dev/null | grep -i chicken > /dev/null; }" */ + char *argv[3]; + pid_t child; + int fd[1]; + int exitstatus; + + argv[0] = "csc"; + argv[1] = "-help"; + argv[2] = NULL; + child = create_pipe_in ("csc", "csc", argv, DEV_NULL, true, true, false, + fd); + csc_present = false; + if (child != -1) + { + /* Read the subprocess output, and test whether it contains the + string "chicken". */ + char c[7]; + size_t count = 0; + + csc_present = true; + while (safe_read (fd[0], &c[count], 1) > 0) + { + if (c[count] >= 'A' && c[count] <= 'Z') + c[count] += 'a' - 'A'; + count++; + if (count == 7) + { + if (memcmp (c, "chicken", 7) == 0) + csc_present = false; + c[0] = c[1]; c[1] = c[2]; c[2] = c[3]; + c[3] = c[4]; c[4] = c[5]; c[5] = c[6]; + count--; + } + } + + close (fd[0]); + + /* Remove zombie process from process list, and retrieve exit + status. */ + exitstatus = + wait_subprocess (child, "csc", false, true, true, false, NULL); + if (exitstatus != 0) + csc_present = false; + } + csc_tested = true; + } + + if (csc_present) + { + unsigned int argc; + char **argv; + char **argp; + int exitstatus; + unsigned int i; + + argc = + 1 + 1 + 1 + libdirs_count + libraries_count + + (optimize ? 1 : 0) + (debug ? 1 : 0) + sources_count; + argv = (char **) xmalloca ((argc + 1) * sizeof (char *)); + + argp = argv; + *argp++ = "csc"; + *argp++ = + (char *) (output_is_library ? "-target:library" : "-target:exe"); + { + char *option = (char *) xmalloca (5 + strlen (output_file) + 1); + memcpy (option, "-out:", 5); + strcpy (option + 5, output_file); + *argp++ = option; + } + for (i = 0; i < libdirs_count; i++) + { + char *option = (char *) xmalloca (5 + strlen (libdirs[i]) + 1); + memcpy (option, "-lib:", 5); + strcpy (option + 5, libdirs[i]); + *argp++ = option; + } + for (i = 0; i < libraries_count; i++) + { + char *option = (char *) xmalloca (11 + strlen (libraries[i]) + 4 + 1); + memcpy (option, "-reference:", 11); + memcpy (option + 11, libraries[i], strlen (libraries[i])); + strcpy (option + 11 + strlen (libraries[i]), ".dll"); + *argp++ = option; + } + if (optimize) + *argp++ = "-optimize+"; + if (debug) + *argp++ = "-debug+"; + for (i = 0; i < sources_count; i++) + { + const char *source_file = sources[i]; + if (strlen (source_file) >= 10 + && memcmp (source_file + strlen (source_file) - 10, ".resources", + 10) == 0) + { + char *option = (char *) xmalloca (10 + strlen (source_file) + 1); + + memcpy (option, "-resource:", 10); + strcpy (option + 10, source_file); + *argp++ = option; + } + else + *argp++ = (char *) source_file; + } + *argp = NULL; + /* Ensure argv length was correctly calculated. */ + if (argp - argv != argc) + abort (); + + if (verbose) + { + char *command = shell_quote_argv (argv); + printf ("%s\n", command); + free (command); + } + + exitstatus = execute ("csc", "csc", argv, false, false, false, false, + true, true, NULL); + + for (i = 2; i < 3 + libdirs_count + libraries_count; i++) + freea (argv[i]); + for (i = 0; i < sources_count; i++) + if (argv[argc - sources_count + i] != sources[i]) + freea (argv[argc - sources_count + i]); + freea (argv); + + return (exitstatus != 0); + } + else + return -1; +} + +bool +compile_csharp_class (const char * const *sources, + unsigned int sources_count, + const char * const *libdirs, + unsigned int libdirs_count, + const char * const *libraries, + unsigned int libraries_count, + const char *output_file, + bool optimize, bool debug, + bool verbose) +{ + bool output_is_library = + (strlen (output_file) >= 4 + && memcmp (output_file + strlen (output_file) - 4, ".dll", 4) == 0); + int result; + + /* First try the C# implementation specified through --enable-csharp. */ +#if CSHARP_CHOICE_PNET + result = compile_csharp_using_pnet (sources, sources_count, + libdirs, libdirs_count, + libraries, libraries_count, + output_file, output_is_library, + optimize, debug, verbose); + if (result >= 0) + return (bool) result; +#endif + +#if CSHARP_CHOICE_MONO + result = compile_csharp_using_mono (sources, sources_count, + libdirs, libdirs_count, + libraries, libraries_count, + output_file, output_is_library, + optimize, debug, verbose); + if (result >= 0) + return (bool) result; +#endif + + /* Then try the remaining C# implementations in our standard order. */ +#if !CSHARP_CHOICE_PNET + result = compile_csharp_using_pnet (sources, sources_count, + libdirs, libdirs_count, + libraries, libraries_count, + output_file, output_is_library, + optimize, debug, verbose); + if (result >= 0) + return (bool) result; +#endif + +#if !CSHARP_CHOICE_MONO + result = compile_csharp_using_mono (sources, sources_count, + libdirs, libdirs_count, + libraries, libraries_count, + output_file, output_is_library, + optimize, debug, verbose); + if (result >= 0) + return (bool) result; +#endif + + result = compile_csharp_using_sscli (sources, sources_count, + libdirs, libdirs_count, + libraries, libraries_count, + output_file, output_is_library, + optimize, debug, verbose); + if (result >= 0) + return (bool) result; + + error (0, 0, _("C# compiler not found, try installing pnet")); + return true; +} diff --git a/gettext-tools/gnulib-lib/csharpcomp.h b/gettext-tools/gnulib-lib/csharpcomp.h new file mode 100644 index 0000000..ae31bfe --- /dev/null +++ b/gettext-tools/gnulib-lib/csharpcomp.h @@ -0,0 +1,40 @@ +/* Compile a C# program. + Copyright (C) 2003, 2009-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2003. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _CSHARPCOMP_H +#define _CSHARPCOMP_H + +#include + +/* Compile a set of C# source files to bytecode. + sources is an array of source file names, including resource files. + libdirs is a list of directories to be searched for libraries. + libraries is a list of libraries on which the program depends. + output_file is the name of the output file; it should end in .exe or .dll. + If verbose, the command to be executed will be printed. + Return false if OK, true on error. */ +extern bool compile_csharp_class (const char * const *sources, + unsigned int sources_count, + const char * const *libdirs, + unsigned int libdirs_count, + const char * const *libraries, + unsigned int libraries_count, + const char *output_file, + bool optimize, bool debug, + bool verbose); + +#endif /* _CSHARPCOMP_H */ diff --git a/gettext-tools/gnulib-lib/csharpexec.c b/gettext-tools/gnulib-lib/csharpexec.c new file mode 100644 index 0000000..138e92b --- /dev/null +++ b/gettext-tools/gnulib-lib/csharpexec.c @@ -0,0 +1,345 @@ +/* Execute a C# program. + Copyright (C) 2003-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2003. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include +#include + +/* Specification. */ +#include "csharpexec.h" + +#include +#include + +#include "execute.h" +#include "sh-quote.h" +#include "xmalloca.h" +#include "error.h" +#include "gettext.h" + +/* Handling of MONO_PATH is just like Java CLASSPATH. */ +#define CLASSPATHVAR "MONO_PATH" +#define new_classpath new_monopath +#define set_classpath set_monopath +#define reset_classpath reset_monopath +#include "classpath.h" +#include "classpath.c" +#undef reset_classpath +#undef set_classpath +#undef new_classpath +#undef CLASSPATHVAR + +/* Handling of clix' PATH variable is just like Java CLASSPATH. */ +#if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ + /* Native Windows, Cygwin */ + #define CLASSPATHVAR "PATH" +#elif defined __APPLE__ && defined __MACH__ + /* Mac OS X */ + #define CLASSPATHVAR "DYLD_LIBRARY_PATH" +#else + /* Normal Unix */ + #define CLASSPATHVAR "LD_LIBRARY_PATH" +#endif +#define new_classpath new_clixpath +#define set_classpath set_clixpath +#define reset_classpath reset_clixpath +#include "classpath.h" +#include "classpath.c" +#undef reset_classpath +#undef set_classpath +#undef new_classpath +#undef CLASSPATHVAR + +#define _(str) gettext (str) + + +/* Survey of CIL interpreters. + + Program from + + ilrun pnet + mono mono + clix sscli + + With Mono, the MONO_PATH is a colon separated list of pathnames. (On + Windows: semicolon separated list of pathnames.) + + We try the CIL interpreters in the following order: + 1. "ilrun", because it is a completely free system. + 2. "mono", because it is a partially free system but doesn't integrate + well with Unix. + 3. "clix", although it is not free, because it is a kind of "reference + implementation" of C#. + But the order can be changed through the --enable-csharp configuration + option. + */ + +static int +execute_csharp_using_pnet (const char *assembly_path, + const char * const *libdirs, + unsigned int libdirs_count, + const char * const *args, unsigned int nargs, + bool verbose, bool quiet, + execute_fn *executer, void *private_data) +{ + static bool ilrun_tested; + static bool ilrun_present; + + if (!ilrun_tested) + { + /* Test for presence of ilrun: + "ilrun --version >/dev/null 2>/dev/null" */ + char *argv[3]; + int exitstatus; + + argv[0] = "ilrun"; + argv[1] = "--version"; + argv[2] = NULL; + exitstatus = execute ("ilrun", "ilrun", argv, false, false, true, true, + true, false, NULL); + ilrun_present = (exitstatus == 0); + ilrun_tested = true; + } + + if (ilrun_present) + { + unsigned int argc; + char **argv; + char **argp; + unsigned int i; + bool err; + + argc = 1 + 2 * libdirs_count + 1 + nargs; + argv = (char **) xmalloca ((argc + 1) * sizeof (char *)); + + argp = argv; + *argp++ = "ilrun"; + for (i = 0; i < libdirs_count; i++) + { + *argp++ = "-L"; + *argp++ = (char *) libdirs[i]; + } + *argp++ = (char *) assembly_path; + for (i = 0; i < nargs; i++) + *argp++ = (char *) args[i]; + *argp = NULL; + /* Ensure argv length was correctly calculated. */ + if (argp - argv != argc) + abort (); + + if (verbose) + { + char *command = shell_quote_argv (argv); + printf ("%s\n", command); + free (command); + } + + err = executer ("ilrun", "ilrun", argv, private_data); + + freea (argv); + + return err; + } + else + return -1; +} + +static int +execute_csharp_using_mono (const char *assembly_path, + const char * const *libdirs, + unsigned int libdirs_count, + const char * const *args, unsigned int nargs, + bool verbose, bool quiet, + execute_fn *executer, void *private_data) +{ + static bool mono_tested; + static bool mono_present; + + if (!mono_tested) + { + /* Test for presence of mono: + "mono --version >/dev/null 2>/dev/null" */ + char *argv[3]; + int exitstatus; + + argv[0] = "mono"; + argv[1] = "--version"; + argv[2] = NULL; + exitstatus = execute ("mono", "mono", argv, false, false, true, true, + true, false, NULL); + mono_present = (exitstatus == 0); + mono_tested = true; + } + + if (mono_present) + { + char *old_monopath; + char **argv = (char **) xmalloca ((2 + nargs + 1) * sizeof (char *)); + unsigned int i; + bool err; + + /* Set MONO_PATH. */ + old_monopath = set_monopath (libdirs, libdirs_count, false, verbose); + + argv[0] = "mono"; + argv[1] = (char *) assembly_path; + for (i = 0; i <= nargs; i++) + argv[2 + i] = (char *) args[i]; + + if (verbose) + { + char *command = shell_quote_argv (argv); + printf ("%s\n", command); + free (command); + } + + err = executer ("mono", "mono", argv, private_data); + + /* Reset MONO_PATH. */ + reset_monopath (old_monopath); + + freea (argv); + + return err; + } + else + return -1; +} + +static int +execute_csharp_using_sscli (const char *assembly_path, + const char * const *libdirs, + unsigned int libdirs_count, + const char * const *args, unsigned int nargs, + bool verbose, bool quiet, + execute_fn *executer, void *private_data) +{ + static bool clix_tested; + static bool clix_present; + + if (!clix_tested) + { + /* Test for presence of clix: + "clix >/dev/null 2>/dev/null ; test $? = 1" */ + char *argv[2]; + int exitstatus; + + argv[0] = "clix"; + argv[1] = NULL; + exitstatus = execute ("clix", "clix", argv, false, false, true, true, + true, false, NULL); + clix_present = (exitstatus == 0 || exitstatus == 1); + clix_tested = true; + } + + if (clix_present) + { + char *old_clixpath; + char **argv = (char **) xmalloca ((2 + nargs + 1) * sizeof (char *)); + unsigned int i; + bool err; + + /* Set clix' PATH variable. */ + old_clixpath = set_clixpath (libdirs, libdirs_count, false, verbose); + + argv[0] = "clix"; + argv[1] = (char *) assembly_path; + for (i = 0; i <= nargs; i++) + argv[2 + i] = (char *) args[i]; + + if (verbose) + { + char *command = shell_quote_argv (argv); + printf ("%s\n", command); + free (command); + } + + err = executer ("clix", "clix", argv, private_data); + + /* Reset clix' PATH variable. */ + reset_clixpath (old_clixpath); + + freea (argv); + + return err; + } + else + return -1; +} + +bool +execute_csharp_program (const char *assembly_path, + const char * const *libdirs, + unsigned int libdirs_count, + const char * const *args, + bool verbose, bool quiet, + execute_fn *executer, void *private_data) +{ + unsigned int nargs; + int result; + + /* Count args. */ + { + const char * const *arg; + + for (nargs = 0, arg = args; *arg != NULL; nargs++, arg++) + ; + } + + /* First try the C# implementation specified through --enable-csharp. */ +#if CSHARP_CHOICE_PNET + result = execute_csharp_using_pnet (assembly_path, libdirs, libdirs_count, + args, nargs, verbose, quiet, + executer, private_data); + if (result >= 0) + return (bool) result; +#endif + +#if CSHARP_CHOICE_MONO + result = execute_csharp_using_mono (assembly_path, libdirs, libdirs_count, + args, nargs, verbose, quiet, + executer, private_data); + if (result >= 0) + return (bool) result; +#endif + + /* Then try the remaining C# implementations in our standard order. */ +#if !CSHARP_CHOICE_PNET + result = execute_csharp_using_pnet (assembly_path, libdirs, libdirs_count, + args, nargs, verbose, quiet, + executer, private_data); + if (result >= 0) + return (bool) result; +#endif + +#if !CSHARP_CHOICE_MONO + result = execute_csharp_using_mono (assembly_path, libdirs, libdirs_count, + args, nargs, verbose, quiet, + executer, private_data); + if (result >= 0) + return (bool) result; +#endif + + result = execute_csharp_using_sscli (assembly_path, libdirs, libdirs_count, + args, nargs, verbose, quiet, + executer, private_data); + if (result >= 0) + return (bool) result; + + if (!quiet) + error (0, 0, _("C# virtual machine not found, try installing pnet")); + return true; +} diff --git a/gettext-tools/gnulib-lib/csharpexec.h b/gettext-tools/gnulib-lib/csharpexec.h new file mode 100644 index 0000000..bfc66fa --- /dev/null +++ b/gettext-tools/gnulib-lib/csharpexec.h @@ -0,0 +1,43 @@ +/* Execute a C# program. + Copyright (C) 2003, 2009-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2003. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _CSHARPEXEC_H +#define _CSHARPEXEC_H + +#include + +typedef bool execute_fn (const char *progname, + const char *prog_path, char **prog_argv, + void *private_data); + +/* Execute a C# program. + assembly_path is the assembly's pathname (= program name with .exe). + libdirs is a list of directories to be searched for libraries. + args is a NULL terminated list of arguments to be passed to the program. + If verbose, the command to be executed will be printed. + Then the command is passed to the execute function together with the + private_data argument. This function returns false if OK, true on error. + Return false if OK, true on error. + If quiet, error messages will not be printed. */ +extern bool execute_csharp_program (const char *assembly_path, + const char * const *libdirs, + unsigned int libdirs_count, + const char * const *args, + bool verbose, bool quiet, + execute_fn *executer, void *private_data); + +#endif /* _CSHARPEXEC_H */ diff --git a/gettext-tools/gnulib-lib/diffseq.h b/gettext-tools/gnulib-lib/diffseq.h new file mode 100644 index 0000000..02ef9f2 --- /dev/null +++ b/gettext-tools/gnulib-lib/diffseq.h @@ -0,0 +1,425 @@ +/* Analyze differences between two vectors. + + Copyright (C) 1988-1989, 1992-1995, 2001-2004, 2006-2014 Free Software + Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + + +/* The basic idea is to consider two vectors as similar if, when + transforming the first vector into the second vector through a + sequence of edits (inserts and deletes of one element each), + this sequence is short - or equivalently, if the ordered list + of elements that are untouched by these edits is long. For a + good introduction to the subject, read about the "Levenshtein + distance" in Wikipedia. + + The basic algorithm is described in: + "An O(ND) Difference Algorithm and its Variations", Eugene W. Myers, + Algorithmica Vol. 1, 1986, pp. 251-266, + . + See especially section 4.2, which describes the variation used below. + + The basic algorithm was independently discovered as described in: + "Algorithms for Approximate String Matching", Esko Ukkonen, + Information and Control Vol. 64, 1985, pp. 100-118, + . */ + +/* Before including this file, you need to define: + ELEMENT The element type of the vectors being compared. + EQUAL A two-argument macro that tests two elements for + equality. + OFFSET A signed integer type sufficient to hold the + difference between two indices. Usually + something like ssize_t. + EXTRA_CONTEXT_FIELDS Declarations of fields for 'struct context'. + NOTE_DELETE(ctxt, xoff) Record the removal of the object xvec[xoff]. + NOTE_INSERT(ctxt, yoff) Record the insertion of the object yvec[yoff]. + EARLY_ABORT(ctxt) (Optional) A boolean expression that triggers an + early abort of the computation. + USE_HEURISTIC (Optional) Define if you want to support the + heuristic for large vectors. + It is also possible to use this file with abstract arrays. In this case, + xvec and yvec are not represented in memory. They only exist conceptually. + In this case, the list of defines above is amended as follows: + ELEMENT Undefined. + EQUAL Undefined. + XVECREF_YVECREF_EQUAL(ctxt, xoff, yoff) + A three-argument macro: References xvec[xoff] and + yvec[yoff] and tests these elements for equality. + Before including this file, you also need to include: + #include + #include + #include "minmax.h" + */ + +/* Maximum value of type OFFSET. */ +#define OFFSET_MAX \ + ((((OFFSET)1 << (sizeof (OFFSET) * CHAR_BIT - 2)) - 1) * 2 + 1) + +/* Default to no early abort. */ +#ifndef EARLY_ABORT +# define EARLY_ABORT(ctxt) false +#endif + +/* Use this to suppress gcc's "...may be used before initialized" warnings. + Beware: The Code argument must not contain commas. */ +#ifndef IF_LINT +# ifdef lint +# define IF_LINT(Code) Code +# else +# define IF_LINT(Code) /* empty */ +# endif +#endif + +/* As above, but when Code must contain one comma. */ +#ifndef IF_LINT2 +# ifdef lint +# define IF_LINT2(Code1, Code2) Code1, Code2 +# else +# define IF_LINT2(Code1, Code2) /* empty */ +# endif +#endif + +/* + * Context of comparison operation. + */ +struct context +{ + #ifdef ELEMENT + /* Vectors being compared. */ + ELEMENT const *xvec; + ELEMENT const *yvec; + #endif + + /* Extra fields. */ + EXTRA_CONTEXT_FIELDS + + /* Vector, indexed by diagonal, containing 1 + the X coordinate of the point + furthest along the given diagonal in the forward search of the edit + matrix. */ + OFFSET *fdiag; + + /* Vector, indexed by diagonal, containing the X coordinate of the point + furthest along the given diagonal in the backward search of the edit + matrix. */ + OFFSET *bdiag; + + #ifdef USE_HEURISTIC + /* This corresponds to the diff --speed-large-files flag. With this + heuristic, for vectors with a constant small density of changes, + the algorithm is linear in the vector size. */ + bool heuristic; + #endif + + /* Snakes bigger than this are considered "big". */ + #define SNAKE_LIMIT 20 +}; + +struct partition +{ + /* Midpoints of this partition. */ + OFFSET xmid; + OFFSET ymid; +}; + + +/* Find the midpoint of the shortest edit script for a specified portion + of the two vectors. + + Scan from the beginnings of the vectors, and simultaneously from the ends, + doing a breadth-first search through the space of edit-sequence. + When the two searches meet, we have found the midpoint of the shortest + edit sequence. + + Set *PART to the midpoint (XMID,YMID). The diagonal number + XMID - YMID equals the number of inserted elements minus the number + of deleted elements (counting only elements before the midpoint). + + This function assumes that the first elements of the specified portions + of the two vectors do not match, and likewise that the last elements do not + match. The caller must trim matching elements from the beginning and end + of the portions it is going to specify. + + If we return the "wrong" partitions, the worst this can do is cause + suboptimal diff output. It cannot cause incorrect diff output. */ + +static void +diag (OFFSET xoff, OFFSET xlim, OFFSET yoff, OFFSET ylim, + struct partition *part, struct context *ctxt) +{ + OFFSET *const fd = ctxt->fdiag; /* Give the compiler a chance. */ + OFFSET *const bd = ctxt->bdiag; /* Additional help for the compiler. */ +#ifdef ELEMENT + ELEMENT const *const xv = ctxt->xvec; /* Still more help for the compiler. */ + ELEMENT const *const yv = ctxt->yvec; /* And more and more . . . */ + #define XREF_YREF_EQUAL(x,y) EQUAL (xv[x], yv[y]) +#else + #define XREF_YREF_EQUAL(x,y) XVECREF_YVECREF_EQUAL (ctxt, x, y) +#endif + const OFFSET dmin = xoff - ylim; /* Minimum valid diagonal. */ + const OFFSET dmax = xlim - yoff; /* Maximum valid diagonal. */ + const OFFSET fmid = xoff - yoff; /* Center diagonal of top-down search. */ + const OFFSET bmid = xlim - ylim; /* Center diagonal of bottom-up search. */ + OFFSET fmin = fmid; + OFFSET fmax = fmid; /* Limits of top-down search. */ + OFFSET bmin = bmid; + OFFSET bmax = bmid; /* Limits of bottom-up search. */ + OFFSET c; /* Cost. */ + bool odd = (fmid - bmid) & 1; /* True if southeast corner is on an odd + diagonal with respect to the northwest. */ + + fd[fmid] = xoff; + bd[bmid] = xlim; + + for (c = 1;; ++c) + { + OFFSET d; /* Active diagonal. */ + bool big_snake _GL_UNUSED = false; + + /* Extend the top-down search by an edit step in each diagonal. */ + if (fmin > dmin) + fd[--fmin - 1] = -1; + else + ++fmin; + if (fmax < dmax) + fd[++fmax + 1] = -1; + else + --fmax; + for (d = fmax; d >= fmin; d -= 2) + { + OFFSET x; + OFFSET y; + OFFSET tlo = fd[d - 1]; + OFFSET thi = fd[d + 1]; + OFFSET x0 = tlo < thi ? thi : tlo + 1; + + for (x = x0, y = x0 - d; + x < xlim && y < ylim && XREF_YREF_EQUAL (x, y); + x++, y++) + continue; + if (x - x0 > SNAKE_LIMIT) + big_snake = true; + fd[d] = x; + if (odd && bmin <= d && d <= bmax && bd[d] <= x) + { + part->xmid = x; + part->ymid = y; + return; + } + } + + /* Similarly extend the bottom-up search. */ + if (bmin > dmin) + bd[--bmin - 1] = OFFSET_MAX; + else + ++bmin; + if (bmax < dmax) + bd[++bmax + 1] = OFFSET_MAX; + else + --bmax; + for (d = bmax; d >= bmin; d -= 2) + { + OFFSET x; + OFFSET y; + OFFSET tlo = bd[d - 1]; + OFFSET thi = bd[d + 1]; + OFFSET x0 = tlo < thi ? tlo : thi - 1; + + for (x = x0, y = x0 - d; + xoff < x && yoff < y && XREF_YREF_EQUAL (x - 1, y - 1); + x--, y--) + continue; + if (x0 - x > SNAKE_LIMIT) + big_snake = true; + bd[d] = x; + if (!odd && fmin <= d && d <= fmax && x <= fd[d]) + { + part->xmid = x; + part->ymid = y; + return; + } + } + +#ifdef USE_HEURISTIC + /* Heuristic: check occasionally for a diagonal that has made lots + of progress compared with the edit distance. If we have any + such, find the one that has made the most progress and return it + as if it had succeeded. + + With this heuristic, for vectors with a constant small density + of changes, the algorithm is linear in the vector size. */ + + if (200 < c && big_snake && ctxt->heuristic) + { + { + OFFSET best = 0; + + for (d = fmax; d >= fmin; d -= 2) + { + OFFSET dd = d - fmid; + OFFSET x = fd[d]; + OFFSET y = x - d; + OFFSET v = (x - xoff) * 2 - dd; + + if (v > 12 * (c + (dd < 0 ? -dd : dd))) + { + if (v > best + && xoff + SNAKE_LIMIT <= x && x < xlim + && yoff + SNAKE_LIMIT <= y && y < ylim) + { + /* We have a good enough best diagonal; now insist + that it end with a significant snake. */ + int k; + + for (k = 1; XREF_YREF_EQUAL (x - k, y - k); k++) + if (k == SNAKE_LIMIT) + { + best = v; + part->xmid = x; + part->ymid = y; + break; + } + } + } + } + if (best > 0) + return; + } + + { + OFFSET best = 0; + + for (d = bmax; d >= bmin; d -= 2) + { + OFFSET dd = d - bmid; + OFFSET x = bd[d]; + OFFSET y = x - d; + OFFSET v = (xlim - x) * 2 + dd; + + if (v > 12 * (c + (dd < 0 ? -dd : dd))) + { + if (v > best + && xoff < x && x <= xlim - SNAKE_LIMIT + && yoff < y && y <= ylim - SNAKE_LIMIT) + { + /* We have a good enough best diagonal; now insist + that it end with a significant snake. */ + int k; + + for (k = 0; XREF_YREF_EQUAL (x + k, y + k); k++) + if (k == SNAKE_LIMIT - 1) + { + best = v; + part->xmid = x; + part->ymid = y; + break; + } + } + } + } + if (best > 0) + return; + } + } +#endif /* USE_HEURISTIC */ + } + #undef XREF_YREF_EQUAL +} + + +/* Compare in detail contiguous subsequences of the two vectors + which are known, as a whole, to match each other. + + The subsequence of vector 0 is [XOFF, XLIM) and likewise for vector 1. + + Note that XLIM, YLIM are exclusive bounds. All indices into the vectors + are origin-0. + + The results are recorded by invoking NOTE_DELETE and NOTE_INSERT. + + Return false if terminated normally, or true if terminated through early + abort. */ + +static bool +compareseq (OFFSET xoff, OFFSET xlim, OFFSET yoff, OFFSET ylim, + struct context *ctxt) +{ +#ifdef ELEMENT + ELEMENT const *xv = ctxt->xvec; /* Help the compiler. */ + ELEMENT const *yv = ctxt->yvec; + #define XREF_YREF_EQUAL(x,y) EQUAL (xv[x], yv[y]) +#else + #define XREF_YREF_EQUAL(x,y) XVECREF_YVECREF_EQUAL (ctxt, x, y) +#endif + + /* Slide down the bottom initial diagonal. */ + while (xoff < xlim && yoff < ylim && XREF_YREF_EQUAL (xoff, yoff)) + { + xoff++; + yoff++; + } + + /* Slide up the top initial diagonal. */ + while (xoff < xlim && yoff < ylim && XREF_YREF_EQUAL (xlim - 1, ylim - 1)) + { + xlim--; + ylim--; + } + + /* Handle simple cases. */ + if (xoff == xlim) + while (yoff < ylim) + { + NOTE_INSERT (ctxt, yoff); + if (EARLY_ABORT (ctxt)) + return true; + yoff++; + } + else if (yoff == ylim) + while (xoff < xlim) + { + NOTE_DELETE (ctxt, xoff); + if (EARLY_ABORT (ctxt)) + return true; + xoff++; + } + else + { + struct partition part IF_LINT2 (= { .xmid = 0, .ymid = 0 }); + + /* Find a point of correspondence in the middle of the vectors. */ + diag (xoff, xlim, yoff, ylim, &part, ctxt); + + /* Use the partitions to split this problem into subproblems. */ + if (compareseq (xoff, part.xmid, yoff, part.ymid, ctxt)) + return true; + if (compareseq (part.xmid, xlim, part.ymid, ylim, ctxt)) + return true; + } + + return false; + #undef XREF_YREF_EQUAL +} + +#undef ELEMENT +#undef EQUAL +#undef OFFSET +#undef EXTRA_CONTEXT_FIELDS +#undef NOTE_DELETE +#undef NOTE_INSERT +#undef EARLY_ABORT +#undef USE_HEURISTIC +#undef XVECREF_YVECREF_EQUAL +#undef OFFSET_MAX diff --git a/gettext-tools/gnulib-lib/dirent-private.h b/gettext-tools/gnulib-lib/dirent-private.h new file mode 100644 index 0000000..83531a1 --- /dev/null +++ b/gettext-tools/gnulib-lib/dirent-private.h @@ -0,0 +1,40 @@ +/* Private details of the DIR type. + Copyright (C) 2011-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _DIRENT_PRIVATE_H +#define _DIRENT_PRIVATE_H 1 + +#define WIN32_LEAN_AND_MEAN +#include + +struct gl_directory +{ + /* Status, or error code to produce in next readdir() call. + -2 means the end of the directory is already reached, + -1 means the entry was already filled by FindFirstFile, + 0 means the entry needs to be filled using FindNextFile. + A positive value is an error code. */ + int status; + /* Handle, reading the directory, at current position. */ + HANDLE current; + /* Found directory entry. */ + WIN32_FIND_DATA entry; + /* Argument to pass to FindFirstFile. It consists of the absolutized + directory name, followed by a directory separator and the wildcards. */ + char dir_name_mask[1]; +}; + +#endif /* _DIRENT_PRIVATE_H */ diff --git a/gettext-tools/gnulib-lib/dirent.in.h b/gettext-tools/gnulib-lib/dirent.in.h new file mode 100644 index 0000000..4822d6b --- /dev/null +++ b/gettext-tools/gnulib-lib/dirent.in.h @@ -0,0 +1,258 @@ +/* A GNU-like . + Copyright (C) 2006-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _@GUARD_PREFIX@_DIRENT_H + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +/* The include_next requires a split double-inclusion guard. */ +#if @HAVE_DIRENT_H@ +# @INCLUDE_NEXT@ @NEXT_DIRENT_H@ +#endif + +#ifndef _@GUARD_PREFIX@_DIRENT_H +#define _@GUARD_PREFIX@_DIRENT_H + +/* Get ino_t. Needed on some systems, including glibc 2.8. */ +#include + +#if !@HAVE_DIRENT_H@ +/* Define types DIR and 'struct dirent'. */ +# if !GNULIB_defined_struct_dirent +struct dirent +{ + char d_type; + char d_name[1]; +}; +/* Possible values for 'd_type'. */ +# define DT_UNKNOWN 0 +# define DT_FIFO 1 /* FIFO */ +# define DT_CHR 2 /* character device */ +# define DT_DIR 4 /* directory */ +# define DT_BLK 6 /* block device */ +# define DT_REG 8 /* regular file */ +# define DT_LNK 10 /* symbolic link */ +# define DT_SOCK 12 /* socket */ +# define DT_WHT 14 /* whiteout */ +typedef struct gl_directory DIR; +# define GNULIB_defined_struct_dirent 1 +# endif +#endif + +/* The __attribute__ feature is available in gcc versions 2.5 and later. + The attribute __pure__ was added in gcc 2.96. */ +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96) +# define _GL_ATTRIBUTE_PURE __attribute__ ((__pure__)) +#else +# define _GL_ATTRIBUTE_PURE /* empty */ +#endif + +/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ + +/* The definition of _GL_ARG_NONNULL is copied here. */ + +/* The definition of _GL_WARN_ON_USE is copied here. */ + + +/* Declare overridden functions. */ + +#if @GNULIB_OPENDIR@ +# if @REPLACE_OPENDIR@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef opendir +# define opendir rpl_opendir +# endif +_GL_FUNCDECL_RPL (opendir, DIR *, (const char *dir_name) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (opendir, DIR *, (const char *dir_name)); +# else +# if !@HAVE_OPENDIR@ +_GL_FUNCDECL_SYS (opendir, DIR *, (const char *dir_name) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (opendir, DIR *, (const char *dir_name)); +# endif +_GL_CXXALIASWARN (opendir); +#elif defined GNULIB_POSIXCHECK +# undef opendir +# if HAVE_RAW_DECL_OPENDIR +_GL_WARN_ON_USE (opendir, "opendir is not portable - " + "use gnulib module opendir for portability"); +# endif +#endif + +#if @GNULIB_READDIR@ +# if !@HAVE_READDIR@ +_GL_FUNCDECL_SYS (readdir, struct dirent *, (DIR *dirp) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (readdir, struct dirent *, (DIR *dirp)); +_GL_CXXALIASWARN (readdir); +#elif defined GNULIB_POSIXCHECK +# undef readdir +# if HAVE_RAW_DECL_READDIR +_GL_WARN_ON_USE (readdir, "readdir is not portable - " + "use gnulib module readdir for portability"); +# endif +#endif + +#if @GNULIB_REWINDDIR@ +# if !@HAVE_REWINDDIR@ +_GL_FUNCDECL_SYS (rewinddir, void, (DIR *dirp) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (rewinddir, void, (DIR *dirp)); +_GL_CXXALIASWARN (rewinddir); +#elif defined GNULIB_POSIXCHECK +# undef rewinddir +# if HAVE_RAW_DECL_REWINDDIR +_GL_WARN_ON_USE (rewinddir, "rewinddir is not portable - " + "use gnulib module rewinddir for portability"); +# endif +#endif + +#if @GNULIB_CLOSEDIR@ +# if @REPLACE_CLOSEDIR@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef closedir +# define closedir rpl_closedir +# endif +_GL_FUNCDECL_RPL (closedir, int, (DIR *dirp) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (closedir, int, (DIR *dirp)); +# else +# if !@HAVE_CLOSEDIR@ +_GL_FUNCDECL_SYS (closedir, int, (DIR *dirp) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (closedir, int, (DIR *dirp)); +# endif +_GL_CXXALIASWARN (closedir); +#elif defined GNULIB_POSIXCHECK +# undef closedir +# if HAVE_RAW_DECL_CLOSEDIR +_GL_WARN_ON_USE (closedir, "closedir is not portable - " + "use gnulib module closedir for portability"); +# endif +#endif + +#if @GNULIB_DIRFD@ +/* Return the file descriptor associated with the given directory stream, + or -1 if none exists. */ +# if @REPLACE_DIRFD@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef dirfd +# define dirfd rpl_dirfd +# endif +_GL_FUNCDECL_RPL (dirfd, int, (DIR *) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (dirfd, int, (DIR *)); +# else +# if defined __cplusplus && defined GNULIB_NAMESPACE && defined dirfd + /* dirfd is defined as a macro and not as a function. + Turn it into a function and get rid of the macro. */ +static inline int (dirfd) (DIR *dp) { return dirfd (dp); } +# undef dirfd +# endif +# if !(@HAVE_DECL_DIRFD@ || defined dirfd) +_GL_FUNCDECL_SYS (dirfd, int, (DIR *) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (dirfd, int, (DIR *)); +# endif +_GL_CXXALIASWARN (dirfd); +#elif defined GNULIB_POSIXCHECK +# undef dirfd +# if HAVE_RAW_DECL_DIRFD +_GL_WARN_ON_USE (dirfd, "dirfd is unportable - " + "use gnulib module dirfd for portability"); +# endif +#endif + +#if @GNULIB_FDOPENDIR@ +/* Open a directory stream visiting the given directory file + descriptor. Return NULL and set errno if fd is not visiting a + directory. On success, this function consumes fd (it will be + implicitly closed either by this function or by a subsequent + closedir). */ +# if @REPLACE_FDOPENDIR@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef fdopendir +# define fdopendir rpl_fdopendir +# endif +_GL_FUNCDECL_RPL (fdopendir, DIR *, (int fd)); +_GL_CXXALIAS_RPL (fdopendir, DIR *, (int fd)); +# else +# if !@HAVE_FDOPENDIR@ || !@HAVE_DECL_FDOPENDIR@ +_GL_FUNCDECL_SYS (fdopendir, DIR *, (int fd)); +# endif +_GL_CXXALIAS_SYS (fdopendir, DIR *, (int fd)); +# endif +_GL_CXXALIASWARN (fdopendir); +#elif defined GNULIB_POSIXCHECK +# undef fdopendir +# if HAVE_RAW_DECL_FDOPENDIR +_GL_WARN_ON_USE (fdopendir, "fdopendir is unportable - " + "use gnulib module fdopendir for portability"); +# endif +#endif + +#if @GNULIB_SCANDIR@ +/* Scan the directory DIR, calling FILTER on each directory entry. + Entries for which FILTER returns nonzero are individually malloc'd, + sorted using qsort with CMP, and collected in a malloc'd array in + *NAMELIST. Returns the number of entries selected, or -1 on error. */ +# if !@HAVE_SCANDIR@ +_GL_FUNCDECL_SYS (scandir, int, + (const char *dir, struct dirent ***namelist, + int (*filter) (const struct dirent *), + int (*cmp) (const struct dirent **, const struct dirent **)) + _GL_ARG_NONNULL ((1, 2, 4))); +# endif +/* Need to cast, because on glibc systems, the fourth parameter is + int (*cmp) (const void *, const void *). */ +_GL_CXXALIAS_SYS_CAST (scandir, int, + (const char *dir, struct dirent ***namelist, + int (*filter) (const struct dirent *), + int (*cmp) (const struct dirent **, const struct dirent **))); +_GL_CXXALIASWARN (scandir); +#elif defined GNULIB_POSIXCHECK +# undef scandir +# if HAVE_RAW_DECL_SCANDIR +_GL_WARN_ON_USE (scandir, "scandir is unportable - " + "use gnulib module scandir for portability"); +# endif +#endif + +#if @GNULIB_ALPHASORT@ +/* Compare two 'struct dirent' entries alphabetically. */ +# if !@HAVE_ALPHASORT@ +_GL_FUNCDECL_SYS (alphasort, int, + (const struct dirent **, const struct dirent **) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1, 2))); +# endif +/* Need to cast, because on glibc systems, the parameters are + (const void *, const void *). */ +_GL_CXXALIAS_SYS_CAST (alphasort, int, + (const struct dirent **, const struct dirent **)); +_GL_CXXALIASWARN (alphasort); +#elif defined GNULIB_POSIXCHECK +# undef alphasort +# if HAVE_RAW_DECL_ALPHASORT +_GL_WARN_ON_USE (alphasort, "alphasort is unportable - " + "use gnulib module alphasort for portability"); +# endif +#endif + + +#endif /* _@GUARD_PREFIX@_DIRENT_H */ +#endif /* _@GUARD_PREFIX@_DIRENT_H */ diff --git a/gettext-tools/gnulib-lib/dosname.h b/gettext-tools/gnulib-lib/dosname.h new file mode 100644 index 0000000..b92adfa --- /dev/null +++ b/gettext-tools/gnulib-lib/dosname.h @@ -0,0 +1,53 @@ +/* File names on MS-DOS/Windows systems. + + Copyright (C) 2000-2001, 2004-2006, 2009-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + From Paul Eggert and Jim Meyering. */ + +#ifndef _DOSNAME_H +#define _DOSNAME_H + +#if (defined _WIN32 || defined __WIN32__ || \ + defined __MSDOS__ || defined __CYGWIN__ || \ + defined __EMX__ || defined __DJGPP__) + /* This internal macro assumes ASCII, but all hosts that support drive + letters use ASCII. */ +# define _IS_DRIVE_LETTER(C) (((unsigned int) (C) | ('a' - 'A')) - 'a' \ + <= 'z' - 'a') +# define FILE_SYSTEM_PREFIX_LEN(Filename) \ + (_IS_DRIVE_LETTER ((Filename)[0]) && (Filename)[1] == ':' ? 2 : 0) +# ifndef __CYGWIN__ +# define FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE 1 +# endif +# define ISSLASH(C) ((C) == '/' || (C) == '\\') +#else +# define FILE_SYSTEM_PREFIX_LEN(Filename) 0 +# define ISSLASH(C) ((C) == '/') +#endif + +#ifndef FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE +# define FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE 0 +#endif + +#if FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE +# define IS_ABSOLUTE_FILE_NAME(F) ISSLASH ((F)[FILE_SYSTEM_PREFIX_LEN (F)]) +# else +# define IS_ABSOLUTE_FILE_NAME(F) \ + (ISSLASH ((F)[0]) || FILE_SYSTEM_PREFIX_LEN (F) != 0) +#endif +#define IS_RELATIVE_FILE_NAME(F) (! IS_ABSOLUTE_FILE_NAME (F)) + +#endif /* DOSNAME_H_ */ diff --git a/gettext-tools/gnulib-lib/dup-safer-flag.c b/gettext-tools/gnulib-lib/dup-safer-flag.c new file mode 100644 index 0000000..2d860fb --- /dev/null +++ b/gettext-tools/gnulib-lib/dup-safer-flag.c @@ -0,0 +1,38 @@ +/* Duplicate a file descriptor result, avoiding clobbering + STD{IN,OUT,ERR}_FILENO, with specific flags. + + Copyright (C) 2001, 2004-2006, 2009-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Written by Paul Eggert and Eric Blake. */ + +#include + +/* Specification. */ +#include "unistd-safer.h" + +#include +#include + +/* Like dup, but do not return STDIN_FILENO, STDOUT_FILENO, or + STDERR_FILENO. If FLAG contains O_CLOEXEC, behave like + fcntl(F_DUPFD_CLOEXEC) rather than fcntl(F_DUPFD). */ + +int +dup_safer_flag (int fd, int flag) +{ + return fcntl (fd, (flag & O_CLOEXEC) ? F_DUPFD_CLOEXEC : F_DUPFD, + STDERR_FILENO + 1); +} diff --git a/gettext-tools/gnulib-lib/dup-safer.c b/gettext-tools/gnulib-lib/dup-safer.c new file mode 100644 index 0000000..8df3cda --- /dev/null +++ b/gettext-tools/gnulib-lib/dup-safer.c @@ -0,0 +1,34 @@ +/* Invoke dup, but avoid some glitches. + + Copyright (C) 2001, 2004-2006, 2009-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Written by Paul Eggert. */ + +#include + +#include "unistd-safer.h" + +#include +#include + +/* Like dup, but do not return STDIN_FILENO, STDOUT_FILENO, or + STDERR_FILENO. */ + +int +dup_safer (int fd) +{ + return fcntl (fd, F_DUPFD, STDERR_FILENO + 1); +} diff --git a/gettext-tools/gnulib-lib/dup2.c b/gettext-tools/gnulib-lib/dup2.c new file mode 100644 index 0000000..7de6805 --- /dev/null +++ b/gettext-tools/gnulib-lib/dup2.c @@ -0,0 +1,164 @@ +/* Duplicate an open file descriptor to a specified file descriptor. + + Copyright (C) 1999, 2004-2007, 2009-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* written by Paul Eggert */ + +#include + +/* Specification. */ +#include + +#include +#include + +#if HAVE_DUP2 + +# undef dup2 + +# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ + +/* Get declarations of the native Windows API functions. */ +# define WIN32_LEAN_AND_MEAN +# include + +# include "msvc-inval.h" + +/* Get _get_osfhandle. */ +# include "msvc-nothrow.h" + +static int +ms_windows_dup2 (int fd, int desired_fd) +{ + int result; + + /* If fd is closed, mingw hangs on dup2 (fd, fd). If fd is open, + dup2 (fd, fd) returns 0, but all further attempts to use fd in + future dup2 calls will hang. */ + if (fd == desired_fd) + { + if ((HANDLE) _get_osfhandle (fd) == INVALID_HANDLE_VALUE) + { + errno = EBADF; + return -1; + } + return fd; + } + + /* Wine 1.0.1 return 0 when desired_fd is negative but not -1: + http://bugs.winehq.org/show_bug.cgi?id=21289 */ + if (desired_fd < 0) + { + errno = EBADF; + return -1; + } + + TRY_MSVC_INVAL + { + result = dup2 (fd, desired_fd); + } + CATCH_MSVC_INVAL + { + errno = EBADF; + result = -1; + } + DONE_MSVC_INVAL; + + if (result == 0) + result = desired_fd; + + return result; +} + +# define dup2 ms_windows_dup2 + +# endif + +int +rpl_dup2 (int fd, int desired_fd) +{ + int result; + +# ifdef F_GETFL + /* On Linux kernels 2.6.26-2.6.29, dup2 (fd, fd) returns -EBADF. + On Cygwin 1.5.x, dup2 (1, 1) returns 0. + On Cygwin 1.7.17, dup2 (1, -1) dumps core. + On Cygwin 1.7.25, dup2 (1, 256) can dump core. + On Haiku, dup2 (fd, fd) mistakenly clears FD_CLOEXEC. */ +# if HAVE_SETDTABLESIZE + setdtablesize (desired_fd + 1); +# endif + if (desired_fd < 0) + fd = desired_fd; + if (fd == desired_fd) + return fcntl (fd, F_GETFL) == -1 ? -1 : fd; +# endif + + result = dup2 (fd, desired_fd); + + /* Correct an errno value on FreeBSD 6.1 and Cygwin 1.5.x. */ + if (result == -1 && errno == EMFILE) + errno = EBADF; +# if REPLACE_FCHDIR + if (fd != desired_fd && result != -1) + result = _gl_register_dup (fd, result); +# endif + return result; +} + +#else /* !HAVE_DUP2 */ + +/* On older platforms, dup2 did not exist. */ + +# ifndef F_DUPFD +static int +dupfd (int fd, int desired_fd) +{ + int duplicated_fd = dup (fd); + if (duplicated_fd < 0 || duplicated_fd == desired_fd) + return duplicated_fd; + else + { + int r = dupfd (fd, desired_fd); + int e = errno; + close (duplicated_fd); + errno = e; + return r; + } +} +# endif + +int +dup2 (int fd, int desired_fd) +{ + int result = fcntl (fd, F_GETFL) < 0 ? -1 : fd; + if (result == -1 || fd == desired_fd) + return result; + close (desired_fd); +# ifdef F_DUPFD + result = fcntl (fd, F_DUPFD, desired_fd); +# if REPLACE_FCHDIR + if (0 <= result) + result = _gl_register_dup (fd, result); +# endif +# else + result = dupfd (fd, desired_fd); +# endif + if (result == -1 && (errno == EMFILE || errno == EINVAL)) + errno = EBADF; + return result; +} +#endif /* !HAVE_DUP2 */ diff --git a/gettext-tools/gnulib-lib/errno.in.h b/gettext-tools/gnulib-lib/errno.in.h new file mode 100644 index 0000000..832afc8 --- /dev/null +++ b/gettext-tools/gnulib-lib/errno.in.h @@ -0,0 +1,279 @@ +/* A POSIX-like . + + Copyright (C) 2008-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . */ + +#ifndef _@GUARD_PREFIX@_ERRNO_H + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +/* The include_next requires a split double-inclusion guard. */ +#@INCLUDE_NEXT@ @NEXT_ERRNO_H@ + +#ifndef _@GUARD_PREFIX@_ERRNO_H +#define _@GUARD_PREFIX@_ERRNO_H + + +/* On native Windows platforms, many macros are not defined. */ +# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ + +/* These are the same values as defined by MSVC 10, for interoperability. */ + +# ifndef ENOMSG +# define ENOMSG 122 +# define GNULIB_defined_ENOMSG 1 +# endif + +# ifndef EIDRM +# define EIDRM 111 +# define GNULIB_defined_EIDRM 1 +# endif + +# ifndef ENOLINK +# define ENOLINK 121 +# define GNULIB_defined_ENOLINK 1 +# endif + +# ifndef EPROTO +# define EPROTO 134 +# define GNULIB_defined_EPROTO 1 +# endif + +# ifndef EBADMSG +# define EBADMSG 104 +# define GNULIB_defined_EBADMSG 1 +# endif + +# ifndef EOVERFLOW +# define EOVERFLOW 132 +# define GNULIB_defined_EOVERFLOW 1 +# endif + +# ifndef ENOTSUP +# define ENOTSUP 129 +# define GNULIB_defined_ENOTSUP 1 +# endif + +# ifndef ENETRESET +# define ENETRESET 117 +# define GNULIB_defined_ENETRESET 1 +# endif + +# ifndef ECONNABORTED +# define ECONNABORTED 106 +# define GNULIB_defined_ECONNABORTED 1 +# endif + +# ifndef ECANCELED +# define ECANCELED 105 +# define GNULIB_defined_ECANCELED 1 +# endif + +# ifndef EOWNERDEAD +# define EOWNERDEAD 133 +# define GNULIB_defined_EOWNERDEAD 1 +# endif + +# ifndef ENOTRECOVERABLE +# define ENOTRECOVERABLE 127 +# define GNULIB_defined_ENOTRECOVERABLE 1 +# endif + +# ifndef EINPROGRESS +# define EINPROGRESS 112 +# define EALREADY 103 +# define ENOTSOCK 128 +# define EDESTADDRREQ 109 +# define EMSGSIZE 115 +# define EPROTOTYPE 136 +# define ENOPROTOOPT 123 +# define EPROTONOSUPPORT 135 +# define EOPNOTSUPP 130 +# define EAFNOSUPPORT 102 +# define EADDRINUSE 100 +# define EADDRNOTAVAIL 101 +# define ENETDOWN 116 +# define ENETUNREACH 118 +# define ECONNRESET 108 +# define ENOBUFS 119 +# define EISCONN 113 +# define ENOTCONN 126 +# define ETIMEDOUT 138 +# define ECONNREFUSED 107 +# define ELOOP 114 +# define EHOSTUNREACH 110 +# define EWOULDBLOCK 140 +# define GNULIB_defined_ESOCK 1 +# endif + +# ifndef ETXTBSY +# define ETXTBSY 139 +# define ENODATA 120 /* not required by POSIX */ +# define ENOSR 124 /* not required by POSIX */ +# define ENOSTR 125 /* not required by POSIX */ +# define ETIME 137 /* not required by POSIX */ +# define EOTHER 131 /* not required by POSIX */ +# define GNULIB_defined_ESTREAMS 1 +# endif + +/* These are intentionally the same values as the WSA* error numbers, defined + in . */ +# define ESOCKTNOSUPPORT 10044 /* not required by POSIX */ +# define EPFNOSUPPORT 10046 /* not required by POSIX */ +# define ESHUTDOWN 10058 /* not required by POSIX */ +# define ETOOMANYREFS 10059 /* not required by POSIX */ +# define EHOSTDOWN 10064 /* not required by POSIX */ +# define EPROCLIM 10067 /* not required by POSIX */ +# define EUSERS 10068 /* not required by POSIX */ +# define EDQUOT 10069 +# define ESTALE 10070 +# define EREMOTE 10071 /* not required by POSIX */ +# define GNULIB_defined_EWINSOCK 1 + +# endif + + +/* On OSF/1 5.1, when _XOPEN_SOURCE_EXTENDED is not defined, the macros + EMULTIHOP, ENOLINK, EOVERFLOW are not defined. */ +# if @EMULTIHOP_HIDDEN@ +# define EMULTIHOP @EMULTIHOP_VALUE@ +# define GNULIB_defined_EMULTIHOP 1 +# endif +# if @ENOLINK_HIDDEN@ +# define ENOLINK @ENOLINK_VALUE@ +# define GNULIB_defined_ENOLINK 1 +# endif +# if @EOVERFLOW_HIDDEN@ +# define EOVERFLOW @EOVERFLOW_VALUE@ +# define GNULIB_defined_EOVERFLOW 1 +# endif + + +/* On OpenBSD 4.0 and on native Windows, the macros ENOMSG, EIDRM, ENOLINK, + EPROTO, EMULTIHOP, EBADMSG, EOVERFLOW, ENOTSUP, ECANCELED are not defined. + Likewise, on NonStop Kernel, EDQUOT is not defined. + Define them here. Values >= 2000 seem safe to use: Solaris ESTALE = 151, + HP-UX EWOULDBLOCK = 246, IRIX EDQUOT = 1133. + + Note: When one of these systems defines some of these macros some day, + binaries will have to be recompiled so that they recognizes the new + errno values from the system. */ + +# ifndef ENOMSG +# define ENOMSG 2000 +# define GNULIB_defined_ENOMSG 1 +# endif + +# ifndef EIDRM +# define EIDRM 2001 +# define GNULIB_defined_EIDRM 1 +# endif + +# ifndef ENOLINK +# define ENOLINK 2002 +# define GNULIB_defined_ENOLINK 1 +# endif + +# ifndef EPROTO +# define EPROTO 2003 +# define GNULIB_defined_EPROTO 1 +# endif + +# ifndef EMULTIHOP +# define EMULTIHOP 2004 +# define GNULIB_defined_EMULTIHOP 1 +# endif + +# ifndef EBADMSG +# define EBADMSG 2005 +# define GNULIB_defined_EBADMSG 1 +# endif + +# ifndef EOVERFLOW +# define EOVERFLOW 2006 +# define GNULIB_defined_EOVERFLOW 1 +# endif + +# ifndef ENOTSUP +# define ENOTSUP 2007 +# define GNULIB_defined_ENOTSUP 1 +# endif + +# ifndef ENETRESET +# define ENETRESET 2011 +# define GNULIB_defined_ENETRESET 1 +# endif + +# ifndef ECONNABORTED +# define ECONNABORTED 2012 +# define GNULIB_defined_ECONNABORTED 1 +# endif + +# ifndef ESTALE +# define ESTALE 2009 +# define GNULIB_defined_ESTALE 1 +# endif + +# ifndef EDQUOT +# define EDQUOT 2010 +# define GNULIB_defined_EDQUOT 1 +# endif + +# ifndef ECANCELED +# define ECANCELED 2008 +# define GNULIB_defined_ECANCELED 1 +# endif + +/* On many platforms, the macros EOWNERDEAD and ENOTRECOVERABLE are not + defined. */ + +# ifndef EOWNERDEAD +# if defined __sun + /* Use the same values as defined for Solaris >= 8, for + interoperability. */ +# define EOWNERDEAD 58 +# define ENOTRECOVERABLE 59 +# elif (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ + /* We have a conflict here: pthreads-win32 defines these values + differently than MSVC 10. It's hairy to decide which one to use. */ +# if defined __MINGW32__ && !defined USE_WINDOWS_THREADS + /* Use the same values as defined by pthreads-win32, for + interoperability. */ +# define EOWNERDEAD 43 +# define ENOTRECOVERABLE 44 +# else + /* Use the same values as defined by MSVC 10, for + interoperability. */ +# define EOWNERDEAD 133 +# define ENOTRECOVERABLE 127 +# endif +# else +# define EOWNERDEAD 2013 +# define ENOTRECOVERABLE 2014 +# endif +# define GNULIB_defined_EOWNERDEAD 1 +# define GNULIB_defined_ENOTRECOVERABLE 1 +# endif + +# ifndef EILSEQ +# define EILSEQ 2015 +# define GNULIB_defined_EILSEQ 1 +# endif + +#endif /* _@GUARD_PREFIX@_ERRNO_H */ +#endif /* _@GUARD_PREFIX@_ERRNO_H */ diff --git a/gettext-tools/gnulib-lib/error-progname.c b/gettext-tools/gnulib-lib/error-progname.c new file mode 100644 index 0000000..189bbd5 --- /dev/null +++ b/gettext-tools/gnulib-lib/error-progname.c @@ -0,0 +1,40 @@ +/* Use of program name in error-reporting functions. + Copyright (C) 2001-2003, 2006 Free Software Foundation, Inc. + Written by Bruno Haible , 2001. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + + +#include + +/* Specification. */ +#include "error-progname.h" + +#include + +#include "progname.h" + + +/* Indicates whether errors and warnings get prefixed with program_name. + Default is true. */ +bool error_with_progname = true; + +/* Print program_name prefix on stderr if and only if error_with_progname + is true. */ +void +maybe_print_progname () +{ + if (error_with_progname) + fprintf (stderr, "%s: ", program_name); +} diff --git a/gettext-tools/gnulib-lib/error-progname.h b/gettext-tools/gnulib-lib/error-progname.h new file mode 100644 index 0000000..77ae822 --- /dev/null +++ b/gettext-tools/gnulib-lib/error-progname.h @@ -0,0 +1,52 @@ +/* Use of program name in error-reporting functions. + Copyright (C) 2001-2003 Free Software Foundation, Inc. + Written by Bruno Haible , 2001. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _ERROR_PROGNAME_H +#define _ERROR_PROGNAME_H + +#include + +/* This file supports selectively prefixing or nor prefixing error messages + with the program name. + + Programs using this file should do the following in main(): + error_print_progname = maybe_print_progname; + */ + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Indicates whether errors and warnings get prefixed with program_name. + Default is true. + A reason to omit the prefix is for better interoperability with Emacs' + compile.el. */ +extern DLL_VARIABLE bool error_with_progname; + +/* Print program_name prefix on stderr if and only if error_with_progname + is true. */ +extern void maybe_print_progname (void); + + +#ifdef __cplusplus +} +#endif + + +#endif /* _ERROR_PROGNAME_H */ diff --git a/gettext-tools/gnulib-lib/error.c b/gettext-tools/gnulib-lib/error.c new file mode 100644 index 0000000..18ff5db --- /dev/null +++ b/gettext-tools/gnulib-lib/error.c @@ -0,0 +1,406 @@ +/* Error handler for noninteractive utilities + Copyright (C) 1990-1998, 2000-2007, 2009-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Written by David MacKenzie . */ + +#if !_LIBC +# include +#endif + +#include "error.h" + +#include +#include +#include +#include + +#if !_LIBC && ENABLE_NLS +# include "gettext.h" +# define _(msgid) gettext (msgid) +#endif + +#ifdef _LIBC +# include +# include +# include +# include +# define mbsrtowcs __mbsrtowcs +# define USE_UNLOCKED_IO 0 +# define _GL_ATTRIBUTE_FORMAT_PRINTF(a, b) +# define _GL_ARG_NONNULL(a) +#endif + +#if USE_UNLOCKED_IO +# include "unlocked-io.h" +#endif + +#ifndef _ +# define _(String) String +#endif + +/* If NULL, error will flush stdout, then print on stderr the program + name, a colon and a space. Otherwise, error will call this + function without parameters instead. */ +void (*error_print_progname) (void); + +/* This variable is incremented each time 'error' is called. */ +unsigned int error_message_count; + +#ifdef _LIBC +/* In the GNU C library, there is a predefined variable for this. */ + +# define program_name program_invocation_name +# include +# include +# include + +/* In GNU libc we want do not want to use the common name 'error' directly. + Instead make it a weak alias. */ +extern void __error (int status, int errnum, const char *message, ...) + __attribute__ ((__format__ (__printf__, 3, 4))); +extern void __error_at_line (int status, int errnum, const char *file_name, + unsigned int line_number, const char *message, + ...) + __attribute__ ((__format__ (__printf__, 5, 6))); +# define error __error +# define error_at_line __error_at_line + +# include +# define fflush(s) _IO_fflush (s) +# undef putc +# define putc(c, fp) _IO_putc (c, fp) + +# include + +#else /* not _LIBC */ + +# include +# include + +# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ +/* Get declarations of the native Windows API functions. */ +# define WIN32_LEAN_AND_MEAN +# include +/* Get _get_osfhandle. */ +# include "msvc-nothrow.h" +# endif + +/* The gnulib override of fcntl is not needed in this file. */ +# undef fcntl + +# if !HAVE_DECL_STRERROR_R +# ifndef HAVE_DECL_STRERROR_R +"this configure-time declaration test was not run" +# endif +# if STRERROR_R_CHAR_P +char *strerror_r (); +# else +int strerror_r (); +# endif +# endif + +/* The calling program should define program_name and set it to the + name of the executing program. */ +extern char *program_name; + +# if HAVE_STRERROR_R || defined strerror_r +# define __strerror_r strerror_r +# endif /* HAVE_STRERROR_R || defined strerror_r */ +#endif /* not _LIBC */ + +#if !_LIBC +/* Return non-zero if FD is open. */ +static int +is_open (int fd) +{ +# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ + /* On native Windows: The initial state of unassigned standard file + descriptors is that they are open but point to an INVALID_HANDLE_VALUE. + There is no fcntl, and the gnulib replacement fcntl does not support + F_GETFL. */ + return (HANDLE) _get_osfhandle (fd) != INVALID_HANDLE_VALUE; +# else +# ifndef F_GETFL +# error Please port fcntl to your platform +# endif + return 0 <= fcntl (fd, F_GETFL); +# endif +} +#endif + +static void +flush_stdout (void) +{ +#if !_LIBC + int stdout_fd; + +# if GNULIB_FREOPEN_SAFER + /* Use of gnulib's freopen-safer module normally ensures that + fileno (stdout) == 1 + whenever stdout is open. */ + stdout_fd = STDOUT_FILENO; +# else + /* POSIX states that fileno (stdout) after fclose is unspecified. But in + practice it is not a problem, because stdout is statically allocated and + the fd of a FILE stream is stored as a field in its allocated memory. */ + stdout_fd = fileno (stdout); +# endif + /* POSIX states that fflush (stdout) after fclose is unspecified; it + is safe in glibc, but not on all other platforms. fflush (NULL) + is always defined, but too draconian. */ + if (0 <= stdout_fd && is_open (stdout_fd)) +#endif + fflush (stdout); +} + +static void +print_errno_message (int errnum) +{ + char const *s; + +#if defined HAVE_STRERROR_R || _LIBC + char errbuf[1024]; +# if _LIBC || STRERROR_R_CHAR_P + s = __strerror_r (errnum, errbuf, sizeof errbuf); +# else + if (__strerror_r (errnum, errbuf, sizeof errbuf) == 0) + s = errbuf; + else + s = 0; +# endif +#else + s = strerror (errnum); +#endif + +#if !_LIBC + if (! s) + s = _("Unknown system error"); +#endif + +#if _LIBC + __fxprintf (NULL, ": %s", s); +#else + fprintf (stderr, ": %s", s); +#endif +} + +static void _GL_ATTRIBUTE_FORMAT_PRINTF (3, 0) _GL_ARG_NONNULL ((3)) +error_tail (int status, int errnum, const char *message, va_list args) +{ +#if _LIBC + if (_IO_fwide (stderr, 0) > 0) + { + size_t len = strlen (message) + 1; + wchar_t *wmessage = NULL; + mbstate_t st; + size_t res; + const char *tmp; + bool use_malloc = false; + + while (1) + { + if (__libc_use_alloca (len * sizeof (wchar_t))) + wmessage = (wchar_t *) alloca (len * sizeof (wchar_t)); + else + { + if (!use_malloc) + wmessage = NULL; + + wchar_t *p = (wchar_t *) realloc (wmessage, + len * sizeof (wchar_t)); + if (p == NULL) + { + free (wmessage); + fputws_unlocked (L"out of memory\n", stderr); + return; + } + wmessage = p; + use_malloc = true; + } + + memset (&st, '\0', sizeof (st)); + tmp = message; + + res = mbsrtowcs (wmessage, &tmp, len, &st); + if (res != len) + break; + + if (__builtin_expect (len >= SIZE_MAX / sizeof (wchar_t) / 2, 0)) + { + /* This really should not happen if everything is fine. */ + res = (size_t) -1; + break; + } + + len *= 2; + } + + if (res == (size_t) -1) + { + /* The string cannot be converted. */ + if (use_malloc) + { + free (wmessage); + use_malloc = false; + } + wmessage = (wchar_t *) L"???"; + } + + __vfwprintf (stderr, wmessage, args); + + if (use_malloc) + free (wmessage); + } + else +#endif + vfprintf (stderr, message, args); + va_end (args); + + ++error_message_count; + if (errnum) + print_errno_message (errnum); +#if _LIBC + __fxprintf (NULL, "\n"); +#else + putc ('\n', stderr); +#endif + fflush (stderr); + if (status) + exit (status); +} + + +/* Print the program name and error message MESSAGE, which is a printf-style + format string with optional args. + If ERRNUM is nonzero, print its corresponding system error message. + Exit with status STATUS if it is nonzero. */ +void +error (int status, int errnum, const char *message, ...) +{ + va_list args; + +#if defined _LIBC && defined __libc_ptf_call + /* We do not want this call to be cut short by a thread + cancellation. Therefore disable cancellation for now. */ + int state = PTHREAD_CANCEL_ENABLE; + __libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state), + 0); +#endif + + flush_stdout (); +#ifdef _LIBC + _IO_flockfile (stderr); +#endif + if (error_print_progname) + (*error_print_progname) (); + else + { +#if _LIBC + __fxprintf (NULL, "%s: ", program_name); +#else + fprintf (stderr, "%s: ", program_name); +#endif + } + + va_start (args, message); + error_tail (status, errnum, message, args); + +#ifdef _LIBC + _IO_funlockfile (stderr); +# ifdef __libc_ptf_call + __libc_ptf_call (pthread_setcancelstate, (state, NULL), 0); +# endif +#endif +} + +/* Sometimes we want to have at most one error per line. This + variable controls whether this mode is selected or not. */ +int error_one_per_line; + +void +error_at_line (int status, int errnum, const char *file_name, + unsigned int line_number, const char *message, ...) +{ + va_list args; + + if (error_one_per_line) + { + static const char *old_file_name; + static unsigned int old_line_number; + + if (old_line_number == line_number + && (file_name == old_file_name + || (old_file_name != NULL + && file_name != NULL + && strcmp (old_file_name, file_name) == 0))) + + /* Simply return and print nothing. */ + return; + + old_file_name = file_name; + old_line_number = line_number; + } + +#if defined _LIBC && defined __libc_ptf_call + /* We do not want this call to be cut short by a thread + cancellation. Therefore disable cancellation for now. */ + int state = PTHREAD_CANCEL_ENABLE; + __libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state), + 0); +#endif + + flush_stdout (); +#ifdef _LIBC + _IO_flockfile (stderr); +#endif + if (error_print_progname) + (*error_print_progname) (); + else + { +#if _LIBC + __fxprintf (NULL, "%s:", program_name); +#else + fprintf (stderr, "%s:", program_name); +#endif + } + +#if _LIBC + __fxprintf (NULL, file_name != NULL ? "%s:%d: " : " ", + file_name, line_number); +#else + fprintf (stderr, file_name != NULL ? "%s:%d: " : " ", + file_name, line_number); +#endif + + va_start (args, message); + error_tail (status, errnum, message, args); + +#ifdef _LIBC + _IO_funlockfile (stderr); +# ifdef __libc_ptf_call + __libc_ptf_call (pthread_setcancelstate, (state, NULL), 0); +# endif +#endif +} + +#ifdef _LIBC +/* Make the weak alias. */ +# undef error +# undef error_at_line +weak_alias (__error, error) +weak_alias (__error_at_line, error_at_line) +#endif diff --git a/gettext-tools/gnulib-lib/error.h b/gettext-tools/gnulib-lib/error.h new file mode 100644 index 0000000..873d9aa --- /dev/null +++ b/gettext-tools/gnulib-lib/error.h @@ -0,0 +1,74 @@ +/* Declaration for error-reporting function + Copyright (C) 1995-1997, 2003, 2006, 2008-2014 Free Software Foundation, + Inc. + This file is part of the GNU C Library. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _ERROR_H +#define _ERROR_H 1 + +/* The __attribute__ feature is available in gcc versions 2.5 and later. + The __-protected variants of the attributes 'format' and 'printf' are + accepted by gcc versions 2.6.4 (effectively 2.7) and later. + We enable _GL_ATTRIBUTE_FORMAT only if these are supported too, because + gnulib and libintl do '#define printf __printf__' when they override + the 'printf' function. */ +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7) +# define _GL_ATTRIBUTE_FORMAT(spec) __attribute__ ((__format__ spec)) +#else +# define _GL_ATTRIBUTE_FORMAT(spec) /* empty */ +#endif + +#if GNULIB_REPLACE_ERROR +# undef error_print_progname +# undef error_message_count +# undef error_one_per_line +# define error_print_progname rpl_error_print_progname +# define error_message_count rpl_error_message_count +# define error_one_per_line rpl_error_one_per_line +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* Print a message with 'fprintf (stderr, FORMAT, ...)'; + if ERRNUM is nonzero, follow it with ": " and strerror (ERRNUM). + If STATUS is nonzero, terminate the program with 'exit (STATUS)'. */ + +extern void error (int __status, int __errnum, const char *__format, ...) + _GL_ATTRIBUTE_FORMAT ((__printf__, 3, 4)); + +extern void error_at_line (int __status, int __errnum, const char *__fname, + unsigned int __lineno, const char *__format, ...) + _GL_ATTRIBUTE_FORMAT ((__printf__, 5, 6)); + +/* If NULL, error will flush stdout, then print on stderr the program + name, a colon and a space. Otherwise, error will call this + function without parameters instead. */ +extern DLL_VARIABLE void (*error_print_progname) (void); + +/* This variable is incremented each time 'error' is called. */ +extern DLL_VARIABLE unsigned int error_message_count; + +/* Sometimes we want to have at most one error per line. This + variable controls whether this mode is selected or not. */ +extern DLL_VARIABLE int error_one_per_line; + +#ifdef __cplusplus +} +#endif + +#endif /* error.h */ diff --git a/gettext-tools/gnulib-lib/execute.c b/gettext-tools/gnulib-lib/execute.c new file mode 100644 index 0000000..489abf5 --- /dev/null +++ b/gettext-tools/gnulib-lib/execute.c @@ -0,0 +1,280 @@ +/* Creation of autonomous subprocesses. + Copyright (C) 2001-2004, 2006-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2001. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + + +#include + +/* Specification. */ +#include "execute.h" + +#include +#include +#include +#include +#include +#include + +#include "error.h" +#include "fatal-signal.h" +#include "wait-process.h" +#include "gettext.h" + +#define _(str) gettext (str) + +#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ + +/* Native Windows API. */ +# include +# include "w32spawn.h" + +#else + +/* Unix API. */ +# include + +#endif + +/* environ is the exported symbol referencing the internal + __cygwin_environ variable on cygwin64: + . */ +#if defined __CYGWIN__ && defined __x86_64__ +extern DLL_VARIABLE char **environ; +#endif + + +#if defined EINTR && ((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__) + +/* EINTR handling for close(), open(). + These functions can return -1/EINTR even though we don't have any + signal handlers set up, namely when we get interrupted via SIGSTOP. */ + +static int +nonintr_close (int fd) +{ + int retval; + + do + retval = close (fd); + while (retval < 0 && errno == EINTR); + + return retval; +} +#define close nonintr_close + +static int +nonintr_open (const char *pathname, int oflag, mode_t mode) +{ + int retval; + + do + retval = open (pathname, oflag, mode); + while (retval < 0 && errno == EINTR); + + return retval; +} +#undef open /* avoid warning on VMS */ +#define open nonintr_open + +#endif + + +/* Execute a command, optionally redirecting any of the three standard file + descriptors to /dev/null. Return its exit code. + If it didn't terminate correctly, exit if exit_on_error is true, otherwise + return 127. + If slave_process is true, the child process will be terminated when its + creator receives a catchable fatal signal. */ +int +execute (const char *progname, + const char *prog_path, char **prog_argv, + bool ignore_sigpipe, + bool null_stdin, bool null_stdout, bool null_stderr, + bool slave_process, bool exit_on_error, + int *termsigp) +{ +#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ + + /* Native Windows API. */ + int orig_stdin; + int orig_stdout; + int orig_stderr; + int exitcode; + int nullinfd; + int nulloutfd; + + /* FIXME: Need to free memory allocated by prepare_spawn. */ + prog_argv = prepare_spawn (prog_argv); + + /* Save standard file handles of parent process. */ + if (null_stdin) + orig_stdin = dup_safer_noinherit (STDIN_FILENO); + if (null_stdout) + orig_stdout = dup_safer_noinherit (STDOUT_FILENO); + if (null_stderr) + orig_stderr = dup_safer_noinherit (STDERR_FILENO); + exitcode = -1; + + /* Create standard file handles of child process. */ + nullinfd = -1; + nulloutfd = -1; + if ((!null_stdin + || ((nullinfd = open ("NUL", O_RDONLY, 0)) >= 0 + && (nullinfd == STDIN_FILENO + || (dup2 (nullinfd, STDIN_FILENO) >= 0 + && close (nullinfd) >= 0)))) + && (!(null_stdout || null_stderr) + || ((nulloutfd = open ("NUL", O_RDWR, 0)) >= 0 + && (!null_stdout + || nulloutfd == STDOUT_FILENO + || dup2 (nulloutfd, STDOUT_FILENO) >= 0) + && (!null_stderr + || nulloutfd == STDERR_FILENO + || dup2 (nulloutfd, STDERR_FILENO) >= 0) + && ((null_stdout && nulloutfd == STDOUT_FILENO) + || (null_stderr && nulloutfd == STDERR_FILENO) + || close (nulloutfd) >= 0)))) + /* Use spawnvpe and pass the environment explicitly. This is needed if + the program has modified the environment using putenv() or [un]setenv(). + On Windows, programs have two environments, one in the "environment + block" of the process and managed through SetEnvironmentVariable(), and + one inside the process, in the location retrieved by the 'environ' + macro. When using spawnvp() without 'e', the child process inherits a + copy of the environment block - ignoring the effects of putenv() and + [un]setenv(). */ + { + exitcode = spawnvpe (P_WAIT, prog_path, (const char **) prog_argv, + (const char **) environ); + if (exitcode < 0 && errno == ENOEXEC) + { + /* prog is not a native executable. Try to execute it as a + shell script. Note that prepare_spawn() has already prepended + a hidden element "sh.exe" to prog_argv. */ + --prog_argv; + exitcode = spawnvpe (P_WAIT, prog_argv[0], (const char **) prog_argv, + (const char **) environ); + } + } + if (nulloutfd >= 0) + close (nulloutfd); + if (nullinfd >= 0) + close (nullinfd); + + /* Restore standard file handles of parent process. */ + if (null_stderr) + undup_safer_noinherit (orig_stderr, STDERR_FILENO); + if (null_stdout) + undup_safer_noinherit (orig_stdout, STDOUT_FILENO); + if (null_stdin) + undup_safer_noinherit (orig_stdin, STDIN_FILENO); + + if (termsigp != NULL) + *termsigp = 0; + + if (exitcode == -1) + { + if (exit_on_error || !null_stderr) + error (exit_on_error ? EXIT_FAILURE : 0, errno, + _("%s subprocess failed"), progname); + return 127; + } + + return exitcode; + +#else + + /* Unix API. */ + /* Note about 127: Some errors during posix_spawnp() cause the function + posix_spawnp() to return an error code; some other errors cause the + subprocess to exit with return code 127. It is implementation + dependent which error is reported which way. We treat both cases as + equivalent. */ + sigset_t blocked_signals; + posix_spawn_file_actions_t actions; + bool actions_allocated; + posix_spawnattr_t attrs; + bool attrs_allocated; + int err; + pid_t child; + + if (slave_process) + { + sigprocmask (SIG_SETMASK, NULL, &blocked_signals); + block_fatal_signals (); + } + actions_allocated = false; + attrs_allocated = false; + if ((err = posix_spawn_file_actions_init (&actions)) != 0 + || (actions_allocated = true, + (null_stdin + && (err = posix_spawn_file_actions_addopen (&actions, + STDIN_FILENO, + "/dev/null", O_RDONLY, + 0)) + != 0) + || (null_stdout + && (err = posix_spawn_file_actions_addopen (&actions, + STDOUT_FILENO, + "/dev/null", O_RDWR, + 0)) + != 0) + || (null_stderr + && (err = posix_spawn_file_actions_addopen (&actions, + STDERR_FILENO, + "/dev/null", O_RDWR, + 0)) + != 0) + || (slave_process + && ((err = posix_spawnattr_init (&attrs)) != 0 + || (attrs_allocated = true, + (err = posix_spawnattr_setsigmask (&attrs, + &blocked_signals)) + != 0 + || (err = posix_spawnattr_setflags (&attrs, + POSIX_SPAWN_SETSIGMASK)) + != 0))) + || (err = posix_spawnp (&child, prog_path, &actions, + attrs_allocated ? &attrs : NULL, prog_argv, + environ)) + != 0)) + { + if (actions_allocated) + posix_spawn_file_actions_destroy (&actions); + if (attrs_allocated) + posix_spawnattr_destroy (&attrs); + if (slave_process) + unblock_fatal_signals (); + if (termsigp != NULL) + *termsigp = 0; + if (exit_on_error || !null_stderr) + error (exit_on_error ? EXIT_FAILURE : 0, err, + _("%s subprocess failed"), progname); + return 127; + } + posix_spawn_file_actions_destroy (&actions); + if (attrs_allocated) + posix_spawnattr_destroy (&attrs); + if (slave_process) + { + register_slave_subprocess (child); + unblock_fatal_signals (); + } + + return wait_subprocess (child, progname, ignore_sigpipe, null_stderr, + slave_process, exit_on_error, termsigp); + +#endif +} diff --git a/gettext-tools/gnulib-lib/execute.h b/gettext-tools/gnulib-lib/execute.h new file mode 100644 index 0000000..8bc0285 --- /dev/null +++ b/gettext-tools/gnulib-lib/execute.h @@ -0,0 +1,44 @@ +/* Creation of autonomous subprocesses. + Copyright (C) 2001-2003, 2008-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2001. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _EXECUTE_H +#define _EXECUTE_H + +#include + +/* Execute a command, optionally redirecting any of the three standard file + descriptors to /dev/null. Return its exit code. + If it didn't terminate correctly, exit if exit_on_error is true, otherwise + return 127. + If ignore_sigpipe is true, consider a subprocess termination due to SIGPIPE + as equivalent to a success. This is suitable for processes whose only + purpose is to write to standard output. + If slave_process is true, the child process will be terminated when its + creator receives a catchable fatal signal. + If termsigp is not NULL, *termsig will be set to the signal that terminated + the subprocess (if supported by the platform: not on native Windows + platforms), otherwise 0. + It is recommended that no signal is blocked or ignored while execute() + is called. See pipe.h for the reason. */ +extern int execute (const char *progname, + const char *prog_path, char **prog_argv, + bool ignore_sigpipe, + bool null_stdin, bool null_stdout, bool null_stderr, + bool slave_process, bool exit_on_error, + int *termsigp); + +#endif /* _EXECUTE_H */ diff --git a/gettext-tools/gnulib-lib/exitfail.c b/gettext-tools/gnulib-lib/exitfail.c new file mode 100644 index 0000000..609afc5 --- /dev/null +++ b/gettext-tools/gnulib-lib/exitfail.c @@ -0,0 +1,24 @@ +/* Failure exit status + + Copyright (C) 2002-2003, 2005-2007, 2009-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +#include "exitfail.h" + +#include + +int volatile exit_failure = EXIT_FAILURE; diff --git a/gettext-tools/gnulib-lib/exitfail.h b/gettext-tools/gnulib-lib/exitfail.h new file mode 100644 index 0000000..2b1daca --- /dev/null +++ b/gettext-tools/gnulib-lib/exitfail.h @@ -0,0 +1,18 @@ +/* Failure exit status + + Copyright (C) 2002, 2009-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +extern DLL_VARIABLE int volatile exit_failure; diff --git a/gettext-tools/gnulib-lib/fatal-signal.c b/gettext-tools/gnulib-lib/fatal-signal.c new file mode 100644 index 0000000..9a6f5f1 --- /dev/null +++ b/gettext-tools/gnulib-lib/fatal-signal.c @@ -0,0 +1,286 @@ +/* Emergency actions in case of a fatal signal. + Copyright (C) 2003-2004, 2006-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2003. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + + +#include + +/* Specification. */ +#include "fatal-signal.h" + +#include +#include +#include +#include + +#include "sig-handler.h" +#include "xalloc.h" + +#define SIZEOF(a) (sizeof(a) / sizeof(a[0])) + +/* ========================================================================= */ + + +/* The list of fatal signals. + These are those signals whose default action is to terminate the process + without a core dump, except + SIGKILL - because it cannot be caught, + SIGALRM SIGUSR1 SIGUSR2 SIGPOLL SIGIO SIGLOST - because applications + often use them for their own purpose, + SIGPROF SIGVTALRM - because they are used for profiling, + SIGSTKFLT - because it is more similar to SIGFPE, SIGSEGV, SIGBUS, + SIGSYS - because it is more similar to SIGABRT, SIGSEGV, + SIGPWR - because it of too special use, + SIGRTMIN...SIGRTMAX - because they are reserved for application use. + plus + SIGXCPU, SIGXFSZ - because they are quite similar to SIGTERM. */ + +static int fatal_signals[] = + { + /* ISO C 99 signals. */ +#ifdef SIGINT + SIGINT, +#endif +#ifdef SIGTERM + SIGTERM, +#endif + /* POSIX:2001 signals. */ +#ifdef SIGHUP + SIGHUP, +#endif +#ifdef SIGPIPE + SIGPIPE, +#endif + /* BSD signals. */ +#ifdef SIGXCPU + SIGXCPU, +#endif +#ifdef SIGXFSZ + SIGXFSZ, +#endif + /* Native Windows signals. */ +#ifdef SIGBREAK + SIGBREAK, +#endif + 0 + }; + +#define num_fatal_signals (SIZEOF (fatal_signals) - 1) + +/* Eliminate signals whose signal handler is SIG_IGN. */ + +static void +init_fatal_signals (void) +{ + static bool fatal_signals_initialized = false; + if (!fatal_signals_initialized) + { + size_t i; + + for (i = 0; i < num_fatal_signals; i++) + { + struct sigaction action; + + if (sigaction (fatal_signals[i], NULL, &action) >= 0 + && get_handler (&action) == SIG_IGN) + fatal_signals[i] = -1; + } + + fatal_signals_initialized = true; + } +} + + +/* ========================================================================= */ + + +typedef void (*action_t) (void); + +/* Type of an entry in the actions array. + The 'action' field is accessed from within the fatal_signal_handler(), + therefore we mark it as 'volatile'. */ +typedef struct +{ + volatile action_t action; +} +actions_entry_t; + +/* The registered cleanup actions. */ +static actions_entry_t static_actions[32]; +static actions_entry_t * volatile actions = static_actions; +static sig_atomic_t volatile actions_count = 0; +static size_t actions_allocated = SIZEOF (static_actions); + + +/* The saved signal handlers. + Size 32 would not be sufficient: On HP-UX, SIGXCPU = 33, SIGXFSZ = 34. */ +static struct sigaction saved_sigactions[64]; + + +/* Uninstall the handlers. */ +static void +uninstall_handlers (void) +{ + size_t i; + + for (i = 0; i < num_fatal_signals; i++) + if (fatal_signals[i] >= 0) + { + int sig = fatal_signals[i]; + if (saved_sigactions[sig].sa_handler == SIG_IGN) + saved_sigactions[sig].sa_handler = SIG_DFL; + sigaction (sig, &saved_sigactions[sig], NULL); + } +} + + +/* The signal handler. It gets called asynchronously. */ +static void +fatal_signal_handler (int sig) +{ + for (;;) + { + /* Get the last registered cleanup action, in a reentrant way. */ + action_t action; + size_t n = actions_count; + if (n == 0) + break; + n--; + actions_count = n; + action = actions[n].action; + /* Execute the action. */ + action (); + } + + /* Now execute the signal's default action. + If the signal being delivered was blocked, the re-raised signal would be + delivered when this handler returns. But the way we install this handler, + no signal is blocked, and the re-raised signal is delivered already + during raise(). */ + uninstall_handlers (); + raise (sig); +} + + +/* Install the handlers. */ +static void +install_handlers (void) +{ + size_t i; + struct sigaction action; + + action.sa_handler = &fatal_signal_handler; + /* If we get a fatal signal while executing fatal_signal_handler, enter + fatal_signal_handler recursively, since it is reentrant. Hence no + SA_RESETHAND. */ + action.sa_flags = SA_NODEFER; + sigemptyset (&action.sa_mask); + for (i = 0; i < num_fatal_signals; i++) + if (fatal_signals[i] >= 0) + { + int sig = fatal_signals[i]; + + if (!(sig < sizeof (saved_sigactions) / sizeof (saved_sigactions[0]))) + abort (); + sigaction (sig, &action, &saved_sigactions[sig]); + } +} + + +/* Register a cleanup function to be executed when a catchable fatal signal + occurs. */ +void +at_fatal_signal (action_t action) +{ + static bool cleanup_initialized = false; + if (!cleanup_initialized) + { + init_fatal_signals (); + install_handlers (); + cleanup_initialized = true; + } + + if (actions_count == actions_allocated) + { + /* Extend the actions array. Note that we cannot use xrealloc(), + because then the cleanup() function could access an already + deallocated array. */ + actions_entry_t *old_actions = actions; + size_t old_actions_allocated = actions_allocated; + size_t new_actions_allocated = 2 * actions_allocated; + actions_entry_t *new_actions = + XNMALLOC (new_actions_allocated, actions_entry_t); + size_t k; + + /* Don't use memcpy() here, because memcpy takes non-volatile arguments + and is therefore not guaranteed to complete all memory stores before + the next statement. */ + for (k = 0; k < old_actions_allocated; k++) + new_actions[k] = old_actions[k]; + actions = new_actions; + actions_allocated = new_actions_allocated; + /* Now we can free the old actions array. */ + if (old_actions != static_actions) + free (old_actions); + } + /* The two uses of 'volatile' in the types above (and ISO C 99 section + 5.1.2.3.(5)) ensure that we increment the actions_count only after + the new action has been written to the memory location + actions[actions_count]. */ + actions[actions_count].action = action; + actions_count++; +} + + +/* ========================================================================= */ + + +static sigset_t fatal_signal_set; + +static void +init_fatal_signal_set (void) +{ + static bool fatal_signal_set_initialized = false; + if (!fatal_signal_set_initialized) + { + size_t i; + + init_fatal_signals (); + + sigemptyset (&fatal_signal_set); + for (i = 0; i < num_fatal_signals; i++) + if (fatal_signals[i] >= 0) + sigaddset (&fatal_signal_set, fatal_signals[i]); + + fatal_signal_set_initialized = true; + } +} + +/* Temporarily delay the catchable fatal signals. */ +void +block_fatal_signals (void) +{ + init_fatal_signal_set (); + sigprocmask (SIG_BLOCK, &fatal_signal_set, NULL); +} + +/* Stop delaying the catchable fatal signals. */ +void +unblock_fatal_signals (void) +{ + init_fatal_signal_set (); + sigprocmask (SIG_UNBLOCK, &fatal_signal_set, NULL); +} diff --git a/gettext-tools/gnulib-lib/fatal-signal.h b/gettext-tools/gnulib-lib/fatal-signal.h new file mode 100644 index 0000000..de98317 --- /dev/null +++ b/gettext-tools/gnulib-lib/fatal-signal.h @@ -0,0 +1,76 @@ +/* Emergency actions in case of a fatal signal. + Copyright (C) 2003-2004, 2009-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2003. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* It is often useful to do some cleanup action when a usually fatal signal + terminates the process, like removing a temporary file or killing a + subprocess that may be stuck waiting for a device, pipe or network input. + Such signals are SIGHUP, SIGINT, SIGPIPE, SIGTERM, and possibly others. + The limitation of this facility is that it cannot work for SIGKILL. + + Signals with a SIG_IGN handler are considered to be non-fatal. The + functions in this file assume that when a SIG_IGN handler is installed + for a signal, it was installed before any functions in this file were + called and it stays so for the whole lifetime of the process. */ + +/* Register a cleanup function to be executed when a catchable fatal signal + occurs. + + Restrictions for the cleanup function: + - The cleanup function can do all kinds of system calls. + - It can also access application dependent memory locations and data + structures provided they are in a consistent state. One way to ensure + this is through block_fatal_signals()/unblock_fatal_signals(), see + below. Another - more tricky - way to ensure this is the careful use + of 'volatile'. + However, + - malloc() and similarly complex facilities are not safe to be called + because they are not guaranteed to be in a consistent state. + - Also, the cleanup function must not block the catchable fatal signals + and leave them blocked upon return. + + The cleanup function is executed asynchronously. It is unspecified + whether during its execution the catchable fatal signals are blocked + or not. */ +extern void at_fatal_signal (void (*function) (void)); + + +/* Sometimes it is necessary to block the usually fatal signals while the + data structures being accessed by the cleanup action are being built or + reorganized. This is the case, for example, when a temporary file or + directory is created through mkstemp() or mkdtemp(), because these + functions create the temporary file or directory _before_ returning its + name to the application. */ + +/* Temporarily delay the catchable fatal signals. + The signals will be blocked (= delayed) until the next call to + unblock_fatal_signals(). If the signals are already blocked, a further + call to block_fatal_signals() has no effect. */ +extern void block_fatal_signals (void); + +/* Stop delaying the catchable fatal signals. */ +extern void unblock_fatal_signals (void); + + +#ifdef __cplusplus +} +#endif diff --git a/gettext-tools/gnulib-lib/fcntl.c b/gettext-tools/gnulib-lib/fcntl.c new file mode 100644 index 0000000..1e35dd1 --- /dev/null +++ b/gettext-tools/gnulib-lib/fcntl.c @@ -0,0 +1,327 @@ +/* Provide file descriptor control. + + Copyright (C) 2009-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Written by Eric Blake . */ + +#include + +/* Specification. */ +#include + +#include +#include +#include +#include + +#if !HAVE_FCNTL +# define rpl_fcntl fcntl +#endif +#undef fcntl + +#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ +/* Get declarations of the native Windows API functions. */ +# define WIN32_LEAN_AND_MEAN +# include + +/* Get _get_osfhandle. */ +# include "msvc-nothrow.h" + +/* Upper bound on getdtablesize(). See lib/getdtablesize.c. */ +# define OPEN_MAX_MAX 0x10000 + +/* Duplicate OLDFD into the first available slot of at least NEWFD, + which must be positive, with FLAGS determining whether the duplicate + will be inheritable. */ +static int +dupfd (int oldfd, int newfd, int flags) +{ + /* Mingw has no way to create an arbitrary fd. Iterate until all + file descriptors less than newfd are filled up. */ + HANDLE curr_process = GetCurrentProcess (); + HANDLE old_handle = (HANDLE) _get_osfhandle (oldfd); + unsigned char fds_to_close[OPEN_MAX_MAX / CHAR_BIT]; + unsigned int fds_to_close_bound = 0; + int result; + BOOL inherit = flags & O_CLOEXEC ? FALSE : TRUE; + int mode; + + if (newfd < 0 || getdtablesize () <= newfd) + { + errno = EINVAL; + return -1; + } + if (old_handle == INVALID_HANDLE_VALUE + || (mode = setmode (oldfd, O_BINARY)) == -1) + { + /* oldfd is not open, or is an unassigned standard file + descriptor. */ + errno = EBADF; + return -1; + } + setmode (oldfd, mode); + flags |= mode; + + for (;;) + { + HANDLE new_handle; + int duplicated_fd; + unsigned int index; + + if (!DuplicateHandle (curr_process, /* SourceProcessHandle */ + old_handle, /* SourceHandle */ + curr_process, /* TargetProcessHandle */ + (PHANDLE) &new_handle, /* TargetHandle */ + (DWORD) 0, /* DesiredAccess */ + inherit, /* InheritHandle */ + DUPLICATE_SAME_ACCESS)) /* Options */ + { + switch (GetLastError ()) + { + case ERROR_TOO_MANY_OPEN_FILES: + errno = EMFILE; + break; + case ERROR_INVALID_HANDLE: + case ERROR_INVALID_TARGET_HANDLE: + case ERROR_DIRECT_ACCESS_HANDLE: + errno = EBADF; + break; + case ERROR_INVALID_PARAMETER: + case ERROR_INVALID_FUNCTION: + case ERROR_INVALID_ACCESS: + errno = EINVAL; + break; + default: + errno = EACCES; + break; + } + result = -1; + break; + } + duplicated_fd = _open_osfhandle ((intptr_t) new_handle, flags); + if (duplicated_fd < 0) + { + CloseHandle (new_handle); + result = -1; + break; + } + if (newfd <= duplicated_fd) + { + result = duplicated_fd; + break; + } + + /* Set the bit duplicated_fd in fds_to_close[]. */ + index = (unsigned int) duplicated_fd / CHAR_BIT; + if (fds_to_close_bound <= index) + { + if (sizeof fds_to_close <= index) + /* Need to increase OPEN_MAX_MAX. */ + abort (); + memset (fds_to_close + fds_to_close_bound, '\0', + index + 1 - fds_to_close_bound); + fds_to_close_bound = index + 1; + } + fds_to_close[index] |= 1 << ((unsigned int) duplicated_fd % CHAR_BIT); + } + + /* Close the previous fds that turned out to be too small. */ + { + int saved_errno = errno; + unsigned int duplicated_fd; + + for (duplicated_fd = 0; + duplicated_fd < fds_to_close_bound * CHAR_BIT; + duplicated_fd++) + if ((fds_to_close[duplicated_fd / CHAR_BIT] + >> (duplicated_fd % CHAR_BIT)) + & 1) + close (duplicated_fd); + + errno = saved_errno; + } + +# if REPLACE_FCHDIR + if (0 <= result) + result = _gl_register_dup (oldfd, result); +# endif + return result; +} +#endif /* W32 */ + +/* Perform the specified ACTION on the file descriptor FD, possibly + using the argument ARG further described below. This replacement + handles the following actions, and forwards all others on to the + native fcntl. An unrecognized ACTION returns -1 with errno set to + EINVAL. + + F_DUPFD - duplicate FD, with int ARG being the minimum target fd. + If successful, return the duplicate, which will be inheritable; + otherwise return -1 and set errno. + + F_DUPFD_CLOEXEC - duplicate FD, with int ARG being the minimum + target fd. If successful, return the duplicate, which will not be + inheritable; otherwise return -1 and set errno. + + F_GETFD - ARG need not be present. If successful, return a + non-negative value containing the descriptor flags of FD (only + FD_CLOEXEC is portable, but other flags may be present); otherwise + return -1 and set errno. */ + +int +rpl_fcntl (int fd, int action, /* arg */...) +{ + va_list arg; + int result = -1; + va_start (arg, action); + switch (action) + { + +#if !HAVE_FCNTL + case F_DUPFD: + { + int target = va_arg (arg, int); + result = dupfd (fd, target, 0); + break; + } +#elif FCNTL_DUPFD_BUGGY || REPLACE_FCHDIR + case F_DUPFD: + { + int target = va_arg (arg, int); + /* Detect invalid target; needed for cygwin 1.5.x. */ + if (target < 0 || getdtablesize () <= target) + errno = EINVAL; + else + { + /* Haiku alpha 2 loses fd flags on original. */ + int flags = fcntl (fd, F_GETFD); + if (flags < 0) + { + result = -1; + break; + } + result = fcntl (fd, action, target); + if (0 <= result && fcntl (fd, F_SETFD, flags) == -1) + { + int saved_errno = errno; + close (result); + result = -1; + errno = saved_errno; + } +# if REPLACE_FCHDIR + if (0 <= result) + result = _gl_register_dup (fd, result); +# endif + } + break; + } /* F_DUPFD */ +#endif /* FCNTL_DUPFD_BUGGY || REPLACE_FCHDIR */ + + case F_DUPFD_CLOEXEC: + { + int target = va_arg (arg, int); + +#if !HAVE_FCNTL + result = dupfd (fd, target, O_CLOEXEC); + break; +#else /* HAVE_FCNTL */ + /* Try the system call first, if the headers claim it exists + (that is, if GNULIB_defined_F_DUPFD_CLOEXEC is 0), since we + may be running with a glibc that has the macro but with an + older kernel that does not support it. Cache the + information on whether the system call really works, but + avoid caching failure if the corresponding F_DUPFD fails + for any reason. 0 = unknown, 1 = yes, -1 = no. */ + static int have_dupfd_cloexec = GNULIB_defined_F_DUPFD_CLOEXEC ? -1 : 0; + if (0 <= have_dupfd_cloexec) + { + result = fcntl (fd, action, target); + if (0 <= result || errno != EINVAL) + { + have_dupfd_cloexec = 1; +# if REPLACE_FCHDIR + if (0 <= result) + result = _gl_register_dup (fd, result); +# endif + } + else + { + result = rpl_fcntl (fd, F_DUPFD, target); + if (result < 0) + break; + have_dupfd_cloexec = -1; + } + } + else + result = rpl_fcntl (fd, F_DUPFD, target); + if (0 <= result && have_dupfd_cloexec == -1) + { + int flags = fcntl (result, F_GETFD); + if (flags < 0 || fcntl (result, F_SETFD, flags | FD_CLOEXEC) == -1) + { + int saved_errno = errno; + close (result); + errno = saved_errno; + result = -1; + } + } + break; +#endif /* HAVE_FCNTL */ + } /* F_DUPFD_CLOEXEC */ + +#if !HAVE_FCNTL + case F_GETFD: + { +# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ + HANDLE handle = (HANDLE) _get_osfhandle (fd); + DWORD flags; + if (handle == INVALID_HANDLE_VALUE + || GetHandleInformation (handle, &flags) == 0) + errno = EBADF; + else + result = (flags & HANDLE_FLAG_INHERIT) ? 0 : FD_CLOEXEC; +# else /* !W32 */ + /* Use dup2 to reject invalid file descriptors. No way to + access this information, so punt. */ + if (0 <= dup2 (fd, fd)) + result = 0; +# endif /* !W32 */ + break; + } /* F_GETFD */ +#endif /* !HAVE_FCNTL */ + + /* Implementing F_SETFD on mingw is not trivial - there is no + API for changing the O_NOINHERIT bit on an fd, and merely + changing the HANDLE_FLAG_INHERIT bit on the underlying handle + can lead to odd state. It may be possible by duplicating the + handle, using _open_osfhandle with the right flags, then + using dup2 to move the duplicate onto the original, but that + is not supported for now. */ + + default: + { +#if HAVE_FCNTL + void *p = va_arg (arg, void *); + result = fcntl (fd, action, p); +#else + errno = EINVAL; +#endif + break; + } + } + va_end (arg); + return result; +} diff --git a/gettext-tools/gnulib-lib/fcntl.in.h b/gettext-tools/gnulib-lib/fcntl.in.h new file mode 100644 index 0000000..f63cd6a --- /dev/null +++ b/gettext-tools/gnulib-lib/fcntl.in.h @@ -0,0 +1,363 @@ +/* Like , but with non-working flags defined to 0. + + Copyright (C) 2006-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* written by Paul Eggert */ + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +#if defined __need_system_fcntl_h +/* Special invocation convention. */ + +/* Needed before . + May also define off_t to a 64-bit type on native Windows. */ +#include +/* On some systems other than glibc, is a prerequisite of + . On glibc systems, we would like to avoid namespace pollution. + But on glibc systems, includes inside an + extern "C" { ... } block, which leads to errors in C++ mode with the + overridden from gnulib. These errors are known to be gone + with g++ version >= 4.3. */ +#if !(defined __GLIBC__ || defined __UCLIBC__) || (defined __cplusplus && defined GNULIB_NAMESPACE && (defined __ICC || !(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)))) +# include +#endif +#@INCLUDE_NEXT@ @NEXT_FCNTL_H@ + +#else +/* Normal invocation convention. */ + +#ifndef _@GUARD_PREFIX@_FCNTL_H + +/* Needed before . + May also define off_t to a 64-bit type on native Windows. */ +#include +/* On some systems other than glibc, is a prerequisite of + . On glibc systems, we would like to avoid namespace pollution. + But on glibc systems, includes inside an + extern "C" { ... } block, which leads to errors in C++ mode with the + overridden from gnulib. These errors are known to be gone + with g++ version >= 4.3. */ +#if !(defined __GLIBC__ || defined __UCLIBC__) || (defined __cplusplus && defined GNULIB_NAMESPACE && (defined __ICC || !(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)))) +# include +#endif +/* The include_next requires a split double-inclusion guard. */ +#@INCLUDE_NEXT@ @NEXT_FCNTL_H@ + +#ifndef _@GUARD_PREFIX@_FCNTL_H +#define _@GUARD_PREFIX@_FCNTL_H + +#ifndef __GLIBC__ /* Avoid namespace pollution on glibc systems. */ +# include +#endif + +/* Native Windows platforms declare open(), creat() in . */ +#if (@GNULIB_OPEN@ || defined GNULIB_POSIXCHECK) \ + && ((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__) +# include +#endif + + +/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ + +/* The definition of _GL_ARG_NONNULL is copied here. */ + +/* The definition of _GL_WARN_ON_USE is copied here. */ + + +/* Declare overridden functions. */ + +#if @GNULIB_FCNTL@ +# if @REPLACE_FCNTL@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef fcntl +# define fcntl rpl_fcntl +# endif +_GL_FUNCDECL_RPL (fcntl, int, (int fd, int action, ...)); +_GL_CXXALIAS_RPL (fcntl, int, (int fd, int action, ...)); +# else +# if !@HAVE_FCNTL@ +_GL_FUNCDECL_SYS (fcntl, int, (int fd, int action, ...)); +# endif +_GL_CXXALIAS_SYS (fcntl, int, (int fd, int action, ...)); +# endif +_GL_CXXALIASWARN (fcntl); +#elif defined GNULIB_POSIXCHECK +# undef fcntl +# if HAVE_RAW_DECL_FCNTL +_GL_WARN_ON_USE (fcntl, "fcntl is not always POSIX compliant - " + "use gnulib module fcntl for portability"); +# endif +#endif + +#if @GNULIB_OPEN@ +# if @REPLACE_OPEN@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef open +# define open rpl_open +# endif +_GL_FUNCDECL_RPL (open, int, (const char *filename, int flags, ...) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (open, int, (const char *filename, int flags, ...)); +# else +_GL_CXXALIAS_SYS (open, int, (const char *filename, int flags, ...)); +# endif +/* On HP-UX 11, in C++ mode, open() is defined as an inline function with a + default argument. _GL_CXXALIASWARN does not work in this case. */ +# if !defined __hpux +_GL_CXXALIASWARN (open); +# endif +#elif defined GNULIB_POSIXCHECK +# undef open +/* Assume open is always declared. */ +_GL_WARN_ON_USE (open, "open is not always POSIX compliant - " + "use gnulib module open for portability"); +#endif + +#if @GNULIB_OPENAT@ +# if @REPLACE_OPENAT@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef openat +# define openat rpl_openat +# endif +_GL_FUNCDECL_RPL (openat, int, + (int fd, char const *file, int flags, /* mode_t mode */ ...) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (openat, int, + (int fd, char const *file, int flags, /* mode_t mode */ ...)); +# else +# if !@HAVE_OPENAT@ +_GL_FUNCDECL_SYS (openat, int, + (int fd, char const *file, int flags, /* mode_t mode */ ...) + _GL_ARG_NONNULL ((2))); +# endif +_GL_CXXALIAS_SYS (openat, int, + (int fd, char const *file, int flags, /* mode_t mode */ ...)); +# endif +_GL_CXXALIASWARN (openat); +#elif defined GNULIB_POSIXCHECK +# undef openat +# if HAVE_RAW_DECL_OPENAT +_GL_WARN_ON_USE (openat, "openat is not portable - " + "use gnulib module openat for portability"); +# endif +#endif + + +/* Fix up the FD_* macros, only known to be missing on mingw. */ + +#ifndef FD_CLOEXEC +# define FD_CLOEXEC 1 +#endif + +/* Fix up the supported F_* macros. Intentionally leave other F_* + macros undefined. Only known to be missing on mingw. */ + +#ifndef F_DUPFD_CLOEXEC +# define F_DUPFD_CLOEXEC 0x40000000 +/* Witness variable: 1 if gnulib defined F_DUPFD_CLOEXEC, 0 otherwise. */ +# define GNULIB_defined_F_DUPFD_CLOEXEC 1 +#else +# define GNULIB_defined_F_DUPFD_CLOEXEC 0 +#endif + +#ifndef F_DUPFD +# define F_DUPFD 1 +#endif + +#ifndef F_GETFD +# define F_GETFD 2 +#endif + +/* Fix up the O_* macros. */ + +/* AIX 7.1 with XL C 12.1 defines O_CLOEXEC, O_NOFOLLOW, and O_TTY_INIT + to values outside 'int' range, so omit these misdefinitions. + But avoid namespace pollution on non-AIX systems. */ +#ifdef _AIX +# include +# if defined O_CLOEXEC && ! (INT_MIN <= O_CLOEXEC && O_CLOEXEC <= INT_MAX) +# undef O_CLOEXEC +# endif +# if defined O_NOFOLLOW && ! (INT_MIN <= O_NOFOLLOW && O_NOFOLLOW <= INT_MAX) +# undef O_NOFOLLOW +# endif +# if defined O_TTY_INIT && ! (INT_MIN <= O_TTY_INIT && O_TTY_INIT <= INT_MAX) +# undef O_TTY_INIT +# endif +#endif + +#if !defined O_DIRECT && defined O_DIRECTIO +/* Tru64 spells it 'O_DIRECTIO'. */ +# define O_DIRECT O_DIRECTIO +#endif + +#if !defined O_CLOEXEC && defined O_NOINHERIT +/* Mingw spells it 'O_NOINHERIT'. */ +# define O_CLOEXEC O_NOINHERIT +#endif + +#ifndef O_CLOEXEC +# define O_CLOEXEC 0 +#endif + +#ifndef O_DIRECT +# define O_DIRECT 0 +#endif + +#ifndef O_DIRECTORY +# define O_DIRECTORY 0 +#endif + +#ifndef O_DSYNC +# define O_DSYNC 0 +#endif + +#ifndef O_EXEC +# define O_EXEC O_RDONLY /* This is often close enough in older systems. */ +#endif + +#ifndef O_IGNORE_CTTY +# define O_IGNORE_CTTY 0 +#endif + +#ifndef O_NDELAY +# define O_NDELAY 0 +#endif + +#ifndef O_NOATIME +# define O_NOATIME 0 +#endif + +#ifndef O_NONBLOCK +# define O_NONBLOCK O_NDELAY +#endif + +/* If the gnulib module 'nonblocking' is in use, guarantee a working non-zero + value of O_NONBLOCK. Otherwise, O_NONBLOCK is defined (above) to O_NDELAY + or to 0 as fallback. */ +#if @GNULIB_NONBLOCKING@ +# if O_NONBLOCK +# define GNULIB_defined_O_NONBLOCK 0 +# else +# define GNULIB_defined_O_NONBLOCK 1 +# undef O_NONBLOCK +# define O_NONBLOCK 0x40000000 +# endif +#endif + +#ifndef O_NOCTTY +# define O_NOCTTY 0 +#endif + +#ifndef O_NOFOLLOW +# define O_NOFOLLOW 0 +#endif + +#ifndef O_NOLINK +# define O_NOLINK 0 +#endif + +#ifndef O_NOLINKS +# define O_NOLINKS 0 +#endif + +#ifndef O_NOTRANS +# define O_NOTRANS 0 +#endif + +#ifndef O_RSYNC +# define O_RSYNC 0 +#endif + +#ifndef O_SEARCH +# define O_SEARCH O_RDONLY /* This is often close enough in older systems. */ +#endif + +#ifndef O_SYNC +# define O_SYNC 0 +#endif + +#ifndef O_TTY_INIT +# define O_TTY_INIT 0 +#endif + +#if ~O_ACCMODE & (O_RDONLY | O_WRONLY | O_RDWR | O_EXEC | O_SEARCH) +# undef O_ACCMODE +# define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR | O_EXEC | O_SEARCH) +#endif + +/* For systems that distinguish between text and binary I/O. + O_BINARY is usually declared in fcntl.h */ +#if !defined O_BINARY && defined _O_BINARY + /* For MSC-compatible compilers. */ +# define O_BINARY _O_BINARY +# define O_TEXT _O_TEXT +#endif + +#if defined __BEOS__ || defined __HAIKU__ + /* BeOS 5 and Haiku have O_BINARY and O_TEXT, but they have no effect. */ +# undef O_BINARY +# undef O_TEXT +#endif + +#ifndef O_BINARY +# define O_BINARY 0 +# define O_TEXT 0 +#endif + +/* Fix up the AT_* macros. */ + +/* Work around a bug in Solaris 9 and 10: AT_FDCWD is positive. Its + value exceeds INT_MAX, so its use as an int doesn't conform to the + C standard, and GCC and Sun C complain in some cases. If the bug + is present, undef AT_FDCWD here, so it can be redefined below. */ +#if 0 < AT_FDCWD && AT_FDCWD == 0xffd19553 +# undef AT_FDCWD +#endif + +/* Use the same bit pattern as Solaris 9, but with the proper + signedness. The bit pattern is important, in case this actually is + Solaris with the above workaround. */ +#ifndef AT_FDCWD +# define AT_FDCWD (-3041965) +#endif + +/* Use the same values as Solaris 9. This shouldn't matter, but + there's no real reason to differ. */ +#ifndef AT_SYMLINK_NOFOLLOW +# define AT_SYMLINK_NOFOLLOW 4096 +#endif + +#ifndef AT_REMOVEDIR +# define AT_REMOVEDIR 1 +#endif + +/* Solaris 9 lacks these two, so just pick unique values. */ +#ifndef AT_SYMLINK_FOLLOW +# define AT_SYMLINK_FOLLOW 2 +#endif + +#ifndef AT_EACCESS +# define AT_EACCESS 4 +#endif + + +#endif /* _@GUARD_PREFIX@_FCNTL_H */ +#endif /* _@GUARD_PREFIX@_FCNTL_H */ +#endif diff --git a/gettext-tools/gnulib-lib/fd-hook.c b/gettext-tools/gnulib-lib/fd-hook.c new file mode 100644 index 0000000..0171cc6 --- /dev/null +++ b/gettext-tools/gnulib-lib/fd-hook.c @@ -0,0 +1,116 @@ +/* Hook for making making file descriptor functions close(), ioctl() extensible. + Copyright (C) 2009-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2009. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include "fd-hook.h" + +#include + +/* Currently, this entire code is only needed for the handling of sockets + on native Windows platforms. */ +#if WINDOWS_SOCKETS + +/* The first and last link in the doubly linked list. + Initially the list is empty. */ +static struct fd_hook anchor = { &anchor, &anchor, NULL, NULL }; + +int +execute_close_hooks (const struct fd_hook *remaining_list, gl_close_fn primary, + int fd) +{ + if (remaining_list == &anchor) + /* End of list reached. */ + return primary (fd); + else + return remaining_list->private_close_fn (remaining_list->private_next, + primary, fd); +} + +int +execute_all_close_hooks (gl_close_fn primary, int fd) +{ + return execute_close_hooks (anchor.private_next, primary, fd); +} + +int +execute_ioctl_hooks (const struct fd_hook *remaining_list, gl_ioctl_fn primary, + int fd, int request, void *arg) +{ + if (remaining_list == &anchor) + /* End of list reached. */ + return primary (fd, request, arg); + else + return remaining_list->private_ioctl_fn (remaining_list->private_next, + primary, fd, request, arg); +} + +int +execute_all_ioctl_hooks (gl_ioctl_fn primary, + int fd, int request, void *arg) +{ + return execute_ioctl_hooks (anchor.private_next, primary, fd, request, arg); +} + +void +register_fd_hook (close_hook_fn close_hook, ioctl_hook_fn ioctl_hook, struct fd_hook *link) +{ + if (close_hook == NULL) + close_hook = execute_close_hooks; + if (ioctl_hook == NULL) + ioctl_hook = execute_ioctl_hooks; + + if (link->private_next == NULL && link->private_prev == NULL) + { + /* Add the link to the doubly linked list. */ + link->private_next = anchor.private_next; + link->private_prev = &anchor; + link->private_close_fn = close_hook; + link->private_ioctl_fn = ioctl_hook; + anchor.private_next->private_prev = link; + anchor.private_next = link; + } + else + { + /* The link is already in use. */ + if (link->private_close_fn != close_hook + || link->private_ioctl_fn != ioctl_hook) + abort (); + } +} + +void +unregister_fd_hook (struct fd_hook *link) +{ + struct fd_hook *next = link->private_next; + struct fd_hook *prev = link->private_prev; + + if (next != NULL && prev != NULL) + { + /* The link is in use. Remove it from the doubly linked list. */ + prev->private_next = next; + next->private_prev = prev; + /* Clear the link, to mark it unused. */ + link->private_next = NULL; + link->private_prev = NULL; + link->private_close_fn = NULL; + link->private_ioctl_fn = NULL; + } +} + +#endif diff --git a/gettext-tools/gnulib-lib/fd-hook.h b/gettext-tools/gnulib-lib/fd-hook.h new file mode 100644 index 0000000..1aa264e --- /dev/null +++ b/gettext-tools/gnulib-lib/fd-hook.h @@ -0,0 +1,119 @@ +/* Hook for making making file descriptor functions close(), ioctl() extensible. + Copyright (C) 2009-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + + +#ifndef FD_HOOK_H +#define FD_HOOK_H + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Currently, this entire code is only needed for the handling of sockets + on native Windows platforms. */ +#if WINDOWS_SOCKETS + + +/* Type of function that closes FD. */ +typedef int (*gl_close_fn) (int fd); + +/* Type of function that applies a control request to FD. */ +typedef int (*gl_ioctl_fn) (int fd, int request, void *arg); + +/* An element of the list of file descriptor hooks. + In CLOS (Common Lisp Object System) speak, it consists of an "around" + method for the close() function and an "around" method for the ioctl() + function. + The fields of this structure are considered private. */ +struct fd_hook +{ + /* Doubly linked list. */ + struct fd_hook *private_next; + struct fd_hook *private_prev; + /* Function that treats the types of FD that it knows about and calls + execute_close_hooks (REMAINING_LIST, PRIMARY, FD) as a fallback. */ + int (*private_close_fn) (const struct fd_hook *remaining_list, + gl_close_fn primary, + int fd); + /* Function that treats the types of FD that it knows about and calls + execute_ioctl_hooks (REMAINING_LIST, PRIMARY, FD, REQUEST, ARG) as a + fallback. */ + int (*private_ioctl_fn) (const struct fd_hook *remaining_list, + gl_ioctl_fn primary, + int fd, int request, void *arg); +}; + +/* This type of function closes FD, applying special knowledge for the FD + types it knows about, and calls + execute_close_hooks (REMAINING_LIST, PRIMARY, FD) + for the other FD types. + In CLOS speak, REMAINING_LIST is the remaining list of "around" methods, + and PRIMARY is the "primary" method for close(). */ +typedef int (*close_hook_fn) (const struct fd_hook *remaining_list, + gl_close_fn primary, + int fd); + +/* Execute the close hooks in REMAINING_LIST, with PRIMARY as "primary" method. + Return 0 or -1, like close() would do. */ +extern int execute_close_hooks (const struct fd_hook *remaining_list, + gl_close_fn primary, + int fd); + +/* Execute all close hooks, with PRIMARY as "primary" method. + Return 0 or -1, like close() would do. */ +extern int execute_all_close_hooks (gl_close_fn primary, int fd); + +/* This type of function applies a control request to FD, applying special + knowledge for the FD types it knows about, and calls + execute_ioctl_hooks (REMAINING_LIST, PRIMARY, FD, REQUEST, ARG) + for the other FD types. + In CLOS speak, REMAINING_LIST is the remaining list of "around" methods, + and PRIMARY is the "primary" method for ioctl(). */ +typedef int (*ioctl_hook_fn) (const struct fd_hook *remaining_list, + gl_ioctl_fn primary, + int fd, int request, void *arg); + +/* Execute the ioctl hooks in REMAINING_LIST, with PRIMARY as "primary" method. + Return 0 or -1, like ioctl() would do. */ +extern int execute_ioctl_hooks (const struct fd_hook *remaining_list, + gl_ioctl_fn primary, + int fd, int request, void *arg); + +/* Execute all ioctl hooks, with PRIMARY as "primary" method. + Return 0 or -1, like ioctl() would do. */ +extern int execute_all_ioctl_hooks (gl_ioctl_fn primary, + int fd, int request, void *arg); + +/* Add a function pair to the list of file descriptor hooks. + CLOSE_HOOK and IOCTL_HOOK may be NULL, indicating no change. + The LINK variable points to a piece of memory which is guaranteed to be + accessible until the corresponding call to unregister_fd_hook. */ +extern void register_fd_hook (close_hook_fn close_hook, ioctl_hook_fn ioctl_hook, + struct fd_hook *link); + +/* Removes a hook from the list of file descriptor hooks. */ +extern void unregister_fd_hook (struct fd_hook *link); + + +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* FD_HOOK_H */ diff --git a/gettext-tools/gnulib-lib/fd-ostream.c b/gettext-tools/gnulib-lib/fd-ostream.c new file mode 100644 index 0000000..783fecf --- /dev/null +++ b/gettext-tools/gnulib-lib/fd-ostream.c @@ -0,0 +1,219 @@ +/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ + +#line 1 "fd-ostream.oo.c" +/* Output stream referring to a file descriptor. + Copyright (C) 2006-2007 Free Software Foundation, Inc. + Written by Bruno Haible , 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include "fd-ostream.h" + +#include +#include +#include +#include + +#include "error.h" +#include "full-write.h" +#include "xalloc.h" +#include "gettext.h" + +#define _(str) gettext (str) + +#line 39 "fd-ostream.c" +#if !IS_CPLUSPLUS +#define fd_ostream_representation any_ostream_representation +#endif +#include "fd_ostream.priv.h" + +const typeinfo_t fd_ostream_typeinfo = { "fd_ostream" }; + +static const typeinfo_t * const fd_ostream_superclasses[] = + { fd_ostream_SUPERCLASSES }; + +#define super ostream_vtable + +#line 43 "fd-ostream.oo.c" + +#define BUFSIZE 4096 + +/* Implementation of ostream_t methods. */ + +static void +fd_ostream__write_mem (fd_ostream_t stream, const void *data, size_t len) +{ + if (len > 0) + { + if (stream->buffer != NULL) + { + /* Buffered. */ + assert (stream->avail > 0); + #if 0 /* unoptimized */ + do + { + size_t n = (len <= stream->avail ? len : stream->avail); + if (n > 0) + { + memcpy (stream->buffer + BUFSIZE - stream->avail, data, n); + data = (char *) data + n; + stream->avail -= n; + len -= n; + } + if (stream->avail == 0) + { + if (full_write (stream->fd, stream->buffer, BUFSIZE) < BUFSIZE) + error (EXIT_FAILURE, errno, _("error writing to %s"), + stream->filename); + stream->avail = BUFSIZE; + } + } + while (len > 0); + #else /* optimized */ + if (len < stream->avail) + { + /* Move the data into the buffer. */ + memcpy (stream->buffer + BUFSIZE - stream->avail, data, len); + stream->avail -= len; + } + else + { + /* Split the data into: + - a first chunk, which is added to the buffer and output, + - a series of chunks of size BUFSIZE, which can be output + directly, without going through the buffer, and + - a last chunk, which is copied to the buffer. */ + size_t n = stream->avail; + memcpy (stream->buffer + BUFSIZE - stream->avail, data, n); + data = (char *) data + n; + len -= n; + if (full_write (stream->fd, stream->buffer, BUFSIZE) < BUFSIZE) + error (EXIT_FAILURE, errno, _("error writing to %s"), + stream->filename); + + while (len >= BUFSIZE) + { + if (full_write (stream->fd, data, BUFSIZE) < BUFSIZE) + error (EXIT_FAILURE, errno, _("error writing to %s"), + stream->filename); + data = (char *) data + BUFSIZE; + len -= BUFSIZE; + } + + if (len > 0) + memcpy (stream->buffer, data, len); + stream->avail = BUFSIZE - len; + } + #endif + assert (stream->avail > 0); + } + else + { + /* Unbuffered. */ + if (full_write (stream->fd, data, len) < len) + error (EXIT_FAILURE, errno, _("error writing to %s"), + stream->filename); + } + } +} + +static void +fd_ostream__flush (fd_ostream_t stream) +{ + if (stream->buffer != NULL && stream->avail < BUFSIZE) + { + size_t filled = BUFSIZE - stream->avail; + if (full_write (stream->fd, stream->buffer, filled) < filled) + error (EXIT_FAILURE, errno, _("error writing to %s"), stream->filename); + stream->avail = BUFSIZE; + } +} + +static void +fd_ostream__free (fd_ostream_t stream) +{ + fd_ostream_flush (stream); + free (stream->filename); + free (stream); +} + +/* Constructor. */ + +fd_ostream_t +fd_ostream_create (int fd, const char *filename, bool buffered) +{ + fd_ostream_t stream = + (struct fd_ostream_representation *) + xmalloc (sizeof (struct fd_ostream_representation) + + (buffered ? BUFSIZE : 0)); + + stream->base.vtable = &fd_ostream_vtable; + stream->fd = fd; + stream->filename = xstrdup (filename); + if (buffered) + { + stream->buffer = + (char *) (void *) stream + sizeof (struct fd_ostream_representation); + stream->avail = BUFSIZE; + } + else + stream->buffer = NULL; + + return stream; +} + +#line 180 "fd-ostream.c" + +const struct fd_ostream_implementation fd_ostream_vtable = +{ + fd_ostream_superclasses, + sizeof (fd_ostream_superclasses) / sizeof (fd_ostream_superclasses[0]), + sizeof (struct fd_ostream_representation), + fd_ostream__write_mem, + fd_ostream__flush, + fd_ostream__free, +}; + +#if !HAVE_INLINE + +/* Define the functions that invoke the methods. */ + +void +fd_ostream_write_mem (fd_ostream_t first_arg, const void *data, size_t len) +{ + const struct fd_ostream_implementation *vtable = + ((struct fd_ostream_representation_header *) (struct fd_ostream_representation *) first_arg)->vtable; + vtable->write_mem (first_arg,data,len); +} + +void +fd_ostream_flush (fd_ostream_t first_arg) +{ + const struct fd_ostream_implementation *vtable = + ((struct fd_ostream_representation_header *) (struct fd_ostream_representation *) first_arg)->vtable; + vtable->flush (first_arg); +} + +void +fd_ostream_free (fd_ostream_t first_arg) +{ + const struct fd_ostream_implementation *vtable = + ((struct fd_ostream_representation_header *) (struct fd_ostream_representation *) first_arg)->vtable; + vtable->free (first_arg); +} + +#endif diff --git a/gettext-tools/gnulib-lib/fd-ostream.h b/gettext-tools/gnulib-lib/fd-ostream.h new file mode 100644 index 0000000..c33f6fb --- /dev/null +++ b/gettext-tools/gnulib-lib/fd-ostream.h @@ -0,0 +1,137 @@ +/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ + +#line 1 "fd-ostream.oo.h" +/* Output stream referring to a file descriptor. + Copyright (C) 2006 Free Software Foundation, Inc. + Written by Bruno Haible , 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _FD_OSTREAM_H +#define _FD_OSTREAM_H + +#include + +#include "ostream.h" + + +#line 30 "fd-ostream.h" +struct fd_ostream_representation; +/* fd_ostream_t is defined as a pointer to struct fd_ostream_representation. + In C++ mode, we use a smart pointer class. + In C mode, we have no other choice than a typedef to the root class type. */ +#if IS_CPLUSPLUS +struct fd_ostream_t +{ +private: + struct fd_ostream_representation *_pointer; +public: + fd_ostream_t () : _pointer (NULL) {} + fd_ostream_t (struct fd_ostream_representation *pointer) : _pointer (pointer) {} + struct fd_ostream_representation * operator -> () { return _pointer; } + operator struct fd_ostream_representation * () { return _pointer; } + operator struct any_ostream_representation * () { return (struct any_ostream_representation *) _pointer; } + operator void * () { return _pointer; } + bool operator == (const void *p) { return _pointer == p; } + bool operator != (const void *p) { return _pointer != p; } + operator ostream_t () { return (ostream_t) (struct any_ostream_representation *) _pointer; } + explicit fd_ostream_t (ostream_t x) : _pointer ((struct fd_ostream_representation *) (void *) x) {} +}; +#else +typedef ostream_t fd_ostream_t; +#endif + +/* Functions that invoke the methods. */ +extern void fd_ostream_write_mem (fd_ostream_t first_arg, const void *data, size_t len); +extern void fd_ostream_flush (fd_ostream_t first_arg); +extern void fd_ostream_free (fd_ostream_t first_arg); + +/* Type representing an implementation of fd_ostream_t. */ +struct fd_ostream_implementation +{ + const typeinfo_t * const *superclasses; + size_t superclasses_length; + size_t instance_size; +#define THIS_ARG fd_ostream_t first_arg +#include "fd_ostream.vt.h" +#undef THIS_ARG +}; + +/* Public portion of the object pointed to by a fd_ostream_t. */ +struct fd_ostream_representation_header +{ + const struct fd_ostream_implementation *vtable; +}; + +#if HAVE_INLINE + +/* Define the functions that invoke the methods as inline accesses to + the fd_ostream_implementation. + Use #define to avoid a warning because of extern vs. static. */ + +# define fd_ostream_write_mem fd_ostream_write_mem_inline +static inline void +fd_ostream_write_mem (fd_ostream_t first_arg, const void *data, size_t len) +{ + const struct fd_ostream_implementation *vtable = + ((struct fd_ostream_representation_header *) (struct fd_ostream_representation *) first_arg)->vtable; + vtable->write_mem (first_arg,data,len); +} + +# define fd_ostream_flush fd_ostream_flush_inline +static inline void +fd_ostream_flush (fd_ostream_t first_arg) +{ + const struct fd_ostream_implementation *vtable = + ((struct fd_ostream_representation_header *) (struct fd_ostream_representation *) first_arg)->vtable; + vtable->flush (first_arg); +} + +# define fd_ostream_free fd_ostream_free_inline +static inline void +fd_ostream_free (fd_ostream_t first_arg) +{ + const struct fd_ostream_implementation *vtable = + ((struct fd_ostream_representation_header *) (struct fd_ostream_representation *) first_arg)->vtable; + vtable->free (first_arg); +} + +#endif + +extern const typeinfo_t fd_ostream_typeinfo; +#define fd_ostream_SUPERCLASSES &fd_ostream_typeinfo, ostream_SUPERCLASSES +#define fd_ostream_SUPERCLASSES_LENGTH (1 + ostream_SUPERCLASSES_LENGTH) + +extern const struct fd_ostream_implementation fd_ostream_vtable; + +#line 30 "fd-ostream.oo.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Create an output stream referring to the file descriptor FD. + FILENAME is used only for error messages. + Note that the resulting stream must be closed before FD can be closed. */ +extern fd_ostream_t fd_ostream_create (int fd, const char *filename, + bool buffered); + + +#ifdef __cplusplus +} +#endif + +#endif /* _FD_OSTREAM_H */ diff --git a/gettext-tools/gnulib-lib/fd-ostream.oo.c b/gettext-tools/gnulib-lib/fd-ostream.oo.c new file mode 100644 index 0000000..0c8978f --- /dev/null +++ b/gettext-tools/gnulib-lib/fd-ostream.oo.c @@ -0,0 +1,168 @@ +/* Output stream referring to a file descriptor. + Copyright (C) 2006-2007 Free Software Foundation, Inc. + Written by Bruno Haible , 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include "fd-ostream.h" + +#include +#include +#include +#include + +#include "error.h" +#include "full-write.h" +#include "xalloc.h" +#include "gettext.h" + +#define _(str) gettext (str) + +struct fd_ostream : struct ostream +{ +fields: + int fd; + char *filename; + char *buffer; /* A buffer, or NULL. */ + size_t avail; /* Number of bytes available in the buffer. */ +}; + +#define BUFSIZE 4096 + +/* Implementation of ostream_t methods. */ + +static void +fd_ostream::write_mem (fd_ostream_t stream, const void *data, size_t len) +{ + if (len > 0) + { + if (stream->buffer != NULL) + { + /* Buffered. */ + assert (stream->avail > 0); + #if 0 /* unoptimized */ + do + { + size_t n = (len <= stream->avail ? len : stream->avail); + if (n > 0) + { + memcpy (stream->buffer + BUFSIZE - stream->avail, data, n); + data = (char *) data + n; + stream->avail -= n; + len -= n; + } + if (stream->avail == 0) + { + if (full_write (stream->fd, stream->buffer, BUFSIZE) < BUFSIZE) + error (EXIT_FAILURE, errno, _("error writing to %s"), + stream->filename); + stream->avail = BUFSIZE; + } + } + while (len > 0); + #else /* optimized */ + if (len < stream->avail) + { + /* Move the data into the buffer. */ + memcpy (stream->buffer + BUFSIZE - stream->avail, data, len); + stream->avail -= len; + } + else + { + /* Split the data into: + - a first chunk, which is added to the buffer and output, + - a series of chunks of size BUFSIZE, which can be output + directly, without going through the buffer, and + - a last chunk, which is copied to the buffer. */ + size_t n = stream->avail; + memcpy (stream->buffer + BUFSIZE - stream->avail, data, n); + data = (char *) data + n; + len -= n; + if (full_write (stream->fd, stream->buffer, BUFSIZE) < BUFSIZE) + error (EXIT_FAILURE, errno, _("error writing to %s"), + stream->filename); + + while (len >= BUFSIZE) + { + if (full_write (stream->fd, data, BUFSIZE) < BUFSIZE) + error (EXIT_FAILURE, errno, _("error writing to %s"), + stream->filename); + data = (char *) data + BUFSIZE; + len -= BUFSIZE; + } + + if (len > 0) + memcpy (stream->buffer, data, len); + stream->avail = BUFSIZE - len; + } + #endif + assert (stream->avail > 0); + } + else + { + /* Unbuffered. */ + if (full_write (stream->fd, data, len) < len) + error (EXIT_FAILURE, errno, _("error writing to %s"), + stream->filename); + } + } +} + +static void +fd_ostream::flush (fd_ostream_t stream) +{ + if (stream->buffer != NULL && stream->avail < BUFSIZE) + { + size_t filled = BUFSIZE - stream->avail; + if (full_write (stream->fd, stream->buffer, filled) < filled) + error (EXIT_FAILURE, errno, _("error writing to %s"), stream->filename); + stream->avail = BUFSIZE; + } +} + +static void +fd_ostream::free (fd_ostream_t stream) +{ + fd_ostream_flush (stream); + free (stream->filename); + free (stream); +} + +/* Constructor. */ + +fd_ostream_t +fd_ostream_create (int fd, const char *filename, bool buffered) +{ + fd_ostream_t stream = + (struct fd_ostream_representation *) + xmalloc (sizeof (struct fd_ostream_representation) + + (buffered ? BUFSIZE : 0)); + + stream->base.vtable = &fd_ostream_vtable; + stream->fd = fd; + stream->filename = xstrdup (filename); + if (buffered) + { + stream->buffer = + (char *) (void *) stream + sizeof (struct fd_ostream_representation); + stream->avail = BUFSIZE; + } + else + stream->buffer = NULL; + + return stream; +} diff --git a/gettext-tools/gnulib-lib/fd-ostream.oo.h b/gettext-tools/gnulib-lib/fd-ostream.oo.h new file mode 100644 index 0000000..bd1f0b4 --- /dev/null +++ b/gettext-tools/gnulib-lib/fd-ostream.oo.h @@ -0,0 +1,48 @@ +/* Output stream referring to a file descriptor. + Copyright (C) 2006 Free Software Foundation, Inc. + Written by Bruno Haible , 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _FD_OSTREAM_H +#define _FD_OSTREAM_H + +#include + +#include "ostream.h" + + +struct fd_ostream : struct ostream +{ +methods: +}; + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Create an output stream referring to the file descriptor FD. + FILENAME is used only for error messages. + Note that the resulting stream must be closed before FD can be closed. */ +extern fd_ostream_t fd_ostream_create (int fd, const char *filename, + bool buffered); + + +#ifdef __cplusplus +} +#endif + +#endif /* _FD_OSTREAM_H */ diff --git a/gettext-tools/gnulib-lib/fd-safer-flag.c b/gettext-tools/gnulib-lib/fd-safer-flag.c new file mode 100644 index 0000000..1701100 --- /dev/null +++ b/gettext-tools/gnulib-lib/fd-safer-flag.c @@ -0,0 +1,52 @@ +/* Adjust a file descriptor result so that it avoids clobbering + STD{IN,OUT,ERR}_FILENO, with specific flags. + + Copyright (C) 2005-2006, 2009-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Written by Paul Eggert and Eric Blake. */ + +#include + +/* Specification. */ +#include "unistd-safer.h" + +#include +#include + +/* Return FD, unless FD would be a copy of standard input, output, or + error; in that case, return a duplicate of FD, closing FD. If FLAG + contains O_CLOEXEC, the returned FD will have close-on-exec + semantics. On failure to duplicate, close FD, set errno, and + return -1. Preserve errno if FD is negative, so that the caller + can always inspect errno when the returned value is negative. + + This function is usefully wrapped around functions that return file + descriptors, e.g., fd_safer_flag (open ("file", O_RDONLY | flag), flag). */ + +int +fd_safer_flag (int fd, int flag) +{ + if (STDIN_FILENO <= fd && fd <= STDERR_FILENO) + { + int f = dup_safer_flag (fd, flag); + int e = errno; + close (fd); + errno = e; + fd = f; + } + + return fd; +} diff --git a/gettext-tools/gnulib-lib/fd-safer.c b/gettext-tools/gnulib-lib/fd-safer.c new file mode 100644 index 0000000..148f735 --- /dev/null +++ b/gettext-tools/gnulib-lib/fd-safer.c @@ -0,0 +1,49 @@ +/* Return a safer copy of a file descriptor. + + Copyright (C) 2005-2006, 2009-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Written by Paul Eggert. */ + +#include + +#include "unistd-safer.h" + +#include +#include + +/* Return FD, unless FD would be a copy of standard input, output, or + error; in that case, return a duplicate of FD, closing FD. On + failure to duplicate, close FD, set errno, and return -1. Preserve + errno if FD is negative, so that the caller can always inspect + errno when the returned value is negative. + + This function is usefully wrapped around functions that return file + descriptors, e.g., fd_safer (open ("file", O_RDONLY)). */ + +int +fd_safer (int fd) +{ + if (STDIN_FILENO <= fd && fd <= STDERR_FILENO) + { + int f = dup_safer (fd); + int e = errno; + close (fd); + errno = e; + fd = f; + } + + return fd; +} diff --git a/gettext-tools/gnulib-lib/fd_ostream.priv.h b/gettext-tools/gnulib-lib/fd_ostream.priv.h new file mode 100644 index 0000000..9bd4c13 --- /dev/null +++ b/gettext-tools/gnulib-lib/fd_ostream.priv.h @@ -0,0 +1,14 @@ +/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ + +/* Field layout of superclass. */ +#include "ostream.priv.h" + +/* Field layout of fd_ostream class. */ +struct fd_ostream_representation +{ + struct ostream_representation base; + int fd; + char *filename; + char *buffer; + size_t avail; +}; diff --git a/gettext-tools/gnulib-lib/fd_ostream.vt.h b/gettext-tools/gnulib-lib/fd_ostream.vt.h new file mode 100644 index 0000000..a6b6485 --- /dev/null +++ b/gettext-tools/gnulib-lib/fd_ostream.vt.h @@ -0,0 +1,6 @@ +/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ + +/* Virtual function table layout of superclass. */ +#include "ostream.vt.h" + +/* Virtual function table layout of fd_ostream class. */ diff --git a/gettext-tools/gnulib-lib/file-has-acl.c b/gettext-tools/gnulib-lib/file-has-acl.c new file mode 100644 index 0000000..5104a41 --- /dev/null +++ b/gettext-tools/gnulib-lib/file-has-acl.c @@ -0,0 +1,919 @@ +/* Test whether a file has a nontrivial access control list. + + Copyright (C) 2002-2003, 2005-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + Written by Paul Eggert, Andreas Grünbacher, and Bruno Haible. */ + +/* Without this pragma, gcc 4.7.0 20120126 may suggest that the + file_has_acl function might be candidate for attribute 'const' */ +#if (__GNUC__ == 4 && 6 <= __GNUC_MINOR__) || 4 < __GNUC__ +# pragma GCC diagnostic ignored "-Wsuggest-attribute=const" +#endif + +#include + +#include "acl.h" + +#include "acl-internal.h" + + +#if USE_ACL && HAVE_ACL_GET_FILE + +# if HAVE_ACL_TYPE_EXTENDED /* Mac OS X */ + +/* ACL is an ACL, from a file, stored as type ACL_TYPE_EXTENDED. + Return 1 if the given ACL is non-trivial. + Return 0 if it is trivial. */ +int +acl_extended_nontrivial (acl_t acl) +{ + /* acl is non-trivial if it is non-empty. */ + return (acl_entries (acl) > 0); +} + +# else /* Linux, FreeBSD, IRIX, Tru64 */ + +/* ACL is an ACL, from a file, stored as type ACL_TYPE_ACCESS. + Return 1 if the given ACL is non-trivial. + Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. + Return -1 and set errno upon failure to determine it. */ +int +acl_access_nontrivial (acl_t acl) +{ + /* acl is non-trivial if it has some entries other than for "user::", + "group::", and "other::". Normally these three should be present + at least, allowing us to write + return (3 < acl_entries (acl)); + but the following code is more robust. */ +# if HAVE_ACL_FIRST_ENTRY /* Linux, FreeBSD */ + + acl_entry_t ace; + int got_one; + + for (got_one = acl_get_entry (acl, ACL_FIRST_ENTRY, &ace); + got_one > 0; + got_one = acl_get_entry (acl, ACL_NEXT_ENTRY, &ace)) + { + acl_tag_t tag; + if (acl_get_tag_type (ace, &tag) < 0) + return -1; + if (!(tag == ACL_USER_OBJ || tag == ACL_GROUP_OBJ || tag == ACL_OTHER)) + return 1; + } + return got_one; + +# elif HAVE_ACL_TO_SHORT_TEXT /* IRIX */ + /* Don't use acl_get_entry: it is undocumented. */ + + int count = acl->acl_cnt; + int i; + + for (i = 0; i < count; i++) + { + acl_entry_t ace = &acl->acl_entry[i]; + acl_tag_t tag = ace->ae_tag; + + if (!(tag == ACL_USER_OBJ || tag == ACL_GROUP_OBJ + || tag == ACL_OTHER_OBJ)) + return 1; + } + return 0; + +# elif HAVE_ACL_FREE_TEXT /* Tru64 */ + /* Don't use acl_get_entry: it takes only one argument and does not work. */ + + int count = acl->acl_num; + acl_entry_t ace; + + for (ace = acl->acl_first; count > 0; ace = ace->next, count--) + { + acl_tag_t tag; + acl_perm_t perm; + + tag = ace->entry->acl_type; + if (!(tag == ACL_USER_OBJ || tag == ACL_GROUP_OBJ || tag == ACL_OTHER)) + return 1; + + perm = ace->entry->acl_perm; + /* On Tru64, perm can also contain non-standard bits such as + PERM_INSERT, PERM_DELETE, PERM_MODIFY, PERM_LOOKUP, ... */ + if ((perm & ~(ACL_READ | ACL_WRITE | ACL_EXECUTE)) != 0) + return 1; + } + return 0; + +# else + + errno = ENOSYS; + return -1; +# endif +} + +# endif + + +#elif USE_ACL && HAVE_FACL && defined GETACL /* Solaris, Cygwin, not HP-UX */ + +/* Test an ACL retrieved with GETACL. + Return 1 if the given ACL, consisting of COUNT entries, is non-trivial. + Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */ +int +acl_nontrivial (int count, aclent_t *entries) +{ + int i; + + for (i = 0; i < count; i++) + { + aclent_t *ace = &entries[i]; + + /* Note: If ace->a_type = USER_OBJ, ace->a_id is the st_uid from stat(). + If ace->a_type = GROUP_OBJ, ace->a_id is the st_gid from stat(). + We don't need to check ace->a_id in these cases. */ + if (!(ace->a_type == USER_OBJ + || ace->a_type == GROUP_OBJ + || ace->a_type == OTHER_OBJ + /* Note: Cygwin does not return a CLASS_OBJ ("mask:") entry + sometimes. */ + || ace->a_type == CLASS_OBJ)) + return 1; + } + return 0; +} + +# ifdef ACE_GETACL + +/* A shortcut for a bitmask. */ +# define NEW_ACE_WRITEA_DATA (NEW_ACE_WRITE_DATA | NEW_ACE_APPEND_DATA) + +/* Test an ACL retrieved with ACE_GETACL. + Return 1 if the given ACL, consisting of COUNT entries, is non-trivial. + Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */ +int +acl_ace_nontrivial (int count, ace_t *entries) +{ + int i; + + /* The flags in the ace_t structure changed in a binary incompatible way + when ACL_NO_TRIVIAL etc. were introduced in version 1.15. + How to distinguish the two conventions at runtime? + In the old convention, usually three ACEs have a_flags = ACE_OWNER / + ACE_GROUP / ACE_OTHER, in the range 0x0100..0x0400. In the new + convention, these values are not used. */ + int old_convention = 0; + + for (i = 0; i < count; i++) + if (entries[i].a_flags & (OLD_ACE_OWNER | OLD_ACE_GROUP | OLD_ACE_OTHER)) + { + old_convention = 1; + break; + } + + if (old_convention) + /* Running on Solaris 10. */ + for (i = 0; i < count; i++) + { + ace_t *ace = &entries[i]; + + /* Note: + If ace->a_flags = ACE_OWNER, ace->a_who is the st_uid from stat(). + If ace->a_flags = ACE_GROUP, ace->a_who is the st_gid from stat(). + We don't need to check ace->a_who in these cases. */ + if (!(ace->a_type == OLD_ALLOW + && (ace->a_flags == OLD_ACE_OWNER + || ace->a_flags == OLD_ACE_GROUP + || ace->a_flags == OLD_ACE_OTHER))) + return 1; + } + else + { + /* Running on Solaris 10 (newer version) or Solaris 11. */ + unsigned int access_masks[6] = + { + 0, /* owner@ deny */ + 0, /* owner@ allow */ + 0, /* group@ deny */ + 0, /* group@ allow */ + 0, /* everyone@ deny */ + 0 /* everyone@ allow */ + }; + + for (i = 0; i < count; i++) + { + ace_t *ace = &entries[i]; + unsigned int index1; + unsigned int index2; + + if (ace->a_type == NEW_ACE_ACCESS_ALLOWED_ACE_TYPE) + index1 = 1; + else if (ace->a_type == NEW_ACE_ACCESS_DENIED_ACE_TYPE) + index1 = 0; + else + return 1; + + if (ace->a_flags == NEW_ACE_OWNER) + index2 = 0; + else if (ace->a_flags == (NEW_ACE_GROUP | NEW_ACE_IDENTIFIER_GROUP)) + index2 = 2; + else if (ace->a_flags == NEW_ACE_EVERYONE) + index2 = 4; + else + return 1; + + access_masks[index1 + index2] |= ace->a_access_mask; + } + + /* The same bit shouldn't be both allowed and denied. */ + if (access_masks[0] & access_masks[1]) + return 1; + if (access_masks[2] & access_masks[3]) + return 1; + if (access_masks[4] & access_masks[5]) + return 1; + + /* Check minimum masks. */ + if ((NEW_ACE_WRITE_NAMED_ATTRS + | NEW_ACE_WRITE_ATTRIBUTES + | NEW_ACE_WRITE_ACL + | NEW_ACE_WRITE_OWNER) + & ~ access_masks[1]) + return 1; + access_masks[1] &= ~(NEW_ACE_WRITE_NAMED_ATTRS + | NEW_ACE_WRITE_ATTRIBUTES + | NEW_ACE_WRITE_ACL + | NEW_ACE_WRITE_OWNER); + if ((NEW_ACE_READ_NAMED_ATTRS + | NEW_ACE_READ_ATTRIBUTES + | NEW_ACE_READ_ACL + | NEW_ACE_SYNCHRONIZE) + & ~ access_masks[5]) + return 1; + access_masks[5] &= ~(NEW_ACE_READ_NAMED_ATTRS + | NEW_ACE_READ_ATTRIBUTES + | NEW_ACE_READ_ACL + | NEW_ACE_SYNCHRONIZE); + + /* Check the allowed or denied bits. */ + switch ((access_masks[0] | access_masks[1]) + & ~(NEW_ACE_READ_NAMED_ATTRS + | NEW_ACE_READ_ATTRIBUTES + | NEW_ACE_READ_ACL + | NEW_ACE_SYNCHRONIZE)) + { + case 0: + case NEW_ACE_READ_DATA: + case NEW_ACE_WRITEA_DATA: + case NEW_ACE_READ_DATA | NEW_ACE_WRITEA_DATA: + case NEW_ACE_EXECUTE: + case NEW_ACE_READ_DATA | NEW_ACE_EXECUTE: + case NEW_ACE_WRITEA_DATA | NEW_ACE_EXECUTE: + case NEW_ACE_READ_DATA | NEW_ACE_WRITEA_DATA | NEW_ACE_EXECUTE: + break; + default: + return 1; + } + switch ((access_masks[2] | access_masks[3]) + & ~(NEW_ACE_READ_NAMED_ATTRS + | NEW_ACE_READ_ATTRIBUTES + | NEW_ACE_READ_ACL + | NEW_ACE_SYNCHRONIZE)) + { + case 0: + case NEW_ACE_READ_DATA: + case NEW_ACE_WRITEA_DATA: + case NEW_ACE_READ_DATA | NEW_ACE_WRITEA_DATA: + case NEW_ACE_EXECUTE: + case NEW_ACE_READ_DATA | NEW_ACE_EXECUTE: + case NEW_ACE_WRITEA_DATA | NEW_ACE_EXECUTE: + case NEW_ACE_READ_DATA | NEW_ACE_WRITEA_DATA | NEW_ACE_EXECUTE: + break; + default: + return 1; + } + switch ((access_masks[4] | access_masks[5]) + & ~(NEW_ACE_WRITE_NAMED_ATTRS + | NEW_ACE_WRITE_ATTRIBUTES + | NEW_ACE_WRITE_ACL + | NEW_ACE_WRITE_OWNER)) + { + case 0: + case NEW_ACE_READ_DATA: + case NEW_ACE_WRITEA_DATA: + case NEW_ACE_READ_DATA | NEW_ACE_WRITEA_DATA: + case NEW_ACE_EXECUTE: + case NEW_ACE_READ_DATA | NEW_ACE_EXECUTE: + case NEW_ACE_WRITEA_DATA | NEW_ACE_EXECUTE: + case NEW_ACE_READ_DATA | NEW_ACE_WRITEA_DATA | NEW_ACE_EXECUTE: + break; + default: + return 1; + } + + /* Check that the NEW_ACE_WRITE_DATA and NEW_ACE_APPEND_DATA bits are + either both allowed or both denied. */ + if (((access_masks[0] & NEW_ACE_WRITE_DATA) != 0) + != ((access_masks[0] & NEW_ACE_APPEND_DATA) != 0)) + return 1; + if (((access_masks[2] & NEW_ACE_WRITE_DATA) != 0) + != ((access_masks[2] & NEW_ACE_APPEND_DATA) != 0)) + return 1; + if (((access_masks[4] & NEW_ACE_WRITE_DATA) != 0) + != ((access_masks[4] & NEW_ACE_APPEND_DATA) != 0)) + return 1; + } + + return 0; +} + +# endif + +#elif USE_ACL && HAVE_GETACL /* HP-UX */ + +/* Return 1 if the given ACL is non-trivial. + Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */ +int +acl_nontrivial (int count, struct acl_entry *entries, struct stat *sb) +{ + int i; + + for (i = 0; i < count; i++) + { + struct acl_entry *ace = &entries[i]; + + if (!((ace->uid == sb->st_uid && ace->gid == ACL_NSGROUP) + || (ace->uid == ACL_NSUSER && ace->gid == sb->st_gid) + || (ace->uid == ACL_NSUSER && ace->gid == ACL_NSGROUP))) + return 1; + } + return 0; +} + +# if HAVE_ACLV_H /* HP-UX >= 11.11 */ + +/* Return 1 if the given ACL is non-trivial. + Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */ +int +aclv_nontrivial (int count, struct acl *entries) +{ + int i; + + for (i = 0; i < count; i++) + { + struct acl *ace = &entries[i]; + + /* Note: If ace->a_type = USER_OBJ, ace->a_id is the st_uid from stat(). + If ace->a_type = GROUP_OBJ, ace->a_id is the st_gid from stat(). + We don't need to check ace->a_id in these cases. */ + if (!(ace->a_type == USER_OBJ /* no need to check ace->a_id here */ + || ace->a_type == GROUP_OBJ /* no need to check ace->a_id here */ + || ace->a_type == CLASS_OBJ + || ace->a_type == OTHER_OBJ)) + return 1; + } + return 0; +} + +# endif + +#elif USE_ACL && (HAVE_ACLX_GET || HAVE_STATACL) /* AIX */ + +/* Return 1 if the given ACL is non-trivial. + Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */ +int +acl_nontrivial (struct acl *a) +{ + /* The normal way to iterate through an ACL is like this: + struct acl_entry *ace; + for (ace = a->acl_ext; ace != acl_last (a); ace = acl_nxt (ace)) + { + struct ace_id *aei; + switch (ace->ace_type) + { + case ACC_PERMIT: + case ACC_DENY: + case ACC_SPECIFY: + ...; + } + for (aei = ace->ace_id; aei != id_last (ace); aei = id_nxt (aei)) + ... + } + */ + return (acl_last (a) != a->acl_ext ? 1 : 0); +} + +# if HAVE_ACLX_GET && defined ACL_AIX_WIP /* newer AIX */ + +/* Return 1 if the given ACL is non-trivial. + Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */ +int +acl_nfs4_nontrivial (nfs4_acl_int_t *a) +{ +# if 1 /* let's try this first */ + return (a->aclEntryN > 0 ? 1 : 0); +# else + int count = a->aclEntryN; + int i; + + for (i = 0; i < count; i++) + { + nfs4_ace_int_t *ace = &a->aclEntry[i]; + + if (!((ace->flags & ACE4_ID_SPECIAL) != 0 + && (ace->aceWho.special_whoid == ACE4_WHO_OWNER + || ace->aceWho.special_whoid == ACE4_WHO_GROUP + || ace->aceWho.special_whoid == ACE4_WHO_EVERYONE) + && ace->aceType == ACE4_ACCESS_ALLOWED_ACE_TYPE + && ace->aceFlags == 0 + && (ace->aceMask & ~(ACE4_READ_DATA | ACE4_LIST_DIRECTORY + | ACE4_WRITE_DATA | ACE4_ADD_FILE + | ACE4_EXECUTE)) == 0)) + return 1; + } + return 0; +# endif +} + +# endif + +#elif USE_ACL && HAVE_ACLSORT /* NonStop Kernel */ + +/* Test an ACL retrieved with ACL_GET. + Return 1 if the given ACL, consisting of COUNT entries, is non-trivial. + Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */ +int +acl_nontrivial (int count, struct acl *entries) +{ + int i; + + for (i = 0; i < count; i++) + { + struct acl *ace = &entries[i]; + + /* Note: If ace->a_type = USER_OBJ, ace->a_id is the st_uid from stat(). + If ace->a_type = GROUP_OBJ, ace->a_id is the st_gid from stat(). + We don't need to check ace->a_id in these cases. */ + if (!(ace->a_type == USER_OBJ /* no need to check ace->a_id here */ + || ace->a_type == GROUP_OBJ /* no need to check ace->a_id here */ + || ace->a_type == CLASS_OBJ + || ace->a_type == OTHER_OBJ)) + return 1; + } + return 0; +} + +#endif + + +/* Return 1 if NAME has a nontrivial access control list, 0 if NAME + only has no or a base access control list, and -1 (setting errno) + on error. SB must be set to the stat buffer of NAME, obtained + through stat() or lstat(). */ + +int +file_has_acl (char const *name, struct stat const *sb) +{ +#if USE_ACL + if (! S_ISLNK (sb->st_mode)) + { +# if HAVE_ACL_GET_FILE + + /* POSIX 1003.1e (draft 17 -- abandoned) specific version. */ + /* Linux, FreeBSD, Mac OS X, IRIX, Tru64 */ + int ret; + + if (HAVE_ACL_EXTENDED_FILE) /* Linux */ + { + /* On Linux, acl_extended_file is an optimized function: It only + makes two calls to getxattr(), one for ACL_TYPE_ACCESS, one for + ACL_TYPE_DEFAULT. */ + ret = acl_extended_file (name); + } + else /* FreeBSD, Mac OS X, IRIX, Tru64 */ + { +# if HAVE_ACL_TYPE_EXTENDED /* Mac OS X */ + /* On Mac OS X, acl_get_file (name, ACL_TYPE_ACCESS) + and acl_get_file (name, ACL_TYPE_DEFAULT) + always return NULL / EINVAL. There is no point in making + these two useless calls. The real ACL is retrieved through + acl_get_file (name, ACL_TYPE_EXTENDED). */ + acl_t acl = acl_get_file (name, ACL_TYPE_EXTENDED); + if (acl) + { + ret = acl_extended_nontrivial (acl); + acl_free (acl); + } + else + ret = -1; +# else /* FreeBSD, IRIX, Tru64 */ + acl_t acl = acl_get_file (name, ACL_TYPE_ACCESS); + if (acl) + { + int saved_errno; + + ret = acl_access_nontrivial (acl); + saved_errno = errno; + acl_free (acl); + errno = saved_errno; +# if HAVE_ACL_FREE_TEXT /* Tru64 */ + /* On OSF/1, acl_get_file (name, ACL_TYPE_DEFAULT) always + returns NULL with errno not set. There is no point in + making this call. */ +# else /* FreeBSD, IRIX */ + /* On Linux, FreeBSD, IRIX, acl_get_file (name, ACL_TYPE_ACCESS) + and acl_get_file (name, ACL_TYPE_DEFAULT) on a directory + either both succeed or both fail; it depends on the + file system. Therefore there is no point in making the second + call if the first one already failed. */ + if (ret == 0 && S_ISDIR (sb->st_mode)) + { + acl = acl_get_file (name, ACL_TYPE_DEFAULT); + if (acl) + { + ret = (0 < acl_entries (acl)); + acl_free (acl); + } + else + ret = -1; + } +# endif + } + else + ret = -1; +# endif + } + if (ret < 0) + return - acl_errno_valid (errno); + return ret; + +# elif HAVE_FACL && defined GETACL /* Solaris, Cygwin, not HP-UX */ + +# if defined ACL_NO_TRIVIAL + + /* Solaris 10 (newer version), which has additional API declared in + (acl_t) and implemented in libsec (acl_set, acl_trivial, + acl_fromtext, ...). */ + return acl_trivial (name); + +# else /* Solaris, Cygwin, general case */ + + /* Solaris 2.5 through Solaris 10, Cygwin, and contemporaneous versions + of Unixware. The acl() call returns the access and default ACL both + at once. */ + { + /* Initially, try to read the entries into a stack-allocated buffer. + Use malloc if it does not fit. */ + enum + { + alloc_init = 4000 / sizeof (aclent_t), /* >= 3 */ + alloc_max = MIN (INT_MAX, SIZE_MAX / sizeof (aclent_t)) + }; + aclent_t buf[alloc_init]; + size_t alloc = alloc_init; + aclent_t *entries = buf; + aclent_t *malloced = NULL; + int count; + + for (;;) + { + count = acl (name, GETACL, alloc, entries); + if (count < 0 && errno == ENOSPC) + { + /* Increase the size of the buffer. */ + free (malloced); + if (alloc > alloc_max / 2) + { + errno = ENOMEM; + return -1; + } + alloc = 2 * alloc; /* <= alloc_max */ + entries = malloced = + (aclent_t *) malloc (alloc * sizeof (aclent_t)); + if (entries == NULL) + { + errno = ENOMEM; + return -1; + } + continue; + } + break; + } + if (count < 0) + { + if (errno == ENOSYS || errno == ENOTSUP) + ; + else + { + int saved_errno = errno; + free (malloced); + errno = saved_errno; + return -1; + } + } + else if (count == 0) + ; + else + { + /* Don't use MIN_ACL_ENTRIES: It's set to 4 on Cygwin, but Cygwin + returns only 3 entries for files with no ACL. But this is safe: + If there are more than 4 entries, there cannot be only the + "user::", "group::", "other:", and "mask:" entries. */ + if (count > 4) + { + free (malloced); + return 1; + } + + if (acl_nontrivial (count, entries)) + { + free (malloced); + return 1; + } + } + free (malloced); + } + +# ifdef ACE_GETACL + /* Solaris also has a different variant of ACLs, used in ZFS and NFSv4 + file systems (whereas the other ones are used in UFS file systems). */ + { + /* Initially, try to read the entries into a stack-allocated buffer. + Use malloc if it does not fit. */ + enum + { + alloc_init = 4000 / sizeof (ace_t), /* >= 3 */ + alloc_max = MIN (INT_MAX, SIZE_MAX / sizeof (ace_t)) + }; + ace_t buf[alloc_init]; + size_t alloc = alloc_init; + ace_t *entries = buf; + ace_t *malloced = NULL; + int count; + + for (;;) + { + count = acl (name, ACE_GETACL, alloc, entries); + if (count < 0 && errno == ENOSPC) + { + /* Increase the size of the buffer. */ + free (malloced); + if (alloc > alloc_max / 2) + { + errno = ENOMEM; + return -1; + } + alloc = 2 * alloc; /* <= alloc_max */ + entries = malloced = (ace_t *) malloc (alloc * sizeof (ace_t)); + if (entries == NULL) + { + errno = ENOMEM; + return -1; + } + continue; + } + break; + } + if (count < 0) + { + if (errno == ENOSYS || errno == EINVAL) + ; + else + { + int saved_errno = errno; + free (malloced); + errno = saved_errno; + return -1; + } + } + else if (count == 0) + ; + else + { + /* In the old (original Solaris 10) convention: + If there are more than 3 entries, there cannot be only the + ACE_OWNER, ACE_GROUP, ACE_OTHER entries. + In the newer Solaris 10 and Solaris 11 convention: + If there are more than 6 entries, there cannot be only the + ACE_OWNER, ACE_GROUP, ACE_EVERYONE entries, each once with + NEW_ACE_ACCESS_ALLOWED_ACE_TYPE and once with + NEW_ACE_ACCESS_DENIED_ACE_TYPE. */ + if (count > 6) + { + free (malloced); + return 1; + } + + if (acl_ace_nontrivial (count, entries)) + { + free (malloced); + return 1; + } + } + free (malloced); + } +# endif + + return 0; +# endif + +# elif HAVE_GETACL /* HP-UX */ + + { + struct acl_entry entries[NACLENTRIES]; + int count; + + count = getacl (name, NACLENTRIES, entries); + + if (count < 0) + { + /* ENOSYS is seen on newer HP-UX versions. + EOPNOTSUPP is typically seen on NFS mounts. + ENOTSUP was seen on Quantum StorNext file systems (cvfs). */ + if (errno == ENOSYS || errno == EOPNOTSUPP || errno == ENOTSUP) + ; + else + return -1; + } + else if (count == 0) + return 0; + else /* count > 0 */ + { + if (count > NACLENTRIES) + /* If NACLENTRIES cannot be trusted, use dynamic memory + allocation. */ + abort (); + + /* If there are more than 3 entries, there cannot be only the + (uid,%), (%,gid), (%,%) entries. */ + if (count > 3) + return 1; + + { + struct stat statbuf; + + if (stat (name, &statbuf) < 0) + return -1; + + return acl_nontrivial (count, entries, &statbuf); + } + } + } + +# if HAVE_ACLV_H /* HP-UX >= 11.11 */ + + { + struct acl entries[NACLVENTRIES]; + int count; + + count = acl ((char *) name, ACL_GET, NACLVENTRIES, entries); + + if (count < 0) + { + /* EOPNOTSUPP is seen on NFS in HP-UX 11.11, 11.23. + EINVAL is seen on NFS in HP-UX 11.31. */ + if (errno == ENOSYS || errno == EOPNOTSUPP || errno == EINVAL) + ; + else + return -1; + } + else if (count == 0) + return 0; + else /* count > 0 */ + { + if (count > NACLVENTRIES) + /* If NACLVENTRIES cannot be trusted, use dynamic memory + allocation. */ + abort (); + + /* If there are more than 4 entries, there cannot be only the + four base ACL entries. */ + if (count > 4) + return 1; + + return aclv_nontrivial (count, entries); + } + } + +# endif + +# elif HAVE_ACLX_GET && defined ACL_AIX_WIP /* AIX */ + + acl_type_t type; + char aclbuf[1024]; + void *acl = aclbuf; + size_t aclsize = sizeof (aclbuf); + mode_t mode; + + for (;;) + { + /* The docs say that type being 0 is equivalent to ACL_ANY, but it + is not true, in AIX 5.3. */ + type.u64 = ACL_ANY; + if (aclx_get (name, 0, &type, aclbuf, &aclsize, &mode) >= 0) + break; + if (errno == ENOSYS) + return 0; + if (errno != ENOSPC) + { + if (acl != aclbuf) + { + int saved_errno = errno; + free (acl); + errno = saved_errno; + } + return -1; + } + aclsize = 2 * aclsize; + if (acl != aclbuf) + free (acl); + acl = malloc (aclsize); + if (acl == NULL) + { + errno = ENOMEM; + return -1; + } + } + + if (type.u64 == ACL_AIXC) + { + int result = acl_nontrivial ((struct acl *) acl); + if (acl != aclbuf) + free (acl); + return result; + } + else if (type.u64 == ACL_NFS4) + { + int result = acl_nfs4_nontrivial ((nfs4_acl_int_t *) acl); + if (acl != aclbuf) + free (acl); + return result; + } + else + { + /* A newer type of ACL has been introduced in the system. + We should better support it. */ + if (acl != aclbuf) + free (acl); + errno = EINVAL; + return -1; + } + +# elif HAVE_STATACL /* older AIX */ + + union { struct acl a; char room[4096]; } u; + + if (statacl (name, STX_NORMAL, &u.a, sizeof (u)) < 0) + return -1; + + return acl_nontrivial (&u.a); + +# elif HAVE_ACLSORT /* NonStop Kernel */ + + { + struct acl entries[NACLENTRIES]; + int count; + + count = acl ((char *) name, ACL_GET, NACLENTRIES, entries); + + if (count < 0) + { + if (errno == ENOSYS || errno == ENOTSUP) + ; + else + return -1; + } + else if (count == 0) + return 0; + else /* count > 0 */ + { + if (count > NACLENTRIES) + /* If NACLENTRIES cannot be trusted, use dynamic memory + allocation. */ + abort (); + + /* If there are more than 4 entries, there cannot be only the + four base ACL entries. */ + if (count > 4) + return 1; + + return acl_nontrivial (count, entries); + } + } + +# endif + } +#endif + + return 0; +} diff --git a/gettext-tools/gnulib-lib/file-ostream.c b/gettext-tools/gnulib-lib/file-ostream.c new file mode 100644 index 0000000..7a7c5d5 --- /dev/null +++ b/gettext-tools/gnulib-lib/file-ostream.c @@ -0,0 +1,120 @@ +/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ + +#line 1 "file-ostream.oo.c" +/* Output stream referring to an stdio FILE. + Copyright (C) 2006 Free Software Foundation, Inc. + Written by Bruno Haible , 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include "file-ostream.h" + +#include + +#include "xalloc.h" + +#line 31 "file-ostream.c" +#if !IS_CPLUSPLUS +#define file_ostream_representation any_ostream_representation +#endif +#include "file_ostream.priv.h" + +const typeinfo_t file_ostream_typeinfo = { "file_ostream" }; + +static const typeinfo_t * const file_ostream_superclasses[] = + { file_ostream_SUPERCLASSES }; + +#define super ostream_vtable + +#line 32 "file-ostream.oo.c" + +/* Implementation of ostream_t methods. */ + +static void +file_ostream__write_mem (file_ostream_t stream, const void *data, size_t len) +{ + if (len > 0) + fwrite (data, 1, len, stream->fp); +} + +static void +file_ostream__flush (file_ostream_t stream) +{ + /* This ostream has no internal buffer. No need to fflush (stream->fp), + since it's external to this ostream. */ +} + +static void +file_ostream__free (file_ostream_t stream) +{ + free (stream); +} + +/* Constructor. */ + +file_ostream_t +file_ostream_create (FILE *fp) +{ + file_ostream_t stream = XMALLOC (struct file_ostream_representation); + + stream->base.vtable = &file_ostream_vtable; + stream->fp = fp; + + return stream; +} + +#line 81 "file-ostream.c" + +const struct file_ostream_implementation file_ostream_vtable = +{ + file_ostream_superclasses, + sizeof (file_ostream_superclasses) / sizeof (file_ostream_superclasses[0]), + sizeof (struct file_ostream_representation), + file_ostream__write_mem, + file_ostream__flush, + file_ostream__free, +}; + +#if !HAVE_INLINE + +/* Define the functions that invoke the methods. */ + +void +file_ostream_write_mem (file_ostream_t first_arg, const void *data, size_t len) +{ + const struct file_ostream_implementation *vtable = + ((struct file_ostream_representation_header *) (struct file_ostream_representation *) first_arg)->vtable; + vtable->write_mem (first_arg,data,len); +} + +void +file_ostream_flush (file_ostream_t first_arg) +{ + const struct file_ostream_implementation *vtable = + ((struct file_ostream_representation_header *) (struct file_ostream_representation *) first_arg)->vtable; + vtable->flush (first_arg); +} + +void +file_ostream_free (file_ostream_t first_arg) +{ + const struct file_ostream_implementation *vtable = + ((struct file_ostream_representation_header *) (struct file_ostream_representation *) first_arg)->vtable; + vtable->free (first_arg); +} + +#endif diff --git a/gettext-tools/gnulib-lib/file-ostream.h b/gettext-tools/gnulib-lib/file-ostream.h new file mode 100644 index 0000000..44e794c --- /dev/null +++ b/gettext-tools/gnulib-lib/file-ostream.h @@ -0,0 +1,135 @@ +/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ + +#line 1 "file-ostream.oo.h" +/* Output stream referring to an stdio FILE. + Copyright (C) 2006 Free Software Foundation, Inc. + Written by Bruno Haible , 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _FILE_OSTREAM_H +#define _FILE_OSTREAM_H + +#include + +#include "ostream.h" + + +#line 30 "file-ostream.h" +struct file_ostream_representation; +/* file_ostream_t is defined as a pointer to struct file_ostream_representation. + In C++ mode, we use a smart pointer class. + In C mode, we have no other choice than a typedef to the root class type. */ +#if IS_CPLUSPLUS +struct file_ostream_t +{ +private: + struct file_ostream_representation *_pointer; +public: + file_ostream_t () : _pointer (NULL) {} + file_ostream_t (struct file_ostream_representation *pointer) : _pointer (pointer) {} + struct file_ostream_representation * operator -> () { return _pointer; } + operator struct file_ostream_representation * () { return _pointer; } + operator struct any_ostream_representation * () { return (struct any_ostream_representation *) _pointer; } + operator void * () { return _pointer; } + bool operator == (const void *p) { return _pointer == p; } + bool operator != (const void *p) { return _pointer != p; } + operator ostream_t () { return (ostream_t) (struct any_ostream_representation *) _pointer; } + explicit file_ostream_t (ostream_t x) : _pointer ((struct file_ostream_representation *) (void *) x) {} +}; +#else +typedef ostream_t file_ostream_t; +#endif + +/* Functions that invoke the methods. */ +extern void file_ostream_write_mem (file_ostream_t first_arg, const void *data, size_t len); +extern void file_ostream_flush (file_ostream_t first_arg); +extern void file_ostream_free (file_ostream_t first_arg); + +/* Type representing an implementation of file_ostream_t. */ +struct file_ostream_implementation +{ + const typeinfo_t * const *superclasses; + size_t superclasses_length; + size_t instance_size; +#define THIS_ARG file_ostream_t first_arg +#include "file_ostream.vt.h" +#undef THIS_ARG +}; + +/* Public portion of the object pointed to by a file_ostream_t. */ +struct file_ostream_representation_header +{ + const struct file_ostream_implementation *vtable; +}; + +#if HAVE_INLINE + +/* Define the functions that invoke the methods as inline accesses to + the file_ostream_implementation. + Use #define to avoid a warning because of extern vs. static. */ + +# define file_ostream_write_mem file_ostream_write_mem_inline +static inline void +file_ostream_write_mem (file_ostream_t first_arg, const void *data, size_t len) +{ + const struct file_ostream_implementation *vtable = + ((struct file_ostream_representation_header *) (struct file_ostream_representation *) first_arg)->vtable; + vtable->write_mem (first_arg,data,len); +} + +# define file_ostream_flush file_ostream_flush_inline +static inline void +file_ostream_flush (file_ostream_t first_arg) +{ + const struct file_ostream_implementation *vtable = + ((struct file_ostream_representation_header *) (struct file_ostream_representation *) first_arg)->vtable; + vtable->flush (first_arg); +} + +# define file_ostream_free file_ostream_free_inline +static inline void +file_ostream_free (file_ostream_t first_arg) +{ + const struct file_ostream_implementation *vtable = + ((struct file_ostream_representation_header *) (struct file_ostream_representation *) first_arg)->vtable; + vtable->free (first_arg); +} + +#endif + +extern const typeinfo_t file_ostream_typeinfo; +#define file_ostream_SUPERCLASSES &file_ostream_typeinfo, ostream_SUPERCLASSES +#define file_ostream_SUPERCLASSES_LENGTH (1 + ostream_SUPERCLASSES_LENGTH) + +extern const struct file_ostream_implementation file_ostream_vtable; + +#line 30 "file-ostream.oo.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Create an output stream referring to FP. + Note that the resulting stream must be closed before FP can be closed. */ +extern file_ostream_t file_ostream_create (FILE *fp); + + +#ifdef __cplusplus +} +#endif + +#endif /* _FILE_OSTREAM_H */ diff --git a/gettext-tools/gnulib-lib/file-ostream.oo.c b/gettext-tools/gnulib-lib/file-ostream.oo.c new file mode 100644 index 0000000..e5884bc --- /dev/null +++ b/gettext-tools/gnulib-lib/file-ostream.oo.c @@ -0,0 +1,66 @@ +/* Output stream referring to an stdio FILE. + Copyright (C) 2006 Free Software Foundation, Inc. + Written by Bruno Haible , 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include "file-ostream.h" + +#include + +#include "xalloc.h" + +struct file_ostream : struct ostream +{ +fields: + FILE *fp; +}; + +/* Implementation of ostream_t methods. */ + +static void +file_ostream::write_mem (file_ostream_t stream, const void *data, size_t len) +{ + if (len > 0) + fwrite (data, 1, len, stream->fp); +} + +static void +file_ostream::flush (file_ostream_t stream) +{ + /* This ostream has no internal buffer. No need to fflush (stream->fp), + since it's external to this ostream. */ +} + +static void +file_ostream::free (file_ostream_t stream) +{ + free (stream); +} + +/* Constructor. */ + +file_ostream_t +file_ostream_create (FILE *fp) +{ + file_ostream_t stream = XMALLOC (struct file_ostream_representation); + + stream->base.vtable = &file_ostream_vtable; + stream->fp = fp; + + return stream; +} diff --git a/gettext-tools/gnulib-lib/file-ostream.oo.h b/gettext-tools/gnulib-lib/file-ostream.oo.h new file mode 100644 index 0000000..6da1dbd --- /dev/null +++ b/gettext-tools/gnulib-lib/file-ostream.oo.h @@ -0,0 +1,46 @@ +/* Output stream referring to an stdio FILE. + Copyright (C) 2006 Free Software Foundation, Inc. + Written by Bruno Haible , 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _FILE_OSTREAM_H +#define _FILE_OSTREAM_H + +#include + +#include "ostream.h" + + +struct file_ostream : struct ostream +{ +methods: +}; + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Create an output stream referring to FP. + Note that the resulting stream must be closed before FP can be closed. */ +extern file_ostream_t file_ostream_create (FILE *fp); + + +#ifdef __cplusplus +} +#endif + +#endif /* _FILE_OSTREAM_H */ diff --git a/gettext-tools/gnulib-lib/file_ostream.priv.h b/gettext-tools/gnulib-lib/file_ostream.priv.h new file mode 100644 index 0000000..9dd844a --- /dev/null +++ b/gettext-tools/gnulib-lib/file_ostream.priv.h @@ -0,0 +1,11 @@ +/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ + +/* Field layout of superclass. */ +#include "ostream.priv.h" + +/* Field layout of file_ostream class. */ +struct file_ostream_representation +{ + struct ostream_representation base; + FILE *fp; +}; diff --git a/gettext-tools/gnulib-lib/file_ostream.vt.h b/gettext-tools/gnulib-lib/file_ostream.vt.h new file mode 100644 index 0000000..c841979 --- /dev/null +++ b/gettext-tools/gnulib-lib/file_ostream.vt.h @@ -0,0 +1,6 @@ +/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ + +/* Virtual function table layout of superclass. */ +#include "ostream.vt.h" + +/* Virtual function table layout of file_ostream class. */ diff --git a/gettext-tools/gnulib-lib/filename.h b/gettext-tools/gnulib-lib/filename.h new file mode 100644 index 0000000..96dbaaa --- /dev/null +++ b/gettext-tools/gnulib-lib/filename.h @@ -0,0 +1,54 @@ +/* Basic filename support macros. + Copyright (C) 2001-2004, 2007-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _FILENAME_H +#define _FILENAME_H + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Pathname support. + ISSLASH(C) tests whether C is a directory separator character. + IS_ABSOLUTE_PATH(P) tests whether P is an absolute path. If it is not, + it may be concatenated to a directory pathname. + IS_PATH_WITH_DIR(P) tests whether P contains a directory specification. + */ +#if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__ + /* Native Windows, Cygwin, OS/2, DOS */ +# define ISSLASH(C) ((C) == '/' || (C) == '\\') +# define HAS_DEVICE(P) \ + ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) \ + && (P)[1] == ':') +# define IS_ABSOLUTE_PATH(P) (ISSLASH ((P)[0]) || HAS_DEVICE (P)) +# define IS_PATH_WITH_DIR(P) \ + (strchr (P, '/') != NULL || strchr (P, '\\') != NULL || HAS_DEVICE (P)) +# define FILE_SYSTEM_PREFIX_LEN(P) (HAS_DEVICE (P) ? 2 : 0) +#else + /* Unix */ +# define ISSLASH(C) ((C) == '/') +# define IS_ABSOLUTE_PATH(P) ISSLASH ((P)[0]) +# define IS_PATH_WITH_DIR(P) (strchr (P, '/') != NULL) +# define FILE_SYSTEM_PREFIX_LEN(P) 0 +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* _FILENAME_H */ diff --git a/gettext-tools/gnulib-lib/findprog.c b/gettext-tools/gnulib-lib/findprog.c new file mode 100644 index 0000000..523d251 --- /dev/null +++ b/gettext-tools/gnulib-lib/findprog.c @@ -0,0 +1,138 @@ +/* Locating a program in PATH. + Copyright (C) 2001-2004, 2006-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2001. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + + +#include + +/* Specification. */ +#include "findprog.h" + +#include +#include +#include +#include + +/* Avoid collision between findprog.c and findprog-lgpl.c. */ +#if IN_FINDPROG_LGPL || ! GNULIB_FINDPROG_LGPL + +#if !IN_FINDPROG_LGPL +# include "xalloc.h" +#endif +#include "concat-filename.h" + + +const char * +find_in_path (const char *progname) +{ +#if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__ + /* Native Windows, Cygwin, OS/2, DOS */ + /* The searching rules with .COM, .EXE, .BAT, .CMD etc. suffixes are + too complicated. Leave it to the OS. */ + return progname; +#else + /* Unix */ + char *path; + char *path_rest; + char *cp; + + if (strchr (progname, '/') != NULL) + /* If progname contains a slash, it is either absolute or relative to + the current directory. PATH is not used. */ + return progname; + + path = getenv ("PATH"); + if (path == NULL || *path == '\0') + /* If PATH is not set, the default search path is implementation + dependent. */ + return progname; + + /* Make a copy, to prepare for destructive modifications. */ +# if !IN_FINDPROG_LGPL + path = xstrdup (path); +# else + path = strdup (path); + if (path == NULL) + /* Out of memory. */ + return progname; +# endif + for (path_rest = path; ; path_rest = cp + 1) + { + const char *dir; + bool last; + char *progpathname; + + /* Extract next directory in PATH. */ + dir = path_rest; + for (cp = path_rest; *cp != '\0' && *cp != ':'; cp++) + ; + last = (*cp == '\0'); + *cp = '\0'; + + /* Empty PATH components designate the current directory. */ + if (dir == cp) + dir = "."; + + /* Concatenate dir and progname. */ +# if !IN_FINDPROG_LGPL + progpathname = xconcatenated_filename (dir, progname, NULL); +# else + progpathname = concatenated_filename (dir, progname, NULL); + if (progpathname == NULL) + { + /* Out of memory. */ + free (path); + return progname; + } +# endif + + /* On systems which have the eaccess() system call, let's use it. + On other systems, let's hope that this program is not installed + setuid or setgid, so that it is ok to call access() despite its + design flaw. */ + if (eaccess (progpathname, X_OK) == 0) + { + /* Found! */ + if (strcmp (progpathname, progname) == 0) + { + free (progpathname); + + /* Add the "./" prefix for real, that xconcatenated_filename() + optimized away. This avoids a second PATH search when the + caller uses execlp/execvp. */ + progpathname = XNMALLOC (2 + strlen (progname) + 1, char); + progpathname[0] = '.'; + progpathname[1] = '/'; + memcpy (progpathname + 2, progname, strlen (progname) + 1); + } + + free (path); + return progpathname; + } + + free (progpathname); + + if (last) + break; + } + + /* Not found in PATH. An error will be signalled at the first call. */ + free (path); + return progname; +#endif +} + +#endif diff --git a/gettext-tools/gnulib-lib/findprog.h b/gettext-tools/gnulib-lib/findprog.h new file mode 100644 index 0000000..90362b6 --- /dev/null +++ b/gettext-tools/gnulib-lib/findprog.h @@ -0,0 +1,37 @@ +/* Locating a program in PATH. + Copyright (C) 2001-2003, 2009-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2001. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Look up a program in the PATH. + Attempt to determine the pathname that would be called by execlp/execvp + of PROGNAME. If successful, return a pathname containing a slash + (either absolute or relative to the current directory). Otherwise, + return PROGNAME unmodified. + Because of the latter case, callers should use execlp/execvp, not + execl/execv on the returned pathname. + The returned string is freshly malloc()ed if it is != PROGNAME. */ +extern const char *find_in_path (const char *progname); + + +#ifdef __cplusplus +} +#endif diff --git a/gettext-tools/gnulib-lib/float+.h b/gettext-tools/gnulib-lib/float+.h new file mode 100644 index 0000000..5ff1511 --- /dev/null +++ b/gettext-tools/gnulib-lib/float+.h @@ -0,0 +1,147 @@ +/* Supplemental information about the floating-point formats. + Copyright (C) 2007, 2009-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2007. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . */ + +#ifndef _FLOATPLUS_H +#define _FLOATPLUS_H + +#include +#include + +/* Number of bits in the mantissa of a floating-point number, including the + "hidden bit". */ +#if FLT_RADIX == 2 +# define FLT_MANT_BIT FLT_MANT_DIG +# define DBL_MANT_BIT DBL_MANT_DIG +# define LDBL_MANT_BIT LDBL_MANT_DIG +#elif FLT_RADIX == 4 +# define FLT_MANT_BIT (FLT_MANT_DIG * 2) +# define DBL_MANT_BIT (DBL_MANT_DIG * 2) +# define LDBL_MANT_BIT (LDBL_MANT_DIG * 2) +#elif FLT_RADIX == 16 +# define FLT_MANT_BIT (FLT_MANT_DIG * 4) +# define DBL_MANT_BIT (DBL_MANT_DIG * 4) +# define LDBL_MANT_BIT (LDBL_MANT_DIG * 4) +#endif + +/* Bit mask that can be used to mask the exponent, as an unsigned number. */ +#define FLT_EXP_MASK ((FLT_MAX_EXP - FLT_MIN_EXP) | 7) +#define DBL_EXP_MASK ((DBL_MAX_EXP - DBL_MIN_EXP) | 7) +#define LDBL_EXP_MASK ((LDBL_MAX_EXP - LDBL_MIN_EXP) | 7) + +/* Number of bits used for the exponent of a floating-point number, including + the exponent's sign. */ +#define FLT_EXP_BIT \ + (FLT_EXP_MASK < 0x100 ? 8 : \ + FLT_EXP_MASK < 0x200 ? 9 : \ + FLT_EXP_MASK < 0x400 ? 10 : \ + FLT_EXP_MASK < 0x800 ? 11 : \ + FLT_EXP_MASK < 0x1000 ? 12 : \ + FLT_EXP_MASK < 0x2000 ? 13 : \ + FLT_EXP_MASK < 0x4000 ? 14 : \ + FLT_EXP_MASK < 0x8000 ? 15 : \ + FLT_EXP_MASK < 0x10000 ? 16 : \ + FLT_EXP_MASK < 0x20000 ? 17 : \ + FLT_EXP_MASK < 0x40000 ? 18 : \ + FLT_EXP_MASK < 0x80000 ? 19 : \ + FLT_EXP_MASK < 0x100000 ? 20 : \ + FLT_EXP_MASK < 0x200000 ? 21 : \ + FLT_EXP_MASK < 0x400000 ? 22 : \ + FLT_EXP_MASK < 0x800000 ? 23 : \ + FLT_EXP_MASK < 0x1000000 ? 24 : \ + FLT_EXP_MASK < 0x2000000 ? 25 : \ + FLT_EXP_MASK < 0x4000000 ? 26 : \ + FLT_EXP_MASK < 0x8000000 ? 27 : \ + FLT_EXP_MASK < 0x10000000 ? 28 : \ + FLT_EXP_MASK < 0x20000000 ? 29 : \ + FLT_EXP_MASK < 0x40000000 ? 30 : \ + FLT_EXP_MASK <= 0x7fffffff ? 31 : \ + 32) +#define DBL_EXP_BIT \ + (DBL_EXP_MASK < 0x100 ? 8 : \ + DBL_EXP_MASK < 0x200 ? 9 : \ + DBL_EXP_MASK < 0x400 ? 10 : \ + DBL_EXP_MASK < 0x800 ? 11 : \ + DBL_EXP_MASK < 0x1000 ? 12 : \ + DBL_EXP_MASK < 0x2000 ? 13 : \ + DBL_EXP_MASK < 0x4000 ? 14 : \ + DBL_EXP_MASK < 0x8000 ? 15 : \ + DBL_EXP_MASK < 0x10000 ? 16 : \ + DBL_EXP_MASK < 0x20000 ? 17 : \ + DBL_EXP_MASK < 0x40000 ? 18 : \ + DBL_EXP_MASK < 0x80000 ? 19 : \ + DBL_EXP_MASK < 0x100000 ? 20 : \ + DBL_EXP_MASK < 0x200000 ? 21 : \ + DBL_EXP_MASK < 0x400000 ? 22 : \ + DBL_EXP_MASK < 0x800000 ? 23 : \ + DBL_EXP_MASK < 0x1000000 ? 24 : \ + DBL_EXP_MASK < 0x2000000 ? 25 : \ + DBL_EXP_MASK < 0x4000000 ? 26 : \ + DBL_EXP_MASK < 0x8000000 ? 27 : \ + DBL_EXP_MASK < 0x10000000 ? 28 : \ + DBL_EXP_MASK < 0x20000000 ? 29 : \ + DBL_EXP_MASK < 0x40000000 ? 30 : \ + DBL_EXP_MASK <= 0x7fffffff ? 31 : \ + 32) +#define LDBL_EXP_BIT \ + (LDBL_EXP_MASK < 0x100 ? 8 : \ + LDBL_EXP_MASK < 0x200 ? 9 : \ + LDBL_EXP_MASK < 0x400 ? 10 : \ + LDBL_EXP_MASK < 0x800 ? 11 : \ + LDBL_EXP_MASK < 0x1000 ? 12 : \ + LDBL_EXP_MASK < 0x2000 ? 13 : \ + LDBL_EXP_MASK < 0x4000 ? 14 : \ + LDBL_EXP_MASK < 0x8000 ? 15 : \ + LDBL_EXP_MASK < 0x10000 ? 16 : \ + LDBL_EXP_MASK < 0x20000 ? 17 : \ + LDBL_EXP_MASK < 0x40000 ? 18 : \ + LDBL_EXP_MASK < 0x80000 ? 19 : \ + LDBL_EXP_MASK < 0x100000 ? 20 : \ + LDBL_EXP_MASK < 0x200000 ? 21 : \ + LDBL_EXP_MASK < 0x400000 ? 22 : \ + LDBL_EXP_MASK < 0x800000 ? 23 : \ + LDBL_EXP_MASK < 0x1000000 ? 24 : \ + LDBL_EXP_MASK < 0x2000000 ? 25 : \ + LDBL_EXP_MASK < 0x4000000 ? 26 : \ + LDBL_EXP_MASK < 0x8000000 ? 27 : \ + LDBL_EXP_MASK < 0x10000000 ? 28 : \ + LDBL_EXP_MASK < 0x20000000 ? 29 : \ + LDBL_EXP_MASK < 0x40000000 ? 30 : \ + LDBL_EXP_MASK <= 0x7fffffff ? 31 : \ + 32) + +/* Number of bits used for a floating-point number: the mantissa (not + counting the "hidden bit", since it may or may not be explicit), the + exponent, and the sign. */ +#define FLT_TOTAL_BIT ((FLT_MANT_BIT - 1) + FLT_EXP_BIT + 1) +#define DBL_TOTAL_BIT ((DBL_MANT_BIT - 1) + DBL_EXP_BIT + 1) +#define LDBL_TOTAL_BIT ((LDBL_MANT_BIT - 1) + LDBL_EXP_BIT + 1) + +/* Number of bytes used for a floating-point number. + This can be smaller than the 'sizeof'. For example, on i386 systems, + 'long double' most often have LDBL_MANT_BIT = 64, LDBL_EXP_BIT = 16, hence + LDBL_TOTAL_BIT = 80 bits, i.e. 10 bytes of consecutive memory, but + sizeof (long double) = 12 or = 16. */ +#define SIZEOF_FLT ((FLT_TOTAL_BIT + CHAR_BIT - 1) / CHAR_BIT) +#define SIZEOF_DBL ((DBL_TOTAL_BIT + CHAR_BIT - 1) / CHAR_BIT) +#define SIZEOF_LDBL ((LDBL_TOTAL_BIT + CHAR_BIT - 1) / CHAR_BIT) + +/* Verify that SIZEOF_FLT <= sizeof (float) etc. */ +typedef int verify_sizeof_flt[SIZEOF_FLT <= sizeof (float) ? 1 : -1]; +typedef int verify_sizeof_dbl[SIZEOF_DBL <= sizeof (double) ? 1 : - 1]; +typedef int verify_sizeof_ldbl[SIZEOF_LDBL <= sizeof (long double) ? 1 : - 1]; + +#endif /* _FLOATPLUS_H */ diff --git a/gettext-tools/gnulib-lib/float.c b/gettext-tools/gnulib-lib/float.c new file mode 100644 index 0000000..b7c321d --- /dev/null +++ b/gettext-tools/gnulib-lib/float.c @@ -0,0 +1,33 @@ +/* Auxiliary definitions for . + Copyright (C) 2011-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2011. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include + +#if (defined _ARCH_PPC || defined _POWER) && (defined _AIX || defined __linux__) && (LDBL_MANT_DIG == 106) && defined __GNUC__ +const union gl_long_double_union gl_LDBL_MAX = + { { DBL_MAX, DBL_MAX / (double)134217728UL / (double)134217728UL } }; +#elif defined __i386__ +const union gl_long_double_union gl_LDBL_MAX = + { { 0xFFFFFFFF, 0xFFFFFFFF, 32766 } }; +#else +/* This declaration is solely to ensure that after preprocessing + this file is never empty. */ +typedef int dummy; +#endif diff --git a/gettext-tools/gnulib-lib/float.in.h b/gettext-tools/gnulib-lib/float.in.h new file mode 100644 index 0000000..db809f8 --- /dev/null +++ b/gettext-tools/gnulib-lib/float.in.h @@ -0,0 +1,188 @@ +/* A correct . + + Copyright (C) 2007-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _@GUARD_PREFIX@_FLOAT_H + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +/* The include_next requires a split double-inclusion guard. */ +#@INCLUDE_NEXT@ @NEXT_FLOAT_H@ + +#ifndef _@GUARD_PREFIX@_FLOAT_H +#define _@GUARD_PREFIX@_FLOAT_H + +/* 'long double' properties. */ + +#if defined __i386__ && (defined __BEOS__ || defined __OpenBSD__) +/* Number of mantissa units, in base FLT_RADIX. */ +# undef LDBL_MANT_DIG +# define LDBL_MANT_DIG 64 +/* Number of decimal digits that is sufficient for representing a number. */ +# undef LDBL_DIG +# define LDBL_DIG 18 +/* x-1 where x is the smallest representable number > 1. */ +# undef LDBL_EPSILON +# define LDBL_EPSILON 1.0842021724855044340E-19L +/* Minimum e such that FLT_RADIX^(e-1) is a normalized number. */ +# undef LDBL_MIN_EXP +# define LDBL_MIN_EXP (-16381) +/* Maximum e such that FLT_RADIX^(e-1) is a representable finite number. */ +# undef LDBL_MAX_EXP +# define LDBL_MAX_EXP 16384 +/* Minimum positive normalized number. */ +# undef LDBL_MIN +# define LDBL_MIN 3.3621031431120935063E-4932L +/* Maximum representable finite number. */ +# undef LDBL_MAX +# define LDBL_MAX 1.1897314953572317650E+4932L +/* Minimum e such that 10^e is in the range of normalized numbers. */ +# undef LDBL_MIN_10_EXP +# define LDBL_MIN_10_EXP (-4931) +/* Maximum e such that 10^e is in the range of representable finite numbers. */ +# undef LDBL_MAX_10_EXP +# define LDBL_MAX_10_EXP 4932 +#endif + +/* On FreeBSD/x86 6.4, the 'long double' type really has only 53 bits of + precision in the compiler but 64 bits of precision at runtime. See + . */ +#if defined __i386__ && defined __FreeBSD__ +/* Number of mantissa units, in base FLT_RADIX. */ +# undef LDBL_MANT_DIG +# define LDBL_MANT_DIG 64 +/* Number of decimal digits that is sufficient for representing a number. */ +# undef LDBL_DIG +# define LDBL_DIG 18 +/* x-1 where x is the smallest representable number > 1. */ +# undef LDBL_EPSILON +# define LDBL_EPSILON 1.084202172485504434007452800869941711426e-19L /* 2^-63 */ +/* Minimum e such that FLT_RADIX^(e-1) is a normalized number. */ +# undef LDBL_MIN_EXP +# define LDBL_MIN_EXP (-16381) +/* Maximum e such that FLT_RADIX^(e-1) is a representable finite number. */ +# undef LDBL_MAX_EXP +# define LDBL_MAX_EXP 16384 +/* Minimum positive normalized number. */ +# undef LDBL_MIN +# define LDBL_MIN 3.3621031431120935E-4932L /* = 0x1p-16382L */ +/* Maximum representable finite number. */ +# undef LDBL_MAX +/* LDBL_MAX is represented as { 0xFFFFFFFF, 0xFFFFFFFF, 32766 }. + But the largest literal that GCC allows us to write is + 0x0.fffffffffffff8p16384L = { 0xFFFFF800, 0xFFFFFFFF, 32766 }. + So, define it like this through a reference to an external variable + + const unsigned int LDBL_MAX[3] = { 0xFFFFFFFF, 0xFFFFFFFF, 32766 }; + extern const long double LDBL_MAX; + + Unfortunately, this is not a constant expression. */ +union gl_long_double_union + { + struct { unsigned int lo; unsigned int hi; unsigned int exponent; } xd; + long double ld; + }; +extern const union gl_long_double_union gl_LDBL_MAX; +# define LDBL_MAX (gl_LDBL_MAX.ld) +/* Minimum e such that 10^e is in the range of normalized numbers. */ +# undef LDBL_MIN_10_EXP +# define LDBL_MIN_10_EXP (-4931) +/* Maximum e such that 10^e is in the range of representable finite numbers. */ +# undef LDBL_MAX_10_EXP +# define LDBL_MAX_10_EXP 4932 +#endif + +/* On AIX 7.1 with gcc 4.2, the values of LDBL_MIN_EXP, LDBL_MIN, LDBL_MAX are + wrong. + On Linux/PowerPC with gcc 4.4, the value of LDBL_MAX is wrong. */ +#if (defined _ARCH_PPC || defined _POWER) && defined _AIX && (LDBL_MANT_DIG == 106) && defined __GNUC__ +# undef LDBL_MIN_EXP +# define LDBL_MIN_EXP DBL_MIN_EXP +# undef LDBL_MIN_10_EXP +# define LDBL_MIN_10_EXP DBL_MIN_10_EXP +# undef LDBL_MIN +# define LDBL_MIN 2.22507385850720138309023271733240406422e-308L /* DBL_MIN = 2^-1022 */ +#endif +#if (defined _ARCH_PPC || defined _POWER) && (defined _AIX || defined __linux__) && (LDBL_MANT_DIG == 106) && defined __GNUC__ +# undef LDBL_MAX +/* LDBL_MAX is represented as { 0x7FEFFFFF, 0xFFFFFFFF, 0x7C8FFFFF, 0xFFFFFFFF }. + It is not easy to define: + #define LDBL_MAX 1.79769313486231580793728971405302307166e308L + is too small, whereas + #define LDBL_MAX 1.79769313486231580793728971405302307167e308L + is too large. Apparently a bug in GCC decimal-to-binary conversion. + Also, I can't get values larger than + #define LDBL63 ((long double) (1ULL << 63)) + #define LDBL882 (LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63) + #define LDBL945 (LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63) + #define LDBL1008 (LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63) + #define LDBL_MAX (LDBL1008 * 65535.0L + LDBL945 * (long double) 9223372036821221375ULL + LDBL882 * (long double) 4611686018427387904ULL) + which is represented as { 0x7FEFFFFF, 0xFFFFFFFF, 0x7C8FFFFF, 0xF8000000 }. + So, define it like this through a reference to an external variable + + const double LDBL_MAX[2] = { DBL_MAX, DBL_MAX / (double)134217728UL / (double)134217728UL }; + extern const long double LDBL_MAX; + + or through a pointer cast + + #define LDBL_MAX \ + (*(const long double *) (double[]) { DBL_MAX, DBL_MAX / (double)134217728UL / (double)134217728UL }) + + Unfortunately, this is not a constant expression, and the latter expression + does not work well when GCC is optimizing.. */ +union gl_long_double_union + { + struct { double hi; double lo; } dd; + long double ld; + }; +extern const union gl_long_double_union gl_LDBL_MAX; +# define LDBL_MAX (gl_LDBL_MAX.ld) +#endif + +/* On IRIX 6.5, with cc, the value of LDBL_MANT_DIG is wrong. + On IRIX 6.5, with gcc 4.2, the values of LDBL_MIN_EXP, LDBL_MIN, LDBL_EPSILON + are wrong. */ +#if defined __sgi && (LDBL_MANT_DIG >= 106) +# undef LDBL_MANT_DIG +# define LDBL_MANT_DIG 106 +# if defined __GNUC__ +# undef LDBL_MIN_EXP +# define LDBL_MIN_EXP DBL_MIN_EXP +# undef LDBL_MIN_10_EXP +# define LDBL_MIN_10_EXP DBL_MIN_10_EXP +# undef LDBL_MIN +# define LDBL_MIN 2.22507385850720138309023271733240406422e-308L /* DBL_MIN = 2^-1022 */ +# undef LDBL_EPSILON +# define LDBL_EPSILON 2.46519032881566189191165176650870696773e-32L /* 2^-105 */ +# endif +#endif + +#if @REPLACE_ITOLD@ +/* Pull in a function that fixes the 'int' to 'long double' conversion + of glibc 2.7. */ +extern +# ifdef __cplusplus +"C" +# endif +void _Qp_itoq (long double *, int); +static void (*_gl_float_fix_itold) (long double *, int) = _Qp_itoq; +#endif + +#endif /* _@GUARD_PREFIX@_FLOAT_H */ +#endif /* _@GUARD_PREFIX@_FLOAT_H */ diff --git a/gettext-tools/gnulib-lib/fnmatch.c b/gettext-tools/gnulib-lib/fnmatch.c new file mode 100644 index 0000000..5b73973 --- /dev/null +++ b/gettext-tools/gnulib-lib/fnmatch.c @@ -0,0 +1,354 @@ +/* Copyright (C) 1991-1993, 1996-2007, 2009-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . */ + +#ifndef _LIBC +# include +#endif + +/* Enable GNU extensions in fnmatch.h. */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +#endif + +#if ! defined __builtin_expect && __GNUC__ < 3 +# define __builtin_expect(expr, expected) (expr) +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#define WIDE_CHAR_SUPPORT \ + (HAVE_WCTYPE_H && HAVE_BTOWC && HAVE_ISWCTYPE \ + && HAVE_WMEMCHR && (HAVE_WMEMCPY || HAVE_WMEMPCPY)) + +/* For platform which support the ISO C amendment 1 functionality we + support user defined character classes. */ +#if defined _LIBC || WIDE_CHAR_SUPPORT +# include +# include +#endif + +/* We need some of the locale data (the collation sequence information) + but there is no interface to get this information in general. Therefore + we support a correct implementation only in glibc. */ +#ifdef _LIBC +# include "../locale/localeinfo.h" +# include "../locale/elem-hash.h" +# include "../locale/coll-lookup.h" +# include + +# define CONCAT(a,b) __CONCAT(a,b) +# define mbsrtowcs __mbsrtowcs +# define fnmatch __fnmatch +extern int fnmatch (const char *pattern, const char *string, int flags); +#endif + +#ifndef SIZE_MAX +# define SIZE_MAX ((size_t) -1) +#endif + +/* We often have to test for FNM_FILE_NAME and FNM_PERIOD being both set. */ +#define NO_LEADING_PERIOD(flags) \ + ((flags & (FNM_FILE_NAME | FNM_PERIOD)) == (FNM_FILE_NAME | FNM_PERIOD)) + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself, and have not detected a bug + in the library. This code is part of the GNU C + Library, but also included in many other GNU distributions. Compiling + and linking in this code is a waste when using the GNU C library + (especially if it is a shared library). Rather than having every GNU + program understand 'configure --with-gnu-libc' and omit the object files, + it is simpler to just do this in the source for each such file. */ + +#if defined _LIBC || !defined __GNU_LIBRARY__ || !HAVE_FNMATCH_GNU + + +# if ! (defined isblank || (HAVE_ISBLANK && HAVE_DECL_ISBLANK)) +# define isblank(c) ((c) == ' ' || (c) == '\t') +# endif + +# define STREQ(s1, s2) (strcmp (s1, s2) == 0) + +# if defined _LIBC || WIDE_CHAR_SUPPORT +/* The GNU C library provides support for user-defined character classes + and the functions from ISO C amendment 1. */ +# ifdef CHARCLASS_NAME_MAX +# define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX +# else +/* This shouldn't happen but some implementation might still have this + problem. Use a reasonable default value. */ +# define CHAR_CLASS_MAX_LENGTH 256 +# endif + +# ifdef _LIBC +# define IS_CHAR_CLASS(string) __wctype (string) +# else +# define IS_CHAR_CLASS(string) wctype (string) +# endif + +# ifdef _LIBC +# define ISWCTYPE(WC, WT) __iswctype (WC, WT) +# else +# define ISWCTYPE(WC, WT) iswctype (WC, WT) +# endif + +# if (HAVE_MBSTATE_T && HAVE_MBSRTOWCS) || _LIBC +/* In this case we are implementing the multibyte character handling. */ +# define HANDLE_MULTIBYTE 1 +# endif + +# else +# define CHAR_CLASS_MAX_LENGTH 6 /* Namely, 'xdigit'. */ + +# define IS_CHAR_CLASS(string) \ + (STREQ (string, "alpha") || STREQ (string, "upper") \ + || STREQ (string, "lower") || STREQ (string, "digit") \ + || STREQ (string, "alnum") || STREQ (string, "xdigit") \ + || STREQ (string, "space") || STREQ (string, "print") \ + || STREQ (string, "punct") || STREQ (string, "graph") \ + || STREQ (string, "cntrl") || STREQ (string, "blank")) +# endif + +/* Avoid depending on library functions or files + whose names are inconsistent. */ + +/* Global variable. */ +static int posixly_correct; + +# ifndef internal_function +/* Inside GNU libc we mark some function in a special way. In other + environments simply ignore the marking. */ +# define internal_function +# endif + +/* Note that this evaluates C many times. */ +# define FOLD(c) ((flags & FNM_CASEFOLD) ? tolower (c) : (c)) +# define CHAR char +# define UCHAR unsigned char +# define INT int +# define FCT internal_fnmatch +# define EXT ext_match +# define END end_pattern +# define L_(CS) CS +# ifdef _LIBC +# define BTOWC(C) __btowc (C) +# else +# define BTOWC(C) btowc (C) +# endif +# define STRLEN(S) strlen (S) +# define STRCAT(D, S) strcat (D, S) +# ifdef _LIBC +# define MEMPCPY(D, S, N) __mempcpy (D, S, N) +# else +# if HAVE_MEMPCPY +# define MEMPCPY(D, S, N) mempcpy (D, S, N) +# else +# define MEMPCPY(D, S, N) ((void *) ((char *) memcpy (D, S, N) + (N))) +# endif +# endif +# define MEMCHR(S, C, N) memchr (S, C, N) +# include "fnmatch_loop.c" + + +# if HANDLE_MULTIBYTE +# define FOLD(c) ((flags & FNM_CASEFOLD) ? towlower (c) : (c)) +# define CHAR wchar_t +# define UCHAR wint_t +# define INT wint_t +# define FCT internal_fnwmatch +# define EXT ext_wmatch +# define END end_wpattern +# define L_(CS) L##CS +# define BTOWC(C) (C) +# ifdef _LIBC +# define STRLEN(S) __wcslen (S) +# define STRCAT(D, S) __wcscat (D, S) +# define MEMPCPY(D, S, N) __wmempcpy (D, S, N) +# else +# define STRLEN(S) wcslen (S) +# define STRCAT(D, S) wcscat (D, S) +# if HAVE_WMEMPCPY +# define MEMPCPY(D, S, N) wmempcpy (D, S, N) +# else +# define MEMPCPY(D, S, N) (wmemcpy (D, S, N) + (N)) +# endif +# endif +# define MEMCHR(S, C, N) wmemchr (S, C, N) +# define WIDE_CHAR_VERSION 1 + +# undef IS_CHAR_CLASS +/* We have to convert the wide character string in a multibyte string. But + we know that the character class names consist of alphanumeric characters + from the portable character set, and since the wide character encoding + for a member of the portable character set is the same code point as + its single-byte encoding, we can use a simplified method to convert the + string to a multibyte character string. */ +static wctype_t +is_char_class (const wchar_t *wcs) +{ + char s[CHAR_CLASS_MAX_LENGTH + 1]; + char *cp = s; + + do + { + /* Test for a printable character from the portable character set. */ +# ifdef _LIBC + if (*wcs < 0x20 || *wcs > 0x7e + || *wcs == 0x24 || *wcs == 0x40 || *wcs == 0x60) + return (wctype_t) 0; +# else + switch (*wcs) + { + case L' ': case L'!': case L'"': case L'#': case L'%': + case L'&': case L'\'': case L'(': case L')': case L'*': + case L'+': case L',': case L'-': case L'.': case L'/': + case L'0': case L'1': case L'2': case L'3': case L'4': + case L'5': case L'6': case L'7': case L'8': case L'9': + case L':': case L';': case L'<': case L'=': case L'>': + case L'?': + case L'A': case L'B': case L'C': case L'D': case L'E': + case L'F': case L'G': case L'H': case L'I': case L'J': + case L'K': case L'L': case L'M': case L'N': case L'O': + case L'P': case L'Q': case L'R': case L'S': case L'T': + case L'U': case L'V': case L'W': case L'X': case L'Y': + case L'Z': + case L'[': case L'\\': case L']': case L'^': case L'_': + case L'a': case L'b': case L'c': case L'd': case L'e': + case L'f': case L'g': case L'h': case L'i': case L'j': + case L'k': case L'l': case L'm': case L'n': case L'o': + case L'p': case L'q': case L'r': case L's': case L't': + case L'u': case L'v': case L'w': case L'x': case L'y': + case L'z': case L'{': case L'|': case L'}': case L'~': + break; + default: + return (wctype_t) 0; + } +# endif + + /* Avoid overrunning the buffer. */ + if (cp == s + CHAR_CLASS_MAX_LENGTH) + return (wctype_t) 0; + + *cp++ = (char) *wcs++; + } + while (*wcs != L'\0'); + + *cp = '\0'; + +# ifdef _LIBC + return __wctype (s); +# else + return wctype (s); +# endif +} +# define IS_CHAR_CLASS(string) is_char_class (string) + +# include "fnmatch_loop.c" +# endif + + +int +fnmatch (const char *pattern, const char *string, int flags) +{ +# if HANDLE_MULTIBYTE +# if HAVE_ALLOCA || defined _LIBC +# define ALLOCA_LIMIT 2000 +# else +# define ALLOCA_LIMIT 0 +# endif + if (__builtin_expect (MB_CUR_MAX, 1) != 1) + { + mbstate_t ps; + size_t patsize; + size_t strsize; + size_t totsize; + wchar_t *wpattern; + wchar_t *wstring; + int res; + + /* Calculate the size needed to convert the strings to + wide characters. */ + memset (&ps, '\0', sizeof (ps)); + patsize = mbsrtowcs (NULL, &pattern, 0, &ps) + 1; + if (__builtin_expect (patsize != 0, 1)) + { + assert (mbsinit (&ps)); + strsize = mbsrtowcs (NULL, &string, 0, &ps) + 1; + if (__builtin_expect (strsize != 0, 1)) + { + assert (mbsinit (&ps)); + totsize = patsize + strsize; + if (__builtin_expect (! (patsize <= totsize + && totsize <= SIZE_MAX / sizeof (wchar_t)), + 0)) + { + errno = ENOMEM; + return -1; + } + + /* Allocate room for the wide characters. */ + if (__builtin_expect (totsize < ALLOCA_LIMIT, 1)) + wpattern = (wchar_t *) alloca (totsize * sizeof (wchar_t)); + else + { + wpattern = malloc (totsize * sizeof (wchar_t)); + if (__builtin_expect (! wpattern, 0)) + { + errno = ENOMEM; + return -1; + } + } + wstring = wpattern + patsize; + + /* Convert the strings into wide characters. */ + mbsrtowcs (wpattern, &pattern, patsize, &ps); + assert (mbsinit (&ps)); + mbsrtowcs (wstring, &string, strsize, &ps); + + res = internal_fnwmatch (wpattern, wstring, wstring + strsize - 1, + flags & FNM_PERIOD, flags); + + if (__builtin_expect (! (totsize < ALLOCA_LIMIT), 0)) + free (wpattern); + return res; + } + } + } + +# endif /* HANDLE_MULTIBYTE */ + + return internal_fnmatch (pattern, string, string + strlen (string), + flags & FNM_PERIOD, flags); +} + +# ifdef _LIBC +# undef fnmatch +versioned_symbol (libc, __fnmatch, fnmatch, GLIBC_2_2_3); +# if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_2_3) +strong_alias (__fnmatch, __fnmatch_old) +compat_symbol (libc, __fnmatch_old, fnmatch, GLIBC_2_0); +# endif +libc_hidden_ver (__fnmatch, fnmatch) +# endif + +#endif /* _LIBC or not __GNU_LIBRARY__. */ diff --git a/gettext-tools/gnulib-lib/fnmatch.in.h b/gettext-tools/gnulib-lib/fnmatch.in.h new file mode 100644 index 0000000..d4cea65 --- /dev/null +++ b/gettext-tools/gnulib-lib/fnmatch.in.h @@ -0,0 +1,67 @@ +/* Copyright (C) 1991-1993, 1996-1999, 2001-2003, 2005, 2007, 2009-2014 Free + Software Foundation, Inc. + + This file is part of the GNU C Library. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . */ + +#ifndef _FNMATCH_H +#define _FNMATCH_H 1 + +/* The definition of _GL_ARG_NONNULL is copied here. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* We #undef these before defining them because some losing systems + (HP-UX A.08.07 for example) define these in . */ +#undef FNM_PATHNAME +#undef FNM_NOESCAPE +#undef FNM_PERIOD + +/* Bits set in the FLAGS argument to 'fnmatch'. */ +#define FNM_PATHNAME (1 << 0) /* No wildcard can ever match '/'. */ +#define FNM_NOESCAPE (1 << 1) /* Backslashes don't quote special chars. */ +#define FNM_PERIOD (1 << 2) /* Leading '.' is matched only explicitly. */ + +#if !defined _POSIX_C_SOURCE || _POSIX_C_SOURCE < 2 || defined _GNU_SOURCE +# define FNM_FILE_NAME FNM_PATHNAME /* Preferred GNU name. */ +# define FNM_LEADING_DIR (1 << 3) /* Ignore '/...' after a match. */ +# define FNM_CASEFOLD (1 << 4) /* Compare without regard to case. */ +# define FNM_EXTMATCH (1 << 5) /* Use ksh-like extended matching. */ +#endif + +/* Value returned by 'fnmatch' if STRING does not match PATTERN. */ +#define FNM_NOMATCH 1 + +/* This value is returned if the implementation does not support + 'fnmatch'. Since this is not the case here it will never be + returned but the conformance test suites still require the symbol + to be defined. */ +#ifdef _XOPEN_SOURCE +# define FNM_NOSYS (-1) +#endif + +/* Match NAME against the file name pattern PATTERN, + returning zero if it matches, FNM_NOMATCH if not. */ +extern int fnmatch (const char *__pattern, const char *__name, + int __flags) + _GL_ARG_NONNULL ((1, 2)); + +#ifdef __cplusplus +} +#endif + +#endif /* fnmatch.h */ diff --git a/gettext-tools/gnulib-lib/fnmatch_loop.c b/gettext-tools/gnulib-lib/fnmatch_loop.c new file mode 100644 index 0000000..b39918c --- /dev/null +++ b/gettext-tools/gnulib-lib/fnmatch_loop.c @@ -0,0 +1,1278 @@ +/* Copyright (C) 1991-1993, 1996-2006, 2009-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . */ + +/* Match STRING against the file name pattern PATTERN, returning zero if + it matches, nonzero if not. */ +static int EXT (INT opt, const CHAR *pattern, const CHAR *string, + const CHAR *string_end, bool no_leading_period, int flags) + internal_function; +static const CHAR *END (const CHAR *patternp) internal_function; + +static int +internal_function +FCT (const CHAR *pattern, const CHAR *string, const CHAR *string_end, + bool no_leading_period, int flags) +{ + register const CHAR *p = pattern, *n = string; + register UCHAR c; +#ifdef _LIBC +# if WIDE_CHAR_VERSION + const char *collseq = (const char *) + _NL_CURRENT(LC_COLLATE, _NL_COLLATE_COLLSEQWC); +# else + const UCHAR *collseq = (const UCHAR *) + _NL_CURRENT(LC_COLLATE, _NL_COLLATE_COLLSEQMB); +# endif +#endif + + while ((c = *p++) != L_('\0')) + { + bool new_no_leading_period = false; + c = FOLD (c); + + switch (c) + { + case L_('?'): + if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(') + { + int res; + + res = EXT (c, p, n, string_end, no_leading_period, + flags); + if (res != -1) + return res; + } + + if (n == string_end) + return FNM_NOMATCH; + else if (*n == L_('/') && (flags & FNM_FILE_NAME)) + return FNM_NOMATCH; + else if (*n == L_('.') && no_leading_period) + return FNM_NOMATCH; + break; + + case L_('\\'): + if (!(flags & FNM_NOESCAPE)) + { + c = *p++; + if (c == L_('\0')) + /* Trailing \ loses. */ + return FNM_NOMATCH; + c = FOLD (c); + } + if (n == string_end || FOLD ((UCHAR) *n) != c) + return FNM_NOMATCH; + break; + + case L_('*'): + if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(') + { + int res; + + res = EXT (c, p, n, string_end, no_leading_period, + flags); + if (res != -1) + return res; + } + + if (n != string_end && *n == L_('.') && no_leading_period) + return FNM_NOMATCH; + + for (c = *p++; c == L_('?') || c == L_('*'); c = *p++) + { + if (*p == L_('(') && (flags & FNM_EXTMATCH) != 0) + { + const CHAR *endp = END (p); + if (endp != p) + { + /* This is a pattern. Skip over it. */ + p = endp; + continue; + } + } + + if (c == L_('?')) + { + /* A ? needs to match one character. */ + if (n == string_end) + /* There isn't another character; no match. */ + return FNM_NOMATCH; + else if (*n == L_('/') + && __builtin_expect (flags & FNM_FILE_NAME, 0)) + /* A slash does not match a wildcard under + FNM_FILE_NAME. */ + return FNM_NOMATCH; + else + /* One character of the string is consumed in matching + this ? wildcard, so *??? won't match if there are + less than three characters. */ + ++n; + } + } + + if (c == L_('\0')) + /* The wildcard(s) is/are the last element of the pattern. + If the name is a file name and contains another slash + this means it cannot match, unless the FNM_LEADING_DIR + flag is set. */ + { + int result = (flags & FNM_FILE_NAME) == 0 ? 0 : FNM_NOMATCH; + + if (flags & FNM_FILE_NAME) + { + if (flags & FNM_LEADING_DIR) + result = 0; + else + { + if (MEMCHR (n, L_('/'), string_end - n) == NULL) + result = 0; + } + } + + return result; + } + else + { + const CHAR *endp; + + endp = MEMCHR (n, (flags & FNM_FILE_NAME) ? L_('/') : L_('\0'), + string_end - n); + if (endp == NULL) + endp = string_end; + + if (c == L_('[') + || (__builtin_expect (flags & FNM_EXTMATCH, 0) != 0 + && (c == L_('@') || c == L_('+') || c == L_('!')) + && *p == L_('('))) + { + int flags2 = ((flags & FNM_FILE_NAME) + ? flags : (flags & ~FNM_PERIOD)); + bool no_leading_period2 = no_leading_period; + + for (--p; n < endp; ++n, no_leading_period2 = false) + if (FCT (p, n, string_end, no_leading_period2, flags2) + == 0) + return 0; + } + else if (c == L_('/') && (flags & FNM_FILE_NAME)) + { + while (n < string_end && *n != L_('/')) + ++n; + if (n < string_end && *n == L_('/') + && (FCT (p, n + 1, string_end, flags & FNM_PERIOD, flags) + == 0)) + return 0; + } + else + { + int flags2 = ((flags & FNM_FILE_NAME) + ? flags : (flags & ~FNM_PERIOD)); + int no_leading_period2 = no_leading_period; + + if (c == L_('\\') && !(flags & FNM_NOESCAPE)) + c = *p; + c = FOLD (c); + for (--p; n < endp; ++n, no_leading_period2 = false) + if (FOLD ((UCHAR) *n) == c + && (FCT (p, n, string_end, no_leading_period2, flags2) + == 0)) + return 0; + } + } + + /* If we come here no match is possible with the wildcard. */ + return FNM_NOMATCH; + + case L_('['): + { + /* Nonzero if the sense of the character class is inverted. */ + const CHAR *p_init = p; + const CHAR *n_init = n; + register bool not; + CHAR cold; + UCHAR fn; + + if (posixly_correct == 0) + posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1; + + if (n == string_end) + return FNM_NOMATCH; + + if (*n == L_('.') && no_leading_period) + return FNM_NOMATCH; + + if (*n == L_('/') && (flags & FNM_FILE_NAME)) + /* '/' cannot be matched. */ + return FNM_NOMATCH; + + not = (*p == L_('!') || (posixly_correct < 0 && *p == L_('^'))); + if (not) + ++p; + + fn = FOLD ((UCHAR) *n); + + c = *p++; + for (;;) + { + bool is_range = false; + + if (!(flags & FNM_NOESCAPE) && c == L_('\\')) + { + if (*p == L_('\0')) + return FNM_NOMATCH; + c = FOLD ((UCHAR) *p); + ++p; + + goto normal_bracket; + } + else if (c == L_('[') && *p == L_(':')) + { + /* Leave room for the null. */ + CHAR str[CHAR_CLASS_MAX_LENGTH + 1]; + size_t c1 = 0; +#if defined _LIBC || WIDE_CHAR_SUPPORT + wctype_t wt; +#endif + const CHAR *startp = p; + + for (;;) + { + if (c1 == CHAR_CLASS_MAX_LENGTH) + /* The name is too long and therefore the pattern + is ill-formed. */ + return FNM_NOMATCH; + + c = *++p; + if (c == L_(':') && p[1] == L_(']')) + { + p += 2; + break; + } + if (c < L_('a') || c >= L_('z')) + { + /* This cannot possibly be a character class name. + Match it as a normal range. */ + p = startp; + c = L_('['); + goto normal_bracket; + } + str[c1++] = c; + } + str[c1] = L_('\0'); + +#if defined _LIBC || WIDE_CHAR_SUPPORT + wt = IS_CHAR_CLASS (str); + if (wt == 0) + /* Invalid character class name. */ + return FNM_NOMATCH; + +# if defined _LIBC && ! WIDE_CHAR_VERSION + /* The following code is glibc specific but does + there a good job in speeding up the code since + we can avoid the btowc() call. */ + if (_ISCTYPE ((UCHAR) *n, wt)) + goto matched; +# else + if (ISWCTYPE (BTOWC ((UCHAR) *n), wt)) + goto matched; +# endif +#else + if ((STREQ (str, L_("alnum")) && isalnum ((UCHAR) *n)) + || (STREQ (str, L_("alpha")) && isalpha ((UCHAR) *n)) + || (STREQ (str, L_("blank")) && isblank ((UCHAR) *n)) + || (STREQ (str, L_("cntrl")) && iscntrl ((UCHAR) *n)) + || (STREQ (str, L_("digit")) && isdigit ((UCHAR) *n)) + || (STREQ (str, L_("graph")) && isgraph ((UCHAR) *n)) + || (STREQ (str, L_("lower")) && islower ((UCHAR) *n)) + || (STREQ (str, L_("print")) && isprint ((UCHAR) *n)) + || (STREQ (str, L_("punct")) && ispunct ((UCHAR) *n)) + || (STREQ (str, L_("space")) && isspace ((UCHAR) *n)) + || (STREQ (str, L_("upper")) && isupper ((UCHAR) *n)) + || (STREQ (str, L_("xdigit")) && isxdigit ((UCHAR) *n))) + goto matched; +#endif + c = *p++; + } +#ifdef _LIBC + else if (c == L_('[') && *p == L_('=')) + { + UCHAR str[1]; + uint32_t nrules = + _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); + const CHAR *startp = p; + + c = *++p; + if (c == L_('\0')) + { + p = startp; + c = L_('['); + goto normal_bracket; + } + str[0] = c; + + c = *++p; + if (c != L_('=') || p[1] != L_(']')) + { + p = startp; + c = L_('['); + goto normal_bracket; + } + p += 2; + + if (nrules == 0) + { + if ((UCHAR) *n == str[0]) + goto matched; + } + else + { + const int32_t *table; +# if WIDE_CHAR_VERSION + const int32_t *weights; + const int32_t *extra; +# else + const unsigned char *weights; + const unsigned char *extra; +# endif + const int32_t *indirect; + int32_t idx; + const UCHAR *cp = (const UCHAR *) str; + + /* This #include defines a local function! */ +# if WIDE_CHAR_VERSION +# include +# else +# include +# endif + +# if WIDE_CHAR_VERSION + table = (const int32_t *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEWC); + weights = (const int32_t *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTWC); + extra = (const int32_t *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAWC); + indirect = (const int32_t *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTWC); +# else + table = (const int32_t *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); + weights = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTMB); + extra = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB); + indirect = (const int32_t *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB); +# endif + + idx = findidx (&cp); + if (idx != 0) + { + /* We found a table entry. Now see whether the + character we are currently at has the same + equivalence class value. */ + int len = weights[idx & 0xffffff]; + int32_t idx2; + const UCHAR *np = (const UCHAR *) n; + + idx2 = findidx (&np); + if (idx2 != 0 + && (idx >> 24) == (idx2 >> 24) + && len == weights[idx2 & 0xffffff]) + { + int cnt = 0; + + idx &= 0xffffff; + idx2 &= 0xffffff; + + while (cnt < len + && (weights[idx + 1 + cnt] + == weights[idx2 + 1 + cnt])) + ++cnt; + + if (cnt == len) + goto matched; + } + } + } + + c = *p++; + } +#endif + else if (c == L_('\0')) + { + /* [ unterminated, treat as normal character. */ + p = p_init; + n = n_init; + c = L_('['); + goto normal_match; + } + else + { +#ifdef _LIBC + bool is_seqval = false; + + if (c == L_('[') && *p == L_('.')) + { + uint32_t nrules = + _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); + const CHAR *startp = p; + size_t c1 = 0; + + while (1) + { + c = *++p; + if (c == L_('.') && p[1] == L_(']')) + { + p += 2; + break; + } + if (c == '\0') + return FNM_NOMATCH; + ++c1; + } + + /* We have to handling the symbols differently in + ranges since then the collation sequence is + important. */ + is_range = *p == L_('-') && p[1] != L_('\0'); + + if (nrules == 0) + { + /* There are no names defined in the collation + data. Therefore we only accept the trivial + names consisting of the character itself. */ + if (c1 != 1) + return FNM_NOMATCH; + + if (!is_range && *n == startp[1]) + goto matched; + + cold = startp[1]; + c = *p++; + } + else + { + int32_t table_size; + const int32_t *symb_table; +# ifdef WIDE_CHAR_VERSION + char str[c1]; + size_t strcnt; +# else +# define str (startp + 1) +# endif + const unsigned char *extra; + int32_t idx; + int32_t elem; + int32_t second; + int32_t hash; + +# ifdef WIDE_CHAR_VERSION + /* We have to convert the name to a single-byte + string. This is possible since the names + consist of ASCII characters and the internal + representation is UCS4. */ + for (strcnt = 0; strcnt < c1; ++strcnt) + str[strcnt] = startp[1 + strcnt]; +# endif + + table_size = + _NL_CURRENT_WORD (LC_COLLATE, + _NL_COLLATE_SYMB_HASH_SIZEMB); + symb_table = (const int32_t *) + _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_SYMB_TABLEMB); + extra = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_SYMB_EXTRAMB); + + /* Locate the character in the hashing table. */ + hash = elem_hash (str, c1); + + idx = 0; + elem = hash % table_size; + if (symb_table[2 * elem] != 0) + { + second = hash % (table_size - 2) + 1; + + do + { + /* First compare the hashing value. */ + if (symb_table[2 * elem] == hash + && (c1 + == extra[symb_table[2 * elem + 1]]) + && memcmp (str, + &extra[symb_table[2 * elem + + 1] + + 1], c1) == 0) + { + /* Yep, this is the entry. */ + idx = symb_table[2 * elem + 1]; + idx += 1 + extra[idx]; + break; + } + + /* Next entry. */ + elem += second; + } + while (symb_table[2 * elem] != 0); + } + + if (symb_table[2 * elem] != 0) + { + /* Compare the byte sequence but only if + this is not part of a range. */ +# ifdef WIDE_CHAR_VERSION + int32_t *wextra; + + idx += 1 + extra[idx]; + /* Adjust for the alignment. */ + idx = (idx + 3) & ~3; + + wextra = (int32_t *) &extra[idx + 4]; +# endif + + if (! is_range) + { +# ifdef WIDE_CHAR_VERSION + for (c1 = 0; + (int32_t) c1 < wextra[idx]; + ++c1) + if (n[c1] != wextra[1 + c1]) + break; + + if ((int32_t) c1 == wextra[idx]) + goto matched; +# else + for (c1 = 0; c1 < extra[idx]; ++c1) + if (n[c1] != extra[1 + c1]) + break; + + if (c1 == extra[idx]) + goto matched; +# endif + } + + /* Get the collation sequence value. */ + is_seqval = true; +# ifdef WIDE_CHAR_VERSION + cold = wextra[1 + wextra[idx]]; +# else + /* Adjust for the alignment. */ + idx += 1 + extra[idx]; + idx = (idx + 3) & ~4; + cold = *((int32_t *) &extra[idx]); +# endif + + c = *p++; + } + else if (c1 == 1) + { + /* No valid character. Match it as a + single byte. */ + if (!is_range && *n == str[0]) + goto matched; + + cold = str[0]; + c = *p++; + } + else + return FNM_NOMATCH; + } + } + else +# undef str +#endif + { + c = FOLD (c); + normal_bracket: + + /* We have to handling the symbols differently in + ranges since then the collation sequence is + important. */ + is_range = (*p == L_('-') && p[1] != L_('\0') + && p[1] != L_(']')); + + if (!is_range && c == fn) + goto matched; + +#if _LIBC + /* This is needed if we goto normal_bracket; from + outside of is_seqval's scope. */ + is_seqval = false; +#endif + + cold = c; + c = *p++; + } + + if (c == L_('-') && *p != L_(']')) + { +#if _LIBC + /* We have to find the collation sequence + value for C. Collation sequence is nothing + we can regularly access. The sequence + value is defined by the order in which the + definitions of the collation values for the + various characters appear in the source + file. A strange concept, nowhere + documented. */ + uint32_t fcollseq; + uint32_t lcollseq; + UCHAR cend = *p++; + +# ifdef WIDE_CHAR_VERSION + /* Search in the 'names' array for the characters. */ + fcollseq = __collseq_table_lookup (collseq, fn); + if (fcollseq == ~((uint32_t) 0)) + /* XXX We don't know anything about the character + we are supposed to match. This means we are + failing. */ + goto range_not_matched; + + if (is_seqval) + lcollseq = cold; + else + lcollseq = __collseq_table_lookup (collseq, cold); +# else + fcollseq = collseq[fn]; + lcollseq = is_seqval ? cold : collseq[(UCHAR) cold]; +# endif + + is_seqval = false; + if (cend == L_('[') && *p == L_('.')) + { + uint32_t nrules = + _NL_CURRENT_WORD (LC_COLLATE, + _NL_COLLATE_NRULES); + const CHAR *startp = p; + size_t c1 = 0; + + while (1) + { + c = *++p; + if (c == L_('.') && p[1] == L_(']')) + { + p += 2; + break; + } + if (c == '\0') + return FNM_NOMATCH; + ++c1; + } + + if (nrules == 0) + { + /* There are no names defined in the + collation data. Therefore we only + accept the trivial names consisting + of the character itself. */ + if (c1 != 1) + return FNM_NOMATCH; + + cend = startp[1]; + } + else + { + int32_t table_size; + const int32_t *symb_table; +# ifdef WIDE_CHAR_VERSION + char str[c1]; + size_t strcnt; +# else +# define str (startp + 1) +# endif + const unsigned char *extra; + int32_t idx; + int32_t elem; + int32_t second; + int32_t hash; + +# ifdef WIDE_CHAR_VERSION + /* We have to convert the name to a single-byte + string. This is possible since the names + consist of ASCII characters and the internal + representation is UCS4. */ + for (strcnt = 0; strcnt < c1; ++strcnt) + str[strcnt] = startp[1 + strcnt]; +# endif + + table_size = + _NL_CURRENT_WORD (LC_COLLATE, + _NL_COLLATE_SYMB_HASH_SIZEMB); + symb_table = (const int32_t *) + _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_SYMB_TABLEMB); + extra = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_SYMB_EXTRAMB); + + /* Locate the character in the hashing + table. */ + hash = elem_hash (str, c1); + + idx = 0; + elem = hash % table_size; + if (symb_table[2 * elem] != 0) + { + second = hash % (table_size - 2) + 1; + + do + { + /* First compare the hashing value. */ + if (symb_table[2 * elem] == hash + && (c1 + == extra[symb_table[2 * elem + 1]]) + && memcmp (str, + &extra[symb_table[2 * elem + 1] + + 1], c1) == 0) + { + /* Yep, this is the entry. */ + idx = symb_table[2 * elem + 1]; + idx += 1 + extra[idx]; + break; + } + + /* Next entry. */ + elem += second; + } + while (symb_table[2 * elem] != 0); + } + + if (symb_table[2 * elem] != 0) + { + /* Compare the byte sequence but only if + this is not part of a range. */ +# ifdef WIDE_CHAR_VERSION + int32_t *wextra; + + idx += 1 + extra[idx]; + /* Adjust for the alignment. */ + idx = (idx + 3) & ~4; + + wextra = (int32_t *) &extra[idx + 4]; +# endif + /* Get the collation sequence value. */ + is_seqval = true; +# ifdef WIDE_CHAR_VERSION + cend = wextra[1 + wextra[idx]]; +# else + /* Adjust for the alignment. */ + idx += 1 + extra[idx]; + idx = (idx + 3) & ~4; + cend = *((int32_t *) &extra[idx]); +# endif + } + else if (symb_table[2 * elem] != 0 && c1 == 1) + { + cend = str[0]; + c = *p++; + } + else + return FNM_NOMATCH; + } +# undef str + } + else + { + if (!(flags & FNM_NOESCAPE) && cend == L_('\\')) + cend = *p++; + if (cend == L_('\0')) + return FNM_NOMATCH; + cend = FOLD (cend); + } + + /* XXX It is not entirely clear to me how to handle + characters which are not mentioned in the + collation specification. */ + if ( +# ifdef WIDE_CHAR_VERSION + lcollseq == 0xffffffff || +# endif + lcollseq <= fcollseq) + { + /* We have to look at the upper bound. */ + uint32_t hcollseq; + + if (is_seqval) + hcollseq = cend; + else + { +# ifdef WIDE_CHAR_VERSION + hcollseq = + __collseq_table_lookup (collseq, cend); + if (hcollseq == ~((uint32_t) 0)) + { + /* Hum, no information about the upper + bound. The matching succeeds if the + lower bound is matched exactly. */ + if (lcollseq != fcollseq) + goto range_not_matched; + + goto matched; + } +# else + hcollseq = collseq[cend]; +# endif + } + + if (lcollseq <= hcollseq && fcollseq <= hcollseq) + goto matched; + } +# ifdef WIDE_CHAR_VERSION + range_not_matched: +# endif +#else + /* We use a boring value comparison of the character + values. This is better than comparing using + 'strcoll' since the latter would have surprising + and sometimes fatal consequences. */ + UCHAR cend = *p++; + + if (!(flags & FNM_NOESCAPE) && cend == L_('\\')) + cend = *p++; + if (cend == L_('\0')) + return FNM_NOMATCH; + + /* It is a range. */ + if (cold <= fn && fn <= cend) + goto matched; +#endif + + c = *p++; + } + } + + if (c == L_(']')) + break; + } + + if (!not) + return FNM_NOMATCH; + break; + + matched: + /* Skip the rest of the [...] that already matched. */ + do + { + ignore_next: + c = *p++; + + if (c == L_('\0')) + /* [... (unterminated) loses. */ + return FNM_NOMATCH; + + if (!(flags & FNM_NOESCAPE) && c == L_('\\')) + { + if (*p == L_('\0')) + return FNM_NOMATCH; + /* XXX 1003.2d11 is unclear if this is right. */ + ++p; + } + else if (c == L_('[') && *p == L_(':')) + { + int c1 = 0; + const CHAR *startp = p; + + while (1) + { + c = *++p; + if (++c1 == CHAR_CLASS_MAX_LENGTH) + return FNM_NOMATCH; + + if (*p == L_(':') && p[1] == L_(']')) + break; + + if (c < L_('a') || c >= L_('z')) + { + p = startp; + goto ignore_next; + } + } + p += 2; + c = *p++; + } + else if (c == L_('[') && *p == L_('=')) + { + c = *++p; + if (c == L_('\0')) + return FNM_NOMATCH; + c = *++p; + if (c != L_('=') || p[1] != L_(']')) + return FNM_NOMATCH; + p += 2; + c = *p++; + } + else if (c == L_('[') && *p == L_('.')) + { + ++p; + while (1) + { + c = *++p; + if (c == '\0') + return FNM_NOMATCH; + + if (*p == L_('.') && p[1] == L_(']')) + break; + } + p += 2; + c = *p++; + } + } + while (c != L_(']')); + if (not) + return FNM_NOMATCH; + } + break; + + case L_('+'): + case L_('@'): + case L_('!'): + if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(') + { + int res; + + res = EXT (c, p, n, string_end, no_leading_period, flags); + if (res != -1) + return res; + } + goto normal_match; + + case L_('/'): + if (NO_LEADING_PERIOD (flags)) + { + if (n == string_end || c != (UCHAR) *n) + return FNM_NOMATCH; + + new_no_leading_period = true; + break; + } + /* FALLTHROUGH */ + default: + normal_match: + if (n == string_end || c != FOLD ((UCHAR) *n)) + return FNM_NOMATCH; + } + + no_leading_period = new_no_leading_period; + ++n; + } + + if (n == string_end) + return 0; + + if ((flags & FNM_LEADING_DIR) && n != string_end && *n == L_('/')) + /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */ + return 0; + + return FNM_NOMATCH; +} + + +static const CHAR * +internal_function +END (const CHAR *pattern) +{ + const CHAR *p = pattern; + + while (1) + if (*++p == L_('\0')) + /* This is an invalid pattern. */ + return pattern; + else if (*p == L_('[')) + { + /* Handle brackets special. */ + if (posixly_correct == 0) + posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1; + + /* Skip the not sign. We have to recognize it because of a possibly + following ']'. */ + if (*++p == L_('!') || (posixly_correct < 0 && *p == L_('^'))) + ++p; + /* A leading ']' is recognized as such. */ + if (*p == L_(']')) + ++p; + /* Skip over all characters of the list. */ + while (*p != L_(']')) + if (*p++ == L_('\0')) + /* This is no valid pattern. */ + return pattern; + } + else if ((*p == L_('?') || *p == L_('*') || *p == L_('+') || *p == L_('@') + || *p == L_('!')) && p[1] == L_('(')) + p = END (p + 1); + else if (*p == L_(')')) + break; + + return p + 1; +} + + +static int +internal_function +EXT (INT opt, const CHAR *pattern, const CHAR *string, const CHAR *string_end, + bool no_leading_period, int flags) +{ + const CHAR *startp; + size_t level; + struct patternlist + { + struct patternlist *next; + int malloced; + CHAR str[1]; + } *list = NULL; + struct patternlist **lastp = &list; + size_t pattern_len = STRLEN (pattern); + const CHAR *p; + const CHAR *rs; +#if HAVE_ALLOCA || defined _LIBC + enum { ALLOCA_LIMIT = 8000 }; +#else + enum { ALLOCA_LIMIT = 0 }; +#endif + int retval; + + /* Parse the pattern. Store the individual parts in the list. */ + level = 0; + for (startp = p = pattern + 1; ; ++p) + if (*p == L_('\0')) + /* This is an invalid pattern. */ + goto failed; + else if (*p == L_('[')) + { + /* Handle brackets special. */ + if (posixly_correct == 0) + posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1; + + /* Skip the not sign. We have to recognize it because of a possibly + following ']'. */ + if (*++p == L_('!') || (posixly_correct < 0 && *p == L_('^'))) + ++p; + /* A leading ']' is recognized as such. */ + if (*p == L_(']')) + ++p; + /* Skip over all characters of the list. */ + while (*p != L_(']')) + if (*p++ == L_('\0')) + /* This is no valid pattern. */ + goto failed; + } + else if ((*p == L_('?') || *p == L_('*') || *p == L_('+') || *p == L_('@') + || *p == L_('!')) && p[1] == L_('(')) + /* Remember the nesting level. */ + ++level; + else if (*p == L_(')')) + { + if (level-- == 0) + { + /* This means we found the end of the pattern. */ +#define NEW_PATTERN \ + struct patternlist *newp; \ + size_t plen; \ + size_t plensize; \ + size_t newpsize; \ + \ + plen = (opt == L_('?') || opt == L_('@') \ + ? pattern_len \ + : p - startp + 1UL); \ + plensize = plen * sizeof (CHAR); \ + newpsize = offsetof (struct patternlist, str) + plensize; \ + if ((size_t) -1 / sizeof (CHAR) < plen \ + || newpsize < offsetof (struct patternlist, str)) \ + goto failed; \ + if (newpsize < ALLOCA_LIMIT) \ + { \ + newp = (struct patternlist *) alloca (newpsize); \ + newp->malloced = 0; \ + } \ + else \ + { \ + newp = (struct patternlist *) malloc (newpsize); \ + if (!newp) \ + goto failed; \ + newp->malloced = 1; \ + } \ + *((CHAR *) MEMPCPY (newp->str, startp, p - startp)) = L_('\0'); \ + newp->next = NULL; \ + *lastp = newp; \ + lastp = &newp->next + NEW_PATTERN; + break; + } + } + else if (*p == L_('|')) + { + if (level == 0) + { + NEW_PATTERN; + startp = p + 1; + } + } + assert (list != NULL); + assert (p[-1] == L_(')')); +#undef NEW_PATTERN + + switch (opt) + { + case L_('*'): + if (FCT (p, string, string_end, no_leading_period, flags) == 0) + { + retval = 0; + goto done; + } + /* FALLTHROUGH */ + + case L_('+'): + do + { + struct patternlist *next; + + for (rs = string; rs <= string_end; ++rs) + /* First match the prefix with the current pattern with the + current pattern. */ + if (FCT (list->str, string, rs, no_leading_period, + flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD) == 0 + /* This was successful. Now match the rest with the rest + of the pattern. */ + && (FCT (p, rs, string_end, + rs == string + ? no_leading_period + : rs[-1] == '/' && NO_LEADING_PERIOD (flags), + flags & FNM_FILE_NAME + ? flags : flags & ~FNM_PERIOD) == 0 + /* This didn't work. Try the whole pattern. */ + || (rs != string + && FCT (pattern - 1, rs, string_end, + rs == string + ? no_leading_period + : rs[-1] == '/' && NO_LEADING_PERIOD (flags), + flags & FNM_FILE_NAME + ? flags : flags & ~FNM_PERIOD) == 0))) + { + /* It worked. Signal success. */ + retval = 0; + goto done; + } + + next = list->next; + if (list->malloced) + free (list); + list = next; + } + while (list != NULL); + + /* None of the patterns lead to a match. */ + return FNM_NOMATCH; + + case L_('?'): + if (FCT (p, string, string_end, no_leading_period, flags) == 0) + { + retval = 0; + goto done; + } + /* FALLTHROUGH */ + + case L_('@'): + do + { + struct patternlist *next; + + /* I cannot believe it but 'strcat' is actually acceptable + here. Match the entire string with the prefix from the + pattern list and the rest of the pattern following the + pattern list. */ + if (FCT (STRCAT (list->str, p), string, string_end, + no_leading_period, + flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD) == 0) + { + /* It worked. Signal success. */ + retval = 0; + goto done; + } + + next = list->next; + if (list->malloced) + free (list); + list = next; + } + while (list != NULL); + + /* None of the patterns lead to a match. */ + return FNM_NOMATCH; + + case L_('!'): + for (rs = string; rs <= string_end; ++rs) + { + struct patternlist *runp; + + for (runp = list; runp != NULL; runp = runp->next) + if (FCT (runp->str, string, rs, no_leading_period, + flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD) == 0) + break; + + /* If none of the patterns matched see whether the rest does. */ + if (runp == NULL + && (FCT (p, rs, string_end, + rs == string + ? no_leading_period + : rs[-1] == '/' && NO_LEADING_PERIOD (flags), + flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD) + == 0)) + { + /* This is successful. */ + retval = 0; + goto done; + } + } + + /* None of the patterns together with the rest of the pattern + lead to a match. */ + retval = FNM_NOMATCH; + goto done; + + default: + assert (! "Invalid extended matching operator"); + break; + } + + failed: + retval = -1; + done: + while (list != NULL) + { + struct patternlist *next = list->next; + + if (list->malloced) + free (list); + list = next; + } + return retval; +} + + +#undef FOLD +#undef CHAR +#undef UCHAR +#undef INT +#undef FCT +#undef EXT +#undef END +#undef MEMPCPY +#undef MEMCHR +#undef STRLEN +#undef STRCAT +#undef L_ +#undef BTOWC diff --git a/gettext-tools/gnulib-lib/fopen.c b/gettext-tools/gnulib-lib/fopen.c new file mode 100644 index 0000000..8fead5a --- /dev/null +++ b/gettext-tools/gnulib-lib/fopen.c @@ -0,0 +1,110 @@ +/* Open a stream to a file. + Copyright (C) 2007-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Written by Bruno Haible , 2007. */ + +/* If the user's config.h happens to include , let it include only + the system's here, so that orig_fopen doesn't recurse to + rpl_fopen. */ +#define __need_FILE +#include + +/* Get the original definition of fopen. It might be defined as a macro. */ +#include +#undef __need_FILE + +static FILE * +orig_fopen (const char *filename, const char *mode) +{ + return fopen (filename, mode); +} + +/* Specification. */ +/* Write "stdio.h" here, not , otherwise OSF/1 5.1 DTK cc eliminates + this include because of the preliminary #include above. */ +#include "stdio.h" + +#include +#include +#include +#include +#include +#include + +FILE * +rpl_fopen (const char *filename, const char *mode) +{ +#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ + if (strcmp (filename, "/dev/null") == 0) + filename = "NUL"; +#endif + +#if FOPEN_TRAILING_SLASH_BUG + /* If the filename ends in a slash and a mode that requires write access is + specified, then fail. + Rationale: POSIX + says that + "A pathname that contains at least one non-slash character and that + ends with one or more trailing slashes shall be resolved as if a + single dot character ( '.' ) were appended to the pathname." + and + "The special filename dot shall refer to the directory specified by + its predecessor." + If the named file already exists as a directory, then if a mode that + requires write access is specified, fopen() must fail because POSIX + says that it + fails with errno = EISDIR in this case. + If the named file does not exist or does not name a directory, then + fopen() must fail since the file does not contain a '.' directory. */ + { + size_t len = strlen (filename); + if (len > 0 && filename[len - 1] == '/') + { + int fd; + struct stat statbuf; + FILE *fp; + + if (mode[0] == 'w' || mode[0] == 'a') + { + errno = EISDIR; + return NULL; + } + + fd = open (filename, O_RDONLY); + if (fd < 0) + return NULL; + + if (fstat (fd, &statbuf) >= 0 && !S_ISDIR (statbuf.st_mode)) + { + close (fd); + errno = ENOTDIR; + return NULL; + } + + fp = fdopen (fd, mode); + if (fp == NULL) + { + int saved_errno = errno; + close (fd); + errno = saved_errno; + } + return fp; + } + } +# endif + + return orig_fopen (filename, mode); +} diff --git a/gettext-tools/gnulib-lib/fstat.c b/gettext-tools/gnulib-lib/fstat.c new file mode 100644 index 0000000..ffcda9f --- /dev/null +++ b/gettext-tools/gnulib-lib/fstat.c @@ -0,0 +1,88 @@ +/* fstat() replacement. + Copyright (C) 2011-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* If the user's config.h happens to include , let it include only + the system's here, so that orig_fstat doesn't recurse to + rpl_fstat. */ +#define __need_system_sys_stat_h +#include + +/* Get the original definition of fstat. It might be defined as a macro. */ +#include +#include +#if _GL_WINDOWS_64_BIT_ST_SIZE +# undef stat /* avoid warning on mingw64 with _FILE_OFFSET_BITS=64 */ +# define stat _stati64 +# undef fstat /* avoid warning on mingw64 with _FILE_OFFSET_BITS=64 */ +# define fstat _fstati64 +#endif +#undef __need_system_sys_stat_h + +static int +orig_fstat (int fd, struct stat *buf) +{ + return fstat (fd, buf); +} + +/* Specification. */ +/* Write "sys/stat.h" here, not , otherwise OSF/1 5.1 DTK cc + eliminates this include because of the preliminary #include + above. */ +#include "sys/stat.h" + +#include +#include + +#if HAVE_MSVC_INVALID_PARAMETER_HANDLER +# include "msvc-inval.h" +#endif + +#if HAVE_MSVC_INVALID_PARAMETER_HANDLER +static int +fstat_nothrow (int fd, struct stat *buf) +{ + int result; + + TRY_MSVC_INVAL + { + result = orig_fstat (fd, buf); + } + CATCH_MSVC_INVAL + { + result = -1; + errno = EBADF; + } + DONE_MSVC_INVAL; + + return result; +} +#else +# define fstat_nothrow orig_fstat +#endif + +int +rpl_fstat (int fd, struct stat *buf) +{ +#if REPLACE_FCHDIR && REPLACE_OPEN_DIRECTORY + /* Handle the case when rpl_open() used a dummy file descriptor to work + around an open() that can't normally visit directories. */ + const char *name = _gl_directory_name (fd); + if (name != NULL) + return stat (name, buf); +#endif + + return fstat_nothrow (fd, buf); +} diff --git a/gettext-tools/gnulib-lib/fstrcmp.c b/gettext-tools/gnulib-lib/fstrcmp.c new file mode 100644 index 0000000..9c73904 --- /dev/null +++ b/gettext-tools/gnulib-lib/fstrcmp.c @@ -0,0 +1,237 @@ +/* Functions to make fuzzy comparisons between strings + Copyright (C) 1988-1989, 1992-1993, 1995, 2001-2003, 2006, 2008-2014 Free + Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + + +#include + +/* Specification. */ +#include "fstrcmp.h" + +#include +#include +#include +#include +#include + +#include "glthread/lock.h" +#include "glthread/tls.h" +#include "minmax.h" +#include "xalloc.h" + +#ifndef uintptr_t +# define uintptr_t unsigned long +#endif + + +#define ELEMENT char +#define EQUAL(x,y) ((x) == (y)) +#define OFFSET int +#define EXTRA_CONTEXT_FIELDS \ + /* The number of edits beyond which the computation can be aborted. */ \ + int edit_count_limit; \ + /* The number of edits (= number of elements inserted, plus the number of \ + elements deleted), temporarily minus edit_count_limit. */ \ + int edit_count; +#define NOTE_DELETE(ctxt, xoff) ctxt->edit_count++ +#define NOTE_INSERT(ctxt, yoff) ctxt->edit_count++ +#define EARLY_ABORT(ctxt) ctxt->edit_count > 0 +/* We don't need USE_HEURISTIC, since it is unlikely in typical uses of + fstrcmp(). */ +#include "diffseq.h" + + +/* Because fstrcmp is typically called multiple times, attempt to minimize + the number of memory allocations performed. Thus, let a call reuse the + memory already allocated by the previous call, if it is sufficient. + To make it multithread-safe, without need for a lock that protects the + already allocated memory, store the allocated memory per thread. Free + it only when the thread exits. */ + +static gl_tls_key_t buffer_key; /* TLS key for a 'int *' */ +static gl_tls_key_t bufmax_key; /* TLS key for a 'size_t' */ + +static void +keys_init (void) +{ + gl_tls_key_init (buffer_key, free); + gl_tls_key_init (bufmax_key, NULL); + /* The per-thread initial values are NULL and 0, respectively. */ +} + +/* Ensure that keys_init is called once only. */ +gl_once_define(static, keys_init_once) + + +/* In the code below, branch probabilities were measured by Ralf Wildenhues, + by running "msgmerge LL.po coreutils.pot" with msgmerge 0.18 for many + values of LL. The probability indicates that the condition evaluates + to true; whether that leads to a branch or a non-branch in the code, + depends on the compiler's reordering of basic blocks. */ + + +double +fstrcmp_bounded (const char *string1, const char *string2, double lower_bound) +{ + struct context ctxt; + int xvec_length = strlen (string1); + int yvec_length = strlen (string2); + int i; + + size_t fdiag_len; + int *buffer; + size_t bufmax; + + /* short-circuit obvious comparisons */ + if (xvec_length == 0 || yvec_length == 0) /* Prob: 1% */ + return (xvec_length == 0 && yvec_length == 0 ? 1.0 : 0.0); + + if (lower_bound > 0) + { + /* Compute a quick upper bound. + Each edit is an insertion or deletion of an element, hence modifies + the length of the sequence by at most 1. + Therefore, when starting from a sequence X and ending at a sequence Y, + with N edits, | yvec_length - xvec_length | <= N. (Proof by + induction over N.) + So, at the end, we will have + edit_count >= | xvec_length - yvec_length |. + and hence + result + = (xvec_length + yvec_length - edit_count) + / (xvec_length + yvec_length) + <= (xvec_length + yvec_length - | yvec_length - xvec_length |) + / (xvec_length + yvec_length) + = 2 * min (xvec_length, yvec_length) / (xvec_length + yvec_length). + */ + volatile double upper_bound = + (double) (2 * MIN (xvec_length, yvec_length)) + / (xvec_length + yvec_length); + + if (upper_bound < lower_bound) /* Prob: 74% */ + /* Return an arbitrary value < LOWER_BOUND. */ + return 0.0; + +#if CHAR_BIT <= 8 + /* When X and Y are both small, avoid the overhead of setting up an + array of size 256. */ + if (xvec_length + yvec_length >= 20) /* Prob: 99% */ + { + /* Compute a less quick upper bound. + Each edit is an insertion or deletion of a character, hence + modifies the occurrence count of a character by 1 and leaves the + other occurrence counts unchanged. + Therefore, when starting from a sequence X and ending at a + sequence Y, and denoting the occurrence count of C in X with + OCC (X, C), with N edits, + sum_C | OCC (X, C) - OCC (Y, C) | <= N. + (Proof by induction over N.) + So, at the end, we will have + edit_count >= sum_C | OCC (X, C) - OCC (Y, C) |, + and hence + result + = (xvec_length + yvec_length - edit_count) + / (xvec_length + yvec_length) + <= (xvec_length + yvec_length - sum_C | OCC(X,C) - OCC(Y,C) |) + / (xvec_length + yvec_length). + */ + int occ_diff[UCHAR_MAX + 1]; /* array C -> OCC(X,C) - OCC(Y,C) */ + int sum; + + /* Determine the occurrence counts in X. */ + memset (occ_diff, 0, sizeof (occ_diff)); + for (i = xvec_length - 1; i >= 0; i--) + occ_diff[(unsigned char) string1[i]]++; + /* Subtract the occurrence counts in Y. */ + for (i = yvec_length - 1; i >= 0; i--) + occ_diff[(unsigned char) string2[i]]--; + /* Sum up the absolute values. */ + sum = 0; + for (i = 0; i <= UCHAR_MAX; i++) + { + int d = occ_diff[i]; + sum += (d >= 0 ? d : -d); + } + + upper_bound = 1.0 - (double) sum / (xvec_length + yvec_length); + + if (upper_bound < lower_bound) /* Prob: 66% */ + /* Return an arbitrary value < LOWER_BOUND. */ + return 0.0; + } +#endif + } + + /* set the info for each string. */ + ctxt.xvec = string1; + ctxt.yvec = string2; + + /* Allocate memory for fdiag and bdiag from a thread-local pool. */ + fdiag_len = xvec_length + yvec_length + 3; + gl_once (keys_init_once, keys_init); + buffer = (int *) gl_tls_get (buffer_key); + bufmax = (size_t) (uintptr_t) gl_tls_get (bufmax_key); + if (fdiag_len > bufmax) + { + /* Need more memory. */ + bufmax = 2 * bufmax; + if (fdiag_len > bufmax) + bufmax = fdiag_len; + /* Calling xrealloc would be a waste: buffer's contents does not need + to be preserved. */ + if (buffer != NULL) + free (buffer); + buffer = (int *) xnmalloc (bufmax, 2 * sizeof (int)); + gl_tls_set (buffer_key, buffer); + gl_tls_set (bufmax_key, (void *) (uintptr_t) bufmax); + } + ctxt.fdiag = buffer + yvec_length + 1; + ctxt.bdiag = ctxt.fdiag + fdiag_len; + + /* The edit_count is only ever increased. The computation can be aborted + when + (xvec_length + yvec_length - edit_count) / (xvec_length + yvec_length) + < lower_bound, + or equivalently + edit_count > (xvec_length + yvec_length) * (1 - lower_bound) + or equivalently + edit_count > floor((xvec_length + yvec_length) * (1 - lower_bound)). + We need to add an epsilon inside the floor(...) argument, to neutralize + rounding errors. */ + ctxt.edit_count_limit = + (lower_bound < 1.0 + ? (int) ((xvec_length + yvec_length) * (1.0 - lower_bound + 0.000001)) + : 0); + + /* Now do the main comparison algorithm */ + ctxt.edit_count = - ctxt.edit_count_limit; + if (compareseq (0, xvec_length, 0, yvec_length, &ctxt)) /* Prob: 98% */ + /* The edit_count passed the limit. Hence the result would be + < lower_bound. We can return any value < lower_bound instead. */ + return 0.0; + ctxt.edit_count += ctxt.edit_count_limit; + + /* The result is + ((number of chars in common) / (average length of the strings)). + The numerator is + = xvec_length - (number of calls to NOTE_DELETE) + = yvec_length - (number of calls to NOTE_INSERT) + = 1/2 * (xvec_length + yvec_length - (number of edits)). + This is admittedly biased towards finding that the strings are + similar, however it does produce meaningful results. */ + return ((double) (xvec_length + yvec_length - ctxt.edit_count) + / (xvec_length + yvec_length)); +} diff --git a/gettext-tools/gnulib-lib/fstrcmp.h b/gettext-tools/gnulib-lib/fstrcmp.h new file mode 100644 index 0000000..e3d24fe --- /dev/null +++ b/gettext-tools/gnulib-lib/fstrcmp.h @@ -0,0 +1,45 @@ +/* Fuzzy string comparison. + Copyright (C) 1995, 2000, 2002-2003, 2006, 2008-2014 Free Software + Foundation, Inc. + + This file was written by Peter Miller + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . */ + +#ifndef _FSTRCMP_H +#define _FSTRCMP_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Fuzzy compare of S1 and S2. Return a measure for the similarity of S1 + and S1. The higher the result, the more similar the strings are. + The result is bounded between 0 (meaning very dissimilar strings) and + 1 (meaning identical strings). */ +extern double fstrcmp (const char *s1, const char *s2); + +/* Like fstrcmp (S1, S2), except that if the result is < LOWER_BOUND, an + arbitrary other value < LOWER_BOUND can be returned. */ +extern double fstrcmp_bounded (const char *s1, const char *s2, + double lower_bound); + +/* A shortcut for fstrcmp. Avoids a function call. */ +#define fstrcmp(s1,s2) fstrcmp_bounded (s1, s2, 0.0) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/gettext-tools/gnulib-lib/full-write.c b/gettext-tools/gnulib-lib/full-write.c new file mode 100644 index 0000000..b803677 --- /dev/null +++ b/gettext-tools/gnulib-lib/full-write.c @@ -0,0 +1,79 @@ +/* An interface to read and write that retries (if necessary) until complete. + + Copyright (C) 1993-1994, 1997-2006, 2009-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#ifdef FULL_READ +# include "full-read.h" +#else +# include "full-write.h" +#endif + +#include + +#ifdef FULL_READ +# include "safe-read.h" +# define safe_rw safe_read +# define full_rw full_read +# undef const +# define const /* empty */ +#else +# include "safe-write.h" +# define safe_rw safe_write +# define full_rw full_write +#endif + +#ifdef FULL_READ +/* Set errno to zero upon EOF. */ +# define ZERO_BYTE_TRANSFER_ERRNO 0 +#else +/* Some buggy drivers return 0 when one tries to write beyond + a device's end. (Example: Linux 1.2.13 on /dev/fd0.) + Set errno to ENOSPC so they get a sensible diagnostic. */ +# define ZERO_BYTE_TRANSFER_ERRNO ENOSPC +#endif + +/* Write(read) COUNT bytes at BUF to(from) descriptor FD, retrying if + interrupted or if a partial write(read) occurs. Return the number + of bytes transferred. + When writing, set errno if fewer than COUNT bytes are written. + When reading, if fewer than COUNT bytes are read, you must examine + errno to distinguish failure from EOF (errno == 0). */ +size_t +full_rw (int fd, const void *buf, size_t count) +{ + size_t total = 0; + const char *ptr = (const char *) buf; + + while (count > 0) + { + size_t n_rw = safe_rw (fd, ptr, count); + if (n_rw == (size_t) -1) + break; + if (n_rw == 0) + { + errno = ZERO_BYTE_TRANSFER_ERRNO; + break; + } + total += n_rw; + ptr += n_rw; + count -= n_rw; + } + + return total; +} diff --git a/gettext-tools/gnulib-lib/full-write.h b/gettext-tools/gnulib-lib/full-write.h new file mode 100644 index 0000000..589f6e1 --- /dev/null +++ b/gettext-tools/gnulib-lib/full-write.h @@ -0,0 +1,34 @@ +/* An interface to write() that writes all it is asked to write. + + Copyright (C) 2002-2003, 2009-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Write COUNT bytes at BUF to descriptor FD, retrying if interrupted + or if partial writes occur. Return the number of bytes successfully + written, setting errno if that is less than COUNT. */ +extern size_t full_write (int fd, const void *buf, size_t count); + + +#ifdef __cplusplus +} +#endif diff --git a/gettext-tools/gnulib-lib/fwriteerror.c b/gettext-tools/gnulib-lib/fwriteerror.c new file mode 100644 index 0000000..9d62e5c --- /dev/null +++ b/gettext-tools/gnulib-lib/fwriteerror.c @@ -0,0 +1,181 @@ +/* Detect write error on a stream. + Copyright (C) 2003-2006, 2008-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2003. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include "fwriteerror.h" + +#include +#include + +static int +do_fwriteerror (FILE *fp, bool ignore_ebadf) +{ + /* State to allow multiple calls to fwriteerror (stdout). */ + static bool stdout_closed = false; + + if (fp == stdout) + { + if (stdout_closed) + return 0; + + /* If we are closing stdout, don't attempt to do it later again. */ + stdout_closed = true; + } + + /* This function returns an error indication if there was a previous failure + or if fclose failed, with two exceptions: + - Ignore an fclose failure if there was no previous error, no data + remains to be flushed, and fclose failed with EBADF. That can + happen when a program like cp is invoked like this 'cp a b >&-' + (i.e., with standard output closed) and doesn't generate any + output (hence no previous error and nothing to be flushed). + - Ignore an fclose failure due to EPIPE. That can happen when a + program blocks or ignores SIGPIPE, and the output pipe or socket + has no readers now. The EPIPE tells us that we should stop writing + to this output. That's what we are doing anyway here. + + Need to + 1. test the error indicator of the stream, + 2. flush the buffers both in userland and in the kernel, through fclose, + testing for error again. */ + + /* Clear errno, so that on non-POSIX systems the caller doesn't see a + wrong value of errno when we return -1. */ + errno = 0; + + if (ferror (fp)) + { + if (fflush (fp)) + goto close_preserving_errno; /* errno is set here */ + /* The stream had an error earlier, but its errno was lost. If the + error was not temporary, we can get the same errno by writing and + flushing one more byte. We can do so because at this point the + stream's contents is garbage anyway. */ + if (fputc ('\0', fp) == EOF) + goto close_preserving_errno; /* errno is set here */ + if (fflush (fp)) + goto close_preserving_errno; /* errno is set here */ + /* Give up on errno. */ + errno = 0; + goto close_preserving_errno; + } + + if (ignore_ebadf) + { + /* We need an explicit fflush to tell whether some output was already + done on FP. */ + if (fflush (fp)) + goto close_preserving_errno; /* errno is set here */ + if (fclose (fp) && errno != EBADF) + goto got_errno; /* errno is set here */ + } + else + { + if (fclose (fp)) + goto got_errno; /* errno is set here */ + } + + return 0; + + close_preserving_errno: + /* There's an error. Nevertheless call fclose(fp), for consistency + with the other cases. */ + { + int saved_errno = errno; + fclose (fp); + errno = saved_errno; + } + got_errno: + /* There's an error. Ignore EPIPE. */ + if (errno == EPIPE) + return 0; + else + return -1; +} + +int +fwriteerror (FILE *fp) +{ + return do_fwriteerror (fp, false); +} + +int +fwriteerror_no_ebadf (FILE *fp) +{ + return do_fwriteerror (fp, true); +} + + +#if TEST + +/* Name of a file on which writing fails. On systems without /dev/full, + you can choose a filename on a full file system. */ +#define UNWRITABLE_FILE "/dev/full" + +int +main () +{ + static int sizes[] = + { + 511, 512, 513, + 1023, 1024, 1025, + 2047, 2048, 2049, + 4095, 4096, 4097, + 8191, 8192, 8193 + }; + static char dummy[8193]; + unsigned int i, j; + + for (i = 0; i < sizeof (sizes) / sizeof (sizes[0]); i++) + { + size_t size = sizes[i]; + + for (j = 0; j < 2; j++) + { + /* Run a test depending on i and j: + Write size bytes and then calls fflush if j==1. */ + FILE *stream = fopen (UNWRITABLE_FILE, "w"); + + if (stream == NULL) + { + fprintf (stderr, "Test %u:%u: could not open file\n", i, j); + continue; + } + + fwrite (dummy, 347, 1, stream); + fwrite (dummy, size - 347, 1, stream); + if (j) + fflush (stream); + + if (fwriteerror (stream) == -1) + { + if (errno != ENOSPC) + fprintf (stderr, "Test %u:%u: fwriteerror ok, errno = %d\n", + i, j, errno); + } + else + fprintf (stderr, "Test %u:%u: fwriteerror found no error!\n", + i, j); + } + } + + return 0; +} + +#endif diff --git a/gettext-tools/gnulib-lib/fwriteerror.h b/gettext-tools/gnulib-lib/fwriteerror.h new file mode 100644 index 0000000..6f7fedc --- /dev/null +++ b/gettext-tools/gnulib-lib/fwriteerror.h @@ -0,0 +1,62 @@ +/* Detect write error on a stream. + Copyright (C) 2003, 2005-2006, 2009-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2003. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* There are two approaches for detecting a write error on a stream opened + for writing: + + (a) Test the return value of every fwrite() or fprintf() call, and react + immediately. + (b) Just before fclose(), test the error indicator in the stream and + the return value of the final fclose() call. + + The benefit of (a) is that non file related errors (such that ENOMEM during + fprintf) and temporary error conditions can be diagnosed accurately. + + A theoretical benefit of (a) is also that, on POSIX systems, in the case of + an ENOSPC error, errno is set and can be used by error() to provide a more + accurate error message. But in practice, this benefit is not big because + users can easily figure out by themselves why a file cannot be written to, + and furthermore the function fwriteerror() can provide errno as well. + + The big drawback of (a) is extensive error checking code: Every function + which does stream output must return an error indicator. + + This file provides support for (b). */ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Write out the not yet written buffered contents of the stream FP, close + the stream FP, and test whether some error occurred on the stream FP. + FP must be a stream opened for writing. + Return 0 if no error occurred and fclose (fp) succeeded. + Return -1 and set errno if there was an error. The errno value will be 0 + if the cause of the error cannot be determined. + For any given stream FP other than stdout, fwriteerror (FP) may only be + called once. */ +extern int fwriteerror (FILE *fp); + +/* Likewise, but don't consider it an error if FP has an invalid file + descriptor and no output was done to FP. */ +extern int fwriteerror_no_ebadf (FILE *fp); + +#ifdef __cplusplus +} +#endif diff --git a/gettext-tools/gnulib-lib/gcd.c b/gettext-tools/gnulib-lib/gcd.c new file mode 100644 index 0000000..e61b62e --- /dev/null +++ b/gettext-tools/gnulib-lib/gcd.c @@ -0,0 +1,87 @@ +/* Arithmetic. + Copyright (C) 2001-2002, 2006, 2009-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2001. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* This file can also be used to define gcd functions for other unsigned + types, such as 'unsigned long long' or 'uintmax_t'. */ +#ifndef WORD_T +/* Specification. */ +# include "gcd.h" +# define WORD_T unsigned long +# define GCD gcd +#endif + +#include + +/* Return the greatest common divisor of a > 0 and b > 0. */ +WORD_T +GCD (WORD_T a, WORD_T b) +{ + /* Why no division, as in Euclid's algorithm? Because in Euclid's algorithm + the division result floor(a/b) or floor(b/a) is very often = 1 or = 2, + and nearly always < 8. A sequence of a few subtractions and tests is + faster than a division. */ + /* Why not Euclid's algorithm? Because the two integers can be shifted by 1 + bit in a single instruction, and the algorithm uses fewer variables than + Euclid's algorithm. */ + + WORD_T c = a | b; + c = c ^ (c - 1); + /* c = largest power of 2 that divides a and b. */ + + if (a & c) + { + if (b & c) + goto odd_odd; + else + goto odd_even; + } + else + { + if (b & c) + goto even_odd; + else + abort (); + } + + for (;;) + { + odd_odd: /* a/c and b/c both odd */ + if (a == b) + break; + if (a > b) + { + a = a - b; + even_odd: /* a/c even, b/c odd */ + do + a = a >> 1; + while ((a & c) == 0); + } + else + { + b = b - a; + odd_even: /* a/c odd, b/c even */ + do + b = b >> 1; + while ((b & c) == 0); + } + } + + /* a = b */ + return a; +} diff --git a/gettext-tools/gnulib-lib/gcd.h b/gettext-tools/gnulib-lib/gcd.h new file mode 100644 index 0000000..c356a66 --- /dev/null +++ b/gettext-tools/gnulib-lib/gcd.h @@ -0,0 +1,34 @@ +/* Arithmetic. + Copyright (C) 2001-2002, 2006, 2009-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2001. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _GCD_H +#define _GCD_H + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Return the greatest common divisor of a > 0 and b > 0. */ +extern unsigned long gcd (unsigned long a, unsigned long b); + + +#ifdef __cplusplus +} +#endif + +#endif /* _GCD_H */ diff --git a/gettext-tools/gnulib-lib/getdelim.c b/gettext-tools/gnulib-lib/getdelim.c new file mode 100644 index 0000000..e5714ba --- /dev/null +++ b/gettext-tools/gnulib-lib/getdelim.c @@ -0,0 +1,135 @@ +/* getdelim.c --- Implementation of replacement getdelim function. + Copyright (C) 1994, 1996-1998, 2001, 2003, 2005-2014 Free Software + Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 3, or (at + your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . */ + +/* Ported from glibc by Simon Josefsson. */ + +/* Don't use __attribute__ __nonnull__ in this compilation unit. Otherwise gcc + optimizes away the lineptr == NULL || n == NULL || fp == NULL tests below. */ +#define _GL_ARG_NONNULL(params) + +#include + +#include + +#include +#include +#include +#include + +#ifndef SSIZE_MAX +# define SSIZE_MAX ((ssize_t) (SIZE_MAX / 2)) +#endif + +#if USE_UNLOCKED_IO +# include "unlocked-io.h" +# define getc_maybe_unlocked(fp) getc(fp) +#elif !HAVE_FLOCKFILE || !HAVE_FUNLOCKFILE || !HAVE_DECL_GETC_UNLOCKED +# undef flockfile +# undef funlockfile +# define flockfile(x) ((void) 0) +# define funlockfile(x) ((void) 0) +# define getc_maybe_unlocked(fp) getc(fp) +#else +# define getc_maybe_unlocked(fp) getc_unlocked(fp) +#endif + +/* Read up to (and including) a DELIMITER from FP into *LINEPTR (and + NUL-terminate it). *LINEPTR is a pointer returned from malloc (or + NULL), pointing to *N characters of space. It is realloc'ed as + necessary. Returns the number of characters read (not including + the null terminator), or -1 on error or EOF. */ + +ssize_t +getdelim (char **lineptr, size_t *n, int delimiter, FILE *fp) +{ + ssize_t result; + size_t cur_len = 0; + + if (lineptr == NULL || n == NULL || fp == NULL) + { + errno = EINVAL; + return -1; + } + + flockfile (fp); + + if (*lineptr == NULL || *n == 0) + { + char *new_lineptr; + *n = 120; + new_lineptr = (char *) realloc (*lineptr, *n); + if (new_lineptr == NULL) + { + result = -1; + goto unlock_return; + } + *lineptr = new_lineptr; + } + + for (;;) + { + int i; + + i = getc_maybe_unlocked (fp); + if (i == EOF) + { + result = -1; + break; + } + + /* Make enough space for len+1 (for final NUL) bytes. */ + if (cur_len + 1 >= *n) + { + size_t needed_max = + SSIZE_MAX < SIZE_MAX ? (size_t) SSIZE_MAX + 1 : SIZE_MAX; + size_t needed = 2 * *n + 1; /* Be generous. */ + char *new_lineptr; + + if (needed_max < needed) + needed = needed_max; + if (cur_len + 1 >= needed) + { + result = -1; + errno = EOVERFLOW; + goto unlock_return; + } + + new_lineptr = (char *) realloc (*lineptr, needed); + if (new_lineptr == NULL) + { + result = -1; + goto unlock_return; + } + + *lineptr = new_lineptr; + *n = needed; + } + + (*lineptr)[cur_len] = i; + cur_len++; + + if (i == delimiter) + break; + } + (*lineptr)[cur_len] = '\0'; + result = cur_len ? cur_len : result; + + unlock_return: + funlockfile (fp); /* doesn't set errno */ + + return result; +} diff --git a/gettext-tools/gnulib-lib/getdtablesize.c b/gettext-tools/gnulib-lib/getdtablesize.c new file mode 100644 index 0000000..f0c6271 --- /dev/null +++ b/gettext-tools/gnulib-lib/getdtablesize.c @@ -0,0 +1,115 @@ +/* getdtablesize() function for platforms that don't have it. + Copyright (C) 2008-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2008. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include + +#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ + +# include + +# include "msvc-inval.h" + +# if HAVE_MSVC_INVALID_PARAMETER_HANDLER +static int +_setmaxstdio_nothrow (int newmax) +{ + int result; + + TRY_MSVC_INVAL + { + result = _setmaxstdio (newmax); + } + CATCH_MSVC_INVAL + { + result = -1; + } + DONE_MSVC_INVAL; + + return result; +} +# define _setmaxstdio _setmaxstdio_nothrow +# endif + +/* Cache for the previous getdtablesize () result. Safe to cache because + Windows also lacks setrlimit. */ +static int dtablesize; + +int +getdtablesize (void) +{ + if (dtablesize == 0) + { + /* We are looking for the number N such that the valid file descriptors + are 0..N-1. It can be obtained through a loop as follows: + { + int fd; + for (fd = 3; fd < 65536; fd++) + if (dup2 (0, fd) == -1) + break; + return fd; + } + On Windows XP, the result is 2048. + The drawback of this loop is that it allocates memory for a libc + internal array that is never freed. + + The number N can also be obtained as the upper bound for + _getmaxstdio (). _getmaxstdio () returns the maximum number of open + FILE objects. The sanity check in _setmaxstdio reveals the maximum + number of file descriptors. This too allocates memory, but it is + freed when we call _setmaxstdio with the original value. */ + int orig_max_stdio = _getmaxstdio (); + unsigned int bound; + for (bound = 0x10000; _setmaxstdio (bound) < 0; bound = bound / 2) + ; + _setmaxstdio (orig_max_stdio); + dtablesize = bound; + } + return dtablesize; +} + +#elif HAVE_GETDTABLESIZE + +# include +# undef getdtablesize + +int +rpl_getdtablesize(void) +{ + /* To date, this replacement is only compiled for Cygwin 1.7.25, + which auto-increased the RLIMIT_NOFILE soft limit until it + hits the compile-time constant hard limit of 3200. Although + that version of cygwin supported a child process inheriting + a smaller soft limit, the smaller limit is not enforced, so + we might as well just report the hard limit. */ + struct rlimit lim; + if (!getrlimit (RLIMIT_NOFILE, &lim) && lim.rlim_max != RLIM_INFINITY) + return lim.rlim_max; + return getdtablesize (); +} + +#elif defined _SC_OPEN_MAX + +int +getdtablesize (void) +{ + return sysconf (_SC_OPEN_MAX); +} + +#endif diff --git a/gettext-tools/gnulib-lib/getline.c b/gettext-tools/gnulib-lib/getline.c new file mode 100644 index 0000000..5282e80 --- /dev/null +++ b/gettext-tools/gnulib-lib/getline.c @@ -0,0 +1,27 @@ +/* getline.c --- Implementation of replacement getline function. + Copyright (C) 2005-2007, 2009-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 3, or (at + your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . */ + +/* Written by Simon Josefsson. */ + +#include + +#include + +ssize_t +getline (char **lineptr, size_t *n, FILE *stream) +{ + return getdelim (lineptr, n, '\n', stream); +} diff --git a/gettext-tools/gnulib-lib/getopt.c b/gettext-tools/gnulib-lib/getopt.c new file mode 100644 index 0000000..7d950af --- /dev/null +++ b/gettext-tools/gnulib-lib/getopt.c @@ -0,0 +1,1245 @@ +/* Getopt for GNU. + NOTE: getopt is part of the C library, so if you don't know what + "Keep this file name-space clean" means, talk to drepper@gnu.org + before changing it! + Copyright (C) 1987-1996, 1998-2004, 2006, 2008-2014 Free Software + Foundation, Inc. + This file is part of the GNU C Library. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _LIBC +# include +#endif + +#include "getopt.h" + +#include +#include +#include +#include + +#ifdef _LIBC +# include +#else +# include "gettext.h" +# define _(msgid) gettext (msgid) +#endif + +#if defined _LIBC && defined USE_IN_LIBIO +# include +#endif + +/* This version of 'getopt' appears to the caller like standard Unix 'getopt' + but it behaves differently for the user, since it allows the user + to intersperse the options with the other arguments. + + As 'getopt_long' works, it permutes the elements of ARGV so that, + when it is done, all the options precede everything else. Thus + all application programs are extended to handle flexible argument order. + + Using 'getopt' or setting the environment variable POSIXLY_CORRECT + disables permutation. + Then the behavior is completely standard. + + GNU application programs can use a third alternative mode in which + they can distinguish the relative order of options and other arguments. */ + +#include "getopt_int.h" + +/* For communication from 'getopt' to the caller. + When 'getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when 'ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +char *optarg; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to 'getopt'. + + On entry to 'getopt', zero means this is the first call; initialize. + + When 'getopt' returns -1, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, 'optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +/* 1003.2 says this must be 1 before any call. */ +int optind = 1; + +/* Callers store zero here to inhibit the error message + for unrecognized options. */ + +int opterr = 1; + +/* Set to an option character which was unrecognized. + This must be initialized on some systems to avoid linking in the + system's own getopt implementation. */ + +int optopt = '?'; + +/* Keep a global copy of all internal members of getopt_data. */ + +static struct _getopt_data getopt_data; + + +#if defined HAVE_DECL_GETENV && !HAVE_DECL_GETENV +extern char *getenv (); +#endif + +#ifdef _LIBC +/* Stored original parameters. + XXX This is no good solution. We should rather copy the args so + that we can compare them later. But we must not use malloc(3). */ +extern int __libc_argc; +extern char **__libc_argv; + +/* Bash 2.0 gives us an environment variable containing flags + indicating ARGV elements that should not be considered arguments. */ + +# ifdef USE_NONOPTION_FLAGS +/* Defined in getopt_init.c */ +extern char *__getopt_nonoption_flags; +# endif + +# ifdef USE_NONOPTION_FLAGS +# define SWAP_FLAGS(ch1, ch2) \ + if (d->__nonoption_flags_len > 0) \ + { \ + char __tmp = __getopt_nonoption_flags[ch1]; \ + __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \ + __getopt_nonoption_flags[ch2] = __tmp; \ + } +# else +# define SWAP_FLAGS(ch1, ch2) +# endif +#else /* !_LIBC */ +# define SWAP_FLAGS(ch1, ch2) +#endif /* _LIBC */ + +/* Exchange two adjacent subsequences of ARGV. + One subsequence is elements [first_nonopt,last_nonopt) + which contains all the non-options that have been skipped so far. + The other is elements [last_nonopt,optind), which contains all + the options processed since those non-options were skipped. + + 'first_nonopt' and 'last_nonopt' are relocated so that they describe + the new indices of the non-options in ARGV after they are moved. */ + +static void +exchange (char **argv, struct _getopt_data *d) +{ + int bottom = d->__first_nonopt; + int middle = d->__last_nonopt; + int top = d->optind; + char *tem; + + /* Exchange the shorter segment with the far end of the longer segment. + That puts the shorter segment into the right place. + It leaves the longer segment in the right place overall, + but it consists of two parts that need to be swapped next. */ + +#if defined _LIBC && defined USE_NONOPTION_FLAGS + /* First make sure the handling of the '__getopt_nonoption_flags' + string can work normally. Our top argument must be in the range + of the string. */ + if (d->__nonoption_flags_len > 0 && top >= d->__nonoption_flags_max_len) + { + /* We must extend the array. The user plays games with us and + presents new arguments. */ + char *new_str = malloc (top + 1); + if (new_str == NULL) + d->__nonoption_flags_len = d->__nonoption_flags_max_len = 0; + else + { + memset (__mempcpy (new_str, __getopt_nonoption_flags, + d->__nonoption_flags_max_len), + '\0', top + 1 - d->__nonoption_flags_max_len); + d->__nonoption_flags_max_len = top + 1; + __getopt_nonoption_flags = new_str; + } + } +#endif + + while (top > middle && middle > bottom) + { + if (top - middle > middle - bottom) + { + /* Bottom segment is the short one. */ + int len = middle - bottom; + register int i; + + /* Swap it with the top part of the top segment. */ + for (i = 0; i < len; i++) + { + tem = argv[bottom + i]; + argv[bottom + i] = argv[top - (middle - bottom) + i]; + argv[top - (middle - bottom) + i] = tem; + SWAP_FLAGS (bottom + i, top - (middle - bottom) + i); + } + /* Exclude the moved bottom segment from further swapping. */ + top -= len; + } + else + { + /* Top segment is the short one. */ + int len = top - middle; + register int i; + + /* Swap it with the bottom part of the bottom segment. */ + for (i = 0; i < len; i++) + { + tem = argv[bottom + i]; + argv[bottom + i] = argv[middle + i]; + argv[middle + i] = tem; + SWAP_FLAGS (bottom + i, middle + i); + } + /* Exclude the moved top segment from further swapping. */ + bottom += len; + } + } + + /* Update records for the slots the non-options now occupy. */ + + d->__first_nonopt += (d->optind - d->__last_nonopt); + d->__last_nonopt = d->optind; +} + +/* Initialize the internal data when the first call is made. */ + +static const char * +_getopt_initialize (int argc _GL_UNUSED, + char **argv _GL_UNUSED, const char *optstring, + struct _getopt_data *d, int posixly_correct) +{ + /* Start processing options with ARGV-element 1 (since ARGV-element 0 + is the program name); the sequence of previously skipped + non-option ARGV-elements is empty. */ + + d->__first_nonopt = d->__last_nonopt = d->optind; + + d->__nextchar = NULL; + + d->__posixly_correct = posixly_correct || !!getenv ("POSIXLY_CORRECT"); + + /* Determine how to handle the ordering of options and nonoptions. */ + + if (optstring[0] == '-') + { + d->__ordering = RETURN_IN_ORDER; + ++optstring; + } + else if (optstring[0] == '+') + { + d->__ordering = REQUIRE_ORDER; + ++optstring; + } + else if (d->__posixly_correct) + d->__ordering = REQUIRE_ORDER; + else + d->__ordering = PERMUTE; + +#if defined _LIBC && defined USE_NONOPTION_FLAGS + if (!d->__posixly_correct + && argc == __libc_argc && argv == __libc_argv) + { + if (d->__nonoption_flags_max_len == 0) + { + if (__getopt_nonoption_flags == NULL + || __getopt_nonoption_flags[0] == '\0') + d->__nonoption_flags_max_len = -1; + else + { + const char *orig_str = __getopt_nonoption_flags; + int len = d->__nonoption_flags_max_len = strlen (orig_str); + if (d->__nonoption_flags_max_len < argc) + d->__nonoption_flags_max_len = argc; + __getopt_nonoption_flags = + (char *) malloc (d->__nonoption_flags_max_len); + if (__getopt_nonoption_flags == NULL) + d->__nonoption_flags_max_len = -1; + else + memset (__mempcpy (__getopt_nonoption_flags, orig_str, len), + '\0', d->__nonoption_flags_max_len - len); + } + } + d->__nonoption_flags_len = d->__nonoption_flags_max_len; + } + else + d->__nonoption_flags_len = 0; +#endif + + return optstring; +} + +/* Scan elements of ARGV (whose length is ARGC) for option characters + given in OPTSTRING. + + If an element of ARGV starts with '-', and is not exactly "-" or "--", + then it is an option element. The characters of this element + (aside from the initial '-') are option characters. If 'getopt' + is called repeatedly, it returns successively each of the option characters + from each of the option elements. + + If 'getopt' finds another option character, it returns that character, + updating 'optind' and 'nextchar' so that the next call to 'getopt' can + resume the scan with the following option character or ARGV-element. + + If there are no more option characters, 'getopt' returns -1. + Then 'optind' is the index in ARGV of the first ARGV-element + that is not an option. (The ARGV-elements have been permuted + so that those that are not options now come last.) + + OPTSTRING is a string containing the legitimate option characters. + If an option character is seen that is not listed in OPTSTRING, + return '?' after printing an error message. If you set 'opterr' to + zero, the error message is suppressed but we still return '?'. + + If a char in OPTSTRING is followed by a colon, that means it wants an arg, + so the following text in the same ARGV-element, or the text of the following + ARGV-element, is returned in 'optarg'. Two colons mean an option that + wants an optional arg; if there is text in the current ARGV-element, + it is returned in 'optarg', otherwise 'optarg' is set to zero. + + If OPTSTRING starts with '-' or '+', it requests different methods of + handling the non-option ARGV-elements. + See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. + + Long-named options begin with '--' instead of '-'. + Their names may be abbreviated as long as the abbreviation is unique + or is an exact match for some defined option. If they have an + argument, it follows the option name in the same ARGV-element, separated + from the option name by a '=', or else the in next ARGV-element. + When 'getopt' finds a long-named option, it returns 0 if that option's + 'flag' field is nonzero, the value of the option's 'val' field + if the 'flag' field is zero. + + The elements of ARGV aren't really const, because we permute them. + But we pretend they're const in the prototype to be compatible + with other systems. + + LONGOPTS is a vector of 'struct option' terminated by an + element containing a name which is zero. + + LONGIND returns the index in LONGOPT of the long-named option found. + It is only valid when a long-named option has been found by the most + recent call. + + If LONG_ONLY is nonzero, '-' as well as '--' can introduce + long-named options. */ + +int +_getopt_internal_r (int argc, char **argv, const char *optstring, + const struct option *longopts, int *longind, + int long_only, struct _getopt_data *d, int posixly_correct) +{ + int print_errors = d->opterr; + + if (argc < 1) + return -1; + + d->optarg = NULL; + + if (d->optind == 0 || !d->__initialized) + { + if (d->optind == 0) + d->optind = 1; /* Don't scan ARGV[0], the program name. */ + optstring = _getopt_initialize (argc, argv, optstring, d, + posixly_correct); + d->__initialized = 1; + } + else if (optstring[0] == '-' || optstring[0] == '+') + optstring++; + if (optstring[0] == ':') + print_errors = 0; + + /* Test whether ARGV[optind] points to a non-option argument. + Either it does not have option syntax, or there is an environment flag + from the shell indicating it is not an option. The later information + is only used when the used in the GNU libc. */ +#if defined _LIBC && defined USE_NONOPTION_FLAGS +# define NONOPTION_P (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0' \ + || (d->optind < d->__nonoption_flags_len \ + && __getopt_nonoption_flags[d->optind] == '1')) +#else +# define NONOPTION_P (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0') +#endif + + if (d->__nextchar == NULL || *d->__nextchar == '\0') + { + /* Advance to the next ARGV-element. */ + + /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been + moved back by the user (who may also have changed the arguments). */ + if (d->__last_nonopt > d->optind) + d->__last_nonopt = d->optind; + if (d->__first_nonopt > d->optind) + d->__first_nonopt = d->optind; + + if (d->__ordering == PERMUTE) + { + /* If we have just processed some options following some non-options, + exchange them so that the options come first. */ + + if (d->__first_nonopt != d->__last_nonopt + && d->__last_nonopt != d->optind) + exchange ((char **) argv, d); + else if (d->__last_nonopt != d->optind) + d->__first_nonopt = d->optind; + + /* Skip any additional non-options + and extend the range of non-options previously skipped. */ + + while (d->optind < argc && NONOPTION_P) + d->optind++; + d->__last_nonopt = d->optind; + } + + /* The special ARGV-element '--' means premature end of options. + Skip it like a null option, + then exchange with previous non-options as if it were an option, + then skip everything else like a non-option. */ + + if (d->optind != argc && !strcmp (argv[d->optind], "--")) + { + d->optind++; + + if (d->__first_nonopt != d->__last_nonopt + && d->__last_nonopt != d->optind) + exchange ((char **) argv, d); + else if (d->__first_nonopt == d->__last_nonopt) + d->__first_nonopt = d->optind; + d->__last_nonopt = argc; + + d->optind = argc; + } + + /* If we have done all the ARGV-elements, stop the scan + and back over any non-options that we skipped and permuted. */ + + if (d->optind == argc) + { + /* Set the next-arg-index to point at the non-options + that we previously skipped, so the caller will digest them. */ + if (d->__first_nonopt != d->__last_nonopt) + d->optind = d->__first_nonopt; + return -1; + } + + /* If we have come to a non-option and did not permute it, + either stop the scan or describe it to the caller and pass it by. */ + + if (NONOPTION_P) + { + if (d->__ordering == REQUIRE_ORDER) + return -1; + d->optarg = argv[d->optind++]; + return 1; + } + + /* We have found another option-ARGV-element. + Skip the initial punctuation. */ + + d->__nextchar = (argv[d->optind] + 1 + + (longopts != NULL && argv[d->optind][1] == '-')); + } + + /* Decode the current option-ARGV-element. */ + + /* Check whether the ARGV-element is a long option. + + If long_only and the ARGV-element has the form "-f", where f is + a valid short option, don't consider it an abbreviated form of + a long option that starts with f. Otherwise there would be no + way to give the -f short option. + + On the other hand, if there's a long option "fubar" and + the ARGV-element is "-fu", do consider that an abbreviation of + the long option, just like "--fu", and not "-f" with arg "u". + + This distinction seems to be the most useful approach. */ + + if (longopts != NULL + && (argv[d->optind][1] == '-' + || (long_only && (argv[d->optind][2] + || !strchr (optstring, argv[d->optind][1]))))) + { + char *nameend; + unsigned int namelen; + const struct option *p; + const struct option *pfound = NULL; + struct option_list + { + const struct option *p; + struct option_list *next; + } *ambig_list = NULL; + int exact = 0; + int indfound = -1; + int option_index; + + for (nameend = d->__nextchar; *nameend && *nameend != '='; nameend++) + /* Do nothing. */ ; + namelen = nameend - d->__nextchar; + + /* Test all long options for either exact match + or abbreviated matches. */ + for (p = longopts, option_index = 0; p->name; p++, option_index++) + if (!strncmp (p->name, d->__nextchar, namelen)) + { + if (namelen == (unsigned int) strlen (p->name)) + { + /* Exact match found. */ + pfound = p; + indfound = option_index; + exact = 1; + break; + } + else if (pfound == NULL) + { + /* First nonexact match found. */ + pfound = p; + indfound = option_index; + } + else if (long_only + || pfound->has_arg != p->has_arg + || pfound->flag != p->flag + || pfound->val != p->val) + { + /* Second or later nonexact match found. */ + struct option_list *newp = malloc (sizeof (*newp)); + newp->p = p; + newp->next = ambig_list; + ambig_list = newp; + } + } + + if (ambig_list != NULL && !exact) + { + if (print_errors) + { + struct option_list first; + first.p = pfound; + first.next = ambig_list; + ambig_list = &first; + +#if defined _LIBC && defined USE_IN_LIBIO + char *buf = NULL; + size_t buflen = 0; + + FILE *fp = open_memstream (&buf, &buflen); + if (fp != NULL) + { + fprintf (fp, + _("%s: option '%s' is ambiguous; possibilities:"), + argv[0], argv[d->optind]); + + do + { + fprintf (fp, " '--%s'", ambig_list->p->name); + ambig_list = ambig_list->next; + } + while (ambig_list != NULL); + + fputc_unlocked ('\n', fp); + + if (__builtin_expect (fclose (fp) != EOF, 1)) + { + _IO_flockfile (stderr); + + int old_flags2 = ((_IO_FILE *) stderr)->_flags2; + ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; + + __fxprintf (NULL, "%s", buf); + + ((_IO_FILE *) stderr)->_flags2 = old_flags2; + _IO_funlockfile (stderr); + + free (buf); + } + } +#else + fprintf (stderr, + _("%s: option '%s' is ambiguous; possibilities:"), + argv[0], argv[d->optind]); + do + { + fprintf (stderr, " '--%s'", ambig_list->p->name); + ambig_list = ambig_list->next; + } + while (ambig_list != NULL); + + fputc ('\n', stderr); +#endif + } + d->__nextchar += strlen (d->__nextchar); + d->optind++; + d->optopt = 0; + return '?'; + } + + while (ambig_list != NULL) + { + struct option_list *pn = ambig_list->next; + free (ambig_list); + ambig_list = pn; + } + + if (pfound != NULL) + { + option_index = indfound; + d->optind++; + if (*nameend) + { + /* Don't test has_arg with >, because some C compilers don't + allow it to be used on enums. */ + if (pfound->has_arg) + d->optarg = nameend + 1; + else + { + if (print_errors) + { +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + int n; +#endif + + if (argv[d->optind - 1][1] == '-') + { + /* --option */ +#if defined _LIBC && defined USE_IN_LIBIO + n = __asprintf (&buf, _("\ +%s: option '--%s' doesn't allow an argument\n"), + argv[0], pfound->name); +#else + fprintf (stderr, _("\ +%s: option '--%s' doesn't allow an argument\n"), + argv[0], pfound->name); +#endif + } + else + { + /* +option or -option */ +#if defined _LIBC && defined USE_IN_LIBIO + n = __asprintf (&buf, _("\ +%s: option '%c%s' doesn't allow an argument\n"), + argv[0], argv[d->optind - 1][0], + pfound->name); +#else + fprintf (stderr, _("\ +%s: option '%c%s' doesn't allow an argument\n"), + argv[0], argv[d->optind - 1][0], + pfound->name); +#endif + } + +#if defined _LIBC && defined USE_IN_LIBIO + if (n >= 0) + { + _IO_flockfile (stderr); + + int old_flags2 = ((_IO_FILE *) stderr)->_flags2; + ((_IO_FILE *) stderr)->_flags2 + |= _IO_FLAGS2_NOTCANCEL; + + __fxprintf (NULL, "%s", buf); + + ((_IO_FILE *) stderr)->_flags2 = old_flags2; + _IO_funlockfile (stderr); + + free (buf); + } +#endif + } + + d->__nextchar += strlen (d->__nextchar); + + d->optopt = pfound->val; + return '?'; + } + } + else if (pfound->has_arg == 1) + { + if (d->optind < argc) + d->optarg = argv[d->optind++]; + else + { + if (print_errors) + { +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + + if (__asprintf (&buf, _("\ +%s: option '--%s' requires an argument\n"), + argv[0], pfound->name) >= 0) + { + _IO_flockfile (stderr); + + int old_flags2 = ((_IO_FILE *) stderr)->_flags2; + ((_IO_FILE *) stderr)->_flags2 + |= _IO_FLAGS2_NOTCANCEL; + + __fxprintf (NULL, "%s", buf); + + ((_IO_FILE *) stderr)->_flags2 = old_flags2; + _IO_funlockfile (stderr); + + free (buf); + } +#else + fprintf (stderr, + _("%s: option '--%s' requires an argument\n"), + argv[0], pfound->name); +#endif + } + d->__nextchar += strlen (d->__nextchar); + d->optopt = pfound->val; + return optstring[0] == ':' ? ':' : '?'; + } + } + d->__nextchar += strlen (d->__nextchar); + if (longind != NULL) + *longind = option_index; + if (pfound->flag) + { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; + } + + /* Can't find it as a long option. If this is not getopt_long_only, + or the option starts with '--' or is not a valid short + option, then it's an error. + Otherwise interpret it as a short option. */ + if (!long_only || argv[d->optind][1] == '-' + || strchr (optstring, *d->__nextchar) == NULL) + { + if (print_errors) + { +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + int n; +#endif + + if (argv[d->optind][1] == '-') + { + /* --option */ +#if defined _LIBC && defined USE_IN_LIBIO + n = __asprintf (&buf, _("%s: unrecognized option '--%s'\n"), + argv[0], d->__nextchar); +#else + fprintf (stderr, _("%s: unrecognized option '--%s'\n"), + argv[0], d->__nextchar); +#endif + } + else + { + /* +option or -option */ +#if defined _LIBC && defined USE_IN_LIBIO + n = __asprintf (&buf, _("%s: unrecognized option '%c%s'\n"), + argv[0], argv[d->optind][0], d->__nextchar); +#else + fprintf (stderr, _("%s: unrecognized option '%c%s'\n"), + argv[0], argv[d->optind][0], d->__nextchar); +#endif + } + +#if defined _LIBC && defined USE_IN_LIBIO + if (n >= 0) + { + _IO_flockfile (stderr); + + int old_flags2 = ((_IO_FILE *) stderr)->_flags2; + ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; + + __fxprintf (NULL, "%s", buf); + + ((_IO_FILE *) stderr)->_flags2 = old_flags2; + _IO_funlockfile (stderr); + + free (buf); + } +#endif + } + d->__nextchar = (char *) ""; + d->optind++; + d->optopt = 0; + return '?'; + } + } + + /* Look at and handle the next short option-character. */ + + { + char c = *d->__nextchar++; + const char *temp = strchr (optstring, c); + + /* Increment 'optind' when we start to process its last character. */ + if (*d->__nextchar == '\0') + ++d->optind; + + if (temp == NULL || c == ':' || c == ';') + { + if (print_errors) + { +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + int n; +#endif + +#if defined _LIBC && defined USE_IN_LIBIO + n = __asprintf (&buf, _("%s: invalid option -- '%c'\n"), + argv[0], c); +#else + fprintf (stderr, _("%s: invalid option -- '%c'\n"), argv[0], c); +#endif + +#if defined _LIBC && defined USE_IN_LIBIO + if (n >= 0) + { + _IO_flockfile (stderr); + + int old_flags2 = ((_IO_FILE *) stderr)->_flags2; + ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; + + __fxprintf (NULL, "%s", buf); + + ((_IO_FILE *) stderr)->_flags2 = old_flags2; + _IO_funlockfile (stderr); + + free (buf); + } +#endif + } + d->optopt = c; + return '?'; + } + /* Convenience. Treat POSIX -W foo same as long option --foo */ + if (temp[0] == 'W' && temp[1] == ';') + { + char *nameend; + const struct option *p; + const struct option *pfound = NULL; + int exact = 0; + int ambig = 0; + int indfound = 0; + int option_index; + + if (longopts == NULL) + goto no_longs; + + /* This is an option that requires an argument. */ + if (*d->__nextchar != '\0') + { + d->optarg = d->__nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + d->optind++; + } + else if (d->optind == argc) + { + if (print_errors) + { +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + + if (__asprintf (&buf, + _("%s: option requires an argument -- '%c'\n"), + argv[0], c) >= 0) + { + _IO_flockfile (stderr); + + int old_flags2 = ((_IO_FILE *) stderr)->_flags2; + ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; + + __fxprintf (NULL, "%s", buf); + + ((_IO_FILE *) stderr)->_flags2 = old_flags2; + _IO_funlockfile (stderr); + + free (buf); + } +#else + fprintf (stderr, + _("%s: option requires an argument -- '%c'\n"), + argv[0], c); +#endif + } + d->optopt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + return c; + } + else + /* We already incremented 'd->optind' once; + increment it again when taking next ARGV-elt as argument. */ + d->optarg = argv[d->optind++]; + + /* optarg is now the argument, see if it's in the + table of longopts. */ + + for (d->__nextchar = nameend = d->optarg; *nameend && *nameend != '='; + nameend++) + /* Do nothing. */ ; + + /* Test all long options for either exact match + or abbreviated matches. */ + for (p = longopts, option_index = 0; p->name; p++, option_index++) + if (!strncmp (p->name, d->__nextchar, nameend - d->__nextchar)) + { + if ((unsigned int) (nameend - d->__nextchar) == strlen (p->name)) + { + /* Exact match found. */ + pfound = p; + indfound = option_index; + exact = 1; + break; + } + else if (pfound == NULL) + { + /* First nonexact match found. */ + pfound = p; + indfound = option_index; + } + else if (long_only + || pfound->has_arg != p->has_arg + || pfound->flag != p->flag + || pfound->val != p->val) + /* Second or later nonexact match found. */ + ambig = 1; + } + if (ambig && !exact) + { + if (print_errors) + { +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + + if (__asprintf (&buf, _("%s: option '-W %s' is ambiguous\n"), + argv[0], d->optarg) >= 0) + { + _IO_flockfile (stderr); + + int old_flags2 = ((_IO_FILE *) stderr)->_flags2; + ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; + + __fxprintf (NULL, "%s", buf); + + ((_IO_FILE *) stderr)->_flags2 = old_flags2; + _IO_funlockfile (stderr); + + free (buf); + } +#else + fprintf (stderr, _("%s: option '-W %s' is ambiguous\n"), + argv[0], d->optarg); +#endif + } + d->__nextchar += strlen (d->__nextchar); + d->optind++; + return '?'; + } + if (pfound != NULL) + { + option_index = indfound; + if (*nameend) + { + /* Don't test has_arg with >, because some C compilers don't + allow it to be used on enums. */ + if (pfound->has_arg) + d->optarg = nameend + 1; + else + { + if (print_errors) + { +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + + if (__asprintf (&buf, _("\ +%s: option '-W %s' doesn't allow an argument\n"), + argv[0], pfound->name) >= 0) + { + _IO_flockfile (stderr); + + int old_flags2 = ((_IO_FILE *) stderr)->_flags2; + ((_IO_FILE *) stderr)->_flags2 + |= _IO_FLAGS2_NOTCANCEL; + + __fxprintf (NULL, "%s", buf); + + ((_IO_FILE *) stderr)->_flags2 = old_flags2; + _IO_funlockfile (stderr); + + free (buf); + } +#else + fprintf (stderr, _("\ +%s: option '-W %s' doesn't allow an argument\n"), + argv[0], pfound->name); +#endif + } + + d->__nextchar += strlen (d->__nextchar); + return '?'; + } + } + else if (pfound->has_arg == 1) + { + if (d->optind < argc) + d->optarg = argv[d->optind++]; + else + { + if (print_errors) + { +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + + if (__asprintf (&buf, _("\ +%s: option '-W %s' requires an argument\n"), + argv[0], pfound->name) >= 0) + { + _IO_flockfile (stderr); + + int old_flags2 = ((_IO_FILE *) stderr)->_flags2; + ((_IO_FILE *) stderr)->_flags2 + |= _IO_FLAGS2_NOTCANCEL; + + __fxprintf (NULL, "%s", buf); + + ((_IO_FILE *) stderr)->_flags2 = old_flags2; + _IO_funlockfile (stderr); + + free (buf); + } +#else + fprintf (stderr, _("\ +%s: option '-W %s' requires an argument\n"), + argv[0], pfound->name); +#endif + } + d->__nextchar += strlen (d->__nextchar); + return optstring[0] == ':' ? ':' : '?'; + } + } + else + d->optarg = NULL; + d->__nextchar += strlen (d->__nextchar); + if (longind != NULL) + *longind = option_index; + if (pfound->flag) + { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; + } + + no_longs: + d->__nextchar = NULL; + return 'W'; /* Let the application handle it. */ + } + if (temp[1] == ':') + { + if (temp[2] == ':') + { + /* This is an option that accepts an argument optionally. */ + if (*d->__nextchar != '\0') + { + d->optarg = d->__nextchar; + d->optind++; + } + else + d->optarg = NULL; + d->__nextchar = NULL; + } + else + { + /* This is an option that requires an argument. */ + if (*d->__nextchar != '\0') + { + d->optarg = d->__nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + d->optind++; + } + else if (d->optind == argc) + { + if (print_errors) + { +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + + if (__asprintf (&buf, _("\ +%s: option requires an argument -- '%c'\n"), + argv[0], c) >= 0) + { + _IO_flockfile (stderr); + + int old_flags2 = ((_IO_FILE *) stderr)->_flags2; + ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; + + __fxprintf (NULL, "%s", buf); + + ((_IO_FILE *) stderr)->_flags2 = old_flags2; + _IO_funlockfile (stderr); + + free (buf); + } +#else + fprintf (stderr, + _("%s: option requires an argument -- '%c'\n"), + argv[0], c); +#endif + } + d->optopt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + } + else + /* We already incremented 'optind' once; + increment it again when taking next ARGV-elt as argument. */ + d->optarg = argv[d->optind++]; + d->__nextchar = NULL; + } + } + return c; + } +} + +int +_getopt_internal (int argc, char **argv, const char *optstring, + const struct option *longopts, int *longind, int long_only, + int posixly_correct) +{ + int result; + + getopt_data.optind = optind; + getopt_data.opterr = opterr; + + result = _getopt_internal_r (argc, argv, optstring, longopts, + longind, long_only, &getopt_data, + posixly_correct); + + optind = getopt_data.optind; + optarg = getopt_data.optarg; + optopt = getopt_data.optopt; + + return result; +} + +/* glibc gets a LSB-compliant getopt. + Standalone applications get a POSIX-compliant getopt. */ +#if _LIBC +enum { POSIXLY_CORRECT = 0 }; +#else +enum { POSIXLY_CORRECT = 1 }; +#endif + +int +getopt (int argc, char *const *argv, const char *optstring) +{ + return _getopt_internal (argc, (char **) argv, optstring, + (const struct option *) 0, + (int *) 0, + 0, POSIXLY_CORRECT); +} + +#ifdef _LIBC +int +__posix_getopt (int argc, char *const *argv, const char *optstring) +{ + return _getopt_internal (argc, argv, optstring, + (const struct option *) 0, + (int *) 0, + 0, 1); +} +#endif + + +#ifdef TEST + +/* Compile with -DTEST to make an executable for use in testing + the above definition of 'getopt'. */ + +int +main (int argc, char **argv) +{ + int c; + int digit_optind = 0; + + while (1) + { + int this_option_optind = optind ? optind : 1; + + c = getopt (argc, argv, "abc:d:0123456789"); + if (c == -1) + break; + + switch (c) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (digit_optind != 0 && digit_optind != this_option_optind) + printf ("digits occur in two different argv-elements.\n"); + digit_optind = this_option_optind; + printf ("option %c\n", c); + break; + + case 'a': + printf ("option a\n"); + break; + + case 'b': + printf ("option b\n"); + break; + + case 'c': + printf ("option c with value '%s'\n", optarg); + break; + + case '?': + break; + + default: + printf ("?? getopt returned character code 0%o ??\n", c); + } + } + + if (optind < argc) + { + printf ("non-option ARGV-elements: "); + while (optind < argc) + printf ("%s ", argv[optind++]); + printf ("\n"); + } + + exit (0); +} + +#endif /* TEST */ diff --git a/gettext-tools/gnulib-lib/getopt.in.h b/gettext-tools/gnulib-lib/getopt.in.h new file mode 100644 index 0000000..c74c812 --- /dev/null +++ b/gettext-tools/gnulib-lib/getopt.in.h @@ -0,0 +1,263 @@ +/* Declarations for getopt. + Copyright (C) 1989-1994, 1996-1999, 2001, 2003-2007, 2009-2014 Free Software + Foundation, Inc. + This file is part of the GNU C Library. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _@GUARD_PREFIX@_GETOPT_H + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +/* The include_next requires a split double-inclusion guard. We must + also inform the replacement unistd.h to not recursively use + ; our definitions will be present soon enough. */ +#if @HAVE_GETOPT_H@ +# define _GL_SYSTEM_GETOPT +# @INCLUDE_NEXT@ @NEXT_GETOPT_H@ +# undef _GL_SYSTEM_GETOPT +#endif + +#ifndef _@GUARD_PREFIX@_GETOPT_H + +#ifndef __need_getopt +# define _@GUARD_PREFIX@_GETOPT_H 1 +#endif + +/* Ensure that DLL_VARIABLE is defined. Since on OSF/1 4.0 and Irix 6.5 + includes , and is not a prerequisite for + using , this file can be included without a prior + "#include ". */ +#ifdef HAVE_CONFIG_H +# include +#endif + +/* Standalone applications should #define __GETOPT_PREFIX to an + identifier that prefixes the external functions and variables + defined in this header. When this happens, include the + headers that might declare getopt so that they will not cause + confusion if included after this file (if the system had , + we have already included it). Then systematically rename + identifiers so that they do not collide with the system functions + and variables. Renaming avoids problems with some compilers and + linkers. */ +#if defined __GETOPT_PREFIX && !defined __need_getopt +# if !@HAVE_GETOPT_H@ +# define __need_system_stdlib_h +# include +# undef __need_system_stdlib_h +# include +# include +# endif +# undef __need_getopt +# undef getopt +# undef getopt_long +# undef getopt_long_only +# undef optarg +# undef opterr +# undef optind +# undef optopt +# undef option +# define __GETOPT_CONCAT(x, y) x ## y +# define __GETOPT_XCONCAT(x, y) __GETOPT_CONCAT (x, y) +# define __GETOPT_ID(y) __GETOPT_XCONCAT (__GETOPT_PREFIX, y) +# define getopt __GETOPT_ID (getopt) +# define getopt_long __GETOPT_ID (getopt_long) +# define getopt_long_only __GETOPT_ID (getopt_long_only) +# define optarg __GETOPT_ID (optarg) +# define opterr __GETOPT_ID (opterr) +# define optind __GETOPT_ID (optind) +# define optopt __GETOPT_ID (optopt) +# define option __GETOPT_ID (option) +# define _getopt_internal __GETOPT_ID (getopt_internal) +#endif + +/* Standalone applications get correct prototypes for getopt_long and + getopt_long_only; they declare "char **argv". libc uses prototypes + with "char *const *argv" that are incorrect because getopt_long and + getopt_long_only can permute argv; this is required for backward + compatibility (e.g., for LSB 2.0.1). + + This used to be '#if defined __GETOPT_PREFIX && !defined __need_getopt', + but it caused redefinition warnings if both unistd.h and getopt.h were + included, since unistd.h includes getopt.h having previously defined + __need_getopt. + + The only place where __getopt_argv_const is used is in definitions + of getopt_long and getopt_long_only below, but these are visible + only if __need_getopt is not defined, so it is quite safe to rewrite + the conditional as follows: +*/ +#if !defined __need_getopt +# if defined __GETOPT_PREFIX +# define __getopt_argv_const /* empty */ +# else +# define __getopt_argv_const const +# endif +#endif + +/* If __GNU_LIBRARY__ is not already defined, either we are being used + standalone, or this is the first header included in the source file. + If we are being used with glibc, we need to include , but + that does not exist if we are standalone. So: if __GNU_LIBRARY__ is + not defined, include , which will pull in for us + if it's from glibc. (Why ctype.h? It's guaranteed to exist and it + doesn't flood the namespace with stuff the way some other headers do.) */ +#if !defined __GNU_LIBRARY__ +# include +#endif + +#ifndef __THROW +# ifndef __GNUC_PREREQ +# define __GNUC_PREREQ(maj, min) (0) +# endif +# if defined __cplusplus && __GNUC_PREREQ (2,8) +# define __THROW throw () +# else +# define __THROW +# endif +#endif + +/* The definition of _GL_ARG_NONNULL is copied here. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* For communication from 'getopt' to the caller. + When 'getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when 'ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +extern DLL_VARIABLE char *optarg; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to 'getopt'. + + On entry to 'getopt', zero means this is the first call; initialize. + + When 'getopt' returns -1, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, 'optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +extern DLL_VARIABLE int optind; + +/* Callers store zero here to inhibit the error message 'getopt' prints + for unrecognized options. */ + +extern DLL_VARIABLE int opterr; + +/* Set to an option character which was unrecognized. */ + +extern DLL_VARIABLE int optopt; + +#ifndef __need_getopt +/* Describe the long-named options requested by the application. + The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector + of 'struct option' terminated by an element containing a name which is + zero. + + The field 'has_arg' is: + no_argument (or 0) if the option does not take an argument, + required_argument (or 1) if the option requires an argument, + optional_argument (or 2) if the option takes an optional argument. + + If the field 'flag' is not NULL, it points to a variable that is set + to the value given in the field 'val' when the option is found, but + left unchanged if the option is not found. + + To have a long-named option do something other than set an 'int' to + a compiled-in constant, such as set a value from 'optarg', set the + option's 'flag' field to zero and its 'val' field to a nonzero + value (the equivalent single-letter option character, if there is + one). For long options that have a zero 'flag' field, 'getopt' + returns the contents of the 'val' field. */ + +# if !GNULIB_defined_struct_option +struct option +{ + const char *name; + /* has_arg can't be an enum because some compilers complain about + type mismatches in all the code that assumes it is an int. */ + int has_arg; + int *flag; + int val; +}; +# define GNULIB_defined_struct_option 1 +# endif + +/* Names for the values of the 'has_arg' field of 'struct option'. */ + +# define no_argument 0 +# define required_argument 1 +# define optional_argument 2 +#endif /* need getopt */ + + +/* Get definitions and prototypes for functions to process the + arguments in ARGV (ARGC of them, minus the program name) for + options given in OPTS. + + Return the option character from OPTS just read. Return -1 when + there are no more options. For unrecognized options, or options + missing arguments, 'optopt' is set to the option letter, and '?' is + returned. + + The OPTS string is a list of characters which are recognized option + letters, optionally followed by colons, specifying that that letter + takes an argument, to be placed in 'optarg'. + + If a letter in OPTS is followed by two colons, its argument is + optional. This behavior is specific to the GNU 'getopt'. + + The argument '--' causes premature termination of argument + scanning, explicitly telling 'getopt' that there are no more + options. + + If OPTS begins with '-', then non-option arguments are treated as + arguments to the option '\1'. This behavior is specific to the GNU + 'getopt'. If OPTS begins with '+', or POSIXLY_CORRECT is set in + the environment, then do not permute arguments. */ + +extern int getopt (int ___argc, char *const *___argv, const char *__shortopts) + __THROW _GL_ARG_NONNULL ((2, 3)); + +#ifndef __need_getopt +extern int getopt_long (int ___argc, char *__getopt_argv_const *___argv, + const char *__shortopts, + const struct option *__longopts, int *__longind) + __THROW _GL_ARG_NONNULL ((2, 3)); +extern int getopt_long_only (int ___argc, char *__getopt_argv_const *___argv, + const char *__shortopts, + const struct option *__longopts, int *__longind) + __THROW _GL_ARG_NONNULL ((2, 3)); + +#endif + +#ifdef __cplusplus +} +#endif + +/* Make sure we later can get all the definitions and declarations. */ +#undef __need_getopt + +#endif /* _@GUARD_PREFIX@_GETOPT_H */ +#endif /* _@GUARD_PREFIX@_GETOPT_H */ diff --git a/gettext-tools/gnulib-lib/getopt1.c b/gettext-tools/gnulib-lib/getopt1.c new file mode 100644 index 0000000..a184865 --- /dev/null +++ b/gettext-tools/gnulib-lib/getopt1.c @@ -0,0 +1,170 @@ +/* getopt_long and getopt_long_only entry points for GNU getopt. + Copyright (C) 1987-1994, 1996-1998, 2004, 2006, 2009-2014 Free Software + Foundation, Inc. + This file is part of the GNU C Library. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifdef _LIBC +# include +#else +# include +# include "getopt.h" +#endif +#include "getopt_int.h" + +#include + +/* This needs to come after some library #include + to get __GNU_LIBRARY__ defined. */ +#ifdef __GNU_LIBRARY__ +#include +#endif + +#ifndef NULL +#define NULL 0 +#endif + +int +getopt_long (int argc, char *__getopt_argv_const *argv, const char *options, + const struct option *long_options, int *opt_index) +{ + return _getopt_internal (argc, (char **) argv, options, long_options, + opt_index, 0, 0); +} + +int +_getopt_long_r (int argc, char **argv, const char *options, + const struct option *long_options, int *opt_index, + struct _getopt_data *d) +{ + return _getopt_internal_r (argc, argv, options, long_options, opt_index, + 0, d, 0); +} + +/* Like getopt_long, but '-' as well as '--' can indicate a long option. + If an option that starts with '-' (not '--') doesn't match a long option, + but does match a short option, it is parsed as a short option + instead. */ + +int +getopt_long_only (int argc, char *__getopt_argv_const *argv, + const char *options, + const struct option *long_options, int *opt_index) +{ + return _getopt_internal (argc, (char **) argv, options, long_options, + opt_index, 1, 0); +} + +int +_getopt_long_only_r (int argc, char **argv, const char *options, + const struct option *long_options, int *opt_index, + struct _getopt_data *d) +{ + return _getopt_internal_r (argc, argv, options, long_options, opt_index, + 1, d, 0); +} + + +#ifdef TEST + +#include + +int +main (int argc, char **argv) +{ + int c; + int digit_optind = 0; + + while (1) + { + int this_option_optind = optind ? optind : 1; + int option_index = 0; + static const struct option long_options[] = + { + {"add", 1, 0, 0}, + {"append", 0, 0, 0}, + {"delete", 1, 0, 0}, + {"verbose", 0, 0, 0}, + {"create", 0, 0, 0}, + {"file", 1, 0, 0}, + {0, 0, 0, 0} + }; + + c = getopt_long (argc, argv, "abc:d:0123456789", + long_options, &option_index); + if (c == -1) + break; + + switch (c) + { + case 0: + printf ("option %s", long_options[option_index].name); + if (optarg) + printf (" with arg %s", optarg); + printf ("\n"); + break; + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (digit_optind != 0 && digit_optind != this_option_optind) + printf ("digits occur in two different argv-elements.\n"); + digit_optind = this_option_optind; + printf ("option %c\n", c); + break; + + case 'a': + printf ("option a\n"); + break; + + case 'b': + printf ("option b\n"); + break; + + case 'c': + printf ("option c with value '%s'\n", optarg); + break; + + case 'd': + printf ("option d with value '%s'\n", optarg); + break; + + case '?': + break; + + default: + printf ("?? getopt returned character code 0%o ??\n", c); + } + } + + if (optind < argc) + { + printf ("non-option ARGV-elements: "); + while (optind < argc) + printf ("%s ", argv[optind++]); + printf ("\n"); + } + + exit (0); +} + +#endif /* TEST */ diff --git a/gettext-tools/gnulib-lib/getopt_int.h b/gettext-tools/gnulib-lib/getopt_int.h new file mode 100644 index 0000000..24ed672 --- /dev/null +++ b/gettext-tools/gnulib-lib/getopt_int.h @@ -0,0 +1,135 @@ +/* Internal declarations for getopt. + Copyright (C) 1989-1994, 1996-1999, 2001, 2003-2004, 2009-2014 Free Software + Foundation, Inc. + This file is part of the GNU C Library. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _GETOPT_INT_H +#define _GETOPT_INT_H 1 + +#include + +extern int _getopt_internal (int ___argc, char **___argv, + const char *__shortopts, + const struct option *__longopts, int *__longind, + int __long_only, int __posixly_correct); + + +/* Reentrant versions which can handle parsing multiple argument + vectors at the same time. */ + +/* Describe how to deal with options that follow non-option ARGV-elements. + + If the caller did not specify anything, + the default is REQUIRE_ORDER if the environment variable + POSIXLY_CORRECT is defined, PERMUTE otherwise. + + REQUIRE_ORDER means don't recognize them as options; + stop option processing when the first non-option is seen. + This is what Unix does. + This mode of operation is selected by either setting the environment + variable POSIXLY_CORRECT, or using '+' as the first character + of the list of option characters, or by calling getopt. + + PERMUTE is the default. We permute the contents of ARGV as we + scan, so that eventually all the non-options are at the end. + This allows options to be given in any order, even with programs + that were not written to expect this. + + RETURN_IN_ORDER is an option available to programs that were + written to expect options and other ARGV-elements in any order + and that care about the ordering of the two. We describe each + non-option ARGV-element as if it were the argument of an option + with character code 1. Using '-' as the first character of the + list of option characters selects this mode of operation. + + The special argument '--' forces an end of option-scanning regardless + of the value of 'ordering'. In the case of RETURN_IN_ORDER, only + '--' can cause 'getopt' to return -1 with 'optind' != ARGC. */ + +enum __ord + { + REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER + }; + +/* Data type for reentrant functions. */ +struct _getopt_data +{ + /* These have exactly the same meaning as the corresponding global + variables, except that they are used for the reentrant + versions of getopt. */ + int optind; + int opterr; + int optopt; + char *optarg; + + /* Internal members. */ + + /* True if the internal members have been initialized. */ + int __initialized; + + /* The next char to be scanned in the option-element + in which the last option character we returned was found. + This allows us to pick up the scan where we left off. + + If this is zero, or a null string, it means resume the scan + by advancing to the next ARGV-element. */ + char *__nextchar; + + /* See __ord above. */ + enum __ord __ordering; + + /* If the POSIXLY_CORRECT environment variable is set + or getopt was called. */ + int __posixly_correct; + + + /* Handle permutation of arguments. */ + + /* Describe the part of ARGV that contains non-options that have + been skipped. 'first_nonopt' is the index in ARGV of the first + of them; 'last_nonopt' is the index after the last of them. */ + + int __first_nonopt; + int __last_nonopt; + +#if defined _LIBC && defined USE_NONOPTION_FLAGS + int __nonoption_flags_max_len; + int __nonoption_flags_len; +#endif +}; + +/* The initializer is necessary to set OPTIND and OPTERR to their + default values and to clear the initialization flag. */ +#define _GETOPT_DATA_INITIALIZER { 1, 1 } + +extern int _getopt_internal_r (int ___argc, char **___argv, + const char *__shortopts, + const struct option *__longopts, int *__longind, + int __long_only, struct _getopt_data *__data, + int __posixly_correct); + +extern int _getopt_long_r (int ___argc, char **___argv, + const char *__shortopts, + const struct option *__longopts, int *__longind, + struct _getopt_data *__data); + +extern int _getopt_long_only_r (int ___argc, char **___argv, + const char *__shortopts, + const struct option *__longopts, + int *__longind, + struct _getopt_data *__data); + +#endif /* getopt_int.h */ diff --git a/gettext-tools/gnulib-lib/gettext.h b/gettext-tools/gnulib-lib/gettext.h new file mode 100644 index 0000000..ac4d7d5 --- /dev/null +++ b/gettext-tools/gnulib-lib/gettext.h @@ -0,0 +1,287 @@ +/* Convenience header for conditional use of GNU . + Copyright (C) 1995-1998, 2000-2002, 2004-2006, 2009-2011 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _LIBGETTEXT_H +#define _LIBGETTEXT_H 1 + +/* NLS can be disabled through the configure --disable-nls option. */ +#if ENABLE_NLS + +/* Get declarations of GNU message catalog functions. */ +# include + +/* You can set the DEFAULT_TEXT_DOMAIN macro to specify the domain used by + the gettext() and ngettext() macros. This is an alternative to calling + textdomain(), and is useful for libraries. */ +# ifdef DEFAULT_TEXT_DOMAIN +# undef gettext +# define gettext(Msgid) \ + dgettext (DEFAULT_TEXT_DOMAIN, Msgid) +# undef ngettext +# define ngettext(Msgid1, Msgid2, N) \ + dngettext (DEFAULT_TEXT_DOMAIN, Msgid1, Msgid2, N) +# endif + +#else + +/* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which + chokes if dcgettext is defined as a macro. So include it now, to make + later inclusions of a NOP. We don't include + as well because people using "gettext.h" will not include , + and also including would fail on SunOS 4, whereas + is OK. */ +#if defined(__sun) +# include +#endif + +/* Many header files from the libstdc++ coming with g++ 3.3 or newer include + , which chokes if dcgettext is defined as a macro. So include + it now, to make later inclusions of a NOP. */ +#if defined(__cplusplus) && defined(__GNUG__) && (__GNUC__ >= 3) +# include +# if (__GLIBC__ >= 2 && !defined __UCLIBC__) || _GLIBCXX_HAVE_LIBINTL_H +# include +# endif +#endif + +/* Disabled NLS. + The casts to 'const char *' serve the purpose of producing warnings + for invalid uses of the value returned from these functions. + On pre-ANSI systems without 'const', the config.h file is supposed to + contain "#define const". */ +# undef gettext +# define gettext(Msgid) ((const char *) (Msgid)) +# undef dgettext +# define dgettext(Domainname, Msgid) ((void) (Domainname), gettext (Msgid)) +# undef dcgettext +# define dcgettext(Domainname, Msgid, Category) \ + ((void) (Category), dgettext (Domainname, Msgid)) +# undef ngettext +# define ngettext(Msgid1, Msgid2, N) \ + ((N) == 1 \ + ? ((void) (Msgid2), (const char *) (Msgid1)) \ + : ((void) (Msgid1), (const char *) (Msgid2))) +# undef dngettext +# define dngettext(Domainname, Msgid1, Msgid2, N) \ + ((void) (Domainname), ngettext (Msgid1, Msgid2, N)) +# undef dcngettext +# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \ + ((void) (Category), dngettext (Domainname, Msgid1, Msgid2, N)) +# undef textdomain +# define textdomain(Domainname) ((const char *) (Domainname)) +# undef bindtextdomain +# define bindtextdomain(Domainname, Dirname) \ + ((void) (Domainname), (const char *) (Dirname)) +# undef bind_textdomain_codeset +# define bind_textdomain_codeset(Domainname, Codeset) \ + ((void) (Domainname), (const char *) (Codeset)) + +#endif + +/* Prefer gnulib's setlocale override over libintl's setlocale override. */ +#ifdef GNULIB_defined_setlocale +# undef setlocale +# define setlocale rpl_setlocale +#endif + +/* A pseudo function call that serves as a marker for the automated + extraction of messages, but does not call gettext(). The run-time + translation is done at a different place in the code. + The argument, String, should be a literal string. Concatenated strings + and other string expressions won't work. + The macro's expansion is not parenthesized, so that it is suitable as + initializer for static 'char[]' or 'const char[]' variables. */ +#define gettext_noop(String) String + +/* The separator between msgctxt and msgid in a .mo file. */ +#define GETTEXT_CONTEXT_GLUE "\004" + +/* Pseudo function calls, taking a MSGCTXT and a MSGID instead of just a + MSGID. MSGCTXT and MSGID must be string literals. MSGCTXT should be + short and rarely need to change. + The letter 'p' stands for 'particular' or 'special'. */ +#ifdef DEFAULT_TEXT_DOMAIN +# define pgettext(Msgctxt, Msgid) \ + pgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES) +#else +# define pgettext(Msgctxt, Msgid) \ + pgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES) +#endif +#define dpgettext(Domainname, Msgctxt, Msgid) \ + pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES) +#define dcpgettext(Domainname, Msgctxt, Msgid, Category) \ + pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, Category) +#ifdef DEFAULT_TEXT_DOMAIN +# define npgettext(Msgctxt, Msgid, MsgidPlural, N) \ + npgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES) +#else +# define npgettext(Msgctxt, Msgid, MsgidPlural, N) \ + npgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES) +#endif +#define dnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N) \ + npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES) +#define dcnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N, Category) \ + npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, Category) + +#ifdef __GNUC__ +__inline +#else +#ifdef __cplusplus +inline +#endif +#endif +static const char * +pgettext_aux (const char *domain, + const char *msg_ctxt_id, const char *msgid, + int category) +{ + const char *translation = dcgettext (domain, msg_ctxt_id, category); + if (translation == msg_ctxt_id) + return msgid; + else + return translation; +} + +#ifdef __GNUC__ +__inline +#else +#ifdef __cplusplus +inline +#endif +#endif +static const char * +npgettext_aux (const char *domain, + const char *msg_ctxt_id, const char *msgid, + const char *msgid_plural, unsigned long int n, + int category) +{ + const char *translation = + dcngettext (domain, msg_ctxt_id, msgid_plural, n, category); + if (translation == msg_ctxt_id || translation == msgid_plural) + return (n == 1 ? msgid : msgid_plural); + else + return translation; +} + +/* The same thing extended for non-constant arguments. Here MSGCTXT and MSGID + can be arbitrary expressions. But for string literals these macros are + less efficient than those above. */ + +#include + +#if (((__GNUC__ >= 3 || __GNUG__ >= 2) && !defined __STRICT_ANSI__) \ + /* || __STDC_VERSION__ >= 199901L */ ) +# define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS 1 +#else +# define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS 0 +#endif + +#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS +#include +#endif + +#define pgettext_expr(Msgctxt, Msgid) \ + dcpgettext_expr (NULL, Msgctxt, Msgid, LC_MESSAGES) +#define dpgettext_expr(Domainname, Msgctxt, Msgid) \ + dcpgettext_expr (Domainname, Msgctxt, Msgid, LC_MESSAGES) + +#ifdef __GNUC__ +__inline +#else +#ifdef __cplusplus +inline +#endif +#endif +static const char * +dcpgettext_expr (const char *domain, + const char *msgctxt, const char *msgid, + int category) +{ + size_t msgctxt_len = strlen (msgctxt) + 1; + size_t msgid_len = strlen (msgid) + 1; + const char *translation; +#if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS + char msg_ctxt_id[msgctxt_len + msgid_len]; +#else + char buf[1024]; + char *msg_ctxt_id = + (msgctxt_len + msgid_len <= sizeof (buf) + ? buf + : (char *) malloc (msgctxt_len + msgid_len)); + if (msg_ctxt_id != NULL) +#endif + { + memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1); + msg_ctxt_id[msgctxt_len - 1] = '\004'; + memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len); + translation = dcgettext (domain, msg_ctxt_id, category); +#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS + if (msg_ctxt_id != buf) + free (msg_ctxt_id); +#endif + if (translation != msg_ctxt_id) + return translation; + } + return msgid; +} + +#define npgettext_expr(Msgctxt, Msgid, MsgidPlural, N) \ + dcnpgettext_expr (NULL, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES) +#define dnpgettext_expr(Domainname, Msgctxt, Msgid, MsgidPlural, N) \ + dcnpgettext_expr (Domainname, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES) + +#ifdef __GNUC__ +__inline +#else +#ifdef __cplusplus +inline +#endif +#endif +static const char * +dcnpgettext_expr (const char *domain, + const char *msgctxt, const char *msgid, + const char *msgid_plural, unsigned long int n, + int category) +{ + size_t msgctxt_len = strlen (msgctxt) + 1; + size_t msgid_len = strlen (msgid) + 1; + const char *translation; +#if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS + char msg_ctxt_id[msgctxt_len + msgid_len]; +#else + char buf[1024]; + char *msg_ctxt_id = + (msgctxt_len + msgid_len <= sizeof (buf) + ? buf + : (char *) malloc (msgctxt_len + msgid_len)); + if (msg_ctxt_id != NULL) +#endif + { + memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1); + msg_ctxt_id[msgctxt_len - 1] = '\004'; + memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len); + translation = dcngettext (domain, msg_ctxt_id, msgid_plural, n, category); +#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS + if (msg_ctxt_id != buf) + free (msg_ctxt_id); +#endif + if (!(translation == msg_ctxt_id || translation == msgid_plural)) + return translation; + } + return (n == 1 ? msgid : msgid_plural); +} + +#endif /* _LIBGETTEXT_H */ diff --git a/gettext-tools/gnulib-lib/gettimeofday.c b/gettext-tools/gnulib-lib/gettimeofday.c new file mode 100644 index 0000000..8b2058e --- /dev/null +++ b/gettext-tools/gnulib-lib/gettimeofday.c @@ -0,0 +1,154 @@ +/* Provide gettimeofday for systems that don't have it or for which it's broken. + + Copyright (C) 2001-2003, 2005-2007, 2009-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . */ + +/* written by Jim Meyering */ + +#include + +/* Specification. */ +#include + +#include + +#if HAVE_SYS_TIMEB_H +# include +#endif + +#if GETTIMEOFDAY_CLOBBERS_LOCALTIME || TZSET_CLOBBERS_LOCALTIME + +/* Work around the bug in some systems whereby gettimeofday clobbers + the static buffer that localtime uses for its return value. The + gettimeofday function from Mac OS X 10.0.4 (i.e., Darwin 1.3.7) has + this problem. The tzset replacement is necessary for at least + Solaris 2.5, 2.5.1, and 2.6. */ + +static struct tm tm_zero_buffer; +static struct tm *localtime_buffer_addr = &tm_zero_buffer; + +# undef localtime +extern struct tm *localtime (time_t const *); + +# undef gmtime +extern struct tm *gmtime (time_t const *); + +/* This is a wrapper for localtime. It is used only on systems for which + gettimeofday clobbers the static buffer used for localtime's result. + + On the first call, record the address of the static buffer that + localtime uses for its result. */ + +struct tm * +rpl_localtime (time_t const *timep) +{ + struct tm *tm = localtime (timep); + + if (localtime_buffer_addr == &tm_zero_buffer) + localtime_buffer_addr = tm; + + return tm; +} + +/* Same as above, since gmtime and localtime use the same buffer. */ +struct tm * +rpl_gmtime (time_t const *timep) +{ + struct tm *tm = gmtime (timep); + + if (localtime_buffer_addr == &tm_zero_buffer) + localtime_buffer_addr = tm; + + return tm; +} + +#endif /* GETTIMEOFDAY_CLOBBERS_LOCALTIME || TZSET_CLOBBERS_LOCALTIME */ + +#if TZSET_CLOBBERS_LOCALTIME + +# undef tzset +extern void tzset (void); + +/* This is a wrapper for tzset, for systems on which tzset may clobber + the static buffer used for localtime's result. */ +void +rpl_tzset (void) +{ + /* Save and restore the contents of the buffer used for localtime's + result around the call to tzset. */ + struct tm save = *localtime_buffer_addr; + tzset (); + *localtime_buffer_addr = save; +} +#endif + +/* This is a wrapper for gettimeofday. It is used only on systems + that lack this function, or whose implementation of this function + causes problems. */ + +int +gettimeofday (struct timeval *restrict tv, void *restrict tz) +{ +#undef gettimeofday +#if HAVE_GETTIMEOFDAY +# if GETTIMEOFDAY_CLOBBERS_LOCALTIME + /* Save and restore the contents of the buffer used for localtime's + result around the call to gettimeofday. */ + struct tm save = *localtime_buffer_addr; +# endif + +# if defined timeval /* 'struct timeval' overridden by gnulib? */ +# undef timeval + struct timeval otv; + int result = gettimeofday (&otv, (struct timezone *) tz); + if (result == 0) + { + tv->tv_sec = otv.tv_sec; + tv->tv_usec = otv.tv_usec; + } +# else + int result = gettimeofday (tv, (struct timezone *) tz); +# endif + +# if GETTIMEOFDAY_CLOBBERS_LOCALTIME + *localtime_buffer_addr = save; +# endif + + return result; + +#else + +# if HAVE__FTIME + + struct _timeb timebuf; + _ftime (&timebuf); + tv->tv_sec = timebuf.time; + tv->tv_usec = timebuf.millitm * 1000; + +# else + +# if !defined OK_TO_USE_1S_CLOCK +# error "Only 1-second nominal clock resolution found. Is that intended?" \ + "If so, compile with the -DOK_TO_USE_1S_CLOCK option." +# endif + tv->tv_sec = time (NULL); + tv->tv_usec = 0; + +# endif + + return 0; + +#endif +} diff --git a/gettext-tools/gnulib-lib/gl_anyhash_list1.h b/gettext-tools/gnulib-lib/gl_anyhash_list1.h new file mode 100644 index 0000000..54d594f --- /dev/null +++ b/gettext-tools/gnulib-lib/gl_anyhash_list1.h @@ -0,0 +1,27 @@ +/* Sequential list data type implemented by a hash table with another list. + Copyright (C) 2006, 2009-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Common code of + gl_linkedhash_list.c, gl_avltreehash_list.c, gl_rbtreehash_list.c. */ + +/* Hash table entry. */ +struct gl_hash_entry +{ + struct gl_hash_entry *hash_next; /* chain of entries in same bucket */ + size_t hashcode; /* cache of values' common hash code */ +}; +typedef struct gl_hash_entry * gl_hash_entry_t; diff --git a/gettext-tools/gnulib-lib/gl_anyhash_list2.h b/gettext-tools/gnulib-lib/gl_anyhash_list2.h new file mode 100644 index 0000000..982c04d --- /dev/null +++ b/gettext-tools/gnulib-lib/gl_anyhash_list2.h @@ -0,0 +1,138 @@ +/* Sequential list data type implemented by a hash table with another list. + Copyright (C) 2006, 2009-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Common code of + gl_linkedhash_list.c, gl_avltreehash_list.c, gl_rbtreehash_list.c. */ + +/* Array of primes, approximately in steps of factor 1.2. + This table was computed by executing the Common Lisp expression + (dotimes (i 244) (format t "nextprime(~D)~%" (ceiling (expt 1.2d0 i)))) + and feeding the result to PARI/gp. */ +static const size_t primes[] = + { + 11, 13, 17, 19, 23, 29, 37, 41, 47, 59, 67, 83, 97, 127, 139, 167, 199, + 239, 293, 347, 419, 499, 593, 709, 853, 1021, 1229, 1471, 1777, 2129, 2543, + 3049, 3659, 4391, 5273, 6323, 7589, 9103, 10937, 13109, 15727, 18899, + 22651, 27179, 32609, 39133, 46957, 56359, 67619, 81157, 97369, 116849, + 140221, 168253, 201907, 242309, 290761, 348889, 418667, 502409, 602887, + 723467, 868151, 1041779, 1250141, 1500181, 1800191, 2160233, 2592277, + 3110741, 3732887, 4479463, 5375371, 6450413, 7740517, 9288589, 11146307, + 13375573, 16050689, 19260817, 23112977, 27735583, 33282701, 39939233, + 47927081, 57512503, 69014987, 82818011, 99381577, 119257891, 143109469, + 171731387, 206077643, 247293161, 296751781, 356102141, 427322587, + 512787097, 615344489, 738413383, 886096061, 1063315271, 1275978331, + 1531174013, 1837408799, 2204890543UL, 2645868653UL, 3175042391UL, + 3810050851UL, +#if SIZE_MAX > 4294967295UL + 4572061027UL, 5486473229UL, 6583767889UL, 7900521449UL, 9480625733UL, + 11376750877UL, 13652101063UL, 16382521261UL, 19659025513UL, 23590830631UL, + 28308996763UL, 33970796089UL, 40764955463UL, 48917946377UL, 58701535657UL, + 70441842749UL, 84530211301UL, 101436253561UL, 121723504277UL, + 146068205131UL, 175281846149UL, 210338215379UL, 252405858521UL, + 302887030151UL, 363464436191UL, 436157323417UL, 523388788231UL, + 628066545713UL, 753679854847UL, 904415825857UL, 1085298991109UL, + 1302358789181UL, 1562830547009UL, 1875396656429UL, 2250475987709UL, + 2700571185239UL, 3240685422287UL, 3888822506759UL, 4666587008147UL, + 5599904409713UL, 6719885291641UL, 8063862349969UL, 9676634819959UL, + 11611961783951UL, 13934354140769UL, 16721224968907UL, 20065469962669UL, + 24078563955191UL, 28894276746229UL, 34673132095507UL, 41607758514593UL, + 49929310217531UL, 59915172260971UL, 71898206713183UL, 86277848055823UL, + 103533417666967UL, 124240101200359UL, 149088121440451UL, 178905745728529UL, + 214686894874223UL, 257624273849081UL, 309149128618903UL, 370978954342639UL, + 445174745211143UL, 534209694253381UL, 641051633104063UL, 769261959724877UL, + 923114351670013UL, 1107737222003791UL, 1329284666404567UL, + 1595141599685509UL, 1914169919622551UL, 2297003903547091UL, + 2756404684256459UL, 3307685621107757UL, 3969222745329323UL, + 4763067294395177UL, 5715680753274209UL, 6858816903929113UL, + 8230580284714831UL, 9876696341657791UL, 11852035609989371UL, + 14222442731987227UL, 17066931278384657UL, 20480317534061597UL, + 24576381040873903UL, 29491657249048679UL, 35389988698858471UL, + 42467986438630267UL, 50961583726356109UL, 61153900471627387UL, + 73384680565952851UL, 88061616679143347UL, 105673940014972061UL, + 126808728017966413UL, 152170473621559703UL, 182604568345871671UL, + 219125482015045997UL, 262950578418055169UL, 315540694101666193UL, + 378648832921999397UL, 454378599506399233UL, 545254319407679131UL, + 654305183289214771UL, 785166219947057701UL, 942199463936469157UL, + 1130639356723763129UL, 1356767228068515623UL, 1628120673682218619UL, + 1953744808418662409UL, 2344493770102394881UL, 2813392524122873857UL, + 3376071028947448339UL, 4051285234736937517UL, 4861542281684325481UL, + 5833850738021191727UL, 7000620885625427969UL, 8400745062750513217UL, + 10080894075300616261UL, 12097072890360739951UL, 14516487468432885797UL, + 17419784962119465179UL, +#endif + SIZE_MAX /* sentinel, to ensure the search terminates */ + }; + +/* Return a suitable prime >= ESTIMATE. */ +static size_t +next_prime (size_t estimate) +{ + size_t i; + + for (i = 0; i < sizeof (primes) / sizeof (primes[0]); i++) + if (primes[i] >= estimate) + return primes[i]; + return SIZE_MAX; /* not a prime, but better than nothing */ +} + +/* Resize the hash table with a new estimated size. */ +static void +hash_resize (gl_list_t list, size_t estimate) +{ + size_t new_size = next_prime (estimate); + + if (new_size > list->table_size) + { + gl_hash_entry_t *old_table = list->table; + /* Allocate the new table. */ + gl_hash_entry_t *new_table; + size_t i; + + if (size_overflow_p (xtimes (new_size, sizeof (gl_hash_entry_t)))) + goto fail; + new_table = + (gl_hash_entry_t *) calloc (new_size, sizeof (gl_hash_entry_t)); + if (new_table == NULL) + goto fail; + + /* Iterate through the entries of the old table. */ + for (i = list->table_size; i > 0; ) + { + gl_hash_entry_t node = old_table[--i]; + + while (node != NULL) + { + gl_hash_entry_t next = node->hash_next; + /* Add the entry to the new table. */ + size_t bucket = node->hashcode % new_size; + node->hash_next = new_table[bucket]; + new_table[bucket] = node; + + node = next; + } + } + + list->table = new_table; + list->table_size = new_size; + free (old_table); + } + return; + + fail: + /* Just continue without resizing the table. */ + return; +} diff --git a/gettext-tools/gnulib-lib/gl_anylinked_list1.h b/gettext-tools/gnulib-lib/gl_anylinked_list1.h new file mode 100644 index 0000000..6433442 --- /dev/null +++ b/gettext-tools/gnulib-lib/gl_anylinked_list1.h @@ -0,0 +1,48 @@ +/* Sequential list data type implemented by a linked list. + Copyright (C) 2006, 2009-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Common code of gl_linked_list.c and gl_linkedhash_list.c. */ + +/* -------------------------- gl_list_t Data Type -------------------------- */ + +/* Concrete list node implementation, valid for this file only. */ +struct gl_list_node_impl +{ +#if WITH_HASHTABLE + struct gl_hash_entry h; /* hash table entry fields; must be first */ +#endif + struct gl_list_node_impl *next; + struct gl_list_node_impl *prev; + const void *value; +}; + +/* Concrete gl_list_impl type, valid for this file only. */ +struct gl_list_impl +{ + struct gl_list_impl_base base; +#if WITH_HASHTABLE + /* A hash table: managed as an array of collision lists. */ + struct gl_hash_entry **table; + size_t table_size; +#endif + /* A circular list anchored at root. + The first node is = root.next, the last node is = root.prev. + The root's value is unused. */ + struct gl_list_node_impl root; + /* Number of list nodes, excluding the root. */ + size_t count; +}; diff --git a/gettext-tools/gnulib-lib/gl_anylinked_list2.h b/gettext-tools/gnulib-lib/gl_anylinked_list2.h new file mode 100644 index 0000000..8711823 --- /dev/null +++ b/gettext-tools/gnulib-lib/gl_anylinked_list2.h @@ -0,0 +1,1195 @@ +/* Sequential list data type implemented by a linked list. + Copyright (C) 2006-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Common code of gl_linked_list.c and gl_linkedhash_list.c. */ + +/* If the symbol SIGNAL_SAFE_LIST is defined, the code is compiled in such + a way that a gl_list_t data structure may be used from within a signal + handler. The operations allowed in the signal handler are: + gl_list_iterator, gl_list_iterator_next, gl_list_iterator_free. + The list and node fields that are therefore accessed from the signal handler + are: + list->root, node->next, node->value. + We are careful to make modifications to these fields only in an order + that maintains the consistency of the list data structure at any moment, + and we use 'volatile' assignments to prevent the compiler from reordering + such assignments. */ +#ifdef SIGNAL_SAFE_LIST +# define ASYNCSAFE(type) *(volatile type *)& +#else +# define ASYNCSAFE(type) +#endif + +/* -------------------------- gl_list_t Data Type -------------------------- */ + +static gl_list_t +gl_linked_nx_create_empty (gl_list_implementation_t implementation, + gl_listelement_equals_fn equals_fn, + gl_listelement_hashcode_fn hashcode_fn, + gl_listelement_dispose_fn dispose_fn, + bool allow_duplicates) +{ + struct gl_list_impl *list = + (struct gl_list_impl *) malloc (sizeof (struct gl_list_impl)); + + if (list == NULL) + return NULL; + + list->base.vtable = implementation; + list->base.equals_fn = equals_fn; + list->base.hashcode_fn = hashcode_fn; + list->base.dispose_fn = dispose_fn; + list->base.allow_duplicates = allow_duplicates; +#if WITH_HASHTABLE + list->table_size = 11; + list->table = + (gl_hash_entry_t *) calloc (list->table_size, sizeof (gl_hash_entry_t)); + if (list->table == NULL) + goto fail; +#endif + list->root.next = &list->root; + list->root.prev = &list->root; + list->count = 0; + + return list; + +#if WITH_HASHTABLE + fail: + free (list); + return NULL; +#endif +} + +static gl_list_t +gl_linked_nx_create (gl_list_implementation_t implementation, + gl_listelement_equals_fn equals_fn, + gl_listelement_hashcode_fn hashcode_fn, + gl_listelement_dispose_fn dispose_fn, + bool allow_duplicates, + size_t count, const void **contents) +{ + struct gl_list_impl *list = + (struct gl_list_impl *) malloc (sizeof (struct gl_list_impl)); + gl_list_node_t tail; + + if (list == NULL) + return NULL; + + list->base.vtable = implementation; + list->base.equals_fn = equals_fn; + list->base.hashcode_fn = hashcode_fn; + list->base.dispose_fn = dispose_fn; + list->base.allow_duplicates = allow_duplicates; +#if WITH_HASHTABLE + { + size_t estimate = xsum (count, count / 2); /* 1.5 * count */ + if (estimate < 10) + estimate = 10; + list->table_size = next_prime (estimate); + if (size_overflow_p (xtimes (list->table_size, sizeof (gl_hash_entry_t)))) + goto fail1; + list->table = + (gl_hash_entry_t *) calloc (list->table_size, sizeof (gl_hash_entry_t)); + if (list->table == NULL) + goto fail1; + } +#endif + list->count = count; + tail = &list->root; + for (; count > 0; contents++, count--) + { + gl_list_node_t node = + (struct gl_list_node_impl *) malloc (sizeof (struct gl_list_node_impl)); + + if (node == NULL) + goto fail2; + + node->value = *contents; +#if WITH_HASHTABLE + node->h.hashcode = + (list->base.hashcode_fn != NULL + ? list->base.hashcode_fn (node->value) + : (size_t)(uintptr_t) node->value); + + /* Add node to the hash table. */ + if (add_to_bucket (list, node) < 0) + { + free (node); + goto fail2; + } +#endif + + /* Add node to the list. */ + node->prev = tail; + tail->next = node; + tail = node; + } + tail->next = &list->root; + list->root.prev = tail; + + return list; + + fail2: + { + gl_list_node_t node; + + for (node = tail; node != &list->root; ) + { + gl_list_node_t prev = node->prev; + + free (node); + node = prev; + } + } +#if WITH_HASHTABLE + free (list->table); + fail1: +#endif + free (list); + return NULL; +} + +static size_t +gl_linked_size (gl_list_t list) +{ + return list->count; +} + +static const void * +gl_linked_node_value (gl_list_t list, gl_list_node_t node) +{ + return node->value; +} + +static int +gl_linked_node_nx_set_value (gl_list_t list, gl_list_node_t node, + const void *elt) +{ +#if WITH_HASHTABLE + if (elt != node->value) + { + size_t new_hashcode = + (list->base.hashcode_fn != NULL + ? list->base.hashcode_fn (elt) + : (size_t)(uintptr_t) elt); + + if (new_hashcode != node->h.hashcode) + { + remove_from_bucket (list, node); + node->value = elt; + node->h.hashcode = new_hashcode; + if (add_to_bucket (list, node) < 0) + { + /* Out of memory. We removed node from a bucket but cannot add + it to another bucket. In order to avoid inconsistencies, we + must remove node entirely from the list. */ + gl_list_node_t before_removed = node->prev; + gl_list_node_t after_removed = node->next; + ASYNCSAFE(gl_list_node_t) before_removed->next = after_removed; + after_removed->prev = before_removed; + list->count--; + free (node); + return -1; + } + } + else + node->value = elt; + } +#else + node->value = elt; +#endif + return 0; +} + +static gl_list_node_t +gl_linked_next_node (gl_list_t list, gl_list_node_t node) +{ + return (node->next != &list->root ? node->next : NULL); +} + +static gl_list_node_t +gl_linked_previous_node (gl_list_t list, gl_list_node_t node) +{ + return (node->prev != &list->root ? node->prev : NULL); +} + +static const void * +gl_linked_get_at (gl_list_t list, size_t position) +{ + size_t count = list->count; + gl_list_node_t node; + + if (!(position < count)) + /* Invalid argument. */ + abort (); + /* Here we know count > 0. */ + if (position <= ((count - 1) / 2)) + { + node = list->root.next; + for (; position > 0; position--) + node = node->next; + } + else + { + position = count - 1 - position; + node = list->root.prev; + for (; position > 0; position--) + node = node->prev; + } + return node->value; +} + +static gl_list_node_t +gl_linked_nx_set_at (gl_list_t list, size_t position, const void *elt) +{ + size_t count = list->count; + gl_list_node_t node; + + if (!(position < count)) + /* Invalid argument. */ + abort (); + /* Here we know count > 0. */ + if (position <= ((count - 1) / 2)) + { + node = list->root.next; + for (; position > 0; position--) + node = node->next; + } + else + { + position = count - 1 - position; + node = list->root.prev; + for (; position > 0; position--) + node = node->prev; + } +#if WITH_HASHTABLE + if (elt != node->value) + { + size_t new_hashcode = + (list->base.hashcode_fn != NULL + ? list->base.hashcode_fn (elt) + : (size_t)(uintptr_t) elt); + + if (new_hashcode != node->h.hashcode) + { + remove_from_bucket (list, node); + node->value = elt; + node->h.hashcode = new_hashcode; + if (add_to_bucket (list, node) < 0) + { + /* Out of memory. We removed node from a bucket but cannot add + it to another bucket. In order to avoid inconsistencies, we + must remove node entirely from the list. */ + gl_list_node_t before_removed = node->prev; + gl_list_node_t after_removed = node->next; + ASYNCSAFE(gl_list_node_t) before_removed->next = after_removed; + after_removed->prev = before_removed; + list->count--; + free (node); + return NULL; + } + } + else + node->value = elt; + } +#else + node->value = elt; +#endif + return node; +} + +static gl_list_node_t +gl_linked_search_from_to (gl_list_t list, size_t start_index, size_t end_index, + const void *elt) +{ + size_t count = list->count; + + if (!(start_index <= end_index && end_index <= count)) + /* Invalid arguments. */ + abort (); + { +#if WITH_HASHTABLE + size_t hashcode = + (list->base.hashcode_fn != NULL + ? list->base.hashcode_fn (elt) + : (size_t)(uintptr_t) elt); + size_t bucket = hashcode % list->table_size; + gl_listelement_equals_fn equals = list->base.equals_fn; + + if (!list->base.allow_duplicates) + { + /* Look for the first match in the hash bucket. */ + gl_list_node_t found = NULL; + gl_list_node_t node; + + for (node = (gl_list_node_t) list->table[bucket]; + node != NULL; + node = (gl_list_node_t) node->h.hash_next) + if (node->h.hashcode == hashcode + && (equals != NULL + ? equals (elt, node->value) + : elt == node->value)) + { + found = node; + break; + } + if (start_index > 0) + /* Look whether found's index is < start_index. */ + for (node = list->root.next; ; node = node->next) + { + if (node == found) + return NULL; + if (--start_index == 0) + break; + } + if (end_index < count) + /* Look whether found's index is >= end_index. */ + { + end_index = count - end_index; + for (node = list->root.prev; ; node = node->prev) + { + if (node == found) + return NULL; + if (--end_index == 0) + break; + } + } + return found; + } + else + { + /* Look whether there is more than one match in the hash bucket. */ + bool multiple_matches = false; + gl_list_node_t first_match = NULL; + gl_list_node_t node; + + for (node = (gl_list_node_t) list->table[bucket]; + node != NULL; + node = (gl_list_node_t) node->h.hash_next) + if (node->h.hashcode == hashcode + && (equals != NULL + ? equals (elt, node->value) + : elt == node->value)) + { + if (first_match == NULL) + first_match = node; + else + { + multiple_matches = true; + break; + } + } + if (multiple_matches) + { + /* We need the match with the smallest index. But we don't have + a fast mapping node -> index. So we have to walk the list. */ + end_index -= start_index; + node = list->root.next; + for (; start_index > 0; start_index--) + node = node->next; + + for (; + end_index > 0; + node = node->next, end_index--) + if (node->h.hashcode == hashcode + && (equals != NULL + ? equals (elt, node->value) + : elt == node->value)) + return node; + /* The matches must have all been at indices < start_index or + >= end_index. */ + return NULL; + } + else + { + if (start_index > 0) + /* Look whether first_match's index is < start_index. */ + for (node = list->root.next; node != &list->root; node = node->next) + { + if (node == first_match) + return NULL; + if (--start_index == 0) + break; + } + if (end_index < list->count) + /* Look whether first_match's index is >= end_index. */ + { + end_index = list->count - end_index; + for (node = list->root.prev; ; node = node->prev) + { + if (node == first_match) + return NULL; + if (--end_index == 0) + break; + } + } + return first_match; + } + } +#else + gl_listelement_equals_fn equals = list->base.equals_fn; + gl_list_node_t node = list->root.next; + + end_index -= start_index; + for (; start_index > 0; start_index--) + node = node->next; + + if (equals != NULL) + { + for (; end_index > 0; node = node->next, end_index--) + if (equals (elt, node->value)) + return node; + } + else + { + for (; end_index > 0; node = node->next, end_index--) + if (elt == node->value) + return node; + } + return NULL; +#endif + } +} + +static size_t +gl_linked_indexof_from_to (gl_list_t list, size_t start_index, size_t end_index, + const void *elt) +{ + size_t count = list->count; + + if (!(start_index <= end_index && end_index <= count)) + /* Invalid arguments. */ + abort (); + { +#if WITH_HASHTABLE + /* Here the hash table doesn't help much. It only allows us to minimize + the number of equals() calls, by looking up first the node and then + its index. */ + size_t hashcode = + (list->base.hashcode_fn != NULL + ? list->base.hashcode_fn (elt) + : (size_t)(uintptr_t) elt); + size_t bucket = hashcode % list->table_size; + gl_listelement_equals_fn equals = list->base.equals_fn; + gl_list_node_t node; + + /* First step: Look up the node. */ + if (!list->base.allow_duplicates) + { + /* Look for the first match in the hash bucket. */ + for (node = (gl_list_node_t) list->table[bucket]; + node != NULL; + node = (gl_list_node_t) node->h.hash_next) + if (node->h.hashcode == hashcode + && (equals != NULL + ? equals (elt, node->value) + : elt == node->value)) + break; + } + else + { + /* Look whether there is more than one match in the hash bucket. */ + bool multiple_matches = false; + gl_list_node_t first_match = NULL; + + for (node = (gl_list_node_t) list->table[bucket]; + node != NULL; + node = (gl_list_node_t) node->h.hash_next) + if (node->h.hashcode == hashcode + && (equals != NULL + ? equals (elt, node->value) + : elt == node->value)) + { + if (first_match == NULL) + first_match = node; + else + { + multiple_matches = true; + break; + } + } + if (multiple_matches) + { + /* We need the match with the smallest index. But we don't have + a fast mapping node -> index. So we have to walk the list. */ + size_t index; + + index = start_index; + node = list->root.next; + for (; start_index > 0; start_index--) + node = node->next; + + for (; + index < end_index; + node = node->next, index++) + if (node->h.hashcode == hashcode + && (equals != NULL + ? equals (elt, node->value) + : elt == node->value)) + return index; + /* The matches must have all been at indices < start_index or + >= end_index. */ + return (size_t)(-1); + } + node = first_match; + } + + /* Second step: Look up the index of the node. */ + if (node == NULL) + return (size_t)(-1); + else + { + size_t index = 0; + + for (; node->prev != &list->root; node = node->prev) + index++; + + if (index >= start_index && index < end_index) + return index; + else + return (size_t)(-1); + } +#else + gl_listelement_equals_fn equals = list->base.equals_fn; + size_t index = start_index; + gl_list_node_t node = list->root.next; + + for (; start_index > 0; start_index--) + node = node->next; + + if (equals != NULL) + { + for (; + index < end_index; + node = node->next, index++) + if (equals (elt, node->value)) + return index; + } + else + { + for (; + index < end_index; + node = node->next, index++) + if (elt == node->value) + return index; + } + return (size_t)(-1); +#endif + } +} + +static gl_list_node_t +gl_linked_nx_add_first (gl_list_t list, const void *elt) +{ + gl_list_node_t node = + (struct gl_list_node_impl *) malloc (sizeof (struct gl_list_node_impl)); + + if (node == NULL) + return NULL; + + ASYNCSAFE(const void *) node->value = elt; +#if WITH_HASHTABLE + node->h.hashcode = + (list->base.hashcode_fn != NULL + ? list->base.hashcode_fn (node->value) + : (size_t)(uintptr_t) node->value); + + /* Add node to the hash table. */ + if (add_to_bucket (list, node) < 0) + { + free (node); + return NULL; + } +#endif + + /* Add node to the list. */ + node->prev = &list->root; + ASYNCSAFE(gl_list_node_t) node->next = list->root.next; + node->next->prev = node; + ASYNCSAFE(gl_list_node_t) list->root.next = node; + list->count++; + +#if WITH_HASHTABLE + hash_resize_after_add (list); +#endif + + return node; +} + +static gl_list_node_t +gl_linked_nx_add_last (gl_list_t list, const void *elt) +{ + gl_list_node_t node = + (struct gl_list_node_impl *) malloc (sizeof (struct gl_list_node_impl)); + + if (node == NULL) + return NULL; + + ASYNCSAFE(const void *) node->value = elt; +#if WITH_HASHTABLE + node->h.hashcode = + (list->base.hashcode_fn != NULL + ? list->base.hashcode_fn (node->value) + : (size_t)(uintptr_t) node->value); + + /* Add node to the hash table. */ + if (add_to_bucket (list, node) < 0) + { + free (node); + return NULL; + } +#endif + + /* Add node to the list. */ + ASYNCSAFE(gl_list_node_t) node->next = &list->root; + node->prev = list->root.prev; + ASYNCSAFE(gl_list_node_t) node->prev->next = node; + list->root.prev = node; + list->count++; + +#if WITH_HASHTABLE + hash_resize_after_add (list); +#endif + + return node; +} + +static gl_list_node_t +gl_linked_nx_add_before (gl_list_t list, gl_list_node_t node, const void *elt) +{ + gl_list_node_t new_node = + (struct gl_list_node_impl *) malloc (sizeof (struct gl_list_node_impl)); + + if (new_node == NULL) + return NULL; + + ASYNCSAFE(const void *) new_node->value = elt; +#if WITH_HASHTABLE + new_node->h.hashcode = + (list->base.hashcode_fn != NULL + ? list->base.hashcode_fn (new_node->value) + : (size_t)(uintptr_t) new_node->value); + + /* Add new_node to the hash table. */ + if (add_to_bucket (list, new_node) < 0) + { + free (new_node); + return NULL; + } +#endif + + /* Add new_node to the list. */ + ASYNCSAFE(gl_list_node_t) new_node->next = node; + new_node->prev = node->prev; + ASYNCSAFE(gl_list_node_t) new_node->prev->next = new_node; + node->prev = new_node; + list->count++; + +#if WITH_HASHTABLE + hash_resize_after_add (list); +#endif + + return new_node; +} + +static gl_list_node_t +gl_linked_nx_add_after (gl_list_t list, gl_list_node_t node, const void *elt) +{ + gl_list_node_t new_node = + (struct gl_list_node_impl *) malloc (sizeof (struct gl_list_node_impl)); + + if (new_node == NULL) + return NULL; + + ASYNCSAFE(const void *) new_node->value = elt; +#if WITH_HASHTABLE + new_node->h.hashcode = + (list->base.hashcode_fn != NULL + ? list->base.hashcode_fn (new_node->value) + : (size_t)(uintptr_t) new_node->value); + + /* Add new_node to the hash table. */ + if (add_to_bucket (list, new_node) < 0) + { + free (new_node); + return NULL; + } +#endif + + /* Add new_node to the list. */ + new_node->prev = node; + ASYNCSAFE(gl_list_node_t) new_node->next = node->next; + new_node->next->prev = new_node; + ASYNCSAFE(gl_list_node_t) node->next = new_node; + list->count++; + +#if WITH_HASHTABLE + hash_resize_after_add (list); +#endif + + return new_node; +} + +static gl_list_node_t +gl_linked_nx_add_at (gl_list_t list, size_t position, const void *elt) +{ + size_t count = list->count; + gl_list_node_t new_node; + + if (!(position <= count)) + /* Invalid argument. */ + abort (); + + new_node = (struct gl_list_node_impl *) malloc (sizeof (struct gl_list_node_impl)); + if (new_node == NULL) + return NULL; + + ASYNCSAFE(const void *) new_node->value = elt; +#if WITH_HASHTABLE + new_node->h.hashcode = + (list->base.hashcode_fn != NULL + ? list->base.hashcode_fn (new_node->value) + : (size_t)(uintptr_t) new_node->value); + + /* Add new_node to the hash table. */ + if (add_to_bucket (list, new_node) < 0) + { + free (new_node); + return NULL; + } +#endif + + /* Add new_node to the list. */ + if (position <= (count / 2)) + { + gl_list_node_t node; + + node = &list->root; + for (; position > 0; position--) + node = node->next; + new_node->prev = node; + ASYNCSAFE(gl_list_node_t) new_node->next = node->next; + new_node->next->prev = new_node; + ASYNCSAFE(gl_list_node_t) node->next = new_node; + } + else + { + gl_list_node_t node; + + position = count - position; + node = &list->root; + for (; position > 0; position--) + node = node->prev; + ASYNCSAFE(gl_list_node_t) new_node->next = node; + new_node->prev = node->prev; + ASYNCSAFE(gl_list_node_t) new_node->prev->next = new_node; + node->prev = new_node; + } + list->count++; + +#if WITH_HASHTABLE + hash_resize_after_add (list); +#endif + + return new_node; +} + +static bool +gl_linked_remove_node (gl_list_t list, gl_list_node_t node) +{ + gl_list_node_t prev; + gl_list_node_t next; + +#if WITH_HASHTABLE + /* Remove node from the hash table. */ + remove_from_bucket (list, node); +#endif + + /* Remove node from the list. */ + prev = node->prev; + next = node->next; + + ASYNCSAFE(gl_list_node_t) prev->next = next; + next->prev = prev; + list->count--; + + if (list->base.dispose_fn != NULL) + list->base.dispose_fn (node->value); + free (node); + return true; +} + +static bool +gl_linked_remove_at (gl_list_t list, size_t position) +{ + size_t count = list->count; + gl_list_node_t removed_node; + + if (!(position < count)) + /* Invalid argument. */ + abort (); + /* Here we know count > 0. */ + if (position <= ((count - 1) / 2)) + { + gl_list_node_t node; + gl_list_node_t after_removed; + + node = &list->root; + for (; position > 0; position--) + node = node->next; + removed_node = node->next; + after_removed = node->next->next; + ASYNCSAFE(gl_list_node_t) node->next = after_removed; + after_removed->prev = node; + } + else + { + gl_list_node_t node; + gl_list_node_t before_removed; + + position = count - 1 - position; + node = &list->root; + for (; position > 0; position--) + node = node->prev; + removed_node = node->prev; + before_removed = node->prev->prev; + node->prev = before_removed; + ASYNCSAFE(gl_list_node_t) before_removed->next = node; + } +#if WITH_HASHTABLE + remove_from_bucket (list, removed_node); +#endif + list->count--; + + if (list->base.dispose_fn != NULL) + list->base.dispose_fn (removed_node->value); + free (removed_node); + return true; +} + +static bool +gl_linked_remove (gl_list_t list, const void *elt) +{ + gl_list_node_t node = gl_linked_search_from_to (list, 0, list->count, elt); + + if (node != NULL) + return gl_linked_remove_node (list, node); + else + return false; +} + +static void +gl_linked_list_free (gl_list_t list) +{ + gl_listelement_dispose_fn dispose = list->base.dispose_fn; + gl_list_node_t node; + + for (node = list->root.next; node != &list->root; ) + { + gl_list_node_t next = node->next; + if (dispose != NULL) + dispose (node->value); + free (node); + node = next; + } +#if WITH_HASHTABLE + free (list->table); +#endif + free (list); +} + +/* --------------------- gl_list_iterator_t Data Type --------------------- */ + +static gl_list_iterator_t +gl_linked_iterator (gl_list_t list) +{ + gl_list_iterator_t result; + + result.vtable = list->base.vtable; + result.list = list; + result.p = list->root.next; + result.q = &list->root; +#ifdef lint + result.i = 0; + result.j = 0; + result.count = 0; +#endif + + return result; +} + +static gl_list_iterator_t +gl_linked_iterator_from_to (gl_list_t list, + size_t start_index, size_t end_index) +{ + gl_list_iterator_t result; + size_t n1, n2, n3; + + if (!(start_index <= end_index && end_index <= list->count)) + /* Invalid arguments. */ + abort (); + result.vtable = list->base.vtable; + result.list = list; + n1 = start_index; + n2 = end_index - start_index; + n3 = list->count - end_index; + /* Find the maximum among n1, n2, n3, so as to reduce the number of + loop iterations to n1 + n2 + n3 - max(n1,n2,n3). */ + if (n1 > n2 && n1 > n3) + { + /* n1 is the maximum, use n2 and n3. */ + gl_list_node_t node; + size_t i; + + node = &list->root; + for (i = n3; i > 0; i--) + node = node->prev; + result.q = node; + for (i = n2; i > 0; i--) + node = node->prev; + result.p = node; + } + else if (n2 > n3) + { + /* n2 is the maximum, use n1 and n3. */ + gl_list_node_t node; + size_t i; + + node = list->root.next; + for (i = n1; i > 0; i--) + node = node->next; + result.p = node; + + node = &list->root; + for (i = n3; i > 0; i--) + node = node->prev; + result.q = node; + } + else + { + /* n3 is the maximum, use n1 and n2. */ + gl_list_node_t node; + size_t i; + + node = list->root.next; + for (i = n1; i > 0; i--) + node = node->next; + result.p = node; + for (i = n2; i > 0; i--) + node = node->next; + result.q = node; + } + +#ifdef lint + result.i = 0; + result.j = 0; + result.count = 0; +#endif + + return result; +} + +static bool +gl_linked_iterator_next (gl_list_iterator_t *iterator, + const void **eltp, gl_list_node_t *nodep) +{ + if (iterator->p != iterator->q) + { + gl_list_node_t node = (gl_list_node_t) iterator->p; + *eltp = node->value; + if (nodep != NULL) + *nodep = node; + iterator->p = node->next; + return true; + } + else + return false; +} + +static void +gl_linked_iterator_free (gl_list_iterator_t *iterator) +{ +} + +/* ---------------------- Sorted gl_list_t Data Type ---------------------- */ + +static gl_list_node_t +gl_linked_sortedlist_search (gl_list_t list, gl_listelement_compar_fn compar, + const void *elt) +{ + gl_list_node_t node; + + for (node = list->root.next; node != &list->root; node = node->next) + { + int cmp = compar (node->value, elt); + + if (cmp > 0) + break; + if (cmp == 0) + return node; + } + return NULL; +} + +static gl_list_node_t +gl_linked_sortedlist_search_from_to (gl_list_t list, + gl_listelement_compar_fn compar, + size_t low, size_t high, + const void *elt) +{ + size_t count = list->count; + + if (!(low <= high && high <= list->count)) + /* Invalid arguments. */ + abort (); + + high -= low; + if (high > 0) + { + /* Here we know low < count. */ + size_t position = low; + gl_list_node_t node; + + if (position <= ((count - 1) / 2)) + { + node = list->root.next; + for (; position > 0; position--) + node = node->next; + } + else + { + position = count - 1 - position; + node = list->root.prev; + for (; position > 0; position--) + node = node->prev; + } + + do + { + int cmp = compar (node->value, elt); + + if (cmp > 0) + break; + if (cmp == 0) + return node; + node = node->next; + } + while (--high > 0); + } + return NULL; +} + +static size_t +gl_linked_sortedlist_indexof (gl_list_t list, gl_listelement_compar_fn compar, + const void *elt) +{ + gl_list_node_t node; + size_t index; + + for (node = list->root.next, index = 0; + node != &list->root; + node = node->next, index++) + { + int cmp = compar (node->value, elt); + + if (cmp > 0) + break; + if (cmp == 0) + return index; + } + return (size_t)(-1); +} + +static size_t +gl_linked_sortedlist_indexof_from_to (gl_list_t list, + gl_listelement_compar_fn compar, + size_t low, size_t high, + const void *elt) +{ + size_t count = list->count; + + if (!(low <= high && high <= list->count)) + /* Invalid arguments. */ + abort (); + + high -= low; + if (high > 0) + { + /* Here we know low < count. */ + size_t index = low; + size_t position = low; + gl_list_node_t node; + + if (position <= ((count - 1) / 2)) + { + node = list->root.next; + for (; position > 0; position--) + node = node->next; + } + else + { + position = count - 1 - position; + node = list->root.prev; + for (; position > 0; position--) + node = node->prev; + } + + do + { + int cmp = compar (node->value, elt); + + if (cmp > 0) + break; + if (cmp == 0) + return index; + node = node->next; + index++; + } + while (--high > 0); + } + return (size_t)(-1); +} + +static gl_list_node_t +gl_linked_sortedlist_nx_add (gl_list_t list, gl_listelement_compar_fn compar, + const void *elt) +{ + gl_list_node_t node; + + for (node = list->root.next; node != &list->root; node = node->next) + if (compar (node->value, elt) >= 0) + return gl_linked_nx_add_before (list, node, elt); + return gl_linked_nx_add_last (list, elt); +} + +static bool +gl_linked_sortedlist_remove (gl_list_t list, gl_listelement_compar_fn compar, + const void *elt) +{ + gl_list_node_t node; + + for (node = list->root.next; node != &list->root; node = node->next) + { + int cmp = compar (node->value, elt); + + if (cmp > 0) + break; + if (cmp == 0) + return gl_linked_remove_node (list, node); + } + return false; +} diff --git a/gettext-tools/gnulib-lib/gl_array_list.c b/gettext-tools/gnulib-lib/gl_array_list.c new file mode 100644 index 0000000..3220dd8 --- /dev/null +++ b/gettext-tools/gnulib-lib/gl_array_list.c @@ -0,0 +1,680 @@ +/* Sequential list data type implemented by an array. + Copyright (C) 2006-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include "gl_array_list.h" + +#include +/* Get memcpy. */ +#include + +/* Checked size_t computations. */ +#include "xsize.h" + +#ifndef uintptr_t +# define uintptr_t unsigned long +#endif + +/* -------------------------- gl_list_t Data Type -------------------------- */ + +/* Concrete gl_list_impl type, valid for this file only. */ +struct gl_list_impl +{ + struct gl_list_impl_base base; + /* An array of ALLOCATED elements, of which the first COUNT are used. + 0 <= COUNT <= ALLOCATED. */ + const void **elements; + size_t count; + size_t allocated; +}; + +/* struct gl_list_node_impl doesn't exist here. The pointers are actually + indices + 1. */ +#define INDEX_TO_NODE(index) (gl_list_node_t)(uintptr_t)(size_t)((index) + 1) +#define NODE_TO_INDEX(node) ((uintptr_t)(node) - 1) + +static gl_list_t +gl_array_nx_create_empty (gl_list_implementation_t implementation, + gl_listelement_equals_fn equals_fn, + gl_listelement_hashcode_fn hashcode_fn, + gl_listelement_dispose_fn dispose_fn, + bool allow_duplicates) +{ + struct gl_list_impl *list = + (struct gl_list_impl *) malloc (sizeof (struct gl_list_impl)); + + if (list == NULL) + return NULL; + + list->base.vtable = implementation; + list->base.equals_fn = equals_fn; + list->base.hashcode_fn = hashcode_fn; + list->base.dispose_fn = dispose_fn; + list->base.allow_duplicates = allow_duplicates; + list->elements = NULL; + list->count = 0; + list->allocated = 0; + + return list; +} + +static gl_list_t +gl_array_nx_create (gl_list_implementation_t implementation, + gl_listelement_equals_fn equals_fn, + gl_listelement_hashcode_fn hashcode_fn, + gl_listelement_dispose_fn dispose_fn, + bool allow_duplicates, + size_t count, const void **contents) +{ + struct gl_list_impl *list = + (struct gl_list_impl *) malloc (sizeof (struct gl_list_impl)); + + if (list == NULL) + return NULL; + + list->base.vtable = implementation; + list->base.equals_fn = equals_fn; + list->base.hashcode_fn = hashcode_fn; + list->base.dispose_fn = dispose_fn; + list->base.allow_duplicates = allow_duplicates; + if (count > 0) + { + if (size_overflow_p (xtimes (count, sizeof (const void *)))) + goto fail; + list->elements = (const void **) malloc (count * sizeof (const void *)); + if (list->elements == NULL) + goto fail; + memcpy (list->elements, contents, count * sizeof (const void *)); + } + else + list->elements = NULL; + list->count = count; + list->allocated = count; + + return list; + + fail: + free (list); + return NULL; +} + +static size_t +gl_array_size (gl_list_t list) +{ + return list->count; +} + +static const void * _GL_ATTRIBUTE_PURE +gl_array_node_value (gl_list_t list, gl_list_node_t node) +{ + uintptr_t index = NODE_TO_INDEX (node); + if (!(index < list->count)) + /* Invalid argument. */ + abort (); + return list->elements[index]; +} + +static int +gl_array_node_nx_set_value (gl_list_t list, gl_list_node_t node, + const void *elt) +{ + uintptr_t index = NODE_TO_INDEX (node); + if (!(index < list->count)) + /* Invalid argument. */ + abort (); + list->elements[index] = elt; + return 0; +} + +static gl_list_node_t _GL_ATTRIBUTE_PURE +gl_array_next_node (gl_list_t list, gl_list_node_t node) +{ + uintptr_t index = NODE_TO_INDEX (node); + if (!(index < list->count)) + /* Invalid argument. */ + abort (); + index++; + if (index < list->count) + return INDEX_TO_NODE (index); + else + return NULL; +} + +static gl_list_node_t _GL_ATTRIBUTE_PURE +gl_array_previous_node (gl_list_t list, gl_list_node_t node) +{ + uintptr_t index = NODE_TO_INDEX (node); + if (!(index < list->count)) + /* Invalid argument. */ + abort (); + if (index > 0) + return INDEX_TO_NODE (index - 1); + else + return NULL; +} + +static const void * _GL_ATTRIBUTE_PURE +gl_array_get_at (gl_list_t list, size_t position) +{ + size_t count = list->count; + + if (!(position < count)) + /* Invalid argument. */ + abort (); + return list->elements[position]; +} + +static gl_list_node_t +gl_array_nx_set_at (gl_list_t list, size_t position, const void *elt) +{ + size_t count = list->count; + + if (!(position < count)) + /* Invalid argument. */ + abort (); + list->elements[position] = elt; + return INDEX_TO_NODE (position); +} + +static size_t +gl_array_indexof_from_to (gl_list_t list, size_t start_index, size_t end_index, + const void *elt) +{ + size_t count = list->count; + + if (!(start_index <= end_index && end_index <= count)) + /* Invalid arguments. */ + abort (); + + if (start_index < end_index) + { + gl_listelement_equals_fn equals = list->base.equals_fn; + if (equals != NULL) + { + size_t i; + + for (i = start_index;;) + { + if (equals (elt, list->elements[i])) + return i; + i++; + if (i == end_index) + break; + } + } + else + { + size_t i; + + for (i = start_index;;) + { + if (elt == list->elements[i]) + return i; + i++; + if (i == end_index) + break; + } + } + } + return (size_t)(-1); +} + +static gl_list_node_t +gl_array_search_from_to (gl_list_t list, size_t start_index, size_t end_index, + const void *elt) +{ + size_t index = gl_array_indexof_from_to (list, start_index, end_index, elt); + return INDEX_TO_NODE (index); +} + +/* Ensure that list->allocated > list->count. + Return 0 upon success, -1 upon out-of-memory. */ +static int +grow (gl_list_t list) +{ + size_t new_allocated; + size_t memory_size; + const void **memory; + + new_allocated = xtimes (list->allocated, 2); + new_allocated = xsum (new_allocated, 1); + memory_size = xtimes (new_allocated, sizeof (const void *)); + if (size_overflow_p (memory_size)) + /* Overflow, would lead to out of memory. */ + return -1; + memory = (const void **) realloc (list->elements, memory_size); + if (memory == NULL) + /* Out of memory. */ + return -1; + list->elements = memory; + list->allocated = new_allocated; + return 0; +} + +static gl_list_node_t +gl_array_nx_add_first (gl_list_t list, const void *elt) +{ + size_t count = list->count; + const void **elements; + size_t i; + + if (count == list->allocated) + if (grow (list) < 0) + return NULL; + elements = list->elements; + for (i = count; i > 0; i--) + elements[i] = elements[i - 1]; + elements[0] = elt; + list->count = count + 1; + return INDEX_TO_NODE (0); +} + +static gl_list_node_t +gl_array_nx_add_last (gl_list_t list, const void *elt) +{ + size_t count = list->count; + + if (count == list->allocated) + if (grow (list) < 0) + return NULL; + list->elements[count] = elt; + list->count = count + 1; + return INDEX_TO_NODE (count); +} + +static gl_list_node_t +gl_array_nx_add_before (gl_list_t list, gl_list_node_t node, const void *elt) +{ + size_t count = list->count; + uintptr_t index = NODE_TO_INDEX (node); + size_t position; + const void **elements; + size_t i; + + if (!(index < count)) + /* Invalid argument. */ + abort (); + position = index; + if (count == list->allocated) + if (grow (list) < 0) + return NULL; + elements = list->elements; + for (i = count; i > position; i--) + elements[i] = elements[i - 1]; + elements[position] = elt; + list->count = count + 1; + return INDEX_TO_NODE (position); +} + +static gl_list_node_t +gl_array_nx_add_after (gl_list_t list, gl_list_node_t node, const void *elt) +{ + size_t count = list->count; + uintptr_t index = NODE_TO_INDEX (node); + size_t position; + const void **elements; + size_t i; + + if (!(index < count)) + /* Invalid argument. */ + abort (); + position = index + 1; + if (count == list->allocated) + if (grow (list) < 0) + return NULL; + elements = list->elements; + for (i = count; i > position; i--) + elements[i] = elements[i - 1]; + elements[position] = elt; + list->count = count + 1; + return INDEX_TO_NODE (position); +} + +static gl_list_node_t +gl_array_nx_add_at (gl_list_t list, size_t position, const void *elt) +{ + size_t count = list->count; + const void **elements; + size_t i; + + if (!(position <= count)) + /* Invalid argument. */ + abort (); + if (count == list->allocated) + if (grow (list) < 0) + return NULL; + elements = list->elements; + for (i = count; i > position; i--) + elements[i] = elements[i - 1]; + elements[position] = elt; + list->count = count + 1; + return INDEX_TO_NODE (position); +} + +static bool +gl_array_remove_node (gl_list_t list, gl_list_node_t node) +{ + size_t count = list->count; + uintptr_t index = NODE_TO_INDEX (node); + size_t position; + const void **elements; + size_t i; + + if (!(index < count)) + /* Invalid argument. */ + abort (); + position = index; + elements = list->elements; + if (list->base.dispose_fn != NULL) + list->base.dispose_fn (elements[position]); + for (i = position + 1; i < count; i++) + elements[i - 1] = elements[i]; + list->count = count - 1; + return true; +} + +static bool +gl_array_remove_at (gl_list_t list, size_t position) +{ + size_t count = list->count; + const void **elements; + size_t i; + + if (!(position < count)) + /* Invalid argument. */ + abort (); + elements = list->elements; + if (list->base.dispose_fn != NULL) + list->base.dispose_fn (elements[position]); + for (i = position + 1; i < count; i++) + elements[i - 1] = elements[i]; + list->count = count - 1; + return true; +} + +static bool +gl_array_remove (gl_list_t list, const void *elt) +{ + size_t position = gl_array_indexof_from_to (list, 0, list->count, elt); + if (position == (size_t)(-1)) + return false; + else + return gl_array_remove_at (list, position); +} + +static void +gl_array_list_free (gl_list_t list) +{ + if (list->elements != NULL) + { + if (list->base.dispose_fn != NULL) + { + size_t count = list->count; + + if (count > 0) + { + gl_listelement_dispose_fn dispose = list->base.dispose_fn; + const void **elements = list->elements; + + do + dispose (*elements++); + while (--count > 0); + } + } + free (list->elements); + } + free (list); +} + +/* --------------------- gl_list_iterator_t Data Type --------------------- */ + +static gl_list_iterator_t +gl_array_iterator (gl_list_t list) +{ + gl_list_iterator_t result; + + result.vtable = list->base.vtable; + result.list = list; + result.count = list->count; + result.p = list->elements + 0; + result.q = list->elements + list->count; +#ifdef lint + result.i = 0; + result.j = 0; +#endif + + return result; +} + +static gl_list_iterator_t +gl_array_iterator_from_to (gl_list_t list, size_t start_index, size_t end_index) +{ + gl_list_iterator_t result; + + if (!(start_index <= end_index && end_index <= list->count)) + /* Invalid arguments. */ + abort (); + result.vtable = list->base.vtable; + result.list = list; + result.count = list->count; + result.p = list->elements + start_index; + result.q = list->elements + end_index; +#ifdef lint + result.i = 0; + result.j = 0; +#endif + + return result; +} + +static bool +gl_array_iterator_next (gl_list_iterator_t *iterator, + const void **eltp, gl_list_node_t *nodep) +{ + gl_list_t list = iterator->list; + if (iterator->count != list->count) + { + if (iterator->count != list->count + 1) + /* Concurrent modifications were done on the list. */ + abort (); + /* The last returned element was removed. */ + iterator->count--; + iterator->p = (const void **) iterator->p - 1; + iterator->q = (const void **) iterator->q - 1; + } + if (iterator->p < iterator->q) + { + const void **p = (const void **) iterator->p; + *eltp = *p; + if (nodep != NULL) + *nodep = INDEX_TO_NODE (p - list->elements); + iterator->p = p + 1; + return true; + } + else + return false; +} + +static void +gl_array_iterator_free (gl_list_iterator_t *iterator) +{ +} + +/* ---------------------- Sorted gl_list_t Data Type ---------------------- */ + +static size_t +gl_array_sortedlist_indexof_from_to (gl_list_t list, + gl_listelement_compar_fn compar, + size_t low, size_t high, + const void *elt) +{ + if (!(low <= high && high <= list->count)) + /* Invalid arguments. */ + abort (); + if (low < high) + { + /* At each loop iteration, low < high; for indices < low the values + are smaller than ELT; for indices >= high the values are greater + than ELT. So, if the element occurs in the list, it is at + low <= position < high. */ + do + { + size_t mid = low + (high - low) / 2; /* low <= mid < high */ + int cmp = compar (list->elements[mid], elt); + + if (cmp < 0) + low = mid + 1; + else if (cmp > 0) + high = mid; + else /* cmp == 0 */ + { + /* We have an element equal to ELT at index MID. But we need + the minimal such index. */ + high = mid; + /* At each loop iteration, low <= high and + compar (list->elements[high], elt) == 0, + and we know that the first occurrence of the element is at + low <= position <= high. */ + while (low < high) + { + size_t mid2 = low + (high - low) / 2; /* low <= mid2 < high */ + int cmp2 = compar (list->elements[mid2], elt); + + if (cmp2 < 0) + low = mid2 + 1; + else if (cmp2 > 0) + /* The list was not sorted. */ + abort (); + else /* cmp2 == 0 */ + { + if (mid2 == low) + break; + high = mid2 - 1; + } + } + return low; + } + } + while (low < high); + /* Here low == high. */ + } + return (size_t)(-1); +} + +static size_t +gl_array_sortedlist_indexof (gl_list_t list, gl_listelement_compar_fn compar, + const void *elt) +{ + return gl_array_sortedlist_indexof_from_to (list, compar, 0, list->count, + elt); +} + +static gl_list_node_t +gl_array_sortedlist_search_from_to (gl_list_t list, + gl_listelement_compar_fn compar, + size_t low, size_t high, + const void *elt) +{ + size_t index = + gl_array_sortedlist_indexof_from_to (list, compar, low, high, elt); + return INDEX_TO_NODE (index); +} + +static gl_list_node_t +gl_array_sortedlist_search (gl_list_t list, gl_listelement_compar_fn compar, + const void *elt) +{ + size_t index = + gl_array_sortedlist_indexof_from_to (list, compar, 0, list->count, elt); + return INDEX_TO_NODE (index); +} + +static gl_list_node_t +gl_array_sortedlist_nx_add (gl_list_t list, gl_listelement_compar_fn compar, + const void *elt) +{ + size_t count = list->count; + size_t low = 0; + size_t high = count; + + /* At each loop iteration, low <= high; for indices < low the values are + smaller than ELT; for indices >= high the values are greater than ELT. */ + while (low < high) + { + size_t mid = low + (high - low) / 2; /* low <= mid < high */ + int cmp = compar (list->elements[mid], elt); + + if (cmp < 0) + low = mid + 1; + else if (cmp > 0) + high = mid; + else /* cmp == 0 */ + { + low = mid; + break; + } + } + return gl_array_nx_add_at (list, low, elt); +} + +static bool +gl_array_sortedlist_remove (gl_list_t list, gl_listelement_compar_fn compar, + const void *elt) +{ + size_t index = gl_array_sortedlist_indexof (list, compar, elt); + if (index == (size_t)(-1)) + return false; + else + return gl_array_remove_at (list, index); +} + + +const struct gl_list_implementation gl_array_list_implementation = + { + gl_array_nx_create_empty, + gl_array_nx_create, + gl_array_size, + gl_array_node_value, + gl_array_node_nx_set_value, + gl_array_next_node, + gl_array_previous_node, + gl_array_get_at, + gl_array_nx_set_at, + gl_array_search_from_to, + gl_array_indexof_from_to, + gl_array_nx_add_first, + gl_array_nx_add_last, + gl_array_nx_add_before, + gl_array_nx_add_after, + gl_array_nx_add_at, + gl_array_remove_node, + gl_array_remove_at, + gl_array_remove, + gl_array_list_free, + gl_array_iterator, + gl_array_iterator_from_to, + gl_array_iterator_next, + gl_array_iterator_free, + gl_array_sortedlist_search, + gl_array_sortedlist_search_from_to, + gl_array_sortedlist_indexof, + gl_array_sortedlist_indexof_from_to, + gl_array_sortedlist_nx_add, + gl_array_sortedlist_remove + }; diff --git a/gettext-tools/gnulib-lib/gl_array_list.h b/gettext-tools/gnulib-lib/gl_array_list.h new file mode 100644 index 0000000..57b1b0e --- /dev/null +++ b/gettext-tools/gnulib-lib/gl_array_list.h @@ -0,0 +1,34 @@ +/* Sequential list data type implemented by an array. + Copyright (C) 2006, 2009-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _GL_ARRAY_LIST_H +#define _GL_ARRAY_LIST_H + +#include "gl_list.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern DLL_VARIABLE const struct gl_list_implementation gl_array_list_implementation; +#define GL_ARRAY_LIST &gl_array_list_implementation + +#ifdef __cplusplus +} +#endif + +#endif /* _GL_ARRAY_LIST_H */ diff --git a/gettext-tools/gnulib-lib/gl_linkedhash_list.c b/gettext-tools/gnulib-lib/gl_linkedhash_list.c new file mode 100644 index 0000000..44e7baa --- /dev/null +++ b/gettext-tools/gnulib-lib/gl_linkedhash_list.c @@ -0,0 +1,124 @@ +/* Sequential list data type implemented by a hash table with a linked list. + Copyright (C) 2006, 2008-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include "gl_linkedhash_list.h" + +#include /* for SIZE_MAX */ +#include + +#include "xsize.h" + +#ifndef uintptr_t +# define uintptr_t unsigned long +#endif + +#define WITH_HASHTABLE 1 + +/* -------------------------- gl_list_t Data Type -------------------------- */ + +/* Generic hash-table code. */ +#include "gl_anyhash_list1.h" + +/* Generic linked list code. */ +#include "gl_anylinked_list1.h" + +/* Generic hash-table code. */ +#include "gl_anyhash_list2.h" + +/* Resize the hash table if needed, after list->count was incremented. */ +static void +hash_resize_after_add (gl_list_t list) +{ + size_t count = list->count; + size_t estimate = xsum (count, count / 2); /* 1.5 * count */ + if (estimate > list->table_size) + hash_resize (list, estimate); +} + +/* Add a node to the hash table structure. */ +static void +add_to_bucket (gl_list_t list, gl_list_node_t node) +{ + size_t bucket = node->h.hashcode % list->table_size; + + node->h.hash_next = list->table[bucket]; + list->table[bucket] = &node->h; +} +/* Tell all compilers that the return value is 0. */ +#define add_to_bucket(list,node) ((add_to_bucket) (list, node), 0) + +/* Remove a node from the hash table structure. */ +static void +remove_from_bucket (gl_list_t list, gl_list_node_t node) +{ + size_t bucket = node->h.hashcode % list->table_size; + gl_hash_entry_t *p; + + for (p = &list->table[bucket]; ; p = &(*p)->hash_next) + { + if (*p == &node->h) + { + *p = node->h.hash_next; + break; + } + if (*p == NULL) + /* node is not in the right bucket. Did the hash codes + change inadvertently? */ + abort (); + } +} + +/* Generic linked list code. */ +#include "gl_anylinked_list2.h" + + +const struct gl_list_implementation gl_linkedhash_list_implementation = + { + gl_linked_nx_create_empty, + gl_linked_nx_create, + gl_linked_size, + gl_linked_node_value, + gl_linked_node_nx_set_value, + gl_linked_next_node, + gl_linked_previous_node, + gl_linked_get_at, + gl_linked_nx_set_at, + gl_linked_search_from_to, + gl_linked_indexof_from_to, + gl_linked_nx_add_first, + gl_linked_nx_add_last, + gl_linked_nx_add_before, + gl_linked_nx_add_after, + gl_linked_nx_add_at, + gl_linked_remove_node, + gl_linked_remove_at, + gl_linked_remove, + gl_linked_list_free, + gl_linked_iterator, + gl_linked_iterator_from_to, + gl_linked_iterator_next, + gl_linked_iterator_free, + gl_linked_sortedlist_search, + gl_linked_sortedlist_search_from_to, + gl_linked_sortedlist_indexof, + gl_linked_sortedlist_indexof_from_to, + gl_linked_sortedlist_nx_add, + gl_linked_sortedlist_remove + }; diff --git a/gettext-tools/gnulib-lib/gl_linkedhash_list.h b/gettext-tools/gnulib-lib/gl_linkedhash_list.h new file mode 100644 index 0000000..c6a6c47 --- /dev/null +++ b/gettext-tools/gnulib-lib/gl_linkedhash_list.h @@ -0,0 +1,34 @@ +/* Sequential list data type implemented by a hash table with a linked list. + Copyright (C) 2006, 2009-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _GL_LINKEDHASH_LIST_H +#define _GL_LINKEDHASH_LIST_H + +#include "gl_list.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern DLL_VARIABLE const struct gl_list_implementation gl_linkedhash_list_implementation; +#define GL_LINKEDHASH_LIST &gl_linkedhash_list_implementation + +#ifdef __cplusplus +} +#endif + +#endif /* _GL_LINKEDHASH_LIST_H */ diff --git a/gettext-tools/gnulib-lib/gl_list.c b/gettext-tools/gnulib-lib/gl_list.c new file mode 100644 index 0000000..8793298 --- /dev/null +++ b/gettext-tools/gnulib-lib/gl_list.c @@ -0,0 +1,3 @@ +#include +#define GL_LIST_INLINE _GL_EXTERN_INLINE +#include "gl_list.h" diff --git a/gettext-tools/gnulib-lib/gl_list.h b/gettext-tools/gnulib-lib/gl_list.h new file mode 100644 index 0000000..ad6d12f --- /dev/null +++ b/gettext-tools/gnulib-lib/gl_list.h @@ -0,0 +1,841 @@ +/* Abstract sequential list data type. + Copyright (C) 2006-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _GL_LIST_H +#define _GL_LIST_H + +#include +#include + +#ifndef _GL_INLINE_HEADER_BEGIN + #error "Please include config.h first." +#endif +_GL_INLINE_HEADER_BEGIN +#ifndef GL_LIST_INLINE +# define GL_LIST_INLINE _GL_INLINE +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + +/* gl_list is an abstract list data type. It can contain any number of + objects ('void *' or 'const void *' pointers) in any given order. + Duplicates are allowed, but can optionally be forbidden. + + There are several implementations of this list datatype, optimized for + different operations or for memory. You can start using the simplest list + implementation, GL_ARRAY_LIST, and switch to a different implementation + later, when you realize which operations are performed the most frequently. + The API of the different implementations is exactly the same; when + switching to a different implementation, you only have to change the + gl_list_create call. + + The implementations are: + GL_ARRAY_LIST a growable array + GL_CARRAY_LIST a growable circular array + GL_LINKED_LIST a linked list + GL_AVLTREE_LIST a binary tree (AVL tree) + GL_RBTREE_LIST a binary tree (red-black tree) + GL_LINKEDHASH_LIST a hash table with a linked list + GL_AVLTREEHASH_LIST a hash table with a binary tree (AVL tree) + GL_RBTREEHASH_LIST a hash table with a binary tree (red-black tree) + + The memory consumption is asymptotically the same: O(1) for every object + in the list. When looking more closely at the average memory consumed + for an object, GL_ARRAY_LIST is the most compact representation, and + GL_LINKEDHASH_LIST and GL_TREEHASH_LIST need more memory. + + The guaranteed average performance of the operations is, for a list of + n elements: + + Operation ARRAY LINKED TREE LINKEDHASH TREEHASH + CARRAY with|without with|without + duplicates duplicates + + gl_list_size O(1) O(1) O(1) O(1) O(1) + gl_list_node_value O(1) O(1) O(1) O(1) O(1) + gl_list_node_set_value O(1) O(1) O(1) O(1) O((log n)²)/O(1) + gl_list_next_node O(1) O(1) O(log n) O(1) O(log n) + gl_list_previous_node O(1) O(1) O(log n) O(1) O(log n) + gl_list_get_at O(1) O(n) O(log n) O(n) O(log n) + gl_list_set_at O(1) O(n) O(log n) O(n) O((log n)²)/O(log n) + gl_list_search O(n) O(n) O(n) O(n)/O(1) O(log n)/O(1) + gl_list_search_from O(n) O(n) O(n) O(n)/O(1) O((log n)²)/O(log n) + gl_list_search_from_to O(n) O(n) O(n) O(n)/O(1) O((log n)²)/O(log n) + gl_list_indexof O(n) O(n) O(n) O(n) O(log n) + gl_list_indexof_from O(n) O(n) O(n) O(n) O((log n)²)/O(log n) + gl_list_indexof_from_to O(n) O(n) O(n) O(n) O((log n)²)/O(log n) + gl_list_add_first O(n)/O(1) O(1) O(log n) O(1) O((log n)²)/O(log n) + gl_list_add_last O(1) O(1) O(log n) O(1) O((log n)²)/O(log n) + gl_list_add_before O(n) O(1) O(log n) O(1) O((log n)²)/O(log n) + gl_list_add_after O(n) O(1) O(log n) O(1) O((log n)²)/O(log n) + gl_list_add_at O(n) O(n) O(log n) O(n) O((log n)²)/O(log n) + gl_list_remove_node O(n) O(1) O(log n) O(n)/O(1) O((log n)²)/O(log n) + gl_list_remove_at O(n) O(n) O(log n) O(n) O((log n)²)/O(log n) + gl_list_remove O(n) O(n) O(n) O(n)/O(1) O((log n)²)/O(log n) + gl_list_iterator O(1) O(1) O(log n) O(1) O(log n) + gl_list_iterator_from_to O(1) O(n) O(log n) O(n) O(log n) + gl_list_iterator_next O(1) O(1) O(log n) O(1) O(log n) + gl_sortedlist_search O(log n) O(n) O(log n) O(n) O(log n) + gl_sortedlist_search_from O(log n) O(n) O(log n) O(n) O(log n) + gl_sortedlist_indexof O(log n) O(n) O(log n) O(n) O(log n) + gl_sortedlist_indexof_fro O(log n) O(n) O(log n) O(n) O(log n) + gl_sortedlist_add O(n) O(n) O(log n) O(n) O((log n)²)/O(log n) + gl_sortedlist_remove O(n) O(n) O(log n) O(n) O((log n)²)/O(log n) + */ + +/* -------------------------- gl_list_t Data Type -------------------------- */ + +/* Type of function used to compare two elements. + NULL denotes pointer comparison. */ +typedef bool (*gl_listelement_equals_fn) (const void *elt1, const void *elt2); + +/* Type of function used to compute a hash code. + NULL denotes a function that depends only on the pointer itself. */ +typedef size_t (*gl_listelement_hashcode_fn) (const void *elt); + +/* Type of function used to dispose an element once it's removed from a list. + NULL denotes a no-op. */ +typedef void (*gl_listelement_dispose_fn) (const void *elt); + +struct gl_list_impl; +/* Type representing an entire list. */ +typedef struct gl_list_impl * gl_list_t; + +struct gl_list_node_impl; +/* Type representing the position of an element in the list, in a way that + is more adapted to the list implementation than a plain index. + Note: It is invalidated by insertions and removals! */ +typedef struct gl_list_node_impl * gl_list_node_t; + +struct gl_list_implementation; +/* Type representing a list datatype implementation. */ +typedef const struct gl_list_implementation * gl_list_implementation_t; + +#if 0 /* Unless otherwise specified, these are defined inline below. */ + +/* Create an empty list. + IMPLEMENTATION is one of GL_ARRAY_LIST, GL_CARRAY_LIST, GL_LINKED_LIST, + GL_AVLTREE_LIST, GL_RBTREE_LIST, GL_LINKEDHASH_LIST, GL_AVLTREEHASH_LIST, + GL_RBTREEHASH_LIST. + EQUALS_FN is an element comparison function or NULL. + HASHCODE_FN is an element hash code function or NULL. + DISPOSE_FN is an element disposal function or NULL. + ALLOW_DUPLICATES is false if duplicate elements shall not be allowed in + the list. The implementation may verify this at runtime. */ +/* declared in gl_xlist.h */ +extern gl_list_t gl_list_create_empty (gl_list_implementation_t implementation, + gl_listelement_equals_fn equals_fn, + gl_listelement_hashcode_fn hashcode_fn, + gl_listelement_dispose_fn dispose_fn, + bool allow_duplicates); +/* Likewise. Return NULL upon out-of-memory. */ +extern gl_list_t gl_list_nx_create_empty (gl_list_implementation_t implementation, + gl_listelement_equals_fn equals_fn, + gl_listelement_hashcode_fn hashcode_fn, + gl_listelement_dispose_fn dispose_fn, + bool allow_duplicates); + +/* Create a list with given contents. + IMPLEMENTATION is one of GL_ARRAY_LIST, GL_CARRAY_LIST, GL_LINKED_LIST, + GL_AVLTREE_LIST, GL_RBTREE_LIST, GL_LINKEDHASH_LIST, GL_AVLTREEHASH_LIST, + GL_RBTREEHASH_LIST. + EQUALS_FN is an element comparison function or NULL. + HASHCODE_FN is an element hash code function or NULL. + DISPOSE_FN is an element disposal function or NULL. + ALLOW_DUPLICATES is false if duplicate elements shall not be allowed in + the list. The implementation may verify this at runtime. + COUNT is the number of initial elements. + CONTENTS[0..COUNT-1] is the initial contents. */ +/* declared in gl_xlist.h */ +extern gl_list_t gl_list_create (gl_list_implementation_t implementation, + gl_listelement_equals_fn equals_fn, + gl_listelement_hashcode_fn hashcode_fn, + gl_listelement_dispose_fn dispose_fn, + bool allow_duplicates, + size_t count, const void **contents); +/* Likewise. Return NULL upon out-of-memory. */ +extern gl_list_t gl_list_nx_create (gl_list_implementation_t implementation, + gl_listelement_equals_fn equals_fn, + gl_listelement_hashcode_fn hashcode_fn, + gl_listelement_dispose_fn dispose_fn, + bool allow_duplicates, + size_t count, const void **contents); + +/* Return the current number of elements in a list. */ +extern size_t gl_list_size (gl_list_t list); + +/* Return the element value represented by a list node. */ +extern const void * gl_list_node_value (gl_list_t list, gl_list_node_t node); + +/* Replace the element value represented by a list node. */ +/* declared in gl_xlist.h */ +extern void gl_list_node_set_value (gl_list_t list, gl_list_node_t node, + const void *elt); +/* Likewise. Return 0 upon success, -1 upon out-of-memory. */ +extern int gl_list_node_nx_set_value (gl_list_t list, gl_list_node_t node, + const void *elt) +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) + __attribute__ ((__warn_unused_result__)) +#endif + ; + +/* Return the node immediately after the given node in the list, or NULL + if the given node is the last (rightmost) one in the list. */ +extern gl_list_node_t gl_list_next_node (gl_list_t list, gl_list_node_t node); + +/* Return the node immediately before the given node in the list, or NULL + if the given node is the first (leftmost) one in the list. */ +extern gl_list_node_t gl_list_previous_node (gl_list_t list, gl_list_node_t node); + +/* Return the element at a given position in the list. + POSITION must be >= 0 and < gl_list_size (list). */ +extern const void * gl_list_get_at (gl_list_t list, size_t position); + +/* Replace the element at a given position in the list. + POSITION must be >= 0 and < gl_list_size (list). + Return its node. */ +/* declared in gl_xlist.h */ +extern gl_list_node_t gl_list_set_at (gl_list_t list, size_t position, + const void *elt); +/* Likewise. Return NULL upon out-of-memory. */ +extern gl_list_node_t gl_list_nx_set_at (gl_list_t list, size_t position, + const void *elt) +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) + __attribute__ ((__warn_unused_result__)) +#endif + ; + +/* Search whether an element is already in the list. + Return its node if found, or NULL if not present in the list. */ +extern gl_list_node_t gl_list_search (gl_list_t list, const void *elt); + +/* Search whether an element is already in the list, + at a position >= START_INDEX. + Return its node if found, or NULL if not present in the list. */ +extern gl_list_node_t gl_list_search_from (gl_list_t list, size_t start_index, + const void *elt); + +/* Search whether an element is already in the list, + at a position >= START_INDEX and < END_INDEX. + Return its node if found, or NULL if not present in the list. */ +extern gl_list_node_t gl_list_search_from_to (gl_list_t list, + size_t start_index, + size_t end_index, + const void *elt); + +/* Search whether an element is already in the list. + Return its position if found, or (size_t)(-1) if not present in the list. */ +extern size_t gl_list_indexof (gl_list_t list, const void *elt); + +/* Search whether an element is already in the list, + at a position >= START_INDEX. + Return its position if found, or (size_t)(-1) if not present in the list. */ +extern size_t gl_list_indexof_from (gl_list_t list, size_t start_index, + const void *elt); + +/* Search whether an element is already in the list, + at a position >= START_INDEX and < END_INDEX. + Return its position if found, or (size_t)(-1) if not present in the list. */ +extern size_t gl_list_indexof_from_to (gl_list_t list, + size_t start_index, size_t end_index, + const void *elt); + +/* Add an element as the first element of the list. + Return its node. */ +/* declared in gl_xlist.h */ +extern gl_list_node_t gl_list_add_first (gl_list_t list, const void *elt); +/* Likewise. Return NULL upon out-of-memory. */ +extern gl_list_node_t gl_list_nx_add_first (gl_list_t list, const void *elt) +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) + __attribute__ ((__warn_unused_result__)) +#endif + ; + +/* Add an element as the last element of the list. + Return its node. */ +/* declared in gl_xlist.h */ +extern gl_list_node_t gl_list_add_last (gl_list_t list, const void *elt); +/* Likewise. Return NULL upon out-of-memory. */ +extern gl_list_node_t gl_list_nx_add_last (gl_list_t list, const void *elt) +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) + __attribute__ ((__warn_unused_result__)) +#endif + ; + +/* Add an element before a given element node of the list. + Return its node. */ +/* declared in gl_xlist.h */ +extern gl_list_node_t gl_list_add_before (gl_list_t list, gl_list_node_t node, + const void *elt); +/* Likewise. Return NULL upon out-of-memory. */ +extern gl_list_node_t gl_list_nx_add_before (gl_list_t list, + gl_list_node_t node, + const void *elt) +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) + __attribute__ ((__warn_unused_result__)) +#endif + ; + +/* Add an element after a given element node of the list. + Return its node. */ +/* declared in gl_xlist.h */ +extern gl_list_node_t gl_list_add_after (gl_list_t list, gl_list_node_t node, + const void *elt); +/* Likewise. Return NULL upon out-of-memory. */ +extern gl_list_node_t gl_list_nx_add_after (gl_list_t list, gl_list_node_t node, + const void *elt) +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) + __attribute__ ((__warn_unused_result__)) +#endif + ; + +/* Add an element at a given position in the list. + POSITION must be >= 0 and <= gl_list_size (list). */ +/* declared in gl_xlist.h */ +extern gl_list_node_t gl_list_add_at (gl_list_t list, size_t position, + const void *elt); +/* Likewise. Return NULL upon out-of-memory. */ +extern gl_list_node_t gl_list_nx_add_at (gl_list_t list, size_t position, + const void *elt) +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) + __attribute__ ((__warn_unused_result__)) +#endif + ; + +/* Remove an element from the list. + Return true. */ +extern bool gl_list_remove_node (gl_list_t list, gl_list_node_t node); + +/* Remove an element at a given position from the list. + POSITION must be >= 0 and < gl_list_size (list). + Return true. */ +extern bool gl_list_remove_at (gl_list_t list, size_t position); + +/* Search and remove an element from the list. + Return true if it was found and removed. */ +extern bool gl_list_remove (gl_list_t list, const void *elt); + +/* Free an entire list. + (But this call does not free the elements of the list.) */ +extern void gl_list_free (gl_list_t list); + +#endif /* End of inline and gl_xlist.h-defined functions. */ + +/* --------------------- gl_list_iterator_t Data Type --------------------- */ + +/* Functions for iterating through a list. */ + +/* Type of an iterator that traverses a list. + This is a fixed-size struct, so that creation of an iterator doesn't need + memory allocation on the heap. */ +typedef struct +{ + /* For fast dispatch of gl_list_iterator_next. */ + const struct gl_list_implementation *vtable; + /* For detecting whether the last returned element was removed. */ + gl_list_t list; + size_t count; + /* Other, implementation-private fields. */ + void *p; void *q; + size_t i; size_t j; +} gl_list_iterator_t; + +#if 0 /* These are defined inline below. */ + +/* Create an iterator traversing a list. + The list contents must not be modified while the iterator is in use, + except for replacing or removing the last returned element. */ +extern gl_list_iterator_t gl_list_iterator (gl_list_t list); + +/* Create an iterator traversing the element with indices i, + start_index <= i < end_index, of a list. + The list contents must not be modified while the iterator is in use, + except for replacing or removing the last returned element. */ +extern gl_list_iterator_t gl_list_iterator_from_to (gl_list_t list, + size_t start_index, + size_t end_index); + +/* If there is a next element, store the next element in *ELTP, store its + node in *NODEP if NODEP is non-NULL, advance the iterator and return true. + Otherwise, return false. */ +extern bool gl_list_iterator_next (gl_list_iterator_t *iterator, + const void **eltp, gl_list_node_t *nodep); + +/* Free an iterator. */ +extern void gl_list_iterator_free (gl_list_iterator_t *iterator); + +#endif /* End of inline functions. */ + +/* ---------------------- Sorted gl_list_t Data Type ---------------------- */ + +/* The following functions are for lists without duplicates where the + order is given by a sort criterion. */ + +/* Type of function used to compare two elements. Same as for qsort(). + NULL denotes pointer comparison. */ +typedef int (*gl_listelement_compar_fn) (const void *elt1, const void *elt2); + +#if 0 /* Unless otherwise specified, these are defined inline below. */ + +/* Search whether an element is already in the list. + The list is assumed to be sorted with COMPAR. + Return its node if found, or NULL if not present in the list. + If the list contains several copies of ELT, the node of the leftmost one is + returned. */ +extern gl_list_node_t gl_sortedlist_search (gl_list_t list, + gl_listelement_compar_fn compar, + const void *elt); + +/* Search whether an element is already in the list. + The list is assumed to be sorted with COMPAR. + Only list elements with indices >= START_INDEX and < END_INDEX are + considered; the implementation uses these bounds to minimize the number + of COMPAR invocations. + Return its node if found, or NULL if not present in the list. + If the list contains several copies of ELT, the node of the leftmost one is + returned. */ +extern gl_list_node_t gl_sortedlist_search_from_to (gl_list_t list, + gl_listelement_compar_fn compar, + size_t start_index, + size_t end_index, + const void *elt); + +/* Search whether an element is already in the list. + The list is assumed to be sorted with COMPAR. + Return its position if found, or (size_t)(-1) if not present in the list. + If the list contains several copies of ELT, the position of the leftmost one + is returned. */ +extern size_t gl_sortedlist_indexof (gl_list_t list, + gl_listelement_compar_fn compar, + const void *elt); + +/* Search whether an element is already in the list. + The list is assumed to be sorted with COMPAR. + Only list elements with indices >= START_INDEX and < END_INDEX are + considered; the implementation uses these bounds to minimize the number + of COMPAR invocations. + Return its position if found, or (size_t)(-1) if not present in the list. + If the list contains several copies of ELT, the position of the leftmost one + is returned. */ +extern size_t gl_sortedlist_indexof_from_to (gl_list_t list, + gl_listelement_compar_fn compar, + size_t start_index, + size_t end_index, + const void *elt); + +/* Add an element at the appropriate position in the list. + The list is assumed to be sorted with COMPAR. + Return its node. */ +/* declared in gl_xlist.h */ +extern gl_list_node_t gl_sortedlist_add (gl_list_t list, + gl_listelement_compar_fn compar, + const void *elt); +/* Likewise. Return NULL upon out-of-memory. */ +extern gl_list_node_t gl_sortedlist_nx_add (gl_list_t list, + gl_listelement_compar_fn compar, + const void *elt) +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) + __attribute__ ((__warn_unused_result__)) +#endif + ; + +/* Search and remove an element from the list. + The list is assumed to be sorted with COMPAR. + Return true if it was found and removed. + If the list contains several copies of ELT, only the leftmost one is + removed. */ +extern bool gl_sortedlist_remove (gl_list_t list, + gl_listelement_compar_fn compar, + const void *elt); + +#endif /* End of inline and gl_xlist.h-defined functions. */ + +/* ------------------------ Implementation Details ------------------------ */ + +struct gl_list_implementation +{ + /* gl_list_t functions. */ + gl_list_t (*nx_create_empty) (gl_list_implementation_t implementation, + gl_listelement_equals_fn equals_fn, + gl_listelement_hashcode_fn hashcode_fn, + gl_listelement_dispose_fn dispose_fn, + bool allow_duplicates); + gl_list_t (*nx_create) (gl_list_implementation_t implementation, + gl_listelement_equals_fn equals_fn, + gl_listelement_hashcode_fn hashcode_fn, + gl_listelement_dispose_fn dispose_fn, + bool allow_duplicates, + size_t count, const void **contents); + size_t (*size) (gl_list_t list); + const void * (*node_value) (gl_list_t list, gl_list_node_t node); + int (*node_nx_set_value) (gl_list_t list, gl_list_node_t node, + const void *elt); + gl_list_node_t (*next_node) (gl_list_t list, gl_list_node_t node); + gl_list_node_t (*previous_node) (gl_list_t list, gl_list_node_t node); + const void * (*get_at) (gl_list_t list, size_t position); + gl_list_node_t (*nx_set_at) (gl_list_t list, size_t position, + const void *elt); + gl_list_node_t (*search_from_to) (gl_list_t list, size_t start_index, + size_t end_index, const void *elt); + size_t (*indexof_from_to) (gl_list_t list, size_t start_index, + size_t end_index, const void *elt); + gl_list_node_t (*nx_add_first) (gl_list_t list, const void *elt); + gl_list_node_t (*nx_add_last) (gl_list_t list, const void *elt); + gl_list_node_t (*nx_add_before) (gl_list_t list, gl_list_node_t node, + const void *elt); + gl_list_node_t (*nx_add_after) (gl_list_t list, gl_list_node_t node, + const void *elt); + gl_list_node_t (*nx_add_at) (gl_list_t list, size_t position, + const void *elt); + bool (*remove_node) (gl_list_t list, gl_list_node_t node); + bool (*remove_at) (gl_list_t list, size_t position); + bool (*remove_elt) (gl_list_t list, const void *elt); + void (*list_free) (gl_list_t list); + /* gl_list_iterator_t functions. */ + gl_list_iterator_t (*iterator) (gl_list_t list); + gl_list_iterator_t (*iterator_from_to) (gl_list_t list, + size_t start_index, + size_t end_index); + bool (*iterator_next) (gl_list_iterator_t *iterator, + const void **eltp, gl_list_node_t *nodep); + void (*iterator_free) (gl_list_iterator_t *iterator); + /* Sorted gl_list_t functions. */ + gl_list_node_t (*sortedlist_search) (gl_list_t list, + gl_listelement_compar_fn compar, + const void *elt); + gl_list_node_t (*sortedlist_search_from_to) (gl_list_t list, + gl_listelement_compar_fn compar, + size_t start_index, + size_t end_index, + const void *elt); + size_t (*sortedlist_indexof) (gl_list_t list, + gl_listelement_compar_fn compar, + const void *elt); + size_t (*sortedlist_indexof_from_to) (gl_list_t list, + gl_listelement_compar_fn compar, + size_t start_index, size_t end_index, + const void *elt); + gl_list_node_t (*sortedlist_nx_add) (gl_list_t list, + gl_listelement_compar_fn compar, + const void *elt); + bool (*sortedlist_remove) (gl_list_t list, + gl_listelement_compar_fn compar, + const void *elt); +}; + +struct gl_list_impl_base +{ + const struct gl_list_implementation *vtable; + gl_listelement_equals_fn equals_fn; + gl_listelement_hashcode_fn hashcode_fn; + gl_listelement_dispose_fn dispose_fn; + bool allow_duplicates; +}; + +/* Define all functions of this file as accesses to the + struct gl_list_implementation. */ + +GL_LIST_INLINE gl_list_t +gl_list_nx_create_empty (gl_list_implementation_t implementation, + gl_listelement_equals_fn equals_fn, + gl_listelement_hashcode_fn hashcode_fn, + gl_listelement_dispose_fn dispose_fn, + bool allow_duplicates) +{ + return implementation->nx_create_empty (implementation, equals_fn, + hashcode_fn, dispose_fn, + allow_duplicates); +} + +GL_LIST_INLINE gl_list_t +gl_list_nx_create (gl_list_implementation_t implementation, + gl_listelement_equals_fn equals_fn, + gl_listelement_hashcode_fn hashcode_fn, + gl_listelement_dispose_fn dispose_fn, + bool allow_duplicates, + size_t count, const void **contents) +{ + return implementation->nx_create (implementation, equals_fn, hashcode_fn, + dispose_fn, allow_duplicates, count, + contents); +} + +GL_LIST_INLINE size_t +gl_list_size (gl_list_t list) +{ + return ((const struct gl_list_impl_base *) list)->vtable + ->size (list); +} + +GL_LIST_INLINE const void * +gl_list_node_value (gl_list_t list, gl_list_node_t node) +{ + return ((const struct gl_list_impl_base *) list)->vtable + ->node_value (list, node); +} + +GL_LIST_INLINE int +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) + __attribute__ ((__warn_unused_result__)) +#endif +gl_list_node_nx_set_value (gl_list_t list, gl_list_node_t node, + const void *elt) +{ + return ((const struct gl_list_impl_base *) list)->vtable + ->node_nx_set_value (list, node, elt); +} + +GL_LIST_INLINE gl_list_node_t +gl_list_next_node (gl_list_t list, gl_list_node_t node) +{ + return ((const struct gl_list_impl_base *) list)->vtable + ->next_node (list, node); +} + +GL_LIST_INLINE gl_list_node_t +gl_list_previous_node (gl_list_t list, gl_list_node_t node) +{ + return ((const struct gl_list_impl_base *) list)->vtable + ->previous_node (list, node); +} + +GL_LIST_INLINE const void * +gl_list_get_at (gl_list_t list, size_t position) +{ + return ((const struct gl_list_impl_base *) list)->vtable + ->get_at (list, position); +} + +GL_LIST_INLINE gl_list_node_t +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) + __attribute__ ((__warn_unused_result__)) +#endif +gl_list_nx_set_at (gl_list_t list, size_t position, const void *elt) +{ + return ((const struct gl_list_impl_base *) list)->vtable + ->nx_set_at (list, position, elt); +} + +GL_LIST_INLINE gl_list_node_t +gl_list_search (gl_list_t list, const void *elt) +{ + size_t size = ((const struct gl_list_impl_base *) list)->vtable->size (list); + return ((const struct gl_list_impl_base *) list)->vtable + ->search_from_to (list, 0, size, elt); +} + +GL_LIST_INLINE gl_list_node_t +gl_list_search_from (gl_list_t list, size_t start_index, const void *elt) +{ + size_t size = ((const struct gl_list_impl_base *) list)->vtable->size (list); + return ((const struct gl_list_impl_base *) list)->vtable + ->search_from_to (list, start_index, size, elt); +} + +GL_LIST_INLINE gl_list_node_t +gl_list_search_from_to (gl_list_t list, size_t start_index, size_t end_index, + const void *elt) +{ + return ((const struct gl_list_impl_base *) list)->vtable + ->search_from_to (list, start_index, end_index, elt); +} + +GL_LIST_INLINE size_t +gl_list_indexof (gl_list_t list, const void *elt) +{ + size_t size = ((const struct gl_list_impl_base *) list)->vtable->size (list); + return ((const struct gl_list_impl_base *) list)->vtable + ->indexof_from_to (list, 0, size, elt); +} + +GL_LIST_INLINE size_t +gl_list_indexof_from (gl_list_t list, size_t start_index, const void *elt) +{ + size_t size = ((const struct gl_list_impl_base *) list)->vtable->size (list); + return ((const struct gl_list_impl_base *) list)->vtable + ->indexof_from_to (list, start_index, size, elt); +} + +GL_LIST_INLINE size_t +gl_list_indexof_from_to (gl_list_t list, size_t start_index, size_t end_index, + const void *elt) +{ + return ((const struct gl_list_impl_base *) list)->vtable + ->indexof_from_to (list, start_index, end_index, elt); +} + +GL_LIST_INLINE gl_list_node_t +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) + __attribute__ ((__warn_unused_result__)) +#endif +gl_list_nx_add_first (gl_list_t list, const void *elt) +{ + return ((const struct gl_list_impl_base *) list)->vtable + ->nx_add_first (list, elt); +} + +GL_LIST_INLINE gl_list_node_t +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) + __attribute__ ((__warn_unused_result__)) +#endif +gl_list_nx_add_last (gl_list_t list, const void *elt) +{ + return ((const struct gl_list_impl_base *) list)->vtable + ->nx_add_last (list, elt); +} + +GL_LIST_INLINE gl_list_node_t +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) + __attribute__ ((__warn_unused_result__)) +#endif +gl_list_nx_add_before (gl_list_t list, gl_list_node_t node, const void *elt) +{ + return ((const struct gl_list_impl_base *) list)->vtable + ->nx_add_before (list, node, elt); +} + +GL_LIST_INLINE gl_list_node_t +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) + __attribute__ ((__warn_unused_result__)) +#endif +gl_list_nx_add_after (gl_list_t list, gl_list_node_t node, const void *elt) +{ + return ((const struct gl_list_impl_base *) list)->vtable + ->nx_add_after (list, node, elt); +} + +GL_LIST_INLINE gl_list_node_t +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) + __attribute__ ((__warn_unused_result__)) +#endif +gl_list_nx_add_at (gl_list_t list, size_t position, const void *elt) +{ + return ((const struct gl_list_impl_base *) list)->vtable + ->nx_add_at (list, position, elt); +} + +GL_LIST_INLINE bool +gl_list_remove_node (gl_list_t list, gl_list_node_t node) +{ + return ((const struct gl_list_impl_base *) list)->vtable + ->remove_node (list, node); +} + +GL_LIST_INLINE bool +gl_list_remove_at (gl_list_t list, size_t position) +{ + return ((const struct gl_list_impl_base *) list)->vtable + ->remove_at (list, position); +} + +GL_LIST_INLINE bool +gl_list_remove (gl_list_t list, const void *elt) +{ + return ((const struct gl_list_impl_base *) list)->vtable + ->remove_elt (list, elt); +} + +GL_LIST_INLINE void +gl_list_free (gl_list_t list) +{ + ((const struct gl_list_impl_base *) list)->vtable->list_free (list); +} + +GL_LIST_INLINE gl_list_iterator_t +gl_list_iterator (gl_list_t list) +{ + return ((const struct gl_list_impl_base *) list)->vtable + ->iterator (list); +} + +GL_LIST_INLINE gl_list_iterator_t +gl_list_iterator_from_to (gl_list_t list, size_t start_index, size_t end_index) +{ + return ((const struct gl_list_impl_base *) list)->vtable + ->iterator_from_to (list, start_index, end_index); +} + +GL_LIST_INLINE bool +gl_list_iterator_next (gl_list_iterator_t *iterator, + const void **eltp, gl_list_node_t *nodep) +{ + return iterator->vtable->iterator_next (iterator, eltp, nodep); +} + +GL_LIST_INLINE void +gl_list_iterator_free (gl_list_iterator_t *iterator) +{ + iterator->vtable->iterator_free (iterator); +} + +GL_LIST_INLINE gl_list_node_t +gl_sortedlist_search (gl_list_t list, gl_listelement_compar_fn compar, const void *elt) +{ + return ((const struct gl_list_impl_base *) list)->vtable + ->sortedlist_search (list, compar, elt); +} + +GL_LIST_INLINE gl_list_node_t +gl_sortedlist_search_from_to (gl_list_t list, gl_listelement_compar_fn compar, size_t start_index, size_t end_index, const void *elt) +{ + return ((const struct gl_list_impl_base *) list)->vtable + ->sortedlist_search_from_to (list, compar, start_index, end_index, + elt); +} + +GL_LIST_INLINE size_t +gl_sortedlist_indexof (gl_list_t list, gl_listelement_compar_fn compar, const void *elt) +{ + return ((const struct gl_list_impl_base *) list)->vtable + ->sortedlist_indexof (list, compar, elt); +} + +GL_LIST_INLINE size_t +gl_sortedlist_indexof_from_to (gl_list_t list, gl_listelement_compar_fn compar, size_t start_index, size_t end_index, const void *elt) +{ + return ((const struct gl_list_impl_base *) list)->vtable + ->sortedlist_indexof_from_to (list, compar, start_index, end_index, + elt); +} + +GL_LIST_INLINE gl_list_node_t +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) + __attribute__ ((__warn_unused_result__)) +#endif +gl_sortedlist_nx_add (gl_list_t list, gl_listelement_compar_fn compar, const void *elt) +{ + return ((const struct gl_list_impl_base *) list)->vtable + ->sortedlist_nx_add (list, compar, elt); +} + +GL_LIST_INLINE bool +gl_sortedlist_remove (gl_list_t list, gl_listelement_compar_fn compar, const void *elt) +{ + return ((const struct gl_list_impl_base *) list)->vtable + ->sortedlist_remove (list, compar, elt); +} + +#ifdef __cplusplus +} +#endif + +_GL_INLINE_HEADER_END + +#endif /* _GL_LIST_H */ diff --git a/gettext-tools/gnulib-lib/gl_xlist.c b/gettext-tools/gnulib-lib/gl_xlist.c new file mode 100644 index 0000000..fe3c893 --- /dev/null +++ b/gettext-tools/gnulib-lib/gl_xlist.c @@ -0,0 +1,3 @@ +#include +#define GL_XLIST_INLINE _GL_EXTERN_INLINE +#include "gl_xlist.h" diff --git a/gettext-tools/gnulib-lib/gl_xlist.h b/gettext-tools/gnulib-lib/gl_xlist.h new file mode 100644 index 0000000..a4f4e89 --- /dev/null +++ b/gettext-tools/gnulib-lib/gl_xlist.h @@ -0,0 +1,177 @@ +/* Abstract sequential list data type, with out-of-memory checking. + Copyright (C) 2009-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2009. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _GL_XLIST_H +#define _GL_XLIST_H + +#include "gl_list.h" +#include "xalloc.h" + +#ifndef _GL_INLINE_HEADER_BEGIN + #error "Please include config.h first." +#endif +_GL_INLINE_HEADER_BEGIN +#ifndef GL_XLIST_INLINE +# define GL_XLIST_INLINE _GL_INLINE +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* These functions are thin wrappers around the corresponding functions with + _nx_ infix from gl_list.h. Upon out-of-memory, they invoke xalloc_die (), + instead of returning an error indicator. */ +#if 0 /* These are defined inline below. */ +extern gl_list_t gl_list_create_empty (gl_list_implementation_t implementation, + gl_listelement_equals_fn equals_fn, + gl_listelement_hashcode_fn hashcode_fn, + gl_listelement_dispose_fn dispose_fn, + bool allow_duplicates); +extern gl_list_t gl_list_create (gl_list_implementation_t implementation, + gl_listelement_equals_fn equals_fn, + gl_listelement_hashcode_fn hashcode_fn, + gl_listelement_dispose_fn dispose_fn, + bool allow_duplicates, + size_t count, const void **contents); +extern void gl_list_node_set_value (gl_list_t list, gl_list_node_t node, + const void *elt); +extern gl_list_node_t gl_list_set_at (gl_list_t list, size_t position, + const void *elt); +extern gl_list_node_t gl_list_add_first (gl_list_t list, const void *elt); +extern gl_list_node_t gl_list_add_last (gl_list_t list, const void *elt); +extern gl_list_node_t gl_list_add_before (gl_list_t list, gl_list_node_t node, + const void *elt); +extern gl_list_node_t gl_list_add_after (gl_list_t list, gl_list_node_t node, + const void *elt); +extern gl_list_node_t gl_list_add_at (gl_list_t list, size_t position, + const void *elt); +extern gl_list_node_t gl_sortedlist_add (gl_list_t list, + gl_listelement_compar_fn compar, + const void *elt); +#endif + +GL_XLIST_INLINE gl_list_t +gl_list_create_empty (gl_list_implementation_t implementation, + gl_listelement_equals_fn equals_fn, + gl_listelement_hashcode_fn hashcode_fn, + gl_listelement_dispose_fn dispose_fn, + bool allow_duplicates) +{ + gl_list_t result = + gl_list_nx_create_empty (implementation, equals_fn, hashcode_fn, dispose_fn, + allow_duplicates); + if (result == NULL) + xalloc_die (); + return result; +} + +GL_XLIST_INLINE gl_list_t +gl_list_create (gl_list_implementation_t implementation, + gl_listelement_equals_fn equals_fn, + gl_listelement_hashcode_fn hashcode_fn, + gl_listelement_dispose_fn dispose_fn, + bool allow_duplicates, + size_t count, const void **contents) +{ + gl_list_t result = + gl_list_nx_create (implementation, equals_fn, hashcode_fn, dispose_fn, + allow_duplicates, count, contents); + if (result == NULL) + xalloc_die (); + return result; +} + +GL_XLIST_INLINE void +gl_list_node_set_value (gl_list_t list, gl_list_node_t node, const void *elt) +{ + int result = gl_list_node_nx_set_value (list, node, elt); + if (result < 0) + xalloc_die (); +} + +GL_XLIST_INLINE gl_list_node_t +gl_list_set_at (gl_list_t list, size_t position, const void *elt) +{ + gl_list_node_t result = gl_list_nx_set_at (list, position, elt); + if (result == NULL) + xalloc_die (); + return result; +} + +GL_XLIST_INLINE gl_list_node_t +gl_list_add_first (gl_list_t list, const void *elt) +{ + gl_list_node_t result = gl_list_nx_add_first (list, elt); + if (result == NULL) + xalloc_die (); + return result; +} + +GL_XLIST_INLINE gl_list_node_t +gl_list_add_last (gl_list_t list, const void *elt) +{ + gl_list_node_t result = gl_list_nx_add_last (list, elt); + if (result == NULL) + xalloc_die (); + return result; +} + +GL_XLIST_INLINE gl_list_node_t +gl_list_add_before (gl_list_t list, gl_list_node_t node, const void *elt) +{ + gl_list_node_t result = gl_list_nx_add_before (list, node, elt); + if (result == NULL) + xalloc_die (); + return result; +} + +GL_XLIST_INLINE gl_list_node_t +gl_list_add_after (gl_list_t list, gl_list_node_t node, const void *elt) +{ + gl_list_node_t result = gl_list_nx_add_after (list, node, elt); + if (result == NULL) + xalloc_die (); + return result; +} + +GL_XLIST_INLINE gl_list_node_t +gl_list_add_at (gl_list_t list, size_t position, const void *elt) +{ + gl_list_node_t result = gl_list_nx_add_at (list, position, elt); + if (result == NULL) + xalloc_die (); + return result; +} + +GL_XLIST_INLINE gl_list_node_t +gl_sortedlist_add (gl_list_t list, gl_listelement_compar_fn compar, + const void *elt) +{ + gl_list_node_t result = gl_sortedlist_nx_add (list, compar, elt); + if (result == NULL) + xalloc_die (); + return result; +} + +#ifdef __cplusplus +} +#endif + +_GL_INLINE_HEADER_END + +#endif /* _GL_XLIST_H */ diff --git a/gettext-tools/gnulib-lib/glib.in.h b/gettext-tools/gnulib-lib/glib.in.h new file mode 100644 index 0000000..e3b5544 --- /dev/null +++ b/gettext-tools/gnulib-lib/glib.in.h @@ -0,0 +1,98 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +/* + * Modified by Bruno Haible for use as a gnulib module. + */ + +#ifndef __G_LIB_H__ +#define __G_LIB_H__ + +#if 0 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif +#include +#if 0 +#include +#include +#include +#endif +#include +#if 0 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif +#include +#if 0 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif +#include +#include +#if 0 +#include +#include +#include +#include +#endif +#include +#if 0 +#include +#include +#ifdef G_PLATFORM_WIN32 +#include +#endif +#endif + +#endif /* __G_LIB_H__ */ diff --git a/gettext-tools/gnulib-lib/glib/ghash.c b/gettext-tools/gnulib-lib/glib/ghash.c new file mode 100644 index 0000000..1039b77 --- /dev/null +++ b/gettext-tools/gnulib-lib/glib/ghash.c @@ -0,0 +1,816 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +/* + * Modified by Bruno Haible for use as a gnulib module. + */ + +/* + * MT safe + */ + +#include "config.h" + +#include "glib.h" +#if 0 +#include "galias.h" +#endif + +#undef CLAMP +#define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x))) + + +#define HASH_TABLE_MIN_SIZE 11 +#define HASH_TABLE_MAX_SIZE 13845163 + + +typedef struct _GHashNode GHashNode; + +struct _GHashNode +{ + gpointer key; + gpointer value; + GHashNode *next; +}; + +struct _GHashTable +{ + gint size; + gint nnodes; + GHashNode **nodes; + GHashFunc hash_func; + GEqualFunc key_equal_func; + volatile guint ref_count; + GDestroyNotify key_destroy_func; + GDestroyNotify value_destroy_func; +}; + +#define G_HASH_TABLE_RESIZE(hash_table) \ + G_STMT_START { \ + if ((hash_table->size >= 3 * hash_table->nnodes && \ + hash_table->size > HASH_TABLE_MIN_SIZE) || \ + (3 * hash_table->size <= hash_table->nnodes && \ + hash_table->size < HASH_TABLE_MAX_SIZE)) \ + g_hash_table_resize (hash_table); \ + } G_STMT_END + +static void g_hash_table_resize (GHashTable *hash_table); +static GHashNode** g_hash_table_lookup_node (GHashTable *hash_table, + gconstpointer key); +static GHashNode* g_hash_node_new (gpointer key, + gpointer value); +#if 0 +static void g_hash_node_destroy (GHashNode *hash_node, + GDestroyNotify key_destroy_func, + GDestroyNotify value_destroy_func); +static void g_hash_nodes_destroy (GHashNode *hash_node, + GDestroyNotify key_destroy_func, + GDestroyNotify value_destroy_func); +static guint g_hash_table_foreach_remove_or_steal (GHashTable *hash_table, + GHRFunc func, + gpointer user_data, + gboolean notify); +#endif + + +/** + * g_hash_table_new: + * @hash_func: a function to create a hash value from a key. + * Hash values are used to determine where keys are stored within the + * #GHashTable data structure. The g_direct_hash(), g_int_hash() and + * g_str_hash() functions are provided for some common types of keys. + * If hash_func is %NULL, g_direct_hash() is used. + * @key_equal_func: a function to check two keys for equality. This is + * used when looking up keys in the #GHashTable. The g_direct_equal(), + * g_int_equal() and g_str_equal() functions are provided for the most + * common types of keys. If @key_equal_func is %NULL, keys are compared + * directly in a similar fashion to g_direct_equal(), but without the + * overhead of a function call. + * + * Creates a new #GHashTable with a reference count of 1. + * + * Return value: a new #GHashTable. + **/ +GHashTable* +g_hash_table_new (GHashFunc hash_func, + GEqualFunc key_equal_func) +{ + return g_hash_table_new_full (hash_func, key_equal_func, NULL, NULL); +} + + +/** + * g_hash_table_new_full: + * @hash_func: a function to create a hash value from a key. + * @key_equal_func: a function to check two keys for equality. + * @key_destroy_func: a function to free the memory allocated for the key + * used when removing the entry from the #GHashTable or %NULL if you + * don't want to supply such a function. + * @value_destroy_func: a function to free the memory allocated for the + * value used when removing the entry from the #GHashTable or %NULL if + * you don't want to supply such a function. + * + * Creates a new #GHashTable like g_hash_table_new() with a reference count + * of 1 and allows to specify functions to free the memory allocated for the + * key and value that get called when removing the entry from the #GHashTable. + * + * Return value: a new #GHashTable. + **/ +GHashTable* +g_hash_table_new_full (GHashFunc hash_func, + GEqualFunc key_equal_func, + GDestroyNotify key_destroy_func, + GDestroyNotify value_destroy_func) +{ + GHashTable *hash_table; + + hash_table = g_slice_new (GHashTable); + hash_table->size = HASH_TABLE_MIN_SIZE; + hash_table->nnodes = 0; + hash_table->hash_func = hash_func; + hash_table->key_equal_func = key_equal_func; + hash_table->ref_count = 1; + hash_table->key_destroy_func = key_destroy_func; + hash_table->value_destroy_func = value_destroy_func; + hash_table->nodes = g_new0 (GHashNode*, hash_table->size); + + return hash_table; +} + +#if 0 + +/** + * g_hash_table_ref: + * @hash_table: a valid #GHashTable. + * + * Atomically increments the reference count of @hash_table by one. + * This function is MT-safe and may be called from any thread. + * + * Return value: the passed in #GHashTable. + * + * Since: 2.10 + **/ +GHashTable* +g_hash_table_ref (GHashTable *hash_table) +{ + g_return_val_if_fail (hash_table != NULL, NULL); + g_return_val_if_fail (hash_table->ref_count > 0, hash_table); + + g_atomic_int_add (&hash_table->ref_count, 1); + return hash_table; +} + +/** + * g_hash_table_unref: + * @hash_table: a valid #GHashTable. + * + * Atomically decrements the reference count of @hash_table by one. + * If the reference count drops to 0, all keys and values will be + * destroyed, and all memory allocated by the hash table is released. + * This function is MT-safe and may be called from any thread. + * + * Since: 2.10 + **/ +void +g_hash_table_unref (GHashTable *hash_table) +{ + g_return_if_fail (hash_table != NULL); + g_return_if_fail (hash_table->ref_count > 0); + + if (g_atomic_int_exchange_and_add (&hash_table->ref_count, -1) - 1 == 0) + { + gint i; + + for (i = 0; i < hash_table->size; i++) + g_hash_nodes_destroy (hash_table->nodes[i], + hash_table->key_destroy_func, + hash_table->value_destroy_func); + g_free (hash_table->nodes); + g_slice_free (GHashTable, hash_table); + } +} + +/** + * g_hash_table_destroy: + * @hash_table: a #GHashTable. + * + * Destroys all keys and values in the #GHashTable and decrements its + * reference count by 1. If keys and/or values are dynamically allocated, + * you should either free them first or create the #GHashTable with destroy + * notifiers using g_hash_table_new_full(). In the latter case the destroy + * functions you supplied will be called on all keys and values during the + * destruction phase. + **/ +void +g_hash_table_destroy (GHashTable *hash_table) +{ + g_return_if_fail (hash_table != NULL); + g_return_if_fail (hash_table->ref_count > 0); + + g_hash_table_remove_all (hash_table); + g_hash_table_unref (hash_table); +} + +#endif + +static inline GHashNode** +g_hash_table_lookup_node (GHashTable *hash_table, + gconstpointer key) +{ + GHashNode **node; + + node = &hash_table->nodes + [(* hash_table->hash_func) (key) % hash_table->size]; + + /* Hash table lookup needs to be fast. + * We therefore remove the extra conditional of testing + * whether to call the key_equal_func or not from + * the inner loop. + */ + if (hash_table->key_equal_func) + while (*node && !(*hash_table->key_equal_func) ((*node)->key, key)) + node = &(*node)->next; + else + while (*node && (*node)->key != key) + node = &(*node)->next; + + return node; +} + +/** + * g_hash_table_lookup: + * @hash_table: a #GHashTable. + * @key: the key to look up. + * + * Looks up a key in a #GHashTable. Note that this function cannot + * distinguish between a key that is not present and one which is present + * and has the value %NULL. If you need this distinction, use + * g_hash_table_lookup_extended(). + * + * Return value: the associated value, or %NULL if the key is not found. + **/ +gpointer +g_hash_table_lookup (GHashTable *hash_table, + gconstpointer key) +{ + GHashNode *node; + + g_return_val_if_fail (hash_table != NULL, NULL); + + node = *g_hash_table_lookup_node (hash_table, key); + + return node ? node->value : NULL; +} + +#if 0 + +/** + * g_hash_table_lookup_extended: + * @hash_table: a #GHashTable. + * @lookup_key: the key to look up. + * @orig_key: returns the original key. + * @value: returns the value associated with the key. + * + * Looks up a key in the #GHashTable, returning the original key and the + * associated value and a #gboolean which is %TRUE if the key was found. This + * is useful if you need to free the memory allocated for the original key, + * for example before calling g_hash_table_remove(). + * + * Return value: %TRUE if the key was found in the #GHashTable. + **/ +gboolean +g_hash_table_lookup_extended (GHashTable *hash_table, + gconstpointer lookup_key, + gpointer *orig_key, + gpointer *value) +{ + GHashNode *node; + + g_return_val_if_fail (hash_table != NULL, FALSE); + + node = *g_hash_table_lookup_node (hash_table, lookup_key); + + if (node) + { + if (orig_key) + *orig_key = node->key; + if (value) + *value = node->value; + return TRUE; + } + else + return FALSE; +} + +#endif + +/** + * g_hash_table_insert: + * @hash_table: a #GHashTable. + * @key: a key to insert. + * @value: the value to associate with the key. + * + * Inserts a new key and value into a #GHashTable. + * + * If the key already exists in the #GHashTable its current value is replaced + * with the new value. If you supplied a @value_destroy_func when creating the + * #GHashTable, the old value is freed using that function. If you supplied + * a @key_destroy_func when creating the #GHashTable, the passed key is freed + * using that function. + **/ +void +g_hash_table_insert (GHashTable *hash_table, + gpointer key, + gpointer value) +{ + GHashNode **node; + + g_return_if_fail (hash_table != NULL); + g_return_if_fail (hash_table->ref_count > 0); + + node = g_hash_table_lookup_node (hash_table, key); + + if (*node) + { + /* do not reset node->key in this place, keeping + * the old key is the intended behaviour. + * g_hash_table_replace() can be used instead. + */ + + /* free the passed key */ + if (hash_table->key_destroy_func) + hash_table->key_destroy_func (key); + + if (hash_table->value_destroy_func) + hash_table->value_destroy_func ((*node)->value); + + (*node)->value = value; + } + else + { + *node = g_hash_node_new (key, value); + hash_table->nnodes++; + G_HASH_TABLE_RESIZE (hash_table); + } +} + +#if 0 + +/** + * g_hash_table_replace: + * @hash_table: a #GHashTable. + * @key: a key to insert. + * @value: the value to associate with the key. + * + * Inserts a new key and value into a #GHashTable similar to + * g_hash_table_insert(). The difference is that if the key already exists + * in the #GHashTable, it gets replaced by the new key. If you supplied a + * @value_destroy_func when creating the #GHashTable, the old value is freed + * using that function. If you supplied a @key_destroy_func when creating the + * #GHashTable, the old key is freed using that function. + **/ +void +g_hash_table_replace (GHashTable *hash_table, + gpointer key, + gpointer value) +{ + GHashNode **node; + + g_return_if_fail (hash_table != NULL); + g_return_if_fail (hash_table->ref_count > 0); + + node = g_hash_table_lookup_node (hash_table, key); + + if (*node) + { + if (hash_table->key_destroy_func) + hash_table->key_destroy_func ((*node)->key); + + if (hash_table->value_destroy_func) + hash_table->value_destroy_func ((*node)->value); + + (*node)->key = key; + (*node)->value = value; + } + else + { + *node = g_hash_node_new (key, value); + hash_table->nnodes++; + G_HASH_TABLE_RESIZE (hash_table); + } +} + +/** + * g_hash_table_remove: + * @hash_table: a #GHashTable. + * @key: the key to remove. + * + * Removes a key and its associated value from a #GHashTable. + * + * If the #GHashTable was created using g_hash_table_new_full(), the + * key and value are freed using the supplied destroy functions, otherwise + * you have to make sure that any dynamically allocated values are freed + * yourself. + * + * Return value: %TRUE if the key was found and removed from the #GHashTable. + **/ +gboolean +g_hash_table_remove (GHashTable *hash_table, + gconstpointer key) +{ + GHashNode **node, *dest; + + g_return_val_if_fail (hash_table != NULL, FALSE); + + node = g_hash_table_lookup_node (hash_table, key); + if (*node) + { + dest = *node; + (*node) = dest->next; + g_hash_node_destroy (dest, + hash_table->key_destroy_func, + hash_table->value_destroy_func); + hash_table->nnodes--; + + G_HASH_TABLE_RESIZE (hash_table); + + return TRUE; + } + + return FALSE; +} + +/** + * g_hash_table_remove_all: + * @hash_table: a #GHashTable + * + * Removes all keys and their associated values from a #GHashTable. + * + * If the #GHashTable was created using g_hash_table_new_full(), the keys + * and values are freed using the supplied destroy functions, otherwise you + * have to make sure that any dynamically allocated values are freed + * yourself. + * + * Since: 2.12 + **/ +void +g_hash_table_remove_all (GHashTable *hash_table) +{ + guint i; + + g_return_if_fail (hash_table != NULL); + + for (i = 0; i < hash_table->size; i++) + { + g_hash_nodes_destroy (hash_table->nodes[i], + hash_table->key_destroy_func, + hash_table->value_destroy_func); + hash_table->nodes[i] = NULL; + } + hash_table->nnodes = 0; + + G_HASH_TABLE_RESIZE (hash_table); +} + +/** + * g_hash_table_steal: + * @hash_table: a #GHashTable. + * @key: the key to remove. + * + * Removes a key and its associated value from a #GHashTable without + * calling the key and value destroy functions. + * + * Return value: %TRUE if the key was found and removed from the #GHashTable. + **/ +gboolean +g_hash_table_steal (GHashTable *hash_table, + gconstpointer key) +{ + GHashNode **node, *dest; + + g_return_val_if_fail (hash_table != NULL, FALSE); + + node = g_hash_table_lookup_node (hash_table, key); + if (*node) + { + dest = *node; + (*node) = dest->next; + g_hash_node_destroy (dest, NULL, NULL); + hash_table->nnodes--; + + G_HASH_TABLE_RESIZE (hash_table); + + return TRUE; + } + + return FALSE; +} + +/** + * g_hash_table_steal_all: + * @hash_table: a #GHashTable. + * + * Removes all keys and their associated values from a #GHashTable + * without calling the key and value destroy functions. + * + * Since: 2.12 + **/ +void +g_hash_table_steal_all (GHashTable *hash_table) +{ + guint i; + + g_return_if_fail (hash_table != NULL); + + for (i = 0; i < hash_table->size; i++) + { + g_hash_nodes_destroy (hash_table->nodes[i], NULL, NULL); + hash_table->nodes[i] = NULL; + } + + hash_table->nnodes = 0; + + G_HASH_TABLE_RESIZE (hash_table); +} + +/** + * g_hash_table_foreach_remove: + * @hash_table: a #GHashTable. + * @func: the function to call for each key/value pair. + * @user_data: user data to pass to the function. + * + * Calls the given function for each key/value pair in the #GHashTable. + * If the function returns %TRUE, then the key/value pair is removed from the + * #GHashTable. If you supplied key or value destroy functions when creating + * the #GHashTable, they are used to free the memory allocated for the removed + * keys and values. + * + * Return value: the number of key/value pairs removed. + **/ +guint +g_hash_table_foreach_remove (GHashTable *hash_table, + GHRFunc func, + gpointer user_data) +{ + g_return_val_if_fail (hash_table != NULL, 0); + g_return_val_if_fail (func != NULL, 0); + + return g_hash_table_foreach_remove_or_steal (hash_table, func, user_data, TRUE); +} + +/** + * g_hash_table_foreach_steal: + * @hash_table: a #GHashTable. + * @func: the function to call for each key/value pair. + * @user_data: user data to pass to the function. + * + * Calls the given function for each key/value pair in the #GHashTable. + * If the function returns %TRUE, then the key/value pair is removed from the + * #GHashTable, but no key or value destroy functions are called. + * + * Return value: the number of key/value pairs removed. + **/ +guint +g_hash_table_foreach_steal (GHashTable *hash_table, + GHRFunc func, + gpointer user_data) +{ + g_return_val_if_fail (hash_table != NULL, 0); + g_return_val_if_fail (func != NULL, 0); + + return g_hash_table_foreach_remove_or_steal (hash_table, func, user_data, FALSE); +} + +static guint +g_hash_table_foreach_remove_or_steal (GHashTable *hash_table, + GHRFunc func, + gpointer user_data, + gboolean notify) +{ + GHashNode *node, *prev; + gint i; + guint deleted = 0; + + for (i = 0; i < hash_table->size; i++) + { + restart: + + prev = NULL; + + for (node = hash_table->nodes[i]; node; prev = node, node = node->next) + { + if ((* func) (node->key, node->value, user_data)) + { + deleted += 1; + + hash_table->nnodes -= 1; + + if (prev) + { + prev->next = node->next; + g_hash_node_destroy (node, + notify ? hash_table->key_destroy_func : NULL, + notify ? hash_table->value_destroy_func : NULL); + node = prev; + } + else + { + hash_table->nodes[i] = node->next; + g_hash_node_destroy (node, + notify ? hash_table->key_destroy_func : NULL, + notify ? hash_table->value_destroy_func : NULL); + goto restart; + } + } + } + } + + G_HASH_TABLE_RESIZE (hash_table); + + return deleted; +} + +/** + * g_hash_table_foreach: + * @hash_table: a #GHashTable. + * @func: the function to call for each key/value pair. + * @user_data: user data to pass to the function. + * + * Calls the given function for each of the key/value pairs in the + * #GHashTable. The function is passed the key and value of each + * pair, and the given @user_data parameter. The hash table may not + * be modified while iterating over it (you can't add/remove + * items). To remove all items matching a predicate, use + * g_hash_table_foreach_remove(). + **/ +void +g_hash_table_foreach (GHashTable *hash_table, + GHFunc func, + gpointer user_data) +{ + GHashNode *node; + gint i; + + g_return_if_fail (hash_table != NULL); + g_return_if_fail (func != NULL); + + for (i = 0; i < hash_table->size; i++) + for (node = hash_table->nodes[i]; node; node = node->next) + (* func) (node->key, node->value, user_data); +} + +/** + * g_hash_table_find: + * @hash_table: a #GHashTable. + * @predicate: function to test the key/value pairs for a certain property. + * @user_data: user data to pass to the function. + * + * Calls the given function for key/value pairs in the #GHashTable until + * @predicate returns %TRUE. The function is passed the key and value of + * each pair, and the given @user_data parameter. The hash table may not + * be modified while iterating over it (you can't add/remove items). + * + * Return value: The value of the first key/value pair is returned, for which + * func evaluates to %TRUE. If no pair with the requested property is found, + * %NULL is returned. + * + * Since: 2.4 + **/ +gpointer +g_hash_table_find (GHashTable *hash_table, + GHRFunc predicate, + gpointer user_data) +{ + GHashNode *node; + gint i; + + g_return_val_if_fail (hash_table != NULL, NULL); + g_return_val_if_fail (predicate != NULL, NULL); + + for (i = 0; i < hash_table->size; i++) + for (node = hash_table->nodes[i]; node; node = node->next) + if (predicate (node->key, node->value, user_data)) + return node->value; + return NULL; +} + +/** + * g_hash_table_size: + * @hash_table: a #GHashTable. + * + * Returns the number of elements contained in the #GHashTable. + * + * Return value: the number of key/value pairs in the #GHashTable. + **/ +guint +g_hash_table_size (GHashTable *hash_table) +{ + g_return_val_if_fail (hash_table != NULL, 0); + + return hash_table->nnodes; +} + +#endif + +static void +g_hash_table_resize (GHashTable *hash_table) +{ + GHashNode **new_nodes; + GHashNode *node; + GHashNode *next; + guint hash_val; + gint new_size; + gint i; + + new_size = g_spaced_primes_closest (hash_table->nnodes); + new_size = CLAMP (new_size, HASH_TABLE_MIN_SIZE, HASH_TABLE_MAX_SIZE); + + new_nodes = g_new0 (GHashNode*, new_size); + + for (i = 0; i < hash_table->size; i++) + for (node = hash_table->nodes[i]; node; node = next) + { + next = node->next; + + hash_val = (* hash_table->hash_func) (node->key) % new_size; + + node->next = new_nodes[hash_val]; + new_nodes[hash_val] = node; + } + + g_free (hash_table->nodes); + hash_table->nodes = new_nodes; + hash_table->size = new_size; +} + +static GHashNode* +g_hash_node_new (gpointer key, + gpointer value) +{ + GHashNode *hash_node = g_slice_new (GHashNode); + + hash_node->key = key; + hash_node->value = value; + hash_node->next = NULL; + + return hash_node; +} + +#if 0 + +static void +g_hash_node_destroy (GHashNode *hash_node, + GDestroyNotify key_destroy_func, + GDestroyNotify value_destroy_func) +{ + if (key_destroy_func) + key_destroy_func (hash_node->key); + if (value_destroy_func) + value_destroy_func (hash_node->value); + g_slice_free (GHashNode, hash_node); +} + +static void +g_hash_nodes_destroy (GHashNode *hash_node, + GFreeFunc key_destroy_func, + GFreeFunc value_destroy_func) +{ + while (hash_node) + { + GHashNode *next = hash_node->next; + if (key_destroy_func) + key_destroy_func (hash_node->key); + if (value_destroy_func) + value_destroy_func (hash_node->value); + g_slice_free (GHashNode, hash_node); + hash_node = next; + } +} + + +#define __G_HASH_C__ +#include "galiasdef.c" +#endif diff --git a/gettext-tools/gnulib-lib/glib/ghash.in.h b/gettext-tools/gnulib-lib/glib/ghash.in.h new file mode 100644 index 0000000..2363612 --- /dev/null +++ b/gettext-tools/gnulib-lib/glib/ghash.in.h @@ -0,0 +1,132 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +/* + * Modified by Bruno Haible for use as a gnulib module. + */ + +#ifndef __G_HASH_H__ +#define __G_HASH_H__ + +#include + +G_BEGIN_DECLS + +typedef struct _GHashTable GHashTable; + +typedef gboolean (*GHRFunc) (gpointer key, + gpointer value, + gpointer user_data); + +/* Hash tables + */ +GHashTable* g_hash_table_new (GHashFunc hash_func, + GEqualFunc key_equal_func); +GHashTable* g_hash_table_new_full (GHashFunc hash_func, + GEqualFunc key_equal_func, + GDestroyNotify key_destroy_func, + GDestroyNotify value_destroy_func); +#if 0 +void g_hash_table_destroy (GHashTable *hash_table); +#endif +void g_hash_table_insert (GHashTable *hash_table, + gpointer key, + gpointer value); +#if 0 +void g_hash_table_replace (GHashTable *hash_table, + gpointer key, + gpointer value); +gboolean g_hash_table_remove (GHashTable *hash_table, + gconstpointer key); +void g_hash_table_remove_all (GHashTable *hash_table); +gboolean g_hash_table_steal (GHashTable *hash_table, + gconstpointer key); +void g_hash_table_steal_all (GHashTable *hash_table); +#endif +gpointer g_hash_table_lookup (GHashTable *hash_table, + gconstpointer key); +#if 0 +gboolean g_hash_table_lookup_extended (GHashTable *hash_table, + gconstpointer lookup_key, + gpointer *orig_key, + gpointer *value); +void g_hash_table_foreach (GHashTable *hash_table, + GHFunc func, + gpointer user_data); +gpointer g_hash_table_find (GHashTable *hash_table, + GHRFunc predicate, + gpointer user_data); +guint g_hash_table_foreach_remove (GHashTable *hash_table, + GHRFunc func, + gpointer user_data); +guint g_hash_table_foreach_steal (GHashTable *hash_table, + GHRFunc func, + gpointer user_data); +guint g_hash_table_size (GHashTable *hash_table); + +/* keeping hash tables alive */ +GHashTable* g_hash_table_ref (GHashTable *hash_table); +void g_hash_table_unref (GHashTable *hash_table); + +#ifndef G_DISABLE_DEPRECATED + +/* The following two functions are deprecated and will be removed in + * the next major release. They do no good. */ +#define g_hash_table_freeze(hash_table) ((void)0) +#define g_hash_table_thaw(hash_table) ((void)0) + +#endif /* G_DISABLE_DEPRECATED */ + +#endif + +/* Hash Functions + */ +gboolean g_str_equal (gconstpointer v1, + gconstpointer v2); +guint g_str_hash (gconstpointer v); + +#if 0 + +gboolean g_int_equal (gconstpointer v1, + gconstpointer v2); +guint g_int_hash (gconstpointer v); + +/* This "hash" function will just return the key's address as an + * unsigned integer. Useful for hashing on plain addresses or + * simple integer values. + * Passing NULL into g_hash_table_new() as GHashFunc has the + * same effect as passing g_direct_hash(). + */ +guint g_direct_hash (gconstpointer v) G_GNUC_CONST; +gboolean g_direct_equal (gconstpointer v1, + gconstpointer v2) G_GNUC_CONST; + +#endif + +G_END_DECLS + +#endif /* __G_HASH_H__ */ + diff --git a/gettext-tools/gnulib-lib/glib/glist.c b/gettext-tools/gnulib-lib/glib/glist.c new file mode 100644 index 0000000..15821b2 --- /dev/null +++ b/gettext-tools/gnulib-lib/glib/glist.c @@ -0,0 +1,688 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +/* + * Modified by Bruno Haible for use as a gnulib module. + */ + +/* + * MT safe + */ + +#include "config.h" + +#include "glib.h" +#if 0 +#include "galias.h" +#endif + + +#if 0 +void g_list_push_allocator (gpointer dummy) { /* present for binary compat only */ } +void g_list_pop_allocator (void) { /* present for binary compat only */ } +#endif + +#define _g_list_alloc() g_slice_new (GList) +#define _g_list_alloc0() g_slice_new0 (GList) +#define _g_list_free1(list) g_slice_free (GList, list) + +#if 0 + +GList* +g_list_alloc (void) +{ + return _g_list_alloc0 (); +} + +#endif + +void +g_list_free (GList *list) +{ + while (list) + { + GList *n = list->next; + g_slice_free (GList, list); + list = n; + } +} + +#if 0 + +void +g_list_free_1 (GList *list) +{ + _g_list_free1 (list); +} + +#endif + +GList* +g_list_append (GList *list, + gpointer data) +{ + GList *new_list; + GList *last; + + new_list = _g_list_alloc (); + new_list->data = data; + new_list->next = NULL; + + if (list) + { + last = g_list_last (list); + /* g_assert (last != NULL); */ + last->next = new_list; + new_list->prev = last; + + return list; + } + else + { + new_list->prev = NULL; + return new_list; + } +} + +GList* +g_list_prepend (GList *list, + gpointer data) +{ + GList *new_list; + + new_list = _g_list_alloc (); + new_list->data = data; + new_list->next = list; + + if (list) + { + new_list->prev = list->prev; + if (list->prev) + list->prev->next = new_list; + list->prev = new_list; + } + else + new_list->prev = NULL; + + return new_list; +} + +#if 0 + +GList* +g_list_insert (GList *list, + gpointer data, + gint position) +{ + GList *new_list; + GList *tmp_list; + + if (position < 0) + return g_list_append (list, data); + else if (position == 0) + return g_list_prepend (list, data); + + tmp_list = g_list_nth (list, position); + if (!tmp_list) + return g_list_append (list, data); + + new_list = _g_list_alloc (); + new_list->data = data; + new_list->prev = tmp_list->prev; + if (tmp_list->prev) + tmp_list->prev->next = new_list; + new_list->next = tmp_list; + tmp_list->prev = new_list; + + if (tmp_list == list) + return new_list; + else + return list; +} + +GList* +g_list_insert_before (GList *list, + GList *sibling, + gpointer data) +{ + if (!list) + { + list = g_list_alloc (); + list->data = data; + g_return_val_if_fail (sibling == NULL, list); + return list; + } + else if (sibling) + { + GList *node; + + node = _g_list_alloc (); + node->data = data; + node->prev = sibling->prev; + node->next = sibling; + sibling->prev = node; + if (node->prev) + { + node->prev->next = node; + return list; + } + else + { + g_return_val_if_fail (sibling == list, node); + return node; + } + } + else + { + GList *last; + + last = list; + while (last->next) + last = last->next; + + last->next = _g_list_alloc (); + last->next->data = data; + last->next->prev = last; + last->next->next = NULL; + + return list; + } +} + +GList * +g_list_concat (GList *list1, GList *list2) +{ + GList *tmp_list; + + if (list2) + { + tmp_list = g_list_last (list1); + if (tmp_list) + tmp_list->next = list2; + else + list1 = list2; + list2->prev = tmp_list; + } + + return list1; +} + +GList* +g_list_remove (GList *list, + gconstpointer data) +{ + GList *tmp; + + tmp = list; + while (tmp) + { + if (tmp->data != data) + tmp = tmp->next; + else + { + if (tmp->prev) + tmp->prev->next = tmp->next; + if (tmp->next) + tmp->next->prev = tmp->prev; + + if (list == tmp) + list = list->next; + + _g_list_free1 (tmp); + + break; + } + } + return list; +} + +GList* +g_list_remove_all (GList *list, + gconstpointer data) +{ + GList *tmp = list; + + while (tmp) + { + if (tmp->data != data) + tmp = tmp->next; + else + { + GList *next = tmp->next; + + if (tmp->prev) + tmp->prev->next = next; + else + list = next; + if (next) + next->prev = tmp->prev; + + _g_list_free1 (tmp); + tmp = next; + } + } + return list; +} + +#endif + +static inline GList* +_g_list_remove_link (GList *list, + GList *link) +{ + if (link) + { + if (link->prev) + link->prev->next = link->next; + if (link->next) + link->next->prev = link->prev; + + if (link == list) + list = list->next; + + link->next = NULL; + link->prev = NULL; + } + + return list; +} + +#if 0 + +GList* +g_list_remove_link (GList *list, + GList *link) +{ + return _g_list_remove_link (list, link); +} + +#endif + +GList* +g_list_delete_link (GList *list, + GList *link) +{ + list = _g_list_remove_link (list, link); + _g_list_free1 (link); + + return list; +} + +#if 0 + +GList* +g_list_copy (GList *list) +{ + GList *new_list = NULL; + + if (list) + { + GList *last; + + new_list = _g_list_alloc (); + new_list->data = list->data; + new_list->prev = NULL; + last = new_list; + list = list->next; + while (list) + { + last->next = _g_list_alloc (); + last->next->prev = last; + last = last->next; + last->data = list->data; + list = list->next; + } + last->next = NULL; + } + + return new_list; +} + +GList* +g_list_reverse (GList *list) +{ + GList *last; + + last = NULL; + while (list) + { + last = list; + list = last->next; + last->next = last->prev; + last->prev = list; + } + + return last; +} + +GList* +g_list_nth (GList *list, + guint n) +{ + while ((n-- > 0) && list) + list = list->next; + + return list; +} + +GList* +g_list_nth_prev (GList *list, + guint n) +{ + while ((n-- > 0) && list) + list = list->prev; + + return list; +} + +gpointer +g_list_nth_data (GList *list, + guint n) +{ + while ((n-- > 0) && list) + list = list->next; + + return list ? list->data : NULL; +} + +GList* +g_list_find (GList *list, + gconstpointer data) +{ + while (list) + { + if (list->data == data) + break; + list = list->next; + } + + return list; +} + +GList* +g_list_find_custom (GList *list, + gconstpointer data, + GCompareFunc func) +{ + g_return_val_if_fail (func != NULL, list); + + while (list) + { + if (! func (list->data, data)) + return list; + list = list->next; + } + + return NULL; +} + + +gint +g_list_position (GList *list, + GList *link) +{ + gint i; + + i = 0; + while (list) + { + if (list == link) + return i; + i++; + list = list->next; + } + + return -1; +} + +gint +g_list_index (GList *list, + gconstpointer data) +{ + gint i; + + i = 0; + while (list) + { + if (list->data == data) + return i; + i++; + list = list->next; + } + + return -1; +} + +#endif + +GList* +g_list_last (GList *list) +{ + if (list) + { + while (list->next) + list = list->next; + } + + return list; +} + +#if 0 + +GList* +g_list_first (GList *list) +{ + if (list) + { + while (list->prev) + list = list->prev; + } + + return list; +} + +guint +g_list_length (GList *list) +{ + guint length; + + length = 0; + while (list) + { + length++; + list = list->next; + } + + return length; +} + +void +g_list_foreach (GList *list, + GFunc func, + gpointer user_data) +{ + while (list) + { + GList *next = list->next; + (*func) (list->data, user_data); + list = next; + } +} + +static GList* +g_list_insert_sorted_real (GList *list, + gpointer data, + GFunc func, + gpointer user_data) +{ + GList *tmp_list = list; + GList *new_list; + gint cmp; + + g_return_val_if_fail (func != NULL, list); + + if (!list) + { + new_list = _g_list_alloc0 (); + new_list->data = data; + return new_list; + } + + cmp = ((GCompareDataFunc) func) (data, tmp_list->data, user_data); + + while ((tmp_list->next) && (cmp > 0)) + { + tmp_list = tmp_list->next; + + cmp = ((GCompareDataFunc) func) (data, tmp_list->data, user_data); + } + + new_list = _g_list_alloc0 (); + new_list->data = data; + + if ((!tmp_list->next) && (cmp > 0)) + { + tmp_list->next = new_list; + new_list->prev = tmp_list; + return list; + } + + if (tmp_list->prev) + { + tmp_list->prev->next = new_list; + new_list->prev = tmp_list->prev; + } + new_list->next = tmp_list; + tmp_list->prev = new_list; + + if (tmp_list == list) + return new_list; + else + return list; +} + +GList* +g_list_insert_sorted (GList *list, + gpointer data, + GCompareFunc func) +{ + return g_list_insert_sorted_real (list, data, (GFunc) func, NULL); +} + +GList* +g_list_insert_sorted_with_data (GList *list, + gpointer data, + GCompareDataFunc func, + gpointer user_data) +{ + return g_list_insert_sorted_real (list, data, (GFunc) func, user_data); +} + +static GList * +g_list_sort_merge (GList *l1, + GList *l2, + GFunc compare_func, + gpointer user_data) +{ + GList list, *l, *lprev; + gint cmp; + + l = &list; + lprev = NULL; + + while (l1 && l2) + { + cmp = ((GCompareDataFunc) compare_func) (l1->data, l2->data, user_data); + + if (cmp <= 0) + { + l->next = l1; + l1 = l1->next; + } + else + { + l->next = l2; + l2 = l2->next; + } + l = l->next; + l->prev = lprev; + lprev = l; + } + l->next = l1 ? l1 : l2; + l->next->prev = l; + + return list.next; +} + +static GList* +g_list_sort_real (GList *list, + GFunc compare_func, + gpointer user_data) +{ + GList *l1, *l2; + + if (!list) + return NULL; + if (!list->next) + return list; + + l1 = list; + l2 = list->next; + + while ((l2 = l2->next) != NULL) + { + if ((l2 = l2->next) == NULL) + break; + l1 = l1->next; + } + l2 = l1->next; + l1->next = NULL; + + return g_list_sort_merge (g_list_sort_real (list, compare_func, user_data), + g_list_sort_real (l2, compare_func, user_data), + compare_func, + user_data); +} + +GList * +g_list_sort (GList *list, + GCompareFunc compare_func) +{ + return g_list_sort_real (list, (GFunc) compare_func, NULL); + +} + +GList * +g_list_sort_with_data (GList *list, + GCompareDataFunc compare_func, + gpointer user_data) +{ + return g_list_sort_real (list, (GFunc) compare_func, user_data); +} + +#define __G_LIST_C__ +#include "galiasdef.c" +#endif diff --git a/gettext-tools/gnulib-lib/glib/glist.in.h b/gettext-tools/gnulib-lib/glib/glist.in.h new file mode 100644 index 0000000..6878384 --- /dev/null +++ b/gettext-tools/gnulib-lib/glib/glist.in.h @@ -0,0 +1,136 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +/* + * Modified by Bruno Haible for use as a gnulib module. + */ + +#ifndef __G_LIST_H__ +#define __G_LIST_H__ + +#if 0 +#include +#endif + +G_BEGIN_DECLS + +typedef struct _GList GList; + +struct _GList +{ + gpointer data; + GList *next; + GList *prev; +}; + +/* Doubly linked lists + */ +#if 0 +GList* g_list_alloc (void) G_GNUC_WARN_UNUSED_RESULT; +#endif +void g_list_free (GList *list); +#if 0 +void g_list_free_1 (GList *list); +#define g_list_free1 g_list_free_1 +#endif +GList* g_list_append (GList *list, + gpointer data) G_GNUC_WARN_UNUSED_RESULT; +GList* g_list_prepend (GList *list, + gpointer data) G_GNUC_WARN_UNUSED_RESULT; +#if 0 +GList* g_list_insert (GList *list, + gpointer data, + gint position) G_GNUC_WARN_UNUSED_RESULT; +GList* g_list_insert_sorted (GList *list, + gpointer data, + GCompareFunc func) G_GNUC_WARN_UNUSED_RESULT; +GList* g_list_insert_sorted_with_data (GList *list, + gpointer data, + GCompareDataFunc func, + gpointer user_data) G_GNUC_WARN_UNUSED_RESULT; +GList* g_list_insert_before (GList *list, + GList *sibling, + gpointer data) G_GNUC_WARN_UNUSED_RESULT; +GList* g_list_concat (GList *list1, + GList *list2) G_GNUC_WARN_UNUSED_RESULT; +GList* g_list_remove (GList *list, + gconstpointer data) G_GNUC_WARN_UNUSED_RESULT; +GList* g_list_remove_all (GList *list, + gconstpointer data) G_GNUC_WARN_UNUSED_RESULT; +GList* g_list_remove_link (GList *list, + GList *llink) G_GNUC_WARN_UNUSED_RESULT; +#endif +GList* g_list_delete_link (GList *list, + GList *link_) G_GNUC_WARN_UNUSED_RESULT; +#if 0 +GList* g_list_reverse (GList *list) G_GNUC_WARN_UNUSED_RESULT; +GList* g_list_copy (GList *list) G_GNUC_WARN_UNUSED_RESULT; +GList* g_list_nth (GList *list, + guint n); +GList* g_list_nth_prev (GList *list, + guint n); +GList* g_list_find (GList *list, + gconstpointer data); +GList* g_list_find_custom (GList *list, + gconstpointer data, + GCompareFunc func); +gint g_list_position (GList *list, + GList *llink); +gint g_list_index (GList *list, + gconstpointer data); +#endif +GList* g_list_last (GList *list); +#if 0 +GList* g_list_first (GList *list); +guint g_list_length (GList *list); +void g_list_foreach (GList *list, + GFunc func, + gpointer user_data); +GList* g_list_sort (GList *list, + GCompareFunc compare_func) G_GNUC_WARN_UNUSED_RESULT; +GList* g_list_sort_with_data (GList *list, + GCompareDataFunc compare_func, + gpointer user_data) G_GNUC_WARN_UNUSED_RESULT; +gpointer g_list_nth_data (GList *list, + guint n); + + +#define g_list_previous(list) ((list) ? (((GList *)(list))->prev) : NULL) +#endif +#define g_list_next(list) ((list) ? (((GList *)(list))->next) : NULL) +#if 0 + +#ifndef G_DISABLE_DEPRECATED +void g_list_push_allocator (gpointer allocator); +void g_list_pop_allocator (void); +#endif + +#endif + +G_END_DECLS + +#endif /* __G_LIST_H__ */ + diff --git a/gettext-tools/gnulib-lib/glib/gmessages.c b/gettext-tools/gnulib-lib/glib/gmessages.c new file mode 100644 index 0000000..fae4ff3 --- /dev/null +++ b/gettext-tools/gnulib-lib/glib/gmessages.c @@ -0,0 +1,68 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +/* + * Modified by Bruno Haible for use as a gnulib module. + */ + +#include "config.h" + +#include "glib.h" +#include "xvasprintf.h" +#include + +void +g_printerr (const gchar *format, ...) +{ + va_list args; + + va_start (args, format); + vfprintf (stderr, format, args); + va_end (args); +} + +void +g_warning (const gchar *format, ...) +{ + va_list args; + char *msg; + + va_start (args, format); + msg = xvasprintf (format, args); + va_end (args); + + fprintf (stderr, "warning: %s", msg); +} + +void +g_log (const char *domain, int level, const char *format, ...) +{ + va_list args; + + va_start (args, format); + vfprintf (stderr, format, args); + va_end (args); +} diff --git a/gettext-tools/gnulib-lib/glib/gprimes.c b/gettext-tools/gnulib-lib/glib/gprimes.c new file mode 100644 index 0000000..4f3a798 --- /dev/null +++ b/gettext-tools/gnulib-lib/glib/gprimes.c @@ -0,0 +1,98 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +/* + * Modified by Bruno Haible for use as a gnulib module. + */ + +/* + * MT safe + */ + +#include "config.h" + +#include "glib.h" +#if 0 +#include "galias.h" +#endif + + +static const guint g_primes[] = +{ + 11, + 19, + 37, + 73, + 109, + 163, + 251, + 367, + 557, + 823, + 1237, + 1861, + 2777, + 4177, + 6247, + 9371, + 14057, + 21089, + 31627, + 47431, + 71143, + 106721, + 160073, + 240101, + 360163, + 540217, + 810343, + 1215497, + 1823231, + 2734867, + 4102283, + 6153409, + 9230113, + 13845163, +}; + +static const guint g_nprimes = sizeof (g_primes) / sizeof (g_primes[0]); + +guint +g_spaced_primes_closest (guint num) +{ + gint i; + + for (i = 0; i < g_nprimes; i++) + if (g_primes[i] > num) + return g_primes[i]; + + return g_primes[g_nprimes - 1]; +} + +#if 0 +#define __G_PRIMES_C__ +#include "galiasdef.c" +#endif diff --git a/gettext-tools/gnulib-lib/glib/gprimes.in.h b/gettext-tools/gnulib-lib/glib/gprimes.in.h new file mode 100644 index 0000000..9d8edbe --- /dev/null +++ b/gettext-tools/gnulib-lib/glib/gprimes.in.h @@ -0,0 +1,51 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +/* + * Modified by Bruno Haible for use as a gnulib module. + */ + +#ifndef __G_PRIMES_H__ +#define __G_PRIMES_H__ + +#include + +G_BEGIN_DECLS + +/* Prime numbers. + */ + +/* This function returns prime numbers spaced by approximately 1.5-2.0 + * and is for use in resizing data structures which prefer + * prime-valued sizes. The closest spaced prime function returns the + * next largest prime, or the highest it knows about which is about + * MAXINT/4. + */ +guint g_spaced_primes_closest (guint num) G_GNUC_CONST; + +G_END_DECLS + +#endif /* __G_PRIMES_H__ */ diff --git a/gettext-tools/gnulib-lib/glib/gstrfuncs.c b/gettext-tools/gnulib-lib/glib/gstrfuncs.c new file mode 100644 index 0000000..7db411a --- /dev/null +++ b/gettext-tools/gnulib-lib/glib/gstrfuncs.c @@ -0,0 +1,2848 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +/* + * Modified by Bruno Haible for use as a gnulib module. + */ + +/* + * MT safe + */ + +#include "config.h" + +#if 0 +#define _GNU_SOURCE /* For stpcpy */ +#endif + +#include +#include +#include +#include +#include +#include +#include /* For tolower() */ +#if !defined (HAVE_STRSIGNAL) || !defined(NO_SYS_SIGLIST_DECL) +#include +#endif + +#include "glib.h" +#if 0 +#include "gprintf.h" +#include "gprintfint.h" + +#include "galias.h" + +#ifdef G_OS_WIN32 +#include +#endif +#endif + +/* do not include in this place since it + * interferes with g_strsignal() on some OSes + */ + +static const guint16 ascii_table_data[256] = { + 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, + 0x004, 0x104, 0x104, 0x004, 0x104, 0x104, 0x004, 0x004, + 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, + 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, + 0x140, 0x0d0, 0x0d0, 0x0d0, 0x0d0, 0x0d0, 0x0d0, 0x0d0, + 0x0d0, 0x0d0, 0x0d0, 0x0d0, 0x0d0, 0x0d0, 0x0d0, 0x0d0, + 0x459, 0x459, 0x459, 0x459, 0x459, 0x459, 0x459, 0x459, + 0x459, 0x459, 0x0d0, 0x0d0, 0x0d0, 0x0d0, 0x0d0, 0x0d0, + 0x0d0, 0x653, 0x653, 0x653, 0x653, 0x653, 0x653, 0x253, + 0x253, 0x253, 0x253, 0x253, 0x253, 0x253, 0x253, 0x253, + 0x253, 0x253, 0x253, 0x253, 0x253, 0x253, 0x253, 0x253, + 0x253, 0x253, 0x253, 0x0d0, 0x0d0, 0x0d0, 0x0d0, 0x0d0, + 0x0d0, 0x473, 0x473, 0x473, 0x473, 0x473, 0x473, 0x073, + 0x073, 0x073, 0x073, 0x073, 0x073, 0x073, 0x073, 0x073, + 0x073, 0x073, 0x073, 0x073, 0x073, 0x073, 0x073, 0x073, + 0x073, 0x073, 0x073, 0x0d0, 0x0d0, 0x0d0, 0x0d0, 0x004 + /* the upper 128 are all zeroes */ +}; + +const guint16 * const g_ascii_table = ascii_table_data; + +gchar* +g_strdup (const gchar *str) +{ + gchar *new_str; + gsize length; + + if (str) + { + length = strlen (str) + 1; + new_str = g_new (char, length); + memcpy (new_str, str, length); + } + else + new_str = NULL; + + return new_str; +} + +#if 0 + +gpointer +g_memdup (gconstpointer mem, + guint byte_size) +{ + gpointer new_mem; + + if (mem) + { + new_mem = g_malloc (byte_size); + memcpy (new_mem, mem, byte_size); + } + else + new_mem = NULL; + + return new_mem; +} + +#endif + +gchar* +g_strndup (const gchar *str, + gsize n) +{ + gchar *new_str; + + if (str) + { + new_str = g_new (gchar, n + 1); + strncpy (new_str, str, n); + new_str[n] = '\0'; + } + else + new_str = NULL; + + return new_str; +} + +#if 0 + +gchar* +g_strnfill (gsize length, + gchar fill_char) +{ + gchar *str; + + str = g_new (gchar, length + 1); + memset (str, (guchar)fill_char, length); + str[length] = '\0'; + + return str; +} + +#endif + +/** + * g_stpcpy: + * @dest: destination buffer. + * @src: source string. + * + * Copies a nul-terminated string into the dest buffer, include the + * trailing nul, and return a pointer to the trailing nul byte. + * This is useful for concatenating multiple strings together + * without having to repeatedly scan for the end. + * + * Return value: a pointer to trailing nul byte. + **/ +gchar * +g_stpcpy (gchar *dest, + const gchar *src) +{ +#ifdef HAVE_STPCPY + g_return_val_if_fail (dest != NULL, NULL); + g_return_val_if_fail (src != NULL, NULL); + return stpcpy (dest, src); +#else + register gchar *d = dest; + register const gchar *s = src; + + g_return_val_if_fail (dest != NULL, NULL); + g_return_val_if_fail (src != NULL, NULL); + do + *d++ = *s; + while (*s++ != '\0'); + + return d - 1; +#endif +} + +gchar* +g_strdup_vprintf (const gchar *format, + va_list args) +{ + gchar *string = NULL; + + g_vasprintf (&string, format, args); + + return string; +} + +gchar* +g_strdup_printf (const gchar *format, + ...) +{ + gchar *buffer; + va_list args; + + va_start (args, format); + buffer = g_strdup_vprintf (format, args); + va_end (args); + + return buffer; +} + +gchar* +g_strconcat (const gchar *string1, ...) +{ + gsize l; + va_list args; + gchar *s; + gchar *concat; + gchar *ptr; + + if (!string1) + return NULL; + + l = 1 + strlen (string1); + va_start (args, string1); + s = va_arg (args, gchar*); + while (s) + { + l += strlen (s); + s = va_arg (args, gchar*); + } + va_end (args); + + concat = g_new (gchar, l); + ptr = concat; + + ptr = g_stpcpy (ptr, string1); + va_start (args, string1); + s = va_arg (args, gchar*); + while (s) + { + ptr = g_stpcpy (ptr, s); + s = va_arg (args, gchar*); + } + va_end (args); + + return concat; +} + +#if 0 + +/** + * g_strtod: + * @nptr: the string to convert to a numeric value. + * @endptr: if non-%NULL, it returns the character after + * the last character used in the conversion. + * + * Converts a string to a #gdouble value. + * It calls the standard strtod() function to handle the conversion, but + * if the string is not completely converted it attempts the conversion + * again with g_ascii_strtod(), and returns the best match. + * + * This function should seldomly be used. The normal situation when reading + * numbers not for human consumption is to use g_ascii_strtod(). Only when + * you know that you must expect both locale formatted and C formatted numbers + * should you use this. Make sure that you don't pass strings such as comma + * separated lists of values, since the commas may be interpreted as a decimal + * point in some locales, causing unexpected results. + * + * Return value: the #gdouble value. + **/ +gdouble +g_strtod (const gchar *nptr, + gchar **endptr) +{ + gchar *fail_pos_1; + gchar *fail_pos_2; + gdouble val_1; + gdouble val_2 = 0; + + g_return_val_if_fail (nptr != NULL, 0); + + fail_pos_1 = NULL; + fail_pos_2 = NULL; + + val_1 = strtod (nptr, &fail_pos_1); + + if (fail_pos_1 && fail_pos_1[0] != 0) + val_2 = g_ascii_strtod (nptr, &fail_pos_2); + + if (!fail_pos_1 || fail_pos_1[0] == 0 || fail_pos_1 >= fail_pos_2) + { + if (endptr) + *endptr = fail_pos_1; + return val_1; + } + else + { + if (endptr) + *endptr = fail_pos_2; + return val_2; + } +} + +/** + * g_ascii_strtod: + * @nptr: the string to convert to a numeric value. + * @endptr: if non-%NULL, it returns the character after + * the last character used in the conversion. + * + * Converts a string to a #gdouble value. + * This function behaves like the standard strtod() function + * does in the C locale. It does this without actually + * changing the current locale, since that would not be + * thread-safe. + * + * This function is typically used when reading configuration + * files or other non-user input that should be locale independent. + * To handle input from the user you should normally use the + * locale-sensitive system strtod() function. + * + * To convert from a #gdouble to a string in a locale-insensitive + * way, use g_ascii_dtostr(). + * + * If the correct value would cause overflow, plus or minus %HUGE_VAL + * is returned (according to the sign of the value), and %ERANGE is + * stored in %errno. If the correct value would cause underflow, + * zero is returned and %ERANGE is stored in %errno. + * + * This function resets %errno before calling strtod() so that + * you can reliably detect overflow and underflow. + * + * Return value: the #gdouble value. + **/ +gdouble +g_ascii_strtod (const gchar *nptr, + gchar **endptr) +{ + gchar *fail_pos; + gdouble val; + struct lconv *locale_data; + const char *decimal_point; + int decimal_point_len; + const char *p, *decimal_point_pos; + const char *end = NULL; /* Silence gcc */ + int strtod_errno; + + g_return_val_if_fail (nptr != NULL, 0); + + fail_pos = NULL; + + locale_data = localeconv (); + decimal_point = locale_data->decimal_point; + decimal_point_len = strlen (decimal_point); + + g_assert (decimal_point_len != 0); + + decimal_point_pos = NULL; + end = NULL; + + if (decimal_point[0] != '.' || + decimal_point[1] != 0) + { + p = nptr; + /* Skip leading space */ + while (g_ascii_isspace (*p)) + p++; + + /* Skip leading optional sign */ + if (*p == '+' || *p == '-') + p++; + + if (p[0] == '0' && + (p[1] == 'x' || p[1] == 'X')) + { + p += 2; + /* HEX - find the (optional) decimal point */ + + while (g_ascii_isxdigit (*p)) + p++; + + if (*p == '.') + decimal_point_pos = p++; + + while (g_ascii_isxdigit (*p)) + p++; + + if (*p == 'p' || *p == 'P') + p++; + if (*p == '+' || *p == '-') + p++; + while (g_ascii_isdigit (*p)) + p++; + + end = p; + } + else if (g_ascii_isdigit (*p) || *p == '.') + { + while (g_ascii_isdigit (*p)) + p++; + + if (*p == '.') + decimal_point_pos = p++; + + while (g_ascii_isdigit (*p)) + p++; + + if (*p == 'e' || *p == 'E') + p++; + if (*p == '+' || *p == '-') + p++; + while (g_ascii_isdigit (*p)) + p++; + + end = p; + } + /* For the other cases, we need not convert the decimal point */ + } + + if (decimal_point_pos) + { + char *copy, *c; + + /* We need to convert the '.' to the locale specific decimal point */ + copy = g_malloc (end - nptr + 1 + decimal_point_len); + + c = copy; + memcpy (c, nptr, decimal_point_pos - nptr); + c += decimal_point_pos - nptr; + memcpy (c, decimal_point, decimal_point_len); + c += decimal_point_len; + memcpy (c, decimal_point_pos + 1, end - (decimal_point_pos + 1)); + c += end - (decimal_point_pos + 1); + *c = 0; + + errno = 0; + val = strtod (copy, &fail_pos); + strtod_errno = errno; + + if (fail_pos) + { + if (fail_pos - copy > decimal_point_pos - nptr) + fail_pos = (char *)nptr + (fail_pos - copy) - (decimal_point_len - 1); + else + fail_pos = (char *)nptr + (fail_pos - copy); + } + + g_free (copy); + + } + else if (end) + { + char *copy; + + copy = g_malloc (end - (char *)nptr + 1); + memcpy (copy, nptr, end - nptr); + *(copy + (end - (char *)nptr)) = 0; + + errno = 0; + val = strtod (copy, &fail_pos); + strtod_errno = errno; + + if (fail_pos) + { + fail_pos = (char *)nptr + (fail_pos - copy); + } + + g_free (copy); + } + else + { + errno = 0; + val = strtod (nptr, &fail_pos); + strtod_errno = errno; + } + + if (endptr) + *endptr = fail_pos; + + errno = strtod_errno; + + return val; +} + + +/** + * g_ascii_dtostr: + * @buffer: A buffer to place the resulting string in + * @buf_len: The length of the buffer. + * @d: The #gdouble to convert + * + * Converts a #gdouble to a string, using the '.' as + * decimal point. + * + * This functions generates enough precision that converting + * the string back using g_ascii_strtod() gives the same machine-number + * (on machines with IEEE compatible 64bit doubles). It is + * guaranteed that the size of the resulting string will never + * be larger than @G_ASCII_DTOSTR_BUF_SIZE bytes. + * + * Return value: The pointer to the buffer with the converted string. + **/ +gchar * +g_ascii_dtostr (gchar *buffer, + gint buf_len, + gdouble d) +{ + return g_ascii_formatd (buffer, buf_len, "%.17g", d); +} + +/** + * g_ascii_formatd: + * @buffer: A buffer to place the resulting string in + * @buf_len: The length of the buffer. + * @format: The printf()-style format to use for the + * code to use for converting. + * @d: The #gdouble to convert + * + * Converts a #gdouble to a string, using the '.' as + * decimal point. To format the number you pass in + * a printf()-style format string. Allowed conversion + * specifiers are 'e', 'E', 'f', 'F', 'g' and 'G'. + * + * If you just want to want to serialize the value into a + * string, use g_ascii_dtostr(). + * + * Return value: The pointer to the buffer with the converted string. + **/ +gchar * +g_ascii_formatd (gchar *buffer, + gint buf_len, + const gchar *format, + gdouble d) +{ + struct lconv *locale_data; + const char *decimal_point; + int decimal_point_len; + gchar *p; + int rest_len; + gchar format_char; + + g_return_val_if_fail (buffer != NULL, NULL); + g_return_val_if_fail (format[0] == '%', NULL); + g_return_val_if_fail (strpbrk (format + 1, "'l%") == NULL, NULL); + + format_char = format[strlen (format) - 1]; + + g_return_val_if_fail (format_char == 'e' || format_char == 'E' || + format_char == 'f' || format_char == 'F' || + format_char == 'g' || format_char == 'G', + NULL); + + if (format[0] != '%') + return NULL; + + if (strpbrk (format + 1, "'l%")) + return NULL; + + if (!(format_char == 'e' || format_char == 'E' || + format_char == 'f' || format_char == 'F' || + format_char == 'g' || format_char == 'G')) + return NULL; + + + _g_snprintf (buffer, buf_len, format, d); + + locale_data = localeconv (); + decimal_point = locale_data->decimal_point; + decimal_point_len = strlen (decimal_point); + + g_assert (decimal_point_len != 0); + + if (decimal_point[0] != '.' || + decimal_point[1] != 0) + { + p = buffer; + + while (g_ascii_isspace (*p)) + p++; + + if (*p == '+' || *p == '-') + p++; + + while (isdigit ((guchar)*p)) + p++; + + if (strncmp (p, decimal_point, decimal_point_len) == 0) + { + *p = '.'; + p++; + if (decimal_point_len > 1) { + rest_len = strlen (p + (decimal_point_len-1)); + memmove (p, p + (decimal_point_len-1), + rest_len); + p[rest_len] = 0; + + } + } + } + + return buffer; +} + +static guint64 +g_parse_long_long (const gchar *nptr, + gchar **endptr, + guint base, + gboolean *negative) +{ + /* this code is based on on the strtol(3) code from GNU libc released under + * the GNU General Public License. + * + * Copyright (C) 1991,92,94,95,96,97,98,99,2000,01,02 + * Free Software Foundation, Inc. + */ +#define ISSPACE(c) ((c) == ' ' || (c) == '\f' || (c) == '\n' || \ + (c) == '\r' || (c) == '\t' || (c) == '\v') +#define ISUPPER(c) ((c) >= 'A' && (c) <= 'Z') +#define ISLOWER(c) ((c) >= 'a' && (c) <= 'z') +#define ISALPHA(c) (ISUPPER (c) || ISLOWER (c)) +#define TOUPPER(c) (ISLOWER (c) ? (c) - 'a' + 'A' : (c)) +#define TOLOWER(c) (ISUPPER (c) ? (c) - 'A' + 'a' : (c)) + gboolean overflow; + guint64 cutoff; + guint64 cutlim; + guint64 ui64; + const gchar *s, *save; + guchar c; + + g_return_val_if_fail (nptr != NULL, 0); + + if (base == 1 || base > 36) + { + errno = EINVAL; + return 0; + } + + save = s = nptr; + + /* Skip white space. */ + while (ISSPACE (*s)) + ++s; + + if (G_UNLIKELY (!*s)) + goto noconv; + + /* Check for a sign. */ + *negative = FALSE; + if (*s == '-') + { + *negative = TRUE; + ++s; + } + else if (*s == '+') + ++s; + + /* Recognize number prefix and if BASE is zero, figure it out ourselves. */ + if (*s == '0') + { + if ((base == 0 || base == 16) && TOUPPER (s[1]) == 'X') + { + s += 2; + base = 16; + } + else if (base == 0) + base = 8; + } + else if (base == 0) + base = 10; + + /* Save the pointer so we can check later if anything happened. */ + save = s; + cutoff = G_MAXUINT64 / base; + cutlim = G_MAXUINT64 % base; + + overflow = FALSE; + ui64 = 0; + c = *s; + for (; c; c = *++s) + { + if (c >= '0' && c <= '9') + c -= '0'; + else if (ISALPHA (c)) + c = TOUPPER (c) - 'A' + 10; + else + break; + if (c >= base) + break; + /* Check for overflow. */ + if (ui64 > cutoff || (ui64 == cutoff && c > cutlim)) + overflow = TRUE; + else + { + ui64 *= base; + ui64 += c; + } + } + + /* Check if anything actually happened. */ + if (s == save) + goto noconv; + + /* Store in ENDPTR the address of one character + past the last character we converted. */ + if (endptr) + *endptr = (gchar*) s; + + if (G_UNLIKELY (overflow)) + { + errno = ERANGE; + return G_MAXUINT64; + } + + return ui64; + + noconv: + /* We must handle a special case here: the base is 0 or 16 and the + first two characters are '0' and 'x', but the rest are no + hexadecimal digits. This is no error case. We return 0 and + ENDPTR points to the `x`. */ + if (endptr) + { + if (save - nptr >= 2 && TOUPPER (save[-1]) == 'X' + && save[-2] == '0') + *endptr = (gchar*) &save[-1]; + else + /* There was no number to convert. */ + *endptr = (gchar*) nptr; + } + return 0; +} + +/** + * g_ascii_strtoull: + * @nptr: the string to convert to a numeric value. + * @endptr: if non-%NULL, it returns the character after + * the last character used in the conversion. + * @base: to be used for the conversion, 2..36 or 0 + * + * Converts a string to a #guint64 value. + * This function behaves like the standard strtoull() function + * does in the C locale. It does this without actually + * changing the current locale, since that would not be + * thread-safe. + * + * This function is typically used when reading configuration + * files or other non-user input that should be locale independent. + * To handle input from the user you should normally use the + * locale-sensitive system strtoull() function. + * + * If the correct value would cause overflow, %G_MAXUINT64 + * is returned, and %ERANGE is stored in %errno. If the base is + * outside the valid range, zero is returned, and %EINVAL is stored + * in %errno. If the string conversion fails, zero is returned, and + * @endptr returns @nptr (if @endptr is non-%NULL). + * + * Return value: the #guint64 value or zero on error. + * + * Since: 2.2 + **/ +guint64 +g_ascii_strtoull (const gchar *nptr, + gchar **endptr, + guint base) +{ + gboolean negative; + guint64 result; + + result = g_parse_long_long (nptr, endptr, base, &negative); + + /* Return the result of the appropriate sign. */ + return negative ? -result : result; +} + +/** + * g_ascii_strtoll: + * @nptr: the string to convert to a numeric value. + * @endptr: if non-%NULL, it returns the character after + * the last character used in the conversion. + * @base: to be used for the conversion, 2..36 or 0 + * + * Converts a string to a #gint64 value. + * This function behaves like the standard strtoll() function + * does in the C locale. It does this without actually + * changing the current locale, since that would not be + * thread-safe. + * + * This function is typically used when reading configuration + * files or other non-user input that should be locale independent. + * To handle input from the user you should normally use the + * locale-sensitive system strtoll() function. + * + * If the correct value would cause overflow, %G_MAXINT64 or %G_MININT64 + * is returned, and %ERANGE is stored in %errno. If the base is + * outside the valid range, zero is returned, and %EINVAL is stored + * in %errno. If the string conversion fails, zero is returned, and + * @endptr returns @nptr (if @endptr is non-%NULL). + * + * Return value: the #gint64 value or zero on error. + * + * Since: 2.12 + **/ +gint64 +g_ascii_strtoll (const gchar *nptr, + gchar **endptr, + guint base) +{ + gboolean negative; + guint64 result; + + result = g_parse_long_long (nptr, endptr, base, &negative); + + if (negative && result > (guint64) G_MININT64) + { + errno = ERANGE; + return G_MININT64; + } + else if (!negative && result > (guint64) G_MAXINT64) + { + errno = ERANGE; + return G_MAXINT64; + } + else + return (gint64) result; +} + +G_CONST_RETURN gchar* +g_strerror (gint errnum) +{ + static GStaticPrivate msg_private = G_STATIC_PRIVATE_INIT; + char *msg; + int saved_errno = errno; + +#ifdef HAVE_STRERROR + const char *msg_locale; + + msg_locale = strerror (errnum); + if (g_get_charset (NULL)) + { + errno = saved_errno; + return msg_locale; + } + else + { + gchar *msg_utf8 = g_locale_to_utf8 (msg_locale, -1, NULL, NULL, NULL); + if (msg_utf8) + { + /* Stick in the quark table so that we can return a static result + */ + GQuark msg_quark = g_quark_from_string (msg_utf8); + g_free (msg_utf8); + + msg_utf8 = (gchar *) g_quark_to_string (msg_quark); + errno = saved_errno; + return msg_utf8; + } + } +#elif NO_SYS_ERRLIST + switch (errnum) + { +#ifdef E2BIG + case E2BIG: return "argument list too long"; +#endif +#ifdef EACCES + case EACCES: return "permission denied"; +#endif +#ifdef EADDRINUSE + case EADDRINUSE: return "address already in use"; +#endif +#ifdef EADDRNOTAVAIL + case EADDRNOTAVAIL: return "can't assign requested address"; +#endif +#ifdef EADV + case EADV: return "advertise error"; +#endif +#ifdef EAFNOSUPPORT + case EAFNOSUPPORT: return "address family not supported by protocol family"; +#endif +#ifdef EAGAIN + case EAGAIN: return "try again"; +#endif +#ifdef EALIGN + case EALIGN: return "EALIGN"; +#endif +#ifdef EALREADY + case EALREADY: return "operation already in progress"; +#endif +#ifdef EBADE + case EBADE: return "bad exchange descriptor"; +#endif +#ifdef EBADF + case EBADF: return "bad file number"; +#endif +#ifdef EBADFD + case EBADFD: return "file descriptor in bad state"; +#endif +#ifdef EBADMSG + case EBADMSG: return "not a data message"; +#endif +#ifdef EBADR + case EBADR: return "bad request descriptor"; +#endif +#ifdef EBADRPC + case EBADRPC: return "RPC structure is bad"; +#endif +#ifdef EBADRQC + case EBADRQC: return "bad request code"; +#endif +#ifdef EBADSLT + case EBADSLT: return "invalid slot"; +#endif +#ifdef EBFONT + case EBFONT: return "bad font file format"; +#endif +#ifdef EBUSY + case EBUSY: return "mount device busy"; +#endif +#ifdef ECHILD + case ECHILD: return "no children"; +#endif +#ifdef ECHRNG + case ECHRNG: return "channel number out of range"; +#endif +#ifdef ECOMM + case ECOMM: return "communication error on send"; +#endif +#ifdef ECONNABORTED + case ECONNABORTED: return "software caused connection abort"; +#endif +#ifdef ECONNREFUSED + case ECONNREFUSED: return "connection refused"; +#endif +#ifdef ECONNRESET + case ECONNRESET: return "connection reset by peer"; +#endif +#if defined(EDEADLK) && (!defined(EWOULDBLOCK) || (EDEADLK != EWOULDBLOCK)) + case EDEADLK: return "resource deadlock avoided"; +#endif +#ifdef EDEADLOCK + case EDEADLOCK: return "resource deadlock avoided"; +#endif +#ifdef EDESTADDRREQ + case EDESTADDRREQ: return "destination address required"; +#endif +#ifdef EDIRTY + case EDIRTY: return "mounting a dirty fs w/o force"; +#endif +#ifdef EDOM + case EDOM: return "math argument out of range"; +#endif +#ifdef EDOTDOT + case EDOTDOT: return "cross mount point"; +#endif +#ifdef EDQUOT + case EDQUOT: return "disk quota exceeded"; +#endif +#ifdef EDUPPKG + case EDUPPKG: return "duplicate package name"; +#endif +#ifdef EEXIST + case EEXIST: return "file already exists"; +#endif +#ifdef EFAULT + case EFAULT: return "bad address in system call argument"; +#endif +#ifdef EFBIG + case EFBIG: return "file too large"; +#endif +#ifdef EHOSTDOWN + case EHOSTDOWN: return "host is down"; +#endif +#ifdef EHOSTUNREACH + case EHOSTUNREACH: return "host is unreachable"; +#endif +#ifdef EIDRM + case EIDRM: return "identifier removed"; +#endif +#ifdef EINIT + case EINIT: return "initialization error"; +#endif +#ifdef EINPROGRESS + case EINPROGRESS: return "operation now in progress"; +#endif +#ifdef EINTR + case EINTR: return "interrupted system call"; +#endif +#ifdef EINVAL + case EINVAL: return "invalid argument"; +#endif +#ifdef EIO + case EIO: return "I/O error"; +#endif +#ifdef EISCONN + case EISCONN: return "socket is already connected"; +#endif +#ifdef EISDIR + case EISDIR: return "is a directory"; +#endif +#ifdef EISNAME + case EISNAM: return "is a name file"; +#endif +#ifdef ELBIN + case ELBIN: return "ELBIN"; +#endif +#ifdef EL2HLT + case EL2HLT: return "level 2 halted"; +#endif +#ifdef EL2NSYNC + case EL2NSYNC: return "level 2 not synchronized"; +#endif +#ifdef EL3HLT + case EL3HLT: return "level 3 halted"; +#endif +#ifdef EL3RST + case EL3RST: return "level 3 reset"; +#endif +#ifdef ELIBACC + case ELIBACC: return "can not access a needed shared library"; +#endif +#ifdef ELIBBAD + case ELIBBAD: return "accessing a corrupted shared library"; +#endif +#ifdef ELIBEXEC + case ELIBEXEC: return "can not exec a shared library directly"; +#endif +#ifdef ELIBMAX + case ELIBMAX: return "attempting to link in more shared libraries than system limit"; +#endif +#ifdef ELIBSCN + case ELIBSCN: return ".lib section in a.out corrupted"; +#endif +#ifdef ELNRNG + case ELNRNG: return "link number out of range"; +#endif +#ifdef ELOOP + case ELOOP: return "too many levels of symbolic links"; +#endif +#ifdef EMFILE + case EMFILE: return "too many open files"; +#endif +#ifdef EMLINK + case EMLINK: return "too many links"; +#endif +#ifdef EMSGSIZE + case EMSGSIZE: return "message too long"; +#endif +#ifdef EMULTIHOP + case EMULTIHOP: return "multihop attempted"; +#endif +#ifdef ENAMETOOLONG + case ENAMETOOLONG: return "file name too long"; +#endif +#ifdef ENAVAIL + case ENAVAIL: return "not available"; +#endif +#ifdef ENET + case ENET: return "ENET"; +#endif +#ifdef ENETDOWN + case ENETDOWN: return "network is down"; +#endif +#ifdef ENETRESET + case ENETRESET: return "network dropped connection on reset"; +#endif +#ifdef ENETUNREACH + case ENETUNREACH: return "network is unreachable"; +#endif +#ifdef ENFILE + case ENFILE: return "file table overflow"; +#endif +#ifdef ENOANO + case ENOANO: return "anode table overflow"; +#endif +#if defined(ENOBUFS) && (!defined(ENOSR) || (ENOBUFS != ENOSR)) + case ENOBUFS: return "no buffer space available"; +#endif +#ifdef ENOCSI + case ENOCSI: return "no CSI structure available"; +#endif +#ifdef ENODATA + case ENODATA: return "no data available"; +#endif +#ifdef ENODEV + case ENODEV: return "no such device"; +#endif +#ifdef ENOENT + case ENOENT: return "no such file or directory"; +#endif +#ifdef ENOEXEC + case ENOEXEC: return "exec format error"; +#endif +#ifdef ENOLCK + case ENOLCK: return "no locks available"; +#endif +#ifdef ENOLINK + case ENOLINK: return "link has be severed"; +#endif +#ifdef ENOMEM + case ENOMEM: return "not enough memory"; +#endif +#ifdef ENOMSG + case ENOMSG: return "no message of desired type"; +#endif +#ifdef ENONET + case ENONET: return "machine is not on the network"; +#endif +#ifdef ENOPKG + case ENOPKG: return "package not installed"; +#endif +#ifdef ENOPROTOOPT + case ENOPROTOOPT: return "bad proocol option"; +#endif +#ifdef ENOSPC + case ENOSPC: return "no space left on device"; +#endif +#ifdef ENOSR + case ENOSR: return "out of stream resources"; +#endif +#ifdef ENOSTR + case ENOSTR: return "not a stream device"; +#endif +#ifdef ENOSYM + case ENOSYM: return "unresolved symbol name"; +#endif +#ifdef ENOSYS + case ENOSYS: return "function not implemented"; +#endif +#ifdef ENOTBLK + case ENOTBLK: return "block device required"; +#endif +#ifdef ENOTCONN + case ENOTCONN: return "socket is not connected"; +#endif +#ifdef ENOTDIR + case ENOTDIR: return "not a directory"; +#endif +#ifdef ENOTEMPTY + case ENOTEMPTY: return "directory not empty"; +#endif +#ifdef ENOTNAM + case ENOTNAM: return "not a name file"; +#endif +#ifdef ENOTSOCK + case ENOTSOCK: return "socket operation on non-socket"; +#endif +#ifdef ENOTTY + case ENOTTY: return "inappropriate device for ioctl"; +#endif +#ifdef ENOTUNIQ + case ENOTUNIQ: return "name not unique on network"; +#endif +#ifdef ENXIO + case ENXIO: return "no such device or address"; +#endif +#ifdef EOPNOTSUPP + case EOPNOTSUPP: return "operation not supported on socket"; +#endif +#ifdef EPERM + case EPERM: return "not owner"; +#endif +#ifdef EPFNOSUPPORT + case EPFNOSUPPORT: return "protocol family not supported"; +#endif +#ifdef EPIPE + case EPIPE: return "broken pipe"; +#endif +#ifdef EPROCLIM + case EPROCLIM: return "too many processes"; +#endif +#ifdef EPROCUNAVAIL + case EPROCUNAVAIL: return "bad procedure for program"; +#endif +#ifdef EPROGMISMATCH + case EPROGMISMATCH: return "program version wrong"; +#endif +#ifdef EPROGUNAVAIL + case EPROGUNAVAIL: return "RPC program not available"; +#endif +#ifdef EPROTO + case EPROTO: return "protocol error"; +#endif +#ifdef EPROTONOSUPPORT + case EPROTONOSUPPORT: return "protocol not suppored"; +#endif +#ifdef EPROTOTYPE + case EPROTOTYPE: return "protocol wrong type for socket"; +#endif +#ifdef ERANGE + case ERANGE: return "math result unrepresentable"; +#endif +#if defined(EREFUSED) && (!defined(ECONNREFUSED) || (EREFUSED != ECONNREFUSED)) + case EREFUSED: return "EREFUSED"; +#endif +#ifdef EREMCHG + case EREMCHG: return "remote address changed"; +#endif +#ifdef EREMDEV + case EREMDEV: return "remote device"; +#endif +#ifdef EREMOTE + case EREMOTE: return "pathname hit remote file system"; +#endif +#ifdef EREMOTEIO + case EREMOTEIO: return "remote i/o error"; +#endif +#ifdef EREMOTERELEASE + case EREMOTERELEASE: return "EREMOTERELEASE"; +#endif +#ifdef EROFS + case EROFS: return "read-only file system"; +#endif +#ifdef ERPCMISMATCH + case ERPCMISMATCH: return "RPC version is wrong"; +#endif +#ifdef ERREMOTE + case ERREMOTE: return "object is remote"; +#endif +#ifdef ESHUTDOWN + case ESHUTDOWN: return "can't send afer socket shutdown"; +#endif +#ifdef ESOCKTNOSUPPORT + case ESOCKTNOSUPPORT: return "socket type not supported"; +#endif +#ifdef ESPIPE + case ESPIPE: return "invalid seek"; +#endif +#ifdef ESRCH + case ESRCH: return "no such process"; +#endif +#ifdef ESRMNT + case ESRMNT: return "srmount error"; +#endif +#ifdef ESTALE + case ESTALE: return "stale remote file handle"; +#endif +#ifdef ESUCCESS + case ESUCCESS: return "Error 0"; +#endif +#ifdef ETIME + case ETIME: return "timer expired"; +#endif +#ifdef ETIMEDOUT + case ETIMEDOUT: return "connection timed out"; +#endif +#ifdef ETOOMANYREFS + case ETOOMANYREFS: return "too many references: can't splice"; +#endif +#ifdef ETXTBSY + case ETXTBSY: return "text file or pseudo-device busy"; +#endif +#ifdef EUCLEAN + case EUCLEAN: return "structure needs cleaning"; +#endif +#ifdef EUNATCH + case EUNATCH: return "protocol driver not attached"; +#endif +#ifdef EUSERS + case EUSERS: return "too many users"; +#endif +#ifdef EVERSION + case EVERSION: return "version mismatch"; +#endif +#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN)) + case EWOULDBLOCK: return "operation would block"; +#endif +#ifdef EXDEV + case EXDEV: return "cross-domain link"; +#endif +#ifdef EXFULL + case EXFULL: return "message tables full"; +#endif + } +#else /* NO_SYS_ERRLIST */ + extern int sys_nerr; + extern char *sys_errlist[]; + + if ((errnum > 0) && (errnum <= sys_nerr)) + return sys_errlist [errnum]; +#endif /* NO_SYS_ERRLIST */ + + msg = g_static_private_get (&msg_private); + if (!msg) + { + msg = g_new (gchar, 64); + g_static_private_set (&msg_private, msg, g_free); + } + + _g_sprintf (msg, "unknown error (%d)", errnum); + + errno = saved_errno; + return msg; +} + +G_CONST_RETURN gchar* +g_strsignal (gint signum) +{ + static GStaticPrivate msg_private = G_STATIC_PRIVATE_INIT; + char *msg; + +#ifdef HAVE_STRSIGNAL + const char *msg_locale; + +#if defined(G_OS_BEOS) || defined(G_WITH_CYGWIN) +extern const char *strsignal(int); +#else + /* this is declared differently (const) in string.h on BeOS */ + extern char *strsignal (int sig); +#endif /* !G_OS_BEOS && !G_WITH_CYGWIN */ + msg_locale = strsignal (signum); + if (g_get_charset (NULL)) + return msg_locale; + else + { + gchar *msg_utf8 = g_locale_to_utf8 (msg_locale, -1, NULL, NULL, NULL); + if (msg_utf8) + { + /* Stick in the quark table so that we can return a static result + */ + GQuark msg_quark = g_quark_from_string (msg_utf8); + g_free (msg_utf8); + + return g_quark_to_string (msg_quark); + } + } +#elif NO_SYS_SIGLIST + switch (signum) + { +#ifdef SIGHUP + case SIGHUP: return "Hangup"; +#endif +#ifdef SIGINT + case SIGINT: return "Interrupt"; +#endif +#ifdef SIGQUIT + case SIGQUIT: return "Quit"; +#endif +#ifdef SIGILL + case SIGILL: return "Illegal instruction"; +#endif +#ifdef SIGTRAP + case SIGTRAP: return "Trace/breakpoint trap"; +#endif +#ifdef SIGABRT + case SIGABRT: return "IOT trap/Abort"; +#endif +#ifdef SIGBUS + case SIGBUS: return "Bus error"; +#endif +#ifdef SIGFPE + case SIGFPE: return "Floating point exception"; +#endif +#ifdef SIGKILL + case SIGKILL: return "Killed"; +#endif +#ifdef SIGUSR1 + case SIGUSR1: return "User defined signal 1"; +#endif +#ifdef SIGSEGV + case SIGSEGV: return "Segmentation fault"; +#endif +#ifdef SIGUSR2 + case SIGUSR2: return "User defined signal 2"; +#endif +#ifdef SIGPIPE + case SIGPIPE: return "Broken pipe"; +#endif +#ifdef SIGALRM + case SIGALRM: return "Alarm clock"; +#endif +#ifdef SIGTERM + case SIGTERM: return "Terminated"; +#endif +#ifdef SIGSTKFLT + case SIGSTKFLT: return "Stack fault"; +#endif +#ifdef SIGCHLD + case SIGCHLD: return "Child exited"; +#endif +#ifdef SIGCONT + case SIGCONT: return "Continued"; +#endif +#ifdef SIGSTOP + case SIGSTOP: return "Stopped (signal)"; +#endif +#ifdef SIGTSTP + case SIGTSTP: return "Stopped"; +#endif +#ifdef SIGTTIN + case SIGTTIN: return "Stopped (tty input)"; +#endif +#ifdef SIGTTOU + case SIGTTOU: return "Stopped (tty output)"; +#endif +#ifdef SIGURG + case SIGURG: return "Urgent condition"; +#endif +#ifdef SIGXCPU + case SIGXCPU: return "CPU time limit exceeded"; +#endif +#ifdef SIGXFSZ + case SIGXFSZ: return "File size limit exceeded"; +#endif +#ifdef SIGVTALRM + case SIGVTALRM: return "Virtual time alarm"; +#endif +#ifdef SIGPROF + case SIGPROF: return "Profile signal"; +#endif +#ifdef SIGWINCH + case SIGWINCH: return "Window size changed"; +#endif +#ifdef SIGIO + case SIGIO: return "Possible I/O"; +#endif +#ifdef SIGPWR + case SIGPWR: return "Power failure"; +#endif +#ifdef SIGUNUSED + case SIGUNUSED: return "Unused signal"; +#endif + } +#else /* NO_SYS_SIGLIST */ + +#ifdef NO_SYS_SIGLIST_DECL + extern char *sys_siglist[]; /*(see Tue Jan 19 00:44:24 1999 in changelog)*/ +#endif + + return (char*) /* this function should return const --josh */ sys_siglist [signum]; +#endif /* NO_SYS_SIGLIST */ + + msg = g_static_private_get (&msg_private); + if (!msg) + { + msg = g_new (gchar, 64); + g_static_private_set (&msg_private, msg, g_free); + } + + _g_sprintf (msg, "unknown signal (%d)", signum); + + return msg; +} + +/* Functions g_strlcpy and g_strlcat were originally developed by + * Todd C. Miller to simplify writing secure code. + * See ftp://ftp.openbsd.org/pub/OpenBSD/src/lib/libc/string/strlcpy.3 + * for more information. + */ + +#ifdef HAVE_STRLCPY +/* Use the native ones, if available; they might be implemented in assembly */ +gsize +g_strlcpy (gchar *dest, + const gchar *src, + gsize dest_size) +{ + g_return_val_if_fail (dest != NULL, 0); + g_return_val_if_fail (src != NULL, 0); + + return strlcpy (dest, src, dest_size); +} + +gsize +g_strlcat (gchar *dest, + const gchar *src, + gsize dest_size) +{ + g_return_val_if_fail (dest != NULL, 0); + g_return_val_if_fail (src != NULL, 0); + + return strlcat (dest, src, dest_size); +} + +#else /* ! HAVE_STRLCPY */ +/* g_strlcpy + * + * Copy string src to buffer dest (of buffer size dest_size). At most + * dest_size-1 characters will be copied. Always NUL terminates + * (unless dest_size == 0). This function does NOT allocate memory. + * Unlike strncpy, this function doesn't pad dest (so it's often faster). + * Returns size of attempted result, strlen(src), + * so if retval >= dest_size, truncation occurred. + */ +gsize +g_strlcpy (gchar *dest, + const gchar *src, + gsize dest_size) +{ + register gchar *d = dest; + register const gchar *s = src; + register gsize n = dest_size; + + g_return_val_if_fail (dest != NULL, 0); + g_return_val_if_fail (src != NULL, 0); + + /* Copy as many bytes as will fit */ + if (n != 0 && --n != 0) + do + { + register gchar c = *s++; + + *d++ = c; + if (c == 0) + break; + } + while (--n != 0); + + /* If not enough room in dest, add NUL and traverse rest of src */ + if (n == 0) + { + if (dest_size != 0) + *d = 0; + while (*s++) + ; + } + + return s - src - 1; /* count does not include NUL */ +} + +/* g_strlcat + * + * Appends string src to buffer dest (of buffer size dest_size). + * At most dest_size-1 characters will be copied. + * Unlike strncat, dest_size is the full size of dest, not the space left over. + * This function does NOT allocate memory. + * This always NUL terminates (unless siz == 0 or there were no NUL characters + * in the dest_size characters of dest to start with). + * Returns size of attempted result, which is + * MIN (dest_size, strlen (original dest)) + strlen (src), + * so if retval >= dest_size, truncation occurred. + */ +gsize +g_strlcat (gchar *dest, + const gchar *src, + gsize dest_size) +{ + register gchar *d = dest; + register const gchar *s = src; + register gsize bytes_left = dest_size; + gsize dlength; /* Logically, MIN (strlen (d), dest_size) */ + + g_return_val_if_fail (dest != NULL, 0); + g_return_val_if_fail (src != NULL, 0); + + /* Find the end of dst and adjust bytes left but don't go past end */ + while (*d != 0 && bytes_left-- != 0) + d++; + dlength = d - dest; + bytes_left = dest_size - dlength; + + if (bytes_left == 0) + return dlength + strlen (s); + + while (*s != 0) + { + if (bytes_left != 1) + { + *d++ = *s; + bytes_left--; + } + s++; + } + *d = 0; + + return dlength + (s - src); /* count does not include NUL */ +} +#endif /* ! HAVE_STRLCPY */ + +/** + * g_ascii_strdown: + * @str: a string. + * @len: length of @str in bytes, or -1 if @str is nul-terminated. + * + * Converts all upper case ASCII letters to lower case ASCII letters. + * + * Return value: a newly-allocated string, with all the upper case + * characters in @str converted to lower case, with + * semantics that exactly match g_ascii_tolower(). (Note + * that this is unlike the old g_strdown(), which modified + * the string in place.) + **/ +gchar* +g_ascii_strdown (const gchar *str, + gssize len) +{ + gchar *result, *s; + + g_return_val_if_fail (str != NULL, NULL); + + if (len < 0) + len = strlen (str); + + result = g_strndup (str, len); + for (s = result; *s; s++) + *s = g_ascii_tolower (*s); + + return result; +} + +#endif + +/** + * g_ascii_strup: + * @str: a string. + * @len: length of @str in bytes, or -1 if @str is nul-terminated. + * + * Converts all lower case ASCII letters to upper case ASCII letters. + * + * Return value: a newly allocated string, with all the lower case + * characters in @str converted to upper case, with + * semantics that exactly match g_ascii_toupper(). (Note + * that this is unlike the old g_strup(), which modified + * the string in place.) + **/ +gchar* +g_ascii_strup (const gchar *str, + gssize len) +{ + gchar *result, *s; + + g_return_val_if_fail (str != NULL, NULL); + + if (len < 0) + len = strlen (str); + + result = g_strndup (str, len); + for (s = result; *s; s++) + *s = g_ascii_toupper (*s); + + return result; +} + +#if 0 + +/** + * g_strdown: + * @string: the string to convert. + * + * Converts a string to lower case. + * + * Return value: the string + * + * Deprecated:2.2: This function is totally broken for the reasons discussed + * in the g_strncasecmp() docs - use g_ascii_strdown() or g_utf8_strdown() + * instead. + **/ +gchar* +g_strdown (gchar *string) +{ + register guchar *s; + + g_return_val_if_fail (string != NULL, NULL); + + s = (guchar *) string; + + while (*s) + { + if (isupper (*s)) + *s = tolower (*s); + s++; + } + + return (gchar *) string; +} + +/** + * g_strup: + * @string: the string to convert. + * + * Converts a string to upper case. + * + * Return value: the string + * + * Deprecated:2.2: This function is totally broken for the reasons discussed + * in the g_strncasecmp() docs - use g_ascii_strup() or g_utf8_strup() instead. + **/ +gchar* +g_strup (gchar *string) +{ + register guchar *s; + + g_return_val_if_fail (string != NULL, NULL); + + s = (guchar *) string; + + while (*s) + { + if (islower (*s)) + *s = toupper (*s); + s++; + } + + return (gchar *) string; +} + +gchar* +g_strreverse (gchar *string) +{ + g_return_val_if_fail (string != NULL, NULL); + + if (*string) + { + register gchar *h, *t; + + h = string; + t = string + strlen (string) - 1; + + while (h < t) + { + register gchar c; + + c = *h; + *h = *t; + h++; + *t = c; + t--; + } + } + + return string; +} + +/** + * g_ascii_tolower: + * @c: any character. + * + * Convert a character to ASCII lower case. + * + * Unlike the standard C library tolower() function, this only + * recognizes standard ASCII letters and ignores the locale, returning + * all non-ASCII characters unchanged, even if they are lower case + * letters in a particular character set. Also unlike the standard + * library function, this takes and returns a char, not an int, so + * don't call it on %EOF but no need to worry about casting to #guchar + * before passing a possibly non-ASCII character in. + * + * Return value: the result of converting @c to lower case. + * If @c is not an ASCII upper case letter, + * @c is returned unchanged. + **/ +gchar +g_ascii_tolower (gchar c) +{ + return g_ascii_isupper (c) ? c - 'A' + 'a' : c; +} + +#endif + +/** + * g_ascii_toupper: + * @c: any character. + * + * Convert a character to ASCII upper case. + * + * Unlike the standard C library toupper() function, this only + * recognizes standard ASCII letters and ignores the locale, returning + * all non-ASCII characters unchanged, even if they are upper case + * letters in a particular character set. Also unlike the standard + * library function, this takes and returns a char, not an int, so + * don't call it on %EOF but no need to worry about casting to #guchar + * before passing a possibly non-ASCII character in. + * + * Return value: the result of converting @c to upper case. + * If @c is not an ASCII lower case letter, + * @c is returned unchanged. + **/ +gchar +g_ascii_toupper (gchar c) +{ + return g_ascii_islower (c) ? c - 'a' + 'A' : c; +} + +#if 0 + +/** + * g_ascii_digit_value: + * @c: an ASCII character. + * + * Determines the numeric value of a character as a decimal + * digit. Differs from g_unichar_digit_value() because it takes + * a char, so there's no worry about sign extension if characters + * are signed. + * + * Return value: If @c is a decimal digit (according to + * g_ascii_isdigit()), its numeric value. Otherwise, -1. + **/ +int +g_ascii_digit_value (gchar c) +{ + if (g_ascii_isdigit (c)) + return c - '0'; + return -1; +} + +/** + * g_ascii_xdigit_value: + * @c: an ASCII character. + * + * Determines the numeric value of a character as a hexidecimal + * digit. Differs from g_unichar_xdigit_value() because it takes + * a char, so there's no worry about sign extension if characters + * are signed. + * + * Return value: If @c is a hex digit (according to + * g_ascii_isxdigit()), its numeric value. Otherwise, -1. + **/ +int +g_ascii_xdigit_value (gchar c) +{ + if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + return g_ascii_digit_value (c); +} + +/** + * g_ascii_strcasecmp: + * @s1: string to compare with @s2. + * @s2: string to compare with @s1. + * + * Compare two strings, ignoring the case of ASCII characters. + * + * Unlike the BSD strcasecmp() function, this only recognizes standard + * ASCII letters and ignores the locale, treating all non-ASCII + * bytes as if they are not letters. + * + * This function should be used only on strings that are known to be + * in encodings where the bytes corresponding to ASCII letters always + * represent themselves. This includes UTF-8 and the ISO-8859-* + * charsets, but not for instance double-byte encodings like the + * Windows Codepage 932, where the trailing bytes of double-byte + * characters include all ASCII letters. If you compare two CP932 + * strings using this function, you will get false matches. + * + * Return value: 0 if the strings match, a negative value if @s1 < @s2, + * or a positive value if @s1 > @s2. + **/ +gint +g_ascii_strcasecmp (const gchar *s1, + const gchar *s2) +{ + gint c1, c2; + + g_return_val_if_fail (s1 != NULL, 0); + g_return_val_if_fail (s2 != NULL, 0); + + while (*s1 && *s2) + { + c1 = (gint)(guchar) TOLOWER (*s1); + c2 = (gint)(guchar) TOLOWER (*s2); + if (c1 != c2) + return (c1 - c2); + s1++; s2++; + } + + return (((gint)(guchar) *s1) - ((gint)(guchar) *s2)); +} + +/** + * g_ascii_strncasecmp: + * @s1: string to compare with @s2. + * @s2: string to compare with @s1. + * @n: number of characters to compare. + * + * Compare @s1 and @s2, ignoring the case of ASCII characters and any + * characters after the first @n in each string. + * + * Unlike the BSD strcasecmp() function, this only recognizes standard + * ASCII letters and ignores the locale, treating all non-ASCII + * characters as if they are not letters. + * + * The same warning as in g_ascii_strcasecmp() applies: Use this + * function only on strings known to be in encodings where bytes + * corresponding to ASCII letters always represent themselves. + * + * Return value: 0 if the strings match, a negative value if @s1 < @s2, + * or a positive value if @s1 > @s2. + **/ +gint +g_ascii_strncasecmp (const gchar *s1, + const gchar *s2, + gsize n) +{ + gint c1, c2; + + g_return_val_if_fail (s1 != NULL, 0); + g_return_val_if_fail (s2 != NULL, 0); + + while (n && *s1 && *s2) + { + n -= 1; + c1 = (gint)(guchar) TOLOWER (*s1); + c2 = (gint)(guchar) TOLOWER (*s2); + if (c1 != c2) + return (c1 - c2); + s1++; s2++; + } + + if (n) + return (((gint) (guchar) *s1) - ((gint) (guchar) *s2)); + else + return 0; +} + +/** + * g_strcasecmp: + * @s1: a string. + * @s2: a string to compare with @s1. + * + * A case-insensitive string comparison, corresponding to the standard + * strcasecmp() function on platforms which support it. + * + * Return value: 0 if the strings match, a negative value if @s1 < @s2, + * or a positive value if @s1 > @s2. + * + * Deprecated:2.2: See g_strncasecmp() for a discussion of why this function + * is deprecated and how to replace it. + **/ +gint +g_strcasecmp (const gchar *s1, + const gchar *s2) +{ +#ifdef HAVE_STRCASECMP + g_return_val_if_fail (s1 != NULL, 0); + g_return_val_if_fail (s2 != NULL, 0); + + return strcasecmp (s1, s2); +#else + gint c1, c2; + + g_return_val_if_fail (s1 != NULL, 0); + g_return_val_if_fail (s2 != NULL, 0); + + while (*s1 && *s2) + { + /* According to A. Cox, some platforms have islower's that + * don't work right on non-uppercase + */ + c1 = isupper ((guchar)*s1) ? tolower ((guchar)*s1) : *s1; + c2 = isupper ((guchar)*s2) ? tolower ((guchar)*s2) : *s2; + if (c1 != c2) + return (c1 - c2); + s1++; s2++; + } + + return (((gint)(guchar) *s1) - ((gint)(guchar) *s2)); +#endif +} + +/** + * g_strncasecmp: + * @s1: a string. + * @s2: a string to compare with @s1. + * @n: the maximum number of characters to compare. + * + * A case-insensitive string comparison, corresponding to the standard + * strncasecmp() function on platforms which support it. + * It is similar to g_strcasecmp() except it only compares the first @n + * characters of the strings. + * + * Return value: 0 if the strings match, a negative value if @s1 < @s2, + * or a positive value if @s1 > @s2. + * + * Deprecated:2.2: The problem with g_strncasecmp() is that it does the + * comparison by calling toupper()/tolower(). These functions are + * locale-specific and operate on single bytes. However, it is impossible + * to handle things correctly from an I18N standpoint by operating on + * bytes, since characters may be multibyte. Thus g_strncasecmp() is + * broken if your string is guaranteed to be ASCII, since it's + * locale-sensitive, and it's broken if your string is localized, since + * it doesn't work on many encodings at all, including UTF-8, EUC-JP, + * etc. + * + * There are therefore two replacement functions: g_ascii_strncasecmp(), + * which only works on ASCII and is not locale-sensitive, and + * g_utf8_casefold(), which is good for case-insensitive sorting of UTF-8. + **/ +gint +g_strncasecmp (const gchar *s1, + const gchar *s2, + guint n) +{ +#ifdef HAVE_STRNCASECMP + return strncasecmp (s1, s2, n); +#else + gint c1, c2; + + g_return_val_if_fail (s1 != NULL, 0); + g_return_val_if_fail (s2 != NULL, 0); + + while (n && *s1 && *s2) + { + n -= 1; + /* According to A. Cox, some platforms have islower's that + * don't work right on non-uppercase + */ + c1 = isupper ((guchar)*s1) ? tolower ((guchar)*s1) : *s1; + c2 = isupper ((guchar)*s2) ? tolower ((guchar)*s2) : *s2; + if (c1 != c2) + return (c1 - c2); + s1++; s2++; + } + + if (n) + return (((gint) (guchar) *s1) - ((gint) (guchar) *s2)); + else + return 0; +#endif +} + +gchar* +g_strdelimit (gchar *string, + const gchar *delimiters, + gchar new_delim) +{ + register gchar *c; + + g_return_val_if_fail (string != NULL, NULL); + + if (!delimiters) + delimiters = G_STR_DELIMITERS; + + for (c = string; *c; c++) + { + if (strchr (delimiters, *c)) + *c = new_delim; + } + + return string; +} + +gchar* +g_strcanon (gchar *string, + const gchar *valid_chars, + gchar substitutor) +{ + register gchar *c; + + g_return_val_if_fail (string != NULL, NULL); + g_return_val_if_fail (valid_chars != NULL, NULL); + + for (c = string; *c; c++) + { + if (!strchr (valid_chars, *c)) + *c = substitutor; + } + + return string; +} + +gchar* +g_strcompress (const gchar *source) +{ + const gchar *p = source, *octal; + gchar *dest = g_malloc (strlen (source) + 1); + gchar *q = dest; + + while (*p) + { + if (*p == '\\') + { + p++; + switch (*p) + { + case '\0': + g_warning ("g_strcompress: trailing \\"); + goto out; + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': + *q = 0; + octal = p; + while ((p < octal + 3) && (*p >= '0') && (*p <= '7')) + { + *q = (*q * 8) + (*p - '0'); + p++; + } + q++; + p--; + break; + case 'b': + *q++ = '\b'; + break; + case 'f': + *q++ = '\f'; + break; + case 'n': + *q++ = '\n'; + break; + case 'r': + *q++ = '\r'; + break; + case 't': + *q++ = '\t'; + break; + default: /* Also handles \" and \\ */ + *q++ = *p; + break; + } + } + else + *q++ = *p; + p++; + } +out: + *q = 0; + + return dest; +} + +gchar * +g_strescape (const gchar *source, + const gchar *exceptions) +{ + const guchar *p; + gchar *dest; + gchar *q; + guchar excmap[256]; + + g_return_val_if_fail (source != NULL, NULL); + + p = (guchar *) source; + /* Each source byte needs maximally four destination chars (\777) */ + q = dest = g_malloc (strlen (source) * 4 + 1); + + memset (excmap, 0, 256); + if (exceptions) + { + guchar *e = (guchar *) exceptions; + + while (*e) + { + excmap[*e] = 1; + e++; + } + } + + while (*p) + { + if (excmap[*p]) + *q++ = *p; + else + { + switch (*p) + { + case '\b': + *q++ = '\\'; + *q++ = 'b'; + break; + case '\f': + *q++ = '\\'; + *q++ = 'f'; + break; + case '\n': + *q++ = '\\'; + *q++ = 'n'; + break; + case '\r': + *q++ = '\\'; + *q++ = 'r'; + break; + case '\t': + *q++ = '\\'; + *q++ = 't'; + break; + case '\\': + *q++ = '\\'; + *q++ = '\\'; + break; + case '"': + *q++ = '\\'; + *q++ = '"'; + break; + default: + if ((*p < ' ') || (*p >= 0177)) + { + *q++ = '\\'; + *q++ = '0' + (((*p) >> 6) & 07); + *q++ = '0' + (((*p) >> 3) & 07); + *q++ = '0' + ((*p) & 07); + } + else + *q++ = *p; + break; + } + } + p++; + } + *q = 0; + return dest; +} + +gchar* +g_strchug (gchar *string) +{ + guchar *start; + + g_return_val_if_fail (string != NULL, NULL); + + for (start = (guchar*) string; *start && g_ascii_isspace (*start); start++) + ; + + g_memmove (string, start, strlen ((gchar *) start) + 1); + + return string; +} + +gchar* +g_strchomp (gchar *string) +{ + gsize len; + + g_return_val_if_fail (string != NULL, NULL); + + len = strlen (string); + while (len--) + { + if (g_ascii_isspace ((guchar) string[len])) + string[len] = '\0'; + else + break; + } + + return string; +} + +/** + * g_strsplit: + * @string: a string to split. + * @delimiter: a string which specifies the places at which to split the string. + * The delimiter is not included in any of the resulting strings, unless + * @max_tokens is reached. + * @max_tokens: the maximum number of pieces to split @string into. If this is + * less than 1, the string is split completely. + * + * Splits a string into a maximum of @max_tokens pieces, using the given + * @delimiter. If @max_tokens is reached, the remainder of @string is appended + * to the last token. + * + * As a special case, the result of splitting the empty string "" is an empty + * vector, not a vector containing a single string. The reason for this + * special case is that being able to represent a empty vector is typically + * more useful than consistent handling of empty elements. If you do need + * to represent empty elements, you'll need to check for the empty string + * before calling g_strsplit(). + * + * Return value: a newly-allocated %NULL-terminated array of strings. Use + * g_strfreev() to free it. + **/ +gchar** +g_strsplit (const gchar *string, + const gchar *delimiter, + gint max_tokens) +{ + GSList *string_list = NULL, *slist; + gchar **str_array, *s; + guint n = 0; + const gchar *remainder; + + g_return_val_if_fail (string != NULL, NULL); + g_return_val_if_fail (delimiter != NULL, NULL); + g_return_val_if_fail (delimiter[0] != '\0', NULL); + + if (max_tokens < 1) + max_tokens = G_MAXINT; + + remainder = string; + s = strstr (remainder, delimiter); + if (s) + { + gsize delimiter_len = strlen (delimiter); + + while (--max_tokens && s) + { + gsize len; + gchar *new_string; + + len = s - remainder; + new_string = g_new (gchar, len + 1); + strncpy (new_string, remainder, len); + new_string[len] = 0; + string_list = g_slist_prepend (string_list, new_string); + n++; + remainder = s + delimiter_len; + s = strstr (remainder, delimiter); + } + } + if (*string) + { + n++; + string_list = g_slist_prepend (string_list, g_strdup (remainder)); + } + + str_array = g_new (gchar*, n + 1); + + str_array[n--] = NULL; + for (slist = string_list; slist; slist = slist->next) + str_array[n--] = slist->data; + + g_slist_free (string_list); + + return str_array; +} + +/** + * g_strsplit_set: + * @string: The string to be tokenized + * @delimiters: A nul-terminated string containing bytes that are used + * to split the string. + * @max_tokens: The maximum number of tokens to split @string into. + * If this is less than 1, the string is split completely + * + * Splits @string into a number of tokens not containing any of the characters + * in @delimiter. A token is the (possibly empty) longest string that does not + * contain any of the characters in @delimiters. If @max_tokens is reached, the + * remainder is appended to the last token. + * + * For example the result of g_strsplit_set ("abc:def/ghi", ":/", -1) is a + * %NULL-terminated vector containing the three strings "abc", "def", + * and "ghi". + * + * The result if g_strsplit_set (":def/ghi:", ":/", -1) is a %NULL-terminated + * vector containing the four strings "", "def", "ghi", and "". + * + * As a special case, the result of splitting the empty string "" is an empty + * vector, not a vector containing a single string. The reason for this + * special case is that being able to represent a empty vector is typically + * more useful than consistent handling of empty elements. If you do need + * to represent empty elements, you'll need to check for the empty string + * before calling g_strsplit_set(). + * + * Note that this function works on bytes not characters, so it can't be used + * to delimit UTF-8 strings for anything but ASCII characters. + * + * Return value: a newly-allocated %NULL-terminated array of strings. Use + * g_strfreev() to free it. + * + * Since: 2.4 + **/ +gchar ** +g_strsplit_set (const gchar *string, + const gchar *delimiters, + gint max_tokens) +{ + gboolean delim_table[256]; + GSList *tokens, *list; + gint n_tokens; + const gchar *s; + const gchar *current; + gchar *token; + gchar **result; + + g_return_val_if_fail (string != NULL, NULL); + g_return_val_if_fail (delimiters != NULL, NULL); + + if (max_tokens < 1) + max_tokens = G_MAXINT; + + if (*string == '\0') + { + result = g_new (char *, 1); + result[0] = NULL; + return result; + } + + memset (delim_table, FALSE, sizeof (delim_table)); + for (s = delimiters; *s != '\0'; ++s) + delim_table[*(guchar *)s] = TRUE; + + tokens = NULL; + n_tokens = 0; + + s = current = string; + while (*s != '\0') + { + if (delim_table[*(guchar *)s] && n_tokens + 1 < max_tokens) + { + gchar *token; + + token = g_strndup (current, s - current); + tokens = g_slist_prepend (tokens, token); + ++n_tokens; + + current = s + 1; + } + + ++s; + } + + token = g_strndup (current, s - current); + tokens = g_slist_prepend (tokens, token); + ++n_tokens; + + result = g_new (gchar *, n_tokens + 1); + + result[n_tokens] = NULL; + for (list = tokens; list != NULL; list = list->next) + result[--n_tokens] = list->data; + + g_slist_free (tokens); + + return result; +} + +/** + * g_strfreev: + * @str_array: a %NULL-terminated array of strings to free. + + * Frees a %NULL-terminated array of strings, and the array itself. + * If called on a %NULL value, g_strfreev() simply returns. + **/ +void +g_strfreev (gchar **str_array) +{ + if (str_array) + { + int i; + + for(i = 0; str_array[i] != NULL; i++) + g_free(str_array[i]); + + g_free (str_array); + } +} + +/** + * g_strdupv: + * @str_array: %NULL-terminated array of strings. + * + * Copies %NULL-terminated array of strings. The copy is a deep copy; + * the new array should be freed by first freeing each string, then + * the array itself. g_strfreev() does this for you. If called + * on a %NULL value, g_strdupv() simply returns %NULL. + * + * Return value: a new %NULL-terminated array of strings. + **/ +gchar** +g_strdupv (gchar **str_array) +{ + if (str_array) + { + gint i; + gchar **retval; + + i = 0; + while (str_array[i]) + ++i; + + retval = g_new (gchar*, i + 1); + + i = 0; + while (str_array[i]) + { + retval[i] = g_strdup (str_array[i]); + ++i; + } + retval[i] = NULL; + + return retval; + } + else + return NULL; +} + +gchar* +g_strjoinv (const gchar *separator, + gchar **str_array) +{ + gchar *string; + gchar *ptr; + + g_return_val_if_fail (str_array != NULL, NULL); + + if (separator == NULL) + separator = ""; + + if (*str_array) + { + gint i; + gsize len; + gsize separator_len; + + separator_len = strlen (separator); + /* First part, getting length */ + len = 1 + strlen (str_array[0]); + for (i = 1; str_array[i] != NULL; i++) + len += strlen (str_array[i]); + len += separator_len * (i - 1); + + /* Second part, building string */ + string = g_new (gchar, len); + ptr = g_stpcpy (string, *str_array); + for (i = 1; str_array[i] != NULL; i++) + { + ptr = g_stpcpy (ptr, separator); + ptr = g_stpcpy (ptr, str_array[i]); + } + } + else + string = g_strdup (""); + + return string; +} + +gchar* +g_strjoin (const gchar *separator, + ...) +{ + gchar *string, *s; + va_list args; + gsize len; + gsize separator_len; + gchar *ptr; + + if (separator == NULL) + separator = ""; + + separator_len = strlen (separator); + + va_start (args, separator); + + s = va_arg (args, gchar*); + + if (s) + { + /* First part, getting length */ + len = 1 + strlen (s); + + s = va_arg (args, gchar*); + while (s) + { + len += separator_len + strlen (s); + s = va_arg (args, gchar*); + } + va_end (args); + + /* Second part, building string */ + string = g_new (gchar, len); + + va_start (args, separator); + + s = va_arg (args, gchar*); + ptr = g_stpcpy (string, s); + + s = va_arg (args, gchar*); + while (s) + { + ptr = g_stpcpy (ptr, separator); + ptr = g_stpcpy (ptr, s); + s = va_arg (args, gchar*); + } + } + else + string = g_strdup (""); + + va_end (args); + + return string; +} + +#endif + +/** + * g_strstr_len: + * @haystack: a string. + * @haystack_len: the maximum length of @haystack. + * @needle: the string to search for. + * + * Searches the string @haystack for the first occurrence + * of the string @needle, limiting the length of the search + * to @haystack_len. + * + * Return value: a pointer to the found occurrence, or + * %NULL if not found. + **/ +gchar * +g_strstr_len (const gchar *haystack, + gssize haystack_len, + const gchar *needle) +{ + g_return_val_if_fail (haystack != NULL, NULL); + g_return_val_if_fail (needle != NULL, NULL); + + if (haystack_len < 0) + return strstr (haystack, needle); + else + { + const gchar *p = haystack; + gsize needle_len = strlen (needle); + const gchar *end; + gsize i; + + if (needle_len == 0) + return (gchar *)haystack; + + if (haystack_len < needle_len) + return NULL; + + end = haystack + haystack_len - needle_len; + + while (*p && p <= end) + { + for (i = 0; i < needle_len; i++) + if (p[i] != needle[i]) + goto next; + + return (gchar *)p; + + next: + p++; + } + + return NULL; + } +} + +#if 0 + +/** + * g_strrstr: + * @haystack: a nul-terminated string. + * @needle: the nul-terminated string to search for. + * + * Searches the string @haystack for the last occurrence + * of the string @needle. + * + * Return value: a pointer to the found occurrence, or + * %NULL if not found. + **/ +gchar * +g_strrstr (const gchar *haystack, + const gchar *needle) +{ + gsize i; + gsize needle_len; + gsize haystack_len; + const gchar *p; + + g_return_val_if_fail (haystack != NULL, NULL); + g_return_val_if_fail (needle != NULL, NULL); + + needle_len = strlen (needle); + haystack_len = strlen (haystack); + + if (needle_len == 0) + return (gchar *)haystack; + + if (haystack_len < needle_len) + return NULL; + + p = haystack + haystack_len - needle_len; + + while (p >= haystack) + { + for (i = 0; i < needle_len; i++) + if (p[i] != needle[i]) + goto next; + + return (gchar *)p; + + next: + p--; + } + + return NULL; +} + +/** + * g_strrstr_len: + * @haystack: a nul-terminated string. + * @haystack_len: the maximum length of @haystack. + * @needle: the nul-terminated string to search for. + * + * Searches the string @haystack for the last occurrence + * of the string @needle, limiting the length of the search + * to @haystack_len. + * + * Return value: a pointer to the found occurrence, or + * %NULL if not found. + **/ +gchar * +g_strrstr_len (const gchar *haystack, + gssize haystack_len, + const gchar *needle) +{ + g_return_val_if_fail (haystack != NULL, NULL); + g_return_val_if_fail (needle != NULL, NULL); + + if (haystack_len < 0) + return g_strrstr (haystack, needle); + else + { + gsize needle_len = strlen (needle); + const gchar *haystack_max = haystack + haystack_len; + const gchar *p = haystack; + gsize i; + + while (p < haystack_max && *p) + p++; + + if (p < haystack + needle_len) + return NULL; + + p -= needle_len; + + while (p >= haystack) + { + for (i = 0; i < needle_len; i++) + if (p[i] != needle[i]) + goto next; + + return (gchar *)p; + + next: + p--; + } + + return NULL; + } +} + + +/** + * g_str_has_suffix: + * @str: a nul-terminated string. + * @suffix: the nul-terminated suffix to look for. + * + * Looks whether the string @str ends with @suffix. + * + * Return value: %TRUE if @str end with @suffix, %FALSE otherwise. + * + * Since: 2.2 + **/ +gboolean +g_str_has_suffix (const gchar *str, + const gchar *suffix) +{ + int str_len; + int suffix_len; + + g_return_val_if_fail (str != NULL, FALSE); + g_return_val_if_fail (suffix != NULL, FALSE); + + str_len = strlen (str); + suffix_len = strlen (suffix); + + if (str_len < suffix_len) + return FALSE; + + return strcmp (str + str_len - suffix_len, suffix) == 0; +} + +/** + * g_str_has_prefix: + * @str: a nul-terminated string. + * @prefix: the nul-terminated prefix to look for. + * + * Looks whether the string @str begins with @prefix. + * + * Return value: %TRUE if @str begins with @prefix, %FALSE otherwise. + * + * Since: 2.2 + **/ +gboolean +g_str_has_prefix (const gchar *str, + const gchar *prefix) +{ + int str_len; + int prefix_len; + + g_return_val_if_fail (str != NULL, FALSE); + g_return_val_if_fail (prefix != NULL, FALSE); + + str_len = strlen (str); + prefix_len = strlen (prefix); + + if (str_len < prefix_len) + return FALSE; + + return strncmp (str, prefix, prefix_len) == 0; +} + + +/** + * g_strip_context: + * @msgid: a string + * @msgval: another string + * + * An auxiliary function for gettext() support (see Q_()). + * + * Return value: @msgval, unless @msgval is identical to @msgid and contains + * a '|' character, in which case a pointer to the substring of msgid after + * the first '|' character is returned. + * + * Since: 2.4 + **/ +G_CONST_RETURN gchar * +g_strip_context (const gchar *msgid, + const gchar *msgval) +{ + if (msgval == msgid) + { + const char *c = strchr (msgid, '|'); + if (c != NULL) + return c + 1; + } + + return msgval; +} + + +/** + * g_strv_length: + * @str_array: a %NULL-terminated array of strings. + * + * Returns the length of the given %NULL-terminated + * string array @str_array. + * + * Return value: length of @str_array. + * + * Since: 2.6 + **/ +guint +g_strv_length (gchar **str_array) +{ + guint i = 0; + + g_return_val_if_fail (str_array != NULL, 0); + + while (str_array[i]) + ++i; + + return i; +} + +#define __G_STRFUNCS_C__ +#include "galiasdef.c" +#endif diff --git a/gettext-tools/gnulib-lib/glib/gstrfuncs.in.h b/gettext-tools/gnulib-lib/glib/gstrfuncs.in.h new file mode 100644 index 0000000..e2bc1b1 --- /dev/null +++ b/gettext-tools/gnulib-lib/glib/gstrfuncs.in.h @@ -0,0 +1,269 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +/* + * Modified by Bruno Haible for use as a gnulib module. + */ + +#ifndef __G_STRFUNCS_H__ +#define __G_STRFUNCS_H__ + +#include +#include + +G_BEGIN_DECLS + +/* Functions like the ones in that are not affected by locale. */ +typedef enum { + G_ASCII_ALNUM = 1 << 0, + G_ASCII_ALPHA = 1 << 1, + G_ASCII_CNTRL = 1 << 2, + G_ASCII_DIGIT = 1 << 3, + G_ASCII_GRAPH = 1 << 4, + G_ASCII_LOWER = 1 << 5, + G_ASCII_PRINT = 1 << 6, + G_ASCII_PUNCT = 1 << 7, + G_ASCII_SPACE = 1 << 8, + G_ASCII_UPPER = 1 << 9, + G_ASCII_XDIGIT = 1 << 10 +} GAsciiType; + +GLIB_VAR const guint16 * const g_ascii_table; + +#define g_ascii_isalnum(c) \ + ((g_ascii_table[(guchar) (c)] & G_ASCII_ALNUM) != 0) + +#define g_ascii_isalpha(c) \ + ((g_ascii_table[(guchar) (c)] & G_ASCII_ALPHA) != 0) + +#define g_ascii_iscntrl(c) \ + ((g_ascii_table[(guchar) (c)] & G_ASCII_CNTRL) != 0) + +#define g_ascii_isdigit(c) \ + ((g_ascii_table[(guchar) (c)] & G_ASCII_DIGIT) != 0) + +#define g_ascii_isgraph(c) \ + ((g_ascii_table[(guchar) (c)] & G_ASCII_GRAPH) != 0) + +#define g_ascii_islower(c) \ + ((g_ascii_table[(guchar) (c)] & G_ASCII_LOWER) != 0) + +#define g_ascii_isprint(c) \ + ((g_ascii_table[(guchar) (c)] & G_ASCII_PRINT) != 0) + +#define g_ascii_ispunct(c) \ + ((g_ascii_table[(guchar) (c)] & G_ASCII_PUNCT) != 0) + +#define g_ascii_isspace(c) \ + ((g_ascii_table[(guchar) (c)] & G_ASCII_SPACE) != 0) + +#define g_ascii_isupper(c) \ + ((g_ascii_table[(guchar) (c)] & G_ASCII_UPPER) != 0) + +#define g_ascii_isxdigit(c) \ + ((g_ascii_table[(guchar) (c)] & G_ASCII_XDIGIT) != 0) + +#if 0 +gchar g_ascii_tolower (gchar c) G_GNUC_CONST; +#endif +gchar g_ascii_toupper (gchar c) G_GNUC_CONST; + +#if 0 +gint g_ascii_digit_value (gchar c) G_GNUC_CONST; +gint g_ascii_xdigit_value (gchar c) G_GNUC_CONST; + +/* String utility functions that modify a string argument or + * return a constant string that must not be freed. + */ +#define G_STR_DELIMITERS "_-|> <." +gchar* g_strdelimit (gchar *string, + const gchar *delimiters, + gchar new_delimiter); +gchar* g_strcanon (gchar *string, + const gchar *valid_chars, + gchar substitutor); +G_CONST_RETURN gchar* g_strerror (gint errnum) G_GNUC_CONST; +G_CONST_RETURN gchar* g_strsignal (gint signum) G_GNUC_CONST; +gchar* g_strreverse (gchar *string); +gsize g_strlcpy (gchar *dest, + const gchar *src, + gsize dest_size); +gsize g_strlcat (gchar *dest, + const gchar *src, + gsize dest_size); +#endif +gchar * g_strstr_len (const gchar *haystack, + gssize haystack_len, + const gchar *needle); +#if 0 +gchar * g_strrstr (const gchar *haystack, + const gchar *needle); +gchar * g_strrstr_len (const gchar *haystack, + gssize haystack_len, + const gchar *needle); + +gboolean g_str_has_suffix (const gchar *str, + const gchar *suffix); +gboolean g_str_has_prefix (const gchar *str, + const gchar *prefix); + +/* String to/from double conversion functions */ + +gdouble g_strtod (const gchar *nptr, + gchar **endptr); +gdouble g_ascii_strtod (const gchar *nptr, + gchar **endptr); +guint64 g_ascii_strtoull (const gchar *nptr, + gchar **endptr, + guint base); +gint64 g_ascii_strtoll (const gchar *nptr, + gchar **endptr, + guint base); +/* 29 bytes should enough for all possible values that + * g_ascii_dtostr can produce. + * Then add 10 for good measure */ +#define G_ASCII_DTOSTR_BUF_SIZE (29 + 10) +gchar * g_ascii_dtostr (gchar *buffer, + gint buf_len, + gdouble d); +gchar * g_ascii_formatd (gchar *buffer, + gint buf_len, + const gchar *format, + gdouble d); + +/* removes leading spaces */ +gchar* g_strchug (gchar *string); +/* removes trailing spaces */ +gchar* g_strchomp (gchar *string); +/* removes leading & trailing spaces */ +#define g_strstrip( string ) g_strchomp (g_strchug (string)) + +gint g_ascii_strcasecmp (const gchar *s1, + const gchar *s2); +gint g_ascii_strncasecmp (const gchar *s1, + const gchar *s2, + gsize n); +gchar* g_ascii_strdown (const gchar *str, + gssize len) G_GNUC_MALLOC; +#endif +gchar* g_ascii_strup (const gchar *str, + gssize len) G_GNUC_MALLOC; + +#if 0 + +#ifndef G_DISABLE_DEPRECATED + +/* The following four functions are deprecated and will be removed in + * the next major release. They use the locale-specific tolower and + * toupper, which is almost never the right thing. + */ + +gint g_strcasecmp (const gchar *s1, + const gchar *s2); +gint g_strncasecmp (const gchar *s1, + const gchar *s2, + guint n); +gchar* g_strdown (gchar *string); +gchar* g_strup (gchar *string); + +#endif /* G_DISABLE_DEPRECATED */ + +#endif + +/* String utility functions that return a newly allocated string which + * ought to be freed with g_free from the caller at some point. + */ +gchar* g_strdup (const gchar *str) G_GNUC_MALLOC; +gchar* g_strdup_printf (const gchar *format, + ...) G_GNUC_PRINTF (1, 2) G_GNUC_MALLOC; +#if 0 +gchar* g_strdup_vprintf (const gchar *format, + va_list args) G_GNUC_MALLOC; +#endif +gchar* g_strndup (const gchar *str, + gsize n) G_GNUC_MALLOC; +#if 0 +gchar* g_strnfill (gsize length, + gchar fill_char) G_GNUC_MALLOC; +#endif +gchar* g_strconcat (const gchar *string1, + ...) G_GNUC_MALLOC G_GNUC_NULL_TERMINATED; +#if 0 +gchar* g_strjoin (const gchar *separator, + ...) G_GNUC_MALLOC G_GNUC_NULL_TERMINATED; + +/* Make a copy of a string interpreting C string -style escape + * sequences. Inverse of g_strescape. The recognized sequences are \b + * \f \n \r \t \\ \" and the octal format. + */ +gchar* g_strcompress (const gchar *source) G_GNUC_MALLOC; + +/* Copy a string escaping nonprintable characters like in C strings. + * Inverse of g_strcompress. The exceptions parameter, if non-NULL, points + * to a string containing characters that are not to be escaped. + * + * Deprecated API: gchar* g_strescape (const gchar *source); + * Luckily this function wasn't used much, using NULL as second parameter + * provides mostly identical semantics. + */ +gchar* g_strescape (const gchar *source, + const gchar *exceptions) G_GNUC_MALLOC; + +gpointer g_memdup (gconstpointer mem, + guint byte_size) G_GNUC_MALLOC; + +/* NULL terminated string arrays. + * g_strsplit(), g_strsplit_set() split up string into max_tokens tokens + * at delim and return a newly allocated string array. + * g_strjoinv() concatenates all of str_array's strings, sliding in an + * optional separator, the returned string is newly allocated. + * g_strfreev() frees the array itself and all of its strings. + * g_strdupv() copies a NULL-terminated array of strings + * g_strv_length() returns the length of a NULL-terminated array of strings + */ +gchar** g_strsplit (const gchar *string, + const gchar *delimiter, + gint max_tokens) G_GNUC_MALLOC; +gchar ** g_strsplit_set (const gchar *string, + const gchar *delimiters, + gint max_tokens) G_GNUC_MALLOC; +gchar* g_strjoinv (const gchar *separator, + gchar **str_array) G_GNUC_MALLOC; +void g_strfreev (gchar **str_array); +gchar** g_strdupv (gchar **str_array) G_GNUC_MALLOC; +guint g_strv_length (gchar **str_array); + +gchar* g_stpcpy (gchar *dest, + const char *src); + +G_CONST_RETURN gchar *g_strip_context (const gchar *msgid, + const gchar *msgval); + +#endif + +G_END_DECLS + +#endif /* __G_STRFUNCS_H__ */ diff --git a/gettext-tools/gnulib-lib/glib/gstring.c b/gettext-tools/gnulib-lib/glib/gstring.c new file mode 100644 index 0000000..dd283fb --- /dev/null +++ b/gettext-tools/gnulib-lib/glib/gstring.c @@ -0,0 +1,958 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +/* + * Modified by Bruno Haible for use as a gnulib module. + */ + +/* + * MT safe + */ + +#include "config.h" + +#ifdef HAVE_UNISTD_H +#include +#endif +#include +#include +#include +#include +#include + +#include "glib.h" +#if 0 +#include "gprintf.h" + +#include "galias.h" + +struct _GStringChunk +{ + GHashTable *const_table; + GSList *storage_list; + gsize storage_next; + gsize this_size; + gsize default_size; +}; +#endif + +/* Hash Functions. + */ + +/** + * g_str_equal: + * @v1: a key. + * @v2: a key to compare with @v1. + * + * Compares two strings and returns %TRUE if they are equal. + * It can be passed to g_hash_table_new() as the @key_equal_func + * parameter, when using strings as keys in a #GHashTable. + * + * Returns: %TRUE if the two keys match. + */ +gboolean +g_str_equal (gconstpointer v1, + gconstpointer v2) +{ + const gchar *string1 = v1; + const gchar *string2 = v2; + + return strcmp (string1, string2) == 0; +} + +/** + * g_str_hash: + * @v: a string key. + * + * Converts a string to a hash value. + * It can be passed to g_hash_table_new() as the @hash_func parameter, + * when using strings as keys in a #GHashTable. + * + * Returns: a hash value corresponding to the key. + */ +guint +g_str_hash (gconstpointer v) +{ + /* 31 bit hash function */ + const signed char *p = v; + guint32 h = *p; + + if (h) + for (p += 1; *p != '\0'; p++) + h = (h << 5) - h + *p; + + return h; +} + +#define MY_MAXSIZE ((gsize)-1) + +static inline gsize +nearest_power (gsize base, gsize num) +{ + if (num > MY_MAXSIZE / 2) + { + return MY_MAXSIZE; + } + else + { + gsize n = base; + + while (n < num) + n <<= 1; + + return n; + } +} + +#if 0 + +/* String Chunks. + */ + +GStringChunk* +g_string_chunk_new (gsize default_size) +{ + GStringChunk *new_chunk = g_new (GStringChunk, 1); + gsize size = 1; + + size = nearest_power (1, default_size); + + new_chunk->const_table = NULL; + new_chunk->storage_list = NULL; + new_chunk->storage_next = size; + new_chunk->default_size = size; + new_chunk->this_size = size; + + return new_chunk; +} + +void +g_string_chunk_free (GStringChunk *chunk) +{ + GSList *tmp_list; + + g_return_if_fail (chunk != NULL); + + if (chunk->storage_list) + { + for (tmp_list = chunk->storage_list; tmp_list; tmp_list = tmp_list->next) + g_free (tmp_list->data); + + g_slist_free (chunk->storage_list); + } + + if (chunk->const_table) + g_hash_table_destroy (chunk->const_table); + + g_free (chunk); +} + +gchar* +g_string_chunk_insert (GStringChunk *chunk, + const gchar *string) +{ + g_return_val_if_fail (chunk != NULL, NULL); + + return g_string_chunk_insert_len (chunk, string, -1); +} + +gchar* +g_string_chunk_insert_const (GStringChunk *chunk, + const gchar *string) +{ + char* lookup; + + g_return_val_if_fail (chunk != NULL, NULL); + + if (!chunk->const_table) + chunk->const_table = g_hash_table_new (g_str_hash, g_str_equal); + + lookup = (char*) g_hash_table_lookup (chunk->const_table, (gchar *)string); + + if (!lookup) + { + lookup = g_string_chunk_insert (chunk, string); + g_hash_table_insert (chunk->const_table, lookup, lookup); + } + + return lookup; +} + +/** + * g_string_chunk_insert_len: + * @chunk: a #GStringChunk + * @string: bytes to insert + * @len: number of bytes of @string to insert, or -1 to insert a + * nul-terminated string. + * + * Adds a copy of the first @len bytes of @string to the #GStringChunk. The + * copy is nul-terminated. + * + * The characters in the string can be changed, if necessary, though you + * should not change anything after the end of the string. + * + * Return value: a pointer to the copy of @string within the #GStringChunk + * + * Since: 2.4 + **/ +gchar* +g_string_chunk_insert_len (GStringChunk *chunk, + const gchar *string, + gssize len) +{ + gssize size; + gchar* pos; + + g_return_val_if_fail (chunk != NULL, NULL); + + if (len < 0) + size = strlen (string); + else + size = len; + + if ((chunk->storage_next + size + 1) > chunk->this_size) + { + gsize new_size = nearest_power (chunk->default_size, size + 1); + + chunk->storage_list = g_slist_prepend (chunk->storage_list, + g_new (gchar, new_size)); + + chunk->this_size = new_size; + chunk->storage_next = 0; + } + + pos = ((gchar *) chunk->storage_list->data) + chunk->storage_next; + + *(pos + size) = '\0'; + + strncpy (pos, string, size); + if (len > 0) + size = strlen (pos); + + chunk->storage_next += size + 1; + + return pos; +} + +#endif + +/* Strings. + */ +static void +g_string_maybe_expand (GString* string, + gsize len) +{ + if (string->len + len >= string->allocated_len) + { + string->allocated_len = nearest_power (1, string->len + len + 1); + string->str = g_realloc (string->str, string->allocated_len); + } +} + +GString* +g_string_sized_new (gsize dfl_size) +{ + GString *string = g_slice_new (GString); + + string->allocated_len = 0; + string->len = 0; + string->str = NULL; + + g_string_maybe_expand (string, MAX (dfl_size, 2)); + string->str[0] = 0; + + return string; +} + +GString* +g_string_new (const gchar *init) +{ + GString *string; + + if (init == NULL || *init == '\0') + string = g_string_sized_new (2); + else + { + gint len; + + len = strlen (init); + string = g_string_sized_new (len + 2); + + g_string_append_len (string, init, len); + } + + return string; +} + +GString* +g_string_new_len (const gchar *init, + gssize len) +{ + GString *string; + + if (len < 0) + return g_string_new (init); + else + { + string = g_string_sized_new (len); + + if (init) + g_string_append_len (string, init, len); + + return string; + } +} + +gchar* +g_string_free (GString *string, + gboolean free_segment) +{ + gchar *segment; + + g_return_val_if_fail (string != NULL, NULL); + + if (free_segment) + { + g_free (string->str); + segment = NULL; + } + else + segment = string->str; + + g_slice_free (GString, string); + + return segment; +} + +#if 0 + +gboolean +g_string_equal (const GString *v, + const GString *v2) +{ + gchar *p, *q; + GString *string1 = (GString *) v; + GString *string2 = (GString *) v2; + gsize i = string1->len; + + if (i != string2->len) + return FALSE; + + p = string1->str; + q = string2->str; + while (i) + { + if (*p != *q) + return FALSE; + p++; + q++; + i--; + } + return TRUE; +} + +/* 31 bit hash function */ +guint +g_string_hash (const GString *str) +{ + const gchar *p = str->str; + gsize n = str->len; + guint h = 0; + + while (n--) + { + h = (h << 5) - h + *p; + p++; + } + + return h; +} + +GString* +g_string_assign (GString *string, + const gchar *rval) +{ + g_return_val_if_fail (string != NULL, NULL); + g_return_val_if_fail (rval != NULL, string); + + /* Make sure assigning to itself doesn't corrupt the string. */ + if (string->str != rval) + { + /* Assigning from substring should be ok since g_string_truncate + does not realloc. */ + g_string_truncate (string, 0); + g_string_append (string, rval); + } + + return string; +} + +GString* +g_string_truncate (GString *string, + gsize len) +{ + g_return_val_if_fail (string != NULL, NULL); + + string->len = MIN (len, string->len); + string->str[string->len] = 0; + + return string; +} + +/** + * g_string_set_size: + * @string: a #GString + * @len: the new length + * + * Sets the length of a #GString. If the length is less than + * the current length, the string will be truncated. If the + * length is greater than the current length, the contents + * of the newly added area are undefined. (However, as + * always, string->str[string->len] will be a nul byte.) + * + * Return value: @string + **/ +GString* +g_string_set_size (GString *string, + gsize len) +{ + g_return_val_if_fail (string != NULL, NULL); + + if (len >= string->allocated_len) + g_string_maybe_expand (string, len - string->len); + + string->len = len; + string->str[len] = 0; + + return string; +} + +#endif + +GString* +g_string_insert_len (GString *string, + gssize pos, + const gchar *val, + gssize len) +{ + g_return_val_if_fail (string != NULL, NULL); + g_return_val_if_fail (val != NULL, string); + + if (len < 0) + len = strlen (val); + + if (pos < 0) + pos = string->len; + else + g_return_val_if_fail (pos <= string->len, string); + + /* Check whether val represents a substring of string. This test + probably violates chapter and verse of the C standards, since + ">=" and "<=" are only valid when val really is a substring. + In practice, it will work on modern archs. */ + if (val >= string->str && val <= string->str + string->len) + { + gsize offset = val - string->str; + gsize precount = 0; + + g_string_maybe_expand (string, len); + val = string->str + offset; + /* At this point, val is valid again. */ + + /* Open up space where we are going to insert. */ + if (pos < string->len) + g_memmove (string->str + pos + len, string->str + pos, string->len - pos); + + /* Move the source part before the gap, if any. */ + if (offset < pos) + { + precount = MIN (len, pos - offset); + memcpy (string->str + pos, val, precount); + } + + /* Move the source part after the gap, if any. */ + if (len > precount) + memcpy (string->str + pos + precount, + val + /* Already moved: */ precount + /* Space opened up: */ len, + len - precount); + } + else + { + g_string_maybe_expand (string, len); + + /* If we aren't appending at the end, move a hunk + * of the old string to the end, opening up space + */ + if (pos < string->len) + g_memmove (string->str + pos + len, string->str + pos, string->len - pos); + + /* insert the new string */ + if (len == 1) + string->str[pos] = *val; + else + memcpy (string->str + pos, val, len); + } + + string->len += len; + + string->str[string->len] = 0; + + return string; +} + +GString* +g_string_append (GString *string, + const gchar *val) +{ + g_return_val_if_fail (string != NULL, NULL); + g_return_val_if_fail (val != NULL, string); + + return g_string_insert_len (string, -1, val, -1); +} + +GString* +g_string_append_len (GString *string, + const gchar *val, + gssize len) +{ + g_return_val_if_fail (string != NULL, NULL); + g_return_val_if_fail (val != NULL, string); + + return g_string_insert_len (string, -1, val, len); +} + +#undef g_string_append_c +GString* +g_string_append_c (GString *string, + gchar c) +{ + g_return_val_if_fail (string != NULL, NULL); + + return g_string_insert_c (string, -1, c); +} + +/** + * g_string_append_unichar: + * @string: a #GString + * @wc: a Unicode character + * + * Converts a Unicode character into UTF-8, and appends it + * to the string. + * + * Return value: @string + **/ +GString* +g_string_append_unichar (GString *string, + gunichar wc) +{ + g_return_val_if_fail (string != NULL, NULL); + + return g_string_insert_unichar (string, -1, wc); +} + +#if 0 + +GString* +g_string_prepend (GString *string, + const gchar *val) +{ + g_return_val_if_fail (string != NULL, NULL); + g_return_val_if_fail (val != NULL, string); + + return g_string_insert_len (string, 0, val, -1); +} + +GString* +g_string_prepend_len (GString *string, + const gchar *val, + gssize len) +{ + g_return_val_if_fail (string != NULL, NULL); + g_return_val_if_fail (val != NULL, string); + + return g_string_insert_len (string, 0, val, len); +} + +GString* +g_string_prepend_c (GString *string, + gchar c) +{ + g_return_val_if_fail (string != NULL, NULL); + + return g_string_insert_c (string, 0, c); +} + +/** + * g_string_prepend_unichar: + * @string: a #GString. + * @wc: a Unicode character. + * + * Converts a Unicode character into UTF-8, and prepends it + * to the string. + * + * Return value: @string. + **/ +GString* +g_string_prepend_unichar (GString *string, + gunichar wc) +{ + g_return_val_if_fail (string != NULL, NULL); + + return g_string_insert_unichar (string, 0, wc); +} + +GString* +g_string_insert (GString *string, + gssize pos, + const gchar *val) +{ + g_return_val_if_fail (string != NULL, NULL); + g_return_val_if_fail (val != NULL, string); + if (pos >= 0) + g_return_val_if_fail (pos <= string->len, string); + + return g_string_insert_len (string, pos, val, -1); +} + +#endif + +GString* +g_string_insert_c (GString *string, + gssize pos, + gchar c) +{ + g_return_val_if_fail (string != NULL, NULL); + + g_string_maybe_expand (string, 1); + + if (pos < 0) + pos = string->len; + else + g_return_val_if_fail (pos <= string->len, string); + + /* If not just an append, move the old stuff */ + if (pos < string->len) + g_memmove (string->str + pos + 1, string->str + pos, string->len - pos); + + string->str[pos] = c; + + string->len += 1; + + string->str[string->len] = 0; + + return string; +} + +/** + * g_string_insert_unichar: + * @string: a #GString + * @pos: the position at which to insert character, or -1 to + * append at the end of the string. + * @wc: a Unicode character + * + * Converts a Unicode character into UTF-8, and insert it + * into the string at the given position. + * + * Return value: @string + **/ +GString* +g_string_insert_unichar (GString *string, + gssize pos, + gunichar wc) +{ + gint charlen, first, i; + gchar *dest; + + g_return_val_if_fail (string != NULL, NULL); + + /* Code copied from g_unichar_to_utf() */ + if (wc < 0x80) + { + first = 0; + charlen = 1; + } + else if (wc < 0x800) + { + first = 0xc0; + charlen = 2; + } + else if (wc < 0x10000) + { + first = 0xe0; + charlen = 3; + } + else if (wc < 0x200000) + { + first = 0xf0; + charlen = 4; + } + else if (wc < 0x4000000) + { + first = 0xf8; + charlen = 5; + } + else + { + first = 0xfc; + charlen = 6; + } + /* End of copied code */ + + g_string_maybe_expand (string, charlen); + + if (pos < 0) + pos = string->len; + else + g_return_val_if_fail (pos <= string->len, string); + + /* If not just an append, move the old stuff */ + if (pos < string->len) + g_memmove (string->str + pos + charlen, string->str + pos, string->len - pos); + + dest = string->str + pos; + /* Code copied from g_unichar_to_utf() */ + for (i = charlen - 1; i > 0; --i) + { + dest[i] = (wc & 0x3f) | 0x80; + wc >>= 6; + } + dest[0] = wc | first; + /* End of copied code */ + + string->len += charlen; + + string->str[string->len] = 0; + + return string; +} + +#if 0 + +GString* +g_string_erase (GString *string, + gssize pos, + gssize len) +{ + g_return_val_if_fail (string != NULL, NULL); + g_return_val_if_fail (pos >= 0, string); + g_return_val_if_fail (pos <= string->len, string); + + if (len < 0) + len = string->len - pos; + else + { + g_return_val_if_fail (pos + len <= string->len, string); + + if (pos + len < string->len) + g_memmove (string->str + pos, string->str + pos + len, string->len - (pos + len)); + } + + string->len -= len; + + string->str[string->len] = 0; + + return string; +} + +/** + * g_string_ascii_down: + * @string: a GString + * + * Converts all upper case ASCII letters to lower case ASCII letters. + * + * Return value: passed-in @string pointer, with all the upper case + * characters converted to lower case in place, with + * semantics that exactly match g_ascii_tolower. + **/ +GString* +g_string_ascii_down (GString *string) +{ + gchar *s; + gint n; + + g_return_val_if_fail (string != NULL, NULL); + + n = string->len; + s = string->str; + + while (n) + { + *s = g_ascii_tolower (*s); + s++; + n--; + } + + return string; +} + +/** + * g_string_ascii_up: + * @string: a GString + * + * Converts all lower case ASCII letters to upper case ASCII letters. + * + * Return value: passed-in @string pointer, with all the lower case + * characters converted to upper case in place, with + * semantics that exactly match g_ascii_toupper. + **/ +GString* +g_string_ascii_up (GString *string) +{ + gchar *s; + gint n; + + g_return_val_if_fail (string != NULL, NULL); + + n = string->len; + s = string->str; + + while (n) + { + *s = g_ascii_toupper (*s); + s++; + n--; + } + + return string; +} + +/** + * g_string_down: + * @string: a #GString + * + * Converts a #GString to lowercase. + * + * Returns: the #GString. + * + * Deprecated:2.2: This function uses the locale-specific tolower() function, + * which is almost never the right thing. Use g_string_ascii_down() or + * g_utf8_strdown() instead. + */ +GString* +g_string_down (GString *string) +{ + guchar *s; + glong n; + + g_return_val_if_fail (string != NULL, NULL); + + n = string->len; + s = (guchar *) string->str; + + while (n) + { + if (isupper (*s)) + *s = tolower (*s); + s++; + n--; + } + + return string; +} + +/** + * g_string_up: + * @string: a #GString + * + * Converts a #GString to uppercase. + * + * Return value: the #GString + * + * Deprecated:2.2: This function uses the locale-specific toupper() function, + * which is almost never the right thing. Use g_string_ascii_up() or + * g_utf8_strup() instead. + **/ +GString* +g_string_up (GString *string) +{ + guchar *s; + glong n; + + g_return_val_if_fail (string != NULL, NULL); + + n = string->len; + s = (guchar *) string->str; + + while (n) + { + if (islower (*s)) + *s = toupper (*s); + s++; + n--; + } + + return string; +} + +#endif + +static void +g_string_append_printf_internal (GString *string, + const gchar *fmt, + va_list args) +{ + gchar *buffer; + gint length; + + length = g_vasprintf (&buffer, fmt, args); + g_string_append_len (string, buffer, length); + g_free (buffer); +} + +#if 0 + +void +g_string_printf (GString *string, + const gchar *fmt, + ...) +{ + va_list args; + + g_string_truncate (string, 0); + + va_start (args, fmt); + g_string_append_printf_internal (string, fmt, args); + va_end (args); +} + +#endif + +void +g_string_append_printf (GString *string, + const gchar *fmt, + ...) +{ + va_list args; + + va_start (args, fmt); + g_string_append_printf_internal (string, fmt, args); + va_end (args); +} + +#if 0 +#define __G_STRING_C__ +#include "galiasdef.c" +#endif diff --git a/gettext-tools/gnulib-lib/glib/gstring.in.h b/gettext-tools/gnulib-lib/glib/gstring.in.h new file mode 100644 index 0000000..b9458cb --- /dev/null +++ b/gettext-tools/gnulib-lib/glib/gstring.in.h @@ -0,0 +1,179 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +/* + * Modified by Bruno Haible for use as a gnulib module. + */ + +#ifndef __G_STRING_H__ +#define __G_STRING_H__ + +#include +#if 0 +#include +#include /* for G_CAN_INLINE */ +#endif + +G_BEGIN_DECLS + +typedef struct _GString GString; +#if 0 +typedef struct _GStringChunk GStringChunk; +#endif + +struct _GString +{ + gchar *str; + gsize len; + gsize allocated_len; +}; + +#if 0 +/* String Chunks + */ +GStringChunk* g_string_chunk_new (gsize size); +void g_string_chunk_free (GStringChunk *chunk); +gchar* g_string_chunk_insert (GStringChunk *chunk, + const gchar *string); +gchar* g_string_chunk_insert_len (GStringChunk *chunk, + const gchar *string, + gssize len); +gchar* g_string_chunk_insert_const (GStringChunk *chunk, + const gchar *string); +#endif + + +/* Strings + */ +GString* g_string_new (const gchar *init); +GString* g_string_new_len (const gchar *init, + gssize len); +#if 0 +GString* g_string_sized_new (gsize dfl_size); +#endif +gchar* g_string_free (GString *string, + gboolean free_segment); +#if 0 +gboolean g_string_equal (const GString *v, + const GString *v2); +guint g_string_hash (const GString *str); +GString* g_string_assign (GString *string, + const gchar *rval); +GString* g_string_truncate (GString *string, + gsize len); +GString* g_string_set_size (GString *string, + gsize len); +GString* g_string_insert_len (GString *string, + gssize pos, + const gchar *val, + gssize len); +#endif +GString* g_string_append (GString *string, + const gchar *val); +GString* g_string_append_len (GString *string, + const gchar *val, + gssize len); +GString* g_string_append_c (GString *string, + gchar c); +GString* g_string_append_unichar (GString *string, + gunichar wc); +#if 0 +GString* g_string_prepend (GString *string, + const gchar *val); +GString* g_string_prepend_c (GString *string, + gchar c); +GString* g_string_prepend_unichar (GString *string, + gunichar wc); +GString* g_string_prepend_len (GString *string, + const gchar *val, + gssize len); +GString* g_string_insert (GString *string, + gssize pos, + const gchar *val); +#endif +GString* g_string_insert_c (GString *string, + gssize pos, + gchar c); +GString* g_string_insert_unichar (GString *string, + gssize pos, + gunichar wc); +#if 0 +GString* g_string_erase (GString *string, + gssize pos, + gssize len); +GString* g_string_ascii_down (GString *string); +GString* g_string_ascii_up (GString *string); +void g_string_printf (GString *string, + const gchar *format, + ...) G_GNUC_PRINTF (2, 3); +#endif +void g_string_append_printf (GString *string, + const gchar *format, + ...) G_GNUC_PRINTF (2, 3); + +#if 0 + +/* -- optimize g_strig_append_c --- */ +#ifdef G_CAN_INLINE +static inline GString* +g_string_append_c_inline (GString *gstring, + gchar c) +{ + if (gstring->len + 1 < gstring->allocated_len) + { + gstring->str[gstring->len++] = c; + gstring->str[gstring->len] = 0; + } + else + g_string_insert_c (gstring, -1, c); + return gstring; +} +#define g_string_append_c(gstr,c) g_string_append_c_inline (gstr, c) +#endif /* G_CAN_INLINE */ + + +#ifndef G_DISABLE_DEPRECATED + +/* The following two functions are deprecated and will be removed in + * the next major release. They use the locale-specific tolower and + * toupper, which is almost never the right thing. + */ + +GString* g_string_down (GString *string); +GString* g_string_up (GString *string); + +/* These aliases are included for compatibility. */ +#define g_string_sprintf g_string_printf +#define g_string_sprintfa g_string_append_printf + +#endif /* G_DISABLE_DEPRECATED */ + +#endif + +G_END_DECLS + +#endif /* __G_STRING_H__ */ + diff --git a/gettext-tools/gnulib-lib/glib/gtypes.in.h b/gettext-tools/gnulib-lib/glib/gtypes.in.h new file mode 100644 index 0000000..c6e9fe9 --- /dev/null +++ b/gettext-tools/gnulib-lib/glib/gtypes.in.h @@ -0,0 +1,430 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +/* + * Modified by Bruno Haible for use as a gnulib module. + */ + +#ifndef __G_TYPES_H__ +#define __G_TYPES_H__ + +#include + +G_BEGIN_DECLS + +/* Provide type definitions for commonly used types. + * These are useful because a "gint8" can be adjusted + * to be 1 byte (8 bits) on all platforms. Similarly and + * more importantly, "gint32" can be adjusted to be + * 4 bytes (32 bits) on all platforms. + */ + +typedef char gchar; +typedef short gshort; +typedef long glong; +typedef int gint; +typedef gint gboolean; + +typedef unsigned char guchar; +typedef unsigned short gushort; +typedef unsigned long gulong; +typedef unsigned int guint; + +typedef float gfloat; +typedef double gdouble; + +/* Define min and max constants for the fixed size numerical types */ +#define G_MININT8 ((gint8) 0x80) +#define G_MAXINT8 ((gint8) 0x7f) +#define G_MAXUINT8 ((guint8) 0xff) + +#define G_MININT16 ((gint16) 0x8000) +#define G_MAXINT16 ((gint16) 0x7fff) +#define G_MAXUINT16 ((guint16) 0xffff) + +#define G_MININT32 ((gint32) 0x80000000) +#define G_MAXINT32 ((gint32) 0x7fffffff) +#define G_MAXUINT32 ((guint32) 0xffffffff) + +#define G_MININT64 ((gint64) G_GINT64_CONSTANT(0x8000000000000000)) +#define G_MAXINT64 G_GINT64_CONSTANT(0x7fffffffffffffff) +#define G_MAXUINT64 G_GINT64_CONSTANT(0xffffffffffffffffU) + +typedef void* gpointer; +typedef const void *gconstpointer; + +typedef gint (*GCompareFunc) (gconstpointer a, + gconstpointer b); +typedef gint (*GCompareDataFunc) (gconstpointer a, + gconstpointer b, + gpointer user_data); +typedef gboolean (*GEqualFunc) (gconstpointer a, + gconstpointer b); +typedef void (*GDestroyNotify) (gpointer data); +typedef void (*GFunc) (gpointer data, + gpointer user_data); +typedef guint (*GHashFunc) (gconstpointer key); +typedef void (*GHFunc) (gpointer key, + gpointer value, + gpointer user_data); +typedef void (*GFreeFunc) (gpointer data); +typedef const gchar * (*GTranslateFunc) (const gchar *str, + gpointer data); + + +/* Define some mathematical constants that aren't available + * symbolically in some strict ISO C implementations. + */ +#define G_E 2.7182818284590452353602874713526624977572470937000 +#define G_LN2 0.69314718055994530941723212145817656807550013436026 +#define G_LN10 2.3025850929940456840179914546843642076011014886288 +#define G_PI 3.1415926535897932384626433832795028841971693993751 +#define G_PI_2 1.5707963267948966192313216916397514420985846996876 +#define G_PI_4 0.78539816339744830961566084581987572104929234984378 +#define G_SQRT2 1.4142135623730950488016887242096980785696718753769 + +#if 0 + +/* Portable endian checks and conversions + * + * glibconfig.h defines G_BYTE_ORDER which expands to one of + * the below macros. + */ +#define G_LITTLE_ENDIAN 1234 +#define G_BIG_ENDIAN 4321 +#define G_PDP_ENDIAN 3412 /* unused, need specific PDP check */ + + +/* Basic bit swapping functions + */ +#define GUINT16_SWAP_LE_BE_CONSTANT(val) ((guint16) ( \ + (guint16) ((guint16) (val) >> 8) | \ + (guint16) ((guint16) (val) << 8))) + +#define GUINT32_SWAP_LE_BE_CONSTANT(val) ((guint32) ( \ + (((guint32) (val) & (guint32) 0x000000ffU) << 24) | \ + (((guint32) (val) & (guint32) 0x0000ff00U) << 8) | \ + (((guint32) (val) & (guint32) 0x00ff0000U) >> 8) | \ + (((guint32) (val) & (guint32) 0xff000000U) >> 24))) + +#define GUINT64_SWAP_LE_BE_CONSTANT(val) ((guint64) ( \ + (((guint64) (val) & \ + (guint64) G_GINT64_CONSTANT (0x00000000000000ffU)) << 56) | \ + (((guint64) (val) & \ + (guint64) G_GINT64_CONSTANT (0x000000000000ff00U)) << 40) | \ + (((guint64) (val) & \ + (guint64) G_GINT64_CONSTANT (0x0000000000ff0000U)) << 24) | \ + (((guint64) (val) & \ + (guint64) G_GINT64_CONSTANT (0x00000000ff000000U)) << 8) | \ + (((guint64) (val) & \ + (guint64) G_GINT64_CONSTANT (0x000000ff00000000U)) >> 8) | \ + (((guint64) (val) & \ + (guint64) G_GINT64_CONSTANT (0x0000ff0000000000U)) >> 24) | \ + (((guint64) (val) & \ + (guint64) G_GINT64_CONSTANT (0x00ff000000000000U)) >> 40) | \ + (((guint64) (val) & \ + (guint64) G_GINT64_CONSTANT (0xff00000000000000U)) >> 56))) + +/* Arch specific stuff for speed + */ +#if defined (__GNUC__) && (__GNUC__ >= 2) && defined (__OPTIMIZE__) +# if defined (__i386__) +# define GUINT16_SWAP_LE_BE_IA32(val) \ + (__extension__ \ + ({ register guint16 __v, __x = ((guint16) (val)); \ + if (__builtin_constant_p (__x)) \ + __v = GUINT16_SWAP_LE_BE_CONSTANT (__x); \ + else \ + __asm__ ("rorw $8, %w0" \ + : "=r" (__v) \ + : "0" (__x) \ + : "cc"); \ + __v; })) +# if !defined (__i486__) && !defined (__i586__) \ + && !defined (__pentium__) && !defined (__i686__) \ + && !defined (__pentiumpro__) && !defined (__pentium4__) +# define GUINT32_SWAP_LE_BE_IA32(val) \ + (__extension__ \ + ({ register guint32 __v, __x = ((guint32) (val)); \ + if (__builtin_constant_p (__x)) \ + __v = GUINT32_SWAP_LE_BE_CONSTANT (__x); \ + else \ + __asm__ ("rorw $8, %w0\n\t" \ + "rorl $16, %0\n\t" \ + "rorw $8, %w0" \ + : "=r" (__v) \ + : "0" (__x) \ + : "cc"); \ + __v; })) +# else /* 486 and higher has bswap */ +# define GUINT32_SWAP_LE_BE_IA32(val) \ + (__extension__ \ + ({ register guint32 __v, __x = ((guint32) (val)); \ + if (__builtin_constant_p (__x)) \ + __v = GUINT32_SWAP_LE_BE_CONSTANT (__x); \ + else \ + __asm__ ("bswap %0" \ + : "=r" (__v) \ + : "0" (__x)); \ + __v; })) +# endif /* processor specific 32-bit stuff */ +# define GUINT64_SWAP_LE_BE_IA32(val) \ + (__extension__ \ + ({ union { guint64 __ll; \ + guint32 __l[2]; } __w, __r; \ + __w.__ll = ((guint64) (val)); \ + if (__builtin_constant_p (__w.__ll)) \ + __r.__ll = GUINT64_SWAP_LE_BE_CONSTANT (__w.__ll); \ + else \ + { \ + __r.__l[0] = GUINT32_SWAP_LE_BE (__w.__l[1]); \ + __r.__l[1] = GUINT32_SWAP_LE_BE (__w.__l[0]); \ + } \ + __r.__ll; })) + /* Possibly just use the constant version and let gcc figure it out? */ +# define GUINT16_SWAP_LE_BE(val) (GUINT16_SWAP_LE_BE_IA32 (val)) +# define GUINT32_SWAP_LE_BE(val) (GUINT32_SWAP_LE_BE_IA32 (val)) +# define GUINT64_SWAP_LE_BE(val) (GUINT64_SWAP_LE_BE_IA32 (val)) +# elif defined (__ia64__) +# define GUINT16_SWAP_LE_BE_IA64(val) \ + (__extension__ \ + ({ register guint16 __v, __x = ((guint16) (val)); \ + if (__builtin_constant_p (__x)) \ + __v = GUINT16_SWAP_LE_BE_CONSTANT (__x); \ + else \ + __asm__ __volatile__ ("shl %0 = %1, 48 ;;" \ + "mux1 %0 = %0, @rev ;;" \ + : "=r" (__v) \ + : "r" (__x)); \ + __v; })) +# define GUINT32_SWAP_LE_BE_IA64(val) \ + (__extension__ \ + ({ register guint32 __v, __x = ((guint32) (val)); \ + if (__builtin_constant_p (__x)) \ + __v = GUINT32_SWAP_LE_BE_CONSTANT (__x); \ + else \ + __asm__ __volatile__ ("shl %0 = %1, 32 ;;" \ + "mux1 %0 = %0, @rev ;;" \ + : "=r" (__v) \ + : "r" (__x)); \ + __v; })) +# define GUINT64_SWAP_LE_BE_IA64(val) \ + (__extension__ \ + ({ register guint64 __v, __x = ((guint64) (val)); \ + if (__builtin_constant_p (__x)) \ + __v = GUINT64_SWAP_LE_BE_CONSTANT (__x); \ + else \ + __asm__ __volatile__ ("mux1 %0 = %1, @rev ;;" \ + : "=r" (__v) \ + : "r" (__x)); \ + __v; })) +# define GUINT16_SWAP_LE_BE(val) (GUINT16_SWAP_LE_BE_IA64 (val)) +# define GUINT32_SWAP_LE_BE(val) (GUINT32_SWAP_LE_BE_IA64 (val)) +# define GUINT64_SWAP_LE_BE(val) (GUINT64_SWAP_LE_BE_IA64 (val)) +# elif defined (__x86_64__) +# define GUINT32_SWAP_LE_BE_X86_64(val) \ + (__extension__ \ + ({ register guint32 __v, __x = ((guint32) (val)); \ + if (__builtin_constant_p (__x)) \ + __v = GUINT32_SWAP_LE_BE_CONSTANT (__x); \ + else \ + __asm__ ("bswapl %0" \ + : "=r" (__v) \ + : "0" (__x)); \ + __v; })) +# define GUINT64_SWAP_LE_BE_X86_64(val) \ + (__extension__ \ + ({ register guint64 __v, __x = ((guint64) (val)); \ + if (__builtin_constant_p (__x)) \ + __v = GUINT64_SWAP_LE_BE_CONSTANT (__x); \ + else \ + __asm__ ("bswapq %0" \ + : "=r" (__v) \ + : "0" (__x)); \ + __v; })) + /* gcc seems to figure out optimal code for this on its own */ +# define GUINT16_SWAP_LE_BE(val) (GUINT16_SWAP_LE_BE_CONSTANT (val)) +# define GUINT32_SWAP_LE_BE(val) (GUINT32_SWAP_LE_BE_X86_64 (val)) +# define GUINT64_SWAP_LE_BE(val) (GUINT64_SWAP_LE_BE_X86_64 (val)) +# else /* generic gcc */ +# define GUINT16_SWAP_LE_BE(val) (GUINT16_SWAP_LE_BE_CONSTANT (val)) +# define GUINT32_SWAP_LE_BE(val) (GUINT32_SWAP_LE_BE_CONSTANT (val)) +# define GUINT64_SWAP_LE_BE(val) (GUINT64_SWAP_LE_BE_CONSTANT (val)) +# endif +#else /* generic */ +# define GUINT16_SWAP_LE_BE(val) (GUINT16_SWAP_LE_BE_CONSTANT (val)) +# define GUINT32_SWAP_LE_BE(val) (GUINT32_SWAP_LE_BE_CONSTANT (val)) +# define GUINT64_SWAP_LE_BE(val) (GUINT64_SWAP_LE_BE_CONSTANT (val)) +#endif /* generic */ + +#define GUINT16_SWAP_LE_PDP(val) ((guint16) (val)) +#define GUINT16_SWAP_BE_PDP(val) (GUINT16_SWAP_LE_BE (val)) +#define GUINT32_SWAP_LE_PDP(val) ((guint32) ( \ + (((guint32) (val) & (guint32) 0x0000ffffU) << 16) | \ + (((guint32) (val) & (guint32) 0xffff0000U) >> 16))) +#define GUINT32_SWAP_BE_PDP(val) ((guint32) ( \ + (((guint32) (val) & (guint32) 0x00ff00ffU) << 8) | \ + (((guint32) (val) & (guint32) 0xff00ff00U) >> 8))) + +/* The G*_TO_?E() macros are defined in glibconfig.h. + * The transformation is symmetric, so the FROM just maps to the TO. + */ +#define GINT16_FROM_LE(val) (GINT16_TO_LE (val)) +#define GUINT16_FROM_LE(val) (GUINT16_TO_LE (val)) +#define GINT16_FROM_BE(val) (GINT16_TO_BE (val)) +#define GUINT16_FROM_BE(val) (GUINT16_TO_BE (val)) +#define GINT32_FROM_LE(val) (GINT32_TO_LE (val)) +#define GUINT32_FROM_LE(val) (GUINT32_TO_LE (val)) +#define GINT32_FROM_BE(val) (GINT32_TO_BE (val)) +#define GUINT32_FROM_BE(val) (GUINT32_TO_BE (val)) + +#define GINT64_FROM_LE(val) (GINT64_TO_LE (val)) +#define GUINT64_FROM_LE(val) (GUINT64_TO_LE (val)) +#define GINT64_FROM_BE(val) (GINT64_TO_BE (val)) +#define GUINT64_FROM_BE(val) (GUINT64_TO_BE (val)) + +#define GLONG_FROM_LE(val) (GLONG_TO_LE (val)) +#define GULONG_FROM_LE(val) (GULONG_TO_LE (val)) +#define GLONG_FROM_BE(val) (GLONG_TO_BE (val)) +#define GULONG_FROM_BE(val) (GULONG_TO_BE (val)) + +#define GINT_FROM_LE(val) (GINT_TO_LE (val)) +#define GUINT_FROM_LE(val) (GUINT_TO_LE (val)) +#define GINT_FROM_BE(val) (GINT_TO_BE (val)) +#define GUINT_FROM_BE(val) (GUINT_TO_BE (val)) + + +/* Portable versions of host-network order stuff + */ +#define g_ntohl(val) (GUINT32_FROM_BE (val)) +#define g_ntohs(val) (GUINT16_FROM_BE (val)) +#define g_htonl(val) (GUINT32_TO_BE (val)) +#define g_htons(val) (GUINT16_TO_BE (val)) + +/* IEEE Standard 754 Single Precision Storage Format (gfloat): + * + * 31 30 23 22 0 + * +--------+---------------+---------------+ + * | s 1bit | e[30:23] 8bit | f[22:0] 23bit | + * +--------+---------------+---------------+ + * B0------------------->B1------->B2-->B3--> + * + * IEEE Standard 754 Double Precision Storage Format (gdouble): + * + * 63 62 52 51 32 31 0 + * +--------+----------------+----------------+ +---------------+ + * | s 1bit | e[62:52] 11bit | f[51:32] 20bit | | f[31:0] 32bit | + * +--------+----------------+----------------+ +---------------+ + * B0--------------->B1---------->B2--->B3----> B4->B5->B6->B7-> + */ +/* subtract from biased_exponent to form base2 exponent (normal numbers) */ +typedef union _GDoubleIEEE754 GDoubleIEEE754; +typedef union _GFloatIEEE754 GFloatIEEE754; +#define G_IEEE754_FLOAT_BIAS (127) +#define G_IEEE754_DOUBLE_BIAS (1023) +/* multiply with base2 exponent to get base10 exponent (normal numbers) */ +#define G_LOG_2_BASE_10 (0.30102999566398119521) +#if G_BYTE_ORDER == G_LITTLE_ENDIAN +union _GFloatIEEE754 +{ + gfloat v_float; + struct { + guint mantissa : 23; + guint biased_exponent : 8; + guint sign : 1; + } mpn; +}; +union _GDoubleIEEE754 +{ + gdouble v_double; + struct { + guint mantissa_low : 32; + guint mantissa_high : 20; + guint biased_exponent : 11; + guint sign : 1; + } mpn; +}; +#elif G_BYTE_ORDER == G_BIG_ENDIAN +union _GFloatIEEE754 +{ + gfloat v_float; + struct { + guint sign : 1; + guint biased_exponent : 8; + guint mantissa : 23; + } mpn; +}; +union _GDoubleIEEE754 +{ + gdouble v_double; + struct { + guint sign : 1; + guint biased_exponent : 11; + guint mantissa_high : 20; + guint mantissa_low : 32; + } mpn; +}; +#else /* !G_LITTLE_ENDIAN && !G_BIG_ENDIAN */ +#error unknown ENDIAN type +#endif /* !G_LITTLE_ENDIAN && !G_BIG_ENDIAN */ + +typedef struct _GTimeVal GTimeVal; + +struct _GTimeVal +{ + glong tv_sec; + glong tv_usec; +}; + +#endif + +G_END_DECLS + +/* We prefix variable declarations so they can + * properly get exported in windows dlls. + */ +#ifndef GLIB_VAR +# ifdef G_PLATFORM_WIN32 +# ifdef GLIB_STATIC_COMPILATION +# define GLIB_VAR extern +# else /* !GLIB_STATIC_COMPILATION */ +# ifdef GLIB_COMPILATION +# ifdef DLL_EXPORT +# define GLIB_VAR __declspec(dllexport) +# else /* !DLL_EXPORT */ +# define GLIB_VAR extern +# endif /* !DLL_EXPORT */ +# else /* !GLIB_COMPILATION */ +# define GLIB_VAR extern __declspec(dllimport) +# endif /* !GLIB_COMPILATION */ +# endif /* !GLIB_STATIC_COMPILATION */ +# else /* !G_PLATFORM_WIN32 */ +# define GLIB_VAR extern +# endif /* !G_PLATFORM_WIN32 */ +#endif /* GLIB_VAR */ + +#endif /* __G_TYPES_H__ */ + diff --git a/gettext-tools/gnulib-lib/glibconfig.in.h b/gettext-tools/gnulib-lib/glibconfig.in.h new file mode 100644 index 0000000..8bff645 --- /dev/null +++ b/gettext-tools/gnulib-lib/glibconfig.in.h @@ -0,0 +1,189 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +/* + * Modified by Bruno Haible for use as a gnulib module. + */ + +/* ====================== Substitute for glibconfig.h ====================== */ + +#include +#include +#include + +typedef uint16_t guint16; +typedef uint32_t guint32; + +typedef size_t gsize; +typedef ssize_t gssize; + +#define GPOINTER_TO_INT(p) ((gint) (intptr_t) (p)) +#define GPOINTER_TO_UINT(p) ((guint) (uintptr_t) (p)) + +#define GINT_TO_POINTER(i) ((gpointer) (intptr_t) (i)) +#define GUINT_TO_POINTER(u) ((gpointer) (uintptr_t) (u)) + +#define g_memmove memmove + +/* ================ Abridged version of for ================ */ + +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96) +#define G_GNUC_PURE \ + __attribute__((__pure__)) +#define G_GNUC_MALLOC \ + __attribute__((__malloc__)) +#else +#define G_GNUC_PURE +#define G_GNUC_MALLOC +#endif + +#if __GNUC__ >= 4 +#define G_GNUC_NULL_TERMINATED __attribute__((__sentinel__)) +#else +#define G_GNUC_NULL_TERMINATED +#endif + +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4) +#define G_GNUC_PRINTF( format_idx, arg_idx ) \ + __attribute__((__format__ (__printf__, format_idx, arg_idx))) +#define G_GNUC_SCANF( format_idx, arg_idx ) \ + __attribute__((__format__ (__scanf__, format_idx, arg_idx))) +#define G_GNUC_FORMAT( arg_idx ) \ + __attribute__((__format_arg__ (arg_idx))) +#define G_GNUC_NORETURN \ + __attribute__((__noreturn__)) +#define G_GNUC_CONST \ + __attribute__((__const__)) +#define G_GNUC_UNUSED \ + __attribute__((__unused__)) +#define G_GNUC_NO_INSTRUMENT \ + __attribute__((__no_instrument_function__)) +#else /* !__GNUC__ */ +#define G_GNUC_PRINTF( format_idx, arg_idx ) +#define G_GNUC_SCANF( format_idx, arg_idx ) +#define G_GNUC_FORMAT( arg_idx ) +#define G_GNUC_NORETURN +#define G_GNUC_CONST +#define G_GNUC_UNUSED +#define G_GNUC_NO_INSTRUMENT +#endif /* !__GNUC__ */ + +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) +#define G_GNUC_WARN_UNUSED_RESULT \ + __attribute__((warn_unused_result)) +#else +#define G_GNUC_WARN_UNUSED_RESULT +#endif /* __GNUC__ */ + +#ifdef __cplusplus +# define G_BEGIN_DECLS extern "C" { +# define G_END_DECLS } +#else +# define G_BEGIN_DECLS +# define G_END_DECLS +#endif + +#ifndef FALSE +#define FALSE (0) +#endif + +#ifndef TRUE +#define TRUE (!FALSE) +#endif + +#undef MAX +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) + +#undef MIN +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) + +#define G_STMT_START +#define G_STMT_END + +/* ====================== Substitute for ====================== */ + +#include "xalloc.h" + +#define g_malloc(n) xmalloc (n) +#define g_malloc0(n) xzalloc (n) +#define g_realloc(p,n) xrealloc (p, n) +#define g_free(p) free (p) +#define g_try_malloc(n) xmalloc (n) +#define g_try_malloc0(n) xzalloc (n) +#define g_try_realloc(p,n) xrealloc (p, n) + +#define g_new(t,n) ((t *) xnmalloc (n, sizeof (t))) +#define g_new0(t,n) ((t *) xcalloc (n, sizeof (t))) +#define g_try_new(t,n) ((t *) xnmalloc (n, sizeof (t))) +#define g_try_new0(t,n) ((t *) xcalloc (n, sizeof (t))) + +/* =================== Substitute for =================== */ + +#include + +#define g_assert(expr) if (!(expr)) abort () +#define g_assert_not_reached() abort () + +#define g_return_if_fail(expr) if (!(expr)) return +#define g_return_val_if_fail(expr,val) if (!(expr)) return (val) +#define g_return_if_reached() return +#define g_return_val_if_reached(val) return (val) + +#define G_LOG_LEVEL_CRITICAL 0 +#define G_LOG_LEVEL_INFO 0 +#define G_LOG_LEVEL_DEBUG 0 + +extern void g_printerr (const char *format, ...) G_GNUC_PRINTF (1, 2); +extern void g_warning (const char *format, ...) G_GNUC_PRINTF (1, 2); +extern void g_log (const char *domain, int level, const char *format, ...) G_GNUC_PRINTF (3, 4); + +/* ==================== Substitute for ==================== */ + +#include + +#define g_printf printf +#define g_fprintf fprintf +#define g_sprintf sprintf +#define g_vprintf vprintf +#define g_vfprintf vfprintf +#define g_vsprintf vsprintf +#define g_vasprintf vasprintf + +/* ===================== Substitute for ===================== */ + +#define g_slice_new(t) XMALLOC (t) +#define g_slice_new0(t) XZALLOC (t) + +#define g_slice_free(t,p) free (p) + +/* ======================= Helper for ======================= */ + +/* We don't need to export variables from a shared library. */ +#define GLIB_VAR extern + +/* ==================== Substitute for ==================== */ + +typedef unsigned int gunichar; diff --git a/gettext-tools/gnulib-lib/glthread/lock.c b/gettext-tools/gnulib-lib/glthread/lock.c new file mode 100644 index 0000000..33c15a0 --- /dev/null +++ b/gettext-tools/gnulib-lib/glthread/lock.c @@ -0,0 +1,1057 @@ +/* Locking in multithreaded situations. + Copyright (C) 2005-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . */ + +/* Written by Bruno Haible , 2005. + Based on GCC's gthr-posix.h, gthr-posix95.h, gthr-solaris.h, + gthr-win32.h. */ + +#include + +#include "glthread/lock.h" + +/* ========================================================================= */ + +#if USE_POSIX_THREADS + +/* -------------------------- gl_lock_t datatype -------------------------- */ + +/* ------------------------- gl_rwlock_t datatype ------------------------- */ + +# if HAVE_PTHREAD_RWLOCK + +# if !defined PTHREAD_RWLOCK_INITIALIZER + +int +glthread_rwlock_init_multithreaded (gl_rwlock_t *lock) +{ + int err; + + err = pthread_rwlock_init (&lock->rwlock, NULL); + if (err != 0) + return err; + lock->initialized = 1; + return 0; +} + +int +glthread_rwlock_rdlock_multithreaded (gl_rwlock_t *lock) +{ + if (!lock->initialized) + { + int err; + + err = pthread_mutex_lock (&lock->guard); + if (err != 0) + return err; + if (!lock->initialized) + { + err = glthread_rwlock_init_multithreaded (lock); + if (err != 0) + { + pthread_mutex_unlock (&lock->guard); + return err; + } + } + err = pthread_mutex_unlock (&lock->guard); + if (err != 0) + return err; + } + return pthread_rwlock_rdlock (&lock->rwlock); +} + +int +glthread_rwlock_wrlock_multithreaded (gl_rwlock_t *lock) +{ + if (!lock->initialized) + { + int err; + + err = pthread_mutex_lock (&lock->guard); + if (err != 0) + return err; + if (!lock->initialized) + { + err = glthread_rwlock_init_multithreaded (lock); + if (err != 0) + { + pthread_mutex_unlock (&lock->guard); + return err; + } + } + err = pthread_mutex_unlock (&lock->guard); + if (err != 0) + return err; + } + return pthread_rwlock_wrlock (&lock->rwlock); +} + +int +glthread_rwlock_unlock_multithreaded (gl_rwlock_t *lock) +{ + if (!lock->initialized) + return EINVAL; + return pthread_rwlock_unlock (&lock->rwlock); +} + +int +glthread_rwlock_destroy_multithreaded (gl_rwlock_t *lock) +{ + int err; + + if (!lock->initialized) + return EINVAL; + err = pthread_rwlock_destroy (&lock->rwlock); + if (err != 0) + return err; + lock->initialized = 0; + return 0; +} + +# endif + +# else + +int +glthread_rwlock_init_multithreaded (gl_rwlock_t *lock) +{ + int err; + + err = pthread_mutex_init (&lock->lock, NULL); + if (err != 0) + return err; + err = pthread_cond_init (&lock->waiting_readers, NULL); + if (err != 0) + return err; + err = pthread_cond_init (&lock->waiting_writers, NULL); + if (err != 0) + return err; + lock->waiting_writers_count = 0; + lock->runcount = 0; + return 0; +} + +int +glthread_rwlock_rdlock_multithreaded (gl_rwlock_t *lock) +{ + int err; + + err = pthread_mutex_lock (&lock->lock); + if (err != 0) + return err; + /* Test whether only readers are currently running, and whether the runcount + field will not overflow. */ + /* POSIX says: "It is implementation-defined whether the calling thread + acquires the lock when a writer does not hold the lock and there are + writers blocked on the lock." Let's say, no: give the writers a higher + priority. */ + while (!(lock->runcount + 1 > 0 && lock->waiting_writers_count == 0)) + { + /* This thread has to wait for a while. Enqueue it among the + waiting_readers. */ + err = pthread_cond_wait (&lock->waiting_readers, &lock->lock); + if (err != 0) + { + pthread_mutex_unlock (&lock->lock); + return err; + } + } + lock->runcount++; + return pthread_mutex_unlock (&lock->lock); +} + +int +glthread_rwlock_wrlock_multithreaded (gl_rwlock_t *lock) +{ + int err; + + err = pthread_mutex_lock (&lock->lock); + if (err != 0) + return err; + /* Test whether no readers or writers are currently running. */ + while (!(lock->runcount == 0)) + { + /* This thread has to wait for a while. Enqueue it among the + waiting_writers. */ + lock->waiting_writers_count++; + err = pthread_cond_wait (&lock->waiting_writers, &lock->lock); + if (err != 0) + { + lock->waiting_writers_count--; + pthread_mutex_unlock (&lock->lock); + return err; + } + lock->waiting_writers_count--; + } + lock->runcount--; /* runcount becomes -1 */ + return pthread_mutex_unlock (&lock->lock); +} + +int +glthread_rwlock_unlock_multithreaded (gl_rwlock_t *lock) +{ + int err; + + err = pthread_mutex_lock (&lock->lock); + if (err != 0) + return err; + if (lock->runcount < 0) + { + /* Drop a writer lock. */ + if (!(lock->runcount == -1)) + { + pthread_mutex_unlock (&lock->lock); + return EINVAL; + } + lock->runcount = 0; + } + else + { + /* Drop a reader lock. */ + if (!(lock->runcount > 0)) + { + pthread_mutex_unlock (&lock->lock); + return EINVAL; + } + lock->runcount--; + } + if (lock->runcount == 0) + { + /* POSIX recommends that "write locks shall take precedence over read + locks", to avoid "writer starvation". */ + if (lock->waiting_writers_count > 0) + { + /* Wake up one of the waiting writers. */ + err = pthread_cond_signal (&lock->waiting_writers); + if (err != 0) + { + pthread_mutex_unlock (&lock->lock); + return err; + } + } + else + { + /* Wake up all waiting readers. */ + err = pthread_cond_broadcast (&lock->waiting_readers); + if (err != 0) + { + pthread_mutex_unlock (&lock->lock); + return err; + } + } + } + return pthread_mutex_unlock (&lock->lock); +} + +int +glthread_rwlock_destroy_multithreaded (gl_rwlock_t *lock) +{ + int err; + + err = pthread_mutex_destroy (&lock->lock); + if (err != 0) + return err; + err = pthread_cond_destroy (&lock->waiting_readers); + if (err != 0) + return err; + err = pthread_cond_destroy (&lock->waiting_writers); + if (err != 0) + return err; + return 0; +} + +# endif + +/* --------------------- gl_recursive_lock_t datatype --------------------- */ + +# if HAVE_PTHREAD_MUTEX_RECURSIVE + +# if defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER || defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP + +int +glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock) +{ + pthread_mutexattr_t attributes; + int err; + + err = pthread_mutexattr_init (&attributes); + if (err != 0) + return err; + err = pthread_mutexattr_settype (&attributes, PTHREAD_MUTEX_RECURSIVE); + if (err != 0) + { + pthread_mutexattr_destroy (&attributes); + return err; + } + err = pthread_mutex_init (lock, &attributes); + if (err != 0) + { + pthread_mutexattr_destroy (&attributes); + return err; + } + err = pthread_mutexattr_destroy (&attributes); + if (err != 0) + return err; + return 0; +} + +# else + +int +glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock) +{ + pthread_mutexattr_t attributes; + int err; + + err = pthread_mutexattr_init (&attributes); + if (err != 0) + return err; + err = pthread_mutexattr_settype (&attributes, PTHREAD_MUTEX_RECURSIVE); + if (err != 0) + { + pthread_mutexattr_destroy (&attributes); + return err; + } + err = pthread_mutex_init (&lock->recmutex, &attributes); + if (err != 0) + { + pthread_mutexattr_destroy (&attributes); + return err; + } + err = pthread_mutexattr_destroy (&attributes); + if (err != 0) + return err; + lock->initialized = 1; + return 0; +} + +int +glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock) +{ + if (!lock->initialized) + { + int err; + + err = pthread_mutex_lock (&lock->guard); + if (err != 0) + return err; + if (!lock->initialized) + { + err = glthread_recursive_lock_init_multithreaded (lock); + if (err != 0) + { + pthread_mutex_unlock (&lock->guard); + return err; + } + } + err = pthread_mutex_unlock (&lock->guard); + if (err != 0) + return err; + } + return pthread_mutex_lock (&lock->recmutex); +} + +int +glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock) +{ + if (!lock->initialized) + return EINVAL; + return pthread_mutex_unlock (&lock->recmutex); +} + +int +glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock) +{ + int err; + + if (!lock->initialized) + return EINVAL; + err = pthread_mutex_destroy (&lock->recmutex); + if (err != 0) + return err; + lock->initialized = 0; + return 0; +} + +# endif + +# else + +int +glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock) +{ + int err; + + err = pthread_mutex_init (&lock->mutex, NULL); + if (err != 0) + return err; + lock->owner = (pthread_t) 0; + lock->depth = 0; + return 0; +} + +int +glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock) +{ + pthread_t self = pthread_self (); + if (lock->owner != self) + { + int err; + + err = pthread_mutex_lock (&lock->mutex); + if (err != 0) + return err; + lock->owner = self; + } + if (++(lock->depth) == 0) /* wraparound? */ + { + lock->depth--; + return EAGAIN; + } + return 0; +} + +int +glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock) +{ + if (lock->owner != pthread_self ()) + return EPERM; + if (lock->depth == 0) + return EINVAL; + if (--(lock->depth) == 0) + { + lock->owner = (pthread_t) 0; + return pthread_mutex_unlock (&lock->mutex); + } + else + return 0; +} + +int +glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock) +{ + if (lock->owner != (pthread_t) 0) + return EBUSY; + return pthread_mutex_destroy (&lock->mutex); +} + +# endif + +/* -------------------------- gl_once_t datatype -------------------------- */ + +static const pthread_once_t fresh_once = PTHREAD_ONCE_INIT; + +int +glthread_once_singlethreaded (pthread_once_t *once_control) +{ + /* We don't know whether pthread_once_t is an integer type, a floating-point + type, a pointer type, or a structure type. */ + char *firstbyte = (char *)once_control; + if (*firstbyte == *(const char *)&fresh_once) + { + /* First time use of once_control. Invert the first byte. */ + *firstbyte = ~ *(const char *)&fresh_once; + return 1; + } + else + return 0; +} + +#endif + +/* ========================================================================= */ + +#if USE_PTH_THREADS + +/* Use the GNU Pth threads library. */ + +/* -------------------------- gl_lock_t datatype -------------------------- */ + +/* ------------------------- gl_rwlock_t datatype ------------------------- */ + +/* --------------------- gl_recursive_lock_t datatype --------------------- */ + +/* -------------------------- gl_once_t datatype -------------------------- */ + +static void +glthread_once_call (void *arg) +{ + void (**gl_once_temp_addr) (void) = (void (**) (void)) arg; + void (*initfunction) (void) = *gl_once_temp_addr; + initfunction (); +} + +int +glthread_once_multithreaded (pth_once_t *once_control, void (*initfunction) (void)) +{ + void (*temp) (void) = initfunction; + return (!pth_once (once_control, glthread_once_call, &temp) ? errno : 0); +} + +int +glthread_once_singlethreaded (pth_once_t *once_control) +{ + /* We know that pth_once_t is an integer type. */ + if (*once_control == PTH_ONCE_INIT) + { + /* First time use of once_control. Invert the marker. */ + *once_control = ~ PTH_ONCE_INIT; + return 1; + } + else + return 0; +} + +#endif + +/* ========================================================================= */ + +#if USE_SOLARIS_THREADS + +/* Use the old Solaris threads library. */ + +/* -------------------------- gl_lock_t datatype -------------------------- */ + +/* ------------------------- gl_rwlock_t datatype ------------------------- */ + +/* --------------------- gl_recursive_lock_t datatype --------------------- */ + +int +glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock) +{ + int err; + + err = mutex_init (&lock->mutex, USYNC_THREAD, NULL); + if (err != 0) + return err; + lock->owner = (thread_t) 0; + lock->depth = 0; + return 0; +} + +int +glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock) +{ + thread_t self = thr_self (); + if (lock->owner != self) + { + int err; + + err = mutex_lock (&lock->mutex); + if (err != 0) + return err; + lock->owner = self; + } + if (++(lock->depth) == 0) /* wraparound? */ + { + lock->depth--; + return EAGAIN; + } + return 0; +} + +int +glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock) +{ + if (lock->owner != thr_self ()) + return EPERM; + if (lock->depth == 0) + return EINVAL; + if (--(lock->depth) == 0) + { + lock->owner = (thread_t) 0; + return mutex_unlock (&lock->mutex); + } + else + return 0; +} + +int +glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock) +{ + if (lock->owner != (thread_t) 0) + return EBUSY; + return mutex_destroy (&lock->mutex); +} + +/* -------------------------- gl_once_t datatype -------------------------- */ + +int +glthread_once_multithreaded (gl_once_t *once_control, void (*initfunction) (void)) +{ + if (!once_control->inited) + { + int err; + + /* Use the mutex to guarantee that if another thread is already calling + the initfunction, this thread waits until it's finished. */ + err = mutex_lock (&once_control->mutex); + if (err != 0) + return err; + if (!once_control->inited) + { + once_control->inited = 1; + initfunction (); + } + return mutex_unlock (&once_control->mutex); + } + else + return 0; +} + +int +glthread_once_singlethreaded (gl_once_t *once_control) +{ + /* We know that gl_once_t contains an integer type. */ + if (!once_control->inited) + { + /* First time use of once_control. Invert the marker. */ + once_control->inited = ~ 0; + return 1; + } + else + return 0; +} + +#endif + +/* ========================================================================= */ + +#if USE_WINDOWS_THREADS + +/* -------------------------- gl_lock_t datatype -------------------------- */ + +void +glthread_lock_init_func (gl_lock_t *lock) +{ + InitializeCriticalSection (&lock->lock); + lock->guard.done = 1; +} + +int +glthread_lock_lock_func (gl_lock_t *lock) +{ + if (!lock->guard.done) + { + if (InterlockedIncrement (&lock->guard.started) == 0) + /* This thread is the first one to need this lock. Initialize it. */ + glthread_lock_init (lock); + else + /* Yield the CPU while waiting for another thread to finish + initializing this lock. */ + while (!lock->guard.done) + Sleep (0); + } + EnterCriticalSection (&lock->lock); + return 0; +} + +int +glthread_lock_unlock_func (gl_lock_t *lock) +{ + if (!lock->guard.done) + return EINVAL; + LeaveCriticalSection (&lock->lock); + return 0; +} + +int +glthread_lock_destroy_func (gl_lock_t *lock) +{ + if (!lock->guard.done) + return EINVAL; + DeleteCriticalSection (&lock->lock); + lock->guard.done = 0; + return 0; +} + +/* ------------------------- gl_rwlock_t datatype ------------------------- */ + +/* In this file, the waitqueues are implemented as circular arrays. */ +#define gl_waitqueue_t gl_carray_waitqueue_t + +static void +gl_waitqueue_init (gl_waitqueue_t *wq) +{ + wq->array = NULL; + wq->count = 0; + wq->alloc = 0; + wq->offset = 0; +} + +/* Enqueues the current thread, represented by an event, in a wait queue. + Returns INVALID_HANDLE_VALUE if an allocation failure occurs. */ +static HANDLE +gl_waitqueue_add (gl_waitqueue_t *wq) +{ + HANDLE event; + unsigned int index; + + if (wq->count == wq->alloc) + { + unsigned int new_alloc = 2 * wq->alloc + 1; + HANDLE *new_array = + (HANDLE *) realloc (wq->array, new_alloc * sizeof (HANDLE)); + if (new_array == NULL) + /* No more memory. */ + return INVALID_HANDLE_VALUE; + /* Now is a good opportunity to rotate the array so that its contents + starts at offset 0. */ + if (wq->offset > 0) + { + unsigned int old_count = wq->count; + unsigned int old_alloc = wq->alloc; + unsigned int old_offset = wq->offset; + unsigned int i; + if (old_offset + old_count > old_alloc) + { + unsigned int limit = old_offset + old_count - old_alloc; + for (i = 0; i < limit; i++) + new_array[old_alloc + i] = new_array[i]; + } + for (i = 0; i < old_count; i++) + new_array[i] = new_array[old_offset + i]; + wq->offset = 0; + } + wq->array = new_array; + wq->alloc = new_alloc; + } + /* Whether the created event is a manual-reset one or an auto-reset one, + does not matter, since we will wait on it only once. */ + event = CreateEvent (NULL, TRUE, FALSE, NULL); + if (event == INVALID_HANDLE_VALUE) + /* No way to allocate an event. */ + return INVALID_HANDLE_VALUE; + index = wq->offset + wq->count; + if (index >= wq->alloc) + index -= wq->alloc; + wq->array[index] = event; + wq->count++; + return event; +} + +/* Notifies the first thread from a wait queue and dequeues it. */ +static void +gl_waitqueue_notify_first (gl_waitqueue_t *wq) +{ + SetEvent (wq->array[wq->offset + 0]); + wq->offset++; + wq->count--; + if (wq->count == 0 || wq->offset == wq->alloc) + wq->offset = 0; +} + +/* Notifies all threads from a wait queue and dequeues them all. */ +static void +gl_waitqueue_notify_all (gl_waitqueue_t *wq) +{ + unsigned int i; + + for (i = 0; i < wq->count; i++) + { + unsigned int index = wq->offset + i; + if (index >= wq->alloc) + index -= wq->alloc; + SetEvent (wq->array[index]); + } + wq->count = 0; + wq->offset = 0; +} + +void +glthread_rwlock_init_func (gl_rwlock_t *lock) +{ + InitializeCriticalSection (&lock->lock); + gl_waitqueue_init (&lock->waiting_readers); + gl_waitqueue_init (&lock->waiting_writers); + lock->runcount = 0; + lock->guard.done = 1; +} + +int +glthread_rwlock_rdlock_func (gl_rwlock_t *lock) +{ + if (!lock->guard.done) + { + if (InterlockedIncrement (&lock->guard.started) == 0) + /* This thread is the first one to need this lock. Initialize it. */ + glthread_rwlock_init (lock); + else + /* Yield the CPU while waiting for another thread to finish + initializing this lock. */ + while (!lock->guard.done) + Sleep (0); + } + EnterCriticalSection (&lock->lock); + /* Test whether only readers are currently running, and whether the runcount + field will not overflow. */ + if (!(lock->runcount + 1 > 0)) + { + /* This thread has to wait for a while. Enqueue it among the + waiting_readers. */ + HANDLE event = gl_waitqueue_add (&lock->waiting_readers); + if (event != INVALID_HANDLE_VALUE) + { + DWORD result; + LeaveCriticalSection (&lock->lock); + /* Wait until another thread signals this event. */ + result = WaitForSingleObject (event, INFINITE); + if (result == WAIT_FAILED || result == WAIT_TIMEOUT) + abort (); + CloseHandle (event); + /* The thread which signalled the event already did the bookkeeping: + removed us from the waiting_readers, incremented lock->runcount. */ + if (!(lock->runcount > 0)) + abort (); + return 0; + } + else + { + /* Allocation failure. Weird. */ + do + { + LeaveCriticalSection (&lock->lock); + Sleep (1); + EnterCriticalSection (&lock->lock); + } + while (!(lock->runcount + 1 > 0)); + } + } + lock->runcount++; + LeaveCriticalSection (&lock->lock); + return 0; +} + +int +glthread_rwlock_wrlock_func (gl_rwlock_t *lock) +{ + if (!lock->guard.done) + { + if (InterlockedIncrement (&lock->guard.started) == 0) + /* This thread is the first one to need this lock. Initialize it. */ + glthread_rwlock_init (lock); + else + /* Yield the CPU while waiting for another thread to finish + initializing this lock. */ + while (!lock->guard.done) + Sleep (0); + } + EnterCriticalSection (&lock->lock); + /* Test whether no readers or writers are currently running. */ + if (!(lock->runcount == 0)) + { + /* This thread has to wait for a while. Enqueue it among the + waiting_writers. */ + HANDLE event = gl_waitqueue_add (&lock->waiting_writers); + if (event != INVALID_HANDLE_VALUE) + { + DWORD result; + LeaveCriticalSection (&lock->lock); + /* Wait until another thread signals this event. */ + result = WaitForSingleObject (event, INFINITE); + if (result == WAIT_FAILED || result == WAIT_TIMEOUT) + abort (); + CloseHandle (event); + /* The thread which signalled the event already did the bookkeeping: + removed us from the waiting_writers, set lock->runcount = -1. */ + if (!(lock->runcount == -1)) + abort (); + return 0; + } + else + { + /* Allocation failure. Weird. */ + do + { + LeaveCriticalSection (&lock->lock); + Sleep (1); + EnterCriticalSection (&lock->lock); + } + while (!(lock->runcount == 0)); + } + } + lock->runcount--; /* runcount becomes -1 */ + LeaveCriticalSection (&lock->lock); + return 0; +} + +int +glthread_rwlock_unlock_func (gl_rwlock_t *lock) +{ + if (!lock->guard.done) + return EINVAL; + EnterCriticalSection (&lock->lock); + if (lock->runcount < 0) + { + /* Drop a writer lock. */ + if (!(lock->runcount == -1)) + abort (); + lock->runcount = 0; + } + else + { + /* Drop a reader lock. */ + if (!(lock->runcount > 0)) + { + LeaveCriticalSection (&lock->lock); + return EPERM; + } + lock->runcount--; + } + if (lock->runcount == 0) + { + /* POSIX recommends that "write locks shall take precedence over read + locks", to avoid "writer starvation". */ + if (lock->waiting_writers.count > 0) + { + /* Wake up one of the waiting writers. */ + lock->runcount--; + gl_waitqueue_notify_first (&lock->waiting_writers); + } + else + { + /* Wake up all waiting readers. */ + lock->runcount += lock->waiting_readers.count; + gl_waitqueue_notify_all (&lock->waiting_readers); + } + } + LeaveCriticalSection (&lock->lock); + return 0; +} + +int +glthread_rwlock_destroy_func (gl_rwlock_t *lock) +{ + if (!lock->guard.done) + return EINVAL; + if (lock->runcount != 0) + return EBUSY; + DeleteCriticalSection (&lock->lock); + if (lock->waiting_readers.array != NULL) + free (lock->waiting_readers.array); + if (lock->waiting_writers.array != NULL) + free (lock->waiting_writers.array); + lock->guard.done = 0; + return 0; +} + +/* --------------------- gl_recursive_lock_t datatype --------------------- */ + +void +glthread_recursive_lock_init_func (gl_recursive_lock_t *lock) +{ + lock->owner = 0; + lock->depth = 0; + InitializeCriticalSection (&lock->lock); + lock->guard.done = 1; +} + +int +glthread_recursive_lock_lock_func (gl_recursive_lock_t *lock) +{ + if (!lock->guard.done) + { + if (InterlockedIncrement (&lock->guard.started) == 0) + /* This thread is the first one to need this lock. Initialize it. */ + glthread_recursive_lock_init (lock); + else + /* Yield the CPU while waiting for another thread to finish + initializing this lock. */ + while (!lock->guard.done) + Sleep (0); + } + { + DWORD self = GetCurrentThreadId (); + if (lock->owner != self) + { + EnterCriticalSection (&lock->lock); + lock->owner = self; + } + if (++(lock->depth) == 0) /* wraparound? */ + { + lock->depth--; + return EAGAIN; + } + } + return 0; +} + +int +glthread_recursive_lock_unlock_func (gl_recursive_lock_t *lock) +{ + if (lock->owner != GetCurrentThreadId ()) + return EPERM; + if (lock->depth == 0) + return EINVAL; + if (--(lock->depth) == 0) + { + lock->owner = 0; + LeaveCriticalSection (&lock->lock); + } + return 0; +} + +int +glthread_recursive_lock_destroy_func (gl_recursive_lock_t *lock) +{ + if (lock->owner != 0) + return EBUSY; + DeleteCriticalSection (&lock->lock); + lock->guard.done = 0; + return 0; +} + +/* -------------------------- gl_once_t datatype -------------------------- */ + +void +glthread_once_func (gl_once_t *once_control, void (*initfunction) (void)) +{ + if (once_control->inited <= 0) + { + if (InterlockedIncrement (&once_control->started) == 0) + { + /* This thread is the first one to come to this once_control. */ + InitializeCriticalSection (&once_control->lock); + EnterCriticalSection (&once_control->lock); + once_control->inited = 0; + initfunction (); + once_control->inited = 1; + LeaveCriticalSection (&once_control->lock); + } + else + { + /* Undo last operation. */ + InterlockedDecrement (&once_control->started); + /* Some other thread has already started the initialization. + Yield the CPU while waiting for the other thread to finish + initializing and taking the lock. */ + while (once_control->inited < 0) + Sleep (0); + if (once_control->inited <= 0) + { + /* Take the lock. This blocks until the other thread has + finished calling the initfunction. */ + EnterCriticalSection (&once_control->lock); + LeaveCriticalSection (&once_control->lock); + if (!(once_control->inited > 0)) + abort (); + } + } + } +} + +#endif + +/* ========================================================================= */ diff --git a/gettext-tools/gnulib-lib/glthread/lock.h b/gettext-tools/gnulib-lib/glthread/lock.h new file mode 100644 index 0000000..36096c4 --- /dev/null +++ b/gettext-tools/gnulib-lib/glthread/lock.h @@ -0,0 +1,927 @@ +/* Locking in multithreaded situations. + Copyright (C) 2005-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . */ + +/* Written by Bruno Haible , 2005. + Based on GCC's gthr-posix.h, gthr-posix95.h, gthr-solaris.h, + gthr-win32.h. */ + +/* This file contains locking primitives for use with a given thread library. + It does not contain primitives for creating threads or for other + synchronization primitives. + + Normal (non-recursive) locks: + Type: gl_lock_t + Declaration: gl_lock_define(extern, name) + Initializer: gl_lock_define_initialized(, name) + Initialization: gl_lock_init (name); + Taking the lock: gl_lock_lock (name); + Releasing the lock: gl_lock_unlock (name); + De-initialization: gl_lock_destroy (name); + Equivalent functions with control of error handling: + Initialization: err = glthread_lock_init (&name); + Taking the lock: err = glthread_lock_lock (&name); + Releasing the lock: err = glthread_lock_unlock (&name); + De-initialization: err = glthread_lock_destroy (&name); + + Read-Write (non-recursive) locks: + Type: gl_rwlock_t + Declaration: gl_rwlock_define(extern, name) + Initializer: gl_rwlock_define_initialized(, name) + Initialization: gl_rwlock_init (name); + Taking the lock: gl_rwlock_rdlock (name); + gl_rwlock_wrlock (name); + Releasing the lock: gl_rwlock_unlock (name); + De-initialization: gl_rwlock_destroy (name); + Equivalent functions with control of error handling: + Initialization: err = glthread_rwlock_init (&name); + Taking the lock: err = glthread_rwlock_rdlock (&name); + err = glthread_rwlock_wrlock (&name); + Releasing the lock: err = glthread_rwlock_unlock (&name); + De-initialization: err = glthread_rwlock_destroy (&name); + + Recursive locks: + Type: gl_recursive_lock_t + Declaration: gl_recursive_lock_define(extern, name) + Initializer: gl_recursive_lock_define_initialized(, name) + Initialization: gl_recursive_lock_init (name); + Taking the lock: gl_recursive_lock_lock (name); + Releasing the lock: gl_recursive_lock_unlock (name); + De-initialization: gl_recursive_lock_destroy (name); + Equivalent functions with control of error handling: + Initialization: err = glthread_recursive_lock_init (&name); + Taking the lock: err = glthread_recursive_lock_lock (&name); + Releasing the lock: err = glthread_recursive_lock_unlock (&name); + De-initialization: err = glthread_recursive_lock_destroy (&name); + + Once-only execution: + Type: gl_once_t + Initializer: gl_once_define(extern, name) + Execution: gl_once (name, initfunction); + Equivalent functions with control of error handling: + Execution: err = glthread_once (&name, initfunction); +*/ + + +#ifndef _LOCK_H +#define _LOCK_H + +#include +#include + +/* ========================================================================= */ + +#if USE_POSIX_THREADS + +/* Use the POSIX threads library. */ + +# include + +# ifdef __cplusplus +extern "C" { +# endif + +# if PTHREAD_IN_USE_DETECTION_HARD + +/* The pthread_in_use() detection needs to be done at runtime. */ +# define pthread_in_use() \ + glthread_in_use () +extern int glthread_in_use (void); + +# endif + +# if USE_POSIX_THREADS_WEAK + +/* Use weak references to the POSIX threads library. */ + +/* Weak references avoid dragging in external libraries if the other parts + of the program don't use them. Here we use them, because we don't want + every program that uses libintl to depend on libpthread. This assumes + that libpthread would not be loaded after libintl; i.e. if libintl is + loaded first, by an executable that does not depend on libpthread, and + then a module is dynamically loaded that depends on libpthread, libintl + will not be multithread-safe. */ + +/* The way to test at runtime whether libpthread is present is to test + whether a function pointer's value, such as &pthread_mutex_init, is + non-NULL. However, some versions of GCC have a bug through which, in + PIC mode, &foo != NULL always evaluates to true if there is a direct + call to foo(...) in the same function. To avoid this, we test the + address of a function in libpthread that we don't use. */ + +# pragma weak pthread_mutex_init +# pragma weak pthread_mutex_lock +# pragma weak pthread_mutex_unlock +# pragma weak pthread_mutex_destroy +# pragma weak pthread_rwlock_init +# pragma weak pthread_rwlock_rdlock +# pragma weak pthread_rwlock_wrlock +# pragma weak pthread_rwlock_unlock +# pragma weak pthread_rwlock_destroy +# pragma weak pthread_once +# pragma weak pthread_cond_init +# pragma weak pthread_cond_wait +# pragma weak pthread_cond_signal +# pragma weak pthread_cond_broadcast +# pragma weak pthread_cond_destroy +# pragma weak pthread_mutexattr_init +# pragma weak pthread_mutexattr_settype +# pragma weak pthread_mutexattr_destroy +# ifndef pthread_self +# pragma weak pthread_self +# endif + +# if !PTHREAD_IN_USE_DETECTION_HARD +# pragma weak pthread_cancel +# define pthread_in_use() (pthread_cancel != NULL) +# endif + +# else + +# if !PTHREAD_IN_USE_DETECTION_HARD +# define pthread_in_use() 1 +# endif + +# endif + +/* -------------------------- gl_lock_t datatype -------------------------- */ + +typedef pthread_mutex_t gl_lock_t; +# define gl_lock_define(STORAGECLASS, NAME) \ + STORAGECLASS pthread_mutex_t NAME; +# define gl_lock_define_initialized(STORAGECLASS, NAME) \ + STORAGECLASS pthread_mutex_t NAME = gl_lock_initializer; +# define gl_lock_initializer \ + PTHREAD_MUTEX_INITIALIZER +# define glthread_lock_init(LOCK) \ + (pthread_in_use () ? pthread_mutex_init (LOCK, NULL) : 0) +# define glthread_lock_lock(LOCK) \ + (pthread_in_use () ? pthread_mutex_lock (LOCK) : 0) +# define glthread_lock_unlock(LOCK) \ + (pthread_in_use () ? pthread_mutex_unlock (LOCK) : 0) +# define glthread_lock_destroy(LOCK) \ + (pthread_in_use () ? pthread_mutex_destroy (LOCK) : 0) + +/* ------------------------- gl_rwlock_t datatype ------------------------- */ + +# if HAVE_PTHREAD_RWLOCK + +# ifdef PTHREAD_RWLOCK_INITIALIZER + +typedef pthread_rwlock_t gl_rwlock_t; +# define gl_rwlock_define(STORAGECLASS, NAME) \ + STORAGECLASS pthread_rwlock_t NAME; +# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \ + STORAGECLASS pthread_rwlock_t NAME = gl_rwlock_initializer; +# define gl_rwlock_initializer \ + PTHREAD_RWLOCK_INITIALIZER +# define glthread_rwlock_init(LOCK) \ + (pthread_in_use () ? pthread_rwlock_init (LOCK, NULL) : 0) +# define glthread_rwlock_rdlock(LOCK) \ + (pthread_in_use () ? pthread_rwlock_rdlock (LOCK) : 0) +# define glthread_rwlock_wrlock(LOCK) \ + (pthread_in_use () ? pthread_rwlock_wrlock (LOCK) : 0) +# define glthread_rwlock_unlock(LOCK) \ + (pthread_in_use () ? pthread_rwlock_unlock (LOCK) : 0) +# define glthread_rwlock_destroy(LOCK) \ + (pthread_in_use () ? pthread_rwlock_destroy (LOCK) : 0) + +# else + +typedef struct + { + int initialized; + pthread_mutex_t guard; /* protects the initialization */ + pthread_rwlock_t rwlock; /* read-write lock */ + } + gl_rwlock_t; +# define gl_rwlock_define(STORAGECLASS, NAME) \ + STORAGECLASS gl_rwlock_t NAME; +# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \ + STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer; +# define gl_rwlock_initializer \ + { 0, PTHREAD_MUTEX_INITIALIZER } +# define glthread_rwlock_init(LOCK) \ + (pthread_in_use () ? glthread_rwlock_init_multithreaded (LOCK) : 0) +# define glthread_rwlock_rdlock(LOCK) \ + (pthread_in_use () ? glthread_rwlock_rdlock_multithreaded (LOCK) : 0) +# define glthread_rwlock_wrlock(LOCK) \ + (pthread_in_use () ? glthread_rwlock_wrlock_multithreaded (LOCK) : 0) +# define glthread_rwlock_unlock(LOCK) \ + (pthread_in_use () ? glthread_rwlock_unlock_multithreaded (LOCK) : 0) +# define glthread_rwlock_destroy(LOCK) \ + (pthread_in_use () ? glthread_rwlock_destroy_multithreaded (LOCK) : 0) +extern int glthread_rwlock_init_multithreaded (gl_rwlock_t *lock); +extern int glthread_rwlock_rdlock_multithreaded (gl_rwlock_t *lock); +extern int glthread_rwlock_wrlock_multithreaded (gl_rwlock_t *lock); +extern int glthread_rwlock_unlock_multithreaded (gl_rwlock_t *lock); +extern int glthread_rwlock_destroy_multithreaded (gl_rwlock_t *lock); + +# endif + +# else + +typedef struct + { + pthread_mutex_t lock; /* protects the remaining fields */ + pthread_cond_t waiting_readers; /* waiting readers */ + pthread_cond_t waiting_writers; /* waiting writers */ + unsigned int waiting_writers_count; /* number of waiting writers */ + int runcount; /* number of readers running, or -1 when a writer runs */ + } + gl_rwlock_t; +# define gl_rwlock_define(STORAGECLASS, NAME) \ + STORAGECLASS gl_rwlock_t NAME; +# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \ + STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer; +# define gl_rwlock_initializer \ + { PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER, 0, 0 } +# define glthread_rwlock_init(LOCK) \ + (pthread_in_use () ? glthread_rwlock_init_multithreaded (LOCK) : 0) +# define glthread_rwlock_rdlock(LOCK) \ + (pthread_in_use () ? glthread_rwlock_rdlock_multithreaded (LOCK) : 0) +# define glthread_rwlock_wrlock(LOCK) \ + (pthread_in_use () ? glthread_rwlock_wrlock_multithreaded (LOCK) : 0) +# define glthread_rwlock_unlock(LOCK) \ + (pthread_in_use () ? glthread_rwlock_unlock_multithreaded (LOCK) : 0) +# define glthread_rwlock_destroy(LOCK) \ + (pthread_in_use () ? glthread_rwlock_destroy_multithreaded (LOCK) : 0) +extern int glthread_rwlock_init_multithreaded (gl_rwlock_t *lock); +extern int glthread_rwlock_rdlock_multithreaded (gl_rwlock_t *lock); +extern int glthread_rwlock_wrlock_multithreaded (gl_rwlock_t *lock); +extern int glthread_rwlock_unlock_multithreaded (gl_rwlock_t *lock); +extern int glthread_rwlock_destroy_multithreaded (gl_rwlock_t *lock); + +# endif + +/* --------------------- gl_recursive_lock_t datatype --------------------- */ + +# if HAVE_PTHREAD_MUTEX_RECURSIVE + +# if defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER || defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP + +typedef pthread_mutex_t gl_recursive_lock_t; +# define gl_recursive_lock_define(STORAGECLASS, NAME) \ + STORAGECLASS pthread_mutex_t NAME; +# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \ + STORAGECLASS pthread_mutex_t NAME = gl_recursive_lock_initializer; +# ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER +# define gl_recursive_lock_initializer \ + PTHREAD_RECURSIVE_MUTEX_INITIALIZER +# else +# define gl_recursive_lock_initializer \ + PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP +# endif +# define glthread_recursive_lock_init(LOCK) \ + (pthread_in_use () ? glthread_recursive_lock_init_multithreaded (LOCK) : 0) +# define glthread_recursive_lock_lock(LOCK) \ + (pthread_in_use () ? pthread_mutex_lock (LOCK) : 0) +# define glthread_recursive_lock_unlock(LOCK) \ + (pthread_in_use () ? pthread_mutex_unlock (LOCK) : 0) +# define glthread_recursive_lock_destroy(LOCK) \ + (pthread_in_use () ? pthread_mutex_destroy (LOCK) : 0) +extern int glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock); + +# else + +typedef struct + { + pthread_mutex_t recmutex; /* recursive mutex */ + pthread_mutex_t guard; /* protects the initialization */ + int initialized; + } + gl_recursive_lock_t; +# define gl_recursive_lock_define(STORAGECLASS, NAME) \ + STORAGECLASS gl_recursive_lock_t NAME; +# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \ + STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer; +# define gl_recursive_lock_initializer \ + { PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, 0 } +# define glthread_recursive_lock_init(LOCK) \ + (pthread_in_use () ? glthread_recursive_lock_init_multithreaded (LOCK) : 0) +# define glthread_recursive_lock_lock(LOCK) \ + (pthread_in_use () ? glthread_recursive_lock_lock_multithreaded (LOCK) : 0) +# define glthread_recursive_lock_unlock(LOCK) \ + (pthread_in_use () ? glthread_recursive_lock_unlock_multithreaded (LOCK) : 0) +# define glthread_recursive_lock_destroy(LOCK) \ + (pthread_in_use () ? glthread_recursive_lock_destroy_multithreaded (LOCK) : 0) +extern int glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock); +extern int glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock); +extern int glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock); +extern int glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock); + +# endif + +# else + +/* Old versions of POSIX threads on Solaris did not have recursive locks. + We have to implement them ourselves. */ + +typedef struct + { + pthread_mutex_t mutex; + pthread_t owner; + unsigned long depth; + } + gl_recursive_lock_t; +# define gl_recursive_lock_define(STORAGECLASS, NAME) \ + STORAGECLASS gl_recursive_lock_t NAME; +# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \ + STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer; +# define gl_recursive_lock_initializer \ + { PTHREAD_MUTEX_INITIALIZER, (pthread_t) 0, 0 } +# define glthread_recursive_lock_init(LOCK) \ + (pthread_in_use () ? glthread_recursive_lock_init_multithreaded (LOCK) : 0) +# define glthread_recursive_lock_lock(LOCK) \ + (pthread_in_use () ? glthread_recursive_lock_lock_multithreaded (LOCK) : 0) +# define glthread_recursive_lock_unlock(LOCK) \ + (pthread_in_use () ? glthread_recursive_lock_unlock_multithreaded (LOCK) : 0) +# define glthread_recursive_lock_destroy(LOCK) \ + (pthread_in_use () ? glthread_recursive_lock_destroy_multithreaded (LOCK) : 0) +extern int glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock); +extern int glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock); +extern int glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock); +extern int glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock); + +# endif + +/* -------------------------- gl_once_t datatype -------------------------- */ + +typedef pthread_once_t gl_once_t; +# define gl_once_define(STORAGECLASS, NAME) \ + STORAGECLASS pthread_once_t NAME = PTHREAD_ONCE_INIT; +# define glthread_once(ONCE_CONTROL, INITFUNCTION) \ + (pthread_in_use () \ + ? pthread_once (ONCE_CONTROL, INITFUNCTION) \ + : (glthread_once_singlethreaded (ONCE_CONTROL) ? (INITFUNCTION (), 0) : 0)) +extern int glthread_once_singlethreaded (pthread_once_t *once_control); + +# ifdef __cplusplus +} +# endif + +#endif + +/* ========================================================================= */ + +#if USE_PTH_THREADS + +/* Use the GNU Pth threads library. */ + +# include + +# ifdef __cplusplus +extern "C" { +# endif + +# if USE_PTH_THREADS_WEAK + +/* Use weak references to the GNU Pth threads library. */ + +# pragma weak pth_mutex_init +# pragma weak pth_mutex_acquire +# pragma weak pth_mutex_release +# pragma weak pth_rwlock_init +# pragma weak pth_rwlock_acquire +# pragma weak pth_rwlock_release +# pragma weak pth_once + +# pragma weak pth_cancel +# define pth_in_use() (pth_cancel != NULL) + +# else + +# define pth_in_use() 1 + +# endif + +/* -------------------------- gl_lock_t datatype -------------------------- */ + +typedef pth_mutex_t gl_lock_t; +# define gl_lock_define(STORAGECLASS, NAME) \ + STORAGECLASS pth_mutex_t NAME; +# define gl_lock_define_initialized(STORAGECLASS, NAME) \ + STORAGECLASS pth_mutex_t NAME = gl_lock_initializer; +# define gl_lock_initializer \ + PTH_MUTEX_INIT +# define glthread_lock_init(LOCK) \ + (pth_in_use () && !pth_mutex_init (LOCK) ? errno : 0) +# define glthread_lock_lock(LOCK) \ + (pth_in_use () && !pth_mutex_acquire (LOCK, 0, NULL) ? errno : 0) +# define glthread_lock_unlock(LOCK) \ + (pth_in_use () && !pth_mutex_release (LOCK) ? errno : 0) +# define glthread_lock_destroy(LOCK) \ + ((void)(LOCK), 0) + +/* ------------------------- gl_rwlock_t datatype ------------------------- */ + +typedef pth_rwlock_t gl_rwlock_t; +# define gl_rwlock_define(STORAGECLASS, NAME) \ + STORAGECLASS pth_rwlock_t NAME; +# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \ + STORAGECLASS pth_rwlock_t NAME = gl_rwlock_initializer; +# define gl_rwlock_initializer \ + PTH_RWLOCK_INIT +# define glthread_rwlock_init(LOCK) \ + (pth_in_use () && !pth_rwlock_init (LOCK) ? errno : 0) +# define glthread_rwlock_rdlock(LOCK) \ + (pth_in_use () && !pth_rwlock_acquire (LOCK, PTH_RWLOCK_RD, 0, NULL) ? errno : 0) +# define glthread_rwlock_wrlock(LOCK) \ + (pth_in_use () && !pth_rwlock_acquire (LOCK, PTH_RWLOCK_RW, 0, NULL) ? errno : 0) +# define glthread_rwlock_unlock(LOCK) \ + (pth_in_use () && !pth_rwlock_release (LOCK) ? errno : 0) +# define glthread_rwlock_destroy(LOCK) \ + ((void)(LOCK), 0) + +/* --------------------- gl_recursive_lock_t datatype --------------------- */ + +/* In Pth, mutexes are recursive by default. */ +typedef pth_mutex_t gl_recursive_lock_t; +# define gl_recursive_lock_define(STORAGECLASS, NAME) \ + STORAGECLASS pth_mutex_t NAME; +# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \ + STORAGECLASS pth_mutex_t NAME = gl_recursive_lock_initializer; +# define gl_recursive_lock_initializer \ + PTH_MUTEX_INIT +# define glthread_recursive_lock_init(LOCK) \ + (pth_in_use () && !pth_mutex_init (LOCK) ? errno : 0) +# define glthread_recursive_lock_lock(LOCK) \ + (pth_in_use () && !pth_mutex_acquire (LOCK, 0, NULL) ? errno : 0) +# define glthread_recursive_lock_unlock(LOCK) \ + (pth_in_use () && !pth_mutex_release (LOCK) ? errno : 0) +# define glthread_recursive_lock_destroy(LOCK) \ + ((void)(LOCK), 0) + +/* -------------------------- gl_once_t datatype -------------------------- */ + +typedef pth_once_t gl_once_t; +# define gl_once_define(STORAGECLASS, NAME) \ + STORAGECLASS pth_once_t NAME = PTH_ONCE_INIT; +# define glthread_once(ONCE_CONTROL, INITFUNCTION) \ + (pth_in_use () \ + ? glthread_once_multithreaded (ONCE_CONTROL, INITFUNCTION) \ + : (glthread_once_singlethreaded (ONCE_CONTROL) ? (INITFUNCTION (), 0) : 0)) +extern int glthread_once_multithreaded (pth_once_t *once_control, void (*initfunction) (void)); +extern int glthread_once_singlethreaded (pth_once_t *once_control); + +# ifdef __cplusplus +} +# endif + +#endif + +/* ========================================================================= */ + +#if USE_SOLARIS_THREADS + +/* Use the old Solaris threads library. */ + +# include +# include + +# ifdef __cplusplus +extern "C" { +# endif + +# if USE_SOLARIS_THREADS_WEAK + +/* Use weak references to the old Solaris threads library. */ + +# pragma weak mutex_init +# pragma weak mutex_lock +# pragma weak mutex_unlock +# pragma weak mutex_destroy +# pragma weak rwlock_init +# pragma weak rw_rdlock +# pragma weak rw_wrlock +# pragma weak rw_unlock +# pragma weak rwlock_destroy +# pragma weak thr_self + +# pragma weak thr_suspend +# define thread_in_use() (thr_suspend != NULL) + +# else + +# define thread_in_use() 1 + +# endif + +/* -------------------------- gl_lock_t datatype -------------------------- */ + +typedef mutex_t gl_lock_t; +# define gl_lock_define(STORAGECLASS, NAME) \ + STORAGECLASS mutex_t NAME; +# define gl_lock_define_initialized(STORAGECLASS, NAME) \ + STORAGECLASS mutex_t NAME = gl_lock_initializer; +# define gl_lock_initializer \ + DEFAULTMUTEX +# define glthread_lock_init(LOCK) \ + (thread_in_use () ? mutex_init (LOCK, USYNC_THREAD, NULL) : 0) +# define glthread_lock_lock(LOCK) \ + (thread_in_use () ? mutex_lock (LOCK) : 0) +# define glthread_lock_unlock(LOCK) \ + (thread_in_use () ? mutex_unlock (LOCK) : 0) +# define glthread_lock_destroy(LOCK) \ + (thread_in_use () ? mutex_destroy (LOCK) : 0) + +/* ------------------------- gl_rwlock_t datatype ------------------------- */ + +typedef rwlock_t gl_rwlock_t; +# define gl_rwlock_define(STORAGECLASS, NAME) \ + STORAGECLASS rwlock_t NAME; +# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \ + STORAGECLASS rwlock_t NAME = gl_rwlock_initializer; +# define gl_rwlock_initializer \ + DEFAULTRWLOCK +# define glthread_rwlock_init(LOCK) \ + (thread_in_use () ? rwlock_init (LOCK, USYNC_THREAD, NULL) : 0) +# define glthread_rwlock_rdlock(LOCK) \ + (thread_in_use () ? rw_rdlock (LOCK) : 0) +# define glthread_rwlock_wrlock(LOCK) \ + (thread_in_use () ? rw_wrlock (LOCK) : 0) +# define glthread_rwlock_unlock(LOCK) \ + (thread_in_use () ? rw_unlock (LOCK) : 0) +# define glthread_rwlock_destroy(LOCK) \ + (thread_in_use () ? rwlock_destroy (LOCK) : 0) + +/* --------------------- gl_recursive_lock_t datatype --------------------- */ + +/* Old Solaris threads did not have recursive locks. + We have to implement them ourselves. */ + +typedef struct + { + mutex_t mutex; + thread_t owner; + unsigned long depth; + } + gl_recursive_lock_t; +# define gl_recursive_lock_define(STORAGECLASS, NAME) \ + STORAGECLASS gl_recursive_lock_t NAME; +# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \ + STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer; +# define gl_recursive_lock_initializer \ + { DEFAULTMUTEX, (thread_t) 0, 0 } +# define glthread_recursive_lock_init(LOCK) \ + (thread_in_use () ? glthread_recursive_lock_init_multithreaded (LOCK) : 0) +# define glthread_recursive_lock_lock(LOCK) \ + (thread_in_use () ? glthread_recursive_lock_lock_multithreaded (LOCK) : 0) +# define glthread_recursive_lock_unlock(LOCK) \ + (thread_in_use () ? glthread_recursive_lock_unlock_multithreaded (LOCK) : 0) +# define glthread_recursive_lock_destroy(LOCK) \ + (thread_in_use () ? glthread_recursive_lock_destroy_multithreaded (LOCK) : 0) +extern int glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock); +extern int glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock); +extern int glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock); +extern int glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock); + +/* -------------------------- gl_once_t datatype -------------------------- */ + +typedef struct + { + volatile int inited; + mutex_t mutex; + } + gl_once_t; +# define gl_once_define(STORAGECLASS, NAME) \ + STORAGECLASS gl_once_t NAME = { 0, DEFAULTMUTEX }; +# define glthread_once(ONCE_CONTROL, INITFUNCTION) \ + (thread_in_use () \ + ? glthread_once_multithreaded (ONCE_CONTROL, INITFUNCTION) \ + : (glthread_once_singlethreaded (ONCE_CONTROL) ? (INITFUNCTION (), 0) : 0)) +extern int glthread_once_multithreaded (gl_once_t *once_control, void (*initfunction) (void)); +extern int glthread_once_singlethreaded (gl_once_t *once_control); + +# ifdef __cplusplus +} +# endif + +#endif + +/* ========================================================================= */ + +#if USE_WINDOWS_THREADS + +# define WIN32_LEAN_AND_MEAN /* avoid including junk */ +# include + +# ifdef __cplusplus +extern "C" { +# endif + +/* We can use CRITICAL_SECTION directly, rather than the native Windows Event, + Mutex, Semaphore types, because + - we need only to synchronize inside a single process (address space), + not inter-process locking, + - we don't need to support trylock operations. (TryEnterCriticalSection + does not work on Windows 95/98/ME. Packages that need trylock usually + define their own mutex type.) */ + +/* There is no way to statically initialize a CRITICAL_SECTION. It needs + to be done lazily, once only. For this we need spinlocks. */ + +typedef struct { volatile int done; volatile long started; } gl_spinlock_t; + +/* -------------------------- gl_lock_t datatype -------------------------- */ + +typedef struct + { + gl_spinlock_t guard; /* protects the initialization */ + CRITICAL_SECTION lock; + } + gl_lock_t; +# define gl_lock_define(STORAGECLASS, NAME) \ + STORAGECLASS gl_lock_t NAME; +# define gl_lock_define_initialized(STORAGECLASS, NAME) \ + STORAGECLASS gl_lock_t NAME = gl_lock_initializer; +# define gl_lock_initializer \ + { { 0, -1 } } +# define glthread_lock_init(LOCK) \ + (glthread_lock_init_func (LOCK), 0) +# define glthread_lock_lock(LOCK) \ + glthread_lock_lock_func (LOCK) +# define glthread_lock_unlock(LOCK) \ + glthread_lock_unlock_func (LOCK) +# define glthread_lock_destroy(LOCK) \ + glthread_lock_destroy_func (LOCK) +extern void glthread_lock_init_func (gl_lock_t *lock); +extern int glthread_lock_lock_func (gl_lock_t *lock); +extern int glthread_lock_unlock_func (gl_lock_t *lock); +extern int glthread_lock_destroy_func (gl_lock_t *lock); + +/* ------------------------- gl_rwlock_t datatype ------------------------- */ + +/* It is impossible to implement read-write locks using plain locks, without + introducing an extra thread dedicated to managing read-write locks. + Therefore here we need to use the low-level Event type. */ + +typedef struct + { + HANDLE *array; /* array of waiting threads, each represented by an event */ + unsigned int count; /* number of waiting threads */ + unsigned int alloc; /* length of allocated array */ + unsigned int offset; /* index of first waiting thread in array */ + } + gl_carray_waitqueue_t; +typedef struct + { + gl_spinlock_t guard; /* protects the initialization */ + CRITICAL_SECTION lock; /* protects the remaining fields */ + gl_carray_waitqueue_t waiting_readers; /* waiting readers */ + gl_carray_waitqueue_t waiting_writers; /* waiting writers */ + int runcount; /* number of readers running, or -1 when a writer runs */ + } + gl_rwlock_t; +# define gl_rwlock_define(STORAGECLASS, NAME) \ + STORAGECLASS gl_rwlock_t NAME; +# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \ + STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer; +# define gl_rwlock_initializer \ + { { 0, -1 } } +# define glthread_rwlock_init(LOCK) \ + (glthread_rwlock_init_func (LOCK), 0) +# define glthread_rwlock_rdlock(LOCK) \ + glthread_rwlock_rdlock_func (LOCK) +# define glthread_rwlock_wrlock(LOCK) \ + glthread_rwlock_wrlock_func (LOCK) +# define glthread_rwlock_unlock(LOCK) \ + glthread_rwlock_unlock_func (LOCK) +# define glthread_rwlock_destroy(LOCK) \ + glthread_rwlock_destroy_func (LOCK) +extern void glthread_rwlock_init_func (gl_rwlock_t *lock); +extern int glthread_rwlock_rdlock_func (gl_rwlock_t *lock); +extern int glthread_rwlock_wrlock_func (gl_rwlock_t *lock); +extern int glthread_rwlock_unlock_func (gl_rwlock_t *lock); +extern int glthread_rwlock_destroy_func (gl_rwlock_t *lock); + +/* --------------------- gl_recursive_lock_t datatype --------------------- */ + +/* The native Windows documentation says that CRITICAL_SECTION already + implements a recursive lock. But we need not rely on it: It's easy to + implement a recursive lock without this assumption. */ + +typedef struct + { + gl_spinlock_t guard; /* protects the initialization */ + DWORD owner; + unsigned long depth; + CRITICAL_SECTION lock; + } + gl_recursive_lock_t; +# define gl_recursive_lock_define(STORAGECLASS, NAME) \ + STORAGECLASS gl_recursive_lock_t NAME; +# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \ + STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer; +# define gl_recursive_lock_initializer \ + { { 0, -1 }, 0, 0 } +# define glthread_recursive_lock_init(LOCK) \ + (glthread_recursive_lock_init_func (LOCK), 0) +# define glthread_recursive_lock_lock(LOCK) \ + glthread_recursive_lock_lock_func (LOCK) +# define glthread_recursive_lock_unlock(LOCK) \ + glthread_recursive_lock_unlock_func (LOCK) +# define glthread_recursive_lock_destroy(LOCK) \ + glthread_recursive_lock_destroy_func (LOCK) +extern void glthread_recursive_lock_init_func (gl_recursive_lock_t *lock); +extern int glthread_recursive_lock_lock_func (gl_recursive_lock_t *lock); +extern int glthread_recursive_lock_unlock_func (gl_recursive_lock_t *lock); +extern int glthread_recursive_lock_destroy_func (gl_recursive_lock_t *lock); + +/* -------------------------- gl_once_t datatype -------------------------- */ + +typedef struct + { + volatile int inited; + volatile long started; + CRITICAL_SECTION lock; + } + gl_once_t; +# define gl_once_define(STORAGECLASS, NAME) \ + STORAGECLASS gl_once_t NAME = { -1, -1 }; +# define glthread_once(ONCE_CONTROL, INITFUNCTION) \ + (glthread_once_func (ONCE_CONTROL, INITFUNCTION), 0) +extern void glthread_once_func (gl_once_t *once_control, void (*initfunction) (void)); + +# ifdef __cplusplus +} +# endif + +#endif + +/* ========================================================================= */ + +#if !(USE_POSIX_THREADS || USE_PTH_THREADS || USE_SOLARIS_THREADS || USE_WINDOWS_THREADS) + +/* Provide dummy implementation if threads are not supported. */ + +/* -------------------------- gl_lock_t datatype -------------------------- */ + +typedef int gl_lock_t; +# define gl_lock_define(STORAGECLASS, NAME) +# define gl_lock_define_initialized(STORAGECLASS, NAME) +# define glthread_lock_init(NAME) 0 +# define glthread_lock_lock(NAME) 0 +# define glthread_lock_unlock(NAME) 0 +# define glthread_lock_destroy(NAME) 0 + +/* ------------------------- gl_rwlock_t datatype ------------------------- */ + +typedef int gl_rwlock_t; +# define gl_rwlock_define(STORAGECLASS, NAME) +# define gl_rwlock_define_initialized(STORAGECLASS, NAME) +# define glthread_rwlock_init(NAME) 0 +# define glthread_rwlock_rdlock(NAME) 0 +# define glthread_rwlock_wrlock(NAME) 0 +# define glthread_rwlock_unlock(NAME) 0 +# define glthread_rwlock_destroy(NAME) 0 + +/* --------------------- gl_recursive_lock_t datatype --------------------- */ + +typedef int gl_recursive_lock_t; +# define gl_recursive_lock_define(STORAGECLASS, NAME) +# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) +# define glthread_recursive_lock_init(NAME) 0 +# define glthread_recursive_lock_lock(NAME) 0 +# define glthread_recursive_lock_unlock(NAME) 0 +# define glthread_recursive_lock_destroy(NAME) 0 + +/* -------------------------- gl_once_t datatype -------------------------- */ + +typedef int gl_once_t; +# define gl_once_define(STORAGECLASS, NAME) \ + STORAGECLASS gl_once_t NAME = 0; +# define glthread_once(ONCE_CONTROL, INITFUNCTION) \ + (*(ONCE_CONTROL) == 0 ? (*(ONCE_CONTROL) = ~ 0, INITFUNCTION (), 0) : 0) + +#endif + +/* ========================================================================= */ + +/* Macros with built-in error handling. */ + +/* -------------------------- gl_lock_t datatype -------------------------- */ + +#define gl_lock_init(NAME) \ + do \ + { \ + if (glthread_lock_init (&NAME)) \ + abort (); \ + } \ + while (0) +#define gl_lock_lock(NAME) \ + do \ + { \ + if (glthread_lock_lock (&NAME)) \ + abort (); \ + } \ + while (0) +#define gl_lock_unlock(NAME) \ + do \ + { \ + if (glthread_lock_unlock (&NAME)) \ + abort (); \ + } \ + while (0) +#define gl_lock_destroy(NAME) \ + do \ + { \ + if (glthread_lock_destroy (&NAME)) \ + abort (); \ + } \ + while (0) + +/* ------------------------- gl_rwlock_t datatype ------------------------- */ + +#define gl_rwlock_init(NAME) \ + do \ + { \ + if (glthread_rwlock_init (&NAME)) \ + abort (); \ + } \ + while (0) +#define gl_rwlock_rdlock(NAME) \ + do \ + { \ + if (glthread_rwlock_rdlock (&NAME)) \ + abort (); \ + } \ + while (0) +#define gl_rwlock_wrlock(NAME) \ + do \ + { \ + if (glthread_rwlock_wrlock (&NAME)) \ + abort (); \ + } \ + while (0) +#define gl_rwlock_unlock(NAME) \ + do \ + { \ + if (glthread_rwlock_unlock (&NAME)) \ + abort (); \ + } \ + while (0) +#define gl_rwlock_destroy(NAME) \ + do \ + { \ + if (glthread_rwlock_destroy (&NAME)) \ + abort (); \ + } \ + while (0) + +/* --------------------- gl_recursive_lock_t datatype --------------------- */ + +#define gl_recursive_lock_init(NAME) \ + do \ + { \ + if (glthread_recursive_lock_init (&NAME)) \ + abort (); \ + } \ + while (0) +#define gl_recursive_lock_lock(NAME) \ + do \ + { \ + if (glthread_recursive_lock_lock (&NAME)) \ + abort (); \ + } \ + while (0) +#define gl_recursive_lock_unlock(NAME) \ + do \ + { \ + if (glthread_recursive_lock_unlock (&NAME)) \ + abort (); \ + } \ + while (0) +#define gl_recursive_lock_destroy(NAME) \ + do \ + { \ + if (glthread_recursive_lock_destroy (&NAME)) \ + abort (); \ + } \ + while (0) + +/* -------------------------- gl_once_t datatype -------------------------- */ + +#define gl_once(NAME, INITFUNCTION) \ + do \ + { \ + if (glthread_once (&NAME, INITFUNCTION)) \ + abort (); \ + } \ + while (0) + +/* ========================================================================= */ + +#endif /* _LOCK_H */ diff --git a/gettext-tools/gnulib-lib/glthread/threadlib.c b/gettext-tools/gnulib-lib/glthread/threadlib.c new file mode 100644 index 0000000..26870de --- /dev/null +++ b/gettext-tools/gnulib-lib/glthread/threadlib.c @@ -0,0 +1,73 @@ +/* Multithreading primitives. + Copyright (C) 2005-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . */ + +/* Written by Bruno Haible , 2005. */ + +#include + +/* ========================================================================= */ + +#if USE_POSIX_THREADS + +/* Use the POSIX threads library. */ + +# include +# include + +# if PTHREAD_IN_USE_DETECTION_HARD + +/* The function to be executed by a dummy thread. */ +static void * +dummy_thread_func (void *arg) +{ + return arg; +} + +int +glthread_in_use (void) +{ + static int tested; + static int result; /* 1: linked with -lpthread, 0: only with libc */ + + if (!tested) + { + pthread_t thread; + + if (pthread_create (&thread, NULL, dummy_thread_func, NULL) != 0) + /* Thread creation failed. */ + result = 0; + else + { + /* Thread creation works. */ + void *retval; + if (pthread_join (thread, &retval) != 0) + abort (); + result = 1; + } + tested = 1; + } + return result; +} + +# endif + +#endif + +/* ========================================================================= */ + +/* This declaration is solely to ensure that after preprocessing + this file is never empty. */ +typedef int dummy; diff --git a/gettext-tools/gnulib-lib/glthread/tls.c b/gettext-tools/gnulib-lib/glthread/tls.c new file mode 100644 index 0000000..971c72a --- /dev/null +++ b/gettext-tools/gnulib-lib/glthread/tls.c @@ -0,0 +1,61 @@ +/* Thread-local storage in multithreaded situations. + Copyright (C) 2005-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Written by Bruno Haible , 2005. */ + +#include + +#include "glthread/tls.h" + +/* ========================================================================= */ + +#if USE_POSIX_THREADS + +#endif + +/* ========================================================================= */ + +#if USE_PTH_THREADS + +#endif + +/* ========================================================================= */ + +#if USE_SOLARIS_THREADS + +/* Use the old Solaris threads library. */ + +/* ------------------------- gl_tls_key_t datatype ------------------------- */ + +void * +glthread_tls_get_multithreaded (thread_key_t key) +{ + void *value; + + if (thr_getspecific (key, &value) != 0) + abort (); + return value; +} + +#endif + +/* ========================================================================= */ + +#if USE_WINDOWS_THREADS + +#endif + +/* ========================================================================= */ diff --git a/gettext-tools/gnulib-lib/glthread/tls.h b/gettext-tools/gnulib-lib/glthread/tls.h new file mode 100644 index 0000000..c0a56e4 --- /dev/null +++ b/gettext-tools/gnulib-lib/glthread/tls.h @@ -0,0 +1,299 @@ +/* Thread-local storage in multithreaded situations. + Copyright (C) 2005, 2007-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Written by Bruno Haible , 2005. */ + +/* This file contains thread-local storage primitives for use with a given + thread library. It does not contain primitives for creating threads or + for other multithreading primitives. + + Type: gl_tls_key_t + Initialization: gl_tls_key_init (name, destructor); + Getting per-thread value: gl_tls_get (name) + Setting per-thread value: gl_tls_set (name, pointer); + De-initialization: gl_tls_key_destroy (name); + Equivalent functions with control of error handling: + Initialization: err = glthread_tls_key_init (&name, destructor); + Setting per-thread value: err = glthread_tls_set (&name, pointer); + De-initialization: err = glthread_tls_key_destroy (&name); + + A per-thread value is of type 'void *'. + + A destructor is a function pointer of type 'void (*) (void *)', called + when a thread exits, and taking the last per-thread value as argument. It + is unspecified whether the destructor function is called when the last + per-thread value is NULL. On some platforms, the destructor function is + not called at all. +*/ + + +#ifndef _TLS_H +#define _TLS_H + +#include +#include + +/* ========================================================================= */ + +#if USE_POSIX_THREADS + +/* Use the POSIX threads library. */ + +# include + +# if PTHREAD_IN_USE_DETECTION_HARD + +/* The pthread_in_use() detection needs to be done at runtime. */ +# define pthread_in_use() \ + glthread_in_use () +extern int glthread_in_use (void); + +# endif + +# if USE_POSIX_THREADS_WEAK + +/* Use weak references to the POSIX threads library. */ + +# pragma weak pthread_key_create +# pragma weak pthread_getspecific +# pragma weak pthread_setspecific +# pragma weak pthread_key_delete +# ifndef pthread_self +# pragma weak pthread_self +# endif + +# if !PTHREAD_IN_USE_DETECTION_HARD +# pragma weak pthread_cancel +# define pthread_in_use() (pthread_cancel != NULL) +# endif + +# else + +# if !PTHREAD_IN_USE_DETECTION_HARD +# define pthread_in_use() 1 +# endif + +# endif + +/* ------------------------- gl_tls_key_t datatype ------------------------- */ + +typedef union + { + void *singlethread_value; + pthread_key_t key; + } + gl_tls_key_t; +# define glthread_tls_key_init(KEY, DESTRUCTOR) \ + (pthread_in_use () \ + ? pthread_key_create (&(KEY)->key, DESTRUCTOR) \ + : ((KEY)->singlethread_value = NULL, 0)) +# define gl_tls_get(NAME) \ + (pthread_in_use () \ + ? pthread_getspecific ((NAME).key) \ + : (NAME).singlethread_value) +# define glthread_tls_set(KEY, POINTER) \ + (pthread_in_use () \ + ? pthread_setspecific ((KEY)->key, (POINTER)) \ + : ((KEY)->singlethread_value = (POINTER), 0)) +# define glthread_tls_key_destroy(KEY) \ + (pthread_in_use () ? pthread_key_delete ((KEY)->key) : 0) + +#endif + +/* ========================================================================= */ + +#if USE_PTH_THREADS + +/* Use the GNU Pth threads library. */ + +# include + +# if USE_PTH_THREADS_WEAK + +/* Use weak references to the GNU Pth threads library. */ + +# pragma weak pth_key_create +# pragma weak pth_key_getdata +# pragma weak pth_key_setdata +# pragma weak pth_key_delete + +# pragma weak pth_cancel +# define pth_in_use() (pth_cancel != NULL) + +# else + +# define pth_in_use() 1 + +# endif + +/* ------------------------- gl_tls_key_t datatype ------------------------- */ + +typedef union + { + void *singlethread_value; + pth_key_t key; + } + gl_tls_key_t; +# define glthread_tls_key_init(KEY, DESTRUCTOR) \ + (pth_in_use () \ + ? (!pth_key_create (&(KEY)->key, DESTRUCTOR) ? errno : 0) \ + : ((KEY)->singlethread_value = NULL, 0)) +# define gl_tls_get(NAME) \ + (pth_in_use () \ + ? pth_key_getdata ((NAME).key) \ + : (NAME).singlethread_value) +# define glthread_tls_set(KEY, POINTER) \ + (pth_in_use () \ + ? (!pth_key_setdata ((KEY)->key, (POINTER)) ? errno : 0) \ + : ((KEY)->singlethread_value = (POINTER), 0)) +# define glthread_tls_key_destroy(KEY) \ + (pth_in_use () \ + ? (!pth_key_delete ((KEY)->key) ? errno : 0) \ + : 0) + +#endif + +/* ========================================================================= */ + +#if USE_SOLARIS_THREADS + +/* Use the old Solaris threads library. */ + +# include + +# if USE_SOLARIS_THREADS_WEAK + +/* Use weak references to the old Solaris threads library. */ + +# pragma weak thr_keycreate +# pragma weak thr_getspecific +# pragma weak thr_setspecific + +# pragma weak thr_suspend +# define thread_in_use() (thr_suspend != NULL) + +# else + +# define thread_in_use() 1 + +# endif + +/* ------------------------- gl_tls_key_t datatype ------------------------- */ + +typedef union + { + void *singlethread_value; + thread_key_t key; + } + gl_tls_key_t; +# define glthread_tls_key_init(KEY, DESTRUCTOR) \ + (thread_in_use () \ + ? thr_keycreate (&(KEY)->key, DESTRUCTOR) \ + : ((KEY)->singlethread_value = NULL, 0)) +# define gl_tls_get(NAME) \ + (thread_in_use () \ + ? glthread_tls_get_multithreaded ((NAME).key) \ + : (NAME).singlethread_value) +extern void *glthread_tls_get_multithreaded (thread_key_t key); +# define glthread_tls_set(KEY, POINTER) \ + (thread_in_use () \ + ? thr_setspecific ((KEY)->key, (POINTER)) \ + : ((KEY)->singlethread_value = (POINTER), 0)) +# define glthread_tls_key_destroy(KEY) \ + /* Unsupported. */ \ + 0 + +#endif + +/* ========================================================================= */ + +#if USE_WINDOWS_THREADS + +# define WIN32_LEAN_AND_MEAN /* avoid including junk */ +# include + +/* ------------------------- gl_tls_key_t datatype ------------------------- */ + +typedef DWORD gl_tls_key_t; +# define glthread_tls_key_init(KEY, DESTRUCTOR) \ + /* The destructor is unsupported. */ \ + ((*(KEY) = TlsAlloc ()) == (DWORD)-1 ? EAGAIN : ((void) (DESTRUCTOR), 0)) +# define gl_tls_get(NAME) \ + TlsGetValue (NAME) +# define glthread_tls_set(KEY, POINTER) \ + (!TlsSetValue (*(KEY), POINTER) ? EINVAL : 0) +# define glthread_tls_key_destroy(KEY) \ + (!TlsFree (*(KEY)) ? EINVAL : 0) + +#endif + +/* ========================================================================= */ + +#if !(USE_POSIX_THREADS || USE_PTH_THREADS || USE_SOLARIS_THREADS || USE_WINDOWS_THREADS) + +/* Provide dummy implementation if threads are not supported. */ + +/* ------------------------- gl_tls_key_t datatype ------------------------- */ + +typedef struct + { + void *singlethread_value; + } + gl_tls_key_t; +# define glthread_tls_key_init(KEY, DESTRUCTOR) \ + ((KEY)->singlethread_value = NULL, \ + (void) (DESTRUCTOR), \ + 0) +# define gl_tls_get(NAME) \ + (NAME).singlethread_value +# define glthread_tls_set(KEY, POINTER) \ + ((KEY)->singlethread_value = (POINTER), 0) +# define glthread_tls_key_destroy(KEY) \ + 0 + +#endif + +/* ========================================================================= */ + +/* Macros with built-in error handling. */ + +/* ------------------------- gl_tls_key_t datatype ------------------------- */ + +#define gl_tls_key_init(NAME, DESTRUCTOR) \ + do \ + { \ + if (glthread_tls_key_init (&NAME, DESTRUCTOR)) \ + abort (); \ + } \ + while (0) +#define gl_tls_set(NAME, POINTER) \ + do \ + { \ + if (glthread_tls_set (&NAME, POINTER)) \ + abort (); \ + } \ + while (0) +#define gl_tls_key_destroy(NAME) \ + do \ + { \ + if (glthread_tls_key_destroy (&NAME)) \ + abort (); \ + } \ + while (0) + +/* ========================================================================= */ + +#endif /* _TLS_H */ diff --git a/gettext-tools/gnulib-lib/hash.c b/gettext-tools/gnulib-lib/hash.c new file mode 100644 index 0000000..1844724 --- /dev/null +++ b/gettext-tools/gnulib-lib/hash.c @@ -0,0 +1,383 @@ +/* hash - implement simple hashing table with string based keys. + Copyright (C) 1994-1995, 2000-2006 Free Software Foundation, Inc. + Written by Ulrich Drepper , October 1994. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include "hash.h" + +#include +#include +#include +#include +#include + +/* Since this simple implementation of hash tables allows only insertion, no + removal of entries, the right data structure for the memory holding all keys + is an obstack. */ +#include "obstack.h" + +/* Use checked memory allocation. */ +#include "xalloc.h" + +#define obstack_chunk_alloc xmalloc +#define obstack_chunk_free free + + +typedef struct hash_entry +{ + unsigned long used; /* Hash code of the key, or 0 for an unused entry. */ + const void *key; /* Key. */ + size_t keylen; + void *data; /* Value. */ + struct hash_entry *next; +} +hash_entry; + + +/* Given an odd CANDIDATE > 1, return true if it is a prime number. */ +static int +is_prime (unsigned long int candidate) +{ + /* No even number and none less than 10 will be passed here. */ + unsigned long int divn = 3; + unsigned long int sq = divn * divn; + + while (sq < candidate && candidate % divn != 0) + { + ++divn; + sq += 4 * divn; + ++divn; + } + + return candidate % divn != 0; +} + + +/* Given SEED > 1, return the smallest odd prime number >= SEED. */ +unsigned long +next_prime (unsigned long int seed) +{ + /* Make it definitely odd. */ + seed |= 1; + + while (!is_prime (seed)) + seed += 2; + + return seed; +} + + +/* Initialize a hash table. INIT_SIZE > 1 is the initial number of available + entries. + Return 0 upon successful completion, -1 upon memory allocation error. */ +int +hash_init (hash_table *htab, unsigned long int init_size) +{ + /* We need the size to be a prime. */ + init_size = next_prime (init_size); + + /* Initialize the data structure. */ + htab->size = init_size; + htab->filled = 0; + htab->first = NULL; + htab->table = XCALLOC (init_size + 1, hash_entry); + + obstack_init (&htab->mem_pool); + + return 0; +} + + +/* Delete a hash table's contents. + Return 0 always. */ +int +hash_destroy (hash_table *htab) +{ + free (htab->table); + obstack_free (&htab->mem_pool, NULL); + return 0; +} + + +/* Compute a hash code for a key consisting of KEYLEN bytes starting at KEY + in memory. */ +static unsigned long +compute_hashval (const void *key, size_t keylen) +{ + size_t cnt; + unsigned long int hval; + + /* Compute the hash value for the given string. The algorithm + is taken from [Aho,Sethi,Ullman], fixed according to + http://www.haible.de/bruno/hashfunc.html. */ + cnt = 0; + hval = keylen; + while (cnt < keylen) + { + hval = (hval << 9) | (hval >> (sizeof (unsigned long) * CHAR_BIT - 9)); + hval += (unsigned long int) *(((const char *) key) + cnt++); + } + return hval != 0 ? hval : ~((unsigned long) 0); +} + + +/* References: + [Aho,Sethi,Ullman] Compilers: Principles, Techniques and Tools, 1986 + [Knuth] The Art of Computer Programming, part3 (6.4) */ + +/* Look up a given key in the hash table. + Return the index of the entry, if present, or otherwise the index a free + entry where it could be inserted. */ +static size_t +lookup (hash_table *htab, + const void *key, size_t keylen, + unsigned long int hval) +{ + unsigned long int hash; + size_t idx; + hash_entry *table = htab->table; + + /* First hash function: simply take the modul but prevent zero. */ + hash = 1 + hval % htab->size; + + idx = hash; + + if (table[idx].used) + { + if (table[idx].used == hval && table[idx].keylen == keylen + && memcmp (table[idx].key, key, keylen) == 0) + return idx; + + /* Second hash function as suggested in [Knuth]. */ + hash = 1 + hval % (htab->size - 2); + + do + { + if (idx <= hash) + idx = htab->size + idx - hash; + else + idx -= hash; + + /* If entry is found use it. */ + if (table[idx].used == hval && table[idx].keylen == keylen + && memcmp (table[idx].key, key, keylen) == 0) + return idx; + } + while (table[idx].used); + } + return idx; +} + + +/* Look up the value of a key in the given table. + If found, return 0 and set *RESULT to it. Otherwise return -1. */ +int +hash_find_entry (hash_table *htab, const void *key, size_t keylen, + void **result) +{ + hash_entry *table = htab->table; + size_t idx = lookup (htab, key, keylen, compute_hashval (key, keylen)); + + if (table[idx].used == 0) + return -1; + + *result = table[idx].data; + return 0; +} + + +/* Insert the pair (KEY[0..KEYLEN-1], DATA) in the hash table at index IDX. + HVAL is the key's hash code. IDX depends on it. The table entry at index + IDX is known to be unused. */ +static void +insert_entry_2 (hash_table *htab, + const void *key, size_t keylen, + unsigned long int hval, size_t idx, void *data) +{ + hash_entry *table = htab->table; + + table[idx].used = hval; + table[idx].key = key; + table[idx].keylen = keylen; + table[idx].data = data; + + /* List the new value in the list. */ + if (htab->first == NULL) + { + table[idx].next = &table[idx]; + htab->first = &table[idx]; + } + else + { + table[idx].next = htab->first->next; + htab->first->next = &table[idx]; + htab->first = &table[idx]; + } + + ++htab->filled; +} + + +/* Grow the hash table. */ +static void +resize (hash_table *htab) +{ + unsigned long int old_size = htab->size; + hash_entry *table = htab->table; + size_t idx; + + htab->size = next_prime (htab->size * 2); + htab->filled = 0; + htab->first = NULL; + htab->table = XCALLOC (1 + htab->size, hash_entry); + + for (idx = 1; idx <= old_size; ++idx) + if (table[idx].used) + insert_entry_2 (htab, table[idx].key, table[idx].keylen, + table[idx].used, + lookup (htab, table[idx].key, table[idx].keylen, + table[idx].used), + table[idx].data); + + free (table); +} + + +/* Try to insert the pair (KEY[0..KEYLEN-1], DATA) in the hash table. + Return non-NULL (more precisely, the address of the KEY inside the table's + memory pool) if successful, or NULL if there is already an entry with the + given key. */ +const void * +hash_insert_entry (hash_table *htab, + const void *key, size_t keylen, + void *data) +{ + unsigned long int hval = compute_hashval (key, keylen); + hash_entry *table = htab->table; + size_t idx = lookup (htab, key, keylen, hval); + + if (table[idx].used) + /* We don't want to overwrite the old value. */ + return NULL; + else + { + /* An empty bucket has been found. */ + void *keycopy = obstack_copy (&htab->mem_pool, key, keylen); + insert_entry_2 (htab, keycopy, keylen, hval, idx, data); + if (100 * htab->filled > 75 * htab->size) + /* Table is filled more than 75%. Resize the table. */ + resize (htab); + return keycopy; + } +} + + +/* Insert the pair (KEY[0..KEYLEN-1], DATA) in the hash table. + Return 0. */ +int +hash_set_value (hash_table *htab, + const void *key, size_t keylen, + void *data) +{ + unsigned long int hval = compute_hashval (key, keylen); + hash_entry *table = htab->table; + size_t idx = lookup (htab, key, keylen, hval); + + if (table[idx].used) + { + /* Overwrite the old value. */ + table[idx].data = data; + return 0; + } + else + { + /* An empty bucket has been found. */ + void *keycopy = obstack_copy (&htab->mem_pool, key, keylen); + insert_entry_2 (htab, keycopy, keylen, hval, idx, data); + if (100 * htab->filled > 75 * htab->size) + /* Table is filled more than 75%. Resize the table. */ + resize (htab); + return 0; + } +} + + +/* Steps *PTR forward to the next used entry in the given hash table. *PTR + should be initially set to NULL. Store information about the next entry + in *KEY, *KEYLEN, *DATA. + Return 0 normally, -1 when the whole hash table has been traversed. */ +int +hash_iterate (hash_table *htab, void **ptr, const void **key, size_t *keylen, + void **data) +{ + hash_entry *curr; + + if (*ptr == NULL) + { + if (htab->first == NULL) + return -1; + curr = htab->first; + } + else + { + if (*ptr == htab->first) + return -1; + curr = (hash_entry *) *ptr; + } + curr = curr->next; + *ptr = (void *) curr; + + *key = curr->key; + *keylen = curr->keylen; + *data = curr->data; + return 0; +} + + +/* Steps *PTR forward to the next used entry in the given hash table. *PTR + should be initially set to NULL. Store information about the next entry + in *KEY, *KEYLEN, *DATAP. *DATAP is set to point to the storage of the + value; modifying **DATAP will modify the value of the entry. + Return 0 normally, -1 when the whole hash table has been traversed. */ +int +hash_iterate_modify (hash_table *htab, void **ptr, + const void **key, size_t *keylen, + void ***datap) +{ + hash_entry *curr; + + if (*ptr == NULL) + { + if (htab->first == NULL) + return -1; + curr = htab->first; + } + else + { + if (*ptr == htab->first) + return -1; + curr = (hash_entry *) *ptr; + } + curr = curr->next; + *ptr = (void *) curr; + + *key = curr->key; + *keylen = curr->keylen; + *datap = &curr->data; + return 0; +} diff --git a/gettext-tools/gnulib-lib/hash.h b/gettext-tools/gnulib-lib/hash.h new file mode 100644 index 0000000..a56ad77 --- /dev/null +++ b/gettext-tools/gnulib-lib/hash.h @@ -0,0 +1,90 @@ +/* Copyright (C) 1995, 2000-2003, 2005-2006 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _HASH_H +#define _HASH_H + +#include "obstack.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct hash_entry; + +typedef struct hash_table +{ + unsigned long int size; /* Number of allocated entries. */ + unsigned long int filled; /* Number of used entries. */ + struct hash_entry *first; /* Pointer to head of list of entries. */ + struct hash_entry *table; /* Pointer to array of entries. */ + struct obstack mem_pool; /* Memory pool holding the keys. */ +} +hash_table; + +/* Initialize a hash table. INIT_SIZE > 1 is the initial number of available + entries. + Return 0 upon successful completion, -1 upon memory allocation error. */ +extern int hash_init (hash_table *htab, unsigned long int init_size); + +/* Delete a hash table's contents. + Return 0 always. */ +extern int hash_destroy (hash_table *htab); + +/* Look up the value of a key in the given table. + If found, return 0 and set *RESULT to it. Otherwise return -1. */ +extern int hash_find_entry (hash_table *htab, + const void *key, size_t keylen, + void **result); + +/* Try to insert the pair (KEY[0..KEYLEN-1], DATA) in the hash table. + Return non-NULL (more precisely, the address of the KEY inside the table's + memory pool) if successful, or NULL if there is already an entry with the + given key. */ +extern const void * hash_insert_entry (hash_table *htab, + const void *key, size_t keylen, + void *data); + +/* Insert the pair (KEY[0..KEYLEN-1], DATA) in the hash table. + Return 0. */ +extern int hash_set_value (hash_table *htab, + const void *key, size_t keylen, + void *data); + +/* Steps *PTR forward to the next used entry in the given hash table. *PTR + should be initially set to NULL. Store information about the next entry + in *KEY, *KEYLEN, *DATA. + Return 0 normally, -1 when the whole hash table has been traversed. */ +extern int hash_iterate (hash_table *htab, void **ptr, + const void **key, size_t *keylen, + void **data); + +/* Steps *PTR forward to the next used entry in the given hash table. *PTR + should be initially set to NULL. Store information about the next entry + in *KEY, *KEYLEN, *DATAP. *DATAP is set to point to the storage of the + value; modifying **DATAP will modify the value of the entry. + Return 0 normally, -1 when the whole hash table has been traversed. */ +extern int hash_iterate_modify (hash_table *htab, void **ptr, + const void **key, size_t *keylen, + void ***datap); + +/* Given SEED > 1, return the smallest odd prime number >= SEED. */ +extern unsigned long int next_prime (unsigned long int seed); + +#ifdef __cplusplus +} +#endif + +#endif /* not _HASH_H */ diff --git a/gettext-tools/gnulib-lib/html-ostream.c b/gettext-tools/gnulib-lib/html-ostream.c new file mode 100644 index 0000000..fcee1ac --- /dev/null +++ b/gettext-tools/gnulib-lib/html-ostream.c @@ -0,0 +1,338 @@ +/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ + +#line 1 "html-ostream.oo.c" +/* Output stream that produces HTML output. + Copyright (C) 2006-2009 Free Software Foundation, Inc. + Written by Bruno Haible , 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include "html-ostream.h" + +#include +#include +#include + +#include "gl_xlist.h" +#include "gl_array_list.h" +#include "unistr.h" +#include "xalloc.h" + +#line 36 "html-ostream.c" +#if !IS_CPLUSPLUS +#define html_ostream_representation any_ostream_representation +#endif +#include "html_ostream.priv.h" + +const typeinfo_t html_ostream_typeinfo = { "html_ostream" }; + +static const typeinfo_t * const html_ostream_superclasses[] = + { html_ostream_SUPERCLASSES }; + +#define super ostream_vtable + +#line 48 "html-ostream.oo.c" + +/* Implementation of ostream_t methods. */ + +static void +emit_pending_spans (html_ostream_t stream, bool shrink_stack) +{ + if (stream->curr_class_stack_size > stream->last_class_stack_size) + { + size_t i; + + for (i = stream->last_class_stack_size; i < stream->curr_class_stack_size; i++) + { + char *classname = (char *) gl_list_get_at (stream->class_stack, i); + + ostream_write_str (stream->destination, "destination, classname); + ostream_write_str (stream->destination, "\">"); + } + stream->last_class_stack_size = stream->curr_class_stack_size; + } + else if (stream->curr_class_stack_size < stream->last_class_stack_size) + { + size_t i = stream->last_class_stack_size; + + while (i > stream->curr_class_stack_size) + { + char *classname; + + --i; + classname = (char *) gl_list_get_at (stream->class_stack, i); + ostream_write_str (stream->destination, ""); + if (shrink_stack) + { + gl_list_remove_at (stream->class_stack, i); + free (classname); + } + } + stream->last_class_stack_size = stream->curr_class_stack_size; + } +} + +static void +html_ostream__write_mem (html_ostream_t stream, const void *data, size_t len) +{ + if (len > 0) + { + #define BUFFERSIZE 2048 + char inbuffer[BUFFERSIZE]; + size_t inbufcount; + + inbufcount = stream->buflen; + if (inbufcount > 0) + memcpy (inbuffer, stream->buf, inbufcount); + for (;;) + { + /* At this point, inbuffer[0..inbufcount-1] is filled. */ + { + /* Combine the previous rest with a chunk of new input. */ + size_t n = + (len <= BUFFERSIZE - inbufcount ? len : BUFFERSIZE - inbufcount); + + if (n > 0) + { + memcpy (inbuffer + inbufcount, data, n); + data = (char *) data + n; + inbufcount += n; + len -= n; + } + } + { + /* Handle complete UTF-8 characters. */ + const char *inptr = inbuffer; + size_t insize = inbufcount; + + while (insize > 0) + { + unsigned char c0; + ucs4_t uc; + int nbytes; + + c0 = ((const unsigned char *) inptr)[0]; + if (insize < (c0 < 0xc0 ? 1 : c0 < 0xe0 ? 2 : c0 < 0xf0 ? 3 : + c0 < 0xf8 ? 4 : c0 < 0xfc ? 5 : 6)) + break; + + nbytes = u8_mbtouc (&uc, (const unsigned char *) inptr, insize); + + if (uc == '\n') + { + size_t prev_class_stack_size = stream->curr_class_stack_size; + stream->curr_class_stack_size = 0; + emit_pending_spans (stream, false); + ostream_write_str (stream->destination, "
"); + stream->curr_class_stack_size = prev_class_stack_size; + } + else + { + emit_pending_spans (stream, true); + + switch (uc) + { + case '"': + ostream_write_str (stream->destination, """); + break; + case '&': + ostream_write_str (stream->destination, "&"); + break; + case '<': + ostream_write_str (stream->destination, "<"); + break; + case '>': + /* Needed to avoid "]]>" in the output. */ + ostream_write_str (stream->destination, ">"); + break; + case ' ': + /* Needed because HTML viewers merge adjacent spaces + and drop spaces adjacent to
and similar. */ + ostream_write_str (stream->destination, " "); + break; + default: + if (uc >= 0x20 && uc < 0x7F) + { + /* Output ASCII characters as such. */ + char bytes[1]; + bytes[0] = uc; + ostream_write_mem (stream->destination, bytes, 1); + } + else + { + /* Output non-ASCII characters in #&nnn; + notation. */ + char bytes[32]; + sprintf (bytes, "&#%d;", (int) uc); + ostream_write_str (stream->destination, bytes); + } + break; + } + } + + inptr += nbytes; + insize -= nbytes; + } + /* Put back the unconverted part. */ + if (insize > BUFSIZE) + abort (); + if (len == 0) + { + if (insize > 0) + memcpy (stream->buf, inptr, insize); + stream->buflen = insize; + break; + } + if (insize > 0) + memmove (inbuffer, inptr, insize); + inbufcount = insize; + } + } + #undef BUFFERSIZE + } +} + +static void +html_ostream__flush (html_ostream_t stream) +{ + /* There's nothing to do here, since stream->buf[] contains only a few + bytes that don't correspond to a character, and it's not worth closing + the open spans. */ +} + +static void +html_ostream__free (html_ostream_t stream) +{ + stream->curr_class_stack_size = 0; + emit_pending_spans (stream, true); + gl_list_free (stream->class_stack); + free (stream); +} + +/* Implementation of html_ostream_t methods. */ + +static void +html_ostream__begin_span (html_ostream_t stream, const char *classname) +{ + if (stream->last_class_stack_size > stream->curr_class_stack_size + && strcmp ((char *) gl_list_get_at (stream->class_stack, + stream->curr_class_stack_size), + classname) != 0) + emit_pending_spans (stream, true); + /* Now either + last_class_stack_size <= curr_class_stack_size + - in this case we have to append the given CLASSNAME - + or + last_class_stack_size > curr_class_stack_size + && class_stack[curr_class_stack_size] == CLASSNAME + - in this case we only need to increment curr_class_stack_size. */ + if (stream->last_class_stack_size <= stream->curr_class_stack_size) + gl_list_add_at (stream->class_stack, stream->curr_class_stack_size, + xstrdup (classname)); + stream->curr_class_stack_size++; +} + +static void +html_ostream__end_span (html_ostream_t stream, const char *classname) +{ + if (!(stream->curr_class_stack_size > 0 + && strcmp ((char *) gl_list_get_at (stream->class_stack, + stream->curr_class_stack_size - 1), + classname) == 0)) + /* Improperly nested begin_span/end_span calls. */ + abort (); + stream->curr_class_stack_size--; +} + +/* Constructor. */ + +html_ostream_t +html_ostream_create (ostream_t destination) +{ + html_ostream_t stream = XMALLOC (struct html_ostream_representation); + + stream->base.vtable = &html_ostream_vtable; + stream->destination = destination; + stream->class_stack = + gl_list_create_empty (GL_ARRAY_LIST, NULL, NULL, NULL, true); + stream->curr_class_stack_size = 0; + stream->last_class_stack_size = 0; + stream->buflen = 0; + + return stream; +} + +#line 281 "html-ostream.c" + +const struct html_ostream_implementation html_ostream_vtable = +{ + html_ostream_superclasses, + sizeof (html_ostream_superclasses) / sizeof (html_ostream_superclasses[0]), + sizeof (struct html_ostream_representation), + html_ostream__write_mem, + html_ostream__flush, + html_ostream__free, + html_ostream__begin_span, + html_ostream__end_span, +}; + +#if !HAVE_INLINE + +/* Define the functions that invoke the methods. */ + +void +html_ostream_write_mem (html_ostream_t first_arg, const void *data, size_t len) +{ + const struct html_ostream_implementation *vtable = + ((struct html_ostream_representation_header *) (struct html_ostream_representation *) first_arg)->vtable; + vtable->write_mem (first_arg,data,len); +} + +void +html_ostream_flush (html_ostream_t first_arg) +{ + const struct html_ostream_implementation *vtable = + ((struct html_ostream_representation_header *) (struct html_ostream_representation *) first_arg)->vtable; + vtable->flush (first_arg); +} + +void +html_ostream_free (html_ostream_t first_arg) +{ + const struct html_ostream_implementation *vtable = + ((struct html_ostream_representation_header *) (struct html_ostream_representation *) first_arg)->vtable; + vtable->free (first_arg); +} + +void +html_ostream_begin_span (html_ostream_t first_arg, const char *classname) +{ + const struct html_ostream_implementation *vtable = + ((struct html_ostream_representation_header *) (struct html_ostream_representation *) first_arg)->vtable; + vtable->begin_span (first_arg,classname); +} + +void +html_ostream_end_span (html_ostream_t first_arg, const char *classname) +{ + const struct html_ostream_implementation *vtable = + ((struct html_ostream_representation_header *) (struct html_ostream_representation *) first_arg)->vtable; + vtable->end_span (first_arg,classname); +} + +#endif diff --git a/gettext-tools/gnulib-lib/html-ostream.h b/gettext-tools/gnulib-lib/html-ostream.h new file mode 100644 index 0000000..9871dd3 --- /dev/null +++ b/gettext-tools/gnulib-lib/html-ostream.h @@ -0,0 +1,158 @@ +/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ + +#line 1 "html-ostream.oo.h" +/* Output stream that produces HTML output. + Copyright (C) 2006 Free Software Foundation, Inc. + Written by Bruno Haible , 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _HTML_OSTREAM_H +#define _HTML_OSTREAM_H + +#include "ostream.h" + + +#line 28 "html-ostream.h" +struct html_ostream_representation; +/* html_ostream_t is defined as a pointer to struct html_ostream_representation. + In C++ mode, we use a smart pointer class. + In C mode, we have no other choice than a typedef to the root class type. */ +#if IS_CPLUSPLUS +struct html_ostream_t +{ +private: + struct html_ostream_representation *_pointer; +public: + html_ostream_t () : _pointer (NULL) {} + html_ostream_t (struct html_ostream_representation *pointer) : _pointer (pointer) {} + struct html_ostream_representation * operator -> () { return _pointer; } + operator struct html_ostream_representation * () { return _pointer; } + operator struct any_ostream_representation * () { return (struct any_ostream_representation *) _pointer; } + operator void * () { return _pointer; } + bool operator == (const void *p) { return _pointer == p; } + bool operator != (const void *p) { return _pointer != p; } + operator ostream_t () { return (ostream_t) (struct any_ostream_representation *) _pointer; } + explicit html_ostream_t (ostream_t x) : _pointer ((struct html_ostream_representation *) (void *) x) {} +}; +#else +typedef ostream_t html_ostream_t; +#endif + +/* Functions that invoke the methods. */ +extern void html_ostream_write_mem (html_ostream_t first_arg, const void *data, size_t len); +extern void html_ostream_flush (html_ostream_t first_arg); +extern void html_ostream_free (html_ostream_t first_arg); +extern void html_ostream_begin_span (html_ostream_t first_arg, const char *classname); +extern void html_ostream_end_span (html_ostream_t first_arg, const char *classname); + +/* Type representing an implementation of html_ostream_t. */ +struct html_ostream_implementation +{ + const typeinfo_t * const *superclasses; + size_t superclasses_length; + size_t instance_size; +#define THIS_ARG html_ostream_t first_arg +#include "html_ostream.vt.h" +#undef THIS_ARG +}; + +/* Public portion of the object pointed to by a html_ostream_t. */ +struct html_ostream_representation_header +{ + const struct html_ostream_implementation *vtable; +}; + +#if HAVE_INLINE + +/* Define the functions that invoke the methods as inline accesses to + the html_ostream_implementation. + Use #define to avoid a warning because of extern vs. static. */ + +# define html_ostream_write_mem html_ostream_write_mem_inline +static inline void +html_ostream_write_mem (html_ostream_t first_arg, const void *data, size_t len) +{ + const struct html_ostream_implementation *vtable = + ((struct html_ostream_representation_header *) (struct html_ostream_representation *) first_arg)->vtable; + vtable->write_mem (first_arg,data,len); +} + +# define html_ostream_flush html_ostream_flush_inline +static inline void +html_ostream_flush (html_ostream_t first_arg) +{ + const struct html_ostream_implementation *vtable = + ((struct html_ostream_representation_header *) (struct html_ostream_representation *) first_arg)->vtable; + vtable->flush (first_arg); +} + +# define html_ostream_free html_ostream_free_inline +static inline void +html_ostream_free (html_ostream_t first_arg) +{ + const struct html_ostream_implementation *vtable = + ((struct html_ostream_representation_header *) (struct html_ostream_representation *) first_arg)->vtable; + vtable->free (first_arg); +} + +# define html_ostream_begin_span html_ostream_begin_span_inline +static inline void +html_ostream_begin_span (html_ostream_t first_arg, const char *classname) +{ + const struct html_ostream_implementation *vtable = + ((struct html_ostream_representation_header *) (struct html_ostream_representation *) first_arg)->vtable; + vtable->begin_span (first_arg,classname); +} + +# define html_ostream_end_span html_ostream_end_span_inline +static inline void +html_ostream_end_span (html_ostream_t first_arg, const char *classname) +{ + const struct html_ostream_implementation *vtable = + ((struct html_ostream_representation_header *) (struct html_ostream_representation *) first_arg)->vtable; + vtable->end_span (first_arg,classname); +} + +#endif + +extern const typeinfo_t html_ostream_typeinfo; +#define html_ostream_SUPERCLASSES &html_ostream_typeinfo, ostream_SUPERCLASSES +#define html_ostream_SUPERCLASSES_LENGTH (1 + ostream_SUPERCLASSES_LENGTH) + +extern const struct html_ostream_implementation html_ostream_vtable; + +#line 37 "html-ostream.oo.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Create an output stream that takes input in the UTF-8 encoding and + writes it in HTML form on DESTINATION. + This stream produces a sequence of lines. The caller is responsible + for opening the elements before and for closing them after + the use of this stream. + Note that the resulting stream must be closed before DESTINATION can be + closed. */ +extern html_ostream_t html_ostream_create (ostream_t destination); + + +#ifdef __cplusplus +} +#endif + +#endif /* _HTML_OSTREAM_H */ diff --git a/gettext-tools/gnulib-lib/html-ostream.oo.c b/gettext-tools/gnulib-lib/html-ostream.oo.c new file mode 100644 index 0000000..bf5c130 --- /dev/null +++ b/gettext-tools/gnulib-lib/html-ostream.oo.c @@ -0,0 +1,277 @@ +/* Output stream that produces HTML output. + Copyright (C) 2006-2009 Free Software Foundation, Inc. + Written by Bruno Haible , 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include "html-ostream.h" + +#include +#include +#include + +#include "gl_xlist.h" +#include "gl_array_list.h" +#include "unistr.h" +#include "xalloc.h" + +struct html_ostream : struct ostream +{ +fields: + /* The destination stream. */ + ostream_t destination; + /* The stack of active CSS classes. */ + gl_list_t /* */ class_stack; + /* Current and last size of the active portion of this stack. Always + size(class_stack) == max(curr_class_stack_size,last_class_stack_size). */ + size_t curr_class_stack_size; + size_t last_class_stack_size; + /* Last few bytes that could not yet be converted. */ + #define BUFSIZE 6 + char buf[BUFSIZE]; + size_t buflen; +}; + +/* Implementation of ostream_t methods. */ + +static void +emit_pending_spans (html_ostream_t stream, bool shrink_stack) +{ + if (stream->curr_class_stack_size > stream->last_class_stack_size) + { + size_t i; + + for (i = stream->last_class_stack_size; i < stream->curr_class_stack_size; i++) + { + char *classname = (char *) gl_list_get_at (stream->class_stack, i); + + ostream_write_str (stream->destination, "destination, classname); + ostream_write_str (stream->destination, "\">"); + } + stream->last_class_stack_size = stream->curr_class_stack_size; + } + else if (stream->curr_class_stack_size < stream->last_class_stack_size) + { + size_t i = stream->last_class_stack_size; + + while (i > stream->curr_class_stack_size) + { + char *classname; + + --i; + classname = (char *) gl_list_get_at (stream->class_stack, i); + ostream_write_str (stream->destination, ""); + if (shrink_stack) + { + gl_list_remove_at (stream->class_stack, i); + free (classname); + } + } + stream->last_class_stack_size = stream->curr_class_stack_size; + } +} + +static void +html_ostream::write_mem (html_ostream_t stream, const void *data, size_t len) +{ + if (len > 0) + { + #define BUFFERSIZE 2048 + char inbuffer[BUFFERSIZE]; + size_t inbufcount; + + inbufcount = stream->buflen; + if (inbufcount > 0) + memcpy (inbuffer, stream->buf, inbufcount); + for (;;) + { + /* At this point, inbuffer[0..inbufcount-1] is filled. */ + { + /* Combine the previous rest with a chunk of new input. */ + size_t n = + (len <= BUFFERSIZE - inbufcount ? len : BUFFERSIZE - inbufcount); + + if (n > 0) + { + memcpy (inbuffer + inbufcount, data, n); + data = (char *) data + n; + inbufcount += n; + len -= n; + } + } + { + /* Handle complete UTF-8 characters. */ + const char *inptr = inbuffer; + size_t insize = inbufcount; + + while (insize > 0) + { + unsigned char c0; + ucs4_t uc; + int nbytes; + + c0 = ((const unsigned char *) inptr)[0]; + if (insize < (c0 < 0xc0 ? 1 : c0 < 0xe0 ? 2 : c0 < 0xf0 ? 3 : + c0 < 0xf8 ? 4 : c0 < 0xfc ? 5 : 6)) + break; + + nbytes = u8_mbtouc (&uc, (const unsigned char *) inptr, insize); + + if (uc == '\n') + { + size_t prev_class_stack_size = stream->curr_class_stack_size; + stream->curr_class_stack_size = 0; + emit_pending_spans (stream, false); + ostream_write_str (stream->destination, "
"); + stream->curr_class_stack_size = prev_class_stack_size; + } + else + { + emit_pending_spans (stream, true); + + switch (uc) + { + case '"': + ostream_write_str (stream->destination, """); + break; + case '&': + ostream_write_str (stream->destination, "&"); + break; + case '<': + ostream_write_str (stream->destination, "<"); + break; + case '>': + /* Needed to avoid "]]>" in the output. */ + ostream_write_str (stream->destination, ">"); + break; + case ' ': + /* Needed because HTML viewers merge adjacent spaces + and drop spaces adjacent to
and similar. */ + ostream_write_str (stream->destination, " "); + break; + default: + if (uc >= 0x20 && uc < 0x7F) + { + /* Output ASCII characters as such. */ + char bytes[1]; + bytes[0] = uc; + ostream_write_mem (stream->destination, bytes, 1); + } + else + { + /* Output non-ASCII characters in #&nnn; + notation. */ + char bytes[32]; + sprintf (bytes, "&#%d;", (int) uc); + ostream_write_str (stream->destination, bytes); + } + break; + } + } + + inptr += nbytes; + insize -= nbytes; + } + /* Put back the unconverted part. */ + if (insize > BUFSIZE) + abort (); + if (len == 0) + { + if (insize > 0) + memcpy (stream->buf, inptr, insize); + stream->buflen = insize; + break; + } + if (insize > 0) + memmove (inbuffer, inptr, insize); + inbufcount = insize; + } + } + #undef BUFFERSIZE + } +} + +static void +html_ostream::flush (html_ostream_t stream) +{ + /* There's nothing to do here, since stream->buf[] contains only a few + bytes that don't correspond to a character, and it's not worth closing + the open spans. */ +} + +static void +html_ostream::free (html_ostream_t stream) +{ + stream->curr_class_stack_size = 0; + emit_pending_spans (stream, true); + gl_list_free (stream->class_stack); + free (stream); +} + +/* Implementation of html_ostream_t methods. */ + +static void +html_ostream::begin_span (html_ostream_t stream, const char *classname) +{ + if (stream->last_class_stack_size > stream->curr_class_stack_size + && strcmp ((char *) gl_list_get_at (stream->class_stack, + stream->curr_class_stack_size), + classname) != 0) + emit_pending_spans (stream, true); + /* Now either + last_class_stack_size <= curr_class_stack_size + - in this case we have to append the given CLASSNAME - + or + last_class_stack_size > curr_class_stack_size + && class_stack[curr_class_stack_size] == CLASSNAME + - in this case we only need to increment curr_class_stack_size. */ + if (stream->last_class_stack_size <= stream->curr_class_stack_size) + gl_list_add_at (stream->class_stack, stream->curr_class_stack_size, + xstrdup (classname)); + stream->curr_class_stack_size++; +} + +static void +html_ostream::end_span (html_ostream_t stream, const char *classname) +{ + if (!(stream->curr_class_stack_size > 0 + && strcmp ((char *) gl_list_get_at (stream->class_stack, + stream->curr_class_stack_size - 1), + classname) == 0)) + /* Improperly nested begin_span/end_span calls. */ + abort (); + stream->curr_class_stack_size--; +} + +/* Constructor. */ + +html_ostream_t +html_ostream_create (ostream_t destination) +{ + html_ostream_t stream = XMALLOC (struct html_ostream_representation); + + stream->base.vtable = &html_ostream_vtable; + stream->destination = destination; + stream->class_stack = + gl_list_create_empty (GL_ARRAY_LIST, NULL, NULL, NULL, true); + stream->curr_class_stack_size = 0; + stream->last_class_stack_size = 0; + stream->buflen = 0; + + return stream; +} diff --git a/gettext-tools/gnulib-lib/html-ostream.oo.h b/gettext-tools/gnulib-lib/html-ostream.oo.h new file mode 100644 index 0000000..5ee26de --- /dev/null +++ b/gettext-tools/gnulib-lib/html-ostream.oo.h @@ -0,0 +1,58 @@ +/* Output stream that produces HTML output. + Copyright (C) 2006 Free Software Foundation, Inc. + Written by Bruno Haible , 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _HTML_OSTREAM_H +#define _HTML_OSTREAM_H + +#include "ostream.h" + + +struct html_ostream : struct ostream +{ +methods: + + /* Start a element. The CLASSNAME is the name + of a CSS class. It can be chosen arbitrarily and customized through + an inline or external CSS. */ + void begin_span (html_ostream_t stream, const char *classname); + + /* End a element. + The begin_span / end_span calls must match properly. */ + void end_span (html_ostream_t stream, const char *classname); +}; + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Create an output stream that takes input in the UTF-8 encoding and + writes it in HTML form on DESTINATION. + This stream produces a sequence of lines. The caller is responsible + for opening the elements before and for closing them after + the use of this stream. + Note that the resulting stream must be closed before DESTINATION can be + closed. */ +extern html_ostream_t html_ostream_create (ostream_t destination); + + +#ifdef __cplusplus +} +#endif + +#endif /* _HTML_OSTREAM_H */ diff --git a/gettext-tools/gnulib-lib/html-styled-ostream.c b/gettext-tools/gnulib-lib/html-styled-ostream.c new file mode 100644 index 0000000..6be0085 --- /dev/null +++ b/gettext-tools/gnulib-lib/html-styled-ostream.c @@ -0,0 +1,227 @@ +/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ + +#line 1 "html-styled-ostream.oo.c" +/* Output stream for CSS styled text, producing HTML output. + Copyright (C) 2006-2007 Free Software Foundation, Inc. + Written by Bruno Haible , 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include "html-styled-ostream.h" + +#include +#include +#include +#include + +#include "html-ostream.h" + +#include "binary-io.h" +#ifndef O_TEXT +# define O_TEXT 0 +#endif + +#include "error.h" +#include "safe-read.h" +#include "xalloc.h" +#include "gettext.h" + +#define _(str) gettext (str) + + +#line 47 "html-styled-ostream.c" +#if !IS_CPLUSPLUS +#define html_styled_ostream_representation any_ostream_representation +#endif +#include "html_styled_ostream.priv.h" + +const typeinfo_t html_styled_ostream_typeinfo = { "html_styled_ostream" }; + +static const typeinfo_t * const html_styled_ostream_superclasses[] = + { html_styled_ostream_SUPERCLASSES }; + +#define super styled_ostream_vtable + +#line 51 "html-styled-ostream.oo.c" + +/* Implementation of ostream_t methods. */ + +static void +html_styled_ostream__write_mem (html_styled_ostream_t stream, + const void *data, size_t len) +{ + html_ostream_write_mem (stream->html_destination, data, len); +} + +static void +html_styled_ostream__flush (html_styled_ostream_t stream) +{ + html_ostream_flush (stream->html_destination); +} + +static void +html_styled_ostream__free (html_styled_ostream_t stream) +{ + html_ostream_free (stream->html_destination); + ostream_write_str (stream->destination, "\n"); + ostream_write_str (stream->destination, "\n"); +} + +/* Implementation of styled_ostream_t methods. */ + +static void +html_styled_ostream__begin_use_class (html_styled_ostream_t stream, + const char *classname) +{ + html_ostream_begin_span (stream->html_destination, classname); +} + +static void +html_styled_ostream__end_use_class (html_styled_ostream_t stream, + const char *classname) +{ + html_ostream_end_span (stream->html_destination, classname); +} + +/* Constructor. */ + +html_styled_ostream_t +html_styled_ostream_create (ostream_t destination, const char *css_filename) +{ + html_styled_ostream_t stream = + XMALLOC (struct html_styled_ostream_representation); + + stream->base.base.vtable = &html_styled_ostream_vtable; + stream->destination = destination; + stream->html_destination = html_ostream_create (destination); + + ostream_write_str (stream->destination, "\n"); + /* HTML 4.01 or XHTML 1.0? + Use HTML 4.01. This is conservative. Before switching to XHTML 1.0, + verify that in the output + - all HTML element names are in lowercase, + - all empty elements are denoted like
or

, + - every attribute specification is in assignment form, like + , + - every element also has an 'id' attribute, + - special characters like < > & " are escaped in the \n"); + } + ostream_write_str (stream->destination, "\n"); + ostream_write_str (stream->destination, "\n"); + + return stream; +} + +#line 170 "html-styled-ostream.c" + +const struct html_styled_ostream_implementation html_styled_ostream_vtable = +{ + html_styled_ostream_superclasses, + sizeof (html_styled_ostream_superclasses) / sizeof (html_styled_ostream_superclasses[0]), + sizeof (struct html_styled_ostream_representation), + html_styled_ostream__write_mem, + html_styled_ostream__flush, + html_styled_ostream__free, + html_styled_ostream__begin_use_class, + html_styled_ostream__end_use_class, +}; + +#if !HAVE_INLINE + +/* Define the functions that invoke the methods. */ + +void +html_styled_ostream_write_mem (html_styled_ostream_t first_arg, const void *data, size_t len) +{ + const struct html_styled_ostream_implementation *vtable = + ((struct html_styled_ostream_representation_header *) (struct html_styled_ostream_representation *) first_arg)->vtable; + vtable->write_mem (first_arg,data,len); +} + +void +html_styled_ostream_flush (html_styled_ostream_t first_arg) +{ + const struct html_styled_ostream_implementation *vtable = + ((struct html_styled_ostream_representation_header *) (struct html_styled_ostream_representation *) first_arg)->vtable; + vtable->flush (first_arg); +} + +void +html_styled_ostream_free (html_styled_ostream_t first_arg) +{ + const struct html_styled_ostream_implementation *vtable = + ((struct html_styled_ostream_representation_header *) (struct html_styled_ostream_representation *) first_arg)->vtable; + vtable->free (first_arg); +} + +void +html_styled_ostream_begin_use_class (html_styled_ostream_t first_arg, const char *classname) +{ + const struct html_styled_ostream_implementation *vtable = + ((struct html_styled_ostream_representation_header *) (struct html_styled_ostream_representation *) first_arg)->vtable; + vtable->begin_use_class (first_arg,classname); +} + +void +html_styled_ostream_end_use_class (html_styled_ostream_t first_arg, const char *classname) +{ + const struct html_styled_ostream_implementation *vtable = + ((struct html_styled_ostream_representation_header *) (struct html_styled_ostream_representation *) first_arg)->vtable; + vtable->end_use_class (first_arg,classname); +} + +#endif diff --git a/gettext-tools/gnulib-lib/html-styled-ostream.h b/gettext-tools/gnulib-lib/html-styled-ostream.h new file mode 100644 index 0000000..fe87d32 --- /dev/null +++ b/gettext-tools/gnulib-lib/html-styled-ostream.h @@ -0,0 +1,160 @@ +/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ + +#line 1 "html-styled-ostream.oo.h" +/* Output stream for CSS styled text, producing HTML output. + Copyright (C) 2006 Free Software Foundation, Inc. + Written by Bruno Haible , 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _HTML_STYLED_OSTREAM_H +#define _HTML_STYLED_OSTREAM_H + +#include "styled-ostream.h" + + +#line 28 "html-styled-ostream.h" +struct html_styled_ostream_representation; +/* html_styled_ostream_t is defined as a pointer to struct html_styled_ostream_representation. + In C++ mode, we use a smart pointer class. + In C mode, we have no other choice than a typedef to the root class type. */ +#if IS_CPLUSPLUS +struct html_styled_ostream_t +{ +private: + struct html_styled_ostream_representation *_pointer; +public: + html_styled_ostream_t () : _pointer (NULL) {} + html_styled_ostream_t (struct html_styled_ostream_representation *pointer) : _pointer (pointer) {} + struct html_styled_ostream_representation * operator -> () { return _pointer; } + operator struct html_styled_ostream_representation * () { return _pointer; } + operator struct any_ostream_representation * () { return (struct any_ostream_representation *) _pointer; } + operator struct styled_ostream_representation * () { return (struct styled_ostream_representation *) _pointer; } + operator void * () { return _pointer; } + bool operator == (const void *p) { return _pointer == p; } + bool operator != (const void *p) { return _pointer != p; } + operator ostream_t () { return (ostream_t) (struct any_ostream_representation *) _pointer; } + explicit html_styled_ostream_t (ostream_t x) : _pointer ((struct html_styled_ostream_representation *) (void *) x) {} + operator styled_ostream_t () { return (styled_ostream_t) (struct styled_ostream_representation *) _pointer; } + explicit html_styled_ostream_t (styled_ostream_t x) : _pointer ((struct html_styled_ostream_representation *) (void *) x) {} +}; +#else +typedef styled_ostream_t html_styled_ostream_t; +#endif + +/* Functions that invoke the methods. */ +extern void html_styled_ostream_write_mem (html_styled_ostream_t first_arg, const void *data, size_t len); +extern void html_styled_ostream_flush (html_styled_ostream_t first_arg); +extern void html_styled_ostream_free (html_styled_ostream_t first_arg); +extern void html_styled_ostream_begin_use_class (html_styled_ostream_t first_arg, const char *classname); +extern void html_styled_ostream_end_use_class (html_styled_ostream_t first_arg, const char *classname); + +/* Type representing an implementation of html_styled_ostream_t. */ +struct html_styled_ostream_implementation +{ + const typeinfo_t * const *superclasses; + size_t superclasses_length; + size_t instance_size; +#define THIS_ARG html_styled_ostream_t first_arg +#include "html_styled_ostream.vt.h" +#undef THIS_ARG +}; + +/* Public portion of the object pointed to by a html_styled_ostream_t. */ +struct html_styled_ostream_representation_header +{ + const struct html_styled_ostream_implementation *vtable; +}; + +#if HAVE_INLINE + +/* Define the functions that invoke the methods as inline accesses to + the html_styled_ostream_implementation. + Use #define to avoid a warning because of extern vs. static. */ + +# define html_styled_ostream_write_mem html_styled_ostream_write_mem_inline +static inline void +html_styled_ostream_write_mem (html_styled_ostream_t first_arg, const void *data, size_t len) +{ + const struct html_styled_ostream_implementation *vtable = + ((struct html_styled_ostream_representation_header *) (struct html_styled_ostream_representation *) first_arg)->vtable; + vtable->write_mem (first_arg,data,len); +} + +# define html_styled_ostream_flush html_styled_ostream_flush_inline +static inline void +html_styled_ostream_flush (html_styled_ostream_t first_arg) +{ + const struct html_styled_ostream_implementation *vtable = + ((struct html_styled_ostream_representation_header *) (struct html_styled_ostream_representation *) first_arg)->vtable; + vtable->flush (first_arg); +} + +# define html_styled_ostream_free html_styled_ostream_free_inline +static inline void +html_styled_ostream_free (html_styled_ostream_t first_arg) +{ + const struct html_styled_ostream_implementation *vtable = + ((struct html_styled_ostream_representation_header *) (struct html_styled_ostream_representation *) first_arg)->vtable; + vtable->free (first_arg); +} + +# define html_styled_ostream_begin_use_class html_styled_ostream_begin_use_class_inline +static inline void +html_styled_ostream_begin_use_class (html_styled_ostream_t first_arg, const char *classname) +{ + const struct html_styled_ostream_implementation *vtable = + ((struct html_styled_ostream_representation_header *) (struct html_styled_ostream_representation *) first_arg)->vtable; + vtable->begin_use_class (first_arg,classname); +} + +# define html_styled_ostream_end_use_class html_styled_ostream_end_use_class_inline +static inline void +html_styled_ostream_end_use_class (html_styled_ostream_t first_arg, const char *classname) +{ + const struct html_styled_ostream_implementation *vtable = + ((struct html_styled_ostream_representation_header *) (struct html_styled_ostream_representation *) first_arg)->vtable; + vtable->end_use_class (first_arg,classname); +} + +#endif + +extern const typeinfo_t html_styled_ostream_typeinfo; +#define html_styled_ostream_SUPERCLASSES &html_styled_ostream_typeinfo, styled_ostream_SUPERCLASSES +#define html_styled_ostream_SUPERCLASSES_LENGTH (1 + styled_ostream_SUPERCLASSES_LENGTH) + +extern const struct html_styled_ostream_implementation html_styled_ostream_vtable; + +#line 28 "html-styled-ostream.oo.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Create an output stream that takes input in the UTF-8 encoding and + writes it in HTML form on DESTINATION, styled with the file CSS_FILENAME. + Note that the resulting stream must be closed before DESTINATION can be + closed. */ +extern html_styled_ostream_t + html_styled_ostream_create (ostream_t destination, + const char *css_filename); + + +#ifdef __cplusplus +} +#endif + +#endif /* _HTML_STYLED_OSTREAM_H */ diff --git a/gettext-tools/gnulib-lib/html-styled-ostream.oo.c b/gettext-tools/gnulib-lib/html-styled-ostream.oo.c new file mode 100644 index 0000000..2766ab0 --- /dev/null +++ b/gettext-tools/gnulib-lib/html-styled-ostream.oo.c @@ -0,0 +1,158 @@ +/* Output stream for CSS styled text, producing HTML output. + Copyright (C) 2006-2007 Free Software Foundation, Inc. + Written by Bruno Haible , 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include "html-styled-ostream.h" + +#include +#include +#include +#include + +#include "html-ostream.h" + +#include "binary-io.h" +#ifndef O_TEXT +# define O_TEXT 0 +#endif + +#include "error.h" +#include "safe-read.h" +#include "xalloc.h" +#include "gettext.h" + +#define _(str) gettext (str) + + +struct html_styled_ostream : struct styled_ostream +{ +fields: + /* The destination stream. */ + ostream_t destination; + /* A HTML aware wrapper around the destination stream. */ + html_ostream_t html_destination; +}; + +/* Implementation of ostream_t methods. */ + +static void +html_styled_ostream::write_mem (html_styled_ostream_t stream, + const void *data, size_t len) +{ + html_ostream_write_mem (stream->html_destination, data, len); +} + +static void +html_styled_ostream::flush (html_styled_ostream_t stream) +{ + html_ostream_flush (stream->html_destination); +} + +static void +html_styled_ostream::free (html_styled_ostream_t stream) +{ + html_ostream_free (stream->html_destination); + ostream_write_str (stream->destination, "\n"); + ostream_write_str (stream->destination, "\n"); +} + +/* Implementation of styled_ostream_t methods. */ + +static void +html_styled_ostream::begin_use_class (html_styled_ostream_t stream, + const char *classname) +{ + html_ostream_begin_span (stream->html_destination, classname); +} + +static void +html_styled_ostream::end_use_class (html_styled_ostream_t stream, + const char *classname) +{ + html_ostream_end_span (stream->html_destination, classname); +} + +/* Constructor. */ + +html_styled_ostream_t +html_styled_ostream_create (ostream_t destination, const char *css_filename) +{ + html_styled_ostream_t stream = + XMALLOC (struct html_styled_ostream_representation); + + stream->base.base.vtable = &html_styled_ostream_vtable; + stream->destination = destination; + stream->html_destination = html_ostream_create (destination); + + ostream_write_str (stream->destination, "\n"); + /* HTML 4.01 or XHTML 1.0? + Use HTML 4.01. This is conservative. Before switching to XHTML 1.0, + verify that in the output + - all HTML element names are in lowercase, + - all empty elements are denoted like
or

, + - every attribute specification is in assignment form, like +
, + - every element also has an 'id' attribute, + - special characters like < > & " are escaped in the \n"); + } + ostream_write_str (stream->destination, "\n"); + ostream_write_str (stream->destination, "\n"); + + return stream; +} diff --git a/gettext-tools/gnulib-lib/html-styled-ostream.oo.h b/gettext-tools/gnulib-lib/html-styled-ostream.oo.h new file mode 100644 index 0000000..c28e0b9 --- /dev/null +++ b/gettext-tools/gnulib-lib/html-styled-ostream.oo.h @@ -0,0 +1,48 @@ +/* Output stream for CSS styled text, producing HTML output. + Copyright (C) 2006 Free Software Foundation, Inc. + Written by Bruno Haible , 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _HTML_STYLED_OSTREAM_H +#define _HTML_STYLED_OSTREAM_H + +#include "styled-ostream.h" + + +struct html_styled_ostream : struct styled_ostream +{ +methods: +}; + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Create an output stream that takes input in the UTF-8 encoding and + writes it in HTML form on DESTINATION, styled with the file CSS_FILENAME. + Note that the resulting stream must be closed before DESTINATION can be + closed. */ +extern html_styled_ostream_t + html_styled_ostream_create (ostream_t destination, + const char *css_filename); + + +#ifdef __cplusplus +} +#endif + +#endif /* _HTML_STYLED_OSTREAM_H */ diff --git a/gettext-tools/gnulib-lib/html_ostream.priv.h b/gettext-tools/gnulib-lib/html_ostream.priv.h new file mode 100644 index 0000000..fb1a4d0 --- /dev/null +++ b/gettext-tools/gnulib-lib/html_ostream.priv.h @@ -0,0 +1,21 @@ +/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ + +/* Field layout of superclass. */ +#include "ostream.priv.h" + +/* Field layout of html_ostream class. */ +struct html_ostream_representation +{ + struct ostream_representation base; + + ostream_t destination; + + gl_list_t class_stack; + + size_t curr_class_stack_size; + size_t last_class_stack_size; + + #define BUFSIZE 6 + char buf[BUFSIZE]; + size_t buflen; +}; diff --git a/gettext-tools/gnulib-lib/html_ostream.vt.h b/gettext-tools/gnulib-lib/html_ostream.vt.h new file mode 100644 index 0000000..9067852 --- /dev/null +++ b/gettext-tools/gnulib-lib/html_ostream.vt.h @@ -0,0 +1,8 @@ +/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ + +/* Virtual function table layout of superclass. */ +#include "ostream.vt.h" + +/* Virtual function table layout of html_ostream class. */ + void (*begin_span) (THIS_ARG, const char *classname); + void (*end_span) (THIS_ARG, const char *classname); diff --git a/gettext-tools/gnulib-lib/html_styled_ostream.priv.h b/gettext-tools/gnulib-lib/html_styled_ostream.priv.h new file mode 100644 index 0000000..f346ab5 --- /dev/null +++ b/gettext-tools/gnulib-lib/html_styled_ostream.priv.h @@ -0,0 +1,14 @@ +/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ + +/* Field layout of superclass. */ +#include "styled_ostream.priv.h" + +/* Field layout of html_styled_ostream class. */ +struct html_styled_ostream_representation +{ + struct styled_ostream_representation base; + + ostream_t destination; + + html_ostream_t html_destination; +}; diff --git a/gettext-tools/gnulib-lib/html_styled_ostream.vt.h b/gettext-tools/gnulib-lib/html_styled_ostream.vt.h new file mode 100644 index 0000000..0c83157 --- /dev/null +++ b/gettext-tools/gnulib-lib/html_styled_ostream.vt.h @@ -0,0 +1,6 @@ +/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ + +/* Virtual function table layout of superclass. */ +#include "styled_ostream.vt.h" + +/* Virtual function table layout of html_styled_ostream class. */ diff --git a/gettext-tools/gnulib-lib/iconv.c b/gettext-tools/gnulib-lib/iconv.c new file mode 100644 index 0000000..b5a427b --- /dev/null +++ b/gettext-tools/gnulib-lib/iconv.c @@ -0,0 +1,449 @@ +/* Character set conversion. + Copyright (C) 1999-2001, 2007, 2009-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, see . */ + +#include + +/* Specification. */ +#include + +#include + +#if REPLACE_ICONV_UTF +# include +# include +# include +# include "unistr.h" +# ifndef uintptr_t +# define uintptr_t unsigned long +# endif +#endif + +#if REPLACE_ICONV_UTF + +/* UTF-{16,32}{BE,LE} converters taken from GNU libiconv 1.11. */ + +/* Return code if invalid. (xxx_mbtowc) */ +# define RET_ILSEQ -1 +/* Return code if no bytes were read. (xxx_mbtowc) */ +# define RET_TOOFEW -2 + +/* Return code if invalid. (xxx_wctomb) */ +# define RET_ILUNI -1 +/* Return code if output buffer is too small. (xxx_wctomb, xxx_reset) */ +# define RET_TOOSMALL -2 + +/* + * UTF-16BE + */ + +/* Specification: RFC 2781 */ + +static int +utf16be_mbtowc (ucs4_t *pwc, const unsigned char *s, size_t n) +{ + if (n >= 2) + { + ucs4_t wc = (s[0] << 8) + s[1]; + if (wc >= 0xd800 && wc < 0xdc00) + { + if (n >= 4) + { + ucs4_t wc2 = (s[2] << 8) + s[3]; + if (!(wc2 >= 0xdc00 && wc2 < 0xe000)) + return RET_ILSEQ; + *pwc = 0x10000 + ((wc - 0xd800) << 10) + (wc2 - 0xdc00); + return 4; + } + } + else if (wc >= 0xdc00 && wc < 0xe000) + { + return RET_ILSEQ; + } + else + { + *pwc = wc; + return 2; + } + } + return RET_TOOFEW; +} + +static int +utf16be_wctomb (unsigned char *r, ucs4_t wc, size_t n) +{ + if (!(wc >= 0xd800 && wc < 0xe000)) + { + if (wc < 0x10000) + { + if (n >= 2) + { + r[0] = (unsigned char) (wc >> 8); + r[1] = (unsigned char) wc; + return 2; + } + else + return RET_TOOSMALL; + } + else if (wc < 0x110000) + { + if (n >= 4) + { + ucs4_t wc1 = 0xd800 + ((wc - 0x10000) >> 10); + ucs4_t wc2 = 0xdc00 + ((wc - 0x10000) & 0x3ff); + r[0] = (unsigned char) (wc1 >> 8); + r[1] = (unsigned char) wc1; + r[2] = (unsigned char) (wc2 >> 8); + r[3] = (unsigned char) wc2; + return 4; + } + else + return RET_TOOSMALL; + } + } + return RET_ILUNI; +} + +/* + * UTF-16LE + */ + +/* Specification: RFC 2781 */ + +static int +utf16le_mbtowc (ucs4_t *pwc, const unsigned char *s, size_t n) +{ + if (n >= 2) + { + ucs4_t wc = s[0] + (s[1] << 8); + if (wc >= 0xd800 && wc < 0xdc00) + { + if (n >= 4) + { + ucs4_t wc2 = s[2] + (s[3] << 8); + if (!(wc2 >= 0xdc00 && wc2 < 0xe000)) + return RET_ILSEQ; + *pwc = 0x10000 + ((wc - 0xd800) << 10) + (wc2 - 0xdc00); + return 4; + } + } + else if (wc >= 0xdc00 && wc < 0xe000) + { + return RET_ILSEQ; + } + else + { + *pwc = wc; + return 2; + } + } + return RET_TOOFEW; +} + +static int +utf16le_wctomb (unsigned char *r, ucs4_t wc, size_t n) +{ + if (!(wc >= 0xd800 && wc < 0xe000)) + { + if (wc < 0x10000) + { + if (n >= 2) + { + r[0] = (unsigned char) wc; + r[1] = (unsigned char) (wc >> 8); + return 2; + } + else + return RET_TOOSMALL; + } + else if (wc < 0x110000) + { + if (n >= 4) + { + ucs4_t wc1 = 0xd800 + ((wc - 0x10000) >> 10); + ucs4_t wc2 = 0xdc00 + ((wc - 0x10000) & 0x3ff); + r[0] = (unsigned char) wc1; + r[1] = (unsigned char) (wc1 >> 8); + r[2] = (unsigned char) wc2; + r[3] = (unsigned char) (wc2 >> 8); + return 4; + } + else + return RET_TOOSMALL; + } + } + return RET_ILUNI; +} + +/* + * UTF-32BE + */ + +/* Specification: Unicode 3.1 Standard Annex #19 */ + +static int +utf32be_mbtowc (ucs4_t *pwc, const unsigned char *s, size_t n) +{ + if (n >= 4) + { + ucs4_t wc = (s[0] << 24) + (s[1] << 16) + (s[2] << 8) + s[3]; + if (wc < 0x110000 && !(wc >= 0xd800 && wc < 0xe000)) + { + *pwc = wc; + return 4; + } + else + return RET_ILSEQ; + } + return RET_TOOFEW; +} + +static int +utf32be_wctomb (unsigned char *r, ucs4_t wc, size_t n) +{ + if (wc < 0x110000 && !(wc >= 0xd800 && wc < 0xe000)) + { + if (n >= 4) + { + r[0] = 0; + r[1] = (unsigned char) (wc >> 16); + r[2] = (unsigned char) (wc >> 8); + r[3] = (unsigned char) wc; + return 4; + } + else + return RET_TOOSMALL; + } + return RET_ILUNI; +} + +/* + * UTF-32LE + */ + +/* Specification: Unicode 3.1 Standard Annex #19 */ + +static int +utf32le_mbtowc (ucs4_t *pwc, const unsigned char *s, size_t n) +{ + if (n >= 4) + { + ucs4_t wc = s[0] + (s[1] << 8) + (s[2] << 16) + (s[3] << 24); + if (wc < 0x110000 && !(wc >= 0xd800 && wc < 0xe000)) + { + *pwc = wc; + return 4; + } + else + return RET_ILSEQ; + } + return RET_TOOFEW; +} + +static int +utf32le_wctomb (unsigned char *r, ucs4_t wc, size_t n) +{ + if (wc < 0x110000 && !(wc >= 0xd800 && wc < 0xe000)) + { + if (n >= 4) + { + r[0] = (unsigned char) wc; + r[1] = (unsigned char) (wc >> 8); + r[2] = (unsigned char) (wc >> 16); + r[3] = 0; + return 4; + } + else + return RET_TOOSMALL; + } + return RET_ILUNI; +} + +#endif + +size_t +rpl_iconv (iconv_t cd, + ICONV_CONST char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +#undef iconv +{ +#if REPLACE_ICONV_UTF + switch ((uintptr_t) cd) + { + { + int (*xxx_wctomb) (unsigned char *, ucs4_t, size_t); + + case (uintptr_t) _ICONV_UTF8_UTF16BE: + xxx_wctomb = utf16be_wctomb; + goto loop_from_utf8; + case (uintptr_t) _ICONV_UTF8_UTF16LE: + xxx_wctomb = utf16le_wctomb; + goto loop_from_utf8; + case (uintptr_t) _ICONV_UTF8_UTF32BE: + xxx_wctomb = utf32be_wctomb; + goto loop_from_utf8; + case (uintptr_t) _ICONV_UTF8_UTF32LE: + xxx_wctomb = utf32le_wctomb; + goto loop_from_utf8; + + loop_from_utf8: + if (inbuf == NULL || *inbuf == NULL) + return 0; + { + ICONV_CONST char *inptr = *inbuf; + size_t inleft = *inbytesleft; + char *outptr = *outbuf; + size_t outleft = *outbytesleft; + size_t res = 0; + while (inleft > 0) + { + ucs4_t uc; + int m = u8_mbtoucr (&uc, (const uint8_t *) inptr, inleft); + if (m <= 0) + { + if (m == -1) + { + errno = EILSEQ; + res = (size_t)(-1); + break; + } + if (m == -2) + { + errno = EINVAL; + res = (size_t)(-1); + break; + } + abort (); + } + else + { + int n = xxx_wctomb ((uint8_t *) outptr, uc, outleft); + if (n < 0) + { + if (n == RET_ILUNI) + { + errno = EILSEQ; + res = (size_t)(-1); + break; + } + if (n == RET_TOOSMALL) + { + errno = E2BIG; + res = (size_t)(-1); + break; + } + abort (); + } + else + { + inptr += m; + inleft -= m; + outptr += n; + outleft -= n; + } + } + } + *inbuf = inptr; + *inbytesleft = inleft; + *outbuf = outptr; + *outbytesleft = outleft; + return res; + } + } + + { + int (*xxx_mbtowc) (ucs4_t *, const unsigned char *, size_t); + + case (uintptr_t) _ICONV_UTF16BE_UTF8: + xxx_mbtowc = utf16be_mbtowc; + goto loop_to_utf8; + case (uintptr_t) _ICONV_UTF16LE_UTF8: + xxx_mbtowc = utf16le_mbtowc; + goto loop_to_utf8; + case (uintptr_t) _ICONV_UTF32BE_UTF8: + xxx_mbtowc = utf32be_mbtowc; + goto loop_to_utf8; + case (uintptr_t) _ICONV_UTF32LE_UTF8: + xxx_mbtowc = utf32le_mbtowc; + goto loop_to_utf8; + + loop_to_utf8: + if (inbuf == NULL || *inbuf == NULL) + return 0; + { + ICONV_CONST char *inptr = *inbuf; + size_t inleft = *inbytesleft; + char *outptr = *outbuf; + size_t outleft = *outbytesleft; + size_t res = 0; + while (inleft > 0) + { + ucs4_t uc; + int m = xxx_mbtowc (&uc, (const uint8_t *) inptr, inleft); + if (m <= 0) + { + if (m == RET_ILSEQ) + { + errno = EILSEQ; + res = (size_t)(-1); + break; + } + if (m == RET_TOOFEW) + { + errno = EINVAL; + res = (size_t)(-1); + break; + } + abort (); + } + else + { + int n = u8_uctomb ((uint8_t *) outptr, uc, outleft); + if (n < 0) + { + if (n == -1) + { + errno = EILSEQ; + res = (size_t)(-1); + break; + } + if (n == -2) + { + errno = E2BIG; + res = (size_t)(-1); + break; + } + abort (); + } + else + { + inptr += m; + inleft -= m; + outptr += n; + outleft -= n; + } + } + } + *inbuf = inptr; + *inbytesleft = inleft; + *outbuf = outptr; + *outbytesleft = outleft; + return res; + } + } + } +#endif + return iconv (cd, inbuf, inbytesleft, outbuf, outbytesleft); +} diff --git a/gettext-tools/gnulib-lib/iconv.in.h b/gettext-tools/gnulib-lib/iconv.in.h new file mode 100644 index 0000000..d0e9836 --- /dev/null +++ b/gettext-tools/gnulib-lib/iconv.in.h @@ -0,0 +1,110 @@ +/* A GNU-like . + + Copyright (C) 2007-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . */ + +#ifndef _@GUARD_PREFIX@_ICONV_H + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +/* The include_next requires a split double-inclusion guard. */ +#@INCLUDE_NEXT@ @NEXT_ICONV_H@ + +#ifndef _@GUARD_PREFIX@_ICONV_H +#define _@GUARD_PREFIX@_ICONV_H + +/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ + +/* The definition of _GL_ARG_NONNULL is copied here. */ + +/* The definition of _GL_WARN_ON_USE is copied here. */ + + +#if @GNULIB_ICONV@ +# if @REPLACE_ICONV_OPEN@ +/* An iconv_open wrapper that supports the IANA standardized encoding names + ("ISO-8859-1" etc.) as far as possible. */ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define iconv_open rpl_iconv_open +# endif +_GL_FUNCDECL_RPL (iconv_open, iconv_t, + (const char *tocode, const char *fromcode) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (iconv_open, iconv_t, + (const char *tocode, const char *fromcode)); +# else +_GL_CXXALIAS_SYS (iconv_open, iconv_t, + (const char *tocode, const char *fromcode)); +# endif +_GL_CXXALIASWARN (iconv_open); +#endif + +#if @REPLACE_ICONV_UTF@ +/* Special constants for supporting UTF-{16,32}{BE,LE} encodings. + Not public. */ +# define _ICONV_UTF8_UTF16BE (iconv_t)(-161) +# define _ICONV_UTF8_UTF16LE (iconv_t)(-162) +# define _ICONV_UTF8_UTF32BE (iconv_t)(-163) +# define _ICONV_UTF8_UTF32LE (iconv_t)(-164) +# define _ICONV_UTF16BE_UTF8 (iconv_t)(-165) +# define _ICONV_UTF16LE_UTF8 (iconv_t)(-166) +# define _ICONV_UTF32BE_UTF8 (iconv_t)(-167) +# define _ICONV_UTF32LE_UTF8 (iconv_t)(-168) +#endif + +#if @GNULIB_ICONV@ +# if @REPLACE_ICONV@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define iconv rpl_iconv +# endif +_GL_FUNCDECL_RPL (iconv, size_t, + (iconv_t cd, + @ICONV_CONST@ char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft)); +_GL_CXXALIAS_RPL (iconv, size_t, + (iconv_t cd, + @ICONV_CONST@ char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft)); +# else +_GL_CXXALIAS_SYS (iconv, size_t, + (iconv_t cd, + @ICONV_CONST@ char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft)); +# endif +_GL_CXXALIASWARN (iconv); +# ifndef ICONV_CONST +# define ICONV_CONST @ICONV_CONST@ +# endif +#endif + +#if @GNULIB_ICONV@ +# if @REPLACE_ICONV@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define iconv_close rpl_iconv_close +# endif +_GL_FUNCDECL_RPL (iconv_close, int, (iconv_t cd)); +_GL_CXXALIAS_RPL (iconv_close, int, (iconv_t cd)); +# else +_GL_CXXALIAS_SYS (iconv_close, int, (iconv_t cd)); +# endif +_GL_CXXALIASWARN (iconv_close); +#endif + + +#endif /* _@GUARD_PREFIX@_ICONV_H */ +#endif /* _@GUARD_PREFIX@_ICONV_H */ diff --git a/gettext-tools/gnulib-lib/iconv_close.c b/gettext-tools/gnulib-lib/iconv_close.c new file mode 100644 index 0000000..d66c115 --- /dev/null +++ b/gettext-tools/gnulib-lib/iconv_close.c @@ -0,0 +1,46 @@ +/* Character set conversion. + Copyright (C) 2007, 2009-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, see . */ + +#include + +/* Specification. */ +#include + +#include +#ifndef uintptr_t +# define uintptr_t unsigned long +#endif + +int +rpl_iconv_close (iconv_t cd) +#undef iconv_close +{ +#if REPLACE_ICONV_UTF + switch ((uintptr_t) cd) + { + case (uintptr_t) _ICONV_UTF8_UTF16BE: + case (uintptr_t) _ICONV_UTF8_UTF16LE: + case (uintptr_t) _ICONV_UTF8_UTF32BE: + case (uintptr_t) _ICONV_UTF8_UTF32LE: + case (uintptr_t) _ICONV_UTF16BE_UTF8: + case (uintptr_t) _ICONV_UTF16LE_UTF8: + case (uintptr_t) _ICONV_UTF32BE_UTF8: + case (uintptr_t) _ICONV_UTF32LE_UTF8: + return 0; + } +#endif + return iconv_close (cd); +} diff --git a/gettext-tools/gnulib-lib/iconv_open-aix.gperf b/gettext-tools/gnulib-lib/iconv_open-aix.gperf new file mode 100644 index 0000000..6782b99 --- /dev/null +++ b/gettext-tools/gnulib-lib/iconv_open-aix.gperf @@ -0,0 +1,44 @@ +struct mapping { int standard_name; const char vendor_name[10 + 1]; }; +%struct-type +%language=ANSI-C +%define slot-name standard_name +%define hash-function-name mapping_hash +%define lookup-function-name mapping_lookup +%readonly-tables +%global-table +%define word-array-name mappings +%pic +%% +# On AIX 5.1, look in /usr/lib/nls/loc/uconvTable. +ISO-8859-1, "ISO8859-1" +ISO-8859-2, "ISO8859-2" +ISO-8859-3, "ISO8859-3" +ISO-8859-4, "ISO8859-4" +ISO-8859-5, "ISO8859-5" +ISO-8859-6, "ISO8859-6" +ISO-8859-7, "ISO8859-7" +ISO-8859-8, "ISO8859-8" +ISO-8859-9, "ISO8859-9" +ISO-8859-15, "ISO8859-15" +CP437, "IBM-437" +CP850, "IBM-850" +CP852, "IBM-852" +CP856, "IBM-856" +CP857, "IBM-857" +CP861, "IBM-861" +CP865, "IBM-865" +CP869, "IBM-869" +ISO-8859-13, "IBM-921" +CP922, "IBM-922" +CP932, "IBM-932" +CP943, "IBM-943" +CP1046, "IBM-1046" +CP1124, "IBM-1124" +CP1125, "IBM-1125" +CP1129, "IBM-1129" +CP1252, "IBM-1252" +GB2312, "IBM-eucCN" +EUC-JP, "IBM-eucJP" +EUC-KR, "IBM-eucKR" +EUC-TW, "IBM-eucTW" +BIG5, "big5" diff --git a/gettext-tools/gnulib-lib/iconv_open-aix.h b/gettext-tools/gnulib-lib/iconv_open-aix.h new file mode 100644 index 0000000..129e030 --- /dev/null +++ b/gettext-tools/gnulib-lib/iconv_open-aix.h @@ -0,0 +1,256 @@ +/* ANSI-C code produced by gperf version 3.0.4 */ +/* Command-line: gperf -m 10 ./iconv_open-aix.gperf */ +/* Computed positions: -k'4,$' */ + +#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ + && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \ + && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \ + && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \ + && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \ + && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \ + && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \ + && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \ + && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \ + && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \ + && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \ + && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \ + && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \ + && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \ + && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \ + && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \ + && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \ + && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \ + && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \ + && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \ + && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \ + && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \ + && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126)) +/* The character set is not based on ISO-646. */ +#error "gperf generated tables don't work with this execution character set. Please report a bug to ." +#endif + +#line 1 "./iconv_open-aix.gperf" +struct mapping { int standard_name; const char vendor_name[10 + 1]; }; + +#define TOTAL_KEYWORDS 32 +#define MIN_WORD_LENGTH 4 +#define MAX_WORD_LENGTH 11 +#define MIN_HASH_VALUE 6 +#define MAX_HASH_VALUE 44 +/* maximum key range = 39, duplicates = 0 */ + +#ifdef __GNUC__ +__inline +#else +#ifdef __cplusplus +inline +#endif +#endif +static unsigned int +mapping_hash (register const char *str, register unsigned int len) +{ + static const unsigned char asso_values[] = + { + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 0, 4, 25, + 0, 11, 24, 9, 17, 3, 14, 21, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 3, 45, 1, 45, 45, 45, 45, 0, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45 + }; + return len + asso_values[(unsigned char)str[3]+2] + asso_values[(unsigned char)str[len - 1]]; +} + +struct stringpool_t + { + char stringpool_str6[sizeof("EUC-TW")]; + char stringpool_str7[sizeof("EUC-KR")]; + char stringpool_str8[sizeof("CP852")]; + char stringpool_str9[sizeof("EUC-JP")]; + char stringpool_str10[sizeof("ISO-8859-2")]; + char stringpool_str11[sizeof("CP857")]; + char stringpool_str12[sizeof("CP850")]; + char stringpool_str13[sizeof("ISO-8859-7")]; + char stringpool_str14[sizeof("CP932")]; + char stringpool_str15[sizeof("GB2312")]; + char stringpool_str16[sizeof("BIG5")]; + char stringpool_str17[sizeof("CP437")]; + char stringpool_str19[sizeof("ISO-8859-5")]; + char stringpool_str20[sizeof("ISO-8859-15")]; + char stringpool_str21[sizeof("ISO-8859-3")]; + char stringpool_str22[sizeof("ISO-8859-13")]; + char stringpool_str23[sizeof("CP1046")]; + char stringpool_str24[sizeof("ISO-8859-8")]; + char stringpool_str25[sizeof("CP856")]; + char stringpool_str26[sizeof("CP1125")]; + char stringpool_str27[sizeof("ISO-8859-6")]; + char stringpool_str28[sizeof("CP865")]; + char stringpool_str29[sizeof("CP922")]; + char stringpool_str30[sizeof("CP1252")]; + char stringpool_str31[sizeof("ISO-8859-9")]; + char stringpool_str33[sizeof("CP943")]; + char stringpool_str34[sizeof("ISO-8859-4")]; + char stringpool_str35[sizeof("ISO-8859-1")]; + char stringpool_str38[sizeof("CP1129")]; + char stringpool_str40[sizeof("CP869")]; + char stringpool_str41[sizeof("CP1124")]; + char stringpool_str44[sizeof("CP861")]; + }; +static const struct stringpool_t stringpool_contents = + { + "EUC-TW", + "EUC-KR", + "CP852", + "EUC-JP", + "ISO-8859-2", + "CP857", + "CP850", + "ISO-8859-7", + "CP932", + "GB2312", + "BIG5", + "CP437", + "ISO-8859-5", + "ISO-8859-15", + "ISO-8859-3", + "ISO-8859-13", + "CP1046", + "ISO-8859-8", + "CP856", + "CP1125", + "ISO-8859-6", + "CP865", + "CP922", + "CP1252", + "ISO-8859-9", + "CP943", + "ISO-8859-4", + "ISO-8859-1", + "CP1129", + "CP869", + "CP1124", + "CP861" + }; +#define stringpool ((const char *) &stringpool_contents) + +static const struct mapping mappings[] = + { + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, +#line 43 "./iconv_open-aix.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str6, "IBM-eucTW"}, +#line 42 "./iconv_open-aix.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str7, "IBM-eucKR"}, +#line 25 "./iconv_open-aix.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str8, "IBM-852"}, +#line 41 "./iconv_open-aix.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str9, "IBM-eucJP"}, +#line 14 "./iconv_open-aix.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str10, "ISO8859-2"}, +#line 27 "./iconv_open-aix.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str11, "IBM-857"}, +#line 24 "./iconv_open-aix.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str12, "IBM-850"}, +#line 19 "./iconv_open-aix.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str13, "ISO8859-7"}, +#line 33 "./iconv_open-aix.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str14, "IBM-932"}, +#line 40 "./iconv_open-aix.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str15, "IBM-eucCN"}, +#line 44 "./iconv_open-aix.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str16, "big5"}, +#line 23 "./iconv_open-aix.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str17, "IBM-437"}, + {-1}, +#line 17 "./iconv_open-aix.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str19, "ISO8859-5"}, +#line 22 "./iconv_open-aix.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str20, "ISO8859-15"}, +#line 15 "./iconv_open-aix.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str21, "ISO8859-3"}, +#line 31 "./iconv_open-aix.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str22, "IBM-921"}, +#line 35 "./iconv_open-aix.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str23, "IBM-1046"}, +#line 20 "./iconv_open-aix.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str24, "ISO8859-8"}, +#line 26 "./iconv_open-aix.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str25, "IBM-856"}, +#line 37 "./iconv_open-aix.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str26, "IBM-1125"}, +#line 18 "./iconv_open-aix.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str27, "ISO8859-6"}, +#line 29 "./iconv_open-aix.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str28, "IBM-865"}, +#line 32 "./iconv_open-aix.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str29, "IBM-922"}, +#line 39 "./iconv_open-aix.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str30, "IBM-1252"}, +#line 21 "./iconv_open-aix.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str31, "ISO8859-9"}, + {-1}, +#line 34 "./iconv_open-aix.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str33, "IBM-943"}, +#line 16 "./iconv_open-aix.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str34, "ISO8859-4"}, +#line 13 "./iconv_open-aix.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str35, "ISO8859-1"}, + {-1}, {-1}, +#line 38 "./iconv_open-aix.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str38, "IBM-1129"}, + {-1}, +#line 30 "./iconv_open-aix.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str40, "IBM-869"}, +#line 36 "./iconv_open-aix.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str41, "IBM-1124"}, + {-1}, {-1}, +#line 28 "./iconv_open-aix.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str44, "IBM-861"} + }; + +#ifdef __GNUC__ +__inline +#if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__ +__attribute__ ((__gnu_inline__)) +#endif +#endif +const struct mapping * +mapping_lookup (register const char *str, register unsigned int len) +{ + if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) + { + register int key = mapping_hash (str, len); + + if (key <= MAX_HASH_VALUE && key >= 0) + { + register int o = mappings[key].standard_name; + if (o >= 0) + { + register const char *s = o + stringpool; + + if (*str == *s && !strcmp (str + 1, s + 1)) + return &mappings[key]; + } + } + } + return 0; +} diff --git a/gettext-tools/gnulib-lib/iconv_open-hpux.gperf b/gettext-tools/gnulib-lib/iconv_open-hpux.gperf new file mode 100644 index 0000000..5a35c83 --- /dev/null +++ b/gettext-tools/gnulib-lib/iconv_open-hpux.gperf @@ -0,0 +1,56 @@ +struct mapping { int standard_name; const char vendor_name[9 + 1]; }; +%struct-type +%language=ANSI-C +%define slot-name standard_name +%define hash-function-name mapping_hash +%define lookup-function-name mapping_lookup +%readonly-tables +%global-table +%define word-array-name mappings +%pic +%% +# On HP-UX 11.11, look in /usr/lib/nls/iconv. +ISO-8859-1, "iso88591" +ISO-8859-2, "iso88592" +ISO-8859-5, "iso88595" +ISO-8859-6, "iso88596" +ISO-8859-7, "iso88597" +ISO-8859-8, "iso88598" +ISO-8859-9, "iso88599" +ISO-8859-15, "iso885915" +CP437, "cp437" +CP775, "cp775" +CP850, "cp850" +CP852, "cp852" +CP855, "cp855" +CP857, "cp857" +CP861, "cp861" +CP862, "cp862" +CP864, "cp864" +CP865, "cp865" +CP866, "cp866" +CP869, "cp869" +CP874, "cp874" +CP1250, "cp1250" +CP1251, "cp1251" +CP1252, "cp1252" +CP1253, "cp1253" +CP1254, "cp1254" +CP1255, "cp1255" +CP1256, "cp1256" +CP1257, "cp1257" +CP1258, "cp1258" +HP-ROMAN8, "roman8" +HP-ARABIC8, "arabic8" +HP-GREEK8, "greek8" +HP-HEBREW8, "hebrew8" +HP-TURKISH8, "turkish8" +HP-KANA8, "kana8" +TIS-620, "tis620" +GB2312, "hp15CN" +EUC-JP, "eucJP" +EUC-KR, "eucKR" +EUC-TW, "eucTW" +BIG5, "big5" +SHIFT_JIS, "sjis" +UTF-8, "utf8" diff --git a/gettext-tools/gnulib-lib/iconv_open-hpux.h b/gettext-tools/gnulib-lib/iconv_open-hpux.h new file mode 100644 index 0000000..3bcff76 --- /dev/null +++ b/gettext-tools/gnulib-lib/iconv_open-hpux.h @@ -0,0 +1,299 @@ +/* ANSI-C code produced by gperf version 3.0.4 */ +/* Command-line: gperf -m 10 ./iconv_open-hpux.gperf */ +/* Computed positions: -k'4,$' */ + +#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ + && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \ + && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \ + && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \ + && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \ + && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \ + && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \ + && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \ + && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \ + && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \ + && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \ + && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \ + && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \ + && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \ + && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \ + && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \ + && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \ + && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \ + && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \ + && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \ + && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \ + && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \ + && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126)) +/* The character set is not based on ISO-646. */ +#error "gperf generated tables don't work with this execution character set. Please report a bug to ." +#endif + +#line 1 "./iconv_open-hpux.gperf" +struct mapping { int standard_name; const char vendor_name[9 + 1]; }; + +#define TOTAL_KEYWORDS 44 +#define MIN_WORD_LENGTH 4 +#define MAX_WORD_LENGTH 11 +#define MIN_HASH_VALUE 6 +#define MAX_HASH_VALUE 49 +/* maximum key range = 44, duplicates = 0 */ + +#ifdef __GNUC__ +__inline +#else +#ifdef __cplusplus +inline +#endif +#endif +static unsigned int +mapping_hash (register const char *str, register unsigned int len) +{ + static const unsigned char asso_values[] = + { + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 1, 2, + 24, 43, 5, 10, 0, 13, 32, 3, 19, 18, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 5, + 50, 50, 50, 50, 14, 5, 0, 50, 50, 0, + 27, 50, 12, 14, 50, 50, 0, 5, 2, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50 + }; + return len + asso_values[(unsigned char)str[3]+4] + asso_values[(unsigned char)str[len - 1]]; +} + +struct stringpool_t + { + char stringpool_str6[sizeof("CP1256")]; + char stringpool_str7[sizeof("CP1250")]; + char stringpool_str8[sizeof("CP1251")]; + char stringpool_str9[sizeof("CP850")]; + char stringpool_str10[sizeof("TIS-620")]; + char stringpool_str11[sizeof("CP1254")]; + char stringpool_str12[sizeof("ISO-8859-6")]; + char stringpool_str13[sizeof("EUC-TW")]; + char stringpool_str14[sizeof("ISO-8859-1")]; + char stringpool_str15[sizeof("ISO-8859-9")]; + char stringpool_str16[sizeof("CP1255")]; + char stringpool_str17[sizeof("BIG5")]; + char stringpool_str18[sizeof("CP855")]; + char stringpool_str19[sizeof("CP1257")]; + char stringpool_str20[sizeof("EUC-KR")]; + char stringpool_str21[sizeof("CP857")]; + char stringpool_str22[sizeof("ISO-8859-5")]; + char stringpool_str23[sizeof("ISO-8859-15")]; + char stringpool_str24[sizeof("CP866")]; + char stringpool_str25[sizeof("ISO-8859-7")]; + char stringpool_str26[sizeof("CP861")]; + char stringpool_str27[sizeof("CP869")]; + char stringpool_str28[sizeof("CP874")]; + char stringpool_str29[sizeof("CP864")]; + char stringpool_str30[sizeof("CP1252")]; + char stringpool_str31[sizeof("CP437")]; + char stringpool_str32[sizeof("CP852")]; + char stringpool_str33[sizeof("CP775")]; + char stringpool_str34[sizeof("CP865")]; + char stringpool_str35[sizeof("EUC-JP")]; + char stringpool_str36[sizeof("ISO-8859-2")]; + char stringpool_str37[sizeof("SHIFT_JIS")]; + char stringpool_str38[sizeof("CP1258")]; + char stringpool_str39[sizeof("UTF-8")]; + char stringpool_str40[sizeof("HP-KANA8")]; + char stringpool_str41[sizeof("HP-ROMAN8")]; + char stringpool_str42[sizeof("HP-HEBREW8")]; + char stringpool_str43[sizeof("GB2312")]; + char stringpool_str44[sizeof("ISO-8859-8")]; + char stringpool_str45[sizeof("HP-TURKISH8")]; + char stringpool_str46[sizeof("HP-GREEK8")]; + char stringpool_str47[sizeof("HP-ARABIC8")]; + char stringpool_str48[sizeof("CP862")]; + char stringpool_str49[sizeof("CP1253")]; + }; +static const struct stringpool_t stringpool_contents = + { + "CP1256", + "CP1250", + "CP1251", + "CP850", + "TIS-620", + "CP1254", + "ISO-8859-6", + "EUC-TW", + "ISO-8859-1", + "ISO-8859-9", + "CP1255", + "BIG5", + "CP855", + "CP1257", + "EUC-KR", + "CP857", + "ISO-8859-5", + "ISO-8859-15", + "CP866", + "ISO-8859-7", + "CP861", + "CP869", + "CP874", + "CP864", + "CP1252", + "CP437", + "CP852", + "CP775", + "CP865", + "EUC-JP", + "ISO-8859-2", + "SHIFT_JIS", + "CP1258", + "UTF-8", + "HP-KANA8", + "HP-ROMAN8", + "HP-HEBREW8", + "GB2312", + "ISO-8859-8", + "HP-TURKISH8", + "HP-GREEK8", + "HP-ARABIC8", + "CP862", + "CP1253" + }; +#define stringpool ((const char *) &stringpool_contents) + +static const struct mapping mappings[] = + { + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, +#line 40 "./iconv_open-hpux.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str6, "cp1256"}, +#line 34 "./iconv_open-hpux.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str7, "cp1250"}, +#line 35 "./iconv_open-hpux.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str8, "cp1251"}, +#line 23 "./iconv_open-hpux.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str9, "cp850"}, +#line 49 "./iconv_open-hpux.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str10, "tis620"}, +#line 38 "./iconv_open-hpux.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str11, "cp1254"}, +#line 16 "./iconv_open-hpux.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str12, "iso88596"}, +#line 53 "./iconv_open-hpux.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str13, "eucTW"}, +#line 13 "./iconv_open-hpux.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str14, "iso88591"}, +#line 19 "./iconv_open-hpux.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str15, "iso88599"}, +#line 39 "./iconv_open-hpux.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str16, "cp1255"}, +#line 54 "./iconv_open-hpux.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str17, "big5"}, +#line 25 "./iconv_open-hpux.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str18, "cp855"}, +#line 41 "./iconv_open-hpux.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str19, "cp1257"}, +#line 52 "./iconv_open-hpux.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str20, "eucKR"}, +#line 26 "./iconv_open-hpux.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str21, "cp857"}, +#line 15 "./iconv_open-hpux.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str22, "iso88595"}, +#line 20 "./iconv_open-hpux.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str23, "iso885915"}, +#line 31 "./iconv_open-hpux.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str24, "cp866"}, +#line 17 "./iconv_open-hpux.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str25, "iso88597"}, +#line 27 "./iconv_open-hpux.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str26, "cp861"}, +#line 32 "./iconv_open-hpux.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str27, "cp869"}, +#line 33 "./iconv_open-hpux.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str28, "cp874"}, +#line 29 "./iconv_open-hpux.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str29, "cp864"}, +#line 36 "./iconv_open-hpux.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str30, "cp1252"}, +#line 21 "./iconv_open-hpux.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str31, "cp437"}, +#line 24 "./iconv_open-hpux.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str32, "cp852"}, +#line 22 "./iconv_open-hpux.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str33, "cp775"}, +#line 30 "./iconv_open-hpux.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str34, "cp865"}, +#line 51 "./iconv_open-hpux.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str35, "eucJP"}, +#line 14 "./iconv_open-hpux.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str36, "iso88592"}, +#line 55 "./iconv_open-hpux.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str37, "sjis"}, +#line 42 "./iconv_open-hpux.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str38, "cp1258"}, +#line 56 "./iconv_open-hpux.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str39, "utf8"}, +#line 48 "./iconv_open-hpux.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str40, "kana8"}, +#line 43 "./iconv_open-hpux.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str41, "roman8"}, +#line 46 "./iconv_open-hpux.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str42, "hebrew8"}, +#line 50 "./iconv_open-hpux.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str43, "hp15CN"}, +#line 18 "./iconv_open-hpux.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str44, "iso88598"}, +#line 47 "./iconv_open-hpux.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str45, "turkish8"}, +#line 45 "./iconv_open-hpux.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str46, "greek8"}, +#line 44 "./iconv_open-hpux.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str47, "arabic8"}, +#line 28 "./iconv_open-hpux.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str48, "cp862"}, +#line 37 "./iconv_open-hpux.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str49, "cp1253"} + }; + +#ifdef __GNUC__ +__inline +#if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__ +__attribute__ ((__gnu_inline__)) +#endif +#endif +const struct mapping * +mapping_lookup (register const char *str, register unsigned int len) +{ + if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) + { + register int key = mapping_hash (str, len); + + if (key <= MAX_HASH_VALUE && key >= 0) + { + register int o = mappings[key].standard_name; + if (o >= 0) + { + register const char *s = o + stringpool; + + if (*str == *s && !strcmp (str + 1, s + 1)) + return &mappings[key]; + } + } + } + return 0; +} diff --git a/gettext-tools/gnulib-lib/iconv_open-irix.gperf b/gettext-tools/gnulib-lib/iconv_open-irix.gperf new file mode 100644 index 0000000..3672a80 --- /dev/null +++ b/gettext-tools/gnulib-lib/iconv_open-irix.gperf @@ -0,0 +1,31 @@ +struct mapping { int standard_name; const char vendor_name[10 + 1]; }; +%struct-type +%language=ANSI-C +%define slot-name standard_name +%define hash-function-name mapping_hash +%define lookup-function-name mapping_lookup +%readonly-tables +%global-table +%define word-array-name mappings +%pic +%% +# On IRIX 6.5, look in /usr/lib/iconv and /usr/lib/international/encodings. +ISO-8859-1, "ISO8859-1" +ISO-8859-2, "ISO8859-2" +ISO-8859-3, "ISO8859-3" +ISO-8859-4, "ISO8859-4" +ISO-8859-5, "ISO8859-5" +ISO-8859-6, "ISO8859-6" +ISO-8859-7, "ISO8859-7" +ISO-8859-8, "ISO8859-8" +ISO-8859-9, "ISO8859-9" +ISO-8859-15, "ISO8859-15" +KOI8-R, "KOI8" +CP855, "DOS855" +CP1251, "WIN1251" +GB2312, "eucCN" +EUC-JP, "eucJP" +EUC-KR, "eucKR" +EUC-TW, "eucTW" +SHIFT_JIS, "sjis" +TIS-620, "TIS620" diff --git a/gettext-tools/gnulib-lib/iconv_open-irix.h b/gettext-tools/gnulib-lib/iconv_open-irix.h new file mode 100644 index 0000000..74ceb8f --- /dev/null +++ b/gettext-tools/gnulib-lib/iconv_open-irix.h @@ -0,0 +1,199 @@ +/* ANSI-C code produced by gperf version 3.0.4 */ +/* Command-line: gperf -m 10 ./iconv_open-irix.gperf */ +/* Computed positions: -k'1,$' */ + +#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ + && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \ + && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \ + && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \ + && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \ + && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \ + && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \ + && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \ + && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \ + && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \ + && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \ + && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \ + && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \ + && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \ + && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \ + && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \ + && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \ + && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \ + && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \ + && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \ + && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \ + && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \ + && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126)) +/* The character set is not based on ISO-646. */ +#error "gperf generated tables don't work with this execution character set. Please report a bug to ." +#endif + +#line 1 "./iconv_open-irix.gperf" +struct mapping { int standard_name; const char vendor_name[10 + 1]; }; + +#define TOTAL_KEYWORDS 19 +#define MIN_WORD_LENGTH 5 +#define MAX_WORD_LENGTH 11 +#define MIN_HASH_VALUE 5 +#define MAX_HASH_VALUE 23 +/* maximum key range = 19, duplicates = 0 */ + +#ifdef __GNUC__ +__inline +#else +#ifdef __cplusplus +inline +#endif +#endif +static unsigned int +mapping_hash (register const char *str, register unsigned int len) +{ + static const unsigned char asso_values[] = + { + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 8, 2, + 5, 12, 11, 0, 10, 9, 8, 7, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 0, 24, 0, + 24, 5, 24, 0, 24, 7, 24, 24, 24, 24, + 7, 24, 1, 0, 8, 24, 24, 0, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24 + }; + return len + asso_values[(unsigned char)str[len - 1]] + asso_values[(unsigned char)str[0]]; +} + +struct stringpool_t + { + char stringpool_str5[sizeof("CP855")]; + char stringpool_str6[sizeof("EUC-TW")]; + char stringpool_str7[sizeof("EUC-KR")]; + char stringpool_str8[sizeof("CP1251")]; + char stringpool_str9[sizeof("SHIFT_JIS")]; + char stringpool_str10[sizeof("ISO-8859-5")]; + char stringpool_str11[sizeof("ISO-8859-15")]; + char stringpool_str12[sizeof("ISO-8859-1")]; + char stringpool_str13[sizeof("EUC-JP")]; + char stringpool_str14[sizeof("KOI8-R")]; + char stringpool_str15[sizeof("ISO-8859-2")]; + char stringpool_str16[sizeof("GB2312")]; + char stringpool_str17[sizeof("ISO-8859-9")]; + char stringpool_str18[sizeof("ISO-8859-8")]; + char stringpool_str19[sizeof("ISO-8859-7")]; + char stringpool_str20[sizeof("ISO-8859-6")]; + char stringpool_str21[sizeof("ISO-8859-4")]; + char stringpool_str22[sizeof("ISO-8859-3")]; + char stringpool_str23[sizeof("TIS-620")]; + }; +static const struct stringpool_t stringpool_contents = + { + "CP855", + "EUC-TW", + "EUC-KR", + "CP1251", + "SHIFT_JIS", + "ISO-8859-5", + "ISO-8859-15", + "ISO-8859-1", + "EUC-JP", + "KOI8-R", + "ISO-8859-2", + "GB2312", + "ISO-8859-9", + "ISO-8859-8", + "ISO-8859-7", + "ISO-8859-6", + "ISO-8859-4", + "ISO-8859-3", + "TIS-620" + }; +#define stringpool ((const char *) &stringpool_contents) + +static const struct mapping mappings[] = + { + {-1}, {-1}, {-1}, {-1}, {-1}, +#line 24 "./iconv_open-irix.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str5, "DOS855"}, +#line 29 "./iconv_open-irix.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str6, "eucTW"}, +#line 28 "./iconv_open-irix.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str7, "eucKR"}, +#line 25 "./iconv_open-irix.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str8, "WIN1251"}, +#line 30 "./iconv_open-irix.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str9, "sjis"}, +#line 17 "./iconv_open-irix.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str10, "ISO8859-5"}, +#line 22 "./iconv_open-irix.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str11, "ISO8859-15"}, +#line 13 "./iconv_open-irix.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str12, "ISO8859-1"}, +#line 27 "./iconv_open-irix.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str13, "eucJP"}, +#line 23 "./iconv_open-irix.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str14, "KOI8"}, +#line 14 "./iconv_open-irix.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str15, "ISO8859-2"}, +#line 26 "./iconv_open-irix.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str16, "eucCN"}, +#line 21 "./iconv_open-irix.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str17, "ISO8859-9"}, +#line 20 "./iconv_open-irix.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str18, "ISO8859-8"}, +#line 19 "./iconv_open-irix.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str19, "ISO8859-7"}, +#line 18 "./iconv_open-irix.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str20, "ISO8859-6"}, +#line 16 "./iconv_open-irix.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str21, "ISO8859-4"}, +#line 15 "./iconv_open-irix.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str22, "ISO8859-3"}, +#line 31 "./iconv_open-irix.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str23, "TIS620"} + }; + +#ifdef __GNUC__ +__inline +#if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__ +__attribute__ ((__gnu_inline__)) +#endif +#endif +const struct mapping * +mapping_lookup (register const char *str, register unsigned int len) +{ + if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) + { + register int key = mapping_hash (str, len); + + if (key <= MAX_HASH_VALUE && key >= 0) + { + register int o = mappings[key].standard_name; + if (o >= 0) + { + register const char *s = o + stringpool; + + if (*str == *s && !strcmp (str + 1, s + 1)) + return &mappings[key]; + } + } + } + return 0; +} diff --git a/gettext-tools/gnulib-lib/iconv_open-osf.gperf b/gettext-tools/gnulib-lib/iconv_open-osf.gperf new file mode 100644 index 0000000..f468ff6 --- /dev/null +++ b/gettext-tools/gnulib-lib/iconv_open-osf.gperf @@ -0,0 +1,50 @@ +struct mapping { int standard_name; const char vendor_name[10 + 1]; }; +%struct-type +%language=ANSI-C +%define slot-name standard_name +%define hash-function-name mapping_hash +%define lookup-function-name mapping_lookup +%readonly-tables +%global-table +%define word-array-name mappings +%pic +%% +# On OSF/1 5.1, look in /usr/lib/nls/loc/iconv. +ISO-8859-1, "ISO8859-1" +ISO-8859-2, "ISO8859-2" +ISO-8859-3, "ISO8859-3" +ISO-8859-4, "ISO8859-4" +ISO-8859-5, "ISO8859-5" +ISO-8859-6, "ISO8859-6" +ISO-8859-7, "ISO8859-7" +ISO-8859-8, "ISO8859-8" +ISO-8859-9, "ISO8859-9" +ISO-8859-15, "ISO8859-15" +CP437, "cp437" +CP775, "cp775" +CP850, "cp850" +CP852, "cp852" +CP855, "cp855" +CP857, "cp857" +CP861, "cp861" +CP862, "cp862" +CP865, "cp865" +CP866, "cp866" +CP869, "cp869" +CP874, "cp874" +CP949, "KSC5601" +CP1250, "cp1250" +CP1251, "cp1251" +CP1252, "cp1252" +CP1253, "cp1253" +CP1254, "cp1254" +CP1255, "cp1255" +CP1256, "cp1256" +CP1257, "cp1257" +CP1258, "cp1258" +EUC-JP, "eucJP" +EUC-KR, "eucKR" +EUC-TW, "eucTW" +BIG5, "big5" +SHIFT_JIS, "SJIS" +TIS-620, "TACTIS" diff --git a/gettext-tools/gnulib-lib/iconv_open-osf.h b/gettext-tools/gnulib-lib/iconv_open-osf.h new file mode 100644 index 0000000..4d35764 --- /dev/null +++ b/gettext-tools/gnulib-lib/iconv_open-osf.h @@ -0,0 +1,278 @@ +/* ANSI-C code produced by gperf version 3.0.4 */ +/* Command-line: gperf -m 10 ./iconv_open-osf.gperf */ +/* Computed positions: -k'4,$' */ + +#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ + && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \ + && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \ + && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \ + && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \ + && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \ + && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \ + && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \ + && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \ + && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \ + && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \ + && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \ + && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \ + && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \ + && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \ + && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \ + && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \ + && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \ + && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \ + && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \ + && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \ + && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \ + && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126)) +/* The character set is not based on ISO-646. */ +#error "gperf generated tables don't work with this execution character set. Please report a bug to ." +#endif + +#line 1 "./iconv_open-osf.gperf" +struct mapping { int standard_name; const char vendor_name[10 + 1]; }; + +#define TOTAL_KEYWORDS 38 +#define MIN_WORD_LENGTH 4 +#define MAX_WORD_LENGTH 11 +#define MIN_HASH_VALUE 6 +#define MAX_HASH_VALUE 47 +/* maximum key range = 42, duplicates = 0 */ + +#ifdef __GNUC__ +__inline +#else +#ifdef __cplusplus +inline +#endif +#endif +static unsigned int +mapping_hash (register const char *str, register unsigned int len) +{ + static const unsigned char asso_values[] = + { + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 2, 29, + 24, 34, 31, 0, 15, 14, 10, 13, 2, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 7, 48, 48, 48, 48, 48, 48, + 11, 48, 2, 7, 48, 48, 48, 1, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48 + }; + return len + asso_values[(unsigned char)str[3]+3] + asso_values[(unsigned char)str[len - 1]]; +} + +struct stringpool_t + { + char stringpool_str6[sizeof("CP1255")]; + char stringpool_str7[sizeof("CP775")]; + char stringpool_str8[sizeof("CP1250")]; + char stringpool_str9[sizeof("EUC-TW")]; + char stringpool_str10[sizeof("EUC-KR")]; + char stringpool_str11[sizeof("TIS-620")]; + char stringpool_str12[sizeof("ISO-8859-5")]; + char stringpool_str13[sizeof("ISO-8859-15")]; + char stringpool_str14[sizeof("BIG5")]; + char stringpool_str15[sizeof("CP855")]; + char stringpool_str16[sizeof("CP1258")]; + char stringpool_str17[sizeof("CP850")]; + char stringpool_str18[sizeof("CP865")]; + char stringpool_str19[sizeof("EUC-JP")]; + char stringpool_str20[sizeof("CP1257")]; + char stringpool_str21[sizeof("CP1256")]; + char stringpool_str22[sizeof("ISO-8859-8")]; + char stringpool_str23[sizeof("SHIFT_JIS")]; + char stringpool_str25[sizeof("ISO-8859-9")]; + char stringpool_str26[sizeof("ISO-8859-7")]; + char stringpool_str27[sizeof("ISO-8859-6")]; + char stringpool_str29[sizeof("CP857")]; + char stringpool_str30[sizeof("CP1252")]; + char stringpool_str31[sizeof("CP869")]; + char stringpool_str32[sizeof("CP949")]; + char stringpool_str33[sizeof("CP866")]; + char stringpool_str34[sizeof("CP437")]; + char stringpool_str35[sizeof("CP1251")]; + char stringpool_str36[sizeof("ISO-8859-2")]; + char stringpool_str37[sizeof("CP1254")]; + char stringpool_str38[sizeof("CP874")]; + char stringpool_str39[sizeof("CP852")]; + char stringpool_str40[sizeof("CP1253")]; + char stringpool_str41[sizeof("ISO-8859-1")]; + char stringpool_str42[sizeof("CP862")]; + char stringpool_str43[sizeof("ISO-8859-4")]; + char stringpool_str46[sizeof("ISO-8859-3")]; + char stringpool_str47[sizeof("CP861")]; + }; +static const struct stringpool_t stringpool_contents = + { + "CP1255", + "CP775", + "CP1250", + "EUC-TW", + "EUC-KR", + "TIS-620", + "ISO-8859-5", + "ISO-8859-15", + "BIG5", + "CP855", + "CP1258", + "CP850", + "CP865", + "EUC-JP", + "CP1257", + "CP1256", + "ISO-8859-8", + "SHIFT_JIS", + "ISO-8859-9", + "ISO-8859-7", + "ISO-8859-6", + "CP857", + "CP1252", + "CP869", + "CP949", + "CP866", + "CP437", + "CP1251", + "ISO-8859-2", + "CP1254", + "CP874", + "CP852", + "CP1253", + "ISO-8859-1", + "CP862", + "ISO-8859-4", + "ISO-8859-3", + "CP861" + }; +#define stringpool ((const char *) &stringpool_contents) + +static const struct mapping mappings[] = + { + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, +#line 41 "./iconv_open-osf.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str6, "cp1255"}, +#line 24 "./iconv_open-osf.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str7, "cp775"}, +#line 36 "./iconv_open-osf.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str8, "cp1250"}, +#line 47 "./iconv_open-osf.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str9, "eucTW"}, +#line 46 "./iconv_open-osf.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str10, "eucKR"}, +#line 50 "./iconv_open-osf.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str11, "TACTIS"}, +#line 17 "./iconv_open-osf.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str12, "ISO8859-5"}, +#line 22 "./iconv_open-osf.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str13, "ISO8859-15"}, +#line 48 "./iconv_open-osf.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str14, "big5"}, +#line 27 "./iconv_open-osf.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str15, "cp855"}, +#line 44 "./iconv_open-osf.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str16, "cp1258"}, +#line 25 "./iconv_open-osf.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str17, "cp850"}, +#line 31 "./iconv_open-osf.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str18, "cp865"}, +#line 45 "./iconv_open-osf.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str19, "eucJP"}, +#line 43 "./iconv_open-osf.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str20, "cp1257"}, +#line 42 "./iconv_open-osf.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str21, "cp1256"}, +#line 20 "./iconv_open-osf.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str22, "ISO8859-8"}, +#line 49 "./iconv_open-osf.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str23, "SJIS"}, + {-1}, +#line 21 "./iconv_open-osf.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str25, "ISO8859-9"}, +#line 19 "./iconv_open-osf.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str26, "ISO8859-7"}, +#line 18 "./iconv_open-osf.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str27, "ISO8859-6"}, + {-1}, +#line 28 "./iconv_open-osf.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str29, "cp857"}, +#line 38 "./iconv_open-osf.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str30, "cp1252"}, +#line 33 "./iconv_open-osf.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str31, "cp869"}, +#line 35 "./iconv_open-osf.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str32, "KSC5601"}, +#line 32 "./iconv_open-osf.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str33, "cp866"}, +#line 23 "./iconv_open-osf.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str34, "cp437"}, +#line 37 "./iconv_open-osf.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str35, "cp1251"}, +#line 14 "./iconv_open-osf.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str36, "ISO8859-2"}, +#line 40 "./iconv_open-osf.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str37, "cp1254"}, +#line 34 "./iconv_open-osf.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str38, "cp874"}, +#line 26 "./iconv_open-osf.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str39, "cp852"}, +#line 39 "./iconv_open-osf.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str40, "cp1253"}, +#line 13 "./iconv_open-osf.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str41, "ISO8859-1"}, +#line 30 "./iconv_open-osf.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str42, "cp862"}, +#line 16 "./iconv_open-osf.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str43, "ISO8859-4"}, + {-1}, {-1}, +#line 15 "./iconv_open-osf.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str46, "ISO8859-3"}, +#line 29 "./iconv_open-osf.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str47, "cp861"} + }; + +#ifdef __GNUC__ +__inline +#if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__ +__attribute__ ((__gnu_inline__)) +#endif +#endif +const struct mapping * +mapping_lookup (register const char *str, register unsigned int len) +{ + if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) + { + register int key = mapping_hash (str, len); + + if (key <= MAX_HASH_VALUE && key >= 0) + { + register int o = mappings[key].standard_name; + if (o >= 0) + { + register const char *s = o + stringpool; + + if (*str == *s && !strcmp (str + 1, s + 1)) + return &mappings[key]; + } + } + } + return 0; +} diff --git a/gettext-tools/gnulib-lib/iconv_open-solaris.gperf b/gettext-tools/gnulib-lib/iconv_open-solaris.gperf new file mode 100644 index 0000000..7d7da38 --- /dev/null +++ b/gettext-tools/gnulib-lib/iconv_open-solaris.gperf @@ -0,0 +1,30 @@ +struct mapping { int standard_name; const char vendor_name[10 + 1]; }; +%struct-type +%language=ANSI-C +%define slot-name standard_name +%define hash-function-name mapping_hash +%define lookup-function-name mapping_lookup +%readonly-tables +%global-table +%define word-array-name mappings +%pic +%% +# On Solaris 10, look in the "iconv -l" output. Some aliases are advertised but +# not actually supported by the iconv() function and by the 'iconv' program. +# For example: +# $ echo abc | iconv -f 646 -t ISO-8859-1 +# Not supported 646 to ISO-8859-1 +# $ echo abc | iconv -f 646 -t ISO8859-1 +$ abc +ASCII, "646" +ISO-8859-1, "ISO8859-1" +ISO-8859-2, "ISO8859-2" +ISO-8859-3, "ISO8859-3" +ISO-8859-4, "ISO8859-4" +ISO-8859-5, "ISO8859-5" +ISO-8859-6, "ISO8859-6" +ISO-8859-7, "ISO8859-7" +ISO-8859-8, "ISO8859-8" +ISO-8859-9, "ISO8859-9" +ISO-8859-15, "ISO8859-15" +CP1251, "ansi-1251" diff --git a/gettext-tools/gnulib-lib/iconv_open-solaris.h b/gettext-tools/gnulib-lib/iconv_open-solaris.h new file mode 100644 index 0000000..630cde1 --- /dev/null +++ b/gettext-tools/gnulib-lib/iconv_open-solaris.h @@ -0,0 +1,190 @@ +/* ANSI-C code produced by gperf version 3.0.4 */ +/* Command-line: gperf -m 10 ./iconv_open-solaris.gperf */ +/* Computed positions: -k'10' */ + +#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ + && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \ + && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \ + && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \ + && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \ + && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \ + && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \ + && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \ + && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \ + && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \ + && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \ + && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \ + && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \ + && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \ + && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \ + && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \ + && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \ + && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \ + && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \ + && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \ + && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \ + && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \ + && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126)) +/* The character set is not based on ISO-646. */ +#error "gperf generated tables don't work with this execution character set. Please report a bug to ." +#endif + +#line 1 "./iconv_open-solaris.gperf" +struct mapping { int standard_name; const char vendor_name[10 + 1]; }; + +#define TOTAL_KEYWORDS 13 +#define MIN_WORD_LENGTH 5 +#define MAX_WORD_LENGTH 11 +#define MIN_HASH_VALUE 5 +#define MAX_HASH_VALUE 19 +/* maximum key range = 15, duplicates = 0 */ + +#ifdef __GNUC__ +__inline +#else +#ifdef __cplusplus +inline +#endif +#endif +static unsigned int +mapping_hash (register const char *str, register unsigned int len) +{ + static const unsigned char asso_values[] = + { + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, + 9, 8, 7, 6, 5, 4, 3, 2, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20 + }; + register int hval = len; + + switch (hval) + { + default: + hval += asso_values[(unsigned char)str[9]]; + /*FALLTHROUGH*/ + case 9: + case 8: + case 7: + case 6: + case 5: + break; + } + return hval; +} + +struct stringpool_t + { + char stringpool_str5[sizeof("ASCII")]; + char stringpool_str6[sizeof("CP1251")]; + char stringpool_str7[sizeof("$ abc")]; + char stringpool_str10[sizeof("ISO-8859-1")]; + char stringpool_str11[sizeof("ISO-8859-15")]; + char stringpool_str12[sizeof("ISO-8859-9")]; + char stringpool_str13[sizeof("ISO-8859-8")]; + char stringpool_str14[sizeof("ISO-8859-7")]; + char stringpool_str15[sizeof("ISO-8859-6")]; + char stringpool_str16[sizeof("ISO-8859-5")]; + char stringpool_str17[sizeof("ISO-8859-4")]; + char stringpool_str18[sizeof("ISO-8859-3")]; + char stringpool_str19[sizeof("ISO-8859-2")]; + }; +static const struct stringpool_t stringpool_contents = + { + "ASCII", + "CP1251", + "$ abc", + "ISO-8859-1", + "ISO-8859-15", + "ISO-8859-9", + "ISO-8859-8", + "ISO-8859-7", + "ISO-8859-6", + "ISO-8859-5", + "ISO-8859-4", + "ISO-8859-3", + "ISO-8859-2" + }; +#define stringpool ((const char *) &stringpool_contents) + +static const struct mapping mappings[] = + { + {-1}, {-1}, {-1}, {-1}, {-1}, +#line 19 "./iconv_open-solaris.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str5, "646"}, +#line 30 "./iconv_open-solaris.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str6, "ansi-1251"}, +#line 18 "./iconv_open-solaris.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str7}, + {-1}, {-1}, +#line 20 "./iconv_open-solaris.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str10, "ISO8859-1"}, +#line 29 "./iconv_open-solaris.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str11, "ISO8859-15"}, +#line 28 "./iconv_open-solaris.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str12, "ISO8859-9"}, +#line 27 "./iconv_open-solaris.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str13, "ISO8859-8"}, +#line 26 "./iconv_open-solaris.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str14, "ISO8859-7"}, +#line 25 "./iconv_open-solaris.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str15, "ISO8859-6"}, +#line 24 "./iconv_open-solaris.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str16, "ISO8859-5"}, +#line 23 "./iconv_open-solaris.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str17, "ISO8859-4"}, +#line 22 "./iconv_open-solaris.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str18, "ISO8859-3"}, +#line 21 "./iconv_open-solaris.gperf" + {(int)(long)&((struct stringpool_t *)0)->stringpool_str19, "ISO8859-2"} + }; + +#ifdef __GNUC__ +__inline +#if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__ +__attribute__ ((__gnu_inline__)) +#endif +#endif +const struct mapping * +mapping_lookup (register const char *str, register unsigned int len) +{ + if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) + { + register int key = mapping_hash (str, len); + + if (key <= MAX_HASH_VALUE && key >= 0) + { + register int o = mappings[key].standard_name; + if (o >= 0) + { + register const char *s = o + stringpool; + + if (*str == *s && !strcmp (str + 1, s + 1)) + return &mappings[key]; + } + } + } + return 0; +} diff --git a/gettext-tools/gnulib-lib/iconv_open.c b/gettext-tools/gnulib-lib/iconv_open.c new file mode 100644 index 0000000..37ce9ce --- /dev/null +++ b/gettext-tools/gnulib-lib/iconv_open.c @@ -0,0 +1,172 @@ +/* Character set conversion. + Copyright (C) 2007, 2009-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, see . */ + +#include + +/* Specification. */ +#include + +#include +#include +#include "c-ctype.h" +#include "c-strcase.h" + +#define SIZEOF(a) (sizeof(a) / sizeof(a[0])) + +/* Namespace cleanliness. */ +#define mapping_lookup rpl_iconv_open_mapping_lookup + +/* The macro ICONV_FLAVOR is defined to one of these or undefined. */ + +#define ICONV_FLAVOR_AIX "iconv_open-aix.h" +#define ICONV_FLAVOR_HPUX "iconv_open-hpux.h" +#define ICONV_FLAVOR_IRIX "iconv_open-irix.h" +#define ICONV_FLAVOR_OSF "iconv_open-osf.h" +#define ICONV_FLAVOR_SOLARIS "iconv_open-solaris.h" + +#ifdef ICONV_FLAVOR +# include ICONV_FLAVOR +#endif + +iconv_t +rpl_iconv_open (const char *tocode, const char *fromcode) +#undef iconv_open +{ + char fromcode_upper[32]; + char tocode_upper[32]; + char *fromcode_upper_end; + char *tocode_upper_end; + +#if REPLACE_ICONV_UTF + /* Special handling of conversion between UTF-8 and UTF-{16,32}{BE,LE}. + Do this here, before calling the real iconv_open(), because OSF/1 5.1 + iconv() to these encoding inserts a BOM, which is wrong. + We do not need to handle conversion between arbitrary encodings and + UTF-{16,32}{BE,LE}, because the 'striconveh' module implements two-step + conversion through UTF-8. + The _ICONV_* constants are chosen to be disjoint from any iconv_t + returned by the system's iconv_open() functions. Recall that iconv_t + is a scalar type. */ + if (c_toupper (fromcode[0]) == 'U' + && c_toupper (fromcode[1]) == 'T' + && c_toupper (fromcode[2]) == 'F' + && fromcode[3] == '-') + { + if (c_toupper (tocode[0]) == 'U' + && c_toupper (tocode[1]) == 'T' + && c_toupper (tocode[2]) == 'F' + && tocode[3] == '-') + { + if (strcmp (fromcode + 4, "8") == 0) + { + if (c_strcasecmp (tocode + 4, "16BE") == 0) + return _ICONV_UTF8_UTF16BE; + if (c_strcasecmp (tocode + 4, "16LE") == 0) + return _ICONV_UTF8_UTF16LE; + if (c_strcasecmp (tocode + 4, "32BE") == 0) + return _ICONV_UTF8_UTF32BE; + if (c_strcasecmp (tocode + 4, "32LE") == 0) + return _ICONV_UTF8_UTF32LE; + } + else if (strcmp (tocode + 4, "8") == 0) + { + if (c_strcasecmp (fromcode + 4, "16BE") == 0) + return _ICONV_UTF16BE_UTF8; + if (c_strcasecmp (fromcode + 4, "16LE") == 0) + return _ICONV_UTF16LE_UTF8; + if (c_strcasecmp (fromcode + 4, "32BE") == 0) + return _ICONV_UTF32BE_UTF8; + if (c_strcasecmp (fromcode + 4, "32LE") == 0) + return _ICONV_UTF32LE_UTF8; + } + } + } +#endif + + /* Do *not* add special support for 8-bit encodings like ASCII or ISO-8859-1 + here. This would lead to programs that work in some locales (such as the + "C" or "en_US" locales) but do not work in East Asian locales. It is + better if programmers make their programs depend on GNU libiconv (except + on glibc systems), e.g. by using the AM_ICONV macro and documenting the + dependency in an INSTALL or DEPENDENCIES file. */ + + /* Try with the original names first. + This covers the case when fromcode or tocode is a lowercase encoding name + that is understood by the system's iconv_open but not listed in our + mappings table. */ + { + iconv_t cd = iconv_open (tocode, fromcode); + if (cd != (iconv_t)(-1)) + return cd; + } + + /* Convert the encodings to upper case, because + 1. in the arguments of iconv_open() on AIX, HP-UX, and OSF/1 the case + matters, + 2. it makes searching in the table faster. */ + { + const char *p = fromcode; + char *q = fromcode_upper; + while ((*q = c_toupper (*p)) != '\0') + { + p++; + q++; + if (q == &fromcode_upper[SIZEOF (fromcode_upper)]) + { + errno = EINVAL; + return (iconv_t)(-1); + } + } + fromcode_upper_end = q; + } + + { + const char *p = tocode; + char *q = tocode_upper; + while ((*q = c_toupper (*p)) != '\0') + { + p++; + q++; + if (q == &tocode_upper[SIZEOF (tocode_upper)]) + { + errno = EINVAL; + return (iconv_t)(-1); + } + } + tocode_upper_end = q; + } + +#ifdef ICONV_FLAVOR + /* Apply the mappings. */ + { + const struct mapping *m = + mapping_lookup (fromcode_upper, fromcode_upper_end - fromcode_upper); + + fromcode = (m != NULL ? m->vendor_name : fromcode_upper); + } + { + const struct mapping *m = + mapping_lookup (tocode_upper, tocode_upper_end - tocode_upper); + + tocode = (m != NULL ? m->vendor_name : tocode_upper); + } +#else + fromcode = fromcode_upper; + tocode = tocode_upper; +#endif + + return iconv_open (tocode, fromcode); +} diff --git a/gettext-tools/gnulib-lib/iconveh.h b/gettext-tools/gnulib-lib/iconveh.h new file mode 100644 index 0000000..9deaea1 --- /dev/null +++ b/gettext-tools/gnulib-lib/iconveh.h @@ -0,0 +1,41 @@ +/* Character set conversion handler type. + Copyright (C) 2001-2007, 2009-2014 Free Software Foundation, Inc. + Written by Bruno Haible. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _ICONVEH_H +#define _ICONVEH_H + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Handling of unconvertible characters. */ +enum iconv_ilseq_handler +{ + iconveh_error, /* return and set errno = EILSEQ */ + iconveh_question_mark, /* use one '?' per unconvertible character */ + iconveh_escape_sequence /* use escape sequence \uxxxx or \Uxxxxxxxx */ +}; + + +#ifdef __cplusplus +} +#endif + + +#endif /* _ICONVEH_H */ diff --git a/gettext-tools/gnulib-lib/ignore-value.h b/gettext-tools/gnulib-lib/ignore-value.h new file mode 100644 index 0000000..4dd0946 --- /dev/null +++ b/gettext-tools/gnulib-lib/ignore-value.h @@ -0,0 +1,50 @@ +/* ignore a function return without a compiler warning + + Copyright (C) 2008-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Written by Jim Meyering, Eric Blake and Pádraig Brady. */ + +/* Use "ignore_value" to avoid a warning when using a function declared with + gcc's warn_unused_result attribute, but for which you really do want to + ignore the result. Traditionally, people have used a "(void)" cast to + indicate that a function's return value is deliberately unused. However, + if the function is declared with __attribute__((warn_unused_result)), + gcc issues a warning even with the cast. + + Caution: most of the time, you really should heed gcc's warning, and + check the return value. However, in those exceptional cases in which + you're sure you know what you're doing, use this function. + + For the record, here's one of the ignorable warnings: + "copy.c:233: warning: ignoring return value of 'fchown', + declared with attribute warn_unused_result". */ + +#ifndef _GL_IGNORE_VALUE_H +#define _GL_IGNORE_VALUE_H + +/* Normally casting an expression to void discards its value, but GCC + versions 3.4 and newer have __attribute__ ((__warn_unused_result__)) + which may cause unwanted diagnostics in that case. Use __typeof__ + and __extension__ to work around the problem, if the workaround is + known to be needed. */ +#if 3 < __GNUC__ + (4 <= __GNUC_MINOR__) +# define ignore_value(x) \ + (__extension__ ({ __typeof__ (x) __x = (x); (void) __x; })) +#else +# define ignore_value(x) ((void) (x)) +#endif + +#endif diff --git a/gettext-tools/gnulib-lib/intprops.h b/gettext-tools/gnulib-lib/intprops.h new file mode 100644 index 0000000..d0bb7a6 --- /dev/null +++ b/gettext-tools/gnulib-lib/intprops.h @@ -0,0 +1,320 @@ +/* intprops.h -- properties of integer types + + Copyright (C) 2001-2005, 2009-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Written by Paul Eggert. */ + +#ifndef _GL_INTPROPS_H +#define _GL_INTPROPS_H + +#include + +/* Return an integer value, converted to the same type as the integer + expression E after integer type promotion. V is the unconverted value. */ +#define _GL_INT_CONVERT(e, v) (0 * (e) + (v)) + +/* Act like _GL_INT_CONVERT (E, -V) but work around a bug in IRIX 6.5 cc; see + . */ +#define _GL_INT_NEGATE_CONVERT(e, v) (0 * (e) - (v)) + +/* The extra casts in the following macros work around compiler bugs, + e.g., in Cray C 5.0.3.0. */ + +/* True if the arithmetic type T is an integer type. bool counts as + an integer. */ +#define TYPE_IS_INTEGER(t) ((t) 1.5 == 1) + +/* True if negative values of the signed integer type T use two's + complement, ones' complement, or signed magnitude representation, + respectively. Much GNU code assumes two's complement, but some + people like to be portable to all possible C hosts. */ +#define TYPE_TWOS_COMPLEMENT(t) ((t) ~ (t) 0 == (t) -1) +#define TYPE_ONES_COMPLEMENT(t) ((t) ~ (t) 0 == 0) +#define TYPE_SIGNED_MAGNITUDE(t) ((t) ~ (t) 0 < (t) -1) + +/* True if the signed integer expression E uses two's complement. */ +#define _GL_INT_TWOS_COMPLEMENT(e) (~ _GL_INT_CONVERT (e, 0) == -1) + +/* True if the arithmetic type T is signed. */ +#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1)) + +/* Return 1 if the integer expression E, after integer promotion, has + a signed type. */ +#define _GL_INT_SIGNED(e) (_GL_INT_NEGATE_CONVERT (e, 1) < 0) + + +/* Minimum and maximum values for integer types and expressions. These + macros have undefined behavior if T is signed and has padding bits. + If this is a problem for you, please let us know how to fix it for + your host. */ + +/* The maximum and minimum values for the integer type T. */ +#define TYPE_MINIMUM(t) \ + ((t) (! TYPE_SIGNED (t) \ + ? (t) 0 \ + : TYPE_SIGNED_MAGNITUDE (t) \ + ? ~ (t) 0 \ + : ~ TYPE_MAXIMUM (t))) +#define TYPE_MAXIMUM(t) \ + ((t) (! TYPE_SIGNED (t) \ + ? (t) -1 \ + : ((((t) 1 << (sizeof (t) * CHAR_BIT - 2)) - 1) * 2 + 1))) + +/* The maximum and minimum values for the type of the expression E, + after integer promotion. E should not have side effects. */ +#define _GL_INT_MINIMUM(e) \ + (_GL_INT_SIGNED (e) \ + ? - _GL_INT_TWOS_COMPLEMENT (e) - _GL_SIGNED_INT_MAXIMUM (e) \ + : _GL_INT_CONVERT (e, 0)) +#define _GL_INT_MAXIMUM(e) \ + (_GL_INT_SIGNED (e) \ + ? _GL_SIGNED_INT_MAXIMUM (e) \ + : _GL_INT_NEGATE_CONVERT (e, 1)) +#define _GL_SIGNED_INT_MAXIMUM(e) \ + (((_GL_INT_CONVERT (e, 1) << (sizeof ((e) + 0) * CHAR_BIT - 2)) - 1) * 2 + 1) + + +/* Return 1 if the __typeof__ keyword works. This could be done by + 'configure', but for now it's easier to do it by hand. */ +#if (2 <= __GNUC__ || defined __IBM__TYPEOF__ \ + || (0x5110 <= __SUNPRO_C && !__STDC__)) +# define _GL_HAVE___TYPEOF__ 1 +#else +# define _GL_HAVE___TYPEOF__ 0 +#endif + +/* Return 1 if the integer type or expression T might be signed. Return 0 + if it is definitely unsigned. This macro does not evaluate its argument, + and expands to an integer constant expression. */ +#if _GL_HAVE___TYPEOF__ +# define _GL_SIGNED_TYPE_OR_EXPR(t) TYPE_SIGNED (__typeof__ (t)) +#else +# define _GL_SIGNED_TYPE_OR_EXPR(t) 1 +#endif + +/* Bound on length of the string representing an unsigned integer + value representable in B bits. log10 (2.0) < 146/485. The + smallest value of B where this bound is not tight is 2621. */ +#define INT_BITS_STRLEN_BOUND(b) (((b) * 146 + 484) / 485) + +/* Bound on length of the string representing an integer type or expression T. + Subtract 1 for the sign bit if T is signed, and then add 1 more for + a minus sign if needed. + + Because _GL_SIGNED_TYPE_OR_EXPR sometimes returns 0 when its argument is + signed, this macro may overestimate the true bound by one byte when + applied to unsigned types of size 2, 4, 16, ... bytes. */ +#define INT_STRLEN_BOUND(t) \ + (INT_BITS_STRLEN_BOUND (sizeof (t) * CHAR_BIT \ + - _GL_SIGNED_TYPE_OR_EXPR (t)) \ + + _GL_SIGNED_TYPE_OR_EXPR (t)) + +/* Bound on buffer size needed to represent an integer type or expression T, + including the terminating null. */ +#define INT_BUFSIZE_BOUND(t) (INT_STRLEN_BOUND (t) + 1) + + +/* Range overflow checks. + + The INT__RANGE_OVERFLOW macros return 1 if the corresponding C + operators might not yield numerically correct answers due to + arithmetic overflow. They do not rely on undefined or + implementation-defined behavior. Their implementations are simple + and straightforward, but they are a bit harder to use than the + INT__OVERFLOW macros described below. + + Example usage: + + long int i = ...; + long int j = ...; + if (INT_MULTIPLY_RANGE_OVERFLOW (i, j, LONG_MIN, LONG_MAX)) + printf ("multiply would overflow"); + else + printf ("product is %ld", i * j); + + Restrictions on *_RANGE_OVERFLOW macros: + + These macros do not check for all possible numerical problems or + undefined or unspecified behavior: they do not check for division + by zero, for bad shift counts, or for shifting negative numbers. + + These macros may evaluate their arguments zero or multiple times, + so the arguments should not have side effects. The arithmetic + arguments (including the MIN and MAX arguments) must be of the same + integer type after the usual arithmetic conversions, and the type + must have minimum value MIN and maximum MAX. Unsigned types should + use a zero MIN of the proper type. + + These macros are tuned for constant MIN and MAX. For commutative + operations such as A + B, they are also tuned for constant B. */ + +/* Return 1 if A + B would overflow in [MIN,MAX] arithmetic. + See above for restrictions. */ +#define INT_ADD_RANGE_OVERFLOW(a, b, min, max) \ + ((b) < 0 \ + ? (a) < (min) - (b) \ + : (max) - (b) < (a)) + +/* Return 1 if A - B would overflow in [MIN,MAX] arithmetic. + See above for restrictions. */ +#define INT_SUBTRACT_RANGE_OVERFLOW(a, b, min, max) \ + ((b) < 0 \ + ? (max) + (b) < (a) \ + : (a) < (min) + (b)) + +/* Return 1 if - A would overflow in [MIN,MAX] arithmetic. + See above for restrictions. */ +#define INT_NEGATE_RANGE_OVERFLOW(a, min, max) \ + ((min) < 0 \ + ? (a) < - (max) \ + : 0 < (a)) + +/* Return 1 if A * B would overflow in [MIN,MAX] arithmetic. + See above for restrictions. Avoid && and || as they tickle + bugs in Sun C 5.11 2010/08/13 and other compilers; see + . */ +#define INT_MULTIPLY_RANGE_OVERFLOW(a, b, min, max) \ + ((b) < 0 \ + ? ((a) < 0 \ + ? (a) < (max) / (b) \ + : (b) == -1 \ + ? 0 \ + : (min) / (b) < (a)) \ + : (b) == 0 \ + ? 0 \ + : ((a) < 0 \ + ? (a) < (min) / (b) \ + : (max) / (b) < (a))) + +/* Return 1 if A / B would overflow in [MIN,MAX] arithmetic. + See above for restrictions. Do not check for division by zero. */ +#define INT_DIVIDE_RANGE_OVERFLOW(a, b, min, max) \ + ((min) < 0 && (b) == -1 && (a) < - (max)) + +/* Return 1 if A % B would overflow in [MIN,MAX] arithmetic. + See above for restrictions. Do not check for division by zero. + Mathematically, % should never overflow, but on x86-like hosts + INT_MIN % -1 traps, and the C standard permits this, so treat this + as an overflow too. */ +#define INT_REMAINDER_RANGE_OVERFLOW(a, b, min, max) \ + INT_DIVIDE_RANGE_OVERFLOW (a, b, min, max) + +/* Return 1 if A << B would overflow in [MIN,MAX] arithmetic. + See above for restrictions. Here, MIN and MAX are for A only, and B need + not be of the same type as the other arguments. The C standard says that + behavior is undefined for shifts unless 0 <= B < wordwidth, and that when + A is negative then A << B has undefined behavior and A >> B has + implementation-defined behavior, but do not check these other + restrictions. */ +#define INT_LEFT_SHIFT_RANGE_OVERFLOW(a, b, min, max) \ + ((a) < 0 \ + ? (a) < (min) >> (b) \ + : (max) >> (b) < (a)) + + +/* The _GL*_OVERFLOW macros have the same restrictions as the + *_RANGE_OVERFLOW macros, except that they do not assume that operands + (e.g., A and B) have the same type as MIN and MAX. Instead, they assume + that the result (e.g., A + B) has that type. */ +#define _GL_ADD_OVERFLOW(a, b, min, max) \ + ((min) < 0 ? INT_ADD_RANGE_OVERFLOW (a, b, min, max) \ + : (a) < 0 ? (b) <= (a) + (b) \ + : (b) < 0 ? (a) <= (a) + (b) \ + : (a) + (b) < (b)) +#define _GL_SUBTRACT_OVERFLOW(a, b, min, max) \ + ((min) < 0 ? INT_SUBTRACT_RANGE_OVERFLOW (a, b, min, max) \ + : (a) < 0 ? 1 \ + : (b) < 0 ? (a) - (b) <= (a) \ + : (a) < (b)) +#define _GL_MULTIPLY_OVERFLOW(a, b, min, max) \ + (((min) == 0 && (((a) < 0 && 0 < (b)) || ((b) < 0 && 0 < (a)))) \ + || INT_MULTIPLY_RANGE_OVERFLOW (a, b, min, max)) +#define _GL_DIVIDE_OVERFLOW(a, b, min, max) \ + ((min) < 0 ? (b) == _GL_INT_NEGATE_CONVERT (min, 1) && (a) < - (max) \ + : (a) < 0 ? (b) <= (a) + (b) - 1 \ + : (b) < 0 && (a) + (b) <= (a)) +#define _GL_REMAINDER_OVERFLOW(a, b, min, max) \ + ((min) < 0 ? (b) == _GL_INT_NEGATE_CONVERT (min, 1) && (a) < - (max) \ + : (a) < 0 ? (a) % (b) != ((max) - (b) + 1) % (b) \ + : (b) < 0 && ! _GL_UNSIGNED_NEG_MULTIPLE (a, b, max)) + +/* Return a nonzero value if A is a mathematical multiple of B, where + A is unsigned, B is negative, and MAX is the maximum value of A's + type. A's type must be the same as (A % B)'s type. Normally (A % + -B == 0) suffices, but things get tricky if -B would overflow. */ +#define _GL_UNSIGNED_NEG_MULTIPLE(a, b, max) \ + (((b) < -_GL_SIGNED_INT_MAXIMUM (b) \ + ? (_GL_SIGNED_INT_MAXIMUM (b) == (max) \ + ? (a) \ + : (a) % (_GL_INT_CONVERT (a, _GL_SIGNED_INT_MAXIMUM (b)) + 1)) \ + : (a) % - (b)) \ + == 0) + + +/* Integer overflow checks. + + The INT__OVERFLOW macros return 1 if the corresponding C operators + might not yield numerically correct answers due to arithmetic overflow. + They work correctly on all known practical hosts, and do not rely + on undefined behavior due to signed arithmetic overflow. + + Example usage: + + long int i = ...; + long int j = ...; + if (INT_MULTIPLY_OVERFLOW (i, j)) + printf ("multiply would overflow"); + else + printf ("product is %ld", i * j); + + These macros do not check for all possible numerical problems or + undefined or unspecified behavior: they do not check for division + by zero, for bad shift counts, or for shifting negative numbers. + + These macros may evaluate their arguments zero or multiple times, so the + arguments should not have side effects. + + These macros are tuned for their last argument being a constant. + + Return 1 if the integer expressions A * B, A - B, -A, A * B, A / B, + A % B, and A << B would overflow, respectively. */ + +#define INT_ADD_OVERFLOW(a, b) \ + _GL_BINARY_OP_OVERFLOW (a, b, _GL_ADD_OVERFLOW) +#define INT_SUBTRACT_OVERFLOW(a, b) \ + _GL_BINARY_OP_OVERFLOW (a, b, _GL_SUBTRACT_OVERFLOW) +#define INT_NEGATE_OVERFLOW(a) \ + INT_NEGATE_RANGE_OVERFLOW (a, _GL_INT_MINIMUM (a), _GL_INT_MAXIMUM (a)) +#define INT_MULTIPLY_OVERFLOW(a, b) \ + _GL_BINARY_OP_OVERFLOW (a, b, _GL_MULTIPLY_OVERFLOW) +#define INT_DIVIDE_OVERFLOW(a, b) \ + _GL_BINARY_OP_OVERFLOW (a, b, _GL_DIVIDE_OVERFLOW) +#define INT_REMAINDER_OVERFLOW(a, b) \ + _GL_BINARY_OP_OVERFLOW (a, b, _GL_REMAINDER_OVERFLOW) +#define INT_LEFT_SHIFT_OVERFLOW(a, b) \ + INT_LEFT_SHIFT_RANGE_OVERFLOW (a, b, \ + _GL_INT_MINIMUM (a), _GL_INT_MAXIMUM (a)) + +/* Return 1 if the expression A B would overflow, + where OP_RESULT_OVERFLOW (A, B, MIN, MAX) does the actual test, + assuming MIN and MAX are the minimum and maximum for the result type. + Arguments should be free of side effects. */ +#define _GL_BINARY_OP_OVERFLOW(a, b, op_result_overflow) \ + op_result_overflow (a, b, \ + _GL_INT_MINIMUM (0 * (b) + (a)), \ + _GL_INT_MAXIMUM (0 * (b) + (a))) + +#endif /* _GL_INTPROPS_H */ diff --git a/gettext-tools/gnulib-lib/iswblank.c b/gettext-tools/gnulib-lib/iswblank.c new file mode 100644 index 0000000..9c1672f --- /dev/null +++ b/gettext-tools/gnulib-lib/iswblank.c @@ -0,0 +1,26 @@ +/* Test wide character for being blank. + Copyright (C) 2008-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, see . */ + +#include + +/* Specification. */ +#include + +int +iswblank (wint_t wc) +{ + return wc == ' ' || wc == '\t'; +} diff --git a/gettext-tools/gnulib-lib/itold.c b/gettext-tools/gnulib-lib/itold.c new file mode 100644 index 0000000..937f480 --- /dev/null +++ b/gettext-tools/gnulib-lib/itold.c @@ -0,0 +1,28 @@ +/* Replacement for 'int' to 'long double' conversion routine. + Copyright (C) 2011-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2011. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include + +void +_Qp_itoq (long double *result, int a) +{ + /* Convert from 'int' to 'double', then from 'double' to 'long double'. */ + *result = (double) a; +} diff --git a/gettext-tools/gnulib-lib/javacomp.c b/gettext-tools/gnulib-lib/javacomp.c new file mode 100644 index 0000000..f54fb59 --- /dev/null +++ b/gettext-tools/gnulib-lib/javacomp.c @@ -0,0 +1,2350 @@ +/* Compile a Java program. + Copyright (C) 2001-2003, 2006-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2001. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include +#include + +/* Specification. */ +#include "javacomp.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "javaversion.h" +#include "execute.h" +#include "spawn-pipe.h" +#include "wait-process.h" +#include "classpath.h" +#include "xsetenv.h" +#include "sh-quote.h" +#include "binary-io.h" +#include "safe-read.h" +#include "xalloc.h" +#include "xmalloca.h" +#include "concat-filename.h" +#include "fwriteerror.h" +#include "clean-temp.h" +#include "error.h" +#include "xvasprintf.h" +#include "c-strstr.h" +#include "gettext.h" + +#define _(str) gettext (str) + + +/* Survey of Java compilers. + + A = does it work without CLASSPATH being set + C = option to set CLASSPATH, other than setting it in the environment + O = option for optimizing + g = option for debugging + T = test for presence + + Program from A C O g T + + $JAVAC unknown N n/a -O -g true + gcj -C GCC 3.2 Y --classpath=P -O -g gcj --version | sed -e 's,^[^0-9]*,,' -e 1q | sed -e '/^3\.[01]/d' | grep '^[3-9]' >/dev/null + javac JDK 1.1.8 Y -classpath P -O -g javac 2>/dev/null; test $? = 1 + javac JDK 1.3.0 Y -classpath P -O -g javac 2>/dev/null; test $? -le 2 + jikes Jikes 1.14 N -classpath P -O -g jikes 2>/dev/null; test $? = 1 + + All compilers support the option "-d DIRECTORY" for the base directory + of the classes to be written. + + The CLASSPATH is a colon separated list of pathnames. (On Windows: a + semicolon separated list of pathnames.) + + We try the Java compilers in the following order: + 1. getenv ("JAVAC"), because the user must be able to override our + preferences, + 2. "gcj -C", because it is a completely free compiler, + 3. "javac", because it is a standard compiler, + 4. "jikes", comes last because it has some deviating interpretation + of the Java Language Specification and because it requires a + CLASSPATH environment variable. + + We unset the JAVA_HOME environment variable, because a wrong setting of + this variable can confuse the JDK's javac. + */ + +/* Return the default target_version. */ +static const char * +default_target_version (void) +{ + /* Use a cache. Assumes that the PATH environment variable doesn't change + during the lifetime of the program. */ + static const char *java_version_cache; + if (java_version_cache == NULL) + { + /* Determine the version from the found JVM. */ + java_version_cache = javaexec_version (); + if (java_version_cache == NULL + || !(java_version_cache[0] == '1' && java_version_cache[1] == '.' + && (java_version_cache[2] >= '1' && java_version_cache[2] <= '6') + && java_version_cache[3] == '\0')) + java_version_cache = "1.1"; + } + return java_version_cache; +} + +/* ======================= Source version dependent ======================= */ + +/* Convert a source version to an index. */ +#define SOURCE_VERSION_BOUND 3 /* exclusive upper bound */ +static unsigned int +source_version_index (const char *source_version) +{ + if (source_version[0] == '1' && source_version[1] == '.' + && (source_version[2] >= '3' && source_version[2] <= '5') + && source_version[3] == '\0') + return source_version[2] - '3'; + error (EXIT_FAILURE, 0, _("invalid source_version argument to compile_java_class")); + return 0; +} + +/* Return a snippet of code that should compile in the given source version. */ +static const char * +get_goodcode_snippet (const char *source_version) +{ + if (strcmp (source_version, "1.3") == 0) + return "class conftest {}\n"; + if (strcmp (source_version, "1.4") == 0) + return "class conftest { static { assert(true); } }\n"; + if (strcmp (source_version, "1.5") == 0) + return "class conftest { T foo() { return null; } }\n"; + error (EXIT_FAILURE, 0, _("invalid source_version argument to compile_java_class")); + return NULL; +} + +/* Return a snippet of code that should fail to compile in the given source + version, or NULL (standing for a snippet that would fail to compile with + any compiler). */ +static const char * +get_failcode_snippet (const char *source_version) +{ + if (strcmp (source_version, "1.3") == 0) + return "class conftestfail { static { assert(true); } }\n"; + if (strcmp (source_version, "1.4") == 0) + return "class conftestfail { T foo() { return null; } }\n"; + if (strcmp (source_version, "1.5") == 0) + return NULL; + error (EXIT_FAILURE, 0, _("invalid source_version argument to compile_java_class")); + return NULL; +} + +/* ======================= Target version dependent ======================= */ + +/* Convert a target version to an index. */ +#define TARGET_VERSION_BOUND 6 /* exclusive upper bound */ +static unsigned int +target_version_index (const char *target_version) +{ + if (target_version[0] == '1' && target_version[1] == '.' + && (target_version[2] >= '1' && target_version[2] <= '6') + && target_version[3] == '\0') + return target_version[2] - '1'; + error (EXIT_FAILURE, 0, _("invalid target_version argument to compile_java_class")); + return 0; +} + +/* Return the class file version number corresponding to a given target + version. */ +static int +corresponding_classfile_version (const char *target_version) +{ + if (strcmp (target_version, "1.1") == 0) + return 45; + if (strcmp (target_version, "1.2") == 0) + return 46; + if (strcmp (target_version, "1.3") == 0) + return 47; + if (strcmp (target_version, "1.4") == 0) + return 48; + if (strcmp (target_version, "1.5") == 0) + return 49; + if (strcmp (target_version, "1.6") == 0) + return 50; + error (EXIT_FAILURE, 0, _("invalid target_version argument to compile_java_class")); + return 0; +} + +/* ======================== Compilation subroutines ======================== */ + +/* Try to compile a set of Java sources with $JAVAC. + Return a failure indicator (true upon error). */ +static bool +compile_using_envjavac (const char *javac, + const char * const *java_sources, + unsigned int java_sources_count, + const char *directory, + bool optimize, bool debug, + bool verbose, bool null_stderr) +{ + /* Because $JAVAC may consist of a command and options, we use the + shell. Because $JAVAC has been set by the user, we leave all + environment variables in place, including JAVA_HOME, and we don't + erase the user's CLASSPATH. */ + bool err; + unsigned int command_length; + char *command; + char *argv[4]; + int exitstatus; + unsigned int i; + char *p; + + command_length = strlen (javac); + if (optimize) + command_length += 3; + if (debug) + command_length += 3; + if (directory != NULL) + command_length += 4 + shell_quote_length (directory); + for (i = 0; i < java_sources_count; i++) + command_length += 1 + shell_quote_length (java_sources[i]); + command_length += 1; + + command = (char *) xmalloca (command_length); + p = command; + /* Don't shell_quote $JAVAC, because it may consist of a command + and options. */ + memcpy (p, javac, strlen (javac)); + p += strlen (javac); + if (optimize) + { + memcpy (p, " -O", 3); + p += 3; + } + if (debug) + { + memcpy (p, " -g", 3); + p += 3; + } + if (directory != NULL) + { + memcpy (p, " -d ", 4); + p += 4; + p = shell_quote_copy (p, directory); + } + for (i = 0; i < java_sources_count; i++) + { + *p++ = ' '; + p = shell_quote_copy (p, java_sources[i]); + } + *p++ = '\0'; + /* Ensure command_length was correctly calculated. */ + if (p - command > command_length) + abort (); + + if (verbose) + printf ("%s\n", command); + + argv[0] = "/bin/sh"; + argv[1] = "-c"; + argv[2] = command; + argv[3] = NULL; + exitstatus = execute (javac, "/bin/sh", argv, false, false, false, + null_stderr, true, true, NULL); + err = (exitstatus != 0); + + freea (command); + + return err; +} + +/* Try to compile a set of Java sources with gcj. + Return a failure indicator (true upon error). */ +static bool +compile_using_gcj (const char * const *java_sources, + unsigned int java_sources_count, + bool no_assert_option, + bool fsource_option, const char *source_version, + bool ftarget_option, const char *target_version, + const char *directory, + bool optimize, bool debug, + bool verbose, bool null_stderr) +{ + bool err; + unsigned int argc; + char **argv; + char **argp; + char *fsource_arg; + char *ftarget_arg; + int exitstatus; + unsigned int i; + + argc = + 2 + (no_assert_option ? 1 : 0) + (fsource_option ? 1 : 0) + + (ftarget_option ? 1 : 0) + (optimize ? 1 : 0) + (debug ? 1 : 0) + + (directory != NULL ? 2 : 0) + java_sources_count; + argv = (char **) xmalloca ((argc + 1) * sizeof (char *)); + + argp = argv; + *argp++ = "gcj"; + *argp++ = "-C"; + if (no_assert_option) + *argp++ = "-fno-assert"; + if (fsource_option) + { + fsource_arg = (char *) xmalloca (9 + strlen (source_version) + 1); + memcpy (fsource_arg, "-fsource=", 9); + strcpy (fsource_arg + 9, source_version); + *argp++ = fsource_arg; + } + else + fsource_arg = NULL; + if (ftarget_option) + { + ftarget_arg = (char *) xmalloca (9 + strlen (target_version) + 1); + memcpy (ftarget_arg, "-ftarget=", 9); + strcpy (ftarget_arg + 9, target_version); + *argp++ = ftarget_arg; + } + else + ftarget_arg = NULL; + if (optimize) + *argp++ = "-O"; + if (debug) + *argp++ = "-g"; + if (directory != NULL) + { + *argp++ = "-d"; + *argp++ = (char *) directory; + } + for (i = 0; i < java_sources_count; i++) + *argp++ = (char *) java_sources[i]; + *argp = NULL; + /* Ensure argv length was correctly calculated. */ + if (argp - argv != argc) + abort (); + + if (verbose) + { + char *command = shell_quote_argv (argv); + printf ("%s\n", command); + free (command); + } + + exitstatus = execute ("gcj", "gcj", argv, false, false, false, null_stderr, + true, true, NULL); + err = (exitstatus != 0); + + if (ftarget_arg != NULL) + freea (ftarget_arg); + if (fsource_arg != NULL) + freea (fsource_arg); + freea (argv); + + return err; +} + +/* Try to compile a set of Java sources with javac. + Return a failure indicator (true upon error). */ +static bool +compile_using_javac (const char * const *java_sources, + unsigned int java_sources_count, + bool source_option, const char *source_version, + bool target_option, const char *target_version, + const char *directory, + bool optimize, bool debug, + bool verbose, bool null_stderr) +{ + bool err; + unsigned int argc; + char **argv; + char **argp; + int exitstatus; + unsigned int i; + + argc = + 1 + (source_option ? 2 : 0) + (target_option ? 2 : 0) + (optimize ? 1 : 0) + + (debug ? 1 : 0) + (directory != NULL ? 2 : 0) + java_sources_count; + argv = (char **) xmalloca ((argc + 1) * sizeof (char *)); + + argp = argv; + *argp++ = "javac"; + if (source_option) + { + *argp++ = "-source"; + *argp++ = (char *) source_version; + } + if (target_option) + { + *argp++ = "-target"; + *argp++ = (char *) target_version; + } + if (optimize) + *argp++ = "-O"; + if (debug) + *argp++ = "-g"; + if (directory != NULL) + { + *argp++ = "-d"; + *argp++ = (char *) directory; + } + for (i = 0; i < java_sources_count; i++) + *argp++ = (char *) java_sources[i]; + *argp = NULL; + /* Ensure argv length was correctly calculated. */ + if (argp - argv != argc) + abort (); + + if (verbose) + { + char *command = shell_quote_argv (argv); + printf ("%s\n", command); + free (command); + } + + exitstatus = execute ("javac", "javac", argv, false, false, false, + null_stderr, true, true, NULL); + err = (exitstatus != 0); + + freea (argv); + + return err; +} + +/* Try to compile a set of Java sources with jikes. + Return a failure indicator (true upon error). */ +static bool +compile_using_jikes (const char * const *java_sources, + unsigned int java_sources_count, + const char *directory, + bool optimize, bool debug, + bool verbose, bool null_stderr) +{ + bool err; + unsigned int argc; + char **argv; + char **argp; + int exitstatus; + unsigned int i; + + argc = + 1 + (optimize ? 1 : 0) + (debug ? 1 : 0) + (directory != NULL ? 2 : 0) + + java_sources_count; + argv = (char **) xmalloca ((argc + 1) * sizeof (char *)); + + argp = argv; + *argp++ = "jikes"; + if (optimize) + *argp++ = "-O"; + if (debug) + *argp++ = "-g"; + if (directory != NULL) + { + *argp++ = "-d"; + *argp++ = (char *) directory; + } + for (i = 0; i < java_sources_count; i++) + *argp++ = (char *) java_sources[i]; + *argp = NULL; + /* Ensure argv length was correctly calculated. */ + if (argp - argv != argc) + abort (); + + if (verbose) + { + char *command = shell_quote_argv (argv); + printf ("%s\n", command); + free (command); + } + + exitstatus = execute ("jikes", "jikes", argv, false, false, false, + null_stderr, true, true, NULL); + err = (exitstatus != 0); + + freea (argv); + + return err; +} + +/* ====================== Usability test subroutines ====================== */ + +/* Write a given contents to a temporary file. + FILE_NAME is the name of a file inside TMPDIR that is known not to exist + yet. + Return a failure indicator (true upon error). */ +static bool +write_temp_file (struct temp_dir *tmpdir, const char *file_name, + const char *contents) +{ + FILE *fp; + + register_temp_file (tmpdir, file_name); + fp = fopen_temp (file_name, "w"); + if (fp == NULL) + { + error (0, errno, _("failed to create \"%s\""), file_name); + unregister_temp_file (tmpdir, file_name); + return true; + } + fputs (contents, fp); + if (fwriteerror_temp (fp)) + { + error (0, errno, _("error while writing \"%s\" file"), file_name); + return true; + } + return false; +} + +/* Return the class file version number of a class file on disk. */ +static int +get_classfile_version (const char *compiled_file_name) +{ + unsigned char header[8]; + int fd; + + /* Open the class file. */ + fd = open (compiled_file_name, O_RDONLY | O_BINARY, 0); + if (fd >= 0) + { + /* Read its first 8 bytes. */ + if (safe_read (fd, header, 8) == 8) + { + /* Verify the class file signature. */ + if (header[0] == 0xCA && header[1] == 0xFE + && header[2] == 0xBA && header[3] == 0xBE) + return header[7]; + } + close (fd); + } + + /* Could not get the class file version. Return a very large one. */ + return INT_MAX; +} + +/* Return true if $JAVAC is a version of gcj. */ +static bool +is_envjavac_gcj (const char *javac) +{ + static bool envjavac_tested; + static bool envjavac_gcj; + + if (!envjavac_tested) + { + /* Test whether $JAVAC is gcj: + "$JAVAC --version 2>/dev/null | sed -e 1q | grep gcj > /dev/null" */ + unsigned int command_length; + char *command; + char *argv[4]; + pid_t child; + int fd[1]; + FILE *fp; + char *line; + size_t linesize; + size_t linelen; + int exitstatus; + char *p; + + /* Setup the command "$JAVAC --version". */ + command_length = strlen (javac) + 1 + 9 + 1; + command = (char *) xmalloca (command_length); + p = command; + /* Don't shell_quote $JAVAC, because it may consist of a command + and options. */ + memcpy (p, javac, strlen (javac)); + p += strlen (javac); + memcpy (p, " --version", 1 + 9 + 1); + p += 1 + 9 + 1; + /* Ensure command_length was correctly calculated. */ + if (p - command > command_length) + abort (); + + /* Call $JAVAC --version 2>/dev/null. */ + argv[0] = "/bin/sh"; + argv[1] = "-c"; + argv[2] = command; + argv[3] = NULL; + child = create_pipe_in (javac, "/bin/sh", argv, DEV_NULL, true, true, + false, fd); + if (child == -1) + goto failed; + + /* Retrieve its result. */ + fp = fdopen (fd[0], "r"); + if (fp == NULL) + goto failed; + + line = NULL; linesize = 0; + linelen = getline (&line, &linesize, fp); + if (linelen == (size_t)(-1)) + { + fclose (fp); + goto failed; + } + /* It is safe to call c_strstr() instead of strstr() here; see the + comments in c-strstr.h. */ + envjavac_gcj = (c_strstr (line, "gcj") != NULL); + + fclose (fp); + + /* Remove zombie process from process list, and retrieve exit status. */ + exitstatus = + wait_subprocess (child, javac, true, true, true, false, NULL); + if (exitstatus != 0) + envjavac_gcj = false; + + failed: + freea (command); + + envjavac_tested = true; + } + + return envjavac_gcj; +} + +/* Return true if $JAVAC, known to be a version of gcj, is a version >= 4.3 + of gcj. */ +static bool +is_envjavac_gcj43 (const char *javac) +{ + static bool envjavac_tested; + static bool envjavac_gcj43; + + if (!envjavac_tested) + { + /* Test whether $JAVAC is gcj: + "$JAVAC --version 2>/dev/null | sed -e 's,^[^0-9]*,,' -e 1q \ + | sed -e '/^4\.[012]/d' | grep '^[4-9]' >/dev/null" */ + unsigned int command_length; + char *command; + char *argv[4]; + pid_t child; + int fd[1]; + FILE *fp; + char *line; + size_t linesize; + size_t linelen; + int exitstatus; + char *p; + + /* Setup the command "$JAVAC --version". */ + command_length = strlen (javac) + 1 + 9 + 1; + command = (char *) xmalloca (command_length); + p = command; + /* Don't shell_quote $JAVAC, because it may consist of a command + and options. */ + memcpy (p, javac, strlen (javac)); + p += strlen (javac); + memcpy (p, " --version", 1 + 9 + 1); + p += 1 + 9 + 1; + /* Ensure command_length was correctly calculated. */ + if (p - command > command_length) + abort (); + + /* Call $JAVAC --version 2>/dev/null. */ + argv[0] = "/bin/sh"; + argv[1] = "-c"; + argv[2] = command; + argv[3] = NULL; + child = create_pipe_in (javac, "/bin/sh", argv, DEV_NULL, true, true, + false, fd); + if (child == -1) + goto failed; + + /* Retrieve its result. */ + fp = fdopen (fd[0], "r"); + if (fp == NULL) + goto failed; + + line = NULL; linesize = 0; + linelen = getline (&line, &linesize, fp); + if (linelen == (size_t)(-1)) + { + fclose (fp); + goto failed; + } + p = line; + while (*p != '\0' && !(*p >= '0' && *p <= '9')) + p++; + envjavac_gcj43 = + !(*p == '4' && p[1] == '.' && p[2] >= '0' && p[2] <= '2') + && (*p >= '4' && *p <= '9'); + + fclose (fp); + + /* Remove zombie process from process list, and retrieve exit status. */ + exitstatus = + wait_subprocess (child, javac, true, true, true, false, NULL); + if (exitstatus != 0) + envjavac_gcj43 = false; + + failed: + freea (command); + + envjavac_tested = true; + } + + return envjavac_gcj43; +} + +/* Test whether $JAVAC, known to be a version of gcj >= 4.3, can be used, and + whether it needs a -fsource and/or -ftarget option. + Return a failure indicator (true upon error). */ +static bool +is_envjavac_gcj43_usable (const char *javac, + const char *source_version, + const char *target_version, + bool *usablep, + bool *fsource_option_p, bool *ftarget_option_p) +{ + /* The cache depends on the source_version and target_version. */ + struct result_t + { + bool tested; + bool usable; + bool fsource_option; + bool ftarget_option; + }; + static struct result_t result_cache[SOURCE_VERSION_BOUND][TARGET_VERSION_BOUND]; + struct result_t *resultp; + + resultp = &result_cache[source_version_index (source_version)] + [target_version_index (target_version)]; + if (!resultp->tested) + { + /* Try $JAVAC. */ + struct temp_dir *tmpdir; + char *conftest_file_name; + char *compiled_file_name; + const char *java_sources[1]; + struct stat statbuf; + + tmpdir = create_temp_dir ("java", NULL, false); + if (tmpdir == NULL) + return true; + + conftest_file_name = + xconcatenated_filename (tmpdir->dir_name, "conftest.java", NULL); + if (write_temp_file (tmpdir, conftest_file_name, + get_goodcode_snippet (source_version))) + { + free (conftest_file_name); + cleanup_temp_dir (tmpdir); + return true; + } + + compiled_file_name = + xconcatenated_filename (tmpdir->dir_name, "conftest.class", NULL); + register_temp_file (tmpdir, compiled_file_name); + + java_sources[0] = conftest_file_name; + if (!compile_using_envjavac (javac, + java_sources, 1, tmpdir->dir_name, + false, false, false, true) + && stat (compiled_file_name, &statbuf) >= 0 + && get_classfile_version (compiled_file_name) + <= corresponding_classfile_version (target_version)) + { + /* $JAVAC compiled conftest.java successfully. */ + /* Try adding -fsource option if it is useful. */ + char *javac_source = + xasprintf ("%s -fsource=%s", javac, source_version); + + unlink (compiled_file_name); + + java_sources[0] = conftest_file_name; + if (!compile_using_envjavac (javac_source, + java_sources, 1, tmpdir->dir_name, + false, false, false, true) + && stat (compiled_file_name, &statbuf) >= 0 + && get_classfile_version (compiled_file_name) + <= corresponding_classfile_version (target_version)) + { + const char *failcode = get_failcode_snippet (source_version); + + if (failcode != NULL) + { + free (compiled_file_name); + free (conftest_file_name); + + conftest_file_name = + xconcatenated_filename (tmpdir->dir_name, + "conftestfail.java", + NULL); + if (write_temp_file (tmpdir, conftest_file_name, failcode)) + { + free (conftest_file_name); + free (javac_source); + cleanup_temp_dir (tmpdir); + return true; + } + + compiled_file_name = + xconcatenated_filename (tmpdir->dir_name, + "conftestfail.class", + NULL); + register_temp_file (tmpdir, compiled_file_name); + + java_sources[0] = conftest_file_name; + if (!compile_using_envjavac (javac, + java_sources, 1, + tmpdir->dir_name, + false, false, false, true) + && stat (compiled_file_name, &statbuf) >= 0) + { + unlink (compiled_file_name); + + java_sources[0] = conftest_file_name; + if (compile_using_envjavac (javac_source, + java_sources, 1, + tmpdir->dir_name, + false, false, false, true)) + /* $JAVAC compiled conftestfail.java successfully, and + "$JAVAC -fsource=$source_version" rejects it. So + the -fsource option is useful. */ + resultp->fsource_option = true; + } + } + } + + free (javac_source); + + resultp->usable = true; + } + else + { + /* Try with -fsource and -ftarget options. */ + char *javac_target = + xasprintf ("%s -fsource=%s -ftarget=%s", + javac, source_version, target_version); + + unlink (compiled_file_name); + + java_sources[0] = conftest_file_name; + if (!compile_using_envjavac (javac_target, + java_sources, 1, tmpdir->dir_name, + false, false, false, true) + && stat (compiled_file_name, &statbuf) >= 0 + && get_classfile_version (compiled_file_name) + <= corresponding_classfile_version (target_version)) + { + /* "$JAVAC -fsource $source_version -ftarget $target_version" + compiled conftest.java successfully. */ + resultp->fsource_option = true; + resultp->ftarget_option = true; + resultp->usable = true; + } + + free (javac_target); + } + + free (compiled_file_name); + free (conftest_file_name); + + resultp->tested = true; + } + + *usablep = resultp->usable; + *fsource_option_p = resultp->fsource_option; + *ftarget_option_p = resultp->ftarget_option; + return false; +} + +/* Test whether $JAVAC, known to be a version of gcj < 4.3, can be used for + compiling with target_version = 1.4 and source_version = 1.4. + Return a failure indicator (true upon error). */ +static bool +is_envjavac_oldgcj_14_14_usable (const char *javac, bool *usablep) +{ + static bool envjavac_tested; + static bool envjavac_usable; + + if (!envjavac_tested) + { + /* Try $JAVAC. */ + struct temp_dir *tmpdir; + char *conftest_file_name; + char *compiled_file_name; + const char *java_sources[1]; + struct stat statbuf; + + tmpdir = create_temp_dir ("java", NULL, false); + if (tmpdir == NULL) + return true; + + conftest_file_name = + xconcatenated_filename (tmpdir->dir_name, "conftest.java", NULL); + if (write_temp_file (tmpdir, conftest_file_name, + get_goodcode_snippet ("1.4"))) + { + free (conftest_file_name); + cleanup_temp_dir (tmpdir); + return true; + } + + compiled_file_name = + xconcatenated_filename (tmpdir->dir_name, "conftest.class", NULL); + register_temp_file (tmpdir, compiled_file_name); + + java_sources[0] = conftest_file_name; + if (!compile_using_envjavac (javac, java_sources, 1, tmpdir->dir_name, + false, false, false, true) + && stat (compiled_file_name, &statbuf) >= 0) + /* Compilation succeeded. */ + envjavac_usable = true; + + free (compiled_file_name); + free (conftest_file_name); + + cleanup_temp_dir (tmpdir); + + envjavac_tested = true; + } + + *usablep = envjavac_usable; + return false; +} + +/* Test whether $JAVAC, known to be a version of gcj < 4.3, can be used for + compiling with target_version = 1.4 and source_version = 1.3. + Return a failure indicator (true upon error). */ +static bool +is_envjavac_oldgcj_14_13_usable (const char *javac, + bool *usablep, bool *need_no_assert_option_p) +{ + static bool envjavac_tested; + static bool envjavac_usable; + static bool envjavac_need_no_assert_option; + + if (!envjavac_tested) + { + /* Try $JAVAC and "$JAVAC -fno-assert". But add -fno-assert only if + it makes a difference. (It could already be part of $JAVAC.) */ + struct temp_dir *tmpdir; + char *conftest_file_name; + char *compiled_file_name; + const char *java_sources[1]; + struct stat statbuf; + bool javac_works; + char *javac_noassert; + bool javac_noassert_works; + + tmpdir = create_temp_dir ("java", NULL, false); + if (tmpdir == NULL) + return true; + + conftest_file_name = + xconcatenated_filename (tmpdir->dir_name, "conftest.java", NULL); + if (write_temp_file (tmpdir, conftest_file_name, + get_goodcode_snippet ("1.3"))) + { + free (conftest_file_name); + cleanup_temp_dir (tmpdir); + return true; + } + + compiled_file_name = + xconcatenated_filename (tmpdir->dir_name, "conftest.class", NULL); + register_temp_file (tmpdir, compiled_file_name); + + java_sources[0] = conftest_file_name; + if (!compile_using_envjavac (javac, + java_sources, 1, tmpdir->dir_name, + false, false, false, true) + && stat (compiled_file_name, &statbuf) >= 0) + /* Compilation succeeded. */ + javac_works = true; + else + javac_works = false; + + unlink (compiled_file_name); + + javac_noassert = xasprintf ("%s -fno-assert", javac); + + java_sources[0] = conftest_file_name; + if (!compile_using_envjavac (javac_noassert, + java_sources, 1, tmpdir->dir_name, + false, false, false, true) + && stat (compiled_file_name, &statbuf) >= 0) + /* Compilation succeeded. */ + javac_noassert_works = true; + else + javac_noassert_works = false; + + free (compiled_file_name); + free (conftest_file_name); + + if (javac_works && javac_noassert_works) + { + conftest_file_name = + xconcatenated_filename (tmpdir->dir_name, "conftestfail.java", + NULL); + if (write_temp_file (tmpdir, conftest_file_name, + get_failcode_snippet ("1.3"))) + { + free (conftest_file_name); + free (javac_noassert); + cleanup_temp_dir (tmpdir); + return true; + } + + compiled_file_name = + xconcatenated_filename (tmpdir->dir_name, "conftestfail.class", + NULL); + register_temp_file (tmpdir, compiled_file_name); + + java_sources[0] = conftest_file_name; + if (!compile_using_envjavac (javac, + java_sources, 1, tmpdir->dir_name, + false, false, false, true) + && stat (compiled_file_name, &statbuf) >= 0) + { + /* Compilation succeeded. */ + unlink (compiled_file_name); + + java_sources[0] = conftest_file_name; + if (!(!compile_using_envjavac (javac_noassert, + java_sources, 1, tmpdir->dir_name, + false, false, false, true) + && stat (compiled_file_name, &statbuf) >= 0)) + /* Compilation failed. */ + /* "$JAVAC -fno-assert" works better than $JAVAC. */ + javac_works = true; + } + + free (compiled_file_name); + free (conftest_file_name); + } + + cleanup_temp_dir (tmpdir); + + if (javac_works) + { + envjavac_usable = true; + envjavac_need_no_assert_option = false; + } + else if (javac_noassert_works) + { + envjavac_usable = true; + envjavac_need_no_assert_option = true; + } + + envjavac_tested = true; + } + + *usablep = envjavac_usable; + *need_no_assert_option_p = envjavac_need_no_assert_option; + return false; +} + +/* Test whether $JAVAC, known to be not a version of gcj, can be used, and + whether it needs a -source and/or -target option. + Return a failure indicator (true upon error). */ +static bool +is_envjavac_nongcj_usable (const char *javac, + const char *source_version, + const char *target_version, + bool *usablep, + bool *source_option_p, bool *target_option_p) +{ + /* The cache depends on the source_version and target_version. */ + struct result_t + { + bool tested; + bool usable; + bool source_option; + bool target_option; + }; + static struct result_t result_cache[SOURCE_VERSION_BOUND][TARGET_VERSION_BOUND]; + struct result_t *resultp; + + resultp = &result_cache[source_version_index (source_version)] + [target_version_index (target_version)]; + if (!resultp->tested) + { + /* Try $JAVAC. */ + struct temp_dir *tmpdir; + char *conftest_file_name; + char *compiled_file_name; + const char *java_sources[1]; + struct stat statbuf; + + tmpdir = create_temp_dir ("java", NULL, false); + if (tmpdir == NULL) + return true; + + conftest_file_name = + xconcatenated_filename (tmpdir->dir_name, "conftest.java", NULL); + if (write_temp_file (tmpdir, conftest_file_name, + get_goodcode_snippet (source_version))) + { + free (conftest_file_name); + cleanup_temp_dir (tmpdir); + return true; + } + + compiled_file_name = + xconcatenated_filename (tmpdir->dir_name, "conftest.class", NULL); + register_temp_file (tmpdir, compiled_file_name); + + java_sources[0] = conftest_file_name; + if (!compile_using_envjavac (javac, + java_sources, 1, tmpdir->dir_name, + false, false, false, true) + && stat (compiled_file_name, &statbuf) >= 0 + && get_classfile_version (compiled_file_name) + <= corresponding_classfile_version (target_version)) + { + /* $JAVAC compiled conftest.java successfully. */ + /* Try adding -source option if it is useful. */ + char *javac_source = + xasprintf ("%s -source %s", javac, source_version); + + unlink (compiled_file_name); + + java_sources[0] = conftest_file_name; + if (!compile_using_envjavac (javac_source, + java_sources, 1, tmpdir->dir_name, + false, false, false, true) + && stat (compiled_file_name, &statbuf) >= 0 + && get_classfile_version (compiled_file_name) + <= corresponding_classfile_version (target_version)) + { + const char *failcode = get_failcode_snippet (source_version); + + if (failcode != NULL) + { + free (compiled_file_name); + free (conftest_file_name); + + conftest_file_name = + xconcatenated_filename (tmpdir->dir_name, + "conftestfail.java", + NULL); + if (write_temp_file (tmpdir, conftest_file_name, failcode)) + { + free (conftest_file_name); + free (javac_source); + cleanup_temp_dir (tmpdir); + return true; + } + + compiled_file_name = + xconcatenated_filename (tmpdir->dir_name, + "conftestfail.class", + NULL); + register_temp_file (tmpdir, compiled_file_name); + + java_sources[0] = conftest_file_name; + if (!compile_using_envjavac (javac, + java_sources, 1, + tmpdir->dir_name, + false, false, false, true) + && stat (compiled_file_name, &statbuf) >= 0) + { + unlink (compiled_file_name); + + java_sources[0] = conftest_file_name; + if (compile_using_envjavac (javac_source, + java_sources, 1, + tmpdir->dir_name, + false, false, false, true)) + /* $JAVAC compiled conftestfail.java successfully, and + "$JAVAC -source $source_version" rejects it. So the + -source option is useful. */ + resultp->source_option = true; + } + } + } + + free (javac_source); + + resultp->usable = true; + } + else + { + /* Try with -target option alone. (Sun javac 1.3.1 has the -target + option but no -source option.) */ + char *javac_target = + xasprintf ("%s -target %s", javac, target_version); + + unlink (compiled_file_name); + + java_sources[0] = conftest_file_name; + if (!compile_using_envjavac (javac_target, + java_sources, 1, tmpdir->dir_name, + false, false, false, true) + && stat (compiled_file_name, &statbuf) >= 0 + && get_classfile_version (compiled_file_name) + <= corresponding_classfile_version (target_version)) + { + /* "$JAVAC -target $target_version" compiled conftest.java + successfully. */ + /* Try adding -source option if it is useful. */ + char *javac_target_source = + xasprintf ("%s -source %s", javac_target, source_version); + + unlink (compiled_file_name); + + java_sources[0] = conftest_file_name; + if (!compile_using_envjavac (javac_target_source, + java_sources, 1, tmpdir->dir_name, + false, false, false, true) + && stat (compiled_file_name, &statbuf) >= 0 + && get_classfile_version (compiled_file_name) + <= corresponding_classfile_version (target_version)) + { + const char *failcode = get_failcode_snippet (source_version); + + if (failcode != NULL) + { + free (compiled_file_name); + free (conftest_file_name); + + conftest_file_name = + xconcatenated_filename (tmpdir->dir_name, + "conftestfail.java", + NULL); + if (write_temp_file (tmpdir, conftest_file_name, + failcode)) + { + free (conftest_file_name); + free (javac_target_source); + free (javac_target); + cleanup_temp_dir (tmpdir); + return true; + } + + compiled_file_name = + xconcatenated_filename (tmpdir->dir_name, + "conftestfail.class", + NULL); + register_temp_file (tmpdir, compiled_file_name); + + java_sources[0] = conftest_file_name; + if (!compile_using_envjavac (javac_target, + java_sources, 1, + tmpdir->dir_name, + false, false, false, true) + && stat (compiled_file_name, &statbuf) >= 0) + { + unlink (compiled_file_name); + + java_sources[0] = conftest_file_name; + if (compile_using_envjavac (javac_target_source, + java_sources, 1, + tmpdir->dir_name, + false, false, false, + true)) + /* "$JAVAC -target $target_version" compiled + conftestfail.java successfully, and + "$JAVAC -target $target_version -source $source_version" + rejects it. So the -source option is useful. */ + resultp->source_option = true; + } + } + } + + free (javac_target_source); + + resultp->target_option = true; + resultp->usable = true; + } + else + { + /* Maybe this -target option requires a -source option? Try with + -target and -source options. (Supported by Sun javac 1.4 and + higher.) */ + char *javac_target_source = + xasprintf ("%s -source %s", javac_target, source_version); + + unlink (compiled_file_name); + + java_sources[0] = conftest_file_name; + if (!compile_using_envjavac (javac_target_source, + java_sources, 1, tmpdir->dir_name, + false, false, false, true) + && stat (compiled_file_name, &statbuf) >= 0 + && get_classfile_version (compiled_file_name) + <= corresponding_classfile_version (target_version)) + { + /* "$JAVAC -target $target_version -source $source_version" + compiled conftest.java successfully. */ + resultp->source_option = true; + resultp->target_option = true; + resultp->usable = true; + } + + free (javac_target_source); + } + + free (javac_target); + } + + free (compiled_file_name); + free (conftest_file_name); + + resultp->tested = true; + } + + *usablep = resultp->usable; + *source_option_p = resultp->source_option; + *target_option_p = resultp->target_option; + return false; +} + +static bool +is_gcj_present (void) +{ + static bool gcj_tested; + static bool gcj_present; + + if (!gcj_tested) + { + /* Test for presence of gcj: + "gcj --version 2> /dev/null | \ + sed -e 's,^[^0-9]*,,' -e 1q | \ + sed -e '/^3\.[01]/d' | grep '^[3-9]' > /dev/null" */ + char *argv[3]; + pid_t child; + int fd[1]; + int exitstatus; + + argv[0] = "gcj"; + argv[1] = "--version"; + argv[2] = NULL; + child = create_pipe_in ("gcj", "gcj", argv, DEV_NULL, true, true, + false, fd); + gcj_present = false; + if (child != -1) + { + /* Read the subprocess output, drop all lines except the first, + drop all characters before the first digit, and test whether + the remaining string starts with a digit >= 3, but not with + "3.0" or "3.1". */ + char c[3]; + size_t count = 0; + + while (safe_read (fd[0], &c[count], 1) > 0) + { + if (c[count] == '\n') + break; + if (count == 0) + { + if (!(c[0] >= '0' && c[0] <= '9')) + continue; + gcj_present = (c[0] >= '3'); + } + count++; + if (count == 3) + { + if (c[0] == '3' && c[1] == '.' + && (c[2] == '0' || c[2] == '1')) + gcj_present = false; + break; + } + } + while (safe_read (fd[0], &c[0], 1) > 0) + ; + + close (fd[0]); + + /* Remove zombie process from process list, and retrieve exit + status. */ + exitstatus = + wait_subprocess (child, "gcj", false, true, true, false, NULL); + if (exitstatus != 0) + gcj_present = false; + } + + if (gcj_present) + { + /* See if libgcj.jar is well installed. */ + struct temp_dir *tmpdir; + + tmpdir = create_temp_dir ("java", NULL, false); + if (tmpdir == NULL) + gcj_present = false; + else + { + char *conftest_file_name; + + conftest_file_name = + xconcatenated_filename (tmpdir->dir_name, "conftestlib.java", + NULL); + if (write_temp_file (tmpdir, conftest_file_name, +"public class conftestlib {\n" +" public static void main (String[] args) {\n" +" }\n" +"}\n")) + gcj_present = false; + else + { + char *compiled_file_name; + const char *java_sources[1]; + + compiled_file_name = + xconcatenated_filename (tmpdir->dir_name, + "conftestlib.class", + NULL); + register_temp_file (tmpdir, compiled_file_name); + + java_sources[0] = conftest_file_name; + if (compile_using_gcj (java_sources, 1, false, + false, NULL, false, NULL, + tmpdir->dir_name, + false, false, false, true)) + gcj_present = false; + + free (compiled_file_name); + } + free (conftest_file_name); + } + cleanup_temp_dir (tmpdir); + } + + gcj_tested = true; + } + + return gcj_present; +} + +static bool +is_gcj_43 (void) +{ + static bool gcj_tested; + static bool gcj_43; + + if (!gcj_tested) + { + /* Test for presence of gcj: + "gcj --version 2> /dev/null | \ + sed -e 's,^[^0-9]*,,' -e 1q | \ + sed -e '/^4\.[012]/d' | grep '^[4-9]'" */ + char *argv[3]; + pid_t child; + int fd[1]; + int exitstatus; + + argv[0] = "gcj"; + argv[1] = "--version"; + argv[2] = NULL; + child = create_pipe_in ("gcj", "gcj", argv, DEV_NULL, true, true, + false, fd); + gcj_43 = false; + if (child != -1) + { + /* Read the subprocess output, drop all lines except the first, + drop all characters before the first digit, and test whether + the remaining string starts with a digit >= 4, but not with + "4.0" or "4.1" or "4.2". */ + char c[3]; + size_t count = 0; + + while (safe_read (fd[0], &c[count], 1) > 0) + { + if (c[count] == '\n') + break; + if (count == 0) + { + if (!(c[0] >= '0' && c[0] <= '9')) + continue; + gcj_43 = (c[0] >= '4'); + } + count++; + if (count == 3) + { + if (c[0] == '4' && c[1] == '.' && c[2] >= '0' && c[2] <= '2') + gcj_43 = false; + break; + } + } + while (safe_read (fd[0], &c[0], 1) > 0) + ; + + close (fd[0]); + + /* Remove zombie process from process list, and retrieve exit + status. */ + exitstatus = + wait_subprocess (child, "gcj", false, true, true, false, NULL); + if (exitstatus != 0) + gcj_43 = false; + } + + gcj_tested = true; + } + + return gcj_43; +} + +/* Test whether gcj >= 4.3 can be used, and whether it needs a -fsource and/or + -ftarget option. + Return a failure indicator (true upon error). */ +static bool +is_gcj43_usable (const char *source_version, + const char *target_version, + bool *usablep, + bool *fsource_option_p, bool *ftarget_option_p) +{ + /* The cache depends on the source_version and target_version. */ + struct result_t + { + bool tested; + bool usable; + bool fsource_option; + bool ftarget_option; + }; + static struct result_t result_cache[SOURCE_VERSION_BOUND][TARGET_VERSION_BOUND]; + struct result_t *resultp; + + resultp = &result_cache[source_version_index (source_version)] + [target_version_index (target_version)]; + if (!resultp->tested) + { + /* Try gcj. */ + struct temp_dir *tmpdir; + char *conftest_file_name; + char *compiled_file_name; + const char *java_sources[1]; + struct stat statbuf; + + tmpdir = create_temp_dir ("java", NULL, false); + if (tmpdir == NULL) + return true; + + conftest_file_name = + xconcatenated_filename (tmpdir->dir_name, "conftest.java", NULL); + if (write_temp_file (tmpdir, conftest_file_name, + get_goodcode_snippet (source_version))) + { + free (conftest_file_name); + cleanup_temp_dir (tmpdir); + return true; + } + + compiled_file_name = + xconcatenated_filename (tmpdir->dir_name, "conftest.class", NULL); + register_temp_file (tmpdir, compiled_file_name); + + java_sources[0] = conftest_file_name; + if (!compile_using_gcj (java_sources, 1, false, false, NULL, false, NULL, + tmpdir->dir_name, false, false, false, true) + && stat (compiled_file_name, &statbuf) >= 0 + && get_classfile_version (compiled_file_name) + <= corresponding_classfile_version (target_version)) + { + /* gcj compiled conftest.java successfully. */ + /* Try adding -fsource option if it is useful. */ + unlink (compiled_file_name); + + java_sources[0] = conftest_file_name; + if (!compile_using_gcj (java_sources, 1, + false, true, source_version, false, NULL, + tmpdir->dir_name, false, false, false, true) + && stat (compiled_file_name, &statbuf) >= 0 + && get_classfile_version (compiled_file_name) + <= corresponding_classfile_version (target_version)) + { + const char *failcode = get_failcode_snippet (source_version); + + if (failcode != NULL) + { + free (compiled_file_name); + free (conftest_file_name); + + conftest_file_name = + xconcatenated_filename (tmpdir->dir_name, + "conftestfail.java", + NULL); + if (write_temp_file (tmpdir, conftest_file_name, failcode)) + { + free (conftest_file_name); + cleanup_temp_dir (tmpdir); + return true; + } + + compiled_file_name = + xconcatenated_filename (tmpdir->dir_name, + "conftestfail.class", + NULL); + register_temp_file (tmpdir, compiled_file_name); + + java_sources[0] = conftest_file_name; + if (!compile_using_gcj (java_sources, 1, + false, false, NULL, false, NULL, + tmpdir->dir_name, + false, false, false, true) + && stat (compiled_file_name, &statbuf) >= 0) + { + unlink (compiled_file_name); + + java_sources[0] = conftest_file_name; + if (compile_using_gcj (java_sources, 1, + false, true, source_version, + false, NULL, + tmpdir->dir_name, + false, false, false, true)) + /* gcj compiled conftestfail.java successfully, and + "gcj -fsource=$source_version" rejects it. So + the -fsource option is useful. */ + resultp->fsource_option = true; + } + } + } + + resultp->usable = true; + } + else + { + /* Try with -fsource and -ftarget options. */ + unlink (compiled_file_name); + + java_sources[0] = conftest_file_name; + if (!compile_using_gcj (java_sources, 1, + false, true, source_version, + true, target_version, + tmpdir->dir_name, + false, false, false, true) + && stat (compiled_file_name, &statbuf) >= 0 + && get_classfile_version (compiled_file_name) + <= corresponding_classfile_version (target_version)) + { + /* "gcj -fsource $source_version -ftarget $target_version" + compiled conftest.java successfully. */ + resultp->fsource_option = true; + resultp->ftarget_option = true; + resultp->usable = true; + } + } + + free (compiled_file_name); + free (conftest_file_name); + + resultp->tested = true; + } + + *usablep = resultp->usable; + *fsource_option_p = resultp->fsource_option; + *ftarget_option_p = resultp->ftarget_option; + return false; +} + +/* Test whether gcj < 4.3 can be used for compiling with target_version = 1.4 + and source_version = 1.4. + Return a failure indicator (true upon error). */ +static bool +is_oldgcj_14_14_usable (bool *usablep) +{ + static bool gcj_tested; + static bool gcj_usable; + + if (!gcj_tested) + { + /* Try gcj. */ + struct temp_dir *tmpdir; + char *conftest_file_name; + char *compiled_file_name; + const char *java_sources[1]; + struct stat statbuf; + + tmpdir = create_temp_dir ("java", NULL, false); + if (tmpdir == NULL) + return true; + + conftest_file_name = + xconcatenated_filename (tmpdir->dir_name, "conftest.java", NULL); + if (write_temp_file (tmpdir, conftest_file_name, + get_goodcode_snippet ("1.4"))) + { + free (conftest_file_name); + cleanup_temp_dir (tmpdir); + return true; + } + + compiled_file_name = + xconcatenated_filename (tmpdir->dir_name, "conftest.class", NULL); + register_temp_file (tmpdir, compiled_file_name); + + java_sources[0] = conftest_file_name; + if (!compile_using_gcj (java_sources, 1, false, false, NULL, false, NULL, + tmpdir->dir_name, false, false, false, true) + && stat (compiled_file_name, &statbuf) >= 0) + /* Compilation succeeded. */ + gcj_usable = true; + + free (compiled_file_name); + free (conftest_file_name); + + cleanup_temp_dir (tmpdir); + + gcj_tested = true; + } + + *usablep = gcj_usable; + return false; +} + +/* Test whether gcj < 4.3 can be used for compiling with target_version = 1.4 + and source_version = 1.3. + Return a failure indicator (true upon error). */ +static bool +is_oldgcj_14_13_usable (bool *usablep, bool *need_no_assert_option_p) +{ + static bool gcj_tested; + static bool gcj_usable; + static bool gcj_need_no_assert_option; + + if (!gcj_tested) + { + /* Try gcj and "gcj -fno-assert". But add -fno-assert only if + it works (not gcj < 3.3). */ + struct temp_dir *tmpdir; + char *conftest_file_name; + char *compiled_file_name; + const char *java_sources[1]; + struct stat statbuf; + + tmpdir = create_temp_dir ("java", NULL, false); + if (tmpdir == NULL) + return true; + + conftest_file_name = + xconcatenated_filename (tmpdir->dir_name, "conftest.java", NULL); + if (write_temp_file (tmpdir, conftest_file_name, + get_goodcode_snippet ("1.3"))) + { + free (conftest_file_name); + cleanup_temp_dir (tmpdir); + return true; + } + + compiled_file_name = + xconcatenated_filename (tmpdir->dir_name, "conftest.class", NULL); + register_temp_file (tmpdir, compiled_file_name); + + java_sources[0] = conftest_file_name; + if (!compile_using_gcj (java_sources, 1, true, false, NULL, false, NULL, + tmpdir->dir_name, false, false, false, true) + && stat (compiled_file_name, &statbuf) >= 0) + /* Compilation succeeded. */ + { + gcj_usable = true; + gcj_need_no_assert_option = true; + } + else + { + unlink (compiled_file_name); + + java_sources[0] = conftest_file_name; + if (!compile_using_gcj (java_sources, 1, false, + false, NULL, false, NULL, + tmpdir->dir_name, false, false, false, true) + && stat (compiled_file_name, &statbuf) >= 0) + /* Compilation succeeded. */ + { + gcj_usable = true; + gcj_need_no_assert_option = false; + } + } + + free (compiled_file_name); + free (conftest_file_name); + + cleanup_temp_dir (tmpdir); + + gcj_tested = true; + } + + *usablep = gcj_usable; + *need_no_assert_option_p = gcj_need_no_assert_option; + return false; +} + +static bool +is_javac_present (void) +{ + static bool javac_tested; + static bool javac_present; + + if (!javac_tested) + { + /* Test for presence of javac: "javac 2> /dev/null ; test $? -le 2" */ + char *argv[2]; + int exitstatus; + + argv[0] = "javac"; + argv[1] = NULL; + exitstatus = execute ("javac", "javac", argv, false, false, true, true, + true, false, NULL); + javac_present = (exitstatus == 0 || exitstatus == 1 || exitstatus == 2); + javac_tested = true; + } + + return javac_present; +} + +/* Test whether javac can be used and whether it needs a -source and/or + -target option. + Return a failure indicator (true upon error). */ +static bool +is_javac_usable (const char *source_version, const char *target_version, + bool *usablep, bool *source_option_p, bool *target_option_p) +{ + /* The cache depends on the source_version and target_version. */ + struct result_t + { + bool tested; + bool usable; + bool source_option; + bool target_option; + }; + static struct result_t result_cache[SOURCE_VERSION_BOUND][TARGET_VERSION_BOUND]; + struct result_t *resultp; + + resultp = &result_cache[source_version_index (source_version)] + [target_version_index (target_version)]; + if (!resultp->tested) + { + /* Try javac. */ + struct temp_dir *tmpdir; + char *conftest_file_name; + char *compiled_file_name; + const char *java_sources[1]; + struct stat statbuf; + + tmpdir = create_temp_dir ("java", NULL, false); + if (tmpdir == NULL) + return true; + + conftest_file_name = + xconcatenated_filename (tmpdir->dir_name, "conftest.java", NULL); + if (write_temp_file (tmpdir, conftest_file_name, + get_goodcode_snippet (source_version))) + { + free (conftest_file_name); + cleanup_temp_dir (tmpdir); + return true; + } + + compiled_file_name = + xconcatenated_filename (tmpdir->dir_name, "conftest.class", NULL); + register_temp_file (tmpdir, compiled_file_name); + + java_sources[0] = conftest_file_name; + if (!compile_using_javac (java_sources, 1, + false, source_version, + false, target_version, + tmpdir->dir_name, false, false, false, true) + && stat (compiled_file_name, &statbuf) >= 0 + && get_classfile_version (compiled_file_name) + <= corresponding_classfile_version (target_version)) + { + /* javac compiled conftest.java successfully. */ + /* Try adding -source option if it is useful. */ + unlink (compiled_file_name); + + java_sources[0] = conftest_file_name; + if (!compile_using_javac (java_sources, 1, + true, source_version, + false, target_version, + tmpdir->dir_name, false, false, false, true) + && stat (compiled_file_name, &statbuf) >= 0 + && get_classfile_version (compiled_file_name) + <= corresponding_classfile_version (target_version)) + { + const char *failcode = get_failcode_snippet (source_version); + + if (failcode != NULL) + { + free (compiled_file_name); + free (conftest_file_name); + + conftest_file_name = + xconcatenated_filename (tmpdir->dir_name, + "conftestfail.java", + NULL); + if (write_temp_file (tmpdir, conftest_file_name, failcode)) + { + free (conftest_file_name); + cleanup_temp_dir (tmpdir); + return true; + } + + compiled_file_name = + xconcatenated_filename (tmpdir->dir_name, + "conftestfail.class", + NULL); + register_temp_file (tmpdir, compiled_file_name); + + java_sources[0] = conftest_file_name; + if (!compile_using_javac (java_sources, 1, + false, source_version, + false, target_version, + tmpdir->dir_name, + false, false, false, true) + && stat (compiled_file_name, &statbuf) >= 0) + { + unlink (compiled_file_name); + + java_sources[0] = conftest_file_name; + if (compile_using_javac (java_sources, 1, + true, source_version, + false, target_version, + tmpdir->dir_name, + false, false, false, true)) + /* javac compiled conftestfail.java successfully, and + "javac -source $source_version" rejects it. So the + -source option is useful. */ + resultp->source_option = true; + } + } + } + + resultp->usable = true; + } + else + { + /* Try with -target option alone. (Sun javac 1.3.1 has the -target + option but no -source option.) */ + unlink (compiled_file_name); + + java_sources[0] = conftest_file_name; + if (!compile_using_javac (java_sources, 1, + false, source_version, + true, target_version, + tmpdir->dir_name, + false, false, false, true) + && stat (compiled_file_name, &statbuf) >= 0 + && get_classfile_version (compiled_file_name) + <= corresponding_classfile_version (target_version)) + { + /* "javac -target $target_version" compiled conftest.java + successfully. */ + /* Try adding -source option if it is useful. */ + unlink (compiled_file_name); + + java_sources[0] = conftest_file_name; + if (!compile_using_javac (java_sources, 1, + true, source_version, + true, target_version, + tmpdir->dir_name, + false, false, false, true) + && stat (compiled_file_name, &statbuf) >= 0 + && get_classfile_version (compiled_file_name) + <= corresponding_classfile_version (target_version)) + { + const char *failcode = get_failcode_snippet (source_version); + + if (failcode != NULL) + { + free (compiled_file_name); + free (conftest_file_name); + + conftest_file_name = + xconcatenated_filename (tmpdir->dir_name, + "conftestfail.java", + NULL); + if (write_temp_file (tmpdir, conftest_file_name, + failcode)) + { + free (conftest_file_name); + cleanup_temp_dir (tmpdir); + return true; + } + + compiled_file_name = + xconcatenated_filename (tmpdir->dir_name, + "conftestfail.class", + NULL); + register_temp_file (tmpdir, compiled_file_name); + + java_sources[0] = conftest_file_name; + if (!compile_using_javac (java_sources, 1, + false, source_version, + true, target_version, + tmpdir->dir_name, + false, false, false, true) + && stat (compiled_file_name, &statbuf) >= 0) + { + unlink (compiled_file_name); + + java_sources[0] = conftest_file_name; + if (compile_using_javac (java_sources, 1, + true, source_version, + true, target_version, + tmpdir->dir_name, + false, false, false, true)) + /* "javac -target $target_version" compiled + conftestfail.java successfully, and + "javac -target $target_version -source $source_version" + rejects it. So the -source option is useful. */ + resultp->source_option = true; + } + } + } + + resultp->target_option = true; + resultp->usable = true; + } + else + { + /* Maybe this -target option requires a -source option? Try with + -target and -source options. (Supported by Sun javac 1.4 and + higher.) */ + unlink (compiled_file_name); + + java_sources[0] = conftest_file_name; + if (!compile_using_javac (java_sources, 1, + true, source_version, + true, target_version, + tmpdir->dir_name, + false, false, false, true) + && stat (compiled_file_name, &statbuf) >= 0 + && get_classfile_version (compiled_file_name) + <= corresponding_classfile_version (target_version)) + { + /* "javac -target $target_version -source $source_version" + compiled conftest.java successfully. */ + resultp->source_option = true; + resultp->target_option = true; + resultp->usable = true; + } + } + } + + free (compiled_file_name); + free (conftest_file_name); + + resultp->tested = true; + } + + *usablep = resultp->usable; + *source_option_p = resultp->source_option; + *target_option_p = resultp->target_option; + return false; +} + +static bool +is_jikes_present (void) +{ + static bool jikes_tested; + static bool jikes_present; + + if (!jikes_tested) + { + /* Test for presence of jikes: "jikes 2> /dev/null ; test $? = 1" */ + char *argv[2]; + int exitstatus; + + argv[0] = "jikes"; + argv[1] = NULL; + exitstatus = execute ("jikes", "jikes", argv, false, false, true, true, + true, false, NULL); + jikes_present = (exitstatus == 0 || exitstatus == 1); + jikes_tested = true; + } + + return jikes_present; +} + +/* ============================= Main function ============================= */ + +bool +compile_java_class (const char * const *java_sources, + unsigned int java_sources_count, + const char * const *classpaths, + unsigned int classpaths_count, + const char *source_version, + const char *target_version, + const char *directory, + bool optimize, bool debug, + bool use_minimal_classpath, + bool verbose) +{ + bool err = false; + char *old_JAVA_HOME; + + { + const char *javac = getenv ("JAVAC"); + if (javac != NULL && javac[0] != '\0') + { + bool usable = false; + bool no_assert_option = false; + bool source_option = false; + bool target_option = false; + bool fsource_option = false; + bool ftarget_option = false; + + if (target_version == NULL) + target_version = default_target_version (); + + if (is_envjavac_gcj (javac)) + { + /* It's a version of gcj. */ + if (is_envjavac_gcj43 (javac)) + { + /* It's a version of gcj >= 4.3. Assume the classfile versions + are correct. */ + if (is_envjavac_gcj43_usable (javac, + source_version, target_version, + &usable, + &fsource_option, &ftarget_option)) + { + err = true; + goto done1; + } + } + else + { + /* It's a version of gcj < 4.3. Ignore the version of the + class files that it creates. */ + if (strcmp (target_version, "1.4") == 0 + && strcmp (source_version, "1.4") == 0) + { + if (is_envjavac_oldgcj_14_14_usable (javac, &usable)) + { + err = true; + goto done1; + } + } + else if (strcmp (target_version, "1.4") == 0 + && strcmp (source_version, "1.3") == 0) + { + if (is_envjavac_oldgcj_14_13_usable (javac, + &usable, + &no_assert_option)) + { + err = true; + goto done1; + } + } + } + } + else + { + /* It's not gcj. Assume the classfile versions are correct. */ + if (is_envjavac_nongcj_usable (javac, + source_version, target_version, + &usable, + &source_option, &target_option)) + { + err = true; + goto done1; + } + } + + if (usable) + { + char *old_classpath; + char *javac_with_options; + + /* Set CLASSPATH. */ + old_classpath = + set_classpath (classpaths, classpaths_count, false, verbose); + + javac_with_options = + (no_assert_option + ? xasprintf ("%s -fno-assert", javac) + : xasprintf ("%s%s%s%s%s%s%s%s%s", + javac, + source_option ? " -source " : "", + source_option ? source_version : "", + target_option ? " -target " : "", + target_option ? target_version : "", + fsource_option ? " -fsource=" : "", + fsource_option ? source_version : "", + ftarget_option ? " -ftarget=" : "", + ftarget_option ? target_version : "")); + + err = compile_using_envjavac (javac_with_options, + java_sources, java_sources_count, + directory, optimize, debug, verbose, + false); + + free (javac_with_options); + + /* Reset CLASSPATH. */ + reset_classpath (old_classpath); + + goto done1; + } + } + } + + /* Unset the JAVA_HOME environment variable. */ + old_JAVA_HOME = getenv ("JAVA_HOME"); + if (old_JAVA_HOME != NULL) + { + old_JAVA_HOME = xstrdup (old_JAVA_HOME); + unsetenv ("JAVA_HOME"); + } + + if (is_gcj_present ()) + { + /* It's a version of gcj. */ + bool usable = false; + bool no_assert_option = false; + bool fsource_option = false; + bool ftarget_option = false; + + if (target_version == NULL) + target_version = default_target_version (); + + if (is_gcj_43 ()) + { + /* It's a version of gcj >= 4.3. Assume the classfile versions + are correct. */ + if (is_gcj43_usable (source_version, target_version, + &usable, &fsource_option, &ftarget_option)) + { + err = true; + goto done1; + } + } + else + { + /* It's a version of gcj < 4.3. Ignore the version of the class + files that it creates. + Test whether it supports the desired target-version and + source-version. */ + if (strcmp (target_version, "1.4") == 0 + && strcmp (source_version, "1.4") == 0) + { + if (is_oldgcj_14_14_usable (&usable)) + { + err = true; + goto done1; + } + } + else if (strcmp (target_version, "1.4") == 0 + && strcmp (source_version, "1.3") == 0) + { + if (is_oldgcj_14_13_usable (&usable, &no_assert_option)) + { + err = true; + goto done1; + } + } + } + + if (usable) + { + char *old_classpath; + + /* Set CLASSPATH. We could also use the --CLASSPATH=... option + of gcj. Note that --classpath=... option is different: its + argument should also contain gcj's libgcj.jar, but we don't + know its location. */ + old_classpath = + set_classpath (classpaths, classpaths_count, use_minimal_classpath, + verbose); + + err = compile_using_gcj (java_sources, java_sources_count, + no_assert_option, + fsource_option, source_version, + ftarget_option, target_version, + directory, optimize, debug, verbose, false); + + /* Reset CLASSPATH. */ + reset_classpath (old_classpath); + + goto done2; + } + } + + if (is_javac_present ()) + { + bool usable = false; + bool source_option = false; + bool target_option = false; + + if (target_version == NULL) + target_version = default_target_version (); + + if (is_javac_usable (source_version, target_version, + &usable, &source_option, &target_option)) + { + err = true; + goto done1; + } + + if (usable) + { + char *old_classpath; + + /* Set CLASSPATH. We don't use the "-classpath ..." option because + in JDK 1.1.x its argument should also contain the JDK's + classes.zip, but we don't know its location. (In JDK 1.3.0 it + would work.) */ + old_classpath = + set_classpath (classpaths, classpaths_count, use_minimal_classpath, + verbose); + + err = compile_using_javac (java_sources, java_sources_count, + source_option, source_version, + target_option, target_version, + directory, optimize, debug, verbose, + false); + + /* Reset CLASSPATH. */ + reset_classpath (old_classpath); + + goto done2; + } + } + + if (is_jikes_present ()) + { + /* Test whether it supports the desired target-version and + source-version. */ + bool usable = (strcmp (source_version, "1.3") == 0); + + if (usable) + { + char *old_classpath; + + /* Set CLASSPATH. We could also use the "-classpath ..." option. + Since jikes doesn't come with its own standard library, it + needs a classes.zip or rt.jar or libgcj.jar in the CLASSPATH. + To increase the chance of success, we reuse the current CLASSPATH + if the user has set it. */ + old_classpath = + set_classpath (classpaths, classpaths_count, false, verbose); + + err = compile_using_jikes (java_sources, java_sources_count, + directory, optimize, debug, verbose, + false); + + /* Reset CLASSPATH. */ + reset_classpath (old_classpath); + + goto done2; + } + } + + error (0, 0, _("Java compiler not found, try installing gcj or set $JAVAC")); + err = true; + + done2: + if (old_JAVA_HOME != NULL) + { + xsetenv ("JAVA_HOME", old_JAVA_HOME, 1); + free (old_JAVA_HOME); + } + + done1: + return err; +} diff --git a/gettext-tools/gnulib-lib/javacomp.h b/gettext-tools/gnulib-lib/javacomp.h new file mode 100644 index 0000000..757e82e --- /dev/null +++ b/gettext-tools/gnulib-lib/javacomp.h @@ -0,0 +1,75 @@ +/* Compile a Java program. + Copyright (C) 2001-2002, 2006, 2009-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2001. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _JAVACOMP_H +#define _JAVACOMP_H + +#include + +/* Compile a Java source file to bytecode. + java_sources is an array of source file names. + classpaths is a list of pathnames to be prepended to the CLASSPATH. + + source_version can be: support for + 1.3 inner classes + 1.4 assert keyword + 1.5 generic classes and methods + 1.6 (not yet supported) + target_version can be: classfile version: + 1.1 45.3 + 1.2 46.0 + 1.3 47.0 + 1.4 48.0 + 1.5 49.0 + 1.6 50.0 + target_version can also be given as NULL. In this case, the required + target_version is determined from the found JVM (see javaversion.h). + Specifying target_version is useful when building a library (.jar) that is + useful outside the given package. Passing target_version = NULL is useful + when building an application. + It is unreasonable to ask for: + - target_version < 1.4 with source_version >= 1.4, or + - target_version < 1.5 with source_version >= 1.5, or + - target_version < 1.6 with source_version >= 1.6, + because even Sun's javac doesn't support these combinations. + It is redundant to ask for a target_version > source_version, since the + smaller target_version = source_version will also always work and newer JVMs + support the older target_versions too. Except for the case + target_version = 1.4, source_version = 1.3, which allows gcj versions 3.0 + to 3.2 to be used. + + directory is the target directory. The .class file for class X.Y.Z is + written at directory/X/Y/Z.class. If directory is NULL, the .class + file is written in the source's directory. + use_minimal_classpath = true means to ignore the user's CLASSPATH and + use a minimal one. This is likely to reduce possible problems if the + user's CLASSPATH contains garbage or a classes.zip file of the wrong + Java version. + If verbose, the command to be executed will be printed. + Return false if OK, true on error. */ +extern bool compile_java_class (const char * const *java_sources, + unsigned int java_sources_count, + const char * const *classpaths, + unsigned int classpaths_count, + const char *source_version, + const char *target_version, + const char *directory, + bool optimize, bool debug, + bool use_minimal_classpath, + bool verbose); + +#endif /* _JAVACOMP_H */ diff --git a/gettext-tools/gnulib-lib/javaexec.c b/gettext-tools/gnulib-lib/javaexec.c new file mode 100644 index 0000000..e48f29b --- /dev/null +++ b/gettext-tools/gnulib-lib/javaexec.c @@ -0,0 +1,429 @@ +/* Execute a Java program. + Copyright (C) 2001-2003, 2006-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2001. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include +#include + +/* Specification. */ +#include "javaexec.h" + +#include +#include +#include + +#include "execute.h" +#include "classpath.h" +#include "xsetenv.h" +#include "sh-quote.h" +#include "concat-filename.h" +#include "xalloc.h" +#include "xmalloca.h" +#include "error.h" +#include "gettext.h" + +#define _(str) gettext (str) + + +/* Survey of Java virtual machines. + + A = does it work without CLASSPATH being set + B = does it work with CLASSPATH being set to empty + C = option to set CLASSPATH, other than setting it in the environment + T = test for presence + + Program from A B C T + + $JAVA unknown N Y n/a true + gij GCC 3.0 Y Y n/a gij --version >/dev/null + java JDK 1.1.8 Y Y -classpath P java -version 2>/dev/null + jre JDK 1.1.8 N Y -classpath P jre 2>/dev/null; test $? = 1 + java JDK 1.3.0 Y Y -classpath P java -version 2>/dev/null + jview MS IE Y Y -cp P jview -? >nul; %errorlevel% = 1 + + The CLASSPATH is a colon separated list of pathnames. (On Windows: a + semicolon separated list of pathnames.) + + We try the Java virtual machines in the following order: + 1. getenv ("JAVA"), because the user must be able to override our + preferences, + 2. "gij", because it is a completely free JVM, + 3. "java", because it is a standard JVM, + 4. "jre", comes last because it requires a CLASSPATH environment variable, + 5. "jview", on Windows only, because it is frequently installed. + + We unset the JAVA_HOME environment variable, because a wrong setting of + this variable can confuse the JDK's javac. + */ + +bool +execute_java_class (const char *class_name, + const char * const *classpaths, + unsigned int classpaths_count, + bool use_minimal_classpath, + const char *exe_dir, + const char * const *args, + bool verbose, bool quiet, + execute_fn *executer, void *private_data) +{ + bool err = false; + unsigned int nargs; + char *old_JAVA_HOME; + + /* Count args. */ + { + const char * const *arg; + + for (nargs = 0, arg = args; *arg != NULL; nargs++, arg++) + ; + } + + /* First, try a class compiled to a native code executable. */ + if (exe_dir != NULL) + { + char *exe_pathname = xconcatenated_filename (exe_dir, class_name, EXEEXT); + char *old_classpath; + char **argv = (char **) xmalloca ((1 + nargs + 1) * sizeof (char *)); + unsigned int i; + + /* Set CLASSPATH. */ + old_classpath = + set_classpath (classpaths, classpaths_count, use_minimal_classpath, + verbose); + + argv[0] = exe_pathname; + for (i = 0; i <= nargs; i++) + argv[1 + i] = (char *) args[i]; + + if (verbose) + { + char *command = shell_quote_argv (argv); + printf ("%s\n", command); + free (command); + } + + err = executer (class_name, exe_pathname, argv, private_data); + + /* Reset CLASSPATH. */ + reset_classpath (old_classpath); + + freea (argv); + + goto done1; + } + + { + const char *java = getenv ("JAVA"); + if (java != NULL && java[0] != '\0') + { + /* Because $JAVA may consist of a command and options, we use the + shell. Because $JAVA has been set by the user, we leave all + all environment variables in place, including JAVA_HOME, and + we don't erase the user's CLASSPATH. */ + char *old_classpath; + unsigned int command_length; + char *command; + char *argv[4]; + const char * const *arg; + char *p; + + /* Set CLASSPATH. */ + old_classpath = + set_classpath (classpaths, classpaths_count, false, + verbose); + + command_length = strlen (java); + command_length += 1 + shell_quote_length (class_name); + for (arg = args; *arg != NULL; arg++) + command_length += 1 + shell_quote_length (*arg); + command_length += 1; + + command = (char *) xmalloca (command_length); + p = command; + /* Don't shell_quote $JAVA, because it may consist of a command + and options. */ + memcpy (p, java, strlen (java)); + p += strlen (java); + *p++ = ' '; + p = shell_quote_copy (p, class_name); + for (arg = args; *arg != NULL; arg++) + { + *p++ = ' '; + p = shell_quote_copy (p, *arg); + } + *p++ = '\0'; + /* Ensure command_length was correctly calculated. */ + if (p - command > command_length) + abort (); + + if (verbose) + printf ("%s\n", command); + + argv[0] = "/bin/sh"; + argv[1] = "-c"; + argv[2] = command; + argv[3] = NULL; + err = executer (java, "/bin/sh", argv, private_data); + + freea (command); + + /* Reset CLASSPATH. */ + reset_classpath (old_classpath); + + goto done1; + } + } + + /* Unset the JAVA_HOME environment variable. */ + old_JAVA_HOME = getenv ("JAVA_HOME"); + if (old_JAVA_HOME != NULL) + { + old_JAVA_HOME = xstrdup (old_JAVA_HOME); + unsetenv ("JAVA_HOME"); + } + + { + static bool gij_tested; + static bool gij_present; + + if (!gij_tested) + { + /* Test for presence of gij: "gij --version > /dev/null" */ + char *argv[3]; + int exitstatus; + + argv[0] = "gij"; + argv[1] = "--version"; + argv[2] = NULL; + exitstatus = execute ("gij", "gij", argv, false, false, true, true, + true, false, NULL); + gij_present = (exitstatus == 0); + gij_tested = true; + } + + if (gij_present) + { + char *old_classpath; + char **argv = (char **) xmalloca ((2 + nargs + 1) * sizeof (char *)); + unsigned int i; + + /* Set CLASSPATH. */ + old_classpath = + set_classpath (classpaths, classpaths_count, use_minimal_classpath, + verbose); + + argv[0] = "gij"; + argv[1] = (char *) class_name; + for (i = 0; i <= nargs; i++) + argv[2 + i] = (char *) args[i]; + + if (verbose) + { + char *command = shell_quote_argv (argv); + printf ("%s\n", command); + free (command); + } + + err = executer ("gij", "gij", argv, private_data); + + /* Reset CLASSPATH. */ + reset_classpath (old_classpath); + + freea (argv); + + goto done2; + } + } + + { + static bool java_tested; + static bool java_present; + + if (!java_tested) + { + /* Test for presence of java: "java -version 2> /dev/null" */ + char *argv[3]; + int exitstatus; + + argv[0] = "java"; + argv[1] = "-version"; + argv[2] = NULL; + exitstatus = execute ("java", "java", argv, false, false, true, true, + true, false, NULL); + java_present = (exitstatus == 0); + java_tested = true; + } + + if (java_present) + { + char *old_classpath; + char **argv = (char **) xmalloca ((2 + nargs + 1) * sizeof (char *)); + unsigned int i; + + /* Set CLASSPATH. We don't use the "-classpath ..." option because + in JDK 1.1.x its argument should also contain the JDK's classes.zip, + but we don't know its location. (In JDK 1.3.0 it would work.) */ + old_classpath = + set_classpath (classpaths, classpaths_count, use_minimal_classpath, + verbose); + + argv[0] = "java"; + argv[1] = (char *) class_name; + for (i = 0; i <= nargs; i++) + argv[2 + i] = (char *) args[i]; + + if (verbose) + { + char *command = shell_quote_argv (argv); + printf ("%s\n", command); + free (command); + } + + err = executer ("java", "java", argv, private_data); + + /* Reset CLASSPATH. */ + reset_classpath (old_classpath); + + freea (argv); + + goto done2; + } + } + + { + static bool jre_tested; + static bool jre_present; + + if (!jre_tested) + { + /* Test for presence of jre: "jre 2> /dev/null ; test $? = 1" */ + char *argv[2]; + int exitstatus; + + argv[0] = "jre"; + argv[1] = NULL; + exitstatus = execute ("jre", "jre", argv, false, false, true, true, + true, false, NULL); + jre_present = (exitstatus == 0 || exitstatus == 1); + jre_tested = true; + } + + if (jre_present) + { + char *old_classpath; + char **argv = (char **) xmalloca ((2 + nargs + 1) * sizeof (char *)); + unsigned int i; + + /* Set CLASSPATH. We don't use the "-classpath ..." option because + in JDK 1.1.x its argument should also contain the JDK's classes.zip, + but we don't know its location. */ + old_classpath = + set_classpath (classpaths, classpaths_count, use_minimal_classpath, + verbose); + + argv[0] = "jre"; + argv[1] = (char *) class_name; + for (i = 0; i <= nargs; i++) + argv[2 + i] = (char *) args[i]; + + if (verbose) + { + char *command = shell_quote_argv (argv); + printf ("%s\n", command); + free (command); + } + + err = executer ("jre", "jre", argv, private_data); + + /* Reset CLASSPATH. */ + reset_classpath (old_classpath); + + freea (argv); + + goto done2; + } + } + +#if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ + /* Native Windows, Cygwin */ + { + static bool jview_tested; + static bool jview_present; + + if (!jview_tested) + { + /* Test for presence of jview: "jview -? >nul ; test $? = 1" */ + char *argv[3]; + int exitstatus; + + argv[0] = "jview"; + argv[1] = "-?"; + argv[2] = NULL; + exitstatus = execute ("jview", "jview", argv, false, false, true, true, + true, false, NULL); + jview_present = (exitstatus == 0 || exitstatus == 1); + jview_tested = true; + } + + if (jview_present) + { + char *old_classpath; + char **argv = (char **) xmalloca ((2 + nargs + 1) * sizeof (char *)); + unsigned int i; + + /* Set CLASSPATH. */ + old_classpath = + set_classpath (classpaths, classpaths_count, use_minimal_classpath, + verbose); + + argv[0] = "jview"; + argv[1] = (char *) class_name; + for (i = 0; i <= nargs; i++) + argv[2 + i] = (char *) args[i]; + + if (verbose) + { + char *command = shell_quote_argv (argv); + printf ("%s\n", command); + free (command); + } + + err = executer ("jview", "jview", argv, private_data); + + /* Reset CLASSPATH. */ + reset_classpath (old_classpath); + + freea (argv); + + goto done2; + } + } +#endif + + if (!quiet) + error (0, 0, _("Java virtual machine not found, try installing gij or set $JAVA")); + err = true; + + done2: + if (old_JAVA_HOME != NULL) + { + xsetenv ("JAVA_HOME", old_JAVA_HOME, 1); + free (old_JAVA_HOME); + } + + done1: + return err; +} diff --git a/gettext-tools/gnulib-lib/javaexec.h b/gettext-tools/gnulib-lib/javaexec.h new file mode 100644 index 0000000..ca9bbd0 --- /dev/null +++ b/gettext-tools/gnulib-lib/javaexec.h @@ -0,0 +1,50 @@ +/* Execute a Java program. + Copyright (C) 2001-2002, 2009-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2001. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _JAVAEXEC_H +#define _JAVAEXEC_H + +#include + +typedef bool execute_fn (const char *progname, + const char *prog_path, char **prog_argv, + void *private_data); + +/* Execute a Java class. + class_name is the Java class name to be executed. + classpaths is a list of pathnames to be prepended to the CLASSPATH. + use_minimal_classpath = true means to ignore the user's CLASSPATH and + use a minimal one. This is likely to reduce possible problems if the + user's CLASSPATH contains garbage or a classes.zip file of the wrong + Java version. + exe_dir is a directory that may contain a native executable for the class. + args is a NULL terminated list of arguments to be passed to the program. + If verbose, the command to be executed will be printed. + Then the command is passed to the execute function together with the + private_data argument. This function returns false if OK, true on error. + Return false if OK, true on error. + If quiet, error messages will not be printed. */ +extern bool execute_java_class (const char *class_name, + const char * const *classpaths, + unsigned int classpaths_count, + bool use_minimal_classpath, + const char *exe_dir, + const char * const *args, + bool verbose, bool quiet, + execute_fn *executer, void *private_data); + +#endif /* _JAVAEXEC_H */ diff --git a/gettext-tools/gnulib-lib/javaversion.c b/gettext-tools/gnulib-lib/javaversion.c new file mode 100644 index 0000000..9cf06c3 --- /dev/null +++ b/gettext-tools/gnulib-lib/javaversion.c @@ -0,0 +1,119 @@ +/* Determine the Java version supported by javaexec. + Copyright (C) 2006-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include "javaversion.h" + +#include +#include +#include + +#if ENABLE_RELOCATABLE +# include "relocatable.h" +#else +# define relocate(pathname) (pathname) +#endif + +#include "javaexec.h" +#include "spawn-pipe.h" +#include "wait-process.h" +#include "error.h" +#include "gettext.h" + +#define _(str) gettext (str) + +/* Get PKGDATADIR. */ +#include "configmake.h" + + +struct locals +{ + /* OUT */ + char *line; +}; + +static bool +execute_and_read_line (const char *progname, + const char *prog_path, char **prog_argv, + void *private_data) +{ + struct locals *l = (struct locals *) private_data; + pid_t child; + int fd[1]; + FILE *fp; + char *line; + size_t linesize; + size_t linelen; + int exitstatus; + + /* Open a pipe to the JVM. */ + child = create_pipe_in (progname, prog_path, prog_argv, DEV_NULL, false, + true, false, fd); + + if (child == -1) + return false; + + /* Retrieve its result. */ + fp = fdopen (fd[0], "r"); + if (fp == NULL) + { + error (0, errno, _("fdopen() failed")); + return false; + } + + line = NULL; linesize = 0; + linelen = getline (&line, &linesize, fp); + if (linelen == (size_t)(-1)) + { + error (0, 0, _("%s subprocess I/O error"), progname); + return false; + } + if (linelen > 0 && line[linelen - 1] == '\n') + line[linelen - 1] = '\0'; + + fclose (fp); + + /* Remove zombie process from process list, and retrieve exit status. */ + exitstatus = + wait_subprocess (child, progname, true, false, true, false, NULL); + if (exitstatus != 0) + { + free (line); + return false; + } + + l->line = line; + return false; +} + +char * +javaexec_version (void) +{ + const char *class_name = "javaversion"; + const char *pkgdatadir = relocate (PKGDATADIR); + const char *args[1]; + struct locals locals; + + args[0] = NULL; + locals.line = NULL; + execute_java_class (class_name, &pkgdatadir, 1, true, NULL, args, + false, false, execute_and_read_line, &locals); + + return locals.line; +} diff --git a/gettext-tools/gnulib-lib/javaversion.class b/gettext-tools/gnulib-lib/javaversion.class new file mode 100644 index 0000000..d62585b Binary files /dev/null and b/gettext-tools/gnulib-lib/javaversion.class differ diff --git a/gettext-tools/gnulib-lib/javaversion.h b/gettext-tools/gnulib-lib/javaversion.h new file mode 100644 index 0000000..dc750fe --- /dev/null +++ b/gettext-tools/gnulib-lib/javaversion.h @@ -0,0 +1,39 @@ +/* Determine the Java version supported by javaexec. + Copyright (C) 2006, 2009-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _JAVAVERSION_H +#define _JAVAVERSION_H + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Return information about the Java version used by execute_java_class(). + This is the value of System.getProperty("java.specification.version"). + Some possible values are: 1.1, 1.2, 1.3, 1.4, 1.5, 1.6. Return NULL if + the Java version cannot be determined. */ +extern char * javaexec_version (void); + + +#ifdef __cplusplus +} +#endif + + +#endif /* _JAVAVERSION_H */ diff --git a/gettext-tools/gnulib-lib/javaversion.java b/gettext-tools/gnulib-lib/javaversion.java new file mode 100644 index 0000000..82732d4 --- /dev/null +++ b/gettext-tools/gnulib-lib/javaversion.java @@ -0,0 +1,31 @@ +/* Show the Java version. + * Copyright (C) 2006, 2009-2014 Free Software Foundation, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * This program shows the Java version. + * + * This program _must_ be compiled with + * javac -d . -target 1.1 javaversion.java + * since its purpose is to show the version of _any_ Java implementation. + * + * @author Bruno Haible + */ +public class javaversion { + public static void main (String[] args) { + System.out.println(System.getProperty("java.specification.version")); + } +} diff --git a/gettext-tools/gnulib-lib/libcroco/cr-additional-sel.c b/gettext-tools/gnulib-lib/libcroco/cr-additional-sel.c new file mode 100644 index 0000000..646b8ea --- /dev/null +++ b/gettext-tools/gnulib-lib/libcroco/cr-additional-sel.c @@ -0,0 +1,501 @@ +/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */ + +/* + * This file is part of The Croco Library + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + * Author: Dodji Seketeli + * See COPYRIGHTS file for copyright information. + * + */ + +#include +#include "cr-additional-sel.h" +#include "string.h" + +/** + * CRAdditionalSel: + * + * #CRAdditionalSel abstracts an additionnal selector. + * An additional selector is the selector part + * that comes after the combination of type selectors. + * It can be either "a class selector (the .class part), + * a pseudo class selector, an attribute selector + * or an id selector. + */ + +/** + * cr_additional_sel_new: + * + * Default constructor of #CRAdditionalSel. + * Returns the newly build instance of #CRAdditionalSel. + */ +CRAdditionalSel * +cr_additional_sel_new (void) +{ + CRAdditionalSel *result = NULL; + + result = g_try_malloc (sizeof (CRAdditionalSel)); + + if (result == NULL) { + cr_utils_trace_debug ("Out of memory"); + return NULL; + } + + memset (result, 0, sizeof (CRAdditionalSel)); + + return result; +} + +/** + * cr_additional_sel_new_with_type: + * @a_sel_type: the type of the newly built instance + * of #CRAdditionalSel. + * + * Constructor of #CRAdditionalSel. + * Returns the newly built instance of #CRAdditionalSel. + */ +CRAdditionalSel * +cr_additional_sel_new_with_type (enum AddSelectorType a_sel_type) +{ + CRAdditionalSel *result = NULL; + + result = cr_additional_sel_new (); + + g_return_val_if_fail (result, NULL); + + result->type = a_sel_type; + + return result; +} + +/** + * cr_additional_sel_set_class_name: + * @a_this: the "this pointer" of the current instance + * of #CRAdditionalSel . + * @a_class_name: the new class name to set. + * + * Sets a new class name to a + * CLASS additional selector. + */ +void +cr_additional_sel_set_class_name (CRAdditionalSel * a_this, + CRString * a_class_name) +{ + g_return_if_fail (a_this && a_this->type == CLASS_ADD_SELECTOR); + + if (a_this->content.class_name) { + cr_string_destroy (a_this->content.class_name); + } + + a_this->content.class_name = a_class_name; +} + +/** + * cr_additional_sel_set_id_name: + * @a_this: the "this pointer" of the current instance + * of #CRAdditionalSel . + * @a_id: the new id to set. + * + * Sets a new id name to an + * ID additional selector. + */ +void +cr_additional_sel_set_id_name (CRAdditionalSel * a_this, CRString * a_id) +{ + g_return_if_fail (a_this && a_this->type == ID_ADD_SELECTOR); + + if (a_this->content.id_name) { + cr_string_destroy (a_this->content.id_name); + } + + a_this->content.id_name = a_id; +} + +/** + * cr_additional_sel_set_pseudo: + * @a_this: the "this pointer" of the current instance + * of #CRAdditionalSel . + * @a_pseudo: the new pseudo to set. + * + * Sets a new pseudo to a + * PSEUDO additional selector. + */ +void +cr_additional_sel_set_pseudo (CRAdditionalSel * a_this, CRPseudo * a_pseudo) +{ + g_return_if_fail (a_this + && a_this->type == PSEUDO_CLASS_ADD_SELECTOR); + + if (a_this->content.pseudo) { + cr_pseudo_destroy (a_this->content.pseudo); + } + + a_this->content.pseudo = a_pseudo; +} + +/** + * cr_additional_sel_set_attr_sel: + * @a_this: the "this pointer" of the current instance + * of #CRAdditionalSel . + * @a_sel: the new instance of #CRAttrSel to set. + * + * Sets a new instance of #CRAttrSel to + * a ATTRIBUTE additional selector. + */ +void +cr_additional_sel_set_attr_sel (CRAdditionalSel * a_this, CRAttrSel * a_sel) +{ + g_return_if_fail (a_this && a_this->type == ATTRIBUTE_ADD_SELECTOR); + + if (a_this->content.attr_sel) { + cr_attr_sel_destroy (a_this->content.attr_sel); + } + + a_this->content.attr_sel = a_sel; +} + +/** + * cr_additional_sel_append: + * @a_this: the "this pointer" of the current instance + * of #CRAdditionalSel . + * @a_sel: the new instance to #CRAdditional to append. + * + * Appends a new instance of #CRAdditional to the + * current list of #CRAdditional. + * + * Returns the new list of CRAdditionalSel or NULL if an error arises. + */ +CRAdditionalSel * +cr_additional_sel_append (CRAdditionalSel * a_this, CRAdditionalSel * a_sel) +{ + CRAdditionalSel *cur_sel = NULL; + + g_return_val_if_fail (a_sel, NULL); + + if (a_this == NULL) { + return a_sel; + } + + if (a_sel == NULL) + return NULL; + + for (cur_sel = a_this; + cur_sel && cur_sel->next; cur_sel = cur_sel->next) ; + + g_return_val_if_fail (cur_sel != NULL, NULL); + + cur_sel->next = a_sel; + a_sel->prev = cur_sel; + + return a_this; +} + +/** + * cr_additional_sel_prepend: + * @a_this: the "this pointer" of the current instance + * of #CRAdditionalSel . + * @a_sel: the new instance to #CRAdditional to preappend. + * + * Preppends a new instance of #CRAdditional to the + * current list of #CRAdditional. + * + * Returns the new list of CRAdditionalSel or NULL if an error arises. + */ +CRAdditionalSel * +cr_additional_sel_prepend (CRAdditionalSel * a_this, CRAdditionalSel * a_sel) +{ + g_return_val_if_fail (a_sel, NULL); + + if (a_this == NULL) { + return a_sel; + } + + a_sel->next = a_this; + a_this->prev = a_sel; + + return a_sel; +} + +guchar * +cr_additional_sel_to_string (CRAdditionalSel * a_this) +{ + guchar *result = NULL; + GString *str_buf = NULL; + CRAdditionalSel *cur = NULL; + + g_return_val_if_fail (a_this, NULL); + + str_buf = g_string_new (NULL); + + for (cur = a_this; cur; cur = cur->next) { + switch (cur->type) { + case CLASS_ADD_SELECTOR: + { + guchar *name = NULL; + + if (cur->content.class_name) { + name = g_strndup + (cur->content.class_name->stryng->str, + cur->content.class_name->stryng->len); + + if (name) { + g_string_append_printf + (str_buf, ".%s", + name); + g_free (name); + name = NULL; + } + } + } + break; + + case ID_ADD_SELECTOR: + { + guchar *name = NULL; + + if (cur->content.class_name) { + name = g_strndup + (cur->content.id_name->stryng->str, + cur->content.id_name->stryng->len); + + if (name) { + g_string_append_printf + (str_buf, "#%s", + name); + g_free (name); + name = NULL; + } + } + } + + break; + + case PSEUDO_CLASS_ADD_SELECTOR: + { + if (cur->content.pseudo) { + guchar *tmp_str = NULL; + + tmp_str = cr_pseudo_to_string + (cur->content.pseudo); + if (tmp_str) { + g_string_append_printf + (str_buf, ":%s", + tmp_str); + g_free (tmp_str); + tmp_str = NULL; + } + } + } + break; + + case ATTRIBUTE_ADD_SELECTOR: + if (cur->content.attr_sel) { + guchar *tmp_str = NULL; + + g_string_append_c (str_buf, '['); + tmp_str = cr_attr_sel_to_string + (cur->content.attr_sel); + if (tmp_str) { + g_string_append_printf + (str_buf, "%s]", tmp_str); + g_free (tmp_str); + tmp_str = NULL; + } + } + break; + + default: + break; + } + } + + if (str_buf) { + result = str_buf->str; + g_string_free (str_buf, FALSE); + str_buf = NULL; + } + + return result; +} + +guchar * +cr_additional_sel_one_to_string (CRAdditionalSel *a_this) +{ + guchar *result = NULL; + GString *str_buf = NULL; + + g_return_val_if_fail (a_this, NULL) ; + + str_buf = g_string_new (NULL) ; + + switch (a_this->type) { + case CLASS_ADD_SELECTOR: + { + guchar *name = NULL; + + if (a_this->content.class_name) { + name = g_strndup + (a_this->content.class_name->stryng->str, + a_this->content.class_name->stryng->len); + + if (name) { + g_string_append_printf + (str_buf, ".%s", + name); + g_free (name); + name = NULL; + } + } + } + break; + + case ID_ADD_SELECTOR: + { + guchar *name = NULL; + + if (a_this->content.class_name) { + name = g_strndup + (a_this->content.id_name->stryng->str, + a_this->content.id_name->stryng->len); + + if (name) { + g_string_append_printf + (str_buf, "#%s", + name); + g_free (name); + name = NULL; + } + } + } + + break; + + case PSEUDO_CLASS_ADD_SELECTOR: + { + if (a_this->content.pseudo) { + guchar *tmp_str = NULL; + + tmp_str = cr_pseudo_to_string + (a_this->content.pseudo); + if (tmp_str) { + g_string_append_printf + (str_buf, ":%s", + tmp_str); + g_free (tmp_str); + tmp_str = NULL; + } + } + } + break; + + case ATTRIBUTE_ADD_SELECTOR: + if (a_this->content.attr_sel) { + guchar *tmp_str = NULL; + + g_string_append_printf (str_buf, "["); + tmp_str = cr_attr_sel_to_string + (a_this->content.attr_sel); + if (tmp_str) { + g_string_append_printf + (str_buf, "%s]", tmp_str); + g_free (tmp_str); + tmp_str = NULL; + } + } + break; + + default: + break; + } + + if (str_buf) { + result = str_buf->str; + g_string_free (str_buf, FALSE); + str_buf = NULL; + } + + return result; +} + +/** + * cr_additional_sel_dump: + * @a_this: the "this pointer" of the current instance of + * #CRAdditionalSel. + * @a_fp: the destination file. + * + * Dumps the current instance of #CRAdditionalSel to a file + */ +void +cr_additional_sel_dump (CRAdditionalSel * a_this, FILE * a_fp) +{ + guchar *tmp_str = NULL; + + g_return_if_fail (a_fp); + + if (a_this) { + tmp_str = cr_additional_sel_to_string (a_this); + if (tmp_str) { + fprintf (a_fp, "%s", tmp_str); + g_free (tmp_str); + tmp_str = NULL; + } + } +} + +/** + * cr_additional_sel_destroy: + * @a_this: the "this pointer" of the current instance + * of #CRAdditionalSel . + * + * Destroys an instance of #CRAdditional. + */ +void +cr_additional_sel_destroy (CRAdditionalSel * a_this) +{ + g_return_if_fail (a_this); + + switch (a_this->type) { + case CLASS_ADD_SELECTOR: + cr_string_destroy (a_this->content.class_name); + a_this->content.class_name = NULL; + break; + + case PSEUDO_CLASS_ADD_SELECTOR: + cr_pseudo_destroy (a_this->content.pseudo); + a_this->content.pseudo = NULL; + break; + + case ID_ADD_SELECTOR: + cr_string_destroy (a_this->content.id_name); + a_this->content.id_name = NULL; + break; + + case ATTRIBUTE_ADD_SELECTOR: + cr_attr_sel_destroy (a_this->content.attr_sel); + a_this->content.attr_sel = NULL; + break; + + default: + break; + } + + if (a_this->next) { + cr_additional_sel_destroy (a_this->next); + } + + g_free (a_this); +} diff --git a/gettext-tools/gnulib-lib/libcroco/cr-additional-sel.h b/gettext-tools/gnulib-lib/libcroco/cr-additional-sel.h new file mode 100644 index 0000000..bf5acb6 --- /dev/null +++ b/gettext-tools/gnulib-lib/libcroco/cr-additional-sel.h @@ -0,0 +1,98 @@ +/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */ + +/* + * This file is part of The Croco Library + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + * Author: Dodji Seketeli + * See the COPYRIGHTS file for copyright information. + */ + + +#ifndef __CR_ADD_SEL_H__ +#define __CR_ADD_SEL_H__ + +#include +#include +#include "cr-utils.h" +#include "cr-attr-sel.h" +#include "cr-pseudo.h" +#include "cr-additional-sel.h" + +G_BEGIN_DECLS + +enum AddSelectorType +{ + NO_ADD_SELECTOR = 0 , + CLASS_ADD_SELECTOR = 1 , + PSEUDO_CLASS_ADD_SELECTOR = 1 << 1, + ID_ADD_SELECTOR = 1 << 3, + ATTRIBUTE_ADD_SELECTOR = 1 << 4 +} ; + +union CRAdditionalSelectorContent +{ + CRString *class_name ; + CRString *id_name ; + CRPseudo *pseudo ; + CRAttrSel *attr_sel ; +} ; + +typedef struct _CRAdditionalSel CRAdditionalSel ; + +struct _CRAdditionalSel +{ + enum AddSelectorType type ; + union CRAdditionalSelectorContent content ; + + CRAdditionalSel * next ; + CRAdditionalSel * prev ; + CRParsingLocation location ; +} ; + +CRAdditionalSel * cr_additional_sel_new (void) ; + +CRAdditionalSel * cr_additional_sel_new_with_type (enum AddSelectorType a_sel_type) ; + +CRAdditionalSel * cr_additional_sel_append (CRAdditionalSel *a_this, + CRAdditionalSel *a_sel) ; + +void cr_additional_sel_set_class_name (CRAdditionalSel *a_this, + CRString *a_class_name) ; + +void cr_additional_sel_set_id_name (CRAdditionalSel *a_this, + CRString *a_id) ; + +void cr_additional_sel_set_pseudo (CRAdditionalSel *a_this, + CRPseudo *a_pseudo) ; + +void cr_additional_sel_set_attr_sel (CRAdditionalSel *a_this, + CRAttrSel *a_sel) ; + +CRAdditionalSel * cr_additional_sel_prepend (CRAdditionalSel *a_this, + CRAdditionalSel *a_sel) ; + +guchar * cr_additional_sel_to_string (CRAdditionalSel *a_this) ; + +guchar * cr_additional_sel_one_to_string (CRAdditionalSel *a_this) ; + +void cr_additional_sel_dump (CRAdditionalSel *a_this, FILE *a_fp) ; + +void cr_additional_sel_destroy (CRAdditionalSel *a_this) ; + +G_END_DECLS + +#endif /*__CR_ADD_SEL_H*/ diff --git a/gettext-tools/gnulib-lib/libcroco/cr-attr-sel.c b/gettext-tools/gnulib-lib/libcroco/cr-attr-sel.c new file mode 100644 index 0000000..72ed5e5 --- /dev/null +++ b/gettext-tools/gnulib-lib/libcroco/cr-attr-sel.c @@ -0,0 +1,236 @@ +/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */ + +/* + * This file is part of The Croco Library + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + * See COPYRIGHTS file for copyrights information. + */ + +#include +#include +#include "cr-attr-sel.h" + +/** + * CRAttrSel: + * + * #CRAdditionalSel abstracts an attribute selector. + * Attributes selectors are described in the css2 spec [5.8]. + * There are more generally used in the css2 selectors described in + * css2 spec [5] . + */ + +/** + * cr_attr_sel_new: + * The constructor of #CRAttrSel. + * Returns the newly allocated instance + * of #CRAttrSel. + */ +CRAttrSel * +cr_attr_sel_new (void) +{ + CRAttrSel *result = NULL; + + result = g_malloc0 (sizeof (CRAttrSel)); + + return result; +} + +/** + * cr_attr_sel_append_attr_sel: + * @a_this: the this pointer of the current instance of #CRAttrSel. + * @a_attr_sel: selector to append. + * + * Appends an attribute selector to the current list of + * attribute selectors represented by a_this. + * Returns CR_OK upon successfull completion, an error code otherwise. + */ +enum CRStatus +cr_attr_sel_append_attr_sel (CRAttrSel * a_this, CRAttrSel * a_attr_sel) +{ + CRAttrSel *cur_sel = NULL; + + g_return_val_if_fail (a_this && a_attr_sel, + CR_BAD_PARAM_ERROR); + + for (cur_sel = a_this; + cur_sel->next; + cur_sel = cur_sel->next) ; + + cur_sel->next = a_attr_sel; + a_attr_sel->prev = cur_sel; + + return CR_OK; +} + +/** + * cr_attr_sel_prepend_attr_sel: + *@a_this: the "this pointer" of the current instance *of #CRAttrSel. + *@a_attr_sel: the attribute selector to append. + * + *Prepends an attribute selector to the list of + *attributes selector represented by a_this. + *Returns CR_OK upon successfull completion, an error code otherwise. + */ +enum CRStatus +cr_attr_sel_prepend_attr_sel (CRAttrSel * a_this, + CRAttrSel * a_attr_sel) +{ + g_return_val_if_fail (a_this && a_attr_sel, + CR_BAD_PARAM_ERROR); + + a_attr_sel->next = a_this; + a_this->prev = a_attr_sel; + + return CR_OK; +} + +/** + * cr_attr_sel_to_string: + * @a_this: the current instance of #CRAttrSel. + * + * Serializes an attribute selector into a string + * Returns the serialized attribute selector. + */ +guchar * +cr_attr_sel_to_string (CRAttrSel * a_this) +{ + CRAttrSel *cur = NULL; + guchar *result = NULL; + GString *str_buf = NULL; + + g_return_val_if_fail (a_this, NULL); + + str_buf = g_string_new (NULL); + + for (cur = a_this; cur; cur = cur->next) { + if (cur->prev) { + g_string_append_c (str_buf, ' '); + } + + if (cur->name) { + guchar *name = NULL; + + name = g_strndup (cur->name->stryng->str, + cur->name->stryng->len); + if (name) { + g_string_append (str_buf, name); + g_free (name); + name = NULL; + } + } + + if (cur->value) { + guchar *value = NULL; + + value = g_strndup (cur->value->stryng->str, + cur->value->stryng->len); + if (value) { + switch (cur->match_way) { + case SET: + break; + + case EQUALS: + g_string_append_c (str_buf, '='); + break; + + case INCLUDES: + g_string_append (str_buf, "~="); + break; + + case DASHMATCH: + g_string_append (str_buf, "|="); + break; + + default: + break; + } + + g_string_append_printf + (str_buf, "\"%s\"", value); + + g_free (value); + value = NULL; + } + } + } + + if (str_buf) { + result = str_buf->str; + g_string_free (str_buf, FALSE); + } + + return result; +} + +/** + * cr_attr_sel_dump: + * @a_this: the "this pointer" of the current instance of + * #CRAttrSel. + * @a_fp: the destination file. + * + * Dumps the current instance of #CRAttrSel to a file. + */ +void +cr_attr_sel_dump (CRAttrSel * a_this, FILE * a_fp) +{ + guchar *tmp_str = NULL; + + g_return_if_fail (a_this); + + tmp_str = cr_attr_sel_to_string (a_this); + + if (tmp_str) { + fprintf (a_fp, "%s", tmp_str); + g_free (tmp_str); + tmp_str = NULL; + } +} + +/** + *cr_attr_sel_destroy: + *@a_this: the "this pointer" of the current + *instance of #CRAttrSel. + * + *Destroys the current instance of #CRAttrSel. + *Frees all the fields if they are non null. + */ +void +cr_attr_sel_destroy (CRAttrSel * a_this) +{ + g_return_if_fail (a_this); + + if (a_this->name) { + cr_string_destroy (a_this->name); + a_this->name = NULL; + } + + if (a_this->value) { + cr_string_destroy (a_this->value); + a_this->value = NULL; + } + + if (a_this->next) { + cr_attr_sel_destroy (a_this->next); + a_this->next = NULL; + } + + if (a_this) { + g_free (a_this); + a_this = NULL; + } +} + diff --git a/gettext-tools/gnulib-lib/libcroco/cr-attr-sel.h b/gettext-tools/gnulib-lib/libcroco/cr-attr-sel.h new file mode 100644 index 0000000..18f56a4 --- /dev/null +++ b/gettext-tools/gnulib-lib/libcroco/cr-attr-sel.h @@ -0,0 +1,74 @@ +/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */ + +/* + * This file is part of The Croco Library + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + * Author: Dodji Seketeli + * See COPYRIGHTS file for copyright information. + */ + +#ifndef __CR_ATTR_SEL_H__ +#define __CR_ATTR_SEL_H__ + +#include +#include +#include "cr-utils.h" +#include "cr-parsing-location.h" +#include "cr-string.h" + +G_BEGIN_DECLS + + +struct _CRAttrSel ; +typedef struct _CRAttrSel CRAttrSel ; + +enum AttrMatchWay +{ + NO_MATCH = 0, + SET, + EQUALS, + INCLUDES, + DASHMATCH +} ; + +struct _CRAttrSel +{ + CRString *name ; + CRString *value ; + enum AttrMatchWay match_way ; + CRAttrSel *next ; + CRAttrSel *prev ; + CRParsingLocation location ; +} ; + +CRAttrSel * cr_attr_sel_new (void) ; + +enum CRStatus cr_attr_sel_append_attr_sel (CRAttrSel * a_this, + CRAttrSel *a_attr_sel) ; + +enum CRStatus cr_attr_sel_prepend_attr_sel (CRAttrSel *a_this, + CRAttrSel *a_attr_sel) ; + +guchar * cr_attr_sel_to_string (CRAttrSel *a_this) ; + +void cr_attr_sel_dump (CRAttrSel *a_this, FILE *a_fp) ; + +void cr_attr_sel_destroy (CRAttrSel *a_this) ; + +G_END_DECLS + +#endif /*__CR_ATTR_SEL_H__*/ diff --git a/gettext-tools/gnulib-lib/libcroco/cr-cascade.c b/gettext-tools/gnulib-lib/libcroco/cr-cascade.c new file mode 100644 index 0000000..0888707 --- /dev/null +++ b/gettext-tools/gnulib-lib/libcroco/cr-cascade.c @@ -0,0 +1,215 @@ +/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */ + +/* + * This file is part of The Croco Library + * + * Copyright (C) 2002-2003 Dodji Seketeli + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of the + * GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the + * GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + +/* + *$Id: cr-cascade.c,v 1.7 2005/05/10 19:48:56 dodji Exp $ + */ + +#include +#include +#include "cr-cascade.h" + +#define PRIVATE(a_this) ((a_this)->priv) + +struct _CRCascadePriv { + /** + *the 3 style sheets of the cascade: + *author, user, and useragent sheet. + *Intended to be addressed by + *sheets[ORIGIN_AUTHOR] or sheets[ORIGIN_USER] + *of sheets[ORIGIN_UA] ; + */ + CRStyleSheet *sheets[3]; + guint ref_count; +}; + +/** + * cr_cascade_new: + *@a_author_sheet: the author origin style sheet. May be NULL. + *@a_user_sheet: the user origin style sheet. May be NULL. + *@a_ua_sheet: the user agent origin style sheet. May be NULL. + * + *Constructor of the #CRCascade class. + *Note that all three parameters of this + *method are ref counted and their refcount is increased. + *Their refcount will be decreased at the destruction of + *the instance of #CRCascade. + *So the caller should not call their destructor. The caller + *should call their ref/unref method instead if it wants + * + *Returns the newly built instance of CRCascade or NULL if + *an error arose during constrution. + */ +CRCascade * +cr_cascade_new (CRStyleSheet * a_author_sheet, + CRStyleSheet * a_user_sheet, CRStyleSheet * a_ua_sheet) +{ + CRCascade *result = NULL; + + result = g_try_malloc (sizeof (CRCascade)); + if (!result) { + cr_utils_trace_info ("Out of memory"); + return NULL; + } + memset (result, 0, sizeof (CRCascade)); + + PRIVATE (result) = g_try_malloc (sizeof (CRCascadePriv)); + if (!PRIVATE (result)) { + cr_utils_trace_info ("Out of memory"); + return NULL; + } + memset (PRIVATE (result), 0, sizeof (CRCascadePriv)); + + if (a_author_sheet) { + cr_cascade_set_sheet (result, a_author_sheet, ORIGIN_AUTHOR); + } + if (a_user_sheet) { + cr_cascade_set_sheet (result, a_user_sheet, ORIGIN_USER); + } + if (a_ua_sheet) { + cr_cascade_set_sheet (result, a_ua_sheet, ORIGIN_UA); + } + + return result; +} + +/** + * cr_cascade_get_sheet: + *@a_this: the current instance of #CRCascade. + *@a_origin: the origin of the style sheet as + *defined in the css2 spec in chapter 6.4. + *Gets a given origin sheet. + * + *Gets a sheet, part of the cascade. + *Note that the returned stylesheet + *is refcounted so if the caller wants + *to manage it's lifecycle, it must use + *cr_stylesheet_ref()/cr_stylesheet_unref() instead + *of the cr_stylesheet_destroy() method. + *Returns the style sheet, or NULL if it does not + *exist. + */ +CRStyleSheet * +cr_cascade_get_sheet (CRCascade * a_this, enum CRStyleOrigin a_origin) +{ + g_return_val_if_fail (a_this + && a_origin >= ORIGIN_UA + && a_origin < NB_ORIGINS, NULL); + + return PRIVATE (a_this)->sheets[a_origin]; +} + +/** + * cr_cascade_set_sheet: + *@a_this: the current instance of #CRCascade. + *@a_sheet: the stylesheet to set. + *@a_origin: the origin of the stylesheet. + * + *Sets a stylesheet in the cascade + * + *Returns CR_OK upon successfull completion, an error + *code otherwise. + */ +enum CRStatus +cr_cascade_set_sheet (CRCascade * a_this, + CRStyleSheet * a_sheet, enum CRStyleOrigin a_origin) +{ + g_return_val_if_fail (a_this + && a_sheet + && a_origin >= ORIGIN_UA + && a_origin < NB_ORIGINS, CR_BAD_PARAM_ERROR); + + if (PRIVATE (a_this)->sheets[a_origin]) + cr_stylesheet_unref (PRIVATE (a_this)->sheets[a_origin]); + PRIVATE (a_this)->sheets[a_origin] = a_sheet; + cr_stylesheet_ref (a_sheet); + a_sheet->origin = a_origin; + return CR_OK; +} + +/** + *cr_cascade_ref: + *@a_this: the current instance of #CRCascade + * + *Increases the reference counter of the current instance + *of #CRCascade. + */ +void +cr_cascade_ref (CRCascade * a_this) +{ + g_return_if_fail (a_this && PRIVATE (a_this)); + + PRIVATE (a_this)->ref_count++; +} + +/** + * cr_cascade_unref: + *@a_this: the current instance of + *#CRCascade. + * + *Decrements the reference counter associated + *to this instance of #CRCascade. If the reference + *counter reaches zero, the instance is destroyed + *using cr_cascade_destroy() + */ +void +cr_cascade_unref (CRCascade * a_this) +{ + g_return_if_fail (a_this && PRIVATE (a_this)); + + if (PRIVATE (a_this)->ref_count) + PRIVATE (a_this)->ref_count--; + if (!PRIVATE (a_this)->ref_count) { + cr_cascade_destroy (a_this); + } +} + +/** + * cr_cascade_destroy: + * @a_this: the current instance of #CRCascade + * + * Destructor of #CRCascade. + */ +void +cr_cascade_destroy (CRCascade * a_this) +{ + g_return_if_fail (a_this); + + if (PRIVATE (a_this)) { + gulong i = 0; + + for (i = 0; PRIVATE (a_this)->sheets && i < NB_ORIGINS; i++) { + if (PRIVATE (a_this)->sheets[i]) { + if (cr_stylesheet_unref + (PRIVATE (a_this)->sheets[i]) + == TRUE) { + PRIVATE (a_this)->sheets[i] = NULL; + } + } + } + g_free (PRIVATE (a_this)); + PRIVATE (a_this) = NULL; + } + g_free (a_this); +} diff --git a/gettext-tools/gnulib-lib/libcroco/cr-cascade.h b/gettext-tools/gnulib-lib/libcroco/cr-cascade.h new file mode 100644 index 0000000..37d5c0e --- /dev/null +++ b/gettext-tools/gnulib-lib/libcroco/cr-cascade.h @@ -0,0 +1,74 @@ +/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */ + +/* + * This file is part of The Croco Library + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of the + * GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the + * GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + */ + +/* + *$Id: cr-cascade.h,v 1.6 2004/01/29 22:05:14 dodji Exp $ + */ + +#ifndef __CR_CASCADE_H__ +#define __CR_CASCADE_H__ + +#include "cr-stylesheet.h" + +/** + *@file + *the declaration of the #CRCascade class. + */ + +G_BEGIN_DECLS + + +typedef struct _CRCascadePriv CRCascadePriv ; + +/** + *An abstraction of the "Cascade" defined + *in the css2 spec, chapter 6.4. + */ +typedef struct _CRCascade CRCascade ; + +struct _CRCascade +{ + CRCascadePriv *priv ; +}; + + +CRCascade * cr_cascade_new (CRStyleSheet *a_author_sheet, + CRStyleSheet *a_user_sheet, + CRStyleSheet *a_ua_sheet) ; + +CRStyleSheet * cr_cascade_get_sheet (CRCascade *a_this, + enum CRStyleOrigin a_origin) ; + +enum CRStatus cr_cascade_set_sheet (CRCascade *a_this, + CRStyleSheet *a_sheet, + enum CRStyleOrigin a_origin) ; + +void cr_cascade_ref (CRCascade *a_this) ; + +void cr_cascade_unref (CRCascade *a_this) ; + +void cr_cascade_destroy (CRCascade *a_this) ; + +G_END_DECLS + +#endif /*__CR_CASCADE_H__*/ diff --git a/gettext-tools/gnulib-lib/libcroco/cr-declaration.c b/gettext-tools/gnulib-lib/libcroco/cr-declaration.c new file mode 100644 index 0000000..994d085 --- /dev/null +++ b/gettext-tools/gnulib-lib/libcroco/cr-declaration.c @@ -0,0 +1,823 @@ +/* -*- Mode: C; indent-tabs-mode: ni; c-basic-offset: 8 -*- */ + +/* + * This file is part of The Croco Library + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + * Author: Dodji Seketeli. + * See COPYRIGHTS file for copyright information. + */ + +#include +#include +#include "cr-declaration.h" +#include "cr-statement.h" +#include "cr-parser.h" + +/** + *@CRDeclaration: + * + *The definition of the #CRDeclaration class. + */ + +/** + * dump: + *@a_this: the current instance of #CRDeclaration. + *@a_fp: the destination file pointer. + *@a_indent: the number of indentation white char. + * + *Dumps (serializes) one css declaration to a file. + */ +static void +dump (CRDeclaration * a_this, FILE * a_fp, glong a_indent) +{ + guchar *str = NULL; + + g_return_if_fail (a_this); + + str = cr_declaration_to_string (a_this, a_indent); + if (str) { + fprintf (a_fp, "%s", str); + g_free (str); + str = NULL; + } +} + +/** + * cr_declaration_new: + * @a_statement: the statement this declaration belongs to. can be NULL. + *@a_property: the property string of the declaration + *@a_value: the value expression of the declaration. + *Constructor of #CRDeclaration. + * + *Returns the newly built instance of #CRDeclaration, or NULL in + *case of error. + */ +CRDeclaration * +cr_declaration_new (CRStatement * a_statement, + CRString * a_property, CRTerm * a_value) +{ + CRDeclaration *result = NULL; + + g_return_val_if_fail (a_property, NULL); + + if (a_statement) + g_return_val_if_fail (a_statement + && ((a_statement->type == RULESET_STMT) + || (a_statement->type + == AT_FONT_FACE_RULE_STMT) + || (a_statement->type + == AT_PAGE_RULE_STMT)), NULL); + + result = g_try_malloc (sizeof (CRDeclaration)); + if (!result) { + cr_utils_trace_info ("Out of memory"); + return NULL; + } + memset (result, 0, sizeof (CRDeclaration)); + result->property = a_property; + result->value = a_value; + + if (a_value) { + cr_term_ref (a_value); + } + result->parent_statement = a_statement; + return result; +} + +/** + * cr_declaration_parse_from_buf: + *@a_statement: the parent css2 statement of this + *this declaration. Must be non NULL and of type + *RULESET_STMT (must be a ruleset). + *@a_str: the string that contains the statement. + *@a_enc: the encoding of a_str. + * + *Parses a text buffer that contains + *a css declaration. + *Returns the parsed declaration, or NULL in case of error. + */ +CRDeclaration * +cr_declaration_parse_from_buf (CRStatement * a_statement, + const guchar * a_str, enum CREncoding a_enc) +{ + enum CRStatus status = CR_OK; + CRTerm *value = NULL; + CRString *property = NULL; + CRDeclaration *result = NULL; + CRParser *parser = NULL; + gboolean important = FALSE; + + g_return_val_if_fail (a_str, NULL); + if (a_statement) + g_return_val_if_fail (a_statement->type == RULESET_STMT, + NULL); + + parser = cr_parser_new_from_buf ((guchar*)a_str, strlen (a_str), a_enc, FALSE); + g_return_val_if_fail (parser, NULL); + + status = cr_parser_try_to_skip_spaces_and_comments (parser); + if (status != CR_OK) + goto cleanup; + + status = cr_parser_parse_declaration (parser, &property, + &value, &important); + if (status != CR_OK || !property) + goto cleanup; + + result = cr_declaration_new (a_statement, property, value); + if (result) { + property = NULL; + value = NULL; + result->important = important; + } + + cleanup: + + if (parser) { + cr_parser_destroy (parser); + parser = NULL; + } + + if (property) { + cr_string_destroy (property); + property = NULL; + } + + if (value) { + cr_term_destroy (value); + value = NULL; + } + + return result; +} + +/** + * cr_declaration_parse_list_from_buf: + *@a_str: the input buffer that contains the list of declaration to + *parse. + *@a_enc: the encoding of a_str + * + *Parses a ';' separated list of properties declaration. + *Returns the parsed list of declaration, NULL if parsing failed. + */ +CRDeclaration * +cr_declaration_parse_list_from_buf (const guchar * a_str, + enum CREncoding a_enc) +{ + + enum CRStatus status = CR_OK; + CRTerm *value = NULL; + CRString *property = NULL; + CRDeclaration *result = NULL, + *cur_decl = NULL; + CRParser *parser = NULL; + CRTknzr *tokenizer = NULL; + gboolean important = FALSE; + + g_return_val_if_fail (a_str, NULL); + + parser = cr_parser_new_from_buf ((guchar*)a_str, strlen (a_str), a_enc, FALSE); + g_return_val_if_fail (parser, NULL); + status = cr_parser_get_tknzr (parser, &tokenizer); + if (status != CR_OK || !tokenizer) { + if (status == CR_OK) + status = CR_ERROR; + goto cleanup; + } + status = cr_parser_try_to_skip_spaces_and_comments (parser); + if (status != CR_OK) + goto cleanup; + + status = cr_parser_parse_declaration (parser, &property, + &value, &important); + if (status != CR_OK || !property) { + if (status != CR_OK) + status = CR_ERROR; + goto cleanup; + } + result = cr_declaration_new (NULL, property, value); + if (result) { + property = NULL; + value = NULL; + result->important = important; + } + /*now, go parse the other declarations */ + for (;;) { + guint32 c = 0; + + cr_parser_try_to_skip_spaces_and_comments (parser); + status = cr_tknzr_peek_char (tokenizer, &c); + if (status != CR_OK) { + if (status == CR_END_OF_INPUT_ERROR) + status = CR_OK; + goto cleanup; + } + if (c == ';') { + status = cr_tknzr_read_char (tokenizer, &c); + } else { + break; + } + important = FALSE; + cr_parser_try_to_skip_spaces_and_comments (parser); + status = cr_parser_parse_declaration (parser, &property, + &value, &important); + if (status != CR_OK || !property) { + if (status == CR_END_OF_INPUT_ERROR) { + status = CR_OK; + } + break; + } + cur_decl = cr_declaration_new (NULL, property, value); + if (cur_decl) { + cur_decl->important = important; + result = cr_declaration_append (result, cur_decl); + property = NULL; + value = NULL; + cur_decl = NULL; + } else { + break; + } + } + + cleanup: + + if (parser) { + cr_parser_destroy (parser); + parser = NULL; + } + + if (property) { + cr_string_destroy (property); + property = NULL; + } + + if (value) { + cr_term_destroy (value); + value = NULL; + } + + if (status != CR_OK && result) { + cr_declaration_destroy (result); + result = NULL; + } + return result; +} + +/** + * cr_declaration_append: + *@a_this: the current declaration list. + *@a_new: the declaration to append. + * + *Appends a new declaration to the current declarations list. + *Returns the declaration list with a_new appended to it, or NULL + *in case of error. + */ +CRDeclaration * +cr_declaration_append (CRDeclaration * a_this, CRDeclaration * a_new) +{ + CRDeclaration *cur = NULL; + + g_return_val_if_fail (a_new, NULL); + + if (!a_this) + return a_new; + + for (cur = a_this; cur && cur->next; cur = cur->next) ; + + cur->next = a_new; + a_new->prev = cur; + + return a_this; +} + +/** + * cr_declaration_unlink: + *@a_decls: the declaration to unlink. + * + *Unlinks the declaration from the declaration list. + *case of a successfull completion, NULL otherwise. + * + *Returns a pointer to the unlinked declaration in + */ +CRDeclaration * +cr_declaration_unlink (CRDeclaration * a_decl) +{ + CRDeclaration *result = a_decl; + + g_return_val_if_fail (result, NULL); + + /* + *some sanity checks first + */ + if (a_decl->prev) { + g_return_val_if_fail (a_decl->prev->next == a_decl, NULL); + + } + if (a_decl->next) { + g_return_val_if_fail (a_decl->next->prev == a_decl, NULL); + } + + /* + *now, the real unlinking job. + */ + if (a_decl->prev) { + a_decl->prev->next = a_decl->next; + } + if (a_decl->next) { + a_decl->next->prev = a_decl->prev; + } + if (a_decl->parent_statement) { + CRDeclaration **children_decl_ptr = NULL; + + switch (a_decl->parent_statement->type) { + case RULESET_STMT: + if (a_decl->parent_statement->kind.ruleset) { + children_decl_ptr = + &a_decl->parent_statement-> + kind.ruleset->decl_list; + } + + break; + + case AT_FONT_FACE_RULE_STMT: + if (a_decl->parent_statement->kind.font_face_rule) { + children_decl_ptr = + &a_decl->parent_statement-> + kind.font_face_rule->decl_list; + } + break; + case AT_PAGE_RULE_STMT: + if (a_decl->parent_statement->kind.page_rule) { + children_decl_ptr = + &a_decl->parent_statement-> + kind.page_rule->decl_list; + } + + default: + break; + } + if (children_decl_ptr + && *children_decl_ptr && *children_decl_ptr == a_decl) + *children_decl_ptr = (*children_decl_ptr)->next; + } + + a_decl->next = NULL; + a_decl->prev = NULL; + a_decl->parent_statement = NULL; + + return result; +} + +/** + * cr_declaration_prepend: + * @a_this: the current declaration list. + * @a_new: the declaration to prepend. + * + * prepends a declaration to the current declaration list. + * + * Returns the list with a_new prepended or NULL in case of error. + */ +CRDeclaration * +cr_declaration_prepend (CRDeclaration * a_this, CRDeclaration * a_new) +{ + CRDeclaration *cur = NULL; + + g_return_val_if_fail (a_new, NULL); + + if (!a_this) + return a_new; + + a_this->prev = a_new; + a_new->next = a_this; + + for (cur = a_new; cur && cur->prev; cur = cur->prev) ; + + return cur; +} + +/** + * cr_declaration_append2: + *@a_this: the current declaration list. + *@a_prop: the property string of the declaration to append. + *@a_value: the value of the declaration to append. + * + *Appends a declaration to the current declaration list. + *Returns the list with the new property appended to it, or NULL in + *case of an error. + */ +CRDeclaration * +cr_declaration_append2 (CRDeclaration * a_this, + CRString * a_prop, CRTerm * a_value) +{ + CRDeclaration *new_elem = NULL; + + if (a_this) { + new_elem = cr_declaration_new (a_this->parent_statement, + a_prop, a_value); + } else { + new_elem = cr_declaration_new (NULL, a_prop, a_value); + } + + g_return_val_if_fail (new_elem, NULL); + + return cr_declaration_append (a_this, new_elem); +} + +/** + * cr_declaration_dump: + *@a_this: the current instance of #CRDeclaration. + *@a_fp: the destination file. + *@a_indent: the number of indentation white char. + *@a_one_per_line: whether to put one declaration per line of not . + * + * + *Dumps a declaration list to a file. + */ +void +cr_declaration_dump (CRDeclaration * a_this, FILE * a_fp, glong a_indent, + gboolean a_one_per_line) +{ + CRDeclaration *cur = NULL; + + g_return_if_fail (a_this); + + for (cur = a_this; cur; cur = cur->next) { + if (cur->prev) { + if (a_one_per_line == TRUE) + fprintf (a_fp, ";\n"); + else + fprintf (a_fp, "; "); + } + dump (cur, a_fp, a_indent); + } +} + +/** + * cr_declaration_dump_one: + *@a_this: the current instance of #CRDeclaration. + *@a_fp: the destination file. + *@a_indent: the number of indentation white char. + * + *Dumps the first declaration of the declaration list to a file. + */ +void +cr_declaration_dump_one (CRDeclaration * a_this, FILE * a_fp, glong a_indent) +{ + g_return_if_fail (a_this); + + dump (a_this, a_fp, a_indent); +} + +/** + * cr_declaration_to_string: + *@a_this: the current instance of #CRDeclaration. + *@a_indent: the number of indentation white char + *to put before the actual serialisation. + * + *Serializes the declaration into a string + *Returns the serialized form the declaration. The caller must + *free the string using g_free(). + */ +gchar * +cr_declaration_to_string (CRDeclaration * a_this, gulong a_indent) +{ + GString *stringue = NULL; + + guchar *str = NULL, + *result = NULL; + + g_return_val_if_fail (a_this, NULL); + + stringue = g_string_new (NULL); + + if (a_this->property + && a_this->property->stryng + && a_this->property->stryng->str) { + str = g_strndup (a_this->property->stryng->str, + a_this->property->stryng->len); + if (str) { + cr_utils_dump_n_chars2 (' ', stringue, + a_indent); + g_string_append (stringue, str); + g_free (str); + str = NULL; + } else + goto error; + + if (a_this->value) { + guchar *value_str = NULL; + + value_str = cr_term_to_string (a_this->value); + if (value_str) { + g_string_append_printf (stringue, " : %s", + value_str); + g_free (value_str); + } else + goto error; + } + if (a_this->important == TRUE) { + g_string_append_printf (stringue, " %s", + "!important"); + } + } + if (stringue && stringue->str) { + result = stringue->str; + g_string_free (stringue, FALSE); + } + return result; + + error: + if (stringue) { + g_string_free (stringue, TRUE); + stringue = NULL; + } + if (str) { + g_free (str); + str = NULL; + } + + return result; +} + +/** + * cr_declaration_list_to_string: + *@a_this: the current instance of #CRDeclaration. + *@a_indent: the number of indentation white char + *to put before the actual serialisation. + * + *Serializes the declaration list into a string + */ +guchar * +cr_declaration_list_to_string (CRDeclaration * a_this, gulong a_indent) +{ + CRDeclaration *cur = NULL; + GString *stringue = NULL; + guchar *str = NULL, + *result = NULL; + + g_return_val_if_fail (a_this, NULL); + + stringue = g_string_new (NULL); + + for (cur = a_this; cur; cur = cur->next) { + str = cr_declaration_to_string (cur, a_indent); + if (str) { + g_string_append_printf (stringue, "%s;", str); + g_free (str); + } else + break; + } + if (stringue && stringue->str) { + result = stringue->str; + g_string_free (stringue, FALSE); + } + + return result; +} + +/** + * cr_declaration_list_to_string2: + *@a_this: the current instance of #CRDeclaration. + *@a_indent: the number of indentation white char + @a_one_decl_per_line: whether to output one doc per line or not. + *to put before the actual serialisation. + * + *Serializes the declaration list into a string + *Returns the serialized form the declararation. + */ +guchar * +cr_declaration_list_to_string2 (CRDeclaration * a_this, + gulong a_indent, gboolean a_one_decl_per_line) +{ + CRDeclaration *cur = NULL; + GString *stringue = NULL; + guchar *str = NULL, + *result = NULL; + + g_return_val_if_fail (a_this, NULL); + + stringue = g_string_new (NULL); + + for (cur = a_this; cur; cur = cur->next) { + str = cr_declaration_to_string (cur, a_indent); + if (str) { + if (a_one_decl_per_line == TRUE) { + if (cur->next) + g_string_append_printf (stringue, + "%s;\n", str); + else + g_string_append (stringue, + str); + } else { + if (cur->next) + g_string_append_printf (stringue, + "%s;", str); + else + g_string_append (stringue, + str); + } + g_free (str); + } else + break; + } + if (stringue && stringue->str) { + result = stringue->str; + g_string_free (stringue, FALSE); + } + + return result; +} + +/** + * cr_declaration_nr_props: + *@a_this: the current instance of #CRDeclaration. + *Return the number of properties in the declaration + */ +gint +cr_declaration_nr_props (CRDeclaration * a_this) +{ + CRDeclaration *cur = NULL; + int nr = 0; + + g_return_val_if_fail (a_this, -1); + + for (cur = a_this; cur; cur = cur->next) + nr++; + return nr; +} + +/** + * cr_declaration_get_from_list: + *@a_this: the current instance of #CRDeclaration. + *@itemnr: the index into the declaration list. + * + *Use an index to get a CRDeclaration from the declaration list. + * + *Returns #CRDeclaration at position itemnr, + *if itemnr > number of declarations - 1, + *it will return NULL. + */ +CRDeclaration * +cr_declaration_get_from_list (CRDeclaration * a_this, int itemnr) +{ + CRDeclaration *cur = NULL; + int nr = 0; + + g_return_val_if_fail (a_this, NULL); + + for (cur = a_this; cur; cur = cur->next) + if (nr++ == itemnr) + return cur; + return NULL; +} + +/** + * cr_declaration_get_by_prop_name: + *@a_this: the current instance of #CRDeclaration. + *@a_prop: the property name to search for. + * + *Use property name to get a CRDeclaration from the declaration list. + *Returns #CRDeclaration with property name a_prop, or NULL if not found. + */ +CRDeclaration * +cr_declaration_get_by_prop_name (CRDeclaration * a_this, + const guchar * a_prop) +{ + CRDeclaration *cur = NULL; + + g_return_val_if_fail (a_this, NULL); + g_return_val_if_fail (a_prop, NULL); + + for (cur = a_this; cur; cur = cur->next) { + if (cur->property + && cur->property->stryng + && cur->property->stryng->str) { + if (!strcmp (cur->property->stryng->str, + a_prop)) { + return cur; + } + } + } + return NULL; +} + +/** + * cr_declaration_ref: + *@a_this: the current instance of #CRDeclaration. + * + *Increases the ref count of the current instance of #CRDeclaration. + */ +void +cr_declaration_ref (CRDeclaration * a_this) +{ + g_return_if_fail (a_this); + + a_this->ref_count++; +} + +/** + * cr_declaration_unref: + *@param a_this the current instance of #CRDeclaration. + *@return TRUE if the current instance of #CRDeclaration has been destroyed + *(ref count reached zero), FALSE otherwise. + * + *Decrements the ref count of the current instance of #CRDeclaration. + *If the ref count reaches zero, the current instance of #CRDeclaration + *if destroyed. + *Returns TRUE if the object got destroyed, FALSE otherwise. + */ +gboolean +cr_declaration_unref (CRDeclaration * a_this) +{ + g_return_val_if_fail (a_this, FALSE); + + if (a_this->ref_count) { + a_this->ref_count--; + } + + if (a_this->ref_count == 0) { + cr_declaration_destroy (a_this); + return TRUE; + } + return FALSE; +} + +/** + * cr_declaration_destroy: + *@a_this: the current instance of #CRDeclaration. + * + *Destructor of the declaration list. + */ +void +cr_declaration_destroy (CRDeclaration * a_this) +{ + CRDeclaration *cur = NULL; + + g_return_if_fail (a_this); + + /* + *Go get the tail of the list. + *Meanwhile, free each property/value pair contained in the list. + */ + for (cur = a_this; cur && cur->next; cur = cur->next) { + if (cur->property) { + cr_string_destroy (cur->property); + cur->property = NULL; + } + + if (cur->value) { + cr_term_destroy (cur->value); + cur->value = NULL; + } + } + + if (cur) { + if (cur->property) { + cr_string_destroy (cur->property); + cur->property = NULL; + } + + if (cur->value) { + cr_term_destroy (cur->value); + cur->value = NULL; + } + } + + /*in case the list contains only one element */ + if (cur && !cur->prev) { + g_free (cur); + return; + } + + /*walk backward the list and free each "next" element */ + for (cur = cur->prev; cur && cur->prev; cur = cur->prev) { + if (cur->next) { + g_free (cur->next); + cur->next = NULL; + } + } + + if (!cur) + return; + + if (cur->next) { + g_free (cur->next); + cur->next = NULL; + } + + g_free (cur); +} diff --git a/gettext-tools/gnulib-lib/libcroco/cr-declaration.h b/gettext-tools/gnulib-lib/libcroco/cr-declaration.h new file mode 100644 index 0000000..2ccfc43 --- /dev/null +++ b/gettext-tools/gnulib-lib/libcroco/cr-declaration.h @@ -0,0 +1,136 @@ +/* -*- Mode: C; indent-tabs-mode: ni; c-basic-offset: 8 -*- */ + +/* + * This file is part of The Croco Library + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + * See the COPYRIGHTS file for copyright information. + */ + +#ifndef __CR_DECLARATION_H__ +#define __CR_DECLARATION_H__ + +#include +#include "cr-utils.h" +#include "cr-term.h" +#include "cr-parsing-location.h" + +G_BEGIN_DECLS + +/** + *@file + *The declaration of the #CRDeclaration class. + */ + +/*forward declaration of what is defined in cr-statement.h*/ +typedef struct _CRStatement CRStatement ; + +/** + *The abstraction of a css declaration defined by the + *css2 spec in chapter 4. + *It is actually a chained list of property/value pairs. + */ +typedef struct _CRDeclaration CRDeclaration ; +struct _CRDeclaration +{ + /**The property.*/ + CRString *property ; + + /**The value of the property.*/ + CRTerm *value ; + + /*the ruleset that contains this declaration*/ + CRStatement *parent_statement ; + + /*the next declaration*/ + CRDeclaration *next ; + + /*the previous one declaration*/ + CRDeclaration *prev ; + + /*does the declaration have the important keyword ?*/ + gboolean important ; + + glong ref_count ; + + CRParsingLocation location ; + /*reserved for future usage*/ + gpointer rfu0 ; + gpointer rfu1 ; + gpointer rfu2 ; + gpointer rfu3 ; +} ; + + +CRDeclaration * cr_declaration_new (CRStatement *a_statement, + CRString *a_property, + CRTerm *a_value) ; + + +CRDeclaration * cr_declaration_parse_from_buf (CRStatement *a_statement, + const guchar *a_str, + enum CREncoding a_enc) ; + +CRDeclaration * cr_declaration_parse_list_from_buf (const guchar *a_str, + enum CREncoding a_enc) ; + +CRDeclaration * cr_declaration_append (CRDeclaration *a_this, + CRDeclaration *a_new) ; + +CRDeclaration * cr_declaration_append2 (CRDeclaration *a_this, + CRString *a_prop, + CRTerm *a_value) ; + +CRDeclaration * cr_declaration_prepend (CRDeclaration *a_this, + CRDeclaration *a_new) ; + +CRDeclaration * cr_declaration_unlink (CRDeclaration * a_decl) ; + +void +cr_declaration_dump (CRDeclaration *a_this, + FILE *a_fp, glong a_indent, + gboolean a_one_per_line) ; + +void cr_declaration_dump_one (CRDeclaration *a_this, + FILE *a_fp, glong a_indent) ; + +gint cr_declaration_nr_props (CRDeclaration *a_this) ; + +CRDeclaration * cr_declaration_get_from_list (CRDeclaration *a_this, + int itemnr) ; + +CRDeclaration * cr_declaration_get_by_prop_name (CRDeclaration *a_this, + const guchar *a_str) ; + +gchar * cr_declaration_to_string (CRDeclaration *a_this, + gulong a_indent) ; + +guchar * cr_declaration_list_to_string (CRDeclaration *a_this, + gulong a_indent) ; + +guchar * cr_declaration_list_to_string2 (CRDeclaration *a_this, + gulong a_indent, + gboolean a_one_decl_per_line) ; + +void cr_declaration_ref (CRDeclaration *a_this) ; + +gboolean cr_declaration_unref (CRDeclaration *a_this) ; + +void cr_declaration_destroy (CRDeclaration *a_this) ; + +G_END_DECLS + +#endif /*__CR_DECLARATION_H__*/ diff --git a/gettext-tools/gnulib-lib/libcroco/cr-doc-handler.c b/gettext-tools/gnulib-lib/libcroco/cr-doc-handler.c new file mode 100644 index 0000000..df44b68 --- /dev/null +++ b/gettext-tools/gnulib-lib/libcroco/cr-doc-handler.c @@ -0,0 +1,275 @@ +/* -*- Mode: C; indent-tabs-mode: ni; c-basic-offset: 8 -*- */ + +/* + * This file is part of The Croco Library + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + * See COPRYRIGHTS file for copyright information. + */ + +#include +#include +#include "cr-doc-handler.h" +#include "cr-parser.h" + +/** + *@CRDocHandler: + * + *The definition of the CRDocHandler class. + *Contains methods to instantiate, destroy, + *and initialyze instances of #CRDocHandler + *to custom values. + */ + +#define PRIVATE(obj) (obj)->priv + +struct _CRDocHandlerPriv { + /** + *This pointer is to hold an application parsing context. + *For example, it used by the Object Model parser to + *store it parsing context. #CRParser does not touch it, but + *#CROMParser does. #CROMParser allocates this pointer at + *the beginning of the css document, and frees it at the end + *of the document. + */ + gpointer context; + + /** + *The place where #CROMParser puts the result of its parsing, if + *any. + */ + gpointer result; + /** + *a pointer to the parser used to parse + *the current document. + */ + CRParser *parser ; +}; + +/** + * cr_doc_handler_new: + *Constructor of #CRDocHandler. + * + *Returns the newly built instance of + *#CRDocHandler + * + */ +CRDocHandler * +cr_doc_handler_new (void) +{ + CRDocHandler *result = NULL; + + result = g_try_malloc (sizeof (CRDocHandler)); + + g_return_val_if_fail (result, NULL); + + memset (result, 0, sizeof (CRDocHandler)); + + result->priv = g_try_malloc (sizeof (CRDocHandlerPriv)); + if (!result->priv) { + cr_utils_trace_info ("Out of memory exception"); + g_free (result); + return NULL; + } + + cr_doc_handler_set_default_sac_handler (result); + + return result; +} + +/** + * cr_doc_handler_get_ctxt: + *@a_this: the current instance of #CRDocHandler. + *@a_ctxt: out parameter. The new parsing context. + * + *Gets the private parsing context associated to the document handler + *The private parsing context is used by libcroco only. + * + *Returns CR_OK upon successfull completion, an error code otherwise. + */ +enum CRStatus +cr_doc_handler_get_ctxt (CRDocHandler * a_this, gpointer * a_ctxt) +{ + g_return_val_if_fail (a_this && a_this->priv, CR_BAD_PARAM_ERROR); + + *a_ctxt = a_this->priv->context; + + return CR_OK; +} + +/** + * cr_doc_handler_set_ctxt: + *@a_this: the current instance of #CRDocHandler + *@a_ctxt: a pointer to the parsing context. + * + *Sets the private parsing context. + *This is used by libcroco only. + *Returns CR_OK upon successfull completion, an error code otherwise. + */ +enum CRStatus +cr_doc_handler_set_ctxt (CRDocHandler * a_this, gpointer a_ctxt) +{ + g_return_val_if_fail (a_this && a_this->priv, CR_BAD_PARAM_ERROR); + a_this->priv->context = a_ctxt; + return CR_OK; +} + +/** + * cr_doc_handler_get_result: + *@a_this: the current instance of #CRDocHandler + *@a_result: out parameter. The returned result. + * + *Gets the private parsing result. + *The private parsing result is used by libcroco only. + * + *Returns CR_OK upon successfull completion, an error code otherwise. + */ +enum CRStatus +cr_doc_handler_get_result (CRDocHandler * a_this, gpointer * a_result) +{ + g_return_val_if_fail (a_this && a_this->priv, CR_BAD_PARAM_ERROR); + + *a_result = a_this->priv->result; + + return CR_OK; +} + +/** + * cr_doc_handler_set_result: + *@a_this: the current instance of #CRDocHandler + *@a_result: the new result. + * + *Sets the private parsing context. + *This is used by libcroco only. + * + *Returns CR_OK upon successfull completion, an error code otherwise. + */ +enum CRStatus +cr_doc_handler_set_result (CRDocHandler * a_this, gpointer a_result) +{ + g_return_val_if_fail (a_this && a_this->priv, CR_BAD_PARAM_ERROR); + a_this->priv->result = a_result; + return CR_OK; +} + +/** + *cr_doc_handler_set_default_sac_handler: + *@a_this: a pointer to the current instance of #CRDocHandler. + * + *Sets the sac handlers contained in the current + *instance of DocHandler to the default handlers. + *For the time being the default handlers are + *test handlers. This is expected to change in a + *near future, when the libcroco gets a bit debugged. + * + *Returns CR_OK upon successfull completion, an error code otherwise. + */ +enum CRStatus +cr_doc_handler_set_default_sac_handler (CRDocHandler * a_this) +{ + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); + + a_this->start_document = NULL; + a_this->end_document = NULL; + a_this->import_style = NULL; + a_this->namespace_declaration = NULL; + a_this->comment = NULL; + a_this->start_selector = NULL; + a_this->end_selector = NULL; + a_this->property = NULL; + a_this->start_font_face = NULL; + a_this->end_font_face = NULL; + a_this->start_media = NULL; + a_this->end_media = NULL; + a_this->start_page = NULL; + a_this->end_page = NULL; + a_this->ignorable_at_rule = NULL; + a_this->error = NULL; + a_this->unrecoverable_error = NULL; + return CR_OK; +} + +/** + * cr_doc_handler_ref: + *@a_this: the current instance of #CRDocHandler. + */ +void +cr_doc_handler_ref (CRDocHandler * a_this) +{ + g_return_if_fail (a_this); + + a_this->ref_count++; +} + +/** + * cr_doc_handler_unref: + *@a_this: the currrent instance of #CRDocHandler. + * + *Decreases the ref count of the current instance of #CRDocHandler. + *If the ref count reaches '0' then, destroys the instance. + * + *Returns TRUE if the instance as been destroyed, FALSE otherwise. + */ +gboolean +cr_doc_handler_unref (CRDocHandler * a_this) +{ + g_return_val_if_fail (a_this, FALSE); + + if (a_this->ref_count > 0) { + a_this->ref_count--; + } + + if (a_this->ref_count == 0) { + cr_doc_handler_destroy (a_this); + return TRUE; + } + return FALSE ; +} + +/** + * cr_doc_handler_destroy: + *@a_this: the instance of #CRDocHandler to + *destroy. + * + *The destructor of the #CRDocHandler class. + */ +void +cr_doc_handler_destroy (CRDocHandler * a_this) +{ + g_return_if_fail (a_this); + + if (a_this->priv) { + g_free (a_this->priv); + a_this->priv = NULL; + } + g_free (a_this); +} + +/** + * cr_doc_handler_associate_a_parser: + *Associates a parser to the current document handler + *@a_this: the current instance of document handler. + *@a_parser: the parser to associate. + */ +void +cr_doc_handler_associate_a_parser (CRDocHandler *a_this, + gpointer a_parser) +{ + g_return_if_fail (a_this && PRIVATE (a_this) + && a_parser) ; + + PRIVATE (a_this)->parser = a_parser ; +} diff --git a/gettext-tools/gnulib-lib/libcroco/cr-doc-handler.h b/gettext-tools/gnulib-lib/libcroco/cr-doc-handler.h new file mode 100644 index 0000000..4cd3096 --- /dev/null +++ b/gettext-tools/gnulib-lib/libcroco/cr-doc-handler.h @@ -0,0 +1,298 @@ +/* -*- Mode: C; indent-tabs-mode: ni; c-basic-offset: 8 -*- */ + +/* + * This file is part of The Croco Library + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + * See the COPYRIGHTS file for copyright information. + */ + +#ifndef __CR_DOC_HANDLER_H__ +#define __CR_DOC_HANDLER_H__ + +/** + *@file + *The declaration of the #CRDocumentHandler class. + *This class is actually the parsing events handler. + */ + +#include +#include "cr-utils.h" +#include "cr-input.h" +#include "cr-stylesheet.h" + +G_BEGIN_DECLS + + +typedef struct _CRDocHandler CRDocHandler ; + +struct _CRDocHandlerPriv ; +typedef struct _CRDocHandlerPriv CRDocHandlerPriv ; + + +/** + *The SAC document handler. + *An instance of this class is to + *be passed to a parser. Then, during the parsing + *the parser calls the convenient function pointer + *whenever a particular event (a css construction) occurs. + */ +struct _CRDocHandler +{ + CRDocHandlerPriv *priv ; + + /** + *This pointer is to be used by the application for + *it custom needs. It is there to extend the doc handler. + */ + gpointer app_data ; + + /** + *Is called at the beginning of the parsing of the document. + *@param a_this a pointer to the current instance of + *#CRDocHandler. + */ + void (*start_document) (CRDocHandler *a_this) ; + + /** + *Is called to notify the end of the parsing of the document. + *@param a_this a pointer to the current instance of + *#CRDocHandler. + */ + void (*end_document) (CRDocHandler *a_this) ; + + /** + *Is called to notify an at charset rule. + *@param a_this the document handler. + *@param a_charset the declared charset. + */ + void (*charset) (CRDocHandler *a_this, + CRString *a_charset, + CRParsingLocation *a_charset_sym_location) ; + + /** + *Is called to notify an import statement in + *the stylesheet. + *@param a_this the current instance of #CRDocHandler. + *@param a_media_list a doubly linked list of GString objects. + *Each GString object contains a string which is the + *destination media for style information. + *@param a_uri the uri of the imported style sheet. + *@param a_uri_default_ns the default namespace of URI + *@param a_location the parsing location of the '@import' + *keyword. + *of the imported style sheet. + */ + void (*import_style) (CRDocHandler *a_this, + GList *a_media_list, + CRString *a_uri, + CRString *a_uri_default_ns, + CRParsingLocation *a_location) ; + + void (*import_style_result) (CRDocHandler *a_this, + GList *a_media_list, + CRString *a_uri, + CRString *a_uri_default_ns, + CRStyleSheet *a_sheet) ; + + /** + *Is called to notify a namespace declaration. + *Not used yet. + *@param a_this the current instance of #CRDocHandler. + *@param a_prefix the prefix of the namespace. + *@param a_uri the uri of the namespace. + *@param a_location the location of the "@namespace" keyword. + */ + void (*namespace_declaration) (CRDocHandler *a_this, + CRString *a_prefix, + CRString *a_uri, + CRParsingLocation *a_location) ; + + /** + *Is called to notify a comment. + *@param a_this a pointer to the current instance + *of #CRDocHandler. + *@param a_comment the comment. + */ + void (*comment) (CRDocHandler *a_this, + CRString *a_comment) ; + + /** + *Is called to notify the beginning of a rule + *statement. + *@param a_this the current instance of #CRDocHandler. + *@param a_selector_list the list of selectors that precedes + *the rule declarations. + */ + void (*start_selector) (CRDocHandler * a_this, + CRSelector *a_selector_list) ; + + /** + *Is called to notify the end of a rule statement. + *@param a_this the current instance of #CRDocHandler. + *@param a_selector_list the list of selectors that precedes + *the rule declarations. This pointer is the same as + *the one passed to start_selector() ; + */ + void (*end_selector) (CRDocHandler *a_this, + CRSelector *a_selector_list) ; + + + /** + *Is called to notify a declaration. + *@param a_this a pointer to the current instance + *of #CRDocHandler. + *@param a_name the name of the parsed property. + *@param a_expression a css expression that represents + *the value of the property. A css expression is + *actually a linked list of 'terms'. Each term can + *be linked to other using operators. + * + */ + void (*property) (CRDocHandler *a_this, + CRString *a_name, + CRTerm *a_expression, + gboolean a_is_important) ; + /** + *Is called to notify the start of a font face statement. + *The parser invokes this method at the beginning of every + *font face statement in the style sheet. There will + *be a corresponding end_font_face () event for every + *start_font_face () event. + * + *@param a_this a pointer to the current instance of + *#CRDocHandler. + *@param a_location the parsing location of the "@font-face" + *keyword. + */ + void (*start_font_face) (CRDocHandler *a_this, + CRParsingLocation *a_location) ; + + /** + *Is called to notify the end of a font face statement. + *@param a_this a pointer to the current instance of + *#CRDocHandler. + */ + void (*end_font_face) (CRDocHandler *a_this) ; + + + /** + *Is called to notify the beginning of a media statement. + *The parser will invoke this method at the beginning of + *every media statement in the style sheet. There will be + *a corresponding end_media() event for every start_media() + *event. + *@param a_this a pointer to the current instance of + *#CRDocHandler. + *@param a_media_list a double linked list of + #CRString * objects. + *Each CRString objects is actually a destination media for + *the style information. + */ + void (*start_media) (CRDocHandler *a_this, + GList *a_media_list, + CRParsingLocation *a_location) ; + + /** + *Is called to notify the end of a media statement. + *@param a_this a pointer to the current instance + *of #CRDocHandler. + *@param a_media_list a double linked list of GString * objects. + *Each GString objects is actually a destination media for + *the style information. + */ + void (*end_media) (CRDocHandler *a_this, + GList *a_media_list) ; + + /** + *Is called to notify the beginning of a page statement. + *The parser invokes this function at the beginning of + *every page statement in the style sheet. There will be + *a corresponding end_page() event for every single + *start_page() event. + *@param a_this a pointer to the current instance of + *#CRDocHandler. + *@param a_name the name of the page (if any, null otherwise). + *@param a_pseudo_page the pseudo page (if any, null otherwise). + *@param a_location the parsing location of the "@page" keyword. + */ + void (*start_page) (CRDocHandler *a_this, + CRString *a_name, + CRString *a_pseudo_page, + CRParsingLocation *a_location) ; + + /** + *Is called to notify the end of a page statement. + *@param a_this a pointer to the current instance of + *#CRDocHandler. + *@param a_name the name of the page (if any, null otherwise). + *@parap a_pseudo_page the pseudo page (if any, null otherwise). + */ + void (*end_page) (CRDocHandler *a_this, + CRString *a_name, + CRString *pseudo_page) ; + + /** + *Is Called to notify an unknown at-rule not supported + *by this parser. + */ + void (*ignorable_at_rule) (CRDocHandler *a_this, + CRString *a_name) ; + + /** + *Is called to notify a parsing error. After this error + *the application must ignore the rule being parsed, if + *any. After completion of this callback, + *the parser will then try to resume the parsing, + *ignoring the current error. + */ + void (*error) (CRDocHandler *a_this) ; + + /** + *Is called to notify an unrecoverable parsing error. + *This is the place to put emergency routines that free allocated + *resources. + */ + void (*unrecoverable_error) (CRDocHandler *a_this) ; + + gboolean resolve_import ; + gulong ref_count ; +} ; + +CRDocHandler * cr_doc_handler_new (void) ; + +enum CRStatus cr_doc_handler_set_result (CRDocHandler *a_this, gpointer a_result) ; + +enum CRStatus cr_doc_handler_get_result (CRDocHandler *a_this, gpointer * a_result) ; + +enum CRStatus cr_doc_handler_set_ctxt (CRDocHandler *a_this, gpointer a_ctxt) ; + +enum CRStatus cr_doc_handler_get_ctxt (CRDocHandler *a_this, gpointer * a_ctxt) ; + +enum CRStatus cr_doc_handler_set_default_sac_handler (CRDocHandler *a_this) ; + +void cr_doc_handler_associate_a_parser (CRDocHandler *a_this, + gpointer a_parser) ; + +void cr_doc_handler_ref (CRDocHandler *a_this) ; + +gboolean cr_doc_handler_unref (CRDocHandler *a_this) ; + +void cr_doc_handler_destroy (CRDocHandler *a_this) ; + +G_END_DECLS + +#endif /*__CR_DOC_HANDLER_H__*/ diff --git a/gettext-tools/gnulib-lib/libcroco/cr-enc-handler.c b/gettext-tools/gnulib-lib/libcroco/cr-enc-handler.c new file mode 100644 index 0000000..f35a51e --- /dev/null +++ b/gettext-tools/gnulib-lib/libcroco/cr-enc-handler.c @@ -0,0 +1,187 @@ +/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8 -*- */ + +/* + * This file is part of The Croco Library + * + * Copyright (C) 2002-2003 Dodji Seketeli + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + +/* + *$Id: cr-enc-handler.c,v 1.8 2005/05/10 19:48:56 dodji Exp $ + */ + +/** + *@file + *The definition of the #CREncHandler class. + */ + +#include +#include "cr-enc-handler.h" +#include "cr-utils.h" + +#include + +struct CREncAlias { + const gchar *name; + enum CREncoding encoding; +}; + +static struct CREncAlias gv_default_aliases[] = { + {"UTF-8", CR_UTF_8}, + {"UTF_8", CR_UTF_8}, + {"UTF8", CR_UTF_8}, + {"UTF-16", CR_UTF_16}, + {"UTF_16", CR_UTF_16}, + {"UTF16", CR_UTF_16}, + {"UCS1", CR_UCS_1}, + {"UCS-1", CR_UCS_1}, + {"UCS_1", CR_UCS_1}, + {"ISO-8859-1", CR_UCS_1}, + {"ISO_8859-1", CR_UCS_1}, + {"UCS-1", CR_UCS_1}, + {"UCS_1", CR_UCS_1}, + {"UCS4", CR_UCS_4}, + {"UCS-4", CR_UCS_4}, + {"UCS_4", CR_UCS_4}, + {"ASCII", CR_ASCII}, + {0, 0} +}; + +static CREncHandler gv_default_enc_handlers[] = { + {CR_UCS_1, cr_utils_ucs1_to_utf8, cr_utils_utf8_to_ucs1, + cr_utils_ucs1_str_len_as_utf8, cr_utils_utf8_str_len_as_ucs1}, + + {CR_ISO_8859_1, cr_utils_ucs1_to_utf8, cr_utils_utf8_to_ucs1, + cr_utils_ucs1_str_len_as_utf8, cr_utils_utf8_str_len_as_ucs1}, + + {CR_ASCII, cr_utils_ucs1_to_utf8, cr_utils_utf8_to_ucs1, + cr_utils_ucs1_str_len_as_utf8, cr_utils_utf8_str_len_as_ucs1}, + + {0, NULL, NULL, NULL, NULL} +}; + +/** + * cr_enc_handler_get_instance: + *@a_enc: the encoding of the Handler. + * + *Gets the instance of encoding handler. + *This function implements a singleton pattern. + * + *Returns the instance of #CREncHandler. + */ +CREncHandler * +cr_enc_handler_get_instance (enum CREncoding a_enc) +{ + gulong i = 0; + + for (i = 0; gv_default_enc_handlers[i].encoding; i++) { + if (gv_default_enc_handlers[i].encoding == a_enc) { + return (CREncHandler *) + & gv_default_enc_handlers[i].encoding; + } + } + + return NULL; +} + +/** + * cr_enc_handler_resolve_enc_alias: + *@a_alias_name: the encoding name. + *@a_enc: output param. The returned encoding type + *or 0 if the alias is not supported. + * + *Given an encoding name (called an alias name) + *the function returns the matching encoding type. + * + *Returns CR_OK upon successfull completion, an error code otherwise. + */ +enum CRStatus +cr_enc_handler_resolve_enc_alias (const guchar * a_alias_name, + enum CREncoding *a_enc) +{ + gulong i = 0; + guchar *alias_name_up = NULL; + enum CRStatus status = CR_ENCODING_NOT_FOUND_ERROR; + + g_return_val_if_fail (a_alias_name != NULL, CR_BAD_PARAM_ERROR); + + alias_name_up = g_strdup (a_alias_name); + g_ascii_strup (alias_name_up, -1); + + for (i = 0; gv_default_aliases[i].name; i++) { + if (!strcmp (gv_default_aliases[i].name, alias_name_up)) { + *a_enc = gv_default_aliases[i].encoding; + status = CR_OK; + break; + } + } + + return status; +} + +/** + * cr_enc_handler_convert_input: + *@a_this: the current instance of #CREncHandler. + *@a_in: the input buffer to convert. + *@a_in_len: in/out parameter. The len of the input + *buffer to convert. After return, contains the number of + *bytes actually consumed. + *@a_out: output parameter. The converted output buffer. + *Must be freed by the buffer. + *@a_out_len: output parameter. The length of the output buffer. + * + *Converts a raw input buffer into an utf8 buffer. + * + *Returns CR_OK upon successfull completion, an error code otherwise. + */ +enum CRStatus +cr_enc_handler_convert_input (CREncHandler * a_this, + const guchar * a_in, + gulong * a_in_len, + guchar ** a_out, gulong * a_out_len) +{ + enum CRStatus status = CR_OK; + + g_return_val_if_fail (a_this && a_in && a_in_len && a_out, + CR_BAD_PARAM_ERROR); + + if (a_this->decode_input == NULL) + return CR_OK; + + if (a_this->enc_str_len_as_utf8) { + status = a_this->enc_str_len_as_utf8 (a_in, + &a_in[*a_in_len - 1], + a_out_len); + + g_return_val_if_fail (status == CR_OK, status); + } else { + *a_out_len = *a_in_len; + } + + *a_out = g_malloc0 (*a_out_len); + + status = a_this->decode_input (a_in, a_in_len, *a_out, a_out_len); + + if (status != CR_OK) { + g_free (*a_out); + *a_out = NULL; + } + + g_return_val_if_fail (status == CR_OK, status); + + return CR_OK; +} diff --git a/gettext-tools/gnulib-lib/libcroco/cr-enc-handler.h b/gettext-tools/gnulib-lib/libcroco/cr-enc-handler.h new file mode 100644 index 0000000..1bd797b --- /dev/null +++ b/gettext-tools/gnulib-lib/libcroco/cr-enc-handler.h @@ -0,0 +1,94 @@ +/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8 -*- */ + +/* + * This file is part of The Croco Library + * + * Copyright (C) 2002-2003 Dodji Seketeli + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + +/* + *$Id: cr-enc-handler.h,v 1.6 2005/05/10 19:48:56 dodji Exp $ + */ + +/** + *@file: + *The declaration of the #CREncHandler class. + * + */ + +#ifndef __CR_ENC_HANDLER_H__ +#define __CR_ENC_HANDLER_H__ + +#include "cr-utils.h" + +G_BEGIN_DECLS + + +typedef struct _CREncHandler CREncHandler ; + +typedef enum CRStatus (*CREncInputFunc) (const guchar * a_in, + gulong *a_in_len, + guchar *a_out, + gulong *a_out_len) ; + +typedef enum CRStatus (*CREncOutputFunc) (const guchar * a_in, + gulong *a_in_len, + guchar *a_out, + gulong *a_out_len) ; + +typedef enum CRStatus (*CREncInputStrLenAsUtf8Func) +(const guchar *a_in_start, + const guchar *a_in_end, + gulong *a_in_size); + +typedef enum CRStatus (*CREncUtf8StrLenAsOutputFunc) +(const guchar *a_in_start, + const guchar *a_in_end, + gulong *a_in_size) ; + +/** + *This class is responsible of the + *the encoding conversions stuffs in + *libcroco. + */ + +struct _CREncHandler +{ + enum CREncoding encoding ; + CREncInputFunc decode_input ; + CREncInputFunc encode_output ; + CREncInputStrLenAsUtf8Func enc_str_len_as_utf8 ; + CREncUtf8StrLenAsOutputFunc utf8_str_len_as_enc ; +} ; + +CREncHandler * +cr_enc_handler_get_instance (enum CREncoding a_enc) ; + +enum CRStatus +cr_enc_handler_resolve_enc_alias (const guchar *a_alias_name, + enum CREncoding *a_enc) ; + +enum CRStatus +cr_enc_handler_convert_input (CREncHandler *a_this, + const guchar *a_in, + gulong *a_in_len, + guchar **a_out, + gulong *a_out_len) ; + +G_END_DECLS + +#endif /*__CR_ENC_HANDLER_H__*/ diff --git a/gettext-tools/gnulib-lib/libcroco/cr-fonts.c b/gettext-tools/gnulib-lib/libcroco/cr-fonts.c new file mode 100644 index 0000000..aae695a --- /dev/null +++ b/gettext-tools/gnulib-lib/libcroco/cr-fonts.c @@ -0,0 +1,947 @@ +/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */ + +/* + * This file is part of The Croco Library + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of + * the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the + * GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + *See COPYRIGHTS file for copyright information + */ + +#include +#include "cr-fonts.h" +#include + +static enum CRStatus +cr_font_family_to_string_real (CRFontFamily * a_this, + gboolean a_walk_list, GString ** a_string) +{ + guchar *name = NULL; + enum CRStatus result = CR_OK; + + if (!*a_string) { + *a_string = g_string_new (NULL); + g_return_val_if_fail (*a_string, + CR_INSTANCIATION_FAILED_ERROR); + } + + if (!a_this) { + g_string_append (*a_string, "NULL"); + return CR_OK; + } + + switch (a_this->type) { + case FONT_FAMILY_SANS_SERIF: + name = (guchar *) "sans-serif"; + break; + + case FONT_FAMILY_SERIF: + name = (guchar *) "sans-serif"; + break; + + case FONT_FAMILY_CURSIVE: + name = (guchar *) "cursive"; + break; + + case FONT_FAMILY_FANTASY: + name = (guchar *) "fantasy"; + break; + + case FONT_FAMILY_MONOSPACE: + name = (guchar *) "monospace"; + break; + + case FONT_FAMILY_NON_GENERIC: + name = (guchar *) a_this->name; + break; + + default: + name = (guchar *) NULL; + break; + } + + if (name) { + if (a_this->prev) { + g_string_append_printf (*a_string, ", %s", name); + } else { + g_string_append (*a_string, name); + } + } + if (a_walk_list == TRUE && a_this->next) { + result = cr_font_family_to_string_real (a_this->next, + TRUE, a_string); + } + return result; +} + +static const gchar * +cr_predefined_absolute_font_size_to_string (enum CRPredefinedAbsoluteFontSize + a_code) +{ + gchar *str = NULL; + + switch (a_code) { + case FONT_SIZE_XX_SMALL: + str = (gchar *) "xx-small"; + break; + case FONT_SIZE_X_SMALL: + str = (gchar *) "x-small"; + break; + case FONT_SIZE_SMALL: + str = (gchar *) "small"; + break; + case FONT_SIZE_MEDIUM: + str = (gchar *) "medium"; + break; + case FONT_SIZE_LARGE: + str = (gchar *) "large"; + break; + case FONT_SIZE_X_LARGE: + str = (gchar *) "x-large"; + break; + case FONT_SIZE_XX_LARGE: + str = (gchar *) "xx-large"; + break; + default: + str = (gchar *) "unknown absolute font size value"; + } + return str; +} + +static const gchar * +cr_relative_font_size_to_string (enum CRRelativeFontSize a_code) +{ + gchar *str = NULL; + + switch (a_code) { + case FONT_SIZE_LARGER: + str = (gchar *) "larger"; + break; + case FONT_SIZE_SMALLER: + str = (gchar *) "smaller"; + break; + default: + str = (gchar *) "unknown relative font size value"; + break; + } + return str; +} + +/** + * cr_font_family_new: + * @a_type: the type of font family to create. + * @a_name: the name of the font family: + * + * create a font family. + * + * Returns the newly built font family. + */ +CRFontFamily * +cr_font_family_new (enum CRFontFamilyType a_type, guchar * a_name) +{ + CRFontFamily *result = NULL; + + result = g_try_malloc (sizeof (CRFontFamily)); + + if (!result) { + cr_utils_trace_info ("Out of memory"); + return NULL; + } + + memset (result, 0, sizeof (CRFontFamily)); + result->type = a_type; + + cr_font_family_set_name (result, a_name); + + return result; +} + +/** + * cr_font_family_to_string: + * @a_this: the current instance of #CRFontFamily. + * @a_walk_font_family_list: wether the serialize the entire list. + * + * Returns the seriliazed font family. The caller has to free it using + * g_free(). + */ +guchar * +cr_font_family_to_string (CRFontFamily * a_this, + gboolean a_walk_font_family_list) +{ + enum CRStatus status = CR_OK; + guchar *result = NULL; + GString *stringue = NULL; + + if (!a_this) { + result = g_strdup ("NULL"); + g_return_val_if_fail (result, NULL); + return result; + } + status = cr_font_family_to_string_real (a_this, + a_walk_font_family_list, + &stringue); + + if (status == CR_OK && stringue) { + result = stringue->str; + g_string_free (stringue, FALSE); + stringue = NULL; + + } else { + if (stringue) { + g_string_free (stringue, TRUE); + stringue = NULL; + } + } + + return result; +} + +/** + * cr_font_family_set_name: + * @a_this: the current instance of #CRFontFamily. + * @a_name: the new name + * + * Returns CR_OK upon sucessful completion, an error code otherwise. + */ +enum CRStatus +cr_font_family_set_name (CRFontFamily * a_this, guchar * a_name) +{ + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); + + /* + *only non generic font families can have a name + */ + + if (a_this->type != FONT_FAMILY_NON_GENERIC) { + return CR_BAD_PARAM_ERROR; + } + + if (a_this->name) { + g_free (a_this->name); + a_this->name = NULL; + } + + a_this->name = a_name; + return CR_OK; +} + +/** + * cr_font_family_append: + * @a_this: the current instance of #CRFontFamily. + * @a_family_to_append: the font family to append to the list + * + * Returns the new font family list. + */ +CRFontFamily * +cr_font_family_append (CRFontFamily * a_this, + CRFontFamily * a_family_to_append) +{ + CRFontFamily *cur_ff = NULL; + + g_return_val_if_fail (a_family_to_append, NULL); + + if (!a_this) + return a_family_to_append; + + for (cur_ff = a_this; cur_ff && cur_ff->next; cur_ff = cur_ff->next) ; + + cur_ff->next = a_family_to_append; + a_family_to_append->prev = cur_ff; + + return a_this; + +} + +/** + * cr_font_family_prepend: + * @a_this: the current instance #CRFontFamily. + * @a_family_to_prepend: the font family to prepend to the list. + * + * Returns the font family list. + */ +CRFontFamily * +cr_font_family_prepend (CRFontFamily * a_this, + CRFontFamily * a_family_to_prepend) +{ + g_return_val_if_fail (a_this && a_family_to_prepend, NULL); + + if (!a_this) + return a_family_to_prepend; + + a_family_to_prepend->next = a_this; + a_this->prev = a_family_to_prepend; + + return CR_OK; +} + +/** + * cr_font_family_destroy: + * @a_this: the current instance of #CRFontFamily. + * + * Returns CR_OK upon sucessful completion, an error code otherwise. + */ +enum CRStatus +cr_font_family_destroy (CRFontFamily * a_this) +{ + CRFontFamily *cur_ff = NULL; + + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); + + for (cur_ff = a_this; cur_ff && cur_ff->next; cur_ff = cur_ff->next) ; + + for (; cur_ff; cur_ff = cur_ff->prev) { + if (a_this->name) { + g_free (a_this->name); + a_this->name = NULL; + } + + if (cur_ff->next) { + g_free (cur_ff->next); + + } + + if (cur_ff->prev == NULL) { + g_free (a_this); + } + } + + return CR_OK; +} + +/*************************************************** + *'font-size' manipulation functions definitions + ***************************************************/ + +/** + * cr_font_size_new: + * + * Returns the newly created font size. + */ +CRFontSize * +cr_font_size_new (void) +{ + CRFontSize *result = NULL; + + result = g_try_malloc (sizeof (CRFontSize)); + if (!result) { + cr_utils_trace_info ("Out of memory"); + return NULL; + } + memset (result, 0, sizeof (CRFontSize)); + + return result; +} + +/** + * cr_font_size_clear: + * @a_this: the current instance of #CRFontSize + * + * Returns CR_OK upon successful completion, an error code otherwise. + */ +enum CRStatus +cr_font_size_clear (CRFontSize * a_this) +{ + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); + + switch (a_this->type) { + case PREDEFINED_ABSOLUTE_FONT_SIZE: + case RELATIVE_FONT_SIZE: + case INHERITED_FONT_SIZE: + memset (a_this, 0, sizeof (CRFontSize)); + break; + + case ABSOLUTE_FONT_SIZE: + memset (a_this, 0, sizeof (CRFontSize)); + break; + + default: + return CR_UNKNOWN_TYPE_ERROR; + } + + return CR_OK; +} + +/** + * cr_font_size_copy: + * @a_dst: the destination #CRFontSize (where to copy to). + * @a_src: the source #CRFontSize (where to copy from). + * + * Returns CR_OK upon successful completion, an error code otherwise. + */ +enum CRStatus +cr_font_size_copy (CRFontSize * a_dst, CRFontSize * a_src) +{ + g_return_val_if_fail (a_dst && a_src, CR_BAD_PARAM_ERROR); + + switch (a_src->type) { + case PREDEFINED_ABSOLUTE_FONT_SIZE: + case RELATIVE_FONT_SIZE: + case INHERITED_FONT_SIZE: + cr_font_size_clear (a_dst); + memcpy (a_dst, a_src, sizeof (CRFontSize)); + break; + + case ABSOLUTE_FONT_SIZE: + cr_font_size_clear (a_dst); + cr_num_copy (&a_dst->value.absolute, + &a_src->value.absolute); + a_dst->type = a_src->type; + break; + + default: + return CR_UNKNOWN_TYPE_ERROR; + } + return CR_OK; +} + +/** + * cr_font_size_set_predefined_absolute_font_size: + * @a_this: the current instance of #CRFontSize. + * @a_predefined: what to set. + * + * Returns CR_OK upon sucessful completion, an error code otherwise. + */ +enum CRStatus +cr_font_size_set_predefined_absolute_font_size (CRFontSize *a_this, + enum CRPredefinedAbsoluteFontSize a_predefined) +{ + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR) ; + g_return_val_if_fail (a_predefined >= PREDEFINED_ABSOLUTE_FONT_SIZE + && a_predefined < NB_FONT_SIZE_TYPE, + CR_BAD_PARAM_ERROR) ; + + a_this->type = PREDEFINED_ABSOLUTE_FONT_SIZE ; + a_this->value.predefined = a_predefined ; + + return CR_OK ; +} + +/** + * cr_font_size_set_relative_font_size: + * @a_this: the current instance of #CRFontSize + * @a_relative: the new relative font size + * + * Returns CR_OK upon successful completion, an error code otherwise. + */ +enum CRStatus +cr_font_size_set_relative_font_size (CRFontSize *a_this, + enum CRRelativeFontSize a_relative) +{ + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR) ; + g_return_val_if_fail (a_relative >= FONT_SIZE_LARGER + && a_relative < NB_RELATIVE_FONT_SIZE, + CR_BAD_PARAM_ERROR) ; + + a_this->type = RELATIVE_FONT_SIZE ; + a_this->value.relative = a_relative ; + return CR_OK ; +} + +/** + * cr_font_size_set_absolute_font_size: + * @a_this: the current instance of #CRFontSize + * @a_num_type: the type of number to set. + * @a_value: the actual value to set. + * + * Returns CR_OK upon succesful completion, an error code otherwise. + */ +enum CRStatus +cr_font_size_set_absolute_font_size (CRFontSize *a_this, + enum CRNumType a_num_type, + gdouble a_value) +{ + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR) ; + g_return_val_if_fail (a_num_type >= NUM_AUTO + && a_num_type < NB_NUM_TYPE, + CR_BAD_PARAM_ERROR) ; + + a_this->type = ABSOLUTE_FONT_SIZE ; + cr_num_set (&a_this->value.absolute, + a_value, a_num_type) ; + return CR_OK ; +} + +/** + * cr_font_size_set_to_inherit: + * @a_this: the current instance of #CRFontSize + * + * Returns CR_OK upon succesful completion, an error code otherwise. + */ +enum CRStatus +cr_font_size_set_to_inherit (CRFontSize *a_this) +{ + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR) ; + + cr_font_size_clear (a_this) ; + a_this->type = INHERITED_FONT_SIZE ; + + return CR_OK ; +} + +/** + * cr_font_size_is_set_to_inherit: + * @a_this: the current instance of #CRFontSize. + * + * Returns TRUE if the current instance is set to 'inherit'. + */ +gboolean +cr_font_size_is_set_to_inherit (CRFontSize *a_this) +{ + g_return_val_if_fail (a_this, FALSE) ; + + return a_this->type == INHERITED_FONT_SIZE ; +} + +/** + * cr_font_size_to_string: + * @a_this: the current instance of #CRFontSize + * + * Returns the serialized form of #CRFontSize. The returned string + * has to bee freed using g_free(). + */ +gchar * +cr_font_size_to_string (CRFontSize * a_this) +{ + gchar *str = NULL; + + if (!a_this) { + str = g_strdup ("NULL"); + g_return_val_if_fail (str, NULL); + return str; + } + switch (a_this->type) { + case PREDEFINED_ABSOLUTE_FONT_SIZE: + str = g_strdup (cr_predefined_absolute_font_size_to_string + (a_this->value.predefined)); + break; + case ABSOLUTE_FONT_SIZE: + str = cr_num_to_string (&a_this->value.absolute); + break; + case RELATIVE_FONT_SIZE: + str = g_strdup (cr_relative_font_size_to_string + (a_this->value.relative)); + break; + case INHERITED_FONT_SIZE: + str = g_strdup ("inherit"); + break; + default: + break; + } + return str; +} + +/** + * cr_font_size_get_smaller_predefined: + * @a_font_size: the font size to consider. + * @a_smaller_size: out parameter. The a smaller value than @a_font_size. + */ +void +cr_font_size_get_smaller_predefined_font_size + (enum CRPredefinedAbsoluteFontSize a_font_size, + enum CRPredefinedAbsoluteFontSize *a_smaller_size) +{ + enum CRPredefinedAbsoluteFontSize result = FONT_SIZE_MEDIUM ; + + g_return_if_fail (a_smaller_size) ; + g_return_if_fail (a_font_size < NB_PREDEFINED_ABSOLUTE_FONT_SIZES + && a_font_size >= FONT_SIZE_XX_SMALL) ; + + switch (a_font_size) { + case FONT_SIZE_XX_SMALL: + result = FONT_SIZE_XX_SMALL ; + break ; + case FONT_SIZE_X_SMALL: + result = FONT_SIZE_XX_SMALL ; + break ; + case FONT_SIZE_SMALL: + result = FONT_SIZE_X_SMALL; + break ; + case FONT_SIZE_MEDIUM: + result = FONT_SIZE_SMALL; + break ; + case FONT_SIZE_LARGE: + result = FONT_SIZE_MEDIUM; + break ; + case FONT_SIZE_X_LARGE: + result = FONT_SIZE_LARGE; + break ; + case FONT_SIZE_XX_LARGE: + result = FONT_SIZE_XX_LARGE; + break ; + case FONT_SIZE_INHERIT: + cr_utils_trace_info ("can't return a smaller size for FONT_SIZE_INHERIT") ; + result = FONT_SIZE_MEDIUM ; + break ; + default: + cr_utils_trace_info ("Unknown FONT_SIZE") ; + result = FONT_SIZE_MEDIUM ; + break ; + } + *a_smaller_size = result ; +} + + +/** + * cr_font_size_get_larger_predefined_font_size: + * @a_font_size: the font size to consider. + * @a_larger_size: out parameter. the font size considered larger than + * @a_font_size. + * + */ +void +cr_font_size_get_larger_predefined_font_size + (enum CRPredefinedAbsoluteFontSize a_font_size, + enum CRPredefinedAbsoluteFontSize *a_larger_size) +{ + enum CRPredefinedAbsoluteFontSize result = FONT_SIZE_MEDIUM ; + + g_return_if_fail (a_larger_size) ; + g_return_if_fail (a_font_size >= FONT_SIZE_XX_SMALL + && a_font_size < NB_PREDEFINED_ABSOLUTE_FONT_SIZES) ; + + switch (a_font_size) { + case FONT_SIZE_XX_SMALL: + result = FONT_SIZE_X_SMALL ; + break ; + case FONT_SIZE_X_SMALL: + result = FONT_SIZE_SMALL ; + break ; + case FONT_SIZE_SMALL: + result = FONT_SIZE_MEDIUM; + break ; + case FONT_SIZE_MEDIUM: + result = FONT_SIZE_LARGE; + break ; + case FONT_SIZE_LARGE: + result = FONT_SIZE_X_LARGE; + break ; + case FONT_SIZE_X_LARGE: + result = FONT_SIZE_XX_LARGE ; + break ; + case FONT_SIZE_XX_LARGE: + result = FONT_SIZE_XX_LARGE; + break ; + case FONT_SIZE_INHERIT: + cr_utils_trace_info ("can't return a bigger size for FONT_SIZE_INHERIT") ; + result = FONT_SIZE_MEDIUM ; + break ; + default: + cr_utils_trace_info ("Unknown FONT_SIZE") ; + result = FONT_SIZE_MEDIUM ; + break ; + } + *a_larger_size = result ; +} + +/** + * cr_font_size_is_predefined_absolute_font_size: + * @a_font_size: the font size to consider. + * + * Returns TRUE if the instance is an predefined absolute font size, FALSE + * otherwise. + */ +gboolean +cr_font_size_is_predefined_absolute_font_size + (enum CRPredefinedAbsoluteFontSize a_font_size) +{ + if (a_font_size >= FONT_SIZE_XX_SMALL + && a_font_size < NB_PREDEFINED_ABSOLUTE_FONT_SIZES) { + return TRUE ; + } else { + return FALSE ; + } +} + +/** + * cr_font_size_adjust_to_string: + * @a_this: the instance of #CRFontSizeAdjust. + * + * Returns the serialized form of #CRFontSizeAdjust + */ +gchar * +cr_font_size_adjust_to_string (CRFontSizeAdjust * a_this) +{ + gchar *str = NULL; + + if (!a_this) { + str = g_strdup ("NULL"); + g_return_val_if_fail (str, NULL); + return str; + } + + switch (a_this->type) { + case FONT_SIZE_ADJUST_NONE: + str = g_strdup ("none"); + break; + case FONT_SIZE_ADJUST_NUMBER: + if (a_this->num) + str = cr_num_to_string (a_this->num); + else + str = g_strdup ("unknow font-size-adjust property value"); /* Should raise an error no?*/ + break; + case FONT_SIZE_ADJUST_INHERIT: + str = g_strdup ("inherit"); + } + return str; +} + +/** + * cr_font_style_to_string: + * @a_code the current instance of #CRFontStyle + * + * Returns the serialized #CRFontStyle. The caller must free the returned + * string using g_free(). + */ +const gchar * +cr_font_style_to_string (enum CRFontStyle a_code) +{ + gchar *str = NULL; + + switch (a_code) { + case FONT_STYLE_NORMAL: + str = (gchar *) "normal"; + break; + case FONT_STYLE_ITALIC: + str = (gchar *) "italic"; + break; + case FONT_STYLE_OBLIQUE: + str = (gchar *) "oblique"; + break; + case FONT_STYLE_INHERIT: + str = (gchar *) "inherit"; + break; + default: + str = (gchar *) "unknown font style value"; + break; + } + return str; +} + +/** + * cr_font_variant_to_string: + * @a_code: the current instance of #CRFontVariant. + * + * Returns the serialized form of #CRFontVariant. The caller has + * to free the returned string using g_free(). + */ +const gchar * +cr_font_variant_to_string (enum CRFontVariant a_code) +{ + gchar *str = NULL; + + switch (a_code) { + case FONT_VARIANT_NORMAL: + str = (gchar *) "normal"; + break; + case FONT_VARIANT_SMALL_CAPS: + str = (gchar *) "small-caps"; + break; + case FONT_VARIANT_INHERIT: + str = (gchar *) "inherit"; + break; + } + return str; +} + +/** + * cr_font_weight_get_bolder: + * @a_weight: the #CRFontWeight to consider. + * + * Returns a font weight bolder than @a_weight + */ +enum CRFontWeight +cr_font_weight_get_bolder (enum CRFontWeight a_weight) +{ + if (a_weight >= NB_FONT_WEIGHTS) { + return FONT_WEIGHT_900 ; + } else if (a_weight < FONT_WEIGHT_NORMAL) { + return FONT_WEIGHT_NORMAL ; + } else if (a_weight == FONT_WEIGHT_BOLDER + || a_weight == FONT_WEIGHT_BOLDER) { + cr_utils_trace_info ("FONT_WEIGHT_BOLDER or FONT_WEIGHT_LIGHTER should not appear here") ; + return FONT_WEIGHT_NORMAL ; + } else { + return a_weight << 1 ; + } +} + +/** + * cr_font_weight_to_string: + * @a_code: the font weight to consider. + * + * Returns the serialized form of #CRFontWeight. + */ +const gchar * +cr_font_weight_to_string (enum CRFontWeight a_code) +{ + gchar *str = NULL; + + switch (a_code) { + case FONT_WEIGHT_NORMAL: + str = (gchar *) "normal"; + break; + case FONT_WEIGHT_BOLD: + str = (gchar *) "bold"; + break; + case FONT_WEIGHT_BOLDER: + str = (gchar *) "bolder"; + break; + case FONT_WEIGHT_LIGHTER: + str = (gchar *) "lighter"; + break; + case FONT_WEIGHT_100: + str = (gchar *) "100"; + break; + case FONT_WEIGHT_200: + str = (gchar *) "200"; + break; + case FONT_WEIGHT_300: + str = (gchar *) "300"; + break; + case FONT_WEIGHT_400: + str = (gchar *) "400"; + break; + case FONT_WEIGHT_500: + str = (gchar *) "500"; + break; + case FONT_WEIGHT_600: + str = (gchar *) "600"; + break; + case FONT_WEIGHT_700: + str = (gchar *) "700"; + break; + case FONT_WEIGHT_800: + str = (gchar *) "800"; + break; + case FONT_WEIGHT_900: + str = (gchar *) "900"; + break; + case FONT_WEIGHT_INHERIT: + str = (gchar *) "inherit"; + break; + default: + str = (gchar *) "unknown font-weight property value"; + break; + } + return str; +} + +/** + * cr_font_stretch_to_string: + * @a_code: the instance of #CRFontStretch to consider. + * + * Returns the serialized form of #CRFontStretch. + */ +const gchar * +cr_font_stretch_to_string (enum CRFontStretch a_code) +{ + gchar *str = NULL; + + switch (a_code) { + case FONT_STRETCH_NORMAL: + str = (gchar *) "normal"; + break; + case FONT_STRETCH_WIDER: + str = (gchar *) "wider"; + break; + case FONT_STRETCH_NARROWER: + str = (gchar *) "narrower"; + break; + case FONT_STRETCH_ULTRA_CONDENSED: + str = (gchar *) "ultra-condensed"; + break; + case FONT_STRETCH_EXTRA_CONDENSED: + str = (gchar *) "extra-condensed"; + break; + case FONT_STRETCH_CONDENSED: + str = (gchar *) "condensed"; + break; + case FONT_STRETCH_SEMI_CONDENSED: + str = (gchar *) "semi-condensed"; + break; + case FONT_STRETCH_SEMI_EXPANDED: + str = (gchar *) "semi-expanded"; + break; + case FONT_STRETCH_EXPANDED: + str = (gchar *) "expanded"; + break; + case FONT_STRETCH_EXTRA_EXPANDED: + str = (gchar *) "extra-expaned"; + break; + case FONT_STRETCH_ULTRA_EXPANDED: + str = (gchar *) "ultra-expanded"; + break; + case FONT_STRETCH_INHERIT: + str = (gchar *) "inherit"; + break; + } + return str; +} + +/** + * cr_font_size_destroy: + * @a_font_size: the font size to destroy + * + */ +void +cr_font_size_destroy (CRFontSize * a_font_size) +{ + g_return_if_fail (a_font_size); + + g_free (a_font_size) ; +} + +/******************************************************* + *'font-size-adjust' manipulation function definition + *******************************************************/ + +/** + * cr_font_size_adjust_new: + * + * Returns a newly built instance of #CRFontSizeAdjust + */ +CRFontSizeAdjust * +cr_font_size_adjust_new (void) +{ + CRFontSizeAdjust *result = NULL; + + result = g_try_malloc (sizeof (CRFontSizeAdjust)); + if (!result) { + cr_utils_trace_info ("Out of memory"); + return NULL; + } + memset (result, 0, sizeof (CRFontSizeAdjust)); + + return result; +} + +/** + * cr_font_size_adjust_destroy: + * @a_this: the current instance of #CRFontSizeAdjust. + * + */ +void +cr_font_size_adjust_destroy (CRFontSizeAdjust * a_this) +{ + g_return_if_fail (a_this); + + if (a_this->type == FONT_SIZE_ADJUST_NUMBER && a_this->num) { + cr_num_destroy (a_this->num); + a_this->num = NULL; + } +} diff --git a/gettext-tools/gnulib-lib/libcroco/cr-fonts.h b/gettext-tools/gnulib-lib/libcroco/cr-fonts.h new file mode 100644 index 0000000..ffe9539 --- /dev/null +++ b/gettext-tools/gnulib-lib/libcroco/cr-fonts.h @@ -0,0 +1,315 @@ +/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */ + +/* + * This file is part of The Croco Library + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of + * the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the + * GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + * Author: Dodji Seketeli + * See COPYRIGHTS file for copyright information. + */ + +#ifndef __CR_FONTS_H__ +#define __CR_FONTS_H__ + +#include "cr-utils.h" +#include "cr-num.h" + +/** + *@file + *Various type declarations about font selection related + *properties. + */ +G_BEGIN_DECLS + + +enum CRFontFamilyType +{ + FONT_FAMILY_SANS_SERIF, + FONT_FAMILY_SERIF, + FONT_FAMILY_CURSIVE, + FONT_FAMILY_FANTASY, + FONT_FAMILY_MONOSPACE, + FONT_FAMILY_NON_GENERIC, + FONT_FAMILY_INHERIT, + /**/ + NB_FONT_FAMILIE_TYPES +} ; + +typedef struct _CRFontFamily CRFontFamily ; + +struct _CRFontFamily +{ + enum CRFontFamilyType type ; + + /* + *The name of the font family, in case + *it is non generic. + *Is set only if the type is FONT_FAMILY_NON_GENERIC. + */ + guchar *name ; + + CRFontFamily *next ; + CRFontFamily *prev ; +} ; + + +/** + *The different types + *of absolute font size. + *This is used by the 'font-size' + *property defined in css2 spec + *in chapter 15.2.4 . + *These values a indexes of + *table of size so please, do not + *change their definition order unless + *you know what you are doing. + */ +enum CRPredefinedAbsoluteFontSize +{ + FONT_SIZE_XX_SMALL=0, + FONT_SIZE_X_SMALL, + FONT_SIZE_SMALL, + FONT_SIZE_MEDIUM, + FONT_SIZE_LARGE, + FONT_SIZE_X_LARGE, + FONT_SIZE_XX_LARGE, + FONT_SIZE_INHERIT, + NB_PREDEFINED_ABSOLUTE_FONT_SIZES +} ; + +/** + *The different types + *of relative font size. + *This is used by the 'font-size' + *property defined in css2 spec + *in chapter 15.2.4 . + *These values a indexes of + *table of size so please, do not + *change their definition order unless + *you know what you are doing. + */ +enum CRRelativeFontSize +{ + FONT_SIZE_LARGER, + FONT_SIZE_SMALLER, + NB_RELATIVE_FONT_SIZE +} ; + +/** + *The type of font-size property. + *Used to define the type of #CRFontSize . + *See css2 spec chapter 15.2.4 to understand. + */ +enum CRFontSizeType { + /** + *If the type of #CRFontSize is + *PREDEFINED_ABSOLUTE_FONT_SIZE, + *the CRFontSize::value.predefined_absolute + *field will be defined. + */ + PREDEFINED_ABSOLUTE_FONT_SIZE, + + /** + *If the type of #CRFontSize is + *ABSOLUTE_FONT_SIZE, + *the CRFontSize::value.absolute + *field will be defined. + */ + ABSOLUTE_FONT_SIZE, + + /** + *If the type of #CRFontSize is + *RELATIVE_FONT_SIZE, + *the CRFontSize::value.relative + *field will be defined. + */ + RELATIVE_FONT_SIZE, + + /** + *If the type of #CRFontSize is + *INHERITED_FONT_SIZE, + *the None of the field of the CRFontSize::value enum + *will be defined. + */ + INHERITED_FONT_SIZE, + + NB_FONT_SIZE_TYPE +} ; + +typedef struct _CRFontSize CRFontSize ; +struct _CRFontSize { + enum CRFontSizeType type ; + union { + enum CRPredefinedAbsoluteFontSize predefined ; + enum CRRelativeFontSize relative ; + CRNum absolute ; + } value; +} ; + +enum CRFontSizeAdjustType +{ + FONT_SIZE_ADJUST_NONE = 0, + FONT_SIZE_ADJUST_NUMBER, + FONT_SIZE_ADJUST_INHERIT +} ; +typedef struct _CRFontSizeAdjust CRFontSizeAdjust ; +struct _CRFontSizeAdjust +{ + enum CRFontSizeAdjustType type ; + CRNum *num ; +} ; + +enum CRFontStyle +{ + FONT_STYLE_NORMAL=0, + FONT_STYLE_ITALIC, + FONT_STYLE_OBLIQUE, + FONT_STYLE_INHERIT +} ; + +enum CRFontVariant +{ + FONT_VARIANT_NORMAL=0, + FONT_VARIANT_SMALL_CAPS, + FONT_VARIANT_INHERIT +} ; + +enum CRFontWeight +{ + FONT_WEIGHT_NORMAL = 1, + FONT_WEIGHT_BOLD = 1<<1, + FONT_WEIGHT_BOLDER = 1<<2, + FONT_WEIGHT_LIGHTER = 1<<3, + FONT_WEIGHT_100 = 1<<4, + FONT_WEIGHT_200 = 1<<5, + FONT_WEIGHT_300 = 1<<6, + FONT_WEIGHT_400 = 1<<7, + FONT_WEIGHT_500 = 1<<8, + FONT_WEIGHT_600 = 1<<9, + FONT_WEIGHT_700 = 1<<10, + FONT_WEIGHT_800 = 1<<11, + FONT_WEIGHT_900 = 1<<12, + FONT_WEIGHT_INHERIT = 1<<13, + NB_FONT_WEIGHTS +} ; + +enum CRFontStretch +{ + FONT_STRETCH_NORMAL=0, + FONT_STRETCH_WIDER, + FONT_STRETCH_NARROWER, + FONT_STRETCH_ULTRA_CONDENSED, + FONT_STRETCH_EXTRA_CONDENSED, + FONT_STRETCH_CONDENSED, + FONT_STRETCH_SEMI_CONDENSED, + FONT_STRETCH_SEMI_EXPANDED, + FONT_STRETCH_EXPANDED, + FONT_STRETCH_EXTRA_EXPANDED, + FONT_STRETCH_ULTRA_EXPANDED, + FONT_STRETCH_INHERIT +} ; + +/************************************** + *'font-family' manipulation functions + ***************************************/ +CRFontFamily * +cr_font_family_new (enum CRFontFamilyType a_type, guchar *a_name) ; + +CRFontFamily * +cr_font_family_append (CRFontFamily *a_this, + CRFontFamily *a_family_to_append) ; + +guchar * +cr_font_family_to_string (CRFontFamily *a_this, + gboolean a_walk_font_family_list) ; + +CRFontFamily * +cr_font_family_prepend (CRFontFamily *a_this, + CRFontFamily *a_family_to_prepend); + +enum CRStatus +cr_font_family_destroy (CRFontFamily *a_this) ; + +enum CRStatus +cr_font_family_set_name (CRFontFamily *a_this, guchar *a_name) ; + + +/************************************ + *'font-size' manipulation functions + ***********************************/ + +CRFontSize * cr_font_size_new (void) ; + +enum CRStatus cr_font_size_clear (CRFontSize *a_this) ; + +enum CRStatus cr_font_size_copy (CRFontSize *a_dst, + CRFontSize *a_src) ; +enum CRStatus cr_font_size_set_predefined_absolute_font_size (CRFontSize *a_this, + enum CRPredefinedAbsoluteFontSize a_predefined) ; +enum CRStatus cr_font_size_set_relative_font_size (CRFontSize *a_this, + enum CRRelativeFontSize a_relative) ; + +enum CRStatus cr_font_size_set_absolute_font_size (CRFontSize *a_this, + enum CRNumType a_num_type, + gdouble a_value) ; + +enum CRStatus cr_font_size_set_to_inherit (CRFontSize *a_this) ; + +gboolean cr_font_size_is_set_to_inherit (CRFontSize *a_this) ; + +gchar* cr_font_size_to_string (CRFontSize *a_this) ; + +void cr_font_size_destroy (CRFontSize *a_font_size) ; + +/******************************************************* + *'font-size-adjust' manipulation function declarations + *******************************************************/ + +CRFontSizeAdjust * cr_font_size_adjust_new (void) ; + +gchar * cr_font_size_adjust_to_string (CRFontSizeAdjust *a_this) ; + +void cr_font_size_adjust_destroy (CRFontSizeAdjust *a_this) ; + +void +cr_font_size_get_smaller_predefined_font_size (enum CRPredefinedAbsoluteFontSize a_font_size, + enum CRPredefinedAbsoluteFontSize *a_smaller_size) ; +void +cr_font_size_get_larger_predefined_font_size (enum CRPredefinedAbsoluteFontSize a_font_size, + enum CRPredefinedAbsoluteFontSize *a_larger_size) ; + +gboolean +cr_font_size_is_predefined_absolute_font_size (enum CRPredefinedAbsoluteFontSize a_font_size) ; + +/*********************************** + *various other font related functions + ***********************************/ +const gchar * cr_font_style_to_string (enum CRFontStyle a_code) ; + +const gchar * cr_font_weight_to_string (enum CRFontWeight a_code) ; + +enum CRFontWeight +cr_font_weight_get_bolder (enum CRFontWeight a_weight) ; + +const gchar * cr_font_variant_to_string (enum CRFontVariant a_code) ; + +const gchar * cr_font_stretch_to_string (enum CRFontStretch a_code) ; + +G_END_DECLS + +#endif /* __CR_FONTS_H__ */ diff --git a/gettext-tools/gnulib-lib/libcroco/cr-input.c b/gettext-tools/gnulib-lib/libcroco/cr-input.c new file mode 100644 index 0000000..44d7ae6 --- /dev/null +++ b/gettext-tools/gnulib-lib/libcroco/cr-input.c @@ -0,0 +1,1183 @@ +/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8-*- */ + +/* + * This file is part of The Croco Library + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + * Author: Dodji Seketeli + * See COPYRIGHTS file for copyright information. + */ + +#include +#include "stdio.h" +#include +#include "cr-input.h" +#include "cr-enc-handler.h" + +/** + *@CRInput: + * + *The definition of the #CRInput class. + */ + +/******************* + *Private type defs + *******************/ + +/** + *The private attributes of + *the #CRInputPriv class. + */ +struct _CRInputPriv { + /* + *The input buffer + */ + guchar *in_buf; + gulong in_buf_size; + + gulong nb_bytes; + + /* + *The index of the next byte + *to be read. + */ + gulong next_byte_index; + + /* + *The current line number + */ + gulong line; + + /* + *The current col number + */ + gulong col; + + gboolean end_of_line; + gboolean end_of_input; + + /* + *the reference count of this + *instance. + */ + guint ref_count; + gboolean free_in_buf; +}; + +#define PRIVATE(object) (object)->priv + +/*************************** + *private constants + **************************/ +#define CR_INPUT_MEM_CHUNK_SIZE 1024 * 4 + +static CRInput *cr_input_new_real (void); + +static CRInput * +cr_input_new_real (void) +{ + CRInput *result = NULL; + + result = g_try_malloc (sizeof (CRInput)); + if (!result) { + cr_utils_trace_info ("Out of memory"); + return NULL; + } + memset (result, 0, sizeof (CRInput)); + + PRIVATE (result) = g_try_malloc (sizeof (CRInputPriv)); + if (!PRIVATE (result)) { + cr_utils_trace_info ("Out of memory"); + g_free (result); + return NULL; + } + memset (PRIVATE (result), 0, sizeof (CRInputPriv)); + PRIVATE (result)->free_in_buf = TRUE; + return result; +} + +/**************** + *Public methods + ***************/ + +/** + * cr_input_new_from_buf: + *@a_buf: the memory buffer to create the input stream from. + *The #CRInput keeps this pointer so user should not free it !. + *@a_len: the size of the input buffer. + *@a_enc: the buffer's encoding. + *@a_free_buf: if set to TRUE, this a_buf will be freed + *at the destruction of this instance. If set to false, it is up + *to the caller to free it. + * + *Creates a new input stream from a memory buffer. + *Returns the newly built instance of #CRInput. + */ +CRInput * +cr_input_new_from_buf (guchar * a_buf, + gulong a_len, + enum CREncoding a_enc, + gboolean a_free_buf) +{ + CRInput *result = NULL; + enum CRStatus status = CR_OK; + CREncHandler *enc_handler = NULL; + gulong len = a_len; + + g_return_val_if_fail (a_buf, NULL); + + result = cr_input_new_real (); + g_return_val_if_fail (result, NULL); + + /*transform the encoding in utf8 */ + if (a_enc != CR_UTF_8) { + enc_handler = cr_enc_handler_get_instance (a_enc); + if (!enc_handler) { + goto error; + } + + status = cr_enc_handler_convert_input + (enc_handler, a_buf, &len, + &PRIVATE (result)->in_buf, + &PRIVATE (result)->in_buf_size); + if (status != CR_OK) + goto error; + PRIVATE (result)->free_in_buf = TRUE; + if (a_free_buf == TRUE && a_buf) { + g_free (a_buf) ; + a_buf = NULL ; + } + PRIVATE (result)->nb_bytes = PRIVATE (result)->in_buf_size; + } else { + PRIVATE (result)->in_buf = (guchar *) a_buf; + PRIVATE (result)->in_buf_size = a_len; + PRIVATE (result)->nb_bytes = a_len; + PRIVATE (result)->free_in_buf = a_free_buf; + } + PRIVATE (result)->line = 1; + PRIVATE (result)->col = 0; + return result; + + error: + if (result) { + cr_input_destroy (result); + result = NULL; + } + + return NULL; +} + +/** + * cr_input_new_from_uri: + *@a_file_uri: the file to create *the input stream from. + *@a_enc: the encoding of the file *to create the input from. + * + *Creates a new input stream from + *a file. + * + *Returns the newly created input stream if + *this method could read the file and create it, + *NULL otherwise. + */ + +CRInput * +cr_input_new_from_uri (const gchar * a_file_uri, enum CREncoding a_enc) +{ + CRInput *result = NULL; + enum CRStatus status = CR_OK; + FILE *file_ptr = NULL; + guchar tmp_buf[CR_INPUT_MEM_CHUNK_SIZE] = { 0 }; + gulong nb_read = 0, + len = 0, + buf_size = 0; + gboolean loop = TRUE; + guchar *buf = NULL; + + g_return_val_if_fail (a_file_uri, NULL); + + file_ptr = fopen (a_file_uri, "r"); + + if (file_ptr == NULL) { + +#ifdef CR_DEBUG + cr_utils_trace_debug ("could not open file"); +#endif + g_warning ("Could not open file %s\n", a_file_uri); + + return NULL; + } + + /*load the file */ + while (loop) { + nb_read = fread (tmp_buf, 1 /*read bytes */ , + CR_INPUT_MEM_CHUNK_SIZE /*nb of bytes */ , + file_ptr); + + if (nb_read != CR_INPUT_MEM_CHUNK_SIZE) { + /*we read less chars than we wanted */ + if (feof (file_ptr)) { + /*we reached eof */ + loop = FALSE; + } else { + /*a pb occured !! */ + cr_utils_trace_debug ("an io error occured"); + status = CR_ERROR; + goto cleanup; + } + } + + if (status == CR_OK) { + /*read went well */ + buf = g_realloc (buf, len + CR_INPUT_MEM_CHUNK_SIZE); + memcpy (buf + len, tmp_buf, nb_read); + len += nb_read; + buf_size += CR_INPUT_MEM_CHUNK_SIZE; + } + } + + if (status == CR_OK) { + result = cr_input_new_from_buf (buf, len, a_enc, TRUE); + if (!result) { + goto cleanup; + } + /* + *we should free buf here because it's own by CRInput. + *(see the last parameter of cr_input_new_from_buf(). + */ + buf = NULL ; + } + + cleanup: + if (file_ptr) { + fclose (file_ptr); + file_ptr = NULL; + } + + if (buf) { + g_free (buf); + buf = NULL; + } + + return result; +} + +/** + * cr_input_destroy: + *@a_this: the current instance of #CRInput. + * + *The destructor of the #CRInput class. + */ +void +cr_input_destroy (CRInput * a_this) +{ + if (a_this == NULL) + return; + + if (PRIVATE (a_this)) { + if (PRIVATE (a_this)->in_buf && PRIVATE (a_this)->free_in_buf) { + g_free (PRIVATE (a_this)->in_buf); + PRIVATE (a_this)->in_buf = NULL; + } + + g_free (PRIVATE (a_this)); + PRIVATE (a_this) = NULL; + } + + g_free (a_this); +} + +/** + * cr_input_ref: + *@a_this: the current instance of #CRInput. + * + *Increments the reference count of the current + *instance of #CRInput. + */ +void +cr_input_ref (CRInput * a_this) +{ + g_return_if_fail (a_this && PRIVATE (a_this)); + + PRIVATE (a_this)->ref_count++; +} + +/** + * cr_input_unref: + *@a_this: the current instance of #CRInput. + * + *Decrements the reference count of this instance + *of #CRInput. If the reference count goes down to + *zero, this instance is destroyed. + * + * Returns TRUE if the instance of #CRInput got destroyed, false otherwise. + */ +gboolean +cr_input_unref (CRInput * a_this) +{ + g_return_val_if_fail (a_this && PRIVATE (a_this), FALSE); + + if (PRIVATE (a_this)->ref_count) { + PRIVATE (a_this)->ref_count--; + } + + if (PRIVATE (a_this)->ref_count == 0) { + cr_input_destroy (a_this); + return TRUE; + } + return FALSE; +} + +/** + * cr_input_end_of_input: + *@a_this: the current instance of #CRInput. + *@a_end_of_input: out parameter. Is set to TRUE if + *the current instance has reached the end of its input buffer, + *FALSE otherwise. + * + *Tests wether the current instance of + *#CRInput has reached its input buffer. + * + * Returns CR_OK upon successful completion, an error code otherwise. + * Note that all the out parameters of this method are valid if + * and only if this method returns CR_OK. + */ +enum CRStatus +cr_input_end_of_input (CRInput * a_this, gboolean * a_end_of_input) +{ + g_return_val_if_fail (a_this && PRIVATE (a_this) + && a_end_of_input, CR_BAD_PARAM_ERROR); + + *a_end_of_input = (PRIVATE (a_this)->next_byte_index + >= PRIVATE (a_this)->in_buf_size) ? TRUE : FALSE; + + return CR_OK; +} + +/** + * cr_input_get_nb_bytes_left: + *@a_this: the current instance of #CRInput. + * + *Returns the number of bytes left in the input stream + *before the end, -1 in case of error. + */ +glong +cr_input_get_nb_bytes_left (CRInput * a_this) +{ + g_return_val_if_fail (a_this && PRIVATE (a_this), -1); + g_return_val_if_fail (PRIVATE (a_this)->nb_bytes + <= PRIVATE (a_this)->in_buf_size, -1); + g_return_val_if_fail (PRIVATE (a_this)->next_byte_index + <= PRIVATE (a_this)->nb_bytes, -1); + + if (PRIVATE (a_this)->end_of_input) + return 0; + + return PRIVATE (a_this)->nb_bytes - PRIVATE (a_this)->next_byte_index; +} + +/** + * cr_input_read_byte: + *@a_this: the current instance of #CRInput. + *@a_byte: out parameter the returned byte. + * + *Gets the next byte of the input. + *Updates the state of the input so that + *the next invocation of this method returns + *the next coming byte. + * + *Returns CR_OK upon successful completion, an error code + *otherwise. All the out parameters of this method are valid if + *and only if this method returns CR_OK. + */ +enum CRStatus +cr_input_read_byte (CRInput * a_this, guchar * a_byte) +{ + g_return_val_if_fail (a_this && PRIVATE (a_this) + && a_byte, CR_BAD_PARAM_ERROR); + + g_return_val_if_fail (PRIVATE (a_this)->next_byte_index <= + PRIVATE (a_this)->nb_bytes, CR_BAD_PARAM_ERROR); + + if (PRIVATE (a_this)->end_of_input == TRUE) + return CR_END_OF_INPUT_ERROR; + + *a_byte = PRIVATE (a_this)->in_buf[PRIVATE (a_this)->next_byte_index]; + + if (PRIVATE (a_this)->nb_bytes - + PRIVATE (a_this)->next_byte_index < 2) { + PRIVATE (a_this)->end_of_input = TRUE; + } else { + PRIVATE (a_this)->next_byte_index++; + } + + return CR_OK; +} + +/** + * cr_input_read_char: + *@a_this: the current instance of CRInput. + *@a_char: out parameter. The read character. + * + *Reads an unicode character from the current instance of + *#CRInput. + * + *Returns CR_OK upon successful completion, an error code + *otherwise. + */ +enum CRStatus +cr_input_read_char (CRInput * a_this, guint32 * a_char) +{ + enum CRStatus status = CR_OK; + gulong consumed = 0, + nb_bytes_left = 0; + + g_return_val_if_fail (a_this && PRIVATE (a_this) && a_char, + CR_BAD_PARAM_ERROR); + + if (PRIVATE (a_this)->end_of_input == TRUE) + return CR_END_OF_INPUT_ERROR; + + nb_bytes_left = cr_input_get_nb_bytes_left (a_this); + + if (nb_bytes_left < 1) { + return CR_END_OF_INPUT_ERROR; + } + + status = cr_utils_read_char_from_utf8_buf + (PRIVATE (a_this)->in_buf + + + PRIVATE (a_this)->next_byte_index, + nb_bytes_left, a_char, &consumed); + + if (status == CR_OK) { + /*update next byte index */ + PRIVATE (a_this)->next_byte_index += consumed; + + /*update line and column number */ + if (PRIVATE (a_this)->end_of_line == TRUE) { + PRIVATE (a_this)->col = 1; + PRIVATE (a_this)->line++; + PRIVATE (a_this)->end_of_line = FALSE; + } else if (*a_char != '\n') { + PRIVATE (a_this)->col++; + } + + if (*a_char == '\n') { + PRIVATE (a_this)->end_of_line = TRUE; + } + + } + + return status; +} + +/** + * cr_input_set_line_num: + *@a_this: the "this pointer" of the current instance of #CRInput. + *@a_line_num: the new line number. + * + *Setter of the current line number. + * + *Return CR_OK upon successful completion, an error code otherwise. + */ +enum CRStatus +cr_input_set_line_num (CRInput * a_this, glong a_line_num) +{ + g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR); + + PRIVATE (a_this)->line = a_line_num; + + return CR_OK; +} + +/** + * cr_input_get_line_num: + *@a_this: the "this pointer" of the current instance of #CRInput. + *@a_line_num: the returned line number. + * + *Getter of the current line number. + * + *Returns CR_OK upon successful completion, an error code otherwise. + */ +enum CRStatus +cr_input_get_line_num (CRInput * a_this, glong * a_line_num) +{ + g_return_val_if_fail (a_this && PRIVATE (a_this) + && a_line_num, CR_BAD_PARAM_ERROR); + + *a_line_num = PRIVATE (a_this)->line; + + return CR_OK; +} + +/** + * cr_input_set_column_num: + *@a_this: the "this pointer" of the current instance of #CRInput. + *@a_col: the new column number. + * + *Setter of the current column number. + * + *Returns CR_OK upon successful completion, an error code otherwise. + */ +enum CRStatus +cr_input_set_column_num (CRInput * a_this, glong a_col) +{ + g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR); + + PRIVATE (a_this)->col = a_col; + + return CR_OK; +} + +/** + * cr_input_get_column_num: + *@a_this: the "this pointer" of the current instance of #CRInput. + *@a_col: out parameter + * + *Getter of the current column number. + * + *Returns CR_OK upon successful completion, an error code otherwise. + */ +enum CRStatus +cr_input_get_column_num (CRInput * a_this, glong * a_col) +{ + g_return_val_if_fail (a_this && PRIVATE (a_this) && a_col, + CR_BAD_PARAM_ERROR); + + *a_col = PRIVATE (a_this)->col; + + return CR_OK; +} + +/** + * cr_input_increment_line_num: + *@a_this: the "this pointer" of the current instance of #CRInput. + *@a_increment: the increment to add to the line number. + * + *Increments the current line number. + * + *Returns CR_OK upon successful completion, an error code otherwise. + */ +enum CRStatus +cr_input_increment_line_num (CRInput * a_this, glong a_increment) +{ + g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR); + + PRIVATE (a_this)->line += a_increment; + + return CR_OK; +} + +/** + * cr_input_increment_col_num: + *@a_this: the "this pointer" of the current instance of #CRInput. + *@a_increment: the increment to add to the column number. + * + *Increments the current column number. + * + *Returns CR_OK upon successful completion, an error code otherwise. + */ +enum CRStatus +cr_input_increment_col_num (CRInput * a_this, glong a_increment) +{ + g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR); + + PRIVATE (a_this)->col += a_increment; + + return CR_OK; +} + +/** + * cr_input_consume_char: + *@a_this: the this pointer. + *@a_char: the character to consume. If set to zero, + *consumes any character. + * + *Consumes the next character of the input stream if + *and only if that character equals a_char. + * + *Returns CR_OK upon successful completion, CR_PARSING_ERROR if + *next char is different from a_char, an other error code otherwise + */ +enum CRStatus +cr_input_consume_char (CRInput * a_this, guint32 a_char) +{ + guint32 c; + enum CRStatus status; + + g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR); + + if ((status = cr_input_peek_char (a_this, &c)) != CR_OK) { + return status; + } + + if (c == a_char || a_char == 0) { + status = cr_input_read_char (a_this, &c); + } else { + return CR_PARSING_ERROR; + } + + return status; +} + +/** + * cr_input_consume_chars: + *@a_this: the this pointer of the current instance of #CRInput. + *@a_char: the character to consume. + *@a_nb_char: in/out parameter. The number of characters to consume. + *If set to a negative value, the function will consume all the occurences + *of a_char found. + *After return, if the return value equals CR_OK, this variable contains + *the number of characters actually consumed. + * + *Consumes up to a_nb_char occurences of the next contiguous characters + *which equal a_char. Note that the next character of the input stream + **MUST* equal a_char to trigger the consumption, or else, the error + *code CR_PARSING_ERROR is returned. + *If the number of contiguous characters that equals a_char is less than + *a_nb_char, then this function consumes all the characters it can consume. + * + *Returns CR_OK if at least one character has been consumed, an error code + *otherwise. + */ +enum CRStatus +cr_input_consume_chars (CRInput * a_this, guint32 a_char, gulong * a_nb_char) +{ + enum CRStatus status = CR_OK; + gulong nb_consumed = 0; + + g_return_val_if_fail (a_this && PRIVATE (a_this) && a_nb_char, + CR_BAD_PARAM_ERROR); + + g_return_val_if_fail (a_char != 0 || a_nb_char != NULL, + CR_BAD_PARAM_ERROR); + + for (nb_consumed = 0; ((status == CR_OK) + && (*a_nb_char > 0 + && nb_consumed < *a_nb_char)); + nb_consumed++) { + status = cr_input_consume_char (a_this, a_char); + } + + *a_nb_char = nb_consumed; + + if ((nb_consumed > 0) + && ((status == CR_PARSING_ERROR) + || (status == CR_END_OF_INPUT_ERROR))) { + status = CR_OK; + } + + return status; +} + +/** + * cr_input_consume_white_spaces: + *@a_this: the "this pointer" of the current instance of #CRInput. + *@a_nb_chars: in/out parameter. The number of white spaces to + *consume. After return, holds the number of white spaces actually consumed. + * + *Same as cr_input_consume_chars() but this one consumes white + *spaces. + * + *Returns CR_OK upon successful completion, an error code otherwise. + */ +enum CRStatus +cr_input_consume_white_spaces (CRInput * a_this, gulong * a_nb_chars) +{ + enum CRStatus status = CR_OK; + guint32 cur_char = 0, + nb_consumed = 0; + + g_return_val_if_fail (a_this && PRIVATE (a_this) && a_nb_chars, + CR_BAD_PARAM_ERROR); + + for (nb_consumed = 0; + ((*a_nb_chars > 0) && (nb_consumed < *a_nb_chars)); + nb_consumed++) { + status = cr_input_peek_char (a_this, &cur_char); + if (status != CR_OK) + break; + + /*if the next char is a white space, consume it ! */ + if (cr_utils_is_white_space (cur_char) == TRUE) { + status = cr_input_read_char (a_this, &cur_char); + if (status != CR_OK) + break; + continue; + } + + break; + + } + + if (nb_consumed && status == CR_END_OF_INPUT_ERROR) { + status = CR_OK; + } + + return status; +} + +/** + * cr_input_peek_char: + *@a_this: the current instance of #CRInput. + *@a_char: out parameter. The returned character. + * + *Same as cr_input_read_char() but does not update the + *internal state of the input stream. The next call + *to cr_input_peek_char() or cr_input_read_char() will thus + *return the same character as the current one. + * + *Returns CR_OK upon successful completion, an error code + *otherwise. + */ +enum CRStatus +cr_input_peek_char (CRInput * a_this, guint32 * a_char) +{ + enum CRStatus status = CR_OK; + glong consumed = 0, + nb_bytes_left = 0; + + g_return_val_if_fail (a_this && PRIVATE (a_this) + && a_char, CR_BAD_PARAM_ERROR); + + if (PRIVATE (a_this)->next_byte_index >= + PRIVATE (a_this)->in_buf_size) { + return CR_END_OF_INPUT_ERROR; + } + + nb_bytes_left = cr_input_get_nb_bytes_left (a_this); + + if (nb_bytes_left < 1) { + return CR_END_OF_INPUT_ERROR; + } + + status = cr_utils_read_char_from_utf8_buf + (PRIVATE (a_this)->in_buf + + PRIVATE (a_this)->next_byte_index, + nb_bytes_left, a_char, &consumed); + + return status; +} + +/** + * cr_input_peek_byte: + *@a_this: the current instance of #CRInput. + *@a_origin: the origin to consider in the calculation + *of the position of the byte to peek. + *@a_offset: the offset of the byte to peek, starting from + *the origin specified by a_origin. + *@a_byte: out parameter the peeked byte. + * + *Gets a byte from the input stream, + *starting from the current position in the input stream. + *Unlike cr_input_peek_next_byte() this method + *does not update the state of the current input stream. + *Subsequent calls to cr_input_peek_byte with the same arguments + *will return the same byte. + * + *Returns CR_OK upon successful completion or, + *CR_BAD_PARAM_ERROR if at least one of the parameters is invalid; + *CR_OUT_OF_BOUNDS_ERROR if the indexed byte is out of bounds. + */ +enum CRStatus +cr_input_peek_byte (CRInput * a_this, enum CRSeekPos a_origin, + gulong a_offset, guchar * a_byte) +{ + gulong abs_offset = 0; + + g_return_val_if_fail (a_this && PRIVATE (a_this) + && a_byte, CR_BAD_PARAM_ERROR); + + switch (a_origin) { + + case CR_SEEK_CUR: + abs_offset = PRIVATE (a_this)->next_byte_index - 1 + a_offset; + break; + + case CR_SEEK_BEGIN: + abs_offset = a_offset; + break; + + case CR_SEEK_END: + abs_offset = PRIVATE (a_this)->in_buf_size - 1 - a_offset; + break; + + default: + return CR_BAD_PARAM_ERROR; + } + + if (abs_offset < PRIVATE (a_this)->in_buf_size) { + + *a_byte = PRIVATE (a_this)->in_buf[abs_offset]; + + return CR_OK; + + } else { + return CR_END_OF_INPUT_ERROR; + } +} + +/** + * cr_input_peek_byte2: + *@a_this: the current byte input stream. + *@a_offset: the offset of the byte to peek, starting + *from the current input position pointer. + *@a_eof: out parameter. Is set to true is we reach end of + *stream. If set to NULL by the caller, this parameter is not taken + *in account. + * + *Same as cr_input_peek_byte() but with a simplified + *interface. + * + *Returns the read byte or 0 if something bad happened. + */ +guchar +cr_input_peek_byte2 (CRInput * a_this, gulong a_offset, gboolean * a_eof) +{ + guchar result = 0; + enum CRStatus status = CR_ERROR; + + g_return_val_if_fail (a_this && PRIVATE (a_this), 0); + + if (a_eof) + *a_eof = FALSE; + + status = cr_input_peek_byte (a_this, CR_SEEK_CUR, a_offset, &result); + + if ((status == CR_END_OF_INPUT_ERROR) + && a_eof) + *a_eof = TRUE; + + return result; +} + +/** + * cr_input_get_byte_addr: + *@a_this: the current instance of #CRInput. + *@a_offset: the offset of the byte in the input stream starting + *from the beginning of the stream. + * + *Gets the memory address of the byte located at a given offset + *in the input stream. + * + *Returns the address, otherwise NULL if an error occured. + */ +guchar * +cr_input_get_byte_addr (CRInput * a_this, gulong a_offset) +{ + g_return_val_if_fail (a_this && PRIVATE (a_this), NULL); + + if (a_offset >= PRIVATE (a_this)->nb_bytes) { + return NULL; + } + + return &PRIVATE (a_this)->in_buf[a_offset]; +} + +/** + * cr_input_get_cur_byte_addr: + *@a_this: the current input stream + *@a_offset: out parameter. The returned address. + * + *Gets the address of the current character pointer. + * + *Returns CR_OK upon successful completion, an error code otherwise. + */ +enum CRStatus +cr_input_get_cur_byte_addr (CRInput * a_this, guchar ** a_offset) +{ + g_return_val_if_fail (a_this && PRIVATE (a_this) && a_offset, + CR_BAD_PARAM_ERROR); + + if (!PRIVATE (a_this)->next_byte_index) { + return CR_START_OF_INPUT_ERROR; + } + + *a_offset = cr_input_get_byte_addr + (a_this, PRIVATE (a_this)->next_byte_index - 1); + + return CR_OK; +} + +/** + * cr_input_seek_index: + *@a_this: the current instance of #CRInput. + *@a_origin: the origin to consider during the calculation + *of the absolute position of the new "current byte index". + *@a_pos: the relative offset of the new "current byte index." + *This offset is relative to the origin a_origin. + * + *Sets the "current byte index" of the current instance + *of #CRInput. Next call to cr_input_get_byte() will return + *the byte next after the new "current byte index". + * + *Returns CR_OK upon successful completion otherwise returns + *CR_BAD_PARAM_ERROR if at least one of the parameters is not valid + *or CR_OUT_BOUNDS_ERROR in case of error. + */ +enum CRStatus +cr_input_seek_index (CRInput * a_this, enum CRSeekPos a_origin, gint a_pos) +{ + + glong abs_offset = 0; + + g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR); + + switch (a_origin) { + + case CR_SEEK_CUR: + abs_offset = PRIVATE (a_this)->next_byte_index - 1 + a_pos; + break; + + case CR_SEEK_BEGIN: + abs_offset = a_pos; + break; + + case CR_SEEK_END: + abs_offset = PRIVATE (a_this)->in_buf_size - 1 - a_pos; + break; + + default: + return CR_BAD_PARAM_ERROR; + } + + if ((abs_offset > 0) + && (gulong) abs_offset < PRIVATE (a_this)->nb_bytes) { + + /*update the input stream's internal state */ + PRIVATE (a_this)->next_byte_index = abs_offset + 1; + + return CR_OK; + } + + return CR_OUT_OF_BOUNDS_ERROR; +} + +/** + * cr_input_get_cur_pos: + *@a_this: the current instance of #CRInput. + *@a_pos: out parameter. The returned position. + * + *Gets the position of the "current byte index" which + *is basically the position of the last returned byte in the + *input stream. + * + *Returns CR_OK upon successful completion. Otherwise, + *CR_BAD_PARAMETER_ERROR if at least one of the arguments is invalid. + *CR_START_OF_INPUT if no call to either cr_input_read_byte() + *or cr_input_seek_index() have been issued before calling + *cr_input_get_cur_pos() + *Note that the out parameters of this function are valid if and only if this + *function returns CR_OK. + */ +enum CRStatus +cr_input_get_cur_pos (CRInput * a_this, CRInputPos * a_pos) +{ + g_return_val_if_fail (a_this && PRIVATE (a_this) && a_pos, + CR_BAD_PARAM_ERROR); + + a_pos->next_byte_index = PRIVATE (a_this)->next_byte_index; + a_pos->line = PRIVATE (a_this)->line; + a_pos->col = PRIVATE (a_this)->col; + a_pos->end_of_line = PRIVATE (a_this)->end_of_line; + a_pos->end_of_file = PRIVATE (a_this)->end_of_input; + + return CR_OK; +} + +/** + * cr_input_get_parsing_location: + *@a_this: the current instance of #CRInput + *@a_loc: the set parsing location. + * + *Gets the current parsing location. + *The Parsing location is a public datastructure that + *represents the current line/column/byte offset/ in the input + *stream. + * + *Returns CR_OK upon successful completion, an error + *code otherwise. + */ +enum CRStatus +cr_input_get_parsing_location (CRInput *a_this, + CRParsingLocation *a_loc) +{ + g_return_val_if_fail (a_this + && PRIVATE (a_this) + && a_loc, + CR_BAD_PARAM_ERROR) ; + + a_loc->line = PRIVATE (a_this)->line ; + a_loc->column = PRIVATE (a_this)->col ; + if (PRIVATE (a_this)->next_byte_index) { + a_loc->byte_offset = PRIVATE (a_this)->next_byte_index - 1 ; + } else { + a_loc->byte_offset = PRIVATE (a_this)->next_byte_index ; + } + return CR_OK ; +} + +/** + * cr_input_get_cur_index: + *@a_this: the "this pointer" of the current instance of + *#CRInput + *@a_index: out parameter. The returned index. + * + *Getter of the next byte index. + *It actually returns the index of the + *next byte to be read. + * + *Returns CR_OK upon successful completion, an error code + *otherwise. + */ +enum CRStatus +cr_input_get_cur_index (CRInput * a_this, glong * a_index) +{ + g_return_val_if_fail (a_this && PRIVATE (a_this) + && a_index, CR_BAD_PARAM_ERROR); + + *a_index = PRIVATE (a_this)->next_byte_index; + + return CR_OK; +} + +/** + * cr_input_set_cur_index: + *@a_this: the "this pointer" of the current instance + *of #CRInput . + *@a_index: the new index to set. + * + *Setter of the next byte index. + *It sets the index of the next byte to be read. + * + *Returns CR_OK upon successful completion, an error code otherwise. + */ +enum CRStatus +cr_input_set_cur_index (CRInput * a_this, glong a_index) +{ + g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR); + + PRIVATE (a_this)->next_byte_index = a_index; + + return CR_OK; +} + +/** + * cr_input_set_end_of_file: + *@a_this: the current instance of #CRInput. + *@a_eof: the new end of file flag. + * + *Sets the end of file flag. + * + *Returns CR_OK upon successful completion, an error code otherwise. + */ +enum CRStatus +cr_input_set_end_of_file (CRInput * a_this, gboolean a_eof) +{ + g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR); + + PRIVATE (a_this)->end_of_input = a_eof; + + return CR_OK; +} + +/** + * cr_input_get_end_of_file: + *@a_this: the current instance of #CRInput. + *@a_eof: out parameter the place to put the end of + *file flag. + * + *Gets the end of file flag. + * + *Returns CR_OK upon successful completion, an error code otherwise. + */ +enum CRStatus +cr_input_get_end_of_file (CRInput * a_this, gboolean * a_eof) +{ + g_return_val_if_fail (a_this && PRIVATE (a_this) + && a_eof, CR_BAD_PARAM_ERROR); + + *a_eof = PRIVATE (a_this)->end_of_input; + + return CR_OK; +} + +/** + * cr_input_set_end_of_line: + *@a_this: the current instance of #CRInput. + *@a_eol: the new end of line flag. + * + *Sets the end of line flag. + * + *Returns CR_OK upon successful completion, an error code + *otherwise. + */ +enum CRStatus +cr_input_set_end_of_line (CRInput * a_this, gboolean a_eol) +{ + g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR); + + PRIVATE (a_this)->end_of_line = a_eol; + + return CR_OK; +} + +/** + * cr_input_get_end_of_line: + *@a_this: the current instance of #CRInput + *@a_eol: out parameter. The place to put + *the returned flag + * + *Gets the end of line flag of the current input. + * + *Returns CR_OK upon successful completion, an error code + *otherwise. + */ +enum CRStatus +cr_input_get_end_of_line (CRInput * a_this, gboolean * a_eol) +{ + g_return_val_if_fail (a_this && PRIVATE (a_this) + && a_eol, CR_BAD_PARAM_ERROR); + + *a_eol = PRIVATE (a_this)->end_of_line; + + return CR_OK; +} + +/** + * cr_input_set_cur_pos: + *@a_this: the "this pointer" of the current instance of + *#CRInput. + *@a_pos: the new position. + * + *Sets the current position in the input stream. + * + * Returns CR_OK upon successful completion, an error code otherwise. + */ +enum CRStatus +cr_input_set_cur_pos (CRInput * a_this, CRInputPos * a_pos) +{ + g_return_val_if_fail (a_this && PRIVATE (a_this) && a_pos, + CR_BAD_PARAM_ERROR); + + cr_input_set_column_num (a_this, a_pos->col); + cr_input_set_line_num (a_this, a_pos->line); + cr_input_set_cur_index (a_this, a_pos->next_byte_index); + cr_input_set_end_of_line (a_this, a_pos->end_of_line); + cr_input_set_end_of_file (a_this, a_pos->end_of_file); + + return CR_OK; +} diff --git a/gettext-tools/gnulib-lib/libcroco/cr-input.h b/gettext-tools/gnulib-lib/libcroco/cr-input.h new file mode 100644 index 0000000..8eb684e --- /dev/null +++ b/gettext-tools/gnulib-lib/libcroco/cr-input.h @@ -0,0 +1,174 @@ +/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset:8 -*- */ + +/* + * This file is part of The Croco Library + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + * Author: Dodji Seketeli + * See the COPYRIGHTS file for copyrights information. + */ + +#ifndef __CR_INPUT_SRC_H__ +#define __CR_INPUT_SRC_H__ + + +#include +#include "cr-utils.h" +#include "cr-parsing-location.h" + +G_BEGIN_DECLS + +/** + *@file + *The libcroco basic input stream class + *declaration file. + */ + +typedef struct _CRInput CRInput ; +typedef struct _CRInputPriv CRInputPriv ; + +/** + *The #CRInput class provides the abstraction of + *an utf8-encoded character stream. + */ +struct _CRInput +{ + CRInputPriv *priv ; +} ; + +typedef struct _CRInputPos CRInputPos ; + +struct _CRInputPos +{ + glong line ; + glong col ; + gboolean end_of_file ; + gboolean end_of_line ; + glong next_byte_index ; +} ; + +CRInput * +cr_input_new_from_buf (guchar *a_buf, gulong a_len, + enum CREncoding a_enc, gboolean a_free_buf) ; +CRInput * +cr_input_new_from_uri (const gchar *a_file_uri, + enum CREncoding a_enc) ; + +void +cr_input_destroy (CRInput *a_this) ; + +void +cr_input_ref (CRInput *a_this) ; + +gboolean +cr_input_unref (CRInput *a_this) ; + +enum CRStatus +cr_input_read_byte (CRInput *a_this, guchar *a_byte) ; + +enum CRStatus +cr_input_read_char (CRInput *a_this, guint32 *a_char) ; + +enum CRStatus +cr_input_consume_chars (CRInput *a_this, guint32 a_char, + gulong *a_nb_char) ; + +enum CRStatus +cr_input_consume_char (CRInput *a_this, guint32 a_char) ; + +enum CRStatus +cr_input_consume_white_spaces (CRInput *a_this, gulong *a_nb_chars) ; + +enum CRStatus +cr_input_peek_byte (CRInput *a_this, enum CRSeekPos a_origin, + gulong a_offset, guchar *a_byte) ; + +guchar +cr_input_peek_byte2 (CRInput *a_this, gulong a_offset, + gboolean *a_eof) ; + +enum CRStatus +cr_input_peek_char (CRInput *a_this, guint32 *a_char) ; + +guchar * +cr_input_get_byte_addr (CRInput *a_this, + gulong a_offset) ; + +enum CRStatus +cr_input_get_cur_byte_addr (CRInput *a_this, guchar ** a_offset) ; + +enum CRStatus +cr_input_seek_index (CRInput *a_this, + enum CRSeekPos a_origin, gint a_pos) ; + +enum CRStatus +cr_input_get_cur_index (CRInput *a_this, glong *a_index) ; + +enum CRStatus +cr_input_set_cur_index (CRInput *a_this, glong a_index) ; + +enum CRStatus +cr_input_get_cur_pos (CRInput *a_this, CRInputPos * a_pos) ; + +enum CRStatus +cr_input_set_cur_pos (CRInput *a_this, CRInputPos *a_pos) ; + +enum CRStatus +cr_input_get_parsing_location (CRInput *a_this, + CRParsingLocation *a_loc) ; + +enum CRStatus +cr_input_get_end_of_line (CRInput *a_this, gboolean *a_eol) ; + +enum CRStatus +cr_input_set_end_of_line (CRInput *a_this, gboolean a_eol) ; + +enum CRStatus +cr_input_get_end_of_file (CRInput *a_this, gboolean *a_eof) ; + +enum CRStatus +cr_input_set_end_of_file (CRInput *a_this, gboolean a_eof) ; + +enum CRStatus +cr_input_set_line_num (CRInput *a_this, glong a_line_num) ; + +enum CRStatus +cr_input_get_line_num (CRInput *a_this, glong *a_line_num) ; + +enum CRStatus +cr_input_set_column_num (CRInput *a_this, glong a_col) ; + +enum CRStatus +cr_input_get_column_num (CRInput *a_this, glong *a_col) ; + +enum CRStatus +cr_input_increment_line_num (CRInput *a_this, + glong a_increment) ; + +enum CRStatus +cr_input_increment_col_num (CRInput *a_this, + glong a_increment) ; + +glong +cr_input_get_nb_bytes_left (CRInput *a_this) ; + +enum CRStatus +cr_input_end_of_input (CRInput *a_this, gboolean *a_end_of_input) ; + +G_END_DECLS + +#endif /*__CR_INPUT_SRC_H__*/ + diff --git a/gettext-tools/gnulib-lib/libcroco/cr-num.c b/gettext-tools/gnulib-lib/libcroco/cr-num.c new file mode 100644 index 0000000..4735fff --- /dev/null +++ b/gettext-tools/gnulib-lib/libcroco/cr-num.c @@ -0,0 +1,312 @@ +/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */ + +/* + * This file is part of The Croco Library + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + * Author: Dodji Seketeli + * See COPYRIGHTS file for copyrights information. + */ + +/** + *@CRNum: + * + *The definition + *of the #CRNum class. + */ + +#include +#include "cr-num.h" +#include "string.h" + +/** + * cr_num_new: + * + *#CRNum. + * + *Returns the newly built instance of + *#CRNum. + */ +CRNum * +cr_num_new (void) +{ + CRNum *result = NULL; + + result = g_try_malloc (sizeof (CRNum)); + + if (result == NULL) { + cr_utils_trace_info ("Out of memory"); + return NULL; + } + + memset (result, 0, sizeof (CRNum)); + + return result; +} + +/** + * cr_num_new_with_val: + * @a_val: the numerical value of the number. + * @a_type: the type of number. + * + * A constructor of #CRNum. + * + * Returns the newly built instance of #CRNum or + * NULL if an error arises. + */ +CRNum * +cr_num_new_with_val (gdouble a_val, enum CRNumType a_type) +{ + CRNum *result = NULL; + + result = cr_num_new (); + + g_return_val_if_fail (result, NULL); + + result->val = a_val; + result->type = a_type; + + return result; +} + +/** + * cr_num_to_string: + *@a_this: the current instance of #CRNum. + * + *Returns the newly built string representation + *of the current instance of #CRNum. The returned + *string is NULL terminated. The caller *must* + *free the returned string. + */ +guchar * +cr_num_to_string (CRNum * a_this) +{ + gdouble test_val = 0.0; + + guchar *tmp_char1 = NULL, + *tmp_char2 = NULL, + *result = NULL; + + g_return_val_if_fail (a_this, NULL); + + test_val = a_this->val - (glong) a_this->val; + + if (!test_val) { + tmp_char1 = g_strdup_printf ("%ld", (glong) a_this->val); + } else { + tmp_char1 = g_strdup_printf ("%.3f", a_this->val); + } + + g_return_val_if_fail (tmp_char1, NULL); + + switch (a_this->type) { + case NUM_LENGTH_EM: + tmp_char2 = (guchar *) "em"; + break; + + case NUM_LENGTH_EX: + tmp_char2 = (guchar *) "ex"; + break; + + case NUM_LENGTH_PX: + tmp_char2 = (guchar *) "px"; + break; + + case NUM_LENGTH_IN: + tmp_char2 = (guchar *) "in"; + break; + + case NUM_LENGTH_CM: + tmp_char2 = (guchar *) "cm"; + break; + + case NUM_LENGTH_MM: + tmp_char2 = (guchar *) "mm"; + break; + + case NUM_LENGTH_PT: + tmp_char2 = (guchar *) "pt"; + break; + + case NUM_LENGTH_PC: + tmp_char2 = (guchar *) "pc"; + break; + + case NUM_ANGLE_DEG: + tmp_char2 = (guchar *) "deg"; + break; + + case NUM_ANGLE_RAD: + tmp_char2 = (guchar *) "rad"; + break; + + case NUM_ANGLE_GRAD: + tmp_char2 = (guchar *) "grad"; + break; + + case NUM_TIME_MS: + tmp_char2 = (guchar *) "ms"; + break; + + case NUM_TIME_S: + tmp_char2 = (guchar *) "s"; + break; + + case NUM_FREQ_HZ: + tmp_char2 = (guchar *) "Hz"; + break; + + case NUM_FREQ_KHZ: + tmp_char2 = (guchar *) "KHz"; + break; + + case NUM_PERCENTAGE: + tmp_char2 = (guchar *) "%"; + break; + case NUM_INHERIT: + tmp_char2 = (guchar *) "inherit"; + break ; + case NUM_AUTO: + tmp_char2 = (guchar *) "auto"; + break ; + case NUM_GENERIC: + tmp_char2 = NULL ; + break ; + default: + tmp_char2 = (guchar *) "unknown"; + break; + } + + if (tmp_char2) { + result = g_strconcat (tmp_char1, tmp_char2, NULL); + g_free (tmp_char1); + } else { + result = tmp_char1; + } + + return result; +} + +/** + * cr_num_copy: + *@a_src: the instance of #CRNum to copy. + *Must be non NULL. + *@a_dest: the destination of the copy. + *Must be non NULL + * + *Copies an instance of #CRNum. + * + *Returns CR_OK upon successful completion, an + *error code otherwise. + */ +enum CRStatus +cr_num_copy (CRNum * a_dest, CRNum * a_src) +{ + g_return_val_if_fail (a_dest && a_src, CR_BAD_PARAM_ERROR); + + memcpy (a_dest, a_src, sizeof (CRNum)); + + return CR_OK; +} + +/** + * cr_num_dup: + *@a_this: the instance of #CRNum to duplicate. + * + *Duplicates an instance of #CRNum + * + *Returns the newly created (duplicated) instance of #CRNum. + *Must be freed by cr_num_destroy(). + */ +CRNum * +cr_num_dup (CRNum * a_this) +{ + CRNum *result = NULL; + enum CRStatus status = CR_OK; + + g_return_val_if_fail (a_this, NULL); + + result = cr_num_new (); + g_return_val_if_fail (result, NULL); + + status = cr_num_copy (result, a_this); + g_return_val_if_fail (status == CR_OK, NULL); + + return result; +} + +/** + * cr_num_set: + *Sets an instance of #CRNum. + *@a_this: the current instance of #CRNum to be set. + *@a_val: the new numerical value to be hold by the current + *instance of #CRNum + *@a_type: the new type of #CRNum. + * + * Returns CR_OK upon succesful completion, an error code otherwise. + */ +enum CRStatus +cr_num_set (CRNum * a_this, gdouble a_val, enum CRNumType a_type) +{ + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); + + a_this->val = a_val; + a_this->type = a_type; + + return CR_OK; +} + +/** + * cr_num_is_fixed_length: + * @a_this: the current instance of #CRNum . + * + *Tests if the current instance of #CRNum is a fixed + *length value or not. Typically a fixed length value + *is anything from NUM_LENGTH_EM to NUM_LENGTH_PC. + *See the definition of #CRNumType to see what we mean. + * + *Returns TRUE if the instance of #CRNum is a fixed length number, + *FALSE otherwise. + */ +gboolean +cr_num_is_fixed_length (CRNum * a_this) +{ + gboolean result = FALSE; + + g_return_val_if_fail (a_this, FALSE); + + if (a_this->type >= NUM_LENGTH_EM + && a_this->type <= NUM_LENGTH_PC) { + result = TRUE ; + } + return result ; +} + +/** + * cr_num_destroy: + *@a_this: the this pointer of + *the current instance of #CRNum. + * + *The destructor of #CRNum. + */ +void +cr_num_destroy (CRNum * a_this) +{ + g_return_if_fail (a_this); + + g_free (a_this); +} diff --git a/gettext-tools/gnulib-lib/libcroco/cr-num.h b/gettext-tools/gnulib-lib/libcroco/cr-num.h new file mode 100644 index 0000000..2af93bc --- /dev/null +++ b/gettext-tools/gnulib-lib/libcroco/cr-num.h @@ -0,0 +1,127 @@ +/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */ + +/* + * This file is part of The Croco Library + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + * Author: Dodji Seketeli + * See COPYRIGHTS file for copyright information + */ + + +/** + *@file + *The declaration + *of the #CRNum class. + */ + +#ifndef __CR_NUM_H__ +#define __CR_NUM_H__ + +#include +#include "cr-utils.h" +#include "cr-parsing-location.h" + +G_BEGIN_DECLS + +/** + *@file + *The declaration of the #CRNum class. + * + */ + +/** + *The different types + *of numbers. + *Please, do not modify + *the declaration order of the enum + *members, unless you know + *what you are doing. + */ +enum CRNumType +{ + NUM_AUTO = 0, + NUM_GENERIC, + NUM_LENGTH_EM, + NUM_LENGTH_EX, + NUM_LENGTH_PX, + NUM_LENGTH_IN, + NUM_LENGTH_CM, + NUM_LENGTH_MM, + NUM_LENGTH_PT, + NUM_LENGTH_PC, + NUM_ANGLE_DEG, + NUM_ANGLE_RAD, + NUM_ANGLE_GRAD, + NUM_TIME_MS, + NUM_TIME_S, + NUM_FREQ_HZ, + NUM_FREQ_KHZ, + NUM_PERCENTAGE, + NUM_INHERIT, + NUM_UNKNOWN_TYPE, + NB_NUM_TYPE +} ; + + +/** + *An abstraction of a number (num) + *as defined in the css2 spec. + */ +typedef struct _CRNum CRNum ; + +/** + *An abstraction of a number (num) + *as defined in the css2 spec. + */ +struct _CRNum +{ + enum CRNumType type ; + gdouble val ; + CRParsingLocation location ; +} ; + +CRNum * +cr_num_new (void) ; + +CRNum * +cr_num_new_with_val (gdouble a_val, + enum CRNumType a_type) ; + +CRNum * +cr_num_dup (CRNum *a_this) ; + +guchar * +cr_num_to_string (CRNum *a_this) ; + +enum CRStatus +cr_num_copy (CRNum *a_dest, CRNum *a_src) ; + +enum CRStatus +cr_num_set (CRNum *a_this, gdouble a_val, + enum CRNumType a_type) ; + +gboolean +cr_num_is_fixed_length (CRNum *a_this) ; + +void +cr_num_destroy (CRNum *a_this) ; + + +G_END_DECLS + + +#endif /*__CR_NUM_H__*/ diff --git a/gettext-tools/gnulib-lib/libcroco/cr-om-parser.c b/gettext-tools/gnulib-lib/libcroco/cr-om-parser.c new file mode 100644 index 0000000..3f8b5ed --- /dev/null +++ b/gettext-tools/gnulib-lib/libcroco/cr-om-parser.c @@ -0,0 +1,1122 @@ +/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */ + +/* + * This file is part of The Croco Library + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + * Author: Dodji Seketeli + * See COPYRIGHTS file for copyright information. + */ + +#include +#include +#include "cr-utils.h" +#include "cr-om-parser.h" + +/** + *@CROMParser: + * + *The definition of the CSS Object Model Parser. + *This parser uses (and sits) the SAC api of libcroco defined + *in cr-parser.h and cr-doc-handler.h + */ + +struct _CROMParserPriv { + CRParser *parser; +}; + +#define PRIVATE(a_this) ((a_this)->priv) + +/* + *Forward declaration of a type defined later + *in this file. + */ +struct _ParsingContext; +typedef struct _ParsingContext ParsingContext; + +static ParsingContext *new_parsing_context (void); + +static void destroy_context (ParsingContext * a_ctxt); + +static void unrecoverable_error (CRDocHandler * a_this); + +static void error (CRDocHandler * a_this); + +static void property (CRDocHandler * a_this, + CRString * a_name, + CRTerm * a_expression, + gboolean a_important); + +static void end_selector (CRDocHandler * a_this, + CRSelector * a_selector_list); + +static void start_selector (CRDocHandler * a_this, + CRSelector * a_selector_list); + +static void start_font_face (CRDocHandler * a_this, + CRParsingLocation *a_location); + +static void end_font_face (CRDocHandler * a_this); + +static void end_document (CRDocHandler * a_this); + +static void start_document (CRDocHandler * a_this); + +static void charset (CRDocHandler * a_this, + CRString * a_charset, + CRParsingLocation *a_location); + +static void start_page (CRDocHandler * a_this, CRString * a_page, + CRString * a_pseudo_page, + CRParsingLocation *a_location); + +static void end_page (CRDocHandler * a_this, CRString * a_page, + CRString * a_pseudo_page); + +static void start_media (CRDocHandler * a_this, + GList * a_media_list, + CRParsingLocation *a_location); + +static void end_media (CRDocHandler * a_this, + GList * a_media_list); + +static void import_style (CRDocHandler * a_this, + GList * a_media_list, + CRString * a_uri, + CRString * a_uri_default_ns, + CRParsingLocation *a_location); + +struct _ParsingContext { + CRStyleSheet *stylesheet; + CRStatement *cur_stmt; + CRStatement *cur_media_stmt; +}; + +/******************************************** + *Private methods + ********************************************/ + +static ParsingContext * +new_parsing_context (void) +{ + ParsingContext *result = NULL; + + result = g_try_malloc (sizeof (ParsingContext)); + if (!result) { + cr_utils_trace_info ("Out of Memory"); + return NULL; + } + memset (result, 0, sizeof (ParsingContext)); + return result; +} + +static void +destroy_context (ParsingContext * a_ctxt) +{ + g_return_if_fail (a_ctxt); + + if (a_ctxt->stylesheet) { + cr_stylesheet_destroy (a_ctxt->stylesheet); + a_ctxt->stylesheet = NULL; + } + if (a_ctxt->cur_stmt) { + cr_statement_destroy (a_ctxt->cur_stmt); + a_ctxt->cur_stmt = NULL; + } + g_free (a_ctxt); +} + +static enum CRStatus +cr_om_parser_init_default_sac_handler (CROMParser * a_this) +{ + CRDocHandler *sac_handler = NULL; + gboolean free_hdlr_if_error = FALSE; + enum CRStatus status = CR_OK; + + g_return_val_if_fail (a_this && PRIVATE (a_this) + && PRIVATE (a_this)->parser, + CR_BAD_PARAM_ERROR); + + status = cr_parser_get_sac_handler (PRIVATE (a_this)->parser, + &sac_handler); + g_return_val_if_fail (status == CR_OK, status); + + if (!sac_handler) { + sac_handler = cr_doc_handler_new (); + free_hdlr_if_error = TRUE; + } + + /* + *initialyze here the sac handler. + */ + sac_handler->start_document = start_document; + sac_handler->end_document = end_document; + sac_handler->start_selector = start_selector; + sac_handler->end_selector = end_selector; + sac_handler->property = property; + sac_handler->start_font_face = start_font_face; + sac_handler->end_font_face = end_font_face; + sac_handler->error = error; + sac_handler->unrecoverable_error = unrecoverable_error; + sac_handler->charset = charset; + sac_handler->start_page = start_page; + sac_handler->end_page = end_page; + sac_handler->start_media = start_media; + sac_handler->end_media = end_media; + sac_handler->import_style = import_style; + + status = cr_parser_set_sac_handler (PRIVATE (a_this)->parser, + sac_handler); + if (status == CR_OK) { + return CR_OK; + } + + if (sac_handler && free_hdlr_if_error == TRUE) { + cr_doc_handler_destroy (sac_handler); + sac_handler = NULL; + } + + return status; + +} + +static void +start_document (CRDocHandler * a_this) +{ + ParsingContext *ctxt = NULL; + CRStyleSheet *stylesheet = NULL; + + g_return_if_fail (a_this); + + ctxt = new_parsing_context (); + g_return_if_fail (ctxt); + + stylesheet = cr_stylesheet_new (NULL); + ctxt->stylesheet = stylesheet; + cr_doc_handler_set_ctxt (a_this, ctxt); +} + +static void +start_font_face (CRDocHandler * a_this, + CRParsingLocation *a_location) +{ + enum CRStatus status = CR_OK; + ParsingContext *ctxt = NULL; + ParsingContext **ctxtptr = NULL; + + g_return_if_fail (a_this); + + g_return_if_fail (a_this); + ctxtptr = &ctxt; + status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); + g_return_if_fail (status == CR_OK && ctxt); + g_return_if_fail (ctxt->cur_stmt == NULL); + + ctxt->cur_stmt = + cr_statement_new_at_font_face_rule (ctxt->stylesheet, NULL); + + g_return_if_fail (ctxt->cur_stmt); +} + +static void +end_font_face (CRDocHandler * a_this) +{ + enum CRStatus status = CR_OK; + ParsingContext *ctxt = NULL; + ParsingContext **ctxtptr = NULL; + CRStatement *stmts = NULL; + + g_return_if_fail (a_this); + + g_return_if_fail (a_this); + ctxtptr = &ctxt; + status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); + g_return_if_fail (status == CR_OK && ctxt); + g_return_if_fail + (ctxt->cur_stmt + && ctxt->cur_stmt->type == AT_FONT_FACE_RULE_STMT + && ctxt->stylesheet); + + stmts = cr_statement_append (ctxt->stylesheet->statements, + ctxt->cur_stmt); + if (!stmts) + goto error; + + ctxt->stylesheet->statements = stmts; + stmts = NULL; + ctxt->cur_stmt = NULL; + + return; + + error: + + if (ctxt->cur_stmt) { + cr_statement_destroy (ctxt->cur_stmt); + ctxt->cur_stmt = NULL; + } + + if (!stmts) { + cr_statement_destroy (stmts); + stmts = NULL; + } +} + +static void +end_document (CRDocHandler * a_this) +{ + enum CRStatus status = CR_OK; + ParsingContext *ctxt = NULL; + ParsingContext **ctxtptr = NULL; + + g_return_if_fail (a_this); + ctxtptr = &ctxt; + status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); + g_return_if_fail (status == CR_OK && ctxt); + + if (!ctxt->stylesheet || ctxt->cur_stmt) + goto error; + + status = cr_doc_handler_set_result (a_this, ctxt->stylesheet); + g_return_if_fail (status == CR_OK); + + ctxt->stylesheet = NULL; + destroy_context (ctxt); + cr_doc_handler_set_ctxt (a_this, NULL); + + return; + + error: + if (ctxt) { + destroy_context (ctxt); + } +} + +static void +charset (CRDocHandler * a_this, CRString * a_charset, + CRParsingLocation *a_location) +{ + enum CRStatus status = CR_OK; + CRStatement *stmt = NULL, + *stmt2 = NULL; + CRString *charset = NULL; + + ParsingContext *ctxt = NULL; + ParsingContext **ctxtptr = NULL; + + g_return_if_fail (a_this); + ctxtptr = &ctxt; + status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); + g_return_if_fail (status == CR_OK && ctxt); + g_return_if_fail (ctxt->stylesheet); + + charset = cr_string_dup (a_charset) ; + stmt = cr_statement_new_at_charset_rule (ctxt->stylesheet, charset); + g_return_if_fail (stmt); + stmt2 = cr_statement_append (ctxt->stylesheet->statements, stmt); + if (!stmt2) { + if (stmt) { + cr_statement_destroy (stmt); + stmt = NULL; + } + if (charset) { + cr_string_destroy (charset); + } + return; + } + ctxt->stylesheet->statements = stmt2; + stmt2 = NULL; +} + +static void +start_page (CRDocHandler * a_this, + CRString * a_page, + CRString * a_pseudo, + CRParsingLocation *a_location) +{ + enum CRStatus status = CR_OK; + ParsingContext *ctxt = NULL; + ParsingContext **ctxtptr = NULL; + + g_return_if_fail (a_this); + ctxtptr = &ctxt; + status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); + g_return_if_fail (status == CR_OK && ctxt); + g_return_if_fail (ctxt->cur_stmt == NULL); + + ctxt->cur_stmt = cr_statement_new_at_page_rule + (ctxt->stylesheet, NULL, NULL, NULL); + if (a_page) { + ctxt->cur_stmt->kind.page_rule->name = + cr_string_dup (a_page) ; + + if (!ctxt->cur_stmt->kind.page_rule->name) { + goto error; + } + } + if (a_pseudo) { + ctxt->cur_stmt->kind.page_rule->pseudo = + cr_string_dup (a_pseudo) ; + if (!ctxt->cur_stmt->kind.page_rule->pseudo) { + goto error; + } + } + return; + + error: + if (ctxt->cur_stmt) { + cr_statement_destroy (ctxt->cur_stmt); + ctxt->cur_stmt = NULL; + } +} + +static void +end_page (CRDocHandler * a_this, + CRString * a_page, + CRString * a_pseudo_page) +{ + enum CRStatus status = CR_OK; + ParsingContext *ctxt = NULL; + ParsingContext **ctxtptr = NULL; + CRStatement *stmt = NULL; + + g_return_if_fail (a_this); + ctxtptr = &ctxt; + status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); + g_return_if_fail (status == CR_OK && ctxt); + g_return_if_fail (ctxt->cur_stmt + && ctxt->cur_stmt->type == AT_PAGE_RULE_STMT + && ctxt->stylesheet); + + stmt = cr_statement_append (ctxt->stylesheet->statements, + ctxt->cur_stmt); + + if (stmt) { + ctxt->stylesheet->statements = stmt; + stmt = NULL; + ctxt->cur_stmt = NULL; + } + + if (ctxt->cur_stmt) { + cr_statement_destroy (ctxt->cur_stmt); + ctxt->cur_stmt = NULL; + } + a_page = NULL; /*keep compiler happy */ + a_pseudo_page = NULL; /*keep compiler happy */ +} + +static void +start_media (CRDocHandler * a_this, + GList * a_media_list, + CRParsingLocation *a_location) +{ + enum CRStatus status = CR_OK; + ParsingContext *ctxt = NULL; + ParsingContext **ctxtptr = NULL; + GList *media_list = NULL; + + g_return_if_fail (a_this); + ctxtptr = &ctxt; + status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); + g_return_if_fail (status == CR_OK && ctxt); + + g_return_if_fail (ctxt + && ctxt->cur_stmt == NULL + && ctxt->cur_media_stmt == NULL + && ctxt->stylesheet); + if (a_media_list) { + /*duplicate the media_list */ + media_list = cr_utils_dup_glist_of_cr_string + (a_media_list); + } + ctxt->cur_media_stmt = + cr_statement_new_at_media_rule + (ctxt->stylesheet, NULL, media_list); + +} + +static void +end_media (CRDocHandler * a_this, GList * a_media_list) +{ + enum CRStatus status = CR_OK; + ParsingContext *ctxt = NULL; + ParsingContext **ctxtptr = NULL; + CRStatement *stmts = NULL; + + g_return_if_fail (a_this); + ctxtptr = &ctxt; + status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); + g_return_if_fail (status == CR_OK && ctxt); + g_return_if_fail (ctxt + && ctxt->cur_media_stmt + && ctxt->cur_media_stmt->type == AT_MEDIA_RULE_STMT + && ctxt->stylesheet); + + stmts = cr_statement_append (ctxt->stylesheet->statements, + ctxt->cur_media_stmt); + if (!stmts) { + cr_statement_destroy (ctxt->cur_media_stmt); + ctxt->cur_media_stmt = NULL; + } + + ctxt->stylesheet->statements = stmts; + stmts = NULL; + + ctxt->cur_stmt = NULL ; + ctxt->cur_media_stmt = NULL ; + a_media_list = NULL; +} + +static void +import_style (CRDocHandler * a_this, + GList * a_media_list, + CRString * a_uri, + CRString * a_uri_default_ns, + CRParsingLocation *a_location) +{ + enum CRStatus status = CR_OK; + CRString *uri = NULL; + CRStatement *stmt = NULL, + *stmt2 = NULL; + ParsingContext *ctxt = NULL; + ParsingContext **ctxtptr = NULL; + GList *media_list = NULL ; + + g_return_if_fail (a_this); + ctxtptr = &ctxt; + status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); + g_return_if_fail (status == CR_OK && ctxt); + g_return_if_fail (ctxt->stylesheet); + + uri = cr_string_dup (a_uri) ; + if (a_media_list) + media_list = cr_utils_dup_glist_of_cr_string (a_media_list) ; + stmt = cr_statement_new_at_import_rule + (ctxt->stylesheet, uri, media_list, NULL); + if (!stmt) + goto error; + + if (ctxt->cur_stmt) { + stmt2 = cr_statement_append (ctxt->cur_stmt, stmt); + if (!stmt2) + goto error; + ctxt->cur_stmt = stmt2; + stmt2 = NULL; + stmt = NULL; + } else { + stmt2 = cr_statement_append (ctxt->stylesheet->statements, + stmt); + if (!stmt2) + goto error; + ctxt->stylesheet->statements = stmt2; + stmt2 = NULL; + stmt = NULL; + } + + return; + + error: + if (uri) { + cr_string_destroy (uri); + } + + if (stmt) { + cr_statement_destroy (stmt); + stmt = NULL; + } + a_uri_default_ns = NULL; /*keep compiler happy */ +} + +static void +start_selector (CRDocHandler * a_this, CRSelector * a_selector_list) +{ + enum CRStatus status = CR_OK ; + ParsingContext *ctxt = NULL; + ParsingContext **ctxtptr = NULL; + + g_return_if_fail (a_this); + ctxtptr = &ctxt; + status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); + g_return_if_fail (status == CR_OK && ctxt); + if (ctxt->cur_stmt) { + /*hmm, this should be NULL so free it */ + cr_statement_destroy (ctxt->cur_stmt); + ctxt->cur_stmt = NULL; + } + + ctxt->cur_stmt = cr_statement_new_ruleset + (ctxt->stylesheet, a_selector_list, NULL, NULL); +} + +static void +end_selector (CRDocHandler * a_this, CRSelector * a_selector_list) +{ + enum CRStatus status = CR_OK; + ParsingContext *ctxt = NULL; + ParsingContext **ctxtptr = NULL; + + g_return_if_fail (a_this); + ctxtptr = &ctxt; + status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); + g_return_if_fail (status == CR_OK && ctxt); + g_return_if_fail (ctxt->cur_stmt && ctxt->stylesheet); + + if (ctxt->cur_stmt) { + CRStatement *stmts = NULL; + + if (ctxt->cur_media_stmt) { + CRAtMediaRule *media_rule = NULL; + + media_rule = ctxt->cur_media_stmt->kind.media_rule; + + stmts = cr_statement_append + (media_rule->rulesets, ctxt->cur_stmt); + + if (!stmts) { + cr_utils_trace_info + ("Could not append a new statement"); + cr_statement_destroy (media_rule->rulesets); + ctxt->cur_media_stmt-> + kind.media_rule->rulesets = NULL; + return; + } + media_rule->rulesets = stmts; + ctxt->cur_stmt = NULL; + } else { + stmts = cr_statement_append + (ctxt->stylesheet->statements, + ctxt->cur_stmt); + if (!stmts) { + cr_utils_trace_info + ("Could not append a new statement"); + cr_statement_destroy (ctxt->cur_stmt); + ctxt->cur_stmt = NULL; + return; + } + ctxt->stylesheet->statements = stmts; + ctxt->cur_stmt = NULL; + } + + } + a_selector_list = NULL; /*keep compiler happy */ +} + +static void +property (CRDocHandler * a_this, + CRString * a_name, + CRTerm * a_expression, + gboolean a_important) +{ + enum CRStatus status = CR_OK; + ParsingContext *ctxt = NULL; + ParsingContext **ctxtptr = NULL; + CRDeclaration *decl = NULL, + *decl2 = NULL; + CRString *str = NULL; + + g_return_if_fail (a_this); + ctxtptr = &ctxt; + status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); + g_return_if_fail (status == CR_OK && ctxt); + + /* + *make sure a current ruleset statement has been allocated + *already. + */ + g_return_if_fail + (ctxt->cur_stmt + && + (ctxt->cur_stmt->type == RULESET_STMT + || ctxt->cur_stmt->type == AT_FONT_FACE_RULE_STMT + || ctxt->cur_stmt->type == AT_PAGE_RULE_STMT)); + + if (a_name) { + str = cr_string_dup (a_name); + g_return_if_fail (str); + } + + /*instanciates a new declaration */ + decl = cr_declaration_new (ctxt->cur_stmt, str, a_expression); + g_return_if_fail (decl); + str = NULL; + decl->important = a_important; + /* + *add the new declaration to the current statement + *being build. + */ + switch (ctxt->cur_stmt->type) { + case RULESET_STMT: + decl2 = cr_declaration_append + (ctxt->cur_stmt->kind.ruleset->decl_list, decl); + if (!decl2) { + cr_declaration_destroy (decl); + cr_utils_trace_info + ("Could not append decl to ruleset"); + goto error; + } + ctxt->cur_stmt->kind.ruleset->decl_list = decl2; + decl = NULL; + decl2 = NULL; + break; + + case AT_FONT_FACE_RULE_STMT: + decl2 = cr_declaration_append + (ctxt->cur_stmt->kind.font_face_rule->decl_list, + decl); + if (!decl2) { + cr_declaration_destroy (decl); + cr_utils_trace_info + ("Could not append decl to ruleset"); + goto error; + } + ctxt->cur_stmt->kind.font_face_rule->decl_list = decl2; + decl = NULL; + decl2 = NULL; + break; + case AT_PAGE_RULE_STMT: + decl2 = cr_declaration_append + (ctxt->cur_stmt->kind.page_rule->decl_list, decl); + if (!decl2) { + cr_declaration_destroy (decl); + cr_utils_trace_info + ("Could not append decl to ruleset"); + goto error; + } + ctxt->cur_stmt->kind.page_rule->decl_list = decl2; + decl = NULL; + decl2 = NULL; + break; + + default: + goto error; + break; + } + + return; + + error: + if (str) { + g_free (str); + str = NULL; + } + + if (decl) { + cr_declaration_destroy (decl); + decl = NULL; + } +} + +static void +error (CRDocHandler * a_this) +{ + enum CRStatus status = CR_OK; + ParsingContext *ctxt = NULL; + ParsingContext **ctxtptr = NULL; + + g_return_if_fail (a_this); + ctxtptr = &ctxt; + status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); + g_return_if_fail (status == CR_OK && ctxt); + + if (ctxt->cur_stmt) { + cr_statement_destroy (ctxt->cur_stmt); + ctxt->cur_stmt = NULL; + } +} + +static void +unrecoverable_error (CRDocHandler * a_this) +{ + enum CRStatus status = CR_OK; + ParsingContext *ctxt = NULL; + ParsingContext **ctxtptr = NULL; + + ctxtptr = &ctxt; + status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); + g_return_if_fail (status == CR_OK); + + if (ctxt) { + if (ctxt->stylesheet) { + status = cr_doc_handler_set_result + (a_this, ctxt->stylesheet); + g_return_if_fail (status == CR_OK); + } + g_free (ctxt); + cr_doc_handler_set_ctxt (a_this, NULL); + } +} + +/******************************************** + *Public methods + ********************************************/ + +/** + * cr_om_parser_new: + *@a_input: the input stream. + * + *Constructor of the CROMParser. + *Returns the newly built instance of #CROMParser. + */ +CROMParser * +cr_om_parser_new (CRInput * a_input) +{ + CROMParser *result = NULL; + enum CRStatus status = CR_OK; + + result = g_try_malloc (sizeof (CROMParser)); + + if (!result) { + cr_utils_trace_info ("Out of memory"); + return NULL; + } + + memset (result, 0, sizeof (CROMParser)); + PRIVATE (result) = g_try_malloc (sizeof (CROMParserPriv)); + + if (!PRIVATE (result)) { + cr_utils_trace_info ("Out of memory"); + goto error; + } + + memset (PRIVATE (result), 0, sizeof (CROMParserPriv)); + + PRIVATE (result)->parser = cr_parser_new_from_input (a_input); + + if (!PRIVATE (result)->parser) { + cr_utils_trace_info ("parsing instanciation failed"); + goto error; + } + + status = cr_om_parser_init_default_sac_handler (result); + + if (status != CR_OK) { + goto error; + } + + return result; + + error: + + if (result) { + cr_om_parser_destroy (result); + } + + return NULL; +} + +/** + * cr_om_parser_parse_buf: + *@a_this: the current instance of #CROMParser. + *@a_buf: the in memory buffer to parse. + *@a_len: the length of the in memory buffer in number of bytes. + *@a_enc: the encoding of the in memory buffer. + *@a_result: out parameter the resulting style sheet + * + *Parses the content of an in memory buffer. + * + *Returns CR_OK upon successfull completion, an error code otherwise. + */ +enum CRStatus +cr_om_parser_parse_buf (CROMParser * a_this, + const guchar * a_buf, + gulong a_len, + enum CREncoding a_enc, CRStyleSheet ** a_result) +{ + + enum CRStatus status = CR_OK; + + g_return_val_if_fail (a_this && a_result, CR_BAD_PARAM_ERROR); + + if (!PRIVATE (a_this)->parser) { + PRIVATE (a_this)->parser = cr_parser_new (NULL); + } + + status = cr_parser_parse_buf (PRIVATE (a_this)->parser, + a_buf, a_len, a_enc); + + if (status == CR_OK) { + CRStyleSheet *result = NULL; + CRStyleSheet **resultptr = NULL; + CRDocHandler *sac_handler = NULL; + + cr_parser_get_sac_handler (PRIVATE (a_this)->parser, + &sac_handler); + g_return_val_if_fail (sac_handler, CR_ERROR); + resultptr = &result; + status = cr_doc_handler_get_result (sac_handler, + (gpointer *) resultptr); + g_return_val_if_fail (status == CR_OK, status); + + if (result) + *a_result = result; + } + + return status; +} + +/** + * cr_om_parser_simply_parse_buf: + *@a_buf: the css2 in memory buffer. + *@a_len: the length of the in memory buffer. + *@a_enc: the encoding of the in memory buffer. + *@a_result: out parameter. The resulting css2 style sheet. + * + *The simpler way to parse an in memory css2 buffer. + * + *Returns CR_OK upon successfull completion, an error code otherwise. + */ +enum CRStatus +cr_om_parser_simply_parse_buf (const guchar * a_buf, + gulong a_len, + enum CREncoding a_enc, + CRStyleSheet ** a_result) +{ + CROMParser *parser = NULL; + enum CRStatus status = CR_OK; + + parser = cr_om_parser_new (NULL); + if (!parser) { + cr_utils_trace_info ("Could not create om parser"); + cr_utils_trace_info ("System possibly out of memory"); + return CR_ERROR; + } + + status = cr_om_parser_parse_buf (parser, a_buf, a_len, + a_enc, a_result); + + if (parser) { + cr_om_parser_destroy (parser); + parser = NULL; + } + + return status; +} + +/** + * cr_om_parser_parse_file: + *@a_this: the current instance of the cssom parser. + *@a_file_uri: the uri of the file. + *(only local file paths are suppported so far) + *@a_enc: the encoding of the file. + *@a_result: out parameter. A pointer + *the build css object model. + * + *Parses a css2 stylesheet contained + *in a file. + * + * Returns CR_OK upon succesful completion, an error code otherwise. + */ +enum CRStatus +cr_om_parser_parse_file (CROMParser * a_this, + const guchar * a_file_uri, + enum CREncoding a_enc, CRStyleSheet ** a_result) +{ + enum CRStatus status = CR_OK; + + g_return_val_if_fail (a_this && a_file_uri && a_result, + CR_BAD_PARAM_ERROR); + + if (!PRIVATE (a_this)->parser) { + PRIVATE (a_this)->parser = cr_parser_new_from_file + (a_file_uri, a_enc); + } + + status = cr_parser_parse_file (PRIVATE (a_this)->parser, + a_file_uri, a_enc); + + if (status == CR_OK) { + CRStyleSheet *result = NULL; + CRStyleSheet **resultptr = NULL; + CRDocHandler *sac_handler = NULL; + + cr_parser_get_sac_handler (PRIVATE (a_this)->parser, + &sac_handler); + g_return_val_if_fail (sac_handler, CR_ERROR); + resultptr = &result; + status = cr_doc_handler_get_result + (sac_handler, (gpointer *) resultptr); + g_return_val_if_fail (status == CR_OK, status); + if (result) + *a_result = result; + } + + return status; +} + +/** + * cr_om_parser_simply_parse_file: + *@a_file_path: the css2 local file path. + *@a_enc: the file encoding. + *@a_result: out parameter. The returned css stylesheet. + *Must be freed by the caller using cr_stylesheet_destroy. + * + *The simpler method to parse a css2 file. + * + *Returns CR_OK upon successfull completion, an error code otherwise. + *Note that this method uses cr_om_parser_parse_file() so both methods + *have the same return values. + */ +enum CRStatus +cr_om_parser_simply_parse_file (const guchar * a_file_path, + enum CREncoding a_enc, + CRStyleSheet ** a_result) +{ + CROMParser *parser = NULL; + enum CRStatus status = CR_OK; + + parser = cr_om_parser_new (NULL); + if (!parser) { + cr_utils_trace_info ("Could not allocate om parser"); + cr_utils_trace_info ("System may be out of memory"); + return CR_ERROR; + } + + status = cr_om_parser_parse_file (parser, a_file_path, + a_enc, a_result); + if (parser) { + cr_om_parser_destroy (parser); + parser = NULL; + } + + return status; +} + +/** + * cr_om_parser_parse_paths_to_cascade: + *@a_this: the current instance of #CROMParser + *@a_author_path: the path to the author stylesheet + *@a_user_path: the path to the user stylesheet + *@a_ua_path: the path to the User Agent stylesheet + *@a_encoding: the encoding of the sheets. + *@a_result: out parameter. The resulting cascade if the parsing + *was okay + * + *Parses three sheets located by their paths and build a cascade + * + *Returns CR_OK upon successful completion, an error code otherwise + */ +enum CRStatus +cr_om_parser_parse_paths_to_cascade (CROMParser * a_this, + const guchar * a_author_path, + const guchar * a_user_path, + const guchar * a_ua_path, + enum CREncoding a_encoding, + CRCascade ** a_result) +{ + enum CRStatus status = CR_OK; + + /*0->author sheet, 1->user sheet, 2->UA sheet */ + CRStyleSheet *sheets[3]; + guchar *paths[3]; + CRCascade *result = NULL; + gint i = 0; + + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); + + memset (sheets, 0, sizeof (CRStyleSheet*) * 3); + paths[0] = (guchar *) a_author_path; + paths[1] = (guchar *) a_user_path; + paths[2] = (guchar *) a_ua_path; + + for (i = 0; i < 3; i++) { + status = cr_om_parser_parse_file (a_this, paths[i], + a_encoding, &sheets[i]); + if (status != CR_OK) { + if (sheets[i]) { + cr_stylesheet_unref (sheets[i]); + sheets[i] = NULL; + } + continue; + } + } + result = cr_cascade_new (sheets[0], sheets[1], sheets[2]); + if (!result) { + for (i = 0; i < 3; i++) { + cr_stylesheet_unref (sheets[i]); + sheets[i] = 0; + } + return CR_ERROR; + } + *a_result = result; + return CR_OK; +} + +/** + * cr_om_parser_simply_parse_paths_to_cascade: + *@a_author_path: the path to the author stylesheet + *@a_user_path: the path to the user stylesheet + *@a_ua_path: the path to the User Agent stylesheet + *@a_encoding: the encoding of the sheets. + *@a_result: out parameter. The resulting cascade if the parsing + *was okay + * + *Parses three sheets located by their paths and build a cascade + * + *Returns CR_OK upon successful completion, an error code otherwise + */ +enum CRStatus +cr_om_parser_simply_parse_paths_to_cascade (const guchar * a_author_path, + const guchar * a_user_path, + const guchar * a_ua_path, + enum CREncoding a_encoding, + CRCascade ** a_result) +{ + enum CRStatus status = CR_OK; + CROMParser *parser = NULL; + + parser = cr_om_parser_new (NULL); + if (!parser) { + cr_utils_trace_info ("could not allocated om parser"); + cr_utils_trace_info ("System may be out of memory"); + return CR_ERROR; + } + status = cr_om_parser_parse_paths_to_cascade (parser, + a_author_path, + a_user_path, + a_ua_path, + a_encoding, a_result); + if (parser) { + cr_om_parser_destroy (parser); + parser = NULL; + } + return status; +} + +/** + * cr_om_parser_destroy: + *@a_this: the current instance of #CROMParser. + * + *Destructor of the #CROMParser. + */ +void +cr_om_parser_destroy (CROMParser * a_this) +{ + g_return_if_fail (a_this && PRIVATE (a_this)); + + if (PRIVATE (a_this)->parser) { + cr_parser_destroy (PRIVATE (a_this)->parser); + PRIVATE (a_this)->parser = NULL; + } + + if (PRIVATE (a_this)) { + g_free (PRIVATE (a_this)); + PRIVATE (a_this) = NULL; + } + + if (a_this) { + g_free (a_this); + a_this = NULL; + } +} diff --git a/gettext-tools/gnulib-lib/libcroco/cr-om-parser.h b/gettext-tools/gnulib-lib/libcroco/cr-om-parser.h new file mode 100644 index 0000000..a8560c0 --- /dev/null +++ b/gettext-tools/gnulib-lib/libcroco/cr-om-parser.h @@ -0,0 +1,98 @@ +/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */ + +/* + * This file is part of The Croco Library + * + * Copyright (C) 2002-2003 Dodji Seketeli + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the + * GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + +/* + *$Id: cr-om-parser.h,v 1.9 2004/01/29 22:05:14 dodji Exp $ + */ + +#ifndef __CR_OM_PARSER_H__ +#define __CR_OM_PARSER_H__ + +#include "cr-parser.h" +#include "cr-cascade.h" + + +/** + *@file + *The definition of the CSS Object Model Parser. + *This parser uses (and sits) the SAC api of libcroco defined + *in cr-parser.h and cr-doc-handler.h + */ + +G_BEGIN_DECLS + +typedef struct _CROMParser CROMParser ; +typedef struct _CROMParserPriv CROMParserPriv ; + +/** + *The Object model parser. + *Can parse a css file and build a css object model. + *This parser uses an instance of #CRParser and defines + *a set of SAC callbacks to build the Object Model. + */ +struct _CROMParser +{ + CROMParserPriv *priv ; +} ; + +CROMParser * cr_om_parser_new (CRInput *a_input) ; + + +enum CRStatus cr_om_parser_simply_parse_file (const guchar *a_file_path, + enum CREncoding a_enc, + CRStyleSheet **a_result) ; + +enum CRStatus cr_om_parser_parse_file (CROMParser *a_this, + const guchar *a_file_uri, + enum CREncoding a_enc, + CRStyleSheet **a_result) ; + +enum CRStatus cr_om_parser_simply_parse_buf (const guchar *a_buf, + gulong a_len, + enum CREncoding a_enc, + CRStyleSheet **a_result) ; + +enum CRStatus cr_om_parser_parse_buf (CROMParser *a_this, + const guchar *a_buf, + gulong a_len, + enum CREncoding a_enc, + CRStyleSheet **a_result) ; + +enum CRStatus cr_om_parser_parse_paths_to_cascade (CROMParser *a_this, + const guchar *a_author_path, + const guchar *a_user_path, + const guchar *a_ua_path, + enum CREncoding a_encoding, + CRCascade ** a_result) ; + +enum CRStatus cr_om_parser_simply_parse_paths_to_cascade (const guchar *a_author_path, + const guchar *a_user_path, + const guchar *a_ua_path, + enum CREncoding a_encoding, + CRCascade ** a_result) ; + +void cr_om_parser_destroy (CROMParser *a_this) ; + +G_END_DECLS + +#endif /*__CR_OM_PARSER_H__*/ diff --git a/gettext-tools/gnulib-lib/libcroco/cr-parser.c b/gettext-tools/gnulib-lib/libcroco/cr-parser.c new file mode 100644 index 0000000..d2adfbf --- /dev/null +++ b/gettext-tools/gnulib-lib/libcroco/cr-parser.c @@ -0,0 +1,4524 @@ +/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */ + +/* + * This file is part of The Croco Library + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of the + * GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + * Author: Dodji Seketeli + * See COPYRIGHTS file for copyrights information. + */ + +/** + *@CRParser: + * + *The definition of the #CRParser class. + */ + +#include +#include "string.h" +#include "cr-parser.h" +#include "cr-num.h" +#include "cr-term.h" +#include "cr-simple-sel.h" +#include "cr-attr-sel.h" + +/* + *Random notes: + *CSS core syntax vs CSS level 2 syntax + *===================================== + * + *One must keep in mind + *that css UA must comply with two syntaxes. + * + *1/the specific syntax that defines the css language + *for a given level of specificatin (e.g css2 syntax + *defined in appendix D.1 of the css2 spec) + * + *2/the core (general) syntax that is there to allow + *UAs to parse style sheets written in levels of CSS that + *didn't exist at the time the UAs were created. + * + *the name of parsing functions (or methods) contained in this file + *follows the following scheme: cr_parser_parse_ (...) ; + *where is the name + *of a production of the css2 language. + *When a given production is + *defined by the css2 level grammar *and* by the + *css core syntax, there will be two functions to parse that production: + *one will parse the production defined by the css2 level grammar and the + *other will parse the production defined by the css core grammar. + *The css2 level grammar related parsing function will be called: + *cr_parser_parse_ (...) ; + *Then css core grammar related parsing function will be called: + *cr_parser_parse__core (...) ; + * + *If a production is defined only by the css core grammar, then + *it will be named: + *cr_parser_parse__core (...) ; + */ + +typedef struct _CRParserError CRParserError; + +/** + *An abstraction of an error reported by by the + *parsing routines. + */ +struct _CRParserError { + guchar *msg; + enum CRStatus status; + glong line; + glong column; + glong byte_num; +}; + +enum CRParserState { + READY_STATE = 0, + TRY_PARSE_CHARSET_STATE, + CHARSET_PARSED_STATE, + TRY_PARSE_IMPORT_STATE, + IMPORT_PARSED_STATE, + TRY_PARSE_RULESET_STATE, + RULESET_PARSED_STATE, + TRY_PARSE_MEDIA_STATE, + MEDIA_PARSED_STATE, + TRY_PARSE_PAGE_STATE, + PAGE_PARSED_STATE, + TRY_PARSE_FONT_FACE_STATE, + FONT_FACE_PARSED_STATE +} ; + +/** + *The private attributes of + *#CRParser. + */ +struct _CRParserPriv { + /** + *The tokenizer + */ + CRTknzr *tknzr; + + /** + *The sac handlers to call + *to notify the parsing of + *the css2 constructions. + */ + CRDocHandler *sac_handler; + + /** + *A stack of errors reported + *by the parsing routines. + *Contains instance of #CRParserError. + *This pointer is the top of the stack. + */ + GList *err_stack; + + enum CRParserState state; + gboolean resolve_import; + gboolean is_case_sensitive; + gboolean use_core_grammar; +}; + +#define PRIVATE(obj) ((obj)->priv) + +#define CHARS_TAB_SIZE 12 + +/** + * IS_NUM: + *@a_char: the char to test. + *return TRUE if the character is a number ([0-9]), FALSE otherwise + */ +#define IS_NUM(a_char) (((a_char) >= '0' && (a_char) <= '9')?TRUE:FALSE) + +/** + *Checks if 'status' equals CR_OK. If not, goto the 'error' label. + * + *@param status the status (of type enum CRStatus) to test. + *@param is_exception if set to FALSE, the final status returned + *by the current function will be CR_PARSING_ERROR. If set to TRUE, the + *current status will be the current value of the 'status' variable. + * + */ +#define CHECK_PARSING_STATUS(status, is_exception) \ +if ((status) != CR_OK) \ +{ \ + if (is_exception == FALSE) \ + { \ + status = CR_PARSING_ERROR ; \ + } \ + goto error ; \ +} + +/** + * CHECK_PARSING_STATUS_ERR: + *@a_this: the current instance of #CRParser . + *@a_status: the status to check. Is of type enum #CRStatus. + *@a_is_exception: in case of error, if is TRUE, the status + *is set to CR_PARSING_ERROR before goto error. If is false, the + *real low level status is kept and will be returned by the + *upper level function that called this macro. Usally,this must + *be set to FALSE. + * + *same as CHECK_PARSING_STATUS() but this one pushes an error + *on the parser error stack when an error arises. + * + */ +#define CHECK_PARSING_STATUS_ERR(a_this, a_status, a_is_exception,\ + a_err_msg, a_err_status) \ +if ((a_status) != CR_OK) \ +{ \ + if (a_is_exception == FALSE) a_status = CR_PARSING_ERROR ; \ + cr_parser_push_error (a_this, a_err_msg, a_err_status) ; \ + goto error ; \ +} + +/** + *Peeks the next char from the input stream of the current parser + *by invoking cr_tknzr_input_peek_char(). + *invokes CHECK_PARSING_STATUS on the status returned by + *cr_tknzr_peek_char(). + * + *@param a_this the current instance of #CRParser. + *@param a_to_char a pointer to the char where to store the + *char peeked. + */ +#define PEEK_NEXT_CHAR(a_this, a_to_char) \ +{\ +enum CRStatus status ; \ +status = cr_tknzr_peek_char (PRIVATE (a_this)->tknzr, a_to_char) ; \ +CHECK_PARSING_STATUS (status, TRUE) \ +} + +/** + *Reads the next char from the input stream of the current parser. + *In case of error, jumps to the "error:" label located in the + *function where this macro is called. + *@param a_this the curent instance of #CRParser + *@param to_char a pointer to the guint32 char where to store + *the character read. + */ +#define READ_NEXT_CHAR(a_this, a_to_char) \ +status = cr_tknzr_read_char (PRIVATE (a_this)->tknzr, a_to_char) ; \ +CHECK_PARSING_STATUS (status, TRUE) + +/** + *Gets information about the current position in + *the input of the parser. + *In case of failure, this macro returns from the + *calling function and + *returns a status code of type enum #CRStatus. + *@param a_this the current instance of #CRParser. + *@param a_pos out parameter. A pointer to the position + *inside the current parser input. Must + */ +#define RECORD_INITIAL_POS(a_this, a_pos) \ +status = cr_tknzr_get_cur_pos (PRIVATE \ +(a_this)->tknzr, a_pos) ; \ +g_return_val_if_fail (status == CR_OK, status) + +/** + *Gets the address of the current byte inside the + *parser input. + *@param parser the current instance of #CRParser. + *@param addr out parameter a pointer (guchar*) + *to where the address must be put. + */ +#define RECORD_CUR_BYTE_ADDR(a_this, a_addr) \ +status = cr_tknzr_get_cur_byte_addr \ + (PRIVATE (a_this)->tknzr, a_addr) ; \ +CHECK_PARSING_STATUS (status, TRUE) + +/** + *Peeks a byte from the topmost parser input at + *a given offset from the current position. + *If it fails, goto the "error:" label. + * + *@param a_parser the current instance of #CRParser. + *@param a_offset the offset of the byte to peek, the + *current byte having the offset '0'. + *@param a_byte_ptr out parameter a pointer (guchar*) to + *where the peeked char is to be stored. + */ +#define PEEK_BYTE(a_parser, a_offset, a_byte_ptr) \ +status = cr_tknzr_peek_byte (PRIVATE (a_this)->tknzr, \ + a_offset, \ + a_byte_ptr) ; \ +CHECK_PARSING_STATUS (status, TRUE) ; + +#define BYTE(a_parser, a_offset, a_eof) \ +cr_tknzr_peek_byte2 (PRIVATE (a_this)->tknzr, a_offset, a_eof) + +/** + *Reads a byte from the topmost parser input + *steam. + *If it fails, goto the "error" label. + *@param a_this the current instance of #CRParser. + *@param a_byte_ptr the guchar * where to put the read char. + */ +#define READ_NEXT_BYTE(a_this, a_byte_ptr) \ +status = cr_tknzr_read_byte (PRIVATE (a_this)->tknzr, a_byte_ptr) ; \ +CHECK_PARSING_STATUS (status, TRUE) ; + +/** + *Skips a given number of byte in the topmost + *parser input. Don't update line and column number. + *In case of error, jumps to the "error:" label + *of the surrounding function. + *@param a_parser the current instance of #CRParser. + *@param a_nb_bytes the number of bytes to skip. + */ +#define SKIP_BYTES(a_this, a_nb_bytes) \ +status = cr_tknzr_seek_index (PRIVATE (a_this)->tknzr, \ + CR_SEEK_CUR, a_nb_bytes) ; \ +CHECK_PARSING_STATUS (status, TRUE) ; + +/** + *Skip utf8 encoded characters. + *Updates line and column numbers. + *@param a_parser the current instance of #CRParser. + *@param a_nb_chars the number of chars to skip. Must be of + *type glong. + */ +#define SKIP_CHARS(a_parser, a_nb_chars) \ +{ \ +glong nb_chars = a_nb_chars ; \ +status = cr_tknzr_consume_chars \ + (PRIVATE (a_parser)->tknzr,0, &nb_chars) ; \ +CHECK_PARSING_STATUS (status, TRUE) ; \ +} + +/** + *Tests the condition and if it is false, sets + *status to "CR_PARSING_ERROR" and goto the 'error' + *label. + *@param condition the condition to test. + */ +#define ENSURE_PARSING_COND(condition) \ +if (! (condition)) {status = CR_PARSING_ERROR; goto error ;} + +#define ENSURE_PARSING_COND_ERR(a_this, a_condition, \ + a_err_msg, a_err_status) \ +if (! (a_condition)) \ +{ \ + status = CR_PARSING_ERROR; \ + cr_parser_push_error (a_this, a_err_msg, a_err_status) ; \ + goto error ; \ +} + +#define GET_NEXT_TOKEN(a_this, a_token_ptr) \ +status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, \ + a_token_ptr) ; \ +ENSURE_PARSING_COND (status == CR_OK) ; + +#ifdef WITH_UNICODE_ESCAPE_AND_RANGE +static enum CRStatus cr_parser_parse_unicode_escape (CRParser * a_this, + guint32 * a_unicode); +static enum CRStatus cr_parser_parse_escape (CRParser * a_this, + guint32 * a_esc_code); + +static enum CRStatus cr_parser_parse_unicode_range (CRParser * a_this, + CRString ** a_inf, + CRString ** a_sup); +#endif + +static enum CRStatus cr_parser_parse_stylesheet_core (CRParser * a_this); + +static enum CRStatus cr_parser_parse_atrule_core (CRParser * a_this); + +static enum CRStatus cr_parser_parse_ruleset_core (CRParser * a_this); + +static enum CRStatus cr_parser_parse_selector_core (CRParser * a_this); + +static enum CRStatus cr_parser_parse_declaration_core (CRParser * a_this); + +static enum CRStatus cr_parser_parse_any_core (CRParser * a_this); + +static enum CRStatus cr_parser_parse_block_core (CRParser * a_this); + +static enum CRStatus cr_parser_parse_value_core (CRParser * a_this); + +static enum CRStatus cr_parser_parse_string (CRParser * a_this, + CRString ** a_str); + +static enum CRStatus cr_parser_parse_ident (CRParser * a_this, + CRString ** a_str); + +static enum CRStatus cr_parser_parse_uri (CRParser * a_this, + CRString ** a_str); + +static enum CRStatus cr_parser_parse_function (CRParser * a_this, + CRString ** a_func_name, + CRTerm ** a_expr); +static enum CRStatus cr_parser_parse_property (CRParser * a_this, + CRString ** a_property); + +static enum CRStatus cr_parser_parse_attribute_selector (CRParser * a_this, + CRAttrSel ** a_sel); + +static enum CRStatus cr_parser_parse_simple_selector (CRParser * a_this, + CRSimpleSel ** a_sel); + +static enum CRStatus cr_parser_parse_simple_sels (CRParser * a_this, + CRSimpleSel ** a_sel); + +static CRParserError *cr_parser_error_new (const guchar * a_msg, + enum CRStatus); + +static void cr_parser_error_set_msg (CRParserError * a_this, + const guchar * a_msg); + +static void cr_parser_error_dump (CRParserError * a_this); + +static void cr_parser_error_set_status (CRParserError * a_this, + enum CRStatus a_status); + +static void cr_parser_error_set_pos (CRParserError * a_this, + glong a_line, + glong a_column, glong a_byte_num); +static void + cr_parser_error_destroy (CRParserError * a_this); + +static enum CRStatus cr_parser_push_error (CRParser * a_this, + const guchar * a_msg, + enum CRStatus a_status); + +static enum CRStatus cr_parser_dump_err_stack (CRParser * a_this, + gboolean a_clear_errs); +static enum CRStatus + cr_parser_clear_errors (CRParser * a_this); + +/***************************** + *error managemet methods + *****************************/ + +/** + *Constructor of #CRParserError class. + *@param a_msg the brute error message. + *@param a_status the error status. + *@return the newly built instance of #CRParserError. + */ +static CRParserError * +cr_parser_error_new (const guchar * a_msg, enum CRStatus a_status) +{ + CRParserError *result = NULL; + + result = g_try_malloc (sizeof (CRParserError)); + + if (result == NULL) { + cr_utils_trace_info ("Out of memory"); + return NULL; + } + + memset (result, 0, sizeof (CRParserError)); + + cr_parser_error_set_msg (result, a_msg); + cr_parser_error_set_status (result, a_status); + + return result; +} + +/** + *Sets the message associated to this instance of #CRError. + *@param a_this the current instance of #CRParserError. + *@param a_msg the new message. + */ +static void +cr_parser_error_set_msg (CRParserError * a_this, const guchar * a_msg) +{ + g_return_if_fail (a_this); + + if (a_this->msg) { + g_free (a_this->msg); + } + + a_this->msg = g_strdup (a_msg); +} + +/** + *Sets the error status. + *@param a_this the current instance of #CRParserError. + *@param a_status the new error status. + * + */ +static void +cr_parser_error_set_status (CRParserError * a_this, enum CRStatus a_status) +{ + g_return_if_fail (a_this); + + a_this->status = a_status; +} + +/** + *Sets the position of the parser error. + *@param a_this the current instance of #CRParserError. + *@param a_line the line number. + *@param a_column the column number. + *@param a_byte_num the byte number. + */ +static void +cr_parser_error_set_pos (CRParserError * a_this, + glong a_line, glong a_column, glong a_byte_num) +{ + g_return_if_fail (a_this); + + a_this->line = a_line; + a_this->column = a_column; + a_this->byte_num = a_byte_num; +} + +static void +cr_parser_error_dump (CRParserError * a_this) +{ + g_return_if_fail (a_this); + + g_printerr ("parsing error: %ld:%ld:", a_this->line, a_this->column); + + g_printerr ("%s\n", a_this->msg); +} + +/** + *The destructor of #CRParserError. + *@param a_this the current instance of #CRParserError. + */ +static void +cr_parser_error_destroy (CRParserError * a_this) +{ + g_return_if_fail (a_this); + + if (a_this->msg) { + g_free (a_this->msg); + a_this->msg = NULL; + } + + g_free (a_this); +} + +/** + *Pushes an error on the parser error stack. + *@param a_this the current instance of #CRParser. + *@param a_msg the error message. + *@param a_status the error status. + *@return CR_OK upon successfull completion, an error code otherwise. + */ +static enum CRStatus +cr_parser_push_error (CRParser * a_this, + const guchar * a_msg, enum CRStatus a_status) +{ + enum CRStatus status = CR_OK; + + CRParserError *error = NULL; + CRInputPos pos; + + g_return_val_if_fail (a_this && PRIVATE (a_this) + && a_msg, CR_BAD_PARAM_ERROR); + + error = cr_parser_error_new (a_msg, a_status); + + g_return_val_if_fail (error, CR_ERROR); + + RECORD_INITIAL_POS (a_this, &pos); + + cr_parser_error_set_pos + (error, pos.line, pos.col, pos.next_byte_index - 1); + + PRIVATE (a_this)->err_stack = + g_list_prepend (PRIVATE (a_this)->err_stack, error); + + if (PRIVATE (a_this)->err_stack == NULL) + goto error; + + return CR_OK; + + error: + + if (error) { + cr_parser_error_destroy (error); + error = NULL; + } + + return status; +} + +/** + *Dumps the error stack on stdout. + *@param a_this the current instance of #CRParser. + *@param a_clear_errs whether to clear the error stack + *after the dump or not. + *@return CR_OK upon successfull completion, an error code + *otherwise. + */ +static enum CRStatus +cr_parser_dump_err_stack (CRParser * a_this, gboolean a_clear_errs) +{ + GList *cur = NULL; + + g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR); + + if (PRIVATE (a_this)->err_stack == NULL) + return CR_OK; + + for (cur = PRIVATE (a_this)->err_stack; cur; cur = cur->next) { + cr_parser_error_dump ((CRParserError *) cur->data); + } + + if (a_clear_errs == TRUE) { + cr_parser_clear_errors (a_this); + } + + return CR_OK; +} + +/** + *Clears all the errors contained in the parser error stack. + *Frees all the errors, and the stack that contains'em. + *@param a_this the current instance of #CRParser. + */ +static enum CRStatus +cr_parser_clear_errors (CRParser * a_this) +{ + GList *cur = NULL; + + g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR); + + for (cur = PRIVATE (a_this)->err_stack; cur; cur = cur->next) { + if (cur->data) { + cr_parser_error_destroy ((CRParserError *) + cur->data); + } + } + + if (PRIVATE (a_this)->err_stack) { + g_list_free (PRIVATE (a_this)->err_stack); + PRIVATE (a_this)->err_stack = NULL; + } + + return CR_OK; +} + +/** + * cr_parser_try_to_skip_spaces_and_comments: + *@a_this: the current instance of #CRParser. + * + *Same as cr_parser_try_to_skip_spaces() but this one skips + *spaces and comments. + * + *Returns CR_OK upon successfull completion, an error code otherwise. + */ +enum CRStatus +cr_parser_try_to_skip_spaces_and_comments (CRParser * a_this) +{ + enum CRStatus status = CR_ERROR; + CRToken *token = NULL; + + g_return_val_if_fail (a_this && PRIVATE (a_this) + && PRIVATE (a_this)->tknzr, CR_BAD_PARAM_ERROR); + do { + if (token) { + cr_token_destroy (token); + token = NULL; + } + + status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, + &token); + if (status != CR_OK) + goto error; + } + while ((token != NULL) + && (token->type == COMMENT_TK || token->type == S_TK)); + + cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, token); + + return status; + + error: + + if (token) { + cr_token_destroy (token); + token = NULL; + } + + return status; +} + +/*************************************** + *End of Parser input handling routines + ***************************************/ + + +/************************************* + *Non trivial terminal productions + *parsing routines + *************************************/ + +/** + *Parses a css stylesheet following the core css grammar. + *This is mainly done for test purposes. + *During the parsing, no callback is called. This is just + *to validate that the stylesheet is well formed according to the + *css core syntax. + *stylesheet : [ CDO | CDC | S | statement ]*; + *@param a_this the current instance of #CRParser. + *@return CR_OK upon successful completion, an error code otherwise. + */ +static enum CRStatus +cr_parser_parse_stylesheet_core (CRParser * a_this) +{ + CRToken *token = NULL; + CRInputPos init_pos; + enum CRStatus status = CR_ERROR; + + g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR); + + RECORD_INITIAL_POS (a_this, &init_pos); + + continue_parsing: + + if (token) { + cr_token_destroy (token); + token = NULL; + } + + cr_parser_try_to_skip_spaces_and_comments (a_this); + status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token); + if (status == CR_END_OF_INPUT_ERROR) { + status = CR_OK; + goto done; + } else if (status != CR_OK) { + goto error; + } + + switch (token->type) { + + case CDO_TK: + case CDC_TK: + goto continue_parsing; + break; + default: + status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, + token); + CHECK_PARSING_STATUS (status, TRUE); + token = NULL; + status = cr_parser_parse_statement_core (a_this); + cr_parser_clear_errors (a_this); + if (status == CR_OK) { + goto continue_parsing; + } else if (status == CR_END_OF_INPUT_ERROR) { + goto done; + } else { + goto error; + } + } + + done: + if (token) { + cr_token_destroy (token); + token = NULL; + } + + cr_parser_clear_errors (a_this); + return CR_OK; + + error: + cr_parser_push_error + (a_this, "could not recognize next production", CR_ERROR); + + cr_parser_dump_err_stack (a_this, TRUE); + + if (token) { + cr_token_destroy (token); + token = NULL; + } + + cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos); + + return status; +} + +/** + *Parses an at-rule as defined by the css core grammar + *in chapter 4.1 in the css2 spec. + *at-rule : ATKEYWORD S* any* [ block | ';' S* ]; + *@param a_this the current instance of #CRParser. + *@return CR_OK upon successfull completion, an error code + *otherwise. + */ +static enum CRStatus +cr_parser_parse_atrule_core (CRParser * a_this) +{ + CRToken *token = NULL; + CRInputPos init_pos; + enum CRStatus status = CR_ERROR; + + g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR); + + RECORD_INITIAL_POS (a_this, &init_pos); + + status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, + &token); + ENSURE_PARSING_COND (status == CR_OK + && token + && + (token->type == ATKEYWORD_TK + || token->type == IMPORT_SYM_TK + || token->type == PAGE_SYM_TK + || token->type == MEDIA_SYM_TK + || token->type == FONT_FACE_SYM_TK + || token->type == CHARSET_SYM_TK)); + + cr_token_destroy (token); + token = NULL; + + cr_parser_try_to_skip_spaces_and_comments (a_this); + + do { + status = cr_parser_parse_any_core (a_this); + } while (status == CR_OK); + + status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, + &token); + ENSURE_PARSING_COND (status == CR_OK && token); + + if (token->type == CBO_TK) { + cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, + token); + token = NULL; + status = cr_parser_parse_block_core (a_this); + CHECK_PARSING_STATUS (status, + FALSE); + goto done; + } else if (token->type == SEMICOLON_TK) { + goto done; + } else { + status = CR_PARSING_ERROR ; + goto error; + } + + done: + if (token) { + cr_token_destroy (token); + token = NULL; + } + return CR_OK; + + error: + if (token) { + cr_token_destroy (token); + token = NULL; + } + cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, + &init_pos); + return status; +} + +/** + *Parses a ruleset as defined by the css core grammar in chapter + *4.1 of the css2 spec. + *ruleset ::= selector? '{' S* declaration? [ ';' S* declaration? ]* '}' S*; + *@param a_this the current instance of #CRParser. + *@return CR_OK upon successfull completion, an error code otherwise. + */ +static enum CRStatus +cr_parser_parse_ruleset_core (CRParser * a_this) +{ + CRToken *token = NULL; + CRInputPos init_pos; + enum CRStatus status = CR_ERROR; + + g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR); + RECORD_INITIAL_POS (a_this, &init_pos); + + status = cr_parser_parse_selector_core (a_this); + + ENSURE_PARSING_COND (status == CR_OK + || status == CR_PARSING_ERROR + || status == CR_END_OF_INPUT_ERROR); + + status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token); + ENSURE_PARSING_COND (status == CR_OK && token + && token->type == CBO_TK); + cr_token_destroy (token); + token = NULL; + + cr_parser_try_to_skip_spaces_and_comments (a_this); + status = cr_parser_parse_declaration_core (a_this); + + parse_declaration_list: + if (token) { + cr_token_destroy (token); + token = NULL; + } + + status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token); + ENSURE_PARSING_COND (status == CR_OK && token); + if (token->type == CBC_TK) { + goto done; + } + + ENSURE_PARSING_COND (status == CR_OK + && token && token->type == SEMICOLON_TK); + + cr_token_destroy (token); + token = NULL; + cr_parser_try_to_skip_spaces_and_comments (a_this); + status = cr_parser_parse_declaration_core (a_this); + cr_parser_clear_errors (a_this); + ENSURE_PARSING_COND (status == CR_OK || status == CR_PARSING_ERROR); + status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token); + ENSURE_PARSING_COND (status == CR_OK && token); + if (token->type == CBC_TK) { + cr_token_destroy (token); + token = NULL; + cr_parser_try_to_skip_spaces_and_comments (a_this); + goto done; + } else { + status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, + token); + token = NULL; + goto parse_declaration_list; + } + + done: + if (token) { + cr_token_destroy (token); + token = NULL; + } + + if (status == CR_OK) { + return CR_OK; + } + + error: + if (token) { + cr_token_destroy (token); + token = NULL; + } + + cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos); + + return status; +} + +/** + *Parses a "selector" as specified by the css core + *grammar. + *selector : any+; + *@param a_this the current instance of #CRParser. + *@return CR_OK upon successfull completion, an error code + *otherwise. + */ +static enum CRStatus +cr_parser_parse_selector_core (CRParser * a_this) +{ + CRToken *token = NULL; + CRInputPos init_pos; + enum CRStatus status = CR_ERROR; + + g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR); + + RECORD_INITIAL_POS (a_this, &init_pos); + + status = cr_parser_parse_any_core (a_this); + CHECK_PARSING_STATUS (status, FALSE); + + do { + status = cr_parser_parse_any_core (a_this); + + } while (status == CR_OK); + + return CR_OK; + + error: + if (token) { + cr_token_destroy (token); + token = NULL; + } + + cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos); + + return status; +} + +/** + *Parses a "block" as defined in the css core grammar + *in chapter 4.1 of the css2 spec. + *block ::= '{' S* [ any | block | ATKEYWORD S* | ';' ]* '}' S*; + *@param a_this the current instance of #CRParser. + *FIXME: code this function. + */ +static enum CRStatus +cr_parser_parse_block_core (CRParser * a_this) +{ + CRToken *token = NULL; + CRInputPos init_pos; + enum CRStatus status = CR_ERROR; + + g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR); + + RECORD_INITIAL_POS (a_this, &init_pos); + + status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token); + ENSURE_PARSING_COND (status == CR_OK && token + && token->type == CBO_TK); + + parse_block_content: + + if (token) { + cr_token_destroy (token); + token = NULL; + } + + cr_parser_try_to_skip_spaces_and_comments (a_this); + + status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token); + ENSURE_PARSING_COND (status == CR_OK && token); + + if (token->type == CBC_TK) { + cr_parser_try_to_skip_spaces_and_comments (a_this); + goto done; + } else if (token->type == SEMICOLON_TK) { + goto parse_block_content; + } else if (token->type == ATKEYWORD_TK) { + cr_parser_try_to_skip_spaces_and_comments (a_this); + goto parse_block_content; + } else if (token->type == CBO_TK) { + cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, token); + token = NULL; + status = cr_parser_parse_block_core (a_this); + CHECK_PARSING_STATUS (status, FALSE); + goto parse_block_content; + } else { + cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, token); + token = NULL; + status = cr_parser_parse_any_core (a_this); + CHECK_PARSING_STATUS (status, FALSE); + goto parse_block_content; + } + + done: + if (token) { + cr_token_destroy (token); + token = NULL; + } + + if (status == CR_OK) + return CR_OK; + + error: + if (token) { + cr_token_destroy (token); + token = NULL; + } + + cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos); + + return status; +} + +static enum CRStatus +cr_parser_parse_declaration_core (CRParser * a_this) +{ + CRToken *token = NULL; + CRInputPos init_pos; + enum CRStatus status = CR_ERROR; + CRString *prop = NULL; + + g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR); + + RECORD_INITIAL_POS (a_this, &init_pos); + + status = cr_parser_parse_property (a_this, &prop); + CHECK_PARSING_STATUS (status, FALSE); + cr_parser_clear_errors (a_this); + ENSURE_PARSING_COND (status == CR_OK && prop); + cr_string_destroy (prop); + prop = NULL; + + status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token); + ENSURE_PARSING_COND (status == CR_OK + && token + && token->type == DELIM_TK + && token->u.unichar == ':'); + cr_token_destroy (token); + token = NULL; + cr_parser_try_to_skip_spaces_and_comments (a_this); + status = cr_parser_parse_value_core (a_this); + CHECK_PARSING_STATUS (status, FALSE); + + return CR_OK; + + error: + + if (prop) { + cr_string_destroy (prop); + prop = NULL; + } + + if (token) { + cr_token_destroy (token); + token = NULL; + } + + cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos); + + return status; +} + +/** + *Parses a "value" production as defined by the css core grammar + *in chapter 4.1. + *value ::= [ any | block | ATKEYWORD S* ]+; + *@param a_this the current instance of #CRParser. + *@return CR_OK upon successfull completion, an error code otherwise. + */ +static enum CRStatus +cr_parser_parse_value_core (CRParser * a_this) +{ + CRToken *token = NULL; + CRInputPos init_pos; + enum CRStatus status = CR_ERROR; + glong ref = 0; + + g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR); + RECORD_INITIAL_POS (a_this, &init_pos); + + continue_parsing: + + if (token) { + cr_token_destroy (token); + token = NULL; + } + + status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token); + ENSURE_PARSING_COND (status == CR_OK && token); + + switch (token->type) { + case CBO_TK: + status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, + token); + token = NULL; + status = cr_parser_parse_block_core (a_this); + CHECK_PARSING_STATUS (status, FALSE); + ref++; + goto continue_parsing; + + case ATKEYWORD_TK: + cr_parser_try_to_skip_spaces_and_comments (a_this); + ref++; + goto continue_parsing; + + default: + status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, + token); + token = NULL; + status = cr_parser_parse_any_core (a_this); + if (status == CR_OK) { + ref++; + goto continue_parsing; + } else if (status == CR_PARSING_ERROR) { + status = CR_OK; + goto done; + } else { + goto error; + } + } + + done: + if (token) { + cr_token_destroy (token); + token = NULL; + } + + if (status == CR_OK && ref) + return CR_OK; + error: + if (token) { + cr_token_destroy (token); + token = NULL; + } + + cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos); + + return status; +} + +/** + *Parses an "any" as defined by the css core grammar in the + *css2 spec in chapter 4.1. + *any ::= [ IDENT | NUMBER | PERCENTAGE | DIMENSION | STRING + * | DELIM | URI | HASH | UNICODE-RANGE | INCLUDES + * | FUNCTION | DASHMATCH | '(' any* ')' | '[' any* ']' ] S*; + * + *@param a_this the current instance of #CRParser. + *@return CR_OK upon successfull completion, an error code otherwise. + */ +static enum CRStatus +cr_parser_parse_any_core (CRParser * a_this) +{ + CRToken *token1 = NULL, + *token2 = NULL; + CRInputPos init_pos; + enum CRStatus status = CR_ERROR; + + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); + + RECORD_INITIAL_POS (a_this, &init_pos); + + status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token1); + + ENSURE_PARSING_COND (status == CR_OK && token1); + + switch (token1->type) { + case IDENT_TK: + case NUMBER_TK: + case RGB_TK: + case PERCENTAGE_TK: + case DIMEN_TK: + case EMS_TK: + case EXS_TK: + case LENGTH_TK: + case ANGLE_TK: + case FREQ_TK: + case TIME_TK: + case STRING_TK: + case DELIM_TK: + case URI_TK: + case HASH_TK: + case UNICODERANGE_TK: + case INCLUDES_TK: + case DASHMATCH_TK: + case S_TK: + case COMMENT_TK: + case IMPORTANT_SYM_TK: + status = CR_OK; + break; + case FUNCTION_TK: + /* + *this case isn't specified by the spec but it + *does happen. So we have to handle it. + *We must consider function with parameters. + *We consider parameter as being an "any*" production. + */ + do { + status = cr_parser_parse_any_core (a_this); + } while (status == CR_OK); + + ENSURE_PARSING_COND (status == CR_PARSING_ERROR); + status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, + &token2); + ENSURE_PARSING_COND (status == CR_OK + && token2 && token2->type == PC_TK); + break; + case PO_TK: + status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, + &token2); + ENSURE_PARSING_COND (status == CR_OK && token2); + + if (token2->type == PC_TK) { + cr_token_destroy (token2); + token2 = NULL; + goto done; + } else { + status = cr_tknzr_unget_token + (PRIVATE (a_this)->tknzr, token2); + token2 = NULL; + } + + do { + status = cr_parser_parse_any_core (a_this); + } while (status == CR_OK); + + ENSURE_PARSING_COND (status == CR_PARSING_ERROR); + + status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, + &token2); + ENSURE_PARSING_COND (status == CR_OK + && token2 && token2->type == PC_TK); + status = CR_OK; + break; + + case BO_TK: + status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, + &token2); + ENSURE_PARSING_COND (status == CR_OK && token2); + + if (token2->type == BC_TK) { + cr_token_destroy (token2); + token2 = NULL; + goto done; + } else { + status = cr_tknzr_unget_token + (PRIVATE (a_this)->tknzr, token2); + token2 = NULL; + } + + do { + status = cr_parser_parse_any_core (a_this); + } while (status == CR_OK); + + ENSURE_PARSING_COND (status == CR_PARSING_ERROR); + + status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, + &token2); + ENSURE_PARSING_COND (status == CR_OK + && token2 && token2->type == BC_TK); + status = CR_OK; + break; + default: + status = CR_PARSING_ERROR; + goto error; + } + + done: + if (token1) { + cr_token_destroy (token1); + token1 = NULL; + } + + if (token2) { + cr_token_destroy (token2); + token2 = NULL; + } + + return CR_OK; + + error: + + if (token1) { + cr_token_destroy (token1); + token1 = NULL; + } + + if (token2) { + cr_token_destroy (token2); + token2 = NULL; + } + + cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos); + return status; +} + +/** + *Parses an attribute selector as defined in the css2 spec in + *appendix D.1: + *attrib ::= '[' S* IDENT S* [ [ '=' | INCLUDES | DASHMATCH ] S* + * [ IDENT | STRING ] S* ]? ']' + * + *@param a_this the "this pointer" of the current instance of + *#CRParser . + *@param a_sel out parameter. The successfully parsed attribute selector. + *@return CR_OK upon successfull completion, an error code otherwise. + */ +static enum CRStatus +cr_parser_parse_attribute_selector (CRParser * a_this, + CRAttrSel ** a_sel) +{ + enum CRStatus status = CR_OK; + CRInputPos init_pos; + CRToken *token = NULL; + CRAttrSel *result = NULL; + CRParsingLocation location = {0} ; + + g_return_val_if_fail (a_this && a_sel, CR_BAD_PARAM_ERROR); + + RECORD_INITIAL_POS (a_this, &init_pos); + + status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token); + ENSURE_PARSING_COND (status == CR_OK && token + && token->type == BO_TK); + cr_parsing_location_copy + (&location, &token->location) ; + cr_token_destroy (token); + token = NULL; + + cr_parser_try_to_skip_spaces_and_comments (a_this); + + result = cr_attr_sel_new (); + if (!result) { + cr_utils_trace_info ("result failed") ; + status = CR_OUT_OF_MEMORY_ERROR ; + goto error ; + } + cr_parsing_location_copy (&result->location, + &location) ; + status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token); + ENSURE_PARSING_COND (status == CR_OK + && token && token->type == IDENT_TK); + + result->name = token->u.str; + token->u.str = NULL; + cr_token_destroy (token); + token = NULL; + + cr_parser_try_to_skip_spaces_and_comments (a_this); + + status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token); + ENSURE_PARSING_COND (status == CR_OK && token); + + if (token->type == INCLUDES_TK) { + result->match_way = INCLUDES; + goto parse_right_part; + } else if (token->type == DASHMATCH_TK) { + result->match_way = DASHMATCH; + goto parse_right_part; + } else if (token->type == DELIM_TK && token->u.unichar == '=') { + result->match_way = EQUALS; + goto parse_right_part; + } else if (token->type == BC_TK) { + result->match_way = SET; + goto done; + } + + parse_right_part: + + if (token) { + cr_token_destroy (token); + token = NULL; + } + + cr_parser_try_to_skip_spaces_and_comments (a_this); + + status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token); + ENSURE_PARSING_COND (status == CR_OK && token); + + if (token->type == IDENT_TK) { + result->value = token->u.str; + token->u.str = NULL; + } else if (token->type == STRING_TK) { + result->value = token->u.str; + token->u.str = NULL; + } else { + status = CR_PARSING_ERROR; + goto error; + } + + if (token) { + cr_token_destroy (token); + token = NULL; + } + + cr_parser_try_to_skip_spaces_and_comments (a_this); + + status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token); + + ENSURE_PARSING_COND (status == CR_OK && token + && token->type == BC_TK); + done: + if (token) { + cr_token_destroy (token); + token = NULL; + } + + if (*a_sel) { + status = cr_attr_sel_append_attr_sel (*a_sel, result); + CHECK_PARSING_STATUS (status, FALSE); + } else { + *a_sel = result; + } + + cr_parser_clear_errors (a_this); + return CR_OK; + + error: + + if (result) { + cr_attr_sel_destroy (result); + result = NULL; + } + + if (token) { + cr_token_destroy (token); + token = NULL; + } + + cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos); + + return status; +} + +/** + *Parses a "property" as specified by the css2 spec at [4.1.1]: + *property : IDENT S*; + * + *@param a_this the "this pointer" of the current instance of #CRParser. + *@param GString a_property out parameter. The parsed property without the + *trailing spaces. If *a_property is NULL, this function allocates a + *new instance of GString and set it content to the parsed property. + *If not, the property is just appended to a_property's previous content. + *In both cases, it is up to the caller to free a_property. + *@return CR_OK upon successfull completion, CR_PARSING_ERROR if the + *next construction was not a "property", or an error code. + */ +static enum CRStatus +cr_parser_parse_property (CRParser * a_this, + CRString ** a_property) +{ + enum CRStatus status = CR_OK; + CRInputPos init_pos; + + g_return_val_if_fail (a_this && PRIVATE (a_this) + && PRIVATE (a_this)->tknzr + && a_property, + CR_BAD_PARAM_ERROR); + + RECORD_INITIAL_POS (a_this, &init_pos); + + status = cr_parser_parse_ident (a_this, a_property); + CHECK_PARSING_STATUS (status, TRUE); + + cr_parser_try_to_skip_spaces_and_comments (a_this); + + cr_parser_clear_errors (a_this); + return CR_OK; + + error: + + cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos); + + return status; +} + +/** + * cr_parser_parse_term: + *@a_term: out parameter. The successfully parsed term. + * + *Parses a "term" as defined in the css2 spec, appendix D.1: + *term ::= unary_operator? [NUMBER S* | PERCENTAGE S* | LENGTH S* | + *EMS S* | EXS S* | ANGLE S* | TIME S* | FREQ S* | function ] | + *STRING S* | IDENT S* | URI S* | RGB S* | UNICODERANGE S* | hexcolor + * + *TODO: handle parsing of 'RGB' + * + *Returns CR_OK upon successfull completion, an error code otherwise. + */ +enum CRStatus +cr_parser_parse_term (CRParser * a_this, CRTerm ** a_term) +{ + enum CRStatus status = CR_PARSING_ERROR; + CRInputPos init_pos; + CRTerm *result = NULL; + CRTerm *param = NULL; + CRToken *token = NULL; + CRString *func_name = NULL; + CRParsingLocation location = {0} ; + + g_return_val_if_fail (a_this && a_term, CR_BAD_PARAM_ERROR); + + RECORD_INITIAL_POS (a_this, &init_pos); + + result = cr_term_new (); + + status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, + &token); + if (status != CR_OK || !token) + goto error; + + cr_parsing_location_copy (&location, &token->location) ; + if (token->type == DELIM_TK && token->u.unichar == '+') { + result->unary_op = PLUS_UOP; + cr_token_destroy (token) ; + token = NULL ; + cr_parser_try_to_skip_spaces_and_comments (a_this); + status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, + &token); + if (status != CR_OK || !token) + goto error; + } else if (token->type == DELIM_TK && token->u.unichar == '-') { + result->unary_op = MINUS_UOP; + cr_token_destroy (token) ; + token = NULL ; + cr_parser_try_to_skip_spaces_and_comments (a_this); + status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, + &token); + if (status != CR_OK || !token) + goto error; + } + + if (token->type == EMS_TK + || token->type == EXS_TK + || token->type == LENGTH_TK + || token->type == ANGLE_TK + || token->type == TIME_TK + || token->type == FREQ_TK + || token->type == PERCENTAGE_TK + || token->type == NUMBER_TK) { + status = cr_term_set_number (result, token->u.num); + CHECK_PARSING_STATUS (status, TRUE); + token->u.num = NULL; + status = CR_OK; + } else if (token && token->type == FUNCTION_TK) { + status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, + token); + token = NULL; + status = cr_parser_parse_function (a_this, &func_name, + ¶m); + + if (status == CR_OK) { + status = cr_term_set_function (result, + func_name, + param); + CHECK_PARSING_STATUS (status, TRUE); + } + } else if (token && token->type == STRING_TK) { + status = cr_term_set_string (result, + token->u.str); + CHECK_PARSING_STATUS (status, TRUE); + token->u.str = NULL; + } else if (token && token->type == IDENT_TK) { + status = cr_term_set_ident (result, token->u.str); + CHECK_PARSING_STATUS (status, TRUE); + token->u.str = NULL; + } else if (token && token->type == URI_TK) { + status = cr_term_set_uri (result, token->u.str); + CHECK_PARSING_STATUS (status, TRUE); + token->u.str = NULL; + } else if (token && token->type == RGB_TK) { + status = cr_term_set_rgb (result, token->u.rgb); + CHECK_PARSING_STATUS (status, TRUE); + token->u.rgb = NULL; + } else if (token && token->type == UNICODERANGE_TK) { + result->type = TERM_UNICODERANGE; + status = CR_PARSING_ERROR; + } else if (token && token->type == HASH_TK) { + status = cr_term_set_hash (result, token->u.str); + CHECK_PARSING_STATUS (status, TRUE); + token->u.str = NULL; + } else { + status = CR_PARSING_ERROR; + } + + if (status != CR_OK) { + goto error; + } + cr_parsing_location_copy (&result->location, + &location) ; + *a_term = cr_term_append_term (*a_term, result); + + result = NULL; + + cr_parser_try_to_skip_spaces_and_comments (a_this); + + if (token) { + cr_token_destroy (token); + token = NULL; + } + + cr_parser_clear_errors (a_this); + return CR_OK; + + error: + + if (result) { + cr_term_destroy (result); + result = NULL; + } + + if (token) { + cr_token_destroy (token); + token = NULL; + } + + if (param) { + cr_term_destroy (param); + param = NULL; + } + + if (func_name) { + cr_string_destroy (func_name); + func_name = NULL; + } + + cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos); + + return status; +} + +/** + * cr_parser_parse_simple_selector: + *@a_this: the "this pointer" of the current instance of #CRParser. + *@a_sel: out parameter. Is set to the successfully parsed simple + *selector. + * + *Parses a "simple_selector" as defined by the css2 spec in appendix D.1 : + *element_name? [ HASH | class | attrib | pseudo ]* S* + *and where pseudo is: + *pseudo ::= ':' [ IDENT | FUNCTION S* IDENT S* ')' ] + * + *Returns CR_OK upon successfull completion, an error code otherwise. + */ +static enum CRStatus +cr_parser_parse_simple_selector (CRParser * a_this, CRSimpleSel ** a_sel) +{ + enum CRStatus status = CR_ERROR; + CRInputPos init_pos; + CRToken *token = NULL; + CRSimpleSel *sel = NULL; + CRAdditionalSel *add_sel_list = NULL; + gboolean found_sel = FALSE; + guint32 cur_char = 0; + + g_return_val_if_fail (a_this && a_sel, CR_BAD_PARAM_ERROR); + + RECORD_INITIAL_POS (a_this, &init_pos); + + status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token); + if (status != CR_OK) + goto error; + + sel = cr_simple_sel_new (); + ENSURE_PARSING_COND (sel); + + cr_parsing_location_copy + (&sel->location, + &token->location) ; + + if (token && token->type == DELIM_TK + && token->u.unichar == '*') { + sel->type_mask |= UNIVERSAL_SELECTOR; + sel->name = cr_string_new_from_string ("*"); + found_sel = TRUE; + } else if (token && token->type == IDENT_TK) { + sel->name = token->u.str; + sel->type_mask |= TYPE_SELECTOR; + token->u.str = NULL; + found_sel = TRUE; + } else { + status = cr_tknzr_unget_token + (PRIVATE (a_this)->tknzr, + token); + token = NULL; + } + + if (token) { + cr_token_destroy (token); + token = NULL; + } + + cr_parser_try_to_skip_spaces_and_comments (a_this); + + for (;;) { + if (token) { + cr_token_destroy (token); + token = NULL; + } + + status = cr_tknzr_get_next_token + (PRIVATE (a_this)->tknzr, + &token); + if (status != CR_OK) + goto error; + + if (token && token->type == HASH_TK) { + /*we parsed an attribute id */ + CRAdditionalSel *add_sel = NULL; + + add_sel = cr_additional_sel_new_with_type + (ID_ADD_SELECTOR); + + add_sel->content.id_name = token->u.str; + token->u.str = NULL; + + cr_parsing_location_copy + (&add_sel->location, + &token->location) ; + add_sel_list = + cr_additional_sel_append + (add_sel_list, add_sel); + found_sel = TRUE; + } else if (token && (token->type == DELIM_TK) + && (token->u.unichar == '.')) { + cr_token_destroy (token); + token = NULL; + + status = cr_tknzr_get_next_token + (PRIVATE (a_this)->tknzr, &token); + if (status != CR_OK) + goto error; + + if (token && token->type == IDENT_TK) { + CRAdditionalSel *add_sel = NULL; + + add_sel = cr_additional_sel_new_with_type + (CLASS_ADD_SELECTOR); + + add_sel->content.class_name = token->u.str; + token->u.str = NULL; + + add_sel_list = + cr_additional_sel_append + (add_sel_list, add_sel); + found_sel = TRUE; + + cr_parsing_location_copy + (&add_sel->location, + & token->location) ; + } else { + status = CR_PARSING_ERROR; + goto error; + } + } else if (token && token->type == BO_TK) { + CRAttrSel *attr_sel = NULL; + CRAdditionalSel *add_sel = NULL; + + status = cr_tknzr_unget_token + (PRIVATE (a_this)->tknzr, token); + if (status != CR_OK) + goto error; + token = NULL; + + status = cr_parser_parse_attribute_selector + (a_this, &attr_sel); + CHECK_PARSING_STATUS (status, FALSE); + + add_sel = cr_additional_sel_new_with_type + (ATTRIBUTE_ADD_SELECTOR); + + ENSURE_PARSING_COND (add_sel != NULL); + + add_sel->content.attr_sel = attr_sel; + + add_sel_list = + cr_additional_sel_append + (add_sel_list, add_sel); + found_sel = TRUE; + cr_parsing_location_copy + (&add_sel->location, + &attr_sel->location) ; + } else if (token && (token->type == DELIM_TK) + && (token->u.unichar == ':')) { + CRPseudo *pseudo = NULL; + + /*try to parse a pseudo */ + + if (token) { + cr_token_destroy (token); + token = NULL; + } + + pseudo = cr_pseudo_new (); + + status = cr_tknzr_get_next_token + (PRIVATE (a_this)->tknzr, &token); + ENSURE_PARSING_COND (status == CR_OK && token); + + cr_parsing_location_copy + (&pseudo->location, + &token->location) ; + + if (token->type == IDENT_TK) { + pseudo->type = IDENT_PSEUDO; + pseudo->name = token->u.str; + token->u.str = NULL; + found_sel = TRUE; + } else if (token->type == FUNCTION_TK) { + pseudo->name = token->u.str; + token->u.str = NULL; + cr_parser_try_to_skip_spaces_and_comments + (a_this); + status = cr_parser_parse_ident + (a_this, &pseudo->extra); + + ENSURE_PARSING_COND (status == CR_OK); + READ_NEXT_CHAR (a_this, &cur_char); + ENSURE_PARSING_COND (cur_char == ')'); + pseudo->type = FUNCTION_PSEUDO; + found_sel = TRUE; + } else { + status = CR_PARSING_ERROR; + goto error; + } + + if (status == CR_OK) { + CRAdditionalSel *add_sel = NULL; + + add_sel = cr_additional_sel_new_with_type + (PSEUDO_CLASS_ADD_SELECTOR); + + add_sel->content.pseudo = pseudo; + cr_parsing_location_copy + (&add_sel->location, + &pseudo->location) ; + add_sel_list = + cr_additional_sel_append + (add_sel_list, add_sel); + status = CR_OK; + } + } else { + status = cr_tknzr_unget_token + (PRIVATE (a_this)->tknzr, token); + token = NULL; + break; + } + } + + if (status == CR_OK && found_sel == TRUE) { + cr_parser_try_to_skip_spaces_and_comments (a_this); + + sel->add_sel = add_sel_list; + add_sel_list = NULL; + + if (*a_sel == NULL) { + *a_sel = sel; + } else { + cr_simple_sel_append_simple_sel (*a_sel, sel); + } + + sel = NULL; + + if (token) { + cr_token_destroy (token); + token = NULL; + } + + cr_parser_clear_errors (a_this); + return CR_OK; + } else { + status = CR_PARSING_ERROR; + } + + error: + + if (token) { + cr_token_destroy (token); + token = NULL; + } + + if (add_sel_list) { + cr_additional_sel_destroy (add_sel_list); + add_sel_list = NULL; + } + + if (sel) { + cr_simple_sel_destroy (sel); + sel = NULL; + } + + cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos); + + return status; + +} + +/** + * cr_parser_parse_simple_sels: + *@a_this: the this pointer of the current instance of #CRParser. + *@a_start: a pointer to the + *first chararcter of the successfully parsed + *string. + *@a_end: a pointer to the last character of the successfully parsed + *string. + * + *Parses a "selector" as defined by the css2 spec in appendix D.1: + *selector ::= simple_selector [ combinator simple_selector ]* + * + *Returns CR_OK upon successfull completion, an error code otherwise. + */ +static enum CRStatus +cr_parser_parse_simple_sels (CRParser * a_this, + CRSimpleSel ** a_sel) +{ + enum CRStatus status = CR_ERROR; + CRInputPos init_pos; + CRSimpleSel *sel = NULL; + guint32 cur_char = 0; + + g_return_val_if_fail (a_this + && PRIVATE (a_this) + && a_sel, + CR_BAD_PARAM_ERROR); + + RECORD_INITIAL_POS (a_this, &init_pos); + + status = cr_parser_parse_simple_selector (a_this, &sel); + CHECK_PARSING_STATUS (status, FALSE); + + *a_sel = cr_simple_sel_append_simple_sel (*a_sel, sel); + + for (;;) { + guint32 next_char = 0; + enum Combinator comb = 0; + + sel = NULL; + + PEEK_NEXT_CHAR (a_this, &next_char); + + if (next_char == '+') { + READ_NEXT_CHAR (a_this, &cur_char); + comb = COMB_PLUS; + cr_parser_try_to_skip_spaces_and_comments (a_this); + } else if (next_char == '>') { + READ_NEXT_CHAR (a_this, &cur_char); + comb = COMB_GT; + cr_parser_try_to_skip_spaces_and_comments (a_this); + } else { + comb = COMB_WS; + } + + status = cr_parser_parse_simple_selector (a_this, &sel); + if (status != CR_OK) + break; + + if (comb && sel) { + sel->combinator = comb; + comb = 0; + } + if (sel) { + *a_sel = cr_simple_sel_append_simple_sel (*a_sel, + sel) ; + } + } + cr_parser_clear_errors (a_this); + return CR_OK; + + error: + + cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos); + + return status; +} + +/** + * cr_parser_parse_selector: + *@a_this: the current instance of #CRParser. + *@a_selector: the parsed list of comma separated + *selectors. + * + *Parses a comma separated list of selectors. + * + *Returns CR_OK upon successful completion, an error + *code otherwise. + */ +static enum CRStatus +cr_parser_parse_selector (CRParser * a_this, + CRSelector ** a_selector) +{ + enum CRStatus status = CR_OK; + CRInputPos init_pos; + guint32 cur_char = 0, + next_char = 0; + CRSimpleSel *simple_sels = NULL; + CRSelector *selector = NULL; + + g_return_val_if_fail (a_this && a_selector, CR_BAD_PARAM_ERROR); + + RECORD_INITIAL_POS (a_this, &init_pos); + + status = cr_parser_parse_simple_sels (a_this, &simple_sels); + CHECK_PARSING_STATUS (status, FALSE); + + if (simple_sels) { + selector = cr_selector_append_simple_sel + (selector, simple_sels); + if (selector) { + cr_parsing_location_copy + (&selector->location, + &simple_sels->location) ; + } + simple_sels = NULL; + } else { + status = CR_PARSING_ERROR ; + goto error ; + } + + status = cr_tknzr_peek_char (PRIVATE (a_this)->tknzr, + &next_char); + if (status != CR_OK) { + if (status == CR_END_OF_INPUT_ERROR) { + status = CR_OK; + goto okay; + } else { + goto error; + } + } + + if (next_char == ',') { + for (;;) { + simple_sels = NULL; + + status = cr_tknzr_peek_char (PRIVATE (a_this)->tknzr, + &next_char); + if (status != CR_OK) { + if (status == CR_END_OF_INPUT_ERROR) { + status = CR_OK; + break; + } else { + goto error; + } + } + + if (next_char != ',') + break; + + /*consume the ',' char */ + READ_NEXT_CHAR (a_this, &cur_char); + + cr_parser_try_to_skip_spaces_and_comments (a_this); + + status = cr_parser_parse_simple_sels + (a_this, &simple_sels); + + CHECK_PARSING_STATUS (status, FALSE); + + if (simple_sels) { + selector = + cr_selector_append_simple_sel + (selector, simple_sels); + + simple_sels = NULL; + } + } + } + + okay: + cr_parser_try_to_skip_spaces_and_comments (a_this); + + if (!*a_selector) { + *a_selector = selector; + } else { + *a_selector = cr_selector_append (*a_selector, selector); + } + + selector = NULL; + return CR_OK; + + error: + + if (simple_sels) { + cr_simple_sel_destroy (simple_sels); + simple_sels = NULL; + } + + if (selector) { + cr_selector_unref (selector); + selector = NULL; + } + + cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos); + + return status; +} + +/** + * cr_parser_parse_function: + *@a_this: the "this pointer" of the current instance of #CRParser. + * + *@a_func_name: out parameter. The parsed function name + *@a_expr: out parameter. The successfully parsed term. + * + *Parses a "function" as defined in css spec at appendix D.1: + *function ::= FUNCTION S* expr ')' S* + *FUNCTION ::= ident'(' + * + *Returns CR_OK upon successfull completion, an error code otherwise. + */ +static enum CRStatus +cr_parser_parse_function (CRParser * a_this, + CRString ** a_func_name, + CRTerm ** a_expr) +{ + CRInputPos init_pos; + enum CRStatus status = CR_OK; + CRToken *token = NULL; + CRTerm *expr = NULL; + + g_return_val_if_fail (a_this && PRIVATE (a_this) + && a_func_name, + CR_BAD_PARAM_ERROR); + + RECORD_INITIAL_POS (a_this, &init_pos); + + status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token); + if (status != CR_OK) + goto error; + + if (token && token->type == FUNCTION_TK) { + *a_func_name = token->u.str; + token->u.str = NULL; + } else { + status = CR_PARSING_ERROR; + goto error; + } + cr_token_destroy (token); + token = NULL; + + cr_parser_try_to_skip_spaces_and_comments (a_this) ; + + status = cr_parser_parse_expr (a_this, &expr); + + CHECK_PARSING_STATUS (status, FALSE); + + status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token); + if (status != CR_OK) + goto error; + + ENSURE_PARSING_COND (token && token->type == PC_TK); + + cr_token_destroy (token); + token = NULL; + + if (expr) { + *a_expr = cr_term_append_term (*a_expr, expr); + expr = NULL; + } + + cr_parser_clear_errors (a_this); + return CR_OK; + + error: + + if (*a_func_name) { + cr_string_destroy (*a_func_name); + *a_func_name = NULL; + } + + if (expr) { + cr_term_destroy (expr); + expr = NULL; + } + + if (token) { + cr_token_destroy (token); + + } + + cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos); + + return status; +} + +/** + * cr_parser_parse_uri: + *@a_this: the current instance of #CRParser. + *@a_str: the successfully parsed url. + * + *Parses an uri as defined by the css spec [4.1.1]: + * URI ::= url\({w}{string}{w}\) + * |url\({w}([!#$%&*-~]|{nonascii}|{escape})*{w}\) + * + *Returns CR_OK upon successfull completion, an error code otherwise. + */ +static enum CRStatus +cr_parser_parse_uri (CRParser * a_this, CRString ** a_str) +{ + + enum CRStatus status = CR_PARSING_ERROR; + + g_return_val_if_fail (a_this && PRIVATE (a_this) + && PRIVATE (a_this)->tknzr, CR_BAD_PARAM_ERROR); + + status = cr_tknzr_parse_token (PRIVATE (a_this)->tknzr, + URI_TK, NO_ET, a_str, NULL); + return status; +} + +/** + * cr_parser_parse_string: + *@a_this: the current instance of #CRParser. + *@a_start: out parameter. Upon successfull completion, + *points to the beginning of the string, points to an undefined value + *otherwise. + *@a_end: out parameter. Upon successfull completion, points to + *the beginning of the string, points to an undefined value otherwise. + * + *Parses a string type as defined in css spec [4.1.1]: + * + *string ::= {string1}|{string2} + *string1 ::= \"([\t !#$%&(-~]|\\{nl}|\'|{nonascii}|{escape})*\" + *string2 ::= \'([\t !#$%&(-~]|\\{nl}|\"|{nonascii}|{escape})*\' + * + *Returns CR_OK upon successfull completion, an error code otherwise. + */ +static enum CRStatus +cr_parser_parse_string (CRParser * a_this, CRString ** a_str) +{ + enum CRStatus status = CR_OK; + + g_return_val_if_fail (a_this && PRIVATE (a_this) + && PRIVATE (a_this)->tknzr + && a_str, CR_BAD_PARAM_ERROR); + + status = cr_tknzr_parse_token (PRIVATE (a_this)->tknzr, + STRING_TK, NO_ET, a_str, NULL); + return status; +} + +/** + *Parses an "ident" as defined in css spec [4.1.1]: + *ident ::= {nmstart}{nmchar}* + * + *@param a_this the currens instance of #CRParser. + * + *@param a_str a pointer to parsed ident. If *a_str is NULL, + *this function allocates a new instance of #CRString. If not, + *the function just appends the parsed string to the one passed. + *In both cases it is up to the caller to free *a_str. + * + *@return CR_OK upon successfull completion, an error code + *otherwise. + */ +static enum CRStatus +cr_parser_parse_ident (CRParser * a_this, CRString ** a_str) +{ + enum CRStatus status = CR_OK; + + g_return_val_if_fail (a_this && PRIVATE (a_this) + && PRIVATE (a_this)->tknzr + && a_str, CR_BAD_PARAM_ERROR); + + status = cr_tknzr_parse_token (PRIVATE (a_this)->tknzr, + IDENT_TK, NO_ET, a_str, NULL); + return status; +} + +/** + *the next rule is ignored as well. This seems to be a bug + *Parses a stylesheet as defined in the css2 spec in appendix D.1: + *stylesheet ::= [ CHARSET_SYM S* STRING S* ';' ]? + * [S|CDO|CDC]* [ import [S|CDO|CDC]* ]* + * [ [ ruleset | media | page | font_face ] [S|CDO|CDC]* ]* + * + *TODO: Finish the code of this function. Think about splitting it into + *smaller functions. + * + *@param a_this the "this pointer" of the current instance of #CRParser. + *@param a_start out parameter. A pointer to the first character of + *the successfully parsed string. + *@param a_end out parameter. A pointer to the first character of + *the successfully parsed string. + * + *@return CR_OK upon successfull completion, an error code otherwise. + */ +static enum CRStatus +cr_parser_parse_stylesheet (CRParser * a_this) +{ + enum CRStatus status = CR_OK; + CRInputPos init_pos; + CRToken *token = NULL; + CRString *charset = NULL; + + g_return_val_if_fail (a_this && PRIVATE (a_this) + && PRIVATE (a_this)->tknzr, CR_BAD_PARAM_ERROR); + + RECORD_INITIAL_POS (a_this, &init_pos); + + PRIVATE (a_this)->state = READY_STATE; + + if (PRIVATE (a_this)->sac_handler + && PRIVATE (a_this)->sac_handler->start_document) { + PRIVATE (a_this)->sac_handler->start_document + (PRIVATE (a_this)->sac_handler); + } + + parse_charset: + status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token); + + if (status == CR_END_OF_INPUT_ERROR) + goto done; + CHECK_PARSING_STATUS (status, TRUE); + + if (token && token->type == CHARSET_SYM_TK) { + CRParsingLocation location = {0} ; + status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, + token); + CHECK_PARSING_STATUS (status, TRUE); + token = NULL; + + status = cr_parser_parse_charset (a_this, + &charset, + &location); + + if (status == CR_OK && charset) { + if (PRIVATE (a_this)->sac_handler + && PRIVATE (a_this)->sac_handler->charset) { + PRIVATE (a_this)->sac_handler->charset + (PRIVATE (a_this)->sac_handler, + charset, &location); + } + } else if (status != CR_END_OF_INPUT_ERROR) { + status = cr_parser_parse_atrule_core (a_this); + CHECK_PARSING_STATUS (status, FALSE); + } + + if (charset) { + cr_string_destroy (charset); + charset = NULL; + } + } else if (token + && (token->type == S_TK + || token->type == COMMENT_TK)) { + status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, + token); + token = NULL; + CHECK_PARSING_STATUS (status, TRUE); + + cr_parser_try_to_skip_spaces_and_comments (a_this); + goto parse_charset ; + } else if (token) { + status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, + token); + token = NULL; + CHECK_PARSING_STATUS (status, TRUE); + } + +/* parse_imports:*/ + do { + if (token) { + cr_token_destroy (token); + token = NULL; + } + cr_parser_try_to_skip_spaces_and_comments (a_this) ; + status = cr_tknzr_get_next_token + (PRIVATE (a_this)->tknzr, &token); + + if (status == CR_END_OF_INPUT_ERROR) + goto done; + CHECK_PARSING_STATUS (status, TRUE); + } while (token + && (token->type == S_TK + || token->type == CDO_TK || token->type == CDC_TK)); + + if (token) { + status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, + token); + token = NULL; + } + + for (;;) { + status = cr_tknzr_get_next_token + (PRIVATE (a_this)->tknzr, &token); + if (status == CR_END_OF_INPUT_ERROR) + goto done; + CHECK_PARSING_STATUS (status, TRUE); + + if (token && token->type == IMPORT_SYM_TK) { + GList *media_list = NULL; + CRString *import_string = NULL; + CRParsingLocation location = {0} ; + + status = cr_tknzr_unget_token + (PRIVATE (a_this)->tknzr, token); + token = NULL; + CHECK_PARSING_STATUS (status, TRUE); + + status = cr_parser_parse_import (a_this, + &media_list, + &import_string, + &location); + if (status == CR_OK) { + if (import_string + && PRIVATE (a_this)->sac_handler + && PRIVATE (a_this)->sac_handler->import_style) { + PRIVATE (a_this)->sac_handler->import_style + (PRIVATE(a_this)->sac_handler, + media_list, + import_string, + NULL, &location) ; + + if ((PRIVATE (a_this)->sac_handler->resolve_import == TRUE)) { + /* + *TODO: resolve the + *import rule. + */ + } + + if ((PRIVATE (a_this)->sac_handler->import_style_result)) { + PRIVATE (a_this)->sac_handler->import_style_result + (PRIVATE (a_this)->sac_handler, + media_list, import_string, + NULL, NULL); + } + } + } else if (status != CR_END_OF_INPUT_ERROR) { + if (PRIVATE (a_this)->sac_handler + && PRIVATE (a_this)->sac_handler->error) { + PRIVATE (a_this)->sac_handler->error + (PRIVATE (a_this)->sac_handler); + } + status = cr_parser_parse_atrule_core (a_this); + CHECK_PARSING_STATUS (status, TRUE) ; + } else { + goto error ; + } + + /* + *then, after calling the appropriate + *SAC handler, free + *the media_list and import_string. + */ + if (media_list) { + GList *cur = NULL; + + /*free the medium list */ + for (cur = media_list; cur; cur = cur->next) { + if (cur->data) { + cr_string_destroy (cur->data); + } + } + + g_list_free (media_list); + media_list = NULL; + } + + if (import_string) { + cr_string_destroy (import_string); + import_string = NULL; + } + + cr_parser_try_to_skip_spaces_and_comments (a_this); + } else if (token + && (token->type == S_TK + || token->type == CDO_TK + || token->type == CDC_TK)) { + status = cr_tknzr_unget_token + (PRIVATE (a_this)->tknzr, token); + token = NULL; + + do { + if (token) { + cr_token_destroy (token); + token = NULL; + } + + status = cr_tknzr_get_next_token + (PRIVATE (a_this)->tknzr, &token); + + if (status == CR_END_OF_INPUT_ERROR) + goto done; + CHECK_PARSING_STATUS (status, TRUE); + } while (token + && (token->type == S_TK + || token->type == CDO_TK + || token->type == CDC_TK)); + } else { + if (token) { + status = cr_tknzr_unget_token + (PRIVATE (a_this)->tknzr, token); + token = NULL; + } + goto parse_ruleset_and_others; + } + } + + parse_ruleset_and_others: + + cr_parser_try_to_skip_spaces_and_comments (a_this); + + for (;;) { + status = cr_tknzr_get_next_token + (PRIVATE (a_this)->tknzr, &token); + if (status == CR_END_OF_INPUT_ERROR) + goto done; + CHECK_PARSING_STATUS (status, TRUE); + + if (token + && (token->type == S_TK + || token->type == CDO_TK || token->type == CDC_TK)) { + status = cr_tknzr_unget_token + (PRIVATE (a_this)->tknzr, token); + token = NULL; + + do { + if (token) { + cr_token_destroy (token); + token = NULL; + } + + cr_parser_try_to_skip_spaces_and_comments + (a_this); + status = cr_tknzr_get_next_token + (PRIVATE (a_this)->tknzr, &token); + } while (token + && (token->type == S_TK + || token->type == COMMENT_TK + || token->type == CDO_TK + || token->type == CDC_TK)); + if (token) { + cr_tknzr_unget_token + (PRIVATE (a_this)->tknzr, token); + token = NULL; + } + } else if (token + && (token->type == HASH_TK + || (token->type == DELIM_TK + && token->u.unichar == '.') + || (token->type == DELIM_TK + && token->u.unichar == ':') + || (token->type == DELIM_TK + && token->u.unichar == '*') + || (token->type == BO_TK) + || token->type == IDENT_TK)) { + /* + *Try to parse a CSS2 ruleset. + *if the parsing fails, try to parse + *a css core ruleset. + */ + status = cr_tknzr_unget_token + (PRIVATE (a_this)->tknzr, token); + CHECK_PARSING_STATUS (status, TRUE); + token = NULL; + + status = cr_parser_parse_ruleset (a_this); + + if (status == CR_OK) { + continue; + } else { + if (PRIVATE (a_this)->sac_handler + && PRIVATE (a_this)->sac_handler->error) { + PRIVATE (a_this)->sac_handler-> + error + (PRIVATE (a_this)-> + sac_handler); + } + + status = cr_parser_parse_ruleset_core + (a_this); + + if (status == CR_OK) { + continue; + } else { + break; + } + } + } else if (token && token->type == MEDIA_SYM_TK) { + status = cr_tknzr_unget_token + (PRIVATE (a_this)->tknzr, token); + CHECK_PARSING_STATUS (status, TRUE); + token = NULL; + + status = cr_parser_parse_media (a_this); + if (status == CR_OK) { + continue; + } else { + if (PRIVATE (a_this)->sac_handler + && PRIVATE (a_this)->sac_handler->error) { + PRIVATE (a_this)->sac_handler-> + error + (PRIVATE (a_this)-> + sac_handler); + } + + status = cr_parser_parse_atrule_core (a_this); + + if (status == CR_OK) { + continue; + } else { + break; + } + } + + } else if (token && token->type == PAGE_SYM_TK) { + status = cr_tknzr_unget_token + (PRIVATE (a_this)->tknzr, token); + CHECK_PARSING_STATUS (status, TRUE); + token = NULL; + status = cr_parser_parse_page (a_this); + + if (status == CR_OK) { + continue; + } else { + if (PRIVATE (a_this)->sac_handler + && PRIVATE (a_this)->sac_handler->error) { + PRIVATE (a_this)->sac_handler-> + error + (PRIVATE (a_this)-> + sac_handler); + } + + status = cr_parser_parse_atrule_core (a_this); + + if (status == CR_OK) { + continue; + } else { + break; + } + } + } else if (token && token->type == FONT_FACE_SYM_TK) { + status = cr_tknzr_unget_token + (PRIVATE (a_this)->tknzr, token); + CHECK_PARSING_STATUS (status, TRUE); + token = NULL; + status = cr_parser_parse_font_face (a_this); + + if (status == CR_OK) { + continue; + } else { + if (PRIVATE (a_this)->sac_handler + && PRIVATE (a_this)->sac_handler->error) { + PRIVATE (a_this)->sac_handler-> + error + (PRIVATE (a_this)-> + sac_handler); + } + + status = cr_parser_parse_atrule_core (a_this); + + if (status == CR_OK) { + continue; + } else { + break; + } + } + } else { + status = cr_tknzr_unget_token + (PRIVATE (a_this)->tknzr, token); + CHECK_PARSING_STATUS (status, TRUE); + token = NULL; + status = cr_parser_parse_statement_core (a_this); + + if (status == CR_OK) { + continue; + } else { + break; + } + } + } + + done: + if (token) { + cr_token_destroy (token); + token = NULL; + } + + if (status == CR_END_OF_INPUT_ERROR || status == CR_OK) { + + if (PRIVATE (a_this)->sac_handler + && PRIVATE (a_this)->sac_handler->end_document) { + PRIVATE (a_this)->sac_handler->end_document + (PRIVATE (a_this)->sac_handler); + } + + return CR_OK; + } + + cr_parser_push_error + (a_this, "could not recognize next production", CR_ERROR); + + if (PRIVATE (a_this)->sac_handler + && PRIVATE (a_this)->sac_handler->unrecoverable_error) { + PRIVATE (a_this)->sac_handler-> + unrecoverable_error (PRIVATE (a_this)->sac_handler); + } + + cr_parser_dump_err_stack (a_this, TRUE); + + return status; + + error: + + if (token) { + cr_token_destroy (token); + token = NULL; + } + + if (PRIVATE (a_this)->sac_handler + && PRIVATE (a_this)->sac_handler->unrecoverable_error) { + PRIVATE (a_this)->sac_handler-> + unrecoverable_error (PRIVATE (a_this)->sac_handler); + } + + cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos); + + return status; +} + +/**************************************** + *Public CRParser Methods + ****************************************/ + +/** + * cr_parser_new: + * @a_tknzr: the tokenizer to use for the parsing. + * + *Creates a new parser to parse data + *coming the input stream given in parameter. + * + *Returns the newly created instance of #CRParser, + *or NULL if an error occured. + */ +CRParser * +cr_parser_new (CRTknzr * a_tknzr) +{ + CRParser *result = NULL; + enum CRStatus status = CR_OK; + + result = g_malloc0 (sizeof (CRParser)); + + PRIVATE (result) = g_malloc0 (sizeof (CRParserPriv)); + + if (a_tknzr) { + status = cr_parser_set_tknzr (result, a_tknzr); + } + + g_return_val_if_fail (status == CR_OK, NULL); + + return result; +} + +/** + * cr_parser_new_from_buf: + *@a_buf: the buffer to parse. + *@a_len: the length of the data in the buffer. + *@a_enc: the encoding of the input buffer a_buf. + *@a_free_buf: if set to TRUE, a_buf will be freed + *during the destruction of the newly built instance + *of #CRParser. If set to FALSE, it is up to the caller to + *eventually free it. + * + *Instanciates a new parser from a memory buffer. + * + *Returns the newly built parser, or NULL if an error arises. + */ +CRParser * +cr_parser_new_from_buf (guchar * a_buf, + gulong a_len, + enum CREncoding a_enc, + gboolean a_free_buf) +{ + CRParser *result = NULL; + CRInput *input = NULL; + + g_return_val_if_fail (a_buf && a_len, NULL); + + input = cr_input_new_from_buf (a_buf, a_len, a_enc, a_free_buf); + g_return_val_if_fail (input, NULL); + + result = cr_parser_new_from_input (input); + if (!result) { + cr_input_destroy (input); + input = NULL; + return NULL; + } + return result; +} + +/** + * cr_parser_new_from_input: + * @a_input: the parser input stream to use. + * + * Returns a newly built parser input. + */ +CRParser * +cr_parser_new_from_input (CRInput * a_input) +{ + CRParser *result = NULL; + CRTknzr *tokenizer = NULL; + + if (a_input) { + tokenizer = cr_tknzr_new (a_input); + g_return_val_if_fail (tokenizer, NULL); + } + + result = cr_parser_new (tokenizer); + g_return_val_if_fail (result, NULL); + + return result; +} + +/** + * cr_parser_new_from_file: + * @a_file_uri: the uri of the file to parse. + * @a_enc: the file encoding to use. + * + * Returns the newly built parser. + */ +CRParser * +cr_parser_new_from_file (const guchar * a_file_uri, enum CREncoding a_enc) +{ + CRParser *result = NULL; + CRTknzr *tokenizer = NULL; + + tokenizer = cr_tknzr_new_from_uri (a_file_uri, a_enc); + if (!tokenizer) { + cr_utils_trace_info ("Could not open input file"); + return NULL; + } + + result = cr_parser_new (tokenizer); + g_return_val_if_fail (result, NULL); + return result; +} + +/** + * cr_parser_set_sac_handler: + *@a_this: the "this pointer" of the current instance of #CRParser. + *@a_handler: the handler to set. + * + *Sets a SAC document handler to the parser. + * + *Returns CR_OK upon successfull completion, an error code otherwise. + */ +enum CRStatus +cr_parser_set_sac_handler (CRParser * a_this, CRDocHandler * a_handler) +{ + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); + + if (PRIVATE (a_this)->sac_handler) { + cr_doc_handler_unref (PRIVATE (a_this)->sac_handler); + } + + PRIVATE (a_this)->sac_handler = a_handler; + cr_doc_handler_ref (a_handler); + + return CR_OK; +} + +/** + * cr_parser_get_sac_handler: + *@a_this: the "this pointer" of the current instance of + *#CRParser. + *@a_handler: out parameter. The returned handler. + * + *Gets the SAC document handler. + * + *Returns CR_OK upon successfull completion, an error code + *otherwise. + */ +enum CRStatus +cr_parser_get_sac_handler (CRParser * a_this, CRDocHandler ** a_handler) +{ + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); + + *a_handler = PRIVATE (a_this)->sac_handler; + + return CR_OK; +} + +/** + * cr_parser_set_default_sac_handler: + *@a_this: a pointer to the current instance of #CRParser. + * + *Sets the SAC handler associated to the current instance + *of #CRParser to the default SAC handler. + * + *Returns CR_OK upon successfull completion, an error code otherwise. + */ +enum CRStatus +cr_parser_set_default_sac_handler (CRParser * a_this) +{ + CRDocHandler *default_sac_handler = NULL; + enum CRStatus status = CR_ERROR; + + g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR); + + default_sac_handler = cr_doc_handler_new (); + + cr_doc_handler_set_default_sac_handler (default_sac_handler); + + status = cr_parser_set_sac_handler (a_this, default_sac_handler); + + if (status != CR_OK) { + cr_doc_handler_destroy (default_sac_handler); + default_sac_handler = NULL; + } + + return status; +} + +/** + * cr_parser_set_use_core_grammar: + * @a_this: the current instance of #CRParser. + * @a_use_core_grammar: where to parse against the css core grammar. + * + * Returns CR_OK upon succesful completion, an error code otherwise. + */ +enum CRStatus +cr_parser_set_use_core_grammar (CRParser * a_this, + gboolean a_use_core_grammar) +{ + g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR); + + PRIVATE (a_this)->use_core_grammar = a_use_core_grammar; + + return CR_OK; +} + +/** + * cr_parser_get_use_core_grammar: + * @a_this: the current instance of #CRParser. + * @a_use_core_grammar: wether to use the core grammar or not. + * + * Returns CR_OK upon succesful completion, an error code otherwise. + */ +enum CRStatus +cr_parser_get_use_core_grammar (CRParser * a_this, + gboolean * a_use_core_grammar) +{ + g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR); + + *a_use_core_grammar = PRIVATE (a_this)->use_core_grammar; + + return CR_OK; +} + +/** + * cr_parser_parse_file: + *@a_this: a pointer to the current instance of #CRParser. + *@a_file_uri: the uri to the file to load. For the time being, + *@a_enc: the encoding of the file to parse. + *only local files are supported. + * + *Parses a the given in parameter. + * + *Returns CR_OK upon successfull completion, an error code otherwise. + */ +enum CRStatus +cr_parser_parse_file (CRParser * a_this, + const guchar * a_file_uri, enum CREncoding a_enc) +{ + enum CRStatus status = CR_ERROR; + CRTknzr *tknzr = NULL; + + g_return_val_if_fail (a_this && PRIVATE (a_this) + && a_file_uri, CR_BAD_PARAM_ERROR); + + tknzr = cr_tknzr_new_from_uri (a_file_uri, a_enc); + + g_return_val_if_fail (tknzr != NULL, CR_ERROR); + + status = cr_parser_set_tknzr (a_this, tknzr); + g_return_val_if_fail (status == CR_OK, CR_ERROR); + + status = cr_parser_parse (a_this); + + return status; +} + +/** + * cr_parser_parse_expr: + * @a_this: the current instance of #CRParser. + * @a_expr: out parameter. the parsed expression. + * + *Parses an expression as defined by the css2 spec in appendix + *D.1: + *expr: term [ operator term ]* + * + * + * Returns CR_OK upon successful completion, an error code otherwise. + */ +enum CRStatus +cr_parser_parse_expr (CRParser * a_this, CRTerm ** a_expr) +{ + enum CRStatus status = CR_ERROR; + CRInputPos init_pos; + CRTerm *expr = NULL, + *expr2 = NULL; + guchar next_byte = 0; + gulong nb_terms = 0; + + g_return_val_if_fail (a_this && PRIVATE (a_this) + && a_expr, CR_BAD_PARAM_ERROR); + + RECORD_INITIAL_POS (a_this, &init_pos); + + status = cr_parser_parse_term (a_this, &expr); + + CHECK_PARSING_STATUS (status, FALSE); + + for (;;) { + guchar operator = 0; + + status = cr_tknzr_peek_byte (PRIVATE (a_this)->tknzr, + 1, &next_byte); + if (status != CR_OK) { + if (status == CR_END_OF_INPUT_ERROR) { + /* + if (!nb_terms) + { + goto error ; + } + */ + status = CR_OK; + break; + } else { + goto error; + } + } + + if (next_byte == '/' || next_byte == ',') { + READ_NEXT_BYTE (a_this, &operator); + } + + cr_parser_try_to_skip_spaces_and_comments (a_this); + + status = cr_parser_parse_term (a_this, &expr2); + + if (status != CR_OK || expr2 == NULL) { + status = CR_OK; + break; + } + + switch (operator) { + case '/': + expr2->the_operator = DIVIDE; + break; + case ',': + expr2->the_operator = COMMA; + + default: + break; + } + + expr = cr_term_append_term (expr, expr2); + expr2 = NULL; + operator = 0; + nb_terms++; + } + + if (status == CR_OK) { + *a_expr = cr_term_append_term (*a_expr, expr); + expr = NULL; + + cr_parser_clear_errors (a_this); + return CR_OK; + } + + error: + + if (expr) { + cr_term_destroy (expr); + expr = NULL; + } + + if (expr2) { + cr_term_destroy (expr2); + expr2 = NULL; + } + + cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos); + + return status; +} + +/** + * cr_parser_parse_prio: + *@a_this: the current instance of #CRParser. + *@a_prio: a string representing the priority. + *Today, only "!important" is returned as only this + *priority is defined by css2. + * + *Parses a declaration priority as defined by + *the css2 grammar in appendix C: + *prio: IMPORTANT_SYM S* + * + * Returns CR_OK upon successful completion, an error code otherwise. + */ +enum CRStatus +cr_parser_parse_prio (CRParser * a_this, CRString ** a_prio) +{ + enum CRStatus status = CR_ERROR; + CRInputPos init_pos; + CRToken *token = NULL; + + g_return_val_if_fail (a_this && PRIVATE (a_this) + && a_prio + && *a_prio == NULL, CR_BAD_PARAM_ERROR); + + RECORD_INITIAL_POS (a_this, &init_pos); + + status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token); + if (status == CR_END_OF_INPUT_ERROR) { + goto error; + } + ENSURE_PARSING_COND (status == CR_OK + && token && token->type == IMPORTANT_SYM_TK); + + cr_parser_try_to_skip_spaces_and_comments (a_this); + *a_prio = cr_string_new_from_string ("!important"); + cr_token_destroy (token); + token = NULL; + return CR_OK; + + error: + if (token) { + cr_token_destroy (token); + token = NULL; + } + cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos); + + return status; +} + +/** + * cr_parser_parse_declaration: + *@a_this: the "this pointer" of the current instance of #CRParser. + *@a_property: the successfully parsed property. The caller + * *must* free the returned pointer. + *@a_expr: the expression that represents the attribute value. + *The caller *must* free the returned pointer. + * + *TODO: return the parsed priority, so that + *upper layers can take benefit from it. + *Parses a "declaration" as defined by the css2 spec in appendix D.1: + *declaration ::= [property ':' S* expr prio?]? + * + *Returns CR_OK upon successfull completion, an error code otherwise. + */ +enum CRStatus +cr_parser_parse_declaration (CRParser * a_this, + CRString ** a_property, + CRTerm ** a_expr, gboolean * a_important) +{ + enum CRStatus status = CR_ERROR; + CRInputPos init_pos; + guint32 cur_char = 0; + CRTerm *expr = NULL; + CRString *prio = NULL; + + g_return_val_if_fail (a_this && PRIVATE (a_this) + && a_property && a_expr + && a_important, CR_BAD_PARAM_ERROR); + + RECORD_INITIAL_POS (a_this, &init_pos); + + status = cr_parser_parse_property (a_this, a_property); + + if (status == CR_END_OF_INPUT_ERROR) + goto error; + + CHECK_PARSING_STATUS_ERR + (a_this, status, FALSE, + "while parsing declaration: next property is malformed", + CR_SYNTAX_ERROR); + + READ_NEXT_CHAR (a_this, &cur_char); + + if (cur_char != ':') { + status = CR_PARSING_ERROR; + cr_parser_push_error + (a_this, + "while parsing declaration: this char must be ':'", + CR_SYNTAX_ERROR); + goto error; + } + + cr_parser_try_to_skip_spaces_and_comments (a_this); + + status = cr_parser_parse_expr (a_this, &expr); + + CHECK_PARSING_STATUS_ERR + (a_this, status, FALSE, + "while parsing declaration: next expression is malformed", + CR_SYNTAX_ERROR); + + cr_parser_try_to_skip_spaces_and_comments (a_this); + status = cr_parser_parse_prio (a_this, &prio); + if (prio) { + cr_string_destroy (prio); + prio = NULL; + *a_important = TRUE; + } else { + *a_important = FALSE; + } + if (*a_expr) { + cr_term_append_term (*a_expr, expr); + expr = NULL; + } else { + *a_expr = expr; + expr = NULL; + } + + cr_parser_clear_errors (a_this); + return CR_OK; + + error: + + if (expr) { + cr_term_destroy (expr); + expr = NULL; + } + + if (*a_property) { + cr_string_destroy (*a_property); + *a_property = NULL; + } + + cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos); + + return status; +} + +/** + * cr_parser_parse_statement_core: + *@a_this: the current instance of #CRParser. + * + *Parses a statement as defined by the css core grammar in + *chapter 4.1 of the css2 spec. + *statement : ruleset | at-rule; + * + *Returns CR_OK upon successfull completion, an error code otherwise. + */ +enum CRStatus +cr_parser_parse_statement_core (CRParser * a_this) +{ + CRToken *token = NULL; + CRInputPos init_pos; + enum CRStatus status = CR_ERROR; + + g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR); + + RECORD_INITIAL_POS (a_this, &init_pos); + + status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token); + + ENSURE_PARSING_COND (status == CR_OK && token); + + switch (token->type) { + case ATKEYWORD_TK: + case IMPORT_SYM_TK: + case PAGE_SYM_TK: + case MEDIA_SYM_TK: + case FONT_FACE_SYM_TK: + case CHARSET_SYM_TK: + cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, token); + token = NULL; + status = cr_parser_parse_atrule_core (a_this); + CHECK_PARSING_STATUS (status, TRUE); + break; + + default: + cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, token); + token = NULL; + status = cr_parser_parse_ruleset_core (a_this); + cr_parser_clear_errors (a_this); + CHECK_PARSING_STATUS (status, TRUE); + } + + return CR_OK; + + error: + if (token) { + cr_token_destroy (token); + token = NULL; + } + + cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos); + + return status; +} + +/** + * cr_parser_parse_ruleset: + *@a_this: the "this pointer" of the current instance of #CRParser. + * + *Parses a "ruleset" as defined in the css2 spec at appendix D.1. + *ruleset ::= selector [ ',' S* selector ]* + *'{' S* declaration? [ ';' S* declaration? ]* '}' S*; + * + *This methods calls the the SAC handler on the relevant SAC handler + *callbacks whenever it encounters some specific constructions. + *See the documentation of #CRDocHandler (the SAC handler) to know + *when which SAC handler is called. + * + *Returns CR_OK upon successfull completion, an error code otherwise. + */ +enum CRStatus +cr_parser_parse_ruleset (CRParser * a_this) +{ + enum CRStatus status = CR_OK; + CRInputPos init_pos; + guint32 cur_char = 0, + next_char = 0; + CRString *property = NULL; + CRTerm *expr = NULL; + CRSimpleSel *simple_sels = NULL; + CRSelector *selector = NULL; + gboolean start_selector = FALSE, + is_important = FALSE; + + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); + + RECORD_INITIAL_POS (a_this, &init_pos); + + status = cr_parser_parse_selector (a_this, &selector); + CHECK_PARSING_STATUS (status, FALSE); + + READ_NEXT_CHAR (a_this, &cur_char); + + ENSURE_PARSING_COND_ERR + (a_this, cur_char == '{', + "while parsing rulset: current char should be '{'", + CR_SYNTAX_ERROR); + + if (PRIVATE (a_this)->sac_handler + && PRIVATE (a_this)->sac_handler->start_selector) { + /* + *the selector is ref counted so that the parser's user + *can choose to keep it. + */ + if (selector) { + cr_selector_ref (selector); + } + + PRIVATE (a_this)->sac_handler->start_selector + (PRIVATE (a_this)->sac_handler, selector); + start_selector = TRUE; + } + + cr_parser_try_to_skip_spaces_and_comments (a_this); + + PRIVATE (a_this)->state = TRY_PARSE_RULESET_STATE; + + status = cr_parser_parse_declaration (a_this, &property, + &expr, + &is_important); + if (expr) { + cr_term_ref (expr); + } + if (status == CR_OK + && PRIVATE (a_this)->sac_handler + && PRIVATE (a_this)->sac_handler->property) { + PRIVATE (a_this)->sac_handler->property + (PRIVATE (a_this)->sac_handler, property, expr, + is_important); + } + if (status == CR_OK) { + /* + *free the allocated + *'property' and 'term' before parsing + *next declarations. + */ + if (property) { + cr_string_destroy (property); + property = NULL; + } + if (expr) { + cr_term_unref (expr); + expr = NULL; + } + } else {/*status != CR_OK*/ + guint32 c = 0 ; + /* + *test if we have reached '}', which + *would mean that we are parsing an empty ruleset (eg. x{ }) + *In that case, goto end_of_ruleset. + */ + status = cr_tknzr_peek_char (PRIVATE (a_this)->tknzr, &c) ; + if (status == CR_OK && c == '}') { + status = CR_OK ; + goto end_of_ruleset ; + } + } + CHECK_PARSING_STATUS_ERR + (a_this, status, FALSE, + "while parsing ruleset: next construction should be a declaration", + CR_SYNTAX_ERROR); + + for (;;) { + PEEK_NEXT_CHAR (a_this, &next_char); + if (next_char != ';') + break; + + /*consume the ';' char */ + READ_NEXT_CHAR (a_this, &cur_char); + + cr_parser_try_to_skip_spaces_and_comments (a_this); + + status = cr_parser_parse_declaration (a_this, &property, + &expr, &is_important); + + if (expr) { + cr_term_ref (expr); + } + if (status == CR_OK + && PRIVATE (a_this)->sac_handler + && PRIVATE (a_this)->sac_handler->property) { + PRIVATE (a_this)->sac_handler->property + (PRIVATE (a_this)->sac_handler, + property, expr, is_important); + } + if (property) { + cr_string_destroy (property); + property = NULL; + } + if (expr) { + cr_term_unref (expr); + expr = NULL; + } + } + + end_of_ruleset: + cr_parser_try_to_skip_spaces_and_comments (a_this); + READ_NEXT_CHAR (a_this, &cur_char); + ENSURE_PARSING_COND_ERR + (a_this, cur_char == '}', + "while parsing rulset: current char must be a '}'", + CR_SYNTAX_ERROR); + + if (PRIVATE (a_this)->sac_handler + && PRIVATE (a_this)->sac_handler->end_selector) { + PRIVATE (a_this)->sac_handler->end_selector + (PRIVATE (a_this)->sac_handler, selector); + start_selector = FALSE; + } + + if (expr) { + cr_term_unref (expr); + expr = NULL; + } + + if (simple_sels) { + cr_simple_sel_destroy (simple_sels); + simple_sels = NULL; + } + + if (selector) { + cr_selector_unref (selector); + selector = NULL; + } + + cr_parser_clear_errors (a_this); + PRIVATE (a_this)->state = RULESET_PARSED_STATE; + + return CR_OK; + + error: + if (start_selector == TRUE + && PRIVATE (a_this)->sac_handler + && PRIVATE (a_this)->sac_handler->error) { + PRIVATE (a_this)->sac_handler->error + (PRIVATE (a_this)->sac_handler); + } + if (expr) { + cr_term_unref (expr); + expr = NULL; + } + if (simple_sels) { + cr_simple_sel_destroy (simple_sels); + simple_sels = NULL; + } + if (property) { + cr_string_destroy (property); + } + if (selector) { + cr_selector_unref (selector); + selector = NULL; + } + + cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos); + + return status; +} + +/** + * cr_parser_parse_import: + *@a_this: the "this pointer" of the current instance + *of #CRParser. + *@a_media_list: out parameter. A linked list of + *#CRString + *Each CRString is a string that contains + *a 'medium' declaration part of the successfully + *parsed 'import' declaration. + *@a_import_string: out parameter. + *A string that contains the 'import + *string". The import string can be either an uri (if it starts with + *the substring "uri(") or a any other css2 string. Note that + * *a_import_string must be initially set to NULL or else, this function + *will return CR_BAD_PARAM_ERROR. + *@a_location: the location (line, column) where the import has been parsed + * + *Parses an 'import' declaration as defined in the css2 spec + *in appendix D.1: + * + *import ::= + *@import [STRING|URI] S* [ medium [ ',' S* medium]* ]? ';' S* + * + *Returns CR_OK upon sucessfull completion, an error code otherwise. + */ +enum CRStatus +cr_parser_parse_import (CRParser * a_this, + GList ** a_media_list, + CRString ** a_import_string, + CRParsingLocation *a_location) +{ + enum CRStatus status = CR_OK; + CRInputPos init_pos; + guint32 cur_char = 0, + next_char = 0; + CRString *medium = NULL; + + g_return_val_if_fail (a_this + && a_import_string + && (*a_import_string == NULL), + CR_BAD_PARAM_ERROR); + + RECORD_INITIAL_POS (a_this, &init_pos); + + if (BYTE (a_this, 1, NULL) == '@' + && BYTE (a_this, 2, NULL) == 'i' + && BYTE (a_this, 3, NULL) == 'm' + && BYTE (a_this, 4, NULL) == 'p' + && BYTE (a_this, 5, NULL) == 'o' + && BYTE (a_this, 6, NULL) == 'r' + && BYTE (a_this, 7, NULL) == 't') { + SKIP_CHARS (a_this, 1); + if (a_location) { + cr_parser_get_parsing_location + (a_this, a_location) ; + } + SKIP_CHARS (a_this, 6); + status = CR_OK; + } else { + status = CR_PARSING_ERROR; + goto error; + } + + cr_parser_try_to_skip_spaces_and_comments (a_this); + + PRIVATE (a_this)->state = TRY_PARSE_IMPORT_STATE; + + PEEK_NEXT_CHAR (a_this, &next_char); + + if (next_char == '"' || next_char == '\'') { + status = cr_parser_parse_string (a_this, a_import_string); + + CHECK_PARSING_STATUS (status, FALSE); + } else { + status = cr_parser_parse_uri (a_this, a_import_string); + + CHECK_PARSING_STATUS (status, FALSE); + } + + cr_parser_try_to_skip_spaces_and_comments (a_this); + + status = cr_parser_parse_ident (a_this, &medium); + + if (status == CR_OK && medium) { + *a_media_list = g_list_append (*a_media_list, medium); + medium = NULL; + } + + cr_parser_try_to_skip_spaces_and_comments (a_this); + + for (; status == CR_OK;) { + if ((status = cr_tknzr_peek_char (PRIVATE (a_this)->tknzr, + &next_char)) != CR_OK) { + if (status == CR_END_OF_INPUT_ERROR) { + status = CR_OK; + goto okay; + } + goto error; + } + + if (next_char == ',') { + READ_NEXT_CHAR (a_this, &cur_char); + } else { + break; + } + + cr_parser_try_to_skip_spaces_and_comments (a_this); + + status = cr_parser_parse_ident (a_this, &medium); + + cr_parser_try_to_skip_spaces_and_comments (a_this); + + if ((status == CR_OK) && medium) { + *a_media_list = g_list_append (*a_media_list, medium); + + medium = NULL; + } + + CHECK_PARSING_STATUS (status, FALSE); + cr_parser_try_to_skip_spaces_and_comments (a_this); + } + cr_parser_try_to_skip_spaces_and_comments (a_this); + READ_NEXT_CHAR (a_this, &cur_char); + ENSURE_PARSING_COND (cur_char == ';'); + cr_parser_try_to_skip_spaces_and_comments (a_this); + okay: + cr_parser_clear_errors (a_this); + PRIVATE (a_this)->state = IMPORT_PARSED_STATE; + + return CR_OK; + + error: + + if (*a_media_list) { + GList *cur = NULL; + + /* + *free each element of *a_media_list. + *Note that each element of *a_medium list *must* + *be a GString* or else, the code that is coming next + *will corrupt the memory and lead to hard to debug + *random crashes. + *This is where C++ and its compile time + *type checking mecanism (through STL containers) would + *have prevented us to go through this hassle. + */ + for (cur = *a_media_list; cur; cur = cur->next) { + if (cur->data) { + cr_string_destroy (cur->data); + } + } + + g_list_free (*a_media_list); + *a_media_list = NULL; + } + + if (*a_import_string) { + cr_string_destroy (*a_import_string); + *a_import_string = NULL; + } + + if (medium) { + cr_string_destroy (medium); + medium = NULL; + } + + cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos); + + return status; +} + +/** + * cr_parser_parse_media: + *@a_this: the "this pointer" of the current instance of #CRParser. + * + *Parses a 'media' declaration as specified in the css2 spec at + *appendix D.1: + * + *media ::= @media S* medium [ ',' S* medium ]* '{' S* ruleset* '}' S* + * + *Note that this function calls the required sac handlers during the parsing + *to notify media productions. See #CRDocHandler to know the callback called + *during @media parsing. + * + *Returns CR_OK upon successfull completion, an error code otherwise. + */ +enum CRStatus +cr_parser_parse_media (CRParser * a_this) +{ + enum CRStatus status = CR_OK; + CRInputPos init_pos; + CRToken *token = NULL; + guint32 next_char = 0, + cur_char = 0; + CRString *medium = NULL; + GList *media_list = NULL; + CRParsingLocation location = {0} ; + + g_return_val_if_fail (a_this + && PRIVATE (a_this), + CR_BAD_PARAM_ERROR); + + RECORD_INITIAL_POS (a_this, &init_pos); + + status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, + &token); + ENSURE_PARSING_COND (status == CR_OK + && token + && token->type == MEDIA_SYM_TK); + cr_parsing_location_copy (&location, &token->location) ; + cr_token_destroy (token); + token = NULL; + + cr_parser_try_to_skip_spaces_and_comments (a_this); + + status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token); + ENSURE_PARSING_COND (status == CR_OK + && token && token->type == IDENT_TK); + + medium = token->u.str; + token->u.str = NULL; + cr_token_destroy (token); + token = NULL; + + if (medium) { + media_list = g_list_append (media_list, medium); + medium = NULL; + } + + for (; status == CR_OK;) { + cr_parser_try_to_skip_spaces_and_comments (a_this); + PEEK_NEXT_CHAR (a_this, &next_char); + + if (next_char == ',') { + READ_NEXT_CHAR (a_this, &cur_char); + } else { + break; + } + + cr_parser_try_to_skip_spaces_and_comments (a_this); + + status = cr_parser_parse_ident (a_this, &medium); + + CHECK_PARSING_STATUS (status, FALSE); + + if (medium) { + media_list = g_list_append (media_list, medium); + medium = NULL; + } + } + + READ_NEXT_CHAR (a_this, &cur_char); + + ENSURE_PARSING_COND (cur_char == '{'); + + /* + *call the SAC handler api here. + */ + if (PRIVATE (a_this)->sac_handler + && PRIVATE (a_this)->sac_handler->start_media) { + PRIVATE (a_this)->sac_handler->start_media + (PRIVATE (a_this)->sac_handler, media_list, + &location); + } + + cr_parser_try_to_skip_spaces_and_comments (a_this); + + PRIVATE (a_this)->state = TRY_PARSE_MEDIA_STATE; + + for (; status == CR_OK;) { + status = cr_parser_parse_ruleset (a_this); + cr_parser_try_to_skip_spaces_and_comments (a_this); + } + + READ_NEXT_CHAR (a_this, &cur_char); + + ENSURE_PARSING_COND (cur_char == '}'); + + /* + *call the right SAC handler api here. + */ + if (PRIVATE (a_this)->sac_handler + && PRIVATE (a_this)->sac_handler->end_media) { + PRIVATE (a_this)->sac_handler->end_media + (PRIVATE (a_this)->sac_handler, media_list); + } + + cr_parser_try_to_skip_spaces_and_comments (a_this); + + /* + *Then, free the data structures passed to + *the last call to the SAC handler. + */ + if (medium) { + cr_string_destroy (medium); + medium = NULL; + } + + if (media_list) { + GList *cur = NULL; + + for (cur = media_list; cur; cur = cur->next) { + cr_string_destroy (cur->data); + } + + g_list_free (media_list); + media_list = NULL; + } + + cr_parser_clear_errors (a_this); + PRIVATE (a_this)->state = MEDIA_PARSED_STATE; + + return CR_OK; + + error: + + if (token) { + cr_token_destroy (token); + token = NULL; + } + + if (medium) { + cr_string_destroy (medium); + medium = NULL; + } + + if (media_list) { + GList *cur = NULL; + + for (cur = media_list; cur; cur = cur->next) { + cr_string_destroy (cur->data); + } + + g_list_free (media_list); + media_list = NULL; + } + + cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos); + + return status; +} + +/** + * cr_parser_parse_page: + *@a_this: the "this pointer" of the current instance of #CRParser. + * + *Parses '@page' rule as specified in the css2 spec in appendix D.1: + *page ::= PAGE_SYM S* IDENT? pseudo_page? S* + *'{' S* declaration [ ';' S* declaration ]* '}' S* + * + *This function also calls the relevant SAC handlers whenever it + *encounters a construction that must + *be reported to the calling application. + * + *Returns CR_OK upon successfull completion, an error code otherwise. + */ +enum CRStatus +cr_parser_parse_page (CRParser * a_this) +{ + enum CRStatus status = CR_OK; + CRInputPos init_pos; + CRToken *token = NULL; + CRTerm *css_expression = NULL; + CRString *page_selector = NULL, + *page_pseudo_class = NULL, + *property = NULL; + gboolean important = TRUE; + CRParsingLocation location = {0} ; + + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); + + RECORD_INITIAL_POS (a_this, &init_pos); + + status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, + &token) ; + ENSURE_PARSING_COND (status == CR_OK + && token + && token->type == PAGE_SYM_TK); + + cr_parsing_location_copy (&location, &token->location) ; + cr_token_destroy (token); + token = NULL; + + cr_parser_try_to_skip_spaces_and_comments (a_this); + + status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token); + ENSURE_PARSING_COND (status == CR_OK && token); + + if (token->type == IDENT_TK) { + page_selector = token->u.str; + token->u.str = NULL; + cr_token_destroy (token); + token = NULL; + } else { + cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, token); + token = NULL; + } + + /* + *try to parse pseudo_page + */ + cr_parser_try_to_skip_spaces_and_comments (a_this); + status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token); + ENSURE_PARSING_COND (status == CR_OK && token); + + if (token->type == DELIM_TK && token->u.unichar == ':') { + cr_token_destroy (token); + token = NULL; + status = cr_parser_parse_ident (a_this, &page_pseudo_class); + CHECK_PARSING_STATUS (status, FALSE); + } else { + cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, token); + token = NULL; + } + + /* + *parse_block + * + */ + cr_parser_try_to_skip_spaces_and_comments (a_this); + + status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token); + + ENSURE_PARSING_COND (status == CR_OK && token + && token->type == CBO_TK); + + cr_token_destroy (token); + token = NULL; + + /* + *Call the appropriate SAC handler here. + */ + if (PRIVATE (a_this)->sac_handler + && PRIVATE (a_this)->sac_handler->start_page) { + PRIVATE (a_this)->sac_handler->start_page + (PRIVATE (a_this)->sac_handler, + page_selector, page_pseudo_class, + &location); + } + cr_parser_try_to_skip_spaces_and_comments (a_this); + + PRIVATE (a_this)->state = TRY_PARSE_PAGE_STATE; + + status = cr_parser_parse_declaration (a_this, &property, + &css_expression, + &important); + ENSURE_PARSING_COND (status == CR_OK); + + /* + *call the relevant SAC handler here... + */ + if (PRIVATE (a_this)->sac_handler + && PRIVATE (a_this)->sac_handler->property) { + if (css_expression) + cr_term_ref (css_expression); + + PRIVATE (a_this)->sac_handler->property + (PRIVATE (a_this)->sac_handler, + property, css_expression, important); + } + /* + *... and free the data structure passed to that last + *SAC handler. + */ + if (property) { + cr_string_destroy (property); + property = NULL; + } + if (css_expression) { + cr_term_unref (css_expression); + css_expression = NULL; + } + + for (;;) { + /*parse the other ';' separated declarations */ + if (token) { + cr_token_destroy (token); + token = NULL; + } + status = cr_tknzr_get_next_token + (PRIVATE (a_this)->tknzr, &token); + + ENSURE_PARSING_COND (status == CR_OK && token); + + if (token->type != SEMICOLON_TK) { + cr_tknzr_unget_token + (PRIVATE (a_this)->tknzr, + token); + token = NULL ; + break; + } + + cr_token_destroy (token); + token = NULL; + cr_parser_try_to_skip_spaces_and_comments (a_this); + + status = cr_parser_parse_declaration (a_this, &property, + &css_expression, + &important); + if (status != CR_OK) + break ; + + /* + *call the relevant SAC handler here... + */ + if (PRIVATE (a_this)->sac_handler + && PRIVATE (a_this)->sac_handler->property) { + cr_term_ref (css_expression); + PRIVATE (a_this)->sac_handler->property + (PRIVATE (a_this)->sac_handler, + property, css_expression, important); + } + /* + *... and free the data structure passed to that last + *SAC handler. + */ + if (property) { + cr_string_destroy (property); + property = NULL; + } + if (css_expression) { + cr_term_unref (css_expression); + css_expression = NULL; + } + } + cr_parser_try_to_skip_spaces_and_comments + (a_this) ; + if (token) { + cr_token_destroy (token) ; + token = NULL ; + } + + status = cr_tknzr_get_next_token + (PRIVATE (a_this)->tknzr, &token); + ENSURE_PARSING_COND (status == CR_OK + && token + && token->type == CBC_TK) ; + cr_token_destroy (token) ; + token = NULL ; + /* + *call the relevant SAC handler here. + */ + if (PRIVATE (a_this)->sac_handler + && PRIVATE (a_this)->sac_handler->end_page) { + PRIVATE (a_this)->sac_handler->end_page + (PRIVATE (a_this)->sac_handler, + page_selector, page_pseudo_class); + } + + if (page_selector) { + cr_string_destroy (page_selector); + page_selector = NULL; + } + + if (page_pseudo_class) { + cr_string_destroy (page_pseudo_class); + page_pseudo_class = NULL; + } + + cr_parser_try_to_skip_spaces_and_comments (a_this); + + /*here goes the former implem of this function ... */ + + cr_parser_clear_errors (a_this); + PRIVATE (a_this)->state = PAGE_PARSED_STATE; + + return CR_OK; + + error: + if (token) { + cr_token_destroy (token); + token = NULL; + } + if (page_selector) { + cr_string_destroy (page_selector); + page_selector = NULL; + } + if (page_pseudo_class) { + cr_string_destroy (page_pseudo_class); + page_pseudo_class = NULL; + } + if (property) { + cr_string_destroy (property); + property = NULL; + } + if (css_expression) { + cr_term_destroy (css_expression); + css_expression = NULL; + } + cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos); + return status; +} + +/** + * cr_parser_parse_charset: + *@a_this: the "this pointer" of the current instance of #CRParser. + *@a_value: out parameter. The actual parsed value of the charset + *declararation. Note that for safety check reasons, *a_value must be + *set to NULL. + *@a_charset_sym_location: the parsing location of the charset rule + * + *Parses a charset declaration as defined implictly by the css2 spec in + *appendix D.1: + *charset ::= CHARSET_SYM S* STRING S* ';' + * + *Returns CR_OK upon successfull completion, an error code otherwise. + */ +enum CRStatus +cr_parser_parse_charset (CRParser * a_this, CRString ** a_value, + CRParsingLocation *a_charset_sym_location) +{ + enum CRStatus status = CR_OK; + CRInputPos init_pos; + CRToken *token = NULL; + CRString *charset_str = NULL; + + g_return_val_if_fail (a_this && a_value + && (*a_value == NULL), + CR_BAD_PARAM_ERROR); + + RECORD_INITIAL_POS (a_this, &init_pos); + + status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token); + + ENSURE_PARSING_COND (status == CR_OK + && token && token->type == CHARSET_SYM_TK); + if (a_charset_sym_location) { + cr_parsing_location_copy (a_charset_sym_location, + &token->location) ; + } + cr_token_destroy (token); + token = NULL; + + PRIVATE (a_this)->state = TRY_PARSE_CHARSET_STATE; + + cr_parser_try_to_skip_spaces_and_comments (a_this); + + status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token); + ENSURE_PARSING_COND (status == CR_OK + && token && token->type == STRING_TK); + charset_str = token->u.str; + token->u.str = NULL; + cr_token_destroy (token); + token = NULL; + + cr_parser_try_to_skip_spaces_and_comments (a_this); + + status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token); + + ENSURE_PARSING_COND (status == CR_OK + && token && token->type == SEMICOLON_TK); + cr_token_destroy (token); + token = NULL; + + if (charset_str) { + *a_value = charset_str; + charset_str = NULL; + } + + PRIVATE (a_this)->state = CHARSET_PARSED_STATE; + return CR_OK; + + error: + + if (token) { + cr_token_destroy (token); + token = NULL; + } + + if (*a_value) { + cr_string_destroy (*a_value); + *a_value = NULL; + } + + if (charset_str) { + cr_string_destroy (charset_str); + charset_str = NULL; + } + + cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos); + + return status; +} + +/** + * cr_parser_parse_font_face: + *@a_this: the current instance of #CRParser. + * + *Parses the "@font-face" rule specified in the css1 spec in + *appendix D.1: + * + *font_face ::= FONT_FACE_SYM S* + *'{' S* declaration [ ';' S* declaration ]* '}' S* + * + *This function will call SAC handlers whenever it is necessary. + * + *Returns CR_OK upon successfull completion, an error code otherwise. + */ +enum CRStatus +cr_parser_parse_font_face (CRParser * a_this) +{ + enum CRStatus status = CR_ERROR; + CRInputPos init_pos; + CRString *property = NULL; + CRTerm *css_expression = NULL; + CRToken *token = NULL; + gboolean important = FALSE; + guint32 next_char = 0, + cur_char = 0; + CRParsingLocation location = {0} ; + + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); + + RECORD_INITIAL_POS (a_this, &init_pos); + + status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token); + ENSURE_PARSING_COND (status == CR_OK + && token + && token->type == FONT_FACE_SYM_TK); + + cr_parser_try_to_skip_spaces_and_comments (a_this); + if (token) { + cr_parsing_location_copy (&location, + &token->location) ; + cr_token_destroy (token); + token = NULL; + } + status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, + &token); + ENSURE_PARSING_COND (status == CR_OK && token + && token->type == CBO_TK); + if (token) { + cr_token_destroy (token); + token = NULL; + } + /* + *here, call the relevant SAC handler. + */ + if (PRIVATE (a_this)->sac_handler + && PRIVATE (a_this)->sac_handler->start_font_face) { + PRIVATE (a_this)->sac_handler->start_font_face + (PRIVATE (a_this)->sac_handler, &location); + } + PRIVATE (a_this)->state = TRY_PARSE_FONT_FACE_STATE; + /* + *and resume the parsing. + */ + cr_parser_try_to_skip_spaces_and_comments (a_this); + status = cr_parser_parse_declaration (a_this, &property, + &css_expression, &important); + if (status == CR_OK) { + /* + *here, call the relevant SAC handler. + */ + cr_term_ref (css_expression); + if (PRIVATE (a_this)->sac_handler && + PRIVATE (a_this)->sac_handler->property) { + PRIVATE (a_this)->sac_handler->property + (PRIVATE (a_this)->sac_handler, + property, css_expression, important); + } + ENSURE_PARSING_COND (css_expression && property); + } + /*free the data structures allocated during last parsing. */ + if (property) { + cr_string_destroy (property); + property = NULL; + } + if (css_expression) { + cr_term_unref (css_expression); + css_expression = NULL; + } + for (;;) { + PEEK_NEXT_CHAR (a_this, &next_char); + if (next_char == ';') { + READ_NEXT_CHAR (a_this, &cur_char); + } else { + break; + } + cr_parser_try_to_skip_spaces_and_comments (a_this); + status = cr_parser_parse_declaration (a_this, + &property, + &css_expression, + &important); + if (status != CR_OK) + break; + /* + *here, call the relevant SAC handler. + */ + cr_term_ref (css_expression); + if (PRIVATE (a_this)->sac_handler->property) { + PRIVATE (a_this)->sac_handler->property + (PRIVATE (a_this)->sac_handler, + property, css_expression, important); + } + /* + *Then, free the data structures allocated during + *last parsing. + */ + if (property) { + cr_string_destroy (property); + property = NULL; + } + if (css_expression) { + cr_term_unref (css_expression); + css_expression = NULL; + } + } + cr_parser_try_to_skip_spaces_and_comments (a_this); + READ_NEXT_CHAR (a_this, &cur_char); + ENSURE_PARSING_COND (cur_char == '}'); + /* + *here, call the relevant SAC handler. + */ + if (PRIVATE (a_this)->sac_handler->end_font_face) { + PRIVATE (a_this)->sac_handler->end_font_face + (PRIVATE (a_this)->sac_handler); + } + cr_parser_try_to_skip_spaces_and_comments (a_this); + + if (token) { + cr_token_destroy (token); + token = NULL; + } + cr_parser_clear_errors (a_this); + PRIVATE (a_this)->state = FONT_FACE_PARSED_STATE; + return CR_OK; + + error: + if (token) { + cr_token_destroy (token); + token = NULL; + } + if (property) { + cr_string_destroy (property); + property = NULL; + } + if (css_expression) { + cr_term_destroy (css_expression); + css_expression = NULL; + } + cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos); + return status; +} + +/** + * cr_parser_parse: + *@a_this: the current instance of #CRParser. + * + *Parses the data that comes from the + *input previously associated to the current instance of + *#CRParser. + * + *Returns CR_OK upon succesful completion, an error code otherwise. + */ +enum CRStatus +cr_parser_parse (CRParser * a_this) +{ + enum CRStatus status = CR_ERROR; + + g_return_val_if_fail (a_this && PRIVATE (a_this) + && PRIVATE (a_this)->tknzr, CR_BAD_PARAM_ERROR); + + if (PRIVATE (a_this)->use_core_grammar == FALSE) { + status = cr_parser_parse_stylesheet (a_this); + } else { + status = cr_parser_parse_stylesheet_core (a_this); + } + + return status; +} + +/** + * cr_parser_set_tknzr: + * @a_this: the current instance of #CRParser; + * @a_tknzr: the new tokenizer. + * + * Returns CR_OK upon successful completion, an error code otherwise. + */ +enum CRStatus +cr_parser_set_tknzr (CRParser * a_this, CRTknzr * a_tknzr) +{ + g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR); + + if (PRIVATE (a_this)->tknzr) { + cr_tknzr_unref (PRIVATE (a_this)->tknzr); + } + + PRIVATE (a_this)->tknzr = a_tknzr; + + if (a_tknzr) + cr_tknzr_ref (a_tknzr); + + return CR_OK; +} + +/** + * cr_parser_get_tknzr: + *@a_this: the current instance of #CRParser + *@a_tknzr: out parameter. The returned tokenizer + * + *Getter of the parser's underlying tokenizer + * + *Returns CR_OK upon succesful completion, an error code + *otherwise + */ +enum CRStatus +cr_parser_get_tknzr (CRParser * a_this, CRTknzr ** a_tknzr) +{ + g_return_val_if_fail (a_this && PRIVATE (a_this) + && a_tknzr, CR_BAD_PARAM_ERROR); + + *a_tknzr = PRIVATE (a_this)->tknzr; + return CR_OK; +} + +/** + * cr_parser_get_parsing_location: + *@a_this: the current instance of #CRParser + *@a_loc: the parsing location to get. + * + *Gets the current parsing location. + * + *Returns CR_OK upon succesful completion, an error code + *otherwise. + */ +enum CRStatus +cr_parser_get_parsing_location (CRParser *a_this, + CRParsingLocation *a_loc) +{ + g_return_val_if_fail (a_this + && PRIVATE (a_this) + && a_loc, CR_BAD_PARAM_ERROR) ; + + return cr_tknzr_get_parsing_location + (PRIVATE (a_this)->tknzr, a_loc) ; +} + +/** + * cr_parser_parse_buf: + *@a_this: the current instance of #CRparser + *@a_buf: the input buffer + *@a_len: the length of the input buffer + *@a_enc: the encoding of the buffer + * + *Parses a stylesheet from a buffer + * + *Returns CR_OK upon successful completion, an error code otherwise. + */ +enum CRStatus +cr_parser_parse_buf (CRParser * a_this, + const guchar * a_buf, + gulong a_len, enum CREncoding a_enc) +{ + enum CRStatus status = CR_ERROR; + CRTknzr *tknzr = NULL; + + g_return_val_if_fail (a_this && PRIVATE (a_this) + && a_buf, CR_BAD_PARAM_ERROR); + + tknzr = cr_tknzr_new_from_buf ((guchar*)a_buf, a_len, a_enc, FALSE); + + g_return_val_if_fail (tknzr != NULL, CR_ERROR); + + status = cr_parser_set_tknzr (a_this, tknzr); + g_return_val_if_fail (status == CR_OK, CR_ERROR); + + status = cr_parser_parse (a_this); + + return status; +} + +/** + * cr_parser_destroy: + *@a_this: the current instance of #CRParser to + *destroy. + * + *Destroys the current instance + *of #CRParser. + */ +void +cr_parser_destroy (CRParser * a_this) +{ + g_return_if_fail (a_this && PRIVATE (a_this)); + + if (PRIVATE (a_this)->tknzr) { + if (cr_tknzr_unref (PRIVATE (a_this)->tknzr) == TRUE) + PRIVATE (a_this)->tknzr = NULL; + } + + if (PRIVATE (a_this)->sac_handler) { + cr_doc_handler_unref (PRIVATE (a_this)->sac_handler); + PRIVATE (a_this)->sac_handler = NULL; + } + + if (PRIVATE (a_this)->err_stack) { + cr_parser_clear_errors (a_this); + PRIVATE (a_this)->err_stack = NULL; + } + + if (PRIVATE (a_this)) { + g_free (PRIVATE (a_this)); + PRIVATE (a_this) = NULL; + } + + if (a_this) { + g_free (a_this); + a_this = NULL; /*useless. Just for the sake of coherence */ + } +} diff --git a/gettext-tools/gnulib-lib/libcroco/cr-parser.h b/gettext-tools/gnulib-lib/libcroco/cr-parser.h new file mode 100644 index 0000000..a1337d6 --- /dev/null +++ b/gettext-tools/gnulib-lib/libcroco/cr-parser.h @@ -0,0 +1,128 @@ +/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */ + +/* + * This file is part of The Croco Library + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + * Author: Dodji Seketeli + * See COPYRIGHTS file for copyrights information. + */ + +#ifndef __CR_PARSER_H__ +#define __CR_PARSER_H__ + +#include +#include "cr-input.h" +#include "cr-tknzr.h" +#include "cr-utils.h" +#include "cr-doc-handler.h" + +G_BEGIN_DECLS + +/** + *@file + *The declaration file + *of the #CRParser class. + */ +typedef struct _CRParser CRParser ; +typedef struct _CRParserPriv CRParserPriv ; + + +/** + *The implementation of + *the SAC parser. + *The Class is opaque + *and must be manipulated through + *the provided methods. + */ +struct _CRParser { + CRParserPriv *priv ; +} ; + + +CRParser * cr_parser_new (CRTknzr *a_tknzr) ; + +CRParser * cr_parser_new_from_buf (guchar *a_buf, gulong a_len, + enum CREncoding a_enc, + gboolean a_free_buf) ; + +CRParser * cr_parser_new_from_file (const guchar *a_file_uri, + enum CREncoding a_enc) ; + +CRParser * cr_parser_new_from_input (CRInput *a_input) ; + +enum CRStatus cr_parser_set_tknzr (CRParser *a_this, CRTknzr *a_tknzr) ; + +enum CRStatus cr_parser_get_tknzr (CRParser *a_this, CRTknzr **a_tknzr) ; + +enum CRStatus cr_parser_get_parsing_location (CRParser *a_this, CRParsingLocation *a_loc) ; + +enum CRStatus cr_parser_try_to_skip_spaces_and_comments (CRParser *a_this) ; + + +enum CRStatus cr_parser_set_sac_handler (CRParser *a_this, + CRDocHandler *a_handler) ; + +enum CRStatus cr_parser_get_sac_handler (CRParser *a_this, + CRDocHandler **a_handler) ; + +enum CRStatus cr_parser_set_use_core_grammar (CRParser *a_this, + gboolean a_use_core_grammar) ; +enum CRStatus cr_parser_get_use_core_grammar (CRParser *a_this, + gboolean *a_use_core_grammar) ; + +enum CRStatus cr_parser_parse (CRParser *a_this) ; + +enum CRStatus cr_parser_parse_file (CRParser *a_this, + const guchar *a_file_uri, + enum CREncoding a_enc) ; + +enum CRStatus cr_parser_parse_buf (CRParser *a_this, const guchar *a_buf, + gulong a_len, enum CREncoding a_enc) ; + +enum CRStatus cr_parser_set_default_sac_handler (CRParser *a_this) ; + +enum CRStatus cr_parser_parse_term (CRParser *a_this, CRTerm **a_term) ; + +enum CRStatus cr_parser_parse_expr (CRParser *a_this, CRTerm **a_expr) ; + +enum CRStatus cr_parser_parse_prio (CRParser *a_this, CRString **a_prio) ; + +enum CRStatus cr_parser_parse_declaration (CRParser *a_this, CRString **a_property, + CRTerm **a_expr, gboolean *a_important) ; + +enum CRStatus cr_parser_parse_statement_core (CRParser *a_this) ; + +enum CRStatus cr_parser_parse_ruleset (CRParser *a_this) ; + +enum CRStatus cr_parser_parse_import (CRParser *a_this, GList ** a_media_list, + CRString **a_import_string, + CRParsingLocation *a_location) ; + +enum CRStatus cr_parser_parse_media (CRParser *a_this) ; + +enum CRStatus cr_parser_parse_page (CRParser *a_this) ; + +enum CRStatus cr_parser_parse_charset (CRParser *a_this, CRString **a_value, + CRParsingLocation *a_charset_sym_location) ; + +enum CRStatus cr_parser_parse_font_face (CRParser *a_this) ; + +void cr_parser_destroy (CRParser *a_this) ; + +G_END_DECLS + +#endif /*__CR_PARSER_H__*/ diff --git a/gettext-tools/gnulib-lib/libcroco/cr-parsing-location.c b/gettext-tools/gnulib-lib/libcroco/cr-parsing-location.c new file mode 100644 index 0000000..1236083 --- /dev/null +++ b/gettext-tools/gnulib-lib/libcroco/cr-parsing-location.c @@ -0,0 +1,173 @@ +/* -*- Mode: C; indent-tabs-mode: ni; c-basic-offset: 8 -*- */ + +/* + * This file is part of The Croco Library + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + * Author: Dodji Seketeli. + * See the COPYRIGHTS file for copyright information. + */ + +#include +#include +#include "cr-parsing-location.h" + +/** + *@CRParsingLocation: + * + *Definition of the #CRparsingLocation class. + */ + + +/** + * cr_parsing_location_new: + *Instanciates a new parsing location. + * + *Returns the newly instanciated #CRParsingLocation. + *Must be freed by cr_parsing_location_destroy() + */ +CRParsingLocation * +cr_parsing_location_new (void) +{ + CRParsingLocation * result = NULL ; + + result = g_try_malloc (sizeof (CRParsingLocation)) ; + if (!result) { + cr_utils_trace_info ("Out of memory error") ; + return NULL ; + } + cr_parsing_location_init (result) ; + return result ; +} + +/** + * cr_parsing_location_init: + *@a_this: the current instance of #CRParsingLocation. + * + *Initializes the an instance of #CRparsingLocation. + * + *Returns CR_OK upon succesful completion, an error code otherwise. + */ +enum CRStatus +cr_parsing_location_init (CRParsingLocation *a_this) +{ + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR) ; + + memset (a_this, 0, sizeof (CRParsingLocation)) ; + return CR_OK ; +} + +/** + * cr_parsing_location_copy: + *@a_to: the destination of the copy. + *Must be allocated by the caller. + *@a_from: the source of the copy. + * + *Copies an instance of CRParsingLocation into another one. + * + *Returns CR_OK upon succesful completion, an error code + *otherwise. + */ +enum CRStatus +cr_parsing_location_copy (CRParsingLocation *a_to, + CRParsingLocation *a_from) +{ + g_return_val_if_fail (a_to && a_from, CR_BAD_PARAM_ERROR) ; + + memcpy (a_to, a_from, sizeof (CRParsingLocation)) ; + return CR_OK ; +} + +/** + * cr_parsing_location_to_string: + *@a_this: the current instance of #CRParsingLocation. + *@a_mask: a bitmap that defines which parts of the + *parsing location are to be serialized (line, column or byte offset) + * + *Returns the serialized string or NULL in case of an error. + */ +gchar * +cr_parsing_location_to_string (CRParsingLocation *a_this, + enum CRParsingLocationSerialisationMask a_mask) +{ + GString *result = NULL ; + gchar *str = NULL ; + + g_return_val_if_fail (a_this, NULL) ; + + if (!a_mask) { + a_mask = DUMP_LINE | DUMP_COLUMN | DUMP_BYTE_OFFSET ; + } + result =g_string_new (NULL) ; + if (!result) + return NULL ; + if (a_mask & DUMP_LINE) { + g_string_append_printf (result, "line:%d ", + a_this->line) ; + } + if (a_mask & DUMP_COLUMN) { + g_string_append_printf (result, "column:%d ", + a_this->column) ; + } + if (a_mask & DUMP_BYTE_OFFSET) { + g_string_append_printf (result, "byte offset:%d ", + a_this->byte_offset) ; + } + if (result->len) { + str = result->str ; + g_string_free (result, FALSE) ; + } else { + g_string_free (result, TRUE) ; + } + return str ; +} + +/** + * cr_parsing_location_dump: + * @a_this: current instance of #CRParsingLocation + * @a_mask: the serialization mask. + * @a_fp: the file pointer to dump the parsing location to. + */ +void +cr_parsing_location_dump (CRParsingLocation *a_this, + enum CRParsingLocationSerialisationMask a_mask, + FILE *a_fp) +{ + gchar *str = NULL ; + + g_return_if_fail (a_this && a_fp) ; + str = cr_parsing_location_to_string (a_this, a_mask) ; + if (str) { + fprintf (a_fp, "%s", str) ; + g_free (str) ; + str = NULL ; + } +} + +/** + * cr_parsing_location_destroy: + *@a_this: the current instance of #CRParsingLocation. Must + *have been allocated with cr_parsing_location_new(). + * + *Destroys the current instance of #CRParsingLocation + */ +void +cr_parsing_location_destroy (CRParsingLocation *a_this) +{ + g_return_if_fail (a_this) ; + g_free (a_this) ; +} + diff --git a/gettext-tools/gnulib-lib/libcroco/cr-parsing-location.h b/gettext-tools/gnulib-lib/libcroco/cr-parsing-location.h new file mode 100644 index 0000000..8153908 --- /dev/null +++ b/gettext-tools/gnulib-lib/libcroco/cr-parsing-location.h @@ -0,0 +1,70 @@ +/* -*- Mode: C; indent-tabs-mode: ni; c-basic-offset: 8 -*- */ + +/* + * This file is part of The Croco Library + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + * Author: Dodji Seketeli. + * See the COPYRIGHTS file for copyright information. + */ + +#ifndef __CR_PARSING_LOCATION_H__ +#define __CR_PARSING_LOCATION_H__ + +#include "cr-utils.h" + +G_BEGIN_DECLS + +/** + *@file + *The declaration of the CRParsingLocation + *object. This object keeps track of line/column/byte offset/ + *at which the parsing of a given CSS construction appears. + */ + +typedef struct _CRParsingLocation CRParsingLocation; +struct _CRParsingLocation { + guint line ; + guint column ; + guint byte_offset ; +} ; + + +enum CRParsingLocationSerialisationMask { + DUMP_LINE = 1, + DUMP_COLUMN = 1 << 1, + DUMP_BYTE_OFFSET = 1 << 2 +} ; + +CRParsingLocation * cr_parsing_location_new (void) ; + +enum CRStatus cr_parsing_location_init (CRParsingLocation *a_this) ; + +enum CRStatus cr_parsing_location_copy (CRParsingLocation *a_to, + CRParsingLocation *a_from) ; + +gchar * cr_parsing_location_to_string (CRParsingLocation *a_this, + enum CRParsingLocationSerialisationMask a_mask) ; +void cr_parsing_location_dump (CRParsingLocation *a_this, + enum CRParsingLocationSerialisationMask a_mask, + FILE *a_fp) ; + +void cr_parsing_location_destroy (CRParsingLocation *a_this) ; + + + +G_END_DECLS +#endif diff --git a/gettext-tools/gnulib-lib/libcroco/cr-prop-list.c b/gettext-tools/gnulib-lib/libcroco/cr-prop-list.c new file mode 100644 index 0000000..d9c1038 --- /dev/null +++ b/gettext-tools/gnulib-lib/libcroco/cr-prop-list.c @@ -0,0 +1,402 @@ +/* + * This file is part of The Croco Library + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + * Author: Dodji Seketeli + * See COPYRIGHTS file for copyrights information. + */ + +#include +#include +#include "cr-prop-list.h" + +#define PRIVATE(a_obj) (a_obj)->priv + +struct _CRPropListPriv { + CRString *prop; + CRDeclaration *decl; + CRPropList *next; + CRPropList *prev; +}; + +static CRPropList *cr_prop_list_allocate (void); + +/** + *Default allocator of CRPropList + *@return the newly allocated CRPropList or NULL + *if an error arises. + */ +static CRPropList * +cr_prop_list_allocate (void) +{ + CRPropList *result = NULL; + + result = g_try_malloc (sizeof (CRPropList)); + if (!result) { + cr_utils_trace_info ("could not allocate CRPropList"); + return NULL; + } + memset (result, 0, sizeof (CRPropList)); + PRIVATE (result) = g_try_malloc (sizeof (CRPropListPriv)); + if (!result) { + cr_utils_trace_info ("could not allocate CRPropListPriv"); + g_free (result); + return NULL; + } + memset (PRIVATE (result), 0, sizeof (CRPropListPriv)); + return result; +} + +/**************** + *public methods + ***************/ + +/** + * cr_prop_list_append: + *@a_this: the current instance of #CRPropList + *@a_to_append: the property list to append + * + *Appends a property list to the current one. + * + *Returns the resulting prop list, or NULL if an error + *occured + */ +CRPropList * +cr_prop_list_append (CRPropList * a_this, CRPropList * a_to_append) +{ + CRPropList *cur = NULL; + + g_return_val_if_fail (a_to_append, NULL); + + if (!a_this) + return a_to_append; + + /*go fetch the last element of the list */ + for (cur = a_this; + cur && PRIVATE (cur) && PRIVATE (cur)->next; + cur = PRIVATE (cur)->next) ; + g_return_val_if_fail (cur, NULL); + PRIVATE (cur)->next = a_to_append; + PRIVATE (a_to_append)->prev = cur; + return a_this; +} + +/** + * cr_prop_list_append2: + *Appends a pair of prop/declaration to + *the current prop list. + *@a_this: the current instance of #CRPropList + *@a_prop: the property to consider + *@a_decl: the declaration to consider + *Returns the resulting property list, or NULL in case + *of an error. + */ +CRPropList * +cr_prop_list_append2 (CRPropList * a_this, + CRString * a_prop, + CRDeclaration * a_decl) +{ + CRPropList *list = NULL, + *result = NULL; + + g_return_val_if_fail (a_prop && a_decl, NULL); + + list = cr_prop_list_allocate (); + g_return_val_if_fail (list && PRIVATE (list), NULL); + + PRIVATE (list)->prop = a_prop; + PRIVATE (list)->decl = a_decl; + + result = cr_prop_list_append (a_this, list); + return result; +} + +/** + * cr_prop_list_prepend: + *@a_this: the current instance of #CRPropList + *@a_to_prepend: the new list to prepend. + * + *Prepends a list to the current list + *Returns the new properties list. + */ +CRPropList * +cr_prop_list_prepend (CRPropList * a_this, CRPropList * a_to_prepend) +{ + CRPropList *cur = NULL; + + g_return_val_if_fail (a_to_prepend, NULL); + + if (!a_this) + return a_to_prepend; + + for (cur = a_to_prepend; cur && PRIVATE (cur)->next; + cur = PRIVATE (cur)->next) ; + g_return_val_if_fail (cur, NULL); + PRIVATE (cur)->next = a_this; + PRIVATE (a_this)->prev = cur; + return a_to_prepend; +} + +/** + * cr_prop_list_prepend2: + *@a_this: the current instance of #CRPropList + *@a_prop_name: property name to append + *@a_decl: the property value to append. + * + *Prepends a propertie to a list of properties + * + * Returns the new property list. + */ +CRPropList * +cr_prop_list_prepend2 (CRPropList * a_this, + CRString * a_prop_name, CRDeclaration * a_decl) +{ + CRPropList *list = NULL, + *result = NULL; + + g_return_val_if_fail (a_this && PRIVATE (a_this) + && a_prop_name && a_decl, NULL); + + list = cr_prop_list_allocate (); + g_return_val_if_fail (list, NULL); + PRIVATE (list)->prop = a_prop_name; + PRIVATE (list)->decl = a_decl; + result = cr_prop_list_prepend (a_this, list); + return result; +} + +/** + * cr_prop_list_set_prop: + *@a_this: the current instance of #CRPropList + *@a_prop: the property to set + * + *Sets the property of a CRPropList + */ +enum CRStatus +cr_prop_list_set_prop (CRPropList * a_this, CRString * a_prop) +{ + g_return_val_if_fail (a_this && PRIVATE (a_this) + && a_prop, CR_BAD_PARAM_ERROR); + + PRIVATE (a_this)->prop = a_prop; + return CR_OK; +} + +/** + * cr_prop_list_get_prop: + *@a_this: the current instance of #CRPropList + *@a_prop: out parameter. The returned property + * + *Getter of the property associated to the current instance + *of #CRPropList + * + *Returns CR_OK upon successful completion, an error code + *otherwise. + */ +enum CRStatus +cr_prop_list_get_prop (CRPropList * a_this, CRString ** a_prop) +{ + g_return_val_if_fail (a_this && PRIVATE (a_this) + && a_prop, CR_BAD_PARAM_ERROR); + + *a_prop = PRIVATE (a_this)->prop; + return CR_OK; +} + +/** + * cr_prop_list_set_decl: + * @a_this: the current instance of #CRPropList + * @a_decl: the new property value. + * Returns CR_OK upon successful completion, an error code otherwise. + */ +enum CRStatus +cr_prop_list_set_decl (CRPropList * a_this, CRDeclaration * a_decl) +{ + g_return_val_if_fail (a_this && PRIVATE (a_this) + && a_decl, CR_BAD_PARAM_ERROR); + + PRIVATE (a_this)->decl = a_decl; + return CR_OK; +} + +/** + * cr_prop_list_get_decl: + * @a_this: the current instance of #CRPropList + * @a_decl: out parameter. The property value + * Returns CR_OK upon successful completion. + */ +enum CRStatus +cr_prop_list_get_decl (CRPropList * a_this, CRDeclaration ** a_decl) +{ + g_return_val_if_fail (a_this && PRIVATE (a_this) + && a_decl, CR_BAD_PARAM_ERROR); + + *a_decl = PRIVATE (a_this)->decl; + return CR_OK; +} + +/** + * cr_prop_list_lookup_prop: + *@a_this: the current instance of #CRPropList + *@a_prop: the property to lookup + *@a_prop_list: out parameter. The property/declaration + *pair found (if and only if the function returned code if CR_OK) + * + *Lookup a given property/declaration pair + * + *Returns CR_OK if a prop/decl pair has been found, + *CR_VALUE_NOT_FOUND_ERROR if not, or an error code if something + *bad happens. + */ +enum CRStatus +cr_prop_list_lookup_prop (CRPropList * a_this, + CRString * a_prop, CRPropList ** a_pair) +{ + CRPropList *cur = NULL; + + g_return_val_if_fail (a_prop && a_pair, CR_BAD_PARAM_ERROR); + + if (!a_this) + return CR_VALUE_NOT_FOUND_ERROR; + + g_return_val_if_fail (PRIVATE (a_this), CR_BAD_PARAM_ERROR); + + for (cur = a_this; cur; cur = PRIVATE (cur)->next) { + if (PRIVATE (cur)->prop + && PRIVATE (cur)->prop->stryng + && PRIVATE (cur)->prop->stryng->str + && a_prop->stryng + && a_prop->stryng->str + && !strcmp (PRIVATE (cur)->prop->stryng->str, + a_prop->stryng->str)) + break; + } + + if (cur) { + *a_pair = cur; + return CR_OK; + } + + return CR_VALUE_NOT_FOUND_ERROR; +} + +/** + * cr_prop_list_get_next: + *@a_this: the current instance of CRPropList + * + *Gets the next prop/decl pair in the list + * + *Returns the next prop/declaration pair of the list, + *or NULL if we reached end of list (or if an error occurs) + */ +CRPropList * +cr_prop_list_get_next (CRPropList * a_this) +{ + g_return_val_if_fail (a_this && PRIVATE (a_this), NULL); + + return PRIVATE (a_this)->next; +} + +/** + * cr_prop_list_get_prev: + *@a_this: the current instance of CRPropList + * + *Gets the previous prop/decl pair in the list + * + *Returns the previous prop/declaration pair of the list, + *or NULL if we reached end of list (or if an error occurs) + */ +CRPropList * +cr_prop_list_get_prev (CRPropList * a_this) +{ + g_return_val_if_fail (a_this && PRIVATE (a_this), NULL); + + return PRIVATE (a_this)->prev; +} + +/** + * cr_prop_list_unlink: + *@a_this: the current list of prop/decl pairs + *@a_pair: the prop/decl pair to unlink. + * + *Unlinks a prop/decl pair from the list + * + *Returns the new list or NULL in case of an error. + */ +CRPropList * +cr_prop_list_unlink (CRPropList * a_this, CRPropList * a_pair) +{ + CRPropList *prev = NULL, + *next = NULL; + + g_return_val_if_fail (a_this && PRIVATE (a_this) && a_pair, NULL); + + /*some sanity checks */ + if (PRIVATE (a_pair)->next) { + next = PRIVATE (a_pair)->next; + g_return_val_if_fail (PRIVATE (next), NULL); + g_return_val_if_fail (PRIVATE (next)->prev == a_pair, NULL); + } + if (PRIVATE (a_pair)->prev) { + prev = PRIVATE (a_pair)->prev; + g_return_val_if_fail (PRIVATE (prev), NULL); + g_return_val_if_fail (PRIVATE (prev)->next == a_pair, NULL); + } + if (prev) { + PRIVATE (prev)->next = next; + } + if (next) { + PRIVATE (next)->prev = prev; + } + PRIVATE (a_pair)->prev = PRIVATE (a_pair)->next = NULL; + if (a_this == a_pair) { + if (next) + return next; + return NULL; + } + return a_this; +} + +/** + * cr_prop_list_detroy: + * @a_this: the current instance of #CRPropList + */ +void +cr_prop_list_destroy (CRPropList * a_this) +{ + CRPropList *tail = NULL, + *cur = NULL; + + g_return_if_fail (a_this && PRIVATE (a_this)); + + for (tail = a_this; + tail && PRIVATE (tail) && PRIVATE (tail)->next; + tail = cr_prop_list_get_next (tail)) ; + g_return_if_fail (tail); + + cur = tail; + + while (cur) { + tail = PRIVATE (cur)->prev; + if (tail && PRIVATE (tail)) + PRIVATE (tail)->next = NULL; + PRIVATE (cur)->prev = NULL; + g_free (PRIVATE (cur)); + PRIVATE (cur) = NULL; + g_free (cur); + cur = tail; + } +} diff --git a/gettext-tools/gnulib-lib/libcroco/cr-prop-list.h b/gettext-tools/gnulib-lib/libcroco/cr-prop-list.h new file mode 100644 index 0000000..ff6ab8d --- /dev/null +++ b/gettext-tools/gnulib-lib/libcroco/cr-prop-list.h @@ -0,0 +1,80 @@ +/* + * This file is part of The Croco Library + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + * Author: Dodji Seketeli + * See COPYRIGHTS file for copyrights information. + */ + +#ifndef __CR_PROP_LIST_H__ +#define __CR_PROP_LIST_H__ + +#include "cr-utils.h" +#include "cr-declaration.h" +#include "cr-string.h" + +G_BEGIN_DECLS + +typedef struct _CRPropList CRPropList ; +typedef struct _CRPropListPriv CRPropListPriv ; + +struct _CRPropList +{ + CRPropListPriv * priv; +} ; + +CRPropList * cr_prop_list_append (CRPropList *a_this, + CRPropList *a_to_append) ; + +CRPropList * cr_prop_list_append2 (CRPropList *a_this, + CRString *a_prop, + CRDeclaration *a_decl) ; + +CRPropList * cr_prop_list_prepend (CRPropList *a_this, + CRPropList *a_to_append) ; + +CRPropList * cr_prop_list_prepend2 (CRPropList *a_this, + CRString *a_prop, + CRDeclaration *a_decl) ; + +enum CRStatus cr_prop_list_set_prop (CRPropList *a_this, + CRString *a_prop) ; + +enum CRStatus cr_prop_list_get_prop (CRPropList *a_this, + CRString **a_prop) ; + +enum CRStatus cr_prop_list_lookup_prop (CRPropList *a_this, + CRString *a_prop, + CRPropList**a_pair) ; + +CRPropList * cr_prop_list_get_next (CRPropList *a_this) ; + +CRPropList * cr_prop_list_get_prev (CRPropList *a_this) ; + +enum CRStatus cr_prop_list_set_decl (CRPropList *a_this, + CRDeclaration *a_decl); + +enum CRStatus cr_prop_list_get_decl (CRPropList *a_this, + CRDeclaration **a_decl) ; + +CRPropList * cr_prop_list_unlink (CRPropList *a_this, + CRPropList *a_pair) ; + +void cr_prop_list_destroy (CRPropList *a_this) ; + +G_END_DECLS + +#endif /*__CR_PROP_LIST_H__*/ diff --git a/gettext-tools/gnulib-lib/libcroco/cr-pseudo.c b/gettext-tools/gnulib-lib/libcroco/cr-pseudo.c new file mode 100644 index 0000000..0b46b02 --- /dev/null +++ b/gettext-tools/gnulib-lib/libcroco/cr-pseudo.c @@ -0,0 +1,167 @@ +/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */ + +/* + * This file is part of The Croco Library + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + * Author: Dodji Seketeli + * See COPYRIGHTS file for copyright information. + */ + +#include +#include "cr-pseudo.h" + +/** + *@CRPseudo: + *The definition of the #CRPseudo class. + */ + +/** + * cr_pseudo_new: + *Constructor of the #CRPseudo class. + * + *Returns the newly build instance. + */ +CRPseudo * +cr_pseudo_new (void) +{ + CRPseudo *result = NULL; + + result = g_malloc0 (sizeof (CRPseudo)); + + return result; +} + +/** + * cr_pseudo_to_string: + * @a_this: the current instance of #CRPseud. + * Returns the serialized pseudo. Caller must free the returned + * string using g_free(). + */ +guchar * +cr_pseudo_to_string (CRPseudo * a_this) +{ + guchar *result = NULL; + GString *str_buf = NULL; + + g_return_val_if_fail (a_this, NULL); + + str_buf = g_string_new (NULL); + + if (a_this->type == IDENT_PSEUDO) { + guchar *name = NULL; + + if (a_this->name == NULL) { + goto error; + } + + name = g_strndup (a_this->name->stryng->str, + a_this->name->stryng->len); + + if (name) { + g_string_append (str_buf, name); + g_free (name); + name = NULL; + } + } else if (a_this->type == FUNCTION_PSEUDO) { + guchar *name = NULL, + *arg = NULL; + + if (a_this->name == NULL) + goto error; + + name = g_strndup (a_this->name->stryng->str, + a_this->name->stryng->len); + + if (a_this->extra) { + arg = g_strndup (a_this->extra->stryng->str, + a_this->extra->stryng->len); + } + + if (name) { + g_string_append_printf (str_buf, "%s(", name); + g_free (name); + name = NULL; + + if (arg) { + g_string_append (str_buf, arg); + g_free (arg); + arg = NULL; + } + + g_string_append_c (str_buf, ')'); + } + } + + if (str_buf) { + result = str_buf->str; + g_string_free (str_buf, FALSE); + str_buf = NULL; + } + + return result; + + error: + g_string_free (str_buf, TRUE); + return NULL; +} + +/** + * cr_pseudo_dump: + *@a_this: the current instance of pseudo + *@a_fp: the destination file pointer. + * + *Dumps the pseudo to a file. + * + */ +void +cr_pseudo_dump (CRPseudo * a_this, FILE * a_fp) +{ + guchar *tmp_str = NULL; + + if (a_this) { + tmp_str = cr_pseudo_to_string (a_this); + if (tmp_str) { + fprintf (a_fp, "%s", tmp_str); + g_free (tmp_str); + tmp_str = NULL; + } + } +} + +/** + * cr_pseudo_destroy: + *@a_this: the current instance to destroy. + * + *destructor of the #CRPseudo class. + */ +void +cr_pseudo_destroy (CRPseudo * a_this) +{ + g_return_if_fail (a_this); + + if (a_this->name) { + cr_string_destroy (a_this->name); + a_this->name = NULL; + } + + if (a_this->extra) { + cr_string_destroy (a_this->extra); + a_this->extra = NULL; + } + + g_free (a_this); +} diff --git a/gettext-tools/gnulib-lib/libcroco/cr-pseudo.h b/gettext-tools/gnulib-lib/libcroco/cr-pseudo.h new file mode 100644 index 0000000..9c69db9 --- /dev/null +++ b/gettext-tools/gnulib-lib/libcroco/cr-pseudo.h @@ -0,0 +1,64 @@ +/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */ + +/* + * This file is part of The Croco Library + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + * See COPYRIGHTS file for copyright information + */ + +#ifndef __CR_PSEUDO_H__ +#define __CR_PSEUDO_H__ + +#include +#include +#include "cr-attr-sel.h" +#include "cr-parsing-location.h" + +G_BEGIN_DECLS + +enum CRPseudoType +{ + IDENT_PSEUDO = 0, + FUNCTION_PSEUDO +} ; + +typedef struct _CRPseudo CRPseudo ; + +/** + *The CRPseudo Class. + *Abstract a "pseudo" as defined by the css2 spec + *in appendix D.1 . + */ +struct _CRPseudo +{ + enum CRPseudoType type ; + CRString *name ; + CRString *extra ; + CRParsingLocation location ; +} ; + +CRPseudo * cr_pseudo_new (void) ; + +guchar * cr_pseudo_to_string (CRPseudo *a_this) ; + +void cr_pseudo_dump (CRPseudo *a_this, FILE *a_fp) ; + +void cr_pseudo_destroy (CRPseudo *a_this) ; + +G_END_DECLS + +#endif /*__CR_PSEUDO_H__*/ diff --git a/gettext-tools/gnulib-lib/libcroco/cr-rgb.c b/gettext-tools/gnulib-lib/libcroco/cr-rgb.c new file mode 100644 index 0000000..b927c0b --- /dev/null +++ b/gettext-tools/gnulib-lib/libcroco/cr-rgb.c @@ -0,0 +1,678 @@ +/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */ + +/* + * This file is part of The Croco Library + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + * Author: Dodji Seketeli + * See COPYRIGHTS file for copyrights information. + */ + +#include +#include +#include +#include "cr-rgb.h" +#include "cr-term.h" +#include "cr-parser.h" + +static CRRgb gv_standard_colors[] = { + {"aliceblue", 240, 248, 255, 0,}, + {"antiquewhite", 250, 235, 215, 0}, + {"aqua", 0, 255, 255, 0}, + {"aquamarine", 127, 255, 212, 0}, + {"azure", 240, 255, 255, 0}, + {"beige", 245, 245, 220, 0}, + {"bisque", 255, 228, 196, 0}, + {"black", 0, 0, 0, 0}, + {"blanchedalmond", 255, 235, 205, 0}, + {"blue", 0, 0, 255, 0}, + {"blueviolet", 138, 43, 226, 0}, + {"brown", 165, 42, 42, 0}, + {"burlywood", 222, 184, 135, 0}, + {"cadetblue", 95, 158, 160, 0}, + {"chartreuse", 127, 255, 0, 0}, + {"chocolate", 210, 105, 30, 0}, + {"coral", 255, 127, 80, 0}, + {"cornflowerblue", 100, 149, 237, 0}, + {"cornsilk", 255, 248, 220, 0}, + {"crimson", 220, 20, 60, 0}, + {"cyan", 0, 255, 255, 0}, + {"darkblue", 0, 0, 139, 0}, + {"darkcyan", 0, 139, 139, 0}, + {"darkgoldenrod", 184, 134, 11, 0}, + {"darkgray", 169, 169, 169, 0}, + {"darkgreen", 0, 100, 0, 0}, + {"darkgrey", 169, 169, 169, 0}, + {"darkkhaki", 189, 183, 107, 0}, + {"darkmagenta", 139, 0, 139, 0}, + {"darkolivegreen", 85, 107, 47, 0}, + {"darkorange", 255, 140, 0, 0}, + {"darkorchid", 153, 50, 204, 0}, + {"darkred", 139, 0, 0, 0}, + {"darksalmon", 233, 150, 122, 0}, + {"darkseagreen", 143, 188, 143, 0}, + {"darkslateblue", 72, 61, 139, 0}, + {"darkslategray", 47, 79, 79, 0}, + {"darkslategrey", 47, 79, 79, 0}, + {"darkturquoise", 0, 206, 209, 0}, + {"darkviolet", 148, 0, 211, 0}, + {"deeppink", 255, 20, 147, 0}, + {"deepskyblue", 0, 191, 255, 0}, + {"dimgray", 105, 105, 105, 0}, + {"dimgrey", 105, 105, 105, 0}, + {"dodgerblue", 30, 144, 255, 0}, + {"firebrick", 178, 34, 34, 0}, + {"floralwhite", 255, 250, 240, 0}, + {"forestgreen", 34, 139, 34, 0}, + {"fuchsia", 255, 0, 255, 0}, + {"gainsboro", 220, 220, 220, 0}, + {"ghostwhite", 248, 248, 255, 0}, + {"gold", 255, 215, 0, 0}, + {"goldenrod", 218, 165, 32, 0}, + {"gray", 128, 128, 128, 0}, + {"grey", 128, 128, 128, 0}, + {"green", 0, 128, 0, 0}, + {"greenyellow", 173, 255, 47, 0}, + {"honeydew", 240, 255, 240, 0}, + {"hotpink", 255, 105, 180, 0}, + {"indianred", 205, 92, 92, 0}, + {"indigo", 75, 0, 130, 0}, + {"ivory", 255, 255, 240, 0}, + {"khaki", 240, 230, 140, 0}, + {"lavender", 230, 230, 250, 0}, + {"lavenderblush", 255, 240, 245, 0}, + {"lawngreen", 124, 252, 0, 0}, + {"lemonchiffon", 255, 250, 205, 0}, + {"lightblue", 173, 216, 230, 0}, + {"lightcoral", 240, 128, 128, 0}, + {"lightcyan", 224, 255, 255, 0}, + {"lightgoldenrodyellow", 250, 250, 210, 0}, + {"lightgray", 211, 211, 211, 0}, + {"lightgreen", 144, 238, 144, 0}, + {"lightgrey", 211, 211, 211, 0}, + {"lightpink", 255, 182, 193, 0}, + {"lightsalmon", 255, 160, 122, 0}, + {"lightseagreen", 32, 178, 170, 0}, + {"lightskyblue", 135, 206, 250, 0}, + {"lightslategray", 119, 136, 153, 0}, + {"lightslategrey", 119, 136, 153, 0}, + {"lightsteelblue", 176, 196, 222, 0}, + {"lightyellow", 255, 255, 224, 0}, + {"lime", 0, 255, 0, 0}, + {"limegreen", 50, 205, 50, 0}, + {"linen", 250, 240, 230, 0}, + {"magenta", 255, 0, 255, 0}, + {"maroon", 128, 0, 0, 0}, + {"mediumaquamarine", 102, 205, 170, 0}, + {"mediumblue", 0, 0, 205, 0}, + {"mediumorchid", 186, 85, 211, 0}, + {"mediumpurple", 147, 112, 219, 0}, + {"mediumseagreen", 60, 179, 113, 0}, + {"mediumslateblue", 123, 104, 238, 0}, + {"mediumspringgreen", 0, 250, 154, 0}, + {"mediumturquoise", 72, 209, 204, 0}, + {"mediumvioletred", 199, 21, 133, 0}, + {"midnightblue", 25, 25, 112, 0}, + {"mintcream", 245, 255, 250, 0}, + {"mistyrose", 255, 228, 225, 0}, + {"moccasin", 255, 228, 181, 0}, + {"navajowhite", 255, 222, 173, 0}, + {"navy", 0, 0, 128, 0}, + {"oldlace", 253, 245, 230, 0}, + {"olive", 128, 128, 0, 0}, + {"olivedrab", 107, 142, 35, 0}, + {"orange", 255, 165, 0, 0}, + {"orangered", 255, 69, 0, 0}, + {"orchid", 218, 112, 214, 0}, + {"palegoldenrod", 238, 232, 170, 0}, + {"palegreen", 152, 251, 152, 0}, + {"paleturquoise", 175, 238, 238, 0}, + {"palevioletred", 219, 112, 147, 0}, + {"papayawhip", 255, 239, 213, 0}, + {"peachpuff", 255, 218, 185, 0}, + {"peru", 205, 133, 63, 0}, + {"pink", 255, 192, 203, 0}, + {"plum", 221, 160, 221, 0}, + {"powderblue", 176, 224, 230, 0}, + {"purple", 128, 0, 128, 0}, + {"red", 255, 0, 0, 0}, + {"rosybrown", 188, 143, 143, 0}, + {"royalblue", 65, 105, 225, 0}, + {"saddlebrown", 139, 69, 19, 0}, + {"salmon", 250, 128, 114, 0}, + {"sandybrown", 244, 164, 96, 0}, + {"seagreen", 46, 139, 87, 0}, + {"seashell", 255, 245, 238, 0}, + {"sienna", 160, 82, 45, 0}, + {"silver", 192, 192, 192, 0}, + {"skyblue", 135, 206, 235, 0}, + {"slateblue", 106, 90, 205, 0}, + {"slategray", 112, 128, 144, 0}, + {"slategrey", 112, 128, 144, 0}, + {"snow", 255, 250, 250, 0}, + {"springgreen", 0, 255, 127, 0}, + {"steelblue", 70, 130, 180, 0}, + {"tan", 210, 180, 140, 0}, + {"teal", 0, 128, 128, 0}, + {"thistle", 216, 191, 216, 0}, + {"tomato", 255, 99, 71, 0}, + {"turquoise", 64, 224, 208, 0}, + {"violet", 238, 130, 238, 0}, + {"wheat", 245, 222, 179, 0}, + {"white", 255, 255, 255, 0}, + {"whitesmoke", 245, 245, 245, 0,}, + {"yellow", 255, 255, 0, 0,}, + {"yellowgreen", 154, 205, 50, 0,}, + {"transparent", 255, 255, 255, 0, 0, 1} +}; + +/** + * cr_rgb_new: + * + *The default constructor of #CRRgb. + * + *Returns the newly built instance of #CRRgb + */ +CRRgb * +cr_rgb_new (void) +{ + CRRgb *result = NULL; + + result = g_try_malloc (sizeof (CRRgb)); + + if (result == NULL) { + cr_utils_trace_info ("No more memory"); + return NULL; + } + + memset (result, 0, sizeof (CRRgb)); + + return result; +} + +/** + * cr_rgb_new_with_vals: + *@a_red: the red component of the color. + *@a_green: the green component of the color. + *@a_blue: the blue component of the color. + *@a_unit: the unit of the rgb values. + *(either percentage or integer values) + * + *A constructor of #CRRgb. + * + *Returns the newly built instance of #CRRgb. + */ +CRRgb * +cr_rgb_new_with_vals (gulong a_red, gulong a_green, + gulong a_blue, gboolean a_is_percentage) +{ + CRRgb *result = NULL; + + result = cr_rgb_new (); + + g_return_val_if_fail (result, NULL); + + result->red = a_red; + result->green = a_green; + result->blue = a_blue; + result->is_percentage = a_is_percentage; + + return result; +} + +/** + * cr_rgb_to_string: + *@a_this: the instance of #CRRgb to serialize. + * + *Serializes the rgb into a zero terminated string. + * + *Returns the zero terminated string containing the serialized + *rgb. MUST BE FREED by the caller using g_free(). + */ +guchar * +cr_rgb_to_string (CRRgb * a_this) +{ + guchar *result = NULL; + GString *str_buf = NULL; + + str_buf = g_string_new (NULL); + g_return_val_if_fail (str_buf, NULL); + + if (a_this->is_percentage == 1) { + g_string_append_printf (str_buf, "%ld", a_this->red); + + g_string_append (str_buf, "%, "); + + g_string_append_printf (str_buf, "%ld", a_this->green); + g_string_append (str_buf, "%, "); + + g_string_append_printf (str_buf, "%ld", a_this->blue); + g_string_append_c (str_buf, '%'); + } else { + g_string_append_printf (str_buf, "%ld", a_this->red); + g_string_append (str_buf, ", "); + + g_string_append_printf (str_buf, "%ld", a_this->green); + g_string_append (str_buf, ", "); + + g_string_append_printf (str_buf, "%ld", a_this->blue); + } + + if (str_buf) { + result = str_buf->str; + g_string_free (str_buf, FALSE); + } + + return result; +} + +/** + * cr_rgb_dump: + *@a_this: the "this pointer" of + *the current instance of #CRRgb. + *@a_fp: the destination file pointer. + * + *Dumps the current instance of #CRRgb + *to a file. + */ +void +cr_rgb_dump (CRRgb * a_this, FILE * a_fp) +{ + guchar *str = NULL; + + g_return_if_fail (a_this); + + str = cr_rgb_to_string (a_this); + + if (str) { + fprintf (a_fp, "%s", str); + g_free (str); + str = NULL; + } +} + +/** + * cr_rgb_compute_from_percentage: + *@a_this: the current instance of #CRRgb + * + *If the rgb values are expressed in percentage, + *compute their real value. + * + *Returns CR_OK upon successful completion, an error code otherwise. + */ +enum CRStatus +cr_rgb_compute_from_percentage (CRRgb * a_this) +{ + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); + + if (a_this->is_percentage == FALSE) + return CR_OK; + a_this->red = a_this->red * 255 / 100; + a_this->green = a_this->green * 255 / 100; + a_this->blue = a_this->blue * 255 / 100; + a_this->is_percentage = FALSE; + return CR_OK; +} + +/** + * cr_rgb_set: + *@a_this: the current instance of #CRRgb. + *@a_red: the red value. + *@a_green: the green value. + *@a_blue: the blue value. + * + *Sets rgb values to the RGB. + * + *Returns CR_OK upon successful completion, an error code + *otherwise. + */ +enum CRStatus +cr_rgb_set (CRRgb * a_this, gulong a_red, + gulong a_green, gulong a_blue, gboolean a_is_percentage) +{ + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); + if (a_is_percentage != FALSE) { + g_return_val_if_fail (a_red <= 100 + && a_green <= 100 + && a_blue <= 100, CR_BAD_PARAM_ERROR); + } + + a_this->is_percentage = a_is_percentage; + + a_this->red = a_red; + a_this->green = a_green; + a_this->blue = a_blue; + a_this->inherit = FALSE ; + a_this->is_transparent = FALSE ; + return CR_OK; +} + +/** + * cr_rgb_set_to_inherit: + *@a_this: the current instance of #CRRgb + * + *sets the value of the rgb to inherit. + *Look at the css spec from chapter 6.1 to 6.2 to understand + *the meaning of "inherit". + * + * Returns CR_OK upon succesful completion, an error code otherwise. + */ +enum CRStatus +cr_rgb_set_to_inherit (CRRgb *a_this, gboolean a_inherit) +{ + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR) ; + + a_this->inherit = a_inherit ; + + return CR_OK ; +} + +/** + * cr_rgb_is_set_to_inherit: + * + * @a_this: the current instance of #CRRgb. + * + * Returns TRUE if the rgb is set to the value "inherit", FALSE otherwise. + */ +gboolean +cr_rgb_is_set_to_inherit (CRRgb *a_this) +{ + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR) ; + + return a_this->inherit ; +} + +/** + * cr_rgb_is_set_to_transparent: + *@a_this: the current instance of + *#CRRgb + * + *Tests if the the rgb is set to the + *value "transparent" or not. + * + *Returns TRUE if the rgb has been set to + *transparent, FALSE otherwise. + */ +gboolean +cr_rgb_is_set_to_transparent (CRRgb *a_this) +{ + g_return_val_if_fail (a_this, FALSE) ; + return a_this->is_transparent ; +} + + +/** + * cr_rgb_set_to_transparent: + *@a_this: the current instance of #CRRgb + *@a_is_transparent: set to transparent or not. + * + *Sets the rgb to the "transparent" value (or not) + *Returns CR_OK upon successfull completion, an error code otherwise. + */ +enum CRStatus +cr_rgb_set_to_transparent (CRRgb *a_this, + gboolean a_is_transparent) +{ + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR) ; + a_this->is_transparent = a_is_transparent ; + return CR_OK ; +} + +/** + * cr_rgb_set_from_rgb: + *@a_this: the current instance of #CRRgb. + *@a_rgb: the rgb to "copy" + * + *Sets the rgb from an other one. + * + *Returns CR_OK upon successful completion, an error code otherwise. + */ +enum CRStatus +cr_rgb_set_from_rgb (CRRgb * a_this, CRRgb * a_rgb) +{ + g_return_val_if_fail (a_this && a_rgb, CR_BAD_PARAM_ERROR); + + cr_rgb_copy (a_this, a_rgb) ; + + return CR_OK; +} + +/** + * cr_rgb_set_from_name: + * @a_this: the current instance of #CRRgb + * @a_color_name: the color name + * + * Returns CR_OK upon successful completion, an error code otherwise. + */ +enum CRStatus +cr_rgb_set_from_name (CRRgb * a_this, const guchar * a_color_name) +{ + gulong i = 0; + enum CRStatus status = CR_OK; + + g_return_val_if_fail (a_this && a_color_name, CR_BAD_PARAM_ERROR); + + for (i = 0; i < sizeof (gv_standard_colors); i++) { + if (!strcmp (a_color_name, gv_standard_colors[i].name)) { + cr_rgb_set_from_rgb (a_this, &gv_standard_colors[i]); + break; + } + } + + if (i < sizeof (gv_standard_colors)) + status = CR_OK; + else + status = CR_UNKNOWN_TYPE_ERROR; + + return status; +} + +/** + * cr_rgb_set_from_hex_str: + * @a_this: the current instance of #CRRgb + * @a_hex: the hexadecimal value to set. + * + * Returns CR_OK upon successful completion. + */ +enum CRStatus +cr_rgb_set_from_hex_str (CRRgb * a_this, const guchar * a_hex) +{ + enum CRStatus status = CR_OK; + gulong i = 0; + guchar colors[3] = { 0 }; + + g_return_val_if_fail (a_this && a_hex, CR_BAD_PARAM_ERROR); + + if (strlen (a_hex) == 3) { + for (i = 0; i < 3; i++) { + if (a_hex[i] >= '0' && a_hex[i] <= '9') { + colors[i] = a_hex[i] - '0'; + colors[i] = (colors[i] << 4) | colors[i]; + } else if (a_hex[i] >= 'a' && a_hex[i] <= 'z') { + colors[i] = 10 + a_hex[i] - 'a'; + colors[i] = (colors[i] << 4) | colors[i]; + } else if (a_hex[i] >= 'A' && a_hex[i] <= 'Z') { + colors[i] = 10 + a_hex[i] - 'A'; + colors[i] = (colors[i] << 4) | colors[i]; + } else { + status = CR_UNKNOWN_TYPE_ERROR; + } + } + } else if (strlen (a_hex) == 6) { + for (i = 0; i < 6; i++) { + if (a_hex[i] >= '0' && a_hex[i] <= '9') { + colors[i / 2] <<= 4; + colors[i / 2] |= a_hex[i] - '0'; + status = CR_OK; + } else if (a_hex[i] >= 'a' && a_hex[i] <= 'z') { + colors[i / 2] <<= 4; + colors[i / 2] |= 10 + a_hex[i] - 'a'; + status = CR_OK; + } else if (a_hex[i] >= 'A' && a_hex[i] <= 'Z') { + colors[i / 2] <<= 4; + colors[i / 2] |= 10 + a_hex[i] - 'A'; + status = CR_OK; + } else { + status = CR_UNKNOWN_TYPE_ERROR; + } + } + } else { + status = CR_UNKNOWN_TYPE_ERROR; + } + + if (status == CR_OK) { + status = cr_rgb_set (a_this, colors[0], + colors[1], colors[2], FALSE); + cr_rgb_set_to_transparent (a_this, FALSE) ; + } + return status; +} + +/** + * cr_rgb_set_from_term: + *@a_this: the instance of #CRRgb to set + *@a_value: the terminal from which to set + * + *Set the rgb from a terminal symbol + * + * Returns CR_OK upon successful completion, an error code otherwise. + */ +enum CRStatus +cr_rgb_set_from_term (CRRgb *a_this, const struct _CRTerm *a_value) +{ + enum CRStatus status = CR_OK ; + g_return_val_if_fail (a_this && a_value, + CR_BAD_PARAM_ERROR) ; + + switch(a_value->type) { + case TERM_RGB: + if (a_value->content.rgb) { + cr_rgb_set_from_rgb + (a_this, a_value->content.rgb) ; + } + break ; + case TERM_IDENT: + if (a_value->content.str + && a_value->content.str->stryng + && a_value->content.str->stryng->str) { + if (!strncmp ("inherit", + a_value->content.str->stryng->str, + sizeof ("inherit")-1)) { + a_this->inherit = TRUE; + a_this->is_transparent = FALSE ; + } else { + status = cr_rgb_set_from_name + (a_this, + a_value->content.str->stryng->str) ; + } + } else { + cr_utils_trace_info + ("a_value has NULL string value") ; + } + break ; + case TERM_HASH: + if (a_value->content.str + && a_value->content.str->stryng + && a_value->content.str->stryng->str) { + status = cr_rgb_set_from_hex_str + (a_this, + a_value->content.str->stryng->str) ; + } else { + cr_utils_trace_info + ("a_value has NULL string value") ; + } + break ; + default: + status = CR_UNKNOWN_TYPE_ERROR ; + } + return status ; +} + +enum CRStatus +cr_rgb_copy (CRRgb *a_dest, CRRgb*a_src) +{ + g_return_val_if_fail (a_dest && a_src, + CR_BAD_PARAM_ERROR) ; + + memcpy (a_dest, a_src, sizeof (CRRgb)) ; + return CR_OK ; +} + +/** + * cr_rgb_destroy: + *@a_this: the "this pointer" of the + *current instance of #CRRgb. + * + *Destructor of #CRRgb. + */ +void +cr_rgb_destroy (CRRgb * a_this) +{ + g_return_if_fail (a_this); + g_free (a_this); +} + +/** + * cr_rgb_parse_from_buf: + *@a_str: a string that contains a color description + *@a_enc: the encoding of a_str + * + *Parses a text buffer that contains a rgb color + * + *Returns the parsed color, or NULL in case of error + */ +CRRgb * +cr_rgb_parse_from_buf (const guchar *a_str, + enum CREncoding a_enc) +{ + enum CRStatus status = CR_OK ; + CRTerm *value = NULL ; + CRParser * parser = NULL; + CRRgb *result = NULL; + + g_return_val_if_fail (a_str, NULL); + + parser = cr_parser_new_from_buf ((guchar*)a_str, strlen (a_str), + a_enc, FALSE) ; + + g_return_val_if_fail (parser, NULL); + + status = cr_parser_try_to_skip_spaces_and_comments (parser) ; + if (status != CR_OK) + goto cleanup; + + status = cr_parser_parse_term (parser, &value); + if (status != CR_OK) + goto cleanup; + + result = cr_rgb_new (); + if (!result) + goto cleanup; + + status = cr_rgb_set_from_term (result, value); + +cleanup: + if (parser) { + cr_parser_destroy (parser); + parser = NULL; + } + if (value) { + cr_term_destroy(value); + value = NULL; + } + return result ; +} + diff --git a/gettext-tools/gnulib-lib/libcroco/cr-rgb.h b/gettext-tools/gnulib-lib/libcroco/cr-rgb.h new file mode 100644 index 0000000..62ce49c --- /dev/null +++ b/gettext-tools/gnulib-lib/libcroco/cr-rgb.h @@ -0,0 +1,94 @@ +/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */ + +/* + * This file is part of The Croco Library + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + * see COPYRIGHTS file for copyright information. + */ + +#ifndef __CR_RGB_H__ +#define __CR_RGB_H__ + +#include +#include +#include "cr-utils.h" +#include "cr-parsing-location.h" + +G_BEGIN_DECLS + + +typedef struct _CRRgb CRRgb ; +struct _CRRgb +{ + /* + *the unit of the rgb. + *Either NO_UNIT (integer) or + *UNIT_PERCENTAGE (percentage). + */ + const guchar *name ; + glong red ; + glong green ; + glong blue ; + gboolean is_percentage ; + gboolean inherit ; + gboolean is_transparent ; + CRParsingLocation location ; +} ; + +CRRgb * cr_rgb_new (void) ; + +CRRgb * cr_rgb_new_with_vals (gulong a_red, gulong a_green, + gulong a_blue, gboolean a_is_percentage) ; + +CRRgb *cr_rgb_parse_from_buf(const guchar *a_str, + enum CREncoding a_enc); + +enum CRStatus cr_rgb_compute_from_percentage (CRRgb *a_this) ; + +enum CRStatus cr_rgb_set (CRRgb *a_this, gulong a_red, + gulong a_green, gulong a_blue, + gboolean a_is_percentage) ; + +enum CRStatus cr_rgb_copy (CRRgb *a_dest, CRRgb*a_src) ; + +enum CRStatus cr_rgb_set_to_inherit (CRRgb *a_this, gboolean a_inherit) ; + +gboolean cr_rgb_is_set_to_inherit (CRRgb *a_this) ; + +gboolean cr_rgb_is_set_to_transparent (CRRgb *a_this) ; + +enum CRStatus cr_rgb_set_to_transparent (CRRgb *a_this, + gboolean a_is_transparent) ; +enum CRStatus cr_rgb_set_from_rgb (CRRgb *a_this, CRRgb *a_rgb) ; + +enum CRStatus cr_rgb_set_from_name (CRRgb *a_this, const guchar *a_color_name) ; + +enum CRStatus cr_rgb_set_from_hex_str (CRRgb *a_this, const guchar * a_hex_value) ; + +struct _CRTerm; + +enum CRStatus cr_rgb_set_from_term (CRRgb *a_this, const struct _CRTerm *a_value); + +guchar * cr_rgb_to_string (CRRgb *a_this) ; + +void cr_rgb_dump (CRRgb *a_this, FILE *a_fp) ; + +void cr_rgb_destroy (CRRgb *a_this) ; + +G_END_DECLS + +#endif /*__CR_RGB_H__*/ diff --git a/gettext-tools/gnulib-lib/libcroco/cr-sel-eng.c b/gettext-tools/gnulib-lib/libcroco/cr-sel-eng.c new file mode 100644 index 0000000..874630f --- /dev/null +++ b/gettext-tools/gnulib-lib/libcroco/cr-sel-eng.c @@ -0,0 +1,1572 @@ +/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */ + +/* + * This file is part of The Croco Library + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser + * General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + * See COPYRIGHTS file for copyright informations. + */ + +#include +#include +#include "cr-sel-eng.h" + +/** + *@CRSelEng: + * + *The definition of the #CRSelEng class. + *The #CRSelEng is actually the "Selection Engine" + *class. This is highly experimental for at the moment and + *its api is very likely to change in a near future. + */ + +#define PRIVATE(a_this) (a_this)->priv + +struct CRPseudoClassSelHandlerEntry { + guchar *name; + enum CRPseudoType type; + CRPseudoClassSelectorHandler handler; +}; + +struct _CRSelEngPriv { + /*not used yet */ + gboolean case_sensitive; + + CRStyleSheet *sheet; + /** + *where to store the next statement + *to be visited so that we can remember + *it from one method call to another. + */ + CRStatement *cur_stmt; + GList *pcs_handlers; + gint pcs_handlers_size; +} ; + +static gboolean class_add_sel_matches_node (CRAdditionalSel * a_add_sel, + xmlNode * a_node); + +static gboolean id_add_sel_matches_node (CRAdditionalSel * a_add_sel, + xmlNode * a_node); + +static gboolean attr_add_sel_matches_node (CRAdditionalSel * a_add_sel, + xmlNode * a_node); + +static enum CRStatus sel_matches_node_real (CRSelEng * a_this, + CRSimpleSel * a_sel, + xmlNode * a_node, + gboolean * a_result, + gboolean a_eval_sel_list_from_end, + gboolean a_recurse); + +static enum CRStatus cr_sel_eng_get_matched_rulesets_real (CRSelEng * a_this, + CRStyleSheet * + a_stylesheet, + xmlNode * a_node, + CRStatement ** + a_rulesets, + gulong * a_len); + +static enum CRStatus put_css_properties_in_props_list (CRPropList ** a_props, + CRStatement * + a_ruleset); + +static gboolean pseudo_class_add_sel_matches_node (CRSelEng * a_this, + CRAdditionalSel * + a_add_sel, + xmlNode * a_node); + +static gboolean lang_pseudo_class_handler (CRSelEng * a_this, + CRAdditionalSel * a_sel, + xmlNode * a_node); + +static gboolean first_child_pseudo_class_handler (CRSelEng * a_this, + CRAdditionalSel * a_sel, + xmlNode * a_node); + +static xmlNode *get_next_element_node (xmlNode * a_node); + +static xmlNode *get_next_child_element_node (xmlNode * a_node); + +static xmlNode *get_prev_element_node (xmlNode * a_node); + +static xmlNode *get_next_parent_element_node (xmlNode * a_node); + +static gboolean +lang_pseudo_class_handler (CRSelEng * a_this, + CRAdditionalSel * a_sel, xmlNode * a_node) +{ + xmlNode *node = a_node; + xmlChar *val = NULL; + gboolean result = FALSE; + + g_return_val_if_fail (a_this && PRIVATE (a_this) + && a_sel && a_sel->content.pseudo + && a_sel->content.pseudo + && a_sel->content.pseudo->name + && a_sel->content.pseudo->name->stryng + && a_node, CR_BAD_PARAM_ERROR); + + if (strncmp (a_sel->content.pseudo->name->stryng->str, + "lang", 4) + || !a_sel->content.pseudo->type == FUNCTION_PSEUDO) { + cr_utils_trace_info ("This handler is for :lang only"); + return CR_BAD_PSEUDO_CLASS_SEL_HANDLER_ERROR; + } + /*lang code should exist and be at least of length 2 */ + if (!a_sel->content.pseudo->extra + || !a_sel->content.pseudo->extra->stryng + || a_sel->content.pseudo->extra->stryng->len < 2) + return FALSE; + for (; node; node = get_next_parent_element_node (node)) { + val = xmlGetProp (node, "lang"); + if (val + && !strncmp (val, + a_sel->content.pseudo->extra->stryng->str, + a_sel->content.pseudo->extra->stryng->len)) { + result = TRUE; + } + if (val) { + xmlFree (val); + val = NULL; + } + } + + return result; +} + +static gboolean +first_child_pseudo_class_handler (CRSelEng * a_this, + CRAdditionalSel * a_sel, xmlNode * a_node) +{ + xmlNode *node = NULL; + + g_return_val_if_fail (a_this && PRIVATE (a_this) + && a_sel && a_sel->content.pseudo + && a_sel->content.pseudo + && a_sel->content.pseudo->name + && a_sel->content.pseudo->name->stryng + && a_node, CR_BAD_PARAM_ERROR); + + if (strcmp (a_sel->content.pseudo->name->stryng->str, + "first-child") + || !a_sel->content.pseudo->type == IDENT_PSEUDO) { + cr_utils_trace_info ("This handler is for :first-child only"); + return CR_BAD_PSEUDO_CLASS_SEL_HANDLER_ERROR; + } + if (!a_node->parent) + return FALSE; + node = get_next_child_element_node (a_node->parent); + if (node == a_node) + return TRUE; + return FALSE; +} + +static gboolean +pseudo_class_add_sel_matches_node (CRSelEng * a_this, + CRAdditionalSel * a_add_sel, + xmlNode * a_node) +{ + enum CRStatus status = CR_OK; + CRPseudoClassSelectorHandler handler = NULL; + + g_return_val_if_fail (a_this && PRIVATE (a_this) + && a_add_sel + && a_add_sel->content.pseudo + && a_add_sel->content.pseudo->name + && a_add_sel->content.pseudo->name->stryng + && a_add_sel->content.pseudo->name->stryng->str + && a_node, CR_BAD_PARAM_ERROR); + + status = cr_sel_eng_get_pseudo_class_selector_handler + (a_this, a_add_sel->content.pseudo->name->stryng->str, + a_add_sel->content.pseudo->type, &handler); + if (status != CR_OK || !handler) + return FALSE; + + return handler (a_this, a_add_sel, a_node); +} + +/** + *@param a_add_sel the class additional selector to consider. + *@param a_node the xml node to consider. + *@return TRUE if the class additional selector matches + *the xml node given in argument, FALSE otherwise. + */ +static gboolean +class_add_sel_matches_node (CRAdditionalSel * a_add_sel, xmlNode * a_node) +{ + gboolean result = FALSE; + xmlChar *klass = NULL, + *cur = NULL; + + g_return_val_if_fail (a_add_sel + && a_add_sel->type == CLASS_ADD_SELECTOR + && a_add_sel->content.class_name + && a_add_sel->content.class_name->stryng + && a_add_sel->content.class_name->stryng->str + && a_node, FALSE); + + if (xmlHasProp (a_node, "class")) { + klass = xmlGetProp (a_node, "class"); + for (cur = klass; cur && *cur; cur++) { + while (cur && *cur + && cr_utils_is_white_space (*cur) + == TRUE) + cur++; + + if (!strncmp (cur, + a_add_sel->content.class_name->stryng->str, + a_add_sel->content.class_name->stryng->len)) { + cur += a_add_sel->content.class_name->stryng->len; + if ((cur && !*cur) + || cr_utils_is_white_space (*cur) == TRUE) + result = TRUE; + } + if (cur && !*cur) + break ; + } + } + if (klass) { + xmlFree (klass); + klass = NULL; + } + return result; + +} + +/** + *@return TRUE if the additional attribute selector matches + *the current xml node given in argument, FALSE otherwise. + *@param a_add_sel the additional attribute selector to consider. + *@param a_node the xml node to consider. + */ +static gboolean +id_add_sel_matches_node (CRAdditionalSel * a_add_sel, xmlNode * a_node) +{ + gboolean result = FALSE; + xmlChar *id = NULL; + + g_return_val_if_fail (a_add_sel + && a_add_sel->type == ID_ADD_SELECTOR + && a_add_sel->content.id_name + && a_add_sel->content.id_name->stryng + && a_add_sel->content.id_name->stryng->str + && a_node, FALSE); + g_return_val_if_fail (a_add_sel + && a_add_sel->type == ID_ADD_SELECTOR + && a_node, FALSE); + + if (xmlHasProp (a_node, "id")) { + id = xmlGetProp (a_node, "id"); + if (!strncmp (id, a_add_sel->content.id_name->stryng->str, + a_add_sel->content.id_name->stryng->len)) { + result = TRUE; + } + } + if (id) { + xmlFree (id); + id = NULL; + } + return result; +} + +/** + *Returns TRUE if the instance of #CRAdditional selector matches + *the node given in parameter, FALSE otherwise. + *@param a_add_sel the additional selector to evaluate. + *@param a_node the xml node against whitch the selector is to + *be evaluated + *return TRUE if the additional selector matches the current xml node + *FALSE otherwise. + */ +static gboolean +attr_add_sel_matches_node (CRAdditionalSel * a_add_sel, xmlNode * a_node) +{ + CRAttrSel *cur_sel = NULL; + + g_return_val_if_fail (a_add_sel + && a_add_sel->type == ATTRIBUTE_ADD_SELECTOR + && a_node, FALSE); + + for (cur_sel = a_add_sel->content.attr_sel; + cur_sel; cur_sel = cur_sel->next) { + switch (cur_sel->match_way) { + case SET: + if (!cur_sel->name + || !cur_sel->name->stryng + || !cur_sel->name->stryng->str) + return FALSE; + + if (!xmlHasProp (a_node, + cur_sel->name->stryng->str)) + return FALSE; + break; + + case EQUALS: + { + xmlChar *value = NULL; + + if (!cur_sel->name + || !cur_sel->name->stryng + || !cur_sel->name->stryng->str + || !cur_sel->value + || !cur_sel->value->stryng + || !cur_sel->value->stryng->str) + return FALSE; + + if (!xmlHasProp + (a_node, + cur_sel->name->stryng->str)) + return FALSE; + + value = xmlGetProp + (a_node, + cur_sel->name->stryng->str); + + if (value + && strcmp + (value, + cur_sel->value->stryng->str)) { + xmlFree (value); + return FALSE; + } + xmlFree (value); + } + break; + + case INCLUDES: + { + xmlChar *value = NULL, + *ptr1 = NULL, + *ptr2 = NULL, + *cur = NULL; + gboolean found = FALSE; + + if (!xmlHasProp + (a_node, + cur_sel->name->stryng->str)) + return FALSE; + value = xmlGetProp + (a_node, + cur_sel->name->stryng->str); + + if (!value) + return FALSE; + + /* + *here, make sure value is a space + *separated list of "words", where one + *value is exactly cur_sel->value->str + */ + for (cur = value; *cur; cur++) { + /* + *set ptr1 to the first non white space + *char addr. + */ + while (cr_utils_is_white_space + (*cur) == TRUE && *cur) + cur++; + if (!*cur) + break; + ptr1 = cur; + + /* + *set ptr2 to the end the word. + */ + while (cr_utils_is_white_space + (*cur) == FALSE && *cur) + cur++; + cur--; + ptr2 = cur; + + if (!strncmp + (ptr1, + cur_sel->value->stryng->str, + ptr2 - ptr1 + 1)) { + found = TRUE; + break; + } + ptr1 = ptr2 = NULL; + } + + if (found == FALSE) { + xmlFree (value); + return FALSE; + } + xmlFree (value); + } + break; + + case DASHMATCH: + { + xmlChar *value = NULL, + *ptr1 = NULL, + *ptr2 = NULL, + *cur = NULL; + gboolean found = FALSE; + + if (!xmlHasProp + (a_node, + cur_sel->name->stryng->str)) + return FALSE; + value = xmlGetProp + (a_node, + cur_sel->name->stryng->str); + + /* + *here, make sure value is an hyphen + *separated list of "words", each of which + *starting with "cur_sel->value->str" + */ + for (cur = value; *cur; cur++) { + if (*cur == '-') + cur++; + ptr1 = cur; + + while (*cur != '-' && *cur) + cur++; + cur--; + ptr2 = cur; + + if (g_strstr_len + (ptr1, ptr2 - ptr1 + 1, + cur_sel->value->stryng->str) + == (gchar *) ptr1) { + found = TRUE; + break; + } + } + + if (found == FALSE) { + xmlFree (value); + return FALSE; + } + xmlFree (value); + } + break; + default: + return FALSE; + } + } + + return TRUE; +} + +/** + *Evaluates if a given additional selector matches an xml node. + *@param a_add_sel the additional selector to consider. + *@param a_node the xml node to consider. + *@return TRUE is a_add_sel matches a_node, FALSE otherwise. + */ +static gboolean +additional_selector_matches_node (CRSelEng * a_this, + CRAdditionalSel * a_add_sel, + xmlNode * a_node) +{ + CRAdditionalSel *cur_add_sel = NULL, *tail = NULL ; + gboolean evaluated = FALSE ; + + for (tail = a_add_sel ; + tail && tail->next; + tail = tail->next) ; + + g_return_val_if_fail (tail, FALSE) ; + + for (cur_add_sel = tail ; + cur_add_sel ; + cur_add_sel = cur_add_sel->prev) { + + evaluated = TRUE ; + if (cur_add_sel->type == NO_ADD_SELECTOR) { + return FALSE; + } + + if (cur_add_sel->type == CLASS_ADD_SELECTOR + && cur_add_sel->content.class_name + && cur_add_sel->content.class_name->stryng + && cur_add_sel->content.class_name->stryng->str) { + if (class_add_sel_matches_node (cur_add_sel, + a_node) == FALSE) { + return FALSE; + } + continue ; + } else if (cur_add_sel->type == ID_ADD_SELECTOR + && cur_add_sel->content.id_name + && cur_add_sel->content.id_name->stryng + && cur_add_sel->content.id_name->stryng->str) { + if (id_add_sel_matches_node (cur_add_sel, a_node) == FALSE) { + return FALSE; + } + continue ; + } else if (cur_add_sel->type == ATTRIBUTE_ADD_SELECTOR + && cur_add_sel->content.attr_sel) { + /* + *here, call a function that does the match + *against an attribute additionnal selector + *and an xml node. + */ + if (attr_add_sel_matches_node (cur_add_sel, a_node) + == FALSE) { + return FALSE; + } + continue ; + } else if (cur_add_sel->type == PSEUDO_CLASS_ADD_SELECTOR + && cur_add_sel->content.pseudo) { + if (pseudo_class_add_sel_matches_node + (a_this, cur_add_sel, a_node) == TRUE) { + return TRUE; + } + return FALSE; + } + } + if (evaluated == TRUE) + return TRUE; + return FALSE ; +} + +static xmlNode * +get_next_element_node (xmlNode * a_node) +{ + xmlNode *cur_node = NULL; + + g_return_val_if_fail (a_node, NULL); + + cur_node = a_node->next; + while (cur_node && cur_node->type != XML_ELEMENT_NODE) { + cur_node = cur_node->next; + } + return cur_node; +} + +static xmlNode * +get_next_child_element_node (xmlNode * a_node) +{ + xmlNode *cur_node = NULL; + + g_return_val_if_fail (a_node, NULL); + + cur_node = a_node->children; + if (!cur_node) + return cur_node; + if (a_node->children->type == XML_ELEMENT_NODE) + return a_node->children; + return get_next_element_node (a_node->children); +} + +static xmlNode * +get_prev_element_node (xmlNode * a_node) +{ + xmlNode *cur_node = NULL; + + g_return_val_if_fail (a_node, NULL); + + cur_node = a_node->prev; + while (cur_node && cur_node->type != XML_ELEMENT_NODE) { + cur_node = cur_node->prev; + } + return cur_node; +} + +static xmlNode * +get_next_parent_element_node (xmlNode * a_node) +{ + xmlNode *cur_node = NULL; + + g_return_val_if_fail (a_node, NULL); + + cur_node = a_node->parent; + while (cur_node && cur_node->type != XML_ELEMENT_NODE) { + cur_node = cur_node->parent; + } + return cur_node; +} + +/** + *Evaluate a selector (a simple selectors list) and says + *if it matches the xml node given in parameter. + *The algorithm used here is the following: + *Walk the combinator separated list of simple selectors backward, starting + *from the end of the list. For each simple selector, looks if + *if matches the current node. + * + *@param a_this the selection engine. + *@param a_sel the simple selection list. + *@param a_node the xml node. + *@param a_result out parameter. Set to true if the + *selector matches the xml node, FALSE otherwise. + *@param a_recurse if set to TRUE, the function will walk to + *the next simple selector (after the evaluation of the current one) + *and recursively evaluate it. Must be usually set to TRUE unless you + *know what you are doing. + */ +static enum CRStatus +sel_matches_node_real (CRSelEng * a_this, CRSimpleSel * a_sel, + xmlNode * a_node, gboolean * a_result, + gboolean a_eval_sel_list_from_end, + gboolean a_recurse) +{ + CRSimpleSel *cur_sel = NULL; + xmlNode *cur_node = NULL; + + g_return_val_if_fail (a_this && PRIVATE (a_this) + && a_this && a_node + && a_result, CR_BAD_PARAM_ERROR); + + *a_result = FALSE; + + if (a_node->type != XML_ELEMENT_NODE) + return CR_OK; + + if (a_eval_sel_list_from_end == TRUE) { + /*go and get the last simple selector of the list */ + for (cur_sel = a_sel; + cur_sel && cur_sel->next; cur_sel = cur_sel->next) ; + } else { + cur_sel = a_sel; + } + + for (cur_node = a_node; cur_sel; cur_sel = cur_sel->prev) { + if (((cur_sel->type_mask & TYPE_SELECTOR) + && (cur_sel->name + && cur_sel->name->stryng + && cur_sel->name->stryng->str) + && (!strcmp (cur_sel->name->stryng->str, + cur_node->name))) + || (cur_sel->type_mask & UNIVERSAL_SELECTOR)) { + /* + *this simple selector + *matches the current xml node + *Let's see if the preceding + *simple selectors also match + *their xml node counterpart. + */ + if (cur_sel->add_sel) { + if (additional_selector_matches_node (a_this, cur_sel->add_sel, + cur_node) == TRUE) { + goto walk_a_step_in_expr; + } else { + goto done; + } + } else { + goto walk_a_step_in_expr; + } + } + if (!(cur_sel->type_mask & TYPE_SELECTOR) + && !(cur_sel->type_mask & UNIVERSAL_SELECTOR)) { + if (!cur_sel->add_sel) { + goto done; + } + if (additional_selector_matches_node + (a_this, cur_sel->add_sel, cur_node) + == TRUE) { + goto walk_a_step_in_expr; + } else { + goto done; + } + } else { + goto done ; + } + + walk_a_step_in_expr: + if (a_recurse == FALSE) { + *a_result = TRUE; + goto done; + } + + /* + *here, depending on the combinator of cur_sel + *choose the axis of the xml tree traversal + *and walk one step in the xml tree. + */ + if (!cur_sel->prev) + break; + + switch (cur_sel->combinator) { + case NO_COMBINATOR: + break; + + case COMB_WS: /*descendant selector */ + { + xmlNode *n = NULL; + enum CRStatus status = CR_OK; + gboolean matches = FALSE; + + /* + *walk the xml tree upward looking for a parent + *node that matches the preceding selector. + */ + for (n = cur_node->parent; n; n = n->parent) { + status = sel_matches_node_real + (a_this, cur_sel->prev, + n, &matches, FALSE, TRUE); + + if (status != CR_OK) + goto done; + + if (matches == TRUE) { + cur_node = n ; + break; + } + } + + if (!n) { + /* + *didn't find any ancestor that matches + *the previous simple selector. + */ + goto done; + } + /* + *in this case, the preceding simple sel + *will have been interpreted twice, which + *is a cpu and mem waste ... I need to find + *another way to do this. Anyway, this is + *my first attempt to write this function and + *I am a bit clueless. + */ + break; + } + + case COMB_PLUS: + cur_node = get_prev_element_node (cur_node); + if (!cur_node) + goto done; + break; + + case COMB_GT: + cur_node = get_next_parent_element_node (cur_node); + if (!cur_node) + goto done; + break; + + default: + goto done; + } + continue; + } + + /* + *if we reached this point, it means the selector matches + *the xml node. + */ + *a_result = TRUE; + + done: + return CR_OK; +} + + +/** + *Returns array of the ruleset statements that matches the + *given xml node. + *The engine keeps in memory the last statement he + *visited during the match. So, the next call + *to this function will eventually return a rulesets list starting + *from the last ruleset statement visited during the previous call. + *The enable users to get matching rulesets in an incremental way. + *Note that for each statement returned, + *the engine calculates the specificity of the selector + *that matched the xml node and stores it in the "specifity" field + *of the statement structure. + * + *@param a_sel_eng the current selection engine + *@param a_node the xml node for which the request + *is being made. + *@param a_sel_list the list of selectors to perform the search in. + *@param a_rulesets in/out parameter. A pointer to the + *returned array of rulesets statements that match the xml node + *given in parameter. The caller allocates the array before calling this + *function. + *@param a_len in/out parameter the length (in sizeof (#CRStatement*)) + *of the returned array. + *(the length of a_rulesets, more precisely). + *The caller must set it to the length of a_ruleset prior to calling this + *function. In return, the function sets it to the length + *(in sizeof (#CRStatement)) of the actually returned CRStatement array. + *@return CR_OUTPUT_TOO_SHORT_ERROR if found more rulesets than the size + *of the a_rulesets array. In this case, the first *a_len rulesets found + *are put in a_rulesets, and a further call will return the following + *ruleset(s) following the same principle. + *@return CR_OK if all the rulesets found have been returned. In this + *case, *a_len is set to the actual number of ruleset found. + *@return CR_BAD_PARAM_ERROR in case any of the given parameter are + *bad (e.g null pointer). + *@return CR_ERROR if any other error occured. + */ +static enum CRStatus +cr_sel_eng_get_matched_rulesets_real (CRSelEng * a_this, + CRStyleSheet * a_stylesheet, + xmlNode * a_node, + CRStatement ** a_rulesets, + gulong * a_len) +{ + CRStatement *cur_stmt = NULL; + CRSelector *sel_list = NULL, + *cur_sel = NULL; + gboolean matches = FALSE; + enum CRStatus status = CR_OK; + gulong i = 0; + + g_return_val_if_fail (a_this + && a_stylesheet + && a_node && a_rulesets, CR_BAD_PARAM_ERROR); + + if (!a_stylesheet->statements) { + *a_rulesets = NULL; + *a_len = 0; + return CR_OK; + } + + /* + *if this stylesheet is "new one" + *let's remember it for subsequent calls. + */ + if (PRIVATE (a_this)->sheet != a_stylesheet) { + PRIVATE (a_this)->sheet = a_stylesheet; + PRIVATE (a_this)->cur_stmt = a_stylesheet->statements; + } + + /* + *walk through the list of statements and, + *get the selectors list inside the statements that + *contain some, and try to match our xml node in these + *selectors lists. + */ + for (cur_stmt = PRIVATE (a_this)->cur_stmt, i = 0; + (PRIVATE (a_this)->cur_stmt = cur_stmt); + cur_stmt = cur_stmt->next) { + /* + *initialyze the selector list in which we will + *really perform the search. + */ + sel_list = NULL; + + /* + *get the the damn selector list in + *which we have to look + */ + switch (cur_stmt->type) { + case RULESET_STMT: + if (cur_stmt->kind.ruleset + && cur_stmt->kind.ruleset->sel_list) { + sel_list = cur_stmt->kind.ruleset->sel_list; + } + break; + + case AT_MEDIA_RULE_STMT: + if (cur_stmt->kind.media_rule + && cur_stmt->kind.media_rule->rulesets + && cur_stmt->kind.media_rule->rulesets-> + kind.ruleset + && cur_stmt->kind.media_rule->rulesets-> + kind.ruleset->sel_list) { + sel_list = + cur_stmt->kind.media_rule-> + rulesets->kind.ruleset->sel_list; + } + break; + + case AT_IMPORT_RULE_STMT: + /* + *some recursivity may be needed here. + *I don't like this :( + */ + break; + default: + break; + } + + if (!sel_list) + continue; + + /* + *now, we have a comma separated selector list to look in. + *let's walk it and try to match the xml_node + *on each item of the list. + */ + for (cur_sel = sel_list; cur_sel; cur_sel = cur_sel->next) { + if (!cur_sel->simple_sel) + continue; + + status = cr_sel_eng_matches_node + (a_this, cur_sel->simple_sel, + a_node, &matches); + + if (status == CR_OK && matches == TRUE) { + /* + *bingo!!! we found one ruleset that + *matches that fucking node. + *lets put it in the out array. + */ + + if (i < *a_len) { + a_rulesets[i] = cur_stmt; + i++; + + /* + *For the cascade computing algorithm + *(which is gonna take place later) + *we must compute the specificity + *(css2 spec chap 6.4.1) of the selector + *that matched the current xml node + *and store it in the css2 statement + *(statement == ruleset here). + */ + status = cr_simple_sel_compute_specificity (cur_sel->simple_sel); + + g_return_val_if_fail (status == CR_OK, + CR_ERROR); + cur_stmt->specificity = + cur_sel->simple_sel-> + specificity; + } else + { + *a_len = i; + return CR_OUTPUT_TOO_SHORT_ERROR; + } + } + } + } + + /* + *if we reached this point, it means + *we reached the end of stylesheet. + *no need to store any info about the stylesheet + *anymore. + */ + g_return_val_if_fail (!PRIVATE (a_this)->cur_stmt, CR_ERROR); + PRIVATE (a_this)->sheet = NULL; + *a_len = i; + return CR_OK; +} + +static enum CRStatus +put_css_properties_in_props_list (CRPropList ** a_props, CRStatement * a_stmt) +{ + CRPropList *props = NULL, + *pair = NULL, + *tmp_props = NULL; + CRDeclaration *cur_decl = NULL; + + g_return_val_if_fail (a_props && a_stmt + && a_stmt->type == RULESET_STMT + && a_stmt->kind.ruleset, CR_BAD_PARAM_ERROR); + + props = *a_props; + + for (cur_decl = a_stmt->kind.ruleset->decl_list; + cur_decl; cur_decl = cur_decl->next) { + CRDeclaration *decl; + + decl = NULL; + pair = NULL; + + if (!cur_decl->property + || !cur_decl->property->stryng + || !cur_decl->property->stryng->str) + continue; + /* + *First, test if the property is not + *already present in our properties list + *If yes, apply the cascading rules to + *compute the precedence. If not, insert + *the property into the list + */ + cr_prop_list_lookup_prop (props, + cur_decl->property, + &pair); + + if (!pair) { + tmp_props = cr_prop_list_append2 + (props, cur_decl->property, cur_decl); + if (tmp_props) { + props = tmp_props; + tmp_props = NULL; + } + continue; + } + + /* + *A property with the same name already exists. + *We must apply here + *some cascading rules + *to compute the precedence. + */ + cr_prop_list_get_decl (pair, &decl); + g_return_val_if_fail (decl, CR_ERROR); + + /* + *first, look at the origin. + *6.4.1 says: + *"for normal declarations, + *author style sheets override user + *style sheets which override + *the default style sheet." + */ + if (decl->parent_statement + && decl->parent_statement->parent_sheet + && (decl->parent_statement->parent_sheet->origin + < a_stmt->parent_sheet->origin)) { + /* + *if the already selected declaration + *is marked as being !important the current + *declaration must not overide it + *(unless the already selected declaration + *has an UA origin) + */ + if (decl->important == TRUE + && decl->parent_statement->parent_sheet->origin + != ORIGIN_UA) { + continue; + } + tmp_props = cr_prop_list_unlink (props, pair); + if (props) { + cr_prop_list_destroy (pair); + } + props = tmp_props; + tmp_props = NULL; + props = cr_prop_list_append2 + (props, cur_decl->property, cur_decl); + + continue; + } else if (decl->parent_statement + && decl->parent_statement->parent_sheet + && (decl->parent_statement-> + parent_sheet->origin + > a_stmt->parent_sheet->origin)) { + cr_utils_trace_info + ("We should not reach this line\n"); + continue; + } + + /* + *A property with the same + *name and the same origin already exists. + *shit. This is lasting longer than expected ... + *Luckily, the spec says in 6.4.1: + *"more specific selectors will override + *more general ones" + *and + *"if two rules have the same weight, + *origin and specificity, + *the later specified wins" + */ + if (a_stmt->specificity + >= decl->parent_statement->specificity) { + if (decl->important == TRUE) + continue; + props = cr_prop_list_unlink (props, pair); + if (pair) { + cr_prop_list_destroy (pair); + pair = NULL; + } + props = cr_prop_list_append2 (props, + cur_decl->property, + cur_decl); + } + } + /*TODO: this may leak. Check this out */ + *a_props = props; + + return CR_OK; +} + +static void +set_style_from_props (CRStyle * a_style, CRPropList * a_props) +{ + CRPropList *cur = NULL; + CRDeclaration *decl = NULL; + + for (cur = a_props; cur; cur = cr_prop_list_get_next (cur)) { + cr_prop_list_get_decl (cur, &decl); + cr_style_set_style_from_decl (a_style, decl); + decl = NULL; + } +} + +/**************************************** + *PUBLIC METHODS + ****************************************/ + +/** + * cr_sel_eng_new: + *Creates a new instance of #CRSelEng. + * + *Returns the newly built instance of #CRSelEng of + *NULL if an error occurs. + */ +CRSelEng * +cr_sel_eng_new (void) +{ + CRSelEng *result = NULL; + + result = g_try_malloc (sizeof (CRSelEng)); + if (!result) { + cr_utils_trace_info ("Out of memory"); + return NULL; + } + memset (result, 0, sizeof (CRSelEng)); + + PRIVATE (result) = g_try_malloc (sizeof (CRSelEngPriv)); + if (!PRIVATE (result)) { + cr_utils_trace_info ("Out of memory"); + g_free (result); + return NULL; + } + memset (PRIVATE (result), 0, sizeof (CRSelEngPriv)); + cr_sel_eng_register_pseudo_class_sel_handler + (result, (guchar *) "first-child", + IDENT_PSEUDO, (CRPseudoClassSelectorHandler) + first_child_pseudo_class_handler); + cr_sel_eng_register_pseudo_class_sel_handler + (result, (guchar *) "lang", + FUNCTION_PSEUDO, (CRPseudoClassSelectorHandler) + lang_pseudo_class_handler); + + return result; +} + +/** + * cr_sel_eng_register_pseudo_class_sel_handler: + *@a_this: the current instance of #CRSelEng + *@a_pseudo_class_sel_name: the name of the pseudo class selector. + *@a_pseudo_class_type: the type of the pseudo class selector. + *@a_handler: the actual handler or callback to be called during + *the selector evaluation process. + * + *Adds a new handler entry in the handlers entry table. + * + *Returns CR_OK, upon successful completion, an error code otherwise. + */ +enum CRStatus +cr_sel_eng_register_pseudo_class_sel_handler (CRSelEng * a_this, + guchar * a_name, + enum CRPseudoType a_type, + CRPseudoClassSelectorHandler + a_handler) +{ + struct CRPseudoClassSelHandlerEntry *handler_entry = NULL; + GList *list = NULL; + + g_return_val_if_fail (a_this && PRIVATE (a_this) + && a_handler && a_name, CR_BAD_PARAM_ERROR); + + handler_entry = g_try_malloc + (sizeof (struct CRPseudoClassSelHandlerEntry)); + if (!handler_entry) { + return CR_OUT_OF_MEMORY_ERROR; + } + memset (handler_entry, 0, + sizeof (struct CRPseudoClassSelHandlerEntry)); + handler_entry->name = g_strdup (a_name); + handler_entry->type = a_type; + handler_entry->handler = a_handler; + list = g_list_append (PRIVATE (a_this)->pcs_handlers, handler_entry); + if (!list) { + return CR_OUT_OF_MEMORY_ERROR; + } + PRIVATE (a_this)->pcs_handlers = list; + return CR_OK; +} + +enum CRStatus +cr_sel_eng_unregister_pseudo_class_sel_handler (CRSelEng * a_this, + guchar * a_name, + enum CRPseudoType a_type) +{ + GList *elem = NULL, + *deleted_elem = NULL; + gboolean found = FALSE; + struct CRPseudoClassSelHandlerEntry *entry = NULL; + + g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR); + + for (elem = PRIVATE (a_this)->pcs_handlers; + elem; elem = g_list_next (elem)) { + entry = elem->data; + if (!strcmp (entry->name, a_name) + && entry->type == a_type) { + found = TRUE; + break; + } + } + if (found == FALSE) + return CR_PSEUDO_CLASS_SEL_HANDLER_NOT_FOUND_ERROR; + PRIVATE (a_this)->pcs_handlers = g_list_delete_link + (PRIVATE (a_this)->pcs_handlers, elem); + entry = elem->data; + if (entry->name) + g_free (entry->name); + g_free (elem); + g_list_free (deleted_elem); + + return CR_OK; +} + +/** + * cr_sel_eng_unregister_all_pseudo_class_sel_handlers: + *@a_this: the current instance of #CRSelEng . + * + *Unregisters all the pseudo class sel handlers + *and frees all the associated allocated datastructures. + * + *Returns CR_OK upon succesful completion, an error code + *otherwise. + */ +enum CRStatus +cr_sel_eng_unregister_all_pseudo_class_sel_handlers (CRSelEng * a_this) +{ + GList *elem = NULL; + struct CRPseudoClassSelHandlerEntry *entry = NULL; + + g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR); + + if (!PRIVATE (a_this)->pcs_handlers) + return CR_OK; + for (elem = PRIVATE (a_this)->pcs_handlers; + elem; elem = g_list_next (elem)) { + entry = elem->data; + if (!entry) + continue; + if (entry->name) { + g_free (entry->name); + entry->name = NULL; + } + g_free (entry); + elem->data = NULL; + } + g_list_free (PRIVATE (a_this)->pcs_handlers); + PRIVATE (a_this)->pcs_handlers = NULL; + return CR_OK; +} + +enum CRStatus +cr_sel_eng_get_pseudo_class_selector_handler (CRSelEng * a_this, + guchar * a_name, + enum CRPseudoType a_type, + CRPseudoClassSelectorHandler * + a_handler) +{ + GList *elem = NULL; + struct CRPseudoClassSelHandlerEntry *entry = NULL; + gboolean found = FALSE; + + g_return_val_if_fail (a_this && PRIVATE (a_this) + && a_name, CR_BAD_PARAM_ERROR); + + for (elem = PRIVATE (a_this)->pcs_handlers; + elem; elem = g_list_next (elem)) { + entry = elem->data; + if (!strcmp (a_name, entry->name) + && entry->type == a_type) { + found = TRUE; + break; + } + } + + if (found == FALSE) + return CR_PSEUDO_CLASS_SEL_HANDLER_NOT_FOUND_ERROR; + *a_handler = entry->handler; + return CR_OK; +} + +/** + * cr_sel_eng_matches_node: + *@a_this: the selection engine. + *@a_sel: the simple selector against which the xml node + *is going to be matched. + *@a_node: the node against which the selector is going to be matched. + *@a_result: out parameter. The result of the match. Is set to + *TRUE if the selector matches the node, FALSE otherwise. This value + *is considered if and only if this functions returns CR_OK. + * + *Evaluates a chained list of simple selectors (known as a css2 selector). + *Says wheter if this selector matches the xml node given in parameter or + *not. + * + *Returns the CR_OK if the selection ran correctly, an error code otherwise. + */ +enum CRStatus +cr_sel_eng_matches_node (CRSelEng * a_this, CRSimpleSel * a_sel, + xmlNode * a_node, gboolean * a_result) +{ + g_return_val_if_fail (a_this && PRIVATE (a_this) + && a_this && a_node + && a_result, CR_BAD_PARAM_ERROR); + + if (a_node->type != XML_ELEMENT_NODE) { + *a_result = FALSE; + return CR_OK; + } + + return sel_matches_node_real (a_this, a_sel, + a_node, a_result, + TRUE, TRUE); +} + +/** + * cr_sel_eng_get_matched_rulesets: + *@a_this: the current instance of the selection engine. + *@a_sheet: the stylesheet that holds the selectors. + *@a_node: the xml node to consider during the walk thru + *the stylesheet. + *@a_rulesets: out parameter. A pointer to an array of + *rulesets statement pointers. *a_rulesets is allocated by + *this function and must be freed by the caller. However, the caller + *must not alter the rulesets statements pointer because they + *point to statements that are still in the css stylesheet. + *@a_len: the length of *a_ruleset. + * + *Returns an array of pointers to selectors that matches + *the xml node given in parameter. + * + *Returns CR_OK upon sucessfull completion, an error code otherwise. + */ +enum CRStatus +cr_sel_eng_get_matched_rulesets (CRSelEng * a_this, + CRStyleSheet * a_sheet, + xmlNode * a_node, + CRStatement *** a_rulesets, gulong * a_len) +{ + CRStatement **stmts_tab = NULL; + enum CRStatus status = CR_OK; + gulong tab_size = 0, + tab_len = 0, + index = 0; + gushort stmts_chunck_size = 8; + + g_return_val_if_fail (a_this + && a_sheet + && a_node + && a_rulesets && *a_rulesets == NULL + && a_len, CR_BAD_PARAM_ERROR); + + stmts_tab = g_try_malloc (stmts_chunck_size * sizeof (CRStatement *)); + + if (!stmts_tab) { + cr_utils_trace_info ("Out of memory"); + status = CR_ERROR; + goto error; + } + memset (stmts_tab, 0, stmts_chunck_size * sizeof (CRStatement *)); + + tab_size = stmts_chunck_size; + tab_len = tab_size; + + while ((status = cr_sel_eng_get_matched_rulesets_real + (a_this, a_sheet, a_node, stmts_tab + index, &tab_len)) + == CR_OUTPUT_TOO_SHORT_ERROR) { + stmts_tab = g_try_realloc (stmts_tab, + (tab_size + stmts_chunck_size) + * sizeof (CRStatement *)); + if (!stmts_tab) { + cr_utils_trace_info ("Out of memory"); + status = CR_ERROR; + goto error; + } + tab_size += stmts_chunck_size; + index += tab_len; + tab_len = tab_size - index; + } + + tab_len = tab_size - stmts_chunck_size + tab_len; + *a_rulesets = stmts_tab; + *a_len = tab_len; + + return CR_OK; + + error: + + if (stmts_tab) { + g_free (stmts_tab); + stmts_tab = NULL; + + } + + *a_len = 0; + return status; +} + + +enum CRStatus +cr_sel_eng_get_matched_properties_from_cascade (CRSelEng * a_this, + CRCascade * a_cascade, + xmlNode * a_node, + CRPropList ** a_props) +{ + CRStatement **stmts_tab = NULL; + enum CRStatus status = CR_OK; + gulong tab_size = 0, + tab_len = 0, + i = 0, + index = 0; + enum CRStyleOrigin origin = 0; + gushort stmts_chunck_size = 8; + CRStyleSheet *sheet = NULL; + + g_return_val_if_fail (a_this + && a_cascade + && a_node && a_props, CR_BAD_PARAM_ERROR); + + for (origin = ORIGIN_UA; origin < NB_ORIGINS; origin++) { + sheet = cr_cascade_get_sheet (a_cascade, origin); + if (!sheet) + continue; + if (tab_size - index < 1) { + stmts_tab = g_try_realloc + (stmts_tab, (tab_size + stmts_chunck_size) + * sizeof (CRStatement *)); + if (!stmts_tab) { + cr_utils_trace_info ("Out of memory"); + status = CR_ERROR; + goto cleanup; + } + tab_size += stmts_chunck_size; + /* + *compute the max size left for + *cr_sel_eng_get_matched_rulesets_real()'s output tab + */ + tab_len = tab_size - index; + } + while ((status = cr_sel_eng_get_matched_rulesets_real + (a_this, sheet, a_node, stmts_tab + index, &tab_len)) + == CR_OUTPUT_TOO_SHORT_ERROR) { + stmts_tab = g_try_realloc + (stmts_tab, (tab_size + stmts_chunck_size) + * sizeof (CRStatement *)); + if (!stmts_tab) { + cr_utils_trace_info ("Out of memory"); + status = CR_ERROR; + goto cleanup; + } + tab_size += stmts_chunck_size; + index += tab_len; + /* + *compute the max size left for + *cr_sel_eng_get_matched_rulesets_real()'s output tab + */ + tab_len = tab_size - index; + } + if (status != CR_OK) { + cr_utils_trace_info ("Error while running " + "selector engine"); + goto cleanup; + } + index += tab_len; + tab_len = tab_size - index; + } + + /* + *TODO, walk down the stmts_tab and build the + *property_name/declaration hashtable. + *Make sure one can walk from the declaration to + *the stylesheet. + */ + for (i = 0; i < index; i++) { + CRStatement *stmt = stmts_tab[i]; + + if (!stmt) + continue; + switch (stmt->type) { + case RULESET_STMT: + if (!stmt->parent_sheet) + continue; + status = put_css_properties_in_props_list + (a_props, stmt); + break; + default: + break; + } + + } + status = CR_OK ; + cleanup: + if (stmts_tab) { + g_free (stmts_tab); + stmts_tab = NULL; + } + + return status; +} + +enum CRStatus +cr_sel_eng_get_matched_style (CRSelEng * a_this, + CRCascade * a_cascade, + xmlNode * a_node, + CRStyle * a_parent_style, + CRStyle ** a_style, + gboolean a_set_props_to_initial_values) +{ + enum CRStatus status = CR_OK; + + CRPropList *props = NULL; + + g_return_val_if_fail (a_this && a_cascade + && a_node && a_style, CR_BAD_PARAM_ERROR); + + status = cr_sel_eng_get_matched_properties_from_cascade + (a_this, a_cascade, a_node, &props); + + g_return_val_if_fail (status == CR_OK, status); + if (props) { + if (!*a_style) { + *a_style = cr_style_new (a_set_props_to_initial_values) ; + g_return_val_if_fail (*a_style, CR_ERROR); + } else { + if (a_set_props_to_initial_values == TRUE) { + cr_style_set_props_to_initial_values (*a_style) ; + } else { + cr_style_set_props_to_default_values (*a_style); + } + } + (*a_style)->parent_style = a_parent_style; + + set_style_from_props (*a_style, props); + if (props) { + cr_prop_list_destroy (props); + props = NULL; + } + } + return CR_OK; +} + +/** + * cr_sel_eng_destroy: + *@a_this: the current instance of the selection engine. + * + *The destructor of #CRSelEng + */ +void +cr_sel_eng_destroy (CRSelEng * a_this) +{ + g_return_if_fail (a_this); + + if (!PRIVATE (a_this)) + goto end ; + if (PRIVATE (a_this)->pcs_handlers) { + cr_sel_eng_unregister_all_pseudo_class_sel_handlers + (a_this) ; + PRIVATE (a_this)->pcs_handlers = NULL ; + } + g_free (PRIVATE (a_this)); + PRIVATE (a_this) = NULL; + end: + if (a_this) { + g_free (a_this); + } +} diff --git a/gettext-tools/gnulib-lib/libcroco/cr-sel-eng.h b/gettext-tools/gnulib-lib/libcroco/cr-sel-eng.h new file mode 100644 index 0000000..97961bc --- /dev/null +++ b/gettext-tools/gnulib-lib/libcroco/cr-sel-eng.h @@ -0,0 +1,114 @@ +/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */ + +/* + * This file is part of The Croco Library + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + * Author: Dodji Seketeli + * See COPYRIGHTS file for copyrights information. + */ + +#ifndef __CR_SEL_ENG_H__ +#define __CR_SEL_ENG_H__ + +#include "cr-utils.h" +#include "cr-stylesheet.h" +#include "cr-cascade.h" +#include "cr-style.h" +#include "cr-prop-list.h" + +#ifdef CROCO_HAVE_LIBXML2 + #include +#endif + + + +/** + *@file: + *The declaration of the #CRSelEng class. + *The #CRSelEng is actually the "Selection Engine" + *class. + */ + +G_BEGIN_DECLS + +typedef struct _CRSelEng CRSelEng ; +typedef struct _CRSelEngPriv CRSelEngPriv ; + +/** + *The Selection engine class. + *The main service provided by this class, is + *the ability to interpret a libcroco implementation + *of css2 selectors, and given an xml node, say if + *the selector matches the node or not. + */ +struct _CRSelEng +{ + CRSelEngPriv *priv ; +} ; + + +typedef gboolean (*CRPseudoClassSelectorHandler) (CRSelEng* a_this, + CRAdditionalSel *a_add_sel, + xmlNode *a_node) ; +CRSelEng * cr_sel_eng_new (void) ; + +enum CRStatus cr_sel_eng_register_pseudo_class_sel_handler (CRSelEng *a_this, + guchar *a_pseudo_class_sel_name, + enum CRPseudoType a_pseudo_class_type, + CRPseudoClassSelectorHandler a_handler) ; + +enum CRStatus cr_sel_eng_unregister_pseudo_class_sel_handler (CRSelEng *a_this, + guchar *a_pseudo_class_sel_name, + enum CRPseudoType a_pseudo_class_type) ; + +enum CRStatus cr_sel_eng_unregister_all_pseudo_class_sel_handlers (CRSelEng *a_this) ; + +enum CRStatus cr_sel_eng_get_pseudo_class_selector_handler (CRSelEng *a_this, + guchar *a_pseudo_class_sel_name, + enum CRPseudoType a_pseudo_class_type, + CRPseudoClassSelectorHandler *a_handler) ; + +enum CRStatus cr_sel_eng_matches_node (CRSelEng *a_this, + CRSimpleSel *a_sel, + xmlNode *a_node, + gboolean *a_result) ; + +enum CRStatus cr_sel_eng_get_matched_rulesets (CRSelEng *a_this, + CRStyleSheet *a_sheet, + xmlNode *a_node, + CRStatement ***a_rulesets, + gulong *a_len) ; + +enum CRStatus +cr_sel_eng_get_matched_properties_from_cascade (CRSelEng *a_this, + CRCascade *a_cascade, + xmlNode *a_node, + CRPropList **a_props) ; + +enum CRStatus cr_sel_eng_get_matched_style (CRSelEng *a_this, + CRCascade *a_cascade, + xmlNode *a_node, + CRStyle *a_parent_style, + CRStyle **a_style, + gboolean a_set_props_to_initial_values) ; + +void cr_sel_eng_destroy (CRSelEng *a_this) ; + +G_END_DECLS + + +#endif/*__CR_SEL_ENG_H__*/ diff --git a/gettext-tools/gnulib-lib/libcroco/cr-selector.c b/gettext-tools/gnulib-lib/libcroco/cr-selector.c new file mode 100644 index 0000000..1ed6d02 --- /dev/null +++ b/gettext-tools/gnulib-lib/libcroco/cr-selector.c @@ -0,0 +1,307 @@ +/* -*- Mode: C; indent-tabs-mode: ni; c-basic-offset: 8 -*- */ + +/* + * This file is part of The Croco Library + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + * See COPYRIGHTS file for copyright information. + */ + +#include +#include +#include "cr-selector.h" +#include "cr-parser.h" + +/** + * cr_selector_new: + * + *@a_simple_sel: the initial simple selector list + *of the current instance of #CRSelector. + * + *Creates a new instance of #CRSelector. + * + *Returns the newly built instance of #CRSelector, or + *NULL in case of failure. + */ +CRSelector * +cr_selector_new (CRSimpleSel * a_simple_sel) +{ + CRSelector *result = NULL; + + result = g_try_malloc (sizeof (CRSelector)); + if (!result) { + cr_utils_trace_info ("Out of memory"); + return NULL; + } + memset (result, 0, sizeof (CRSelector)); + result->simple_sel = a_simple_sel; + return result; +} + +CRSelector * +cr_selector_parse_from_buf (const guchar * a_char_buf, enum CREncoding a_enc) +{ + CRParser *parser = NULL; + + g_return_val_if_fail (a_char_buf, NULL); + + parser = cr_parser_new_from_buf ((guchar*)a_char_buf, strlen (a_char_buf), + a_enc, FALSE); + g_return_val_if_fail (parser, NULL); + + return NULL; +} + +/** + * cr_selector_append: + * + *@a_this: the current instance of #CRSelector. + *@a_new: the instance of #CRSelector to be appended. + * + *Appends a new instance of #CRSelector to the current selector list. + * + *Returns the new list. + */ +CRSelector * +cr_selector_append (CRSelector * a_this, CRSelector * a_new) +{ + CRSelector *cur = NULL; + + if (!a_this) { + return a_new; + } + + /*walk forward the list headed by a_this to get the list tail */ + for (cur = a_this; cur && cur->next; cur = cur->next) ; + + cur->next = a_new; + a_new->prev = cur; + + return a_this; +} + +/** + * cr_selector_prepend: + * + *@a_this: the current instance of #CRSelector list. + *@a_new: the instance of #CRSelector. + * + *Prepends an element to the #CRSelector list. + * + *Returns the new list. + */ +CRSelector * +cr_selector_prepend (CRSelector * a_this, CRSelector * a_new) +{ + CRSelector *cur = NULL; + + a_new->next = a_this; + a_this->prev = a_new; + + for (cur = a_new; cur && cur->prev; cur = cur->prev) ; + + return cur; +} + +/** + * cr_selector_append_simple_sel: + * + *@a_this: the current instance of #CRSelector. + *@a_simple_sel: the simple selector to append. + * + *append a simple selector to the current #CRSelector list. + * + *Returns the new list or NULL in case of failure. + */ +CRSelector * +cr_selector_append_simple_sel (CRSelector * a_this, + CRSimpleSel * a_simple_sel) +{ + CRSelector *selector = NULL; + + selector = cr_selector_new (a_simple_sel); + g_return_val_if_fail (selector, NULL); + + return cr_selector_append (a_this, selector); +} + +guchar * +cr_selector_to_string (CRSelector * a_this) +{ + guchar *result = NULL; + GString *str_buf = NULL; + + str_buf = g_string_new (NULL); + g_return_val_if_fail (str_buf, NULL); + + if (a_this) { + CRSelector *cur = NULL; + + for (cur = a_this; cur; cur = cur->next) { + if (cur->simple_sel) { + guchar *tmp_str = NULL; + + tmp_str = cr_simple_sel_to_string + (cur->simple_sel); + + if (tmp_str) { + if (cur->prev) + g_string_append (str_buf, + ", "); + + g_string_append (str_buf, tmp_str); + + g_free (tmp_str); + tmp_str = NULL; + } + } + } + } + + if (str_buf) { + result = str_buf->str; + g_string_free (str_buf, FALSE); + str_buf = NULL; + } + + return result; +} + +/** + * cr_selector_dump: + * + *@a_this: the current instance of #CRSelector. + *@a_fp: the destination file. + * + *Serializes the current instance of #CRSelector to a file. + */ +void +cr_selector_dump (CRSelector * a_this, FILE * a_fp) +{ + guchar *tmp_buf = NULL; + + if (a_this) { + tmp_buf = cr_selector_to_string (a_this); + if (tmp_buf) { + fprintf (a_fp, "%s", tmp_buf); + g_free (tmp_buf); + tmp_buf = NULL; + } + } +} + +/** + * cr_selector_ref: + * + *@a_this: the current instance of #CRSelector. + * + *Increments the ref count of the current instance + *of #CRSelector. + */ +void +cr_selector_ref (CRSelector * a_this) +{ + g_return_if_fail (a_this); + + a_this->ref_count++; +} + +/** + * cr_selector_unref: + * + *@a_this: the current instance of #CRSelector. + * + *Decrements the ref count of the current instance of + *#CRSelector. + *If the ref count reaches zero, the current instance of + *#CRSelector is destroyed. + * + *Returns TRUE if this function destroyed the current instance + *of #CRSelector, FALSE otherwise. + */ +gboolean +cr_selector_unref (CRSelector * a_this) +{ + g_return_val_if_fail (a_this, FALSE); + + if (a_this->ref_count) { + a_this->ref_count--; + } + + if (a_this->ref_count == 0) { + cr_selector_destroy (a_this); + return TRUE; + } + + return FALSE; +} + +/** + * cr_selector_destroy: + * + *@a_this: the current instance of #CRSelector. + * + *Destroys the selector list. + */ +void +cr_selector_destroy (CRSelector * a_this) +{ + CRSelector *cur = NULL; + + g_return_if_fail (a_this); + + /* + *go and get the list tail. In the same time, free + *all the simple selectors contained in the list. + */ + for (cur = a_this; cur && cur->next; cur = cur->next) { + if (cur->simple_sel) { + cr_simple_sel_destroy (cur->simple_sel); + cur->simple_sel = NULL; + } + } + + if (cur) { + if (cur->simple_sel) { + cr_simple_sel_destroy (cur->simple_sel); + cur->simple_sel = NULL; + } + } + + /*in case the list has only one element */ + if (cur && !cur->prev) { + g_free (cur); + return; + } + + /*walk backward the list and free each "next element" */ + for (cur = cur->prev; cur && cur->prev; cur = cur->prev) { + if (cur->next) { + g_free (cur->next); + cur->next = NULL; + } + } + + if (!cur) + return; + + if (cur->next) { + g_free (cur->next); + cur->next = NULL; + } + + g_free (cur); +} diff --git a/gettext-tools/gnulib-lib/libcroco/cr-selector.h b/gettext-tools/gnulib-lib/libcroco/cr-selector.h new file mode 100644 index 0000000..b7bbb62 --- /dev/null +++ b/gettext-tools/gnulib-lib/libcroco/cr-selector.h @@ -0,0 +1,95 @@ +/* -*- Mode: C; indent-tabs-mode: ni; c-basic-offset: 8 -*- */ + +/* + * This file is part of The Croco Library + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + * + * Author: Dodji Seketeli + * See COPYRIGHTS file for copyright information. + */ + +#ifndef __CR_SELECTOR_H__ +#define __CR_SELECTOR_H__ + +#include +#include "cr-utils.h" +#include "cr-simple-sel.h" +#include "cr-parsing-location.h" + +/** + *@file + *The declaration file of the #CRSelector file. + */ + +G_BEGIN_DECLS + +typedef struct _CRSelector CRSelector ; + +/** + *Abstracts a CSS2 selector as defined in the right part + *of the 'ruleset" production in the appendix D.1 of the + *css2 spec. + *It is actually the abstraction of a comma separated list + *of simple selectors list. + *In a css2 file, a selector is a list of simple selectors + *separated by a comma. + *e.g: sel0, sel1, sel2 ... + *Each seln is a simple selector + */ +struct _CRSelector +{ + /** + *A Selection expression. + *It is a list of basic selectors. + *Each basic selector can be either an element + *selector, an id selector, a class selector, an + *attribute selector, an universal selector etc ... + */ + CRSimpleSel *simple_sel ; + + /**The next selector list element*/ + CRSelector *next ; + CRSelector *prev ; + CRParsingLocation location ; + glong ref_count ; +}; + +CRSelector* cr_selector_new (CRSimpleSel *a_sel_expr) ; + +CRSelector * cr_selector_parse_from_buf (const guchar * a_char_buf, + enum CREncoding a_enc) ; + +CRSelector* cr_selector_append (CRSelector *a_this, CRSelector *a_new) ; + +CRSelector* cr_selector_append_simple_sel (CRSelector *a_this, + CRSimpleSel *a_simple_sel) ; + +CRSelector* cr_selector_prepend (CRSelector *a_this, CRSelector *a_new) ; + +guchar * cr_selector_to_string (CRSelector *a_this) ; + +void cr_selector_dump (CRSelector *a_this, FILE *a_fp) ; + +void cr_selector_ref (CRSelector *a_this) ; + +gboolean cr_selector_unref (CRSelector *a_this) ; + +void cr_selector_destroy (CRSelector *a_this) ; + +G_END_DECLS + +#endif /*__CR_SELECTOR_H__*/ diff --git a/gettext-tools/gnulib-lib/libcroco/cr-simple-sel.c b/gettext-tools/gnulib-lib/libcroco/cr-simple-sel.c new file mode 100644 index 0000000..87c96db --- /dev/null +++ b/gettext-tools/gnulib-lib/libcroco/cr-simple-sel.c @@ -0,0 +1,325 @@ +/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */ + +/* + * This file is part of The Croco Library + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + * Author: Dodji Seketeli + * See COPYRIGHTS file for copyright information. + */ + +#include +#include +#include +#include "cr-simple-sel.h" + +/** + * cr_simple_sel_new: + * + *The constructor of #CRSimpleSel. + * + *Returns the new instance of #CRSimpleSel. + */ +CRSimpleSel * +cr_simple_sel_new (void) +{ + CRSimpleSel *result = NULL; + + result = g_try_malloc (sizeof (CRSimpleSel)); + if (!result) { + cr_utils_trace_info ("Out of memory"); + return NULL; + } + memset (result, 0, sizeof (CRSimpleSel)); + + return result; +} + +/** + * cr_simple_sel_append_simple_sel: + * + *Appends a simpe selector to the current list of simple selector. + * + *@a_this: the this pointer of the current instance of #CRSimpleSel. + *@a_sel: the simple selector to append. + *Returns: the new list upon successfull completion, an error code otherwise. + */ +CRSimpleSel * +cr_simple_sel_append_simple_sel (CRSimpleSel * a_this, CRSimpleSel * a_sel) +{ + CRSimpleSel *cur = NULL; + + g_return_val_if_fail (a_sel, NULL); + + if (a_this == NULL) + return a_sel; + + for (cur = a_this; cur->next; cur = cur->next) ; + + cur->next = a_sel; + a_sel->prev = cur; + + return a_this; +} + +/** + * cr_simple_sel_prepend_simple_sel: + * + *@a_this: the this pointer of the current instance of #CRSimpleSel. + *@a_sel: the simple selector to prepend. + * + *Prepends a simple selector to the current list of simple selectors. + * + *Returns the new list upon successfull completion, an error code otherwise. + */ +CRSimpleSel * +cr_simple_sel_prepend_simple_sel (CRSimpleSel * a_this, CRSimpleSel * a_sel) +{ + g_return_val_if_fail (a_sel, NULL); + + if (a_this == NULL) + return a_sel; + + a_sel->next = a_this; + a_this->prev = a_sel; + + return a_sel; +} + +guchar * +cr_simple_sel_to_string (CRSimpleSel * a_this) +{ + GString *str_buf = NULL; + guchar *result = NULL; + + CRSimpleSel *cur = NULL; + + g_return_val_if_fail (a_this, NULL); + + str_buf = g_string_new (NULL); + for (cur = a_this; cur; cur = cur->next) { + if (cur->name) { + guchar *str = g_strndup (cur->name->stryng->str, + cur->name->stryng->len); + + if (str) { + switch (cur->combinator) { + case COMB_WS: + g_string_append (str_buf, " "); + break; + + case COMB_PLUS: + g_string_append (str_buf, "+"); + break; + + case COMB_GT: + g_string_append (str_buf, ">"); + break; + + default: + break; + } + + g_string_append (str_buf, str); + g_free (str); + str = NULL; + } + } + + if (cur->add_sel) { + guchar *tmp_str = NULL; + + tmp_str = cr_additional_sel_to_string (cur->add_sel); + if (tmp_str) { + g_string_append (str_buf, tmp_str); + g_free (tmp_str); + tmp_str = NULL; + } + } + } + + if (str_buf) { + result = str_buf->str; + g_string_free (str_buf, FALSE); + str_buf = NULL; + } + + return result; +} + + +guchar * +cr_simple_sel_one_to_string (CRSimpleSel * a_this) +{ + GString *str_buf = NULL; + guchar *result = NULL; + + g_return_val_if_fail (a_this, NULL); + + str_buf = g_string_new (NULL); + if (a_this->name) { + guchar *str = g_strndup (a_this->name->stryng->str, + a_this->name->stryng->len); + + if (str) { + g_string_append_printf (str_buf, "%s", str); + g_free (str); + str = NULL; + } + } + + if (a_this->add_sel) { + guchar *tmp_str = NULL; + + tmp_str = cr_additional_sel_to_string (a_this->add_sel); + if (tmp_str) { + g_string_append_printf + (str_buf, "%s", tmp_str); + g_free (tmp_str); + tmp_str = NULL; + } + } + + if (str_buf) { + result = str_buf->str; + g_string_free (str_buf, FALSE); + str_buf = NULL; + } + + return result; +} + +/** + * cr_simple_sel_dump: + *@a_this: the current instance of #CRSimpleSel. + *@a_fp: the destination file pointer. + * + *Dumps the selector to a file. + *TODO: add the support of unicode in the dump. + * + *Returns CR_OK upon successfull completion, an error code + *otherwise. + */ +enum CRStatus +cr_simple_sel_dump (CRSimpleSel * a_this, FILE * a_fp) +{ + guchar *tmp_str = NULL; + + g_return_val_if_fail (a_fp, CR_BAD_PARAM_ERROR); + + if (a_this) { + tmp_str = cr_simple_sel_to_string (a_this); + if (tmp_str) { + fprintf (a_fp, "%s", tmp_str); + g_free (tmp_str); + tmp_str = NULL; + } + } + + return CR_OK; +} + +/** + * cr_simple_sel_compute_specificity: + * + *@a_this: the current instance of #CRSimpleSel + * + *Computes the selector (combinator separated list of simple selectors) + *as defined in the css2 spec in chapter 6.4.3 + * + *Returns CR_OK upon successfull completion, an error code otherwise. + */ +enum CRStatus +cr_simple_sel_compute_specificity (CRSimpleSel * a_this) +{ + CRAdditionalSel *cur_add_sel = NULL; + CRSimpleSel *cur_sel = NULL; + gulong a = 0, + b = 0, + c = 0; + + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); + + for (cur_sel = a_this; cur_sel; cur_sel = cur_sel->next) { + if (cur_sel->type_mask | TYPE_SELECTOR) { + c++; /*hmmh, is this a new language ? */ + } else if (!cur_sel->name + || !cur_sel->name->stryng + || !cur_sel->name->stryng->str) { + if (cur_sel->add_sel->type == + PSEUDO_CLASS_ADD_SELECTOR) { + /* + *this is a pseudo element, and + *the spec says, "ignore pseudo elements". + */ + continue; + } + } + + for (cur_add_sel = cur_sel->add_sel; + cur_add_sel; cur_add_sel = cur_add_sel->next) { + switch (cur_add_sel->type) { + case ID_ADD_SELECTOR: + a++; + break; + + case NO_ADD_SELECTOR: + continue; + + default: + b++; + break; + } + } + } + + /*we suppose a, b and c have 1 to 3 digits */ + a_this->specificity = a * 1000000 + b * 1000 + c; + + return CR_OK; +} + +/** + * cr_simple_sel_destroy: + * + *@a_this: the this pointer of the current instance of #CRSimpleSel. + * + *The destructor of the current instance of + *#CRSimpleSel. + */ +void +cr_simple_sel_destroy (CRSimpleSel * a_this) +{ + g_return_if_fail (a_this); + + if (a_this->name) { + cr_string_destroy (a_this->name); + a_this->name = NULL; + } + + if (a_this->add_sel) { + cr_additional_sel_destroy (a_this->add_sel); + a_this->add_sel = NULL; + } + + if (a_this->next) { + cr_simple_sel_destroy (a_this->next); + } + + if (a_this) { + g_free (a_this); + } +} diff --git a/gettext-tools/gnulib-lib/libcroco/cr-simple-sel.h b/gettext-tools/gnulib-lib/libcroco/cr-simple-sel.h new file mode 100644 index 0000000..45aa66f --- /dev/null +++ b/gettext-tools/gnulib-lib/libcroco/cr-simple-sel.h @@ -0,0 +1,130 @@ +/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */ + +/* + * This file is part of The Croco Library + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + * Author: Dodji Seketeli + * See COPYRIGHTS file for copyright information. + */ + + +#ifndef __CR_SEL_H__ +#define __CR_SEL_H__ + +#include +#include +#include "cr-additional-sel.h" +#include "cr-parsing-location.h" + +G_BEGIN_DECLS + +/** + *@file + *the declaration of the #CRSimpleSel class. + * + */ +enum Combinator +{ + NO_COMBINATOR, + COMB_WS,/*whitespace: descendent*/ + COMB_PLUS,/*'+': preceded by*/ + COMB_GT/*greater than ('>'): child*/ +} ; + +enum SimpleSelectorType +{ + NO_SELECTOR_TYPE = 0, + UNIVERSAL_SELECTOR = 1, + TYPE_SELECTOR = 1 << 1 +} ; + +typedef struct _CRSimpleSel CRSimpleSel ; + +/** + *The abstraction of a css2 simple selection list + *as defined by the right part of the "selector" production in the + *appendix D.1 of the css2 spec. + *It is basically a list of simple selector, each + *simple selector being separated by a combinator. + * + *In the libcroco's implementation, each simple selector + *is made of at most two parts: + * + *1/An element name or 'type selector' (which can hold a '*' and + *then been called 'universal selector') + * + *2/An additional selector that "specializes" the preceding type or + *universal selector. The additionnal selector can be either + *an id selector, or a class selector, or an attribute selector. + */ +struct _CRSimpleSel +{ + enum SimpleSelectorType type_mask ; + gboolean is_case_sentive ; + CRString * name ; + /** + *The combinator that separates + *this simple selector from the previous + *one. + */ + enum Combinator combinator ; + + /** + *The additional selector list of the + *current simple selector. + *An additional selector may + *be a class selector, an id selector, + *or an attribute selector. + *Note that this field is a linked list. + */ + CRAdditionalSel *add_sel ; + + /* + *the specificity as specified by + *chapter 6.4.3 of the spec. + */ + gulong specificity ; + + CRSimpleSel *next ; + CRSimpleSel *prev ; + CRParsingLocation location ; +} ; + +CRSimpleSel * cr_simple_sel_new (void) ; + +CRSimpleSel * cr_simple_sel_append_simple_sel (CRSimpleSel *a_this, + CRSimpleSel *a_sel) ; + +CRSimpleSel * cr_simple_sel_prepend_simple_sel (CRSimpleSel *a_this, + CRSimpleSel *a_sel) ; + +guchar * cr_simple_sel_to_string (CRSimpleSel *a_this) ; + +guchar * cr_simple_sel_one_to_string (CRSimpleSel * a_this) ; + +enum CRStatus cr_simple_sel_dump (CRSimpleSel *a_this, FILE *a_fp) ; + +enum CRStatus cr_simple_sel_dump_attr_sel_list (CRSimpleSel *a_this) ; + +enum CRStatus cr_simple_sel_compute_specificity (CRSimpleSel *a_this) ; + +void cr_simple_sel_destroy (CRSimpleSel *a_this) ; + +G_END_DECLS + + +#endif /*__CR_SIMPLE_SEL_H__*/ diff --git a/gettext-tools/gnulib-lib/libcroco/cr-statement.c b/gettext-tools/gnulib-lib/libcroco/cr-statement.c new file mode 100644 index 0000000..617520f --- /dev/null +++ b/gettext-tools/gnulib-lib/libcroco/cr-statement.c @@ -0,0 +1,2791 @@ +/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8 -*- */ + +/* + * This file is part of The Croco Library + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + * Author: Dodji Seketeli. + * See COPYRIGHTS files for copyrights information. + */ + +#include +#include +#include "cr-statement.h" +#include "cr-parser.h" + +/** + *@file + *Definition of the #CRStatement class. + */ + +#define DECLARATION_INDENT_NB 2 + +static void cr_statement_clear (CRStatement * a_this); + +static void +parse_font_face_start_font_face_cb (CRDocHandler * a_this, + CRParsingLocation *a_location) +{ + CRStatement *stmt = NULL; + enum CRStatus status = CR_OK; + + stmt = cr_statement_new_at_font_face_rule (NULL, NULL); + g_return_if_fail (stmt); + + status = cr_doc_handler_set_ctxt (a_this, stmt); + g_return_if_fail (status == CR_OK); +} + +static void +parse_font_face_unrecoverable_error_cb (CRDocHandler * a_this) +{ + CRStatement *stmt = NULL; + CRStatement **stmtptr = NULL; + enum CRStatus status = CR_OK; + + g_return_if_fail (a_this); + + stmtptr = &stmt; + status = cr_doc_handler_get_ctxt (a_this, (gpointer *) stmtptr); + if (status != CR_OK) { + cr_utils_trace_info ("Couldn't get parsing context. " + "This may lead to some memory leaks."); + return; + } + if (stmt) { + cr_statement_destroy (stmt); + cr_doc_handler_set_ctxt (a_this, NULL); + return; + } +} + +static void +parse_font_face_property_cb (CRDocHandler * a_this, + CRString * a_name, + CRTerm * a_value, gboolean a_important) +{ + enum CRStatus status = CR_OK; + CRString *name = NULL; + CRDeclaration *decl = NULL; + CRStatement *stmt = NULL; + CRStatement **stmtptr = NULL; + + g_return_if_fail (a_this && a_name); + + stmtptr = &stmt; + status = cr_doc_handler_get_ctxt (a_this, (gpointer *) stmtptr); + g_return_if_fail (status == CR_OK && stmt); + g_return_if_fail (stmt->type == AT_FONT_FACE_RULE_STMT); + + name = cr_string_dup (a_name) ; + g_return_if_fail (name); + decl = cr_declaration_new (stmt, name, a_value); + if (!decl) { + cr_utils_trace_info ("cr_declaration_new () failed."); + goto error; + } + name = NULL; + + stmt->kind.font_face_rule->decl_list = + cr_declaration_append (stmt->kind.font_face_rule->decl_list, + decl); + if (!stmt->kind.font_face_rule->decl_list) + goto error; + decl = NULL; + + error: + if (decl) { + cr_declaration_unref (decl); + decl = NULL; + } + if (name) { + cr_string_destroy (name); + name = NULL; + } +} + +static void +parse_font_face_end_font_face_cb (CRDocHandler * a_this) +{ + CRStatement *result = NULL; + CRStatement **resultptr = NULL; + enum CRStatus status = CR_OK; + + g_return_if_fail (a_this); + + resultptr = &result; + status = cr_doc_handler_get_ctxt (a_this, (gpointer *) resultptr); + g_return_if_fail (status == CR_OK && result); + g_return_if_fail (result->type == AT_FONT_FACE_RULE_STMT); + + status = cr_doc_handler_set_result (a_this, result); + g_return_if_fail (status == CR_OK); +} + +static void +parse_page_start_page_cb (CRDocHandler * a_this, + CRString * a_name, + CRString * a_pseudo_page, + CRParsingLocation *a_location) +{ + CRStatement *stmt = NULL; + enum CRStatus status = CR_OK; + CRString *page_name = NULL, *pseudo_name = NULL ; + + if (a_name) + page_name = cr_string_dup (a_name) ; + if (a_pseudo_page) + pseudo_name = cr_string_dup (a_pseudo_page) ; + + stmt = cr_statement_new_at_page_rule (NULL, NULL, + page_name, + pseudo_name); + page_name = NULL ; + pseudo_name = NULL ; + g_return_if_fail (stmt); + status = cr_doc_handler_set_ctxt (a_this, stmt); + g_return_if_fail (status == CR_OK); +} + +static void +parse_page_unrecoverable_error_cb (CRDocHandler * a_this) +{ + CRStatement *stmt = NULL; + CRStatement **stmtptr = NULL; + enum CRStatus status = CR_OK; + + g_return_if_fail (a_this); + + stmtptr = &stmt; + status = cr_doc_handler_get_ctxt (a_this, (gpointer *) stmtptr); + if (status != CR_OK) { + cr_utils_trace_info ("Couldn't get parsing context. " + "This may lead to some memory leaks."); + return; + } + if (stmt) { + cr_statement_destroy (stmt); + stmt = NULL; + cr_doc_handler_set_ctxt (a_this, NULL); + } +} + +static void +parse_page_property_cb (CRDocHandler * a_this, + CRString * a_name, + CRTerm * a_expression, gboolean a_important) +{ + CRString *name = NULL; + CRStatement *stmt = NULL; + CRStatement **stmtptr = NULL; + CRDeclaration *decl = NULL; + enum CRStatus status = CR_OK; + + stmtptr = &stmt; + status = cr_doc_handler_get_ctxt (a_this, (gpointer *) stmtptr); + g_return_if_fail (status == CR_OK && stmt->type == AT_PAGE_RULE_STMT); + + name = cr_string_dup (a_name); + g_return_if_fail (name); + + decl = cr_declaration_new (stmt, name, a_expression); + g_return_if_fail (decl); + decl->important = a_important; + stmt->kind.page_rule->decl_list = + cr_declaration_append (stmt->kind.page_rule->decl_list, decl); + g_return_if_fail (stmt->kind.page_rule->decl_list); +} + +static void +parse_page_end_page_cb (CRDocHandler * a_this, + CRString * a_name, + CRString * a_pseudo_page) +{ + enum CRStatus status = CR_OK; + CRStatement *stmt = NULL; + CRStatement **stmtptr = NULL; + + stmtptr = &stmt; + status = cr_doc_handler_get_ctxt (a_this, (gpointer *) stmtptr); + g_return_if_fail (status == CR_OK && stmt); + g_return_if_fail (stmt->type == AT_PAGE_RULE_STMT); + + status = cr_doc_handler_set_result (a_this, stmt); + g_return_if_fail (status == CR_OK); +} + +static void +parse_at_media_start_media_cb (CRDocHandler * a_this, + GList * a_media_list, + CRParsingLocation *a_location) +{ + enum CRStatus status = CR_OK; + CRStatement *at_media = NULL; + GList *media_list = NULL; + + g_return_if_fail (a_this && a_this->priv); + + if (a_media_list) { + /*duplicate media list */ + media_list = cr_utils_dup_glist_of_cr_string + (a_media_list); + } + + g_return_if_fail (media_list); + + /*make sure cr_statement_new_at_media_rule works in this case. */ + at_media = cr_statement_new_at_media_rule (NULL, NULL, media_list); + + status = cr_doc_handler_set_ctxt (a_this, at_media); + g_return_if_fail (status == CR_OK); + status = cr_doc_handler_set_result (a_this, at_media); + g_return_if_fail (status == CR_OK); +} + +static void +parse_at_media_unrecoverable_error_cb (CRDocHandler * a_this) +{ + enum CRStatus status = CR_OK; + CRStatement *stmt = NULL; + CRStatement **stmtptr = NULL; + + g_return_if_fail (a_this); + + stmtptr = &stmt; + status = cr_doc_handler_get_result (a_this, (gpointer *) stmtptr); + if (status != CR_OK) { + cr_utils_trace_info ("Couldn't get parsing context. " + "This may lead to some memory leaks."); + return; + } + if (stmt) { + cr_statement_destroy (stmt); + stmt = NULL; + cr_doc_handler_set_ctxt (a_this, NULL); + cr_doc_handler_set_result (a_this, NULL); + } +} + +static void +parse_at_media_start_selector_cb (CRDocHandler * a_this, + CRSelector * a_sellist) +{ + enum CRStatus status = CR_OK; + CRStatement *at_media = NULL; + CRStatement **at_media_ptr = NULL; + CRStatement *ruleset = NULL; + + g_return_if_fail (a_this && a_this->priv && a_sellist); + + at_media_ptr = &at_media; + status = cr_doc_handler_get_ctxt (a_this, (gpointer *) at_media_ptr); + g_return_if_fail (status == CR_OK && at_media); + g_return_if_fail (at_media->type == AT_MEDIA_RULE_STMT); + ruleset = cr_statement_new_ruleset (NULL, a_sellist, NULL, at_media); + g_return_if_fail (ruleset); + status = cr_doc_handler_set_ctxt (a_this, ruleset); + g_return_if_fail (status == CR_OK); +} + +static void +parse_at_media_property_cb (CRDocHandler * a_this, + CRString * a_name, CRTerm * a_value, + gboolean a_important) +{ + enum CRStatus status = CR_OK; + + /* + *the current ruleset stmt, child of the + *current at-media being parsed. + */ + CRStatement *stmt = NULL; + CRStatement **stmtptr = NULL; + CRDeclaration *decl = NULL; + CRString *name = NULL; + + g_return_if_fail (a_this && a_name); + + name = cr_string_dup (a_name) ; + g_return_if_fail (name); + + stmtptr = &stmt; + status = cr_doc_handler_get_ctxt (a_this, + (gpointer *) stmtptr); + g_return_if_fail (status == CR_OK && stmt); + g_return_if_fail (stmt->type == RULESET_STMT); + + decl = cr_declaration_new (stmt, name, a_value); + g_return_if_fail (decl); + decl->important = a_important; + status = cr_statement_ruleset_append_decl (stmt, decl); + g_return_if_fail (status == CR_OK); +} + +static void +parse_at_media_end_selector_cb (CRDocHandler * a_this, + CRSelector * a_sellist) +{ + enum CRStatus status = CR_OK; + + /* + *the current ruleset stmt, child of the + *current at-media being parsed. + */ + CRStatement *stmt = NULL; + CRStatement **stmtptr = NULL; + + g_return_if_fail (a_this && a_sellist); + + stmtptr = &stmt; + status = cr_doc_handler_get_ctxt (a_this, (gpointer *) stmtptr); + g_return_if_fail (status == CR_OK && stmt + && stmt->type == RULESET_STMT); + g_return_if_fail (stmt->kind.ruleset->parent_media_rule); + + status = cr_doc_handler_set_ctxt + (a_this, stmt->kind.ruleset->parent_media_rule); + g_return_if_fail (status == CR_OK); +} + +static void +parse_at_media_end_media_cb (CRDocHandler * a_this, + GList * a_media_list) +{ + enum CRStatus status = CR_OK; + CRStatement *at_media = NULL; + CRStatement **at_media_ptr = NULL; + + g_return_if_fail (a_this && a_this->priv); + + at_media_ptr = &at_media; + status = cr_doc_handler_get_ctxt (a_this, + (gpointer *) at_media_ptr); + g_return_if_fail (status == CR_OK && at_media); + status = cr_doc_handler_set_result (a_this, at_media); +} + +static void +parse_ruleset_start_selector_cb (CRDocHandler * a_this, + CRSelector * a_sellist) +{ + CRStatement *ruleset = NULL; + + g_return_if_fail (a_this && a_this->priv && a_sellist); + + ruleset = cr_statement_new_ruleset (NULL, a_sellist, NULL, NULL); + g_return_if_fail (ruleset); + + cr_doc_handler_set_result (a_this, ruleset); +} + +static void +parse_ruleset_unrecoverable_error_cb (CRDocHandler * a_this) +{ + CRStatement *stmt = NULL; + CRStatement **stmtptr = NULL; + enum CRStatus status = CR_OK; + + stmtptr = &stmt; + status = cr_doc_handler_get_result (a_this, (gpointer *) stmtptr); + if (status != CR_OK) { + cr_utils_trace_info ("Couldn't get parsing context. " + "This may lead to some memory leaks."); + return; + } + if (stmt) { + cr_statement_destroy (stmt); + stmt = NULL; + cr_doc_handler_set_result (a_this, NULL); + } +} + +static void +parse_ruleset_property_cb (CRDocHandler * a_this, + CRString * a_name, + CRTerm * a_value, gboolean a_important) +{ + enum CRStatus status = CR_OK; + CRStatement *ruleset = NULL; + CRStatement **rulesetptr = NULL; + CRDeclaration *decl = NULL; + CRString *stringue = NULL; + + g_return_if_fail (a_this && a_this->priv && a_name); + + stringue = cr_string_dup (a_name); + g_return_if_fail (stringue); + + rulesetptr = &ruleset; + status = cr_doc_handler_get_result (a_this, (gpointer *) rulesetptr); + g_return_if_fail (status == CR_OK + && ruleset + && ruleset->type == RULESET_STMT); + + decl = cr_declaration_new (ruleset, stringue, a_value); + g_return_if_fail (decl); + decl->important = a_important; + status = cr_statement_ruleset_append_decl (ruleset, decl); + g_return_if_fail (status == CR_OK); +} + +static void +parse_ruleset_end_selector_cb (CRDocHandler * a_this, + CRSelector * a_sellist) +{ + CRStatement *result = NULL; + CRStatement **resultptr = NULL; + enum CRStatus status = CR_OK; + + g_return_if_fail (a_this && a_sellist); + + resultptr = &result; + status = cr_doc_handler_get_result (a_this, (gpointer *) resultptr); + + g_return_if_fail (status == CR_OK + && result + && result->type == RULESET_STMT); +} + +static void +cr_statement_clear (CRStatement * a_this) +{ + g_return_if_fail (a_this); + + switch (a_this->type) { + case AT_RULE_STMT: + break; + case RULESET_STMT: + if (!a_this->kind.ruleset) + return; + if (a_this->kind.ruleset->sel_list) { + cr_selector_unref (a_this->kind.ruleset->sel_list); + a_this->kind.ruleset->sel_list = NULL; + } + if (a_this->kind.ruleset->decl_list) { + cr_declaration_destroy + (a_this->kind.ruleset->decl_list); + a_this->kind.ruleset->decl_list = NULL; + } + g_free (a_this->kind.ruleset); + a_this->kind.ruleset = NULL; + break; + + case AT_IMPORT_RULE_STMT: + if (!a_this->kind.import_rule) + return; + if (a_this->kind.import_rule->url) { + cr_string_destroy + (a_this->kind.import_rule->url) ; + a_this->kind.import_rule->url = NULL; + } + g_free (a_this->kind.import_rule); + a_this->kind.import_rule = NULL; + break; + + case AT_MEDIA_RULE_STMT: + if (!a_this->kind.media_rule) + return; + if (a_this->kind.media_rule->rulesets) { + cr_statement_destroy + (a_this->kind.media_rule->rulesets); + a_this->kind.media_rule->rulesets = NULL; + } + if (a_this->kind.media_rule->media_list) { + GList *cur = NULL; + + for (cur = a_this->kind.media_rule->media_list; + cur; cur = cur->next) { + if (cur->data) { + cr_string_destroy ((CRString *) cur->data); + cur->data = NULL; + } + + } + g_list_free (a_this->kind.media_rule->media_list); + a_this->kind.media_rule->media_list = NULL; + } + g_free (a_this->kind.media_rule); + a_this->kind.media_rule = NULL; + break; + + case AT_PAGE_RULE_STMT: + if (!a_this->kind.page_rule) + return; + + if (a_this->kind.page_rule->decl_list) { + cr_declaration_destroy + (a_this->kind.page_rule->decl_list); + a_this->kind.page_rule->decl_list = NULL; + } + if (a_this->kind.page_rule->name) { + cr_string_destroy + (a_this->kind.page_rule->name); + a_this->kind.page_rule->name = NULL; + } + if (a_this->kind.page_rule->pseudo) { + cr_string_destroy + (a_this->kind.page_rule->pseudo); + a_this->kind.page_rule->pseudo = NULL; + } + g_free (a_this->kind.page_rule); + a_this->kind.page_rule = NULL; + break; + + case AT_CHARSET_RULE_STMT: + if (!a_this->kind.charset_rule) + return; + + if (a_this->kind.charset_rule->charset) { + cr_string_destroy + (a_this->kind.charset_rule->charset); + a_this->kind.charset_rule->charset = NULL; + } + g_free (a_this->kind.charset_rule); + a_this->kind.charset_rule = NULL; + break; + + case AT_FONT_FACE_RULE_STMT: + if (!a_this->kind.font_face_rule) + return; + + if (a_this->kind.font_face_rule->decl_list) { + cr_declaration_unref + (a_this->kind.font_face_rule->decl_list); + a_this->kind.font_face_rule->decl_list = NULL; + } + g_free (a_this->kind.font_face_rule); + a_this->kind.font_face_rule = NULL; + break; + + default: + break; + } +} + +/** + * cr_statement_ruleset_to_string: + * + *@a_this: the current instance of #CRStatement + *@a_indent: the number of whitespace to use for indentation + * + *Serializes the ruleset statement into a string + * + *Returns the newly allocated serialised string. Must be freed + *by the caller, using g_free(). + */ +static gchar * +cr_statement_ruleset_to_string (CRStatement * a_this, glong a_indent) +{ + GString *stringue = NULL; + gchar *tmp_str = NULL, + *result = NULL; + + g_return_val_if_fail (a_this && a_this->type == RULESET_STMT, NULL); + + stringue = g_string_new (NULL); + + if (a_this->kind.ruleset->sel_list) { + if (a_indent) + cr_utils_dump_n_chars2 (' ', stringue, a_indent); + + tmp_str = + cr_selector_to_string (a_this->kind.ruleset-> + sel_list); + if (tmp_str) { + g_string_append (stringue, tmp_str); + g_free (tmp_str); + tmp_str = NULL; + } + } + g_string_append (stringue, " {\n"); + if (a_this->kind.ruleset->decl_list) { + tmp_str = cr_declaration_list_to_string2 + (a_this->kind.ruleset->decl_list, + a_indent + DECLARATION_INDENT_NB, TRUE); + if (tmp_str) { + g_string_append (stringue, tmp_str); + g_free (tmp_str); + tmp_str = NULL; + } + g_string_append (stringue, "\n"); + cr_utils_dump_n_chars2 (' ', stringue, a_indent); + } + g_string_append (stringue, "}"); + result = stringue->str; + + if (stringue) { + g_string_free (stringue, FALSE); + stringue = NULL; + } + if (tmp_str) { + g_free (tmp_str); + tmp_str = NULL; + } + return result; +} + + +/** + * cr_statement_font_face_rule_to_string: + * + *@a_this: the current instance of #CRStatement to consider + *It must be a font face rule statement. + *@a_indent: the number of white spaces of indentation. + * + *Serializes a font face rule statement into a string. + * + *Returns the serialized string. Must be deallocated by the caller + *using g_free(). + */ +static gchar * +cr_statement_font_face_rule_to_string (CRStatement * a_this, + glong a_indent) +{ + gchar *result = NULL, *tmp_str = NULL ; + GString *stringue = NULL ; + + g_return_val_if_fail (a_this + && a_this->type == AT_FONT_FACE_RULE_STMT, + NULL); + + if (a_this->kind.font_face_rule->decl_list) { + stringue = g_string_new (NULL) ; + g_return_val_if_fail (stringue, NULL) ; + if (a_indent) + cr_utils_dump_n_chars2 (' ', stringue, + a_indent); + g_string_append (stringue, "@font-face {\n"); + tmp_str = cr_declaration_list_to_string2 + (a_this->kind.font_face_rule->decl_list, + a_indent + DECLARATION_INDENT_NB, TRUE) ; + if (tmp_str) { + g_string_append (stringue, + tmp_str) ; + g_free (tmp_str) ; + tmp_str = NULL ; + } + g_string_append (stringue, "\n}"); + } + if (stringue) { + result = stringue->str ; + g_string_free (stringue, FALSE) ; + stringue = NULL ; + } + return result ; +} + + +/** + * cr_statetement_charset_to_string: + * + *Serialises an @charset statement into a string. + *@a_this: the statement to serialize. + *@a_indent: the number of indentation spaces + *Returns the serialized charset statement. Must be + *freed by the caller using g_free(). + */ +static gchar * +cr_statement_charset_to_string (CRStatement *a_this, + gulong a_indent) +{ + gchar *str = NULL ; + GString *stringue = NULL ; + + g_return_val_if_fail (a_this + && a_this->type == AT_CHARSET_RULE_STMT, + NULL) ; + + if (a_this->kind.charset_rule + && a_this->kind.charset_rule->charset + && a_this->kind.charset_rule->charset->stryng + && a_this->kind.charset_rule->charset->stryng->str) { + str = g_strndup (a_this->kind.charset_rule->charset->stryng->str, + a_this->kind.charset_rule->charset->stryng->len); + g_return_val_if_fail (str, NULL); + stringue = g_string_new (NULL) ; + g_return_val_if_fail (stringue, NULL) ; + cr_utils_dump_n_chars2 (' ', stringue, a_indent); + g_string_append_printf (stringue, + "@charset \"%s\" ;", str); + if (str) { + g_free (str); + str = NULL; + } + } + if (stringue) { + str = stringue->str ; + g_string_free (stringue, FALSE) ; + } + return str ; +} + + +/** + * cr_statement_at_page_rule_to_string: + * + *Serialises the at page rule statement into a string + *@a_this: the current instance of #CRStatement. Must + *be an "@page" rule statement. + *Returns the serialized string. Must be freed by the caller + */ +static gchar * +cr_statement_at_page_rule_to_string (CRStatement *a_this, + gulong a_indent) +{ + GString *stringue = NULL; + gchar *result = NULL ; + + stringue = g_string_new (NULL) ; + + cr_utils_dump_n_chars2 (' ', stringue, a_indent) ; + g_string_append (stringue, "@page"); + if (a_this->kind.page_rule->name + && a_this->kind.page_rule->name->stryng) { + g_string_append_printf + (stringue, " %s", + a_this->kind.page_rule->name->stryng->str) ; + } else { + g_string_append (stringue, " "); + } + if (a_this->kind.page_rule->pseudo + && a_this->kind.page_rule->pseudo->stryng) { + g_string_append_printf + (stringue, " :%s", + a_this->kind.page_rule->pseudo->stryng->str) ; + } + if (a_this->kind.page_rule->decl_list) { + gchar *str = NULL ; + g_string_append (stringue, " {\n"); + str = cr_declaration_list_to_string2 + (a_this->kind.page_rule->decl_list, + a_indent + DECLARATION_INDENT_NB, TRUE) ; + if (str) { + g_string_append (stringue, str) ; + g_free (str) ; + str = NULL ; + } + g_string_append (stringue, "\n}\n"); + } + result = stringue->str ; + g_string_free (stringue, FALSE) ; + stringue = NULL ; + return result ; +} + + +/** + *Serializes an @media statement. + *@param a_this the current instance of #CRStatement + *@param a_indent the number of spaces of indentation. + *@return the serialized @media statement. Must be freed + *by the caller using g_free(). + */ +static gchar * +cr_statement_media_rule_to_string (CRStatement *a_this, + gulong a_indent) +{ + gchar *str = NULL ; + GString *stringue = NULL ; + GList *cur = NULL; + + g_return_val_if_fail (a_this->type == AT_MEDIA_RULE_STMT, + NULL); + + if (a_this->kind.media_rule) { + stringue = g_string_new (NULL) ; + cr_utils_dump_n_chars2 (' ', stringue, a_indent); + g_string_append (stringue, "@media"); + + for (cur = a_this->kind.media_rule->media_list; cur; + cur = cur->next) { + if (cur->data) { + guchar *str = cr_string_dup2 + ((CRString *) cur->data); + + if (str) { + if (cur->prev) { + g_string_append + (stringue, + ","); + } + g_string_append_printf + (stringue, + " %s", str); + g_free (str); + str = NULL; + } + } + } + g_string_append (stringue, " {\n"); + str = cr_statement_list_to_string + (a_this->kind.media_rule->rulesets, + a_indent + DECLARATION_INDENT_NB) ; + if (str) { + g_string_append (stringue, str) ; + g_free (str) ; + str = NULL ; + } + g_string_append (stringue, "\n}"); + } + if (stringue) { + str = stringue->str ; + g_string_free (stringue, FALSE) ; + } + return str ; +} + + +static gchar * +cr_statement_import_rule_to_string (CRStatement *a_this, + gulong a_indent) +{ + GString *stringue = NULL ; + guchar *str = NULL; + + g_return_val_if_fail (a_this + && a_this->type == AT_IMPORT_RULE_STMT + && a_this->kind.import_rule, + NULL) ; + + if (a_this->kind.import_rule->url + && a_this->kind.import_rule->url->stryng) { + stringue = g_string_new (NULL) ; + g_return_val_if_fail (stringue, NULL) ; + str = g_strndup (a_this->kind.import_rule->url->stryng->str, + a_this->kind.import_rule->url->stryng->len); + cr_utils_dump_n_chars2 (' ', stringue, a_indent); + if (str) { + g_string_append_printf (stringue, + "@import url(\"%s\")", + str); + g_free (str); + str = NULL ; + } else /*there is no url, so no import rule, get out! */ + return NULL; + + if (a_this->kind.import_rule->media_list) { + GList *cur = NULL; + + for (cur = a_this->kind.import_rule->media_list; + cur; cur = cur->next) { + if (cur->data) { + CRString *crstr = cur->data; + + if (cur->prev) { + g_string_append + (stringue, ", "); + } + if (crstr + && crstr->stryng + && crstr->stryng->str) { + g_string_append_len + (stringue, + crstr->stryng->str, + crstr->stryng->len) ; + } + } + } + } + g_string_append (stringue, " ;"); + } + if (stringue) { + str = stringue->str ; + g_string_free (stringue, FALSE) ; + stringue = NULL ; + } + return str ; +} + + +/******************* + *public functions + ******************/ + +/** + * cr_statement_does_buf_parses_against_core: + * + *@a_buf: the buffer to parse. + *@a_encoding: the character encoding of a_buf. + * + *Tries to parse a buffer and says whether if the content of the buffer + *is a css statement as defined by the "Core CSS Grammar" (chapter 4 of the + *css spec) or not. + * + *Returns TRUE if the buffer parses against the core grammar, false otherwise. + */ +gboolean +cr_statement_does_buf_parses_against_core (const guchar * a_buf, + enum CREncoding a_encoding) +{ + CRParser *parser = NULL; + enum CRStatus status = CR_OK; + gboolean result = FALSE; + + parser = cr_parser_new_from_buf ((guchar*)a_buf, strlen (a_buf), + a_encoding, FALSE); + g_return_val_if_fail (parser, FALSE); + + status = cr_parser_set_use_core_grammar (parser, TRUE); + if (status != CR_OK) { + goto cleanup; + } + + status = cr_parser_parse_statement_core (parser); + if (status == CR_OK) { + result = TRUE; + } + + cleanup: + if (parser) { + cr_parser_destroy (parser); + } + + return result; +} + +/** + * cr_statement_parse_from_buf: + * + *@a_buf: the buffer to parse. + *@a_encoding: the character encoding of a_buf. + * + *Parses a buffer that contains a css statement and returns + *an instance of #CRStatement in case of successfull parsing. + *TODO: at support of "@import" rules. + * + *Returns the newly built instance of #CRStatement in case + *of successfull parsing, NULL otherwise. + */ +CRStatement * +cr_statement_parse_from_buf (const guchar * a_buf, enum CREncoding a_encoding) +{ + CRStatement *result = NULL; + + /* + *The strategy of this function is "brute force". + *It tries to parse all the types of #CRStatement it knows about. + *I could do this a smarter way but I don't have the time now. + *I think I will revisit this when time of performances and + *pull based incremental parsing comes. + */ + + result = cr_statement_ruleset_parse_from_buf (a_buf, a_encoding); + if (!result) { + result = cr_statement_at_charset_rule_parse_from_buf + (a_buf, a_encoding); + } else { + goto out; + } + + if (!result) { + result = cr_statement_at_media_rule_parse_from_buf + (a_buf, a_encoding); + } else { + goto out; + } + + if (!result) { + result = cr_statement_at_charset_rule_parse_from_buf + (a_buf, a_encoding); + } else { + goto out; + } + + if (!result) { + result = cr_statement_font_face_rule_parse_from_buf + (a_buf, a_encoding); + + } else { + goto out; + } + + if (!result) { + result = cr_statement_at_page_rule_parse_from_buf + (a_buf, a_encoding); + } else { + goto out; + } + + if (!result) { + result = cr_statement_at_import_rule_parse_from_buf + (a_buf, a_encoding); + } else { + goto out; + } + + out: + return result; +} + +/** + * cr_statement_ruleset_parse_from_buf: + * + *@a_buf: the buffer to parse. + *@a_enc: the character encoding of a_buf. + * + *Parses a buffer that contains a ruleset statement an instanciates + *a #CRStatement of type RULESET_STMT. + * + *Returns the newly built instance of #CRStatement in case of successfull parsing, + *NULL otherwise. + */ +CRStatement * +cr_statement_ruleset_parse_from_buf (const guchar * a_buf, + enum CREncoding a_enc) +{ + enum CRStatus status = CR_OK; + CRStatement *result = NULL; + CRStatement **resultptr = NULL; + CRParser *parser = NULL; + CRDocHandler *sac_handler = NULL; + + g_return_val_if_fail (a_buf, NULL); + + parser = cr_parser_new_from_buf ((guchar*)a_buf, strlen (a_buf), + a_enc, FALSE); + + g_return_val_if_fail (parser, NULL); + + sac_handler = cr_doc_handler_new (); + g_return_val_if_fail (parser, NULL); + + sac_handler->start_selector = parse_ruleset_start_selector_cb; + sac_handler->end_selector = parse_ruleset_end_selector_cb; + sac_handler->property = parse_ruleset_property_cb; + sac_handler->unrecoverable_error = + parse_ruleset_unrecoverable_error_cb; + + cr_parser_set_sac_handler (parser, sac_handler); + cr_parser_try_to_skip_spaces_and_comments (parser); + status = cr_parser_parse_ruleset (parser); + if (status != CR_OK) { + goto cleanup; + } + + resultptr = &result; + status = cr_doc_handler_get_result (sac_handler, + (gpointer *) resultptr); + if (!((status == CR_OK) && result)) { + if (result) { + cr_statement_destroy (result); + result = NULL; + } + } + + cleanup: + if (parser) { + cr_parser_destroy (parser); + parser = NULL; + sac_handler = NULL ; + } + if (sac_handler) { + cr_doc_handler_unref (sac_handler); + sac_handler = NULL; + } + return result; +} + +/** + * cr_statement_new_ruleset: + * + *@a_sel_list: the list of #CRSimpleSel (selectors) + *the rule applies to. + *@a_decl_list: the list of instances of #CRDeclaration + *that composes the ruleset. + *@a_media_types: a list of instances of GString that + *describe the media list this ruleset applies to. + * + *Creates a new instance of #CRStatement of type + *#CRRulSet. + * + *Returns the new instance of #CRStatement or NULL if something + *went wrong. + */ +CRStatement * +cr_statement_new_ruleset (CRStyleSheet * a_sheet, + CRSelector * a_sel_list, + CRDeclaration * a_decl_list, + CRStatement * a_parent_media_rule) +{ + CRStatement *result = NULL; + + g_return_val_if_fail (a_sel_list, NULL); + + if (a_parent_media_rule) { + g_return_val_if_fail + (a_parent_media_rule->type == AT_MEDIA_RULE_STMT, + NULL); + g_return_val_if_fail (a_parent_media_rule->kind.media_rule, + NULL); + } + + result = g_try_malloc (sizeof (CRStatement)); + + if (!result) { + cr_utils_trace_info ("Out of memory"); + return NULL; + } + + memset (result, 0, sizeof (CRStatement)); + result->type = RULESET_STMT; + result->kind.ruleset = g_try_malloc (sizeof (CRRuleSet)); + + if (!result->kind.ruleset) { + cr_utils_trace_info ("Out of memory"); + if (result) + g_free (result); + return NULL; + } + + memset (result->kind.ruleset, 0, sizeof (CRRuleSet)); + result->kind.ruleset->sel_list = a_sel_list; + if (a_sel_list) + cr_selector_ref (a_sel_list); + result->kind.ruleset->decl_list = a_decl_list; + + if (a_parent_media_rule) { + result->kind.ruleset->parent_media_rule = a_parent_media_rule; + a_parent_media_rule->kind.media_rule->rulesets = + cr_statement_append + (a_parent_media_rule->kind.media_rule->rulesets, + result); + } + + cr_statement_set_parent_sheet (result, a_sheet); + + return result; +} + +/** + * cr_statement_at_media_rule_parse_from_buf: + * + *@a_buf: the input to parse. + *@a_enc: the encoding of the buffer. + * + *Parses a buffer that contains an "@media" declaration + *and builds an @media css statement. + * + *Returns the @media statement, or NULL if the buffer could not + *be successfully parsed. + */ +CRStatement * +cr_statement_at_media_rule_parse_from_buf (const guchar * a_buf, + enum CREncoding a_enc) +{ + CRParser *parser = NULL; + CRStatement *result = NULL; + CRStatement **resultptr = NULL; + CRDocHandler *sac_handler = NULL; + enum CRStatus status = CR_OK; + + parser = cr_parser_new_from_buf ((guchar*)a_buf, strlen (a_buf), + a_enc, FALSE); + if (!parser) { + cr_utils_trace_info ("Instanciation of the parser failed"); + goto cleanup; + } + + sac_handler = cr_doc_handler_new (); + if (!sac_handler) { + cr_utils_trace_info + ("Instanciation of the sac handler failed"); + goto cleanup; + } + + sac_handler->start_media = parse_at_media_start_media_cb; + sac_handler->start_selector = parse_at_media_start_selector_cb; + sac_handler->property = parse_at_media_property_cb; + sac_handler->end_selector = parse_at_media_end_selector_cb; + sac_handler->end_media = parse_at_media_end_media_cb; + sac_handler->unrecoverable_error = + parse_at_media_unrecoverable_error_cb; + + status = cr_parser_set_sac_handler (parser, sac_handler); + if (status != CR_OK) + goto cleanup; + + status = cr_parser_try_to_skip_spaces_and_comments (parser); + if (status != CR_OK) + goto cleanup; + + status = cr_parser_parse_media (parser); + if (status != CR_OK) + goto cleanup; + + resultptr = &result; + status = cr_doc_handler_get_result (sac_handler, + (gpointer *) resultptr); + if (status != CR_OK) + goto cleanup; + + cleanup: + + if (parser) { + cr_parser_destroy (parser); + parser = NULL; + sac_handler = NULL ; + } + if (sac_handler) { + cr_doc_handler_unref (sac_handler); + sac_handler = NULL; + } + + return result; +} + +/** + * cr_statement_new_at_media_rule: + * + *@a_ruleset: the ruleset statements contained + *in the @media rule. + *@a_media: the media string list. A list of GString pointers. + * + *Instanciates an instance of #CRStatement of type + *AT_MEDIA_RULE_STMT (@media ruleset). + * + */ +CRStatement * +cr_statement_new_at_media_rule (CRStyleSheet * a_sheet, + CRStatement * a_rulesets, GList * a_media) +{ + CRStatement *result = NULL, + *cur = NULL; + + if (a_rulesets) + g_return_val_if_fail (a_rulesets->type == RULESET_STMT, NULL); + + result = g_try_malloc (sizeof (CRStatement)); + + if (!result) { + cr_utils_trace_info ("Out of memory"); + return NULL; + } + + memset (result, 0, sizeof (CRStatement)); + result->type = AT_MEDIA_RULE_STMT; + + result->kind.media_rule = g_try_malloc (sizeof (CRAtMediaRule)); + if (!result->kind.media_rule) { + cr_utils_trace_info ("Out of memory"); + g_free (result); + return NULL; + } + memset (result->kind.media_rule, 0, sizeof (CRAtMediaRule)); + result->kind.media_rule->rulesets = a_rulesets; + for (cur = a_rulesets; cur; cur = cur->next) { + if (cur->type != RULESET_STMT || !cur->kind.ruleset) { + cr_utils_trace_info ("Bad parameter a_rulesets. " + "It should be a list of " + "correct ruleset statement only !"); + goto error; + } + cur->kind.ruleset->parent_media_rule = result; + } + + result->kind.media_rule->media_list = a_media; + if (a_sheet) { + cr_statement_set_parent_sheet (result, a_sheet); + } + + return result; + + error: + return NULL; +} + +/** + * cr_statement_new_at_import_rule: + * + *@a_url: the url to connect to the get the file + *to be imported. + *@a_sheet: the imported parsed stylesheet. + * + *Creates a new instance of #CRStatment of type + *#CRAtImportRule. + * + *Returns the newly built instance of #CRStatement. + */ +CRStatement * +cr_statement_new_at_import_rule (CRStyleSheet * a_container_sheet, + CRString * a_url, + GList * a_media_list, + CRStyleSheet * a_imported_sheet) +{ + CRStatement *result = NULL; + + result = g_try_malloc (sizeof (CRStatement)); + + if (!result) { + cr_utils_trace_info ("Out of memory"); + return NULL; + } + + memset (result, 0, sizeof (CRStatement)); + result->type = AT_IMPORT_RULE_STMT; + + result->kind.import_rule = g_try_malloc (sizeof (CRAtImportRule)); + + if (!result->kind.import_rule) { + cr_utils_trace_info ("Out of memory"); + g_free (result); + return NULL; + } + + memset (result->kind.import_rule, 0, sizeof (CRAtImportRule)); + result->kind.import_rule->url = a_url; + result->kind.import_rule->media_list = a_media_list; + result->kind.import_rule->sheet = a_imported_sheet; + if (a_container_sheet) + cr_statement_set_parent_sheet (result, a_container_sheet); + + return result; +} + +/** + * cr_statement_at_import_rule_parse_from_buf: + * + *@a_buf: the buffer to parse. + *@a_encoding: the encoding of a_buf. + * + *Parses a buffer that contains an "@import" rule and + *instanciate a #CRStatement of type AT_IMPORT_RULE_STMT + * + *Returns the newly built instance of #CRStatement in case of + *a successfull parsing, NULL otherwise. + */ +CRStatement * +cr_statement_at_import_rule_parse_from_buf (const guchar * a_buf, + enum CREncoding a_encoding) +{ + enum CRStatus status = CR_OK; + CRParser *parser = NULL; + CRStatement *result = NULL; + GList *media_list = NULL; + CRString *import_string = NULL; + CRParsingLocation location = {0} ; + + parser = cr_parser_new_from_buf ((guchar*)a_buf, strlen (a_buf), + a_encoding, FALSE); + if (!parser) { + cr_utils_trace_info ("Instanciation of parser failed."); + goto cleanup; + } + + status = cr_parser_try_to_skip_spaces_and_comments (parser); + if (status != CR_OK) + goto cleanup; + + status = cr_parser_parse_import (parser, + &media_list, + &import_string, + &location); + if (status != CR_OK || !import_string) + goto cleanup; + + result = cr_statement_new_at_import_rule (NULL, import_string, + media_list, NULL); + if (result) { + cr_parsing_location_copy (&result->location, + &location) ; + import_string = NULL; + media_list = NULL; + } + + cleanup: + if (parser) { + cr_parser_destroy (parser); + parser = NULL; + } + if (media_list) { + GList *cur = NULL; + + for (cur = media_list; media_list; + media_list = g_list_next (media_list)) { + if (media_list->data) { + cr_string_destroy ((CRString*)media_list->data); + media_list->data = NULL; + } + } + g_list_free (media_list); + media_list = NULL; + } + if (import_string) { + cr_string_destroy (import_string); + import_string = NULL; + } + + return result; +} + +/** + * cr_statement_new_at_page_rule: + * + *@a_decl_list: a list of instances of #CRDeclarations + *which is actually the list of declarations that applies to + *this page rule. + *@a_selector: the page rule selector. + * + *Creates a new instance of #CRStatement of type + *#CRAtPageRule. + * + *Returns the newly built instance of #CRStatement or NULL + *in case of error. + */ +CRStatement * +cr_statement_new_at_page_rule (CRStyleSheet * a_sheet, + CRDeclaration * a_decl_list, + CRString * a_name, CRString * a_pseudo) +{ + CRStatement *result = NULL; + + result = g_try_malloc (sizeof (CRStatement)); + + if (!result) { + cr_utils_trace_info ("Out of memory"); + return NULL; + } + + memset (result, 0, sizeof (CRStatement)); + result->type = AT_PAGE_RULE_STMT; + + result->kind.page_rule = g_try_malloc (sizeof (CRAtPageRule)); + + if (!result->kind.page_rule) { + cr_utils_trace_info ("Out of memory"); + g_free (result); + return NULL; + } + + memset (result->kind.page_rule, 0, sizeof (CRAtPageRule)); + if (a_decl_list) { + result->kind.page_rule->decl_list = a_decl_list; + cr_declaration_ref (a_decl_list); + } + result->kind.page_rule->name = a_name; + result->kind.page_rule->pseudo = a_pseudo; + if (a_sheet) + cr_statement_set_parent_sheet (result, a_sheet); + + return result; +} + +/** + * cr_statement_at_page_rule_parse_from_buf: + * + *@a_buf: the character buffer to parse. + *@a_encoding: the character encoding of a_buf. + * + *Parses a buffer that contains an "@page" production and, + *if the parsing succeeds, builds the page statement. + * + *Returns the newly built at page statement in case of successfull parsing, + *NULL otherwise. + */ +CRStatement * +cr_statement_at_page_rule_parse_from_buf (const guchar * a_buf, + enum CREncoding a_encoding) +{ + enum CRStatus status = CR_OK; + CRParser *parser = NULL; + CRDocHandler *sac_handler = NULL; + CRStatement *result = NULL; + CRStatement **resultptr = NULL; + + g_return_val_if_fail (a_buf, NULL); + + parser = cr_parser_new_from_buf ((guchar*)a_buf, strlen (a_buf), + a_encoding, FALSE); + if (!parser) { + cr_utils_trace_info ("Instanciation of the parser failed."); + goto cleanup; + } + + sac_handler = cr_doc_handler_new (); + if (!sac_handler) { + cr_utils_trace_info + ("Instanciation of the sac handler failed."); + goto cleanup; + } + + sac_handler->start_page = parse_page_start_page_cb; + sac_handler->property = parse_page_property_cb; + sac_handler->end_page = parse_page_end_page_cb; + sac_handler->unrecoverable_error = parse_page_unrecoverable_error_cb; + + status = cr_parser_set_sac_handler (parser, sac_handler); + if (status != CR_OK) + goto cleanup; + + /*Now, invoke the parser to parse the "@page production" */ + cr_parser_try_to_skip_spaces_and_comments (parser); + if (status != CR_OK) + goto cleanup; + status = cr_parser_parse_page (parser); + if (status != CR_OK) + goto cleanup; + + resultptr = &result; + status = cr_doc_handler_get_result (sac_handler, + (gpointer *) resultptr); + + cleanup: + + if (parser) { + cr_parser_destroy (parser); + parser = NULL; + sac_handler = NULL ; + } + if (sac_handler) { + cr_doc_handler_unref (sac_handler); + sac_handler = NULL; + } + return result; +} + +/** + * cr_statement_new_at_charset_rule: + * + *@a_charset: the string representing the charset. + *Note that the newly built instance of #CRStatement becomes + *the owner of a_charset. The caller must not free a_charset !!!. + * + *Creates a new instance of #CRStatement of type + *#CRAtCharsetRule. + * + *Returns the newly built instance of #CRStatement or NULL + *if an error arises. + */ +CRStatement * +cr_statement_new_at_charset_rule (CRStyleSheet * a_sheet, + CRString * a_charset) +{ + CRStatement *result = NULL; + + g_return_val_if_fail (a_charset, NULL); + + result = g_try_malloc (sizeof (CRStatement)); + + if (!result) { + cr_utils_trace_info ("Out of memory"); + return NULL; + } + + memset (result, 0, sizeof (CRStatement)); + result->type = AT_CHARSET_RULE_STMT; + + result->kind.charset_rule = g_try_malloc (sizeof (CRAtCharsetRule)); + + if (!result->kind.charset_rule) { + cr_utils_trace_info ("Out of memory"); + g_free (result); + return NULL; + } + memset (result->kind.charset_rule, 0, sizeof (CRAtCharsetRule)); + result->kind.charset_rule->charset = a_charset; + cr_statement_set_parent_sheet (result, a_sheet); + + return result; +} + +/** + * cr_statement_at_charset_rule_parse_from_buf: + * + *@a_buf: the buffer to parse. + *@a_encoding: the character encoding of the buffer. + * + *Parses a buffer that contains an '@charset' rule and + *creates an instance of #CRStatement of type AT_CHARSET_RULE_STMT. + * + *Returns the newly built instance of #CRStatement. + */ +CRStatement * +cr_statement_at_charset_rule_parse_from_buf (const guchar * a_buf, + enum CREncoding a_encoding) +{ + enum CRStatus status = CR_OK; + CRParser *parser = NULL; + CRStatement *result = NULL; + CRString *charset = NULL; + + g_return_val_if_fail (a_buf, NULL); + + parser = cr_parser_new_from_buf ((guchar*)a_buf, strlen (a_buf), + a_encoding, FALSE); + if (!parser) { + cr_utils_trace_info ("Instanciation of the parser failed."); + goto cleanup; + } + + /*Now, invoke the parser to parse the "@charset production" */ + cr_parser_try_to_skip_spaces_and_comments (parser); + if (status != CR_OK) + goto cleanup; + status = cr_parser_parse_charset (parser, &charset, NULL); + if (status != CR_OK || !charset) + goto cleanup; + + result = cr_statement_new_at_charset_rule (NULL, charset); + if (result) + charset = NULL; + + cleanup: + + if (parser) { + cr_parser_destroy (parser); + parser = NULL; + } + if (charset) { + cr_string_destroy (charset); + } + + return result; +} + +/** + * cr_statemeent_new_at_font_face_rule: + * + *@a_font_decls: a list of instances of #CRDeclaration. Each declaration + *is actually a font declaration. + * + *Creates an instance of #CRStatement of type #CRAtFontFaceRule. + * + *Returns the newly built instance of #CRStatement. + */ +CRStatement * +cr_statement_new_at_font_face_rule (CRStyleSheet * a_sheet, + CRDeclaration * a_font_decls) +{ + CRStatement *result = NULL; + + result = g_try_malloc (sizeof (CRStatement)); + + if (!result) { + cr_utils_trace_info ("Out of memory"); + return NULL; + } + memset (result, 0, sizeof (CRStatement)); + result->type = AT_FONT_FACE_RULE_STMT; + + result->kind.font_face_rule = g_try_malloc + (sizeof (CRAtFontFaceRule)); + + if (!result->kind.font_face_rule) { + cr_utils_trace_info ("Out of memory"); + g_free (result); + return NULL; + } + memset (result->kind.font_face_rule, 0, sizeof (CRAtFontFaceRule)); + + result->kind.font_face_rule->decl_list = a_font_decls; + if (a_sheet) + cr_statement_set_parent_sheet (result, a_sheet); + + return result; +} + +/** + * cr_statement_font_face_rule_parse_from_buf: + * + * + *@a_buf: the buffer to parse. + *@a_encoding: the character encoding of a_buf. + * + *Parses a buffer that contains an "@font-face" rule and builds + *an instance of #CRStatement of type AT_FONT_FACE_RULE_STMT out of it. + * + *Returns the newly built instance of #CRStatement in case of successufull + *parsing, NULL otherwise. + */ +CRStatement * +cr_statement_font_face_rule_parse_from_buf (const guchar * a_buf, + enum CREncoding a_encoding) +{ + CRStatement *result = NULL; + CRStatement **resultptr = NULL; + CRParser *parser = NULL; + CRDocHandler *sac_handler = NULL; + enum CRStatus status = CR_OK; + + parser = cr_parser_new_from_buf ((guchar*)a_buf, strlen (a_buf), + a_encoding, FALSE); + if (!parser) + goto cleanup; + + sac_handler = cr_doc_handler_new (); + if (!sac_handler) + goto cleanup; + + /* + *set sac callbacks here + */ + sac_handler->start_font_face = parse_font_face_start_font_face_cb; + sac_handler->property = parse_font_face_property_cb; + sac_handler->end_font_face = parse_font_face_end_font_face_cb; + sac_handler->unrecoverable_error = + parse_font_face_unrecoverable_error_cb; + + status = cr_parser_set_sac_handler (parser, sac_handler); + if (status != CR_OK) + goto cleanup; + + /* + *cleanup spaces of comment that may be there before the real + *"@font-face" thing. + */ + status = cr_parser_try_to_skip_spaces_and_comments (parser); + if (status != CR_OK) + goto cleanup; + + status = cr_parser_parse_font_face (parser); + if (status != CR_OK) + goto cleanup; + + resultptr = &result; + status = cr_doc_handler_get_result (sac_handler, + (gpointer *) resultptr); + if (status != CR_OK || !result) + goto cleanup; + + cleanup: + if (parser) { + cr_parser_destroy (parser); + parser = NULL; + sac_handler = NULL ; + } + if (sac_handler) { + cr_doc_handler_unref (sac_handler); + sac_handler = NULL; + } + return result; +} + +/** + * cr_statement_set_parent_sheet: + * + *@a_this: the current instance of #CRStatement. + *@a_sheet: the sheet that contains the current statement. + * + *Sets the container stylesheet. + * + *Returns CR_OK upon successfull completion, an errror code otherwise. + */ +enum CRStatus +cr_statement_set_parent_sheet (CRStatement * a_this, CRStyleSheet * a_sheet) +{ + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); + a_this->parent_sheet = a_sheet; + return CR_OK; +} + +/** + * cr_statement_get_parent_sheet: + * + *@a_this: the current #CRStatement. + *@a_sheet: out parameter. A pointer to the sheets that + * + *Gets the sheets that contains the current statement. + * + *Returns CR_OK upon successfull completion, an error code otherwise. + */ +enum CRStatus +cr_statement_get_parent_sheet (CRStatement * a_this, CRStyleSheet ** a_sheet) +{ + g_return_val_if_fail (a_this && a_sheet, CR_BAD_PARAM_ERROR); + *a_sheet = a_this->parent_sheet; + return CR_OK; +} + +/** + * cr_statement_append: + * + *@a_this: the current instance of the statement list. + *@a_new: a_new the new instance of #CRStatement to append. + * + *Appends a new statement to the statement list. + * + *Returns the new list statement list, or NULL in cas of failure. + */ +CRStatement * +cr_statement_append (CRStatement * a_this, CRStatement * a_new) +{ + CRStatement *cur = NULL; + + g_return_val_if_fail (a_new, NULL); + + if (!a_this) { + return a_new; + } + + /*walk forward in the current list to find the tail list element */ + for (cur = a_this; cur && cur->next; cur = cur->next) ; + + cur->next = a_new; + a_new->prev = cur; + + return a_this; +} + +/** + * cr_statement_prepend: + * + *@a_this: the current instance of #CRStatement. + *@a_new: the new statement to prepend. + * + *Prepends the an instance of #CRStatement to + *the current statement list. + * + *Returns the new list with the new statement prepended, + *or NULL in case of an error. + */ +CRStatement * +cr_statement_prepend (CRStatement * a_this, CRStatement * a_new) +{ + CRStatement *cur = NULL; + + g_return_val_if_fail (a_new, NULL); + + if (!a_this) + return a_new; + + a_new->next = a_this; + a_this->prev = a_new; + + /*walk backward in the prepended list to find the head list element */ + for (cur = a_new; cur && cur->prev; cur = cur->prev) ; + + return cur; +} + +/** + * cr_statement_unlink: + * + *@a_this: the current statements list. + *@a_to_unlink: the statement to unlink from the list. + *Returns the new list where a_to_unlink has been unlinked + * + *Unlinks a statement from the statements list. + * + *from, or NULL in case of error. + */ +CRStatement * +cr_statement_unlink (CRStatement * a_stmt) +{ + CRStatement *result = a_stmt; + + g_return_val_if_fail (result, NULL); + + /** + *Some sanity checks first + */ + if (a_stmt->next) { + g_return_val_if_fail (a_stmt->next->prev == a_stmt, NULL); + } + if (a_stmt->prev) { + g_return_val_if_fail (a_stmt->prev->next == a_stmt, NULL); + } + + /** + *Now, the real unlinking job. + */ + if (a_stmt->next) { + a_stmt->next->prev = a_stmt->prev; + } + if (a_stmt->prev) { + a_stmt->prev->next = a_stmt->next; + } + + if (a_stmt->parent_sheet + && a_stmt->parent_sheet->statements == a_stmt) { + a_stmt->parent_sheet->statements = + a_stmt->parent_sheet->statements->next; + } + + a_stmt->next = NULL; + a_stmt->prev = NULL; + a_stmt->parent_sheet = NULL; + + return result; +} + +/** + * cr_statement_nr_rules: + * + *@a_this: the current instance of #CRStatement. + * + *Gets the number of rules in the statement list; + * + *Returns number of rules in the statement list. + */ +gint +cr_statement_nr_rules (CRStatement * a_this) +{ + CRStatement *cur = NULL; + int nr = 0; + + g_return_val_if_fail (a_this, -1); + + for (cur = a_this; cur; cur = cur->next) + nr++; + return nr; +} + +/** + * cr_statement_get_from_list: + * + *@a_this: the current instance of #CRStatement. + *@itemnr: the index into the statement list. + * + *Use an index to get a CRStatement from the statement list. + * + *Returns CRStatement at position itemnr, if itemnr > number of statements - 1, + *it will return NULL. + */ +CRStatement * +cr_statement_get_from_list (CRStatement * a_this, int itemnr) +{ + CRStatement *cur = NULL; + int nr = 0; + + g_return_val_if_fail (a_this, NULL); + + for (cur = a_this; cur; cur = cur->next) + if (nr++ == itemnr) + return cur; + return NULL; +} + +/** + * cr_statement_ruleset_set_sel_list: + * + *@a_this: the current ruleset statement. + *@a_sel_list: the selector list to set. Note + *that this function increments the ref count of a_sel_list. + *The sel list will be destroyed at the destruction of the + *current instance of #CRStatement. + * + *Sets a selector list to a ruleset statement. + * + *Returns CR_OK upon successfull completion, an error code otherwise. + */ +enum CRStatus +cr_statement_ruleset_set_sel_list (CRStatement * a_this, + CRSelector * a_sel_list) +{ + g_return_val_if_fail (a_this && a_this->type == RULESET_STMT, + CR_BAD_PARAM_ERROR); + + if (a_this->kind.ruleset->sel_list) + cr_selector_unref (a_this->kind.ruleset->sel_list); + + a_this->kind.ruleset->sel_list = a_sel_list; + + if (a_sel_list) + cr_selector_ref (a_sel_list); + + return CR_OK; +} + +/** + * cr_statement_ruleset_get_declarations: + * + *@a_this: the current instance of #CRStatement. + *@a_decl_list: out parameter. A pointer to the the returned + *list of declaration. Must not be NULL. + * + *Gets a pointer to the list of declaration contained + *in the ruleset statement. + * + *Returns CR_OK upon successfull completion, an error code if something + *bad happened. + */ +enum CRStatus +cr_statement_ruleset_get_declarations (CRStatement * a_this, + CRDeclaration ** a_decl_list) +{ + g_return_val_if_fail (a_this + && a_this->type == RULESET_STMT + && a_this->kind.ruleset + && a_decl_list, CR_BAD_PARAM_ERROR); + + *a_decl_list = a_this->kind.ruleset->decl_list; + + return CR_OK; +} + +/** + * cr_statement_get_sel_list: + * + *@a_this: the current ruleset statement. + *@a_list: out parameter. The returned selector list, + *if and only if the function returned CR_OK. + * + *Gets a pointer to the selector list contained in + *the current ruleset statement. + * + *Returns CR_OK upon successfull completion, an error code otherwise. + */ +enum CRStatus +cr_statement_ruleset_get_sel_list (CRStatement * a_this, CRSelector ** a_list) +{ + g_return_val_if_fail (a_this && a_this->type == RULESET_STMT + && a_this->kind.ruleset, CR_BAD_PARAM_ERROR); + + *a_list = a_this->kind.ruleset->sel_list; + + return CR_OK; +} + +/** + * cr_statement_ruleset_sel_decl_list: + * + *@a_this: the current ruleset statement. + *@a_list: the declaration list to be added to the current + *ruleset statement. + * + *Sets a declaration list to the current ruleset statement. + * + *Returns CR_OK upon successfull completion, an error code otherwise. + */ +enum CRStatus +cr_statement_ruleset_set_decl_list (CRStatement * a_this, + CRDeclaration * a_list) +{ + g_return_val_if_fail (a_this && a_this->type == RULESET_STMT + && a_this->kind.ruleset, CR_BAD_PARAM_ERROR); + + if (a_this->kind.ruleset->decl_list == a_list) + return CR_OK; + + if (a_this->kind.ruleset->sel_list) { + cr_declaration_destroy (a_this->kind.ruleset->decl_list); + } + + a_this->kind.ruleset->sel_list = NULL; + + return CR_OK; +} + +/** + * cr_statement_ruleset_append_decl2: + * + *@a_this: the current statement. + *@a_prop: the property of the declaration. + *@a_value: the value of the declaration. + * + *Appends a declaration to the current ruleset statement. + * + *@Returns CR_OK uppon successfull completion, an error code + *otherwise. + */ +enum CRStatus +cr_statement_ruleset_append_decl2 (CRStatement * a_this, + CRString * a_prop, + CRTerm * a_value) +{ + CRDeclaration *new_decls = NULL; + + g_return_val_if_fail (a_this && a_this->type == RULESET_STMT + && a_this->kind.ruleset, CR_BAD_PARAM_ERROR); + + new_decls = cr_declaration_append2 + (a_this->kind.ruleset->decl_list, + a_prop, a_value); + g_return_val_if_fail (new_decls, CR_ERROR); + a_this->kind.ruleset->decl_list = new_decls; + + return CR_OK; +} + +/** + * cr_statement_ruleset_append_decl: + * + *Appends a declaration to the current statement. + * + *@a_this: the current statement. + *@a_declaration: the declaration to append. + *Returns CR_OK upon sucessfull completion, an error code + *otherwise. + */ +enum CRStatus +cr_statement_ruleset_append_decl (CRStatement * a_this, + CRDeclaration * a_decl) +{ + CRDeclaration *new_decls = NULL; + + g_return_val_if_fail (a_this && a_this->type == RULESET_STMT + && a_this->kind.ruleset, CR_BAD_PARAM_ERROR); + + new_decls = cr_declaration_append + (a_this->kind.ruleset->decl_list, a_decl); + g_return_val_if_fail (new_decls, CR_ERROR); + a_this->kind.ruleset->decl_list = new_decls; + + return CR_OK; +} + +/** + * cr_statement_ruleset_append_decl: + * + *Sets a stylesheet to the current @import rule. + *@a_this: the current @import rule. + *@a_sheet: the stylesheet. The stylesheet is owned + *by the current instance of #CRStatement, that is, the + *stylesheet will be destroyed when the current instance + *of #CRStatement will be destroyed. + *Returns CR_OK upon successfull completion, an error code otherwise. + */ +enum CRStatus +cr_statement_at_import_rule_set_imported_sheet (CRStatement * a_this, + CRStyleSheet * a_sheet) +{ + g_return_val_if_fail (a_this + && a_this->type == AT_IMPORT_RULE_STMT + && a_this->kind.import_rule, + CR_BAD_PARAM_ERROR); + + a_this->kind.import_rule->sheet = a_sheet; + + return CR_OK; +} + +/** + * cr_statement_at_import_rule_get_importe_sheet: + * + *@a_this: the current @import rule statement. + *@a_sheet: out parameter. The returned stylesheet if and + *only if the function returns CR_OK. + * + *Gets the stylesheet contained by the @import rule statement. + *Returns CR_OK upon sucessfull completion, an error code otherwise. + */ +enum CRStatus +cr_statement_at_import_rule_get_imported_sheet (CRStatement * a_this, + CRStyleSheet ** a_sheet) +{ + g_return_val_if_fail (a_this + && a_this->type == AT_IMPORT_RULE_STMT + && a_this->kind.import_rule, + CR_BAD_PARAM_ERROR); + *a_sheet = a_this->kind.import_rule->sheet; + return CR_OK; + +} + +/** + * cr_statement_at_import_rule_set_url: + * + *@a_this: the current @import rule statement. + *@a_url: the url to set. + * + *Sets an url to the current @import rule statement. + * + *Returns CR_OK upon successfull completion, an error code otherwise. + */ +enum CRStatus +cr_statement_at_import_rule_set_url (CRStatement * a_this, + CRString * a_url) +{ + g_return_val_if_fail (a_this + && a_this->type == AT_IMPORT_RULE_STMT + && a_this->kind.import_rule, + CR_BAD_PARAM_ERROR); + + if (a_this->kind.import_rule->url) { + cr_string_destroy (a_this->kind.import_rule->url); + } + + a_this->kind.import_rule->url = a_url; + + return CR_OK; +} + +/** + * cr_statement_at_import_rule_get_url: + * + *@a_this: the current @import rule statement. + *@a_url: out parameter. The returned url if + *and only if the function returned CR_OK. + * + *Gets the url of the @import rule statement. + *Returns CR_OK upon successful completion, an error code otherwise. + */ +enum CRStatus +cr_statement_at_import_rule_get_url (CRStatement * a_this, + CRString ** a_url) +{ + g_return_val_if_fail (a_this + && a_this->type == AT_IMPORT_RULE_STMT + && a_this->kind.import_rule, + CR_BAD_PARAM_ERROR); + + *a_url = a_this->kind.import_rule->url; + + return CR_OK; +} + +/** + * cr_statement_at_media_nr_rules: + * + *@a_this: the current instance of #CRStatement. + *Returns the number of rules in the media rule; + */ +int +cr_statement_at_media_nr_rules (CRStatement * a_this) +{ + g_return_val_if_fail (a_this + && a_this->type == AT_MEDIA_RULE_STMT + && a_this->kind.media_rule, CR_BAD_PARAM_ERROR); + + return cr_statement_nr_rules (a_this->kind.media_rule->rulesets); +} + +/** + * cr_statement_at_media_get_from_list: + * + *@a_this: the current instance of #CRStatement. + *@itemnr: the index into the media rule list of rules. + * + *Use an index to get a CRStatement from the media rule list of rules. + * + *Returns CRStatement at position itemnr, if itemnr > number of rules - 1, + *it will return NULL. + */ +CRStatement * +cr_statement_at_media_get_from_list (CRStatement * a_this, int itemnr) +{ + g_return_val_if_fail (a_this + && a_this->type == AT_MEDIA_RULE_STMT + && a_this->kind.media_rule, NULL); + + return cr_statement_get_from_list (a_this->kind.media_rule->rulesets, + itemnr); +} + +/** + * cr_statement_at_page_rule_get_declarations: + * + *@a_this: the current @page rule statement. + *@a_decl_list: the declaration list to add. Will be freed + *by the current instance of #CRStatement when it is destroyed. + * + *Sets a declaration list to the current @page rule statement. + * + *Returns CR_OK upon successfull completion, an error code otherwise. + */ +enum CRStatus +cr_statement_at_page_rule_set_declarations (CRStatement * a_this, + CRDeclaration * a_decl_list) +{ + g_return_val_if_fail (a_this + && a_this->type == AT_PAGE_RULE_STMT + && a_this->kind.page_rule, CR_BAD_PARAM_ERROR); + + if (a_this->kind.page_rule->decl_list) { + cr_declaration_unref (a_this->kind.page_rule->decl_list); + } + + a_this->kind.page_rule->decl_list = a_decl_list; + + if (a_decl_list) { + cr_declaration_ref (a_decl_list); + } + + return CR_OK; +} + +/** + * cr_statemenet_at_page_rule_get_declarations: + * + *@a_this: the current @page rule statement. + *@a_decl_list: out parameter. The returned declaration list. + * + *Gets the declaration list associated to the current @page rule + *statement. + * + *Returns CR_OK upon successfull completion, an error code otherwise. + */ +enum CRStatus +cr_statement_at_page_rule_get_declarations (CRStatement * a_this, + CRDeclaration ** a_decl_list) +{ + g_return_val_if_fail (a_this + && a_this->type == AT_PAGE_RULE_STMT + && a_this->kind.page_rule, CR_BAD_PARAM_ERROR); + + *a_decl_list = a_this->kind.page_rule->decl_list; + + return CR_OK; +} + +/** + * cr_statement_at_charset_rule_set_charset: + * + * + *@a_this: the current @charset rule statement. + *@a_charset: the charset to set. + * + *Sets the charset of the current @charset rule statement. + * + *Returns CR_OK upon successfull completion, an error code otherwise. + */ +enum CRStatus +cr_statement_at_charset_rule_set_charset (CRStatement * a_this, + CRString * a_charset) +{ + g_return_val_if_fail (a_this + && a_this->type == AT_CHARSET_RULE_STMT + && a_this->kind.charset_rule, + CR_BAD_PARAM_ERROR); + + if (a_this->kind.charset_rule->charset) { + cr_string_destroy (a_this->kind.charset_rule->charset); + } + a_this->kind.charset_rule->charset = a_charset; + return CR_OK; +} + +/** + * cr_statement_at_charset_rule_get_charset: + *@a_this: the current @charset rule statement. + *@a_charset: out parameter. The returned charset string if + *and only if the function returned CR_OK. + * + *Gets the charset string associated to the current + *@charset rule statement. + * + * Returns CR_OK upon successful completion, an error code otherwise. + */ +enum CRStatus +cr_statement_at_charset_rule_get_charset (CRStatement * a_this, + CRString ** a_charset) +{ + g_return_val_if_fail (a_this + && a_this->type == AT_CHARSET_RULE_STMT + && a_this->kind.charset_rule, + CR_BAD_PARAM_ERROR); + + *a_charset = a_this->kind.charset_rule->charset; + + return CR_OK; +} + +/** + * cr_statement_at_font_face_rule_set_decls: + * + *@a_this: the current @font-face rule statement. + *@a_decls: the declarations list to set. + * + *Sets a declaration list to the current @font-face rule statement. + * + *Returns CR_OK upon successfull completion, an error code otherwise. + */ +enum CRStatus +cr_statement_at_font_face_rule_set_decls (CRStatement * a_this, + CRDeclaration * a_decls) +{ + g_return_val_if_fail (a_this + && a_this->type == AT_FONT_FACE_RULE_STMT + && a_this->kind.font_face_rule, + CR_BAD_PARAM_ERROR); + + if (a_this->kind.font_face_rule->decl_list) { + cr_declaration_unref (a_this->kind.font_face_rule->decl_list); + } + + a_this->kind.font_face_rule->decl_list = a_decls; + cr_declaration_ref (a_decls); + + return CR_OK; +} + +/** + * cr_statement_at_fot_face_rule_set_decls: + * + *@a_this: the current @font-face rule statement. + *@a_decls: out parameter. The returned declaration list if + *and only if this function returns CR_OK. + * + *Gets the declaration list associated to the current instance + *of @font-face rule statement. + * + *Returns CR_OK upon successfull completion, an error code otherwise. + */ +enum CRStatus +cr_statement_at_font_face_rule_get_decls (CRStatement * a_this, + CRDeclaration ** a_decls) +{ + g_return_val_if_fail (a_this + && a_this->type == AT_FONT_FACE_RULE_STMT + && a_this->kind.font_face_rule, + CR_BAD_PARAM_ERROR); + + *a_decls = a_this->kind.font_face_rule->decl_list; + + return CR_OK; +} + +/** + * cr_statement_at_font_face_rule_add_decl: + * + *@a_this: the current @font-face rule statement. + *@a_prop: the property of the declaration. + *@a_value: the value of the declaration. + * + *Adds a declaration to the current @font-face rule + *statement. + * + *Returns CR_OK upon successfull completion, an error code otherwise. + */ +enum CRStatus +cr_statement_at_font_face_rule_add_decl (CRStatement * a_this, + CRString * a_prop, CRTerm * a_value) +{ + CRDeclaration *decls = NULL; + + g_return_val_if_fail (a_this + && a_this->type == AT_FONT_FACE_RULE_STMT + && a_this->kind.font_face_rule, + CR_BAD_PARAM_ERROR); + + decls = cr_declaration_append2 + (a_this->kind.font_face_rule->decl_list, + a_prop, a_value); + + g_return_val_if_fail (decls, CR_ERROR); + + if (a_this->kind.font_face_rule->decl_list == NULL) + cr_declaration_ref (decls); + + a_this->kind.font_face_rule->decl_list = decls; + + return CR_OK; +} + + +/** + * cr_statement_to_string: + * + *@a_this: the current statement to serialize + *@a_indent: the number of white space of indentation. + * + *Serializes a css statement into a string + * + *Returns the serialized statement. Must be freed by the caller + *using g_free(). + */ +gchar * +cr_statement_to_string (CRStatement * a_this, gulong a_indent) +{ + gchar *str = NULL ; + + if (!a_this) + return NULL; + + switch (a_this->type) { + case RULESET_STMT: + str = cr_statement_ruleset_to_string + (a_this, a_indent); + break; + + case AT_FONT_FACE_RULE_STMT: + str = cr_statement_font_face_rule_to_string + (a_this, a_indent) ; + break; + + case AT_CHARSET_RULE_STMT: + str = cr_statement_charset_to_string + (a_this, a_indent); + break; + + case AT_PAGE_RULE_STMT: + str = cr_statement_at_page_rule_to_string + (a_this, a_indent); + break; + + case AT_MEDIA_RULE_STMT: + str = cr_statement_media_rule_to_string + (a_this, a_indent); + break; + + case AT_IMPORT_RULE_STMT: + str = cr_statement_import_rule_to_string + (a_this, a_indent); + break; + + default: + cr_utils_trace_info ("Statement unrecognized"); + break; + } + return str ; +} + +gchar* +cr_statement_list_to_string (CRStatement *a_this, gulong a_indent) +{ + CRStatement *cur_stmt = NULL ; + GString *stringue = NULL ; + gchar *str = NULL ; + + g_return_val_if_fail (a_this, NULL) ; + + stringue = g_string_new (NULL) ; + if (!stringue) { + cr_utils_trace_info ("Out of memory") ; + return NULL ; + } + for (cur_stmt = a_this ; cur_stmt; + cur_stmt = cur_stmt->next) { + str = cr_statement_to_string (cur_stmt, a_indent) ; + if (str) { + if (!cur_stmt->prev) { + g_string_append (stringue, str) ; + } else { + g_string_append_printf + (stringue, "\n%s", str) ; + } + g_free (str) ; + str = NULL ; + } + } + str = stringue->str ; + g_string_free (stringue, FALSE) ; + return str ; +} + +/** + * cr_statement_dump: + * + *@a_this: the current css2 statement. + *@a_fp: the destination file pointer. + *@a_indent: the number of white space indentation characters. + * + *Dumps the css2 statement to a file. + */ +void +cr_statement_dump (CRStatement * a_this, FILE * a_fp, gulong a_indent) +{ + gchar *str = NULL ; + + if (!a_this) + return; + + str = cr_statement_to_string (a_this, a_indent) ; + if (str) { + fprintf (a_fp, "%s",str) ; + g_free (str) ; + str = NULL ; + } +} + +/** + * cr_statement_dump_ruleset: + * + *@a_this: the current instance of #CRStatement. + *@a_fp: the destination file pointer. + *@a_indent: the number of indentation white spaces to add. + * + *Dumps a ruleset statement to a file. + */ +void +cr_statement_dump_ruleset (CRStatement * a_this, FILE * a_fp, glong a_indent) +{ + guchar *str = NULL; + + g_return_if_fail (a_fp && a_this); + str = cr_statement_ruleset_to_string (a_this, a_indent); + if (str) { + fprintf (a_fp, str); + g_free (str); + str = NULL; + } +} + +/** + * cr_statement_dump_font_face_rule: + * + *@a_this: the current instance of font face rule statement. + *@a_fp: the destination file pointer. + *@a_indent: the number of white space indentation. + * + *Dumps a font face rule statement to a file. + */ +void +cr_statement_dump_font_face_rule (CRStatement * a_this, FILE * a_fp, + glong a_indent) +{ + gchar *str = NULL ; + g_return_if_fail (a_this + && a_this->type == AT_FONT_FACE_RULE_STMT); + + str = cr_statement_font_face_rule_to_string (a_this, + a_indent) ; + if (str) { + fprintf (a_fp, "%s", str) ; + g_free (str) ; + str = NULL ; + } +} + +/** + * cr_statement_dump_charset: + * + *@a_this: the current instance of the @charset rule statement. + *@a_fp: the destination file pointer. + *@a_indent: the number of indentation white spaces. + * + *Dumps an @charset rule statement to a file. + */ +void +cr_statement_dump_charset (CRStatement * a_this, FILE * a_fp, gulong a_indent) +{ + guchar *str = NULL; + + g_return_if_fail (a_this && a_this->type == AT_CHARSET_RULE_STMT); + + str = cr_statement_charset_to_string (a_this, + a_indent) ; + if (str) { + fprintf (a_fp, str) ; + g_free (str) ; + str = NULL ; + } +} + + +/** + * cr_statement_dump_page: + * + *@a_this: the statement to dump on stdout. + *@a_fp: the destination file pointer. + *@a_indent: the number of indentation white spaces. + * + *Dumps an @page rule statement on stdout. + */ +void +cr_statement_dump_page (CRStatement * a_this, FILE * a_fp, gulong a_indent) +{ + guchar *str = NULL; + + g_return_if_fail (a_this + && a_this->type == AT_PAGE_RULE_STMT + && a_this->kind.page_rule); + + str = cr_statement_at_page_rule_to_string (a_this, a_indent) ; + if (str) { + fprintf (a_fp, str); + g_free (str) ; + str = NULL ; + } +} + + +/** + * cr_statement_dump_media_rule: + * + *@a_this: the statement to dump. + *@a_fp: the destination file pointer + *@a_indent: the number of white spaces indentation. + * + *Dumps an @media rule statement to a file. + */ +void +cr_statement_dump_media_rule (CRStatement * a_this, + FILE * a_fp, + gulong a_indent) +{ + gchar *str = NULL ; + g_return_if_fail (a_this->type == AT_MEDIA_RULE_STMT); + + str = cr_statement_media_rule_to_string (a_this, a_indent) ; + if (str) { + fprintf (a_fp, str) ; + g_free (str) ; + str = NULL ; + } +} + +/** + * cr_statement_dump_import_rule: + * + *@a_fp: the destination file pointer. + *@a_indent: the number of white space indentations. + * + *Dumps an @import rule statement to a file. + */ +void +cr_statement_dump_import_rule (CRStatement * a_this, FILE * a_fp, + gulong a_indent) +{ + gchar *str = NULL ; + g_return_if_fail (a_this + && a_this->type == AT_IMPORT_RULE_STMT + && a_fp + && a_this->kind.import_rule); + + str = cr_statement_import_rule_to_string (a_this, a_indent) ; + if (str) { + fprintf (a_fp, str) ; + g_free (str) ; + str = NULL ; + } +} + +/** + * cr_statement_destroy: + * + * @a_this: the current instance of #CRStatement. + *Destructor of #CRStatement. + */ +void +cr_statement_destroy (CRStatement * a_this) +{ + CRStatement *cur = NULL; + + g_return_if_fail (a_this); + + /*go get the tail of the list */ + for (cur = a_this; cur && cur->next; cur = cur->next) { + cr_statement_clear (cur); + } + + if (cur) + cr_statement_clear (cur); + + if (cur->prev == NULL) { + g_free (a_this); + return; + } + + /*walk backward and free next element */ + for (cur = cur->prev; cur && cur->prev; cur = cur->prev) { + if (cur->next) { + g_free (cur->next); + cur->next = NULL; + } + } + + if (!cur) + return; + + /*free the one remaining list */ + if (cur->next) { + g_free (cur->next); + cur->next = NULL; + } + + g_free (cur); + cur = NULL; +} diff --git a/gettext-tools/gnulib-lib/libcroco/cr-statement.h b/gettext-tools/gnulib-lib/libcroco/cr-statement.h new file mode 100644 index 0000000..48fc851 --- /dev/null +++ b/gettext-tools/gnulib-lib/libcroco/cr-statement.h @@ -0,0 +1,440 @@ +/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8 -*- */ + +/* + * This file is part of The Croco Library + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + * Author: Dodji Seketeli + * See COPYRIGHTS file for copyright information. + */ + +#include +#include "cr-utils.h" +#include "cr-term.h" +#include "cr-selector.h" +#include "cr-declaration.h" + +#ifndef __CR_STATEMENT_H__ +#define __CR_STATEMENT_H__ + +G_BEGIN_DECLS + +/** + *@file + *Declaration of the #CRStatement class. + */ + +/* + *forward declaration of CRStyleSheet which is defined in + *cr-stylesheet.h + */ + +struct _CRStatement ; + +/* + *typedef struct _CRStatement CRStatement ; + *this is forward declared in + *cr-declaration.h already. + */ + +struct _CRAtMediaRule ; +typedef struct _CRAtMediaRule CRAtMediaRule ; + +typedef struct _CRRuleSet CRRuleSet ; + +/** + *The abstraction of a css ruleset. + *A ruleset is made of a list of selectors, + *followed by a list of declarations. + */ +struct _CRRuleSet +{ + /**A list of instances of #CRSimpeSel*/ + CRSelector *sel_list ; + + /**A list of instances of #CRDeclaration*/ + CRDeclaration *decl_list ; + + /** + *The parent media rule, or NULL if + *no parent media rule exists. + */ + CRStatement *parent_media_rule ; +} ; + +/* + *a forward declaration of CRStylesheet. + *CRStylesheet is actually declared in + *cr-stylesheet.h + */ +struct _CRStyleSheet ; +typedef struct _CRStyleSheet CRStyleSheet; + + +/**The @import rule abstraction.*/ +typedef struct _CRAtImportRule CRAtImportRule ; +struct _CRAtImportRule +{ + /**the url of the import rule*/ + CRString *url ; + + GList *media_list ; + + /** + *the stylesheet fetched from the url, if any. + *this is not "owned" by #CRAtImportRule which means + *it is not destroyed by the destructor of #CRAtImportRule. + */ + CRStyleSheet * sheet; +}; + + +/**abstraction of an @media rule*/ +struct _CRAtMediaRule +{ + GList *media_list ; + CRStatement *rulesets ; +} ; + + +typedef struct _CRAtPageRule CRAtPageRule ; +/**The @page rule abstraction*/ +struct _CRAtPageRule +{ + /**a list of instances of #CRDeclaration*/ + CRDeclaration *decl_list ; + + /**page selector. Is a pseudo selector*/ + CRString *name ; + CRString *pseudo ; +} ; + +/**The @charset rule abstraction*/ +typedef struct _CRAtCharsetRule CRAtCharsetRule ; +struct _CRAtCharsetRule +{ + CRString * charset ; +}; + +/**The abstaction of the @font-face rule.*/ +typedef struct _CRAtFontFaceRule CRAtFontFaceRule ; +struct _CRAtFontFaceRule +{ + /*a list of instanaces of #CRDeclaration*/ + CRDeclaration *decl_list ; +} ; + + +/** + *The possible types of css2 statements. + */ +enum CRStatementType +{ + /** + *A generic css at-rule + *each unknown at-rule will + *be of this type. + */ + + /**A css at-rule*/ + AT_RULE_STMT = 0, + + /*A css ruleset*/ + RULESET_STMT, + + /**A css2 import rule*/ + AT_IMPORT_RULE_STMT, + + /**A css2 media rule*/ + AT_MEDIA_RULE_STMT, + + /**A css2 page rule*/ + AT_PAGE_RULE_STMT, + + /**A css2 charset rule*/ + AT_CHARSET_RULE_STMT, + + /**A css2 font face rule*/ + AT_FONT_FACE_RULE_STMT +} ; + + +/** + *The abstraction of css statement as defined + *in the chapter 4 and appendix D.1 of the css2 spec. + *A statement is actually a double chained list of + *statements.A statement can be a ruleset, an \@import + *rule, an \@page rule etc ... + */ +struct _CRStatement +{ + /** + *The type of the statement. + */ + enum CRStatementType type ; + + union + { + CRRuleSet *ruleset ; + CRAtImportRule *import_rule ; + CRAtMediaRule *media_rule ; + CRAtPageRule *page_rule ; + CRAtCharsetRule *charset_rule ; + CRAtFontFaceRule *font_face_rule ; + } kind ; + + /* + *the specificity of the selector + *that matched this statement. + *This is only used by the cascading + *order determination algorithm. + */ + gulong specificity ; + + /* + *the style sheet that contains + *this css statement. + */ + CRStyleSheet *parent_sheet ; + CRStatement *next ; + CRStatement *prev ; + + CRParsingLocation location ; + + /** + *a custom pointer useable by + *applications that use libcroco. + *libcroco itself will never modify + *this pointer. + */ + gpointer app_data ; + + /** + *a custom pointer used + *by the upper layers of libcroco. + *application should never use this + *pointer. + */ + gpointer croco_data ; + +} ; + + +gboolean +cr_statement_does_buf_parses_against_core (const guchar *a_buf, + enum CREncoding a_encoding) ; +CRStatement * +cr_statement_parse_from_buf (const guchar *a_buf, + enum CREncoding a_encoding) ; +CRStatement* +cr_statement_new_ruleset (CRStyleSheet *a_sheet, + CRSelector *a_sel_list, + CRDeclaration *a_decl_list, + CRStatement *a_media_rule) ; +CRStatement * +cr_statement_ruleset_parse_from_buf (const guchar * a_buf, + enum CREncoding a_enc) ; + +CRStatement* +cr_statement_new_at_import_rule (CRStyleSheet *a_container_sheet, + CRString *a_url, + GList *a_media_list, + CRStyleSheet *a_imported_sheet) ; + +CRStatement * +cr_statement_at_import_rule_parse_from_buf (const guchar * a_buf, + enum CREncoding a_encoding) ; + +CRStatement * +cr_statement_new_at_media_rule (CRStyleSheet *a_sheet, + CRStatement *a_ruleset, + GList *a_media) ; +CRStatement * +cr_statement_at_media_rule_parse_from_buf (const guchar *a_buf, + enum CREncoding a_enc) ; + +CRStatement * +cr_statement_new_at_charset_rule (CRStyleSheet *a_sheet, + CRString *a_charset) ; +CRStatement * +cr_statement_at_charset_rule_parse_from_buf (const guchar *a_buf, + enum CREncoding a_encoding); + + +CRStatement * +cr_statement_new_at_font_face_rule (CRStyleSheet *a_sheet, + CRDeclaration *a_font_decls) ; +CRStatement * +cr_statement_font_face_rule_parse_from_buf (const guchar *a_buf, + enum CREncoding a_encoding) ; + +CRStatement * +cr_statement_new_at_page_rule (CRStyleSheet *a_sheet, + CRDeclaration *a_decl_list, + CRString *a_name, + CRString *a_pseudo) ; +CRStatement * +cr_statement_at_page_rule_parse_from_buf (const guchar *a_buf, + enum CREncoding a_encoding) ; + +enum CRStatus +cr_statement_set_parent_sheet (CRStatement *a_this, + CRStyleSheet *a_sheet) ; + +enum CRStatus +cr_statement_get_parent_sheet (CRStatement *a_this, + CRStyleSheet **a_sheet) ; + +CRStatement * +cr_statement_append (CRStatement *a_this, + CRStatement *a_new) ; + +CRStatement* +cr_statement_prepend (CRStatement *a_this, + CRStatement *a_new) ; + +CRStatement * +cr_statement_unlink (CRStatement *a_stmt) ; + +enum CRStatus +cr_statement_ruleset_set_sel_list (CRStatement *a_this, + CRSelector *a_sel_list) ; + +enum CRStatus +cr_statement_ruleset_get_sel_list (CRStatement *a_this, + CRSelector **a_list) ; + +enum CRStatus +cr_statement_ruleset_set_decl_list (CRStatement *a_this, + CRDeclaration *a_list) ; + +enum CRStatus +cr_statement_ruleset_get_declarations (CRStatement *a_this, + CRDeclaration **a_decl_list) ; + +enum CRStatus +cr_statement_ruleset_append_decl2 (CRStatement *a_this, + CRString *a_prop, CRTerm *a_value) ; + +enum CRStatus +cr_statement_ruleset_append_decl (CRStatement *a_this, + CRDeclaration *a_decl) ; + +enum CRStatus +cr_statement_at_import_rule_set_imported_sheet (CRStatement *a_this, + CRStyleSheet *a_sheet) ; + +enum CRStatus +cr_statement_at_import_rule_get_imported_sheet (CRStatement *a_this, + CRStyleSheet **a_sheet) ; + +enum CRStatus +cr_statement_at_import_rule_set_url (CRStatement *a_this, + CRString *a_url) ; + +enum CRStatus +cr_statement_at_import_rule_get_url (CRStatement *a_this, + CRString **a_url) ; + +gint +cr_statement_at_media_nr_rules (CRStatement *a_this) ; + +CRStatement * +cr_statement_at_media_get_from_list (CRStatement *a_this, int itemnr) ; + +enum CRStatus +cr_statement_at_page_rule_set_sel (CRStatement *a_this, + CRSelector *a_sel) ; + +enum CRStatus +cr_statement_at_page_rule_get_sel (CRStatement *a_this, + CRSelector **a_sel) ; + +enum CRStatus +cr_statement_at_page_rule_set_declarations (CRStatement *a_this, + CRDeclaration *a_decl_list) ; + +enum CRStatus +cr_statement_at_page_rule_get_declarations (CRStatement *a_this, + CRDeclaration **a_decl_list) ; + +enum CRStatus +cr_statement_at_charset_rule_set_charset (CRStatement *a_this, + CRString *a_charset) ; + +enum CRStatus +cr_statement_at_charset_rule_get_charset (CRStatement *a_this, + CRString **a_charset) ; + +enum CRStatus +cr_statement_at_font_face_rule_set_decls (CRStatement *a_this, + CRDeclaration *a_decls) ; + +enum CRStatus +cr_statement_at_font_face_rule_get_decls (CRStatement *a_this, + CRDeclaration **a_decls) ; + +enum CRStatus +cr_statement_at_font_face_rule_add_decl (CRStatement *a_this, + CRString *a_prop, + CRTerm *a_value) ; + +gchar * +cr_statement_to_string (CRStatement * a_this, gulong a_indent) ; + +gchar* +cr_statement_list_to_string (CRStatement *a_this, gulong a_indent) ; + +void +cr_statement_dump (CRStatement *a_this, FILE *a_fp, gulong a_indent) ; + +void +cr_statement_dump_ruleset (CRStatement * a_this, FILE * a_fp, + glong a_indent) ; + +void +cr_statement_dump_font_face_rule (CRStatement * a_this, + FILE * a_fp, + glong a_indent) ; + +void +cr_statement_dump_page (CRStatement * a_this, FILE * a_fp, + gulong a_indent) ; + + +void +cr_statement_dump_media_rule (CRStatement * a_this, + FILE * a_fp, + gulong a_indent) ; + +void +cr_statement_dump_import_rule (CRStatement * a_this, FILE * a_fp, + gulong a_indent) ; +void +cr_statement_dump_charset (CRStatement * a_this, FILE * a_fp, + gulong a_indent) ; +gint +cr_statement_nr_rules (CRStatement *a_this) ; + +CRStatement * +cr_statement_get_from_list (CRStatement *a_this, int itemnr) ; + +void +cr_statement_destroy (CRStatement *a_this) ; + +G_END_DECLS + +#endif /*__CR_STATEMENT_H__*/ diff --git a/gettext-tools/gnulib-lib/libcroco/cr-string.c b/gettext-tools/gnulib-lib/libcroco/cr-string.c new file mode 100644 index 0000000..212d05e --- /dev/null +++ b/gettext-tools/gnulib-lib/libcroco/cr-string.c @@ -0,0 +1,169 @@ +/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */ + +/* + * This file is part of The Croco Library + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + * Author: Dodji Seketeli. + * See COPYRIGHTS file for copyright information. + */ + +#include +#include +#include "cr-string.h" + +/** + *Instanciates a #CRString + *@return the newly instanciated #CRString + *Must be freed with cr_string_destroy(). + */ +CRString * +cr_string_new (void) +{ + CRString *result = NULL ; + + result = g_try_malloc (sizeof (CRString)) ; + if (!result) { + cr_utils_trace_info ("Out of memory") ; + return NULL ; + } + memset (result, 0, sizeof (CRString)) ; + result->stryng = g_string_new (NULL) ; + return result ; +} + +/** + *Instanciate a string and initialise it to + *a_string. + *@param a_string the initial string + *@return the newly instanciated string. + */ +CRString * +cr_string_new_from_string (const gchar * a_string) +{ + CRString *result = NULL ; + + result = cr_string_new () ; + if (!result) { + cr_utils_trace_info ("Out of memory") ; + return NULL ; + } + if (a_string) + g_string_append (result->stryng, a_string) ; + return result ; +} + +/** + *Instanciates a #CRString from an instance of GString. + *@param a_string the input string that will be copied into + *the newly instanciated #CRString + *@return the newly instanciated #CRString. + */ +CRString * +cr_string_new_from_gstring (GString *a_string) +{ + CRString *result = NULL ; + + result = cr_string_new () ; + if (!result) { + cr_utils_trace_info ("Out of memory") ; + return NULL ; + } + if (a_string) { + result->stryng = g_string_new_len + (a_string->str, a_string->len) ; + } else { + result->stryng = g_string_new (NULL) ; + } + return result ; +} + +CRString * +cr_string_dup (CRString *a_this) +{ + CRString *result = NULL ; + g_return_val_if_fail (a_this, NULL) ; + + result = cr_string_new_from_gstring (a_this->stryng) ; + if (!result) { + cr_utils_trace_info ("Out of memory") ; + return NULL ; + } + cr_parsing_location_copy (&result->location, + &a_this->location) ; + return result ; +} + +gchar * +cr_string_dup2 (CRString *a_this) +{ + gchar *result = NULL ; + + g_return_val_if_fail (a_this, NULL) ; + + if (a_this + && a_this->stryng + && a_this->stryng->str) { + result = g_strndup (a_this->stryng->str, + a_this->stryng->len) ; + } + return result ; +} + +/** + *Returns a pointer to the internal raw NULL terminated string + *of the current instance of #CRString. + *@param a_this the current instance of #CRString + */ +const gchar * +cr_string_peek_raw_str (CRString *a_this) +{ + g_return_val_if_fail (a_this, NULL) ; + + if (a_this->stryng && a_this->stryng->str) + return a_this->stryng->str ; + return NULL ; +} + +/** + *Returns the length of the internal raw NULL terminated + *string of the current instance of #CRString. + *@param a_this the current instance of #CRString. + *@return the len of the internal raw NULL termninated string, + *of -1 if no length can be returned. + */ +gint +cr_string_peek_raw_str_len (CRString *a_this) +{ + g_return_val_if_fail (a_this && a_this->stryng, + -1) ; + return a_this->stryng->len ; +} + +/** + *@param a_this the #CRString to destroy. + */ +void +cr_string_destroy (CRString *a_this) +{ + g_return_if_fail (a_this) ; + + if (a_this->stryng) { + g_string_free (a_this->stryng, TRUE) ; + a_this->stryng = NULL ; + } + g_free (a_this) ; +} diff --git a/gettext-tools/gnulib-lib/libcroco/cr-string.h b/gettext-tools/gnulib-lib/libcroco/cr-string.h new file mode 100644 index 0000000..f12c04a --- /dev/null +++ b/gettext-tools/gnulib-lib/libcroco/cr-string.h @@ -0,0 +1,76 @@ +/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */ + +/* + * This file is part of The Croco Library + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + * See COPYRIGHTS file for copyright information. + */ + +/** + *@file + *Declaration file of the #CRString class. + */ + +#ifndef __CR_STRING_H__ +#define __CR_STRING_H__ + +#include +#include "cr-utils.h" +#include "cr-parsing-location.h" + +G_BEGIN_DECLS + +typedef struct _CRString CRString ; + +/** + *This is a ship implementation of string based on GString. + *Actually, the aim of CRString is to store the parsing location + *(line,column,byte offset) at which a given string has been parsed + *in the input CSS. + *So this class has a gstring field of type GString that users can + *freely manipulate, and also a CRParginLocation type where the + *parsing location is store. If you don't want to deal with parsing + *location stuffs, then use GString instead. If we were in C++ for example, + *CRString would just inherit GString and just add accessors to + *the CRParsingLocation data ... but we are not and we still have + *to provide the parsing location information. + */ +struct _CRString { + /** + *The GString where all the string + *operation happen. + */ + GString *stryng ; + /** + *The parsing location storage area. + */ + CRParsingLocation location ; +} ; + +CRString * cr_string_new (void) ; + +CRString *cr_string_new_from_string (const gchar * a_string) ; +CRString * cr_string_new_from_gstring (GString *a_string) ; +CRString *cr_string_dup (CRString *a_this) ; +gchar *cr_string_dup2 (CRString *a_this) ; +const gchar *cr_string_peek_raw_str (CRString *a_this) ; +gint cr_string_peek_raw_str_len (CRString *a_this) ; +void cr_string_destroy (CRString *a_this) ; + +G_END_DECLS + +#endif diff --git a/gettext-tools/gnulib-lib/libcroco/cr-style.c b/gettext-tools/gnulib-lib/libcroco/cr-style.c new file mode 100644 index 0000000..bdae497 --- /dev/null +++ b/gettext-tools/gnulib-lib/libcroco/cr-style.c @@ -0,0 +1,2852 @@ +/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */ + +/* + * This file is part of The Croco Library + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of + * the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the + * GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + * Author: Dodji Seketeli. + * see COPYRIGTHS file for copyright information + */ + +#include +#include +#include "cr-style.h" + +/** + *@file + *The definition of the #CRStyle class. + */ + +/** + *A property ID. + *Each supported css property has an ID which is + *an entry into a property "population" jump table. + *each entry of the property population jump table + *contains code to tranform the literal form of + *a property value into a strongly typed value. + */ +enum CRPropertyID { + PROP_ID_NOT_KNOWN = 0, + PROP_ID_PADDING_TOP, + PROP_ID_PADDING_RIGHT, + PROP_ID_PADDING_BOTTOM, + PROP_ID_PADDING_LEFT, + PROP_ID_PADDING, + PROP_ID_BORDER_TOP_WIDTH, + PROP_ID_BORDER_RIGHT_WIDTH, + PROP_ID_BORDER_BOTTOM_WIDTH, + PROP_ID_BORDER_LEFT_WIDTH, + PROP_ID_BORDER_WIDTH, + PROP_ID_BORDER_TOP_STYLE, + PROP_ID_BORDER_RIGHT_STYLE, + PROP_ID_BORDER_BOTTOM_STYLE, + PROP_ID_BORDER_LEFT_STYLE, + PROP_ID_BORDER_STYLE, + PROP_ID_BORDER_TOP_COLOR, + PROP_ID_BORDER_RIGHT_COLOR, + PROP_ID_BORDER_BOTTOM_COLOR, + PROP_ID_BORDER_LEFT_COLOR, + PROP_ID_BORDER_TOP, + PROP_ID_BORDER_RIGHT, + PROP_ID_BORDER_BOTTOM, + PROP_ID_BORDER_LEFT, + PROP_ID_BORDER, + PROP_ID_MARGIN_TOP, + PROP_ID_MARGIN_RIGHT, + PROP_ID_MARGIN_BOTTOM, + PROP_ID_MARGIN_LEFT, + PROP_ID_MARGIN, + PROP_ID_DISPLAY, + PROP_ID_POSITION, + PROP_ID_TOP, + PROP_ID_RIGHT, + PROP_ID_BOTTOM, + PROP_ID_LEFT, + PROP_ID_FLOAT, + PROP_ID_WIDTH, + PROP_ID_COLOR, + PROP_ID_BACKGROUND_COLOR, + PROP_ID_FONT_FAMILY, + PROP_ID_FONT_SIZE, + PROP_ID_FONT_STYLE, + PROP_ID_FONT_WEIGHT, + PROP_ID_WHITE_SPACE, + /*should be the last one. */ + NB_PROP_IDS +}; + +typedef struct _CRPropertyDesc CRPropertyDesc; + +struct _CRPropertyDesc { + const guchar *name; + enum CRPropertyID prop_id; +}; + +static CRPropertyDesc gv_prop_table[] = { + {"padding-top", PROP_ID_PADDING_TOP}, + {"padding-right", PROP_ID_PADDING_RIGHT}, + {"padding-bottom", PROP_ID_PADDING_BOTTOM}, + {"padding-left", PROP_ID_PADDING_LEFT}, + {"padding", PROP_ID_PADDING}, + {"border-top-width", PROP_ID_BORDER_TOP_WIDTH}, + {"border-right-width", PROP_ID_BORDER_RIGHT_WIDTH}, + {"border-bottom-width", PROP_ID_BORDER_BOTTOM_WIDTH}, + {"border-left-width", PROP_ID_BORDER_LEFT_WIDTH}, + {"border-width", PROP_ID_BORDER_WIDTH}, + {"border-top-style", PROP_ID_BORDER_TOP_STYLE}, + {"border-right-style", PROP_ID_BORDER_RIGHT_STYLE}, + {"border-bottom-style", PROP_ID_BORDER_BOTTOM_STYLE}, + {"border-left-style", PROP_ID_BORDER_LEFT_STYLE}, + {"border-style", PROP_ID_BORDER_STYLE}, + {"border-top", PROP_ID_BORDER_TOP}, + {"border-right", PROP_ID_BORDER_RIGHT}, + {"border-bottom", PROP_ID_BORDER_BOTTOM}, + {"border-left", PROP_ID_BORDER_LEFT}, + {"border", PROP_ID_BORDER}, + {"margin-top", PROP_ID_MARGIN_TOP}, + {"margin-right", PROP_ID_MARGIN_RIGHT}, + {"margin-bottom", PROP_ID_MARGIN_BOTTOM}, + {"margin-left", PROP_ID_MARGIN_LEFT}, + {"margin", PROP_ID_MARGIN}, + {"display", PROP_ID_DISPLAY}, + {"position", PROP_ID_POSITION}, + {"top", PROP_ID_TOP}, + {"right", PROP_ID_RIGHT}, + {"bottom", PROP_ID_BOTTOM}, + {"left", PROP_ID_LEFT}, + {"float", PROP_ID_FLOAT}, + {"width", PROP_ID_WIDTH}, + {"color", PROP_ID_COLOR}, + {"border-top-color", PROP_ID_BORDER_TOP_COLOR}, + {"border-right-color", PROP_ID_BORDER_RIGHT_COLOR}, + {"border-bottom-color", PROP_ID_BORDER_BOTTOM_COLOR}, + {"border-left-color", PROP_ID_BORDER_LEFT_COLOR}, + {"background-color", PROP_ID_BACKGROUND_COLOR}, + {"font-family", PROP_ID_FONT_FAMILY}, + {"font-size", PROP_ID_FONT_SIZE}, + {"font-style", PROP_ID_FONT_STYLE}, + {"font-weight", PROP_ID_FONT_WEIGHT}, + {"white-space", PROP_ID_WHITE_SPACE}, + /*must be the last one */ + {NULL, 0} +}; + +/** + *A the key/value pair of this hash table + *are: + *key => name of the the css propertie found in gv_prop_table + *value => matching property id found in gv_prop_table. + *So this hash table is here just to retrieval of a property id + *from a property name. + */ +static GHashTable *gv_prop_hash = NULL; + +/** + *incremented by each new instance of #CRStyle + *and decremented at the it destroy time. + *When this reaches zero, gv_prop_hash is destroyed. + */ +static gulong gv_prop_hash_ref_count = 0; + +struct CRNumPropEnumDumpInfo { + enum CRNumProp code; + const gchar *str; +}; + +static struct CRNumPropEnumDumpInfo gv_num_props_dump_infos[] = { + {NUM_PROP_TOP, "top"}, + {NUM_PROP_RIGHT, "right"}, + {NUM_PROP_BOTTOM, "bottom"}, + {NUM_PROP_LEFT, "left"}, + {NUM_PROP_PADDING_TOP, "padding-top"}, + {NUM_PROP_PADDING_RIGHT, "padding-right"}, + {NUM_PROP_PADDING_BOTTOM, "padding-bottom"}, + {NUM_PROP_PADDING_LEFT, "padding-left"}, + {NUM_PROP_BORDER_TOP, "border-top"}, + {NUM_PROP_BORDER_RIGHT, "border-right"}, + {NUM_PROP_BORDER_BOTTOM, "border-bottom"}, + {NUM_PROP_BORDER_LEFT, "border-left"}, + {NUM_PROP_MARGIN_TOP, "margin-top"}, + {NUM_PROP_MARGIN_RIGHT, "margin-right"}, + {NUM_PROP_MARGIN_BOTTOM, "margin-bottom"}, + {NUM_PROP_MARGIN_LEFT, "margin-left"}, + {NUM_PROP_WIDTH, "width"}, + {0, NULL} +}; + +struct CRRgbPropEnumDumpInfo { + enum CRRgbProp code; + const gchar *str; +}; + +static struct CRRgbPropEnumDumpInfo gv_rgb_props_dump_infos[] = { + {RGB_PROP_BORDER_TOP_COLOR, "border-top-color"}, + {RGB_PROP_BORDER_RIGHT_COLOR, "border-right-color"}, + {RGB_PROP_BORDER_BOTTOM_COLOR, "bottom-color"}, + {RGB_PROP_BORDER_LEFT_COLOR, "left-color"}, + {RGB_PROP_COLOR, "color"}, + {RGB_PROP_BACKGROUND_COLOR, "background-color"}, + {0, NULL} +}; + +struct CRBorderStylePropEnumDumpInfo { + enum CRBorderStyleProp code; + const gchar *str; + +}; + +static struct CRBorderStylePropEnumDumpInfo gv_border_style_props_dump_infos[] + = { + {BORDER_STYLE_PROP_TOP, "border-style-top"}, + {BORDER_STYLE_PROP_RIGHT, "border-style-right"}, + {BORDER_STYLE_PROP_BOTTOM, "boder-style-bottom"}, + {BORDER_STYLE_PROP_LEFT, "border-style-left"}, + {0, NULL} +}; + +static enum CRStatus + cr_style_init_properties (void); + +enum CRDirection { + DIR_TOP = 0, + DIR_RIGHT, + DIR_BOTTOM, + DIR_LEFT, + + /*must be the last one */ + NB_DIRS +}; + +static const gchar *num_prop_code_to_string (enum CRNumProp a_code); + +static const gchar *rgb_prop_code_to_string (enum CRRgbProp a_code); + +static const gchar *border_style_prop_code_to_string (enum CRBorderStyleProp + a_code); + +static enum CRStatus +set_prop_padding_x_from_value (CRStyle * a_style, + CRTerm * a_value, enum CRDirection a_dir); + +static enum CRStatus +set_prop_border_x_width_from_value (CRStyle * a_style, + CRTerm * a_value, + enum CRDirection a_dir); +static enum CRStatus +set_prop_border_width_from_value (CRStyle *a_style, + CRTerm *a_value) ; + +static enum CRStatus +set_prop_border_x_style_from_value (CRStyle * a_style, + CRTerm * a_value, + enum CRDirection a_dir); +static enum CRStatus +set_prop_border_style_from_value (CRStyle *a_style, + CRTerm *a_value) ; + +static enum CRStatus +set_prop_margin_x_from_value (CRStyle * a_style, CRTerm * a_value, + enum CRDirection a_dir); + +static enum CRStatus +set_prop_display_from_value (CRStyle * a_style, CRTerm * a_value); + +static enum CRStatus +set_prop_position_from_value (CRStyle * a_style, CRTerm * a_value); + +static enum CRStatus +set_prop_x_from_value (CRStyle * a_style, CRTerm * a_value, + enum CRDirection a_dir); + +static enum CRStatus +set_prop_float (CRStyle * a_style, CRTerm * a_value); + +static enum CRStatus +set_prop_width (CRStyle * a_style, CRTerm * a_value); + +static enum CRStatus +set_prop_color (CRStyle * a_style, CRTerm * a_value); + +static enum CRStatus +set_prop_background_color (CRStyle * a_style, CRTerm * a_value); + +static enum CRStatus +set_prop_border_x_color_from_value (CRStyle * a_style, CRTerm * a_value, + enum CRDirection a_dir); + +static enum CRStatus +set_prop_border_x_from_value (CRStyle * a_style, CRTerm * a_value, + enum CRDirection a_dir); + +static enum CRStatus +set_prop_border_from_value (CRStyle * a_style, CRTerm * a_value); + +static enum CRStatus +set_prop_padding_from_value (CRStyle * a_style, CRTerm * a_value); + +static enum CRStatus +set_prop_margin_from_value (CRStyle * a_style, CRTerm * a_value); + +static enum CRStatus +set_prop_font_family_from_value (CRStyle * a_style, CRTerm * a_value); + +static enum CRStatus +init_style_font_size_field (CRStyle * a_style); + +static enum CRStatus +set_prop_font_size_from_value (CRStyle * a_style, CRTerm * a_value); + +static enum CRStatus +set_prop_font_style_from_value (CRStyle * a_style, CRTerm * a_value); + +static enum CRStatus +set_prop_font_weight_from_value (CRStyle * a_style, CRTerm * a_value); + +static const gchar * +num_prop_code_to_string (enum CRNumProp a_code) +{ + gint len = sizeof (gv_num_props_dump_infos) / + sizeof (struct CRNumPropEnumDumpInfo); + if (a_code >= len) { + cr_utils_trace_info ("A field has been added " + "to 'enum CRNumProp' and no matching" + " entry has been " + "added to gv_num_prop_dump_infos table.\n" + "Please add the missing matching entry"); + return NULL; + } + if (gv_num_props_dump_infos[a_code].code != a_code) { + cr_utils_trace_info ("mismatch between the order of fields in" + " 'enum CRNumProp' and " + "the order of entries in " + "the gv_num_prop_dump_infos table"); + return NULL; + } + return gv_num_props_dump_infos[a_code].str; +} + +static const gchar * +rgb_prop_code_to_string (enum CRRgbProp a_code) +{ + gint len = sizeof (gv_rgb_props_dump_infos) / + sizeof (struct CRRgbPropEnumDumpInfo); + + if (a_code >= len) { + cr_utils_trace_info ("A field has been added " + "to 'enum CRRgbProp' and no matching" + " entry has been " + "added to gv_rgb_prop_dump_infos table.\n" + "Please add the missing matching entry"); + return NULL; + } + if (gv_rgb_props_dump_infos[a_code].code != a_code) { + cr_utils_trace_info ("mismatch between the order of fields in" + " 'enum CRRgbProp' and " + "the order of entries in " + "the gv_rgb_props_dump_infos table"); + return NULL; + } + return gv_rgb_props_dump_infos[a_code].str; +} + +static const gchar * +border_style_prop_code_to_string (enum CRBorderStyleProp a_code) +{ + gint len = sizeof (gv_border_style_props_dump_infos) / + sizeof (struct CRBorderStylePropEnumDumpInfo); + + if (a_code >= len) { + cr_utils_trace_info ("A field has been added " + "to 'enum CRBorderStyleProp' and no matching" + " entry has been " + "added to gv_border_style_prop_dump_infos table.\n" + "Please add the missing matching entry"); + return NULL; + } + if (gv_border_style_props_dump_infos[a_code].code != a_code) { + cr_utils_trace_info ("mismatch between the order of fields in" + " 'enum CRBorderStyleProp' and " + "the order of entries in " + "the gv_border_style_props_dump_infos table"); + return NULL; + } + return gv_border_style_props_dump_infos[a_code].str; +} + +static enum CRStatus +cr_style_init_properties (void) +{ + + if (!gv_prop_hash) { + gulong i = 0; + + gv_prop_hash = g_hash_table_new (g_str_hash, g_str_equal); + if (!gv_prop_hash) { + cr_utils_trace_info ("Out of memory"); + return CR_ERROR; + } + + /*load gv_prop_hash from gv_prop_table */ + for (i = 0; gv_prop_table[i].name; i++) { + g_hash_table_insert + (gv_prop_hash, + (gpointer) gv_prop_table[i].name, + GINT_TO_POINTER (gv_prop_table[i].prop_id)); + } + } + + return CR_OK; +} + +static enum CRPropertyID +cr_style_get_prop_id (const guchar * a_prop) +{ + gpointer *raw_id = NULL; + + if (!gv_prop_hash) { + cr_style_init_properties (); + } + + raw_id = g_hash_table_lookup (gv_prop_hash, a_prop); + if (!raw_id) { + return PROP_ID_NOT_KNOWN; + } + return GPOINTER_TO_INT (raw_id); +} + +static enum CRStatus +set_prop_padding_x_from_value (CRStyle * a_style, + CRTerm * a_value, enum CRDirection a_dir) +{ + enum CRStatus status = CR_OK; + CRNum *num_val = NULL; + + g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR); + + if (a_value->type != TERM_NUMBER && a_value->type != TERM_IDENT) + return CR_BAD_PARAM_ERROR; + + switch (a_dir) { + case DIR_TOP: + num_val = &a_style->num_props[NUM_PROP_PADDING_TOP].sv; + break; + + case DIR_RIGHT: + num_val = &a_style->num_props[NUM_PROP_PADDING_RIGHT].sv; + break; + + case DIR_BOTTOM: + num_val = &a_style->num_props[NUM_PROP_PADDING_BOTTOM].sv; + break; + + case DIR_LEFT: + num_val = &a_style->num_props[NUM_PROP_PADDING_LEFT].sv; + break; + + default: + return CR_BAD_PARAM_ERROR; + } + + if (a_value->type == TERM_IDENT) { + if (a_value->content.str + && a_value->content.str->stryng + && a_value->content.str->stryng->str + && !strncmp ((guchar *) "inherit", + a_value->content.str->stryng->str, + sizeof ("inherit")-1)) { + status = cr_num_set (num_val, 0.0, NUM_INHERIT); + return CR_OK; + } else + return CR_UNKNOWN_TYPE_ERROR; + } + + g_return_val_if_fail (a_value->type == TERM_NUMBER + && a_value->content.num, CR_UNKNOWN_TYPE_ERROR); + + switch (a_value->content.num->type) { + case NUM_LENGTH_EM: + case NUM_LENGTH_EX: + case NUM_LENGTH_PX: + case NUM_LENGTH_IN: + case NUM_LENGTH_CM: + case NUM_LENGTH_MM: + case NUM_LENGTH_PT: + case NUM_LENGTH_PC: + case NUM_PERCENTAGE: + status = cr_num_copy (num_val, a_value->content.num); + break; + default: + status = CR_UNKNOWN_TYPE_ERROR; + break; + } + + return status; +} + +static enum CRStatus +set_prop_border_x_width_from_value (CRStyle * a_style, + CRTerm * a_value, + enum CRDirection a_dir) +{ + enum CRStatus status = CR_OK; + CRNum *num_val = NULL; + + g_return_val_if_fail (a_value && a_style, CR_BAD_PARAM_ERROR); + + switch (a_dir) { + case DIR_TOP: + num_val = &a_style->num_props[NUM_PROP_BORDER_TOP].sv; + break; + + case DIR_RIGHT: + num_val = &a_style->num_props[NUM_PROP_BORDER_RIGHT].sv; + break; + + case DIR_BOTTOM: + num_val = &a_style->num_props[NUM_PROP_BORDER_BOTTOM].sv; + break; + + case DIR_LEFT: + num_val = &a_style->num_props[NUM_PROP_BORDER_LEFT].sv; + break; + + default: + return CR_BAD_PARAM_ERROR; + break; + } + + if (a_value->type == TERM_IDENT) { + if (a_value->content.str + && a_value->content.str->stryng + && a_value->content.str->stryng->str) { + if (!strncmp ("thin", + a_value->content.str->stryng->str, + sizeof ("thin")-1)) { + cr_num_set (num_val, BORDER_THIN, + NUM_LENGTH_PX); + } else if (!strncmp + ("medium", + a_value->content.str->stryng->str, + sizeof ("medium")-1)) { + cr_num_set (num_val, BORDER_MEDIUM, + NUM_LENGTH_PX); + } else if (!strncmp ("thick", + a_value->content.str->stryng->str, + sizeof ("thick")-1)) { + cr_num_set (num_val, BORDER_THICK, + NUM_LENGTH_PX); + } else { + return CR_UNKNOWN_TYPE_ERROR; + } + } + } else if (a_value->type == TERM_NUMBER) { + if (a_value->content.num) { + cr_num_copy (num_val, a_value->content.num); + } + } else if (a_value->type != TERM_NUMBER + || a_value->content.num == NULL) { + return CR_UNKNOWN_TYPE_ERROR; + } + + return status; +} + +static enum CRStatus +set_prop_border_width_from_value (CRStyle *a_style, + CRTerm *a_value) +{ + CRTerm *cur_term = NULL ; + enum CRDirection direction = DIR_TOP ; + + g_return_val_if_fail (a_style && a_value, + CR_BAD_PARAM_ERROR) ; + cur_term = a_value ; + + if (!cur_term) + return CR_ERROR ; + + for (direction = DIR_TOP ; + direction < NB_DIRS ; direction ++) { + set_prop_border_x_width_from_value (a_style, + cur_term, + direction) ; + } + + cur_term = cur_term->next ; + if (!cur_term) + return CR_OK ; + set_prop_border_x_width_from_value (a_style, cur_term, + DIR_RIGHT) ; + set_prop_border_x_width_from_value (a_style, cur_term, + DIR_LEFT) ; + + cur_term = cur_term->next ; + if (!cur_term) + return CR_OK ; + set_prop_border_x_width_from_value (a_style, cur_term, + DIR_BOTTOM) ; + + cur_term = cur_term->next ; + if (!cur_term) + return CR_OK ; + set_prop_border_x_width_from_value (a_style, cur_term, + DIR_LEFT) ; + + return CR_OK ; +} + +static enum CRStatus +set_prop_border_x_style_from_value (CRStyle * a_style, + CRTerm * a_value, enum CRDirection a_dir) +{ + enum CRStatus status = CR_OK; + enum CRBorderStyle *border_style_ptr = NULL; + + g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR); + + switch (a_dir) { + case DIR_TOP: + border_style_ptr = &a_style-> + border_style_props[BORDER_STYLE_PROP_TOP]; + break; + + case DIR_RIGHT: + border_style_ptr = + &a_style->border_style_props[BORDER_STYLE_PROP_RIGHT]; + break; + + case DIR_BOTTOM: + border_style_ptr = &a_style-> + border_style_props[BORDER_STYLE_PROP_BOTTOM]; + break; + + case DIR_LEFT: + border_style_ptr = &a_style-> + border_style_props[BORDER_STYLE_PROP_LEFT]; + break; + + default: + break; + } + + if (a_value->type != TERM_IDENT || !a_value->content.str) { + return CR_UNKNOWN_TYPE_ERROR; + } + + if (!strncmp ("none", + a_value->content.str->stryng->str, + sizeof ("none")-1)) { + *border_style_ptr = BORDER_STYLE_NONE; + } else if (!strncmp ("hidden", + a_value->content.str->stryng->str, + sizeof ("hidden")-1)) { + *border_style_ptr = BORDER_STYLE_HIDDEN; + } else if (!strncmp ("dotted", + a_value->content.str->stryng->str, + sizeof ("dotted")-1)) { + *border_style_ptr = BORDER_STYLE_DOTTED; + } else if (!strncmp ("dashed", + a_value->content.str->stryng->str, sizeof ("dashed")-1)) { + *border_style_ptr = BORDER_STYLE_DASHED; + } else if (!strncmp ("solid", + a_value->content.str->stryng->str, sizeof ("solid")-1)) { + *border_style_ptr = BORDER_STYLE_SOLID; + } else if (!strncmp ("double", + a_value->content.str->stryng->str, sizeof ("double")-1)) { + *border_style_ptr = BORDER_STYLE_DOUBLE; + } else if (!strncmp ("groove", + a_value->content.str->stryng->str, sizeof ("groove")-1)) { + *border_style_ptr = BORDER_STYLE_GROOVE; + } else if (!strncmp ("ridge", + a_value->content.str->stryng->str, + sizeof ("ridge")-1)) { + *border_style_ptr = BORDER_STYLE_RIDGE; + } else if (!strncmp ("inset", + a_value->content.str->stryng->str, + sizeof ("inset")-1)) { + *border_style_ptr = BORDER_STYLE_INSET; + } else if (!strncmp ("outset", + a_value->content.str->stryng->str, + sizeof ("outset")-1)) { + *border_style_ptr = BORDER_STYLE_OUTSET; + } else if (!strncmp ("inherit", + a_value->content.str->stryng->str, + sizeof ("inherit")-1)) { + *border_style_ptr = BORDER_STYLE_INHERIT; + } else { + status = CR_UNKNOWN_TYPE_ERROR; + } + + return status; +} + +static enum CRStatus +set_prop_border_style_from_value (CRStyle *a_style, + CRTerm *a_value) +{ + CRTerm *cur_term = NULL ; + enum CRDirection direction = DIR_TOP ; + + g_return_val_if_fail (a_style && a_value, + CR_BAD_PARAM_ERROR) ; + + cur_term = a_value ; + if (!cur_term || cur_term->type != TERM_IDENT) { + return CR_ERROR ; + } + + for (direction = DIR_TOP ; + direction < NB_DIRS ; + direction ++) { + set_prop_border_x_style_from_value (a_style, + cur_term, + direction) ; + } + + cur_term = cur_term->next ; + if (!cur_term || cur_term->type != TERM_IDENT) { + return CR_OK ; + } + + set_prop_border_x_style_from_value (a_style, cur_term, + DIR_RIGHT) ; + set_prop_border_x_style_from_value (a_style, cur_term, + DIR_LEFT) ; + + cur_term = cur_term->next ; + if (!cur_term || cur_term->type != TERM_IDENT) { + return CR_OK ; + } + set_prop_border_x_style_from_value (a_style, cur_term, + DIR_BOTTOM) ; + + cur_term = cur_term->next ; + if (!cur_term || cur_term->type != TERM_IDENT) { + return CR_OK ; + } + set_prop_border_x_style_from_value (a_style, cur_term, + DIR_LEFT) ; + return CR_OK ; +} + +static enum CRStatus +set_prop_margin_x_from_value (CRStyle * a_style, CRTerm * a_value, + enum CRDirection a_dir) +{ + enum CRStatus status = CR_OK; + CRNum *num_val = NULL; + + g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR); + + switch (a_dir) { + case DIR_TOP: + num_val = &a_style->num_props[NUM_PROP_MARGIN_TOP].sv; + break; + + case DIR_RIGHT: + num_val = &a_style->num_props[NUM_PROP_MARGIN_RIGHT].sv; + break; + + case DIR_BOTTOM: + num_val = &a_style->num_props[NUM_PROP_MARGIN_BOTTOM].sv; + break; + + case DIR_LEFT: + num_val = &a_style->num_props[NUM_PROP_MARGIN_LEFT].sv; + break; + + default: + break; + } + + switch (a_value->type) { + case TERM_IDENT: + if (a_value->content.str + && a_value->content.str->stryng + && a_value->content.str->stryng->str + && !strcmp (a_value->content.str->stryng->str, + "inherit")) { + status = cr_num_set (num_val, 0.0, NUM_INHERIT); + } else if (a_value->content.str + && a_value->content.str->stryng + && !strcmp (a_value->content.str->stryng->str, + "auto")) { + status = cr_num_set (num_val, 0.0, NUM_AUTO); + } else { + status = CR_UNKNOWN_TYPE_ERROR; + } + break ; + + case TERM_NUMBER: + status = cr_num_copy (num_val, a_value->content.num); + break; + + default: + status = CR_UNKNOWN_TYPE_ERROR; + break; + } + + return status; +} + +struct CRPropDisplayValPair { + const guchar *prop_name; + enum CRDisplayType type; +}; + +static enum CRStatus +set_prop_display_from_value (CRStyle * a_style, CRTerm * a_value) +{ + static const struct CRPropDisplayValPair disp_vals_map[] = { + {"none", DISPLAY_NONE}, + {"inline", DISPLAY_INLINE}, + {"block", DISPLAY_BLOCK}, + {"run-in", DISPLAY_RUN_IN}, + {"compact", DISPLAY_COMPACT}, + {"marker", DISPLAY_MARKER}, + {"table", DISPLAY_TABLE}, + {"inline-table", DISPLAY_INLINE_TABLE}, + {"table-row-group", DISPLAY_TABLE_ROW_GROUP}, + {"table-header-group", DISPLAY_TABLE_HEADER_GROUP}, + {"table-footer-group", DISPLAY_TABLE_FOOTER_GROUP}, + {"table-row", DISPLAY_TABLE_ROW}, + {"table-column-group", DISPLAY_TABLE_COLUMN_GROUP}, + {"table-column", DISPLAY_TABLE_COLUMN}, + {"table-cell", DISPLAY_TABLE_CELL}, + {"table-caption", DISPLAY_TABLE_CAPTION}, + {"inherit", DISPLAY_INHERIT}, + {NULL, DISPLAY_NONE} + }; + + g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR); + + switch (a_value->type) { + case TERM_IDENT: + { + int i = 0; + + if (!a_value->content.str + || !a_value->content.str->stryng + || !a_value->content.str->stryng->str) + break; + + for (i = 0; disp_vals_map[i].prop_name; i++) { + if (!strncmp + (disp_vals_map[i].prop_name, + a_value->content.str->stryng->str, + strlen (disp_vals_map[i].prop_name))) { + a_style->display = + disp_vals_map[i].type; + break; + } + } + } + break; + + default: + break; + } + + return CR_OK; +} + +struct CRPropPositionValPair { + const guchar *name; + enum CRPositionType type; +}; + +static enum CRStatus +set_prop_position_from_value (CRStyle * a_style, CRTerm * a_value) +{ + enum CRStatus status = CR_UNKNOWN_PROP_VAL_ERROR; + static const struct CRPropPositionValPair position_vals_map[] = { + {"static", POSITION_STATIC}, + {"relative", POSITION_RELATIVE}, + {"absolute", POSITION_ABSOLUTE}, + {"fixed", POSITION_FIXED}, + {"inherit", POSITION_INHERIT}, + {NULL, POSITION_STATIC} + /*must alwas be the last one */ + }; + + g_return_val_if_fail (a_value, CR_BAD_PARAM_ERROR); + + switch (a_value->type) { + case TERM_IDENT: + { + int i = 0; + + if (!a_value->content.str + || !a_value->content.str->stryng + || !a_value->content.str->stryng->str) + break; + + for (i = 0; position_vals_map[i].name; i++) { + if (!strncmp (position_vals_map[i].name, + a_value->content.str->stryng->str, + strlen (position_vals_map[i]. + name))) { + a_style->position = + position_vals_map[i].type; + status = CR_OK; + break; + } + } + } + break; + + default: + break; + } + + return CR_OK; +} + +static enum CRStatus +set_prop_x_from_value (CRStyle * a_style, CRTerm * a_value, + enum CRDirection a_dir) +{ + CRNum *box_offset = NULL; + + g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR); + + if (!(a_value->type == TERM_NUMBER) + && !(a_value->type == TERM_IDENT)) { + return CR_UNKNOWN_PROP_VAL_ERROR; + } + + switch (a_dir) { + case DIR_TOP: + box_offset = &a_style->num_props[NUM_PROP_TOP].sv; + break; + + case DIR_RIGHT: + box_offset = &a_style->num_props[NUM_PROP_RIGHT].sv; + break; + + case DIR_BOTTOM: + box_offset = &a_style->num_props[NUM_PROP_BOTTOM].sv; + break; + case DIR_LEFT: + box_offset = &a_style->num_props[NUM_PROP_LEFT].sv; + break; + + default: + break; + } + + box_offset->type = NUM_AUTO; + + if (a_value->type == TERM_NUMBER && a_value->content.num) { + cr_num_copy (box_offset, a_value->content.num); + } else if (a_value->type == TERM_IDENT + && a_value->content.str + && a_value->content.str->stryng + && a_value->content.str->stryng->str) { + if (!strncmp ("inherit", + a_value->content.str->stryng->str, + sizeof ("inherit")-1)) { + cr_num_set (box_offset, 0.0, NUM_INHERIT); + } else if (!strncmp ("auto", + a_value->content.str->stryng->str, + sizeof ("auto")-1)) { + box_offset->type = NUM_AUTO; + } + } + + return CR_OK; +} + +static enum CRStatus +set_prop_float (CRStyle * a_style, CRTerm * a_value) +{ + g_return_val_if_fail (a_style && a_value, + CR_BAD_PARAM_ERROR); + + /*the default float type as specified by the css2 spec */ + a_style->float_type = FLOAT_NONE; + + if (a_value->type != TERM_IDENT + || !a_value->content.str + || !a_value->content.str->stryng + || !a_value->content.str->stryng->str) { + /*unknow type, the float type is set to it's default value */ + return CR_OK; + } + + if (!strncmp ("none", + a_value->content.str->stryng->str, + sizeof ("none")-1)) { + a_style->float_type = FLOAT_NONE; + } else if (!strncmp ("left", + a_value->content.str->stryng->str, + sizeof ("left")-1)) { + a_style->float_type = FLOAT_LEFT; + } else if (!strncmp ("right", + a_value->content.str->stryng->str, + sizeof ("right")-1)) { + a_style->float_type = FLOAT_RIGHT; + } else if (!strncmp ("inherit", + a_value->content.str->stryng->str, + sizeof ("inherit")-1)) { + a_style->float_type = FLOAT_INHERIT; + } + return CR_OK; +} + +static enum CRStatus +set_prop_width (CRStyle * a_style, CRTerm * a_value) +{ + CRNum *width = NULL; + g_return_val_if_fail (a_style + && a_value, + CR_BAD_PARAM_ERROR); + + width = &a_style->num_props[NUM_PROP_WIDTH].sv; + cr_num_set (width, 0.0, NUM_AUTO); + + if (a_value->type == TERM_IDENT) { + if (a_value->content.str + && a_value->content.str->stryng + && a_value->content.str->stryng->str) { + if (!strncmp ("auto", + a_value->content.str->stryng->str, + sizeof ("auto")-1)) { + cr_num_set (width, 0.0, NUM_AUTO); + } else if (!strncmp ("inherit", + a_value->content.str->stryng->str, + sizeof ("inherit")-1)) { + cr_num_set (width, 0.0, NUM_INHERIT); + } + } + } else if (a_value->type == TERM_NUMBER) { + if (a_value->content.num) { + cr_num_copy (&a_style->num_props[NUM_PROP_WIDTH].sv, + a_value->content.num); + } + } + return CR_OK; +} + +static enum CRStatus +set_prop_color (CRStyle * a_style, CRTerm * a_value) +{ + enum CRStatus status = CR_OK; + CRRgb *a_rgb = &a_style->rgb_props[RGB_PROP_COLOR].sv; + + g_return_val_if_fail (a_style + && a_value, CR_BAD_PARAM_ERROR); + + status = cr_rgb_set_from_term (a_rgb, a_value); + + return status; +} + +static enum CRStatus +set_prop_background_color (CRStyle * a_style, CRTerm * a_value) +{ + enum CRStatus status = CR_OK; + CRRgb *rgb = &a_style->rgb_props[RGB_PROP_BACKGROUND_COLOR].sv; + + g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR); + + status = cr_rgb_set_from_term (rgb, a_value); + return status; +} + +/** + *Sets border-top-color, border-right-color, + *border-bottom-color or border-left-color properties + *in the style structure. The value is taken from a + *css2 term of type IDENT or RGB. + *@param a_style the style structure to set. + *@param a_value the css2 term to take the color information from. + *@param a_dir the direction (TOP, LEFT, RIGHT, or BOTTOM). + *@return CR_OK upon successfull completion, an error code otherwise. + */ +static enum CRStatus +set_prop_border_x_color_from_value (CRStyle * a_style, CRTerm * a_value, + enum CRDirection a_dir) +{ + CRRgb *rgb_color = NULL; + enum CRStatus status = CR_OK; + + g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR); + + switch (a_dir) { + case DIR_TOP: + rgb_color = &a_style->rgb_props[RGB_PROP_BORDER_TOP_COLOR].sv; + break; + + case DIR_RIGHT: + rgb_color = + &a_style->rgb_props[RGB_PROP_BORDER_RIGHT_COLOR].sv; + break; + + case DIR_BOTTOM: + rgb_color = + &a_style->rgb_props[RGB_PROP_BORDER_BOTTOM_COLOR].sv; + break; + + case DIR_LEFT: + rgb_color = + &a_style->rgb_props[RGB_PROP_BORDER_LEFT_COLOR].sv; + break; + + default: + cr_utils_trace_info ("unknown DIR type"); + return CR_BAD_PARAM_ERROR; + } + + status = CR_UNKNOWN_PROP_VAL_ERROR; + + if (a_value->type == TERM_IDENT) { + if (a_value->content.str + && a_value->content.str->stryng + && a_value->content.str->stryng->str) { + status = cr_rgb_set_from_name + (rgb_color, + a_value->content.str->stryng->str); + + } + if (status != CR_OK) { + cr_rgb_set_from_name (rgb_color, "black"); + } + } else if (a_value->type == TERM_RGB) { + if (a_value->content.rgb) { + status = cr_rgb_set_from_rgb + (rgb_color, a_value->content.rgb); + } + } + return status; +} + +static enum CRStatus +set_prop_border_x_from_value (CRStyle * a_style, CRTerm * a_value, + enum CRDirection a_dir) +{ + CRTerm *cur_term = NULL; + + enum CRStatus status = CR_OK; + + g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR); + + for (cur_term = a_value; + cur_term; + cur_term = cur_term->next) { + status = set_prop_border_x_width_from_value (a_style, + cur_term, a_dir); + + if (status != CR_OK) { + status = set_prop_border_x_style_from_value + (a_style, cur_term, a_dir); + } + if (status != CR_OK) { + status = set_prop_border_x_color_from_value + (a_style, cur_term, a_dir); + } + } + return CR_OK; +} + +static enum CRStatus +set_prop_border_from_value (CRStyle * a_style, CRTerm * a_value) +{ + enum CRDirection direction = 0; + + g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR); + + for (direction = 0; direction < NB_DIRS; direction++) { + set_prop_border_x_from_value (a_style, + a_value, + direction); + } + + return CR_OK; +} + +static enum CRStatus +set_prop_padding_from_value (CRStyle * a_style, CRTerm * a_value) +{ + CRTerm *cur_term = NULL; + enum CRDirection direction = 0; + enum CRStatus status = CR_OK; + + g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR); + + cur_term = a_value; + + /*filter the eventual non NUMBER terms some user can have written here*/ + while (cur_term && cur_term->type != TERM_NUMBER) { + cur_term = cur_term->next; + } + if (!cur_term) + return CR_ERROR ; + + for (direction = 0; direction < NB_DIRS; direction++) { + set_prop_padding_x_from_value (a_style, cur_term, direction); + } + cur_term = cur_term->next; + + /*filter non NUMBER terms that some users can have written here...*/ + while (cur_term && cur_term->type != TERM_NUMBER) { + cur_term = cur_term->next; + } + /*the user can have just written padding: 1px*/ + if (!cur_term) + return CR_OK; + + set_prop_padding_x_from_value (a_style, cur_term, DIR_RIGHT); + set_prop_padding_x_from_value (a_style, cur_term, DIR_LEFT); + + while (cur_term && cur_term->type != TERM_NUMBER) { + cur_term = cur_term->next; + } + if (!cur_term) + return CR_OK; + + set_prop_padding_x_from_value (a_style, cur_term, DIR_BOTTOM); + + while (cur_term && cur_term->type != TERM_NUMBER) { + cur_term = cur_term->next; + } + if (!cur_term) + return CR_OK; + status = set_prop_padding_x_from_value (a_style, cur_term, DIR_LEFT); + return status; +} + +static enum CRStatus +set_prop_margin_from_value (CRStyle * a_style, CRTerm * a_value) +{ + CRTerm *cur_term = NULL; + enum CRDirection direction = 0; + enum CRStatus status = CR_OK; + + g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR); + + cur_term = a_value; + + while (cur_term && cur_term->type != TERM_NUMBER) { + cur_term = cur_term->next; + } + + if (!cur_term) + return CR_OK; + + for (direction = 0; direction < NB_DIRS; direction++) { + set_prop_margin_x_from_value (a_style, cur_term, direction); + } + cur_term = cur_term->next; + + while (cur_term && cur_term->type != TERM_NUMBER) { + cur_term = cur_term->next; + } + if (!cur_term) + return CR_OK; + + set_prop_margin_x_from_value (a_style, cur_term, DIR_RIGHT); + set_prop_margin_x_from_value (a_style, cur_term, DIR_LEFT); + + while (cur_term && cur_term->type != TERM_NUMBER) { + cur_term = cur_term->next; + } + if (!cur_term) + return CR_OK; + + set_prop_margin_x_from_value (a_style, cur_term, DIR_BOTTOM); + + while (cur_term && cur_term->type != TERM_NUMBER) { + cur_term = cur_term->next; + } + if (!cur_term) + return CR_OK; + + status = set_prop_margin_x_from_value (a_style, cur_term, DIR_LEFT); + + return status; +} + +static enum CRStatus +set_prop_font_family_from_value (CRStyle * a_style, CRTerm * a_value) +{ + CRTerm *cur_term = NULL; + CRFontFamily *font_family = NULL, + *cur_ff = NULL, + *cur_ff2 = NULL; + + g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR); + + if (a_value->type == TERM_IDENT && + a_value->content.str && + a_value->content.str->stryng && + a_value->content.str->stryng->str && + !strcmp ("inherit", a_value->content.str->stryng->str)) + { + font_family = cr_font_family_new (FONT_FAMILY_INHERIT, NULL); + goto out; + } + + for (cur_term = a_value; cur_term; cur_term = cur_term->next) { + switch (cur_term->type) { + case TERM_IDENT: + { + enum CRFontFamilyType font_type; + + if (cur_term->content.str + && cur_term->content.str->stryng + && cur_term->content.str->stryng->str + && !strcmp + (cur_term->content.str->stryng->str, + "sans-serif")) { + font_type = FONT_FAMILY_SANS_SERIF; + } else if (cur_term->content.str + && cur_term->content.str->stryng + && cur_term->content.str->stryng->str + && !strcmp + (cur_term->content.str->stryng->str, + "serif")) { + font_type = FONT_FAMILY_SERIF; + } else if (cur_term->content.str + && cur_term->content.str->stryng + && cur_term->content.str->stryng->str + && !strcmp (cur_term->content.str->stryng->str, + "cursive")) { + font_type = FONT_FAMILY_CURSIVE; + } else if (cur_term->content.str + && cur_term->content.str->stryng + && cur_term->content.str->stryng->str + && !strcmp (cur_term->content.str->stryng->str, + "fantasy")) { + font_type = FONT_FAMILY_FANTASY; + } else if (cur_term->content.str + && cur_term->content.str->stryng + && cur_term->content.str->stryng->str + && !strcmp (cur_term->content.str->stryng->str, + "monospace")) { + font_type = FONT_FAMILY_MONOSPACE; + } else { + /* + *unknown property value. + *ignore it. + */ + continue; + } + + cur_ff = cr_font_family_new (font_type, NULL); + } + break; + + case TERM_STRING: + { + if (cur_term->content.str + && cur_term->content.str->stryng + && cur_term->content.str->stryng->str) { + cur_ff = cr_font_family_new + (FONT_FAMILY_NON_GENERIC, + cur_term->content.str->stryng->str); + } + } + break; + + default: + break; + } + + cur_ff2 = cr_font_family_append (font_family, cur_ff); + if (cur_ff2) { + font_family = cur_ff2; + } + } + + out: + if (font_family) { + if (a_style->font_family) { + cr_font_family_destroy (a_style->font_family); + a_style->font_family = NULL ; + } + a_style->font_family = font_family; + font_family = NULL ; + } + + return CR_OK; +} + +static enum CRStatus +init_style_font_size_field (CRStyle * a_style) +{ + g_return_val_if_fail (a_style, CR_BAD_PARAM_ERROR); + + memset (&a_style->font_size, 0, + sizeof (CRFontSizeVal)) ; + /* + if (!a_style->font_size) { + a_style->font_size = cr_font_size_new (); + if (!a_style->font_size) { + return CR_INSTANCIATION_FAILED_ERROR; + } + } else { + cr_font_size_clear (a_style->font_size); + } + */ + return CR_OK; +} + +static enum CRStatus +set_prop_font_size_from_value (CRStyle * a_style, CRTerm * a_value) +{ + enum CRStatus status = CR_OK; + + g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR); + + switch (a_value->type) { + case TERM_IDENT: + if (a_value->content.str + && a_value->content.str->stryng + && a_value->content.str->stryng->str + && !strcmp (a_value->content.str->stryng->str, + "xx-small")) { + status = init_style_font_size_field (a_style); + g_return_val_if_fail (status == CR_OK, status); + + a_style->font_size.sv.type = + PREDEFINED_ABSOLUTE_FONT_SIZE; + a_style->font_size.sv.value.predefined = + FONT_SIZE_XX_SMALL; + + } else if (a_value->content.str + && a_value->content.str->stryng + && a_value->content.str->stryng->str + && !strcmp (a_value->content.str->stryng->str, + "x-small")) { + status = init_style_font_size_field (a_style); + g_return_val_if_fail (status == CR_OK, status); + + a_style->font_size.sv.type = + PREDEFINED_ABSOLUTE_FONT_SIZE; + a_style->font_size.sv.value.predefined = + FONT_SIZE_X_SMALL; + } else if (a_value->content.str + && a_value->content.str->stryng + && a_value->content.str->stryng->str + && !strcmp (a_value->content.str->stryng->str, + "small")) { + status = init_style_font_size_field (a_style); + g_return_val_if_fail (status == CR_OK, status); + + a_style->font_size.sv.type = + PREDEFINED_ABSOLUTE_FONT_SIZE; + a_style->font_size.sv.value.predefined = + FONT_SIZE_SMALL; + } else if (a_value->content.str + && a_value->content.str->stryng + && a_value->content.str->stryng->str + && !strcmp (a_value->content.str->stryng->str, "medium")) { + status = init_style_font_size_field (a_style); + g_return_val_if_fail (status == CR_OK, status); + + a_style->font_size.sv.type = + PREDEFINED_ABSOLUTE_FONT_SIZE; + a_style->font_size.sv.value.predefined = + FONT_SIZE_MEDIUM; + } else if (a_value->content.str + && a_value->content.str->stryng + && a_value->content.str->stryng->str + && !strcmp (a_value->content.str->stryng->str, + "large")) { + status = init_style_font_size_field (a_style); + g_return_val_if_fail (status == CR_OK, status); + + a_style->font_size.sv.type = + PREDEFINED_ABSOLUTE_FONT_SIZE; + a_style->font_size.sv.value.predefined = + FONT_SIZE_LARGE; + } else if (a_value->content.str + && a_value->content.str->stryng + && a_value->content.str->stryng->str + && !strcmp (a_value->content.str->stryng->str, + "x-large")) { + status = init_style_font_size_field (a_style); + g_return_val_if_fail (status == CR_OK, status); + + a_style->font_size.sv.type = + PREDEFINED_ABSOLUTE_FONT_SIZE; + a_style->font_size.sv.value.predefined = + FONT_SIZE_X_LARGE; + } else if (a_value->content.str + && a_value->content.str->stryng + && a_value->content.str->stryng->str + && !strcmp (a_value->content.str->stryng->str, + "xx-large")) { + status = init_style_font_size_field (a_style); + g_return_val_if_fail (status == CR_OK, status); + + a_style->font_size.sv.type = + PREDEFINED_ABSOLUTE_FONT_SIZE; + a_style->font_size.sv.value.predefined = + FONT_SIZE_XX_LARGE; + } else if (a_value->content.str + && a_value->content.str->stryng + && a_value->content.str->stryng->str + && !strcmp (a_value->content.str->stryng->str, + "larger")) { + status = init_style_font_size_field (a_style); + g_return_val_if_fail (status == CR_OK, status); + + a_style->font_size.sv.type = RELATIVE_FONT_SIZE; + a_style->font_size.sv.value.relative = FONT_SIZE_LARGER; + } else if (a_value->content.str + && a_value->content.str->stryng + && a_value->content.str->stryng->str + && !strcmp (a_value->content.str->stryng->str, + "smaller")) { + status = init_style_font_size_field (a_style); + g_return_val_if_fail (status == CR_OK, status); + + a_style->font_size.sv.type = RELATIVE_FONT_SIZE; + a_style->font_size.sv.value.relative = + FONT_SIZE_SMALLER; + } else if (a_value->content.str + && a_value->content.str->stryng + && a_value->content.str->stryng->str + && !strcmp (a_value->content.str->stryng->str, "inherit")) { + status = init_style_font_size_field (a_style); + g_return_val_if_fail (status == CR_OK, status); + a_style->font_size.sv.type = INHERITED_FONT_SIZE; + + } else { + cr_utils_trace_info ("Unknow value of font-size") ; + status = init_style_font_size_field (a_style); + return CR_UNKNOWN_PROP_VAL_ERROR; + } + break; + + case TERM_NUMBER: + if (a_value->content.num) { + status = init_style_font_size_field (a_style); + g_return_val_if_fail (status == CR_OK, status); + + a_style->font_size.sv.type = ABSOLUTE_FONT_SIZE; + cr_num_copy (&a_style->font_size.sv.value.absolute, + a_value->content.num) ; + } + break; + + default: + status = init_style_font_size_field (a_style); + return CR_UNKNOWN_PROP_VAL_ERROR; + } + return CR_OK; +} + +static enum CRStatus +set_prop_font_style_from_value (CRStyle * a_style, CRTerm * a_value) +{ + enum CRStatus status = CR_OK; + + g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR); + + switch (a_value->type) { + case TERM_IDENT: + if (a_value->content.str + && a_value->content.str->stryng + && a_value->content.str->stryng->str) { + if (!strcmp (a_value->content.str->stryng->str, "normal")) { + a_style->font_style = FONT_STYLE_NORMAL; + } else if (!strcmp + (a_value->content.str->stryng->str, + "italic")) { + a_style->font_style = FONT_STYLE_ITALIC; + } else if (!strcmp + (a_value->content.str->stryng->str, + "oblique")) { + a_style->font_style = FONT_STYLE_OBLIQUE; + } else if (!strcmp + (a_value->content.str->stryng->str, + "inherit")) { + a_style->font_style = FONT_STYLE_INHERIT; + } else { + status = CR_UNKNOWN_PROP_VAL_ERROR; + } + } + break; + + default: + status = CR_UNKNOWN_PROP_VAL_ERROR; + break; + } + + return status; +} + +static enum CRStatus +set_prop_font_weight_from_value (CRStyle * a_style, CRTerm * a_value) +{ + enum CRStatus status = CR_OK; + + g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR); + + switch (a_value->type) { + case TERM_IDENT: + if (a_value->content.str + && a_value->content.str->stryng + && a_value->content.str->stryng->str) { + if (!strcmp (a_value->content.str->stryng->str, + "normal")) { + a_style->font_weight = FONT_WEIGHT_NORMAL; + } else if (!strcmp (a_value->content.str->stryng->str, + "bold")) { + a_style->font_weight = FONT_WEIGHT_BOLD; + } else if (!strcmp (a_value->content.str->stryng->str, + "bolder")) { + a_style->font_weight = FONT_WEIGHT_BOLDER; + } else if (!strcmp (a_value->content.str->stryng->str, + "lighter")) { + a_style->font_weight = FONT_WEIGHT_LIGHTER; + } else if (!strcmp (a_value->content.str->stryng->str, + "inherit")) { + a_style->font_weight = FONT_WEIGHT_INHERIT; + + } else { + status = CR_UNKNOWN_PROP_VAL_ERROR; + } + + } + break; + + case TERM_NUMBER: + if (a_value->content.num + && (a_value->content.num->type == NUM_GENERIC + || a_value->content.num->type == NUM_AUTO)) { + if (a_value->content.num->val <= 150) { + a_style->font_weight = FONT_WEIGHT_100; + } else if (a_value->content.num->val <= 250) { + a_style->font_weight = FONT_WEIGHT_200; + } else if (a_value->content.num->val <= 350) { + a_style->font_weight = FONT_WEIGHT_300; + } else if (a_value->content.num->val <= 450) { + a_style->font_weight = FONT_WEIGHT_400; + } else if (a_value->content.num->val <= 550) { + a_style->font_weight = FONT_WEIGHT_500; + } else if (a_value->content.num->val <= 650) { + a_style->font_weight = FONT_WEIGHT_600; + } else if (a_value->content.num->val <= 750) { + a_style->font_weight = FONT_WEIGHT_700; + } else if (a_value->content.num->val <= 850) { + a_style->font_weight = FONT_WEIGHT_800; + } else { + a_style->font_weight = FONT_WEIGHT_900; + } + } + break; + + default: + status = CR_UNKNOWN_PROP_VAL_ERROR; + break; + } + + return status; +} + +static enum CRStatus +set_prop_white_space_from_value (CRStyle * a_style, CRTerm * a_value) +{ + enum CRStatus status = CR_OK; + + g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR); + + switch (a_value->type) { + case TERM_IDENT: + if (a_value->content.str && a_value->content.str->stryng) { + if (!strcmp (a_value->content.str->stryng->str, "normal")) { + a_style->white_space = WHITE_SPACE_NORMAL; + } else if (!strcmp (a_value->content.str->stryng->str, + "pre")) { + a_style->font_weight = WHITE_SPACE_PRE; + } else if (!strcmp (a_value->content.str->stryng->str, + "nowrap")) { + a_style->white_space = WHITE_SPACE_NOWRAP; + } else if (!strcmp (a_value->content.str->stryng->str, + "inherit")) { + a_style->white_space = WHITE_SPACE_INHERIT; + } else { + status = CR_UNKNOWN_PROP_VAL_ERROR; + } + } + break; + default: + status = CR_UNKNOWN_PROP_VAL_ERROR; + break; + } + + return status; +} + +/****************** + *Public methods + ******************/ + +/** + *Default constructor of #CRStyle. + *@param a_set_props_to_initial_values if TRUE, the style properties + *will be set to the default values. Only the style properties of the + *root box should be set to their initial values. + *Otherwise, the style values are set to their default value. + *Read the CSS2 spec, chapters 6.1.1 to 6.2. + */ +CRStyle * +cr_style_new (gboolean a_set_props_to_initial_values) +{ + CRStyle *result = NULL; + + result = g_try_malloc (sizeof (CRStyle)); + if (!result) { + cr_utils_trace_info ("Out of memory"); + return NULL; + } + memset (result, 0, sizeof (CRStyle)); + gv_prop_hash_ref_count++; + + if (a_set_props_to_initial_values == TRUE) { + cr_style_set_props_to_initial_values (result); + } else { + cr_style_set_props_to_default_values (result); + } + + return result; +} + +/** + *Sets the style properties to their default values according to the css2 spec + * i.e inherit if the property is inherited, its initial value otherwise. + *@param a_this the current instance of #CRStyle. + *@return CR_OK upon successfull completion, an error code otherwise. + */ +enum CRStatus +cr_style_set_props_to_default_values (CRStyle * a_this) +{ + glong i = 0; + + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); + + for (i = 0; i < NB_NUM_PROPS; i++) + { + switch (i) + { + case NUM_PROP_WIDTH: + case NUM_PROP_TOP: + case NUM_PROP_RIGHT: + case NUM_PROP_BOTTOM: + case NUM_PROP_LEFT: + cr_num_set (&a_this->num_props[i].sv, 0, NUM_AUTO); + break; + + case NUM_PROP_PADDING_TOP: + case NUM_PROP_PADDING_RIGHT: + case NUM_PROP_PADDING_BOTTOM: + case NUM_PROP_PADDING_LEFT: + case NUM_PROP_BORDER_TOP: + case NUM_PROP_BORDER_RIGHT: + case NUM_PROP_BORDER_BOTTOM: + case NUM_PROP_BORDER_LEFT: + case NUM_PROP_MARGIN_TOP: + case NUM_PROP_MARGIN_RIGHT: + case NUM_PROP_MARGIN_BOTTOM: + case NUM_PROP_MARGIN_LEFT: + cr_num_set (&a_this->num_props[i].sv, + 0, NUM_LENGTH_PX); + break; + + default: + cr_utils_trace_info ("Unknown property"); + break; + } + } + + for (i = 0; i < NB_RGB_PROPS; i++) { + + switch (i) { + /*default foreground color is black */ + case RGB_PROP_COLOR: + /* + *REVIEW: color is inherited and the default value is + *ua dependant. + */ + cr_rgb_set_to_inherit (&a_this->rgb_props[i].sv, + TRUE) ; + break; + + /*default background color is white */ + case RGB_PROP_BACKGROUND_COLOR: + /* TODO: the default value should be transparent */ + cr_rgb_set (&a_this->rgb_props[i].sv, + 255, 255, 255, FALSE); + cr_rgb_set_to_transparent (&a_this->rgb_props[i].sv, + TRUE) ; + break; + + default: + /* + *TODO: for BORDER_COLOR the initial value should + * be the same as COLOR + */ + cr_rgb_set (&a_this->rgb_props[i].sv, 0, 0, 0, + FALSE); + break; + } + } + + for (i = 0; i < NB_BORDER_STYLE_PROPS; i++) { + a_this->border_style_props[i] = BORDER_STYLE_NONE; + } + + a_this->display = DISPLAY_INLINE; + a_this->position = POSITION_STATIC; + a_this->float_type = FLOAT_NONE; + a_this->parent_style = NULL; + a_this->font_style = FONT_STYLE_INHERIT; + a_this->font_variant = FONT_VARIANT_INHERIT; + a_this->font_weight = FONT_WEIGHT_INHERIT; + a_this->font_family = NULL; + + cr_font_size_set_to_inherit (&a_this->font_size.sv) ; + cr_font_size_clear (&a_this->font_size.cv) ; + cr_font_size_clear (&a_this->font_size.av) ; + + /* To make the inheritance resolution possible and efficient */ + a_this->inherited_props_resolved = FALSE ; + return CR_OK; +} + +/** + *Sets the style properties to their initial value according to the css2 spec. + *This function should be used to initialize the style of the root element + *of an xml tree. + *Some properties are user agent dependant like font-family, and + *are not initialized, read the spec to make you renderer compliant. + *@param a_this the current instance of #CRStyle. + *@return CR_OK upon successfull completion, an error code otherwise. + */ +enum CRStatus +cr_style_set_props_to_initial_values (CRStyle *a_this) +{ + glong i = 0; + + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); + + for (i = 0; i < NB_NUM_PROPS; i++) { + switch (i) { + case NUM_PROP_WIDTH: + cr_num_set (&a_this->num_props[i].sv, 800, + NUM_LENGTH_PX) ; + break ; + case NUM_PROP_TOP: + case NUM_PROP_RIGHT: + case NUM_PROP_BOTTOM: + case NUM_PROP_LEFT: + cr_num_set (&a_this->num_props[i].sv, 0, NUM_AUTO); + break; + + case NUM_PROP_PADDING_TOP: + case NUM_PROP_PADDING_RIGHT: + case NUM_PROP_PADDING_BOTTOM: + case NUM_PROP_PADDING_LEFT: + case NUM_PROP_BORDER_TOP: + case NUM_PROP_BORDER_RIGHT: + case NUM_PROP_BORDER_BOTTOM: + case NUM_PROP_BORDER_LEFT: + case NUM_PROP_MARGIN_TOP: + case NUM_PROP_MARGIN_RIGHT: + case NUM_PROP_MARGIN_BOTTOM: + case NUM_PROP_MARGIN_LEFT: + cr_num_set (&a_this->num_props[i].sv, + 0, NUM_LENGTH_PX); + break; + + default: + cr_utils_trace_info ("Unknown property"); + break; + } + } + + for (i = 0; i < NB_RGB_PROPS; i++) { + + switch (i) { + /*default foreground color is black */ + case RGB_PROP_COLOR: + cr_rgb_set (&a_this->rgb_props[i].sv, 0, 0, 0, FALSE); + break; + + /*default background color is white */ + case RGB_PROP_BACKGROUND_COLOR: + cr_rgb_set (&a_this->rgb_props[i].sv, + 255, 255, 255, FALSE); + cr_rgb_set_to_transparent (&a_this->rgb_props[i].sv, + TRUE) ; + break; + default: + cr_rgb_set (&a_this->rgb_props[i].sv, 0, 0, 0, FALSE); + break; + } + } + + for (i = 0; i < NB_BORDER_STYLE_PROPS; i++) { + a_this->border_style_props[i] = BORDER_STYLE_NONE; + } + + a_this->display = DISPLAY_BLOCK; + a_this->position = POSITION_STATIC; + a_this->float_type = FLOAT_NONE; + a_this->font_style = FONT_STYLE_NORMAL; + a_this->font_variant = FONT_VARIANT_NORMAL; + a_this->font_weight = FONT_WEIGHT_NORMAL; + a_this->font_stretch = FONT_STRETCH_NORMAL; + a_this->white_space = WHITE_SPACE_NORMAL; + cr_font_size_set_predefined_absolute_font_size + (&a_this->font_size.sv, FONT_SIZE_MEDIUM) ; + a_this->inherited_props_resolved = FALSE ; + + return CR_OK; +} + +/** + *Resolves the inherited properties. + *The function sets the "inherited" properties to either the value of + *their parent properties. + *This function is *NOT* recursive. So the inherited properties of + *the parent style must have been resolved prior to calling this function. + *@param a_this the instance where + *@return CR_OK if a root node is found and the propagation is successful, + *an error code otherwise + */ +enum CRStatus +cr_style_resolve_inherited_properties (CRStyle *a_this) +{ + enum CRStatus ret = CR_OK; + glong i = 0; + + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); + g_return_val_if_fail (a_this->parent_style, CR_BAD_PARAM_ERROR) ; + + if (a_this->inherited_props_resolved == TRUE) + return CR_OK ; + + for (i=0 ; i < NB_NUM_PROPS ;i++) { + if (a_this->num_props[i].sv.type == NUM_INHERIT) { + cr_num_copy (&a_this->num_props[i].cv, + &a_this->parent_style->num_props[i].cv); + } + } + for (i=0; i < NB_RGB_PROPS; i++) { + if (cr_rgb_is_set_to_inherit (&a_this->rgb_props[i].sv) == TRUE) { + cr_rgb_copy ( + &a_this->rgb_props[i].cv, + &a_this->parent_style->rgb_props[i].cv); + } + } + for (i = 0; i < NB_BORDER_STYLE_PROPS; i++) { + if (a_this->border_style_props[i] == BORDER_STYLE_INHERIT) { + a_this->border_style_props[i] = + a_this->parent_style->border_style_props[i]; + } + } + + if (a_this->display == DISPLAY_INHERIT) { + a_this->display = a_this->parent_style->display; + } + if (a_this->position == POSITION_INHERIT) { + a_this->position = a_this->parent_style->position; + } + if (a_this->float_type == FLOAT_INHERIT) { + a_this->float_type = a_this->parent_style->float_type; + } + if (a_this->font_style == FONT_STYLE_INHERIT) { + a_this->font_style = a_this->parent_style->font_style; + } + if (a_this->font_variant == FONT_VARIANT_INHERIT) { + a_this->font_variant = a_this->parent_style->font_variant; + } + if (a_this->font_weight == FONT_WEIGHT_INHERIT) { + a_this->font_weight = a_this->parent_style->font_weight; + } + if (a_this->font_stretch == FONT_STRETCH_INHERIT) { + a_this->font_stretch = a_this->parent_style->font_stretch; + } + /*NULL is inherit marker for font_famiy*/ + if (a_this->font_family == NULL) { + a_this->font_family = a_this->parent_style->font_family; + } + if (a_this->font_size.sv.type == INHERITED_FONT_SIZE) { + cr_font_size_copy (&a_this->font_size.cv, + &a_this->parent_style->font_size.cv) ; + } + a_this->inherited_props_resolved = TRUE ; + return ret; +} + +/** + *Walks through a css2 property declaration, and populated the + *according field(s) in the #CRStyle structure. + *If the properties or their value(s) are/is not known, + *sets the corresponding field(s) of #CRStyle to its/their default + *value(s) + *@param a_this the instance of #CRStyle to set. + *@param a_decl the declaration from which the #CRStyle fields are set. + *@return CR_OK upon successfull completion, an error code otherwise. + */ +enum CRStatus +cr_style_set_style_from_decl (CRStyle * a_this, CRDeclaration * a_decl) +{ + CRTerm *value = NULL; + enum CRStatus status = CR_OK; + + enum CRPropertyID prop_id = PROP_ID_NOT_KNOWN; + + g_return_val_if_fail (a_this && a_decl + && a_decl + && a_decl->property + && a_decl->property->stryng + && a_decl->property->stryng->str, + CR_BAD_PARAM_ERROR); + + prop_id = cr_style_get_prop_id + (a_decl->property->stryng->str); + + value = a_decl->value; + switch (prop_id) { + case PROP_ID_PADDING_TOP: + status = set_prop_padding_x_from_value + (a_this, value, DIR_TOP); + break; + + case PROP_ID_PADDING_RIGHT: + status = set_prop_padding_x_from_value + (a_this, value, DIR_RIGHT); + break; + case PROP_ID_PADDING_BOTTOM: + status = set_prop_padding_x_from_value + (a_this, value, DIR_BOTTOM); + break; + + case PROP_ID_PADDING_LEFT: + status = set_prop_padding_x_from_value + (a_this, value, DIR_LEFT); + break; + + case PROP_ID_PADDING: + status = set_prop_padding_from_value (a_this, value) ; + break; + + case PROP_ID_BORDER_TOP_WIDTH: + status = set_prop_border_x_width_from_value (a_this, value, + DIR_TOP); + break; + + case PROP_ID_BORDER_RIGHT_WIDTH: + status = set_prop_border_x_width_from_value (a_this, value, + DIR_RIGHT); + break; + + case PROP_ID_BORDER_BOTTOM_WIDTH: + status = set_prop_border_x_width_from_value (a_this, value, + DIR_BOTTOM); + break; + + case PROP_ID_BORDER_LEFT_WIDTH: + status = set_prop_border_x_width_from_value (a_this, value, + DIR_LEFT); + break; + + case PROP_ID_BORDER_WIDTH: + status = set_prop_border_width_from_value (a_this, value) ; + break ; + + case PROP_ID_BORDER_TOP_STYLE: + status = set_prop_border_x_style_from_value (a_this, value, + DIR_TOP); + break; + + case PROP_ID_BORDER_RIGHT_STYLE: + status = set_prop_border_x_style_from_value (a_this, value, + DIR_RIGHT); + break; + + case PROP_ID_BORDER_BOTTOM_STYLE: + status = set_prop_border_x_style_from_value (a_this, value, + DIR_BOTTOM); + break; + + case PROP_ID_BORDER_LEFT_STYLE: + status = set_prop_border_x_style_from_value (a_this, value, + DIR_LEFT); + break; + + case PROP_ID_BORDER_STYLE: + status = set_prop_border_style_from_value (a_this, value) ; + break ; + + case PROP_ID_BORDER_TOP_COLOR: + status = set_prop_border_x_color_from_value (a_this, value, + DIR_TOP); + break; + + case PROP_ID_BORDER_RIGHT_COLOR: + status = set_prop_border_x_color_from_value (a_this, value, + DIR_RIGHT); + break; + + case PROP_ID_BORDER_BOTTOM_COLOR: + status = set_prop_border_x_color_from_value (a_this, value, + DIR_BOTTOM); + break; + + case PROP_ID_BORDER_LEFT_COLOR: + status = set_prop_border_x_color_from_value (a_this, value, + DIR_BOTTOM); + break; + + case PROP_ID_BORDER_TOP: + status = set_prop_border_x_from_value (a_this, value, + DIR_TOP); + break; + + case PROP_ID_BORDER_RIGHT: + status = set_prop_border_x_from_value (a_this, value, + DIR_RIGHT); + break; + + case PROP_ID_BORDER_BOTTOM: + status = set_prop_border_x_from_value (a_this, value, + DIR_BOTTOM); + break; + + case PROP_ID_BORDER_LEFT: + status = set_prop_border_x_from_value (a_this, value, + DIR_LEFT); + break; + + case PROP_ID_MARGIN_TOP: + status = set_prop_margin_x_from_value (a_this, value, + DIR_TOP); + break; + + case PROP_ID_BORDER: + status = set_prop_border_from_value (a_this, value); + break; + + case PROP_ID_MARGIN_RIGHT: + status = set_prop_margin_x_from_value (a_this, value, + DIR_RIGHT); + break; + + case PROP_ID_MARGIN_BOTTOM: + status = set_prop_margin_x_from_value (a_this, value, + DIR_BOTTOM); + break; + + case PROP_ID_MARGIN_LEFT: + status = set_prop_margin_x_from_value (a_this, value, + DIR_LEFT); + break; + + case PROP_ID_MARGIN: + status = set_prop_margin_from_value (a_this, value); + break; + + case PROP_ID_DISPLAY: + status = set_prop_display_from_value (a_this, value); + break; + + case PROP_ID_POSITION: + status = set_prop_position_from_value (a_this, value); + break; + + case PROP_ID_TOP: + status = set_prop_x_from_value (a_this, value, DIR_TOP); + break; + + case PROP_ID_RIGHT: + status = set_prop_x_from_value (a_this, value, DIR_RIGHT); + break; + + case PROP_ID_BOTTOM: + status = set_prop_x_from_value (a_this, value, DIR_BOTTOM); + break; + + case PROP_ID_LEFT: + status = set_prop_x_from_value (a_this, value, DIR_LEFT); + break; + + case PROP_ID_FLOAT: + status = set_prop_float (a_this, value); + break; + + case PROP_ID_WIDTH: + status = set_prop_width (a_this, value); + break; + + case PROP_ID_COLOR: + status = set_prop_color (a_this, value); + break; + + case PROP_ID_BACKGROUND_COLOR: + status = set_prop_background_color (a_this, value); + break; + + case PROP_ID_FONT_FAMILY: + status = set_prop_font_family_from_value (a_this, value); + break; + + case PROP_ID_FONT_SIZE: + status = set_prop_font_size_from_value (a_this, value); + break; + + case PROP_ID_FONT_STYLE: + status = set_prop_font_style_from_value (a_this, value); + break; + + case PROP_ID_FONT_WEIGHT: + status = set_prop_font_weight_from_value (a_this, value); + break; + + case PROP_ID_WHITE_SPACE: + status = set_prop_white_space_from_value(a_this, value); + break; + + default: + return CR_UNKNOWN_TYPE_ERROR; + + } + + return status; +} + +/** + *Increases the reference count + *of the current instance of #CRStyle. + *@param a_this the current instance of #CRStyle. + *@return CR_OK upon successfull completion, an error code + *otherwise. + */ +enum CRStatus +cr_style_ref (CRStyle * a_this) +{ + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); + + a_this->ref_count++; + return CR_OK; +} + +/** + *Decreases the reference count of + *the current instance of #CRStyle. + *If the reference count reaches 0, the + *instance of #CRStyle is destoyed. + *@param a_this the current instance of #CRStyle. + *@return TRUE if the instance has been destroyed, FALSE + *otherwise. + */ +gboolean +cr_style_unref (CRStyle * a_this) +{ + g_return_val_if_fail (a_this, FALSE); + + if (a_this->ref_count) + a_this->ref_count--; + + if (!a_this->ref_count) { + cr_style_destroy (a_this); + return TRUE; + } + + return FALSE; +} + +/** + *Duplicates the current instance of #CRStyle . + *The newly created instance of #CRStyle must be + *freed using cr_style_destroy (). + *@param a_this the current instance of #CRStyle. + *@return the newly duplicated instance of #CRStyle. + */ +CRStyle * +cr_style_dup (CRStyle * a_this) +{ + CRStyle *result = NULL; + + g_return_val_if_fail (a_this, NULL); + + result = cr_style_new (FALSE); + if (!result) { + cr_utils_trace_info ("Out of memory"); + return NULL; + } + cr_style_copy (result, a_this); + return result; +} + +/** + *Copies a style data structure into another. + *TODO: this is actually broken because it's based + *on memcpy although some data stuctures of CRStyle should + *be properly duplicated. + *@param a_dest the destination style datastructure + *@param a_src the source style datastructure. + *@return CR_OK upon succesfull completion, an error code otherwise + */ +enum CRStatus +cr_style_copy (CRStyle * a_dest, CRStyle * a_src) +{ + g_return_val_if_fail (a_dest && a_src, CR_BAD_PARAM_ERROR); + + memcpy (a_dest, a_src, sizeof (CRStyle)); + return CR_OK; +} + +/** + *dump a CRNumpPropVal in a string. + *@param a_prop_val the numerical property value to dump + *@param a_str the string to dump the numerical propertie into. + *Note that the string value is appended to a_str. + *@param a_nb_indent the number white chars of indentation. + */ +enum CRStatus +cr_style_num_prop_val_to_string (CRNumPropVal * a_prop_val, + GString * a_str, guint a_nb_indent) +{ + enum CRStatus status = CR_OK; + guchar *tmp_str = NULL; + GString *str = NULL; + + g_return_val_if_fail (a_prop_val && a_str, CR_BAD_PARAM_ERROR); + + str = g_string_new (NULL); + cr_utils_dump_n_chars2 (' ', str, a_nb_indent); + g_string_append (str, "NumPropVal {"); + tmp_str = cr_num_to_string (&a_prop_val->sv); + if (!tmp_str) { + status = CR_ERROR; + goto cleanup; + } + g_string_append_printf (str, "sv: %s ", tmp_str); + g_free (tmp_str); + tmp_str = NULL; + + tmp_str = cr_num_to_string (&a_prop_val->cv); + if (!tmp_str) { + status = CR_ERROR; + goto cleanup; + } + g_string_append_printf (str, "cv: %s ", tmp_str); + g_free (tmp_str); + tmp_str = NULL; + + tmp_str = cr_num_to_string (&a_prop_val->av); + if (!tmp_str) { + status = CR_ERROR; + goto cleanup; + } + g_string_append_printf (str, "av: %s ", tmp_str); + g_free (tmp_str); + tmp_str = NULL; + g_string_append (str, "}"); + g_string_append (a_str, str->str); + status = CR_OK; + cleanup: + + if (tmp_str) { + g_free (tmp_str); + tmp_str = NULL; + } + if (str) { + g_string_free (str, TRUE); + } + return status; +} + +enum CRStatus +cr_style_rgb_prop_val_to_string (CRRgbPropVal * a_prop_val, + GString * a_str, guint a_nb_indent) +{ + enum CRStatus status = CR_OK; + guchar *tmp_str = NULL; + GString *str = NULL; + + g_return_val_if_fail (a_prop_val && a_str, CR_BAD_PARAM_ERROR); + + str = g_string_new (NULL); + + cr_utils_dump_n_chars2 (' ', str, a_nb_indent); + g_string_append (str, "RGBPropVal {"); + tmp_str = cr_rgb_to_string (&a_prop_val->sv); + if (!tmp_str) { + status = CR_ERROR; + goto cleanup; + } + g_string_append_printf (str, "sv: %s ", tmp_str); + g_free (tmp_str); + tmp_str = NULL; + tmp_str = cr_rgb_to_string (&a_prop_val->cv); + if (!tmp_str) { + status = CR_ERROR; + goto cleanup; + } + g_string_append_printf (str, "cv: %s ", tmp_str); + g_free (tmp_str); + tmp_str = NULL; + tmp_str = cr_rgb_to_string (&a_prop_val->av); + if (!tmp_str) { + status = CR_ERROR; + goto cleanup; + } + g_string_append_printf (str, "av: %s ", tmp_str); + g_free (tmp_str); + tmp_str = NULL; + + g_string_append (str, "}"); + g_string_append (a_str, str->str); + status = CR_OK; + cleanup: + + if (tmp_str) { + g_free (tmp_str); + tmp_str = NULL; + } + if (str) { + g_string_free (str, TRUE); + } + return status; +} + +enum CRStatus +cr_style_border_style_to_string (enum CRBorderStyle a_prop, + GString * a_str, guint a_nb_indent) +{ + gchar *str = NULL; + + g_return_val_if_fail (a_str, CR_BAD_PARAM_ERROR); + + switch (a_prop) { + case BORDER_STYLE_NONE: + str = (gchar *) "border-style-none"; + break; + case BORDER_STYLE_HIDDEN: + str = (gchar *) "border-style-hidden"; + break; + case BORDER_STYLE_DOTTED: + str = (gchar *) "border-style-dotted"; + break; + case BORDER_STYLE_DASHED: + str = (gchar *) "border-style-dashed"; + break; + case BORDER_STYLE_SOLID: + str = (gchar *) "border-style-solid"; + break; + case BORDER_STYLE_DOUBLE: + str = (gchar *) "border-style-double"; + break; + case BORDER_STYLE_GROOVE: + str = (gchar *) "border-style-groove"; + break; + case BORDER_STYLE_RIDGE: + str = (gchar *) "border-style-ridge"; + break; + case BORDER_STYLE_INSET: + str = (gchar *) "border-style-inset"; + break; + case BORDER_STYLE_OUTSET: + str = (gchar *) "border-style-outset"; + break; + default: + str = (gchar *) "unknown border style"; + break; + } + cr_utils_dump_n_chars2 (' ', a_str, a_nb_indent); + g_string_append (a_str, str); + return CR_OK; +} + +enum CRStatus +cr_style_display_type_to_string (enum CRDisplayType a_code, + GString * a_str, guint a_nb_indent) +{ + gchar *str = NULL; + + g_return_val_if_fail (a_str, CR_BAD_PARAM_ERROR); + + switch (a_code) { + case DISPLAY_NONE: + str = (gchar *) "display-none"; + break; + case DISPLAY_INLINE: + str = (gchar *) "display-inline"; + break; + case DISPLAY_BLOCK: + str = (gchar *) "display-block"; + break; + case DISPLAY_LIST_ITEM: + str = (gchar *) "display-list-item"; + break; + case DISPLAY_RUN_IN: + str = (gchar *) "display-run-in"; + break; + case DISPLAY_COMPACT: + str = (gchar *) "display-compact"; + break; + case DISPLAY_MARKER: + str = (gchar *) "display-marker"; + break; + case DISPLAY_TABLE: + str = (gchar *) "display-table"; + break; + case DISPLAY_INLINE_TABLE: + str = (gchar *) "display-inline-table"; + break; + case DISPLAY_TABLE_ROW_GROUP: + str = (gchar *) "display-table-row-group"; + break; + case DISPLAY_TABLE_HEADER_GROUP: + str = (gchar *) "display-table-header-group"; + break; + case DISPLAY_TABLE_FOOTER_GROUP: + str = (gchar *) "display-table-footer-group"; + break; + case DISPLAY_TABLE_ROW: + str = (gchar *) "display-table-row"; + break; + case DISPLAY_TABLE_COLUMN_GROUP: + str = (gchar *) "display-table-column-group"; + break; + case DISPLAY_TABLE_COLUMN: + str = (gchar *) "display-table-column"; + break; + case DISPLAY_TABLE_CELL: + str = (gchar *) "display-table-cell"; + break; + case DISPLAY_TABLE_CAPTION: + str = (gchar *) "display-table-caption"; + break; + case DISPLAY_INHERIT: + str = (gchar *) "display-inherit"; + break; + default: + str = (gchar *) "unknown display property"; + break; + } + cr_utils_dump_n_chars2 (' ', a_str, a_nb_indent); + g_string_append (a_str, str); + return CR_OK; + +} + +enum CRStatus +cr_style_position_type_to_string (enum CRPositionType a_code, + GString * a_str, guint a_nb_indent) +{ + gchar *str = NULL; + + g_return_val_if_fail (a_str, CR_BAD_PARAM_ERROR); + + switch (a_code) { + case POSITION_STATIC: + str = (gchar *) "position-static"; + break; + case POSITION_RELATIVE: + str = (gchar *) "position-relative"; + break; + case POSITION_ABSOLUTE: + str = (gchar *) "position-absolute"; + break; + case POSITION_FIXED: + str = (gchar *) "position-fixed"; + break; + case POSITION_INHERIT: + str = (gchar *) "position-inherit"; + break; + default: + str = (gchar *) "unknown static property"; + } + cr_utils_dump_n_chars2 (' ', a_str, a_nb_indent); + g_string_append (a_str, str); + return CR_OK; +} + +enum CRStatus +cr_style_float_type_to_string (enum CRFloatType a_code, + GString * a_str, guint a_nb_indent) +{ + gchar *str = NULL; + + g_return_val_if_fail (a_str, CR_BAD_PARAM_ERROR); + + switch (a_code) { + case FLOAT_NONE: + str = (gchar *) "float-none"; + break; + case FLOAT_LEFT: + str = (gchar *) "float-left"; + break; + case FLOAT_RIGHT: + str = (gchar *) "float-right"; + break; + case FLOAT_INHERIT: + str = (gchar *) "float-inherit"; + break; + default: + str = (gchar *) "unknown float property value"; + break; + } + cr_utils_dump_n_chars2 (' ', a_str, a_nb_indent); + g_string_append (a_str, str); + return CR_OK; +} + +enum CRStatus +cr_style_white_space_type_to_string (enum CRWhiteSpaceType a_code, + GString * a_str, guint a_nb_indent) +{ + gchar *str = NULL; + + g_return_val_if_fail (a_str, CR_BAD_PARAM_ERROR); + + switch (a_code) { + case WHITE_SPACE_NORMAL: + str = (gchar *) "normal"; + break; + case WHITE_SPACE_PRE: + str = (gchar *) "pre"; + break; + case WHITE_SPACE_NOWRAP: + str = (gchar *) "nowrap"; + break; + case WHITE_SPACE_INHERIT: + str = (gchar *) "inherited"; + break; + default: + str = (gchar *) "unknow white space property value"; + break; + } + cr_utils_dump_n_chars2 (' ', a_str, a_nb_indent); + g_string_append (a_str, str); + return CR_OK; +} + +/** + *Serializes in instance of #CRStyle into + *a string + *@param a_this the instance of #CRStyle to serialize + *@param a_str the string to serialise the style into. + *if *a_str is NULL, a new GString is instanciated, otherwise + *the style serialisation is appended to the existed *a_str + *@param the number of white space char to use for indentation. + *@return CR_OK upon successful completion, an error code otherwise. + */ +enum CRStatus +cr_style_to_string (CRStyle * a_this, GString ** a_str, guint a_nb_indent) +{ + const gint INTERNAL_INDENT = 2; + gint indent = a_nb_indent + INTERNAL_INDENT; + gchar *tmp_str = NULL; + GString *str = NULL; + gint i = 0; + + g_return_val_if_fail (a_this && a_str, CR_BAD_PARAM_ERROR); + + if (!*a_str) { + str = g_string_new (NULL); + } else { + str = *a_str; + } + cr_utils_dump_n_chars2 (' ', str, a_nb_indent); + g_string_append (str, "style {\n"); + + /*loop over the num_props and to_string() them */ + for (i = NUM_PROP_TOP; i < NB_NUM_PROPS; i++) { + /* + *to_string() the name of the num_prop + *(using num_prop_code_to_string) + *before outputing it value + */ + cr_utils_dump_n_chars2 (' ', str, indent); + tmp_str = (gchar *) num_prop_code_to_string (i); + if (tmp_str) { + g_string_append_printf (str, "%s: ", tmp_str); + } else { + g_string_append (str, "NULL"); + } + tmp_str = NULL; + cr_style_num_prop_val_to_string (&a_this->num_props[i], str, + a_nb_indent + + INTERNAL_INDENT); + g_string_append (str, "\n"); + } + /*loop over the rgb_props and to_string() them all */ + for (i = RGB_PROP_BORDER_TOP_COLOR; i < NB_RGB_PROPS; i++) { + tmp_str = (gchar *) rgb_prop_code_to_string (i); + cr_utils_dump_n_chars2 (' ', str, indent); + if (tmp_str) { + g_string_append_printf (str, "%s: ", tmp_str); + } else { + g_string_append (str, "NULL: "); + } + tmp_str = NULL; + cr_style_rgb_prop_val_to_string (&a_this->rgb_props[i], str, + a_nb_indent + + INTERNAL_INDENT); + g_string_append (str, "\n"); + } + /*loop over the border_style_props and to_string() them */ + for (i = BORDER_STYLE_PROP_TOP; i < NB_BORDER_STYLE_PROPS; i++) { + tmp_str = (gchar *) border_style_prop_code_to_string (i); + cr_utils_dump_n_chars2 (' ', str, indent); + if (tmp_str) { + g_string_append_printf (str, "%s: ", tmp_str); + } else { + g_string_append (str, "NULL: "); + } + tmp_str = NULL; + cr_style_border_style_to_string (a_this-> + border_style_props[i], str, + 0); + g_string_append (str, "\n"); + } + cr_utils_dump_n_chars2 (' ', str, indent); + g_string_append (str, "display: "); + cr_style_display_type_to_string (a_this->display, str, 0); + g_string_append (str, "\n"); + + cr_utils_dump_n_chars2 (' ', str, indent); + g_string_append (str, "position: "); + cr_style_position_type_to_string (a_this->position, str, 0); + g_string_append (str, "\n"); + + cr_utils_dump_n_chars2 (' ', str, indent); + g_string_append (str, "float-type: "); + cr_style_float_type_to_string (a_this->float_type, str, 0); + g_string_append (str, "\n"); + + cr_utils_dump_n_chars2 (' ', str, indent); + g_string_append (str, "white-space: "); + cr_style_white_space_type_to_string (a_this->white_space, str, 0); + g_string_append (str, "\n"); + + cr_utils_dump_n_chars2 (' ', str, indent); + g_string_append (str, "font-family: "); + tmp_str = cr_font_family_to_string (a_this->font_family, TRUE); + if (tmp_str) { + g_string_append (str, tmp_str); + g_free (tmp_str); + tmp_str = NULL; + } else { + g_string_append (str, "NULL"); + } + g_string_append (str, "\n"); + + cr_utils_dump_n_chars2 (' ', str, indent); + tmp_str = cr_font_size_to_string (&a_this->font_size.sv); + if (tmp_str) { + g_string_append_printf (str, "font-size {sv:%s, ", + tmp_str) ; + } else { + g_string_append (str, "font-size {sv:NULL, "); + } + tmp_str = cr_font_size_to_string (&a_this->font_size.cv); + if (tmp_str) { + g_string_append_printf (str, "cv:%s, ", tmp_str); + } else { + g_string_append (str, "cv:NULL, "); + } + tmp_str = cr_font_size_to_string (&a_this->font_size.av); + if (tmp_str) { + g_string_append_printf (str, "av:%s}", tmp_str); + } else { + g_string_append (str, "av:NULL}"); + } + + tmp_str = NULL; + g_string_append (str, "\n"); + + cr_utils_dump_n_chars2 (' ', str, indent); + tmp_str = cr_font_size_adjust_to_string (a_this->font_size_adjust); + if (tmp_str) { + g_string_append_printf (str, "font-size-adjust: %s", tmp_str); + } else { + g_string_append (str, "font-size-adjust: NULL"); + } + tmp_str = NULL; + g_string_append (str, "\n"); + + cr_utils_dump_n_chars2 (' ', str, indent); + tmp_str = (gchar *) cr_font_style_to_string (a_this->font_style); + if (tmp_str) { + g_string_append_printf (str, "font-style: %s", tmp_str); + } else { + g_string_append (str, "font-style: NULL"); + } + tmp_str = NULL; + g_string_append (str, "\n"); + + cr_utils_dump_n_chars2 (' ', str, indent); + tmp_str = (gchar *) cr_font_variant_to_string (a_this->font_variant); + if (tmp_str) { + g_string_append_printf (str, "font-variant: %s", tmp_str); + } else { + g_string_append (str, "font-variant: NULL"); + } + tmp_str = NULL; + g_string_append (str, "\n"); + + cr_utils_dump_n_chars2 (' ', str, indent); + tmp_str = (gchar *) cr_font_weight_to_string (a_this->font_weight); + if (tmp_str) { + g_string_append_printf (str, "font-weight: %s", tmp_str); + } else { + g_string_append (str, "font-weight: NULL"); + } + tmp_str = NULL; + g_string_append (str, "\n"); + + cr_utils_dump_n_chars2 (' ', str, indent); + tmp_str = (gchar *) cr_font_stretch_to_string (a_this->font_stretch); + if (tmp_str) { + g_string_append_printf (str, "font-stretch: %s", tmp_str); + } else { + g_string_append (str, "font-stretch: NULL"); + } + tmp_str = NULL; + g_string_append (str, "\n"); + + + cr_utils_dump_n_chars2 (' ', str, a_nb_indent); + g_string_append (str, "}"); + + return CR_OK; +} + +/** + *Destructor of the #CRStyle class. + *@param a_this the instance to destroy. + */ +void +cr_style_destroy (CRStyle * a_this) +{ + g_return_if_fail (a_this); + + g_free (a_this); +} + diff --git a/gettext-tools/gnulib-lib/libcroco/cr-style.h b/gettext-tools/gnulib-lib/libcroco/cr-style.h new file mode 100644 index 0000000..f528cf5 --- /dev/null +++ b/gettext-tools/gnulib-lib/libcroco/cr-style.h @@ -0,0 +1,339 @@ +/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */ + +/* + * This file is part of The Croco Library + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + * Author: Dodji Seketeli. + * See COPYRIGHTS file for copyright information. + */ + +#ifndef __CR_STYLE_H__ +#define __CR_STYLE_H__ + +#include "cr-utils.h" +#include "cr-statement.h" +#include "cr-fonts.h" + +/** + *@file + *The declaration of the #CRStyle class. + */ +G_BEGIN_DECLS + +typedef struct _CRStyle CRStyle ; + +enum CRBorderStyle +{ + BORDER_STYLE_NONE = 0, + BORDER_STYLE_HIDDEN, + BORDER_STYLE_DOTTED, + BORDER_STYLE_DASHED, + BORDER_STYLE_SOLID, + BORDER_STYLE_DOUBLE, + BORDER_STYLE_GROOVE, + BORDER_STYLE_RIDGE, + BORDER_STYLE_INSET, + BORDER_STYLE_OUTSET, + BORDER_STYLE_INHERIT +} ; + +enum CRDisplayType +{ + DISPLAY_NONE, + DISPLAY_INLINE, + DISPLAY_BLOCK, + DISPLAY_LIST_ITEM, + DISPLAY_RUN_IN, + DISPLAY_COMPACT, + DISPLAY_MARKER, + DISPLAY_TABLE, + DISPLAY_INLINE_TABLE, + DISPLAY_TABLE_ROW_GROUP, + DISPLAY_TABLE_HEADER_GROUP, + DISPLAY_TABLE_FOOTER_GROUP, + DISPLAY_TABLE_ROW, + DISPLAY_TABLE_COLUMN_GROUP, + DISPLAY_TABLE_COLUMN, + DISPLAY_TABLE_CELL, + DISPLAY_TABLE_CAPTION, + DISPLAY_INHERIT +} ; + +enum CRPositionType +{ + POSITION_STATIC, + POSITION_RELATIVE, + POSITION_ABSOLUTE, + POSITION_FIXED, + POSITION_INHERIT +} ; + +enum CRFloatType +{ + FLOAT_NONE, + FLOAT_LEFT, + FLOAT_RIGHT, + FLOAT_INHERIT +} ; + +enum CRWhiteSpaceType +{ + WHITE_SPACE_NORMAL, + WHITE_SPACE_PRE, + WHITE_SPACE_NOWRAP, + WHITE_SPACE_INHERIT +} ; + + +#define BORDER_THIN 2 +#define BORDER_MEDIUM 4 +#define BORDER_THICK 6 + + +/** + *A numerical css property value. + *This data type is actually split in 3 parts: + *1/the specified value + *2/the computed value + *3/the actual value. + *To understand the semantic of these three parts, + *see css2 spec chap 6.1 ("Specified, computed and actual values."). + */ +typedef struct _CRNumPropVal CRNumPropVal ; +struct _CRNumPropVal +{ + /**specified value*/ + CRNum sv ; + /**computed value*/ + CRNum cv ; + /**actual value*/ + CRNum av ; +} ; + +/** + *An rgb css property value. + *This data type is actually split in 3 parts: + *1/the specified value + *2/the computed value + *3/the actual value. + *To understand the semantic of these three parts, + *see css2 spec chap 6.1 ("Specified, computed and actual values."). + */ +typedef struct _CRRgbPropVal CRRgbPropVal ; +struct _CRRgbPropVal +{ + /**specified value*/ + CRRgb sv ; + /**computed value*/ + CRRgb cv ; + /**actual value*/ + CRRgb av ; +} ; + + +enum CRNumProp +{ + NUM_PROP_TOP=0, + NUM_PROP_RIGHT, + NUM_PROP_BOTTOM, + NUM_PROP_LEFT,/*3*/ + + NUM_PROP_PADDING_TOP, + NUM_PROP_PADDING_RIGHT, + NUM_PROP_PADDING_BOTTOM, + NUM_PROP_PADDING_LEFT,/*7*/ + + NUM_PROP_BORDER_TOP, + NUM_PROP_BORDER_RIGHT, + NUM_PROP_BORDER_BOTTOM, + NUM_PROP_BORDER_LEFT,/*11*/ + + NUM_PROP_MARGIN_TOP, + NUM_PROP_MARGIN_RIGHT, + NUM_PROP_MARGIN_BOTTOM, + NUM_PROP_MARGIN_LEFT,/*15*/ + + NUM_PROP_WIDTH, + + /*must be last*/ + NB_NUM_PROPS +} ; + +enum CRRgbProp +{ + RGB_PROP_BORDER_TOP_COLOR = 0, + RGB_PROP_BORDER_RIGHT_COLOR, + RGB_PROP_BORDER_BOTTOM_COLOR, + RGB_PROP_BORDER_LEFT_COLOR, + RGB_PROP_COLOR, + RGB_PROP_BACKGROUND_COLOR, + + /*must be last*/ + NB_RGB_PROPS +} ; + + +enum CRBorderStyleProp +{ + BORDER_STYLE_PROP_TOP = 0, + BORDER_STYLE_PROP_RIGHT, + BORDER_STYLE_PROP_BOTTOM, + BORDER_STYLE_PROP_LEFT, + + /*must be last*/ + NB_BORDER_STYLE_PROPS +} ; + +enum CRBoxOffsetProp +{ + BOX_OFFSET_PROP_TOP = 0, + BOX_OFFSET_PROP_RIGHT, + BOX_OFFSET_PROP_BOTTOM, + BOX_OFFSET_PROP_LEFT, + + /*must be last*/ + NB_BOX_OFFSET_PROPS +} ; + +typedef struct _CRFontSizeVal CRFontSizeVal ; +struct _CRFontSizeVal { + /*specified value*/ + CRFontSize sv ; + /*computed value*/ + CRFontSize cv ; + /*actual value*/ + CRFontSize av ; +} ; + +/** + *The css2 style class. + *Contains computed and actual values + *inferred from the declarations found + *in the stylesheets. + *See css2 spec chapter 6. + */ +struct _CRStyle +{ + /** + *numerical properties. + *the properties are indexed by + *enum #CRNumProp. + */ + CRNumPropVal num_props[NB_NUM_PROPS] ; + + /** + *color properties. + *They are indexed by enum #CRRgbProp . + */ + CRRgbPropVal rgb_props[NB_RGB_PROPS] ; + + /** + *border style properties. + *They are indexed by enum #CRBorderStyleProp . + */ + enum CRBorderStyle border_style_props[NB_BORDER_STYLE_PROPS] ; + + /**box display type*/ + enum CRDisplayType display ; + + /**the positioning scheme*/ + enum CRPositionType position ; + + /**the float property*/ + enum CRFloatType float_type ; + + /* + *the 'font-family' property. + */ + CRFontFamily *font_family ; + + /** + *the 'font-size' property. + */ + CRFontSizeVal font_size ; + CRFontSizeAdjust *font_size_adjust ; + enum CRFontStyle font_style ; + enum CRFontVariant font_variant ; + enum CRFontWeight font_weight ; + enum CRFontStretch font_stretch ; + + /** + * the 'tex' properties + */ + enum CRWhiteSpaceType white_space; + + gboolean inherited_props_resolved ; + CRStyle *parent_style ; + gulong ref_count ; +} ; + +enum CRStatus cr_style_white_space_type_to_string (enum CRWhiteSpaceType a_code, + GString * a_str, guint a_nb_indent) ; + +enum CRStatus cr_style_num_prop_val_to_string (CRNumPropVal *a_prop_val, + GString *a_str, + guint a_nb_indent) ; + +enum CRStatus cr_style_rgb_prop_val_to_string (CRRgbPropVal *a_prop_val, + GString *a_str, + guint a_nb_indent) ; + +enum CRStatus cr_style_border_style_to_string (enum CRBorderStyle a_prop, + GString *a_str, + guint a_nb_indent) ; + +enum CRStatus cr_style_display_type_to_string (enum CRDisplayType a_code, + GString *a_str, + guint a_nb_indent) ; + +enum CRStatus cr_style_position_type_to_string (enum CRPositionType a_code, + GString *a_str, + guint a_nb_indent) ; + +enum CRStatus cr_style_float_type_to_string (enum CRFloatType a_code, + GString *a_str, + guint a_nb_indent) ; + +CRStyle * cr_style_new (gboolean a_set_props_to_initial_values) ; + +enum CRStatus cr_style_set_props_to_default_values (CRStyle *a_this) ; +enum CRStatus cr_style_set_props_to_initial_values (CRStyle *a_this) ; +enum CRStatus cr_style_resolve_inherited_properties (CRStyle *a_this) ; +enum CRStatus cr_style_propagate_from_parent (CRStyle *a_this); + +enum CRStatus cr_style_set_style_from_decl (CRStyle *a_this, + CRDeclaration *a_decl) ; + + +enum CRStatus cr_style_copy (CRStyle *a_dest, CRStyle *a_src) ; + +enum CRStatus cr_style_ref (CRStyle *a_this) ; + +gboolean cr_style_unref (CRStyle *a_this) ; + +void cr_style_destroy (CRStyle *a_this) ; + +CRStyle * cr_style_dup (CRStyle *a_this) ; + +enum CRStatus cr_style_to_string (CRStyle *a_this, + GString **a_str, + guint a_nb_indent) ; + +G_END_DECLS + +#endif /*__CR_STYLE_H__*/ diff --git a/gettext-tools/gnulib-lib/libcroco/cr-stylesheet.c b/gettext-tools/gnulib-lib/libcroco/cr-stylesheet.c new file mode 100644 index 0000000..3c93def --- /dev/null +++ b/gettext-tools/gnulib-lib/libcroco/cr-stylesheet.c @@ -0,0 +1,179 @@ +/* -*- Mode: C; indent-tabs-mode: ni; c-basic-offset: 8 -*- */ + +/* + * This file is part of The Croco Library + * + * Copyright (C) 2002-2004 Dodji Seketeli + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + +#include +#include "string.h" +#include "cr-stylesheet.h" + +/** + *@file + *The definition of the #CRStyleSheet class + */ + +/** + *Constructor of the #CRStyleSheet class. + *@param the initial list of css statements. + *@return the newly built css2 stylesheet, or NULL in case of error. + */ +CRStyleSheet * +cr_stylesheet_new (CRStatement * a_stmts) +{ + CRStyleSheet *result; + + result = g_try_malloc (sizeof (CRStyleSheet)); + if (!result) { + cr_utils_trace_info ("Out of memory"); + return NULL; + } + + memset (result, 0, sizeof (CRStyleSheet)); + + if (a_stmts) + result->statements = a_stmts; + + return result; +} + +/** + *@param a_this the current instance of #CRStyleSheet + *@return the serialized stylesheet. + */ +gchar * +cr_stylesheet_to_string (CRStyleSheet *a_this) +{ + gchar *str = NULL; + GString *stringue = NULL; + CRStatement *cur_stmt = NULL; + + g_return_val_if_fail (a_this, NULL); + + if (a_this->statements) { + stringue = g_string_new (NULL) ; + g_return_val_if_fail (stringue, NULL) ; + } + for (cur_stmt = a_this->statements; + cur_stmt; cur_stmt = cur_stmt->next) { + if (cur_stmt->prev) { + g_string_append (stringue, "\n\n") ; + } + str = cr_statement_to_string (cur_stmt, 0) ; + if (str) { + g_string_append (stringue, str) ; + g_free (str) ; + str = NULL ; + } + } + if (stringue) { + str = stringue->str ; + g_string_free (stringue, FALSE) ; + stringue = NULL ; + } + return str ; +} + +/** + *Dumps the current css2 stylesheet to a file. + *@param a_this the current instance of #CRStyleSheet. + *@param a_fp the destination file + */ +void +cr_stylesheet_dump (CRStyleSheet * a_this, FILE * a_fp) +{ + gchar *str = NULL ; + + g_return_if_fail (a_this); + + str = cr_stylesheet_to_string (a_this) ; + if (str) { + fprintf (a_fp, "%s", str) ; + g_free (str) ; + str = NULL ; + } +} + +/** + *Return the number of rules in the stylesheet. + *@param a_this the current instance of #CRStyleSheet. + *@return number of rules in the stylesheet. + */ +gint +cr_stylesheet_nr_rules (CRStyleSheet * a_this) +{ + g_return_val_if_fail (a_this, -1); + + return cr_statement_nr_rules (a_this->statements); +} + +/** + *Use an index to get a CRStatement from the rules in a given stylesheet. + *@param a_this the current instance of #CRStatement. + *@param itemnr the index into the rules. + *@return CRStatement at position itemnr, if itemnr > number of rules - 1, + *it will return NULL. + */ +CRStatement * +cr_stylesheet_statement_get_from_list (CRStyleSheet * a_this, int itemnr) +{ + g_return_val_if_fail (a_this, NULL); + + return cr_statement_get_from_list (a_this->statements, itemnr); +} + +void +cr_stylesheet_ref (CRStyleSheet * a_this) +{ + g_return_if_fail (a_this); + + a_this->ref_count++; +} + +gboolean +cr_stylesheet_unref (CRStyleSheet * a_this) +{ + g_return_val_if_fail (a_this, FALSE); + + if (a_this->ref_count) + a_this->ref_count--; + + if (!a_this->ref_count) { + cr_stylesheet_destroy (a_this); + return TRUE; + } + + return FALSE; +} + +/** + *Destructor of the #CRStyleSheet class. + *@param a_this the current instance of the #CRStyleSheet class. + */ +void +cr_stylesheet_destroy (CRStyleSheet * a_this) +{ + g_return_if_fail (a_this); + + if (a_this->statements) { + cr_statement_destroy (a_this->statements); + a_this->statements = NULL; + } + g_free (a_this); +} diff --git a/gettext-tools/gnulib-lib/libcroco/cr-stylesheet.h b/gettext-tools/gnulib-lib/libcroco/cr-stylesheet.h new file mode 100644 index 0000000..5991626 --- /dev/null +++ b/gettext-tools/gnulib-lib/libcroco/cr-stylesheet.h @@ -0,0 +1,102 @@ +/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8 -*- */ + +/* + * This file is part of The Croco Library + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + * see COPYRIGHTS file for copyright information. + */ + + +#ifndef __CR_STYLESHEET_H__ +#define __CR_STYLESHEET_H__ + +#include "cr-utils.h" +#include "cr-statement.h" + +G_BEGIN_DECLS + +/** + *@file + *The declaration of the #CRStyleSheet class. + */ + + +enum CRStyleOrigin +{ + /*Please don't change the order of + *the values enumerated here ... + *New values should be added at the end, + *just before ORIGIN_END. + */ + ORIGIN_UA = 0, + ORIGIN_USER, + ORIGIN_AUTHOR, + + /*must always be the last one*/ + NB_ORIGINS +} ; + +/** + *An abstraction of a css stylesheet as defined + *by the css2 spec in chapter 4. + */ +struct _CRStyleSheet +{ + /**The css statements list*/ + CRStatement *statements ; + + enum CRStyleOrigin origin ; + + /*the parent import rule, if any.*/ + CRStatement *parent_import_rule ; + + /**custom data used by libcroco*/ + gpointer croco_data ; + + /** + *custom application data pointer + *Can be used by applications. + */ + gpointer app_data ; + + /** + *the reference count of this insance + *Please, don't never ever modify it + *directly. Use cr_stylesheet_ref() + *and cr_stylesheet_unref() instead. + */ + gulong ref_count ; +} ; + +CRStyleSheet * cr_stylesheet_new (CRStatement *a_stmts) ; + +gchar * cr_stylesheet_to_string (CRStyleSheet *a_this) ; +void cr_stylesheet_dump (CRStyleSheet *a_this, FILE *a_fp) ; + +gint cr_stylesheet_nr_rules (CRStyleSheet *a_this) ; + +CRStatement * cr_stylesheet_statement_get_from_list (CRStyleSheet *a_this, int itemnr) ; + +void cr_stylesheet_ref (CRStyleSheet *a_this) ; + +gboolean cr_stylesheet_unref (CRStyleSheet *a_this) ; + +void cr_stylesheet_destroy (CRStyleSheet *a_this) ; + +G_END_DECLS + +#endif /*__CR_STYLESHEET_H__*/ diff --git a/gettext-tools/gnulib-lib/libcroco/cr-term.c b/gettext-tools/gnulib-lib/libcroco/cr-term.c new file mode 100644 index 0000000..037b0da --- /dev/null +++ b/gettext-tools/gnulib-lib/libcroco/cr-term.c @@ -0,0 +1,792 @@ +/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */ + +/* + * This file is part of The Croco Library + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + * Author: Dodji Seketeli + * See COPYRIGHTS file for copyright information. + */ + +#include +#include +#include +#include "cr-term.h" +#include "cr-num.h" +#include "cr-parser.h" + +/** + *@file + *Definition of the #CRTem class. + */ + +static void +cr_term_clear (CRTerm * a_this) +{ + g_return_if_fail (a_this); + + switch (a_this->type) { + case TERM_NUMBER: + if (a_this->content.num) { + cr_num_destroy (a_this->content.num); + a_this->content.num = NULL; + } + break; + + case TERM_FUNCTION: + if (a_this->ext_content.func_param) { + cr_term_destroy (a_this->ext_content.func_param); + a_this->ext_content.func_param = NULL; + } + case TERM_STRING: + case TERM_IDENT: + case TERM_URI: + case TERM_HASH: + if (a_this->content.str) { + cr_string_destroy (a_this->content.str); + a_this->content.str = NULL; + } + break; + + case TERM_RGB: + if (a_this->content.rgb) { + cr_rgb_destroy (a_this->content.rgb); + a_this->content.rgb = NULL; + } + break; + + case TERM_UNICODERANGE: + case TERM_NO_TYPE: + default: + break; + } + + a_this->type = TERM_NO_TYPE; +} + +/** + *Instanciate a #CRTerm. + *@return the newly build instance + *of #CRTerm. + */ +CRTerm * +cr_term_new (void) +{ + CRTerm *result = NULL; + + result = g_try_malloc (sizeof (CRTerm)); + if (!result) { + cr_utils_trace_info ("Out of memory"); + return NULL; + } + memset (result, 0, sizeof (CRTerm)); + return result; +} + +/** + *Parses an expresion as defined by the css2 spec + *and builds the expression as a list of terms. + *@param a_buf the buffer to parse. + *@return a pointer to the first term of the expression or + *NULL if parsing failed. + */ +CRTerm * +cr_term_parse_expression_from_buf (const guchar * a_buf, + enum CREncoding a_encoding) +{ + CRParser *parser = NULL; + CRTerm *result = NULL; + enum CRStatus status = CR_OK; + + g_return_val_if_fail (a_buf, NULL); + + parser = cr_parser_new_from_buf ((guchar*)a_buf, strlen (a_buf), + a_encoding, FALSE); + g_return_val_if_fail (parser, NULL); + + status = cr_parser_try_to_skip_spaces_and_comments (parser); + if (status != CR_OK) { + goto cleanup; + } + status = cr_parser_parse_expr (parser, &result); + if (status != CR_OK) { + if (result) { + cr_term_destroy (result); + result = NULL; + } + } + + cleanup: + if (parser) { + cr_parser_destroy (parser); + parser = NULL; + } + + return result; +} + +enum CRStatus +cr_term_set_number (CRTerm * a_this, CRNum * a_num) +{ + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); + + cr_term_clear (a_this); + + a_this->type = TERM_NUMBER; + a_this->content.num = a_num; + return CR_OK; +} + +enum CRStatus +cr_term_set_function (CRTerm * a_this, CRString * a_func_name, + CRTerm * a_func_param) +{ + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); + + cr_term_clear (a_this); + + a_this->type = TERM_FUNCTION; + a_this->content.str = a_func_name; + a_this->ext_content.func_param = a_func_param; + return CR_OK; +} + +enum CRStatus +cr_term_set_string (CRTerm * a_this, CRString * a_str) +{ + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); + + cr_term_clear (a_this); + + a_this->type = TERM_STRING; + a_this->content.str = a_str; + return CR_OK; +} + +enum CRStatus +cr_term_set_ident (CRTerm * a_this, CRString * a_str) +{ + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); + + cr_term_clear (a_this); + + a_this->type = TERM_IDENT; + a_this->content.str = a_str; + return CR_OK; +} + +enum CRStatus +cr_term_set_uri (CRTerm * a_this, CRString * a_str) +{ + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); + + cr_term_clear (a_this); + + a_this->type = TERM_URI; + a_this->content.str = a_str; + return CR_OK; +} + +enum CRStatus +cr_term_set_rgb (CRTerm * a_this, CRRgb * a_rgb) +{ + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); + + cr_term_clear (a_this); + + a_this->type = TERM_RGB; + a_this->content.rgb = a_rgb; + return CR_OK; +} + +enum CRStatus +cr_term_set_hash (CRTerm * a_this, CRString * a_str) +{ + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); + + cr_term_clear (a_this); + + a_this->type = TERM_HASH; + a_this->content.str = a_str; + return CR_OK; +} + +/** + *Appends a new term to the current list of #CRTerm. + * + *@param a_this the "this pointer" of the current instance + *of #CRTerm . + *@param a_new_term the term to append. + *@return the list of terms with the a_new_term appended to it. + */ +CRTerm * +cr_term_append_term (CRTerm * a_this, CRTerm * a_new_term) +{ + CRTerm *cur = NULL; + + g_return_val_if_fail (a_new_term, NULL); + + if (a_this == NULL) + return a_new_term; + + for (cur = a_this; cur->next; cur = cur->next) ; + + cur->next = a_new_term; + a_new_term->prev = cur; + + return a_this; +} + +/** + *Prepends a term to the list of terms represented by a_this. + * + *@param a_this the "this pointer" of the current instance of + *#CRTerm . + *@param a_new_term the term to prepend. + *@return the head of the new list. + */ +CRTerm * +cr_term_prepend_term (CRTerm * a_this, CRTerm * a_new_term) +{ + g_return_val_if_fail (a_this && a_new_term, NULL); + + a_new_term->next = a_this; + a_this->prev = a_new_term; + + return a_new_term; +} + +/** + *Serializes the expression represented by + *the chained instances of #CRterm. + *@param a_this the current instance of #CRTerm + *@return the zero terminated string containing the serialized + *form of #CRTerm. MUST BE FREED BY THE CALLER using g_free(). + */ +guchar * +cr_term_to_string (CRTerm * a_this) +{ + GString *str_buf = NULL; + CRTerm *cur = NULL; + guchar *result = NULL, + *content = NULL; + + g_return_val_if_fail (a_this, NULL); + + str_buf = g_string_new (NULL); + g_return_val_if_fail (str_buf, NULL); + + for (cur = a_this; cur; cur = cur->next) { + if ((cur->content.str == NULL) + && (cur->content.num == NULL) + && (cur->content.str == NULL) + && (cur->content.rgb == NULL)) + continue; + + switch (cur->the_operator) { + case DIVIDE: + g_string_append (str_buf, " / "); + break; + + case COMMA: + g_string_append (str_buf, ", "); + break; + + case NO_OP: + if (cur->prev) { + g_string_append (str_buf, " "); + } + break; + default: + + break; + } + + switch (cur->unary_op) { + case PLUS_UOP: + g_string_append (str_buf, "+"); + break; + + case MINUS_UOP: + g_string_append (str_buf, "-"); + break; + + default: + break; + } + + switch (cur->type) { + case TERM_NUMBER: + if (cur->content.num) { + content = cr_num_to_string (cur->content.num); + } + + if (content) { + g_string_append (str_buf, content); + g_free (content); + content = NULL; + } + + break; + + case TERM_FUNCTION: + if (cur->content.str) { + content = g_strndup + (cur->content.str->stryng->str, + cur->content.str->stryng->len); + } + + if (content) { + g_string_append_printf (str_buf, "%s(", + content); + + if (cur->ext_content.func_param) { + guchar *tmp_str = NULL; + + tmp_str = cr_term_to_string + (cur-> + ext_content.func_param); + + if (tmp_str) { + g_string_append (str_buf, + tmp_str); + g_free (tmp_str); + tmp_str = NULL; + } + + g_free (content); + content = NULL; + } + g_string_append (str_buf, ")"); + } + + break; + + case TERM_STRING: + if (cur->content.str) { + content = g_strndup + (cur->content.str->stryng->str, + cur->content.str->stryng->len); + } + + if (content) { + g_string_append_printf (str_buf, + "\"%s\"", content); + g_free (content); + content = NULL; + } + break; + + case TERM_IDENT: + if (cur->content.str) { + content = g_strndup + (cur->content.str->stryng->str, + cur->content.str->stryng->len); + } + + if (content) { + g_string_append (str_buf, content); + g_free (content); + content = NULL; + } + break; + + case TERM_URI: + if (cur->content.str) { + content = g_strndup + (cur->content.str->stryng->str, + cur->content.str->stryng->len); + } + + if (content) { + g_string_append_printf + (str_buf, "url(%s)", content); + g_free (content); + content = NULL; + } + break; + + case TERM_RGB: + if (cur->content.rgb) { + guchar *tmp_str = NULL; + + g_string_append (str_buf, "rgb("); + tmp_str = cr_rgb_to_string (cur->content.rgb); + + if (tmp_str) { + g_string_append (str_buf, tmp_str); + g_free (tmp_str); + tmp_str = NULL; + } + g_string_append (str_buf, ")"); + } + + break; + + case TERM_UNICODERANGE: + g_string_append + (str_buf, + "?found unicoderange: dump not supported yet?"); + break; + + case TERM_HASH: + if (cur->content.str) { + content = g_strndup + (cur->content.str->stryng->str, + cur->content.str->stryng->len); + } + + if (content) { + g_string_append_printf (str_buf, + "#%s", content); + g_free (content); + content = NULL; + } + break; + + default: + g_string_append (str_buf, + "Unrecognized Term type"); + break; + } + } + + if (str_buf) { + result = str_buf->str; + g_string_free (str_buf, FALSE); + str_buf = NULL; + } + + return result; +} + +guchar * +cr_term_one_to_string (CRTerm * a_this) +{ + GString *str_buf = NULL; + guchar *result = NULL, + *content = NULL; + + g_return_val_if_fail (a_this, NULL); + + str_buf = g_string_new (NULL); + g_return_val_if_fail (str_buf, NULL); + + if ((a_this->content.str == NULL) + && (a_this->content.num == NULL) + && (a_this->content.str == NULL) + && (a_this->content.rgb == NULL)) + return NULL ; + + switch (a_this->the_operator) { + case DIVIDE: + g_string_append_printf (str_buf, " / "); + break; + + case COMMA: + g_string_append_printf (str_buf, ", "); + break; + + case NO_OP: + if (a_this->prev) { + g_string_append_printf (str_buf, " "); + } + break; + default: + + break; + } + + switch (a_this->unary_op) { + case PLUS_UOP: + g_string_append_printf (str_buf, "+"); + break; + + case MINUS_UOP: + g_string_append_printf (str_buf, "-"); + break; + + default: + break; + } + + switch (a_this->type) { + case TERM_NUMBER: + if (a_this->content.num) { + content = cr_num_to_string (a_this->content.num); + } + + if (content) { + g_string_append (str_buf, content); + g_free (content); + content = NULL; + } + + break; + + case TERM_FUNCTION: + if (a_this->content.str) { + content = g_strndup + (a_this->content.str->stryng->str, + a_this->content.str->stryng->len); + } + + if (content) { + g_string_append_printf (str_buf, "%s(", + content); + + if (a_this->ext_content.func_param) { + guchar *tmp_str = NULL; + + tmp_str = cr_term_to_string + (a_this-> + ext_content.func_param); + + if (tmp_str) { + g_string_append_printf + (str_buf, + "%s", tmp_str); + g_free (tmp_str); + tmp_str = NULL; + } + + g_string_append_printf (str_buf, ")"); + g_free (content); + content = NULL; + } + } + + break; + + case TERM_STRING: + if (a_this->content.str) { + content = g_strndup + (a_this->content.str->stryng->str, + a_this->content.str->stryng->len); + } + + if (content) { + g_string_append_printf (str_buf, + "\"%s\"", content); + g_free (content); + content = NULL; + } + break; + + case TERM_IDENT: + if (a_this->content.str) { + content = g_strndup + (a_this->content.str->stryng->str, + a_this->content.str->stryng->len); + } + + if (content) { + g_string_append (str_buf, content); + g_free (content); + content = NULL; + } + break; + + case TERM_URI: + if (a_this->content.str) { + content = g_strndup + (a_this->content.str->stryng->str, + a_this->content.str->stryng->len); + } + + if (content) { + g_string_append_printf + (str_buf, "url(%s)", content); + g_free (content); + content = NULL; + } + break; + + case TERM_RGB: + if (a_this->content.rgb) { + guchar *tmp_str = NULL; + + g_string_append_printf (str_buf, "rgb("); + tmp_str = cr_rgb_to_string (a_this->content.rgb); + + if (tmp_str) { + g_string_append (str_buf, tmp_str); + g_free (tmp_str); + tmp_str = NULL; + } + g_string_append_printf (str_buf, ")"); + } + + break; + + case TERM_UNICODERANGE: + g_string_append_printf + (str_buf, + "?found unicoderange: dump not supported yet?"); + break; + + case TERM_HASH: + if (a_this->content.str) { + content = g_strndup + (a_this->content.str->stryng->str, + a_this->content.str->stryng->len); + } + + if (content) { + g_string_append_printf (str_buf, + "#%s", content); + g_free (content); + content = NULL; + } + break; + + default: + g_string_append_printf (str_buf, + "%s", + "Unrecognized Term type"); + break; + } + + if (str_buf) { + result = str_buf->str; + g_string_free (str_buf, FALSE); + str_buf = NULL; + } + + return result; +} + +/** + *Dumps the expression (a list of terms connected by operators) + *to a file. + *TODO: finish the dump. The dump of some type of terms have not yet been + *implemented. + *@param a_this the current instance of #CRTerm. + *@param a_fp the destination file pointer. + */ +void +cr_term_dump (CRTerm * a_this, FILE * a_fp) +{ + guchar *content = NULL; + + g_return_if_fail (a_this); + + content = cr_term_to_string (a_this); + + if (content) { + fprintf (a_fp, "%s", content); + g_free (content); + } +} + +/** + *Return the number of terms in the expression. + *@param a_this the current instance of #CRTerm. + *@return number of terms in the expression. + */ +int +cr_term_nr_values (CRTerm *a_this) +{ + CRTerm *cur = NULL ; + int nr = 0; + + g_return_val_if_fail (a_this, -1) ; + + for (cur = a_this ; cur ; cur = cur->next) + nr ++; + return nr; +} + +/** + *Use an index to get a CRTerm from the expression. + *@param a_this the current instance of #CRTerm. + *@param itemnr the index into the expression. + *@return CRTerm at position itemnr, if itemnr > number of terms - 1, + *it will return NULL. + */ +CRTerm * +cr_term_get_from_list (CRTerm *a_this, int itemnr) +{ + CRTerm *cur = NULL ; + int nr = 0; + + g_return_val_if_fail (a_this, NULL) ; + + for (cur = a_this ; cur ; cur = cur->next) + if (nr++ == itemnr) + return cur; + return NULL; +} + +/** + *Increments the reference counter of the current instance + *of #CRTerm.* + *@param a_this the current instance of #CRTerm. + */ +void +cr_term_ref (CRTerm * a_this) +{ + g_return_if_fail (a_this); + + a_this->ref_count++; +} + +/** + *Decrements the ref count of the current instance of + *#CRTerm. If the ref count reaches zero, the instance is + *destroyed. + *@param a_this the current instance of #CRTerm. + *@return TRUE if the current instance has been destroyed, FALSE otherwise. + */ +gboolean +cr_term_unref (CRTerm * a_this) +{ + g_return_val_if_fail (a_this, FALSE); + + if (a_this->ref_count) { + a_this->ref_count--; + } + + if (a_this->ref_count == 0) { + cr_term_destroy (a_this); + return TRUE; + } + + return FALSE; +} + +/** + *The destructor of the the #CRTerm class. + *@param a_this the "this pointer" of the current instance + *of #CRTerm. + */ +void +cr_term_destroy (CRTerm * a_this) +{ + g_return_if_fail (a_this); + + cr_term_clear (a_this); + + if (a_this->next) { + cr_term_destroy (a_this->next); + a_this->next = NULL; + } + + if (a_this) { + g_free (a_this); + } + +} diff --git a/gettext-tools/gnulib-lib/libcroco/cr-term.h b/gettext-tools/gnulib-lib/libcroco/cr-term.h new file mode 100644 index 0000000..3880e30 --- /dev/null +++ b/gettext-tools/gnulib-lib/libcroco/cr-term.h @@ -0,0 +1,190 @@ +/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */ + +/* + * This file is part of The Croco Library + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + * Author: Dodji Seketeli + * See COPYRIGHTS file for copyright information. + */ + +#include +#include +#include "cr-utils.h" +#include "cr-rgb.h" +#include "cr-num.h" +#include "cr-string.h" + +#ifndef __CR_TERM_H__ +#define __CR_TERM_H__ + +G_BEGIN_DECLS + +/** + *@file + *Declaration of the #CRTem class. + */ + +enum CRTermType +{ + TERM_NO_TYPE = 0, + TERM_NUMBER, + TERM_FUNCTION, + TERM_STRING, + TERM_IDENT, + TERM_URI, + TERM_RGB, + TERM_UNICODERANGE, + TERM_HASH +} ; + + +enum UnaryOperator +{ + NO_UNARY_UOP = 0, + PLUS_UOP, + MINUS_UOP, + EMPTY_UNARY_UOP +} ; + +enum Operator +{ + NO_OP = 0, + DIVIDE, + COMMA +} ; + +struct _CRTerm ; +typedef struct _CRTerm CRTerm ; + +/** + *An abstraction of a css2 term as + *defined in the CSS2 spec in appendix D.1: + *term ::= + *[ NUMBER S* | PERCENTAGE S* | LENGTH S* | EMS S* | EXS S* + *| ANGLE S* | TIME S* | FREQ S* | function ] + * | STRING S* | IDENT S* | URI S* | RGB S* + *| UNICODERANGE S* | hexcolor + */ +struct _CRTerm +{ + /** + *The type of the term. + */ + enum CRTermType type ; + + /** + *The unary operator associated to + *the current term. + */ + enum UnaryOperator unary_op ; + + /** + *The operator associated to the current term. + */ + enum Operator the_operator ; + + + /** + *The content of the term. + *Depending of the type of the term, + *this holds either a number, a percentage ... + */ + union + { + CRNum *num ; + CRString * str ; + CRRgb * rgb ; + } content ; + + /** + *If the term is of type UNICODERANGE, + *this field holds the upper bound of the range. + *if the term is of type FUNCTION, this holds + *an instance of CRTerm that represents + * the expression which is the argument of the function. + */ + union + { + CRTerm *func_param ; + } ext_content ; + + /** + *A spare pointer, just in case. + *Can be used by the application. + */ + gpointer app_data ; + + glong ref_count ; + + /** + *A pointer to the next term, + *just in case this term is part of + *an expression. + */ + CRTerm *next ; + + /** + *A pointer to the previous + *term. + */ + CRTerm *prev ; + CRParsingLocation location ; +} ; + +CRTerm * cr_term_parse_expression_from_buf (const guchar *a_buf, + enum CREncoding a_encoding) ; +CRTerm * cr_term_new (void) ; + +enum CRStatus cr_term_set_number (CRTerm *a_this, CRNum *a_num) ; + +enum CRStatus cr_term_set_function (CRTerm *a_this, + CRString *a_func_name, + CRTerm *a_func_param) ; + +enum CRStatus cr_term_set_string (CRTerm *a_this, CRString *a_str) ; + +enum CRStatus cr_term_set_ident (CRTerm *a_this, CRString *a_str) ; + +enum CRStatus cr_term_set_uri (CRTerm *a_this, CRString *a_str) ; + +enum CRStatus cr_term_set_rgb (CRTerm *a_this, CRRgb *a_rgb) ; + +enum CRStatus cr_term_set_hash (CRTerm *a_this, CRString *a_str) ; + +CRTerm * cr_term_append_term (CRTerm *a_this, CRTerm *a_new_term) ; + +CRTerm * cr_term_prepend_term (CRTerm *a_this, CRTerm *a_new_term) ; + +guchar * cr_term_to_string (CRTerm *a_this) ; + +guchar * cr_term_one_to_string (CRTerm * a_this) ; + +void cr_term_dump (CRTerm *a_this, FILE *a_fp) ; + +int cr_term_nr_values (CRTerm *a_this) ; + +CRTerm * cr_term_get_from_list (CRTerm *a_this, int itemnr) ; + +void cr_term_ref (CRTerm *a_this) ; + +gboolean cr_term_unref (CRTerm *a_this) ; + +void cr_term_destroy (CRTerm * a_term) ; + +G_END_DECLS + +#endif /*__CR_TERM_H__*/ diff --git a/gettext-tools/gnulib-lib/libcroco/cr-tknzr.c b/gettext-tools/gnulib-lib/libcroco/cr-tknzr.c new file mode 100644 index 0000000..2f342bd --- /dev/null +++ b/gettext-tools/gnulib-lib/libcroco/cr-tknzr.c @@ -0,0 +1,2764 @@ +/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */ + +/* + * This file is part of The Croco Library + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + * Author: Dodji Seketeli + * See the COPYRIGHTS file for copyrights information. + */ + +/** + *@file + *The definition of the #CRTknzr (tokenizer) + *class. + */ + +#include +#include "string.h" +#include "cr-tknzr.h" +#include "cr-doc-handler.h" + +struct _CRTknzrPriv { + /**The parser input stream of bytes*/ + CRInput *input; + + /** + *A cache where tknzr_unget_token() + *puts back the token. tknzr_get_next_token() + *first look in this cache, and if and + *only if it's empty, fetches the next token + *from the input stream. + */ + CRToken *token_cache; + + /** + *The position of the end of the previous token + *or char fetched. + */ + CRInputPos prev_pos; + + CRDocHandler *sac_handler; + + /** + *The reference count of the current instance + *of #CRTknzr. Is manipulated by cr_tknzr_ref() + *and cr_tknzr_unref(). + */ + glong ref_count; +}; + +#define PRIVATE(obj) ((obj)->priv) + +/** + *return TRUE if the character is a number ([0-9]), FALSE otherwise + *@param a_char the char to test. + */ +#define IS_NUM(a_char) (((a_char) >= '0' && (a_char) <= '9')?TRUE:FALSE) + +/** + *Checks if 'status' equals CR_OK. If not, goto the 'error' label. + * + *@param status the status (of type enum CRStatus) to test. + *@param is_exception if set to FALSE, the final status returned the + *current function will be CR_PARSING_ERROR. If set to TRUE, the + *current status will be the current value of the 'status' variable. + * + */ +#define CHECK_PARSING_STATUS(status, is_exception) \ +if ((status) != CR_OK) \ +{ \ + if (is_exception == FALSE) \ + { \ + status = CR_PARSING_ERROR ; \ + } \ + goto error ; \ +} + +/** + *Peeks the next char from the input stream of the current tokenizer. + *invokes CHECK_PARSING_STATUS on the status returned by + *cr_tknzr_input_peek_char(). + * + *@param the current instance of #CRTkzr. + *@param to_char a pointer to the char where to store the + *char peeked. + */ +#define PEEK_NEXT_CHAR(a_tknzr, a_to_char) \ +{\ +status = cr_tknzr_peek_char (a_tknzr, a_to_char) ; \ +CHECK_PARSING_STATUS (status, TRUE) \ +} + +/** + *Reads the next char from the input stream of the current parser. + *In case of error, jumps to the "error:" label located in the + *function where this macro is called. + *@param parser the curent instance of #CRTknzr + *@param to_char a pointer to the guint32 char where to store + *the character read. + */ +#define READ_NEXT_CHAR(a_tknzr, to_char) \ +status = cr_tknzr_read_char (a_tknzr, to_char) ;\ +CHECK_PARSING_STATUS (status, TRUE) + +/** + *Gets information about the current position in + *the input of the parser. + *In case of failure, this macro returns from the + *calling function and + *returns a status code of type enum #CRStatus. + *@param parser the current instance of #CRTknzr. + *@param pos out parameter. A pointer to the position + *inside the current parser input. Must + */ +#define RECORD_INITIAL_POS(a_tknzr, a_pos) \ +status = cr_input_get_cur_pos (PRIVATE \ +(a_tknzr)->input, a_pos) ; \ +g_return_val_if_fail (status == CR_OK, status) + +/** + *Gets the address of the current byte inside the + *parser input. + *@param parser the current instance of #CRTknzr. + *@param addr out parameter a pointer (guchar*) + *to where the address must be put. + */ +#define RECORD_CUR_BYTE_ADDR(a_tknzr, a_addr) \ +status = cr_input_get_cur_byte_addr \ + (PRIVATE (a_tknzr)->input, a_addr) ; \ +CHECK_PARSING_STATUS (status, TRUE) + +/** + *Peeks a byte from the topmost parser input at + *a given offset from the current position. + *If it fails, goto the "error:" label. + * + *@param a_parser the current instance of #CRTknzr. + *@param a_offset the offset of the byte to peek, the + *current byte having the offset '0'. + *@param a_byte_ptr out parameter a pointer (guchar*) to + *where the peeked char is to be stored. + */ +#define PEEK_BYTE(a_tknzr, a_offset, a_byte_ptr) \ +status = cr_tknzr_peek_byte (a_tknzr, \ + a_offset, \ + a_byte_ptr) ; \ +CHECK_PARSING_STATUS (status, TRUE) ; + +#define BYTE(a_input, a_n, a_eof) \ +cr_input_peek_byte2 (a_input, a_n, a_eof) + +/** + *Reads a byte from the topmost parser input + *steam. + *If it fails, goto the "error" label. + *@param a_parser the current instance of #CRTknzr. + *@param a_byte_ptr the guchar * where to put the read char. + */ +#define READ_NEXT_BYTE(a_tknzr, a_byte_ptr) \ +status = \ +cr_input_read_byte (PRIVATE (a_tknzr)->input, a_byte_ptr) ;\ +CHECK_PARSING_STATUS (status, TRUE) ; + +/** + *Skips a given number of byte in the topmost + *parser input. Don't update line and column number. + *In case of error, jumps to the "error:" label + *of the surrounding function. + *@param a_parser the current instance of #CRTknzr. + *@param a_nb_bytes the number of bytes to skip. + */ +#define SKIP_BYTES(a_tknzr, a_nb_bytes) \ +status = cr_input_seek_index (PRIVATE (a_tknzr)->input, \ + CR_SEEK_CUR, a_nb_bytes) ; \ +CHECK_PARSING_STATUS (status, TRUE) ; + +/** + *Skip utf8 encoded characters. + *Updates line and column numbers. + *@param a_parser the current instance of #CRTknzr. + *@param a_nb_chars the number of chars to skip. Must be of + *type glong. + */ +#define SKIP_CHARS(a_tknzr, a_nb_chars) \ +{ \ +glong nb_chars = a_nb_chars ; \ +status = cr_input_consume_chars \ + (PRIVATE (a_tknzr)->input,0, &nb_chars) ; \ +CHECK_PARSING_STATUS (status, TRUE) ; \ +} + +/** + *Tests the condition and if it is false, sets + *status to "CR_PARSING_ERROR" and goto the 'error' + *label. + *@param condition the condition to test. + */ +#define ENSURE_PARSING_COND(condition) \ +if (! (condition)) {status = CR_PARSING_ERROR; goto error ;} + +static enum CRStatus cr_tknzr_parse_nl (CRTknzr * a_this, + guchar ** a_start, + guchar ** a_end, + CRParsingLocation *a_location); + +static enum CRStatus cr_tknzr_parse_w (CRTknzr * a_this, + guchar ** a_start, + guchar ** a_end, + CRParsingLocation *a_location) ; + +static enum CRStatus cr_tknzr_parse_unicode_escape (CRTknzr * a_this, + guint32 * a_unicode, + CRParsingLocation *a_location) ; + +static enum CRStatus cr_tknzr_parse_escape (CRTknzr * a_this, + guint32 * a_esc_code, + CRParsingLocation *a_location); + +static enum CRStatus cr_tknzr_parse_string (CRTknzr * a_this, + CRString ** a_str); + +static enum CRStatus cr_tknzr_parse_comment (CRTknzr * a_this, + CRString ** a_comment); + +static enum CRStatus cr_tknzr_parse_nmstart (CRTknzr * a_this, + guint32 * a_char, + CRParsingLocation *a_location); + +static enum CRStatus cr_tknzr_parse_num (CRTknzr * a_this, + CRNum ** a_num); + +/********************************** + *PRIVATE methods + **********************************/ + +/** + *Parses a "w" as defined by the css spec at [4.1.1]: + * w ::= [ \t\r\n\f]* + * + *@param a_this the current instance of #CRTknzr. + *@param a_start out param. Upon successfull completion, points + *to the beginning of the parsed white space, points to NULL otherwise. + *Can also point to NULL is there is no white space actually. + *@param a_end out param. Upon successfull completion, points + *to the end of the parsed white space, points to NULL otherwise. + *Can also point to NULL is there is no white space actually. + */ +static enum CRStatus +cr_tknzr_parse_w (CRTknzr * a_this, + guchar ** a_start, + guchar ** a_end, + CRParsingLocation *a_location) +{ + guint32 cur_char = 0; + CRInputPos init_pos; + enum CRStatus status = CR_OK; + + g_return_val_if_fail (a_this && PRIVATE (a_this) + && PRIVATE (a_this)->input + && a_start && a_end, + CR_BAD_PARAM_ERROR); + + RECORD_INITIAL_POS (a_this, &init_pos); + + *a_start = NULL; + *a_end = NULL; + + READ_NEXT_CHAR (a_this, &cur_char); + + if (cr_utils_is_white_space (cur_char) == FALSE) { + status = CR_PARSING_ERROR; + goto error; + } + if (a_location) { + cr_tknzr_get_parsing_location (a_this, + a_location) ; + } + RECORD_CUR_BYTE_ADDR (a_this, a_start); + *a_end = *a_start; + + for (;;) { + gboolean is_eof = FALSE; + + cr_input_get_end_of_file (PRIVATE (a_this)->input, &is_eof); + if (is_eof) + break; + + status = cr_tknzr_peek_char (a_this, &cur_char); + if (status == CR_END_OF_INPUT_ERROR) { + status = CR_OK; + break; + } else if (status != CR_OK) { + goto error; + } + + if (cr_utils_is_white_space (cur_char) == TRUE) { + READ_NEXT_CHAR (a_this, &cur_char); + RECORD_CUR_BYTE_ADDR (a_this, a_end); + } else { + break; + } + } + + return CR_OK; + + error: + cr_tknzr_set_cur_pos (a_this, &init_pos); + + return status; +} + +/** + *Parses a newline as defined in the css2 spec: + * nl ::= \n|\r\n|\r|\f + * + *@param a_this the "this pointer" of the current instance of #CRTknzr. + *@param a_start a pointer to the first character of the successfully + *parsed string. + *@param a_end a pointer to the last character of the successfully parsed + *string. + *@result CR_OK uppon successfull completion, an error code otherwise. + */ +static enum CRStatus +cr_tknzr_parse_nl (CRTknzr * a_this, + guchar ** a_start, + guchar ** a_end, + CRParsingLocation *a_location) +{ + CRInputPos init_pos; + guchar next_chars[2] = { 0 }; + enum CRStatus status = CR_PARSING_ERROR; + + g_return_val_if_fail (a_this && PRIVATE (a_this) + && a_start && a_end, CR_BAD_PARAM_ERROR); + + RECORD_INITIAL_POS (a_this, &init_pos); + + PEEK_BYTE (a_this, 1, &next_chars[0]); + PEEK_BYTE (a_this, 2, &next_chars[1]); + + if ((next_chars[0] == '\r' && next_chars[1] == '\n')) { + SKIP_BYTES (a_this, 1); + if (a_location) { + cr_tknzr_get_parsing_location + (a_this, a_location) ; + } + SKIP_CHARS (a_this, 1); + + RECORD_CUR_BYTE_ADDR (a_this, a_end); + + status = CR_OK; + } else if (next_chars[0] == '\n' + || next_chars[0] == '\r' || next_chars[0] == '\f') { + SKIP_CHARS (a_this, 1); + if (a_location) { + cr_tknzr_get_parsing_location + (a_this, a_location) ; + } + RECORD_CUR_BYTE_ADDR (a_this, a_start); + *a_end = *a_start; + status = CR_OK; + } else { + status = CR_PARSING_ERROR; + goto error; + } + return CR_OK ; + + error: + cr_tknzr_set_cur_pos (a_this, &init_pos) ; + return status; +} + +/** + *Go ahead in the parser input, skipping all the spaces. + *If the next char if not a white space, this function does nothing. + *In any cases, it stops when it encounters a non white space character. + * + *@param a_this the current instance of #CRTknzr. + *@return CR_OK upon successfull completion, an error code otherwise. + */ +static enum CRStatus +cr_tknzr_try_to_skip_spaces (CRTknzr * a_this) +{ + enum CRStatus status = CR_ERROR; + guint32 cur_char = 0; + + g_return_val_if_fail (a_this && PRIVATE (a_this) + && PRIVATE (a_this)->input, CR_BAD_PARAM_ERROR); + + status = cr_input_peek_char (PRIVATE (a_this)->input, &cur_char); + + if (status != CR_OK) { + if (status == CR_END_OF_INPUT_ERROR) + return CR_OK; + return status; + } + + if (cr_utils_is_white_space (cur_char) == TRUE) { + glong nb_chars = -1; /*consume all spaces */ + + status = cr_input_consume_white_spaces + (PRIVATE (a_this)->input, &nb_chars); + } + + return status; +} + +/** + *Parses a "comment" as defined in the css spec at [4.1.1]: + *COMMENT ::= \/\*[^*]*\*+([^/][^*]*\*+)*\/ . + *This complex regexp is just to say that comments start + *with the two chars '/''*' and ends with the two chars '*''/'. + *It also means that comments cannot be nested. + *So based on that, I've just tried to implement the parsing function + *simply and in a straight forward manner. + */ +static enum CRStatus +cr_tknzr_parse_comment (CRTknzr * a_this, + CRString ** a_comment) +{ + enum CRStatus status = CR_OK; + CRInputPos init_pos; + guint32 cur_char = 0, next_char= 0; + CRString *comment = NULL; + CRParsingLocation loc = {0} ; + + g_return_val_if_fail (a_this && PRIVATE (a_this) + && PRIVATE (a_this)->input, + CR_BAD_PARAM_ERROR); + + RECORD_INITIAL_POS (a_this, &init_pos); + READ_NEXT_CHAR (a_this, &cur_char) ; + ENSURE_PARSING_COND (cur_char == '/'); + cr_tknzr_get_parsing_location (a_this, &loc) ; + + READ_NEXT_CHAR (a_this, &cur_char); + ENSURE_PARSING_COND (cur_char == '*'); + comment = cr_string_new (); + for (;;) { + READ_NEXT_CHAR (a_this, &cur_char); + + /*make sure there are no nested comments */ + if (cur_char == '/') { + READ_NEXT_CHAR (a_this, &cur_char); + ENSURE_PARSING_COND (cur_char != '*'); + g_string_append_c (comment->stryng, '/'); + g_string_append_unichar (comment->stryng, + cur_char); + continue; + } + + /*Detect the end of the comments region */ + if (cur_char == '*') { + PEEK_NEXT_CHAR (a_this, &next_char); + + if (next_char == '/') { + /* + *end of comments region + *Now, call the right SAC callback. + */ + SKIP_CHARS (a_this, 1) ; + status = CR_OK; + break; + } else { + g_string_append_c (comment->stryng, + '*'); + } + } + g_string_append_unichar (comment->stryng, cur_char); + } + + if (status == CR_OK) { + cr_parsing_location_copy (&comment->location, + &loc) ; + *a_comment = comment; + return CR_OK; + } + error: + + if (comment) { + cr_string_destroy (comment); + comment = NULL; + } + + cr_tknzr_set_cur_pos (a_this, &init_pos); + + return status; +} + +/** + *Parses an 'unicode' escape sequence defined + *in css spec at chap 4.1.1: + *unicode ::= \\[0-9a-f]{1,6}[ \n\r\t\f]? + *@param a_this the current instance of #CRTknzr. + *@param a_start out parameter. A pointer to the start + *of the unicode escape sequence. Must *NOT* be deleted by + *the caller. + *@param a_end out parameter. A pointer to the last character + *of the unicode escape sequence. Must *NOT* be deleted by the caller. + *@return CR_OK if parsing succeded, an error code otherwise. + *Error code can be either CR_PARSING_ERROR if the string + *parsed just doesn't + *respect the production or another error if a + *lower level error occured. + */ +static enum CRStatus +cr_tknzr_parse_unicode_escape (CRTknzr * a_this, + guint32 * a_unicode, + CRParsingLocation *a_location) +{ + guint32 cur_char; + CRInputPos init_pos; + glong occur = 0; + guint32 unicode = 0; + guchar *tmp_char_ptr1 = NULL, + *tmp_char_ptr2 = NULL; + enum CRStatus status = CR_OK; + + g_return_val_if_fail (a_this && PRIVATE (a_this) + && a_unicode, CR_BAD_PARAM_ERROR); + + /*first, let's backup the current position pointer */ + RECORD_INITIAL_POS (a_this, &init_pos); + + READ_NEXT_CHAR (a_this, &cur_char); + + if (cur_char != '\\') { + status = CR_PARSING_ERROR; + goto error; + } + if (a_location) { + cr_tknzr_get_parsing_location + (a_this, a_location) ; + } + PEEK_NEXT_CHAR (a_this, &cur_char); + + for (occur = 0, unicode = 0; ((cur_char >= '0' && cur_char <= '9') + || (cur_char >= 'a' && cur_char <= 'f') + || (cur_char >= 'A' && cur_char <= 'F')) + && occur < 6; occur++) { + gint cur_char_val = 0; + + READ_NEXT_CHAR (a_this, &cur_char); + + if ((cur_char >= '0' && cur_char <= '9')) { + cur_char_val = (cur_char - '0'); + } else if ((cur_char >= 'a' && cur_char <= 'f')) { + cur_char_val = 10 + (cur_char - 'a'); + } else if ((cur_char >= 'A' && cur_char <= 'F')) { + cur_char_val = 10 + (cur_char - 'A'); + } + + unicode = unicode * 10 + cur_char_val; + + PEEK_NEXT_CHAR (a_this, &cur_char); + } + + if (occur == 5) { + /* + *the unicode escape is 6 digit length + */ + + /* + *parse one space that may + *appear just after the unicode + *escape. + */ + cr_tknzr_parse_w (a_this, &tmp_char_ptr1, + &tmp_char_ptr2, NULL); + status = CR_OK; + } else { + /* + *The unicode escape is less than + *6 digit length. The character + *that comes right after the escape + *must be a white space. + */ + status = cr_tknzr_parse_w (a_this, &tmp_char_ptr1, + &tmp_char_ptr2, NULL); + } + + if (status == CR_OK) { + *a_unicode = unicode; + return CR_OK; + } + + error: + /* + *restore the initial position pointer backuped at + *the beginning of this function. + */ + cr_tknzr_set_cur_pos (a_this, &init_pos); + + return status; +} + +/** + *parses an escape sequence as defined by the css spec: + *escape ::= {unicode}|\\[ -~\200-\4177777] + *@param a_this the current instance of #CRTknzr . + */ +static enum CRStatus +cr_tknzr_parse_escape (CRTknzr * a_this, guint32 * a_esc_code, + CRParsingLocation *a_location) +{ + enum CRStatus status = CR_OK; + guint32 cur_char = 0; + CRInputPos init_pos; + guchar next_chars[2]; + + g_return_val_if_fail (a_this && PRIVATE (a_this) + && a_esc_code, CR_BAD_PARAM_ERROR); + + RECORD_INITIAL_POS (a_this, &init_pos); + + PEEK_BYTE (a_this, 1, &next_chars[0]); + PEEK_BYTE (a_this, 2, &next_chars[1]); + + if (next_chars[0] != '\\') { + status = CR_PARSING_ERROR; + goto error; + } + + if ((next_chars[1] >= '0' && next_chars[1] <= '9') + || (next_chars[1] >= 'a' && next_chars[1] <= 'f') + || (next_chars[1] >= 'A' && next_chars[1] <= 'F')) { + status = cr_tknzr_parse_unicode_escape (a_this, a_esc_code, + a_location); + } else { + /*consume the '\' char */ + READ_NEXT_CHAR (a_this, &cur_char); + if (a_location) { + cr_tknzr_get_parsing_location (a_this, + a_location) ; + } + /*then read the char after the '\' */ + READ_NEXT_CHAR (a_this, &cur_char); + + if (cur_char != ' ' && (cur_char < 200 || cur_char > 4177777)) { + status = CR_PARSING_ERROR; + goto error; + } + *a_esc_code = cur_char; + + } + if (status == CR_OK) { + return CR_OK; + } + error: + cr_tknzr_set_cur_pos (a_this, &init_pos); + return status; +} + +/** + *Parses a string type as defined in css spec [4.1.1]: + * + *string ::= {string1}|{string2} + *string1 ::= \"([\t !#$%&(-~]|\\{nl}|\'|{nonascii}|{escape})*\" + *string2 ::= \'([\t !#$%&(-~]|\\{nl}|\"|{nonascii}|{escape})*\' + * + *@param a_this the current instance of #CRTknzr. + *@param a_start out parameter. Upon successfull completion, + *points to the beginning of the string, points to an undefined value + *otherwise. + *@param a_end out parameter. Upon successfull completion, points to + *the beginning of the string, points to an undefined value otherwise. + *@return CR_OK upon successfull completion, an error code otherwise. + */ +static enum CRStatus +cr_tknzr_parse_string (CRTknzr * a_this, CRString ** a_str) +{ + guint32 cur_char = 0, + delim = 0; + CRInputPos init_pos; + enum CRStatus status = CR_OK; + CRString *str = NULL; + + g_return_val_if_fail (a_this && PRIVATE (a_this) + && PRIVATE (a_this)->input + && a_str, CR_BAD_PARAM_ERROR); + + RECORD_INITIAL_POS (a_this, &init_pos); + READ_NEXT_CHAR (a_this, &cur_char); + + if (cur_char == '"') + delim = '"'; + else if (cur_char == '\'') + delim = '\''; + else { + status = CR_PARSING_ERROR; + goto error; + } + str = cr_string_new (); + if (str) { + cr_tknzr_get_parsing_location + (a_this, &str->location) ; + } + for (;;) { + guchar next_chars[2] = { 0 }; + + PEEK_BYTE (a_this, 1, &next_chars[0]); + PEEK_BYTE (a_this, 2, &next_chars[1]); + + if (next_chars[0] == '\\') { + guchar *tmp_char_ptr1 = NULL, + *tmp_char_ptr2 = NULL; + guint32 esc_code = 0; + + if (next_chars[1] == '\'' || next_chars[1] == '"') { + g_string_append_unichar (str->stryng, + next_chars[1]); + SKIP_BYTES (a_this, 2); + status = CR_OK; + } else { + status = cr_tknzr_parse_escape + (a_this, &esc_code, NULL); + + if (status == CR_OK) { + g_string_append_unichar + (str->stryng, + esc_code); + } + } + + if (status != CR_OK) { + /* + *consume the '\' char, and try to parse + *a newline. + */ + READ_NEXT_CHAR (a_this, &cur_char); + + status = cr_tknzr_parse_nl + (a_this, &tmp_char_ptr1, + &tmp_char_ptr2, NULL); + } + + CHECK_PARSING_STATUS (status, FALSE); + } else if (strchr ("\t !#$%&", next_chars[0]) + || (next_chars[0] >= '(' && next_chars[0] <= '~')) { + READ_NEXT_CHAR (a_this, &cur_char); + g_string_append_unichar (str->stryng, + cur_char); + status = CR_OK; + } + + else if (cr_utils_is_nonascii (next_chars[0])) { + READ_NEXT_CHAR (a_this, &cur_char); + g_string_append_unichar (str->stryng, cur_char); + } else if (next_chars[0] == delim) { + READ_NEXT_CHAR (a_this, &cur_char); + break; + } else { + status = CR_PARSING_ERROR; + goto error; + } + } + + if (status == CR_OK) { + if (*a_str == NULL) { + *a_str = str; + str = NULL; + } else { + (*a_str)->stryng = g_string_append_len + ((*a_str)->stryng, + str->stryng->str, + str->stryng->len); + cr_string_destroy (str); + } + return CR_OK; + } + + error: + + if (str) { + cr_string_destroy (str) ; + str = NULL; + } + cr_tknzr_set_cur_pos (a_this, &init_pos); + return status; +} + +/** + *Parses the an nmstart as defined by the css2 spec [4.1.1]: + * nmstart [a-zA-Z]|{nonascii}|{escape} + * + *@param a_this the current instance of #CRTknzr. + *@param a_start out param. A pointer to the starting point of + *the token. + *@param a_end out param. A pointer to the ending point of the + *token. + *@param a_char out param. The actual parsed nmchar. + *@return CR_OK upon successfull completion, + *an error code otherwise. + */ +static enum CRStatus +cr_tknzr_parse_nmstart (CRTknzr * a_this, + guint32 * a_char, + CRParsingLocation *a_location) +{ + CRInputPos init_pos; + enum CRStatus status = CR_OK; + guint32 cur_char = 0, + next_char = 0; + + g_return_val_if_fail (a_this && PRIVATE (a_this) + && PRIVATE (a_this)->input + && a_char, CR_BAD_PARAM_ERROR); + + RECORD_INITIAL_POS (a_this, &init_pos); + + PEEK_NEXT_CHAR (a_this, &next_char); + + if (next_char == '\\') { + status = cr_tknzr_parse_escape (a_this, a_char, + a_location); + + if (status != CR_OK) + goto error; + + } else if (cr_utils_is_nonascii (next_char) == TRUE + || ((next_char >= 'a') && (next_char <= 'z')) + || ((next_char >= 'A') && (next_char <= 'Z')) + ) { + READ_NEXT_CHAR (a_this, &cur_char); + if (a_location) { + cr_tknzr_get_parsing_location (a_this, + a_location) ; + } + *a_char = cur_char; + status = CR_OK; + } else { + status = CR_PARSING_ERROR; + goto error; + } + + return CR_OK; + + error: + cr_tknzr_set_cur_pos (a_this, &init_pos); + + return status; + +} + +/** + *Parses an nmchar as described in the css spec at + *chap 4.1.1: + *nmchar ::= [a-z0-9-]|{nonascii}|{escape} + * + *Humm, I have added the possibility for nmchar to + *contain upper case letters. + * + *@param a_this the current instance of #CRTknzr. + *@param a_start out param. A pointer to the starting point of + *the token. + *@param a_end out param. A pointer to the ending point of the + *token. + *@param a_char out param. The actual parsed nmchar. + *@return CR_OK upon successfull completion, + *an error code otherwise. + */ +static enum CRStatus +cr_tknzr_parse_nmchar (CRTknzr * a_this, guint32 * a_char, + CRParsingLocation *a_location) +{ + guint32 cur_char = 0, + next_char = 0; + enum CRStatus status = CR_OK; + CRInputPos init_pos; + + g_return_val_if_fail (a_this && PRIVATE (a_this) && a_char, + CR_BAD_PARAM_ERROR); + + RECORD_INITIAL_POS (a_this, &init_pos); + + status = cr_input_peek_char (PRIVATE (a_this)->input, + &next_char) ; + if (status != CR_OK) + goto error; + + if (next_char == '\\') { + status = cr_tknzr_parse_escape (a_this, a_char, + a_location); + + if (status != CR_OK) + goto error; + + } else if (cr_utils_is_nonascii (next_char) == TRUE + || ((next_char >= 'a') && (next_char <= 'z')) + || ((next_char >= 'A') && (next_char <= 'Z')) + || ((next_char >= '0') && (next_char <= '9')) + || (next_char == '-') + || (next_char == '_') /*'_' not allowed by the spec. */ + ) { + READ_NEXT_CHAR (a_this, &cur_char); + *a_char = cur_char; + status = CR_OK; + if (a_location) { + cr_tknzr_get_parsing_location + (a_this, a_location) ; + } + } else { + status = CR_PARSING_ERROR; + goto error; + } + return CR_OK; + + error: + cr_tknzr_set_cur_pos (a_this, &init_pos); + return status; +} + +/** + *Parses an "ident" as defined in css spec [4.1.1]: + *ident ::= {nmstart}{nmchar}* + * + *Actually parses it using the css3 grammar: + *ident ::= -?{nmstart}{nmchar}* + *@param a_this the currens instance of #CRTknzr. + * + *@param a_str a pointer to parsed ident. If *a_str is NULL, + *this function allocates a new instance of CRString. If not, + *the function just appends the parsed string to the one passed. + *In both cases it is up to the caller to free *a_str. + * + *@return CR_OK upon successfull completion, an error code + *otherwise. + */ +static enum CRStatus +cr_tknzr_parse_ident (CRTknzr * a_this, CRString ** a_str) +{ + guint32 tmp_char = 0; + CRString *stringue = NULL ; + CRInputPos init_pos; + enum CRStatus status = CR_OK; + gboolean location_is_set = FALSE ; + + g_return_val_if_fail (a_this && PRIVATE (a_this) + && PRIVATE (a_this)->input + && a_str, CR_BAD_PARAM_ERROR); + + RECORD_INITIAL_POS (a_this, &init_pos); + PEEK_NEXT_CHAR (a_this, &tmp_char) ; + stringue = cr_string_new () ; + g_return_val_if_fail (stringue, + CR_OUT_OF_MEMORY_ERROR) ; + + if (tmp_char == '-') { + READ_NEXT_CHAR (a_this, &tmp_char) ; + cr_tknzr_get_parsing_location + (a_this, &stringue->location) ; + location_is_set = TRUE ; + g_string_append_unichar (stringue->stryng, + tmp_char) ; + } + status = cr_tknzr_parse_nmstart (a_this, &tmp_char, NULL); + if (status != CR_OK) { + status = CR_PARSING_ERROR; + goto end ; + } + if (location_is_set == FALSE) { + cr_tknzr_get_parsing_location + (a_this, &stringue->location) ; + location_is_set = TRUE ; + } + g_string_append_unichar (stringue->stryng, tmp_char); + for (;;) { + status = cr_tknzr_parse_nmchar (a_this, + &tmp_char, + NULL); + if (status != CR_OK) { + status = CR_OK ; + break; + } + g_string_append_unichar (stringue->stryng, tmp_char); + } + if (status == CR_OK) { + if (!*a_str) { + *a_str = stringue ; + + } else { + g_string_append_len ((*a_str)->stryng, + stringue->stryng->str, + stringue->stryng->len) ; + cr_string_destroy (stringue) ; + } + stringue = NULL ; + } + + error: + end: + if (stringue) { + cr_string_destroy (stringue) ; + stringue = NULL ; + } + if (status != CR_OK ) { + cr_tknzr_set_cur_pos (a_this, &init_pos) ; + } + return status ; +} + + +/** + *Parses a "name" as defined by css spec [4.1.1]: + *name ::= {nmchar}+ + * + *@param a_this the current instance of #CRTknzr. + * + *@param a_str out parameter. A pointer to the successfully parsed + *name. If *a_str is set to NULL, this function allocates a new instance + *of CRString. If not, it just appends the parsed name to the passed *a_str. + *In both cases, it is up to the caller to free *a_str. + * + *@return CR_OK upon successfull completion, an error code otherwise. + */ +static enum CRStatus +cr_tknzr_parse_name (CRTknzr * a_this, + CRString ** a_str) +{ + guint32 tmp_char = 0; + CRInputPos init_pos; + enum CRStatus status = CR_OK; + gboolean str_needs_free = FALSE, + is_first_nmchar=TRUE ; + glong i = 0; + CRParsingLocation loc = {0} ; + + g_return_val_if_fail (a_this && PRIVATE (a_this) + && PRIVATE (a_this)->input + && a_str, + CR_BAD_PARAM_ERROR) ; + + RECORD_INITIAL_POS (a_this, &init_pos); + + if (*a_str == NULL) { + *a_str = cr_string_new (); + str_needs_free = TRUE; + } + for (i = 0;; i++) { + if (is_first_nmchar == TRUE) { + status = cr_tknzr_parse_nmchar + (a_this, &tmp_char, + &loc) ; + is_first_nmchar = FALSE ; + } else { + status = cr_tknzr_parse_nmchar + (a_this, &tmp_char, NULL) ; + } + if (status != CR_OK) + break; + g_string_append_unichar ((*a_str)->stryng, + tmp_char); + } + if (i > 0) { + cr_parsing_location_copy + (&(*a_str)->location, &loc) ; + return CR_OK; + } + if (str_needs_free == TRUE && *a_str) { + cr_string_destroy (*a_str); + *a_str = NULL; + } + cr_tknzr_set_cur_pos (a_this, &init_pos); + return CR_PARSING_ERROR; +} + +/** + *Parses a "hash" as defined by the css spec in [4.1.1]: + *HASH ::= #{name} + */ +static enum CRStatus +cr_tknzr_parse_hash (CRTknzr * a_this, CRString ** a_str) +{ + guint32 cur_char = 0; + CRInputPos init_pos; + enum CRStatus status = CR_OK; + gboolean str_needs_free = FALSE; + CRParsingLocation loc = {0} ; + + g_return_val_if_fail (a_this && PRIVATE (a_this) + && PRIVATE (a_this)->input, + CR_BAD_PARAM_ERROR); + + RECORD_INITIAL_POS (a_this, &init_pos); + READ_NEXT_CHAR (a_this, &cur_char); + if (cur_char != '#') { + status = CR_PARSING_ERROR; + goto error; + } + if (*a_str == NULL) { + *a_str = cr_string_new (); + str_needs_free = TRUE; + } + cr_tknzr_get_parsing_location (a_this, + &loc) ; + status = cr_tknzr_parse_name (a_this, a_str); + cr_parsing_location_copy (&(*a_str)->location, &loc) ; + if (status != CR_OK) { + goto error; + } + return CR_OK; + + error: + if (str_needs_free == TRUE && *a_str) { + cr_string_destroy (*a_str); + *a_str = NULL; + } + + cr_tknzr_set_cur_pos (a_this, &init_pos); + return status; +} + +/** + *Parses an uri as defined by the css spec [4.1.1]: + * URI ::= url\({w}{string}{w}\) + * |url\({w}([!#$%&*-~]|{nonascii}|{escape})*{w}\) + * + *@param a_this the current instance of #CRTknzr. + *@param a_str the successfully parsed url. + *@return CR_OK upon successfull completion, an error code otherwise. + */ +static enum CRStatus +cr_tknzr_parse_uri (CRTknzr * a_this, + CRString ** a_str) +{ + guint32 cur_char = 0; + CRInputPos init_pos; + enum CRStatus status = CR_PARSING_ERROR; + guchar tab[4] = { 0 }, *tmp_ptr1 = NULL, *tmp_ptr2 = NULL; + CRString *str = NULL; + CRParsingLocation location = {0} ; + + g_return_val_if_fail (a_this + && PRIVATE (a_this) + && PRIVATE (a_this)->input + && a_str, + CR_BAD_PARAM_ERROR); + + RECORD_INITIAL_POS (a_this, &init_pos); + + PEEK_BYTE (a_this, 1, &tab[0]); + PEEK_BYTE (a_this, 2, &tab[1]); + PEEK_BYTE (a_this, 3, &tab[2]); + PEEK_BYTE (a_this, 4, &tab[3]); + + if (tab[0] != 'u' || tab[1] != 'r' || tab[2] != 'l' || tab[3] != '(') { + status = CR_PARSING_ERROR; + goto error; + } + /* + *Here, we want to skip 4 bytes ('u''r''l''('). + *But we also need to keep track of the parsing location + *of the 'u'. So, we skip 1 byte, we record the parsing + *location, then we skip the 3 remaining bytes. + */ + SKIP_CHARS (a_this, 1); + cr_tknzr_get_parsing_location (a_this, &location) ; + SKIP_CHARS (a_this, 3); + cr_tknzr_try_to_skip_spaces (a_this); + status = cr_tknzr_parse_string (a_this, a_str); + + if (status == CR_OK) { + guint32 next_char = 0; + status = cr_tknzr_parse_w (a_this, &tmp_ptr1, + &tmp_ptr2, NULL); + cr_tknzr_try_to_skip_spaces (a_this); + PEEK_NEXT_CHAR (a_this, &next_char); + if (next_char == ')') { + READ_NEXT_CHAR (a_this, &cur_char); + status = CR_OK; + } else { + status = CR_PARSING_ERROR; + } + } + if (status != CR_OK) { + str = cr_string_new (); + for (;;) { + guint32 next_char = 0; + PEEK_NEXT_CHAR (a_this, &next_char); + if (strchr ("!#$%&", next_char) + || (next_char >= '*' && next_char <= '~') + || (cr_utils_is_nonascii (next_char) == TRUE)) { + READ_NEXT_CHAR (a_this, &cur_char); + g_string_append_unichar + (str->stryng, cur_char); + status = CR_OK; + } else { + guint32 esc_code = 0; + status = cr_tknzr_parse_escape + (a_this, &esc_code, NULL); + if (status == CR_OK) { + g_string_append_unichar + (str->stryng, + esc_code); + } else { + status = CR_OK; + break; + } + } + } + cr_tknzr_try_to_skip_spaces (a_this); + READ_NEXT_CHAR (a_this, &cur_char); + if (cur_char == ')') { + status = CR_OK; + } else { + status = CR_PARSING_ERROR; + goto error; + } + if (str) { + if (*a_str == NULL) { + *a_str = str; + str = NULL; + } else { + g_string_append_len + ((*a_str)->stryng, + str->stryng->str, + str->stryng->len); + cr_string_destroy (str); + } + } + } + + cr_parsing_location_copy + (&(*a_str)->location, + &location) ; + return CR_OK ; + error: + if (str) { + cr_string_destroy (str); + str = NULL; + } + cr_tknzr_set_cur_pos (a_this, &init_pos); + return status; +} + +/** + *parses an RGB as defined in the css2 spec. + *rgb: rgb '('S*{num}%?S* ',' {num}#?S*,S*{num}#?S*')' + * + *@param a_this the "this pointer" of the current instance of + *@param a_rgb out parameter the parsed rgb. + *@return CR_OK upon successfull completion, an error code otherwise. + */ +static enum CRStatus +cr_tknzr_parse_rgb (CRTknzr * a_this, CRRgb ** a_rgb) +{ + enum CRStatus status = CR_OK; + CRInputPos init_pos; + CRNum *num = NULL; + guchar next_bytes[3] = { 0 }, cur_byte = 0; + glong red = 0, + green = 0, + blue = 0, + i = 0; + gboolean is_percentage = FALSE; + CRParsingLocation location = {0} ; + + g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR); + + RECORD_INITIAL_POS (a_this, &init_pos); + + PEEK_BYTE (a_this, 1, &next_bytes[0]); + PEEK_BYTE (a_this, 2, &next_bytes[1]); + PEEK_BYTE (a_this, 3, &next_bytes[2]); + + if (((next_bytes[0] == 'r') || (next_bytes[0] == 'R')) + && ((next_bytes[1] == 'g') || (next_bytes[1] == 'G')) + && ((next_bytes[2] == 'b') || (next_bytes[2] == 'B'))) { + SKIP_CHARS (a_this, 1); + cr_tknzr_get_parsing_location (a_this, &location) ; + SKIP_CHARS (a_this, 2); + } else { + status = CR_PARSING_ERROR; + goto error; + } + READ_NEXT_BYTE (a_this, &cur_byte); + ENSURE_PARSING_COND (cur_byte == '('); + + cr_tknzr_try_to_skip_spaces (a_this); + status = cr_tknzr_parse_num (a_this, &num); + ENSURE_PARSING_COND ((status == CR_OK) && (num != NULL)); + + red = num->val; + cr_num_destroy (num); + num = NULL; + + PEEK_BYTE (a_this, 1, &next_bytes[0]); + if (next_bytes[0] == '%') { + SKIP_CHARS (a_this, 1); + is_percentage = TRUE; + } + cr_tknzr_try_to_skip_spaces (a_this); + + for (i = 0; i < 2; i++) { + READ_NEXT_BYTE (a_this, &cur_byte); + ENSURE_PARSING_COND (cur_byte == ','); + + cr_tknzr_try_to_skip_spaces (a_this); + status = cr_tknzr_parse_num (a_this, &num); + ENSURE_PARSING_COND ((status == CR_OK) && (num != NULL)); + + PEEK_BYTE (a_this, 1, &next_bytes[0]); + if (next_bytes[0] == '%') { + SKIP_CHARS (a_this, 1); + is_percentage = 1; + } + + if (i == 0) { + green = num->val; + } else if (i == 1) { + blue = num->val; + } + + if (num) { + cr_num_destroy (num); + num = NULL; + } + cr_tknzr_try_to_skip_spaces (a_this); + } + + READ_NEXT_BYTE (a_this, &cur_byte); + if (*a_rgb == NULL) { + *a_rgb = cr_rgb_new_with_vals (red, green, blue, + is_percentage); + + if (*a_rgb == NULL) { + status = CR_ERROR; + goto error; + } + status = CR_OK; + } else { + (*a_rgb)->red = red; + (*a_rgb)->green = green; + (*a_rgb)->blue = blue; + (*a_rgb)->is_percentage = is_percentage; + + status = CR_OK; + } + + if (status == CR_OK) { + if (a_rgb && *a_rgb) { + cr_parsing_location_copy + (&(*a_rgb)->location, + &location) ; + } + return CR_OK; + } + + error: + if (num) { + cr_num_destroy (num); + num = NULL; + } + + cr_tknzr_set_cur_pos (a_this, &init_pos); + return CR_OK; +} + +/** + *Parses a atkeyword as defined by the css spec in [4.1.1]: + *ATKEYWORD ::= @{ident} + * + *@param a_this the "this pointer" of the current instance of + *#CRTknzr. + * + *@param a_str out parameter. The parsed atkeyword. If *a_str is + *set to NULL this function allocates a new instance of CRString and + *sets it to the parsed atkeyword. If not, this function just appends + *the parsed atkeyword to the end of *a_str. In both cases it is up to + *the caller to free *a_str. + * + *@return CR_OK upon successfull completion, an error code otherwise. + */ +static enum CRStatus +cr_tknzr_parse_atkeyword (CRTknzr * a_this, + CRString ** a_str) +{ + guint32 cur_char = 0; + CRInputPos init_pos; + gboolean str_needs_free = FALSE; + enum CRStatus status = CR_OK; + + g_return_val_if_fail (a_this && PRIVATE (a_this) + && PRIVATE (a_this)->input + && a_str, CR_BAD_PARAM_ERROR); + + RECORD_INITIAL_POS (a_this, &init_pos); + + READ_NEXT_CHAR (a_this, &cur_char); + + if (cur_char != '@') { + status = CR_PARSING_ERROR; + goto error; + } + + if (*a_str == NULL) { + *a_str = cr_string_new (); + str_needs_free = TRUE; + } + status = cr_tknzr_parse_ident (a_this, a_str); + if (status != CR_OK) { + goto error; + } + return CR_OK; + error: + + if (str_needs_free == TRUE && *a_str) { + cr_string_destroy (*a_str); + *a_str = NULL; + } + cr_tknzr_set_cur_pos (a_this, &init_pos); + return status; +} + +static enum CRStatus +cr_tknzr_parse_important (CRTknzr * a_this, + CRParsingLocation *a_location) +{ + guint32 cur_char = 0; + CRInputPos init_pos; + enum CRStatus status = CR_OK; + + g_return_val_if_fail (a_this && PRIVATE (a_this) + && PRIVATE (a_this)->input, + CR_BAD_PARAM_ERROR); + + RECORD_INITIAL_POS (a_this, &init_pos); + READ_NEXT_CHAR (a_this, &cur_char); + ENSURE_PARSING_COND (cur_char == '!'); + if (a_location) { + cr_tknzr_get_parsing_location (a_this, + a_location) ; + } + cr_tknzr_try_to_skip_spaces (a_this); + + if (BYTE (PRIVATE (a_this)->input, 1, NULL) == 'i' + && BYTE (PRIVATE (a_this)->input, 2, NULL) == 'm' + && BYTE (PRIVATE (a_this)->input, 3, NULL) == 'p' + && BYTE (PRIVATE (a_this)->input, 4, NULL) == 'o' + && BYTE (PRIVATE (a_this)->input, 5, NULL) == 'r' + && BYTE (PRIVATE (a_this)->input, 6, NULL) == 't' + && BYTE (PRIVATE (a_this)->input, 7, NULL) == 'a' + && BYTE (PRIVATE (a_this)->input, 8, NULL) == 'n' + && BYTE (PRIVATE (a_this)->input, 9, NULL) == 't') { + SKIP_BYTES (a_this, 9); + if (a_location) { + cr_tknzr_get_parsing_location (a_this, + a_location) ; + } + return CR_OK; + } else { + status = CR_PARSING_ERROR; + } + + error: + cr_tknzr_set_cur_pos (a_this, &init_pos); + + return status; +} + +/** + *Parses a num as defined in the css spec [4.1.1]: + *[0-9]+|[0-9]*\.[0-9]+ + *@param a_this the current instance of #CRTknzr. + *@param a_num out parameter. The parsed number. + *@return CR_OK upon successfull completion, + *an error code otherwise. + */ +static enum CRStatus +cr_tknzr_parse_num (CRTknzr * a_this, + CRNum ** a_num) +{ + enum CRStatus status = CR_PARSING_ERROR; + enum CRNumType val_type = NUM_GENERIC; + gboolean parsing_dec = FALSE, + parsed = FALSE; + guint32 cur_char = 0, + int_part = 0, + dec_part = 0, + next_char = 0, + decimal_places = 0; + CRInputPos init_pos; + CRParsingLocation location = {0} ; + + g_return_val_if_fail (a_this && PRIVATE (a_this) + && PRIVATE (a_this)->input, + CR_BAD_PARAM_ERROR); + + RECORD_INITIAL_POS (a_this, &init_pos); + READ_NEXT_CHAR (a_this, &cur_char); + if (IS_NUM (cur_char) == TRUE) { + int_part = int_part * 10 + (cur_char - '0'); + + parsed = TRUE; + } else if (cur_char == '.') { + parsing_dec = TRUE; + } else { + status = CR_PARSING_ERROR; + goto error; + } + cr_tknzr_get_parsing_location (a_this, &location) ; + + for (;;) { + status = cr_tknzr_peek_char (a_this, &next_char); + if (status != CR_OK) { + if (status == CR_END_OF_INPUT_ERROR) + status = CR_OK; + break; + } + if (next_char == '.') { + if (parsing_dec == TRUE) { + status = CR_PARSING_ERROR; + goto error; + } + + READ_NEXT_CHAR (a_this, &cur_char); + parsing_dec = TRUE; + parsed = TRUE; + } else if (IS_NUM (next_char) == TRUE) { + READ_NEXT_CHAR (a_this, &cur_char); + parsed = TRUE; + + if (parsing_dec == FALSE) { + int_part = int_part * 10 + (cur_char - '0'); + } else { + decimal_places++; + dec_part = dec_part * 10 + (cur_char - '0'); + } + } else { + break; + } + } + + if (parsed == FALSE) { + status = CR_PARSING_ERROR; + } + + /* + *Now, set the output param values. + */ + if (status == CR_OK) { + gdouble val = 0.0; + + val = int_part; + val += cr_utils_n_to_0_dot_n (dec_part, decimal_places); + if (*a_num == NULL) { + *a_num = cr_num_new_with_val (val, val_type); + + if (*a_num == NULL) { + status = CR_ERROR; + goto error; + } + } else { + (*a_num)->val = val; + (*a_num)->type = val_type; + } + cr_parsing_location_copy (&(*a_num)->location, + &location) ; + return CR_OK; + } + + error: + + cr_tknzr_set_cur_pos (a_this, &init_pos); + + return status; +} + +/********************************************* + *PUBLIC methods + ********************************************/ + +CRTknzr * +cr_tknzr_new (CRInput * a_input) +{ + CRTknzr *result = NULL; + + result = g_try_malloc (sizeof (CRTknzr)); + + if (result == NULL) { + cr_utils_trace_info ("Out of memory"); + return NULL; + } + + memset (result, 0, sizeof (CRTknzr)); + + result->priv = g_try_malloc (sizeof (CRTknzrPriv)); + + if (result->priv == NULL) { + cr_utils_trace_info ("Out of memory"); + + if (result) { + g_free (result); + result = NULL; + } + + return NULL; + } + memset (result->priv, 0, sizeof (CRTknzrPriv)); + if (a_input) + cr_tknzr_set_input (result, a_input); + return result; +} + +CRTknzr * +cr_tknzr_new_from_buf (guchar * a_buf, gulong a_len, + enum CREncoding a_enc, + gboolean a_free_at_destroy) +{ + CRTknzr *result = NULL; + CRInput *input = NULL; + + input = cr_input_new_from_buf (a_buf, a_len, a_enc, + a_free_at_destroy); + + g_return_val_if_fail (input != NULL, NULL); + + result = cr_tknzr_new (input); + + return result; +} + +CRTknzr * +cr_tknzr_new_from_uri (const guchar * a_file_uri, + enum CREncoding a_enc) +{ + CRTknzr *result = NULL; + CRInput *input = NULL; + + input = cr_input_new_from_uri (a_file_uri, a_enc); + g_return_val_if_fail (input != NULL, NULL); + + result = cr_tknzr_new (input); + + return result; +} + +void +cr_tknzr_ref (CRTknzr * a_this) +{ + g_return_if_fail (a_this && PRIVATE (a_this)); + + PRIVATE (a_this)->ref_count++; +} + +gboolean +cr_tknzr_unref (CRTknzr * a_this) +{ + g_return_val_if_fail (a_this && PRIVATE (a_this), FALSE); + + if (PRIVATE (a_this)->ref_count > 0) { + PRIVATE (a_this)->ref_count--; + } + + if (PRIVATE (a_this)->ref_count == 0) { + cr_tknzr_destroy (a_this); + return TRUE; + } + + return FALSE; +} + +enum CRStatus +cr_tknzr_set_input (CRTknzr * a_this, CRInput * a_input) +{ + g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR); + + if (PRIVATE (a_this)->input) { + cr_input_unref (PRIVATE (a_this)->input); + } + + PRIVATE (a_this)->input = a_input; + + cr_input_ref (PRIVATE (a_this)->input); + + return CR_OK; +} + +enum CRStatus +cr_tknzr_get_input (CRTknzr * a_this, CRInput ** a_input) +{ + g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR); + + *a_input = PRIVATE (a_this)->input; + + return CR_OK; +} + +/********************************* + *Tokenizer input handling routines + *********************************/ + +/** + *Reads the next byte from the parser input stream. + *@param a_this the "this pointer" of the current instance of + *#CRParser. + *@param a_byte out parameter the place where to store the byte + *read. + *@return CR_OK upon successfull completion, an error + *code otherwise. + */ +enum CRStatus +cr_tknzr_read_byte (CRTknzr * a_this, guchar * a_byte) +{ + g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR); + + return cr_input_read_byte (PRIVATE (a_this)->input, a_byte); + +} + +/** + *Reads the next char from the parser input stream. + *@param a_this the current instance of #CRTknzr. + *@param a_char out parameter. The read char. + *@return CR_OK upon successfull completion, an error code + *otherwise. + */ +enum CRStatus +cr_tknzr_read_char (CRTknzr * a_this, guint32 * a_char) +{ + g_return_val_if_fail (a_this && PRIVATE (a_this) + && PRIVATE (a_this)->input + && a_char, CR_BAD_PARAM_ERROR); + + if (PRIVATE (a_this)->token_cache) { + cr_input_set_cur_pos (PRIVATE (a_this)->input, + &PRIVATE (a_this)->prev_pos); + cr_token_destroy (PRIVATE (a_this)->token_cache); + PRIVATE (a_this)->token_cache = NULL; + } + + return cr_input_read_char (PRIVATE (a_this)->input, a_char); +} + +/** + *Peeks a char from the parser input stream. + *To "peek a char" means reads the next char without consuming it. + *Subsequent calls to this function return the same char. + *@param a_this the current instance of #CRTknzr. + *@param a_char out parameter. The peeked char uppon successfull completion. + *@return CR_OK upon successfull completion, an error code otherwise. + */ +enum CRStatus +cr_tknzr_peek_char (CRTknzr * a_this, guint32 * a_char) +{ + g_return_val_if_fail (a_this && PRIVATE (a_this) + && PRIVATE (a_this)->input + && a_char, CR_BAD_PARAM_ERROR); + + if (PRIVATE (a_this)->token_cache) { + cr_input_set_cur_pos (PRIVATE (a_this)->input, + &PRIVATE (a_this)->prev_pos); + cr_token_destroy (PRIVATE (a_this)->token_cache); + PRIVATE (a_this)->token_cache = NULL; + } + + return cr_input_peek_char (PRIVATE (a_this)->input, a_char); +} + +/** + *Peeks a byte ahead at a given postion in the parser input stream. + *@param a_this the current instance of #CRTknzr. + *@param a_offset the offset of the peeked byte starting from the current + *byte in the parser input stream. + *@param a_byte out parameter. The peeked byte upon + *successfull completion. + *@return CR_OK upon successfull completion, an error code otherwise. + */ +enum CRStatus +cr_tknzr_peek_byte (CRTknzr * a_this, gulong a_offset, guchar * a_byte) +{ + g_return_val_if_fail (a_this && PRIVATE (a_this) + && PRIVATE (a_this)->input && a_byte, + CR_BAD_PARAM_ERROR); + + if (PRIVATE (a_this)->token_cache) { + cr_input_set_cur_pos (PRIVATE (a_this)->input, + &PRIVATE (a_this)->prev_pos); + cr_token_destroy (PRIVATE (a_this)->token_cache); + PRIVATE (a_this)->token_cache = NULL; + } + + return cr_input_peek_byte (PRIVATE (a_this)->input, + CR_SEEK_CUR, a_offset, a_byte); +} + +/** + *Same as cr_tknzr_peek_byte() but this api returns the byte peeked. + *@param a_this the current instance of #CRTknzr. + *@param a_offset the offset of the peeked byte starting from the current + *byte in the parser input stream. + *@param a_eof out parameter. If not NULL, is set to TRUE if we reached end of + *file, FALE otherwise. If the caller sets it to NULL, this parameter + *is just ignored. + *@return the peeked byte. + */ +guchar +cr_tknzr_peek_byte2 (CRTknzr * a_this, gulong a_offset, gboolean * a_eof) +{ + g_return_val_if_fail (a_this && PRIVATE (a_this) + && PRIVATE (a_this)->input, 0); + + return cr_input_peek_byte2 (PRIVATE (a_this)->input, a_offset, a_eof); +} + +/** + *Gets the number of bytes left in the topmost input stream + *associated to this parser. + *@param a_this the current instance of #CRTknzr + *@return the number of bytes left or -1 in case of error. + */ +glong +cr_tknzr_get_nb_bytes_left (CRTknzr * a_this) +{ + g_return_val_if_fail (a_this && PRIVATE (a_this) + && PRIVATE (a_this)->input, CR_BAD_PARAM_ERROR); + + if (PRIVATE (a_this)->token_cache) { + cr_input_set_cur_pos (PRIVATE (a_this)->input, + &PRIVATE (a_this)->prev_pos); + cr_token_destroy (PRIVATE (a_this)->token_cache); + PRIVATE (a_this)->token_cache = NULL; + } + + return cr_input_get_nb_bytes_left (PRIVATE (a_this)->input); +} + +enum CRStatus +cr_tknzr_get_cur_pos (CRTknzr * a_this, CRInputPos * a_pos) +{ + g_return_val_if_fail (a_this && PRIVATE (a_this) + && PRIVATE (a_this)->input + && a_pos, CR_BAD_PARAM_ERROR); + + if (PRIVATE (a_this)->token_cache) { + cr_input_set_cur_pos (PRIVATE (a_this)->input, + &PRIVATE (a_this)->prev_pos); + cr_token_destroy (PRIVATE (a_this)->token_cache); + PRIVATE (a_this)->token_cache = NULL; + } + + return cr_input_get_cur_pos (PRIVATE (a_this)->input, a_pos); +} + +enum CRStatus +cr_tknzr_get_parsing_location (CRTknzr *a_this, + CRParsingLocation *a_loc) +{ + g_return_val_if_fail (a_this + && PRIVATE (a_this) + && a_loc, + CR_BAD_PARAM_ERROR) ; + + return cr_input_get_parsing_location + (PRIVATE (a_this)->input, a_loc) ; +} + +enum CRStatus +cr_tknzr_get_cur_byte_addr (CRTknzr * a_this, guchar ** a_addr) +{ + g_return_val_if_fail (a_this && PRIVATE (a_this) + && PRIVATE (a_this)->input, CR_BAD_PARAM_ERROR); + if (PRIVATE (a_this)->token_cache) { + cr_input_set_cur_pos (PRIVATE (a_this)->input, + &PRIVATE (a_this)->prev_pos); + cr_token_destroy (PRIVATE (a_this)->token_cache); + PRIVATE (a_this)->token_cache = NULL; + } + + return cr_input_get_cur_byte_addr (PRIVATE (a_this)->input, a_addr); +} + +enum CRStatus +cr_tknzr_seek_index (CRTknzr * a_this, enum CRSeekPos a_origin, gint a_pos) +{ + g_return_val_if_fail (a_this && PRIVATE (a_this) + && PRIVATE (a_this)->input, CR_BAD_PARAM_ERROR); + + if (PRIVATE (a_this)->token_cache) { + cr_input_set_cur_pos (PRIVATE (a_this)->input, + &PRIVATE (a_this)->prev_pos); + cr_token_destroy (PRIVATE (a_this)->token_cache); + PRIVATE (a_this)->token_cache = NULL; + } + + return cr_input_seek_index (PRIVATE (a_this)->input, a_origin, a_pos); +} + +enum CRStatus +cr_tknzr_consume_chars (CRTknzr * a_this, guint32 a_char, glong * a_nb_char) +{ + g_return_val_if_fail (a_this && PRIVATE (a_this) + && PRIVATE (a_this)->input, CR_BAD_PARAM_ERROR); + + if (PRIVATE (a_this)->token_cache) { + cr_input_set_cur_pos (PRIVATE (a_this)->input, + &PRIVATE (a_this)->prev_pos); + cr_token_destroy (PRIVATE (a_this)->token_cache); + PRIVATE (a_this)->token_cache = NULL; + } + + return cr_input_consume_chars (PRIVATE (a_this)->input, + a_char, a_nb_char); +} + +enum CRStatus +cr_tknzr_set_cur_pos (CRTknzr * a_this, CRInputPos * a_pos) +{ + g_return_val_if_fail (a_this && PRIVATE (a_this) + && PRIVATE (a_this)->input, CR_BAD_PARAM_ERROR); + + if (PRIVATE (a_this)->token_cache) { + cr_token_destroy (PRIVATE (a_this)->token_cache); + PRIVATE (a_this)->token_cache = NULL; + } + + return cr_input_set_cur_pos (PRIVATE (a_this)->input, a_pos); +} + +enum CRStatus +cr_tknzr_unget_token (CRTknzr * a_this, CRToken * a_token) +{ + g_return_val_if_fail (a_this && PRIVATE (a_this) + && PRIVATE (a_this)->token_cache == NULL, + CR_BAD_PARAM_ERROR); + + PRIVATE (a_this)->token_cache = a_token; + + return CR_OK; +} + +/** + *Returns the next token of the input stream. + *This method is really central. Each parsing + *method calls it. + *@param a_this the current tokenizer. + *@param a_tk out parameter. The returned token. + *for the sake of mem leak avoidance, *a_tk must + *be NULL. + *@param CR_OK upon successfull completion, an error code + *otherwise. + */ +enum CRStatus +cr_tknzr_get_next_token (CRTknzr * a_this, CRToken ** a_tk) +{ + enum CRStatus status = CR_OK; + CRToken *token = NULL; + CRInputPos init_pos; + guint32 next_char = 0; + guchar next_bytes[4] = { 0 }; + gboolean reached_eof = FALSE; + CRInput *input = NULL; + CRString *str = NULL; + CRRgb *rgb = NULL; + CRParsingLocation location = {0} ; + + g_return_val_if_fail (a_this && PRIVATE (a_this) + && a_tk && *a_tk == NULL + && PRIVATE (a_this)->input, + CR_BAD_PARAM_ERROR); + + if (PRIVATE (a_this)->token_cache) { + *a_tk = PRIVATE (a_this)->token_cache; + PRIVATE (a_this)->token_cache = NULL; + return CR_OK; + } + + RECORD_INITIAL_POS (a_this, &init_pos); + + status = cr_input_get_end_of_file + (PRIVATE (a_this)->input, &reached_eof); + ENSURE_PARSING_COND (status == CR_OK); + + if (reached_eof == TRUE) { + status = CR_END_OF_INPUT_ERROR; + goto error; + } + + input = PRIVATE (a_this)->input; + + PEEK_NEXT_CHAR (a_this, &next_char); + token = cr_token_new (); + ENSURE_PARSING_COND (token); + + switch (next_char) { + case '@': + { + if (BYTE (input, 2, NULL) == 'f' + && BYTE (input, 3, NULL) == 'o' + && BYTE (input, 4, NULL) == 'n' + && BYTE (input, 5, NULL) == 't' + && BYTE (input, 6, NULL) == '-' + && BYTE (input, 7, NULL) == 'f' + && BYTE (input, 8, NULL) == 'a' + && BYTE (input, 9, NULL) == 'c' + && BYTE (input, 10, NULL) == 'e') { + SKIP_CHARS (a_this, 1); + cr_tknzr_get_parsing_location + (a_this, &location) ; + SKIP_CHARS (a_this, 9); + status = cr_token_set_font_face_sym (token); + CHECK_PARSING_STATUS (status, TRUE); + cr_parsing_location_copy (&token->location, + &location) ; + goto done; + } + + if (BYTE (input, 2, NULL) == 'c' + && BYTE (input, 3, NULL) == 'h' + && BYTE (input, 4, NULL) == 'a' + && BYTE (input, 5, NULL) == 'r' + && BYTE (input, 6, NULL) == 's' + && BYTE (input, 7, NULL) == 'e' + && BYTE (input, 8, NULL) == 't') { + SKIP_CHARS (a_this, 1); + cr_tknzr_get_parsing_location + (a_this, &location) ; + SKIP_CHARS (a_this, 7); + status = cr_token_set_charset_sym (token); + CHECK_PARSING_STATUS (status, TRUE); + cr_parsing_location_copy (&token->location, + &location) ; + goto done; + } + + if (BYTE (input, 2, NULL) == 'i' + && BYTE (input, 3, NULL) == 'm' + && BYTE (input, 4, NULL) == 'p' + && BYTE (input, 5, NULL) == 'o' + && BYTE (input, 6, NULL) == 'r' + && BYTE (input, 7, NULL) == 't') { + SKIP_CHARS (a_this, 1); + cr_tknzr_get_parsing_location + (a_this, &location) ; + SKIP_CHARS (a_this, 6); + status = cr_token_set_import_sym (token); + CHECK_PARSING_STATUS (status, TRUE); + cr_parsing_location_copy (&token->location, + &location) ; + goto done; + } + + if (BYTE (input, 2, NULL) == 'm' + && BYTE (input, 3, NULL) == 'e' + && BYTE (input, 4, NULL) == 'd' + && BYTE (input, 5, NULL) == 'i' + && BYTE (input, 6, NULL) == 'a') { + SKIP_CHARS (a_this, 1); + cr_tknzr_get_parsing_location (a_this, + &location) ; + SKIP_CHARS (a_this, 5); + status = cr_token_set_media_sym (token); + CHECK_PARSING_STATUS (status, TRUE); + cr_parsing_location_copy (&token->location, + &location) ; + goto done; + } + + if (BYTE (input, 2, NULL) == 'p' + && BYTE (input, 3, NULL) == 'a' + && BYTE (input, 4, NULL) == 'g' + && BYTE (input, 5, NULL) == 'e') { + SKIP_CHARS (a_this, 1); + cr_tknzr_get_parsing_location (a_this, + &location) ; + SKIP_CHARS (a_this, 4); + status = cr_token_set_page_sym (token); + CHECK_PARSING_STATUS (status, TRUE); + cr_parsing_location_copy (&token->location, + &location) ; + goto done; + } + status = cr_tknzr_parse_atkeyword (a_this, &str); + if (status == CR_OK) { + status = cr_token_set_atkeyword (token, str); + CHECK_PARSING_STATUS (status, TRUE); + if (str) { + cr_parsing_location_copy (&token->location, + &str->location) ; + } + goto done; + } + } + break; + + case 'u': + + if (BYTE (input, 2, NULL) == 'r' + && BYTE (input, 3, NULL) == 'l' + && BYTE (input, 4, NULL) == '(') { + CRString *str = NULL; + + status = cr_tknzr_parse_uri (a_this, &str); + if (status == CR_OK) { + status = cr_token_set_uri (token, str); + CHECK_PARSING_STATUS (status, TRUE); + if (str) { + cr_parsing_location_copy (&token->location, + &str->location) ; + } + goto done; + } + } else { + status = cr_tknzr_parse_ident (a_this, &str); + if (status == CR_OK && str) { + status = cr_token_set_ident (token, str); + CHECK_PARSING_STATUS (status, TRUE); + if (str) { + cr_parsing_location_copy (&token->location, + &str->location) ; + } + goto done; + } + } + break; + + case 'r': + if (BYTE (input, 2, NULL) == 'g' + && BYTE (input, 3, NULL) == 'b' + && BYTE (input, 4, NULL) == '(') { + status = cr_tknzr_parse_rgb (a_this, &rgb); + if (status == CR_OK && rgb) { + status = cr_token_set_rgb (token, rgb); + CHECK_PARSING_STATUS (status, TRUE); + if (rgb) { + cr_parsing_location_copy (&token->location, + &rgb->location) ; + } + rgb = NULL; + goto done; + } + + } else { + status = cr_tknzr_parse_ident (a_this, &str); + if (status == CR_OK) { + status = cr_token_set_ident (token, str); + CHECK_PARSING_STATUS (status, TRUE); + if (str) { + cr_parsing_location_copy (&token->location, + &str->location) ; + } + str = NULL; + goto done; + } + } + break; + + case '<': + if (BYTE (input, 2, NULL) == '-' + && BYTE (input, 3, NULL) == '-') { + SKIP_CHARS (a_this, 1); + cr_tknzr_get_parsing_location (a_this, + &location) ; + SKIP_CHARS (a_this, 2); + status = cr_token_set_cdo (token); + CHECK_PARSING_STATUS (status, TRUE); + cr_parsing_location_copy (&token->location, + &location) ; + goto done; + } + break; + + case '-': + if (BYTE (input, 2, NULL) == '-' + && BYTE (input, 3, NULL) == '>') { + SKIP_CHARS (a_this, 1); + cr_tknzr_get_parsing_location (a_this, + &location) ; + SKIP_CHARS (a_this, 2); + status = cr_token_set_cdc (token); + CHECK_PARSING_STATUS (status, TRUE); + cr_parsing_location_copy (&token->location, + &location) ; + goto done; + } else { + status = cr_tknzr_parse_ident + (a_this, &str); + if (status == CR_OK) { + cr_token_set_ident + (token, str); + if (str) { + cr_parsing_location_copy (&token->location, + &str->location) ; + } + goto done; + } + } + break; + + case '~': + if (BYTE (input, 2, NULL) == '=') { + SKIP_CHARS (a_this, 1); + cr_tknzr_get_parsing_location (a_this, + &location) ; + SKIP_CHARS (a_this, 1); + status = cr_token_set_includes (token); + CHECK_PARSING_STATUS (status, TRUE); + cr_parsing_location_copy (&token->location, + &location) ; + goto done; + } + break; + + case '|': + if (BYTE (input, 2, NULL) == '=') { + SKIP_CHARS (a_this, 1); + cr_tknzr_get_parsing_location (a_this, + &location) ; + SKIP_CHARS (a_this, 1); + status = cr_token_set_dashmatch (token); + CHECK_PARSING_STATUS (status, TRUE); + cr_parsing_location_copy (&token->location, + &location) ; + goto done; + } + break; + + case '/': + if (BYTE (input, 2, NULL) == '*') { + status = cr_tknzr_parse_comment (a_this, &str); + + if (status == CR_OK) { + status = cr_token_set_comment (token, str); + str = NULL; + CHECK_PARSING_STATUS (status, TRUE); + if (str) { + cr_parsing_location_copy (&token->location, + &str->location) ; + } + goto done; + } + } + break ; + + case ';': + SKIP_CHARS (a_this, 1); + cr_tknzr_get_parsing_location (a_this, + &location) ; + status = cr_token_set_semicolon (token); + CHECK_PARSING_STATUS (status, TRUE); + cr_parsing_location_copy (&token->location, + &location) ; + goto done; + + case '{': + SKIP_CHARS (a_this, 1); + cr_tknzr_get_parsing_location (a_this, + &location) ; + status = cr_token_set_cbo (token); + CHECK_PARSING_STATUS (status, TRUE); + cr_tknzr_get_parsing_location (a_this, + &location) ; + goto done; + + case '}': + SKIP_CHARS (a_this, 1); + cr_tknzr_get_parsing_location (a_this, + &location) ; + status = cr_token_set_cbc (token); + CHECK_PARSING_STATUS (status, TRUE); + cr_parsing_location_copy (&token->location, + &location) ; + goto done; + + case '(': + SKIP_CHARS (a_this, 1); + cr_tknzr_get_parsing_location (a_this, + &location) ; + status = cr_token_set_po (token); + CHECK_PARSING_STATUS (status, TRUE); + cr_parsing_location_copy (&token->location, + &location) ; + goto done; + + case ')': + SKIP_CHARS (a_this, 1); + cr_tknzr_get_parsing_location (a_this, + &location) ; + status = cr_token_set_pc (token); + CHECK_PARSING_STATUS (status, TRUE); + cr_parsing_location_copy (&token->location, + &location) ; + goto done; + + case '[': + SKIP_CHARS (a_this, 1); + cr_tknzr_get_parsing_location (a_this, + &location) ; + status = cr_token_set_bo (token); + CHECK_PARSING_STATUS (status, TRUE); + cr_parsing_location_copy (&token->location, + &location) ; + goto done; + + case ']': + SKIP_CHARS (a_this, 1); + cr_tknzr_get_parsing_location (a_this, + &location) ; + status = cr_token_set_bc (token); + CHECK_PARSING_STATUS (status, TRUE); + cr_parsing_location_copy (&token->location, + &location) ; + goto done; + + case ' ': + case '\t': + case '\n': + case '\f': + case '\r': + { + guchar *start = NULL, + *end = NULL; + + status = cr_tknzr_parse_w (a_this, &start, + &end, &location); + if (status == CR_OK) { + status = cr_token_set_s (token); + CHECK_PARSING_STATUS (status, TRUE); + cr_tknzr_get_parsing_location (a_this, + &location) ; + goto done; + } + } + break; + + case '#': + { + status = cr_tknzr_parse_hash (a_this, &str); + if (status == CR_OK && str) { + status = cr_token_set_hash (token, str); + CHECK_PARSING_STATUS (status, TRUE); + if (str) { + cr_parsing_location_copy (&token->location, + &str->location) ; + } + str = NULL; + goto done; + } + } + break; + + case '\'': + case '"': + status = cr_tknzr_parse_string (a_this, &str); + if (status == CR_OK && str) { + status = cr_token_set_string (token, str); + CHECK_PARSING_STATUS (status, TRUE); + if (str) { + cr_parsing_location_copy (&token->location, + &str->location) ; + } + str = NULL; + goto done; + } + break; + + case '!': + status = cr_tknzr_parse_important (a_this, &location); + if (status == CR_OK) { + status = cr_token_set_important_sym (token); + CHECK_PARSING_STATUS (status, TRUE); + cr_parsing_location_copy (&token->location, + &location) ; + goto done; + } + break; + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '.': + { + CRNum *num = NULL; + + status = cr_tknzr_parse_num (a_this, &num); + if (status == CR_OK && num) { + next_bytes[0] = BYTE (input, 1, NULL); + next_bytes[1] = BYTE (input, 2, NULL); + next_bytes[2] = BYTE (input, 3, NULL); + next_bytes[3] = BYTE (input, 3, NULL); + + if (next_bytes[0] == 'e' + && next_bytes[1] == 'm') { + num->type = NUM_LENGTH_EM; + status = cr_token_set_ems (token, + num); + num = NULL; + SKIP_CHARS (a_this, 2); + } else if (next_bytes[0] == 'e' + && next_bytes[1] == 'x') { + num->type = NUM_LENGTH_EX; + status = cr_token_set_exs (token, + num); + num = NULL; + SKIP_CHARS (a_this, 2); + } else if (next_bytes[0] == 'p' + && next_bytes[1] == 'x') { + num->type = NUM_LENGTH_PX; + status = cr_token_set_length + (token, num, LENGTH_PX_ET); + num = NULL; + SKIP_CHARS (a_this, 2); + } else if (next_bytes[0] == 'c' + && next_bytes[1] == 'm') { + num->type = NUM_LENGTH_CM; + status = cr_token_set_length + (token, num, LENGTH_CM_ET); + num = NULL; + SKIP_CHARS (a_this, 2); + } else if (next_bytes[0] == 'm' + && next_bytes[1] == 'm') { + num->type = NUM_LENGTH_MM; + status = cr_token_set_length + (token, num, LENGTH_MM_ET); + num = NULL; + SKIP_CHARS (a_this, 2); + } else if (next_bytes[0] == 'i' + && next_bytes[1] == 'n') { + num->type = NUM_LENGTH_IN; + status = cr_token_set_length + (token, num, LENGTH_IN_ET); + num = NULL; + SKIP_CHARS (a_this, 2); + } else if (next_bytes[0] == 'p' + && next_bytes[1] == 't') { + num->type = NUM_LENGTH_PT; + status = cr_token_set_length + (token, num, LENGTH_PT_ET); + num = NULL; + SKIP_CHARS (a_this, 2); + } else if (next_bytes[0] == 'p' + && next_bytes[1] == 'c') { + num->type = NUM_LENGTH_PC; + status = cr_token_set_length + (token, num, LENGTH_PC_ET); + num = NULL; + SKIP_CHARS (a_this, 2); + } else if (next_bytes[0] == 'd' + && next_bytes[1] == 'e' + && next_bytes[2] == 'g') { + num->type = NUM_ANGLE_DEG; + status = cr_token_set_angle + (token, num, ANGLE_DEG_ET); + num = NULL; + SKIP_CHARS (a_this, 3); + } else if (next_bytes[0] == 'r' + && next_bytes[1] == 'a' + && next_bytes[2] == 'd') { + num->type = NUM_ANGLE_RAD; + status = cr_token_set_angle + (token, num, ANGLE_RAD_ET); + num = NULL; + SKIP_CHARS (a_this, 3); + } else if (next_bytes[0] == 'g' + && next_bytes[1] == 'r' + && next_bytes[2] == 'a' + && next_bytes[3] == 'd') { + num->type = NUM_ANGLE_GRAD; + status = cr_token_set_angle + (token, num, ANGLE_GRAD_ET); + num = NULL; + SKIP_CHARS (a_this, 4); + } else if (next_bytes[0] == 'm' + && next_bytes[1] == 's') { + num->type = NUM_TIME_MS; + status = cr_token_set_time + (token, num, TIME_MS_ET); + num = NULL; + SKIP_CHARS (a_this, 2); + } else if (next_bytes[0] == 's') { + num->type = NUM_TIME_S; + status = cr_token_set_time + (token, num, TIME_S_ET); + num = NULL; + SKIP_CHARS (a_this, 1); + } else if (next_bytes[0] == 'H' + && next_bytes[1] == 'z') { + num->type = NUM_FREQ_HZ; + status = cr_token_set_freq + (token, num, FREQ_HZ_ET); + num = NULL; + SKIP_CHARS (a_this, 2); + } else if (next_bytes[0] == 'k' + && next_bytes[1] == 'H' + && next_bytes[2] == 'z') { + num->type = NUM_FREQ_KHZ; + status = cr_token_set_freq + (token, num, FREQ_KHZ_ET); + num = NULL; + SKIP_CHARS (a_this, 3); + } else if (next_bytes[0] == '%') { + num->type = NUM_PERCENTAGE; + status = cr_token_set_percentage + (token, num); + num = NULL; + SKIP_CHARS (a_this, 1); + } else { + status = cr_tknzr_parse_ident (a_this, + &str); + if (status == CR_OK && str) { + num->type = NUM_UNKNOWN_TYPE; + status = cr_token_set_dimen + (token, num, str); + num = NULL; + CHECK_PARSING_STATUS (status, + TRUE); + str = NULL; + } else { + status = cr_token_set_number + (token, num); + num = NULL; + CHECK_PARSING_STATUS (status, CR_OK); + str = NULL; + } + } + if (token && token->u.num) { + cr_parsing_location_copy (&token->location, + &token->u.num->location) ; + } else { + status = CR_ERROR ; + } + goto done ; + } + } + break; + + default: + /*process the fallback cases here */ + + if (next_char == '\\' + || (cr_utils_is_nonascii (next_bytes[0]) == TRUE) + || ((next_char >= 'a') && (next_char <= 'z')) + || ((next_char >= 'A') && (next_char <= 'Z'))) { + status = cr_tknzr_parse_ident (a_this, &str); + if (status == CR_OK && str) { + guint32 next_c = 0; + + status = cr_input_peek_char + (PRIVATE (a_this)->input, &next_c); + + if (status == CR_OK && next_c == '(') { + + SKIP_CHARS (a_this, 1); + status = cr_token_set_function + (token, str); + CHECK_PARSING_STATUS (status, TRUE); + /*ownership is transfered + *to token by cr_token_set_function. + */ + if (str) { + cr_parsing_location_copy (&token->location, + &str->location) ; + } + str = NULL; + } else { + status = cr_token_set_ident (token, + str); + CHECK_PARSING_STATUS (status, TRUE); + if (str) { + cr_parsing_location_copy (&token->location, + &str->location) ; + } + str = NULL; + } + goto done; + } else { + if (str) { + cr_string_destroy (str); + str = NULL; + } + } + } + break; + } + + READ_NEXT_CHAR (a_this, &next_char); + cr_tknzr_get_parsing_location (a_this, + &location) ; + status = cr_token_set_delim (token, next_char); + CHECK_PARSING_STATUS (status, TRUE); + cr_parsing_location_copy (&token->location, + &location) ; + done: + + if (status == CR_OK && token) { + *a_tk = token; + /* + *store the previous position input stream pos. + */ + memmove (&PRIVATE (a_this)->prev_pos, + &init_pos, sizeof (CRInputPos)); + return CR_OK; + } + + error: + if (token) { + cr_token_destroy (token); + token = NULL; + } + + if (str) { + cr_string_destroy (str); + str = NULL; + } + cr_tknzr_set_cur_pos (a_this, &init_pos); + return status; + +} + +enum CRStatus +cr_tknzr_parse_token (CRTknzr * a_this, enum CRTokenType a_type, + enum CRTokenExtraType a_et, gpointer a_res, + gpointer a_extra_res) +{ + enum CRStatus status = CR_OK; + CRToken *token = NULL; + + g_return_val_if_fail (a_this && PRIVATE (a_this) + && PRIVATE (a_this)->input + && a_res, CR_BAD_PARAM_ERROR); + + status = cr_tknzr_get_next_token (a_this, &token); + if (status != CR_OK) + return status; + if (token == NULL) + return CR_PARSING_ERROR; + + if (token->type == a_type) { + switch (a_type) { + case NO_TK: + case S_TK: + case CDO_TK: + case CDC_TK: + case INCLUDES_TK: + case DASHMATCH_TK: + case IMPORT_SYM_TK: + case PAGE_SYM_TK: + case MEDIA_SYM_TK: + case FONT_FACE_SYM_TK: + case CHARSET_SYM_TK: + case IMPORTANT_SYM_TK: + status = CR_OK; + break; + + case STRING_TK: + case IDENT_TK: + case HASH_TK: + case ATKEYWORD_TK: + case FUNCTION_TK: + case COMMENT_TK: + case URI_TK: + *((CRString **) a_res) = token->u.str; + token->u.str = NULL; + status = CR_OK; + break; + + case EMS_TK: + case EXS_TK: + case PERCENTAGE_TK: + case NUMBER_TK: + *((CRNum **) a_res) = token->u.num; + token->u.num = NULL; + status = CR_OK; + break; + + case LENGTH_TK: + case ANGLE_TK: + case TIME_TK: + case FREQ_TK: + if (token->extra_type == a_et) { + *((CRNum **) a_res) = token->u.num; + token->u.num = NULL; + status = CR_OK; + } + break; + + case DIMEN_TK: + *((CRNum **) a_res) = token->u.num; + if (a_extra_res == NULL) { + status = CR_BAD_PARAM_ERROR; + goto error; + } + + *((CRString **) a_extra_res) = token->dimen; + token->u.num = NULL; + token->dimen = NULL; + status = CR_OK; + break; + + case DELIM_TK: + *((guint32 *) a_res) = token->u.unichar; + status = CR_OK; + break; + + case UNICODERANGE_TK: + default: + status = CR_PARSING_ERROR; + break; + } + + cr_token_destroy (token); + token = NULL; + } else { + cr_tknzr_unget_token (a_this, token); + token = NULL; + status = CR_PARSING_ERROR; + } + + return status; + + error: + + if (token) { + cr_tknzr_unget_token (a_this, token); + token = NULL; + } + + return status; +} + +void +cr_tknzr_destroy (CRTknzr * a_this) +{ + g_return_if_fail (a_this); + + if (PRIVATE (a_this) && PRIVATE (a_this)->input) { + if (cr_input_unref (PRIVATE (a_this)->input) + == TRUE) { + PRIVATE (a_this)->input = NULL; + } + } + + if (PRIVATE (a_this)->token_cache) { + cr_token_destroy (PRIVATE (a_this)->token_cache); + PRIVATE (a_this)->token_cache = NULL; + } + + if (PRIVATE (a_this)) { + g_free (PRIVATE (a_this)); + PRIVATE (a_this) = NULL; + } + + g_free (a_this); +} diff --git a/gettext-tools/gnulib-lib/libcroco/cr-tknzr.h b/gettext-tools/gnulib-lib/libcroco/cr-tknzr.h new file mode 100644 index 0000000..f9dea59 --- /dev/null +++ b/gettext-tools/gnulib-lib/libcroco/cr-tknzr.h @@ -0,0 +1,115 @@ +/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */ + +/* + * This file is part of The Croco Library + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + * Author: Dodji Seketeli + * See COPYRIGHTS file for coypyright information. + */ + +/** + *@file + *The declaration of the #CRTknzr (tokenizer) + *class. + */ + +#ifndef __CR_TKNZR_H__ +#define __CR_TKNZR_H__ + +#include "cr-utils.h" +#include "cr-input.h" +#include "cr-token.h" + +G_BEGIN_DECLS + + +typedef struct _CRTknzr CRTknzr ; +typedef struct _CRTknzrPriv CRTknzrPriv ; + +/** + *The tokenizer is the class that knows + *about all the css token. Its main job is + *to return the next token found in the character + *input stream. + */ +struct _CRTknzr +{ + /*the private data of the tokenizer.*/ + CRTknzrPriv *priv ; +} ; + +CRTknzr * cr_tknzr_new (CRInput *a_input) ; + +CRTknzr * cr_tknzr_new_from_uri (const guchar *a_file_uri, + enum CREncoding a_enc) ; + +CRTknzr * cr_tknzr_new_from_buf (guchar *a_buf, gulong a_len, + enum CREncoding a_enc, + gboolean a_free_at_destroy) ; + +gboolean cr_tknzr_unref (CRTknzr *a_this) ; + +void cr_tknzr_ref (CRTknzr *a_this) ; + +enum CRStatus cr_tknzr_read_byte (CRTknzr *a_this, guchar *a_byte) ; + +enum CRStatus cr_tknzr_read_char (CRTknzr *a_this, guint32 *a_char); + +enum CRStatus cr_tknzr_peek_char (CRTknzr *a_this, guint32 *a_char) ; + +enum CRStatus cr_tknzr_peek_byte (CRTknzr *a_this, gulong a_offset, + guchar *a_byte) ; + +guchar cr_tknzr_peek_byte2 (CRTknzr *a_this, gulong a_offset, + gboolean *a_eof) ; + +enum CRStatus cr_tknzr_set_cur_pos (CRTknzr *a_this, CRInputPos *a_pos) ; + +glong cr_tknzr_get_nb_bytes_left (CRTknzr *a_this) ; + +enum CRStatus cr_tknzr_get_cur_pos (CRTknzr *a_this, CRInputPos *a_pos) ; + +enum CRStatus cr_tknzr_get_parsing_location (CRTknzr *a_this, + CRParsingLocation *a_loc) ; + +enum CRStatus cr_tknzr_seek_index (CRTknzr *a_this, + enum CRSeekPos a_origin, + gint a_pos) ; + +enum CRStatus cr_tknzr_get_cur_byte_addr (CRTknzr *a_this, guchar **a_addr) ; + + +enum CRStatus cr_tknzr_consume_chars (CRTknzr *a_this, guint32 a_char, + glong *a_nb_char) ; + +enum CRStatus cr_tknzr_get_next_token (CRTknzr *a_this, CRToken ** a_tk) ; + +enum CRStatus cr_tknzr_unget_token (CRTknzr *a_this, CRToken *a_token) ; + + +enum CRStatus cr_tknzr_parse_token (CRTknzr *a_this, enum CRTokenType a_type, + enum CRTokenExtraType a_et, gpointer a_res, + gpointer a_extra_res) ; +enum CRStatus cr_tknzr_set_input (CRTknzr *a_this, CRInput *a_input) ; + +enum CRStatus cr_tknzr_get_input (CRTknzr *a_this, CRInput **a_input) ; + +void cr_tknzr_destroy (CRTknzr *a_this) ; + +G_END_DECLS + +#endif /*__CR_TKZNR_H__*/ diff --git a/gettext-tools/gnulib-lib/libcroco/cr-token.c b/gettext-tools/gnulib-lib/libcroco/cr-token.c new file mode 100644 index 0000000..83b0dfa --- /dev/null +++ b/gettext-tools/gnulib-lib/libcroco/cr-token.c @@ -0,0 +1,637 @@ +/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */ + +/* + * This file is part of The Croco Library + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + * Author: Dodji Seketeli + * see COPYRIGHTS file for copyright information. + */ + +/** + *@file + *The definition of the #CRToken class. + *Abstracts a css2 token. + */ + +#include +#include +#include "cr-token.h" + +/* + *TODO: write a CRToken::to_string() method. + */ + +/** + *Frees the attributes of the current instance + *of #CRtoken. + *@param a_this the current instance of #CRToken. + */ +static void +cr_token_clear (CRToken * a_this) +{ + g_return_if_fail (a_this); + + switch (a_this->type) { + case S_TK: + case CDO_TK: + case INCLUDES_TK: + case DASHMATCH_TK: + case PAGE_SYM_TK: + case MEDIA_SYM_TK: + case FONT_FACE_SYM_TK: + case CHARSET_SYM_TK: + case IMPORT_SYM_TK: + case IMPORTANT_SYM_TK: + case SEMICOLON_TK: + case NO_TK: + case DELIM_TK: + case CBO_TK: + case CBC_TK: + case BO_TK: + case BC_TK: + break; + + case STRING_TK: + case IDENT_TK: + case HASH_TK: + case URI_TK: + case FUNCTION_TK: + case COMMENT_TK: + case ATKEYWORD_TK: + if (a_this->u.str) { + cr_string_destroy (a_this->u.str); + a_this->u.str = NULL; + } + break; + + case EMS_TK: + case EXS_TK: + case LENGTH_TK: + case ANGLE_TK: + case TIME_TK: + case FREQ_TK: + case PERCENTAGE_TK: + case NUMBER_TK: + case PO_TK: + case PC_TK: + if (a_this->u.num) { + cr_num_destroy (a_this->u.num); + a_this->u.num = NULL; + } + break; + + case DIMEN_TK: + if (a_this->u.num) { + cr_num_destroy (a_this->u.num); + a_this->u.num = NULL; + } + + if (a_this->dimen) { + cr_string_destroy (a_this->dimen); + a_this->dimen = NULL; + } + + break; + + case RGB_TK: + if (a_this->u.rgb) { + cr_rgb_destroy (a_this->u.rgb) ; + a_this->u.rgb = NULL ; + } + break ; + + case UNICODERANGE_TK: + /*not supported yet. */ + break; + + default: + cr_utils_trace_info ("I don't know how to clear this token\n") ; + break; + } + + a_this->type = NO_TK; +} + +/** + *Default constructor of + *the #CRToken class. + *@return the newly built instance of #CRToken. + */ +CRToken * +cr_token_new (void) +{ + CRToken *result = NULL; + + result = g_try_malloc (sizeof (CRToken)); + + if (result == NULL) { + cr_utils_trace_info ("Out of memory"); + return NULL; + } + + memset (result, 0, sizeof (CRToken)); + + return result; +} + +/** + *Sets the type of curren instance of + *#CRToken to 'S_TK' (S in the css2 spec) + *@param a_this the current instance of #CRToken. + *@return CR_OK upon successfull completion, an error + *code otherwise. + */ +enum CRStatus +cr_token_set_s (CRToken * a_this) +{ + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); + + cr_token_clear (a_this); + + a_this->type = S_TK; + + return CR_OK; +} + +/** + *Sets the type of the current instance of + *#CRToken to 'CDO_TK' (CDO as said by the css2 spec) + *@param a_this the current instance of #CRToken. + *@return CR_OK upon successfull completion, an error + *code otherwise. + */ +enum CRStatus +cr_token_set_cdo (CRToken * a_this) +{ + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); + + cr_token_clear (a_this); + + a_this->type = CDO_TK; + + return CR_OK; +} + +/** + *Sets the type of the current token to + *CDC_TK (CDC as said by the css2 spec). + *@param a_this the current instance of #CRToken. + *@return CR_OK upon successfull completion, an error + *code otherwise. + */ +enum CRStatus +cr_token_set_cdc (CRToken * a_this) +{ + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); + + cr_token_clear (a_this); + + a_this->type = CDC_TK; + + return CR_OK; +} + +/** + *Sets the type of the current instance of + *#CRToken to INCLUDES_TK (INCLUDES as said by the css2 spec). + *@param a_this the current instance of #CRToken. + *@return CR_OK upon successfull completion, an error + *code otherwise. + */ +enum CRStatus +cr_token_set_includes (CRToken * a_this) +{ + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); + + cr_token_clear (a_this); + + a_this->type = INCLUDES_TK; + + return CR_OK; +} + +/** + *Sets the type of the current instance of + *#CRToken to DASHMATCH_TK (DASHMATCH as said by the css2 spec). + *@param a_this the current instance of #CRToken. + *@return CR_OK upon successfull completion, an error + *code otherwise. + */ +enum CRStatus +cr_token_set_dashmatch (CRToken * a_this) +{ + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); + + cr_token_clear (a_this); + + a_this->type = DASHMATCH_TK; + + return CR_OK; +} + +enum CRStatus +cr_token_set_comment (CRToken * a_this, CRString * a_str) +{ + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); + + cr_token_clear (a_this); + a_this->type = COMMENT_TK; + a_this->u.str = a_str ; + return CR_OK; +} + +enum CRStatus +cr_token_set_string (CRToken * a_this, CRString * a_str) +{ + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); + + cr_token_clear (a_this); + + a_this->type = STRING_TK; + + a_this->u.str = a_str ; + + return CR_OK; +} + +enum CRStatus +cr_token_set_ident (CRToken * a_this, CRString * a_ident) +{ + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); + + cr_token_clear (a_this); + a_this->type = IDENT_TK; + a_this->u.str = a_ident; + return CR_OK; +} + + +enum CRStatus +cr_token_set_function (CRToken * a_this, CRString * a_fun_name) +{ + g_return_val_if_fail (a_this, + CR_BAD_PARAM_ERROR); + + cr_token_clear (a_this); + a_this->type = FUNCTION_TK; + a_this->u.str = a_fun_name; + return CR_OK; +} + +enum CRStatus +cr_token_set_hash (CRToken * a_this, CRString * a_hash) +{ + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); + + cr_token_clear (a_this); + a_this->type = HASH_TK; + a_this->u.str = a_hash; + + return CR_OK; +} + +enum CRStatus +cr_token_set_rgb (CRToken * a_this, CRRgb * a_rgb) +{ + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); + + cr_token_clear (a_this); + a_this->type = RGB_TK; + a_this->u.rgb = a_rgb; + + return CR_OK; +} + +enum CRStatus +cr_token_set_import_sym (CRToken * a_this) +{ + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); + + cr_token_clear (a_this); + + a_this->type = IMPORT_SYM_TK; + + return CR_OK; +} + +enum CRStatus +cr_token_set_page_sym (CRToken * a_this) +{ + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); + + cr_token_clear (a_this); + + a_this->type = PAGE_SYM_TK; + + return CR_OK; +} + +enum CRStatus +cr_token_set_media_sym (CRToken * a_this) +{ + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); + + cr_token_clear (a_this); + + a_this->type = MEDIA_SYM_TK; + + return CR_OK; +} + +enum CRStatus +cr_token_set_font_face_sym (CRToken * a_this) +{ + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); + + cr_token_clear (a_this); + a_this->type = FONT_FACE_SYM_TK; + + return CR_OK; +} + +enum CRStatus +cr_token_set_charset_sym (CRToken * a_this) +{ + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); + + cr_token_clear (a_this); + a_this->type = CHARSET_SYM_TK; + + return CR_OK; +} + +enum CRStatus +cr_token_set_atkeyword (CRToken * a_this, CRString * a_atname) +{ + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); + + cr_token_clear (a_this); + a_this->type = ATKEYWORD_TK; + a_this->u.str = a_atname; + return CR_OK; +} + +enum CRStatus +cr_token_set_important_sym (CRToken * a_this) +{ + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); + cr_token_clear (a_this); + a_this->type = IMPORTANT_SYM_TK; + return CR_OK; +} + +enum CRStatus +cr_token_set_ems (CRToken * a_this, CRNum * a_num) +{ + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); + cr_token_clear (a_this); + a_this->type = EMS_TK; + a_this->u.num = a_num; + return CR_OK; +} + +enum CRStatus +cr_token_set_exs (CRToken * a_this, CRNum * a_num) +{ + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); + cr_token_clear (a_this); + a_this->type = EXS_TK; + a_this->u.num = a_num; + return CR_OK; +} + +enum CRStatus +cr_token_set_length (CRToken * a_this, CRNum * a_num, + enum CRTokenExtraType a_et) +{ + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); + + cr_token_clear (a_this); + + a_this->type = LENGTH_TK; + a_this->extra_type = a_et; + a_this->u.num = a_num; + + return CR_OK; +} + +enum CRStatus +cr_token_set_angle (CRToken * a_this, CRNum * a_num, + enum CRTokenExtraType a_et) +{ + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); + + cr_token_clear (a_this); + + a_this->type = ANGLE_TK; + a_this->extra_type = a_et; + a_this->u.num = a_num; + + return CR_OK; +} + +enum CRStatus +cr_token_set_time (CRToken * a_this, CRNum * a_num, + enum CRTokenExtraType a_et) +{ + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); + + cr_token_clear (a_this); + + a_this->type = TIME_TK; + a_this->extra_type = a_et; + a_this->u.num = a_num; + + return CR_OK; +} + +enum CRStatus +cr_token_set_freq (CRToken * a_this, CRNum * a_num, + enum CRTokenExtraType a_et) +{ + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); + + cr_token_clear (a_this); + + a_this->type = FREQ_TK; + a_this->extra_type = a_et; + a_this->u.num = a_num; + + return CR_OK; +} + +enum CRStatus +cr_token_set_dimen (CRToken * a_this, CRNum * a_num, + CRString * a_dim) +{ + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); + cr_token_clear (a_this); + a_this->type = DIMEN_TK; + a_this->u.num = a_num; + a_this->dimen = a_dim; + return CR_OK; + +} + +enum CRStatus +cr_token_set_percentage (CRToken * a_this, CRNum * a_num) +{ + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); + + cr_token_clear (a_this); + + a_this->type = PERCENTAGE_TK; + a_this->u.num = a_num; + + return CR_OK; +} + +enum CRStatus +cr_token_set_number (CRToken * a_this, CRNum * a_num) +{ + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); + + cr_token_clear (a_this); + + a_this->type = NUMBER_TK; + a_this->u.num = a_num; + return CR_OK; +} + +enum CRStatus +cr_token_set_uri (CRToken * a_this, CRString * a_uri) +{ + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); + + cr_token_clear (a_this); + + a_this->type = URI_TK; + a_this->u.str = a_uri; + + return CR_OK; +} + +enum CRStatus +cr_token_set_delim (CRToken * a_this, guint32 a_char) +{ + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); + + cr_token_clear (a_this); + + a_this->type = DELIM_TK; + a_this->u.unichar = a_char; + + return CR_OK; +} + +enum CRStatus +cr_token_set_semicolon (CRToken * a_this) +{ + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); + + cr_token_clear (a_this); + + a_this->type = SEMICOLON_TK; + + return CR_OK; +} + +enum CRStatus +cr_token_set_cbo (CRToken * a_this) +{ + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); + + cr_token_clear (a_this); + + a_this->type = CBO_TK; + + return CR_OK; +} + +enum CRStatus +cr_token_set_cbc (CRToken * a_this) +{ + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); + + cr_token_clear (a_this); + + a_this->type = CBC_TK; + + return CR_OK; +} + +enum CRStatus +cr_token_set_po (CRToken * a_this) +{ + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); + + cr_token_clear (a_this); + + a_this->type = PO_TK; + + return CR_OK; +} + +enum CRStatus +cr_token_set_pc (CRToken * a_this) +{ + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); + + cr_token_clear (a_this); + + a_this->type = PC_TK; + + return CR_OK; +} + +enum CRStatus +cr_token_set_bo (CRToken * a_this) +{ + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); + + cr_token_clear (a_this); + + a_this->type = BO_TK; + + return CR_OK; +} + +enum CRStatus +cr_token_set_bc (CRToken * a_this) +{ + g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); + + cr_token_clear (a_this); + + a_this->type = BC_TK; + + return CR_OK; +} + +/** + *The destructor of the #CRToken class. + *@param a_this the current instance of #CRToken. + */ +void +cr_token_destroy (CRToken * a_this) +{ + g_return_if_fail (a_this); + + cr_token_clear (a_this); + + g_free (a_this); +} diff --git a/gettext-tools/gnulib-lib/libcroco/cr-token.h b/gettext-tools/gnulib-lib/libcroco/cr-token.h new file mode 100644 index 0000000..4009cd1 --- /dev/null +++ b/gettext-tools/gnulib-lib/libcroco/cr-token.h @@ -0,0 +1,212 @@ +/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */ + +/* + * This file is part of The Croco Library + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + * Author: Dodji Seketeli + * See COPYRIGHTS file for copyright information. + */ + +#ifndef __CR_TOKEN_H__ +#define __CR_TOKEN_H__ + +#include "cr-utils.h" +#include "cr-input.h" +#include "cr-num.h" +#include "cr-rgb.h" +#include "cr-string.h" +#include "cr-parsing-location.h" + +G_BEGIN_DECLS + +enum CRTokenType +{ + NO_TK, + S_TK, + CDO_TK, + CDC_TK, + INCLUDES_TK, + DASHMATCH_TK, + COMMENT_TK, + STRING_TK, + IDENT_TK, + HASH_TK, + IMPORT_SYM_TK, + PAGE_SYM_TK, + MEDIA_SYM_TK, + FONT_FACE_SYM_TK, + CHARSET_SYM_TK, + ATKEYWORD_TK, + IMPORTANT_SYM_TK, + EMS_TK, + EXS_TK, + LENGTH_TK, + ANGLE_TK, + TIME_TK, + FREQ_TK, + DIMEN_TK, + PERCENTAGE_TK, + NUMBER_TK, + RGB_TK, + URI_TK, + FUNCTION_TK, + UNICODERANGE_TK, + SEMICOLON_TK, + CBO_TK, /*opening curly bracket*/ + CBC_TK, /*closing curly bracket*/ + PO_TK, /*opening parenthesis*/ + PC_TK, /*closing parenthesis*/ + BO_TK, /*opening bracket*/ + BC_TK, /*closing bracket*/ + DELIM_TK +} ; + +enum CRTokenExtraType +{ + NO_ET = 0, + LENGTH_PX_ET, + LENGTH_CM_ET, + LENGTH_MM_ET, + LENGTH_IN_ET, + LENGTH_PT_ET, + LENGTH_PC_ET, + ANGLE_DEG_ET, + ANGLE_RAD_ET, + ANGLE_GRAD_ET, + TIME_MS_ET, + TIME_S_ET, + FREQ_HZ_ET, + FREQ_KHZ_ET +} ; + +typedef struct _CRToken CRToken ; + +/** + *This class abstracts a css2 token. + */ +struct _CRToken +{ + enum CRTokenType type ; + enum CRTokenExtraType extra_type ; + CRInputPos pos ; + + union + { + CRString *str ; + CRRgb *rgb ; + CRNum *num ; + guint32 unichar ; + } u ; + + CRString * dimen ; + CRParsingLocation location ; +} ; + +CRToken* cr_token_new (void) ; + +enum CRStatus cr_token_set_s (CRToken *a_this) ; + +enum CRStatus cr_token_set_cdo (CRToken *a_this) ; + +enum CRStatus cr_token_set_cdc (CRToken *a_this) ; + +enum CRStatus cr_token_set_includes (CRToken *a_this) ; + +enum CRStatus cr_token_set_dashmatch (CRToken *a_this) ; + +enum CRStatus cr_token_set_comment (CRToken *a_this, CRString *a_str) ; + +enum CRStatus cr_token_set_string (CRToken *a_this, CRString *a_str) ; + +enum CRStatus cr_token_set_ident (CRToken *a_this, CRString * a_ident) ; + +enum CRStatus cr_token_set_hash (CRToken *a_this, CRString *a_hash) ; + +enum CRStatus cr_token_set_rgb (CRToken *a_this, CRRgb *a_rgb) ; + +enum CRStatus cr_token_set_import_sym (CRToken *a_this) ; + +enum CRStatus cr_token_set_page_sym (CRToken *a_this) ; + +enum CRStatus cr_token_set_media_sym (CRToken *a_this) ; + +enum CRStatus cr_token_set_font_face_sym (CRToken *a_this) ; + +enum CRStatus cr_token_set_charset_sym (CRToken *a_this) ; + +enum CRStatus cr_token_set_atkeyword (CRToken *a_this, CRString *a_atname) ; + +enum CRStatus cr_token_set_important_sym (CRToken *a_this) ; + +enum CRStatus cr_token_set_ems (CRToken *a_this, CRNum *a_num) ; + +enum CRStatus cr_token_set_exs (CRToken *a_this, CRNum *a_num) ; + +enum CRStatus cr_token_set_length (CRToken *a_this, CRNum *a_num, + enum CRTokenExtraType a_et) ; + +enum CRStatus cr_token_set_angle (CRToken *a_this, CRNum *a_num, + enum CRTokenExtraType a_et) ; + +enum CRStatus cr_token_set_time (CRToken *a_this, CRNum *a_num, + enum CRTokenExtraType a_et) ; + +enum CRStatus cr_token_set_freq (CRToken *a_this, CRNum *a_num, + enum CRTokenExtraType a_et) ; + +enum CRStatus cr_token_set_dimen (CRToken *a_this, CRNum *a_num, + CRString *a_dim) ; + +enum CRStatus cr_token_set_percentage (CRToken *a_this, CRNum *a_num) ; + +enum CRStatus cr_token_set_number (CRToken *a_this, CRNum *a_num) ; + +enum CRStatus cr_token_set_uri (CRToken *a_this, CRString *a_uri) ; + +enum CRStatus cr_token_set_function (CRToken *a_this, + CRString *a_fun_name) ; + +enum CRStatus cr_token_set_bc (CRToken *a_this) ; + +enum CRStatus cr_token_set_bo (CRToken *a_this) ; + +enum CRStatus cr_token_set_po (CRToken *a_this) ; + +enum CRStatus cr_token_set_pc (CRToken *a_this) ; + +enum CRStatus cr_token_set_cbc (CRToken *a_this) ; + +enum CRStatus cr_token_set_cbo (CRToken *a_this) ; + +enum CRStatus cr_token_set_semicolon (CRToken *a_this) ; + +enum CRStatus cr_token_set_delim (CRToken *a_this, guint32 a_char) ; + + +/* + enum CRStatus + cr_token_set_unicoderange (CRToken *a_this, + CRUnicodeRange *a_range) ; +*/ + +void +cr_token_destroy (CRToken *a_this) ; + + +G_END_DECLS + +#endif /*__CR_TOKEN_H__*/ diff --git a/gettext-tools/gnulib-lib/libcroco/cr-utils.c b/gettext-tools/gnulib-lib/libcroco/cr-utils.c new file mode 100644 index 0000000..423027f --- /dev/null +++ b/gettext-tools/gnulib-lib/libcroco/cr-utils.c @@ -0,0 +1,1357 @@ +/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8 -*- */ + +/* + * This file is part of The Croco Library + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + * Author: Dodji Seketeli + * See COPYRIGHTS file for copyright information. + */ + +#include +#include "cr-utils.h" +#include "cr-string.h" + +/** + *@file: + *Some misc utility functions used + *in the libcroco. + *Note that troughout this file I will + *refer to the CSS SPECIFICATIONS DOCUMENTATION + *written by the w3c guys. You can find that document + *at http://www.w3.org/TR/REC-CSS2/ . + */ + +/**************************** + *Encoding transformations and + *encoding helpers + ****************************/ + +/* + *Here is the correspondance between the ucs-4 charactere codes + *and there matching utf-8 encoding pattern as dscribed by RFC 2279: + * + *UCS-4 range (hex.) UTF-8 octet sequence (binary) + *------------------ ----------------------------- + *0000 0000-0000 007F 0xxxxxxx + *0000 0080-0000 07FF 110xxxxx 10xxxxxx + *0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx + *0001 0000-001F FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + *0020 0000-03FF FFFF 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx + *0400 0000-7FFF FFFF 1111110x 10xxxxxx ... 10xxxxxx + */ + +/** + *Given an utf8 string buffer, calculates + *the length of this string if it was encoded + *in ucs4. + *@param a_in_start a pointer to the begining of + *the input utf8 string. + *@param a_in_end a pointre to the end of the input + *utf8 string (points to the last byte of the buffer) + *@param a_len out parameter the calculated length. + *@return CR_OK upon succesfull completion, an error code + *otherwise. + */ +enum CRStatus +cr_utils_utf8_str_len_as_ucs4 (const guchar * a_in_start, + const guchar * a_in_end, gulong * a_len) +{ + guchar *byte_ptr = NULL; + gint len = 0; + + /* + *to store the final decoded + *unicode char + */ + guint c = 0; + + g_return_val_if_fail (a_in_start && a_in_end && a_len, + CR_BAD_PARAM_ERROR); + *a_len = 0; + + for (byte_ptr = (guchar *) a_in_start; + byte_ptr <= a_in_end; byte_ptr++) { + gint nb_bytes_2_decode = 0; + + if (*byte_ptr <= 0x7F) { + /* + *7 bits long char + *encoded over 1 byte: + * 0xxx xxxx + */ + c = *byte_ptr; + nb_bytes_2_decode = 1; + + } else if ((*byte_ptr & 0xE0) == 0xC0) { + /* + *up to 11 bits long char. + *encoded over 2 bytes: + *110x xxxx 10xx xxxx + */ + c = *byte_ptr & 0x1F; + nb_bytes_2_decode = 2; + + } else if ((*byte_ptr & 0xF0) == 0xE0) { + /* + *up to 16 bit long char + *encoded over 3 bytes: + *1110 xxxx 10xx xxxx 10xx xxxx + */ + c = *byte_ptr & 0x0F; + nb_bytes_2_decode = 3; + + } else if ((*byte_ptr & 0xF8) == 0xF0) { + /* + *up to 21 bits long char + *encoded over 4 bytes: + *1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx + */ + c = *byte_ptr & 0x7; + nb_bytes_2_decode = 4; + + } else if ((*byte_ptr & 0xFC) == 0xF8) { + /* + *up to 26 bits long char + *encoded over 5 bytes. + *1111 10xx 10xx xxxx 10xx xxxx + *10xx xxxx 10xx xxxx + */ + c = *byte_ptr & 3; + nb_bytes_2_decode = 5; + + } else if ((*byte_ptr & 0xFE) == 0xFC) { + /* + *up to 31 bits long char + *encoded over 6 bytes: + *1111 110x 10xx xxxx 10xx xxxx + *10xx xxxx 10xx xxxx 10xx xxxx + */ + c = *byte_ptr & 1; + nb_bytes_2_decode = 6; + + } else { + /* + *BAD ENCODING + */ + return CR_ENCODING_ERROR; + } + + /* + *Go and decode the remaining byte(s) + *(if any) to get the current character. + */ + for (; nb_bytes_2_decode > 1; nb_bytes_2_decode--) { + /*decode the next byte */ + byte_ptr++; + + /*byte pattern must be: 10xx xxxx */ + if ((*byte_ptr & 0xC0) != 0x80) { + return CR_ENCODING_ERROR; + } + + c = (c << 6) | (*byte_ptr & 0x3F); + } + + len++; + } + + *a_len = len; + + return CR_OK; +} + +/** + *Given an ucs4 string, this function + *returns the size (in bytes) this string + *would have occupied if it was encoded in utf-8. + *@param a_in_start a pointer to the beginning of the input + *buffer. + *@param a_in_end a pointer to the end of the input buffer. + *@param a_len out parameter. The computed length. + *@return CR_OK upon successfull completion, an error code otherwise. + */ +enum CRStatus +cr_utils_ucs4_str_len_as_utf8 (const guint32 * a_in_start, + const guint32 * a_in_end, gulong * a_len) +{ + gint len = 0; + guint32 *char_ptr = NULL; + + g_return_val_if_fail (a_in_start && a_in_end && a_len, + CR_BAD_PARAM_ERROR); + + for (char_ptr = (guint32 *) a_in_start; + char_ptr <= a_in_end; char_ptr++) { + if (*char_ptr <= 0x7F) { + /*the utf-8 char would take 1 byte */ + len += 1; + } else if (*char_ptr <= 0x7FF) { + /*the utf-8 char would take 2 bytes */ + len += 2; + } else if (*char_ptr <= 0xFFFF) { + len += 3; + } else if (*char_ptr <= 0x1FFFFF) { + len += 4; + } else if (*char_ptr <= 0x3FFFFFF) { + len += 5; + } else if (*char_ptr <= 0x7FFFFFFF) { + len += 6; + } + } + + *a_len = len; + return CR_OK; +} + +/** + *Given an ucsA string, this function + *returns the size (in bytes) this string + *would have occupied if it was encoded in utf-8. + *@param a_in_start a pointer to the beginning of the input + *buffer. + *@param a_in_end a pointer to the end of the input buffer. + *@param a_len out parameter. The computed length. + *@return CR_OK upon successfull completion, an error code otherwise. + */ +enum CRStatus +cr_utils_ucs1_str_len_as_utf8 (const guchar * a_in_start, + const guchar * a_in_end, gulong * a_len) +{ + gint len = 0; + guchar *char_ptr = NULL; + + g_return_val_if_fail (a_in_start && a_in_end && a_len, + CR_BAD_PARAM_ERROR); + + for (char_ptr = (guchar *) a_in_start; + char_ptr <= a_in_end; char_ptr++) { + if (*char_ptr <= 0x7F) { + /*the utf-8 char would take 1 byte */ + len += 1; + } else { + /*the utf-8 char would take 2 bytes */ + len += 2; + } + } + + *a_len = len; + return CR_OK; +} + +/** + *Converts an utf8 buffer into an ucs4 buffer. + * + *@param a_in the input utf8 buffer to convert. + *@param a_in_len in/out parameter. The size of the + *input buffer to convert. After return, this parameter contains + *the actual number of bytes consumed. + *@param a_out the output converted ucs4 buffer. Must be allocated by + *the caller. + *@param a_out_len in/out parameter. The size of the output buffer. + *If this size is actually smaller than the real needed size, the function + *just converts what it can and returns a success status. After return, + *this param points to the actual number of characters decoded. + *@return CR_OK upon successfull completion, an error code otherwise. + */ +enum CRStatus +cr_utils_utf8_to_ucs4 (const guchar * a_in, + gulong * a_in_len, guint32 * a_out, gulong * a_out_len) +{ + gulong in_len = 0, + out_len = 0, + in_index = 0, + out_index = 0; + enum CRStatus status = CR_OK; + + /* + *to store the final decoded + *unicode char + */ + guint c = 0; + + g_return_val_if_fail (a_in && a_in_len + && a_out && a_out_len, CR_BAD_PARAM_ERROR); + + if (*a_in_len < 1) { + status = CR_OK; + goto end; + } + + in_len = *a_in_len; + out_len = *a_out_len; + + for (in_index = 0, out_index = 0; + (in_index < in_len) && (out_index < out_len); + in_index++, out_index++) { + gint nb_bytes_2_decode = 0; + + if (a_in[in_index] <= 0x7F) { + /* + *7 bits long char + *encoded over 1 byte: + * 0xxx xxxx + */ + c = a_in[in_index]; + nb_bytes_2_decode = 1; + + } else if ((a_in[in_index] & 0xE0) == 0xC0) { + /* + *up to 11 bits long char. + *encoded over 2 bytes: + *110x xxxx 10xx xxxx + */ + c = a_in[in_index] & 0x1F; + nb_bytes_2_decode = 2; + + } else if ((a_in[in_index] & 0xF0) == 0xE0) { + /* + *up to 16 bit long char + *encoded over 3 bytes: + *1110 xxxx 10xx xxxx 10xx xxxx + */ + c = a_in[in_index] & 0x0F; + nb_bytes_2_decode = 3; + + } else if ((a_in[in_index] & 0xF8) == 0xF0) { + /* + *up to 21 bits long char + *encoded over 4 bytes: + *1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx + */ + c = a_in[in_index] & 0x7; + nb_bytes_2_decode = 4; + + } else if ((a_in[in_index] & 0xFC) == 0xF8) { + /* + *up to 26 bits long char + *encoded over 5 bytes. + *1111 10xx 10xx xxxx 10xx xxxx + *10xx xxxx 10xx xxxx + */ + c = a_in[in_index] & 3; + nb_bytes_2_decode = 5; + + } else if ((a_in[in_index] & 0xFE) == 0xFC) { + /* + *up to 31 bits long char + *encoded over 6 bytes: + *1111 110x 10xx xxxx 10xx xxxx + *10xx xxxx 10xx xxxx 10xx xxxx + */ + c = a_in[in_index] & 1; + nb_bytes_2_decode = 6; + + } else { + /*BAD ENCODING */ + goto end; + } + + /* + *Go and decode the remaining byte(s) + *(if any) to get the current character. + */ + for (; nb_bytes_2_decode > 1; nb_bytes_2_decode--) { + /*decode the next byte */ + in_index++; + + /*byte pattern must be: 10xx xxxx */ + if ((a_in[in_index] & 0xC0) != 0x80) { + goto end; + } + + c = (c << 6) | (a_in[in_index] & 0x3F); + } + + /* + *The decoded ucs4 char is now + *in c. + */ + + /************************ + *Some security tests + ***********************/ + + /*be sure c is a char */ + if (c == 0xFFFF || c == 0xFFFE) + goto end; + + /*be sure c is inferior to the max ucs4 char value */ + if (c > 0x10FFFF) + goto end; + + /* + *c must be less than UTF16 "lower surrogate begin" + *or higher than UTF16 "High surrogate end" + */ + if (c >= 0xD800 && c <= 0xDFFF) + goto end; + + /*Avoid characters that equals zero */ + if (c == 0) + goto end; + + a_out[out_index] = c; + } + + end: + *a_out_len = out_index + 1; + *a_in_len = in_index + 1; + + return status; +} + +/** + *Reads a character from an utf8 buffer. + *Actually decode the next character code (unicode character code) + *and returns it. + *@param a_in the starting address of the utf8 buffer. + *@param a_in_len the length of the utf8 buffer. + *@param a_out output parameter. The resulting read char. + *@param a_consumed the number of the bytes consumed to + *decode the returned character code. + *@return CR_OK upon successfull completion, an error code otherwise. + */ +enum CRStatus +cr_utils_read_char_from_utf8_buf (const guchar * a_in, + gulong a_in_len, + guint32 * a_out, gulong * a_consumed) +{ + gulong in_len = 0, + in_index = 0, + nb_bytes_2_decode = 0; + enum CRStatus status = CR_OK; + + /* + *to store the final decoded + *unicode char + */ + guint32 c = 0; + + g_return_val_if_fail (a_in && a_out && a_out + && a_consumed, CR_BAD_PARAM_ERROR); + + if (a_in_len < 1) { + status = CR_OK; + goto end; + } + + in_len = a_in_len; + + if (*a_in <= 0x7F) { + /* + *7 bits long char + *encoded over 1 byte: + * 0xxx xxxx + */ + c = *a_in; + nb_bytes_2_decode = 1; + + } else if ((*a_in & 0xE0) == 0xC0) { + /* + *up to 11 bits long char. + *encoded over 2 bytes: + *110x xxxx 10xx xxxx + */ + c = *a_in & 0x1F; + nb_bytes_2_decode = 2; + + } else if ((*a_in & 0xF0) == 0xE0) { + /* + *up to 16 bit long char + *encoded over 3 bytes: + *1110 xxxx 10xx xxxx 10xx xxxx + */ + c = *a_in & 0x0F; + nb_bytes_2_decode = 3; + + } else if ((*a_in & 0xF8) == 0xF0) { + /* + *up to 21 bits long char + *encoded over 4 bytes: + *1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx + */ + c = *a_in & 0x7; + nb_bytes_2_decode = 4; + + } else if ((*a_in & 0xFC) == 0xF8) { + /* + *up to 26 bits long char + *encoded over 5 bytes. + *1111 10xx 10xx xxxx 10xx xxxx + *10xx xxxx 10xx xxxx + */ + c = *a_in & 3; + nb_bytes_2_decode = 5; + + } else if ((*a_in & 0xFE) == 0xFC) { + /* + *up to 31 bits long char + *encoded over 6 bytes: + *1111 110x 10xx xxxx 10xx xxxx + *10xx xxxx 10xx xxxx 10xx xxxx + */ + c = *a_in & 1; + nb_bytes_2_decode = 6; + + } else { + /*BAD ENCODING */ + goto end; + } + + if (nb_bytes_2_decode > a_in_len) { + status = CR_END_OF_INPUT_ERROR; + goto end; + } + + /* + *Go and decode the remaining byte(s) + *(if any) to get the current character. + */ + for (in_index = 1; in_index < nb_bytes_2_decode; in_index++) { + /*byte pattern must be: 10xx xxxx */ + if ((a_in[in_index] & 0xC0) != 0x80) { + goto end; + } + + c = (c << 6) | (a_in[in_index] & 0x3F); + } + + /* + *The decoded ucs4 char is now + *in c. + */ + + /************************ + *Some security tests + ***********************/ + + /*be sure c is a char */ + if (c == 0xFFFF || c == 0xFFFE) + goto end; + + /*be sure c is inferior to the max ucs4 char value */ + if (c > 0x10FFFF) + goto end; + + /* + *c must be less than UTF16 "lower surrogate begin" + *or higher than UTF16 "High surrogate end" + */ + if (c >= 0xD800 && c <= 0xDFFF) + goto end; + + /*Avoid characters that equals zero */ + if (c == 0) + goto end; + + *a_out = c; + + end: + *a_consumed = nb_bytes_2_decode; + + return status; +} + +/** + * + */ +enum CRStatus +cr_utils_utf8_str_len_as_ucs1 (const guchar * a_in_start, + const guchar * a_in_end, gulong * a_len) +{ + /* + *Note: this function can be made shorter + *but it considers all the cases of the utf8 encoding + *to ease further extensions ... + */ + + guchar *byte_ptr = NULL; + gint len = 0; + + /* + *to store the final decoded + *unicode char + */ + guint c = 0; + + g_return_val_if_fail (a_in_start && a_in_end && a_len, + CR_BAD_PARAM_ERROR); + *a_len = 0; + + for (byte_ptr = (guchar *) a_in_start; + byte_ptr <= a_in_end; byte_ptr++) { + gint nb_bytes_2_decode = 0; + + if (*byte_ptr <= 0x7F) { + /* + *7 bits long char + *encoded over 1 byte: + * 0xxx xxxx + */ + c = *byte_ptr; + nb_bytes_2_decode = 1; + + } else if ((*byte_ptr & 0xE0) == 0xC0) { + /* + *up to 11 bits long char. + *encoded over 2 bytes: + *110x xxxx 10xx xxxx + */ + c = *byte_ptr & 0x1F; + nb_bytes_2_decode = 2; + + } else if ((*byte_ptr & 0xF0) == 0xE0) { + /* + *up to 16 bit long char + *encoded over 3 bytes: + *1110 xxxx 10xx xxxx 10xx xxxx + */ + c = *byte_ptr & 0x0F; + nb_bytes_2_decode = 3; + + } else if ((*byte_ptr & 0xF8) == 0xF0) { + /* + *up to 21 bits long char + *encoded over 4 bytes: + *1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx + */ + c = *byte_ptr & 0x7; + nb_bytes_2_decode = 4; + + } else if ((*byte_ptr & 0xFC) == 0xF8) { + /* + *up to 26 bits long char + *encoded over 5 bytes. + *1111 10xx 10xx xxxx 10xx xxxx + *10xx xxxx 10xx xxxx + */ + c = *byte_ptr & 3; + nb_bytes_2_decode = 5; + + } else if ((*byte_ptr & 0xFE) == 0xFC) { + /* + *up to 31 bits long char + *encoded over 6 bytes: + *1111 110x 10xx xxxx 10xx xxxx + *10xx xxxx 10xx xxxx 10xx xxxx + */ + c = *byte_ptr & 1; + nb_bytes_2_decode = 6; + + } else { + /* + *BAD ENCODING + */ + return CR_ENCODING_ERROR; + } + + /* + *Go and decode the remaining byte(s) + *(if any) to get the current character. + */ + for (; nb_bytes_2_decode > 1; nb_bytes_2_decode--) { + /*decode the next byte */ + byte_ptr++; + + /*byte pattern must be: 10xx xxxx */ + if ((*byte_ptr & 0xC0) != 0x80) { + return CR_ENCODING_ERROR; + } + + c = (c << 6) | (*byte_ptr & 0x3F); + } + + /* + *The decoded ucs4 char is now + *in c. + */ + + if (c <= 0xFF) { /*Add other conditions to support + *other char sets (ucs2, ucs3, ucs4). + */ + len++; + } else { + /*the char is too long to fit + *into the supposed charset len. + */ + return CR_ENCODING_ERROR; + } + } + + *a_len = len; + + return CR_OK; +} + +/** + *Converts an utf8 string into an ucs4 string. + *@param a_in the input string to convert. + *@param a_in_len in/out parameter. The length of the input + *string. After return, points to the actual number of bytes + *consumed. This can be usefull to debug the input stream in case + *of encoding error. + *@param a_out out parameter. Points to the output string. It is allocated + *by this function and must be freed by the caller. + *@param a_out_len out parameter. The length of the output string. + *@return CR_OK upon successfull completion, an error code otherwise. + * + */ +enum CRStatus +cr_utils_utf8_str_to_ucs4 (const guchar * a_in, + gulong * a_in_len, + guint32 ** a_out, gulong * a_out_len) +{ + enum CRStatus status = CR_OK; + + g_return_val_if_fail (a_in && a_in_len + && a_out && a_out_len, CR_BAD_PARAM_ERROR); + + status = cr_utils_utf8_str_len_as_ucs4 (a_in, + &a_in[*a_in_len - 1], + a_out_len); + + g_return_val_if_fail (status == CR_OK, status); + + *a_out = g_malloc0 (*a_out_len * sizeof (guint32)); + + status = cr_utils_utf8_to_ucs4 (a_in, a_in_len, *a_out, a_out_len); + + return status; +} + +/** + *Converts an ucs4 buffer into an utf8 buffer. + * + *@param a_in the input ucs4 buffer to convert. + *@param a_in_len in/out parameter. The size of the + *input buffer to convert. After return, this parameter contains + *the actual number of characters consumed. + *@param a_out the output converted utf8 buffer. Must be allocated by + *the caller. + *@param a_out_len in/out parameter. The size of the output buffer. + *If this size is actually smaller than the real needed size, the function + *just converts what it can and returns a success status. After return, + *this param points to the actual number of bytes in the buffer. + *@return CR_OK upon successfull completion, an error code otherwise. + */ +enum CRStatus +cr_utils_ucs4_to_utf8 (const guint32 * a_in, + gulong * a_in_len, guchar * a_out, gulong * a_out_len) +{ + gulong in_len = 0, + in_index = 0, + out_index = 0; + enum CRStatus status = CR_OK; + + g_return_val_if_fail (a_in && a_in_len && a_out && a_out_len, + CR_BAD_PARAM_ERROR); + + if (*a_in_len < 1) { + status = CR_OK; + goto end; + } + + in_len = *a_in_len; + + for (in_index = 0; in_index < in_len; in_index++) { + /* + *FIXME: return whenever we encounter forbidden char values. + */ + + if (a_in[in_index] <= 0x7F) { + a_out[out_index] = a_in[in_index]; + out_index++; + } else if (a_in[in_index] <= 0x7FF) { + a_out[out_index] = (0xC0 | (a_in[in_index] >> 6)); + a_out[out_index + 1] = + (0x80 | (a_in[in_index] & 0x3F)); + out_index += 2; + } else if (a_in[in_index] <= 0xFFFF) { + a_out[out_index] = (0xE0 | (a_in[in_index] >> 12)); + a_out[out_index + 1] = + (0x80 | ((a_in[in_index] >> 6) & 0x3F)); + a_out[out_index + 2] = + (0x80 | (a_in[in_index] & 0x3F)); + out_index += 3; + } else if (a_in[in_index] <= 0x1FFFFF) { + a_out[out_index] = (0xF0 | (a_in[in_index] >> 18)); + a_out[out_index + 1] + = (0x80 | ((a_in[in_index] >> 12) & 0x3F)); + a_out[out_index + 2] + = (0x80 | ((a_in[in_index] >> 6) & 0x3F)); + a_out[out_index + 3] + = (0x80 | (a_in[in_index] & 0x3F)); + out_index += 4; + } else if (a_in[in_index] <= 0x3FFFFFF) { + a_out[out_index] = (0xF8 | (a_in[in_index] >> 24)); + a_out[out_index + 1] = + (0x80 | (a_in[in_index] >> 18)); + a_out[out_index + 2] + = (0x80 | ((a_in[in_index] >> 12) & 0x3F)); + a_out[out_index + 3] + = (0x80 | ((a_in[in_index] >> 6) & 0x3F)); + a_out[out_index + 4] + = (0x80 | (a_in[in_index] & 0x3F)); + out_index += 5; + } else if (a_in[in_index] <= 0x7FFFFFFF) { + a_out[out_index] = (0xFC | (a_in[in_index] >> 30)); + a_out[out_index + 1] = + (0x80 | (a_in[in_index] >> 24)); + a_out[out_index + 2] + = (0x80 | ((a_in[in_index] >> 18) & 0x3F)); + a_out[out_index + 3] + = (0x80 | ((a_in[in_index] >> 12) & 0x3F)); + a_out[out_index + 4] + = (0x80 | ((a_in[in_index] >> 6) & 0x3F)); + a_out[out_index + 4] + = (0x80 | (a_in[in_index] & 0x3F)); + out_index += 6; + } else { + status = CR_ENCODING_ERROR; + goto end; + } + } /*end for */ + + end: + *a_in_len = in_index + 1; + *a_out_len = out_index + 1; + + return status; +} + +/** + *Converts an ucs4 string into an utf8 string. + *@param a_in the input string to convert. + *@param a_in_len in/out parameter. The length of the input + *string. After return, points to the actual number of characters + *consumed. This can be usefull to debug the input string in case + *of encoding error. + *@param a_out out parameter. Points to the output string. It is allocated + *by this function and must be freed by the caller. + *@param a_out_len out parameter. The length (in bytes) of the output string. + *@return CR_OK upon successfull completion, an error code otherwise. + */ +enum CRStatus +cr_utils_ucs4_str_to_utf8 (const guint32 * a_in, + gulong * a_in_len, + guchar ** a_out, gulong * a_out_len) +{ + enum CRStatus status = CR_OK; + + g_return_val_if_fail (a_in && a_in_len && a_out + && a_out_len, CR_BAD_PARAM_ERROR); + + status = cr_utils_ucs4_str_len_as_utf8 (a_in, + &a_in[*a_out_len - 1], + a_out_len); + + g_return_val_if_fail (status == CR_OK, status); + + status = cr_utils_ucs4_to_utf8 (a_in, a_in_len, *a_out, a_out_len); + + return status; +} + +/** + *Converts an ucs1 buffer into an utf8 buffer. + *The caller must know the size of the resulting buffer and + *allocate it prior to calling this function. + * + *@param a_in the input ucs1 buffer. + * + *@param a_in_len in/out parameter. The length of the input buffer. + *After return, points to the number of bytes actually consumed even + *in case of encoding error. + * + *@param a_out out parameter. The output utf8 converted buffer. + * + *@param a_out_len in/out parameter. The size of the output buffer. + *If the output buffer size is shorter than the actual needed size, + *this function just convert what it can. + * + *@return CR_OK upon successfull completion, an error code otherwise. + * + */ +enum CRStatus +cr_utils_ucs1_to_utf8 (const guchar * a_in, + gulong * a_in_len, guchar * a_out, gulong * a_out_len) +{ + gulong out_index = 0, + in_index = 0, + in_len = 0, + out_len = 0; + enum CRStatus status = CR_OK; + + g_return_val_if_fail (a_in && a_in_len + && a_out_len, + CR_BAD_PARAM_ERROR); + + if (*a_in_len == 0) { + *a_out_len = 0 ; + return CR_OK ; + } + g_return_val_if_fail (a_out, CR_BAD_PARAM_ERROR) ; + + if (*a_in_len < 1) { + status = CR_OK; + goto end; + } + + in_len = *a_in_len; + out_len = *a_out_len; + + for (in_index = 0, out_index = 0; + (in_index < in_len) && (out_index < out_len); in_index++) { + /* + *FIXME: return whenever we encounter forbidden char values. + */ + + if (a_in[in_index] <= 0x7F) { + a_out[out_index] = a_in[in_index]; + out_index++; + } else { + a_out[out_index] = (0xC0 | (a_in[in_index] >> 6)); + a_out[out_index + 1] = + (0x80 | (a_in[in_index] & 0x3F)); + out_index += 2; + } + } /*end for */ + + end: + *a_in_len = in_index; + *a_out_len = out_index; + + return CR_OK; +} + +/** + *Converts an ucs1 string into an utf8 string. + *@param a_in_start the beginning of the input string to convert. + *@param a_in_end the end of the input string to convert. + *@param a_out out parameter. The converted string. + *@param a_out out parameter. The length of the converted string. + *@return CR_OK upon successfull completion, an error code otherwise. + * + */ +enum CRStatus +cr_utils_ucs1_str_to_utf8 (const guchar * a_in, + gulong * a_in_len, + guchar ** a_out, gulong * a_out_len) +{ + gulong in_len = 0, + out_len = 0; + enum CRStatus status = CR_OK; + + g_return_val_if_fail (a_in && a_in_len && a_out + && a_out_len, CR_BAD_PARAM_ERROR); + + if (*a_in_len < 1) { + *a_out_len = 0; + *a_out = NULL; + return CR_OK; + } + + status = cr_utils_ucs1_str_len_as_utf8 (a_in, &a_in[*a_in_len - 1], + &out_len); + + g_return_val_if_fail (status == CR_OK, status); + + in_len = *a_in_len; + + *a_out = g_malloc0 (out_len); + + status = cr_utils_ucs1_to_utf8 (a_in, a_in_len, *a_out, &out_len); + + *a_out_len = out_len; + + return status; +} + +/** + *Converts an utf8 buffer into an ucs1 buffer. + *The caller must know the size of the resulting + *converted buffer, and allocated it prior to calling this + *function. + * + *@param a_in the input utf8 buffer to convert. + * + *@param a_in_len in/out parameter. The size of the input utf8 buffer. + *After return, points to the number of bytes consumed + *by the function even in case of encoding error. + * + *@param a_out out parameter. Points to the resulting buffer. + *Must be allocated by the caller. If the size of a_out is shorter + *than its required size, this function converts what it can and return + *a successfull status. + * + *@param a_out_len in/out parameter. The size of the output buffer. + *After return, points to the number of bytes consumed even in case of + *encoding error. + * + *@return CR_OK upon successfull completion, an error code otherwise. + */ +enum CRStatus +cr_utils_utf8_to_ucs1 (const guchar * a_in, + gulong * a_in_len, guchar * a_out, gulong * a_out_len) +{ + gulong in_index = 0, + out_index = 0, + in_len = 0, + out_len = 0; + enum CRStatus status = CR_OK; + + /* + *to store the final decoded + *unicode char + */ + guint32 c = 0; + + g_return_val_if_fail (a_in && a_in_len + && a_out && a_out_len, CR_BAD_PARAM_ERROR); + + if (*a_in_len < 1) { + status = CR_OK; + goto end; + } + + in_len = *a_in_len; + out_len = *a_out_len; + + for (in_index = 0, out_index = 0; + (in_index < in_len) && (out_index < out_len); + in_index++, out_index++) { + gint nb_bytes_2_decode = 0; + + if (a_in[in_index] <= 0x7F) { + /* + *7 bits long char + *encoded over 1 byte: + * 0xxx xxxx + */ + c = a_in[in_index]; + nb_bytes_2_decode = 1; + + } else if ((a_in[in_index] & 0xE0) == 0xC0) { + /* + *up to 11 bits long char. + *encoded over 2 bytes: + *110x xxxx 10xx xxxx + */ + c = a_in[in_index] & 0x1F; + nb_bytes_2_decode = 2; + + } else if ((a_in[in_index] & 0xF0) == 0xE0) { + /* + *up to 16 bit long char + *encoded over 3 bytes: + *1110 xxxx 10xx xxxx 10xx xxxx + */ + c = a_in[in_index] & 0x0F; + nb_bytes_2_decode = 3; + + } else if ((a_in[in_index] & 0xF8) == 0xF0) { + /* + *up to 21 bits long char + *encoded over 4 bytes: + *1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx + */ + c = a_in[in_index] & 0x7; + nb_bytes_2_decode = 4; + + } else if ((a_in[in_index] & 0xFC) == 0xF8) { + /* + *up to 26 bits long char + *encoded over 5 bytes. + *1111 10xx 10xx xxxx 10xx xxxx + *10xx xxxx 10xx xxxx + */ + c = a_in[in_index] & 3; + nb_bytes_2_decode = 5; + + } else if ((a_in[in_index] & 0xFE) == 0xFC) { + /* + *up to 31 bits long char + *encoded over 6 bytes: + *1111 110x 10xx xxxx 10xx xxxx + *10xx xxxx 10xx xxxx 10xx xxxx + */ + c = a_in[in_index] & 1; + nb_bytes_2_decode = 6; + + } else { + /*BAD ENCODING */ + status = CR_ENCODING_ERROR; + goto end; + } + + /* + *Go and decode the remaining byte(s) + *(if any) to get the current character. + */ + if (in_index + nb_bytes_2_decode - 1 >= in_len) { + status = CR_OK; + goto end; + } + + for (; nb_bytes_2_decode > 1; nb_bytes_2_decode--) { + /*decode the next byte */ + in_index++; + + /*byte pattern must be: 10xx xxxx */ + if ((a_in[in_index] & 0xC0) != 0x80) { + status = CR_ENCODING_ERROR; + goto end; + } + + c = (c << 6) | (a_in[in_index] & 0x3F); + } + + /* + *The decoded ucs4 char is now + *in c. + */ + + if (c > 0xFF) { + status = CR_ENCODING_ERROR; + goto end; + } + + a_out[out_index] = c; + } + + end: + *a_out_len = out_index; + *a_in_len = in_index; + + return CR_OK; +} + +/** + *Converts an utf8 buffer into an + *ucs1 buffer. + *@param a_in_start the start of the input buffer. + *@param a_in_end the end of the input buffer. + *@param a_out out parameter. The resulting converted ucs4 buffer. + *Must be freed by the caller. + *@param a_out_len out parameter. The length of the converted buffer. + *@return CR_OK upon successfull completion, an error code otherwise. + *Note that out parameters are valid if and only if this function + *returns CR_OK. + */ +enum CRStatus +cr_utils_utf8_str_to_ucs1 (const guchar * a_in, + gulong * a_in_len, + guchar ** a_out, gulong * a_out_len) +{ + enum CRStatus status = CR_OK; + + g_return_val_if_fail (a_in && a_in_len + && a_out && a_out_len, CR_BAD_PARAM_ERROR); + + if (*a_in_len < 1) { + *a_out_len = 0; + *a_out = NULL; + return CR_OK; + } + + status = cr_utils_utf8_str_len_as_ucs4 (a_in, &a_in[*a_in_len - 1], + a_out_len); + + g_return_val_if_fail (status == CR_OK, status); + + *a_out = g_malloc0 (*a_out_len * sizeof (guint32)); + + status = cr_utils_utf8_to_ucs1 (a_in, a_in_len, *a_out, a_out_len); + return status; +} + +/***************************************** + *CSS basic types identification utilities + *****************************************/ + +/** + *Returns TRUE if a_char is a white space as + *defined in the css spec in chap 4.1.1. + * + *white-space ::= ' '| \t|\r|\n|\f + * + *@param a_char the character to test. + *return TRUE if is a white space, false otherwise. + */ +gboolean +cr_utils_is_white_space (guint32 a_char) +{ + switch (a_char) { + case ' ': + case '\t': + case '\r': + case '\n': + case '\f': + return TRUE; + break; + default: + return FALSE; + } +} + +/** + *Returns true if the character is a newline + *as defined in the css spec in the chap 4.1.1. + * + *nl ::= \n|\r\n|\r|\f + * + *@param a_char the character to test. + *@return TRUE if the character is a newline, FALSE otherwise. + */ +gboolean +cr_utils_is_newline (guint32 a_char) +{ + switch (a_char) { + case '\n': + case '\r': + case '\f': + return TRUE; + break; + default: + return FALSE; + } +} + +/** + *returns TRUE if the char is part of an hexa num char: + *i.e hexa_char ::= [0-9A-F] + */ +gboolean +cr_utils_is_hexa_char (guint32 a_char) +{ + if ((a_char >= '0' && a_char <= '9') + || (a_char >= 'A' && a_char <= 'F')) { + return TRUE; + } + return FALSE; +} + +/** + *Returns true if the character is a nonascii + *character (as defined in the css spec chap 4.1.1): + * + *nonascii ::= [^\0-\177] + * + *@param a_char the character to test. + *@return TRUE if the character is a nonascii char, + *FALSE otherwise. + */ +gboolean +cr_utils_is_nonascii (guint32 a_char) +{ + if (a_char <= 177) { + return FALSE; + } + + return TRUE; +} + +/** + *Dumps a character a_nb times on a file. + *@param a_char the char to dump + *@param a_fp the destination file pointer + *@param a_nb the number of times a_char is to be dumped. + */ +void +cr_utils_dump_n_chars (guchar a_char, FILE * a_fp, glong a_nb) +{ + glong i = 0; + + for (i = 0; i < a_nb; i++) { + fprintf (a_fp, "%c", a_char); + } +} + +void +cr_utils_dump_n_chars2 (guchar a_char, GString * a_string, glong a_nb) +{ + glong i = 0; + + g_return_if_fail (a_string); + + for (i = 0; i < a_nb; i++) { + g_string_append_printf (a_string, "%c", a_char); + } +} + +gdouble +cr_utils_n_to_0_dot_n (glong a_n, glong decimal_places) +{ + gdouble result = a_n; + + while (decimal_places > 0) { + result = result / 10; + decimal_places--; + } + + return result; +} + +/** + *Duplicates a list of GString instances. + *@return the duplicated list of GString instances or NULL if + *something bad happened. + *@param a_list_of_strings the list of strings to be duplicated. + */ +GList * +cr_utils_dup_glist_of_string (GList * a_list_of_strings) +{ + GList *cur = NULL, + *result = NULL; + + g_return_val_if_fail (a_list_of_strings, NULL); + + for (cur = a_list_of_strings; cur; cur = cur->next) { + GString *str = NULL; + + str = g_string_new_len (((GString *) cur->data)->str, + ((GString *) cur->data)->len); + if (str) + result = g_list_append (result, str); + } + + return result; +} + +/** + *Duplicate a GList where the GList::data is a CRString. + *@param a_list_of_strings the list to duplicate + *@return the duplicated list, or NULL if something bad + *happened. + */ +GList * +cr_utils_dup_glist_of_cr_string (GList * a_list_of_strings) +{ + GList *cur = NULL, *result = NULL; + + g_return_val_if_fail (a_list_of_strings, NULL); + + for (cur = a_list_of_strings; cur; cur = cur->next) { + CRString *str = NULL; + + str = cr_string_dup ((CRString *) cur->data) ; + if (str) + result = g_list_append (result, str); + } + + return result; +} diff --git a/gettext-tools/gnulib-lib/libcroco/cr-utils.h b/gettext-tools/gnulib-lib/libcroco/cr-utils.h new file mode 100644 index 0000000..294dfea --- /dev/null +++ b/gettext-tools/gnulib-lib/libcroco/cr-utils.h @@ -0,0 +1,249 @@ +/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8 -*- */ + +/* + * This file is part of The Croco Library + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + * Author: Dodji Seketeli + * Look at file COPYRIGHTS for copyright information + */ + +#ifndef __CR_DEFS_H__ +#define __CR_DEFS_H__ + +#include +#include +#include "libcroco-config.h" + +G_BEGIN_DECLS + +/** + *@file + *The Croco library basic types definitions + *And global definitions. + */ + +/** + *The status type returned + *by the methods of the croco library. + */ +enum CRStatus { + CR_OK, + CR_BAD_PARAM_ERROR, + CR_INSTANCIATION_FAILED_ERROR, + CR_UNKNOWN_TYPE_ERROR, + CR_UNKNOWN_PROP_ERROR, + CR_UNKNOWN_PROP_VAL_ERROR, + CR_UNEXPECTED_POSITION_SCHEME, + CR_START_OF_INPUT_ERROR, + CR_END_OF_INPUT_ERROR, + CR_OUTPUT_TOO_SHORT_ERROR, + CR_INPUT_TOO_SHORT_ERROR, + CR_OUT_OF_BOUNDS_ERROR, + CR_EMPTY_PARSER_INPUT_ERROR, + CR_ENCODING_ERROR, + CR_ENCODING_NOT_FOUND_ERROR, + CR_PARSING_ERROR, + CR_SYNTAX_ERROR, + CR_NO_ROOT_NODE_ERROR, + CR_NO_TOKEN, + CR_OUT_OF_MEMORY_ERROR, + CR_PSEUDO_CLASS_SEL_HANDLER_NOT_FOUND_ERROR, + CR_BAD_PSEUDO_CLASS_SEL_HANDLER_ERROR, + CR_ERROR, + CR_FILE_NOT_FOUND_ERROR, + CR_VALUE_NOT_FOUND_ERROR +} ; + +/** + *Values used by + *cr_input_seek_position() ; + */ +enum CRSeekPos { + CR_SEEK_CUR, + CR_SEEK_BEGIN, + CR_SEEK_END +} ; + +/** + *Encoding values. + */ +enum CREncoding +{ + CR_UCS_4 = 1/*Must be not NULL*/, + CR_UCS_1, + CR_ISO_8859_1, + CR_ASCII, + CR_UTF_8, + CR_UTF_16, + CR_AUTO/*should be the last one*/ +} ; + + + + +#define CROCO_LOG_DOMAIN "LIBCROCO" + +#ifdef __GNUC__ +#define cr_utils_trace(a_log_level, a_msg) \ +g_log (CROCO_LOG_DOMAIN, \ + G_LOG_LEVEL_CRITICAL, \ + "file %s: line %d (%s): %s\n", \ + __FILE__, \ + __LINE__, \ + __PRETTY_FUNCTION__, \ + a_msg) +#else /*__GNUC__*/ + +#define cr_utils_trace(a_log_level, a_msg) \ +g_log (CROCO_LOG_DOMAIN, \ + G_LOG_LEVEL_CRITICAL, \ + "file %s: line %d: %s\n", \ + __FILE__, \ + __LINE__, \ + a_msg) +#endif + +/** + *Traces an info message. + *The file, line and enclosing function + *of the message will be automatically + *added to the message. + *@param a_msg the msg to trace. + */ +#define cr_utils_trace_info(a_msg) \ +cr_utils_trace (G_LOG_LEVEL_INFO, a_msg) + +/** + *Trace a debug message. + *The file, line and enclosing function + *of the message will be automatically + *added to the message. + *@param a_msg the msg to trace. + */ +#define cr_utils_trace_debug(a_msg) \ +cr_utils_trace (G_LOG_LEVEL_DEBUG, a_msg) ; + + +/**************************** + *Encoding transformations and + *encoding helpers + ****************************/ + +enum CRStatus +cr_utils_read_char_from_utf8_buf (const guchar * a_in, gulong a_in_len, + guint32 *a_out, gulong *a_consumed) ; + +enum CRStatus +cr_utils_ucs1_to_utf8 (const guchar *a_in, gulong *a_in_len, + guchar *a_out, gulong *a_out_len) ; + +enum CRStatus +cr_utils_utf8_to_ucs1 (const guchar * a_in, gulong * a_in_len, + guchar *a_out, gulong *a_out_len) ; + +enum CRStatus +cr_utils_ucs4_to_utf8 (const guint32 *a_in, gulong *a_in_len, + guchar *a_out, gulong *a_out_len) ; + +enum CRStatus +cr_utils_utf8_str_len_as_ucs4 (const guchar *a_in_start, + const guchar *a_in_end, + gulong *a_len) ; +enum CRStatus +cr_utils_ucs1_str_len_as_utf8 (const guchar *a_in_start, + const guchar *a_in_end, + gulong *a_len) ; +enum CRStatus +cr_utils_utf8_str_len_as_ucs1 (const guchar *a_in_start, + const guchar *a_in_end, + gulong *a_len) ; +enum CRStatus +cr_utils_ucs4_str_len_as_utf8 (const guint32 *a_in_start, + const guint32 *a_in_end, + gulong *a_len) ; + +enum CRStatus +cr_utils_ucs1_str_to_utf8 (const guchar *a_in_start, + gulong *a_in_len, + guchar **a_out, + gulong *a_len) ; + +enum CRStatus +cr_utils_utf8_str_to_ucs1 (const guchar * a_in_start, + gulong * a_in_len, + guchar **a_out, + gulong *a_out_len) ; + +enum CRStatus +cr_utils_utf8_to_ucs4 (const guchar * a_in, + gulong * a_in_len, + guint32 *a_out, gulong *a_out_len) ; + +enum CRStatus +cr_utils_ucs4_str_to_utf8 (const guint32 *a_in, + gulong *a_in_len, + guchar **a_out, gulong *a_out_len) ; + +enum CRStatus +cr_utils_utf8_str_to_ucs4 (const guchar * a_in, + gulong *a_in_len, + guint32 **a_out, + gulong *a_out_len) ; + + +/***************************************** + *CSS basic types identification utilities + *****************************************/ + +gboolean +cr_utils_is_newline (guint32 a_char) ; + +gboolean +cr_utils_is_white_space (guint32 a_char) ; + +gboolean +cr_utils_is_nonascii (guint32 a_char) ; + +gboolean +cr_utils_is_hexa_char (guint32 a_char) ; + + +/********************************** + *Miscellaneous utility functions + ***********************************/ + +void +cr_utils_dump_n_chars (guchar a_char, + FILE *a_fp, + glong a_nb) ; + +void +cr_utils_dump_n_chars2 (guchar a_char, + GString *a_string, + glong a_nb) ; +gdouble +cr_utils_n_to_0_dot_n (glong a_n, glong decimal_places) ; + +GList * +cr_utils_dup_glist_of_string (GList *a_list) ; + +GList * +cr_utils_dup_glist_of_cr_string (GList * a_list_of_strings) ; + +G_END_DECLS + +#endif /*__CR_DEFS_H__*/ diff --git a/gettext-tools/gnulib-lib/libcroco/libcroco-config.h b/gettext-tools/gnulib-lib/libcroco/libcroco-config.h new file mode 100644 index 0000000..1bd3422 --- /dev/null +++ b/gettext-tools/gnulib-lib/libcroco/libcroco-config.h @@ -0,0 +1,18 @@ +#ifndef LIBCROCO_VERSION_NUMBER +#define LIBCROCO_VERSION_NUMBER 601 +#endif + +#ifndef LIBCROCO_VERSION +#define LIBCROCO_VERSION "0.6.1" +#endif + +#ifndef G_DISABLE_CHECKS +#if 0 +#define G_DISABLE_CHECKS 0 +#endif +#endif + +#if 1 +#define CROCO_HAVE_LIBXML2 1 +#endif + diff --git a/gettext-tools/gnulib-lib/libcroco/libcroco.h b/gettext-tools/gnulib-lib/libcroco/libcroco.h new file mode 100644 index 0000000..21d2c28 --- /dev/null +++ b/gettext-tools/gnulib-lib/libcroco/libcroco.h @@ -0,0 +1,44 @@ +/* + * This file is part of The Croco Library + * + * Copyright (C) 2002-2003 Dodji Seketeli + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 3 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + +#ifndef __LIBCROCO_H__ +#define __LIBCROCO_H__ + +#include "libcroco-config.h" + +#include "cr-utils.h" +#include "cr-pseudo.h" +#include "cr-term.h" +#include "cr-attr-sel.h" +#include "cr-simple-sel.h" +#include "cr-selector.h" +#include "cr-enc-handler.h" +#include "cr-doc-handler.h" +#include "cr-input.h" +#include "cr-parser.h" +#include "cr-statement.h" +#include "cr-stylesheet.h" +#include "cr-om-parser.h" +#include "cr-prop-list.h" +#include "cr-sel-eng.h" +#include "cr-style.h" +#include "cr-string.h" + +#endif /*__LIBCROCO_H__*/ diff --git a/gettext-tools/gnulib-lib/libunistring.valgrind b/gettext-tools/gnulib-lib/libunistring.valgrind new file mode 100644 index 0000000..aba265a --- /dev/null +++ b/gettext-tools/gnulib-lib/libunistring.valgrind @@ -0,0 +1,9 @@ +# Suppress valgrind messages in an installed libunistring. + +# Suppress a valgrind message about use of uninitialized memory in freea(). +# This use is OK because it provides only a speedup. +{ + libunistring_freea + Memcheck:Cond + fun:libunistring_freea +} diff --git a/gettext-tools/gnulib-lib/libxml/COPYING b/gettext-tools/gnulib-lib/libxml/COPYING new file mode 100644 index 0000000..417e955 --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/COPYING @@ -0,0 +1,27 @@ +Except where otherwise noted in the source code (e.g. the files hash.c, +list.c and the trio files, which are covered by a similar licence but +with different Copyright notices) all the files are: + + Copyright (C) 1998-2003 Daniel Veillard. All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is fur- +nished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT- +NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +DANIEL VEILLARD BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CON- +NECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Daniel Veillard shall not +be used in advertising or otherwise to promote the sale, use or other deal- +ings in this Software without prior written authorization from him. + diff --git a/gettext-tools/gnulib-lib/libxml/DOCBparser.c b/gettext-tools/gnulib-lib/libxml/DOCBparser.c new file mode 100644 index 0000000..3573743 --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/DOCBparser.c @@ -0,0 +1,305 @@ +/* + * DOCBparser.c : an attempt to parse SGML Docbook documents + * + * This is deprecated !!! + * Code removed with release 2.6.0 it was broken. + * The doc are expect to be migrated to XML DocBook + * + * See Copyright for the status of this software. + * + * daniel@veillard.com + */ + +#define IN_LIBXML +#include "libxml.h" +#ifdef LIBXML_DOCB_ENABLED + +#include +#include + +/** + * docbEncodeEntities: + * @out: a pointer to an array of bytes to store the result + * @outlen: the length of @out + * @in: a pointer to an array of UTF-8 chars + * @inlen: the length of @in + * @quoteChar: the quote character to escape (' or ") or zero. + * + * Take a block of UTF-8 chars in and try to convert it to an ASCII + * plus SGML entities block of chars out. + * + * Returns 0 if success, -2 if the transcoding fails, or -1 otherwise + * The value of @inlen after return is the number of octets consumed + * as the return value is positive, else unpredictable. + * The value of @outlen after return is the number of octets consumed. + */ +int +docbEncodeEntities(unsigned char *out ATTRIBUTE_UNUSED, + int *outlen ATTRIBUTE_UNUSED, + const unsigned char *in ATTRIBUTE_UNUSED, + int *inlen ATTRIBUTE_UNUSED, + int quoteChar ATTRIBUTE_UNUSED) +{ + static int deprecated = 0; + + if (!deprecated) { + xmlGenericError(xmlGenericErrorContext, + "docbEncodeEntities() deprecated function reached\n"); + deprecated = 1; + } + return(-1); +} + +/** + * docbParseDocument: + * @ctxt: an SGML parser context + * + * parse an SGML document (and build a tree if using the standard SAX + * interface). + * + * Returns 0, -1 in case of error. the parser context is augmented + * as a result of the parsing. + */ + +int +docbParseDocument(docbParserCtxtPtr ctxt ATTRIBUTE_UNUSED) +{ + static int deprecated = 0; + + if (!deprecated) { + xmlGenericError(xmlGenericErrorContext, + "docbParseDocument() deprecated function reached\n"); + deprecated = 1; + } + return (xmlParseDocument(ctxt)); +} + +/** + * docbFreeParserCtxt: + * @ctxt: an SGML parser context + * + * Free all the memory used by a parser context. However the parsed + * document in ctxt->myDoc is not freed. + */ + +void +docbFreeParserCtxt(docbParserCtxtPtr ctxt ATTRIBUTE_UNUSED) +{ + static int deprecated = 0; + + if (!deprecated) { + xmlGenericError(xmlGenericErrorContext, + "docbFreeParserCtxt() deprecated function reached\n"); + deprecated = 1; + } + xmlFreeParserCtxt(ctxt); +} + +/** + * docbParseChunk: + * @ctxt: an XML parser context + * @chunk: an char array + * @size: the size in byte of the chunk + * @terminate: last chunk indicator + * + * Parse a Chunk of memory + * + * Returns zero if no error, the xmlParserErrors otherwise. + */ +int +docbParseChunk(docbParserCtxtPtr ctxt ATTRIBUTE_UNUSED, + const char *chunk ATTRIBUTE_UNUSED, + int size ATTRIBUTE_UNUSED, + int terminate ATTRIBUTE_UNUSED) +{ + static int deprecated = 0; + + if (!deprecated) { + xmlGenericError(xmlGenericErrorContext, + "docbParseChunk() deprecated function reached\n"); + deprecated = 1; + } + + return (xmlParseChunk(ctxt, chunk, size, terminate)); +} + +/** + * docbCreatePushParserCtxt: + * @sax: a SAX handler + * @user_data: The user data returned on SAX callbacks + * @chunk: a pointer to an array of chars + * @size: number of chars in the array + * @filename: an optional file name or URI + * @enc: an optional encoding + * + * Create a parser context for using the DocBook SGML parser in push mode + * To allow content encoding detection, @size should be >= 4 + * The value of @filename is used for fetching external entities + * and error/warning reports. + * + * Returns the new parser context or NULL + */ +docbParserCtxtPtr +docbCreatePushParserCtxt(docbSAXHandlerPtr sax ATTRIBUTE_UNUSED, + void *user_data ATTRIBUTE_UNUSED, + const char *chunk ATTRIBUTE_UNUSED, + int size ATTRIBUTE_UNUSED, + const char *filename ATTRIBUTE_UNUSED, + xmlCharEncoding enc ATTRIBUTE_UNUSED) +{ + static int deprecated = 0; + + if (!deprecated) { + xmlGenericError(xmlGenericErrorContext, + "docbParseChunk() deprecated function reached\n"); + deprecated = 1; + } + + return(xmlCreatePushParserCtxt(sax, user_data, chunk, size, filename)); +} + +/** + * docbSAXParseDoc: + * @cur: a pointer to an array of xmlChar + * @encoding: a free form C string describing the SGML document encoding, or NULL + * @sax: the SAX handler block + * @userData: if using SAX, this pointer will be provided on callbacks. + * + * parse an SGML in-memory document and build a tree. + * It use the given SAX function block to handle the parsing callback. + * If sax is NULL, fallback to the default DOM tree building routines. + * + * Returns the resulting document tree + */ + +docbDocPtr +docbSAXParseDoc(xmlChar * cur ATTRIBUTE_UNUSED, + const char *encoding ATTRIBUTE_UNUSED, + docbSAXHandlerPtr sax ATTRIBUTE_UNUSED, + void *userData ATTRIBUTE_UNUSED) +{ + static int deprecated = 0; + + if (!deprecated) { + xmlGenericError(xmlGenericErrorContext, + "docbParseChunk() deprecated function reached\n"); + deprecated = 1; + } + + return (xmlSAXParseMemoryWithData(sax, (const char *)cur, + xmlStrlen((const xmlChar *) cur), 0, userData)); +} + +/** + * docbParseDoc: + * @cur: a pointer to an array of xmlChar + * @encoding: a free form C string describing the SGML document encoding, or NULL + * + * parse an SGML in-memory document and build a tree. + * + * Returns the resulting document tree + */ + +docbDocPtr +docbParseDoc(xmlChar * cur ATTRIBUTE_UNUSED, + const char *encoding ATTRIBUTE_UNUSED) +{ + static int deprecated = 0; + + if (!deprecated) { + xmlGenericError(xmlGenericErrorContext, + "docbParseChunk() deprecated function reached\n"); + deprecated = 1; + } + + return (xmlParseDoc(cur)); +} + + +/** + * docbCreateFileParserCtxt: + * @filename: the filename + * @encoding: the SGML document encoding, or NULL + * + * Create a parser context for a file content. + * Automatic support for ZLIB/Compress compressed document is provided + * by default if found at compile-time. + * + * Returns the new parser context or NULL + */ +docbParserCtxtPtr +docbCreateFileParserCtxt(const char *filename ATTRIBUTE_UNUSED, + const char *encoding ATTRIBUTE_UNUSED) +{ + static int deprecated = 0; + + if (!deprecated) { + xmlGenericError(xmlGenericErrorContext, + "docbCreateFileParserCtxt() deprecated function reached\n"); + deprecated = 1; + } + + return (xmlCreateFileParserCtxt(filename)); +} + +/** + * docbSAXParseFile: + * @filename: the filename + * @encoding: a free form C string describing the SGML document encoding, or NULL + * @sax: the SAX handler block + * @userData: if using SAX, this pointer will be provided on callbacks. + * + * parse an SGML file and build a tree. Automatic support for ZLIB/Compress + * compressed document is provided by default if found at compile-time. + * It use the given SAX function block to handle the parsing callback. + * If sax is NULL, fallback to the default DOM tree building routines. + * + * Returns the resulting document tree + */ + +docbDocPtr +docbSAXParseFile(const char *filename ATTRIBUTE_UNUSED, + const char *encoding ATTRIBUTE_UNUSED, + docbSAXHandlerPtr sax ATTRIBUTE_UNUSED, + void *userData ATTRIBUTE_UNUSED) +{ + static int deprecated = 0; + + if (!deprecated) { + xmlGenericError(xmlGenericErrorContext, + "docbSAXParseFile() deprecated function reached\n"); + deprecated = 1; + } + + return (xmlSAXParseFileWithData(sax, filename, 0, userData)); +} + +/** + * docbParseFile: + * @filename: the filename + * @encoding: a free form C string describing document encoding, or NULL + * + * parse a Docbook SGML file and build a tree. Automatic support for + * ZLIB/Compress compressed document is provided by default if found + * at compile-time. + * + * Returns the resulting document tree + */ + +docbDocPtr +docbParseFile(const char *filename ATTRIBUTE_UNUSED, + const char *encoding ATTRIBUTE_UNUSED) +{ + static int deprecated = 0; + + if (!deprecated) { + xmlGenericError(xmlGenericErrorContext, + "docbParseFile() deprecated function reached\n"); + deprecated = 1; + } + + return (xmlParseFile(filename)); +} +#define bottom_DOCBparser +#include "elfgcchack.h" +#endif /* LIBXML_DOCB_ENABLED */ diff --git a/gettext-tools/gnulib-lib/libxml/DOCBparser.in.h b/gettext-tools/gnulib-lib/libxml/DOCBparser.in.h new file mode 100644 index 0000000..461d4ee --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/DOCBparser.in.h @@ -0,0 +1,96 @@ +/* + * Summary: old DocBook SGML parser + * Description: interface for a DocBook SGML non-verifying parser + * This code is DEPRECATED, and should not be used anymore. + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + +#ifndef __DOCB_PARSER_H__ +#define __DOCB_PARSER_H__ +#include + +#ifdef LIBXML_DOCB_ENABLED + +#include +#include + +#ifndef IN_LIBXML +#ifdef __GNUC__ +#warning "The DOCBparser module has been deprecated in libxml2-2.6.0" +#endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Most of the back-end structures from XML and SGML are shared. + */ +typedef xmlParserCtxt docbParserCtxt; +typedef xmlParserCtxtPtr docbParserCtxtPtr; +typedef xmlSAXHandler docbSAXHandler; +typedef xmlSAXHandlerPtr docbSAXHandlerPtr; +typedef xmlParserInput docbParserInput; +typedef xmlParserInputPtr docbParserInputPtr; +typedef xmlDocPtr docbDocPtr; + +/* + * There is only few public functions. + */ +XMLPUBFUN int XMLCALL + docbEncodeEntities(unsigned char *out, + int *outlen, + const unsigned char *in, + int *inlen, int quoteChar); + +XMLPUBFUN docbDocPtr XMLCALL + docbSAXParseDoc (xmlChar *cur, + const char *encoding, + docbSAXHandlerPtr sax, + void *userData); +XMLPUBFUN docbDocPtr XMLCALL + docbParseDoc (xmlChar *cur, + const char *encoding); +XMLPUBFUN docbDocPtr XMLCALL + docbSAXParseFile (const char *filename, + const char *encoding, + docbSAXHandlerPtr sax, + void *userData); +XMLPUBFUN docbDocPtr XMLCALL + docbParseFile (const char *filename, + const char *encoding); + +/** + * Interfaces for the Push mode. + */ +XMLPUBFUN void XMLCALL + docbFreeParserCtxt (docbParserCtxtPtr ctxt); +XMLPUBFUN docbParserCtxtPtr XMLCALL + docbCreatePushParserCtxt(docbSAXHandlerPtr sax, + void *user_data, + const char *chunk, + int size, + const char *filename, + xmlCharEncoding enc); +XMLPUBFUN int XMLCALL + docbParseChunk (docbParserCtxtPtr ctxt, + const char *chunk, + int size, + int terminate); +XMLPUBFUN docbParserCtxtPtr XMLCALL + docbCreateFileParserCtxt(const char *filename, + const char *encoding); +XMLPUBFUN int XMLCALL + docbParseDocument (docbParserCtxtPtr ctxt); + +#ifdef __cplusplus +} +#endif + +#endif /* LIBXML_DOCB_ENABLED */ + +#endif /* __DOCB_PARSER_H__ */ diff --git a/gettext-tools/gnulib-lib/libxml/HTMLparser.c b/gettext-tools/gnulib-lib/libxml/HTMLparser.c new file mode 100644 index 0000000..5e23ad7 --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/HTMLparser.c @@ -0,0 +1,6276 @@ +/* + * HTMLparser.c : an HTML 4.0 non-verifying parser + * + * See Copyright for the status of this software. + * + * daniel@veillard.com + */ + +#define IN_LIBXML +#include "libxml.h" +#ifdef LIBXML_HTML_ENABLED + +#include +#ifdef HAVE_CTYPE_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_SYS_STAT_H +#include +#endif +#ifdef HAVE_FCNTL_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_ZLIB_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define HTML_MAX_NAMELEN 1000 +#define HTML_PARSER_BIG_BUFFER_SIZE 1000 +#define HTML_PARSER_BUFFER_SIZE 100 + +/* #define DEBUG */ +/* #define DEBUG_PUSH */ + +static int htmlOmittedDefaultValue = 1; + +xmlChar * htmlDecodeEntities(htmlParserCtxtPtr ctxt, int len, + xmlChar end, xmlChar end2, xmlChar end3); +static void htmlParseComment(htmlParserCtxtPtr ctxt); + +/************************************************************************ + * * + * Some factorized error routines * + * * + ************************************************************************/ + +/** + * htmlErrMemory: + * @ctxt: an HTML parser context + * @extra: extra informations + * + * Handle a redefinition of attribute error + */ +static void +htmlErrMemory(xmlParserCtxtPtr ctxt, const char *extra) +{ + if ((ctxt != NULL) && (ctxt->disableSAX != 0) && + (ctxt->instate == XML_PARSER_EOF)) + return; + if (ctxt != NULL) { + ctxt->errNo = XML_ERR_NO_MEMORY; + ctxt->instate = XML_PARSER_EOF; + ctxt->disableSAX = 1; + } + if (extra) + __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, + XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, extra, + NULL, NULL, 0, 0, + "Memory allocation failed : %s\n", extra); + else + __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, + XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, NULL, + NULL, NULL, 0, 0, "Memory allocation failed\n"); +} + +/** + * htmlParseErr: + * @ctxt: an HTML parser context + * @error: the error number + * @msg: the error message + * @str1: string infor + * @str2: string infor + * + * Handle a fatal parser error, i.e. violating Well-Formedness constraints + */ +static void +htmlParseErr(xmlParserCtxtPtr ctxt, xmlParserErrors error, + const char *msg, const xmlChar *str1, const xmlChar *str2) +{ + if ((ctxt != NULL) && (ctxt->disableSAX != 0) && + (ctxt->instate == XML_PARSER_EOF)) + return; + if (ctxt != NULL) + ctxt->errNo = error; + __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_HTML, error, + XML_ERR_ERROR, NULL, 0, + (const char *) str1, (const char *) str2, + NULL, 0, 0, + msg, str1, str2); + if (ctxt != NULL) + ctxt->wellFormed = 0; +} + +/** + * htmlParseErrInt: + * @ctxt: an HTML parser context + * @error: the error number + * @msg: the error message + * @val: integer info + * + * Handle a fatal parser error, i.e. violating Well-Formedness constraints + */ +static void +htmlParseErrInt(xmlParserCtxtPtr ctxt, xmlParserErrors error, + const char *msg, int val) +{ + if ((ctxt != NULL) && (ctxt->disableSAX != 0) && + (ctxt->instate == XML_PARSER_EOF)) + return; + if (ctxt != NULL) + ctxt->errNo = error; + __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_HTML, error, + XML_ERR_ERROR, NULL, 0, NULL, NULL, + NULL, val, 0, msg, val); + if (ctxt != NULL) + ctxt->wellFormed = 0; +} + +/************************************************************************ + * * + * Parser stacks related functions and macros * + * * + ************************************************************************/ + +/** + * htmlnamePush: + * @ctxt: an HTML parser context + * @value: the element name + * + * Pushes a new element name on top of the name stack + * + * Returns 0 in case of error, the index in the stack otherwise + */ +static int +htmlnamePush(htmlParserCtxtPtr ctxt, const xmlChar * value) +{ + if (ctxt->nameNr >= ctxt->nameMax) { + ctxt->nameMax *= 2; + ctxt->nameTab = (const xmlChar * *) + xmlRealloc((xmlChar * *)ctxt->nameTab, + ctxt->nameMax * + sizeof(ctxt->nameTab[0])); + if (ctxt->nameTab == NULL) { + htmlErrMemory(ctxt, NULL); + return (0); + } + } + ctxt->nameTab[ctxt->nameNr] = value; + ctxt->name = value; + return (ctxt->nameNr++); +} +/** + * htmlnamePop: + * @ctxt: an HTML parser context + * + * Pops the top element name from the name stack + * + * Returns the name just removed + */ +static const xmlChar * +htmlnamePop(htmlParserCtxtPtr ctxt) +{ + const xmlChar *ret; + + if (ctxt->nameNr <= 0) + return (NULL); + ctxt->nameNr--; + if (ctxt->nameNr < 0) + return (NULL); + if (ctxt->nameNr > 0) + ctxt->name = ctxt->nameTab[ctxt->nameNr - 1]; + else + ctxt->name = NULL; + ret = ctxt->nameTab[ctxt->nameNr]; + ctxt->nameTab[ctxt->nameNr] = NULL; + return (ret); +} + +/* + * Macros for accessing the content. Those should be used only by the parser, + * and not exported. + * + * Dirty macros, i.e. one need to make assumption on the context to use them + * + * CUR_PTR return the current pointer to the xmlChar to be parsed. + * CUR returns the current xmlChar value, i.e. a 8 bit value if compiled + * in ISO-Latin or UTF-8, and the current 16 bit value if compiled + * in UNICODE mode. This should be used internally by the parser + * only to compare to ASCII values otherwise it would break when + * running with UTF-8 encoding. + * NXT(n) returns the n'th next xmlChar. Same as CUR is should be used only + * to compare on ASCII based substring. + * UPP(n) returns the n'th next xmlChar converted to uppercase. Same as CUR + * it should be used only to compare on ASCII based substring. + * SKIP(n) Skip n xmlChar, and must also be used only to skip ASCII defined + * strings without newlines within the parser. + * + * Clean macros, not dependent of an ASCII context, expect UTF-8 encoding + * + * CURRENT Returns the current char value, with the full decoding of + * UTF-8 if we are using this mode. It returns an int. + * NEXT Skip to the next character, this does the proper decoding + * in UTF-8 mode. It also pop-up unfinished entities on the fly. + * NEXTL(l) Skip the current unicode character of l xmlChars long. + * COPY(to) copy one char to *to, increment CUR_PTR and to accordingly + */ + +#define UPPER (toupper(*ctxt->input->cur)) + +#define SKIP(val) ctxt->nbChars += (val),ctxt->input->cur += (val),ctxt->input->col+=(val) + +#define NXT(val) ctxt->input->cur[(val)] + +#define UPP(val) (toupper(ctxt->input->cur[(val)])) + +#define CUR_PTR ctxt->input->cur + +#define SHRINK if ((ctxt->input->cur - ctxt->input->base > 2 * INPUT_CHUNK) && \ + (ctxt->input->end - ctxt->input->cur < 2 * INPUT_CHUNK)) \ + xmlParserInputShrink(ctxt->input) + +#define GROW if ((ctxt->progressive == 0) && \ + (ctxt->input->end - ctxt->input->cur < INPUT_CHUNK)) \ + xmlParserInputGrow(ctxt->input, INPUT_CHUNK) + +#define CURRENT ((int) (*ctxt->input->cur)) + +#define SKIP_BLANKS htmlSkipBlankChars(ctxt) + +/* Inported from XML */ + +/* #define CUR (ctxt->token ? ctxt->token : (int) (*ctxt->input->cur)) */ +#define CUR ((int) (*ctxt->input->cur)) +#define NEXT xmlNextChar(ctxt) + +#define RAW (ctxt->token ? -1 : (*ctxt->input->cur)) +#define NXT(val) ctxt->input->cur[(val)] +#define CUR_PTR ctxt->input->cur + + +#define NEXTL(l) do { \ + if (*(ctxt->input->cur) == '\n') { \ + ctxt->input->line++; ctxt->input->col = 1; \ + } else ctxt->input->col++; \ + ctxt->token = 0; ctxt->input->cur += l; ctxt->nbChars++; \ + } while (0) + +/************ + \ + if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt); \ + if (*ctxt->input->cur == '&') xmlParserHandleReference(ctxt); + ************/ + +#define CUR_CHAR(l) htmlCurrentChar(ctxt, &l) +#define CUR_SCHAR(s, l) xmlStringCurrentChar(ctxt, s, &l) + +#define COPY_BUF(l,b,i,v) \ + if (l == 1) b[i++] = (xmlChar) v; \ + else i += xmlCopyChar(l,&b[i],v) + +/** + * htmlCurrentChar: + * @ctxt: the HTML parser context + * @len: pointer to the length of the char read + * + * The current char value, if using UTF-8 this may actually span multiple + * bytes in the input buffer. Implement the end of line normalization: + * 2.11 End-of-Line Handling + * If the encoding is unspecified, in the case we find an ISO-Latin-1 + * char, then the encoding converter is plugged in automatically. + * + * Returns the current char value and its length + */ + +static int +htmlCurrentChar(xmlParserCtxtPtr ctxt, int *len) { + if (ctxt->instate == XML_PARSER_EOF) + return(0); + + if (ctxt->token != 0) { + *len = 0; + return(ctxt->token); + } + if (ctxt->charset == XML_CHAR_ENCODING_UTF8) { + /* + * We are supposed to handle UTF8, check it's valid + * From rfc2044: encoding of the Unicode values on UTF-8: + * + * UCS-4 range (hex.) UTF-8 octet sequence (binary) + * 0000 0000-0000 007F 0xxxxxxx + * 0000 0080-0000 07FF 110xxxxx 10xxxxxx + * 0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx + * + * Check for the 0x110000 limit too + */ + const unsigned char *cur = ctxt->input->cur; + unsigned char c; + unsigned int val; + + c = *cur; + if (c & 0x80) { + if (cur[1] == 0) + xmlParserInputGrow(ctxt->input, INPUT_CHUNK); + if ((cur[1] & 0xc0) != 0x80) + goto encoding_error; + if ((c & 0xe0) == 0xe0) { + + if (cur[2] == 0) + xmlParserInputGrow(ctxt->input, INPUT_CHUNK); + if ((cur[2] & 0xc0) != 0x80) + goto encoding_error; + if ((c & 0xf0) == 0xf0) { + if (cur[3] == 0) + xmlParserInputGrow(ctxt->input, INPUT_CHUNK); + if (((c & 0xf8) != 0xf0) || + ((cur[3] & 0xc0) != 0x80)) + goto encoding_error; + /* 4-byte code */ + *len = 4; + val = (cur[0] & 0x7) << 18; + val |= (cur[1] & 0x3f) << 12; + val |= (cur[2] & 0x3f) << 6; + val |= cur[3] & 0x3f; + } else { + /* 3-byte code */ + *len = 3; + val = (cur[0] & 0xf) << 12; + val |= (cur[1] & 0x3f) << 6; + val |= cur[2] & 0x3f; + } + } else { + /* 2-byte code */ + *len = 2; + val = (cur[0] & 0x1f) << 6; + val |= cur[1] & 0x3f; + } + if (!IS_CHAR(val)) { + htmlParseErrInt(ctxt, XML_ERR_INVALID_CHAR, + "Char 0x%X out of allowed range\n", val); + } + return(val); + } else { + /* 1-byte code */ + *len = 1; + return((int) *ctxt->input->cur); + } + } + /* + * Assume it's a fixed length encoding (1) with + * a compatible encoding for the ASCII set, since + * XML constructs only use < 128 chars + */ + *len = 1; + if ((int) *ctxt->input->cur < 0x80) + return((int) *ctxt->input->cur); + + /* + * Humm this is bad, do an automatic flow conversion + */ + xmlSwitchEncoding(ctxt, XML_CHAR_ENCODING_8859_1); + ctxt->charset = XML_CHAR_ENCODING_UTF8; + return(xmlCurrentChar(ctxt, len)); + +encoding_error: + /* + * If we detect an UTF8 error that probably mean that the + * input encoding didn't get properly advertized in the + * declaration header. Report the error and switch the encoding + * to ISO-Latin-1 (if you don't like this policy, just declare the + * encoding !) + */ + { + char buffer[150]; + + snprintf(buffer, 149, "Bytes: 0x%02X 0x%02X 0x%02X 0x%02X\n", + ctxt->input->cur[0], ctxt->input->cur[1], + ctxt->input->cur[2], ctxt->input->cur[3]); + htmlParseErr(ctxt, XML_ERR_INVALID_ENCODING, + "Input is not proper UTF-8, indicate encoding !\n", + BAD_CAST buffer, NULL); + } + + ctxt->charset = XML_CHAR_ENCODING_8859_1; + *len = 1; + return((int) *ctxt->input->cur); +} + +/** + * htmlSkipBlankChars: + * @ctxt: the HTML parser context + * + * skip all blanks character found at that point in the input streams. + * + * Returns the number of space chars skipped + */ + +static int +htmlSkipBlankChars(xmlParserCtxtPtr ctxt) { + int res = 0; + + while (IS_BLANK_CH(*(ctxt->input->cur))) { + if ((*ctxt->input->cur == 0) && + (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0)) { + xmlPopInput(ctxt); + } else { + if (*(ctxt->input->cur) == '\n') { + ctxt->input->line++; ctxt->input->col = 1; + } else ctxt->input->col++; + ctxt->input->cur++; + ctxt->nbChars++; + if (*ctxt->input->cur == 0) + xmlParserInputGrow(ctxt->input, INPUT_CHUNK); + } + res++; + } + return(res); +} + + + +/************************************************************************ + * * + * The list of HTML elements and their properties * + * * + ************************************************************************/ + +/* + * Start Tag: 1 means the start tag can be ommited + * End Tag: 1 means the end tag can be ommited + * 2 means it's forbidden (empty elements) + * 3 means the tag is stylistic and should be closed easily + * Depr: this element is deprecated + * DTD: 1 means that this element is valid only in the Loose DTD + * 2 means that this element is valid only in the Frameset DTD + * + * Name,Start Tag,End Tag,Save End,Empty,Deprecated,DTD,inline,Description + , subElements , impliedsubelt , Attributes, userdata + */ + +/* Definitions and a couple of vars for HTML Elements */ + +#define FONTSTYLE "tt", "i", "b", "u", "s", "strike", "big", "small" +#define NB_FONTSTYLE 8 +#define PHRASE "em", "strong", "dfn", "code", "samp", "kbd", "var", "cite", "abbr", "acronym" +#define NB_PHRASE 10 +#define SPECIAL "a", "img", "applet", "object", "font", "basefont", "br", "script", "map", "q", "sub", "sup", "span", "bdo", "iframe" +#define NB_SPECIAL 15 +#define INLINE PCDATA FONTSTYLE PHRASE SPECIAL FORMCTRL +#define NB_INLINE NB_PCDATA + NB_FONTSTYLE + NB_PHRASE + NB_SPECIAL + NB_FORMCTRL +#define BLOCK HEADING, LIST "pre", "p", "dl", "div", "center", "noscript", "noframes", "blockquote", "form", "isindex", "hr", "table", "fieldset", "address" +#define NB_BLOCK NB_HEADING + NB_LIST + 14 +#define FORMCTRL "input", "select", "textarea", "label", "button" +#define NB_FORMCTRL 5 +#define PCDATA +#define NB_PCDATA 0 +#define HEADING "h1", "h2", "h3", "h4", "h5", "h6" +#define NB_HEADING 6 +#define LIST "ul", "ol", "dir", "menu" +#define NB_LIST 4 +#define MODIFIER +#define NB_MODIFIER 0 +#define FLOW BLOCK,INLINE +#define NB_FLOW NB_BLOCK + NB_INLINE +#define EMPTY NULL + + +static const char* const html_flow[] = { FLOW, NULL } ; +static const char* const html_inline[] = { INLINE, NULL } ; + +/* placeholders: elts with content but no subelements */ +static const char* const html_pcdata[] = { NULL } ; +#define html_cdata html_pcdata + + +/* ... and for HTML Attributes */ + +#define COREATTRS "id", "class", "style", "title" +#define NB_COREATTRS 4 +#define I18N "lang", "dir" +#define NB_I18N 2 +#define EVENTS "onclick", "ondblclick", "onmousedown", "onmouseup", "onmouseover", "onmouseout", "onkeypress", "onkeydown", "onkeyup" +#define NB_EVENTS 9 +#define ATTRS COREATTRS,I18N,EVENTS +#define NB_ATTRS NB_NB_COREATTRS + NB_I18N + NB_EVENTS +#define CELLHALIGN "align", "char", "charoff" +#define NB_CELLHALIGN 3 +#define CELLVALIGN "valign" +#define NB_CELLVALIGN 1 + +static const char* const html_attrs[] = { ATTRS, NULL } ; +static const char* const core_i18n_attrs[] = { COREATTRS, I18N, NULL } ; +static const char* const core_attrs[] = { COREATTRS, NULL } ; +static const char* const i18n_attrs[] = { I18N, NULL } ; + + +/* Other declarations that should go inline ... */ +static const char* const a_attrs[] = { ATTRS, "charset", "type", "name", + "href", "hreflang", "rel", "rev", "accesskey", "shape", "coords", + "tabindex", "onfocus", "onblur", NULL } ; +static const char* const target_attr[] = { "target", NULL } ; +static const char* const rows_cols_attr[] = { "rows", "cols", NULL } ; +static const char* const alt_attr[] = { "alt", NULL } ; +static const char* const src_alt_attrs[] = { "src", "alt", NULL } ; +static const char* const href_attrs[] = { "href", NULL } ; +static const char* const clear_attrs[] = { "clear", NULL } ; +static const char* const inline_p[] = { INLINE, "p", NULL } ; + +static const char* const flow_param[] = { FLOW, "param", NULL } ; +static const char* const applet_attrs[] = { COREATTRS , "codebase", + "archive", "alt", "name", "height", "width", "align", + "hspace", "vspace", NULL } ; +static const char* const area_attrs[] = { "shape", "coords", "href", "nohref", + "tabindex", "accesskey", "onfocus", "onblur", NULL } ; +static const char* const basefont_attrs[] = + { "id", "size", "color", "face", NULL } ; +static const char* const quote_attrs[] = { ATTRS, "cite", NULL } ; +static const char* const body_contents[] = { FLOW, "ins", "del", NULL } ; +static const char* const body_attrs[] = { ATTRS, "onload", "onunload", NULL } ; +static const char* const body_depr[] = { "background", "bgcolor", "text", + "link", "vlink", "alink", NULL } ; +static const char* const button_attrs[] = { ATTRS, "name", "value", "type", + "disabled", "tabindex", "accesskey", "onfocus", "onblur", NULL } ; + + +static const char* const col_attrs[] = { ATTRS, "span", "width", CELLHALIGN, CELLVALIGN, NULL } ; +static const char* const col_elt[] = { "col", NULL } ; +static const char* const edit_attrs[] = { ATTRS, "datetime", "cite", NULL } ; +static const char* const compact_attrs[] = { ATTRS, "compact", NULL } ; +static const char* const dl_contents[] = { "dt", "dd", NULL } ; +static const char* const compact_attr[] = { "compact", NULL } ; +static const char* const label_attr[] = { "label", NULL } ; +static const char* const fieldset_contents[] = { FLOW, "legend" } ; +static const char* const font_attrs[] = { COREATTRS, I18N, "size", "color", "face" , NULL } ; +static const char* const form_contents[] = { HEADING, LIST, INLINE, "pre", "p", "div", "center", "noscript", "noframes", "blockquote", "isindex", "hr", "table", "fieldset", "address", NULL } ; +static const char* const form_attrs[] = { ATTRS, "method", "enctype", "accept", "name", "onsubmit", "onreset", "accept-charset", NULL } ; +static const char* const frame_attrs[] = { COREATTRS, "longdesc", "name", "src", "frameborder", "marginwidth", "marginheight", "noresize", "scrolling" , NULL } ; +static const char* const frameset_attrs[] = { COREATTRS, "rows", "cols", "onload", "onunload", NULL } ; +static const char* const frameset_contents[] = { "frameset", "frame", "noframes", NULL } ; +static const char* const head_attrs[] = { I18N, "profile", NULL } ; +static const char* const head_contents[] = { "title", "isindex", "base", "script", "style", "meta", "link", "object", NULL } ; +static const char* const hr_depr[] = { "align", "noshade", "size", "width", NULL } ; +static const char* const version_attr[] = { "version", NULL } ; +static const char* const html_content[] = { "head", "body", "frameset", NULL } ; +static const char* const iframe_attrs[] = { COREATTRS, "longdesc", "name", "src", "frameborder", "marginwidth", "marginheight", "scrolling", "align", "height", "width", NULL } ; +static const char* const img_attrs[] = { ATTRS, "longdesc", "name", "height", "width", "usemap", "ismap", NULL } ; +static const char* const input_attrs[] = { ATTRS, "type", "name", "value", "checked", "disabled", "readonly", "size", "maxlength", "src", "alt", "usemap", "ismap", "tabindex", "accesskey", "onfocus", "onblur", "onselect", "onchange", "accept", NULL } ; +static const char* const prompt_attrs[] = { COREATTRS, I18N, "prompt", NULL } ; +static const char* const label_attrs[] = { ATTRS, "for", "accesskey", "onfocus", "onblur", NULL } ; +static const char* const legend_attrs[] = { ATTRS, "accesskey", NULL } ; +static const char* const align_attr[] = { "align", NULL } ; +static const char* const link_attrs[] = { ATTRS, "charset", "href", "hreflang", "type", "rel", "rev", "media", NULL } ; +static const char* const map_contents[] = { BLOCK, "area", NULL } ; +static const char* const name_attr[] = { "name", NULL } ; +static const char* const action_attr[] = { "action", NULL } ; +static const char* const blockli_elt[] = { BLOCK, "li", NULL } ; +static const char* const meta_attrs[] = { I18N, "http-equiv", "name", "scheme", NULL } ; +static const char* const content_attr[] = { "content", NULL } ; +static const char* const type_attr[] = { "type", NULL } ; +static const char* const noframes_content[] = { "body", FLOW MODIFIER, NULL } ; +static const char* const object_contents[] = { FLOW, "param", NULL } ; +static const char* const object_attrs[] = { ATTRS, "declare", "classid", "codebase", "data", "type", "codetype", "archive", "standby", "height", "width", "usemap", "name", "tabindex", NULL } ; +static const char* const object_depr[] = { "align", "border", "hspace", "vspace", NULL } ; +static const char* const ol_attrs[] = { "type", "compact", "start", NULL} ; +static const char* const option_elt[] = { "option", NULL } ; +static const char* const optgroup_attrs[] = { ATTRS, "disabled", NULL } ; +static const char* const option_attrs[] = { ATTRS, "disabled", "label", "selected", "value", NULL } ; +static const char* const param_attrs[] = { "id", "value", "valuetype", "type", NULL } ; +static const char* const width_attr[] = { "width", NULL } ; +static const char* const pre_content[] = { PHRASE, "tt", "i", "b", "u", "s", "strike", "a", "br", "script", "map", "q", "span", "bdo", "iframe", NULL } ; +static const char* const script_attrs[] = { "charset", "src", "defer", "event", "for", NULL } ; +static const char* const language_attr[] = { "language", NULL } ; +static const char* const select_content[] = { "optgroup", "option", NULL } ; +static const char* const select_attrs[] = { ATTRS, "name", "size", "multiple", "disabled", "tabindex", "onfocus", "onblur", "onchange", NULL } ; +static const char* const style_attrs[] = { I18N, "media", "title", NULL } ; +static const char* const table_attrs[] = { ATTRS "summary", "width", "border", "frame", "rules", "cellspacing", "cellpadding", "datapagesize", NULL } ; +static const char* const table_depr[] = { "align", "bgcolor", NULL } ; +static const char* const table_contents[] = { "caption", "col", "colgroup", "thead", "tfoot", "tbody", "tr", NULL} ; +static const char* const tr_elt[] = { "tr", NULL } ; +static const char* const talign_attrs[] = { ATTRS, CELLHALIGN, CELLVALIGN, NULL} ; +static const char* const th_td_depr[] = { "nowrap", "bgcolor", "width", "height", NULL } ; +static const char* const th_td_attr[] = { ATTRS, "abbr", "axis", "headers", "scope", "rowspan", "colspan", CELLHALIGN, CELLVALIGN, NULL } ; +static const char* const textarea_attrs[] = { ATTRS, "name", "disabled", "readonly", "tabindex", "accesskey", "onfocus", "onblur", "onselect", "onchange", NULL } ; +static const char* const tr_contents[] = { "th", "td", NULL } ; +static const char* const bgcolor_attr[] = { "bgcolor", NULL } ; +static const char* const li_elt[] = { "li", NULL } ; +static const char* const ul_depr[] = { "type", "compact", NULL} ; +static const char* const dir_attr[] = { "dir", NULL} ; + +#define DECL (const char**) + +static const htmlElemDesc +html40ElementTable[] = { +{ "a", 0, 0, 0, 0, 0, 0, 1, "anchor ", + DECL html_inline , NULL , DECL a_attrs , DECL target_attr, NULL +}, +{ "abbr", 0, 0, 0, 0, 0, 0, 1, "abbreviated form", + DECL html_inline , NULL , DECL html_attrs, NULL, NULL +}, +{ "acronym", 0, 0, 0, 0, 0, 0, 1, "", + DECL html_inline , NULL , DECL html_attrs, NULL, NULL +}, +{ "address", 0, 0, 0, 0, 0, 0, 0, "information on author ", + DECL inline_p , NULL , DECL html_attrs, NULL, NULL +}, +{ "applet", 0, 0, 0, 0, 1, 1, 2, "java applet ", + DECL flow_param , NULL , NULL , DECL applet_attrs, NULL +}, +{ "area", 0, 2, 2, 1, 0, 0, 0, "client-side image map area ", + EMPTY , NULL , DECL area_attrs , DECL target_attr, DECL alt_attr +}, +{ "b", 0, 3, 0, 0, 0, 0, 1, "bold text style", + DECL html_inline , NULL , DECL html_attrs, NULL, NULL +}, +{ "base", 0, 2, 2, 1, 0, 0, 0, "document base uri ", + EMPTY , NULL , NULL , DECL target_attr, DECL href_attrs +}, +{ "basefont", 0, 2, 2, 1, 1, 1, 1, "base font size " , + EMPTY , NULL , NULL, DECL basefont_attrs, NULL +}, +{ "bdo", 0, 0, 0, 0, 0, 0, 1, "i18n bidi over-ride ", + DECL html_inline , NULL , DECL core_i18n_attrs, NULL, DECL dir_attr +}, +{ "big", 0, 3, 0, 0, 0, 0, 1, "large text style", + DECL html_inline , NULL , DECL html_attrs, NULL, NULL +}, +{ "blockquote", 0, 0, 0, 0, 0, 0, 0, "long quotation ", + DECL html_flow , NULL , DECL quote_attrs , NULL, NULL +}, +{ "body", 1, 1, 0, 0, 0, 0, 0, "document body ", + DECL body_contents , "div" , DECL body_attrs, DECL body_depr, NULL +}, +{ "br", 0, 2, 2, 1, 0, 0, 1, "forced line break ", + EMPTY , NULL , DECL core_attrs, DECL clear_attrs , NULL +}, +{ "button", 0, 0, 0, 0, 0, 0, 2, "push button ", + DECL html_flow MODIFIER , NULL , DECL button_attrs, NULL, NULL +}, +{ "caption", 0, 0, 0, 0, 0, 0, 0, "table caption ", + DECL html_inline , NULL , DECL html_attrs, NULL, NULL +}, +{ "center", 0, 3, 0, 0, 1, 1, 0, "shorthand for div align=center ", + DECL html_flow , NULL , NULL, DECL html_attrs, NULL +}, +{ "cite", 0, 0, 0, 0, 0, 0, 1, "citation", + DECL html_inline , NULL , DECL html_attrs, NULL, NULL +}, +{ "code", 0, 0, 0, 0, 0, 0, 1, "computer code fragment", + DECL html_inline , NULL , DECL html_attrs, NULL, NULL +}, +{ "col", 0, 2, 2, 1, 0, 0, 0, "table column ", + EMPTY , NULL , DECL col_attrs , NULL, NULL +}, +{ "colgroup", 0, 1, 0, 0, 0, 0, 0, "table column group ", + DECL col_elt , "col" , DECL col_attrs , NULL, NULL +}, +{ "dd", 0, 1, 0, 0, 0, 0, 0, "definition description ", + DECL html_flow , NULL , DECL html_attrs, NULL, NULL +}, +{ "del", 0, 0, 0, 0, 0, 0, 2, "deleted text ", + DECL html_flow , NULL , DECL edit_attrs , NULL, NULL +}, +{ "dfn", 0, 0, 0, 0, 0, 0, 1, "instance definition", + DECL html_inline , NULL , DECL html_attrs, NULL, NULL +}, +{ "dir", 0, 0, 0, 0, 1, 1, 0, "directory list", + DECL blockli_elt, "li" , NULL, DECL compact_attrs, NULL +}, +{ "div", 0, 0, 0, 0, 0, 0, 0, "generic language/style container", + DECL html_flow, NULL, DECL html_attrs, DECL align_attr, NULL +}, +{ "dl", 0, 0, 0, 0, 0, 0, 0, "definition list ", + DECL dl_contents , "dd" , html_attrs, DECL compact_attr, NULL +}, +{ "dt", 0, 1, 0, 0, 0, 0, 0, "definition term ", + DECL html_inline, NULL, DECL html_attrs, NULL, NULL +}, +{ "em", 0, 3, 0, 0, 0, 0, 1, "emphasis", + DECL html_inline, NULL, DECL html_attrs, NULL, NULL +}, +{ "fieldset", 0, 0, 0, 0, 0, 0, 0, "form control group ", + DECL fieldset_contents , NULL, DECL html_attrs, NULL, NULL +}, +{ "font", 0, 3, 0, 0, 1, 1, 1, "local change to font ", + DECL html_inline, NULL, NULL, DECL font_attrs, NULL +}, +{ "form", 0, 0, 0, 0, 0, 0, 0, "interactive form ", + DECL form_contents, "fieldset", DECL form_attrs , DECL target_attr, DECL action_attr +}, +{ "frame", 0, 2, 2, 1, 0, 2, 0, "subwindow " , + EMPTY, NULL, NULL, DECL frame_attrs, NULL +}, +{ "frameset", 0, 0, 0, 0, 0, 2, 0, "window subdivision" , + DECL frameset_contents, "noframes" , NULL , DECL frameset_attrs, NULL +}, +{ "h1", 0, 0, 0, 0, 0, 0, 0, "heading ", + DECL html_inline, NULL, DECL html_attrs, DECL align_attr, NULL +}, +{ "h2", 0, 0, 0, 0, 0, 0, 0, "heading ", + DECL html_inline, NULL, DECL html_attrs, DECL align_attr, NULL +}, +{ "h3", 0, 0, 0, 0, 0, 0, 0, "heading ", + DECL html_inline, NULL, DECL html_attrs, DECL align_attr, NULL +}, +{ "h4", 0, 0, 0, 0, 0, 0, 0, "heading ", + DECL html_inline, NULL, DECL html_attrs, DECL align_attr, NULL +}, +{ "h5", 0, 0, 0, 0, 0, 0, 0, "heading ", + DECL html_inline, NULL, DECL html_attrs, DECL align_attr, NULL +}, +{ "h6", 0, 0, 0, 0, 0, 0, 0, "heading ", + DECL html_inline, NULL, DECL html_attrs, DECL align_attr, NULL +}, +{ "head", 1, 1, 0, 0, 0, 0, 0, "document head ", + DECL head_contents, NULL, DECL head_attrs, NULL, NULL +}, +{ "hr", 0, 2, 2, 1, 0, 0, 0, "horizontal rule " , + EMPTY, NULL, DECL html_attrs, DECL hr_depr, NULL +}, +{ "html", 1, 1, 0, 0, 0, 0, 0, "document root element ", + DECL html_content , NULL , DECL i18n_attrs, DECL version_attr, NULL +}, +{ "i", 0, 3, 0, 0, 0, 0, 1, "italic text style", + DECL html_inline, NULL, DECL html_attrs, NULL, NULL +}, +{ "iframe", 0, 0, 0, 0, 0, 1, 2, "inline subwindow ", + DECL html_flow, NULL, NULL, DECL iframe_attrs, NULL +}, +{ "img", 0, 2, 2, 1, 0, 0, 1, "embedded image ", + EMPTY, NULL, DECL img_attrs, DECL align_attr, src_alt_attrs +}, +{ "input", 0, 2, 2, 1, 0, 0, 1, "form control ", + EMPTY, NULL, DECL input_attrs , DECL align_attr, NULL +}, +{ "ins", 0, 0, 0, 0, 0, 0, 2, "inserted text", + DECL html_flow, NULL, DECL edit_attrs, NULL, NULL +}, +{ "isindex", 0, 2, 2, 1, 1, 1, 0, "single line prompt ", + EMPTY, NULL, NULL, DECL prompt_attrs, NULL +}, +{ "kbd", 0, 0, 0, 0, 0, 0, 1, "text to be entered by the user", + DECL html_inline, NULL, DECL html_attrs, NULL, NULL +}, +{ "label", 0, 0, 0, 0, 0, 0, 1, "form field label text ", + DECL html_inline MODIFIER, NULL, DECL label_attrs , NULL, NULL +}, +{ "legend", 0, 0, 0, 0, 0, 0, 0, "fieldset legend ", + DECL html_inline, NULL, DECL legend_attrs , DECL align_attr, NULL +}, +{ "li", 0, 1, 1, 0, 0, 0, 0, "list item ", + DECL html_flow, NULL, DECL html_attrs, NULL, NULL +}, +{ "link", 0, 2, 2, 1, 0, 0, 0, "a media-independent link ", + EMPTY, NULL, DECL link_attrs, DECL target_attr, NULL +}, +{ "map", 0, 0, 0, 0, 0, 0, 2, "client-side image map ", + DECL map_contents , NULL, DECL html_attrs , NULL, name_attr +}, +{ "menu", 0, 0, 0, 0, 1, 1, 0, "menu list ", + DECL blockli_elt , NULL, NULL, DECL compact_attrs, NULL +}, +{ "meta", 0, 2, 2, 1, 0, 0, 0, "generic metainformation ", + EMPTY, NULL, DECL meta_attrs , NULL , DECL content_attr +}, +{ "noframes", 0, 0, 0, 0, 0, 2, 0, "alternate content container for non frame-based rendering ", + DECL noframes_content, "body" , DECL html_attrs, NULL, NULL +}, +{ "noscript", 0, 0, 0, 0, 0, 0, 0, "alternate content container for non script-based rendering ", + DECL html_flow, "div", DECL html_attrs, NULL, NULL +}, +{ "object", 0, 0, 0, 0, 0, 0, 2, "generic embedded object ", + DECL object_contents , "div" , DECL object_attrs, DECL object_depr, NULL +}, +{ "ol", 0, 0, 0, 0, 0, 0, 0, "ordered list ", + DECL li_elt , "li" , DECL html_attrs, DECL ol_attrs, NULL +}, +{ "optgroup", 0, 0, 0, 0, 0, 0, 0, "option group ", + option_elt , "option", DECL optgroup_attrs, NULL, DECL label_attr +}, +{ "option", 0, 1, 0, 0, 0, 0, 0, "selectable choice " , + DECL html_pcdata, NULL, DECL option_attrs, NULL, NULL +}, +{ "p", 0, 1, 0, 0, 0, 0, 0, "paragraph ", + DECL html_inline, NULL, DECL html_attrs, DECL align_attr, NULL +}, +{ "param", 0, 2, 2, 1, 0, 0, 0, "named property value ", + EMPTY, NULL, DECL param_attrs, NULL, name_attr +}, +{ "pre", 0, 0, 0, 0, 0, 0, 0, "preformatted text ", + DECL pre_content, NULL, DECL html_attrs, DECL width_attr, NULL +}, +{ "q", 0, 0, 0, 0, 0, 0, 1, "short inline quotation ", + DECL html_inline, NULL, DECL quote_attrs, NULL, NULL +}, +{ "s", 0, 3, 0, 0, 1, 1, 1, "strike-through text style", + DECL html_inline, NULL, NULL, DECL html_attrs, NULL +}, +{ "samp", 0, 0, 0, 0, 0, 0, 1, "sample program output, scripts, etc.", + DECL html_inline, NULL, DECL html_attrs, NULL, NULL +}, +{ "script", 0, 0, 0, 0, 0, 0, 2, "script statements ", + DECL html_cdata, NULL, DECL script_attrs, DECL language_attr, DECL type_attr +}, +{ "select", 0, 0, 0, 0, 0, 0, 1, "option selector ", + DECL select_content, NULL, DECL select_attrs, NULL, NULL +}, +{ "small", 0, 3, 0, 0, 0, 0, 1, "small text style", + DECL html_inline, NULL, DECL html_attrs, NULL, NULL +}, +{ "span", 0, 0, 0, 0, 0, 0, 1, "generic language/style container ", + DECL html_inline, NULL, DECL html_attrs, NULL, NULL +}, +{ "strike", 0, 3, 0, 0, 1, 1, 1, "strike-through text", + DECL html_inline, NULL, NULL, DECL html_attrs, NULL +}, +{ "strong", 0, 3, 0, 0, 0, 0, 1, "strong emphasis", + DECL html_inline, NULL, DECL html_attrs, NULL, NULL +}, +{ "style", 0, 0, 0, 0, 0, 0, 0, "style info ", + DECL html_cdata, NULL, DECL style_attrs, NULL, DECL type_attr +}, +{ "sub", 0, 3, 0, 0, 0, 0, 1, "subscript", + DECL html_inline, NULL, DECL html_attrs, NULL, NULL +}, +{ "sup", 0, 3, 0, 0, 0, 0, 1, "superscript ", + DECL html_inline, NULL, DECL html_attrs, NULL, NULL +}, +{ "table", 0, 0, 0, 0, 0, 0, 0, "", + DECL table_contents , "tr" , DECL table_attrs , DECL table_depr, NULL +}, +{ "tbody", 1, 0, 0, 0, 0, 0, 0, "table body ", + DECL tr_elt , "tr" , DECL talign_attrs, NULL, NULL +}, +{ "td", 0, 0, 0, 0, 0, 0, 0, "table data cell", + DECL html_flow, NULL, DECL th_td_attr, DECL th_td_depr, NULL +}, +{ "textarea", 0, 0, 0, 0, 0, 0, 1, "multi-line text field ", + DECL html_pcdata, NULL, DECL textarea_attrs, NULL, DECL rows_cols_attr +}, +{ "tfoot", 0, 1, 0, 0, 0, 0, 0, "table footer ", + DECL tr_elt , "tr" , DECL talign_attrs, NULL, NULL +}, +{ "th", 0, 1, 0, 0, 0, 0, 0, "table header cell", + DECL html_flow, NULL, DECL th_td_attr, DECL th_td_depr, NULL +}, +{ "thead", 0, 1, 0, 0, 0, 0, 0, "table header ", + DECL tr_elt , "tr" , DECL talign_attrs, NULL, NULL +}, +{ "title", 0, 0, 0, 0, 0, 0, 0, "document title ", + DECL html_pcdata, NULL, DECL i18n_attrs, NULL, NULL +}, +{ "tr", 0, 0, 0, 0, 0, 0, 0, "table row ", + DECL tr_contents , "td" , DECL talign_attrs, DECL bgcolor_attr, NULL +}, +{ "tt", 0, 3, 0, 0, 0, 0, 1, "teletype or monospaced text style", + DECL html_inline, NULL, DECL html_attrs, NULL, NULL +}, +{ "u", 0, 3, 0, 0, 1, 1, 1, "underlined text style", + DECL html_inline, NULL, NULL, DECL html_attrs, NULL +}, +{ "ul", 0, 0, 0, 0, 0, 0, 0, "unordered list ", + DECL li_elt , "li" , DECL html_attrs, DECL ul_depr, NULL +}, +{ "var", 0, 0, 0, 0, 0, 0, 1, "instance of a variable or program argument", + DECL html_inline, NULL, DECL html_attrs, NULL, NULL +} +}; + +/* + * start tags that imply the end of current element + */ +static const char * const htmlStartClose[] = { +"form", "form", "p", "hr", "h1", "h2", "h3", "h4", "h5", "h6", + "dl", "ul", "ol", "menu", "dir", "address", "pre", + "listing", "xmp", "head", NULL, +"head", "p", NULL, +"title", "p", NULL, +"body", "head", "style", "link", "title", "p", NULL, +"frameset", "head", "style", "link", "title", "p", NULL, +"li", "p", "h1", "h2", "h3", "h4", "h5", "h6", "dl", "address", + "pre", "listing", "xmp", "head", "li", NULL, +"hr", "p", "head", NULL, +"h1", "p", "head", NULL, +"h2", "p", "head", NULL, +"h3", "p", "head", NULL, +"h4", "p", "head", NULL, +"h5", "p", "head", NULL, +"h6", "p", "head", NULL, +"dir", "p", "head", NULL, +"address", "p", "head", "ul", NULL, +"pre", "p", "head", "ul", NULL, +"listing", "p", "head", NULL, +"xmp", "p", "head", NULL, +"blockquote", "p", "head", NULL, +"dl", "p", "dt", "menu", "dir", "address", "pre", "listing", + "xmp", "head", NULL, +"dt", "p", "menu", "dir", "address", "pre", "listing", "xmp", + "head", "dd", NULL, +"dd", "p", "menu", "dir", "address", "pre", "listing", "xmp", + "head", "dt", NULL, +"ul", "p", "head", "ol", "menu", "dir", "address", "pre", + "listing", "xmp", NULL, +"ol", "p", "head", "ul", NULL, +"menu", "p", "head", "ul", NULL, +"p", "p", "head", "h1", "h2", "h3", "h4", "h5", "h6", NULL, +"div", "p", "head", NULL, +"noscript", "p", "head", NULL, +"center", "font", "b", "i", "p", "head", NULL, +"a", "a", NULL, +"caption", "p", NULL, +"colgroup", "caption", "colgroup", "col", "p", NULL, +"col", "caption", "col", "p", NULL, +"table", "p", "head", "h1", "h2", "h3", "h4", "h5", "h6", "pre", + "listing", "xmp", "a", NULL, +"th", "th", "td", "p", "span", "font", "a", "b", "i", "u", NULL, +"td", "th", "td", "p", "span", "font", "a", "b", "i", "u", NULL, +"tr", "th", "td", "tr", "caption", "col", "colgroup", "p", NULL, +"thead", "caption", "col", "colgroup", NULL, +"tfoot", "th", "td", "tr", "caption", "col", "colgroup", "thead", + "tbody", "p", NULL, +"tbody", "th", "td", "tr", "caption", "col", "colgroup", "thead", + "tfoot", "tbody", "p", NULL, +"optgroup", "option", NULL, +"option", "option", NULL, +"fieldset", "legend", "p", "head", "h1", "h2", "h3", "h4", "h5", "h6", + "pre", "listing", "xmp", "a", NULL, +NULL +}; + +/* + * The list of HTML elements which are supposed not to have + * CDATA content and where a p element will be implied + * + * TODO: extend that list by reading the HTML SGML DTD on + * implied paragraph + */ +static const char *const htmlNoContentElements[] = { + "html", + "head", + NULL +}; + +/* + * The list of HTML attributes which are of content %Script; + * NOTE: when adding ones, check htmlIsScriptAttribute() since + * it assumes the name starts with 'on' + */ +static const char *const htmlScriptAttributes[] = { + "onclick", + "ondblclick", + "onmousedown", + "onmouseup", + "onmouseover", + "onmousemove", + "onmouseout", + "onkeypress", + "onkeydown", + "onkeyup", + "onload", + "onunload", + "onfocus", + "onblur", + "onsubmit", + "onrest", + "onchange", + "onselect" +}; + +/* + * This table is used by the htmlparser to know what to do with + * broken html pages. By assigning different priorities to different + * elements the parser can decide how to handle extra endtags. + * Endtags are only allowed to close elements with lower or equal + * priority. + */ + +typedef struct { + const char *name; + int priority; +} elementPriority; + +static const elementPriority htmlEndPriority[] = { + {"div", 150}, + {"td", 160}, + {"th", 160}, + {"tr", 170}, + {"thead", 180}, + {"tbody", 180}, + {"tfoot", 180}, + {"table", 190}, + {"head", 200}, + {"body", 200}, + {"html", 220}, + {NULL, 100} /* Default priority */ +}; + +static const char** htmlStartCloseIndex[100]; +static int htmlStartCloseIndexinitialized = 0; + +/************************************************************************ + * * + * functions to handle HTML specific data * + * * + ************************************************************************/ + +/** + * htmlInitAutoClose: + * + * Initialize the htmlStartCloseIndex for fast lookup of closing tags names. + * This is not reentrant. Call xmlInitParser() once before processing in + * case of use in multithreaded programs. + */ +void +htmlInitAutoClose(void) { + int indx, i = 0; + + if (htmlStartCloseIndexinitialized) return; + + for (indx = 0;indx < 100;indx ++) htmlStartCloseIndex[indx] = NULL; + indx = 0; + while ((htmlStartClose[i] != NULL) && (indx < 100 - 1)) { + htmlStartCloseIndex[indx++] = (const char**) &htmlStartClose[i]; + while (htmlStartClose[i] != NULL) i++; + i++; + } + htmlStartCloseIndexinitialized = 1; +} + +/** + * htmlTagLookup: + * @tag: The tag name in lowercase + * + * Lookup the HTML tag in the ElementTable + * + * Returns the related htmlElemDescPtr or NULL if not found. + */ +const htmlElemDesc * +htmlTagLookup(const xmlChar *tag) { + unsigned int i; + + for (i = 0; i < (sizeof(html40ElementTable) / + sizeof(html40ElementTable[0]));i++) { + if (!xmlStrcasecmp(tag, BAD_CAST html40ElementTable[i].name)) + return((htmlElemDescPtr) &html40ElementTable[i]); + } + return(NULL); +} + +/** + * htmlGetEndPriority: + * @name: The name of the element to look up the priority for. + * + * Return value: The "endtag" priority. + **/ +static int +htmlGetEndPriority (const xmlChar *name) { + int i = 0; + + while ((htmlEndPriority[i].name != NULL) && + (!xmlStrEqual((const xmlChar *)htmlEndPriority[i].name, name))) + i++; + + return(htmlEndPriority[i].priority); +} + + +/** + * htmlCheckAutoClose: + * @newtag: The new tag name + * @oldtag: The old tag name + * + * Checks whether the new tag is one of the registered valid tags for + * closing old. + * Initialize the htmlStartCloseIndex for fast lookup of closing tags names. + * + * Returns 0 if no, 1 if yes. + */ +static int +htmlCheckAutoClose(const xmlChar * newtag, const xmlChar * oldtag) +{ + int i, indx; + const char **closed = NULL; + + if (htmlStartCloseIndexinitialized == 0) + htmlInitAutoClose(); + + /* inefficient, but not a big deal */ + for (indx = 0; indx < 100; indx++) { + closed = htmlStartCloseIndex[indx]; + if (closed == NULL) + return (0); + if (xmlStrEqual(BAD_CAST * closed, newtag)) + break; + } + + i = closed - htmlStartClose; + i++; + while (htmlStartClose[i] != NULL) { + if (xmlStrEqual(BAD_CAST htmlStartClose[i], oldtag)) { + return (1); + } + i++; + } + return (0); +} + +/** + * htmlAutoCloseOnClose: + * @ctxt: an HTML parser context + * @newtag: The new tag name + * @force: force the tag closure + * + * The HTML DTD allows an ending tag to implicitly close other tags. + */ +static void +htmlAutoCloseOnClose(htmlParserCtxtPtr ctxt, const xmlChar * newtag) +{ + const htmlElemDesc *info; + int i, priority; + + priority = htmlGetEndPriority(newtag); + + for (i = (ctxt->nameNr - 1); i >= 0; i--) { + + if (xmlStrEqual(newtag, ctxt->nameTab[i])) + break; + /* + * A missplaced endtag can only close elements with lower + * or equal priority, so if we find an element with higher + * priority before we find an element with + * matching name, we just ignore this endtag + */ + if (htmlGetEndPriority(ctxt->nameTab[i]) > priority) + return; + } + if (i < 0) + return; + + while (!xmlStrEqual(newtag, ctxt->name)) { + info = htmlTagLookup(ctxt->name); + if ((info != NULL) && (info->endTag == 3)) { + htmlParseErr(ctxt, XML_ERR_TAG_NAME_MISMATCH, + "Opening and ending tag mismatch: %s and %s\n", + newtag, ctxt->name); + } + if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL)) + ctxt->sax->endElement(ctxt->userData, ctxt->name); + htmlnamePop(ctxt); + } +} + +/** + * htmlAutoCloseOnEnd: + * @ctxt: an HTML parser context + * + * Close all remaining tags at the end of the stream + */ +static void +htmlAutoCloseOnEnd(htmlParserCtxtPtr ctxt) +{ + int i; + + if (ctxt->nameNr == 0) + return; + for (i = (ctxt->nameNr - 1); i >= 0; i--) { + if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL)) + ctxt->sax->endElement(ctxt->userData, ctxt->name); + htmlnamePop(ctxt); + } +} + +/** + * htmlAutoClose: + * @ctxt: an HTML parser context + * @newtag: The new tag name or NULL + * + * The HTML DTD allows a tag to implicitly close other tags. + * The list is kept in htmlStartClose array. This function is + * called when a new tag has been detected and generates the + * appropriates closes if possible/needed. + * If newtag is NULL this mean we are at the end of the resource + * and we should check + */ +static void +htmlAutoClose(htmlParserCtxtPtr ctxt, const xmlChar * newtag) +{ + while ((newtag != NULL) && (ctxt->name != NULL) && + (htmlCheckAutoClose(newtag, ctxt->name))) { + if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL)) + ctxt->sax->endElement(ctxt->userData, ctxt->name); + htmlnamePop(ctxt); + } + if (newtag == NULL) { + htmlAutoCloseOnEnd(ctxt); + return; + } + while ((newtag == NULL) && (ctxt->name != NULL) && + ((xmlStrEqual(ctxt->name, BAD_CAST "head")) || + (xmlStrEqual(ctxt->name, BAD_CAST "body")) || + (xmlStrEqual(ctxt->name, BAD_CAST "html")))) { + if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL)) + ctxt->sax->endElement(ctxt->userData, ctxt->name); + htmlnamePop(ctxt); + } +} + +/** + * htmlAutoCloseTag: + * @doc: the HTML document + * @name: The tag name + * @elem: the HTML element + * + * The HTML DTD allows a tag to implicitly close other tags. + * The list is kept in htmlStartClose array. This function checks + * if the element or one of it's children would autoclose the + * given tag. + * + * Returns 1 if autoclose, 0 otherwise + */ +int +htmlAutoCloseTag(htmlDocPtr doc, const xmlChar *name, htmlNodePtr elem) { + htmlNodePtr child; + + if (elem == NULL) return(1); + if (xmlStrEqual(name, elem->name)) return(0); + if (htmlCheckAutoClose(elem->name, name)) return(1); + child = elem->children; + while (child != NULL) { + if (htmlAutoCloseTag(doc, name, child)) return(1); + child = child->next; + } + return(0); +} + +/** + * htmlIsAutoClosed: + * @doc: the HTML document + * @elem: the HTML element + * + * The HTML DTD allows a tag to implicitly close other tags. + * The list is kept in htmlStartClose array. This function checks + * if a tag is autoclosed by one of it's child + * + * Returns 1 if autoclosed, 0 otherwise + */ +int +htmlIsAutoClosed(htmlDocPtr doc, htmlNodePtr elem) { + htmlNodePtr child; + + if (elem == NULL) return(1); + child = elem->children; + while (child != NULL) { + if (htmlAutoCloseTag(doc, elem->name, child)) return(1); + child = child->next; + } + return(0); +} + +/** + * htmlCheckImplied: + * @ctxt: an HTML parser context + * @newtag: The new tag name + * + * The HTML DTD allows a tag to exists only implicitly + * called when a new tag has been detected and generates the + * appropriates implicit tags if missing + */ +static void +htmlCheckImplied(htmlParserCtxtPtr ctxt, const xmlChar *newtag) { + if (!htmlOmittedDefaultValue) + return; + if (xmlStrEqual(newtag, BAD_CAST"html")) + return; + if (ctxt->nameNr <= 0) { + htmlnamePush(ctxt, BAD_CAST"html"); + if ((ctxt->sax != NULL) && (ctxt->sax->startElement != NULL)) + ctxt->sax->startElement(ctxt->userData, BAD_CAST"html", NULL); + } + if ((xmlStrEqual(newtag, BAD_CAST"body")) || (xmlStrEqual(newtag, BAD_CAST"head"))) + return; + if ((ctxt->nameNr <= 1) && + ((xmlStrEqual(newtag, BAD_CAST"script")) || + (xmlStrEqual(newtag, BAD_CAST"style")) || + (xmlStrEqual(newtag, BAD_CAST"meta")) || + (xmlStrEqual(newtag, BAD_CAST"link")) || + (xmlStrEqual(newtag, BAD_CAST"title")) || + (xmlStrEqual(newtag, BAD_CAST"base")))) { + /* + * dropped OBJECT ... i you put it first BODY will be + * assumed ! + */ + htmlnamePush(ctxt, BAD_CAST"head"); + if ((ctxt->sax != NULL) && (ctxt->sax->startElement != NULL)) + ctxt->sax->startElement(ctxt->userData, BAD_CAST"head", NULL); + } else if ((!xmlStrEqual(newtag, BAD_CAST"noframes")) && + (!xmlStrEqual(newtag, BAD_CAST"frame")) && + (!xmlStrEqual(newtag, BAD_CAST"frameset"))) { + int i; + for (i = 0;i < ctxt->nameNr;i++) { + if (xmlStrEqual(ctxt->nameTab[i], BAD_CAST"body")) { + return; + } + if (xmlStrEqual(ctxt->nameTab[i], BAD_CAST"head")) { + return; + } + } + + htmlnamePush(ctxt, BAD_CAST"body"); + if ((ctxt->sax != NULL) && (ctxt->sax->startElement != NULL)) + ctxt->sax->startElement(ctxt->userData, BAD_CAST"body", NULL); + } +} + +/** + * htmlCheckParagraph + * @ctxt: an HTML parser context + * + * Check whether a p element need to be implied before inserting + * characters in the current element. + * + * Returns 1 if a paragraph has been inserted, 0 if not and -1 + * in case of error. + */ + +static int +htmlCheckParagraph(htmlParserCtxtPtr ctxt) { + const xmlChar *tag; + int i; + + if (ctxt == NULL) + return(-1); + tag = ctxt->name; + if (tag == NULL) { + htmlAutoClose(ctxt, BAD_CAST"p"); + htmlCheckImplied(ctxt, BAD_CAST"p"); + htmlnamePush(ctxt, BAD_CAST"p"); + if ((ctxt->sax != NULL) && (ctxt->sax->startElement != NULL)) + ctxt->sax->startElement(ctxt->userData, BAD_CAST"p", NULL); + return(1); + } + if (!htmlOmittedDefaultValue) + return(0); + for (i = 0; htmlNoContentElements[i] != NULL; i++) { + if (xmlStrEqual(tag, BAD_CAST htmlNoContentElements[i])) { + htmlAutoClose(ctxt, BAD_CAST"p"); + htmlCheckImplied(ctxt, BAD_CAST"p"); + htmlnamePush(ctxt, BAD_CAST"p"); + if ((ctxt->sax != NULL) && (ctxt->sax->startElement != NULL)) + ctxt->sax->startElement(ctxt->userData, BAD_CAST"p", NULL); + return(1); + } + } + return(0); +} + +/** + * htmlIsScriptAttribute: + * @name: an attribute name + * + * Check if an attribute is of content type Script + * + * Returns 1 is the attribute is a script 0 otherwise + */ +int +htmlIsScriptAttribute(const xmlChar *name) { + unsigned int i; + + if (name == NULL) + return(0); + /* + * all script attributes start with 'on' + */ + if ((name[0] != 'o') || (name[1] != 'n')) + return(0); + for (i = 0; + i < sizeof(htmlScriptAttributes)/sizeof(htmlScriptAttributes[0]); + i++) { + if (xmlStrEqual(name, (const xmlChar *) htmlScriptAttributes[i])) + return(1); + } + return(0); +} + +/************************************************************************ + * * + * The list of HTML predefined entities * + * * + ************************************************************************/ + + +static const htmlEntityDesc html40EntitiesTable[] = { +/* + * the 4 absolute ones, plus apostrophe. + */ +{ 34, "quot", "quotation mark = APL quote, U+0022 ISOnum" }, +{ 38, "amp", "ampersand, U+0026 ISOnum" }, +{ 39, "apos", "single quote" }, +{ 60, "lt", "less-than sign, U+003C ISOnum" }, +{ 62, "gt", "greater-than sign, U+003E ISOnum" }, + +/* + * A bunch still in the 128-255 range + * Replacing them depend really on the charset used. + */ +{ 160, "nbsp", "no-break space = non-breaking space, U+00A0 ISOnum" }, +{ 161, "iexcl","inverted exclamation mark, U+00A1 ISOnum" }, +{ 162, "cent", "cent sign, U+00A2 ISOnum" }, +{ 163, "pound","pound sign, U+00A3 ISOnum" }, +{ 164, "curren","currency sign, U+00A4 ISOnum" }, +{ 165, "yen", "yen sign = yuan sign, U+00A5 ISOnum" }, +{ 166, "brvbar","broken bar = broken vertical bar, U+00A6 ISOnum" }, +{ 167, "sect", "section sign, U+00A7 ISOnum" }, +{ 168, "uml", "diaeresis = spacing diaeresis, U+00A8 ISOdia" }, +{ 169, "copy", "copyright sign, U+00A9 ISOnum" }, +{ 170, "ordf", "feminine ordinal indicator, U+00AA ISOnum" }, +{ 171, "laquo","left-pointing double angle quotation mark = left pointing guillemet, U+00AB ISOnum" }, +{ 172, "not", "not sign, U+00AC ISOnum" }, +{ 173, "shy", "soft hyphen = discretionary hyphen, U+00AD ISOnum" }, +{ 174, "reg", "registered sign = registered trade mark sign, U+00AE ISOnum" }, +{ 175, "macr", "macron = spacing macron = overline = APL overbar, U+00AF ISOdia" }, +{ 176, "deg", "degree sign, U+00B0 ISOnum" }, +{ 177, "plusmn","plus-minus sign = plus-or-minus sign, U+00B1 ISOnum" }, +{ 178, "sup2", "superscript two = superscript digit two = squared, U+00B2 ISOnum" }, +{ 179, "sup3", "superscript three = superscript digit three = cubed, U+00B3 ISOnum" }, +{ 180, "acute","acute accent = spacing acute, U+00B4 ISOdia" }, +{ 181, "micro","micro sign, U+00B5 ISOnum" }, +{ 182, "para", "pilcrow sign = paragraph sign, U+00B6 ISOnum" }, +{ 183, "middot","middle dot = Georgian comma Greek middle dot, U+00B7 ISOnum" }, +{ 184, "cedil","cedilla = spacing cedilla, U+00B8 ISOdia" }, +{ 185, "sup1", "superscript one = superscript digit one, U+00B9 ISOnum" }, +{ 186, "ordm", "masculine ordinal indicator, U+00BA ISOnum" }, +{ 187, "raquo","right-pointing double angle quotation mark right pointing guillemet, U+00BB ISOnum" }, +{ 188, "frac14","vulgar fraction one quarter = fraction one quarter, U+00BC ISOnum" }, +{ 189, "frac12","vulgar fraction one half = fraction one half, U+00BD ISOnum" }, +{ 190, "frac34","vulgar fraction three quarters = fraction three quarters, U+00BE ISOnum" }, +{ 191, "iquest","inverted question mark = turned question mark, U+00BF ISOnum" }, +{ 192, "Agrave","latin capital letter A with grave = latin capital letter A grave, U+00C0 ISOlat1" }, +{ 193, "Aacute","latin capital letter A with acute, U+00C1 ISOlat1" }, +{ 194, "Acirc","latin capital letter A with circumflex, U+00C2 ISOlat1" }, +{ 195, "Atilde","latin capital letter A with tilde, U+00C3 ISOlat1" }, +{ 196, "Auml", "latin capital letter A with diaeresis, U+00C4 ISOlat1" }, +{ 197, "Aring","latin capital letter A with ring above = latin capital letter A ring, U+00C5 ISOlat1" }, +{ 198, "AElig","latin capital letter AE = latin capital ligature AE, U+00C6 ISOlat1" }, +{ 199, "Ccedil","latin capital letter C with cedilla, U+00C7 ISOlat1" }, +{ 200, "Egrave","latin capital letter E with grave, U+00C8 ISOlat1" }, +{ 201, "Eacute","latin capital letter E with acute, U+00C9 ISOlat1" }, +{ 202, "Ecirc","latin capital letter E with circumflex, U+00CA ISOlat1" }, +{ 203, "Euml", "latin capital letter E with diaeresis, U+00CB ISOlat1" }, +{ 204, "Igrave","latin capital letter I with grave, U+00CC ISOlat1" }, +{ 205, "Iacute","latin capital letter I with acute, U+00CD ISOlat1" }, +{ 206, "Icirc","latin capital letter I with circumflex, U+00CE ISOlat1" }, +{ 207, "Iuml", "latin capital letter I with diaeresis, U+00CF ISOlat1" }, +{ 208, "ETH", "latin capital letter ETH, U+00D0 ISOlat1" }, +{ 209, "Ntilde","latin capital letter N with tilde, U+00D1 ISOlat1" }, +{ 210, "Ograve","latin capital letter O with grave, U+00D2 ISOlat1" }, +{ 211, "Oacute","latin capital letter O with acute, U+00D3 ISOlat1" }, +{ 212, "Ocirc","latin capital letter O with circumflex, U+00D4 ISOlat1" }, +{ 213, "Otilde","latin capital letter O with tilde, U+00D5 ISOlat1" }, +{ 214, "Ouml", "latin capital letter O with diaeresis, U+00D6 ISOlat1" }, +{ 215, "times","multiplication sign, U+00D7 ISOnum" }, +{ 216, "Oslash","latin capital letter O with stroke latin capital letter O slash, U+00D8 ISOlat1" }, +{ 217, "Ugrave","latin capital letter U with grave, U+00D9 ISOlat1" }, +{ 218, "Uacute","latin capital letter U with acute, U+00DA ISOlat1" }, +{ 219, "Ucirc","latin capital letter U with circumflex, U+00DB ISOlat1" }, +{ 220, "Uuml", "latin capital letter U with diaeresis, U+00DC ISOlat1" }, +{ 221, "Yacute","latin capital letter Y with acute, U+00DD ISOlat1" }, +{ 222, "THORN","latin capital letter THORN, U+00DE ISOlat1" }, +{ 223, "szlig","latin small letter sharp s = ess-zed, U+00DF ISOlat1" }, +{ 224, "agrave","latin small letter a with grave = latin small letter a grave, U+00E0 ISOlat1" }, +{ 225, "aacute","latin small letter a with acute, U+00E1 ISOlat1" }, +{ 226, "acirc","latin small letter a with circumflex, U+00E2 ISOlat1" }, +{ 227, "atilde","latin small letter a with tilde, U+00E3 ISOlat1" }, +{ 228, "auml", "latin small letter a with diaeresis, U+00E4 ISOlat1" }, +{ 229, "aring","latin small letter a with ring above = latin small letter a ring, U+00E5 ISOlat1" }, +{ 230, "aelig","latin small letter ae = latin small ligature ae, U+00E6 ISOlat1" }, +{ 231, "ccedil","latin small letter c with cedilla, U+00E7 ISOlat1" }, +{ 232, "egrave","latin small letter e with grave, U+00E8 ISOlat1" }, +{ 233, "eacute","latin small letter e with acute, U+00E9 ISOlat1" }, +{ 234, "ecirc","latin small letter e with circumflex, U+00EA ISOlat1" }, +{ 235, "euml", "latin small letter e with diaeresis, U+00EB ISOlat1" }, +{ 236, "igrave","latin small letter i with grave, U+00EC ISOlat1" }, +{ 237, "iacute","latin small letter i with acute, U+00ED ISOlat1" }, +{ 238, "icirc","latin small letter i with circumflex, U+00EE ISOlat1" }, +{ 239, "iuml", "latin small letter i with diaeresis, U+00EF ISOlat1" }, +{ 240, "eth", "latin small letter eth, U+00F0 ISOlat1" }, +{ 241, "ntilde","latin small letter n with tilde, U+00F1 ISOlat1" }, +{ 242, "ograve","latin small letter o with grave, U+00F2 ISOlat1" }, +{ 243, "oacute","latin small letter o with acute, U+00F3 ISOlat1" }, +{ 244, "ocirc","latin small letter o with circumflex, U+00F4 ISOlat1" }, +{ 245, "otilde","latin small letter o with tilde, U+00F5 ISOlat1" }, +{ 246, "ouml", "latin small letter o with diaeresis, U+00F6 ISOlat1" }, +{ 247, "divide","division sign, U+00F7 ISOnum" }, +{ 248, "oslash","latin small letter o with stroke, = latin small letter o slash, U+00F8 ISOlat1" }, +{ 249, "ugrave","latin small letter u with grave, U+00F9 ISOlat1" }, +{ 250, "uacute","latin small letter u with acute, U+00FA ISOlat1" }, +{ 251, "ucirc","latin small letter u with circumflex, U+00FB ISOlat1" }, +{ 252, "uuml", "latin small letter u with diaeresis, U+00FC ISOlat1" }, +{ 253, "yacute","latin small letter y with acute, U+00FD ISOlat1" }, +{ 254, "thorn","latin small letter thorn with, U+00FE ISOlat1" }, +{ 255, "yuml", "latin small letter y with diaeresis, U+00FF ISOlat1" }, + +{ 338, "OElig","latin capital ligature OE, U+0152 ISOlat2" }, +{ 339, "oelig","latin small ligature oe, U+0153 ISOlat2" }, +{ 352, "Scaron","latin capital letter S with caron, U+0160 ISOlat2" }, +{ 353, "scaron","latin small letter s with caron, U+0161 ISOlat2" }, +{ 376, "Yuml", "latin capital letter Y with diaeresis, U+0178 ISOlat2" }, + +/* + * Anything below should really be kept as entities references + */ +{ 402, "fnof", "latin small f with hook = function = florin, U+0192 ISOtech" }, + +{ 710, "circ", "modifier letter circumflex accent, U+02C6 ISOpub" }, +{ 732, "tilde","small tilde, U+02DC ISOdia" }, + +{ 913, "Alpha","greek capital letter alpha, U+0391" }, +{ 914, "Beta", "greek capital letter beta, U+0392" }, +{ 915, "Gamma","greek capital letter gamma, U+0393 ISOgrk3" }, +{ 916, "Delta","greek capital letter delta, U+0394 ISOgrk3" }, +{ 917, "Epsilon","greek capital letter epsilon, U+0395" }, +{ 918, "Zeta", "greek capital letter zeta, U+0396" }, +{ 919, "Eta", "greek capital letter eta, U+0397" }, +{ 920, "Theta","greek capital letter theta, U+0398 ISOgrk3" }, +{ 921, "Iota", "greek capital letter iota, U+0399" }, +{ 922, "Kappa","greek capital letter kappa, U+039A" }, +{ 923, "Lambda", "greek capital letter lambda, U+039B ISOgrk3" }, +{ 924, "Mu", "greek capital letter mu, U+039C" }, +{ 925, "Nu", "greek capital letter nu, U+039D" }, +{ 926, "Xi", "greek capital letter xi, U+039E ISOgrk3" }, +{ 927, "Omicron","greek capital letter omicron, U+039F" }, +{ 928, "Pi", "greek capital letter pi, U+03A0 ISOgrk3" }, +{ 929, "Rho", "greek capital letter rho, U+03A1" }, +{ 931, "Sigma","greek capital letter sigma, U+03A3 ISOgrk3" }, +{ 932, "Tau", "greek capital letter tau, U+03A4" }, +{ 933, "Upsilon","greek capital letter upsilon, U+03A5 ISOgrk3" }, +{ 934, "Phi", "greek capital letter phi, U+03A6 ISOgrk3" }, +{ 935, "Chi", "greek capital letter chi, U+03A7" }, +{ 936, "Psi", "greek capital letter psi, U+03A8 ISOgrk3" }, +{ 937, "Omega","greek capital letter omega, U+03A9 ISOgrk3" }, + +{ 945, "alpha","greek small letter alpha, U+03B1 ISOgrk3" }, +{ 946, "beta", "greek small letter beta, U+03B2 ISOgrk3" }, +{ 947, "gamma","greek small letter gamma, U+03B3 ISOgrk3" }, +{ 948, "delta","greek small letter delta, U+03B4 ISOgrk3" }, +{ 949, "epsilon","greek small letter epsilon, U+03B5 ISOgrk3" }, +{ 950, "zeta", "greek small letter zeta, U+03B6 ISOgrk3" }, +{ 951, "eta", "greek small letter eta, U+03B7 ISOgrk3" }, +{ 952, "theta","greek small letter theta, U+03B8 ISOgrk3" }, +{ 953, "iota", "greek small letter iota, U+03B9 ISOgrk3" }, +{ 954, "kappa","greek small letter kappa, U+03BA ISOgrk3" }, +{ 955, "lambda","greek small letter lambda, U+03BB ISOgrk3" }, +{ 956, "mu", "greek small letter mu, U+03BC ISOgrk3" }, +{ 957, "nu", "greek small letter nu, U+03BD ISOgrk3" }, +{ 958, "xi", "greek small letter xi, U+03BE ISOgrk3" }, +{ 959, "omicron","greek small letter omicron, U+03BF NEW" }, +{ 960, "pi", "greek small letter pi, U+03C0 ISOgrk3" }, +{ 961, "rho", "greek small letter rho, U+03C1 ISOgrk3" }, +{ 962, "sigmaf","greek small letter final sigma, U+03C2 ISOgrk3" }, +{ 963, "sigma","greek small letter sigma, U+03C3 ISOgrk3" }, +{ 964, "tau", "greek small letter tau, U+03C4 ISOgrk3" }, +{ 965, "upsilon","greek small letter upsilon, U+03C5 ISOgrk3" }, +{ 966, "phi", "greek small letter phi, U+03C6 ISOgrk3" }, +{ 967, "chi", "greek small letter chi, U+03C7 ISOgrk3" }, +{ 968, "psi", "greek small letter psi, U+03C8 ISOgrk3" }, +{ 969, "omega","greek small letter omega, U+03C9 ISOgrk3" }, +{ 977, "thetasym","greek small letter theta symbol, U+03D1 NEW" }, +{ 978, "upsih","greek upsilon with hook symbol, U+03D2 NEW" }, +{ 982, "piv", "greek pi symbol, U+03D6 ISOgrk3" }, + +{ 8194, "ensp", "en space, U+2002 ISOpub" }, +{ 8195, "emsp", "em space, U+2003 ISOpub" }, +{ 8201, "thinsp","thin space, U+2009 ISOpub" }, +{ 8204, "zwnj", "zero width non-joiner, U+200C NEW RFC 2070" }, +{ 8205, "zwj", "zero width joiner, U+200D NEW RFC 2070" }, +{ 8206, "lrm", "left-to-right mark, U+200E NEW RFC 2070" }, +{ 8207, "rlm", "right-to-left mark, U+200F NEW RFC 2070" }, +{ 8211, "ndash","en dash, U+2013 ISOpub" }, +{ 8212, "mdash","em dash, U+2014 ISOpub" }, +{ 8216, "lsquo","left single quotation mark, U+2018 ISOnum" }, +{ 8217, "rsquo","right single quotation mark, U+2019 ISOnum" }, +{ 8218, "sbquo","single low-9 quotation mark, U+201A NEW" }, +{ 8220, "ldquo","left double quotation mark, U+201C ISOnum" }, +{ 8221, "rdquo","right double quotation mark, U+201D ISOnum" }, +{ 8222, "bdquo","double low-9 quotation mark, U+201E NEW" }, +{ 8224, "dagger","dagger, U+2020 ISOpub" }, +{ 8225, "Dagger","double dagger, U+2021 ISOpub" }, + +{ 8226, "bull", "bullet = black small circle, U+2022 ISOpub" }, +{ 8230, "hellip","horizontal ellipsis = three dot leader, U+2026 ISOpub" }, + +{ 8240, "permil","per mille sign, U+2030 ISOtech" }, + +{ 8242, "prime","prime = minutes = feet, U+2032 ISOtech" }, +{ 8243, "Prime","double prime = seconds = inches, U+2033 ISOtech" }, + +{ 8249, "lsaquo","single left-pointing angle quotation mark, U+2039 ISO proposed" }, +{ 8250, "rsaquo","single right-pointing angle quotation mark, U+203A ISO proposed" }, + +{ 8254, "oline","overline = spacing overscore, U+203E NEW" }, +{ 8260, "frasl","fraction slash, U+2044 NEW" }, + +{ 8364, "euro", "euro sign, U+20AC NEW" }, + +{ 8465, "image","blackletter capital I = imaginary part, U+2111 ISOamso" }, +{ 8472, "weierp","script capital P = power set = Weierstrass p, U+2118 ISOamso" }, +{ 8476, "real", "blackletter capital R = real part symbol, U+211C ISOamso" }, +{ 8482, "trade","trade mark sign, U+2122 ISOnum" }, +{ 8501, "alefsym","alef symbol = first transfinite cardinal, U+2135 NEW" }, +{ 8592, "larr", "leftwards arrow, U+2190 ISOnum" }, +{ 8593, "uarr", "upwards arrow, U+2191 ISOnum" }, +{ 8594, "rarr", "rightwards arrow, U+2192 ISOnum" }, +{ 8595, "darr", "downwards arrow, U+2193 ISOnum" }, +{ 8596, "harr", "left right arrow, U+2194 ISOamsa" }, +{ 8629, "crarr","downwards arrow with corner leftwards = carriage return, U+21B5 NEW" }, +{ 8656, "lArr", "leftwards double arrow, U+21D0 ISOtech" }, +{ 8657, "uArr", "upwards double arrow, U+21D1 ISOamsa" }, +{ 8658, "rArr", "rightwards double arrow, U+21D2 ISOtech" }, +{ 8659, "dArr", "downwards double arrow, U+21D3 ISOamsa" }, +{ 8660, "hArr", "left right double arrow, U+21D4 ISOamsa" }, + +{ 8704, "forall","for all, U+2200 ISOtech" }, +{ 8706, "part", "partial differential, U+2202 ISOtech" }, +{ 8707, "exist","there exists, U+2203 ISOtech" }, +{ 8709, "empty","empty set = null set = diameter, U+2205 ISOamso" }, +{ 8711, "nabla","nabla = backward difference, U+2207 ISOtech" }, +{ 8712, "isin", "element of, U+2208 ISOtech" }, +{ 8713, "notin","not an element of, U+2209 ISOtech" }, +{ 8715, "ni", "contains as member, U+220B ISOtech" }, +{ 8719, "prod", "n-ary product = product sign, U+220F ISOamsb" }, +{ 8721, "sum", "n-ary summation, U+2211 ISOamsb" }, +{ 8722, "minus","minus sign, U+2212 ISOtech" }, +{ 8727, "lowast","asterisk operator, U+2217 ISOtech" }, +{ 8730, "radic","square root = radical sign, U+221A ISOtech" }, +{ 8733, "prop", "proportional to, U+221D ISOtech" }, +{ 8734, "infin","infinity, U+221E ISOtech" }, +{ 8736, "ang", "angle, U+2220 ISOamso" }, +{ 8743, "and", "logical and = wedge, U+2227 ISOtech" }, +{ 8744, "or", "logical or = vee, U+2228 ISOtech" }, +{ 8745, "cap", "intersection = cap, U+2229 ISOtech" }, +{ 8746, "cup", "union = cup, U+222A ISOtech" }, +{ 8747, "int", "integral, U+222B ISOtech" }, +{ 8756, "there4","therefore, U+2234 ISOtech" }, +{ 8764, "sim", "tilde operator = varies with = similar to, U+223C ISOtech" }, +{ 8773, "cong", "approximately equal to, U+2245 ISOtech" }, +{ 8776, "asymp","almost equal to = asymptotic to, U+2248 ISOamsr" }, +{ 8800, "ne", "not equal to, U+2260 ISOtech" }, +{ 8801, "equiv","identical to, U+2261 ISOtech" }, +{ 8804, "le", "less-than or equal to, U+2264 ISOtech" }, +{ 8805, "ge", "greater-than or equal to, U+2265 ISOtech" }, +{ 8834, "sub", "subset of, U+2282 ISOtech" }, +{ 8835, "sup", "superset of, U+2283 ISOtech" }, +{ 8836, "nsub", "not a subset of, U+2284 ISOamsn" }, +{ 8838, "sube", "subset of or equal to, U+2286 ISOtech" }, +{ 8839, "supe", "superset of or equal to, U+2287 ISOtech" }, +{ 8853, "oplus","circled plus = direct sum, U+2295 ISOamsb" }, +{ 8855, "otimes","circled times = vector product, U+2297 ISOamsb" }, +{ 8869, "perp", "up tack = orthogonal to = perpendicular, U+22A5 ISOtech" }, +{ 8901, "sdot", "dot operator, U+22C5 ISOamsb" }, +{ 8968, "lceil","left ceiling = apl upstile, U+2308 ISOamsc" }, +{ 8969, "rceil","right ceiling, U+2309 ISOamsc" }, +{ 8970, "lfloor","left floor = apl downstile, U+230A ISOamsc" }, +{ 8971, "rfloor","right floor, U+230B ISOamsc" }, +{ 9001, "lang", "left-pointing angle bracket = bra, U+2329 ISOtech" }, +{ 9002, "rang", "right-pointing angle bracket = ket, U+232A ISOtech" }, +{ 9674, "loz", "lozenge, U+25CA ISOpub" }, + +{ 9824, "spades","black spade suit, U+2660 ISOpub" }, +{ 9827, "clubs","black club suit = shamrock, U+2663 ISOpub" }, +{ 9829, "hearts","black heart suit = valentine, U+2665 ISOpub" }, +{ 9830, "diams","black diamond suit, U+2666 ISOpub" }, + +}; + +/************************************************************************ + * * + * Commodity functions to handle entities * + * * + ************************************************************************/ + +/* + * Macro used to grow the current buffer. + */ +#define growBuffer(buffer) { \ + xmlChar *tmp; \ + buffer##_size *= 2; \ + tmp = (xmlChar *) xmlRealloc(buffer, buffer##_size * sizeof(xmlChar)); \ + if (tmp == NULL) { \ + htmlErrMemory(ctxt, "growing buffer\n"); \ + xmlFree(buffer); \ + return(NULL); \ + } \ + buffer = tmp; \ +} + +/** + * htmlEntityLookup: + * @name: the entity name + * + * Lookup the given entity in EntitiesTable + * + * TODO: the linear scan is really ugly, an hash table is really needed. + * + * Returns the associated htmlEntityDescPtr if found, NULL otherwise. + */ +const htmlEntityDesc * +htmlEntityLookup(const xmlChar *name) { + unsigned int i; + + for (i = 0;i < (sizeof(html40EntitiesTable)/ + sizeof(html40EntitiesTable[0]));i++) { + if (xmlStrEqual(name, BAD_CAST html40EntitiesTable[i].name)) { + return((htmlEntityDescPtr) &html40EntitiesTable[i]); + } + } + return(NULL); +} + +/** + * htmlEntityValueLookup: + * @value: the entity's unicode value + * + * Lookup the given entity in EntitiesTable + * + * TODO: the linear scan is really ugly, an hash table is really needed. + * + * Returns the associated htmlEntityDescPtr if found, NULL otherwise. + */ +const htmlEntityDesc * +htmlEntityValueLookup(unsigned int value) { + unsigned int i; + + for (i = 0;i < (sizeof(html40EntitiesTable)/ + sizeof(html40EntitiesTable[0]));i++) { + if (html40EntitiesTable[i].value >= value) { + if (html40EntitiesTable[i].value > value) + break; + return((htmlEntityDescPtr) &html40EntitiesTable[i]); + } + } + return(NULL); +} + +/** + * UTF8ToHtml: + * @out: a pointer to an array of bytes to store the result + * @outlen: the length of @out + * @in: a pointer to an array of UTF-8 chars + * @inlen: the length of @in + * + * Take a block of UTF-8 chars in and try to convert it to an ASCII + * plus HTML entities block of chars out. + * + * Returns 0 if success, -2 if the transcoding fails, or -1 otherwise + * The value of @inlen after return is the number of octets consumed + * as the return value is positive, else unpredictable. + * The value of @outlen after return is the number of octets consumed. + */ +int +UTF8ToHtml(unsigned char* out, int *outlen, + const unsigned char* in, int *inlen) { + const unsigned char* processed = in; + const unsigned char* outend; + const unsigned char* outstart = out; + const unsigned char* instart = in; + const unsigned char* inend; + unsigned int c, d; + int trailing; + + if ((out == NULL) || (outlen == NULL) || (inlen == NULL)) return(-1); + if (in == NULL) { + /* + * initialization nothing to do + */ + *outlen = 0; + *inlen = 0; + return(0); + } + inend = in + (*inlen); + outend = out + (*outlen); + while (in < inend) { + d = *in++; + if (d < 0x80) { c= d; trailing= 0; } + else if (d < 0xC0) { + /* trailing byte in leading position */ + *outlen = out - outstart; + *inlen = processed - instart; + return(-2); + } else if (d < 0xE0) { c= d & 0x1F; trailing= 1; } + else if (d < 0xF0) { c= d & 0x0F; trailing= 2; } + else if (d < 0xF8) { c= d & 0x07; trailing= 3; } + else { + /* no chance for this in Ascii */ + *outlen = out - outstart; + *inlen = processed - instart; + return(-2); + } + + if (inend - in < trailing) { + break; + } + + for ( ; trailing; trailing--) { + if ((in >= inend) || (((d= *in++) & 0xC0) != 0x80)) + break; + c <<= 6; + c |= d & 0x3F; + } + + /* assertion: c is a single UTF-4 value */ + if (c < 0x80) { + if (out + 1 >= outend) + break; + *out++ = c; + } else { + int len; + const htmlEntityDesc * ent; + + /* + * Try to lookup a predefined HTML entity for it + */ + + ent = htmlEntityValueLookup(c); + if (ent == NULL) { + /* no chance for this in Ascii */ + *outlen = out - outstart; + *inlen = processed - instart; + return(-2); + } + len = strlen(ent->name); + if (out + 2 + len >= outend) + break; + *out++ = '&'; + memcpy(out, ent->name, len); + out += len; + *out++ = ';'; + } + processed = in; + } + *outlen = out - outstart; + *inlen = processed - instart; + return(0); +} + +/** + * htmlEncodeEntities: + * @out: a pointer to an array of bytes to store the result + * @outlen: the length of @out + * @in: a pointer to an array of UTF-8 chars + * @inlen: the length of @in + * @quoteChar: the quote character to escape (' or ") or zero. + * + * Take a block of UTF-8 chars in and try to convert it to an ASCII + * plus HTML entities block of chars out. + * + * Returns 0 if success, -2 if the transcoding fails, or -1 otherwise + * The value of @inlen after return is the number of octets consumed + * as the return value is positive, else unpredictable. + * The value of @outlen after return is the number of octets consumed. + */ +int +htmlEncodeEntities(unsigned char* out, int *outlen, + const unsigned char* in, int *inlen, int quoteChar) { + const unsigned char* processed = in; + const unsigned char* outend; + const unsigned char* outstart = out; + const unsigned char* instart = in; + const unsigned char* inend; + unsigned int c, d; + int trailing; + + if ((out == NULL) || (outlen == NULL) || (inlen == NULL) || (in == NULL)) + return(-1); + outend = out + (*outlen); + inend = in + (*inlen); + while (in < inend) { + d = *in++; + if (d < 0x80) { c= d; trailing= 0; } + else if (d < 0xC0) { + /* trailing byte in leading position */ + *outlen = out - outstart; + *inlen = processed - instart; + return(-2); + } else if (d < 0xE0) { c= d & 0x1F; trailing= 1; } + else if (d < 0xF0) { c= d & 0x0F; trailing= 2; } + else if (d < 0xF8) { c= d & 0x07; trailing= 3; } + else { + /* no chance for this in Ascii */ + *outlen = out - outstart; + *inlen = processed - instart; + return(-2); + } + + if (inend - in < trailing) + break; + + while (trailing--) { + if (((d= *in++) & 0xC0) != 0x80) { + *outlen = out - outstart; + *inlen = processed - instart; + return(-2); + } + c <<= 6; + c |= d & 0x3F; + } + + /* assertion: c is a single UTF-4 value */ + if ((c < 0x80) && (c != (unsigned int) quoteChar) && + (c != '&') && (c != '<') && (c != '>')) { + if (out >= outend) + break; + *out++ = c; + } else { + const htmlEntityDesc * ent; + const char *cp; + char nbuf[16]; + int len; + + /* + * Try to lookup a predefined HTML entity for it + */ + ent = htmlEntityValueLookup(c); + if (ent == NULL) { + snprintf(nbuf, sizeof(nbuf), "#%u", c); + cp = nbuf; + } + else + cp = ent->name; + len = strlen(cp); + if (out + 2 + len > outend) + break; + *out++ = '&'; + memcpy(out, cp, len); + out += len; + *out++ = ';'; + } + processed = in; + } + *outlen = out - outstart; + *inlen = processed - instart; + return(0); +} + +/************************************************************************ + * * + * Commodity functions to handle streams * + * * + ************************************************************************/ + +/** + * htmlNewInputStream: + * @ctxt: an HTML parser context + * + * Create a new input stream structure + * Returns the new input stream or NULL + */ +static htmlParserInputPtr +htmlNewInputStream(htmlParserCtxtPtr ctxt) { + htmlParserInputPtr input; + + input = (xmlParserInputPtr) xmlMalloc(sizeof(htmlParserInput)); + if (input == NULL) { + htmlErrMemory(ctxt, "couldn't allocate a new input stream\n"); + return(NULL); + } + memset(input, 0, sizeof(htmlParserInput)); + input->filename = NULL; + input->directory = NULL; + input->base = NULL; + input->cur = NULL; + input->buf = NULL; + input->line = 1; + input->col = 1; + input->buf = NULL; + input->free = NULL; + input->version = NULL; + input->consumed = 0; + input->length = 0; + return(input); +} + + +/************************************************************************ + * * + * Commodity functions, cleanup needed ? * + * * + ************************************************************************/ +/* + * all tags allowing pc data from the html 4.01 loose dtd + * NOTE: it might be more apropriate to integrate this information + * into the html40ElementTable array but I don't want to risk any + * binary incomptibility + */ +static const char *allowPCData[] = { + "a", "abbr", "acronym", "address", "applet", "b", "bdo", "big", + "blockquote", "body", "button", "caption", "center", "cite", "code", + "dd", "del", "dfn", "div", "dt", "em", "font", "form", "h1", "h2", + "h3", "h4", "h5", "h6", "i", "iframe", "ins", "kbd", "label", "legend", + "li", "noframes", "noscript", "object", "p", "pre", "q", "s", "samp", + "small", "span", "strike", "strong", "td", "th", "tt", "u", "var" +}; + +/** + * areBlanks: + * @ctxt: an HTML parser context + * @str: a xmlChar * + * @len: the size of @str + * + * Is this a sequence of blank chars that one can ignore ? + * + * Returns 1 if ignorable 0 otherwise. + */ + +static int areBlanks(htmlParserCtxtPtr ctxt, const xmlChar *str, int len) { + unsigned int i; + int j; + xmlNodePtr lastChild; + xmlDtdPtr dtd; + + for (j = 0;j < len;j++) + if (!(IS_BLANK_CH(str[j]))) return(0); + + if (CUR == 0) return(1); + if (CUR != '<') return(0); + if (ctxt->name == NULL) + return(1); + if (xmlStrEqual(ctxt->name, BAD_CAST"html")) + return(1); + if (xmlStrEqual(ctxt->name, BAD_CAST"head")) + return(1); + + /* Only strip CDATA children of the body tag for strict HTML DTDs */ + if (xmlStrEqual(ctxt->name, BAD_CAST "body") && ctxt->myDoc != NULL) { + dtd = xmlGetIntSubset(ctxt->myDoc); + if (dtd != NULL && dtd->ExternalID != NULL) { + if (!xmlStrcasecmp(dtd->ExternalID, BAD_CAST "-//W3C//DTD HTML 4.01//EN") || + !xmlStrcasecmp(dtd->ExternalID, BAD_CAST "-//W3C//DTD HTML 4//EN")) + return(1); + } + } + + if (ctxt->node == NULL) return(0); + lastChild = xmlGetLastChild(ctxt->node); + while ((lastChild) && (lastChild->type == XML_COMMENT_NODE)) + lastChild = lastChild->prev; + if (lastChild == NULL) { + if ((ctxt->node->type != XML_ELEMENT_NODE) && + (ctxt->node->content != NULL)) return(0); + /* keep ws in constructs like ... ... + for all tags "b" allowing PCDATA */ + for ( i = 0; i < sizeof(allowPCData)/sizeof(allowPCData[0]); i++ ) { + if ( xmlStrEqual(ctxt->name, BAD_CAST allowPCData[i]) ) { + return(0); + } + } + } else if (xmlNodeIsText(lastChild)) { + return(0); + } else { + /* keep ws in constructs like

xy z

+ for all tags "p" allowing PCDATA */ + for ( i = 0; i < sizeof(allowPCData)/sizeof(allowPCData[0]); i++ ) { + if ( xmlStrEqual(lastChild->name, BAD_CAST allowPCData[i]) ) { + return(0); + } + } + } + return(1); +} + +/** + * htmlNewDocNoDtD: + * @URI: URI for the dtd, or NULL + * @ExternalID: the external ID of the DTD, or NULL + * + * Creates a new HTML document without a DTD node if @URI and @ExternalID + * are NULL + * + * Returns a new document, do not initialize the DTD if not provided + */ +htmlDocPtr +htmlNewDocNoDtD(const xmlChar *URI, const xmlChar *ExternalID) { + xmlDocPtr cur; + + /* + * Allocate a new document and fill the fields. + */ + cur = (xmlDocPtr) xmlMalloc(sizeof(xmlDoc)); + if (cur == NULL) { + htmlErrMemory(NULL, "HTML document creation failed\n"); + return(NULL); + } + memset(cur, 0, sizeof(xmlDoc)); + + cur->type = XML_HTML_DOCUMENT_NODE; + cur->version = NULL; + cur->intSubset = NULL; + cur->doc = cur; + cur->name = NULL; + cur->children = NULL; + cur->extSubset = NULL; + cur->oldNs = NULL; + cur->encoding = NULL; + cur->standalone = 1; + cur->compression = 0; + cur->ids = NULL; + cur->refs = NULL; + cur->_private = NULL; + cur->charset = XML_CHAR_ENCODING_UTF8; + if ((ExternalID != NULL) || + (URI != NULL)) + xmlCreateIntSubset(cur, BAD_CAST "html", ExternalID, URI); + return(cur); +} + +/** + * htmlNewDoc: + * @URI: URI for the dtd, or NULL + * @ExternalID: the external ID of the DTD, or NULL + * + * Creates a new HTML document + * + * Returns a new document + */ +htmlDocPtr +htmlNewDoc(const xmlChar *URI, const xmlChar *ExternalID) { + if ((URI == NULL) && (ExternalID == NULL)) + return(htmlNewDocNoDtD( + BAD_CAST "http://www.w3.org/TR/REC-html40/loose.dtd", + BAD_CAST "-//W3C//DTD HTML 4.0 Transitional//EN")); + + return(htmlNewDocNoDtD(URI, ExternalID)); +} + + +/************************************************************************ + * * + * The parser itself * + * Relates to http://www.w3.org/TR/html40 * + * * + ************************************************************************/ + +/************************************************************************ + * * + * The parser itself * + * * + ************************************************************************/ + +static const xmlChar * htmlParseNameComplex(xmlParserCtxtPtr ctxt); + +/** + * htmlParseHTMLName: + * @ctxt: an HTML parser context + * + * parse an HTML tag or attribute name, note that we convert it to lowercase + * since HTML names are not case-sensitive. + * + * Returns the Tag Name parsed or NULL + */ + +static const xmlChar * +htmlParseHTMLName(htmlParserCtxtPtr ctxt) { + int i = 0; + xmlChar loc[HTML_PARSER_BUFFER_SIZE]; + + if (!IS_ASCII_LETTER(CUR) && (CUR != '_') && + (CUR != ':')) return(NULL); + + while ((i < HTML_PARSER_BUFFER_SIZE) && + ((IS_ASCII_LETTER(CUR)) || (IS_ASCII_DIGIT(CUR)) || + (CUR == ':') || (CUR == '-') || (CUR == '_'))) { + if ((CUR >= 'A') && (CUR <= 'Z')) loc[i] = CUR + 0x20; + else loc[i] = CUR; + i++; + + NEXT; + } + + return(xmlDictLookup(ctxt->dict, loc, i)); +} + +/** + * htmlParseName: + * @ctxt: an HTML parser context + * + * parse an HTML name, this routine is case sensitive. + * + * Returns the Name parsed or NULL + */ + +static const xmlChar * +htmlParseName(htmlParserCtxtPtr ctxt) { + const xmlChar *in; + const xmlChar *ret; + int count = 0; + + GROW; + + /* + * Accelerator for simple ASCII names + */ + in = ctxt->input->cur; + if (((*in >= 0x61) && (*in <= 0x7A)) || + ((*in >= 0x41) && (*in <= 0x5A)) || + (*in == '_') || (*in == ':')) { + in++; + while (((*in >= 0x61) && (*in <= 0x7A)) || + ((*in >= 0x41) && (*in <= 0x5A)) || + ((*in >= 0x30) && (*in <= 0x39)) || + (*in == '_') || (*in == '-') || + (*in == ':') || (*in == '.')) + in++; + if ((*in > 0) && (*in < 0x80)) { + count = in - ctxt->input->cur; + ret = xmlDictLookup(ctxt->dict, ctxt->input->cur, count); + ctxt->input->cur = in; + ctxt->nbChars += count; + ctxt->input->col += count; + return(ret); + } + } + return(htmlParseNameComplex(ctxt)); +} + +static const xmlChar * +htmlParseNameComplex(xmlParserCtxtPtr ctxt) { + int len = 0, l; + int c; + int count = 0; + + /* + * Handler for more complex cases + */ + GROW; + c = CUR_CHAR(l); + if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */ + (!IS_LETTER(c) && (c != '_') && + (c != ':'))) { + return(NULL); + } + + while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */ + ((IS_LETTER(c)) || (IS_DIGIT(c)) || + (c == '.') || (c == '-') || + (c == '_') || (c == ':') || + (IS_COMBINING(c)) || + (IS_EXTENDER(c)))) { + if (count++ > 100) { + count = 0; + GROW; + } + len += l; + NEXTL(l); + c = CUR_CHAR(l); + } + return(xmlDictLookup(ctxt->dict, ctxt->input->cur - len, len)); +} + + +/** + * htmlParseHTMLAttribute: + * @ctxt: an HTML parser context + * @stop: a char stop value + * + * parse an HTML attribute value till the stop (quote), if + * stop is 0 then it stops at the first space + * + * Returns the attribute parsed or NULL + */ + +static xmlChar * +htmlParseHTMLAttribute(htmlParserCtxtPtr ctxt, const xmlChar stop) { + xmlChar *buffer = NULL; + int buffer_size = 0; + xmlChar *out = NULL; + const xmlChar *name = NULL; + const xmlChar *cur = NULL; + const htmlEntityDesc * ent; + + /* + * allocate a translation buffer. + */ + buffer_size = HTML_PARSER_BUFFER_SIZE; + buffer = (xmlChar *) xmlMallocAtomic(buffer_size * sizeof(xmlChar)); + if (buffer == NULL) { + htmlErrMemory(ctxt, "buffer allocation failed\n"); + return(NULL); + } + out = buffer; + + /* + * Ok loop until we reach one of the ending chars + */ + while ((CUR != 0) && (CUR != stop)) { + if ((stop == 0) && (CUR == '>')) break; + if ((stop == 0) && (IS_BLANK_CH(CUR))) break; + if (CUR == '&') { + if (NXT(1) == '#') { + unsigned int c; + int bits; + + c = htmlParseCharRef(ctxt); + if (c < 0x80) + { *out++ = c; bits= -6; } + else if (c < 0x800) + { *out++ =((c >> 6) & 0x1F) | 0xC0; bits= 0; } + else if (c < 0x10000) + { *out++ =((c >> 12) & 0x0F) | 0xE0; bits= 6; } + else + { *out++ =((c >> 18) & 0x07) | 0xF0; bits= 12; } + + for ( ; bits >= 0; bits-= 6) { + *out++ = ((c >> bits) & 0x3F) | 0x80; + } + + if (out - buffer > buffer_size - 100) { + int indx = out - buffer; + + growBuffer(buffer); + out = &buffer[indx]; + } + } else { + ent = htmlParseEntityRef(ctxt, &name); + if (name == NULL) { + *out++ = '&'; + if (out - buffer > buffer_size - 100) { + int indx = out - buffer; + + growBuffer(buffer); + out = &buffer[indx]; + } + } else if (ent == NULL) { + *out++ = '&'; + cur = name; + while (*cur != 0) { + if (out - buffer > buffer_size - 100) { + int indx = out - buffer; + + growBuffer(buffer); + out = &buffer[indx]; + } + *out++ = *cur++; + } + } else { + unsigned int c; + int bits; + + if (out - buffer > buffer_size - 100) { + int indx = out - buffer; + + growBuffer(buffer); + out = &buffer[indx]; + } + c = ent->value; + if (c < 0x80) + { *out++ = c; bits= -6; } + else if (c < 0x800) + { *out++ =((c >> 6) & 0x1F) | 0xC0; bits= 0; } + else if (c < 0x10000) + { *out++ =((c >> 12) & 0x0F) | 0xE0; bits= 6; } + else + { *out++ =((c >> 18) & 0x07) | 0xF0; bits= 12; } + + for ( ; bits >= 0; bits-= 6) { + *out++ = ((c >> bits) & 0x3F) | 0x80; + } + } + } + } else { + unsigned int c; + int bits, l; + + if (out - buffer > buffer_size - 100) { + int indx = out - buffer; + + growBuffer(buffer); + out = &buffer[indx]; + } + c = CUR_CHAR(l); + if (c < 0x80) + { *out++ = c; bits= -6; } + else if (c < 0x800) + { *out++ =((c >> 6) & 0x1F) | 0xC0; bits= 0; } + else if (c < 0x10000) + { *out++ =((c >> 12) & 0x0F) | 0xE0; bits= 6; } + else + { *out++ =((c >> 18) & 0x07) | 0xF0; bits= 12; } + + for ( ; bits >= 0; bits-= 6) { + *out++ = ((c >> bits) & 0x3F) | 0x80; + } + NEXT; + } + } + *out++ = 0; + return(buffer); +} + +/** + * htmlParseEntityRef: + * @ctxt: an HTML parser context + * @str: location to store the entity name + * + * parse an HTML ENTITY references + * + * [68] EntityRef ::= '&' Name ';' + * + * Returns the associated htmlEntityDescPtr if found, or NULL otherwise, + * if non-NULL *str will have to be freed by the caller. + */ +const htmlEntityDesc * +htmlParseEntityRef(htmlParserCtxtPtr ctxt, const xmlChar **str) { + const xmlChar *name; + const htmlEntityDesc * ent = NULL; + + if (str != NULL) *str = NULL; + if ((ctxt == NULL) || (ctxt->input == NULL)) return(NULL); + + if (CUR == '&') { + NEXT; + name = htmlParseName(ctxt); + if (name == NULL) { + htmlParseErr(ctxt, XML_ERR_NAME_REQUIRED, + "htmlParseEntityRef: no name\n", NULL, NULL); + } else { + GROW; + if (CUR == ';') { + if (str != NULL) + *str = name; + + /* + * Lookup the entity in the table. + */ + ent = htmlEntityLookup(name); + if (ent != NULL) /* OK that's ugly !!! */ + NEXT; + } else { + htmlParseErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, + "htmlParseEntityRef: expecting ';'\n", + NULL, NULL); + if (str != NULL) + *str = name; + } + } + } + return(ent); +} + +/** + * htmlParseAttValue: + * @ctxt: an HTML parser context + * + * parse a value for an attribute + * Note: the parser won't do substitution of entities here, this + * will be handled later in xmlStringGetNodeList, unless it was + * asked for ctxt->replaceEntities != 0 + * + * Returns the AttValue parsed or NULL. + */ + +static xmlChar * +htmlParseAttValue(htmlParserCtxtPtr ctxt) { + xmlChar *ret = NULL; + + if (CUR == '"') { + NEXT; + ret = htmlParseHTMLAttribute(ctxt, '"'); + if (CUR != '"') { + htmlParseErr(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED, + "AttValue: \" expected\n", NULL, NULL); + } else + NEXT; + } else if (CUR == '\'') { + NEXT; + ret = htmlParseHTMLAttribute(ctxt, '\''); + if (CUR != '\'') { + htmlParseErr(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED, + "AttValue: ' expected\n", NULL, NULL); + } else + NEXT; + } else { + /* + * That's an HTMLism, the attribute value may not be quoted + */ + ret = htmlParseHTMLAttribute(ctxt, 0); + if (ret == NULL) { + htmlParseErr(ctxt, XML_ERR_ATTRIBUTE_WITHOUT_VALUE, + "AttValue: no value found\n", NULL, NULL); + } + } + return(ret); +} + +/** + * htmlParseSystemLiteral: + * @ctxt: an HTML parser context + * + * parse an HTML Literal + * + * [11] SystemLiteral ::= ('"' [^"]* '"') | ("'" [^']* "'") + * + * Returns the SystemLiteral parsed or NULL + */ + +static xmlChar * +htmlParseSystemLiteral(htmlParserCtxtPtr ctxt) { + const xmlChar *q; + xmlChar *ret = NULL; + + if (CUR == '"') { + NEXT; + q = CUR_PTR; + while ((IS_CHAR_CH(CUR)) && (CUR != '"')) + NEXT; + if (!IS_CHAR_CH(CUR)) { + htmlParseErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED, + "Unfinished SystemLiteral\n", NULL, NULL); + } else { + ret = xmlStrndup(q, CUR_PTR - q); + NEXT; + } + } else if (CUR == '\'') { + NEXT; + q = CUR_PTR; + while ((IS_CHAR_CH(CUR)) && (CUR != '\'')) + NEXT; + if (!IS_CHAR_CH(CUR)) { + htmlParseErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED, + "Unfinished SystemLiteral\n", NULL, NULL); + } else { + ret = xmlStrndup(q, CUR_PTR - q); + NEXT; + } + } else { + htmlParseErr(ctxt, XML_ERR_LITERAL_NOT_STARTED, + " or ' expected\n", NULL, NULL); + } + + return(ret); +} + +/** + * htmlParsePubidLiteral: + * @ctxt: an HTML parser context + * + * parse an HTML public literal + * + * [12] PubidLiteral ::= '"' PubidChar* '"' | "'" (PubidChar - "'")* "'" + * + * Returns the PubidLiteral parsed or NULL. + */ + +static xmlChar * +htmlParsePubidLiteral(htmlParserCtxtPtr ctxt) { + const xmlChar *q; + xmlChar *ret = NULL; + /* + * Name ::= (Letter | '_') (NameChar)* + */ + if (CUR == '"') { + NEXT; + q = CUR_PTR; + while (IS_PUBIDCHAR_CH(CUR)) NEXT; + if (CUR != '"') { + htmlParseErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED, + "Unfinished PubidLiteral\n", NULL, NULL); + } else { + ret = xmlStrndup(q, CUR_PTR - q); + NEXT; + } + } else if (CUR == '\'') { + NEXT; + q = CUR_PTR; + while ((IS_PUBIDCHAR_CH(CUR)) && (CUR != '\'')) + NEXT; + if (CUR != '\'') { + htmlParseErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED, + "Unfinished PubidLiteral\n", NULL, NULL); + } else { + ret = xmlStrndup(q, CUR_PTR - q); + NEXT; + } + } else { + htmlParseErr(ctxt, XML_ERR_LITERAL_NOT_STARTED, + "PubidLiteral \" or ' expected\n", NULL, NULL); + } + + return(ret); +} + +/** + * htmlParseScript: + * @ctxt: an HTML parser context + * + * parse the content of an HTML SCRIPT or STYLE element + * http://www.w3.org/TR/html4/sgml/dtd.html#Script + * http://www.w3.org/TR/html4/sgml/dtd.html#StyleSheet + * http://www.w3.org/TR/html4/types.html#type-script + * http://www.w3.org/TR/html4/types.html#h-6.15 + * http://www.w3.org/TR/html4/appendix/notes.html#h-B.3.2.1 + * + * Script data ( %Script; in the DTD) can be the content of the SCRIPT + * element and the value of intrinsic event attributes. User agents must + * not evaluate script data as HTML markup but instead must pass it on as + * data to a script engine. + * NOTES: + * - The content is passed like CDATA + * - the attributes for style and scripting "onXXX" are also described + * as CDATA but SGML allows entities references in attributes so their + * processing is identical as other attributes + */ +static void +htmlParseScript(htmlParserCtxtPtr ctxt) { + xmlChar buf[HTML_PARSER_BIG_BUFFER_SIZE + 5]; + int nbchar = 0; + int cur,l; + + SHRINK; + cur = CUR_CHAR(l); + while (IS_CHAR_CH(cur)) { + if ((cur == '<') && (NXT(1) == '!') && (NXT(2) == '-') && + (NXT(3) == '-')) { + if ((nbchar != 0) && (ctxt->sax != NULL) && (!ctxt->disableSAX)) { + if (ctxt->sax->cdataBlock!= NULL) { + /* + * Insert as CDATA, which is the same as HTML_PRESERVE_NODE + */ + ctxt->sax->cdataBlock(ctxt->userData, buf, nbchar); + } else if (ctxt->sax->characters != NULL) { + ctxt->sax->characters(ctxt->userData, buf, nbchar); + } + } + nbchar = 0; + htmlParseComment(ctxt); + cur = CUR_CHAR(l); + continue; + } else if ((cur == '<') && (NXT(1) == '/')) { + /* + * One should break here, the specification is clear: + * Authors should therefore escape "recovery) { + if (xmlStrncasecmp(ctxt->name, ctxt->input->cur+2, + xmlStrlen(ctxt->name)) == 0) + { + break; /* while */ + } else { + htmlParseErr(ctxt, XML_ERR_TAG_NAME_MISMATCH, + "Element %s embeds close tag\n", + ctxt->name, NULL); + } + } else { + if (((NXT(2) >= 'A') && (NXT(2) <= 'Z')) || + ((NXT(2) >= 'a') && (NXT(2) <= 'z'))) + { + break; /* while */ + } + } + } + COPY_BUF(l,buf,nbchar,cur); + if (nbchar >= HTML_PARSER_BIG_BUFFER_SIZE) { + if (ctxt->sax->cdataBlock!= NULL) { + /* + * Insert as CDATA, which is the same as HTML_PRESERVE_NODE + */ + ctxt->sax->cdataBlock(ctxt->userData, buf, nbchar); + } else if (ctxt->sax->characters != NULL) { + ctxt->sax->characters(ctxt->userData, buf, nbchar); + } + nbchar = 0; + } + GROW; + NEXTL(l); + cur = CUR_CHAR(l); + } + + if ((!(IS_CHAR_CH(cur))) && (!((cur == 0) && (ctxt->progressive)))) { + htmlParseErrInt(ctxt, XML_ERR_INVALID_CHAR, + "Invalid char in CDATA 0x%X\n", cur); + NEXT; + } + + if ((nbchar != 0) && (ctxt->sax != NULL) && (!ctxt->disableSAX)) { + if (ctxt->sax->cdataBlock!= NULL) { + /* + * Insert as CDATA, which is the same as HTML_PRESERVE_NODE + */ + ctxt->sax->cdataBlock(ctxt->userData, buf, nbchar); + } else if (ctxt->sax->characters != NULL) { + ctxt->sax->characters(ctxt->userData, buf, nbchar); + } + } +} + + +/** + * htmlParseCharData: + * @ctxt: an HTML parser context + * + * parse a CharData section. + * if we are within a CDATA section ']]>' marks an end of section. + * + * [14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*) + */ + +static void +htmlParseCharData(htmlParserCtxtPtr ctxt) { + xmlChar buf[HTML_PARSER_BIG_BUFFER_SIZE + 5]; + int nbchar = 0; + int cur, l; + + SHRINK; + cur = CUR_CHAR(l); + while (((cur != '<') || (ctxt->token == '<')) && + ((cur != '&') || (ctxt->token == '&')) && + (IS_CHAR(cur))) { + COPY_BUF(l,buf,nbchar,cur); + if (nbchar >= HTML_PARSER_BIG_BUFFER_SIZE) { + /* + * Ok the segment is to be consumed as chars. + */ + if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) { + if (areBlanks(ctxt, buf, nbchar)) { + if (ctxt->sax->ignorableWhitespace != NULL) + ctxt->sax->ignorableWhitespace(ctxt->userData, + buf, nbchar); + } else { + htmlCheckParagraph(ctxt); + if (ctxt->sax->characters != NULL) + ctxt->sax->characters(ctxt->userData, buf, nbchar); + } + } + nbchar = 0; + } + NEXTL(l); + cur = CUR_CHAR(l); + if (cur == 0) { + SHRINK; + GROW; + cur = CUR_CHAR(l); + } + } + if (nbchar != 0) { + buf[nbchar] = 0; + + /* + * Ok the segment is to be consumed as chars. + */ + if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) { + if (areBlanks(ctxt, buf, nbchar)) { + if (ctxt->sax->ignorableWhitespace != NULL) + ctxt->sax->ignorableWhitespace(ctxt->userData, buf, nbchar); + } else { + htmlCheckParagraph(ctxt); + if (ctxt->sax->characters != NULL) + ctxt->sax->characters(ctxt->userData, buf, nbchar); + } + } + } else { + /* + * Loop detection + */ + if (cur == 0) + ctxt->instate = XML_PARSER_EOF; + } +} + +/** + * htmlParseExternalID: + * @ctxt: an HTML parser context + * @publicID: a xmlChar** receiving PubidLiteral + * + * Parse an External ID or a Public ID + * + * [75] ExternalID ::= 'SYSTEM' S SystemLiteral + * | 'PUBLIC' S PubidLiteral S SystemLiteral + * + * [83] PublicID ::= 'PUBLIC' S PubidLiteral + * + * Returns the function returns SystemLiteral and in the second + * case publicID receives PubidLiteral, is strict is off + * it is possible to return NULL and have publicID set. + */ + +static xmlChar * +htmlParseExternalID(htmlParserCtxtPtr ctxt, xmlChar **publicID) { + xmlChar *URI = NULL; + + if ((UPPER == 'S') && (UPP(1) == 'Y') && + (UPP(2) == 'S') && (UPP(3) == 'T') && + (UPP(4) == 'E') && (UPP(5) == 'M')) { + SKIP(6); + if (!IS_BLANK_CH(CUR)) { + htmlParseErr(ctxt, XML_ERR_SPACE_REQUIRED, + "Space required after 'SYSTEM'\n", NULL, NULL); + } + SKIP_BLANKS; + URI = htmlParseSystemLiteral(ctxt); + if (URI == NULL) { + htmlParseErr(ctxt, XML_ERR_URI_REQUIRED, + "htmlParseExternalID: SYSTEM, no URI\n", NULL, NULL); + } + } else if ((UPPER == 'P') && (UPP(1) == 'U') && + (UPP(2) == 'B') && (UPP(3) == 'L') && + (UPP(4) == 'I') && (UPP(5) == 'C')) { + SKIP(6); + if (!IS_BLANK_CH(CUR)) { + htmlParseErr(ctxt, XML_ERR_SPACE_REQUIRED, + "Space required after 'PUBLIC'\n", NULL, NULL); + } + SKIP_BLANKS; + *publicID = htmlParsePubidLiteral(ctxt); + if (*publicID == NULL) { + htmlParseErr(ctxt, XML_ERR_PUBID_REQUIRED, + "htmlParseExternalID: PUBLIC, no Public Identifier\n", + NULL, NULL); + } + SKIP_BLANKS; + if ((CUR == '"') || (CUR == '\'')) { + URI = htmlParseSystemLiteral(ctxt); + } + } + return(URI); +} + +/** + * xmlParsePI: + * @ctxt: an XML parser context + * + * parse an XML Processing Instruction. + * + * [16] PI ::= '' Char*)))? '?>' + */ +static void +htmlParsePI(htmlParserCtxtPtr ctxt) { + xmlChar *buf = NULL; + int len = 0; + int size = HTML_PARSER_BUFFER_SIZE; + int cur, l; + const xmlChar *target; + xmlParserInputState state; + int count = 0; + + if ((RAW == '<') && (NXT(1) == '?')) { + state = ctxt->instate; + ctxt->instate = XML_PARSER_PI; + /* + * this is a Processing Instruction. + */ + SKIP(2); + SHRINK; + + /* + * Parse the target name and check for special support like + * namespace. + */ + target = htmlParseName(ctxt); + if (target != NULL) { + if (RAW == '>') { + SKIP(1); + + /* + * SAX: PI detected. + */ + if ((ctxt->sax) && (!ctxt->disableSAX) && + (ctxt->sax->processingInstruction != NULL)) + ctxt->sax->processingInstruction(ctxt->userData, + target, NULL); + ctxt->instate = state; + return; + } + buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar)); + if (buf == NULL) { + htmlErrMemory(ctxt, NULL); + ctxt->instate = state; + return; + } + cur = CUR; + if (!IS_BLANK(cur)) { + htmlParseErr(ctxt, XML_ERR_SPACE_REQUIRED, + "ParsePI: PI %s space expected\n", target, NULL); + } + SKIP_BLANKS; + cur = CUR_CHAR(l); + while (IS_CHAR(cur) && (cur != '>')) { + if (len + 5 >= size) { + xmlChar *tmp; + + size *= 2; + tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar)); + if (tmp == NULL) { + htmlErrMemory(ctxt, NULL); + xmlFree(buf); + ctxt->instate = state; + return; + } + buf = tmp; + } + count++; + if (count > 50) { + GROW; + count = 0; + } + COPY_BUF(l,buf,len,cur); + NEXTL(l); + cur = CUR_CHAR(l); + if (cur == 0) { + SHRINK; + GROW; + cur = CUR_CHAR(l); + } + } + buf[len] = 0; + if (cur != '>') { + htmlParseErr(ctxt, XML_ERR_PI_NOT_FINISHED, + "ParsePI: PI %s never end ...\n", target, NULL); + } else { + SKIP(1); + + /* + * SAX: PI detected. + */ + if ((ctxt->sax) && (!ctxt->disableSAX) && + (ctxt->sax->processingInstruction != NULL)) + ctxt->sax->processingInstruction(ctxt->userData, + target, buf); + } + xmlFree(buf); + } else { + htmlParseErr(ctxt, XML_ERR_PI_NOT_STARTED, + "PI is not started correctly", NULL, NULL); + } + ctxt->instate = state; + } +} + +/** + * htmlParseComment: + * @ctxt: an HTML parser context + * + * Parse an XML (SGML) comment + * + * [15] Comment ::= '' + */ +static void +htmlParseComment(htmlParserCtxtPtr ctxt) { + xmlChar *buf = NULL; + int len; + int size = HTML_PARSER_BUFFER_SIZE; + int q, ql; + int r, rl; + int cur, l; + xmlParserInputState state; + + /* + * Check that there is a comment right here. + */ + if ((RAW != '<') || (NXT(1) != '!') || + (NXT(2) != '-') || (NXT(3) != '-')) return; + + state = ctxt->instate; + ctxt->instate = XML_PARSER_COMMENT; + SHRINK; + SKIP(4); + buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar)); + if (buf == NULL) { + htmlErrMemory(ctxt, "buffer allocation failed\n"); + ctxt->instate = state; + return; + } + q = CUR_CHAR(ql); + NEXTL(ql); + r = CUR_CHAR(rl); + NEXTL(rl); + cur = CUR_CHAR(l); + len = 0; + while (IS_CHAR(cur) && + ((cur != '>') || + (r != '-') || (q != '-'))) { + if (len + 5 >= size) { + xmlChar *tmp; + + size *= 2; + tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar)); + if (tmp == NULL) { + xmlFree(buf); + htmlErrMemory(ctxt, "growing buffer failed\n"); + ctxt->instate = state; + return; + } + buf = tmp; + } + COPY_BUF(ql,buf,len,q); + q = r; + ql = rl; + r = cur; + rl = l; + NEXTL(l); + cur = CUR_CHAR(l); + if (cur == 0) { + SHRINK; + GROW; + cur = CUR_CHAR(l); + } + } + buf[len] = 0; + if (!IS_CHAR(cur)) { + htmlParseErr(ctxt, XML_ERR_COMMENT_NOT_FINISHED, + "Comment not terminated \n */ + base += 2; + } + } + if (incomment) { + if (base + 3 > len) + return(-1); + if ((buf[base] == '-') && (buf[base + 1] == '-') && + (buf[base + 2] == '>')) { + incomment = 0; + base += 2; + } + continue; + } + if (buf[base] == first) { + if (third != 0) { + if ((buf[base + 1] != next) || + (buf[base + 2] != third)) continue; + } else if (next != 0) { + if (buf[base + 1] != next) continue; + } + ctxt->checkIndex = 0; +#ifdef DEBUG_PUSH + if (next == 0) + xmlGenericError(xmlGenericErrorContext, + "HPP: lookup '%c' found at %d\n", + first, base); + else if (third == 0) + xmlGenericError(xmlGenericErrorContext, + "HPP: lookup '%c%c' found at %d\n", + first, next, base); + else + xmlGenericError(xmlGenericErrorContext, + "HPP: lookup '%c%c%c' found at %d\n", + first, next, third, base); +#endif + return(base - (in->cur - in->base)); + } + } + ctxt->checkIndex = base; +#ifdef DEBUG_PUSH + if (next == 0) + xmlGenericError(xmlGenericErrorContext, + "HPP: lookup '%c' failed\n", first); + else if (third == 0) + xmlGenericError(xmlGenericErrorContext, + "HPP: lookup '%c%c' failed\n", first, next); + else + xmlGenericError(xmlGenericErrorContext, + "HPP: lookup '%c%c%c' failed\n", first, next, third); +#endif + return(-1); +} + +/** + * htmlParseTryOrFinish: + * @ctxt: an HTML parser context + * @terminate: last chunk indicator + * + * Try to progress on parsing + * + * Returns zero if no parsing was possible + */ +static int +htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) { + int ret = 0; + htmlParserInputPtr in; + int avail = 0; + xmlChar cur, next; + +#ifdef DEBUG_PUSH + switch (ctxt->instate) { + case XML_PARSER_EOF: + xmlGenericError(xmlGenericErrorContext, + "HPP: try EOF\n"); break; + case XML_PARSER_START: + xmlGenericError(xmlGenericErrorContext, + "HPP: try START\n"); break; + case XML_PARSER_MISC: + xmlGenericError(xmlGenericErrorContext, + "HPP: try MISC\n");break; + case XML_PARSER_COMMENT: + xmlGenericError(xmlGenericErrorContext, + "HPP: try COMMENT\n");break; + case XML_PARSER_PROLOG: + xmlGenericError(xmlGenericErrorContext, + "HPP: try PROLOG\n");break; + case XML_PARSER_START_TAG: + xmlGenericError(xmlGenericErrorContext, + "HPP: try START_TAG\n");break; + case XML_PARSER_CONTENT: + xmlGenericError(xmlGenericErrorContext, + "HPP: try CONTENT\n");break; + case XML_PARSER_CDATA_SECTION: + xmlGenericError(xmlGenericErrorContext, + "HPP: try CDATA_SECTION\n");break; + case XML_PARSER_END_TAG: + xmlGenericError(xmlGenericErrorContext, + "HPP: try END_TAG\n");break; + case XML_PARSER_ENTITY_DECL: + xmlGenericError(xmlGenericErrorContext, + "HPP: try ENTITY_DECL\n");break; + case XML_PARSER_ENTITY_VALUE: + xmlGenericError(xmlGenericErrorContext, + "HPP: try ENTITY_VALUE\n");break; + case XML_PARSER_ATTRIBUTE_VALUE: + xmlGenericError(xmlGenericErrorContext, + "HPP: try ATTRIBUTE_VALUE\n");break; + case XML_PARSER_DTD: + xmlGenericError(xmlGenericErrorContext, + "HPP: try DTD\n");break; + case XML_PARSER_EPILOG: + xmlGenericError(xmlGenericErrorContext, + "HPP: try EPILOG\n");break; + case XML_PARSER_PI: + xmlGenericError(xmlGenericErrorContext, + "HPP: try PI\n");break; + case XML_PARSER_SYSTEM_LITERAL: + xmlGenericError(xmlGenericErrorContext, + "HPP: try SYSTEM_LITERAL\n");break; + } +#endif + + while (1) { + + in = ctxt->input; + if (in == NULL) break; + if (in->buf == NULL) + avail = in->length - (in->cur - in->base); + else + avail = in->buf->buffer->use - (in->cur - in->base); + if ((avail == 0) && (terminate)) { + htmlAutoCloseOnEnd(ctxt); + if ((ctxt->nameNr == 0) && (ctxt->instate != XML_PARSER_EOF)) { + /* + * SAX: end of the document processing. + */ + ctxt->instate = XML_PARSER_EOF; + if ((ctxt->sax) && (ctxt->sax->endDocument != NULL)) + ctxt->sax->endDocument(ctxt->userData); + } + } + if (avail < 1) + goto done; + cur = in->cur[0]; + if (cur == 0) { + SKIP(1); + continue; + } + + switch (ctxt->instate) { + case XML_PARSER_EOF: + /* + * Document parsing is done ! + */ + goto done; + case XML_PARSER_START: + /* + * Very first chars read from the document flow. + */ + cur = in->cur[0]; + if (IS_BLANK_CH(cur)) { + SKIP_BLANKS; + if (in->buf == NULL) + avail = in->length - (in->cur - in->base); + else + avail = in->buf->buffer->use - (in->cur - in->base); + } + if ((ctxt->sax) && (ctxt->sax->setDocumentLocator)) + ctxt->sax->setDocumentLocator(ctxt->userData, + &xmlDefaultSAXLocator); + if ((ctxt->sax) && (ctxt->sax->startDocument) && + (!ctxt->disableSAX)) + ctxt->sax->startDocument(ctxt->userData); + + cur = in->cur[0]; + next = in->cur[1]; + if ((cur == '<') && (next == '!') && + (UPP(2) == 'D') && (UPP(3) == 'O') && + (UPP(4) == 'C') && (UPP(5) == 'T') && + (UPP(6) == 'Y') && (UPP(7) == 'P') && + (UPP(8) == 'E')) { + if ((!terminate) && + (htmlParseLookupSequence(ctxt, '>', 0, 0, 0) < 0)) + goto done; +#ifdef DEBUG_PUSH + xmlGenericError(xmlGenericErrorContext, + "HPP: Parsing internal subset\n"); +#endif + htmlParseDocTypeDecl(ctxt); + ctxt->instate = XML_PARSER_PROLOG; +#ifdef DEBUG_PUSH + xmlGenericError(xmlGenericErrorContext, + "HPP: entering PROLOG\n"); +#endif + } else { + ctxt->instate = XML_PARSER_MISC; +#ifdef DEBUG_PUSH + xmlGenericError(xmlGenericErrorContext, + "HPP: entering MISC\n"); +#endif + } + break; + case XML_PARSER_MISC: + SKIP_BLANKS; + if (in->buf == NULL) + avail = in->length - (in->cur - in->base); + else + avail = in->buf->buffer->use - (in->cur - in->base); + if (avail < 2) + goto done; + cur = in->cur[0]; + next = in->cur[1]; + if ((cur == '<') && (next == '!') && + (in->cur[2] == '-') && (in->cur[3] == '-')) { + if ((!terminate) && + (htmlParseLookupSequence(ctxt, '-', '-', '>', 1) < 0)) + goto done; +#ifdef DEBUG_PUSH + xmlGenericError(xmlGenericErrorContext, + "HPP: Parsing Comment\n"); +#endif + htmlParseComment(ctxt); + ctxt->instate = XML_PARSER_MISC; + } else if ((cur == '<') && (next == '?')) { + if ((!terminate) && + (htmlParseLookupSequence(ctxt, '>', 0, 0, 0) < 0)) + goto done; +#ifdef DEBUG_PUSH + xmlGenericError(xmlGenericErrorContext, + "HPP: Parsing PI\n"); +#endif + htmlParsePI(ctxt); + ctxt->instate = XML_PARSER_MISC; + } else if ((cur == '<') && (next == '!') && + (UPP(2) == 'D') && (UPP(3) == 'O') && + (UPP(4) == 'C') && (UPP(5) == 'T') && + (UPP(6) == 'Y') && (UPP(7) == 'P') && + (UPP(8) == 'E')) { + if ((!terminate) && + (htmlParseLookupSequence(ctxt, '>', 0, 0, 0) < 0)) + goto done; +#ifdef DEBUG_PUSH + xmlGenericError(xmlGenericErrorContext, + "HPP: Parsing internal subset\n"); +#endif + htmlParseDocTypeDecl(ctxt); + ctxt->instate = XML_PARSER_PROLOG; +#ifdef DEBUG_PUSH + xmlGenericError(xmlGenericErrorContext, + "HPP: entering PROLOG\n"); +#endif + } else if ((cur == '<') && (next == '!') && + (avail < 9)) { + goto done; + } else { + ctxt->instate = XML_PARSER_START_TAG; +#ifdef DEBUG_PUSH + xmlGenericError(xmlGenericErrorContext, + "HPP: entering START_TAG\n"); +#endif + } + break; + case XML_PARSER_PROLOG: + SKIP_BLANKS; + if (in->buf == NULL) + avail = in->length - (in->cur - in->base); + else + avail = in->buf->buffer->use - (in->cur - in->base); + if (avail < 2) + goto done; + cur = in->cur[0]; + next = in->cur[1]; + if ((cur == '<') && (next == '!') && + (in->cur[2] == '-') && (in->cur[3] == '-')) { + if ((!terminate) && + (htmlParseLookupSequence(ctxt, '-', '-', '>', 1) < 0)) + goto done; +#ifdef DEBUG_PUSH + xmlGenericError(xmlGenericErrorContext, + "HPP: Parsing Comment\n"); +#endif + htmlParseComment(ctxt); + ctxt->instate = XML_PARSER_PROLOG; + } else if ((cur == '<') && (next == '?')) { + if ((!terminate) && + (htmlParseLookupSequence(ctxt, '>', 0, 0, 0) < 0)) + goto done; +#ifdef DEBUG_PUSH + xmlGenericError(xmlGenericErrorContext, + "HPP: Parsing PI\n"); +#endif + htmlParsePI(ctxt); + ctxt->instate = XML_PARSER_PROLOG; + } else if ((cur == '<') && (next == '!') && + (avail < 4)) { + goto done; + } else { + ctxt->instate = XML_PARSER_START_TAG; +#ifdef DEBUG_PUSH + xmlGenericError(xmlGenericErrorContext, + "HPP: entering START_TAG\n"); +#endif + } + break; + case XML_PARSER_EPILOG: + if (in->buf == NULL) + avail = in->length - (in->cur - in->base); + else + avail = in->buf->buffer->use - (in->cur - in->base); + if (avail < 1) + goto done; + cur = in->cur[0]; + if (IS_BLANK_CH(cur)) { + htmlParseCharData(ctxt); + goto done; + } + if (avail < 2) + goto done; + next = in->cur[1]; + if ((cur == '<') && (next == '!') && + (in->cur[2] == '-') && (in->cur[3] == '-')) { + if ((!terminate) && + (htmlParseLookupSequence(ctxt, '-', '-', '>', 1) < 0)) + goto done; +#ifdef DEBUG_PUSH + xmlGenericError(xmlGenericErrorContext, + "HPP: Parsing Comment\n"); +#endif + htmlParseComment(ctxt); + ctxt->instate = XML_PARSER_EPILOG; + } else if ((cur == '<') && (next == '?')) { + if ((!terminate) && + (htmlParseLookupSequence(ctxt, '>', 0, 0, 0) < 0)) + goto done; +#ifdef DEBUG_PUSH + xmlGenericError(xmlGenericErrorContext, + "HPP: Parsing PI\n"); +#endif + htmlParsePI(ctxt); + ctxt->instate = XML_PARSER_EPILOG; + } else if ((cur == '<') && (next == '!') && + (avail < 4)) { + goto done; + } else { + ctxt->errNo = XML_ERR_DOCUMENT_END; + ctxt->wellFormed = 0; + ctxt->instate = XML_PARSER_EOF; +#ifdef DEBUG_PUSH + xmlGenericError(xmlGenericErrorContext, + "HPP: entering EOF\n"); +#endif + if ((ctxt->sax) && (ctxt->sax->endDocument != NULL)) + ctxt->sax->endDocument(ctxt->userData); + goto done; + } + break; + case XML_PARSER_START_TAG: { + const xmlChar *name; + int failed; + const htmlElemDesc * info; + + if (avail < 2) + goto done; + cur = in->cur[0]; + if (cur != '<') { + ctxt->instate = XML_PARSER_CONTENT; +#ifdef DEBUG_PUSH + xmlGenericError(xmlGenericErrorContext, + "HPP: entering CONTENT\n"); +#endif + break; + } + if (in->cur[1] == '/') { + ctxt->instate = XML_PARSER_END_TAG; + ctxt->checkIndex = 0; +#ifdef DEBUG_PUSH + xmlGenericError(xmlGenericErrorContext, + "HPP: entering END_TAG\n"); +#endif + break; + } + if ((!terminate) && + (htmlParseLookupSequence(ctxt, '>', 0, 0, 0) < 0)) + goto done; + + failed = htmlParseStartTag(ctxt); + name = ctxt->name; + if (failed || + (name == NULL)) { + if (CUR == '>') + NEXT; + break; + } + + /* + * Lookup the info for that element. + */ + info = htmlTagLookup(name); + if (info == NULL) { + htmlParseErr(ctxt, XML_HTML_UNKNOWN_TAG, + "Tag %s invalid\n", name, NULL); + } + + /* + * Check for an Empty Element labeled the XML/SGML way + */ + if ((CUR == '/') && (NXT(1) == '>')) { + SKIP(2); + if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL)) + ctxt->sax->endElement(ctxt->userData, name); + htmlnamePop(ctxt); + ctxt->instate = XML_PARSER_CONTENT; +#ifdef DEBUG_PUSH + xmlGenericError(xmlGenericErrorContext, + "HPP: entering CONTENT\n"); +#endif + break; + } + + if (CUR == '>') { + NEXT; + } else { + htmlParseErr(ctxt, XML_ERR_GT_REQUIRED, + "Couldn't find end of Start Tag %s\n", + name, NULL); + + /* + * end of parsing of this node. + */ + if (xmlStrEqual(name, ctxt->name)) { + nodePop(ctxt); + htmlnamePop(ctxt); + } + + ctxt->instate = XML_PARSER_CONTENT; +#ifdef DEBUG_PUSH + xmlGenericError(xmlGenericErrorContext, + "HPP: entering CONTENT\n"); +#endif + break; + } + + /* + * Check for an Empty Element from DTD definition + */ + if ((info != NULL) && (info->empty)) { + if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL)) + ctxt->sax->endElement(ctxt->userData, name); + htmlnamePop(ctxt); + } + ctxt->instate = XML_PARSER_CONTENT; +#ifdef DEBUG_PUSH + xmlGenericError(xmlGenericErrorContext, + "HPP: entering CONTENT\n"); +#endif + break; + } + case XML_PARSER_CONTENT: { + long cons; + /* + * Handle preparsed entities and charRef + */ + if (ctxt->token != 0) { + xmlChar chr[2] = { 0 , 0 } ; + + chr[0] = (xmlChar) ctxt->token; + htmlCheckParagraph(ctxt); + if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL)) + ctxt->sax->characters(ctxt->userData, chr, 1); + ctxt->token = 0; + ctxt->checkIndex = 0; + } + if ((avail == 1) && (terminate)) { + cur = in->cur[0]; + if ((cur != '<') && (cur != '&')) { + if (ctxt->sax != NULL) { + if (IS_BLANK_CH(cur)) { + if (ctxt->sax->ignorableWhitespace != NULL) + ctxt->sax->ignorableWhitespace( + ctxt->userData, &cur, 1); + } else { + htmlCheckParagraph(ctxt); + if (ctxt->sax->characters != NULL) + ctxt->sax->characters( + ctxt->userData, &cur, 1); + } + } + ctxt->token = 0; + ctxt->checkIndex = 0; + in->cur++; + break; + } + } + if (avail < 2) + goto done; + cur = in->cur[0]; + next = in->cur[1]; + cons = ctxt->nbChars; + if ((xmlStrEqual(ctxt->name, BAD_CAST"script")) || + (xmlStrEqual(ctxt->name, BAD_CAST"style"))) { + /* + * Handle SCRIPT/STYLE separately + */ + if (!terminate) { + int idx; + xmlChar val; + + idx = htmlParseLookupSequence(ctxt, '<', '/', 0, 0); + if (idx < 0) + goto done; + val = in->cur[idx + 2]; + if (val == 0) /* bad cut of input */ + goto done; + } + htmlParseScript(ctxt); + if ((cur == '<') && (next == '/')) { + ctxt->instate = XML_PARSER_END_TAG; + ctxt->checkIndex = 0; +#ifdef DEBUG_PUSH + xmlGenericError(xmlGenericErrorContext, + "HPP: entering END_TAG\n"); +#endif + break; + } + } else { + /* + * Sometimes DOCTYPE arrives in the middle of the document + */ + if ((cur == '<') && (next == '!') && + (UPP(2) == 'D') && (UPP(3) == 'O') && + (UPP(4) == 'C') && (UPP(5) == 'T') && + (UPP(6) == 'Y') && (UPP(7) == 'P') && + (UPP(8) == 'E')) { + if ((!terminate) && + (htmlParseLookupSequence(ctxt, '>', 0, 0, 0) < 0)) + goto done; + htmlParseErr(ctxt, XML_HTML_STRUCURE_ERROR, + "Misplaced DOCTYPE declaration\n", + BAD_CAST "DOCTYPE" , NULL); + htmlParseDocTypeDecl(ctxt); + } else if ((cur == '<') && (next == '!') && + (in->cur[2] == '-') && (in->cur[3] == '-')) { + if ((!terminate) && + (htmlParseLookupSequence( + ctxt, '-', '-', '>', 1) < 0)) + goto done; +#ifdef DEBUG_PUSH + xmlGenericError(xmlGenericErrorContext, + "HPP: Parsing Comment\n"); +#endif + htmlParseComment(ctxt); + ctxt->instate = XML_PARSER_CONTENT; + } else if ((cur == '<') && (next == '?')) { + if ((!terminate) && + (htmlParseLookupSequence(ctxt, '>', 0, 0, 0) < 0)) + goto done; +#ifdef DEBUG_PUSH + xmlGenericError(xmlGenericErrorContext, + "HPP: Parsing PI\n"); +#endif + htmlParsePI(ctxt); + ctxt->instate = XML_PARSER_CONTENT; + } else if ((cur == '<') && (next == '!') && (avail < 4)) { + goto done; + } else if ((cur == '<') && (next == '/')) { + ctxt->instate = XML_PARSER_END_TAG; + ctxt->checkIndex = 0; +#ifdef DEBUG_PUSH + xmlGenericError(xmlGenericErrorContext, + "HPP: entering END_TAG\n"); +#endif + break; + } else if (cur == '<') { + ctxt->instate = XML_PARSER_START_TAG; + ctxt->checkIndex = 0; +#ifdef DEBUG_PUSH + xmlGenericError(xmlGenericErrorContext, + "HPP: entering START_TAG\n"); +#endif + break; + } else if (cur == '&') { + if ((!terminate) && + (htmlParseLookupSequence(ctxt, ';', 0, 0, 0) < 0)) + goto done; +#ifdef DEBUG_PUSH + xmlGenericError(xmlGenericErrorContext, + "HPP: Parsing Reference\n"); +#endif + /* TODO: check generation of subtrees if noent !!! */ + htmlParseReference(ctxt); + } else { + /* + * check that the text sequence is complete + * before handing out the data to the parser + * to avoid problems with erroneous end of + * data detection. + */ + if ((!terminate) && + (htmlParseLookupSequence(ctxt, '<', 0, 0, 0) < 0)) + goto done; + ctxt->checkIndex = 0; +#ifdef DEBUG_PUSH + xmlGenericError(xmlGenericErrorContext, + "HPP: Parsing char data\n"); +#endif + htmlParseCharData(ctxt); + } + } + if (cons == ctxt->nbChars) { + if (ctxt->node != NULL) { + htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR, + "detected an error in element content\n", + NULL, NULL); + } + NEXT; + break; + } + + break; + } + case XML_PARSER_END_TAG: + if (avail < 2) + goto done; + if ((!terminate) && + (htmlParseLookupSequence(ctxt, '>', 0, 0, 0) < 0)) + goto done; + htmlParseEndTag(ctxt); + if (ctxt->nameNr == 0) { + ctxt->instate = XML_PARSER_EPILOG; + } else { + ctxt->instate = XML_PARSER_CONTENT; + } + ctxt->checkIndex = 0; +#ifdef DEBUG_PUSH + xmlGenericError(xmlGenericErrorContext, + "HPP: entering CONTENT\n"); +#endif + break; + case XML_PARSER_CDATA_SECTION: + htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR, + "HPP: internal error, state == CDATA\n", + NULL, NULL); + ctxt->instate = XML_PARSER_CONTENT; + ctxt->checkIndex = 0; +#ifdef DEBUG_PUSH + xmlGenericError(xmlGenericErrorContext, + "HPP: entering CONTENT\n"); +#endif + break; + case XML_PARSER_DTD: + htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR, + "HPP: internal error, state == DTD\n", + NULL, NULL); + ctxt->instate = XML_PARSER_CONTENT; + ctxt->checkIndex = 0; +#ifdef DEBUG_PUSH + xmlGenericError(xmlGenericErrorContext, + "HPP: entering CONTENT\n"); +#endif + break; + case XML_PARSER_COMMENT: + htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR, + "HPP: internal error, state == COMMENT\n", + NULL, NULL); + ctxt->instate = XML_PARSER_CONTENT; + ctxt->checkIndex = 0; +#ifdef DEBUG_PUSH + xmlGenericError(xmlGenericErrorContext, + "HPP: entering CONTENT\n"); +#endif + break; + case XML_PARSER_PI: + htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR, + "HPP: internal error, state == PI\n", + NULL, NULL); + ctxt->instate = XML_PARSER_CONTENT; + ctxt->checkIndex = 0; +#ifdef DEBUG_PUSH + xmlGenericError(xmlGenericErrorContext, + "HPP: entering CONTENT\n"); +#endif + break; + case XML_PARSER_ENTITY_DECL: + htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR, + "HPP: internal error, state == ENTITY_DECL\n", + NULL, NULL); + ctxt->instate = XML_PARSER_CONTENT; + ctxt->checkIndex = 0; +#ifdef DEBUG_PUSH + xmlGenericError(xmlGenericErrorContext, + "HPP: entering CONTENT\n"); +#endif + break; + case XML_PARSER_ENTITY_VALUE: + htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR, + "HPP: internal error, state == ENTITY_VALUE\n", + NULL, NULL); + ctxt->instate = XML_PARSER_CONTENT; + ctxt->checkIndex = 0; +#ifdef DEBUG_PUSH + xmlGenericError(xmlGenericErrorContext, + "HPP: entering DTD\n"); +#endif + break; + case XML_PARSER_ATTRIBUTE_VALUE: + htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR, + "HPP: internal error, state == ATTRIBUTE_VALUE\n", + NULL, NULL); + ctxt->instate = XML_PARSER_START_TAG; + ctxt->checkIndex = 0; +#ifdef DEBUG_PUSH + xmlGenericError(xmlGenericErrorContext, + "HPP: entering START_TAG\n"); +#endif + break; + case XML_PARSER_SYSTEM_LITERAL: + htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR, + "HPP: internal error, state == XML_PARSER_SYSTEM_LITERAL\n", + NULL, NULL); + ctxt->instate = XML_PARSER_CONTENT; + ctxt->checkIndex = 0; +#ifdef DEBUG_PUSH + xmlGenericError(xmlGenericErrorContext, + "HPP: entering CONTENT\n"); +#endif + break; + case XML_PARSER_IGNORE: + htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR, + "HPP: internal error, state == XML_PARSER_IGNORE\n", + NULL, NULL); + ctxt->instate = XML_PARSER_CONTENT; + ctxt->checkIndex = 0; +#ifdef DEBUG_PUSH + xmlGenericError(xmlGenericErrorContext, + "HPP: entering CONTENT\n"); +#endif + break; + case XML_PARSER_PUBLIC_LITERAL: + htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR, + "HPP: internal error, state == XML_PARSER_LITERAL\n", + NULL, NULL); + ctxt->instate = XML_PARSER_CONTENT; + ctxt->checkIndex = 0; +#ifdef DEBUG_PUSH + xmlGenericError(xmlGenericErrorContext, + "HPP: entering CONTENT\n"); +#endif + break; + + } + } +done: + if ((avail == 0) && (terminate)) { + htmlAutoCloseOnEnd(ctxt); + if ((ctxt->nameNr == 0) && (ctxt->instate != XML_PARSER_EOF)) { + /* + * SAX: end of the document processing. + */ + ctxt->instate = XML_PARSER_EOF; + if ((ctxt->sax) && (ctxt->sax->endDocument != NULL)) + ctxt->sax->endDocument(ctxt->userData); + } + } + if ((ctxt->myDoc != NULL) && + ((terminate) || (ctxt->instate == XML_PARSER_EOF) || + (ctxt->instate == XML_PARSER_EPILOG))) { + xmlDtdPtr dtd; + dtd = xmlGetIntSubset(ctxt->myDoc); + if (dtd == NULL) + ctxt->myDoc->intSubset = + xmlCreateIntSubset(ctxt->myDoc, BAD_CAST "html", + BAD_CAST "-//W3C//DTD HTML 4.0 Transitional//EN", + BAD_CAST "http://www.w3.org/TR/REC-html40/loose.dtd"); + } +#ifdef DEBUG_PUSH + xmlGenericError(xmlGenericErrorContext, "HPP: done %d\n", ret); +#endif + return(ret); +} + +/** + * htmlParseChunk: + * @ctxt: an HTML parser context + * @chunk: an char array + * @size: the size in byte of the chunk + * @terminate: last chunk indicator + * + * Parse a Chunk of memory + * + * Returns zero if no error, the xmlParserErrors otherwise. + */ +int +htmlParseChunk(htmlParserCtxtPtr ctxt, const char *chunk, int size, + int terminate) { + if ((ctxt == NULL) || (ctxt->input == NULL)) { + htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR, + "htmlParseChunk: context error\n", NULL, NULL); + return(XML_ERR_INTERNAL_ERROR); + } + if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) && + (ctxt->input->buf != NULL) && (ctxt->instate != XML_PARSER_EOF)) { + int base = ctxt->input->base - ctxt->input->buf->buffer->content; + int cur = ctxt->input->cur - ctxt->input->base; + int res; + + res = xmlParserInputBufferPush(ctxt->input->buf, size, chunk); + if (res < 0) { + ctxt->errNo = XML_PARSER_EOF; + ctxt->disableSAX = 1; + return (XML_PARSER_EOF); + } + ctxt->input->base = ctxt->input->buf->buffer->content + base; + ctxt->input->cur = ctxt->input->base + cur; + ctxt->input->end = + &ctxt->input->buf->buffer->content[ctxt->input->buf->buffer->use]; +#ifdef DEBUG_PUSH + xmlGenericError(xmlGenericErrorContext, "HPP: pushed %d\n", size); +#endif + +#if 0 + if ((terminate) || (ctxt->input->buf->buffer->use > 80)) + htmlParseTryOrFinish(ctxt, terminate); +#endif + } else if (ctxt->instate != XML_PARSER_EOF) { + if ((ctxt->input != NULL) && ctxt->input->buf != NULL) { + xmlParserInputBufferPtr in = ctxt->input->buf; + if ((in->encoder != NULL) && (in->buffer != NULL) && + (in->raw != NULL)) { + int nbchars; + + nbchars = xmlCharEncInFunc(in->encoder, in->buffer, in->raw); + if (nbchars < 0) { + htmlParseErr(ctxt, XML_ERR_INVALID_ENCODING, + "encoder error\n", NULL, NULL); + return(XML_ERR_INVALID_ENCODING); + } + } + } + } + htmlParseTryOrFinish(ctxt, terminate); + if (terminate) { + if ((ctxt->instate != XML_PARSER_EOF) && + (ctxt->instate != XML_PARSER_EPILOG) && + (ctxt->instate != XML_PARSER_MISC)) { + ctxt->errNo = XML_ERR_DOCUMENT_END; + ctxt->wellFormed = 0; + } + if (ctxt->instate != XML_PARSER_EOF) { + if ((ctxt->sax) && (ctxt->sax->endDocument != NULL)) + ctxt->sax->endDocument(ctxt->userData); + } + ctxt->instate = XML_PARSER_EOF; + } + return((xmlParserErrors) ctxt->errNo); +} + +/************************************************************************ + * * + * User entry points * + * * + ************************************************************************/ + +/** + * htmlCreatePushParserCtxt: + * @sax: a SAX handler + * @user_data: The user data returned on SAX callbacks + * @chunk: a pointer to an array of chars + * @size: number of chars in the array + * @filename: an optional file name or URI + * @enc: an optional encoding + * + * Create a parser context for using the HTML parser in push mode + * The value of @filename is used for fetching external entities + * and error/warning reports. + * + * Returns the new parser context or NULL + */ +htmlParserCtxtPtr +htmlCreatePushParserCtxt(htmlSAXHandlerPtr sax, void *user_data, + const char *chunk, int size, const char *filename, + xmlCharEncoding enc) { + htmlParserCtxtPtr ctxt; + htmlParserInputPtr inputStream; + xmlParserInputBufferPtr buf; + + xmlInitParser(); + + buf = xmlAllocParserInputBuffer(enc); + if (buf == NULL) return(NULL); + + ctxt = htmlNewParserCtxt(); + if (ctxt == NULL) { + xmlFreeParserInputBuffer(buf); + return(NULL); + } + if(enc==XML_CHAR_ENCODING_UTF8 || buf->encoder) + ctxt->charset=XML_CHAR_ENCODING_UTF8; + if (sax != NULL) { + if (ctxt->sax != (xmlSAXHandlerPtr) &htmlDefaultSAXHandler) + xmlFree(ctxt->sax); + ctxt->sax = (htmlSAXHandlerPtr) xmlMalloc(sizeof(htmlSAXHandler)); + if (ctxt->sax == NULL) { + xmlFree(buf); + xmlFree(ctxt); + return(NULL); + } + memcpy(ctxt->sax, sax, sizeof(htmlSAXHandler)); + if (user_data != NULL) + ctxt->userData = user_data; + } + if (filename == NULL) { + ctxt->directory = NULL; + } else { + ctxt->directory = xmlParserGetDirectory(filename); + } + + inputStream = htmlNewInputStream(ctxt); + if (inputStream == NULL) { + xmlFreeParserCtxt(ctxt); + xmlFree(buf); + return(NULL); + } + + if (filename == NULL) + inputStream->filename = NULL; + else + inputStream->filename = (char *) + xmlCanonicPath((const xmlChar *) filename); + inputStream->buf = buf; + inputStream->base = inputStream->buf->buffer->content; + inputStream->cur = inputStream->buf->buffer->content; + inputStream->end = + &inputStream->buf->buffer->content[inputStream->buf->buffer->use]; + + inputPush(ctxt, inputStream); + + if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) && + (ctxt->input->buf != NULL)) { + int base = ctxt->input->base - ctxt->input->buf->buffer->content; + int cur = ctxt->input->cur - ctxt->input->base; + + xmlParserInputBufferPush(ctxt->input->buf, size, chunk); + + ctxt->input->base = ctxt->input->buf->buffer->content + base; + ctxt->input->cur = ctxt->input->base + cur; + ctxt->input->end = + &ctxt->input->buf->buffer->content[ctxt->input->buf->buffer->use]; +#ifdef DEBUG_PUSH + xmlGenericError(xmlGenericErrorContext, "HPP: pushed %d\n", size); +#endif + } + ctxt->progressive = 1; + + return(ctxt); +} +#endif /* LIBXML_PUSH_ENABLED */ + +/** + * htmlSAXParseDoc: + * @cur: a pointer to an array of xmlChar + * @encoding: a free form C string describing the HTML document encoding, or NULL + * @sax: the SAX handler block + * @userData: if using SAX, this pointer will be provided on callbacks. + * + * Parse an HTML in-memory document. If sax is not NULL, use the SAX callbacks + * to handle parse events. If sax is NULL, fallback to the default DOM + * behavior and return a tree. + * + * Returns the resulting document tree unless SAX is NULL or the document is + * not well formed. + */ + +htmlDocPtr +htmlSAXParseDoc(xmlChar *cur, const char *encoding, htmlSAXHandlerPtr sax, void *userData) { + htmlDocPtr ret; + htmlParserCtxtPtr ctxt; + + xmlInitParser(); + + if (cur == NULL) return(NULL); + + + ctxt = htmlCreateDocParserCtxt(cur, encoding); + if (ctxt == NULL) return(NULL); + if (sax != NULL) { + if (ctxt->sax != NULL) xmlFree (ctxt->sax); + ctxt->sax = sax; + ctxt->userData = userData; + } + + htmlParseDocument(ctxt); + ret = ctxt->myDoc; + if (sax != NULL) { + ctxt->sax = NULL; + ctxt->userData = NULL; + } + htmlFreeParserCtxt(ctxt); + + return(ret); +} + +/** + * htmlParseDoc: + * @cur: a pointer to an array of xmlChar + * @encoding: a free form C string describing the HTML document encoding, or NULL + * + * parse an HTML in-memory document and build a tree. + * + * Returns the resulting document tree + */ + +htmlDocPtr +htmlParseDoc(xmlChar *cur, const char *encoding) { + return(htmlSAXParseDoc(cur, encoding, NULL, NULL)); +} + + +/** + * htmlCreateFileParserCtxt: + * @filename: the filename + * @encoding: a free form C string describing the HTML document encoding, or NULL + * + * Create a parser context for a file content. + * Automatic support for ZLIB/Compress compressed document is provided + * by default if found at compile-time. + * + * Returns the new parser context or NULL + */ +htmlParserCtxtPtr +htmlCreateFileParserCtxt(const char *filename, const char *encoding) +{ + htmlParserCtxtPtr ctxt; + htmlParserInputPtr inputStream; + char *canonicFilename; + /* htmlCharEncoding enc; */ + xmlChar *content, *content_line = (xmlChar *) "charset="; + + if (filename == NULL) + return(NULL); + + ctxt = htmlNewParserCtxt(); + if (ctxt == NULL) { + return(NULL); + } + canonicFilename = (char *) xmlCanonicPath((const xmlChar *) filename); + if (canonicFilename == NULL) { +#ifdef LIBXML_SAX1_ENABLED + if (xmlDefaultSAXHandler.error != NULL) { + xmlDefaultSAXHandler.error(NULL, "out of memory\n"); + } +#endif + xmlFreeParserCtxt(ctxt); + return(NULL); + } + + inputStream = xmlLoadExternalEntity(canonicFilename, NULL, ctxt); + xmlFree(canonicFilename); + if (inputStream == NULL) { + xmlFreeParserCtxt(ctxt); + return(NULL); + } + + inputPush(ctxt, inputStream); + + /* set encoding */ + if (encoding) { + content = xmlMallocAtomic (xmlStrlen(content_line) + strlen(encoding) + 1); + if (content) { + strcpy ((char *)content, (char *)content_line); + strcat ((char *)content, (char *)encoding); + htmlCheckEncoding (ctxt, content); + xmlFree (content); + } + } + + return(ctxt); +} + +/** + * htmlSAXParseFile: + * @filename: the filename + * @encoding: a free form C string describing the HTML document encoding, or NULL + * @sax: the SAX handler block + * @userData: if using SAX, this pointer will be provided on callbacks. + * + * parse an HTML file and build a tree. Automatic support for ZLIB/Compress + * compressed document is provided by default if found at compile-time. + * It use the given SAX function block to handle the parsing callback. + * If sax is NULL, fallback to the default DOM tree building routines. + * + * Returns the resulting document tree unless SAX is NULL or the document is + * not well formed. + */ + +htmlDocPtr +htmlSAXParseFile(const char *filename, const char *encoding, htmlSAXHandlerPtr sax, + void *userData) { + htmlDocPtr ret; + htmlParserCtxtPtr ctxt; + htmlSAXHandlerPtr oldsax = NULL; + + xmlInitParser(); + + ctxt = htmlCreateFileParserCtxt(filename, encoding); + if (ctxt == NULL) return(NULL); + if (sax != NULL) { + oldsax = ctxt->sax; + ctxt->sax = sax; + ctxt->userData = userData; + } + + htmlParseDocument(ctxt); + + ret = ctxt->myDoc; + if (sax != NULL) { + ctxt->sax = oldsax; + ctxt->userData = NULL; + } + htmlFreeParserCtxt(ctxt); + + return(ret); +} + +/** + * htmlParseFile: + * @filename: the filename + * @encoding: a free form C string describing the HTML document encoding, or NULL + * + * parse an HTML file and build a tree. Automatic support for ZLIB/Compress + * compressed document is provided by default if found at compile-time. + * + * Returns the resulting document tree + */ + +htmlDocPtr +htmlParseFile(const char *filename, const char *encoding) { + return(htmlSAXParseFile(filename, encoding, NULL, NULL)); +} + +/** + * htmlHandleOmittedElem: + * @val: int 0 or 1 + * + * Set and return the previous value for handling HTML omitted tags. + * + * Returns the last value for 0 for no handling, 1 for auto insertion. + */ + +int +htmlHandleOmittedElem(int val) { + int old = htmlOmittedDefaultValue; + + htmlOmittedDefaultValue = val; + return(old); +} + +/** + * htmlElementAllowedHere: + * @parent: HTML parent element + * @elt: HTML element + * + * Checks whether an HTML element may be a direct child of a parent element. + * Note - doesn't check for deprecated elements + * + * Returns 1 if allowed; 0 otherwise. + */ +int +htmlElementAllowedHere(const htmlElemDesc* parent, const xmlChar* elt) { + const char** p ; + + if ( ! elt || ! parent || ! parent->subelts ) + return 0 ; + + for ( p = parent->subelts; *p; ++p ) + if ( !xmlStrcmp((const xmlChar *)*p, elt) ) + return 1 ; + + return 0 ; +} +/** + * htmlElementStatusHere: + * @parent: HTML parent element + * @elt: HTML element + * + * Checks whether an HTML element may be a direct child of a parent element. + * and if so whether it is valid or deprecated. + * + * Returns one of HTML_VALID, HTML_DEPRECATED, HTML_INVALID + */ +htmlStatus +htmlElementStatusHere(const htmlElemDesc* parent, const htmlElemDesc* elt) { + if ( ! parent || ! elt ) + return HTML_INVALID ; + if ( ! htmlElementAllowedHere(parent, (const xmlChar*) elt->name ) ) + return HTML_INVALID ; + + return ( elt->dtd == 0 ) ? HTML_VALID : HTML_DEPRECATED ; +} +/** + * htmlAttrAllowed: + * @elt: HTML element + * @attr: HTML attribute + * @legacy: whether to allow deprecated attributes + * + * Checks whether an attribute is valid for an element + * Has full knowledge of Required and Deprecated attributes + * + * Returns one of HTML_REQUIRED, HTML_VALID, HTML_DEPRECATED, HTML_INVALID + */ +htmlStatus +htmlAttrAllowed(const htmlElemDesc* elt, const xmlChar* attr, int legacy) { + const char** p ; + + if ( !elt || ! attr ) + return HTML_INVALID ; + + if ( elt->attrs_req ) + for ( p = elt->attrs_req; *p; ++p) + if ( !xmlStrcmp((const xmlChar*)*p, attr) ) + return HTML_REQUIRED ; + + if ( elt->attrs_opt ) + for ( p = elt->attrs_opt; *p; ++p) + if ( !xmlStrcmp((const xmlChar*)*p, attr) ) + return HTML_VALID ; + + if ( legacy && elt->attrs_depr ) + for ( p = elt->attrs_depr; *p; ++p) + if ( !xmlStrcmp((const xmlChar*)*p, attr) ) + return HTML_DEPRECATED ; + + return HTML_INVALID ; +} +/** + * htmlNodeStatus: + * @node: an htmlNodePtr in a tree + * @legacy: whether to allow deprecated elements (YES is faster here + * for Element nodes) + * + * Checks whether the tree node is valid. Experimental (the author + * only uses the HTML enhancements in a SAX parser) + * + * Return: for Element nodes, a return from htmlElementAllowedHere (if + * legacy allowed) or htmlElementStatusHere (otherwise). + * for Attribute nodes, a return from htmlAttrAllowed + * for other nodes, HTML_NA (no checks performed) + */ +htmlStatus +htmlNodeStatus(const htmlNodePtr node, int legacy) { + if ( ! node ) + return HTML_INVALID ; + + switch ( node->type ) { + case XML_ELEMENT_NODE: + return legacy + ? ( htmlElementAllowedHere ( + htmlTagLookup(node->parent->name) , node->name + ) ? HTML_VALID : HTML_INVALID ) + : htmlElementStatusHere( + htmlTagLookup(node->parent->name) , + htmlTagLookup(node->name) ) + ; + case XML_ATTRIBUTE_NODE: + return htmlAttrAllowed( + htmlTagLookup(node->parent->name) , node->name, legacy) ; + default: return HTML_NA ; + } +} +/************************************************************************ + * * + * New set (2.6.0) of simpler and more flexible APIs * + * * + ************************************************************************/ +/** + * DICT_FREE: + * @str: a string + * + * Free a string if it is not owned by the "dict" dictionnary in the + * current scope + */ +#define DICT_FREE(str) \ + if ((str) && ((!dict) || \ + (xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \ + xmlFree((char *)(str)); + +/** + * htmlCtxtReset: + * @ctxt: an HTML parser context + * + * Reset a parser context + */ +void +htmlCtxtReset(htmlParserCtxtPtr ctxt) +{ + xmlParserInputPtr input; + xmlDictPtr dict; + + if (ctxt == NULL) + return; + + xmlInitParser(); + dict = ctxt->dict; + + while ((input = inputPop(ctxt)) != NULL) { /* Non consuming */ + xmlFreeInputStream(input); + } + ctxt->inputNr = 0; + ctxt->input = NULL; + + ctxt->spaceNr = 0; + if (ctxt->spaceTab != NULL) { + ctxt->spaceTab[0] = -1; + ctxt->space = &ctxt->spaceTab[0]; + } else { + ctxt->space = NULL; + } + + + ctxt->nodeNr = 0; + ctxt->node = NULL; + + ctxt->nameNr = 0; + ctxt->name = NULL; + + DICT_FREE(ctxt->version); + ctxt->version = NULL; + DICT_FREE(ctxt->encoding); + ctxt->encoding = NULL; + DICT_FREE(ctxt->directory); + ctxt->directory = NULL; + DICT_FREE(ctxt->extSubURI); + ctxt->extSubURI = NULL; + DICT_FREE(ctxt->extSubSystem); + ctxt->extSubSystem = NULL; + if (ctxt->myDoc != NULL) + xmlFreeDoc(ctxt->myDoc); + ctxt->myDoc = NULL; + + ctxt->standalone = -1; + ctxt->hasExternalSubset = 0; + ctxt->hasPErefs = 0; + ctxt->html = 1; + ctxt->external = 0; + ctxt->instate = XML_PARSER_START; + ctxt->token = 0; + + ctxt->wellFormed = 1; + ctxt->nsWellFormed = 1; + ctxt->valid = 1; + ctxt->vctxt.userData = ctxt; + ctxt->vctxt.error = xmlParserValidityError; + ctxt->vctxt.warning = xmlParserValidityWarning; + ctxt->record_info = 0; + ctxt->nbChars = 0; + ctxt->checkIndex = 0; + ctxt->inSubset = 0; + ctxt->errNo = XML_ERR_OK; + ctxt->depth = 0; + ctxt->charset = XML_CHAR_ENCODING_UTF8; + ctxt->catalogs = NULL; + xmlInitNodeInfoSeq(&ctxt->node_seq); + + if (ctxt->attsDefault != NULL) { + xmlHashFree(ctxt->attsDefault, (xmlHashDeallocator) xmlFree); + ctxt->attsDefault = NULL; + } + if (ctxt->attsSpecial != NULL) { + xmlHashFree(ctxt->attsSpecial, NULL); + ctxt->attsSpecial = NULL; + } +} + +/** + * htmlCtxtUseOptions: + * @ctxt: an HTML parser context + * @options: a combination of htmlParserOption(s) + * + * Applies the options to the parser context + * + * Returns 0 in case of success, the set of unknown or unimplemented options + * in case of error. + */ +int +htmlCtxtUseOptions(htmlParserCtxtPtr ctxt, int options) +{ + if (ctxt == NULL) + return(-1); + + if (options & HTML_PARSE_NOWARNING) { + ctxt->sax->warning = NULL; + ctxt->vctxt.warning = NULL; + options -= XML_PARSE_NOWARNING; + ctxt->options |= XML_PARSE_NOWARNING; + } + if (options & HTML_PARSE_NOERROR) { + ctxt->sax->error = NULL; + ctxt->vctxt.error = NULL; + ctxt->sax->fatalError = NULL; + options -= XML_PARSE_NOERROR; + ctxt->options |= XML_PARSE_NOERROR; + } + if (options & HTML_PARSE_PEDANTIC) { + ctxt->pedantic = 1; + options -= XML_PARSE_PEDANTIC; + ctxt->options |= XML_PARSE_PEDANTIC; + } else + ctxt->pedantic = 0; + if (options & XML_PARSE_NOBLANKS) { + ctxt->keepBlanks = 0; + ctxt->sax->ignorableWhitespace = xmlSAX2IgnorableWhitespace; + options -= XML_PARSE_NOBLANKS; + ctxt->options |= XML_PARSE_NOBLANKS; + } else + ctxt->keepBlanks = 1; + if (options & HTML_PARSE_RECOVER) { + ctxt->recovery = 1; + options -= HTML_PARSE_RECOVER; + } else + ctxt->recovery = 0; + if (options & HTML_PARSE_COMPACT) { + ctxt->options |= HTML_PARSE_COMPACT; + options -= HTML_PARSE_COMPACT; + } + ctxt->dictNames = 0; + return (options); +} + +/** + * htmlDoRead: + * @ctxt: an HTML parser context + * @URL: the base URL to use for the document + * @encoding: the document encoding, or NULL + * @options: a combination of htmlParserOption(s) + * @reuse: keep the context for reuse + * + * Common front-end for the htmlRead functions + * + * Returns the resulting document tree or NULL + */ +static htmlDocPtr +htmlDoRead(htmlParserCtxtPtr ctxt, const char *URL, const char *encoding, + int options, int reuse) +{ + htmlDocPtr ret; + + htmlCtxtUseOptions(ctxt, options); + ctxt->html = 1; + if (encoding != NULL) { + xmlCharEncodingHandlerPtr hdlr; + + hdlr = xmlFindCharEncodingHandler(encoding); + if (hdlr != NULL) + xmlSwitchToEncoding(ctxt, hdlr); + } + if ((URL != NULL) && (ctxt->input != NULL) && + (ctxt->input->filename == NULL)) + ctxt->input->filename = (char *) xmlStrdup((const xmlChar *) URL); + htmlParseDocument(ctxt); + ret = ctxt->myDoc; + ctxt->myDoc = NULL; + if (!reuse) { + if ((ctxt->dictNames) && + (ret != NULL) && + (ret->dict == ctxt->dict)) + ctxt->dict = NULL; + xmlFreeParserCtxt(ctxt); + } + return (ret); +} + +/** + * htmlReadDoc: + * @cur: a pointer to a zero terminated string + * @URL: the base URL to use for the document + * @encoding: the document encoding, or NULL + * @options: a combination of htmlParserOption(s) + * + * parse an XML in-memory document and build a tree. + * + * Returns the resulting document tree + */ +htmlDocPtr +htmlReadDoc(const xmlChar * cur, const char *URL, const char *encoding, int options) +{ + htmlParserCtxtPtr ctxt; + + if (cur == NULL) + return (NULL); + + xmlInitParser(); + ctxt = htmlCreateDocParserCtxt(cur, NULL); + if (ctxt == NULL) + return (NULL); + return (htmlDoRead(ctxt, URL, encoding, options, 0)); +} + +/** + * htmlReadFile: + * @filename: a file or URL + * @encoding: the document encoding, or NULL + * @options: a combination of htmlParserOption(s) + * + * parse an XML file from the filesystem or the network. + * + * Returns the resulting document tree + */ +htmlDocPtr +htmlReadFile(const char *filename, const char *encoding, int options) +{ + htmlParserCtxtPtr ctxt; + + xmlInitParser(); + ctxt = htmlCreateFileParserCtxt(filename, encoding); + if (ctxt == NULL) + return (NULL); + return (htmlDoRead(ctxt, NULL, NULL, options, 0)); +} + +/** + * htmlReadMemory: + * @buffer: a pointer to a char array + * @size: the size of the array + * @URL: the base URL to use for the document + * @encoding: the document encoding, or NULL + * @options: a combination of htmlParserOption(s) + * + * parse an XML in-memory document and build a tree. + * + * Returns the resulting document tree + */ +htmlDocPtr +htmlReadMemory(const char *buffer, int size, const char *URL, const char *encoding, int options) +{ + htmlParserCtxtPtr ctxt; + + xmlInitParser(); + ctxt = xmlCreateMemoryParserCtxt(buffer, size); + if (ctxt == NULL) + return (NULL); + htmlDefaultSAXHandlerInit(); + if (ctxt->sax != NULL) + memcpy(ctxt->sax, &htmlDefaultSAXHandler, sizeof(xmlSAXHandlerV1)); + return (htmlDoRead(ctxt, URL, encoding, options, 0)); +} + +/** + * htmlReadFd: + * @fd: an open file descriptor + * @URL: the base URL to use for the document + * @encoding: the document encoding, or NULL + * @options: a combination of htmlParserOption(s) + * + * parse an XML from a file descriptor and build a tree. + * + * Returns the resulting document tree + */ +htmlDocPtr +htmlReadFd(int fd, const char *URL, const char *encoding, int options) +{ + htmlParserCtxtPtr ctxt; + xmlParserInputBufferPtr input; + xmlParserInputPtr stream; + + if (fd < 0) + return (NULL); + + xmlInitParser(); + input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE); + if (input == NULL) + return (NULL); + ctxt = xmlNewParserCtxt(); + if (ctxt == NULL) { + xmlFreeParserInputBuffer(input); + return (NULL); + } + stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE); + if (stream == NULL) { + xmlFreeParserInputBuffer(input); + xmlFreeParserCtxt(ctxt); + return (NULL); + } + inputPush(ctxt, stream); + return (htmlDoRead(ctxt, URL, encoding, options, 0)); +} + +/** + * htmlReadIO: + * @ioread: an I/O read function + * @ioclose: an I/O close function + * @ioctx: an I/O handler + * @URL: the base URL to use for the document + * @encoding: the document encoding, or NULL + * @options: a combination of htmlParserOption(s) + * + * parse an HTML document from I/O functions and source and build a tree. + * + * Returns the resulting document tree + */ +htmlDocPtr +htmlReadIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose, + void *ioctx, const char *URL, const char *encoding, int options) +{ + htmlParserCtxtPtr ctxt; + xmlParserInputBufferPtr input; + xmlParserInputPtr stream; + + if (ioread == NULL) + return (NULL); + xmlInitParser(); + + input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx, + XML_CHAR_ENCODING_NONE); + if (input == NULL) + return (NULL); + ctxt = htmlNewParserCtxt(); + if (ctxt == NULL) { + xmlFreeParserInputBuffer(input); + return (NULL); + } + stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE); + if (stream == NULL) { + xmlFreeParserInputBuffer(input); + xmlFreeParserCtxt(ctxt); + return (NULL); + } + inputPush(ctxt, stream); + return (htmlDoRead(ctxt, URL, encoding, options, 0)); +} + +/** + * htmlCtxtReadDoc: + * @ctxt: an HTML parser context + * @cur: a pointer to a zero terminated string + * @URL: the base URL to use for the document + * @encoding: the document encoding, or NULL + * @options: a combination of htmlParserOption(s) + * + * parse an XML in-memory document and build a tree. + * This reuses the existing @ctxt parser context + * + * Returns the resulting document tree + */ +htmlDocPtr +htmlCtxtReadDoc(htmlParserCtxtPtr ctxt, const xmlChar * cur, + const char *URL, const char *encoding, int options) +{ + xmlParserInputPtr stream; + + if (cur == NULL) + return (NULL); + if (ctxt == NULL) + return (NULL); + + htmlCtxtReset(ctxt); + + stream = xmlNewStringInputStream(ctxt, cur); + if (stream == NULL) { + return (NULL); + } + inputPush(ctxt, stream); + return (htmlDoRead(ctxt, URL, encoding, options, 1)); +} + +/** + * htmlCtxtReadFile: + * @ctxt: an HTML parser context + * @filename: a file or URL + * @encoding: the document encoding, or NULL + * @options: a combination of htmlParserOption(s) + * + * parse an XML file from the filesystem or the network. + * This reuses the existing @ctxt parser context + * + * Returns the resulting document tree + */ +htmlDocPtr +htmlCtxtReadFile(htmlParserCtxtPtr ctxt, const char *filename, + const char *encoding, int options) +{ + xmlParserInputPtr stream; + + if (filename == NULL) + return (NULL); + if (ctxt == NULL) + return (NULL); + + htmlCtxtReset(ctxt); + + stream = xmlLoadExternalEntity(filename, NULL, ctxt); + if (stream == NULL) { + return (NULL); + } + inputPush(ctxt, stream); + return (htmlDoRead(ctxt, NULL, encoding, options, 1)); +} + +/** + * htmlCtxtReadMemory: + * @ctxt: an HTML parser context + * @buffer: a pointer to a char array + * @size: the size of the array + * @URL: the base URL to use for the document + * @encoding: the document encoding, or NULL + * @options: a combination of htmlParserOption(s) + * + * parse an XML in-memory document and build a tree. + * This reuses the existing @ctxt parser context + * + * Returns the resulting document tree + */ +htmlDocPtr +htmlCtxtReadMemory(htmlParserCtxtPtr ctxt, const char *buffer, int size, + const char *URL, const char *encoding, int options) +{ + xmlParserInputBufferPtr input; + xmlParserInputPtr stream; + + if (ctxt == NULL) + return (NULL); + if (buffer == NULL) + return (NULL); + + htmlCtxtReset(ctxt); + + input = xmlParserInputBufferCreateMem(buffer, size, XML_CHAR_ENCODING_NONE); + if (input == NULL) { + return(NULL); + } + + stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE); + if (stream == NULL) { + xmlFreeParserInputBuffer(input); + return(NULL); + } + + inputPush(ctxt, stream); + return (htmlDoRead(ctxt, URL, encoding, options, 1)); +} + +/** + * htmlCtxtReadFd: + * @ctxt: an HTML parser context + * @fd: an open file descriptor + * @URL: the base URL to use for the document + * @encoding: the document encoding, or NULL + * @options: a combination of htmlParserOption(s) + * + * parse an XML from a file descriptor and build a tree. + * This reuses the existing @ctxt parser context + * + * Returns the resulting document tree + */ +htmlDocPtr +htmlCtxtReadFd(htmlParserCtxtPtr ctxt, int fd, + const char *URL, const char *encoding, int options) +{ + xmlParserInputBufferPtr input; + xmlParserInputPtr stream; + + if (fd < 0) + return (NULL); + if (ctxt == NULL) + return (NULL); + + htmlCtxtReset(ctxt); + + + input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE); + if (input == NULL) + return (NULL); + stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE); + if (stream == NULL) { + xmlFreeParserInputBuffer(input); + return (NULL); + } + inputPush(ctxt, stream); + return (htmlDoRead(ctxt, URL, encoding, options, 1)); +} + +/** + * htmlCtxtReadIO: + * @ctxt: an HTML parser context + * @ioread: an I/O read function + * @ioclose: an I/O close function + * @ioctx: an I/O handler + * @URL: the base URL to use for the document + * @encoding: the document encoding, or NULL + * @options: a combination of htmlParserOption(s) + * + * parse an HTML document from I/O functions and source and build a tree. + * This reuses the existing @ctxt parser context + * + * Returns the resulting document tree + */ +htmlDocPtr +htmlCtxtReadIO(htmlParserCtxtPtr ctxt, xmlInputReadCallback ioread, + xmlInputCloseCallback ioclose, void *ioctx, + const char *URL, + const char *encoding, int options) +{ + xmlParserInputBufferPtr input; + xmlParserInputPtr stream; + + if (ioread == NULL) + return (NULL); + if (ctxt == NULL) + return (NULL); + + htmlCtxtReset(ctxt); + + input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx, + XML_CHAR_ENCODING_NONE); + if (input == NULL) + return (NULL); + stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE); + if (stream == NULL) { + xmlFreeParserInputBuffer(input); + return (NULL); + } + inputPush(ctxt, stream); + return (htmlDoRead(ctxt, URL, encoding, options, 1)); +} + +#define bottom_HTMLparser +#include "elfgcchack.h" +#endif /* LIBXML_HTML_ENABLED */ diff --git a/gettext-tools/gnulib-lib/libxml/HTMLparser.in.h b/gettext-tools/gnulib-lib/libxml/HTMLparser.in.h new file mode 100644 index 0000000..05905e4 --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/HTMLparser.in.h @@ -0,0 +1,303 @@ +/* + * Summary: interface for an HTML 4.0 non-verifying parser + * Description: this module implements an HTML 4.0 non-verifying parser + * with API compatible with the XML parser ones. It should + * be able to parse "real world" HTML, even if severely + * broken from a specification point of view. + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + +#ifndef __HTML_PARSER_H__ +#define __HTML_PARSER_H__ +#include +#include + +#ifdef LIBXML_HTML_ENABLED + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Most of the back-end structures from XML and HTML are shared. + */ +typedef xmlParserCtxt htmlParserCtxt; +typedef xmlParserCtxtPtr htmlParserCtxtPtr; +typedef xmlParserNodeInfo htmlParserNodeInfo; +typedef xmlSAXHandler htmlSAXHandler; +typedef xmlSAXHandlerPtr htmlSAXHandlerPtr; +typedef xmlParserInput htmlParserInput; +typedef xmlParserInputPtr htmlParserInputPtr; +typedef xmlDocPtr htmlDocPtr; +typedef xmlNodePtr htmlNodePtr; + +/* + * Internal description of an HTML element, representing HTML 4.01 + * and XHTML 1.0 (which share the same structure). + */ +typedef struct _htmlElemDesc htmlElemDesc; +typedef htmlElemDesc *htmlElemDescPtr; +struct _htmlElemDesc { + const char *name; /* The tag name */ + char startTag; /* Whether the start tag can be implied */ + char endTag; /* Whether the end tag can be implied */ + char saveEndTag; /* Whether the end tag should be saved */ + char empty; /* Is this an empty element ? */ + char depr; /* Is this a deprecated element ? */ + char dtd; /* 1: only in Loose DTD, 2: only Frameset one */ + char isinline; /* is this a block 0 or inline 1 element */ + const char *desc; /* the description */ + +/* NRK Jan.2003 + * New fields encapsulating HTML structure + * + * Bugs: + * This is a very limited representation. It fails to tell us when + * an element *requires* subelements (we only have whether they're + * allowed or not), and it doesn't tell us where CDATA and PCDATA + * are allowed. Some element relationships are not fully represented: + * these are flagged with the word MODIFIER + */ + const char** subelts; /* allowed sub-elements of this element */ + const char* defaultsubelt; /* subelement for suggested auto-repair + if necessary or NULL */ + const char** attrs_opt; /* Optional Attributes */ + const char** attrs_depr; /* Additional deprecated attributes */ + const char** attrs_req; /* Required attributes */ +}; + +/* + * Internal description of an HTML entity. + */ +typedef struct _htmlEntityDesc htmlEntityDesc; +typedef htmlEntityDesc *htmlEntityDescPtr; +struct _htmlEntityDesc { + unsigned int value; /* the UNICODE value for the character */ + const char *name; /* The entity name */ + const char *desc; /* the description */ +}; + +/* + * There is only few public functions. + */ +XMLPUBFUN const htmlElemDesc * XMLCALL + htmlTagLookup (const xmlChar *tag); +XMLPUBFUN const htmlEntityDesc * XMLCALL + htmlEntityLookup(const xmlChar *name); +XMLPUBFUN const htmlEntityDesc * XMLCALL + htmlEntityValueLookup(unsigned int value); + +XMLPUBFUN int XMLCALL + htmlIsAutoClosed(htmlDocPtr doc, + htmlNodePtr elem); +XMLPUBFUN int XMLCALL + htmlAutoCloseTag(htmlDocPtr doc, + const xmlChar *name, + htmlNodePtr elem); +XMLPUBFUN const htmlEntityDesc * XMLCALL + htmlParseEntityRef(htmlParserCtxtPtr ctxt, + const xmlChar **str); +XMLPUBFUN int XMLCALL + htmlParseCharRef(htmlParserCtxtPtr ctxt); +XMLPUBFUN void XMLCALL + htmlParseElement(htmlParserCtxtPtr ctxt); + +XMLPUBFUN htmlParserCtxtPtr XMLCALL + htmlNewParserCtxt(void); + +XMLPUBFUN htmlParserCtxtPtr XMLCALL + htmlCreateMemoryParserCtxt(const char *buffer, + int size); + +XMLPUBFUN int XMLCALL + htmlParseDocument(htmlParserCtxtPtr ctxt); +XMLPUBFUN htmlDocPtr XMLCALL + htmlSAXParseDoc (xmlChar *cur, + const char *encoding, + htmlSAXHandlerPtr sax, + void *userData); +XMLPUBFUN htmlDocPtr XMLCALL + htmlParseDoc (xmlChar *cur, + const char *encoding); +XMLPUBFUN htmlDocPtr XMLCALL + htmlSAXParseFile(const char *filename, + const char *encoding, + htmlSAXHandlerPtr sax, + void *userData); +XMLPUBFUN htmlDocPtr XMLCALL + htmlParseFile (const char *filename, + const char *encoding); +XMLPUBFUN int XMLCALL + UTF8ToHtml (unsigned char *out, + int *outlen, + const unsigned char *in, + int *inlen); +XMLPUBFUN int XMLCALL + htmlEncodeEntities(unsigned char *out, + int *outlen, + const unsigned char *in, + int *inlen, int quoteChar); +XMLPUBFUN int XMLCALL + htmlIsScriptAttribute(const xmlChar *name); +XMLPUBFUN int XMLCALL + htmlHandleOmittedElem(int val); + +#ifdef LIBXML_PUSH_ENABLED +/** + * Interfaces for the Push mode. + */ +XMLPUBFUN htmlParserCtxtPtr XMLCALL + htmlCreatePushParserCtxt(htmlSAXHandlerPtr sax, + void *user_data, + const char *chunk, + int size, + const char *filename, + xmlCharEncoding enc); +XMLPUBFUN int XMLCALL + htmlParseChunk (htmlParserCtxtPtr ctxt, + const char *chunk, + int size, + int terminate); +#endif /* LIBXML_PUSH_ENABLED */ + +XMLPUBFUN void XMLCALL + htmlFreeParserCtxt (htmlParserCtxtPtr ctxt); + +/* + * New set of simpler/more flexible APIs + */ +/** + * xmlParserOption: + * + * This is the set of XML parser options that can be passed down + * to the xmlReadDoc() and similar calls. + */ +typedef enum { + HTML_PARSE_RECOVER = 1<<0, /* Relaxed parsing */ + HTML_PARSE_NOERROR = 1<<5, /* suppress error reports */ + HTML_PARSE_NOWARNING= 1<<6, /* suppress warning reports */ + HTML_PARSE_PEDANTIC = 1<<7, /* pedantic error reporting */ + HTML_PARSE_NOBLANKS = 1<<8, /* remove blank nodes */ + HTML_PARSE_NONET = 1<<11,/* Forbid network access */ + HTML_PARSE_COMPACT = 1<<16 /* compact small text nodes */ +} htmlParserOption; + +XMLPUBFUN void XMLCALL + htmlCtxtReset (htmlParserCtxtPtr ctxt); +XMLPUBFUN int XMLCALL + htmlCtxtUseOptions (htmlParserCtxtPtr ctxt, + int options); +XMLPUBFUN htmlDocPtr XMLCALL + htmlReadDoc (const xmlChar *cur, + const char *URL, + const char *encoding, + int options); +XMLPUBFUN htmlDocPtr XMLCALL + htmlReadFile (const char *URL, + const char *encoding, + int options); +XMLPUBFUN htmlDocPtr XMLCALL + htmlReadMemory (const char *buffer, + int size, + const char *URL, + const char *encoding, + int options); +XMLPUBFUN htmlDocPtr XMLCALL + htmlReadFd (int fd, + const char *URL, + const char *encoding, + int options); +XMLPUBFUN htmlDocPtr XMLCALL + htmlReadIO (xmlInputReadCallback ioread, + xmlInputCloseCallback ioclose, + void *ioctx, + const char *URL, + const char *encoding, + int options); +XMLPUBFUN htmlDocPtr XMLCALL + htmlCtxtReadDoc (xmlParserCtxtPtr ctxt, + const xmlChar *cur, + const char *URL, + const char *encoding, + int options); +XMLPUBFUN htmlDocPtr XMLCALL + htmlCtxtReadFile (xmlParserCtxtPtr ctxt, + const char *filename, + const char *encoding, + int options); +XMLPUBFUN htmlDocPtr XMLCALL + htmlCtxtReadMemory (xmlParserCtxtPtr ctxt, + const char *buffer, + int size, + const char *URL, + const char *encoding, + int options); +XMLPUBFUN htmlDocPtr XMLCALL + htmlCtxtReadFd (xmlParserCtxtPtr ctxt, + int fd, + const char *URL, + const char *encoding, + int options); +XMLPUBFUN htmlDocPtr XMLCALL + htmlCtxtReadIO (xmlParserCtxtPtr ctxt, + xmlInputReadCallback ioread, + xmlInputCloseCallback ioclose, + void *ioctx, + const char *URL, + const char *encoding, + int options); + +/* NRK/Jan2003: further knowledge of HTML structure + */ +typedef enum { + HTML_NA = 0 , /* something we don't check at all */ + HTML_INVALID = 0x1 , + HTML_DEPRECATED = 0x2 , + HTML_VALID = 0x4 , + HTML_REQUIRED = 0xc /* VALID bit set so ( & HTML_VALID ) is TRUE */ +} htmlStatus ; + +/* Using htmlElemDesc rather than name here, to emphasise the fact + that otherwise there's a lookup overhead +*/ +XMLPUBFUN htmlStatus XMLCALL htmlAttrAllowed(const htmlElemDesc*, const xmlChar*, int) ; +XMLPUBFUN int XMLCALL htmlElementAllowedHere(const htmlElemDesc*, const xmlChar*) ; +XMLPUBFUN htmlStatus XMLCALL htmlElementStatusHere(const htmlElemDesc*, const htmlElemDesc*) ; +XMLPUBFUN htmlStatus XMLCALL htmlNodeStatus(const htmlNodePtr, int) ; +/** + * htmlDefaultSubelement: + * @elt: HTML element + * + * Returns the default subelement for this element + */ +#define htmlDefaultSubelement(elt) elt->defaultsubelt +/** + * htmlElementAllowedHereDesc: + * @parent: HTML parent element + * @elt: HTML element + * + * Checks whether an HTML element description may be a + * direct child of the specified element. + * + * Returns 1 if allowed; 0 otherwise. + */ +#define htmlElementAllowedHereDesc(parent,elt) \ + htmlElementAllowedHere((parent), (elt)->name) +/** + * htmlRequiredAttrs: + * @elt: HTML element + * + * Returns the attributes required for the specified element. + */ +#define htmlRequiredAttrs(elt) (elt)->attrs_req + + +#ifdef __cplusplus +} +#endif + +#endif /* LIBXML_HTML_ENABLED */ +#endif /* __HTML_PARSER_H__ */ diff --git a/gettext-tools/gnulib-lib/libxml/HTMLtree.c b/gettext-tools/gnulib-lib/libxml/HTMLtree.c new file mode 100644 index 0000000..c1e5a0a --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/HTMLtree.c @@ -0,0 +1,1213 @@ +/* + * HTMLtree.c : implementation of access function for an HTML tree. + * + * See Copyright for the status of this software. + * + * daniel@veillard.com + */ + + +#define IN_LIBXML +#include "libxml.h" +#ifdef LIBXML_HTML_ENABLED + +#include /* for memset() only ! */ + +#ifdef HAVE_CTYPE_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/************************************************************************ + * * + * Getting/Setting encoding meta tags * + * * + ************************************************************************/ + +/** + * htmlGetMetaEncoding: + * @doc: the document + * + * Encoding definition lookup in the Meta tags + * + * Returns the current encoding as flagged in the HTML source + */ +const xmlChar * +htmlGetMetaEncoding(htmlDocPtr doc) { + htmlNodePtr cur; + const xmlChar *content; + const xmlChar *encoding; + + if (doc == NULL) + return(NULL); + cur = doc->children; + + /* + * Search the html + */ + while (cur != NULL) { + if ((cur->type == XML_ELEMENT_NODE) && (cur->name != NULL)) { + if (xmlStrEqual(cur->name, BAD_CAST"html")) + break; + if (xmlStrEqual(cur->name, BAD_CAST"head")) + goto found_head; + if (xmlStrEqual(cur->name, BAD_CAST"meta")) + goto found_meta; + } + cur = cur->next; + } + if (cur == NULL) + return(NULL); + cur = cur->children; + + /* + * Search the head + */ + while (cur != NULL) { + if ((cur->type == XML_ELEMENT_NODE) && (cur->name != NULL)) { + if (xmlStrEqual(cur->name, BAD_CAST"head")) + break; + if (xmlStrEqual(cur->name, BAD_CAST"meta")) + goto found_meta; + } + cur = cur->next; + } + if (cur == NULL) + return(NULL); +found_head: + cur = cur->children; + + /* + * Search the meta elements + */ +found_meta: + while (cur != NULL) { + if ((cur->type == XML_ELEMENT_NODE) && (cur->name != NULL)) { + if (xmlStrEqual(cur->name, BAD_CAST"meta")) { + xmlAttrPtr attr = cur->properties; + int http; + const xmlChar *value; + + content = NULL; + http = 0; + while (attr != NULL) { + if ((attr->children != NULL) && + (attr->children->type == XML_TEXT_NODE) && + (attr->children->next == NULL)) { + value = attr->children->content; + if ((!xmlStrcasecmp(attr->name, BAD_CAST"http-equiv")) + && (!xmlStrcasecmp(value, BAD_CAST"Content-Type"))) + http = 1; + else if ((value != NULL) + && (!xmlStrcasecmp(attr->name, BAD_CAST"content"))) + content = value; + if ((http != 0) && (content != NULL)) + goto found_content; + } + attr = attr->next; + } + } + } + cur = cur->next; + } + return(NULL); + +found_content: + encoding = xmlStrstr(content, BAD_CAST"charset="); + if (encoding == NULL) + encoding = xmlStrstr(content, BAD_CAST"Charset="); + if (encoding == NULL) + encoding = xmlStrstr(content, BAD_CAST"CHARSET="); + if (encoding != NULL) { + encoding += 8; + } else { + encoding = xmlStrstr(content, BAD_CAST"charset ="); + if (encoding == NULL) + encoding = xmlStrstr(content, BAD_CAST"Charset ="); + if (encoding == NULL) + encoding = xmlStrstr(content, BAD_CAST"CHARSET ="); + if (encoding != NULL) + encoding += 9; + } + if (encoding != NULL) { + while ((*encoding == ' ') || (*encoding == '\t')) encoding++; + } + return(encoding); +} + +/** + * htmlSetMetaEncoding: + * @doc: the document + * @encoding: the encoding string + * + * Sets the current encoding in the Meta tags + * NOTE: this will not change the document content encoding, just + * the META flag associated. + * + * Returns 0 in case of success and -1 in case of error + */ +int +htmlSetMetaEncoding(htmlDocPtr doc, const xmlChar *encoding) { + htmlNodePtr cur, meta; + const xmlChar *content; + char newcontent[100]; + + + if (doc == NULL) + return(-1); + + if (encoding != NULL) { + snprintf(newcontent, sizeof(newcontent), "text/html; charset=%s", + (char *)encoding); + newcontent[sizeof(newcontent) - 1] = 0; + } + + cur = doc->children; + + /* + * Search the html + */ + while (cur != NULL) { + if ((cur->type == XML_ELEMENT_NODE) && (cur->name != NULL)) { + if (xmlStrcasecmp(cur->name, BAD_CAST"html") == 0) + break; + if (xmlStrcasecmp(cur->name, BAD_CAST"head") == 0) + goto found_head; + if (xmlStrcasecmp(cur->name, BAD_CAST"meta") == 0) + goto found_meta; + } + cur = cur->next; + } + if (cur == NULL) + return(-1); + cur = cur->children; + + /* + * Search the head + */ + while (cur != NULL) { + if ((cur->type == XML_ELEMENT_NODE) && (cur->name != NULL)) { + if (xmlStrcasecmp(cur->name, BAD_CAST"head") == 0) + break; + if (xmlStrcasecmp(cur->name, BAD_CAST"meta") == 0) + goto found_meta; + } + cur = cur->next; + } + if (cur == NULL) + return(-1); +found_head: + if (cur->children == NULL) { + if (encoding == NULL) + return(0); + meta = xmlNewDocNode(doc, NULL, BAD_CAST"meta", NULL); + xmlAddChild(cur, meta); + xmlNewProp(meta, BAD_CAST"http-equiv", BAD_CAST"Content-Type"); + xmlNewProp(meta, BAD_CAST"content", BAD_CAST newcontent); + return(0); + } + cur = cur->children; + +found_meta: + if (encoding != NULL) { + /* + * Create a new Meta element with the right attributes + */ + + meta = xmlNewDocNode(doc, NULL, BAD_CAST"meta", NULL); + xmlAddPrevSibling(cur, meta); + xmlNewProp(meta, BAD_CAST"http-equiv", BAD_CAST"Content-Type"); + xmlNewProp(meta, BAD_CAST"content", BAD_CAST newcontent); + } + + /* + * Search and destroy all the remaining the meta elements carrying + * encoding informations + */ + while (cur != NULL) { + if ((cur->type == XML_ELEMENT_NODE) && (cur->name != NULL)) { + if (xmlStrcasecmp(cur->name, BAD_CAST"meta") == 0) { + xmlAttrPtr attr = cur->properties; + int http; + const xmlChar *value; + + content = NULL; + http = 0; + while (attr != NULL) { + if ((attr->children != NULL) && + (attr->children->type == XML_TEXT_NODE) && + (attr->children->next == NULL)) { + value = attr->children->content; + if ((!xmlStrcasecmp(attr->name, BAD_CAST"http-equiv")) + && (!xmlStrcasecmp(value, BAD_CAST"Content-Type"))) + http = 1; + else + { + if ((value != NULL) && + (!xmlStrcasecmp(attr->name, BAD_CAST"content"))) + content = value; + } + if ((http != 0) && (content != NULL)) + break; + } + attr = attr->next; + } + if ((http != 0) && (content != NULL)) { + meta = cur; + cur = cur->next; + xmlUnlinkNode(meta); + xmlFreeNode(meta); + continue; + } + + } + } + cur = cur->next; + } + return(0); +} + +/** + * booleanHTMLAttrs: + * + * These are the HTML attributes which will be output + * in minimized form, i.e. */ + ret = xmlNewNsPropEatName(ctxt->node, namespace, name, NULL); + + if (ret != NULL) { + if ((ctxt->replaceEntities == 0) && (!ctxt->html)) { + xmlNodePtr tmp; + + ret->children = xmlStringGetNodeList(ctxt->myDoc, value); + tmp = ret->children; + while (tmp != NULL) { + tmp->parent = (xmlNodePtr) ret; + if (tmp->next == NULL) + ret->last = tmp; + tmp = tmp->next; + } + } else if (value != NULL) { + ret->children = xmlNewDocText(ctxt->myDoc, value); + ret->last = ret->children; + if (ret->children != NULL) + ret->children->parent = (xmlNodePtr) ret; + } + } + +#ifdef LIBXML_VALID_ENABLED + if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed && + ctxt->myDoc && ctxt->myDoc->intSubset) { + + /* + * If we don't substitute entities, the validation should be + * done on a value with replaced entities anyway. + */ + if (!ctxt->replaceEntities) { + xmlChar *val; + + ctxt->depth++; + val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF, + 0,0,0); + ctxt->depth--; + + if (val == NULL) + ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, + ctxt->myDoc, ctxt->node, ret, value); + else { + xmlChar *nvalnorm; + + /* + * Do the last stage of the attribute normalization + * It need to be done twice ... it's an extra burden related + * to the ability to keep xmlSAX2References in attributes + */ + nvalnorm = xmlValidNormalizeAttributeValue(ctxt->myDoc, + ctxt->node, fullname, val); + if (nvalnorm != NULL) { + xmlFree(val); + val = nvalnorm; + } + + ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, + ctxt->myDoc, ctxt->node, ret, val); + xmlFree(val); + } + } else { + ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc, + ctxt->node, ret, value); + } + } else +#endif /* LIBXML_VALID_ENABLED */ + if (((ctxt->loadsubset & XML_SKIP_IDS) == 0) && + (((ctxt->replaceEntities == 0) && (ctxt->external != 2)) || + ((ctxt->replaceEntities != 0) && (ctxt->inSubset == 0)))) { + /* + * when validating, the ID registration is done at the attribute + * validation level. Otherwise we have to do specific handling here. + */ + if (xmlStrEqual(fullname, BAD_CAST "xml:id")) { + /* + * Add the xml:id value + * + * Open issue: normalization of the value. + */ + if (xmlValidateNCName(value, 1) != 0) { + xmlErrValid(ctxt, XML_DTD_XMLID_VALUE, + "xml:id : attribute value %s is not an NCName\n", + (const char *) value, NULL); + } + xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret); + } else if (xmlIsID(ctxt->myDoc, ctxt->node, ret)) + xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret); + else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret)) + xmlAddRef(&ctxt->vctxt, ctxt->myDoc, value, ret); + } + +error: + if (nval != NULL) + xmlFree(nval); + if (ns != NULL) + xmlFree(ns); +} + +/* + * xmlCheckDefaultedAttributes: + * + * Check defaulted attributes from the DTD + */ +static void +xmlCheckDefaultedAttributes(xmlParserCtxtPtr ctxt, const xmlChar *name, + const xmlChar *prefix, const xmlChar **atts) { + xmlElementPtr elemDecl; + const xmlChar *att; + int internal = 1; + int i; + + elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->intSubset, name, prefix); + if (elemDecl == NULL) { + elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->extSubset, name, prefix); + internal = 0; + } + +process_external_subset: + + if (elemDecl != NULL) { + xmlAttributePtr attr = elemDecl->attributes; + /* + * Check against defaulted attributes from the external subset + * if the document is stamped as standalone + */ + if ((ctxt->myDoc->standalone == 1) && + (ctxt->myDoc->extSubset != NULL) && + (ctxt->validate)) { + while (attr != NULL) { + if ((attr->defaultValue != NULL) && + (xmlGetDtdQAttrDesc(ctxt->myDoc->extSubset, + attr->elem, attr->name, + attr->prefix) == attr) && + (xmlGetDtdQAttrDesc(ctxt->myDoc->intSubset, + attr->elem, attr->name, + attr->prefix) == NULL)) { + xmlChar *fulln; + + if (attr->prefix != NULL) { + fulln = xmlStrdup(attr->prefix); + fulln = xmlStrcat(fulln, BAD_CAST ":"); + fulln = xmlStrcat(fulln, attr->name); + } else { + fulln = xmlStrdup(attr->name); + } + + /* + * Check that the attribute is not declared in the + * serialization + */ + att = NULL; + if (atts != NULL) { + i = 0; + att = atts[i]; + while (att != NULL) { + if (xmlStrEqual(att, fulln)) + break; + i += 2; + att = atts[i]; + } + } + if (att == NULL) { + xmlErrValid(ctxt, XML_DTD_STANDALONE_DEFAULTED, + "standalone: attribute %s on %s defaulted from external subset\n", + (const char *)fulln, + (const char *)attr->elem); + } + } + attr = attr->nexth; + } + } + + /* + * Actually insert defaulted values when needed + */ + attr = elemDecl->attributes; + while (attr != NULL) { + /* + * Make sure that attributes redefinition occuring in the + * internal subset are not overriden by definitions in the + * external subset. + */ + if (attr->defaultValue != NULL) { + /* + * the element should be instantiated in the tree if: + * - this is a namespace prefix + * - the user required for completion in the tree + * like XSLT + * - there isn't already an attribute definition + * in the internal subset overriding it. + */ + if (((attr->prefix != NULL) && + (xmlStrEqual(attr->prefix, BAD_CAST "xmlns"))) || + ((attr->prefix == NULL) && + (xmlStrEqual(attr->name, BAD_CAST "xmlns"))) || + (ctxt->loadsubset & XML_COMPLETE_ATTRS)) { + xmlAttributePtr tst; + + tst = xmlGetDtdQAttrDesc(ctxt->myDoc->intSubset, + attr->elem, attr->name, + attr->prefix); + if ((tst == attr) || (tst == NULL)) { + xmlChar fn[50]; + xmlChar *fulln; + + fulln = xmlBuildQName(attr->name, attr->prefix, fn, 50); + if (fulln == NULL) { + xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement"); + return; + } + + /* + * Check that the attribute is not declared in the + * serialization + */ + att = NULL; + if (atts != NULL) { + i = 0; + att = atts[i]; + while (att != NULL) { + if (xmlStrEqual(att, fulln)) + break; + i += 2; + att = atts[i]; + } + } + if (att == NULL) { + xmlSAX2AttributeInternal(ctxt, fulln, + attr->defaultValue, prefix); + } + if ((fulln != fn) && (fulln != attr->name)) + xmlFree(fulln); + } + } + } + attr = attr->nexth; + } + if (internal == 1) { + elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->extSubset, + name, prefix); + internal = 0; + goto process_external_subset; + } + } +} + +/** + * xmlSAX2StartElement: + * @ctx: the user data (XML parser context) + * @fullname: The element name, including namespace prefix + * @atts: An array of name/value attributes pairs, NULL terminated + * + * called when an opening tag has been processed. + */ +void +xmlSAX2StartElement(void *ctx, const xmlChar *fullname, const xmlChar **atts) +{ + xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; + xmlNodePtr ret; + xmlNodePtr parent; + xmlNsPtr ns; + xmlChar *name; + xmlChar *prefix; + const xmlChar *att; + const xmlChar *value; + int i; + + if ((ctx == NULL) || (fullname == NULL) || (ctxt->myDoc == NULL)) return; + parent = ctxt->node; +#ifdef DEBUG_SAX + xmlGenericError(xmlGenericErrorContext, + "SAX.xmlSAX2StartElement(%s)\n", fullname); +#endif + + /* + * First check on validity: + */ + if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) && + ((ctxt->myDoc->intSubset == NULL) || + ((ctxt->myDoc->intSubset->notations == NULL) && + (ctxt->myDoc->intSubset->elements == NULL) && + (ctxt->myDoc->intSubset->attributes == NULL) && + (ctxt->myDoc->intSubset->entities == NULL)))) { + xmlErrValid(ctxt, XML_ERR_NO_DTD, + "Validation failed: no DTD found !", NULL, NULL); + ctxt->validate = 0; + } + + + /* + * Split the full name into a namespace prefix and the tag name + */ + name = xmlSplitQName(ctxt, fullname, &prefix); + + + /* + * Note : the namespace resolution is deferred until the end of the + * attributes parsing, since local namespace can be defined as + * an attribute at this level. + */ + ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL, name, NULL); + if (ret == NULL) { + if (prefix != NULL) + xmlFree(prefix); + xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement"); + return; + } + if (ctxt->myDoc->children == NULL) { +#ifdef DEBUG_SAX_TREE + xmlGenericError(xmlGenericErrorContext, "Setting %s as root\n", name); +#endif + xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret); + } else if (parent == NULL) { + parent = ctxt->myDoc->children; + } + ctxt->nodemem = -1; + if (ctxt->linenumbers) { + if (ctxt->input != NULL) { + if (ctxt->input->line < 65535) + ret->line = (short) ctxt->input->line; + else + ret->line = 65535; + } + } + + /* + * We are parsing a new node. + */ +#ifdef DEBUG_SAX_TREE + xmlGenericError(xmlGenericErrorContext, "pushing(%s)\n", name); +#endif + nodePush(ctxt, ret); + + /* + * Link the child element + */ + if (parent != NULL) { + if (parent->type == XML_ELEMENT_NODE) { +#ifdef DEBUG_SAX_TREE + xmlGenericError(xmlGenericErrorContext, + "adding child %s to %s\n", name, parent->name); +#endif + xmlAddChild(parent, ret); + } else { +#ifdef DEBUG_SAX_TREE + xmlGenericError(xmlGenericErrorContext, + "adding sibling %s to ", name); + xmlDebugDumpOneNode(stderr, parent, 0); +#endif + xmlAddSibling(parent, ret); + } + } + + /* + * Insert all the defaulted attributes from the DTD especially namespaces + */ + if ((!ctxt->html) && + ((ctxt->myDoc->intSubset != NULL) || + (ctxt->myDoc->extSubset != NULL))) { + xmlCheckDefaultedAttributes(ctxt, name, prefix, atts); + } + + /* + * process all the attributes whose name start with "xmlns" + */ + if (atts != NULL) { + i = 0; + att = atts[i++]; + value = atts[i++]; + if (!ctxt->html) { + while ((att != NULL) && (value != NULL)) { + if ((att[0] == 'x') && (att[1] == 'm') && (att[2] == 'l') && + (att[3] == 'n') && (att[4] == 's')) + xmlSAX2AttributeInternal(ctxt, att, value, prefix); + + att = atts[i++]; + value = atts[i++]; + } + } + } + + /* + * Search the namespace, note that since the attributes have been + * processed, the local namespaces are available. + */ + ns = xmlSearchNs(ctxt->myDoc, ret, prefix); + if ((ns == NULL) && (parent != NULL)) + ns = xmlSearchNs(ctxt->myDoc, parent, prefix); + if ((prefix != NULL) && (ns == NULL)) { + ns = xmlNewNs(ret, NULL, prefix); + xmlNsWarnMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE, + "Namespace prefix %s is not defined\n", + prefix, NULL); + } + + /* + * set the namespace node, making sure that if the default namspace + * is unbound on a parent we simply kee it NULL + */ + if ((ns != NULL) && (ns->href != NULL) && + ((ns->href[0] != 0) || (ns->prefix != NULL))) + xmlSetNs(ret, ns); + + /* + * process all the other attributes + */ + if (atts != NULL) { + i = 0; + att = atts[i++]; + value = atts[i++]; + if (ctxt->html) { + while (att != NULL) { + xmlSAX2AttributeInternal(ctxt, att, value, NULL); + att = atts[i++]; + value = atts[i++]; + } + } else { + while ((att != NULL) && (value != NULL)) { + if ((att[0] != 'x') || (att[1] != 'm') || (att[2] != 'l') || + (att[3] != 'n') || (att[4] != 's')) + xmlSAX2AttributeInternal(ctxt, att, value, NULL); + + /* + * Next ones + */ + att = atts[i++]; + value = atts[i++]; + } + } + } + +#ifdef LIBXML_VALID_ENABLED + /* + * If it's the Document root, finish the DTD validation and + * check the document root element for validity + */ + if ((ctxt->validate) && (ctxt->vctxt.finishDtd == XML_CTXT_FINISH_DTD_0)) { + int chk; + + chk = xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc); + if (chk <= 0) + ctxt->valid = 0; + if (chk < 0) + ctxt->wellFormed = 0; + ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc); + ctxt->vctxt.finishDtd = XML_CTXT_FINISH_DTD_1; + } +#endif /* LIBXML_VALID_ENABLED */ + + if (prefix != NULL) + xmlFree(prefix); + +} + +/** + * xmlSAX2EndElement: + * @ctx: the user data (XML parser context) + * @name: The element name + * + * called when the end of an element has been detected. + */ +void +xmlSAX2EndElement(void *ctx, const xmlChar *name ATTRIBUTE_UNUSED) +{ + xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; + xmlParserNodeInfo node_info; + xmlNodePtr cur; + + if (ctx == NULL) return; + cur = ctxt->node; +#ifdef DEBUG_SAX + if (name == NULL) + xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2EndElement(NULL)\n"); + else + xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2EndElement(%s)\n", name); +#endif + + /* Capture end position and add node */ + if (cur != NULL && ctxt->record_info) { + node_info.end_pos = ctxt->input->cur - ctxt->input->base; + node_info.end_line = ctxt->input->line; + node_info.node = cur; + xmlParserAddNodeInfo(ctxt, &node_info); + } + ctxt->nodemem = -1; + +#ifdef LIBXML_VALID_ENABLED + if (ctxt->validate && ctxt->wellFormed && + ctxt->myDoc && ctxt->myDoc->intSubset) + ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc, + cur); +#endif /* LIBXML_VALID_ENABLED */ + + + /* + * end of parsing of this node. + */ +#ifdef DEBUG_SAX_TREE + xmlGenericError(xmlGenericErrorContext, "popping(%s)\n", cur->name); +#endif + nodePop(ctxt); +} +#endif /* LIBXML_SAX1_ENABLED || LIBXML_HTML_ENABLE */ + +/* + * xmlSAX2TextNode: + * @ctxt: the parser context + * @str: the input string + * @len: the string length + * + * Remove the entities from an attribute value + * + * Returns the newly allocated string or NULL if not needed or error + */ +static xmlNodePtr +xmlSAX2TextNode(xmlParserCtxtPtr ctxt, const xmlChar *str, int len) { + xmlNodePtr ret; + const xmlChar *intern = NULL; + + /* + * Allocate + */ + if (ctxt->freeElems != NULL) { + ret = ctxt->freeElems; + ctxt->freeElems = ret->next; + ctxt->freeElemsNr--; + } else { + ret = (xmlNodePtr) xmlMalloc(sizeof(xmlNode)); + } + if (ret == NULL) { + xmlErrMemory(ctxt, "xmlSAX2Characters"); + return(NULL); + } + memset(ret, 0, sizeof(xmlNode)); + /* + * intern the formatting blanks found between tags, or the + * very short strings + */ + if (ctxt->dictNames) { + xmlChar cur = str[len]; + + if ((len < (int) (2 * sizeof(void *))) && + (ctxt->options & XML_PARSE_COMPACT)) { + /* store the string in the node overrithing properties and nsDef */ + xmlChar *tmp = (xmlChar *) &(ret->properties); + memcpy(tmp, str, len); + tmp[len] = 0; + intern = tmp; + } else if ((len <= 3) && ((cur == '"') || (cur == '\'') || + ((cur == '<') && (str[len + 1] != '!')))) { + intern = xmlDictLookup(ctxt->dict, str, len); + } else if (IS_BLANK_CH(*str) && (len < 60) && (cur == '<') && + (str[len + 1] != '!')) { + int i; + + for (i = 1;i < len;i++) { + if (!IS_BLANK_CH(str[i])) goto skip; + } + intern = xmlDictLookup(ctxt->dict, str, len); + } + } +skip: + ret->type = XML_TEXT_NODE; + + ret->name = xmlStringText; + if (intern == NULL) { + ret->content = xmlStrndup(str, len); + if (ret->content == NULL) { + xmlSAX2ErrMemory(ctxt, "xmlSAX2TextNode"); + xmlFree(ret); + return(NULL); + } + } else + ret->content = (xmlChar *) intern; + + if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)) + xmlRegisterNodeDefaultValue(ret); + return(ret); +} + +#ifdef LIBXML_VALID_ENABLED +/* + * xmlSAX2DecodeAttrEntities: + * @ctxt: the parser context + * @str: the input string + * @len: the string length + * + * Remove the entities from an attribute value + * + * Returns the newly allocated string or NULL if not needed or error + */ +static xmlChar * +xmlSAX2DecodeAttrEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, + const xmlChar *end) { + const xmlChar *in; + xmlChar *ret; + + in = str; + while (in < end) + if (*in++ == '&') + goto decode; + return(NULL); +decode: + ctxt->depth++; + ret = xmlStringLenDecodeEntities(ctxt, str, end - str, + XML_SUBSTITUTE_REF, 0,0,0); + ctxt->depth--; + return(ret); +} +#endif /* LIBXML_VALID_ENABLED */ + +/** + * xmlSAX2AttributeNs: + * @ctx: the user data (XML parser context) + * @localname: the local name of the attribute + * @prefix: the attribute namespace prefix if available + * @URI: the attribute namespace name if available + * @value: Start of the attribute value + * @valueend: end of the attribute value + * + * Handle an attribute that has been read by the parser. + * The default handling is to convert the attribute into an + * DOM subtree and past it in a new xmlAttr element added to + * the element. + */ +static void +xmlSAX2AttributeNs(xmlParserCtxtPtr ctxt, + const xmlChar * localname, + const xmlChar * prefix, + const xmlChar * value, + const xmlChar * valueend) +{ + xmlAttrPtr ret; + xmlNsPtr namespace = NULL; + xmlChar *dup = NULL; + + /* + * Note: if prefix == NULL, the attribute is not in the default namespace + */ + if (prefix != NULL) + namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, prefix); + + /* + * allocate the node + */ + if (ctxt->freeAttrs != NULL) { + ret = ctxt->freeAttrs; + ctxt->freeAttrs = ret->next; + ctxt->freeAttrsNr--; + memset(ret, 0, sizeof(xmlAttr)); + ret->type = XML_ATTRIBUTE_NODE; + + ret->parent = ctxt->node; + ret->doc = ctxt->myDoc; + ret->ns = namespace; + + if (ctxt->dictNames) + ret->name = localname; + else + ret->name = xmlStrdup(localname); + + /* link at the end to preserv order, TODO speed up with a last */ + if (ctxt->node->properties == NULL) { + ctxt->node->properties = ret; + } else { + xmlAttrPtr prev = ctxt->node->properties; + + while (prev->next != NULL) prev = prev->next; + prev->next = ret; + ret->prev = prev; + } + + if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)) + xmlRegisterNodeDefaultValue((xmlNodePtr)ret); + } else { + if (ctxt->dictNames) + ret = xmlNewNsPropEatName(ctxt->node, namespace, + (xmlChar *) localname, NULL); + else + ret = xmlNewNsProp(ctxt->node, namespace, localname, NULL); + if (ret == NULL) { + xmlErrMemory(ctxt, "xmlSAX2AttributeNs"); + return; + } + } + + if ((ctxt->replaceEntities == 0) && (!ctxt->html)) { + xmlNodePtr tmp; + + /* + * We know that if there is an entity reference, then + * the string has been dup'ed and terminates with 0 + * otherwise with ' or " + */ + if (*valueend != 0) { + tmp = xmlSAX2TextNode(ctxt, value, valueend - value); + ret->children = tmp; + ret->last = tmp; + if (tmp != NULL) { + tmp->doc = ret->doc; + tmp->parent = (xmlNodePtr) ret; + } + } else { + ret->children = xmlStringLenGetNodeList(ctxt->myDoc, value, + valueend - value); + tmp = ret->children; + while (tmp != NULL) { + tmp->doc = ret->doc; + tmp->parent = (xmlNodePtr) ret; + if (tmp->next == NULL) + ret->last = tmp; + tmp = tmp->next; + } + } + } else if (value != NULL) { + xmlNodePtr tmp; + + tmp = xmlSAX2TextNode(ctxt, value, valueend - value); + ret->children = tmp; + ret->last = tmp; + if (tmp != NULL) { + tmp->doc = ret->doc; + tmp->parent = (xmlNodePtr) ret; + } + } + +#ifdef LIBXML_VALID_ENABLED + if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed && + ctxt->myDoc && ctxt->myDoc->intSubset) { + /* + * If we don't substitute entities, the validation should be + * done on a value with replaced entities anyway. + */ + if (!ctxt->replaceEntities) { + dup = xmlSAX2DecodeAttrEntities(ctxt, value, valueend); + if (dup == NULL) { + if (*valueend == 0) { + ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, + ctxt->myDoc, ctxt->node, ret, value); + } else { + /* + * That should already be normalized. + * cheaper to finally allocate here than duplicate + * entry points in the full validation code + */ + dup = xmlStrndup(value, valueend - value); + + ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, + ctxt->myDoc, ctxt->node, ret, dup); + } + } else { + /* + * dup now contains a string of the flattened attribute + * content with entities substitued. Check if we need to + * apply an extra layer of normalization. + * It need to be done twice ... it's an extra burden related + * to the ability to keep references in attributes + */ + if (ctxt->attsSpecial != NULL) { + xmlChar *nvalnorm; + xmlChar fn[50]; + xmlChar *fullname; + + fullname = xmlBuildQName(localname, prefix, fn, 50); + if (fullname != NULL) { + ctxt->vctxt.valid = 1; + nvalnorm = xmlValidCtxtNormalizeAttributeValue( + &ctxt->vctxt, ctxt->myDoc, + ctxt->node, fullname, dup); + if (ctxt->vctxt.valid != 1) + ctxt->valid = 0; + + if ((fullname != fn) && (fullname != localname)) + xmlFree(fullname); + if (nvalnorm != NULL) { + xmlFree(dup); + dup = nvalnorm; + } + } + } + + ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, + ctxt->myDoc, ctxt->node, ret, dup); + } + } else { + /* + * if entities already have been substitued, then + * the attribute as passed is already normalized + */ + dup = xmlStrndup(value, valueend - value); + + ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, + ctxt->myDoc, ctxt->node, ret, dup); + } + } else +#endif /* LIBXML_VALID_ENABLED */ + if (((ctxt->loadsubset & XML_SKIP_IDS) == 0) && + (((ctxt->replaceEntities == 0) && (ctxt->external != 2)) || + ((ctxt->replaceEntities != 0) && (ctxt->inSubset == 0)))) { + /* + * when validating, the ID registration is done at the attribute + * validation level. Otherwise we have to do specific handling here. + */ + if ((prefix == ctxt->str_xml) && + (localname[0] == 'i') && (localname[1] == 'd') && + (localname[2] == 0)) { + /* + * Add the xml:id value + * + * Open issue: normalization of the value. + */ + if (dup == NULL) + dup = xmlStrndup(value, valueend - value); +#ifdef LIBXML_VALID_ENABLED + if (xmlValidateNCName(dup, 1) != 0) { + xmlErrValid(ctxt, XML_DTD_XMLID_VALUE, + "xml:id : attribute value %s is not an NCName\n", + (const char *) dup, NULL); + } +#endif + xmlAddID(&ctxt->vctxt, ctxt->myDoc, dup, ret); + } else if (xmlIsID(ctxt->myDoc, ctxt->node, ret)) { + /* might be worth duplicate entry points and not copy */ + if (dup == NULL) + dup = xmlStrndup(value, valueend - value); + xmlAddID(&ctxt->vctxt, ctxt->myDoc, dup, ret); + } else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret)) { + if (dup == NULL) + dup = xmlStrndup(value, valueend - value); + xmlAddRef(&ctxt->vctxt, ctxt->myDoc, dup, ret); + } + } + if (dup != NULL) + xmlFree(dup); +} + +/** + * xmlSAX2StartElementNs: + * @ctx: the user data (XML parser context) + * @localname: the local name of the element + * @prefix: the element namespace prefix if available + * @URI: the element namespace name if available + * @nb_namespaces: number of namespace definitions on that node + * @namespaces: pointer to the array of prefix/URI pairs namespace definitions + * @nb_attributes: the number of attributes on that node + * @nb_defaulted: the number of defaulted attributes. + * @attributes: pointer to the array of (localname/prefix/URI/value/end) + * attribute values. + * + * SAX2 callback when an element start has been detected by the parser. + * It provides the namespace informations for the element, as well as + * the new namespace declarations on the element. + */ +void +xmlSAX2StartElementNs(void *ctx, + const xmlChar *localname, + const xmlChar *prefix, + const xmlChar *URI, + int nb_namespaces, + const xmlChar **namespaces, + int nb_attributes, + int nb_defaulted, + const xmlChar **attributes) +{ + xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; + xmlNodePtr ret; + xmlNodePtr parent; + xmlNsPtr last = NULL, ns; + const xmlChar *uri, *pref; + int i, j; + + if (ctx == NULL) return; + parent = ctxt->node; + /* + * First check on validity: + */ + if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) && + ((ctxt->myDoc->intSubset == NULL) || + ((ctxt->myDoc->intSubset->notations == NULL) && + (ctxt->myDoc->intSubset->elements == NULL) && + (ctxt->myDoc->intSubset->attributes == NULL) && + (ctxt->myDoc->intSubset->entities == NULL)))) { + xmlErrValid(ctxt, XML_ERR_NO_DTD, + "Validation failed: no DTD found !", NULL, NULL); + ctxt->validate = 0; + } + + /* + * allocate the node + */ + if (ctxt->freeElems != NULL) { + ret = ctxt->freeElems; + ctxt->freeElems = ret->next; + ctxt->freeElemsNr--; + memset(ret, 0, sizeof(xmlNode)); + ret->type = XML_ELEMENT_NODE; + + if (ctxt->dictNames) + ret->name = localname; + else { + ret->name = xmlStrdup(localname); + if (ret->name == NULL) { + xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs"); + return; + } + } + if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)) + xmlRegisterNodeDefaultValue(ret); + } else { + if (ctxt->dictNames) + ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL, + (xmlChar *) localname, NULL); + else + ret = xmlNewDocNode(ctxt->myDoc, NULL, localname, NULL); + if (ret == NULL) { + xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs"); + return; + } + } + if (ctxt->linenumbers) { + if (ctxt->input != NULL) { + if (ctxt->input->line < 65535) + ret->line = (short) ctxt->input->line; + else + ret->line = 65535; + } + } + + if ((ctxt->myDoc->children == NULL) || (parent == NULL)) { + xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret); + } + /* + * Build the namespace list + */ + for (i = 0,j = 0;j < nb_namespaces;j++) { + pref = namespaces[i++]; + uri = namespaces[i++]; + ns = xmlNewNs(NULL, uri, pref); + if (ns != NULL) { + if (last == NULL) { + ret->nsDef = last = ns; + } else { + last->next = ns; + last = ns; + } + if ((URI != NULL) && (prefix == pref)) + ret->ns = ns; + } else { + xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs"); + return; + } +#ifdef LIBXML_VALID_ENABLED + if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed && + ctxt->myDoc && ctxt->myDoc->intSubset) { + ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc, + ret, prefix, ns, uri); + } +#endif /* LIBXML_VALID_ENABLED */ + } + ctxt->nodemem = -1; + + /* + * We are parsing a new node. + */ + nodePush(ctxt, ret); + + /* + * Link the child element + */ + if (parent != NULL) { + if (parent->type == XML_ELEMENT_NODE) { + xmlAddChild(parent, ret); + } else { + xmlAddSibling(parent, ret); + } + } + + /* + * Insert the defaulted attributes from the DTD only if requested: + */ + if ((nb_defaulted != 0) && + ((ctxt->loadsubset & XML_COMPLETE_ATTRS) == 0)) + nb_attributes -= nb_defaulted; + + /* + * Search the namespace if it wasn't already found + * Note that, if prefix is NULL, this searches for the default Ns + */ + if ((URI != NULL) && (ret->ns == NULL)) { + ret->ns = xmlSearchNs(ctxt->myDoc, parent, prefix); + if ((ret->ns == NULL) && (xmlStrEqual(prefix, BAD_CAST "xml"))) { + ret->ns = xmlSearchNs(ctxt->myDoc, ret, prefix); + } + if (ret->ns == NULL) { + ns = xmlNewNs(ret, NULL, prefix); + if (ns == NULL) { + + xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs"); + return; + } + xmlNsWarnMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE, + "Namespace prefix %s was not found\n", + prefix, NULL); + } + } + + /* + * process all the other attributes + */ + if (nb_attributes > 0) { + for (j = 0,i = 0;i < nb_attributes;i++,j+=5) { + xmlSAX2AttributeNs(ctxt, attributes[j], attributes[j+1], + attributes[j+3], attributes[j+4]); + } + } + +#ifdef LIBXML_VALID_ENABLED + /* + * If it's the Document root, finish the DTD validation and + * check the document root element for validity + */ + if ((ctxt->validate) && (ctxt->vctxt.finishDtd == XML_CTXT_FINISH_DTD_0)) { + int chk; + + chk = xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc); + if (chk <= 0) + ctxt->valid = 0; + if (chk < 0) + ctxt->wellFormed = 0; + ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc); + ctxt->vctxt.finishDtd = XML_CTXT_FINISH_DTD_1; + } +#endif /* LIBXML_VALID_ENABLED */ +} + +/** + * xmlSAX2EndElementNs: + * @ctx: the user data (XML parser context) + * @localname: the local name of the element + * @prefix: the element namespace prefix if available + * @URI: the element namespace name if available + * + * SAX2 callback when an element end has been detected by the parser. + * It provides the namespace informations for the element. + */ +void +xmlSAX2EndElementNs(void *ctx, + const xmlChar * localname ATTRIBUTE_UNUSED, + const xmlChar * prefix ATTRIBUTE_UNUSED, + const xmlChar * URI ATTRIBUTE_UNUSED) +{ + xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; + xmlParserNodeInfo node_info; + xmlNodePtr cur; + + if (ctx == NULL) return; + cur = ctxt->node; + /* Capture end position and add node */ + if ((ctxt->record_info) && (cur != NULL)) { + node_info.end_pos = ctxt->input->cur - ctxt->input->base; + node_info.end_line = ctxt->input->line; + node_info.node = cur; + xmlParserAddNodeInfo(ctxt, &node_info); + } + ctxt->nodemem = -1; + +#ifdef LIBXML_VALID_ENABLED + if (ctxt->validate && ctxt->wellFormed && + ctxt->myDoc && ctxt->myDoc->intSubset) + ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc, cur); +#endif /* LIBXML_VALID_ENABLED */ + + /* + * end of parsing of this node. + */ + nodePop(ctxt); +} + +/** + * xmlSAX2Reference: + * @ctx: the user data (XML parser context) + * @name: The entity name + * + * called when an entity xmlSAX2Reference is detected. + */ +void +xmlSAX2Reference(void *ctx, const xmlChar *name) +{ + xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; + xmlNodePtr ret; + + if (ctx == NULL) return; +#ifdef DEBUG_SAX + xmlGenericError(xmlGenericErrorContext, + "SAX.xmlSAX2Reference(%s)\n", name); +#endif + if (name[0] == '#') + ret = xmlNewCharRef(ctxt->myDoc, name); + else + ret = xmlNewReference(ctxt->myDoc, name); +#ifdef DEBUG_SAX_TREE + xmlGenericError(xmlGenericErrorContext, + "add xmlSAX2Reference %s to %s \n", name, ctxt->node->name); +#endif + xmlAddChild(ctxt->node, ret); +} + +/** + * xmlSAX2Characters: + * @ctx: the user data (XML parser context) + * @ch: a xmlChar string + * @len: the number of xmlChar + * + * receiving some chars from the parser. + */ +void +xmlSAX2Characters(void *ctx, const xmlChar *ch, int len) +{ + xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; + xmlNodePtr lastChild; + + if (ctx == NULL) return; +#ifdef DEBUG_SAX + xmlGenericError(xmlGenericErrorContext, + "SAX.xmlSAX2Characters(%.30s, %d)\n", ch, len); +#endif + /* + * Handle the data if any. If there is no child + * add it as content, otherwise if the last child is text, + * concatenate it, else create a new node of type text. + */ + + if (ctxt->node == NULL) { +#ifdef DEBUG_SAX_TREE + xmlGenericError(xmlGenericErrorContext, + "add chars: ctxt->node == NULL !\n"); +#endif + return; + } + lastChild = ctxt->node->last; +#ifdef DEBUG_SAX_TREE + xmlGenericError(xmlGenericErrorContext, + "add chars to %s \n", ctxt->node->name); +#endif + + /* + * Here we needed an accelerator mechanism in case of very large + * elements. Use an attribute in the structure !!! + */ + if (lastChild == NULL) { + lastChild = xmlSAX2TextNode(ctxt, ch, len); + if (lastChild != NULL) { + ctxt->node->children = lastChild; + ctxt->node->last = lastChild; + lastChild->parent = ctxt->node; + lastChild->doc = ctxt->node->doc; + ctxt->nodelen = len; + ctxt->nodemem = len + 1; + } else { + xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters"); + return; + } + } else { + int coalesceText = (lastChild != NULL) && + (lastChild->type == XML_TEXT_NODE) && + (lastChild->name == xmlStringText); + if ((coalesceText) && (ctxt->nodemem != 0)) { + /* + * The whole point of maintaining nodelen and nodemem, + * xmlTextConcat is too costly, i.e. compute length, + * reallocate a new buffer, move data, append ch. Here + * We try to minimaze realloc() uses and avoid copying + * and recomputing length over and over. + */ + if (lastChild->content == (xmlChar *)&(lastChild->properties)) { + lastChild->content = xmlStrdup(lastChild->content); + lastChild->properties = NULL; + } else if ((ctxt->nodemem == ctxt->nodelen + 1) && + (xmlDictOwns(ctxt->dict, lastChild->content))) { + lastChild->content = xmlStrdup(lastChild->content); + } + if (ctxt->nodelen + len >= ctxt->nodemem) { + xmlChar *newbuf; + int size; + + size = ctxt->nodemem + len; + size *= 2; + newbuf = (xmlChar *) xmlRealloc(lastChild->content,size); + if (newbuf == NULL) { + xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters"); + return; + } + ctxt->nodemem = size; + lastChild->content = newbuf; + } + memcpy(&lastChild->content[ctxt->nodelen], ch, len); + ctxt->nodelen += len; + lastChild->content[ctxt->nodelen] = 0; + } else if (coalesceText) { + if (xmlTextConcat(lastChild, ch, len)) { + xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters"); + } + if (ctxt->node->children != NULL) { + ctxt->nodelen = xmlStrlen(lastChild->content); + ctxt->nodemem = ctxt->nodelen + 1; + } + } else { + /* Mixed content, first time */ + lastChild = xmlSAX2TextNode(ctxt, ch, len); + if (lastChild != NULL) { + xmlAddChild(ctxt->node, lastChild); + if (ctxt->node->children != NULL) { + ctxt->nodelen = len; + ctxt->nodemem = len + 1; + } + } + } + } +} + +/** + * xmlSAX2IgnorableWhitespace: + * @ctx: the user data (XML parser context) + * @ch: a xmlChar string + * @len: the number of xmlChar + * + * receiving some ignorable whitespaces from the parser. + * UNUSED: by default the DOM building will use xmlSAX2Characters + */ +void +xmlSAX2IgnorableWhitespace(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch ATTRIBUTE_UNUSED, int len ATTRIBUTE_UNUSED) +{ + /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */ +#ifdef DEBUG_SAX + xmlGenericError(xmlGenericErrorContext, + "SAX.xmlSAX2IgnorableWhitespace(%.30s, %d)\n", ch, len); +#endif +} + +/** + * xmlSAX2ProcessingInstruction: + * @ctx: the user data (XML parser context) + * @target: the target name + * @data: the PI data's + * + * A processing instruction has been parsed. + */ +void +xmlSAX2ProcessingInstruction(void *ctx, const xmlChar *target, + const xmlChar *data) +{ + xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; + xmlNodePtr ret; + xmlNodePtr parent; + + if (ctx == NULL) return; + parent = ctxt->node; +#ifdef DEBUG_SAX + xmlGenericError(xmlGenericErrorContext, + "SAX.xmlSAX2ProcessingInstruction(%s, %s)\n", target, data); +#endif + + ret = xmlNewDocPI(ctxt->myDoc, target, data); + if (ret == NULL) return; + parent = ctxt->node; + + if (ctxt->linenumbers) { + if (ctxt->input != NULL) { + if (ctxt->input->line < 65535) + ret->line = (short) ctxt->input->line; + else + ret->line = 65535; + } + } + if (ctxt->inSubset == 1) { + xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret); + return; + } else if (ctxt->inSubset == 2) { + xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret); + return; + } + if ((ctxt->myDoc->children == NULL) || (parent == NULL)) { +#ifdef DEBUG_SAX_TREE + xmlGenericError(xmlGenericErrorContext, + "Setting PI %s as root\n", target); +#endif + xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret); + return; + } + if (parent->type == XML_ELEMENT_NODE) { +#ifdef DEBUG_SAX_TREE + xmlGenericError(xmlGenericErrorContext, + "adding PI %s child to %s\n", target, parent->name); +#endif + xmlAddChild(parent, ret); + } else { +#ifdef DEBUG_SAX_TREE + xmlGenericError(xmlGenericErrorContext, + "adding PI %s sibling to ", target); + xmlDebugDumpOneNode(stderr, parent, 0); +#endif + xmlAddSibling(parent, ret); + } +} + +/** + * xmlSAX2Comment: + * @ctx: the user data (XML parser context) + * @value: the xmlSAX2Comment content + * + * A xmlSAX2Comment has been parsed. + */ +void +xmlSAX2Comment(void *ctx, const xmlChar *value) +{ + xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; + xmlNodePtr ret; + xmlNodePtr parent; + + if (ctx == NULL) return; + parent = ctxt->node; +#ifdef DEBUG_SAX + xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2Comment(%s)\n", value); +#endif + ret = xmlNewDocComment(ctxt->myDoc, value); + if (ret == NULL) return; + if (ctxt->linenumbers) { + if (ctxt->input != NULL) { + if (ctxt->input->line < 65535) + ret->line = (short) ctxt->input->line; + else + ret->line = 65535; + } + } + + if (ctxt->inSubset == 1) { + xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret); + return; + } else if (ctxt->inSubset == 2) { + xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret); + return; + } + if ((ctxt->myDoc->children == NULL) || (parent == NULL)) { +#ifdef DEBUG_SAX_TREE + xmlGenericError(xmlGenericErrorContext, + "Setting xmlSAX2Comment as root\n"); +#endif + xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret); + return; + } + if (parent->type == XML_ELEMENT_NODE) { +#ifdef DEBUG_SAX_TREE + xmlGenericError(xmlGenericErrorContext, + "adding xmlSAX2Comment child to %s\n", parent->name); +#endif + xmlAddChild(parent, ret); + } else { +#ifdef DEBUG_SAX_TREE + xmlGenericError(xmlGenericErrorContext, + "adding xmlSAX2Comment sibling to "); + xmlDebugDumpOneNode(stderr, parent, 0); +#endif + xmlAddSibling(parent, ret); + } +} + +/** + * xmlSAX2CDataBlock: + * @ctx: the user data (XML parser context) + * @value: The pcdata content + * @len: the block length + * + * called when a pcdata block has been parsed + */ +void +xmlSAX2CDataBlock(void *ctx, const xmlChar *value, int len) +{ + xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; + xmlNodePtr ret, lastChild; + + if (ctx == NULL) return; +#ifdef DEBUG_SAX + xmlGenericError(xmlGenericErrorContext, + "SAX.pcdata(%.10s, %d)\n", value, len); +#endif + lastChild = xmlGetLastChild(ctxt->node); +#ifdef DEBUG_SAX_TREE + xmlGenericError(xmlGenericErrorContext, + "add chars to %s \n", ctxt->node->name); +#endif + if ((lastChild != NULL) && + (lastChild->type == XML_CDATA_SECTION_NODE)) { + xmlTextConcat(lastChild, value, len); + } else { + ret = xmlNewCDataBlock(ctxt->myDoc, value, len); + xmlAddChild(ctxt->node, ret); + } +} + +static int xmlSAX2DefaultVersionValue = 2; + +#ifdef LIBXML_SAX1_ENABLED +/** + * xmlSAXDefaultVersion: + * @version: the version, 1 or 2 + * + * Set the default version of SAX used globally by the library. + * By default, during initialization the default is set to 2. + * Note that it is generally a better coding style to use + * xmlSAXVersion() to set up the version explicitly for a given + * parsing context. + * + * Returns the previous value in case of success and -1 in case of error. + */ +int +xmlSAXDefaultVersion(int version) +{ + int ret = xmlSAX2DefaultVersionValue; + + if ((version != 1) && (version != 2)) + return(-1); + xmlSAX2DefaultVersionValue = version; + return(ret); +} +#endif /* LIBXML_SAX1_ENABLED */ + +/** + * xmlSAXVersion: + * @hdlr: the SAX handler + * @version: the version, 1 or 2 + * + * Initialize the default XML SAX handler according to the version + * + * Returns 0 in case of success and -1 in case of error. + */ +int +xmlSAXVersion(xmlSAXHandler *hdlr, int version) +{ + if (hdlr == NULL) return(-1); + if (version == 2) { + hdlr->startElement = NULL; + hdlr->endElement = NULL; + hdlr->startElementNs = xmlSAX2StartElementNs; + hdlr->endElementNs = xmlSAX2EndElementNs; + hdlr->serror = NULL; + hdlr->initialized = XML_SAX2_MAGIC; +#ifdef LIBXML_SAX1_ENABLED + } else if (version == 1) { + hdlr->startElement = xmlSAX2StartElement; + hdlr->endElement = xmlSAX2EndElement; + hdlr->initialized = 1; +#endif /* LIBXML_SAX1_ENABLED */ + } else + return(-1); + hdlr->internalSubset = xmlSAX2InternalSubset; + hdlr->externalSubset = xmlSAX2ExternalSubset; + hdlr->isStandalone = xmlSAX2IsStandalone; + hdlr->hasInternalSubset = xmlSAX2HasInternalSubset; + hdlr->hasExternalSubset = xmlSAX2HasExternalSubset; + hdlr->resolveEntity = xmlSAX2ResolveEntity; + hdlr->getEntity = xmlSAX2GetEntity; + hdlr->getParameterEntity = xmlSAX2GetParameterEntity; + hdlr->entityDecl = xmlSAX2EntityDecl; + hdlr->attributeDecl = xmlSAX2AttributeDecl; + hdlr->elementDecl = xmlSAX2ElementDecl; + hdlr->notationDecl = xmlSAX2NotationDecl; + hdlr->unparsedEntityDecl = xmlSAX2UnparsedEntityDecl; + hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator; + hdlr->startDocument = xmlSAX2StartDocument; + hdlr->endDocument = xmlSAX2EndDocument; + hdlr->reference = xmlSAX2Reference; + hdlr->characters = xmlSAX2Characters; + hdlr->cdataBlock = xmlSAX2CDataBlock; + hdlr->ignorableWhitespace = xmlSAX2Characters; + hdlr->processingInstruction = xmlSAX2ProcessingInstruction; + hdlr->comment = xmlSAX2Comment; + hdlr->warning = xmlParserWarning; + hdlr->error = xmlParserError; + hdlr->fatalError = xmlParserError; + + return(0); +} + +/** + * xmlSAX2InitDefaultSAXHandler: + * @hdlr: the SAX handler + * @warning: flag if non-zero sets the handler warning procedure + * + * Initialize the default XML SAX2 handler + */ +void +xmlSAX2InitDefaultSAXHandler(xmlSAXHandler *hdlr, int warning) +{ + if ((hdlr == NULL) || (hdlr->initialized != 0)) + return; + + xmlSAXVersion(hdlr, xmlSAX2DefaultVersionValue); + if (warning == 0) + hdlr->warning = NULL; + else + hdlr->warning = xmlParserWarning; +} + +/** + * xmlDefaultSAXHandlerInit: + * + * Initialize the default SAX2 handler + */ +void +xmlDefaultSAXHandlerInit(void) +{ +#ifdef LIBXML_SAX1_ENABLED + xmlSAXVersion((xmlSAXHandlerPtr) &xmlDefaultSAXHandler, 1); +#endif /* LIBXML_SAX1_ENABLED */ +} + +#ifdef LIBXML_HTML_ENABLED + +/** + * xmlSAX2InitHtmlDefaultSAXHandler: + * @hdlr: the SAX handler + * + * Initialize the default HTML SAX2 handler + */ +void +xmlSAX2InitHtmlDefaultSAXHandler(xmlSAXHandler *hdlr) +{ + if ((hdlr == NULL) || (hdlr->initialized != 0)) + return; + + hdlr->internalSubset = xmlSAX2InternalSubset; + hdlr->externalSubset = NULL; + hdlr->isStandalone = NULL; + hdlr->hasInternalSubset = NULL; + hdlr->hasExternalSubset = NULL; + hdlr->resolveEntity = NULL; + hdlr->getEntity = xmlSAX2GetEntity; + hdlr->getParameterEntity = NULL; + hdlr->entityDecl = NULL; + hdlr->attributeDecl = NULL; + hdlr->elementDecl = NULL; + hdlr->notationDecl = NULL; + hdlr->unparsedEntityDecl = NULL; + hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator; + hdlr->startDocument = xmlSAX2StartDocument; + hdlr->endDocument = xmlSAX2EndDocument; + hdlr->startElement = xmlSAX2StartElement; + hdlr->endElement = xmlSAX2EndElement; + hdlr->reference = NULL; + hdlr->characters = xmlSAX2Characters; + hdlr->cdataBlock = xmlSAX2CDataBlock; + hdlr->ignorableWhitespace = xmlSAX2IgnorableWhitespace; + hdlr->processingInstruction = xmlSAX2ProcessingInstruction; + hdlr->comment = xmlSAX2Comment; + hdlr->warning = xmlParserWarning; + hdlr->error = xmlParserError; + hdlr->fatalError = xmlParserError; + + hdlr->initialized = 1; +} + +/** + * htmlDefaultSAXHandlerInit: + * + * Initialize the default SAX handler + */ +void +htmlDefaultSAXHandlerInit(void) +{ + xmlSAX2InitHtmlDefaultSAXHandler((xmlSAXHandlerPtr) &htmlDefaultSAXHandler); +} + +#endif /* LIBXML_HTML_ENABLED */ + +#ifdef LIBXML_DOCB_ENABLED + +/** + * xmlSAX2InitDocbDefaultSAXHandler: + * @hdlr: the SAX handler + * + * Initialize the default DocBook SAX2 handler + */ +void +xmlSAX2InitDocbDefaultSAXHandler(xmlSAXHandler *hdlr) +{ + if ((hdlr == NULL) || (hdlr->initialized != 0)) + return; + + hdlr->internalSubset = xmlSAX2InternalSubset; + hdlr->externalSubset = NULL; + hdlr->isStandalone = xmlSAX2IsStandalone; + hdlr->hasInternalSubset = xmlSAX2HasInternalSubset; + hdlr->hasExternalSubset = xmlSAX2HasExternalSubset; + hdlr->resolveEntity = xmlSAX2ResolveEntity; + hdlr->getEntity = xmlSAX2GetEntity; + hdlr->getParameterEntity = NULL; + hdlr->entityDecl = xmlSAX2EntityDecl; + hdlr->attributeDecl = NULL; + hdlr->elementDecl = NULL; + hdlr->notationDecl = NULL; + hdlr->unparsedEntityDecl = NULL; + hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator; + hdlr->startDocument = xmlSAX2StartDocument; + hdlr->endDocument = xmlSAX2EndDocument; + hdlr->startElement = xmlSAX2StartElement; + hdlr->endElement = xmlSAX2EndElement; + hdlr->reference = xmlSAX2Reference; + hdlr->characters = xmlSAX2Characters; + hdlr->cdataBlock = NULL; + hdlr->ignorableWhitespace = xmlSAX2IgnorableWhitespace; + hdlr->processingInstruction = NULL; + hdlr->comment = xmlSAX2Comment; + hdlr->warning = xmlParserWarning; + hdlr->error = xmlParserError; + hdlr->fatalError = xmlParserError; + + hdlr->initialized = 1; +} + +/** + * docbDefaultSAXHandlerInit: + * + * Initialize the default SAX handler + */ +void +docbDefaultSAXHandlerInit(void) +{ + xmlSAX2InitDocbDefaultSAXHandler((xmlSAXHandlerPtr) &docbDefaultSAXHandler); +} + +#endif /* LIBXML_DOCB_ENABLED */ +#define bottom_SAX2 +#include "elfgcchack.h" diff --git a/gettext-tools/gnulib-lib/libxml/SAX2.in.h b/gettext-tools/gnulib-lib/libxml/SAX2.in.h new file mode 100644 index 0000000..8d2db02 --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/SAX2.in.h @@ -0,0 +1,176 @@ +/* + * Summary: SAX2 parser interface used to build the DOM tree + * Description: those are the default SAX2 interfaces used by + * the library when building DOM tree. + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + + +#ifndef __XML_SAX2_H__ +#define __XML_SAX2_H__ + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif +XMLPUBFUN const xmlChar * XMLCALL + xmlSAX2GetPublicId (void *ctx); +XMLPUBFUN const xmlChar * XMLCALL + xmlSAX2GetSystemId (void *ctx); +XMLPUBFUN void XMLCALL + xmlSAX2SetDocumentLocator (void *ctx, + xmlSAXLocatorPtr loc); + +XMLPUBFUN int XMLCALL + xmlSAX2GetLineNumber (void *ctx); +XMLPUBFUN int XMLCALL + xmlSAX2GetColumnNumber (void *ctx); + +XMLPUBFUN int XMLCALL + xmlSAX2IsStandalone (void *ctx); +XMLPUBFUN int XMLCALL + xmlSAX2HasInternalSubset (void *ctx); +XMLPUBFUN int XMLCALL + xmlSAX2HasExternalSubset (void *ctx); + +XMLPUBFUN void XMLCALL + xmlSAX2InternalSubset (void *ctx, + const xmlChar *name, + const xmlChar *ExternalID, + const xmlChar *SystemID); +XMLPUBFUN void XMLCALL + xmlSAX2ExternalSubset (void *ctx, + const xmlChar *name, + const xmlChar *ExternalID, + const xmlChar *SystemID); +XMLPUBFUN xmlEntityPtr XMLCALL + xmlSAX2GetEntity (void *ctx, + const xmlChar *name); +XMLPUBFUN xmlEntityPtr XMLCALL + xmlSAX2GetParameterEntity (void *ctx, + const xmlChar *name); +XMLPUBFUN xmlParserInputPtr XMLCALL + xmlSAX2ResolveEntity (void *ctx, + const xmlChar *publicId, + const xmlChar *systemId); + +XMLPUBFUN void XMLCALL + xmlSAX2EntityDecl (void *ctx, + const xmlChar *name, + int type, + const xmlChar *publicId, + const xmlChar *systemId, + xmlChar *content); +XMLPUBFUN void XMLCALL + xmlSAX2AttributeDecl (void *ctx, + const xmlChar *elem, + const xmlChar *fullname, + int type, + int def, + const xmlChar *defaultValue, + xmlEnumerationPtr tree); +XMLPUBFUN void XMLCALL + xmlSAX2ElementDecl (void *ctx, + const xmlChar *name, + int type, + xmlElementContentPtr content); +XMLPUBFUN void XMLCALL + xmlSAX2NotationDecl (void *ctx, + const xmlChar *name, + const xmlChar *publicId, + const xmlChar *systemId); +XMLPUBFUN void XMLCALL + xmlSAX2UnparsedEntityDecl (void *ctx, + const xmlChar *name, + const xmlChar *publicId, + const xmlChar *systemId, + const xmlChar *notationName); + +XMLPUBFUN void XMLCALL + xmlSAX2StartDocument (void *ctx); +XMLPUBFUN void XMLCALL + xmlSAX2EndDocument (void *ctx); +#if defined(LIBXML_SAX1_ENABLED) || defined(LIBXML_HTML_ENABLED) || defined(LIBXML_WRITER_ENABLED) || defined(LIBXML_DOCB_ENABLED) +XMLPUBFUN void XMLCALL + xmlSAX2StartElement (void *ctx, + const xmlChar *fullname, + const xmlChar **atts); +XMLPUBFUN void XMLCALL + xmlSAX2EndElement (void *ctx, + const xmlChar *name); +#endif /* LIBXML_SAX1_ENABLED or LIBXML_HTML_ENABLED */ +XMLPUBFUN void XMLCALL + xmlSAX2StartElementNs (void *ctx, + const xmlChar *localname, + const xmlChar *prefix, + const xmlChar *URI, + int nb_namespaces, + const xmlChar **namespaces, + int nb_attributes, + int nb_defaulted, + const xmlChar **attributes); +XMLPUBFUN void XMLCALL + xmlSAX2EndElementNs (void *ctx, + const xmlChar *localname, + const xmlChar *prefix, + const xmlChar *URI); +XMLPUBFUN void XMLCALL + xmlSAX2Reference (void *ctx, + const xmlChar *name); +XMLPUBFUN void XMLCALL + xmlSAX2Characters (void *ctx, + const xmlChar *ch, + int len); +XMLPUBFUN void XMLCALL + xmlSAX2IgnorableWhitespace (void *ctx, + const xmlChar *ch, + int len); +XMLPUBFUN void XMLCALL + xmlSAX2ProcessingInstruction (void *ctx, + const xmlChar *target, + const xmlChar *data); +XMLPUBFUN void XMLCALL + xmlSAX2Comment (void *ctx, + const xmlChar *value); +XMLPUBFUN void XMLCALL + xmlSAX2CDataBlock (void *ctx, + const xmlChar *value, + int len); + +#ifdef LIBXML_SAX1_ENABLED +XMLPUBFUN int XMLCALL + xmlSAXDefaultVersion (int version); +#endif /* LIBXML_SAX1_ENABLED */ + +XMLPUBFUN int XMLCALL + xmlSAXVersion (xmlSAXHandler *hdlr, + int version); +XMLPUBFUN void XMLCALL + xmlSAX2InitDefaultSAXHandler (xmlSAXHandler *hdlr, + int warning); +#ifdef LIBXML_HTML_ENABLED +XMLPUBFUN void XMLCALL + xmlSAX2InitHtmlDefaultSAXHandler(xmlSAXHandler *hdlr); +XMLPUBFUN void XMLCALL + htmlDefaultSAXHandlerInit (void); +#endif +#ifdef LIBXML_DOCB_ENABLED +XMLPUBFUN void XMLCALL + xmlSAX2InitDocbDefaultSAXHandler(xmlSAXHandler *hdlr); +XMLPUBFUN void XMLCALL + docbDefaultSAXHandlerInit (void); +#endif +XMLPUBFUN void XMLCALL + xmlDefaultSAXHandlerInit (void); +#ifdef __cplusplus +} +#endif +#endif /* __XML_SAX2_H__ */ diff --git a/gettext-tools/gnulib-lib/libxml/c14n.c b/gettext-tools/gnulib-lib/libxml/c14n.c new file mode 100644 index 0000000..bb7c9ba --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/c14n.c @@ -0,0 +1,1928 @@ +/* + * "Canonical XML" implementation + * http://www.w3.org/TR/xml-c14n + * + * "Exclusive XML Canonicalization" implementation + * http://www.w3.org/TR/xml-exc-c14n + * + * See Copyright for the status of this software. + * + * Author: Aleksey Sanin + */ +#define IN_LIBXML +#include "libxml.h" +#ifdef LIBXML_C14N_ENABLED +#ifdef LIBXML_OUTPUT_ENABLED + +#ifdef HAVE_STDLIB_H +#include +#endif +#include + +#include +#include +#include +#include +#include +#include +#include + +/************************************************************************ + * * + * Some declaration better left private ATM * + * * + ************************************************************************/ + +typedef enum { + XMLC14N_BEFORE_DOCUMENT_ELEMENT = 0, + XMLC14N_INSIDE_DOCUMENT_ELEMENT = 1, + XMLC14N_AFTER_DOCUMENT_ELEMENT = 2 +} xmlC14NPosition; + +typedef struct _xmlC14NVisibleNsStack { + int nsCurEnd; /* number of nodes in the set */ + int nsPrevStart; /* the begginning of the stack for previous visible node */ + int nsPrevEnd; /* the end of the stack for previous visible node */ + int nsMax; /* size of the array as allocated */ + xmlNsPtr *nsTab; /* array of ns in no particular order */ + xmlNodePtr *nodeTab; /* array of nodes in no particular order */ +} xmlC14NVisibleNsStack, *xmlC14NVisibleNsStackPtr; + +typedef struct _xmlC14NCtx { + /* input parameters */ + xmlDocPtr doc; + xmlC14NIsVisibleCallback is_visible_callback; + void* user_data; + int with_comments; + xmlOutputBufferPtr buf; + + /* position in the XML document */ + xmlC14NPosition pos; + int parent_is_doc; + xmlC14NVisibleNsStackPtr ns_rendered; + + /* exclusive canonicalization */ + int exclusive; + xmlChar **inclusive_ns_prefixes; + + /* error number */ + int error; +} xmlC14NCtx, *xmlC14NCtxPtr; + +static xmlC14NVisibleNsStackPtr xmlC14NVisibleNsStackCreate (void); +static void xmlC14NVisibleNsStackDestroy (xmlC14NVisibleNsStackPtr cur); +static void xmlC14NVisibleNsStackAdd (xmlC14NVisibleNsStackPtr cur, + xmlNsPtr ns, + xmlNodePtr node); +static void xmlC14NVisibleNsStackSave (xmlC14NVisibleNsStackPtr cur, + xmlC14NVisibleNsStackPtr state); +static void xmlC14NVisibleNsStackRestore (xmlC14NVisibleNsStackPtr cur, + xmlC14NVisibleNsStackPtr state); +static void xmlC14NVisibleNsStackShift (xmlC14NVisibleNsStackPtr cur); +static int xmlC14NVisibleNsStackFind (xmlC14NVisibleNsStackPtr cur, + xmlNsPtr ns); +static int xmlExcC14NVisibleNsStackFind (xmlC14NVisibleNsStackPtr cur, + xmlNsPtr ns, + xmlC14NCtxPtr ctx); + +static int xmlC14NIsNodeInNodeset (xmlNodeSetPtr nodes, + xmlNodePtr node, + xmlNodePtr parent); + + + +static int xmlC14NProcessNode(xmlC14NCtxPtr ctx, xmlNodePtr cur); +static int xmlC14NProcessNodeList(xmlC14NCtxPtr ctx, xmlNodePtr cur); +typedef enum { + XMLC14N_NORMALIZE_ATTR = 0, + XMLC14N_NORMALIZE_COMMENT = 1, + XMLC14N_NORMALIZE_PI = 2, + XMLC14N_NORMALIZE_TEXT = 3 +} xmlC14NNormalizationMode; + +static xmlChar *xmlC11NNormalizeString(const xmlChar * input, + xmlC14NNormalizationMode mode); + +#define xmlC11NNormalizeAttr( a ) \ + xmlC11NNormalizeString((a), XMLC14N_NORMALIZE_ATTR) +#define xmlC11NNormalizeComment( a ) \ + xmlC11NNormalizeString((a), XMLC14N_NORMALIZE_COMMENT) +#define xmlC11NNormalizePI( a ) \ + xmlC11NNormalizeString((a), XMLC14N_NORMALIZE_PI) +#define xmlC11NNormalizeText( a ) \ + xmlC11NNormalizeString((a), XMLC14N_NORMALIZE_TEXT) + +#define xmlC14NIsVisible( ctx, node, parent ) \ + (((ctx)->is_visible_callback != NULL) ? \ + (ctx)->is_visible_callback((ctx)->user_data, \ + (xmlNodePtr)(node), (xmlNodePtr)(parent)) : 1) + +/************************************************************************ + * * + * Some factorized error routines * + * * + ************************************************************************/ + +/** + * xmlC14NErrMemory: + * @extra: extra informations + * + * Handle a redefinition of memory error + */ +static void +xmlC14NErrMemory(const char *extra) +{ + __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_C14N, + XML_ERR_NO_MEMORY, XML_ERR_ERROR, NULL, 0, extra, + NULL, NULL, 0, 0, + "Memory allocation failed : %s\n", extra); +} + +/** + * xmlC14NErrParam: + * @extra: extra informations + * + * Handle a redefinition of param error + */ +static void +xmlC14NErrParam(const char *extra) +{ + __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_C14N, + XML_ERR_INTERNAL_ERROR, XML_ERR_ERROR, NULL, 0, extra, + NULL, NULL, 0, 0, + "Invalid parameter : %s\n", extra); +} + +/** + * xmlC14NErrInternal: + * @extra: extra informations + * + * Handle a redefinition of internal error + */ +static void +xmlC14NErrInternal(const char *extra) +{ + __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_C14N, + XML_ERR_INTERNAL_ERROR, XML_ERR_ERROR, NULL, 0, extra, + NULL, NULL, 0, 0, + "Internal error : %s\n", extra); +} + +/** + * xmlC14NErrInvalidNode: + * @extra: extra informations + * + * Handle a redefinition of invalid node error + */ +static void +xmlC14NErrInvalidNode(const char *node_type, const char *extra) +{ + __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_C14N, + XML_C14N_INVALID_NODE, XML_ERR_ERROR, NULL, 0, extra, + NULL, NULL, 0, 0, + "Node %s is invalid here : %s\n", node_type, extra); +} + +/** + * xmlC14NErrUnknownNode: + * @extra: extra informations + * + * Handle a redefinition of unknown node error + */ +static void +xmlC14NErrUnknownNode(int node_type, const char *extra) +{ + __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_C14N, + XML_C14N_UNKNOW_NODE, XML_ERR_ERROR, NULL, 0, extra, + NULL, NULL, 0, 0, + "Unknown node type %d found : %s\n", node_type, extra); +} + +/** + * xmlC14NErrRelativeNamespace: + * @extra: extra informations + * + * Handle a redefinition of relative namespace error + */ +static void +xmlC14NErrRelativeNamespace(const char *ns_uri) +{ + __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_C14N, + XML_C14N_RELATIVE_NAMESPACE, XML_ERR_ERROR, NULL, 0, NULL, + NULL, NULL, 0, 0, + "Relative namespace UR is invalid here : %s\n", ns_uri); +} + + + +/** + * xmlC14NErr: + * @ctxt: a C14N evaluation context + * @node: the context node + * @error: the erorr code + * @msg: the message + * @extra: extra informations + * + * Handle a redefinition of attribute error + */ +static void +xmlC14NErr(xmlC14NCtxPtr ctxt, xmlNodePtr node, int error, + const char * msg) +{ + if (ctxt != NULL) + ctxt->error = error; + __xmlRaiseError(NULL, NULL, NULL, + ctxt, node, XML_FROM_C14N, error, + XML_ERR_ERROR, NULL, 0, + NULL, NULL, NULL, 0, 0, msg); +} + +/************************************************************************ + * * + * The implementation internals * + * * + ************************************************************************/ +#define XML_NAMESPACES_DEFAULT 16 + +static int +xmlC14NIsNodeInNodeset(xmlNodeSetPtr nodes, xmlNodePtr node, xmlNodePtr parent) { + if((nodes != NULL) && (node != NULL)) { + if(node->type != XML_NAMESPACE_DECL) { + return(xmlXPathNodeSetContains(nodes, node)); + } else { + xmlNs ns; + + memcpy(&ns, node, sizeof(ns)); + + /* this is a libxml hack! check xpath.c for details */ + if((parent != NULL) && (parent->type == XML_ATTRIBUTE_NODE)) { + ns.next = (xmlNsPtr)parent->parent; + } else { + ns.next = (xmlNsPtr)parent; + } + + /* + * If the input is an XPath node-set, then the node-set must explicitly + * contain every node to be rendered to the canonical form. + */ + return(xmlXPathNodeSetContains(nodes, (xmlNodePtr)&ns)); + } + } + return(1); +} + +static xmlC14NVisibleNsStackPtr +xmlC14NVisibleNsStackCreate(void) { + xmlC14NVisibleNsStackPtr ret; + + ret = (xmlC14NVisibleNsStackPtr) xmlMalloc(sizeof(xmlC14NVisibleNsStack)); + if (ret == NULL) { + xmlC14NErrMemory("creating namespaces stack"); + return(NULL); + } + memset(ret, 0 , (size_t) sizeof(xmlC14NVisibleNsStack)); + return(ret); +} + +static void +xmlC14NVisibleNsStackDestroy(xmlC14NVisibleNsStackPtr cur) { + if(cur == NULL) { + xmlC14NErrParam("destroying namespaces stack"); + return; + } + if(cur->nsTab != NULL) { + memset(cur->nsTab, 0, cur->nsMax * sizeof(xmlNsPtr)); + xmlFree(cur->nsTab); + } + if(cur->nodeTab != NULL) { + memset(cur->nodeTab, 0, cur->nsMax * sizeof(xmlNodePtr)); + xmlFree(cur->nodeTab); + } + memset(cur, 0, sizeof(xmlC14NVisibleNsStack)); + xmlFree(cur); + +} + +static void +xmlC14NVisibleNsStackAdd(xmlC14NVisibleNsStackPtr cur, xmlNsPtr ns, xmlNodePtr node) { + if((cur == NULL) || + ((cur->nsTab == NULL) && (cur->nodeTab != NULL)) || + ((cur->nsTab != NULL) && (cur->nodeTab == NULL))) { + xmlC14NErrParam("adding namespace to stack"); + return; + } + + if ((cur->nsTab == NULL) && (cur->nodeTab == NULL)) { + cur->nsTab = (xmlNsPtr*) xmlMalloc(XML_NAMESPACES_DEFAULT * sizeof(xmlNsPtr)); + cur->nodeTab = (xmlNodePtr*) xmlMalloc(XML_NAMESPACES_DEFAULT * sizeof(xmlNodePtr)); + if ((cur->nsTab == NULL) || (cur->nodeTab == NULL)) { + xmlC14NErrMemory("adding node to stack"); + return; + } + memset(cur->nsTab, 0 , XML_NAMESPACES_DEFAULT * sizeof(xmlNsPtr)); + memset(cur->nodeTab, 0 , XML_NAMESPACES_DEFAULT * sizeof(xmlNodePtr)); + cur->nsMax = XML_NAMESPACES_DEFAULT; + } else if(cur->nsMax == cur->nsCurEnd) { + void *tmp; + int tmpSize; + + tmpSize = 2 * cur->nsMax; + tmp = xmlRealloc(cur->nsTab, tmpSize * sizeof(xmlNsPtr)); + if (tmp == NULL) { + xmlC14NErrMemory("adding node to stack"); + return; + } + cur->nsTab = (xmlNsPtr*)tmp; + + tmp = xmlRealloc(cur->nodeTab, tmpSize * sizeof(xmlNodePtr)); + if (tmp == NULL) { + xmlC14NErrMemory("adding node to stack"); + return; + } + cur->nodeTab = (xmlNodePtr*)tmp; + + cur->nsMax = tmpSize; + } + cur->nsTab[cur->nsCurEnd] = ns; + cur->nodeTab[cur->nsCurEnd] = node; + + ++cur->nsCurEnd; +} + +static void +xmlC14NVisibleNsStackSave(xmlC14NVisibleNsStackPtr cur, xmlC14NVisibleNsStackPtr state) { + if((cur == NULL) || (state == NULL)) { + xmlC14NErrParam("saving namespaces stack"); + return; + } + + state->nsCurEnd = cur->nsCurEnd; + state->nsPrevStart = cur->nsPrevStart; + state->nsPrevEnd = cur->nsPrevEnd; +} + +static void +xmlC14NVisibleNsStackRestore(xmlC14NVisibleNsStackPtr cur, xmlC14NVisibleNsStackPtr state) { + if((cur == NULL) || (state == NULL)) { + xmlC14NErrParam("restoring namespaces stack"); + return; + } + cur->nsCurEnd = state->nsCurEnd; + cur->nsPrevStart = state->nsPrevStart; + cur->nsPrevEnd = state->nsPrevEnd; +} + +static void +xmlC14NVisibleNsStackShift(xmlC14NVisibleNsStackPtr cur) { + if(cur == NULL) { + xmlC14NErrParam("shifting namespaces stack"); + return; + } + cur->nsPrevStart = cur->nsPrevEnd; + cur->nsPrevEnd = cur->nsCurEnd; +} + +static int +xmlC14NStrEqual(const xmlChar *str1, const xmlChar *str2) { + if (str1 == str2) return(1); + if (str1 == NULL) return((*str2) == '\0'); + if (str2 == NULL) return((*str1) == '\0'); + do { + if (*str1++ != *str2) return(0); + } while (*str2++); + return(1); +} + +/** + * xmlC14NVisibleNsStackFind: + * @ctx: the C14N context + * @ns: the namespace to check + * + * Checks whether the given namespace was already rendered or not + * + * Returns 1 if we already wrote this namespace or 0 otherwise + */ +static int +xmlC14NVisibleNsStackFind(xmlC14NVisibleNsStackPtr cur, xmlNsPtr ns) +{ + int i; + const xmlChar *prefix; + const xmlChar *href; + int has_empty_ns; + + if(cur == NULL) { + xmlC14NErrParam("searching namespaces stack (c14n)"); + return (0); + } + + /* + * if the default namespace xmlns="" is not defined yet then + * we do not want to print it out + */ + prefix = ((ns == NULL) || (ns->prefix == NULL)) ? BAD_CAST "" : ns->prefix; + href = ((ns == NULL) || (ns->href == NULL)) ? BAD_CAST "" : ns->href; + has_empty_ns = (xmlC14NStrEqual(prefix, NULL) && xmlC14NStrEqual(href, NULL)); + + if (cur->nsTab != NULL) { + int start = (has_empty_ns) ? 0 : cur->nsPrevStart; + for (i = cur->nsCurEnd - 1; i >= start; --i) { + xmlNsPtr ns1 = cur->nsTab[i]; + + if(xmlC14NStrEqual(prefix, (ns1 != NULL) ? ns1->prefix : NULL)) { + return(xmlC14NStrEqual(href, (ns1 != NULL) ? ns1->href : NULL)); + } + } + } + return(has_empty_ns); +} + +static int +xmlExcC14NVisibleNsStackFind(xmlC14NVisibleNsStackPtr cur, xmlNsPtr ns, xmlC14NCtxPtr ctx) { + int i; + const xmlChar *prefix; + const xmlChar *href; + int has_empty_ns; + + if(cur == NULL) { + xmlC14NErrParam("searching namespaces stack (exc c14n)"); + return (0); + } + + /* + * if the default namespace xmlns="" is not defined yet then + * we do not want to print it out + */ + prefix = ((ns == NULL) || (ns->prefix == NULL)) ? BAD_CAST "" : ns->prefix; + href = ((ns == NULL) || (ns->href == NULL)) ? BAD_CAST "" : ns->href; + has_empty_ns = (xmlC14NStrEqual(prefix, NULL) && xmlC14NStrEqual(href, NULL)); + + if (cur->nsTab != NULL) { + int start = 0; + for (i = cur->nsCurEnd - 1; i >= start; --i) { + xmlNsPtr ns1 = cur->nsTab[i]; + + if(xmlC14NStrEqual(prefix, (ns1 != NULL) ? ns1->prefix : NULL)) { + if(xmlC14NStrEqual(href, (ns1 != NULL) ? ns1->href : NULL)) { + return(xmlC14NIsVisible(ctx, ns1, cur->nodeTab[i])); + } else { + return(0); + } + } + } + } + return(has_empty_ns); +} + + + + +/** + * xmlC14NIsXmlNs: + * @ns: the namespace to check + * + * Checks whether the given namespace is a default "xml:" namespace + * with href="http://www.w3.org/XML/1998/namespace" + * + * Returns 1 if the node is default or 0 otherwise + */ + +/* todo: make it a define? */ +static int +xmlC14NIsXmlNs(xmlNsPtr ns) +{ + return ((ns != NULL) && + (xmlStrEqual(ns->prefix, BAD_CAST "xml")) && + (xmlStrEqual(ns->href, + BAD_CAST + "http://www.w3.org/XML/1998/namespace"))); +} + + +/** + * xmlC14NNsCompare: + * @ns1: the pointer to first namespace + * @ns2: the pointer to second namespace + * + * Compares the namespaces by names (prefixes). + * + * Returns -1 if ns1 < ns2, 0 if ns1 == ns2 or 1 if ns1 > ns2. + */ +static int +xmlC14NNsCompare(xmlNsPtr ns1, xmlNsPtr ns2) +{ + if (ns1 == ns2) + return (0); + if (ns1 == NULL) + return (-1); + if (ns2 == NULL) + return (1); + + return (xmlStrcmp(ns1->prefix, ns2->prefix)); +} + + +/** + * xmlC14NPrintNamespaces: + * @ns: the pointer to namespace + * @ctx: the C14N context + * + * Prints the given namespace to the output buffer from C14N context. + * + * Returns 1 on success or 0 on fail. + */ +static int +xmlC14NPrintNamespaces(const xmlNsPtr ns, xmlC14NCtxPtr ctx) +{ + + if ((ns == NULL) || (ctx == NULL)) { + xmlC14NErrParam("writing namespaces"); + return 0; + } + + if (ns->prefix != NULL) { + xmlOutputBufferWriteString(ctx->buf, " xmlns:"); + xmlOutputBufferWriteString(ctx->buf, (const char *) ns->prefix); + xmlOutputBufferWriteString(ctx->buf, "=\""); + } else { + xmlOutputBufferWriteString(ctx->buf, " xmlns=\""); + } + if(ns->href != NULL) { + xmlOutputBufferWriteString(ctx->buf, (const char *) ns->href); + } + xmlOutputBufferWriteString(ctx->buf, "\""); + return (1); +} + +/** + * xmlC14NProcessNamespacesAxis: + * @ctx: the C14N context + * @node: the current node + * + * Prints out canonical namespace axis of the current node to the + * buffer from C14N context as follows + * + * Canonical XML v 1.0 (http://www.w3.org/TR/xml-c14n) + * + * Namespace Axis + * Consider a list L containing only namespace nodes in the + * axis and in the node-set in lexicographic order (ascending). To begin + * processing L, if the first node is not the default namespace node (a node + * with no namespace URI and no local name), then generate a space followed + * by xmlns="" if and only if the following conditions are met: + * - the element E that owns the axis is in the node-set + * - The nearest ancestor element of E in the node-set has a default + * namespace node in the node-set (default namespace nodes always + * have non-empty values in XPath) + * The latter condition eliminates unnecessary occurrences of xmlns="" in + * the canonical form since an element only receives an xmlns="" if its + * default namespace is empty and if it has an immediate parent in the + * canonical form that has a non-empty default namespace. To finish + * processing L, simply process every namespace node in L, except omit + * namespace node with local name xml, which defines the xml prefix, + * if its string value is http://www.w3.org/XML/1998/namespace. + * + * Exclusive XML Canonicalization v 1.0 (http://www.w3.org/TR/xml-exc-c14n) + * Canonical XML applied to a document subset requires the search of the + * ancestor nodes of each orphan element node for attributes in the xml + * namespace, such as xml:lang and xml:space. These are copied into the + * element node except if a declaration of the same attribute is already + * in the attribute axis of the element (whether or not it is included in + * the document subset). This search and copying are omitted from the + * Exclusive XML Canonicalization method. + * + * Returns 0 on success or -1 on fail. + */ +static int +xmlC14NProcessNamespacesAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur, int visible) +{ + xmlNodePtr n; + xmlNsPtr ns, tmp; + xmlListPtr list; + int already_rendered; + int has_empty_ns = 0; + + if ((ctx == NULL) || (cur == NULL) || (cur->type != XML_ELEMENT_NODE)) { + xmlC14NErrParam("processing namespaces axis (c14n)"); + return (-1); + } + + /* + * Create a sorted list to store element namespaces + */ + list = xmlListCreate(NULL, (xmlListDataCompare) xmlC14NNsCompare); + if (list == NULL) { + xmlC14NErrInternal("creating namespaces list (c14n)"); + return (-1); + } + + /* check all namespaces */ + for(n = cur; n != NULL; n = n->parent) { + for(ns = n->nsDef; ns != NULL; ns = ns->next) { + tmp = xmlSearchNs(cur->doc, cur, ns->prefix); + + if((tmp == ns) && !xmlC14NIsXmlNs(ns) && xmlC14NIsVisible(ctx, ns, cur)) { + already_rendered = xmlC14NVisibleNsStackFind(ctx->ns_rendered, ns); + if(visible) { + xmlC14NVisibleNsStackAdd(ctx->ns_rendered, ns, cur); + } + if(!already_rendered) { + xmlListInsert(list, ns); + } + if(xmlStrlen(ns->prefix) == 0) { + has_empty_ns = 1; + } + } + } + } + + /** + * if the first node is not the default namespace node (a node with no + * namespace URI and no local name), then generate a space followed by + * xmlns="" if and only if the following conditions are met: + * - the element E that owns the axis is in the node-set + * - the nearest ancestor element of E in the node-set has a default + * namespace node in the node-set (default namespace nodes always + * have non-empty values in XPath) + */ + if(visible && !has_empty_ns) { + static xmlNs ns_default; + + memset(&ns_default, 0, sizeof(ns_default)); + if(!xmlC14NVisibleNsStackFind(ctx->ns_rendered, &ns_default)) { + xmlC14NPrintNamespaces(&ns_default, ctx); + } + } + + + /* + * print out all elements from list + */ + xmlListWalk(list, (xmlListWalker) xmlC14NPrintNamespaces, (const void *) ctx); + + /* + * Cleanup + */ + xmlListDelete(list); + return (0); +} + + +/** + * xmlExcC14NProcessNamespacesAxis: + * @ctx: the C14N context + * @node: the current node + * + * Prints out exclusive canonical namespace axis of the current node to the + * buffer from C14N context as follows + * + * Exclusive XML Canonicalization + * http://www.w3.org/TR/xml-exc-c14n + * + * If the element node is in the XPath subset then output the node in + * accordance with Canonical XML except for namespace nodes which are + * rendered as follows: + * + * 1. Render each namespace node iff: + * * it is visibly utilized by the immediate parent element or one of + * its attributes, or is present in InclusiveNamespaces PrefixList, and + * * its prefix and value do not appear in ns_rendered. ns_rendered is + * obtained by popping the state stack in order to obtain a list of + * prefixes and their values which have already been rendered by + * an output ancestor of the namespace node's parent element. + * 2. Append the rendered namespace node to the list ns_rendered of namespace + * nodes rendered by output ancestors. Push ns_rendered on state stack and + * recurse. + * 3. After the recursion returns, pop thestate stack. + * + * + * Returns 0 on success or -1 on fail. + */ +static int +xmlExcC14NProcessNamespacesAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur, int visible) +{ + xmlNsPtr ns; + xmlListPtr list; + xmlAttrPtr attr; + int already_rendered; + int has_empty_ns = 0; + int has_visibly_utilized_empty_ns = 0; + int has_empty_ns_in_inclusive_list = 0; + + if ((ctx == NULL) || (cur == NULL) || (cur->type != XML_ELEMENT_NODE)) { + xmlC14NErrParam("processing namespaces axis (exc c14n)"); + return (-1); + } + + if(!ctx->exclusive) { + xmlC14NErrParam("processing namespaces axis (exc c14n)"); + return (-1); + + } + + /* + * Create a sorted list to store element namespaces + */ + list = xmlListCreate(NULL, (xmlListDataCompare) xmlC14NNsCompare); + if (list == NULL) { + xmlC14NErrInternal("creating namespaces list (exc c14n)"); + return (-1); + } + + /* + * process inclusive namespaces: + * All namespace nodes appearing on inclusive ns list are + * handled as provided in Canonical XML + */ + if(ctx->inclusive_ns_prefixes != NULL) { + xmlChar *prefix; + int i; + + for (i = 0; ctx->inclusive_ns_prefixes[i] != NULL; ++i) { + prefix = ctx->inclusive_ns_prefixes[i]; + /* + * Special values for namespace with empty prefix + */ + if (xmlStrEqual(prefix, BAD_CAST "#default") + || xmlStrEqual(prefix, BAD_CAST "")) { + prefix = NULL; + has_empty_ns_in_inclusive_list = 1; + } + + ns = xmlSearchNs(cur->doc, cur, prefix); + if((ns != NULL) && !xmlC14NIsXmlNs(ns) && xmlC14NIsVisible(ctx, ns, cur)) { + already_rendered = xmlC14NVisibleNsStackFind(ctx->ns_rendered, ns); + if(visible) { + xmlC14NVisibleNsStackAdd(ctx->ns_rendered, ns, cur); + } + if(!already_rendered) { + xmlListInsert(list, ns); + } + if(xmlStrlen(ns->prefix) == 0) { + has_empty_ns = 1; + } + } + } + } + + /* add node namespace */ + if(cur->ns != NULL) { + ns = cur->ns; + } else { + ns = xmlSearchNs(cur->doc, cur, NULL); + has_visibly_utilized_empty_ns = 1; + } + if((ns != NULL) && !xmlC14NIsXmlNs(ns)) { + if(visible && xmlC14NIsVisible(ctx, ns, cur)) { + if(!xmlExcC14NVisibleNsStackFind(ctx->ns_rendered, ns, ctx)) { + xmlListInsert(list, ns); + } + } + if(visible) { + xmlC14NVisibleNsStackAdd(ctx->ns_rendered, ns, cur); + } + if(xmlStrlen(ns->prefix) == 0) { + has_empty_ns = 1; + } + } + + + /* add attributes */ + for(attr = cur->properties; attr != NULL; attr = attr->next) { + /* + * we need to check that attribute is visible and has non + * default namespace (XML Namespaces: "default namespaces + * do not apply directly to attributes") + */ + if((attr->ns != NULL) && !xmlC14NIsXmlNs(attr->ns) && xmlC14NIsVisible(ctx, attr, cur)) { + already_rendered = xmlExcC14NVisibleNsStackFind(ctx->ns_rendered, attr->ns, ctx); + xmlC14NVisibleNsStackAdd(ctx->ns_rendered, attr->ns, cur); + if(!already_rendered && visible) { + xmlListInsert(list, attr->ns); + } + if(xmlStrlen(attr->ns->prefix) == 0) { + has_empty_ns = 1; + } + } else if((attr->ns != NULL) && (xmlStrlen(attr->ns->prefix) == 0) && (xmlStrlen(attr->ns->href) == 0)) { + has_visibly_utilized_empty_ns = 1; + } + } + + /* + * Process xmlns="" + */ + if(visible && has_visibly_utilized_empty_ns && + !has_empty_ns && !has_empty_ns_in_inclusive_list) { + static xmlNs ns_default; + + memset(&ns_default, 0, sizeof(ns_default)); + + already_rendered = xmlExcC14NVisibleNsStackFind(ctx->ns_rendered, &ns_default, ctx); + if(!already_rendered) { + xmlC14NPrintNamespaces(&ns_default, ctx); + } + } else if(visible && !has_empty_ns && has_empty_ns_in_inclusive_list) { + static xmlNs ns_default; + + memset(&ns_default, 0, sizeof(ns_default)); + if(!xmlC14NVisibleNsStackFind(ctx->ns_rendered, &ns_default)) { + xmlC14NPrintNamespaces(&ns_default, ctx); + } + } + + + + /* + * print out all elements from list + */ + xmlListWalk(list, (xmlListWalker) xmlC14NPrintNamespaces, (const void *) ctx); + + /* + * Cleanup + */ + xmlListDelete(list); + return (0); +} + + +/** + * xmlC14NAttrsCompare: + * @attr1: the pointer tls o first attr + * @attr2: the pointer to second attr + * + * Prints the given attribute to the output buffer from C14N context. + * + * Returns -1 if attr1 < attr2, 0 if attr1 == attr2 or 1 if attr1 > attr2. + */ +static int +xmlC14NAttrsCompare(xmlAttrPtr attr1, xmlAttrPtr attr2) +{ + int ret = 0; + + /* + * Simple cases + */ + if (attr1 == attr2) + return (0); + if (attr1 == NULL) + return (-1); + if (attr2 == NULL) + return (1); + if (attr1->ns == attr2->ns) { + return (xmlStrcmp(attr1->name, attr2->name)); + } + + /* + * Attributes in the default namespace are first + * because the default namespace is not applied to + * unqualified attributes + */ + if (attr1->ns == NULL) + return (-1); + if (attr2->ns == NULL) + return (1); + if (attr1->ns->prefix == NULL) + return (-1); + if (attr2->ns->prefix == NULL) + return (1); + + ret = xmlStrcmp(attr1->ns->href, attr2->ns->href); + if (ret == 0) { + ret = xmlStrcmp(attr1->name, attr2->name); + } + return (ret); +} + + +/** + * xmlC14NPrintAttrs: + * @attr: the pointer to attr + * @ctx: the C14N context + * + * Prints out canonical attribute urrent node to the + * buffer from C14N context as follows + * + * Canonical XML v 1.0 (http://www.w3.org/TR/xml-c14n) + * + * Returns 1 on success or 0 on fail. + */ +static int +xmlC14NPrintAttrs(const xmlAttrPtr attr, xmlC14NCtxPtr ctx) +{ + xmlChar *value; + xmlChar *buffer; + + if ((attr == NULL) || (ctx == NULL)) { + xmlC14NErrParam("writing attributes"); + return (0); + } + + xmlOutputBufferWriteString(ctx->buf, " "); + if (attr->ns != NULL && xmlStrlen(attr->ns->prefix) > 0) { + xmlOutputBufferWriteString(ctx->buf, + (const char *) attr->ns->prefix); + xmlOutputBufferWriteString(ctx->buf, ":"); + } + xmlOutputBufferWriteString(ctx->buf, (const char *) attr->name); + xmlOutputBufferWriteString(ctx->buf, "=\""); + + value = xmlNodeListGetString(attr->doc, attr->children, 1); + /* todo: should we log an error if value==NULL ? */ + if (value != NULL) { + buffer = xmlC11NNormalizeAttr(value); + xmlFree(value); + if (buffer != NULL) { + xmlOutputBufferWriteString(ctx->buf, (const char *) buffer); + xmlFree(buffer); + } else { + xmlC14NErrInternal("normalizing attributes axis"); + return (0); + } + } + xmlOutputBufferWriteString(ctx->buf, "\""); + return (1); +} + +/** + * xmlC14NProcessAttrsAxis: + * @ctx: the C14N context + * @cur: the current node + * @parent_visible: the visibility of parent node + * + * Prints out canonical attribute axis of the current node to the + * buffer from C14N context as follows + * + * Canonical XML v 1.0 (http://www.w3.org/TR/xml-c14n) + * + * Attribute Axis + * In lexicographic order (ascending), process each node that + * is in the element's attribute axis and in the node-set. + * + * The processing of an element node E MUST be modified slightly + * when an XPath node-set is given as input and the element's + * parent is omitted from the node-set. + * + * + * Exclusive XML Canonicalization v 1.0 (http://www.w3.org/TR/xml-exc-c14n) + * + * Canonical XML applied to a document subset requires the search of the + * ancestor nodes of each orphan element node for attributes in the xml + * namespace, such as xml:lang and xml:space. These are copied into the + * element node except if a declaration of the same attribute is already + * in the attribute axis of the element (whether or not it is included in + * the document subset). This search and copying are omitted from the + * Exclusive XML Canonicalization method. + * + * Returns 0 on success or -1 on fail. + */ +static int +xmlC14NProcessAttrsAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur, int parent_visible) +{ + xmlAttrPtr attr; + xmlListPtr list; + + if ((ctx == NULL) || (cur == NULL) || (cur->type != XML_ELEMENT_NODE)) { + xmlC14NErrParam("processing attributes axis"); + return (-1); + } + + /* + * Create a sorted list to store element attributes + */ + list = xmlListCreate(NULL, (xmlListDataCompare) xmlC14NAttrsCompare); + if (list == NULL) { + xmlC14NErrInternal("creating attributes list"); + return (-1); + } + + /* + * Add all visible attributes from current node. + */ + attr = cur->properties; + while (attr != NULL) { + /* check that attribute is visible */ + if (xmlC14NIsVisible(ctx, attr, cur)) { + xmlListInsert(list, attr); + } + attr = attr->next; + } + + /* + * include attributes in "xml" namespace defined in ancestors + * (only for non-exclusive XML Canonicalization) + */ + if (parent_visible && (!ctx->exclusive) && (cur->parent != NULL) + && (!xmlC14NIsVisible(ctx, cur->parent, cur->parent->parent))) { + /* + * If XPath node-set is not specified then the parent is always + * visible! + */ + cur = cur->parent; + while (cur != NULL) { + attr = cur->properties; + while (attr != NULL) { + if ((attr->ns != NULL) + && (xmlStrEqual(attr->ns->prefix, BAD_CAST "xml"))) { + if (xmlListSearch(list, attr) == NULL) { + xmlListInsert(list, attr); + } + } + attr = attr->next; + } + cur = cur->parent; + } + } + + /* + * print out all elements from list + */ + xmlListWalk(list, (xmlListWalker) xmlC14NPrintAttrs, (const void *) ctx); + + /* + * Cleanup + */ + xmlListDelete(list); + return (0); +} + +/** + * xmlC14NCheckForRelativeNamespaces: + * @ctx: the C14N context + * @cur: the current element node + * + * Checks that current element node has no relative namespaces defined + * + * Returns 0 if the node has no relative namespaces or -1 otherwise. + */ +static int +xmlC14NCheckForRelativeNamespaces(xmlC14NCtxPtr ctx, xmlNodePtr cur) +{ + xmlNsPtr ns; + + if ((ctx == NULL) || (cur == NULL) || (cur->type != XML_ELEMENT_NODE)) { + xmlC14NErrParam("checking for relative namespaces"); + return (-1); + } + + ns = cur->nsDef; + while (ns != NULL) { + if (xmlStrlen(ns->href) > 0) { + xmlURIPtr uri; + + uri = xmlParseURI((const char *) ns->href); + if (uri == NULL) { + xmlC14NErrInternal("parsing namespace uri"); + return (-1); + } + if (xmlStrlen((const xmlChar *) uri->scheme) == 0) { + xmlC14NErrRelativeNamespace(uri->scheme); + xmlFreeURI(uri); + return (-1); + } + if ((xmlStrcasecmp((const xmlChar *) uri->scheme, BAD_CAST "urn") != 0) + && (xmlStrcasecmp((const xmlChar *) uri->scheme, BAD_CAST "dav") !=0) + && (xmlStrlen((const xmlChar *) uri->server) == 0)) { + xmlC14NErrRelativeNamespace(uri->scheme); + xmlFreeURI(uri); + return (-1); + } + xmlFreeURI(uri); + } + ns = ns->next; + } + return (0); +} + +/** + * xmlC14NProcessElementNode: + * @ctx: the pointer to C14N context object + * @cur: the node to process + * + * Canonical XML v 1.0 (http://www.w3.org/TR/xml-c14n) + * + * Element Nodes + * If the element is not in the node-set, then the result is obtained + * by processing the namespace axis, then the attribute axis, then + * processing the child nodes of the element that are in the node-set + * (in document order). If the element is in the node-set, then the result + * is an open angle bracket (<), the element QName, the result of + * processing the namespace axis, the result of processing the attribute + * axis, a close angle bracket (>), the result of processing the child + * nodes of the element that are in the node-set (in document order), an + * open angle bracket, a forward slash (/), the element QName, and a close + * angle bracket. + * + * Returns non-negative value on success or negative value on fail + */ +static int +xmlC14NProcessElementNode(xmlC14NCtxPtr ctx, xmlNodePtr cur, int visible) +{ + int ret; + xmlC14NVisibleNsStack state; + int parent_is_doc = 0; + + if ((ctx == NULL) || (cur == NULL) || (cur->type != XML_ELEMENT_NODE)) { + xmlC14NErrParam("processing element node"); + return (-1); + } + + /* + * Check relative relative namespaces: + * implementations of XML canonicalization MUST report an operation + * failure on documents containing relative namespace URIs. + */ + if (xmlC14NCheckForRelativeNamespaces(ctx, cur) < 0) { + xmlC14NErrInternal("checking for relative namespaces"); + return (-1); + } + + + /* + * Save ns_rendered stack position + */ + memset(&state, 0, sizeof(state)); + xmlC14NVisibleNsStackSave(ctx->ns_rendered, &state); + + if (visible) { + if (ctx->parent_is_doc) { + /* save this flag into the stack */ + parent_is_doc = ctx->parent_is_doc; + ctx->parent_is_doc = 0; + ctx->pos = XMLC14N_INSIDE_DOCUMENT_ELEMENT; + } + xmlOutputBufferWriteString(ctx->buf, "<"); + + if ((cur->ns != NULL) && (xmlStrlen(cur->ns->prefix) > 0)) { + xmlOutputBufferWriteString(ctx->buf, + (const char *) cur->ns->prefix); + xmlOutputBufferWriteString(ctx->buf, ":"); + } + xmlOutputBufferWriteString(ctx->buf, (const char *) cur->name); + } + + if (!ctx->exclusive) { + ret = xmlC14NProcessNamespacesAxis(ctx, cur, visible); + } else { + ret = xmlExcC14NProcessNamespacesAxis(ctx, cur, visible); + } + if (ret < 0) { + xmlC14NErrInternal("processing namespaces axis"); + return (-1); + } + /* todo: shouldn't this go to "visible only"? */ + if(visible) { + xmlC14NVisibleNsStackShift(ctx->ns_rendered); + } + + ret = xmlC14NProcessAttrsAxis(ctx, cur, visible); + if (ret < 0) { + xmlC14NErrInternal("processing attributes axis"); + return (-1); + } + + if (visible) { + xmlOutputBufferWriteString(ctx->buf, ">"); + } + if (cur->children != NULL) { + ret = xmlC14NProcessNodeList(ctx, cur->children); + if (ret < 0) { + xmlC14NErrInternal("processing childrens list"); + return (-1); + } + } + if (visible) { + xmlOutputBufferWriteString(ctx->buf, "ns != NULL) && (xmlStrlen(cur->ns->prefix) > 0)) { + xmlOutputBufferWriteString(ctx->buf, + (const char *) cur->ns->prefix); + xmlOutputBufferWriteString(ctx->buf, ":"); + } + xmlOutputBufferWriteString(ctx->buf, (const char *) cur->name); + xmlOutputBufferWriteString(ctx->buf, ">"); + if (parent_is_doc) { + /* restore this flag from the stack for next node */ + ctx->parent_is_doc = parent_is_doc; + ctx->pos = XMLC14N_AFTER_DOCUMENT_ELEMENT; + } + } + + /* + * Restore ns_rendered stack position + */ + xmlC14NVisibleNsStackRestore(ctx->ns_rendered, &state); + return (0); +} + +/** + * xmlC14NProcessNode: + * @ctx: the pointer to C14N context object + * @cur: the node to process + * + * Processes the given node + * + * Returns non-negative value on success or negative value on fail + */ +static int +xmlC14NProcessNode(xmlC14NCtxPtr ctx, xmlNodePtr cur) +{ + int ret = 0; + int visible; + + if ((ctx == NULL) || (cur == NULL)) { + xmlC14NErrParam("processing node"); + return (-1); + } + + visible = xmlC14NIsVisible(ctx, cur, cur->parent); + switch (cur->type) { + case XML_ELEMENT_NODE: + ret = xmlC14NProcessElementNode(ctx, cur, visible); + break; + case XML_CDATA_SECTION_NODE: + case XML_TEXT_NODE: + /* + * Text Nodes + * the string value, except all ampersands are replaced + * by &, all open angle brackets (<) are replaced by <, all closing + * angle brackets (>) are replaced by >, and all #xD characters are + * replaced by . + */ + /* cdata sections are processed as text nodes */ + /* todo: verify that cdata sections are included in XPath nodes set */ + if ((visible) && (cur->content != NULL)) { + xmlChar *buffer; + + buffer = xmlC11NNormalizeText(cur->content); + if (buffer != NULL) { + xmlOutputBufferWriteString(ctx->buf, + (const char *) buffer); + xmlFree(buffer); + } else { + xmlC14NErrInternal("normalizing text node"); + return (-1); + } + } + break; + case XML_PI_NODE: + /* + * Processing Instruction (PI) Nodes- + * The opening PI symbol (). If the string value is empty, + * then the leading space is not added. Also, a trailing #xA is + * rendered after the closing PI symbol for PI children of the + * root node with a lesser document order than the document + * element, and a leading #xA is rendered before the opening PI + * symbol of PI children of the root node with a greater document + * order than the document element. + */ + if (visible) { + if (ctx->pos == XMLC14N_AFTER_DOCUMENT_ELEMENT) { + xmlOutputBufferWriteString(ctx->buf, "\x0Abuf, "buf, + (const char *) cur->name); + if ((cur->content != NULL) && (*(cur->content) != '\0')) { + xmlChar *buffer; + + xmlOutputBufferWriteString(ctx->buf, " "); + + /* todo: do we need to normalize pi? */ + buffer = xmlC11NNormalizePI(cur->content); + if (buffer != NULL) { + xmlOutputBufferWriteString(ctx->buf, + (const char *) buffer); + xmlFree(buffer); + } else { + xmlC14NErrInternal("normalizing pi node"); + return (-1); + } + } + + if (ctx->pos == XMLC14N_BEFORE_DOCUMENT_ELEMENT) { + xmlOutputBufferWriteString(ctx->buf, "?>\x0A"); + } else { + xmlOutputBufferWriteString(ctx->buf, "?>"); + } + } + break; + case XML_COMMENT_NODE: + /* + * Comment Nodes + * Nothing if generating canonical XML without comments. For + * canonical XML with comments, generate the opening comment + * symbol (). Also, a trailing #xA is rendered + * after the closing comment symbol for comment children of the + * root node with a lesser document order than the document + * element, and a leading #xA is rendered before the opening + * comment symbol of comment children of the root node with a + * greater document order than the document element. (Comment + * children of the root node represent comments outside of the + * top-level document element and outside of the document type + * declaration). + */ + if (visible && ctx->with_comments) { + if (ctx->pos == XMLC14N_AFTER_DOCUMENT_ELEMENT) { + xmlOutputBufferWriteString(ctx->buf, "\x0A\x0A"); + } else { + xmlOutputBufferWriteString(ctx->buf, "-->"); + } + } + break; + case XML_DOCUMENT_NODE: + case XML_DOCUMENT_FRAG_NODE: /* should be processed as document? */ +#ifdef LIBXML_DOCB_ENABLED + case XML_DOCB_DOCUMENT_NODE: /* should be processed as document? */ +#endif +#ifdef LIBXML_HTML_ENABLED + case XML_HTML_DOCUMENT_NODE: /* should be processed as document? */ +#endif + if (cur->children != NULL) { + ctx->pos = XMLC14N_BEFORE_DOCUMENT_ELEMENT; + ctx->parent_is_doc = 1; + ret = xmlC14NProcessNodeList(ctx, cur->children); + } + break; + + case XML_ATTRIBUTE_NODE: + xmlC14NErrInvalidNode("XML_ATTRIBUTE_NODE", "processing node"); + return (-1); + case XML_NAMESPACE_DECL: + xmlC14NErrInvalidNode("XML_NAMESPACE_DECL", "processing node"); + return (-1); + case XML_ENTITY_REF_NODE: + xmlC14NErrInvalidNode("XML_ENTITY_REF_NODE", "processing node"); + return (-1); + case XML_ENTITY_NODE: + xmlC14NErrInvalidNode("XML_ENTITY_NODE", "processing node"); + return (-1); + + case XML_DOCUMENT_TYPE_NODE: + case XML_NOTATION_NODE: + case XML_DTD_NODE: + case XML_ELEMENT_DECL: + case XML_ATTRIBUTE_DECL: + case XML_ENTITY_DECL: +#ifdef LIBXML_XINCLUDE_ENABLED + case XML_XINCLUDE_START: + case XML_XINCLUDE_END: +#endif + /* + * should be ignored according to "W3C Canonical XML" + */ + break; + default: + xmlC14NErrUnknownNode(cur->type, "processing node"); + return (-1); + } + + return (ret); +} + +/** + * xmlC14NProcessNodeList: + * @ctx: the pointer to C14N context object + * @cur: the node to start from + * + * Processes all nodes in the row starting from cur. + * + * Returns non-negative value on success or negative value on fail + */ +static int +xmlC14NProcessNodeList(xmlC14NCtxPtr ctx, xmlNodePtr cur) +{ + int ret; + + if (ctx == NULL) { + xmlC14NErrParam("processing node list"); + return (-1); + } + + for (ret = 0; cur != NULL && ret >= 0; cur = cur->next) { + ret = xmlC14NProcessNode(ctx, cur); + } + return (ret); +} + + +/** + * xmlC14NFreeCtx: + * @ctx: the pointer to C14N context object + * + * Cleanups the C14N context object. + */ + +static void +xmlC14NFreeCtx(xmlC14NCtxPtr ctx) +{ + if (ctx == NULL) { + xmlC14NErrParam("freeing context"); + return; + } + + if (ctx->ns_rendered != NULL) { + xmlC14NVisibleNsStackDestroy(ctx->ns_rendered); + } + xmlFree(ctx); +} + +/** + * xmlC14NNewCtx: + * @doc: the XML document for canonization + * @is_visible_callback:the function to use to determine is node visible + * or not + * @user_data: the first parameter for @is_visible_callback function + * (in most cases, it is nodes set) + * @inclusive_ns_prefixe the list of inclusive namespace prefixes + * ended with a NULL or NULL if there is no + * inclusive namespaces (only for exclusive + * canonicalization) + * @with_comments: include comments in the result (!=0) or not (==0) + * @buf: the output buffer to store canonical XML; this + * buffer MUST have encoder==NULL because C14N requires + * UTF-8 output + * + * Creates new C14N context object to store C14N parameters. + * + * Returns pointer to newly created object (success) or NULL (fail) + */ +static xmlC14NCtxPtr +xmlC14NNewCtx(xmlDocPtr doc, + xmlC14NIsVisibleCallback is_visible_callback, void* user_data, + int exclusive, xmlChar ** inclusive_ns_prefixes, + int with_comments, xmlOutputBufferPtr buf) +{ + xmlC14NCtxPtr ctx = NULL; + + if ((doc == NULL) || (buf == NULL)) { + xmlC14NErrParam("creating new context"); + return (NULL); + } + + /* + * Validate the encoding output buffer encoding + */ + if (buf->encoder != NULL) { + xmlC14NErr(ctx, (xmlNodePtr) doc, XML_C14N_REQUIRES_UTF8, +"xmlC14NNewCtx: output buffer encoder != NULL but C14N requires UTF8 output\n"); + return (NULL); + } + + /* + * Validate the XML document encoding value, if provided. + */ + if (doc->charset != XML_CHAR_ENCODING_UTF8) { + xmlC14NErr(ctx, (xmlNodePtr) doc, XML_C14N_REQUIRES_UTF8, + "xmlC14NNewCtx: source document not in UTF8\n"); + return (NULL); + } + + /* + * Allocate a new xmlC14NCtxPtr and fill the fields. + */ + ctx = (xmlC14NCtxPtr) xmlMalloc(sizeof(xmlC14NCtx)); + if (ctx == NULL) { + xmlC14NErrMemory("creating context"); + return (NULL); + } + memset(ctx, 0, sizeof(xmlC14NCtx)); + + /* + * initialize C14N context + */ + ctx->doc = doc; + ctx->with_comments = with_comments; + ctx->is_visible_callback = is_visible_callback; + ctx->user_data = user_data; + ctx->buf = buf; + ctx->parent_is_doc = 1; + ctx->pos = XMLC14N_BEFORE_DOCUMENT_ELEMENT; + ctx->ns_rendered = xmlC14NVisibleNsStackCreate(); + + if(ctx->ns_rendered == NULL) { + xmlC14NErr(ctx, (xmlNodePtr) doc, XML_C14N_CREATE_STACK, + "xmlC14NNewCtx: xmlC14NVisibleNsStackCreate failed\n"); + xmlC14NFreeCtx(ctx); + return (NULL); + } + + /* + * Set "exclusive" flag, create a nodes set for namespaces + * stack and remember list of incluseve prefixes + */ + if (exclusive) { + ctx->exclusive = 1; + ctx->inclusive_ns_prefixes = inclusive_ns_prefixes; + } + return (ctx); +} + +/** + * xmlC14NExecute: + * @doc: the XML document for canonization + * @is_visible_callback:the function to use to determine is node visible + * or not + * @user_data: the first parameter for @is_visible_callback function + * (in most cases, it is nodes set) + * @exclusive: the exclusive flag (0 - non-exclusive canonicalization; + * otherwise - exclusive canonicalization) + * @inclusive_ns_prefixes: the list of inclusive namespace prefixes + * ended with a NULL or NULL if there is no + * inclusive namespaces (only for exclusive + * canonicalization, ignored otherwise) + * @with_comments: include comments in the result (!=0) or not (==0) + * @buf: the output buffer to store canonical XML; this + * buffer MUST have encoder==NULL because C14N requires + * UTF-8 output + * + * Dumps the canonized image of given XML document into the provided buffer. + * For details see "Canonical XML" (http://www.w3.org/TR/xml-c14n) or + * "Exclusive XML Canonicalization" (http://www.w3.org/TR/xml-exc-c14n) + * + * Returns non-negative value on success or a negative value on fail + */ +int +xmlC14NExecute(xmlDocPtr doc, xmlC14NIsVisibleCallback is_visible_callback, + void* user_data, int exclusive, xmlChar **inclusive_ns_prefixes, + int with_comments, xmlOutputBufferPtr buf) { + + xmlC14NCtxPtr ctx; + int ret; + + if ((buf == NULL) || (doc == NULL)) { + xmlC14NErrParam("executing c14n"); + return (-1); + } + + /* + * Validate the encoding output buffer encoding + */ + if (buf->encoder != NULL) { + xmlC14NErr(NULL, (xmlNodePtr) doc, XML_C14N_REQUIRES_UTF8, +"xmlC14NExecute: output buffer encoder != NULL but C14N requires UTF8 output\n"); + return (-1); + } + + ctx = xmlC14NNewCtx(doc, is_visible_callback, user_data, + exclusive, inclusive_ns_prefixes, + with_comments, buf); + if (ctx == NULL) { + xmlC14NErr(NULL, (xmlNodePtr) doc, XML_C14N_CREATE_CTXT, + "xmlC14NExecute: unable to create C14N context\n"); + return (-1); + } + + + + /* + * Root Node + * The root node is the parent of the top-level document element. The + * result of processing each of its child nodes that is in the node-set + * in document order. The root node does not generate a byte order mark, + * XML declaration, nor anything from within the document type + * declaration. + */ + if (doc->children != NULL) { + ret = xmlC14NProcessNodeList(ctx, doc->children); + if (ret < 0) { + xmlC14NErrInternal("processing docs children list"); + xmlC14NFreeCtx(ctx); + return (-1); + } + } + + /* + * Flush buffer to get number of bytes written + */ + ret = xmlOutputBufferFlush(buf); + if (ret < 0) { + xmlC14NErrInternal("flushing output buffer"); + xmlC14NFreeCtx(ctx); + return (-1); + } + + /* + * Cleanup + */ + xmlC14NFreeCtx(ctx); + return (ret); +} + +/** + * xmlC14NDocSaveTo: + * @doc: the XML document for canonization + * @nodes: the nodes set to be included in the canonized image + * or NULL if all document nodes should be included + * @exclusive: the exclusive flag (0 - non-exclusive canonicalization; + * otherwise - exclusive canonicalization) + * @inclusive_ns_prefixes: the list of inclusive namespace prefixes + * ended with a NULL or NULL if there is no + * inclusive namespaces (only for exclusive + * canonicalization, ignored otherwise) + * @with_comments: include comments in the result (!=0) or not (==0) + * @buf: the output buffer to store canonical XML; this + * buffer MUST have encoder==NULL because C14N requires + * UTF-8 output + * + * Dumps the canonized image of given XML document into the provided buffer. + * For details see "Canonical XML" (http://www.w3.org/TR/xml-c14n) or + * "Exclusive XML Canonicalization" (http://www.w3.org/TR/xml-exc-c14n) + * + * Returns non-negative value on success or a negative value on fail + */ +int +xmlC14NDocSaveTo(xmlDocPtr doc, xmlNodeSetPtr nodes, + int exclusive, xmlChar ** inclusive_ns_prefixes, + int with_comments, xmlOutputBufferPtr buf) { + return(xmlC14NExecute(doc, + (xmlC14NIsVisibleCallback)xmlC14NIsNodeInNodeset, + nodes, + exclusive, + inclusive_ns_prefixes, + with_comments, + buf)); +} + + +/** + * xmlC14NDocDumpMemory: + * @doc: the XML document for canonization + * @nodes: the nodes set to be included in the canonized image + * or NULL if all document nodes should be included + * @exclusive: the exclusive flag (0 - non-exclusive canonicalization; + * otherwise - exclusive canonicalization) + * @inclusive_ns_prefixes: the list of inclusive namespace prefixes + * ended with a NULL or NULL if there is no + * inclusive namespaces (only for exclusive + * canonicalization, ignored otherwise) + * @with_comments: include comments in the result (!=0) or not (==0) + * @doc_txt_ptr: the memory pointer for allocated canonical XML text; + * the caller of this functions is responsible for calling + * xmlFree() to free allocated memory + * + * Dumps the canonized image of given XML document into memory. + * For details see "Canonical XML" (http://www.w3.org/TR/xml-c14n) or + * "Exclusive XML Canonicalization" (http://www.w3.org/TR/xml-exc-c14n) + * + * Returns the number of bytes written on success or a negative value on fail + */ +int +xmlC14NDocDumpMemory(xmlDocPtr doc, xmlNodeSetPtr nodes, + int exclusive, xmlChar ** inclusive_ns_prefixes, + int with_comments, xmlChar ** doc_txt_ptr) +{ + int ret; + xmlOutputBufferPtr buf; + + if (doc_txt_ptr == NULL) { + xmlC14NErrParam("dumping doc to memory"); + return (-1); + } + + *doc_txt_ptr = NULL; + + /* + * create memory buffer with UTF8 (default) encoding + */ + buf = xmlAllocOutputBuffer(NULL); + if (buf == NULL) { + xmlC14NErrMemory("creating output buffer"); + return (-1); + } + + /* + * canonize document and write to buffer + */ + ret = xmlC14NDocSaveTo(doc, nodes, exclusive, inclusive_ns_prefixes, + with_comments, buf); + if (ret < 0) { + xmlC14NErrInternal("saving doc to output buffer"); + (void) xmlOutputBufferClose(buf); + return (-1); + } + + ret = buf->buffer->use; + if (ret > 0) { + *doc_txt_ptr = xmlStrndup(buf->buffer->content, ret); + } + (void) xmlOutputBufferClose(buf); + + if ((*doc_txt_ptr == NULL) && (ret > 0)) { + xmlC14NErrMemory("coping canonicanized document"); + return (-1); + } + return (ret); +} + +/** + * xmlC14NDocSave: + * @doc: the XML document for canonization + * @nodes: the nodes set to be included in the canonized image + * or NULL if all document nodes should be included + * @exclusive: the exclusive flag (0 - non-exclusive canonicalization; + * otherwise - exclusive canonicalization) + * @inclusive_ns_prefixes: the list of inclusive namespace prefixes + * ended with a NULL or NULL if there is no + * inclusive namespaces (only for exclusive + * canonicalization, ignored otherwise) + * @with_comments: include comments in the result (!=0) or not (==0) + * @filename: the filename to store canonical XML image + * @compression: the compression level (zlib requred): + * -1 - libxml default, + * 0 - uncompressed, + * >0 - compression level + * + * Dumps the canonized image of given XML document into the file. + * For details see "Canonical XML" (http://www.w3.org/TR/xml-c14n) or + * "Exclusive XML Canonicalization" (http://www.w3.org/TR/xml-exc-c14n) + * + * Returns the number of bytes written success or a negative value on fail + */ +int +xmlC14NDocSave(xmlDocPtr doc, xmlNodeSetPtr nodes, + int exclusive, xmlChar ** inclusive_ns_prefixes, + int with_comments, const char *filename, int compression) +{ + xmlOutputBufferPtr buf; + int ret; + + if (filename == NULL) { + xmlC14NErrParam("saving doc"); + return (-1); + } +#ifdef HAVE_ZLIB_H + if (compression < 0) + compression = xmlGetCompressMode(); +#endif + + /* + * save the content to a temp buffer, use default UTF8 encoding. + */ + buf = xmlOutputBufferCreateFilename(filename, NULL, compression); + if (buf == NULL) { + xmlC14NErrInternal("creating temporary filename"); + return (-1); + } + + /* + * canonize document and write to buffer + */ + ret = xmlC14NDocSaveTo(doc, nodes, exclusive, inclusive_ns_prefixes, + with_comments, buf); + if (ret < 0) { + xmlC14NErrInternal("cannicanize document to buffer"); + (void) xmlOutputBufferClose(buf); + return (-1); + } + + /* + * get the numbers of bytes written + */ + ret = xmlOutputBufferClose(buf); + return (ret); +} + + + +/* + * Macro used to grow the current buffer. + */ +#define growBufferReentrant() { \ + buffer_size *= 2; \ + buffer = (xmlChar *) \ + xmlRealloc(buffer, buffer_size * sizeof(xmlChar)); \ + if (buffer == NULL) { \ + xmlC14NErrMemory("growing buffer"); \ + return(NULL); \ + } \ +} + +/** + * xmlC11NNormalizeString: + * @input: the input string + * @mode: the normalization mode (attribute, comment, PI or text) + * + * Converts a string to a canonical (normalized) format. The code is stolen + * from xmlEncodeEntitiesReentrant(). Added normalization of \x09, \x0a, \x0A + * and the @mode parameter + * + * Returns a normalized string (caller is responsible for calling xmlFree()) + * or NULL if an error occurs + */ +static xmlChar * +xmlC11NNormalizeString(const xmlChar * input, + xmlC14NNormalizationMode mode) +{ + const xmlChar *cur = input; + xmlChar *buffer = NULL; + xmlChar *out = NULL; + int buffer_size = 0; + + if (input == NULL) + return (NULL); + + /* + * allocate an translation buffer. + */ + buffer_size = 1000; + buffer = (xmlChar *) xmlMallocAtomic(buffer_size * sizeof(xmlChar)); + if (buffer == NULL) { + xmlC14NErrMemory("allocating buffer"); + return (NULL); + } + out = buffer; + + while (*cur != '\0') { + if ((out - buffer) > (buffer_size - 10)) { + int indx = out - buffer; + + growBufferReentrant(); + out = &buffer[indx]; + } + + if ((*cur == '<') && ((mode == XMLC14N_NORMALIZE_ATTR) || + (mode == XMLC14N_NORMALIZE_TEXT))) { + *out++ = '&'; + *out++ = 'l'; + *out++ = 't'; + *out++ = ';'; + } else if ((*cur == '>') && (mode == XMLC14N_NORMALIZE_TEXT)) { + *out++ = '&'; + *out++ = 'g'; + *out++ = 't'; + *out++ = ';'; + } else if ((*cur == '&') && ((mode == XMLC14N_NORMALIZE_ATTR) || + (mode == XMLC14N_NORMALIZE_TEXT))) { + *out++ = '&'; + *out++ = 'a'; + *out++ = 'm'; + *out++ = 'p'; + *out++ = ';'; + } else if ((*cur == '"') && (mode == XMLC14N_NORMALIZE_ATTR)) { + *out++ = '&'; + *out++ = 'q'; + *out++ = 'u'; + *out++ = 'o'; + *out++ = 't'; + *out++ = ';'; + } else if ((*cur == '\x09') && (mode == XMLC14N_NORMALIZE_ATTR)) { + *out++ = '&'; + *out++ = '#'; + *out++ = 'x'; + *out++ = '9'; + *out++ = ';'; + } else if ((*cur == '\x0A') && (mode == XMLC14N_NORMALIZE_ATTR)) { + *out++ = '&'; + *out++ = '#'; + *out++ = 'x'; + *out++ = 'A'; + *out++ = ';'; + } else if ((*cur == '\x0D') && ((mode == XMLC14N_NORMALIZE_ATTR) || + (mode == XMLC14N_NORMALIZE_TEXT) || + (mode == XMLC14N_NORMALIZE_COMMENT) || + (mode == XMLC14N_NORMALIZE_PI))) { + *out++ = '&'; + *out++ = '#'; + *out++ = 'x'; + *out++ = 'D'; + *out++ = ';'; + } else { + /* + * Works because on UTF-8, all extended sequences cannot + * result in bytes in the ASCII range. + */ + *out++ = *cur; + } + cur++; + } + *out++ = 0; + return (buffer); +} +#endif /* LIBXML_OUTPUT_ENABLED */ +#define bottom_c14n +#include "elfgcchack.h" +#endif /* LIBXML_C14N_ENABLED */ diff --git a/gettext-tools/gnulib-lib/libxml/c14n.in.h b/gettext-tools/gnulib-lib/libxml/c14n.in.h new file mode 100644 index 0000000..9f4c6c0 --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/c14n.in.h @@ -0,0 +1,105 @@ +/* + * Summary: Provide Canonical XML and Exclusive XML Canonicalization + * Description: the c14n modules provides a + * + * "Canonical XML" implementation + * http://www.w3.org/TR/xml-c14n + * + * and an + * + * "Exclusive XML Canonicalization" implementation + * http://www.w3.org/TR/xml-exc-c14n + + * Copy: See Copyright for the status of this software. + * + * Author: Aleksey Sanin + */ +#ifndef __XML_C14N_H__ +#define __XML_C14N_H__ +#ifdef LIBXML_C14N_ENABLED +#ifdef LIBXML_OUTPUT_ENABLED + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include +#include +#include + +/* + * XML Canonicazation + * http://www.w3.org/TR/xml-c14n + * + * Exclusive XML Canonicazation + * http://www.w3.org/TR/xml-exc-c14n + * + * Canonical form of an XML document could be created if and only if + * a) default attributes (if any) are added to all nodes + * b) all character and parsed entity references are resolved + * In order to achive this in libxml2 the document MUST be loaded with + * following global setings: + * + * xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS; + * xmlSubstituteEntitiesDefault(1); + * + * or corresponding parser context setting: + * xmlParserCtxtPtr ctxt; + * + * ... + * ctxt->loadsubset = XML_DETECT_IDS | XML_COMPLETE_ATTRS; + * ctxt->replaceEntities = 1; + * ... + */ + + +XMLPUBFUN int XMLCALL + xmlC14NDocSaveTo (xmlDocPtr doc, + xmlNodeSetPtr nodes, + int exclusive, + xmlChar **inclusive_ns_prefixes, + int with_comments, + xmlOutputBufferPtr buf); + +XMLPUBFUN int XMLCALL + xmlC14NDocDumpMemory (xmlDocPtr doc, + xmlNodeSetPtr nodes, + int exclusive, + xmlChar **inclusive_ns_prefixes, + int with_comments, + xmlChar **doc_txt_ptr); + +XMLPUBFUN int XMLCALL + xmlC14NDocSave (xmlDocPtr doc, + xmlNodeSetPtr nodes, + int exclusive, + xmlChar **inclusive_ns_prefixes, + int with_comments, + const char* filename, + int compression); + + +/** + * This is the core C14N function + */ +typedef int (*xmlC14NIsVisibleCallback) (void* user_data, + xmlNodePtr node, + xmlNodePtr parent); + +XMLPUBFUN int XMLCALL + xmlC14NExecute (xmlDocPtr doc, + xmlC14NIsVisibleCallback is_visible_callback, + void* user_data, + int exclusive, + xmlChar **inclusive_ns_prefixes, + int with_comments, + xmlOutputBufferPtr buf); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* LIBXML_OUTPUT_ENABLED */ +#endif /* LIBXML_C14N_ENABLED */ +#endif /* __XML_C14N_H__ */ + diff --git a/gettext-tools/gnulib-lib/libxml/catalog.c b/gettext-tools/gnulib-lib/libxml/catalog.c new file mode 100644 index 0000000..5456094 --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/catalog.c @@ -0,0 +1,3788 @@ +/** + * catalog.c: set of generic Catalog related routines + * + * Reference: SGML Open Technical Resolution TR9401:1997. + * http://www.jclark.com/sp/catalog.htm + * + * XML Catalogs Working Draft 06 August 2001 + * http://www.oasis-open.org/committees/entity/spec-2001-08-06.html + * + * See Copyright for the status of this software. + * + * Daniel.Veillard@imag.fr + */ + +#define IN_LIBXML +#include "libxml.h" + +#ifdef LIBXML_CATALOG_ENABLED +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_STAT_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_FCNTL_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_DELEGATE 50 +#define MAX_CATAL_DEPTH 50 + +/** + * TODO: + * + * macro to flag unimplemented blocks + * XML_CATALOG_PREFER user env to select between system/public prefered + * option. C.f. Richard Tobin + *> Just FYI, I am using an environment variable XML_CATALOG_PREFER with + *> values "system" and "public". I have made the default be "system" to + *> match yours. + */ +#define TODO \ + xmlGenericError(xmlGenericErrorContext, \ + "Unimplemented block at %s:%d\n", \ + __FILE__, __LINE__); + +#define XML_URN_PUBID "urn:publicid:" +#define XML_CATAL_BREAK ((xmlChar *) -1) +#ifndef XML_XML_DEFAULT_CATALOG +#define XML_XML_DEFAULT_CATALOG "file:///etc/xml/catalog" +#endif +#ifndef XML_SGML_DEFAULT_CATALOG +#define XML_SGML_DEFAULT_CATALOG "file:///etc/sgml/catalog" +#endif + +#if defined(_WIN32) && defined(_MSC_VER) +#undef XML_XML_DEFAULT_CATALOG +static char XML_XML_DEFAULT_CATALOG[256] = "file:///etc/xml/catalog"; +void* __stdcall GetModuleHandleA(const char*); +unsigned long __stdcall GetModuleFileNameA(void*, char*, unsigned long); +#endif + +static xmlChar *xmlCatalogNormalizePublic(const xmlChar *pubID); +static int xmlExpandCatalog(xmlCatalogPtr catal, const char *filename); + +/************************************************************************ + * * + * Types, all private * + * * + ************************************************************************/ + +typedef enum { + XML_CATA_REMOVED = -1, + XML_CATA_NONE = 0, + XML_CATA_CATALOG, + XML_CATA_BROKEN_CATALOG, + XML_CATA_NEXT_CATALOG, + XML_CATA_GROUP, + XML_CATA_PUBLIC, + XML_CATA_SYSTEM, + XML_CATA_REWRITE_SYSTEM, + XML_CATA_DELEGATE_PUBLIC, + XML_CATA_DELEGATE_SYSTEM, + XML_CATA_URI, + XML_CATA_REWRITE_URI, + XML_CATA_DELEGATE_URI, + SGML_CATA_SYSTEM, + SGML_CATA_PUBLIC, + SGML_CATA_ENTITY, + SGML_CATA_PENTITY, + SGML_CATA_DOCTYPE, + SGML_CATA_LINKTYPE, + SGML_CATA_NOTATION, + SGML_CATA_DELEGATE, + SGML_CATA_BASE, + SGML_CATA_CATALOG, + SGML_CATA_DOCUMENT, + SGML_CATA_SGMLDECL +} xmlCatalogEntryType; + +typedef struct _xmlCatalogEntry xmlCatalogEntry; +typedef xmlCatalogEntry *xmlCatalogEntryPtr; +struct _xmlCatalogEntry { + struct _xmlCatalogEntry *next; + struct _xmlCatalogEntry *parent; + struct _xmlCatalogEntry *children; + xmlCatalogEntryType type; + xmlChar *name; + xmlChar *value; + xmlChar *URL; /* The expanded URL using the base */ + xmlCatalogPrefer prefer; + int dealloc; + int depth; + struct _xmlCatalogEntry *group; +}; + +typedef enum { + XML_XML_CATALOG_TYPE = 1, + XML_SGML_CATALOG_TYPE +} xmlCatalogType; + +#define XML_MAX_SGML_CATA_DEPTH 10 +struct _xmlCatalog { + xmlCatalogType type; /* either XML or SGML */ + + /* + * SGML Catalogs are stored as a simple hash table of catalog entries + * Catalog stack to check against overflows when building the + * SGML catalog + */ + char *catalTab[XML_MAX_SGML_CATA_DEPTH]; /* stack of catals */ + int catalNr; /* Number of current catal streams */ + int catalMax; /* Max number of catal streams */ + xmlHashTablePtr sgml; + + /* + * XML Catalogs are stored as a tree of Catalog entries + */ + xmlCatalogPrefer prefer; + xmlCatalogEntryPtr xml; +}; + +/************************************************************************ + * * + * Global variables * + * * + ************************************************************************/ + +/* + * Those are preferences + */ +static int xmlDebugCatalogs = 0; /* used for debugging */ +static xmlCatalogAllow xmlCatalogDefaultAllow = XML_CATA_ALLOW_ALL; +static xmlCatalogPrefer xmlCatalogDefaultPrefer = XML_CATA_PREFER_PUBLIC; + +/* + * Hash table containing all the trees of XML catalogs parsed by + * the application. + */ +static xmlHashTablePtr xmlCatalogXMLFiles = NULL; + +/* + * The default catalog in use by the application + */ +static xmlCatalogPtr xmlDefaultCatalog = NULL; + +/* + * A mutex for modifying the shared global catalog(s) + * xmlDefaultCatalog tree. + * It also protects xmlCatalogXMLFiles + * The core of this readers/writer scheme is in xmlFetchXMLCatalogFile() + */ +static xmlRMutexPtr xmlCatalogMutex = NULL; + +/* + * Whether the catalog support was initialized. + */ +static int xmlCatalogInitialized = 0; + +/************************************************************************ + * * + * Catalog error handlers * + * * + ************************************************************************/ + +/** + * xmlCatalogErrMemory: + * @extra: extra informations + * + * Handle an out of memory condition + */ +static void +xmlCatalogErrMemory(const char *extra) +{ + __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_CATALOG, + XML_ERR_NO_MEMORY, XML_ERR_ERROR, NULL, 0, + extra, NULL, NULL, 0, 0, + "Memory allocation failed : %s\n", extra); +} + +/** + * xmlCatalogErr: + * @catal: the Catalog entry + * @node: the context node + * @msg: the error message + * @extra: extra informations + * + * Handle a catalog error + */ +static void +xmlCatalogErr(xmlCatalogEntryPtr catal, xmlNodePtr node, int error, + const char *msg, const xmlChar *str1, const xmlChar *str2, + const xmlChar *str3) +{ + __xmlRaiseError(NULL, NULL, NULL, catal, node, XML_FROM_CATALOG, + error, XML_ERR_ERROR, NULL, 0, + (const char *) str1, (const char *) str2, + (const char *) str3, 0, 0, + msg, str1, str2, str3); +} + + +/************************************************************************ + * * + * Allocation and Freeing * + * * + ************************************************************************/ + +/** + * xmlNewCatalogEntry: + * @type: type of entry + * @name: name of the entry + * @value: value of the entry + * @prefer: the PUBLIC vs. SYSTEM current preference value + * @group: for members of a group, the group entry + * + * create a new Catalog entry, this type is shared both by XML and + * SGML catalogs, but the acceptable types values differs. + * + * Returns the xmlCatalogEntryPtr or NULL in case of error + */ +static xmlCatalogEntryPtr +xmlNewCatalogEntry(xmlCatalogEntryType type, const xmlChar *name, + const xmlChar *value, const xmlChar *URL, xmlCatalogPrefer prefer, + xmlCatalogEntryPtr group) { + xmlCatalogEntryPtr ret; + xmlChar *normid = NULL; + + ret = (xmlCatalogEntryPtr) xmlMalloc(sizeof(xmlCatalogEntry)); + if (ret == NULL) { + xmlCatalogErrMemory("allocating catalog entry"); + return(NULL); + } + ret->next = NULL; + ret->parent = NULL; + ret->children = NULL; + ret->type = type; + if (type == XML_CATA_PUBLIC || type == XML_CATA_DELEGATE_PUBLIC) { + normid = xmlCatalogNormalizePublic(name); + if (normid != NULL) + name = (*normid != 0 ? normid : NULL); + } + if (name != NULL) + ret->name = xmlStrdup(name); + else + ret->name = NULL; + if (normid != NULL) + xmlFree(normid); + if (value != NULL) + ret->value = xmlStrdup(value); + else + ret->value = NULL; + if (URL == NULL) + URL = value; + if (URL != NULL) + ret->URL = xmlStrdup(URL); + else + ret->URL = NULL; + ret->prefer = prefer; + ret->dealloc = 0; + ret->depth = 0; + ret->group = group; + return(ret); +} + +static void +xmlFreeCatalogEntryList(xmlCatalogEntryPtr ret); + +/** + * xmlFreeCatalogEntry: + * @ret: a Catalog entry + * + * Free the memory allocated to a Catalog entry + */ +static void +xmlFreeCatalogEntry(xmlCatalogEntryPtr ret) { + if (ret == NULL) + return; + /* + * Entries stored in the file hash must be deallocated + * only by the file hash cleaner ! + */ + if (ret->dealloc == 1) + return; + + if (xmlDebugCatalogs) { + if (ret->name != NULL) + xmlGenericError(xmlGenericErrorContext, + "Free catalog entry %s\n", ret->name); + else if (ret->value != NULL) + xmlGenericError(xmlGenericErrorContext, + "Free catalog entry %s\n", ret->value); + else + xmlGenericError(xmlGenericErrorContext, + "Free catalog entry\n"); + } + + if (ret->name != NULL) + xmlFree(ret->name); + if (ret->value != NULL) + xmlFree(ret->value); + if (ret->URL != NULL) + xmlFree(ret->URL); + xmlFree(ret); +} + +/** + * xmlFreeCatalogEntryList: + * @ret: a Catalog entry list + * + * Free the memory allocated to a full chained list of Catalog entries + */ +static void +xmlFreeCatalogEntryList(xmlCatalogEntryPtr ret) { + xmlCatalogEntryPtr next; + + while (ret != NULL) { + next = ret->next; + xmlFreeCatalogEntry(ret); + ret = next; + } +} + +/** + * xmlFreeCatalogHashEntryList: + * @ret: a Catalog entry list + * + * Free the memory allocated to list of Catalog entries from the + * catalog file hash. + */ +static void +xmlFreeCatalogHashEntryList(xmlCatalogEntryPtr catal) { + xmlCatalogEntryPtr children, next; + + if (catal == NULL) + return; + + children = catal->children; + while (children != NULL) { + next = children->next; + children->dealloc = 0; + children->children = NULL; + xmlFreeCatalogEntry(children); + children = next; + } + catal->dealloc = 0; + xmlFreeCatalogEntry(catal); +} + +/** + * xmlCreateNewCatalog: + * @type: type of catalog + * @prefer: the PUBLIC vs. SYSTEM current preference value + * + * create a new Catalog, this type is shared both by XML and + * SGML catalogs, but the acceptable types values differs. + * + * Returns the xmlCatalogPtr or NULL in case of error + */ +static xmlCatalogPtr +xmlCreateNewCatalog(xmlCatalogType type, xmlCatalogPrefer prefer) { + xmlCatalogPtr ret; + + ret = (xmlCatalogPtr) xmlMalloc(sizeof(xmlCatalog)); + if (ret == NULL) { + xmlCatalogErrMemory("allocating catalog"); + return(NULL); + } + memset(ret, 0, sizeof(xmlCatalog)); + ret->type = type; + ret->catalNr = 0; + ret->catalMax = XML_MAX_SGML_CATA_DEPTH; + ret->prefer = prefer; + if (ret->type == XML_SGML_CATALOG_TYPE) + ret->sgml = xmlHashCreate(10); + return(ret); +} + +/** + * xmlFreeCatalog: + * @catal: a Catalog + * + * Free the memory allocated to a Catalog + */ +void +xmlFreeCatalog(xmlCatalogPtr catal) { + if (catal == NULL) + return; + if (catal->xml != NULL) + xmlFreeCatalogEntryList(catal->xml); + if (catal->sgml != NULL) + xmlHashFree(catal->sgml, + (xmlHashDeallocator) xmlFreeCatalogEntry); + xmlFree(catal); +} + +/************************************************************************ + * * + * Serializing Catalogs * + * * + ************************************************************************/ + +#ifdef LIBXML_OUTPUT_ENABLED +/** + * xmlCatalogDumpEntry: + * @entry: the catalog entry + * @out: the file. + * + * Serialize an SGML Catalog entry + */ +static void +xmlCatalogDumpEntry(xmlCatalogEntryPtr entry, FILE *out) { + if ((entry == NULL) || (out == NULL)) + return; + switch (entry->type) { + case SGML_CATA_ENTITY: + fprintf(out, "ENTITY "); break; + case SGML_CATA_PENTITY: + fprintf(out, "ENTITY %%"); break; + case SGML_CATA_DOCTYPE: + fprintf(out, "DOCTYPE "); break; + case SGML_CATA_LINKTYPE: + fprintf(out, "LINKTYPE "); break; + case SGML_CATA_NOTATION: + fprintf(out, "NOTATION "); break; + case SGML_CATA_PUBLIC: + fprintf(out, "PUBLIC "); break; + case SGML_CATA_SYSTEM: + fprintf(out, "SYSTEM "); break; + case SGML_CATA_DELEGATE: + fprintf(out, "DELEGATE "); break; + case SGML_CATA_BASE: + fprintf(out, "BASE "); break; + case SGML_CATA_CATALOG: + fprintf(out, "CATALOG "); break; + case SGML_CATA_DOCUMENT: + fprintf(out, "DOCUMENT "); break; + case SGML_CATA_SGMLDECL: + fprintf(out, "SGMLDECL "); break; + default: + return; + } + switch (entry->type) { + case SGML_CATA_ENTITY: + case SGML_CATA_PENTITY: + case SGML_CATA_DOCTYPE: + case SGML_CATA_LINKTYPE: + case SGML_CATA_NOTATION: + fprintf(out, "%s", (const char *) entry->name); break; + case SGML_CATA_PUBLIC: + case SGML_CATA_SYSTEM: + case SGML_CATA_SGMLDECL: + case SGML_CATA_DOCUMENT: + case SGML_CATA_CATALOG: + case SGML_CATA_BASE: + case SGML_CATA_DELEGATE: + fprintf(out, "\"%s\"", entry->name); break; + default: + break; + } + switch (entry->type) { + case SGML_CATA_ENTITY: + case SGML_CATA_PENTITY: + case SGML_CATA_DOCTYPE: + case SGML_CATA_LINKTYPE: + case SGML_CATA_NOTATION: + case SGML_CATA_PUBLIC: + case SGML_CATA_SYSTEM: + case SGML_CATA_DELEGATE: + fprintf(out, " \"%s\"", entry->value); break; + default: + break; + } + fprintf(out, "\n"); +} + +/** + * xmlDumpXMLCatalogNode: + * @catal: top catalog entry + * @catalog: pointer to the xml tree + * @doc: the containing document + * @ns: the current namespace + * @cgroup: group node for group members + * + * Serializes a Catalog entry, called by xmlDumpXMLCatalog and recursively + * for group entries + */ +static void xmlDumpXMLCatalogNode(xmlCatalogEntryPtr catal, xmlNodePtr catalog, + xmlDocPtr doc, xmlNsPtr ns, xmlCatalogEntryPtr cgroup) { + xmlNodePtr node; + xmlCatalogEntryPtr cur; + /* + * add all the catalog entries + */ + cur = catal; + while (cur != NULL) { + if (cur->group == cgroup) { + switch (cur->type) { + case XML_CATA_REMOVED: + break; + case XML_CATA_BROKEN_CATALOG: + case XML_CATA_CATALOG: + if (cur == catal) { + cur = cur->children; + continue; + } + break; + case XML_CATA_NEXT_CATALOG: + node = xmlNewDocNode(doc, ns, BAD_CAST "nextCatalog", NULL); + xmlSetProp(node, BAD_CAST "catalog", cur->value); + xmlAddChild(catalog, node); + break; + case XML_CATA_NONE: + break; + case XML_CATA_GROUP: + node = xmlNewDocNode(doc, ns, BAD_CAST "group", NULL); + xmlSetProp(node, BAD_CAST "id", cur->name); + if (cur->value != NULL) { + xmlNsPtr xns; + xns = xmlSearchNsByHref(doc, node, XML_XML_NAMESPACE); + if (xns != NULL) + xmlSetNsProp(node, xns, BAD_CAST "base", + cur->value); + } + switch (cur->prefer) { + case XML_CATA_PREFER_NONE: + break; + case XML_CATA_PREFER_PUBLIC: + xmlSetProp(node, BAD_CAST "prefer", BAD_CAST "public"); + break; + case XML_CATA_PREFER_SYSTEM: + xmlSetProp(node, BAD_CAST "prefer", BAD_CAST "system"); + break; + } + xmlDumpXMLCatalogNode(cur->next, node, doc, ns, cur); + xmlAddChild(catalog, node); + break; + case XML_CATA_PUBLIC: + node = xmlNewDocNode(doc, ns, BAD_CAST "public", NULL); + xmlSetProp(node, BAD_CAST "publicId", cur->name); + xmlSetProp(node, BAD_CAST "uri", cur->value); + xmlAddChild(catalog, node); + break; + case XML_CATA_SYSTEM: + node = xmlNewDocNode(doc, ns, BAD_CAST "system", NULL); + xmlSetProp(node, BAD_CAST "systemId", cur->name); + xmlSetProp(node, BAD_CAST "uri", cur->value); + xmlAddChild(catalog, node); + break; + case XML_CATA_REWRITE_SYSTEM: + node = xmlNewDocNode(doc, ns, BAD_CAST "rewriteSystem", NULL); + xmlSetProp(node, BAD_CAST "systemIdStartString", cur->name); + xmlSetProp(node, BAD_CAST "rewritePrefix", cur->value); + xmlAddChild(catalog, node); + break; + case XML_CATA_DELEGATE_PUBLIC: + node = xmlNewDocNode(doc, ns, BAD_CAST "delegatePublic", NULL); + xmlSetProp(node, BAD_CAST "publicIdStartString", cur->name); + xmlSetProp(node, BAD_CAST "catalog", cur->value); + xmlAddChild(catalog, node); + break; + case XML_CATA_DELEGATE_SYSTEM: + node = xmlNewDocNode(doc, ns, BAD_CAST "delegateSystem", NULL); + xmlSetProp(node, BAD_CAST "systemIdStartString", cur->name); + xmlSetProp(node, BAD_CAST "catalog", cur->value); + xmlAddChild(catalog, node); + break; + case XML_CATA_URI: + node = xmlNewDocNode(doc, ns, BAD_CAST "uri", NULL); + xmlSetProp(node, BAD_CAST "name", cur->name); + xmlSetProp(node, BAD_CAST "uri", cur->value); + xmlAddChild(catalog, node); + break; + case XML_CATA_REWRITE_URI: + node = xmlNewDocNode(doc, ns, BAD_CAST "rewriteURI", NULL); + xmlSetProp(node, BAD_CAST "uriStartString", cur->name); + xmlSetProp(node, BAD_CAST "rewritePrefix", cur->value); + xmlAddChild(catalog, node); + break; + case XML_CATA_DELEGATE_URI: + node = xmlNewDocNode(doc, ns, BAD_CAST "delegateURI", NULL); + xmlSetProp(node, BAD_CAST "uriStartString", cur->name); + xmlSetProp(node, BAD_CAST "catalog", cur->value); + xmlAddChild(catalog, node); + break; + case SGML_CATA_SYSTEM: + case SGML_CATA_PUBLIC: + case SGML_CATA_ENTITY: + case SGML_CATA_PENTITY: + case SGML_CATA_DOCTYPE: + case SGML_CATA_LINKTYPE: + case SGML_CATA_NOTATION: + case SGML_CATA_DELEGATE: + case SGML_CATA_BASE: + case SGML_CATA_CATALOG: + case SGML_CATA_DOCUMENT: + case SGML_CATA_SGMLDECL: + break; + } + } + cur = cur->next; + } +} + +static int +xmlDumpXMLCatalog(FILE *out, xmlCatalogEntryPtr catal) { + int ret; + xmlDocPtr doc; + xmlNsPtr ns; + xmlDtdPtr dtd; + xmlNodePtr catalog; + xmlOutputBufferPtr buf; + + /* + * Rebuild a catalog + */ + doc = xmlNewDoc(NULL); + if (doc == NULL) + return(-1); + dtd = xmlNewDtd(doc, BAD_CAST "catalog", + BAD_CAST "-//OASIS//DTD Entity Resolution XML Catalog V1.0//EN", +BAD_CAST "http://www.oasis-open.org/committees/entity/release/1.0/catalog.dtd"); + + xmlAddChild((xmlNodePtr) doc, (xmlNodePtr) dtd); + + ns = xmlNewNs(NULL, XML_CATALOGS_NAMESPACE, NULL); + if (ns == NULL) { + xmlFreeDoc(doc); + return(-1); + } + catalog = xmlNewDocNode(doc, ns, BAD_CAST "catalog", NULL); + if (catalog == NULL) { + xmlFreeNs(ns); + xmlFreeDoc(doc); + return(-1); + } + catalog->nsDef = ns; + xmlAddChild((xmlNodePtr) doc, catalog); + + xmlDumpXMLCatalogNode(catal, catalog, doc, ns, NULL); + + /* + * reserialize it + */ + buf = xmlOutputBufferCreateFile(out, NULL); + if (buf == NULL) { + xmlFreeDoc(doc); + return(-1); + } + ret = xmlSaveFormatFileTo(buf, doc, NULL, 1); + + /* + * Free it + */ + xmlFreeDoc(doc); + + return(ret); +} +#endif /* LIBXML_OUTPUT_ENABLED */ + +/************************************************************************ + * * + * Converting SGML Catalogs to XML * + * * + ************************************************************************/ + +/** + * xmlCatalogConvertEntry: + * @entry: the entry + * @catal: pointer to the catalog being converted + * + * Convert one entry from the catalog + */ +static void +xmlCatalogConvertEntry(xmlCatalogEntryPtr entry, xmlCatalogPtr catal) { + if ((entry == NULL) || (catal == NULL) || (catal->sgml == NULL) || + (catal->xml == NULL)) + return; + switch (entry->type) { + case SGML_CATA_ENTITY: + entry->type = XML_CATA_PUBLIC; + break; + case SGML_CATA_PENTITY: + entry->type = XML_CATA_PUBLIC; + break; + case SGML_CATA_DOCTYPE: + entry->type = XML_CATA_PUBLIC; + break; + case SGML_CATA_LINKTYPE: + entry->type = XML_CATA_PUBLIC; + break; + case SGML_CATA_NOTATION: + entry->type = XML_CATA_PUBLIC; + break; + case SGML_CATA_PUBLIC: + entry->type = XML_CATA_PUBLIC; + break; + case SGML_CATA_SYSTEM: + entry->type = XML_CATA_SYSTEM; + break; + case SGML_CATA_DELEGATE: + entry->type = XML_CATA_DELEGATE_PUBLIC; + break; + case SGML_CATA_CATALOG: + entry->type = XML_CATA_CATALOG; + break; + default: + xmlHashRemoveEntry(catal->sgml, entry->name, + (xmlHashDeallocator) xmlFreeCatalogEntry); + return; + } + /* + * Conversion successful, remove from the SGML catalog + * and add it to the default XML one + */ + xmlHashRemoveEntry(catal->sgml, entry->name, NULL); + entry->parent = catal->xml; + entry->next = NULL; + if (catal->xml->children == NULL) + catal->xml->children = entry; + else { + xmlCatalogEntryPtr prev; + + prev = catal->xml->children; + while (prev->next != NULL) + prev = prev->next; + prev->next = entry; + } +} + +/** + * xmlConvertSGMLCatalog: + * @catal: the catalog + * + * Convert all the SGML catalog entries as XML ones + * + * Returns the number of entries converted if successful, -1 otherwise + */ +int +xmlConvertSGMLCatalog(xmlCatalogPtr catal) { + + if ((catal == NULL) || (catal->type != XML_SGML_CATALOG_TYPE)) + return(-1); + + if (xmlDebugCatalogs) { + xmlGenericError(xmlGenericErrorContext, + "Converting SGML catalog to XML\n"); + } + xmlHashScan(catal->sgml, + (xmlHashScanner) xmlCatalogConvertEntry, + &catal); + return(0); +} + +/************************************************************************ + * * + * Helper function * + * * + ************************************************************************/ + +/** + * xmlCatalogUnWrapURN: + * @urn: an "urn:publicid:" to unwrap + * + * Expand the URN into the equivalent Public Identifier + * + * Returns the new identifier or NULL, the string must be deallocated + * by the caller. + */ +static xmlChar * +xmlCatalogUnWrapURN(const xmlChar *urn) { + xmlChar result[2000]; + unsigned int i = 0; + + if (xmlStrncmp(urn, BAD_CAST XML_URN_PUBID, sizeof(XML_URN_PUBID) - 1)) + return(NULL); + urn += sizeof(XML_URN_PUBID) - 1; + + while (*urn != 0) { + if (i > sizeof(result) - 4) + break; + if (*urn == '+') { + result[i++] = ' '; + urn++; + } else if (*urn == ':') { + result[i++] = '/'; + result[i++] = '/'; + urn++; + } else if (*urn == ';') { + result[i++] = ':'; + result[i++] = ':'; + urn++; + } else if (*urn == '%') { + if ((urn[1] == '2') && (urn[2] == 'B')) + result[i++] = '+'; + else if ((urn[1] == '3') && (urn[2] == 'A')) + result[i++] = ':'; + else if ((urn[1] == '2') && (urn[2] == 'F')) + result[i++] = '/'; + else if ((urn[1] == '3') && (urn[2] == 'B')) + result[i++] = ';'; + else if ((urn[1] == '2') && (urn[2] == '7')) + result[i++] = '\''; + else if ((urn[1] == '3') && (urn[2] == 'F')) + result[i++] = '?'; + else if ((urn[1] == '2') && (urn[2] == '3')) + result[i++] = '#'; + else if ((urn[1] == '2') && (urn[2] == '5')) + result[i++] = '%'; + else { + result[i++] = *urn; + urn++; + continue; + } + urn += 3; + } else { + result[i++] = *urn; + urn++; + } + } + result[i] = 0; + + return(xmlStrdup(result)); +} + +/** + * xmlParseCatalogFile: + * @filename: the filename + * + * parse an XML file and build a tree. It's like xmlParseFile() + * except it bypass all catalog lookups. + * + * Returns the resulting document tree or NULL in case of error + */ + +xmlDocPtr +xmlParseCatalogFile(const char *filename) { + xmlDocPtr ret; + xmlParserCtxtPtr ctxt; + char *directory = NULL; + xmlParserInputPtr inputStream; + xmlParserInputBufferPtr buf; + + ctxt = xmlNewParserCtxt(); + if (ctxt == NULL) { +#ifdef LIBXML_SAX1_ENABLED + if (xmlDefaultSAXHandler.error != NULL) { + xmlDefaultSAXHandler.error(NULL, "out of memory\n"); + } +#endif + return(NULL); + } + + buf = xmlParserInputBufferCreateFilename(filename, XML_CHAR_ENCODING_NONE); + if (buf == NULL) { + xmlFreeParserCtxt(ctxt); + return(NULL); + } + + inputStream = xmlNewInputStream(ctxt); + if (inputStream == NULL) { + xmlFreeParserCtxt(ctxt); + return(NULL); + } + + inputStream->filename = (char *) xmlCanonicPath((const xmlChar *)filename); + inputStream->buf = buf; + inputStream->base = inputStream->buf->buffer->content; + inputStream->cur = inputStream->buf->buffer->content; + inputStream->end = + &inputStream->buf->buffer->content[inputStream->buf->buffer->use]; + + inputPush(ctxt, inputStream); + if ((ctxt->directory == NULL) && (directory == NULL)) + directory = xmlParserGetDirectory(filename); + if ((ctxt->directory == NULL) && (directory != NULL)) + ctxt->directory = directory; + ctxt->valid = 0; + ctxt->validate = 0; + ctxt->loadsubset = 0; + ctxt->pedantic = 0; + ctxt->dictNames = 1; + + xmlParseDocument(ctxt); + + if (ctxt->wellFormed) + ret = ctxt->myDoc; + else { + ret = NULL; + xmlFreeDoc(ctxt->myDoc); + ctxt->myDoc = NULL; + } + xmlFreeParserCtxt(ctxt); + + return(ret); +} + +/** + * xmlLoadFileContent: + * @filename: a file path + * + * Load a file content into memory. + * + * Returns a pointer to the 0 terminated string or NULL in case of error + */ +static xmlChar * +xmlLoadFileContent(const char *filename) +{ +#ifdef HAVE_STAT + int fd; +#else + FILE *fd; +#endif + int len; + long size; + +#ifdef HAVE_STAT + struct stat info; +#endif + xmlChar *content; + + if (filename == NULL) + return (NULL); + +#ifdef HAVE_STAT + if (stat(filename, &info) < 0) + return (NULL); +#endif + +#ifdef HAVE_STAT + if ((fd = open(filename, O_RDONLY)) < 0) +#else + if ((fd = fopen(filename, "rb")) == NULL) +#endif + { + return (NULL); + } +#ifdef HAVE_STAT + size = info.st_size; +#else + if (fseek(fd, 0, SEEK_END) || (size = ftell(fd)) == EOF || fseek(fd, 0, SEEK_SET)) { /* File operations denied? ok, just close and return failure */ + fclose(fd); + return (NULL); + } +#endif + content = xmlMallocAtomic(size + 10); + if (content == NULL) { + xmlCatalogErrMemory("allocating catalog data"); + return (NULL); + } +#ifdef HAVE_STAT + len = read(fd, content, size); +#else + len = fread(content, 1, size, fd); +#endif + if (len < 0) { + xmlFree(content); + return (NULL); + } +#ifdef HAVE_STAT + close(fd); +#else + fclose(fd); +#endif + content[len] = 0; + + return(content); +} + +/** + * xmlCatalogNormalizePublic: + * @pubID: the public ID string + * + * Normalizes the Public Identifier + * + * Implements 6.2. Public Identifier Normalization + * from http://www.oasis-open.org/committees/entity/spec-2001-08-06.html + * + * Returns the new string or NULL, the string must be deallocated + * by the caller. + */ +static xmlChar * +xmlCatalogNormalizePublic(const xmlChar *pubID) +{ + int ok = 1; + int white; + const xmlChar *p; + xmlChar *ret; + xmlChar *q; + + if (pubID == NULL) + return(NULL); + + white = 1; + for (p = pubID;*p != 0 && ok;p++) { + if (!xmlIsBlank_ch(*p)) + white = 0; + else if (*p == 0x20 && !white) + white = 1; + else + ok = 0; + } + if (ok && !white) /* is normalized */ + return(NULL); + + ret = xmlStrdup(pubID); + q = ret; + white = 0; + for (p = pubID;*p != 0;p++) { + if (xmlIsBlank_ch(*p)) { + if (q != ret) + white = 1; + } else { + if (white) { + *(q++) = 0x20; + white = 0; + } + *(q++) = *p; + } + } + *q = 0; + return(ret); +} + +/************************************************************************ + * * + * The XML Catalog parser * + * * + ************************************************************************/ + +static xmlCatalogEntryPtr +xmlParseXMLCatalogFile(xmlCatalogPrefer prefer, const xmlChar *filename); +static void +xmlParseXMLCatalogNodeList(xmlNodePtr cur, xmlCatalogPrefer prefer, + xmlCatalogEntryPtr parent, xmlCatalogEntryPtr cgroup); +static xmlChar * +xmlCatalogListXMLResolve(xmlCatalogEntryPtr catal, const xmlChar *pubID, + const xmlChar *sysID); +static xmlChar * +xmlCatalogListXMLResolveURI(xmlCatalogEntryPtr catal, const xmlChar *URI); + + +/** + * xmlGetXMLCatalogEntryType: + * @name: the name + * + * lookup the internal type associated to an XML catalog entry name + * + * Returns the type associated with that name + */ +static xmlCatalogEntryType +xmlGetXMLCatalogEntryType(const xmlChar *name) { + xmlCatalogEntryType type = XML_CATA_NONE; + if (xmlStrEqual(name, (const xmlChar *) "system")) + type = XML_CATA_SYSTEM; + else if (xmlStrEqual(name, (const xmlChar *) "public")) + type = XML_CATA_PUBLIC; + else if (xmlStrEqual(name, (const xmlChar *) "rewriteSystem")) + type = XML_CATA_REWRITE_SYSTEM; + else if (xmlStrEqual(name, (const xmlChar *) "delegatePublic")) + type = XML_CATA_DELEGATE_PUBLIC; + else if (xmlStrEqual(name, (const xmlChar *) "delegateSystem")) + type = XML_CATA_DELEGATE_SYSTEM; + else if (xmlStrEqual(name, (const xmlChar *) "uri")) + type = XML_CATA_URI; + else if (xmlStrEqual(name, (const xmlChar *) "rewriteURI")) + type = XML_CATA_REWRITE_URI; + else if (xmlStrEqual(name, (const xmlChar *) "delegateURI")) + type = XML_CATA_DELEGATE_URI; + else if (xmlStrEqual(name, (const xmlChar *) "nextCatalog")) + type = XML_CATA_NEXT_CATALOG; + else if (xmlStrEqual(name, (const xmlChar *) "catalog")) + type = XML_CATA_CATALOG; + return(type); +} + +/** + * xmlParseXMLCatalogOneNode: + * @cur: the XML node + * @type: the type of Catalog entry + * @name: the name of the node + * @attrName: the attribute holding the value + * @uriAttrName: the attribute holding the URI-Reference + * @prefer: the PUBLIC vs. SYSTEM current preference value + * @cgroup: the group which includes this node + * + * Finishes the examination of an XML tree node of a catalog and build + * a Catalog entry from it. + * + * Returns the new Catalog entry node or NULL in case of error. + */ +static xmlCatalogEntryPtr +xmlParseXMLCatalogOneNode(xmlNodePtr cur, xmlCatalogEntryType type, + const xmlChar *name, const xmlChar *attrName, + const xmlChar *uriAttrName, xmlCatalogPrefer prefer, + xmlCatalogEntryPtr cgroup) { + int ok = 1; + xmlChar *uriValue; + xmlChar *nameValue = NULL; + xmlChar *base = NULL; + xmlChar *URL = NULL; + xmlCatalogEntryPtr ret = NULL; + + if (attrName != NULL) { + nameValue = xmlGetProp(cur, attrName); + if (nameValue == NULL) { + xmlCatalogErr(ret, cur, XML_CATALOG_MISSING_ATTR, + "%s entry lacks '%s'\n", name, attrName, NULL); + ok = 0; + } + } + uriValue = xmlGetProp(cur, uriAttrName); + if (uriValue == NULL) { + xmlCatalogErr(ret, cur, XML_CATALOG_MISSING_ATTR, + "%s entry lacks '%s'\n", name, uriAttrName, NULL); + ok = 0; + } + if (!ok) { + if (nameValue != NULL) + xmlFree(nameValue); + if (uriValue != NULL) + xmlFree(uriValue); + return(NULL); + } + + base = xmlNodeGetBase(cur->doc, cur); + URL = xmlBuildURI(uriValue, base); + if (URL != NULL) { + if (xmlDebugCatalogs > 1) { + if (nameValue != NULL) + xmlGenericError(xmlGenericErrorContext, + "Found %s: '%s' '%s'\n", name, nameValue, URL); + else + xmlGenericError(xmlGenericErrorContext, + "Found %s: '%s'\n", name, URL); + } + ret = xmlNewCatalogEntry(type, nameValue, uriValue, URL, prefer, cgroup); + } else { + xmlCatalogErr(ret, cur, XML_CATALOG_ENTRY_BROKEN, + "%s entry '%s' broken ?: %s\n", name, uriAttrName, uriValue); + } + if (nameValue != NULL) + xmlFree(nameValue); + if (uriValue != NULL) + xmlFree(uriValue); + if (base != NULL) + xmlFree(base); + if (URL != NULL) + xmlFree(URL); + return(ret); +} + +/** + * xmlParseXMLCatalogNode: + * @cur: the XML node + * @prefer: the PUBLIC vs. SYSTEM current preference value + * @parent: the parent Catalog entry + * @cgroup: the group which includes this node + * + * Examines an XML tree node of a catalog and build + * a Catalog entry from it adding it to its parent. The examination can + * be recursive. + */ +static void +xmlParseXMLCatalogNode(xmlNodePtr cur, xmlCatalogPrefer prefer, + xmlCatalogEntryPtr parent, xmlCatalogEntryPtr cgroup) +{ + xmlChar *base = NULL; + xmlCatalogEntryPtr entry = NULL; + + if (cur == NULL) + return; + if (xmlStrEqual(cur->name, BAD_CAST "group")) { + xmlChar *prop; + xmlCatalogPrefer pref = XML_CATA_PREFER_NONE; + + prop = xmlGetProp(cur, BAD_CAST "prefer"); + if (prop != NULL) { + if (xmlStrEqual(prop, BAD_CAST "system")) { + prefer = XML_CATA_PREFER_SYSTEM; + } else if (xmlStrEqual(prop, BAD_CAST "public")) { + prefer = XML_CATA_PREFER_PUBLIC; + } else { + xmlCatalogErr(parent, cur, XML_CATALOG_PREFER_VALUE, + "Invalid value for prefer: '%s'\n", + prop, NULL, NULL); + } + xmlFree(prop); + pref = prefer; + } + prop = xmlGetProp(cur, BAD_CAST "id"); + base = xmlGetNsProp(cur, BAD_CAST "base", XML_XML_NAMESPACE); + entry = xmlNewCatalogEntry(XML_CATA_GROUP, prop, base, NULL, pref, cgroup); + xmlFree(prop); + } else if (xmlStrEqual(cur->name, BAD_CAST "public")) { + entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_PUBLIC, + BAD_CAST "public", BAD_CAST "publicId", BAD_CAST "uri", prefer, cgroup); + } else if (xmlStrEqual(cur->name, BAD_CAST "system")) { + entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_SYSTEM, + BAD_CAST "system", BAD_CAST "systemId", BAD_CAST "uri", prefer, cgroup); + } else if (xmlStrEqual(cur->name, BAD_CAST "rewriteSystem")) { + entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_REWRITE_SYSTEM, + BAD_CAST "rewriteSystem", BAD_CAST "systemIdStartString", + BAD_CAST "rewritePrefix", prefer, cgroup); + } else if (xmlStrEqual(cur->name, BAD_CAST "delegatePublic")) { + entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_DELEGATE_PUBLIC, + BAD_CAST "delegatePublic", BAD_CAST "publicIdStartString", + BAD_CAST "catalog", prefer, cgroup); + } else if (xmlStrEqual(cur->name, BAD_CAST "delegateSystem")) { + entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_DELEGATE_SYSTEM, + BAD_CAST "delegateSystem", BAD_CAST "systemIdStartString", + BAD_CAST "catalog", prefer, cgroup); + } else if (xmlStrEqual(cur->name, BAD_CAST "uri")) { + entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_URI, + BAD_CAST "uri", BAD_CAST "name", + BAD_CAST "uri", prefer, cgroup); + } else if (xmlStrEqual(cur->name, BAD_CAST "rewriteURI")) { + entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_REWRITE_URI, + BAD_CAST "rewriteURI", BAD_CAST "uriStartString", + BAD_CAST "rewritePrefix", prefer, cgroup); + } else if (xmlStrEqual(cur->name, BAD_CAST "delegateURI")) { + entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_DELEGATE_URI, + BAD_CAST "delegateURI", BAD_CAST "uriStartString", + BAD_CAST "catalog", prefer, cgroup); + } else if (xmlStrEqual(cur->name, BAD_CAST "nextCatalog")) { + entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_NEXT_CATALOG, + BAD_CAST "nextCatalog", NULL, + BAD_CAST "catalog", prefer, cgroup); + } + if (entry != NULL) { + if (parent != NULL) { + entry->parent = parent; + if (parent->children == NULL) + parent->children = entry; + else { + xmlCatalogEntryPtr prev; + + prev = parent->children; + while (prev->next != NULL) + prev = prev->next; + prev->next = entry; + } + } + if (entry->type == XML_CATA_GROUP) { + /* + * Recurse to propagate prefer to the subtree + * (xml:base handling is automated) + */ + xmlParseXMLCatalogNodeList(cur->children, prefer, parent, entry); + } + } + if (base != NULL) + xmlFree(base); +} + +/** + * xmlParseXMLCatalogNodeList: + * @cur: the XML node list of siblings + * @prefer: the PUBLIC vs. SYSTEM current preference value + * @parent: the parent Catalog entry + * @cgroup: the group which includes this list + * + * Examines a list of XML sibling nodes of a catalog and build + * a list of Catalog entry from it adding it to the parent. + * The examination will recurse to examine node subtrees. + */ +static void +xmlParseXMLCatalogNodeList(xmlNodePtr cur, xmlCatalogPrefer prefer, + xmlCatalogEntryPtr parent, xmlCatalogEntryPtr cgroup) { + while (cur != NULL) { + if ((cur->ns != NULL) && (cur->ns->href != NULL) && + (xmlStrEqual(cur->ns->href, XML_CATALOGS_NAMESPACE))) { + xmlParseXMLCatalogNode(cur, prefer, parent, cgroup); + } + cur = cur->next; + } + /* TODO: sort the list according to REWRITE lengths and prefer value */ +} + +/** + * xmlParseXMLCatalogFile: + * @prefer: the PUBLIC vs. SYSTEM current preference value + * @filename: the filename for the catalog + * + * Parses the catalog file to extract the XML tree and then analyze the + * tree to build a list of Catalog entries corresponding to this catalog + * + * Returns the resulting Catalog entries list + */ +static xmlCatalogEntryPtr +xmlParseXMLCatalogFile(xmlCatalogPrefer prefer, const xmlChar *filename) { + xmlDocPtr doc; + xmlNodePtr cur; + xmlChar *prop; + xmlCatalogEntryPtr parent = NULL; + + if (filename == NULL) + return(NULL); + + doc = xmlParseCatalogFile((const char *) filename); + if (doc == NULL) { + if (xmlDebugCatalogs) + xmlGenericError(xmlGenericErrorContext, + "Failed to parse catalog %s\n", filename); + return(NULL); + } + + if (xmlDebugCatalogs) + xmlGenericError(xmlGenericErrorContext, + "%d Parsing catalog %s\n", xmlGetThreadId(), filename); + + cur = xmlDocGetRootElement(doc); + if ((cur != NULL) && (xmlStrEqual(cur->name, BAD_CAST "catalog")) && + (cur->ns != NULL) && (cur->ns->href != NULL) && + (xmlStrEqual(cur->ns->href, XML_CATALOGS_NAMESPACE))) { + + parent = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL, + (const xmlChar *)filename, NULL, prefer, NULL); + if (parent == NULL) { + xmlFreeDoc(doc); + return(NULL); + } + + prop = xmlGetProp(cur, BAD_CAST "prefer"); + if (prop != NULL) { + if (xmlStrEqual(prop, BAD_CAST "system")) { + prefer = XML_CATA_PREFER_SYSTEM; + } else if (xmlStrEqual(prop, BAD_CAST "public")) { + prefer = XML_CATA_PREFER_PUBLIC; + } else { + xmlCatalogErr(NULL, cur, XML_CATALOG_PREFER_VALUE, + "Invalid value for prefer: '%s'\n", + prop, NULL, NULL); + } + xmlFree(prop); + } + cur = cur->children; + xmlParseXMLCatalogNodeList(cur, prefer, parent, NULL); + } else { + xmlCatalogErr(NULL, (xmlNodePtr) doc, XML_CATALOG_NOT_CATALOG, + "File %s is not an XML Catalog\n", + filename, NULL, NULL); + xmlFreeDoc(doc); + return(NULL); + } + xmlFreeDoc(doc); + return(parent); +} + +/** + * xmlFetchXMLCatalogFile: + * @catal: an existing but incomplete catalog entry + * + * Fetch and parse the subcatalog referenced by an entry + * + * Returns 0 in case of success, -1 otherwise + */ +static int +xmlFetchXMLCatalogFile(xmlCatalogEntryPtr catal) { + xmlCatalogEntryPtr doc; + + if (catal == NULL) + return(-1); + if (catal->URL == NULL) + return(-1); + if (catal->children != NULL) + return(-1); + + /* + * lock the whole catalog for modification + */ + xmlRMutexLock(xmlCatalogMutex); + if (catal->children != NULL) { + /* Okay someone else did it in the meantime */ + xmlRMutexUnlock(xmlCatalogMutex); + return(0); + } + + if (xmlCatalogXMLFiles != NULL) { + doc = (xmlCatalogEntryPtr) + xmlHashLookup(xmlCatalogXMLFiles, catal->URL); + if (doc != NULL) { + if (xmlDebugCatalogs) + xmlGenericError(xmlGenericErrorContext, + "Found %s in file hash\n", catal->URL); + + if (catal->type == XML_CATA_CATALOG) + catal->children = doc->children; + else + catal->children = doc; + catal->dealloc = 0; + xmlRMutexUnlock(xmlCatalogMutex); + return(0); + } + if (xmlDebugCatalogs) + xmlGenericError(xmlGenericErrorContext, + "%s not found in file hash\n", catal->URL); + } + + /* + * Fetch and parse. Note that xmlParseXMLCatalogFile does not + * use the existing catalog, there is no recursion allowed at + * that level. + */ + doc = xmlParseXMLCatalogFile(catal->prefer, catal->URL); + if (doc == NULL) { + catal->type = XML_CATA_BROKEN_CATALOG; + xmlRMutexUnlock(xmlCatalogMutex); + return(-1); + } + + if (catal->type == XML_CATA_CATALOG) + catal->children = doc->children; + else + catal->children = doc; + + doc->dealloc = 1; + + if (xmlCatalogXMLFiles == NULL) + xmlCatalogXMLFiles = xmlHashCreate(10); + if (xmlCatalogXMLFiles != NULL) { + if (xmlDebugCatalogs) + xmlGenericError(xmlGenericErrorContext, + "%s added to file hash\n", catal->URL); + xmlHashAddEntry(xmlCatalogXMLFiles, catal->URL, doc); + } + xmlRMutexUnlock(xmlCatalogMutex); + return(0); +} + +/************************************************************************ + * * + * XML Catalog handling * + * * + ************************************************************************/ + +/** + * xmlAddXMLCatalog: + * @catal: top of an XML catalog + * @type: the type of record to add to the catalog + * @orig: the system, public or prefix to match (or NULL) + * @replace: the replacement value for the match + * + * Add an entry in the XML catalog, it may overwrite existing but + * different entries. + * + * Returns 0 if successful, -1 otherwise + */ +static int +xmlAddXMLCatalog(xmlCatalogEntryPtr catal, const xmlChar *type, + const xmlChar *orig, const xmlChar *replace) { + xmlCatalogEntryPtr cur; + xmlCatalogEntryType typ; + int doregister = 0; + + if ((catal == NULL) || + ((catal->type != XML_CATA_CATALOG) && + (catal->type != XML_CATA_BROKEN_CATALOG))) + return(-1); + if (catal->children == NULL) { + xmlFetchXMLCatalogFile(catal); + } + if (catal->children == NULL) + doregister = 1; + + typ = xmlGetXMLCatalogEntryType(type); + if (typ == XML_CATA_NONE) { + if (xmlDebugCatalogs) + xmlGenericError(xmlGenericErrorContext, + "Failed to add unknown element %s to catalog\n", type); + return(-1); + } + + cur = catal->children; + /* + * Might be a simple "update in place" + */ + if (cur != NULL) { + while (cur != NULL) { + if ((orig != NULL) && (cur->type == typ) && + (xmlStrEqual(orig, cur->name))) { + if (xmlDebugCatalogs) + xmlGenericError(xmlGenericErrorContext, + "Updating element %s to catalog\n", type); + if (cur->value != NULL) + xmlFree(cur->value); + if (cur->URL != NULL) + xmlFree(cur->URL); + cur->value = xmlStrdup(replace); + cur->URL = xmlStrdup(replace); + return(0); + } + if (cur->next == NULL) + break; + cur = cur->next; + } + } + if (xmlDebugCatalogs) + xmlGenericError(xmlGenericErrorContext, + "Adding element %s to catalog\n", type); + if (cur == NULL) + catal->children = xmlNewCatalogEntry(typ, orig, replace, + NULL, catal->prefer, NULL); + else + cur->next = xmlNewCatalogEntry(typ, orig, replace, + NULL, catal->prefer, NULL); + if (doregister) { + catal->type = XML_CATA_CATALOG; + cur = xmlHashLookup(xmlCatalogXMLFiles, catal->URL); + if (cur != NULL) + cur->children = catal->children; + } + + return(0); +} + +/** + * xmlDelXMLCatalog: + * @catal: top of an XML catalog + * @value: the value to remove from the catalog + * + * Remove entries in the XML catalog where the value or the URI + * is equal to @value + * + * Returns the number of entries removed if successful, -1 otherwise + */ +static int +xmlDelXMLCatalog(xmlCatalogEntryPtr catal, const xmlChar *value) { + xmlCatalogEntryPtr cur; + int ret = 0; + + if ((catal == NULL) || + ((catal->type != XML_CATA_CATALOG) && + (catal->type != XML_CATA_BROKEN_CATALOG))) + return(-1); + if (value == NULL) + return(-1); + if (catal->children == NULL) { + xmlFetchXMLCatalogFile(catal); + } + + /* + * Scan the children + */ + cur = catal->children; + while (cur != NULL) { + if (((cur->name != NULL) && (xmlStrEqual(value, cur->name))) || + (xmlStrEqual(value, cur->value))) { + if (xmlDebugCatalogs) { + if (cur->name != NULL) + xmlGenericError(xmlGenericErrorContext, + "Removing element %s from catalog\n", cur->name); + else + xmlGenericError(xmlGenericErrorContext, + "Removing element %s from catalog\n", cur->value); + } + cur->type = XML_CATA_REMOVED; + } + cur = cur->next; + } + return(ret); +} + +/** + * xmlCatalogXMLResolve: + * @catal: a catalog list + * @pubID: the public ID string + * @sysID: the system ID string + * + * Do a complete resolution lookup of an External Identifier for a + * list of catalog entries. + * + * Implements (or tries to) 7.1. External Identifier Resolution + * from http://www.oasis-open.org/committees/entity/spec-2001-08-06.html + * + * Returns the URI of the resource or NULL if not found + */ +static xmlChar * +xmlCatalogXMLResolve(xmlCatalogEntryPtr catal, const xmlChar *pubID, + const xmlChar *sysID) { + xmlChar *ret = NULL; + xmlCatalogEntryPtr cur; + int haveDelegate = 0; + int haveNext = 0; + + /* + * protection against loops + */ + if (catal->depth > MAX_CATAL_DEPTH) { + xmlCatalogErr(catal, NULL, XML_CATALOG_RECURSION, + "Detected recursion in catalog %s\n", + catal->name, NULL, NULL); + return(NULL); + } + catal->depth++; + + /* + * First tries steps 2/ 3/ 4/ if a system ID is provided. + */ + if (sysID != NULL) { + xmlCatalogEntryPtr rewrite = NULL; + int lenrewrite = 0, len; + cur = catal; + haveDelegate = 0; + while (cur != NULL) { + switch (cur->type) { + case XML_CATA_SYSTEM: + if (xmlStrEqual(sysID, cur->name)) { + if (xmlDebugCatalogs) + xmlGenericError(xmlGenericErrorContext, + "Found system match %s, using %s\n", + cur->name, cur->URL); + catal->depth--; + return(xmlStrdup(cur->URL)); + } + break; + case XML_CATA_REWRITE_SYSTEM: + len = xmlStrlen(cur->name); + if ((len > lenrewrite) && + (!xmlStrncmp(sysID, cur->name, len))) { + lenrewrite = len; + rewrite = cur; + } + break; + case XML_CATA_DELEGATE_SYSTEM: + if (!xmlStrncmp(sysID, cur->name, xmlStrlen(cur->name))) + haveDelegate++; + break; + case XML_CATA_NEXT_CATALOG: + haveNext++; + break; + default: + break; + } + cur = cur->next; + } + if (rewrite != NULL) { + if (xmlDebugCatalogs) + xmlGenericError(xmlGenericErrorContext, + "Using rewriting rule %s\n", rewrite->name); + ret = xmlStrdup(rewrite->URL); + if (ret != NULL) + ret = xmlStrcat(ret, &sysID[lenrewrite]); + catal->depth--; + return(ret); + } + if (haveDelegate) { + const xmlChar *delegates[MAX_DELEGATE]; + int nbList = 0, i; + + /* + * Assume the entries have been sorted by decreasing substring + * matches when the list was produced. + */ + cur = catal; + while (cur != NULL) { + if ((cur->type == XML_CATA_DELEGATE_SYSTEM) && + (!xmlStrncmp(sysID, cur->name, xmlStrlen(cur->name)))) { + for (i = 0;i < nbList;i++) + if (xmlStrEqual(cur->URL, delegates[i])) + break; + if (i < nbList) { + cur = cur->next; + continue; + } + if (nbList < MAX_DELEGATE) + delegates[nbList++] = cur->URL; + + if (cur->children == NULL) { + xmlFetchXMLCatalogFile(cur); + } + if (cur->children != NULL) { + if (xmlDebugCatalogs) + xmlGenericError(xmlGenericErrorContext, + "Trying system delegate %s\n", cur->URL); + ret = xmlCatalogListXMLResolve( + cur->children, NULL, sysID); + if (ret != NULL) { + catal->depth--; + return(ret); + } + } + } + cur = cur->next; + } + /* + * Apply the cut algorithm explained in 4/ + */ + catal->depth--; + return(XML_CATAL_BREAK); + } + } + /* + * Then tries 5/ 6/ if a public ID is provided + */ + if (pubID != NULL) { + cur = catal; + haveDelegate = 0; + while (cur != NULL) { + switch (cur->type) { + case XML_CATA_PUBLIC: + if (xmlStrEqual(pubID, cur->name)) { + if (xmlDebugCatalogs) + xmlGenericError(xmlGenericErrorContext, + "Found public match %s\n", cur->name); + catal->depth--; + return(xmlStrdup(cur->URL)); + } + break; + case XML_CATA_DELEGATE_PUBLIC: + if (!xmlStrncmp(pubID, cur->name, xmlStrlen(cur->name)) && + (cur->prefer == XML_CATA_PREFER_PUBLIC)) + haveDelegate++; + break; + case XML_CATA_NEXT_CATALOG: + if (sysID == NULL) + haveNext++; + break; + default: + break; + } + cur = cur->next; + } + if (haveDelegate) { + const xmlChar *delegates[MAX_DELEGATE]; + int nbList = 0, i; + + /* + * Assume the entries have been sorted by decreasing substring + * matches when the list was produced. + */ + cur = catal; + while (cur != NULL) { + if ((cur->type == XML_CATA_DELEGATE_PUBLIC) && + (cur->prefer == XML_CATA_PREFER_PUBLIC) && + (!xmlStrncmp(pubID, cur->name, xmlStrlen(cur->name)))) { + + for (i = 0;i < nbList;i++) + if (xmlStrEqual(cur->URL, delegates[i])) + break; + if (i < nbList) { + cur = cur->next; + continue; + } + if (nbList < MAX_DELEGATE) + delegates[nbList++] = cur->URL; + + if (cur->children == NULL) { + xmlFetchXMLCatalogFile(cur); + } + if (cur->children != NULL) { + if (xmlDebugCatalogs) + xmlGenericError(xmlGenericErrorContext, + "Trying public delegate %s\n", cur->URL); + ret = xmlCatalogListXMLResolve( + cur->children, pubID, NULL); + if (ret != NULL) { + catal->depth--; + return(ret); + } + } + } + cur = cur->next; + } + /* + * Apply the cut algorithm explained in 4/ + */ + catal->depth--; + return(XML_CATAL_BREAK); + } + } + if (haveNext) { + cur = catal; + while (cur != NULL) { + if (cur->type == XML_CATA_NEXT_CATALOG) { + if (cur->children == NULL) { + xmlFetchXMLCatalogFile(cur); + } + if (cur->children != NULL) { + ret = xmlCatalogListXMLResolve(cur->children, pubID, sysID); + if (ret != NULL) { + catal->depth--; + return(ret); + } + } + } + cur = cur->next; + } + } + + catal->depth--; + return(NULL); +} + +/** + * xmlCatalogXMLResolveURI: + * @catal: a catalog list + * @URI: the URI + * @sysID: the system ID string + * + * Do a complete resolution lookup of an External Identifier for a + * list of catalog entries. + * + * Implements (or tries to) 7.2.2. URI Resolution + * from http://www.oasis-open.org/committees/entity/spec-2001-08-06.html + * + * Returns the URI of the resource or NULL if not found + */ +static xmlChar * +xmlCatalogXMLResolveURI(xmlCatalogEntryPtr catal, const xmlChar *URI) { + xmlChar *ret = NULL; + xmlCatalogEntryPtr cur; + int haveDelegate = 0; + int haveNext = 0; + xmlCatalogEntryPtr rewrite = NULL; + int lenrewrite = 0, len; + + if (catal == NULL) + return(NULL); + + if (URI == NULL) + return(NULL); + + /* + * First tries steps 2/ 3/ 4/ if a system ID is provided. + */ + cur = catal; + haveDelegate = 0; + while (cur != NULL) { + switch (cur->type) { + case XML_CATA_URI: + if (xmlStrEqual(URI, cur->name)) { + if (xmlDebugCatalogs) + xmlGenericError(xmlGenericErrorContext, + "Found URI match %s\n", cur->name); + return(xmlStrdup(cur->URL)); + } + break; + case XML_CATA_REWRITE_URI: + len = xmlStrlen(cur->name); + if ((len > lenrewrite) && + (!xmlStrncmp(URI, cur->name, len))) { + lenrewrite = len; + rewrite = cur; + } + break; + case XML_CATA_DELEGATE_URI: + if (!xmlStrncmp(URI, cur->name, xmlStrlen(cur->name))) + haveDelegate++; + break; + case XML_CATA_NEXT_CATALOG: + haveNext++; + break; + default: + break; + } + cur = cur->next; + } + if (rewrite != NULL) { + if (xmlDebugCatalogs) + xmlGenericError(xmlGenericErrorContext, + "Using rewriting rule %s\n", rewrite->name); + ret = xmlStrdup(rewrite->URL); + if (ret != NULL) + ret = xmlStrcat(ret, &URI[lenrewrite]); + return(ret); + } + if (haveDelegate) { + const xmlChar *delegates[MAX_DELEGATE]; + int nbList = 0, i; + + /* + * Assume the entries have been sorted by decreasing substring + * matches when the list was produced. + */ + cur = catal; + while (cur != NULL) { + if (((cur->type == XML_CATA_DELEGATE_SYSTEM) || + (cur->type == XML_CATA_DELEGATE_URI)) && + (!xmlStrncmp(URI, cur->name, xmlStrlen(cur->name)))) { + for (i = 0;i < nbList;i++) + if (xmlStrEqual(cur->URL, delegates[i])) + break; + if (i < nbList) { + cur = cur->next; + continue; + } + if (nbList < MAX_DELEGATE) + delegates[nbList++] = cur->URL; + + if (cur->children == NULL) { + xmlFetchXMLCatalogFile(cur); + } + if (cur->children != NULL) { + if (xmlDebugCatalogs) + xmlGenericError(xmlGenericErrorContext, + "Trying URI delegate %s\n", cur->URL); + ret = xmlCatalogListXMLResolveURI( + cur->children, URI); + if (ret != NULL) + return(ret); + } + } + cur = cur->next; + } + /* + * Apply the cut algorithm explained in 4/ + */ + return(XML_CATAL_BREAK); + } + if (haveNext) { + cur = catal; + while (cur != NULL) { + if (cur->type == XML_CATA_NEXT_CATALOG) { + if (cur->children == NULL) { + xmlFetchXMLCatalogFile(cur); + } + if (cur->children != NULL) { + ret = xmlCatalogListXMLResolveURI(cur->children, URI); + if (ret != NULL) + return(ret); + } + } + cur = cur->next; + } + } + + return(NULL); +} + +/** + * xmlCatalogListXMLResolve: + * @catal: a catalog list + * @pubID: the public ID string + * @sysID: the system ID string + * + * Do a complete resolution lookup of an External Identifier for a + * list of catalogs + * + * Implements (or tries to) 7.1. External Identifier Resolution + * from http://www.oasis-open.org/committees/entity/spec-2001-08-06.html + * + * Returns the URI of the resource or NULL if not found + */ +static xmlChar * +xmlCatalogListXMLResolve(xmlCatalogEntryPtr catal, const xmlChar *pubID, + const xmlChar *sysID) { + xmlChar *ret = NULL; + xmlChar *urnID = NULL; + xmlChar *normid; + + if (catal == NULL) + return(NULL); + if ((pubID == NULL) && (sysID == NULL)) + return(NULL); + + normid = xmlCatalogNormalizePublic(pubID); + if (normid != NULL) + pubID = (*normid != 0 ? normid : NULL); + + if (!xmlStrncmp(pubID, BAD_CAST XML_URN_PUBID, sizeof(XML_URN_PUBID) - 1)) { + urnID = xmlCatalogUnWrapURN(pubID); + if (xmlDebugCatalogs) { + if (urnID == NULL) + xmlGenericError(xmlGenericErrorContext, + "Public URN ID %s expanded to NULL\n", pubID); + else + xmlGenericError(xmlGenericErrorContext, + "Public URN ID expanded to %s\n", urnID); + } + ret = xmlCatalogListXMLResolve(catal, urnID, sysID); + if (urnID != NULL) + xmlFree(urnID); + if (normid != NULL) + xmlFree(normid); + return(ret); + } + if (!xmlStrncmp(sysID, BAD_CAST XML_URN_PUBID, sizeof(XML_URN_PUBID) - 1)) { + urnID = xmlCatalogUnWrapURN(sysID); + if (xmlDebugCatalogs) { + if (urnID == NULL) + xmlGenericError(xmlGenericErrorContext, + "System URN ID %s expanded to NULL\n", sysID); + else + xmlGenericError(xmlGenericErrorContext, + "System URN ID expanded to %s\n", urnID); + } + if (pubID == NULL) + ret = xmlCatalogListXMLResolve(catal, urnID, NULL); + else if (xmlStrEqual(pubID, urnID)) + ret = xmlCatalogListXMLResolve(catal, pubID, NULL); + else { + ret = xmlCatalogListXMLResolve(catal, pubID, urnID); + } + if (urnID != NULL) + xmlFree(urnID); + if (normid != NULL) + xmlFree(normid); + return(ret); + } + while (catal != NULL) { + if (catal->type == XML_CATA_CATALOG) { + if (catal->children == NULL) { + xmlFetchXMLCatalogFile(catal); + } + if (catal->children != NULL) { + ret = xmlCatalogXMLResolve(catal->children, pubID, sysID); + if (ret != NULL) { + if (normid != NULL) + xmlFree(normid); + return(ret); + } + } + } + catal = catal->next; + } + if (normid != NULL) + xmlFree(normid); + return(ret); +} + +/** + * xmlCatalogListXMLResolveURI: + * @catal: a catalog list + * @URI: the URI + * + * Do a complete resolution lookup of an URI for a list of catalogs + * + * Implements (or tries to) 7.2. URI Resolution + * from http://www.oasis-open.org/committees/entity/spec-2001-08-06.html + * + * Returns the URI of the resource or NULL if not found + */ +static xmlChar * +xmlCatalogListXMLResolveURI(xmlCatalogEntryPtr catal, const xmlChar *URI) { + xmlChar *ret = NULL; + xmlChar *urnID = NULL; + + if (catal == NULL) + return(NULL); + if (URI == NULL) + return(NULL); + + if (!xmlStrncmp(URI, BAD_CAST XML_URN_PUBID, sizeof(XML_URN_PUBID) - 1)) { + urnID = xmlCatalogUnWrapURN(URI); + if (xmlDebugCatalogs) { + if (urnID == NULL) + xmlGenericError(xmlGenericErrorContext, + "URN ID %s expanded to NULL\n", URI); + else + xmlGenericError(xmlGenericErrorContext, + "URN ID expanded to %s\n", urnID); + } + ret = xmlCatalogListXMLResolve(catal, urnID, NULL); + if (urnID != NULL) + xmlFree(urnID); + return(ret); + } + while (catal != NULL) { + if (catal->type == XML_CATA_CATALOG) { + if (catal->children == NULL) { + xmlFetchXMLCatalogFile(catal); + } + if (catal->children != NULL) { + ret = xmlCatalogXMLResolveURI(catal->children, URI); + if (ret != NULL) + return(ret); + } + } + catal = catal->next; + } + return(ret); +} + +/************************************************************************ + * * + * The SGML Catalog parser * + * * + ************************************************************************/ + + +#define RAW *cur +#define NEXT cur++; +#define SKIP(x) cur += x; + +#define SKIP_BLANKS while (IS_BLANK_CH(*cur)) NEXT; + +/** + * xmlParseSGMLCatalogComment: + * @cur: the current character + * + * Skip a comment in an SGML catalog + * + * Returns new current character + */ +static const xmlChar * +xmlParseSGMLCatalogComment(const xmlChar *cur) { + if ((cur[0] != '-') || (cur[1] != '-')) + return(cur); + SKIP(2); + while ((cur[0] != 0) && ((cur[0] != '-') || ((cur[1] != '-')))) + NEXT; + if (cur[0] == 0) { + return(NULL); + } + return(cur + 2); +} + +/** + * xmlParseSGMLCatalogPubid: + * @cur: the current character + * @id: the return location + * + * Parse an SGML catalog ID + * + * Returns new current character and store the value in @id + */ +static const xmlChar * +xmlParseSGMLCatalogPubid(const xmlChar *cur, xmlChar **id) { + xmlChar *buf = NULL, *tmp; + int len = 0; + int size = 50; + xmlChar stop; + int count = 0; + + *id = NULL; + + if (RAW == '"') { + NEXT; + stop = '"'; + } else if (RAW == '\'') { + NEXT; + stop = '\''; + } else { + stop = ' '; + } + buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar)); + if (buf == NULL) { + xmlCatalogErrMemory("allocating public ID"); + return(NULL); + } + while (IS_PUBIDCHAR_CH(*cur) || (*cur == '?')) { + if ((*cur == stop) && (stop != ' ')) + break; + if ((stop == ' ') && (IS_BLANK_CH(*cur))) + break; + if (len + 1 >= size) { + size *= 2; + tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar)); + if (tmp == NULL) { + xmlCatalogErrMemory("allocating public ID"); + xmlFree(buf); + return(NULL); + } + buf = tmp; + } + buf[len++] = *cur; + count++; + NEXT; + } + buf[len] = 0; + if (stop == ' ') { + if (!IS_BLANK_CH(*cur)) { + xmlFree(buf); + return(NULL); + } + } else { + if (*cur != stop) { + xmlFree(buf); + return(NULL); + } + NEXT; + } + *id = buf; + return(cur); +} + +/** + * xmlParseSGMLCatalogName: + * @cur: the current character + * @name: the return location + * + * Parse an SGML catalog name + * + * Returns new current character and store the value in @name + */ +static const xmlChar * +xmlParseSGMLCatalogName(const xmlChar *cur, xmlChar **name) { + xmlChar buf[XML_MAX_NAMELEN + 5]; + int len = 0; + int c; + + *name = NULL; + + /* + * Handler for more complex cases + */ + c = *cur; + if ((!IS_LETTER(c) && (c != '_') && (c != ':'))) { + return(NULL); + } + + while (((IS_LETTER(c)) || (IS_DIGIT(c)) || + (c == '.') || (c == '-') || + (c == '_') || (c == ':'))) { + buf[len++] = c; + cur++; + c = *cur; + if (len >= XML_MAX_NAMELEN) + return(NULL); + } + *name = xmlStrndup(buf, len); + return(cur); +} + +/** + * xmlGetSGMLCatalogEntryType: + * @name: the entry name + * + * Get the Catalog entry type for a given SGML Catalog name + * + * Returns Catalog entry type + */ +static xmlCatalogEntryType +xmlGetSGMLCatalogEntryType(const xmlChar *name) { + xmlCatalogEntryType type = XML_CATA_NONE; + if (xmlStrEqual(name, (const xmlChar *) "SYSTEM")) + type = SGML_CATA_SYSTEM; + else if (xmlStrEqual(name, (const xmlChar *) "PUBLIC")) + type = SGML_CATA_PUBLIC; + else if (xmlStrEqual(name, (const xmlChar *) "DELEGATE")) + type = SGML_CATA_DELEGATE; + else if (xmlStrEqual(name, (const xmlChar *) "ENTITY")) + type = SGML_CATA_ENTITY; + else if (xmlStrEqual(name, (const xmlChar *) "DOCTYPE")) + type = SGML_CATA_DOCTYPE; + else if (xmlStrEqual(name, (const xmlChar *) "LINKTYPE")) + type = SGML_CATA_LINKTYPE; + else if (xmlStrEqual(name, (const xmlChar *) "NOTATION")) + type = SGML_CATA_NOTATION; + else if (xmlStrEqual(name, (const xmlChar *) "SGMLDECL")) + type = SGML_CATA_SGMLDECL; + else if (xmlStrEqual(name, (const xmlChar *) "DOCUMENT")) + type = SGML_CATA_DOCUMENT; + else if (xmlStrEqual(name, (const xmlChar *) "CATALOG")) + type = SGML_CATA_CATALOG; + else if (xmlStrEqual(name, (const xmlChar *) "BASE")) + type = SGML_CATA_BASE; + return(type); +} + +/** + * xmlParseSGMLCatalog: + * @catal: the SGML Catalog + * @value: the content of the SGML Catalog serialization + * @file: the filepath for the catalog + * @super: should this be handled as a Super Catalog in which case + * parsing is not recursive + * + * Parse an SGML catalog content and fill up the @catal hash table with + * the new entries found. + * + * Returns 0 in case of success, -1 in case of error. + */ +static int +xmlParseSGMLCatalog(xmlCatalogPtr catal, const xmlChar *value, + const char *file, int super) { + const xmlChar *cur = value; + xmlChar *base = NULL; + int res; + + if ((cur == NULL) || (file == NULL)) + return(-1); + base = xmlStrdup((const xmlChar *) file); + + while ((cur != NULL) && (cur[0] != 0)) { + SKIP_BLANKS; + if (cur[0] == 0) + break; + if ((cur[0] == '-') && (cur[1] == '-')) { + cur = xmlParseSGMLCatalogComment(cur); + if (cur == NULL) { + /* error */ + break; + } + } else { + xmlChar *sysid = NULL; + xmlChar *name = NULL; + xmlCatalogEntryType type = XML_CATA_NONE; + + cur = xmlParseSGMLCatalogName(cur, &name); + if (name == NULL) { + /* error */ + break; + } + if (!IS_BLANK_CH(*cur)) { + /* error */ + break; + } + SKIP_BLANKS; + if (xmlStrEqual(name, (const xmlChar *) "SYSTEM")) + type = SGML_CATA_SYSTEM; + else if (xmlStrEqual(name, (const xmlChar *) "PUBLIC")) + type = SGML_CATA_PUBLIC; + else if (xmlStrEqual(name, (const xmlChar *) "DELEGATE")) + type = SGML_CATA_DELEGATE; + else if (xmlStrEqual(name, (const xmlChar *) "ENTITY")) + type = SGML_CATA_ENTITY; + else if (xmlStrEqual(name, (const xmlChar *) "DOCTYPE")) + type = SGML_CATA_DOCTYPE; + else if (xmlStrEqual(name, (const xmlChar *) "LINKTYPE")) + type = SGML_CATA_LINKTYPE; + else if (xmlStrEqual(name, (const xmlChar *) "NOTATION")) + type = SGML_CATA_NOTATION; + else if (xmlStrEqual(name, (const xmlChar *) "SGMLDECL")) + type = SGML_CATA_SGMLDECL; + else if (xmlStrEqual(name, (const xmlChar *) "DOCUMENT")) + type = SGML_CATA_DOCUMENT; + else if (xmlStrEqual(name, (const xmlChar *) "CATALOG")) + type = SGML_CATA_CATALOG; + else if (xmlStrEqual(name, (const xmlChar *) "BASE")) + type = SGML_CATA_BASE; + else if (xmlStrEqual(name, (const xmlChar *) "OVERRIDE")) { + xmlFree(name); + cur = xmlParseSGMLCatalogName(cur, &name); + if (name == NULL) { + /* error */ + break; + } + xmlFree(name); + continue; + } + xmlFree(name); + name = NULL; + + switch(type) { + case SGML_CATA_ENTITY: + if (*cur == '%') + type = SGML_CATA_PENTITY; + case SGML_CATA_PENTITY: + case SGML_CATA_DOCTYPE: + case SGML_CATA_LINKTYPE: + case SGML_CATA_NOTATION: + cur = xmlParseSGMLCatalogName(cur, &name); + if (cur == NULL) { + /* error */ + break; + } + if (!IS_BLANK_CH(*cur)) { + /* error */ + break; + } + SKIP_BLANKS; + cur = xmlParseSGMLCatalogPubid(cur, &sysid); + if (cur == NULL) { + /* error */ + break; + } + break; + case SGML_CATA_PUBLIC: + case SGML_CATA_SYSTEM: + case SGML_CATA_DELEGATE: + cur = xmlParseSGMLCatalogPubid(cur, &name); + if (cur == NULL) { + /* error */ + break; + } + if (type != SGML_CATA_SYSTEM) { + xmlChar *normid; + + normid = xmlCatalogNormalizePublic(name); + if (normid != NULL) { + if (name != NULL) + xmlFree(name); + if (*normid != 0) + name = normid; + else { + xmlFree(normid); + name = NULL; + } + } + } + if (!IS_BLANK_CH(*cur)) { + /* error */ + break; + } + SKIP_BLANKS; + cur = xmlParseSGMLCatalogPubid(cur, &sysid); + if (cur == NULL) { + /* error */ + break; + } + break; + case SGML_CATA_BASE: + case SGML_CATA_CATALOG: + case SGML_CATA_DOCUMENT: + case SGML_CATA_SGMLDECL: + cur = xmlParseSGMLCatalogPubid(cur, &sysid); + if (cur == NULL) { + /* error */ + break; + } + break; + default: + break; + } + if (cur == NULL) { + if (name != NULL) + xmlFree(name); + if (sysid != NULL) + xmlFree(sysid); + break; + } else if (type == SGML_CATA_BASE) { + if (base != NULL) + xmlFree(base); + base = xmlStrdup(sysid); + } else if ((type == SGML_CATA_PUBLIC) || + (type == SGML_CATA_SYSTEM)) { + xmlChar *filename; + + filename = xmlBuildURI(sysid, base); + if (filename != NULL) { + xmlCatalogEntryPtr entry; + + entry = xmlNewCatalogEntry(type, name, filename, + NULL, XML_CATA_PREFER_NONE, NULL); + res = xmlHashAddEntry(catal->sgml, name, entry); + if (res < 0) { + xmlFreeCatalogEntry(entry); + } + xmlFree(filename); + } + + } else if (type == SGML_CATA_CATALOG) { + if (super) { + xmlCatalogEntryPtr entry; + + entry = xmlNewCatalogEntry(type, sysid, NULL, NULL, + XML_CATA_PREFER_NONE, NULL); + res = xmlHashAddEntry(catal->sgml, sysid, entry); + if (res < 0) { + xmlFreeCatalogEntry(entry); + } + } else { + xmlChar *filename; + + filename = xmlBuildURI(sysid, base); + if (filename != NULL) { + xmlExpandCatalog(catal, (const char *)filename); + xmlFree(filename); + } + } + } + /* + * drop anything else we won't handle it + */ + if (name != NULL) + xmlFree(name); + if (sysid != NULL) + xmlFree(sysid); + } + } + if (base != NULL) + xmlFree(base); + if (cur == NULL) + return(-1); + return(0); +} + +/************************************************************************ + * * + * SGML Catalog handling * + * * + ************************************************************************/ + +/** + * xmlCatalogGetSGMLPublic: + * @catal: an SGML catalog hash + * @pubID: the public ID string + * + * Try to lookup the catalog local reference associated to a public ID + * + * Returns the local resource if found or NULL otherwise. + */ +static const xmlChar * +xmlCatalogGetSGMLPublic(xmlHashTablePtr catal, const xmlChar *pubID) { + xmlCatalogEntryPtr entry; + xmlChar *normid; + + if (catal == NULL) + return(NULL); + + normid = xmlCatalogNormalizePublic(pubID); + if (normid != NULL) + pubID = (*normid != 0 ? normid : NULL); + + entry = (xmlCatalogEntryPtr) xmlHashLookup(catal, pubID); + if (entry == NULL) { + if (normid != NULL) + xmlFree(normid); + return(NULL); + } + if (entry->type == SGML_CATA_PUBLIC) { + if (normid != NULL) + xmlFree(normid); + return(entry->URL); + } + if (normid != NULL) + xmlFree(normid); + return(NULL); +} + +/** + * xmlCatalogGetSGMLSystem: + * @catal: an SGML catalog hash + * @sysID: the system ID string + * + * Try to lookup the catalog local reference for a system ID + * + * Returns the local resource if found or NULL otherwise. + */ +static const xmlChar * +xmlCatalogGetSGMLSystem(xmlHashTablePtr catal, const xmlChar *sysID) { + xmlCatalogEntryPtr entry; + + if (catal == NULL) + return(NULL); + + entry = (xmlCatalogEntryPtr) xmlHashLookup(catal, sysID); + if (entry == NULL) + return(NULL); + if (entry->type == SGML_CATA_SYSTEM) + return(entry->URL); + return(NULL); +} + +/** + * xmlCatalogSGMLResolve: + * @catal: the SGML catalog + * @pubID: the public ID string + * @sysID: the system ID string + * + * Do a complete resolution lookup of an External Identifier + * + * Returns the URI of the resource or NULL if not found + */ +static const xmlChar * +xmlCatalogSGMLResolve(xmlCatalogPtr catal, const xmlChar *pubID, + const xmlChar *sysID) { + const xmlChar *ret = NULL; + + if (catal->sgml == NULL) + return(NULL); + + if (pubID != NULL) + ret = xmlCatalogGetSGMLPublic(catal->sgml, pubID); + if (ret != NULL) + return(ret); + if (sysID != NULL) + ret = xmlCatalogGetSGMLSystem(catal->sgml, sysID); + return(NULL); +} + +/************************************************************************ + * * + * Specific Public interfaces * + * * + ************************************************************************/ + +/** + * xmlLoadSGMLSuperCatalog: + * @filename: a file path + * + * Load an SGML super catalog. It won't expand CATALOG or DELEGATE + * references. This is only needed for manipulating SGML Super Catalogs + * like adding and removing CATALOG or DELEGATE entries. + * + * Returns the catalog parsed or NULL in case of error + */ +xmlCatalogPtr +xmlLoadSGMLSuperCatalog(const char *filename) +{ + xmlChar *content; + xmlCatalogPtr catal; + int ret; + + content = xmlLoadFileContent(filename); + if (content == NULL) + return(NULL); + + catal = xmlCreateNewCatalog(XML_SGML_CATALOG_TYPE, xmlCatalogDefaultPrefer); + if (catal == NULL) { + xmlFree(content); + return(NULL); + } + + ret = xmlParseSGMLCatalog(catal, content, filename, 1); + xmlFree(content); + if (ret < 0) { + xmlFreeCatalog(catal); + return(NULL); + } + return (catal); +} + +/** + * xmlLoadACatalog: + * @filename: a file path + * + * Load the catalog and build the associated data structures. + * This can be either an XML Catalog or an SGML Catalog + * It will recurse in SGML CATALOG entries. On the other hand XML + * Catalogs are not handled recursively. + * + * Returns the catalog parsed or NULL in case of error + */ +xmlCatalogPtr +xmlLoadACatalog(const char *filename) +{ + xmlChar *content; + xmlChar *first; + xmlCatalogPtr catal; + int ret; + + content = xmlLoadFileContent(filename); + if (content == NULL) + return(NULL); + + + first = content; + + while ((*first != 0) && (*first != '-') && (*first != '<') && + (!(((*first >= 'A') && (*first <= 'Z')) || + ((*first >= 'a') && (*first <= 'z'))))) + first++; + + if (*first != '<') { + catal = xmlCreateNewCatalog(XML_SGML_CATALOG_TYPE, xmlCatalogDefaultPrefer); + if (catal == NULL) { + xmlFree(content); + return(NULL); + } + ret = xmlParseSGMLCatalog(catal, content, filename, 0); + if (ret < 0) { + xmlFreeCatalog(catal); + xmlFree(content); + return(NULL); + } + } else { + catal = xmlCreateNewCatalog(XML_XML_CATALOG_TYPE, xmlCatalogDefaultPrefer); + if (catal == NULL) { + xmlFree(content); + return(NULL); + } + catal->xml = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL, + NULL, BAD_CAST filename, xmlCatalogDefaultPrefer, NULL); + } + xmlFree(content); + return (catal); +} + +/** + * xmlExpandCatalog: + * @catal: a catalog + * @filename: a file path + * + * Load the catalog and expand the existing catal structure. + * This can be either an XML Catalog or an SGML Catalog + * + * Returns 0 in case of success, -1 in case of error + */ +static int +xmlExpandCatalog(xmlCatalogPtr catal, const char *filename) +{ + int ret; + + if ((catal == NULL) || (filename == NULL)) + return(-1); + + + if (catal->type == XML_SGML_CATALOG_TYPE) { + xmlChar *content; + + content = xmlLoadFileContent(filename); + if (content == NULL) + return(-1); + + ret = xmlParseSGMLCatalog(catal, content, filename, 0); + if (ret < 0) { + xmlFree(content); + return(-1); + } + xmlFree(content); + } else { + xmlCatalogEntryPtr tmp, cur; + tmp = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL, + NULL, BAD_CAST filename, xmlCatalogDefaultPrefer, NULL); + + cur = catal->xml; + if (cur == NULL) { + catal->xml = tmp; + } else { + while (cur->next != NULL) cur = cur->next; + cur->next = tmp; + } + } + return (0); +} + +/** + * xmlACatalogResolveSystem: + * @catal: a Catalog + * @sysID: the system ID string + * + * Try to lookup the catalog resource for a system ID + * + * Returns the resource if found or NULL otherwise, the value returned + * must be freed by the caller. + */ +xmlChar * +xmlACatalogResolveSystem(xmlCatalogPtr catal, const xmlChar *sysID) { + xmlChar *ret = NULL; + + if ((sysID == NULL) || (catal == NULL)) + return(NULL); + + if (xmlDebugCatalogs) + xmlGenericError(xmlGenericErrorContext, + "Resolve sysID %s\n", sysID); + + if (catal->type == XML_XML_CATALOG_TYPE) { + ret = xmlCatalogListXMLResolve(catal->xml, NULL, sysID); + if (ret == XML_CATAL_BREAK) + ret = NULL; + } else { + const xmlChar *sgml; + + sgml = xmlCatalogGetSGMLSystem(catal->sgml, sysID); + if (sgml != NULL) + ret = xmlStrdup(sgml); + } + return(ret); +} + +/** + * xmlACatalogResolvePublic: + * @catal: a Catalog + * @pubID: the public ID string + * + * Try to lookup the catalog local reference associated to a public ID in that catalog + * + * Returns the local resource if found or NULL otherwise, the value returned + * must be freed by the caller. + */ +xmlChar * +xmlACatalogResolvePublic(xmlCatalogPtr catal, const xmlChar *pubID) { + xmlChar *ret = NULL; + + if ((pubID == NULL) || (catal == NULL)) + return(NULL); + + if (xmlDebugCatalogs) + xmlGenericError(xmlGenericErrorContext, + "Resolve pubID %s\n", pubID); + + if (catal->type == XML_XML_CATALOG_TYPE) { + ret = xmlCatalogListXMLResolve(catal->xml, pubID, NULL); + if (ret == XML_CATAL_BREAK) + ret = NULL; + } else { + const xmlChar *sgml; + + sgml = xmlCatalogGetSGMLPublic(catal->sgml, pubID); + if (sgml != NULL) + ret = xmlStrdup(sgml); + } + return(ret); +} + +/** + * xmlACatalogResolve: + * @catal: a Catalog + * @pubID: the public ID string + * @sysID: the system ID string + * + * Do a complete resolution lookup of an External Identifier + * + * Returns the URI of the resource or NULL if not found, it must be freed + * by the caller. + */ +xmlChar * +xmlACatalogResolve(xmlCatalogPtr catal, const xmlChar * pubID, + const xmlChar * sysID) +{ + xmlChar *ret = NULL; + + if (((pubID == NULL) && (sysID == NULL)) || (catal == NULL)) + return (NULL); + + if (xmlDebugCatalogs) { + if ((pubID != NULL) && (sysID != NULL)) { + xmlGenericError(xmlGenericErrorContext, + "Resolve: pubID %s sysID %s\n", pubID, sysID); + } else if (pubID != NULL) { + xmlGenericError(xmlGenericErrorContext, + "Resolve: pubID %s\n", pubID); + } else { + xmlGenericError(xmlGenericErrorContext, + "Resolve: sysID %s\n", sysID); + } + } + + if (catal->type == XML_XML_CATALOG_TYPE) { + ret = xmlCatalogListXMLResolve(catal->xml, pubID, sysID); + if (ret == XML_CATAL_BREAK) + ret = NULL; + } else { + const xmlChar *sgml; + + sgml = xmlCatalogSGMLResolve(catal, pubID, sysID); + if (sgml != NULL) + ret = xmlStrdup(sgml); + } + return (ret); +} + +/** + * xmlACatalogResolveURI: + * @catal: a Catalog + * @URI: the URI + * + * Do a complete resolution lookup of an URI + * + * Returns the URI of the resource or NULL if not found, it must be freed + * by the caller. + */ +xmlChar * +xmlACatalogResolveURI(xmlCatalogPtr catal, const xmlChar *URI) { + xmlChar *ret = NULL; + + if ((URI == NULL) || (catal == NULL)) + return(NULL); + + if (xmlDebugCatalogs) + xmlGenericError(xmlGenericErrorContext, + "Resolve URI %s\n", URI); + + if (catal->type == XML_XML_CATALOG_TYPE) { + ret = xmlCatalogListXMLResolveURI(catal->xml, URI); + if (ret == XML_CATAL_BREAK) + ret = NULL; + } else { + const xmlChar *sgml; + + sgml = xmlCatalogSGMLResolve(catal, NULL, URI); + if (sgml != NULL) + sgml = xmlStrdup(sgml); + } + return(ret); +} + +#ifdef LIBXML_OUTPUT_ENABLED +/** + * xmlACatalogDump: + * @catal: a Catalog + * @out: the file. + * + * Dump the given catalog to the given file. + */ +void +xmlACatalogDump(xmlCatalogPtr catal, FILE *out) { + if ((out == NULL) || (catal == NULL)) + return; + + if (catal->type == XML_XML_CATALOG_TYPE) { + xmlDumpXMLCatalog(out, catal->xml); + } else { + xmlHashScan(catal->sgml, + (xmlHashScanner) xmlCatalogDumpEntry, out); + } +} +#endif /* LIBXML_OUTPUT_ENABLED */ + +/** + * xmlACatalogAdd: + * @catal: a Catalog + * @type: the type of record to add to the catalog + * @orig: the system, public or prefix to match + * @replace: the replacement value for the match + * + * Add an entry in the catalog, it may overwrite existing but + * different entries. + * + * Returns 0 if successful, -1 otherwise + */ +int +xmlACatalogAdd(xmlCatalogPtr catal, const xmlChar * type, + const xmlChar * orig, const xmlChar * replace) +{ + int res = -1; + + if (catal == NULL) + return(-1); + + if (catal->type == XML_XML_CATALOG_TYPE) { + res = xmlAddXMLCatalog(catal->xml, type, orig, replace); + } else { + xmlCatalogEntryType cattype; + + cattype = xmlGetSGMLCatalogEntryType(type); + if (cattype != XML_CATA_NONE) { + xmlCatalogEntryPtr entry; + + entry = xmlNewCatalogEntry(cattype, orig, replace, NULL, + XML_CATA_PREFER_NONE, NULL); + if (catal->sgml == NULL) + catal->sgml = xmlHashCreate(10); + res = xmlHashAddEntry(catal->sgml, orig, entry); + } + } + return (res); +} + +/** + * xmlACatalogRemove: + * @catal: a Catalog + * @value: the value to remove + * + * Remove an entry from the catalog + * + * Returns the number of entries removed if successful, -1 otherwise + */ +int +xmlACatalogRemove(xmlCatalogPtr catal, const xmlChar *value) { + int res = -1; + + if ((catal == NULL) || (value == NULL)) + return(-1); + + if (catal->type == XML_XML_CATALOG_TYPE) { + res = xmlDelXMLCatalog(catal->xml, value); + } else { + res = xmlHashRemoveEntry(catal->sgml, value, + (xmlHashDeallocator) xmlFreeCatalogEntry); + if (res == 0) + res = 1; + } + return(res); +} + +/** + * xmlNewCatalog: + * @sgml: should this create an SGML catalog + * + * create a new Catalog. + * + * Returns the xmlCatalogPtr or NULL in case of error + */ +xmlCatalogPtr +xmlNewCatalog(int sgml) { + xmlCatalogPtr catal = NULL; + + if (sgml) { + catal = xmlCreateNewCatalog(XML_SGML_CATALOG_TYPE, + xmlCatalogDefaultPrefer); + if ((catal != NULL) && (catal->sgml == NULL)) + catal->sgml = xmlHashCreate(10); + } else + catal = xmlCreateNewCatalog(XML_XML_CATALOG_TYPE, + xmlCatalogDefaultPrefer); + return(catal); +} + +/** + * xmlCatalogIsEmpty: + * @catal: should this create an SGML catalog + * + * Check is a catalog is empty + * + * Returns 1 if the catalog is empty, 0 if not, amd -1 in case of error. + */ +int +xmlCatalogIsEmpty(xmlCatalogPtr catal) { + if (catal == NULL) + return(-1); + + if (catal->type == XML_XML_CATALOG_TYPE) { + if (catal->xml == NULL) + return(1); + if ((catal->xml->type != XML_CATA_CATALOG) && + (catal->xml->type != XML_CATA_BROKEN_CATALOG)) + return(-1); + if (catal->xml->children == NULL) + return(1); + return(0); + } else { + int res; + + if (catal->sgml == NULL) + return(1); + res = xmlHashSize(catal->sgml); + if (res == 0) + return(1); + if (res < 0) + return(-1); + } + return(0); +} + +/************************************************************************ + * * + * Public interfaces manipulating the global shared default catalog * + * * + ************************************************************************/ + +/** + * xmlInitializeCatalogData: + * + * Do the catalog initialization only of global data, doesn't try to load + * any catalog actually. + * this function is not thread safe, catalog initialization should + * preferably be done once at startup + */ +static void +xmlInitializeCatalogData(void) { + if (xmlCatalogInitialized != 0) + return; + + if (getenv("XML_DEBUG_CATALOG")) + xmlDebugCatalogs = 1; + xmlCatalogMutex = xmlNewRMutex(); + + xmlCatalogInitialized = 1; +} +/** + * xmlInitializeCatalog: + * + * Do the catalog initialization. + * this function is not thread safe, catalog initialization should + * preferably be done once at startup + */ +void +xmlInitializeCatalog(void) { + if (xmlCatalogInitialized != 0) + return; + + xmlInitializeCatalogData(); + xmlRMutexLock(xmlCatalogMutex); + + if (getenv("XML_DEBUG_CATALOG")) + xmlDebugCatalogs = 1; + + if (xmlDefaultCatalog == NULL) { + const char *catalogs; + char *path; + const char *cur, *paths; + xmlCatalogPtr catal; + xmlCatalogEntryPtr *nextent; + + catalogs = (const char *) getenv("XML_CATALOG_FILES"); + if (catalogs == NULL) +#if defined(_WIN32) && defined(_MSC_VER) + { + void* hmodule; + hmodule = GetModuleHandleA("libxml2.dll"); + if (hmodule == NULL) + hmodule = GetModuleHandleA(NULL); + if (hmodule != NULL) { + char buf[256]; + unsigned long len = GetModuleFileNameA(hmodule, buf, 255); + if (len != 0) { + char* p = &(buf[len]); + while (*p != '\\' && p > buf) + p--; + if (p != buf) { + xmlChar* uri; + strncpy(p, "\\..\\etc\\catalog", 255 - (p - buf)); + uri = xmlCanonicPath(buf); + if (uri != NULL) { + strncpy(XML_XML_DEFAULT_CATALOG, uri, 255); + xmlFree(uri); + } + } + } + } + catalogs = XML_XML_DEFAULT_CATALOG; + } +#else + catalogs = XML_XML_DEFAULT_CATALOG; +#endif + + catal = xmlCreateNewCatalog(XML_XML_CATALOG_TYPE, + xmlCatalogDefaultPrefer); + if (catal != NULL) { + /* the XML_CATALOG_FILES envvar is allowed to contain a + space-separated list of entries. */ + cur = catalogs; + nextent = &catal->xml; + while (*cur != '\0') { + while (xmlIsBlank_ch(*cur)) + cur++; + if (*cur != 0) { + paths = cur; + while ((*cur != 0) && (!xmlIsBlank_ch(*cur))) + cur++; + path = (char *) xmlStrndup((const xmlChar *)paths, cur - paths); + if (path != NULL) { + *nextent = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL, + NULL, BAD_CAST path, xmlCatalogDefaultPrefer, NULL); + if (*nextent != NULL) + nextent = &((*nextent)->next); + xmlFree(path); + } + } + } + xmlDefaultCatalog = catal; + } + } + + xmlRMutexUnlock(xmlCatalogMutex); +} + + +/** + * xmlLoadCatalog: + * @filename: a file path + * + * Load the catalog and makes its definitions effective for the default + * external entity loader. It will recurse in SGML CATALOG entries. + * this function is not thread safe, catalog initialization should + * preferably be done once at startup + * + * Returns 0 in case of success -1 in case of error + */ +int +xmlLoadCatalog(const char *filename) +{ + int ret; + xmlCatalogPtr catal; + + if (!xmlCatalogInitialized) + xmlInitializeCatalogData(); + + xmlRMutexLock(xmlCatalogMutex); + + if (xmlDefaultCatalog == NULL) { + catal = xmlLoadACatalog(filename); + if (catal == NULL) { + xmlRMutexUnlock(xmlCatalogMutex); + return(-1); + } + + xmlDefaultCatalog = catal; + xmlRMutexUnlock(xmlCatalogMutex); + return(0); + } + + ret = xmlExpandCatalog(xmlDefaultCatalog, filename); + xmlRMutexUnlock(xmlCatalogMutex); + return(ret); +} + +/** + * xmlLoadCatalogs: + * @pathss: a list of directories separated by a colon or a space. + * + * Load the catalogs and makes their definitions effective for the default + * external entity loader. + * this function is not thread safe, catalog initialization should + * preferably be done once at startup + */ +void +xmlLoadCatalogs(const char *pathss) { + const char *cur; + const char *paths; + xmlChar *path; + + if (pathss == NULL) + return; + + cur = pathss; + while (*cur != 0) { + while (xmlIsBlank_ch(*cur)) cur++; + if (*cur != 0) { + paths = cur; + while ((*cur != 0) && (*cur != ':') && (!xmlIsBlank_ch(*cur))) + cur++; + path = xmlStrndup((const xmlChar *)paths, cur - paths); + if (path != NULL) { + xmlLoadCatalog((const char *) path); + xmlFree(path); + } + } + while (*cur == ':') + cur++; + } +} + +/** + * xmlCatalogCleanup: + * + * Free up all the memory associated with catalogs + */ +void +xmlCatalogCleanup(void) { + if (xmlCatalogInitialized == 0) + return; + + xmlRMutexLock(xmlCatalogMutex); + if (xmlDebugCatalogs) + xmlGenericError(xmlGenericErrorContext, + "Catalogs cleanup\n"); + if (xmlCatalogXMLFiles != NULL) + xmlHashFree(xmlCatalogXMLFiles, + (xmlHashDeallocator)xmlFreeCatalogHashEntryList); + xmlCatalogXMLFiles = NULL; + if (xmlDefaultCatalog != NULL) + xmlFreeCatalog(xmlDefaultCatalog); + xmlDefaultCatalog = NULL; + xmlDebugCatalogs = 0; + xmlCatalogInitialized = 0; + xmlRMutexUnlock(xmlCatalogMutex); + xmlFreeRMutex(xmlCatalogMutex); +} + +/** + * xmlCatalogResolveSystem: + * @sysID: the system ID string + * + * Try to lookup the catalog resource for a system ID + * + * Returns the resource if found or NULL otherwise, the value returned + * must be freed by the caller. + */ +xmlChar * +xmlCatalogResolveSystem(const xmlChar *sysID) { + xmlChar *ret; + + if (!xmlCatalogInitialized) + xmlInitializeCatalog(); + + ret = xmlACatalogResolveSystem(xmlDefaultCatalog, sysID); + return(ret); +} + +/** + * xmlCatalogResolvePublic: + * @pubID: the public ID string + * + * Try to lookup the catalog reference associated to a public ID + * + * Returns the resource if found or NULL otherwise, the value returned + * must be freed by the caller. + */ +xmlChar * +xmlCatalogResolvePublic(const xmlChar *pubID) { + xmlChar *ret; + + if (!xmlCatalogInitialized) + xmlInitializeCatalog(); + + ret = xmlACatalogResolvePublic(xmlDefaultCatalog, pubID); + return(ret); +} + +/** + * xmlCatalogResolve: + * @pubID: the public ID string + * @sysID: the system ID string + * + * Do a complete resolution lookup of an External Identifier + * + * Returns the URI of the resource or NULL if not found, it must be freed + * by the caller. + */ +xmlChar * +xmlCatalogResolve(const xmlChar *pubID, const xmlChar *sysID) { + xmlChar *ret; + + if (!xmlCatalogInitialized) + xmlInitializeCatalog(); + + ret = xmlACatalogResolve(xmlDefaultCatalog, pubID, sysID); + return(ret); +} + +/** + * xmlCatalogResolveURI: + * @URI: the URI + * + * Do a complete resolution lookup of an URI + * + * Returns the URI of the resource or NULL if not found, it must be freed + * by the caller. + */ +xmlChar * +xmlCatalogResolveURI(const xmlChar *URI) { + xmlChar *ret; + + if (!xmlCatalogInitialized) + xmlInitializeCatalog(); + + ret = xmlACatalogResolveURI(xmlDefaultCatalog, URI); + return(ret); +} + +#ifdef LIBXML_OUTPUT_ENABLED +/** + * xmlCatalogDump: + * @out: the file. + * + * Dump all the global catalog content to the given file. + */ +void +xmlCatalogDump(FILE *out) { + if (out == NULL) + return; + + if (!xmlCatalogInitialized) + xmlInitializeCatalog(); + + xmlACatalogDump(xmlDefaultCatalog, out); +} +#endif /* LIBXML_OUTPUT_ENABLED */ + +/** + * xmlCatalogAdd: + * @type: the type of record to add to the catalog + * @orig: the system, public or prefix to match + * @replace: the replacement value for the match + * + * Add an entry in the catalog, it may overwrite existing but + * different entries. + * If called before any other catalog routine, allows to override the + * default shared catalog put in place by xmlInitializeCatalog(); + * + * Returns 0 if successful, -1 otherwise + */ +int +xmlCatalogAdd(const xmlChar *type, const xmlChar *orig, const xmlChar *replace) { + int res = -1; + + if (!xmlCatalogInitialized) + xmlInitializeCatalogData(); + + xmlRMutexLock(xmlCatalogMutex); + /* + * Specific case where one want to override the default catalog + * put in place by xmlInitializeCatalog(); + */ + if ((xmlDefaultCatalog == NULL) && + (xmlStrEqual(type, BAD_CAST "catalog"))) { + xmlDefaultCatalog = xmlCreateNewCatalog(XML_XML_CATALOG_TYPE, + xmlCatalogDefaultPrefer); + xmlDefaultCatalog->xml = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL, + orig, NULL, xmlCatalogDefaultPrefer, NULL); + + xmlRMutexUnlock(xmlCatalogMutex); + return(0); + } + + res = xmlACatalogAdd(xmlDefaultCatalog, type, orig, replace); + xmlRMutexUnlock(xmlCatalogMutex); + return(res); +} + +/** + * xmlCatalogRemove: + * @value: the value to remove + * + * Remove an entry from the catalog + * + * Returns the number of entries removed if successful, -1 otherwise + */ +int +xmlCatalogRemove(const xmlChar *value) { + int res; + + if (!xmlCatalogInitialized) + xmlInitializeCatalog(); + + xmlRMutexLock(xmlCatalogMutex); + res = xmlACatalogRemove(xmlDefaultCatalog, value); + xmlRMutexUnlock(xmlCatalogMutex); + return(res); +} + +/** + * xmlCatalogConvert: + * + * Convert all the SGML catalog entries as XML ones + * + * Returns the number of entries converted if successful, -1 otherwise + */ +int +xmlCatalogConvert(void) { + int res = -1; + + if (!xmlCatalogInitialized) + xmlInitializeCatalog(); + + xmlRMutexLock(xmlCatalogMutex); + res = xmlConvertSGMLCatalog(xmlDefaultCatalog); + xmlRMutexUnlock(xmlCatalogMutex); + return(res); +} + +/************************************************************************ + * * + * Public interface manipulating the common preferences * + * * + ************************************************************************/ + +/** + * xmlCatalogGetDefaults: + * + * Used to get the user preference w.r.t. to what catalogs should + * be accepted + * + * Returns the current xmlCatalogAllow value + */ +xmlCatalogAllow +xmlCatalogGetDefaults(void) { + return(xmlCatalogDefaultAllow); +} + +/** + * xmlCatalogSetDefaults: + * @allow: what catalogs should be accepted + * + * Used to set the user preference w.r.t. to what catalogs should + * be accepted + */ +void +xmlCatalogSetDefaults(xmlCatalogAllow allow) { + if (xmlDebugCatalogs) { + switch (allow) { + case XML_CATA_ALLOW_NONE: + xmlGenericError(xmlGenericErrorContext, + "Disabling catalog usage\n"); + break; + case XML_CATA_ALLOW_GLOBAL: + xmlGenericError(xmlGenericErrorContext, + "Allowing only global catalogs\n"); + break; + case XML_CATA_ALLOW_DOCUMENT: + xmlGenericError(xmlGenericErrorContext, + "Allowing only catalogs from the document\n"); + break; + case XML_CATA_ALLOW_ALL: + xmlGenericError(xmlGenericErrorContext, + "Allowing all catalogs\n"); + break; + } + } + xmlCatalogDefaultAllow = allow; +} + +/** + * xmlCatalogSetDefaultPrefer: + * @prefer: the default preference for delegation + * + * Allows to set the preference between public and system for deletion + * in XML Catalog resolution. C.f. section 4.1.1 of the spec + * Values accepted are XML_CATA_PREFER_PUBLIC or XML_CATA_PREFER_SYSTEM + * + * Returns the previous value of the default preference for delegation + */ +xmlCatalogPrefer +xmlCatalogSetDefaultPrefer(xmlCatalogPrefer prefer) { + xmlCatalogPrefer ret = xmlCatalogDefaultPrefer; + + if (prefer == XML_CATA_PREFER_NONE) + return(ret); + + if (xmlDebugCatalogs) { + switch (prefer) { + case XML_CATA_PREFER_PUBLIC: + xmlGenericError(xmlGenericErrorContext, + "Setting catalog preference to PUBLIC\n"); + break; + case XML_CATA_PREFER_SYSTEM: + xmlGenericError(xmlGenericErrorContext, + "Setting catalog preference to SYSTEM\n"); + break; + case XML_CATA_PREFER_NONE: + break; + } + } + xmlCatalogDefaultPrefer = prefer; + return(ret); +} + +/** + * xmlCatalogSetDebug: + * @level: the debug level of catalogs required + * + * Used to set the debug level for catalog operation, 0 disable + * debugging, 1 enable it + * + * Returns the previous value of the catalog debugging level + */ +int +xmlCatalogSetDebug(int level) { + int ret = xmlDebugCatalogs; + + if (level <= 0) + xmlDebugCatalogs = 0; + else + xmlDebugCatalogs = level; + return(ret); +} + +/************************************************************************ + * * + * Minimal interfaces used for per-document catalogs by the parser * + * * + ************************************************************************/ + +/** + * xmlCatalogFreeLocal: + * @catalogs: a document's list of catalogs + * + * Free up the memory associated to the catalog list + */ +void +xmlCatalogFreeLocal(void *catalogs) { + xmlCatalogEntryPtr catal; + + if (!xmlCatalogInitialized) + xmlInitializeCatalog(); + + catal = (xmlCatalogEntryPtr) catalogs; + if (catal != NULL) + xmlFreeCatalogEntryList(catal); +} + + +/** + * xmlCatalogAddLocal: + * @catalogs: a document's list of catalogs + * @URL: the URL to a new local catalog + * + * Add the new entry to the catalog list + * + * Returns the updated list + */ +void * +xmlCatalogAddLocal(void *catalogs, const xmlChar *URL) { + xmlCatalogEntryPtr catal, add; + + if (!xmlCatalogInitialized) + xmlInitializeCatalog(); + + if (URL == NULL) + return(catalogs); + + if (xmlDebugCatalogs) + xmlGenericError(xmlGenericErrorContext, + "Adding document catalog %s\n", URL); + + add = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL, URL, NULL, + xmlCatalogDefaultPrefer, NULL); + if (add == NULL) + return(catalogs); + + catal = (xmlCatalogEntryPtr) catalogs; + if (catal == NULL) + return((void *) add); + + while (catal->next != NULL) + catal = catal->next; + catal->next = add; + return(catalogs); +} + +/** + * xmlCatalogLocalResolve: + * @catalogs: a document's list of catalogs + * @pubID: the public ID string + * @sysID: the system ID string + * + * Do a complete resolution lookup of an External Identifier using a + * document's private catalog list + * + * Returns the URI of the resource or NULL if not found, it must be freed + * by the caller. + */ +xmlChar * +xmlCatalogLocalResolve(void *catalogs, const xmlChar *pubID, + const xmlChar *sysID) { + xmlCatalogEntryPtr catal; + xmlChar *ret; + + if (!xmlCatalogInitialized) + xmlInitializeCatalog(); + + if ((pubID == NULL) && (sysID == NULL)) + return(NULL); + + if (xmlDebugCatalogs) { + if ((pubID != NULL) && (sysID != NULL)) { + xmlGenericError(xmlGenericErrorContext, + "Local Resolve: pubID %s sysID %s\n", pubID, sysID); + } else if (pubID != NULL) { + xmlGenericError(xmlGenericErrorContext, + "Local Resolve: pubID %s\n", pubID); + } else { + xmlGenericError(xmlGenericErrorContext, + "Local Resolve: sysID %s\n", sysID); + } + } + + catal = (xmlCatalogEntryPtr) catalogs; + if (catal == NULL) + return(NULL); + ret = xmlCatalogListXMLResolve(catal, pubID, sysID); + if ((ret != NULL) && (ret != XML_CATAL_BREAK)) + return(ret); + return(NULL); +} + +/** + * xmlCatalogLocalResolveURI: + * @catalogs: a document's list of catalogs + * @URI: the URI + * + * Do a complete resolution lookup of an URI using a + * document's private catalog list + * + * Returns the URI of the resource or NULL if not found, it must be freed + * by the caller. + */ +xmlChar * +xmlCatalogLocalResolveURI(void *catalogs, const xmlChar *URI) { + xmlCatalogEntryPtr catal; + xmlChar *ret; + + if (!xmlCatalogInitialized) + xmlInitializeCatalog(); + + if (URI == NULL) + return(NULL); + + if (xmlDebugCatalogs) + xmlGenericError(xmlGenericErrorContext, + "Resolve URI %s\n", URI); + + catal = (xmlCatalogEntryPtr) catalogs; + if (catal == NULL) + return(NULL); + ret = xmlCatalogListXMLResolveURI(catal, URI); + if ((ret != NULL) && (ret != XML_CATAL_BREAK)) + return(ret); + return(NULL); +} + +/************************************************************************ + * * + * Deprecated interfaces * + * * + ************************************************************************/ +/** + * xmlCatalogGetSystem: + * @sysID: the system ID string + * + * Try to lookup the catalog reference associated to a system ID + * DEPRECATED, use xmlCatalogResolveSystem() + * + * Returns the resource if found or NULL otherwise. + */ +const xmlChar * +xmlCatalogGetSystem(const xmlChar *sysID) { + xmlChar *ret; + static xmlChar result[1000]; + static int msg = 0; + + if (!xmlCatalogInitialized) + xmlInitializeCatalog(); + + if (msg == 0) { + xmlGenericError(xmlGenericErrorContext, + "Use of deprecated xmlCatalogGetSystem() call\n"); + msg++; + } + + if (sysID == NULL) + return(NULL); + + /* + * Check first the XML catalogs + */ + if (xmlDefaultCatalog != NULL) { + ret = xmlCatalogListXMLResolve(xmlDefaultCatalog->xml, NULL, sysID); + if ((ret != NULL) && (ret != XML_CATAL_BREAK)) { + snprintf((char *) result, sizeof(result) - 1, "%s", (char *) ret); + result[sizeof(result) - 1] = 0; + return(result); + } + } + + if (xmlDefaultCatalog != NULL) + return(xmlCatalogGetSGMLSystem(xmlDefaultCatalog->sgml, sysID)); + return(NULL); +} + +/** + * xmlCatalogGetPublic: + * @pubID: the public ID string + * + * Try to lookup the catalog reference associated to a public ID + * DEPRECATED, use xmlCatalogResolvePublic() + * + * Returns the resource if found or NULL otherwise. + */ +const xmlChar * +xmlCatalogGetPublic(const xmlChar *pubID) { + xmlChar *ret; + static xmlChar result[1000]; + static int msg = 0; + + if (!xmlCatalogInitialized) + xmlInitializeCatalog(); + + if (msg == 0) { + xmlGenericError(xmlGenericErrorContext, + "Use of deprecated xmlCatalogGetPublic() call\n"); + msg++; + } + + if (pubID == NULL) + return(NULL); + + /* + * Check first the XML catalogs + */ + if (xmlDefaultCatalog != NULL) { + ret = xmlCatalogListXMLResolve(xmlDefaultCatalog->xml, pubID, NULL); + if ((ret != NULL) && (ret != XML_CATAL_BREAK)) { + snprintf((char *) result, sizeof(result) - 1, "%s", (char *) ret); + result[sizeof(result) - 1] = 0; + return(result); + } + } + + if (xmlDefaultCatalog != NULL) + return(xmlCatalogGetSGMLPublic(xmlDefaultCatalog->sgml, pubID)); + return(NULL); +} + +#define bottom_catalog +#include "elfgcchack.h" +#endif /* LIBXML_CATALOG_ENABLED */ diff --git a/gettext-tools/gnulib-lib/libxml/catalog.in.h b/gettext-tools/gnulib-lib/libxml/catalog.in.h new file mode 100644 index 0000000..b444137 --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/catalog.in.h @@ -0,0 +1,182 @@ +/** + * Summary: interfaces to the Catalog handling system + * Description: the catalog module implements the support for + * XML Catalogs and SGML catalogs + * + * SGML Open Technical Resolution TR9401:1997. + * http://www.jclark.com/sp/catalog.htm + * + * XML Catalogs Working Draft 06 August 2001 + * http://www.oasis-open.org/committees/entity/spec-2001-08-06.html + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + +#ifndef __XML_CATALOG_H__ +#define __XML_CATALOG_H__ + +#include + +#include +#include +#include + +#ifdef LIBXML_CATALOG_ENABLED + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * XML_CATALOGS_NAMESPACE: + * + * The namespace for the XML Catalogs elements. + */ +#define XML_CATALOGS_NAMESPACE \ + (const xmlChar *) "urn:oasis:names:tc:entity:xmlns:xml:catalog" +/** + * XML_CATALOG_PI: + * + * The specific XML Catalog Processing Instuction name. + */ +#define XML_CATALOG_PI \ + (const xmlChar *) "oasis-xml-catalog" + +/* + * The API is voluntarily limited to general cataloging. + */ +typedef enum { + XML_CATA_PREFER_NONE = 0, + XML_CATA_PREFER_PUBLIC = 1, + XML_CATA_PREFER_SYSTEM +} xmlCatalogPrefer; + +typedef enum { + XML_CATA_ALLOW_NONE = 0, + XML_CATA_ALLOW_GLOBAL = 1, + XML_CATA_ALLOW_DOCUMENT = 2, + XML_CATA_ALLOW_ALL = 3 +} xmlCatalogAllow; + +typedef struct _xmlCatalog xmlCatalog; +typedef xmlCatalog *xmlCatalogPtr; + +/* + * Operations on a given catalog. + */ +XMLPUBFUN xmlCatalogPtr XMLCALL + xmlNewCatalog (int sgml); +XMLPUBFUN xmlCatalogPtr XMLCALL + xmlLoadACatalog (const char *filename); +XMLPUBFUN xmlCatalogPtr XMLCALL + xmlLoadSGMLSuperCatalog (const char *filename); +XMLPUBFUN int XMLCALL + xmlConvertSGMLCatalog (xmlCatalogPtr catal); +XMLPUBFUN int XMLCALL + xmlACatalogAdd (xmlCatalogPtr catal, + const xmlChar *type, + const xmlChar *orig, + const xmlChar *replace); +XMLPUBFUN int XMLCALL + xmlACatalogRemove (xmlCatalogPtr catal, + const xmlChar *value); +XMLPUBFUN xmlChar * XMLCALL + xmlACatalogResolve (xmlCatalogPtr catal, + const xmlChar *pubID, + const xmlChar *sysID); +XMLPUBFUN xmlChar * XMLCALL + xmlACatalogResolveSystem(xmlCatalogPtr catal, + const xmlChar *sysID); +XMLPUBFUN xmlChar * XMLCALL + xmlACatalogResolvePublic(xmlCatalogPtr catal, + const xmlChar *pubID); +XMLPUBFUN xmlChar * XMLCALL + xmlACatalogResolveURI (xmlCatalogPtr catal, + const xmlChar *URI); +#ifdef LIBXML_OUTPUT_ENABLED +XMLPUBFUN void XMLCALL + xmlACatalogDump (xmlCatalogPtr catal, + FILE *out); +#endif /* LIBXML_OUTPUT_ENABLED */ +XMLPUBFUN void XMLCALL + xmlFreeCatalog (xmlCatalogPtr catal); +XMLPUBFUN int XMLCALL + xmlCatalogIsEmpty (xmlCatalogPtr catal); + +/* + * Global operations. + */ +XMLPUBFUN void XMLCALL + xmlInitializeCatalog (void); +XMLPUBFUN int XMLCALL + xmlLoadCatalog (const char *filename); +XMLPUBFUN void XMLCALL + xmlLoadCatalogs (const char *paths); +XMLPUBFUN void XMLCALL + xmlCatalogCleanup (void); +#ifdef LIBXML_OUTPUT_ENABLED +XMLPUBFUN void XMLCALL + xmlCatalogDump (FILE *out); +#endif /* LIBXML_OUTPUT_ENABLED */ +XMLPUBFUN xmlChar * XMLCALL + xmlCatalogResolve (const xmlChar *pubID, + const xmlChar *sysID); +XMLPUBFUN xmlChar * XMLCALL + xmlCatalogResolveSystem (const xmlChar *sysID); +XMLPUBFUN xmlChar * XMLCALL + xmlCatalogResolvePublic (const xmlChar *pubID); +XMLPUBFUN xmlChar * XMLCALL + xmlCatalogResolveURI (const xmlChar *URI); +XMLPUBFUN int XMLCALL + xmlCatalogAdd (const xmlChar *type, + const xmlChar *orig, + const xmlChar *replace); +XMLPUBFUN int XMLCALL + xmlCatalogRemove (const xmlChar *value); +XMLPUBFUN xmlDocPtr XMLCALL + xmlParseCatalogFile (const char *filename); +XMLPUBFUN int XMLCALL + xmlCatalogConvert (void); + +/* + * Strictly minimal interfaces for per-document catalogs used + * by the parser. + */ +XMLPUBFUN void XMLCALL + xmlCatalogFreeLocal (void *catalogs); +XMLPUBFUN void * XMLCALL + xmlCatalogAddLocal (void *catalogs, + const xmlChar *URL); +XMLPUBFUN xmlChar * XMLCALL + xmlCatalogLocalResolve (void *catalogs, + const xmlChar *pubID, + const xmlChar *sysID); +XMLPUBFUN xmlChar * XMLCALL + xmlCatalogLocalResolveURI(void *catalogs, + const xmlChar *URI); +/* + * Preference settings. + */ +XMLPUBFUN int XMLCALL + xmlCatalogSetDebug (int level); +XMLPUBFUN xmlCatalogPrefer XMLCALL + xmlCatalogSetDefaultPrefer(xmlCatalogPrefer prefer); +XMLPUBFUN void XMLCALL + xmlCatalogSetDefaults (xmlCatalogAllow allow); +XMLPUBFUN xmlCatalogAllow XMLCALL + xmlCatalogGetDefaults (void); + + +/* DEPRECATED interfaces */ +XMLPUBFUN const xmlChar * XMLCALL + xmlCatalogGetSystem (const xmlChar *sysID); +XMLPUBFUN const xmlChar * XMLCALL + xmlCatalogGetPublic (const xmlChar *pubID); + +#ifdef __cplusplus +} +#endif +#endif /* LIBXML_CATALOG_ENABLED */ +#endif /* __XML_CATALOG_H__ */ diff --git a/gettext-tools/gnulib-lib/libxml/chvalid.c b/gettext-tools/gnulib-lib/libxml/chvalid.c new file mode 100644 index 0000000..00dd962 --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/chvalid.c @@ -0,0 +1,336 @@ +/* + * chvalid.c: this module implements the character range + * validation APIs + * + * This file is automatically generated from the cvs source + * definition files using the genChRanges.py Python script + * + * Generation date: Mon Mar 27 11:09:48 2006 + * Sources: chvalid.def + * William Brack + */ + +#define IN_LIBXML +#include "libxml.h" +#include + +/* + * The initial tables ({func_name}_tab) are used to validate whether a + * single-byte character is within the specified group. Each table + * contains 256 bytes, with each byte representing one of the 256 + * possible characters. If the table byte is set, the character is + * allowed. + * + */ +const unsigned char xmlIsPubidChar_tab[256] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 }; + +static const xmlChSRange xmlIsBaseChar_srng[] = { {0x100, 0x131}, + {0x134, 0x13e}, {0x141, 0x148}, {0x14a, 0x17e}, {0x180, 0x1c3}, + {0x1cd, 0x1f0}, {0x1f4, 0x1f5}, {0x1fa, 0x217}, {0x250, 0x2a8}, + {0x2bb, 0x2c1}, {0x386, 0x386}, {0x388, 0x38a}, {0x38c, 0x38c}, + {0x38e, 0x3a1}, {0x3a3, 0x3ce}, {0x3d0, 0x3d6}, {0x3da, 0x3da}, + {0x3dc, 0x3dc}, {0x3de, 0x3de}, {0x3e0, 0x3e0}, {0x3e2, 0x3f3}, + {0x401, 0x40c}, {0x40e, 0x44f}, {0x451, 0x45c}, {0x45e, 0x481}, + {0x490, 0x4c4}, {0x4c7, 0x4c8}, {0x4cb, 0x4cc}, {0x4d0, 0x4eb}, + {0x4ee, 0x4f5}, {0x4f8, 0x4f9}, {0x531, 0x556}, {0x559, 0x559}, + {0x561, 0x586}, {0x5d0, 0x5ea}, {0x5f0, 0x5f2}, {0x621, 0x63a}, + {0x641, 0x64a}, {0x671, 0x6b7}, {0x6ba, 0x6be}, {0x6c0, 0x6ce}, + {0x6d0, 0x6d3}, {0x6d5, 0x6d5}, {0x6e5, 0x6e6}, {0x905, 0x939}, + {0x93d, 0x93d}, {0x958, 0x961}, {0x985, 0x98c}, {0x98f, 0x990}, + {0x993, 0x9a8}, {0x9aa, 0x9b0}, {0x9b2, 0x9b2}, {0x9b6, 0x9b9}, + {0x9dc, 0x9dd}, {0x9df, 0x9e1}, {0x9f0, 0x9f1}, {0xa05, 0xa0a}, + {0xa0f, 0xa10}, {0xa13, 0xa28}, {0xa2a, 0xa30}, {0xa32, 0xa33}, + {0xa35, 0xa36}, {0xa38, 0xa39}, {0xa59, 0xa5c}, {0xa5e, 0xa5e}, + {0xa72, 0xa74}, {0xa85, 0xa8b}, {0xa8d, 0xa8d}, {0xa8f, 0xa91}, + {0xa93, 0xaa8}, {0xaaa, 0xab0}, {0xab2, 0xab3}, {0xab5, 0xab9}, + {0xabd, 0xabd}, {0xae0, 0xae0}, {0xb05, 0xb0c}, {0xb0f, 0xb10}, + {0xb13, 0xb28}, {0xb2a, 0xb30}, {0xb32, 0xb33}, {0xb36, 0xb39}, + {0xb3d, 0xb3d}, {0xb5c, 0xb5d}, {0xb5f, 0xb61}, {0xb85, 0xb8a}, + {0xb8e, 0xb90}, {0xb92, 0xb95}, {0xb99, 0xb9a}, {0xb9c, 0xb9c}, + {0xb9e, 0xb9f}, {0xba3, 0xba4}, {0xba8, 0xbaa}, {0xbae, 0xbb5}, + {0xbb7, 0xbb9}, {0xc05, 0xc0c}, {0xc0e, 0xc10}, {0xc12, 0xc28}, + {0xc2a, 0xc33}, {0xc35, 0xc39}, {0xc60, 0xc61}, {0xc85, 0xc8c}, + {0xc8e, 0xc90}, {0xc92, 0xca8}, {0xcaa, 0xcb3}, {0xcb5, 0xcb9}, + {0xcde, 0xcde}, {0xce0, 0xce1}, {0xd05, 0xd0c}, {0xd0e, 0xd10}, + {0xd12, 0xd28}, {0xd2a, 0xd39}, {0xd60, 0xd61}, {0xe01, 0xe2e}, + {0xe30, 0xe30}, {0xe32, 0xe33}, {0xe40, 0xe45}, {0xe81, 0xe82}, + {0xe84, 0xe84}, {0xe87, 0xe88}, {0xe8a, 0xe8a}, {0xe8d, 0xe8d}, + {0xe94, 0xe97}, {0xe99, 0xe9f}, {0xea1, 0xea3}, {0xea5, 0xea5}, + {0xea7, 0xea7}, {0xeaa, 0xeab}, {0xead, 0xeae}, {0xeb0, 0xeb0}, + {0xeb2, 0xeb3}, {0xebd, 0xebd}, {0xec0, 0xec4}, {0xf40, 0xf47}, + {0xf49, 0xf69}, {0x10a0, 0x10c5}, {0x10d0, 0x10f6}, {0x1100, 0x1100}, + {0x1102, 0x1103}, {0x1105, 0x1107}, {0x1109, 0x1109}, {0x110b, 0x110c}, + {0x110e, 0x1112}, {0x113c, 0x113c}, {0x113e, 0x113e}, {0x1140, 0x1140}, + {0x114c, 0x114c}, {0x114e, 0x114e}, {0x1150, 0x1150}, {0x1154, 0x1155}, + {0x1159, 0x1159}, {0x115f, 0x1161}, {0x1163, 0x1163}, {0x1165, 0x1165}, + {0x1167, 0x1167}, {0x1169, 0x1169}, {0x116d, 0x116e}, {0x1172, 0x1173}, + {0x1175, 0x1175}, {0x119e, 0x119e}, {0x11a8, 0x11a8}, {0x11ab, 0x11ab}, + {0x11ae, 0x11af}, {0x11b7, 0x11b8}, {0x11ba, 0x11ba}, {0x11bc, 0x11c2}, + {0x11eb, 0x11eb}, {0x11f0, 0x11f0}, {0x11f9, 0x11f9}, {0x1e00, 0x1e9b}, + {0x1ea0, 0x1ef9}, {0x1f00, 0x1f15}, {0x1f18, 0x1f1d}, {0x1f20, 0x1f45}, + {0x1f48, 0x1f4d}, {0x1f50, 0x1f57}, {0x1f59, 0x1f59}, {0x1f5b, 0x1f5b}, + {0x1f5d, 0x1f5d}, {0x1f5f, 0x1f7d}, {0x1f80, 0x1fb4}, {0x1fb6, 0x1fbc}, + {0x1fbe, 0x1fbe}, {0x1fc2, 0x1fc4}, {0x1fc6, 0x1fcc}, {0x1fd0, 0x1fd3}, + {0x1fd6, 0x1fdb}, {0x1fe0, 0x1fec}, {0x1ff2, 0x1ff4}, {0x1ff6, 0x1ffc}, + {0x2126, 0x2126}, {0x212a, 0x212b}, {0x212e, 0x212e}, {0x2180, 0x2182}, + {0x3041, 0x3094}, {0x30a1, 0x30fa}, {0x3105, 0x312c}, {0xac00, 0xd7a3}}; +const xmlChRangeGroup xmlIsBaseCharGroup = + {197, 0, xmlIsBaseChar_srng, (xmlChLRangePtr)0}; + +static const xmlChSRange xmlIsChar_srng[] = { {0x100, 0xd7ff}, + {0xe000, 0xfffd}}; +static const xmlChLRange xmlIsChar_lrng[] = { {0x10000, 0x10ffff}}; +const xmlChRangeGroup xmlIsCharGroup = + {2, 1, xmlIsChar_srng, xmlIsChar_lrng}; + +static const xmlChSRange xmlIsCombining_srng[] = { {0x300, 0x345}, + {0x360, 0x361}, {0x483, 0x486}, {0x591, 0x5a1}, {0x5a3, 0x5b9}, + {0x5bb, 0x5bd}, {0x5bf, 0x5bf}, {0x5c1, 0x5c2}, {0x5c4, 0x5c4}, + {0x64b, 0x652}, {0x670, 0x670}, {0x6d6, 0x6dc}, {0x6dd, 0x6df}, + {0x6e0, 0x6e4}, {0x6e7, 0x6e8}, {0x6ea, 0x6ed}, {0x901, 0x903}, + {0x93c, 0x93c}, {0x93e, 0x94c}, {0x94d, 0x94d}, {0x951, 0x954}, + {0x962, 0x963}, {0x981, 0x983}, {0x9bc, 0x9bc}, {0x9be, 0x9be}, + {0x9bf, 0x9bf}, {0x9c0, 0x9c4}, {0x9c7, 0x9c8}, {0x9cb, 0x9cd}, + {0x9d7, 0x9d7}, {0x9e2, 0x9e3}, {0xa02, 0xa02}, {0xa3c, 0xa3c}, + {0xa3e, 0xa3e}, {0xa3f, 0xa3f}, {0xa40, 0xa42}, {0xa47, 0xa48}, + {0xa4b, 0xa4d}, {0xa70, 0xa71}, {0xa81, 0xa83}, {0xabc, 0xabc}, + {0xabe, 0xac5}, {0xac7, 0xac9}, {0xacb, 0xacd}, {0xb01, 0xb03}, + {0xb3c, 0xb3c}, {0xb3e, 0xb43}, {0xb47, 0xb48}, {0xb4b, 0xb4d}, + {0xb56, 0xb57}, {0xb82, 0xb83}, {0xbbe, 0xbc2}, {0xbc6, 0xbc8}, + {0xbca, 0xbcd}, {0xbd7, 0xbd7}, {0xc01, 0xc03}, {0xc3e, 0xc44}, + {0xc46, 0xc48}, {0xc4a, 0xc4d}, {0xc55, 0xc56}, {0xc82, 0xc83}, + {0xcbe, 0xcc4}, {0xcc6, 0xcc8}, {0xcca, 0xccd}, {0xcd5, 0xcd6}, + {0xd02, 0xd03}, {0xd3e, 0xd43}, {0xd46, 0xd48}, {0xd4a, 0xd4d}, + {0xd57, 0xd57}, {0xe31, 0xe31}, {0xe34, 0xe3a}, {0xe47, 0xe4e}, + {0xeb1, 0xeb1}, {0xeb4, 0xeb9}, {0xebb, 0xebc}, {0xec8, 0xecd}, + {0xf18, 0xf19}, {0xf35, 0xf35}, {0xf37, 0xf37}, {0xf39, 0xf39}, + {0xf3e, 0xf3e}, {0xf3f, 0xf3f}, {0xf71, 0xf84}, {0xf86, 0xf8b}, + {0xf90, 0xf95}, {0xf97, 0xf97}, {0xf99, 0xfad}, {0xfb1, 0xfb7}, + {0xfb9, 0xfb9}, {0x20d0, 0x20dc}, {0x20e1, 0x20e1}, {0x302a, 0x302f}, + {0x3099, 0x3099}, {0x309a, 0x309a}}; +const xmlChRangeGroup xmlIsCombiningGroup = + {95, 0, xmlIsCombining_srng, (xmlChLRangePtr)0}; + +static const xmlChSRange xmlIsDigit_srng[] = { {0x660, 0x669}, + {0x6f0, 0x6f9}, {0x966, 0x96f}, {0x9e6, 0x9ef}, {0xa66, 0xa6f}, + {0xae6, 0xaef}, {0xb66, 0xb6f}, {0xbe7, 0xbef}, {0xc66, 0xc6f}, + {0xce6, 0xcef}, {0xd66, 0xd6f}, {0xe50, 0xe59}, {0xed0, 0xed9}, + {0xf20, 0xf29}}; +const xmlChRangeGroup xmlIsDigitGroup = + {14, 0, xmlIsDigit_srng, (xmlChLRangePtr)0}; + +static const xmlChSRange xmlIsExtender_srng[] = { {0x2d0, 0x2d0}, + {0x2d1, 0x2d1}, {0x387, 0x387}, {0x640, 0x640}, {0xe46, 0xe46}, + {0xec6, 0xec6}, {0x3005, 0x3005}, {0x3031, 0x3035}, {0x309d, 0x309e}, + {0x30fc, 0x30fe}}; +const xmlChRangeGroup xmlIsExtenderGroup = + {10, 0, xmlIsExtender_srng, (xmlChLRangePtr)0}; + +static const xmlChSRange xmlIsIdeographic_srng[] = { {0x3007, 0x3007}, + {0x3021, 0x3029}, {0x4e00, 0x9fa5}}; +const xmlChRangeGroup xmlIsIdeographicGroup = + {3, 0, xmlIsIdeographic_srng, (xmlChLRangePtr)0}; + + +/** + * xmlCharInRange: + * @val: character to be validated + * @rptr: pointer to range to be used to validate + * + * Does a binary search of the range table to determine if char + * is valid + * + * Returns: true if character valid, false otherwise + */ +int +xmlCharInRange (unsigned int val, const xmlChRangeGroup *rptr) { + int low, high, mid; + const xmlChSRange *sptr; + const xmlChLRange *lptr; + + if (rptr == NULL) return(0); + if (val < 0x10000) { /* is val in 'short' or 'long' array? */ + if (rptr->nbShortRange == 0) + return 0; + low = 0; + high = rptr->nbShortRange - 1; + sptr = rptr->shortRange; + while (low <= high) { + mid = (low + high) / 2; + if ((unsigned short) val < sptr[mid].low) { + high = mid - 1; + } else { + if ((unsigned short) val > sptr[mid].high) { + low = mid + 1; + } else { + return 1; + } + } + } + } else { + if (rptr->nbLongRange == 0) { + return 0; + } + low = 0; + high = rptr->nbLongRange - 1; + lptr = rptr->longRange; + while (low <= high) { + mid = (low + high) / 2; + if (val < lptr[mid].low) { + high = mid - 1; + } else { + if (val > lptr[mid].high) { + low = mid + 1; + } else { + return 1; + } + } + } + } + return 0; +} + + +/** + * xmlIsBaseChar: + * @ch: character to validate + * + * This function is DEPRECATED. + * Use xmlIsBaseChar_ch or xmlIsBaseCharQ instead + * + * Returns true if argument valid, false otherwise + */ +int +xmlIsBaseChar(unsigned int ch) { + return(xmlIsBaseCharQ(ch)); +} + + +/** + * xmlIsBlank: + * @ch: character to validate + * + * This function is DEPRECATED. + * Use xmlIsBlank_ch or xmlIsBlankQ instead + * + * Returns true if argument valid, false otherwise + */ +int +xmlIsBlank(unsigned int ch) { + return(xmlIsBlankQ(ch)); +} + + +/** + * xmlIsChar: + * @ch: character to validate + * + * This function is DEPRECATED. + * Use xmlIsChar_ch or xmlIsCharQ instead + * + * Returns true if argument valid, false otherwise + */ +int +xmlIsChar(unsigned int ch) { + return(xmlIsCharQ(ch)); +} + + +/** + * xmlIsCombining: + * @ch: character to validate + * + * This function is DEPRECATED. + * Use xmlIsCombiningQ instead + * + * Returns true if argument valid, false otherwise + */ +int +xmlIsCombining(unsigned int ch) { + return(xmlIsCombiningQ(ch)); +} + + +/** + * xmlIsDigit: + * @ch: character to validate + * + * This function is DEPRECATED. + * Use xmlIsDigit_ch or xmlIsDigitQ instead + * + * Returns true if argument valid, false otherwise + */ +int +xmlIsDigit(unsigned int ch) { + return(xmlIsDigitQ(ch)); +} + + +/** + * xmlIsExtender: + * @ch: character to validate + * + * This function is DEPRECATED. + * Use xmlIsExtender_ch or xmlIsExtenderQ instead + * + * Returns true if argument valid, false otherwise + */ +int +xmlIsExtender(unsigned int ch) { + return(xmlIsExtenderQ(ch)); +} + + +/** + * xmlIsIdeographic: + * @ch: character to validate + * + * This function is DEPRECATED. + * Use xmlIsIdeographicQ instead + * + * Returns true if argument valid, false otherwise + */ +int +xmlIsIdeographic(unsigned int ch) { + return(xmlIsIdeographicQ(ch)); +} + + +/** + * xmlIsPubidChar: + * @ch: character to validate + * + * This function is DEPRECATED. + * Use xmlIsPubidChar_ch or xmlIsPubidCharQ instead + * + * Returns true if argument valid, false otherwise + */ +int +xmlIsPubidChar(unsigned int ch) { + return(xmlIsPubidCharQ(ch)); +} + +#define bottom_chvalid +#include "elfgcchack.h" diff --git a/gettext-tools/gnulib-lib/libxml/chvalid.in.h b/gettext-tools/gnulib-lib/libxml/chvalid.in.h new file mode 100644 index 0000000..fb43016 --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/chvalid.in.h @@ -0,0 +1,230 @@ +/* + * Summary: Unicode character range checking + * Description: this module exports interfaces for the character + * range validation APIs + * + * This file is automatically generated from the cvs source + * definition files using the genChRanges.py Python script + * + * Generation date: Mon Mar 27 11:09:48 2006 + * Sources: chvalid.def + * Author: William Brack + */ + +#ifndef __XML_CHVALID_H__ +#define __XML_CHVALID_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Define our typedefs and structures + * + */ +typedef struct _xmlChSRange xmlChSRange; +typedef xmlChSRange *xmlChSRangePtr; +struct _xmlChSRange { + unsigned short low; + unsigned short high; +}; + +typedef struct _xmlChLRange xmlChLRange; +typedef xmlChLRange *xmlChLRangePtr; +struct _xmlChLRange { + unsigned int low; + unsigned int high; +}; + +typedef struct _xmlChRangeGroup xmlChRangeGroup; +typedef xmlChRangeGroup *xmlChRangeGroupPtr; +struct _xmlChRangeGroup { + int nbShortRange; + int nbLongRange; + const xmlChSRange *shortRange; /* points to an array of ranges */ + const xmlChLRange *longRange; +}; + +/** + * Range checking routine + */ +XMLPUBFUN int XMLCALL + xmlCharInRange(unsigned int val, const xmlChRangeGroup *group); + + +/** + * xmlIsBaseChar_ch: + * @c: char to validate + * + * Automatically generated by genChRanges.py + */ +#define xmlIsBaseChar_ch(c) (((0x41 <= (c)) && ((c) <= 0x5a)) || \ + ((0x61 <= (c)) && ((c) <= 0x7a)) || \ + ((0xc0 <= (c)) && ((c) <= 0xd6)) || \ + ((0xd8 <= (c)) && ((c) <= 0xf6)) || \ + (0xf8 <= (c))) + +/** + * xmlIsBaseCharQ: + * @c: char to validate + * + * Automatically generated by genChRanges.py + */ +#define xmlIsBaseCharQ(c) (((c) < 0x100) ? \ + xmlIsBaseChar_ch((c)) : \ + xmlCharInRange((c), &xmlIsBaseCharGroup)) + +XMLPUBVAR const xmlChRangeGroup xmlIsBaseCharGroup; + +/** + * xmlIsBlank_ch: + * @c: char to validate + * + * Automatically generated by genChRanges.py + */ +#define xmlIsBlank_ch(c) (((c) == 0x20) || \ + ((0x9 <= (c)) && ((c) <= 0xa)) || \ + ((c) == 0xd)) + +/** + * xmlIsBlankQ: + * @c: char to validate + * + * Automatically generated by genChRanges.py + */ +#define xmlIsBlankQ(c) (((c) < 0x100) ? \ + xmlIsBlank_ch((c)) : 0) + + +/** + * xmlIsChar_ch: + * @c: char to validate + * + * Automatically generated by genChRanges.py + */ +#define xmlIsChar_ch(c) (((0x9 <= (c)) && ((c) <= 0xa)) || \ + ((c) == 0xd) || \ + (0x20 <= (c))) + +/** + * xmlIsCharQ: + * @c: char to validate + * + * Automatically generated by genChRanges.py + */ +#define xmlIsCharQ(c) (((c) < 0x100) ? \ + xmlIsChar_ch((c)) :\ + (((0x100 <= (c)) && ((c) <= 0xd7ff)) || \ + ((0xe000 <= (c)) && ((c) <= 0xfffd)) || \ + ((0x10000 <= (c)) && ((c) <= 0x10ffff)))) + +XMLPUBVAR const xmlChRangeGroup xmlIsCharGroup; + +/** + * xmlIsCombiningQ: + * @c: char to validate + * + * Automatically generated by genChRanges.py + */ +#define xmlIsCombiningQ(c) (((c) < 0x100) ? \ + 0 : \ + xmlCharInRange((c), &xmlIsCombiningGroup)) + +XMLPUBVAR const xmlChRangeGroup xmlIsCombiningGroup; + +/** + * xmlIsDigit_ch: + * @c: char to validate + * + * Automatically generated by genChRanges.py + */ +#define xmlIsDigit_ch(c) (((0x30 <= (c)) && ((c) <= 0x39))) + +/** + * xmlIsDigitQ: + * @c: char to validate + * + * Automatically generated by genChRanges.py + */ +#define xmlIsDigitQ(c) (((c) < 0x100) ? \ + xmlIsDigit_ch((c)) : \ + xmlCharInRange((c), &xmlIsDigitGroup)) + +XMLPUBVAR const xmlChRangeGroup xmlIsDigitGroup; + +/** + * xmlIsExtender_ch: + * @c: char to validate + * + * Automatically generated by genChRanges.py + */ +#define xmlIsExtender_ch(c) (((c) == 0xb7)) + +/** + * xmlIsExtenderQ: + * @c: char to validate + * + * Automatically generated by genChRanges.py + */ +#define xmlIsExtenderQ(c) (((c) < 0x100) ? \ + xmlIsExtender_ch((c)) : \ + xmlCharInRange((c), &xmlIsExtenderGroup)) + +XMLPUBVAR const xmlChRangeGroup xmlIsExtenderGroup; + +/** + * xmlIsIdeographicQ: + * @c: char to validate + * + * Automatically generated by genChRanges.py + */ +#define xmlIsIdeographicQ(c) (((c) < 0x100) ? \ + 0 :\ + (((0x4e00 <= (c)) && ((c) <= 0x9fa5)) || \ + ((c) == 0x3007) || \ + ((0x3021 <= (c)) && ((c) <= 0x3029)))) + +XMLPUBVAR const xmlChRangeGroup xmlIsIdeographicGroup; +XMLPUBVAR const unsigned char xmlIsPubidChar_tab[256]; + +/** + * xmlIsPubidChar_ch: + * @c: char to validate + * + * Automatically generated by genChRanges.py + */ +#define xmlIsPubidChar_ch(c) (xmlIsPubidChar_tab[(c)]) + +/** + * xmlIsPubidCharQ: + * @c: char to validate + * + * Automatically generated by genChRanges.py + */ +#define xmlIsPubidCharQ(c) (((c) < 0x100) ? \ + xmlIsPubidChar_ch((c)) : 0) + +XMLPUBFUN int XMLCALL + xmlIsBaseChar(unsigned int ch); +XMLPUBFUN int XMLCALL + xmlIsBlank(unsigned int ch); +XMLPUBFUN int XMLCALL + xmlIsChar(unsigned int ch); +XMLPUBFUN int XMLCALL + xmlIsCombining(unsigned int ch); +XMLPUBFUN int XMLCALL + xmlIsDigit(unsigned int ch); +XMLPUBFUN int XMLCALL + xmlIsExtender(unsigned int ch); +XMLPUBFUN int XMLCALL + xmlIsIdeographic(unsigned int ch); +XMLPUBFUN int XMLCALL + xmlIsPubidChar(unsigned int ch); + +#ifdef __cplusplus +} +#endif +#endif /* __XML_CHVALID_H__ */ diff --git a/gettext-tools/gnulib-lib/libxml/debugXML.c b/gettext-tools/gnulib-lib/libxml/debugXML.c new file mode 100644 index 0000000..3985ad3 --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/debugXML.c @@ -0,0 +1,3264 @@ +/* + * debugXML.c : This is a set of routines used for debugging the tree + * produced by the XML parser. + * + * See Copyright for the status of this software. + * + * Daniel Veillard + */ + +#define IN_LIBXML +#include "libxml.h" +#ifdef LIBXML_DEBUG_ENABLED + +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef LIBXML_SCHEMAS_ENABLED +#include +#endif + +#define DUMP_TEXT_TYPE 1 + +typedef struct _xmlDebugCtxt xmlDebugCtxt; +typedef xmlDebugCtxt *xmlDebugCtxtPtr; +struct _xmlDebugCtxt { + FILE *output; /* the output file */ + char shift[101]; /* used for indenting */ + int depth; /* current depth */ + xmlDocPtr doc; /* current document */ + xmlNodePtr node; /* current node */ + xmlDictPtr dict; /* the doc dictionnary */ + int check; /* do just checkings */ + int errors; /* number of errors found */ + int nodict; /* if the document has no dictionnary */ + int options; /* options */ +}; + +static void xmlCtxtDumpNodeList(xmlDebugCtxtPtr ctxt, xmlNodePtr node); + +static void +xmlCtxtDumpInitCtxt(xmlDebugCtxtPtr ctxt) +{ + int i; + + ctxt->depth = 0; + ctxt->check = 0; + ctxt->errors = 0; + ctxt->output = stdout; + ctxt->doc = NULL; + ctxt->node = NULL; + ctxt->dict = NULL; + ctxt->nodict = 0; + ctxt->options = 0; + for (i = 0; i < 100; i++) + ctxt->shift[i] = ' '; + ctxt->shift[100] = 0; +} + +static void +xmlCtxtDumpCleanCtxt(xmlDebugCtxtPtr ctxt ATTRIBUTE_UNUSED) +{ + /* remove the ATTRIBUTE_UNUSED when this is added */ +} + +/** + * xmlNsCheckScope: + * @node: the node + * @ns: the namespace node + * + * Check that a given namespace is in scope on a node. + * + * Returns 1 if in scope, -1 in case of argument error, + * -2 if the namespace is not in scope, and -3 if not on + * an ancestor node. + */ +static int +xmlNsCheckScope(xmlNodePtr node, xmlNsPtr ns) +{ + xmlNsPtr cur; + + if ((node == NULL) || (ns == NULL)) + return(-1); + + if ((node->type != XML_ELEMENT_NODE) && + (node->type != XML_ATTRIBUTE_NODE) && + (node->type != XML_DOCUMENT_NODE) && + (node->type != XML_TEXT_NODE) && + (node->type != XML_HTML_DOCUMENT_NODE) && + (node->type != XML_XINCLUDE_START)) + return(-2); + + while ((node != NULL) && + ((node->type == XML_ELEMENT_NODE) || + (node->type == XML_ATTRIBUTE_NODE) || + (node->type == XML_TEXT_NODE) || + (node->type == XML_XINCLUDE_START))) { + if ((node->type == XML_ELEMENT_NODE) || + (node->type == XML_XINCLUDE_START)) { + cur = node->nsDef; + while (cur != NULL) { + if (cur == ns) + return(1); + if (xmlStrEqual(cur->prefix, ns->prefix)) + return(-2); + cur = cur->next; + } + } + node = node->parent; + } + /* the xml namespace may be declared on the document node */ + if ((node != NULL) && + ((node->type == XML_DOCUMENT_NODE) || + (node->type == XML_HTML_DOCUMENT_NODE))) { + xmlNsPtr oldNs = ((xmlDocPtr) node)->oldNs; + if (oldNs == ns) + return(1); + } + return(-3); +} + +static void +xmlCtxtDumpSpaces(xmlDebugCtxtPtr ctxt) +{ + if (ctxt->check) + return; + if ((ctxt->output != NULL) && (ctxt->depth > 0)) { + if (ctxt->depth < 50) + fprintf(ctxt->output, &ctxt->shift[100 - 2 * ctxt->depth]); + else + fprintf(ctxt->output, ctxt->shift); + } +} + +/** + * xmlDebugErr: + * @ctxt: a debug context + * @error: the error code + * + * Handle a debug error. + */ +static void +xmlDebugErr(xmlDebugCtxtPtr ctxt, int error, const char *msg) +{ + ctxt->errors++; + __xmlRaiseError(NULL, NULL, NULL, + NULL, ctxt->node, XML_FROM_CHECK, + error, XML_ERR_ERROR, NULL, 0, + NULL, NULL, NULL, 0, 0, + msg); +} +static void +xmlDebugErr2(xmlDebugCtxtPtr ctxt, int error, const char *msg, int extra) +{ + ctxt->errors++; + __xmlRaiseError(NULL, NULL, NULL, + NULL, ctxt->node, XML_FROM_CHECK, + error, XML_ERR_ERROR, NULL, 0, + NULL, NULL, NULL, 0, 0, + msg, extra); +} +static void +xmlDebugErr3(xmlDebugCtxtPtr ctxt, int error, const char *msg, const char *extra) +{ + ctxt->errors++; + __xmlRaiseError(NULL, NULL, NULL, + NULL, ctxt->node, XML_FROM_CHECK, + error, XML_ERR_ERROR, NULL, 0, + NULL, NULL, NULL, 0, 0, + msg, extra); +} + +/** + * xmlCtxtNsCheckScope: + * @ctxt: the debugging context + * @node: the node + * @ns: the namespace node + * + * Report if a given namespace is is not in scope. + */ +static void +xmlCtxtNsCheckScope(xmlDebugCtxtPtr ctxt, xmlNodePtr node, xmlNsPtr ns) +{ + int ret; + + ret = xmlNsCheckScope(node, ns); + if (ret == -2) { + if (ns->prefix == NULL) + xmlDebugErr(ctxt, XML_CHECK_NS_SCOPE, + "Reference to default namespace not in scope\n"); + else + xmlDebugErr3(ctxt, XML_CHECK_NS_SCOPE, + "Reference to namespace '%s' not in scope\n", + (char *) ns->prefix); + } + if (ret == -3) { + if (ns->prefix == NULL) + xmlDebugErr(ctxt, XML_CHECK_NS_ANCESTOR, + "Reference to default namespace not on ancestor\n"); + else + xmlDebugErr3(ctxt, XML_CHECK_NS_ANCESTOR, + "Reference to namespace '%s' not on ancestor\n", + (char *) ns->prefix); + } +} + +/** + * xmlCtxtCheckString: + * @ctxt: the debug context + * @str: the string + * + * Do debugging on the string, currently it just checks the UTF-8 content + */ +static void +xmlCtxtCheckString(xmlDebugCtxtPtr ctxt, const xmlChar * str) +{ + if (str == NULL) return; + if (ctxt->check) { + if (!xmlCheckUTF8(str)) { + xmlDebugErr3(ctxt, XML_CHECK_NOT_UTF8, + "String is not UTF-8 %s", (const char *) str); + } + } +} + +/** + * xmlCtxtCheckName: + * @ctxt: the debug context + * @name: the name + * + * Do debugging on the name, for example the dictionnary status and + * conformance to the Name production. + */ +static void +xmlCtxtCheckName(xmlDebugCtxtPtr ctxt, const xmlChar * name) +{ + if (ctxt->check) { + if (name == NULL) { + xmlDebugErr(ctxt, XML_CHECK_NO_NAME, "Name is NULL"); + return; + } + if (xmlValidateName(name, 0)) { + xmlDebugErr3(ctxt, XML_CHECK_NOT_NCNAME, + "Name is not an NCName '%s'", (const char *) name); + } + if ((ctxt->dict != NULL) && + (!xmlDictOwns(ctxt->dict, name))) { + xmlDebugErr3(ctxt, XML_CHECK_OUTSIDE_DICT, + "Name is not from the document dictionnary '%s'", + (const char *) name); + } + } +} + +static void +xmlCtxtGenericNodeCheck(xmlDebugCtxtPtr ctxt, xmlNodePtr node) { + xmlDocPtr doc; + xmlDictPtr dict; + + doc = node->doc; + + if (node->parent == NULL) + xmlDebugErr(ctxt, XML_CHECK_NO_PARENT, + "Node has no parent\n"); + if (node->doc == NULL) { + xmlDebugErr(ctxt, XML_CHECK_NO_DOC, + "Node has no doc\n"); + dict = NULL; + } else { + dict = doc->dict; + if ((dict == NULL) && (ctxt->nodict == 0)) { +#if 0 + /* desactivated right now as it raises too many errors */ + if (doc->type == XML_DOCUMENT_NODE) + xmlDebugErr(ctxt, XML_CHECK_NO_DICT, + "Document has no dictionnary\n"); +#endif + ctxt->nodict = 1; + } + if (ctxt->doc == NULL) + ctxt->doc = doc; + + if (ctxt->dict == NULL) { + ctxt->dict = dict; + } + } + if ((node->parent != NULL) && (node->doc != node->parent->doc) && + (!xmlStrEqual(node->name, BAD_CAST "pseudoroot"))) + xmlDebugErr(ctxt, XML_CHECK_WRONG_DOC, + "Node doc differs from parent's one\n"); + if (node->prev == NULL) { + if (node->type == XML_ATTRIBUTE_NODE) { + if ((node->parent != NULL) && + (node != (xmlNodePtr) node->parent->properties)) + xmlDebugErr(ctxt, XML_CHECK_NO_PREV, + "Attr has no prev and not first of attr list\n"); + + } else if ((node->parent != NULL) && (node->parent->children != node)) + xmlDebugErr(ctxt, XML_CHECK_NO_PREV, + "Node has no prev and not first of parent list\n"); + } else { + if (node->prev->next != node) + xmlDebugErr(ctxt, XML_CHECK_WRONG_PREV, + "Node prev->next : back link wrong\n"); + } + if (node->next == NULL) { + if ((node->parent != NULL) && (node->type != XML_ATTRIBUTE_NODE) && + (node->parent->last != node)) + xmlDebugErr(ctxt, XML_CHECK_NO_NEXT, + "Node has no next and not last of parent list\n"); + } else { + if (node->next->prev != node) + xmlDebugErr(ctxt, XML_CHECK_WRONG_NEXT, + "Node next->prev : forward link wrong\n"); + if (node->next->parent != node->parent) + xmlDebugErr(ctxt, XML_CHECK_WRONG_PARENT, + "Node next->prev : forward link wrong\n"); + } + if (node->type == XML_ELEMENT_NODE) { + xmlNsPtr ns; + + ns = node->nsDef; + while (ns != NULL) { + xmlCtxtNsCheckScope(ctxt, node, ns); + ns = ns->next; + } + if (node->ns != NULL) + xmlCtxtNsCheckScope(ctxt, node, node->ns); + } else if (node->type == XML_ATTRIBUTE_NODE) { + if (node->ns != NULL) + xmlCtxtNsCheckScope(ctxt, node, node->ns); + } + + if ((node->type != XML_ELEMENT_NODE) && + (node->type != XML_ATTRIBUTE_NODE) && + (node->type != XML_ELEMENT_DECL) && + (node->type != XML_ATTRIBUTE_DECL) && + (node->type != XML_DTD_NODE) && + (node->type != XML_ELEMENT_DECL) && + (node->type != XML_HTML_DOCUMENT_NODE) && + (node->type != XML_DOCUMENT_NODE)) { + if (node->content != NULL) + xmlCtxtCheckString(ctxt, (const xmlChar *) node->content); + } + switch (node->type) { + case XML_ELEMENT_NODE: + case XML_ATTRIBUTE_NODE: + xmlCtxtCheckName(ctxt, node->name); + break; + case XML_TEXT_NODE: + if ((node->name == xmlStringText) || + (node->name == xmlStringTextNoenc)) + break; + /* some case of entity substitution can lead to this */ + if ((ctxt->dict != NULL) && + (node->name == xmlDictLookup(ctxt->dict, BAD_CAST "nbktext", + 7))) + break; + + xmlDebugErr3(ctxt, XML_CHECK_WRONG_NAME, + "Text node has wrong name '%s'", + (const char *) node->name); + break; + case XML_COMMENT_NODE: + if (node->name == xmlStringComment) + break; + xmlDebugErr3(ctxt, XML_CHECK_WRONG_NAME, + "Comment node has wrong name '%s'", + (const char *) node->name); + break; + case XML_PI_NODE: + xmlCtxtCheckName(ctxt, node->name); + break; + case XML_CDATA_SECTION_NODE: + if (node->name == NULL) + break; + xmlDebugErr3(ctxt, XML_CHECK_NAME_NOT_NULL, + "CData section has non NULL name '%s'", + (const char *) node->name); + break; + case XML_ENTITY_REF_NODE: + case XML_ENTITY_NODE: + case XML_DOCUMENT_TYPE_NODE: + case XML_DOCUMENT_FRAG_NODE: + case XML_NOTATION_NODE: + case XML_DTD_NODE: + case XML_ELEMENT_DECL: + case XML_ATTRIBUTE_DECL: + case XML_ENTITY_DECL: + case XML_NAMESPACE_DECL: + case XML_XINCLUDE_START: + case XML_XINCLUDE_END: +#ifdef LIBXML_DOCB_ENABLED + case XML_DOCB_DOCUMENT_NODE: +#endif + case XML_DOCUMENT_NODE: + case XML_HTML_DOCUMENT_NODE: + break; + } +} + +static void +xmlCtxtDumpString(xmlDebugCtxtPtr ctxt, const xmlChar * str) +{ + int i; + + if (ctxt->check) { + return; + } + /* TODO: check UTF8 content of the string */ + if (str == NULL) { + fprintf(ctxt->output, "(NULL)"); + return; + } + for (i = 0; i < 40; i++) + if (str[i] == 0) + return; + else if (IS_BLANK_CH(str[i])) + fputc(' ', ctxt->output); + else if (str[i] >= 0x80) + fprintf(ctxt->output, "#%X", str[i]); + else + fputc(str[i], ctxt->output); + fprintf(ctxt->output, "..."); +} + +static void +xmlCtxtDumpDtdNode(xmlDebugCtxtPtr ctxt, xmlDtdPtr dtd) +{ + xmlCtxtDumpSpaces(ctxt); + + if (dtd == NULL) { + if (!ctxt->check) + fprintf(ctxt->output, "DTD node is NULL\n"); + return; + } + + if (dtd->type != XML_DTD_NODE) { + xmlDebugErr(ctxt, XML_CHECK_NOT_DTD, + "Node is not a DTD"); + return; + } + if (!ctxt->check) { + if (dtd->name != NULL) + fprintf(ctxt->output, "DTD(%s)", (char *) dtd->name); + else + fprintf(ctxt->output, "DTD"); + if (dtd->ExternalID != NULL) + fprintf(ctxt->output, ", PUBLIC %s", (char *) dtd->ExternalID); + if (dtd->SystemID != NULL) + fprintf(ctxt->output, ", SYSTEM %s", (char *) dtd->SystemID); + fprintf(ctxt->output, "\n"); + } + /* + * Do a bit of checking + */ + xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) dtd); +} + +static void +xmlCtxtDumpAttrDecl(xmlDebugCtxtPtr ctxt, xmlAttributePtr attr) +{ + xmlCtxtDumpSpaces(ctxt); + + if (attr == NULL) { + if (!ctxt->check) + fprintf(ctxt->output, "Attribute declaration is NULL\n"); + return; + } + if (attr->type != XML_ATTRIBUTE_DECL) { + xmlDebugErr(ctxt, XML_CHECK_NOT_ATTR_DECL, + "Node is not an attribute declaration"); + return; + } + if (attr->name != NULL) { + if (!ctxt->check) + fprintf(ctxt->output, "ATTRDECL(%s)", (char *) attr->name); + } else + xmlDebugErr(ctxt, XML_CHECK_NO_NAME, + "Node attribute declaration has no name"); + if (attr->elem != NULL) { + if (!ctxt->check) + fprintf(ctxt->output, " for %s", (char *) attr->elem); + } else + xmlDebugErr(ctxt, XML_CHECK_NO_ELEM, + "Node attribute declaration has no element name"); + if (!ctxt->check) { + switch (attr->atype) { + case XML_ATTRIBUTE_CDATA: + fprintf(ctxt->output, " CDATA"); + break; + case XML_ATTRIBUTE_ID: + fprintf(ctxt->output, " ID"); + break; + case XML_ATTRIBUTE_IDREF: + fprintf(ctxt->output, " IDREF"); + break; + case XML_ATTRIBUTE_IDREFS: + fprintf(ctxt->output, " IDREFS"); + break; + case XML_ATTRIBUTE_ENTITY: + fprintf(ctxt->output, " ENTITY"); + break; + case XML_ATTRIBUTE_ENTITIES: + fprintf(ctxt->output, " ENTITIES"); + break; + case XML_ATTRIBUTE_NMTOKEN: + fprintf(ctxt->output, " NMTOKEN"); + break; + case XML_ATTRIBUTE_NMTOKENS: + fprintf(ctxt->output, " NMTOKENS"); + break; + case XML_ATTRIBUTE_ENUMERATION: + fprintf(ctxt->output, " ENUMERATION"); + break; + case XML_ATTRIBUTE_NOTATION: + fprintf(ctxt->output, " NOTATION "); + break; + } + if (attr->tree != NULL) { + int indx; + xmlEnumerationPtr cur = attr->tree; + + for (indx = 0; indx < 5; indx++) { + if (indx != 0) + fprintf(ctxt->output, "|%s", (char *) cur->name); + else + fprintf(ctxt->output, " (%s", (char *) cur->name); + cur = cur->next; + if (cur == NULL) + break; + } + if (cur == NULL) + fprintf(ctxt->output, ")"); + else + fprintf(ctxt->output, "...)"); + } + switch (attr->def) { + case XML_ATTRIBUTE_NONE: + break; + case XML_ATTRIBUTE_REQUIRED: + fprintf(ctxt->output, " REQUIRED"); + break; + case XML_ATTRIBUTE_IMPLIED: + fprintf(ctxt->output, " IMPLIED"); + break; + case XML_ATTRIBUTE_FIXED: + fprintf(ctxt->output, " FIXED"); + break; + } + if (attr->defaultValue != NULL) { + fprintf(ctxt->output, "\""); + xmlCtxtDumpString(ctxt, attr->defaultValue); + fprintf(ctxt->output, "\""); + } + fprintf(ctxt->output, "\n"); + } + + /* + * Do a bit of checking + */ + xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) attr); +} + +static void +xmlCtxtDumpElemDecl(xmlDebugCtxtPtr ctxt, xmlElementPtr elem) +{ + xmlCtxtDumpSpaces(ctxt); + + if (elem == NULL) { + if (!ctxt->check) + fprintf(ctxt->output, "Element declaration is NULL\n"); + return; + } + if (elem->type != XML_ELEMENT_DECL) { + xmlDebugErr(ctxt, XML_CHECK_NOT_ELEM_DECL, + "Node is not an element declaration"); + return; + } + if (elem->name != NULL) { + if (!ctxt->check) { + fprintf(ctxt->output, "ELEMDECL("); + xmlCtxtDumpString(ctxt, elem->name); + fprintf(ctxt->output, ")"); + } + } else + xmlDebugErr(ctxt, XML_CHECK_NO_NAME, + "Element declaration has no name"); + if (!ctxt->check) { + switch (elem->etype) { + case XML_ELEMENT_TYPE_UNDEFINED: + fprintf(ctxt->output, ", UNDEFINED"); + break; + case XML_ELEMENT_TYPE_EMPTY: + fprintf(ctxt->output, ", EMPTY"); + break; + case XML_ELEMENT_TYPE_ANY: + fprintf(ctxt->output, ", ANY"); + break; + case XML_ELEMENT_TYPE_MIXED: + fprintf(ctxt->output, ", MIXED "); + break; + case XML_ELEMENT_TYPE_ELEMENT: + fprintf(ctxt->output, ", MIXED "); + break; + } + if ((elem->type != XML_ELEMENT_NODE) && (elem->content != NULL)) { + char buf[5001]; + + buf[0] = 0; + xmlSnprintfElementContent(buf, 5000, elem->content, 1); + buf[5000] = 0; + fprintf(ctxt->output, "%s", buf); + } + fprintf(ctxt->output, "\n"); + } + + /* + * Do a bit of checking + */ + xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) elem); +} + +static void +xmlCtxtDumpEntityDecl(xmlDebugCtxtPtr ctxt, xmlEntityPtr ent) +{ + xmlCtxtDumpSpaces(ctxt); + + if (ent == NULL) { + if (!ctxt->check) + fprintf(ctxt->output, "Entity declaration is NULL\n"); + return; + } + if (ent->type != XML_ENTITY_DECL) { + xmlDebugErr(ctxt, XML_CHECK_NOT_ENTITY_DECL, + "Node is not an entity declaration"); + return; + } + if (ent->name != NULL) { + if (!ctxt->check) { + fprintf(ctxt->output, "ENTITYDECL("); + xmlCtxtDumpString(ctxt, ent->name); + fprintf(ctxt->output, ")"); + } + } else + xmlDebugErr(ctxt, XML_CHECK_NO_NAME, + "Entity declaration has no name"); + if (!ctxt->check) { + switch (ent->etype) { + case XML_INTERNAL_GENERAL_ENTITY: + fprintf(ctxt->output, ", internal\n"); + break; + case XML_EXTERNAL_GENERAL_PARSED_ENTITY: + fprintf(ctxt->output, ", external parsed\n"); + break; + case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY: + fprintf(ctxt->output, ", unparsed\n"); + break; + case XML_INTERNAL_PARAMETER_ENTITY: + fprintf(ctxt->output, ", parameter\n"); + break; + case XML_EXTERNAL_PARAMETER_ENTITY: + fprintf(ctxt->output, ", external parameter\n"); + break; + case XML_INTERNAL_PREDEFINED_ENTITY: + fprintf(ctxt->output, ", predefined\n"); + break; + } + if (ent->ExternalID) { + xmlCtxtDumpSpaces(ctxt); + fprintf(ctxt->output, " ExternalID=%s\n", + (char *) ent->ExternalID); + } + if (ent->SystemID) { + xmlCtxtDumpSpaces(ctxt); + fprintf(ctxt->output, " SystemID=%s\n", + (char *) ent->SystemID); + } + if (ent->URI != NULL) { + xmlCtxtDumpSpaces(ctxt); + fprintf(ctxt->output, " URI=%s\n", (char *) ent->URI); + } + if (ent->content) { + xmlCtxtDumpSpaces(ctxt); + fprintf(ctxt->output, " content="); + xmlCtxtDumpString(ctxt, ent->content); + fprintf(ctxt->output, "\n"); + } + } + + /* + * Do a bit of checking + */ + xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) ent); +} + +static void +xmlCtxtDumpNamespace(xmlDebugCtxtPtr ctxt, xmlNsPtr ns) +{ + xmlCtxtDumpSpaces(ctxt); + + if (ns == NULL) { + if (!ctxt->check) + fprintf(ctxt->output, "namespace node is NULL\n"); + return; + } + if (ns->type != XML_NAMESPACE_DECL) { + xmlDebugErr(ctxt, XML_CHECK_NOT_NS_DECL, + "Node is not a namespace declaration"); + return; + } + if (ns->href == NULL) { + if (ns->prefix != NULL) + xmlDebugErr3(ctxt, XML_CHECK_NO_HREF, + "Incomplete namespace %s href=NULL\n", + (char *) ns->prefix); + else + xmlDebugErr(ctxt, XML_CHECK_NO_HREF, + "Incomplete default namespace href=NULL\n"); + } else { + if (!ctxt->check) { + if (ns->prefix != NULL) + fprintf(ctxt->output, "namespace %s href=", + (char *) ns->prefix); + else + fprintf(ctxt->output, "default namespace href="); + + xmlCtxtDumpString(ctxt, ns->href); + fprintf(ctxt->output, "\n"); + } + } +} + +static void +xmlCtxtDumpNamespaceList(xmlDebugCtxtPtr ctxt, xmlNsPtr ns) +{ + while (ns != NULL) { + xmlCtxtDumpNamespace(ctxt, ns); + ns = ns->next; + } +} + +static void +xmlCtxtDumpEntity(xmlDebugCtxtPtr ctxt, xmlEntityPtr ent) +{ + xmlCtxtDumpSpaces(ctxt); + + if (ent == NULL) { + if (!ctxt->check) + fprintf(ctxt->output, "Entity is NULL\n"); + return; + } + if (!ctxt->check) { + switch (ent->etype) { + case XML_INTERNAL_GENERAL_ENTITY: + fprintf(ctxt->output, "INTERNAL_GENERAL_ENTITY "); + break; + case XML_EXTERNAL_GENERAL_PARSED_ENTITY: + fprintf(ctxt->output, "EXTERNAL_GENERAL_PARSED_ENTITY "); + break; + case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY: + fprintf(ctxt->output, "EXTERNAL_GENERAL_UNPARSED_ENTITY "); + break; + case XML_INTERNAL_PARAMETER_ENTITY: + fprintf(ctxt->output, "INTERNAL_PARAMETER_ENTITY "); + break; + case XML_EXTERNAL_PARAMETER_ENTITY: + fprintf(ctxt->output, "EXTERNAL_PARAMETER_ENTITY "); + break; + default: + fprintf(ctxt->output, "ENTITY_%d ! ", (int) ent->etype); + } + fprintf(ctxt->output, "%s\n", ent->name); + if (ent->ExternalID) { + xmlCtxtDumpSpaces(ctxt); + fprintf(ctxt->output, "ExternalID=%s\n", + (char *) ent->ExternalID); + } + if (ent->SystemID) { + xmlCtxtDumpSpaces(ctxt); + fprintf(ctxt->output, "SystemID=%s\n", (char *) ent->SystemID); + } + if (ent->URI) { + xmlCtxtDumpSpaces(ctxt); + fprintf(ctxt->output, "URI=%s\n", (char *) ent->URI); + } + if (ent->content) { + xmlCtxtDumpSpaces(ctxt); + fprintf(ctxt->output, "content="); + xmlCtxtDumpString(ctxt, ent->content); + fprintf(ctxt->output, "\n"); + } + } +} + +/** + * xmlCtxtDumpAttr: + * @output: the FILE * for the output + * @attr: the attribute + * @depth: the indentation level. + * + * Dumps debug information for the attribute + */ +static void +xmlCtxtDumpAttr(xmlDebugCtxtPtr ctxt, xmlAttrPtr attr) +{ + xmlCtxtDumpSpaces(ctxt); + + if (attr == NULL) { + if (!ctxt->check) + fprintf(ctxt->output, "Attr is NULL"); + return; + } + if (!ctxt->check) { + fprintf(ctxt->output, "ATTRIBUTE "); + xmlCtxtDumpString(ctxt, attr->name); + fprintf(ctxt->output, "\n"); + if (attr->children != NULL) { + ctxt->depth++; + xmlCtxtDumpNodeList(ctxt, attr->children); + ctxt->depth--; + } + } + if (attr->name == NULL) + xmlDebugErr(ctxt, XML_CHECK_NO_NAME, + "Attribute has no name"); + + /* + * Do a bit of checking + */ + xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) attr); +} + +/** + * xmlCtxtDumpAttrList: + * @output: the FILE * for the output + * @attr: the attribute list + * @depth: the indentation level. + * + * Dumps debug information for the attribute list + */ +static void +xmlCtxtDumpAttrList(xmlDebugCtxtPtr ctxt, xmlAttrPtr attr) +{ + while (attr != NULL) { + xmlCtxtDumpAttr(ctxt, attr); + attr = attr->next; + } +} + +/** + * xmlCtxtDumpOneNode: + * @output: the FILE * for the output + * @node: the node + * @depth: the indentation level. + * + * Dumps debug information for the element node, it is not recursive + */ +static void +xmlCtxtDumpOneNode(xmlDebugCtxtPtr ctxt, xmlNodePtr node) +{ + if (node == NULL) { + if (!ctxt->check) { + xmlCtxtDumpSpaces(ctxt); + fprintf(ctxt->output, "node is NULL\n"); + } + return; + } + ctxt->node = node; + + switch (node->type) { + case XML_ELEMENT_NODE: + if (!ctxt->check) { + xmlCtxtDumpSpaces(ctxt); + fprintf(ctxt->output, "ELEMENT "); + if ((node->ns != NULL) && (node->ns->prefix != NULL)) { + xmlCtxtDumpString(ctxt, node->ns->prefix); + fprintf(ctxt->output, ":"); + } + xmlCtxtDumpString(ctxt, node->name); + fprintf(ctxt->output, "\n"); + } + break; + case XML_ATTRIBUTE_NODE: + if (!ctxt->check) + xmlCtxtDumpSpaces(ctxt); + fprintf(ctxt->output, "Error, ATTRIBUTE found here\n"); + xmlCtxtGenericNodeCheck(ctxt, node); + return; + case XML_TEXT_NODE: + if (!ctxt->check) { + xmlCtxtDumpSpaces(ctxt); + if (node->name == (const xmlChar *) xmlStringTextNoenc) + fprintf(ctxt->output, "TEXT no enc"); + else + fprintf(ctxt->output, "TEXT"); + if (ctxt->options & DUMP_TEXT_TYPE) { + if (node->content == (xmlChar *) &(node->properties)) + fprintf(ctxt->output, " compact\n"); + else if (xmlDictOwns(ctxt->dict, node->content) == 1) + fprintf(ctxt->output, " interned\n"); + else + fprintf(ctxt->output, "\n"); + } else + fprintf(ctxt->output, "\n"); + } + break; + case XML_CDATA_SECTION_NODE: + if (!ctxt->check) { + xmlCtxtDumpSpaces(ctxt); + fprintf(ctxt->output, "CDATA_SECTION\n"); + } + break; + case XML_ENTITY_REF_NODE: + if (!ctxt->check) { + xmlCtxtDumpSpaces(ctxt); + fprintf(ctxt->output, "ENTITY_REF(%s)\n", + (char *) node->name); + } + break; + case XML_ENTITY_NODE: + if (!ctxt->check) { + xmlCtxtDumpSpaces(ctxt); + fprintf(ctxt->output, "ENTITY\n"); + } + break; + case XML_PI_NODE: + if (!ctxt->check) { + xmlCtxtDumpSpaces(ctxt); + fprintf(ctxt->output, "PI %s\n", (char *) node->name); + } + break; + case XML_COMMENT_NODE: + if (!ctxt->check) { + xmlCtxtDumpSpaces(ctxt); + fprintf(ctxt->output, "COMMENT\n"); + } + break; + case XML_DOCUMENT_NODE: + case XML_HTML_DOCUMENT_NODE: + if (!ctxt->check) { + xmlCtxtDumpSpaces(ctxt); + } + fprintf(ctxt->output, "Error, DOCUMENT found here\n"); + xmlCtxtGenericNodeCheck(ctxt, node); + return; + case XML_DOCUMENT_TYPE_NODE: + if (!ctxt->check) { + xmlCtxtDumpSpaces(ctxt); + fprintf(ctxt->output, "DOCUMENT_TYPE\n"); + } + break; + case XML_DOCUMENT_FRAG_NODE: + if (!ctxt->check) { + xmlCtxtDumpSpaces(ctxt); + fprintf(ctxt->output, "DOCUMENT_FRAG\n"); + } + break; + case XML_NOTATION_NODE: + if (!ctxt->check) { + xmlCtxtDumpSpaces(ctxt); + fprintf(ctxt->output, "NOTATION\n"); + } + break; + case XML_DTD_NODE: + xmlCtxtDumpDtdNode(ctxt, (xmlDtdPtr) node); + return; + case XML_ELEMENT_DECL: + xmlCtxtDumpElemDecl(ctxt, (xmlElementPtr) node); + return; + case XML_ATTRIBUTE_DECL: + xmlCtxtDumpAttrDecl(ctxt, (xmlAttributePtr) node); + return; + case XML_ENTITY_DECL: + xmlCtxtDumpEntityDecl(ctxt, (xmlEntityPtr) node); + return; + case XML_NAMESPACE_DECL: + xmlCtxtDumpNamespace(ctxt, (xmlNsPtr) node); + return; + case XML_XINCLUDE_START: + if (!ctxt->check) { + xmlCtxtDumpSpaces(ctxt); + fprintf(ctxt->output, "INCLUDE START\n"); + } + return; + case XML_XINCLUDE_END: + if (!ctxt->check) { + xmlCtxtDumpSpaces(ctxt); + fprintf(ctxt->output, "INCLUDE END\n"); + } + return; + default: + if (!ctxt->check) + xmlCtxtDumpSpaces(ctxt); + xmlDebugErr2(ctxt, XML_CHECK_UNKNOWN_NODE, + "Unknown node type %d\n", node->type); + return; + } + if (node->doc == NULL) { + if (!ctxt->check) { + xmlCtxtDumpSpaces(ctxt); + } + fprintf(ctxt->output, "PBM: doc == NULL !!!\n"); + } + ctxt->depth++; + if ((node->type == XML_ELEMENT_NODE) && (node->nsDef != NULL)) + xmlCtxtDumpNamespaceList(ctxt, node->nsDef); + if ((node->type == XML_ELEMENT_NODE) && (node->properties != NULL)) + xmlCtxtDumpAttrList(ctxt, node->properties); + if (node->type != XML_ENTITY_REF_NODE) { + if ((node->type != XML_ELEMENT_NODE) && (node->content != NULL)) { + if (!ctxt->check) { + xmlCtxtDumpSpaces(ctxt); + fprintf(ctxt->output, "content="); + xmlCtxtDumpString(ctxt, node->content); + fprintf(ctxt->output, "\n"); + } + } + } else { + xmlEntityPtr ent; + + ent = xmlGetDocEntity(node->doc, node->name); + if (ent != NULL) + xmlCtxtDumpEntity(ctxt, ent); + } + ctxt->depth--; + + /* + * Do a bit of checking + */ + xmlCtxtGenericNodeCheck(ctxt, node); +} + +/** + * xmlCtxtDumpNode: + * @output: the FILE * for the output + * @node: the node + * @depth: the indentation level. + * + * Dumps debug information for the element node, it is recursive + */ +static void +xmlCtxtDumpNode(xmlDebugCtxtPtr ctxt, xmlNodePtr node) +{ + if (node == NULL) { + if (!ctxt->check) { + xmlCtxtDumpSpaces(ctxt); + fprintf(ctxt->output, "node is NULL\n"); + } + return; + } + xmlCtxtDumpOneNode(ctxt, node); + if ((node->type != XML_NAMESPACE_DECL) && + (node->children != NULL) && (node->type != XML_ENTITY_REF_NODE)) { + ctxt->depth++; + xmlCtxtDumpNodeList(ctxt, node->children); + ctxt->depth--; + } +} + +/** + * xmlCtxtDumpNodeList: + * @output: the FILE * for the output + * @node: the node list + * @depth: the indentation level. + * + * Dumps debug information for the list of element node, it is recursive + */ +static void +xmlCtxtDumpNodeList(xmlDebugCtxtPtr ctxt, xmlNodePtr node) +{ + while (node != NULL) { + xmlCtxtDumpNode(ctxt, node); + node = node->next; + } +} + +static void +xmlCtxtDumpDocHead(xmlDebugCtxtPtr ctxt, xmlDocPtr doc) +{ + if (doc == NULL) { + if (!ctxt->check) + fprintf(ctxt->output, "DOCUMENT == NULL !\n"); + return; + } + ctxt->node = (xmlNodePtr) doc; + + switch (doc->type) { + case XML_ELEMENT_NODE: + xmlDebugErr(ctxt, XML_CHECK_FOUND_ELEMENT, + "Misplaced ELEMENT node\n"); + break; + case XML_ATTRIBUTE_NODE: + xmlDebugErr(ctxt, XML_CHECK_FOUND_ATTRIBUTE, + "Misplaced ATTRIBUTE node\n"); + break; + case XML_TEXT_NODE: + xmlDebugErr(ctxt, XML_CHECK_FOUND_TEXT, + "Misplaced TEXT node\n"); + break; + case XML_CDATA_SECTION_NODE: + xmlDebugErr(ctxt, XML_CHECK_FOUND_CDATA, + "Misplaced CDATA node\n"); + break; + case XML_ENTITY_REF_NODE: + xmlDebugErr(ctxt, XML_CHECK_FOUND_ENTITYREF, + "Misplaced ENTITYREF node\n"); + break; + case XML_ENTITY_NODE: + xmlDebugErr(ctxt, XML_CHECK_FOUND_ENTITY, + "Misplaced ENTITY node\n"); + break; + case XML_PI_NODE: + xmlDebugErr(ctxt, XML_CHECK_FOUND_PI, + "Misplaced PI node\n"); + break; + case XML_COMMENT_NODE: + xmlDebugErr(ctxt, XML_CHECK_FOUND_COMMENT, + "Misplaced COMMENT node\n"); + break; + case XML_DOCUMENT_NODE: + if (!ctxt->check) + fprintf(ctxt->output, "DOCUMENT\n"); + break; + case XML_HTML_DOCUMENT_NODE: + if (!ctxt->check) + fprintf(ctxt->output, "HTML DOCUMENT\n"); + break; + case XML_DOCUMENT_TYPE_NODE: + xmlDebugErr(ctxt, XML_CHECK_FOUND_DOCTYPE, + "Misplaced DOCTYPE node\n"); + break; + case XML_DOCUMENT_FRAG_NODE: + xmlDebugErr(ctxt, XML_CHECK_FOUND_FRAGMENT, + "Misplaced FRAGMENT node\n"); + break; + case XML_NOTATION_NODE: + xmlDebugErr(ctxt, XML_CHECK_FOUND_NOTATION, + "Misplaced NOTATION node\n"); + break; + default: + xmlDebugErr2(ctxt, XML_CHECK_UNKNOWN_NODE, + "Unknown node type %d\n", doc->type); + } +} + +/** + * xmlCtxtDumpDocumentHead: + * @output: the FILE * for the output + * @doc: the document + * + * Dumps debug information cncerning the document, not recursive + */ +static void +xmlCtxtDumpDocumentHead(xmlDebugCtxtPtr ctxt, xmlDocPtr doc) +{ + if (doc == NULL) return; + xmlCtxtDumpDocHead(ctxt, doc); + if (!ctxt->check) { + if (doc->name != NULL) { + fprintf(ctxt->output, "name="); + xmlCtxtDumpString(ctxt, BAD_CAST doc->name); + fprintf(ctxt->output, "\n"); + } + if (doc->version != NULL) { + fprintf(ctxt->output, "version="); + xmlCtxtDumpString(ctxt, doc->version); + fprintf(ctxt->output, "\n"); + } + if (doc->encoding != NULL) { + fprintf(ctxt->output, "encoding="); + xmlCtxtDumpString(ctxt, doc->encoding); + fprintf(ctxt->output, "\n"); + } + if (doc->URL != NULL) { + fprintf(ctxt->output, "URL="); + xmlCtxtDumpString(ctxt, doc->URL); + fprintf(ctxt->output, "\n"); + } + if (doc->standalone) + fprintf(ctxt->output, "standalone=true\n"); + } + if (doc->oldNs != NULL) + xmlCtxtDumpNamespaceList(ctxt, doc->oldNs); +} + +/** + * xmlCtxtDumpDocument: + * @output: the FILE * for the output + * @doc: the document + * + * Dumps debug information for the document, it's recursive + */ +static void +xmlCtxtDumpDocument(xmlDebugCtxtPtr ctxt, xmlDocPtr doc) +{ + if (doc == NULL) { + if (!ctxt->check) + fprintf(ctxt->output, "DOCUMENT == NULL !\n"); + return; + } + xmlCtxtDumpDocumentHead(ctxt, doc); + if (((doc->type == XML_DOCUMENT_NODE) || + (doc->type == XML_HTML_DOCUMENT_NODE)) + && (doc->children != NULL)) { + ctxt->depth++; + xmlCtxtDumpNodeList(ctxt, doc->children); + ctxt->depth--; + } +} + +static void +xmlCtxtDumpEntityCallback(xmlEntityPtr cur, xmlDebugCtxtPtr ctxt) +{ + if (cur == NULL) { + if (!ctxt->check) + fprintf(ctxt->output, "Entity is NULL"); + return; + } + if (!ctxt->check) { + fprintf(ctxt->output, "%s : ", (char *) cur->name); + switch (cur->etype) { + case XML_INTERNAL_GENERAL_ENTITY: + fprintf(ctxt->output, "INTERNAL GENERAL, "); + break; + case XML_EXTERNAL_GENERAL_PARSED_ENTITY: + fprintf(ctxt->output, "EXTERNAL PARSED, "); + break; + case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY: + fprintf(ctxt->output, "EXTERNAL UNPARSED, "); + break; + case XML_INTERNAL_PARAMETER_ENTITY: + fprintf(ctxt->output, "INTERNAL PARAMETER, "); + break; + case XML_EXTERNAL_PARAMETER_ENTITY: + fprintf(ctxt->output, "EXTERNAL PARAMETER, "); + break; + default: + xmlDebugErr2(ctxt, XML_CHECK_ENTITY_TYPE, + "Unknown entity type %d\n", cur->etype); + } + if (cur->ExternalID != NULL) + fprintf(ctxt->output, "ID \"%s\"", (char *) cur->ExternalID); + if (cur->SystemID != NULL) + fprintf(ctxt->output, "SYSTEM \"%s\"", (char *) cur->SystemID); + if (cur->orig != NULL) + fprintf(ctxt->output, "\n orig \"%s\"", (char *) cur->orig); + if ((cur->type != XML_ELEMENT_NODE) && (cur->content != NULL)) + fprintf(ctxt->output, "\n content \"%s\"", + (char *) cur->content); + fprintf(ctxt->output, "\n"); + } +} + +/** + * xmlCtxtDumpEntities: + * @output: the FILE * for the output + * @doc: the document + * + * Dumps debug information for all the entities in use by the document + */ +static void +xmlCtxtDumpEntities(xmlDebugCtxtPtr ctxt, xmlDocPtr doc) +{ + if (doc == NULL) return; + xmlCtxtDumpDocHead(ctxt, doc); + if ((doc->intSubset != NULL) && (doc->intSubset->entities != NULL)) { + xmlEntitiesTablePtr table = (xmlEntitiesTablePtr) + doc->intSubset->entities; + + if (!ctxt->check) + fprintf(ctxt->output, "Entities in internal subset\n"); + xmlHashScan(table, (xmlHashScanner) xmlCtxtDumpEntityCallback, + ctxt); + } else + fprintf(ctxt->output, "No entities in internal subset\n"); + if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) { + xmlEntitiesTablePtr table = (xmlEntitiesTablePtr) + doc->extSubset->entities; + + if (!ctxt->check) + fprintf(ctxt->output, "Entities in external subset\n"); + xmlHashScan(table, (xmlHashScanner) xmlCtxtDumpEntityCallback, + ctxt); + } else if (!ctxt->check) + fprintf(ctxt->output, "No entities in external subset\n"); +} + +/** + * xmlCtxtDumpDTD: + * @output: the FILE * for the output + * @dtd: the DTD + * + * Dumps debug information for the DTD + */ +static void +xmlCtxtDumpDTD(xmlDebugCtxtPtr ctxt, xmlDtdPtr dtd) +{ + if (dtd == NULL) { + if (!ctxt->check) + fprintf(ctxt->output, "DTD is NULL\n"); + return; + } + xmlCtxtDumpDtdNode(ctxt, dtd); + if (dtd->children == NULL) + fprintf(ctxt->output, " DTD is empty\n"); + else { + ctxt->depth++; + xmlCtxtDumpNodeList(ctxt, dtd->children); + ctxt->depth--; + } +} + +/************************************************************************ + * * + * Public entry points for dump * + * * + ************************************************************************/ + +/** + * xmlDebugDumpString: + * @output: the FILE * for the output + * @str: the string + * + * Dumps informations about the string, shorten it if necessary + */ +void +xmlDebugDumpString(FILE * output, const xmlChar * str) +{ + int i; + + if (output == NULL) + output = stdout; + if (str == NULL) { + fprintf(output, "(NULL)"); + return; + } + for (i = 0; i < 40; i++) + if (str[i] == 0) + return; + else if (IS_BLANK_CH(str[i])) + fputc(' ', output); + else if (str[i] >= 0x80) + fprintf(output, "#%X", str[i]); + else + fputc(str[i], output); + fprintf(output, "..."); +} + +/** + * xmlDebugDumpAttr: + * @output: the FILE * for the output + * @attr: the attribute + * @depth: the indentation level. + * + * Dumps debug information for the attribute + */ +void +xmlDebugDumpAttr(FILE *output, xmlAttrPtr attr, int depth) { + xmlDebugCtxt ctxt; + + if (output == NULL) return; + xmlCtxtDumpInitCtxt(&ctxt); + ctxt.output = output; + ctxt.depth = depth; + xmlCtxtDumpAttr(&ctxt, attr); + xmlCtxtDumpCleanCtxt(&ctxt); +} + + +/** + * xmlDebugDumpEntities: + * @output: the FILE * for the output + * @doc: the document + * + * Dumps debug information for all the entities in use by the document + */ +void +xmlDebugDumpEntities(FILE * output, xmlDocPtr doc) +{ + xmlDebugCtxt ctxt; + + if (output == NULL) return; + xmlCtxtDumpInitCtxt(&ctxt); + ctxt.output = output; + xmlCtxtDumpEntities(&ctxt, doc); + xmlCtxtDumpCleanCtxt(&ctxt); +} + +/** + * xmlDebugDumpAttrList: + * @output: the FILE * for the output + * @attr: the attribute list + * @depth: the indentation level. + * + * Dumps debug information for the attribute list + */ +void +xmlDebugDumpAttrList(FILE * output, xmlAttrPtr attr, int depth) +{ + xmlDebugCtxt ctxt; + + if (output == NULL) return; + xmlCtxtDumpInitCtxt(&ctxt); + ctxt.output = output; + ctxt.depth = depth; + xmlCtxtDumpAttrList(&ctxt, attr); + xmlCtxtDumpCleanCtxt(&ctxt); +} + +/** + * xmlDebugDumpOneNode: + * @output: the FILE * for the output + * @node: the node + * @depth: the indentation level. + * + * Dumps debug information for the element node, it is not recursive + */ +void +xmlDebugDumpOneNode(FILE * output, xmlNodePtr node, int depth) +{ + xmlDebugCtxt ctxt; + + if (output == NULL) return; + xmlCtxtDumpInitCtxt(&ctxt); + ctxt.output = output; + ctxt.depth = depth; + xmlCtxtDumpOneNode(&ctxt, node); + xmlCtxtDumpCleanCtxt(&ctxt); +} + +/** + * xmlDebugDumpNode: + * @output: the FILE * for the output + * @node: the node + * @depth: the indentation level. + * + * Dumps debug information for the element node, it is recursive + */ +void +xmlDebugDumpNode(FILE * output, xmlNodePtr node, int depth) +{ + xmlDebugCtxt ctxt; + + if (output == NULL) + output = stdout; + xmlCtxtDumpInitCtxt(&ctxt); + ctxt.output = output; + ctxt.depth = depth; + xmlCtxtDumpNode(&ctxt, node); + xmlCtxtDumpCleanCtxt(&ctxt); +} + +/** + * xmlDebugDumpNodeList: + * @output: the FILE * for the output + * @node: the node list + * @depth: the indentation level. + * + * Dumps debug information for the list of element node, it is recursive + */ +void +xmlDebugDumpNodeList(FILE * output, xmlNodePtr node, int depth) +{ + xmlDebugCtxt ctxt; + + if (output == NULL) + output = stdout; + xmlCtxtDumpInitCtxt(&ctxt); + ctxt.output = output; + ctxt.depth = depth; + xmlCtxtDumpNodeList(&ctxt, node); + xmlCtxtDumpCleanCtxt(&ctxt); +} + +/** + * xmlDebugDumpDocumentHead: + * @output: the FILE * for the output + * @doc: the document + * + * Dumps debug information cncerning the document, not recursive + */ +void +xmlDebugDumpDocumentHead(FILE * output, xmlDocPtr doc) +{ + xmlDebugCtxt ctxt; + + if (output == NULL) + output = stdout; + xmlCtxtDumpInitCtxt(&ctxt); + ctxt.options |= DUMP_TEXT_TYPE; + ctxt.output = output; + xmlCtxtDumpDocumentHead(&ctxt, doc); + xmlCtxtDumpCleanCtxt(&ctxt); +} + +/** + * xmlDebugDumpDocument: + * @output: the FILE * for the output + * @doc: the document + * + * Dumps debug information for the document, it's recursive + */ +void +xmlDebugDumpDocument(FILE * output, xmlDocPtr doc) +{ + xmlDebugCtxt ctxt; + + if (output == NULL) + output = stdout; + xmlCtxtDumpInitCtxt(&ctxt); + ctxt.options |= DUMP_TEXT_TYPE; + ctxt.output = output; + xmlCtxtDumpDocument(&ctxt, doc); + xmlCtxtDumpCleanCtxt(&ctxt); +} + +/** + * xmlDebugDumpDTD: + * @output: the FILE * for the output + * @dtd: the DTD + * + * Dumps debug information for the DTD + */ +void +xmlDebugDumpDTD(FILE * output, xmlDtdPtr dtd) +{ + xmlDebugCtxt ctxt; + + if (output == NULL) + output = stdout; + xmlCtxtDumpInitCtxt(&ctxt); + ctxt.options |= DUMP_TEXT_TYPE; + ctxt.output = output; + xmlCtxtDumpDTD(&ctxt, dtd); + xmlCtxtDumpCleanCtxt(&ctxt); +} + +/************************************************************************ + * * + * Public entry points for checkings * + * * + ************************************************************************/ + +/** + * xmlDebugCheckDocument: + * @output: the FILE * for the output + * @doc: the document + * + * Check the document for potential content problems, and output + * the errors to @output + * + * Returns the number of errors found + */ +int +xmlDebugCheckDocument(FILE * output, xmlDocPtr doc) +{ + xmlDebugCtxt ctxt; + + if (output == NULL) + output = stdout; + xmlCtxtDumpInitCtxt(&ctxt); + ctxt.output = output; + ctxt.check = 1; + xmlCtxtDumpDocument(&ctxt, doc); + xmlCtxtDumpCleanCtxt(&ctxt); + return(ctxt.errors); +} + +/************************************************************************ + * * + * Helpers for Shell * + * * + ************************************************************************/ + +/** + * xmlLsCountNode: + * @node: the node to count + * + * Count the children of @node. + * + * Returns the number of children of @node. + */ +int +xmlLsCountNode(xmlNodePtr node) { + int ret = 0; + xmlNodePtr list = NULL; + + if (node == NULL) + return(0); + + switch (node->type) { + case XML_ELEMENT_NODE: + list = node->children; + break; + case XML_DOCUMENT_NODE: + case XML_HTML_DOCUMENT_NODE: +#ifdef LIBXML_DOCB_ENABLED + case XML_DOCB_DOCUMENT_NODE: +#endif + list = ((xmlDocPtr) node)->children; + break; + case XML_ATTRIBUTE_NODE: + list = ((xmlAttrPtr) node)->children; + break; + case XML_TEXT_NODE: + case XML_CDATA_SECTION_NODE: + case XML_PI_NODE: + case XML_COMMENT_NODE: + if (node->content != NULL) { + ret = xmlStrlen(node->content); + } + break; + case XML_ENTITY_REF_NODE: + case XML_DOCUMENT_TYPE_NODE: + case XML_ENTITY_NODE: + case XML_DOCUMENT_FRAG_NODE: + case XML_NOTATION_NODE: + case XML_DTD_NODE: + case XML_ELEMENT_DECL: + case XML_ATTRIBUTE_DECL: + case XML_ENTITY_DECL: + case XML_NAMESPACE_DECL: + case XML_XINCLUDE_START: + case XML_XINCLUDE_END: + ret = 1; + break; + } + for (;list != NULL;ret++) + list = list->next; + return(ret); +} + +/** + * xmlLsOneNode: + * @output: the FILE * for the output + * @node: the node to dump + * + * Dump to @output the type and name of @node. + */ +void +xmlLsOneNode(FILE *output, xmlNodePtr node) { + if (output == NULL) return; + if (node == NULL) { + fprintf(output, "NULL\n"); + return; + } + switch (node->type) { + case XML_ELEMENT_NODE: + fprintf(output, "-"); + break; + case XML_ATTRIBUTE_NODE: + fprintf(output, "a"); + break; + case XML_TEXT_NODE: + fprintf(output, "t"); + break; + case XML_CDATA_SECTION_NODE: + fprintf(output, "C"); + break; + case XML_ENTITY_REF_NODE: + fprintf(output, "e"); + break; + case XML_ENTITY_NODE: + fprintf(output, "E"); + break; + case XML_PI_NODE: + fprintf(output, "p"); + break; + case XML_COMMENT_NODE: + fprintf(output, "c"); + break; + case XML_DOCUMENT_NODE: + fprintf(output, "d"); + break; + case XML_HTML_DOCUMENT_NODE: + fprintf(output, "h"); + break; + case XML_DOCUMENT_TYPE_NODE: + fprintf(output, "T"); + break; + case XML_DOCUMENT_FRAG_NODE: + fprintf(output, "F"); + break; + case XML_NOTATION_NODE: + fprintf(output, "N"); + break; + case XML_NAMESPACE_DECL: + fprintf(output, "n"); + break; + default: + fprintf(output, "?"); + } + if (node->type != XML_NAMESPACE_DECL) { + if (node->properties != NULL) + fprintf(output, "a"); + else + fprintf(output, "-"); + if (node->nsDef != NULL) + fprintf(output, "n"); + else + fprintf(output, "-"); + } + + fprintf(output, " %8d ", xmlLsCountNode(node)); + + switch (node->type) { + case XML_ELEMENT_NODE: + if (node->name != NULL) + fprintf(output, "%s", (const char *) node->name); + break; + case XML_ATTRIBUTE_NODE: + if (node->name != NULL) + fprintf(output, "%s", (const char *) node->name); + break; + case XML_TEXT_NODE: + if (node->content != NULL) { + xmlDebugDumpString(output, node->content); + } + break; + case XML_CDATA_SECTION_NODE: + break; + case XML_ENTITY_REF_NODE: + if (node->name != NULL) + fprintf(output, "%s", (const char *) node->name); + break; + case XML_ENTITY_NODE: + if (node->name != NULL) + fprintf(output, "%s", (const char *) node->name); + break; + case XML_PI_NODE: + if (node->name != NULL) + fprintf(output, "%s", (const char *) node->name); + break; + case XML_COMMENT_NODE: + break; + case XML_DOCUMENT_NODE: + break; + case XML_HTML_DOCUMENT_NODE: + break; + case XML_DOCUMENT_TYPE_NODE: + break; + case XML_DOCUMENT_FRAG_NODE: + break; + case XML_NOTATION_NODE: + break; + case XML_NAMESPACE_DECL: { + xmlNsPtr ns = (xmlNsPtr) node; + + if (ns->prefix == NULL) + fprintf(output, "default -> %s", (char *)ns->href); + else + fprintf(output, "%s -> %s", (char *)ns->prefix, + (char *)ns->href); + break; + } + default: + if (node->name != NULL) + fprintf(output, "%s", (const char *) node->name); + } + fprintf(output, "\n"); +} + +/** + * xmlBoolToText: + * @boolval: a bool to turn into text + * + * Convenient way to turn bool into text + * + * Returns a pointer to either "True" or "False" + */ +const char * +xmlBoolToText(int boolval) +{ + if (boolval) + return("True"); + else + return("False"); +} + +#ifdef LIBXML_XPATH_ENABLED +/**************************************************************** + * * + * The XML shell related functions * + * * + ****************************************************************/ + + + +/* + * TODO: Improvement/cleanups for the XML shell + * - allow to shell out an editor on a subpart + * - cleanup function registrations (with help) and calling + * - provide registration routines + */ + +/** + * xmlShellPrintXPathError: + * @errorType: valid xpath error id + * @arg: the argument that cause xpath to fail + * + * Print the xpath error to libxml default error channel + */ +void +xmlShellPrintXPathError(int errorType, const char *arg) +{ + const char *default_arg = "Result"; + + if (!arg) + arg = default_arg; + + switch (errorType) { + case XPATH_UNDEFINED: + xmlGenericError(xmlGenericErrorContext, + "%s: no such node\n", arg); + break; + + case XPATH_BOOLEAN: + xmlGenericError(xmlGenericErrorContext, + "%s is a Boolean\n", arg); + break; + case XPATH_NUMBER: + xmlGenericError(xmlGenericErrorContext, + "%s is a number\n", arg); + break; + case XPATH_STRING: + xmlGenericError(xmlGenericErrorContext, + "%s is a string\n", arg); + break; + case XPATH_POINT: + xmlGenericError(xmlGenericErrorContext, + "%s is a point\n", arg); + break; + case XPATH_RANGE: + xmlGenericError(xmlGenericErrorContext, + "%s is a range\n", arg); + break; + case XPATH_LOCATIONSET: + xmlGenericError(xmlGenericErrorContext, + "%s is a range\n", arg); + break; + case XPATH_USERS: + xmlGenericError(xmlGenericErrorContext, + "%s is user-defined\n", arg); + break; + case XPATH_XSLT_TREE: + xmlGenericError(xmlGenericErrorContext, + "%s is an XSLT value tree\n", arg); + break; + } +#if 0 + xmlGenericError(xmlGenericErrorContext, + "Try casting the result string function (xpath builtin)\n", + arg); +#endif +} + + +#ifdef LIBXML_OUTPUT_ENABLED +/** + * xmlShellPrintNodeCtxt: + * @ctxt : a non-null shell context + * @node : a non-null node to print to the output FILE + * + * Print node to the output FILE + */ +static void +xmlShellPrintNodeCtxt(xmlShellCtxtPtr ctxt,xmlNodePtr node) +{ + FILE *fp; + + if (!node) + return; + if (ctxt == NULL) + fp = stdout; + else + fp = ctxt->output; + + if (node->type == XML_DOCUMENT_NODE) + xmlDocDump(fp, (xmlDocPtr) node); + else if (node->type == XML_ATTRIBUTE_NODE) + xmlDebugDumpAttrList(fp, (xmlAttrPtr) node, 0); + else + xmlElemDump(fp, node->doc, node); + + fprintf(fp, "\n"); +} + +/** + * xmlShellPrintNode: + * @node : a non-null node to print to the output FILE + * + * Print node to the output FILE + */ +void +xmlShellPrintNode(xmlNodePtr node) +{ + xmlShellPrintNodeCtxt(NULL, node); +} +#endif /* LIBXML_OUTPUT_ENABLED */ + +/** + * xmlShellPrintXPathResultCtxt: + * @ctxt: a valid shell context + * @list: a valid result generated by an xpath evaluation + * + * Prints result to the output FILE + */ +static void +xmlShellPrintXPathResultCtxt(xmlShellCtxtPtr ctxt,xmlXPathObjectPtr list) +{ + if (!ctxt) + return; + + if (list != NULL) { + switch (list->type) { + case XPATH_NODESET:{ +#ifdef LIBXML_OUTPUT_ENABLED + int indx; + + if (list->nodesetval) { + for (indx = 0; indx < list->nodesetval->nodeNr; + indx++) { + xmlShellPrintNodeCtxt(ctxt, + list->nodesetval->nodeTab[indx]); + } + } else { + xmlGenericError(xmlGenericErrorContext, + "Empty node set\n"); + } + break; +#else + xmlGenericError(xmlGenericErrorContext, + "Node set\n"); +#endif /* LIBXML_OUTPUT_ENABLED */ + } + case XPATH_BOOLEAN: + xmlGenericError(xmlGenericErrorContext, + "Is a Boolean:%s\n", + xmlBoolToText(list->boolval)); + break; + case XPATH_NUMBER: + xmlGenericError(xmlGenericErrorContext, + "Is a number:%0g\n", list->floatval); + break; + case XPATH_STRING: + xmlGenericError(xmlGenericErrorContext, + "Is a string:%s\n", list->stringval); + break; + + default: + xmlShellPrintXPathError(list->type, NULL); + } + } +} + +/** + * xmlShellPrintXPathResult: + * @list: a valid result generated by an xpath evaluation + * + * Prints result to the output FILE + */ +void +xmlShellPrintXPathResult(xmlXPathObjectPtr list) +{ + xmlShellPrintXPathResultCtxt(NULL, list); +} + +/** + * xmlShellList: + * @ctxt: the shell context + * @arg: unused + * @node: a node + * @node2: unused + * + * Implements the XML shell function "ls" + * Does an Unix like listing of the given node (like a directory) + * + * Returns 0 + */ +int +xmlShellList(xmlShellCtxtPtr ctxt, + char *arg ATTRIBUTE_UNUSED, xmlNodePtr node, + xmlNodePtr node2 ATTRIBUTE_UNUSED) +{ + xmlNodePtr cur; + if (!ctxt) + return (0); + if (node == NULL) { + fprintf(ctxt->output, "NULL\n"); + return (0); + } + if ((node->type == XML_DOCUMENT_NODE) || + (node->type == XML_HTML_DOCUMENT_NODE)) { + cur = ((xmlDocPtr) node)->children; + } else if (node->type == XML_NAMESPACE_DECL) { + xmlLsOneNode(ctxt->output, node); + return (0); + } else if (node->children != NULL) { + cur = node->children; + } else { + xmlLsOneNode(ctxt->output, node); + return (0); + } + while (cur != NULL) { + xmlLsOneNode(ctxt->output, cur); + cur = cur->next; + } + return (0); +} + +/** + * xmlShellBase: + * @ctxt: the shell context + * @arg: unused + * @node: a node + * @node2: unused + * + * Implements the XML shell function "base" + * dumps the current XML base of the node + * + * Returns 0 + */ +int +xmlShellBase(xmlShellCtxtPtr ctxt, + char *arg ATTRIBUTE_UNUSED, xmlNodePtr node, + xmlNodePtr node2 ATTRIBUTE_UNUSED) +{ + xmlChar *base; + if (!ctxt) + return 0; + if (node == NULL) { + fprintf(ctxt->output, "NULL\n"); + return (0); + } + + base = xmlNodeGetBase(node->doc, node); + + if (base == NULL) { + fprintf(ctxt->output, " No base found !!!\n"); + } else { + fprintf(ctxt->output, "%s\n", base); + xmlFree(base); + } + return (0); +} + +#ifdef LIBXML_TREE_ENABLED +/** + * xmlShellSetBase: + * @ctxt: the shell context + * @arg: the new base + * @node: a node + * @node2: unused + * + * Implements the XML shell function "setbase" + * change the current XML base of the node + * + * Returns 0 + */ +static int +xmlShellSetBase(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED, + char *arg ATTRIBUTE_UNUSED, xmlNodePtr node, + xmlNodePtr node2 ATTRIBUTE_UNUSED) +{ + xmlNodeSetBase(node, (xmlChar*) arg); + return (0); +} +#endif + +#ifdef LIBXML_XPATH_ENABLED +/** + * xmlShellRegisterNamespace: + * @ctxt: the shell context + * @arg: a string in prefix=nsuri format + * @node: unused + * @node2: unused + * + * Implements the XML shell function "setns" + * register/unregister a prefix=namespace pair + * on the XPath context + * + * Returns 0 on success and a negative value otherwise. + */ +static int +xmlShellRegisterNamespace(xmlShellCtxtPtr ctxt, char *arg, + xmlNodePtr node ATTRIBUTE_UNUSED, xmlNodePtr node2 ATTRIBUTE_UNUSED) +{ + xmlChar* nsListDup; + xmlChar* prefix; + xmlChar* href; + xmlChar* next; + + nsListDup = xmlStrdup((xmlChar *) arg); + next = nsListDup; + while(next != NULL) { + /* skip spaces */ + /*while((*next) == ' ') next++;*/ + if((*next) == '\0') break; + + /* find prefix */ + prefix = next; + next = (xmlChar*)xmlStrchr(next, '='); + if(next == NULL) { + fprintf(ctxt->output, "setns: prefix=[nsuri] required\n"); + xmlFree(nsListDup); + return(-1); + } + *(next++) = '\0'; + + /* find href */ + href = next; + next = (xmlChar*)xmlStrchr(next, ' '); + if(next != NULL) { + *(next++) = '\0'; + } + + /* do register namespace */ + if(xmlXPathRegisterNs(ctxt->pctxt, prefix, href) != 0) { + fprintf(ctxt->output,"Error: unable to register NS with prefix=\"%s\" and href=\"%s\"\n", prefix, href); + xmlFree(nsListDup); + return(-1); + } + } + + xmlFree(nsListDup); + return(0); +} +/** + * xmlShellRegisterRootNamespaces: + * @ctxt: the shell context + * @arg: unused + * @node: the root element + * @node2: unused + * + * Implements the XML shell function "setrootns" + * which registers all namespaces declarations found on the root element. + * + * Returns 0 on success and a negative value otherwise. + */ +static int +xmlShellRegisterRootNamespaces(xmlShellCtxtPtr ctxt, char *arg ATTRIBUTE_UNUSED, + xmlNodePtr root, xmlNodePtr node2 ATTRIBUTE_UNUSED) +{ + xmlNsPtr ns; + + if ((root == NULL) || (root->type != XML_ELEMENT_NODE) || + (root->nsDef == NULL) || (ctxt == NULL) || (ctxt->pctxt == NULL)) + return(-1); + ns = root->nsDef; + while (ns != NULL) { + if (ns->prefix == NULL) + xmlXPathRegisterNs(ctxt->pctxt, BAD_CAST "defaultns", ns->href); + else + xmlXPathRegisterNs(ctxt->pctxt, ns->prefix, ns->href); + ns = ns->next; + } + return(0); +} +#endif + +/** + * xmlShellGrep: + * @ctxt: the shell context + * @arg: the string or regular expression to find + * @node: a node + * @node2: unused + * + * Implements the XML shell function "grep" + * dumps informations about the node (namespace, attributes, content). + * + * Returns 0 + */ +static int +xmlShellGrep(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED, + char *arg, xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED) +{ + if (!ctxt) + return (0); + if (node == NULL) + return (0); + if (arg == NULL) + return (0); +#ifdef LIBXML_REGEXP_ENABLED + if ((xmlStrchr((xmlChar *) arg, '?')) || + (xmlStrchr((xmlChar *) arg, '*')) || + (xmlStrchr((xmlChar *) arg, '.')) || + (xmlStrchr((xmlChar *) arg, '['))) { + } +#endif + while (node != NULL) { + if (node->type == XML_COMMENT_NODE) { + if (xmlStrstr(node->content, (xmlChar *) arg)) { + + fprintf(ctxt->output, "%s : ", xmlGetNodePath(node)); + xmlShellList(ctxt, NULL, node, NULL); + } + } else if (node->type == XML_TEXT_NODE) { + if (xmlStrstr(node->content, (xmlChar *) arg)) { + + fprintf(ctxt->output, "%s : ", xmlGetNodePath(node->parent)); + xmlShellList(ctxt, NULL, node->parent, NULL); + } + } + + /* + * Browse the full subtree, deep first + */ + + if ((node->type == XML_DOCUMENT_NODE) || + (node->type == XML_HTML_DOCUMENT_NODE)) { + node = ((xmlDocPtr) node)->children; + } else if ((node->children != NULL) + && (node->type != XML_ENTITY_REF_NODE)) { + /* deep first */ + node = node->children; + } else if (node->next != NULL) { + /* then siblings */ + node = node->next; + } else { + /* go up to parents->next if needed */ + while (node != NULL) { + if (node->parent != NULL) { + node = node->parent; + } + if (node->next != NULL) { + node = node->next; + break; + } + if (node->parent == NULL) { + node = NULL; + break; + } + } + } + } + return (0); +} + +/** + * xmlShellDir: + * @ctxt: the shell context + * @arg: unused + * @node: a node + * @node2: unused + * + * Implements the XML shell function "dir" + * dumps informations about the node (namespace, attributes, content). + * + * Returns 0 + */ +int +xmlShellDir(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED, + char *arg ATTRIBUTE_UNUSED, xmlNodePtr node, + xmlNodePtr node2 ATTRIBUTE_UNUSED) +{ + if (!ctxt) + return (0); + if (node == NULL) { + fprintf(ctxt->output, "NULL\n"); + return (0); + } + if ((node->type == XML_DOCUMENT_NODE) || + (node->type == XML_HTML_DOCUMENT_NODE)) { + xmlDebugDumpDocumentHead(ctxt->output, (xmlDocPtr) node); + } else if (node->type == XML_ATTRIBUTE_NODE) { + xmlDebugDumpAttr(ctxt->output, (xmlAttrPtr) node, 0); + } else { + xmlDebugDumpOneNode(ctxt->output, node, 0); + } + return (0); +} + +/** + * xmlShellSetContent: + * @ctxt: the shell context + * @value: the content as a string + * @node: a node + * @node2: unused + * + * Implements the XML shell function "dir" + * dumps informations about the node (namespace, attributes, content). + * + * Returns 0 + */ +static int +xmlShellSetContent(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED, + char *value, xmlNodePtr node, + xmlNodePtr node2 ATTRIBUTE_UNUSED) +{ + xmlNodePtr results; + xmlParserErrors ret; + + if (!ctxt) + return (0); + if (node == NULL) { + fprintf(ctxt->output, "NULL\n"); + return (0); + } + if (value == NULL) { + fprintf(ctxt->output, "NULL\n"); + return (0); + } + + ret = xmlParseInNodeContext(node, value, strlen(value), 0, &results); + if (ret == XML_ERR_OK) { + if (node->children != NULL) { + xmlFreeNodeList(node->children); + node->children = NULL; + node->last = NULL; + } + xmlAddChildList(node, results); + } else { + fprintf(ctxt->output, "failed to parse content\n"); + } + return (0); +} + +#ifdef LIBXML_SCHEMAS_ENABLED +/** + * xmlShellRNGValidate: + * @ctxt: the shell context + * @schemas: the path to the Relax-NG schemas + * @node: a node + * @node2: unused + * + * Implements the XML shell function "relaxng" + * validating the instance against a Relax-NG schemas + * + * Returns 0 + */ +static int +xmlShellRNGValidate(xmlShellCtxtPtr sctxt, char *schemas, + xmlNodePtr node ATTRIBUTE_UNUSED, + xmlNodePtr node2 ATTRIBUTE_UNUSED) +{ + xmlRelaxNGPtr relaxngschemas; + xmlRelaxNGParserCtxtPtr ctxt; + xmlRelaxNGValidCtxtPtr vctxt; + int ret; + + ctxt = xmlRelaxNGNewParserCtxt(schemas); + xmlRelaxNGSetParserErrors(ctxt, + (xmlRelaxNGValidityErrorFunc) fprintf, + (xmlRelaxNGValidityWarningFunc) fprintf, + stderr); + relaxngschemas = xmlRelaxNGParse(ctxt); + xmlRelaxNGFreeParserCtxt(ctxt); + if (relaxngschemas == NULL) { + xmlGenericError(xmlGenericErrorContext, + "Relax-NG schema %s failed to compile\n", schemas); + return(-1); + } + vctxt = xmlRelaxNGNewValidCtxt(relaxngschemas); + xmlRelaxNGSetValidErrors(vctxt, + (xmlRelaxNGValidityErrorFunc) fprintf, + (xmlRelaxNGValidityWarningFunc) fprintf, + stderr); + ret = xmlRelaxNGValidateDoc(vctxt, sctxt->doc); + if (ret == 0) { + fprintf(stderr, "%s validates\n", sctxt->filename); + } else if (ret > 0) { + fprintf(stderr, "%s fails to validate\n", sctxt->filename); + } else { + fprintf(stderr, "%s validation generated an internal error\n", + sctxt->filename); + } + xmlRelaxNGFreeValidCtxt(vctxt); + if (relaxngschemas != NULL) + xmlRelaxNGFree(relaxngschemas); + return(0); +} +#endif + +#ifdef LIBXML_OUTPUT_ENABLED +/** + * xmlShellCat: + * @ctxt: the shell context + * @arg: unused + * @node: a node + * @node2: unused + * + * Implements the XML shell function "cat" + * dumps the serialization node content (XML or HTML). + * + * Returns 0 + */ +int +xmlShellCat(xmlShellCtxtPtr ctxt, char *arg ATTRIBUTE_UNUSED, + xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED) +{ + if (!ctxt) + return (0); + if (node == NULL) { + fprintf(ctxt->output, "NULL\n"); + return (0); + } + if (ctxt->doc->type == XML_HTML_DOCUMENT_NODE) { +#ifdef LIBXML_HTML_ENABLED + if (node->type == XML_HTML_DOCUMENT_NODE) + htmlDocDump(ctxt->output, (htmlDocPtr) node); + else + htmlNodeDumpFile(ctxt->output, ctxt->doc, node); +#else + if (node->type == XML_DOCUMENT_NODE) + xmlDocDump(ctxt->output, (xmlDocPtr) node); + else + xmlElemDump(ctxt->output, ctxt->doc, node); +#endif /* LIBXML_HTML_ENABLED */ + } else { + if (node->type == XML_DOCUMENT_NODE) + xmlDocDump(ctxt->output, (xmlDocPtr) node); + else + xmlElemDump(ctxt->output, ctxt->doc, node); + } + fprintf(ctxt->output, "\n"); + return (0); +} +#endif /* LIBXML_OUTPUT_ENABLED */ + +/** + * xmlShellLoad: + * @ctxt: the shell context + * @filename: the file name + * @node: unused + * @node2: unused + * + * Implements the XML shell function "load" + * loads a new document specified by the filename + * + * Returns 0 or -1 if loading failed + */ +int +xmlShellLoad(xmlShellCtxtPtr ctxt, char *filename, + xmlNodePtr node ATTRIBUTE_UNUSED, + xmlNodePtr node2 ATTRIBUTE_UNUSED) +{ + xmlDocPtr doc; + int html = 0; + + if ((ctxt == NULL) || (filename == NULL)) return(-1); + if (ctxt->doc != NULL) + html = (ctxt->doc->type == XML_HTML_DOCUMENT_NODE); + + if (html) { +#ifdef LIBXML_HTML_ENABLED + doc = htmlParseFile(filename, NULL); +#else + fprintf(ctxt->output, "HTML support not compiled in\n"); + doc = NULL; +#endif /* LIBXML_HTML_ENABLED */ + } else { + doc = xmlReadFile(filename,NULL,0); + } + if (doc != NULL) { + if (ctxt->loaded == 1) { + xmlFreeDoc(ctxt->doc); + } + ctxt->loaded = 1; +#ifdef LIBXML_XPATH_ENABLED + xmlXPathFreeContext(ctxt->pctxt); +#endif /* LIBXML_XPATH_ENABLED */ + xmlFree(ctxt->filename); + ctxt->doc = doc; + ctxt->node = (xmlNodePtr) doc; +#ifdef LIBXML_XPATH_ENABLED + ctxt->pctxt = xmlXPathNewContext(doc); +#endif /* LIBXML_XPATH_ENABLED */ + ctxt->filename = (char *) xmlCanonicPath((xmlChar *) filename); + } else + return (-1); + return (0); +} + +#ifdef LIBXML_OUTPUT_ENABLED +/** + * xmlShellWrite: + * @ctxt: the shell context + * @filename: the file name + * @node: a node in the tree + * @node2: unused + * + * Implements the XML shell function "write" + * Write the current node to the filename, it saves the serialization + * of the subtree under the @node specified + * + * Returns 0 or -1 in case of error + */ +int +xmlShellWrite(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node, + xmlNodePtr node2 ATTRIBUTE_UNUSED) +{ + if (node == NULL) + return (-1); + if ((filename == NULL) || (filename[0] == 0)) { + return (-1); + } +#ifdef W_OK + if (access((char *) filename, W_OK)) { + xmlGenericError(xmlGenericErrorContext, + "Cannot write to %s\n", filename); + return (-1); + } +#endif + switch (node->type) { + case XML_DOCUMENT_NODE: + if (xmlSaveFile((char *) filename, ctxt->doc) < -1) { + xmlGenericError(xmlGenericErrorContext, + "Failed to write to %s\n", filename); + return (-1); + } + break; + case XML_HTML_DOCUMENT_NODE: +#ifdef LIBXML_HTML_ENABLED + if (htmlSaveFile((char *) filename, ctxt->doc) < 0) { + xmlGenericError(xmlGenericErrorContext, + "Failed to write to %s\n", filename); + return (-1); + } +#else + if (xmlSaveFile((char *) filename, ctxt->doc) < -1) { + xmlGenericError(xmlGenericErrorContext, + "Failed to write to %s\n", filename); + return (-1); + } +#endif /* LIBXML_HTML_ENABLED */ + break; + default:{ + FILE *f; + + f = fopen((char *) filename, "w"); + if (f == NULL) { + xmlGenericError(xmlGenericErrorContext, + "Failed to write to %s\n", filename); + return (-1); + } + xmlElemDump(f, ctxt->doc, node); + fclose(f); + } + } + return (0); +} + +/** + * xmlShellSave: + * @ctxt: the shell context + * @filename: the file name (optional) + * @node: unused + * @node2: unused + * + * Implements the XML shell function "save" + * Write the current document to the filename, or it's original name + * + * Returns 0 or -1 in case of error + */ +int +xmlShellSave(xmlShellCtxtPtr ctxt, char *filename, + xmlNodePtr node ATTRIBUTE_UNUSED, + xmlNodePtr node2 ATTRIBUTE_UNUSED) +{ + if ((ctxt == NULL) || (ctxt->doc == NULL)) + return (-1); + if ((filename == NULL) || (filename[0] == 0)) + filename = ctxt->filename; + if (filename == NULL) + return (-1); +#ifdef W_OK + if (access((char *) filename, W_OK)) { + xmlGenericError(xmlGenericErrorContext, + "Cannot save to %s\n", filename); + return (-1); + } +#endif + switch (ctxt->doc->type) { + case XML_DOCUMENT_NODE: + if (xmlSaveFile((char *) filename, ctxt->doc) < 0) { + xmlGenericError(xmlGenericErrorContext, + "Failed to save to %s\n", filename); + } + break; + case XML_HTML_DOCUMENT_NODE: +#ifdef LIBXML_HTML_ENABLED + if (htmlSaveFile((char *) filename, ctxt->doc) < 0) { + xmlGenericError(xmlGenericErrorContext, + "Failed to save to %s\n", filename); + } +#else + if (xmlSaveFile((char *) filename, ctxt->doc) < 0) { + xmlGenericError(xmlGenericErrorContext, + "Failed to save to %s\n", filename); + } +#endif /* LIBXML_HTML_ENABLED */ + break; + default: + xmlGenericError(xmlGenericErrorContext, + "To save to subparts of a document use the 'write' command\n"); + return (-1); + + } + return (0); +} +#endif /* LIBXML_OUTPUT_ENABLED */ + +#ifdef LIBXML_VALID_ENABLED +/** + * xmlShellValidate: + * @ctxt: the shell context + * @dtd: the DTD URI (optional) + * @node: unused + * @node2: unused + * + * Implements the XML shell function "validate" + * Validate the document, if a DTD path is provided, then the validation + * is done against the given DTD. + * + * Returns 0 or -1 in case of error + */ +int +xmlShellValidate(xmlShellCtxtPtr ctxt, char *dtd, + xmlNodePtr node ATTRIBUTE_UNUSED, + xmlNodePtr node2 ATTRIBUTE_UNUSED) +{ + xmlValidCtxt vctxt; + int res = -1; + + if ((ctxt == NULL) || (ctxt->doc == NULL)) return(-1); + vctxt.userData = stderr; + vctxt.error = (xmlValidityErrorFunc) fprintf; + vctxt.warning = (xmlValidityWarningFunc) fprintf; + + if ((dtd == NULL) || (dtd[0] == 0)) { + res = xmlValidateDocument(&vctxt, ctxt->doc); + } else { + xmlDtdPtr subset; + + subset = xmlParseDTD(NULL, (xmlChar *) dtd); + if (subset != NULL) { + res = xmlValidateDtd(&vctxt, ctxt->doc, subset); + + xmlFreeDtd(subset); + } + } + return (res); +} +#endif /* LIBXML_VALID_ENABLED */ + +/** + * xmlShellDu: + * @ctxt: the shell context + * @arg: unused + * @tree: a node defining a subtree + * @node2: unused + * + * Implements the XML shell function "du" + * show the structure of the subtree under node @tree + * If @tree is null, the command works on the current node. + * + * Returns 0 or -1 in case of error + */ +int +xmlShellDu(xmlShellCtxtPtr ctxt, + char *arg ATTRIBUTE_UNUSED, xmlNodePtr tree, + xmlNodePtr node2 ATTRIBUTE_UNUSED) +{ + xmlNodePtr node; + int indent = 0, i; + + if (!ctxt) + return (-1); + + if (tree == NULL) + return (-1); + node = tree; + while (node != NULL) { + if ((node->type == XML_DOCUMENT_NODE) || + (node->type == XML_HTML_DOCUMENT_NODE)) { + fprintf(ctxt->output, "/\n"); + } else if (node->type == XML_ELEMENT_NODE) { + for (i = 0; i < indent; i++) + fprintf(ctxt->output, " "); + fprintf(ctxt->output, "%s\n", node->name); + } else { + } + + /* + * Browse the full subtree, deep first + */ + + if ((node->type == XML_DOCUMENT_NODE) || + (node->type == XML_HTML_DOCUMENT_NODE)) { + node = ((xmlDocPtr) node)->children; + } else if ((node->children != NULL) + && (node->type != XML_ENTITY_REF_NODE)) { + /* deep first */ + node = node->children; + indent++; + } else if ((node != tree) && (node->next != NULL)) { + /* then siblings */ + node = node->next; + } else if (node != tree) { + /* go up to parents->next if needed */ + while (node != tree) { + if (node->parent != NULL) { + node = node->parent; + indent--; + } + if ((node != tree) && (node->next != NULL)) { + node = node->next; + break; + } + if (node->parent == NULL) { + node = NULL; + break; + } + if (node == tree) { + node = NULL; + break; + } + } + /* exit condition */ + if (node == tree) + node = NULL; + } else + node = NULL; + } + return (0); +} + +/** + * xmlShellPwd: + * @ctxt: the shell context + * @buffer: the output buffer + * @node: a node + * @node2: unused + * + * Implements the XML shell function "pwd" + * Show the full path from the root to the node, if needed building + * thumblers when similar elements exists at a given ancestor level. + * The output is compatible with XPath commands. + * + * Returns 0 or -1 in case of error + */ +int +xmlShellPwd(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED, char *buffer, + xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED) +{ + xmlChar *path; + + if ((node == NULL) || (buffer == NULL)) + return (-1); + + path = xmlGetNodePath(node); + if (path == NULL) + return (-1); + + /* + * This test prevents buffer overflow, because this routine + * is only called by xmlShell, in which the second argument is + * 500 chars long. + * It is a dirty hack before a cleaner solution is found. + * Documentation should mention that the second argument must + * be at least 500 chars long, and could be stripped if too long. + */ + snprintf(buffer, 499, "%s", path); + buffer[499] = '0'; + xmlFree(path); + + return (0); +} + +/** + * xmlShell: + * @doc: the initial document + * @filename: the output buffer + * @input: the line reading function + * @output: the output FILE*, defaults to stdout if NULL + * + * Implements the XML shell + * This allow to load, validate, view, modify and save a document + * using a environment similar to a UNIX commandline. + */ +void +xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input, + FILE * output) +{ + char prompt[500] = "/ > "; + char *cmdline = NULL, *cur; + int nbargs; + char command[100]; + char arg[400]; + int i; + xmlShellCtxtPtr ctxt; + xmlXPathObjectPtr list; + + if (doc == NULL) + return; + if (filename == NULL) + return; + if (input == NULL) + return; + if (output == NULL) + output = stdout; + ctxt = (xmlShellCtxtPtr) xmlMalloc(sizeof(xmlShellCtxt)); + if (ctxt == NULL) + return; + ctxt->loaded = 0; + ctxt->doc = doc; + ctxt->input = input; + ctxt->output = output; + ctxt->filename = (char *) xmlStrdup((xmlChar *) filename); + ctxt->node = (xmlNodePtr) ctxt->doc; + +#ifdef LIBXML_XPATH_ENABLED + ctxt->pctxt = xmlXPathNewContext(ctxt->doc); + if (ctxt->pctxt == NULL) { + xmlFree(ctxt); + return; + } +#endif /* LIBXML_XPATH_ENABLED */ + while (1) { + if (ctxt->node == (xmlNodePtr) ctxt->doc) + snprintf(prompt, sizeof(prompt), "%s > ", "/"); + else if ((ctxt->node != NULL) && (ctxt->node->name)) + snprintf(prompt, sizeof(prompt), "%s > ", ctxt->node->name); + else + snprintf(prompt, sizeof(prompt), "? > "); + prompt[sizeof(prompt) - 1] = 0; + + /* + * Get a new command line + */ + cmdline = ctxt->input(prompt); + if (cmdline == NULL) + break; + + /* + * Parse the command itself + */ + cur = cmdline; + nbargs = 0; + while ((*cur == ' ') || (*cur == '\t')) + cur++; + i = 0; + while ((*cur != ' ') && (*cur != '\t') && + (*cur != '\n') && (*cur != '\r')) { + if (*cur == 0) + break; + command[i++] = *cur++; + } + command[i] = 0; + if (i == 0) + continue; + nbargs++; + + /* + * Parse the argument + */ + while ((*cur == ' ') || (*cur == '\t')) + cur++; + i = 0; + while ((*cur != '\n') && (*cur != '\r') && (*cur != 0)) { + if (*cur == 0) + break; + arg[i++] = *cur++; + } + arg[i] = 0; + if (i != 0) + nbargs++; + + /* + * start interpreting the command + */ + if (!strcmp(command, "exit")) + break; + if (!strcmp(command, "quit")) + break; + if (!strcmp(command, "bye")) + break; + if (!strcmp(command, "help")) { + fprintf(ctxt->output, "\tbase display XML base of the node\n"); + fprintf(ctxt->output, "\tsetbase URI change the XML base of the node\n"); + fprintf(ctxt->output, "\tbye leave shell\n"); + fprintf(ctxt->output, "\tcat [node] display node or current node\n"); + fprintf(ctxt->output, "\tcd [path] change directory to path or to root\n"); + fprintf(ctxt->output, "\tdir [path] dumps informations about the node (namespace, attributes, content)\n"); + fprintf(ctxt->output, "\tdu [path] show the structure of the subtree under path or the current node\n"); + fprintf(ctxt->output, "\texit leave shell\n"); + fprintf(ctxt->output, "\thelp display this help\n"); + fprintf(ctxt->output, "\tfree display memory usage\n"); + fprintf(ctxt->output, "\tload [name] load a new document with name\n"); + fprintf(ctxt->output, "\tls [path] list contents of path or the current directory\n"); + fprintf(ctxt->output, "\tset xml_fragment replace the current node content with the fragment parsed in context\n"); +#ifdef LIBXML_XPATH_ENABLED + fprintf(ctxt->output, "\txpath expr evaluate the XPath expression in that context and print the result\n"); + fprintf(ctxt->output, "\tsetns nsreg register a namespace to a prefix in the XPath evaluation context\n"); + fprintf(ctxt->output, "\t format for nsreg is: prefix=[nsuri] (i.e. prefix= unsets a prefix)\n"); + fprintf(ctxt->output, "\tsetrootns register all namespace found on the root element\n"); + fprintf(ctxt->output, "\t the default namespace if any uses 'defaultns' prefix\n"); +#endif /* LIBXML_XPATH_ENABLED */ + fprintf(ctxt->output, "\tpwd display current working directory\n"); + fprintf(ctxt->output, "\tquit leave shell\n"); +#ifdef LIBXML_OUTPUT_ENABLED + fprintf(ctxt->output, "\tsave [name] save this document to name or the original name\n"); + fprintf(ctxt->output, "\twrite [name] write the current node to the filename\n"); +#endif /* LIBXML_OUTPUT_ENABLED */ +#ifdef LIBXML_VALID_ENABLED + fprintf(ctxt->output, "\tvalidate check the document for errors\n"); +#endif /* LIBXML_VALID_ENABLED */ +#ifdef LIBXML_SCHEMAS_ENABLED + fprintf(ctxt->output, "\trelaxng rng validate the document agaisnt the Relax-NG schemas\n"); +#endif + fprintf(ctxt->output, "\tgrep string search for a string in the subtree\n"); +#ifdef LIBXML_VALID_ENABLED + } else if (!strcmp(command, "validate")) { + xmlShellValidate(ctxt, arg, NULL, NULL); +#endif /* LIBXML_VALID_ENABLED */ + } else if (!strcmp(command, "load")) { + xmlShellLoad(ctxt, arg, NULL, NULL); +#ifdef LIBXML_SCHEMAS_ENABLED + } else if (!strcmp(command, "relaxng")) { + xmlShellRNGValidate(ctxt, arg, NULL, NULL); +#endif +#ifdef LIBXML_OUTPUT_ENABLED + } else if (!strcmp(command, "save")) { + xmlShellSave(ctxt, arg, NULL, NULL); + } else if (!strcmp(command, "write")) { + if ((arg == NULL) || (arg[0] == 0)) + xmlGenericError(xmlGenericErrorContext, + "Write command requires a filename argument\n"); + else + xmlShellWrite(ctxt, arg, NULL, NULL); +#endif /* LIBXML_OUTPUT_ENABLED */ + } else if (!strcmp(command, "grep")) { + xmlShellGrep(ctxt, arg, ctxt->node, NULL); + } else if (!strcmp(command, "free")) { + if (arg[0] == 0) { + xmlMemShow(ctxt->output, 0); + } else { + int len = 0; + + sscanf(arg, "%d", &len); + xmlMemShow(ctxt->output, len); + } + } else if (!strcmp(command, "pwd")) { + char dir[500]; + + if (!xmlShellPwd(ctxt, dir, ctxt->node, NULL)) + fprintf(ctxt->output, "%s\n", dir); + } else if (!strcmp(command, "du")) { + xmlShellDu(ctxt, NULL, ctxt->node, NULL); + } else if (!strcmp(command, "base")) { + xmlShellBase(ctxt, NULL, ctxt->node, NULL); + } else if (!strcmp(command, "set")) { + xmlShellSetContent(ctxt, arg, ctxt->node, NULL); +#ifdef LIBXML_XPATH_ENABLED + } else if (!strcmp(command, "setns")) { + if (arg[0] == 0) { + xmlGenericError(xmlGenericErrorContext, + "setns: prefix=[nsuri] required\n"); + } else { + xmlShellRegisterNamespace(ctxt, arg, NULL, NULL); + } + } else if (!strcmp(command, "setrootns")) { + xmlNodePtr root; + + root = xmlDocGetRootElement(ctxt->doc); + xmlShellRegisterRootNamespaces(ctxt, NULL, root, NULL); + } else if (!strcmp(command, "xpath")) { + if (arg[0] == 0) { + xmlGenericError(xmlGenericErrorContext, + "xpath: expression required\n"); + } else { + ctxt->pctxt->node = ctxt->node; + list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt); + xmlXPathDebugDumpObject(ctxt->output, list, 0); + xmlXPathFreeObject(list); + } +#endif /* LIBXML_XPATH_ENABLED */ +#ifdef LIBXML_TREE_ENABLED + } else if (!strcmp(command, "setbase")) { + xmlShellSetBase(ctxt, arg, ctxt->node, NULL); +#endif + } else if ((!strcmp(command, "ls")) || (!strcmp(command, "dir"))) { + int dir = (!strcmp(command, "dir")); + + if (arg[0] == 0) { + if (dir) + xmlShellDir(ctxt, NULL, ctxt->node, NULL); + else + xmlShellList(ctxt, NULL, ctxt->node, NULL); + } else { + ctxt->pctxt->node = ctxt->node; +#ifdef LIBXML_XPATH_ENABLED + ctxt->pctxt->node = ctxt->node; + list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt); +#else + list = NULL; +#endif /* LIBXML_XPATH_ENABLED */ + if (list != NULL) { + switch (list->type) { + case XPATH_UNDEFINED: + xmlGenericError(xmlGenericErrorContext, + "%s: no such node\n", arg); + break; + case XPATH_NODESET:{ + int indx; + + if (list->nodesetval == NULL) + break; + + for (indx = 0; + indx < list->nodesetval->nodeNr; + indx++) { + if (dir) + xmlShellDir(ctxt, NULL, + list->nodesetval-> + nodeTab[indx], NULL); + else + xmlShellList(ctxt, NULL, + list->nodesetval-> + nodeTab[indx], NULL); + } + break; + } + case XPATH_BOOLEAN: + xmlGenericError(xmlGenericErrorContext, + "%s is a Boolean\n", arg); + break; + case XPATH_NUMBER: + xmlGenericError(xmlGenericErrorContext, + "%s is a number\n", arg); + break; + case XPATH_STRING: + xmlGenericError(xmlGenericErrorContext, + "%s is a string\n", arg); + break; + case XPATH_POINT: + xmlGenericError(xmlGenericErrorContext, + "%s is a point\n", arg); + break; + case XPATH_RANGE: + xmlGenericError(xmlGenericErrorContext, + "%s is a range\n", arg); + break; + case XPATH_LOCATIONSET: + xmlGenericError(xmlGenericErrorContext, + "%s is a range\n", arg); + break; + case XPATH_USERS: + xmlGenericError(xmlGenericErrorContext, + "%s is user-defined\n", arg); + break; + case XPATH_XSLT_TREE: + xmlGenericError(xmlGenericErrorContext, + "%s is an XSLT value tree\n", + arg); + break; + } +#ifdef LIBXML_XPATH_ENABLED + xmlXPathFreeObject(list); +#endif + } else { + xmlGenericError(xmlGenericErrorContext, + "%s: no such node\n", arg); + } + ctxt->pctxt->node = NULL; + } + } else if (!strcmp(command, "cd")) { + if (arg[0] == 0) { + ctxt->node = (xmlNodePtr) ctxt->doc; + } else { +#ifdef LIBXML_XPATH_ENABLED + ctxt->pctxt->node = ctxt->node; + list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt); +#else + list = NULL; +#endif /* LIBXML_XPATH_ENABLED */ + if (list != NULL) { + switch (list->type) { + case XPATH_UNDEFINED: + xmlGenericError(xmlGenericErrorContext, + "%s: no such node\n", arg); + break; + case XPATH_NODESET: + if (list->nodesetval != NULL) { + if (list->nodesetval->nodeNr == 1) { + ctxt->node = list->nodesetval->nodeTab[0]; + if ((ctxt->node != NULL) && + (ctxt->node->type == + XML_NAMESPACE_DECL)) { + xmlGenericError(xmlGenericErrorContext, + "cannot cd to namespace\n"); + ctxt->node = NULL; + } + } else + xmlGenericError(xmlGenericErrorContext, + "%s is a %d Node Set\n", + arg, + list->nodesetval->nodeNr); + } else + xmlGenericError(xmlGenericErrorContext, + "%s is an empty Node Set\n", + arg); + break; + case XPATH_BOOLEAN: + xmlGenericError(xmlGenericErrorContext, + "%s is a Boolean\n", arg); + break; + case XPATH_NUMBER: + xmlGenericError(xmlGenericErrorContext, + "%s is a number\n", arg); + break; + case XPATH_STRING: + xmlGenericError(xmlGenericErrorContext, + "%s is a string\n", arg); + break; + case XPATH_POINT: + xmlGenericError(xmlGenericErrorContext, + "%s is a point\n", arg); + break; + case XPATH_RANGE: + xmlGenericError(xmlGenericErrorContext, + "%s is a range\n", arg); + break; + case XPATH_LOCATIONSET: + xmlGenericError(xmlGenericErrorContext, + "%s is a range\n", arg); + break; + case XPATH_USERS: + xmlGenericError(xmlGenericErrorContext, + "%s is user-defined\n", arg); + break; + case XPATH_XSLT_TREE: + xmlGenericError(xmlGenericErrorContext, + "%s is an XSLT value tree\n", + arg); + break; + } +#ifdef LIBXML_XPATH_ENABLED + xmlXPathFreeObject(list); +#endif + } else { + xmlGenericError(xmlGenericErrorContext, + "%s: no such node\n", arg); + } + ctxt->pctxt->node = NULL; + } +#ifdef LIBXML_OUTPUT_ENABLED + } else if (!strcmp(command, "cat")) { + if (arg[0] == 0) { + xmlShellCat(ctxt, NULL, ctxt->node, NULL); + } else { + ctxt->pctxt->node = ctxt->node; +#ifdef LIBXML_XPATH_ENABLED + ctxt->pctxt->node = ctxt->node; + list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt); +#else + list = NULL; +#endif /* LIBXML_XPATH_ENABLED */ + if (list != NULL) { + switch (list->type) { + case XPATH_UNDEFINED: + xmlGenericError(xmlGenericErrorContext, + "%s: no such node\n", arg); + break; + case XPATH_NODESET:{ + int indx; + + if (list->nodesetval == NULL) + break; + + for (indx = 0; + indx < list->nodesetval->nodeNr; + indx++) { + if (i > 0) + fprintf(ctxt->output, " -------\n"); + xmlShellCat(ctxt, NULL, + list->nodesetval-> + nodeTab[indx], NULL); + } + break; + } + case XPATH_BOOLEAN: + xmlGenericError(xmlGenericErrorContext, + "%s is a Boolean\n", arg); + break; + case XPATH_NUMBER: + xmlGenericError(xmlGenericErrorContext, + "%s is a number\n", arg); + break; + case XPATH_STRING: + xmlGenericError(xmlGenericErrorContext, + "%s is a string\n", arg); + break; + case XPATH_POINT: + xmlGenericError(xmlGenericErrorContext, + "%s is a point\n", arg); + break; + case XPATH_RANGE: + xmlGenericError(xmlGenericErrorContext, + "%s is a range\n", arg); + break; + case XPATH_LOCATIONSET: + xmlGenericError(xmlGenericErrorContext, + "%s is a range\n", arg); + break; + case XPATH_USERS: + xmlGenericError(xmlGenericErrorContext, + "%s is user-defined\n", arg); + break; + case XPATH_XSLT_TREE: + xmlGenericError(xmlGenericErrorContext, + "%s is an XSLT value tree\n", + arg); + break; + } +#ifdef LIBXML_XPATH_ENABLED + xmlXPathFreeObject(list); +#endif + } else { + xmlGenericError(xmlGenericErrorContext, + "%s: no such node\n", arg); + } + ctxt->pctxt->node = NULL; + } +#endif /* LIBXML_OUTPUT_ENABLED */ + } else { + xmlGenericError(xmlGenericErrorContext, + "Unknown command %s\n", command); + } + free(cmdline); /* not xmlFree here ! */ + } +#ifdef LIBXML_XPATH_ENABLED + xmlXPathFreeContext(ctxt->pctxt); +#endif /* LIBXML_XPATH_ENABLED */ + if (ctxt->loaded) { + xmlFreeDoc(ctxt->doc); + } + if (ctxt->filename != NULL) + xmlFree(ctxt->filename); + xmlFree(ctxt); + if (cmdline != NULL) + free(cmdline); /* not xmlFree here ! */ +} + +#endif /* LIBXML_XPATH_ENABLED */ +#define bottom_debugXML +#include "elfgcchack.h" +#endif /* LIBXML_DEBUG_ENABLED */ diff --git a/gettext-tools/gnulib-lib/libxml/debugXML.in.h b/gettext-tools/gnulib-lib/libxml/debugXML.in.h new file mode 100644 index 0000000..5a9d20b --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/debugXML.in.h @@ -0,0 +1,217 @@ +/* + * Summary: Tree debugging APIs + * Description: Interfaces to a set of routines used for debugging the tree + * produced by the XML parser. + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + +#ifndef __DEBUG_XML__ +#define __DEBUG_XML__ +#include +#include +#include + +#ifdef LIBXML_DEBUG_ENABLED + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * The standard Dump routines. + */ +XMLPUBFUN void XMLCALL + xmlDebugDumpString (FILE *output, + const xmlChar *str); +XMLPUBFUN void XMLCALL + xmlDebugDumpAttr (FILE *output, + xmlAttrPtr attr, + int depth); +XMLPUBFUN void XMLCALL + xmlDebugDumpAttrList (FILE *output, + xmlAttrPtr attr, + int depth); +XMLPUBFUN void XMLCALL + xmlDebugDumpOneNode (FILE *output, + xmlNodePtr node, + int depth); +XMLPUBFUN void XMLCALL + xmlDebugDumpNode (FILE *output, + xmlNodePtr node, + int depth); +XMLPUBFUN void XMLCALL + xmlDebugDumpNodeList (FILE *output, + xmlNodePtr node, + int depth); +XMLPUBFUN void XMLCALL + xmlDebugDumpDocumentHead(FILE *output, + xmlDocPtr doc); +XMLPUBFUN void XMLCALL + xmlDebugDumpDocument (FILE *output, + xmlDocPtr doc); +XMLPUBFUN void XMLCALL + xmlDebugDumpDTD (FILE *output, + xmlDtdPtr dtd); +XMLPUBFUN void XMLCALL + xmlDebugDumpEntities (FILE *output, + xmlDocPtr doc); + +/**************************************************************** + * * + * Checking routines * + * * + ****************************************************************/ + +XMLPUBFUN int XMLCALL + xmlDebugCheckDocument (FILE * output, + xmlDocPtr doc); + +/**************************************************************** + * * + * XML shell helpers * + * * + ****************************************************************/ + +XMLPUBFUN void XMLCALL + xmlLsOneNode (FILE *output, xmlNodePtr node); +XMLPUBFUN int XMLCALL + xmlLsCountNode (xmlNodePtr node); + +XMLPUBFUN const char * XMLCALL + xmlBoolToText (int boolval); + +/**************************************************************** + * * + * The XML shell related structures and functions * + * * + ****************************************************************/ + +#ifdef LIBXML_XPATH_ENABLED +/** + * xmlShellReadlineFunc: + * @prompt: a string prompt + * + * This is a generic signature for the XML shell input function. + * + * Returns a string which will be freed by the Shell. + */ +typedef char * (* xmlShellReadlineFunc)(char *prompt); + +/** + * xmlShellCtxt: + * + * A debugging shell context. + * TODO: add the defined function tables. + */ +typedef struct _xmlShellCtxt xmlShellCtxt; +typedef xmlShellCtxt *xmlShellCtxtPtr; +struct _xmlShellCtxt { + char *filename; + xmlDocPtr doc; + xmlNodePtr node; + xmlXPathContextPtr pctxt; + int loaded; + FILE *output; + xmlShellReadlineFunc input; +}; + +/** + * xmlShellCmd: + * @ctxt: a shell context + * @arg: a string argument + * @node: a first node + * @node2: a second node + * + * This is a generic signature for the XML shell functions. + * + * Returns an int, negative returns indicating errors. + */ +typedef int (* xmlShellCmd) (xmlShellCtxtPtr ctxt, + char *arg, + xmlNodePtr node, + xmlNodePtr node2); + +XMLPUBFUN void XMLCALL + xmlShellPrintXPathError (int errorType, + const char *arg); +XMLPUBFUN void XMLCALL + xmlShellPrintXPathResult(xmlXPathObjectPtr list); +XMLPUBFUN int XMLCALL + xmlShellList (xmlShellCtxtPtr ctxt, + char *arg, + xmlNodePtr node, + xmlNodePtr node2); +XMLPUBFUN int XMLCALL + xmlShellBase (xmlShellCtxtPtr ctxt, + char *arg, + xmlNodePtr node, + xmlNodePtr node2); +XMLPUBFUN int XMLCALL + xmlShellDir (xmlShellCtxtPtr ctxt, + char *arg, + xmlNodePtr node, + xmlNodePtr node2); +XMLPUBFUN int XMLCALL + xmlShellLoad (xmlShellCtxtPtr ctxt, + char *filename, + xmlNodePtr node, + xmlNodePtr node2); +#ifdef LIBXML_OUTPUT_ENABLED +XMLPUBFUN void XMLCALL + xmlShellPrintNode (xmlNodePtr node); +XMLPUBFUN int XMLCALL + xmlShellCat (xmlShellCtxtPtr ctxt, + char *arg, + xmlNodePtr node, + xmlNodePtr node2); +XMLPUBFUN int XMLCALL + xmlShellWrite (xmlShellCtxtPtr ctxt, + char *filename, + xmlNodePtr node, + xmlNodePtr node2); +XMLPUBFUN int XMLCALL + xmlShellSave (xmlShellCtxtPtr ctxt, + char *filename, + xmlNodePtr node, + xmlNodePtr node2); +#endif /* LIBXML_OUTPUT_ENABLED */ +#ifdef LIBXML_VALID_ENABLED +XMLPUBFUN int XMLCALL + xmlShellValidate (xmlShellCtxtPtr ctxt, + char *dtd, + xmlNodePtr node, + xmlNodePtr node2); +#endif /* LIBXML_VALID_ENABLED */ +XMLPUBFUN int XMLCALL + xmlShellDu (xmlShellCtxtPtr ctxt, + char *arg, + xmlNodePtr tree, + xmlNodePtr node2); +XMLPUBFUN int XMLCALL + xmlShellPwd (xmlShellCtxtPtr ctxt, + char *buffer, + xmlNodePtr node, + xmlNodePtr node2); + +/* + * The Shell interface. + */ +XMLPUBFUN void XMLCALL + xmlShell (xmlDocPtr doc, + char *filename, + xmlShellReadlineFunc input, + FILE *output); + +#endif /* LIBXML_XPATH_ENABLED */ + +#ifdef __cplusplus +} +#endif + +#endif /* LIBXML_DEBUG_ENABLED */ +#endif /* __DEBUG_XML__ */ diff --git a/gettext-tools/gnulib-lib/libxml/dict.c b/gettext-tools/gnulib-lib/libxml/dict.c new file mode 100644 index 0000000..3b4054f --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/dict.c @@ -0,0 +1,901 @@ +/* + * dict.c: dictionary of reusable strings, just used to avoid allocation + * and freeing operations. + * + * Copyright (C) 2003 Daniel Veillard. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND + * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER. + * + * Author: daniel@veillard.com + */ + +#define IN_LIBXML +#include "libxml.h" + +#include +#include +#include +#include +#include +#include + +#define MAX_HASH_LEN 4 +#define MIN_DICT_SIZE 128 +#define MAX_DICT_HASH 8 * 2048 + +/* #define ALLOW_REMOVAL */ +/* #define DEBUG_GROW */ + +/* + * An entry in the dictionnary + */ +typedef struct _xmlDictEntry xmlDictEntry; +typedef xmlDictEntry *xmlDictEntryPtr; +struct _xmlDictEntry { + struct _xmlDictEntry *next; + const xmlChar *name; + int len; + int valid; +}; + +typedef struct _xmlDictStrings xmlDictStrings; +typedef xmlDictStrings *xmlDictStringsPtr; +struct _xmlDictStrings { + xmlDictStringsPtr next; + xmlChar *free; + xmlChar *end; + int size; + int nbStrings; + xmlChar array[1]; +}; +/* + * The entire dictionnary + */ +struct _xmlDict { + int ref_counter; + xmlRMutexPtr mutex; + + struct _xmlDictEntry *dict; + int size; + int nbElems; + xmlDictStringsPtr strings; + + struct _xmlDict *subdict; +}; + +/* + * A mutex for modifying the reference counter for shared + * dictionaries. + */ +static xmlRMutexPtr xmlDictMutex = NULL; + +/* + * Whether the dictionary mutex was initialized. + */ +static int xmlDictInitialized = 0; + +/** + * xmlInitializeDict: + * + * Do the dictionary mutex initialization. + * this function is not thread safe, initialization should + * preferably be done once at startup + */ +static int xmlInitializeDict(void) { + if (xmlDictInitialized) + return(1); + + if ((xmlDictMutex = xmlNewRMutex()) == NULL) + return(0); + + xmlDictInitialized = 1; + return(1); +} + +/** + * xmlDictCleanup: + * + * Free the dictionary mutex. + */ +void +xmlDictCleanup(void) { + if (!xmlDictInitialized) + return; + + xmlFreeRMutex(xmlDictMutex); + + xmlDictInitialized = 0; +} + +/* + * xmlDictAddString: + * @dict: the dictionnary + * @name: the name of the userdata + * @len: the length of the name, if -1 it is recomputed + * + * Add the string to the array[s] + * + * Returns the pointer of the local string, or NULL in case of error. + */ +static const xmlChar * +xmlDictAddString(xmlDictPtr dict, const xmlChar *name, int namelen) { + xmlDictStringsPtr pool; + const xmlChar *ret; + int size = 0; /* + sizeof(_xmlDictStrings) == 1024 */ + + pool = dict->strings; + while (pool != NULL) { + if (pool->end - pool->free > namelen) + goto found_pool; + if (pool->size > size) size = pool->size; + pool = pool->next; + } + /* + * Not found, need to allocate + */ + if (pool == NULL) { + if (size == 0) size = 1000; + else size *= 4; /* exponential growth */ + if (size < 4 * namelen) + size = 4 * namelen; /* just in case ! */ + pool = (xmlDictStringsPtr) xmlMalloc(sizeof(xmlDictStrings) + size); + if (pool == NULL) + return(NULL); + pool->size = size; + pool->nbStrings = 0; + pool->free = &pool->array[0]; + pool->end = &pool->array[size]; + pool->next = dict->strings; + dict->strings = pool; + } +found_pool: + ret = pool->free; + memcpy(pool->free, name, namelen); + pool->free += namelen; + *(pool->free++) = 0; + return(ret); +} + +/* + * xmlDictAddQString: + * @dict: the dictionnary + * @prefix: the prefix of the userdata + * @name: the name of the userdata + * @len: the length of the name, if -1 it is recomputed + * + * Add the QName to the array[s] + * + * Returns the pointer of the local string, or NULL in case of error. + */ +static const xmlChar * +xmlDictAddQString(xmlDictPtr dict, const xmlChar *prefix, + const xmlChar *name, int namelen) +{ + xmlDictStringsPtr pool; + const xmlChar *ret; + int size = 0; /* + sizeof(_xmlDictStrings) == 1024 */ + int plen; + + if (prefix == NULL) return(xmlDictAddString(dict, name, namelen)); + plen = xmlStrlen(prefix); + + pool = dict->strings; + while (pool != NULL) { + if (pool->end - pool->free > namelen) + goto found_pool; + if (pool->size > size) size = pool->size; + pool = pool->next; + } + /* + * Not found, need to allocate + */ + if (pool == NULL) { + if (size == 0) size = 1000; + else size *= 4; /* exponential growth */ + if (size < 4 * namelen) + size = 4 * namelen; /* just in case ! */ + pool = (xmlDictStringsPtr) xmlMalloc(sizeof(xmlDictStrings) + size); + if (pool == NULL) + return(NULL); + pool->size = size; + pool->nbStrings = 0; + pool->free = &pool->array[0]; + pool->end = &pool->array[size]; + pool->next = dict->strings; + dict->strings = pool; + } +found_pool: + ret = pool->free; + memcpy(pool->free, prefix, plen); + pool->free += plen; + *(pool->free++) = ':'; + namelen -= plen + 1; + memcpy(pool->free, name, namelen); + pool->free += namelen; + *(pool->free++) = 0; + return(ret); +} + +/* + * xmlDictComputeKey: + * Calculate the hash key + */ +static unsigned long +xmlDictComputeKey(const xmlChar *name, int namelen) { + unsigned long value = 0L; + + if (name == NULL) return(0); + value = *name; + value <<= 5; + if (namelen > 10) { + value += name[namelen - 1]; + namelen = 10; + } + switch (namelen) { + case 10: value += name[9]; + case 9: value += name[8]; + case 8: value += name[7]; + case 7: value += name[6]; + case 6: value += name[5]; + case 5: value += name[4]; + case 4: value += name[3]; + case 3: value += name[2]; + case 2: value += name[1]; + default: break; + } + return(value); +} + +/* + * xmlDictComputeQKey: + * Calculate the hash key + */ +static unsigned long +xmlDictComputeQKey(const xmlChar *prefix, const xmlChar *name, int len) +{ + unsigned long value = 0L; + int plen; + + if (prefix == NULL) + return(xmlDictComputeKey(name, len)); + + plen = xmlStrlen(prefix); + if (plen == 0) + value += 30 * (unsigned long) ':'; + else + value += 30 * (*prefix); + + if (len > 10) { + value += name[len - (plen + 1 + 1)]; + len = 10; + if (plen > 10) + plen = 10; + } + switch (plen) { + case 10: value += prefix[9]; + case 9: value += prefix[8]; + case 8: value += prefix[7]; + case 7: value += prefix[6]; + case 6: value += prefix[5]; + case 5: value += prefix[4]; + case 4: value += prefix[3]; + case 3: value += prefix[2]; + case 2: value += prefix[1]; + case 1: value += prefix[0]; + default: break; + } + len -= plen; + if (len > 0) { + value += (unsigned long) ':'; + len--; + } + switch (len) { + case 10: value += name[9]; + case 9: value += name[8]; + case 8: value += name[7]; + case 7: value += name[6]; + case 6: value += name[5]; + case 5: value += name[4]; + case 4: value += name[3]; + case 3: value += name[2]; + case 2: value += name[1]; + case 1: value += name[0]; + default: break; + } + return(value); +} + +/** + * xmlDictCreate: + * + * Create a new dictionary + * + * Returns the newly created dictionnary, or NULL if an error occured. + */ +xmlDictPtr +xmlDictCreate(void) { + xmlDictPtr dict; + + if (!xmlDictInitialized) + if (!xmlInitializeDict()) + return(NULL); + + dict = xmlMalloc(sizeof(xmlDict)); + if (dict) { + dict->ref_counter = 1; + + dict->size = MIN_DICT_SIZE; + dict->nbElems = 0; + dict->dict = xmlMalloc(MIN_DICT_SIZE * sizeof(xmlDictEntry)); + dict->strings = NULL; + dict->subdict = NULL; + if (dict->dict) { + if ((dict->mutex = xmlNewRMutex()) != NULL) { + memset(dict->dict, 0, MIN_DICT_SIZE * sizeof(xmlDictEntry)); + return(dict); + } + xmlFree(dict->dict); + } + xmlFree(dict); + } + return(NULL); +} + +/** + * xmlDictCreateSub: + * @sub: an existing dictionnary + * + * Create a new dictionary, inheriting strings from the read-only + * dictionnary @sub. On lookup, strings are first searched in the + * new dictionnary, then in @sub, and if not found are created in the + * new dictionnary. + * + * Returns the newly created dictionnary, or NULL if an error occured. + */ +xmlDictPtr +xmlDictCreateSub(xmlDictPtr sub) { + xmlDictPtr dict = xmlDictCreate(); + + if ((dict != NULL) && (sub != NULL)) { + dict->subdict = sub; + xmlDictReference(dict->subdict); + } + return(dict); +} + +/** + * xmlDictReference: + * @dict: the dictionnary + * + * Increment the reference counter of a dictionary + * + * Returns 0 in case of success and -1 in case of error + */ +int +xmlDictReference(xmlDictPtr dict) { + if (!xmlDictInitialized) + if (!xmlInitializeDict()) + return(-1); + + if (dict == NULL) return -1; + xmlRMutexLock(xmlDictMutex); + dict->ref_counter++; + xmlRMutexUnlock(xmlDictMutex); + return(0); +} + +/** + * xmlDictGrow: + * @dict: the dictionnary + * @size: the new size of the dictionnary + * + * resize the dictionnary + * + * Returns 0 in case of success, -1 in case of failure + */ +static int +xmlDictGrow(xmlDictPtr dict, int size) { + unsigned long key; + int oldsize, i; + xmlDictEntryPtr iter, next; + struct _xmlDictEntry *olddict; +#ifdef DEBUG_GROW + unsigned long nbElem = 0; +#endif + + if (dict == NULL) + return(-1); + if (size < 8) + return(-1); + if (size > 8 * 2048) + return(-1); + + oldsize = dict->size; + olddict = dict->dict; + if (olddict == NULL) + return(-1); + + dict->dict = xmlMalloc(size * sizeof(xmlDictEntry)); + if (dict->dict == NULL) { + dict->dict = olddict; + return(-1); + } + memset(dict->dict, 0, size * sizeof(xmlDictEntry)); + dict->size = size; + + /* If the two loops are merged, there would be situations where + a new entry needs to allocated and data copied into it from + the main dict. So instead, we run through the array twice, first + copying all the elements in the main array (where we can't get + conflicts) and then the rest, so we only free (and don't allocate) + */ + for (i = 0; i < oldsize; i++) { + if (olddict[i].valid == 0) + continue; + key = xmlDictComputeKey(olddict[i].name, olddict[i].len) % dict->size; + memcpy(&(dict->dict[key]), &(olddict[i]), sizeof(xmlDictEntry)); + dict->dict[key].next = NULL; +#ifdef DEBUG_GROW + nbElem++; +#endif + } + + for (i = 0; i < oldsize; i++) { + iter = olddict[i].next; + while (iter) { + next = iter->next; + + /* + * put back the entry in the new dict + */ + + key = xmlDictComputeKey(iter->name, iter->len) % dict->size; + if (dict->dict[key].valid == 0) { + memcpy(&(dict->dict[key]), iter, sizeof(xmlDictEntry)); + dict->dict[key].next = NULL; + dict->dict[key].valid = 1; + xmlFree(iter); + } else { + iter->next = dict->dict[key].next; + dict->dict[key].next = iter; + } + +#ifdef DEBUG_GROW + nbElem++; +#endif + + iter = next; + } + } + + xmlFree(olddict); + +#ifdef DEBUG_GROW + xmlGenericError(xmlGenericErrorContext, + "xmlDictGrow : from %d to %d, %d elems\n", oldsize, size, nbElem); +#endif + + return(0); +} + +/** + * xmlDictFree: + * @dict: the dictionnary + * + * Free the hash @dict and its contents. The userdata is + * deallocated with @f if provided. + */ +void +xmlDictFree(xmlDictPtr dict) { + int i; + xmlDictEntryPtr iter; + xmlDictEntryPtr next; + int inside_dict = 0; + xmlDictStringsPtr pool, nextp; + + if (dict == NULL) + return; + + if (!xmlDictInitialized) + if (!xmlInitializeDict()) + return; + + /* decrement the counter, it may be shared by a parser and docs */ + xmlRMutexLock(xmlDictMutex); + dict->ref_counter--; + if (dict->ref_counter > 0) { + xmlRMutexUnlock(xmlDictMutex); + return; + } + + xmlRMutexUnlock(xmlDictMutex); + + if (dict->subdict != NULL) { + xmlDictFree(dict->subdict); + } + + if (dict->dict) { + for(i = 0; ((i < dict->size) && (dict->nbElems > 0)); i++) { + iter = &(dict->dict[i]); + if (iter->valid == 0) + continue; + inside_dict = 1; + while (iter) { + next = iter->next; + if (!inside_dict) + xmlFree(iter); + dict->nbElems--; + inside_dict = 0; + iter = next; + } + inside_dict = 0; + } + xmlFree(dict->dict); + } + pool = dict->strings; + while (pool != NULL) { + nextp = pool->next; + xmlFree(pool); + pool = nextp; + } + xmlFreeRMutex(dict->mutex); + xmlFree(dict); +} + +/** + * xmlDictLookup: + * @dict: the dictionnary + * @name: the name of the userdata + * @len: the length of the name, if -1 it is recomputed + * + * Add the @name to the dictionnary @dict if not present. + * + * Returns the internal copy of the name or NULL in case of internal error + */ +const xmlChar * +xmlDictLookup(xmlDictPtr dict, const xmlChar *name, int len) { + unsigned long key, okey, nbi = 0; + xmlDictEntryPtr entry; + xmlDictEntryPtr insert; + const xmlChar *ret; + + if ((dict == NULL) || (name == NULL)) + return(NULL); + + if (len < 0) + len = xmlStrlen(name); + + /* + * Check for duplicate and insertion location. + */ + okey = xmlDictComputeKey(name, len); + key = okey % dict->size; + if (dict->dict[key].valid == 0) { + insert = NULL; + } else { + for (insert = &(dict->dict[key]); insert->next != NULL; + insert = insert->next) { +#ifdef __GNUC__ + if (insert->len == len) { + if (!memcmp(insert->name, name, len)) + return(insert->name); + } +#else + if ((insert->len == len) && + (!xmlStrncmp(insert->name, name, len))) + return(insert->name); +#endif + nbi++; + } +#ifdef __GNUC__ + if (insert->len == len) { + if (!memcmp(insert->name, name, len)) + return(insert->name); + } +#else + if ((insert->len == len) && + (!xmlStrncmp(insert->name, name, len))) + return(insert->name); +#endif + } + + if (dict->subdict) { + key = okey % dict->subdict->size; + if (dict->subdict->dict[key].valid != 0) { + xmlDictEntryPtr tmp; + + for (tmp = &(dict->subdict->dict[key]); tmp->next != NULL; + tmp = tmp->next) { +#ifdef __GNUC__ + if (tmp->len == len) { + if (!memcmp(tmp->name, name, len)) + return(tmp->name); + } +#else + if ((tmp->len == len) && + (!xmlStrncmp(tmp->name, name, len))) + return(tmp->name); +#endif + nbi++; + } +#ifdef __GNUC__ + if (tmp->len == len) { + if (!memcmp(tmp->name, name, len)) + return(tmp->name); + } +#else + if ((tmp->len == len) && + (!xmlStrncmp(tmp->name, name, len))) + return(tmp->name); +#endif + } + key = okey % dict->size; + } + + ret = xmlDictAddString(dict, name, len); + if (ret == NULL) + return(NULL); + if (insert == NULL) { + entry = &(dict->dict[key]); + } else { + entry = xmlMalloc(sizeof(xmlDictEntry)); + if (entry == NULL) + return(NULL); + } + entry->name = ret; + entry->len = len; + entry->next = NULL; + entry->valid = 1; + + + if (insert != NULL) + insert->next = entry; + + dict->nbElems++; + + if ((nbi > MAX_HASH_LEN) && + (dict->size <= ((MAX_DICT_HASH / 2) / MAX_HASH_LEN))) + xmlDictGrow(dict, MAX_HASH_LEN * 2 * dict->size); + /* Note that entry may have been freed at this point by xmlDictGrow */ + + return(ret); +} + +/** + * xmlDictExists: + * @dict: the dictionnary + * @name: the name of the userdata + * @len: the length of the name, if -1 it is recomputed + * + * Check if the @name exists in the dictionnary @dict. + * + * Returns the internal copy of the name or NULL if not found. + */ +const xmlChar * +xmlDictExists(xmlDictPtr dict, const xmlChar *name, int len) { + unsigned long key, okey, nbi = 0; + xmlDictEntryPtr insert; + + if ((dict == NULL) || (name == NULL)) + return(NULL); + + if (len < 0) + len = xmlStrlen(name); + + /* + * Check for duplicate and insertion location. + */ + okey = xmlDictComputeKey(name, len); + key = okey % dict->size; + if (dict->dict[key].valid == 0) { + insert = NULL; + } else { + for (insert = &(dict->dict[key]); insert->next != NULL; + insert = insert->next) { +#ifdef __GNUC__ + if (insert->len == len) { + if (!memcmp(insert->name, name, len)) + return(insert->name); + } +#else + if ((insert->len == len) && + (!xmlStrncmp(insert->name, name, len))) + return(insert->name); +#endif + nbi++; + } +#ifdef __GNUC__ + if (insert->len == len) { + if (!memcmp(insert->name, name, len)) + return(insert->name); + } +#else + if ((insert->len == len) && + (!xmlStrncmp(insert->name, name, len))) + return(insert->name); +#endif + } + + if (dict->subdict) { + key = okey % dict->subdict->size; + if (dict->subdict->dict[key].valid != 0) { + xmlDictEntryPtr tmp; + + for (tmp = &(dict->subdict->dict[key]); tmp->next != NULL; + tmp = tmp->next) { +#ifdef __GNUC__ + if (tmp->len == len) { + if (!memcmp(tmp->name, name, len)) + return(tmp->name); + } +#else + if ((tmp->len == len) && + (!xmlStrncmp(tmp->name, name, len))) + return(tmp->name); +#endif + nbi++; + } +#ifdef __GNUC__ + if (tmp->len == len) { + if (!memcmp(tmp->name, name, len)) + return(tmp->name); + } +#else + if ((tmp->len == len) && + (!xmlStrncmp(tmp->name, name, len))) + return(tmp->name); +#endif + } + key = okey % dict->size; + } + + /* not found */ + return(NULL); +} + +/** + * xmlDictQLookup: + * @dict: the dictionnary + * @prefix: the prefix + * @name: the name + * + * Add the QName @prefix:@name to the hash @dict if not present. + * + * Returns the internal copy of the QName or NULL in case of internal error + */ +const xmlChar * +xmlDictQLookup(xmlDictPtr dict, const xmlChar *prefix, const xmlChar *name) { + unsigned long okey, key, nbi = 0; + xmlDictEntryPtr entry; + xmlDictEntryPtr insert; + const xmlChar *ret; + int len; + + if ((dict == NULL) || (name == NULL)) + return(NULL); + + len = xmlStrlen(name); + if (prefix != NULL) + len += 1 + xmlStrlen(prefix); + + /* + * Check for duplicate and insertion location. + */ + okey = xmlDictComputeQKey(prefix, name, len); + key = okey % dict->size; + if (dict->dict[key].valid == 0) { + insert = NULL; + } else { + for (insert = &(dict->dict[key]); insert->next != NULL; + insert = insert->next) { + if ((insert->len == len) && + (xmlStrQEqual(prefix, name, insert->name))) + return(insert->name); + nbi++; + } + if ((insert->len == len) && + (xmlStrQEqual(prefix, name, insert->name))) + return(insert->name); + } + + if (dict->subdict) { + key = okey % dict->subdict->size; + if (dict->subdict->dict[key].valid != 0) { + xmlDictEntryPtr tmp; + for (tmp = &(dict->subdict->dict[key]); tmp->next != NULL; + tmp = tmp->next) { + if ((tmp->len == len) && + (xmlStrQEqual(prefix, name, tmp->name))) + return(tmp->name); + nbi++; + } + if ((tmp->len == len) && + (xmlStrQEqual(prefix, name, tmp->name))) + return(tmp->name); + } + key = okey % dict->size; + } + + ret = xmlDictAddQString(dict, prefix, name, len); + if (ret == NULL) + return(NULL); + if (insert == NULL) { + entry = &(dict->dict[key]); + } else { + entry = xmlMalloc(sizeof(xmlDictEntry)); + if (entry == NULL) + return(NULL); + } + entry->name = ret; + entry->len = len; + entry->next = NULL; + entry->valid = 1; + + if (insert != NULL) + insert->next = entry; + + dict->nbElems++; + + if ((nbi > MAX_HASH_LEN) && + (dict->size <= ((MAX_DICT_HASH / 2) / MAX_HASH_LEN))) + xmlDictGrow(dict, MAX_HASH_LEN * 2 * dict->size); + /* Note that entry may have been freed at this point by xmlDictGrow */ + + return(ret); +} + +/** + * xmlDictOwns: + * @dict: the dictionnary + * @str: the string + * + * check if a string is owned by the disctionary + * + * Returns 1 if true, 0 if false and -1 in case of error + * -1 in case of error + */ +int +xmlDictOwns(xmlDictPtr dict, const xmlChar *str) { + xmlDictStringsPtr pool; + + if ((dict == NULL) || (str == NULL)) + return(-1); + pool = dict->strings; + while (pool != NULL) { + if ((str >= &pool->array[0]) && (str <= pool->free)) + return(1); + pool = pool->next; + } + if (dict->subdict) + return(xmlDictOwns(dict->subdict, str)); + return(0); +} + +/** + * xmlDictSize: + * @dict: the dictionnary + * + * Query the number of elements installed in the hash @dict. + * + * Returns the number of elements in the dictionnary or + * -1 in case of error + */ +int +xmlDictSize(xmlDictPtr dict) { + if (dict == NULL) + return(-1); + if (dict->subdict) + return(dict->nbElems + dict->subdict->nbElems); + return(dict->nbElems); +} + + +#define bottom_dict +#include "elfgcchack.h" diff --git a/gettext-tools/gnulib-lib/libxml/dict.in.h b/gettext-tools/gnulib-lib/libxml/dict.in.h new file mode 100644 index 0000000..abb8339 --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/dict.in.h @@ -0,0 +1,69 @@ +/* + * Summary: string dictionnary + * Description: dictionary of reusable strings, just used to avoid allocation + * and freeing operations. + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + +#ifndef __XML_DICT_H__ +#define __XML_DICT_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * The dictionnary. + */ +typedef struct _xmlDict xmlDict; +typedef xmlDict *xmlDictPtr; + +/* + * Constructor and destructor. + */ +XMLPUBFUN xmlDictPtr XMLCALL + xmlDictCreate (void); +XMLPUBFUN xmlDictPtr XMLCALL + xmlDictCreateSub(xmlDictPtr sub); +XMLPUBFUN int XMLCALL + xmlDictReference(xmlDictPtr dict); +XMLPUBFUN void XMLCALL + xmlDictFree (xmlDictPtr dict); + +/* + * Lookup of entry in the dictionnary. + */ +XMLPUBFUN const xmlChar * XMLCALL + xmlDictLookup (xmlDictPtr dict, + const xmlChar *name, + int len); +XMLPUBFUN const xmlChar * XMLCALL + xmlDictExists (xmlDictPtr dict, + const xmlChar *name, + int len); +XMLPUBFUN const xmlChar * XMLCALL + xmlDictQLookup (xmlDictPtr dict, + const xmlChar *prefix, + const xmlChar *name); +XMLPUBFUN int XMLCALL + xmlDictOwns (xmlDictPtr dict, + const xmlChar *str); +XMLPUBFUN int XMLCALL + xmlDictSize (xmlDictPtr dict); + +/* + * Cleanup function + */ +XMLPUBFUN void XMLCALL + xmlDictCleanup (void); + +#ifdef __cplusplus +} +#endif +#endif /* ! __XML_DICT_H__ */ diff --git a/gettext-tools/gnulib-lib/libxml/elfgcchack.h b/gettext-tools/gnulib-lib/libxml/elfgcchack.h new file mode 100644 index 0000000..e69de29 diff --git a/gettext-tools/gnulib-lib/libxml/encoding.c b/gettext-tools/gnulib-lib/libxml/encoding.c new file mode 100644 index 0000000..ee33df1 --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/encoding.c @@ -0,0 +1,3295 @@ +/* + * encoding.c : implements the encoding conversion functions needed for XML + * + * Related specs: + * rfc2044 (UTF-8 and UTF-16) F. Yergeau Alis Technologies + * rfc2781 UTF-16, an encoding of ISO 10646, P. Hoffman, F. Yergeau + * [ISO-10646] UTF-8 and UTF-16 in Annexes + * [ISO-8859-1] ISO Latin-1 characters codes. + * [UNICODE] The Unicode Consortium, "The Unicode Standard -- + * Worldwide Character Encoding -- Version 1.0", Addison- + * Wesley, Volume 1, 1991, Volume 2, 1992. UTF-8 is + * described in Unicode Technical Report #4. + * [US-ASCII] Coded Character Set--7-bit American Standard Code for + * Information Interchange, ANSI X3.4-1986. + * + * See Copyright for the status of this software. + * + * daniel@veillard.com + * + * Original code for IsoLatin1 and UTF-16 by "Martin J. Duerst" + */ + +#define IN_LIBXML +#include "libxml.h" + +#include + +#ifdef HAVE_CTYPE_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef LIBXML_ICONV_ENABLED +#ifdef HAVE_ERRNO_H +#include +#endif +#endif +#include +#include +#ifdef LIBXML_HTML_ENABLED +#include +#endif +#include +#include + +static xmlCharEncodingHandlerPtr xmlUTF16LEHandler = NULL; +static xmlCharEncodingHandlerPtr xmlUTF16BEHandler = NULL; + +typedef struct _xmlCharEncodingAlias xmlCharEncodingAlias; +typedef xmlCharEncodingAlias *xmlCharEncodingAliasPtr; +struct _xmlCharEncodingAlias { + const char *name; + const char *alias; +}; + +static xmlCharEncodingAliasPtr xmlCharEncodingAliases = NULL; +static int xmlCharEncodingAliasesNb = 0; +static int xmlCharEncodingAliasesMax = 0; + +#ifdef LIBXML_ICONV_ENABLED +#if 0 +#define DEBUG_ENCODING /* Define this to get encoding traces */ +#endif +#else +#ifdef LIBXML_ISO8859X_ENABLED +static void xmlRegisterCharEncodingHandlersISO8859x (void); +#endif +#endif + +static int xmlLittleEndian = 1; + +/** + * xmlEncodingErrMemory: + * @extra: extra informations + * + * Handle an out of memory condition + */ +static void +xmlEncodingErrMemory(const char *extra) +{ + __xmlSimpleError(XML_FROM_I18N, XML_ERR_NO_MEMORY, NULL, NULL, extra); +} + +/** + * xmlErrEncoding: + * @error: the error number + * @msg: the error message + * + * n encoding error + */ +static void +xmlEncodingErr(xmlParserErrors error, const char *msg, const char *val) +{ + __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, + XML_FROM_I18N, error, XML_ERR_FATAL, + NULL, 0, val, NULL, NULL, 0, 0, msg, val); +} + +/************************************************************************ + * * + * Conversions To/From UTF8 encoding * + * * + ************************************************************************/ + +/** + * asciiToUTF8: + * @out: a pointer to an array of bytes to store the result + * @outlen: the length of @out + * @in: a pointer to an array of ASCII chars + * @inlen: the length of @in + * + * Take a block of ASCII chars in and try to convert it to an UTF-8 + * block of chars out. + * Returns 0 if success, or -1 otherwise + * The value of @inlen after return is the number of octets consumed + * if the return value is positive, else unpredictable. + * The value of @outlen after return is the number of octets consumed. + */ +static int +asciiToUTF8(unsigned char* out, int *outlen, + const unsigned char* in, int *inlen) { + unsigned char* outstart = out; + const unsigned char* base = in; + const unsigned char* processed = in; + unsigned char* outend = out + *outlen; + const unsigned char* inend; + unsigned int c; + + inend = in + (*inlen); + while ((in < inend) && (out - outstart + 5 < *outlen)) { + c= *in++; + + if (out >= outend) + break; + if (c < 0x80) { + *out++ = c; + } else { + *outlen = out - outstart; + *inlen = processed - base; + return(-1); + } + + processed = (const unsigned char*) in; + } + *outlen = out - outstart; + *inlen = processed - base; + return(*outlen); +} + +#ifdef LIBXML_OUTPUT_ENABLED +/** + * UTF8Toascii: + * @out: a pointer to an array of bytes to store the result + * @outlen: the length of @out + * @in: a pointer to an array of UTF-8 chars + * @inlen: the length of @in + * + * Take a block of UTF-8 chars in and try to convert it to an ASCII + * block of chars out. + * + * Returns 0 if success, -2 if the transcoding fails, or -1 otherwise + * The value of @inlen after return is the number of octets consumed + * if the return value is positive, else unpredictable. + * The value of @outlen after return is the number of octets consumed. + */ +static int +UTF8Toascii(unsigned char* out, int *outlen, + const unsigned char* in, int *inlen) { + const unsigned char* processed = in; + const unsigned char* outend; + const unsigned char* outstart = out; + const unsigned char* instart = in; + const unsigned char* inend; + unsigned int c, d; + int trailing; + + if ((out == NULL) || (outlen == NULL) || (inlen == NULL)) return(-1); + if (in == NULL) { + /* + * initialization nothing to do + */ + *outlen = 0; + *inlen = 0; + return(0); + } + inend = in + (*inlen); + outend = out + (*outlen); + while (in < inend) { + d = *in++; + if (d < 0x80) { c= d; trailing= 0; } + else if (d < 0xC0) { + /* trailing byte in leading position */ + *outlen = out - outstart; + *inlen = processed - instart; + return(-2); + } else if (d < 0xE0) { c= d & 0x1F; trailing= 1; } + else if (d < 0xF0) { c= d & 0x0F; trailing= 2; } + else if (d < 0xF8) { c= d & 0x07; trailing= 3; } + else { + /* no chance for this in Ascii */ + *outlen = out - outstart; + *inlen = processed - instart; + return(-2); + } + + if (inend - in < trailing) { + break; + } + + for ( ; trailing; trailing--) { + if ((in >= inend) || (((d= *in++) & 0xC0) != 0x80)) + break; + c <<= 6; + c |= d & 0x3F; + } + + /* assertion: c is a single UTF-4 value */ + if (c < 0x80) { + if (out >= outend) + break; + *out++ = c; + } else { + /* no chance for this in Ascii */ + *outlen = out - outstart; + *inlen = processed - instart; + return(-2); + } + processed = in; + } + *outlen = out - outstart; + *inlen = processed - instart; + return(*outlen); +} +#endif /* LIBXML_OUTPUT_ENABLED */ + +/** + * isolat1ToUTF8: + * @out: a pointer to an array of bytes to store the result + * @outlen: the length of @out + * @in: a pointer to an array of ISO Latin 1 chars + * @inlen: the length of @in + * + * Take a block of ISO Latin 1 chars in and try to convert it to an UTF-8 + * block of chars out. + * Returns the number of bytes written if success, or -1 otherwise + * The value of @inlen after return is the number of octets consumed + * if the return value is positive, else unpredictable. + * The value of @outlen after return is the number of octets consumed. + */ +int +isolat1ToUTF8(unsigned char* out, int *outlen, + const unsigned char* in, int *inlen) { + unsigned char* outstart = out; + const unsigned char* base = in; + unsigned char* outend; + const unsigned char* inend; + const unsigned char* instop; + + if ((out == NULL) || (in == NULL) || (outlen == NULL) || (inlen == NULL)) + return(-1); + + outend = out + *outlen; + inend = in + (*inlen); + instop = inend; + + while (in < inend && out < outend - 1) { + if (*in >= 0x80) { + *out++ = (((*in) >> 6) & 0x1F) | 0xC0; + *out++ = ((*in) & 0x3F) | 0x80; + ++in; + } + if (instop - in > outend - out) instop = in + (outend - out); + while (in < instop && *in < 0x80) { + *out++ = *in++; + } + } + if (in < inend && out < outend && *in < 0x80) { + *out++ = *in++; + } + *outlen = out - outstart; + *inlen = in - base; + return(*outlen); +} + +/** + * UTF8ToUTF8: + * @out: a pointer to an array of bytes to store the result + * @outlen: the length of @out + * @inb: a pointer to an array of UTF-8 chars + * @inlenb: the length of @in in UTF-8 chars + * + * No op copy operation for UTF8 handling. + * + * Returns the number of bytes written, or -1 if lack of space. + * The value of *inlen after return is the number of octets consumed + * if the return value is positive, else unpredictable. + */ +static int +UTF8ToUTF8(unsigned char* out, int *outlen, + const unsigned char* inb, int *inlenb) +{ + int len; + + if ((out == NULL) || (inb == NULL) || (outlen == NULL) || (inlenb == NULL)) + return(-1); + if (*outlen > *inlenb) { + len = *inlenb; + } else { + len = *outlen; + } + if (len < 0) + return(-1); + + memcpy(out, inb, len); + + *outlen = len; + *inlenb = len; + return(*outlen); +} + + +#ifdef LIBXML_OUTPUT_ENABLED +/** + * UTF8Toisolat1: + * @out: a pointer to an array of bytes to store the result + * @outlen: the length of @out + * @in: a pointer to an array of UTF-8 chars + * @inlen: the length of @in + * + * Take a block of UTF-8 chars in and try to convert it to an ISO Latin 1 + * block of chars out. + * + * Returns the number of bytes written if success, -2 if the transcoding fails, + or -1 otherwise + * The value of @inlen after return is the number of octets consumed + * if the return value is positive, else unpredictable. + * The value of @outlen after return is the number of octets consumed. + */ +int +UTF8Toisolat1(unsigned char* out, int *outlen, + const unsigned char* in, int *inlen) { + const unsigned char* processed = in; + const unsigned char* outend; + const unsigned char* outstart = out; + const unsigned char* instart = in; + const unsigned char* inend; + unsigned int c, d; + int trailing; + + if ((out == NULL) || (outlen == NULL) || (inlen == NULL)) return(-1); + if (in == NULL) { + /* + * initialization nothing to do + */ + *outlen = 0; + *inlen = 0; + return(0); + } + inend = in + (*inlen); + outend = out + (*outlen); + while (in < inend) { + d = *in++; + if (d < 0x80) { c= d; trailing= 0; } + else if (d < 0xC0) { + /* trailing byte in leading position */ + *outlen = out - outstart; + *inlen = processed - instart; + return(-2); + } else if (d < 0xE0) { c= d & 0x1F; trailing= 1; } + else if (d < 0xF0) { c= d & 0x0F; trailing= 2; } + else if (d < 0xF8) { c= d & 0x07; trailing= 3; } + else { + /* no chance for this in IsoLat1 */ + *outlen = out - outstart; + *inlen = processed - instart; + return(-2); + } + + if (inend - in < trailing) { + break; + } + + for ( ; trailing; trailing--) { + if (in >= inend) + break; + if (((d= *in++) & 0xC0) != 0x80) { + *outlen = out - outstart; + *inlen = processed - instart; + return(-2); + } + c <<= 6; + c |= d & 0x3F; + } + + /* assertion: c is a single UTF-4 value */ + if (c <= 0xFF) { + if (out >= outend) + break; + *out++ = c; + } else { + /* no chance for this in IsoLat1 */ + *outlen = out - outstart; + *inlen = processed - instart; + return(-2); + } + processed = in; + } + *outlen = out - outstart; + *inlen = processed - instart; + return(*outlen); +} +#endif /* LIBXML_OUTPUT_ENABLED */ + +/** + * UTF16LEToUTF8: + * @out: a pointer to an array of bytes to store the result + * @outlen: the length of @out + * @inb: a pointer to an array of UTF-16LE passwd as a byte array + * @inlenb: the length of @in in UTF-16LE chars + * + * Take a block of UTF-16LE ushorts in and try to convert it to an UTF-8 + * block of chars out. This function assumes the endian property + * is the same between the native type of this machine and the + * inputed one. + * + * Returns the number of bytes written, or -1 if lack of space, or -2 + * if the transcoding fails (if *in is not a valid utf16 string) + * The value of *inlen after return is the number of octets consumed + * if the return value is positive, else unpredictable. + */ +static int +UTF16LEToUTF8(unsigned char* out, int *outlen, + const unsigned char* inb, int *inlenb) +{ + unsigned char* outstart = out; + const unsigned char* processed = inb; + unsigned char* outend = out + *outlen; + unsigned short* in = (unsigned short*) inb; + unsigned short* inend; + unsigned int c, d, inlen; + unsigned char *tmp; + int bits; + + if ((*inlenb % 2) == 1) + (*inlenb)--; + inlen = *inlenb / 2; + inend = in + inlen; + while ((in < inend) && (out - outstart + 5 < *outlen)) { + if (xmlLittleEndian) { + c= *in++; + } else { + tmp = (unsigned char *) in; + c = *tmp++; + c = c | (((unsigned int)*tmp) << 8); + in++; + } + if ((c & 0xFC00) == 0xD800) { /* surrogates */ + if (in >= inend) { /* (in > inend) shouldn't happens */ + break; + } + if (xmlLittleEndian) { + d = *in++; + } else { + tmp = (unsigned char *) in; + d = *tmp++; + d = d | (((unsigned int)*tmp) << 8); + in++; + } + if ((d & 0xFC00) == 0xDC00) { + c &= 0x03FF; + c <<= 10; + c |= d & 0x03FF; + c += 0x10000; + } + else { + *outlen = out - outstart; + *inlenb = processed - inb; + return(-2); + } + } + + /* assertion: c is a single UTF-4 value */ + if (out >= outend) + break; + if (c < 0x80) { *out++= c; bits= -6; } + else if (c < 0x800) { *out++= ((c >> 6) & 0x1F) | 0xC0; bits= 0; } + else if (c < 0x10000) { *out++= ((c >> 12) & 0x0F) | 0xE0; bits= 6; } + else { *out++= ((c >> 18) & 0x07) | 0xF0; bits= 12; } + + for ( ; bits >= 0; bits-= 6) { + if (out >= outend) + break; + *out++= ((c >> bits) & 0x3F) | 0x80; + } + processed = (const unsigned char*) in; + } + *outlen = out - outstart; + *inlenb = processed - inb; + return(*outlen); +} + +#ifdef LIBXML_OUTPUT_ENABLED +/** + * UTF8ToUTF16LE: + * @outb: a pointer to an array of bytes to store the result + * @outlen: the length of @outb + * @in: a pointer to an array of UTF-8 chars + * @inlen: the length of @in + * + * Take a block of UTF-8 chars in and try to convert it to an UTF-16LE + * block of chars out. + * + * Returns the number of bytes written, or -1 if lack of space, or -2 + * if the transcoding failed. + */ +static int +UTF8ToUTF16LE(unsigned char* outb, int *outlen, + const unsigned char* in, int *inlen) +{ + unsigned short* out = (unsigned short*) outb; + const unsigned char* processed = in; + const unsigned char *const instart = in; + unsigned short* outstart= out; + unsigned short* outend; + const unsigned char* inend; + unsigned int c, d; + int trailing; + unsigned char *tmp; + unsigned short tmp1, tmp2; + + /* UTF16LE encoding has no BOM */ + if ((out == NULL) || (outlen == NULL) || (inlen == NULL)) return(-1); + if (in == NULL) { + *outlen = 0; + *inlen = 0; + return(0); + } + inend= in + *inlen; + outend = out + (*outlen / 2); + while (in < inend) { + d= *in++; + if (d < 0x80) { c= d; trailing= 0; } + else if (d < 0xC0) { + /* trailing byte in leading position */ + *outlen = (out - outstart) * 2; + *inlen = processed - instart; + return(-2); + } else if (d < 0xE0) { c= d & 0x1F; trailing= 1; } + else if (d < 0xF0) { c= d & 0x0F; trailing= 2; } + else if (d < 0xF8) { c= d & 0x07; trailing= 3; } + else { + /* no chance for this in UTF-16 */ + *outlen = (out - outstart) * 2; + *inlen = processed - instart; + return(-2); + } + + if (inend - in < trailing) { + break; + } + + for ( ; trailing; trailing--) { + if ((in >= inend) || (((d= *in++) & 0xC0) != 0x80)) + break; + c <<= 6; + c |= d & 0x3F; + } + + /* assertion: c is a single UTF-4 value */ + if (c < 0x10000) { + if (out >= outend) + break; + if (xmlLittleEndian) { + *out++ = c; + } else { + tmp = (unsigned char *) out; + *tmp = c ; + *(tmp + 1) = c >> 8 ; + out++; + } + } + else if (c < 0x110000) { + if (out+1 >= outend) + break; + c -= 0x10000; + if (xmlLittleEndian) { + *out++ = 0xD800 | (c >> 10); + *out++ = 0xDC00 | (c & 0x03FF); + } else { + tmp1 = 0xD800 | (c >> 10); + tmp = (unsigned char *) out; + *tmp = (unsigned char) tmp1; + *(tmp + 1) = tmp1 >> 8; + out++; + + tmp2 = 0xDC00 | (c & 0x03FF); + tmp = (unsigned char *) out; + *tmp = (unsigned char) tmp2; + *(tmp + 1) = tmp2 >> 8; + out++; + } + } + else + break; + processed = in; + } + *outlen = (out - outstart) * 2; + *inlen = processed - instart; + return(*outlen); +} + +/** + * UTF8ToUTF16: + * @outb: a pointer to an array of bytes to store the result + * @outlen: the length of @outb + * @in: a pointer to an array of UTF-8 chars + * @inlen: the length of @in + * + * Take a block of UTF-8 chars in and try to convert it to an UTF-16 + * block of chars out. + * + * Returns the number of bytes written, or -1 if lack of space, or -2 + * if the transcoding failed. + */ +static int +UTF8ToUTF16(unsigned char* outb, int *outlen, + const unsigned char* in, int *inlen) +{ + if (in == NULL) { + /* + * initialization, add the Byte Order Mark for UTF-16LE + */ + if (*outlen >= 2) { + outb[0] = 0xFF; + outb[1] = 0xFE; + *outlen = 2; + *inlen = 0; +#ifdef DEBUG_ENCODING + xmlGenericError(xmlGenericErrorContext, + "Added FFFE Byte Order Mark\n"); +#endif + return(2); + } + *outlen = 0; + *inlen = 0; + return(0); + } + return (UTF8ToUTF16LE(outb, outlen, in, inlen)); +} +#endif /* LIBXML_OUTPUT_ENABLED */ + +/** + * UTF16BEToUTF8: + * @out: a pointer to an array of bytes to store the result + * @outlen: the length of @out + * @inb: a pointer to an array of UTF-16 passed as a byte array + * @inlenb: the length of @in in UTF-16 chars + * + * Take a block of UTF-16 ushorts in and try to convert it to an UTF-8 + * block of chars out. This function assumes the endian property + * is the same between the native type of this machine and the + * inputed one. + * + * Returns the number of bytes written, or -1 if lack of space, or -2 + * if the transcoding fails (if *in is not a valid utf16 string) + * The value of *inlen after return is the number of octets consumed + * if the return value is positive, else unpredictable. + */ +static int +UTF16BEToUTF8(unsigned char* out, int *outlen, + const unsigned char* inb, int *inlenb) +{ + unsigned char* outstart = out; + const unsigned char* processed = inb; + unsigned char* outend = out + *outlen; + unsigned short* in = (unsigned short*) inb; + unsigned short* inend; + unsigned int c, d, inlen; + unsigned char *tmp; + int bits; + + if ((*inlenb % 2) == 1) + (*inlenb)--; + inlen = *inlenb / 2; + inend= in + inlen; + while (in < inend) { + if (xmlLittleEndian) { + tmp = (unsigned char *) in; + c = *tmp++; + c = c << 8; + c = c | (unsigned int) *tmp; + in++; + } else { + c= *in++; + } + if ((c & 0xFC00) == 0xD800) { /* surrogates */ + if (in >= inend) { /* (in > inend) shouldn't happens */ + *outlen = out - outstart; + *inlenb = processed - inb; + return(-2); + } + if (xmlLittleEndian) { + tmp = (unsigned char *) in; + d = *tmp++; + d = d << 8; + d = d | (unsigned int) *tmp; + in++; + } else { + d= *in++; + } + if ((d & 0xFC00) == 0xDC00) { + c &= 0x03FF; + c <<= 10; + c |= d & 0x03FF; + c += 0x10000; + } + else { + *outlen = out - outstart; + *inlenb = processed - inb; + return(-2); + } + } + + /* assertion: c is a single UTF-4 value */ + if (out >= outend) + break; + if (c < 0x80) { *out++= c; bits= -6; } + else if (c < 0x800) { *out++= ((c >> 6) & 0x1F) | 0xC0; bits= 0; } + else if (c < 0x10000) { *out++= ((c >> 12) & 0x0F) | 0xE0; bits= 6; } + else { *out++= ((c >> 18) & 0x07) | 0xF0; bits= 12; } + + for ( ; bits >= 0; bits-= 6) { + if (out >= outend) + break; + *out++= ((c >> bits) & 0x3F) | 0x80; + } + processed = (const unsigned char*) in; + } + *outlen = out - outstart; + *inlenb = processed - inb; + return(*outlen); +} + +#ifdef LIBXML_OUTPUT_ENABLED +/** + * UTF8ToUTF16BE: + * @outb: a pointer to an array of bytes to store the result + * @outlen: the length of @outb + * @in: a pointer to an array of UTF-8 chars + * @inlen: the length of @in + * + * Take a block of UTF-8 chars in and try to convert it to an UTF-16BE + * block of chars out. + * + * Returns the number of byte written, or -1 by lack of space, or -2 + * if the transcoding failed. + */ +static int +UTF8ToUTF16BE(unsigned char* outb, int *outlen, + const unsigned char* in, int *inlen) +{ + unsigned short* out = (unsigned short*) outb; + const unsigned char* processed = in; + const unsigned char *const instart = in; + unsigned short* outstart= out; + unsigned short* outend; + const unsigned char* inend; + unsigned int c, d; + int trailing; + unsigned char *tmp; + unsigned short tmp1, tmp2; + + /* UTF-16BE has no BOM */ + if ((outb == NULL) || (outlen == NULL) || (inlen == NULL)) return(-1); + if (in == NULL) { + *outlen = 0; + *inlen = 0; + return(0); + } + inend= in + *inlen; + outend = out + (*outlen / 2); + while (in < inend) { + d= *in++; + if (d < 0x80) { c= d; trailing= 0; } + else if (d < 0xC0) { + /* trailing byte in leading position */ + *outlen = out - outstart; + *inlen = processed - instart; + return(-2); + } else if (d < 0xE0) { c= d & 0x1F; trailing= 1; } + else if (d < 0xF0) { c= d & 0x0F; trailing= 2; } + else if (d < 0xF8) { c= d & 0x07; trailing= 3; } + else { + /* no chance for this in UTF-16 */ + *outlen = out - outstart; + *inlen = processed - instart; + return(-2); + } + + if (inend - in < trailing) { + break; + } + + for ( ; trailing; trailing--) { + if ((in >= inend) || (((d= *in++) & 0xC0) != 0x80)) break; + c <<= 6; + c |= d & 0x3F; + } + + /* assertion: c is a single UTF-4 value */ + if (c < 0x10000) { + if (out >= outend) break; + if (xmlLittleEndian) { + tmp = (unsigned char *) out; + *tmp = c >> 8; + *(tmp + 1) = c; + out++; + } else { + *out++ = c; + } + } + else if (c < 0x110000) { + if (out+1 >= outend) break; + c -= 0x10000; + if (xmlLittleEndian) { + tmp1 = 0xD800 | (c >> 10); + tmp = (unsigned char *) out; + *tmp = tmp1 >> 8; + *(tmp + 1) = (unsigned char) tmp1; + out++; + + tmp2 = 0xDC00 | (c & 0x03FF); + tmp = (unsigned char *) out; + *tmp = tmp2 >> 8; + *(tmp + 1) = (unsigned char) tmp2; + out++; + } else { + *out++ = 0xD800 | (c >> 10); + *out++ = 0xDC00 | (c & 0x03FF); + } + } + else + break; + processed = in; + } + *outlen = (out - outstart) * 2; + *inlen = processed - instart; + return(*outlen); +} +#endif /* LIBXML_OUTPUT_ENABLED */ + +/************************************************************************ + * * + * Generic encoding handling routines * + * * + ************************************************************************/ + +/** + * xmlDetectCharEncoding: + * @in: a pointer to the first bytes of the XML entity, must be at least + * 2 bytes long (at least 4 if encoding is UTF4 variant). + * @len: pointer to the length of the buffer + * + * Guess the encoding of the entity using the first bytes of the entity content + * according to the non-normative appendix F of the XML-1.0 recommendation. + * + * Returns one of the XML_CHAR_ENCODING_... values. + */ +xmlCharEncoding +xmlDetectCharEncoding(const unsigned char* in, int len) +{ + if (in == NULL) + return(XML_CHAR_ENCODING_NONE); + if (len >= 4) { + if ((in[0] == 0x00) && (in[1] == 0x00) && + (in[2] == 0x00) && (in[3] == 0x3C)) + return(XML_CHAR_ENCODING_UCS4BE); + if ((in[0] == 0x3C) && (in[1] == 0x00) && + (in[2] == 0x00) && (in[3] == 0x00)) + return(XML_CHAR_ENCODING_UCS4LE); + if ((in[0] == 0x00) && (in[1] == 0x00) && + (in[2] == 0x3C) && (in[3] == 0x00)) + return(XML_CHAR_ENCODING_UCS4_2143); + if ((in[0] == 0x00) && (in[1] == 0x3C) && + (in[2] == 0x00) && (in[3] == 0x00)) + return(XML_CHAR_ENCODING_UCS4_3412); + if ((in[0] == 0x4C) && (in[1] == 0x6F) && + (in[2] == 0xA7) && (in[3] == 0x94)) + return(XML_CHAR_ENCODING_EBCDIC); + if ((in[0] == 0x3C) && (in[1] == 0x3F) && + (in[2] == 0x78) && (in[3] == 0x6D)) + return(XML_CHAR_ENCODING_UTF8); + /* + * Although not part of the recommendation, we also + * attempt an "auto-recognition" of UTF-16LE and + * UTF-16BE encodings. + */ + if ((in[0] == 0x3C) && (in[1] == 0x00) && + (in[2] == 0x3F) && (in[3] == 0x00)) + return(XML_CHAR_ENCODING_UTF16LE); + if ((in[0] == 0x00) && (in[1] == 0x3C) && + (in[2] == 0x00) && (in[3] == 0x3F)) + return(XML_CHAR_ENCODING_UTF16BE); + } + if (len >= 3) { + /* + * Errata on XML-1.0 June 20 2001 + * We now allow an UTF8 encoded BOM + */ + if ((in[0] == 0xEF) && (in[1] == 0xBB) && + (in[2] == 0xBF)) + return(XML_CHAR_ENCODING_UTF8); + } + /* For UTF-16 we can recognize by the BOM */ + if (len >= 2) { + if ((in[0] == 0xFE) && (in[1] == 0xFF)) + return(XML_CHAR_ENCODING_UTF16BE); + if ((in[0] == 0xFF) && (in[1] == 0xFE)) + return(XML_CHAR_ENCODING_UTF16LE); + } + return(XML_CHAR_ENCODING_NONE); +} + +/** + * xmlCleanupEncodingAliases: + * + * Unregisters all aliases + */ +void +xmlCleanupEncodingAliases(void) { + int i; + + if (xmlCharEncodingAliases == NULL) + return; + + for (i = 0;i < xmlCharEncodingAliasesNb;i++) { + if (xmlCharEncodingAliases[i].name != NULL) + xmlFree((char *) xmlCharEncodingAliases[i].name); + if (xmlCharEncodingAliases[i].alias != NULL) + xmlFree((char *) xmlCharEncodingAliases[i].alias); + } + xmlCharEncodingAliasesNb = 0; + xmlCharEncodingAliasesMax = 0; + xmlFree(xmlCharEncodingAliases); + xmlCharEncodingAliases = NULL; +} + +/** + * xmlGetEncodingAlias: + * @alias: the alias name as parsed, in UTF-8 format (ASCII actually) + * + * Lookup an encoding name for the given alias. + * + * Returns NULL if not found, otherwise the original name + */ +const char * +xmlGetEncodingAlias(const char *alias) { + int i; + char upper[100]; + + if (alias == NULL) + return(NULL); + + if (xmlCharEncodingAliases == NULL) + return(NULL); + + for (i = 0;i < 99;i++) { + upper[i] = toupper(alias[i]); + if (upper[i] == 0) break; + } + upper[i] = 0; + + /* + * Walk down the list looking for a definition of the alias + */ + for (i = 0;i < xmlCharEncodingAliasesNb;i++) { + if (!strcmp(xmlCharEncodingAliases[i].alias, upper)) { + return(xmlCharEncodingAliases[i].name); + } + } + return(NULL); +} + +/** + * xmlAddEncodingAlias: + * @name: the encoding name as parsed, in UTF-8 format (ASCII actually) + * @alias: the alias name as parsed, in UTF-8 format (ASCII actually) + * + * Registers an alias @alias for an encoding named @name. Existing alias + * will be overwritten. + * + * Returns 0 in case of success, -1 in case of error + */ +int +xmlAddEncodingAlias(const char *name, const char *alias) { + int i; + char upper[100]; + + if ((name == NULL) || (alias == NULL)) + return(-1); + + for (i = 0;i < 99;i++) { + upper[i] = toupper(alias[i]); + if (upper[i] == 0) break; + } + upper[i] = 0; + + if (xmlCharEncodingAliases == NULL) { + xmlCharEncodingAliasesNb = 0; + xmlCharEncodingAliasesMax = 20; + xmlCharEncodingAliases = (xmlCharEncodingAliasPtr) + xmlMalloc(xmlCharEncodingAliasesMax * sizeof(xmlCharEncodingAlias)); + if (xmlCharEncodingAliases == NULL) + return(-1); + } else if (xmlCharEncodingAliasesNb >= xmlCharEncodingAliasesMax) { + xmlCharEncodingAliasesMax *= 2; + xmlCharEncodingAliases = (xmlCharEncodingAliasPtr) + xmlRealloc(xmlCharEncodingAliases, + xmlCharEncodingAliasesMax * sizeof(xmlCharEncodingAlias)); + } + /* + * Walk down the list looking for a definition of the alias + */ + for (i = 0;i < xmlCharEncodingAliasesNb;i++) { + if (!strcmp(xmlCharEncodingAliases[i].alias, upper)) { + /* + * Replace the definition. + */ + xmlFree((char *) xmlCharEncodingAliases[i].name); + xmlCharEncodingAliases[i].name = xmlMemStrdup(name); + return(0); + } + } + /* + * Add the definition + */ + xmlCharEncodingAliases[xmlCharEncodingAliasesNb].name = xmlMemStrdup(name); + xmlCharEncodingAliases[xmlCharEncodingAliasesNb].alias = xmlMemStrdup(upper); + xmlCharEncodingAliasesNb++; + return(0); +} + +/** + * xmlDelEncodingAlias: + * @alias: the alias name as parsed, in UTF-8 format (ASCII actually) + * + * Unregisters an encoding alias @alias + * + * Returns 0 in case of success, -1 in case of error + */ +int +xmlDelEncodingAlias(const char *alias) { + int i; + + if (alias == NULL) + return(-1); + + if (xmlCharEncodingAliases == NULL) + return(-1); + /* + * Walk down the list looking for a definition of the alias + */ + for (i = 0;i < xmlCharEncodingAliasesNb;i++) { + if (!strcmp(xmlCharEncodingAliases[i].alias, alias)) { + xmlFree((char *) xmlCharEncodingAliases[i].name); + xmlFree((char *) xmlCharEncodingAliases[i].alias); + xmlCharEncodingAliasesNb--; + memmove(&xmlCharEncodingAliases[i], &xmlCharEncodingAliases[i + 1], + sizeof(xmlCharEncodingAlias) * (xmlCharEncodingAliasesNb - i)); + return(0); + } + } + return(-1); +} + +/** + * xmlParseCharEncoding: + * @name: the encoding name as parsed, in UTF-8 format (ASCII actually) + * + * Compare the string to the encoding schemes already known. Note + * that the comparison is case insensitive accordingly to the section + * [XML] 4.3.3 Character Encoding in Entities. + * + * Returns one of the XML_CHAR_ENCODING_... values or XML_CHAR_ENCODING_NONE + * if not recognized. + */ +xmlCharEncoding +xmlParseCharEncoding(const char* name) +{ + const char *alias; + char upper[500]; + int i; + + if (name == NULL) + return(XML_CHAR_ENCODING_NONE); + + /* + * Do the alias resolution + */ + alias = xmlGetEncodingAlias(name); + if (alias != NULL) + name = alias; + + for (i = 0;i < 499;i++) { + upper[i] = toupper(name[i]); + if (upper[i] == 0) break; + } + upper[i] = 0; + + if (!strcmp(upper, "")) return(XML_CHAR_ENCODING_NONE); + if (!strcmp(upper, "UTF-8")) return(XML_CHAR_ENCODING_UTF8); + if (!strcmp(upper, "UTF8")) return(XML_CHAR_ENCODING_UTF8); + + /* + * NOTE: if we were able to parse this, the endianness of UTF16 is + * already found and in use + */ + if (!strcmp(upper, "UTF-16")) return(XML_CHAR_ENCODING_UTF16LE); + if (!strcmp(upper, "UTF16")) return(XML_CHAR_ENCODING_UTF16LE); + + if (!strcmp(upper, "ISO-10646-UCS-2")) return(XML_CHAR_ENCODING_UCS2); + if (!strcmp(upper, "UCS-2")) return(XML_CHAR_ENCODING_UCS2); + if (!strcmp(upper, "UCS2")) return(XML_CHAR_ENCODING_UCS2); + + /* + * NOTE: if we were able to parse this, the endianness of UCS4 is + * already found and in use + */ + if (!strcmp(upper, "ISO-10646-UCS-4")) return(XML_CHAR_ENCODING_UCS4LE); + if (!strcmp(upper, "UCS-4")) return(XML_CHAR_ENCODING_UCS4LE); + if (!strcmp(upper, "UCS4")) return(XML_CHAR_ENCODING_UCS4LE); + + + if (!strcmp(upper, "ISO-8859-1")) return(XML_CHAR_ENCODING_8859_1); + if (!strcmp(upper, "ISO-LATIN-1")) return(XML_CHAR_ENCODING_8859_1); + if (!strcmp(upper, "ISO LATIN 1")) return(XML_CHAR_ENCODING_8859_1); + + if (!strcmp(upper, "ISO-8859-2")) return(XML_CHAR_ENCODING_8859_2); + if (!strcmp(upper, "ISO-LATIN-2")) return(XML_CHAR_ENCODING_8859_2); + if (!strcmp(upper, "ISO LATIN 2")) return(XML_CHAR_ENCODING_8859_2); + + if (!strcmp(upper, "ISO-8859-3")) return(XML_CHAR_ENCODING_8859_3); + if (!strcmp(upper, "ISO-8859-4")) return(XML_CHAR_ENCODING_8859_4); + if (!strcmp(upper, "ISO-8859-5")) return(XML_CHAR_ENCODING_8859_5); + if (!strcmp(upper, "ISO-8859-6")) return(XML_CHAR_ENCODING_8859_6); + if (!strcmp(upper, "ISO-8859-7")) return(XML_CHAR_ENCODING_8859_7); + if (!strcmp(upper, "ISO-8859-8")) return(XML_CHAR_ENCODING_8859_8); + if (!strcmp(upper, "ISO-8859-9")) return(XML_CHAR_ENCODING_8859_9); + + if (!strcmp(upper, "ISO-2022-JP")) return(XML_CHAR_ENCODING_2022_JP); + if (!strcmp(upper, "SHIFT_JIS")) return(XML_CHAR_ENCODING_SHIFT_JIS); + if (!strcmp(upper, "EUC-JP")) return(XML_CHAR_ENCODING_EUC_JP); + +#ifdef DEBUG_ENCODING + xmlGenericError(xmlGenericErrorContext, "Unknown encoding %s\n", name); +#endif + return(XML_CHAR_ENCODING_ERROR); +} + +/** + * xmlGetCharEncodingName: + * @enc: the encoding + * + * The "canonical" name for XML encoding. + * C.f. http://www.w3.org/TR/REC-xml#charencoding + * Section 4.3.3 Character Encoding in Entities + * + * Returns the canonical name for the given encoding + */ + +const char* +xmlGetCharEncodingName(xmlCharEncoding enc) { + switch (enc) { + case XML_CHAR_ENCODING_ERROR: + return(NULL); + case XML_CHAR_ENCODING_NONE: + return(NULL); + case XML_CHAR_ENCODING_UTF8: + return("UTF-8"); + case XML_CHAR_ENCODING_UTF16LE: + return("UTF-16"); + case XML_CHAR_ENCODING_UTF16BE: + return("UTF-16"); + case XML_CHAR_ENCODING_EBCDIC: + return("EBCDIC"); + case XML_CHAR_ENCODING_UCS4LE: + return("ISO-10646-UCS-4"); + case XML_CHAR_ENCODING_UCS4BE: + return("ISO-10646-UCS-4"); + case XML_CHAR_ENCODING_UCS4_2143: + return("ISO-10646-UCS-4"); + case XML_CHAR_ENCODING_UCS4_3412: + return("ISO-10646-UCS-4"); + case XML_CHAR_ENCODING_UCS2: + return("ISO-10646-UCS-2"); + case XML_CHAR_ENCODING_8859_1: + return("ISO-8859-1"); + case XML_CHAR_ENCODING_8859_2: + return("ISO-8859-2"); + case XML_CHAR_ENCODING_8859_3: + return("ISO-8859-3"); + case XML_CHAR_ENCODING_8859_4: + return("ISO-8859-4"); + case XML_CHAR_ENCODING_8859_5: + return("ISO-8859-5"); + case XML_CHAR_ENCODING_8859_6: + return("ISO-8859-6"); + case XML_CHAR_ENCODING_8859_7: + return("ISO-8859-7"); + case XML_CHAR_ENCODING_8859_8: + return("ISO-8859-8"); + case XML_CHAR_ENCODING_8859_9: + return("ISO-8859-9"); + case XML_CHAR_ENCODING_2022_JP: + return("ISO-2022-JP"); + case XML_CHAR_ENCODING_SHIFT_JIS: + return("Shift-JIS"); + case XML_CHAR_ENCODING_EUC_JP: + return("EUC-JP"); + case XML_CHAR_ENCODING_ASCII: + return(NULL); + } + return(NULL); +} + +/************************************************************************ + * * + * Char encoding handlers * + * * + ************************************************************************/ + + +/* the size should be growable, but it's not a big deal ... */ +#define MAX_ENCODING_HANDLERS 50 +static xmlCharEncodingHandlerPtr *handlers = NULL; +static int nbCharEncodingHandler = 0; + +/* + * The default is UTF-8 for XML, that's also the default used for the + * parser internals, so the default encoding handler is NULL + */ + +static xmlCharEncodingHandlerPtr xmlDefaultCharEncodingHandler = NULL; + +/** + * xmlNewCharEncodingHandler: + * @name: the encoding name, in UTF-8 format (ASCII actually) + * @input: the xmlCharEncodingInputFunc to read that encoding + * @output: the xmlCharEncodingOutputFunc to write that encoding + * + * Create and registers an xmlCharEncodingHandler. + * + * Returns the xmlCharEncodingHandlerPtr created (or NULL in case of error). + */ +xmlCharEncodingHandlerPtr +xmlNewCharEncodingHandler(const char *name, + xmlCharEncodingInputFunc input, + xmlCharEncodingOutputFunc output) { + xmlCharEncodingHandlerPtr handler; + const char *alias; + char upper[500]; + int i; + char *up = NULL; + + /* + * Do the alias resolution + */ + alias = xmlGetEncodingAlias(name); + if (alias != NULL) + name = alias; + + /* + * Keep only the uppercase version of the encoding. + */ + if (name == NULL) { + xmlEncodingErr(XML_I18N_NO_NAME, + "xmlNewCharEncodingHandler : no name !\n", NULL); + return(NULL); + } + for (i = 0;i < 499;i++) { + upper[i] = toupper(name[i]); + if (upper[i] == 0) break; + } + upper[i] = 0; + up = xmlMemStrdup(upper); + if (up == NULL) { + xmlEncodingErrMemory("xmlNewCharEncodingHandler : out of memory !\n"); + return(NULL); + } + + /* + * allocate and fill-up an handler block. + */ + handler = (xmlCharEncodingHandlerPtr) + xmlMalloc(sizeof(xmlCharEncodingHandler)); + if (handler == NULL) { + xmlFree(up); + xmlEncodingErrMemory("xmlNewCharEncodingHandler : out of memory !\n"); + return(NULL); + } + handler->input = input; + handler->output = output; + handler->name = up; + +#ifdef LIBXML_ICONV_ENABLED + handler->iconv_in = NULL; + handler->iconv_out = NULL; +#endif /* LIBXML_ICONV_ENABLED */ + + /* + * registers and returns the handler. + */ + xmlRegisterCharEncodingHandler(handler); +#ifdef DEBUG_ENCODING + xmlGenericError(xmlGenericErrorContext, + "Registered encoding handler for %s\n", name); +#endif + return(handler); +} + +/** + * xmlInitCharEncodingHandlers: + * + * Initialize the char encoding support, it registers the default + * encoding supported. + * NOTE: while public, this function usually doesn't need to be called + * in normal processing. + */ +void +xmlInitCharEncodingHandlers(void) { + unsigned short int tst = 0x1234; + unsigned char *ptr = (unsigned char *) &tst; + + if (handlers != NULL) return; + + handlers = (xmlCharEncodingHandlerPtr *) + xmlMalloc(MAX_ENCODING_HANDLERS * sizeof(xmlCharEncodingHandlerPtr)); + + if (*ptr == 0x12) xmlLittleEndian = 0; + else if (*ptr == 0x34) xmlLittleEndian = 1; + else { + xmlEncodingErr(XML_ERR_INTERNAL_ERROR, + "Odd problem at endianness detection\n", NULL); + } + + if (handlers == NULL) { + xmlEncodingErrMemory("xmlInitCharEncodingHandlers : out of memory !\n"); + return; + } + xmlNewCharEncodingHandler("UTF-8", UTF8ToUTF8, UTF8ToUTF8); +#ifdef LIBXML_OUTPUT_ENABLED + xmlUTF16LEHandler = + xmlNewCharEncodingHandler("UTF-16LE", UTF16LEToUTF8, UTF8ToUTF16LE); + xmlUTF16BEHandler = + xmlNewCharEncodingHandler("UTF-16BE", UTF16BEToUTF8, UTF8ToUTF16BE); + xmlNewCharEncodingHandler("UTF-16", UTF16LEToUTF8, UTF8ToUTF16); + xmlNewCharEncodingHandler("ISO-8859-1", isolat1ToUTF8, UTF8Toisolat1); + xmlNewCharEncodingHandler("ASCII", asciiToUTF8, UTF8Toascii); + xmlNewCharEncodingHandler("US-ASCII", asciiToUTF8, UTF8Toascii); +#ifdef LIBXML_HTML_ENABLED + xmlNewCharEncodingHandler("HTML", NULL, UTF8ToHtml); +#endif +#else + xmlUTF16LEHandler = + xmlNewCharEncodingHandler("UTF-16LE", UTF16LEToUTF8, NULL); + xmlUTF16BEHandler = + xmlNewCharEncodingHandler("UTF-16BE", UTF16BEToUTF8, NULL); + xmlNewCharEncodingHandler("UTF-16", UTF16LEToUTF8, NULL); + xmlNewCharEncodingHandler("ISO-8859-1", isolat1ToUTF8, NULL); + xmlNewCharEncodingHandler("ASCII", asciiToUTF8, NULL); + xmlNewCharEncodingHandler("US-ASCII", asciiToUTF8, NULL); +#endif /* LIBXML_OUTPUT_ENABLED */ +#ifndef LIBXML_ICONV_ENABLED +#ifdef LIBXML_ISO8859X_ENABLED + xmlRegisterCharEncodingHandlersISO8859x (); +#endif +#endif + +} + +/** + * xmlCleanupCharEncodingHandlers: + * + * Cleanup the memory allocated for the char encoding support, it + * unregisters all the encoding handlers and the aliases. + */ +void +xmlCleanupCharEncodingHandlers(void) { + xmlCleanupEncodingAliases(); + + if (handlers == NULL) return; + + for (;nbCharEncodingHandler > 0;) { + nbCharEncodingHandler--; + if (handlers[nbCharEncodingHandler] != NULL) { + if (handlers[nbCharEncodingHandler]->name != NULL) + xmlFree(handlers[nbCharEncodingHandler]->name); + xmlFree(handlers[nbCharEncodingHandler]); + } + } + xmlFree(handlers); + handlers = NULL; + nbCharEncodingHandler = 0; + xmlDefaultCharEncodingHandler = NULL; +} + +/** + * xmlRegisterCharEncodingHandler: + * @handler: the xmlCharEncodingHandlerPtr handler block + * + * Register the char encoding handler, surprising, isn't it ? + */ +void +xmlRegisterCharEncodingHandler(xmlCharEncodingHandlerPtr handler) { + if (handlers == NULL) xmlInitCharEncodingHandlers(); + if (handler == NULL) { + xmlEncodingErr(XML_I18N_NO_HANDLER, + "xmlRegisterCharEncodingHandler: NULL handler !\n", NULL); + return; + } + + if (nbCharEncodingHandler >= MAX_ENCODING_HANDLERS) { + xmlEncodingErr(XML_I18N_EXCESS_HANDLER, + "xmlRegisterCharEncodingHandler: Too many handler registered, see %s\n", + "MAX_ENCODING_HANDLERS"); + return; + } + handlers[nbCharEncodingHandler++] = handler; +} + +/** + * xmlGetCharEncodingHandler: + * @enc: an xmlCharEncoding value. + * + * Search in the registered set the handler able to read/write that encoding. + * + * Returns the handler or NULL if not found + */ +xmlCharEncodingHandlerPtr +xmlGetCharEncodingHandler(xmlCharEncoding enc) { + xmlCharEncodingHandlerPtr handler; + + if (handlers == NULL) xmlInitCharEncodingHandlers(); + switch (enc) { + case XML_CHAR_ENCODING_ERROR: + return(NULL); + case XML_CHAR_ENCODING_NONE: + return(NULL); + case XML_CHAR_ENCODING_UTF8: + return(NULL); + case XML_CHAR_ENCODING_UTF16LE: + return(xmlUTF16LEHandler); + case XML_CHAR_ENCODING_UTF16BE: + return(xmlUTF16BEHandler); + case XML_CHAR_ENCODING_EBCDIC: + handler = xmlFindCharEncodingHandler("EBCDIC"); + if (handler != NULL) return(handler); + handler = xmlFindCharEncodingHandler("ebcdic"); + if (handler != NULL) return(handler); + break; + case XML_CHAR_ENCODING_UCS4BE: + handler = xmlFindCharEncodingHandler("ISO-10646-UCS-4"); + if (handler != NULL) return(handler); + handler = xmlFindCharEncodingHandler("UCS-4"); + if (handler != NULL) return(handler); + handler = xmlFindCharEncodingHandler("UCS4"); + if (handler != NULL) return(handler); + break; + case XML_CHAR_ENCODING_UCS4LE: + handler = xmlFindCharEncodingHandler("ISO-10646-UCS-4"); + if (handler != NULL) return(handler); + handler = xmlFindCharEncodingHandler("UCS-4"); + if (handler != NULL) return(handler); + handler = xmlFindCharEncodingHandler("UCS4"); + if (handler != NULL) return(handler); + break; + case XML_CHAR_ENCODING_UCS4_2143: + break; + case XML_CHAR_ENCODING_UCS4_3412: + break; + case XML_CHAR_ENCODING_UCS2: + handler = xmlFindCharEncodingHandler("ISO-10646-UCS-2"); + if (handler != NULL) return(handler); + handler = xmlFindCharEncodingHandler("UCS-2"); + if (handler != NULL) return(handler); + handler = xmlFindCharEncodingHandler("UCS2"); + if (handler != NULL) return(handler); + break; + + /* + * We used to keep ISO Latin encodings native in the + * generated data. This led to so many problems that + * this has been removed. One can still change this + * back by registering no-ops encoders for those + */ + case XML_CHAR_ENCODING_8859_1: + handler = xmlFindCharEncodingHandler("ISO-8859-1"); + if (handler != NULL) return(handler); + break; + case XML_CHAR_ENCODING_8859_2: + handler = xmlFindCharEncodingHandler("ISO-8859-2"); + if (handler != NULL) return(handler); + break; + case XML_CHAR_ENCODING_8859_3: + handler = xmlFindCharEncodingHandler("ISO-8859-3"); + if (handler != NULL) return(handler); + break; + case XML_CHAR_ENCODING_8859_4: + handler = xmlFindCharEncodingHandler("ISO-8859-4"); + if (handler != NULL) return(handler); + break; + case XML_CHAR_ENCODING_8859_5: + handler = xmlFindCharEncodingHandler("ISO-8859-5"); + if (handler != NULL) return(handler); + break; + case XML_CHAR_ENCODING_8859_6: + handler = xmlFindCharEncodingHandler("ISO-8859-6"); + if (handler != NULL) return(handler); + break; + case XML_CHAR_ENCODING_8859_7: + handler = xmlFindCharEncodingHandler("ISO-8859-7"); + if (handler != NULL) return(handler); + break; + case XML_CHAR_ENCODING_8859_8: + handler = xmlFindCharEncodingHandler("ISO-8859-8"); + if (handler != NULL) return(handler); + break; + case XML_CHAR_ENCODING_8859_9: + handler = xmlFindCharEncodingHandler("ISO-8859-9"); + if (handler != NULL) return(handler); + break; + + + case XML_CHAR_ENCODING_2022_JP: + handler = xmlFindCharEncodingHandler("ISO-2022-JP"); + if (handler != NULL) return(handler); + break; + case XML_CHAR_ENCODING_SHIFT_JIS: + handler = xmlFindCharEncodingHandler("SHIFT-JIS"); + if (handler != NULL) return(handler); + handler = xmlFindCharEncodingHandler("SHIFT_JIS"); + if (handler != NULL) return(handler); + handler = xmlFindCharEncodingHandler("Shift_JIS"); + if (handler != NULL) return(handler); + break; + case XML_CHAR_ENCODING_EUC_JP: + handler = xmlFindCharEncodingHandler("EUC-JP"); + if (handler != NULL) return(handler); + break; + default: + break; + } + +#ifdef DEBUG_ENCODING + xmlGenericError(xmlGenericErrorContext, + "No handler found for encoding %d\n", enc); +#endif + return(NULL); +} + +/** + * xmlFindCharEncodingHandler: + * @name: a string describing the char encoding. + * + * Search in the registered set the handler able to read/write that encoding. + * + * Returns the handler or NULL if not found + */ +xmlCharEncodingHandlerPtr +xmlFindCharEncodingHandler(const char *name) { + const char *nalias; + const char *norig; + xmlCharEncoding alias; +#ifdef LIBXML_ICONV_ENABLED + xmlCharEncodingHandlerPtr enc; + iconv_t icv_in, icv_out; +#endif /* LIBXML_ICONV_ENABLED */ + char upper[100]; + int i; + + if (handlers == NULL) xmlInitCharEncodingHandlers(); + if (name == NULL) return(xmlDefaultCharEncodingHandler); + if (name[0] == 0) return(xmlDefaultCharEncodingHandler); + + /* + * Do the alias resolution + */ + norig = name; + nalias = xmlGetEncodingAlias(name); + if (nalias != NULL) + name = nalias; + + /* + * Check first for directly registered encoding names + */ + for (i = 0;i < 99;i++) { + upper[i] = toupper(name[i]); + if (upper[i] == 0) break; + } + upper[i] = 0; + + for (i = 0;i < nbCharEncodingHandler; i++) + if (!strcmp(upper, handlers[i]->name)) { +#ifdef DEBUG_ENCODING + xmlGenericError(xmlGenericErrorContext, + "Found registered handler for encoding %s\n", name); +#endif + return(handlers[i]); + } + +#ifdef LIBXML_ICONV_ENABLED + /* check whether iconv can handle this */ + icv_in = iconv_open("UTF-8", name); + icv_out = iconv_open(name, "UTF-8"); + if (icv_in == (iconv_t) -1) { + icv_in = iconv_open("UTF-8", upper); + } + if (icv_out == (iconv_t) -1) { + icv_out = iconv_open(upper, "UTF-8"); + } + if ((icv_in != (iconv_t) -1) && (icv_out != (iconv_t) -1)) { + enc = (xmlCharEncodingHandlerPtr) + xmlMalloc(sizeof(xmlCharEncodingHandler)); + if (enc == NULL) { + iconv_close(icv_in); + iconv_close(icv_out); + return(NULL); + } + enc->name = xmlMemStrdup(name); + enc->input = NULL; + enc->output = NULL; + enc->iconv_in = icv_in; + enc->iconv_out = icv_out; +#ifdef DEBUG_ENCODING + xmlGenericError(xmlGenericErrorContext, + "Found iconv handler for encoding %s\n", name); +#endif + return enc; + } else if ((icv_in != (iconv_t) -1) || icv_out != (iconv_t) -1) { + xmlEncodingErr(XML_ERR_INTERNAL_ERROR, + "iconv : problems with filters for '%s'\n", name); + } +#endif /* LIBXML_ICONV_ENABLED */ + +#ifdef DEBUG_ENCODING + xmlGenericError(xmlGenericErrorContext, + "No handler found for encoding %s\n", name); +#endif + + /* + * Fallback using the canonical names + */ + alias = xmlParseCharEncoding(norig); + if (alias != XML_CHAR_ENCODING_ERROR) { + const char* canon; + canon = xmlGetCharEncodingName(alias); + if ((canon != NULL) && (strcmp(name, canon))) { + return(xmlFindCharEncodingHandler(canon)); + } + } + + /* If "none of the above", give up */ + return(NULL); +} + +/************************************************************************ + * * + * ICONV based generic conversion functions * + * * + ************************************************************************/ + +#ifdef LIBXML_ICONV_ENABLED +/** + * xmlIconvWrapper: + * @cd: iconv converter data structure + * @out: a pointer to an array of bytes to store the result + * @outlen: the length of @out + * @in: a pointer to an array of ISO Latin 1 chars + * @inlen: the length of @in + * + * Returns 0 if success, or + * -1 by lack of space, or + * -2 if the transcoding fails (for *in is not valid utf8 string or + * the result of transformation can't fit into the encoding we want), or + * -3 if there the last byte can't form a single output char. + * + * The value of @inlen after return is the number of octets consumed + * as the return value is positive, else unpredictable. + * The value of @outlen after return is the number of ocetes consumed. + */ +static int +xmlIconvWrapper(iconv_t cd, unsigned char *out, int *outlen, + const unsigned char *in, int *inlen) { + size_t icv_inlen, icv_outlen; + const char *icv_in = (const char *) in; + char *icv_out = (char *) out; + int ret; + + if ((out == NULL) || (outlen == NULL) || (inlen == NULL) || (in == NULL)) { + if (outlen != NULL) *outlen = 0; + return(-1); + } + icv_inlen = *inlen; + icv_outlen = *outlen; + ret = iconv(cd, (char **) &icv_in, &icv_inlen, &icv_out, &icv_outlen); + *inlen -= icv_inlen; + *outlen -= icv_outlen; + if ((icv_inlen != 0) || (ret == -1)) { +#ifdef EILSEQ + if (errno == EILSEQ) { + return -2; + } else +#endif +#ifdef E2BIG + if (errno == E2BIG) { + return -1; + } else +#endif +#ifdef EINVAL + if (errno == EINVAL) { + return -3; + } else +#endif + { + return -3; + } + } + return 0; +} +#endif /* LIBXML_ICONV_ENABLED */ + +/************************************************************************ + * * + * The real API used by libxml for on-the-fly conversion * + * * + ************************************************************************/ + +/** + * xmlCharEncFirstLine: + * @handler: char enconding transformation data structure + * @out: an xmlBuffer for the output. + * @in: an xmlBuffer for the input + * + * Front-end for the encoding handler input function, but handle only + * the very first line, i.e. limit itself to 45 chars. + * + * Returns the number of byte written if success, or + * -1 general error + * -2 if the transcoding fails (for *in is not valid utf8 string or + * the result of transformation can't fit into the encoding we want), or + */ +int +xmlCharEncFirstLine(xmlCharEncodingHandler *handler, xmlBufferPtr out, + xmlBufferPtr in) { + int ret = -2; + int written; + int toconv; + + if (handler == NULL) return(-1); + if (out == NULL) return(-1); + if (in == NULL) return(-1); + + written = out->size - out->use; + toconv = in->use; + if (toconv * 2 >= written) { + xmlBufferGrow(out, toconv); + written = out->size - out->use - 1; + } + + /* + * echo '' | wc -c => 38 + * 45 chars should be sufficient to reach the end of the encoding + * declaration without going too far inside the document content. + */ + written = 45; + + if (handler->input != NULL) { + ret = handler->input(&out->content[out->use], &written, + in->content, &toconv); + xmlBufferShrink(in, toconv); + out->use += written; + out->content[out->use] = 0; + } +#ifdef LIBXML_ICONV_ENABLED + else if (handler->iconv_in != NULL) { + ret = xmlIconvWrapper(handler->iconv_in, &out->content[out->use], + &written, in->content, &toconv); + xmlBufferShrink(in, toconv); + out->use += written; + out->content[out->use] = 0; + if (ret == -1) ret = -3; + } +#endif /* LIBXML_ICONV_ENABLED */ +#ifdef DEBUG_ENCODING + switch (ret) { + case 0: + xmlGenericError(xmlGenericErrorContext, + "converted %d bytes to %d bytes of input\n", + toconv, written); + break; + case -1: + xmlGenericError(xmlGenericErrorContext,"converted %d bytes to %d bytes of input, %d left\n", + toconv, written, in->use); + break; + case -2: + xmlGenericError(xmlGenericErrorContext, + "input conversion failed due to input error\n"); + break; + case -3: + xmlGenericError(xmlGenericErrorContext,"converted %d bytes to %d bytes of input, %d left\n", + toconv, written, in->use); + break; + default: + xmlGenericError(xmlGenericErrorContext,"Unknown input conversion failed %d\n", ret); + } +#endif /* DEBUG_ENCODING */ + /* + * Ignore when input buffer is not on a boundary + */ + if (ret == -3) ret = 0; + if (ret == -1) ret = 0; + return(ret); +} + +/** + * xmlCharEncInFunc: + * @handler: char encoding transformation data structure + * @out: an xmlBuffer for the output. + * @in: an xmlBuffer for the input + * + * Generic front-end for the encoding handler input function + * + * Returns the number of byte written if success, or + * -1 general error + * -2 if the transcoding fails (for *in is not valid utf8 string or + * the result of transformation can't fit into the encoding we want), or + */ +int +xmlCharEncInFunc(xmlCharEncodingHandler * handler, xmlBufferPtr out, + xmlBufferPtr in) +{ + int ret = -2; + int written; + int toconv; + + if (handler == NULL) + return (-1); + if (out == NULL) + return (-1); + if (in == NULL) + return (-1); + + toconv = in->use; + if (toconv == 0) + return (0); + written = out->size - out->use; + if (toconv * 2 >= written) { + xmlBufferGrow(out, out->size + toconv * 2); + written = out->size - out->use - 1; + } + if (handler->input != NULL) { + ret = handler->input(&out->content[out->use], &written, + in->content, &toconv); + xmlBufferShrink(in, toconv); + out->use += written; + out->content[out->use] = 0; + } +#ifdef LIBXML_ICONV_ENABLED + else if (handler->iconv_in != NULL) { + ret = xmlIconvWrapper(handler->iconv_in, &out->content[out->use], + &written, in->content, &toconv); + xmlBufferShrink(in, toconv); + out->use += written; + out->content[out->use] = 0; + if (ret == -1) + ret = -3; + } +#endif /* LIBXML_ICONV_ENABLED */ + switch (ret) { + case 0: +#ifdef DEBUG_ENCODING + xmlGenericError(xmlGenericErrorContext, + "converted %d bytes to %d bytes of input\n", + toconv, written); +#endif + break; + case -1: +#ifdef DEBUG_ENCODING + xmlGenericError(xmlGenericErrorContext, + "converted %d bytes to %d bytes of input, %d left\n", + toconv, written, in->use); +#endif + break; + case -3: +#ifdef DEBUG_ENCODING + xmlGenericError(xmlGenericErrorContext, + "converted %d bytes to %d bytes of input, %d left\n", + toconv, written, in->use); +#endif + break; + case -2: { + char buf[50]; + + snprintf(&buf[0], 49, "0x%02X 0x%02X 0x%02X 0x%02X", + in->content[0], in->content[1], + in->content[2], in->content[3]); + buf[49] = 0; + xmlEncodingErr(XML_I18N_CONV_FAILED, + "input conversion failed due to input error, bytes %s\n", + buf); + } + } + /* + * Ignore when input buffer is not on a boundary + */ + if (ret == -3) + ret = 0; + return (written? written : ret); +} + +/** + * xmlCharEncOutFunc: + * @handler: char enconding transformation data structure + * @out: an xmlBuffer for the output. + * @in: an xmlBuffer for the input + * + * Generic front-end for the encoding handler output function + * a first call with @in == NULL has to be made firs to initiate the + * output in case of non-stateless encoding needing to initiate their + * state or the output (like the BOM in UTF16). + * In case of UTF8 sequence conversion errors for the given encoder, + * the content will be automatically remapped to a CharRef sequence. + * + * Returns the number of byte written if success, or + * -1 general error + * -2 if the transcoding fails (for *in is not valid utf8 string or + * the result of transformation can't fit into the encoding we want), or + */ +int +xmlCharEncOutFunc(xmlCharEncodingHandler *handler, xmlBufferPtr out, + xmlBufferPtr in) { + int ret = -2; + int written; + int writtentot = 0; + int toconv; + int output = 0; + + if (handler == NULL) return(-1); + if (out == NULL) return(-1); + +retry: + + written = out->size - out->use; + + if (written > 0) + written--; /* Gennady: count '/0' */ + + /* + * First specific handling of in = NULL, i.e. the initialization call + */ + if (in == NULL) { + toconv = 0; + if (handler->output != NULL) { + ret = handler->output(&out->content[out->use], &written, + NULL, &toconv); + if (ret >= 0) { /* Gennady: check return value */ + out->use += written; + out->content[out->use] = 0; + } + } +#ifdef LIBXML_ICONV_ENABLED + else if (handler->iconv_out != NULL) { + ret = xmlIconvWrapper(handler->iconv_out, &out->content[out->use], + &written, NULL, &toconv); + out->use += written; + out->content[out->use] = 0; + } +#endif /* LIBXML_ICONV_ENABLED */ +#ifdef DEBUG_ENCODING + xmlGenericError(xmlGenericErrorContext, + "initialized encoder\n"); +#endif + return(0); + } + + /* + * Conversion itself. + */ + toconv = in->use; + if (toconv == 0) + return(0); + if (toconv * 2 >= written) { + xmlBufferGrow(out, toconv * 2); + written = out->size - out->use - 1; + } + if (handler->output != NULL) { + ret = handler->output(&out->content[out->use], &written, + in->content, &toconv); + xmlBufferShrink(in, toconv); + out->use += written; + writtentot += written; + out->content[out->use] = 0; + } +#ifdef LIBXML_ICONV_ENABLED + else if (handler->iconv_out != NULL) { + ret = xmlIconvWrapper(handler->iconv_out, &out->content[out->use], + &written, in->content, &toconv); + xmlBufferShrink(in, toconv); + out->use += written; + writtentot += written; + out->content[out->use] = 0; + if (ret == -1) { + if (written > 0) { + /* + * Can be a limitation of iconv + */ + goto retry; + } + ret = -3; + } + } +#endif /* LIBXML_ICONV_ENABLED */ + else { + xmlEncodingErr(XML_I18N_NO_OUTPUT, + "xmlCharEncOutFunc: no output function !\n", NULL); + return(-1); + } + + if (ret >= 0) output += ret; + + /* + * Attempt to handle error cases + */ + switch (ret) { + case 0: +#ifdef DEBUG_ENCODING + xmlGenericError(xmlGenericErrorContext, + "converted %d bytes to %d bytes of output\n", + toconv, written); +#endif + break; + case -1: +#ifdef DEBUG_ENCODING + xmlGenericError(xmlGenericErrorContext, + "output conversion failed by lack of space\n"); +#endif + break; + case -3: +#ifdef DEBUG_ENCODING + xmlGenericError(xmlGenericErrorContext,"converted %d bytes to %d bytes of output %d left\n", + toconv, written, in->use); +#endif + break; + case -2: { + int len = in->use; + const xmlChar *utf = (const xmlChar *) in->content; + int cur; + + cur = xmlGetUTF8Char(utf, &len); + if (cur > 0) { + xmlChar charref[20]; + +#ifdef DEBUG_ENCODING + xmlGenericError(xmlGenericErrorContext, + "handling output conversion error\n"); + xmlGenericError(xmlGenericErrorContext, + "Bytes: 0x%02X 0x%02X 0x%02X 0x%02X\n", + in->content[0], in->content[1], + in->content[2], in->content[3]); +#endif + /* + * Removes the UTF8 sequence, and replace it by a charref + * and continue the transcoding phase, hoping the error + * did not mangle the encoder state. + */ + snprintf((char *) &charref[0], sizeof(charref), "&#%d;", cur); + xmlBufferShrink(in, len); + xmlBufferAddHead(in, charref, -1); + + goto retry; + } else { + char buf[50]; + + snprintf(&buf[0], 49, "0x%02X 0x%02X 0x%02X 0x%02X", + in->content[0], in->content[1], + in->content[2], in->content[3]); + buf[49] = 0; + xmlEncodingErr(XML_I18N_CONV_FAILED, + "output conversion failed due to conv error, bytes %s\n", + buf); + if (in->alloc != XML_BUFFER_ALLOC_IMMUTABLE) + in->content[0] = ' '; + } + break; + } + } + return(ret); +} + +/** + * xmlCharEncCloseFunc: + * @handler: char enconding transformation data structure + * + * Generic front-end for encoding handler close function + * + * Returns 0 if success, or -1 in case of error + */ +int +xmlCharEncCloseFunc(xmlCharEncodingHandler *handler) { + int ret = 0; + if (handler == NULL) return(-1); + if (handler->name == NULL) return(-1); +#ifdef LIBXML_ICONV_ENABLED + /* + * Iconv handlers can be used only once, free the whole block. + * and the associated icon resources. + */ + if ((handler->iconv_out != NULL) || (handler->iconv_in != NULL)) { + if (handler->name != NULL) + xmlFree(handler->name); + handler->name = NULL; + if (handler->iconv_out != NULL) { + if (iconv_close(handler->iconv_out)) + ret = -1; + handler->iconv_out = NULL; + } + if (handler->iconv_in != NULL) { + if (iconv_close(handler->iconv_in)) + ret = -1; + handler->iconv_in = NULL; + } + xmlFree(handler); + } +#endif /* LIBXML_ICONV_ENABLED */ +#ifdef DEBUG_ENCODING + if (ret) + xmlGenericError(xmlGenericErrorContext, + "failed to close the encoding handler\n"); + else + xmlGenericError(xmlGenericErrorContext, + "closed the encoding handler\n"); +#endif + + return(ret); +} + +/** + * xmlByteConsumed: + * @ctxt: an XML parser context + * + * This function provides the current index of the parser relative + * to the start of the current entity. This function is computed in + * bytes from the beginning starting at zero and finishing at the + * size in byte of the file if parsing a file. The function is + * of constant cost if the input is UTF-8 but can be costly if run + * on non-UTF-8 input. + * + * Returns the index in bytes from the beginning of the entity or -1 + * in case the index could not be computed. + */ +long +xmlByteConsumed(xmlParserCtxtPtr ctxt) { + xmlParserInputPtr in; + + if (ctxt == NULL) return(-1); + in = ctxt->input; + if (in == NULL) return(-1); + if ((in->buf != NULL) && (in->buf->encoder != NULL)) { + unsigned int unused = 0; + xmlCharEncodingHandler * handler = in->buf->encoder; + /* + * Encoding conversion, compute the number of unused original + * bytes from the input not consumed and substract that from + * the raw consumed value, this is not a cheap operation + */ + if (in->end - in->cur > 0) { + unsigned char convbuf[32000]; + const unsigned char *cur = (const unsigned char *)in->cur; + int toconv = in->end - in->cur, written = 32000; + + int ret; + + if (handler->output != NULL) { + do { + toconv = in->end - cur; + written = 32000; + ret = handler->output(&convbuf[0], &written, + cur, &toconv); + if (ret == -1) return(-1); + unused += written; + cur += toconv; + } while (ret == -2); +#ifdef LIBXML_ICONV_ENABLED + } else if (handler->iconv_out != NULL) { + do { + toconv = in->end - cur; + written = 32000; + ret = xmlIconvWrapper(handler->iconv_out, &convbuf[0], + &written, cur, &toconv); + if (ret < 0) { + if (written > 0) + ret = -2; + else + return(-1); + } + unused += written; + cur += toconv; + } while (ret == -2); +#endif + } else { + /* could not find a converter */ + return(-1); + } + } + if (in->buf->rawconsumed < unused) + return(-1); + return(in->buf->rawconsumed - unused); + } + return(in->consumed + (in->cur - in->base)); +} + +#ifndef LIBXML_ICONV_ENABLED +#ifdef LIBXML_ISO8859X_ENABLED + +/** + * UTF8ToISO8859x: + * @out: a pointer to an array of bytes to store the result + * @outlen: the length of @out + * @in: a pointer to an array of UTF-8 chars + * @inlen: the length of @in + * @xlattable: the 2-level transcoding table + * + * Take a block of UTF-8 chars in and try to convert it to an ISO 8859-* + * block of chars out. + * + * Returns 0 if success, -2 if the transcoding fails, or -1 otherwise + * The value of @inlen after return is the number of octets consumed + * as the return value is positive, else unpredictable. + * The value of @outlen after return is the number of ocetes consumed. + */ +static int +UTF8ToISO8859x(unsigned char* out, int *outlen, + const unsigned char* in, int *inlen, + unsigned char const *xlattable) { + const unsigned char* outstart = out; + const unsigned char* inend; + const unsigned char* instart = in; + + if ((out == NULL) || (outlen == NULL) || (inlen == NULL) || + (xlattable == NULL)) + return(-1); + if (in == NULL) { + /* + * initialization nothing to do + */ + *outlen = 0; + *inlen = 0; + return(0); + } + inend = in + (*inlen); + while (in < inend) { + unsigned char d = *in++; + if (d < 0x80) { + *out++ = d; + } else if (d < 0xC0) { + /* trailing byte in leading position */ + *outlen = out - outstart; + *inlen = in - instart - 1; + return(-2); + } else if (d < 0xE0) { + unsigned char c; + if (!(in < inend)) { + /* trailing byte not in input buffer */ + *outlen = out - outstart; + *inlen = in - instart - 1; + return(-2); + } + c = *in++; + if ((c & 0xC0) != 0x80) { + /* not a trailing byte */ + *outlen = out - outstart; + *inlen = in - instart - 2; + return(-2); + } + c = c & 0x3F; + d = d & 0x1F; + d = xlattable [48 + c + xlattable [d] * 64]; + if (d == 0) { + /* not in character set */ + *outlen = out - outstart; + *inlen = in - instart - 2; + return(-2); + } + *out++ = d; + } else if (d < 0xF0) { + unsigned char c1; + unsigned char c2; + if (!(in < inend - 1)) { + /* trailing bytes not in input buffer */ + *outlen = out - outstart; + *inlen = in - instart - 1; + return(-2); + } + c1 = *in++; + if ((c1 & 0xC0) != 0x80) { + /* not a trailing byte (c1) */ + *outlen = out - outstart; + *inlen = in - instart - 2; + return(-2); + } + c2 = *in++; + if ((c2 & 0xC0) != 0x80) { + /* not a trailing byte (c2) */ + *outlen = out - outstart; + *inlen = in - instart - 2; + return(-2); + } + c1 = c1 & 0x3F; + c2 = c2 & 0x3F; + d = d & 0x0F; + d = xlattable [48 + c2 + xlattable [48 + c1 + + xlattable [32 + d] * 64] * 64]; + if (d == 0) { + /* not in character set */ + *outlen = out - outstart; + *inlen = in - instart - 3; + return(-2); + } + *out++ = d; + } else { + /* cannot transcode >= U+010000 */ + *outlen = out - outstart; + *inlen = in - instart - 1; + return(-2); + } + } + *outlen = out - outstart; + *inlen = in - instart; + return(*outlen); +} + +/** + * ISO8859xToUTF8 + * @out: a pointer to an array of bytes to store the result + * @outlen: the length of @out + * @in: a pointer to an array of ISO Latin 1 chars + * @inlen: the length of @in + * + * Take a block of ISO 8859-* chars in and try to convert it to an UTF-8 + * block of chars out. + * Returns 0 if success, or -1 otherwise + * The value of @inlen after return is the number of octets consumed + * The value of @outlen after return is the number of ocetes produced. + */ +static int +ISO8859xToUTF8(unsigned char* out, int *outlen, + const unsigned char* in, int *inlen, + unsigned short const *unicodetable) { + unsigned char* outstart = out; + unsigned char* outend; + const unsigned char* instart = in; + const unsigned char* inend; + const unsigned char* instop; + unsigned int c; + + if ((out == NULL) || (outlen == NULL) || (inlen == NULL) || + (in == NULL) || (unicodetable == NULL)) + return(-1); + outend = out + *outlen; + inend = in + *inlen; + instop = inend; + c = *in; + while (in < inend && out < outend - 1) { + if (c >= 0x80) { + c = unicodetable [c - 0x80]; + if (c == 0) { + /* undefined code point */ + *outlen = out - outstart; + *inlen = in - instart; + return (-1); + } + if (c < 0x800) { + *out++ = ((c >> 6) & 0x1F) | 0xC0; + *out++ = (c & 0x3F) | 0x80; + } else { + *out++ = ((c >> 12) & 0x0F) | 0xE0; + *out++ = ((c >> 6) & 0x3F) | 0x80; + *out++ = (c & 0x3F) | 0x80; + } + ++in; + c = *in; + } + if (instop - in > outend - out) instop = in + (outend - out); + while (c < 0x80 && in < instop) { + *out++ = c; + ++in; + c = *in; + } + } + if (in < inend && out < outend && c < 0x80) { + *out++ = c; + ++in; + } + *outlen = out - outstart; + *inlen = in - instart; + return (*outlen); +} + + +/************************************************************************ + * Lookup tables for ISO-8859-2..ISO-8859-16 transcoding * + ************************************************************************/ + +static unsigned short const xmlunicodetable_ISO8859_2 [128] = { + 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, + 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f, + 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, + 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f, + 0x00a0, 0x0104, 0x02d8, 0x0141, 0x00a4, 0x013d, 0x015a, 0x00a7, + 0x00a8, 0x0160, 0x015e, 0x0164, 0x0179, 0x00ad, 0x017d, 0x017b, + 0x00b0, 0x0105, 0x02db, 0x0142, 0x00b4, 0x013e, 0x015b, 0x02c7, + 0x00b8, 0x0161, 0x015f, 0x0165, 0x017a, 0x02dd, 0x017e, 0x017c, + 0x0154, 0x00c1, 0x00c2, 0x0102, 0x00c4, 0x0139, 0x0106, 0x00c7, + 0x010c, 0x00c9, 0x0118, 0x00cb, 0x011a, 0x00cd, 0x00ce, 0x010e, + 0x0110, 0x0143, 0x0147, 0x00d3, 0x00d4, 0x0150, 0x00d6, 0x00d7, + 0x0158, 0x016e, 0x00da, 0x0170, 0x00dc, 0x00dd, 0x0162, 0x00df, + 0x0155, 0x00e1, 0x00e2, 0x0103, 0x00e4, 0x013a, 0x0107, 0x00e7, + 0x010d, 0x00e9, 0x0119, 0x00eb, 0x011b, 0x00ed, 0x00ee, 0x010f, + 0x0111, 0x0144, 0x0148, 0x00f3, 0x00f4, 0x0151, 0x00f6, 0x00f7, + 0x0159, 0x016f, 0x00fa, 0x0171, 0x00fc, 0x00fd, 0x0163, 0x02d9, +}; + +static unsigned char const xmltranscodetable_ISO8859_2 [48 + 6 * 64] = { + "\x00\x00\x01\x05\x02\x04\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f" + "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" + "\xa0\x00\x00\x00\xa4\x00\x00\xa7\xa8\x00\x00\x00\x00\xad\x00\x00" + "\xb0\x00\x00\x00\xb4\x00\x00\x00\xb8\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\xc3\xe3\xa1\xb1\xc6\xe6\x00\x00\x00\x00\xc8\xe8\xcf\xef" + "\xd0\xf0\x00\x00\x00\x00\x00\x00\xca\xea\xcc\xec\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc5\xe5\x00\x00\xa5\xb5\x00" + "\x00\x00\x00\x00\x00\x00\x00\xb7\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\xa2\xff\x00\xb2\x00\xbd\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\xa3\xb3\xd1\xf1\x00\x00\xd2\xf2\x00\x00\x00\x00\x00\x00\x00" + "\xd5\xf5\x00\x00\xc0\xe0\x00\x00\xd8\xf8\xa6\xb6\x00\x00\xaa\xba" + "\xa9\xb9\xde\xfe\xab\xbb\x00\x00\x00\x00\x00\x00\x00\x00\xd9\xf9" + "\xdb\xfb\x00\x00\x00\x00\x00\x00\x00\xac\xbc\xaf\xbf\xae\xbe\x00" + "\x00\xc1\xc2\x00\xc4\x00\x00\xc7\x00\xc9\x00\xcb\x00\xcd\xce\x00" + "\x00\x00\x00\xd3\xd4\x00\xd6\xd7\x00\x00\xda\x00\xdc\xdd\x00\xdf" + "\x00\xe1\xe2\x00\xe4\x00\x00\xe7\x00\xe9\x00\xeb\x00\xed\xee\x00" + "\x00\x00\x00\xf3\xf4\x00\xf6\xf7\x00\x00\xfa\x00\xfc\xfd\x00\x00" +}; + +static unsigned short const xmlunicodetable_ISO8859_3 [128] = { + 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, + 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f, + 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, + 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f, + 0x00a0, 0x0126, 0x02d8, 0x00a3, 0x00a4, 0x0000, 0x0124, 0x00a7, + 0x00a8, 0x0130, 0x015e, 0x011e, 0x0134, 0x00ad, 0x0000, 0x017b, + 0x00b0, 0x0127, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x0125, 0x00b7, + 0x00b8, 0x0131, 0x015f, 0x011f, 0x0135, 0x00bd, 0x0000, 0x017c, + 0x00c0, 0x00c1, 0x00c2, 0x0000, 0x00c4, 0x010a, 0x0108, 0x00c7, + 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf, + 0x0000, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x0120, 0x00d6, 0x00d7, + 0x011c, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x016c, 0x015c, 0x00df, + 0x00e0, 0x00e1, 0x00e2, 0x0000, 0x00e4, 0x010b, 0x0109, 0x00e7, + 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, + 0x0000, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x0121, 0x00f6, 0x00f7, + 0x011d, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x016d, 0x015d, 0x02d9, +}; + +static unsigned char const xmltranscodetable_ISO8859_3 [48 + 7 * 64] = { + "\x04\x00\x01\x06\x02\x05\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f" + "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" + "\xa0\x00\x00\xa3\xa4\x00\x00\xa7\xa8\x00\x00\x00\x00\xad\x00\x00" + "\xb0\x00\xb2\xb3\xb4\xb5\x00\xb7\xb8\x00\x00\x00\x00\xbd\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\xc6\xe6\xc5\xe5\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd8\xf8\xab\xbb" + "\xd5\xf5\x00\x00\xa6\xb6\xa1\xb1\x00\x00\x00\x00\x00\x00\x00\x00" + "\xa9\xb9\x00\x00\xac\xbc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\xa2\xff\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xde\xfe\xaa\xba" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xdd\xfd\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaf\xbf\x00\x00\x00" + "\xc0\xc1\xc2\x00\xc4\x00\x00\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" + "\x00\xd1\xd2\xd3\xd4\x00\xd6\xd7\x00\xd9\xda\xdb\xdc\x00\x00\xdf" + "\xe0\xe1\xe2\x00\xe4\x00\x00\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef" + "\x00\xf1\xf2\xf3\xf4\x00\xf6\xf7\x00\xf9\xfa\xfb\xfc\x00\x00\x00" +}; + +static unsigned short const xmlunicodetable_ISO8859_4 [128] = { + 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, + 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f, + 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, + 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f, + 0x00a0, 0x0104, 0x0138, 0x0156, 0x00a4, 0x0128, 0x013b, 0x00a7, + 0x00a8, 0x0160, 0x0112, 0x0122, 0x0166, 0x00ad, 0x017d, 0x00af, + 0x00b0, 0x0105, 0x02db, 0x0157, 0x00b4, 0x0129, 0x013c, 0x02c7, + 0x00b8, 0x0161, 0x0113, 0x0123, 0x0167, 0x014a, 0x017e, 0x014b, + 0x0100, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x012e, + 0x010c, 0x00c9, 0x0118, 0x00cb, 0x0116, 0x00cd, 0x00ce, 0x012a, + 0x0110, 0x0145, 0x014c, 0x0136, 0x00d4, 0x00d5, 0x00d6, 0x00d7, + 0x00d8, 0x0172, 0x00da, 0x00db, 0x00dc, 0x0168, 0x016a, 0x00df, + 0x0101, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x012f, + 0x010d, 0x00e9, 0x0119, 0x00eb, 0x0117, 0x00ed, 0x00ee, 0x012b, + 0x0111, 0x0146, 0x014d, 0x0137, 0x00f4, 0x00f5, 0x00f6, 0x00f7, + 0x00f8, 0x0173, 0x00fa, 0x00fb, 0x00fc, 0x0169, 0x016b, 0x02d9, +}; + +static unsigned char const xmltranscodetable_ISO8859_4 [48 + 6 * 64] = { + "\x00\x00\x01\x05\x02\x03\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f" + "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" + "\xa0\x00\x00\x00\xa4\x00\x00\xa7\xa8\x00\x00\x00\x00\xad\x00\xaf" + "\xb0\x00\x00\x00\xb4\x00\x00\x00\xb8\x00\x00\x00\x00\x00\x00\x00" + "\xc0\xe0\x00\x00\xa1\xb1\x00\x00\x00\x00\x00\x00\xc8\xe8\x00\x00" + "\xd0\xf0\xaa\xba\x00\x00\xcc\xec\xca\xea\x00\x00\x00\x00\x00\x00" + "\x00\x00\xab\xbb\x00\x00\x00\x00\xa5\xb5\xcf\xef\x00\x00\xc7\xe7" + "\x00\x00\x00\x00\x00\x00\xd3\xf3\xa2\x00\x00\xa6\xb6\x00\x00\x00" + "\x00\x00\x00\x00\x00\xd1\xf1\x00\x00\x00\xbd\xbf\xd2\xf2\x00\x00" + "\x00\x00\x00\x00\x00\x00\xa3\xb3\x00\x00\x00\x00\x00\x00\x00\x00" + "\xa9\xb9\x00\x00\x00\x00\xac\xbc\xdd\xfd\xde\xfe\x00\x00\x00\x00" + "\x00\x00\xd9\xf9\x00\x00\x00\x00\x00\x00\x00\x00\x00\xae\xbe\x00" + "\x00\x00\x00\x00\x00\x00\x00\xb7\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\x00\xb2\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\xc1\xc2\xc3\xc4\xc5\xc6\x00\x00\xc9\x00\xcb\x00\xcd\xce\x00" + "\x00\x00\x00\x00\xd4\xd5\xd6\xd7\xd8\x00\xda\xdb\xdc\x00\x00\xdf" + "\x00\xe1\xe2\xe3\xe4\xe5\xe6\x00\x00\xe9\x00\xeb\x00\xed\xee\x00" + "\x00\x00\x00\x00\xf4\xf5\xf6\xf7\xf8\x00\xfa\xfb\xfc\x00\x00\x00" +}; + +static unsigned short const xmlunicodetable_ISO8859_5 [128] = { + 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, + 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f, + 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, + 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f, + 0x00a0, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407, + 0x0408, 0x0409, 0x040a, 0x040b, 0x040c, 0x00ad, 0x040e, 0x040f, + 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, + 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, 0x041f, + 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, + 0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d, 0x042e, 0x042f, + 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, + 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, 0x043f, + 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, + 0x0448, 0x0449, 0x044a, 0x044b, 0x044c, 0x044d, 0x044e, 0x044f, + 0x2116, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457, + 0x0458, 0x0459, 0x045a, 0x045b, 0x045c, 0x00a7, 0x045e, 0x045f, +}; + +static unsigned char const xmltranscodetable_ISO8859_5 [48 + 6 * 64] = { + "\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x02\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f" + "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" + "\xa0\x00\x00\x00\x00\x00\x00\xfd\x00\x00\x00\x00\x00\xad\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\x00\xae\xaf" + "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf" + "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" + "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf" + "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef" + "\x00\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\x00\xfe\xff" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +}; + +static unsigned short const xmlunicodetable_ISO8859_6 [128] = { + 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, + 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f, + 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, + 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f, + 0x00a0, 0x0000, 0x0000, 0x0000, 0x00a4, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x060c, 0x00ad, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x061b, 0x0000, 0x0000, 0x0000, 0x061f, + 0x0000, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627, + 0x0628, 0x0629, 0x062a, 0x062b, 0x062c, 0x062d, 0x062e, 0x062f, + 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x0637, + 0x0638, 0x0639, 0x063a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0640, 0x0641, 0x0642, 0x0643, 0x0644, 0x0645, 0x0646, 0x0647, + 0x0648, 0x0649, 0x064a, 0x064b, 0x064c, 0x064d, 0x064e, 0x064f, + 0x0650, 0x0651, 0x0652, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +}; + +static unsigned char const xmltranscodetable_ISO8859_6 [48 + 5 * 64] = { + "\x02\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x03\x04\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f" + "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" + "\xa0\x00\x00\x00\xa4\x00\x00\x00\x00\x00\x00\x00\x00\xad\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xac\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xbb\x00\x00\x00\xbf" + "\x00\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" + "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\x00\x00\x00\x00\x00" + "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef" + "\xf0\xf1\xf2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +}; + +static unsigned short const xmlunicodetable_ISO8859_7 [128] = { + 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, + 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f, + 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, + 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f, + 0x00a0, 0x2018, 0x2019, 0x00a3, 0x0000, 0x0000, 0x00a6, 0x00a7, + 0x00a8, 0x00a9, 0x0000, 0x00ab, 0x00ac, 0x00ad, 0x0000, 0x2015, + 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x0384, 0x0385, 0x0386, 0x00b7, + 0x0388, 0x0389, 0x038a, 0x00bb, 0x038c, 0x00bd, 0x038e, 0x038f, + 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, + 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f, + 0x03a0, 0x03a1, 0x0000, 0x03a3, 0x03a4, 0x03a5, 0x03a6, 0x03a7, + 0x03a8, 0x03a9, 0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03ae, 0x03af, + 0x03b0, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7, + 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf, + 0x03c0, 0x03c1, 0x03c2, 0x03c3, 0x03c4, 0x03c5, 0x03c6, 0x03c7, + 0x03c8, 0x03c9, 0x03ca, 0x03cb, 0x03cc, 0x03cd, 0x03ce, 0x0000, +}; + +static unsigned char const xmltranscodetable_ISO8859_7 [48 + 7 * 64] = { + "\x04\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x06" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f" + "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" + "\xa0\x00\x00\xa3\x00\x00\xa6\xa7\xa8\xa9\x00\xab\xac\xad\x00\x00" + "\xb0\xb1\xb2\xb3\x00\x00\x00\xb7\x00\x00\x00\xbb\x00\xbd\x00\x00" + "\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\xaf\x00\x00\xa1\xa2\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\xb4\xb5\xb6\x00\xb8\xb9\xba\x00\xbc\x00\xbe\xbf" + "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" + "\xd0\xd1\x00\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf" + "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef" + "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +}; + +static unsigned short const xmlunicodetable_ISO8859_8 [128] = { + 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, + 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f, + 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, + 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f, + 0x00a0, 0x0000, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, + 0x00a8, 0x00a9, 0x00d7, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af, + 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, + 0x00b8, 0x00b9, 0x00f7, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2017, + 0x05d0, 0x05d1, 0x05d2, 0x05d3, 0x05d4, 0x05d5, 0x05d6, 0x05d7, + 0x05d8, 0x05d9, 0x05da, 0x05db, 0x05dc, 0x05dd, 0x05de, 0x05df, + 0x05e0, 0x05e1, 0x05e2, 0x05e3, 0x05e4, 0x05e5, 0x05e6, 0x05e7, + 0x05e8, 0x05e9, 0x05ea, 0x0000, 0x0000, 0x200e, 0x200f, 0x0000, +}; + +static unsigned char const xmltranscodetable_ISO8859_8 [48 + 7 * 64] = { + "\x02\x00\x01\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f" + "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" + "\xa0\x00\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\x00\xab\xac\xad\xae\xaf" + "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\x00\xbb\xbc\xbd\xbe\x00" + "\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\xaa\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\xba\x00\x00\x00\x00\x00\x00\x00\x00" + "\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xfd\xfe" + "\x00\x00\x00\x00\x00\x00\x00\xdf\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef" + "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +}; + +static unsigned short const xmlunicodetable_ISO8859_9 [128] = { + 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, + 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f, + 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, + 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f, + 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, + 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af, + 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, + 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf, + 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7, + 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf, + 0x011e, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7, + 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x0130, 0x015e, 0x00df, + 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, + 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, + 0x011f, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, + 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x0131, 0x015f, 0x00ff, +}; + +static unsigned char const xmltranscodetable_ISO8859_9 [48 + 5 * 64] = { + "\x00\x00\x01\x02\x03\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f" + "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" + "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf" + "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf" + "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" + "\x00\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\x00\x00\xdf" + "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef" + "\x00\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\x00\x00\xff" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd0\xf0" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\xdd\xfd\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xde\xfe" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +}; + +static unsigned short const xmlunicodetable_ISO8859_10 [128] = { + 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, + 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f, + 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, + 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f, + 0x00a0, 0x0104, 0x0112, 0x0122, 0x012a, 0x0128, 0x0136, 0x00a7, + 0x013b, 0x0110, 0x0160, 0x0166, 0x017d, 0x00ad, 0x016a, 0x014a, + 0x00b0, 0x0105, 0x0113, 0x0123, 0x012b, 0x0129, 0x0137, 0x00b7, + 0x013c, 0x0111, 0x0161, 0x0167, 0x017e, 0x2015, 0x016b, 0x014b, + 0x0100, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x012e, + 0x010c, 0x00c9, 0x0118, 0x00cb, 0x0116, 0x00cd, 0x00ce, 0x00cf, + 0x00d0, 0x0145, 0x014c, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x0168, + 0x00d8, 0x0172, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df, + 0x0101, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x012f, + 0x010d, 0x00e9, 0x0119, 0x00eb, 0x0117, 0x00ed, 0x00ee, 0x00ef, + 0x00f0, 0x0146, 0x014d, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x0169, + 0x00f8, 0x0173, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x0138, +}; + +static unsigned char const xmltranscodetable_ISO8859_10 [48 + 7 * 64] = { + "\x00\x00\x01\x06\x02\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f" + "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" + "\xa0\x00\x00\x00\x00\x00\x00\xa7\x00\x00\x00\x00\x00\xad\x00\x00" + "\xb0\x00\x00\x00\x00\x00\x00\xb7\x00\x00\x00\x00\x00\x00\x00\x00" + "\xc0\xe0\x00\x00\xa1\xb1\x00\x00\x00\x00\x00\x00\xc8\xe8\x00\x00" + "\xa9\xb9\xa2\xb2\x00\x00\xcc\xec\xca\xea\x00\x00\x00\x00\x00\x00" + "\x00\x00\xa3\xb3\x00\x00\x00\x00\xa5\xb5\xa4\xb4\x00\x00\xc7\xe7" + "\x00\x00\x00\x00\x00\x00\xa6\xb6\xff\x00\x00\xa8\xb8\x00\x00\x00" + "\x00\x00\x00\x00\x00\xd1\xf1\x00\x00\x00\xaf\xbf\xd2\xf2\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\xaa\xba\x00\x00\x00\x00\xab\xbb\xd7\xf7\xae\xbe\x00\x00\x00\x00" + "\x00\x00\xd9\xf9\x00\x00\x00\x00\x00\x00\x00\x00\x00\xac\xbc\x00" + "\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\xbd\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\xc1\xc2\xc3\xc4\xc5\xc6\x00\x00\xc9\x00\xcb\x00\xcd\xce\xcf" + "\xd0\x00\x00\xd3\xd4\xd5\xd6\x00\xd8\x00\xda\xdb\xdc\xdd\xde\xdf" + "\x00\xe1\xe2\xe3\xe4\xe5\xe6\x00\x00\xe9\x00\xeb\x00\xed\xee\xef" + "\xf0\x00\x00\xf3\xf4\xf5\xf6\x00\xf8\x00\xfa\xfb\xfc\xfd\xfe\x00" +}; + +static unsigned short const xmlunicodetable_ISO8859_11 [128] = { + 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, + 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f, + 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, + 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f, + 0x00a0, 0x0e01, 0x0e02, 0x0e03, 0x0e04, 0x0e05, 0x0e06, 0x0e07, + 0x0e08, 0x0e09, 0x0e0a, 0x0e0b, 0x0e0c, 0x0e0d, 0x0e0e, 0x0e0f, + 0x0e10, 0x0e11, 0x0e12, 0x0e13, 0x0e14, 0x0e15, 0x0e16, 0x0e17, + 0x0e18, 0x0e19, 0x0e1a, 0x0e1b, 0x0e1c, 0x0e1d, 0x0e1e, 0x0e1f, + 0x0e20, 0x0e21, 0x0e22, 0x0e23, 0x0e24, 0x0e25, 0x0e26, 0x0e27, + 0x0e28, 0x0e29, 0x0e2a, 0x0e2b, 0x0e2c, 0x0e2d, 0x0e2e, 0x0e2f, + 0x0e30, 0x0e31, 0x0e32, 0x0e33, 0x0e34, 0x0e35, 0x0e36, 0x0e37, + 0x0e38, 0x0e39, 0x0e3a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0e3f, + 0x0e40, 0x0e41, 0x0e42, 0x0e43, 0x0e44, 0x0e45, 0x0e46, 0x0e47, + 0x0e48, 0x0e49, 0x0e4a, 0x0e4b, 0x0e4c, 0x0e4d, 0x0e4e, 0x0e4f, + 0x0e50, 0x0e51, 0x0e52, 0x0e53, 0x0e54, 0x0e55, 0x0e56, 0x0e57, + 0x0e58, 0x0e59, 0x0e5a, 0x0e5b, 0x0000, 0x0000, 0x0000, 0x0000, +}; + +static unsigned char const xmltranscodetable_ISO8859_11 [48 + 6 * 64] = { + "\x04\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f" + "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" + "\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x03\x05\x00\x00\x00\x00\x00\x00" + "\x00\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf" + "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf" + "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" + "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\x00\x00\x00\x00\xdf" + "\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef" + "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +}; + +static unsigned short const xmlunicodetable_ISO8859_13 [128] = { + 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, + 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f, + 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, + 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f, + 0x00a0, 0x201d, 0x00a2, 0x00a3, 0x00a4, 0x201e, 0x00a6, 0x00a7, + 0x00d8, 0x00a9, 0x0156, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00c6, + 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x201c, 0x00b5, 0x00b6, 0x00b7, + 0x00f8, 0x00b9, 0x0157, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00e6, + 0x0104, 0x012e, 0x0100, 0x0106, 0x00c4, 0x00c5, 0x0118, 0x0112, + 0x010c, 0x00c9, 0x0179, 0x0116, 0x0122, 0x0136, 0x012a, 0x013b, + 0x0160, 0x0143, 0x0145, 0x00d3, 0x014c, 0x00d5, 0x00d6, 0x00d7, + 0x0172, 0x0141, 0x015a, 0x016a, 0x00dc, 0x017b, 0x017d, 0x00df, + 0x0105, 0x012f, 0x0101, 0x0107, 0x00e4, 0x00e5, 0x0119, 0x0113, + 0x010d, 0x00e9, 0x017a, 0x0117, 0x0123, 0x0137, 0x012b, 0x013c, + 0x0161, 0x0144, 0x0146, 0x00f3, 0x014d, 0x00f5, 0x00f6, 0x00f7, + 0x0173, 0x0142, 0x015b, 0x016b, 0x00fc, 0x017c, 0x017e, 0x2019, +}; + +static unsigned char const xmltranscodetable_ISO8859_13 [48 + 7 * 64] = { + "\x00\x00\x01\x04\x06\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f" + "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" + "\xa0\x00\xa2\xa3\xa4\x00\xa6\xa7\x00\xa9\x00\xab\xac\xad\xae\x00" + "\xb0\xb1\xb2\xb3\x00\xb5\xb6\xb7\x00\xb9\x00\xbb\xbc\xbd\xbe\x00" + "\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\x00\x00\xb4\xa1\xa5\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\xc4\xc5\xaf\x00\x00\xc9\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\xd3\x00\xd5\xd6\xd7\xa8\x00\x00\x00\xdc\x00\x00\xdf" + "\x00\x00\x00\x00\xe4\xe5\xbf\x00\x00\xe9\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\xf3\x00\xf5\xf6\xf7\xb8\x00\x00\x00\xfc\x00\x00\x00" + "\x00\xd9\xf9\xd1\xf1\xd2\xf2\x00\x00\x00\x00\x00\xd4\xf4\x00\x00" + "\x00\x00\x00\x00\x00\x00\xaa\xba\x00\x00\xda\xfa\x00\x00\x00\x00" + "\xd0\xf0\x00\x00\x00\x00\x00\x00\x00\x00\xdb\xfb\x00\x00\x00\x00" + "\x00\x00\xd8\xf8\x00\x00\x00\x00\x00\xca\xea\xdd\xfd\xde\xfe\x00" + "\xc2\xe2\x00\x00\xc0\xe0\xc3\xe3\x00\x00\x00\x00\xc8\xe8\x00\x00" + "\x00\x00\xc7\xe7\x00\x00\xcb\xeb\xc6\xe6\x00\x00\x00\x00\x00\x00" + "\x00\x00\xcc\xec\x00\x00\x00\x00\x00\x00\xce\xee\x00\x00\xc1\xe1" + "\x00\x00\x00\x00\x00\x00\xcd\xed\x00\x00\x00\xcf\xef\x00\x00\x00" +}; + +static unsigned short const xmlunicodetable_ISO8859_14 [128] = { + 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, + 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f, + 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, + 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f, + 0x00a0, 0x1e02, 0x1e03, 0x00a3, 0x010a, 0x010b, 0x1e0a, 0x00a7, + 0x1e80, 0x00a9, 0x1e82, 0x1e0b, 0x1ef2, 0x00ad, 0x00ae, 0x0178, + 0x1e1e, 0x1e1f, 0x0120, 0x0121, 0x1e40, 0x1e41, 0x00b6, 0x1e56, + 0x1e81, 0x1e57, 0x1e83, 0x1e60, 0x1ef3, 0x1e84, 0x1e85, 0x1e61, + 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7, + 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf, + 0x0174, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x1e6a, + 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x0176, 0x00df, + 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, + 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, + 0x0175, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x1e6b, + 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x0177, 0x00ff, +}; + +static unsigned char const xmltranscodetable_ISO8859_14 [48 + 10 * 64] = { + "\x00\x00\x01\x09\x04\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f" + "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" + "\xa0\x00\x00\xa3\x00\x00\x00\xa7\x00\xa9\x00\x00\x00\xad\xae\x00" + "\x00\x00\x00\x00\x00\x00\xb6\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x03\x08\x05\x06\x00\x00\x00\x00" + "\x00\x00\xa1\xa2\x00\x00\x00\x00\x00\x00\xa6\xab\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xb0\xb1" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\xa5\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\xb2\xb3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\xa8\xb8\xaa\xba\xbd\xbe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\xac\xbc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\xd0\xf0\xde\xfe\xaf\x00\x00\x00\x00\x00\x00\x00" + "\xb4\xb5\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\xb7\xb9\x00\x00\x00\x00\x00\x00\x00\x00" + "\xbb\xbf\x00\x00\x00\x00\x00\x00\x00\x00\xd7\xf7\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" + "\x00\xd1\xd2\xd3\xd4\xd5\xd6\x00\xd8\xd9\xda\xdb\xdc\xdd\x00\xdf" + "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef" + "\x00\xf1\xf2\xf3\xf4\xf5\xf6\x00\xf8\xf9\xfa\xfb\xfc\xfd\x00\xff" +}; + +static unsigned short const xmlunicodetable_ISO8859_15 [128] = { + 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, + 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f, + 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, + 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f, + 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x20ac, 0x00a5, 0x0160, 0x00a7, + 0x0161, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af, + 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x017d, 0x00b5, 0x00b6, 0x00b7, + 0x017e, 0x00b9, 0x00ba, 0x00bb, 0x0152, 0x0153, 0x0178, 0x00bf, + 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7, + 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf, + 0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7, + 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df, + 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, + 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, + 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, + 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff, +}; + +static unsigned char const xmltranscodetable_ISO8859_15 [48 + 6 * 64] = { + "\x00\x00\x01\x05\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f" + "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" + "\xa0\xa1\xa2\xa3\x00\xa5\x00\xa7\x00\xa9\xaa\xab\xac\xad\xae\xaf" + "\xb0\xb1\xb2\xb3\x00\xb5\xb6\xb7\x00\xb9\xba\xbb\x00\x00\x00\xbf" + "\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\xbc\xbd\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\xa6\xa8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\xbe\x00\x00\x00\x00\xb4\xb8\x00" + "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" + "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf" + "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef" + "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff" +}; + +static unsigned short const xmlunicodetable_ISO8859_16 [128] = { + 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, + 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f, + 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, + 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f, + 0x00a0, 0x0104, 0x0105, 0x0141, 0x20ac, 0x201e, 0x0160, 0x00a7, + 0x0161, 0x00a9, 0x0218, 0x00ab, 0x0179, 0x00ad, 0x017a, 0x017b, + 0x00b0, 0x00b1, 0x010c, 0x0142, 0x017d, 0x201d, 0x00b6, 0x00b7, + 0x017e, 0x010d, 0x0219, 0x00bb, 0x0152, 0x0153, 0x0178, 0x017c, + 0x00c0, 0x00c1, 0x00c2, 0x0102, 0x00c4, 0x0106, 0x00c6, 0x00c7, + 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf, + 0x0110, 0x0143, 0x00d2, 0x00d3, 0x00d4, 0x0150, 0x00d6, 0x015a, + 0x0170, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x0118, 0x021a, 0x00df, + 0x00e0, 0x00e1, 0x00e2, 0x0103, 0x00e4, 0x0107, 0x00e6, 0x00e7, + 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, + 0x0111, 0x0144, 0x00f2, 0x00f3, 0x00f4, 0x0151, 0x00f6, 0x015b, + 0x0171, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x0119, 0x021b, 0x00ff, +}; + +static unsigned char const xmltranscodetable_ISO8859_16 [48 + 9 * 64] = { + "\x00\x00\x01\x08\x02\x03\x00\x00\x07\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f" + "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" + "\xa0\x00\x00\x00\x00\x00\x00\xa7\x00\xa9\x00\xab\x00\xad\x00\x00" + "\xb0\xb1\x00\x00\x00\x00\xb6\xb7\x00\x00\x00\xbb\x00\x00\x00\x00" + "\x00\x00\xc3\xe3\xa1\xa2\xc5\xe5\x00\x00\x00\x00\xb2\xb9\x00\x00" + "\xd0\xf0\x00\x00\x00\x00\x00\x00\xdd\xfd\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\xa3\xb3\xd1\xf1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\xd5\xf5\xbc\xbd\x00\x00\x00\x00\x00\x00\xd7\xf7\x00\x00\x00\x00" + "\xa6\xa8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\xd8\xf8\x00\x00\x00\x00\x00\x00\xbe\xac\xae\xaf\xbf\xb4\xb8\x00" + "\x06\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xb5\xa5\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\xaa\xba\xde\xfe\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\xc0\xc1\xc2\x00\xc4\x00\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" + "\x00\x00\xd2\xd3\xd4\x00\xd6\x00\x00\xd9\xda\xdb\xdc\x00\x00\xdf" + "\xe0\xe1\xe2\x00\xe4\x00\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef" + "\x00\x00\xf2\xf3\xf4\x00\xf6\x00\x00\xf9\xfa\xfb\xfc\x00\x00\xff" +}; + + +/* + * auto-generated functions for ISO-8859-2 .. ISO-8859-16 + */ + +static int ISO8859_2ToUTF8 (unsigned char* out, int *outlen, + const unsigned char* in, int *inlen) { + return ISO8859xToUTF8 (out, outlen, in, inlen, xmlunicodetable_ISO8859_2); +} +static int UTF8ToISO8859_2 (unsigned char* out, int *outlen, + const unsigned char* in, int *inlen) { + return UTF8ToISO8859x (out, outlen, in, inlen, xmltranscodetable_ISO8859_2); +} + +static int ISO8859_3ToUTF8 (unsigned char* out, int *outlen, + const unsigned char* in, int *inlen) { + return ISO8859xToUTF8 (out, outlen, in, inlen, xmlunicodetable_ISO8859_3); +} +static int UTF8ToISO8859_3 (unsigned char* out, int *outlen, + const unsigned char* in, int *inlen) { + return UTF8ToISO8859x (out, outlen, in, inlen, xmltranscodetable_ISO8859_3); +} + +static int ISO8859_4ToUTF8 (unsigned char* out, int *outlen, + const unsigned char* in, int *inlen) { + return ISO8859xToUTF8 (out, outlen, in, inlen, xmlunicodetable_ISO8859_4); +} +static int UTF8ToISO8859_4 (unsigned char* out, int *outlen, + const unsigned char* in, int *inlen) { + return UTF8ToISO8859x (out, outlen, in, inlen, xmltranscodetable_ISO8859_4); +} + +static int ISO8859_5ToUTF8 (unsigned char* out, int *outlen, + const unsigned char* in, int *inlen) { + return ISO8859xToUTF8 (out, outlen, in, inlen, xmlunicodetable_ISO8859_5); +} +static int UTF8ToISO8859_5 (unsigned char* out, int *outlen, + const unsigned char* in, int *inlen) { + return UTF8ToISO8859x (out, outlen, in, inlen, xmltranscodetable_ISO8859_5); +} + +static int ISO8859_6ToUTF8 (unsigned char* out, int *outlen, + const unsigned char* in, int *inlen) { + return ISO8859xToUTF8 (out, outlen, in, inlen, xmlunicodetable_ISO8859_6); +} +static int UTF8ToISO8859_6 (unsigned char* out, int *outlen, + const unsigned char* in, int *inlen) { + return UTF8ToISO8859x (out, outlen, in, inlen, xmltranscodetable_ISO8859_6); +} + +static int ISO8859_7ToUTF8 (unsigned char* out, int *outlen, + const unsigned char* in, int *inlen) { + return ISO8859xToUTF8 (out, outlen, in, inlen, xmlunicodetable_ISO8859_7); +} +static int UTF8ToISO8859_7 (unsigned char* out, int *outlen, + const unsigned char* in, int *inlen) { + return UTF8ToISO8859x (out, outlen, in, inlen, xmltranscodetable_ISO8859_7); +} + +static int ISO8859_8ToUTF8 (unsigned char* out, int *outlen, + const unsigned char* in, int *inlen) { + return ISO8859xToUTF8 (out, outlen, in, inlen, xmlunicodetable_ISO8859_8); +} +static int UTF8ToISO8859_8 (unsigned char* out, int *outlen, + const unsigned char* in, int *inlen) { + return UTF8ToISO8859x (out, outlen, in, inlen, xmltranscodetable_ISO8859_8); +} + +static int ISO8859_9ToUTF8 (unsigned char* out, int *outlen, + const unsigned char* in, int *inlen) { + return ISO8859xToUTF8 (out, outlen, in, inlen, xmlunicodetable_ISO8859_9); +} +static int UTF8ToISO8859_9 (unsigned char* out, int *outlen, + const unsigned char* in, int *inlen) { + return UTF8ToISO8859x (out, outlen, in, inlen, xmltranscodetable_ISO8859_9); +} + +static int ISO8859_10ToUTF8 (unsigned char* out, int *outlen, + const unsigned char* in, int *inlen) { + return ISO8859xToUTF8 (out, outlen, in, inlen, xmlunicodetable_ISO8859_10); +} +static int UTF8ToISO8859_10 (unsigned char* out, int *outlen, + const unsigned char* in, int *inlen) { + return UTF8ToISO8859x (out, outlen, in, inlen, xmltranscodetable_ISO8859_10); +} + +static int ISO8859_11ToUTF8 (unsigned char* out, int *outlen, + const unsigned char* in, int *inlen) { + return ISO8859xToUTF8 (out, outlen, in, inlen, xmlunicodetable_ISO8859_11); +} +static int UTF8ToISO8859_11 (unsigned char* out, int *outlen, + const unsigned char* in, int *inlen) { + return UTF8ToISO8859x (out, outlen, in, inlen, xmltranscodetable_ISO8859_11); +} + +static int ISO8859_13ToUTF8 (unsigned char* out, int *outlen, + const unsigned char* in, int *inlen) { + return ISO8859xToUTF8 (out, outlen, in, inlen, xmlunicodetable_ISO8859_13); +} +static int UTF8ToISO8859_13 (unsigned char* out, int *outlen, + const unsigned char* in, int *inlen) { + return UTF8ToISO8859x (out, outlen, in, inlen, xmltranscodetable_ISO8859_13); +} + +static int ISO8859_14ToUTF8 (unsigned char* out, int *outlen, + const unsigned char* in, int *inlen) { + return ISO8859xToUTF8 (out, outlen, in, inlen, xmlunicodetable_ISO8859_14); +} +static int UTF8ToISO8859_14 (unsigned char* out, int *outlen, + const unsigned char* in, int *inlen) { + return UTF8ToISO8859x (out, outlen, in, inlen, xmltranscodetable_ISO8859_14); +} + +static int ISO8859_15ToUTF8 (unsigned char* out, int *outlen, + const unsigned char* in, int *inlen) { + return ISO8859xToUTF8 (out, outlen, in, inlen, xmlunicodetable_ISO8859_15); +} +static int UTF8ToISO8859_15 (unsigned char* out, int *outlen, + const unsigned char* in, int *inlen) { + return UTF8ToISO8859x (out, outlen, in, inlen, xmltranscodetable_ISO8859_15); +} + +static int ISO8859_16ToUTF8 (unsigned char* out, int *outlen, + const unsigned char* in, int *inlen) { + return ISO8859xToUTF8 (out, outlen, in, inlen, xmlunicodetable_ISO8859_16); +} +static int UTF8ToISO8859_16 (unsigned char* out, int *outlen, + const unsigned char* in, int *inlen) { + return UTF8ToISO8859x (out, outlen, in, inlen, xmltranscodetable_ISO8859_16); +} + +static void +xmlRegisterCharEncodingHandlersISO8859x (void) { + xmlNewCharEncodingHandler ("ISO-8859-2", ISO8859_2ToUTF8, UTF8ToISO8859_2); + xmlNewCharEncodingHandler ("ISO-8859-3", ISO8859_3ToUTF8, UTF8ToISO8859_3); + xmlNewCharEncodingHandler ("ISO-8859-4", ISO8859_4ToUTF8, UTF8ToISO8859_4); + xmlNewCharEncodingHandler ("ISO-8859-5", ISO8859_5ToUTF8, UTF8ToISO8859_5); + xmlNewCharEncodingHandler ("ISO-8859-6", ISO8859_6ToUTF8, UTF8ToISO8859_6); + xmlNewCharEncodingHandler ("ISO-8859-7", ISO8859_7ToUTF8, UTF8ToISO8859_7); + xmlNewCharEncodingHandler ("ISO-8859-8", ISO8859_8ToUTF8, UTF8ToISO8859_8); + xmlNewCharEncodingHandler ("ISO-8859-9", ISO8859_9ToUTF8, UTF8ToISO8859_9); + xmlNewCharEncodingHandler ("ISO-8859-10", ISO8859_10ToUTF8, UTF8ToISO8859_10); + xmlNewCharEncodingHandler ("ISO-8859-11", ISO8859_11ToUTF8, UTF8ToISO8859_11); + xmlNewCharEncodingHandler ("ISO-8859-13", ISO8859_13ToUTF8, UTF8ToISO8859_13); + xmlNewCharEncodingHandler ("ISO-8859-14", ISO8859_14ToUTF8, UTF8ToISO8859_14); + xmlNewCharEncodingHandler ("ISO-8859-15", ISO8859_15ToUTF8, UTF8ToISO8859_15); + xmlNewCharEncodingHandler ("ISO-8859-16", ISO8859_16ToUTF8, UTF8ToISO8859_16); +} + +#endif +#endif + +#define bottom_encoding +#include "elfgcchack.h" + diff --git a/gettext-tools/gnulib-lib/libxml/encoding.in.h b/gettext-tools/gnulib-lib/libxml/encoding.in.h new file mode 100644 index 0000000..c74b25f --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/encoding.in.h @@ -0,0 +1,226 @@ +/* + * Summary: interface for the encoding conversion functions + * Description: interface for the encoding conversion functions needed for + * XML basic encoding and iconv() support. + * + * Related specs are + * rfc2044 (UTF-8 and UTF-16) F. Yergeau Alis Technologies + * [ISO-10646] UTF-8 and UTF-16 in Annexes + * [ISO-8859-1] ISO Latin-1 characters codes. + * [UNICODE] The Unicode Consortium, "The Unicode Standard -- + * Worldwide Character Encoding -- Version 1.0", Addison- + * Wesley, Volume 1, 1991, Volume 2, 1992. UTF-8 is + * described in Unicode Technical Report #4. + * [US-ASCII] Coded Character Set--7-bit American Standard Code for + * Information Interchange, ANSI X3.4-1986. + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + +#ifndef __XML_CHAR_ENCODING_H__ +#define __XML_CHAR_ENCODING_H__ + +#include + +#ifdef LIBXML_ICONV_ENABLED +#include +#endif +#ifdef __cplusplus +extern "C" { +#endif + +/* + * xmlCharEncoding: + * + * Predefined values for some standard encodings. + * Libxml does not do beforehand translation on UTF8 and ISOLatinX. + * It also supports ASCII, ISO-8859-1, and UTF16 (LE and BE) by default. + * + * Anything else would have to be translated to UTF8 before being + * given to the parser itself. The BOM for UTF16 and the encoding + * declaration are looked at and a converter is looked for at that + * point. If not found the parser stops here as asked by the XML REC. A + * converter can be registered by the user using xmlRegisterCharEncodingHandler + * but the current form doesn't allow stateful transcoding (a serious + * problem agreed !). If iconv has been found it will be used + * automatically and allow stateful transcoding, the simplest is then + * to be sure to enable iconv and to provide iconv libs for the encoding + * support needed. + * + * Note that the generic "UTF-16" is not a predefined value. Instead, only + * the specific UTF-16LE and UTF-16BE are present. + */ +typedef enum { + XML_CHAR_ENCODING_ERROR= -1, /* No char encoding detected */ + XML_CHAR_ENCODING_NONE= 0, /* No char encoding detected */ + XML_CHAR_ENCODING_UTF8= 1, /* UTF-8 */ + XML_CHAR_ENCODING_UTF16LE= 2, /* UTF-16 little endian */ + XML_CHAR_ENCODING_UTF16BE= 3, /* UTF-16 big endian */ + XML_CHAR_ENCODING_UCS4LE= 4, /* UCS-4 little endian */ + XML_CHAR_ENCODING_UCS4BE= 5, /* UCS-4 big endian */ + XML_CHAR_ENCODING_EBCDIC= 6, /* EBCDIC uh! */ + XML_CHAR_ENCODING_UCS4_2143=7, /* UCS-4 unusual ordering */ + XML_CHAR_ENCODING_UCS4_3412=8, /* UCS-4 unusual ordering */ + XML_CHAR_ENCODING_UCS2= 9, /* UCS-2 */ + XML_CHAR_ENCODING_8859_1= 10,/* ISO-8859-1 ISO Latin 1 */ + XML_CHAR_ENCODING_8859_2= 11,/* ISO-8859-2 ISO Latin 2 */ + XML_CHAR_ENCODING_8859_3= 12,/* ISO-8859-3 */ + XML_CHAR_ENCODING_8859_4= 13,/* ISO-8859-4 */ + XML_CHAR_ENCODING_8859_5= 14,/* ISO-8859-5 */ + XML_CHAR_ENCODING_8859_6= 15,/* ISO-8859-6 */ + XML_CHAR_ENCODING_8859_7= 16,/* ISO-8859-7 */ + XML_CHAR_ENCODING_8859_8= 17,/* ISO-8859-8 */ + XML_CHAR_ENCODING_8859_9= 18,/* ISO-8859-9 */ + XML_CHAR_ENCODING_2022_JP= 19,/* ISO-2022-JP */ + XML_CHAR_ENCODING_SHIFT_JIS=20,/* Shift_JIS */ + XML_CHAR_ENCODING_EUC_JP= 21,/* EUC-JP */ + XML_CHAR_ENCODING_ASCII= 22 /* pure ASCII */ +} xmlCharEncoding; + +/** + * xmlCharEncodingInputFunc: + * @out: a pointer to an array of bytes to store the UTF-8 result + * @outlen: the length of @out + * @in: a pointer to an array of chars in the original encoding + * @inlen: the length of @in + * + * Take a block of chars in the original encoding and try to convert + * it to an UTF-8 block of chars out. + * + * Returns the number of bytes written, -1 if lack of space, or -2 + * if the transcoding failed. + * The value of @inlen after return is the number of octets consumed + * if the return value is positive, else unpredictiable. + * The value of @outlen after return is the number of octets consumed. + */ +typedef int (* xmlCharEncodingInputFunc)(unsigned char *out, int *outlen, + const unsigned char *in, int *inlen); + + +/** + * xmlCharEncodingOutputFunc: + * @out: a pointer to an array of bytes to store the result + * @outlen: the length of @out + * @in: a pointer to an array of UTF-8 chars + * @inlen: the length of @in + * + * Take a block of UTF-8 chars in and try to convert it to another + * encoding. + * Note: a first call designed to produce heading info is called with + * in = NULL. If stateful this should also initialize the encoder state. + * + * Returns the number of bytes written, -1 if lack of space, or -2 + * if the transcoding failed. + * The value of @inlen after return is the number of octets consumed + * if the return value is positive, else unpredictiable. + * The value of @outlen after return is the number of octets produced. + */ +typedef int (* xmlCharEncodingOutputFunc)(unsigned char *out, int *outlen, + const unsigned char *in, int *inlen); + + +/* + * Block defining the handlers for non UTF-8 encodings. + * If iconv is supported, there are two extra fields. + */ + +typedef struct _xmlCharEncodingHandler xmlCharEncodingHandler; +typedef xmlCharEncodingHandler *xmlCharEncodingHandlerPtr; +struct _xmlCharEncodingHandler { + char *name; + xmlCharEncodingInputFunc input; + xmlCharEncodingOutputFunc output; +#ifdef LIBXML_ICONV_ENABLED + iconv_t iconv_in; + iconv_t iconv_out; +#endif /* LIBXML_ICONV_ENABLED */ +}; + +#ifdef __cplusplus +} +#endif +#include +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Interfaces for encoding handlers. + */ +XMLPUBFUN void XMLCALL + xmlInitCharEncodingHandlers (void); +XMLPUBFUN void XMLCALL + xmlCleanupCharEncodingHandlers (void); +XMLPUBFUN void XMLCALL + xmlRegisterCharEncodingHandler (xmlCharEncodingHandlerPtr handler); +XMLPUBFUN xmlCharEncodingHandlerPtr XMLCALL + xmlGetCharEncodingHandler (xmlCharEncoding enc); +XMLPUBFUN xmlCharEncodingHandlerPtr XMLCALL + xmlFindCharEncodingHandler (const char *name); +XMLPUBFUN xmlCharEncodingHandlerPtr XMLCALL + xmlNewCharEncodingHandler (const char *name, + xmlCharEncodingInputFunc input, + xmlCharEncodingOutputFunc output); + +/* + * Interfaces for encoding names and aliases. + */ +XMLPUBFUN int XMLCALL + xmlAddEncodingAlias (const char *name, + const char *alias); +XMLPUBFUN int XMLCALL + xmlDelEncodingAlias (const char *alias); +XMLPUBFUN const char * XMLCALL + xmlGetEncodingAlias (const char *alias); +XMLPUBFUN void XMLCALL + xmlCleanupEncodingAliases (void); +XMLPUBFUN xmlCharEncoding XMLCALL + xmlParseCharEncoding (const char *name); +XMLPUBFUN const char * XMLCALL + xmlGetCharEncodingName (xmlCharEncoding enc); + +/* + * Interfaces directly used by the parsers. + */ +XMLPUBFUN xmlCharEncoding XMLCALL + xmlDetectCharEncoding (const unsigned char *in, + int len); + +XMLPUBFUN int XMLCALL + xmlCharEncOutFunc (xmlCharEncodingHandler *handler, + xmlBufferPtr out, + xmlBufferPtr in); + +XMLPUBFUN int XMLCALL + xmlCharEncInFunc (xmlCharEncodingHandler *handler, + xmlBufferPtr out, + xmlBufferPtr in); +XMLPUBFUN int XMLCALL + xmlCharEncFirstLine (xmlCharEncodingHandler *handler, + xmlBufferPtr out, + xmlBufferPtr in); +XMLPUBFUN int XMLCALL + xmlCharEncCloseFunc (xmlCharEncodingHandler *handler); + +/* + * Export a few useful functions + */ +#ifdef LIBXML_OUTPUT_ENABLED +XMLPUBFUN int XMLCALL + UTF8Toisolat1 (unsigned char *out, + int *outlen, + const unsigned char *in, + int *inlen); +#endif /* LIBXML_OUTPUT_ENABLED */ +XMLPUBFUN int XMLCALL + isolat1ToUTF8 (unsigned char *out, + int *outlen, + const unsigned char *in, + int *inlen); +#ifdef __cplusplus +} +#endif + +#endif /* __XML_CHAR_ENCODING_H__ */ diff --git a/gettext-tools/gnulib-lib/libxml/entities.c b/gettext-tools/gnulib-lib/libxml/entities.c new file mode 100644 index 0000000..91a3978 --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/entities.c @@ -0,0 +1,966 @@ +/* + * entities.c : implementation for the XML entities handling + * + * See Copyright for the status of this software. + * + * daniel@veillard.com + */ + +#define IN_LIBXML +#include "libxml.h" + +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * The XML predefined entities. + */ + +static xmlEntity xmlEntityLt = { + NULL, XML_ENTITY_DECL, BAD_CAST "lt", + NULL, NULL, NULL, NULL, NULL, NULL, + BAD_CAST "<", BAD_CAST "<", 1, + XML_INTERNAL_PREDEFINED_ENTITY, + NULL, NULL, NULL, NULL, 0, 1 +}; +static xmlEntity xmlEntityGt = { + NULL, XML_ENTITY_DECL, BAD_CAST "gt", + NULL, NULL, NULL, NULL, NULL, NULL, + BAD_CAST ">", BAD_CAST ">", 1, + XML_INTERNAL_PREDEFINED_ENTITY, + NULL, NULL, NULL, NULL, 0, 1 +}; +static xmlEntity xmlEntityAmp = { + NULL, XML_ENTITY_DECL, BAD_CAST "amp", + NULL, NULL, NULL, NULL, NULL, NULL, + BAD_CAST "&", BAD_CAST "&", 1, + XML_INTERNAL_PREDEFINED_ENTITY, + NULL, NULL, NULL, NULL, 0, 1 +}; +static xmlEntity xmlEntityQuot = { + NULL, XML_ENTITY_DECL, BAD_CAST "quot", + NULL, NULL, NULL, NULL, NULL, NULL, + BAD_CAST "\"", BAD_CAST "\"", 1, + XML_INTERNAL_PREDEFINED_ENTITY, + NULL, NULL, NULL, NULL, 0, 1 +}; +static xmlEntity xmlEntityApos = { + NULL, XML_ENTITY_DECL, BAD_CAST "apos", + NULL, NULL, NULL, NULL, NULL, NULL, + BAD_CAST "'", BAD_CAST "'", 1, + XML_INTERNAL_PREDEFINED_ENTITY, + NULL, NULL, NULL, NULL, 0, 1 +}; + +/** + * xmlEntitiesErrMemory: + * @extra: extra informations + * + * Handle an out of memory condition + */ +static void +xmlEntitiesErrMemory(const char *extra) +{ + __xmlSimpleError(XML_FROM_TREE, XML_ERR_NO_MEMORY, NULL, NULL, extra); +} + +/** + * xmlEntitiesErr: + * @code: the error code + * @msg: the message + * + * Handle an out of memory condition + */ +static void +xmlEntitiesErr(xmlParserErrors code, const char *msg) +{ + __xmlSimpleError(XML_FROM_TREE, code, NULL, msg, NULL); +} + +/* + * xmlFreeEntity : clean-up an entity record. + */ +static void +xmlFreeEntity(xmlEntityPtr entity) +{ + xmlDictPtr dict = NULL; + + if (entity == NULL) + return; + + if (entity->doc != NULL) + dict = entity->doc->dict; + + + if ((entity->children) && (entity->owner == 1) && + (entity == (xmlEntityPtr) entity->children->parent)) + xmlFreeNodeList(entity->children); + if (dict != NULL) { + if ((entity->name != NULL) && (!xmlDictOwns(dict, entity->name))) + xmlFree((char *) entity->name); + if ((entity->ExternalID != NULL) && + (!xmlDictOwns(dict, entity->ExternalID))) + xmlFree((char *) entity->ExternalID); + if ((entity->SystemID != NULL) && + (!xmlDictOwns(dict, entity->SystemID))) + xmlFree((char *) entity->SystemID); + if ((entity->URI != NULL) && (!xmlDictOwns(dict, entity->URI))) + xmlFree((char *) entity->URI); + if ((entity->content != NULL) + && (!xmlDictOwns(dict, entity->content))) + xmlFree((char *) entity->content); + if ((entity->orig != NULL) && (!xmlDictOwns(dict, entity->orig))) + xmlFree((char *) entity->orig); + } else { + if (entity->name != NULL) + xmlFree((char *) entity->name); + if (entity->ExternalID != NULL) + xmlFree((char *) entity->ExternalID); + if (entity->SystemID != NULL) + xmlFree((char *) entity->SystemID); + if (entity->URI != NULL) + xmlFree((char *) entity->URI); + if (entity->content != NULL) + xmlFree((char *) entity->content); + if (entity->orig != NULL) + xmlFree((char *) entity->orig); + } + xmlFree(entity); +} + +/* + * xmlAddEntity : register a new entity for an entities table. + */ +static xmlEntityPtr +xmlAddEntity(xmlDtdPtr dtd, const xmlChar *name, int type, + const xmlChar *ExternalID, const xmlChar *SystemID, + const xmlChar *content) { + xmlDictPtr dict = NULL; + xmlEntitiesTablePtr table = NULL; + xmlEntityPtr ret; + + if (name == NULL) + return(NULL); + if (dtd == NULL) + return(NULL); + if (dtd->doc != NULL) + dict = dtd->doc->dict; + + switch (type) { + case XML_INTERNAL_GENERAL_ENTITY: + case XML_EXTERNAL_GENERAL_PARSED_ENTITY: + case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY: + if (dtd->entities == NULL) + dtd->entities = xmlHashCreateDict(0, dict); + table = dtd->entities; + break; + case XML_INTERNAL_PARAMETER_ENTITY: + case XML_EXTERNAL_PARAMETER_ENTITY: + if (dtd->pentities == NULL) + dtd->pentities = xmlHashCreateDict(0, dict); + table = dtd->pentities; + break; + case XML_INTERNAL_PREDEFINED_ENTITY: + return(NULL); + } + if (table == NULL) + return(NULL); + ret = (xmlEntityPtr) xmlMalloc(sizeof(xmlEntity)); + if (ret == NULL) { + xmlEntitiesErrMemory("xmlAddEntity:: malloc failed"); + return(NULL); + } + memset(ret, 0, sizeof(xmlEntity)); + ret->type = XML_ENTITY_DECL; + ret->checked = 0; + + /* + * fill the structure. + */ + ret->etype = (xmlEntityType) type; + if (dict == NULL) { + ret->name = xmlStrdup(name); + if (ExternalID != NULL) + ret->ExternalID = xmlStrdup(ExternalID); + if (SystemID != NULL) + ret->SystemID = xmlStrdup(SystemID); + } else { + ret->name = xmlDictLookup(dict, name, -1); + if (ExternalID != NULL) + ret->ExternalID = xmlDictLookup(dict, ExternalID, -1); + if (SystemID != NULL) + ret->SystemID = xmlDictLookup(dict, SystemID, -1); + } + if (content != NULL) { + ret->length = xmlStrlen(content); + if ((dict != NULL) && (ret->length < 5)) + ret->content = (xmlChar *) + xmlDictLookup(dict, content, ret->length); + else + ret->content = xmlStrndup(content, ret->length); + } else { + ret->length = 0; + ret->content = NULL; + } + ret->URI = NULL; /* to be computed by the layer knowing + the defining entity */ + ret->orig = NULL; + ret->owner = 0; + ret->doc = dtd->doc; + + if (xmlHashAddEntry(table, name, ret)) { + /* + * entity was already defined at another level. + */ + xmlFreeEntity(ret); + return(NULL); + } + return(ret); +} + +/** + * xmlGetPredefinedEntity: + * @name: the entity name + * + * Check whether this name is an predefined entity. + * + * Returns NULL if not, otherwise the entity + */ +xmlEntityPtr +xmlGetPredefinedEntity(const xmlChar *name) { + if (name == NULL) return(NULL); + switch (name[0]) { + case 'l': + if (xmlStrEqual(name, BAD_CAST "lt")) + return(&xmlEntityLt); + break; + case 'g': + if (xmlStrEqual(name, BAD_CAST "gt")) + return(&xmlEntityGt); + break; + case 'a': + if (xmlStrEqual(name, BAD_CAST "amp")) + return(&xmlEntityAmp); + if (xmlStrEqual(name, BAD_CAST "apos")) + return(&xmlEntityApos); + break; + case 'q': + if (xmlStrEqual(name, BAD_CAST "quot")) + return(&xmlEntityQuot); + break; + default: + break; + } + return(NULL); +} + +/** + * xmlAddDtdEntity: + * @doc: the document + * @name: the entity name + * @type: the entity type XML_xxx_yyy_ENTITY + * @ExternalID: the entity external ID if available + * @SystemID: the entity system ID if available + * @content: the entity content + * + * Register a new entity for this document DTD external subset. + * + * Returns a pointer to the entity or NULL in case of error + */ +xmlEntityPtr +xmlAddDtdEntity(xmlDocPtr doc, const xmlChar *name, int type, + const xmlChar *ExternalID, const xmlChar *SystemID, + const xmlChar *content) { + xmlEntityPtr ret; + xmlDtdPtr dtd; + + if (doc == NULL) { + xmlEntitiesErr(XML_DTD_NO_DOC, + "xmlAddDtdEntity: document is NULL"); + return(NULL); + } + if (doc->extSubset == NULL) { + xmlEntitiesErr(XML_DTD_NO_DTD, + "xmlAddDtdEntity: document without external subset"); + return(NULL); + } + dtd = doc->extSubset; + ret = xmlAddEntity(dtd, name, type, ExternalID, SystemID, content); + if (ret == NULL) return(NULL); + + /* + * Link it to the DTD + */ + ret->parent = dtd; + ret->doc = dtd->doc; + if (dtd->last == NULL) { + dtd->children = dtd->last = (xmlNodePtr) ret; + } else { + dtd->last->next = (xmlNodePtr) ret; + ret->prev = dtd->last; + dtd->last = (xmlNodePtr) ret; + } + return(ret); +} + +/** + * xmlAddDocEntity: + * @doc: the document + * @name: the entity name + * @type: the entity type XML_xxx_yyy_ENTITY + * @ExternalID: the entity external ID if available + * @SystemID: the entity system ID if available + * @content: the entity content + * + * Register a new entity for this document. + * + * Returns a pointer to the entity or NULL in case of error + */ +xmlEntityPtr +xmlAddDocEntity(xmlDocPtr doc, const xmlChar *name, int type, + const xmlChar *ExternalID, const xmlChar *SystemID, + const xmlChar *content) { + xmlEntityPtr ret; + xmlDtdPtr dtd; + + if (doc == NULL) { + xmlEntitiesErr(XML_DTD_NO_DOC, + "xmlAddDocEntity: document is NULL"); + return(NULL); + } + if (doc->intSubset == NULL) { + xmlEntitiesErr(XML_DTD_NO_DTD, + "xmlAddDocEntity: document without internal subset"); + return(NULL); + } + dtd = doc->intSubset; + ret = xmlAddEntity(dtd, name, type, ExternalID, SystemID, content); + if (ret == NULL) return(NULL); + + /* + * Link it to the DTD + */ + ret->parent = dtd; + ret->doc = dtd->doc; + if (dtd->last == NULL) { + dtd->children = dtd->last = (xmlNodePtr) ret; + } else { + dtd->last->next = (xmlNodePtr) ret; + ret->prev = dtd->last; + dtd->last = (xmlNodePtr) ret; + } + return(ret); +} + +/** + * xmlGetEntityFromTable: + * @table: an entity table + * @name: the entity name + * @parameter: look for parameter entities + * + * Do an entity lookup in the table. + * returns the corresponding parameter entity, if found. + * + * Returns A pointer to the entity structure or NULL if not found. + */ +static xmlEntityPtr +xmlGetEntityFromTable(xmlEntitiesTablePtr table, const xmlChar *name) { + return((xmlEntityPtr) xmlHashLookup(table, name)); +} + +/** + * xmlGetParameterEntity: + * @doc: the document referencing the entity + * @name: the entity name + * + * Do an entity lookup in the internal and external subsets and + * returns the corresponding parameter entity, if found. + * + * Returns A pointer to the entity structure or NULL if not found. + */ +xmlEntityPtr +xmlGetParameterEntity(xmlDocPtr doc, const xmlChar *name) { + xmlEntitiesTablePtr table; + xmlEntityPtr ret; + + if (doc == NULL) + return(NULL); + if ((doc->intSubset != NULL) && (doc->intSubset->pentities != NULL)) { + table = (xmlEntitiesTablePtr) doc->intSubset->pentities; + ret = xmlGetEntityFromTable(table, name); + if (ret != NULL) + return(ret); + } + if ((doc->extSubset != NULL) && (doc->extSubset->pentities != NULL)) { + table = (xmlEntitiesTablePtr) doc->extSubset->pentities; + return(xmlGetEntityFromTable(table, name)); + } + return(NULL); +} + +/** + * xmlGetDtdEntity: + * @doc: the document referencing the entity + * @name: the entity name + * + * Do an entity lookup in the DTD entity hash table and + * returns the corresponding entity, if found. + * Note: the first argument is the document node, not the DTD node. + * + * Returns A pointer to the entity structure or NULL if not found. + */ +xmlEntityPtr +xmlGetDtdEntity(xmlDocPtr doc, const xmlChar *name) { + xmlEntitiesTablePtr table; + + if (doc == NULL) + return(NULL); + if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) { + table = (xmlEntitiesTablePtr) doc->extSubset->entities; + return(xmlGetEntityFromTable(table, name)); + } + return(NULL); +} + +/** + * xmlGetDocEntity: + * @doc: the document referencing the entity + * @name: the entity name + * + * Do an entity lookup in the document entity hash table and + * returns the corresponding entity, otherwise a lookup is done + * in the predefined entities too. + * + * Returns A pointer to the entity structure or NULL if not found. + */ +xmlEntityPtr +xmlGetDocEntity(xmlDocPtr doc, const xmlChar *name) { + xmlEntityPtr cur; + xmlEntitiesTablePtr table; + + if (doc != NULL) { + if ((doc->intSubset != NULL) && (doc->intSubset->entities != NULL)) { + table = (xmlEntitiesTablePtr) doc->intSubset->entities; + cur = xmlGetEntityFromTable(table, name); + if (cur != NULL) + return(cur); + } + if (doc->standalone != 1) { + if ((doc->extSubset != NULL) && + (doc->extSubset->entities != NULL)) { + table = (xmlEntitiesTablePtr) doc->extSubset->entities; + cur = xmlGetEntityFromTable(table, name); + if (cur != NULL) + return(cur); + } + } + } + return(xmlGetPredefinedEntity(name)); +} + +/* + * Macro used to grow the current buffer. + */ +#define growBufferReentrant() { \ + buffer_size *= 2; \ + buffer = (xmlChar *) \ + xmlRealloc(buffer, buffer_size * sizeof(xmlChar)); \ + if (buffer == NULL) { \ + xmlEntitiesErrMemory("xmlEncodeEntitiesReentrant: realloc failed");\ + return(NULL); \ + } \ +} + + +/** + * xmlEncodeEntitiesReentrant: + * @doc: the document containing the string + * @input: A string to convert to XML. + * + * Do a global encoding of a string, replacing the predefined entities + * and non ASCII values with their entities and CharRef counterparts. + * Contrary to xmlEncodeEntities, this routine is reentrant, and result + * must be deallocated. + * + * Returns A newly allocated string with the substitution done. + */ +xmlChar * +xmlEncodeEntitiesReentrant(xmlDocPtr doc, const xmlChar *input) { + const xmlChar *cur = input; + xmlChar *buffer = NULL; + xmlChar *out = NULL; + int buffer_size = 0; + int html = 0; + + if (input == NULL) return(NULL); + if (doc != NULL) + html = (doc->type == XML_HTML_DOCUMENT_NODE); + + /* + * allocate an translation buffer. + */ + buffer_size = 1000; + buffer = (xmlChar *) xmlMalloc(buffer_size * sizeof(xmlChar)); + if (buffer == NULL) { + xmlEntitiesErrMemory("xmlEncodeEntitiesReentrant: malloc failed"); + return(NULL); + } + out = buffer; + + while (*cur != '\0') { + if (out - buffer > buffer_size - 100) { + int indx = out - buffer; + + growBufferReentrant(); + out = &buffer[indx]; + } + + /* + * By default one have to encode at least '<', '>', '"' and '&' ! + */ + if (*cur == '<') { + *out++ = '&'; + *out++ = 'l'; + *out++ = 't'; + *out++ = ';'; + } else if (*cur == '>') { + *out++ = '&'; + *out++ = 'g'; + *out++ = 't'; + *out++ = ';'; + } else if (*cur == '&') { + *out++ = '&'; + *out++ = 'a'; + *out++ = 'm'; + *out++ = 'p'; + *out++ = ';'; + } else if (((*cur >= 0x20) && (*cur < 0x80)) || + (*cur == '\n') || (*cur == '\t') || ((html) && (*cur == '\r'))) { + /* + * default case, just copy ! + */ + *out++ = *cur; + } else if (*cur >= 0x80) { + if (((doc != NULL) && (doc->encoding != NULL)) || (html)) { + /* + * Bjørn Reese provided the patch + xmlChar xc; + xc = (*cur & 0x3F) << 6; + if (cur[1] != 0) { + xc += *(++cur) & 0x3F; + *out++ = xc; + } else + */ + *out++ = *cur; + } else { + /* + * We assume we have UTF-8 input. + */ + char buf[11], *ptr; + int val = 0, l = 1; + + if (*cur < 0xC0) { + xmlEntitiesErr(XML_CHECK_NOT_UTF8, + "xmlEncodeEntitiesReentrant : input not UTF-8"); + if (doc != NULL) + doc->encoding = xmlStrdup(BAD_CAST "ISO-8859-1"); + snprintf(buf, sizeof(buf), "&#%d;", *cur); + buf[sizeof(buf) - 1] = 0; + ptr = buf; + while (*ptr != 0) *out++ = *ptr++; + cur++; + continue; + } else if (*cur < 0xE0) { + val = (cur[0]) & 0x1F; + val <<= 6; + val |= (cur[1]) & 0x3F; + l = 2; + } else if (*cur < 0xF0) { + val = (cur[0]) & 0x0F; + val <<= 6; + val |= (cur[1]) & 0x3F; + val <<= 6; + val |= (cur[2]) & 0x3F; + l = 3; + } else if (*cur < 0xF8) { + val = (cur[0]) & 0x07; + val <<= 6; + val |= (cur[1]) & 0x3F; + val <<= 6; + val |= (cur[2]) & 0x3F; + val <<= 6; + val |= (cur[3]) & 0x3F; + l = 4; + } + if ((l == 1) || (!IS_CHAR(val))) { + xmlEntitiesErr(XML_ERR_INVALID_CHAR, + "xmlEncodeEntitiesReentrant : char out of range\n"); + if (doc != NULL) + doc->encoding = xmlStrdup(BAD_CAST "ISO-8859-1"); + snprintf(buf, sizeof(buf), "&#%d;", *cur); + buf[sizeof(buf) - 1] = 0; + ptr = buf; + while (*ptr != 0) *out++ = *ptr++; + cur++; + continue; + } + /* + * We could do multiple things here. Just save as a char ref + */ + snprintf(buf, sizeof(buf), "&#x%X;", val); + buf[sizeof(buf) - 1] = 0; + ptr = buf; + while (*ptr != 0) *out++ = *ptr++; + cur += l; + continue; + } + } else if (IS_BYTE_CHAR(*cur)) { + char buf[11], *ptr; + + snprintf(buf, sizeof(buf), "&#%d;", *cur); + buf[sizeof(buf) - 1] = 0; + ptr = buf; + while (*ptr != 0) *out++ = *ptr++; + } + cur++; + } + *out++ = 0; + return(buffer); +} + +/** + * xmlEncodeSpecialChars: + * @doc: the document containing the string + * @input: A string to convert to XML. + * + * Do a global encoding of a string, replacing the predefined entities + * this routine is reentrant, and result must be deallocated. + * + * Returns A newly allocated string with the substitution done. + */ +xmlChar * +xmlEncodeSpecialChars(xmlDocPtr doc ATTRIBUTE_UNUSED, const xmlChar *input) { + const xmlChar *cur = input; + xmlChar *buffer = NULL; + xmlChar *out = NULL; + int buffer_size = 0; + if (input == NULL) return(NULL); + + /* + * allocate an translation buffer. + */ + buffer_size = 1000; + buffer = (xmlChar *) xmlMalloc(buffer_size * sizeof(xmlChar)); + if (buffer == NULL) { + xmlEntitiesErrMemory("xmlEncodeSpecialChars: malloc failed"); + return(NULL); + } + out = buffer; + + while (*cur != '\0') { + if (out - buffer > buffer_size - 10) { + int indx = out - buffer; + + growBufferReentrant(); + out = &buffer[indx]; + } + + /* + * By default one have to encode at least '<', '>', '"' and '&' ! + */ + if (*cur == '<') { + *out++ = '&'; + *out++ = 'l'; + *out++ = 't'; + *out++ = ';'; + } else if (*cur == '>') { + *out++ = '&'; + *out++ = 'g'; + *out++ = 't'; + *out++ = ';'; + } else if (*cur == '&') { + *out++ = '&'; + *out++ = 'a'; + *out++ = 'm'; + *out++ = 'p'; + *out++ = ';'; + } else if (*cur == '"') { + *out++ = '&'; + *out++ = 'q'; + *out++ = 'u'; + *out++ = 'o'; + *out++ = 't'; + *out++ = ';'; + } else if (*cur == '\r') { + *out++ = '&'; + *out++ = '#'; + *out++ = '1'; + *out++ = '3'; + *out++ = ';'; + } else { + /* + * Works because on UTF-8, all extended sequences cannot + * result in bytes in the ASCII range. + */ + *out++ = *cur; + } + cur++; + } + *out++ = 0; + return(buffer); +} + +/** + * xmlCreateEntitiesTable: + * + * create and initialize an empty entities hash table. + * This really doesn't make sense and should be deprecated + * + * Returns the xmlEntitiesTablePtr just created or NULL in case of error. + */ +xmlEntitiesTablePtr +xmlCreateEntitiesTable(void) { + return((xmlEntitiesTablePtr) xmlHashCreate(0)); +} + +/** + * xmlFreeEntityWrapper: + * @entity: An entity + * @name: its name + * + * Deallocate the memory used by an entities in the hash table. + */ +static void +xmlFreeEntityWrapper(xmlEntityPtr entity, + const xmlChar *name ATTRIBUTE_UNUSED) { + if (entity != NULL) + xmlFreeEntity(entity); +} + +/** + * xmlFreeEntitiesTable: + * @table: An entity table + * + * Deallocate the memory used by an entities hash table. + */ +void +xmlFreeEntitiesTable(xmlEntitiesTablePtr table) { + xmlHashFree(table, (xmlHashDeallocator) xmlFreeEntityWrapper); +} + +#ifdef LIBXML_TREE_ENABLED +/** + * xmlCopyEntity: + * @ent: An entity + * + * Build a copy of an entity + * + * Returns the new xmlEntitiesPtr or NULL in case of error. + */ +static xmlEntityPtr +xmlCopyEntity(xmlEntityPtr ent) { + xmlEntityPtr cur; + + cur = (xmlEntityPtr) xmlMalloc(sizeof(xmlEntity)); + if (cur == NULL) { + xmlEntitiesErrMemory("xmlCopyEntity:: malloc failed"); + return(NULL); + } + memset(cur, 0, sizeof(xmlEntity)); + cur->type = XML_ENTITY_DECL; + + cur->etype = ent->etype; + if (ent->name != NULL) + cur->name = xmlStrdup(ent->name); + if (ent->ExternalID != NULL) + cur->ExternalID = xmlStrdup(ent->ExternalID); + if (ent->SystemID != NULL) + cur->SystemID = xmlStrdup(ent->SystemID); + if (ent->content != NULL) + cur->content = xmlStrdup(ent->content); + if (ent->orig != NULL) + cur->orig = xmlStrdup(ent->orig); + if (ent->URI != NULL) + cur->URI = xmlStrdup(ent->URI); + return(cur); +} + +/** + * xmlCopyEntitiesTable: + * @table: An entity table + * + * Build a copy of an entity table. + * + * Returns the new xmlEntitiesTablePtr or NULL in case of error. + */ +xmlEntitiesTablePtr +xmlCopyEntitiesTable(xmlEntitiesTablePtr table) { + return(xmlHashCopy(table, (xmlHashCopier) xmlCopyEntity)); +} +#endif /* LIBXML_TREE_ENABLED */ + +#ifdef LIBXML_OUTPUT_ENABLED + +/** + * xmlDumpEntityContent: + * @buf: An XML buffer. + * @content: The entity content. + * + * This will dump the quoted string value, taking care of the special + * treatment required by % + */ +static void +xmlDumpEntityContent(xmlBufferPtr buf, const xmlChar *content) { + if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return; + if (xmlStrchr(content, '%')) { + const xmlChar * base, *cur; + + xmlBufferCCat(buf, "\""); + base = cur = content; + while (*cur != 0) { + if (*cur == '"') { + if (base != cur) + xmlBufferAdd(buf, base, cur - base); + xmlBufferAdd(buf, BAD_CAST """, 6); + cur++; + base = cur; + } else if (*cur == '%') { + if (base != cur) + xmlBufferAdd(buf, base, cur - base); + xmlBufferAdd(buf, BAD_CAST "%", 6); + cur++; + base = cur; + } else { + cur++; + } + } + if (base != cur) + xmlBufferAdd(buf, base, cur - base); + xmlBufferCCat(buf, "\""); + } else { + xmlBufferWriteQuotedString(buf, content); + } +} + +/** + * xmlDumpEntityDecl: + * @buf: An XML buffer. + * @ent: An entity table + * + * This will dump the content of the entity table as an XML DTD definition + */ +void +xmlDumpEntityDecl(xmlBufferPtr buf, xmlEntityPtr ent) { + if ((buf == NULL) || (ent == NULL)) return; + switch (ent->etype) { + case XML_INTERNAL_GENERAL_ENTITY: + xmlBufferWriteChar(buf, "name); + xmlBufferWriteChar(buf, " "); + if (ent->orig != NULL) + xmlBufferWriteQuotedString(buf, ent->orig); + else + xmlDumpEntityContent(buf, ent->content); + xmlBufferWriteChar(buf, ">\n"); + break; + case XML_EXTERNAL_GENERAL_PARSED_ENTITY: + xmlBufferWriteChar(buf, "name); + if (ent->ExternalID != NULL) { + xmlBufferWriteChar(buf, " PUBLIC "); + xmlBufferWriteQuotedString(buf, ent->ExternalID); + xmlBufferWriteChar(buf, " "); + xmlBufferWriteQuotedString(buf, ent->SystemID); + } else { + xmlBufferWriteChar(buf, " SYSTEM "); + xmlBufferWriteQuotedString(buf, ent->SystemID); + } + xmlBufferWriteChar(buf, ">\n"); + break; + case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY: + xmlBufferWriteChar(buf, "name); + if (ent->ExternalID != NULL) { + xmlBufferWriteChar(buf, " PUBLIC "); + xmlBufferWriteQuotedString(buf, ent->ExternalID); + xmlBufferWriteChar(buf, " "); + xmlBufferWriteQuotedString(buf, ent->SystemID); + } else { + xmlBufferWriteChar(buf, " SYSTEM "); + xmlBufferWriteQuotedString(buf, ent->SystemID); + } + if (ent->content != NULL) { /* Should be true ! */ + xmlBufferWriteChar(buf, " NDATA "); + if (ent->orig != NULL) + xmlBufferWriteCHAR(buf, ent->orig); + else + xmlBufferWriteCHAR(buf, ent->content); + } + xmlBufferWriteChar(buf, ">\n"); + break; + case XML_INTERNAL_PARAMETER_ENTITY: + xmlBufferWriteChar(buf, "name); + xmlBufferWriteChar(buf, " "); + if (ent->orig == NULL) + xmlDumpEntityContent(buf, ent->content); + else + xmlBufferWriteQuotedString(buf, ent->orig); + xmlBufferWriteChar(buf, ">\n"); + break; + case XML_EXTERNAL_PARAMETER_ENTITY: + xmlBufferWriteChar(buf, "name); + if (ent->ExternalID != NULL) { + xmlBufferWriteChar(buf, " PUBLIC "); + xmlBufferWriteQuotedString(buf, ent->ExternalID); + xmlBufferWriteChar(buf, " "); + xmlBufferWriteQuotedString(buf, ent->SystemID); + } else { + xmlBufferWriteChar(buf, " SYSTEM "); + xmlBufferWriteQuotedString(buf, ent->SystemID); + } + xmlBufferWriteChar(buf, ">\n"); + break; + default: + xmlEntitiesErr(XML_DTD_UNKNOWN_ENTITY, + "xmlDumpEntitiesDecl: internal: unknown type entity type"); + } +} + +/** + * xmlDumpEntityDeclScan: + * @ent: An entity table + * @buf: An XML buffer. + * + * When using the hash table scan function, arguments need to be reversed + */ +static void +xmlDumpEntityDeclScan(xmlEntityPtr ent, xmlBufferPtr buf) { + xmlDumpEntityDecl(buf, ent); +} + +/** + * xmlDumpEntitiesTable: + * @buf: An XML buffer. + * @table: An entity table + * + * This will dump the content of the entity table as an XML DTD definition + */ +void +xmlDumpEntitiesTable(xmlBufferPtr buf, xmlEntitiesTablePtr table) { + xmlHashScan(table, (xmlHashScanner)xmlDumpEntityDeclScan, buf); +} +#endif /* LIBXML_OUTPUT_ENABLED */ +#define bottom_entities +#include "elfgcchack.h" diff --git a/gettext-tools/gnulib-lib/libxml/entities.in.h b/gettext-tools/gnulib-lib/libxml/entities.in.h new file mode 100644 index 0000000..fdd7222 --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/entities.in.h @@ -0,0 +1,140 @@ +/* + * Summary: interface for the XML entities handling + * Description: this module provides some of the entity API needed + * for the parser and applications. + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + +#ifndef __XML_ENTITIES_H__ +#define __XML_ENTITIES_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * The different valid entity types. + */ +typedef enum { + XML_INTERNAL_GENERAL_ENTITY = 1, + XML_EXTERNAL_GENERAL_PARSED_ENTITY = 2, + XML_EXTERNAL_GENERAL_UNPARSED_ENTITY = 3, + XML_INTERNAL_PARAMETER_ENTITY = 4, + XML_EXTERNAL_PARAMETER_ENTITY = 5, + XML_INTERNAL_PREDEFINED_ENTITY = 6 +} xmlEntityType; + +/* + * An unit of storage for an entity, contains the string, the value + * and the linkind data needed for the linking in the hash table. + */ + +struct _xmlEntity { + void *_private; /* application data */ + xmlElementType type; /* XML_ENTITY_DECL, must be second ! */ + const xmlChar *name; /* Entity name */ + struct _xmlNode *children; /* First child link */ + struct _xmlNode *last; /* Last child link */ + struct _xmlDtd *parent; /* -> DTD */ + struct _xmlNode *next; /* next sibling link */ + struct _xmlNode *prev; /* previous sibling link */ + struct _xmlDoc *doc; /* the containing document */ + + xmlChar *orig; /* content without ref substitution */ + xmlChar *content; /* content or ndata if unparsed */ + int length; /* the content length */ + xmlEntityType etype; /* The entity type */ + const xmlChar *ExternalID; /* External identifier for PUBLIC */ + const xmlChar *SystemID; /* URI for a SYSTEM or PUBLIC Entity */ + + struct _xmlEntity *nexte; /* unused */ + const xmlChar *URI; /* the full URI as computed */ + int owner; /* does the entity own the childrens */ + int checked; /* was the entity content checked */ +}; + +/* + * All entities are stored in an hash table. + * There is 2 separate hash tables for global and parameter entities. + */ + +typedef struct _xmlHashTable xmlEntitiesTable; +typedef xmlEntitiesTable *xmlEntitiesTablePtr; + +/* + * External functions: + */ + +#ifdef LIBXML_LEGACY_ENABLED +XMLPUBFUN void XMLCALL + xmlInitializePredefinedEntities (void); +#endif /* LIBXML_LEGACY_ENABLED */ +XMLPUBFUN xmlEntityPtr XMLCALL + xmlAddDocEntity (xmlDocPtr doc, + const xmlChar *name, + int type, + const xmlChar *ExternalID, + const xmlChar *SystemID, + const xmlChar *content); +XMLPUBFUN xmlEntityPtr XMLCALL + xmlAddDtdEntity (xmlDocPtr doc, + const xmlChar *name, + int type, + const xmlChar *ExternalID, + const xmlChar *SystemID, + const xmlChar *content); +XMLPUBFUN xmlEntityPtr XMLCALL + xmlGetPredefinedEntity (const xmlChar *name); +XMLPUBFUN xmlEntityPtr XMLCALL + xmlGetDocEntity (xmlDocPtr doc, + const xmlChar *name); +XMLPUBFUN xmlEntityPtr XMLCALL + xmlGetDtdEntity (xmlDocPtr doc, + const xmlChar *name); +XMLPUBFUN xmlEntityPtr XMLCALL + xmlGetParameterEntity (xmlDocPtr doc, + const xmlChar *name); +#ifdef LIBXML_LEGACY_ENABLED +XMLPUBFUN const xmlChar * XMLCALL + xmlEncodeEntities (xmlDocPtr doc, + const xmlChar *input); +#endif /* LIBXML_LEGACY_ENABLED */ +XMLPUBFUN xmlChar * XMLCALL + xmlEncodeEntitiesReentrant(xmlDocPtr doc, + const xmlChar *input); +XMLPUBFUN xmlChar * XMLCALL + xmlEncodeSpecialChars (xmlDocPtr doc, + const xmlChar *input); +XMLPUBFUN xmlEntitiesTablePtr XMLCALL + xmlCreateEntitiesTable (void); +#ifdef LIBXML_TREE_ENABLED +XMLPUBFUN xmlEntitiesTablePtr XMLCALL + xmlCopyEntitiesTable (xmlEntitiesTablePtr table); +#endif /* LIBXML_TREE_ENABLED */ +XMLPUBFUN void XMLCALL + xmlFreeEntitiesTable (xmlEntitiesTablePtr table); +#ifdef LIBXML_OUTPUT_ENABLED +XMLPUBFUN void XMLCALL + xmlDumpEntitiesTable (xmlBufferPtr buf, + xmlEntitiesTablePtr table); +XMLPUBFUN void XMLCALL + xmlDumpEntityDecl (xmlBufferPtr buf, + xmlEntityPtr ent); +#endif /* LIBXML_OUTPUT_ENABLED */ +#ifdef LIBXML_LEGACY_ENABLED +XMLPUBFUN void XMLCALL + xmlCleanupPredefinedEntities(void); +#endif /* LIBXML_LEGACY_ENABLED */ + + +#ifdef __cplusplus +} +#endif + +# endif /* __XML_ENTITIES_H__ */ diff --git a/gettext-tools/gnulib-lib/libxml/error.c b/gettext-tools/gnulib-lib/libxml/error.c new file mode 100644 index 0000000..722ffbb --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/error.c @@ -0,0 +1,986 @@ +/* + * error.c: module displaying/handling XML parser errors + * + * See Copyright for the status of this software. + * + * Daniel Veillard + */ + +#define IN_LIBXML +#include "libxml.h" + +#include +#include +#include +#include +#include +#include + +void XMLCDECL xmlGenericErrorDefaultFunc (void *ctx ATTRIBUTE_UNUSED, + const char *msg, + ...); + +#define XML_GET_VAR_STR(msg, str) { \ + int size, prev_size = -1; \ + int chars; \ + char *larger; \ + va_list ap; \ + \ + str = (char *) xmlMalloc(150); \ + if (str != NULL) { \ + \ + size = 150; \ + \ + while (1) { \ + va_start(ap, msg); \ + chars = vsnprintf(str, size, msg, ap); \ + va_end(ap); \ + if ((chars > -1) && (chars < size)) { \ + if (prev_size == chars) { \ + break; \ + } else { \ + prev_size = chars; \ + } \ + } \ + if (chars > -1) \ + size += chars + 1; \ + else \ + size += 100; \ + if ((larger = (char *) xmlRealloc(str, size)) == NULL) {\ + break; \ + } \ + str = larger; \ + }} \ +} + +/************************************************************************ + * * + * Handling of out of context errors * + * * + ************************************************************************/ + +/** + * xmlGenericErrorDefaultFunc: + * @ctx: an error context + * @msg: the message to display/transmit + * @...: extra parameters for the message display + * + * Default handler for out of context error messages. + */ +void XMLCDECL +xmlGenericErrorDefaultFunc(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...) { + va_list args; + + if (xmlGenericErrorContext == NULL) + xmlGenericErrorContext = (void *) stderr; + + va_start(args, msg); + vfprintf((FILE *)xmlGenericErrorContext, msg, args); + va_end(args); +} + +/** + * initGenericErrorDefaultFunc: + * @handler: the handler + * + * Set or reset (if NULL) the default handler for generic errors + * to the builtin error function. + */ +void +initGenericErrorDefaultFunc(xmlGenericErrorFunc * handler) +{ + if (handler == NULL) + xmlGenericError = xmlGenericErrorDefaultFunc; + else + xmlGenericError = (*handler); +} + +/** + * xmlSetGenericErrorFunc: + * @ctx: the new error handling context + * @handler: the new handler function + * + * Function to reset the handler and the error context for out of + * context error messages. + * This simply means that @handler will be called for subsequent + * error messages while not parsing nor validating. And @ctx will + * be passed as first argument to @handler + * One can simply force messages to be emitted to another FILE * than + * stderr by setting @ctx to this file handle and @handler to NULL. + * For multi-threaded applications, this must be set separately for each thread. + */ +void +xmlSetGenericErrorFunc(void *ctx, xmlGenericErrorFunc handler) { + xmlGenericErrorContext = ctx; + if (handler != NULL) + xmlGenericError = handler; + else + xmlGenericError = xmlGenericErrorDefaultFunc; +} + +/** + * xmlSetStructuredErrorFunc: + * @ctx: the new error handling context + * @handler: the new handler function + * + * Function to reset the handler and the error context for out of + * context structured error messages. + * This simply means that @handler will be called for subsequent + * error messages while not parsing nor validating. And @ctx will + * be passed as first argument to @handler + * For multi-threaded applications, this must be set separately for each thread. + */ +void +xmlSetStructuredErrorFunc(void *ctx, xmlStructuredErrorFunc handler) { + xmlGenericErrorContext = ctx; + xmlStructuredError = handler; +} + +/************************************************************************ + * * + * Handling of parsing errors * + * * + ************************************************************************/ + +/** + * xmlParserPrintFileInfo: + * @input: an xmlParserInputPtr input + * + * Displays the associated file and line informations for the current input + */ + +void +xmlParserPrintFileInfo(xmlParserInputPtr input) { + if (input != NULL) { + if (input->filename) + xmlGenericError(xmlGenericErrorContext, + "%s:%d: ", input->filename, + input->line); + else + xmlGenericError(xmlGenericErrorContext, + "Entity: line %d: ", input->line); + } +} + +/** + * xmlParserPrintFileContext: + * @input: an xmlParserInputPtr input + * + * Displays current context within the input content for error tracking + */ + +static void +xmlParserPrintFileContextInternal(xmlParserInputPtr input , + xmlGenericErrorFunc channel, void *data ) { + const xmlChar *cur, *base; + unsigned int n, col; /* GCC warns if signed, because compared with sizeof() */ + xmlChar content[81]; /* space for 80 chars + line terminator */ + xmlChar *ctnt; + + if (input == NULL) return; + cur = input->cur; + base = input->base; + /* skip backwards over any end-of-lines */ + while ((cur > base) && ((*(cur) == '\n') || (*(cur) == '\r'))) { + cur--; + } + n = 0; + /* search backwards for beginning-of-line (to max buff size) */ + while ((n++ < (sizeof(content)-1)) && (cur > base) && + (*(cur) != '\n') && (*(cur) != '\r')) + cur--; + if ((*(cur) == '\n') || (*(cur) == '\r')) cur++; + /* calculate the error position in terms of the current position */ + col = input->cur - cur; + /* search forward for end-of-line (to max buff size) */ + n = 0; + ctnt = content; + /* copy selected text to our buffer */ + while ((*cur != 0) && (*(cur) != '\n') && + (*(cur) != '\r') && (n < sizeof(content)-1)) { + *ctnt++ = *cur++; + n++; + } + *ctnt = 0; + /* print out the selected text */ + channel(data ,"%s\n", content); + /* create blank line with problem pointer */ + n = 0; + ctnt = content; + /* (leave buffer space for pointer + line terminator) */ + while ((nfile; + line = err->line; + code = err->code; + domain = err->domain; + level = err->level; + node = err->node; + + if (code == XML_ERR_OK) + return; + + if ((node != NULL) && (node->type == XML_ELEMENT_NODE)) + name = node->name; + + /* + * Maintain the compatibility with the legacy error handling + */ + if (ctxt != NULL) { + input = ctxt->input; + if ((input != NULL) && (input->filename == NULL) && + (ctxt->inputNr > 1)) { + cur = input; + input = ctxt->inputTab[ctxt->inputNr - 2]; + } + if (input != NULL) { + if (input->filename) + channel(data, "%s:%d: ", input->filename, input->line); + else if ((line != 0) && (domain == XML_FROM_PARSER)) + channel(data, "Entity: line %d: ", input->line); + } + } else { + if (file != NULL) + channel(data, "%s:%d: ", file, line); + else if ((line != 0) && (domain == XML_FROM_PARSER)) + channel(data, "Entity: line %d: ", line); + } + if (name != NULL) { + channel(data, "element %s: ", name); + } + switch (domain) { + case XML_FROM_PARSER: + channel(data, "parser "); + break; + case XML_FROM_NAMESPACE: + channel(data, "namespace "); + break; + case XML_FROM_DTD: + case XML_FROM_VALID: + channel(data, "validity "); + break; + case XML_FROM_HTML: + channel(data, "HTML parser "); + break; + case XML_FROM_MEMORY: + channel(data, "memory "); + break; + case XML_FROM_OUTPUT: + channel(data, "output "); + break; + case XML_FROM_IO: + channel(data, "I/O "); + break; + case XML_FROM_XINCLUDE: + channel(data, "XInclude "); + break; + case XML_FROM_XPATH: + channel(data, "XPath "); + break; + case XML_FROM_XPOINTER: + channel(data, "parser "); + break; + case XML_FROM_REGEXP: + channel(data, "regexp "); + break; + case XML_FROM_MODULE: + channel(data, "module "); + break; + case XML_FROM_SCHEMASV: + channel(data, "Schemas validity "); + break; + case XML_FROM_SCHEMASP: + channel(data, "Schemas parser "); + break; + case XML_FROM_RELAXNGP: + channel(data, "Relax-NG parser "); + break; + case XML_FROM_RELAXNGV: + channel(data, "Relax-NG validity "); + break; + case XML_FROM_CATALOG: + channel(data, "Catalog "); + break; + case XML_FROM_C14N: + channel(data, "C14N "); + break; + case XML_FROM_XSLT: + channel(data, "XSLT "); + break; + case XML_FROM_I18N: + channel(data, "encoding "); + break; + default: + break; + } + switch (level) { + case XML_ERR_NONE: + channel(data, ": "); + break; + case XML_ERR_WARNING: + channel(data, "warning : "); + break; + case XML_ERR_ERROR: + channel(data, "error : "); + break; + case XML_ERR_FATAL: + channel(data, "error : "); + break; + } + if (str != NULL) { + int len; + len = xmlStrlen((const xmlChar *)str); + if ((len > 0) && (str[len - 1] != '\n')) + channel(data, "%s\n", str); + else + channel(data, "%s", str); + } else { + channel(data, "%s\n", "out of memory error"); + } + + if (ctxt != NULL) { + xmlParserPrintFileContextInternal(input, channel, data); + if (cur != NULL) { + if (cur->filename) + channel(data, "%s:%d: \n", cur->filename, cur->line); + else if ((line != 0) && (domain == XML_FROM_PARSER)) + channel(data, "Entity: line %d: \n", cur->line); + xmlParserPrintFileContextInternal(cur, channel, data); + } + } + if ((domain == XML_FROM_XPATH) && (err->str1 != NULL) && + (err->int1 < 100) && + (err->int1 < xmlStrlen((const xmlChar *)err->str1))) { + xmlChar buf[150]; + int i; + + channel(data, "%s\n", err->str1); + for (i=0;i < err->int1;i++) + buf[i] = ' '; + buf[i++] = '^'; + buf[i] = 0; + channel(data, "%s\n", buf); + } +} + +/** + * __xmlRaiseError: + * @schannel: the structured callback channel + * @channel: the old callback channel + * @data: the callback data + * @ctx: the parser context or NULL + * @ctx: the parser context or NULL + * @domain: the domain for the error + * @code: the code for the error + * @level: the xmlErrorLevel for the error + * @file: the file source of the error (or NULL) + * @line: the line of the error or 0 if N/A + * @str1: extra string info + * @str2: extra string info + * @str3: extra string info + * @int1: extra int info + * @col: column number of the error or 0 if N/A + * @msg: the message to display/transmit + * @...: extra parameters for the message display + * + * Update the appropriate global or contextual error structure, + * then forward the error message down the parser or generic + * error callback handler + */ +void XMLCDECL +__xmlRaiseError(xmlStructuredErrorFunc schannel, + xmlGenericErrorFunc channel, void *data, void *ctx, + void *nod, int domain, int code, xmlErrorLevel level, + const char *file, int line, const char *str1, + const char *str2, const char *str3, int int1, int col, + const char *msg, ...) +{ + xmlParserCtxtPtr ctxt = NULL; + xmlNodePtr node = (xmlNodePtr) nod; + char *str = NULL; + xmlParserInputPtr input = NULL; + xmlErrorPtr to = &xmlLastError; + xmlNodePtr baseptr = NULL; + + if ((xmlGetWarningsDefaultValue == 0) && (level == XML_ERR_WARNING)) + return; + if ((domain == XML_FROM_PARSER) || (domain == XML_FROM_HTML) || + (domain == XML_FROM_DTD) || (domain == XML_FROM_NAMESPACE) || + (domain == XML_FROM_IO) || (domain == XML_FROM_VALID)) { + ctxt = (xmlParserCtxtPtr) ctx; + if ((schannel == NULL) && (ctxt != NULL) && (ctxt->sax != NULL) && + (ctxt->sax->initialized == XML_SAX2_MAGIC)) + schannel = ctxt->sax->serror; + } + /* + * Check if structured error handler set + */ + if (schannel == NULL) { + schannel = xmlStructuredError; + /* + * if user has defined handler, change data ptr to user's choice + */ + if (schannel != NULL) + data = xmlGenericErrorContext; + } + if ((domain == XML_FROM_VALID) && + ((channel == xmlParserValidityError) || + (channel == xmlParserValidityWarning))) { + ctxt = (xmlParserCtxtPtr) ctx; + if ((schannel == NULL) && (ctxt != NULL) && (ctxt->sax != NULL) && + (ctxt->sax->initialized == XML_SAX2_MAGIC)) + schannel = ctxt->sax->serror; + } + if (code == XML_ERR_OK) + return; + /* + * Formatting the message + */ + if (msg == NULL) { + str = (char *) xmlStrdup(BAD_CAST "No error message provided"); + } else { + XML_GET_VAR_STR(msg, str); + } + + /* + * specific processing if a parser context is provided + */ + if (ctxt != NULL) { + if (file == NULL) { + input = ctxt->input; + if ((input != NULL) && (input->filename == NULL) && + (ctxt->inputNr > 1)) { + input = ctxt->inputTab[ctxt->inputNr - 2]; + } + if (input != NULL) { + file = input->filename; + line = input->line; + col = input->col; + } + } + to = &ctxt->lastError; + } else if ((node != NULL) && (file == NULL)) { + int i; + + if ((node->doc != NULL) && (node->doc->URL != NULL)) { + baseptr = node; +/* file = (const char *) node->doc->URL; */ + } + for (i = 0; + ((i < 10) && (node != NULL) && (node->type != XML_ELEMENT_NODE)); + i++) + node = node->parent; + if ((baseptr == NULL) && (node != NULL) && + (node->doc != NULL) && (node->doc->URL != NULL)) + baseptr = node; + + if ((node != NULL) && (node->type == XML_ELEMENT_NODE)) + line = node->line; + } + + /* + * Save the information about the error + */ + xmlResetError(to); + to->domain = domain; + to->code = code; + to->message = str; + to->level = level; + if (file != NULL) + to->file = (char *) xmlStrdup((const xmlChar *) file); + else if (baseptr != NULL) { +#ifdef LIBXML_XINCLUDE_ENABLED + /* + * We check if the error is within an XInclude section and, + * if so, attempt to print out the href of the XInclude instead + * of the usual "base" (doc->URL) for the node (bug 152623). + */ + xmlNodePtr prev = baseptr; + int inclcount = 0; + while (prev != NULL) { + if (prev->prev == NULL) + prev = prev->parent; + else { + prev = prev->prev; + if (prev->type == XML_XINCLUDE_START) { + if (--inclcount < 0) + break; + } else if (prev->type == XML_XINCLUDE_END) + inclcount++; + } + } + if (prev != NULL) { + if (prev->type == XML_XINCLUDE_START) { + prev->type = XML_ELEMENT_NODE; + to->file = (char *) xmlGetProp(prev, BAD_CAST "href"); + prev->type = XML_XINCLUDE_START; + } else { + to->file = (char *) xmlGetProp(prev, BAD_CAST "href"); + } + } else +#endif + to->file = (char *) xmlStrdup(baseptr->doc->URL); + if ((to->file == NULL) && (node != NULL) && (node->doc != NULL)) { + to->file = (char *) xmlStrdup(node->doc->URL); + } + file = to->file; + } + to->line = line; + if (str1 != NULL) + to->str1 = (char *) xmlStrdup((const xmlChar *) str1); + if (str2 != NULL) + to->str2 = (char *) xmlStrdup((const xmlChar *) str2); + if (str3 != NULL) + to->str3 = (char *) xmlStrdup((const xmlChar *) str3); + to->int1 = int1; + to->int2 = col; + to->node = node; + to->ctxt = ctx; + + if (to != &xmlLastError) + xmlCopyError(to,&xmlLastError); + + /* + * Find the callback channel if channel param is NULL + */ + if ((ctxt != NULL) && (channel == NULL) && (xmlStructuredError == NULL) && (ctxt->sax != NULL)) { + if (level == XML_ERR_WARNING) + channel = ctxt->sax->warning; + else + channel = ctxt->sax->error; + data = ctxt->userData; + } else if (channel == NULL) { + if (xmlStructuredError != NULL) + schannel = xmlStructuredError; + else + channel = xmlGenericError; + if (!data) { + data = xmlGenericErrorContext; + } + } + if (schannel != NULL) { + schannel(data, to); + return; + } + if (channel == NULL) + return; + + if ((channel == xmlParserError) || + (channel == xmlParserWarning) || + (channel == xmlParserValidityError) || + (channel == xmlParserValidityWarning)) + xmlReportError(to, ctxt, str, NULL, NULL); + else if ((channel == (xmlGenericErrorFunc) fprintf) || + (channel == xmlGenericErrorDefaultFunc)) + xmlReportError(to, ctxt, str, channel, data); + else + channel(data, "%s", str); +} + +/** + * __xmlSimpleError: + * @domain: where the error comes from + * @code: the error code + * @node: the context node + * @extra: extra informations + * + * Handle an out of memory condition + */ +void +__xmlSimpleError(int domain, int code, xmlNodePtr node, + const char *msg, const char *extra) +{ + + if (code == XML_ERR_NO_MEMORY) { + if (extra) + __xmlRaiseError(NULL, NULL, NULL, NULL, node, domain, + XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, extra, + NULL, NULL, 0, 0, + "Memory allocation failed : %s\n", extra); + else + __xmlRaiseError(NULL, NULL, NULL, NULL, node, domain, + XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, NULL, + NULL, NULL, 0, 0, "Memory allocation failed\n"); + } else { + __xmlRaiseError(NULL, NULL, NULL, NULL, node, domain, + code, XML_ERR_ERROR, NULL, 0, extra, + NULL, NULL, 0, 0, msg, extra); + } +} +/** + * xmlParserError: + * @ctx: an XML parser context + * @msg: the message to display/transmit + * @...: extra parameters for the message display + * + * Display and format an error messages, gives file, line, position and + * extra parameters. + */ +void XMLCDECL +xmlParserError(void *ctx, const char *msg, ...) +{ + xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; + xmlParserInputPtr input = NULL; + xmlParserInputPtr cur = NULL; + char * str; + + if (ctxt != NULL) { + input = ctxt->input; + if ((input != NULL) && (input->filename == NULL) && + (ctxt->inputNr > 1)) { + cur = input; + input = ctxt->inputTab[ctxt->inputNr - 2]; + } + xmlParserPrintFileInfo(input); + } + + xmlGenericError(xmlGenericErrorContext, "error: "); + XML_GET_VAR_STR(msg, str); + xmlGenericError(xmlGenericErrorContext, "%s", str); + if (str != NULL) + xmlFree(str); + + if (ctxt != NULL) { + xmlParserPrintFileContext(input); + if (cur != NULL) { + xmlParserPrintFileInfo(cur); + xmlGenericError(xmlGenericErrorContext, "\n"); + xmlParserPrintFileContext(cur); + } + } +} + +/** + * xmlParserWarning: + * @ctx: an XML parser context + * @msg: the message to display/transmit + * @...: extra parameters for the message display + * + * Display and format a warning messages, gives file, line, position and + * extra parameters. + */ +void XMLCDECL +xmlParserWarning(void *ctx, const char *msg, ...) +{ + xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; + xmlParserInputPtr input = NULL; + xmlParserInputPtr cur = NULL; + char * str; + + if (ctxt != NULL) { + input = ctxt->input; + if ((input != NULL) && (input->filename == NULL) && + (ctxt->inputNr > 1)) { + cur = input; + input = ctxt->inputTab[ctxt->inputNr - 2]; + } + xmlParserPrintFileInfo(input); + } + + xmlGenericError(xmlGenericErrorContext, "warning: "); + XML_GET_VAR_STR(msg, str); + xmlGenericError(xmlGenericErrorContext, "%s", str); + if (str != NULL) + xmlFree(str); + + if (ctxt != NULL) { + xmlParserPrintFileContext(input); + if (cur != NULL) { + xmlParserPrintFileInfo(cur); + xmlGenericError(xmlGenericErrorContext, "\n"); + xmlParserPrintFileContext(cur); + } + } +} + +/************************************************************************ + * * + * Handling of validation errors * + * * + ************************************************************************/ + +/** + * xmlParserValidityError: + * @ctx: an XML parser context + * @msg: the message to display/transmit + * @...: extra parameters for the message display + * + * Display and format an validity error messages, gives file, + * line, position and extra parameters. + */ +void XMLCDECL +xmlParserValidityError(void *ctx, const char *msg, ...) +{ + xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; + xmlParserInputPtr input = NULL; + char * str; + int len = xmlStrlen((const xmlChar *) msg); + static int had_info = 0; + + if ((len > 1) && (msg[len - 2] != ':')) { + if (ctxt != NULL) { + input = ctxt->input; + if ((input->filename == NULL) && (ctxt->inputNr > 1)) + input = ctxt->inputTab[ctxt->inputNr - 2]; + + if (had_info == 0) { + xmlParserPrintFileInfo(input); + } + } + xmlGenericError(xmlGenericErrorContext, "validity error: "); + had_info = 0; + } else { + had_info = 1; + } + + XML_GET_VAR_STR(msg, str); + xmlGenericError(xmlGenericErrorContext, "%s", str); + if (str != NULL) + xmlFree(str); + + if ((ctxt != NULL) && (input != NULL)) { + xmlParserPrintFileContext(input); + } +} + +/** + * xmlParserValidityWarning: + * @ctx: an XML parser context + * @msg: the message to display/transmit + * @...: extra parameters for the message display + * + * Display and format a validity warning messages, gives file, line, + * position and extra parameters. + */ +void XMLCDECL +xmlParserValidityWarning(void *ctx, const char *msg, ...) +{ + xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; + xmlParserInputPtr input = NULL; + char * str; + int len = xmlStrlen((const xmlChar *) msg); + + if ((ctxt != NULL) && (len != 0) && (msg[len - 1] != ':')) { + input = ctxt->input; + if ((input->filename == NULL) && (ctxt->inputNr > 1)) + input = ctxt->inputTab[ctxt->inputNr - 2]; + + xmlParserPrintFileInfo(input); + } + + xmlGenericError(xmlGenericErrorContext, "validity warning: "); + XML_GET_VAR_STR(msg, str); + xmlGenericError(xmlGenericErrorContext, "%s", str); + if (str != NULL) + xmlFree(str); + + if (ctxt != NULL) { + xmlParserPrintFileContext(input); + } +} + + +/************************************************************************ + * * + * Extended Error Handling * + * * + ************************************************************************/ + +/** + * xmlGetLastError: + * + * Get the last global error registered. This is per thread if compiled + * with thread support. + * + * Returns NULL if no error occured or a pointer to the error + */ +xmlErrorPtr +xmlGetLastError(void) +{ + if (xmlLastError.code == XML_ERR_OK) + return (NULL); + return (&xmlLastError); +} + +/** + * xmlResetError: + * @err: pointer to the error. + * + * Cleanup the error. + */ +void +xmlResetError(xmlErrorPtr err) +{ + if (err == NULL) + return; + if (err->code == XML_ERR_OK) + return; + if (err->message != NULL) + xmlFree(err->message); + if (err->file != NULL) + xmlFree(err->file); + if (err->str1 != NULL) + xmlFree(err->str1); + if (err->str2 != NULL) + xmlFree(err->str2); + if (err->str3 != NULL) + xmlFree(err->str3); + memset(err, 0, sizeof(xmlError)); + err->code = XML_ERR_OK; +} + +/** + * xmlResetLastError: + * + * Cleanup the last global error registered. For parsing error + * this does not change the well-formedness result. + */ +void +xmlResetLastError(void) +{ + if (xmlLastError.code == XML_ERR_OK) + return; + xmlResetError(&xmlLastError); +} + +/** + * xmlCtxtGetLastError: + * @ctx: an XML parser context + * + * Get the last parsing error registered. + * + * Returns NULL if no error occured or a pointer to the error + */ +xmlErrorPtr +xmlCtxtGetLastError(void *ctx) +{ + xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; + + if (ctxt == NULL) + return (NULL); + if (ctxt->lastError.code == XML_ERR_OK) + return (NULL); + return (&ctxt->lastError); +} + +/** + * xmlCtxtResetLastError: + * @ctx: an XML parser context + * + * Cleanup the last global error registered. For parsing error + * this does not change the well-formedness result. + */ +void +xmlCtxtResetLastError(void *ctx) +{ + xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; + + if (ctxt == NULL) + return; + if (ctxt->lastError.code == XML_ERR_OK) + return; + xmlResetError(&ctxt->lastError); +} + +/** + * xmlCopyError: + * @from: a source error + * @to: a target error + * + * Save the original error to the new place. + * + * Returns 0 in case of success and -1 in case of error. + */ +int +xmlCopyError(xmlErrorPtr from, xmlErrorPtr to) { + char *message, *file, *str1, *str2, *str3; + + if ((from == NULL) || (to == NULL)) + return(-1); + + message = (char *) xmlStrdup((xmlChar *) from->message); + file = (char *) xmlStrdup ((xmlChar *) from->file); + str1 = (char *) xmlStrdup ((xmlChar *) from->str1); + str2 = (char *) xmlStrdup ((xmlChar *) from->str2); + str3 = (char *) xmlStrdup ((xmlChar *) from->str3); + + if (to->message != NULL) + xmlFree(to->message); + if (to->file != NULL) + xmlFree(to->file); + if (to->str1 != NULL) + xmlFree(to->str1); + if (to->str2 != NULL) + xmlFree(to->str2); + if (to->str3 != NULL) + xmlFree(to->str3); + to->domain = from->domain; + to->code = from->code; + to->level = from->level; + to->line = from->line; + to->node = from->node; + to->int1 = from->int1; + to->int2 = from->int2; + to->node = from->node; + to->ctxt = from->ctxt; + to->message = message; + to->file = file; + to->str1 = str1; + to->str2 = str2; + to->str3 = str3; + + return 0; +} + +#define bottom_error +#include "elfgcchack.h" diff --git a/gettext-tools/gnulib-lib/libxml/globals.c b/gettext-tools/gnulib-lib/libxml/globals.c new file mode 100644 index 0000000..c104a1a --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/globals.c @@ -0,0 +1,1094 @@ +/* + * globals.c: definition and handling of the set of global variables + * of the library + * + * The bottom of this file is automatically generated by build_glob.py + * based on the description file global.data + * + * See Copyright for the status of this software. + * + * Gary Pennington + * daniel@veillard.com + */ + +#define IN_LIBXML +#include "libxml.h" + +#ifdef HAVE_STDLIB_H +#include +#endif +#include + +#include +#include +#include + +/* #define DEBUG_GLOBALS */ + +/* + * Helpful Macro + */ +#ifdef LIBXML_THREAD_ENABLED +#define IS_MAIN_THREAD (xmlIsMainThread()) +#else +#define IS_MAIN_THREAD 1 +#endif + +/* + * Mutex to protect "ForNewThreads" variables + */ +static xmlMutexPtr xmlThrDefMutex = NULL; + +/** + * xmlInitGlobals: + * + * Additional initialisation for multi-threading + */ +void xmlInitGlobals(void) +{ + xmlThrDefMutex = xmlNewMutex(); +} + +/** + * xmlCleanupGlobals: + * + * Additional cleanup for multi-threading + */ +void xmlCleanupGlobals(void) +{ + if (xmlThrDefMutex != NULL) { + xmlFreeMutex(xmlThrDefMutex); + xmlThrDefMutex = NULL; + } +} + +/************************************************************************ + * * + * All the user accessible global variables of the library * + * * + ************************************************************************/ + +/* + * Memory allocation routines + */ +#undef xmlFree +#undef xmlMalloc +#undef xmlMallocAtomic +#undef xmlMemStrdup +#undef xmlRealloc + +#if defined(DEBUG_MEMORY_LOCATION) || defined(DEBUG_MEMORY) +xmlFreeFunc xmlFree = (xmlFreeFunc) xmlMemFree; +xmlMallocFunc xmlMalloc = (xmlMallocFunc) xmlMemMalloc; +xmlMallocFunc xmlMallocAtomic = (xmlMallocFunc) xmlMemMalloc; +xmlReallocFunc xmlRealloc = (xmlReallocFunc) xmlMemRealloc; +xmlStrdupFunc xmlMemStrdup = (xmlStrdupFunc) xmlMemoryStrdup; +#else +/** + * xmlFree: + * @mem: an already allocated block of memory + * + * The variable holding the libxml free() implementation + */ +xmlFreeFunc xmlFree = (xmlFreeFunc) free; +/** + * xmlMalloc: + * @size: the size requested in bytes + * + * The variable holding the libxml malloc() implementation + * + * Returns a pointer to the newly allocated block or NULL in case of error + */ +xmlMallocFunc xmlMalloc = (xmlMallocFunc) malloc; +/** + * xmlMallocAtomic: + * @size: the size requested in bytes + * + * The variable holding the libxml malloc() implementation for atomic + * data (i.e. blocks not containings pointers), useful when using a + * garbage collecting allocator. + * + * Returns a pointer to the newly allocated block or NULL in case of error + */ +xmlMallocFunc xmlMallocAtomic = (xmlMallocFunc) malloc; +/** + * xmlRealloc: + * @mem: an already allocated block of memory + * @size: the new size requested in bytes + * + * The variable holding the libxml realloc() implementation + * + * Returns a pointer to the newly reallocated block or NULL in case of error + */ +xmlReallocFunc xmlRealloc = (xmlReallocFunc) realloc; +/** + * xmlMemStrdup: + * @str: a zero terminated string + * + * The variable holding the libxml strdup() implementation + * + * Returns the copy of the string or NULL in case of error + */ +xmlStrdupFunc xmlMemStrdup = (xmlStrdupFunc) xmlStrdup; +#endif /* DEBUG_MEMORY_LOCATION || DEBUG_MEMORY */ + +#include +#include +#include + +#undef docbDefaultSAXHandler +#undef htmlDefaultSAXHandler +#undef oldXMLWDcompatibility +#undef xmlBufferAllocScheme +#undef xmlDefaultBufferSize +#undef xmlDefaultSAXHandler +#undef xmlDefaultSAXLocator +#undef xmlDoValidityCheckingDefaultValue +#undef xmlGenericError +#undef xmlStructuredError +#undef xmlGenericErrorContext +#undef xmlGetWarningsDefaultValue +#undef xmlIndentTreeOutput +#undef xmlTreeIndentString +#undef xmlKeepBlanksDefaultValue +#undef xmlLineNumbersDefaultValue +#undef xmlLoadExtDtdDefaultValue +#undef xmlParserDebugEntities +#undef xmlParserVersion +#undef xmlPedanticParserDefaultValue +#undef xmlSaveNoEmptyTags +#undef xmlSubstituteEntitiesDefaultValue +#undef xmlRegisterNodeDefaultValue +#undef xmlDeregisterNodeDefaultValue +#undef xmlLastError + +#undef xmlParserInputBufferCreateFilenameValue +#undef xmlOutputBufferCreateFilenameValue +/** + * xmlParserVersion: + * + * Constant string describing the internal version of the library + */ +const char *xmlParserVersion = LIBXML_VERSION_STRING LIBXML_VERSION_EXTRA; + +/** + * xmlBufferAllocScheme: + * + * Global setting, default allocation policy for buffers, default is + * XML_BUFFER_ALLOC_EXACT + */ +xmlBufferAllocationScheme xmlBufferAllocScheme = XML_BUFFER_ALLOC_EXACT; +static xmlBufferAllocationScheme xmlBufferAllocSchemeThrDef = XML_BUFFER_ALLOC_EXACT; +/** + * xmlDefaultBufferSize: + * + * Global setting, default buffer size. Default value is BASE_BUFFER_SIZE + */ +int xmlDefaultBufferSize = BASE_BUFFER_SIZE; +static int xmlDefaultBufferSizeThrDef = BASE_BUFFER_SIZE; + +/* + * Parser defaults + */ + +/** + * oldXMLWDcompatibility: + * + * Global setting, DEPRECATED. + */ +int oldXMLWDcompatibility = 0; /* DEPRECATED */ +/** + * xmlParserDebugEntities: + * + * Global setting, asking the parser to print out debugging informations. + * while handling entities. + * Disabled by default + */ +int xmlParserDebugEntities = 0; +static int xmlParserDebugEntitiesThrDef = 0; +/** + * xmlDoValidityCheckingDefaultValue: + * + * Global setting, indicate that the parser should work in validating mode. + * Disabled by default. + */ +int xmlDoValidityCheckingDefaultValue = 0; +static int xmlDoValidityCheckingDefaultValueThrDef = 0; +/** + * xmlGetWarningsDefaultValue: + * + * Global setting, indicate that the parser should provide warnings. + * Activated by default. + */ +int xmlGetWarningsDefaultValue = 1; +static int xmlGetWarningsDefaultValueThrDef = 1; +/** + * xmlLoadExtDtdDefaultValue: + * + * Global setting, indicate that the parser should load DTD while not + * validating. + * Disabled by default. + */ +int xmlLoadExtDtdDefaultValue = 0; +static int xmlLoadExtDtdDefaultValueThrDef = 0; +/** + * xmlPedanticParserDefaultValue: + * + * Global setting, indicate that the parser be pedantic + * Disabled by default. + */ +int xmlPedanticParserDefaultValue = 0; +static int xmlPedanticParserDefaultValueThrDef = 0; +/** + * xmlLineNumbersDefaultValue: + * + * Global setting, indicate that the parser should store the line number + * in the content field of elements in the DOM tree. + * Disabled by default since this may not be safe for old classes of + * applicaton. + */ +int xmlLineNumbersDefaultValue = 0; +static int xmlLineNumbersDefaultValueThrDef = 0; +/** + * xmlKeepBlanksDefaultValue: + * + * Global setting, indicate that the parser should keep all blanks + * nodes found in the content + * Activated by default, this is actually needed to have the parser + * conformant to the XML Recommendation, however the option is kept + * for some applications since this was libxml1 default behaviour. + */ +int xmlKeepBlanksDefaultValue = 1; +static int xmlKeepBlanksDefaultValueThrDef = 1; +/** + * xmlSubstituteEntitiesDefaultValue: + * + * Global setting, indicate that the parser should not generate entity + * references but replace them with the actual content of the entity + * Disabled by default, this should be activated when using XPath since + * the XPath data model requires entities replacement and the XPath + * engine does not handle entities references transparently. + */ +int xmlSubstituteEntitiesDefaultValue = 0; +static int xmlSubstituteEntitiesDefaultValueThrDef = 0; + +xmlRegisterNodeFunc xmlRegisterNodeDefaultValue = NULL; +static xmlRegisterNodeFunc xmlRegisterNodeDefaultValueThrDef = NULL; +xmlDeregisterNodeFunc xmlDeregisterNodeDefaultValue = NULL; +static xmlDeregisterNodeFunc xmlDeregisterNodeDefaultValueThrDef = NULL; + +xmlParserInputBufferCreateFilenameFunc xmlParserInputBufferCreateFilenameValue = NULL; +static xmlParserInputBufferCreateFilenameFunc xmlParserInputBufferCreateFilenameValueThrDef = NULL; + +xmlOutputBufferCreateFilenameFunc xmlOutputBufferCreateFilenameValue = NULL; +static xmlOutputBufferCreateFilenameFunc xmlOutputBufferCreateFilenameValueThrDef = NULL; + +/* + * Error handling + */ + +/* xmlGenericErrorFunc xmlGenericError = xmlGenericErrorDefaultFunc; */ +/* Must initialize xmlGenericError in xmlInitParser */ +void XMLCDECL xmlGenericErrorDefaultFunc (void *ctx ATTRIBUTE_UNUSED, + const char *msg, + ...); +/** + * xmlGenericError: + * + * Global setting: function used for generic error callbacks + */ +xmlGenericErrorFunc xmlGenericError = xmlGenericErrorDefaultFunc; +static xmlGenericErrorFunc xmlGenericErrorThrDef = xmlGenericErrorDefaultFunc; +/** + * xmlStructuredError: + * + * Global setting: function used for structured error callbacks + */ +xmlStructuredErrorFunc xmlStructuredError = NULL; +static xmlStructuredErrorFunc xmlStructuredErrorThrDef = NULL; +/** + * xmlGenericErrorContext: + * + * Global setting passed to generic error callbacks + */ +void *xmlGenericErrorContext = NULL; +static void *xmlGenericErrorContextThrDef = NULL; +xmlError xmlLastError; + +/* + * output defaults + */ +/** + * xmlIndentTreeOutput: + * + * Global setting, asking the serializer to indent the output tree by default + * Enabled by default + */ +int xmlIndentTreeOutput = 1; +static int xmlIndentTreeOutputThrDef = 1; + +/** + * xmlTreeIndentString: + * + * The string used to do one-level indent. By default is equal to " " (two spaces) + */ +const char *xmlTreeIndentString = " "; +static const char *xmlTreeIndentStringThrDef = " "; + +/** + * xmlSaveNoEmptyTags: + * + * Global setting, asking the serializer to not output empty tags + * as but . those two forms are undistinguishable + * once parsed. + * Disabled by default + */ +int xmlSaveNoEmptyTags = 0; +static int xmlSaveNoEmptyTagsThrDef = 0; + +#ifdef LIBXML_SAX1_ENABLED +/** + * xmlDefaultSAXHandler: + * + * Default SAX version1 handler for XML, builds the DOM tree + */ +xmlSAXHandlerV1 xmlDefaultSAXHandler = { + xmlSAX2InternalSubset, + xmlSAX2IsStandalone, + xmlSAX2HasInternalSubset, + xmlSAX2HasExternalSubset, + xmlSAX2ResolveEntity, + xmlSAX2GetEntity, + xmlSAX2EntityDecl, + xmlSAX2NotationDecl, + xmlSAX2AttributeDecl, + xmlSAX2ElementDecl, + xmlSAX2UnparsedEntityDecl, + xmlSAX2SetDocumentLocator, + xmlSAX2StartDocument, + xmlSAX2EndDocument, + xmlSAX2StartElement, + xmlSAX2EndElement, + xmlSAX2Reference, + xmlSAX2Characters, + xmlSAX2Characters, + xmlSAX2ProcessingInstruction, + xmlSAX2Comment, + xmlParserWarning, + xmlParserError, + xmlParserError, + xmlSAX2GetParameterEntity, + xmlSAX2CDataBlock, + xmlSAX2ExternalSubset, + 0, +}; +#endif /* LIBXML_SAX1_ENABLED */ + +/** + * xmlDefaultSAXLocator: + * + * The default SAX Locator + * { getPublicId, getSystemId, getLineNumber, getColumnNumber} + */ +xmlSAXLocator xmlDefaultSAXLocator = { + xmlSAX2GetPublicId, + xmlSAX2GetSystemId, + xmlSAX2GetLineNumber, + xmlSAX2GetColumnNumber +}; + +#ifdef LIBXML_HTML_ENABLED +/** + * htmlDefaultSAXHandler: + * + * Default old SAX v1 handler for HTML, builds the DOM tree + */ +xmlSAXHandlerV1 htmlDefaultSAXHandler = { + xmlSAX2InternalSubset, + NULL, + NULL, + NULL, + NULL, + xmlSAX2GetEntity, + NULL, + NULL, + NULL, + NULL, + NULL, + xmlSAX2SetDocumentLocator, + xmlSAX2StartDocument, + xmlSAX2EndDocument, + xmlSAX2StartElement, + xmlSAX2EndElement, + NULL, + xmlSAX2Characters, + xmlSAX2IgnorableWhitespace, + xmlSAX2ProcessingInstruction, + xmlSAX2Comment, + xmlParserWarning, + xmlParserError, + xmlParserError, + xmlSAX2GetParameterEntity, + xmlSAX2CDataBlock, + NULL, + 0, +}; +#endif /* LIBXML_HTML_ENABLED */ + +#ifdef LIBXML_DOCB_ENABLED +/** + * docbDefaultSAXHandler: + * + * Default old SAX v1 handler for SGML DocBook, builds the DOM tree + */ +xmlSAXHandlerV1 docbDefaultSAXHandler = { + xmlSAX2InternalSubset, + xmlSAX2IsStandalone, + xmlSAX2HasInternalSubset, + xmlSAX2HasExternalSubset, + xmlSAX2ResolveEntity, + xmlSAX2GetEntity, + xmlSAX2EntityDecl, + NULL, + NULL, + NULL, + NULL, + xmlSAX2SetDocumentLocator, + xmlSAX2StartDocument, + xmlSAX2EndDocument, + xmlSAX2StartElement, + xmlSAX2EndElement, + xmlSAX2Reference, + xmlSAX2Characters, + xmlSAX2IgnorableWhitespace, + NULL, + xmlSAX2Comment, + xmlParserWarning, + xmlParserError, + xmlParserError, + xmlSAX2GetParameterEntity, + NULL, + NULL, + 0, +}; +#endif /* LIBXML_DOCB_ENABLED */ + +/** + * xmlInitializeGlobalState: + * @gs: a pointer to a newly allocated global state + * + * xmlInitializeGlobalState() initialize a global state with all the + * default values of the library. + */ +void +xmlInitializeGlobalState(xmlGlobalStatePtr gs) +{ +#ifdef DEBUG_GLOBALS + fprintf(stderr, "Initializing globals at %lu for thread %d\n", + (unsigned long) gs, xmlGetThreadId()); +#endif + + /* + * Perform initialization as required by libxml + */ + if (xmlThrDefMutex == NULL) + xmlInitGlobals(); + + xmlMutexLock(xmlThrDefMutex); + +#if defined(LIBXML_DOCB_ENABLED) && defined(LIBXML_LEGACY_ENABLED) && defined(LIBXML_SAX1_ENABLED) + initdocbDefaultSAXHandler(&gs->docbDefaultSAXHandler); +#endif +#if defined(LIBXML_HTML_ENABLED) && defined(LIBXML_LEGACY_ENABLED) + inithtmlDefaultSAXHandler(&gs->htmlDefaultSAXHandler); +#endif + + gs->oldXMLWDcompatibility = 0; + gs->xmlBufferAllocScheme = xmlBufferAllocSchemeThrDef; + gs->xmlDefaultBufferSize = xmlDefaultBufferSizeThrDef; +#if defined(LIBXML_SAX1_ENABLED) && defined(LIBXML_LEGACY_ENABLED) + initxmlDefaultSAXHandler(&gs->xmlDefaultSAXHandler, 1); +#endif /* LIBXML_SAX1_ENABLED */ + gs->xmlDefaultSAXLocator.getPublicId = xmlSAX2GetPublicId; + gs->xmlDefaultSAXLocator.getSystemId = xmlSAX2GetSystemId; + gs->xmlDefaultSAXLocator.getLineNumber = xmlSAX2GetLineNumber; + gs->xmlDefaultSAXLocator.getColumnNumber = xmlSAX2GetColumnNumber; + gs->xmlDoValidityCheckingDefaultValue = + xmlDoValidityCheckingDefaultValueThrDef; +#if defined(DEBUG_MEMORY_LOCATION) | defined(DEBUG_MEMORY) + gs->xmlFree = (xmlFreeFunc) xmlMemFree; + gs->xmlMalloc = (xmlMallocFunc) xmlMemMalloc; + gs->xmlMallocAtomic = (xmlMallocFunc) xmlMemMalloc; + gs->xmlRealloc = (xmlReallocFunc) xmlMemRealloc; + gs->xmlMemStrdup = (xmlStrdupFunc) xmlMemoryStrdup; +#else + gs->xmlFree = (xmlFreeFunc) free; + gs->xmlMalloc = (xmlMallocFunc) malloc; + gs->xmlMallocAtomic = (xmlMallocFunc) malloc; + gs->xmlRealloc = (xmlReallocFunc) realloc; + gs->xmlMemStrdup = (xmlStrdupFunc) xmlStrdup; +#endif + gs->xmlGetWarningsDefaultValue = xmlGetWarningsDefaultValueThrDef; + gs->xmlIndentTreeOutput = xmlIndentTreeOutputThrDef; + gs->xmlTreeIndentString = xmlTreeIndentStringThrDef; + gs->xmlKeepBlanksDefaultValue = xmlKeepBlanksDefaultValueThrDef; + gs->xmlLineNumbersDefaultValue = xmlLineNumbersDefaultValueThrDef; + gs->xmlLoadExtDtdDefaultValue = xmlLoadExtDtdDefaultValueThrDef; + gs->xmlParserDebugEntities = xmlParserDebugEntitiesThrDef; + gs->xmlParserVersion = LIBXML_VERSION_STRING; + gs->xmlPedanticParserDefaultValue = xmlPedanticParserDefaultValueThrDef; + gs->xmlSaveNoEmptyTags = xmlSaveNoEmptyTagsThrDef; + gs->xmlSubstituteEntitiesDefaultValue = + xmlSubstituteEntitiesDefaultValueThrDef; + + gs->xmlGenericError = xmlGenericErrorThrDef; + gs->xmlStructuredError = xmlStructuredErrorThrDef; + gs->xmlGenericErrorContext = xmlGenericErrorContextThrDef; + gs->xmlRegisterNodeDefaultValue = xmlRegisterNodeDefaultValueThrDef; + gs->xmlDeregisterNodeDefaultValue = xmlDeregisterNodeDefaultValueThrDef; + + gs->xmlParserInputBufferCreateFilenameValue = xmlParserInputBufferCreateFilenameValueThrDef; + gs->xmlOutputBufferCreateFilenameValue = xmlOutputBufferCreateFilenameValueThrDef; + memset(&gs->xmlLastError, 0, sizeof(xmlError)); + + xmlMutexUnlock(xmlThrDefMutex); +} + +/** + * DOC_DISABLE : we ignore missing doc for the xmlThrDef functions, + * those are really internal work + */ +void +xmlThrDefSetGenericErrorFunc(void *ctx, xmlGenericErrorFunc handler) { + xmlMutexLock(xmlThrDefMutex); + xmlGenericErrorContextThrDef = ctx; + if (handler != NULL) + xmlGenericErrorThrDef = handler; + else + xmlGenericErrorThrDef = xmlGenericErrorDefaultFunc; + xmlMutexUnlock(xmlThrDefMutex); +} + +void +xmlThrDefSetStructuredErrorFunc(void *ctx, xmlStructuredErrorFunc handler) { + xmlMutexLock(xmlThrDefMutex); + xmlGenericErrorContextThrDef = ctx; + xmlStructuredErrorThrDef = handler; + xmlMutexUnlock(xmlThrDefMutex); +} + +/** + * xmlRegisterNodeDefault: + * @func: function pointer to the new RegisterNodeFunc + * + * Registers a callback for node creation + * + * Returns the old value of the registration function + */ +xmlRegisterNodeFunc +xmlRegisterNodeDefault(xmlRegisterNodeFunc func) +{ + xmlRegisterNodeFunc old = xmlRegisterNodeDefaultValue; + + __xmlRegisterCallbacks = 1; + xmlRegisterNodeDefaultValue = func; + return(old); +} + +xmlRegisterNodeFunc +xmlThrDefRegisterNodeDefault(xmlRegisterNodeFunc func) +{ + xmlRegisterNodeFunc old; + + xmlMutexLock(xmlThrDefMutex); + old = xmlRegisterNodeDefaultValueThrDef; + + __xmlRegisterCallbacks = 1; + xmlRegisterNodeDefaultValueThrDef = func; + xmlMutexUnlock(xmlThrDefMutex); + + return(old); +} + +/** + * xmlDeregisterNodeDefault: + * @func: function pointer to the new DeregisterNodeFunc + * + * Registers a callback for node destruction + * + * Returns the previous value of the deregistration function + */ +xmlDeregisterNodeFunc +xmlDeregisterNodeDefault(xmlDeregisterNodeFunc func) +{ + xmlDeregisterNodeFunc old = xmlDeregisterNodeDefaultValue; + + __xmlRegisterCallbacks = 1; + xmlDeregisterNodeDefaultValue = func; + return(old); +} + +xmlDeregisterNodeFunc +xmlThrDefDeregisterNodeDefault(xmlDeregisterNodeFunc func) +{ + xmlDeregisterNodeFunc old; + + xmlMutexLock(xmlThrDefMutex); + old = xmlDeregisterNodeDefaultValueThrDef; + + __xmlRegisterCallbacks = 1; + xmlDeregisterNodeDefaultValueThrDef = func; + xmlMutexUnlock(xmlThrDefMutex); + + return(old); +} + +xmlParserInputBufferCreateFilenameFunc +xmlThrDefParserInputBufferCreateFilenameDefault(xmlParserInputBufferCreateFilenameFunc func) +{ + xmlParserInputBufferCreateFilenameFunc old; + + xmlMutexLock(xmlThrDefMutex); + old = xmlParserInputBufferCreateFilenameValueThrDef; + if (old == NULL) { + old = __xmlParserInputBufferCreateFilename; + } + + xmlParserInputBufferCreateFilenameValueThrDef = func; + xmlMutexUnlock(xmlThrDefMutex); + + return(old); +} + +xmlOutputBufferCreateFilenameFunc +xmlThrDefOutputBufferCreateFilenameDefault(xmlOutputBufferCreateFilenameFunc func) +{ + xmlOutputBufferCreateFilenameFunc old; + + xmlMutexLock(xmlThrDefMutex); + old = xmlOutputBufferCreateFilenameValueThrDef; +#ifdef LIBXML_OUTPUT_ENABLED + if (old == NULL) { + old = __xmlOutputBufferCreateFilename; + } +#endif + xmlOutputBufferCreateFilenameValueThrDef = func; + xmlMutexUnlock(xmlThrDefMutex); + + return(old); +} + +#ifdef LIBXML_DOCB_ENABLED +#undef docbDefaultSAXHandler +xmlSAXHandlerV1 * +__docbDefaultSAXHandler(void) { + if (IS_MAIN_THREAD) + return (&docbDefaultSAXHandler); + else + return (&xmlGetGlobalState()->docbDefaultSAXHandler); +} +#endif + +#ifdef LIBXML_HTML_ENABLED +#undef htmlDefaultSAXHandler +xmlSAXHandlerV1 * +__htmlDefaultSAXHandler(void) { + if (IS_MAIN_THREAD) + return (&htmlDefaultSAXHandler); + else + return (&xmlGetGlobalState()->htmlDefaultSAXHandler); +} +#endif + +#undef xmlLastError +xmlError * +__xmlLastError(void) { + if (IS_MAIN_THREAD) + return (&xmlLastError); + else + return (&xmlGetGlobalState()->xmlLastError); +} + +/* + * The following memory routines were apparently lost at some point, + * and were re-inserted at this point on June 10, 2004. Hope it's + * the right place for them :-) + */ +#if defined(LIBXML_THREAD_ALLOC_ENABLED) && defined(LIBXML_THREAD_ENABLED) +#undef xmlMalloc +xmlMallocFunc * +__xmlMalloc(void){ + if (IS_MAIN_THREAD) + return (&xmlMalloc); + else + return (&xmlGetGlobalState()->xmlMalloc); +} + +#undef xmlMallocAtomic +xmlMallocFunc * +__xmlMallocAtomic(void){ + if (IS_MAIN_THREAD) + return (&xmlMallocAtomic); + else + return (&xmlGetGlobalState()->xmlMallocAtomic); +} + +#undef xmlRealloc +xmlReallocFunc * +__xmlRealloc(void){ + if (IS_MAIN_THREAD) + return (&xmlRealloc); + else + return (&xmlGetGlobalState()->xmlRealloc); +} + +#undef xmlFree +xmlFreeFunc * +__xmlFree(void){ + if (IS_MAIN_THREAD) + return (&xmlFree); + else + return (&xmlGetGlobalState()->xmlFree); +} + +xmlStrdupFunc * +__xmlMemStrdup(void){ + if (IS_MAIN_THREAD) + return (&xmlMemStrdup); + else + return (&xmlGetGlobalState()->xmlMemStrdup); +} + +#endif + +/* + * Everything starting from the line below is + * Automatically generated by build_glob.py. + * Do not modify the previous line. + */ + + +#undef oldXMLWDcompatibility +int * +__oldXMLWDcompatibility(void) { + if (IS_MAIN_THREAD) + return (&oldXMLWDcompatibility); + else + return (&xmlGetGlobalState()->oldXMLWDcompatibility); +} + +#undef xmlBufferAllocScheme +xmlBufferAllocationScheme * +__xmlBufferAllocScheme(void) { + if (IS_MAIN_THREAD) + return (&xmlBufferAllocScheme); + else + return (&xmlGetGlobalState()->xmlBufferAllocScheme); +} +xmlBufferAllocationScheme xmlThrDefBufferAllocScheme(xmlBufferAllocationScheme v) { + xmlBufferAllocationScheme ret; + xmlMutexLock(xmlThrDefMutex); + ret = xmlBufferAllocSchemeThrDef; + xmlBufferAllocSchemeThrDef = v; + xmlMutexUnlock(xmlThrDefMutex); + return ret; +} + +#undef xmlDefaultBufferSize +int * +__xmlDefaultBufferSize(void) { + if (IS_MAIN_THREAD) + return (&xmlDefaultBufferSize); + else + return (&xmlGetGlobalState()->xmlDefaultBufferSize); +} +int xmlThrDefDefaultBufferSize(int v) { + int ret; + xmlMutexLock(xmlThrDefMutex); + ret = xmlDefaultBufferSizeThrDef; + xmlDefaultBufferSizeThrDef = v; + xmlMutexUnlock(xmlThrDefMutex); + return ret; +} + +#ifdef LIBXML_SAX1_ENABLED +#undef xmlDefaultSAXHandler +xmlSAXHandlerV1 * +__xmlDefaultSAXHandler(void) { + if (IS_MAIN_THREAD) + return (&xmlDefaultSAXHandler); + else + return (&xmlGetGlobalState()->xmlDefaultSAXHandler); +} +#endif /* LIBXML_SAX1_ENABLED */ + +#undef xmlDefaultSAXLocator +xmlSAXLocator * +__xmlDefaultSAXLocator(void) { + if (IS_MAIN_THREAD) + return (&xmlDefaultSAXLocator); + else + return (&xmlGetGlobalState()->xmlDefaultSAXLocator); +} + +#undef xmlDoValidityCheckingDefaultValue +int * +__xmlDoValidityCheckingDefaultValue(void) { + if (IS_MAIN_THREAD) + return (&xmlDoValidityCheckingDefaultValue); + else + return (&xmlGetGlobalState()->xmlDoValidityCheckingDefaultValue); +} +int xmlThrDefDoValidityCheckingDefaultValue(int v) { + int ret; + xmlMutexLock(xmlThrDefMutex); + ret = xmlDoValidityCheckingDefaultValueThrDef; + xmlDoValidityCheckingDefaultValueThrDef = v; + xmlMutexUnlock(xmlThrDefMutex); + return ret; +} + +#undef xmlGenericError +xmlGenericErrorFunc * +__xmlGenericError(void) { + if (IS_MAIN_THREAD) + return (&xmlGenericError); + else + return (&xmlGetGlobalState()->xmlGenericError); +} + +#undef xmlStructuredError +xmlStructuredErrorFunc * +__xmlStructuredError(void) { + if (IS_MAIN_THREAD) + return (&xmlStructuredError); + else + return (&xmlGetGlobalState()->xmlStructuredError); +} + +#undef xmlGenericErrorContext +void * * +__xmlGenericErrorContext(void) { + if (IS_MAIN_THREAD) + return (&xmlGenericErrorContext); + else + return (&xmlGetGlobalState()->xmlGenericErrorContext); +} + +#undef xmlGetWarningsDefaultValue +int * +__xmlGetWarningsDefaultValue(void) { + if (IS_MAIN_THREAD) + return (&xmlGetWarningsDefaultValue); + else + return (&xmlGetGlobalState()->xmlGetWarningsDefaultValue); +} +int xmlThrDefGetWarningsDefaultValue(int v) { + int ret; + xmlMutexLock(xmlThrDefMutex); + ret = xmlGetWarningsDefaultValueThrDef; + xmlGetWarningsDefaultValueThrDef = v; + xmlMutexUnlock(xmlThrDefMutex); + return ret; +} + +#undef xmlIndentTreeOutput +int * +__xmlIndentTreeOutput(void) { + if (IS_MAIN_THREAD) + return (&xmlIndentTreeOutput); + else + return (&xmlGetGlobalState()->xmlIndentTreeOutput); +} +int xmlThrDefIndentTreeOutput(int v) { + int ret; + xmlMutexLock(xmlThrDefMutex); + ret = xmlIndentTreeOutputThrDef; + xmlIndentTreeOutputThrDef = v; + xmlMutexUnlock(xmlThrDefMutex); + return ret; +} + +#undef xmlTreeIndentString +const char * * +__xmlTreeIndentString(void) { + if (IS_MAIN_THREAD) + return (&xmlTreeIndentString); + else + return (&xmlGetGlobalState()->xmlTreeIndentString); +} +const char * xmlThrDefTreeIndentString(const char * v) { + const char * ret; + xmlMutexLock(xmlThrDefMutex); + ret = xmlTreeIndentStringThrDef; + xmlTreeIndentStringThrDef = v; + xmlMutexUnlock(xmlThrDefMutex); + return ret; +} + +#undef xmlKeepBlanksDefaultValue +int * +__xmlKeepBlanksDefaultValue(void) { + if (IS_MAIN_THREAD) + return (&xmlKeepBlanksDefaultValue); + else + return (&xmlGetGlobalState()->xmlKeepBlanksDefaultValue); +} +int xmlThrDefKeepBlanksDefaultValue(int v) { + int ret; + xmlMutexLock(xmlThrDefMutex); + ret = xmlKeepBlanksDefaultValueThrDef; + xmlKeepBlanksDefaultValueThrDef = v; + xmlMutexUnlock(xmlThrDefMutex); + return ret; +} + +#undef xmlLineNumbersDefaultValue +int * +__xmlLineNumbersDefaultValue(void) { + if (IS_MAIN_THREAD) + return (&xmlLineNumbersDefaultValue); + else + return (&xmlGetGlobalState()->xmlLineNumbersDefaultValue); +} +int xmlThrDefLineNumbersDefaultValue(int v) { + int ret; + xmlMutexLock(xmlThrDefMutex); + ret = xmlLineNumbersDefaultValueThrDef; + xmlLineNumbersDefaultValueThrDef = v; + xmlMutexUnlock(xmlThrDefMutex); + return ret; +} + +#undef xmlLoadExtDtdDefaultValue +int * +__xmlLoadExtDtdDefaultValue(void) { + if (IS_MAIN_THREAD) + return (&xmlLoadExtDtdDefaultValue); + else + return (&xmlGetGlobalState()->xmlLoadExtDtdDefaultValue); +} +int xmlThrDefLoadExtDtdDefaultValue(int v) { + int ret; + xmlMutexLock(xmlThrDefMutex); + ret = xmlLoadExtDtdDefaultValueThrDef; + xmlLoadExtDtdDefaultValueThrDef = v; + xmlMutexUnlock(xmlThrDefMutex); + return ret; +} + +#undef xmlParserDebugEntities +int * +__xmlParserDebugEntities(void) { + if (IS_MAIN_THREAD) + return (&xmlParserDebugEntities); + else + return (&xmlGetGlobalState()->xmlParserDebugEntities); +} +int xmlThrDefParserDebugEntities(int v) { + int ret; + xmlMutexLock(xmlThrDefMutex); + ret = xmlParserDebugEntitiesThrDef; + xmlParserDebugEntitiesThrDef = v; + xmlMutexUnlock(xmlThrDefMutex); + return ret; +} + +#undef xmlParserVersion +const char * * +__xmlParserVersion(void) { + if (IS_MAIN_THREAD) + return (&xmlParserVersion); + else + return (&xmlGetGlobalState()->xmlParserVersion); +} + +#undef xmlPedanticParserDefaultValue +int * +__xmlPedanticParserDefaultValue(void) { + if (IS_MAIN_THREAD) + return (&xmlPedanticParserDefaultValue); + else + return (&xmlGetGlobalState()->xmlPedanticParserDefaultValue); +} +int xmlThrDefPedanticParserDefaultValue(int v) { + int ret; + xmlMutexLock(xmlThrDefMutex); + ret = xmlPedanticParserDefaultValueThrDef; + xmlPedanticParserDefaultValueThrDef = v; + xmlMutexUnlock(xmlThrDefMutex); + return ret; +} + +#undef xmlSaveNoEmptyTags +int * +__xmlSaveNoEmptyTags(void) { + if (IS_MAIN_THREAD) + return (&xmlSaveNoEmptyTags); + else + return (&xmlGetGlobalState()->xmlSaveNoEmptyTags); +} +int xmlThrDefSaveNoEmptyTags(int v) { + int ret; + xmlMutexLock(xmlThrDefMutex); + ret = xmlSaveNoEmptyTagsThrDef; + xmlSaveNoEmptyTagsThrDef = v; + xmlMutexUnlock(xmlThrDefMutex); + return ret; +} + +#undef xmlSubstituteEntitiesDefaultValue +int * +__xmlSubstituteEntitiesDefaultValue(void) { + if (IS_MAIN_THREAD) + return (&xmlSubstituteEntitiesDefaultValue); + else + return (&xmlGetGlobalState()->xmlSubstituteEntitiesDefaultValue); +} +int xmlThrDefSubstituteEntitiesDefaultValue(int v) { + int ret; + xmlMutexLock(xmlThrDefMutex); + ret = xmlSubstituteEntitiesDefaultValueThrDef; + xmlSubstituteEntitiesDefaultValueThrDef = v; + xmlMutexUnlock(xmlThrDefMutex); + return ret; +} + +#undef xmlRegisterNodeDefaultValue +xmlRegisterNodeFunc * +__xmlRegisterNodeDefaultValue(void) { + if (IS_MAIN_THREAD) + return (&xmlRegisterNodeDefaultValue); + else + return (&xmlGetGlobalState()->xmlRegisterNodeDefaultValue); +} + +#undef xmlDeregisterNodeDefaultValue +xmlDeregisterNodeFunc * +__xmlDeregisterNodeDefaultValue(void) { + if (IS_MAIN_THREAD) + return (&xmlDeregisterNodeDefaultValue); + else + return (&xmlGetGlobalState()->xmlDeregisterNodeDefaultValue); +} + +#undef xmlParserInputBufferCreateFilenameValue +xmlParserInputBufferCreateFilenameFunc * +__xmlParserInputBufferCreateFilenameValue(void) { + if (IS_MAIN_THREAD) + return (&xmlParserInputBufferCreateFilenameValue); + else + return (&xmlGetGlobalState()->xmlParserInputBufferCreateFilenameValue); +} + +#undef xmlOutputBufferCreateFilenameValue +xmlOutputBufferCreateFilenameFunc * +__xmlOutputBufferCreateFilenameValue(void) { + if (IS_MAIN_THREAD) + return (&xmlOutputBufferCreateFilenameValue); + else + return (&xmlGetGlobalState()->xmlOutputBufferCreateFilenameValue); +} + +#define bottom_globals +#include "elfgcchack.h" diff --git a/gettext-tools/gnulib-lib/libxml/globals.in.h b/gettext-tools/gnulib-lib/libxml/globals.in.h new file mode 100644 index 0000000..1173a8f --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/globals.in.h @@ -0,0 +1,455 @@ +/* + * Summary: interface for all global variables of the library + * Description: all the global variables and thread handling for + * those variables is handled by this module. + * + * The bottom of this file is automatically generated by build_glob.py + * based on the description file global.data + * + * Copy: See Copyright for the status of this software. + * + * Author: Gary Pennington , Daniel Veillard + */ + +#ifndef __XML_GLOBALS_H +#define __XML_GLOBALS_H + +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +XMLPUBFUN void XMLCALL xmlInitGlobals(void); +XMLPUBFUN void XMLCALL xmlCleanupGlobals(void); + +typedef xmlParserInputBufferPtr (*xmlParserInputBufferCreateFilenameFunc) (const char *URI, xmlCharEncoding enc); +typedef xmlOutputBufferPtr (*xmlOutputBufferCreateFilenameFunc) (const char *URI, xmlCharEncodingHandlerPtr encoder, int compression); +XMLPUBFUN xmlParserInputBufferCreateFilenameFunc +XMLCALL xmlParserInputBufferCreateFilenameDefault (xmlParserInputBufferCreateFilenameFunc func); +XMLPUBFUN xmlOutputBufferCreateFilenameFunc +XMLCALL xmlOutputBufferCreateFilenameDefault (xmlOutputBufferCreateFilenameFunc func); + +/* + * Externally global symbols which need to be protected for backwards + * compatibility support. + */ + +#undef docbDefaultSAXHandler +#undef htmlDefaultSAXHandler +#undef oldXMLWDcompatibility +#undef xmlBufferAllocScheme +#undef xmlDefaultBufferSize +#undef xmlDefaultSAXHandler +#undef xmlDefaultSAXLocator +#undef xmlDoValidityCheckingDefaultValue +#undef xmlFree +#undef xmlGenericError +#undef xmlStructuredError +#undef xmlGenericErrorContext +#undef xmlGetWarningsDefaultValue +#undef xmlIndentTreeOutput +#undef xmlTreeIndentString +#undef xmlKeepBlanksDefaultValue +#undef xmlLineNumbersDefaultValue +#undef xmlLoadExtDtdDefaultValue +#undef xmlMalloc +#undef xmlMallocAtomic +#undef xmlMemStrdup +#undef xmlParserDebugEntities +#undef xmlParserVersion +#undef xmlPedanticParserDefaultValue +#undef xmlRealloc +#undef xmlSaveNoEmptyTags +#undef xmlSubstituteEntitiesDefaultValue +#undef xmlRegisterNodeDefaultValue +#undef xmlDeregisterNodeDefaultValue +#undef xmlLastError +#undef xmlParserInputBufferCreateFilenameValue +#undef xmlOutputBufferCreateFilenameValue + +typedef void (*xmlRegisterNodeFunc) (xmlNodePtr node); +typedef void (*xmlDeregisterNodeFunc) (xmlNodePtr node); + +typedef struct _xmlGlobalState xmlGlobalState; +typedef xmlGlobalState *xmlGlobalStatePtr; +struct _xmlGlobalState +{ + const char *xmlParserVersion; + + xmlSAXLocator xmlDefaultSAXLocator; + xmlSAXHandlerV1 xmlDefaultSAXHandler; + xmlSAXHandlerV1 docbDefaultSAXHandler; + xmlSAXHandlerV1 htmlDefaultSAXHandler; + + xmlFreeFunc xmlFree; + xmlMallocFunc xmlMalloc; + xmlStrdupFunc xmlMemStrdup; + xmlReallocFunc xmlRealloc; + + xmlGenericErrorFunc xmlGenericError; + xmlStructuredErrorFunc xmlStructuredError; + void *xmlGenericErrorContext; + + int oldXMLWDcompatibility; + + xmlBufferAllocationScheme xmlBufferAllocScheme; + int xmlDefaultBufferSize; + + int xmlSubstituteEntitiesDefaultValue; + int xmlDoValidityCheckingDefaultValue; + int xmlGetWarningsDefaultValue; + int xmlKeepBlanksDefaultValue; + int xmlLineNumbersDefaultValue; + int xmlLoadExtDtdDefaultValue; + int xmlParserDebugEntities; + int xmlPedanticParserDefaultValue; + + int xmlSaveNoEmptyTags; + int xmlIndentTreeOutput; + const char *xmlTreeIndentString; + + xmlRegisterNodeFunc xmlRegisterNodeDefaultValue; + xmlDeregisterNodeFunc xmlDeregisterNodeDefaultValue; + + xmlMallocFunc xmlMallocAtomic; + xmlError xmlLastError; + + xmlParserInputBufferCreateFilenameFunc xmlParserInputBufferCreateFilenameValue; + xmlOutputBufferCreateFilenameFunc xmlOutputBufferCreateFilenameValue; +}; + +#ifdef __cplusplus +} +#endif +#include +#ifdef __cplusplus +extern "C" { +#endif + +XMLPUBFUN void XMLCALL xmlInitializeGlobalState(xmlGlobalStatePtr gs); + +XMLPUBFUN void XMLCALL xmlThrDefSetGenericErrorFunc(void *ctx, xmlGenericErrorFunc handler); + +XMLPUBFUN void XMLCALL xmlThrDefSetStructuredErrorFunc(void *ctx, xmlStructuredErrorFunc handler); + +XMLPUBFUN xmlRegisterNodeFunc XMLCALL xmlRegisterNodeDefault(xmlRegisterNodeFunc func); +XMLPUBFUN xmlRegisterNodeFunc XMLCALL xmlThrDefRegisterNodeDefault(xmlRegisterNodeFunc func); +XMLPUBFUN xmlDeregisterNodeFunc XMLCALL xmlDeregisterNodeDefault(xmlDeregisterNodeFunc func); +XMLPUBFUN xmlDeregisterNodeFunc XMLCALL xmlThrDefDeregisterNodeDefault(xmlDeregisterNodeFunc func); + +XMLPUBFUN xmlOutputBufferCreateFilenameFunc XMLCALL + xmlThrDefOutputBufferCreateFilenameDefault(xmlOutputBufferCreateFilenameFunc func); +XMLPUBFUN xmlParserInputBufferCreateFilenameFunc XMLCALL + xmlThrDefParserInputBufferCreateFilenameDefault(xmlParserInputBufferCreateFilenameFunc func); + +/** DOC_DISABLE */ +/* + * In general the memory allocation entry points are not kept + * thread specific but this can be overridden by LIBXML_THREAD_ALLOC_ENABLED + * - xmlMalloc + * - xmlMallocAtomic + * - xmlRealloc + * - xmlMemStrdup + * - xmlFree + */ + +#ifdef LIBXML_THREAD_ALLOC_ENABLED +#ifdef LIBXML_THREAD_ENABLED +XMLPUBFUN xmlMallocFunc * XMLCALL __xmlMalloc(void); +#define xmlMalloc \ +(*(__xmlMalloc())) +#else +XMLPUBVAR xmlMallocFunc xmlMalloc; +#endif + +#ifdef LIBXML_THREAD_ENABLED +XMLPUBFUN xmlMallocFunc * XMLCALL __xmlMallocAtomic(void); +#define xmlMallocAtomic \ +(*(__xmlMallocAtomic())) +#else +XMLPUBVAR xmlMallocFunc xmlMallocAtomic; +#endif + +#ifdef LIBXML_THREAD_ENABLED +XMLPUBFUN xmlReallocFunc * XMLCALL __xmlRealloc(void); +#define xmlRealloc \ +(*(__xmlRealloc())) +#else +XMLPUBVAR xmlReallocFunc xmlRealloc; +#endif + +#ifdef LIBXML_THREAD_ENABLED +XMLPUBFUN xmlFreeFunc * XMLCALL __xmlFree(void); +#define xmlFree \ +(*(__xmlFree())) +#else +XMLPUBVAR xmlFreeFunc xmlFree; +#endif + +#ifdef LIBXML_THREAD_ENABLED +XMLPUBFUN xmlStrdupFunc * XMLCALL __xmlMemStrdup(void); +#define xmlMemStrdup \ +(*(__xmlMemStrdup())) +#else +XMLPUBVAR xmlStrdupFunc xmlMemStrdup; +#endif + +#else /* !LIBXML_THREAD_ALLOC_ENABLED */ +XMLPUBVAR xmlMallocFunc xmlMalloc; +XMLPUBVAR xmlMallocFunc xmlMallocAtomic; +XMLPUBVAR xmlReallocFunc xmlRealloc; +XMLPUBVAR xmlFreeFunc xmlFree; +XMLPUBVAR xmlStrdupFunc xmlMemStrdup; +#endif /* LIBXML_THREAD_ALLOC_ENABLED */ + +#ifdef LIBXML_DOCB_ENABLED +XMLPUBFUN xmlSAXHandlerV1 * XMLCALL __docbDefaultSAXHandler(void); +#ifdef LIBXML_THREAD_ENABLED +#define docbDefaultSAXHandler \ +(*(__docbDefaultSAXHandler())) +#else +XMLPUBVAR xmlSAXHandlerV1 docbDefaultSAXHandler; +#endif +#endif + +#ifdef LIBXML_HTML_ENABLED +XMLPUBFUN xmlSAXHandlerV1 * XMLCALL __htmlDefaultSAXHandler(void); +#ifdef LIBXML_THREAD_ENABLED +#define htmlDefaultSAXHandler \ +(*(__htmlDefaultSAXHandler())) +#else +XMLPUBVAR xmlSAXHandlerV1 htmlDefaultSAXHandler; +#endif +#endif + +XMLPUBFUN xmlError * XMLCALL __xmlLastError(void); +#ifdef LIBXML_THREAD_ENABLED +#define xmlLastError \ +(*(__xmlLastError())) +#else +XMLPUBVAR xmlError xmlLastError; +#endif + +/* + * Everything starting from the line below is + * Automatically generated by build_glob.py. + * Do not modify the previous line. + */ + + +XMLPUBFUN int * XMLCALL __oldXMLWDcompatibility(void); +#ifdef LIBXML_THREAD_ENABLED +#define oldXMLWDcompatibility \ +(*(__oldXMLWDcompatibility())) +#else +XMLPUBVAR int oldXMLWDcompatibility; +#endif + +XMLPUBFUN xmlBufferAllocationScheme * XMLCALL __xmlBufferAllocScheme(void); +#ifdef LIBXML_THREAD_ENABLED +#define xmlBufferAllocScheme \ +(*(__xmlBufferAllocScheme())) +#else +XMLPUBVAR xmlBufferAllocationScheme xmlBufferAllocScheme; +#endif +XMLPUBFUN xmlBufferAllocationScheme XMLCALL xmlThrDefBufferAllocScheme(xmlBufferAllocationScheme v); + +XMLPUBFUN int * XMLCALL __xmlDefaultBufferSize(void); +#ifdef LIBXML_THREAD_ENABLED +#define xmlDefaultBufferSize \ +(*(__xmlDefaultBufferSize())) +#else +XMLPUBVAR int xmlDefaultBufferSize; +#endif +XMLPUBFUN int XMLCALL xmlThrDefDefaultBufferSize(int v); + +XMLPUBFUN xmlSAXHandlerV1 * XMLCALL __xmlDefaultSAXHandler(void); +#ifdef LIBXML_THREAD_ENABLED +#define xmlDefaultSAXHandler \ +(*(__xmlDefaultSAXHandler())) +#else +XMLPUBVAR xmlSAXHandlerV1 xmlDefaultSAXHandler; +#endif + +XMLPUBFUN xmlSAXLocator * XMLCALL __xmlDefaultSAXLocator(void); +#ifdef LIBXML_THREAD_ENABLED +#define xmlDefaultSAXLocator \ +(*(__xmlDefaultSAXLocator())) +#else +XMLPUBVAR xmlSAXLocator xmlDefaultSAXLocator; +#endif + +XMLPUBFUN int * XMLCALL __xmlDoValidityCheckingDefaultValue(void); +#ifdef LIBXML_THREAD_ENABLED +#define xmlDoValidityCheckingDefaultValue \ +(*(__xmlDoValidityCheckingDefaultValue())) +#else +XMLPUBVAR int xmlDoValidityCheckingDefaultValue; +#endif +XMLPUBFUN int XMLCALL xmlThrDefDoValidityCheckingDefaultValue(int v); + +XMLPUBFUN xmlGenericErrorFunc * XMLCALL __xmlGenericError(void); +#ifdef LIBXML_THREAD_ENABLED +#define xmlGenericError \ +(*(__xmlGenericError())) +#else +XMLPUBVAR xmlGenericErrorFunc xmlGenericError; +#endif + +XMLPUBFUN xmlStructuredErrorFunc * XMLCALL __xmlStructuredError(void); +#ifdef LIBXML_THREAD_ENABLED +#define xmlStructuredError \ +(*(__xmlStructuredError())) +#else +XMLPUBVAR xmlStructuredErrorFunc xmlStructuredError; +#endif + +XMLPUBFUN void * * XMLCALL __xmlGenericErrorContext(void); +#ifdef LIBXML_THREAD_ENABLED +#define xmlGenericErrorContext \ +(*(__xmlGenericErrorContext())) +#else +XMLPUBVAR void * xmlGenericErrorContext; +#endif + +XMLPUBFUN int * XMLCALL __xmlGetWarningsDefaultValue(void); +#ifdef LIBXML_THREAD_ENABLED +#define xmlGetWarningsDefaultValue \ +(*(__xmlGetWarningsDefaultValue())) +#else +XMLPUBVAR int xmlGetWarningsDefaultValue; +#endif +XMLPUBFUN int XMLCALL xmlThrDefGetWarningsDefaultValue(int v); + +XMLPUBFUN int * XMLCALL __xmlIndentTreeOutput(void); +#ifdef LIBXML_THREAD_ENABLED +#define xmlIndentTreeOutput \ +(*(__xmlIndentTreeOutput())) +#else +XMLPUBVAR int xmlIndentTreeOutput; +#endif +XMLPUBFUN int XMLCALL xmlThrDefIndentTreeOutput(int v); + +XMLPUBFUN const char * * XMLCALL __xmlTreeIndentString(void); +#ifdef LIBXML_THREAD_ENABLED +#define xmlTreeIndentString \ +(*(__xmlTreeIndentString())) +#else +XMLPUBVAR const char * xmlTreeIndentString; +#endif +XMLPUBFUN const char * XMLCALL xmlThrDefTreeIndentString(const char * v); + +XMLPUBFUN int * XMLCALL __xmlKeepBlanksDefaultValue(void); +#ifdef LIBXML_THREAD_ENABLED +#define xmlKeepBlanksDefaultValue \ +(*(__xmlKeepBlanksDefaultValue())) +#else +XMLPUBVAR int xmlKeepBlanksDefaultValue; +#endif +XMLPUBFUN int XMLCALL xmlThrDefKeepBlanksDefaultValue(int v); + +XMLPUBFUN int * XMLCALL __xmlLineNumbersDefaultValue(void); +#ifdef LIBXML_THREAD_ENABLED +#define xmlLineNumbersDefaultValue \ +(*(__xmlLineNumbersDefaultValue())) +#else +XMLPUBVAR int xmlLineNumbersDefaultValue; +#endif +XMLPUBFUN int XMLCALL xmlThrDefLineNumbersDefaultValue(int v); + +XMLPUBFUN int * XMLCALL __xmlLoadExtDtdDefaultValue(void); +#ifdef LIBXML_THREAD_ENABLED +#define xmlLoadExtDtdDefaultValue \ +(*(__xmlLoadExtDtdDefaultValue())) +#else +XMLPUBVAR int xmlLoadExtDtdDefaultValue; +#endif +XMLPUBFUN int XMLCALL xmlThrDefLoadExtDtdDefaultValue(int v); + +XMLPUBFUN int * XMLCALL __xmlParserDebugEntities(void); +#ifdef LIBXML_THREAD_ENABLED +#define xmlParserDebugEntities \ +(*(__xmlParserDebugEntities())) +#else +XMLPUBVAR int xmlParserDebugEntities; +#endif +XMLPUBFUN int XMLCALL xmlThrDefParserDebugEntities(int v); + +XMLPUBFUN const char * * XMLCALL __xmlParserVersion(void); +#ifdef LIBXML_THREAD_ENABLED +#define xmlParserVersion \ +(*(__xmlParserVersion())) +#else +XMLPUBVAR const char * xmlParserVersion; +#endif + +XMLPUBFUN int * XMLCALL __xmlPedanticParserDefaultValue(void); +#ifdef LIBXML_THREAD_ENABLED +#define xmlPedanticParserDefaultValue \ +(*(__xmlPedanticParserDefaultValue())) +#else +XMLPUBVAR int xmlPedanticParserDefaultValue; +#endif +XMLPUBFUN int XMLCALL xmlThrDefPedanticParserDefaultValue(int v); + +XMLPUBFUN int * XMLCALL __xmlSaveNoEmptyTags(void); +#ifdef LIBXML_THREAD_ENABLED +#define xmlSaveNoEmptyTags \ +(*(__xmlSaveNoEmptyTags())) +#else +XMLPUBVAR int xmlSaveNoEmptyTags; +#endif +XMLPUBFUN int XMLCALL xmlThrDefSaveNoEmptyTags(int v); + +XMLPUBFUN int * XMLCALL __xmlSubstituteEntitiesDefaultValue(void); +#ifdef LIBXML_THREAD_ENABLED +#define xmlSubstituteEntitiesDefaultValue \ +(*(__xmlSubstituteEntitiesDefaultValue())) +#else +XMLPUBVAR int xmlSubstituteEntitiesDefaultValue; +#endif +XMLPUBFUN int XMLCALL xmlThrDefSubstituteEntitiesDefaultValue(int v); + +XMLPUBFUN xmlRegisterNodeFunc * XMLCALL __xmlRegisterNodeDefaultValue(void); +#ifdef LIBXML_THREAD_ENABLED +#define xmlRegisterNodeDefaultValue \ +(*(__xmlRegisterNodeDefaultValue())) +#else +XMLPUBVAR xmlRegisterNodeFunc xmlRegisterNodeDefaultValue; +#endif + +XMLPUBFUN xmlDeregisterNodeFunc * XMLCALL __xmlDeregisterNodeDefaultValue(void); +#ifdef LIBXML_THREAD_ENABLED +#define xmlDeregisterNodeDefaultValue \ +(*(__xmlDeregisterNodeDefaultValue())) +#else +XMLPUBVAR xmlDeregisterNodeFunc xmlDeregisterNodeDefaultValue; +#endif + +XMLPUBFUN xmlParserInputBufferCreateFilenameFunc * XMLCALL __xmlParserInputBufferCreateFilenameValue(void); +#ifdef LIBXML_THREAD_ENABLED +#define xmlParserInputBufferCreateFilenameValue \ +(*(__xmlParserInputBufferCreateFilenameValue())) +#else +XMLPUBVAR xmlParserInputBufferCreateFilenameFunc xmlParserInputBufferCreateFilenameValue; +#endif + +XMLPUBFUN xmlOutputBufferCreateFilenameFunc * XMLCALL __xmlOutputBufferCreateFilenameValue(void); +#ifdef LIBXML_THREAD_ENABLED +#define xmlOutputBufferCreateFilenameValue \ +(*(__xmlOutputBufferCreateFilenameValue())) +#else +XMLPUBVAR xmlOutputBufferCreateFilenameFunc xmlOutputBufferCreateFilenameValue; +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __XML_GLOBALS_H */ diff --git a/gettext-tools/gnulib-lib/libxml/hash.c b/gettext-tools/gnulib-lib/libxml/hash.c new file mode 100644 index 0000000..e92a5a0 --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/hash.c @@ -0,0 +1,1079 @@ +/* + * hash.c: chained hash tables + * + * Reference: Your favorite introductory book on algorithms + * + * Copyright (C) 2000 Bjorn Reese and Daniel Veillard. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND + * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER. + * + * Author: breese@users.sourceforge.net + */ + +#define IN_LIBXML +#include "libxml.h" + +#include +#include +#include +#include +#include +#include + +#define MAX_HASH_LEN 8 + +/* #define DEBUG_GROW */ + +/* + * A single entry in the hash table + */ +typedef struct _xmlHashEntry xmlHashEntry; +typedef xmlHashEntry *xmlHashEntryPtr; +struct _xmlHashEntry { + struct _xmlHashEntry *next; + xmlChar *name; + xmlChar *name2; + xmlChar *name3; + void *payload; + int valid; +}; + +/* + * The entire hash table + */ +struct _xmlHashTable { + struct _xmlHashEntry *table; + int size; + int nbElems; + xmlDictPtr dict; +}; + +/* + * xmlHashComputeKey: + * Calculate the hash key + */ +static unsigned long +xmlHashComputeKey(xmlHashTablePtr table, const xmlChar *name, + const xmlChar *name2, const xmlChar *name3) { + unsigned long value = 0L; + char ch; + + if (name != NULL) { + value += 30 * (*name); + while ((ch = *name++) != 0) { + value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch); + } + } + if (name2 != NULL) { + while ((ch = *name2++) != 0) { + value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch); + } + } + if (name3 != NULL) { + while ((ch = *name3++) != 0) { + value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch); + } + } + return (value % table->size); +} + +static unsigned long +xmlHashComputeQKey(xmlHashTablePtr table, + const xmlChar *prefix, const xmlChar *name, + const xmlChar *prefix2, const xmlChar *name2, + const xmlChar *prefix3, const xmlChar *name3) { + unsigned long value = 0L; + char ch; + + if (prefix != NULL) + value += 30 * (*prefix); + else + value += 30 * (*name); + + if (prefix != NULL) { + while ((ch = *prefix++) != 0) { + value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch); + } + value = value ^ ((value << 5) + (value >> 3) + (unsigned long)':'); + } + if (name != NULL) { + while ((ch = *name++) != 0) { + value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch); + } + } + if (prefix2 != NULL) { + while ((ch = *prefix2++) != 0) { + value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch); + } + value = value ^ ((value << 5) + (value >> 3) + (unsigned long)':'); + } + if (name2 != NULL) { + while ((ch = *name2++) != 0) { + value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch); + } + } + if (prefix3 != NULL) { + while ((ch = *prefix3++) != 0) { + value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch); + } + value = value ^ ((value << 5) + (value >> 3) + (unsigned long)':'); + } + if (name3 != NULL) { + while ((ch = *name3++) != 0) { + value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch); + } + } + return (value % table->size); +} + +/** + * xmlHashCreate: + * @size: the size of the hash table + * + * Create a new xmlHashTablePtr. + * + * Returns the newly created object, or NULL if an error occured. + */ +xmlHashTablePtr +xmlHashCreate(int size) { + xmlHashTablePtr table; + + if (size <= 0) + size = 256; + + table = xmlMalloc(sizeof(xmlHashTable)); + if (table) { + table->dict = NULL; + table->size = size; + table->nbElems = 0; + table->table = xmlMalloc(size * sizeof(xmlHashEntry)); + if (table->table) { + memset(table->table, 0, size * sizeof(xmlHashEntry)); + return(table); + } + xmlFree(table); + } + return(NULL); +} + +/** + * xmlHashCreateDict: + * @size: the size of the hash table + * @dict: a dictionary to use for the hash + * + * Create a new xmlHashTablePtr which will use @dict as the internal dictionary + * + * Returns the newly created object, or NULL if an error occured. + */ +xmlHashTablePtr +xmlHashCreateDict(int size, xmlDictPtr dict) { + xmlHashTablePtr table; + + table = xmlHashCreate(size); + if (table != NULL) { + table->dict = dict; + xmlDictReference(dict); + } + return(table); +} + +/** + * xmlHashGrow: + * @table: the hash table + * @size: the new size of the hash table + * + * resize the hash table + * + * Returns 0 in case of success, -1 in case of failure + */ +static int +xmlHashGrow(xmlHashTablePtr table, int size) { + unsigned long key; + int oldsize, i; + xmlHashEntryPtr iter, next; + struct _xmlHashEntry *oldtable; +#ifdef DEBUG_GROW + unsigned long nbElem = 0; +#endif + + if (table == NULL) + return(-1); + if (size < 8) + return(-1); + if (size > 8 * 2048) + return(-1); + + oldsize = table->size; + oldtable = table->table; + if (oldtable == NULL) + return(-1); + + table->table = xmlMalloc(size * sizeof(xmlHashEntry)); + if (table->table == NULL) { + table->table = oldtable; + return(-1); + } + memset(table->table, 0, size * sizeof(xmlHashEntry)); + table->size = size; + + /* If the two loops are merged, there would be situations where + a new entry needs to allocated and data copied into it from + the main table. So instead, we run through the array twice, first + copying all the elements in the main array (where we can't get + conflicts) and then the rest, so we only free (and don't allocate) + */ + for (i = 0; i < oldsize; i++) { + if (oldtable[i].valid == 0) + continue; + key = xmlHashComputeKey(table, oldtable[i].name, oldtable[i].name2, + oldtable[i].name3); + memcpy(&(table->table[key]), &(oldtable[i]), sizeof(xmlHashEntry)); + table->table[key].next = NULL; + } + + for (i = 0; i < oldsize; i++) { + iter = oldtable[i].next; + while (iter) { + next = iter->next; + + /* + * put back the entry in the new table + */ + + key = xmlHashComputeKey(table, iter->name, iter->name2, + iter->name3); + if (table->table[key].valid == 0) { + memcpy(&(table->table[key]), iter, sizeof(xmlHashEntry)); + table->table[key].next = NULL; + xmlFree(iter); + } else { + iter->next = table->table[key].next; + table->table[key].next = iter; + } + +#ifdef DEBUG_GROW + nbElem++; +#endif + + iter = next; + } + } + + xmlFree(oldtable); + +#ifdef DEBUG_GROW + xmlGenericError(xmlGenericErrorContext, + "xmlHashGrow : from %d to %d, %d elems\n", oldsize, size, nbElem); +#endif + + return(0); +} + +/** + * xmlHashFree: + * @table: the hash table + * @f: the deallocator function for items in the hash + * + * Free the hash @table and its contents. The userdata is + * deallocated with @f if provided. + */ +void +xmlHashFree(xmlHashTablePtr table, xmlHashDeallocator f) { + int i; + xmlHashEntryPtr iter; + xmlHashEntryPtr next; + int inside_table = 0; + int nbElems; + + if (table == NULL) + return; + if (table->table) { + nbElems = table->nbElems; + for(i = 0; (i < table->size) && (nbElems > 0); i++) { + iter = &(table->table[i]); + if (iter->valid == 0) + continue; + inside_table = 1; + while (iter) { + next = iter->next; + if ((f != NULL) && (iter->payload != NULL)) + f(iter->payload, iter->name); + if (table->dict == NULL) { + if (iter->name) + xmlFree(iter->name); + if (iter->name2) + xmlFree(iter->name2); + if (iter->name3) + xmlFree(iter->name3); + } + iter->payload = NULL; + if (!inside_table) + xmlFree(iter); + nbElems--; + inside_table = 0; + iter = next; + } + inside_table = 0; + } + xmlFree(table->table); + } + if (table->dict) + xmlDictFree(table->dict); + xmlFree(table); +} + +/** + * xmlHashAddEntry: + * @table: the hash table + * @name: the name of the userdata + * @userdata: a pointer to the userdata + * + * Add the @userdata to the hash @table. This can later be retrieved + * by using the @name. Duplicate names generate errors. + * + * Returns 0 the addition succeeded and -1 in case of error. + */ +int +xmlHashAddEntry(xmlHashTablePtr table, const xmlChar *name, void *userdata) { + return(xmlHashAddEntry3(table, name, NULL, NULL, userdata)); +} + +/** + * xmlHashAddEntry2: + * @table: the hash table + * @name: the name of the userdata + * @name2: a second name of the userdata + * @userdata: a pointer to the userdata + * + * Add the @userdata to the hash @table. This can later be retrieved + * by using the (@name, @name2) tuple. Duplicate tuples generate errors. + * + * Returns 0 the addition succeeded and -1 in case of error. + */ +int +xmlHashAddEntry2(xmlHashTablePtr table, const xmlChar *name, + const xmlChar *name2, void *userdata) { + return(xmlHashAddEntry3(table, name, name2, NULL, userdata)); +} + +/** + * xmlHashUpdateEntry: + * @table: the hash table + * @name: the name of the userdata + * @userdata: a pointer to the userdata + * @f: the deallocator function for replaced item (if any) + * + * Add the @userdata to the hash @table. This can later be retrieved + * by using the @name. Existing entry for this @name will be removed + * and freed with @f if found. + * + * Returns 0 the addition succeeded and -1 in case of error. + */ +int +xmlHashUpdateEntry(xmlHashTablePtr table, const xmlChar *name, + void *userdata, xmlHashDeallocator f) { + return(xmlHashUpdateEntry3(table, name, NULL, NULL, userdata, f)); +} + +/** + * xmlHashUpdateEntry2: + * @table: the hash table + * @name: the name of the userdata + * @name2: a second name of the userdata + * @userdata: a pointer to the userdata + * @f: the deallocator function for replaced item (if any) + * + * Add the @userdata to the hash @table. This can later be retrieved + * by using the (@name, @name2) tuple. Existing entry for this tuple will + * be removed and freed with @f if found. + * + * Returns 0 the addition succeeded and -1 in case of error. + */ +int +xmlHashUpdateEntry2(xmlHashTablePtr table, const xmlChar *name, + const xmlChar *name2, void *userdata, + xmlHashDeallocator f) { + return(xmlHashUpdateEntry3(table, name, name2, NULL, userdata, f)); +} + +/** + * xmlHashLookup: + * @table: the hash table + * @name: the name of the userdata + * + * Find the userdata specified by the @name. + * + * Returns the pointer to the userdata + */ +void * +xmlHashLookup(xmlHashTablePtr table, const xmlChar *name) { + return(xmlHashLookup3(table, name, NULL, NULL)); +} + +/** + * xmlHashLookup2: + * @table: the hash table + * @name: the name of the userdata + * @name2: a second name of the userdata + * + * Find the userdata specified by the (@name, @name2) tuple. + * + * Returns the pointer to the userdata + */ +void * +xmlHashLookup2(xmlHashTablePtr table, const xmlChar *name, + const xmlChar *name2) { + return(xmlHashLookup3(table, name, name2, NULL)); +} + +/** + * xmlHashQLookup: + * @table: the hash table + * @prefix: the prefix of the userdata + * @name: the name of the userdata + * + * Find the userdata specified by the QName @prefix:@name/@name. + * + * Returns the pointer to the userdata + */ +void * +xmlHashQLookup(xmlHashTablePtr table, const xmlChar *prefix, + const xmlChar *name) { + return(xmlHashQLookup3(table, prefix, name, NULL, NULL, NULL, NULL)); +} + +/** + * xmlHashQLookup2: + * @table: the hash table + * @prefix: the prefix of the userdata + * @name: the name of the userdata + * @prefix2: the second prefix of the userdata + * @name2: a second name of the userdata + * + * Find the userdata specified by the QNames tuple + * + * Returns the pointer to the userdata + */ +void * +xmlHashQLookup2(xmlHashTablePtr table, const xmlChar *prefix, + const xmlChar *name, const xmlChar *prefix2, + const xmlChar *name2) { + return(xmlHashQLookup3(table, prefix, name, prefix2, name2, NULL, NULL)); +} + +/** + * xmlHashAddEntry3: + * @table: the hash table + * @name: the name of the userdata + * @name2: a second name of the userdata + * @name3: a third name of the userdata + * @userdata: a pointer to the userdata + * + * Add the @userdata to the hash @table. This can later be retrieved + * by using the tuple (@name, @name2, @name3). Duplicate entries generate + * errors. + * + * Returns 0 the addition succeeded and -1 in case of error. + */ +int +xmlHashAddEntry3(xmlHashTablePtr table, const xmlChar *name, + const xmlChar *name2, const xmlChar *name3, + void *userdata) { + unsigned long key, len = 0; + xmlHashEntryPtr entry; + xmlHashEntryPtr insert; + + if ((table == NULL) || (name == NULL)) + return(-1); + + /* + * If using a dict internalize if needed + */ + if (table->dict) { + if (!xmlDictOwns(table->dict, name)) { + name = xmlDictLookup(table->dict, name, -1); + if (name == NULL) + return(-1); + } + if ((name2 != NULL) && (!xmlDictOwns(table->dict, name2))) { + name2 = xmlDictLookup(table->dict, name2, -1); + if (name2 == NULL) + return(-1); + } + if ((name3 != NULL) && (!xmlDictOwns(table->dict, name3))) { + name3 = xmlDictLookup(table->dict, name3, -1); + if (name3 == NULL) + return(-1); + } + } + + /* + * Check for duplicate and insertion location. + */ + key = xmlHashComputeKey(table, name, name2, name3); + if (table->table[key].valid == 0) { + insert = NULL; + } else { + if (table->dict) { + for (insert = &(table->table[key]); insert->next != NULL; + insert = insert->next) { + if ((insert->name == name) && + (insert->name2 == name2) && + (insert->name3 == name3)) + return(-1); + len++; + } + if ((insert->name == name) && + (insert->name2 == name2) && + (insert->name3 == name3)) + return(-1); + } else { + for (insert = &(table->table[key]); insert->next != NULL; + insert = insert->next) { + if ((xmlStrEqual(insert->name, name)) && + (xmlStrEqual(insert->name2, name2)) && + (xmlStrEqual(insert->name3, name3))) + return(-1); + len++; + } + if ((xmlStrEqual(insert->name, name)) && + (xmlStrEqual(insert->name2, name2)) && + (xmlStrEqual(insert->name3, name3))) + return(-1); + } + } + + if (insert == NULL) { + entry = &(table->table[key]); + } else { + entry = xmlMalloc(sizeof(xmlHashEntry)); + if (entry == NULL) + return(-1); + } + + if (table->dict != NULL) { + entry->name = (xmlChar *) name; + entry->name2 = (xmlChar *) name2; + entry->name3 = (xmlChar *) name3; + } else { + entry->name = xmlStrdup(name); + entry->name2 = xmlStrdup(name2); + entry->name3 = xmlStrdup(name3); + } + entry->payload = userdata; + entry->next = NULL; + entry->valid = 1; + + + if (insert != NULL) + insert->next = entry; + + table->nbElems++; + + if (len > MAX_HASH_LEN) + xmlHashGrow(table, MAX_HASH_LEN * table->size); + + return(0); +} + +/** + * xmlHashUpdateEntry3: + * @table: the hash table + * @name: the name of the userdata + * @name2: a second name of the userdata + * @name3: a third name of the userdata + * @userdata: a pointer to the userdata + * @f: the deallocator function for replaced item (if any) + * + * Add the @userdata to the hash @table. This can later be retrieved + * by using the tuple (@name, @name2, @name3). Existing entry for this tuple + * will be removed and freed with @f if found. + * + * Returns 0 the addition succeeded and -1 in case of error. + */ +int +xmlHashUpdateEntry3(xmlHashTablePtr table, const xmlChar *name, + const xmlChar *name2, const xmlChar *name3, + void *userdata, xmlHashDeallocator f) { + unsigned long key; + xmlHashEntryPtr entry; + xmlHashEntryPtr insert; + + if ((table == NULL) || name == NULL) + return(-1); + + /* + * If using a dict internalize if needed + */ + if (table->dict) { + if (!xmlDictOwns(table->dict, name)) { + name = xmlDictLookup(table->dict, name, -1); + if (name == NULL) + return(-1); + } + if ((name2 != NULL) && (!xmlDictOwns(table->dict, name2))) { + name2 = xmlDictLookup(table->dict, name2, -1); + if (name2 == NULL) + return(-1); + } + if ((name3 != NULL) && (!xmlDictOwns(table->dict, name3))) { + name3 = xmlDictLookup(table->dict, name3, -1); + if (name3 == NULL) + return(-1); + } + } + + /* + * Check for duplicate and insertion location. + */ + key = xmlHashComputeKey(table, name, name2, name3); + if (table->table[key].valid == 0) { + insert = NULL; + } else { + if (table ->dict) { + for (insert = &(table->table[key]); insert->next != NULL; + insert = insert->next) { + if ((insert->name == name) && + (insert->name2 == name2) && + (insert->name3 == name3)) { + if (f) + f(insert->payload, insert->name); + insert->payload = userdata; + return(0); + } + } + if ((insert->name == name) && + (insert->name2 == name2) && + (insert->name3 == name3)) { + if (f) + f(insert->payload, insert->name); + insert->payload = userdata; + return(0); + } + } else { + for (insert = &(table->table[key]); insert->next != NULL; + insert = insert->next) { + if ((xmlStrEqual(insert->name, name)) && + (xmlStrEqual(insert->name2, name2)) && + (xmlStrEqual(insert->name3, name3))) { + if (f) + f(insert->payload, insert->name); + insert->payload = userdata; + return(0); + } + } + if ((xmlStrEqual(insert->name, name)) && + (xmlStrEqual(insert->name2, name2)) && + (xmlStrEqual(insert->name3, name3))) { + if (f) + f(insert->payload, insert->name); + insert->payload = userdata; + return(0); + } + } + } + + if (insert == NULL) { + entry = &(table->table[key]); + } else { + entry = xmlMalloc(sizeof(xmlHashEntry)); + if (entry == NULL) + return(-1); + } + + if (table->dict != NULL) { + entry->name = (xmlChar *) name; + entry->name2 = (xmlChar *) name2; + entry->name3 = (xmlChar *) name3; + } else { + entry->name = xmlStrdup(name); + entry->name2 = xmlStrdup(name2); + entry->name3 = xmlStrdup(name3); + } + entry->payload = userdata; + entry->next = NULL; + entry->valid = 1; + table->nbElems++; + + + if (insert != NULL) { + insert->next = entry; + } + return(0); +} + +/** + * xmlHashLookup3: + * @table: the hash table + * @name: the name of the userdata + * @name2: a second name of the userdata + * @name3: a third name of the userdata + * + * Find the userdata specified by the (@name, @name2, @name3) tuple. + * + * Returns the a pointer to the userdata + */ +void * +xmlHashLookup3(xmlHashTablePtr table, const xmlChar *name, + const xmlChar *name2, const xmlChar *name3) { + unsigned long key; + xmlHashEntryPtr entry; + + if (table == NULL) + return(NULL); + if (name == NULL) + return(NULL); + key = xmlHashComputeKey(table, name, name2, name3); + if (table->table[key].valid == 0) + return(NULL); + if (table->dict) { + for (entry = &(table->table[key]); entry != NULL; entry = entry->next) { + if ((entry->name == name) && + (entry->name2 == name2) && + (entry->name3 == name3)) + return(entry->payload); + } + } + for (entry = &(table->table[key]); entry != NULL; entry = entry->next) { + if ((xmlStrEqual(entry->name, name)) && + (xmlStrEqual(entry->name2, name2)) && + (xmlStrEqual(entry->name3, name3))) + return(entry->payload); + } + return(NULL); +} + +/** + * xmlHashQLookup3: + * @table: the hash table + * @prefix: the prefix of the userdata + * @name: the name of the userdata + * @prefix2: the second prefix of the userdata + * @name2: a second name of the userdata + * @prefix3: the third prefix of the userdata + * @name3: a third name of the userdata + * + * Find the userdata specified by the (@name, @name2, @name3) tuple. + * + * Returns the a pointer to the userdata + */ +void * +xmlHashQLookup3(xmlHashTablePtr table, + const xmlChar *prefix, const xmlChar *name, + const xmlChar *prefix2, const xmlChar *name2, + const xmlChar *prefix3, const xmlChar *name3) { + unsigned long key; + xmlHashEntryPtr entry; + + if (table == NULL) + return(NULL); + if (name == NULL) + return(NULL); + key = xmlHashComputeQKey(table, prefix, name, prefix2, + name2, prefix3, name3); + if (table->table[key].valid == 0) + return(NULL); + for (entry = &(table->table[key]); entry != NULL; entry = entry->next) { + if ((xmlStrQEqual(prefix, name, entry->name)) && + (xmlStrQEqual(prefix2, name2, entry->name2)) && + (xmlStrQEqual(prefix3, name3, entry->name3))) + return(entry->payload); + } + return(NULL); +} + +typedef struct { + xmlHashScanner hashscanner; + void *data; +} stubData; + +static void +stubHashScannerFull (void *payload, void *data, const xmlChar *name, + const xmlChar *name2 ATTRIBUTE_UNUSED, + const xmlChar *name3 ATTRIBUTE_UNUSED) { + stubData *stubdata = (stubData *) data; + stubdata->hashscanner (payload, stubdata->data, (xmlChar *) name); +} + +/** + * xmlHashScan: + * @table: the hash table + * @f: the scanner function for items in the hash + * @data: extra data passed to f + * + * Scan the hash @table and applied @f to each value. + */ +void +xmlHashScan(xmlHashTablePtr table, xmlHashScanner f, void *data) { + stubData stubdata; + stubdata.data = data; + stubdata.hashscanner = f; + xmlHashScanFull (table, stubHashScannerFull, &stubdata); +} + +/** + * xmlHashScanFull: + * @table: the hash table + * @f: the scanner function for items in the hash + * @data: extra data passed to f + * + * Scan the hash @table and applied @f to each value. + */ +void +xmlHashScanFull(xmlHashTablePtr table, xmlHashScannerFull f, void *data) { + int i; + xmlHashEntryPtr iter; + xmlHashEntryPtr next; + + if (table == NULL) + return; + if (f == NULL) + return; + + if (table->table) { + for(i = 0; i < table->size; i++) { + if (table->table[i].valid == 0) + continue; + iter = &(table->table[i]); + while (iter) { + next = iter->next; + if ((f != NULL) && (iter->payload != NULL)) + f(iter->payload, data, iter->name, + iter->name2, iter->name3); + iter = next; + } + } + } +} + +/** + * xmlHashScan3: + * @table: the hash table + * @name: the name of the userdata or NULL + * @name2: a second name of the userdata or NULL + * @name3: a third name of the userdata or NULL + * @f: the scanner function for items in the hash + * @data: extra data passed to f + * + * Scan the hash @table and applied @f to each value matching + * (@name, @name2, @name3) tuple. If one of the names is null, + * the comparison is considered to match. + */ +void +xmlHashScan3(xmlHashTablePtr table, const xmlChar *name, + const xmlChar *name2, const xmlChar *name3, + xmlHashScanner f, void *data) { + xmlHashScanFull3 (table, name, name2, name3, + (xmlHashScannerFull) f, data); +} + +/** + * xmlHashScanFull3: + * @table: the hash table + * @name: the name of the userdata or NULL + * @name2: a second name of the userdata or NULL + * @name3: a third name of the userdata or NULL + * @f: the scanner function for items in the hash + * @data: extra data passed to f + * + * Scan the hash @table and applied @f to each value matching + * (@name, @name2, @name3) tuple. If one of the names is null, + * the comparison is considered to match. + */ +void +xmlHashScanFull3(xmlHashTablePtr table, const xmlChar *name, + const xmlChar *name2, const xmlChar *name3, + xmlHashScannerFull f, void *data) { + int i; + xmlHashEntryPtr iter; + xmlHashEntryPtr next; + + if (table == NULL) + return; + if (f == NULL) + return; + + if (table->table) { + for(i = 0; i < table->size; i++) { + if (table->table[i].valid == 0) + continue; + iter = &(table->table[i]); + while (iter) { + next = iter->next; + if (((name == NULL) || (xmlStrEqual(name, iter->name))) && + ((name2 == NULL) || (xmlStrEqual(name2, iter->name2))) && + ((name3 == NULL) || (xmlStrEqual(name3, iter->name3))) && + (iter->payload != NULL)) { + f(iter->payload, data, iter->name, + iter->name2, iter->name3); + } + iter = next; + } + } + } +} + +/** + * xmlHashCopy: + * @table: the hash table + * @f: the copier function for items in the hash + * + * Scan the hash @table and applied @f to each value. + * + * Returns the new table or NULL in case of error. + */ +xmlHashTablePtr +xmlHashCopy(xmlHashTablePtr table, xmlHashCopier f) { + int i; + xmlHashEntryPtr iter; + xmlHashEntryPtr next; + xmlHashTablePtr ret; + + if (table == NULL) + return(NULL); + if (f == NULL) + return(NULL); + + ret = xmlHashCreate(table->size); + if (table->table) { + for(i = 0; i < table->size; i++) { + if (table->table[i].valid == 0) + continue; + iter = &(table->table[i]); + while (iter) { + next = iter->next; + xmlHashAddEntry3(ret, iter->name, iter->name2, + iter->name3, f(iter->payload, iter->name)); + iter = next; + } + } + } + ret->nbElems = table->nbElems; + return(ret); +} + +/** + * xmlHashSize: + * @table: the hash table + * + * Query the number of elements installed in the hash @table. + * + * Returns the number of elements in the hash table or + * -1 in case of error + */ +int +xmlHashSize(xmlHashTablePtr table) { + if (table == NULL) + return(-1); + return(table->nbElems); +} + +/** + * xmlHashRemoveEntry: + * @table: the hash table + * @name: the name of the userdata + * @f: the deallocator function for removed item (if any) + * + * Find the userdata specified by the @name and remove + * it from the hash @table. Existing userdata for this tuple will be removed + * and freed with @f. + * + * Returns 0 if the removal succeeded and -1 in case of error or not found. + */ +int xmlHashRemoveEntry(xmlHashTablePtr table, const xmlChar *name, + xmlHashDeallocator f) { + return(xmlHashRemoveEntry3(table, name, NULL, NULL, f)); +} + +/** + * xmlHashRemoveEntry2: + * @table: the hash table + * @name: the name of the userdata + * @name2: a second name of the userdata + * @f: the deallocator function for removed item (if any) + * + * Find the userdata specified by the (@name, @name2) tuple and remove + * it from the hash @table. Existing userdata for this tuple will be removed + * and freed with @f. + * + * Returns 0 if the removal succeeded and -1 in case of error or not found. + */ +int +xmlHashRemoveEntry2(xmlHashTablePtr table, const xmlChar *name, + const xmlChar *name2, xmlHashDeallocator f) { + return(xmlHashRemoveEntry3(table, name, name2, NULL, f)); +} + +/** + * xmlHashRemoveEntry3: + * @table: the hash table + * @name: the name of the userdata + * @name2: a second name of the userdata + * @name3: a third name of the userdata + * @f: the deallocator function for removed item (if any) + * + * Find the userdata specified by the (@name, @name2, @name3) tuple and remove + * it from the hash @table. Existing userdata for this tuple will be removed + * and freed with @f. + * + * Returns 0 if the removal succeeded and -1 in case of error or not found. + */ +int +xmlHashRemoveEntry3(xmlHashTablePtr table, const xmlChar *name, + const xmlChar *name2, const xmlChar *name3, xmlHashDeallocator f) { + unsigned long key; + xmlHashEntryPtr entry; + xmlHashEntryPtr prev = NULL; + + if (table == NULL || name == NULL) + return(-1); + + key = xmlHashComputeKey(table, name, name2, name3); + if (table->table[key].valid == 0) { + return(-1); + } else { + for (entry = &(table->table[key]); entry != NULL; entry = entry->next) { + if (xmlStrEqual(entry->name, name) && + xmlStrEqual(entry->name2, name2) && + xmlStrEqual(entry->name3, name3)) { + if ((f != NULL) && (entry->payload != NULL)) + f(entry->payload, entry->name); + entry->payload = NULL; + if (table->dict == NULL) { + if(entry->name) + xmlFree(entry->name); + if(entry->name2) + xmlFree(entry->name2); + if(entry->name3) + xmlFree(entry->name3); + } + if(prev) { + prev->next = entry->next; + xmlFree(entry); + } else { + if (entry->next == NULL) { + entry->valid = 0; + } else { + entry = entry->next; + memcpy(&(table->table[key]), entry, sizeof(xmlHashEntry)); + xmlFree(entry); + } + } + table->nbElems--; + return(0); + } + prev = entry; + } + return(-1); + } +} + +#define bottom_hash +#include "elfgcchack.h" diff --git a/gettext-tools/gnulib-lib/libxml/hash.in.h b/gettext-tools/gnulib-lib/libxml/hash.in.h new file mode 100644 index 0000000..7fe4be7 --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/hash.in.h @@ -0,0 +1,233 @@ +/* + * Summary: Chained hash tables + * Description: This module implements the hash table support used in + * various places in the library. + * + * Copy: See Copyright for the status of this software. + * + * Author: Bjorn Reese + */ + +#ifndef __XML_HASH_H__ +#define __XML_HASH_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * The hash table. + */ +typedef struct _xmlHashTable xmlHashTable; +typedef xmlHashTable *xmlHashTablePtr; + +#ifdef __cplusplus +} +#endif + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Recent version of gcc produce a warning when a function pointer is assigned + * to an object pointer, or vice versa. The following macro is a dirty hack + * to allow suppression of the warning. If your architecture has function + * pointers which are a different size than a void pointer, there may be some + * serious trouble within the library. + */ +/** + * XML_CAST_FPTR: + * @fptr: pointer to a function + * + * Macro to do a casting from an object pointer to a + * function pointer without encountering a warning from + * gcc + * + * #define XML_CAST_FPTR(fptr) (*(void **)(&fptr)) + * This macro violated ISO C aliasing rules (gcc4 on s390 broke) + * so it is disabled now + */ + +#define XML_CAST_FPTR(fptr) fptr + + +/* + * function types: + */ +/** + * xmlHashDeallocator: + * @payload: the data in the hash + * @name: the name associated + * + * Callback to free data from a hash. + */ +typedef void (*xmlHashDeallocator)(void *payload, xmlChar *name); +/** + * xmlHashCopier: + * @payload: the data in the hash + * @name: the name associated + * + * Callback to copy data from a hash. + * + * Returns a copy of the data or NULL in case of error. + */ +typedef void *(*xmlHashCopier)(void *payload, xmlChar *name); +/** + * xmlHashScanner: + * @payload: the data in the hash + * @data: extra scannner data + * @name: the name associated + * + * Callback when scanning data in a hash with the simple scanner. + */ +typedef void (*xmlHashScanner)(void *payload, void *data, xmlChar *name); +/** + * xmlHashScannerFull: + * @payload: the data in the hash + * @data: extra scannner data + * @name: the name associated + * @name2: the second name associated + * @name3: the third name associated + * + * Callback when scanning data in a hash with the full scanner. + */ +typedef void (*xmlHashScannerFull)(void *payload, void *data, + const xmlChar *name, const xmlChar *name2, + const xmlChar *name3); + +/* + * Constructor and destructor. + */ +XMLPUBFUN xmlHashTablePtr XMLCALL + xmlHashCreate (int size); +XMLPUBFUN xmlHashTablePtr XMLCALL + xmlHashCreateDict(int size, + xmlDictPtr dict); +XMLPUBFUN void XMLCALL + xmlHashFree (xmlHashTablePtr table, + xmlHashDeallocator f); + +/* + * Add a new entry to the hash table. + */ +XMLPUBFUN int XMLCALL + xmlHashAddEntry (xmlHashTablePtr table, + const xmlChar *name, + void *userdata); +XMLPUBFUN int XMLCALL + xmlHashUpdateEntry(xmlHashTablePtr table, + const xmlChar *name, + void *userdata, + xmlHashDeallocator f); +XMLPUBFUN int XMLCALL + xmlHashAddEntry2(xmlHashTablePtr table, + const xmlChar *name, + const xmlChar *name2, + void *userdata); +XMLPUBFUN int XMLCALL + xmlHashUpdateEntry2(xmlHashTablePtr table, + const xmlChar *name, + const xmlChar *name2, + void *userdata, + xmlHashDeallocator f); +XMLPUBFUN int XMLCALL + xmlHashAddEntry3(xmlHashTablePtr table, + const xmlChar *name, + const xmlChar *name2, + const xmlChar *name3, + void *userdata); +XMLPUBFUN int XMLCALL + xmlHashUpdateEntry3(xmlHashTablePtr table, + const xmlChar *name, + const xmlChar *name2, + const xmlChar *name3, + void *userdata, + xmlHashDeallocator f); + +/* + * Remove an entry from the hash table. + */ +XMLPUBFUN int XMLCALL + xmlHashRemoveEntry(xmlHashTablePtr table, const xmlChar *name, + xmlHashDeallocator f); +XMLPUBFUN int XMLCALL + xmlHashRemoveEntry2(xmlHashTablePtr table, const xmlChar *name, + const xmlChar *name2, xmlHashDeallocator f); +XMLPUBFUN int XMLCALL + xmlHashRemoveEntry3(xmlHashTablePtr table, const xmlChar *name, + const xmlChar *name2, const xmlChar *name3, + xmlHashDeallocator f); + +/* + * Retrieve the userdata. + */ +XMLPUBFUN void * XMLCALL + xmlHashLookup (xmlHashTablePtr table, + const xmlChar *name); +XMLPUBFUN void * XMLCALL + xmlHashLookup2 (xmlHashTablePtr table, + const xmlChar *name, + const xmlChar *name2); +XMLPUBFUN void * XMLCALL + xmlHashLookup3 (xmlHashTablePtr table, + const xmlChar *name, + const xmlChar *name2, + const xmlChar *name3); +XMLPUBFUN void * XMLCALL + xmlHashQLookup (xmlHashTablePtr table, + const xmlChar *name, + const xmlChar *prefix); +XMLPUBFUN void * XMLCALL + xmlHashQLookup2 (xmlHashTablePtr table, + const xmlChar *name, + const xmlChar *prefix, + const xmlChar *name2, + const xmlChar *prefix2); +XMLPUBFUN void * XMLCALL + xmlHashQLookup3 (xmlHashTablePtr table, + const xmlChar *name, + const xmlChar *prefix, + const xmlChar *name2, + const xmlChar *prefix2, + const xmlChar *name3, + const xmlChar *prefix3); + +/* + * Helpers. + */ +XMLPUBFUN xmlHashTablePtr XMLCALL + xmlHashCopy (xmlHashTablePtr table, + xmlHashCopier f); +XMLPUBFUN int XMLCALL + xmlHashSize (xmlHashTablePtr table); +XMLPUBFUN void XMLCALL + xmlHashScan (xmlHashTablePtr table, + xmlHashScanner f, + void *data); +XMLPUBFUN void XMLCALL + xmlHashScan3 (xmlHashTablePtr table, + const xmlChar *name, + const xmlChar *name2, + const xmlChar *name3, + xmlHashScanner f, + void *data); +XMLPUBFUN void XMLCALL + xmlHashScanFull (xmlHashTablePtr table, + xmlHashScannerFull f, + void *data); +XMLPUBFUN void XMLCALL + xmlHashScanFull3(xmlHashTablePtr table, + const xmlChar *name, + const xmlChar *name2, + const xmlChar *name3, + xmlHashScannerFull f, + void *data); +#ifdef __cplusplus +} +#endif +#endif /* ! __XML_HASH_H__ */ diff --git a/gettext-tools/gnulib-lib/libxml/legacy.c b/gettext-tools/gnulib-lib/libxml/legacy.c new file mode 100644 index 0000000..e75178a --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/legacy.c @@ -0,0 +1,1343 @@ +/* + * legacy.c: set of deprecated routines, not to be used anymore but + * kept purely for ABI compatibility + * + * See Copyright for the status of this software. + * + * daniel@veillard.com + */ + +#define IN_LIBXML +#include "libxml.h" + +#ifdef LIBXML_LEGACY_ENABLED +#include + +#include +#include +#include +#include +#include + +void xmlUpgradeOldNs(xmlDocPtr doc); + +/************************************************************************ + * * + * Deprecated functions kept for compatibility * + * * + ************************************************************************/ + +#ifdef LIBXML_HTML_ENABLED +xmlChar *htmlDecodeEntities(htmlParserCtxtPtr ctxt, int len, xmlChar end, + xmlChar end2, xmlChar end3); + +/** + * htmlDecodeEntities: + * @ctxt: the parser context + * @len: the len to decode (in bytes !), -1 for no size limit + * @end: an end marker xmlChar, 0 if none + * @end2: an end marker xmlChar, 0 if none + * @end3: an end marker xmlChar, 0 if none + * + * Substitute the HTML entities by their value + * + * DEPRECATED !!!! + * + * Returns A newly allocated string with the substitution done. The caller + * must deallocate it ! + */ +xmlChar * +htmlDecodeEntities(htmlParserCtxtPtr ctxt ATTRIBUTE_UNUSED, + int len ATTRIBUTE_UNUSED, xmlChar end ATTRIBUTE_UNUSED, + xmlChar end2 ATTRIBUTE_UNUSED, + xmlChar end3 ATTRIBUTE_UNUSED) +{ + static int deprecated = 0; + + if (!deprecated) { + xmlGenericError(xmlGenericErrorContext, + "htmlDecodeEntities() deprecated function reached\n"); + deprecated = 1; + } + return (NULL); +} +#endif + +/** + * xmlInitializePredefinedEntities: + * + * Set up the predefined entities. + * Deprecated call + */ +void +xmlInitializePredefinedEntities(void) +{ +} + +/** + * xmlCleanupPredefinedEntities: + * + * Cleanup up the predefined entities table. + * Deprecated call + */ +void +xmlCleanupPredefinedEntities(void) +{ +} + +static const char *xmlFeaturesList[] = { + "validate", + "load subset", + "keep blanks", + "disable SAX", + "fetch external entities", + "substitute entities", + "gather line info", + "user data", + "is html", + "is standalone", + "stop parser", + "document", + "is well formed", + "is valid", + "SAX block", + "SAX function internalSubset", + "SAX function isStandalone", + "SAX function hasInternalSubset", + "SAX function hasExternalSubset", + "SAX function resolveEntity", + "SAX function getEntity", + "SAX function entityDecl", + "SAX function notationDecl", + "SAX function attributeDecl", + "SAX function elementDecl", + "SAX function unparsedEntityDecl", + "SAX function setDocumentLocator", + "SAX function startDocument", + "SAX function endDocument", + "SAX function startElement", + "SAX function endElement", + "SAX function reference", + "SAX function characters", + "SAX function ignorableWhitespace", + "SAX function processingInstruction", + "SAX function comment", + "SAX function warning", + "SAX function error", + "SAX function fatalError", + "SAX function getParameterEntity", + "SAX function cdataBlock", + "SAX function externalSubset", +}; + +/** + * xmlGetFeaturesList: + * @len: the length of the features name array (input/output) + * @result: an array of string to be filled with the features name. + * + * Copy at most *@len feature names into the @result array + * + * Returns -1 in case or error, or the total number of features, + * len is updated with the number of strings copied, + * strings must not be deallocated + */ +int +xmlGetFeaturesList(int *len, const char **result) +{ + int ret, i; + + ret = sizeof(xmlFeaturesList) / sizeof(xmlFeaturesList[0]); + if ((len == NULL) || (result == NULL)) + return (ret); + if ((*len < 0) || (*len >= 1000)) + return (-1); + if (*len > ret) + *len = ret; + for (i = 0; i < *len; i++) + result[i] = xmlFeaturesList[i]; + return (ret); +} + +/** + * xmlGetFeature: + * @ctxt: an XML/HTML parser context + * @name: the feature name + * @result: location to store the result + * + * Read the current value of one feature of this parser instance + * + * Returns -1 in case or error, 0 otherwise + */ +int +xmlGetFeature(xmlParserCtxtPtr ctxt, const char *name, void *result) +{ + if ((ctxt == NULL) || (name == NULL) || (result == NULL)) + return (-1); + + if (!strcmp(name, "validate")) { + *((int *) result) = ctxt->validate; + } else if (!strcmp(name, "keep blanks")) { + *((int *) result) = ctxt->keepBlanks; + } else if (!strcmp(name, "disable SAX")) { + *((int *) result) = ctxt->disableSAX; + } else if (!strcmp(name, "fetch external entities")) { + *((int *) result) = ctxt->loadsubset; + } else if (!strcmp(name, "substitute entities")) { + *((int *) result) = ctxt->replaceEntities; + } else if (!strcmp(name, "gather line info")) { + *((int *) result) = ctxt->record_info; + } else if (!strcmp(name, "user data")) { + *((void **) result) = ctxt->userData; + } else if (!strcmp(name, "is html")) { + *((int *) result) = ctxt->html; + } else if (!strcmp(name, "is standalone")) { + *((int *) result) = ctxt->standalone; + } else if (!strcmp(name, "document")) { + *((xmlDocPtr *) result) = ctxt->myDoc; + } else if (!strcmp(name, "is well formed")) { + *((int *) result) = ctxt->wellFormed; + } else if (!strcmp(name, "is valid")) { + *((int *) result) = ctxt->valid; + } else if (!strcmp(name, "SAX block")) { + *((xmlSAXHandlerPtr *) result) = ctxt->sax; + } else if (!strcmp(name, "SAX function internalSubset")) { + *((internalSubsetSAXFunc *) result) = ctxt->sax->internalSubset; + } else if (!strcmp(name, "SAX function isStandalone")) { + *((isStandaloneSAXFunc *) result) = ctxt->sax->isStandalone; + } else if (!strcmp(name, "SAX function hasInternalSubset")) { + *((hasInternalSubsetSAXFunc *) result) = + ctxt->sax->hasInternalSubset; + } else if (!strcmp(name, "SAX function hasExternalSubset")) { + *((hasExternalSubsetSAXFunc *) result) = + ctxt->sax->hasExternalSubset; + } else if (!strcmp(name, "SAX function resolveEntity")) { + *((resolveEntitySAXFunc *) result) = ctxt->sax->resolveEntity; + } else if (!strcmp(name, "SAX function getEntity")) { + *((getEntitySAXFunc *) result) = ctxt->sax->getEntity; + } else if (!strcmp(name, "SAX function entityDecl")) { + *((entityDeclSAXFunc *) result) = ctxt->sax->entityDecl; + } else if (!strcmp(name, "SAX function notationDecl")) { + *((notationDeclSAXFunc *) result) = ctxt->sax->notationDecl; + } else if (!strcmp(name, "SAX function attributeDecl")) { + *((attributeDeclSAXFunc *) result) = ctxt->sax->attributeDecl; + } else if (!strcmp(name, "SAX function elementDecl")) { + *((elementDeclSAXFunc *) result) = ctxt->sax->elementDecl; + } else if (!strcmp(name, "SAX function unparsedEntityDecl")) { + *((unparsedEntityDeclSAXFunc *) result) = + ctxt->sax->unparsedEntityDecl; + } else if (!strcmp(name, "SAX function setDocumentLocator")) { + *((setDocumentLocatorSAXFunc *) result) = + ctxt->sax->setDocumentLocator; + } else if (!strcmp(name, "SAX function startDocument")) { + *((startDocumentSAXFunc *) result) = ctxt->sax->startDocument; + } else if (!strcmp(name, "SAX function endDocument")) { + *((endDocumentSAXFunc *) result) = ctxt->sax->endDocument; + } else if (!strcmp(name, "SAX function startElement")) { + *((startElementSAXFunc *) result) = ctxt->sax->startElement; + } else if (!strcmp(name, "SAX function endElement")) { + *((endElementSAXFunc *) result) = ctxt->sax->endElement; + } else if (!strcmp(name, "SAX function reference")) { + *((referenceSAXFunc *) result) = ctxt->sax->reference; + } else if (!strcmp(name, "SAX function characters")) { + *((charactersSAXFunc *) result) = ctxt->sax->characters; + } else if (!strcmp(name, "SAX function ignorableWhitespace")) { + *((ignorableWhitespaceSAXFunc *) result) = + ctxt->sax->ignorableWhitespace; + } else if (!strcmp(name, "SAX function processingInstruction")) { + *((processingInstructionSAXFunc *) result) = + ctxt->sax->processingInstruction; + } else if (!strcmp(name, "SAX function comment")) { + *((commentSAXFunc *) result) = ctxt->sax->comment; + } else if (!strcmp(name, "SAX function warning")) { + *((warningSAXFunc *) result) = ctxt->sax->warning; + } else if (!strcmp(name, "SAX function error")) { + *((errorSAXFunc *) result) = ctxt->sax->error; + } else if (!strcmp(name, "SAX function fatalError")) { + *((fatalErrorSAXFunc *) result) = ctxt->sax->fatalError; + } else if (!strcmp(name, "SAX function getParameterEntity")) { + *((getParameterEntitySAXFunc *) result) = + ctxt->sax->getParameterEntity; + } else if (!strcmp(name, "SAX function cdataBlock")) { + *((cdataBlockSAXFunc *) result) = ctxt->sax->cdataBlock; + } else if (!strcmp(name, "SAX function externalSubset")) { + *((externalSubsetSAXFunc *) result) = ctxt->sax->externalSubset; + } else { + return (-1); + } + return (0); +} + +/** + * xmlSetFeature: + * @ctxt: an XML/HTML parser context + * @name: the feature name + * @value: pointer to the location of the new value + * + * Change the current value of one feature of this parser instance + * + * Returns -1 in case or error, 0 otherwise + */ +int +xmlSetFeature(xmlParserCtxtPtr ctxt, const char *name, void *value) +{ + if ((ctxt == NULL) || (name == NULL) || (value == NULL)) + return (-1); + + if (!strcmp(name, "validate")) { + int newvalidate = *((int *) value); + + if ((!ctxt->validate) && (newvalidate != 0)) { + if (ctxt->vctxt.warning == NULL) + ctxt->vctxt.warning = xmlParserValidityWarning; + if (ctxt->vctxt.error == NULL) + ctxt->vctxt.error = xmlParserValidityError; + ctxt->vctxt.nodeMax = 0; + } + ctxt->validate = newvalidate; + } else if (!strcmp(name, "keep blanks")) { + ctxt->keepBlanks = *((int *) value); + } else if (!strcmp(name, "disable SAX")) { + ctxt->disableSAX = *((int *) value); + } else if (!strcmp(name, "fetch external entities")) { + ctxt->loadsubset = *((int *) value); + } else if (!strcmp(name, "substitute entities")) { + ctxt->replaceEntities = *((int *) value); + } else if (!strcmp(name, "gather line info")) { + ctxt->record_info = *((int *) value); + } else if (!strcmp(name, "user data")) { + ctxt->userData = *((void **) value); + } else if (!strcmp(name, "is html")) { + ctxt->html = *((int *) value); + } else if (!strcmp(name, "is standalone")) { + ctxt->standalone = *((int *) value); + } else if (!strcmp(name, "document")) { + ctxt->myDoc = *((xmlDocPtr *) value); + } else if (!strcmp(name, "is well formed")) { + ctxt->wellFormed = *((int *) value); + } else if (!strcmp(name, "is valid")) { + ctxt->valid = *((int *) value); + } else if (!strcmp(name, "SAX block")) { + ctxt->sax = *((xmlSAXHandlerPtr *) value); + } else if (!strcmp(name, "SAX function internalSubset")) { + ctxt->sax->internalSubset = *((internalSubsetSAXFunc *) value); + } else if (!strcmp(name, "SAX function isStandalone")) { + ctxt->sax->isStandalone = *((isStandaloneSAXFunc *) value); + } else if (!strcmp(name, "SAX function hasInternalSubset")) { + ctxt->sax->hasInternalSubset = + *((hasInternalSubsetSAXFunc *) value); + } else if (!strcmp(name, "SAX function hasExternalSubset")) { + ctxt->sax->hasExternalSubset = + *((hasExternalSubsetSAXFunc *) value); + } else if (!strcmp(name, "SAX function resolveEntity")) { + ctxt->sax->resolveEntity = *((resolveEntitySAXFunc *) value); + } else if (!strcmp(name, "SAX function getEntity")) { + ctxt->sax->getEntity = *((getEntitySAXFunc *) value); + } else if (!strcmp(name, "SAX function entityDecl")) { + ctxt->sax->entityDecl = *((entityDeclSAXFunc *) value); + } else if (!strcmp(name, "SAX function notationDecl")) { + ctxt->sax->notationDecl = *((notationDeclSAXFunc *) value); + } else if (!strcmp(name, "SAX function attributeDecl")) { + ctxt->sax->attributeDecl = *((attributeDeclSAXFunc *) value); + } else if (!strcmp(name, "SAX function elementDecl")) { + ctxt->sax->elementDecl = *((elementDeclSAXFunc *) value); + } else if (!strcmp(name, "SAX function unparsedEntityDecl")) { + ctxt->sax->unparsedEntityDecl = + *((unparsedEntityDeclSAXFunc *) value); + } else if (!strcmp(name, "SAX function setDocumentLocator")) { + ctxt->sax->setDocumentLocator = + *((setDocumentLocatorSAXFunc *) value); + } else if (!strcmp(name, "SAX function startDocument")) { + ctxt->sax->startDocument = *((startDocumentSAXFunc *) value); + } else if (!strcmp(name, "SAX function endDocument")) { + ctxt->sax->endDocument = *((endDocumentSAXFunc *) value); + } else if (!strcmp(name, "SAX function startElement")) { + ctxt->sax->startElement = *((startElementSAXFunc *) value); + } else if (!strcmp(name, "SAX function endElement")) { + ctxt->sax->endElement = *((endElementSAXFunc *) value); + } else if (!strcmp(name, "SAX function reference")) { + ctxt->sax->reference = *((referenceSAXFunc *) value); + } else if (!strcmp(name, "SAX function characters")) { + ctxt->sax->characters = *((charactersSAXFunc *) value); + } else if (!strcmp(name, "SAX function ignorableWhitespace")) { + ctxt->sax->ignorableWhitespace = + *((ignorableWhitespaceSAXFunc *) value); + } else if (!strcmp(name, "SAX function processingInstruction")) { + ctxt->sax->processingInstruction = + *((processingInstructionSAXFunc *) value); + } else if (!strcmp(name, "SAX function comment")) { + ctxt->sax->comment = *((commentSAXFunc *) value); + } else if (!strcmp(name, "SAX function warning")) { + ctxt->sax->warning = *((warningSAXFunc *) value); + } else if (!strcmp(name, "SAX function error")) { + ctxt->sax->error = *((errorSAXFunc *) value); + } else if (!strcmp(name, "SAX function fatalError")) { + ctxt->sax->fatalError = *((fatalErrorSAXFunc *) value); + } else if (!strcmp(name, "SAX function getParameterEntity")) { + ctxt->sax->getParameterEntity = + *((getParameterEntitySAXFunc *) value); + } else if (!strcmp(name, "SAX function cdataBlock")) { + ctxt->sax->cdataBlock = *((cdataBlockSAXFunc *) value); + } else if (!strcmp(name, "SAX function externalSubset")) { + ctxt->sax->externalSubset = *((externalSubsetSAXFunc *) value); + } else { + return (-1); + } + return (0); +} + +/** + * xmlDecodeEntities: + * @ctxt: the parser context + * @len: the len to decode (in bytes !), -1 for no size limit + * @what: combination of XML_SUBSTITUTE_REF and XML_SUBSTITUTE_PEREF + * @end: an end marker xmlChar, 0 if none + * @end2: an end marker xmlChar, 0 if none + * @end3: an end marker xmlChar, 0 if none + * + * This function is deprecated, we now always process entities content + * through xmlStringDecodeEntities + * + * TODO: remove it in next major release. + * + * [67] Reference ::= EntityRef | CharRef + * + * [69] PEReference ::= '%' Name ';' + * + * Returns A newly allocated string with the substitution done. The caller + * must deallocate it ! + */ +xmlChar * +xmlDecodeEntities(xmlParserCtxtPtr ctxt ATTRIBUTE_UNUSED, + int len ATTRIBUTE_UNUSED, int what ATTRIBUTE_UNUSED, + xmlChar end ATTRIBUTE_UNUSED, + xmlChar end2 ATTRIBUTE_UNUSED, + xmlChar end3 ATTRIBUTE_UNUSED) +{ + static int deprecated = 0; + + if (!deprecated) { + xmlGenericError(xmlGenericErrorContext, + "xmlDecodeEntities() deprecated function reached\n"); + deprecated = 1; + } + return (NULL); +} + +/** + * xmlNamespaceParseNCName: + * @ctxt: an XML parser context + * + * parse an XML namespace name. + * + * TODO: this seems not in use anymore, the namespace handling is done on + * top of the SAX interfaces, i.e. not on raw input. + * + * [NS 3] NCName ::= (Letter | '_') (NCNameChar)* + * + * [NS 4] NCNameChar ::= Letter | Digit | '.' | '-' | '_' | + * CombiningChar | Extender + * + * Returns the namespace name or NULL + */ + +xmlChar * +xmlNamespaceParseNCName(xmlParserCtxtPtr ctxt ATTRIBUTE_UNUSED) +{ + static int deprecated = 0; + + if (!deprecated) { + xmlGenericError(xmlGenericErrorContext, + "xmlNamespaceParseNCName() deprecated function reached\n"); + deprecated = 1; + } + return (NULL); +} + +/** + * xmlNamespaceParseQName: + * @ctxt: an XML parser context + * @prefix: a xmlChar ** + * + * TODO: this seems not in use anymore, the namespace handling is done on + * top of the SAX interfaces, i.e. not on raw input. + * + * parse an XML qualified name + * + * [NS 5] QName ::= (Prefix ':')? LocalPart + * + * [NS 6] Prefix ::= NCName + * + * [NS 7] LocalPart ::= NCName + * + * Returns the local part, and prefix is updated + * to get the Prefix if any. + */ + +xmlChar * +xmlNamespaceParseQName(xmlParserCtxtPtr ctxt ATTRIBUTE_UNUSED, + xmlChar ** prefix ATTRIBUTE_UNUSED) +{ + + static int deprecated = 0; + + if (!deprecated) { + xmlGenericError(xmlGenericErrorContext, + "xmlNamespaceParseQName() deprecated function reached\n"); + deprecated = 1; + } + return (NULL); +} + +/** + * xmlNamespaceParseNSDef: + * @ctxt: an XML parser context + * + * parse a namespace prefix declaration + * + * TODO: this seems not in use anymore, the namespace handling is done on + * top of the SAX interfaces, i.e. not on raw input. + * + * [NS 1] NSDef ::= PrefixDef Eq SystemLiteral + * + * [NS 2] PrefixDef ::= 'xmlns' (':' NCName)? + * + * Returns the namespace name + */ + +xmlChar * +xmlNamespaceParseNSDef(xmlParserCtxtPtr ctxt ATTRIBUTE_UNUSED) +{ + static int deprecated = 0; + + if (!deprecated) { + xmlGenericError(xmlGenericErrorContext, + "xmlNamespaceParseNSDef() deprecated function reached\n"); + deprecated = 1; + } + return (NULL); +} + +/** + * xmlParseQuotedString: + * @ctxt: an XML parser context + * + * Parse and return a string between quotes or doublequotes + * + * TODO: Deprecated, to be removed at next drop of binary compatibility + * + * Returns the string parser or NULL. + */ +xmlChar * +xmlParseQuotedString(xmlParserCtxtPtr ctxt ATTRIBUTE_UNUSED) +{ + static int deprecated = 0; + + if (!deprecated) { + xmlGenericError(xmlGenericErrorContext, + "xmlParseQuotedString() deprecated function reached\n"); + deprecated = 1; + } + return (NULL); +} + +/** + * xmlParseNamespace: + * @ctxt: an XML parser context + * + * xmlParseNamespace: parse specific PI ' +#endif + +#if defined(__Lynx__) +#include /* pull definition of size_t */ +#include +int snprintf(char *, size_t, const char *, ...); +int vfprintf(FILE *, const char *, va_list); +#endif + +#ifndef WITH_TRIO +#include +#else +/** + * TRIO_REPLACE_STDIO: + * + * This macro is defined if teh trio string formatting functions are to + * be used instead of the default stdio ones. + */ +#define TRIO_REPLACE_STDIO +#include "trio.h" +#endif + +/* + * Internal variable indicating if a callback has been registered for + * node creation/destruction. It avoids spending a lot of time in locking + * function while checking if the callback exists. + */ +extern int __xmlRegisterCallbacks; +/* + * internal error reporting routines, shared but not partof the API. + */ +void __xmlIOErr(int domain, int code, const char *extra); +void __xmlLoaderErr(void *ctx, const char *msg, const char *filename); +#ifdef LIBXML_HTML_ENABLED +/* + * internal function of HTML parser needed for xmlParseInNodeContext + * but not part of the API + */ +void __htmlParseContent(void *ctx); +#endif + + +#ifdef IN_LIBXML +#ifdef __GNUC__ +#ifdef PIC +#ifdef linux +#if (__GNUC__ == 3 && __GNUC_MINOR__ >= 3) || (__GNUC__ > 3) +#include "elfgcchack.h" +#endif +#endif +#endif +#endif +#endif +#endif /* ! __XML_LIBXML_H__ */ diff --git a/gettext-tools/gnulib-lib/libxml/list.c b/gettext-tools/gnulib-lib/libxml/list.c new file mode 100644 index 0000000..2dc6d96 --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/list.c @@ -0,0 +1,779 @@ +/* + * list.c: lists handling implementation + * + * Copyright (C) 2000 Gary Pennington and Daniel Veillard. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND + * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER. + * + * Author: Gary.Pennington@uk.sun.com + */ + +#define IN_LIBXML +#include "libxml.h" + +#include +#include +#include +#include +#include + +/* + * Type definition are kept internal + */ + +struct _xmlLink +{ + struct _xmlLink *next; + struct _xmlLink *prev; + void *data; +}; + +struct _xmlList +{ + xmlLinkPtr sentinel; + void (*linkDeallocator)(xmlLinkPtr ); + int (*linkCompare)(const void *, const void*); +}; + +/************************************************************************ + * * + * Interfaces * + * * + ************************************************************************/ + +/** + * xmlLinkDeallocator: + * @l: a list + * @lk: a link + * + * Unlink and deallocate @lk from list @l + */ +static void +xmlLinkDeallocator(xmlListPtr l, xmlLinkPtr lk) +{ + (lk->prev)->next = lk->next; + (lk->next)->prev = lk->prev; + if(l->linkDeallocator) + l->linkDeallocator(lk); + xmlFree(lk); +} + +/** + * xmlLinkCompare: + * @data0: first data + * @data1: second data + * + * Compares two arbitrary data + * + * Returns -1, 0 or 1 depending on whether data1 is greater equal or smaller + * than data0 + */ +static int +xmlLinkCompare(const void *data0, const void *data1) +{ + if (data0 < data1) + return (-1); + else if (data0 == data1) + return (0); + return (1); +} + +/** + * xmlListLowerSearch: + * @l: a list + * @data: a data + * + * Search data in the ordered list walking from the beginning + * + * Returns the link containing the data or NULL + */ +static xmlLinkPtr +xmlListLowerSearch(xmlListPtr l, void *data) +{ + xmlLinkPtr lk; + + if (l == NULL) + return(NULL); + for(lk = l->sentinel->next;lk != l->sentinel && l->linkCompare(lk->data, data) <0 ;lk = lk->next); + return lk; +} + +/** + * xmlListHigherSearch: + * @l: a list + * @data: a data + * + * Search data in the ordered list walking backward from the end + * + * Returns the link containing the data or NULL + */ +static xmlLinkPtr +xmlListHigherSearch(xmlListPtr l, void *data) +{ + xmlLinkPtr lk; + + if (l == NULL) + return(NULL); + for(lk = l->sentinel->prev;lk != l->sentinel && l->linkCompare(lk->data, data) >0 ;lk = lk->prev); + return lk; +} + +/** + * xmlListSearch: + * @l: a list + * @data: a data + * + * Search data in the list + * + * Returns the link containing the data or NULL + */ +static xmlLinkPtr +xmlListLinkSearch(xmlListPtr l, void *data) +{ + xmlLinkPtr lk; + if (l == NULL) + return(NULL); + lk = xmlListLowerSearch(l, data); + if (lk == l->sentinel) + return NULL; + else { + if (l->linkCompare(lk->data, data) ==0) + return lk; + return NULL; + } +} + +/** + * xmlListLinkReverseSearch: + * @l: a list + * @data: a data + * + * Search data in the list processing backward + * + * Returns the link containing the data or NULL + */ +static xmlLinkPtr +xmlListLinkReverseSearch(xmlListPtr l, void *data) +{ + xmlLinkPtr lk; + if (l == NULL) + return(NULL); + lk = xmlListHigherSearch(l, data); + if (lk == l->sentinel) + return NULL; + else { + if (l->linkCompare(lk->data, data) ==0) + return lk; + return NULL; + } +} + +/** + * xmlListCreate: + * @deallocator: an optional deallocator function + * @compare: an optional comparison function + * + * Create a new list + * + * Returns the new list or NULL in case of error + */ +xmlListPtr +xmlListCreate(xmlListDeallocator deallocator, xmlListDataCompare compare) +{ + xmlListPtr l; + if (NULL == (l = (xmlListPtr )xmlMalloc( sizeof(xmlList)))) { + xmlGenericError(xmlGenericErrorContext, + "Cannot initialize memory for list"); + return (NULL); + } + /* Initialize the list to NULL */ + memset(l, 0, sizeof(xmlList)); + + /* Add the sentinel */ + if (NULL ==(l->sentinel = (xmlLinkPtr )xmlMalloc(sizeof(xmlLink)))) { + xmlGenericError(xmlGenericErrorContext, + "Cannot initialize memory for sentinel"); + xmlFree(l); + return (NULL); + } + l->sentinel->next = l->sentinel; + l->sentinel->prev = l->sentinel; + l->sentinel->data = NULL; + + /* If there is a link deallocator, use it */ + if (deallocator != NULL) + l->linkDeallocator = deallocator; + /* If there is a link comparator, use it */ + if (compare != NULL) + l->linkCompare = compare; + else /* Use our own */ + l->linkCompare = xmlLinkCompare; + return l; +} + +/** + * xmlListSearch: + * @l: a list + * @data: a search value + * + * Search the list for an existing value of @data + * + * Returns the value associated to @data or NULL in case of error + */ +void * +xmlListSearch(xmlListPtr l, void *data) +{ + xmlLinkPtr lk; + if (l == NULL) + return(NULL); + lk = xmlListLinkSearch(l, data); + if (lk) + return (lk->data); + return NULL; +} + +/** + * xmlListReverseSearch: + * @l: a list + * @data: a search value + * + * Search the list in reverse order for an existing value of @data + * + * Returns the value associated to @data or NULL in case of error + */ +void * +xmlListReverseSearch(xmlListPtr l, void *data) +{ + xmlLinkPtr lk; + if (l == NULL) + return(NULL); + lk = xmlListLinkReverseSearch(l, data); + if (lk) + return (lk->data); + return NULL; +} + +/** + * xmlListInsert: + * @l: a list + * @data: the data + * + * Insert data in the ordered list at the beginning for this value + * + * Returns 0 in case of success, 1 in case of failure + */ +int +xmlListInsert(xmlListPtr l, void *data) +{ + xmlLinkPtr lkPlace, lkNew; + + if (l == NULL) + return(1); + lkPlace = xmlListLowerSearch(l, data); + /* Add the new link */ + lkNew = (xmlLinkPtr) xmlMalloc(sizeof(xmlLink)); + if (lkNew == NULL) { + xmlGenericError(xmlGenericErrorContext, + "Cannot initialize memory for new link"); + return (1); + } + lkNew->data = data; + lkPlace = lkPlace->prev; + lkNew->next = lkPlace->next; + (lkPlace->next)->prev = lkNew; + lkPlace->next = lkNew; + lkNew->prev = lkPlace; + return 0; +} + +/** + * xmlListAppend: + * @l: a list + * @data: the data + * + * Insert data in the ordered list at the end for this value + * + * Returns 0 in case of success, 1 in case of failure + */ +int xmlListAppend(xmlListPtr l, void *data) +{ + xmlLinkPtr lkPlace, lkNew; + + if (l == NULL) + return(1); + lkPlace = xmlListHigherSearch(l, data); + /* Add the new link */ + lkNew = (xmlLinkPtr) xmlMalloc(sizeof(xmlLink)); + if (lkNew == NULL) { + xmlGenericError(xmlGenericErrorContext, + "Cannot initialize memory for new link"); + return (0); + } + lkNew->data = data; + lkNew->next = lkPlace->next; + (lkPlace->next)->prev = lkNew; + lkPlace->next = lkNew; + lkNew->prev = lkPlace; + return 1; +} + +/** + * xmlListDelete: + * @l: a list + * + * Deletes the list and its associated data + */ +void xmlListDelete(xmlListPtr l) +{ + if (l == NULL) + return; + + xmlListClear(l); + xmlFree(l->sentinel); + xmlFree(l); +} + +/** + * xmlListRemoveFirst: + * @l: a list + * @data: list data + * + * Remove the first instance associated to data in the list + * + * Returns 1 if a deallocation occured, or 0 if not found + */ +int +xmlListRemoveFirst(xmlListPtr l, void *data) +{ + xmlLinkPtr lk; + + if (l == NULL) + return(0); + /*Find the first instance of this data */ + lk = xmlListLinkSearch(l, data); + if (lk != NULL) { + xmlLinkDeallocator(l, lk); + return 1; + } + return 0; +} + +/** + * xmlListRemoveLast: + * @l: a list + * @data: list data + * + * Remove the last instance associated to data in the list + * + * Returns 1 if a deallocation occured, or 0 if not found + */ +int +xmlListRemoveLast(xmlListPtr l, void *data) +{ + xmlLinkPtr lk; + + if (l == NULL) + return(0); + /*Find the last instance of this data */ + lk = xmlListLinkReverseSearch(l, data); + if (lk != NULL) { + xmlLinkDeallocator(l, lk); + return 1; + } + return 0; +} + +/** + * xmlListRemoveAll: + * @l: a list + * @data: list data + * + * Remove the all instance associated to data in the list + * + * Returns the number of deallocation, or 0 if not found + */ +int +xmlListRemoveAll(xmlListPtr l, void *data) +{ + int count=0; + + if (l == NULL) + return(0); + + while(xmlListRemoveFirst(l, data)) + count++; + return count; +} + +/** + * xmlListClear: + * @l: a list + * + * Remove the all data in the list + */ +void +xmlListClear(xmlListPtr l) +{ + xmlLinkPtr lk; + + if (l == NULL) + return; + lk = l->sentinel->next; + while(lk != l->sentinel) { + xmlLinkPtr next = lk->next; + + xmlLinkDeallocator(l, lk); + lk = next; + } +} + +/** + * xmlListEmpty: + * @l: a list + * + * Is the list empty ? + * + * Returns 1 if the list is empty, 0 if not empty and -1 in case of error + */ +int +xmlListEmpty(xmlListPtr l) +{ + if (l == NULL) + return(-1); + return (l->sentinel->next == l->sentinel); +} + +/** + * xmlListFront: + * @l: a list + * + * Get the first element in the list + * + * Returns the first element in the list, or NULL + */ +xmlLinkPtr +xmlListFront(xmlListPtr l) +{ + if (l == NULL) + return(NULL); + return (l->sentinel->next); +} + +/** + * xmlListEnd: + * @l: a list + * + * Get the last element in the list + * + * Returns the last element in the list, or NULL + */ +xmlLinkPtr +xmlListEnd(xmlListPtr l) +{ + if (l == NULL) + return(NULL); + return (l->sentinel->prev); +} + +/** + * xmlListSize: + * @l: a list + * + * Get the number of elements in the list + * + * Returns the number of elements in the list or -1 in case of error + */ +int +xmlListSize(xmlListPtr l) +{ + xmlLinkPtr lk; + int count=0; + + if (l == NULL) + return(-1); + /* TODO: keep a counter in xmlList instead */ + for(lk = l->sentinel->next; lk != l->sentinel; lk = lk->next, count++); + return count; +} + +/** + * xmlListPopFront: + * @l: a list + * + * Removes the first element in the list + */ +void +xmlListPopFront(xmlListPtr l) +{ + if(!xmlListEmpty(l)) + xmlLinkDeallocator(l, l->sentinel->next); +} + +/** + * xmlListPopBack: + * @l: a list + * + * Removes the last element in the list + */ +void +xmlListPopBack(xmlListPtr l) +{ + if(!xmlListEmpty(l)) + xmlLinkDeallocator(l, l->sentinel->prev); +} + +/** + * xmlListPushFront: + * @l: a list + * @data: new data + * + * add the new data at the beginning of the list + * + * Returns 1 if successful, 0 otherwise + */ +int +xmlListPushFront(xmlListPtr l, void *data) +{ + xmlLinkPtr lkPlace, lkNew; + + if (l == NULL) + return(0); + lkPlace = l->sentinel; + /* Add the new link */ + lkNew = (xmlLinkPtr) xmlMalloc(sizeof(xmlLink)); + if (lkNew == NULL) { + xmlGenericError(xmlGenericErrorContext, + "Cannot initialize memory for new link"); + return (0); + } + lkNew->data = data; + lkNew->next = lkPlace->next; + (lkPlace->next)->prev = lkNew; + lkPlace->next = lkNew; + lkNew->prev = lkPlace; + return 1; +} + +/** + * xmlListPushBack: + * @l: a list + * @data: new data + * + * add the new data at the end of the list + * + * Returns 1 if successful, 0 otherwise + */ +int +xmlListPushBack(xmlListPtr l, void *data) +{ + xmlLinkPtr lkPlace, lkNew; + + if (l == NULL) + return(0); + lkPlace = l->sentinel->prev; + /* Add the new link */ + if (NULL ==(lkNew = (xmlLinkPtr )xmlMalloc(sizeof(xmlLink)))) { + xmlGenericError(xmlGenericErrorContext, + "Cannot initialize memory for new link"); + return (0); + } + lkNew->data = data; + lkNew->next = lkPlace->next; + (lkPlace->next)->prev = lkNew; + lkPlace->next = lkNew; + lkNew->prev = lkPlace; + return 1; +} + +/** + * xmlLinkGetData: + * @lk: a link + * + * See Returns. + * + * Returns a pointer to the data referenced from this link + */ +void * +xmlLinkGetData(xmlLinkPtr lk) +{ + if (lk == NULL) + return(NULL); + return lk->data; +} + +/** + * xmlListReverse: + * @l: a list + * + * Reverse the order of the elements in the list + */ +void +xmlListReverse(xmlListPtr l) +{ + xmlLinkPtr lk; + xmlLinkPtr lkPrev; + + if (l == NULL) + return; + lkPrev = l->sentinel; + for (lk = l->sentinel->next; lk != l->sentinel; lk = lk->next) { + lkPrev->next = lkPrev->prev; + lkPrev->prev = lk; + lkPrev = lk; + } + /* Fix up the last node */ + lkPrev->next = lkPrev->prev; + lkPrev->prev = lk; +} + +/** + * xmlListSort: + * @l: a list + * + * Sort all the elements in the list + */ +void +xmlListSort(xmlListPtr l) +{ + xmlListPtr lTemp; + + if (l == NULL) + return; + if(xmlListEmpty(l)) + return; + + /* I think that the real answer is to implement quicksort, the + * alternative is to implement some list copying procedure which + * would be based on a list copy followed by a clear followed by + * an insert. This is slow... + */ + + if (NULL ==(lTemp = xmlListDup(l))) + return; + xmlListClear(l); + xmlListMerge(l, lTemp); + xmlListDelete(lTemp); + return; +} + +/** + * xmlListWalk: + * @l: a list + * @walker: a processing function + * @user: a user parameter passed to the walker function + * + * Walk all the element of the first from first to last and + * apply the walker function to it + */ +void +xmlListWalk(xmlListPtr l, xmlListWalker walker, const void *user) { + xmlLinkPtr lk; + + if ((l == NULL) || (walker == NULL)) + return; + for(lk = l->sentinel->next; lk != l->sentinel; lk = lk->next) { + if((walker(lk->data, user)) == 0) + break; + } +} + +/** + * xmlListReverseWalk: + * @l: a list + * @walker: a processing function + * @user: a user parameter passed to the walker function + * + * Walk all the element of the list in reverse order and + * apply the walker function to it + */ +void +xmlListReverseWalk(xmlListPtr l, xmlListWalker walker, const void *user) { + xmlLinkPtr lk; + + if ((l == NULL) || (walker == NULL)) + return; + for(lk = l->sentinel->prev; lk != l->sentinel; lk = lk->prev) { + if((walker(lk->data, user)) == 0) + break; + } +} + +/** + * xmlListMerge: + * @l1: the original list + * @l2: the new list + * + * include all the elements of the second list in the first one and + * clear the second list + */ +void +xmlListMerge(xmlListPtr l1, xmlListPtr l2) +{ + xmlListCopy(l1, l2); + xmlListClear(l2); +} + +/** + * xmlListDup: + * @old: the list + * + * Duplicate the list + * + * Returns a new copy of the list or NULL in case of error + */ +xmlListPtr +xmlListDup(const xmlListPtr old) +{ + xmlListPtr cur; + + if (old == NULL) + return(NULL); + /* Hmmm, how to best deal with allocation issues when copying + * lists. If there is a de-allocator, should responsibility lie with + * the new list or the old list. Surely not both. I'll arbitrarily + * set it to be the old list for the time being whilst I work out + * the answer + */ + if (NULL ==(cur = xmlListCreate(NULL, old->linkCompare))) + return (NULL); + if (0 != xmlListCopy(cur, old)) + return NULL; + return cur; +} + +/** + * xmlListCopy: + * @cur: the new list + * @old: the old list + * + * Move all the element from the old list in the new list + * + * Returns 0 in case of success 1 in case of error + */ +int +xmlListCopy(xmlListPtr cur, const xmlListPtr old) +{ + /* Walk the old tree and insert the data into the new one */ + xmlLinkPtr lk; + + if ((old == NULL) || (cur == NULL)) + return(1); + for(lk = old->sentinel->next; lk != old->sentinel; lk = lk->next) { + if (0 !=xmlListInsert(cur, lk->data)) { + xmlListDelete(cur); + return (1); + } + } + return (0); +} +/* xmlListUnique() */ +/* xmlListSwap */ +#define bottom_list +#include "elfgcchack.h" diff --git a/gettext-tools/gnulib-lib/libxml/list.in.h b/gettext-tools/gnulib-lib/libxml/list.in.h new file mode 100644 index 0000000..1d83482 --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/list.in.h @@ -0,0 +1,137 @@ +/* + * Summary: lists interfaces + * Description: this module implement the list support used in + * various place in the library. + * + * Copy: See Copyright for the status of this software. + * + * Author: Gary Pennington + */ + +#ifndef __XML_LINK_INCLUDE__ +#define __XML_LINK_INCLUDE__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _xmlLink xmlLink; +typedef xmlLink *xmlLinkPtr; + +typedef struct _xmlList xmlList; +typedef xmlList *xmlListPtr; + +/** + * xmlListDeallocator: + * @lk: the data to deallocate + * + * Callback function used to free data from a list. + */ +typedef void (*xmlListDeallocator) (xmlLinkPtr lk); +/** + * xmlListDataCompare: + * @data0: the first data + * @data1: the second data + * + * Callback function used to compare 2 data. + * + * Returns 0 is equality, -1 or 1 otherwise depending on the ordering. + */ +typedef int (*xmlListDataCompare) (const void *data0, const void *data1); +/** + * xmlListWalker: + * @data: the data found in the list + * @user: extra user provided data to the walker + * + * Callback function used when walking a list with xmlListWalk(). + * + * Returns 0 to stop walking the list, 1 otherwise. + */ +typedef int (*xmlListWalker) (const void *data, const void *user); + +/* Creation/Deletion */ +XMLPUBFUN xmlListPtr XMLCALL + xmlListCreate (xmlListDeallocator deallocator, + xmlListDataCompare compare); +XMLPUBFUN void XMLCALL + xmlListDelete (xmlListPtr l); + +/* Basic Operators */ +XMLPUBFUN void * XMLCALL + xmlListSearch (xmlListPtr l, + void *data); +XMLPUBFUN void * XMLCALL + xmlListReverseSearch (xmlListPtr l, + void *data); +XMLPUBFUN int XMLCALL + xmlListInsert (xmlListPtr l, + void *data) ; +XMLPUBFUN int XMLCALL + xmlListAppend (xmlListPtr l, + void *data) ; +XMLPUBFUN int XMLCALL + xmlListRemoveFirst (xmlListPtr l, + void *data); +XMLPUBFUN int XMLCALL + xmlListRemoveLast (xmlListPtr l, + void *data); +XMLPUBFUN int XMLCALL + xmlListRemoveAll (xmlListPtr l, + void *data); +XMLPUBFUN void XMLCALL + xmlListClear (xmlListPtr l); +XMLPUBFUN int XMLCALL + xmlListEmpty (xmlListPtr l); +XMLPUBFUN xmlLinkPtr XMLCALL + xmlListFront (xmlListPtr l); +XMLPUBFUN xmlLinkPtr XMLCALL + xmlListEnd (xmlListPtr l); +XMLPUBFUN int XMLCALL + xmlListSize (xmlListPtr l); + +XMLPUBFUN void XMLCALL + xmlListPopFront (xmlListPtr l); +XMLPUBFUN void XMLCALL + xmlListPopBack (xmlListPtr l); +XMLPUBFUN int XMLCALL + xmlListPushFront (xmlListPtr l, + void *data); +XMLPUBFUN int XMLCALL + xmlListPushBack (xmlListPtr l, + void *data); + +/* Advanced Operators */ +XMLPUBFUN void XMLCALL + xmlListReverse (xmlListPtr l); +XMLPUBFUN void XMLCALL + xmlListSort (xmlListPtr l); +XMLPUBFUN void XMLCALL + xmlListWalk (xmlListPtr l, + xmlListWalker walker, + const void *user); +XMLPUBFUN void XMLCALL + xmlListReverseWalk (xmlListPtr l, + xmlListWalker walker, + const void *user); +XMLPUBFUN void XMLCALL + xmlListMerge (xmlListPtr l1, + xmlListPtr l2); +XMLPUBFUN xmlListPtr XMLCALL + xmlListDup (const xmlListPtr old); +XMLPUBFUN int XMLCALL + xmlListCopy (xmlListPtr cur, + const xmlListPtr old); +/* Link operators */ +XMLPUBFUN void * XMLCALL + xmlLinkGetData (xmlLinkPtr lk); + +/* xmlListUnique() */ +/* xmlListSwap */ + +#ifdef __cplusplus +} +#endif + +#endif /* __XML_LINK_INCLUDE__ */ diff --git a/gettext-tools/gnulib-lib/libxml/nanoftp.c b/gettext-tools/gnulib-lib/libxml/nanoftp.c new file mode 100644 index 0000000..c78503b --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/nanoftp.c @@ -0,0 +1,2109 @@ +/* + * nanoftp.c: basic FTP client support + * + * Reference: RFC 959 + */ + +#ifdef TESTING +#define STANDALONE +#define HAVE_STDLIB_H +#define HAVE_UNISTD_H +#define HAVE_SYS_SOCKET_H +#define HAVE_NETINET_IN_H +#define HAVE_NETDB_H +#define HAVE_SYS_TIME_H +#else /* TESTING */ +#define NEED_SOCKETS +#endif /* TESTING */ + +#define IN_LIBXML +#include "libxml.h" + +#ifdef LIBXML_FTP_ENABLED +#include + +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_FCNTL_H +#include +#endif +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_SYS_TIME_H +#include +#endif +#ifdef HAVE_SYS_SELECT_H +#include +#endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_STRINGS_H +#include +#endif + +#include +#include +#include +#include +#include +#include + +/* #define DEBUG_FTP 1 */ +#ifdef STANDALONE +#ifndef DEBUG_FTP +#define DEBUG_FTP 1 +#endif +#endif + + +#ifdef __MINGW32__ +#define _WINSOCKAPI_ +#include +#include +#undef XML_SOCKLEN_T +#define XML_SOCKLEN_T unsigned int +#endif + +/** + * A couple portability macros + */ +#ifndef _WINSOCKAPI_ +#ifndef __BEOS__ +#define closesocket(s) close(s) +#endif +#define SOCKET int +#endif + +#ifdef __BEOS__ +#ifndef PF_INET +#define PF_INET AF_INET +#endif +#endif + +#ifdef _AIX +#define ss_family __ss_family +#endif + +#ifndef XML_SOCKLEN_T +#define XML_SOCKLEN_T unsigned int +#endif + +#define FTP_COMMAND_OK 200 +#define FTP_SYNTAX_ERROR 500 +#define FTP_GET_PASSWD 331 +#define FTP_BUF_SIZE 1024 + +#define XML_NANO_MAX_URLBUF 4096 + +typedef struct xmlNanoFTPCtxt { + char *protocol; /* the protocol name */ + char *hostname; /* the host name */ + int port; /* the port */ + char *path; /* the path within the URL */ + char *user; /* user string */ + char *passwd; /* passwd string */ +#ifdef SUPPORT_IP6 + struct sockaddr_storage ftpAddr; /* this is large enough to hold IPv6 address*/ +#else + struct sockaddr_in ftpAddr; /* the socket address struct */ +#endif + int passive; /* currently we support only passive !!! */ + SOCKET controlFd; /* the file descriptor for the control socket */ + SOCKET dataFd; /* the file descriptor for the data socket */ + int state; /* WRITE / READ / CLOSED */ + int returnValue; /* the protocol return value */ + /* buffer for data received from the control connection */ + char controlBuf[FTP_BUF_SIZE + 1]; + int controlBufIndex; + int controlBufUsed; + int controlBufAnswer; +} xmlNanoFTPCtxt, *xmlNanoFTPCtxtPtr; + +static int initialized = 0; +static char *proxy = NULL; /* the proxy name if any */ +static int proxyPort = 0; /* the proxy port if any */ +static char *proxyUser = NULL; /* user for proxy authentication */ +static char *proxyPasswd = NULL;/* passwd for proxy authentication */ +static int proxyType = 0; /* uses TYPE or a@b ? */ + +#ifdef SUPPORT_IP6 +static +int have_ipv6(void) { + int s; + + s = socket (AF_INET6, SOCK_STREAM, 0); + if (s != -1) { + close (s); + return (1); + } + return (0); +} +#endif + +/** + * xmlFTPErrMemory: + * @extra: extra informations + * + * Handle an out of memory condition + */ +static void +xmlFTPErrMemory(const char *extra) +{ + __xmlSimpleError(XML_FROM_FTP, XML_ERR_NO_MEMORY, NULL, NULL, extra); +} + +/** + * xmlNanoFTPInit: + * + * Initialize the FTP protocol layer. + * Currently it just checks for proxy informations, + * and get the hostname + */ + +void +xmlNanoFTPInit(void) { + const char *env; +#ifdef _WINSOCKAPI_ + WSADATA wsaData; +#endif + + if (initialized) + return; + +#ifdef _WINSOCKAPI_ + if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0) + return; +#endif + + proxyPort = 21; + env = getenv("no_proxy"); + if (env && ((env[0] == '*' ) && (env[1] == 0))) + return; + env = getenv("ftp_proxy"); + if (env != NULL) { + xmlNanoFTPScanProxy(env); + } else { + env = getenv("FTP_PROXY"); + if (env != NULL) { + xmlNanoFTPScanProxy(env); + } + } + env = getenv("ftp_proxy_user"); + if (env != NULL) { + proxyUser = xmlMemStrdup(env); + } + env = getenv("ftp_proxy_password"); + if (env != NULL) { + proxyPasswd = xmlMemStrdup(env); + } + initialized = 1; +} + +/** + * xmlNanoFTPCleanup: + * + * Cleanup the FTP protocol layer. This cleanup proxy informations. + */ + +void +xmlNanoFTPCleanup(void) { + if (proxy != NULL) { + xmlFree(proxy); + proxy = NULL; + } + if (proxyUser != NULL) { + xmlFree(proxyUser); + proxyUser = NULL; + } + if (proxyPasswd != NULL) { + xmlFree(proxyPasswd); + proxyPasswd = NULL; + } +#ifdef _WINSOCKAPI_ + if (initialized) + WSACleanup(); +#endif + initialized = 0; +} + +/** + * xmlNanoFTPProxy: + * @host: the proxy host name + * @port: the proxy port + * @user: the proxy user name + * @passwd: the proxy password + * @type: the type of proxy 1 for using SITE, 2 for USER a@b + * + * Setup the FTP proxy informations. + * This can also be done by using ftp_proxy ftp_proxy_user and + * ftp_proxy_password environment variables. + */ + +void +xmlNanoFTPProxy(const char *host, int port, const char *user, + const char *passwd, int type) { + if (proxy != NULL) { + xmlFree(proxy); + proxy = NULL; + } + if (proxyUser != NULL) { + xmlFree(proxyUser); + proxyUser = NULL; + } + if (proxyPasswd != NULL) { + xmlFree(proxyPasswd); + proxyPasswd = NULL; + } + if (host) + proxy = xmlMemStrdup(host); + if (user) + proxyUser = xmlMemStrdup(user); + if (passwd) + proxyPasswd = xmlMemStrdup(passwd); + proxyPort = port; + proxyType = type; +} + +/** + * xmlNanoFTPScanURL: + * @ctx: an FTP context + * @URL: The URL used to initialize the context + * + * (Re)Initialize an FTP context by parsing the URL and finding + * the protocol host port and path it indicates. + */ + +static void +xmlNanoFTPScanURL(void *ctx, const char *URL) { + xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx; + xmlURIPtr uri; + + /* + * Clear any existing data from the context + */ + if (ctxt->protocol != NULL) { + xmlFree(ctxt->protocol); + ctxt->protocol = NULL; + } + if (ctxt->hostname != NULL) { + xmlFree(ctxt->hostname); + ctxt->hostname = NULL; + } + if (ctxt->path != NULL) { + xmlFree(ctxt->path); + ctxt->path = NULL; + } + if (URL == NULL) return; + + uri = xmlParseURIRaw(URL, 1); + if (uri == NULL) + return; + + if ((uri->scheme == NULL) || (uri->server == NULL)) { + xmlFreeURI(uri); + return; + } + + ctxt->protocol = xmlMemStrdup(uri->scheme); + ctxt->hostname = xmlMemStrdup(uri->server); + if (uri->path != NULL) + ctxt->path = xmlMemStrdup(uri->path); + else + ctxt->path = xmlMemStrdup("/"); + if (uri->port != 0) + ctxt->port = uri->port; + + if (uri->user != NULL) { + char *cptr; + if ((cptr=strchr(uri->user, ':')) == NULL) + ctxt->user = xmlMemStrdup(uri->user); + else { + ctxt->user = (char *)xmlStrndup((xmlChar *)uri->user, + (cptr - uri->user)); + ctxt->passwd = xmlMemStrdup(cptr+1); + } + } + + xmlFreeURI(uri); + +} + +/** + * xmlNanoFTPUpdateURL: + * @ctx: an FTP context + * @URL: The URL used to update the context + * + * Update an FTP context by parsing the URL and finding + * new path it indicates. If there is an error in the + * protocol, hostname, port or other information, the + * error is raised. It indicates a new connection has to + * be established. + * + * Returns 0 if Ok, -1 in case of error (other host). + */ + +int +xmlNanoFTPUpdateURL(void *ctx, const char *URL) { + xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx; + xmlURIPtr uri; + + if (URL == NULL) + return(-1); + if (ctxt == NULL) + return(-1); + if (ctxt->protocol == NULL) + return(-1); + if (ctxt->hostname == NULL) + return(-1); + + uri = xmlParseURIRaw(URL, 1); + if (uri == NULL) + return(-1); + + if ((uri->scheme == NULL) || (uri->server == NULL)) { + xmlFreeURI(uri); + return(-1); + } + if ((strcmp(ctxt->protocol, uri->scheme)) || + (strcmp(ctxt->hostname, uri->server)) || + ((uri->port != 0) && (ctxt->port != uri->port))) { + xmlFreeURI(uri); + return(-1); + } + + if (uri->port != 0) + ctxt->port = uri->port; + + if (ctxt->path != NULL) { + xmlFree(ctxt->path); + ctxt->path = NULL; + } + + if (uri->path == NULL) + ctxt->path = xmlMemStrdup("/"); + else + ctxt->path = xmlMemStrdup(uri->path); + + xmlFreeURI(uri); + + return(0); +} + +/** + * xmlNanoFTPScanProxy: + * @URL: The proxy URL used to initialize the proxy context + * + * (Re)Initialize the FTP Proxy context by parsing the URL and finding + * the protocol host port it indicates. + * Should be like ftp://myproxy/ or ftp://myproxy:3128/ + * A NULL URL cleans up proxy informations. + */ + +void +xmlNanoFTPScanProxy(const char *URL) { + xmlURIPtr uri; + + if (proxy != NULL) { + xmlFree(proxy); + proxy = NULL; + } + proxyPort = 0; + +#ifdef DEBUG_FTP + if (URL == NULL) + xmlGenericError(xmlGenericErrorContext, + "Removing FTP proxy info\n"); + else + xmlGenericError(xmlGenericErrorContext, + "Using FTP proxy %s\n", URL); +#endif + if (URL == NULL) return; + + uri = xmlParseURIRaw(URL, 1); + if ((uri == NULL) || (uri->scheme == NULL) || + (strcmp(uri->scheme, "ftp")) || (uri->server == NULL)) { + __xmlIOErr(XML_FROM_FTP, XML_FTP_URL_SYNTAX, "Syntax Error\n"); + if (uri != NULL) + xmlFreeURI(uri); + return; + } + + proxy = xmlMemStrdup(uri->server); + if (uri->port != 0) + proxyPort = uri->port; + + xmlFreeURI(uri); +} + +/** + * xmlNanoFTPNewCtxt: + * @URL: The URL used to initialize the context + * + * Allocate and initialize a new FTP context. + * + * Returns an FTP context or NULL in case of error. + */ + +void* +xmlNanoFTPNewCtxt(const char *URL) { + xmlNanoFTPCtxtPtr ret; + char *unescaped; + + ret = (xmlNanoFTPCtxtPtr) xmlMalloc(sizeof(xmlNanoFTPCtxt)); + if (ret == NULL) { + xmlFTPErrMemory("allocating FTP context"); + return(NULL); + } + + memset(ret, 0, sizeof(xmlNanoFTPCtxt)); + ret->port = 21; + ret->passive = 1; + ret->returnValue = 0; + ret->controlBufIndex = 0; + ret->controlBufUsed = 0; + ret->controlFd = -1; + + unescaped = xmlURIUnescapeString(URL, 0, NULL); + if (unescaped != NULL) { + xmlNanoFTPScanURL(ret, unescaped); + xmlFree(unescaped); + } else if (URL != NULL) + xmlNanoFTPScanURL(ret, URL); + + return(ret); +} + +/** + * xmlNanoFTPFreeCtxt: + * @ctx: an FTP context + * + * Frees the context after closing the connection. + */ + +void +xmlNanoFTPFreeCtxt(void * ctx) { + xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx; + if (ctxt == NULL) return; + if (ctxt->hostname != NULL) xmlFree(ctxt->hostname); + if (ctxt->protocol != NULL) xmlFree(ctxt->protocol); + if (ctxt->path != NULL) xmlFree(ctxt->path); + ctxt->passive = 1; + if (ctxt->controlFd >= 0) closesocket(ctxt->controlFd); + ctxt->controlFd = -1; + ctxt->controlBufIndex = -1; + ctxt->controlBufUsed = -1; + xmlFree(ctxt); +} + +/** + * xmlNanoFTPParseResponse: + * @buf: the buffer containing the response + * @len: the buffer length + * + * Parsing of the server answer, we just extract the code. + * + * returns 0 for errors + * +XXX for last line of response + * -XXX for response to be continued + */ +static int +xmlNanoFTPParseResponse(char *buf, int len) { + int val = 0; + + if (len < 3) return(-1); + if ((*buf >= '0') && (*buf <= '9')) + val = val * 10 + (*buf - '0'); + else + return(0); + buf++; + if ((*buf >= '0') && (*buf <= '9')) + val = val * 10 + (*buf - '0'); + else + return(0); + buf++; + if ((*buf >= '0') && (*buf <= '9')) + val = val * 10 + (*buf - '0'); + else + return(0); + buf++; + if (*buf == '-') + return(-val); + return(val); +} + +/** + * xmlNanoFTPGetMore: + * @ctx: an FTP context + * + * Read more information from the FTP control connection + * Returns the number of bytes read, < 0 indicates an error + */ +static int +xmlNanoFTPGetMore(void *ctx) { + xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx; + int len; + int size; + + if ((ctxt == NULL) || (ctxt->controlFd < 0)) return(-1); + + if ((ctxt->controlBufIndex < 0) || (ctxt->controlBufIndex > FTP_BUF_SIZE)) { +#ifdef DEBUG_FTP + xmlGenericError(xmlGenericErrorContext, + "xmlNanoFTPGetMore : controlBufIndex = %d\n", + ctxt->controlBufIndex); +#endif + return(-1); + } + + if ((ctxt->controlBufUsed < 0) || (ctxt->controlBufUsed > FTP_BUF_SIZE)) { +#ifdef DEBUG_FTP + xmlGenericError(xmlGenericErrorContext, + "xmlNanoFTPGetMore : controlBufUsed = %d\n", + ctxt->controlBufUsed); +#endif + return(-1); + } + if (ctxt->controlBufIndex > ctxt->controlBufUsed) { +#ifdef DEBUG_FTP + xmlGenericError(xmlGenericErrorContext, + "xmlNanoFTPGetMore : controlBufIndex > controlBufUsed %d > %d\n", + ctxt->controlBufIndex, ctxt->controlBufUsed); +#endif + return(-1); + } + + /* + * First pack the control buffer + */ + if (ctxt->controlBufIndex > 0) { + memmove(&ctxt->controlBuf[0], &ctxt->controlBuf[ctxt->controlBufIndex], + ctxt->controlBufUsed - ctxt->controlBufIndex); + ctxt->controlBufUsed -= ctxt->controlBufIndex; + ctxt->controlBufIndex = 0; + } + size = FTP_BUF_SIZE - ctxt->controlBufUsed; + if (size == 0) { +#ifdef DEBUG_FTP + xmlGenericError(xmlGenericErrorContext, + "xmlNanoFTPGetMore : buffer full %d \n", ctxt->controlBufUsed); +#endif + return(0); + } + + /* + * Read the amount left on the control connection + */ + if ((len = recv(ctxt->controlFd, &ctxt->controlBuf[ctxt->controlBufIndex], + size, 0)) < 0) { + __xmlIOErr(XML_FROM_FTP, 0, "recv failed"); + closesocket(ctxt->controlFd); ctxt->controlFd = -1; + ctxt->controlFd = -1; + return(-1); + } +#ifdef DEBUG_FTP + xmlGenericError(xmlGenericErrorContext, + "xmlNanoFTPGetMore : read %d [%d - %d]\n", len, + ctxt->controlBufUsed, ctxt->controlBufUsed + len); +#endif + ctxt->controlBufUsed += len; + ctxt->controlBuf[ctxt->controlBufUsed] = 0; + + return(len); +} + +/** + * xmlNanoFTPReadResponse: + * @ctx: an FTP context + * + * Read the response from the FTP server after a command. + * Returns the code number + */ +static int +xmlNanoFTPReadResponse(void *ctx) { + xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx; + char *ptr, *end; + int len; + int res = -1, cur = -1; + + if ((ctxt == NULL) || (ctxt->controlFd < 0)) return(-1); + +get_more: + /* + * Assumes everything up to controlBuf[controlBufIndex] has been read + * and analyzed. + */ + len = xmlNanoFTPGetMore(ctx); + if (len < 0) { + return(-1); + } + if ((ctxt->controlBufUsed == 0) && (len == 0)) { + return(-1); + } + ptr = &ctxt->controlBuf[ctxt->controlBufIndex]; + end = &ctxt->controlBuf[ctxt->controlBufUsed]; + +#ifdef DEBUG_FTP + xmlGenericError(xmlGenericErrorContext, + "\n<<<\n%s\n--\n", ptr); +#endif + while (ptr < end) { + cur = xmlNanoFTPParseResponse(ptr, end - ptr); + if (cur > 0) { + /* + * Successfully scanned the control code, scratch + * till the end of the line, but keep the index to be + * able to analyze the result if needed. + */ + res = cur; + ptr += 3; + ctxt->controlBufAnswer = ptr - ctxt->controlBuf; + while ((ptr < end) && (*ptr != '\n')) ptr++; + if (*ptr == '\n') ptr++; + if (*ptr == '\r') ptr++; + break; + } + while ((ptr < end) && (*ptr != '\n')) ptr++; + if (ptr >= end) { + ctxt->controlBufIndex = ctxt->controlBufUsed; + goto get_more; + } + if (*ptr != '\r') ptr++; + } + + if (res < 0) goto get_more; + ctxt->controlBufIndex = ptr - ctxt->controlBuf; +#ifdef DEBUG_FTP + ptr = &ctxt->controlBuf[ctxt->controlBufIndex]; + xmlGenericError(xmlGenericErrorContext, "\n---\n%s\n--\n", ptr); +#endif + +#ifdef DEBUG_FTP + xmlGenericError(xmlGenericErrorContext, "Got %d\n", res); +#endif + return(res / 100); +} + +/** + * xmlNanoFTPGetResponse: + * @ctx: an FTP context + * + * Get the response from the FTP server after a command. + * Returns the code number + */ + +int +xmlNanoFTPGetResponse(void *ctx) { + int res; + + res = xmlNanoFTPReadResponse(ctx); + + return(res); +} + +/** + * xmlNanoFTPCheckResponse: + * @ctx: an FTP context + * + * Check if there is a response from the FTP server after a command. + * Returns the code number, or 0 + */ + +int +xmlNanoFTPCheckResponse(void *ctx) { + xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx; + fd_set rfd; + struct timeval tv; + + if ((ctxt == NULL) || (ctxt->controlFd < 0)) return(-1); + tv.tv_sec = 0; + tv.tv_usec = 0; + FD_ZERO(&rfd); + FD_SET(ctxt->controlFd, &rfd); + switch(select(ctxt->controlFd + 1, &rfd, NULL, NULL, &tv)) { + case 0: + return(0); + case -1: + __xmlIOErr(XML_FROM_FTP, 0, "select"); + return(-1); + + } + + return(xmlNanoFTPReadResponse(ctx)); +} + +/** + * Send the user authentication + */ + +static int +xmlNanoFTPSendUser(void *ctx) { + xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx; + char buf[200]; + int len; + int res; + + if (ctxt->user == NULL) + snprintf(buf, sizeof(buf), "USER anonymous\r\n"); + else + snprintf(buf, sizeof(buf), "USER %s\r\n", ctxt->user); + buf[sizeof(buf) - 1] = 0; + len = strlen(buf); +#ifdef DEBUG_FTP + xmlGenericError(xmlGenericErrorContext, "%s", buf); +#endif + res = send(ctxt->controlFd, buf, len, 0); + if (res < 0) { + __xmlIOErr(XML_FROM_FTP, 0, "send failed"); + return(res); + } + return(0); +} + +/** + * Send the password authentication + */ + +static int +xmlNanoFTPSendPasswd(void *ctx) { + xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx; + char buf[200]; + int len; + int res; + + if (ctxt->passwd == NULL) + snprintf(buf, sizeof(buf), "PASS anonymous@\r\n"); + else + snprintf(buf, sizeof(buf), "PASS %s\r\n", ctxt->passwd); + buf[sizeof(buf) - 1] = 0; + len = strlen(buf); +#ifdef DEBUG_FTP + xmlGenericError(xmlGenericErrorContext, "%s", buf); +#endif + res = send(ctxt->controlFd, buf, len, 0); + if (res < 0) { + __xmlIOErr(XML_FROM_FTP, 0, "send failed"); + return(res); + } + return(0); +} + +/** + * xmlNanoFTPQuit: + * @ctx: an FTP context + * + * Send a QUIT command to the server + * + * Returns -1 in case of error, 0 otherwise + */ + + +int +xmlNanoFTPQuit(void *ctx) { + xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx; + char buf[200]; + int len, res; + + if ((ctxt == NULL) || (ctxt->controlFd < 0)) return(-1); + + snprintf(buf, sizeof(buf), "QUIT\r\n"); + len = strlen(buf); +#ifdef DEBUG_FTP + xmlGenericError(xmlGenericErrorContext, "%s", buf); /* Just to be consistent, even though we know it can't have a % in it */ +#endif + res = send(ctxt->controlFd, buf, len, 0); + if (res < 0) { + __xmlIOErr(XML_FROM_FTP, 0, "send failed"); + return(res); + } + return(0); +} + +/** + * xmlNanoFTPConnect: + * @ctx: an FTP context + * + * Tries to open a control connection + * + * Returns -1 in case of error, 0 otherwise + */ + +int +xmlNanoFTPConnect(void *ctx) { + xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx; + struct hostent *hp; + int port; + int res; + int addrlen = sizeof (struct sockaddr_in); + + if (ctxt == NULL) + return(-1); + if (ctxt->hostname == NULL) + return(-1); + + /* + * do the blocking DNS query. + */ + if (proxy) { + port = proxyPort; + } else { + port = ctxt->port; + } + if (port == 0) + port = 21; + + memset (&ctxt->ftpAddr, 0, sizeof(ctxt->ftpAddr)); + +#ifdef SUPPORT_IP6 + if (have_ipv6 ()) { + struct addrinfo hints, *tmp, *result; + + result = NULL; + memset (&hints, 0, sizeof(hints)); + hints.ai_socktype = SOCK_STREAM; + + if (proxy) { + if (getaddrinfo (proxy, NULL, &hints, &result) != 0) { + __xmlIOErr(XML_FROM_FTP, 0, "getaddrinfo failed"); + return (-1); + } + } + else + if (getaddrinfo (ctxt->hostname, NULL, &hints, &result) != 0) { + __xmlIOErr(XML_FROM_FTP, 0, "getaddrinfo failed"); + return (-1); + } + + for (tmp = result; tmp; tmp = tmp->ai_next) + if (tmp->ai_family == AF_INET || tmp->ai_family == AF_INET6) + break; + + if (!tmp) { + if (result) + freeaddrinfo (result); + __xmlIOErr(XML_FROM_FTP, 0, "getaddrinfo failed"); + return (-1); + } + if (tmp->ai_addrlen > sizeof(ctxt->ftpAddr)) { + __xmlIOErr(XML_FROM_FTP, 0, "gethostbyname address mismatch"); + return (-1); + } + if (tmp->ai_family == AF_INET6) { + memcpy (&ctxt->ftpAddr, tmp->ai_addr, tmp->ai_addrlen); + ((struct sockaddr_in6 *) &ctxt->ftpAddr)->sin6_port = htons (port); + ctxt->controlFd = socket (AF_INET6, SOCK_STREAM, 0); + } + else { + memcpy (&ctxt->ftpAddr, tmp->ai_addr, tmp->ai_addrlen); + ((struct sockaddr_in *) &ctxt->ftpAddr)->sin_port = htons (port); + ctxt->controlFd = socket (AF_INET, SOCK_STREAM, 0); + } + addrlen = tmp->ai_addrlen; + freeaddrinfo (result); + } + else +#endif + { + if (proxy) + hp = gethostbyname (proxy); + else + hp = gethostbyname (ctxt->hostname); + if (hp == NULL) { + __xmlIOErr(XML_FROM_FTP, 0, "gethostbyname failed"); + return (-1); + } + if ((unsigned int) hp->h_length > + sizeof(((struct sockaddr_in *)&ctxt->ftpAddr)->sin_addr)) { + __xmlIOErr(XML_FROM_FTP, 0, "gethostbyname address mismatch"); + return (-1); + } + + /* + * Prepare the socket + */ + ((struct sockaddr_in *)&ctxt->ftpAddr)->sin_family = AF_INET; + memcpy (&((struct sockaddr_in *)&ctxt->ftpAddr)->sin_addr, + hp->h_addr_list[0], hp->h_length); + ((struct sockaddr_in *)&ctxt->ftpAddr)->sin_port = (u_short)htons ((unsigned short)port); + ctxt->controlFd = socket (AF_INET, SOCK_STREAM, 0); + addrlen = sizeof (struct sockaddr_in); + } + + if (ctxt->controlFd < 0) { + __xmlIOErr(XML_FROM_FTP, 0, "socket failed"); + return(-1); + } + + /* + * Do the connect. + */ + if (connect(ctxt->controlFd, (struct sockaddr *) &ctxt->ftpAddr, + addrlen) < 0) { + __xmlIOErr(XML_FROM_FTP, 0, "Failed to create a connection"); + closesocket(ctxt->controlFd); ctxt->controlFd = -1; + ctxt->controlFd = -1; + return(-1); + } + + /* + * Wait for the HELLO from the server. + */ + res = xmlNanoFTPGetResponse(ctxt); + if (res != 2) { + closesocket(ctxt->controlFd); ctxt->controlFd = -1; + ctxt->controlFd = -1; + return(-1); + } + + /* + * State diagram for the login operation on the FTP server + * + * Reference: RFC 959 + * + * 1 + * +---+ USER +---+------------->+---+ + * | B |---------->| W | 2 ---->| E | + * +---+ +---+------ | -->+---+ + * | | | | | + * 3 | | 4,5 | | | + * -------------- ----- | | | + * | | | | | + * | | | | | + * | --------- | + * | 1| | | | + * V | | | | + * +---+ PASS +---+ 2 | ------>+---+ + * | |---------->| W |------------->| S | + * +---+ +---+ ---------->+---+ + * | | | | | + * 3 | |4,5| | | + * -------------- -------- | + * | | | | | + * | | | | | + * | ----------- + * | 1,3| | | | + * V | 2| | | + * +---+ ACCT +---+-- | ----->+---+ + * | |---------->| W | 4,5 -------->| F | + * +---+ +---+------------->+---+ + * + * Of course in case of using a proxy this get really nasty and is not + * standardized at all :-( + */ + if (proxy) { + int len; + char buf[400]; + + if (proxyUser != NULL) { + /* + * We need proxy auth + */ + snprintf(buf, sizeof(buf), "USER %s\r\n", proxyUser); + buf[sizeof(buf) - 1] = 0; + len = strlen(buf); +#ifdef DEBUG_FTP + xmlGenericError(xmlGenericErrorContext, "%s", buf); +#endif + res = send(ctxt->controlFd, buf, len, 0); + if (res < 0) { + __xmlIOErr(XML_FROM_FTP, 0, "send failed"); + closesocket(ctxt->controlFd); + ctxt->controlFd = -1; + return(res); + } + res = xmlNanoFTPGetResponse(ctxt); + switch (res) { + case 2: + if (proxyPasswd == NULL) + break; + case 3: + if (proxyPasswd != NULL) + snprintf(buf, sizeof(buf), "PASS %s\r\n", proxyPasswd); + else + snprintf(buf, sizeof(buf), "PASS anonymous@\r\n"); + buf[sizeof(buf) - 1] = 0; + len = strlen(buf); +#ifdef DEBUG_FTP + xmlGenericError(xmlGenericErrorContext, "%s", buf); +#endif + res = send(ctxt->controlFd, buf, len, 0); + if (res < 0) { + __xmlIOErr(XML_FROM_FTP, 0, "send failed"); + closesocket(ctxt->controlFd); + ctxt->controlFd = -1; + return(res); + } + res = xmlNanoFTPGetResponse(ctxt); + if (res > 3) { + closesocket(ctxt->controlFd); + ctxt->controlFd = -1; + return(-1); + } + break; + case 1: + break; + case 4: + case 5: + case -1: + default: + closesocket(ctxt->controlFd); + ctxt->controlFd = -1; + return(-1); + } + } + + /* + * We assume we don't need more authentication to the proxy + * and that it succeeded :-\ + */ + switch (proxyType) { + case 0: + /* we will try in sequence */ + case 1: + /* Using SITE command */ + snprintf(buf, sizeof(buf), "SITE %s\r\n", ctxt->hostname); + buf[sizeof(buf) - 1] = 0; + len = strlen(buf); +#ifdef DEBUG_FTP + xmlGenericError(xmlGenericErrorContext, "%s", buf); +#endif + res = send(ctxt->controlFd, buf, len, 0); + if (res < 0) { + __xmlIOErr(XML_FROM_FTP, 0, "send failed"); + closesocket(ctxt->controlFd); ctxt->controlFd = -1; + ctxt->controlFd = -1; + return(res); + } + res = xmlNanoFTPGetResponse(ctxt); + if (res == 2) { + /* we assume it worked :-\ 1 is error for SITE command */ + proxyType = 1; + break; + } + if (proxyType == 1) { + closesocket(ctxt->controlFd); ctxt->controlFd = -1; + ctxt->controlFd = -1; + return(-1); + } + case 2: + /* USER user@host command */ + if (ctxt->user == NULL) + snprintf(buf, sizeof(buf), "USER anonymous@%s\r\n", + ctxt->hostname); + else + snprintf(buf, sizeof(buf), "USER %s@%s\r\n", + ctxt->user, ctxt->hostname); + buf[sizeof(buf) - 1] = 0; + len = strlen(buf); +#ifdef DEBUG_FTP + xmlGenericError(xmlGenericErrorContext, "%s", buf); +#endif + res = send(ctxt->controlFd, buf, len, 0); + if (res < 0) { + __xmlIOErr(XML_FROM_FTP, 0, "send failed"); + closesocket(ctxt->controlFd); ctxt->controlFd = -1; + ctxt->controlFd = -1; + return(res); + } + res = xmlNanoFTPGetResponse(ctxt); + if ((res == 1) || (res == 2)) { + /* we assume it worked :-\ */ + proxyType = 2; + return(0); + } + if (ctxt->passwd == NULL) + snprintf(buf, sizeof(buf), "PASS anonymous@\r\n"); + else + snprintf(buf, sizeof(buf), "PASS %s\r\n", ctxt->passwd); + buf[sizeof(buf) - 1] = 0; + len = strlen(buf); +#ifdef DEBUG_FTP + xmlGenericError(xmlGenericErrorContext, "%s", buf); +#endif + res = send(ctxt->controlFd, buf, len, 0); + if (res < 0) { + __xmlIOErr(XML_FROM_FTP, 0, "send failed"); + closesocket(ctxt->controlFd); ctxt->controlFd = -1; + ctxt->controlFd = -1; + return(res); + } + res = xmlNanoFTPGetResponse(ctxt); + if ((res == 1) || (res == 2)) { + /* we assume it worked :-\ */ + proxyType = 2; + return(0); + } + if (proxyType == 2) { + closesocket(ctxt->controlFd); ctxt->controlFd = -1; + ctxt->controlFd = -1; + return(-1); + } + case 3: + /* + * If you need support for other Proxy authentication scheme + * send the code or at least the sequence in use. + */ + default: + closesocket(ctxt->controlFd); ctxt->controlFd = -1; + ctxt->controlFd = -1; + return(-1); + } + } + /* + * Non-proxy handling. + */ + res = xmlNanoFTPSendUser(ctxt); + if (res < 0) { + closesocket(ctxt->controlFd); ctxt->controlFd = -1; + ctxt->controlFd = -1; + return(-1); + } + res = xmlNanoFTPGetResponse(ctxt); + switch (res) { + case 2: + return(0); + case 3: + break; + case 1: + case 4: + case 5: + case -1: + default: + closesocket(ctxt->controlFd); ctxt->controlFd = -1; + ctxt->controlFd = -1; + return(-1); + } + res = xmlNanoFTPSendPasswd(ctxt); + if (res < 0) { + closesocket(ctxt->controlFd); ctxt->controlFd = -1; + ctxt->controlFd = -1; + return(-1); + } + res = xmlNanoFTPGetResponse(ctxt); + switch (res) { + case 2: + break; + case 3: + __xmlIOErr(XML_FROM_FTP, XML_FTP_ACCNT, + "FTP server asking for ACCNT on anonymous\n"); + case 1: + case 4: + case 5: + case -1: + default: + closesocket(ctxt->controlFd); ctxt->controlFd = -1; + ctxt->controlFd = -1; + return(-1); + } + + return(0); +} + +/** + * xmlNanoFTPConnectTo: + * @server: an FTP server name + * @port: the port (use 21 if 0) + * + * Tries to open a control connection to the given server/port + * + * Returns an fTP context or NULL if it failed + */ + +void* +xmlNanoFTPConnectTo(const char *server, int port) { + xmlNanoFTPCtxtPtr ctxt; + int res; + + xmlNanoFTPInit(); + if (server == NULL) + return(NULL); + if (port <= 0) + return(NULL); + ctxt = (xmlNanoFTPCtxtPtr) xmlNanoFTPNewCtxt(NULL); + ctxt->hostname = xmlMemStrdup(server); + if (port != 0) + ctxt->port = port; + res = xmlNanoFTPConnect(ctxt); + if (res < 0) { + xmlNanoFTPFreeCtxt(ctxt); + return(NULL); + } + return(ctxt); +} + +/** + * xmlNanoFTPCwd: + * @ctx: an FTP context + * @directory: a directory on the server + * + * Tries to change the remote directory + * + * Returns -1 incase of error, 1 if CWD worked, 0 if it failed + */ + +int +xmlNanoFTPCwd(void *ctx, const char *directory) { + xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx; + char buf[400]; + int len; + int res; + + if ((ctxt == NULL) || (ctxt->controlFd < 0)) return(-1); + if (directory == NULL) return 0; + + /* + * Expected response code for CWD: + * + * CWD + * 250 + * 500, 501, 502, 421, 530, 550 + */ + snprintf(buf, sizeof(buf), "CWD %s\r\n", directory); + buf[sizeof(buf) - 1] = 0; + len = strlen(buf); +#ifdef DEBUG_FTP + xmlGenericError(xmlGenericErrorContext, "%s", buf); +#endif + res = send(ctxt->controlFd, buf, len, 0); + if (res < 0) { + __xmlIOErr(XML_FROM_FTP, 0, "send failed"); + return(res); + } + res = xmlNanoFTPGetResponse(ctxt); + if (res == 4) { + return(-1); + } + if (res == 2) return(1); + if (res == 5) { + return(0); + } + return(0); +} + +/** + * xmlNanoFTPDele: + * @ctx: an FTP context + * @file: a file or directory on the server + * + * Tries to delete an item (file or directory) from server + * + * Returns -1 incase of error, 1 if DELE worked, 0 if it failed + */ + +int +xmlNanoFTPDele(void *ctx, const char *file) { + xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx; + char buf[400]; + int len; + int res; + + if ((ctxt == NULL) || (ctxt->controlFd < 0) || (file == NULL)) return(-1); + if (file == NULL) return (0); + + /* + * Expected response code for DELE: + * + * DELE + * 250 + * 450, 550 + * 500, 501, 502, 421, 530 + */ + + snprintf(buf, sizeof(buf), "DELE %s\r\n", file); + buf[sizeof(buf) - 1] = 0; + len = strlen(buf); +#ifdef DEBUG_FTP + xmlGenericError(xmlGenericErrorContext, "%s", buf); +#endif + res = send(ctxt->controlFd, buf, len, 0); + if (res < 0) { + __xmlIOErr(XML_FROM_FTP, 0, "send failed"); + return(res); + } + res = xmlNanoFTPGetResponse(ctxt); + if (res == 4) { + return(-1); + } + if (res == 2) return(1); + if (res == 5) { + return(0); + } + return(0); +} +/** + * xmlNanoFTPGetConnection: + * @ctx: an FTP context + * + * Try to open a data connection to the server. Currently only + * passive mode is supported. + * + * Returns -1 incase of error, 0 otherwise + */ + +int +xmlNanoFTPGetConnection(void *ctx) { + xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx; + char buf[200], *cur; + int len, i; + int res; + unsigned char ad[6], *adp, *portp; + unsigned int temp[6]; +#ifdef SUPPORT_IP6 + struct sockaddr_storage dataAddr; +#else + struct sockaddr_in dataAddr; +#endif + XML_SOCKLEN_T dataAddrLen; + + if (ctxt == NULL) return(-1); + + memset (&dataAddr, 0, sizeof(dataAddr)); +#ifdef SUPPORT_IP6 + if ((ctxt->ftpAddr).ss_family == AF_INET6) { + ctxt->dataFd = socket (AF_INET6, SOCK_STREAM, IPPROTO_TCP); + ((struct sockaddr_in6 *)&dataAddr)->sin6_family = AF_INET6; + dataAddrLen = sizeof(struct sockaddr_in6); + } else +#endif + { + ctxt->dataFd = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); + ((struct sockaddr_in *)&dataAddr)->sin_family = AF_INET; + dataAddrLen = sizeof (struct sockaddr_in); + } + + if (ctxt->dataFd < 0) { + __xmlIOErr(XML_FROM_FTP, 0, "socket failed"); + return (-1); + } + + if (ctxt->passive) { +#ifdef SUPPORT_IP6 + if ((ctxt->ftpAddr).ss_family == AF_INET6) + snprintf (buf, sizeof(buf), "EPSV\r\n"); + else +#endif + snprintf (buf, sizeof(buf), "PASV\r\n"); + len = strlen (buf); +#ifdef DEBUG_FTP + xmlGenericError(xmlGenericErrorContext, "%s", buf); +#endif + res = send(ctxt->controlFd, buf, len, 0); + if (res < 0) { + __xmlIOErr(XML_FROM_FTP, 0, "send failed"); + closesocket(ctxt->dataFd); ctxt->dataFd = -1; + return(res); + } + res = xmlNanoFTPReadResponse(ctx); + if (res != 2) { + if (res == 5) { + closesocket(ctxt->dataFd); ctxt->dataFd = -1; + return(-1); + } else { + /* + * retry with an active connection + */ + closesocket(ctxt->dataFd); ctxt->dataFd = -1; + ctxt->passive = 0; + } + } + cur = &ctxt->controlBuf[ctxt->controlBufAnswer]; + while (((*cur < '0') || (*cur > '9')) && *cur != '\0') cur++; +#ifdef SUPPORT_IP6 + if ((ctxt->ftpAddr).ss_family == AF_INET6) { + if (sscanf (cur, "%u", &temp[0]) != 1) { + __xmlIOErr(XML_FROM_FTP, XML_FTP_EPSV_ANSWER, + "Invalid answer to EPSV\n"); + if (ctxt->dataFd != -1) { + closesocket (ctxt->dataFd); ctxt->dataFd = -1; + } + return (-1); + } + memcpy (&((struct sockaddr_in6 *)&dataAddr)->sin6_addr, &((struct sockaddr_in6 *)&ctxt->ftpAddr)->sin6_addr, sizeof(struct in6_addr)); + ((struct sockaddr_in6 *)&dataAddr)->sin6_port = htons (temp[0]); + } + else +#endif + { + if (sscanf (cur, "%u,%u,%u,%u,%u,%u", &temp[0], &temp[1], &temp[2], + &temp[3], &temp[4], &temp[5]) != 6) { + __xmlIOErr(XML_FROM_FTP, XML_FTP_PASV_ANSWER, + "Invalid answer to PASV\n"); + if (ctxt->dataFd != -1) { + closesocket (ctxt->dataFd); ctxt->dataFd = -1; + } + return (-1); + } + for (i=0; i<6; i++) ad[i] = (unsigned char) (temp[i] & 0xff); + memcpy (&((struct sockaddr_in *)&dataAddr)->sin_addr, &ad[0], 4); + memcpy (&((struct sockaddr_in *)&dataAddr)->sin_port, &ad[4], 2); + } + + if (connect(ctxt->dataFd, (struct sockaddr *) &dataAddr, dataAddrLen) < 0) { + __xmlIOErr(XML_FROM_FTP, 0, "Failed to create a data connection"); + closesocket(ctxt->dataFd); ctxt->dataFd = -1; + return (-1); + } + } else { + getsockname(ctxt->dataFd, (struct sockaddr *) &dataAddr, &dataAddrLen); +#ifdef SUPPORT_IP6 + if ((ctxt->ftpAddr).ss_family == AF_INET6) + ((struct sockaddr_in6 *)&dataAddr)->sin6_port = 0; + else +#endif + ((struct sockaddr_in *)&dataAddr)->sin_port = 0; + + if (bind(ctxt->dataFd, (struct sockaddr *) &dataAddr, dataAddrLen) < 0) { + __xmlIOErr(XML_FROM_FTP, 0, "bind failed"); + closesocket(ctxt->dataFd); ctxt->dataFd = -1; + return (-1); + } + getsockname(ctxt->dataFd, (struct sockaddr *) &dataAddr, &dataAddrLen); + + if (listen(ctxt->dataFd, 1) < 0) { + __xmlIOErr(XML_FROM_FTP, 0, "listen failed"); + closesocket(ctxt->dataFd); ctxt->dataFd = -1; + return (-1); + } +#ifdef SUPPORT_IP6 + if ((ctxt->ftpAddr).ss_family == AF_INET6) { + char buf6[INET6_ADDRSTRLEN]; + inet_ntop (AF_INET6, &((struct sockaddr_in6 *)&dataAddr)->sin6_addr, + buf6, INET6_ADDRSTRLEN); + adp = (unsigned char *) buf6; + portp = (unsigned char *) &((struct sockaddr_in6 *)&dataAddr)->sin6_port; + snprintf (buf, sizeof(buf), "EPRT |2|%s|%s|\r\n", adp, portp); + } else +#endif + { + adp = (unsigned char *) &((struct sockaddr_in *)&dataAddr)->sin_addr; + portp = (unsigned char *) &((struct sockaddr_in *)&dataAddr)->sin_port; + snprintf (buf, sizeof(buf), "PORT %d,%d,%d,%d,%d,%d\r\n", + adp[0] & 0xff, adp[1] & 0xff, adp[2] & 0xff, adp[3] & 0xff, + portp[0] & 0xff, portp[1] & 0xff); + } + + buf[sizeof(buf) - 1] = 0; + len = strlen(buf); +#ifdef DEBUG_FTP + xmlGenericError(xmlGenericErrorContext, "%s", buf); +#endif + + res = send(ctxt->controlFd, buf, len, 0); + if (res < 0) { + __xmlIOErr(XML_FROM_FTP, 0, "send failed"); + closesocket(ctxt->dataFd); ctxt->dataFd = -1; + return(res); + } + res = xmlNanoFTPGetResponse(ctxt); + if (res != 2) { + closesocket(ctxt->dataFd); ctxt->dataFd = -1; + return(-1); + } + } + return(ctxt->dataFd); + +} + +/** + * xmlNanoFTPCloseConnection: + * @ctx: an FTP context + * + * Close the data connection from the server + * + * Returns -1 incase of error, 0 otherwise + */ + +int +xmlNanoFTPCloseConnection(void *ctx) { + xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx; + int res; + fd_set rfd, efd; + struct timeval tv; + + if ((ctxt == NULL) || (ctxt->controlFd < 0)) return(-1); + + closesocket(ctxt->dataFd); ctxt->dataFd = -1; + tv.tv_sec = 15; + tv.tv_usec = 0; + FD_ZERO(&rfd); + FD_SET(ctxt->controlFd, &rfd); + FD_ZERO(&efd); + FD_SET(ctxt->controlFd, &efd); + res = select(ctxt->controlFd + 1, &rfd, NULL, &efd, &tv); + if (res < 0) { +#ifdef DEBUG_FTP + perror("select"); +#endif + closesocket(ctxt->controlFd); ctxt->controlFd = -1; + return(-1); + } + if (res == 0) { +#ifdef DEBUG_FTP + xmlGenericError(xmlGenericErrorContext, + "xmlNanoFTPCloseConnection: timeout\n"); +#endif + closesocket(ctxt->controlFd); ctxt->controlFd = -1; + } else { + res = xmlNanoFTPGetResponse(ctxt); + if (res != 2) { + closesocket(ctxt->controlFd); ctxt->controlFd = -1; + return(-1); + } + } + return(0); +} + +/** + * xmlNanoFTPParseList: + * @list: some data listing received from the server + * @callback: the user callback + * @userData: the user callback data + * + * Parse at most one entry from the listing. + * + * Returns -1 incase of error, the length of data parsed otherwise + */ + +static int +xmlNanoFTPParseList(const char *list, ftpListCallback callback, void *userData) { + const char *cur = list; + char filename[151]; + char attrib[11]; + char owner[11]; + char group[11]; + char month[4]; + int year = 0; + int minute = 0; + int hour = 0; + int day = 0; + unsigned long size = 0; + int links = 0; + int i; + + if (!strncmp(cur, "total", 5)) { + cur += 5; + while (*cur == ' ') cur++; + while ((*cur >= '0') && (*cur <= '9')) + links = (links * 10) + (*cur++ - '0'); + while ((*cur == ' ') || (*cur == '\n') || (*cur == '\r')) + cur++; + return(cur - list); + } else if (*list == '+') { + return(0); + } else { + while ((*cur == ' ') || (*cur == '\n') || (*cur == '\r')) + cur++; + if (*cur == 0) return(0); + i = 0; + while (*cur != ' ') { + if (i < 10) + attrib[i++] = *cur; + cur++; + if (*cur == 0) return(0); + } + attrib[10] = 0; + while (*cur == ' ') cur++; + if (*cur == 0) return(0); + while ((*cur >= '0') && (*cur <= '9')) + links = (links * 10) + (*cur++ - '0'); + while (*cur == ' ') cur++; + if (*cur == 0) return(0); + i = 0; + while (*cur != ' ') { + if (i < 10) + owner[i++] = *cur; + cur++; + if (*cur == 0) return(0); + } + owner[i] = 0; + while (*cur == ' ') cur++; + if (*cur == 0) return(0); + i = 0; + while (*cur != ' ') { + if (i < 10) + group[i++] = *cur; + cur++; + if (*cur == 0) return(0); + } + group[i] = 0; + while (*cur == ' ') cur++; + if (*cur == 0) return(0); + while ((*cur >= '0') && (*cur <= '9')) + size = (size * 10) + (*cur++ - '0'); + while (*cur == ' ') cur++; + if (*cur == 0) return(0); + i = 0; + while (*cur != ' ') { + if (i < 3) + month[i++] = *cur; + cur++; + if (*cur == 0) return(0); + } + month[i] = 0; + while (*cur == ' ') cur++; + if (*cur == 0) return(0); + while ((*cur >= '0') && (*cur <= '9')) + day = (day * 10) + (*cur++ - '0'); + while (*cur == ' ') cur++; + if (*cur == 0) return(0); + if ((cur[1] == 0) || (cur[2] == 0)) return(0); + if ((cur[1] == ':') || (cur[2] == ':')) { + while ((*cur >= '0') && (*cur <= '9')) + hour = (hour * 10) + (*cur++ - '0'); + if (*cur == ':') cur++; + while ((*cur >= '0') && (*cur <= '9')) + minute = (minute * 10) + (*cur++ - '0'); + } else { + while ((*cur >= '0') && (*cur <= '9')) + year = (year * 10) + (*cur++ - '0'); + } + while (*cur == ' ') cur++; + if (*cur == 0) return(0); + i = 0; + while ((*cur != '\n') && (*cur != '\r')) { + if (i < 150) + filename[i++] = *cur; + cur++; + if (*cur == 0) return(0); + } + filename[i] = 0; + if ((*cur != '\n') && (*cur != '\r')) + return(0); + while ((*cur == '\n') || (*cur == '\r')) + cur++; + } + if (callback != NULL) { + callback(userData, filename, attrib, owner, group, size, links, + year, month, day, hour, minute); + } + return(cur - list); +} + +/** + * xmlNanoFTPList: + * @ctx: an FTP context + * @callback: the user callback + * @userData: the user callback data + * @filename: optional files to list + * + * Do a listing on the server. All files info are passed back + * in the callbacks. + * + * Returns -1 incase of error, 0 otherwise + */ + +int +xmlNanoFTPList(void *ctx, ftpListCallback callback, void *userData, + const char *filename) { + xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx; + char buf[4096 + 1]; + int len, res; + int indx = 0, base; + fd_set rfd, efd; + struct timeval tv; + + if (ctxt == NULL) return (-1); + if (filename == NULL) { + if (xmlNanoFTPCwd(ctxt, ctxt->path) < 1) + return(-1); + ctxt->dataFd = xmlNanoFTPGetConnection(ctxt); + if (ctxt->dataFd == -1) + return(-1); + snprintf(buf, sizeof(buf), "LIST -L\r\n"); + } else { + if (filename[0] != '/') { + if (xmlNanoFTPCwd(ctxt, ctxt->path) < 1) + return(-1); + } + ctxt->dataFd = xmlNanoFTPGetConnection(ctxt); + if (ctxt->dataFd == -1) + return(-1); + snprintf(buf, sizeof(buf), "LIST -L %s\r\n", filename); + } + buf[sizeof(buf) - 1] = 0; + len = strlen(buf); +#ifdef DEBUG_FTP + xmlGenericError(xmlGenericErrorContext, "%s", buf); +#endif + res = send(ctxt->controlFd, buf, len, 0); + if (res < 0) { + __xmlIOErr(XML_FROM_FTP, 0, "send failed"); + closesocket(ctxt->dataFd); ctxt->dataFd = -1; + return(res); + } + res = xmlNanoFTPReadResponse(ctxt); + if (res != 1) { + closesocket(ctxt->dataFd); ctxt->dataFd = -1; + return(-res); + } + + do { + tv.tv_sec = 1; + tv.tv_usec = 0; + FD_ZERO(&rfd); + FD_SET(ctxt->dataFd, &rfd); + FD_ZERO(&efd); + FD_SET(ctxt->dataFd, &efd); + res = select(ctxt->dataFd + 1, &rfd, NULL, &efd, &tv); + if (res < 0) { +#ifdef DEBUG_FTP + perror("select"); +#endif + closesocket(ctxt->dataFd); ctxt->dataFd = -1; + return(-1); + } + if (res == 0) { + res = xmlNanoFTPCheckResponse(ctxt); + if (res < 0) { + closesocket(ctxt->dataFd); ctxt->dataFd = -1; + ctxt->dataFd = -1; + return(-1); + } + if (res == 2) { + closesocket(ctxt->dataFd); ctxt->dataFd = -1; + return(0); + } + + continue; + } + + if ((len = recv(ctxt->dataFd, &buf[indx], sizeof(buf) - (indx + 1), 0)) < 0) { + __xmlIOErr(XML_FROM_FTP, 0, "recv"); + closesocket(ctxt->dataFd); ctxt->dataFd = -1; + ctxt->dataFd = -1; + return(-1); + } +#ifdef DEBUG_FTP + write(1, &buf[indx], len); +#endif + indx += len; + buf[indx] = 0; + base = 0; + do { + res = xmlNanoFTPParseList(&buf[base], callback, userData); + base += res; + } while (res > 0); + + memmove(&buf[0], &buf[base], indx - base); + indx -= base; + } while (len != 0); + xmlNanoFTPCloseConnection(ctxt); + return(0); +} + +/** + * xmlNanoFTPGetSocket: + * @ctx: an FTP context + * @filename: the file to retrieve (or NULL if path is in context). + * + * Initiate fetch of the given file from the server. + * + * Returns the socket for the data connection, or <0 in case of error + */ + + +int +xmlNanoFTPGetSocket(void *ctx, const char *filename) { + xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx; + char buf[300]; + int res, len; + if (ctx == NULL) + return(-1); + if ((filename == NULL) && (ctxt->path == NULL)) + return(-1); + ctxt->dataFd = xmlNanoFTPGetConnection(ctxt); + if (ctxt->dataFd == -1) + return(-1); + + snprintf(buf, sizeof(buf), "TYPE I\r\n"); + len = strlen(buf); +#ifdef DEBUG_FTP + xmlGenericError(xmlGenericErrorContext, "%s", buf); +#endif + res = send(ctxt->controlFd, buf, len, 0); + if (res < 0) { + __xmlIOErr(XML_FROM_FTP, 0, "send failed"); + closesocket(ctxt->dataFd); ctxt->dataFd = -1; + return(res); + } + res = xmlNanoFTPReadResponse(ctxt); + if (res != 2) { + closesocket(ctxt->dataFd); ctxt->dataFd = -1; + return(-res); + } + if (filename == NULL) + snprintf(buf, sizeof(buf), "RETR %s\r\n", ctxt->path); + else + snprintf(buf, sizeof(buf), "RETR %s\r\n", filename); + buf[sizeof(buf) - 1] = 0; + len = strlen(buf); +#ifdef DEBUG_FTP + xmlGenericError(xmlGenericErrorContext, "%s", buf); +#endif + res = send(ctxt->controlFd, buf, len, 0); + if (res < 0) { + __xmlIOErr(XML_FROM_FTP, 0, "send failed"); + closesocket(ctxt->dataFd); ctxt->dataFd = -1; + return(res); + } + res = xmlNanoFTPReadResponse(ctxt); + if (res != 1) { + closesocket(ctxt->dataFd); ctxt->dataFd = -1; + return(-res); + } + return(ctxt->dataFd); +} + +/** + * xmlNanoFTPGet: + * @ctx: an FTP context + * @callback: the user callback + * @userData: the user callback data + * @filename: the file to retrieve + * + * Fetch the given file from the server. All data are passed back + * in the callbacks. The last callback has a size of 0 block. + * + * Returns -1 incase of error, 0 otherwise + */ + +int +xmlNanoFTPGet(void *ctx, ftpDataCallback callback, void *userData, + const char *filename) { + xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx; + char buf[4096]; + int len = 0, res; + fd_set rfd; + struct timeval tv; + + if (ctxt == NULL) return(-1); + if ((filename == NULL) && (ctxt->path == NULL)) + return(-1); + if (callback == NULL) + return(-1); + if (xmlNanoFTPGetSocket(ctxt, filename) < 0) + return(-1); + + do { + tv.tv_sec = 1; + tv.tv_usec = 0; + FD_ZERO(&rfd); + FD_SET(ctxt->dataFd, &rfd); + res = select(ctxt->dataFd + 1, &rfd, NULL, NULL, &tv); + if (res < 0) { +#ifdef DEBUG_FTP + perror("select"); +#endif + closesocket(ctxt->dataFd); ctxt->dataFd = -1; + return(-1); + } + if (res == 0) { + res = xmlNanoFTPCheckResponse(ctxt); + if (res < 0) { + closesocket(ctxt->dataFd); ctxt->dataFd = -1; + ctxt->dataFd = -1; + return(-1); + } + if (res == 2) { + closesocket(ctxt->dataFd); ctxt->dataFd = -1; + return(0); + } + + continue; + } + if ((len = recv(ctxt->dataFd, buf, sizeof(buf), 0)) < 0) { + __xmlIOErr(XML_FROM_FTP, 0, "recv failed"); + callback(userData, buf, len); + closesocket(ctxt->dataFd); ctxt->dataFd = -1; + return(-1); + } + callback(userData, buf, len); + } while (len != 0); + + return(xmlNanoFTPCloseConnection(ctxt)); +} + +/** + * xmlNanoFTPRead: + * @ctx: the FTP context + * @dest: a buffer + * @len: the buffer length + * + * This function tries to read @len bytes from the existing FTP connection + * and saves them in @dest. This is a blocking call. + * + * Returns the number of byte read. 0 is an indication of an end of connection. + * -1 indicates a parameter error. + */ +int +xmlNanoFTPRead(void *ctx, void *dest, int len) { + xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx; + + if (ctx == NULL) return(-1); + if (ctxt->dataFd < 0) return(0); + if (dest == NULL) return(-1); + if (len <= 0) return(0); + + len = recv(ctxt->dataFd, dest, len, 0); + if (len <= 0) { + if (len < 0) + __xmlIOErr(XML_FROM_FTP, 0, "recv failed"); + xmlNanoFTPCloseConnection(ctxt); + } +#ifdef DEBUG_FTP + xmlGenericError(xmlGenericErrorContext, "Recvd %d bytes\n", len); +#endif + return(len); +} + +/** + * xmlNanoFTPOpen: + * @URL: the URL to the resource + * + * Start to fetch the given ftp:// resource + * + * Returns an FTP context, or NULL + */ + +void* +xmlNanoFTPOpen(const char *URL) { + xmlNanoFTPCtxtPtr ctxt; + int sock; + + xmlNanoFTPInit(); + if (URL == NULL) return(NULL); + if (strncmp("ftp://", URL, 6)) return(NULL); + + ctxt = (xmlNanoFTPCtxtPtr) xmlNanoFTPNewCtxt(URL); + if (ctxt == NULL) return(NULL); + if (xmlNanoFTPConnect(ctxt) < 0) { + xmlNanoFTPFreeCtxt(ctxt); + return(NULL); + } + sock = xmlNanoFTPGetSocket(ctxt, ctxt->path); + if (sock < 0) { + xmlNanoFTPFreeCtxt(ctxt); + return(NULL); + } + return(ctxt); +} + +/** + * xmlNanoFTPClose: + * @ctx: an FTP context + * + * Close the connection and both control and transport + * + * Returns -1 incase of error, 0 otherwise + */ + +int +xmlNanoFTPClose(void *ctx) { + xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx; + + if (ctxt == NULL) + return(-1); + + if (ctxt->dataFd >= 0) { + closesocket(ctxt->dataFd); + ctxt->dataFd = -1; + } + if (ctxt->controlFd >= 0) { + xmlNanoFTPQuit(ctxt); + closesocket(ctxt->controlFd); + ctxt->controlFd = -1; + } + xmlNanoFTPFreeCtxt(ctxt); + return(0); +} + +#ifdef STANDALONE +/************************************************************************ + * * + * Basic test in Standalone mode * + * * + ************************************************************************/ +static +void ftpList(void *userData, const char *filename, const char* attrib, + const char *owner, const char *group, unsigned long size, int links, + int year, const char *month, int day, int hour, int minute) { + xmlGenericError(xmlGenericErrorContext, + "%s %s %s %ld %s\n", attrib, owner, group, size, filename); +} +static +void ftpData(void *userData, const char *data, int len) { + if (userData == NULL) return; + if (len <= 0) { + fclose((FILE*)userData); + return; + } + fwrite(data, len, 1, (FILE*)userData); +} + +int main(int argc, char **argv) { + void *ctxt; + FILE *output; + char *tstfile = NULL; + + xmlNanoFTPInit(); + if (argc > 1) { + ctxt = xmlNanoFTPNewCtxt(argv[1]); + if (xmlNanoFTPConnect(ctxt) < 0) { + xmlGenericError(xmlGenericErrorContext, + "Couldn't connect to %s\n", argv[1]); + exit(1); + } + if (argc > 2) + tstfile = argv[2]; + } else + ctxt = xmlNanoFTPConnectTo("localhost", 0); + if (ctxt == NULL) { + xmlGenericError(xmlGenericErrorContext, + "Couldn't connect to localhost\n"); + exit(1); + } + xmlNanoFTPList(ctxt, ftpList, NULL, tstfile); + output = fopen("/tmp/tstdata", "w"); + if (output != NULL) { + if (xmlNanoFTPGet(ctxt, ftpData, (void *) output, tstfile) < 0) + xmlGenericError(xmlGenericErrorContext, + "Failed to get file\n"); + + } + xmlNanoFTPClose(ctxt); + xmlMemoryDump(); + exit(0); +} +#endif /* STANDALONE */ +#else /* !LIBXML_FTP_ENABLED */ +#ifdef STANDALONE +#include +int main(int argc, char **argv) { + xmlGenericError(xmlGenericErrorContext, + "%s : FTP support not compiled in\n", argv[0]); + return(0); +} +#endif /* STANDALONE */ +#endif /* LIBXML_FTP_ENABLED */ +#define bottom_nanoftp +#include "elfgcchack.h" diff --git a/gettext-tools/gnulib-lib/libxml/nanoftp.in.h b/gettext-tools/gnulib-lib/libxml/nanoftp.in.h new file mode 100644 index 0000000..e3c28a0 --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/nanoftp.in.h @@ -0,0 +1,143 @@ +/* + * Summary: minimal FTP implementation + * Description: minimal FTP implementation allowing to fetch resources + * like external subset. + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + +#ifndef __NANO_FTP_H__ +#define __NANO_FTP_H__ + +#include + +#ifdef LIBXML_FTP_ENABLED + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * ftpListCallback: + * @userData: user provided data for the callback + * @filename: the file name (including "->" when links are shown) + * @attrib: the attribute string + * @owner: the owner string + * @group: the group string + * @size: the file size + * @links: the link count + * @year: the year + * @month: the month + * @day: the day + * @hour: the hour + * @minute: the minute + * + * A callback for the xmlNanoFTPList command. + * Note that only one of year and day:minute are specified. + */ +typedef void (*ftpListCallback) (void *userData, + const char *filename, const char *attrib, + const char *owner, const char *group, + unsigned long size, int links, int year, + const char *month, int day, int hour, + int minute); +/** + * ftpDataCallback: + * @userData: the user provided context + * @data: the data received + * @len: its size in bytes + * + * A callback for the xmlNanoFTPGet command. + */ +typedef void (*ftpDataCallback) (void *userData, + const char *data, + int len); + +/* + * Init + */ +XMLPUBFUN void XMLCALL + xmlNanoFTPInit (void); +XMLPUBFUN void XMLCALL + xmlNanoFTPCleanup (void); + +/* + * Creating/freeing contexts. + */ +XMLPUBFUN void * XMLCALL + xmlNanoFTPNewCtxt (const char *URL); +XMLPUBFUN void XMLCALL + xmlNanoFTPFreeCtxt (void * ctx); +XMLPUBFUN void * XMLCALL + xmlNanoFTPConnectTo (const char *server, + int port); +/* + * Opening/closing session connections. + */ +XMLPUBFUN void * XMLCALL + xmlNanoFTPOpen (const char *URL); +XMLPUBFUN int XMLCALL + xmlNanoFTPConnect (void *ctx); +XMLPUBFUN int XMLCALL + xmlNanoFTPClose (void *ctx); +XMLPUBFUN int XMLCALL + xmlNanoFTPQuit (void *ctx); +XMLPUBFUN void XMLCALL + xmlNanoFTPScanProxy (const char *URL); +XMLPUBFUN void XMLCALL + xmlNanoFTPProxy (const char *host, + int port, + const char *user, + const char *passwd, + int type); +XMLPUBFUN int XMLCALL + xmlNanoFTPUpdateURL (void *ctx, + const char *URL); + +/* + * Rather internal commands. + */ +XMLPUBFUN int XMLCALL + xmlNanoFTPGetResponse (void *ctx); +XMLPUBFUN int XMLCALL + xmlNanoFTPCheckResponse (void *ctx); + +/* + * CD/DIR/GET handlers. + */ +XMLPUBFUN int XMLCALL + xmlNanoFTPCwd (void *ctx, + const char *directory); +XMLPUBFUN int XMLCALL + xmlNanoFTPDele (void *ctx, + const char *file); + +XMLPUBFUN int XMLCALL + xmlNanoFTPGetConnection (void *ctx); +XMLPUBFUN int XMLCALL + xmlNanoFTPCloseConnection(void *ctx); +XMLPUBFUN int XMLCALL + xmlNanoFTPList (void *ctx, + ftpListCallback callback, + void *userData, + const char *filename); +XMLPUBFUN int XMLCALL + xmlNanoFTPGetSocket (void *ctx, + const char *filename); +XMLPUBFUN int XMLCALL + xmlNanoFTPGet (void *ctx, + ftpDataCallback callback, + void *userData, + const char *filename); +XMLPUBFUN int XMLCALL + xmlNanoFTPRead (void *ctx, + void *dest, + int len); + +#ifdef __cplusplus +} +#endif +#endif /* LIBXML_FTP_ENABLED */ +#endif /* __NANO_FTP_H__ */ diff --git a/gettext-tools/gnulib-lib/libxml/nanohttp.c b/gettext-tools/gnulib-lib/libxml/nanohttp.c new file mode 100644 index 0000000..ae7923f --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/nanohttp.c @@ -0,0 +1,1791 @@ +/* + * nanohttp.c: minimalist HTTP GET implementation to fetch external subsets. + * focuses on size, streamability, reentrancy and portability + * + * This is clearly not a general purpose HTTP implementation + * If you look for one, check: + * http://www.w3.org/Library/ + * + * See Copyright for the status of this software. + * + * daniel@veillard.com + */ + +#define NEED_SOCKETS +#define IN_LIBXML +#include "libxml.h" + +#ifdef LIBXML_HTTP_ENABLED +#include + +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_RESOLV_H +#ifdef HAVE_ARPA_NAMESER_H +#include +#endif +#include +#endif +#ifdef HAVE_FCNTL_H +#include +#endif +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_SYS_TIME_H +#include +#endif +#ifdef HAVE_SYS_SELECT_H +#include +#endif +#ifdef HAVE_STRINGS_H +#include +#endif +#ifdef SUPPORT_IP6 +#include +#endif +#ifdef HAVE_ZLIB_H +#include +#endif + + +#ifdef VMS +#include +#define XML_SOCKLEN_T unsigned int +#define SOCKET int +#endif + + +#ifdef __MINGW32__ +#define _WINSOCKAPI_ +#include +#include +#undef XML_SOCKLEN_T +#define XML_SOCKLEN_T unsigned int +#endif + + +#include +#include +#include +#include /* for xmlStr(n)casecmp() */ +#include +#include +#include + +/** + * A couple portability macros + */ +#ifndef _WINSOCKAPI_ +#ifndef __BEOS__ +#define closesocket(s) close(s) +#endif +#define SOCKET int +#endif + +#ifdef __BEOS__ +#ifndef PF_INET +#define PF_INET AF_INET +#endif +#endif + +#ifndef XML_SOCKLEN_T +#define XML_SOCKLEN_T unsigned int +#endif +#ifndef SOCKET +#define SOCKET int +#endif + +#ifdef STANDALONE +#define DEBUG_HTTP +#define xmlStrncasecmp(a, b, n) strncasecmp((char *)a, (char *)b, n) +#define xmlStrcasecmpi(a, b) strcasecmp((char *)a, (char *)b) +#endif + +#define XML_NANO_HTTP_MAX_REDIR 10 + +#define XML_NANO_HTTP_CHUNK 4096 + +#define XML_NANO_HTTP_CLOSED 0 +#define XML_NANO_HTTP_WRITE 1 +#define XML_NANO_HTTP_READ 2 +#define XML_NANO_HTTP_NONE 4 + +typedef struct xmlNanoHTTPCtxt { + char *protocol; /* the protocol name */ + char *hostname; /* the host name */ + int port; /* the port */ + char *path; /* the path within the URL */ + char *query; /* the query string */ + SOCKET fd; /* the file descriptor for the socket */ + int state; /* WRITE / READ / CLOSED */ + char *out; /* buffer sent (zero terminated) */ + char *outptr; /* index within the buffer sent */ + char *in; /* the receiving buffer */ + char *content; /* the start of the content */ + char *inptr; /* the next byte to read from network */ + char *inrptr; /* the next byte to give back to the client */ + int inlen; /* len of the input buffer */ + int last; /* return code for last operation */ + int returnValue; /* the protocol return value */ + int ContentLength; /* specified content length from HTTP header */ + char *contentType; /* the MIME type for the input */ + char *location; /* the new URL in case of redirect */ + char *authHeader; /* contents of {WWW,Proxy}-Authenticate header */ + char *encoding; /* encoding extracted from the contentType */ + char *mimeType; /* Mime-Type extracted from the contentType */ +#ifdef HAVE_ZLIB_H + z_stream *strm; /* Zlib stream object */ + int usesGzip; /* "Content-Encoding: gzip" was detected */ +#endif +} xmlNanoHTTPCtxt, *xmlNanoHTTPCtxtPtr; + +static int initialized = 0; +static char *proxy = NULL; /* the proxy name if any */ +static int proxyPort; /* the proxy port if any */ +static unsigned int timeout = 60;/* the select() timeout in seconds */ + +static int xmlNanoHTTPFetchContent( void * ctx, char ** ptr, int * len ); + +/** + * xmlHTTPErrMemory: + * @extra: extra informations + * + * Handle an out of memory condition + */ +static void +xmlHTTPErrMemory(const char *extra) +{ + __xmlSimpleError(XML_FROM_HTTP, XML_ERR_NO_MEMORY, NULL, NULL, extra); +} + +/** + * A portability function + */ +static int socket_errno(void) { +#ifdef _WINSOCKAPI_ + return(WSAGetLastError()); +#else + return(errno); +#endif +} + +#ifdef SUPPORT_IP6 +static +int have_ipv6(void) { + int s; + + s = socket (AF_INET6, SOCK_STREAM, 0); + if (s != -1) { + close (s); + return (1); + } + return (0); +} +#endif + +/** + * xmlNanoHTTPInit: + * + * Initialize the HTTP protocol layer. + * Currently it just checks for proxy informations + */ + +void +xmlNanoHTTPInit(void) { + const char *env; +#ifdef _WINSOCKAPI_ + WSADATA wsaData; +#endif + + if (initialized) + return; + +#ifdef _WINSOCKAPI_ + if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0) + return; +#endif + + if (proxy == NULL) { + proxyPort = 80; + env = getenv("no_proxy"); + if (env && ((env[0] == '*') && (env[1] == 0))) + goto done; + env = getenv("http_proxy"); + if (env != NULL) { + xmlNanoHTTPScanProxy(env); + goto done; + } + env = getenv("HTTP_PROXY"); + if (env != NULL) { + xmlNanoHTTPScanProxy(env); + goto done; + } + } +done: + initialized = 1; +} + +/** + * xmlNanoHTTPCleanup: + * + * Cleanup the HTTP protocol layer. + */ + +void +xmlNanoHTTPCleanup(void) { + if (proxy != NULL) { + xmlFree(proxy); + proxy = NULL; + } +#ifdef _WINSOCKAPI_ + if (initialized) + WSACleanup(); +#endif + initialized = 0; + return; +} + +/** + * xmlNanoHTTPScanURL: + * @ctxt: an HTTP context + * @URL: The URL used to initialize the context + * + * (Re)Initialize an HTTP context by parsing the URL and finding + * the protocol host port and path it indicates. + */ + +static void +xmlNanoHTTPScanURL(xmlNanoHTTPCtxtPtr ctxt, const char *URL) { + xmlURIPtr uri; + /* + * Clear any existing data from the context + */ + if (ctxt->protocol != NULL) { + xmlFree(ctxt->protocol); + ctxt->protocol = NULL; + } + if (ctxt->hostname != NULL) { + xmlFree(ctxt->hostname); + ctxt->hostname = NULL; + } + if (ctxt->path != NULL) { + xmlFree(ctxt->path); + ctxt->path = NULL; + } + if (ctxt->query != NULL) { + xmlFree(ctxt->query); + ctxt->query = NULL; + } + if (URL == NULL) return; + + uri = xmlParseURIRaw(URL, 1); + if (uri == NULL) + return; + + if ((uri->scheme == NULL) || (uri->server == NULL)) { + xmlFreeURI(uri); + return; + } + + ctxt->protocol = xmlMemStrdup(uri->scheme); + ctxt->hostname = xmlMemStrdup(uri->server); + if (uri->path != NULL) + ctxt->path = xmlMemStrdup(uri->path); + else + ctxt->path = xmlMemStrdup("/"); + if (uri->query != NULL) + ctxt->query = xmlMemStrdup(uri->query); + if (uri->port != 0) + ctxt->port = uri->port; + + xmlFreeURI(uri); +} + +/** + * xmlNanoHTTPScanProxy: + * @URL: The proxy URL used to initialize the proxy context + * + * (Re)Initialize the HTTP Proxy context by parsing the URL and finding + * the protocol host port it indicates. + * Should be like http://myproxy/ or http://myproxy:3128/ + * A NULL URL cleans up proxy informations. + */ + +void +xmlNanoHTTPScanProxy(const char *URL) { + xmlURIPtr uri; + + if (proxy != NULL) { + xmlFree(proxy); + proxy = NULL; + } + proxyPort = 0; + +#ifdef DEBUG_HTTP + if (URL == NULL) + xmlGenericError(xmlGenericErrorContext, + "Removing HTTP proxy info\n"); + else + xmlGenericError(xmlGenericErrorContext, + "Using HTTP proxy %s\n", URL); +#endif + if (URL == NULL) return; + + uri = xmlParseURIRaw(URL, 1); + if ((uri == NULL) || (uri->scheme == NULL) || + (strcmp(uri->scheme, "http")) || (uri->server == NULL)) { + __xmlIOErr(XML_FROM_HTTP, XML_HTTP_URL_SYNTAX, "Syntax Error\n"); + if (uri != NULL) + xmlFreeURI(uri); + return; + } + + proxy = xmlMemStrdup(uri->server); + if (uri->port != 0) + proxyPort = uri->port; + + xmlFreeURI(uri); +} + +/** + * xmlNanoHTTPNewCtxt: + * @URL: The URL used to initialize the context + * + * Allocate and initialize a new HTTP context. + * + * Returns an HTTP context or NULL in case of error. + */ + +static xmlNanoHTTPCtxtPtr +xmlNanoHTTPNewCtxt(const char *URL) { + xmlNanoHTTPCtxtPtr ret; + + ret = (xmlNanoHTTPCtxtPtr) xmlMalloc(sizeof(xmlNanoHTTPCtxt)); + if (ret == NULL) { + xmlHTTPErrMemory("allocating context"); + return(NULL); + } + + memset(ret, 0, sizeof(xmlNanoHTTPCtxt)); + ret->port = 80; + ret->returnValue = 0; + ret->fd = -1; + ret->ContentLength = -1; + + xmlNanoHTTPScanURL(ret, URL); + + return(ret); +} + +/** + * xmlNanoHTTPFreeCtxt: + * @ctxt: an HTTP context + * + * Frees the context after closing the connection. + */ + +static void +xmlNanoHTTPFreeCtxt(xmlNanoHTTPCtxtPtr ctxt) { + if (ctxt == NULL) return; + if (ctxt->hostname != NULL) xmlFree(ctxt->hostname); + if (ctxt->protocol != NULL) xmlFree(ctxt->protocol); + if (ctxt->path != NULL) xmlFree(ctxt->path); + if (ctxt->query != NULL) xmlFree(ctxt->query); + if (ctxt->out != NULL) xmlFree(ctxt->out); + if (ctxt->in != NULL) xmlFree(ctxt->in); + if (ctxt->contentType != NULL) xmlFree(ctxt->contentType); + if (ctxt->encoding != NULL) xmlFree(ctxt->encoding); + if (ctxt->mimeType != NULL) xmlFree(ctxt->mimeType); + if (ctxt->location != NULL) xmlFree(ctxt->location); + if (ctxt->authHeader != NULL) xmlFree(ctxt->authHeader); +#ifdef HAVE_ZLIB_H + if (ctxt->strm != NULL) { + inflateEnd(ctxt->strm); + xmlFree(ctxt->strm); + } +#endif + + ctxt->state = XML_NANO_HTTP_NONE; + if (ctxt->fd >= 0) closesocket(ctxt->fd); + ctxt->fd = -1; + xmlFree(ctxt); +} + +/** + * xmlNanoHTTPSend: + * @ctxt: an HTTP context + * + * Send the input needed to initiate the processing on the server side + * Returns number of bytes sent or -1 on error. + */ + +static int +xmlNanoHTTPSend(xmlNanoHTTPCtxtPtr ctxt, const char * xmt_ptr, int outlen) { + + int total_sent = 0; + + if ( (ctxt->state & XML_NANO_HTTP_WRITE) && (xmt_ptr != NULL ) ) { + while (total_sent < outlen) { + int nsent = send(ctxt->fd, xmt_ptr + total_sent, + outlen - total_sent, 0); + if (nsent>0) + total_sent += nsent; + else if ( ( nsent == -1 ) && +#if defined(EAGAIN) && EAGAIN != EWOULDBLOCK + ( socket_errno( ) != EAGAIN ) && +#endif + ( socket_errno( ) != EWOULDBLOCK ) ) { + __xmlIOErr(XML_FROM_HTTP, 0, "send failed\n"); + if ( total_sent == 0 ) + total_sent = -1; + break; + } + else { + /* + ** No data sent + ** Since non-blocking sockets are used, wait for + ** socket to be writable or default timeout prior + ** to retrying. + */ + + struct timeval tv; + fd_set wfd; + + tv.tv_sec = timeout; + tv.tv_usec = 0; + FD_ZERO( &wfd ); +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4018) +#endif + FD_SET( ctxt->fd, &wfd ); +#ifdef _MSC_VER +#pragma warning(pop) +#endif + (void)select( ctxt->fd + 1, NULL, &wfd, NULL, &tv ); + } + } + } + + return total_sent; +} + +/** + * xmlNanoHTTPRecv: + * @ctxt: an HTTP context + * + * Read information coming from the HTTP connection. + * This is a blocking call (but it blocks in select(), not read()). + * + * Returns the number of byte read or -1 in case of error. + */ + +static int +xmlNanoHTTPRecv(xmlNanoHTTPCtxtPtr ctxt) { + fd_set rfd; + struct timeval tv; + + + while (ctxt->state & XML_NANO_HTTP_READ) { + if (ctxt->in == NULL) { + ctxt->in = (char *) xmlMallocAtomic(65000 * sizeof(char)); + if (ctxt->in == NULL) { + xmlHTTPErrMemory("allocating input"); + ctxt->last = -1; + return(-1); + } + ctxt->inlen = 65000; + ctxt->inptr = ctxt->content = ctxt->inrptr = ctxt->in; + } + if (ctxt->inrptr > ctxt->in + XML_NANO_HTTP_CHUNK) { + int delta = ctxt->inrptr - ctxt->in; + int len = ctxt->inptr - ctxt->inrptr; + + memmove(ctxt->in, ctxt->inrptr, len); + ctxt->inrptr -= delta; + ctxt->content -= delta; + ctxt->inptr -= delta; + } + if ((ctxt->in + ctxt->inlen) < (ctxt->inptr + XML_NANO_HTTP_CHUNK)) { + int d_inptr = ctxt->inptr - ctxt->in; + int d_content = ctxt->content - ctxt->in; + int d_inrptr = ctxt->inrptr - ctxt->in; + char * tmp_ptr = ctxt->in; + + ctxt->inlen *= 2; + ctxt->in = (char *) xmlRealloc(tmp_ptr, ctxt->inlen); + if (ctxt->in == NULL) { + xmlHTTPErrMemory("allocating input buffer"); + xmlFree( tmp_ptr ); + ctxt->last = -1; + return(-1); + } + ctxt->inptr = ctxt->in + d_inptr; + ctxt->content = ctxt->in + d_content; + ctxt->inrptr = ctxt->in + d_inrptr; + } + ctxt->last = recv(ctxt->fd, ctxt->inptr, XML_NANO_HTTP_CHUNK, 0); + if (ctxt->last > 0) { + ctxt->inptr += ctxt->last; + return(ctxt->last); + } + if (ctxt->last == 0) { + return(0); + } + if (ctxt->last == -1) { + switch (socket_errno()) { + case EINPROGRESS: + case EWOULDBLOCK: +#if defined(EAGAIN) && EAGAIN != EWOULDBLOCK + case EAGAIN: +#endif + break; + + case ECONNRESET: + case ESHUTDOWN: + return ( 0 ); + + default: + __xmlIOErr(XML_FROM_HTTP, 0, "recv failed\n"); + return(-1); + } + } + + tv.tv_sec = timeout; + tv.tv_usec = 0; + FD_ZERO(&rfd); +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4018) +#endif + FD_SET(ctxt->fd, &rfd); +#ifdef _MSC_VER +#pragma warning(pop) +#endif + + if ( (select(ctxt->fd+1, &rfd, NULL, NULL, &tv)<1) +#if defined(EINTR) + && (errno != EINTR) +#endif + ) + return(0); + } + return(0); +} + +/** + * xmlNanoHTTPReadLine: + * @ctxt: an HTTP context + * + * Read one line in the HTTP server output, usually for extracting + * the HTTP protocol informations from the answer header. + * + * Returns a newly allocated string with a copy of the line, or NULL + * which indicate the end of the input. + */ + +static char * +xmlNanoHTTPReadLine(xmlNanoHTTPCtxtPtr ctxt) { + char buf[4096]; + char *bp = buf; + int rc; + + while (bp - buf < 4095) { + if (ctxt->inrptr == ctxt->inptr) { + if ( (rc = xmlNanoHTTPRecv(ctxt)) == 0) { + if (bp == buf) + return(NULL); + else + *bp = 0; + return(xmlMemStrdup(buf)); + } + else if ( rc == -1 ) { + return ( NULL ); + } + } + *bp = *ctxt->inrptr++; + if (*bp == '\n') { + *bp = 0; + return(xmlMemStrdup(buf)); + } + if (*bp != '\r') + bp++; + } + buf[4095] = 0; + return(xmlMemStrdup(buf)); +} + + +/** + * xmlNanoHTTPScanAnswer: + * @ctxt: an HTTP context + * @line: an HTTP header line + * + * Try to extract useful informations from the server answer. + * We currently parse and process: + * - The HTTP revision/ return code + * - The Content-Type, Mime-Type and charset used + * - The Location for redirect processing. + * + * Returns -1 in case of failure, the file descriptor number otherwise + */ + +static void +xmlNanoHTTPScanAnswer(xmlNanoHTTPCtxtPtr ctxt, const char *line) { + const char *cur = line; + + if (line == NULL) return; + + if (!strncmp(line, "HTTP/", 5)) { + int version = 0; + int ret = 0; + + cur += 5; + while ((*cur >= '0') && (*cur <= '9')) { + version *= 10; + version += *cur - '0'; + cur++; + } + if (*cur == '.') { + cur++; + if ((*cur >= '0') && (*cur <= '9')) { + version *= 10; + version += *cur - '0'; + cur++; + } + while ((*cur >= '0') && (*cur <= '9')) + cur++; + } else + version *= 10; + if ((*cur != ' ') && (*cur != '\t')) return; + while ((*cur == ' ') || (*cur == '\t')) cur++; + if ((*cur < '0') || (*cur > '9')) return; + while ((*cur >= '0') && (*cur <= '9')) { + ret *= 10; + ret += *cur - '0'; + cur++; + } + if ((*cur != 0) && (*cur != ' ') && (*cur != '\t')) return; + ctxt->returnValue = ret; + } else if (!xmlStrncasecmp(BAD_CAST line, BAD_CAST"Content-Type:", 13)) { + const xmlChar *charset, *last, *mime; + cur += 13; + while ((*cur == ' ') || (*cur == '\t')) cur++; + if (ctxt->contentType != NULL) + xmlFree(ctxt->contentType); + ctxt->contentType = xmlMemStrdup(cur); + mime = (const xmlChar *) cur; + last = mime; + while ((*last != 0) && (*last != ' ') && (*last != '\t') && + (*last != ';') && (*last != ',')) + last++; + if (ctxt->mimeType != NULL) + xmlFree(ctxt->mimeType); + ctxt->mimeType = (char *) xmlStrndup(mime, last - mime); + charset = xmlStrstr(BAD_CAST ctxt->contentType, BAD_CAST "charset="); + if (charset != NULL) { + charset += 8; + last = charset; + while ((*last != 0) && (*last != ' ') && (*last != '\t') && + (*last != ';') && (*last != ',')) + last++; + if (ctxt->encoding != NULL) + xmlFree(ctxt->encoding); + ctxt->encoding = (char *) xmlStrndup(charset, last - charset); + } + } else if (!xmlStrncasecmp(BAD_CAST line, BAD_CAST"ContentType:", 12)) { + const xmlChar *charset, *last, *mime; + cur += 12; + if (ctxt->contentType != NULL) return; + while ((*cur == ' ') || (*cur == '\t')) cur++; + ctxt->contentType = xmlMemStrdup(cur); + mime = (const xmlChar *) cur; + last = mime; + while ((*last != 0) && (*last != ' ') && (*last != '\t') && + (*last != ';') && (*last != ',')) + last++; + if (ctxt->mimeType != NULL) + xmlFree(ctxt->mimeType); + ctxt->mimeType = (char *) xmlStrndup(mime, last - mime); + charset = xmlStrstr(BAD_CAST ctxt->contentType, BAD_CAST "charset="); + if (charset != NULL) { + charset += 8; + last = charset; + while ((*last != 0) && (*last != ' ') && (*last != '\t') && + (*last != ';') && (*last != ',')) + last++; + if (ctxt->encoding != NULL) + xmlFree(ctxt->encoding); + ctxt->encoding = (char *) xmlStrndup(charset, last - charset); + } + } else if (!xmlStrncasecmp(BAD_CAST line, BAD_CAST"Location:", 9)) { + cur += 9; + while ((*cur == ' ') || (*cur == '\t')) cur++; + if (ctxt->location != NULL) + xmlFree(ctxt->location); + if (*cur == '/') { + xmlChar *tmp_http = xmlStrdup(BAD_CAST "http://"); + xmlChar *tmp_loc = + xmlStrcat(tmp_http, (const xmlChar *) ctxt->hostname); + ctxt->location = + (char *) xmlStrcat (tmp_loc, (const xmlChar *) cur); + } else { + ctxt->location = xmlMemStrdup(cur); + } + } else if (!xmlStrncasecmp(BAD_CAST line, BAD_CAST"WWW-Authenticate:", 17)) { + cur += 17; + while ((*cur == ' ') || (*cur == '\t')) cur++; + if (ctxt->authHeader != NULL) + xmlFree(ctxt->authHeader); + ctxt->authHeader = xmlMemStrdup(cur); + } else if (!xmlStrncasecmp(BAD_CAST line, BAD_CAST"Proxy-Authenticate:", 19)) { + cur += 19; + while ((*cur == ' ') || (*cur == '\t')) cur++; + if (ctxt->authHeader != NULL) + xmlFree(ctxt->authHeader); + ctxt->authHeader = xmlMemStrdup(cur); +#ifdef HAVE_ZLIB_H + } else if ( !xmlStrncasecmp( BAD_CAST line, BAD_CAST"Content-Encoding:", 17) ) { + cur += 17; + while ((*cur == ' ') || (*cur == '\t')) cur++; + if ( !xmlStrncasecmp( BAD_CAST cur, BAD_CAST"gzip", 4) ) { + ctxt->usesGzip = 1; + + ctxt->strm = xmlMalloc(sizeof(z_stream)); + + if (ctxt->strm != NULL) { + ctxt->strm->zalloc = Z_NULL; + ctxt->strm->zfree = Z_NULL; + ctxt->strm->opaque = Z_NULL; + ctxt->strm->avail_in = 0; + ctxt->strm->next_in = Z_NULL; + + inflateInit2( ctxt->strm, 31 ); + } + } +#endif + } else if ( !xmlStrncasecmp( BAD_CAST line, BAD_CAST"Content-Length:", 15) ) { + cur += 15; + ctxt->ContentLength = strtol( cur, NULL, 10 ); + } +} + +/** + * xmlNanoHTTPConnectAttempt: + * @addr: a socket address structure + * + * Attempt a connection to the given IP:port endpoint. It forces + * non-blocking semantic on the socket, and allow 60 seconds for + * the host to answer. + * + * Returns -1 in case of failure, the file descriptor number otherwise + */ + +static int +xmlNanoHTTPConnectAttempt(struct sockaddr *addr) +{ + fd_set wfd; +#ifdef _WINSOCKAPI_ + fd_set xfd; +#endif + struct timeval tv; + int status; + int addrlen; + SOCKET s; + +#ifdef SUPPORT_IP6 + if (addr->sa_family == AF_INET6) { + s = socket (PF_INET6, SOCK_STREAM, IPPROTO_TCP); + addrlen = sizeof (struct sockaddr_in6); + } + else +#endif + { + s = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP); + addrlen = sizeof (struct sockaddr_in); + } + if (s==-1) { +#ifdef DEBUG_HTTP + perror("socket"); +#endif + __xmlIOErr(XML_FROM_HTTP, 0, "socket failed\n"); + return(-1); + } + +#ifdef _WINSOCKAPI_ + { + u_long one = 1; + + status = ioctlsocket(s, FIONBIO, &one) == SOCKET_ERROR ? -1 : 0; + } +#else /* _WINSOCKAPI_ */ +#if defined(VMS) + { + int enable = 1; + status = ioctl(s, FIONBIO, &enable); + } +#else /* VMS */ +#if defined(__BEOS__) + { + bool noblock = true; + status = setsockopt(s, SOL_SOCKET, SO_NONBLOCK, &noblock, sizeof(noblock)); + } +#else /* __BEOS__ */ + if ((status = fcntl(s, F_GETFL, 0)) != -1) { +#ifdef O_NONBLOCK + status |= O_NONBLOCK; +#else /* O_NONBLOCK */ +#ifdef F_NDELAY + status |= F_NDELAY; +#endif /* F_NDELAY */ +#endif /* !O_NONBLOCK */ + status = fcntl(s, F_SETFL, status); + } + if (status < 0) { +#ifdef DEBUG_HTTP + perror("nonblocking"); +#endif + __xmlIOErr(XML_FROM_HTTP, 0, "error setting non-blocking IO\n"); + closesocket(s); + return(-1); + } +#endif /* !__BEOS__ */ +#endif /* !VMS */ +#endif /* !_WINSOCKAPI_ */ + + if (connect (s, addr, addrlen) == -1) { + switch (socket_errno()) { + case EINPROGRESS: + case EWOULDBLOCK: + break; + default: + __xmlIOErr(XML_FROM_HTTP, 0, "error connecting to HTTP server"); + closesocket(s); + return(-1); + } + } + + tv.tv_sec = timeout; + tv.tv_usec = 0; + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4018) +#endif + FD_ZERO(&wfd); + FD_SET(s, &wfd); + +#ifdef _WINSOCKAPI_ + FD_ZERO(&xfd); + FD_SET(s, &xfd); + + switch(select(s+1, NULL, &wfd, &xfd, &tv)) +#else + switch(select(s+1, NULL, &wfd, NULL, &tv)) +#endif +#ifdef _MSC_VER +#pragma warning(pop) +#endif + { + case 0: + /* Time out */ + __xmlIOErr(XML_FROM_HTTP, 0, "Connect attempt timed out"); + closesocket(s); + return(-1); + case -1: + /* Ermm.. ?? */ + __xmlIOErr(XML_FROM_HTTP, 0, "Connect failed"); + closesocket(s); + return(-1); + } + + if ( FD_ISSET(s, &wfd) +#ifdef _WINSOCKAPI_ + || FD_ISSET(s, &xfd) +#endif + ) { + XML_SOCKLEN_T len; + len = sizeof(status); +#ifdef SO_ERROR + if (getsockopt(s, SOL_SOCKET, SO_ERROR, (char*)&status, &len) < 0 ) { + /* Solaris error code */ + __xmlIOErr(XML_FROM_HTTP, 0, "getsockopt failed\n"); + return (-1); + } +#endif + if ( status ) { + __xmlIOErr(XML_FROM_HTTP, 0, "Error connecting to remote host"); + closesocket(s); + errno = status; + return (-1); + } + } else { + /* pbm */ + __xmlIOErr(XML_FROM_HTTP, 0, "select failed\n"); + closesocket(s); + return (-1); + } + + return(s); +} + +/** + * xmlNanoHTTPConnectHost: + * @host: the host name + * @port: the port number + * + * Attempt a connection to the given host:port endpoint. It tries + * the multiple IP provided by the DNS if available. + * + * Returns -1 in case of failure, the file descriptor number otherwise + */ + +static int +xmlNanoHTTPConnectHost(const char *host, int port) +{ + struct hostent *h; + struct sockaddr *addr = NULL; + struct in_addr ia; + struct sockaddr_in sockin; + +#ifdef SUPPORT_IP6 + struct in6_addr ia6; + struct sockaddr_in6 sockin6; +#endif + int i; + int s; + + memset (&sockin, 0, sizeof(sockin)); +#ifdef SUPPORT_IP6 + memset (&sockin6, 0, sizeof(sockin6)); +#endif + +#if !defined(HAVE_GETADDRINFO) && defined(SUPPORT_IP6) && defined(RES_USE_INET6) + if (have_ipv6 ()) + { + if (!(_res.options & RES_INIT)) + res_init(); + _res.options |= RES_USE_INET6; + } +#endif + +#if defined(HAVE_GETADDRINFO) && defined(SUPPORT_IP6) && !defined(_WIN32) + if (have_ipv6 ()) +#endif +#if defined(HAVE_GETADDRINFO) && (defined(SUPPORT_IP6) || defined(_WIN32)) + { + int status; + struct addrinfo hints, *res, *result; + + result = NULL; + memset (&hints, 0,sizeof(hints)); + hints.ai_socktype = SOCK_STREAM; + + status = getaddrinfo (host, NULL, &hints, &result); + if (status) { + __xmlIOErr(XML_FROM_HTTP, 0, "getaddrinfo failed\n"); + return (-1); + } + + for (res = result; res; res = res->ai_next) { + if (res->ai_family == AF_INET) { + if (res->ai_addrlen > sizeof(sockin)) { + __xmlIOErr(XML_FROM_HTTP, 0, "address size mismatch\n"); + freeaddrinfo (result); + return (-1); + } + memcpy (&sockin, res->ai_addr, res->ai_addrlen); + sockin.sin_port = htons (port); + addr = (struct sockaddr *)&sockin; +#ifdef SUPPORT_IP6 + } else if (have_ipv6 () && (res->ai_family == AF_INET6)) { + if (res->ai_addrlen > sizeof(sockin6)) { + __xmlIOErr(XML_FROM_HTTP, 0, "address size mismatch\n"); + freeaddrinfo (result); + return (-1); + } + memcpy (&sockin6, res->ai_addr, res->ai_addrlen); + sockin6.sin6_port = htons (port); + addr = (struct sockaddr *)&sockin6; +#endif + } else + continue; /* for */ + + s = xmlNanoHTTPConnectAttempt (addr); + if (s != -1) { + freeaddrinfo (result); + return (s); + } + } + + if (result) + freeaddrinfo (result); + } +#endif +#if defined(HAVE_GETADDRINFO) && defined(SUPPORT_IP6) && !defined(_WIN32) + else +#endif +#if !defined(HAVE_GETADDRINFO) || !defined(_WIN32) + { + h = gethostbyname (host); + if (h == NULL) { + +/* + * Okay, I got fed up by the non-portability of this error message + * extraction code. it work on Linux, if it work on your platform + * and one want to enable it, send me the defined(foobar) needed + */ +#if defined(HAVE_NETDB_H) && defined(HOST_NOT_FOUND) && defined(linux) + const char *h_err_txt = ""; + + switch (h_errno) { + case HOST_NOT_FOUND: + h_err_txt = "Authoritive host not found"; + break; + + case TRY_AGAIN: + h_err_txt = + "Non-authoritive host not found or server failure."; + break; + + case NO_RECOVERY: + h_err_txt = + "Non-recoverable errors: FORMERR, REFUSED, or NOTIMP."; + break; + + case NO_ADDRESS: + h_err_txt = + "Valid name, no data record of requested type."; + break; + + default: + h_err_txt = "No error text defined."; + break; + } + __xmlIOErr(XML_FROM_HTTP, 0, h_err_txt); +#else + __xmlIOErr(XML_FROM_HTTP, 0, "Failed to resolve host"); +#endif + return (-1); + } + + for (i = 0; h->h_addr_list[i]; i++) { + if (h->h_addrtype == AF_INET) { + /* A records (IPv4) */ + if ((unsigned int) h->h_length > sizeof(ia)) { + __xmlIOErr(XML_FROM_HTTP, 0, "address size mismatch\n"); + return (-1); + } + memcpy (&ia, h->h_addr_list[i], h->h_length); + sockin.sin_family = h->h_addrtype; + sockin.sin_addr = ia; + sockin.sin_port = (u_short)htons ((unsigned short)port); + addr = (struct sockaddr *) &sockin; +#ifdef SUPPORT_IP6 + } else if (have_ipv6 () && (h->h_addrtype == AF_INET6)) { + /* AAAA records (IPv6) */ + if ((unsigned int) h->h_length > sizeof(ia6)) { + __xmlIOErr(XML_FROM_HTTP, 0, "address size mismatch\n"); + return (-1); + } + memcpy (&ia6, h->h_addr_list[i], h->h_length); + sockin6.sin6_family = h->h_addrtype; + sockin6.sin6_addr = ia6; + sockin6.sin6_port = htons (port); + addr = (struct sockaddr *) &sockin6; +#endif + } else + break; /* for */ + + s = xmlNanoHTTPConnectAttempt (addr); + if (s != -1) + return (s); + } + } +#endif + +#ifdef DEBUG_HTTP + xmlGenericError(xmlGenericErrorContext, + "xmlNanoHTTPConnectHost: unable to connect to '%s'.\n", + host); +#endif + return (-1); +} + + +/** + * xmlNanoHTTPOpen: + * @URL: The URL to load + * @contentType: if available the Content-Type information will be + * returned at that location + * + * This function try to open a connection to the indicated resource + * via HTTP GET. + * + * Returns NULL in case of failure, otherwise a request handler. + * The contentType, if provided must be freed by the caller + */ + +void* +xmlNanoHTTPOpen(const char *URL, char **contentType) { + if (contentType != NULL) *contentType = NULL; + return(xmlNanoHTTPMethod(URL, NULL, NULL, contentType, NULL, 0)); +} + +/** + * xmlNanoHTTPOpenRedir: + * @URL: The URL to load + * @contentType: if available the Content-Type information will be + * returned at that location + * @redir: if available the redirected URL will be returned + * + * This function try to open a connection to the indicated resource + * via HTTP GET. + * + * Returns NULL in case of failure, otherwise a request handler. + * The contentType, if provided must be freed by the caller + */ + +void* +xmlNanoHTTPOpenRedir(const char *URL, char **contentType, char **redir) { + if (contentType != NULL) *contentType = NULL; + if (redir != NULL) *redir = NULL; + return(xmlNanoHTTPMethodRedir(URL, NULL, NULL, contentType, redir, NULL,0)); +} + +/** + * xmlNanoHTTPRead: + * @ctx: the HTTP context + * @dest: a buffer + * @len: the buffer length + * + * This function tries to read @len bytes from the existing HTTP connection + * and saves them in @dest. This is a blocking call. + * + * Returns the number of byte read. 0 is an indication of an end of connection. + * -1 indicates a parameter error. + */ +int +xmlNanoHTTPRead(void *ctx, void *dest, int len) { + xmlNanoHTTPCtxtPtr ctxt = (xmlNanoHTTPCtxtPtr) ctx; +#ifdef HAVE_ZLIB_H + int bytes_read = 0; + int orig_avail_in; + int z_ret; +#endif + + if (ctx == NULL) return(-1); + if (dest == NULL) return(-1); + if (len <= 0) return(0); + +#ifdef HAVE_ZLIB_H + if (ctxt->usesGzip == 1) { + if (ctxt->strm == NULL) return(0); + + ctxt->strm->next_out = dest; + ctxt->strm->avail_out = len; + + do { + orig_avail_in = ctxt->strm->avail_in = ctxt->inptr - ctxt->inrptr - bytes_read; + ctxt->strm->next_in = BAD_CAST (ctxt->inrptr + bytes_read); + + z_ret = inflate(ctxt->strm, Z_NO_FLUSH); + bytes_read += orig_avail_in - ctxt->strm->avail_in; + + if (z_ret != Z_OK) break; + } while (ctxt->strm->avail_out > 0 && xmlNanoHTTPRecv(ctxt) > 0); + + ctxt->inrptr += bytes_read; + return(len - ctxt->strm->avail_out); + } +#endif + + while (ctxt->inptr - ctxt->inrptr < len) { + if (xmlNanoHTTPRecv(ctxt) <= 0) break; + } + if (ctxt->inptr - ctxt->inrptr < len) + len = ctxt->inptr - ctxt->inrptr; + memcpy(dest, ctxt->inrptr, len); + ctxt->inrptr += len; + return(len); +} + +/** + * xmlNanoHTTPClose: + * @ctx: the HTTP context + * + * This function closes an HTTP context, it ends up the connection and + * free all data related to it. + */ +void +xmlNanoHTTPClose(void *ctx) { + xmlNanoHTTPCtxtPtr ctxt = (xmlNanoHTTPCtxtPtr) ctx; + + if (ctx == NULL) return; + + xmlNanoHTTPFreeCtxt(ctxt); +} + +/** + * xmlNanoHTTPMethodRedir: + * @URL: The URL to load + * @method: the HTTP method to use + * @input: the input string if any + * @contentType: the Content-Type information IN and OUT + * @redir: the redirected URL OUT + * @headers: the extra headers + * @ilen: input length + * + * This function try to open a connection to the indicated resource + * via HTTP using the given @method, adding the given extra headers + * and the input buffer for the request content. + * + * Returns NULL in case of failure, otherwise a request handler. + * The contentType, or redir, if provided must be freed by the caller + */ + +void* +xmlNanoHTTPMethodRedir(const char *URL, const char *method, const char *input, + char **contentType, char **redir, + const char *headers, int ilen ) { + xmlNanoHTTPCtxtPtr ctxt; + char *bp, *p; + int blen, ret; + int head; + int nbRedirects = 0; + char *redirURL = NULL; +#ifdef DEBUG_HTTP + int xmt_bytes; +#endif + + if (URL == NULL) return(NULL); + if (method == NULL) method = "GET"; + xmlNanoHTTPInit(); + +retry: + if (redirURL == NULL) + ctxt = xmlNanoHTTPNewCtxt(URL); + else { + ctxt = xmlNanoHTTPNewCtxt(redirURL); + ctxt->location = xmlMemStrdup(redirURL); + } + + if ( ctxt == NULL ) { + return ( NULL ); + } + + if ((ctxt->protocol == NULL) || (strcmp(ctxt->protocol, "http"))) { + __xmlIOErr(XML_FROM_HTTP, XML_HTTP_URL_SYNTAX, "Not a valid HTTP URI"); + xmlNanoHTTPFreeCtxt(ctxt); + if (redirURL != NULL) xmlFree(redirURL); + return(NULL); + } + if (ctxt->hostname == NULL) { + __xmlIOErr(XML_FROM_HTTP, XML_HTTP_UNKNOWN_HOST, + "Failed to identify host in URI"); + xmlNanoHTTPFreeCtxt(ctxt); + if (redirURL != NULL) xmlFree(redirURL); + return(NULL); + } + if (proxy) { + blen = strlen(ctxt->hostname) * 2 + 16; + ret = xmlNanoHTTPConnectHost(proxy, proxyPort); + } + else { + blen = strlen(ctxt->hostname); + ret = xmlNanoHTTPConnectHost(ctxt->hostname, ctxt->port); + } + if (ret < 0) { + xmlNanoHTTPFreeCtxt(ctxt); + if (redirURL != NULL) xmlFree(redirURL); + return(NULL); + } + ctxt->fd = ret; + + if (input == NULL) + ilen = 0; + else + blen += 36; + + if (headers != NULL) + blen += strlen(headers) + 2; + if (contentType && *contentType) + blen += strlen(*contentType) + 16; + if (ctxt->query != NULL) + blen += strlen(ctxt->query) + 1; + blen += strlen(method) + strlen(ctxt->path) + 24; +#ifdef HAVE_ZLIB_H + blen += 23; +#endif + bp = (char*)xmlMallocAtomic(blen); + if ( bp == NULL ) { + xmlNanoHTTPFreeCtxt( ctxt ); + xmlHTTPErrMemory("allocating header buffer"); + return ( NULL ); + } + + p = bp; + + if (proxy) { + if (ctxt->port != 80) { + p += snprintf( p, blen - (p - bp), "%s http://%s:%d%s", + method, ctxt->hostname, + ctxt->port, ctxt->path ); + } + else + p += snprintf( p, blen - (p - bp), "%s http://%s%s", method, + ctxt->hostname, ctxt->path); + } + else + p += snprintf( p, blen - (p - bp), "%s %s", method, ctxt->path); + + if (ctxt->query != NULL) + p += snprintf( p, blen - (p - bp), "?%s", ctxt->query); + + p += snprintf( p, blen - (p - bp), " HTTP/1.0\r\nHost: %s\r\n", + ctxt->hostname); + +#ifdef HAVE_ZLIB_H + p += snprintf(p, blen - (p - bp), "Accept-Encoding: gzip\r\n"); +#endif + + if (contentType != NULL && *contentType) + p += snprintf(p, blen - (p - bp), "Content-Type: %s\r\n", *contentType); + + if (headers != NULL) + p += snprintf( p, blen - (p - bp), "%s", headers ); + + if (input != NULL) + snprintf(p, blen - (p - bp), "Content-Length: %d\r\n\r\n", ilen ); + else + snprintf(p, blen - (p - bp), "\r\n"); + +#ifdef DEBUG_HTTP + xmlGenericError(xmlGenericErrorContext, + "-> %s%s", proxy? "(Proxy) " : "", bp); + if ((blen -= strlen(bp)+1) < 0) + xmlGenericError(xmlGenericErrorContext, + "ERROR: overflowed buffer by %d bytes\n", -blen); +#endif + ctxt->outptr = ctxt->out = bp; + ctxt->state = XML_NANO_HTTP_WRITE; + blen = strlen( ctxt->out ); +#ifdef DEBUG_HTTP + xmt_bytes = xmlNanoHTTPSend(ctxt, ctxt->out, blen ); + if ( xmt_bytes != blen ) + xmlGenericError( xmlGenericErrorContext, + "xmlNanoHTTPMethodRedir: Only %d of %d %s %s\n", + xmt_bytes, blen, + "bytes of HTTP headers sent to host", + ctxt->hostname ); +#else + xmlNanoHTTPSend(ctxt, ctxt->out, blen ); +#endif + + if ( input != NULL ) { +#ifdef DEBUG_HTTP + xmt_bytes = xmlNanoHTTPSend( ctxt, input, ilen ); + + if ( xmt_bytes != ilen ) + xmlGenericError( xmlGenericErrorContext, + "xmlNanoHTTPMethodRedir: Only %d of %d %s %s\n", + xmt_bytes, ilen, + "bytes of HTTP content sent to host", + ctxt->hostname ); +#else + xmlNanoHTTPSend( ctxt, input, ilen ); +#endif + } + + ctxt->state = XML_NANO_HTTP_READ; + head = 1; + + while ((p = xmlNanoHTTPReadLine(ctxt)) != NULL) { + if (head && (*p == 0)) { + head = 0; + ctxt->content = ctxt->inrptr; + xmlFree(p); + break; + } + xmlNanoHTTPScanAnswer(ctxt, p); + +#ifdef DEBUG_HTTP + xmlGenericError(xmlGenericErrorContext, "<- %s\n", p); +#endif + xmlFree(p); + } + + if ((ctxt->location != NULL) && (ctxt->returnValue >= 300) && + (ctxt->returnValue < 400)) { +#ifdef DEBUG_HTTP + xmlGenericError(xmlGenericErrorContext, + "\nRedirect to: %s\n", ctxt->location); +#endif + while ( xmlNanoHTTPRecv(ctxt) > 0 ) ; + if (nbRedirects < XML_NANO_HTTP_MAX_REDIR) { + nbRedirects++; + if (redirURL != NULL) + xmlFree(redirURL); + redirURL = xmlMemStrdup(ctxt->location); + xmlNanoHTTPFreeCtxt(ctxt); + goto retry; + } + xmlNanoHTTPFreeCtxt(ctxt); + if (redirURL != NULL) xmlFree(redirURL); +#ifdef DEBUG_HTTP + xmlGenericError(xmlGenericErrorContext, + "xmlNanoHTTPMethodRedir: Too many redirects, aborting ...\n"); +#endif + return(NULL); + } + + if (contentType != NULL) { + if (ctxt->contentType != NULL) + *contentType = xmlMemStrdup(ctxt->contentType); + else + *contentType = NULL; + } + + if ((redir != NULL) && (redirURL != NULL)) { + *redir = redirURL; + } else { + if (redirURL != NULL) + xmlFree(redirURL); + if (redir != NULL) + *redir = NULL; + } + +#ifdef DEBUG_HTTP + if (ctxt->contentType != NULL) + xmlGenericError(xmlGenericErrorContext, + "\nCode %d, content-type '%s'\n\n", + ctxt->returnValue, ctxt->contentType); + else + xmlGenericError(xmlGenericErrorContext, + "\nCode %d, no content-type\n\n", + ctxt->returnValue); +#endif + + return((void *) ctxt); +} + +/** + * xmlNanoHTTPMethod: + * @URL: The URL to load + * @method: the HTTP method to use + * @input: the input string if any + * @contentType: the Content-Type information IN and OUT + * @headers: the extra headers + * @ilen: input length + * + * This function try to open a connection to the indicated resource + * via HTTP using the given @method, adding the given extra headers + * and the input buffer for the request content. + * + * Returns NULL in case of failure, otherwise a request handler. + * The contentType, if provided must be freed by the caller + */ + +void* +xmlNanoHTTPMethod(const char *URL, const char *method, const char *input, + char **contentType, const char *headers, int ilen) { + return(xmlNanoHTTPMethodRedir(URL, method, input, contentType, + NULL, headers, ilen)); +} + +/** + * xmlNanoHTTPFetch: + * @URL: The URL to load + * @filename: the filename where the content should be saved + * @contentType: if available the Content-Type information will be + * returned at that location + * + * This function try to fetch the indicated resource via HTTP GET + * and save it's content in the file. + * + * Returns -1 in case of failure, 0 incase of success. The contentType, + * if provided must be freed by the caller + */ +int +xmlNanoHTTPFetch(const char *URL, const char *filename, char **contentType) { + void *ctxt = NULL; + char *buf = NULL; + int fd; + int len; + + if (filename == NULL) return(-1); + ctxt = xmlNanoHTTPOpen(URL, contentType); + if (ctxt == NULL) return(-1); + + if (!strcmp(filename, "-")) + fd = 0; + else { + fd = open(filename, O_CREAT | O_WRONLY, 00644); + if (fd < 0) { + xmlNanoHTTPClose(ctxt); + if ((contentType != NULL) && (*contentType != NULL)) { + xmlFree(*contentType); + *contentType = NULL; + } + return(-1); + } + } + + xmlNanoHTTPFetchContent( ctxt, &buf, &len ); + if ( len > 0 ) { + write(fd, buf, len); + } + + xmlNanoHTTPClose(ctxt); + close(fd); + return(0); +} + +#ifdef LIBXML_OUTPUT_ENABLED +/** + * xmlNanoHTTPSave: + * @ctxt: the HTTP context + * @filename: the filename where the content should be saved + * + * This function saves the output of the HTTP transaction to a file + * It closes and free the context at the end + * + * Returns -1 in case of failure, 0 incase of success. + */ +int +xmlNanoHTTPSave(void *ctxt, const char *filename) { + char *buf = NULL; + int fd; + int len; + + if ((ctxt == NULL) || (filename == NULL)) return(-1); + + if (!strcmp(filename, "-")) + fd = 0; + else { + fd = open(filename, O_CREAT | O_WRONLY); + if (fd < 0) { + xmlNanoHTTPClose(ctxt); + return(-1); + } + } + + xmlNanoHTTPFetchContent( ctxt, &buf, &len ); + if ( len > 0 ) { + write(fd, buf, len); + } + + xmlNanoHTTPClose(ctxt); + close(fd); + return(0); +} +#endif /* LIBXML_OUTPUT_ENABLED */ + +/** + * xmlNanoHTTPReturnCode: + * @ctx: the HTTP context + * + * Get the latest HTTP return code received + * + * Returns the HTTP return code for the request. + */ +int +xmlNanoHTTPReturnCode(void *ctx) { + xmlNanoHTTPCtxtPtr ctxt = (xmlNanoHTTPCtxtPtr) ctx; + + if (ctxt == NULL) return(-1); + + return(ctxt->returnValue); +} + +/** + * xmlNanoHTTPAuthHeader: + * @ctx: the HTTP context + * + * Get the authentication header of an HTTP context + * + * Returns the stashed value of the WWW-Authenticate or Proxy-Authenticate + * header. + */ +const char * +xmlNanoHTTPAuthHeader(void *ctx) { + xmlNanoHTTPCtxtPtr ctxt = (xmlNanoHTTPCtxtPtr) ctx; + + if (ctxt == NULL) return(NULL); + + return(ctxt->authHeader); +} + +/** + * xmlNanoHTTPContentLength: + * @ctx: the HTTP context + * + * Provides the specified content length from the HTTP header. + * + * Return the specified content length from the HTTP header. Note that + * a value of -1 indicates that the content length element was not included in + * the response header. + */ +int +xmlNanoHTTPContentLength( void * ctx ) { + xmlNanoHTTPCtxtPtr ctxt = (xmlNanoHTTPCtxtPtr)ctx; + + return ( ( ctxt == NULL ) ? -1 : ctxt->ContentLength ); +} + +/** + * xmlNanoHTTPRedir: + * @ctx: the HTTP context + * + * Provides the specified redirection URL if available from the HTTP header. + * + * Return the specified redirection URL or NULL if not redirected. + */ +const char * +xmlNanoHTTPRedir( void * ctx ) { + xmlNanoHTTPCtxtPtr ctxt = (xmlNanoHTTPCtxtPtr)ctx; + + return ( ( ctxt == NULL ) ? NULL : ctxt->location ); +} + +/** + * xmlNanoHTTPEncoding: + * @ctx: the HTTP context + * + * Provides the specified encoding if specified in the HTTP headers. + * + * Return the specified encoding or NULL if not available + */ +const char * +xmlNanoHTTPEncoding( void * ctx ) { + xmlNanoHTTPCtxtPtr ctxt = (xmlNanoHTTPCtxtPtr)ctx; + + return ( ( ctxt == NULL ) ? NULL : ctxt->encoding ); +} + +/** + * xmlNanoHTTPMimeType: + * @ctx: the HTTP context + * + * Provides the specified Mime-Type if specified in the HTTP headers. + * + * Return the specified Mime-Type or NULL if not available + */ +const char * +xmlNanoHTTPMimeType( void * ctx ) { + xmlNanoHTTPCtxtPtr ctxt = (xmlNanoHTTPCtxtPtr)ctx; + + return ( ( ctxt == NULL ) ? NULL : ctxt->mimeType ); +} + +/** + * xmlNanoHTTPFetchContent: + * @ctx: the HTTP context + * @ptr: pointer to set to the content buffer. + * @len: integer pointer to hold the length of the content + * + * Check if all the content was read + * + * Returns 0 if all the content was read and available, returns + * -1 if received content length was less than specified or an error + * occurred. + */ +static int +xmlNanoHTTPFetchContent( void * ctx, char ** ptr, int * len ) { + xmlNanoHTTPCtxtPtr ctxt = (xmlNanoHTTPCtxtPtr)ctx; + + int rc = 0; + int cur_lgth; + int rcvd_lgth; + int dummy_int; + char * dummy_ptr = NULL; + + /* Dummy up return input parameters if not provided */ + + if ( len == NULL ) + len = &dummy_int; + + if ( ptr == NULL ) + ptr = &dummy_ptr; + + /* But can't work without the context pointer */ + + if ( ( ctxt == NULL ) || ( ctxt->content == NULL ) ) { + *len = 0; + *ptr = NULL; + return ( -1 ); + } + + rcvd_lgth = ctxt->inptr - ctxt->content; + + while ( (cur_lgth = xmlNanoHTTPRecv( ctxt )) > 0 ) { + + rcvd_lgth += cur_lgth; + if ( (ctxt->ContentLength > 0) && (rcvd_lgth >= ctxt->ContentLength) ) + break; + } + + *ptr = ctxt->content; + *len = rcvd_lgth; + + if ( ( ctxt->ContentLength > 0 ) && ( rcvd_lgth < ctxt->ContentLength ) ) + rc = -1; + else if ( rcvd_lgth == 0 ) + rc = -1; + + return ( rc ); +} + +#ifdef STANDALONE +int main(int argc, char **argv) { + char *contentType = NULL; + + if (argv[1] != NULL) { + if (argv[2] != NULL) + xmlNanoHTTPFetch(argv[1], argv[2], &contentType); + else + xmlNanoHTTPFetch(argv[1], "-", &contentType); + if (contentType != NULL) xmlFree(contentType); + } else { + xmlGenericError(xmlGenericErrorContext, + "%s: minimal HTTP GET implementation\n", argv[0]); + xmlGenericError(xmlGenericErrorContext, + "\tusage %s [ URL [ filename ] ]\n", argv[0]); + } + xmlNanoHTTPCleanup(); + xmlMemoryDump(); + return(0); +} +#endif /* STANDALONE */ +#else /* !LIBXML_HTTP_ENABLED */ +#ifdef STANDALONE +#include +int main(int argc, char **argv) { + xmlGenericError(xmlGenericErrorContext, + "%s : HTTP support not compiled in\n", argv[0]); + return(0); +} +#endif /* STANDALONE */ +#endif /* LIBXML_HTTP_ENABLED */ +#define bottom_nanohttp +#include "elfgcchack.h" diff --git a/gettext-tools/gnulib-lib/libxml/nanohttp.in.h b/gettext-tools/gnulib-lib/libxml/nanohttp.in.h new file mode 100644 index 0000000..1d8ac24 --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/nanohttp.in.h @@ -0,0 +1,81 @@ +/* + * Summary: minimal HTTP implementation + * Description: minimal HTTP implementation allowing to fetch resources + * like external subset. + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + +#ifndef __NANO_HTTP_H__ +#define __NANO_HTTP_H__ + +#include + +#ifdef LIBXML_HTTP_ENABLED + +#ifdef __cplusplus +extern "C" { +#endif +XMLPUBFUN void XMLCALL + xmlNanoHTTPInit (void); +XMLPUBFUN void XMLCALL + xmlNanoHTTPCleanup (void); +XMLPUBFUN void XMLCALL + xmlNanoHTTPScanProxy (const char *URL); +XMLPUBFUN int XMLCALL + xmlNanoHTTPFetch (const char *URL, + const char *filename, + char **contentType); +XMLPUBFUN void * XMLCALL + xmlNanoHTTPMethod (const char *URL, + const char *method, + const char *input, + char **contentType, + const char *headers, + int ilen); +XMLPUBFUN void * XMLCALL + xmlNanoHTTPMethodRedir (const char *URL, + const char *method, + const char *input, + char **contentType, + char **redir, + const char *headers, + int ilen); +XMLPUBFUN void * XMLCALL + xmlNanoHTTPOpen (const char *URL, + char **contentType); +XMLPUBFUN void * XMLCALL + xmlNanoHTTPOpenRedir (const char *URL, + char **contentType, + char **redir); +XMLPUBFUN int XMLCALL + xmlNanoHTTPReturnCode (void *ctx); +XMLPUBFUN const char * XMLCALL + xmlNanoHTTPAuthHeader (void *ctx); +XMLPUBFUN const char * XMLCALL + xmlNanoHTTPRedir (void *ctx); +XMLPUBFUN int XMLCALL + xmlNanoHTTPContentLength( void * ctx ); +XMLPUBFUN const char * XMLCALL + xmlNanoHTTPEncoding (void *ctx); +XMLPUBFUN const char * XMLCALL + xmlNanoHTTPMimeType (void *ctx); +XMLPUBFUN int XMLCALL + xmlNanoHTTPRead (void *ctx, + void *dest, + int len); +#ifdef LIBXML_OUTPUT_ENABLED +XMLPUBFUN int XMLCALL + xmlNanoHTTPSave (void *ctxt, + const char *filename); +#endif /* LIBXML_OUTPUT_ENABLED */ +XMLPUBFUN void XMLCALL + xmlNanoHTTPClose (void *ctx); +#ifdef __cplusplus +} +#endif + +#endif /* LIBXML_HTTP_ENABLED */ +#endif /* __NANO_HTTP_H__ */ diff --git a/gettext-tools/gnulib-lib/libxml/parser.c b/gettext-tools/gnulib-lib/libxml/parser.c new file mode 100644 index 0000000..bd44585 --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/parser.c @@ -0,0 +1,13614 @@ +/* + * parser.c : an XML 1.0 parser, namespaces and validity support are mostly + * implemented on top of the SAX interfaces + * + * References: + * The XML specification: + * http://www.w3.org/TR/REC-xml + * Original 1.0 version: + * http://www.w3.org/TR/1998/REC-xml-19980210 + * XML second edition working draft + * http://www.w3.org/TR/2000/WD-xml-2e-20000814 + * + * Okay this is a big file, the parser core is around 7000 lines, then it + * is followed by the progressive parser top routines, then the various + * high level APIs to call the parser and a few miscellaneous functions. + * A number of helper functions and deprecated ones have been moved to + * parserInternals.c to reduce this file size. + * As much as possible the functions are associated with their relative + * production in the XML specification. A few productions defining the + * different ranges of character are actually implanted either in + * parserInternals.h or parserInternals.c + * The DOM tree build is realized from the default SAX callbacks in + * the module SAX.c. + * The routines doing the validation checks are in valid.c and called either + * from the SAX callbacks or as standalone functions using a preparsed + * document. + * + * See Copyright for the status of this software. + * + * daniel@veillard.com + */ + +#define IN_LIBXML +#include "libxml.h" + +#if defined(WIN32) && !defined (__CYGWIN__) +#define XML_DIR_SEP '\\' +#else +#define XML_DIR_SEP '/' +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef LIBXML_CATALOG_ENABLED +#include +#endif +#ifdef LIBXML_SCHEMAS_ENABLED +#include +#include +#endif +#ifdef HAVE_CTYPE_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_SYS_STAT_H +#include +#endif +#ifdef HAVE_FCNTL_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_ZLIB_H +#include +#endif + +/** + * xmlParserMaxDepth: + * + * arbitrary depth limit for the XML documents that we allow to + * process. This is not a limitation of the parser but a safety + * boundary feature. + */ +unsigned int xmlParserMaxDepth = 1024; + +#define SAX2 1 + +#define XML_PARSER_BIG_BUFFER_SIZE 300 +#define XML_PARSER_BUFFER_SIZE 100 + +#define SAX_COMPAT_MODE BAD_CAST "SAX compatibility mode document" + +/* + * List of XML prefixed PI allowed by W3C specs + */ + +static const char *xmlW3CPIs[] = { + "xml-stylesheet", + NULL +}; + + +/* DEPR void xmlParserHandleReference(xmlParserCtxtPtr ctxt); */ +xmlEntityPtr xmlParseStringPEReference(xmlParserCtxtPtr ctxt, + const xmlChar **str); + +static xmlParserErrors +xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt, + xmlSAXHandlerPtr sax, + void *user_data, int depth, const xmlChar *URL, + const xmlChar *ID, xmlNodePtr *list); + +#ifdef LIBXML_LEGACY_ENABLED +static void +xmlAddEntityReference(xmlEntityPtr ent, xmlNodePtr firstNode, + xmlNodePtr lastNode); +#endif /* LIBXML_LEGACY_ENABLED */ + +static xmlParserErrors +xmlParseBalancedChunkMemoryInternal(xmlParserCtxtPtr oldctxt, + const xmlChar *string, void *user_data, xmlNodePtr *lst); + +/************************************************************************ + * * + * Some factorized error routines * + * * + ************************************************************************/ + +/** + * xmlErrAttributeDup: + * @ctxt: an XML parser context + * @prefix: the attribute prefix + * @localname: the attribute localname + * + * Handle a redefinition of attribute error + */ +static void +xmlErrAttributeDup(xmlParserCtxtPtr ctxt, const xmlChar * prefix, + const xmlChar * localname) +{ + if ((ctxt != NULL) && (ctxt->disableSAX != 0) && + (ctxt->instate == XML_PARSER_EOF)) + return; + if (ctxt != NULL) + ctxt->errNo = XML_ERR_ATTRIBUTE_REDEFINED; + if (prefix == NULL) + __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, + ctxt->errNo, XML_ERR_FATAL, NULL, 0, + (const char *) localname, NULL, NULL, 0, 0, + "Attribute %s redefined\n", localname); + else + __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, + ctxt->errNo, XML_ERR_FATAL, NULL, 0, + (const char *) prefix, (const char *) localname, + NULL, 0, 0, "Attribute %s:%s redefined\n", prefix, + localname); + if (ctxt != NULL) { + ctxt->wellFormed = 0; + if (ctxt->recovery == 0) + ctxt->disableSAX = 1; + } +} + +/** + * xmlFatalErr: + * @ctxt: an XML parser context + * @error: the error number + * @extra: extra information string + * + * Handle a fatal parser error, i.e. violating Well-Formedness constraints + */ +static void +xmlFatalErr(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *info) +{ + const char *errmsg; + + if ((ctxt != NULL) && (ctxt->disableSAX != 0) && + (ctxt->instate == XML_PARSER_EOF)) + return; + switch (error) { + case XML_ERR_INVALID_HEX_CHARREF: + errmsg = "CharRef: invalid hexadecimal value\n"; + break; + case XML_ERR_INVALID_DEC_CHARREF: + errmsg = "CharRef: invalid decimal value\n"; + break; + case XML_ERR_INVALID_CHARREF: + errmsg = "CharRef: invalid value\n"; + break; + case XML_ERR_INTERNAL_ERROR: + errmsg = "internal error"; + break; + case XML_ERR_PEREF_AT_EOF: + errmsg = "PEReference at end of document\n"; + break; + case XML_ERR_PEREF_IN_PROLOG: + errmsg = "PEReference in prolog\n"; + break; + case XML_ERR_PEREF_IN_EPILOG: + errmsg = "PEReference in epilog\n"; + break; + case XML_ERR_PEREF_NO_NAME: + errmsg = "PEReference: no name\n"; + break; + case XML_ERR_PEREF_SEMICOL_MISSING: + errmsg = "PEReference: expecting ';'\n"; + break; + case XML_ERR_ENTITY_LOOP: + errmsg = "Detected an entity reference loop\n"; + break; + case XML_ERR_ENTITY_NOT_STARTED: + errmsg = "EntityValue: \" or ' expected\n"; + break; + case XML_ERR_ENTITY_PE_INTERNAL: + errmsg = "PEReferences forbidden in internal subset\n"; + break; + case XML_ERR_ENTITY_NOT_FINISHED: + errmsg = "EntityValue: \" or ' expected\n"; + break; + case XML_ERR_ATTRIBUTE_NOT_STARTED: + errmsg = "AttValue: \" or ' expected\n"; + break; + case XML_ERR_LT_IN_ATTRIBUTE: + errmsg = "Unescaped '<' not allowed in attributes values\n"; + break; + case XML_ERR_LITERAL_NOT_STARTED: + errmsg = "SystemLiteral \" or ' expected\n"; + break; + case XML_ERR_LITERAL_NOT_FINISHED: + errmsg = "Unfinished System or Public ID \" or ' expected\n"; + break; + case XML_ERR_MISPLACED_CDATA_END: + errmsg = "Sequence ']]>' not allowed in content\n"; + break; + case XML_ERR_URI_REQUIRED: + errmsg = "SYSTEM or PUBLIC, the URI is missing\n"; + break; + case XML_ERR_PUBID_REQUIRED: + errmsg = "PUBLIC, the Public Identifier is missing\n"; + break; + case XML_ERR_HYPHEN_IN_COMMENT: + errmsg = "Comment must not contain '--' (double-hyphen)\n"; + break; + case XML_ERR_PI_NOT_STARTED: + errmsg = "xmlParsePI : no target name\n"; + break; + case XML_ERR_RESERVED_XML_NAME: + errmsg = "Invalid PI name\n"; + break; + case XML_ERR_NOTATION_NOT_STARTED: + errmsg = "NOTATION: Name expected here\n"; + break; + case XML_ERR_NOTATION_NOT_FINISHED: + errmsg = "'>' required to close NOTATION declaration\n"; + break; + case XML_ERR_VALUE_REQUIRED: + errmsg = "Entity value required\n"; + break; + case XML_ERR_URI_FRAGMENT: + errmsg = "Fragment not allowed"; + break; + case XML_ERR_ATTLIST_NOT_STARTED: + errmsg = "'(' required to start ATTLIST enumeration\n"; + break; + case XML_ERR_NMTOKEN_REQUIRED: + errmsg = "NmToken expected in ATTLIST enumeration\n"; + break; + case XML_ERR_ATTLIST_NOT_FINISHED: + errmsg = "')' required to finish ATTLIST enumeration\n"; + break; + case XML_ERR_MIXED_NOT_STARTED: + errmsg = "MixedContentDecl : '|' or ')*' expected\n"; + break; + case XML_ERR_PCDATA_REQUIRED: + errmsg = "MixedContentDecl : '#PCDATA' expected\n"; + break; + case XML_ERR_ELEMCONTENT_NOT_STARTED: + errmsg = "ContentDecl : Name or '(' expected\n"; + break; + case XML_ERR_ELEMCONTENT_NOT_FINISHED: + errmsg = "ContentDecl : ',' '|' or ')' expected\n"; + break; + case XML_ERR_PEREF_IN_INT_SUBSET: + errmsg = + "PEReference: forbidden within markup decl in internal subset\n"; + break; + case XML_ERR_GT_REQUIRED: + errmsg = "expected '>'\n"; + break; + case XML_ERR_CONDSEC_INVALID: + errmsg = "XML conditional section '[' expected\n"; + break; + case XML_ERR_EXT_SUBSET_NOT_FINISHED: + errmsg = "Content error in the external subset\n"; + break; + case XML_ERR_CONDSEC_INVALID_KEYWORD: + errmsg = + "conditional section INCLUDE or IGNORE keyword expected\n"; + break; + case XML_ERR_CONDSEC_NOT_FINISHED: + errmsg = "XML conditional section not closed\n"; + break; + case XML_ERR_XMLDECL_NOT_STARTED: + errmsg = "Text declaration '' expected\n"; + break; + case XML_ERR_EXT_ENTITY_STANDALONE: + errmsg = "external parsed entities cannot be standalone\n"; + break; + case XML_ERR_ENTITYREF_SEMICOL_MISSING: + errmsg = "EntityRef: expecting ';'\n"; + break; + case XML_ERR_DOCTYPE_NOT_FINISHED: + errmsg = "DOCTYPE improperly terminated\n"; + break; + case XML_ERR_LTSLASH_REQUIRED: + errmsg = "EndTag: 'errNo = error; + __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error, + XML_ERR_FATAL, NULL, 0, info, NULL, NULL, 0, 0, errmsg, + info); + if (ctxt != NULL) { + ctxt->wellFormed = 0; + if (ctxt->recovery == 0) + ctxt->disableSAX = 1; + } +} + +/** + * xmlFatalErrMsg: + * @ctxt: an XML parser context + * @error: the error number + * @msg: the error message + * + * Handle a fatal parser error, i.e. violating Well-Formedness constraints + */ +static void +xmlFatalErrMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error, + const char *msg) +{ + if ((ctxt != NULL) && (ctxt->disableSAX != 0) && + (ctxt->instate == XML_PARSER_EOF)) + return; + if (ctxt != NULL) + ctxt->errNo = error; + __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error, + XML_ERR_FATAL, NULL, 0, NULL, NULL, NULL, 0, 0, msg); + if (ctxt != NULL) { + ctxt->wellFormed = 0; + if (ctxt->recovery == 0) + ctxt->disableSAX = 1; + } +} + +/** + * xmlWarningMsg: + * @ctxt: an XML parser context + * @error: the error number + * @msg: the error message + * @str1: extra data + * @str2: extra data + * + * Handle a warning. + */ +static void +xmlWarningMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error, + const char *msg, const xmlChar *str1, const xmlChar *str2) +{ + xmlStructuredErrorFunc schannel = NULL; + + if ((ctxt != NULL) && (ctxt->disableSAX != 0) && + (ctxt->instate == XML_PARSER_EOF)) + return; + if ((ctxt != NULL) && (ctxt->sax != NULL) && + (ctxt->sax->initialized == XML_SAX2_MAGIC)) + schannel = ctxt->sax->serror; + __xmlRaiseError(schannel, + (ctxt->sax) ? ctxt->sax->warning : NULL, + ctxt->userData, + ctxt, NULL, XML_FROM_PARSER, error, + XML_ERR_WARNING, NULL, 0, + (const char *) str1, (const char *) str2, NULL, 0, 0, + msg, (const char *) str1, (const char *) str2); +} + +/** + * xmlValidityError: + * @ctxt: an XML parser context + * @error: the error number + * @msg: the error message + * @str1: extra data + * + * Handle a validity error. + */ +static void +xmlValidityError(xmlParserCtxtPtr ctxt, xmlParserErrors error, + const char *msg, const xmlChar *str1) +{ + xmlStructuredErrorFunc schannel = NULL; + + if ((ctxt != NULL) && (ctxt->disableSAX != 0) && + (ctxt->instate == XML_PARSER_EOF)) + return; + if (ctxt != NULL) { + ctxt->errNo = error; + if ((ctxt->sax != NULL) && (ctxt->sax->initialized == XML_SAX2_MAGIC)) + schannel = ctxt->sax->serror; + } + __xmlRaiseError(schannel, + ctxt->vctxt.error, ctxt->vctxt.userData, + ctxt, NULL, XML_FROM_DTD, error, + XML_ERR_ERROR, NULL, 0, (const char *) str1, + NULL, NULL, 0, 0, + msg, (const char *) str1); + if (ctxt != NULL) { + ctxt->valid = 0; + } +} + +/** + * xmlFatalErrMsgInt: + * @ctxt: an XML parser context + * @error: the error number + * @msg: the error message + * @val: an integer value + * + * Handle a fatal parser error, i.e. violating Well-Formedness constraints + */ +static void +xmlFatalErrMsgInt(xmlParserCtxtPtr ctxt, xmlParserErrors error, + const char *msg, int val) +{ + if ((ctxt != NULL) && (ctxt->disableSAX != 0) && + (ctxt->instate == XML_PARSER_EOF)) + return; + if (ctxt != NULL) + ctxt->errNo = error; + __xmlRaiseError(NULL, NULL, NULL, + ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL, + NULL, 0, NULL, NULL, NULL, val, 0, msg, val); + if (ctxt != NULL) { + ctxt->wellFormed = 0; + if (ctxt->recovery == 0) + ctxt->disableSAX = 1; + } +} + +/** + * xmlFatalErrMsgStrIntStr: + * @ctxt: an XML parser context + * @error: the error number + * @msg: the error message + * @str1: an string info + * @val: an integer value + * @str2: an string info + * + * Handle a fatal parser error, i.e. violating Well-Formedness constraints + */ +static void +xmlFatalErrMsgStrIntStr(xmlParserCtxtPtr ctxt, xmlParserErrors error, + const char *msg, const xmlChar *str1, int val, + const xmlChar *str2) +{ + if ((ctxt != NULL) && (ctxt->disableSAX != 0) && + (ctxt->instate == XML_PARSER_EOF)) + return; + if (ctxt != NULL) + ctxt->errNo = error; + __xmlRaiseError(NULL, NULL, NULL, + ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL, + NULL, 0, (const char *) str1, (const char *) str2, + NULL, val, 0, msg, str1, val, str2); + if (ctxt != NULL) { + ctxt->wellFormed = 0; + if (ctxt->recovery == 0) + ctxt->disableSAX = 1; + } +} + +/** + * xmlFatalErrMsgStr: + * @ctxt: an XML parser context + * @error: the error number + * @msg: the error message + * @val: a string value + * + * Handle a fatal parser error, i.e. violating Well-Formedness constraints + */ +static void +xmlFatalErrMsgStr(xmlParserCtxtPtr ctxt, xmlParserErrors error, + const char *msg, const xmlChar * val) +{ + if ((ctxt != NULL) && (ctxt->disableSAX != 0) && + (ctxt->instate == XML_PARSER_EOF)) + return; + if (ctxt != NULL) + ctxt->errNo = error; + __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, + XML_FROM_PARSER, error, XML_ERR_FATAL, + NULL, 0, (const char *) val, NULL, NULL, 0, 0, msg, + val); + if (ctxt != NULL) { + ctxt->wellFormed = 0; + if (ctxt->recovery == 0) + ctxt->disableSAX = 1; + } +} + +/** + * xmlErrMsgStr: + * @ctxt: an XML parser context + * @error: the error number + * @msg: the error message + * @val: a string value + * + * Handle a non fatal parser error + */ +static void +xmlErrMsgStr(xmlParserCtxtPtr ctxt, xmlParserErrors error, + const char *msg, const xmlChar * val) +{ + if ((ctxt != NULL) && (ctxt->disableSAX != 0) && + (ctxt->instate == XML_PARSER_EOF)) + return; + if (ctxt != NULL) + ctxt->errNo = error; + __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, + XML_FROM_PARSER, error, XML_ERR_ERROR, + NULL, 0, (const char *) val, NULL, NULL, 0, 0, msg, + val); +} + +/** + * xmlNsErr: + * @ctxt: an XML parser context + * @error: the error number + * @msg: the message + * @info1: extra information string + * @info2: extra information string + * + * Handle a fatal parser error, i.e. violating Well-Formedness constraints + */ +static void +xmlNsErr(xmlParserCtxtPtr ctxt, xmlParserErrors error, + const char *msg, + const xmlChar * info1, const xmlChar * info2, + const xmlChar * info3) +{ + if ((ctxt != NULL) && (ctxt->disableSAX != 0) && + (ctxt->instate == XML_PARSER_EOF)) + return; + if (ctxt != NULL) + ctxt->errNo = error; + __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_NAMESPACE, error, + XML_ERR_ERROR, NULL, 0, (const char *) info1, + (const char *) info2, (const char *) info3, 0, 0, msg, + info1, info2, info3); + if (ctxt != NULL) + ctxt->nsWellFormed = 0; +} + +/************************************************************************ + * * + * Library wide options * + * * + ************************************************************************/ + +/** + * xmlHasFeature: + * @feature: the feature to be examined + * + * Examines if the library has been compiled with a given feature. + * + * Returns a non-zero value if the feature exist, otherwise zero. + * Returns zero (0) if the feature does not exist or an unknown + * unknown feature is requested, non-zero otherwise. + */ +int +xmlHasFeature(xmlFeature feature) +{ + switch (feature) { + case XML_WITH_THREAD: +#ifdef LIBXML_THREAD_ENABLED + return(1); +#else + return(0); +#endif + case XML_WITH_TREE: +#ifdef LIBXML_TREE_ENABLED + return(1); +#else + return(0); +#endif + case XML_WITH_OUTPUT: +#ifdef LIBXML_OUTPUT_ENABLED + return(1); +#else + return(0); +#endif + case XML_WITH_PUSH: +#ifdef LIBXML_PUSH_ENABLED + return(1); +#else + return(0); +#endif + case XML_WITH_READER: +#ifdef LIBXML_READER_ENABLED + return(1); +#else + return(0); +#endif + case XML_WITH_PATTERN: +#ifdef LIBXML_PATTERN_ENABLED + return(1); +#else + return(0); +#endif + case XML_WITH_WRITER: +#ifdef LIBXML_WRITER_ENABLED + return(1); +#else + return(0); +#endif + case XML_WITH_SAX1: +#ifdef LIBXML_SAX1_ENABLED + return(1); +#else + return(0); +#endif + case XML_WITH_FTP: +#ifdef LIBXML_FTP_ENABLED + return(1); +#else + return(0); +#endif + case XML_WITH_HTTP: +#ifdef LIBXML_HTTP_ENABLED + return(1); +#else + return(0); +#endif + case XML_WITH_VALID: +#ifdef LIBXML_VALID_ENABLED + return(1); +#else + return(0); +#endif + case XML_WITH_HTML: +#ifdef LIBXML_HTML_ENABLED + return(1); +#else + return(0); +#endif + case XML_WITH_LEGACY: +#ifdef LIBXML_LEGACY_ENABLED + return(1); +#else + return(0); +#endif + case XML_WITH_C14N: +#ifdef LIBXML_C14N_ENABLED + return(1); +#else + return(0); +#endif + case XML_WITH_CATALOG: +#ifdef LIBXML_CATALOG_ENABLED + return(1); +#else + return(0); +#endif + case XML_WITH_XPATH: +#ifdef LIBXML_XPATH_ENABLED + return(1); +#else + return(0); +#endif + case XML_WITH_XPTR: +#ifdef LIBXML_XPTR_ENABLED + return(1); +#else + return(0); +#endif + case XML_WITH_XINCLUDE: +#ifdef LIBXML_XINCLUDE_ENABLED + return(1); +#else + return(0); +#endif + case XML_WITH_ICONV: +#ifdef LIBXML_ICONV_ENABLED + return(1); +#else + return(0); +#endif + case XML_WITH_ISO8859X: +#ifdef LIBXML_ISO8859X_ENABLED + return(1); +#else + return(0); +#endif + case XML_WITH_UNICODE: +#ifdef LIBXML_UNICODE_ENABLED + return(1); +#else + return(0); +#endif + case XML_WITH_REGEXP: +#ifdef LIBXML_REGEXP_ENABLED + return(1); +#else + return(0); +#endif + case XML_WITH_AUTOMATA: +#ifdef LIBXML_AUTOMATA_ENABLED + return(1); +#else + return(0); +#endif + case XML_WITH_EXPR: +#ifdef LIBXML_EXPR_ENABLED + return(1); +#else + return(0); +#endif + case XML_WITH_SCHEMAS: +#ifdef LIBXML_SCHEMAS_ENABLED + return(1); +#else + return(0); +#endif + case XML_WITH_SCHEMATRON: +#ifdef LIBXML_SCHEMATRON_ENABLED + return(1); +#else + return(0); +#endif + case XML_WITH_MODULES: +#ifdef LIBXML_MODULES_ENABLED + return(1); +#else + return(0); +#endif + case XML_WITH_DEBUG: +#ifdef LIBXML_DEBUG_ENABLED + return(1); +#else + return(0); +#endif + case XML_WITH_DEBUG_MEM: +#ifdef DEBUG_MEMORY_LOCATION + return(1); +#else + return(0); +#endif + case XML_WITH_DEBUG_RUN: +#ifdef LIBXML_DEBUG_RUNTIME + return(1); +#else + return(0); +#endif + case XML_WITH_ZLIB: +#ifdef LIBXML_ZLIB_ENABLED + return(1); +#else + return(0); +#endif + default: + break; + } + return(0); +} + +/************************************************************************ + * * + * SAX2 defaulted attributes handling * + * * + ************************************************************************/ + +/** + * xmlDetectSAX2: + * @ctxt: an XML parser context + * + * Do the SAX2 detection and specific intialization + */ +static void +xmlDetectSAX2(xmlParserCtxtPtr ctxt) { + if (ctxt == NULL) return; +#ifdef LIBXML_SAX1_ENABLED + if ((ctxt->sax) && (ctxt->sax->initialized == XML_SAX2_MAGIC) && + ((ctxt->sax->startElementNs != NULL) || + (ctxt->sax->endElementNs != NULL))) ctxt->sax2 = 1; +#else + ctxt->sax2 = 1; +#endif /* LIBXML_SAX1_ENABLED */ + + ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3); + ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5); + ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36); + if ((ctxt->str_xml==NULL) || (ctxt->str_xmlns==NULL) || + (ctxt->str_xml_ns == NULL)) { + xmlErrMemory(ctxt, NULL); + } +} + +typedef struct _xmlDefAttrs xmlDefAttrs; +typedef xmlDefAttrs *xmlDefAttrsPtr; +struct _xmlDefAttrs { + int nbAttrs; /* number of defaulted attributes on that element */ + int maxAttrs; /* the size of the array */ + const xmlChar *values[4]; /* array of localname/prefix/values */ +}; + +/** + * xmlAddDefAttrs: + * @ctxt: an XML parser context + * @fullname: the element fullname + * @fullattr: the attribute fullname + * @value: the attribute value + * + * Add a defaulted attribute for an element + */ +static void +xmlAddDefAttrs(xmlParserCtxtPtr ctxt, + const xmlChar *fullname, + const xmlChar *fullattr, + const xmlChar *value) { + xmlDefAttrsPtr defaults; + int len; + const xmlChar *name; + const xmlChar *prefix; + + if (ctxt->attsDefault == NULL) { + ctxt->attsDefault = xmlHashCreateDict(10, ctxt->dict); + if (ctxt->attsDefault == NULL) + goto mem_error; + } + + /* + * split the element name into prefix:localname , the string found + * are within the DTD and then not associated to namespace names. + */ + name = xmlSplitQName3(fullname, &len); + if (name == NULL) { + name = xmlDictLookup(ctxt->dict, fullname, -1); + prefix = NULL; + } else { + name = xmlDictLookup(ctxt->dict, name, -1); + prefix = xmlDictLookup(ctxt->dict, fullname, len); + } + + /* + * make sure there is some storage + */ + defaults = xmlHashLookup2(ctxt->attsDefault, name, prefix); + if (defaults == NULL) { + defaults = (xmlDefAttrsPtr) xmlMalloc(sizeof(xmlDefAttrs) + + (4 * 4) * sizeof(const xmlChar *)); + if (defaults == NULL) + goto mem_error; + defaults->nbAttrs = 0; + defaults->maxAttrs = 4; + xmlHashUpdateEntry2(ctxt->attsDefault, name, prefix, defaults, NULL); + } else if (defaults->nbAttrs >= defaults->maxAttrs) { + xmlDefAttrsPtr temp; + + temp = (xmlDefAttrsPtr) xmlRealloc(defaults, sizeof(xmlDefAttrs) + + (2 * defaults->maxAttrs * 4) * sizeof(const xmlChar *)); + if (temp == NULL) + goto mem_error; + defaults = temp; + defaults->maxAttrs *= 2; + xmlHashUpdateEntry2(ctxt->attsDefault, name, prefix, defaults, NULL); + } + + /* + * Split the element name into prefix:localname , the string found + * are within the DTD and hen not associated to namespace names. + */ + name = xmlSplitQName3(fullattr, &len); + if (name == NULL) { + name = xmlDictLookup(ctxt->dict, fullattr, -1); + prefix = NULL; + } else { + name = xmlDictLookup(ctxt->dict, name, -1); + prefix = xmlDictLookup(ctxt->dict, fullattr, len); + } + + defaults->values[4 * defaults->nbAttrs] = name; + defaults->values[4 * defaults->nbAttrs + 1] = prefix; + /* intern the string and precompute the end */ + len = xmlStrlen(value); + value = xmlDictLookup(ctxt->dict, value, len); + defaults->values[4 * defaults->nbAttrs + 2] = value; + defaults->values[4 * defaults->nbAttrs + 3] = value + len; + defaults->nbAttrs++; + + return; + +mem_error: + xmlErrMemory(ctxt, NULL); + return; +} + +/** + * xmlAddSpecialAttr: + * @ctxt: an XML parser context + * @fullname: the element fullname + * @fullattr: the attribute fullname + * @type: the attribute type + * + * Register that this attribute is not CDATA + */ +static void +xmlAddSpecialAttr(xmlParserCtxtPtr ctxt, + const xmlChar *fullname, + const xmlChar *fullattr, + int type) +{ + if (ctxt->attsSpecial == NULL) { + ctxt->attsSpecial = xmlHashCreateDict(10, ctxt->dict); + if (ctxt->attsSpecial == NULL) + goto mem_error; + } + + xmlHashAddEntry2(ctxt->attsSpecial, fullname, fullattr, + (void *) (long) type); + return; + +mem_error: + xmlErrMemory(ctxt, NULL); + return; +} + +/** + * xmlCheckLanguageID: + * @lang: pointer to the string value + * + * Checks that the value conforms to the LanguageID production: + * + * NOTE: this is somewhat deprecated, those productions were removed from + * the XML Second edition. + * + * [33] LanguageID ::= Langcode ('-' Subcode)* + * [34] Langcode ::= ISO639Code | IanaCode | UserCode + * [35] ISO639Code ::= ([a-z] | [A-Z]) ([a-z] | [A-Z]) + * [36] IanaCode ::= ('i' | 'I') '-' ([a-z] | [A-Z])+ + * [37] UserCode ::= ('x' | 'X') '-' ([a-z] | [A-Z])+ + * [38] Subcode ::= ([a-z] | [A-Z])+ + * + * Returns 1 if correct 0 otherwise + **/ +int +xmlCheckLanguageID(const xmlChar * lang) +{ + const xmlChar *cur = lang; + + if (cur == NULL) + return (0); + if (((cur[0] == 'i') && (cur[1] == '-')) || + ((cur[0] == 'I') && (cur[1] == '-'))) { + /* + * IANA code + */ + cur += 2; + while (((cur[0] >= 'A') && (cur[0] <= 'Z')) || /* non input consuming */ + ((cur[0] >= 'a') && (cur[0] <= 'z'))) + cur++; + } else if (((cur[0] == 'x') && (cur[1] == '-')) || + ((cur[0] == 'X') && (cur[1] == '-'))) { + /* + * User code + */ + cur += 2; + while (((cur[0] >= 'A') && (cur[0] <= 'Z')) || /* non input consuming */ + ((cur[0] >= 'a') && (cur[0] <= 'z'))) + cur++; + } else if (((cur[0] >= 'A') && (cur[0] <= 'Z')) || + ((cur[0] >= 'a') && (cur[0] <= 'z'))) { + /* + * ISO639 + */ + cur++; + if (((cur[0] >= 'A') && (cur[0] <= 'Z')) || + ((cur[0] >= 'a') && (cur[0] <= 'z'))) + cur++; + else + return (0); + } else + return (0); + while (cur[0] != 0) { /* non input consuming */ + if (cur[0] != '-') + return (0); + cur++; + if (((cur[0] >= 'A') && (cur[0] <= 'Z')) || + ((cur[0] >= 'a') && (cur[0] <= 'z'))) + cur++; + else + return (0); + while (((cur[0] >= 'A') && (cur[0] <= 'Z')) || /* non input consuming */ + ((cur[0] >= 'a') && (cur[0] <= 'z'))) + cur++; + } + return (1); +} + +/************************************************************************ + * * + * Parser stacks related functions and macros * + * * + ************************************************************************/ + +xmlEntityPtr xmlParseStringEntityRef(xmlParserCtxtPtr ctxt, + const xmlChar ** str); + +#ifdef SAX2 +/** + * nsPush: + * @ctxt: an XML parser context + * @prefix: the namespace prefix or NULL + * @URL: the namespace name + * + * Pushes a new parser namespace on top of the ns stack + * + * Returns -1 in case of error, -2 if the namespace should be discarded + * and the index in the stack otherwise. + */ +static int +nsPush(xmlParserCtxtPtr ctxt, const xmlChar *prefix, const xmlChar *URL) +{ + if (ctxt->options & XML_PARSE_NSCLEAN) { + int i; + for (i = 0;i < ctxt->nsNr;i += 2) { + if (ctxt->nsTab[i] == prefix) { + /* in scope */ + if (ctxt->nsTab[i + 1] == URL) + return(-2); + /* out of scope keep it */ + break; + } + } + } + if ((ctxt->nsMax == 0) || (ctxt->nsTab == NULL)) { + ctxt->nsMax = 10; + ctxt->nsNr = 0; + ctxt->nsTab = (const xmlChar **) + xmlMalloc(ctxt->nsMax * sizeof(xmlChar *)); + if (ctxt->nsTab == NULL) { + xmlErrMemory(ctxt, NULL); + ctxt->nsMax = 0; + return (-1); + } + } else if (ctxt->nsNr >= ctxt->nsMax) { + ctxt->nsMax *= 2; + ctxt->nsTab = (const xmlChar **) + xmlRealloc((char *) ctxt->nsTab, + ctxt->nsMax * sizeof(ctxt->nsTab[0])); + if (ctxt->nsTab == NULL) { + xmlErrMemory(ctxt, NULL); + ctxt->nsMax /= 2; + return (-1); + } + } + ctxt->nsTab[ctxt->nsNr++] = prefix; + ctxt->nsTab[ctxt->nsNr++] = URL; + return (ctxt->nsNr); +} +/** + * nsPop: + * @ctxt: an XML parser context + * @nr: the number to pop + * + * Pops the top @nr parser prefix/namespace from the ns stack + * + * Returns the number of namespaces removed + */ +static int +nsPop(xmlParserCtxtPtr ctxt, int nr) +{ + int i; + + if (ctxt->nsTab == NULL) return(0); + if (ctxt->nsNr < nr) { + xmlGenericError(xmlGenericErrorContext, "Pbm popping %d NS\n", nr); + nr = ctxt->nsNr; + } + if (ctxt->nsNr <= 0) + return (0); + + for (i = 0;i < nr;i++) { + ctxt->nsNr--; + ctxt->nsTab[ctxt->nsNr] = NULL; + } + return(nr); +} +#endif + +static int +xmlCtxtGrowAttrs(xmlParserCtxtPtr ctxt, int nr) { + const xmlChar **atts; + int *attallocs; + int maxatts; + + if (ctxt->atts == NULL) { + maxatts = 55; /* allow for 10 attrs by default */ + atts = (const xmlChar **) + xmlMalloc(maxatts * sizeof(xmlChar *)); + if (atts == NULL) goto mem_error; + ctxt->atts = atts; + attallocs = (int *) xmlMalloc((maxatts / 5) * sizeof(int)); + if (attallocs == NULL) goto mem_error; + ctxt->attallocs = attallocs; + ctxt->maxatts = maxatts; + } else if (nr + 5 > ctxt->maxatts) { + maxatts = (nr + 5) * 2; + atts = (const xmlChar **) xmlRealloc((void *) ctxt->atts, + maxatts * sizeof(const xmlChar *)); + if (atts == NULL) goto mem_error; + ctxt->atts = atts; + attallocs = (int *) xmlRealloc((void *) ctxt->attallocs, + (maxatts / 5) * sizeof(int)); + if (attallocs == NULL) goto mem_error; + ctxt->attallocs = attallocs; + ctxt->maxatts = maxatts; + } + return(ctxt->maxatts); +mem_error: + xmlErrMemory(ctxt, NULL); + return(-1); +} + +/** + * inputPush: + * @ctxt: an XML parser context + * @value: the parser input + * + * Pushes a new parser input on top of the input stack + * + * Returns 0 in case of error, the index in the stack otherwise + */ +int +inputPush(xmlParserCtxtPtr ctxt, xmlParserInputPtr value) +{ + if ((ctxt == NULL) || (value == NULL)) + return(0); + if (ctxt->inputNr >= ctxt->inputMax) { + ctxt->inputMax *= 2; + ctxt->inputTab = + (xmlParserInputPtr *) xmlRealloc(ctxt->inputTab, + ctxt->inputMax * + sizeof(ctxt->inputTab[0])); + if (ctxt->inputTab == NULL) { + xmlErrMemory(ctxt, NULL); + return (0); + } + } + ctxt->inputTab[ctxt->inputNr] = value; + ctxt->input = value; + return (ctxt->inputNr++); +} +/** + * inputPop: + * @ctxt: an XML parser context + * + * Pops the top parser input from the input stack + * + * Returns the input just removed + */ +xmlParserInputPtr +inputPop(xmlParserCtxtPtr ctxt) +{ + xmlParserInputPtr ret; + + if (ctxt == NULL) + return(NULL); + if (ctxt->inputNr <= 0) + return (NULL); + ctxt->inputNr--; + if (ctxt->inputNr > 0) + ctxt->input = ctxt->inputTab[ctxt->inputNr - 1]; + else + ctxt->input = NULL; + ret = ctxt->inputTab[ctxt->inputNr]; + ctxt->inputTab[ctxt->inputNr] = NULL; + return (ret); +} +/** + * nodePush: + * @ctxt: an XML parser context + * @value: the element node + * + * Pushes a new element node on top of the node stack + * + * Returns 0 in case of error, the index in the stack otherwise + */ +int +nodePush(xmlParserCtxtPtr ctxt, xmlNodePtr value) +{ + if (ctxt == NULL) return(0); + if (ctxt->nodeNr >= ctxt->nodeMax) { + xmlNodePtr *tmp; + + tmp = (xmlNodePtr *) xmlRealloc(ctxt->nodeTab, + ctxt->nodeMax * 2 * + sizeof(ctxt->nodeTab[0])); + if (tmp == NULL) { + xmlErrMemory(ctxt, NULL); + return (0); + } + ctxt->nodeTab = tmp; + ctxt->nodeMax *= 2; + } + if (((unsigned int) ctxt->nodeNr) > xmlParserMaxDepth) { + xmlFatalErrMsgInt(ctxt, XML_ERR_INTERNAL_ERROR, + "Excessive depth in document: change xmlParserMaxDepth = %d\n", + xmlParserMaxDepth); + ctxt->instate = XML_PARSER_EOF; + return(0); + } + ctxt->nodeTab[ctxt->nodeNr] = value; + ctxt->node = value; + return (ctxt->nodeNr++); +} +/** + * nodePop: + * @ctxt: an XML parser context + * + * Pops the top element node from the node stack + * + * Returns the node just removed + */ +xmlNodePtr +nodePop(xmlParserCtxtPtr ctxt) +{ + xmlNodePtr ret; + + if (ctxt == NULL) return(NULL); + if (ctxt->nodeNr <= 0) + return (NULL); + ctxt->nodeNr--; + if (ctxt->nodeNr > 0) + ctxt->node = ctxt->nodeTab[ctxt->nodeNr - 1]; + else + ctxt->node = NULL; + ret = ctxt->nodeTab[ctxt->nodeNr]; + ctxt->nodeTab[ctxt->nodeNr] = NULL; + return (ret); +} + +#ifdef LIBXML_PUSH_ENABLED +/** + * nameNsPush: + * @ctxt: an XML parser context + * @value: the element name + * @prefix: the element prefix + * @URI: the element namespace name + * + * Pushes a new element name/prefix/URL on top of the name stack + * + * Returns -1 in case of error, the index in the stack otherwise + */ +static int +nameNsPush(xmlParserCtxtPtr ctxt, const xmlChar * value, + const xmlChar *prefix, const xmlChar *URI, int nsNr) +{ + if (ctxt->nameNr >= ctxt->nameMax) { + const xmlChar * *tmp; + void **tmp2; + ctxt->nameMax *= 2; + tmp = (const xmlChar * *) xmlRealloc((xmlChar * *)ctxt->nameTab, + ctxt->nameMax * + sizeof(ctxt->nameTab[0])); + if (tmp == NULL) { + ctxt->nameMax /= 2; + goto mem_error; + } + ctxt->nameTab = tmp; + tmp2 = (void **) xmlRealloc((void * *)ctxt->pushTab, + ctxt->nameMax * 3 * + sizeof(ctxt->pushTab[0])); + if (tmp2 == NULL) { + ctxt->nameMax /= 2; + goto mem_error; + } + ctxt->pushTab = tmp2; + } + ctxt->nameTab[ctxt->nameNr] = value; + ctxt->name = value; + ctxt->pushTab[ctxt->nameNr * 3] = (void *) prefix; + ctxt->pushTab[ctxt->nameNr * 3 + 1] = (void *) URI; + ctxt->pushTab[ctxt->nameNr * 3 + 2] = (void *) (long) nsNr; + return (ctxt->nameNr++); +mem_error: + xmlErrMemory(ctxt, NULL); + return (-1); +} +/** + * nameNsPop: + * @ctxt: an XML parser context + * + * Pops the top element/prefix/URI name from the name stack + * + * Returns the name just removed + */ +static const xmlChar * +nameNsPop(xmlParserCtxtPtr ctxt) +{ + const xmlChar *ret; + + if (ctxt->nameNr <= 0) + return (NULL); + ctxt->nameNr--; + if (ctxt->nameNr > 0) + ctxt->name = ctxt->nameTab[ctxt->nameNr - 1]; + else + ctxt->name = NULL; + ret = ctxt->nameTab[ctxt->nameNr]; + ctxt->nameTab[ctxt->nameNr] = NULL; + return (ret); +} +#endif /* LIBXML_PUSH_ENABLED */ + +/** + * namePush: + * @ctxt: an XML parser context + * @value: the element name + * + * Pushes a new element name on top of the name stack + * + * Returns -1 in case of error, the index in the stack otherwise + */ +int +namePush(xmlParserCtxtPtr ctxt, const xmlChar * value) +{ + if (ctxt == NULL) return (-1); + + if (ctxt->nameNr >= ctxt->nameMax) { + const xmlChar * *tmp; + ctxt->nameMax *= 2; + tmp = (const xmlChar * *) xmlRealloc((xmlChar * *)ctxt->nameTab, + ctxt->nameMax * + sizeof(ctxt->nameTab[0])); + if (tmp == NULL) { + ctxt->nameMax /= 2; + goto mem_error; + } + ctxt->nameTab = tmp; + } + ctxt->nameTab[ctxt->nameNr] = value; + ctxt->name = value; + return (ctxt->nameNr++); +mem_error: + xmlErrMemory(ctxt, NULL); + return (-1); +} +/** + * namePop: + * @ctxt: an XML parser context + * + * Pops the top element name from the name stack + * + * Returns the name just removed + */ +const xmlChar * +namePop(xmlParserCtxtPtr ctxt) +{ + const xmlChar *ret; + + if ((ctxt == NULL) || (ctxt->nameNr <= 0)) + return (NULL); + ctxt->nameNr--; + if (ctxt->nameNr > 0) + ctxt->name = ctxt->nameTab[ctxt->nameNr - 1]; + else + ctxt->name = NULL; + ret = ctxt->nameTab[ctxt->nameNr]; + ctxt->nameTab[ctxt->nameNr] = NULL; + return (ret); +} + +static int spacePush(xmlParserCtxtPtr ctxt, int val) { + if (ctxt->spaceNr >= ctxt->spaceMax) { + ctxt->spaceMax *= 2; + ctxt->spaceTab = (int *) xmlRealloc(ctxt->spaceTab, + ctxt->spaceMax * sizeof(ctxt->spaceTab[0])); + if (ctxt->spaceTab == NULL) { + xmlErrMemory(ctxt, NULL); + return(0); + } + } + ctxt->spaceTab[ctxt->spaceNr] = val; + ctxt->space = &ctxt->spaceTab[ctxt->spaceNr]; + return(ctxt->spaceNr++); +} + +static int spacePop(xmlParserCtxtPtr ctxt) { + int ret; + if (ctxt->spaceNr <= 0) return(0); + ctxt->spaceNr--; + if (ctxt->spaceNr > 0) + ctxt->space = &ctxt->spaceTab[ctxt->spaceNr - 1]; + else + ctxt->space = &ctxt->spaceTab[0]; + ret = ctxt->spaceTab[ctxt->spaceNr]; + ctxt->spaceTab[ctxt->spaceNr] = -1; + return(ret); +} + +/* + * Macros for accessing the content. Those should be used only by the parser, + * and not exported. + * + * Dirty macros, i.e. one often need to make assumption on the context to + * use them + * + * CUR_PTR return the current pointer to the xmlChar to be parsed. + * To be used with extreme caution since operations consuming + * characters may move the input buffer to a different location ! + * CUR returns the current xmlChar value, i.e. a 8 bit value if compiled + * This should be used internally by the parser + * only to compare to ASCII values otherwise it would break when + * running with UTF-8 encoding. + * RAW same as CUR but in the input buffer, bypass any token + * extraction that may have been done + * NXT(n) returns the n'th next xmlChar. Same as CUR is should be used only + * to compare on ASCII based substring. + * SKIP(n) Skip n xmlChar, and must also be used only to skip ASCII defined + * strings without newlines within the parser. + * NEXT1(l) Skip 1 xmlChar, and must also be used only to skip 1 non-newline ASCII + * defined char within the parser. + * Clean macros, not dependent of an ASCII context, expect UTF-8 encoding + * + * NEXT Skip to the next character, this does the proper decoding + * in UTF-8 mode. It also pop-up unfinished entities on the fly. + * NEXTL(l) Skip the current unicode character of l xmlChars long. + * CUR_CHAR(l) returns the current unicode character (int), set l + * to the number of xmlChars used for the encoding [0-5]. + * CUR_SCHAR same but operate on a string instead of the context + * COPY_BUF copy the current unicode char to the target buffer, increment + * the index + * GROW, SHRINK handling of input buffers + */ + +#define RAW (*ctxt->input->cur) +#define CUR (*ctxt->input->cur) +#define NXT(val) ctxt->input->cur[(val)] +#define CUR_PTR ctxt->input->cur + +#define CMP4( s, c1, c2, c3, c4 ) \ + ( ((unsigned char *) s)[ 0 ] == c1 && ((unsigned char *) s)[ 1 ] == c2 && \ + ((unsigned char *) s)[ 2 ] == c3 && ((unsigned char *) s)[ 3 ] == c4 ) +#define CMP5( s, c1, c2, c3, c4, c5 ) \ + ( CMP4( s, c1, c2, c3, c4 ) && ((unsigned char *) s)[ 4 ] == c5 ) +#define CMP6( s, c1, c2, c3, c4, c5, c6 ) \ + ( CMP5( s, c1, c2, c3, c4, c5 ) && ((unsigned char *) s)[ 5 ] == c6 ) +#define CMP7( s, c1, c2, c3, c4, c5, c6, c7 ) \ + ( CMP6( s, c1, c2, c3, c4, c5, c6 ) && ((unsigned char *) s)[ 6 ] == c7 ) +#define CMP8( s, c1, c2, c3, c4, c5, c6, c7, c8 ) \ + ( CMP7( s, c1, c2, c3, c4, c5, c6, c7 ) && ((unsigned char *) s)[ 7 ] == c8 ) +#define CMP9( s, c1, c2, c3, c4, c5, c6, c7, c8, c9 ) \ + ( CMP8( s, c1, c2, c3, c4, c5, c6, c7, c8 ) && \ + ((unsigned char *) s)[ 8 ] == c9 ) +#define CMP10( s, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10 ) \ + ( CMP9( s, c1, c2, c3, c4, c5, c6, c7, c8, c9 ) && \ + ((unsigned char *) s)[ 9 ] == c10 ) + +#define SKIP(val) do { \ + ctxt->nbChars += (val),ctxt->input->cur += (val),ctxt->input->col+=(val); \ + if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt); \ + if ((*ctxt->input->cur == 0) && \ + (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0)) \ + xmlPopInput(ctxt); \ + } while (0) + +#define SKIPL(val) do { \ + int skipl; \ + for(skipl=0; skiplinput->cur) == '\n') { \ + ctxt->input->line++; ctxt->input->col = 1; \ + } else ctxt->input->col++; \ + ctxt->nbChars++; \ + ctxt->input->cur++; \ + } \ + if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt); \ + if ((*ctxt->input->cur == 0) && \ + (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0)) \ + xmlPopInput(ctxt); \ + } while (0) + +#define SHRINK if ((ctxt->progressive == 0) && \ + (ctxt->input->cur - ctxt->input->base > 2 * INPUT_CHUNK) && \ + (ctxt->input->end - ctxt->input->cur < 2 * INPUT_CHUNK)) \ + xmlSHRINK (ctxt); + +static void xmlSHRINK (xmlParserCtxtPtr ctxt) { + xmlParserInputShrink(ctxt->input); + if ((*ctxt->input->cur == 0) && + (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0)) + xmlPopInput(ctxt); + } + +#define GROW if ((ctxt->progressive == 0) && \ + (ctxt->input->end - ctxt->input->cur < INPUT_CHUNK)) \ + xmlGROW (ctxt); + +static void xmlGROW (xmlParserCtxtPtr ctxt) { + xmlParserInputGrow(ctxt->input, INPUT_CHUNK); + if ((*ctxt->input->cur == 0) && + (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0)) + xmlPopInput(ctxt); +} + +#define SKIP_BLANKS xmlSkipBlankChars(ctxt) + +#define NEXT xmlNextChar(ctxt) + +#define NEXT1 { \ + ctxt->input->col++; \ + ctxt->input->cur++; \ + ctxt->nbChars++; \ + if (*ctxt->input->cur == 0) \ + xmlParserInputGrow(ctxt->input, INPUT_CHUNK); \ + } + +#define NEXTL(l) do { \ + if (*(ctxt->input->cur) == '\n') { \ + ctxt->input->line++; ctxt->input->col = 1; \ + } else ctxt->input->col++; \ + ctxt->input->cur += l; \ + if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt); \ + } while (0) + +#define CUR_CHAR(l) xmlCurrentChar(ctxt, &l) +#define CUR_SCHAR(s, l) xmlStringCurrentChar(ctxt, s, &l) + +#define COPY_BUF(l,b,i,v) \ + if (l == 1) b[i++] = (xmlChar) v; \ + else i += xmlCopyCharMultiByte(&b[i],v) + +/** + * xmlSkipBlankChars: + * @ctxt: the XML parser context + * + * skip all blanks character found at that point in the input streams. + * It pops up finished entities in the process if allowable at that point. + * + * Returns the number of space chars skipped + */ + +int +xmlSkipBlankChars(xmlParserCtxtPtr ctxt) { + int res = 0; + + /* + * It's Okay to use CUR/NEXT here since all the blanks are on + * the ASCII range. + */ + if ((ctxt->inputNr == 1) && (ctxt->instate != XML_PARSER_DTD)) { + const xmlChar *cur; + /* + * if we are in the document content, go really fast + */ + cur = ctxt->input->cur; + while (IS_BLANK_CH(*cur)) { + if (*cur == '\n') { + ctxt->input->line++; ctxt->input->col = 1; + } + cur++; + res++; + if (*cur == 0) { + ctxt->input->cur = cur; + xmlParserInputGrow(ctxt->input, INPUT_CHUNK); + cur = ctxt->input->cur; + } + } + ctxt->input->cur = cur; + } else { + int cur; + do { + cur = CUR; + while (IS_BLANK_CH(cur)) { /* CHECKED tstblanks.xml */ + NEXT; + cur = CUR; + res++; + } + while ((cur == 0) && (ctxt->inputNr > 1) && + (ctxt->instate != XML_PARSER_COMMENT)) { + xmlPopInput(ctxt); + cur = CUR; + } + /* + * Need to handle support of entities branching here + */ + if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt); + } while (IS_BLANK(cur)); /* CHECKED tstblanks.xml */ + } + return(res); +} + +/************************************************************************ + * * + * Commodity functions to handle entities * + * * + ************************************************************************/ + +/** + * xmlPopInput: + * @ctxt: an XML parser context + * + * xmlPopInput: the current input pointed by ctxt->input came to an end + * pop it and return the next char. + * + * Returns the current xmlChar in the parser context + */ +xmlChar +xmlPopInput(xmlParserCtxtPtr ctxt) { + if ((ctxt == NULL) || (ctxt->inputNr <= 1)) return(0); + if (xmlParserDebugEntities) + xmlGenericError(xmlGenericErrorContext, + "Popping input %d\n", ctxt->inputNr); + xmlFreeInputStream(inputPop(ctxt)); + if ((*ctxt->input->cur == 0) && + (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0)) + return(xmlPopInput(ctxt)); + return(CUR); +} + +/** + * xmlPushInput: + * @ctxt: an XML parser context + * @input: an XML parser input fragment (entity, XML fragment ...). + * + * xmlPushInput: switch to a new input stream which is stacked on top + * of the previous one(s). + */ +void +xmlPushInput(xmlParserCtxtPtr ctxt, xmlParserInputPtr input) { + if (input == NULL) return; + + if (xmlParserDebugEntities) { + if ((ctxt->input != NULL) && (ctxt->input->filename)) + xmlGenericError(xmlGenericErrorContext, + "%s(%d): ", ctxt->input->filename, + ctxt->input->line); + xmlGenericError(xmlGenericErrorContext, + "Pushing input %d : %.30s\n", ctxt->inputNr+1, input->cur); + } + inputPush(ctxt, input); + GROW; +} + +/** + * xmlParseCharRef: + * @ctxt: an XML parser context + * + * parse Reference declarations + * + * [66] CharRef ::= '&#' [0-9]+ ';' | + * '&#x' [0-9a-fA-F]+ ';' + * + * [ WFC: Legal Character ] + * Characters referred to using character references must match the + * production for Char. + * + * Returns the value parsed (as an int), 0 in case of error + */ +int +xmlParseCharRef(xmlParserCtxtPtr ctxt) { + unsigned int val = 0; + int count = 0; + unsigned int outofrange = 0; + + /* + * Using RAW/CUR/NEXT is okay since we are working on ASCII range here + */ + if ((RAW == '&') && (NXT(1) == '#') && + (NXT(2) == 'x')) { + SKIP(3); + GROW; + while (RAW != ';') { /* loop blocked by count */ + if (count++ > 20) { + count = 0; + GROW; + } + if ((RAW >= '0') && (RAW <= '9')) + val = val * 16 + (CUR - '0'); + else if ((RAW >= 'a') && (RAW <= 'f') && (count < 20)) + val = val * 16 + (CUR - 'a') + 10; + else if ((RAW >= 'A') && (RAW <= 'F') && (count < 20)) + val = val * 16 + (CUR - 'A') + 10; + else { + xmlFatalErr(ctxt, XML_ERR_INVALID_HEX_CHARREF, NULL); + val = 0; + break; + } + if (val > 0x10FFFF) + outofrange = val; + + NEXT; + count++; + } + if (RAW == ';') { + /* on purpose to avoid reentrancy problems with NEXT and SKIP */ + ctxt->input->col++; + ctxt->nbChars ++; + ctxt->input->cur++; + } + } else if ((RAW == '&') && (NXT(1) == '#')) { + SKIP(2); + GROW; + while (RAW != ';') { /* loop blocked by count */ + if (count++ > 20) { + count = 0; + GROW; + } + if ((RAW >= '0') && (RAW <= '9')) + val = val * 10 + (CUR - '0'); + else { + xmlFatalErr(ctxt, XML_ERR_INVALID_DEC_CHARREF, NULL); + val = 0; + break; + } + if (val > 0x10FFFF) + outofrange = val; + + NEXT; + count++; + } + if (RAW == ';') { + /* on purpose to avoid reentrancy problems with NEXT and SKIP */ + ctxt->input->col++; + ctxt->nbChars ++; + ctxt->input->cur++; + } + } else { + xmlFatalErr(ctxt, XML_ERR_INVALID_CHARREF, NULL); + } + + /* + * [ WFC: Legal Character ] + * Characters referred to using character references must match the + * production for Char. + */ + if ((IS_CHAR(val) && (outofrange == 0))) { + return(val); + } else { + xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR, + "xmlParseCharRef: invalid xmlChar value %d\n", + val); + } + return(0); +} + +/** + * xmlParseStringCharRef: + * @ctxt: an XML parser context + * @str: a pointer to an index in the string + * + * parse Reference declarations, variant parsing from a string rather + * than an an input flow. + * + * [66] CharRef ::= '&#' [0-9]+ ';' | + * '&#x' [0-9a-fA-F]+ ';' + * + * [ WFC: Legal Character ] + * Characters referred to using character references must match the + * production for Char. + * + * Returns the value parsed (as an int), 0 in case of error, str will be + * updated to the current value of the index + */ +static int +xmlParseStringCharRef(xmlParserCtxtPtr ctxt, const xmlChar **str) { + const xmlChar *ptr; + xmlChar cur; + unsigned int val = 0; + unsigned int outofrange = 0; + + if ((str == NULL) || (*str == NULL)) return(0); + ptr = *str; + cur = *ptr; + if ((cur == '&') && (ptr[1] == '#') && (ptr[2] == 'x')) { + ptr += 3; + cur = *ptr; + while (cur != ';') { /* Non input consuming loop */ + if ((cur >= '0') && (cur <= '9')) + val = val * 16 + (cur - '0'); + else if ((cur >= 'a') && (cur <= 'f')) + val = val * 16 + (cur - 'a') + 10; + else if ((cur >= 'A') && (cur <= 'F')) + val = val * 16 + (cur - 'A') + 10; + else { + xmlFatalErr(ctxt, XML_ERR_INVALID_HEX_CHARREF, NULL); + val = 0; + break; + } + if (val > 0x10FFFF) + outofrange = val; + + ptr++; + cur = *ptr; + } + if (cur == ';') + ptr++; + } else if ((cur == '&') && (ptr[1] == '#')){ + ptr += 2; + cur = *ptr; + while (cur != ';') { /* Non input consuming loops */ + if ((cur >= '0') && (cur <= '9')) + val = val * 10 + (cur - '0'); + else { + xmlFatalErr(ctxt, XML_ERR_INVALID_DEC_CHARREF, NULL); + val = 0; + break; + } + if (val > 0x10FFFF) + outofrange = val; + + ptr++; + cur = *ptr; + } + if (cur == ';') + ptr++; + } else { + xmlFatalErr(ctxt, XML_ERR_INVALID_CHARREF, NULL); + return(0); + } + *str = ptr; + + /* + * [ WFC: Legal Character ] + * Characters referred to using character references must match the + * production for Char. + */ + if ((IS_CHAR(val) && (outofrange == 0))) { + return(val); + } else { + xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR, + "xmlParseStringCharRef: invalid xmlChar value %d\n", + val); + } + return(0); +} + +/** + * xmlNewBlanksWrapperInputStream: + * @ctxt: an XML parser context + * @entity: an Entity pointer + * + * Create a new input stream for wrapping + * blanks around a PEReference + * + * Returns the new input stream or NULL + */ + +static void deallocblankswrapper (xmlChar *str) {xmlFree(str);} + +static xmlParserInputPtr +xmlNewBlanksWrapperInputStream(xmlParserCtxtPtr ctxt, xmlEntityPtr entity) { + xmlParserInputPtr input; + xmlChar *buffer; + size_t length; + if (entity == NULL) { + xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR, + "xmlNewBlanksWrapperInputStream entity\n"); + return(NULL); + } + if (xmlParserDebugEntities) + xmlGenericError(xmlGenericErrorContext, + "new blanks wrapper for entity: %s\n", entity->name); + input = xmlNewInputStream(ctxt); + if (input == NULL) { + return(NULL); + } + length = xmlStrlen(entity->name) + 5; + buffer = xmlMallocAtomic(length); + if (buffer == NULL) { + xmlErrMemory(ctxt, NULL); + return(NULL); + } + buffer [0] = ' '; + buffer [1] = '%'; + buffer [length-3] = ';'; + buffer [length-2] = ' '; + buffer [length-1] = 0; + memcpy(buffer + 2, entity->name, length - 5); + input->free = deallocblankswrapper; + input->base = buffer; + input->cur = buffer; + input->length = length; + input->end = &buffer[length]; + return(input); +} + +/** + * xmlParserHandlePEReference: + * @ctxt: the parser context + * + * [69] PEReference ::= '%' Name ';' + * + * [ WFC: No Recursion ] + * A parsed entity must not contain a recursive + * reference to itself, either directly or indirectly. + * + * [ WFC: Entity Declared ] + * In a document without any DTD, a document with only an internal DTD + * subset which contains no parameter entity references, or a document + * with "standalone='yes'", ... ... The declaration of a parameter + * entity must precede any reference to it... + * + * [ VC: Entity Declared ] + * In a document with an external subset or external parameter entities + * with "standalone='no'", ... ... The declaration of a parameter entity + * must precede any reference to it... + * + * [ WFC: In DTD ] + * Parameter-entity references may only appear in the DTD. + * NOTE: misleading but this is handled. + * + * A PEReference may have been detected in the current input stream + * the handling is done accordingly to + * http://www.w3.org/TR/REC-xml#entproc + * i.e. + * - Included in literal in entity values + * - Included as Parameter Entity reference within DTDs + */ +void +xmlParserHandlePEReference(xmlParserCtxtPtr ctxt) { + const xmlChar *name; + xmlEntityPtr entity = NULL; + xmlParserInputPtr input; + + if (RAW != '%') return; + switch(ctxt->instate) { + case XML_PARSER_CDATA_SECTION: + return; + case XML_PARSER_COMMENT: + return; + case XML_PARSER_START_TAG: + return; + case XML_PARSER_END_TAG: + return; + case XML_PARSER_EOF: + xmlFatalErr(ctxt, XML_ERR_PEREF_AT_EOF, NULL); + return; + case XML_PARSER_PROLOG: + case XML_PARSER_START: + case XML_PARSER_MISC: + xmlFatalErr(ctxt, XML_ERR_PEREF_IN_PROLOG, NULL); + return; + case XML_PARSER_ENTITY_DECL: + case XML_PARSER_CONTENT: + case XML_PARSER_ATTRIBUTE_VALUE: + case XML_PARSER_PI: + case XML_PARSER_SYSTEM_LITERAL: + case XML_PARSER_PUBLIC_LITERAL: + /* we just ignore it there */ + return; + case XML_PARSER_EPILOG: + xmlFatalErr(ctxt, XML_ERR_PEREF_IN_EPILOG, NULL); + return; + case XML_PARSER_ENTITY_VALUE: + /* + * NOTE: in the case of entity values, we don't do the + * substitution here since we need the literal + * entity value to be able to save the internal + * subset of the document. + * This will be handled by xmlStringDecodeEntities + */ + return; + case XML_PARSER_DTD: + /* + * [WFC: Well-Formedness Constraint: PEs in Internal Subset] + * In the internal DTD subset, parameter-entity references + * can occur only where markup declarations can occur, not + * within markup declarations. + * In that case this is handled in xmlParseMarkupDecl + */ + if ((ctxt->external == 0) && (ctxt->inputNr == 1)) + return; + if (IS_BLANK_CH(NXT(1)) || NXT(1) == 0) + return; + break; + case XML_PARSER_IGNORE: + return; + } + + NEXT; + name = xmlParseName(ctxt); + if (xmlParserDebugEntities) + xmlGenericError(xmlGenericErrorContext, + "PEReference: %s\n", name); + if (name == NULL) { + xmlFatalErr(ctxt, XML_ERR_PEREF_NO_NAME, NULL); + } else { + if (RAW == ';') { + NEXT; + if ((ctxt->sax != NULL) && (ctxt->sax->getParameterEntity != NULL)) + entity = ctxt->sax->getParameterEntity(ctxt->userData, name); + if (entity == NULL) { + + /* + * [ WFC: Entity Declared ] + * In a document without any DTD, a document with only an + * internal DTD subset which contains no parameter entity + * references, or a document with "standalone='yes'", ... + * ... The declaration of a parameter entity must precede + * any reference to it... + */ + if ((ctxt->standalone == 1) || + ((ctxt->hasExternalSubset == 0) && + (ctxt->hasPErefs == 0))) { + xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY, + "PEReference: %%%s; not found\n", name); + } else { + /* + * [ VC: Entity Declared ] + * In a document with an external subset or external + * parameter entities with "standalone='no'", ... + * ... The declaration of a parameter entity must precede + * any reference to it... + */ + if ((ctxt->validate) && (ctxt->vctxt.error != NULL)) { + xmlValidityError(ctxt, XML_WAR_UNDECLARED_ENTITY, + "PEReference: %%%s; not found\n", + name); + } else + xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY, + "PEReference: %%%s; not found\n", + name, NULL); + ctxt->valid = 0; + } + } else if (ctxt->input->free != deallocblankswrapper) { + input = xmlNewBlanksWrapperInputStream(ctxt, entity); + xmlPushInput(ctxt, input); + } else { + if ((entity->etype == XML_INTERNAL_PARAMETER_ENTITY) || + (entity->etype == XML_EXTERNAL_PARAMETER_ENTITY)) { + xmlChar start[4]; + xmlCharEncoding enc; + + /* + * handle the extra spaces added before and after + * c.f. http://www.w3.org/TR/REC-xml#as-PE + * this is done independently. + */ + input = xmlNewEntityInputStream(ctxt, entity); + xmlPushInput(ctxt, input); + + /* + * Get the 4 first bytes and decode the charset + * if enc != XML_CHAR_ENCODING_NONE + * plug some encoding conversion routines. + * Note that, since we may have some non-UTF8 + * encoding (like UTF16, bug 135229), the 'length' + * is not known, but we can calculate based upon + * the amount of data in the buffer. + */ + GROW + if ((ctxt->input->end - ctxt->input->cur)>=4) { + start[0] = RAW; + start[1] = NXT(1); + start[2] = NXT(2); + start[3] = NXT(3); + enc = xmlDetectCharEncoding(start, 4); + if (enc != XML_CHAR_ENCODING_NONE) { + xmlSwitchEncoding(ctxt, enc); + } + } + + if ((entity->etype == XML_EXTERNAL_PARAMETER_ENTITY) && + (CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l' )) && + (IS_BLANK_CH(NXT(5)))) { + xmlParseTextDecl(ctxt); + } + } else { + xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_PARAMETER, + "PEReference: %s is not a parameter entity\n", + name); + } + } + } else { + xmlFatalErr(ctxt, XML_ERR_PEREF_SEMICOL_MISSING, NULL); + } + } +} + +/* + * Macro used to grow the current buffer. + */ +#define growBuffer(buffer) { \ + xmlChar *tmp; \ + buffer##_size *= 2; \ + tmp = (xmlChar *) \ + xmlRealloc(buffer, buffer##_size * sizeof(xmlChar)); \ + if (tmp == NULL) goto mem_error; \ + buffer = tmp; \ +} + +/** + * xmlStringLenDecodeEntities: + * @ctxt: the parser context + * @str: the input string + * @len: the string length + * @what: combination of XML_SUBSTITUTE_REF and XML_SUBSTITUTE_PEREF + * @end: an end marker xmlChar, 0 if none + * @end2: an end marker xmlChar, 0 if none + * @end3: an end marker xmlChar, 0 if none + * + * Takes a entity string content and process to do the adequate substitutions. + * + * [67] Reference ::= EntityRef | CharRef + * + * [69] PEReference ::= '%' Name ';' + * + * Returns A newly allocated string with the substitution done. The caller + * must deallocate it ! + */ +xmlChar * +xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len, + int what, xmlChar end, xmlChar end2, xmlChar end3) { + xmlChar *buffer = NULL; + int buffer_size = 0; + + xmlChar *current = NULL; + const xmlChar *last; + xmlEntityPtr ent; + int c,l; + int nbchars = 0; + + if ((ctxt == NULL) || (str == NULL) || (len < 0)) + return(NULL); + last = str + len; + + if (ctxt->depth > 40) { + xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL); + return(NULL); + } + + /* + * allocate a translation buffer. + */ + buffer_size = XML_PARSER_BIG_BUFFER_SIZE; + buffer = (xmlChar *) xmlMallocAtomic(buffer_size * sizeof(xmlChar)); + if (buffer == NULL) goto mem_error; + + /* + * OK loop until we reach one of the ending char or a size limit. + * we are operating on already parsed values. + */ + if (str < last) + c = CUR_SCHAR(str, l); + else + c = 0; + while ((c != 0) && (c != end) && /* non input consuming loop */ + (c != end2) && (c != end3)) { + + if (c == 0) break; + if ((c == '&') && (str[1] == '#')) { + int val = xmlParseStringCharRef(ctxt, &str); + if (val != 0) { + COPY_BUF(0,buffer,nbchars,val); + } + if (nbchars > buffer_size - XML_PARSER_BUFFER_SIZE) { + growBuffer(buffer); + } + } else if ((c == '&') && (what & XML_SUBSTITUTE_REF)) { + if (xmlParserDebugEntities) + xmlGenericError(xmlGenericErrorContext, + "String decoding Entity Reference: %.30s\n", + str); + ent = xmlParseStringEntityRef(ctxt, &str); + if ((ent != NULL) && + (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) { + if (ent->content != NULL) { + COPY_BUF(0,buffer,nbchars,ent->content[0]); + if (nbchars > buffer_size - XML_PARSER_BUFFER_SIZE) { + growBuffer(buffer); + } + } else { + xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR, + "predefined entity has no content\n"); + } + } else if ((ent != NULL) && (ent->content != NULL)) { + xmlChar *rep; + + ctxt->depth++; + rep = xmlStringDecodeEntities(ctxt, ent->content, what, + 0, 0, 0); + ctxt->depth--; + if (rep != NULL) { + current = rep; + while (*current != 0) { /* non input consuming loop */ + buffer[nbchars++] = *current++; + if (nbchars > + buffer_size - XML_PARSER_BUFFER_SIZE) { + growBuffer(buffer); + } + } + xmlFree(rep); + } + } else if (ent != NULL) { + int i = xmlStrlen(ent->name); + const xmlChar *cur = ent->name; + + buffer[nbchars++] = '&'; + if (nbchars > buffer_size - i - XML_PARSER_BUFFER_SIZE) { + growBuffer(buffer); + } + for (;i > 0;i--) + buffer[nbchars++] = *cur++; + buffer[nbchars++] = ';'; + } + } else if (c == '%' && (what & XML_SUBSTITUTE_PEREF)) { + if (xmlParserDebugEntities) + xmlGenericError(xmlGenericErrorContext, + "String decoding PE Reference: %.30s\n", str); + ent = xmlParseStringPEReference(ctxt, &str); + if (ent != NULL) { + xmlChar *rep; + + ctxt->depth++; + rep = xmlStringDecodeEntities(ctxt, ent->content, what, + 0, 0, 0); + ctxt->depth--; + if (rep != NULL) { + current = rep; + while (*current != 0) { /* non input consuming loop */ + buffer[nbchars++] = *current++; + if (nbchars > + buffer_size - XML_PARSER_BUFFER_SIZE) { + growBuffer(buffer); + } + } + xmlFree(rep); + } + } + } else { + COPY_BUF(l,buffer,nbchars,c); + str += l; + if (nbchars > buffer_size - XML_PARSER_BUFFER_SIZE) { + growBuffer(buffer); + } + } + if (str < last) + c = CUR_SCHAR(str, l); + else + c = 0; + } + buffer[nbchars++] = 0; + return(buffer); + +mem_error: + xmlErrMemory(ctxt, NULL); + return(NULL); +} + +/** + * xmlStringDecodeEntities: + * @ctxt: the parser context + * @str: the input string + * @what: combination of XML_SUBSTITUTE_REF and XML_SUBSTITUTE_PEREF + * @end: an end marker xmlChar, 0 if none + * @end2: an end marker xmlChar, 0 if none + * @end3: an end marker xmlChar, 0 if none + * + * Takes a entity string content and process to do the adequate substitutions. + * + * [67] Reference ::= EntityRef | CharRef + * + * [69] PEReference ::= '%' Name ';' + * + * Returns A newly allocated string with the substitution done. The caller + * must deallocate it ! + */ +xmlChar * +xmlStringDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int what, + xmlChar end, xmlChar end2, xmlChar end3) { + if ((ctxt == NULL) || (str == NULL)) return(NULL); + return(xmlStringLenDecodeEntities(ctxt, str, xmlStrlen(str), what, + end, end2, end3)); +} + +/************************************************************************ + * * + * Commodity functions, cleanup needed ? * + * * + ************************************************************************/ + +/** + * areBlanks: + * @ctxt: an XML parser context + * @str: a xmlChar * + * @len: the size of @str + * @blank_chars: we know the chars are blanks + * + * Is this a sequence of blank chars that one can ignore ? + * + * Returns 1 if ignorable 0 otherwise. + */ + +static int areBlanks(xmlParserCtxtPtr ctxt, const xmlChar *str, int len, + int blank_chars) { + int i, ret; + xmlNodePtr lastChild; + + /* + * Don't spend time trying to differentiate them, the same callback is + * used ! + */ + if (ctxt->sax->ignorableWhitespace == ctxt->sax->characters) + return(0); + + /* + * Check for xml:space value. + */ + if ((ctxt->space == NULL) || (*(ctxt->space) == 1) || + (*(ctxt->space) == -2)) + return(0); + + /* + * Check that the string is made of blanks + */ + if (blank_chars == 0) { + for (i = 0;i < len;i++) + if (!(IS_BLANK_CH(str[i]))) return(0); + } + + /* + * Look if the element is mixed content in the DTD if available + */ + if (ctxt->node == NULL) return(0); + if (ctxt->myDoc != NULL) { + ret = xmlIsMixedElement(ctxt->myDoc, ctxt->node->name); + if (ret == 0) return(1); + if (ret == 1) return(0); + } + + /* + * Otherwise, heuristic :-\ + */ + if ((RAW != '<') && (RAW != 0xD)) return(0); + if ((ctxt->node->children == NULL) && + (RAW == '<') && (NXT(1) == '/')) return(0); + + lastChild = xmlGetLastChild(ctxt->node); + if (lastChild == NULL) { + if ((ctxt->node->type != XML_ELEMENT_NODE) && + (ctxt->node->content != NULL)) return(0); + } else if (xmlNodeIsText(lastChild)) + return(0); + else if ((ctxt->node->children != NULL) && + (xmlNodeIsText(ctxt->node->children))) + return(0); + return(1); +} + +/************************************************************************ + * * + * Extra stuff for namespace support * + * Relates to http://www.w3.org/TR/WD-xml-names * + * * + ************************************************************************/ + +/** + * xmlSplitQName: + * @ctxt: an XML parser context + * @name: an XML parser context + * @prefix: a xmlChar ** + * + * parse an UTF8 encoded XML qualified name string + * + * [NS 5] QName ::= (Prefix ':')? LocalPart + * + * [NS 6] Prefix ::= NCName + * + * [NS 7] LocalPart ::= NCName + * + * Returns the local part, and prefix is updated + * to get the Prefix if any. + */ + +xmlChar * +xmlSplitQName(xmlParserCtxtPtr ctxt, const xmlChar *name, xmlChar **prefix) { + xmlChar buf[XML_MAX_NAMELEN + 5]; + xmlChar *buffer = NULL; + int len = 0; + int max = XML_MAX_NAMELEN; + xmlChar *ret = NULL; + const xmlChar *cur = name; + int c; + + if (prefix == NULL) return(NULL); + *prefix = NULL; + + if (cur == NULL) return(NULL); + +#ifndef XML_XML_NAMESPACE + /* xml: prefix is not really a namespace */ + if ((cur[0] == 'x') && (cur[1] == 'm') && + (cur[2] == 'l') && (cur[3] == ':')) + return(xmlStrdup(name)); +#endif + + /* nasty but well=formed */ + if (cur[0] == ':') + return(xmlStrdup(name)); + + c = *cur++; + while ((c != 0) && (c != ':') && (len < max)) { /* tested bigname.xml */ + buf[len++] = c; + c = *cur++; + } + if (len >= max) { + /* + * Okay someone managed to make a huge name, so he's ready to pay + * for the processing speed. + */ + max = len * 2; + + buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar)); + if (buffer == NULL) { + xmlErrMemory(ctxt, NULL); + return(NULL); + } + memcpy(buffer, buf, len); + while ((c != 0) && (c != ':')) { /* tested bigname.xml */ + if (len + 10 > max) { + xmlChar *tmp; + + max *= 2; + tmp = (xmlChar *) xmlRealloc(buffer, + max * sizeof(xmlChar)); + if (tmp == NULL) { + xmlFree(tmp); + xmlErrMemory(ctxt, NULL); + return(NULL); + } + buffer = tmp; + } + buffer[len++] = c; + c = *cur++; + } + buffer[len] = 0; + } + + if ((c == ':') && (*cur == 0)) { + if (buffer != NULL) + xmlFree(buffer); + *prefix = NULL; + return(xmlStrdup(name)); + } + + if (buffer == NULL) + ret = xmlStrndup(buf, len); + else { + ret = buffer; + buffer = NULL; + max = XML_MAX_NAMELEN; + } + + + if (c == ':') { + c = *cur; + *prefix = ret; + if (c == 0) { + return(xmlStrndup(BAD_CAST "", 0)); + } + len = 0; + + /* + * Check that the first character is proper to start + * a new name + */ + if (!(((c >= 0x61) && (c <= 0x7A)) || + ((c >= 0x41) && (c <= 0x5A)) || + (c == '_') || (c == ':'))) { + int l; + int first = CUR_SCHAR(cur, l); + + if (!IS_LETTER(first) && (first != '_')) { + xmlFatalErrMsgStr(ctxt, XML_NS_ERR_QNAME, + "Name %s is not XML Namespace compliant\n", + name); + } + } + cur++; + + while ((c != 0) && (len < max)) { /* tested bigname2.xml */ + buf[len++] = c; + c = *cur++; + } + if (len >= max) { + /* + * Okay someone managed to make a huge name, so he's ready to pay + * for the processing speed. + */ + max = len * 2; + + buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar)); + if (buffer == NULL) { + xmlErrMemory(ctxt, NULL); + return(NULL); + } + memcpy(buffer, buf, len); + while (c != 0) { /* tested bigname2.xml */ + if (len + 10 > max) { + xmlChar *tmp; + + max *= 2; + tmp = (xmlChar *) xmlRealloc(buffer, + max * sizeof(xmlChar)); + if (tmp == NULL) { + xmlErrMemory(ctxt, NULL); + xmlFree(buffer); + return(NULL); + } + buffer = tmp; + } + buffer[len++] = c; + c = *cur++; + } + buffer[len] = 0; + } + + if (buffer == NULL) + ret = xmlStrndup(buf, len); + else { + ret = buffer; + } + } + + return(ret); +} + +/************************************************************************ + * * + * The parser itself * + * Relates to http://www.w3.org/TR/REC-xml * + * * + ************************************************************************/ + +static const xmlChar * xmlParseNameComplex(xmlParserCtxtPtr ctxt); +static xmlChar * xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, + int *len, int *alloc, int normalize); + +/** + * xmlParseName: + * @ctxt: an XML parser context + * + * parse an XML name. + * + * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' | + * CombiningChar | Extender + * + * [5] Name ::= (Letter | '_' | ':') (NameChar)* + * + * [6] Names ::= Name (#x20 Name)* + * + * Returns the Name parsed or NULL + */ + +const xmlChar * +xmlParseName(xmlParserCtxtPtr ctxt) { + const xmlChar *in; + const xmlChar *ret; + int count = 0; + + GROW; + + /* + * Accelerator for simple ASCII names + */ + in = ctxt->input->cur; + if (((*in >= 0x61) && (*in <= 0x7A)) || + ((*in >= 0x41) && (*in <= 0x5A)) || + (*in == '_') || (*in == ':')) { + in++; + while (((*in >= 0x61) && (*in <= 0x7A)) || + ((*in >= 0x41) && (*in <= 0x5A)) || + ((*in >= 0x30) && (*in <= 0x39)) || + (*in == '_') || (*in == '-') || + (*in == ':') || (*in == '.')) + in++; + if ((*in > 0) && (*in < 0x80)) { + count = in - ctxt->input->cur; + ret = xmlDictLookup(ctxt->dict, ctxt->input->cur, count); + ctxt->input->cur = in; + ctxt->nbChars += count; + ctxt->input->col += count; + if (ret == NULL) + xmlErrMemory(ctxt, NULL); + return(ret); + } + } + return(xmlParseNameComplex(ctxt)); +} + +/** + * xmlParseNameAndCompare: + * @ctxt: an XML parser context + * + * parse an XML name and compares for match + * (specialized for endtag parsing) + * + * Returns NULL for an illegal name, (xmlChar*) 1 for success + * and the name for mismatch + */ + +static const xmlChar * +xmlParseNameAndCompare(xmlParserCtxtPtr ctxt, xmlChar const *other) { + register const xmlChar *cmp = other; + register const xmlChar *in; + const xmlChar *ret; + + GROW; + + in = ctxt->input->cur; + while (*in != 0 && *in == *cmp) { + ++in; + ++cmp; + ctxt->input->col++; + } + if (*cmp == 0 && (*in == '>' || IS_BLANK_CH (*in))) { + /* success */ + ctxt->input->cur = in; + return (const xmlChar*) 1; + } + /* failure (or end of input buffer), check with full function */ + ret = xmlParseName (ctxt); + /* strings coming from the dictionnary direct compare possible */ + if (ret == other) { + return (const xmlChar*) 1; + } + return ret; +} + +static const xmlChar * +xmlParseNameComplex(xmlParserCtxtPtr ctxt) { + int len = 0, l; + int c; + int count = 0; + + /* + * Handler for more complex cases + */ + GROW; + c = CUR_CHAR(l); + if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */ + (!IS_LETTER(c) && (c != '_') && + (c != ':'))) { + return(NULL); + } + + while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */ + ((IS_LETTER(c)) || (IS_DIGIT(c)) || + (c == '.') || (c == '-') || + (c == '_') || (c == ':') || + (IS_COMBINING(c)) || + (IS_EXTENDER(c)))) { + if (count++ > 100) { + count = 0; + GROW; + } + len += l; + NEXTL(l); + c = CUR_CHAR(l); + } + if ((*ctxt->input->cur == '\n') && (ctxt->input->cur[-1] == '\r')) + return(xmlDictLookup(ctxt->dict, ctxt->input->cur - (len + 1), len)); + return(xmlDictLookup(ctxt->dict, ctxt->input->cur - len, len)); +} + +/** + * xmlParseStringName: + * @ctxt: an XML parser context + * @str: a pointer to the string pointer (IN/OUT) + * + * parse an XML name. + * + * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' | + * CombiningChar | Extender + * + * [5] Name ::= (Letter | '_' | ':') (NameChar)* + * + * [6] Names ::= Name (#x20 Name)* + * + * Returns the Name parsed or NULL. The @str pointer + * is updated to the current location in the string. + */ + +static xmlChar * +xmlParseStringName(xmlParserCtxtPtr ctxt, const xmlChar** str) { + xmlChar buf[XML_MAX_NAMELEN + 5]; + const xmlChar *cur = *str; + int len = 0, l; + int c; + + c = CUR_SCHAR(cur, l); + if (!IS_LETTER(c) && (c != '_') && + (c != ':')) { + return(NULL); + } + + while ((IS_LETTER(c)) || (IS_DIGIT(c)) || /* test bigentname.xml */ + (c == '.') || (c == '-') || + (c == '_') || (c == ':') || + (IS_COMBINING(c)) || + (IS_EXTENDER(c))) { + COPY_BUF(l,buf,len,c); + cur += l; + c = CUR_SCHAR(cur, l); + if (len >= XML_MAX_NAMELEN) { /* test bigentname.xml */ + /* + * Okay someone managed to make a huge name, so he's ready to pay + * for the processing speed. + */ + xmlChar *buffer; + int max = len * 2; + + buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar)); + if (buffer == NULL) { + xmlErrMemory(ctxt, NULL); + return(NULL); + } + memcpy(buffer, buf, len); + while ((IS_LETTER(c)) || (IS_DIGIT(c)) || + /* test bigentname.xml */ + (c == '.') || (c == '-') || + (c == '_') || (c == ':') || + (IS_COMBINING(c)) || + (IS_EXTENDER(c))) { + if (len + 10 > max) { + xmlChar *tmp; + max *= 2; + tmp = (xmlChar *) xmlRealloc(buffer, + max * sizeof(xmlChar)); + if (tmp == NULL) { + xmlErrMemory(ctxt, NULL); + xmlFree(buffer); + return(NULL); + } + buffer = tmp; + } + COPY_BUF(l,buffer,len,c); + cur += l; + c = CUR_SCHAR(cur, l); + } + buffer[len] = 0; + *str = cur; + return(buffer); + } + } + *str = cur; + return(xmlStrndup(buf, len)); +} + +/** + * xmlParseNmtoken: + * @ctxt: an XML parser context + * + * parse an XML Nmtoken. + * + * [7] Nmtoken ::= (NameChar)+ + * + * [8] Nmtokens ::= Nmtoken (#x20 Nmtoken)* + * + * Returns the Nmtoken parsed or NULL + */ + +xmlChar * +xmlParseNmtoken(xmlParserCtxtPtr ctxt) { + xmlChar buf[XML_MAX_NAMELEN + 5]; + int len = 0, l; + int c; + int count = 0; + + GROW; + c = CUR_CHAR(l); + + while ((IS_LETTER(c)) || (IS_DIGIT(c)) || /* test bigtoken.xml */ + (c == '.') || (c == '-') || + (c == '_') || (c == ':') || + (IS_COMBINING(c)) || + (IS_EXTENDER(c))) { + if (count++ > 100) { + count = 0; + GROW; + } + COPY_BUF(l,buf,len,c); + NEXTL(l); + c = CUR_CHAR(l); + if (len >= XML_MAX_NAMELEN) { + /* + * Okay someone managed to make a huge token, so he's ready to pay + * for the processing speed. + */ + xmlChar *buffer; + int max = len * 2; + + buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar)); + if (buffer == NULL) { + xmlErrMemory(ctxt, NULL); + return(NULL); + } + memcpy(buffer, buf, len); + while ((IS_LETTER(c)) || (IS_DIGIT(c)) || /* test bigtoken.xml */ + (c == '.') || (c == '-') || + (c == '_') || (c == ':') || + (IS_COMBINING(c)) || + (IS_EXTENDER(c))) { + if (count++ > 100) { + count = 0; + GROW; + } + if (len + 10 > max) { + xmlChar *tmp; + + max *= 2; + tmp = (xmlChar *) xmlRealloc(buffer, + max * sizeof(xmlChar)); + if (tmp == NULL) { + xmlErrMemory(ctxt, NULL); + xmlFree(buffer); + return(NULL); + } + buffer = tmp; + } + COPY_BUF(l,buffer,len,c); + NEXTL(l); + c = CUR_CHAR(l); + } + buffer[len] = 0; + return(buffer); + } + } + if (len == 0) + return(NULL); + return(xmlStrndup(buf, len)); +} + +/** + * xmlParseEntityValue: + * @ctxt: an XML parser context + * @orig: if non-NULL store a copy of the original entity value + * + * parse a value for ENTITY declarations + * + * [9] EntityValue ::= '"' ([^%&"] | PEReference | Reference)* '"' | + * "'" ([^%&'] | PEReference | Reference)* "'" + * + * Returns the EntityValue parsed with reference substituted or NULL + */ + +xmlChar * +xmlParseEntityValue(xmlParserCtxtPtr ctxt, xmlChar **orig) { + xmlChar *buf = NULL; + int len = 0; + int size = XML_PARSER_BUFFER_SIZE; + int c, l; + xmlChar stop; + xmlChar *ret = NULL; + const xmlChar *cur = NULL; + xmlParserInputPtr input; + + if (RAW == '"') stop = '"'; + else if (RAW == '\'') stop = '\''; + else { + xmlFatalErr(ctxt, XML_ERR_ENTITY_NOT_STARTED, NULL); + return(NULL); + } + buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar)); + if (buf == NULL) { + xmlErrMemory(ctxt, NULL); + return(NULL); + } + + /* + * The content of the entity definition is copied in a buffer. + */ + + ctxt->instate = XML_PARSER_ENTITY_VALUE; + input = ctxt->input; + GROW; + NEXT; + c = CUR_CHAR(l); + /* + * NOTE: 4.4.5 Included in Literal + * When a parameter entity reference appears in a literal entity + * value, ... a single or double quote character in the replacement + * text is always treated as a normal data character and will not + * terminate the literal. + * In practice it means we stop the loop only when back at parsing + * the initial entity and the quote is found + */ + while ((IS_CHAR(c)) && ((c != stop) || /* checked */ + (ctxt->input != input))) { + if (len + 5 >= size) { + xmlChar *tmp; + + size *= 2; + tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar)); + if (tmp == NULL) { + xmlErrMemory(ctxt, NULL); + xmlFree(buf); + return(NULL); + } + buf = tmp; + } + COPY_BUF(l,buf,len,c); + NEXTL(l); + /* + * Pop-up of finished entities. + */ + while ((RAW == 0) && (ctxt->inputNr > 1)) /* non input consuming */ + xmlPopInput(ctxt); + + GROW; + c = CUR_CHAR(l); + if (c == 0) { + GROW; + c = CUR_CHAR(l); + } + } + buf[len] = 0; + + /* + * Raise problem w.r.t. '&' and '%' being used in non-entities + * reference constructs. Note Charref will be handled in + * xmlStringDecodeEntities() + */ + cur = buf; + while (*cur != 0) { /* non input consuming */ + if ((*cur == '%') || ((*cur == '&') && (cur[1] != '#'))) { + xmlChar *name; + xmlChar tmp = *cur; + + cur++; + name = xmlParseStringName(ctxt, &cur); + if ((name == NULL) || (*cur != ';')) { + xmlFatalErrMsgInt(ctxt, XML_ERR_ENTITY_CHAR_ERROR, + "EntityValue: '%c' forbidden except for entities references\n", + tmp); + } + if ((tmp == '%') && (ctxt->inSubset == 1) && + (ctxt->inputNr == 1)) { + xmlFatalErr(ctxt, XML_ERR_ENTITY_PE_INTERNAL, NULL); + } + if (name != NULL) + xmlFree(name); + if (*cur == 0) + break; + } + cur++; + } + + /* + * Then PEReference entities are substituted. + */ + if (c != stop) { + xmlFatalErr(ctxt, XML_ERR_ENTITY_NOT_FINISHED, NULL); + xmlFree(buf); + } else { + NEXT; + /* + * NOTE: 4.4.7 Bypassed + * When a general entity reference appears in the EntityValue in + * an entity declaration, it is bypassed and left as is. + * so XML_SUBSTITUTE_REF is not set here. + */ + ret = xmlStringDecodeEntities(ctxt, buf, XML_SUBSTITUTE_PEREF, + 0, 0, 0); + if (orig != NULL) + *orig = buf; + else + xmlFree(buf); + } + + return(ret); +} + +/** + * xmlParseAttValueComplex: + * @ctxt: an XML parser context + * @len: the resulting attribute len + * @normalize: wether to apply the inner normalization + * + * parse a value for an attribute, this is the fallback function + * of xmlParseAttValue() when the attribute parsing requires handling + * of non-ASCII characters, or normalization compaction. + * + * Returns the AttValue parsed or NULL. The value has to be freed by the caller. + */ +static xmlChar * +xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) { + xmlChar limit = 0; + xmlChar *buf = NULL; + int len = 0; + int buf_size = 0; + int c, l, in_space = 0; + xmlChar *current = NULL; + xmlEntityPtr ent; + + if (NXT(0) == '"') { + ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE; + limit = '"'; + NEXT; + } else if (NXT(0) == '\'') { + limit = '\''; + ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE; + NEXT; + } else { + xmlFatalErr(ctxt, XML_ERR_ATTRIBUTE_NOT_STARTED, NULL); + return(NULL); + } + + /* + * allocate a translation buffer. + */ + buf_size = XML_PARSER_BUFFER_SIZE; + buf = (xmlChar *) xmlMallocAtomic(buf_size * sizeof(xmlChar)); + if (buf == NULL) goto mem_error; + + /* + * OK loop until we reach one of the ending char or a size limit. + */ + c = CUR_CHAR(l); + while ((NXT(0) != limit) && /* checked */ + (c != '<')) { + if (c == 0) break; + if (c == '&') { + in_space = 0; + if (NXT(1) == '#') { + int val = xmlParseCharRef(ctxt); + + if (val == '&') { + if (ctxt->replaceEntities) { + if (len > buf_size - 10) { + growBuffer(buf); + } + buf[len++] = '&'; + } else { + /* + * The reparsing will be done in xmlStringGetNodeList() + * called by the attribute() function in SAX.c + */ + if (len > buf_size - 10) { + growBuffer(buf); + } + buf[len++] = '&'; + buf[len++] = '#'; + buf[len++] = '3'; + buf[len++] = '8'; + buf[len++] = ';'; + } + } else { + if (len > buf_size - 10) { + growBuffer(buf); + } + len += xmlCopyChar(0, &buf[len], val); + } + } else { + ent = xmlParseEntityRef(ctxt); + if ((ent != NULL) && + (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) { + if (len > buf_size - 10) { + growBuffer(buf); + } + if ((ctxt->replaceEntities == 0) && + (ent->content[0] == '&')) { + buf[len++] = '&'; + buf[len++] = '#'; + buf[len++] = '3'; + buf[len++] = '8'; + buf[len++] = ';'; + } else { + buf[len++] = ent->content[0]; + } + } else if ((ent != NULL) && + (ctxt->replaceEntities != 0)) { + xmlChar *rep; + + if (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) { + rep = xmlStringDecodeEntities(ctxt, ent->content, + XML_SUBSTITUTE_REF, + 0, 0, 0); + if (rep != NULL) { + current = rep; + while (*current != 0) { /* non input consuming */ + buf[len++] = *current++; + if (len > buf_size - 10) { + growBuffer(buf); + } + } + xmlFree(rep); + } + } else { + if (len > buf_size - 10) { + growBuffer(buf); + } + if (ent->content != NULL) + buf[len++] = ent->content[0]; + } + } else if (ent != NULL) { + int i = xmlStrlen(ent->name); + const xmlChar *cur = ent->name; + + /* + * This may look absurd but is needed to detect + * entities problems + */ + if ((ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) && + (ent->content != NULL)) { + xmlChar *rep; + rep = xmlStringDecodeEntities(ctxt, ent->content, + XML_SUBSTITUTE_REF, 0, 0, 0); + if (rep != NULL) + xmlFree(rep); + } + + /* + * Just output the reference + */ + buf[len++] = '&'; + if (len > buf_size - i - 10) { + growBuffer(buf); + } + for (;i > 0;i--) + buf[len++] = *cur++; + buf[len++] = ';'; + } + } + } else { + if ((c == 0x20) || (c == 0xD) || (c == 0xA) || (c == 0x9)) { + if ((len != 0) || (!normalize)) { + if ((!normalize) || (!in_space)) { + COPY_BUF(l,buf,len,0x20); + if (len > buf_size - 10) { + growBuffer(buf); + } + } + in_space = 1; + } + } else { + in_space = 0; + COPY_BUF(l,buf,len,c); + if (len > buf_size - 10) { + growBuffer(buf); + } + } + NEXTL(l); + } + GROW; + c = CUR_CHAR(l); + } + if ((in_space) && (normalize)) { + while (buf[len - 1] == 0x20) len--; + } + buf[len] = 0; + if (RAW == '<') { + xmlFatalErr(ctxt, XML_ERR_LT_IN_ATTRIBUTE, NULL); + } else if (RAW != limit) { + xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED, + "AttValue: ' expected\n"); + } else + NEXT; + if (attlen != NULL) *attlen = len; + return(buf); + +mem_error: + xmlErrMemory(ctxt, NULL); + return(NULL); +} + +/** + * xmlParseAttValue: + * @ctxt: an XML parser context + * + * parse a value for an attribute + * Note: the parser won't do substitution of entities here, this + * will be handled later in xmlStringGetNodeList + * + * [10] AttValue ::= '"' ([^<&"] | Reference)* '"' | + * "'" ([^<&'] | Reference)* "'" + * + * 3.3.3 Attribute-Value Normalization: + * Before the value of an attribute is passed to the application or + * checked for validity, the XML processor must normalize it as follows: + * - a character reference is processed by appending the referenced + * character to the attribute value + * - an entity reference is processed by recursively processing the + * replacement text of the entity + * - a whitespace character (#x20, #xD, #xA, #x9) is processed by + * appending #x20 to the normalized value, except that only a single + * #x20 is appended for a "#xD#xA" sequence that is part of an external + * parsed entity or the literal entity value of an internal parsed entity + * - other characters are processed by appending them to the normalized value + * If the declared value is not CDATA, then the XML processor must further + * process the normalized attribute value by discarding any leading and + * trailing space (#x20) characters, and by replacing sequences of space + * (#x20) characters by a single space (#x20) character. + * All attributes for which no declaration has been read should be treated + * by a non-validating parser as if declared CDATA. + * + * Returns the AttValue parsed or NULL. The value has to be freed by the caller. + */ + + +xmlChar * +xmlParseAttValue(xmlParserCtxtPtr ctxt) { + if ((ctxt == NULL) || (ctxt->input == NULL)) return(NULL); + return(xmlParseAttValueInternal(ctxt, NULL, NULL, 0)); +} + +/** + * xmlParseSystemLiteral: + * @ctxt: an XML parser context + * + * parse an XML Literal + * + * [11] SystemLiteral ::= ('"' [^"]* '"') | ("'" [^']* "'") + * + * Returns the SystemLiteral parsed or NULL + */ + +xmlChar * +xmlParseSystemLiteral(xmlParserCtxtPtr ctxt) { + xmlChar *buf = NULL; + int len = 0; + int size = XML_PARSER_BUFFER_SIZE; + int cur, l; + xmlChar stop; + int state = ctxt->instate; + int count = 0; + + SHRINK; + if (RAW == '"') { + NEXT; + stop = '"'; + } else if (RAW == '\'') { + NEXT; + stop = '\''; + } else { + xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_STARTED, NULL); + return(NULL); + } + + buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar)); + if (buf == NULL) { + xmlErrMemory(ctxt, NULL); + return(NULL); + } + ctxt->instate = XML_PARSER_SYSTEM_LITERAL; + cur = CUR_CHAR(l); + while ((IS_CHAR(cur)) && (cur != stop)) { /* checked */ + if (len + 5 >= size) { + xmlChar *tmp; + + size *= 2; + tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar)); + if (tmp == NULL) { + xmlFree(buf); + xmlErrMemory(ctxt, NULL); + ctxt->instate = (xmlParserInputState) state; + return(NULL); + } + buf = tmp; + } + count++; + if (count > 50) { + GROW; + count = 0; + } + COPY_BUF(l,buf,len,cur); + NEXTL(l); + cur = CUR_CHAR(l); + if (cur == 0) { + GROW; + SHRINK; + cur = CUR_CHAR(l); + } + } + buf[len] = 0; + ctxt->instate = (xmlParserInputState) state; + if (!IS_CHAR(cur)) { + xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED, NULL); + } else { + NEXT; + } + return(buf); +} + +/** + * xmlParsePubidLiteral: + * @ctxt: an XML parser context + * + * parse an XML public literal + * + * [12] PubidLiteral ::= '"' PubidChar* '"' | "'" (PubidChar - "'")* "'" + * + * Returns the PubidLiteral parsed or NULL. + */ + +xmlChar * +xmlParsePubidLiteral(xmlParserCtxtPtr ctxt) { + xmlChar *buf = NULL; + int len = 0; + int size = XML_PARSER_BUFFER_SIZE; + xmlChar cur; + xmlChar stop; + int count = 0; + xmlParserInputState oldstate = ctxt->instate; + + SHRINK; + if (RAW == '"') { + NEXT; + stop = '"'; + } else if (RAW == '\'') { + NEXT; + stop = '\''; + } else { + xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_STARTED, NULL); + return(NULL); + } + buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar)); + if (buf == NULL) { + xmlErrMemory(ctxt, NULL); + return(NULL); + } + ctxt->instate = XML_PARSER_PUBLIC_LITERAL; + cur = CUR; + while ((IS_PUBIDCHAR_CH(cur)) && (cur != stop)) { /* checked */ + if (len + 1 >= size) { + xmlChar *tmp; + + size *= 2; + tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar)); + if (tmp == NULL) { + xmlErrMemory(ctxt, NULL); + xmlFree(buf); + return(NULL); + } + buf = tmp; + } + buf[len++] = cur; + count++; + if (count > 50) { + GROW; + count = 0; + } + NEXT; + cur = CUR; + if (cur == 0) { + GROW; + SHRINK; + cur = CUR; + } + } + buf[len] = 0; + if (cur != stop) { + xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED, NULL); + } else { + NEXT; + } + ctxt->instate = oldstate; + return(buf); +} + +void xmlParseCharDataComplex(xmlParserCtxtPtr ctxt, int cdata); + +/* + * used for the test in the inner loop of the char data testing + */ +static const unsigned char test_char_data[256] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9, CR/LF separated */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x00, 0x27, /* & */ + 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3A, 0x3B, 0x00, 0x3D, 0x3E, 0x3F, /* < */ + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x00, 0x5E, 0x5F, /* ] */ + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* non-ascii */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +/** + * xmlParseCharData: + * @ctxt: an XML parser context + * @cdata: int indicating whether we are within a CDATA section + * + * parse a CharData section. + * if we are within a CDATA section ']]>' marks an end of section. + * + * The right angle bracket (>) may be represented using the string ">", + * and must, for compatibility, be escaped using ">" or a character + * reference when it appears in the string "]]>" in content, when that + * string is not marking the end of a CDATA section. + * + * [14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*) + */ + +void +xmlParseCharData(xmlParserCtxtPtr ctxt, int cdata) { + const xmlChar *in; + int nbchar = 0; + int line = ctxt->input->line; + int col = ctxt->input->col; + int ccol; + + SHRINK; + GROW; + /* + * Accelerated common case where input don't need to be + * modified before passing it to the handler. + */ + if (!cdata) { + in = ctxt->input->cur; + do { +get_more_space: + while (*in == 0x20) in++; + if (*in == 0xA) { + do { + ctxt->input->line++; ctxt->input->col = 1; + in++; + } while (*in == 0xA); + goto get_more_space; + } + if (*in == '<') { + nbchar = in - ctxt->input->cur; + if (nbchar > 0) { + const xmlChar *tmp = ctxt->input->cur; + ctxt->input->cur = in; + + if ((ctxt->sax != NULL) && + (ctxt->sax->ignorableWhitespace != + ctxt->sax->characters)) { + if (areBlanks(ctxt, tmp, nbchar, 1)) { + if (ctxt->sax->ignorableWhitespace != NULL) + ctxt->sax->ignorableWhitespace(ctxt->userData, + tmp, nbchar); + } else { + if (ctxt->sax->characters != NULL) + ctxt->sax->characters(ctxt->userData, + tmp, nbchar); + if (*ctxt->space == -1) + *ctxt->space = -2; + } + } else if ((ctxt->sax != NULL) && + (ctxt->sax->characters != NULL)) { + ctxt->sax->characters(ctxt->userData, + tmp, nbchar); + } + } + return; + } + +get_more: + ccol = ctxt->input->col; + while (test_char_data[*in]) { + in++; + ccol++; + } + ctxt->input->col = ccol; + if (*in == 0xA) { + do { + ctxt->input->line++; ctxt->input->col = 1; + in++; + } while (*in == 0xA); + goto get_more; + } + if (*in == ']') { + if ((in[1] == ']') && (in[2] == '>')) { + xmlFatalErr(ctxt, XML_ERR_MISPLACED_CDATA_END, NULL); + ctxt->input->cur = in; + return; + } + in++; + ctxt->input->col++; + goto get_more; + } + nbchar = in - ctxt->input->cur; + if (nbchar > 0) { + if ((ctxt->sax != NULL) && + (ctxt->sax->ignorableWhitespace != + ctxt->sax->characters) && + (IS_BLANK_CH(*ctxt->input->cur))) { + const xmlChar *tmp = ctxt->input->cur; + ctxt->input->cur = in; + + if (areBlanks(ctxt, tmp, nbchar, 0)) { + if (ctxt->sax->ignorableWhitespace != NULL) + ctxt->sax->ignorableWhitespace(ctxt->userData, + tmp, nbchar); + } else { + if (ctxt->sax->characters != NULL) + ctxt->sax->characters(ctxt->userData, + tmp, nbchar); + if (*ctxt->space == -1) + *ctxt->space = -2; + } + line = ctxt->input->line; + col = ctxt->input->col; + } else if (ctxt->sax != NULL) { + if (ctxt->sax->characters != NULL) + ctxt->sax->characters(ctxt->userData, + ctxt->input->cur, nbchar); + line = ctxt->input->line; + col = ctxt->input->col; + } + } + ctxt->input->cur = in; + if (*in == 0xD) { + in++; + if (*in == 0xA) { + ctxt->input->cur = in; + in++; + ctxt->input->line++; ctxt->input->col = 1; + continue; /* while */ + } + in--; + } + if (*in == '<') { + return; + } + if (*in == '&') { + return; + } + SHRINK; + GROW; + in = ctxt->input->cur; + } while (((*in >= 0x20) && (*in <= 0x7F)) || (*in == 0x09)); + nbchar = 0; + } + ctxt->input->line = line; + ctxt->input->col = col; + xmlParseCharDataComplex(ctxt, cdata); +} + +/** + * xmlParseCharDataComplex: + * @ctxt: an XML parser context + * @cdata: int indicating whether we are within a CDATA section + * + * parse a CharData section.this is the fallback function + * of xmlParseCharData() when the parsing requires handling + * of non-ASCII characters. + */ +void +xmlParseCharDataComplex(xmlParserCtxtPtr ctxt, int cdata) { + xmlChar buf[XML_PARSER_BIG_BUFFER_SIZE + 5]; + int nbchar = 0; + int cur, l; + int count = 0; + + SHRINK; + GROW; + cur = CUR_CHAR(l); + while ((cur != '<') && /* checked */ + (cur != '&') && + (IS_CHAR(cur))) /* test also done in xmlCurrentChar() */ { + if ((cur == ']') && (NXT(1) == ']') && + (NXT(2) == '>')) { + if (cdata) break; + else { + xmlFatalErr(ctxt, XML_ERR_MISPLACED_CDATA_END, NULL); + } + } + COPY_BUF(l,buf,nbchar,cur); + if (nbchar >= XML_PARSER_BIG_BUFFER_SIZE) { + buf[nbchar] = 0; + + /* + * OK the segment is to be consumed as chars. + */ + if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) { + if (areBlanks(ctxt, buf, nbchar, 0)) { + if (ctxt->sax->ignorableWhitespace != NULL) + ctxt->sax->ignorableWhitespace(ctxt->userData, + buf, nbchar); + } else { + if (ctxt->sax->characters != NULL) + ctxt->sax->characters(ctxt->userData, buf, nbchar); + if ((ctxt->sax->characters != + ctxt->sax->ignorableWhitespace) && + (*ctxt->space == -1)) + *ctxt->space = -2; + } + } + nbchar = 0; + } + count++; + if (count > 50) { + GROW; + count = 0; + } + NEXTL(l); + cur = CUR_CHAR(l); + } + if (nbchar != 0) { + buf[nbchar] = 0; + /* + * OK the segment is to be consumed as chars. + */ + if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) { + if (areBlanks(ctxt, buf, nbchar, 0)) { + if (ctxt->sax->ignorableWhitespace != NULL) + ctxt->sax->ignorableWhitespace(ctxt->userData, buf, nbchar); + } else { + if (ctxt->sax->characters != NULL) + ctxt->sax->characters(ctxt->userData, buf, nbchar); + if ((ctxt->sax->characters != ctxt->sax->ignorableWhitespace) && + (*ctxt->space == -1)) + *ctxt->space = -2; + } + } + } + if ((cur != 0) && (!IS_CHAR(cur))) { + /* Generate the error and skip the offending character */ + xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR, + "PCDATA invalid Char value %d\n", + cur); + NEXTL(l); + } +} + +/** + * xmlParseExternalID: + * @ctxt: an XML parser context + * @publicID: a xmlChar** receiving PubidLiteral + * @strict: indicate whether we should restrict parsing to only + * production [75], see NOTE below + * + * Parse an External ID or a Public ID + * + * NOTE: Productions [75] and [83] interact badly since [75] can generate + * 'PUBLIC' S PubidLiteral S SystemLiteral + * + * [75] ExternalID ::= 'SYSTEM' S SystemLiteral + * | 'PUBLIC' S PubidLiteral S SystemLiteral + * + * [83] PublicID ::= 'PUBLIC' S PubidLiteral + * + * Returns the function returns SystemLiteral and in the second + * case publicID receives PubidLiteral, is strict is off + * it is possible to return NULL and have publicID set. + */ + +xmlChar * +xmlParseExternalID(xmlParserCtxtPtr ctxt, xmlChar **publicID, int strict) { + xmlChar *URI = NULL; + + SHRINK; + + *publicID = NULL; + if (CMP6(CUR_PTR, 'S', 'Y', 'S', 'T', 'E', 'M')) { + SKIP(6); + if (!IS_BLANK_CH(CUR)) { + xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED, + "Space required after 'SYSTEM'\n"); + } + SKIP_BLANKS; + URI = xmlParseSystemLiteral(ctxt); + if (URI == NULL) { + xmlFatalErr(ctxt, XML_ERR_URI_REQUIRED, NULL); + } + } else if (CMP6(CUR_PTR, 'P', 'U', 'B', 'L', 'I', 'C')) { + SKIP(6); + if (!IS_BLANK_CH(CUR)) { + xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED, + "Space required after 'PUBLIC'\n"); + } + SKIP_BLANKS; + *publicID = xmlParsePubidLiteral(ctxt); + if (*publicID == NULL) { + xmlFatalErr(ctxt, XML_ERR_PUBID_REQUIRED, NULL); + } + if (strict) { + /* + * We don't handle [83] so "S SystemLiteral" is required. + */ + if (!IS_BLANK_CH(CUR)) { + xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED, + "Space required after the Public Identifier\n"); + } + } else { + /* + * We handle [83] so we return immediately, if + * "S SystemLiteral" is not detected. From a purely parsing + * point of view that's a nice mess. + */ + const xmlChar *ptr; + GROW; + + ptr = CUR_PTR; + if (!IS_BLANK_CH(*ptr)) return(NULL); + + while (IS_BLANK_CH(*ptr)) ptr++; /* TODO: dangerous, fix ! */ + if ((*ptr != '\'') && (*ptr != '"')) return(NULL); + } + SKIP_BLANKS; + URI = xmlParseSystemLiteral(ctxt); + if (URI == NULL) { + xmlFatalErr(ctxt, XML_ERR_URI_REQUIRED, NULL); + } + } + return(URI); +} + +/** + * xmlParseCommentComplex: + * @ctxt: an XML parser context + * @buf: the already parsed part of the buffer + * @len: number of bytes filles in the buffer + * @size: allocated size of the buffer + * + * Skip an XML (SGML) comment + * The spec says that "For compatibility, the string "--" (double-hyphen) + * must not occur within comments. " + * This is the slow routine in case the accelerator for ascii didn't work + * + * [15] Comment ::= '' + */ +static void +xmlParseCommentComplex(xmlParserCtxtPtr ctxt, xmlChar *buf, int len, int size) { + int q, ql; + int r, rl; + int cur, l; + xmlParserInputPtr input = ctxt->input; + int count = 0; + + if (buf == NULL) { + len = 0; + size = XML_PARSER_BUFFER_SIZE; + buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar)); + if (buf == NULL) { + xmlErrMemory(ctxt, NULL); + return; + } + } + q = CUR_CHAR(ql); + if (q == 0) + goto not_terminated; + NEXTL(ql); + r = CUR_CHAR(rl); + if (r == 0) + goto not_terminated; + NEXTL(rl); + cur = CUR_CHAR(l); + if (cur == 0) + goto not_terminated; + while (IS_CHAR(cur) && /* checked */ + ((cur != '>') || + (r != '-') || (q != '-'))) { + if ((r == '-') && (q == '-')) { + xmlFatalErr(ctxt, XML_ERR_HYPHEN_IN_COMMENT, NULL); + } + if (len + 5 >= size) { + xmlChar *new_buf; + size *= 2; + new_buf = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar)); + if (new_buf == NULL) { + xmlFree (buf); + xmlErrMemory(ctxt, NULL); + return; + } + buf = new_buf; + } + COPY_BUF(ql,buf,len,q); + q = r; + ql = rl; + r = cur; + rl = l; + + count++; + if (count > 50) { + GROW; + count = 0; + } + NEXTL(l); + cur = CUR_CHAR(l); + if (cur == 0) { + SHRINK; + GROW; + cur = CUR_CHAR(l); + } + } + buf[len] = 0; + if (!IS_CHAR(cur)) { + xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED, + "Comment not terminated \n + * The spec says that "For compatibility, the string "--" (double-hyphen) + * must not occur within comments. " + * + * [15] Comment ::= '' + */ +void +xmlParseComment(xmlParserCtxtPtr ctxt) { + xmlChar *buf = NULL; + int size = XML_PARSER_BUFFER_SIZE; + int len = 0; + xmlParserInputState state; + const xmlChar *in; + int nbchar = 0, ccol; + + /* + * Check that there is a comment right here. + */ + if ((RAW != '<') || (NXT(1) != '!') || + (NXT(2) != '-') || (NXT(3) != '-')) return; + + state = ctxt->instate; + ctxt->instate = XML_PARSER_COMMENT; + SKIP(4); + SHRINK; + GROW; + + /* + * Accelerated common case where input don't need to be + * modified before passing it to the handler. + */ + in = ctxt->input->cur; + do { + if (*in == 0xA) { + do { + ctxt->input->line++; ctxt->input->col = 1; + in++; + } while (*in == 0xA); + } +get_more: + ccol = ctxt->input->col; + while (((*in > '-') && (*in <= 0x7F)) || + ((*in >= 0x20) && (*in < '-')) || + (*in == 0x09)) { + in++; + ccol++; + } + ctxt->input->col = ccol; + if (*in == 0xA) { + do { + ctxt->input->line++; ctxt->input->col = 1; + in++; + } while (*in == 0xA); + goto get_more; + } + nbchar = in - ctxt->input->cur; + /* + * save current set of data + */ + if (nbchar > 0) { + if ((ctxt->sax != NULL) && + (ctxt->sax->comment != NULL)) { + if (buf == NULL) { + if ((*in == '-') && (in[1] == '-')) + size = nbchar + 1; + else + size = XML_PARSER_BUFFER_SIZE + nbchar; + buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar)); + if (buf == NULL) { + xmlErrMemory(ctxt, NULL); + ctxt->instate = state; + return; + } + len = 0; + } else if (len + nbchar + 1 >= size) { + xmlChar *new_buf; + size += len + nbchar + XML_PARSER_BUFFER_SIZE; + new_buf = (xmlChar *) xmlRealloc(buf, + size * sizeof(xmlChar)); + if (new_buf == NULL) { + xmlFree (buf); + xmlErrMemory(ctxt, NULL); + ctxt->instate = state; + return; + } + buf = new_buf; + } + memcpy(&buf[len], ctxt->input->cur, nbchar); + len += nbchar; + buf[len] = 0; + } + } + ctxt->input->cur = in; + if (*in == 0xA) { + in++; + ctxt->input->line++; ctxt->input->col = 1; + } + if (*in == 0xD) { + in++; + if (*in == 0xA) { + ctxt->input->cur = in; + in++; + ctxt->input->line++; ctxt->input->col = 1; + continue; /* while */ + } + in--; + } + SHRINK; + GROW; + in = ctxt->input->cur; + if (*in == '-') { + if (in[1] == '-') { + if (in[2] == '>') { + SKIP(3); + if ((ctxt->sax != NULL) && (ctxt->sax->comment != NULL) && + (!ctxt->disableSAX)) { + if (buf != NULL) + ctxt->sax->comment(ctxt->userData, buf); + else + ctxt->sax->comment(ctxt->userData, BAD_CAST ""); + } + if (buf != NULL) + xmlFree(buf); + ctxt->instate = state; + return; + } + if (buf != NULL) + xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED, + "Comment not terminated \n"); + } + fprintf(output, ">\n"); + if (grammar->start == NULL) { + fprintf(output, " "); + } else { + fprintf(output, "\n"); + xmlRelaxNGDumpDefine(output, grammar->start); + fprintf(output, "\n"); + } + /* TODO ? Dump the defines ? */ + fprintf(output, "\n"); +} + +/** + * xmlRelaxNGDump: + * @output: the file output + * @schema: a schema structure + * + * Dump a RelaxNG structure back + */ +void +xmlRelaxNGDump(FILE * output, xmlRelaxNGPtr schema) +{ + if (output == NULL) + return; + if (schema == NULL) { + fprintf(output, "RelaxNG empty or failed to compile\n"); + return; + } + fprintf(output, "RelaxNG: "); + if (schema->doc == NULL) { + fprintf(output, "no document\n"); + } else if (schema->doc->URL != NULL) { + fprintf(output, "%s\n", schema->doc->URL); + } else { + fprintf(output, "\n"); + } + if (schema->topgrammar == NULL) { + fprintf(output, "RelaxNG has no top grammar\n"); + return; + } + xmlRelaxNGDumpGrammar(output, schema->topgrammar, 1); +} + +/** + * xmlRelaxNGDumpTree: + * @output: the file output + * @schema: a schema structure + * + * Dump the transformed RelaxNG tree. + */ +void +xmlRelaxNGDumpTree(FILE * output, xmlRelaxNGPtr schema) +{ + if (output == NULL) + return; + if (schema == NULL) { + fprintf(output, "RelaxNG empty or failed to compile\n"); + return; + } + if (schema->doc == NULL) { + fprintf(output, "no document\n"); + } else { + xmlDocDump(output, schema->doc); + } +} +#endif /* LIBXML_OUTPUT_ENABLED */ + +/************************************************************************ + * * + * Validation of compiled content * + * * + ************************************************************************/ +static int xmlRelaxNGValidateDefinition(xmlRelaxNGValidCtxtPtr ctxt, + xmlRelaxNGDefinePtr define); + +/** + * xmlRelaxNGValidateCompiledCallback: + * @exec: the regular expression instance + * @token: the token which matched + * @transdata: callback data, the define for the subelement if available + @ @inputdata: callback data, the Relax NG validation context + * + * Handle the callback and if needed validate the element children. + */ +static void +xmlRelaxNGValidateCompiledCallback(xmlRegExecCtxtPtr exec ATTRIBUTE_UNUSED, + const xmlChar * token, + void *transdata, void *inputdata) +{ + xmlRelaxNGValidCtxtPtr ctxt = (xmlRelaxNGValidCtxtPtr) inputdata; + xmlRelaxNGDefinePtr define = (xmlRelaxNGDefinePtr) transdata; + int ret; + +#ifdef DEBUG_COMPILE + xmlGenericError(xmlGenericErrorContext, + "Compiled callback for: '%s'\n", token); +#endif + if (ctxt == NULL) { + fprintf(stderr, "callback on %s missing context\n", token); + return; + } + if (define == NULL) { + if (token[0] == '#') + return; + fprintf(stderr, "callback on %s missing define\n", token); + if ((ctxt != NULL) && (ctxt->errNo == XML_RELAXNG_OK)) + ctxt->errNo = XML_RELAXNG_ERR_INTERNAL; + return; + } + if ((ctxt == NULL) || (define == NULL)) { + fprintf(stderr, "callback on %s missing info\n", token); + if ((ctxt != NULL) && (ctxt->errNo == XML_RELAXNG_OK)) + ctxt->errNo = XML_RELAXNG_ERR_INTERNAL; + return; + } else if (define->type != XML_RELAXNG_ELEMENT) { + fprintf(stderr, "callback on %s define is not element\n", token); + if (ctxt->errNo == XML_RELAXNG_OK) + ctxt->errNo = XML_RELAXNG_ERR_INTERNAL; + return; + } + ret = xmlRelaxNGValidateDefinition(ctxt, define); + if (ret != 0) + ctxt->perr = ret; +} + +/** + * xmlRelaxNGValidateCompiledContent: + * @ctxt: the RelaxNG validation context + * @regexp: the regular expression as compiled + * @content: list of children to test against the regexp + * + * Validate the content model of an element or start using the regexp + * + * Returns 0 in case of success, -1 in case of error. + */ +static int +xmlRelaxNGValidateCompiledContent(xmlRelaxNGValidCtxtPtr ctxt, + xmlRegexpPtr regexp, xmlNodePtr content) +{ + xmlRegExecCtxtPtr exec; + xmlNodePtr cur; + int ret = 0; + int oldperr; + + if ((ctxt == NULL) || (regexp == NULL)) + return (-1); + oldperr = ctxt->perr; + exec = xmlRegNewExecCtxt(regexp, + xmlRelaxNGValidateCompiledCallback, ctxt); + ctxt->perr = 0; + cur = content; + while (cur != NULL) { + ctxt->state->seq = cur; + switch (cur->type) { + case XML_TEXT_NODE: + case XML_CDATA_SECTION_NODE: + if (xmlIsBlankNode(cur)) + break; + ret = xmlRegExecPushString(exec, BAD_CAST "#text", ctxt); + if (ret < 0) { + VALID_ERR2(XML_RELAXNG_ERR_TEXTWRONG, + cur->parent->name); + } + break; + case XML_ELEMENT_NODE: + if (cur->ns != NULL) { + ret = xmlRegExecPushString2(exec, cur->name, + cur->ns->href, ctxt); + } else { + ret = xmlRegExecPushString(exec, cur->name, ctxt); + } + if (ret < 0) { + VALID_ERR2(XML_RELAXNG_ERR_ELEMWRONG, cur->name); + } + break; + default: + break; + } + if (ret < 0) + break; + /* + * Switch to next element + */ + cur = cur->next; + } + ret = xmlRegExecPushString(exec, NULL, NULL); + if (ret == 1) { + ret = 0; + ctxt->state->seq = NULL; + } else if (ret == 0) { + /* + * TODO: get some of the names needed to exit the current state of exec + */ + VALID_ERR2(XML_RELAXNG_ERR_NOELEM, BAD_CAST ""); + ret = -1; + if ((ctxt->flags & FLAGS_IGNORABLE) == 0) + xmlRelaxNGDumpValidError(ctxt); + } else { + ret = -1; + } + xmlRegFreeExecCtxt(exec); + /* + * There might be content model errors outside of the pure + * regexp validation, e.g. for attribute values. + */ + if ((ret == 0) && (ctxt->perr != 0)) { + ret = ctxt->perr; + } + ctxt->perr = oldperr; + return (ret); +} + +/************************************************************************ + * * + * Progressive validation of when possible * + * * + ************************************************************************/ +static int xmlRelaxNGValidateAttributeList(xmlRelaxNGValidCtxtPtr ctxt, + xmlRelaxNGDefinePtr defines); +static int xmlRelaxNGValidateElementEnd(xmlRelaxNGValidCtxtPtr ctxt, + int dolog); +static void xmlRelaxNGLogBestError(xmlRelaxNGValidCtxtPtr ctxt); + +/** + * xmlRelaxNGElemPush: + * @ctxt: the validation context + * @exec: the regexp runtime for the new content model + * + * Push a new regexp for the current node content model on the stack + * + * Returns 0 in case of success and -1 in case of error. + */ +static int +xmlRelaxNGElemPush(xmlRelaxNGValidCtxtPtr ctxt, xmlRegExecCtxtPtr exec) +{ + if (ctxt->elemTab == NULL) { + ctxt->elemMax = 10; + ctxt->elemTab = (xmlRegExecCtxtPtr *) xmlMalloc(ctxt->elemMax * + sizeof + (xmlRegExecCtxtPtr)); + if (ctxt->elemTab == NULL) { + xmlRngVErrMemory(ctxt, "validating\n"); + return (-1); + } + } + if (ctxt->elemNr >= ctxt->elemMax) { + ctxt->elemMax *= 2; + ctxt->elemTab = (xmlRegExecCtxtPtr *) xmlRealloc(ctxt->elemTab, + ctxt->elemMax * + sizeof + (xmlRegExecCtxtPtr)); + if (ctxt->elemTab == NULL) { + xmlRngVErrMemory(ctxt, "validating\n"); + return (-1); + } + } + ctxt->elemTab[ctxt->elemNr++] = exec; + ctxt->elem = exec; + return (0); +} + +/** + * xmlRelaxNGElemPop: + * @ctxt: the validation context + * + * Pop the regexp of the current node content model from the stack + * + * Returns the exec or NULL if empty + */ +static xmlRegExecCtxtPtr +xmlRelaxNGElemPop(xmlRelaxNGValidCtxtPtr ctxt) +{ + xmlRegExecCtxtPtr ret; + + if (ctxt->elemNr <= 0) + return (NULL); + ctxt->elemNr--; + ret = ctxt->elemTab[ctxt->elemNr]; + ctxt->elemTab[ctxt->elemNr] = NULL; + if (ctxt->elemNr > 0) + ctxt->elem = ctxt->elemTab[ctxt->elemNr - 1]; + else + ctxt->elem = NULL; + return (ret); +} + +/** + * xmlRelaxNGValidateProgressiveCallback: + * @exec: the regular expression instance + * @token: the token which matched + * @transdata: callback data, the define for the subelement if available + @ @inputdata: callback data, the Relax NG validation context + * + * Handle the callback and if needed validate the element children. + * some of the in/out informations are passed via the context in @inputdata. + */ +static void +xmlRelaxNGValidateProgressiveCallback(xmlRegExecCtxtPtr exec + ATTRIBUTE_UNUSED, + const xmlChar * token, + void *transdata, void *inputdata) +{ + xmlRelaxNGValidCtxtPtr ctxt = (xmlRelaxNGValidCtxtPtr) inputdata; + xmlRelaxNGDefinePtr define = (xmlRelaxNGDefinePtr) transdata; + xmlRelaxNGValidStatePtr state, oldstate; + xmlNodePtr node; + int ret = 0, oldflags; + +#ifdef DEBUG_PROGRESSIVE + xmlGenericError(xmlGenericErrorContext, + "Progressive callback for: '%s'\n", token); +#endif + if (ctxt == NULL) { + fprintf(stderr, "callback on %s missing context\n", token); + return; + } + node = ctxt->pnode; + ctxt->pstate = 1; + if (define == NULL) { + if (token[0] == '#') + return; + fprintf(stderr, "callback on %s missing define\n", token); + if ((ctxt != NULL) && (ctxt->errNo == XML_RELAXNG_OK)) + ctxt->errNo = XML_RELAXNG_ERR_INTERNAL; + ctxt->pstate = -1; + return; + } + if ((ctxt == NULL) || (define == NULL)) { + fprintf(stderr, "callback on %s missing info\n", token); + if ((ctxt != NULL) && (ctxt->errNo == XML_RELAXNG_OK)) + ctxt->errNo = XML_RELAXNG_ERR_INTERNAL; + ctxt->pstate = -1; + return; + } else if (define->type != XML_RELAXNG_ELEMENT) { + fprintf(stderr, "callback on %s define is not element\n", token); + if (ctxt->errNo == XML_RELAXNG_OK) + ctxt->errNo = XML_RELAXNG_ERR_INTERNAL; + ctxt->pstate = -1; + return; + } + if (node->type != XML_ELEMENT_NODE) { + VALID_ERR(XML_RELAXNG_ERR_NOTELEM); + if ((ctxt->flags & FLAGS_IGNORABLE) == 0) + xmlRelaxNGDumpValidError(ctxt); + ctxt->pstate = -1; + return; + } + if (define->contModel == NULL) { + /* + * this node cannot be validated in a streamable fashion + */ +#ifdef DEBUG_PROGRESSIVE + xmlGenericError(xmlGenericErrorContext, + "Element '%s' validation is not streamable\n", + token); +#endif + ctxt->pstate = 0; + ctxt->pdef = define; + return; + } + exec = xmlRegNewExecCtxt(define->contModel, + xmlRelaxNGValidateProgressiveCallback, ctxt); + if (exec == NULL) { + ctxt->pstate = -1; + return; + } + xmlRelaxNGElemPush(ctxt, exec); + + /* + * Validate the attributes part of the content. + */ + state = xmlRelaxNGNewValidState(ctxt, node); + if (state == NULL) { + ctxt->pstate = -1; + return; + } + oldstate = ctxt->state; + ctxt->state = state; + if (define->attrs != NULL) { + ret = xmlRelaxNGValidateAttributeList(ctxt, define->attrs); + if (ret != 0) { + ctxt->pstate = -1; + VALID_ERR2(XML_RELAXNG_ERR_ATTRVALID, node->name); + } + } + if (ctxt->state != NULL) { + ctxt->state->seq = NULL; + ret = xmlRelaxNGValidateElementEnd(ctxt, 1); + if (ret != 0) { + ctxt->pstate = -1; + } + xmlRelaxNGFreeValidState(ctxt, ctxt->state); + } else if (ctxt->states != NULL) { + int tmp = -1, i; + + oldflags = ctxt->flags; + + for (i = 0; i < ctxt->states->nbState; i++) { + state = ctxt->states->tabState[i]; + ctxt->state = state; + ctxt->state->seq = NULL; + + if (xmlRelaxNGValidateElementEnd(ctxt, 0) == 0) { + tmp = 0; + break; + } + } + if (tmp != 0) { + /* + * validation error, log the message for the "best" one + */ + ctxt->flags |= FLAGS_IGNORABLE; + xmlRelaxNGLogBestError(ctxt); + } + for (i = 0; i < ctxt->states->nbState; i++) { + xmlRelaxNGFreeValidState(ctxt, ctxt->states->tabState[i]); + } + xmlRelaxNGFreeStates(ctxt, ctxt->states); + ctxt->states = NULL; + if ((ret == 0) && (tmp == -1)) + ctxt->pstate = -1; + ctxt->flags = oldflags; + } + if (ctxt->pstate == -1) { + if ((ctxt->flags & FLAGS_IGNORABLE) == 0) { + xmlRelaxNGDumpValidError(ctxt); + } + } + ctxt->state = oldstate; +} + +/** + * xmlRelaxNGValidatePushElement: + * @ctxt: the validation context + * @doc: a document instance + * @elem: an element instance + * + * Push a new element start on the RelaxNG validation stack. + * + * returns 1 if no validation problem was found or 0 if validating the + * element requires a full node, and -1 in case of error. + */ +int +xmlRelaxNGValidatePushElement(xmlRelaxNGValidCtxtPtr ctxt, + xmlDocPtr doc ATTRIBUTE_UNUSED, + xmlNodePtr elem) +{ + int ret = 1; + + if ((ctxt == NULL) || (elem == NULL)) + return (-1); + +#ifdef DEBUG_PROGRESSIVE + xmlGenericError(xmlGenericErrorContext, "PushElem %s\n", elem->name); +#endif + if (ctxt->elem == 0) { + xmlRelaxNGPtr schema; + xmlRelaxNGGrammarPtr grammar; + xmlRegExecCtxtPtr exec; + xmlRelaxNGDefinePtr define; + + schema = ctxt->schema; + if (schema == NULL) { + VALID_ERR(XML_RELAXNG_ERR_NOGRAMMAR); + return (-1); + } + grammar = schema->topgrammar; + if ((grammar == NULL) || (grammar->start == NULL)) { + VALID_ERR(XML_RELAXNG_ERR_NOGRAMMAR); + return (-1); + } + define = grammar->start; + if (define->contModel == NULL) { + ctxt->pdef = define; + return (0); + } + exec = xmlRegNewExecCtxt(define->contModel, + xmlRelaxNGValidateProgressiveCallback, + ctxt); + if (exec == NULL) { + return (-1); + } + xmlRelaxNGElemPush(ctxt, exec); + } + ctxt->pnode = elem; + ctxt->pstate = 0; + if (elem->ns != NULL) { + ret = + xmlRegExecPushString2(ctxt->elem, elem->name, elem->ns->href, + ctxt); + } else { + ret = xmlRegExecPushString(ctxt->elem, elem->name, ctxt); + } + if (ret < 0) { + VALID_ERR2(XML_RELAXNG_ERR_ELEMWRONG, elem->name); + } else { + if (ctxt->pstate == 0) + ret = 0; + else if (ctxt->pstate < 0) + ret = -1; + else + ret = 1; + } +#ifdef DEBUG_PROGRESSIVE + if (ret < 0) + xmlGenericError(xmlGenericErrorContext, "PushElem %s failed\n", + elem->name); +#endif + return (ret); +} + +/** + * xmlRelaxNGValidatePushCData: + * @ctxt: the RelaxNG validation context + * @data: some character data read + * @len: the lenght of the data + * + * check the CData parsed for validation in the current stack + * + * returns 1 if no validation problem was found or -1 otherwise + */ +int +xmlRelaxNGValidatePushCData(xmlRelaxNGValidCtxtPtr ctxt, + const xmlChar * data, int len ATTRIBUTE_UNUSED) +{ + int ret = 1; + + if ((ctxt == NULL) || (ctxt->elem == NULL) || (data == NULL)) + return (-1); + +#ifdef DEBUG_PROGRESSIVE + xmlGenericError(xmlGenericErrorContext, "CDATA %s %d\n", data, len); +#endif + + while (*data != 0) { + if (!IS_BLANK_CH(*data)) + break; + data++; + } + if (*data == 0) + return (1); + + ret = xmlRegExecPushString(ctxt->elem, BAD_CAST "#text", ctxt); + if (ret < 0) { + VALID_ERR2(XML_RELAXNG_ERR_TEXTWRONG, BAD_CAST " TODO "); +#ifdef DEBUG_PROGRESSIVE + xmlGenericError(xmlGenericErrorContext, "CDATA failed\n"); +#endif + + return (-1); + } + return (1); +} + +/** + * xmlRelaxNGValidatePopElement: + * @ctxt: the RelaxNG validation context + * @doc: a document instance + * @elem: an element instance + * + * Pop the element end from the RelaxNG validation stack. + * + * returns 1 if no validation problem was found or 0 otherwise + */ +int +xmlRelaxNGValidatePopElement(xmlRelaxNGValidCtxtPtr ctxt, + xmlDocPtr doc ATTRIBUTE_UNUSED, + xmlNodePtr elem) +{ + int ret; + xmlRegExecCtxtPtr exec; + + if ((ctxt == NULL) || (ctxt->elem == NULL) || (elem == NULL)) + return (-1); +#ifdef DEBUG_PROGRESSIVE + xmlGenericError(xmlGenericErrorContext, "PopElem %s\n", elem->name); +#endif + /* + * verify that we reached a terminal state of the content model. + */ + exec = xmlRelaxNGElemPop(ctxt); + ret = xmlRegExecPushString(exec, NULL, NULL); + if (ret == 0) { + /* + * TODO: get some of the names needed to exit the current state of exec + */ + VALID_ERR2(XML_RELAXNG_ERR_NOELEM, BAD_CAST ""); + ret = -1; + } else if (ret < 0) { + ret = -1; + } else { + ret = 1; + } + xmlRegFreeExecCtxt(exec); +#ifdef DEBUG_PROGRESSIVE + if (ret < 0) + xmlGenericError(xmlGenericErrorContext, "PopElem %s failed\n", + elem->name); +#endif + return (ret); +} + +/** + * xmlRelaxNGValidateFullElement: + * @ctxt: the validation context + * @doc: a document instance + * @elem: an element instance + * + * Validate a full subtree when xmlRelaxNGValidatePushElement() returned + * 0 and the content of the node has been expanded. + * + * returns 1 if no validation problem was found or -1 in case of error. + */ +int +xmlRelaxNGValidateFullElement(xmlRelaxNGValidCtxtPtr ctxt, + xmlDocPtr doc ATTRIBUTE_UNUSED, + xmlNodePtr elem) +{ + int ret; + xmlRelaxNGValidStatePtr state; + + if ((ctxt == NULL) || (ctxt->pdef == NULL) || (elem == NULL)) + return (-1); +#ifdef DEBUG_PROGRESSIVE + xmlGenericError(xmlGenericErrorContext, "FullElem %s\n", elem->name); +#endif + state = xmlRelaxNGNewValidState(ctxt, elem->parent); + if (state == NULL) { + return (-1); + } + state->seq = elem; + ctxt->state = state; + ctxt->errNo = XML_RELAXNG_OK; + ret = xmlRelaxNGValidateDefinition(ctxt, ctxt->pdef); + if ((ret != 0) || (ctxt->errNo != XML_RELAXNG_OK)) + ret = -1; + else + ret = 1; + xmlRelaxNGFreeValidState(ctxt, state); + ctxt->state = NULL; +#ifdef DEBUG_PROGRESSIVE + if (ret < 0) + xmlGenericError(xmlGenericErrorContext, "FullElem %s failed\n", + elem->name); +#endif + return (ret); +} + +/************************************************************************ + * * + * Generic interpreted validation implementation * + * * + ************************************************************************/ +static int xmlRelaxNGValidateValue(xmlRelaxNGValidCtxtPtr ctxt, + xmlRelaxNGDefinePtr define); + +/** + * xmlRelaxNGSkipIgnored: + * @ctxt: a schema validation context + * @node: the top node. + * + * Skip ignorable nodes in that context + * + * Returns the new sibling or NULL in case of error. + */ +static xmlNodePtr +xmlRelaxNGSkipIgnored(xmlRelaxNGValidCtxtPtr ctxt ATTRIBUTE_UNUSED, + xmlNodePtr node) +{ + /* + * TODO complete and handle entities + */ + while ((node != NULL) && + ((node->type == XML_COMMENT_NODE) || + (node->type == XML_PI_NODE) || + (node->type == XML_XINCLUDE_START) || + (node->type == XML_XINCLUDE_END) || + (((node->type == XML_TEXT_NODE) || + (node->type == XML_CDATA_SECTION_NODE)) && + ((ctxt->flags & FLAGS_MIXED_CONTENT) || + (IS_BLANK_NODE(node)))))) { + node = node->next; + } + return (node); +} + +/** + * xmlRelaxNGNormalize: + * @ctxt: a schema validation context + * @str: the string to normalize + * + * Implements the normalizeWhiteSpace( s ) function from + * section 6.2.9 of the spec + * + * Returns the new string or NULL in case of error. + */ +static xmlChar * +xmlRelaxNGNormalize(xmlRelaxNGValidCtxtPtr ctxt, const xmlChar * str) +{ + xmlChar *ret, *p; + const xmlChar *tmp; + int len; + + if (str == NULL) + return (NULL); + tmp = str; + while (*tmp != 0) + tmp++; + len = tmp - str; + + ret = (xmlChar *) xmlMallocAtomic((len + 1) * sizeof(xmlChar)); + if (ret == NULL) { + xmlRngVErrMemory(ctxt, "validating\n"); + return (NULL); + } + p = ret; + while (IS_BLANK_CH(*str)) + str++; + while (*str != 0) { + if (IS_BLANK_CH(*str)) { + while (IS_BLANK_CH(*str)) + str++; + if (*str == 0) + break; + *p++ = ' '; + } else + *p++ = *str++; + } + *p = 0; + return (ret); +} + +/** + * xmlRelaxNGValidateDatatype: + * @ctxt: a Relax-NG validation context + * @value: the string value + * @type: the datatype definition + * @node: the node + * + * Validate the given value against the dataype + * + * Returns 0 if the validation succeeded or an error code. + */ +static int +xmlRelaxNGValidateDatatype(xmlRelaxNGValidCtxtPtr ctxt, + const xmlChar * value, + xmlRelaxNGDefinePtr define, xmlNodePtr node) +{ + int ret, tmp; + xmlRelaxNGTypeLibraryPtr lib; + void *result = NULL; + xmlRelaxNGDefinePtr cur; + + if ((define == NULL) || (define->data == NULL)) { + return (-1); + } + lib = (xmlRelaxNGTypeLibraryPtr) define->data; + if (lib->check != NULL) { + if ((define->attrs != NULL) && + (define->attrs->type == XML_RELAXNG_PARAM)) { + ret = + lib->check(lib->data, define->name, value, &result, node); + } else { + ret = lib->check(lib->data, define->name, value, NULL, node); + } + } else + ret = -1; + if (ret < 0) { + VALID_ERR2(XML_RELAXNG_ERR_TYPE, define->name); + if ((result != NULL) && (lib != NULL) && (lib->freef != NULL)) + lib->freef(lib->data, result); + return (-1); + } else if (ret == 1) { + ret = 0; + } else if (ret == 2) { + VALID_ERR2P(XML_RELAXNG_ERR_DUPID, value); + } else { + VALID_ERR3P(XML_RELAXNG_ERR_TYPEVAL, define->name, value); + ret = -1; + } + cur = define->attrs; + while ((ret == 0) && (cur != NULL) && (cur->type == XML_RELAXNG_PARAM)) { + if (lib->facet != NULL) { + tmp = lib->facet(lib->data, define->name, cur->name, + cur->value, value, result); + if (tmp != 0) + ret = -1; + } + cur = cur->next; + } + if ((ret == 0) && (define->content != NULL)) { + const xmlChar *oldvalue, *oldendvalue; + + oldvalue = ctxt->state->value; + oldendvalue = ctxt->state->endvalue; + ctxt->state->value = (xmlChar *) value; + ctxt->state->endvalue = NULL; + ret = xmlRelaxNGValidateValue(ctxt, define->content); + ctxt->state->value = (xmlChar *) oldvalue; + ctxt->state->endvalue = (xmlChar *) oldendvalue; + } + if ((result != NULL) && (lib != NULL) && (lib->freef != NULL)) + lib->freef(lib->data, result); + return (ret); +} + +/** + * xmlRelaxNGNextValue: + * @ctxt: a Relax-NG validation context + * + * Skip to the next value when validating within a list + * + * Returns 0 if the operation succeeded or an error code. + */ +static int +xmlRelaxNGNextValue(xmlRelaxNGValidCtxtPtr ctxt) +{ + xmlChar *cur; + + cur = ctxt->state->value; + if ((cur == NULL) || (ctxt->state->endvalue == NULL)) { + ctxt->state->value = NULL; + ctxt->state->endvalue = NULL; + return (0); + } + while (*cur != 0) + cur++; + while ((cur != ctxt->state->endvalue) && (*cur == 0)) + cur++; + if (cur == ctxt->state->endvalue) + ctxt->state->value = NULL; + else + ctxt->state->value = cur; + return (0); +} + +/** + * xmlRelaxNGValidateValueList: + * @ctxt: a Relax-NG validation context + * @defines: the list of definitions to verify + * + * Validate the given set of definitions for the current value + * + * Returns 0 if the validation succeeded or an error code. + */ +static int +xmlRelaxNGValidateValueList(xmlRelaxNGValidCtxtPtr ctxt, + xmlRelaxNGDefinePtr defines) +{ + int ret = 0; + + while (defines != NULL) { + ret = xmlRelaxNGValidateValue(ctxt, defines); + if (ret != 0) + break; + defines = defines->next; + } + return (ret); +} + +/** + * xmlRelaxNGValidateValue: + * @ctxt: a Relax-NG validation context + * @define: the definition to verify + * + * Validate the given definition for the current value + * + * Returns 0 if the validation succeeded or an error code. + */ +static int +xmlRelaxNGValidateValue(xmlRelaxNGValidCtxtPtr ctxt, + xmlRelaxNGDefinePtr define) +{ + int ret = 0, oldflags; + xmlChar *value; + + value = ctxt->state->value; + switch (define->type) { + case XML_RELAXNG_EMPTY:{ + if ((value != NULL) && (value[0] != 0)) { + int idx = 0; + + while (IS_BLANK_CH(value[idx])) + idx++; + if (value[idx] != 0) + ret = -1; + } + break; + } + case XML_RELAXNG_TEXT: + break; + case XML_RELAXNG_VALUE:{ + if (!xmlStrEqual(value, define->value)) { + if (define->name != NULL) { + xmlRelaxNGTypeLibraryPtr lib; + + lib = (xmlRelaxNGTypeLibraryPtr) define->data; + if ((lib != NULL) && (lib->comp != NULL)) { + ret = lib->comp(lib->data, define->name, + define->value, define->node, + (void *) define->attrs, + value, ctxt->state->node); + } else + ret = -1; + if (ret < 0) { + VALID_ERR2(XML_RELAXNG_ERR_TYPECMP, + define->name); + return (-1); + } else if (ret == 1) { + ret = 0; + } else { + ret = -1; + } + } else { + xmlChar *nval, *nvalue; + + /* + * TODO: trivial optimizations are possible by + * computing at compile-time + */ + nval = xmlRelaxNGNormalize(ctxt, define->value); + nvalue = xmlRelaxNGNormalize(ctxt, value); + + if ((nval == NULL) || (nvalue == NULL) || + (!xmlStrEqual(nval, nvalue))) + ret = -1; + if (nval != NULL) + xmlFree(nval); + if (nvalue != NULL) + xmlFree(nvalue); + } + } + if (ret == 0) + xmlRelaxNGNextValue(ctxt); + break; + } + case XML_RELAXNG_DATATYPE:{ + ret = xmlRelaxNGValidateDatatype(ctxt, value, define, + ctxt->state->seq); + if (ret == 0) + xmlRelaxNGNextValue(ctxt); + + break; + } + case XML_RELAXNG_CHOICE:{ + xmlRelaxNGDefinePtr list = define->content; + xmlChar *oldvalue; + + oldflags = ctxt->flags; + ctxt->flags |= FLAGS_IGNORABLE; + + oldvalue = ctxt->state->value; + while (list != NULL) { + ret = xmlRelaxNGValidateValue(ctxt, list); + if (ret == 0) { + break; + } + ctxt->state->value = oldvalue; + list = list->next; + } + ctxt->flags = oldflags; + if (ret != 0) { + if ((ctxt->flags & FLAGS_IGNORABLE) == 0) + xmlRelaxNGDumpValidError(ctxt); + } else { + if (ctxt->errNr > 0) + xmlRelaxNGPopErrors(ctxt, 0); + } + break; + } + case XML_RELAXNG_LIST:{ + xmlRelaxNGDefinePtr list = define->content; + xmlChar *oldvalue, *oldend, *val, *cur; + +#ifdef DEBUG_LIST + int nb_values = 0; +#endif + + oldvalue = ctxt->state->value; + oldend = ctxt->state->endvalue; + + val = xmlStrdup(oldvalue); + if (val == NULL) { + val = xmlStrdup(BAD_CAST ""); + } + if (val == NULL) { + VALID_ERR(XML_RELAXNG_ERR_NOSTATE); + return (-1); + } + cur = val; + while (*cur != 0) { + if (IS_BLANK_CH(*cur)) { + *cur = 0; + cur++; +#ifdef DEBUG_LIST + nb_values++; +#endif + while (IS_BLANK_CH(*cur)) + *cur++ = 0; + } else + cur++; + } +#ifdef DEBUG_LIST + xmlGenericError(xmlGenericErrorContext, + "list value: '%s' found %d items\n", + oldvalue, nb_values); + nb_values = 0; +#endif + ctxt->state->endvalue = cur; + cur = val; + while ((*cur == 0) && (cur != ctxt->state->endvalue)) + cur++; + + ctxt->state->value = cur; + + while (list != NULL) { + if (ctxt->state->value == ctxt->state->endvalue) + ctxt->state->value = NULL; + ret = xmlRelaxNGValidateValue(ctxt, list); + if (ret != 0) { +#ifdef DEBUG_LIST + xmlGenericError(xmlGenericErrorContext, + "Failed to validate value: '%s' with %d rule\n", + ctxt->state->value, nb_values); +#endif + break; + } +#ifdef DEBUG_LIST + nb_values++; +#endif + list = list->next; + } + + if ((ret == 0) && (ctxt->state->value != NULL) && + (ctxt->state->value != ctxt->state->endvalue)) { + VALID_ERR2(XML_RELAXNG_ERR_LISTEXTRA, + ctxt->state->value); + ret = -1; + } + xmlFree(val); + ctxt->state->value = oldvalue; + ctxt->state->endvalue = oldend; + break; + } + case XML_RELAXNG_ONEORMORE: + ret = xmlRelaxNGValidateValueList(ctxt, define->content); + if (ret != 0) { + break; + } + /* no break on purpose */ + case XML_RELAXNG_ZEROORMORE:{ + xmlChar *cur, *temp; + + oldflags = ctxt->flags; + ctxt->flags |= FLAGS_IGNORABLE; + cur = ctxt->state->value; + temp = NULL; + while ((cur != NULL) && (cur != ctxt->state->endvalue) && + (temp != cur)) { + temp = cur; + ret = + xmlRelaxNGValidateValueList(ctxt, define->content); + if (ret != 0) { + ctxt->state->value = temp; + ret = 0; + break; + } + cur = ctxt->state->value; + } + ctxt->flags = oldflags; + if (ctxt->errNr > 0) + xmlRelaxNGPopErrors(ctxt, 0); + break; + } + case XML_RELAXNG_EXCEPT:{ + xmlRelaxNGDefinePtr list; + + list = define->content; + while (list != NULL) { + ret = xmlRelaxNGValidateValue(ctxt, list); + if (ret == 0) { + ret = -1; + break; + } else + ret = 0; + list = list->next; + } + break; + } + case XML_RELAXNG_DEF: + case XML_RELAXNG_GROUP:{ + xmlRelaxNGDefinePtr list; + + list = define->content; + while (list != NULL) { + ret = xmlRelaxNGValidateValue(ctxt, list); + if (ret != 0) { + ret = -1; + break; + } else + ret = 0; + list = list->next; + } + break; + } + case XML_RELAXNG_REF: + case XML_RELAXNG_PARENTREF: + ret = xmlRelaxNGValidateValue(ctxt, define->content); + break; + default: + TODO ret = -1; + } + return (ret); +} + +/** + * xmlRelaxNGValidateValueContent: + * @ctxt: a Relax-NG validation context + * @defines: the list of definitions to verify + * + * Validate the given definitions for the current value + * + * Returns 0 if the validation succeeded or an error code. + */ +static int +xmlRelaxNGValidateValueContent(xmlRelaxNGValidCtxtPtr ctxt, + xmlRelaxNGDefinePtr defines) +{ + int ret = 0; + + while (defines != NULL) { + ret = xmlRelaxNGValidateValue(ctxt, defines); + if (ret != 0) + break; + defines = defines->next; + } + return (ret); +} + +/** + * xmlRelaxNGAttributeMatch: + * @ctxt: a Relax-NG validation context + * @define: the definition to check + * @prop: the attribute + * + * Check if the attribute matches the definition nameClass + * + * Returns 1 if the attribute matches, 0 if no, or -1 in case of error + */ +static int +xmlRelaxNGAttributeMatch(xmlRelaxNGValidCtxtPtr ctxt, + xmlRelaxNGDefinePtr define, xmlAttrPtr prop) +{ + int ret; + + if (define->name != NULL) { + if (!xmlStrEqual(define->name, prop->name)) + return (0); + } + if (define->ns != NULL) { + if (define->ns[0] == 0) { + if (prop->ns != NULL) + return (0); + } else { + if ((prop->ns == NULL) || + (!xmlStrEqual(define->ns, prop->ns->href))) + return (0); + } + } + if (define->nameClass == NULL) + return (1); + define = define->nameClass; + if (define->type == XML_RELAXNG_EXCEPT) { + xmlRelaxNGDefinePtr list; + + list = define->content; + while (list != NULL) { + ret = xmlRelaxNGAttributeMatch(ctxt, list, prop); + if (ret == 1) + return (0); + if (ret < 0) + return (ret); + list = list->next; + } + } else { + TODO} + return (1); +} + +/** + * xmlRelaxNGValidateAttribute: + * @ctxt: a Relax-NG validation context + * @define: the definition to verify + * + * Validate the given attribute definition for that node + * + * Returns 0 if the validation succeeded or an error code. + */ +static int +xmlRelaxNGValidateAttribute(xmlRelaxNGValidCtxtPtr ctxt, + xmlRelaxNGDefinePtr define) +{ + int ret = 0, i; + xmlChar *value, *oldvalue; + xmlAttrPtr prop = NULL, tmp; + xmlNodePtr oldseq; + + if (ctxt->state->nbAttrLeft <= 0) + return (-1); + if (define->name != NULL) { + for (i = 0; i < ctxt->state->nbAttrs; i++) { + tmp = ctxt->state->attrs[i]; + if ((tmp != NULL) && (xmlStrEqual(define->name, tmp->name))) { + if ((((define->ns == NULL) || (define->ns[0] == 0)) && + (tmp->ns == NULL)) || + ((tmp->ns != NULL) && + (xmlStrEqual(define->ns, tmp->ns->href)))) { + prop = tmp; + break; + } + } + } + if (prop != NULL) { + value = xmlNodeListGetString(prop->doc, prop->children, 1); + oldvalue = ctxt->state->value; + oldseq = ctxt->state->seq; + ctxt->state->seq = (xmlNodePtr) prop; + ctxt->state->value = value; + ctxt->state->endvalue = NULL; + ret = xmlRelaxNGValidateValueContent(ctxt, define->content); + if (ctxt->state->value != NULL) + value = ctxt->state->value; + if (value != NULL) + xmlFree(value); + ctxt->state->value = oldvalue; + ctxt->state->seq = oldseq; + if (ret == 0) { + /* + * flag the attribute as processed + */ + ctxt->state->attrs[i] = NULL; + ctxt->state->nbAttrLeft--; + } + } else { + ret = -1; + } +#ifdef DEBUG + xmlGenericError(xmlGenericErrorContext, + "xmlRelaxNGValidateAttribute(%s): %d\n", + define->name, ret); +#endif + } else { + for (i = 0; i < ctxt->state->nbAttrs; i++) { + tmp = ctxt->state->attrs[i]; + if ((tmp != NULL) && + (xmlRelaxNGAttributeMatch(ctxt, define, tmp) == 1)) { + prop = tmp; + break; + } + } + if (prop != NULL) { + value = xmlNodeListGetString(prop->doc, prop->children, 1); + oldvalue = ctxt->state->value; + oldseq = ctxt->state->seq; + ctxt->state->seq = (xmlNodePtr) prop; + ctxt->state->value = value; + ret = xmlRelaxNGValidateValueContent(ctxt, define->content); + if (ctxt->state->value != NULL) + value = ctxt->state->value; + if (value != NULL) + xmlFree(value); + ctxt->state->value = oldvalue; + ctxt->state->seq = oldseq; + if (ret == 0) { + /* + * flag the attribute as processed + */ + ctxt->state->attrs[i] = NULL; + ctxt->state->nbAttrLeft--; + } + } else { + ret = -1; + } +#ifdef DEBUG + if (define->ns != NULL) { + xmlGenericError(xmlGenericErrorContext, + "xmlRelaxNGValidateAttribute(nsName ns = %s): %d\n", + define->ns, ret); + } else { + xmlGenericError(xmlGenericErrorContext, + "xmlRelaxNGValidateAttribute(anyName): %d\n", + ret); + } +#endif + } + + return (ret); +} + +/** + * xmlRelaxNGValidateAttributeList: + * @ctxt: a Relax-NG validation context + * @define: the list of definition to verify + * + * Validate the given node against the list of attribute definitions + * + * Returns 0 if the validation succeeded or an error code. + */ +static int +xmlRelaxNGValidateAttributeList(xmlRelaxNGValidCtxtPtr ctxt, + xmlRelaxNGDefinePtr defines) +{ + int ret = 0, res; + int needmore = 0; + xmlRelaxNGDefinePtr cur; + + cur = defines; + while (cur != NULL) { + if (cur->type == XML_RELAXNG_ATTRIBUTE) { + if (xmlRelaxNGValidateAttribute(ctxt, cur) != 0) + ret = -1; + } else + needmore = 1; + cur = cur->next; + } + if (!needmore) + return (ret); + cur = defines; + while (cur != NULL) { + if (cur->type != XML_RELAXNG_ATTRIBUTE) { + if ((ctxt->state != NULL) || (ctxt->states != NULL)) { + res = xmlRelaxNGValidateDefinition(ctxt, cur); + if (res < 0) + ret = -1; + } else { + VALID_ERR(XML_RELAXNG_ERR_NOSTATE); + return (-1); + } + if (res == -1) /* continues on -2 */ + break; + } + cur = cur->next; + } + + return (ret); +} + +/** + * xmlRelaxNGNodeMatchesList: + * @node: the node + * @list: a NULL terminated array of definitions + * + * Check if a node can be matched by one of the definitions + * + * Returns 1 if matches 0 otherwise + */ +static int +xmlRelaxNGNodeMatchesList(xmlNodePtr node, xmlRelaxNGDefinePtr * list) +{ + xmlRelaxNGDefinePtr cur; + int i = 0, tmp; + + if ((node == NULL) || (list == NULL)) + return (0); + + cur = list[i++]; + while (cur != NULL) { + if ((node->type == XML_ELEMENT_NODE) && + (cur->type == XML_RELAXNG_ELEMENT)) { + tmp = xmlRelaxNGElementMatch(NULL, cur, node); + if (tmp == 1) + return (1); + } else if (((node->type == XML_TEXT_NODE) || + (node->type == XML_CDATA_SECTION_NODE)) && + (cur->type == XML_RELAXNG_TEXT)) { + return (1); + } + cur = list[i++]; + } + return (0); +} + +/** + * xmlRelaxNGValidateInterleave: + * @ctxt: a Relax-NG validation context + * @define: the definition to verify + * + * Validate an interleave definition for a node. + * + * Returns 0 if the validation succeeded or an error code. + */ +static int +xmlRelaxNGValidateInterleave(xmlRelaxNGValidCtxtPtr ctxt, + xmlRelaxNGDefinePtr define) +{ + int ret = 0, i, nbgroups; + int errNr = ctxt->errNr; + int oldflags; + + xmlRelaxNGValidStatePtr oldstate; + xmlRelaxNGPartitionPtr partitions; + xmlRelaxNGInterleaveGroupPtr group = NULL; + xmlNodePtr cur, start, last = NULL, lastchg = NULL, lastelem; + xmlNodePtr *list = NULL, *lasts = NULL; + + if (define->data != NULL) { + partitions = (xmlRelaxNGPartitionPtr) define->data; + nbgroups = partitions->nbgroups; + } else { + VALID_ERR(XML_RELAXNG_ERR_INTERNODATA); + return (-1); + } + /* + * Optimizations for MIXED + */ + oldflags = ctxt->flags; + if (define->dflags & IS_MIXED) { + ctxt->flags |= FLAGS_MIXED_CONTENT; + if (nbgroups == 2) { + /* + * this is a pure case + */ + if (ctxt->state != NULL) + ctxt->state->seq = xmlRelaxNGSkipIgnored(ctxt, + ctxt->state->seq); + if (partitions->groups[0]->rule->type == XML_RELAXNG_TEXT) + ret = xmlRelaxNGValidateDefinition(ctxt, + partitions->groups[1]-> + rule); + else + ret = xmlRelaxNGValidateDefinition(ctxt, + partitions->groups[0]-> + rule); + if (ret == 0) { + if (ctxt->state != NULL) + ctxt->state->seq = xmlRelaxNGSkipIgnored(ctxt, + ctxt->state-> + seq); + } + ctxt->flags = oldflags; + return (ret); + } + } + + /* + * Build arrays to store the first and last node of the chain + * pertaining to each group + */ + list = (xmlNodePtr *) xmlMalloc(nbgroups * sizeof(xmlNodePtr)); + if (list == NULL) { + xmlRngVErrMemory(ctxt, "validating\n"); + return (-1); + } + memset(list, 0, nbgroups * sizeof(xmlNodePtr)); + lasts = (xmlNodePtr *) xmlMalloc(nbgroups * sizeof(xmlNodePtr)); + if (lasts == NULL) { + xmlRngVErrMemory(ctxt, "validating\n"); + return (-1); + } + memset(lasts, 0, nbgroups * sizeof(xmlNodePtr)); + + /* + * Walk the sequence of children finding the right group and + * sorting them in sequences. + */ + cur = ctxt->state->seq; + cur = xmlRelaxNGSkipIgnored(ctxt, cur); + start = cur; + while (cur != NULL) { + ctxt->state->seq = cur; + if ((partitions->triage != NULL) && + (partitions->flags & IS_DETERMINIST)) { + void *tmp = NULL; + + if ((cur->type == XML_TEXT_NODE) || + (cur->type == XML_CDATA_SECTION_NODE)) { + tmp = xmlHashLookup2(partitions->triage, BAD_CAST "#text", + NULL); + } else if (cur->type == XML_ELEMENT_NODE) { + if (cur->ns != NULL) { + tmp = xmlHashLookup2(partitions->triage, cur->name, + cur->ns->href); + if (tmp == NULL) + tmp = xmlHashLookup2(partitions->triage, + BAD_CAST "#any", + cur->ns->href); + } else + tmp = + xmlHashLookup2(partitions->triage, cur->name, + NULL); + if (tmp == NULL) + tmp = + xmlHashLookup2(partitions->triage, BAD_CAST "#any", + NULL); + } + + if (tmp == NULL) { + i = nbgroups; + } else { + i = ((long) tmp) - 1; + if (partitions->flags & IS_NEEDCHECK) { + group = partitions->groups[i]; + if (!xmlRelaxNGNodeMatchesList(cur, group->defs)) + i = nbgroups; + } + } + } else { + for (i = 0; i < nbgroups; i++) { + group = partitions->groups[i]; + if (group == NULL) + continue; + if (xmlRelaxNGNodeMatchesList(cur, group->defs)) + break; + } + } + /* + * We break as soon as an element not matched is found + */ + if (i >= nbgroups) { + break; + } + if (lasts[i] != NULL) { + lasts[i]->next = cur; + lasts[i] = cur; + } else { + list[i] = cur; + lasts[i] = cur; + } + if (cur->next != NULL) + lastchg = cur->next; + else + lastchg = cur; + cur = xmlRelaxNGSkipIgnored(ctxt, cur->next); + } + if (ret != 0) { + VALID_ERR(XML_RELAXNG_ERR_INTERSEQ); + ret = -1; + goto done; + } + lastelem = cur; + oldstate = ctxt->state; + for (i = 0; i < nbgroups; i++) { + ctxt->state = xmlRelaxNGCopyValidState(ctxt, oldstate); + group = partitions->groups[i]; + if (lasts[i] != NULL) { + last = lasts[i]->next; + lasts[i]->next = NULL; + } + ctxt->state->seq = list[i]; + ret = xmlRelaxNGValidateDefinition(ctxt, group->rule); + if (ret != 0) + break; + if (ctxt->state != NULL) { + cur = ctxt->state->seq; + cur = xmlRelaxNGSkipIgnored(ctxt, cur); + xmlRelaxNGFreeValidState(ctxt, oldstate); + oldstate = ctxt->state; + ctxt->state = NULL; + if (cur != NULL) { + VALID_ERR2(XML_RELAXNG_ERR_INTEREXTRA, cur->name); + ret = -1; + ctxt->state = oldstate; + goto done; + } + } else if (ctxt->states != NULL) { + int j; + int found = 0; + int best = -1; + int lowattr = -1; + + /* + * PBM: what happen if there is attributes checks in the interleaves + */ + + for (j = 0; j < ctxt->states->nbState; j++) { + cur = ctxt->states->tabState[j]->seq; + cur = xmlRelaxNGSkipIgnored(ctxt, cur); + if (cur == NULL) { + if (found == 0) { + lowattr = ctxt->states->tabState[j]->nbAttrLeft; + best = j; + } + found = 1; + if (ctxt->states->tabState[j]->nbAttrLeft <= lowattr) { + /* try to keep the latest one to mach old heuristic */ + lowattr = ctxt->states->tabState[j]->nbAttrLeft; + best = j; + } + if (lowattr == 0) + break; + } else if (found == 0) { + if (lowattr == -1) { + lowattr = ctxt->states->tabState[j]->nbAttrLeft; + best = j; + } else + if (ctxt->states->tabState[j]->nbAttrLeft <= lowattr) { + /* try to keep the latest one to mach old heuristic */ + lowattr = ctxt->states->tabState[j]->nbAttrLeft; + best = j; + } + } + } + /* + * BIG PBM: here we pick only one restarting point :-( + */ + if (ctxt->states->nbState > 0) { + xmlRelaxNGFreeValidState(ctxt, oldstate); + if (best != -1) { + oldstate = ctxt->states->tabState[best]; + ctxt->states->tabState[best] = NULL; + } else { + oldstate = + ctxt->states->tabState[ctxt->states->nbState - 1]; + ctxt->states->tabState[ctxt->states->nbState - 1] = NULL; + } + } + for (j = 0; j < ctxt->states->nbState ; j++) { + xmlRelaxNGFreeValidState(ctxt, ctxt->states->tabState[j]); + } + xmlRelaxNGFreeStates(ctxt, ctxt->states); + ctxt->states = NULL; + if (found == 0) { + VALID_ERR2(XML_RELAXNG_ERR_INTEREXTRA, cur->name); + ret = -1; + ctxt->state = oldstate; + goto done; + } + } else { + ret = -1; + break; + } + if (lasts[i] != NULL) { + lasts[i]->next = last; + } + } + if (ctxt->state != NULL) + xmlRelaxNGFreeValidState(ctxt, ctxt->state); + ctxt->state = oldstate; + ctxt->state->seq = lastelem; + if (ret != 0) { + VALID_ERR(XML_RELAXNG_ERR_INTERSEQ); + ret = -1; + goto done; + } + + done: + ctxt->flags = oldflags; + /* + * builds the next links chain from the prev one + */ + cur = lastchg; + while (cur != NULL) { + if ((cur == start) || (cur->prev == NULL)) + break; + cur->prev->next = cur; + cur = cur->prev; + } + if (ret == 0) { + if (ctxt->errNr > errNr) + xmlRelaxNGPopErrors(ctxt, errNr); + } + + xmlFree(list); + xmlFree(lasts); + return (ret); +} + +/** + * xmlRelaxNGValidateDefinitionList: + * @ctxt: a Relax-NG validation context + * @define: the list of definition to verify + * + * Validate the given node content against the (list) of definitions + * + * Returns 0 if the validation succeeded or an error code. + */ +static int +xmlRelaxNGValidateDefinitionList(xmlRelaxNGValidCtxtPtr ctxt, + xmlRelaxNGDefinePtr defines) +{ + int ret = 0, res; + + + if (defines == NULL) { + VALID_ERR2(XML_RELAXNG_ERR_INTERNAL, + BAD_CAST "NULL definition list"); + return (-1); + } + while (defines != NULL) { + if ((ctxt->state != NULL) || (ctxt->states != NULL)) { + res = xmlRelaxNGValidateDefinition(ctxt, defines); + if (res < 0) + ret = -1; + } else { + VALID_ERR(XML_RELAXNG_ERR_NOSTATE); + return (-1); + } + if (res == -1) /* continues on -2 */ + break; + defines = defines->next; + } + + return (ret); +} + +/** + * xmlRelaxNGElementMatch: + * @ctxt: a Relax-NG validation context + * @define: the definition to check + * @elem: the element + * + * Check if the element matches the definition nameClass + * + * Returns 1 if the element matches, 0 if no, or -1 in case of error + */ +static int +xmlRelaxNGElementMatch(xmlRelaxNGValidCtxtPtr ctxt, + xmlRelaxNGDefinePtr define, xmlNodePtr elem) +{ + int ret = 0, oldflags = 0; + + if (define->name != NULL) { + if (!xmlStrEqual(elem->name, define->name)) { + VALID_ERR3(XML_RELAXNG_ERR_ELEMNAME, define->name, elem->name); + return (0); + } + } + if ((define->ns != NULL) && (define->ns[0] != 0)) { + if (elem->ns == NULL) { + VALID_ERR2(XML_RELAXNG_ERR_ELEMNONS, elem->name); + return (0); + } else if (!xmlStrEqual(elem->ns->href, define->ns)) { + VALID_ERR3(XML_RELAXNG_ERR_ELEMWRONGNS, + elem->name, define->ns); + return (0); + } + } else if ((elem->ns != NULL) && (define->ns != NULL) && + (define->name == NULL)) { + VALID_ERR2(XML_RELAXNG_ERR_ELEMEXTRANS, elem->name); + return (0); + } else if ((elem->ns != NULL) && (define->name != NULL)) { + VALID_ERR2(XML_RELAXNG_ERR_ELEMEXTRANS, define->name); + return (0); + } + + if (define->nameClass == NULL) + return (1); + + define = define->nameClass; + if (define->type == XML_RELAXNG_EXCEPT) { + xmlRelaxNGDefinePtr list; + + if (ctxt != NULL) { + oldflags = ctxt->flags; + ctxt->flags |= FLAGS_IGNORABLE; + } + + list = define->content; + while (list != NULL) { + ret = xmlRelaxNGElementMatch(ctxt, list, elem); + if (ret == 1) { + if (ctxt != NULL) + ctxt->flags = oldflags; + return (0); + } + if (ret < 0) { + if (ctxt != NULL) + ctxt->flags = oldflags; + return (ret); + } + list = list->next; + } + ret = 1; + if (ctxt != NULL) { + ctxt->flags = oldflags; + } + } else if (define->type == XML_RELAXNG_CHOICE) { + xmlRelaxNGDefinePtr list; + + if (ctxt != NULL) { + oldflags = ctxt->flags; + ctxt->flags |= FLAGS_IGNORABLE; + } + + list = define->nameClass; + while (list != NULL) { + ret = xmlRelaxNGElementMatch(ctxt, list, elem); + if (ret == 1) { + if (ctxt != NULL) + ctxt->flags = oldflags; + return (1); + } + if (ret < 0) { + if (ctxt != NULL) + ctxt->flags = oldflags; + return (ret); + } + list = list->next; + } + if (ctxt != NULL) { + if (ret != 0) { + if ((ctxt->flags & FLAGS_IGNORABLE) == 0) + xmlRelaxNGDumpValidError(ctxt); + } else { + if (ctxt->errNr > 0) + xmlRelaxNGPopErrors(ctxt, 0); + } + } + ret = 0; + if (ctxt != NULL) { + ctxt->flags = oldflags; + } + } else { + TODO ret = -1; + } + return (ret); +} + +/** + * xmlRelaxNGBestState: + * @ctxt: a Relax-NG validation context + * + * Find the "best" state in the ctxt->states list of states to report + * errors about. I.e. a state with no element left in the child list + * or the one with the less attributes left. + * This is called only if a falidation error was detected + * + * Returns the index of the "best" state or -1 in case of error + */ +static int +xmlRelaxNGBestState(xmlRelaxNGValidCtxtPtr ctxt) +{ + xmlRelaxNGValidStatePtr state; + int i, tmp; + int best = -1; + int value = 1000000; + + if ((ctxt == NULL) || (ctxt->states == NULL) || + (ctxt->states->nbState <= 0)) + return (-1); + + for (i = 0; i < ctxt->states->nbState; i++) { + state = ctxt->states->tabState[i]; + if (state == NULL) + continue; + if (state->seq != NULL) { + if ((best == -1) || (value > 100000)) { + value = 100000; + best = i; + } + } else { + tmp = state->nbAttrLeft; + if ((best == -1) || (value > tmp)) { + value = tmp; + best = i; + } + } + } + return (best); +} + +/** + * xmlRelaxNGLogBestError: + * @ctxt: a Relax-NG validation context + * + * Find the "best" state in the ctxt->states list of states to report + * errors about and log it. + */ +static void +xmlRelaxNGLogBestError(xmlRelaxNGValidCtxtPtr ctxt) +{ + int best; + + if ((ctxt == NULL) || (ctxt->states == NULL) || + (ctxt->states->nbState <= 0)) + return; + + best = xmlRelaxNGBestState(ctxt); + if ((best >= 0) && (best < ctxt->states->nbState)) { + ctxt->state = ctxt->states->tabState[best]; + + xmlRelaxNGValidateElementEnd(ctxt, 1); + } +} + +/** + * xmlRelaxNGValidateElementEnd: + * @ctxt: a Relax-NG validation context + * @dolog: indicate that error logging should be done + * + * Validate the end of the element, implements check that + * there is nothing left not consumed in the element content + * or in the attribute list. + * + * Returns 0 if the validation succeeded or an error code. + */ +static int +xmlRelaxNGValidateElementEnd(xmlRelaxNGValidCtxtPtr ctxt, int dolog) +{ + int i; + xmlRelaxNGValidStatePtr state; + + state = ctxt->state; + if (state->seq != NULL) { + state->seq = xmlRelaxNGSkipIgnored(ctxt, state->seq); + if (state->seq != NULL) { + if (dolog) { + VALID_ERR3(XML_RELAXNG_ERR_EXTRACONTENT, + state->node->name, state->seq->name); + } + return (-1); + } + } + for (i = 0; i < state->nbAttrs; i++) { + if (state->attrs[i] != NULL) { + if (dolog) { + VALID_ERR3(XML_RELAXNG_ERR_INVALIDATTR, + state->attrs[i]->name, state->node->name); + } + return (-1 - i); + } + } + return (0); +} + +/** + * xmlRelaxNGValidateState: + * @ctxt: a Relax-NG validation context + * @define: the definition to verify + * + * Validate the current state against the definition + * + * Returns 0 if the validation succeeded or an error code. + */ +static int +xmlRelaxNGValidateState(xmlRelaxNGValidCtxtPtr ctxt, + xmlRelaxNGDefinePtr define) +{ + xmlNodePtr node; + int ret = 0, i, tmp, oldflags, errNr; + xmlRelaxNGValidStatePtr oldstate = NULL, state; + + if (define == NULL) { + VALID_ERR(XML_RELAXNG_ERR_NODEFINE); + return (-1); + } + + if (ctxt->state != NULL) { + node = ctxt->state->seq; + } else { + node = NULL; + } +#ifdef DEBUG + for (i = 0; i < ctxt->depth; i++) + xmlGenericError(xmlGenericErrorContext, " "); + xmlGenericError(xmlGenericErrorContext, + "Start validating %s ", xmlRelaxNGDefName(define)); + if (define->name != NULL) + xmlGenericError(xmlGenericErrorContext, "%s ", define->name); + if ((node != NULL) && (node->name != NULL)) + xmlGenericError(xmlGenericErrorContext, "on %s\n", node->name); + else + xmlGenericError(xmlGenericErrorContext, "\n"); +#endif + ctxt->depth++; + switch (define->type) { + case XML_RELAXNG_EMPTY: + node = xmlRelaxNGSkipIgnored(ctxt, node); + ret = 0; + break; + case XML_RELAXNG_NOT_ALLOWED: + ret = -1; + break; + case XML_RELAXNG_TEXT: + while ((node != NULL) && + ((node->type == XML_TEXT_NODE) || + (node->type == XML_COMMENT_NODE) || + (node->type == XML_PI_NODE) || + (node->type == XML_CDATA_SECTION_NODE))) + node = node->next; + ctxt->state->seq = node; + break; + case XML_RELAXNG_ELEMENT: + errNr = ctxt->errNr; + node = xmlRelaxNGSkipIgnored(ctxt, node); + if (node == NULL) { + VALID_ERR2(XML_RELAXNG_ERR_NOELEM, define->name); + ret = -1; + if ((ctxt->flags & FLAGS_IGNORABLE) == 0) + xmlRelaxNGDumpValidError(ctxt); + break; + } + if (node->type != XML_ELEMENT_NODE) { + VALID_ERR(XML_RELAXNG_ERR_NOTELEM); + ret = -1; + if ((ctxt->flags & FLAGS_IGNORABLE) == 0) + xmlRelaxNGDumpValidError(ctxt); + break; + } + /* + * This node was already validated successfully against + * this definition. + */ + if (node->psvi == define) { + ctxt->state->seq = xmlRelaxNGSkipIgnored(ctxt, node->next); + if (ctxt->errNr > errNr) + xmlRelaxNGPopErrors(ctxt, errNr); + if (ctxt->errNr != 0) { + while ((ctxt->err != NULL) && + (((ctxt->err->err == XML_RELAXNG_ERR_ELEMNAME) + && (xmlStrEqual(ctxt->err->arg2, node->name))) + || + ((ctxt->err->err == + XML_RELAXNG_ERR_ELEMEXTRANS) + && (xmlStrEqual(ctxt->err->arg1, node->name))) + || (ctxt->err->err == XML_RELAXNG_ERR_NOELEM) + || (ctxt->err->err == + XML_RELAXNG_ERR_NOTELEM))) + xmlRelaxNGValidErrorPop(ctxt); + } + break; + } + + ret = xmlRelaxNGElementMatch(ctxt, define, node); + if (ret <= 0) { + ret = -1; + if ((ctxt->flags & FLAGS_IGNORABLE) == 0) + xmlRelaxNGDumpValidError(ctxt); + break; + } + ret = 0; + if (ctxt->errNr != 0) { + if (ctxt->errNr > errNr) + xmlRelaxNGPopErrors(ctxt, errNr); + while ((ctxt->err != NULL) && + (((ctxt->err->err == XML_RELAXNG_ERR_ELEMNAME) && + (xmlStrEqual(ctxt->err->arg2, node->name))) || + ((ctxt->err->err == XML_RELAXNG_ERR_ELEMEXTRANS) && + (xmlStrEqual(ctxt->err->arg1, node->name))) || + (ctxt->err->err == XML_RELAXNG_ERR_NOELEM) || + (ctxt->err->err == XML_RELAXNG_ERR_NOTELEM))) + xmlRelaxNGValidErrorPop(ctxt); + } + errNr = ctxt->errNr; + + oldflags = ctxt->flags; + if (ctxt->flags & FLAGS_MIXED_CONTENT) { + ctxt->flags -= FLAGS_MIXED_CONTENT; + } + state = xmlRelaxNGNewValidState(ctxt, node); + if (state == NULL) { + ret = -1; + if ((ctxt->flags & FLAGS_IGNORABLE) == 0) + xmlRelaxNGDumpValidError(ctxt); + break; + } + + oldstate = ctxt->state; + ctxt->state = state; + if (define->attrs != NULL) { + tmp = xmlRelaxNGValidateAttributeList(ctxt, define->attrs); + if (tmp != 0) { + ret = -1; + VALID_ERR2(XML_RELAXNG_ERR_ATTRVALID, node->name); + } + } + if (define->contModel != NULL) { + xmlRelaxNGValidStatePtr nstate, tmpstate = ctxt->state; + xmlRelaxNGStatesPtr tmpstates = ctxt->states; + xmlNodePtr nseq; + + nstate = xmlRelaxNGNewValidState(ctxt, node); + ctxt->state = nstate; + ctxt->states = NULL; + + tmp = xmlRelaxNGValidateCompiledContent(ctxt, + define->contModel, + ctxt->state->seq); + nseq = ctxt->state->seq; + ctxt->state = tmpstate; + ctxt->states = tmpstates; + xmlRelaxNGFreeValidState(ctxt, nstate); + +#ifdef DEBUG_COMPILE + xmlGenericError(xmlGenericErrorContext, + "Validating content of '%s' : %d\n", + define->name, tmp); +#endif + if (tmp != 0) + ret = -1; + + if (ctxt->states != NULL) { + tmp = -1; + + for (i = 0; i < ctxt->states->nbState; i++) { + state = ctxt->states->tabState[i]; + ctxt->state = state; + ctxt->state->seq = nseq; + + if (xmlRelaxNGValidateElementEnd(ctxt, 0) == 0) { + tmp = 0; + break; + } + } + if (tmp != 0) { + /* + * validation error, log the message for the "best" one + */ + ctxt->flags |= FLAGS_IGNORABLE; + xmlRelaxNGLogBestError(ctxt); + } + for (i = 0; i < ctxt->states->nbState; i++) { + xmlRelaxNGFreeValidState(ctxt, + ctxt->states-> + tabState[i]); + } + xmlRelaxNGFreeStates(ctxt, ctxt->states); + ctxt->flags = oldflags; + ctxt->states = NULL; + if ((ret == 0) && (tmp == -1)) + ret = -1; + } else { + state = ctxt->state; + ctxt->state->seq = nseq; + if (ret == 0) + ret = xmlRelaxNGValidateElementEnd(ctxt, 1); + xmlRelaxNGFreeValidState(ctxt, state); + } + } else { + if (define->content != NULL) { + tmp = xmlRelaxNGValidateDefinitionList(ctxt, + define-> + content); + if (tmp != 0) { + ret = -1; + if (ctxt->state == NULL) { + ctxt->state = oldstate; + VALID_ERR2(XML_RELAXNG_ERR_CONTENTVALID, + node->name); + ctxt->state = NULL; + } else { + VALID_ERR2(XML_RELAXNG_ERR_CONTENTVALID, + node->name); + } + + } + } + if (ctxt->states != NULL) { + tmp = -1; + + for (i = 0; i < ctxt->states->nbState; i++) { + state = ctxt->states->tabState[i]; + ctxt->state = state; + + if (xmlRelaxNGValidateElementEnd(ctxt, 0) == 0) { + tmp = 0; + break; + } + } + if (tmp != 0) { + /* + * validation error, log the message for the "best" one + */ + ctxt->flags |= FLAGS_IGNORABLE; + xmlRelaxNGLogBestError(ctxt); + } + for (i = 0; i < ctxt->states->nbState; i++) { + xmlRelaxNGFreeValidState(ctxt, + ctxt->states-> + tabState[i]); + } + xmlRelaxNGFreeStates(ctxt, ctxt->states); + ctxt->flags = oldflags; + ctxt->states = NULL; + if ((ret == 0) && (tmp == -1)) + ret = -1; + } else { + state = ctxt->state; + if (ret == 0) + ret = xmlRelaxNGValidateElementEnd(ctxt, 1); + xmlRelaxNGFreeValidState(ctxt, state); + } + } + if (ret == 0) { + node->psvi = define; + } + ctxt->flags = oldflags; + ctxt->state = oldstate; + if (oldstate != NULL) + oldstate->seq = xmlRelaxNGSkipIgnored(ctxt, node->next); + if (ret != 0) { + if ((ctxt->flags & FLAGS_IGNORABLE) == 0) { + xmlRelaxNGDumpValidError(ctxt); + ret = 0; +#if 0 + } else { + ret = -2; +#endif + } + } else { + if (ctxt->errNr > errNr) + xmlRelaxNGPopErrors(ctxt, errNr); + } + +#ifdef DEBUG + xmlGenericError(xmlGenericErrorContext, + "xmlRelaxNGValidateDefinition(): validated %s : %d", + node->name, ret); + if (oldstate == NULL) + xmlGenericError(xmlGenericErrorContext, ": no state\n"); + else if (oldstate->seq == NULL) + xmlGenericError(xmlGenericErrorContext, ": done\n"); + else if (oldstate->seq->type == XML_ELEMENT_NODE) + xmlGenericError(xmlGenericErrorContext, ": next elem %s\n", + oldstate->seq->name); + else + xmlGenericError(xmlGenericErrorContext, ": next %s %d\n", + oldstate->seq->name, oldstate->seq->type); +#endif + break; + case XML_RELAXNG_OPTIONAL:{ + errNr = ctxt->errNr; + oldflags = ctxt->flags; + ctxt->flags |= FLAGS_IGNORABLE; + oldstate = xmlRelaxNGCopyValidState(ctxt, ctxt->state); + ret = + xmlRelaxNGValidateDefinitionList(ctxt, + define->content); + if (ret != 0) { + if (ctxt->state != NULL) + xmlRelaxNGFreeValidState(ctxt, ctxt->state); + ctxt->state = oldstate; + ctxt->flags = oldflags; + ret = 0; + if (ctxt->errNr > errNr) + xmlRelaxNGPopErrors(ctxt, errNr); + break; + } + if (ctxt->states != NULL) { + xmlRelaxNGAddStates(ctxt, ctxt->states, oldstate); + } else { + ctxt->states = xmlRelaxNGNewStates(ctxt, 1); + if (ctxt->states == NULL) { + xmlRelaxNGFreeValidState(ctxt, oldstate); + ctxt->flags = oldflags; + ret = -1; + if (ctxt->errNr > errNr) + xmlRelaxNGPopErrors(ctxt, errNr); + break; + } + xmlRelaxNGAddStates(ctxt, ctxt->states, oldstate); + xmlRelaxNGAddStates(ctxt, ctxt->states, ctxt->state); + ctxt->state = NULL; + } + ctxt->flags = oldflags; + ret = 0; + if (ctxt->errNr > errNr) + xmlRelaxNGPopErrors(ctxt, errNr); + break; + } + case XML_RELAXNG_ONEORMORE: + errNr = ctxt->errNr; + ret = xmlRelaxNGValidateDefinitionList(ctxt, define->content); + if (ret != 0) { + break; + } + if (ctxt->errNr > errNr) + xmlRelaxNGPopErrors(ctxt, errNr); + /* no break on purpose */ + case XML_RELAXNG_ZEROORMORE:{ + int progress; + xmlRelaxNGStatesPtr states = NULL, res = NULL; + int base, j; + + errNr = ctxt->errNr; + res = xmlRelaxNGNewStates(ctxt, 1); + if (res == NULL) { + ret = -1; + break; + } + /* + * All the input states are also exit states + */ + if (ctxt->state != NULL) { + xmlRelaxNGAddStates(ctxt, res, + xmlRelaxNGCopyValidState(ctxt, + ctxt-> + state)); + } else { + for (j = 0; j < ctxt->states->nbState; j++) { + xmlRelaxNGAddStates(ctxt, res, + xmlRelaxNGCopyValidState(ctxt, + ctxt-> + states-> + tabState + [j])); + } + } + oldflags = ctxt->flags; + ctxt->flags |= FLAGS_IGNORABLE; + do { + progress = 0; + base = res->nbState; + + if (ctxt->states != NULL) { + states = ctxt->states; + for (i = 0; i < states->nbState; i++) { + ctxt->state = states->tabState[i]; + ctxt->states = NULL; + ret = xmlRelaxNGValidateDefinitionList(ctxt, + define-> + content); + if (ret == 0) { + if (ctxt->state != NULL) { + tmp = xmlRelaxNGAddStates(ctxt, res, + ctxt->state); + ctxt->state = NULL; + if (tmp == 1) + progress = 1; + } else if (ctxt->states != NULL) { + for (j = 0; j < ctxt->states->nbState; + j++) { + tmp = + xmlRelaxNGAddStates(ctxt, res, + ctxt-> + states-> + tabState + [j]); + if (tmp == 1) + progress = 1; + } + xmlRelaxNGFreeStates(ctxt, + ctxt->states); + ctxt->states = NULL; + } + } else { + if (ctxt->state != NULL) { + xmlRelaxNGFreeValidState(ctxt, + ctxt->state); + ctxt->state = NULL; + } + } + } + } else { + ret = xmlRelaxNGValidateDefinitionList(ctxt, + define-> + content); + if (ret != 0) { + xmlRelaxNGFreeValidState(ctxt, ctxt->state); + ctxt->state = NULL; + } else { + base = res->nbState; + if (ctxt->state != NULL) { + tmp = xmlRelaxNGAddStates(ctxt, res, + ctxt->state); + ctxt->state = NULL; + if (tmp == 1) + progress = 1; + } else if (ctxt->states != NULL) { + for (j = 0; j < ctxt->states->nbState; j++) { + tmp = xmlRelaxNGAddStates(ctxt, res, + ctxt-> + states-> + tabState[j]); + if (tmp == 1) + progress = 1; + } + if (states == NULL) { + states = ctxt->states; + } else { + xmlRelaxNGFreeStates(ctxt, + ctxt->states); + } + ctxt->states = NULL; + } + } + } + if (progress) { + /* + * Collect all the new nodes added at that step + * and make them the new node set + */ + if (res->nbState - base == 1) { + ctxt->state = xmlRelaxNGCopyValidState(ctxt, + res-> + tabState + [base]); + } else { + if (states == NULL) { + xmlRelaxNGNewStates(ctxt, + res->nbState - base); + states = ctxt->states; + if (states == NULL) { + progress = 0; + break; + } + } + states->nbState = 0; + for (i = base; i < res->nbState; i++) + xmlRelaxNGAddStates(ctxt, states, + xmlRelaxNGCopyValidState + (ctxt, + res->tabState[i])); + ctxt->states = states; + } + } + } while (progress == 1); + if (states != NULL) { + xmlRelaxNGFreeStates(ctxt, states); + } + ctxt->states = res; + ctxt->flags = oldflags; +#if 0 + /* + * errors may have to be propagated back... + */ + if (ctxt->errNr > errNr) + xmlRelaxNGPopErrors(ctxt, errNr); +#endif + ret = 0; + break; + } + case XML_RELAXNG_CHOICE:{ + xmlRelaxNGDefinePtr list = NULL; + xmlRelaxNGStatesPtr states = NULL; + + node = xmlRelaxNGSkipIgnored(ctxt, node); + + errNr = ctxt->errNr; + if ((define->dflags & IS_TRIABLE) && (define->data != NULL) && + (node != NULL)) { + /* + * node == NULL can't be optimized since IS_TRIABLE + * doesn't account for choice which may lead to + * only attributes. + */ + xmlHashTablePtr triage = + (xmlHashTablePtr) define->data; + + /* + * Something we can optimize cleanly there is only one + * possble branch out ! + */ + if ((node->type == XML_TEXT_NODE) || + (node->type == XML_CDATA_SECTION_NODE)) { + list = + xmlHashLookup2(triage, BAD_CAST "#text", NULL); + } else if (node->type == XML_ELEMENT_NODE) { + if (node->ns != NULL) { + list = xmlHashLookup2(triage, node->name, + node->ns->href); + if (list == NULL) + list = + xmlHashLookup2(triage, BAD_CAST "#any", + node->ns->href); + } else + list = + xmlHashLookup2(triage, node->name, NULL); + if (list == NULL) + list = + xmlHashLookup2(triage, BAD_CAST "#any", + NULL); + } + if (list == NULL) { + ret = -1; + VALID_ERR2(XML_RELAXNG_ERR_ELEMWRONG, node->name); + break; + } + ret = xmlRelaxNGValidateDefinition(ctxt, list); + if (ret == 0) { + } + break; + } + + list = define->content; + oldflags = ctxt->flags; + ctxt->flags |= FLAGS_IGNORABLE; + + while (list != NULL) { + oldstate = xmlRelaxNGCopyValidState(ctxt, ctxt->state); + ret = xmlRelaxNGValidateDefinition(ctxt, list); + if (ret == 0) { + if (states == NULL) { + states = xmlRelaxNGNewStates(ctxt, 1); + } + if (ctxt->state != NULL) { + xmlRelaxNGAddStates(ctxt, states, ctxt->state); + } else if (ctxt->states != NULL) { + for (i = 0; i < ctxt->states->nbState; i++) { + xmlRelaxNGAddStates(ctxt, states, + ctxt->states-> + tabState[i]); + } + xmlRelaxNGFreeStates(ctxt, ctxt->states); + ctxt->states = NULL; + } + } else { + xmlRelaxNGFreeValidState(ctxt, ctxt->state); + } + ctxt->state = oldstate; + list = list->next; + } + if (states != NULL) { + xmlRelaxNGFreeValidState(ctxt, oldstate); + ctxt->states = states; + ctxt->state = NULL; + ret = 0; + } else { + ctxt->states = NULL; + } + ctxt->flags = oldflags; + if (ret != 0) { + if ((ctxt->flags & FLAGS_IGNORABLE) == 0) { + xmlRelaxNGDumpValidError(ctxt); + } + } else { + if (ctxt->errNr > errNr) + xmlRelaxNGPopErrors(ctxt, errNr); + } + break; + } + case XML_RELAXNG_DEF: + case XML_RELAXNG_GROUP: + ret = xmlRelaxNGValidateDefinitionList(ctxt, define->content); + break; + case XML_RELAXNG_INTERLEAVE: + ret = xmlRelaxNGValidateInterleave(ctxt, define); + break; + case XML_RELAXNG_ATTRIBUTE: + ret = xmlRelaxNGValidateAttribute(ctxt, define); + break; + case XML_RELAXNG_START: + case XML_RELAXNG_NOOP: + case XML_RELAXNG_REF: + case XML_RELAXNG_EXTERNALREF: + case XML_RELAXNG_PARENTREF: + ret = xmlRelaxNGValidateDefinition(ctxt, define->content); + break; + case XML_RELAXNG_DATATYPE:{ + xmlNodePtr child; + xmlChar *content = NULL; + + child = node; + while (child != NULL) { + if (child->type == XML_ELEMENT_NODE) { + VALID_ERR2(XML_RELAXNG_ERR_DATAELEM, + node->parent->name); + ret = -1; + break; + } else if ((child->type == XML_TEXT_NODE) || + (child->type == XML_CDATA_SECTION_NODE)) { + content = xmlStrcat(content, child->content); + } + /* TODO: handle entities ... */ + child = child->next; + } + if (ret == -1) { + if (content != NULL) + xmlFree(content); + break; + } + if (content == NULL) { + content = xmlStrdup(BAD_CAST ""); + if (content == NULL) { + xmlRngVErrMemory(ctxt, "validating\n"); + ret = -1; + break; + } + } + ret = xmlRelaxNGValidateDatatype(ctxt, content, define, + ctxt->state->seq); + if (ret == -1) { + VALID_ERR2(XML_RELAXNG_ERR_DATATYPE, define->name); + } else if (ret == 0) { + ctxt->state->seq = NULL; + } + if (content != NULL) + xmlFree(content); + break; + } + case XML_RELAXNG_VALUE:{ + xmlChar *content = NULL; + xmlChar *oldvalue; + xmlNodePtr child; + + child = node; + while (child != NULL) { + if (child->type == XML_ELEMENT_NODE) { + VALID_ERR2(XML_RELAXNG_ERR_VALELEM, + node->parent->name); + ret = -1; + break; + } else if ((child->type == XML_TEXT_NODE) || + (child->type == XML_CDATA_SECTION_NODE)) { + content = xmlStrcat(content, child->content); + } + /* TODO: handle entities ... */ + child = child->next; + } + if (ret == -1) { + if (content != NULL) + xmlFree(content); + break; + } + if (content == NULL) { + content = xmlStrdup(BAD_CAST ""); + if (content == NULL) { + xmlRngVErrMemory(ctxt, "validating\n"); + ret = -1; + break; + } + } + oldvalue = ctxt->state->value; + ctxt->state->value = content; + ret = xmlRelaxNGValidateValue(ctxt, define); + ctxt->state->value = oldvalue; + if (ret == -1) { + VALID_ERR2(XML_RELAXNG_ERR_VALUE, define->name); + } else if (ret == 0) { + ctxt->state->seq = NULL; + } + if (content != NULL) + xmlFree(content); + break; + } + case XML_RELAXNG_LIST:{ + xmlChar *content; + xmlNodePtr child; + xmlChar *oldvalue, *oldendvalue; + int len; + + /* + * Make sure it's only text nodes + */ + + content = NULL; + child = node; + while (child != NULL) { + if (child->type == XML_ELEMENT_NODE) { + VALID_ERR2(XML_RELAXNG_ERR_LISTELEM, + node->parent->name); + ret = -1; + break; + } else if ((child->type == XML_TEXT_NODE) || + (child->type == XML_CDATA_SECTION_NODE)) { + content = xmlStrcat(content, child->content); + } + /* TODO: handle entities ... */ + child = child->next; + } + if (ret == -1) { + if (content != NULL) + xmlFree(content); + break; + } + if (content == NULL) { + content = xmlStrdup(BAD_CAST ""); + if (content == NULL) { + xmlRngVErrMemory(ctxt, "validating\n"); + ret = -1; + break; + } + } + len = xmlStrlen(content); + oldvalue = ctxt->state->value; + oldendvalue = ctxt->state->endvalue; + ctxt->state->value = content; + ctxt->state->endvalue = content + len; + ret = xmlRelaxNGValidateValue(ctxt, define); + ctxt->state->value = oldvalue; + ctxt->state->endvalue = oldendvalue; + if (ret == -1) { + VALID_ERR(XML_RELAXNG_ERR_LIST); + } else if ((ret == 0) && (node != NULL)) { + ctxt->state->seq = node->next; + } + if (content != NULL) + xmlFree(content); + break; + } + case XML_RELAXNG_EXCEPT: + case XML_RELAXNG_PARAM: + TODO ret = -1; + break; + } + ctxt->depth--; +#ifdef DEBUG + for (i = 0; i < ctxt->depth; i++) + xmlGenericError(xmlGenericErrorContext, " "); + xmlGenericError(xmlGenericErrorContext, + "Validating %s ", xmlRelaxNGDefName(define)); + if (define->name != NULL) + xmlGenericError(xmlGenericErrorContext, "%s ", define->name); + if (ret == 0) + xmlGenericError(xmlGenericErrorContext, "suceeded\n"); + else + xmlGenericError(xmlGenericErrorContext, "failed\n"); +#endif + return (ret); +} + +/** + * xmlRelaxNGValidateDefinition: + * @ctxt: a Relax-NG validation context + * @define: the definition to verify + * + * Validate the current node lists against the definition + * + * Returns 0 if the validation succeeded or an error code. + */ +static int +xmlRelaxNGValidateDefinition(xmlRelaxNGValidCtxtPtr ctxt, + xmlRelaxNGDefinePtr define) +{ + xmlRelaxNGStatesPtr states, res; + int i, j, k, ret, oldflags; + + /* + * We should NOT have both ctxt->state and ctxt->states + */ + if ((ctxt->state != NULL) && (ctxt->states != NULL)) { + TODO xmlRelaxNGFreeValidState(ctxt, ctxt->state); + ctxt->state = NULL; + } + + if ((ctxt->states == NULL) || (ctxt->states->nbState == 1)) { + if (ctxt->states != NULL) { + ctxt->state = ctxt->states->tabState[0]; + xmlRelaxNGFreeStates(ctxt, ctxt->states); + ctxt->states = NULL; + } + ret = xmlRelaxNGValidateState(ctxt, define); + if ((ctxt->state != NULL) && (ctxt->states != NULL)) { + TODO xmlRelaxNGFreeValidState(ctxt, ctxt->state); + ctxt->state = NULL; + } + if ((ctxt->states != NULL) && (ctxt->states->nbState == 1)) { + ctxt->state = ctxt->states->tabState[0]; + xmlRelaxNGFreeStates(ctxt, ctxt->states); + ctxt->states = NULL; + } + return (ret); + } + + states = ctxt->states; + ctxt->states = NULL; + res = NULL; + j = 0; + oldflags = ctxt->flags; + ctxt->flags |= FLAGS_IGNORABLE; + for (i = 0; i < states->nbState; i++) { + ctxt->state = states->tabState[i]; + ctxt->states = NULL; + ret = xmlRelaxNGValidateState(ctxt, define); + /* + * We should NOT have both ctxt->state and ctxt->states + */ + if ((ctxt->state != NULL) && (ctxt->states != NULL)) { + TODO xmlRelaxNGFreeValidState(ctxt, ctxt->state); + ctxt->state = NULL; + } + if (ret == 0) { + if (ctxt->states == NULL) { + if (res != NULL) { + /* add the state to the container */ + xmlRelaxNGAddStates(ctxt, res, ctxt->state); + ctxt->state = NULL; + } else { + /* add the state directly in states */ + states->tabState[j++] = ctxt->state; + ctxt->state = NULL; + } + } else { + if (res == NULL) { + /* make it the new container and copy other results */ + res = ctxt->states; + ctxt->states = NULL; + for (k = 0; k < j; k++) + xmlRelaxNGAddStates(ctxt, res, + states->tabState[k]); + } else { + /* add all the new results to res and reff the container */ + for (k = 0; k < ctxt->states->nbState; k++) + xmlRelaxNGAddStates(ctxt, res, + ctxt->states->tabState[k]); + xmlRelaxNGFreeStates(ctxt, ctxt->states); + ctxt->states = NULL; + } + } + } else { + if (ctxt->state != NULL) { + xmlRelaxNGFreeValidState(ctxt, ctxt->state); + ctxt->state = NULL; + } else if (ctxt->states != NULL) { + for (k = 0; k < ctxt->states->nbState; k++) + xmlRelaxNGFreeValidState(ctxt, + ctxt->states->tabState[k]); + xmlRelaxNGFreeStates(ctxt, ctxt->states); + ctxt->states = NULL; + } + } + } + ctxt->flags = oldflags; + if (res != NULL) { + xmlRelaxNGFreeStates(ctxt, states); + ctxt->states = res; + ret = 0; + } else if (j > 1) { + states->nbState = j; + ctxt->states = states; + ret = 0; + } else if (j == 1) { + ctxt->state = states->tabState[0]; + xmlRelaxNGFreeStates(ctxt, states); + ret = 0; + } else { + ret = -1; + xmlRelaxNGFreeStates(ctxt, states); + if (ctxt->states != NULL) { + xmlRelaxNGFreeStates(ctxt, ctxt->states); + ctxt->states = NULL; + } + } + if ((ctxt->state != NULL) && (ctxt->states != NULL)) { + TODO xmlRelaxNGFreeValidState(ctxt, ctxt->state); + ctxt->state = NULL; + } + return (ret); +} + +/** + * xmlRelaxNGValidateDocument: + * @ctxt: a Relax-NG validation context + * @doc: the document + * + * Validate the given document + * + * Returns 0 if the validation succeeded or an error code. + */ +static int +xmlRelaxNGValidateDocument(xmlRelaxNGValidCtxtPtr ctxt, xmlDocPtr doc) +{ + int ret; + xmlRelaxNGPtr schema; + xmlRelaxNGGrammarPtr grammar; + xmlRelaxNGValidStatePtr state; + xmlNodePtr node; + + if ((ctxt == NULL) || (ctxt->schema == NULL) || (doc == NULL)) + return (-1); + + ctxt->errNo = XML_RELAXNG_OK; + schema = ctxt->schema; + grammar = schema->topgrammar; + if (grammar == NULL) { + VALID_ERR(XML_RELAXNG_ERR_NOGRAMMAR); + return (-1); + } + state = xmlRelaxNGNewValidState(ctxt, NULL); + ctxt->state = state; + ret = xmlRelaxNGValidateDefinition(ctxt, grammar->start); + if ((ctxt->state != NULL) && (state->seq != NULL)) { + state = ctxt->state; + node = state->seq; + node = xmlRelaxNGSkipIgnored(ctxt, node); + if (node != NULL) { + if (ret != -1) { + VALID_ERR(XML_RELAXNG_ERR_EXTRADATA); + ret = -1; + } + } + } else if (ctxt->states != NULL) { + int i; + int tmp = -1; + + for (i = 0; i < ctxt->states->nbState; i++) { + state = ctxt->states->tabState[i]; + node = state->seq; + node = xmlRelaxNGSkipIgnored(ctxt, node); + if (node == NULL) + tmp = 0; + xmlRelaxNGFreeValidState(ctxt, state); + } + if (tmp == -1) { + if (ret != -1) { + VALID_ERR(XML_RELAXNG_ERR_EXTRADATA); + ret = -1; + } + } + } + if (ctxt->state != NULL) { + xmlRelaxNGFreeValidState(ctxt, ctxt->state); + ctxt->state = NULL; + } + if (ret != 0) + xmlRelaxNGDumpValidError(ctxt); +#ifdef DEBUG + else if (ctxt->errNr != 0) { + ctxt->error(ctxt->userData, + "%d Extra error messages left on stack !\n", + ctxt->errNr); + xmlRelaxNGDumpValidError(ctxt); + } +#endif +#ifdef LIBXML_VALID_ENABLED + if (ctxt->idref == 1) { + xmlValidCtxt vctxt; + + memset(&vctxt, 0, sizeof(xmlValidCtxt)); + vctxt.valid = 1; + vctxt.error = ctxt->error; + vctxt.warning = ctxt->warning; + vctxt.userData = ctxt->userData; + + if (xmlValidateDocumentFinal(&vctxt, doc) != 1) + ret = -1; + } +#endif /* LIBXML_VALID_ENABLED */ + if ((ret == 0) && (ctxt->errNo != XML_RELAXNG_OK)) + ret = -1; + + return (ret); +} + +/************************************************************************ + * * + * Validation interfaces * + * * + ************************************************************************/ + +/** + * xmlRelaxNGNewValidCtxt: + * @schema: a precompiled XML RelaxNGs + * + * Create an XML RelaxNGs validation context based on the given schema + * + * Returns the validation context or NULL in case of error + */ +xmlRelaxNGValidCtxtPtr +xmlRelaxNGNewValidCtxt(xmlRelaxNGPtr schema) +{ + xmlRelaxNGValidCtxtPtr ret; + + ret = (xmlRelaxNGValidCtxtPtr) xmlMalloc(sizeof(xmlRelaxNGValidCtxt)); + if (ret == NULL) { + xmlRngVErrMemory(NULL, "building context\n"); + return (NULL); + } + memset(ret, 0, sizeof(xmlRelaxNGValidCtxt)); + ret->schema = schema; + ret->error = xmlGenericError; + ret->userData = xmlGenericErrorContext; + ret->errNr = 0; + ret->errMax = 0; + ret->err = NULL; + ret->errTab = NULL; + if (schema != NULL) + ret->idref = schema->idref; + ret->states = NULL; + ret->freeState = NULL; + ret->freeStates = NULL; + ret->errNo = XML_RELAXNG_OK; + return (ret); +} + +/** + * xmlRelaxNGFreeValidCtxt: + * @ctxt: the schema validation context + * + * Free the resources associated to the schema validation context + */ +void +xmlRelaxNGFreeValidCtxt(xmlRelaxNGValidCtxtPtr ctxt) +{ + int k; + + if (ctxt == NULL) + return; + if (ctxt->states != NULL) + xmlRelaxNGFreeStates(NULL, ctxt->states); + if (ctxt->freeState != NULL) { + for (k = 0; k < ctxt->freeState->nbState; k++) { + xmlRelaxNGFreeValidState(NULL, ctxt->freeState->tabState[k]); + } + xmlRelaxNGFreeStates(NULL, ctxt->freeState); + } + if (ctxt->freeStates != NULL) { + for (k = 0; k < ctxt->freeStatesNr; k++) { + xmlRelaxNGFreeStates(NULL, ctxt->freeStates[k]); + } + xmlFree(ctxt->freeStates); + } + if (ctxt->errTab != NULL) + xmlFree(ctxt->errTab); + if (ctxt->elemTab != NULL) { + xmlRegExecCtxtPtr exec; + + exec = xmlRelaxNGElemPop(ctxt); + while (exec != NULL) { + xmlRegFreeExecCtxt(exec); + exec = xmlRelaxNGElemPop(ctxt); + } + xmlFree(ctxt->elemTab); + } + xmlFree(ctxt); +} + +/** + * xmlRelaxNGSetValidErrors: + * @ctxt: a Relax-NG validation context + * @err: the error function + * @warn: the warning function + * @ctx: the functions context + * + * Set the error and warning callback informations + */ +void +xmlRelaxNGSetValidErrors(xmlRelaxNGValidCtxtPtr ctxt, + xmlRelaxNGValidityErrorFunc err, + xmlRelaxNGValidityWarningFunc warn, void *ctx) +{ + if (ctxt == NULL) + return; + ctxt->error = err; + ctxt->warning = warn; + ctxt->userData = ctx; + ctxt->serror = NULL; +} + +/** + * xmlRelaxNGSetValidStructuredErrors: + * @ctxt: a Relax-NG validation context + * @serror: the structured error function + * @ctx: the functions context + * + * Set the structured error callback + */ +void +xmlRelaxNGSetValidStructuredErrors(xmlRelaxNGValidCtxtPtr ctxt, + xmlStructuredErrorFunc serror, void *ctx) +{ + if (ctxt == NULL) + return; + ctxt->serror = serror; + ctxt->error = NULL; + ctxt->warning = NULL; + ctxt->userData = ctx; +} + +/** + * xmlRelaxNGGetValidErrors: + * @ctxt: a Relax-NG validation context + * @err: the error function result + * @warn: the warning function result + * @ctx: the functions context result + * + * Get the error and warning callback informations + * + * Returns -1 in case of error and 0 otherwise + */ +int +xmlRelaxNGGetValidErrors(xmlRelaxNGValidCtxtPtr ctxt, + xmlRelaxNGValidityErrorFunc * err, + xmlRelaxNGValidityWarningFunc * warn, void **ctx) +{ + if (ctxt == NULL) + return (-1); + if (err != NULL) + *err = ctxt->error; + if (warn != NULL) + *warn = ctxt->warning; + if (ctx != NULL) + *ctx = ctxt->userData; + return (0); +} + +/** + * xmlRelaxNGValidateDoc: + * @ctxt: a Relax-NG validation context + * @doc: a parsed document tree + * + * Validate a document tree in memory. + * + * Returns 0 if the document is valid, a positive error code + * number otherwise and -1 in case of internal or API error. + */ +int +xmlRelaxNGValidateDoc(xmlRelaxNGValidCtxtPtr ctxt, xmlDocPtr doc) +{ + int ret; + + if ((ctxt == NULL) || (doc == NULL)) + return (-1); + + ctxt->doc = doc; + + ret = xmlRelaxNGValidateDocument(ctxt, doc); + /* + * TODO: build error codes + */ + if (ret == -1) + return (1); + return (ret); +} + +#define bottom_relaxng +#include "elfgcchack.h" +#endif /* LIBXML_SCHEMAS_ENABLED */ diff --git a/gettext-tools/gnulib-lib/libxml/relaxng.in.h b/gettext-tools/gnulib-lib/libxml/relaxng.in.h new file mode 100644 index 0000000..6acd467 --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/relaxng.in.h @@ -0,0 +1,196 @@ +/* + * Summary: implementation of the Relax-NG validation + * Description: implementation of the Relax-NG validation + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + +#ifndef __XML_RELAX_NG__ +#define __XML_RELAX_NG__ + +#include +#include +#include + +#ifdef LIBXML_SCHEMAS_ENABLED + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _xmlRelaxNG xmlRelaxNG; +typedef xmlRelaxNG *xmlRelaxNGPtr; + + +/** + * A schemas validation context + */ +typedef void (XMLCDECL *xmlRelaxNGValidityErrorFunc) (void *ctx, const char *msg, ...); +typedef void (XMLCDECL *xmlRelaxNGValidityWarningFunc) (void *ctx, const char *msg, ...); + +typedef struct _xmlRelaxNGParserCtxt xmlRelaxNGParserCtxt; +typedef xmlRelaxNGParserCtxt *xmlRelaxNGParserCtxtPtr; + +typedef struct _xmlRelaxNGValidCtxt xmlRelaxNGValidCtxt; +typedef xmlRelaxNGValidCtxt *xmlRelaxNGValidCtxtPtr; + +/* + * xmlRelaxNGValidErr: + * + * List of possible Relax NG validation errors + */ +typedef enum { + XML_RELAXNG_OK = 0, + XML_RELAXNG_ERR_MEMORY, + XML_RELAXNG_ERR_TYPE, + XML_RELAXNG_ERR_TYPEVAL, + XML_RELAXNG_ERR_DUPID, + XML_RELAXNG_ERR_TYPECMP, + XML_RELAXNG_ERR_NOSTATE, + XML_RELAXNG_ERR_NODEFINE, + XML_RELAXNG_ERR_LISTEXTRA, + XML_RELAXNG_ERR_LISTEMPTY, + XML_RELAXNG_ERR_INTERNODATA, + XML_RELAXNG_ERR_INTERSEQ, + XML_RELAXNG_ERR_INTEREXTRA, + XML_RELAXNG_ERR_ELEMNAME, + XML_RELAXNG_ERR_ATTRNAME, + XML_RELAXNG_ERR_ELEMNONS, + XML_RELAXNG_ERR_ATTRNONS, + XML_RELAXNG_ERR_ELEMWRONGNS, + XML_RELAXNG_ERR_ATTRWRONGNS, + XML_RELAXNG_ERR_ELEMEXTRANS, + XML_RELAXNG_ERR_ATTREXTRANS, + XML_RELAXNG_ERR_ELEMNOTEMPTY, + XML_RELAXNG_ERR_NOELEM, + XML_RELAXNG_ERR_NOTELEM, + XML_RELAXNG_ERR_ATTRVALID, + XML_RELAXNG_ERR_CONTENTVALID, + XML_RELAXNG_ERR_EXTRACONTENT, + XML_RELAXNG_ERR_INVALIDATTR, + XML_RELAXNG_ERR_DATAELEM, + XML_RELAXNG_ERR_VALELEM, + XML_RELAXNG_ERR_LISTELEM, + XML_RELAXNG_ERR_DATATYPE, + XML_RELAXNG_ERR_VALUE, + XML_RELAXNG_ERR_LIST, + XML_RELAXNG_ERR_NOGRAMMAR, + XML_RELAXNG_ERR_EXTRADATA, + XML_RELAXNG_ERR_LACKDATA, + XML_RELAXNG_ERR_INTERNAL, + XML_RELAXNG_ERR_ELEMWRONG, + XML_RELAXNG_ERR_TEXTWRONG +} xmlRelaxNGValidErr; + +/* + * xmlRelaxNGParserFlags: + * + * List of possible Relax NG Parser flags + */ +typedef enum { + XML_RELAXNGP_NONE = 0, + XML_RELAXNGP_FREE_DOC = 1, + XML_RELAXNGP_CRNG = 2 +} xmlRelaxNGParserFlag; + +XMLPUBFUN int XMLCALL + xmlRelaxNGInitTypes (void); +XMLPUBFUN void XMLCALL + xmlRelaxNGCleanupTypes (void); + +/* + * Interfaces for parsing. + */ +XMLPUBFUN xmlRelaxNGParserCtxtPtr XMLCALL + xmlRelaxNGNewParserCtxt (const char *URL); +XMLPUBFUN xmlRelaxNGParserCtxtPtr XMLCALL + xmlRelaxNGNewMemParserCtxt (const char *buffer, + int size); +XMLPUBFUN xmlRelaxNGParserCtxtPtr XMLCALL + xmlRelaxNGNewDocParserCtxt (xmlDocPtr doc); + +XMLPUBFUN int XMLCALL + xmlRelaxParserSetFlag (xmlRelaxNGParserCtxtPtr ctxt, + int flag); + +XMLPUBFUN void XMLCALL + xmlRelaxNGFreeParserCtxt (xmlRelaxNGParserCtxtPtr ctxt); +XMLPUBFUN void XMLCALL + xmlRelaxNGSetParserErrors(xmlRelaxNGParserCtxtPtr ctxt, + xmlRelaxNGValidityErrorFunc err, + xmlRelaxNGValidityWarningFunc warn, + void *ctx); +XMLPUBFUN int XMLCALL + xmlRelaxNGGetParserErrors(xmlRelaxNGParserCtxtPtr ctxt, + xmlRelaxNGValidityErrorFunc *err, + xmlRelaxNGValidityWarningFunc *warn, + void **ctx); +XMLPUBFUN void XMLCALL + xmlRelaxNGSetParserStructuredErrors( + xmlRelaxNGParserCtxtPtr ctxt, + xmlStructuredErrorFunc serror, + void *ctx); +XMLPUBFUN xmlRelaxNGPtr XMLCALL + xmlRelaxNGParse (xmlRelaxNGParserCtxtPtr ctxt); +XMLPUBFUN void XMLCALL + xmlRelaxNGFree (xmlRelaxNGPtr schema); +#ifdef LIBXML_OUTPUT_ENABLED +XMLPUBFUN void XMLCALL + xmlRelaxNGDump (FILE *output, + xmlRelaxNGPtr schema); +XMLPUBFUN void XMLCALL + xmlRelaxNGDumpTree (FILE * output, + xmlRelaxNGPtr schema); +#endif /* LIBXML_OUTPUT_ENABLED */ +/* + * Interfaces for validating + */ +XMLPUBFUN void XMLCALL + xmlRelaxNGSetValidErrors(xmlRelaxNGValidCtxtPtr ctxt, + xmlRelaxNGValidityErrorFunc err, + xmlRelaxNGValidityWarningFunc warn, + void *ctx); +XMLPUBFUN int XMLCALL + xmlRelaxNGGetValidErrors(xmlRelaxNGValidCtxtPtr ctxt, + xmlRelaxNGValidityErrorFunc *err, + xmlRelaxNGValidityWarningFunc *warn, + void **ctx); +XMLPUBFUN void XMLCALL + xmlRelaxNGSetValidStructuredErrors(xmlRelaxNGValidCtxtPtr ctxt, + xmlStructuredErrorFunc serror, void *ctx); +XMLPUBFUN xmlRelaxNGValidCtxtPtr XMLCALL + xmlRelaxNGNewValidCtxt (xmlRelaxNGPtr schema); +XMLPUBFUN void XMLCALL + xmlRelaxNGFreeValidCtxt (xmlRelaxNGValidCtxtPtr ctxt); +XMLPUBFUN int XMLCALL + xmlRelaxNGValidateDoc (xmlRelaxNGValidCtxtPtr ctxt, + xmlDocPtr doc); +/* + * Interfaces for progressive validation when possible + */ +XMLPUBFUN int XMLCALL + xmlRelaxNGValidatePushElement (xmlRelaxNGValidCtxtPtr ctxt, + xmlDocPtr doc, + xmlNodePtr elem); +XMLPUBFUN int XMLCALL + xmlRelaxNGValidatePushCData (xmlRelaxNGValidCtxtPtr ctxt, + const xmlChar *data, + int len); +XMLPUBFUN int XMLCALL + xmlRelaxNGValidatePopElement (xmlRelaxNGValidCtxtPtr ctxt, + xmlDocPtr doc, + xmlNodePtr elem); +XMLPUBFUN int XMLCALL + xmlRelaxNGValidateFullElement (xmlRelaxNGValidCtxtPtr ctxt, + xmlDocPtr doc, + xmlNodePtr elem); + +#ifdef __cplusplus +} +#endif + +#endif /* LIBXML_SCHEMAS_ENABLED */ + +#endif /* __XML_RELAX_NG__ */ diff --git a/gettext-tools/gnulib-lib/libxml/schemasInternals.in.h b/gettext-tools/gnulib-lib/libxml/schemasInternals.in.h new file mode 100644 index 0000000..b68a6e1 --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/schemasInternals.in.h @@ -0,0 +1,958 @@ +/* + * Summary: internal interfaces for XML Schemas + * Description: internal interfaces for the XML Schemas handling + * and schema validity checking + * The Schemas development is a Work In Progress. + * Some of those interfaces are not garanteed to be API or ABI stable ! + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + + +#ifndef __XML_SCHEMA_INTERNALS_H__ +#define __XML_SCHEMA_INTERNALS_H__ + +#include + +#ifdef LIBXML_SCHEMAS_ENABLED + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + XML_SCHEMAS_UNKNOWN = 0, + XML_SCHEMAS_STRING, + XML_SCHEMAS_NORMSTRING, + XML_SCHEMAS_DECIMAL, + XML_SCHEMAS_TIME, + XML_SCHEMAS_GDAY, + XML_SCHEMAS_GMONTH, + XML_SCHEMAS_GMONTHDAY, + XML_SCHEMAS_GYEAR, + XML_SCHEMAS_GYEARMONTH, + XML_SCHEMAS_DATE, + XML_SCHEMAS_DATETIME, + XML_SCHEMAS_DURATION, + XML_SCHEMAS_FLOAT, + XML_SCHEMAS_DOUBLE, + XML_SCHEMAS_BOOLEAN, + XML_SCHEMAS_TOKEN, + XML_SCHEMAS_LANGUAGE, + XML_SCHEMAS_NMTOKEN, + XML_SCHEMAS_NMTOKENS, + XML_SCHEMAS_NAME, + XML_SCHEMAS_QNAME, + XML_SCHEMAS_NCNAME, + XML_SCHEMAS_ID, + XML_SCHEMAS_IDREF, + XML_SCHEMAS_IDREFS, + XML_SCHEMAS_ENTITY, + XML_SCHEMAS_ENTITIES, + XML_SCHEMAS_NOTATION, + XML_SCHEMAS_ANYURI, + XML_SCHEMAS_INTEGER, + XML_SCHEMAS_NPINTEGER, + XML_SCHEMAS_NINTEGER, + XML_SCHEMAS_NNINTEGER, + XML_SCHEMAS_PINTEGER, + XML_SCHEMAS_INT, + XML_SCHEMAS_UINT, + XML_SCHEMAS_LONG, + XML_SCHEMAS_ULONG, + XML_SCHEMAS_SHORT, + XML_SCHEMAS_USHORT, + XML_SCHEMAS_BYTE, + XML_SCHEMAS_UBYTE, + XML_SCHEMAS_HEXBINARY, + XML_SCHEMAS_BASE64BINARY, + XML_SCHEMAS_ANYTYPE, + XML_SCHEMAS_ANYSIMPLETYPE +} xmlSchemaValType; + +/* + * XML Schemas defines multiple type of types. + */ +typedef enum { + XML_SCHEMA_TYPE_BASIC = 1, /* A built-in datatype */ + XML_SCHEMA_TYPE_ANY, + XML_SCHEMA_TYPE_FACET, + XML_SCHEMA_TYPE_SIMPLE, + XML_SCHEMA_TYPE_COMPLEX, + XML_SCHEMA_TYPE_SEQUENCE = 6, + XML_SCHEMA_TYPE_CHOICE, + XML_SCHEMA_TYPE_ALL, + XML_SCHEMA_TYPE_SIMPLE_CONTENT, + XML_SCHEMA_TYPE_COMPLEX_CONTENT, + XML_SCHEMA_TYPE_UR, + XML_SCHEMA_TYPE_RESTRICTION, + XML_SCHEMA_TYPE_EXTENSION, + XML_SCHEMA_TYPE_ELEMENT, + XML_SCHEMA_TYPE_ATTRIBUTE, + XML_SCHEMA_TYPE_ATTRIBUTEGROUP, + XML_SCHEMA_TYPE_GROUP, + XML_SCHEMA_TYPE_NOTATION, + XML_SCHEMA_TYPE_LIST, + XML_SCHEMA_TYPE_UNION, + XML_SCHEMA_TYPE_ANY_ATTRIBUTE, + XML_SCHEMA_TYPE_IDC_UNIQUE, + XML_SCHEMA_TYPE_IDC_KEY, + XML_SCHEMA_TYPE_IDC_KEYREF, + XML_SCHEMA_TYPE_PARTICLE = 25, + XML_SCHEMA_TYPE_ATTRIBUTE_USE, + XML_SCHEMA_FACET_MININCLUSIVE = 1000, + XML_SCHEMA_FACET_MINEXCLUSIVE, + XML_SCHEMA_FACET_MAXINCLUSIVE, + XML_SCHEMA_FACET_MAXEXCLUSIVE, + XML_SCHEMA_FACET_TOTALDIGITS, + XML_SCHEMA_FACET_FRACTIONDIGITS, + XML_SCHEMA_FACET_PATTERN, + XML_SCHEMA_FACET_ENUMERATION, + XML_SCHEMA_FACET_WHITESPACE, + XML_SCHEMA_FACET_LENGTH, + XML_SCHEMA_FACET_MAXLENGTH, + XML_SCHEMA_FACET_MINLENGTH, + XML_SCHEMA_EXTRA_QNAMEREF = 2000, + XML_SCHEMA_EXTRA_ATTR_USE_PROHIB +} xmlSchemaTypeType; + +typedef enum { + XML_SCHEMA_CONTENT_UNKNOWN = 0, + XML_SCHEMA_CONTENT_EMPTY = 1, + XML_SCHEMA_CONTENT_ELEMENTS, + XML_SCHEMA_CONTENT_MIXED, + XML_SCHEMA_CONTENT_SIMPLE, + XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS, /* Obsolete */ + XML_SCHEMA_CONTENT_BASIC, + XML_SCHEMA_CONTENT_ANY +} xmlSchemaContentType; + +typedef struct _xmlSchemaVal xmlSchemaVal; +typedef xmlSchemaVal *xmlSchemaValPtr; + +typedef struct _xmlSchemaType xmlSchemaType; +typedef xmlSchemaType *xmlSchemaTypePtr; + +typedef struct _xmlSchemaFacet xmlSchemaFacet; +typedef xmlSchemaFacet *xmlSchemaFacetPtr; + +/** + * Annotation + */ +typedef struct _xmlSchemaAnnot xmlSchemaAnnot; +typedef xmlSchemaAnnot *xmlSchemaAnnotPtr; +struct _xmlSchemaAnnot { + struct _xmlSchemaAnnot *next; + xmlNodePtr content; /* the annotation */ +}; + +/** + * XML_SCHEMAS_ANYATTR_SKIP: + * + * Skip unknown attribute from validation + * Obsolete, not used anymore. + */ +#define XML_SCHEMAS_ANYATTR_SKIP 1 +/** + * XML_SCHEMAS_ANYATTR_LAX: + * + * Ignore validation non definition on attributes + * Obsolete, not used anymore. + */ +#define XML_SCHEMAS_ANYATTR_LAX 2 +/** + * XML_SCHEMAS_ANYATTR_STRICT: + * + * Apply strict validation rules on attributes + * Obsolete, not used anymore. + */ +#define XML_SCHEMAS_ANYATTR_STRICT 3 +/** + * XML_SCHEMAS_ANY_SKIP: + * + * Skip unknown attribute from validation + */ +#define XML_SCHEMAS_ANY_SKIP 1 +/** + * XML_SCHEMAS_ANY_LAX: + * + * Used by wildcards. + * Validate if type found, don't worry if not found + */ +#define XML_SCHEMAS_ANY_LAX 2 +/** + * XML_SCHEMAS_ANY_STRICT: + * + * Used by wildcards. + * Apply strict validation rules + */ +#define XML_SCHEMAS_ANY_STRICT 3 +/** + * XML_SCHEMAS_ATTR_USE_PROHIBITED: + * + * Used by wildcards. + * The attribute is prohibited. + */ +#define XML_SCHEMAS_ATTR_USE_PROHIBITED 0 +/** + * XML_SCHEMAS_ATTR_USE_REQUIRED: + * + * The attribute is required. + */ +#define XML_SCHEMAS_ATTR_USE_REQUIRED 1 +/** + * XML_SCHEMAS_ATTR_USE_OPTIONAL: + * + * The attribute is optional. + */ +#define XML_SCHEMAS_ATTR_USE_OPTIONAL 2 +/** + * XML_SCHEMAS_ATTR_GLOBAL: + * + * allow elements in no namespace + */ +#define XML_SCHEMAS_ATTR_GLOBAL 1 << 0 +/** + * XML_SCHEMAS_ATTR_NSDEFAULT: + * + * allow elements in no namespace + */ +#define XML_SCHEMAS_ATTR_NSDEFAULT 1 << 7 +/** + * XML_SCHEMAS_ATTR_INTERNAL_RESOLVED: + * + * this is set when the "type" and "ref" references + * have been resolved. + */ +#define XML_SCHEMAS_ATTR_INTERNAL_RESOLVED 1 << 8 +/** + * XML_SCHEMAS_ATTR_FIXED: + * + * the attribute has a fixed value + */ +#define XML_SCHEMAS_ATTR_FIXED 1 << 9 + +/** + * xmlSchemaAttribute: + * An attribute definition. + */ + +typedef struct _xmlSchemaAttribute xmlSchemaAttribute; +typedef xmlSchemaAttribute *xmlSchemaAttributePtr; +struct _xmlSchemaAttribute { + xmlSchemaTypeType type; + struct _xmlSchemaAttribute *next; /* the next attribute (not used?) */ + const xmlChar *name; /* the name of the declaration */ + const xmlChar *id; /* Deprecated; not used */ + const xmlChar *ref; /* Deprecated; not used */ + const xmlChar *refNs; /* Deprecated; not used */ + const xmlChar *typeName; /* the local name of the type definition */ + const xmlChar *typeNs; /* the ns URI of the type definition */ + xmlSchemaAnnotPtr annot; + + xmlSchemaTypePtr base; /* Deprecated; not used */ + int occurs; /* Deprecated; not used */ + const xmlChar *defValue; /* The initial value of the value constraint */ + xmlSchemaTypePtr subtypes; /* the type definition */ + xmlNodePtr node; + const xmlChar *targetNamespace; + int flags; + const xmlChar *refPrefix; /* Deprecated; not used */ + xmlSchemaValPtr defVal; /* The compiled value constraint */ + xmlSchemaAttributePtr refDecl; /* Deprecated; not used */ +}; + +/** + * xmlSchemaAttributeLink: + * Used to build a list of attribute uses on complexType definitions. + * WARNING: Deprecated; not used. + */ +typedef struct _xmlSchemaAttributeLink xmlSchemaAttributeLink; +typedef xmlSchemaAttributeLink *xmlSchemaAttributeLinkPtr; +struct _xmlSchemaAttributeLink { + struct _xmlSchemaAttributeLink *next;/* the next attribute link ... */ + struct _xmlSchemaAttribute *attr;/* the linked attribute */ +}; + +/** + * XML_SCHEMAS_WILDCARD_COMPLETE: + * + * If the wildcard is complete. + */ +#define XML_SCHEMAS_WILDCARD_COMPLETE 1 << 0 + +/** + * xmlSchemaCharValueLink: + * Used to build a list of namespaces on wildcards. + */ +typedef struct _xmlSchemaWildcardNs xmlSchemaWildcardNs; +typedef xmlSchemaWildcardNs *xmlSchemaWildcardNsPtr; +struct _xmlSchemaWildcardNs { + struct _xmlSchemaWildcardNs *next;/* the next constraint link ... */ + const xmlChar *value;/* the value */ +}; + +/** + * xmlSchemaWildcard. + * A wildcard. + */ +typedef struct _xmlSchemaWildcard xmlSchemaWildcard; +typedef xmlSchemaWildcard *xmlSchemaWildcardPtr; +struct _xmlSchemaWildcard { + xmlSchemaTypeType type; /* The kind of type */ + const xmlChar *id; /* Deprecated; not used */ + xmlSchemaAnnotPtr annot; + xmlNodePtr node; + int minOccurs; /* Deprecated; not used */ + int maxOccurs; /* Deprecated; not used */ + int processContents; + int any; /* Indicates if the ns constraint is of ##any */ + xmlSchemaWildcardNsPtr nsSet; /* The list of allowed namespaces */ + xmlSchemaWildcardNsPtr negNsSet; /* The negated namespace */ + int flags; +}; + +/** + * XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED: + * + * The attribute wildcard has been already builded. + */ +#define XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED 1 << 0 +/** + * XML_SCHEMAS_ATTRGROUP_GLOBAL: + * + * The attribute wildcard has been already builded. + */ +#define XML_SCHEMAS_ATTRGROUP_GLOBAL 1 << 1 +/** + * XML_SCHEMAS_ATTRGROUP_MARKED: + * + * Marks the attr group as marked; used for circular checks. + */ +#define XML_SCHEMAS_ATTRGROUP_MARKED 1 << 2 + +/** + * XML_SCHEMAS_ATTRGROUP_REDEFINED: + * + * The attr group was redefined. + */ +#define XML_SCHEMAS_ATTRGROUP_REDEFINED 1 << 3 +/** + * XML_SCHEMAS_ATTRGROUP_HAS_REFS: + * + * Whether this attr. group contains attr. group references. + */ +#define XML_SCHEMAS_ATTRGROUP_HAS_REFS 1 << 4 + +/** + * An attribute group definition. + * + * xmlSchemaAttribute and xmlSchemaAttributeGroup start of structures + * must be kept similar + */ +typedef struct _xmlSchemaAttributeGroup xmlSchemaAttributeGroup; +typedef xmlSchemaAttributeGroup *xmlSchemaAttributeGroupPtr; +struct _xmlSchemaAttributeGroup { + xmlSchemaTypeType type; /* The kind of type */ + struct _xmlSchemaAttribute *next;/* the next attribute if in a group ... */ + const xmlChar *name; + const xmlChar *id; + const xmlChar *ref; /* Deprecated; not used */ + const xmlChar *refNs; /* Deprecated; not used */ + xmlSchemaAnnotPtr annot; + + xmlSchemaAttributePtr attributes; /* Deprecated; not used */ + xmlNodePtr node; + int flags; + xmlSchemaWildcardPtr attributeWildcard; + const xmlChar *refPrefix; /* Deprecated; not used */ + xmlSchemaAttributeGroupPtr refItem; /* Deprecated; not used */ + const xmlChar *targetNamespace; + void *attrUses; +}; + +/** + * xmlSchemaTypeLink: + * Used to build a list of types (e.g. member types of + * simpleType with variety "union"). + */ +typedef struct _xmlSchemaTypeLink xmlSchemaTypeLink; +typedef xmlSchemaTypeLink *xmlSchemaTypeLinkPtr; +struct _xmlSchemaTypeLink { + struct _xmlSchemaTypeLink *next;/* the next type link ... */ + xmlSchemaTypePtr type;/* the linked type */ +}; + +/** + * xmlSchemaFacetLink: + * Used to build a list of facets. + */ +typedef struct _xmlSchemaFacetLink xmlSchemaFacetLink; +typedef xmlSchemaFacetLink *xmlSchemaFacetLinkPtr; +struct _xmlSchemaFacetLink { + struct _xmlSchemaFacetLink *next;/* the next facet link ... */ + xmlSchemaFacetPtr facet;/* the linked facet */ +}; + +/** + * XML_SCHEMAS_TYPE_MIXED: + * + * the element content type is mixed + */ +#define XML_SCHEMAS_TYPE_MIXED 1 << 0 +/** + * XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION: + * + * the simple or complex type has a derivation method of "extension". + */ +#define XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION 1 << 1 +/** + * XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION: + * + * the simple or complex type has a derivation method of "restriction". + */ +#define XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION 1 << 2 +/** + * XML_SCHEMAS_TYPE_GLOBAL: + * + * the type is global + */ +#define XML_SCHEMAS_TYPE_GLOBAL 1 << 3 +/** + * XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD: + * + * the complexType owns an attribute wildcard, i.e. + * it can be freed by the complexType + */ +#define XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD 1 << 4 /* Obsolete. */ +/** + * XML_SCHEMAS_TYPE_VARIETY_ABSENT: + * + * the simpleType has a variety of "absent". + * TODO: Actually not necessary :-/, since if + * none of the variety flags occur then it's + * automatically absent. + */ +#define XML_SCHEMAS_TYPE_VARIETY_ABSENT 1 << 5 +/** + * XML_SCHEMAS_TYPE_VARIETY_LIST: + * + * the simpleType has a variety of "list". + */ +#define XML_SCHEMAS_TYPE_VARIETY_LIST 1 << 6 +/** + * XML_SCHEMAS_TYPE_VARIETY_UNION: + * + * the simpleType has a variety of "union". + */ +#define XML_SCHEMAS_TYPE_VARIETY_UNION 1 << 7 +/** + * XML_SCHEMAS_TYPE_VARIETY_ATOMIC: + * + * the simpleType has a variety of "union". + */ +#define XML_SCHEMAS_TYPE_VARIETY_ATOMIC 1 << 8 +/** + * XML_SCHEMAS_TYPE_FINAL_EXTENSION: + * + * the complexType has a final of "extension". + */ +#define XML_SCHEMAS_TYPE_FINAL_EXTENSION 1 << 9 +/** + * XML_SCHEMAS_TYPE_FINAL_RESTRICTION: + * + * the simpleType/complexType has a final of "restriction". + */ +#define XML_SCHEMAS_TYPE_FINAL_RESTRICTION 1 << 10 +/** + * XML_SCHEMAS_TYPE_FINAL_LIST: + * + * the simpleType has a final of "list". + */ +#define XML_SCHEMAS_TYPE_FINAL_LIST 1 << 11 +/** + * XML_SCHEMAS_TYPE_FINAL_UNION: + * + * the simpleType has a final of "union". + */ +#define XML_SCHEMAS_TYPE_FINAL_UNION 1 << 12 +/** + * XML_SCHEMAS_TYPE_FINAL_DEFAULT: + * + * the simpleType has a final of "default". + */ +#define XML_SCHEMAS_TYPE_FINAL_DEFAULT 1 << 13 +/** + * XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE: + * + * Marks the item as a builtin primitive. + */ +#define XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE 1 << 14 +/** + * XML_SCHEMAS_TYPE_MARKED: + * + * Marks the item as marked; used for circular checks. + */ +#define XML_SCHEMAS_TYPE_MARKED 1 << 16 +/** + * XML_SCHEMAS_TYPE_BLOCK_DEFAULT: + * + * the complexType did not specify 'block' so use the default of the + * item. + */ +#define XML_SCHEMAS_TYPE_BLOCK_DEFAULT 1 << 17 +/** + * XML_SCHEMAS_TYPE_BLOCK_EXTENSION: + * + * the complexType has a 'block' of "extension". + */ +#define XML_SCHEMAS_TYPE_BLOCK_EXTENSION 1 << 18 +/** + * XML_SCHEMAS_TYPE_BLOCK_RESTRICTION: + * + * the complexType has a 'block' of "restriction". + */ +#define XML_SCHEMAS_TYPE_BLOCK_RESTRICTION 1 << 19 +/** + * XML_SCHEMAS_TYPE_ABSTRACT: + * + * the simple/complexType is abstract. + */ +#define XML_SCHEMAS_TYPE_ABSTRACT 1 << 20 +/** + * XML_SCHEMAS_TYPE_FACETSNEEDVALUE: + * + * indicates if the facets need a computed value + */ +#define XML_SCHEMAS_TYPE_FACETSNEEDVALUE 1 << 21 +/** + * XML_SCHEMAS_TYPE_INTERNAL_RESOLVED: + * + * indicates that the type was typefixed + */ +#define XML_SCHEMAS_TYPE_INTERNAL_RESOLVED 1 << 22 +/** + * XML_SCHEMAS_TYPE_INTERNAL_INVALID: + * + * indicates that the type is invalid + */ +#define XML_SCHEMAS_TYPE_INTERNAL_INVALID 1 << 23 +/** + * XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE: + * + * a whitespace-facet value of "preserve" + */ +#define XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE 1 << 24 +/** + * XML_SCHEMAS_TYPE_WHITESPACE_REPLACE: + * + * a whitespace-facet value of "replace" + */ +#define XML_SCHEMAS_TYPE_WHITESPACE_REPLACE 1 << 25 +/** + * XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE: + * + * a whitespace-facet value of "collapse" + */ +#define XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE 1 << 26 +/** + * XML_SCHEMAS_TYPE_HAS_FACETS: + * + * has facets + */ +#define XML_SCHEMAS_TYPE_HAS_FACETS 1 << 27 +/** + * XML_SCHEMAS_TYPE_NORMVALUENEEDED: + * + * indicates if the facets (pattern) need a normalized value + */ +#define XML_SCHEMAS_TYPE_NORMVALUENEEDED 1 << 28 + +/** + * XML_SCHEMAS_TYPE_FIXUP_1: + * + * First stage of fixup was done. + */ +#define XML_SCHEMAS_TYPE_FIXUP_1 1 << 29 + +/** + * XML_SCHEMAS_TYPE_REDEFINED: + * + * The type was redefined. + */ +#define XML_SCHEMAS_TYPE_REDEFINED 1 << 30 +/** + * XML_SCHEMAS_TYPE_REDEFINING: + * + * The type redefines an other type. + */ +/* #define XML_SCHEMAS_TYPE_REDEFINING 1 << 31 */ + +/** + * _xmlSchemaType: + * + * Schemas type definition. + */ +struct _xmlSchemaType { + xmlSchemaTypeType type; /* The kind of type */ + struct _xmlSchemaType *next; /* the next type if in a sequence ... */ + const xmlChar *name; + const xmlChar *id ; /* Deprecated; not used */ + const xmlChar *ref; /* Deprecated; not used */ + const xmlChar *refNs; /* Deprecated; not used */ + xmlSchemaAnnotPtr annot; + xmlSchemaTypePtr subtypes; + xmlSchemaAttributePtr attributes; /* Deprecated; not used */ + xmlNodePtr node; + int minOccurs; /* Deprecated; not used */ + int maxOccurs; /* Deprecated; not used */ + + int flags; + xmlSchemaContentType contentType; + const xmlChar *base; /* Base type's local name */ + const xmlChar *baseNs; /* Base type's target namespace */ + xmlSchemaTypePtr baseType; /* The base type component */ + xmlSchemaFacetPtr facets; /* Local facets */ + struct _xmlSchemaType *redef; /* Deprecated; not used */ + int recurse; /* Obsolete */ + xmlSchemaAttributeLinkPtr *attributeUses; /* Deprecated; not used */ + xmlSchemaWildcardPtr attributeWildcard; + int builtInType; /* Type of built-in types. */ + xmlSchemaTypeLinkPtr memberTypes; /* member-types if a union type. */ + xmlSchemaFacetLinkPtr facetSet; /* All facets (incl. inherited) */ + const xmlChar *refPrefix; /* Deprecated; not used */ + xmlSchemaTypePtr contentTypeDef; /* Used for the simple content of complex types. + Could we use @subtypes for this? */ + xmlRegexpPtr contModel; /* Holds the automaton of the content model */ + const xmlChar *targetNamespace; + void *attrUses; +}; + +/* + * xmlSchemaElement: + * An element definition. + * + * xmlSchemaType, xmlSchemaFacet and xmlSchemaElement start of + * structures must be kept similar + */ +/** + * XML_SCHEMAS_ELEM_NILLABLE: + * + * the element is nillable + */ +#define XML_SCHEMAS_ELEM_NILLABLE 1 << 0 +/** + * XML_SCHEMAS_ELEM_GLOBAL: + * + * the element is global + */ +#define XML_SCHEMAS_ELEM_GLOBAL 1 << 1 +/** + * XML_SCHEMAS_ELEM_DEFAULT: + * + * the element has a default value + */ +#define XML_SCHEMAS_ELEM_DEFAULT 1 << 2 +/** + * XML_SCHEMAS_ELEM_FIXED: + * + * the element has a fixed value + */ +#define XML_SCHEMAS_ELEM_FIXED 1 << 3 +/** + * XML_SCHEMAS_ELEM_ABSTRACT: + * + * the element is abstract + */ +#define XML_SCHEMAS_ELEM_ABSTRACT 1 << 4 +/** + * XML_SCHEMAS_ELEM_TOPLEVEL: + * + * the element is top level + * obsolete: use XML_SCHEMAS_ELEM_GLOBAL instead + */ +#define XML_SCHEMAS_ELEM_TOPLEVEL 1 << 5 +/** + * XML_SCHEMAS_ELEM_REF: + * + * the element is a reference to a type + */ +#define XML_SCHEMAS_ELEM_REF 1 << 6 +/** + * XML_SCHEMAS_ELEM_NSDEFAULT: + * + * allow elements in no namespace + * Obsolete, not used anymore. + */ +#define XML_SCHEMAS_ELEM_NSDEFAULT 1 << 7 +/** + * XML_SCHEMAS_ELEM_INTERNAL_RESOLVED: + * + * this is set when "type", "ref", "substitutionGroup" + * references have been resolved. + */ +#define XML_SCHEMAS_ELEM_INTERNAL_RESOLVED 1 << 8 + /** + * XML_SCHEMAS_ELEM_CIRCULAR: + * + * a helper flag for the search of circular references. + */ +#define XML_SCHEMAS_ELEM_CIRCULAR 1 << 9 +/** + * XML_SCHEMAS_ELEM_BLOCK_ABSENT: + * + * the "block" attribute is absent + */ +#define XML_SCHEMAS_ELEM_BLOCK_ABSENT 1 << 10 +/** + * XML_SCHEMAS_ELEM_BLOCK_EXTENSION: + * + * disallowed substitutions are absent + */ +#define XML_SCHEMAS_ELEM_BLOCK_EXTENSION 1 << 11 +/** + * XML_SCHEMAS_ELEM_BLOCK_RESTRICTION: + * + * disallowed substitutions: "restriction" + */ +#define XML_SCHEMAS_ELEM_BLOCK_RESTRICTION 1 << 12 +/** + * XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION: + * + * disallowed substitutions: "substituion" + */ +#define XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION 1 << 13 +/** + * XML_SCHEMAS_ELEM_FINAL_ABSENT: + * + * substitution group exclusions are absent + */ +#define XML_SCHEMAS_ELEM_FINAL_ABSENT 1 << 14 +/** + * XML_SCHEMAS_ELEM_FINAL_EXTENSION: + * + * substitution group exclusions: "extension" + */ +#define XML_SCHEMAS_ELEM_FINAL_EXTENSION 1 << 15 +/** + * XML_SCHEMAS_ELEM_FINAL_RESTRICTION: + * + * substitution group exclusions: "restriction" + */ +#define XML_SCHEMAS_ELEM_FINAL_RESTRICTION 1 << 16 +/** + * XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD: + * + * the declaration is a substitution group head + */ +#define XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD 1 << 17 +/** + * XML_SCHEMAS_ELEM_INTERNAL_CHECKED: + * + * this is set when the elem decl has been checked against + * all constraints + */ +#define XML_SCHEMAS_ELEM_INTERNAL_CHECKED 1 << 18 + +typedef struct _xmlSchemaElement xmlSchemaElement; +typedef xmlSchemaElement *xmlSchemaElementPtr; +struct _xmlSchemaElement { + xmlSchemaTypeType type; /* The kind of type */ + struct _xmlSchemaType *next; /* Not used? */ + const xmlChar *name; + const xmlChar *id; /* Deprecated; not used */ + const xmlChar *ref; /* Deprecated; not used */ + const xmlChar *refNs; /* Deprecated; not used */ + xmlSchemaAnnotPtr annot; + xmlSchemaTypePtr subtypes; /* the type definition */ + xmlSchemaAttributePtr attributes; + xmlNodePtr node; + int minOccurs; /* Deprecated; not used */ + int maxOccurs; /* Deprecated; not used */ + + int flags; + const xmlChar *targetNamespace; + const xmlChar *namedType; + const xmlChar *namedTypeNs; + const xmlChar *substGroup; + const xmlChar *substGroupNs; + const xmlChar *scope; + const xmlChar *value; /* The original value of the value constraint. */ + struct _xmlSchemaElement *refDecl; /* This will now be used for the + substitution group affiliation */ + xmlRegexpPtr contModel; /* Obsolete for WXS, maybe used for RelaxNG */ + xmlSchemaContentType contentType; + const xmlChar *refPrefix; /* Deprecated; not used */ + xmlSchemaValPtr defVal; /* The compiled value contraint. */ + void *idcs; /* The identity-constraint defs */ +}; + +/* + * XML_SCHEMAS_FACET_UNKNOWN: + * + * unknown facet handling + */ +#define XML_SCHEMAS_FACET_UNKNOWN 0 +/* + * XML_SCHEMAS_FACET_PRESERVE: + * + * preserve the type of the facet + */ +#define XML_SCHEMAS_FACET_PRESERVE 1 +/* + * XML_SCHEMAS_FACET_REPLACE: + * + * replace the type of the facet + */ +#define XML_SCHEMAS_FACET_REPLACE 2 +/* + * XML_SCHEMAS_FACET_COLLAPSE: + * + * collapse the types of the facet + */ +#define XML_SCHEMAS_FACET_COLLAPSE 3 +/** + * A facet definition. + */ +struct _xmlSchemaFacet { + xmlSchemaTypeType type; /* The kind of type */ + struct _xmlSchemaFacet *next;/* the next type if in a sequence ... */ + const xmlChar *value; /* The original value */ + const xmlChar *id; /* Obsolete */ + xmlSchemaAnnotPtr annot; + xmlNodePtr node; + int fixed; /* XML_SCHEMAS_FACET_PRESERVE, etc. */ + int whitespace; + xmlSchemaValPtr val; /* The compiled value */ + xmlRegexpPtr regexp; /* The regex for patterns */ +}; + +/** + * A notation definition. + */ +typedef struct _xmlSchemaNotation xmlSchemaNotation; +typedef xmlSchemaNotation *xmlSchemaNotationPtr; +struct _xmlSchemaNotation { + xmlSchemaTypeType type; /* The kind of type */ + const xmlChar *name; + xmlSchemaAnnotPtr annot; + const xmlChar *identifier; + const xmlChar *targetNamespace; +}; + +/* +* TODO: Actually all those flags used for the schema should sit +* on the schema parser context, since they are used only +* during parsing an XML schema document, and not available +* on the component level as per spec. +*/ +/** + * XML_SCHEMAS_QUALIF_ELEM: + * + * Reflects elementFormDefault == qualified in + * an XML schema document. + */ +#define XML_SCHEMAS_QUALIF_ELEM 1 << 0 +/** + * XML_SCHEMAS_QUALIF_ATTR: + * + * Reflects attributeFormDefault == qualified in + * an XML schema document. + */ +#define XML_SCHEMAS_QUALIF_ATTR 1 << 1 +/** + * XML_SCHEMAS_FINAL_DEFAULT_EXTENSION: + * + * the schema has "extension" in the set of finalDefault. + */ +#define XML_SCHEMAS_FINAL_DEFAULT_EXTENSION 1 << 2 +/** + * XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION: + * + * the schema has "restriction" in the set of finalDefault. + */ +#define XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION 1 << 3 +/** + * XML_SCHEMAS_FINAL_DEFAULT_LIST: + * + * the cshema has "list" in the set of finalDefault. + */ +#define XML_SCHEMAS_FINAL_DEFAULT_LIST 1 << 4 +/** + * XML_SCHEMAS_FINAL_DEFAULT_UNION: + * + * the schema has "union" in the set of finalDefault. + */ +#define XML_SCHEMAS_FINAL_DEFAULT_UNION 1 << 5 +/** + * XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION: + * + * the schema has "extension" in the set of blockDefault. + */ +#define XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION 1 << 6 +/** + * XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION: + * + * the schema has "restriction" in the set of blockDefault. + */ +#define XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION 1 << 7 +/** + * XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION: + * + * the schema has "substitution" in the set of blockDefault. + */ +#define XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION 1 << 8 +/** + * XML_SCHEMAS_INCLUDING_CONVERT_NS: + * + * the schema is currently including an other schema with + * no target namespace. + */ +#define XML_SCHEMAS_INCLUDING_CONVERT_NS 1 << 9 +/** + * _xmlSchema: + * + * A Schemas definition + */ +struct _xmlSchema { + const xmlChar *name; /* schema name */ + const xmlChar *targetNamespace; /* the target namespace */ + const xmlChar *version; + const xmlChar *id; /* Obsolete */ + xmlDocPtr doc; + xmlSchemaAnnotPtr annot; + int flags; + + xmlHashTablePtr typeDecl; + xmlHashTablePtr attrDecl; + xmlHashTablePtr attrgrpDecl; + xmlHashTablePtr elemDecl; + xmlHashTablePtr notaDecl; + + xmlHashTablePtr schemasImports; + + void *_private; /* unused by the library for users or bindings */ + xmlHashTablePtr groupDecl; + xmlDictPtr dict; + void *includes; /* the includes, this is opaque for now */ + int preserve; /* whether to free the document */ + int counter; /* used to give ononymous components unique names */ + xmlHashTablePtr idcDef; /* All identity-constraint defs. */ + void *volatiles; /* Obsolete */ +}; + +XMLPUBFUN void XMLCALL xmlSchemaFreeType (xmlSchemaTypePtr type); +XMLPUBFUN void XMLCALL xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard); + +#ifdef __cplusplus +} +#endif + +#endif /* LIBXML_SCHEMAS_ENABLED */ +#endif /* __XML_SCHEMA_INTERNALS_H__ */ diff --git a/gettext-tools/gnulib-lib/libxml/schematron.c b/gettext-tools/gnulib-lib/libxml/schematron.c new file mode 100644 index 0000000..0a90ff8 --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/schematron.c @@ -0,0 +1,1730 @@ +/* + * schematron.c : implementation of the Schematron schema validity checking + * + * See Copyright for the status of this software. + * + * Daniel Veillard + */ + +/* + * TODO: + * + double check the semantic, especially + * - multiple rules applying in a single pattern/node + * - the semantic of libxml2 patterns vs. XSLT production referenced + * by the spec. + * + export of results in SVRL + * + full parsing and coverage of the spec, conformance of the input to the + * spec + * + divergences between the draft and the ISO proposed standard :-( + * + hook and test include + * + try and compare with the XSLT version + */ + +#define IN_LIBXML +#include "libxml.h" + +#ifdef LIBXML_SCHEMATRON_ENABLED + +#include +#include +#include +#include +#include +#include +#include +#include + +#define SCHEMATRON_PARSE_OPTIONS XML_PARSE_NOENT + +#define SCT_OLD_NS BAD_CAST "http://www.ascc.net/xml/schematron" + +#define XML_SCHEMATRON_NS BAD_CAST "http://purl.oclc.org/dsdl/schematron" + + +static const xmlChar *xmlSchematronNs = XML_SCHEMATRON_NS; +static const xmlChar *xmlOldSchematronNs = SCT_OLD_NS; + +#define IS_SCHEMATRON(node, elem) \ + ((node != NULL) && (node->type == XML_ELEMENT_NODE ) && \ + (node->ns != NULL) && \ + (xmlStrEqual(node->name, (const xmlChar *) elem)) && \ + ((xmlStrEqual(node->ns->href, xmlSchematronNs)) || \ + (xmlStrEqual(node->ns->href, xmlOldSchematronNs)))) + +#define NEXT_SCHEMATRON(node) \ + while (node != NULL) { \ + if ((node->type == XML_ELEMENT_NODE ) && (node->ns != NULL) && \ + ((xmlStrEqual(node->ns->href, xmlSchematronNs)) || \ + (xmlStrEqual(node->ns->href, xmlOldSchematronNs)))) \ + break; \ + node = node->next; \ + } + +/** + * TODO: + * + * macro to flag unimplemented blocks + */ +#define TODO \ + xmlGenericError(xmlGenericErrorContext, \ + "Unimplemented block at %s:%d\n", \ + __FILE__, __LINE__); + +typedef enum { + XML_SCHEMATRON_ASSERT=1, + XML_SCHEMATRON_REPORT=2 +} xmlSchematronTestType; + +/** + * _xmlSchematronTest: + * + * A Schematrons test, either an assert or a report + */ +typedef struct _xmlSchematronTest xmlSchematronTest; +typedef xmlSchematronTest *xmlSchematronTestPtr; +struct _xmlSchematronTest { + xmlSchematronTestPtr next; /* the next test in the list */ + xmlSchematronTestType type; /* the test type */ + xmlNodePtr node; /* the node in the tree */ + xmlChar *test; /* the expression to test */ + xmlXPathCompExprPtr comp; /* the compiled expression */ + xmlChar *report; /* the message to report */ +}; + +/** + * _xmlSchematronRule: + * + * A Schematrons rule + */ +typedef struct _xmlSchematronRule xmlSchematronRule; +typedef xmlSchematronRule *xmlSchematronRulePtr; +struct _xmlSchematronRule { + xmlSchematronRulePtr next; /* the next rule in the list */ + xmlSchematronRulePtr patnext;/* the next rule in the pattern list */ + xmlNodePtr node; /* the node in the tree */ + xmlChar *context; /* the context evaluation rule */ + xmlSchematronTestPtr tests; /* the list of tests */ + xmlPatternPtr pattern; /* the compiled pattern associated */ + xmlChar *report; /* the message to report */ +}; + +/** + * _xmlSchematronPattern: + * + * A Schematrons pattern + */ +typedef struct _xmlSchematronPattern xmlSchematronPattern; +typedef xmlSchematronPattern *xmlSchematronPatternPtr; +struct _xmlSchematronPattern { + xmlSchematronPatternPtr next;/* the next pattern in the list */ + xmlSchematronRulePtr rules; /* the list of rules */ + xmlChar *name; /* the name of the pattern */ +}; + +/** + * _xmlSchematron: + * + * A Schematrons definition + */ +struct _xmlSchematron { + const xmlChar *name; /* schema name */ + int preserve; /* was the document passed by the user */ + xmlDocPtr doc; /* pointer to the parsed document */ + int flags; /* specific to this schematron */ + + void *_private; /* unused by the library */ + xmlDictPtr dict; /* the dictionnary used internally */ + + const xmlChar *title; /* the title if any */ + + int nbNs; /* the number of namespaces */ + + int nbPattern; /* the number of patterns */ + xmlSchematronPatternPtr patterns;/* the patterns found */ + xmlSchematronRulePtr rules; /* the rules gathered */ + int nbNamespaces; /* number of namespaces in the array */ + int maxNamespaces; /* size of the array */ + const xmlChar **namespaces; /* the array of namespaces */ +}; + +/** + * xmlSchematronValidCtxt: + * + * A Schematrons validation context + */ +struct _xmlSchematronValidCtxt { + int type; + int flags; /* an or of xmlSchematronValidOptions */ + + xmlDictPtr dict; + int nberrors; + int err; + + xmlSchematronPtr schema; + xmlXPathContextPtr xctxt; + + FILE *outputFile; /* if using XML_SCHEMATRON_OUT_FILE */ + xmlBufferPtr outputBuffer; /* if using XML_SCHEMATRON_OUT_BUFFER */ + xmlOutputWriteCallback iowrite; /* if using XML_SCHEMATRON_OUT_IO */ + xmlOutputCloseCallback ioclose; + void *ioctx; +}; + +struct _xmlSchematronParserCtxt { + int type; + const xmlChar *URL; + xmlDocPtr doc; + int preserve; /* Whether the doc should be freed */ + const char *buffer; + int size; + + xmlDictPtr dict; /* dictionnary for interned string names */ + + int nberrors; + int err; + xmlXPathContextPtr xctxt; /* the XPath context used for compilation */ + xmlSchematronPtr schema; + + int nbNamespaces; /* number of namespaces in the array */ + int maxNamespaces; /* size of the array */ + const xmlChar **namespaces; /* the array of namespaces */ + + int nbIncludes; /* number of includes in the array */ + int maxIncludes; /* size of the array */ + xmlNodePtr *includes; /* the array of includes */ + + /* error rreporting data */ + void *userData; /* user specific data block */ + xmlSchematronValidityErrorFunc error;/* the callback in case of errors */ + xmlSchematronValidityWarningFunc warning;/* callback in case of warning */ + xmlStructuredErrorFunc serror; /* the structured function */ + +}; + +#define XML_STRON_CTXT_PARSER 1 +#define XML_STRON_CTXT_VALIDATOR 2 + +/************************************************************************ + * * + * Error reporting * + * * + ************************************************************************/ + +/** + * xmlSchematronPErrMemory: + * @node: a context node + * @extra: extra informations + * + * Handle an out of memory condition + */ +static void +xmlSchematronPErrMemory(xmlSchematronParserCtxtPtr ctxt, + const char *extra, xmlNodePtr node) +{ + if (ctxt != NULL) + ctxt->nberrors++; + __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL, + extra); +} + +/** + * xmlSchematronPErr: + * @ctxt: the parsing context + * @node: the context node + * @error: the error code + * @msg: the error message + * @str1: extra data + * @str2: extra data + * + * Handle a parser error + */ +static void +xmlSchematronPErr(xmlSchematronParserCtxtPtr ctxt, xmlNodePtr node, int error, + const char *msg, const xmlChar * str1, const xmlChar * str2) +{ + xmlGenericErrorFunc channel = NULL; + xmlStructuredErrorFunc schannel = NULL; + void *data = NULL; + + if (ctxt != NULL) { + ctxt->nberrors++; + channel = ctxt->error; + data = ctxt->userData; + schannel = ctxt->serror; + } + __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP, + error, XML_ERR_ERROR, NULL, 0, + (const char *) str1, (const char *) str2, NULL, 0, 0, + msg, str1, str2); +} + +/** + * xmlSchematronVTypeErrMemory: + * @node: a context node + * @extra: extra informations + * + * Handle an out of memory condition + */ +static void +xmlSchematronVErrMemory(xmlSchematronValidCtxtPtr ctxt, + const char *extra, xmlNodePtr node) +{ + if (ctxt != NULL) { + ctxt->nberrors++; + ctxt->err = XML_SCHEMAV_INTERNAL; + } + __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL, + extra); +} + +/************************************************************************ + * * + * Parsing and compilation of the Schematrontrons * + * * + ************************************************************************/ + +/** + * xmlSchematronAddTest: + * @ctxt: the schema parsing context + * @type: the type of test + * @rule: the parent rule + * @node: the node hosting the test + * @test: the associated test + * @report: the associated report string + * + * Add a test to a schematron + * + * Returns the new pointer or NULL in case of error + */ +static xmlSchematronTestPtr +xmlSchematronAddTest(xmlSchematronParserCtxtPtr ctxt, + xmlSchematronTestType type, + xmlSchematronRulePtr rule, + xmlNodePtr node, xmlChar *test, xmlChar *report) +{ + xmlSchematronTestPtr ret; + xmlXPathCompExprPtr comp; + + if ((ctxt == NULL) || (rule == NULL) || (node == NULL) || + (test == NULL)) + return(NULL); + + /* + * try first to compile the test expression + */ + comp = xmlXPathCtxtCompile(ctxt->xctxt, test); + if (comp == NULL) { + xmlSchematronPErr(ctxt, node, + XML_SCHEMAP_NOROOT, + "Failed to compile test expression %s", + test, NULL); + return(NULL); + } + + ret = (xmlSchematronTestPtr) xmlMalloc(sizeof(xmlSchematronTest)); + if (ret == NULL) { + xmlSchematronPErrMemory(ctxt, "allocating schema test", node); + return (NULL); + } + memset(ret, 0, sizeof(xmlSchematronTest)); + ret->type = type; + ret->node = node; + ret->test = test; + ret->comp = comp; + ret->report = report; + ret->next = NULL; + if (rule->tests == NULL) { + rule->tests = ret; + } else { + xmlSchematronTestPtr prev = rule->tests; + + while (prev->next != NULL) + prev = prev->next; + prev->next = ret; + } + return (ret); +} + +/** + * xmlSchematronFreeTests: + * @tests: a list of tests + * + * Free a list of tests. + */ +static void +xmlSchematronFreeTests(xmlSchematronTestPtr tests) { + xmlSchematronTestPtr next; + + while (tests != NULL) { + next = tests->next; + if (tests->test != NULL) + xmlFree(tests->test); + if (tests->comp != NULL) + xmlXPathFreeCompExpr(tests->comp); + if (tests->report != NULL) + xmlFree(tests->report); + xmlFree(tests); + tests = next; + } +} + +/** + * xmlSchematronAddRule: + * @ctxt: the schema parsing context + * @schema: a schema structure + * @node: the node hosting the rule + * @context: the associated context string + * @report: the associated report string + * + * Add a rule to a schematron + * + * Returns the new pointer or NULL in case of error + */ +static xmlSchematronRulePtr +xmlSchematronAddRule(xmlSchematronParserCtxtPtr ctxt, xmlSchematronPtr schema, + xmlSchematronPatternPtr pat, xmlNodePtr node, + xmlChar *context, xmlChar *report) +{ + xmlSchematronRulePtr ret; + xmlPatternPtr pattern; + + if ((ctxt == NULL) || (schema == NULL) || (node == NULL) || + (context == NULL)) + return(NULL); + + /* + * Try first to compile the pattern + */ + pattern = xmlPatterncompile(context, ctxt->dict, XML_PATTERN_XPATH, + ctxt->namespaces); + if (pattern == NULL) { + xmlSchematronPErr(ctxt, node, + XML_SCHEMAP_NOROOT, + "Failed to compile context expression %s", + context, NULL); + } + + ret = (xmlSchematronRulePtr) xmlMalloc(sizeof(xmlSchematronRule)); + if (ret == NULL) { + xmlSchematronPErrMemory(ctxt, "allocating schema rule", node); + return (NULL); + } + memset(ret, 0, sizeof(xmlSchematronRule)); + ret->node = node; + ret->context = context; + ret->pattern = pattern; + ret->report = report; + ret->next = NULL; + if (schema->rules == NULL) { + schema->rules = ret; + } else { + xmlSchematronRulePtr prev = schema->rules; + + while (prev->next != NULL) + prev = prev->next; + prev->next = ret; + } + ret->patnext = NULL; + if (pat->rules == NULL) { + pat->rules = ret; + } else { + xmlSchematronRulePtr prev = pat->rules; + + while (prev->patnext != NULL) + prev = prev->patnext; + prev->patnext = ret; + } + return (ret); +} + +/** + * xmlSchematronFreeRules: + * @rules: a list of rules + * + * Free a list of rules. + */ +static void +xmlSchematronFreeRules(xmlSchematronRulePtr rules) { + xmlSchematronRulePtr next; + + while (rules != NULL) { + next = rules->next; + if (rules->tests) + xmlSchematronFreeTests(rules->tests); + if (rules->context != NULL) + xmlFree(rules->context); + if (rules->pattern) + xmlFreePattern(rules->pattern); + if (rules->report != NULL) + xmlFree(rules->report); + xmlFree(rules); + rules = next; + } +} + +/** + * xmlSchematronAddPattern: + * @ctxt: the schema parsing context + * @schema: a schema structure + * @node: the node hosting the pattern + * @id: the id or name of the pattern + * + * Add a pattern to a schematron + * + * Returns the new pointer or NULL in case of error + */ +static xmlSchematronPatternPtr +xmlSchematronAddPattern(xmlSchematronParserCtxtPtr ctxt, + xmlSchematronPtr schema, xmlNodePtr node, xmlChar *name) +{ + xmlSchematronPatternPtr ret; + + if ((ctxt == NULL) || (schema == NULL) || (node == NULL) || (name == NULL)) + return(NULL); + + ret = (xmlSchematronPatternPtr) xmlMalloc(sizeof(xmlSchematronPattern)); + if (ret == NULL) { + xmlSchematronPErrMemory(ctxt, "allocating schema pattern", node); + return (NULL); + } + memset(ret, 0, sizeof(xmlSchematronPattern)); + ret->name = name; + ret->next = NULL; + if (schema->patterns == NULL) { + schema->patterns = ret; + } else { + xmlSchematronPatternPtr prev = schema->patterns; + + while (prev->next != NULL) + prev = prev->next; + prev->next = ret; + } + return (ret); +} + +/** + * xmlSchematronFreePatterns: + * @patterns: a list of patterns + * + * Free a list of patterns. + */ +static void +xmlSchematronFreePatterns(xmlSchematronPatternPtr patterns) { + xmlSchematronPatternPtr next; + + while (patterns != NULL) { + next = patterns->next; + if (patterns->name != NULL) + xmlFree(patterns->name); + xmlFree(patterns); + patterns = next; + } +} + +/** + * xmlSchematronNewSchematron: + * @ctxt: a schema validation context + * + * Allocate a new Schematron structure. + * + * Returns the newly allocated structure or NULL in case or error + */ +static xmlSchematronPtr +xmlSchematronNewSchematron(xmlSchematronParserCtxtPtr ctxt) +{ + xmlSchematronPtr ret; + + ret = (xmlSchematronPtr) xmlMalloc(sizeof(xmlSchematron)); + if (ret == NULL) { + xmlSchematronPErrMemory(ctxt, "allocating schema", NULL); + return (NULL); + } + memset(ret, 0, sizeof(xmlSchematron)); + ret->dict = ctxt->dict; + xmlDictReference(ret->dict); + + return (ret); +} + +/** + * xmlSchematronFree: + * @schema: a schema structure + * + * Deallocate a Schematron structure. + */ +void +xmlSchematronFree(xmlSchematronPtr schema) +{ + if (schema == NULL) + return; + + if ((schema->doc != NULL) && (!(schema->preserve))) + xmlFreeDoc(schema->doc); + + if (schema->namespaces != NULL) + xmlFree((char **) schema->namespaces); + + xmlSchematronFreeRules(schema->rules); + xmlSchematronFreePatterns(schema->patterns); + xmlDictFree(schema->dict); + xmlFree(schema); +} + +/** + * xmlSchematronNewParserCtxt: + * @URL: the location of the schema + * + * Create an XML Schematrons parse context for that file/resource expected + * to contain an XML Schematrons file. + * + * Returns the parser context or NULL in case of error + */ +xmlSchematronParserCtxtPtr +xmlSchematronNewParserCtxt(const char *URL) +{ + xmlSchematronParserCtxtPtr ret; + + if (URL == NULL) + return (NULL); + + ret = + (xmlSchematronParserCtxtPtr) + xmlMalloc(sizeof(xmlSchematronParserCtxt)); + if (ret == NULL) { + xmlSchematronPErrMemory(NULL, "allocating schema parser context", + NULL); + return (NULL); + } + memset(ret, 0, sizeof(xmlSchematronParserCtxt)); + ret->type = XML_STRON_CTXT_PARSER; + ret->dict = xmlDictCreate(); + ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1); + ret->includes = NULL; + ret->xctxt = xmlXPathNewContext(NULL); + if (ret->xctxt == NULL) { + xmlSchematronPErrMemory(NULL, "allocating schema parser XPath context", + NULL); + xmlSchematronFreeParserCtxt(ret); + return (NULL); + } + ret->xctxt->flags = XML_XPATH_CHECKNS; + return (ret); +} + +/** + * xmlSchematronNewMemParserCtxt: + * @buffer: a pointer to a char array containing the schemas + * @size: the size of the array + * + * Create an XML Schematrons parse context for that memory buffer expected + * to contain an XML Schematrons file. + * + * Returns the parser context or NULL in case of error + */ +xmlSchematronParserCtxtPtr +xmlSchematronNewMemParserCtxt(const char *buffer, int size) +{ + xmlSchematronParserCtxtPtr ret; + + if ((buffer == NULL) || (size <= 0)) + return (NULL); + + ret = + (xmlSchematronParserCtxtPtr) + xmlMalloc(sizeof(xmlSchematronParserCtxt)); + if (ret == NULL) { + xmlSchematronPErrMemory(NULL, "allocating schema parser context", + NULL); + return (NULL); + } + memset(ret, 0, sizeof(xmlSchematronParserCtxt)); + ret->buffer = buffer; + ret->size = size; + ret->dict = xmlDictCreate(); + ret->xctxt = xmlXPathNewContext(NULL); + if (ret->xctxt == NULL) { + xmlSchematronPErrMemory(NULL, "allocating schema parser XPath context", + NULL); + xmlSchematronFreeParserCtxt(ret); + return (NULL); + } + return (ret); +} + +/** + * xmlSchematronNewDocParserCtxt: + * @doc: a preparsed document tree + * + * Create an XML Schematrons parse context for that document. + * NB. The document may be modified during the parsing process. + * + * Returns the parser context or NULL in case of error + */ +xmlSchematronParserCtxtPtr +xmlSchematronNewDocParserCtxt(xmlDocPtr doc) +{ + xmlSchematronParserCtxtPtr ret; + + if (doc == NULL) + return (NULL); + + ret = + (xmlSchematronParserCtxtPtr) + xmlMalloc(sizeof(xmlSchematronParserCtxt)); + if (ret == NULL) { + xmlSchematronPErrMemory(NULL, "allocating schema parser context", + NULL); + return (NULL); + } + memset(ret, 0, sizeof(xmlSchematronParserCtxt)); + ret->doc = doc; + ret->dict = xmlDictCreate(); + /* The application has responsibility for the document */ + ret->preserve = 1; + ret->xctxt = xmlXPathNewContext(doc); + if (ret->xctxt == NULL) { + xmlSchematronPErrMemory(NULL, "allocating schema parser XPath context", + NULL); + xmlSchematronFreeParserCtxt(ret); + return (NULL); + } + + return (ret); +} + +/** + * xmlSchematronFreeParserCtxt: + * @ctxt: the schema parser context + * + * Free the resources associated to the schema parser context + */ +void +xmlSchematronFreeParserCtxt(xmlSchematronParserCtxtPtr ctxt) +{ + if (ctxt == NULL) + return; + if (ctxt->doc != NULL && !ctxt->preserve) + xmlFreeDoc(ctxt->doc); + if (ctxt->xctxt != NULL) { + xmlXPathFreeContext(ctxt->xctxt); + } + if (ctxt->namespaces != NULL) + xmlFree((char **) ctxt->namespaces); + xmlDictFree(ctxt->dict); + xmlFree(ctxt); +} + +/** + * xmlSchematronPushInclude: + * @ctxt: the schema parser context + * @doc: the included document + * @cur: the current include node + * + * Add an included document + */ +static void +xmlSchematronPushInclude(xmlSchematronParserCtxtPtr ctxt, + xmlDocPtr doc, xmlNodePtr cur) +{ + if (ctxt->includes == NULL) { + ctxt->maxIncludes = 10; + ctxt->includes = (xmlNodePtr *) + xmlMalloc(ctxt->maxIncludes * 2 * sizeof(xmlNodePtr)); + if (ctxt->includes == NULL) { + xmlSchematronPErrMemory(NULL, "allocating parser includes", + NULL); + return; + } + ctxt->nbIncludes = 0; + } else if (ctxt->nbIncludes + 2 >= ctxt->maxIncludes) { + xmlNodePtr *tmp; + + tmp = (xmlNodePtr *) + xmlRealloc(ctxt->includes, ctxt->maxIncludes * 4 * + sizeof(xmlNodePtr)); + if (tmp == NULL) { + xmlSchematronPErrMemory(NULL, "allocating parser includes", + NULL); + return; + } + ctxt->includes = tmp; + ctxt->maxIncludes *= 2; + } + ctxt->includes[2 * ctxt->nbIncludes] = cur; + ctxt->includes[2 * ctxt->nbIncludes + 1] = (xmlNodePtr) doc; + ctxt->nbIncludes++; +} + +/** + * xmlSchematronPopInclude: + * @ctxt: the schema parser context + * + * Pop an include level. The included document is being freed + * + * Returns the node immediately following the include or NULL if the + * include list was empty. + */ +static xmlNodePtr +xmlSchematronPopInclude(xmlSchematronParserCtxtPtr ctxt) +{ + xmlDocPtr doc; + xmlNodePtr ret; + + if (ctxt->nbIncludes <= 0) + return(NULL); + ctxt->nbIncludes--; + doc = (xmlDocPtr) ctxt->includes[2 * ctxt->nbIncludes + 1]; + ret = ctxt->includes[2 * ctxt->nbIncludes]; + xmlFreeDoc(doc); + if (ret != NULL) + ret = ret->next; + if (ret == NULL) + return(xmlSchematronPopInclude(ctxt)); + return(ret); +} + +/** + * xmlSchematronAddNamespace: + * @ctxt: the schema parser context + * @prefix: the namespace prefix + * @ns: the namespace name + * + * Add a namespace definition in the context + */ +static void +xmlSchematronAddNamespace(xmlSchematronParserCtxtPtr ctxt, + const xmlChar *prefix, const xmlChar *ns) +{ + if (ctxt->namespaces == NULL) { + ctxt->maxNamespaces = 10; + ctxt->namespaces = (const xmlChar **) + xmlMalloc(ctxt->maxNamespaces * 2 * sizeof(const xmlChar *)); + if (ctxt->namespaces == NULL) { + xmlSchematronPErrMemory(NULL, "allocating parser namespaces", + NULL); + return; + } + ctxt->nbNamespaces = 0; + } else if (ctxt->nbNamespaces + 2 >= ctxt->maxNamespaces) { + const xmlChar **tmp; + + tmp = (const xmlChar **) + xmlRealloc((xmlChar **) ctxt->namespaces, ctxt->maxNamespaces * 4 * + sizeof(const xmlChar *)); + if (tmp == NULL) { + xmlSchematronPErrMemory(NULL, "allocating parser namespaces", + NULL); + return; + } + ctxt->namespaces = tmp; + ctxt->maxNamespaces *= 2; + } + ctxt->namespaces[2 * ctxt->nbNamespaces] = + xmlDictLookup(ctxt->dict, ns, -1); + ctxt->namespaces[2 * ctxt->nbNamespaces + 1] = + xmlDictLookup(ctxt->dict, prefix, -1); + ctxt->nbNamespaces++; + ctxt->namespaces[2 * ctxt->nbNamespaces] = NULL; + ctxt->namespaces[2 * ctxt->nbNamespaces + 1] = NULL; + +} + +/** + * xmlSchematronParseRule: + * @ctxt: a schema validation context + * @rule: the rule node + * + * parse a rule element + */ +static void +xmlSchematronParseRule(xmlSchematronParserCtxtPtr ctxt, + xmlSchematronPatternPtr pattern, + xmlNodePtr rule) +{ + xmlNodePtr cur; + int nbChecks = 0; + xmlChar *test; + xmlChar *context; + xmlChar *report; + xmlSchematronRulePtr ruleptr; + xmlSchematronTestPtr testptr; + + if ((ctxt == NULL) || (rule == NULL)) return; + + context = xmlGetNoNsProp(rule, BAD_CAST "context"); + if (context == NULL) { + xmlSchematronPErr(ctxt, rule, + XML_SCHEMAP_NOROOT, + "rule has no context attribute", + NULL, NULL); + return; + } else if (context[0] == 0) { + xmlSchematronPErr(ctxt, rule, + XML_SCHEMAP_NOROOT, + "rule has an empty context attribute", + NULL, NULL); + xmlFree(context); + return; + } else { + ruleptr = xmlSchematronAddRule(ctxt, ctxt->schema, pattern, + rule, context, NULL); + if (ruleptr == NULL) { + xmlFree(context); + return; + } + } + + cur = rule->children; + NEXT_SCHEMATRON(cur); + while (cur != NULL) { + if (IS_SCHEMATRON(cur, "assert")) { + nbChecks++; + test = xmlGetNoNsProp(cur, BAD_CAST "test"); + if (test == NULL) { + xmlSchematronPErr(ctxt, cur, + XML_SCHEMAP_NOROOT, + "assert has no test attribute", + NULL, NULL); + } else if (test[0] == 0) { + xmlSchematronPErr(ctxt, cur, + XML_SCHEMAP_NOROOT, + "assert has an empty test attribute", + NULL, NULL); + xmlFree(test); + } else { + /* TODO will need dynamic processing instead */ + report = xmlNodeGetContent(cur); + + testptr = xmlSchematronAddTest(ctxt, XML_SCHEMATRON_ASSERT, + ruleptr, cur, test, report); + if (testptr == NULL) + xmlFree(test); + } + } else if (IS_SCHEMATRON(cur, "report")) { + nbChecks++; + test = xmlGetNoNsProp(cur, BAD_CAST "test"); + if (test == NULL) { + xmlSchematronPErr(ctxt, cur, + XML_SCHEMAP_NOROOT, + "assert has no test attribute", + NULL, NULL); + } else if (test[0] == 0) { + xmlSchematronPErr(ctxt, cur, + XML_SCHEMAP_NOROOT, + "assert has an empty test attribute", + NULL, NULL); + xmlFree(test); + } else { + /* TODO will need dynamic processing instead */ + report = xmlNodeGetContent(cur); + + testptr = xmlSchematronAddTest(ctxt, XML_SCHEMATRON_REPORT, + ruleptr, cur, test, report); + if (testptr == NULL) + xmlFree(test); + } + } else { + xmlSchematronPErr(ctxt, cur, + XML_SCHEMAP_NOROOT, + "Expecting an assert or a report element instead of %s", + cur->name, NULL); + } + cur = cur->next; + NEXT_SCHEMATRON(cur); + } + if (nbChecks == 0) { + xmlSchematronPErr(ctxt, rule, + XML_SCHEMAP_NOROOT, + "rule has no assert nor report element", NULL, NULL); + } +} + +/** + * xmlSchematronParsePattern: + * @ctxt: a schema validation context + * @pat: the pattern node + * + * parse a pattern element + */ +static void +xmlSchematronParsePattern(xmlSchematronParserCtxtPtr ctxt, xmlNodePtr pat) +{ + xmlNodePtr cur; + xmlSchematronPatternPtr pattern; + int nbRules = 0; + xmlChar *id; + + if ((ctxt == NULL) || (pat == NULL)) return; + + id = xmlGetNoNsProp(pat, BAD_CAST "id"); + if (id == NULL) { + id = xmlGetNoNsProp(pat, BAD_CAST "name"); + } + pattern = xmlSchematronAddPattern(ctxt, ctxt->schema, pat, id); + if (pattern == NULL) { + if (id != NULL) + xmlFree(id); + return; + } + cur = pat->children; + NEXT_SCHEMATRON(cur); + while (cur != NULL) { + if (IS_SCHEMATRON(cur, "rule")) { + xmlSchematronParseRule(ctxt, pattern, cur); + nbRules++; + } else { + xmlSchematronPErr(ctxt, cur, + XML_SCHEMAP_NOROOT, + "Expecting a rule element instead of %s", cur->name, NULL); + } + cur = cur->next; + NEXT_SCHEMATRON(cur); + } + if (nbRules == 0) { + xmlSchematronPErr(ctxt, pat, + XML_SCHEMAP_NOROOT, + "Pattern has no rule element", NULL, NULL); + } +} + +/** + * xmlSchematronLoadInclude: + * @ctxt: a schema validation context + * @cur: the include element + * + * Load the include document, Push the current pointer + * + * Returns the updated node pointer + */ +static xmlNodePtr +xmlSchematronLoadInclude(xmlSchematronParserCtxtPtr ctxt, xmlNodePtr cur) +{ + xmlNodePtr ret = NULL; + xmlDocPtr doc = NULL; + xmlChar *href = NULL; + xmlChar *base = NULL; + xmlChar *URI = NULL; + + if ((ctxt == NULL) || (cur == NULL)) + return(NULL); + + href = xmlGetNoNsProp(cur, BAD_CAST "href"); + if (href == NULL) { + xmlSchematronPErr(ctxt, cur, + XML_SCHEMAP_NOROOT, + "Include has no href attribute", NULL, NULL); + return(cur->next); + } + + /* do the URI base composition, load and find the root */ + base = xmlNodeGetBase(cur->doc, cur); + URI = xmlBuildURI(href, base); + doc = xmlReadFile((const char *) URI, NULL, SCHEMATRON_PARSE_OPTIONS); + if (doc == NULL) { + xmlSchematronPErr(ctxt, cur, + XML_SCHEMAP_FAILED_LOAD, + "could not load include '%s'.\n", + URI, NULL); + goto done; + } + ret = xmlDocGetRootElement(doc); + if (ret == NULL) { + xmlSchematronPErr(ctxt, cur, + XML_SCHEMAP_FAILED_LOAD, + "could not find root from include '%s'.\n", + URI, NULL); + goto done; + } + + /* Success, push the include for rollback on exit */ + xmlSchematronPushInclude(ctxt, doc, cur); + +done: + if (ret == NULL) { + if (doc != NULL) + xmlFreeDoc(doc); + } + xmlFree(href); + if (base != NULL) + xmlFree(base); + if (URI != NULL) + xmlFree(URI); + return(ret); +} + +/** + * xmlSchematronParse: + * @ctxt: a schema validation context + * + * parse a schema definition resource and build an internal + * XML Shema struture which can be used to validate instances. + * + * Returns the internal XML Schematron structure built from the resource or + * NULL in case of error + */ +xmlSchematronPtr +xmlSchematronParse(xmlSchematronParserCtxtPtr ctxt) +{ + xmlSchematronPtr ret = NULL; + xmlDocPtr doc; + xmlNodePtr root, cur; + int preserve = 0; + + if (ctxt == NULL) + return (NULL); + + ctxt->nberrors = 0; + + /* + * First step is to parse the input document into an DOM/Infoset + */ + if (ctxt->URL != NULL) { + doc = xmlReadFile((const char *) ctxt->URL, NULL, + SCHEMATRON_PARSE_OPTIONS); + if (doc == NULL) { + xmlSchematronPErr(ctxt, NULL, + XML_SCHEMAP_FAILED_LOAD, + "xmlSchematronParse: could not load '%s'.\n", + ctxt->URL, NULL); + return (NULL); + } + ctxt->preserve = 0; + } else if (ctxt->buffer != NULL) { + doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL, + SCHEMATRON_PARSE_OPTIONS); + if (doc == NULL) { + xmlSchematronPErr(ctxt, NULL, + XML_SCHEMAP_FAILED_PARSE, + "xmlSchematronParse: could not parse.\n", + NULL, NULL); + return (NULL); + } + doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer"); + ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1); + ctxt->preserve = 0; + } else if (ctxt->doc != NULL) { + doc = ctxt->doc; + preserve = 1; + ctxt->preserve = 1; + } else { + xmlSchematronPErr(ctxt, NULL, + XML_SCHEMAP_NOTHING_TO_PARSE, + "xmlSchematronParse: could not parse.\n", + NULL, NULL); + return (NULL); + } + + /* + * Then extract the root and Schematron parse it + */ + root = xmlDocGetRootElement(doc); + if (root == NULL) { + xmlSchematronPErr(ctxt, (xmlNodePtr) doc, + XML_SCHEMAP_NOROOT, + "The schema has no document element.\n", NULL, NULL); + if (!preserve) { + xmlFreeDoc(doc); + } + return (NULL); + } + + if (!IS_SCHEMATRON(root, "schema")) { + xmlSchematronPErr(ctxt, root, + XML_SCHEMAP_NOROOT, + "The XML document '%s' is not a XML schematron document", + ctxt->URL, NULL); + goto exit; + } + ret = xmlSchematronNewSchematron(ctxt); + if (ret == NULL) + goto exit; + ctxt->schema = ret; + + /* + * scan the schema elements + */ + cur = root->children; + NEXT_SCHEMATRON(cur); + if (IS_SCHEMATRON(cur, "title")) { + xmlChar *title = xmlNodeGetContent(cur); + if (title != NULL) { + ret->title = xmlDictLookup(ret->dict, title, -1); + xmlFree(title); + } + cur = cur->next; + NEXT_SCHEMATRON(cur); + } + while (IS_SCHEMATRON(cur, "ns")) { + xmlChar *prefix = xmlGetNoNsProp(cur, BAD_CAST "prefix"); + xmlChar *uri = xmlGetNoNsProp(cur, BAD_CAST "uri"); + if ((uri == NULL) || (uri[0] == 0)) { + xmlSchematronPErr(ctxt, cur, + XML_SCHEMAP_NOROOT, + "ns element has no uri", NULL, NULL); + } + if ((prefix == NULL) || (prefix[0] == 0)) { + xmlSchematronPErr(ctxt, cur, + XML_SCHEMAP_NOROOT, + "ns element has no prefix", NULL, NULL); + } + if ((prefix) && (uri)) { + xmlXPathRegisterNs(ctxt->xctxt, prefix, uri); + xmlSchematronAddNamespace(ctxt, prefix, uri); + ret->nbNs++; + } + if (uri) + xmlFree(uri); + if (prefix) + xmlFree(prefix); + cur = cur->next; + NEXT_SCHEMATRON(cur); + } + while (cur != NULL) { + if (IS_SCHEMATRON(cur, "pattern")) { + xmlSchematronParsePattern(ctxt, cur); + ret->nbPattern++; + } else { + xmlSchematronPErr(ctxt, cur, + XML_SCHEMAP_NOROOT, + "Expecting a pattern element instead of %s", cur->name, NULL); + } + cur = cur->next; + NEXT_SCHEMATRON(cur); + } + if (ret->nbPattern == 0) { + xmlSchematronPErr(ctxt, root, + XML_SCHEMAP_NOROOT, + "The schematron document '%s' has no pattern", + ctxt->URL, NULL); + goto exit; + } + /* the original document must be kept for reporting */ + ret->doc = doc; + preserve = 1; + +exit: + if (!preserve) { + xmlFreeDoc(doc); + } + if (ret != NULL) { + if (ctxt->nberrors != 0) { + xmlSchematronFree(ret); + ret = NULL; + } else { + ret->namespaces = ctxt->namespaces; + ret->nbNamespaces = ctxt->nbNamespaces; + ctxt->namespaces = NULL; + } + } + return (ret); +} + +/************************************************************************ + * * + * Schematrontron Reports handler * + * * + ************************************************************************/ + +static xmlNodePtr +xmlSchematronGetNode(xmlSchematronValidCtxtPtr ctxt, + xmlNodePtr cur, const xmlChar *xpath) { + xmlNodePtr node = NULL; + xmlXPathObjectPtr ret; + + if ((ctxt == NULL) || (cur == NULL) || (xpath == NULL)) + return(NULL); + + ctxt->xctxt->doc = cur->doc; + ctxt->xctxt->node = cur; + ret = xmlXPathEval(xpath, ctxt->xctxt); + if (ret == NULL) + return(NULL); + + if ((ret->type == XPATH_NODESET) && + (ret->nodesetval != NULL) && (ret->nodesetval->nodeNr > 0)) + node = ret->nodesetval->nodeTab[0]; + + xmlXPathFreeObject(ret); + return(node); +} + +/** + * xmlSchematronReportOutput: + * @ctxt: the validation context + * @cur: the current node tested + * @msg: the message output + * + * Output part of the report to whatever channel the user selected + */ +static void +xmlSchematronReportOutput(xmlSchematronValidCtxtPtr ctxt ATTRIBUTE_UNUSED, + xmlNodePtr cur ATTRIBUTE_UNUSED, + const char *msg) { + /* TODO */ + fprintf(stderr, "%s", msg); +} + +/** + * xmlSchematronFormatReport: + * @ctxt: the validation context + * @test: the test node + * @cur: the current node tested + * + * Build the string being reported to the user. + * + * Returns a report string or NULL in case of error. The string needs + * to be deallocated by teh caller + */ +static xmlChar * +xmlSchematronFormatReport(xmlSchematronValidCtxtPtr ctxt, + xmlNodePtr test, xmlNodePtr cur) { + xmlChar *ret = NULL; + xmlNodePtr child, node; + + if ((test == NULL) || (cur == NULL)) + return(ret); + + child = test->children; + while (child != NULL) { + if ((child->type == XML_TEXT_NODE) || + (child->type == XML_CDATA_SECTION_NODE)) + ret = xmlStrcat(ret, child->content); + else if (IS_SCHEMATRON(child, "name")) { + xmlChar *path; + + path = xmlGetNoNsProp(child, BAD_CAST "path"); + + node = cur; + if (path != NULL) { + node = xmlSchematronGetNode(ctxt, cur, path); + if (node == NULL) + node = cur; + xmlFree(path); + } + + if ((node->ns == NULL) || (node->ns->prefix == NULL)) + ret = xmlStrcat(ret, node->name); + else { + ret = xmlStrcat(ret, node->ns->prefix); + ret = xmlStrcat(ret, BAD_CAST ":"); + ret = xmlStrcat(ret, node->name); + } + } else { + child = child->next; + continue; + } + + /* + * remove superfluous \n + */ + if (ret != NULL) { + int len = xmlStrlen(ret); + xmlChar c; + + if (len > 0) { + c = ret[len - 1]; + if ((c == ' ') || (c == '\n') || (c == '\r') || (c == '\t')) { + while ((c == ' ') || (c == '\n') || + (c == '\r') || (c == '\t')) { + len--; + if (len == 0) + break; + c = ret[len - 1]; + } + ret[len] = ' '; + ret[len + 1] = 0; + } + } + } + + child = child->next; + } + return(ret); +} + +/** + * xmlSchematronReportSuccess: + * @ctxt: the validation context + * @test: the compiled test + * @cur: the current node tested + * @success: boolean value for the result + * + * called from the validation engine when an assert or report test have + * been done. + */ +static void +xmlSchematronReportSuccess(xmlSchematronValidCtxtPtr ctxt, + xmlSchematronTestPtr test, xmlNodePtr cur, int success) { + if ((ctxt == NULL) || (cur == NULL) || (test == NULL)) + return; + /* if quiet and not SVRL report only failures */ + if ((ctxt->flags & XML_SCHEMATRON_OUT_QUIET) && + ((ctxt->flags & XML_SCHEMATRON_OUT_XML) == 0) && + (test->type == XML_SCHEMATRON_REPORT)) + return; + if (ctxt->flags & XML_SCHEMATRON_OUT_XML) { + TODO + } else { + xmlChar *path; + char msg[1000]; + long line; + const xmlChar *report = NULL; + + if (((test->type == XML_SCHEMATRON_REPORT) & (!success)) || + ((test->type == XML_SCHEMATRON_ASSERT) & (success))) + return; + line = xmlGetLineNo(cur); + path = xmlGetNodePath(cur); + if (path == NULL) + path = (xmlChar *) cur->name; +#if 0 + if ((test->report != NULL) && (test->report[0] != 0)) + report = test->report; +#endif + if (test->node != NULL) + report = xmlSchematronFormatReport(ctxt, test->node, cur); + if (report == NULL) { + if (test->type == XML_SCHEMATRON_ASSERT) { + snprintf(msg, 999, "%s line %ld: node failed assert\n", + (const char *) path, line); + } else { + snprintf(msg, 999, "%s line %ld: node failed report\n", + (const char *) path, line); + } + } else { + snprintf(msg, 999, "%s line %ld: %s\n", (const char *) path, + line, (const char *) report); + xmlFree((char *) report); + } + xmlSchematronReportOutput(ctxt, cur, &msg[0]); + if ((path != NULL) && (path != (xmlChar *) cur->name)) + xmlFree(path); + } +} + +/** + * xmlSchematronReportPattern: + * @ctxt: the validation context + * @pattern: the current pattern + * + * called from the validation engine when starting to check a pattern + */ +static void +xmlSchematronReportPattern(xmlSchematronValidCtxtPtr ctxt, + xmlSchematronPatternPtr pattern) { + if ((ctxt == NULL) || (pattern == NULL)) + return; + if (ctxt->flags & XML_SCHEMATRON_OUT_QUIET) + return; + if (ctxt->flags & XML_SCHEMATRON_OUT_XML) { + TODO + } else { + char msg[1000]; + + if (pattern->name == NULL) + return; + snprintf(msg, 999, "Pattern: %s\n", (const char *) pattern->name); + xmlSchematronReportOutput(ctxt, NULL, &msg[0]); + } +} + + +/************************************************************************ + * * + * Validation against a Schematrontron * + * * + ************************************************************************/ + +/** + * xmlSchematronNewValidCtxt: + * @schema: a precompiled XML Schematrons + * @options: a set of xmlSchematronValidOptions + * + * Create an XML Schematrons validation context based on the given schema. + * + * Returns the validation context or NULL in case of error + */ +xmlSchematronValidCtxtPtr +xmlSchematronNewValidCtxt(xmlSchematronPtr schema, int options) +{ + int i; + xmlSchematronValidCtxtPtr ret; + + ret = (xmlSchematronValidCtxtPtr) xmlMalloc(sizeof(xmlSchematronValidCtxt)); + if (ret == NULL) { + xmlSchematronVErrMemory(NULL, "allocating validation context", + NULL); + return (NULL); + } + memset(ret, 0, sizeof(xmlSchematronValidCtxt)); + ret->type = XML_STRON_CTXT_VALIDATOR; + ret->schema = schema; + ret->xctxt = xmlXPathNewContext(NULL); + ret->flags = options; + if (ret->xctxt == NULL) { + xmlSchematronPErrMemory(NULL, "allocating schema parser XPath context", + NULL); + xmlSchematronFreeValidCtxt(ret); + return (NULL); + } + for (i = 0;i < schema->nbNamespaces;i++) { + if ((schema->namespaces[2 * i] == NULL) || + (schema->namespaces[2 * i + 1] == NULL)) + break; + xmlXPathRegisterNs(ret->xctxt, schema->namespaces[2 * i + 1], + schema->namespaces[2 * i]); + } + return (ret); +} + +/** + * xmlSchematronFreeValidCtxt: + * @ctxt: the schema validation context + * + * Free the resources associated to the schema validation context + */ +void +xmlSchematronFreeValidCtxt(xmlSchematronValidCtxtPtr ctxt) +{ + if (ctxt == NULL) + return; + if (ctxt->xctxt != NULL) + xmlXPathFreeContext(ctxt->xctxt); + if (ctxt->dict != NULL) + xmlDictFree(ctxt->dict); + xmlFree(ctxt); +} + +static xmlNodePtr +xmlSchematronNextNode(xmlNodePtr cur) { + if (cur->children != NULL) { + /* + * Do not descend on entities declarations + */ + if (cur->children->type != XML_ENTITY_DECL) { + cur = cur->children; + /* + * Skip DTDs + */ + if (cur->type != XML_DTD_NODE) + return(cur); + } + } + + while (cur->next != NULL) { + cur = cur->next; + if ((cur->type != XML_ENTITY_DECL) && + (cur->type != XML_DTD_NODE)) + return(cur); + } + + do { + cur = cur->parent; + if (cur == NULL) break; + if (cur->type == XML_DOCUMENT_NODE) return(NULL); + if (cur->next != NULL) { + cur = cur->next; + return(cur); + } + } while (cur != NULL); + return(cur); +} + +/** + * xmlSchematronRunTest: + * @ctxt: the schema validation context + * @test: the current test + * @instance: the document instace tree + * @cur: the current node in the instance + * + * Validate a rule against a tree instance at a given position + * + * Returns 1 in case of success, 0 if error and -1 in case of internal error + */ +static int +xmlSchematronRunTest(xmlSchematronValidCtxtPtr ctxt, + xmlSchematronTestPtr test, xmlDocPtr instance, xmlNodePtr cur) +{ + xmlXPathObjectPtr ret; + int failed; + + failed = 0; + ctxt->xctxt->doc = instance; + ctxt->xctxt->node = cur; + ret = xmlXPathCompiledEval(test->comp, ctxt->xctxt); + if (ret == NULL) { + failed = 1; + } else { + switch (ret->type) { + case XPATH_XSLT_TREE: + case XPATH_NODESET: + if ((ret->nodesetval == NULL) || + (ret->nodesetval->nodeNr == 0)) + failed = 1; + break; + case XPATH_BOOLEAN: + failed = !ret->boolval; + break; + case XPATH_NUMBER: + if ((xmlXPathIsNaN(ret->floatval)) || + (ret->floatval == 0.0)) + failed = 1; + break; + case XPATH_STRING: + if ((ret->stringval == NULL) || + (ret->stringval[0] == 0)) + failed = 1; + break; + case XPATH_UNDEFINED: + case XPATH_POINT: + case XPATH_RANGE: + case XPATH_LOCATIONSET: + case XPATH_USERS: + failed = 1; + break; + } + xmlXPathFreeObject(ret); + } + if ((failed) && (test->type == XML_SCHEMATRON_ASSERT)) + ctxt->nberrors++; + else if ((!failed) && (test->type == XML_SCHEMATRON_REPORT)) + ctxt->nberrors++; + + xmlSchematronReportSuccess(ctxt, test, cur, !failed); + + return(!failed); +} + +/** + * xmlSchematronValidateDoc: + * @ctxt: the schema validation context + * @instance: the document instace tree + * + * Validate a tree instance against the schematron + * + * Returns 0 in case of success, -1 in case of internal error + * and an error count otherwise. + */ +int +xmlSchematronValidateDoc(xmlSchematronValidCtxtPtr ctxt, xmlDocPtr instance) +{ + xmlNodePtr cur, root; + xmlSchematronPatternPtr pattern; + xmlSchematronRulePtr rule; + xmlSchematronTestPtr test; + + if ((ctxt == NULL) || (ctxt->schema == NULL) || + (ctxt->schema->rules == NULL) || (instance == NULL)) + return(-1); + ctxt->nberrors = 0; + root = xmlDocGetRootElement(instance); + if (root == NULL) { + TODO + ctxt->nberrors++; + return(1); + } + if ((ctxt->flags & XML_SCHEMATRON_OUT_QUIET) || + (ctxt->flags == 0)) { + /* + * we are just trying to assert the validity of the document, + * speed primes over the output, run in a single pass + */ + cur = root; + while (cur != NULL) { + rule = ctxt->schema->rules; + while (rule != NULL) { + if (xmlPatternMatch(rule->pattern, cur) == 1) { + test = rule->tests; + while (test != NULL) { + xmlSchematronRunTest(ctxt, test, instance, cur); + test = test->next; + } + } + rule = rule->next; + } + + cur = xmlSchematronNextNode(cur); + } + } else { + /* + * Process all contexts one at a time + */ + pattern = ctxt->schema->patterns; + + while (pattern != NULL) { + xmlSchematronReportPattern(ctxt, pattern); + + /* + * TODO convert the pattern rule to a direct XPath and + * compute directly instead of using the pattern matching + * over the full document... + * Check the exact semantic + */ + cur = root; + while (cur != NULL) { + rule = pattern->rules; + while (rule != NULL) { + if (xmlPatternMatch(rule->pattern, cur) == 1) { + test = rule->tests; + while (test != NULL) { + xmlSchematronRunTest(ctxt, test, instance, cur); + test = test->next; + } + } + rule = rule->patnext; + } + + cur = xmlSchematronNextNode(cur); + } + pattern = pattern->next; + } + } + return(ctxt->nberrors); +} + +#ifdef STANDALONE +int +main(void) +{ + int ret; + xmlDocPtr instance; + xmlSchematronParserCtxtPtr pctxt; + xmlSchematronValidCtxtPtr vctxt; + xmlSchematronPtr schema = NULL; + + pctxt = xmlSchematronNewParserCtxt("tst.sct"); + if (pctxt == NULL) { + fprintf(stderr, "failed to build schematron parser\n"); + } else { + schema = xmlSchematronParse(pctxt); + if (schema == NULL) { + fprintf(stderr, "failed to compile schematron\n"); + } + xmlSchematronFreeParserCtxt(pctxt); + } + instance = xmlReadFile("tst.sct", NULL, + XML_PARSE_NOENT | XML_PARSE_NOCDATA); + if (instance == NULL) { + fprintf(stderr, "failed to parse instance\n"); + } + if ((schema != NULL) && (instance != NULL)) { + vctxt = xmlSchematronNewValidCtxt(schema); + if (vctxt == NULL) { + fprintf(stderr, "failed to build schematron validator\n"); + } else { + ret = xmlSchematronValidateDoc(vctxt, instance); + xmlSchematronFreeValidCtxt(vctxt); + } + } + xmlSchematronFree(schema); + xmlFreeDoc(instance); + + xmlCleanupParser(); + xmlMemoryDump(); + + return (0); +} +#endif +#define bottom_schematron +#include "elfgcchack.h" +#endif /* LIBXML_SCHEMATRON_ENABLED */ diff --git a/gettext-tools/gnulib-lib/libxml/schematron.in.h b/gettext-tools/gnulib-lib/libxml/schematron.in.h new file mode 100644 index 0000000..6eaa699 --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/schematron.in.h @@ -0,0 +1,124 @@ +/* + * Summary: XML Schemastron implementation + * Description: interface to the XML Schematron validity checking. + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + + +#ifndef __XML_SCHEMATRON_H__ +#define __XML_SCHEMATRON_H__ + +#include + +#ifdef LIBXML_SCHEMATRON_ENABLED + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + XML_SCHEMATRON_OUT_QUIET = 1 << 0, /* quiet no report */ + XML_SCHEMATRON_OUT_TEXT = 1 << 1, /* build a textual report */ + XML_SCHEMATRON_OUT_XML = 1 << 2, /* output SVRL */ + XML_SCHEMATRON_OUT_FILE = 1 << 8, /* output to a file descriptor */ + XML_SCHEMATRON_OUT_BUFFER = 1 << 9, /* output to a buffer */ + XML_SCHEMATRON_OUT_IO = 1 << 10 /* output to I/O mechanism */ +} xmlSchematronValidOptions; + +/** + * The schemas related types are kept internal + */ +typedef struct _xmlSchematron xmlSchematron; +typedef xmlSchematron *xmlSchematronPtr; + +/** + * A schemas validation context + */ +typedef void (*xmlSchematronValidityErrorFunc) (void *ctx, const char *msg, ...); +typedef void (*xmlSchematronValidityWarningFunc) (void *ctx, const char *msg, ...); + +typedef struct _xmlSchematronParserCtxt xmlSchematronParserCtxt; +typedef xmlSchematronParserCtxt *xmlSchematronParserCtxtPtr; + +typedef struct _xmlSchematronValidCtxt xmlSchematronValidCtxt; +typedef xmlSchematronValidCtxt *xmlSchematronValidCtxtPtr; + +/* + * Interfaces for parsing. + */ +XMLPUBFUN xmlSchematronParserCtxtPtr XMLCALL + xmlSchematronNewParserCtxt (const char *URL); +XMLPUBFUN xmlSchematronParserCtxtPtr XMLCALL + xmlSchematronNewMemParserCtxt(const char *buffer, + int size); +XMLPUBFUN xmlSchematronParserCtxtPtr XMLCALL + xmlSchematronNewDocParserCtxt(xmlDocPtr doc); +XMLPUBFUN void XMLCALL + xmlSchematronFreeParserCtxt (xmlSchematronParserCtxtPtr ctxt); +/***** +XMLPUBFUN void XMLCALL + xmlSchematronSetParserErrors(xmlSchematronParserCtxtPtr ctxt, + xmlSchematronValidityErrorFunc err, + xmlSchematronValidityWarningFunc warn, + void *ctx); +XMLPUBFUN int XMLCALL + xmlSchematronGetParserErrors(xmlSchematronParserCtxtPtr ctxt, + xmlSchematronValidityErrorFunc * err, + xmlSchematronValidityWarningFunc * warn, + void **ctx); +XMLPUBFUN int XMLCALL + xmlSchematronIsValid (xmlSchematronValidCtxtPtr ctxt); + *****/ +XMLPUBFUN xmlSchematronPtr XMLCALL + xmlSchematronParse (xmlSchematronParserCtxtPtr ctxt); +XMLPUBFUN void XMLCALL + xmlSchematronFree (xmlSchematronPtr schema); +/* + * Interfaces for validating + */ +/****** +XMLPUBFUN void XMLCALL + xmlSchematronSetValidStructuredErrors( + xmlSchematronValidCtxtPtr ctxt, + xmlStructuredErrorFunc serror, + void *ctx); +XMLPUBFUN void XMLCALL + xmlSchematronSetValidErrors (xmlSchematronValidCtxtPtr ctxt, + xmlSchematronValidityErrorFunc err, + xmlSchematronValidityWarningFunc warn, + void *ctx); +XMLPUBFUN int XMLCALL + xmlSchematronGetValidErrors (xmlSchematronValidCtxtPtr ctxt, + xmlSchematronValidityErrorFunc *err, + xmlSchematronValidityWarningFunc *warn, + void **ctx); +XMLPUBFUN int XMLCALL + xmlSchematronSetValidOptions(xmlSchematronValidCtxtPtr ctxt, + int options); +XMLPUBFUN int XMLCALL + xmlSchematronValidCtxtGetOptions(xmlSchematronValidCtxtPtr ctxt); +XMLPUBFUN int XMLCALL + xmlSchematronValidateOneElement (xmlSchematronValidCtxtPtr ctxt, + xmlNodePtr elem); + *******/ + +XMLPUBFUN xmlSchematronValidCtxtPtr XMLCALL + xmlSchematronNewValidCtxt (xmlSchematronPtr schema, + int options); +XMLPUBFUN void XMLCALL + xmlSchematronFreeValidCtxt (xmlSchematronValidCtxtPtr ctxt); +XMLPUBFUN int XMLCALL + xmlSchematronValidateDoc (xmlSchematronValidCtxtPtr ctxt, + xmlDocPtr instance); + +#ifdef __cplusplus +} +#endif + +#endif /* LIBXML_SCHEMATRON_ENABLED */ +#endif /* __XML_SCHEMATRON_H__ */ diff --git a/gettext-tools/gnulib-lib/libxml/threads.c b/gettext-tools/gnulib-lib/libxml/threads.c new file mode 100644 index 0000000..7124bca --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/threads.c @@ -0,0 +1,867 @@ +/** + * threads.c: set of generic threading related routines + * + * See Copyright for the status of this software. + * + * Gary Pennington + * daniel@veillard.com + */ + +#define IN_LIBXML +#include "libxml.h" + +#include + +#include +#include + +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_PTHREAD_H +#include +#endif + +#ifdef HAVE_WIN32_THREADS +#include +#ifndef HAVE_COMPILER_TLS +#include +#endif +#endif + +#ifdef HAVE_BEOS_THREADS +#include +#include +#endif + +#if defined(SOLARIS) +#include +#endif + +/* #define DEBUG_THREADS */ + +#ifdef HAVE_PTHREAD_H + +static int libxml_is_threaded = -1; +#ifdef __GNUC__ +#ifdef linux +#if (__GNUC__ == 3 && __GNUC_MINOR__ >= 3) || (__GNUC__ > 3) +extern int pthread_once (pthread_once_t *__once_control, + void (*__init_routine) (void)) + __attribute((weak)); +extern void *pthread_getspecific (pthread_key_t __key) + __attribute((weak)); +extern int pthread_setspecific (pthread_key_t __key, + __const void *__pointer) + __attribute((weak)); +extern int pthread_key_create (pthread_key_t *__key, + void (*__destr_function) (void *)) + __attribute((weak)); +extern int pthread_mutex_init () + __attribute((weak)); +extern int pthread_mutex_destroy () + __attribute((weak)); +extern int pthread_mutex_lock () + __attribute((weak)); +extern int pthread_mutex_unlock () + __attribute((weak)); +extern int pthread_cond_init () + __attribute((weak)); +extern int pthread_equal () + __attribute((weak)); +extern pthread_t pthread_self () + __attribute((weak)); +extern int pthread_key_create () + __attribute((weak)); +extern int pthread_cond_signal () + __attribute((weak)); +#endif +#endif /* linux */ +#endif /* __GNUC__ */ +#endif /* HAVE_PTHREAD_H */ + +/* + * TODO: this module still uses malloc/free and not xmlMalloc/xmlFree + * to avoid some crazyness since xmlMalloc/xmlFree may actually + * be hosted on allocated blocks needing them for the allocation ... + */ + +/* + * xmlMutex are a simple mutual exception locks + */ +struct _xmlMutex { +#ifdef HAVE_PTHREAD_H + pthread_mutex_t lock; +#elif defined HAVE_WIN32_THREADS + HANDLE mutex; +#elif defined HAVE_BEOS_THREADS + sem_id sem; + thread_id tid; +#else + int empty; +#endif +}; + +/* + * xmlRMutex are reentrant mutual exception locks + */ +struct _xmlRMutex { +#ifdef HAVE_PTHREAD_H + pthread_mutex_t lock; + unsigned int held; + unsigned int waiters; + pthread_t tid; + pthread_cond_t cv; +#elif defined HAVE_WIN32_THREADS + CRITICAL_SECTION cs; + unsigned int count; +#elif defined HAVE_BEOS_THREADS + xmlMutexPtr lock; + thread_id tid; + int32 count; +#else + int empty; +#endif +}; +/* + * This module still has some internal static data. + * - xmlLibraryLock a global lock + * - globalkey used for per-thread data + */ + +#ifdef HAVE_PTHREAD_H +static pthread_key_t globalkey; +static pthread_t mainthread; +static pthread_once_t once_control = PTHREAD_ONCE_INIT; +#elif defined HAVE_WIN32_THREADS +#if defined(HAVE_COMPILER_TLS) +static __declspec(thread) xmlGlobalState tlstate; +static __declspec(thread) int tlstate_inited = 0; +#else /* HAVE_COMPILER_TLS */ +static DWORD globalkey = TLS_OUT_OF_INDEXES; +#endif /* HAVE_COMPILER_TLS */ +static DWORD mainthread; +static struct +{ + DWORD done; + DWORD control; +} run_once = { 0, 0 }; +/* endif HAVE_WIN32_THREADS */ +#elif defined HAVE_BEOS_THREADS +int32 globalkey = 0; +thread_id mainthread = 0; +int32 run_once_init = 0; +#endif + +static xmlRMutexPtr xmlLibraryLock = NULL; +#ifdef LIBXML_THREAD_ENABLED +static void xmlOnceInit(void); +#endif + +/** + * xmlNewMutex: + * + * xmlNewMutex() is used to allocate a libxml2 token struct for use in + * synchronizing access to data. + * + * Returns a new simple mutex pointer or NULL in case of error + */ +xmlMutexPtr +xmlNewMutex(void) +{ + xmlMutexPtr tok; + + if ((tok = malloc(sizeof(xmlMutex))) == NULL) + return (NULL); +#ifdef HAVE_PTHREAD_H + if (libxml_is_threaded != 0) + pthread_mutex_init(&tok->lock, NULL); +#elif defined HAVE_WIN32_THREADS + tok->mutex = CreateMutex(NULL, FALSE, NULL); +#elif defined HAVE_BEOS_THREADS + if ((tok->sem = create_sem(1, "xmlMutex")) < B_OK) { + free(tok); + return NULL; + } + tok->tid = -1; +#endif + return (tok); +} + +/** + * xmlFreeMutex: + * @tok: the simple mutex + * + * xmlFreeMutex() is used to reclaim resources associated with a libxml2 token + * struct. + */ +void +xmlFreeMutex(xmlMutexPtr tok) +{ + if (tok == NULL) return; + +#ifdef HAVE_PTHREAD_H + if (libxml_is_threaded != 0) + pthread_mutex_destroy(&tok->lock); +#elif defined HAVE_WIN32_THREADS + CloseHandle(tok->mutex); +#elif defined HAVE_BEOS_THREADS + delete_sem(tok->sem); +#endif + free(tok); +} + +/** + * xmlMutexLock: + * @tok: the simple mutex + * + * xmlMutexLock() is used to lock a libxml2 token. + */ +void +xmlMutexLock(xmlMutexPtr tok) +{ + if (tok == NULL) + return; +#ifdef HAVE_PTHREAD_H + if (libxml_is_threaded != 0) + pthread_mutex_lock(&tok->lock); +#elif defined HAVE_WIN32_THREADS + WaitForSingleObject(tok->mutex, INFINITE); +#elif defined HAVE_BEOS_THREADS + if (acquire_sem(tok->sem) != B_NO_ERROR) { +#ifdef DEBUG_THREADS + xmlGenericError(xmlGenericErrorContext, "xmlMutexLock():BeOS:Couldn't aquire semaphore\n"); + exit(); +#endif + } + tok->tid = find_thread(NULL); +#endif + +} + +/** + * xmlMutexUnlock: + * @tok: the simple mutex + * + * xmlMutexUnlock() is used to unlock a libxml2 token. + */ +void +xmlMutexUnlock(xmlMutexPtr tok) +{ + if (tok == NULL) + return; +#ifdef HAVE_PTHREAD_H + if (libxml_is_threaded != 0) + pthread_mutex_unlock(&tok->lock); +#elif defined HAVE_WIN32_THREADS + ReleaseMutex(tok->mutex); +#elif defined HAVE_BEOS_THREADS + if (tok->tid == find_thread(NULL)) { + tok->tid = -1; + release_sem(tok->sem); + } +#endif +} + +/** + * xmlNewRMutex: + * + * xmlRNewMutex() is used to allocate a reentrant mutex for use in + * synchronizing access to data. token_r is a re-entrant lock and thus useful + * for synchronizing access to data structures that may be manipulated in a + * recursive fashion. + * + * Returns the new reentrant mutex pointer or NULL in case of error + */ +xmlRMutexPtr +xmlNewRMutex(void) +{ + xmlRMutexPtr tok; + + if ((tok = malloc(sizeof(xmlRMutex))) == NULL) + return (NULL); +#ifdef HAVE_PTHREAD_H + if (libxml_is_threaded != 0) { + pthread_mutex_init(&tok->lock, NULL); + tok->held = 0; + tok->waiters = 0; + pthread_cond_init(&tok->cv, NULL); + } +#elif defined HAVE_WIN32_THREADS + InitializeCriticalSection(&tok->cs); + tok->count = 0; +#elif defined HAVE_BEOS_THREADS + if ((tok->lock = xmlNewMutex()) == NULL) { + free(tok); + return NULL; + } + tok->count = 0; +#endif + return (tok); +} + +/** + * xmlFreeRMutex: + * @tok: the reentrant mutex + * + * xmlRFreeMutex() is used to reclaim resources associated with a + * reentrant mutex. + */ +void +xmlFreeRMutex(xmlRMutexPtr tok ATTRIBUTE_UNUSED) +{ + if (tok == NULL) + return; +#ifdef HAVE_PTHREAD_H + if (libxml_is_threaded != 0) { + pthread_mutex_destroy(&tok->lock); + pthread_cond_destroy(&tok->cv); + } +#elif defined HAVE_WIN32_THREADS + DeleteCriticalSection(&tok->cs); +#elif defined HAVE_BEOS_THREADS + xmlFreeMutex(tok->lock); +#endif + free(tok); +} + +/** + * xmlRMutexLock: + * @tok: the reentrant mutex + * + * xmlRMutexLock() is used to lock a libxml2 token_r. + */ +void +xmlRMutexLock(xmlRMutexPtr tok) +{ + if (tok == NULL) + return; +#ifdef HAVE_PTHREAD_H + if (libxml_is_threaded == 0) + return; + + pthread_mutex_lock(&tok->lock); + if (tok->held) { + if (pthread_equal(tok->tid, pthread_self())) { + tok->held++; + pthread_mutex_unlock(&tok->lock); + return; + } else { + tok->waiters++; + while (tok->held) + pthread_cond_wait(&tok->cv, &tok->lock); + tok->waiters--; + } + } + tok->tid = pthread_self(); + tok->held = 1; + pthread_mutex_unlock(&tok->lock); +#elif defined HAVE_WIN32_THREADS + EnterCriticalSection(&tok->cs); + ++tok->count; +#elif defined HAVE_BEOS_THREADS + if (tok->lock->tid == find_thread(NULL)) { + tok->count++; + return; + } else { + xmlMutexLock(tok->lock); + tok->count = 1; + } +#endif +} + +/** + * xmlRMutexUnlock: + * @tok: the reentrant mutex + * + * xmlRMutexUnlock() is used to unlock a libxml2 token_r. + */ +void +xmlRMutexUnlock(xmlRMutexPtr tok ATTRIBUTE_UNUSED) +{ + if (tok == NULL) + return; +#ifdef HAVE_PTHREAD_H + if (libxml_is_threaded == 0) + return; + + pthread_mutex_lock(&tok->lock); + tok->held--; + if (tok->held == 0) { + if (tok->waiters) + pthread_cond_signal(&tok->cv); + tok->tid = 0; + } + pthread_mutex_unlock(&tok->lock); +#elif defined HAVE_WIN32_THREADS + if (!--tok->count) + LeaveCriticalSection(&tok->cs); +#elif defined HAVE_BEOS_THREADS + if (tok->lock->tid == find_thread(NULL)) { + tok->count--; + if (tok->count == 0) { + xmlMutexUnlock(tok->lock); + } + return; + } +#endif +} + +/************************************************************************ + * * + * Per thread global state handling * + * * + ************************************************************************/ + +#ifdef LIBXML_THREAD_ENABLED +#ifdef xmlLastError +#undef xmlLastError +#endif +/** + * xmlFreeGlobalState: + * @state: a thread global state + * + * xmlFreeGlobalState() is called when a thread terminates with a non-NULL + * global state. It is is used here to reclaim memory resources. + */ +static void +xmlFreeGlobalState(void *state) +{ + xmlGlobalState *gs = (xmlGlobalState *) state; + + /* free any memory allocated in the thread's xmlLastError */ + xmlResetError(&(gs->xmlLastError)); + free(state); +} + +/** + * xmlNewGlobalState: + * + * xmlNewGlobalState() allocates a global state. This structure is used to + * hold all data for use by a thread when supporting backwards compatibility + * of libxml2 to pre-thread-safe behaviour. + * + * Returns the newly allocated xmlGlobalStatePtr or NULL in case of error + */ +static xmlGlobalStatePtr +xmlNewGlobalState(void) +{ + xmlGlobalState *gs; + + gs = malloc(sizeof(xmlGlobalState)); + if (gs == NULL) + return(NULL); + + memset(gs, 0, sizeof(xmlGlobalState)); + xmlInitializeGlobalState(gs); + return (gs); +} +#endif /* LIBXML_THREAD_ENABLED */ + + +#ifdef HAVE_WIN32_THREADS +#if !defined(HAVE_COMPILER_TLS) +#if defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL) +typedef struct _xmlGlobalStateCleanupHelperParams +{ + HANDLE thread; + void *memory; +} xmlGlobalStateCleanupHelperParams; + +static void XMLCDECL xmlGlobalStateCleanupHelper (void *p) +{ + xmlGlobalStateCleanupHelperParams *params = (xmlGlobalStateCleanupHelperParams *) p; + WaitForSingleObject(params->thread, INFINITE); + CloseHandle(params->thread); + xmlFreeGlobalState(params->memory); + free(params); + _endthread(); +} +#else /* LIBXML_STATIC && !LIBXML_STATIC_FOR_DLL */ + +typedef struct _xmlGlobalStateCleanupHelperParams +{ + void *memory; + struct _xmlGlobalStateCleanupHelperParams * prev; + struct _xmlGlobalStateCleanupHelperParams * next; +} xmlGlobalStateCleanupHelperParams; + +static xmlGlobalStateCleanupHelperParams * cleanup_helpers_head = NULL; +static CRITICAL_SECTION cleanup_helpers_cs; + +#endif /* LIBXMLSTATIC && !LIBXML_STATIC_FOR_DLL */ +#endif /* HAVE_COMPILER_TLS */ +#endif /* HAVE_WIN32_THREADS */ + +#if defined HAVE_BEOS_THREADS +/** + * xmlGlobalStateCleanup: + * @data: unused parameter + * + * Used for Beos only + */ +void xmlGlobalStateCleanup(void *data) +{ + void *globalval = tls_get(globalkey); + if (globalval != NULL) + xmlFreeGlobalState(globalval); +} +#endif + +/** + * xmlGetGlobalState: + * + * xmlGetGlobalState() is called to retrieve the global state for a thread. + * + * Returns the thread global state or NULL in case of error + */ +xmlGlobalStatePtr +xmlGetGlobalState(void) +{ +#ifdef HAVE_PTHREAD_H + xmlGlobalState *globalval; + + if (libxml_is_threaded == 0) + return(NULL); + + pthread_once(&once_control, xmlOnceInit); + + if ((globalval = (xmlGlobalState *) + pthread_getspecific(globalkey)) == NULL) { + xmlGlobalState *tsd = xmlNewGlobalState(); + + pthread_setspecific(globalkey, tsd); + return (tsd); + } + return (globalval); +#elif defined HAVE_WIN32_THREADS +#if defined(HAVE_COMPILER_TLS) + if (!tlstate_inited) { + tlstate_inited = 1; + xmlInitializeGlobalState(&tlstate); + } + return &tlstate; +#else /* HAVE_COMPILER_TLS */ + xmlGlobalState *globalval; + xmlGlobalStateCleanupHelperParams * p; + + xmlOnceInit(); +#if defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL) + globalval = (xmlGlobalState *)TlsGetValue(globalkey); +#else + p = (xmlGlobalStateCleanupHelperParams*)TlsGetValue(globalkey); + globalval = (xmlGlobalState *)(p ? p->memory : NULL); +#endif + if (globalval == NULL) { + xmlGlobalState *tsd = xmlNewGlobalState(); + p = (xmlGlobalStateCleanupHelperParams *) malloc(sizeof(xmlGlobalStateCleanupHelperParams)); + p->memory = tsd; +#if defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL) + DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), + GetCurrentProcess(), &p->thread, 0, TRUE, DUPLICATE_SAME_ACCESS); + TlsSetValue(globalkey, tsd); + _beginthread(xmlGlobalStateCleanupHelper, 0, p); +#else + EnterCriticalSection(&cleanup_helpers_cs); + if (cleanup_helpers_head != NULL) { + cleanup_helpers_head->prev = p; + } + p->next = cleanup_helpers_head; + p->prev = NULL; + cleanup_helpers_head = p; + TlsSetValue(globalkey, p); + LeaveCriticalSection(&cleanup_helpers_cs); +#endif + + return (tsd); + } + return (globalval); +#endif /* HAVE_COMPILER_TLS */ +#elif defined HAVE_BEOS_THREADS + xmlGlobalState *globalval; + + xmlOnceInit(); + + if ((globalval = (xmlGlobalState *) + tls_get(globalkey)) == NULL) { + xmlGlobalState *tsd = xmlNewGlobalState(); + + tls_set(globalkey, tsd); + on_exit_thread(xmlGlobalStateCleanup, NULL); + return (tsd); + } + return (globalval); +#else + return(NULL); +#endif +} + +/************************************************************************ + * * + * Library wide thread interfaces * + * * + ************************************************************************/ + +/** + * xmlGetThreadId: + * + * xmlGetThreadId() find the current thread ID number + * + * Returns the current thread ID number + */ +int +xmlGetThreadId(void) +{ +#ifdef HAVE_PTHREAD_H + if (libxml_is_threaded == 0) + return(0); + return((int) pthread_self()); +#elif defined HAVE_WIN32_THREADS + return GetCurrentThreadId(); +#elif defined HAVE_BEOS_THREADS + return find_thread(NULL); +#else + return((int) 0); +#endif +} + +/** + * xmlIsMainThread: + * + * xmlIsMainThread() check whether the current thread is the main thread. + * + * Returns 1 if the current thread is the main thread, 0 otherwise + */ +int +xmlIsMainThread(void) +{ +#ifdef HAVE_PTHREAD_H + if (libxml_is_threaded == -1) + xmlInitThreads(); + if (libxml_is_threaded == 0) + return(1); + pthread_once(&once_control, xmlOnceInit); +#elif defined HAVE_WIN32_THREADS + xmlOnceInit (); +#elif defined HAVE_BEOS_THREADS + xmlOnceInit(); +#endif + +#ifdef DEBUG_THREADS + xmlGenericError(xmlGenericErrorContext, "xmlIsMainThread()\n"); +#endif +#ifdef HAVE_PTHREAD_H + return(mainthread == pthread_self()); +#elif defined HAVE_WIN32_THREADS + return(mainthread == GetCurrentThreadId ()); +#elif defined HAVE_BEOS_THREADS + return(mainthread == find_thread(NULL)); +#else + return(1); +#endif +} + +/** + * xmlLockLibrary: + * + * xmlLockLibrary() is used to take out a re-entrant lock on the libxml2 + * library. + */ +void +xmlLockLibrary(void) +{ +#ifdef DEBUG_THREADS + xmlGenericError(xmlGenericErrorContext, "xmlLockLibrary()\n"); +#endif + xmlRMutexLock(xmlLibraryLock); +} + +/** + * xmlUnlockLibrary: + * + * xmlUnlockLibrary() is used to release a re-entrant lock on the libxml2 + * library. + */ +void +xmlUnlockLibrary(void) +{ +#ifdef DEBUG_THREADS + xmlGenericError(xmlGenericErrorContext, "xmlUnlockLibrary()\n"); +#endif + xmlRMutexUnlock(xmlLibraryLock); +} + +/** + * xmlInitThreads: + * + * xmlInitThreads() is used to to initialize all the thread related + * data of the libxml2 library. + */ +void +xmlInitThreads(void) +{ +#ifdef DEBUG_THREADS + xmlGenericError(xmlGenericErrorContext, "xmlInitThreads()\n"); +#endif +#if defined(HAVE_WIN32_THREADS) && !defined(HAVE_COMPILER_TLS) && (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL)) + InitializeCriticalSection(&cleanup_helpers_cs); +#endif +#ifdef HAVE_PTHREAD_H + if (libxml_is_threaded == -1) { + if ((pthread_once != NULL) && + (pthread_getspecific != NULL) && + (pthread_setspecific != NULL) && + (pthread_key_create != NULL) && + (pthread_mutex_init != NULL) && + (pthread_mutex_destroy != NULL) && + (pthread_mutex_lock != NULL) && + (pthread_mutex_unlock != NULL) && + (pthread_cond_init != NULL) && + (pthread_equal != NULL) && + (pthread_self != NULL) && + (pthread_key_create != NULL) && + (pthread_cond_signal != NULL)) { + libxml_is_threaded = 1; +/* fprintf(stderr, "Running multithreaded\n"); */ + } else { +/* fprintf(stderr, "Running without multithread\n"); */ + libxml_is_threaded = 0; + } + } +#endif +} + +/** + * xmlCleanupThreads: + * + * xmlCleanupThreads() is used to to cleanup all the thread related + * data of the libxml2 library once processing has ended. + */ +void +xmlCleanupThreads(void) +{ +#ifdef DEBUG_THREADS + xmlGenericError(xmlGenericErrorContext, "xmlCleanupThreads()\n"); +#endif +#if defined(HAVE_WIN32_THREADS) && !defined(HAVE_COMPILER_TLS) && (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL)) + if (globalkey != TLS_OUT_OF_INDEXES) { + xmlGlobalStateCleanupHelperParams * p; + EnterCriticalSection(&cleanup_helpers_cs); + p = cleanup_helpers_head; + while (p != NULL) { + xmlGlobalStateCleanupHelperParams * temp = p; + p = p->next; + xmlFreeGlobalState(temp->memory); + free(temp); + } + cleanup_helpers_head = 0; + LeaveCriticalSection(&cleanup_helpers_cs); + TlsFree(globalkey); + globalkey = TLS_OUT_OF_INDEXES; + } + DeleteCriticalSection(&cleanup_helpers_cs); +#endif +} + +#ifdef LIBXML_THREAD_ENABLED +/** + * xmlOnceInit + * + * xmlOnceInit() is used to initialize the value of mainthread for use + * in other routines. This function should only be called using + * pthread_once() in association with the once_control variable to ensure + * that the function is only called once. See man pthread_once for more + * details. + */ +static void +xmlOnceInit(void) { +#ifdef HAVE_PTHREAD_H + (void) pthread_key_create(&globalkey, xmlFreeGlobalState); + mainthread = pthread_self(); +#endif + +#if defined(HAVE_WIN32_THREADS) + if (!run_once.done) { + if (InterlockedIncrement(&run_once.control) == 1) + { +#if !defined(HAVE_COMPILER_TLS) + globalkey = TlsAlloc(); +#endif + mainthread = GetCurrentThreadId(); + run_once.done = 1; + } + else { + /* Another thread is working; give up our slice and + * wait until they're done. */ + while (!run_once.done) + Sleep(0); + } + } +#endif + +#ifdef HAVE_BEOS_THREADS + if (atomic_add(&run_once_init, 1) == 0) { + globalkey = tls_allocate(); + tls_set(globalkey, NULL); + mainthread = find_thread(NULL); + } else + atomic_add(&run_once_init, -1); +#endif +} +#endif + +/** + * DllMain: + * @hinstDLL: handle to DLL instance + * @fdwReason: Reason code for entry + * @lpvReserved: generic pointer (depends upon reason code) + * + * Entry point for Windows library. It is being used to free thread-specific + * storage. + * + * Returns TRUE always + */ +#if defined(HAVE_WIN32_THREADS) && !defined(HAVE_COMPILER_TLS) && (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL)) +#if defined(LIBXML_STATIC_FOR_DLL) +BOOL WINAPI xmlDllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +#else +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +#endif +{ + switch(fdwReason) { + case DLL_THREAD_DETACH: + if (globalkey != TLS_OUT_OF_INDEXES) { + xmlGlobalState *globalval = NULL; + xmlGlobalStateCleanupHelperParams * p = + (xmlGlobalStateCleanupHelperParams*)TlsGetValue(globalkey); + globalval = (xmlGlobalState *)(p ? p->memory : NULL); + if (globalval) { + xmlFreeGlobalState(globalval); + TlsSetValue(globalkey,NULL); + } + if (p) + { + EnterCriticalSection(&cleanup_helpers_cs); + if (p == cleanup_helpers_head) + cleanup_helpers_head = p->next; + else + p->prev->next = p->next; + if (p->next != NULL) + p->next->prev = p->prev; + LeaveCriticalSection(&cleanup_helpers_cs); + free(p); + } + } + break; + } + return TRUE; +} +#endif +#define bottom_threads +#include "elfgcchack.h" diff --git a/gettext-tools/gnulib-lib/libxml/threads.in.h b/gettext-tools/gnulib-lib/libxml/threads.in.h new file mode 100644 index 0000000..4f7d10f --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/threads.in.h @@ -0,0 +1,80 @@ +/** + * Summary: interfaces for thread handling + * Description: set of generic threading related routines + * should work with pthreads, Windows native or TLS threads + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + +#ifndef __XML_THREADS_H__ +#define __XML_THREADS_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * xmlMutex are a simple mutual exception locks. + */ +typedef struct _xmlMutex xmlMutex; +typedef xmlMutex *xmlMutexPtr; + +/* + * xmlRMutex are reentrant mutual exception locks. + */ +typedef struct _xmlRMutex xmlRMutex; +typedef xmlRMutex *xmlRMutexPtr; + +#ifdef __cplusplus +} +#endif +#include +#ifdef __cplusplus +extern "C" { +#endif +XMLPUBFUN xmlMutexPtr XMLCALL + xmlNewMutex (void); +XMLPUBFUN void XMLCALL + xmlMutexLock (xmlMutexPtr tok); +XMLPUBFUN void XMLCALL + xmlMutexUnlock (xmlMutexPtr tok); +XMLPUBFUN void XMLCALL + xmlFreeMutex (xmlMutexPtr tok); + +XMLPUBFUN xmlRMutexPtr XMLCALL + xmlNewRMutex (void); +XMLPUBFUN void XMLCALL + xmlRMutexLock (xmlRMutexPtr tok); +XMLPUBFUN void XMLCALL + xmlRMutexUnlock (xmlRMutexPtr tok); +XMLPUBFUN void XMLCALL + xmlFreeRMutex (xmlRMutexPtr tok); + +/* + * Library wide APIs. + */ +XMLPUBFUN void XMLCALL + xmlInitThreads (void); +XMLPUBFUN void XMLCALL + xmlLockLibrary (void); +XMLPUBFUN void XMLCALL + xmlUnlockLibrary(void); +XMLPUBFUN int XMLCALL + xmlGetThreadId (void); +XMLPUBFUN int XMLCALL + xmlIsMainThread (void); +XMLPUBFUN void XMLCALL + xmlCleanupThreads(void); +XMLPUBFUN xmlGlobalStatePtr XMLCALL + xmlGetGlobalState(void); + +#ifdef __cplusplus +} +#endif + + +#endif /* __XML_THREADS_H__ */ diff --git a/gettext-tools/gnulib-lib/libxml/tree.c b/gettext-tools/gnulib-lib/libxml/tree.c new file mode 100644 index 0000000..d5b9fec --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/tree.c @@ -0,0 +1,9537 @@ +/* + * tree.c : implementation of access function for an XML tree. + * + * References: + * XHTML 1.0 W3C REC: http://www.w3.org/TR/2002/REC-xhtml1-20020801/ + * + * See Copyright for the status of this software. + * + * daniel@veillard.com + * + */ + +#define IN_LIBXML +#include "libxml.h" + +#include /* for memset() only ! */ + +#ifdef HAVE_CTYPE_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_ZLIB_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef LIBXML_HTML_ENABLED +#include +#endif +#ifdef LIBXML_DEBUG_ENABLED +#include +#endif + +int __xmlRegisterCallbacks = 0; + +/************************************************************************ + * * + * Forward declarations * + * * + ************************************************************************/ + +xmlNsPtr xmlNewReconciliedNs(xmlDocPtr doc, xmlNodePtr tree, xmlNsPtr ns); + +static xmlChar* xmlGetPropNodeValueInternal(xmlAttrPtr prop); + +/************************************************************************ + * * + * Tree memory error handler * + * * + ************************************************************************/ +/** + * xmlTreeErrMemory: + * @extra: extra informations + * + * Handle an out of memory condition + */ +static void +xmlTreeErrMemory(const char *extra) +{ + __xmlSimpleError(XML_FROM_TREE, XML_ERR_NO_MEMORY, NULL, NULL, extra); +} + +/** + * xmlTreeErr: + * @code: the error number + * @extra: extra informations + * + * Handle an out of memory condition + */ +static void +xmlTreeErr(int code, xmlNodePtr node, const char *extra) +{ + const char *msg = NULL; + + switch(code) { + case XML_TREE_INVALID_HEX: + msg = "invalid hexadecimal character value\n"; + break; + case XML_TREE_INVALID_DEC: + msg = "invalid decimal character value\n"; + break; + case XML_TREE_UNTERMINATED_ENTITY: + msg = "unterminated entity reference %15s\n"; + break; + default: + msg = "unexpected error number\n"; + } + __xmlSimpleError(XML_FROM_TREE, code, node, msg, extra); +} + +/************************************************************************ + * * + * A few static variables and macros * + * * + ************************************************************************/ +/* #undef xmlStringText */ +const xmlChar xmlStringText[] = { 't', 'e', 'x', 't', 0 }; +/* #undef xmlStringTextNoenc */ +const xmlChar xmlStringTextNoenc[] = + { 't', 'e', 'x', 't', 'n', 'o', 'e', 'n', 'c', 0 }; +/* #undef xmlStringComment */ +const xmlChar xmlStringComment[] = { 'c', 'o', 'm', 'm', 'e', 'n', 't', 0 }; + +static int xmlCompressMode = 0; +static int xmlCheckDTD = 1; + +#define UPDATE_LAST_CHILD_AND_PARENT(n) if ((n) != NULL) { \ + xmlNodePtr ulccur = (n)->children; \ + if (ulccur == NULL) { \ + (n)->last = NULL; \ + } else { \ + while (ulccur->next != NULL) { \ + ulccur->parent = (n); \ + ulccur = ulccur->next; \ + } \ + ulccur->parent = (n); \ + (n)->last = ulccur; \ +}} + +#define IS_STR_XML(str) ((str != NULL) && (str[0] == 'x') && \ + (str[1] == 'm') && (str[2] == 'l') && (str[3] == 0)) + +/* #define DEBUG_BUFFER */ +/* #define DEBUG_TREE */ + +/************************************************************************ + * * + * Functions to move to entities.c once the * + * API freeze is smoothen and they can be made public. * + * * + ************************************************************************/ +#include + +#ifdef LIBXML_TREE_ENABLED +/** + * xmlGetEntityFromDtd: + * @dtd: A pointer to the DTD to search + * @name: The entity name + * + * Do an entity lookup in the DTD entity hash table and + * return the corresponding entity, if found. + * + * Returns A pointer to the entity structure or NULL if not found. + */ +static xmlEntityPtr +xmlGetEntityFromDtd(xmlDtdPtr dtd, const xmlChar *name) { + xmlEntitiesTablePtr table; + + if((dtd != NULL) && (dtd->entities != NULL)) { + table = (xmlEntitiesTablePtr) dtd->entities; + return((xmlEntityPtr) xmlHashLookup(table, name)); + /* return(xmlGetEntityFromTable(table, name)); */ + } + return(NULL); +} +/** + * xmlGetParameterEntityFromDtd: + * @dtd: A pointer to the DTD to search + * @name: The entity name + * + * Do an entity lookup in the DTD pararmeter entity hash table and + * return the corresponding entity, if found. + * + * Returns A pointer to the entity structure or NULL if not found. + */ +static xmlEntityPtr +xmlGetParameterEntityFromDtd(xmlDtdPtr dtd, const xmlChar *name) { + xmlEntitiesTablePtr table; + + if ((dtd != NULL) && (dtd->pentities != NULL)) { + table = (xmlEntitiesTablePtr) dtd->pentities; + return((xmlEntityPtr) xmlHashLookup(table, name)); + /* return(xmlGetEntityFromTable(table, name)); */ + } + return(NULL); +} +#endif /* LIBXML_TREE_ENABLED */ + +/************************************************************************ + * * + * QName handling helper * + * * + ************************************************************************/ + +/** + * xmlBuildQName: + * @ncname: the Name + * @prefix: the prefix + * @memory: preallocated memory + * @len: preallocated memory length + * + * Builds the QName @prefix:@ncname in @memory if there is enough space + * and prefix is not NULL nor empty, otherwise allocate a new string. + * If prefix is NULL or empty it returns ncname. + * + * Returns the new string which must be freed by the caller if different from + * @memory and @ncname or NULL in case of error + */ +xmlChar * +xmlBuildQName(const xmlChar *ncname, const xmlChar *prefix, + xmlChar *memory, int len) { + int lenn, lenp; + xmlChar *ret; + + if (ncname == NULL) return(NULL); + if (prefix == NULL) return((xmlChar *) ncname); + + lenn = strlen((char *) ncname); + lenp = strlen((char *) prefix); + + if ((memory == NULL) || (len < lenn + lenp + 2)) { + ret = (xmlChar *) xmlMallocAtomic(lenn + lenp + 2); + if (ret == NULL) { + xmlTreeErrMemory("building QName"); + return(NULL); + } + } else { + ret = memory; + } + memcpy(&ret[0], prefix, lenp); + ret[lenp] = ':'; + memcpy(&ret[lenp + 1], ncname, lenn); + ret[lenn + lenp + 1] = 0; + return(ret); +} + +/** + * xmlSplitQName2: + * @name: the full QName + * @prefix: a xmlChar ** + * + * parse an XML qualified name string + * + * [NS 5] QName ::= (Prefix ':')? LocalPart + * + * [NS 6] Prefix ::= NCName + * + * [NS 7] LocalPart ::= NCName + * + * Returns NULL if not a QName, otherwise the local part, and prefix + * is updated to get the Prefix if any. + */ + +xmlChar * +xmlSplitQName2(const xmlChar *name, xmlChar **prefix) { + int len = 0; + xmlChar *ret = NULL; + + if (prefix == NULL) return(NULL); + *prefix = NULL; + if (name == NULL) return(NULL); + +#ifndef XML_XML_NAMESPACE + /* xml: prefix is not really a namespace */ + if ((name[0] == 'x') && (name[1] == 'm') && + (name[2] == 'l') && (name[3] == ':')) + return(NULL); +#endif + + /* nasty but valid */ + if (name[0] == ':') + return(NULL); + + /* + * we are not trying to validate but just to cut, and yes it will + * work even if this is as set of UTF-8 encoded chars + */ + while ((name[len] != 0) && (name[len] != ':')) + len++; + + if (name[len] == 0) + return(NULL); + + *prefix = xmlStrndup(name, len); + if (*prefix == NULL) { + xmlTreeErrMemory("QName split"); + return(NULL); + } + ret = xmlStrdup(&name[len + 1]); + if (ret == NULL) { + xmlTreeErrMemory("QName split"); + if (*prefix != NULL) { + xmlFree(*prefix); + *prefix = NULL; + } + return(NULL); + } + + return(ret); +} + +/** + * xmlSplitQName3: + * @name: the full QName + * @len: an int * + * + * parse an XML qualified name string,i + * + * returns NULL if it is not a Qualified Name, otherwise, update len + * with the lenght in byte of the prefix and return a pointer + * to the start of the name without the prefix + */ + +const xmlChar * +xmlSplitQName3(const xmlChar *name, int *len) { + int l = 0; + + if (name == NULL) return(NULL); + if (len == NULL) return(NULL); + + /* nasty but valid */ + if (name[0] == ':') + return(NULL); + + /* + * we are not trying to validate but just to cut, and yes it will + * work even if this is as set of UTF-8 encoded chars + */ + while ((name[l] != 0) && (name[l] != ':')) + l++; + + if (name[l] == 0) + return(NULL); + + *len = l; + + return(&name[l+1]); +} + +/************************************************************************ + * * + * Check Name, NCName and QName strings * + * * + ************************************************************************/ + +#define CUR_SCHAR(s, l) xmlStringCurrentChar(NULL, s, &l) + +#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) || defined(LIBXML_DEBUG_ENABLED) || defined (LIBXML_HTML_ENABLED) || defined(LIBXML_SAX1_ENABLED) || defined(LIBXML_HTML_ENABLED) || defined(LIBXML_WRITER_ENABLED) || defined(LIBXML_DOCB_ENABLED) +/** + * xmlValidateNCName: + * @value: the value to check + * @space: allow spaces in front and end of the string + * + * Check that a value conforms to the lexical space of NCName + * + * Returns 0 if this validates, a positive error code number otherwise + * and -1 in case of internal or API error. + */ +int +xmlValidateNCName(const xmlChar *value, int space) { + const xmlChar *cur = value; + int c,l; + + if (value == NULL) + return(-1); + + /* + * First quick algorithm for ASCII range + */ + if (space) + while (IS_BLANK_CH(*cur)) cur++; + if (((*cur >= 'a') && (*cur <= 'z')) || ((*cur >= 'A') && (*cur <= 'Z')) || + (*cur == '_')) + cur++; + else + goto try_complex; + while (((*cur >= 'a') && (*cur <= 'z')) || + ((*cur >= 'A') && (*cur <= 'Z')) || + ((*cur >= '0') && (*cur <= '9')) || + (*cur == '_') || (*cur == '-') || (*cur == '.')) + cur++; + if (space) + while (IS_BLANK_CH(*cur)) cur++; + if (*cur == 0) + return(0); + +try_complex: + /* + * Second check for chars outside the ASCII range + */ + cur = value; + c = CUR_SCHAR(cur, l); + if (space) { + while (IS_BLANK(c)) { + cur += l; + c = CUR_SCHAR(cur, l); + } + } + if ((!IS_LETTER(c)) && (c != '_')) + return(1); + cur += l; + c = CUR_SCHAR(cur, l); + while (IS_LETTER(c) || IS_DIGIT(c) || (c == '.') || + (c == '-') || (c == '_') || IS_COMBINING(c) || + IS_EXTENDER(c)) { + cur += l; + c = CUR_SCHAR(cur, l); + } + if (space) { + while (IS_BLANK(c)) { + cur += l; + c = CUR_SCHAR(cur, l); + } + } + if (c != 0) + return(1); + + return(0); +} +#endif + +#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) +/** + * xmlValidateQName: + * @value: the value to check + * @space: allow spaces in front and end of the string + * + * Check that a value conforms to the lexical space of QName + * + * Returns 0 if this validates, a positive error code number otherwise + * and -1 in case of internal or API error. + */ +int +xmlValidateQName(const xmlChar *value, int space) { + const xmlChar *cur = value; + int c,l; + + if (value == NULL) + return(-1); + /* + * First quick algorithm for ASCII range + */ + if (space) + while (IS_BLANK_CH(*cur)) cur++; + if (((*cur >= 'a') && (*cur <= 'z')) || ((*cur >= 'A') && (*cur <= 'Z')) || + (*cur == '_')) + cur++; + else + goto try_complex; + while (((*cur >= 'a') && (*cur <= 'z')) || + ((*cur >= 'A') && (*cur <= 'Z')) || + ((*cur >= '0') && (*cur <= '9')) || + (*cur == '_') || (*cur == '-') || (*cur == '.')) + cur++; + if (*cur == ':') { + cur++; + if (((*cur >= 'a') && (*cur <= 'z')) || + ((*cur >= 'A') && (*cur <= 'Z')) || + (*cur == '_')) + cur++; + else + goto try_complex; + while (((*cur >= 'a') && (*cur <= 'z')) || + ((*cur >= 'A') && (*cur <= 'Z')) || + ((*cur >= '0') && (*cur <= '9')) || + (*cur == '_') || (*cur == '-') || (*cur == '.')) + cur++; + } + if (space) + while (IS_BLANK_CH(*cur)) cur++; + if (*cur == 0) + return(0); + +try_complex: + /* + * Second check for chars outside the ASCII range + */ + cur = value; + c = CUR_SCHAR(cur, l); + if (space) { + while (IS_BLANK(c)) { + cur += l; + c = CUR_SCHAR(cur, l); + } + } + if ((!IS_LETTER(c)) && (c != '_')) + return(1); + cur += l; + c = CUR_SCHAR(cur, l); + while (IS_LETTER(c) || IS_DIGIT(c) || (c == '.') || + (c == '-') || (c == '_') || IS_COMBINING(c) || + IS_EXTENDER(c)) { + cur += l; + c = CUR_SCHAR(cur, l); + } + if (c == ':') { + cur += l; + c = CUR_SCHAR(cur, l); + if ((!IS_LETTER(c)) && (c != '_')) + return(1); + cur += l; + c = CUR_SCHAR(cur, l); + while (IS_LETTER(c) || IS_DIGIT(c) || (c == '.') || + (c == '-') || (c == '_') || IS_COMBINING(c) || + IS_EXTENDER(c)) { + cur += l; + c = CUR_SCHAR(cur, l); + } + } + if (space) { + while (IS_BLANK(c)) { + cur += l; + c = CUR_SCHAR(cur, l); + } + } + if (c != 0) + return(1); + return(0); +} + +/** + * xmlValidateName: + * @value: the value to check + * @space: allow spaces in front and end of the string + * + * Check that a value conforms to the lexical space of Name + * + * Returns 0 if this validates, a positive error code number otherwise + * and -1 in case of internal or API error. + */ +int +xmlValidateName(const xmlChar *value, int space) { + const xmlChar *cur = value; + int c,l; + + if (value == NULL) + return(-1); + /* + * First quick algorithm for ASCII range + */ + if (space) + while (IS_BLANK_CH(*cur)) cur++; + if (((*cur >= 'a') && (*cur <= 'z')) || ((*cur >= 'A') && (*cur <= 'Z')) || + (*cur == '_') || (*cur == ':')) + cur++; + else + goto try_complex; + while (((*cur >= 'a') && (*cur <= 'z')) || + ((*cur >= 'A') && (*cur <= 'Z')) || + ((*cur >= '0') && (*cur <= '9')) || + (*cur == '_') || (*cur == '-') || (*cur == '.') || (*cur == ':')) + cur++; + if (space) + while (IS_BLANK_CH(*cur)) cur++; + if (*cur == 0) + return(0); + +try_complex: + /* + * Second check for chars outside the ASCII range + */ + cur = value; + c = CUR_SCHAR(cur, l); + if (space) { + while (IS_BLANK(c)) { + cur += l; + c = CUR_SCHAR(cur, l); + } + } + if ((!IS_LETTER(c)) && (c != '_') && (c != ':')) + return(1); + cur += l; + c = CUR_SCHAR(cur, l); + while (IS_LETTER(c) || IS_DIGIT(c) || (c == '.') || (c == ':') || + (c == '-') || (c == '_') || IS_COMBINING(c) || IS_EXTENDER(c)) { + cur += l; + c = CUR_SCHAR(cur, l); + } + if (space) { + while (IS_BLANK(c)) { + cur += l; + c = CUR_SCHAR(cur, l); + } + } + if (c != 0) + return(1); + return(0); +} + +/** + * xmlValidateNMToken: + * @value: the value to check + * @space: allow spaces in front and end of the string + * + * Check that a value conforms to the lexical space of NMToken + * + * Returns 0 if this validates, a positive error code number otherwise + * and -1 in case of internal or API error. + */ +int +xmlValidateNMToken(const xmlChar *value, int space) { + const xmlChar *cur = value; + int c,l; + + if (value == NULL) + return(-1); + /* + * First quick algorithm for ASCII range + */ + if (space) + while (IS_BLANK_CH(*cur)) cur++; + if (((*cur >= 'a') && (*cur <= 'z')) || + ((*cur >= 'A') && (*cur <= 'Z')) || + ((*cur >= '0') && (*cur <= '9')) || + (*cur == '_') || (*cur == '-') || (*cur == '.') || (*cur == ':')) + cur++; + else + goto try_complex; + while (((*cur >= 'a') && (*cur <= 'z')) || + ((*cur >= 'A') && (*cur <= 'Z')) || + ((*cur >= '0') && (*cur <= '9')) || + (*cur == '_') || (*cur == '-') || (*cur == '.') || (*cur == ':')) + cur++; + if (space) + while (IS_BLANK_CH(*cur)) cur++; + if (*cur == 0) + return(0); + +try_complex: + /* + * Second check for chars outside the ASCII range + */ + cur = value; + c = CUR_SCHAR(cur, l); + if (space) { + while (IS_BLANK(c)) { + cur += l; + c = CUR_SCHAR(cur, l); + } + } + if (!(IS_LETTER(c) || IS_DIGIT(c) || (c == '.') || (c == ':') || + (c == '-') || (c == '_') || IS_COMBINING(c) || IS_EXTENDER(c))) + return(1); + cur += l; + c = CUR_SCHAR(cur, l); + while (IS_LETTER(c) || IS_DIGIT(c) || (c == '.') || (c == ':') || + (c == '-') || (c == '_') || IS_COMBINING(c) || IS_EXTENDER(c)) { + cur += l; + c = CUR_SCHAR(cur, l); + } + if (space) { + while (IS_BLANK(c)) { + cur += l; + c = CUR_SCHAR(cur, l); + } + } + if (c != 0) + return(1); + return(0); +} +#endif /* LIBXML_TREE_ENABLED */ + +/************************************************************************ + * * + * Allocation and deallocation of basic structures * + * * + ************************************************************************/ + +/** + * xmlSetBufferAllocationScheme: + * @scheme: allocation method to use + * + * Set the buffer allocation method. Types are + * XML_BUFFER_ALLOC_EXACT - use exact sizes, keeps memory usage down + * XML_BUFFER_ALLOC_DOUBLEIT - double buffer when extra needed, + * improves performance + */ +void +xmlSetBufferAllocationScheme(xmlBufferAllocationScheme scheme) { + xmlBufferAllocScheme = scheme; +} + +/** + * xmlGetBufferAllocationScheme: + * + * Types are + * XML_BUFFER_ALLOC_EXACT - use exact sizes, keeps memory usage down + * XML_BUFFER_ALLOC_DOUBLEIT - double buffer when extra needed, + * improves performance + * + * Returns the current allocation scheme + */ +xmlBufferAllocationScheme +xmlGetBufferAllocationScheme(void) { + return(xmlBufferAllocScheme); +} + +/** + * xmlNewNs: + * @node: the element carrying the namespace + * @href: the URI associated + * @prefix: the prefix for the namespace + * + * Creation of a new Namespace. This function will refuse to create + * a namespace with a similar prefix than an existing one present on this + * node. + * We use href==NULL in the case of an element creation where the namespace + * was not defined. + * Returns a new namespace pointer or NULL + */ +xmlNsPtr +xmlNewNs(xmlNodePtr node, const xmlChar *href, const xmlChar *prefix) { + xmlNsPtr cur; + + if ((node != NULL) && (node->type != XML_ELEMENT_NODE)) + return(NULL); + + if ((prefix != NULL) && (xmlStrEqual(prefix, BAD_CAST "xml"))) + return(NULL); + + /* + * Allocate a new Namespace and fill the fields. + */ + cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs)); + if (cur == NULL) { + xmlTreeErrMemory("building namespace"); + return(NULL); + } + memset(cur, 0, sizeof(xmlNs)); + cur->type = XML_LOCAL_NAMESPACE; + + if (href != NULL) + cur->href = xmlStrdup(href); + if (prefix != NULL) + cur->prefix = xmlStrdup(prefix); + + /* + * Add it at the end to preserve parsing order ... + * and checks for existing use of the prefix + */ + if (node != NULL) { + if (node->nsDef == NULL) { + node->nsDef = cur; + } else { + xmlNsPtr prev = node->nsDef; + + if (((prev->prefix == NULL) && (cur->prefix == NULL)) || + (xmlStrEqual(prev->prefix, cur->prefix))) { + xmlFreeNs(cur); + return(NULL); + } + while (prev->next != NULL) { + prev = prev->next; + if (((prev->prefix == NULL) && (cur->prefix == NULL)) || + (xmlStrEqual(prev->prefix, cur->prefix))) { + xmlFreeNs(cur); + return(NULL); + } + } + prev->next = cur; + } + } + return(cur); +} + +/** + * xmlSetNs: + * @node: a node in the document + * @ns: a namespace pointer + * + * Associate a namespace to a node, a posteriori. + */ +void +xmlSetNs(xmlNodePtr node, xmlNsPtr ns) { + if (node == NULL) { +#ifdef DEBUG_TREE + xmlGenericError(xmlGenericErrorContext, + "xmlSetNs: node == NULL\n"); +#endif + return; + } + node->ns = ns; +} + +/** + * xmlFreeNs: + * @cur: the namespace pointer + * + * Free up the structures associated to a namespace + */ +void +xmlFreeNs(xmlNsPtr cur) { + if (cur == NULL) { +#ifdef DEBUG_TREE + xmlGenericError(xmlGenericErrorContext, + "xmlFreeNs : ns == NULL\n"); +#endif + return; + } + if (cur->href != NULL) xmlFree((char *) cur->href); + if (cur->prefix != NULL) xmlFree((char *) cur->prefix); + xmlFree(cur); +} + +/** + * xmlFreeNsList: + * @cur: the first namespace pointer + * + * Free up all the structures associated to the chained namespaces. + */ +void +xmlFreeNsList(xmlNsPtr cur) { + xmlNsPtr next; + if (cur == NULL) { +#ifdef DEBUG_TREE + xmlGenericError(xmlGenericErrorContext, + "xmlFreeNsList : ns == NULL\n"); +#endif + return; + } + while (cur != NULL) { + next = cur->next; + xmlFreeNs(cur); + cur = next; + } +} + +/** + * xmlNewDtd: + * @doc: the document pointer + * @name: the DTD name + * @ExternalID: the external ID + * @SystemID: the system ID + * + * Creation of a new DTD for the external subset. To create an + * internal subset, use xmlCreateIntSubset(). + * + * Returns a pointer to the new DTD structure + */ +xmlDtdPtr +xmlNewDtd(xmlDocPtr doc, const xmlChar *name, + const xmlChar *ExternalID, const xmlChar *SystemID) { + xmlDtdPtr cur; + + if ((doc != NULL) && (doc->extSubset != NULL)) { +#ifdef DEBUG_TREE + xmlGenericError(xmlGenericErrorContext, + "xmlNewDtd(%s): document %s already have a DTD %s\n", + /* !!! */ (char *) name, doc->name, + /* !!! */ (char *)doc->extSubset->name); +#endif + return(NULL); + } + + /* + * Allocate a new DTD and fill the fields. + */ + cur = (xmlDtdPtr) xmlMalloc(sizeof(xmlDtd)); + if (cur == NULL) { + xmlTreeErrMemory("building DTD"); + return(NULL); + } + memset(cur, 0 , sizeof(xmlDtd)); + cur->type = XML_DTD_NODE; + + if (name != NULL) + cur->name = xmlStrdup(name); + if (ExternalID != NULL) + cur->ExternalID = xmlStrdup(ExternalID); + if (SystemID != NULL) + cur->SystemID = xmlStrdup(SystemID); + if (doc != NULL) + doc->extSubset = cur; + cur->doc = doc; + + if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)) + xmlRegisterNodeDefaultValue((xmlNodePtr)cur); + return(cur); +} + +/** + * xmlGetIntSubset: + * @doc: the document pointer + * + * Get the internal subset of a document + * Returns a pointer to the DTD structure or NULL if not found + */ + +xmlDtdPtr +xmlGetIntSubset(xmlDocPtr doc) { + xmlNodePtr cur; + + if (doc == NULL) + return(NULL); + cur = doc->children; + while (cur != NULL) { + if (cur->type == XML_DTD_NODE) + return((xmlDtdPtr) cur); + cur = cur->next; + } + return((xmlDtdPtr) doc->intSubset); +} + +/** + * xmlCreateIntSubset: + * @doc: the document pointer + * @name: the DTD name + * @ExternalID: the external (PUBLIC) ID + * @SystemID: the system ID + * + * Create the internal subset of a document + * Returns a pointer to the new DTD structure + */ +xmlDtdPtr +xmlCreateIntSubset(xmlDocPtr doc, const xmlChar *name, + const xmlChar *ExternalID, const xmlChar *SystemID) { + xmlDtdPtr cur; + + if ((doc != NULL) && (xmlGetIntSubset(doc) != NULL)) { +#ifdef DEBUG_TREE + xmlGenericError(xmlGenericErrorContext, + + "xmlCreateIntSubset(): document %s already have an internal subset\n", + doc->name); +#endif + return(NULL); + } + + /* + * Allocate a new DTD and fill the fields. + */ + cur = (xmlDtdPtr) xmlMalloc(sizeof(xmlDtd)); + if (cur == NULL) { + xmlTreeErrMemory("building internal subset"); + return(NULL); + } + memset(cur, 0, sizeof(xmlDtd)); + cur->type = XML_DTD_NODE; + + if (name != NULL) { + cur->name = xmlStrdup(name); + if (cur->name == NULL) { + xmlTreeErrMemory("building internal subset"); + xmlFree(cur); + return(NULL); + } + } + if (ExternalID != NULL) { + cur->ExternalID = xmlStrdup(ExternalID); + if (cur->ExternalID == NULL) { + xmlTreeErrMemory("building internal subset"); + if (cur->name != NULL) + xmlFree((char *)cur->name); + xmlFree(cur); + return(NULL); + } + } + if (SystemID != NULL) { + cur->SystemID = xmlStrdup(SystemID); + if (cur->SystemID == NULL) { + xmlTreeErrMemory("building internal subset"); + if (cur->name != NULL) + xmlFree((char *)cur->name); + if (cur->ExternalID != NULL) + xmlFree((char *)cur->ExternalID); + xmlFree(cur); + return(NULL); + } + } + if (doc != NULL) { + doc->intSubset = cur; + cur->parent = doc; + cur->doc = doc; + if (doc->children == NULL) { + doc->children = (xmlNodePtr) cur; + doc->last = (xmlNodePtr) cur; + } else { + if (doc->type == XML_HTML_DOCUMENT_NODE) { + xmlNodePtr prev; + + prev = doc->children; + prev->prev = (xmlNodePtr) cur; + cur->next = prev; + doc->children = (xmlNodePtr) cur; + } else { + xmlNodePtr next; + + next = doc->children; + while ((next != NULL) && (next->type != XML_ELEMENT_NODE)) + next = next->next; + if (next == NULL) { + cur->prev = doc->last; + cur->prev->next = (xmlNodePtr) cur; + cur->next = NULL; + doc->last = (xmlNodePtr) cur; + } else { + cur->next = next; + cur->prev = next->prev; + if (cur->prev == NULL) + doc->children = (xmlNodePtr) cur; + else + cur->prev->next = (xmlNodePtr) cur; + next->prev = (xmlNodePtr) cur; + } + } + } + } + + if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)) + xmlRegisterNodeDefaultValue((xmlNodePtr)cur); + return(cur); +} + +/** + * DICT_FREE: + * @str: a string + * + * Free a string if it is not owned by the "dict" dictionnary in the + * current scope + */ +#define DICT_FREE(str) \ + if ((str) && ((!dict) || \ + (xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \ + xmlFree((char *)(str)); + + +/** + * DICT_COPY: + * @str: a string + * + * Copy a string using a "dict" dictionnary in the current scope, + * if availabe. + */ +#define DICT_COPY(str, cpy) \ + if (str) { \ + if (dict) { \ + if (xmlDictOwns(dict, (const xmlChar *)(str))) \ + cpy = (xmlChar *) (str); \ + else \ + cpy = (xmlChar *) xmlDictLookup((dict), (const xmlChar *)(str), -1); \ + } else \ + cpy = xmlStrdup((const xmlChar *)(str)); } + +/** + * DICT_CONST_COPY: + * @str: a string + * + * Copy a string using a "dict" dictionnary in the current scope, + * if availabe. + */ +#define DICT_CONST_COPY(str, cpy) \ + if (str) { \ + if (dict) { \ + if (xmlDictOwns(dict, (const xmlChar *)(str))) \ + cpy = (const xmlChar *) (str); \ + else \ + cpy = xmlDictLookup((dict), (const xmlChar *)(str), -1); \ + } else \ + cpy = (const xmlChar *) xmlStrdup((const xmlChar *)(str)); } + + +/** + * xmlFreeDtd: + * @cur: the DTD structure to free up + * + * Free a DTD structure. + */ +void +xmlFreeDtd(xmlDtdPtr cur) { + xmlDictPtr dict = NULL; + + if (cur == NULL) { + return; + } + if (cur->doc != NULL) dict = cur->doc->dict; + + if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue)) + xmlDeregisterNodeDefaultValue((xmlNodePtr)cur); + + if (cur->children != NULL) { + xmlNodePtr next, c = cur->children; + + /* + * Cleanup all nodes which are not part of the specific lists + * of notations, elements, attributes and entities. + */ + while (c != NULL) { + next = c->next; + if ((c->type != XML_NOTATION_NODE) && + (c->type != XML_ELEMENT_DECL) && + (c->type != XML_ATTRIBUTE_DECL) && + (c->type != XML_ENTITY_DECL)) { + xmlUnlinkNode(c); + xmlFreeNode(c); + } + c = next; + } + } + DICT_FREE(cur->name) + DICT_FREE(cur->SystemID) + DICT_FREE(cur->ExternalID) + /* TODO !!! */ + if (cur->notations != NULL) + xmlFreeNotationTable((xmlNotationTablePtr) cur->notations); + + if (cur->elements != NULL) + xmlFreeElementTable((xmlElementTablePtr) cur->elements); + if (cur->attributes != NULL) + xmlFreeAttributeTable((xmlAttributeTablePtr) cur->attributes); + if (cur->entities != NULL) + xmlFreeEntitiesTable((xmlEntitiesTablePtr) cur->entities); + if (cur->pentities != NULL) + xmlFreeEntitiesTable((xmlEntitiesTablePtr) cur->pentities); + + xmlFree(cur); +} + +/** + * xmlNewDoc: + * @version: xmlChar string giving the version of XML "1.0" + * + * Creates a new XML document + * + * Returns a new document + */ +xmlDocPtr +xmlNewDoc(const xmlChar *version) { + xmlDocPtr cur; + + if (version == NULL) + version = (const xmlChar *) "1.0"; + + /* + * Allocate a new document and fill the fields. + */ + cur = (xmlDocPtr) xmlMalloc(sizeof(xmlDoc)); + if (cur == NULL) { + xmlTreeErrMemory("building doc"); + return(NULL); + } + memset(cur, 0, sizeof(xmlDoc)); + cur->type = XML_DOCUMENT_NODE; + + cur->version = xmlStrdup(version); + if (cur->version == NULL) { + xmlTreeErrMemory("building doc"); + xmlFree(cur); + return(NULL); + } + cur->standalone = -1; + cur->compression = -1; /* not initialized */ + cur->doc = cur; + /* + * The in memory encoding is always UTF8 + * This field will never change and would + * be obsolete if not for binary compatibility. + */ + cur->charset = XML_CHAR_ENCODING_UTF8; + + if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)) + xmlRegisterNodeDefaultValue((xmlNodePtr)cur); + return(cur); +} + +/** + * xmlFreeDoc: + * @cur: pointer to the document + * + * Free up all the structures used by a document, tree included. + */ +void +xmlFreeDoc(xmlDocPtr cur) { + xmlDtdPtr extSubset, intSubset; + xmlDictPtr dict = NULL; + + if (cur == NULL) { +#ifdef DEBUG_TREE + xmlGenericError(xmlGenericErrorContext, + "xmlFreeDoc : document == NULL\n"); +#endif + return; + } +#ifdef LIBXML_DEBUG_RUNTIME +#ifdef LIBXML_DEBUG_ENABLED + xmlDebugCheckDocument(stderr, cur); +#endif +#endif + + if (cur != NULL) dict = cur->dict; + + if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue)) + xmlDeregisterNodeDefaultValue((xmlNodePtr)cur); + + /* + * Do this before freeing the children list to avoid ID lookups + */ + if (cur->ids != NULL) xmlFreeIDTable((xmlIDTablePtr) cur->ids); + cur->ids = NULL; + if (cur->refs != NULL) xmlFreeRefTable((xmlRefTablePtr) cur->refs); + cur->refs = NULL; + extSubset = cur->extSubset; + intSubset = cur->intSubset; + if (intSubset == extSubset) + extSubset = NULL; + if (extSubset != NULL) { + xmlUnlinkNode((xmlNodePtr) cur->extSubset); + cur->extSubset = NULL; + xmlFreeDtd(extSubset); + } + if (intSubset != NULL) { + xmlUnlinkNode((xmlNodePtr) cur->intSubset); + cur->intSubset = NULL; + xmlFreeDtd(intSubset); + } + + if (cur->children != NULL) xmlFreeNodeList(cur->children); + if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs); + + DICT_FREE(cur->version) + DICT_FREE(cur->name) + DICT_FREE(cur->encoding) + DICT_FREE(cur->URL) + xmlFree(cur); + if (dict) xmlDictFree(dict); +} + +/** + * xmlStringLenGetNodeList: + * @doc: the document + * @value: the value of the text + * @len: the length of the string value + * + * Parse the value string and build the node list associated. Should + * produce a flat tree with only TEXTs and ENTITY_REFs. + * Returns a pointer to the first child + */ +xmlNodePtr +xmlStringLenGetNodeList(xmlDocPtr doc, const xmlChar *value, int len) { + xmlNodePtr ret = NULL, last = NULL; + xmlNodePtr node; + xmlChar *val; + const xmlChar *cur = value, *end = cur + len; + const xmlChar *q; + xmlEntityPtr ent; + + if (value == NULL) return(NULL); + + q = cur; + while ((cur < end) && (*cur != 0)) { + if (cur[0] == '&') { + int charval = 0; + xmlChar tmp; + + /* + * Save the current text. + */ + if (cur != q) { + if ((last != NULL) && (last->type == XML_TEXT_NODE)) { + xmlNodeAddContentLen(last, q, cur - q); + } else { + node = xmlNewDocTextLen(doc, q, cur - q); + if (node == NULL) return(ret); + if (last == NULL) + last = ret = node; + else { + last->next = node; + node->prev = last; + last = node; + } + } + } + q = cur; + if ((cur + 2 < end) && (cur[1] == '#') && (cur[2] == 'x')) { + cur += 3; + if (cur < end) + tmp = *cur; + else + tmp = 0; + while (tmp != ';') { /* Non input consuming loop */ + if ((tmp >= '0') && (tmp <= '9')) + charval = charval * 16 + (tmp - '0'); + else if ((tmp >= 'a') && (tmp <= 'f')) + charval = charval * 16 + (tmp - 'a') + 10; + else if ((tmp >= 'A') && (tmp <= 'F')) + charval = charval * 16 + (tmp - 'A') + 10; + else { + xmlTreeErr(XML_TREE_INVALID_HEX, (xmlNodePtr) doc, + NULL); + charval = 0; + break; + } + cur++; + if (cur < end) + tmp = *cur; + else + tmp = 0; + } + if (tmp == ';') + cur++; + q = cur; + } else if ((cur + 1 < end) && (cur[1] == '#')) { + cur += 2; + if (cur < end) + tmp = *cur; + else + tmp = 0; + while (tmp != ';') { /* Non input consuming loops */ + if ((tmp >= '0') && (tmp <= '9')) + charval = charval * 10 + (tmp - '0'); + else { + xmlTreeErr(XML_TREE_INVALID_DEC, (xmlNodePtr) doc, + NULL); + charval = 0; + break; + } + cur++; + if (cur < end) + tmp = *cur; + else + tmp = 0; + } + if (tmp == ';') + cur++; + q = cur; + } else { + /* + * Read the entity string + */ + cur++; + q = cur; + while ((cur < end) && (*cur != 0) && (*cur != ';')) cur++; + if ((cur >= end) || (*cur == 0)) { + xmlTreeErr(XML_TREE_UNTERMINATED_ENTITY, (xmlNodePtr) doc, + (const char *) q); + return(ret); + } + if (cur != q) { + /* + * Predefined entities don't generate nodes + */ + val = xmlStrndup(q, cur - q); + ent = xmlGetDocEntity(doc, val); + if ((ent != NULL) && + (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) { + if (last == NULL) { + node = xmlNewDocText(doc, ent->content); + last = ret = node; + } else if (last->type != XML_TEXT_NODE) { + node = xmlNewDocText(doc, ent->content); + last = xmlAddNextSibling(last, node); + } else + xmlNodeAddContent(last, ent->content); + + } else { + /* + * Create a new REFERENCE_REF node + */ + node = xmlNewReference(doc, val); + if (node == NULL) { + if (val != NULL) xmlFree(val); + return(ret); + } + else if ((ent != NULL) && (ent->children == NULL)) { + xmlNodePtr temp; + + ent->children = xmlStringGetNodeList(doc, + (const xmlChar*)node->content); + ent->owner = 1; + temp = ent->children; + while (temp) { + temp->parent = (xmlNodePtr)ent; + ent->last = temp; + temp = temp->next; + } + } + if (last == NULL) { + last = ret = node; + } else { + last = xmlAddNextSibling(last, node); + } + } + xmlFree(val); + } + cur++; + q = cur; + } + if (charval != 0) { + xmlChar buf[10]; + int l; + + l = xmlCopyCharMultiByte(buf, charval); + buf[l] = 0; + node = xmlNewDocText(doc, buf); + if (node != NULL) { + if (last == NULL) { + last = ret = node; + } else { + last = xmlAddNextSibling(last, node); + } + } + charval = 0; + } + } else + cur++; + } + if ((cur != q) || (ret == NULL)) { + /* + * Handle the last piece of text. + */ + if ((last != NULL) && (last->type == XML_TEXT_NODE)) { + xmlNodeAddContentLen(last, q, cur - q); + } else { + node = xmlNewDocTextLen(doc, q, cur - q); + if (node == NULL) return(ret); + if (last == NULL) { + last = ret = node; + } else { + last = xmlAddNextSibling(last, node); + } + } + } + return(ret); +} + +/** + * xmlStringGetNodeList: + * @doc: the document + * @value: the value of the attribute + * + * Parse the value string and build the node list associated. Should + * produce a flat tree with only TEXTs and ENTITY_REFs. + * Returns a pointer to the first child + */ +xmlNodePtr +xmlStringGetNodeList(xmlDocPtr doc, const xmlChar *value) { + xmlNodePtr ret = NULL, last = NULL; + xmlNodePtr node; + xmlChar *val; + const xmlChar *cur = value; + const xmlChar *q; + xmlEntityPtr ent; + + if (value == NULL) return(NULL); + + q = cur; + while (*cur != 0) { + if (cur[0] == '&') { + int charval = 0; + xmlChar tmp; + + /* + * Save the current text. + */ + if (cur != q) { + if ((last != NULL) && (last->type == XML_TEXT_NODE)) { + xmlNodeAddContentLen(last, q, cur - q); + } else { + node = xmlNewDocTextLen(doc, q, cur - q); + if (node == NULL) return(ret); + if (last == NULL) + last = ret = node; + else { + last->next = node; + node->prev = last; + last = node; + } + } + } + q = cur; + if ((cur[1] == '#') && (cur[2] == 'x')) { + cur += 3; + tmp = *cur; + while (tmp != ';') { /* Non input consuming loop */ + if ((tmp >= '0') && (tmp <= '9')) + charval = charval * 16 + (tmp - '0'); + else if ((tmp >= 'a') && (tmp <= 'f')) + charval = charval * 16 + (tmp - 'a') + 10; + else if ((tmp >= 'A') && (tmp <= 'F')) + charval = charval * 16 + (tmp - 'A') + 10; + else { + xmlTreeErr(XML_TREE_INVALID_HEX, (xmlNodePtr) doc, + NULL); + charval = 0; + break; + } + cur++; + tmp = *cur; + } + if (tmp == ';') + cur++; + q = cur; + } else if (cur[1] == '#') { + cur += 2; + tmp = *cur; + while (tmp != ';') { /* Non input consuming loops */ + if ((tmp >= '0') && (tmp <= '9')) + charval = charval * 10 + (tmp - '0'); + else { + xmlTreeErr(XML_TREE_INVALID_DEC, (xmlNodePtr) doc, + NULL); + charval = 0; + break; + } + cur++; + tmp = *cur; + } + if (tmp == ';') + cur++; + q = cur; + } else { + /* + * Read the entity string + */ + cur++; + q = cur; + while ((*cur != 0) && (*cur != ';')) cur++; + if (*cur == 0) { + xmlTreeErr(XML_TREE_UNTERMINATED_ENTITY, + (xmlNodePtr) doc, (const char *) q); + return(ret); + } + if (cur != q) { + /* + * Predefined entities don't generate nodes + */ + val = xmlStrndup(q, cur - q); + ent = xmlGetDocEntity(doc, val); + if ((ent != NULL) && + (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) { + if (last == NULL) { + node = xmlNewDocText(doc, ent->content); + last = ret = node; + } else if (last->type != XML_TEXT_NODE) { + node = xmlNewDocText(doc, ent->content); + last = xmlAddNextSibling(last, node); + } else + xmlNodeAddContent(last, ent->content); + + } else { + /* + * Create a new REFERENCE_REF node + */ + node = xmlNewReference(doc, val); + if (node == NULL) { + if (val != NULL) xmlFree(val); + return(ret); + } + else if ((ent != NULL) && (ent->children == NULL)) { + xmlNodePtr temp; + + ent->children = xmlStringGetNodeList(doc, + (const xmlChar*)node->content); + ent->owner = 1; + temp = ent->children; + while (temp) { + temp->parent = (xmlNodePtr)ent; + temp = temp->next; + } + } + if (last == NULL) { + last = ret = node; + } else { + last = xmlAddNextSibling(last, node); + } + } + xmlFree(val); + } + cur++; + q = cur; + } + if (charval != 0) { + xmlChar buf[10]; + int len; + + len = xmlCopyCharMultiByte(buf, charval); + buf[len] = 0; + node = xmlNewDocText(doc, buf); + if (node != NULL) { + if (last == NULL) { + last = ret = node; + } else { + last = xmlAddNextSibling(last, node); + } + } + + charval = 0; + } + } else + cur++; + } + if ((cur != q) || (ret == NULL)) { + /* + * Handle the last piece of text. + */ + if ((last != NULL) && (last->type == XML_TEXT_NODE)) { + xmlNodeAddContentLen(last, q, cur - q); + } else { + node = xmlNewDocTextLen(doc, q, cur - q); + if (node == NULL) return(ret); + if (last == NULL) { + last = ret = node; + } else { + last = xmlAddNextSibling(last, node); + } + } + } + return(ret); +} + +/** + * xmlNodeListGetString: + * @doc: the document + * @list: a Node list + * @inLine: should we replace entity contents or show their external form + * + * Build the string equivalent to the text contained in the Node list + * made of TEXTs and ENTITY_REFs + * + * Returns a pointer to the string copy, the caller must free it with xmlFree(). + */ +xmlChar * +xmlNodeListGetString(xmlDocPtr doc, xmlNodePtr list, int inLine) +{ + xmlNodePtr node = list; + xmlChar *ret = NULL; + xmlEntityPtr ent; + + if (list == NULL) + return (NULL); + + while (node != NULL) { + if ((node->type == XML_TEXT_NODE) || + (node->type == XML_CDATA_SECTION_NODE)) { + if (inLine) { + ret = xmlStrcat(ret, node->content); + } else { + xmlChar *buffer; + + buffer = xmlEncodeEntitiesReentrant(doc, node->content); + if (buffer != NULL) { + ret = xmlStrcat(ret, buffer); + xmlFree(buffer); + } + } + } else if (node->type == XML_ENTITY_REF_NODE) { + if (inLine) { + ent = xmlGetDocEntity(doc, node->name); + if (ent != NULL) { + xmlChar *buffer; + + /* an entity content can be any "well balanced chunk", + * i.e. the result of the content [43] production: + * http://www.w3.org/TR/REC-xml#NT-content. + * So it can contain text, CDATA section or nested + * entity reference nodes (among others). + * -> we recursive call xmlNodeListGetString() + * which handles these types */ + buffer = xmlNodeListGetString(doc, ent->children, 1); + if (buffer != NULL) { + ret = xmlStrcat(ret, buffer); + xmlFree(buffer); + } + } else { + ret = xmlStrcat(ret, node->content); + } + } else { + xmlChar buf[2]; + + buf[0] = '&'; + buf[1] = 0; + ret = xmlStrncat(ret, buf, 1); + ret = xmlStrcat(ret, node->name); + buf[0] = ';'; + buf[1] = 0; + ret = xmlStrncat(ret, buf, 1); + } + } +#if 0 + else { + xmlGenericError(xmlGenericErrorContext, + "xmlGetNodeListString : invalid node type %d\n", + node->type); + } +#endif + node = node->next; + } + return (ret); +} + +#ifdef LIBXML_TREE_ENABLED +/** + * xmlNodeListGetRawString: + * @doc: the document + * @list: a Node list + * @inLine: should we replace entity contents or show their external form + * + * Builds the string equivalent to the text contained in the Node list + * made of TEXTs and ENTITY_REFs, contrary to xmlNodeListGetString() + * this function doesn't do any character encoding handling. + * + * Returns a pointer to the string copy, the caller must free it with xmlFree(). + */ +xmlChar * +xmlNodeListGetRawString(xmlDocPtr doc, xmlNodePtr list, int inLine) +{ + xmlNodePtr node = list; + xmlChar *ret = NULL; + xmlEntityPtr ent; + + if (list == NULL) + return (NULL); + + while (node != NULL) { + if ((node->type == XML_TEXT_NODE) || + (node->type == XML_CDATA_SECTION_NODE)) { + if (inLine) { + ret = xmlStrcat(ret, node->content); + } else { + xmlChar *buffer; + + buffer = xmlEncodeSpecialChars(doc, node->content); + if (buffer != NULL) { + ret = xmlStrcat(ret, buffer); + xmlFree(buffer); + } + } + } else if (node->type == XML_ENTITY_REF_NODE) { + if (inLine) { + ent = xmlGetDocEntity(doc, node->name); + if (ent != NULL) { + xmlChar *buffer; + + /* an entity content can be any "well balanced chunk", + * i.e. the result of the content [43] production: + * http://www.w3.org/TR/REC-xml#NT-content. + * So it can contain text, CDATA section or nested + * entity reference nodes (among others). + * -> we recursive call xmlNodeListGetRawString() + * which handles these types */ + buffer = + xmlNodeListGetRawString(doc, ent->children, 1); + if (buffer != NULL) { + ret = xmlStrcat(ret, buffer); + xmlFree(buffer); + } + } else { + ret = xmlStrcat(ret, node->content); + } + } else { + xmlChar buf[2]; + + buf[0] = '&'; + buf[1] = 0; + ret = xmlStrncat(ret, buf, 1); + ret = xmlStrcat(ret, node->name); + buf[0] = ';'; + buf[1] = 0; + ret = xmlStrncat(ret, buf, 1); + } + } +#if 0 + else { + xmlGenericError(xmlGenericErrorContext, + "xmlGetNodeListString : invalid node type %d\n", + node->type); + } +#endif + node = node->next; + } + return (ret); +} +#endif /* LIBXML_TREE_ENABLED */ + +static xmlAttrPtr +xmlNewPropInternal(xmlNodePtr node, xmlNsPtr ns, + const xmlChar * name, const xmlChar * value, + int eatname) +{ + xmlAttrPtr cur; + xmlDocPtr doc = NULL; + + if ((node != NULL) && (node->type != XML_ELEMENT_NODE)) { + if (eatname == 1) + xmlFree((xmlChar *) name); + return (NULL); + } + + /* + * Allocate a new property and fill the fields. + */ + cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr)); + if (cur == NULL) { + if (eatname == 1) + xmlFree((xmlChar *) name); + xmlTreeErrMemory("building attribute"); + return (NULL); + } + memset(cur, 0, sizeof(xmlAttr)); + cur->type = XML_ATTRIBUTE_NODE; + + cur->parent = node; + if (node != NULL) { + doc = node->doc; + cur->doc = doc; + } + cur->ns = ns; + + if (eatname == 0) { + if ((doc != NULL) && (doc->dict != NULL)) + cur->name = (xmlChar *) xmlDictLookup(doc->dict, name, -1); + else + cur->name = xmlStrdup(name); + } else + cur->name = name; + + if (value != NULL) { + xmlChar *buffer; + xmlNodePtr tmp; + + buffer = xmlEncodeEntitiesReentrant(doc, value); + cur->children = xmlStringGetNodeList(doc, buffer); + cur->last = NULL; + tmp = cur->children; + while (tmp != NULL) { + tmp->parent = (xmlNodePtr) cur; + if (tmp->next == NULL) + cur->last = tmp; + tmp = tmp->next; + } + xmlFree(buffer); + } + + /* + * Add it at the end to preserve parsing order ... + */ + if (node != NULL) { + if (node->properties == NULL) { + node->properties = cur; + } else { + xmlAttrPtr prev = node->properties; + + while (prev->next != NULL) + prev = prev->next; + prev->next = cur; + cur->prev = prev; + } + } + + if (xmlIsID((node == NULL) ? NULL : node->doc, node, cur) == 1) + xmlAddID(NULL, node->doc, value, cur); + + if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)) + xmlRegisterNodeDefaultValue((xmlNodePtr) cur); + return (cur); +} + +#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_HTML_ENABLED) || \ + defined(LIBXML_SCHEMAS_ENABLED) +/** + * xmlNewProp: + * @node: the holding node + * @name: the name of the attribute + * @value: the value of the attribute + * + * Create a new property carried by a node. + * Returns a pointer to the attribute + */ +xmlAttrPtr +xmlNewProp(xmlNodePtr node, const xmlChar *name, const xmlChar *value) { + + if (name == NULL) { +#ifdef DEBUG_TREE + xmlGenericError(xmlGenericErrorContext, + "xmlNewProp : name == NULL\n"); +#endif + return(NULL); + } + + return xmlNewPropInternal(node, NULL, name, value, 0); +} +#endif /* LIBXML_TREE_ENABLED */ + +/** + * xmlNewNsProp: + * @node: the holding node + * @ns: the namespace + * @name: the name of the attribute + * @value: the value of the attribute + * + * Create a new property tagged with a namespace and carried by a node. + * Returns a pointer to the attribute + */ +xmlAttrPtr +xmlNewNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name, + const xmlChar *value) { + + if (name == NULL) { +#ifdef DEBUG_TREE + xmlGenericError(xmlGenericErrorContext, + "xmlNewNsProp : name == NULL\n"); +#endif + return(NULL); + } + + return xmlNewPropInternal(node, ns, name, value, 0); +} + +/** + * xmlNewNsPropEatName: + * @node: the holding node + * @ns: the namespace + * @name: the name of the attribute + * @value: the value of the attribute + * + * Create a new property tagged with a namespace and carried by a node. + * Returns a pointer to the attribute + */ +xmlAttrPtr +xmlNewNsPropEatName(xmlNodePtr node, xmlNsPtr ns, xmlChar *name, + const xmlChar *value) { + + if (name == NULL) { +#ifdef DEBUG_TREE + xmlGenericError(xmlGenericErrorContext, + "xmlNewNsPropEatName : name == NULL\n"); +#endif + return(NULL); + } + + return xmlNewPropInternal(node, ns, name, value, 1); +} + +/** + * xmlNewDocProp: + * @doc: the document + * @name: the name of the attribute + * @value: the value of the attribute + * + * Create a new property carried by a document. + * Returns a pointer to the attribute + */ +xmlAttrPtr +xmlNewDocProp(xmlDocPtr doc, const xmlChar *name, const xmlChar *value) { + xmlAttrPtr cur; + + if (name == NULL) { +#ifdef DEBUG_TREE + xmlGenericError(xmlGenericErrorContext, + "xmlNewDocProp : name == NULL\n"); +#endif + return(NULL); + } + + /* + * Allocate a new property and fill the fields. + */ + cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr)); + if (cur == NULL) { + xmlTreeErrMemory("building attribute"); + return(NULL); + } + memset(cur, 0, sizeof(xmlAttr)); + cur->type = XML_ATTRIBUTE_NODE; + + if ((doc != NULL) && (doc->dict != NULL)) + cur->name = xmlDictLookup(doc->dict, name, -1); + else + cur->name = xmlStrdup(name); + cur->doc = doc; + if (value != NULL) { + xmlNodePtr tmp; + + cur->children = xmlStringGetNodeList(doc, value); + cur->last = NULL; + + tmp = cur->children; + while (tmp != NULL) { + tmp->parent = (xmlNodePtr) cur; + if (tmp->next == NULL) + cur->last = tmp; + tmp = tmp->next; + } + } + + if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)) + xmlRegisterNodeDefaultValue((xmlNodePtr)cur); + return(cur); +} + +/** + * xmlFreePropList: + * @cur: the first property in the list + * + * Free a property and all its siblings, all the children are freed too. + */ +void +xmlFreePropList(xmlAttrPtr cur) { + xmlAttrPtr next; + if (cur == NULL) return; + while (cur != NULL) { + next = cur->next; + xmlFreeProp(cur); + cur = next; + } +} + +/** + * xmlFreeProp: + * @cur: an attribute + * + * Free one attribute, all the content is freed too + */ +void +xmlFreeProp(xmlAttrPtr cur) { + xmlDictPtr dict = NULL; + if (cur == NULL) return; + + if (cur->doc != NULL) dict = cur->doc->dict; + + if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue)) + xmlDeregisterNodeDefaultValue((xmlNodePtr)cur); + + /* Check for ID removal -> leading to invalid references ! */ + if ((cur->doc != NULL) && (cur->atype == XML_ATTRIBUTE_ID)) { + xmlRemoveID(cur->doc, cur); + } + if (cur->children != NULL) xmlFreeNodeList(cur->children); + DICT_FREE(cur->name) + xmlFree(cur); +} + +/** + * xmlRemoveProp: + * @cur: an attribute + * + * Unlink and free one attribute, all the content is freed too + * Note this doesn't work for namespace definition attributes + * + * Returns 0 if success and -1 in case of error. + */ +int +xmlRemoveProp(xmlAttrPtr cur) { + xmlAttrPtr tmp; + if (cur == NULL) { +#ifdef DEBUG_TREE + xmlGenericError(xmlGenericErrorContext, + "xmlRemoveProp : cur == NULL\n"); +#endif + return(-1); + } + if (cur->parent == NULL) { +#ifdef DEBUG_TREE + xmlGenericError(xmlGenericErrorContext, + "xmlRemoveProp : cur->parent == NULL\n"); +#endif + return(-1); + } + tmp = cur->parent->properties; + if (tmp == cur) { + cur->parent->properties = cur->next; + if (cur->next != NULL) + cur->next->prev = NULL; + xmlFreeProp(cur); + return(0); + } + while (tmp != NULL) { + if (tmp->next == cur) { + tmp->next = cur->next; + if (tmp->next != NULL) + tmp->next->prev = tmp; + xmlFreeProp(cur); + return(0); + } + tmp = tmp->next; + } +#ifdef DEBUG_TREE + xmlGenericError(xmlGenericErrorContext, + "xmlRemoveProp : attribute not owned by its node\n"); +#endif + return(-1); +} + +/** + * xmlNewDocPI: + * @doc: the target document + * @name: the processing instruction name + * @content: the PI content + * + * Creation of a processing instruction element. + * Returns a pointer to the new node object. + */ +xmlNodePtr +xmlNewDocPI(xmlDocPtr doc, const xmlChar *name, const xmlChar *content) { + xmlNodePtr cur; + + if (name == NULL) { +#ifdef DEBUG_TREE + xmlGenericError(xmlGenericErrorContext, + "xmlNewPI : name == NULL\n"); +#endif + return(NULL); + } + + /* + * Allocate a new node and fill the fields. + */ + cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode)); + if (cur == NULL) { + xmlTreeErrMemory("building PI"); + return(NULL); + } + memset(cur, 0, sizeof(xmlNode)); + cur->type = XML_PI_NODE; + + if ((doc != NULL) && (doc->dict != NULL)) + cur->name = xmlDictLookup(doc->dict, name, -1); + else + cur->name = xmlStrdup(name); + if (content != NULL) { + cur->content = xmlStrdup(content); + } + cur->doc = doc; + + if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)) + xmlRegisterNodeDefaultValue((xmlNodePtr)cur); + return(cur); +} + +/** + * xmlNewPI: + * @name: the processing instruction name + * @content: the PI content + * + * Creation of a processing instruction element. + * Use xmlDocNewPI preferably to get string interning + * + * Returns a pointer to the new node object. + */ +xmlNodePtr +xmlNewPI(const xmlChar *name, const xmlChar *content) { + return(xmlNewDocPI(NULL, name, content)); +} + +/** + * xmlNewNode: + * @ns: namespace if any + * @name: the node name + * + * Creation of a new node element. @ns is optional (NULL). + * + * Returns a pointer to the new node object. Uses xmlStrdup() to make + * copy of @name. + */ +xmlNodePtr +xmlNewNode(xmlNsPtr ns, const xmlChar *name) { + xmlNodePtr cur; + + if (name == NULL) { +#ifdef DEBUG_TREE + xmlGenericError(xmlGenericErrorContext, + "xmlNewNode : name == NULL\n"); +#endif + return(NULL); + } + + /* + * Allocate a new node and fill the fields. + */ + cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode)); + if (cur == NULL) { + xmlTreeErrMemory("building node"); + return(NULL); + } + memset(cur, 0, sizeof(xmlNode)); + cur->type = XML_ELEMENT_NODE; + + cur->name = xmlStrdup(name); + cur->ns = ns; + + if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)) + xmlRegisterNodeDefaultValue(cur); + return(cur); +} + +/** + * xmlNewNodeEatName: + * @ns: namespace if any + * @name: the node name + * + * Creation of a new node element. @ns is optional (NULL). + * + * Returns a pointer to the new node object, with pointer @name as + * new node's name. Use xmlNewNode() if a copy of @name string is + * is needed as new node's name. + */ +xmlNodePtr +xmlNewNodeEatName(xmlNsPtr ns, xmlChar *name) { + xmlNodePtr cur; + + if (name == NULL) { +#ifdef DEBUG_TREE + xmlGenericError(xmlGenericErrorContext, + "xmlNewNode : name == NULL\n"); +#endif + return(NULL); + } + + /* + * Allocate a new node and fill the fields. + */ + cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode)); + if (cur == NULL) { + xmlFree(name); + xmlTreeErrMemory("building node"); + return(NULL); + } + memset(cur, 0, sizeof(xmlNode)); + cur->type = XML_ELEMENT_NODE; + + cur->name = name; + cur->ns = ns; + + if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)) + xmlRegisterNodeDefaultValue((xmlNodePtr)cur); + return(cur); +} + +/** + * xmlNewDocNode: + * @doc: the document + * @ns: namespace if any + * @name: the node name + * @content: the XML text content if any + * + * Creation of a new node element within a document. @ns and @content + * are optional (NULL). + * NOTE: @content is supposed to be a piece of XML CDATA, so it allow entities + * references, but XML special chars need to be escaped first by using + * xmlEncodeEntitiesReentrant(). Use xmlNewDocRawNode() if you don't + * need entities support. + * + * Returns a pointer to the new node object. + */ +xmlNodePtr +xmlNewDocNode(xmlDocPtr doc, xmlNsPtr ns, + const xmlChar *name, const xmlChar *content) { + xmlNodePtr cur; + + if ((doc != NULL) && (doc->dict != NULL)) + cur = xmlNewNodeEatName(ns, (xmlChar *) + xmlDictLookup(doc->dict, name, -1)); + else + cur = xmlNewNode(ns, name); + if (cur != NULL) { + cur->doc = doc; + if (content != NULL) { + cur->children = xmlStringGetNodeList(doc, content); + UPDATE_LAST_CHILD_AND_PARENT(cur) + } + } + + return(cur); +} + +/** + * xmlNewDocNodeEatName: + * @doc: the document + * @ns: namespace if any + * @name: the node name + * @content: the XML text content if any + * + * Creation of a new node element within a document. @ns and @content + * are optional (NULL). + * NOTE: @content is supposed to be a piece of XML CDATA, so it allow entities + * references, but XML special chars need to be escaped first by using + * xmlEncodeEntitiesReentrant(). Use xmlNewDocRawNode() if you don't + * need entities support. + * + * Returns a pointer to the new node object. + */ +xmlNodePtr +xmlNewDocNodeEatName(xmlDocPtr doc, xmlNsPtr ns, + xmlChar *name, const xmlChar *content) { + xmlNodePtr cur; + + cur = xmlNewNodeEatName(ns, name); + if (cur != NULL) { + cur->doc = doc; + if (content != NULL) { + cur->children = xmlStringGetNodeList(doc, content); + UPDATE_LAST_CHILD_AND_PARENT(cur) + } + } + return(cur); +} + +#ifdef LIBXML_TREE_ENABLED +/** + * xmlNewDocRawNode: + * @doc: the document + * @ns: namespace if any + * @name: the node name + * @content: the text content if any + * + * Creation of a new node element within a document. @ns and @content + * are optional (NULL). + * + * Returns a pointer to the new node object. + */ +xmlNodePtr +xmlNewDocRawNode(xmlDocPtr doc, xmlNsPtr ns, + const xmlChar *name, const xmlChar *content) { + xmlNodePtr cur; + + cur = xmlNewDocNode(doc, ns, name, NULL); + if (cur != NULL) { + cur->doc = doc; + if (content != NULL) { + cur->children = xmlNewDocText(doc, content); + UPDATE_LAST_CHILD_AND_PARENT(cur) + } + } + return(cur); +} + +/** + * xmlNewDocFragment: + * @doc: the document owning the fragment + * + * Creation of a new Fragment node. + * Returns a pointer to the new node object. + */ +xmlNodePtr +xmlNewDocFragment(xmlDocPtr doc) { + xmlNodePtr cur; + + /* + * Allocate a new DocumentFragment node and fill the fields. + */ + cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode)); + if (cur == NULL) { + xmlTreeErrMemory("building fragment"); + return(NULL); + } + memset(cur, 0, sizeof(xmlNode)); + cur->type = XML_DOCUMENT_FRAG_NODE; + + cur->doc = doc; + + if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)) + xmlRegisterNodeDefaultValue(cur); + return(cur); +} +#endif /* LIBXML_TREE_ENABLED */ + +/** + * xmlNewText: + * @content: the text content + * + * Creation of a new text node. + * Returns a pointer to the new node object. + */ +xmlNodePtr +xmlNewText(const xmlChar *content) { + xmlNodePtr cur; + + /* + * Allocate a new node and fill the fields. + */ + cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode)); + if (cur == NULL) { + xmlTreeErrMemory("building text"); + return(NULL); + } + memset(cur, 0, sizeof(xmlNode)); + cur->type = XML_TEXT_NODE; + + cur->name = xmlStringText; + if (content != NULL) { + cur->content = xmlStrdup(content); + } + + if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)) + xmlRegisterNodeDefaultValue(cur); + return(cur); +} + +#ifdef LIBXML_TREE_ENABLED +/** + * xmlNewTextChild: + * @parent: the parent node + * @ns: a namespace if any + * @name: the name of the child + * @content: the text content of the child if any. + * + * Creation of a new child element, added at the end of @parent children list. + * @ns and @content parameters are optional (NULL). If @ns is NULL, the newly + * created element inherits the namespace of @parent. If @content is non NULL, + * a child TEXT node will be created containing the string @content. + * NOTE: Use xmlNewChild() if @content will contain entities that need to be + * preserved. Use this function, xmlNewTextChild(), if you need to ensure that + * reserved XML chars that might appear in @content, such as the ampersand, + * greater-than or less-than signs, are automatically replaced by their XML + * escaped entity representations. + * + * Returns a pointer to the new node object. + */ +xmlNodePtr +xmlNewTextChild(xmlNodePtr parent, xmlNsPtr ns, + const xmlChar *name, const xmlChar *content) { + xmlNodePtr cur, prev; + + if (parent == NULL) { +#ifdef DEBUG_TREE + xmlGenericError(xmlGenericErrorContext, + "xmlNewTextChild : parent == NULL\n"); +#endif + return(NULL); + } + + if (name == NULL) { +#ifdef DEBUG_TREE + xmlGenericError(xmlGenericErrorContext, + "xmlNewTextChild : name == NULL\n"); +#endif + return(NULL); + } + + /* + * Allocate a new node + */ + if (parent->type == XML_ELEMENT_NODE) { + if (ns == NULL) + cur = xmlNewDocRawNode(parent->doc, parent->ns, name, content); + else + cur = xmlNewDocRawNode(parent->doc, ns, name, content); + } else if ((parent->type == XML_DOCUMENT_NODE) || + (parent->type == XML_HTML_DOCUMENT_NODE)) { + if (ns == NULL) + cur = xmlNewDocRawNode((xmlDocPtr) parent, NULL, name, content); + else + cur = xmlNewDocRawNode((xmlDocPtr) parent, ns, name, content); + } else if (parent->type == XML_DOCUMENT_FRAG_NODE) { + cur = xmlNewDocRawNode( parent->doc, ns, name, content); + } else { + return(NULL); + } + if (cur == NULL) return(NULL); + + /* + * add the new element at the end of the children list. + */ + cur->type = XML_ELEMENT_NODE; + cur->parent = parent; + cur->doc = parent->doc; + if (parent->children == NULL) { + parent->children = cur; + parent->last = cur; + } else { + prev = parent->last; + prev->next = cur; + cur->prev = prev; + parent->last = cur; + } + + return(cur); +} +#endif /* LIBXML_TREE_ENABLED */ + +/** + * xmlNewCharRef: + * @doc: the document + * @name: the char ref string, starting with # or "&# ... ;" + * + * Creation of a new character reference node. + * Returns a pointer to the new node object. + */ +xmlNodePtr +xmlNewCharRef(xmlDocPtr doc, const xmlChar *name) { + xmlNodePtr cur; + + if (name == NULL) + return(NULL); + + /* + * Allocate a new node and fill the fields. + */ + cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode)); + if (cur == NULL) { + xmlTreeErrMemory("building character reference"); + return(NULL); + } + memset(cur, 0, sizeof(xmlNode)); + cur->type = XML_ENTITY_REF_NODE; + + cur->doc = doc; + if (name[0] == '&') { + int len; + name++; + len = xmlStrlen(name); + if (name[len - 1] == ';') + cur->name = xmlStrndup(name, len - 1); + else + cur->name = xmlStrndup(name, len); + } else + cur->name = xmlStrdup(name); + + if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)) + xmlRegisterNodeDefaultValue(cur); + return(cur); +} + +/** + * xmlNewReference: + * @doc: the document + * @name: the reference name, or the reference string with & and ; + * + * Creation of a new reference node. + * Returns a pointer to the new node object. + */ +xmlNodePtr +xmlNewReference(xmlDocPtr doc, const xmlChar *name) { + xmlNodePtr cur; + xmlEntityPtr ent; + + if (name == NULL) + return(NULL); + + /* + * Allocate a new node and fill the fields. + */ + cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode)); + if (cur == NULL) { + xmlTreeErrMemory("building reference"); + return(NULL); + } + memset(cur, 0, sizeof(xmlNode)); + cur->type = XML_ENTITY_REF_NODE; + + cur->doc = doc; + if (name[0] == '&') { + int len; + name++; + len = xmlStrlen(name); + if (name[len - 1] == ';') + cur->name = xmlStrndup(name, len - 1); + else + cur->name = xmlStrndup(name, len); + } else + cur->name = xmlStrdup(name); + + ent = xmlGetDocEntity(doc, cur->name); + if (ent != NULL) { + cur->content = ent->content; + /* + * The parent pointer in entity is a DTD pointer and thus is NOT + * updated. Not sure if this is 100% correct. + * -George + */ + cur->children = (xmlNodePtr) ent; + cur->last = (xmlNodePtr) ent; + } + + if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)) + xmlRegisterNodeDefaultValue(cur); + return(cur); +} + +/** + * xmlNewDocText: + * @doc: the document + * @content: the text content + * + * Creation of a new text node within a document. + * Returns a pointer to the new node object. + */ +xmlNodePtr +xmlNewDocText(xmlDocPtr doc, const xmlChar *content) { + xmlNodePtr cur; + + cur = xmlNewText(content); + if (cur != NULL) cur->doc = doc; + return(cur); +} + +/** + * xmlNewTextLen: + * @content: the text content + * @len: the text len. + * + * Creation of a new text node with an extra parameter for the content's length + * Returns a pointer to the new node object. + */ +xmlNodePtr +xmlNewTextLen(const xmlChar *content, int len) { + xmlNodePtr cur; + + /* + * Allocate a new node and fill the fields. + */ + cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode)); + if (cur == NULL) { + xmlTreeErrMemory("building text"); + return(NULL); + } + memset(cur, 0, sizeof(xmlNode)); + cur->type = XML_TEXT_NODE; + + cur->name = xmlStringText; + if (content != NULL) { + cur->content = xmlStrndup(content, len); + } + + if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)) + xmlRegisterNodeDefaultValue(cur); + return(cur); +} + +/** + * xmlNewDocTextLen: + * @doc: the document + * @content: the text content + * @len: the text len. + * + * Creation of a new text node with an extra content length parameter. The + * text node pertain to a given document. + * Returns a pointer to the new node object. + */ +xmlNodePtr +xmlNewDocTextLen(xmlDocPtr doc, const xmlChar *content, int len) { + xmlNodePtr cur; + + cur = xmlNewTextLen(content, len); + if (cur != NULL) cur->doc = doc; + return(cur); +} + +/** + * xmlNewComment: + * @content: the comment content + * + * Creation of a new node containing a comment. + * Returns a pointer to the new node object. + */ +xmlNodePtr +xmlNewComment(const xmlChar *content) { + xmlNodePtr cur; + + /* + * Allocate a new node and fill the fields. + */ + cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode)); + if (cur == NULL) { + xmlTreeErrMemory("building comment"); + return(NULL); + } + memset(cur, 0, sizeof(xmlNode)); + cur->type = XML_COMMENT_NODE; + + cur->name = xmlStringComment; + if (content != NULL) { + cur->content = xmlStrdup(content); + } + + if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)) + xmlRegisterNodeDefaultValue(cur); + return(cur); +} + +/** + * xmlNewCDataBlock: + * @doc: the document + * @content: the CDATA block content content + * @len: the length of the block + * + * Creation of a new node containing a CDATA block. + * Returns a pointer to the new node object. + */ +xmlNodePtr +xmlNewCDataBlock(xmlDocPtr doc, const xmlChar *content, int len) { + xmlNodePtr cur; + + /* + * Allocate a new node and fill the fields. + */ + cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode)); + if (cur == NULL) { + xmlTreeErrMemory("building CDATA"); + return(NULL); + } + memset(cur, 0, sizeof(xmlNode)); + cur->type = XML_CDATA_SECTION_NODE; + cur->doc = doc; + + if (content != NULL) { + cur->content = xmlStrndup(content, len); + } + + if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)) + xmlRegisterNodeDefaultValue(cur); + return(cur); +} + +/** + * xmlNewDocComment: + * @doc: the document + * @content: the comment content + * + * Creation of a new node containing a comment within a document. + * Returns a pointer to the new node object. + */ +xmlNodePtr +xmlNewDocComment(xmlDocPtr doc, const xmlChar *content) { + xmlNodePtr cur; + + cur = xmlNewComment(content); + if (cur != NULL) cur->doc = doc; + return(cur); +} + +/** + * xmlSetTreeDoc: + * @tree: the top element + * @doc: the document + * + * update all nodes under the tree to point to the right document + */ +void +xmlSetTreeDoc(xmlNodePtr tree, xmlDocPtr doc) { + xmlAttrPtr prop; + + if (tree == NULL) + return; + if (tree->doc != doc) { + if(tree->type == XML_ELEMENT_NODE) { + prop = tree->properties; + while (prop != NULL) { + prop->doc = doc; + xmlSetListDoc(prop->children, doc); + prop = prop->next; + } + } + if (tree->children != NULL) + xmlSetListDoc(tree->children, doc); + tree->doc = doc; + } +} + +/** + * xmlSetListDoc: + * @list: the first element + * @doc: the document + * + * update all nodes in the list to point to the right document + */ +void +xmlSetListDoc(xmlNodePtr list, xmlDocPtr doc) { + xmlNodePtr cur; + + if (list == NULL) + return; + cur = list; + while (cur != NULL) { + if (cur->doc != doc) + xmlSetTreeDoc(cur, doc); + cur = cur->next; + } +} + +#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) +/** + * xmlNewChild: + * @parent: the parent node + * @ns: a namespace if any + * @name: the name of the child + * @content: the XML content of the child if any. + * + * Creation of a new child element, added at the end of @parent children list. + * @ns and @content parameters are optional (NULL). If @ns is NULL, the newly + * created element inherits the namespace of @parent. If @content is non NULL, + * a child list containing the TEXTs and ENTITY_REFs node will be created. + * NOTE: @content is supposed to be a piece of XML CDATA, so it allows entity + * references. XML special chars must be escaped first by using + * xmlEncodeEntitiesReentrant(), or xmlNewTextChild() should be used. + * + * Returns a pointer to the new node object. + */ +xmlNodePtr +xmlNewChild(xmlNodePtr parent, xmlNsPtr ns, + const xmlChar *name, const xmlChar *content) { + xmlNodePtr cur, prev; + + if (parent == NULL) { +#ifdef DEBUG_TREE + xmlGenericError(xmlGenericErrorContext, + "xmlNewChild : parent == NULL\n"); +#endif + return(NULL); + } + + if (name == NULL) { +#ifdef DEBUG_TREE + xmlGenericError(xmlGenericErrorContext, + "xmlNewChild : name == NULL\n"); +#endif + return(NULL); + } + + /* + * Allocate a new node + */ + if (parent->type == XML_ELEMENT_NODE) { + if (ns == NULL) + cur = xmlNewDocNode(parent->doc, parent->ns, name, content); + else + cur = xmlNewDocNode(parent->doc, ns, name, content); + } else if ((parent->type == XML_DOCUMENT_NODE) || + (parent->type == XML_HTML_DOCUMENT_NODE)) { + if (ns == NULL) + cur = xmlNewDocNode((xmlDocPtr) parent, NULL, name, content); + else + cur = xmlNewDocNode((xmlDocPtr) parent, ns, name, content); + } else if (parent->type == XML_DOCUMENT_FRAG_NODE) { + cur = xmlNewDocNode( parent->doc, ns, name, content); + } else { + return(NULL); + } + if (cur == NULL) return(NULL); + + /* + * add the new element at the end of the children list. + */ + cur->type = XML_ELEMENT_NODE; + cur->parent = parent; + cur->doc = parent->doc; + if (parent->children == NULL) { + parent->children = cur; + parent->last = cur; + } else { + prev = parent->last; + prev->next = cur; + cur->prev = prev; + parent->last = cur; + } + + return(cur); +} +#endif /* LIBXML_TREE_ENABLED */ + +/** + * xmlAddPropSibling: + * @prev: the attribute to which @prop is added after + * @cur: the base attribute passed to calling function + * @prop: the new attribute + * + * Add a new attribute after @prev using @cur as base attribute. + * When inserting before @cur, @prev is passed as @cur->prev. + * When inserting after @cur, @prev is passed as @cur. + * If an existing attribute is found it is detroyed prior to adding @prop. + * + * Returns the attribute being inserted or NULL in case of error. + */ +static xmlNodePtr +xmlAddPropSibling(xmlNodePtr prev, xmlNodePtr cur, xmlNodePtr prop) { + xmlAttrPtr attr; + + if (cur->type != XML_ATTRIBUTE_NODE) + return(NULL); + + /* check if an attribute with the same name exists */ + if (prop->ns == NULL) + attr = xmlHasNsProp(cur->parent, prop->name, NULL); + else + attr = xmlHasNsProp(cur->parent, prop->name, prop->ns->href); + + if (prop->doc != cur->doc) { + xmlSetTreeDoc(prop, cur->doc); + } + prop->parent = cur->parent; + prop->prev = prev; + if (prev != NULL) { + prop->next = prev->next; + prev->next = prop; + if (prop->next) + prop->next->prev = prop; + } else { + prop->next = cur; + cur->prev = prop; + } + if (prop->prev == NULL && prop->parent != NULL) + prop->parent->properties = (xmlAttrPtr) prop; + if ((attr != NULL) && (attr->type != XML_ATTRIBUTE_DECL)) { + /* different instance, destroy it (attributes must be unique) */ + xmlRemoveProp((xmlAttrPtr) attr); + } + return prop; +} + +/** + * xmlAddNextSibling: + * @cur: the child node + * @elem: the new node + * + * Add a new node @elem as the next sibling of @cur + * If the new node was already inserted in a document it is + * first unlinked from its existing context. + * As a result of text merging @elem may be freed. + * If the new node is ATTRIBUTE, it is added into properties instead of children. + * If there is an attribute with equal name, it is first destroyed. + * + * Returns the new node or NULL in case of error. + */ +xmlNodePtr +xmlAddNextSibling(xmlNodePtr cur, xmlNodePtr elem) { + if (cur == NULL) { +#ifdef DEBUG_TREE + xmlGenericError(xmlGenericErrorContext, + "xmlAddNextSibling : cur == NULL\n"); +#endif + return(NULL); + } + if (elem == NULL) { +#ifdef DEBUG_TREE + xmlGenericError(xmlGenericErrorContext, + "xmlAddNextSibling : elem == NULL\n"); +#endif + return(NULL); + } + + if (cur == elem) { +#ifdef DEBUG_TREE + xmlGenericError(xmlGenericErrorContext, + "xmlAddNextSibling : cur == elem\n"); +#endif + return(NULL); + } + + xmlUnlinkNode(elem); + + if (elem->type == XML_TEXT_NODE) { + if (cur->type == XML_TEXT_NODE) { + xmlNodeAddContent(cur, elem->content); + xmlFreeNode(elem); + return(cur); + } + if ((cur->next != NULL) && (cur->next->type == XML_TEXT_NODE) && + (cur->name == cur->next->name)) { + xmlChar *tmp; + + tmp = xmlStrdup(elem->content); + tmp = xmlStrcat(tmp, cur->next->content); + xmlNodeSetContent(cur->next, tmp); + xmlFree(tmp); + xmlFreeNode(elem); + return(cur->next); + } + } else if (elem->type == XML_ATTRIBUTE_NODE) { + return xmlAddPropSibling(cur, cur, elem); + } + + if (elem->doc != cur->doc) { + xmlSetTreeDoc(elem, cur->doc); + } + elem->parent = cur->parent; + elem->prev = cur; + elem->next = cur->next; + cur->next = elem; + if (elem->next != NULL) + elem->next->prev = elem; + if ((elem->parent != NULL) && (elem->parent->last == cur)) + elem->parent->last = elem; + return(elem); +} + +#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_HTML_ENABLED) || \ + defined(LIBXML_SCHEMAS_ENABLED) +/** + * xmlAddPrevSibling: + * @cur: the child node + * @elem: the new node + * + * Add a new node @elem as the previous sibling of @cur + * merging adjacent TEXT nodes (@elem may be freed) + * If the new node was already inserted in a document it is + * first unlinked from its existing context. + * If the new node is ATTRIBUTE, it is added into properties instead of children. + * If there is an attribute with equal name, it is first destroyed. + * + * Returns the new node or NULL in case of error. + */ +xmlNodePtr +xmlAddPrevSibling(xmlNodePtr cur, xmlNodePtr elem) { + if (cur == NULL) { +#ifdef DEBUG_TREE + xmlGenericError(xmlGenericErrorContext, + "xmlAddPrevSibling : cur == NULL\n"); +#endif + return(NULL); + } + if (elem == NULL) { +#ifdef DEBUG_TREE + xmlGenericError(xmlGenericErrorContext, + "xmlAddPrevSibling : elem == NULL\n"); +#endif + return(NULL); + } + + if (cur == elem) { +#ifdef DEBUG_TREE + xmlGenericError(xmlGenericErrorContext, + "xmlAddPrevSibling : cur == elem\n"); +#endif + return(NULL); + } + + xmlUnlinkNode(elem); + + if (elem->type == XML_TEXT_NODE) { + if (cur->type == XML_TEXT_NODE) { + xmlChar *tmp; + + tmp = xmlStrdup(elem->content); + tmp = xmlStrcat(tmp, cur->content); + xmlNodeSetContent(cur, tmp); + xmlFree(tmp); + xmlFreeNode(elem); + return(cur); + } + if ((cur->prev != NULL) && (cur->prev->type == XML_TEXT_NODE) && + (cur->name == cur->prev->name)) { + xmlNodeAddContent(cur->prev, elem->content); + xmlFreeNode(elem); + return(cur->prev); + } + } else if (elem->type == XML_ATTRIBUTE_NODE) { + return xmlAddPropSibling(cur->prev, cur, elem); + } + + if (elem->doc != cur->doc) { + xmlSetTreeDoc(elem, cur->doc); + } + elem->parent = cur->parent; + elem->next = cur; + elem->prev = cur->prev; + cur->prev = elem; + if (elem->prev != NULL) + elem->prev->next = elem; + if ((elem->parent != NULL) && (elem->parent->children == cur)) { + elem->parent->children = elem; + } + return(elem); +} +#endif /* LIBXML_TREE_ENABLED */ + +/** + * xmlAddSibling: + * @cur: the child node + * @elem: the new node + * + * Add a new element @elem to the list of siblings of @cur + * merging adjacent TEXT nodes (@elem may be freed) + * If the new element was already inserted in a document it is + * first unlinked from its existing context. + * + * Returns the new element or NULL in case of error. + */ +xmlNodePtr +xmlAddSibling(xmlNodePtr cur, xmlNodePtr elem) { + xmlNodePtr parent; + + if (cur == NULL) { +#ifdef DEBUG_TREE + xmlGenericError(xmlGenericErrorContext, + "xmlAddSibling : cur == NULL\n"); +#endif + return(NULL); + } + + if (elem == NULL) { +#ifdef DEBUG_TREE + xmlGenericError(xmlGenericErrorContext, + "xmlAddSibling : elem == NULL\n"); +#endif + return(NULL); + } + + /* + * Constant time is we can rely on the ->parent->last to find + * the last sibling. + */ + if ((cur->type != XML_ATTRIBUTE_NODE) && (cur->parent != NULL) && + (cur->parent->children != NULL) && + (cur->parent->last != NULL) && + (cur->parent->last->next == NULL)) { + cur = cur->parent->last; + } else { + while (cur->next != NULL) cur = cur->next; + } + + xmlUnlinkNode(elem); + + if ((cur->type == XML_TEXT_NODE) && (elem->type == XML_TEXT_NODE) && + (cur->name == elem->name)) { + xmlNodeAddContent(cur, elem->content); + xmlFreeNode(elem); + return(cur); + } else if (elem->type == XML_ATTRIBUTE_NODE) { + return xmlAddPropSibling(cur, cur, elem); + } + + if (elem->doc != cur->doc) { + xmlSetTreeDoc(elem, cur->doc); + } + parent = cur->parent; + elem->prev = cur; + elem->next = NULL; + elem->parent = parent; + cur->next = elem; + if (parent != NULL) + parent->last = elem; + + return(elem); +} + +/** + * xmlAddChildList: + * @parent: the parent node + * @cur: the first node in the list + * + * Add a list of node at the end of the child list of the parent + * merging adjacent TEXT nodes (@cur may be freed) + * + * Returns the last child or NULL in case of error. + */ +xmlNodePtr +xmlAddChildList(xmlNodePtr parent, xmlNodePtr cur) { + xmlNodePtr prev; + + if (parent == NULL) { +#ifdef DEBUG_TREE + xmlGenericError(xmlGenericErrorContext, + "xmlAddChildList : parent == NULL\n"); +#endif + return(NULL); + } + + if (cur == NULL) { +#ifdef DEBUG_TREE + xmlGenericError(xmlGenericErrorContext, + "xmlAddChildList : child == NULL\n"); +#endif + return(NULL); + } + + if ((cur->doc != NULL) && (parent->doc != NULL) && + (cur->doc != parent->doc)) { +#ifdef DEBUG_TREE + xmlGenericError(xmlGenericErrorContext, + "Elements moved to a different document\n"); +#endif + } + + /* + * add the first element at the end of the children list. + */ + + if (parent->children == NULL) { + parent->children = cur; + } else { + /* + * If cur and parent->last both are TEXT nodes, then merge them. + */ + if ((cur->type == XML_TEXT_NODE) && + (parent->last->type == XML_TEXT_NODE) && + (cur->name == parent->last->name)) { + xmlNodeAddContent(parent->last, cur->content); + /* + * if it's the only child, nothing more to be done. + */ + if (cur->next == NULL) { + xmlFreeNode(cur); + return(parent->last); + } + prev = cur; + cur = cur->next; + xmlFreeNode(prev); + } + prev = parent->last; + prev->next = cur; + cur->prev = prev; + } + while (cur->next != NULL) { + cur->parent = parent; + if (cur->doc != parent->doc) { + xmlSetTreeDoc(cur, parent->doc); + } + cur = cur->next; + } + cur->parent = parent; + cur->doc = parent->doc; /* the parent may not be linked to a doc ! */ + parent->last = cur; + + return(cur); +} + +/** + * xmlAddChild: + * @parent: the parent node + * @cur: the child node + * + * Add a new node to @parent, at the end of the child (or property) list + * merging adjacent TEXT nodes (in which case @cur is freed) + * If the new node is ATTRIBUTE, it is added into properties instead of children. + * If there is an attribute with equal name, it is first destroyed. + * + * Returns the child or NULL in case of error. + */ +xmlNodePtr +xmlAddChild(xmlNodePtr parent, xmlNodePtr cur) { + xmlNodePtr prev; + + if (parent == NULL) { +#ifdef DEBUG_TREE + xmlGenericError(xmlGenericErrorContext, + "xmlAddChild : parent == NULL\n"); +#endif + return(NULL); + } + + if (cur == NULL) { +#ifdef DEBUG_TREE + xmlGenericError(xmlGenericErrorContext, + "xmlAddChild : child == NULL\n"); +#endif + return(NULL); + } + + if (parent == cur) { +#ifdef DEBUG_TREE + xmlGenericError(xmlGenericErrorContext, + "xmlAddChild : parent == cur\n"); +#endif + return(NULL); + } + /* + * If cur is a TEXT node, merge its content with adjacent TEXT nodes + * cur is then freed. + */ + if (cur->type == XML_TEXT_NODE) { + if ((parent->type == XML_TEXT_NODE) && + (parent->content != NULL) && + (parent->name == cur->name)) { + xmlNodeAddContent(parent, cur->content); + xmlFreeNode(cur); + return(parent); + } + if ((parent->last != NULL) && (parent->last->type == XML_TEXT_NODE) && + (parent->last->name == cur->name) && + (parent->last != cur)) { + xmlNodeAddContent(parent->last, cur->content); + xmlFreeNode(cur); + return(parent->last); + } + } + + /* + * add the new element at the end of the children list. + */ + prev = cur->parent; + cur->parent = parent; + if (cur->doc != parent->doc) { + xmlSetTreeDoc(cur, parent->doc); + } + /* this check prevents a loop on tree-traversions if a developer + * tries to add a node to its parent multiple times + */ + if (prev == parent) + return(cur); + + /* + * Coalescing + */ + if ((parent->type == XML_TEXT_NODE) && + (parent->content != NULL) && + (parent != cur)) { + xmlNodeAddContent(parent, cur->content); + xmlFreeNode(cur); + return(parent); + } + if (cur->type == XML_ATTRIBUTE_NODE) { + if (parent->type != XML_ELEMENT_NODE) + return(NULL); + if (parent->properties == NULL) { + parent->properties = (xmlAttrPtr) cur; + } else { + /* check if an attribute with the same name exists */ + xmlAttrPtr lastattr; + + if (cur->ns == NULL) + lastattr = xmlHasNsProp(parent, cur->name, NULL); + else + lastattr = xmlHasNsProp(parent, cur->name, cur->ns->href); + if ((lastattr != NULL) && (lastattr != (xmlAttrPtr) cur) && (lastattr->type != XML_ATTRIBUTE_DECL)) { + /* different instance, destroy it (attributes must be unique) */ + xmlUnlinkNode((xmlNodePtr) lastattr); + xmlFreeProp(lastattr); + } + if (lastattr == (xmlAttrPtr) cur) + return(cur); + /* find the end */ + lastattr = parent->properties; + while (lastattr->next != NULL) { + lastattr = lastattr->next; + } + lastattr->next = (xmlAttrPtr) cur; + ((xmlAttrPtr) cur)->prev = lastattr; + } + } else { + if (parent->children == NULL) { + parent->children = cur; + parent->last = cur; + } else { + prev = parent->last; + prev->next = cur; + cur->prev = prev; + parent->last = cur; + } + } + return(cur); +} + +/** + * xmlGetLastChild: + * @parent: the parent node + * + * Search the last child of a node. + * Returns the last child or NULL if none. + */ +xmlNodePtr +xmlGetLastChild(xmlNodePtr parent) { + if (parent == NULL) { +#ifdef DEBUG_TREE + xmlGenericError(xmlGenericErrorContext, + "xmlGetLastChild : parent == NULL\n"); +#endif + return(NULL); + } + return(parent->last); +} + +/** + * xmlFreeNodeList: + * @cur: the first node in the list + * + * Free a node and all its siblings, this is a recursive behaviour, all + * the children are freed too. + */ +void +xmlFreeNodeList(xmlNodePtr cur) { + xmlNodePtr next; + xmlDictPtr dict = NULL; + + if (cur == NULL) return; + if (cur->type == XML_NAMESPACE_DECL) { + xmlFreeNsList((xmlNsPtr) cur); + return; + } + if ((cur->type == XML_DOCUMENT_NODE) || +#ifdef LIBXML_DOCB_ENABLED + (cur->type == XML_DOCB_DOCUMENT_NODE) || +#endif + (cur->type == XML_HTML_DOCUMENT_NODE)) { + xmlFreeDoc((xmlDocPtr) cur); + return; + } + if (cur->doc != NULL) dict = cur->doc->dict; + while (cur != NULL) { + next = cur->next; + if (cur->type != XML_DTD_NODE) { + + if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue)) + xmlDeregisterNodeDefaultValue(cur); + + if ((cur->children != NULL) && + (cur->type != XML_ENTITY_REF_NODE)) + xmlFreeNodeList(cur->children); + if (((cur->type == XML_ELEMENT_NODE) || + (cur->type == XML_XINCLUDE_START) || + (cur->type == XML_XINCLUDE_END)) && + (cur->properties != NULL)) + xmlFreePropList(cur->properties); + if ((cur->type != XML_ELEMENT_NODE) && + (cur->type != XML_XINCLUDE_START) && + (cur->type != XML_XINCLUDE_END) && + (cur->type != XML_ENTITY_REF_NODE) && + (cur->content != (xmlChar *) &(cur->properties))) { + DICT_FREE(cur->content) + } + if (((cur->type == XML_ELEMENT_NODE) || + (cur->type == XML_XINCLUDE_START) || + (cur->type == XML_XINCLUDE_END)) && + (cur->nsDef != NULL)) + xmlFreeNsList(cur->nsDef); + + /* + * When a node is a text node or a comment, it uses a global static + * variable for the name of the node. + * Otherwise the node name might come from the document's + * dictionnary + */ + if ((cur->name != NULL) && + (cur->type != XML_TEXT_NODE) && + (cur->type != XML_COMMENT_NODE)) + DICT_FREE(cur->name) + xmlFree(cur); + } + cur = next; + } +} + +/** + * xmlFreeNode: + * @cur: the node + * + * Free a node, this is a recursive behaviour, all the children are freed too. + * This doesn't unlink the child from the list, use xmlUnlinkNode() first. + */ +void +xmlFreeNode(xmlNodePtr cur) { + xmlDictPtr dict = NULL; + + if (cur == NULL) return; + + /* use xmlFreeDtd for DTD nodes */ + if (cur->type == XML_DTD_NODE) { + xmlFreeDtd((xmlDtdPtr) cur); + return; + } + if (cur->type == XML_NAMESPACE_DECL) { + xmlFreeNs((xmlNsPtr) cur); + return; + } + if (cur->type == XML_ATTRIBUTE_NODE) { + xmlFreeProp((xmlAttrPtr) cur); + return; + } + + if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue)) + xmlDeregisterNodeDefaultValue(cur); + + if (cur->doc != NULL) dict = cur->doc->dict; + + if ((cur->children != NULL) && + (cur->type != XML_ENTITY_REF_NODE)) + xmlFreeNodeList(cur->children); + if (((cur->type == XML_ELEMENT_NODE) || + (cur->type == XML_XINCLUDE_START) || + (cur->type == XML_XINCLUDE_END)) && + (cur->properties != NULL)) + xmlFreePropList(cur->properties); + if ((cur->type != XML_ELEMENT_NODE) && + (cur->content != NULL) && + (cur->type != XML_ENTITY_REF_NODE) && + (cur->type != XML_XINCLUDE_END) && + (cur->type != XML_XINCLUDE_START) && + (cur->content != (xmlChar *) &(cur->properties))) { + DICT_FREE(cur->content) + } + + /* + * When a node is a text node or a comment, it uses a global static + * variable for the name of the node. + * Otherwise the node name might come from the document's dictionnary + */ + if ((cur->name != NULL) && + (cur->type != XML_TEXT_NODE) && + (cur->type != XML_COMMENT_NODE)) + DICT_FREE(cur->name) + + if (((cur->type == XML_ELEMENT_NODE) || + (cur->type == XML_XINCLUDE_START) || + (cur->type == XML_XINCLUDE_END)) && + (cur->nsDef != NULL)) + xmlFreeNsList(cur->nsDef); + xmlFree(cur); +} + +/** + * xmlUnlinkNode: + * @cur: the node + * + * Unlink a node from it's current context, the node is not freed + */ +void +xmlUnlinkNode(xmlNodePtr cur) { + if (cur == NULL) { +#ifdef DEBUG_TREE + xmlGenericError(xmlGenericErrorContext, + "xmlUnlinkNode : node == NULL\n"); +#endif + return; + } + if (cur->type == XML_DTD_NODE) { + xmlDocPtr doc; + doc = cur->doc; + if (doc != NULL) { + if (doc->intSubset == (xmlDtdPtr) cur) + doc->intSubset = NULL; + if (doc->extSubset == (xmlDtdPtr) cur) + doc->extSubset = NULL; + } + } + if (cur->parent != NULL) { + xmlNodePtr parent; + parent = cur->parent; + if (cur->type == XML_ATTRIBUTE_NODE) { + if (parent->properties == (xmlAttrPtr) cur) + parent->properties = ((xmlAttrPtr) cur)->next; + } else { + if (parent->children == cur) + parent->children = cur->next; + if (parent->last == cur) + parent->last = cur->prev; + } + cur->parent = NULL; + } + if (cur->next != NULL) + cur->next->prev = cur->prev; + if (cur->prev != NULL) + cur->prev->next = cur->next; + cur->next = cur->prev = NULL; +} + +#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_WRITER_ENABLED) +/** + * xmlReplaceNode: + * @old: the old node + * @cur: the node + * + * Unlink the old node from its current context, prune the new one + * at the same place. If @cur was already inserted in a document it is + * first unlinked from its existing context. + * + * Returns the @old node + */ +xmlNodePtr +xmlReplaceNode(xmlNodePtr old, xmlNodePtr cur) { + if (old == cur) return(NULL); + if ((old == NULL) || (old->parent == NULL)) { +#ifdef DEBUG_TREE + xmlGenericError(xmlGenericErrorContext, + "xmlReplaceNode : old == NULL or without parent\n"); +#endif + return(NULL); + } + if (cur == NULL) { + xmlUnlinkNode(old); + return(old); + } + if (cur == old) { + return(old); + } + if ((old->type==XML_ATTRIBUTE_NODE) && (cur->type!=XML_ATTRIBUTE_NODE)) { +#ifdef DEBUG_TREE + xmlGenericError(xmlGenericErrorContext, + "xmlReplaceNode : Trying to replace attribute node with other node type\n"); +#endif + return(old); + } + if ((cur->type==XML_ATTRIBUTE_NODE) && (old->type!=XML_ATTRIBUTE_NODE)) { +#ifdef DEBUG_TREE + xmlGenericError(xmlGenericErrorContext, + "xmlReplaceNode : Trying to replace a non-attribute node with attribute node\n"); +#endif + return(old); + } + xmlUnlinkNode(cur); + xmlSetTreeDoc(cur, old->doc); + cur->parent = old->parent; + cur->next = old->next; + if (cur->next != NULL) + cur->next->prev = cur; + cur->prev = old->prev; + if (cur->prev != NULL) + cur->prev->next = cur; + if (cur->parent != NULL) { + if (cur->type == XML_ATTRIBUTE_NODE) { + if (cur->parent->properties == (xmlAttrPtr)old) + cur->parent->properties = ((xmlAttrPtr) cur); + } else { + if (cur->parent->children == old) + cur->parent->children = cur; + if (cur->parent->last == old) + cur->parent->last = cur; + } + } + old->next = old->prev = NULL; + old->parent = NULL; + return(old); +} +#endif /* LIBXML_TREE_ENABLED */ + +/************************************************************************ + * * + * Copy operations * + * * + ************************************************************************/ + +/** + * xmlCopyNamespace: + * @cur: the namespace + * + * Do a copy of the namespace. + * + * Returns: a new #xmlNsPtr, or NULL in case of error. + */ +xmlNsPtr +xmlCopyNamespace(xmlNsPtr cur) { + xmlNsPtr ret; + + if (cur == NULL) return(NULL); + switch (cur->type) { + case XML_LOCAL_NAMESPACE: + ret = xmlNewNs(NULL, cur->href, cur->prefix); + break; + default: +#ifdef DEBUG_TREE + xmlGenericError(xmlGenericErrorContext, + "xmlCopyNamespace: invalid type %d\n", cur->type); +#endif + return(NULL); + } + return(ret); +} + +/** + * xmlCopyNamespaceList: + * @cur: the first namespace + * + * Do a copy of an namespace list. + * + * Returns: a new #xmlNsPtr, or NULL in case of error. + */ +xmlNsPtr +xmlCopyNamespaceList(xmlNsPtr cur) { + xmlNsPtr ret = NULL; + xmlNsPtr p = NULL,q; + + while (cur != NULL) { + q = xmlCopyNamespace(cur); + if (p == NULL) { + ret = p = q; + } else { + p->next = q; + p = q; + } + cur = cur->next; + } + return(ret); +} + +static xmlNodePtr +xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent); + +static xmlAttrPtr +xmlCopyPropInternal(xmlDocPtr doc, xmlNodePtr target, xmlAttrPtr cur) { + xmlAttrPtr ret; + + if (cur == NULL) return(NULL); + if (target != NULL) + ret = xmlNewDocProp(target->doc, cur->name, NULL); + else if (doc != NULL) + ret = xmlNewDocProp(doc, cur->name, NULL); + else if (cur->parent != NULL) + ret = xmlNewDocProp(cur->parent->doc, cur->name, NULL); + else if (cur->children != NULL) + ret = xmlNewDocProp(cur->children->doc, cur->name, NULL); + else + ret = xmlNewDocProp(NULL, cur->name, NULL); + if (ret == NULL) return(NULL); + ret->parent = target; + + if ((cur->ns != NULL) && (target != NULL)) { + xmlNsPtr ns; + + ns = xmlSearchNs(target->doc, target, cur->ns->prefix); + if (ns == NULL) { + /* + * Humm, we are copying an element whose namespace is defined + * out of the new tree scope. Search it in the original tree + * and add it at the top of the new tree + */ + ns = xmlSearchNs(cur->doc, cur->parent, cur->ns->prefix); + if (ns != NULL) { + xmlNodePtr root = target; + xmlNodePtr pred = NULL; + + while (root->parent != NULL) { + pred = root; + root = root->parent; + } + if (root == (xmlNodePtr) target->doc) { + /* correct possibly cycling above the document elt */ + root = pred; + } + ret->ns = xmlNewNs(root, ns->href, ns->prefix); + } + } else { + /* + * we have to find something appropriate here since + * we cant be sure, that the namespce we found is identified + * by the prefix + */ + if (xmlStrEqual(ns->href, cur->ns->href)) { + /* this is the nice case */ + ret->ns = ns; + } else { + /* + * we are in trouble: we need a new reconcilied namespace. + * This is expensive + */ + ret->ns = xmlNewReconciliedNs(target->doc, target, cur->ns); + } + } + + } else + ret->ns = NULL; + + if (cur->children != NULL) { + xmlNodePtr tmp; + + ret->children = xmlStaticCopyNodeList(cur->children, ret->doc, (xmlNodePtr) ret); + ret->last = NULL; + tmp = ret->children; + while (tmp != NULL) { + /* tmp->parent = (xmlNodePtr)ret; */ + if (tmp->next == NULL) + ret->last = tmp; + tmp = tmp->next; + } + } + /* + * Try to handle IDs + */ + if ((target!= NULL) && (cur!= NULL) && + (target->doc != NULL) && (cur->doc != NULL) && + (cur->doc->ids != NULL) && (cur->parent != NULL)) { + if (xmlIsID(cur->doc, cur->parent, cur)) { + xmlChar *id; + + id = xmlNodeListGetString(cur->doc, cur->children, 1); + if (id != NULL) { + xmlAddID(NULL, target->doc, id, ret); + xmlFree(id); + } + } + } + return(ret); +} + +/** + * xmlCopyProp: + * @target: the element where the attribute will be grafted + * @cur: the attribute + * + * Do a copy of the attribute. + * + * Returns: a new #xmlAttrPtr, or NULL in case of error. + */ +xmlAttrPtr +xmlCopyProp(xmlNodePtr target, xmlAttrPtr cur) { + return xmlCopyPropInternal(NULL, target, cur); +} + +/** + * xmlCopyPropList: + * @target: the element where the attributes will be grafted + * @cur: the first attribute + * + * Do a copy of an attribute list. + * + * Returns: a new #xmlAttrPtr, or NULL in case of error. + */ +xmlAttrPtr +xmlCopyPropList(xmlNodePtr target, xmlAttrPtr cur) { + xmlAttrPtr ret = NULL; + xmlAttrPtr p = NULL,q; + + while (cur != NULL) { + q = xmlCopyProp(target, cur); + if (q == NULL) + return(NULL); + if (p == NULL) { + ret = p = q; + } else { + p->next = q; + q->prev = p; + p = q; + } + cur = cur->next; + } + return(ret); +} + +/* + * NOTE about the CopyNode operations ! + * + * They are split into external and internal parts for one + * tricky reason: namespaces. Doing a direct copy of a node + * say RPM:Copyright without changing the namespace pointer to + * something else can produce stale links. One way to do it is + * to keep a reference counter but this doesn't work as soon + * as one move the element or the subtree out of the scope of + * the existing namespace. The actual solution seems to add + * a copy of the namespace at the top of the copied tree if + * not available in the subtree. + * Hence two functions, the public front-end call the inner ones + * The argument "recursive" normally indicates a recursive copy + * of the node with values 0 (no) and 1 (yes). For XInclude, + * however, we allow a value of 2 to indicate copy properties and + * namespace info, but don't recurse on children. + */ + +static xmlNodePtr +xmlStaticCopyNode(const xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent, + int extended) { + xmlNodePtr ret; + + if (node == NULL) return(NULL); + switch (node->type) { + case XML_TEXT_NODE: + case XML_CDATA_SECTION_NODE: + case XML_ELEMENT_NODE: + case XML_DOCUMENT_FRAG_NODE: + case XML_ENTITY_REF_NODE: + case XML_ENTITY_NODE: + case XML_PI_NODE: + case XML_COMMENT_NODE: + case XML_XINCLUDE_START: + case XML_XINCLUDE_END: + break; + case XML_ATTRIBUTE_NODE: + return((xmlNodePtr) xmlCopyPropInternal(doc, parent, (xmlAttrPtr) node)); + case XML_NAMESPACE_DECL: + return((xmlNodePtr) xmlCopyNamespaceList((xmlNsPtr) node)); + + case XML_DOCUMENT_NODE: + case XML_HTML_DOCUMENT_NODE: +#ifdef LIBXML_DOCB_ENABLED + case XML_DOCB_DOCUMENT_NODE: +#endif +#ifdef LIBXML_TREE_ENABLED + return((xmlNodePtr) xmlCopyDoc((xmlDocPtr) node, extended)); +#endif /* LIBXML_TREE_ENABLED */ + case XML_DOCUMENT_TYPE_NODE: + case XML_NOTATION_NODE: + case XML_DTD_NODE: + case XML_ELEMENT_DECL: + case XML_ATTRIBUTE_DECL: + case XML_ENTITY_DECL: + return(NULL); + } + + /* + * Allocate a new node and fill the fields. + */ + ret = (xmlNodePtr) xmlMalloc(sizeof(xmlNode)); + if (ret == NULL) { + xmlTreeErrMemory("copying node"); + return(NULL); + } + memset(ret, 0, sizeof(xmlNode)); + ret->type = node->type; + + ret->doc = doc; + ret->parent = parent; + if (node->name == xmlStringText) + ret->name = xmlStringText; + else if (node->name == xmlStringTextNoenc) + ret->name = xmlStringTextNoenc; + else if (node->name == xmlStringComment) + ret->name = xmlStringComment; + else if (node->name != NULL) { + if ((doc != NULL) && (doc->dict != NULL)) + ret->name = xmlDictLookup(doc->dict, node->name, -1); + else + ret->name = xmlStrdup(node->name); + } + if ((node->type != XML_ELEMENT_NODE) && + (node->content != NULL) && + (node->type != XML_ENTITY_REF_NODE) && + (node->type != XML_XINCLUDE_END) && + (node->type != XML_XINCLUDE_START)) { + ret->content = xmlStrdup(node->content); + }else{ + if (node->type == XML_ELEMENT_NODE) + ret->line = node->line; + } + if (parent != NULL) { + xmlNodePtr tmp; + + /* + * this is a tricky part for the node register thing: + * in case ret does get coalesced in xmlAddChild + * the deregister-node callback is called; so we register ret now already + */ + if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)) + xmlRegisterNodeDefaultValue((xmlNodePtr)ret); + + tmp = xmlAddChild(parent, ret); + /* node could have coalesced */ + if (tmp != ret) + return(tmp); + } + + if (!extended) + goto out; + if ((node->type == XML_ELEMENT_NODE) && (node->nsDef != NULL)) + ret->nsDef = xmlCopyNamespaceList(node->nsDef); + + if (node->ns != NULL) { + xmlNsPtr ns; + + ns = xmlSearchNs(doc, ret, node->ns->prefix); + if (ns == NULL) { + /* + * Humm, we are copying an element whose namespace is defined + * out of the new tree scope. Search it in the original tree + * and add it at the top of the new tree + */ + ns = xmlSearchNs(node->doc, node, node->ns->prefix); + if (ns != NULL) { + xmlNodePtr root = ret; + + while (root->parent != NULL) root = root->parent; + ret->ns = xmlNewNs(root, ns->href, ns->prefix); + } + } else { + /* + * reference the existing namespace definition in our own tree. + */ + ret->ns = ns; + } + } + if ((node->type == XML_ELEMENT_NODE) && (node->properties != NULL)) + ret->properties = xmlCopyPropList(ret, node->properties); + if (node->type == XML_ENTITY_REF_NODE) { + if ((doc == NULL) || (node->doc != doc)) { + /* + * The copied node will go into a separate document, so + * to avoid dangling references to the ENTITY_DECL node + * we cannot keep the reference. Try to find it in the + * target document. + */ + ret->children = (xmlNodePtr) xmlGetDocEntity(doc, ret->name); + } else { + ret->children = node->children; + } + ret->last = ret->children; + } else if ((node->children != NULL) && (extended != 2)) { + ret->children = xmlStaticCopyNodeList(node->children, doc, ret); + UPDATE_LAST_CHILD_AND_PARENT(ret) + } + +out: + /* if parent != NULL we already registered the node above */ + if ((parent == NULL) && + ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))) + xmlRegisterNodeDefaultValue((xmlNodePtr)ret); + return(ret); +} + +static xmlNodePtr +xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent) { + xmlNodePtr ret = NULL; + xmlNodePtr p = NULL,q; + + while (node != NULL) { +#ifdef LIBXML_TREE_ENABLED + if (node->type == XML_DTD_NODE ) { + if (doc == NULL) { + node = node->next; + continue; + } + if (doc->intSubset == NULL) { + q = (xmlNodePtr) xmlCopyDtd( (xmlDtdPtr) node ); + q->doc = doc; + q->parent = parent; + doc->intSubset = (xmlDtdPtr) q; + xmlAddChild(parent, q); + } else { + q = (xmlNodePtr) doc->intSubset; + xmlAddChild(parent, q); + } + } else +#endif /* LIBXML_TREE_ENABLED */ + q = xmlStaticCopyNode(node, doc, parent, 1); + if (ret == NULL) { + q->prev = NULL; + ret = p = q; + } else if (p != q) { + /* the test is required if xmlStaticCopyNode coalesced 2 text nodes */ + p->next = q; + q->prev = p; + p = q; + } + node = node->next; + } + return(ret); +} + +/** + * xmlCopyNode: + * @node: the node + * @extended: if 1 do a recursive copy (properties, namespaces and children + * when applicable) + * if 2 copy properties and namespaces (when applicable) + * + * Do a copy of the node. + * + * Returns: a new #xmlNodePtr, or NULL in case of error. + */ +xmlNodePtr +xmlCopyNode(const xmlNodePtr node, int extended) { + xmlNodePtr ret; + + ret = xmlStaticCopyNode(node, NULL, NULL, extended); + return(ret); +} + +/** + * xmlDocCopyNode: + * @node: the node + * @doc: the document + * @extended: if 1 do a recursive copy (properties, namespaces and children + * when applicable) + * if 2 copy properties and namespaces (when applicable) + * + * Do a copy of the node to a given document. + * + * Returns: a new #xmlNodePtr, or NULL in case of error. + */ +xmlNodePtr +xmlDocCopyNode(const xmlNodePtr node, xmlDocPtr doc, int extended) { + xmlNodePtr ret; + + ret = xmlStaticCopyNode(node, doc, NULL, extended); + return(ret); +} + +/** + * xmlDocCopyNodeList: + * @doc: the target document + * @node: the first node in the list. + * + * Do a recursive copy of the node list. + * + * Returns: a new #xmlNodePtr, or NULL in case of error. + */ +xmlNodePtr xmlDocCopyNodeList(xmlDocPtr doc, const xmlNodePtr node) { + xmlNodePtr ret = xmlStaticCopyNodeList(node, doc, NULL); + return(ret); +} + +/** + * xmlCopyNodeList: + * @node: the first node in the list. + * + * Do a recursive copy of the node list. + * Use xmlDocCopyNodeList() if possible to ensure string interning. + * + * Returns: a new #xmlNodePtr, or NULL in case of error. + */ +xmlNodePtr xmlCopyNodeList(const xmlNodePtr node) { + xmlNodePtr ret = xmlStaticCopyNodeList(node, NULL, NULL); + return(ret); +} + +#if defined(LIBXML_TREE_ENABLED) +/** + * xmlCopyDtd: + * @dtd: the dtd + * + * Do a copy of the dtd. + * + * Returns: a new #xmlDtdPtr, or NULL in case of error. + */ +xmlDtdPtr +xmlCopyDtd(xmlDtdPtr dtd) { + xmlDtdPtr ret; + xmlNodePtr cur, p = NULL, q; + + if (dtd == NULL) return(NULL); + ret = xmlNewDtd(NULL, dtd->name, dtd->ExternalID, dtd->SystemID); + if (ret == NULL) return(NULL); + if (dtd->entities != NULL) + ret->entities = (void *) xmlCopyEntitiesTable( + (xmlEntitiesTablePtr) dtd->entities); + if (dtd->notations != NULL) + ret->notations = (void *) xmlCopyNotationTable( + (xmlNotationTablePtr) dtd->notations); + if (dtd->elements != NULL) + ret->elements = (void *) xmlCopyElementTable( + (xmlElementTablePtr) dtd->elements); + if (dtd->attributes != NULL) + ret->attributes = (void *) xmlCopyAttributeTable( + (xmlAttributeTablePtr) dtd->attributes); + if (dtd->pentities != NULL) + ret->pentities = (void *) xmlCopyEntitiesTable( + (xmlEntitiesTablePtr) dtd->pentities); + + cur = dtd->children; + while (cur != NULL) { + q = NULL; + + if (cur->type == XML_ENTITY_DECL) { + xmlEntityPtr tmp = (xmlEntityPtr) cur; + switch (tmp->etype) { + case XML_INTERNAL_GENERAL_ENTITY: + case XML_EXTERNAL_GENERAL_PARSED_ENTITY: + case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY: + q = (xmlNodePtr) xmlGetEntityFromDtd(ret, tmp->name); + break; + case XML_INTERNAL_PARAMETER_ENTITY: + case XML_EXTERNAL_PARAMETER_ENTITY: + q = (xmlNodePtr) + xmlGetParameterEntityFromDtd(ret, tmp->name); + break; + case XML_INTERNAL_PREDEFINED_ENTITY: + break; + } + } else if (cur->type == XML_ELEMENT_DECL) { + xmlElementPtr tmp = (xmlElementPtr) cur; + q = (xmlNodePtr) + xmlGetDtdQElementDesc(ret, tmp->name, tmp->prefix); + } else if (cur->type == XML_ATTRIBUTE_DECL) { + xmlAttributePtr tmp = (xmlAttributePtr) cur; + q = (xmlNodePtr) + xmlGetDtdQAttrDesc(ret, tmp->elem, tmp->name, tmp->prefix); + } else if (cur->type == XML_COMMENT_NODE) { + q = xmlCopyNode(cur, 0); + } + + if (q == NULL) { + cur = cur->next; + continue; + } + + if (p == NULL) + ret->children = q; + else + p->next = q; + + q->prev = p; + q->parent = (xmlNodePtr) ret; + q->next = NULL; + ret->last = q; + p = q; + cur = cur->next; + } + + return(ret); +} +#endif + +#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) +/** + * xmlCopyDoc: + * @doc: the document + * @recursive: if not zero do a recursive copy. + * + * Do a copy of the document info. If recursive, the content tree will + * be copied too as well as DTD, namespaces and entities. + * + * Returns: a new #xmlDocPtr, or NULL in case of error. + */ +xmlDocPtr +xmlCopyDoc(xmlDocPtr doc, int recursive) { + xmlDocPtr ret; + + if (doc == NULL) return(NULL); + ret = xmlNewDoc(doc->version); + if (ret == NULL) return(NULL); + if (doc->name != NULL) + ret->name = xmlMemStrdup(doc->name); + if (doc->encoding != NULL) + ret->encoding = xmlStrdup(doc->encoding); + if (doc->URL != NULL) + ret->URL = xmlStrdup(doc->URL); + ret->charset = doc->charset; + ret->compression = doc->compression; + ret->standalone = doc->standalone; + if (!recursive) return(ret); + + ret->last = NULL; + ret->children = NULL; +#ifdef LIBXML_TREE_ENABLED + if (doc->intSubset != NULL) { + ret->intSubset = xmlCopyDtd(doc->intSubset); + xmlSetTreeDoc((xmlNodePtr)ret->intSubset, ret); + ret->intSubset->parent = ret; + } +#endif + if (doc->oldNs != NULL) + ret->oldNs = xmlCopyNamespaceList(doc->oldNs); + if (doc->children != NULL) { + xmlNodePtr tmp; + + ret->children = xmlStaticCopyNodeList(doc->children, ret, + (xmlNodePtr)ret); + ret->last = NULL; + tmp = ret->children; + while (tmp != NULL) { + if (tmp->next == NULL) + ret->last = tmp; + tmp = tmp->next; + } + } + return(ret); +} +#endif /* LIBXML_TREE_ENABLED */ + +/************************************************************************ + * * + * Content access functions * + * * + ************************************************************************/ + +/** + * xmlGetLineNo: + * @node: valid node + * + * Get line number of @node. This requires activation of this option + * before invoking the parser by calling xmlLineNumbersDefault(1) + * + * Returns the line number if successful, -1 otherwise + */ +long +xmlGetLineNo(xmlNodePtr node) +{ + long result = -1; + + if (!node) + return result; + if ((node->type == XML_ELEMENT_NODE) || + (node->type == XML_TEXT_NODE) || + (node->type == XML_COMMENT_NODE) || + (node->type == XML_PI_NODE)) + result = (long) node->line; + else if ((node->prev != NULL) && + ((node->prev->type == XML_ELEMENT_NODE) || + (node->prev->type == XML_TEXT_NODE) || + (node->prev->type == XML_COMMENT_NODE) || + (node->prev->type == XML_PI_NODE))) + result = xmlGetLineNo(node->prev); + else if ((node->parent != NULL) && + (node->parent->type == XML_ELEMENT_NODE)) + result = xmlGetLineNo(node->parent); + + return result; +} + +#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_DEBUG_ENABLED) +/** + * xmlGetNodePath: + * @node: a node + * + * Build a structure based Path for the given node + * + * Returns the new path or NULL in case of error. The caller must free + * the returned string + */ +xmlChar * +xmlGetNodePath(xmlNodePtr node) +{ + xmlNodePtr cur, tmp, next; + xmlChar *buffer = NULL, *temp; + size_t buf_len; + xmlChar *buf; + const char *sep; + const char *name; + char nametemp[100]; + int occur = 0, generic; + + if (node == NULL) + return (NULL); + + buf_len = 500; + buffer = (xmlChar *) xmlMallocAtomic(buf_len * sizeof(xmlChar)); + if (buffer == NULL) { + xmlTreeErrMemory("getting node path"); + return (NULL); + } + buf = (xmlChar *) xmlMallocAtomic(buf_len * sizeof(xmlChar)); + if (buf == NULL) { + xmlTreeErrMemory("getting node path"); + xmlFree(buffer); + return (NULL); + } + + buffer[0] = 0; + cur = node; + do { + name = ""; + sep = "?"; + occur = 0; + if ((cur->type == XML_DOCUMENT_NODE) || + (cur->type == XML_HTML_DOCUMENT_NODE)) { + if (buffer[0] == '/') + break; + sep = "/"; + next = NULL; + } else if (cur->type == XML_ELEMENT_NODE) { + generic = 0; + sep = "/"; + name = (const char *) cur->name; + if (cur->ns) { + if (cur->ns->prefix != NULL) { + snprintf(nametemp, sizeof(nametemp) - 1, "%s:%s", + (char *)cur->ns->prefix, (char *)cur->name); + nametemp[sizeof(nametemp) - 1] = 0; + name = nametemp; + } else { + /* + * We cannot express named elements in the default + * namespace, so use "*". + */ + generic = 1; + name = "*"; + } + } + next = cur->parent; + + /* + * Thumbler index computation + * TODO: the ocurence test seems bogus for namespaced names + */ + tmp = cur->prev; + while (tmp != NULL) { + if ((tmp->type == XML_ELEMENT_NODE) && + (generic || + (xmlStrEqual(cur->name, tmp->name) && + ((tmp->ns == cur->ns) || + ((tmp->ns != NULL) && (cur->ns != NULL) && + (xmlStrEqual(cur->ns->prefix, tmp->ns->prefix))))))) + occur++; + tmp = tmp->prev; + } + if (occur == 0) { + tmp = cur->next; + while (tmp != NULL && occur == 0) { + if ((tmp->type == XML_ELEMENT_NODE) && + (generic || + (xmlStrEqual(cur->name, tmp->name) && + ((tmp->ns == cur->ns) || + ((tmp->ns != NULL) && (cur->ns != NULL) && + (xmlStrEqual(cur->ns->prefix, tmp->ns->prefix))))))) + occur++; + tmp = tmp->next; + } + if (occur != 0) + occur = 1; + } else + occur++; + } else if (cur->type == XML_COMMENT_NODE) { + sep = "/"; + name = "comment()"; + next = cur->parent; + + /* + * Thumbler index computation + */ + tmp = cur->prev; + while (tmp != NULL) { + if (tmp->type == XML_COMMENT_NODE) + occur++; + tmp = tmp->prev; + } + if (occur == 0) { + tmp = cur->next; + while (tmp != NULL && occur == 0) { + if (tmp->type == XML_COMMENT_NODE) + occur++; + tmp = tmp->next; + } + if (occur != 0) + occur = 1; + } else + occur++; + } else if ((cur->type == XML_TEXT_NODE) || + (cur->type == XML_CDATA_SECTION_NODE)) { + sep = "/"; + name = "text()"; + next = cur->parent; + + /* + * Thumbler index computation + */ + tmp = cur->prev; + while (tmp != NULL) { + if ((tmp->type == XML_TEXT_NODE) || + (tmp->type == XML_CDATA_SECTION_NODE)) + occur++; + tmp = tmp->prev; + } + /* + * Evaluate if this is the only text- or CDATA-section-node; + * if yes, then we'll get "text()", otherwise "text()[1]". + */ + if (occur == 0) { + tmp = cur->next; + while (tmp != NULL) { + if ((tmp->type == XML_TEXT_NODE) || + (tmp->type == XML_CDATA_SECTION_NODE)) + { + occur = 1; + break; + } + tmp = tmp->next; + } + } else + occur++; + } else if (cur->type == XML_PI_NODE) { + sep = "/"; + snprintf(nametemp, sizeof(nametemp) - 1, + "processing-instruction('%s')", (char *)cur->name); + nametemp[sizeof(nametemp) - 1] = 0; + name = nametemp; + + next = cur->parent; + + /* + * Thumbler index computation + */ + tmp = cur->prev; + while (tmp != NULL) { + if ((tmp->type == XML_PI_NODE) && + (xmlStrEqual(cur->name, tmp->name))) + occur++; + tmp = tmp->prev; + } + if (occur == 0) { + tmp = cur->next; + while (tmp != NULL && occur == 0) { + if ((tmp->type == XML_PI_NODE) && + (xmlStrEqual(cur->name, tmp->name))) + occur++; + tmp = tmp->next; + } + if (occur != 0) + occur = 1; + } else + occur++; + + } else if (cur->type == XML_ATTRIBUTE_NODE) { + sep = "/@"; + name = (const char *) (((xmlAttrPtr) cur)->name); + if (cur->ns) { + if (cur->ns->prefix != NULL) + snprintf(nametemp, sizeof(nametemp) - 1, "%s:%s", + (char *)cur->ns->prefix, (char *)cur->name); + else + snprintf(nametemp, sizeof(nametemp) - 1, "%s", + (char *)cur->name); + nametemp[sizeof(nametemp) - 1] = 0; + name = nametemp; + } + next = ((xmlAttrPtr) cur)->parent; + } else { + next = cur->parent; + } + + /* + * Make sure there is enough room + */ + if (xmlStrlen(buffer) + sizeof(nametemp) + 20 > buf_len) { + buf_len = + 2 * buf_len + xmlStrlen(buffer) + sizeof(nametemp) + 20; + temp = (xmlChar *) xmlRealloc(buffer, buf_len); + if (temp == NULL) { + xmlTreeErrMemory("getting node path"); + xmlFree(buf); + xmlFree(buffer); + return (NULL); + } + buffer = temp; + temp = (xmlChar *) xmlRealloc(buf, buf_len); + if (temp == NULL) { + xmlTreeErrMemory("getting node path"); + xmlFree(buf); + xmlFree(buffer); + return (NULL); + } + buf = temp; + } + if (occur == 0) + snprintf((char *) buf, buf_len, "%s%s%s", + sep, name, (char *) buffer); + else + snprintf((char *) buf, buf_len, "%s%s[%d]%s", + sep, name, occur, (char *) buffer); + snprintf((char *) buffer, buf_len, "%s", (char *)buf); + cur = next; + } while (cur != NULL); + xmlFree(buf); + return (buffer); +} +#endif /* LIBXML_TREE_ENABLED */ + +/** + * xmlDocGetRootElement: + * @doc: the document + * + * Get the root element of the document (doc->children is a list + * containing possibly comments, PIs, etc ...). + * + * Returns the #xmlNodePtr for the root or NULL + */ +xmlNodePtr +xmlDocGetRootElement(xmlDocPtr doc) { + xmlNodePtr ret; + + if (doc == NULL) return(NULL); + ret = doc->children; + while (ret != NULL) { + if (ret->type == XML_ELEMENT_NODE) + return(ret); + ret = ret->next; + } + return(ret); +} + +#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_WRITER_ENABLED) +/** + * xmlDocSetRootElement: + * @doc: the document + * @root: the new document root element, if root is NULL no action is taken, + * to remove a node from a document use xmlUnlinkNode(root) instead. + * + * Set the root element of the document (doc->children is a list + * containing possibly comments, PIs, etc ...). + * + * Returns the old root element if any was found, NULL if root was NULL + */ +xmlNodePtr +xmlDocSetRootElement(xmlDocPtr doc, xmlNodePtr root) { + xmlNodePtr old = NULL; + + if (doc == NULL) return(NULL); + if (root == NULL) + return(NULL); + xmlUnlinkNode(root); + xmlSetTreeDoc(root, doc); + root->parent = (xmlNodePtr) doc; + old = doc->children; + while (old != NULL) { + if (old->type == XML_ELEMENT_NODE) + break; + old = old->next; + } + if (old == NULL) { + if (doc->children == NULL) { + doc->children = root; + doc->last = root; + } else { + xmlAddSibling(doc->children, root); + } + } else { + xmlReplaceNode(old, root); + } + return(old); +} +#endif + +#if defined(LIBXML_TREE_ENABLED) +/** + * xmlNodeSetLang: + * @cur: the node being changed + * @lang: the language description + * + * Set the language of a node, i.e. the values of the xml:lang + * attribute. + */ +void +xmlNodeSetLang(xmlNodePtr cur, const xmlChar *lang) { + xmlNsPtr ns; + + if (cur == NULL) return; + switch(cur->type) { + case XML_TEXT_NODE: + case XML_CDATA_SECTION_NODE: + case XML_COMMENT_NODE: + case XML_DOCUMENT_NODE: + case XML_DOCUMENT_TYPE_NODE: + case XML_DOCUMENT_FRAG_NODE: + case XML_NOTATION_NODE: + case XML_HTML_DOCUMENT_NODE: + case XML_DTD_NODE: + case XML_ELEMENT_DECL: + case XML_ATTRIBUTE_DECL: + case XML_ENTITY_DECL: + case XML_PI_NODE: + case XML_ENTITY_REF_NODE: + case XML_ENTITY_NODE: + case XML_NAMESPACE_DECL: +#ifdef LIBXML_DOCB_ENABLED + case XML_DOCB_DOCUMENT_NODE: +#endif + case XML_XINCLUDE_START: + case XML_XINCLUDE_END: + return; + case XML_ELEMENT_NODE: + case XML_ATTRIBUTE_NODE: + break; + } + ns = xmlSearchNsByHref(cur->doc, cur, XML_XML_NAMESPACE); + if (ns == NULL) + return; + xmlSetNsProp(cur, ns, BAD_CAST "lang", lang); +} +#endif /* LIBXML_TREE_ENABLED */ + +/** + * xmlNodeGetLang: + * @cur: the node being checked + * + * Searches the language of a node, i.e. the values of the xml:lang + * attribute or the one carried by the nearest ancestor. + * + * Returns a pointer to the lang value, or NULL if not found + * It's up to the caller to free the memory with xmlFree(). + */ +xmlChar * +xmlNodeGetLang(xmlNodePtr cur) { + xmlChar *lang; + + while (cur != NULL) { + lang = xmlGetNsProp(cur, BAD_CAST "lang", XML_XML_NAMESPACE); + if (lang != NULL) + return(lang); + cur = cur->parent; + } + return(NULL); +} + + +#ifdef LIBXML_TREE_ENABLED +/** + * xmlNodeSetSpacePreserve: + * @cur: the node being changed + * @val: the xml:space value ("0": default, 1: "preserve") + * + * Set (or reset) the space preserving behaviour of a node, i.e. the + * value of the xml:space attribute. + */ +void +xmlNodeSetSpacePreserve(xmlNodePtr cur, int val) { + xmlNsPtr ns; + + if (cur == NULL) return; + switch(cur->type) { + case XML_TEXT_NODE: + case XML_CDATA_SECTION_NODE: + case XML_COMMENT_NODE: + case XML_DOCUMENT_NODE: + case XML_DOCUMENT_TYPE_NODE: + case XML_DOCUMENT_FRAG_NODE: + case XML_NOTATION_NODE: + case XML_HTML_DOCUMENT_NODE: + case XML_DTD_NODE: + case XML_ELEMENT_DECL: + case XML_ATTRIBUTE_DECL: + case XML_ENTITY_DECL: + case XML_PI_NODE: + case XML_ENTITY_REF_NODE: + case XML_ENTITY_NODE: + case XML_NAMESPACE_DECL: + case XML_XINCLUDE_START: + case XML_XINCLUDE_END: +#ifdef LIBXML_DOCB_ENABLED + case XML_DOCB_DOCUMENT_NODE: +#endif + return; + case XML_ELEMENT_NODE: + case XML_ATTRIBUTE_NODE: + break; + } + ns = xmlSearchNsByHref(cur->doc, cur, XML_XML_NAMESPACE); + if (ns == NULL) + return; + switch (val) { + case 0: + xmlSetNsProp(cur, ns, BAD_CAST "space", BAD_CAST "default"); + break; + case 1: + xmlSetNsProp(cur, ns, BAD_CAST "space", BAD_CAST "preserve"); + break; + } +} +#endif /* LIBXML_TREE_ENABLED */ + +/** + * xmlNodeGetSpacePreserve: + * @cur: the node being checked + * + * Searches the space preserving behaviour of a node, i.e. the values + * of the xml:space attribute or the one carried by the nearest + * ancestor. + * + * Returns -1 if xml:space is not inherited, 0 if "default", 1 if "preserve" + */ +int +xmlNodeGetSpacePreserve(xmlNodePtr cur) { + xmlChar *space; + + while (cur != NULL) { + space = xmlGetNsProp(cur, BAD_CAST "space", XML_XML_NAMESPACE); + if (space != NULL) { + if (xmlStrEqual(space, BAD_CAST "preserve")) { + xmlFree(space); + return(1); + } + if (xmlStrEqual(space, BAD_CAST "default")) { + xmlFree(space); + return(0); + } + xmlFree(space); + } + cur = cur->parent; + } + return(-1); +} + +#ifdef LIBXML_TREE_ENABLED +/** + * xmlNodeSetName: + * @cur: the node being changed + * @name: the new tag name + * + * Set (or reset) the name of a node. + */ +void +xmlNodeSetName(xmlNodePtr cur, const xmlChar *name) { + xmlDocPtr doc; + xmlDictPtr dict; + + if (cur == NULL) return; + if (name == NULL) return; + switch(cur->type) { + case XML_TEXT_NODE: + case XML_CDATA_SECTION_NODE: + case XML_COMMENT_NODE: + case XML_DOCUMENT_TYPE_NODE: + case XML_DOCUMENT_FRAG_NODE: + case XML_NOTATION_NODE: + case XML_HTML_DOCUMENT_NODE: + case XML_NAMESPACE_DECL: + case XML_XINCLUDE_START: + case XML_XINCLUDE_END: +#ifdef LIBXML_DOCB_ENABLED + case XML_DOCB_DOCUMENT_NODE: +#endif + return; + case XML_ELEMENT_NODE: + case XML_ATTRIBUTE_NODE: + case XML_PI_NODE: + case XML_ENTITY_REF_NODE: + case XML_ENTITY_NODE: + case XML_DTD_NODE: + case XML_DOCUMENT_NODE: + case XML_ELEMENT_DECL: + case XML_ATTRIBUTE_DECL: + case XML_ENTITY_DECL: + break; + } + doc = cur->doc; + if (doc != NULL) + dict = doc->dict; + else + dict = NULL; + if (dict != NULL) { + if ((cur->name != NULL) && (!xmlDictOwns(dict, cur->name))) + xmlFree((xmlChar *) cur->name); + cur->name = xmlDictLookup(dict, name, -1); + } else { + if (cur->name != NULL) xmlFree((xmlChar *) cur->name); + cur->name = xmlStrdup(name); + } +} +#endif + +#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XINCLUDE_ENABLED) +/** + * xmlNodeSetBase: + * @cur: the node being changed + * @uri: the new base URI + * + * Set (or reset) the base URI of a node, i.e. the value of the + * xml:base attribute. + */ +void +xmlNodeSetBase(xmlNodePtr cur, const xmlChar* uri) { + xmlNsPtr ns; + const xmlChar* fixed; + + if (cur == NULL) return; + switch(cur->type) { + case XML_TEXT_NODE: + case XML_CDATA_SECTION_NODE: + case XML_COMMENT_NODE: + case XML_DOCUMENT_TYPE_NODE: + case XML_DOCUMENT_FRAG_NODE: + case XML_NOTATION_NODE: + case XML_DTD_NODE: + case XML_ELEMENT_DECL: + case XML_ATTRIBUTE_DECL: + case XML_ENTITY_DECL: + case XML_PI_NODE: + case XML_ENTITY_REF_NODE: + case XML_ENTITY_NODE: + case XML_NAMESPACE_DECL: + case XML_XINCLUDE_START: + case XML_XINCLUDE_END: + return; + case XML_ELEMENT_NODE: + case XML_ATTRIBUTE_NODE: + break; + case XML_DOCUMENT_NODE: +#ifdef LIBXML_DOCB_ENABLED + case XML_DOCB_DOCUMENT_NODE: +#endif + case XML_HTML_DOCUMENT_NODE: { + xmlDocPtr doc = (xmlDocPtr) cur; + + if (doc->URL != NULL) + xmlFree((xmlChar *) doc->URL); + if (uri == NULL) + doc->URL = NULL; + else + doc->URL = xmlPathToURI(uri); + return; + } + } + + ns = xmlSearchNsByHref(cur->doc, cur, XML_XML_NAMESPACE); + if (ns == NULL) + return; + fixed = xmlPathToURI(uri); + if (fixed != NULL) { + xmlSetNsProp(cur, ns, BAD_CAST "base", fixed); + xmlFree(fixed); + } else { + xmlSetNsProp(cur, ns, BAD_CAST "base", uri); + } +} +#endif /* LIBXML_TREE_ENABLED */ + +/** + * xmlNodeGetBase: + * @doc: the document the node pertains to + * @cur: the node being checked + * + * Searches for the BASE URL. The code should work on both XML + * and HTML document even if base mechanisms are completely different. + * It returns the base as defined in RFC 2396 sections + * 5.1.1. Base URI within Document Content + * and + * 5.1.2. Base URI from the Encapsulating Entity + * However it does not return the document base (5.1.3), use + * xmlDocumentGetBase() for this + * + * Returns a pointer to the base URL, or NULL if not found + * It's up to the caller to free the memory with xmlFree(). + */ +xmlChar * +xmlNodeGetBase(xmlDocPtr doc, xmlNodePtr cur) { + xmlChar *oldbase = NULL; + xmlChar *base, *newbase; + + if ((cur == NULL) && (doc == NULL)) + return(NULL); + if (doc == NULL) doc = cur->doc; + if ((doc != NULL) && (doc->type == XML_HTML_DOCUMENT_NODE)) { + cur = doc->children; + while ((cur != NULL) && (cur->name != NULL)) { + if (cur->type != XML_ELEMENT_NODE) { + cur = cur->next; + continue; + } + if (!xmlStrcasecmp(cur->name, BAD_CAST "html")) { + cur = cur->children; + continue; + } + if (!xmlStrcasecmp(cur->name, BAD_CAST "head")) { + cur = cur->children; + continue; + } + if (!xmlStrcasecmp(cur->name, BAD_CAST "base")) { + return(xmlGetProp(cur, BAD_CAST "href")); + } + cur = cur->next; + } + return(NULL); + } + while (cur != NULL) { + if (cur->type == XML_ENTITY_DECL) { + xmlEntityPtr ent = (xmlEntityPtr) cur; + return(xmlStrdup(ent->URI)); + } + if (cur->type == XML_ELEMENT_NODE) { + base = xmlGetNsProp(cur, BAD_CAST "base", XML_XML_NAMESPACE); + if (base != NULL) { + if (oldbase != NULL) { + newbase = xmlBuildURI(oldbase, base); + if (newbase != NULL) { + xmlFree(oldbase); + xmlFree(base); + oldbase = newbase; + } else { + xmlFree(oldbase); + xmlFree(base); + return(NULL); + } + } else { + oldbase = base; + } + if ((!xmlStrncmp(oldbase, BAD_CAST "http://", 7)) || + (!xmlStrncmp(oldbase, BAD_CAST "ftp://", 6)) || + (!xmlStrncmp(oldbase, BAD_CAST "urn:", 4))) + return(oldbase); + } + } + cur = cur->parent; + } + if ((doc != NULL) && (doc->URL != NULL)) { + if (oldbase == NULL) + return(xmlStrdup(doc->URL)); + newbase = xmlBuildURI(oldbase, doc->URL); + xmlFree(oldbase); + return(newbase); + } + return(oldbase); +} + +/** + * xmlNodeBufGetContent: + * @buffer: a buffer + * @cur: the node being read + * + * Read the value of a node @cur, this can be either the text carried + * directly by this node if it's a TEXT node or the aggregate string + * of the values carried by this node child's (TEXT and ENTITY_REF). + * Entity references are substituted. + * Fills up the buffer @buffer with this value + * + * Returns 0 in case of success and -1 in case of error. + */ +int +xmlNodeBufGetContent(xmlBufferPtr buffer, xmlNodePtr cur) +{ + if ((cur == NULL) || (buffer == NULL)) return(-1); + switch (cur->type) { + case XML_CDATA_SECTION_NODE: + case XML_TEXT_NODE: + xmlBufferCat(buffer, cur->content); + break; + case XML_DOCUMENT_FRAG_NODE: + case XML_ELEMENT_NODE:{ + xmlNodePtr tmp = cur; + + while (tmp != NULL) { + switch (tmp->type) { + case XML_CDATA_SECTION_NODE: + case XML_TEXT_NODE: + if (tmp->content != NULL) + xmlBufferCat(buffer, tmp->content); + break; + case XML_ENTITY_REF_NODE: + xmlNodeBufGetContent(buffer, tmp); + break; + default: + break; + } + /* + * Skip to next node + */ + if (tmp->children != NULL) { + if (tmp->children->type != XML_ENTITY_DECL) { + tmp = tmp->children; + continue; + } + } + if (tmp == cur) + break; + + if (tmp->next != NULL) { + tmp = tmp->next; + continue; + } + + do { + tmp = tmp->parent; + if (tmp == NULL) + break; + if (tmp == cur) { + tmp = NULL; + break; + } + if (tmp->next != NULL) { + tmp = tmp->next; + break; + } + } while (tmp != NULL); + } + break; + } + case XML_ATTRIBUTE_NODE:{ + xmlAttrPtr attr = (xmlAttrPtr) cur; + xmlNodePtr tmp = attr->children; + + while (tmp != NULL) { + if (tmp->type == XML_TEXT_NODE) + xmlBufferCat(buffer, tmp->content); + else + xmlNodeBufGetContent(buffer, tmp); + tmp = tmp->next; + } + break; + } + case XML_COMMENT_NODE: + case XML_PI_NODE: + xmlBufferCat(buffer, cur->content); + break; + case XML_ENTITY_REF_NODE:{ + xmlEntityPtr ent; + xmlNodePtr tmp; + + /* lookup entity declaration */ + ent = xmlGetDocEntity(cur->doc, cur->name); + if (ent == NULL) + return(-1); + + /* an entity content can be any "well balanced chunk", + * i.e. the result of the content [43] production: + * http://www.w3.org/TR/REC-xml#NT-content + * -> we iterate through child nodes and recursive call + * xmlNodeGetContent() which handles all possible node types */ + tmp = ent->children; + while (tmp) { + xmlNodeBufGetContent(buffer, tmp); + tmp = tmp->next; + } + break; + } + case XML_ENTITY_NODE: + case XML_DOCUMENT_TYPE_NODE: + case XML_NOTATION_NODE: + case XML_DTD_NODE: + case XML_XINCLUDE_START: + case XML_XINCLUDE_END: + break; + case XML_DOCUMENT_NODE: +#ifdef LIBXML_DOCB_ENABLED + case XML_DOCB_DOCUMENT_NODE: +#endif + case XML_HTML_DOCUMENT_NODE: + cur = cur->children; + while (cur!= NULL) { + if ((cur->type == XML_ELEMENT_NODE) || + (cur->type == XML_TEXT_NODE) || + (cur->type == XML_CDATA_SECTION_NODE)) { + xmlNodeBufGetContent(buffer, cur); + } + cur = cur->next; + } + break; + case XML_NAMESPACE_DECL: + xmlBufferCat(buffer, ((xmlNsPtr) cur)->href); + break; + case XML_ELEMENT_DECL: + case XML_ATTRIBUTE_DECL: + case XML_ENTITY_DECL: + break; + } + return(0); +} +/** + * xmlNodeGetContent: + * @cur: the node being read + * + * Read the value of a node, this can be either the text carried + * directly by this node if it's a TEXT node or the aggregate string + * of the values carried by this node child's (TEXT and ENTITY_REF). + * Entity references are substituted. + * Returns a new #xmlChar * or NULL if no content is available. + * It's up to the caller to free the memory with xmlFree(). + */ +xmlChar * +xmlNodeGetContent(xmlNodePtr cur) +{ + if (cur == NULL) + return (NULL); + switch (cur->type) { + case XML_DOCUMENT_FRAG_NODE: + case XML_ELEMENT_NODE:{ + xmlBufferPtr buffer; + xmlChar *ret; + + buffer = xmlBufferCreateSize(64); + if (buffer == NULL) + return (NULL); + xmlNodeBufGetContent(buffer, cur); + ret = buffer->content; + buffer->content = NULL; + xmlBufferFree(buffer); + return (ret); + } + case XML_ATTRIBUTE_NODE: + return(xmlGetPropNodeValueInternal((xmlAttrPtr) cur)); + case XML_COMMENT_NODE: + case XML_PI_NODE: + if (cur->content != NULL) + return (xmlStrdup(cur->content)); + return (NULL); + case XML_ENTITY_REF_NODE:{ + xmlEntityPtr ent; + xmlBufferPtr buffer; + xmlChar *ret; + + /* lookup entity declaration */ + ent = xmlGetDocEntity(cur->doc, cur->name); + if (ent == NULL) + return (NULL); + + buffer = xmlBufferCreate(); + if (buffer == NULL) + return (NULL); + + xmlNodeBufGetContent(buffer, cur); + + ret = buffer->content; + buffer->content = NULL; + xmlBufferFree(buffer); + return (ret); + } + case XML_ENTITY_NODE: + case XML_DOCUMENT_TYPE_NODE: + case XML_NOTATION_NODE: + case XML_DTD_NODE: + case XML_XINCLUDE_START: + case XML_XINCLUDE_END: + return (NULL); + case XML_DOCUMENT_NODE: +#ifdef LIBXML_DOCB_ENABLED + case XML_DOCB_DOCUMENT_NODE: +#endif + case XML_HTML_DOCUMENT_NODE: { + xmlBufferPtr buffer; + xmlChar *ret; + + buffer = xmlBufferCreate(); + if (buffer == NULL) + return (NULL); + + xmlNodeBufGetContent(buffer, (xmlNodePtr) cur); + + ret = buffer->content; + buffer->content = NULL; + xmlBufferFree(buffer); + return (ret); + } + case XML_NAMESPACE_DECL: { + xmlChar *tmp; + + tmp = xmlStrdup(((xmlNsPtr) cur)->href); + return (tmp); + } + case XML_ELEMENT_DECL: + /* TODO !!! */ + return (NULL); + case XML_ATTRIBUTE_DECL: + /* TODO !!! */ + return (NULL); + case XML_ENTITY_DECL: + /* TODO !!! */ + return (NULL); + case XML_CDATA_SECTION_NODE: + case XML_TEXT_NODE: + if (cur->content != NULL) + return (xmlStrdup(cur->content)); + return (NULL); + } + return (NULL); +} + +/** + * xmlNodeSetContent: + * @cur: the node being modified + * @content: the new value of the content + * + * Replace the content of a node. + */ +void +xmlNodeSetContent(xmlNodePtr cur, const xmlChar *content) { + if (cur == NULL) { +#ifdef DEBUG_TREE + xmlGenericError(xmlGenericErrorContext, + "xmlNodeSetContent : node == NULL\n"); +#endif + return; + } + switch (cur->type) { + case XML_DOCUMENT_FRAG_NODE: + case XML_ELEMENT_NODE: + case XML_ATTRIBUTE_NODE: + if (cur->children != NULL) xmlFreeNodeList(cur->children); + cur->children = xmlStringGetNodeList(cur->doc, content); + UPDATE_LAST_CHILD_AND_PARENT(cur) + break; + case XML_TEXT_NODE: + case XML_CDATA_SECTION_NODE: + case XML_ENTITY_REF_NODE: + case XML_ENTITY_NODE: + case XML_PI_NODE: + case XML_COMMENT_NODE: + if ((cur->content != NULL) && + (cur->content != (xmlChar *) &(cur->properties))) { + if (!((cur->doc != NULL) && (cur->doc->dict != NULL) && + (xmlDictOwns(cur->doc->dict, cur->content)))) + xmlFree(cur->content); + } + if (cur->children != NULL) xmlFreeNodeList(cur->children); + cur->last = cur->children = NULL; + if (content != NULL) { + cur->content = xmlStrdup(content); + } else + cur->content = NULL; + cur->properties = NULL; + cur->nsDef = NULL; + break; + case XML_DOCUMENT_NODE: + case XML_HTML_DOCUMENT_NODE: + case XML_DOCUMENT_TYPE_NODE: + case XML_XINCLUDE_START: + case XML_XINCLUDE_END: +#ifdef LIBXML_DOCB_ENABLED + case XML_DOCB_DOCUMENT_NODE: +#endif + break; + case XML_NOTATION_NODE: + break; + case XML_DTD_NODE: + break; + case XML_NAMESPACE_DECL: + break; + case XML_ELEMENT_DECL: + /* TODO !!! */ + break; + case XML_ATTRIBUTE_DECL: + /* TODO !!! */ + break; + case XML_ENTITY_DECL: + /* TODO !!! */ + break; + } +} + +#ifdef LIBXML_TREE_ENABLED +/** + * xmlNodeSetContentLen: + * @cur: the node being modified + * @content: the new value of the content + * @len: the size of @content + * + * Replace the content of a node. + */ +void +xmlNodeSetContentLen(xmlNodePtr cur, const xmlChar *content, int len) { + if (cur == NULL) { +#ifdef DEBUG_TREE + xmlGenericError(xmlGenericErrorContext, + "xmlNodeSetContentLen : node == NULL\n"); +#endif + return; + } + switch (cur->type) { + case XML_DOCUMENT_FRAG_NODE: + case XML_ELEMENT_NODE: + case XML_ATTRIBUTE_NODE: + if (cur->children != NULL) xmlFreeNodeList(cur->children); + cur->children = xmlStringLenGetNodeList(cur->doc, content, len); + UPDATE_LAST_CHILD_AND_PARENT(cur) + break; + case XML_TEXT_NODE: + case XML_CDATA_SECTION_NODE: + case XML_ENTITY_REF_NODE: + case XML_ENTITY_NODE: + case XML_PI_NODE: + case XML_COMMENT_NODE: + case XML_NOTATION_NODE: + if ((cur->content != NULL) && + (cur->content != (xmlChar *) &(cur->properties))) { + if (!((cur->doc != NULL) && (cur->doc->dict != NULL) && + (xmlDictOwns(cur->doc->dict, cur->content)))) + xmlFree(cur->content); + } + if (cur->children != NULL) xmlFreeNodeList(cur->children); + cur->children = cur->last = NULL; + if (content != NULL) { + cur->content = xmlStrndup(content, len); + } else + cur->content = NULL; + cur->properties = NULL; + cur->nsDef = NULL; + break; + case XML_DOCUMENT_NODE: + case XML_DTD_NODE: + case XML_HTML_DOCUMENT_NODE: + case XML_DOCUMENT_TYPE_NODE: + case XML_NAMESPACE_DECL: + case XML_XINCLUDE_START: + case XML_XINCLUDE_END: +#ifdef LIBXML_DOCB_ENABLED + case XML_DOCB_DOCUMENT_NODE: +#endif + break; + case XML_ELEMENT_DECL: + /* TODO !!! */ + break; + case XML_ATTRIBUTE_DECL: + /* TODO !!! */ + break; + case XML_ENTITY_DECL: + /* TODO !!! */ + break; + } +} +#endif /* LIBXML_TREE_ENABLED */ + +/** + * xmlNodeAddContentLen: + * @cur: the node being modified + * @content: extra content + * @len: the size of @content + * + * Append the extra substring to the node content. + */ +void +xmlNodeAddContentLen(xmlNodePtr cur, const xmlChar *content, int len) { + if (cur == NULL) { +#ifdef DEBUG_TREE + xmlGenericError(xmlGenericErrorContext, + "xmlNodeAddContentLen : node == NULL\n"); +#endif + return; + } + if (len <= 0) return; + switch (cur->type) { + case XML_DOCUMENT_FRAG_NODE: + case XML_ELEMENT_NODE: { + xmlNodePtr last, newNode, tmp; + + last = cur->last; + newNode = xmlNewTextLen(content, len); + if (newNode != NULL) { + tmp = xmlAddChild(cur, newNode); + if (tmp != newNode) + return; + if ((last != NULL) && (last->next == newNode)) { + xmlTextMerge(last, newNode); + } + } + break; + } + case XML_ATTRIBUTE_NODE: + break; + case XML_TEXT_NODE: + case XML_CDATA_SECTION_NODE: + case XML_ENTITY_REF_NODE: + case XML_ENTITY_NODE: + case XML_PI_NODE: + case XML_COMMENT_NODE: + case XML_NOTATION_NODE: + if (content != NULL) { + if ((cur->content == (xmlChar *) &(cur->properties)) || + ((cur->doc != NULL) && (cur->doc->dict != NULL) && + xmlDictOwns(cur->doc->dict, cur->content))) { + cur->content = xmlStrncatNew(cur->content, content, len); + cur->properties = NULL; + cur->nsDef = NULL; + break; + } + cur->content = xmlStrncat(cur->content, content, len); + } + case XML_DOCUMENT_NODE: + case XML_DTD_NODE: + case XML_HTML_DOCUMENT_NODE: + case XML_DOCUMENT_TYPE_NODE: + case XML_NAMESPACE_DECL: + case XML_XINCLUDE_START: + case XML_XINCLUDE_END: +#ifdef LIBXML_DOCB_ENABLED + case XML_DOCB_DOCUMENT_NODE: +#endif + break; + case XML_ELEMENT_DECL: + case XML_ATTRIBUTE_DECL: + case XML_ENTITY_DECL: + break; + } +} + +/** + * xmlNodeAddContent: + * @cur: the node being modified + * @content: extra content + * + * Append the extra substring to the node content. + */ +void +xmlNodeAddContent(xmlNodePtr cur, const xmlChar *content) { + int len; + + if (cur == NULL) { +#ifdef DEBUG_TREE + xmlGenericError(xmlGenericErrorContext, + "xmlNodeAddContent : node == NULL\n"); +#endif + return; + } + if (content == NULL) return; + len = xmlStrlen(content); + xmlNodeAddContentLen(cur, content, len); +} + +/** + * xmlTextMerge: + * @first: the first text node + * @second: the second text node being merged + * + * Merge two text nodes into one + * Returns the first text node augmented + */ +xmlNodePtr +xmlTextMerge(xmlNodePtr first, xmlNodePtr second) { + if (first == NULL) return(second); + if (second == NULL) return(first); + if (first->type != XML_TEXT_NODE) return(first); + if (second->type != XML_TEXT_NODE) return(first); + if (second->name != first->name) + return(first); + xmlNodeAddContent(first, second->content); + xmlUnlinkNode(second); + xmlFreeNode(second); + return(first); +} + +#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) +/** + * xmlGetNsList: + * @doc: the document + * @node: the current node + * + * Search all the namespace applying to a given element. + * Returns an NULL terminated array of all the #xmlNsPtr found + * that need to be freed by the caller or NULL if no + * namespace if defined + */ +xmlNsPtr * +xmlGetNsList(xmlDocPtr doc ATTRIBUTE_UNUSED, xmlNodePtr node) +{ + xmlNsPtr cur; + xmlNsPtr *ret = NULL; + int nbns = 0; + int maxns = 10; + int i; + + while (node != NULL) { + if (node->type == XML_ELEMENT_NODE) { + cur = node->nsDef; + while (cur != NULL) { + if (ret == NULL) { + ret = + (xmlNsPtr *) xmlMalloc((maxns + 1) * + sizeof(xmlNsPtr)); + if (ret == NULL) { + xmlTreeErrMemory("getting namespace list"); + return (NULL); + } + ret[nbns] = NULL; + } + for (i = 0; i < nbns; i++) { + if ((cur->prefix == ret[i]->prefix) || + (xmlStrEqual(cur->prefix, ret[i]->prefix))) + break; + } + if (i >= nbns) { + if (nbns >= maxns) { + maxns *= 2; + ret = (xmlNsPtr *) xmlRealloc(ret, + (maxns + + 1) * + sizeof(xmlNsPtr)); + if (ret == NULL) { + xmlTreeErrMemory("getting namespace list"); + return (NULL); + } + } + ret[nbns++] = cur; + ret[nbns] = NULL; + } + + cur = cur->next; + } + } + node = node->parent; + } + return (ret); +} +#endif /* LIBXML_TREE_ENABLED */ + +/* +* xmlTreeEnsureXMLDecl: +* @doc: the doc +* +* Ensures that there is an XML namespace declaration on the doc. +* +* Returns the XML ns-struct or NULL on API and internal errors. +*/ +static xmlNsPtr +xmlTreeEnsureXMLDecl(xmlDocPtr doc) +{ + if (doc == NULL) + return (NULL); + if (doc->oldNs != NULL) + return (doc->oldNs); + { + xmlNsPtr ns; + ns = (xmlNsPtr) xmlMalloc(sizeof(xmlNs)); + if (ns == NULL) { + xmlTreeErrMemory( + "allocating the XML namespace"); + return (NULL); + } + memset(ns, 0, sizeof(xmlNs)); + ns->type = XML_LOCAL_NAMESPACE; + ns->href = xmlStrdup(XML_XML_NAMESPACE); + ns->prefix = xmlStrdup((const xmlChar *)"xml"); + doc->oldNs = ns; + return (ns); + } +} + +/** + * xmlSearchNs: + * @doc: the document + * @node: the current node + * @nameSpace: the namespace prefix + * + * Search a Ns registered under a given name space for a document. + * recurse on the parents until it finds the defined namespace + * or return NULL otherwise. + * @nameSpace can be NULL, this is a search for the default namespace. + * We don't allow to cross entities boundaries. If you don't declare + * the namespace within those you will be in troubles !!! A warning + * is generated to cover this case. + * + * Returns the namespace pointer or NULL. + */ +xmlNsPtr +xmlSearchNs(xmlDocPtr doc, xmlNodePtr node, const xmlChar *nameSpace) { + + xmlNsPtr cur; + xmlNodePtr orig = node; + + if (node == NULL) return(NULL); + if ((nameSpace != NULL) && + (xmlStrEqual(nameSpace, (const xmlChar *)"xml"))) { + if ((doc == NULL) && (node->type == XML_ELEMENT_NODE)) { + /* + * The XML-1.0 namespace is normally held on the root + * element. In this case exceptionally create it on the + * node element. + */ + cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs)); + if (cur == NULL) { + xmlTreeErrMemory("searching namespace"); + return(NULL); + } + memset(cur, 0, sizeof(xmlNs)); + cur->type = XML_LOCAL_NAMESPACE; + cur->href = xmlStrdup(XML_XML_NAMESPACE); + cur->prefix = xmlStrdup((const xmlChar *)"xml"); + cur->next = node->nsDef; + node->nsDef = cur; + return(cur); + } + if (doc == NULL) { + doc = node->doc; + if (doc == NULL) + return(NULL); + } + /* + * Return the XML namespace declaration held by the doc. + */ + if (doc->oldNs == NULL) + return(xmlTreeEnsureXMLDecl(doc)); + else + return(doc->oldNs); + } + while (node != NULL) { + if ((node->type == XML_ENTITY_REF_NODE) || + (node->type == XML_ENTITY_NODE) || + (node->type == XML_ENTITY_DECL)) + return(NULL); + if (node->type == XML_ELEMENT_NODE) { + cur = node->nsDef; + while (cur != NULL) { + if ((cur->prefix == NULL) && (nameSpace == NULL) && + (cur->href != NULL)) + return(cur); + if ((cur->prefix != NULL) && (nameSpace != NULL) && + (cur->href != NULL) && + (xmlStrEqual(cur->prefix, nameSpace))) + return(cur); + cur = cur->next; + } + if (orig != node) { + cur = node->ns; + if (cur != NULL) { + if ((cur->prefix == NULL) && (nameSpace == NULL) && + (cur->href != NULL)) + return(cur); + if ((cur->prefix != NULL) && (nameSpace != NULL) && + (cur->href != NULL) && + (xmlStrEqual(cur->prefix, nameSpace))) + return(cur); + } + } + } + node = node->parent; + } + return(NULL); +} + +/** + * xmlNsInScope: + * @doc: the document + * @node: the current node + * @ancestor: the ancestor carrying the namespace + * @prefix: the namespace prefix + * + * Verify that the given namespace held on @ancestor is still in scope + * on node. + * + * Returns 1 if true, 0 if false and -1 in case of error. + */ +static int +xmlNsInScope(xmlDocPtr doc ATTRIBUTE_UNUSED, xmlNodePtr node, + xmlNodePtr ancestor, const xmlChar * prefix) +{ + xmlNsPtr tst; + + while ((node != NULL) && (node != ancestor)) { + if ((node->type == XML_ENTITY_REF_NODE) || + (node->type == XML_ENTITY_NODE) || + (node->type == XML_ENTITY_DECL)) + return (-1); + if (node->type == XML_ELEMENT_NODE) { + tst = node->nsDef; + while (tst != NULL) { + if ((tst->prefix == NULL) + && (prefix == NULL)) + return (0); + if ((tst->prefix != NULL) + && (prefix != NULL) + && (xmlStrEqual(tst->prefix, prefix))) + return (0); + tst = tst->next; + } + } + node = node->parent; + } + if (node != ancestor) + return (-1); + return (1); +} + +/** + * xmlSearchNsByHref: + * @doc: the document + * @node: the current node + * @href: the namespace value + * + * Search a Ns aliasing a given URI. Recurse on the parents until it finds + * the defined namespace or return NULL otherwise. + * Returns the namespace pointer or NULL. + */ +xmlNsPtr +xmlSearchNsByHref(xmlDocPtr doc, xmlNodePtr node, const xmlChar * href) +{ + xmlNsPtr cur; + xmlNodePtr orig = node; + int is_attr; + + if ((node == NULL) || (href == NULL)) + return (NULL); + if (xmlStrEqual(href, XML_XML_NAMESPACE)) { + /* + * Only the document can hold the XML spec namespace. + */ + if ((doc == NULL) && (node->type == XML_ELEMENT_NODE)) { + /* + * The XML-1.0 namespace is normally held on the root + * element. In this case exceptionally create it on the + * node element. + */ + cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs)); + if (cur == NULL) { + xmlTreeErrMemory("searching namespace"); + return (NULL); + } + memset(cur, 0, sizeof(xmlNs)); + cur->type = XML_LOCAL_NAMESPACE; + cur->href = xmlStrdup(XML_XML_NAMESPACE); + cur->prefix = xmlStrdup((const xmlChar *) "xml"); + cur->next = node->nsDef; + node->nsDef = cur; + return (cur); + } + if (doc == NULL) { + doc = node->doc; + if (doc == NULL) + return(NULL); + } + /* + * Return the XML namespace declaration held by the doc. + */ + if (doc->oldNs == NULL) + return(xmlTreeEnsureXMLDecl(doc)); + else + return(doc->oldNs); + } + is_attr = (node->type == XML_ATTRIBUTE_NODE); + while (node != NULL) { + if ((node->type == XML_ENTITY_REF_NODE) || + (node->type == XML_ENTITY_NODE) || + (node->type == XML_ENTITY_DECL)) + return (NULL); + if (node->type == XML_ELEMENT_NODE) { + cur = node->nsDef; + while (cur != NULL) { + if ((cur->href != NULL) && (href != NULL) && + (xmlStrEqual(cur->href, href))) { + if (((!is_attr) || (cur->prefix != NULL)) && + (xmlNsInScope(doc, orig, node, cur->prefix) == 1)) + return (cur); + } + cur = cur->next; + } + if (orig != node) { + cur = node->ns; + if (cur != NULL) { + if ((cur->href != NULL) && (href != NULL) && + (xmlStrEqual(cur->href, href))) { + if (((!is_attr) || (cur->prefix != NULL)) && + (xmlNsInScope(doc, orig, node, cur->prefix) == 1)) + return (cur); + } + } + } + } + node = node->parent; + } + return (NULL); +} + +/** + * xmlNewReconciliedNs: + * @doc: the document + * @tree: a node expected to hold the new namespace + * @ns: the original namespace + * + * This function tries to locate a namespace definition in a tree + * ancestors, or create a new namespace definition node similar to + * @ns trying to reuse the same prefix. However if the given prefix is + * null (default namespace) or reused within the subtree defined by + * @tree or on one of its ancestors then a new prefix is generated. + * Returns the (new) namespace definition or NULL in case of error + */ +xmlNsPtr +xmlNewReconciliedNs(xmlDocPtr doc, xmlNodePtr tree, xmlNsPtr ns) { + xmlNsPtr def; + xmlChar prefix[50]; + int counter = 1; + + if (tree == NULL) { +#ifdef DEBUG_TREE + xmlGenericError(xmlGenericErrorContext, + "xmlNewReconciliedNs : tree == NULL\n"); +#endif + return(NULL); + } + if ((ns == NULL) || (ns->type != XML_NAMESPACE_DECL)) { +#ifdef DEBUG_TREE + xmlGenericError(xmlGenericErrorContext, + "xmlNewReconciliedNs : ns == NULL\n"); +#endif + return(NULL); + } + /* + * Search an existing namespace definition inherited. + */ + def = xmlSearchNsByHref(doc, tree, ns->href); + if (def != NULL) + return(def); + + /* + * Find a close prefix which is not already in use. + * Let's strip namespace prefixes longer than 20 chars ! + */ + if (ns->prefix == NULL) + snprintf((char *) prefix, sizeof(prefix), "default"); + else + snprintf((char *) prefix, sizeof(prefix), "%.20s", (char *)ns->prefix); + + def = xmlSearchNs(doc, tree, prefix); + while (def != NULL) { + if (counter > 1000) return(NULL); + if (ns->prefix == NULL) + snprintf((char *) prefix, sizeof(prefix), "default%d", counter++); + else + snprintf((char *) prefix, sizeof(prefix), "%.20s%d", + (char *)ns->prefix, counter++); + def = xmlSearchNs(doc, tree, prefix); + } + + /* + * OK, now we are ready to create a new one. + */ + def = xmlNewNs(tree, ns->href, prefix); + return(def); +} + +#ifdef LIBXML_TREE_ENABLED +/** + * xmlReconciliateNs: + * @doc: the document + * @tree: a node defining the subtree to reconciliate + * + * This function checks that all the namespaces declared within the given + * tree are properly declared. This is needed for example after Copy or Cut + * and then paste operations. The subtree may still hold pointers to + * namespace declarations outside the subtree or invalid/masked. As much + * as possible the function try to reuse the existing namespaces found in + * the new environment. If not possible the new namespaces are redeclared + * on @tree at the top of the given subtree. + * Returns the number of namespace declarations created or -1 in case of error. + */ +int +xmlReconciliateNs(xmlDocPtr doc, xmlNodePtr tree) { + xmlNsPtr *oldNs = NULL; + xmlNsPtr *newNs = NULL; + int sizeCache = 0; + int nbCache = 0; + + xmlNsPtr n; + xmlNodePtr node = tree; + xmlAttrPtr attr; + int ret = 0, i; + + if ((node == NULL) || (node->type != XML_ELEMENT_NODE)) return(-1); + if ((doc == NULL) || (doc->type != XML_DOCUMENT_NODE)) return(-1); + if (node->doc != doc) return(-1); + while (node != NULL) { + /* + * Reconciliate the node namespace + */ + if (node->ns != NULL) { + /* + * initialize the cache if needed + */ + if (sizeCache == 0) { + sizeCache = 10; + oldNs = (xmlNsPtr *) xmlMalloc(sizeCache * + sizeof(xmlNsPtr)); + if (oldNs == NULL) { + xmlTreeErrMemory("fixing namespaces"); + return(-1); + } + newNs = (xmlNsPtr *) xmlMalloc(sizeCache * + sizeof(xmlNsPtr)); + if (newNs == NULL) { + xmlTreeErrMemory("fixing namespaces"); + xmlFree(oldNs); + return(-1); + } + } + for (i = 0;i < nbCache;i++) { + if (oldNs[i] == node->ns) { + node->ns = newNs[i]; + break; + } + } + if (i == nbCache) { + /* + * OK we need to recreate a new namespace definition + */ + n = xmlNewReconciliedNs(doc, tree, node->ns); + if (n != NULL) { /* :-( what if else ??? */ + /* + * check if we need to grow the cache buffers. + */ + if (sizeCache <= nbCache) { + sizeCache *= 2; + oldNs = (xmlNsPtr *) xmlRealloc(oldNs, sizeCache * + sizeof(xmlNsPtr)); + if (oldNs == NULL) { + xmlTreeErrMemory("fixing namespaces"); + xmlFree(newNs); + return(-1); + } + newNs = (xmlNsPtr *) xmlRealloc(newNs, sizeCache * + sizeof(xmlNsPtr)); + if (newNs == NULL) { + xmlTreeErrMemory("fixing namespaces"); + xmlFree(oldNs); + return(-1); + } + } + newNs[nbCache] = n; + oldNs[nbCache++] = node->ns; + node->ns = n; + } + } + } + /* + * now check for namespace hold by attributes on the node. + */ + if (node->type == XML_ELEMENT_NODE) { + attr = node->properties; + while (attr != NULL) { + if (attr->ns != NULL) { + /* + * initialize the cache if needed + */ + if (sizeCache == 0) { + sizeCache = 10; + oldNs = (xmlNsPtr *) xmlMalloc(sizeCache * + sizeof(xmlNsPtr)); + if (oldNs == NULL) { + xmlTreeErrMemory("fixing namespaces"); + return(-1); + } + newNs = (xmlNsPtr *) xmlMalloc(sizeCache * + sizeof(xmlNsPtr)); + if (newNs == NULL) { + xmlTreeErrMemory("fixing namespaces"); + xmlFree(oldNs); + return(-1); + } + } + for (i = 0;i < nbCache;i++) { + if (oldNs[i] == attr->ns) { + attr->ns = newNs[i]; + break; + } + } + if (i == nbCache) { + /* + * OK we need to recreate a new namespace definition + */ + n = xmlNewReconciliedNs(doc, tree, attr->ns); + if (n != NULL) { /* :-( what if else ??? */ + /* + * check if we need to grow the cache buffers. + */ + if (sizeCache <= nbCache) { + sizeCache *= 2; + oldNs = (xmlNsPtr *) xmlRealloc(oldNs, + sizeCache * sizeof(xmlNsPtr)); + if (oldNs == NULL) { + xmlTreeErrMemory("fixing namespaces"); + xmlFree(newNs); + return(-1); + } + newNs = (xmlNsPtr *) xmlRealloc(newNs, + sizeCache * sizeof(xmlNsPtr)); + if (newNs == NULL) { + xmlTreeErrMemory("fixing namespaces"); + xmlFree(oldNs); + return(-1); + } + } + newNs[nbCache] = n; + oldNs[nbCache++] = attr->ns; + attr->ns = n; + } + } + } + attr = attr->next; + } + } + + /* + * Browse the full subtree, deep first + */ + if ((node->children != NULL) && (node->type != XML_ENTITY_REF_NODE)) { + /* deep first */ + node = node->children; + } else if ((node != tree) && (node->next != NULL)) { + /* then siblings */ + node = node->next; + } else if (node != tree) { + /* go up to parents->next if needed */ + while (node != tree) { + if (node->parent != NULL) + node = node->parent; + if ((node != tree) && (node->next != NULL)) { + node = node->next; + break; + } + if (node->parent == NULL) { + node = NULL; + break; + } + } + /* exit condition */ + if (node == tree) + node = NULL; + } else + break; + } + if (oldNs != NULL) + xmlFree(oldNs); + if (newNs != NULL) + xmlFree(newNs); + return(ret); +} +#endif /* LIBXML_TREE_ENABLED */ + +static xmlAttrPtr +xmlGetPropNodeInternal(xmlNodePtr node, const xmlChar *name, + const xmlChar *nsName, int useDTD) +{ + xmlAttrPtr prop; + + if ((node == NULL) || (node->type != XML_ELEMENT_NODE) || (name == NULL)) + return(NULL); + + if (node->properties != NULL) { + prop = node->properties; + if (nsName == NULL) { + /* + * We want the attr to be in no namespace. + */ + do { + if ((prop->ns == NULL) && xmlStrEqual(prop->name, name)) { + return(prop); + } + prop = prop->next; + } while (prop != NULL); + } else { + /* + * We want the attr to be in the specified namespace. + */ + do { + if ((prop->ns != NULL) && xmlStrEqual(prop->name, name) && + ((prop->ns->href == nsName) || + xmlStrEqual(prop->ns->href, nsName))) + { + return(prop); + } + prop = prop->next; + } while (prop != NULL); + } + } + +#ifdef LIBXML_TREE_ENABLED + if (! useDTD) + return(NULL); + /* + * Check if there is a default/fixed attribute declaration in + * the internal or external subset. + */ + if ((node->doc != NULL) && (node->doc->intSubset != NULL)) { + xmlDocPtr doc = node->doc; + xmlAttributePtr attrDecl = NULL; + xmlChar *elemQName, *tmpstr = NULL; + + /* + * We need the QName of the element for the DTD-lookup. + */ + if ((node->ns != NULL) && (node->ns->prefix != NULL)) { + tmpstr = xmlStrdup(node->ns->prefix); + tmpstr = xmlStrcat(tmpstr, BAD_CAST ":"); + tmpstr = xmlStrcat(tmpstr, node->name); + if (tmpstr == NULL) + return(NULL); + elemQName = tmpstr; + } else + elemQName = (xmlChar *) node->name; + if (nsName == NULL) { + /* + * The common and nice case: Attr in no namespace. + */ + attrDecl = xmlGetDtdQAttrDesc(doc->intSubset, + elemQName, name, NULL); + if ((attrDecl == NULL) && (doc->extSubset != NULL)) { + attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, + elemQName, name, NULL); + } + } else { + xmlNsPtr *nsList, *cur; + + /* + * The ugly case: Search using the prefixes of in-scope + * ns-decls corresponding to @nsName. + */ + nsList = xmlGetNsList(node->doc, node); + if (nsList == NULL) { + if (tmpstr != NULL) + xmlFree(tmpstr); + return(NULL); + } + cur = nsList; + while (*cur != NULL) { + if (xmlStrEqual((*cur)->href, nsName)) { + attrDecl = xmlGetDtdQAttrDesc(doc->intSubset, elemQName, + name, (*cur)->prefix); + if (attrDecl) + break; + if (doc->extSubset != NULL) { + attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, elemQName, + name, (*cur)->prefix); + if (attrDecl) + break; + } + } + cur++; + } + xmlFree(nsList); + } + if (tmpstr != NULL) + xmlFree(tmpstr); + /* + * Only default/fixed attrs are relevant. + */ + if ((attrDecl != NULL) && (attrDecl->defaultValue != NULL)) + return((xmlAttrPtr) attrDecl); + } +#endif /* LIBXML_TREE_ENABLED */ + return(NULL); +} + +static xmlChar* +xmlGetPropNodeValueInternal(xmlAttrPtr prop) +{ + if (prop == NULL) + return(NULL); + if (prop->type == XML_ATTRIBUTE_NODE) { + /* + * Note that we return at least the empty string. + * TODO: Do we really always want that? + */ + if (prop->children != NULL) { + if ((prop->children->next == NULL) && + ((prop->children->type == XML_TEXT_NODE) || + (prop->children->type == XML_CDATA_SECTION_NODE))) + { + /* + * Optimization for the common case: only 1 text node. + */ + return(xmlStrdup(prop->children->content)); + } else { + xmlChar *ret; + + ret = xmlNodeListGetString(prop->doc, prop->children, 1); + if (ret != NULL) + return(ret); + } + } + return(xmlStrdup((xmlChar *)"")); + } else if (prop->type == XML_ATTRIBUTE_DECL) { + return(xmlStrdup(((xmlAttributePtr)prop)->defaultValue)); + } + return(NULL); +} + +/** + * xmlHasProp: + * @node: the node + * @name: the attribute name + * + * Search an attribute associated to a node + * This function also looks in DTD attribute declaration for #FIXED or + * default declaration values unless DTD use has been turned off. + * + * Returns the attribute or the attribute declaration or NULL if + * neither was found. + */ +xmlAttrPtr +xmlHasProp(xmlNodePtr node, const xmlChar *name) { + xmlAttrPtr prop; + xmlDocPtr doc; + + if ((node == NULL) || (node->type != XML_ELEMENT_NODE) || (name == NULL)) + return(NULL); + /* + * Check on the properties attached to the node + */ + prop = node->properties; + while (prop != NULL) { + if (xmlStrEqual(prop->name, name)) { + return(prop); + } + prop = prop->next; + } + if (!xmlCheckDTD) return(NULL); + + /* + * Check if there is a default declaration in the internal + * or external subsets + */ + doc = node->doc; + if (doc != NULL) { + xmlAttributePtr attrDecl; + if (doc->intSubset != NULL) { + attrDecl = xmlGetDtdAttrDesc(doc->intSubset, node->name, name); + if ((attrDecl == NULL) && (doc->extSubset != NULL)) + attrDecl = xmlGetDtdAttrDesc(doc->extSubset, node->name, name); + if ((attrDecl != NULL) && (attrDecl->defaultValue != NULL)) + /* return attribute declaration only if a default value is given + (that includes #FIXED declarations) */ + return((xmlAttrPtr) attrDecl); + } + } + return(NULL); +} + +/** + * xmlHasNsProp: + * @node: the node + * @name: the attribute name + * @nameSpace: the URI of the namespace + * + * Search for an attribute associated to a node + * This attribute has to be anchored in the namespace specified. + * This does the entity substitution. + * This function looks in DTD attribute declaration for #FIXED or + * default declaration values unless DTD use has been turned off. + * Note that a namespace of NULL indicates to use the default namespace. + * + * Returns the attribute or the attribute declaration or NULL + * if neither was found. + */ +xmlAttrPtr +xmlHasNsProp(xmlNodePtr node, const xmlChar *name, const xmlChar *nameSpace) { + + return(xmlGetPropNodeInternal(node, name, nameSpace, xmlCheckDTD)); +} + +/** + * xmlGetProp: + * @node: the node + * @name: the attribute name + * + * Search and get the value of an attribute associated to a node + * This does the entity substitution. + * This function looks in DTD attribute declaration for #FIXED or + * default declaration values unless DTD use has been turned off. + * NOTE: this function acts independently of namespaces associated + * to the attribute. Use xmlGetNsProp() or xmlGetNoNsProp() + * for namespace aware processing. + * + * Returns the attribute value or NULL if not found. + * It's up to the caller to free the memory with xmlFree(). + */ +xmlChar * +xmlGetProp(xmlNodePtr node, const xmlChar *name) { + xmlAttrPtr prop; + + prop = xmlHasProp(node, name); + if (prop == NULL) + return(NULL); + return(xmlGetPropNodeValueInternal(prop)); +} + +/** + * xmlGetNoNsProp: + * @node: the node + * @name: the attribute name + * + * Search and get the value of an attribute associated to a node + * This does the entity substitution. + * This function looks in DTD attribute declaration for #FIXED or + * default declaration values unless DTD use has been turned off. + * This function is similar to xmlGetProp except it will accept only + * an attribute in no namespace. + * + * Returns the attribute value or NULL if not found. + * It's up to the caller to free the memory with xmlFree(). + */ +xmlChar * +xmlGetNoNsProp(xmlNodePtr node, const xmlChar *name) { + xmlAttrPtr prop; + + prop = xmlGetPropNodeInternal(node, name, NULL, xmlCheckDTD); + if (prop == NULL) + return(NULL); + return(xmlGetPropNodeValueInternal(prop)); +} + +/** + * xmlGetNsProp: + * @node: the node + * @name: the attribute name + * @nameSpace: the URI of the namespace + * + * Search and get the value of an attribute associated to a node + * This attribute has to be anchored in the namespace specified. + * This does the entity substitution. + * This function looks in DTD attribute declaration for #FIXED or + * default declaration values unless DTD use has been turned off. + * + * Returns the attribute value or NULL if not found. + * It's up to the caller to free the memory with xmlFree(). + */ +xmlChar * +xmlGetNsProp(xmlNodePtr node, const xmlChar *name, const xmlChar *nameSpace) { + xmlAttrPtr prop; + + prop = xmlGetPropNodeInternal(node, name, nameSpace, xmlCheckDTD); + if (prop == NULL) + return(NULL); + return(xmlGetPropNodeValueInternal(prop)); +} + +#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) +/** + * xmlUnsetProp: + * @node: the node + * @name: the attribute name + * + * Remove an attribute carried by a node. + * This handles only attributes in no namespace. + * Returns 0 if successful, -1 if not found + */ +int +xmlUnsetProp(xmlNodePtr node, const xmlChar *name) { + xmlAttrPtr prop; + + prop = xmlGetPropNodeInternal(node, name, NULL, 0); + if (prop == NULL) + return(-1); + xmlUnlinkNode((xmlNodePtr) prop); + xmlFreeProp(prop); + return(0); +} + +/** + * xmlUnsetNsProp: + * @node: the node + * @ns: the namespace definition + * @name: the attribute name + * + * Remove an attribute carried by a node. + * Returns 0 if successful, -1 if not found + */ +int +xmlUnsetNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name) { + xmlAttrPtr prop; + + prop = xmlGetPropNodeInternal(node, name, (ns != NULL) ? ns->href : NULL, 0); + if (prop == NULL) + return(-1); + xmlUnlinkNode((xmlNodePtr) prop); + xmlFreeProp(prop); + return(0); +} +#endif + +#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XINCLUDE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) || defined(LIBXML_HTML_ENABLED) +/** + * xmlSetProp: + * @node: the node + * @name: the attribute name (a QName) + * @value: the attribute value + * + * Set (or reset) an attribute carried by a node. + * If @name has a prefix, then the corresponding + * namespace-binding will be used, if in scope; it is an + * error it there's no such ns-binding for the prefix in + * scope. + * Returns the attribute pointer. + * + */ +xmlAttrPtr +xmlSetProp(xmlNodePtr node, const xmlChar *name, const xmlChar *value) { + int len; + const xmlChar *nqname; + + if ((node == NULL) || (name == NULL) || (node->type != XML_ELEMENT_NODE)) + return(NULL); + + /* + * handle QNames + */ + nqname = xmlSplitQName3(name, &len); + if (nqname != NULL) { + xmlNsPtr ns; + xmlChar *prefix = xmlStrndup(name, len); + ns = xmlSearchNs(node->doc, node, prefix); + if (prefix != NULL) + xmlFree(prefix); + if (ns != NULL) + return(xmlSetNsProp(node, ns, nqname, value)); + } + return(xmlSetNsProp(node, NULL, name, value)); +} + +/** + * xmlSetNsProp: + * @node: the node + * @ns: the namespace definition + * @name: the attribute name + * @value: the attribute value + * + * Set (or reset) an attribute carried by a node. + * The ns structure must be in scope, this is not checked + * + * Returns the attribute pointer. + */ +xmlAttrPtr +xmlSetNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name, + const xmlChar *value) +{ + xmlAttrPtr prop; + + if (ns && (ns->href == NULL)) + return(NULL); + prop = xmlGetPropNodeInternal(node, name, (ns != NULL) ? ns->href : NULL, 0); + if (prop != NULL) { + /* + * Modify the attribute's value. + */ + if (prop->atype == XML_ATTRIBUTE_ID) { + xmlRemoveID(node->doc, prop); + prop->atype = XML_ATTRIBUTE_ID; + } + if (prop->children != NULL) + xmlFreeNodeList(prop->children); + prop->children = NULL; + prop->last = NULL; + prop->ns = ns; + if (value != NULL) { + xmlChar *buffer; + xmlNodePtr tmp; + + buffer = xmlEncodeEntitiesReentrant(node->doc, value); + prop->children = xmlStringGetNodeList(node->doc, buffer); + prop->last = NULL; + tmp = prop->children; + while (tmp != NULL) { + tmp->parent = (xmlNodePtr) prop; + if (tmp->next == NULL) + prop->last = tmp; + tmp = tmp->next; + } + xmlFree(buffer); + } + if (prop->atype == XML_ATTRIBUTE_ID) + xmlAddID(NULL, node->doc, value, prop); + return(prop); + } + /* + * No equal attr found; create a new one. + */ + return(xmlNewPropInternal(node, ns, name, value, 0)); +} + +#endif /* LIBXML_TREE_ENABLED */ + +/** + * xmlNodeIsText: + * @node: the node + * + * Is this node a Text node ? + * Returns 1 yes, 0 no + */ +int +xmlNodeIsText(xmlNodePtr node) { + if (node == NULL) return(0); + + if (node->type == XML_TEXT_NODE) return(1); + return(0); +} + +/** + * xmlIsBlankNode: + * @node: the node + * + * Checks whether this node is an empty or whitespace only + * (and possibly ignorable) text-node. + * + * Returns 1 yes, 0 no + */ +int +xmlIsBlankNode(xmlNodePtr node) { + const xmlChar *cur; + if (node == NULL) return(0); + + if ((node->type != XML_TEXT_NODE) && + (node->type != XML_CDATA_SECTION_NODE)) + return(0); + if (node->content == NULL) return(1); + cur = node->content; + while (*cur != 0) { + if (!IS_BLANK_CH(*cur)) return(0); + cur++; + } + + return(1); +} + +/** + * xmlTextConcat: + * @node: the node + * @content: the content + * @len: @content length + * + * Concat the given string at the end of the existing node content + * + * Returns -1 in case of error, 0 otherwise + */ + +int +xmlTextConcat(xmlNodePtr node, const xmlChar *content, int len) { + if (node == NULL) return(-1); + + if ((node->type != XML_TEXT_NODE) && + (node->type != XML_CDATA_SECTION_NODE) && + (node->type != XML_COMMENT_NODE) && + (node->type != XML_PI_NODE)) { +#ifdef DEBUG_TREE + xmlGenericError(xmlGenericErrorContext, + "xmlTextConcat: node is not text nor CDATA\n"); +#endif + return(-1); + } + /* need to check if content is currently in the dictionary */ + if ((node->content == (xmlChar *) &(node->properties)) || + ((node->doc != NULL) && (node->doc->dict != NULL) && + xmlDictOwns(node->doc->dict, node->content))) { + node->content = xmlStrncatNew(node->content, content, len); + } else { + node->content = xmlStrncat(node->content, content, len); + } + node->properties = NULL; + if (node->content == NULL) + return(-1); + return(0); +} + +/************************************************************************ + * * + * Output : to a FILE or in memory * + * * + ************************************************************************/ + +/** + * xmlBufferCreate: + * + * routine to create an XML buffer. + * returns the new structure. + */ +xmlBufferPtr +xmlBufferCreate(void) { + xmlBufferPtr ret; + + ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer)); + if (ret == NULL) { + xmlTreeErrMemory("creating buffer"); + return(NULL); + } + ret->use = 0; + ret->size = xmlDefaultBufferSize; + ret->alloc = xmlBufferAllocScheme; + ret->content = (xmlChar *) xmlMallocAtomic(ret->size * sizeof(xmlChar)); + if (ret->content == NULL) { + xmlTreeErrMemory("creating buffer"); + xmlFree(ret); + return(NULL); + } + ret->content[0] = 0; + return(ret); +} + +/** + * xmlBufferCreateSize: + * @size: initial size of buffer + * + * routine to create an XML buffer. + * returns the new structure. + */ +xmlBufferPtr +xmlBufferCreateSize(size_t size) { + xmlBufferPtr ret; + + ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer)); + if (ret == NULL) { + xmlTreeErrMemory("creating buffer"); + return(NULL); + } + ret->use = 0; + ret->alloc = xmlBufferAllocScheme; + ret->size = (size ? size+2 : 0); /* +1 for ending null */ + if (ret->size){ + ret->content = (xmlChar *) xmlMallocAtomic(ret->size * sizeof(xmlChar)); + if (ret->content == NULL) { + xmlTreeErrMemory("creating buffer"); + xmlFree(ret); + return(NULL); + } + ret->content[0] = 0; + } else + ret->content = NULL; + return(ret); +} + +/** + * xmlBufferCreateStatic: + * @mem: the memory area + * @size: the size in byte + * + * routine to create an XML buffer from an immutable memory area. + * The area won't be modified nor copied, and is expected to be + * present until the end of the buffer lifetime. + * + * returns the new structure. + */ +xmlBufferPtr +xmlBufferCreateStatic(void *mem, size_t size) { + xmlBufferPtr ret; + + if ((mem == NULL) || (size == 0)) + return(NULL); + + ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer)); + if (ret == NULL) { + xmlTreeErrMemory("creating buffer"); + return(NULL); + } + ret->use = size; + ret->size = size; + ret->alloc = XML_BUFFER_ALLOC_IMMUTABLE; + ret->content = (xmlChar *) mem; + return(ret); +} + +/** + * xmlBufferSetAllocationScheme: + * @buf: the buffer to tune + * @scheme: allocation scheme to use + * + * Sets the allocation scheme for this buffer + */ +void +xmlBufferSetAllocationScheme(xmlBufferPtr buf, + xmlBufferAllocationScheme scheme) { + if (buf == NULL) { +#ifdef DEBUG_BUFFER + xmlGenericError(xmlGenericErrorContext, + "xmlBufferSetAllocationScheme: buf == NULL\n"); +#endif + return; + } + if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return; + + buf->alloc = scheme; +} + +/** + * xmlBufferFree: + * @buf: the buffer to free + * + * Frees an XML buffer. It frees both the content and the structure which + * encapsulate it. + */ +void +xmlBufferFree(xmlBufferPtr buf) { + if (buf == NULL) { +#ifdef DEBUG_BUFFER + xmlGenericError(xmlGenericErrorContext, + "xmlBufferFree: buf == NULL\n"); +#endif + return; + } + + if ((buf->content != NULL) && + (buf->alloc != XML_BUFFER_ALLOC_IMMUTABLE)) { + xmlFree(buf->content); + } + xmlFree(buf); +} + +/** + * xmlBufferEmpty: + * @buf: the buffer + * + * empty a buffer. + */ +void +xmlBufferEmpty(xmlBufferPtr buf) { + if (buf == NULL) return; + if (buf->content == NULL) return; + buf->use = 0; + if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) { + buf->content = BAD_CAST ""; + } else { + memset(buf->content, 0, buf->size); + } +} + +/** + * xmlBufferShrink: + * @buf: the buffer to dump + * @len: the number of xmlChar to remove + * + * Remove the beginning of an XML buffer. + * + * Returns the number of #xmlChar removed, or -1 in case of failure. + */ +int +xmlBufferShrink(xmlBufferPtr buf, unsigned int len) { + if (buf == NULL) return(-1); + if (len == 0) return(0); + if (len > buf->use) return(-1); + + buf->use -= len; + if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) { + buf->content += len; + } else { + memmove(buf->content, &buf->content[len], buf->use * sizeof(xmlChar)); + buf->content[buf->use] = 0; + } + return(len); +} + +/** + * xmlBufferGrow: + * @buf: the buffer + * @len: the minimum free size to allocate + * + * Grow the available space of an XML buffer. + * + * Returns the new available space or -1 in case of error + */ +int +xmlBufferGrow(xmlBufferPtr buf, unsigned int len) { + int size; + xmlChar *newbuf; + + if (buf == NULL) return(-1); + + if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return(0); + if (len + buf->use < buf->size) return(0); + +/* + * Windows has a BIG problem on realloc timing, so we try to double + * the buffer size (if that's enough) (bug 146697) + */ +#ifdef WIN32 + if (buf->size > len) + size = buf->size * 2; + else + size = buf->use + len + 100; +#else + size = buf->use + len + 100; +#endif + + newbuf = (xmlChar *) xmlRealloc(buf->content, size); + if (newbuf == NULL) { + xmlTreeErrMemory("growing buffer"); + return(-1); + } + buf->content = newbuf; + buf->size = size; + return(buf->size - buf->use); +} + +/** + * xmlBufferDump: + * @file: the file output + * @buf: the buffer to dump + * + * Dumps an XML buffer to a FILE *. + * Returns the number of #xmlChar written + */ +int +xmlBufferDump(FILE *file, xmlBufferPtr buf) { + int ret; + + if (buf == NULL) { +#ifdef DEBUG_BUFFER + xmlGenericError(xmlGenericErrorContext, + "xmlBufferDump: buf == NULL\n"); +#endif + return(0); + } + if (buf->content == NULL) { +#ifdef DEBUG_BUFFER + xmlGenericError(xmlGenericErrorContext, + "xmlBufferDump: buf->content == NULL\n"); +#endif + return(0); + } + if (file == NULL) + file = stdout; + ret = fwrite(buf->content, sizeof(xmlChar), buf->use, file); + return(ret); +} + +/** + * xmlBufferContent: + * @buf: the buffer + * + * Function to extract the content of a buffer + * + * Returns the internal content + */ + +const xmlChar * +xmlBufferContent(const xmlBufferPtr buf) +{ + if(!buf) + return NULL; + + return buf->content; +} + +/** + * xmlBufferLength: + * @buf: the buffer + * + * Function to get the length of a buffer + * + * Returns the length of data in the internal content + */ + +int +xmlBufferLength(const xmlBufferPtr buf) +{ + if(!buf) + return 0; + + return buf->use; +} + +/** + * xmlBufferResize: + * @buf: the buffer to resize + * @size: the desired size + * + * Resize a buffer to accommodate minimum size of @size. + * + * Returns 0 in case of problems, 1 otherwise + */ +int +xmlBufferResize(xmlBufferPtr buf, unsigned int size) +{ + unsigned int newSize; + xmlChar* rebuf = NULL; + + if (buf == NULL) + return(0); + + if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return(0); + + /* Don't resize if we don't have to */ + if (size < buf->size) + return 1; + + /* figure out new size */ + switch (buf->alloc){ + case XML_BUFFER_ALLOC_DOUBLEIT: + /*take care of empty case*/ + newSize = (buf->size ? buf->size*2 : size + 10); + while (size > newSize) newSize *= 2; + break; + case XML_BUFFER_ALLOC_EXACT: + newSize = size+10; + break; + default: + newSize = size+10; + break; + } + + if (buf->content == NULL) + rebuf = (xmlChar *) xmlMallocAtomic(newSize * sizeof(xmlChar)); + else if (buf->size - buf->use < 100) { + rebuf = (xmlChar *) xmlRealloc(buf->content, + newSize * sizeof(xmlChar)); + } else { + /* + * if we are reallocating a buffer far from being full, it's + * better to make a new allocation and copy only the used range + * and free the old one. + */ + rebuf = (xmlChar *) xmlMallocAtomic(newSize * sizeof(xmlChar)); + if (rebuf != NULL) { + memcpy(rebuf, buf->content, buf->use); + xmlFree(buf->content); + rebuf[buf->use] = 0; + } + } + if (rebuf == NULL) { + xmlTreeErrMemory("growing buffer"); + return 0; + } + buf->content = rebuf; + buf->size = newSize; + + return 1; +} + +/** + * xmlBufferAdd: + * @buf: the buffer to dump + * @str: the #xmlChar string + * @len: the number of #xmlChar to add + * + * Add a string range to an XML buffer. if len == -1, the length of + * str is recomputed. + * + * Returns 0 successful, a positive error code number otherwise + * and -1 in case of internal or API error. + */ +int +xmlBufferAdd(xmlBufferPtr buf, const xmlChar *str, int len) { + unsigned int needSize; + + if ((str == NULL) || (buf == NULL)) { + return -1; + } + if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return -1; + if (len < -1) { +#ifdef DEBUG_BUFFER + xmlGenericError(xmlGenericErrorContext, + "xmlBufferAdd: len < 0\n"); +#endif + return -1; + } + if (len == 0) return 0; + + if (len < 0) + len = xmlStrlen(str); + + if (len <= 0) return -1; + + needSize = buf->use + len + 2; + if (needSize > buf->size){ + if (!xmlBufferResize(buf, needSize)){ + xmlTreeErrMemory("growing buffer"); + return XML_ERR_NO_MEMORY; + } + } + + memmove(&buf->content[buf->use], str, len*sizeof(xmlChar)); + buf->use += len; + buf->content[buf->use] = 0; + return 0; +} + +/** + * xmlBufferAddHead: + * @buf: the buffer + * @str: the #xmlChar string + * @len: the number of #xmlChar to add + * + * Add a string range to the beginning of an XML buffer. + * if len == -1, the length of @str is recomputed. + * + * Returns 0 successful, a positive error code number otherwise + * and -1 in case of internal or API error. + */ +int +xmlBufferAddHead(xmlBufferPtr buf, const xmlChar *str, int len) { + unsigned int needSize; + + if (buf == NULL) + return(-1); + if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return -1; + if (str == NULL) { +#ifdef DEBUG_BUFFER + xmlGenericError(xmlGenericErrorContext, + "xmlBufferAddHead: str == NULL\n"); +#endif + return -1; + } + if (len < -1) { +#ifdef DEBUG_BUFFER + xmlGenericError(xmlGenericErrorContext, + "xmlBufferAddHead: len < 0\n"); +#endif + return -1; + } + if (len == 0) return 0; + + if (len < 0) + len = xmlStrlen(str); + + if (len <= 0) return -1; + + needSize = buf->use + len + 2; + if (needSize > buf->size){ + if (!xmlBufferResize(buf, needSize)){ + xmlTreeErrMemory("growing buffer"); + return XML_ERR_NO_MEMORY; + } + } + + memmove(&buf->content[len], &buf->content[0], buf->use * sizeof(xmlChar)); + memmove(&buf->content[0], str, len * sizeof(xmlChar)); + buf->use += len; + buf->content[buf->use] = 0; + return 0; +} + +/** + * xmlBufferCat: + * @buf: the buffer to add to + * @str: the #xmlChar string + * + * Append a zero terminated string to an XML buffer. + * + * Returns 0 successful, a positive error code number otherwise + * and -1 in case of internal or API error. + */ +int +xmlBufferCat(xmlBufferPtr buf, const xmlChar *str) { + if (buf == NULL) + return(-1); + if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return -1; + if (str == NULL) return -1; + return xmlBufferAdd(buf, str, -1); +} + +/** + * xmlBufferCCat: + * @buf: the buffer to dump + * @str: the C char string + * + * Append a zero terminated C string to an XML buffer. + * + * Returns 0 successful, a positive error code number otherwise + * and -1 in case of internal or API error. + */ +int +xmlBufferCCat(xmlBufferPtr buf, const char *str) { + const char *cur; + + if (buf == NULL) + return(-1); + if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return -1; + if (str == NULL) { +#ifdef DEBUG_BUFFER + xmlGenericError(xmlGenericErrorContext, + "xmlBufferCCat: str == NULL\n"); +#endif + return -1; + } + for (cur = str;*cur != 0;cur++) { + if (buf->use + 10 >= buf->size) { + if (!xmlBufferResize(buf, buf->use+10)){ + xmlTreeErrMemory("growing buffer"); + return XML_ERR_NO_MEMORY; + } + } + buf->content[buf->use++] = *cur; + } + buf->content[buf->use] = 0; + return 0; +} + +/** + * xmlBufferWriteCHAR: + * @buf: the XML buffer + * @string: the string to add + * + * routine which manages and grows an output buffer. This one adds + * xmlChars at the end of the buffer. + */ +void +xmlBufferWriteCHAR(xmlBufferPtr buf, const xmlChar *string) { + if (buf == NULL) + return; + if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return; + xmlBufferCat(buf, string); +} + +/** + * xmlBufferWriteChar: + * @buf: the XML buffer output + * @string: the string to add + * + * routine which manage and grows an output buffer. This one add + * C chars at the end of the array. + */ +void +xmlBufferWriteChar(xmlBufferPtr buf, const char *string) { + if (buf == NULL) + return; + if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return; + xmlBufferCCat(buf, string); +} + + +/** + * xmlBufferWriteQuotedString: + * @buf: the XML buffer output + * @string: the string to add + * + * routine which manage and grows an output buffer. This one writes + * a quoted or double quoted #xmlChar string, checking first if it holds + * quote or double-quotes internally + */ +void +xmlBufferWriteQuotedString(xmlBufferPtr buf, const xmlChar *string) { + const xmlChar *cur, *base; + if (buf == NULL) + return; + if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return; + if (xmlStrchr(string, '\"')) { + if (xmlStrchr(string, '\'')) { +#ifdef DEBUG_BUFFER + xmlGenericError(xmlGenericErrorContext, + "xmlBufferWriteQuotedString: string contains quote and double-quotes !\n"); +#endif + xmlBufferCCat(buf, "\""); + base = cur = string; + while(*cur != 0){ + if(*cur == '"'){ + if (base != cur) + xmlBufferAdd(buf, base, cur - base); + xmlBufferAdd(buf, BAD_CAST """, 6); + cur++; + base = cur; + } + else { + cur++; + } + } + if (base != cur) + xmlBufferAdd(buf, base, cur - base); + xmlBufferCCat(buf, "\""); + } + else{ + xmlBufferCCat(buf, "\'"); + xmlBufferCat(buf, string); + xmlBufferCCat(buf, "\'"); + } + } else { + xmlBufferCCat(buf, "\""); + xmlBufferCat(buf, string); + xmlBufferCCat(buf, "\""); + } +} + + +/** + * xmlGetDocCompressMode: + * @doc: the document + * + * get the compression ratio for a document, ZLIB based + * Returns 0 (uncompressed) to 9 (max compression) + */ +int +xmlGetDocCompressMode (xmlDocPtr doc) { + if (doc == NULL) return(-1); + return(doc->compression); +} + +/** + * xmlSetDocCompressMode: + * @doc: the document + * @mode: the compression ratio + * + * set the compression ratio for a document, ZLIB based + * Correct values: 0 (uncompressed) to 9 (max compression) + */ +void +xmlSetDocCompressMode (xmlDocPtr doc, int mode) { + if (doc == NULL) return; + if (mode < 0) doc->compression = 0; + else if (mode > 9) doc->compression = 9; + else doc->compression = mode; +} + +/** + * xmlGetCompressMode: + * + * get the default compression mode used, ZLIB based. + * Returns 0 (uncompressed) to 9 (max compression) + */ +int +xmlGetCompressMode(void) +{ + return (xmlCompressMode); +} + +/** + * xmlSetCompressMode: + * @mode: the compression ratio + * + * set the default compression mode used, ZLIB based + * Correct values: 0 (uncompressed) to 9 (max compression) + */ +void +xmlSetCompressMode(int mode) { + if (mode < 0) xmlCompressMode = 0; + else if (mode > 9) xmlCompressMode = 9; + else xmlCompressMode = mode; +} + +#define XML_TREE_NSMAP_PARENT -1 +#define XML_TREE_NSMAP_XML -2 +#define XML_TREE_NSMAP_DOC -3 +#define XML_TREE_NSMAP_CUSTOM -4 + +typedef struct xmlNsMapItem *xmlNsMapItemPtr; +struct xmlNsMapItem { + xmlNsMapItemPtr next; + xmlNsMapItemPtr prev; + xmlNsPtr oldNs; /* old ns decl reference */ + xmlNsPtr newNs; /* new ns decl reference */ + int shadowDepth; /* Shadowed at this depth */ + /* + * depth: + * >= 0 == @node's ns-decls + * -1 == @parent's ns-decls + * -2 == the doc->oldNs XML ns-decl + * -3 == the doc->oldNs storage ns-decls + * -4 == ns-decls provided via custom ns-handling + */ + int depth; +}; + +typedef struct xmlNsMap *xmlNsMapPtr; +struct xmlNsMap { + xmlNsMapItemPtr first; + xmlNsMapItemPtr last; + xmlNsMapItemPtr pool; +}; + +#define XML_NSMAP_NOTEMPTY(m) (((m) != NULL) && ((m)->first != NULL)) +#define XML_NSMAP_FOREACH(m, i) for (i = (m)->first; i != NULL; i = (i)->next) +#define XML_NSMAP_POP(m, i) \ + i = (m)->last; \ + (m)->last = (i)->prev; \ + if ((m)->last == NULL) \ + (m)->first = NULL; \ + else \ + (m)->last->next = NULL; \ + (i)->next = (m)->pool; \ + (m)->pool = i; + +/* +* xmlDOMWrapNsMapFree: +* @map: the ns-map +* +* Frees the ns-map +*/ +static void +xmlDOMWrapNsMapFree(xmlNsMapPtr nsmap) +{ + xmlNsMapItemPtr cur, tmp; + + if (nsmap == NULL) + return; + cur = nsmap->pool; + while (cur != NULL) { + tmp = cur; + cur = cur->next; + xmlFree(tmp); + } + cur = nsmap->first; + while (cur != NULL) { + tmp = cur; + cur = cur->next; + xmlFree(tmp); + } + xmlFree(nsmap); +} + +/* +* xmlDOMWrapNsMapAddItem: +* @map: the ns-map +* @oldNs: the old ns-struct +* @newNs: the new ns-struct +* @depth: depth and ns-kind information +* +* Adds an ns-mapping item. +*/ +static xmlNsMapItemPtr +xmlDOMWrapNsMapAddItem(xmlNsMapPtr *nsmap, int position, + xmlNsPtr oldNs, xmlNsPtr newNs, int depth) +{ + xmlNsMapItemPtr ret; + xmlNsMapPtr map; + + if (nsmap == NULL) + return(NULL); + if ((position != -1) && (position != 0)) + return(NULL); + map = *nsmap; + + if (map == NULL) { + /* + * Create the ns-map. + */ + map = (xmlNsMapPtr) xmlMalloc(sizeof(struct xmlNsMap)); + if (map == NULL) { + xmlTreeErrMemory("allocating namespace map"); + return (NULL); + } + memset(map, 0, sizeof(struct xmlNsMap)); + *nsmap = map; + } + + if (map->pool != NULL) { + /* + * Reuse an item from the pool. + */ + ret = map->pool; + map->pool = ret->next; + memset(ret, 0, sizeof(struct xmlNsMapItem)); + } else { + /* + * Create a new item. + */ + ret = (xmlNsMapItemPtr) xmlMalloc(sizeof(struct xmlNsMapItem)); + if (ret == NULL) { + xmlTreeErrMemory("allocating namespace map item"); + return (NULL); + } + memset(ret, 0, sizeof(struct xmlNsMapItem)); + } + + if (map->first == NULL) { + /* + * First ever. + */ + map->first = ret; + map->last = ret; + } else if (position == -1) { + /* + * Append. + */ + ret->prev = map->last; + map->last->next = ret; + map->last = ret; + } else if (position == 0) { + /* + * Set on first position. + */ + map->first->prev = ret; + ret->next = map->first; + map->first = ret; + } else + return(NULL); + + ret->oldNs = oldNs; + ret->newNs = newNs; + ret->shadowDepth = -1; + ret->depth = depth; + return (ret); +} + +/* +* xmlDOMWrapStoreNs: +* @doc: the doc +* @nsName: the namespace name +* @prefix: the prefix +* +* Creates or reuses an xmlNs struct on doc->oldNs with +* the given prefix and namespace name. +* +* Returns the aquired ns struct or NULL in case of an API +* or internal error. +*/ +static xmlNsPtr +xmlDOMWrapStoreNs(xmlDocPtr doc, + const xmlChar *nsName, + const xmlChar *prefix) +{ + xmlNsPtr ns; + + if (doc == NULL) + return (NULL); + ns = xmlTreeEnsureXMLDecl(doc); + if (ns == NULL) + return (NULL); + if (ns->next != NULL) { + /* Reuse. */ + ns = ns->next; + while (ns != NULL) { + if (((ns->prefix == prefix) || + xmlStrEqual(ns->prefix, prefix)) && + xmlStrEqual(ns->href, nsName)) { + return (ns); + } + if (ns->next == NULL) + break; + ns = ns->next; + } + } + /* Create. */ + ns->next = xmlNewNs(NULL, nsName, prefix); + return (ns->next); +} + +/* +* xmlDOMWrapNewCtxt: +* +* Allocates and initializes a new DOM-wrapper context. +* +* Returns the xmlDOMWrapCtxtPtr or NULL in case of an internal errror. +*/ +xmlDOMWrapCtxtPtr +xmlDOMWrapNewCtxt(void) +{ + xmlDOMWrapCtxtPtr ret; + + ret = xmlMalloc(sizeof(xmlDOMWrapCtxt)); + if (ret == NULL) { + xmlTreeErrMemory("allocating DOM-wrapper context"); + return (NULL); + } + memset(ret, 0, sizeof(xmlDOMWrapCtxt)); + return (ret); +} + +/* +* xmlDOMWrapFreeCtxt: +* @ctxt: the DOM-wrapper context +* +* Frees the DOM-wrapper context. +*/ +void +xmlDOMWrapFreeCtxt(xmlDOMWrapCtxtPtr ctxt) +{ + if (ctxt == NULL) + return; + if (ctxt->namespaceMap != NULL) + xmlDOMWrapNsMapFree((xmlNsMapPtr) ctxt->namespaceMap); + /* + * TODO: Store the namespace map in the context. + */ + xmlFree(ctxt); +} + +/* +* xmlTreeLookupNsListByPrefix: +* @nsList: a list of ns-structs +* @prefix: the searched prefix +* +* Searches for a ns-decl with the given prefix in @nsList. +* +* Returns the ns-decl if found, NULL if not found and on +* API errors. +*/ +static xmlNsPtr +xmlTreeNSListLookupByPrefix(xmlNsPtr nsList, const xmlChar *prefix) +{ + if (nsList == NULL) + return (NULL); + { + xmlNsPtr ns; + ns = nsList; + do { + if ((prefix == ns->prefix) || + xmlStrEqual(prefix, ns->prefix)) { + return (ns); + } + ns = ns->next; + } while (ns != NULL); + } + return (NULL); +} + +/* +* +* xmlDOMWrapNSNormGatherInScopeNs: +* @map: the namespace map +* @node: the node to start with +* +* Puts in-scope namespaces into the ns-map. +* +* Returns 0 on success, -1 on API or internal errors. +*/ +static int +xmlDOMWrapNSNormGatherInScopeNs(xmlNsMapPtr *map, + xmlNodePtr node) +{ + xmlNodePtr cur; + xmlNsPtr ns; + xmlNsMapItemPtr mi; + int shadowed; + + if ((map == NULL) || (*map != NULL)) + return (-1); + /* + * Get in-scope ns-decls of @parent. + */ + cur = node; + while ((cur != NULL) && (cur != (xmlNodePtr) cur->doc)) { + if (cur->type == XML_ELEMENT_NODE) { + if (cur->nsDef != NULL) { + ns = cur->nsDef; + do { + shadowed = 0; + if (XML_NSMAP_NOTEMPTY(*map)) { + /* + * Skip shadowed prefixes. + */ + XML_NSMAP_FOREACH(*map, mi) { + if ((ns->prefix == mi->newNs->prefix) || + xmlStrEqual(ns->prefix, mi->newNs->prefix)) { + shadowed = 1; + break; + } + } + } + /* + * Insert mapping. + */ + mi = xmlDOMWrapNsMapAddItem(map, 0, NULL, + ns, XML_TREE_NSMAP_PARENT); + if (mi == NULL) + return (-1); + if (shadowed) + mi->shadowDepth = 0; + ns = ns->next; + } while (ns != NULL); + } + } + cur = cur->parent; + } + return (0); +} + +/* +* XML_TREE_ADOPT_STR: If we have a dest-dict, put @str in the dict; +* otherwise copy it, when it was in the source-dict. +*/ +#define XML_TREE_ADOPT_STR(str) \ + if (adoptStr && (str != NULL)) { \ + if (destDoc->dict) { \ + const xmlChar *old = str; \ + str = xmlDictLookup(destDoc->dict, str, -1); \ + if ((sourceDoc == NULL) || (sourceDoc->dict == NULL) || \ + (!xmlDictOwns(sourceDoc->dict, old))) \ + xmlFree((char *)old); \ + } else if ((sourceDoc) && (sourceDoc->dict) && \ + xmlDictOwns(sourceDoc->dict, str)) { \ + str = BAD_CAST xmlStrdup(str); \ + } \ + } + +/* +* XML_TREE_ADOPT_STR_2: If @str was in the source-dict, then +* put it in dest-dict or copy it. +*/ +#define XML_TREE_ADOPT_STR_2(str) \ + if (adoptStr && (str != NULL) && (sourceDoc != NULL) && \ + (sourceDoc->dict != NULL) && \ + xmlDictOwns(sourceDoc->dict, cur->content)) { \ + if (destDoc->dict) \ + cur->content = (xmlChar *) \ + xmlDictLookup(destDoc->dict, cur->content, -1); \ + else \ + cur->content = xmlStrdup(BAD_CAST cur->content); \ + } + +/* +* xmlDOMWrapNSNormAddNsMapItem2: +* +* For internal use. Adds a ns-decl mapping. +* +* Returns 0 on success, -1 on internal errors. +*/ +static int +xmlDOMWrapNSNormAddNsMapItem2(xmlNsPtr **list, int *size, int *number, + xmlNsPtr oldNs, xmlNsPtr newNs) +{ + if (*list == NULL) { + *list = (xmlNsPtr *) xmlMalloc(6 * sizeof(xmlNsPtr)); + if (*list == NULL) { + xmlTreeErrMemory("alloc ns map item"); + return(-1); + } + *size = 3; + *number = 0; + } else if ((*number) >= (*size)) { + *size *= 2; + *list = (xmlNsPtr *) xmlRealloc(*list, + (*size) * 2 * sizeof(xmlNsPtr)); + if (*list == NULL) { + xmlTreeErrMemory("realloc ns map item"); + return(-1); + } + } + (*list)[2 * (*number)] = oldNs; + (*list)[2 * (*number) +1] = newNs; + (*number)++; + return (0); +} + +/* +* xmlDOMWrapRemoveNode: +* @ctxt: a DOM wrapper context +* @doc: the doc +* @node: the node to be removed. +* @options: set of options, unused at the moment +* +* Unlinks the given node from its owner. +* This will substitute ns-references to node->nsDef for +* ns-references to doc->oldNs, thus ensuring the removed +* branch to be autark wrt ns-references. +* +* NOTE: This function was not intensively tested. +* +* Returns 0 on success, 1 if the node is not supported, +* -1 on API and internal errors. +*/ +int +xmlDOMWrapRemoveNode(xmlDOMWrapCtxtPtr ctxt, xmlDocPtr doc, + xmlNodePtr node, int options ATTRIBUTE_UNUSED) +{ + xmlNsPtr *list = NULL; + int sizeList, nbList, i, j; + xmlNsPtr ns; + + if ((node == NULL) || (doc == NULL) || (node->doc != doc)) + return (-1); + + /* TODO: 0 or -1 ? */ + if (node->parent == NULL) + return (0); + + switch (node->type) { + case XML_TEXT_NODE: + case XML_CDATA_SECTION_NODE: + case XML_ENTITY_REF_NODE: + case XML_PI_NODE: + case XML_COMMENT_NODE: + xmlUnlinkNode(node); + return (0); + case XML_ELEMENT_NODE: + case XML_ATTRIBUTE_NODE: + break; + default: + return (1); + } + xmlUnlinkNode(node); + /* + * Save out-of-scope ns-references in doc->oldNs. + */ + do { + switch (node->type) { + case XML_ELEMENT_NODE: + if ((ctxt == NULL) && (node->nsDef != NULL)) { + ns = node->nsDef; + do { + if (xmlDOMWrapNSNormAddNsMapItem2(&list, &sizeList, + &nbList, ns, ns) == -1) + goto internal_error; + ns = ns->next; + } while (ns != NULL); + } + /* No break on purpose. */ + case XML_ATTRIBUTE_NODE: + if (node->ns != NULL) { + /* + * Find a mapping. + */ + if (list != NULL) { + for (i = 0, j = 0; i < nbList; i++, j += 2) { + if (node->ns == list[j]) { + node->ns = list[++j]; + goto next_node; + } + } + } + ns = NULL; + if (ctxt != NULL) { + /* + * User defined. + */ + } else { + /* + * Add to doc's oldNs. + */ + ns = xmlDOMWrapStoreNs(doc, node->ns->href, + node->ns->prefix); + if (ns == NULL) + goto internal_error; + } + if (ns != NULL) { + /* + * Add mapping. + */ + if (xmlDOMWrapNSNormAddNsMapItem2(&list, &sizeList, + &nbList, node->ns, ns) == -1) + goto internal_error; + } + node->ns = ns; + } + if ((node->type == XML_ELEMENT_NODE) && + (node->properties != NULL)) { + node = (xmlNodePtr) node->properties; + continue; + } + break; + default: + goto next_sibling; + } +next_node: + if ((node->type == XML_ELEMENT_NODE) && + (node->children != NULL)) { + node = node->children; + continue; + } +next_sibling: + if (node == NULL) + break; + if (node->next != NULL) + node = node->next; + else { + node = node->parent; + goto next_sibling; + } + } while (node != NULL); + + if (list != NULL) + xmlFree(list); + return (0); + +internal_error: + if (list != NULL) + xmlFree(list); + return (-1); +} + +/* +* xmlSearchNsByNamespaceStrict: +* @doc: the document +* @node: the start node +* @nsName: the searched namespace name +* @retNs: the resulting ns-decl +* @prefixed: if the found ns-decl must have a prefix (for attributes) +* +* Dynamically searches for a ns-declaration which matches +* the given @nsName in the ancestor-or-self axis of @node. +* +* Returns 1 if a ns-decl was found, 0 if not and -1 on API +* and internal errors. +*/ +static int +xmlSearchNsByNamespaceStrict(xmlDocPtr doc, xmlNodePtr node, + const xmlChar* nsName, + xmlNsPtr *retNs, int prefixed) +{ + xmlNodePtr cur, prev = NULL, out = NULL; + xmlNsPtr ns, prevns; + + if ((doc == NULL) || (nsName == NULL) || (retNs == NULL)) + return (-1); + + *retNs = NULL; + if (xmlStrEqual(nsName, XML_XML_NAMESPACE)) { + *retNs = xmlTreeEnsureXMLDecl(doc); + if (*retNs == NULL) + return (-1); + return (1); + } + cur = node; + do { + if (cur->type == XML_ELEMENT_NODE) { + if (cur->nsDef != NULL) { + for (ns = cur->nsDef; ns != NULL; ns = ns->next) { + if (prefixed && (ns->prefix == NULL)) + continue; + if (prev != NULL) { + /* + * Check the last level of ns-decls for a + * shadowing prefix. + */ + prevns = prev->nsDef; + do { + if ((prevns->prefix == ns->prefix) || + ((prevns->prefix != NULL) && + (ns->prefix != NULL) && + xmlStrEqual(prevns->prefix, ns->prefix))) { + /* + * Shadowed. + */ + break; + } + prevns = prevns->next; + } while (prevns != NULL); + if (prevns != NULL) + continue; + } + /* + * Ns-name comparison. + */ + if ((nsName == ns->href) || + xmlStrEqual(nsName, ns->href)) { + /* + * At this point the prefix can only be shadowed, + * if we are the the (at least) 3rd level of + * ns-decls. + */ + if (out) { + int ret; + + ret = xmlNsInScope(doc, node, prev, ns->prefix); + if (ret < 0) + return (-1); + /* + * TODO: Should we try to find a matching ns-name + * only once? This here keeps on searching. + * I think we should try further since, there might + * be an other matching ns-decl with an unshadowed + * prefix. + */ + if (! ret) + continue; + } + *retNs = ns; + return (1); + } + } + out = prev; + prev = cur; + } + } else if ((cur->type == XML_ENTITY_NODE) || + (cur->type == XML_ENTITY_DECL)) + return (0); + cur = cur->parent; + } while ((cur != NULL) && (cur->doc != (xmlDocPtr) cur)); + return (0); +} + +/* +* xmlSearchNsByPrefixStrict: +* @doc: the document +* @node: the start node +* @prefix: the searched namespace prefix +* @retNs: the resulting ns-decl +* +* Dynamically searches for a ns-declaration which matches +* the given @nsName in the ancestor-or-self axis of @node. +* +* Returns 1 if a ns-decl was found, 0 if not and -1 on API +* and internal errors. +*/ +static int +xmlSearchNsByPrefixStrict(xmlDocPtr doc, xmlNodePtr node, + const xmlChar* prefix, + xmlNsPtr *retNs) +{ + xmlNodePtr cur; + xmlNsPtr ns; + + if ((doc == NULL) || (node == NULL)) + return (-1); + + if (retNs) + *retNs = NULL; + if (IS_STR_XML(prefix)) { + if (retNs) { + *retNs = xmlTreeEnsureXMLDecl(doc); + if (*retNs == NULL) + return (-1); + } + return (1); + } + cur = node; + do { + if (cur->type == XML_ELEMENT_NODE) { + if (cur->nsDef != NULL) { + ns = cur->nsDef; + do { + if ((prefix == ns->prefix) || + xmlStrEqual(prefix, ns->prefix)) + { + /* + * Disabled namespaces, e.g. xmlns:abc="". + */ + if (ns->href == NULL) + return(0); + if (retNs) + *retNs = ns; + return (1); + } + ns = ns->next; + } while (ns != NULL); + } + } else if ((cur->type == XML_ENTITY_NODE) || + (cur->type == XML_ENTITY_DECL)) + return (0); + cur = cur->parent; + } while ((cur != NULL) && (cur->doc != (xmlDocPtr) cur)); + return (0); +} + +/* +* xmlDOMWrapNSNormDeclareNsForced: +* @doc: the doc +* @elem: the element-node to declare on +* @nsName: the namespace-name of the ns-decl +* @prefix: the preferred prefix of the ns-decl +* @checkShadow: ensure that the new ns-decl doesn't shadow ancestor ns-decls +* +* Declares a new namespace on @elem. It tries to use the +* given @prefix; if a ns-decl with the given prefix is already existent +* on @elem, it will generate an other prefix. +* +* Returns 1 if a ns-decl was found, 0 if not and -1 on API +* and internal errors. +*/ +static xmlNsPtr +xmlDOMWrapNSNormDeclareNsForced(xmlDocPtr doc, + xmlNodePtr elem, + const xmlChar *nsName, + const xmlChar *prefix, + int checkShadow) +{ + + xmlNsPtr ret; + char buf[50]; + const xmlChar *pref; + int counter = 0; + /* + * Create a ns-decl on @anchor. + */ + pref = prefix; + while (1) { + /* + * Lookup whether the prefix is unused in elem's ns-decls. + */ + if ((elem->nsDef != NULL) && + (xmlTreeNSListLookupByPrefix(elem->nsDef, pref) != NULL)) + goto ns_next_prefix; + if (checkShadow && elem->parent && + ((xmlNodePtr) elem->parent->doc != elem->parent)) { + /* + * Does it shadow ancestor ns-decls? + */ + if (xmlSearchNsByPrefixStrict(doc, elem->parent, pref, NULL) == 1) + goto ns_next_prefix; + } + ret = xmlNewNs(NULL, nsName, pref); + if (ret == NULL) + return (NULL); + if (elem->nsDef == NULL) + elem->nsDef = ret; + else { + xmlNsPtr ns2 = elem->nsDef; + while (ns2->next != NULL) + ns2 = ns2->next; + ns2->next = ret; + } + return (ret); +ns_next_prefix: + counter++; + if (counter > 1000) + return (NULL); + if (prefix == NULL) { + snprintf((char *) buf, sizeof(buf), + "ns_%d", counter); + } else + snprintf((char *) buf, sizeof(buf), + "%.30s_%d", (char *)prefix, counter); + pref = BAD_CAST buf; + } +} + +/* +* xmlDOMWrapNSNormAquireNormalizedNs: +* @doc: the doc +* @elem: the element-node to declare namespaces on +* @ns: the ns-struct to use for the search +* @retNs: the found/created ns-struct +* @nsMap: the ns-map +* @depth: the current tree depth +* @ancestorsOnly: search in ancestor ns-decls only +* @prefixed: if the searched ns-decl must have a prefix (for attributes) +* +* Searches for a matching ns-name in the ns-decls of @nsMap, if not +* found it will either declare it on @elem, or store it in doc->oldNs. +* If a new ns-decl needs to be declared on @elem, it tries to use the +* @ns->prefix for it, if this prefix is already in use on @elem, it will +* change the prefix or the new ns-decl. +* +* Returns 0 if succeeded, -1 otherwise and on API/internal errors. +*/ +static int +xmlDOMWrapNSNormAquireNormalizedNs(xmlDocPtr doc, + xmlNodePtr elem, + xmlNsPtr ns, + xmlNsPtr *retNs, + xmlNsMapPtr *nsMap, + + int depth, + int ancestorsOnly, + int prefixed) +{ + xmlNsMapItemPtr mi; + + if ((doc == NULL) || (ns == NULL) || (retNs == NULL) || + (nsMap == NULL)) + return (-1); + + *retNs = NULL; + /* + * Handle XML namespace. + */ + if (IS_STR_XML(ns->prefix)) { + /* + * Insert XML namespace mapping. + */ + *retNs = xmlTreeEnsureXMLDecl(doc); + if (*retNs == NULL) + return (-1); + return (0); + } + /* + * If the search should be done in ancestors only and no + * @elem (the first ancestor) was specified, then skip the search. + */ + if ((XML_NSMAP_NOTEMPTY(*nsMap)) && + (! (ancestorsOnly && (elem == NULL)))) + { + /* + * Try to find an equal ns-name in in-scope ns-decls. + */ + XML_NSMAP_FOREACH(*nsMap, mi) { + if ((mi->depth >= XML_TREE_NSMAP_PARENT) && + /* + * ancestorsOnly: This should be turned on to gain speed, + * if one knows that the branch itself was already + * ns-wellformed and no stale references existed. + * I.e. it searches in the ancestor axis only. + */ + ((! ancestorsOnly) || (mi->depth == XML_TREE_NSMAP_PARENT)) && + /* Skip shadowed prefixes. */ + (mi->shadowDepth == -1) && + /* Skip xmlns="" or xmlns:foo="". */ + ((mi->newNs->href != NULL) && + (mi->newNs->href[0] != 0)) && + /* Ensure a prefix if wanted. */ + ((! prefixed) || (mi->newNs->prefix != NULL)) && + /* Equal ns name */ + ((mi->newNs->href == ns->href) || + xmlStrEqual(mi->newNs->href, ns->href))) { + /* Set the mapping. */ + mi->oldNs = ns; + *retNs = mi->newNs; + return (0); + } + } + } + /* + * No luck, the namespace is out of scope or shadowed. + */ + if (elem == NULL) { + xmlNsPtr tmpns; + + /* + * Store ns-decls in "oldNs" of the document-node. + */ + tmpns = xmlDOMWrapStoreNs(doc, ns->href, ns->prefix); + if (tmpns == NULL) + return (-1); + /* + * Insert mapping. + */ + if (xmlDOMWrapNsMapAddItem(nsMap, -1, ns, + tmpns, XML_TREE_NSMAP_DOC) == NULL) { + xmlFreeNs(tmpns); + return (-1); + } + *retNs = tmpns; + } else { + xmlNsPtr tmpns; + + tmpns = xmlDOMWrapNSNormDeclareNsForced(doc, elem, ns->href, + ns->prefix, 0); + if (tmpns == NULL) + return (-1); + + if (*nsMap != NULL) { + /* + * Does it shadow ancestor ns-decls? + */ + XML_NSMAP_FOREACH(*nsMap, mi) { + if ((mi->depth < depth) && + (mi->shadowDepth == -1) && + ((ns->prefix == mi->newNs->prefix) || + xmlStrEqual(ns->prefix, mi->newNs->prefix))) { + /* + * Shadows. + */ + mi->shadowDepth = depth; + break; + } + } + } + if (xmlDOMWrapNsMapAddItem(nsMap, -1, ns, tmpns, depth) == NULL) { + xmlFreeNs(tmpns); + return (-1); + } + *retNs = tmpns; + } + return (0); +} + +typedef enum { + XML_DOM_RECONNS_REMOVEREDUND = 1<<0 +} xmlDOMReconcileNSOptions; + +/* +* xmlDOMWrapReconcileNamespaces: +* @ctxt: DOM wrapper context, unused at the moment +* @elem: the element-node +* @options: option flags +* +* Ensures that ns-references point to ns-decls hold on element-nodes. +* Ensures that the tree is namespace wellformed by creating additional +* ns-decls where needed. Note that, since prefixes of already existent +* ns-decls can be shadowed by this process, it could break QNames in +* attribute values or element content. +* +* NOTE: This function was not intensively tested. +* +* Returns 0 if succeeded, -1 otherwise and on API/internal errors. +*/ + +int +xmlDOMWrapReconcileNamespaces(xmlDOMWrapCtxtPtr ctxt ATTRIBUTE_UNUSED, + xmlNodePtr elem, + int options) +{ + int depth = -1, adoptns = 0, parnsdone = 0; + xmlNsPtr ns, prevns; + xmlDocPtr doc; + xmlNodePtr cur, curElem = NULL; + xmlNsMapPtr nsMap = NULL; + xmlNsMapItemPtr /* topmi = NULL, */ mi; + /* @ancestorsOnly should be set by an option flag. */ + int ancestorsOnly = 0; + int optRemoveRedundantNS = + ((xmlDOMReconcileNSOptions) options & XML_DOM_RECONNS_REMOVEREDUND) ? 1 : 0; + xmlNsPtr *listRedund = NULL; + int sizeRedund = 0, nbRedund = 0, ret, i, j; + + if ((elem == NULL) || (elem->doc == NULL) || + (elem->type != XML_ELEMENT_NODE)) + return (-1); + + doc = elem->doc; + cur = elem; + do { + switch (cur->type) { + case XML_ELEMENT_NODE: + adoptns = 1; + curElem = cur; + depth++; + /* + * Namespace declarations. + */ + if (cur->nsDef != NULL) { + prevns = NULL; + ns = cur->nsDef; + while (ns != NULL) { + if (! parnsdone) { + if ((elem->parent) && + ((xmlNodePtr) elem->parent->doc != elem->parent)) { + /* + * Gather ancestor in-scope ns-decls. + */ + if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap, + elem->parent) == -1) + goto internal_error; + } + parnsdone = 1; + } + + /* + * Lookup the ns ancestor-axis for equal ns-decls in scope. + */ + if (optRemoveRedundantNS && XML_NSMAP_NOTEMPTY(nsMap)) { + XML_NSMAP_FOREACH(nsMap, mi) { + if ((mi->depth >= XML_TREE_NSMAP_PARENT) && + (mi->shadowDepth == -1) && + ((ns->prefix == mi->newNs->prefix) || + xmlStrEqual(ns->prefix, mi->newNs->prefix)) && + ((ns->href == mi->newNs->href) || + xmlStrEqual(ns->href, mi->newNs->href))) + { + /* + * A redundant ns-decl was found. + * Add it to the list of redundant ns-decls. + */ + if (xmlDOMWrapNSNormAddNsMapItem2(&listRedund, + &sizeRedund, &nbRedund, ns, mi->newNs) == -1) + goto internal_error; + /* + * Remove the ns-decl from the element-node. + */ + if (prevns) + prevns->next = ns->next; + else + cur->nsDef = ns->next; + goto next_ns_decl; + } + } + } + + /* + * Skip ns-references handling if the referenced + * ns-decl is declared on the same element. + */ + if ((cur->ns != NULL) && adoptns && (cur->ns == ns)) + adoptns = 0; + /* + * Does it shadow any ns-decl? + */ + if (XML_NSMAP_NOTEMPTY(nsMap)) { + XML_NSMAP_FOREACH(nsMap, mi) { + if ((mi->depth >= XML_TREE_NSMAP_PARENT) && + (mi->shadowDepth == -1) && + ((ns->prefix == mi->newNs->prefix) || + xmlStrEqual(ns->prefix, mi->newNs->prefix))) { + + mi->shadowDepth = depth; + } + } + } + /* + * Push mapping. + */ + if (xmlDOMWrapNsMapAddItem(&nsMap, -1, ns, ns, + depth) == NULL) + goto internal_error; + + prevns = ns; +next_ns_decl: + ns = ns->next; + } + } + if (! adoptns) + goto ns_end; + /* No break on purpose. */ + case XML_ATTRIBUTE_NODE: + /* No ns, no fun. */ + if (cur->ns == NULL) + goto ns_end; + + if (! parnsdone) { + if ((elem->parent) && + ((xmlNodePtr) elem->parent->doc != elem->parent)) { + if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap, + elem->parent) == -1) + goto internal_error; + } + parnsdone = 1; + } + /* + * Adjust the reference if this was a redundant ns-decl. + */ + if (listRedund) { + for (i = 0, j = 0; i < nbRedund; i++, j += 2) { + if (cur->ns == listRedund[j]) { + cur->ns = listRedund[++j]; + break; + } + } + } + /* + * Adopt ns-references. + */ + if (XML_NSMAP_NOTEMPTY(nsMap)) { + /* + * Search for a mapping. + */ + XML_NSMAP_FOREACH(nsMap, mi) { + if ((mi->shadowDepth == -1) && + (cur->ns == mi->oldNs)) { + + cur->ns = mi->newNs; + goto ns_end; + } + } + } + /* + * Aquire a normalized ns-decl and add it to the map. + */ + if (xmlDOMWrapNSNormAquireNormalizedNs(doc, curElem, + cur->ns, &ns, + &nsMap, depth, + ancestorsOnly, + (cur->type == XML_ATTRIBUTE_NODE) ? 1 : 0) == -1) + goto internal_error; + cur->ns = ns; + +ns_end: + if ((cur->type == XML_ELEMENT_NODE) && + (cur->properties != NULL)) { + /* + * Process attributes. + */ + cur = (xmlNodePtr) cur->properties; + continue; + } + break; + default: + goto next_sibling; + } +into_content: + if ((cur->type == XML_ELEMENT_NODE) && + (cur->children != NULL)) { + /* + * Process content of element-nodes only. + */ + cur = cur->children; + continue; + } +next_sibling: + if (cur == elem) + break; + if (cur->type == XML_ELEMENT_NODE) { + if (XML_NSMAP_NOTEMPTY(nsMap)) { + /* + * Pop mappings. + */ + while ((nsMap->last != NULL) && + (nsMap->last->depth >= depth)) + { + XML_NSMAP_POP(nsMap, mi) + } + /* + * Unshadow. + */ + XML_NSMAP_FOREACH(nsMap, mi) { + if (mi->shadowDepth >= depth) + mi->shadowDepth = -1; + } + } + depth--; + } + if (cur->next != NULL) + cur = cur->next; + else { + if (cur->type == XML_ATTRIBUTE_NODE) { + cur = cur->parent; + goto into_content; + } + cur = cur->parent; + goto next_sibling; + } + } while (cur != NULL); + + ret = 0; + goto exit; +internal_error: + ret = -1; +exit: + if (listRedund) { + for (i = 0, j = 0; i < nbRedund; i++, j += 2) { + xmlFreeNs(listRedund[j]); + } + xmlFree(listRedund); + } + if (nsMap != NULL) + xmlDOMWrapNsMapFree(nsMap); + return (ret); +} + +/* +* xmlDOMWrapAdoptBranch: +* @ctxt: the optional context for custom processing +* @sourceDoc: the optional sourceDoc +* @node: the element-node to start with +* @destDoc: the destination doc for adoption +* @destParent: the optional new parent of @node in @destDoc +* @options: option flags +* +* Ensures that ns-references point to @destDoc: either to +* elements->nsDef entries if @destParent is given, or to +* @destDoc->oldNs otherwise. +* If @destParent is given, it ensures that the tree is namespace +* wellformed by creating additional ns-decls where needed. +* Note that, since prefixes of already existent ns-decls can be +* shadowed by this process, it could break QNames in attribute +* values or element content. +* +* NOTE: This function was not intensively tested. +* +* Returns 0 if succeeded, -1 otherwise and on API/internal errors. +*/ +static int +xmlDOMWrapAdoptBranch(xmlDOMWrapCtxtPtr ctxt, + xmlDocPtr sourceDoc, + xmlNodePtr node, + xmlDocPtr destDoc, + xmlNodePtr destParent, + int options ATTRIBUTE_UNUSED) +{ + int ret = 0; + xmlNodePtr cur, curElem = NULL; + xmlNsMapPtr nsMap = NULL; + xmlNsMapItemPtr mi; + xmlNsPtr ns = NULL; + int depth = -1, adoptStr = 1; + /* gather @parent's ns-decls. */ + int parnsdone; + /* @ancestorsOnly should be set per option. */ + int ancestorsOnly = 0; + + /* + * Optimize string adoption for equal or none dicts. + */ + if ((sourceDoc != NULL) && + (sourceDoc->dict == destDoc->dict)) + adoptStr = 0; + else + adoptStr = 1; + + /* + * Get the ns-map from the context if available. + */ + if (ctxt) + nsMap = (xmlNsMapPtr) ctxt->namespaceMap; + /* + * Disable search for ns-decls in the parent-axis of the + * desination element, if: + * 1) there's no destination parent + * 2) custom ns-reference handling is used + */ + if ((destParent == NULL) || + (ctxt && ctxt->getNsForNodeFunc)) + { + parnsdone = 1; + } else + parnsdone = 0; + + cur = node; + while (cur != NULL) { + /* + * Paranoid source-doc sanity check. + */ + if (cur->doc != sourceDoc) { + /* + * We'll assume XIncluded nodes if the doc differs. + * TODO: Do we need to reconciliate XIncluded nodes? + * This here skips XIncluded nodes and tries to handle + * broken sequences. + */ + if (cur->next == NULL) + goto leave_node; + do { + cur = cur->next; + if ((cur->type == XML_XINCLUDE_END) || + (cur->doc == node->doc)) + break; + } while (cur->next != NULL); + + if (cur->doc != node->doc) + goto leave_node; + } + cur->doc = destDoc; + switch (cur->type) { + case XML_XINCLUDE_START: + case XML_XINCLUDE_END: + /* + * TODO + */ + return (-1); + case XML_ELEMENT_NODE: + curElem = cur; + depth++; + /* + * Namespace declarations. + * - ns->href and ns->prefix are never in the dict, so + * we need not move the values over to the destination dict. + * - Note that for custom handling of ns-references, + * the ns-decls need not be stored in the ns-map, + * since they won't be referenced by node->ns. + */ + if ((cur->nsDef) && + ((ctxt == NULL) || (ctxt->getNsForNodeFunc == NULL))) + { + if (! parnsdone) { + /* + * Gather @parent's in-scope ns-decls. + */ + if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap, + destParent) == -1) + goto internal_error; + parnsdone = 1; + } + for (ns = cur->nsDef; ns != NULL; ns = ns->next) { + /* + * NOTE: ns->prefix and ns->href are never in the dict. + * XML_TREE_ADOPT_STR(ns->prefix) + * XML_TREE_ADOPT_STR(ns->href) + */ + /* + * Does it shadow any ns-decl? + */ + if (XML_NSMAP_NOTEMPTY(nsMap)) { + XML_NSMAP_FOREACH(nsMap, mi) { + if ((mi->depth >= XML_TREE_NSMAP_PARENT) && + (mi->shadowDepth == -1) && + ((ns->prefix == mi->newNs->prefix) || + xmlStrEqual(ns->prefix, + mi->newNs->prefix))) { + + mi->shadowDepth = depth; + } + } + } + /* + * Push mapping. + */ + if (xmlDOMWrapNsMapAddItem(&nsMap, -1, + ns, ns, depth) == NULL) + goto internal_error; + } + } + /* No break on purpose. */ + case XML_ATTRIBUTE_NODE: + /* No namespace, no fun. */ + if (cur->ns == NULL) + goto ns_end; + + if (! parnsdone) { + if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap, + destParent) == -1) + goto internal_error; + parnsdone = 1; + } + /* + * Adopt ns-references. + */ + if (XML_NSMAP_NOTEMPTY(nsMap)) { + /* + * Search for a mapping. + */ + XML_NSMAP_FOREACH(nsMap, mi) { + if ((mi->shadowDepth == -1) && + (cur->ns == mi->oldNs)) { + + cur->ns = mi->newNs; + goto ns_end; + } + } + } + /* + * No matching namespace in scope. We need a new one. + */ + if ((ctxt) && (ctxt->getNsForNodeFunc)) { + /* + * User-defined behaviour. + */ + ns = ctxt->getNsForNodeFunc(ctxt, cur, + cur->ns->href, cur->ns->prefix); + /* + * Insert mapping if ns is available; it's the users fault + * if not. + */ + if (xmlDOMWrapNsMapAddItem(&nsMap, -1, + cur->ns, ns, XML_TREE_NSMAP_CUSTOM) == NULL) + goto internal_error; + cur->ns = ns; + } else { + /* + * Aquire a normalized ns-decl and add it to the map. + */ + if (xmlDOMWrapNSNormAquireNormalizedNs(destDoc, + /* ns-decls on curElem or on destDoc->oldNs */ + destParent ? curElem : NULL, + cur->ns, &ns, + &nsMap, depth, + ancestorsOnly, + /* ns-decls must be prefixed for attributes. */ + (cur->type == XML_ATTRIBUTE_NODE) ? 1 : 0) == -1) + goto internal_error; + cur->ns = ns; + } +ns_end: + /* + * Further node properties. + * TODO: Is this all? + */ + XML_TREE_ADOPT_STR(cur->name) + if (cur->type == XML_ELEMENT_NODE) { + cur->psvi = NULL; + cur->line = 0; + cur->extra = 0; + /* + * Walk attributes. + */ + if (cur->properties != NULL) { + /* + * Process first attribute node. + */ + cur = (xmlNodePtr) cur->properties; + continue; + } + } else { + /* + * Attributes. + */ + if ((sourceDoc != NULL) && + (((xmlAttrPtr) cur)->atype == XML_ATTRIBUTE_ID)) + { + xmlRemoveID(sourceDoc, (xmlAttrPtr) cur); + } + ((xmlAttrPtr) cur)->atype = 0; + ((xmlAttrPtr) cur)->psvi = NULL; + } + break; + case XML_TEXT_NODE: + case XML_CDATA_SECTION_NODE: + /* + * This puts the content in the dest dict, only if + * it was previously in the source dict. + */ + XML_TREE_ADOPT_STR_2(cur->content) + goto leave_node; + case XML_ENTITY_REF_NODE: + /* + * Remove reference to the entitity-node. + */ + cur->content = NULL; + cur->children = NULL; + cur->last = NULL; + if ((destDoc->intSubset) || (destDoc->extSubset)) { + xmlEntityPtr ent; + /* + * Assign new entity-node if available. + */ + ent = xmlGetDocEntity(destDoc, cur->name); + if (ent != NULL) { + cur->content = ent->content; + cur->children = (xmlNodePtr) ent; + cur->last = (xmlNodePtr) ent; + } + } + goto leave_node; + case XML_PI_NODE: + XML_TREE_ADOPT_STR(cur->name) + XML_TREE_ADOPT_STR_2(cur->content) + break; + case XML_COMMENT_NODE: + break; + default: + goto internal_error; + } + /* + * Walk the tree. + */ + if (cur->children != NULL) { + cur = cur->children; + continue; + } + +leave_node: + if (cur == node) + break; + if ((cur->type == XML_ELEMENT_NODE) || + (cur->type == XML_XINCLUDE_START) || + (cur->type == XML_XINCLUDE_END)) + { + /* + * TODO: Do we expect nsDefs on XML_XINCLUDE_START? + */ + if (XML_NSMAP_NOTEMPTY(nsMap)) { + /* + * Pop mappings. + */ + while ((nsMap->last != NULL) && + (nsMap->last->depth >= depth)) + { + XML_NSMAP_POP(nsMap, mi) + } + /* + * Unshadow. + */ + XML_NSMAP_FOREACH(nsMap, mi) { + if (mi->shadowDepth >= depth) + mi->shadowDepth = -1; + } + } + depth--; + } + if (cur->next != NULL) + cur = cur->next; + else if ((cur->type == XML_ATTRIBUTE_NODE) && + (cur->parent->children != NULL)) + { + cur = cur->parent->children; + } else { + cur = cur->parent; + goto leave_node; + } + } + + goto exit; + +internal_error: + ret = -1; + +exit: + /* + * Cleanup. + */ + if (nsMap != NULL) { + if ((ctxt) && (ctxt->namespaceMap == nsMap)) { + /* + * Just cleanup the map but don't free. + */ + if (nsMap->first) { + if (nsMap->pool) + nsMap->last->next = nsMap->pool; + nsMap->pool = nsMap->first; + nsMap->first = NULL; + } + } else + xmlDOMWrapNsMapFree(nsMap); + } + return(ret); +} + +/* +* xmlDOMWrapCloneNode: +* @ctxt: the optional context for custom processing +* @sourceDoc: the optional sourceDoc +* @node: the node to start with +* @resNode: the clone of the given @node +* @destDoc: the destination doc +* @destParent: the optional new parent of @node in @destDoc +* @deep: descend into child if set +* @options: option flags +* +* References of out-of scope ns-decls are remapped to point to @destDoc: +* 1) If @destParent is given, then nsDef entries on element-nodes are used +* 2) If *no* @destParent is given, then @destDoc->oldNs entries are used. +* This is the case when you don't know already where the cloned branch +* will be added to. +* +* If @destParent is given, it ensures that the tree is namespace +* wellformed by creating additional ns-decls where needed. +* Note that, since prefixes of already existent ns-decls can be +* shadowed by this process, it could break QNames in attribute +* values or element content. +* TODO: +* 1) What to do with XInclude? Currently this returns an error for XInclude. +* +* Returns 0 if the operation succeeded, +* 1 if a node of unsupported (or not yet supported) type was given, +* -1 on API/internal errors. +*/ + +int +xmlDOMWrapCloneNode(xmlDOMWrapCtxtPtr ctxt, + xmlDocPtr sourceDoc, + xmlNodePtr node, + xmlNodePtr *resNode, + xmlDocPtr destDoc, + xmlNodePtr destParent, + int deep, + int options ATTRIBUTE_UNUSED) +{ + int ret = 0; + xmlNodePtr cur, curElem = NULL; + xmlNsMapPtr nsMap = NULL; + xmlNsMapItemPtr mi; + xmlNsPtr ns; + int depth = -1; + /* int adoptStr = 1; */ + /* gather @parent's ns-decls. */ + int parnsdone = 0; + /* + * @ancestorsOnly: + * TODO: @ancestorsOnly should be set per option. + * + */ + int ancestorsOnly = 0; + xmlNodePtr resultClone = NULL, clone = NULL, parentClone = NULL, prevClone = NULL; + xmlNsPtr cloneNs = NULL, *cloneNsDefSlot = NULL; + xmlDictPtr dict; /* The destination dict */ + + if ((node == NULL) || (resNode == NULL) || (destDoc == NULL)) + return(-1); + /* + * TODO: Initially we support only element-nodes. + */ + if (node->type != XML_ELEMENT_NODE) + return(1); + /* + * Check node->doc sanity. + */ + if ((node->doc != NULL) && (sourceDoc != NULL) && + (node->doc != sourceDoc)) { + /* + * Might be an XIncluded node. + */ + return (-1); + } + if (sourceDoc == NULL) + sourceDoc = node->doc; + if (sourceDoc == NULL) + return (-1); + + dict = destDoc->dict; + /* + * Reuse the namespace map of the context. + */ + if (ctxt) + nsMap = (xmlNsMapPtr) ctxt->namespaceMap; + + *resNode = NULL; + + cur = node; + while (cur != NULL) { + if (cur->doc != sourceDoc) { + /* + * We'll assume XIncluded nodes if the doc differs. + * TODO: Do we need to reconciliate XIncluded nodes? + * TODO: This here returns -1 in this case. + */ + goto internal_error; + } + /* + * Create a new node. + */ + switch (cur->type) { + case XML_XINCLUDE_START: + case XML_XINCLUDE_END: + /* + * TODO: What to do with XInclude? + */ + goto internal_error; + break; + case XML_ELEMENT_NODE: + case XML_TEXT_NODE: + case XML_CDATA_SECTION_NODE: + case XML_COMMENT_NODE: + case XML_PI_NODE: + case XML_DOCUMENT_FRAG_NODE: + case XML_ENTITY_REF_NODE: + case XML_ENTITY_NODE: + /* + * Nodes of xmlNode structure. + */ + clone = (xmlNodePtr) xmlMalloc(sizeof(xmlNode)); + if (clone == NULL) { + xmlTreeErrMemory("xmlDOMWrapCloneNode(): allocating a node"); + goto internal_error; + } + memset(clone, 0, sizeof(xmlNode)); + /* + * Set hierachical links. + */ + if (resultClone != NULL) { + clone->parent = parentClone; + if (prevClone) { + prevClone->next = clone; + clone->prev = prevClone; + } else + parentClone->children = clone; + } else + resultClone = clone; + + break; + case XML_ATTRIBUTE_NODE: + /* + * Attributes (xmlAttr). + */ + clone = (xmlNodePtr) xmlMalloc(sizeof(xmlAttr)); + if (clone == NULL) { + xmlTreeErrMemory("xmlDOMWrapCloneNode(): allocating an attr-node"); + goto internal_error; + } + memset(clone, 0, sizeof(xmlAttr)); + /* + * Set hierachical links. + * TODO: Change this to add to the end of attributes. + */ + if (resultClone != NULL) { + clone->parent = parentClone; + if (prevClone) { + prevClone->next = clone; + clone->prev = prevClone; + } else + parentClone->properties = (xmlAttrPtr) clone; + } else + resultClone = clone; + break; + default: + /* + * TODO QUESTION: Any other nodes expected? + */ + goto internal_error; + } + + clone->type = cur->type; + clone->doc = destDoc; + + /* + * Clone the name of the node if any. + */ + if (cur->name == xmlStringText) + clone->name = xmlStringText; + else if (cur->name == xmlStringTextNoenc) + /* + * NOTE: Although xmlStringTextNoenc is never assigned to a node + * in tree.c, it might be set in Libxslt via + * "xsl:disable-output-escaping". + */ + clone->name = xmlStringTextNoenc; + else if (cur->name == xmlStringComment) + clone->name = xmlStringComment; + else if (cur->name != NULL) { + DICT_CONST_COPY(cur->name, clone->name); + } + + switch (cur->type) { + case XML_XINCLUDE_START: + case XML_XINCLUDE_END: + /* + * TODO + */ + return (-1); + case XML_ELEMENT_NODE: + curElem = cur; + depth++; + /* + * Namespace declarations. + */ + if (cur->nsDef != NULL) { + if (! parnsdone) { + if (destParent && (ctxt == NULL)) { + /* + * Gather @parent's in-scope ns-decls. + */ + if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap, + destParent) == -1) + goto internal_error; + } + parnsdone = 1; + } + /* + * Clone namespace declarations. + */ + cloneNsDefSlot = &(clone->nsDef); + for (ns = cur->nsDef; ns != NULL; ns = ns->next) { + /* + * Create a new xmlNs. + */ + cloneNs = (xmlNsPtr) xmlMalloc(sizeof(xmlNs)); + if (cloneNs == NULL) { + xmlTreeErrMemory("xmlDOMWrapCloneNode(): " + "allocating namespace"); + return(-1); + } + memset(cloneNs, 0, sizeof(xmlNs)); + cloneNs->type = XML_LOCAL_NAMESPACE; + + if (ns->href != NULL) + cloneNs->href = xmlStrdup(ns->href); + if (ns->prefix != NULL) + cloneNs->prefix = xmlStrdup(ns->prefix); + + *cloneNsDefSlot = cloneNs; + cloneNsDefSlot = &(cloneNs->next); + + /* + * Note that for custom handling of ns-references, + * the ns-decls need not be stored in the ns-map, + * since they won't be referenced by node->ns. + */ + if ((ctxt == NULL) || + (ctxt->getNsForNodeFunc == NULL)) + { + /* + * Does it shadow any ns-decl? + */ + if (XML_NSMAP_NOTEMPTY(nsMap)) { + XML_NSMAP_FOREACH(nsMap, mi) { + if ((mi->depth >= XML_TREE_NSMAP_PARENT) && + (mi->shadowDepth == -1) && + ((ns->prefix == mi->newNs->prefix) || + xmlStrEqual(ns->prefix, + mi->newNs->prefix))) { + /* + * Mark as shadowed at the current + * depth. + */ + mi->shadowDepth = depth; + } + } + } + /* + * Push mapping. + */ + if (xmlDOMWrapNsMapAddItem(&nsMap, -1, + ns, cloneNs, depth) == NULL) + goto internal_error; + } + } + } + /* cur->ns will be processed further down. */ + break; + case XML_ATTRIBUTE_NODE: + /* IDs will be processed further down. */ + /* cur->ns will be processed further down. */ + break; + case XML_TEXT_NODE: + case XML_CDATA_SECTION_NODE: + /* + * Note that this will also cover the values of attributes. + */ + DICT_COPY(cur->content, clone->content); + goto leave_node; + case XML_ENTITY_NODE: + /* TODO: What to do here? */ + goto leave_node; + case XML_ENTITY_REF_NODE: + if (sourceDoc != destDoc) { + if ((destDoc->intSubset) || (destDoc->extSubset)) { + xmlEntityPtr ent; + /* + * Different doc: Assign new entity-node if available. + */ + ent = xmlGetDocEntity(destDoc, cur->name); + if (ent != NULL) { + clone->content = ent->content; + clone->children = (xmlNodePtr) ent; + clone->last = (xmlNodePtr) ent; + } + } + } else { + /* + * Same doc: Use the current node's entity declaration + * and value. + */ + clone->content = cur->content; + clone->children = cur->children; + clone->last = cur->last; + } + goto leave_node; + case XML_PI_NODE: + DICT_COPY(cur->content, clone->content); + goto leave_node; + case XML_COMMENT_NODE: + DICT_COPY(cur->content, clone->content); + goto leave_node; + default: + goto internal_error; + } + + if (cur->ns == NULL) + goto end_ns_reference; + +/* handle_ns_reference: */ + /* + ** The following will take care of references to ns-decls ******** + ** and is intended only for element- and attribute-nodes. + ** + */ + if (! parnsdone) { + if (destParent && (ctxt == NULL)) { + if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap, destParent) == -1) + goto internal_error; + } + parnsdone = 1; + } + /* + * Adopt ns-references. + */ + if (XML_NSMAP_NOTEMPTY(nsMap)) { + /* + * Search for a mapping. + */ + XML_NSMAP_FOREACH(nsMap, mi) { + if ((mi->shadowDepth == -1) && + (cur->ns == mi->oldNs)) { + /* + * This is the nice case: a mapping was found. + */ + clone->ns = mi->newNs; + goto end_ns_reference; + } + } + } + /* + * No matching namespace in scope. We need a new one. + */ + if ((ctxt != NULL) && (ctxt->getNsForNodeFunc != NULL)) { + /* + * User-defined behaviour. + */ + ns = ctxt->getNsForNodeFunc(ctxt, cur, + cur->ns->href, cur->ns->prefix); + /* + * Add user's mapping. + */ + if (xmlDOMWrapNsMapAddItem(&nsMap, -1, + cur->ns, ns, XML_TREE_NSMAP_CUSTOM) == NULL) + goto internal_error; + clone->ns = ns; + } else { + /* + * Aquire a normalized ns-decl and add it to the map. + */ + if (xmlDOMWrapNSNormAquireNormalizedNs(destDoc, + /* ns-decls on curElem or on destDoc->oldNs */ + destParent ? curElem : NULL, + cur->ns, &ns, + &nsMap, depth, + /* if we need to search only in the ancestor-axis */ + ancestorsOnly, + /* ns-decls must be prefixed for attributes. */ + (cur->type == XML_ATTRIBUTE_NODE) ? 1 : 0) == -1) + goto internal_error; + clone->ns = ns; + } + +end_ns_reference: + + /* + * Some post-processing. + * + * Handle ID attributes. + */ + if ((clone->type == XML_ATTRIBUTE_NODE) && + (clone->parent != NULL)) + { + if (xmlIsID(destDoc, clone->parent, (xmlAttrPtr) clone)) { + + xmlChar *idVal; + + idVal = xmlNodeListGetString(cur->doc, cur->children, 1); + if (idVal != NULL) { + if (xmlAddID(NULL, destDoc, idVal, (xmlAttrPtr) cur) == NULL) { + /* TODO: error message. */ + xmlFree(idVal); + goto internal_error; + } + xmlFree(idVal); + } + } + } + /* + ** + ** The following will traverse the tree ************************** + ** + * + * Walk the element's attributes before descending into child-nodes. + */ + if ((cur->type == XML_ELEMENT_NODE) && (cur->properties != NULL)) { + prevClone = NULL; + parentClone = clone; + cur = (xmlNodePtr) cur->properties; + continue; + } +into_content: + /* + * Descend into child-nodes. + */ + if (cur->children != NULL) { + if (deep || (cur->type == XML_ATTRIBUTE_NODE)) { + prevClone = NULL; + parentClone = clone; + cur = cur->children; + continue; + } + } + +leave_node: + /* + * At this point we are done with the node, its content + * and an element-nodes's attribute-nodes. + */ + if (cur == node) + break; + if ((cur->type == XML_ELEMENT_NODE) || + (cur->type == XML_XINCLUDE_START) || + (cur->type == XML_XINCLUDE_END)) { + /* + * TODO: Do we expect nsDefs on XML_XINCLUDE_START? + */ + if (XML_NSMAP_NOTEMPTY(nsMap)) { + /* + * Pop mappings. + */ + while ((nsMap->last != NULL) && + (nsMap->last->depth >= depth)) + { + XML_NSMAP_POP(nsMap, mi) + } + /* + * Unshadow. + */ + XML_NSMAP_FOREACH(nsMap, mi) { + if (mi->shadowDepth >= depth) + mi->shadowDepth = -1; + } + } + depth--; + } + if (cur->next != NULL) { + prevClone = clone; + cur = cur->next; + } else if (cur->type != XML_ATTRIBUTE_NODE) { + /* + * Set clone->last. + */ + if (clone->parent != NULL) + clone->parent->last = clone; + clone = clone->parent; + parentClone = clone->parent; + /* + * Process parent --> next; + */ + cur = cur->parent; + goto leave_node; + } else { + /* This is for attributes only. */ + clone = clone->parent; + parentClone = clone->parent; + /* + * Process parent-element --> children. + */ + cur = cur->parent; + goto into_content; + } + } + goto exit; + +internal_error: + ret = -1; + +exit: + /* + * Cleanup. + */ + if (nsMap != NULL) { + if ((ctxt) && (ctxt->namespaceMap == nsMap)) { + /* + * Just cleanup the map but don't free. + */ + if (nsMap->first) { + if (nsMap->pool) + nsMap->last->next = nsMap->pool; + nsMap->pool = nsMap->first; + nsMap->first = NULL; + } + } else + xmlDOMWrapNsMapFree(nsMap); + } + /* + * TODO: Should we try a cleanup of the cloned node in case of a + * fatal error? + */ + *resNode = resultClone; + return (ret); +} + +/* +* xmlDOMWrapAdoptAttr: +* @ctxt: the optional context for custom processing +* @sourceDoc: the optional source document of attr +* @attr: the attribute-node to be adopted +* @destDoc: the destination doc for adoption +* @destParent: the optional new parent of @attr in @destDoc +* @options: option flags +* +* @attr is adopted by @destDoc. +* Ensures that ns-references point to @destDoc: either to +* elements->nsDef entries if @destParent is given, or to +* @destDoc->oldNs otherwise. +* +* Returns 0 if succeeded, -1 otherwise and on API/internal errors. +*/ +static int +xmlDOMWrapAdoptAttr(xmlDOMWrapCtxtPtr ctxt, + xmlDocPtr sourceDoc, + xmlAttrPtr attr, + xmlDocPtr destDoc, + xmlNodePtr destParent, + int options ATTRIBUTE_UNUSED) +{ + xmlNodePtr cur; + int adoptStr = 1; + + if ((attr == NULL) || (destDoc == NULL)) + return (-1); + + attr->doc = destDoc; + if (attr->ns != NULL) { + xmlNsPtr ns = NULL; + + if (ctxt != NULL) { + /* TODO: User defined. */ + } + /* XML Namespace. */ + if (IS_STR_XML(attr->ns->prefix)) { + ns = xmlTreeEnsureXMLDecl(destDoc); + } else if (destParent == NULL) { + /* + * Store in @destDoc->oldNs. + */ + ns = xmlDOMWrapStoreNs(destDoc, attr->ns->href, attr->ns->prefix); + } else { + /* + * Declare on @destParent. + */ + if (xmlSearchNsByNamespaceStrict(destDoc, destParent, attr->ns->href, + &ns, 1) == -1) + goto internal_error; + if (ns == NULL) { + ns = xmlDOMWrapNSNormDeclareNsForced(destDoc, destParent, + attr->ns->href, attr->ns->prefix, 1); + } + } + if (ns == NULL) + goto internal_error; + attr->ns = ns; + } + + XML_TREE_ADOPT_STR(attr->name); + attr->atype = 0; + attr->psvi = NULL; + /* + * Walk content. + */ + if (attr->children == NULL) + return (0); + cur = attr->children; + while (cur != NULL) { + cur->doc = destDoc; + switch (cur->type) { + case XML_TEXT_NODE: + case XML_CDATA_SECTION_NODE: + XML_TREE_ADOPT_STR_2(cur->content) + break; + case XML_ENTITY_REF_NODE: + /* + * Remove reference to the entitity-node. + */ + cur->content = NULL; + cur->children = NULL; + cur->last = NULL; + if ((destDoc->intSubset) || (destDoc->extSubset)) { + xmlEntityPtr ent; + /* + * Assign new entity-node if available. + */ + ent = xmlGetDocEntity(destDoc, cur->name); + if (ent != NULL) { + cur->content = ent->content; + cur->children = (xmlNodePtr) ent; + cur->last = (xmlNodePtr) ent; + } + } + break; + default: + break; + } + if (cur->children != NULL) { + cur = cur->children; + continue; + } +next_sibling: + if (cur == (xmlNodePtr) attr) + break; + if (cur->next != NULL) + cur = cur->next; + else { + cur = cur->parent; + goto next_sibling; + } + } + return (0); +internal_error: + return (-1); +} + +/* +* xmlDOMWrapAdoptNode: +* @ctxt: the optional context for custom processing +* @sourceDoc: the optional sourceDoc +* @node: the node to start with +* @destDoc: the destination doc +* @destParent: the optional new parent of @node in @destDoc +* @options: option flags +* +* References of out-of scope ns-decls are remapped to point to @destDoc: +* 1) If @destParent is given, then nsDef entries on element-nodes are used +* 2) If *no* @destParent is given, then @destDoc->oldNs entries are used +* This is the case when you have an unliked node and just want to move it +* to the context of +* +* If @destParent is given, it ensures that the tree is namespace +* wellformed by creating additional ns-decls where needed. +* Note that, since prefixes of already existent ns-decls can be +* shadowed by this process, it could break QNames in attribute +* values or element content. +* NOTE: This function was not intensively tested. +* +* Returns 0 if the operation succeeded, +* 1 if a node of unsupported type was given, +* 2 if a node of not yet supported type was given and +* -1 on API/internal errors. +*/ +int +xmlDOMWrapAdoptNode(xmlDOMWrapCtxtPtr ctxt, + xmlDocPtr sourceDoc, + xmlNodePtr node, + xmlDocPtr destDoc, + xmlNodePtr destParent, + int options) +{ + if ((node == NULL) || (destDoc == NULL) || + ((destParent != NULL) && (destParent->doc != destDoc))) + return(-1); + /* + * Check node->doc sanity. + */ + if ((node->doc != NULL) && (sourceDoc != NULL) && + (node->doc != sourceDoc)) { + /* + * Might be an XIncluded node. + */ + return (-1); + } + if (sourceDoc == NULL) + sourceDoc = node->doc; + if (sourceDoc == destDoc) + return (-1); + switch (node->type) { + case XML_ELEMENT_NODE: + case XML_ATTRIBUTE_NODE: + case XML_TEXT_NODE: + case XML_CDATA_SECTION_NODE: + case XML_ENTITY_REF_NODE: + case XML_PI_NODE: + case XML_COMMENT_NODE: + break; + case XML_DOCUMENT_FRAG_NODE: + /* TODO: Support document-fragment-nodes. */ + return (2); + default: + return (1); + } + /* + * Unlink only if @node was not already added to @destParent. + */ + if ((node->parent != NULL) && (destParent != node->parent)) + xmlUnlinkNode(node); + + if (node->type == XML_ELEMENT_NODE) { + return (xmlDOMWrapAdoptBranch(ctxt, sourceDoc, node, + destDoc, destParent, options)); + } else if (node->type == XML_ATTRIBUTE_NODE) { + return (xmlDOMWrapAdoptAttr(ctxt, sourceDoc, + (xmlAttrPtr) node, destDoc, destParent, options)); + } else { + xmlNodePtr cur = node; + int adoptStr = 1; + + cur->doc = destDoc; + /* + * Optimize string adoption. + */ + if ((sourceDoc != NULL) && + (sourceDoc->dict == destDoc->dict)) + adoptStr = 0; + switch (node->type) { + case XML_TEXT_NODE: + case XML_CDATA_SECTION_NODE: + XML_TREE_ADOPT_STR_2(node->content) + break; + case XML_ENTITY_REF_NODE: + /* + * Remove reference to the entitity-node. + */ + node->content = NULL; + node->children = NULL; + node->last = NULL; + if ((destDoc->intSubset) || (destDoc->extSubset)) { + xmlEntityPtr ent; + /* + * Assign new entity-node if available. + */ + ent = xmlGetDocEntity(destDoc, node->name); + if (ent != NULL) { + node->content = ent->content; + node->children = (xmlNodePtr) ent; + node->last = (xmlNodePtr) ent; + } + } + XML_TREE_ADOPT_STR(node->name) + break; + case XML_PI_NODE: { + XML_TREE_ADOPT_STR(node->name) + XML_TREE_ADOPT_STR_2(node->content) + break; + } + default: + break; + } + } + return (0); +} + +#define bottom_tree +#include "elfgcchack.h" diff --git a/gettext-tools/gnulib-lib/libxml/tree.in.h b/gettext-tools/gnulib-lib/libxml/tree.in.h new file mode 100644 index 0000000..321280e --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/tree.in.h @@ -0,0 +1,1208 @@ +/* + * Summary: interfaces for tree manipulation + * Description: this module describes the structures found in an tree resulting + * from an XML or HTML parsing, as well as the API provided for + * various processing on that tree + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + +#ifndef __XML_TREE_H__ +#define __XML_TREE_H__ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Some of the basic types pointer to structures: + */ +/* xmlIO.h */ +typedef struct _xmlParserInputBuffer xmlParserInputBuffer; +typedef xmlParserInputBuffer *xmlParserInputBufferPtr; + +typedef struct _xmlOutputBuffer xmlOutputBuffer; +typedef xmlOutputBuffer *xmlOutputBufferPtr; + +/* parser.h */ +typedef struct _xmlParserInput xmlParserInput; +typedef xmlParserInput *xmlParserInputPtr; + +typedef struct _xmlParserCtxt xmlParserCtxt; +typedef xmlParserCtxt *xmlParserCtxtPtr; + +typedef struct _xmlSAXLocator xmlSAXLocator; +typedef xmlSAXLocator *xmlSAXLocatorPtr; + +typedef struct _xmlSAXHandler xmlSAXHandler; +typedef xmlSAXHandler *xmlSAXHandlerPtr; + +/* entities.h */ +typedef struct _xmlEntity xmlEntity; +typedef xmlEntity *xmlEntityPtr; + +/** + * BASE_BUFFER_SIZE: + * + * default buffer size 4000. + */ +#define BASE_BUFFER_SIZE 4096 + +/** + * LIBXML_NAMESPACE_DICT: + * + * Defines experimental behaviour: + * 1) xmlNs gets an additional field @context (a xmlDoc) + * 2) when creating a tree, xmlNs->href is stored in the dict of xmlDoc. + */ +/* #define LIBXML_NAMESPACE_DICT */ + +/** + * xmlBufferAllocationScheme: + * + * A buffer allocation scheme can be defined to either match exactly the + * need or double it's allocated size each time it is found too small. + */ + +typedef enum { + XML_BUFFER_ALLOC_DOUBLEIT, + XML_BUFFER_ALLOC_EXACT, + XML_BUFFER_ALLOC_IMMUTABLE +} xmlBufferAllocationScheme; + +/** + * xmlBuffer: + * + * A buffer structure. + */ +typedef struct _xmlBuffer xmlBuffer; +typedef xmlBuffer *xmlBufferPtr; +struct _xmlBuffer { + xmlChar *content; /* The buffer content UTF8 */ + unsigned int use; /* The buffer size used */ + unsigned int size; /* The buffer size */ + xmlBufferAllocationScheme alloc; /* The realloc method */ +}; + +/** + * XML_XML_NAMESPACE: + * + * This is the namespace for the special xml: prefix predefined in the + * XML Namespace specification. + */ +#define XML_XML_NAMESPACE \ + (const xmlChar *) "http://www.w3.org/XML/1998/namespace" + +/** + * XML_XML_ID: + * + * This is the name for the special xml:id attribute + */ +#define XML_XML_ID (const xmlChar *) "xml:id" + +/* + * The different element types carried by an XML tree. + * + * NOTE: This is synchronized with DOM Level1 values + * See http://www.w3.org/TR/REC-DOM-Level-1/ + * + * Actually this had diverged a bit, and now XML_DOCUMENT_TYPE_NODE should + * be deprecated to use an XML_DTD_NODE. + */ +typedef enum { + XML_ELEMENT_NODE= 1, + XML_ATTRIBUTE_NODE= 2, + XML_TEXT_NODE= 3, + XML_CDATA_SECTION_NODE= 4, + XML_ENTITY_REF_NODE= 5, + XML_ENTITY_NODE= 6, + XML_PI_NODE= 7, + XML_COMMENT_NODE= 8, + XML_DOCUMENT_NODE= 9, + XML_DOCUMENT_TYPE_NODE= 10, + XML_DOCUMENT_FRAG_NODE= 11, + XML_NOTATION_NODE= 12, + XML_HTML_DOCUMENT_NODE= 13, + XML_DTD_NODE= 14, + XML_ELEMENT_DECL= 15, + XML_ATTRIBUTE_DECL= 16, + XML_ENTITY_DECL= 17, + XML_NAMESPACE_DECL= 18, + XML_XINCLUDE_START= 19, + XML_XINCLUDE_END= 20 +#ifdef LIBXML_DOCB_ENABLED + ,XML_DOCB_DOCUMENT_NODE= 21 +#endif +} xmlElementType; + + +/** + * xmlNotation: + * + * A DTD Notation definition. + */ + +typedef struct _xmlNotation xmlNotation; +typedef xmlNotation *xmlNotationPtr; +struct _xmlNotation { + const xmlChar *name; /* Notation name */ + const xmlChar *PublicID; /* Public identifier, if any */ + const xmlChar *SystemID; /* System identifier, if any */ +}; + +/** + * xmlAttributeType: + * + * A DTD Attribute type definition. + */ + +typedef enum { + XML_ATTRIBUTE_CDATA = 1, + XML_ATTRIBUTE_ID, + XML_ATTRIBUTE_IDREF , + XML_ATTRIBUTE_IDREFS, + XML_ATTRIBUTE_ENTITY, + XML_ATTRIBUTE_ENTITIES, + XML_ATTRIBUTE_NMTOKEN, + XML_ATTRIBUTE_NMTOKENS, + XML_ATTRIBUTE_ENUMERATION, + XML_ATTRIBUTE_NOTATION +} xmlAttributeType; + +/** + * xmlAttributeDefault: + * + * A DTD Attribute default definition. + */ + +typedef enum { + XML_ATTRIBUTE_NONE = 1, + XML_ATTRIBUTE_REQUIRED, + XML_ATTRIBUTE_IMPLIED, + XML_ATTRIBUTE_FIXED +} xmlAttributeDefault; + +/** + * xmlEnumeration: + * + * List structure used when there is an enumeration in DTDs. + */ + +typedef struct _xmlEnumeration xmlEnumeration; +typedef xmlEnumeration *xmlEnumerationPtr; +struct _xmlEnumeration { + struct _xmlEnumeration *next; /* next one */ + const xmlChar *name; /* Enumeration name */ +}; + +/** + * xmlAttribute: + * + * An Attribute declaration in a DTD. + */ + +typedef struct _xmlAttribute xmlAttribute; +typedef xmlAttribute *xmlAttributePtr; +struct _xmlAttribute { + void *_private; /* application data */ + xmlElementType type; /* XML_ATTRIBUTE_DECL, must be second ! */ + const xmlChar *name; /* Attribute name */ + struct _xmlNode *children; /* NULL */ + struct _xmlNode *last; /* NULL */ + struct _xmlDtd *parent; /* -> DTD */ + struct _xmlNode *next; /* next sibling link */ + struct _xmlNode *prev; /* previous sibling link */ + struct _xmlDoc *doc; /* the containing document */ + + struct _xmlAttribute *nexth; /* next in hash table */ + xmlAttributeType atype; /* The attribute type */ + xmlAttributeDefault def; /* the default */ + const xmlChar *defaultValue; /* or the default value */ + xmlEnumerationPtr tree; /* or the enumeration tree if any */ + const xmlChar *prefix; /* the namespace prefix if any */ + const xmlChar *elem; /* Element holding the attribute */ +}; + +/** + * xmlElementContentType: + * + * Possible definitions of element content types. + */ +typedef enum { + XML_ELEMENT_CONTENT_PCDATA = 1, + XML_ELEMENT_CONTENT_ELEMENT, + XML_ELEMENT_CONTENT_SEQ, + XML_ELEMENT_CONTENT_OR +} xmlElementContentType; + +/** + * xmlElementContentOccur: + * + * Possible definitions of element content occurrences. + */ +typedef enum { + XML_ELEMENT_CONTENT_ONCE = 1, + XML_ELEMENT_CONTENT_OPT, + XML_ELEMENT_CONTENT_MULT, + XML_ELEMENT_CONTENT_PLUS +} xmlElementContentOccur; + +/** + * xmlElementContent: + * + * An XML Element content as stored after parsing an element definition + * in a DTD. + */ + +typedef struct _xmlElementContent xmlElementContent; +typedef xmlElementContent *xmlElementContentPtr; +struct _xmlElementContent { + xmlElementContentType type; /* PCDATA, ELEMENT, SEQ or OR */ + xmlElementContentOccur ocur; /* ONCE, OPT, MULT or PLUS */ + const xmlChar *name; /* Element name */ + struct _xmlElementContent *c1; /* first child */ + struct _xmlElementContent *c2; /* second child */ + struct _xmlElementContent *parent; /* parent */ + const xmlChar *prefix; /* Namespace prefix */ +}; + +/** + * xmlElementTypeVal: + * + * The different possibilities for an element content type. + */ + +typedef enum { + XML_ELEMENT_TYPE_UNDEFINED = 0, + XML_ELEMENT_TYPE_EMPTY = 1, + XML_ELEMENT_TYPE_ANY, + XML_ELEMENT_TYPE_MIXED, + XML_ELEMENT_TYPE_ELEMENT +} xmlElementTypeVal; + +#ifdef __cplusplus +} +#endif +#include +#ifdef __cplusplus +extern "C" { +#endif + +/** + * xmlElement: + * + * An XML Element declaration from a DTD. + */ + +typedef struct _xmlElement xmlElement; +typedef xmlElement *xmlElementPtr; +struct _xmlElement { + void *_private; /* application data */ + xmlElementType type; /* XML_ELEMENT_DECL, must be second ! */ + const xmlChar *name; /* Element name */ + struct _xmlNode *children; /* NULL */ + struct _xmlNode *last; /* NULL */ + struct _xmlDtd *parent; /* -> DTD */ + struct _xmlNode *next; /* next sibling link */ + struct _xmlNode *prev; /* previous sibling link */ + struct _xmlDoc *doc; /* the containing document */ + + xmlElementTypeVal etype; /* The type */ + xmlElementContentPtr content; /* the allowed element content */ + xmlAttributePtr attributes; /* List of the declared attributes */ + const xmlChar *prefix; /* the namespace prefix if any */ +#ifdef LIBXML_REGEXP_ENABLED + xmlRegexpPtr contModel; /* the validating regexp */ +#else + void *contModel; +#endif +}; + + +/** + * XML_LOCAL_NAMESPACE: + * + * A namespace declaration node. + */ +#define XML_LOCAL_NAMESPACE XML_NAMESPACE_DECL +typedef xmlElementType xmlNsType; + +/** + * xmlNs: + * + * An XML namespace. + * Note that prefix == NULL is valid, it defines the default namespace + * within the subtree (until overridden). + * + * xmlNsType is unified with xmlElementType. + */ + +typedef struct _xmlNs xmlNs; +typedef xmlNs *xmlNsPtr; +struct _xmlNs { + struct _xmlNs *next; /* next Ns link for this node */ + xmlNsType type; /* global or local */ + const xmlChar *href; /* URL for the namespace */ + const xmlChar *prefix; /* prefix for the namespace */ + void *_private; /* application data */ + struct _xmlDoc *context; /* normally an xmlDoc */ +}; + +/** + * xmlDtd: + * + * An XML DTD, as defined by parent link */ + struct _xmlNode *next; /* next sibling link */ + struct _xmlNode *prev; /* previous sibling link */ + struct _xmlDoc *doc; /* the containing document */ + + /* End of common part */ + void *notations; /* Hash table for notations if any */ + void *elements; /* Hash table for elements if any */ + void *attributes; /* Hash table for attributes if any */ + void *entities; /* Hash table for entities if any */ + const xmlChar *ExternalID; /* External identifier for PUBLIC DTD */ + const xmlChar *SystemID; /* URI for a SYSTEM or PUBLIC DTD */ + void *pentities; /* Hash table for param entities if any */ +}; + +/** + * xmlAttr: + * + * An attribute on an XML node. + */ +typedef struct _xmlAttr xmlAttr; +typedef xmlAttr *xmlAttrPtr; +struct _xmlAttr { + void *_private; /* application data */ + xmlElementType type; /* XML_ATTRIBUTE_NODE, must be second ! */ + const xmlChar *name; /* the name of the property */ + struct _xmlNode *children; /* the value of the property */ + struct _xmlNode *last; /* NULL */ + struct _xmlNode *parent; /* child->parent link */ + struct _xmlAttr *next; /* next sibling link */ + struct _xmlAttr *prev; /* previous sibling link */ + struct _xmlDoc *doc; /* the containing document */ + xmlNs *ns; /* pointer to the associated namespace */ + xmlAttributeType atype; /* the attribute type if validating */ + void *psvi; /* for type/PSVI informations */ +}; + +/** + * xmlID: + * + * An XML ID instance. + */ + +typedef struct _xmlID xmlID; +typedef xmlID *xmlIDPtr; +struct _xmlID { + struct _xmlID *next; /* next ID */ + const xmlChar *value; /* The ID name */ + xmlAttrPtr attr; /* The attribute holding it */ + const xmlChar *name; /* The attribute if attr is not available */ + int lineno; /* The line number if attr is not available */ + struct _xmlDoc *doc; /* The document holding the ID */ +}; + +/** + * xmlRef: + * + * An XML IDREF instance. + */ + +typedef struct _xmlRef xmlRef; +typedef xmlRef *xmlRefPtr; +struct _xmlRef { + struct _xmlRef *next; /* next Ref */ + const xmlChar *value; /* The Ref name */ + xmlAttrPtr attr; /* The attribute holding it */ + const xmlChar *name; /* The attribute if attr is not available */ + int lineno; /* The line number if attr is not available */ +}; + +/** + * xmlNode: + * + * A node in an XML tree. + */ +typedef struct _xmlNode xmlNode; +typedef xmlNode *xmlNodePtr; +struct _xmlNode { + void *_private; /* application data */ + xmlElementType type; /* type number, must be second ! */ + const xmlChar *name; /* the name of the node, or the entity */ + struct _xmlNode *children; /* parent->childs link */ + struct _xmlNode *last; /* last child link */ + struct _xmlNode *parent; /* child->parent link */ + struct _xmlNode *next; /* next sibling link */ + struct _xmlNode *prev; /* previous sibling link */ + struct _xmlDoc *doc; /* the containing document */ + + /* End of common part */ + xmlNs *ns; /* pointer to the associated namespace */ + xmlChar *content; /* the content */ + struct _xmlAttr *properties;/* properties list */ + xmlNs *nsDef; /* namespace definitions on this node */ + void *psvi; /* for type/PSVI informations */ + unsigned short line; /* line number */ + unsigned short extra; /* extra data for XPath/XSLT */ +}; + +/** + * XML_GET_CONTENT: + * + * Macro to extract the content pointer of a node. + */ +#define XML_GET_CONTENT(n) \ + ((n)->type == XML_ELEMENT_NODE ? NULL : (n)->content) + +/** + * XML_GET_LINE: + * + * Macro to extract the line number of an element node. + */ +#define XML_GET_LINE(n) \ + (xmlGetLineNo(n)) + + +/** + * xmlDoc: + * + * An XML document. + */ +typedef struct _xmlDoc xmlDoc; +typedef xmlDoc *xmlDocPtr; +struct _xmlDoc { + void *_private; /* application data */ + xmlElementType type; /* XML_DOCUMENT_NODE, must be second ! */ + char *name; /* name/filename/URI of the document */ + struct _xmlNode *children; /* the document tree */ + struct _xmlNode *last; /* last child link */ + struct _xmlNode *parent; /* child->parent link */ + struct _xmlNode *next; /* next sibling link */ + struct _xmlNode *prev; /* previous sibling link */ + struct _xmlDoc *doc; /* autoreference to itself */ + + /* End of common part */ + int compression;/* level of zlib compression */ + int standalone; /* standalone document (no external refs) */ + struct _xmlDtd *intSubset; /* the document internal subset */ + struct _xmlDtd *extSubset; /* the document external subset */ + struct _xmlNs *oldNs; /* Global namespace, the old way */ + const xmlChar *version; /* the XML version string */ + const xmlChar *encoding; /* external initial encoding, if any */ + void *ids; /* Hash table for ID attributes if any */ + void *refs; /* Hash table for IDREFs attributes if any */ + const xmlChar *URL; /* The URI for that document */ + int charset; /* encoding of the in-memory content + actually an xmlCharEncoding */ + struct _xmlDict *dict; /* dict used to allocate names or NULL */ + void *psvi; /* for type/PSVI informations */ +}; + + +typedef struct _xmlDOMWrapCtxt xmlDOMWrapCtxt; +typedef xmlDOMWrapCtxt *xmlDOMWrapCtxtPtr; + +/** + * xmlDOMWrapAcquireNsFunction: + * @ctxt: a DOM wrapper context + * @node: the context node (element or attribute) + * @nsName: the requested namespace name + * @nsPrefix: the requested namespace prefix + * + * A function called to acquire namespaces (xmlNs) from the wrapper. + * + * Returns an xmlNsPtr or NULL in case of an error. + */ +typedef xmlNsPtr (*xmlDOMWrapAcquireNsFunction) (xmlDOMWrapCtxtPtr ctxt, + xmlNodePtr node, + const xmlChar *nsName, + const xmlChar *nsPrefix); + +/** + * xmlDOMWrapCtxt: + * + * Context for DOM wrapper-operations. + */ +struct _xmlDOMWrapCtxt { + void * _private; + /* + * The type of this context, just in case we need specialized + * contexts in the future. + */ + int type; + /* + * Internal namespace map used for various operations. + */ + void * namespaceMap; + /* + * Use this one to acquire an xmlNsPtr intended for node->ns. + * (Note that this is not intended for elem->nsDef). + */ + xmlDOMWrapAcquireNsFunction getNsForNodeFunc; +}; + +/** + * xmlChildrenNode: + * + * Macro for compatibility naming layer with libxml1. Maps + * to "children." + */ +#ifndef xmlChildrenNode +#define xmlChildrenNode children +#endif + +/** + * xmlRootNode: + * + * Macro for compatibility naming layer with libxml1. Maps + * to "children". + */ +#ifndef xmlRootNode +#define xmlRootNode children +#endif + +/* + * Variables. + */ + +/* + * Some helper functions + */ +#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) || defined(LIBXML_DEBUG_ENABLED) || defined (LIBXML_HTML_ENABLED) || defined(LIBXML_SAX1_ENABLED) || defined(LIBXML_HTML_ENABLED) || defined(LIBXML_WRITER_ENABLED) || defined(LIBXML_DOCB_ENABLED) +XMLPUBFUN int XMLCALL + xmlValidateNCName (const xmlChar *value, + int space); +#endif + +#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) +XMLPUBFUN int XMLCALL + xmlValidateQName (const xmlChar *value, + int space); +XMLPUBFUN int XMLCALL + xmlValidateName (const xmlChar *value, + int space); +XMLPUBFUN int XMLCALL + xmlValidateNMToken (const xmlChar *value, + int space); +#endif + +XMLPUBFUN xmlChar * XMLCALL + xmlBuildQName (const xmlChar *ncname, + const xmlChar *prefix, + xmlChar *memory, + int len); +XMLPUBFUN xmlChar * XMLCALL + xmlSplitQName2 (const xmlChar *name, + xmlChar **prefix); +XMLPUBFUN const xmlChar * XMLCALL + xmlSplitQName3 (const xmlChar *name, + int *len); + +/* + * Handling Buffers. + */ + +XMLPUBFUN void XMLCALL + xmlSetBufferAllocationScheme(xmlBufferAllocationScheme scheme); +XMLPUBFUN xmlBufferAllocationScheme XMLCALL + xmlGetBufferAllocationScheme(void); + +XMLPUBFUN xmlBufferPtr XMLCALL + xmlBufferCreate (void); +XMLPUBFUN xmlBufferPtr XMLCALL + xmlBufferCreateSize (size_t size); +XMLPUBFUN xmlBufferPtr XMLCALL + xmlBufferCreateStatic (void *mem, + size_t size); +XMLPUBFUN int XMLCALL + xmlBufferResize (xmlBufferPtr buf, + unsigned int size); +XMLPUBFUN void XMLCALL + xmlBufferFree (xmlBufferPtr buf); +XMLPUBFUN int XMLCALL + xmlBufferDump (FILE *file, + xmlBufferPtr buf); +XMLPUBFUN int XMLCALL + xmlBufferAdd (xmlBufferPtr buf, + const xmlChar *str, + int len); +XMLPUBFUN int XMLCALL + xmlBufferAddHead (xmlBufferPtr buf, + const xmlChar *str, + int len); +XMLPUBFUN int XMLCALL + xmlBufferCat (xmlBufferPtr buf, + const xmlChar *str); +XMLPUBFUN int XMLCALL + xmlBufferCCat (xmlBufferPtr buf, + const char *str); +XMLPUBFUN int XMLCALL + xmlBufferShrink (xmlBufferPtr buf, + unsigned int len); +XMLPUBFUN int XMLCALL + xmlBufferGrow (xmlBufferPtr buf, + unsigned int len); +XMLPUBFUN void XMLCALL + xmlBufferEmpty (xmlBufferPtr buf); +XMLPUBFUN const xmlChar* XMLCALL + xmlBufferContent (const xmlBufferPtr buf); +XMLPUBFUN void XMLCALL + xmlBufferSetAllocationScheme(xmlBufferPtr buf, + xmlBufferAllocationScheme scheme); +XMLPUBFUN int XMLCALL + xmlBufferLength (const xmlBufferPtr buf); + +/* + * Creating/freeing new structures. + */ +XMLPUBFUN xmlDtdPtr XMLCALL + xmlCreateIntSubset (xmlDocPtr doc, + const xmlChar *name, + const xmlChar *ExternalID, + const xmlChar *SystemID); +XMLPUBFUN xmlDtdPtr XMLCALL + xmlNewDtd (xmlDocPtr doc, + const xmlChar *name, + const xmlChar *ExternalID, + const xmlChar *SystemID); +XMLPUBFUN xmlDtdPtr XMLCALL + xmlGetIntSubset (xmlDocPtr doc); +XMLPUBFUN void XMLCALL + xmlFreeDtd (xmlDtdPtr cur); +#ifdef LIBXML_LEGACY_ENABLED +XMLPUBFUN xmlNsPtr XMLCALL + xmlNewGlobalNs (xmlDocPtr doc, + const xmlChar *href, + const xmlChar *prefix); +#endif /* LIBXML_LEGACY_ENABLED */ +XMLPUBFUN xmlNsPtr XMLCALL + xmlNewNs (xmlNodePtr node, + const xmlChar *href, + const xmlChar *prefix); +XMLPUBFUN void XMLCALL + xmlFreeNs (xmlNsPtr cur); +XMLPUBFUN void XMLCALL + xmlFreeNsList (xmlNsPtr cur); +XMLPUBFUN xmlDocPtr XMLCALL + xmlNewDoc (const xmlChar *version); +XMLPUBFUN void XMLCALL + xmlFreeDoc (xmlDocPtr cur); +XMLPUBFUN xmlAttrPtr XMLCALL + xmlNewDocProp (xmlDocPtr doc, + const xmlChar *name, + const xmlChar *value); +#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_HTML_ENABLED) || \ + defined(LIBXML_SCHEMAS_ENABLED) +XMLPUBFUN xmlAttrPtr XMLCALL + xmlNewProp (xmlNodePtr node, + const xmlChar *name, + const xmlChar *value); +#endif +XMLPUBFUN xmlAttrPtr XMLCALL + xmlNewNsProp (xmlNodePtr node, + xmlNsPtr ns, + const xmlChar *name, + const xmlChar *value); +XMLPUBFUN xmlAttrPtr XMLCALL + xmlNewNsPropEatName (xmlNodePtr node, + xmlNsPtr ns, + xmlChar *name, + const xmlChar *value); +XMLPUBFUN void XMLCALL + xmlFreePropList (xmlAttrPtr cur); +XMLPUBFUN void XMLCALL + xmlFreeProp (xmlAttrPtr cur); +XMLPUBFUN xmlAttrPtr XMLCALL + xmlCopyProp (xmlNodePtr target, + xmlAttrPtr cur); +XMLPUBFUN xmlAttrPtr XMLCALL + xmlCopyPropList (xmlNodePtr target, + xmlAttrPtr cur); +#ifdef LIBXML_TREE_ENABLED +XMLPUBFUN xmlDtdPtr XMLCALL + xmlCopyDtd (xmlDtdPtr dtd); +#endif /* LIBXML_TREE_ENABLED */ +#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) +XMLPUBFUN xmlDocPtr XMLCALL + xmlCopyDoc (xmlDocPtr doc, + int recursive); +#endif /* defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) */ +/* + * Creating new nodes. + */ +XMLPUBFUN xmlNodePtr XMLCALL + xmlNewDocNode (xmlDocPtr doc, + xmlNsPtr ns, + const xmlChar *name, + const xmlChar *content); +XMLPUBFUN xmlNodePtr XMLCALL + xmlNewDocNodeEatName (xmlDocPtr doc, + xmlNsPtr ns, + xmlChar *name, + const xmlChar *content); +XMLPUBFUN xmlNodePtr XMLCALL + xmlNewNode (xmlNsPtr ns, + const xmlChar *name); +XMLPUBFUN xmlNodePtr XMLCALL + xmlNewNodeEatName (xmlNsPtr ns, + xmlChar *name); +#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) +XMLPUBFUN xmlNodePtr XMLCALL + xmlNewChild (xmlNodePtr parent, + xmlNsPtr ns, + const xmlChar *name, + const xmlChar *content); +#endif +XMLPUBFUN xmlNodePtr XMLCALL + xmlNewDocText (xmlDocPtr doc, + const xmlChar *content); +XMLPUBFUN xmlNodePtr XMLCALL + xmlNewText (const xmlChar *content); +XMLPUBFUN xmlNodePtr XMLCALL + xmlNewDocPI (xmlDocPtr doc, + const xmlChar *name, + const xmlChar *content); +XMLPUBFUN xmlNodePtr XMLCALL + xmlNewPI (const xmlChar *name, + const xmlChar *content); +XMLPUBFUN xmlNodePtr XMLCALL + xmlNewDocTextLen (xmlDocPtr doc, + const xmlChar *content, + int len); +XMLPUBFUN xmlNodePtr XMLCALL + xmlNewTextLen (const xmlChar *content, + int len); +XMLPUBFUN xmlNodePtr XMLCALL + xmlNewDocComment (xmlDocPtr doc, + const xmlChar *content); +XMLPUBFUN xmlNodePtr XMLCALL + xmlNewComment (const xmlChar *content); +XMLPUBFUN xmlNodePtr XMLCALL + xmlNewCDataBlock (xmlDocPtr doc, + const xmlChar *content, + int len); +XMLPUBFUN xmlNodePtr XMLCALL + xmlNewCharRef (xmlDocPtr doc, + const xmlChar *name); +XMLPUBFUN xmlNodePtr XMLCALL + xmlNewReference (xmlDocPtr doc, + const xmlChar *name); +XMLPUBFUN xmlNodePtr XMLCALL + xmlCopyNode (const xmlNodePtr node, + int recursive); +XMLPUBFUN xmlNodePtr XMLCALL + xmlDocCopyNode (const xmlNodePtr node, + xmlDocPtr doc, + int recursive); +XMLPUBFUN xmlNodePtr XMLCALL + xmlDocCopyNodeList (xmlDocPtr doc, + const xmlNodePtr node); +XMLPUBFUN xmlNodePtr XMLCALL + xmlCopyNodeList (const xmlNodePtr node); +#ifdef LIBXML_TREE_ENABLED +XMLPUBFUN xmlNodePtr XMLCALL + xmlNewTextChild (xmlNodePtr parent, + xmlNsPtr ns, + const xmlChar *name, + const xmlChar *content); +XMLPUBFUN xmlNodePtr XMLCALL + xmlNewDocRawNode (xmlDocPtr doc, + xmlNsPtr ns, + const xmlChar *name, + const xmlChar *content); +XMLPUBFUN xmlNodePtr XMLCALL + xmlNewDocFragment (xmlDocPtr doc); +#endif /* LIBXML_TREE_ENABLED */ + +/* + * Navigating. + */ +XMLPUBFUN long XMLCALL + xmlGetLineNo (xmlNodePtr node); +#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_DEBUG_ENABLED) +XMLPUBFUN xmlChar * XMLCALL + xmlGetNodePath (xmlNodePtr node); +#endif /* defined(LIBXML_TREE_ENABLED) || defined(LIBXML_DEBUG_ENABLED) */ +XMLPUBFUN xmlNodePtr XMLCALL + xmlDocGetRootElement (xmlDocPtr doc); +XMLPUBFUN xmlNodePtr XMLCALL + xmlGetLastChild (xmlNodePtr parent); +XMLPUBFUN int XMLCALL + xmlNodeIsText (xmlNodePtr node); +XMLPUBFUN int XMLCALL + xmlIsBlankNode (xmlNodePtr node); + +/* + * Changing the structure. + */ +#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_WRITER_ENABLED) +XMLPUBFUN xmlNodePtr XMLCALL + xmlDocSetRootElement (xmlDocPtr doc, + xmlNodePtr root); +#endif /* defined(LIBXML_TREE_ENABLED) || defined(LIBXML_WRITER_ENABLED) */ +#ifdef LIBXML_TREE_ENABLED +XMLPUBFUN void XMLCALL + xmlNodeSetName (xmlNodePtr cur, + const xmlChar *name); +#endif /* LIBXML_TREE_ENABLED */ +XMLPUBFUN xmlNodePtr XMLCALL + xmlAddChild (xmlNodePtr parent, + xmlNodePtr cur); +XMLPUBFUN xmlNodePtr XMLCALL + xmlAddChildList (xmlNodePtr parent, + xmlNodePtr cur); +#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_WRITER_ENABLED) +XMLPUBFUN xmlNodePtr XMLCALL + xmlReplaceNode (xmlNodePtr old, + xmlNodePtr cur); +#endif /* defined(LIBXML_TREE_ENABLED) || defined(LIBXML_WRITER_ENABLED) */ +#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_HTML_ENABLED) || \ + defined(LIBXML_SCHEMAS_ENABLED) +XMLPUBFUN xmlNodePtr XMLCALL + xmlAddPrevSibling (xmlNodePtr cur, + xmlNodePtr elem); +#endif /* LIBXML_TREE_ENABLED || LIBXML_HTML_ENABLED || LIBXML_SCHEMAS_ENABLED */ +XMLPUBFUN xmlNodePtr XMLCALL + xmlAddSibling (xmlNodePtr cur, + xmlNodePtr elem); +XMLPUBFUN xmlNodePtr XMLCALL + xmlAddNextSibling (xmlNodePtr cur, + xmlNodePtr elem); +XMLPUBFUN void XMLCALL + xmlUnlinkNode (xmlNodePtr cur); +XMLPUBFUN xmlNodePtr XMLCALL + xmlTextMerge (xmlNodePtr first, + xmlNodePtr second); +XMLPUBFUN int XMLCALL + xmlTextConcat (xmlNodePtr node, + const xmlChar *content, + int len); +XMLPUBFUN void XMLCALL + xmlFreeNodeList (xmlNodePtr cur); +XMLPUBFUN void XMLCALL + xmlFreeNode (xmlNodePtr cur); +XMLPUBFUN void XMLCALL + xmlSetTreeDoc (xmlNodePtr tree, + xmlDocPtr doc); +XMLPUBFUN void XMLCALL + xmlSetListDoc (xmlNodePtr list, + xmlDocPtr doc); +/* + * Namespaces. + */ +XMLPUBFUN xmlNsPtr XMLCALL + xmlSearchNs (xmlDocPtr doc, + xmlNodePtr node, + const xmlChar *nameSpace); +XMLPUBFUN xmlNsPtr XMLCALL + xmlSearchNsByHref (xmlDocPtr doc, + xmlNodePtr node, + const xmlChar *href); +#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) +XMLPUBFUN xmlNsPtr * XMLCALL + xmlGetNsList (xmlDocPtr doc, + xmlNodePtr node); +#endif /* defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XPATH_ENABLED) */ + +XMLPUBFUN void XMLCALL + xmlSetNs (xmlNodePtr node, + xmlNsPtr ns); +XMLPUBFUN xmlNsPtr XMLCALL + xmlCopyNamespace (xmlNsPtr cur); +XMLPUBFUN xmlNsPtr XMLCALL + xmlCopyNamespaceList (xmlNsPtr cur); + +/* + * Changing the content. + */ +#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XINCLUDE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) || defined(LIBXML_HTML_ENABLED) +XMLPUBFUN xmlAttrPtr XMLCALL + xmlSetProp (xmlNodePtr node, + const xmlChar *name, + const xmlChar *value); +XMLPUBFUN xmlAttrPtr XMLCALL + xmlSetNsProp (xmlNodePtr node, + xmlNsPtr ns, + const xmlChar *name, + const xmlChar *value); +#endif /* defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XINCLUDE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) || defined(LIBXML_HTML_ENABLED) */ +XMLPUBFUN xmlChar * XMLCALL + xmlGetNoNsProp (xmlNodePtr node, + const xmlChar *name); +XMLPUBFUN xmlChar * XMLCALL + xmlGetProp (xmlNodePtr node, + const xmlChar *name); +XMLPUBFUN xmlAttrPtr XMLCALL + xmlHasProp (xmlNodePtr node, + const xmlChar *name); +XMLPUBFUN xmlAttrPtr XMLCALL + xmlHasNsProp (xmlNodePtr node, + const xmlChar *name, + const xmlChar *nameSpace); +XMLPUBFUN xmlChar * XMLCALL + xmlGetNsProp (xmlNodePtr node, + const xmlChar *name, + const xmlChar *nameSpace); +XMLPUBFUN xmlNodePtr XMLCALL + xmlStringGetNodeList (xmlDocPtr doc, + const xmlChar *value); +XMLPUBFUN xmlNodePtr XMLCALL + xmlStringLenGetNodeList (xmlDocPtr doc, + const xmlChar *value, + int len); +XMLPUBFUN xmlChar * XMLCALL + xmlNodeListGetString (xmlDocPtr doc, + xmlNodePtr list, + int inLine); +#ifdef LIBXML_TREE_ENABLED +XMLPUBFUN xmlChar * XMLCALL + xmlNodeListGetRawString (xmlDocPtr doc, + xmlNodePtr list, + int inLine); +#endif /* LIBXML_TREE_ENABLED */ +XMLPUBFUN void XMLCALL + xmlNodeSetContent (xmlNodePtr cur, + const xmlChar *content); +#ifdef LIBXML_TREE_ENABLED +XMLPUBFUN void XMLCALL + xmlNodeSetContentLen (xmlNodePtr cur, + const xmlChar *content, + int len); +#endif /* LIBXML_TREE_ENABLED */ +XMLPUBFUN void XMLCALL + xmlNodeAddContent (xmlNodePtr cur, + const xmlChar *content); +XMLPUBFUN void XMLCALL + xmlNodeAddContentLen (xmlNodePtr cur, + const xmlChar *content, + int len); +XMLPUBFUN xmlChar * XMLCALL + xmlNodeGetContent (xmlNodePtr cur); +XMLPUBFUN int XMLCALL + xmlNodeBufGetContent (xmlBufferPtr buffer, + xmlNodePtr cur); +XMLPUBFUN xmlChar * XMLCALL + xmlNodeGetLang (xmlNodePtr cur); +XMLPUBFUN int XMLCALL + xmlNodeGetSpacePreserve (xmlNodePtr cur); +#ifdef LIBXML_TREE_ENABLED +XMLPUBFUN void XMLCALL + xmlNodeSetLang (xmlNodePtr cur, + const xmlChar *lang); +XMLPUBFUN void XMLCALL + xmlNodeSetSpacePreserve (xmlNodePtr cur, + int val); +#endif /* LIBXML_TREE_ENABLED */ +XMLPUBFUN xmlChar * XMLCALL + xmlNodeGetBase (xmlDocPtr doc, + xmlNodePtr cur); +#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XINCLUDE_ENABLED) +XMLPUBFUN void XMLCALL + xmlNodeSetBase (xmlNodePtr cur, + const xmlChar *uri); +#endif + +/* + * Removing content. + */ +XMLPUBFUN int XMLCALL + xmlRemoveProp (xmlAttrPtr cur); +#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) +XMLPUBFUN int XMLCALL + xmlUnsetNsProp (xmlNodePtr node, + xmlNsPtr ns, + const xmlChar *name); +XMLPUBFUN int XMLCALL + xmlUnsetProp (xmlNodePtr node, + const xmlChar *name); +#endif /* defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) */ + +/* + * Internal, don't use. + */ +XMLPUBFUN void XMLCALL + xmlBufferWriteCHAR (xmlBufferPtr buf, + const xmlChar *string); +XMLPUBFUN void XMLCALL + xmlBufferWriteChar (xmlBufferPtr buf, + const char *string); +XMLPUBFUN void XMLCALL + xmlBufferWriteQuotedString(xmlBufferPtr buf, + const xmlChar *string); + +#ifdef LIBXML_OUTPUT_ENABLED +XMLPUBFUN void xmlAttrSerializeTxtContent(xmlBufferPtr buf, + xmlDocPtr doc, + xmlAttrPtr attr, + const xmlChar *string); +#endif /* LIBXML_OUTPUT_ENABLED */ + +#ifdef LIBXML_TREE_ENABLED +/* + * Namespace handling. + */ +XMLPUBFUN int XMLCALL + xmlReconciliateNs (xmlDocPtr doc, + xmlNodePtr tree); +#endif + +#ifdef LIBXML_OUTPUT_ENABLED +/* + * Saving. + */ +XMLPUBFUN void XMLCALL + xmlDocDumpFormatMemory (xmlDocPtr cur, + xmlChar **mem, + int *size, + int format); +XMLPUBFUN void XMLCALL + xmlDocDumpMemory (xmlDocPtr cur, + xmlChar **mem, + int *size); +XMLPUBFUN void XMLCALL + xmlDocDumpMemoryEnc (xmlDocPtr out_doc, + xmlChar **doc_txt_ptr, + int * doc_txt_len, + const char *txt_encoding); +XMLPUBFUN void XMLCALL + xmlDocDumpFormatMemoryEnc(xmlDocPtr out_doc, + xmlChar **doc_txt_ptr, + int * doc_txt_len, + const char *txt_encoding, + int format); +XMLPUBFUN int XMLCALL + xmlDocFormatDump (FILE *f, + xmlDocPtr cur, + int format); +XMLPUBFUN int XMLCALL + xmlDocDump (FILE *f, + xmlDocPtr cur); +XMLPUBFUN void XMLCALL + xmlElemDump (FILE *f, + xmlDocPtr doc, + xmlNodePtr cur); +XMLPUBFUN int XMLCALL + xmlSaveFile (const char *filename, + xmlDocPtr cur); +XMLPUBFUN int XMLCALL + xmlSaveFormatFile (const char *filename, + xmlDocPtr cur, + int format); +XMLPUBFUN int XMLCALL + xmlNodeDump (xmlBufferPtr buf, + xmlDocPtr doc, + xmlNodePtr cur, + int level, + int format); + +XMLPUBFUN int XMLCALL + xmlSaveFileTo (xmlOutputBufferPtr buf, + xmlDocPtr cur, + const char *encoding); +XMLPUBFUN int XMLCALL + xmlSaveFormatFileTo (xmlOutputBufferPtr buf, + xmlDocPtr cur, + const char *encoding, + int format); +XMLPUBFUN void XMLCALL + xmlNodeDumpOutput (xmlOutputBufferPtr buf, + xmlDocPtr doc, + xmlNodePtr cur, + int level, + int format, + const char *encoding); + +XMLPUBFUN int XMLCALL + xmlSaveFormatFileEnc (const char *filename, + xmlDocPtr cur, + const char *encoding, + int format); + +XMLPUBFUN int XMLCALL + xmlSaveFileEnc (const char *filename, + xmlDocPtr cur, + const char *encoding); + +#endif /* LIBXML_OUTPUT_ENABLED */ +/* + * XHTML + */ +XMLPUBFUN int XMLCALL + xmlIsXHTML (const xmlChar *systemID, + const xmlChar *publicID); + +/* + * Compression. + */ +XMLPUBFUN int XMLCALL + xmlGetDocCompressMode (xmlDocPtr doc); +XMLPUBFUN void XMLCALL + xmlSetDocCompressMode (xmlDocPtr doc, + int mode); +XMLPUBFUN int XMLCALL + xmlGetCompressMode (void); +XMLPUBFUN void XMLCALL + xmlSetCompressMode (int mode); + +/* +* DOM-wrapper helper functions. +*/ +XMLPUBFUN xmlDOMWrapCtxtPtr XMLCALL + xmlDOMWrapNewCtxt (void); +XMLPUBFUN void XMLCALL + xmlDOMWrapFreeCtxt (xmlDOMWrapCtxtPtr ctxt); +XMLPUBFUN int XMLCALL + xmlDOMWrapReconcileNamespaces(xmlDOMWrapCtxtPtr ctxt, + xmlNodePtr elem, + int options); +XMLPUBFUN int XMLCALL + xmlDOMWrapAdoptNode (xmlDOMWrapCtxtPtr ctxt, + xmlDocPtr sourceDoc, + xmlNodePtr node, + xmlDocPtr destDoc, + xmlNodePtr destParent, + int options); +XMLPUBFUN int XMLCALL + xmlDOMWrapRemoveNode (xmlDOMWrapCtxtPtr ctxt, + xmlDocPtr doc, + xmlNodePtr node, + int options); +XMLPUBFUN int XMLCALL + xmlDOMWrapCloneNode (xmlDOMWrapCtxtPtr ctxt, + xmlDocPtr sourceDoc, + xmlNodePtr node, + xmlNodePtr *clonedNode, + xmlDocPtr destDoc, + xmlNodePtr destParent, + int deep, + int options); + +#ifdef __cplusplus +} +#endif +#ifndef __XML_PARSER_H__ +#include +#endif + +#endif /* __XML_TREE_H__ */ + diff --git a/gettext-tools/gnulib-lib/libxml/uri.c b/gettext-tools/gnulib-lib/libxml/uri.c new file mode 100644 index 0000000..1e29223 --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/uri.c @@ -0,0 +1,2483 @@ +/** + * uri.c: set of generic URI related routines + * + * Reference: RFCs 2396, 2732 and 2373 + * + * See Copyright for the status of this software. + * + * daniel@veillard.com + */ + +#define IN_LIBXML +#include "libxml.h" + +#include + +#include +#include +#include +#include + +/************************************************************************ + * * + * Macros to differentiate various character type * + * directly extracted from RFC 2396 * + * * + ************************************************************************/ + +/* + * alpha = lowalpha | upalpha + */ +#define IS_ALPHA(x) (IS_LOWALPHA(x) || IS_UPALPHA(x)) + + +/* + * lowalpha = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" | + * "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" | "s" | "t" | + * "u" | "v" | "w" | "x" | "y" | "z" + */ + +#define IS_LOWALPHA(x) (((x) >= 'a') && ((x) <= 'z')) + +/* + * upalpha = "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "J" | + * "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" | "S" | "T" | + * "U" | "V" | "W" | "X" | "Y" | "Z" + */ +#define IS_UPALPHA(x) (((x) >= 'A') && ((x) <= 'Z')) + +#ifdef IS_DIGIT +#undef IS_DIGIT +#endif +/* + * digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" + */ +#define IS_DIGIT(x) (((x) >= '0') && ((x) <= '9')) + +/* + * alphanum = alpha | digit + */ + +#define IS_ALPHANUM(x) (IS_ALPHA(x) || IS_DIGIT(x)) + +/* + * hex = digit | "A" | "B" | "C" | "D" | "E" | "F" | + * "a" | "b" | "c" | "d" | "e" | "f" + */ + +#define IS_HEX(x) ((IS_DIGIT(x)) || (((x) >= 'a') && ((x) <= 'f')) || \ + (((x) >= 'A') && ((x) <= 'F'))) + +/* + * mark = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")" + */ + +#define IS_MARK(x) (((x) == '-') || ((x) == '_') || ((x) == '.') || \ + ((x) == '!') || ((x) == '~') || ((x) == '*') || ((x) == '\'') || \ + ((x) == '(') || ((x) == ')')) + + +/* + * reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | "," | + * "[" | "]" + */ + +#define IS_RESERVED(x) (((x) == ';') || ((x) == '/') || ((x) == '?') || \ + ((x) == ':') || ((x) == '@') || ((x) == '&') || ((x) == '=') || \ + ((x) == '+') || ((x) == '$') || ((x) == ',') || ((x) == '[') || \ + ((x) == ']')) + +/* + * unreserved = alphanum | mark + */ + +#define IS_UNRESERVED(x) (IS_ALPHANUM(x) || IS_MARK(x)) + +/* + * escaped = "%" hex hex + */ + +#define IS_ESCAPED(p) ((*(p) == '%') && (IS_HEX((p)[1])) && \ + (IS_HEX((p)[2]))) + +/* + * uric_no_slash = unreserved | escaped | ";" | "?" | ":" | "@" | + * "&" | "=" | "+" | "$" | "," + */ +#define IS_URIC_NO_SLASH(p) ((IS_UNRESERVED(*(p))) || (IS_ESCAPED(p)) ||\ + ((*(p) == ';')) || ((*(p) == '?')) || ((*(p) == ':')) ||\ + ((*(p) == '@')) || ((*(p) == '&')) || ((*(p) == '=')) ||\ + ((*(p) == '+')) || ((*(p) == '$')) || ((*(p) == ','))) + +/* + * pchar = unreserved | escaped | ":" | "@" | "&" | "=" | "+" | "$" | "," + */ +#define IS_PCHAR(p) ((IS_UNRESERVED(*(p))) || (IS_ESCAPED(p)) || \ + ((*(p) == ':')) || ((*(p) == '@')) || ((*(p) == '&')) ||\ + ((*(p) == '=')) || ((*(p) == '+')) || ((*(p) == '$')) ||\ + ((*(p) == ','))) + +/* + * rel_segment = 1*( unreserved | escaped | + * ";" | "@" | "&" | "=" | "+" | "$" | "," ) + */ + +#define IS_SEGMENT(p) ((IS_UNRESERVED(*(p))) || (IS_ESCAPED(p)) || \ + ((*(p) == ';')) || ((*(p) == '@')) || ((*(p) == '&')) || \ + ((*(p) == '=')) || ((*(p) == '+')) || ((*(p) == '$')) || \ + ((*(p) == ','))) + +/* + * scheme = alpha *( alpha | digit | "+" | "-" | "." ) + */ + +#define IS_SCHEME(x) ((IS_ALPHA(x)) || (IS_DIGIT(x)) || \ + ((x) == '+') || ((x) == '-') || ((x) == '.')) + +/* + * reg_name = 1*( unreserved | escaped | "$" | "," | + * ";" | ":" | "@" | "&" | "=" | "+" ) + */ + +#define IS_REG_NAME(p) ((IS_UNRESERVED(*(p))) || (IS_ESCAPED(p)) || \ + ((*(p) == '$')) || ((*(p) == ',')) || ((*(p) == ';')) || \ + ((*(p) == ':')) || ((*(p) == '@')) || ((*(p) == '&')) || \ + ((*(p) == '=')) || ((*(p) == '+'))) + +/* + * userinfo = *( unreserved | escaped | ";" | ":" | "&" | "=" | + * "+" | "$" | "," ) + */ +#define IS_USERINFO(p) ((IS_UNRESERVED(*(p))) || (IS_ESCAPED(p)) || \ + ((*(p) == ';')) || ((*(p) == ':')) || ((*(p) == '&')) || \ + ((*(p) == '=')) || ((*(p) == '+')) || ((*(p) == '$')) || \ + ((*(p) == ','))) + +/* + * uric = reserved | unreserved | escaped + */ + +#define IS_URIC(p) ((IS_UNRESERVED(*(p))) || (IS_ESCAPED(p)) || \ + (IS_RESERVED(*(p)))) + +/* +* unwise = "{" | "}" | "|" | "\" | "^" | "`" +*/ + +#define IS_UNWISE(p) \ + (((*(p) == '{')) || ((*(p) == '}')) || ((*(p) == '|')) || \ + ((*(p) == '\\')) || ((*(p) == '^')) || ((*(p) == '[')) || \ + ((*(p) == ']')) || ((*(p) == '`'))) + +/* + * Skip to next pointer char, handle escaped sequences + */ + +#define NEXT(p) ((*p == '%')? p += 3 : p++) + +/* + * Productions from the spec. + * + * authority = server | reg_name + * reg_name = 1*( unreserved | escaped | "$" | "," | + * ";" | ":" | "@" | "&" | "=" | "+" ) + * + * path = [ abs_path | opaque_part ] + */ + +#define STRNDUP(s, n) (char *) xmlStrndup((const xmlChar *)(s), (n)) + +/************************************************************************ + * * + * Generic URI structure functions * + * * + ************************************************************************/ + +/** + * xmlCreateURI: + * + * Simply creates an empty xmlURI + * + * Returns the new structure or NULL in case of error + */ +xmlURIPtr +xmlCreateURI(void) { + xmlURIPtr ret; + + ret = (xmlURIPtr) xmlMalloc(sizeof(xmlURI)); + if (ret == NULL) { + xmlGenericError(xmlGenericErrorContext, + "xmlCreateURI: out of memory\n"); + return(NULL); + } + memset(ret, 0, sizeof(xmlURI)); + return(ret); +} + +/** + * xmlSaveUri: + * @uri: pointer to an xmlURI + * + * Save the URI as an escaped string + * + * Returns a new string (to be deallocated by caller) + */ +xmlChar * +xmlSaveUri(xmlURIPtr uri) { + xmlChar *ret = NULL; + const char *p; + int len; + int max; + + if (uri == NULL) return(NULL); + + + max = 80; + ret = (xmlChar *) xmlMallocAtomic((max + 1) * sizeof(xmlChar)); + if (ret == NULL) { + xmlGenericError(xmlGenericErrorContext, + "xmlSaveUri: out of memory\n"); + return(NULL); + } + len = 0; + + if (uri->scheme != NULL) { + p = uri->scheme; + while (*p != 0) { + if (len >= max) { + max *= 2; + ret = (xmlChar *) xmlRealloc(ret, (max + 1) * sizeof(xmlChar)); + if (ret == NULL) { + xmlGenericError(xmlGenericErrorContext, + "xmlSaveUri: out of memory\n"); + return(NULL); + } + } + ret[len++] = *p++; + } + if (len >= max) { + max *= 2; + ret = (xmlChar *) xmlRealloc(ret, (max + 1) * sizeof(xmlChar)); + if (ret == NULL) { + xmlGenericError(xmlGenericErrorContext, + "xmlSaveUri: out of memory\n"); + return(NULL); + } + } + ret[len++] = ':'; + } + if (uri->opaque != NULL) { + p = uri->opaque; + while (*p != 0) { + if (len + 3 >= max) { + max *= 2; + ret = (xmlChar *) xmlRealloc(ret, (max + 1) * sizeof(xmlChar)); + if (ret == NULL) { + xmlGenericError(xmlGenericErrorContext, + "xmlSaveUri: out of memory\n"); + return(NULL); + } + } + if (IS_RESERVED(*(p)) || IS_UNRESERVED(*(p))) + ret[len++] = *p++; + else { + int val = *(unsigned char *)p++; + int hi = val / 0x10, lo = val % 0x10; + ret[len++] = '%'; + ret[len++] = hi + (hi > 9? 'A'-10 : '0'); + ret[len++] = lo + (lo > 9? 'A'-10 : '0'); + } + } + } else { + if (uri->server != NULL) { + if (len + 3 >= max) { + max *= 2; + ret = (xmlChar *) xmlRealloc(ret, (max + 1) * sizeof(xmlChar)); + if (ret == NULL) { + xmlGenericError(xmlGenericErrorContext, + "xmlSaveUri: out of memory\n"); + return(NULL); + } + } + ret[len++] = '/'; + ret[len++] = '/'; + if (uri->user != NULL) { + p = uri->user; + while (*p != 0) { + if (len + 3 >= max) { + max *= 2; + ret = (xmlChar *) xmlRealloc(ret, + (max + 1) * sizeof(xmlChar)); + if (ret == NULL) { + xmlGenericError(xmlGenericErrorContext, + "xmlSaveUri: out of memory\n"); + return(NULL); + } + } + if ((IS_UNRESERVED(*(p))) || + ((*(p) == ';')) || ((*(p) == ':')) || + ((*(p) == '&')) || ((*(p) == '=')) || + ((*(p) == '+')) || ((*(p) == '$')) || + ((*(p) == ','))) + ret[len++] = *p++; + else { + int val = *(unsigned char *)p++; + int hi = val / 0x10, lo = val % 0x10; + ret[len++] = '%'; + ret[len++] = hi + (hi > 9? 'A'-10 : '0'); + ret[len++] = lo + (lo > 9? 'A'-10 : '0'); + } + } + if (len + 3 >= max) { + max *= 2; + ret = (xmlChar *) xmlRealloc(ret, + (max + 1) * sizeof(xmlChar)); + if (ret == NULL) { + xmlGenericError(xmlGenericErrorContext, + "xmlSaveUri: out of memory\n"); + return(NULL); + } + } + ret[len++] = '@'; + } + p = uri->server; + while (*p != 0) { + if (len >= max) { + max *= 2; + ret = (xmlChar *) xmlRealloc(ret, + (max + 1) * sizeof(xmlChar)); + if (ret == NULL) { + xmlGenericError(xmlGenericErrorContext, + "xmlSaveUri: out of memory\n"); + return(NULL); + } + } + ret[len++] = *p++; + } + if (uri->port > 0) { + if (len + 10 >= max) { + max *= 2; + ret = (xmlChar *) xmlRealloc(ret, + (max + 1) * sizeof(xmlChar)); + if (ret == NULL) { + xmlGenericError(xmlGenericErrorContext, + "xmlSaveUri: out of memory\n"); + return(NULL); + } + } + len += snprintf((char *) &ret[len], max - len, ":%d", uri->port); + } + } else if (uri->authority != NULL) { + if (len + 3 >= max) { + max *= 2; + ret = (xmlChar *) xmlRealloc(ret, + (max + 1) * sizeof(xmlChar)); + if (ret == NULL) { + xmlGenericError(xmlGenericErrorContext, + "xmlSaveUri: out of memory\n"); + return(NULL); + } + } + ret[len++] = '/'; + ret[len++] = '/'; + p = uri->authority; + while (*p != 0) { + if (len + 3 >= max) { + max *= 2; + ret = (xmlChar *) xmlRealloc(ret, + (max + 1) * sizeof(xmlChar)); + if (ret == NULL) { + xmlGenericError(xmlGenericErrorContext, + "xmlSaveUri: out of memory\n"); + return(NULL); + } + } + if ((IS_UNRESERVED(*(p))) || + ((*(p) == '$')) || ((*(p) == ',')) || ((*(p) == ';')) || + ((*(p) == ':')) || ((*(p) == '@')) || ((*(p) == '&')) || + ((*(p) == '=')) || ((*(p) == '+'))) + ret[len++] = *p++; + else { + int val = *(unsigned char *)p++; + int hi = val / 0x10, lo = val % 0x10; + ret[len++] = '%'; + ret[len++] = hi + (hi > 9? 'A'-10 : '0'); + ret[len++] = lo + (lo > 9? 'A'-10 : '0'); + } + } + } else if (uri->scheme != NULL) { + if (len + 3 >= max) { + max *= 2; + ret = (xmlChar *) xmlRealloc(ret, + (max + 1) * sizeof(xmlChar)); + if (ret == NULL) { + xmlGenericError(xmlGenericErrorContext, + "xmlSaveUri: out of memory\n"); + return(NULL); + } + } + ret[len++] = '/'; + ret[len++] = '/'; + } + if (uri->path != NULL) { + p = uri->path; + while (*p != 0) { + if (len + 3 >= max) { + max *= 2; + ret = (xmlChar *) xmlRealloc(ret, + (max + 1) * sizeof(xmlChar)); + if (ret == NULL) { + xmlGenericError(xmlGenericErrorContext, + "xmlSaveUri: out of memory\n"); + return(NULL); + } + } + if ((IS_UNRESERVED(*(p))) || ((*(p) == '/')) || + ((*(p) == ';')) || ((*(p) == '@')) || ((*(p) == '&')) || + ((*(p) == '=')) || ((*(p) == '+')) || ((*(p) == '$')) || + ((*(p) == ','))) + ret[len++] = *p++; + else { + int val = *(unsigned char *)p++; + int hi = val / 0x10, lo = val % 0x10; + ret[len++] = '%'; + ret[len++] = hi + (hi > 9? 'A'-10 : '0'); + ret[len++] = lo + (lo > 9? 'A'-10 : '0'); + } + } + } + if (uri->query != NULL) { + if (len + 3 >= max) { + max *= 2; + ret = (xmlChar *) xmlRealloc(ret, + (max + 1) * sizeof(xmlChar)); + if (ret == NULL) { + xmlGenericError(xmlGenericErrorContext, + "xmlSaveUri: out of memory\n"); + return(NULL); + } + } + ret[len++] = '?'; + p = uri->query; + while (*p != 0) { + if (len + 3 >= max) { + max *= 2; + ret = (xmlChar *) xmlRealloc(ret, + (max + 1) * sizeof(xmlChar)); + if (ret == NULL) { + xmlGenericError(xmlGenericErrorContext, + "xmlSaveUri: out of memory\n"); + return(NULL); + } + } + if ((IS_UNRESERVED(*(p))) || (IS_RESERVED(*(p)))) + ret[len++] = *p++; + else { + int val = *(unsigned char *)p++; + int hi = val / 0x10, lo = val % 0x10; + ret[len++] = '%'; + ret[len++] = hi + (hi > 9? 'A'-10 : '0'); + ret[len++] = lo + (lo > 9? 'A'-10 : '0'); + } + } + } + } + if (uri->fragment != NULL) { + if (len + 3 >= max) { + max *= 2; + ret = (xmlChar *) xmlRealloc(ret, + (max + 1) * sizeof(xmlChar)); + if (ret == NULL) { + xmlGenericError(xmlGenericErrorContext, + "xmlSaveUri: out of memory\n"); + return(NULL); + } + } + ret[len++] = '#'; + p = uri->fragment; + while (*p != 0) { + if (len + 3 >= max) { + max *= 2; + ret = (xmlChar *) xmlRealloc(ret, + (max + 1) * sizeof(xmlChar)); + if (ret == NULL) { + xmlGenericError(xmlGenericErrorContext, + "xmlSaveUri: out of memory\n"); + return(NULL); + } + } + if ((IS_UNRESERVED(*(p))) || (IS_RESERVED(*(p)))) + ret[len++] = *p++; + else { + int val = *(unsigned char *)p++; + int hi = val / 0x10, lo = val % 0x10; + ret[len++] = '%'; + ret[len++] = hi + (hi > 9? 'A'-10 : '0'); + ret[len++] = lo + (lo > 9? 'A'-10 : '0'); + } + } + } + if (len >= max) { + max *= 2; + ret = (xmlChar *) xmlRealloc(ret, (max + 1) * sizeof(xmlChar)); + if (ret == NULL) { + xmlGenericError(xmlGenericErrorContext, + "xmlSaveUri: out of memory\n"); + return(NULL); + } + } + ret[len++] = 0; + return(ret); +} + +/** + * xmlPrintURI: + * @stream: a FILE* for the output + * @uri: pointer to an xmlURI + * + * Prints the URI in the stream @stream. + */ +void +xmlPrintURI(FILE *stream, xmlURIPtr uri) { + xmlChar *out; + + out = xmlSaveUri(uri); + if (out != NULL) { + fprintf(stream, "%s", (char *) out); + xmlFree(out); + } +} + +/** + * xmlCleanURI: + * @uri: pointer to an xmlURI + * + * Make sure the xmlURI struct is free of content + */ +static void +xmlCleanURI(xmlURIPtr uri) { + if (uri == NULL) return; + + if (uri->scheme != NULL) xmlFree(uri->scheme); + uri->scheme = NULL; + if (uri->server != NULL) xmlFree(uri->server); + uri->server = NULL; + if (uri->user != NULL) xmlFree(uri->user); + uri->user = NULL; + if (uri->path != NULL) xmlFree(uri->path); + uri->path = NULL; + if (uri->fragment != NULL) xmlFree(uri->fragment); + uri->fragment = NULL; + if (uri->opaque != NULL) xmlFree(uri->opaque); + uri->opaque = NULL; + if (uri->authority != NULL) xmlFree(uri->authority); + uri->authority = NULL; + if (uri->query != NULL) xmlFree(uri->query); + uri->query = NULL; +} + +/** + * xmlFreeURI: + * @uri: pointer to an xmlURI + * + * Free up the xmlURI struct + */ +void +xmlFreeURI(xmlURIPtr uri) { + if (uri == NULL) return; + + if (uri->scheme != NULL) xmlFree(uri->scheme); + if (uri->server != NULL) xmlFree(uri->server); + if (uri->user != NULL) xmlFree(uri->user); + if (uri->path != NULL) xmlFree(uri->path); + if (uri->fragment != NULL) xmlFree(uri->fragment); + if (uri->opaque != NULL) xmlFree(uri->opaque); + if (uri->authority != NULL) xmlFree(uri->authority); + if (uri->query != NULL) xmlFree(uri->query); + xmlFree(uri); +} + +/************************************************************************ + * * + * Helper functions * + * * + ************************************************************************/ + +/** + * xmlNormalizeURIPath: + * @path: pointer to the path string + * + * Applies the 5 normalization steps to a path string--that is, RFC 2396 + * Section 5.2, steps 6.c through 6.g. + * + * Normalization occurs directly on the string, no new allocation is done + * + * Returns 0 or an error code + */ +int +xmlNormalizeURIPath(char *path) { + char *cur, *out; + + if (path == NULL) + return(-1); + + /* Skip all initial "/" chars. We want to get to the beginning of the + * first non-empty segment. + */ + cur = path; + while (cur[0] == '/') + ++cur; + if (cur[0] == '\0') + return(0); + + /* Keep everything we've seen so far. */ + out = cur; + + /* + * Analyze each segment in sequence for cases (c) and (d). + */ + while (cur[0] != '\0') { + /* + * c) All occurrences of "./", where "." is a complete path segment, + * are removed from the buffer string. + */ + if ((cur[0] == '.') && (cur[1] == '/')) { + cur += 2; + /* '//' normalization should be done at this point too */ + while (cur[0] == '/') + cur++; + continue; + } + + /* + * d) If the buffer string ends with "." as a complete path segment, + * that "." is removed. + */ + if ((cur[0] == '.') && (cur[1] == '\0')) + break; + + /* Otherwise keep the segment. */ + while (cur[0] != '/') { + if (cur[0] == '\0') + goto done_cd; + (out++)[0] = (cur++)[0]; + } + /* nomalize // */ + while ((cur[0] == '/') && (cur[1] == '/')) + cur++; + + (out++)[0] = (cur++)[0]; + } + done_cd: + out[0] = '\0'; + + /* Reset to the beginning of the first segment for the next sequence. */ + cur = path; + while (cur[0] == '/') + ++cur; + if (cur[0] == '\0') + return(0); + + /* + * Analyze each segment in sequence for cases (e) and (f). + * + * e) All occurrences of "/../", where is a + * complete path segment not equal to "..", are removed from the + * buffer string. Removal of these path segments is performed + * iteratively, removing the leftmost matching pattern on each + * iteration, until no matching pattern remains. + * + * f) If the buffer string ends with "/..", where + * is a complete path segment not equal to "..", that + * "/.." is removed. + * + * To satisfy the "iterative" clause in (e), we need to collapse the + * string every time we find something that needs to be removed. Thus, + * we don't need to keep two pointers into the string: we only need a + * "current position" pointer. + */ + while (1) { + char *segp, *tmp; + + /* At the beginning of each iteration of this loop, "cur" points to + * the first character of the segment we want to examine. + */ + + /* Find the end of the current segment. */ + segp = cur; + while ((segp[0] != '/') && (segp[0] != '\0')) + ++segp; + + /* If this is the last segment, we're done (we need at least two + * segments to meet the criteria for the (e) and (f) cases). + */ + if (segp[0] == '\0') + break; + + /* If the first segment is "..", or if the next segment _isn't_ "..", + * keep this segment and try the next one. + */ + ++segp; + if (((cur[0] == '.') && (cur[1] == '.') && (segp == cur+3)) + || ((segp[0] != '.') || (segp[1] != '.') + || ((segp[2] != '/') && (segp[2] != '\0')))) { + cur = segp; + continue; + } + + /* If we get here, remove this segment and the next one and back up + * to the previous segment (if there is one), to implement the + * "iteratively" clause. It's pretty much impossible to back up + * while maintaining two pointers into the buffer, so just compact + * the whole buffer now. + */ + + /* If this is the end of the buffer, we're done. */ + if (segp[2] == '\0') { + cur[0] = '\0'; + break; + } + /* Valgrind complained, strcpy(cur, segp + 3); */ + /* string will overlap, do not use strcpy */ + tmp = cur; + segp += 3; + while ((*tmp++ = *segp++) != 0); + + /* If there are no previous segments, then keep going from here. */ + segp = cur; + while ((segp > path) && ((--segp)[0] == '/')) + ; + if (segp == path) + continue; + + /* "segp" is pointing to the end of a previous segment; find it's + * start. We need to back up to the previous segment and start + * over with that to handle things like "foo/bar/../..". If we + * don't do this, then on the first pass we'll remove the "bar/..", + * but be pointing at the second ".." so we won't realize we can also + * remove the "foo/..". + */ + cur = segp; + while ((cur > path) && (cur[-1] != '/')) + --cur; + } + out[0] = '\0'; + + /* + * g) If the resulting buffer string still begins with one or more + * complete path segments of "..", then the reference is + * considered to be in error. Implementations may handle this + * error by retaining these components in the resolved path (i.e., + * treating them as part of the final URI), by removing them from + * the resolved path (i.e., discarding relative levels above the + * root), or by avoiding traversal of the reference. + * + * We discard them from the final path. + */ + if (path[0] == '/') { + cur = path; + while ((cur[0] == '/') && (cur[1] == '.') && (cur[2] == '.') + && ((cur[3] == '/') || (cur[3] == '\0'))) + cur += 3; + + if (cur != path) { + out = path; + while (cur[0] != '\0') + (out++)[0] = (cur++)[0]; + out[0] = 0; + } + } + + return(0); +} + +static int is_hex(char c) { + if (((c >= '0') && (c <= '9')) || + ((c >= 'a') && (c <= 'f')) || + ((c >= 'A') && (c <= 'F'))) + return(1); + return(0); +} + +/** + * xmlURIUnescapeString: + * @str: the string to unescape + * @len: the length in bytes to unescape (or <= 0 to indicate full string) + * @target: optional destination buffer + * + * Unescaping routine, does not do validity checks ! + * Output is direct unsigned char translation of %XX values (no encoding) + * + * Returns an copy of the string, but unescaped + */ +char * +xmlURIUnescapeString(const char *str, int len, char *target) { + char *ret, *out; + const char *in; + + if (str == NULL) + return(NULL); + if (len <= 0) len = strlen(str); + if (len < 0) return(NULL); + + if (target == NULL) { + ret = (char *) xmlMallocAtomic(len + 1); + if (ret == NULL) { + xmlGenericError(xmlGenericErrorContext, + "xmlURIUnescapeString: out of memory\n"); + return(NULL); + } + } else + ret = target; + in = str; + out = ret; + while(len > 0) { + if ((len > 2) && (*in == '%') && (is_hex(in[1])) && (is_hex(in[2]))) { + in++; + if ((*in >= '0') && (*in <= '9')) + *out = (*in - '0'); + else if ((*in >= 'a') && (*in <= 'f')) + *out = (*in - 'a') + 10; + else if ((*in >= 'A') && (*in <= 'F')) + *out = (*in - 'A') + 10; + in++; + if ((*in >= '0') && (*in <= '9')) + *out = *out * 16 + (*in - '0'); + else if ((*in >= 'a') && (*in <= 'f')) + *out = *out * 16 + (*in - 'a') + 10; + else if ((*in >= 'A') && (*in <= 'F')) + *out = *out * 16 + (*in - 'A') + 10; + in++; + len -= 3; + out++; + } else { + *out++ = *in++; + len--; + } + } + *out = 0; + return(ret); +} + +/** + * xmlURIEscapeStr: + * @str: string to escape + * @list: exception list string of chars not to escape + * + * This routine escapes a string to hex, ignoring reserved characters (a-z) + * and the characters in the exception list. + * + * Returns a new escaped string or NULL in case of error. + */ +xmlChar * +xmlURIEscapeStr(const xmlChar *str, const xmlChar *list) { + xmlChar *ret, ch; + const xmlChar *in; + + unsigned int len, out; + + if (str == NULL) + return(NULL); + if (str[0] == 0) + return(xmlStrdup(str)); + len = xmlStrlen(str); + if (!(len > 0)) return(NULL); + + len += 20; + ret = (xmlChar *) xmlMallocAtomic(len); + if (ret == NULL) { + xmlGenericError(xmlGenericErrorContext, + "xmlURIEscapeStr: out of memory\n"); + return(NULL); + } + in = (const xmlChar *) str; + out = 0; + while(*in != 0) { + if (len - out <= 3) { + len += 20; + ret = (xmlChar *) xmlRealloc(ret, len); + if (ret == NULL) { + xmlGenericError(xmlGenericErrorContext, + "xmlURIEscapeStr: out of memory\n"); + return(NULL); + } + } + + ch = *in; + + if ((ch != '@') && (!IS_UNRESERVED(ch)) && (!xmlStrchr(list, ch))) { + unsigned char val; + ret[out++] = '%'; + val = ch >> 4; + if (val <= 9) + ret[out++] = '0' + val; + else + ret[out++] = 'A' + val - 0xA; + val = ch & 0xF; + if (val <= 9) + ret[out++] = '0' + val; + else + ret[out++] = 'A' + val - 0xA; + in++; + } else { + ret[out++] = *in++; + } + + } + ret[out] = 0; + return(ret); +} + +/** + * xmlURIEscape: + * @str: the string of the URI to escape + * + * Escaping routine, does not do validity checks ! + * It will try to escape the chars needing this, but this is heuristic + * based it's impossible to be sure. + * + * Returns an copy of the string, but escaped + * + * 25 May 2001 + * Uses xmlParseURI and xmlURIEscapeStr to try to escape correctly + * according to RFC2396. + * - Carl Douglas + */ +xmlChar * +xmlURIEscape(const xmlChar * str) +{ + xmlChar *ret, *segment = NULL; + xmlURIPtr uri; + int ret2; + +#define NULLCHK(p) if(!p) { \ + xmlGenericError(xmlGenericErrorContext, \ + "xmlURIEscape: out of memory\n"); \ + return NULL; } + + if (str == NULL) + return (NULL); + + uri = xmlCreateURI(); + if (uri != NULL) { + /* + * Allow escaping errors in the unescaped form + */ + uri->cleanup = 1; + ret2 = xmlParseURIReference(uri, (const char *)str); + if (ret2) { + xmlFreeURI(uri); + return (NULL); + } + } + + if (!uri) + return NULL; + + ret = NULL; + + if (uri->scheme) { + segment = xmlURIEscapeStr(BAD_CAST uri->scheme, BAD_CAST "+-."); + NULLCHK(segment) + ret = xmlStrcat(ret, segment); + ret = xmlStrcat(ret, BAD_CAST ":"); + xmlFree(segment); + } + + if (uri->authority) { + segment = + xmlURIEscapeStr(BAD_CAST uri->authority, BAD_CAST "/?;:@"); + NULLCHK(segment) + ret = xmlStrcat(ret, BAD_CAST "//"); + ret = xmlStrcat(ret, segment); + xmlFree(segment); + } + + if (uri->user) { + segment = xmlURIEscapeStr(BAD_CAST uri->user, BAD_CAST ";:&=+$,"); + NULLCHK(segment) + ret = xmlStrcat(ret,BAD_CAST "//"); + ret = xmlStrcat(ret, segment); + ret = xmlStrcat(ret, BAD_CAST "@"); + xmlFree(segment); + } + + if (uri->server) { + segment = xmlURIEscapeStr(BAD_CAST uri->server, BAD_CAST "/?;:@"); + NULLCHK(segment) + if (uri->user == NULL) + ret = xmlStrcat(ret, BAD_CAST "//"); + ret = xmlStrcat(ret, segment); + xmlFree(segment); + } + + if (uri->port) { + xmlChar port[10]; + + snprintf((char *) port, 10, "%d", uri->port); + ret = xmlStrcat(ret, BAD_CAST ":"); + ret = xmlStrcat(ret, port); + } + + if (uri->path) { + segment = + xmlURIEscapeStr(BAD_CAST uri->path, BAD_CAST ":@&=+$,/?;"); + NULLCHK(segment) + ret = xmlStrcat(ret, segment); + xmlFree(segment); + } + + if (uri->query) { + segment = + xmlURIEscapeStr(BAD_CAST uri->query, BAD_CAST ";/?:@&=+,$"); + NULLCHK(segment) + ret = xmlStrcat(ret, BAD_CAST "?"); + ret = xmlStrcat(ret, segment); + xmlFree(segment); + } + + if (uri->opaque) { + segment = xmlURIEscapeStr(BAD_CAST uri->opaque, BAD_CAST ""); + NULLCHK(segment) + ret = xmlStrcat(ret, segment); + xmlFree(segment); + } + + if (uri->fragment) { + segment = xmlURIEscapeStr(BAD_CAST uri->fragment, BAD_CAST "#"); + NULLCHK(segment) + ret = xmlStrcat(ret, BAD_CAST "#"); + ret = xmlStrcat(ret, segment); + xmlFree(segment); + } + + xmlFreeURI(uri); +#undef NULLCHK + + return (ret); +} + +/************************************************************************ + * * + * Escaped URI parsing * + * * + ************************************************************************/ + +/** + * xmlParseURIFragment: + * @uri: pointer to an URI structure + * @str: pointer to the string to analyze + * + * Parse an URI fragment string and fills in the appropriate fields + * of the @uri structure. + * + * fragment = *uric + * + * Returns 0 or the error code + */ +static int +xmlParseURIFragment(xmlURIPtr uri, const char **str) +{ + const char *cur; + + if (str == NULL) + return (-1); + + cur = *str; + + while (IS_URIC(cur) || IS_UNWISE(cur)) + NEXT(cur); + if (uri != NULL) { + if (uri->fragment != NULL) + xmlFree(uri->fragment); + if (uri->cleanup & 2) + uri->fragment = STRNDUP(*str, cur - *str); + else + uri->fragment = xmlURIUnescapeString(*str, cur - *str, NULL); + } + *str = cur; + return (0); +} + +/** + * xmlParseURIQuery: + * @uri: pointer to an URI structure + * @str: pointer to the string to analyze + * + * Parse the query part of an URI + * + * query = *uric + * + * Returns 0 or the error code + */ +static int +xmlParseURIQuery(xmlURIPtr uri, const char **str) +{ + const char *cur; + + if (str == NULL) + return (-1); + + cur = *str; + + while ((IS_URIC(cur)) || + ((uri != NULL) && (uri->cleanup & 1) && (IS_UNWISE(cur)))) + NEXT(cur); + if (uri != NULL) { + if (uri->query != NULL) + xmlFree(uri->query); + if (uri->cleanup & 2) + uri->query = STRNDUP(*str, cur - *str); + else + uri->query = xmlURIUnescapeString(*str, cur - *str, NULL); + } + *str = cur; + return (0); +} + +/** + * xmlParseURIScheme: + * @uri: pointer to an URI structure + * @str: pointer to the string to analyze + * + * Parse an URI scheme + * + * scheme = alpha *( alpha | digit | "+" | "-" | "." ) + * + * Returns 0 or the error code + */ +static int +xmlParseURIScheme(xmlURIPtr uri, const char **str) { + const char *cur; + + if (str == NULL) + return(-1); + + cur = *str; + if (!IS_ALPHA(*cur)) + return(2); + cur++; + while (IS_SCHEME(*cur)) cur++; + if (uri != NULL) { + if (uri->scheme != NULL) xmlFree(uri->scheme); + uri->scheme = STRNDUP(*str, cur - *str); + } + *str = cur; + return(0); +} + +/** + * xmlParseURIOpaquePart: + * @uri: pointer to an URI structure + * @str: pointer to the string to analyze + * + * Parse an URI opaque part + * + * opaque_part = uric_no_slash *uric + * + * Returns 0 or the error code + */ +static int +xmlParseURIOpaquePart(xmlURIPtr uri, const char **str) +{ + const char *cur; + + if (str == NULL) + return (-1); + + cur = *str; + if (!((IS_URIC_NO_SLASH(cur)) || + ((uri != NULL) && (uri->cleanup & 1) && (IS_UNWISE(cur))))) { + return (3); + } + NEXT(cur); + while ((IS_URIC(cur)) || + ((uri != NULL) && (uri->cleanup & 1) && (IS_UNWISE(cur)))) + NEXT(cur); + if (uri != NULL) { + if (uri->opaque != NULL) + xmlFree(uri->opaque); + if (uri->cleanup & 2) + uri->opaque = STRNDUP(*str, cur - *str); + else + uri->opaque = xmlURIUnescapeString(*str, cur - *str, NULL); + } + *str = cur; + return (0); +} + +/** + * xmlParseURIServer: + * @uri: pointer to an URI structure + * @str: pointer to the string to analyze + * + * Parse a server subpart of an URI, it's a finer grain analysis + * of the authority part. + * + * server = [ [ userinfo "@" ] hostport ] + * userinfo = *( unreserved | escaped | + * ";" | ":" | "&" | "=" | "+" | "$" | "," ) + * hostport = host [ ":" port ] + * host = hostname | IPv4address | IPv6reference + * hostname = *( domainlabel "." ) toplabel [ "." ] + * domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum + * toplabel = alpha | alpha *( alphanum | "-" ) alphanum + * IPv6reference = "[" IPv6address "]" + * IPv6address = hexpart [ ":" IPv4address ] + * IPv4address = 1*3digit "." 1*3digit "." 1*3digit "." 1*3digit + * hexpart = hexseq | hexseq "::" [ hexseq ]| "::" [ hexseq ] + * hexseq = hex4 *( ":" hex4) + * hex4 = 1*4hexdig + * port = *digit + * + * Returns 0 or the error code + */ +static int +xmlParseURIServer(xmlURIPtr uri, const char **str) { + const char *cur; + const char *host, *tmp; + const int IPV4max = 4; + const int IPV6max = 8; + int oct; + + if (str == NULL) + return(-1); + + cur = *str; + + /* + * is there a userinfo ? + */ + while (IS_USERINFO(cur)) NEXT(cur); + if (*cur == '@') { + if (uri != NULL) { + if (uri->user != NULL) xmlFree(uri->user); + if (uri->cleanup & 2) + uri->path = STRNDUP(*str, cur - *str); + else + uri->user = xmlURIUnescapeString(*str, cur - *str, NULL); + } + cur++; + } else { + if (uri != NULL) { + if (uri->user != NULL) xmlFree(uri->user); + uri->user = NULL; + } + cur = *str; + } + /* + * This can be empty in the case where there is no server + */ + host = cur; + if (*cur == '/') { + if (uri != NULL) { + if (uri->authority != NULL) xmlFree(uri->authority); + uri->authority = NULL; + if (uri->server != NULL) xmlFree(uri->server); + uri->server = NULL; + uri->port = 0; + } + return(0); + } + /* + * host part of hostport can denote an IPV4 address, an IPV6 address + * or an unresolved name. Check the IP first, its easier to detect + * errors if wrong one. + * An IPV6 address must start with a '[' and end with a ']'. + */ + if (*cur == '[') { + int compress=0; + cur++; + for (oct = 0; oct < IPV6max; ++oct) { + if (*cur == ':') { + if (compress) + return(3); /* multiple compression attempted */ + if (!oct) { /* initial char is compression */ + if (*++cur != ':') + return(3); + } + compress = 1; /* set compression-encountered flag */ + cur++; /* skip over the second ':' */ + continue; + } + while(IS_HEX(*cur)) cur++; + if (oct == (IPV6max-1)) + continue; + if (*cur != ':') + break; + cur++; + } + if ((!compress) && (oct != IPV6max)) + return(3); + if (*cur != ']') + return(3); + if (uri != NULL) { + if (uri->server != NULL) xmlFree(uri->server); + uri->server = (char *)xmlStrndup((xmlChar *)host+1, + (cur-host)-1); + } + cur++; + } else { + /* + * Not IPV6, maybe IPV4 + */ + for (oct = 0; oct < IPV4max; ++oct) { + if (*cur == '.') + return(3); /* e.g. http://.xml/ or http://18.29..30/ */ + while(IS_DIGIT(*cur)) cur++; + if (oct == (IPV4max-1)) + continue; + if (*cur != '.') + break; + cur++; + } + } + if ((host[0] != '[') && (oct < IPV4max || (*cur == '.' && cur++) || + IS_ALPHA(*cur))) { + /* maybe host_name */ + if (!IS_ALPHANUM(*cur)) + return(4); /* e.g. http://xml.$oft */ + do { + do ++cur; while (IS_ALPHANUM(*cur)); + if (*cur == '-') { + --cur; + if (*cur == '.') + return(5); /* e.g. http://xml.-soft */ + ++cur; + continue; + } + if (*cur == '.') { + --cur; + if (*cur == '-') + return(6); /* e.g. http://xml-.soft */ + if (*cur == '.') + return(7); /* e.g. http://xml..soft */ + ++cur; + continue; + } + break; + } while (1); + tmp = cur; + if (tmp[-1] == '.') + --tmp; /* e.g. http://xml.$Oft/ */ + do --tmp; while (tmp >= host && IS_ALPHANUM(*tmp)); + if ((++tmp == host || tmp[-1] == '.') && !IS_ALPHA(*tmp)) + return(8); /* e.g. http://xmlsOft.0rg/ */ + } + if (uri != NULL) { + if (uri->authority != NULL) xmlFree(uri->authority); + uri->authority = NULL; + if (host[0] != '[') { /* it's not an IPV6 addr */ + if (uri->server != NULL) xmlFree(uri->server); + if (uri->cleanup & 2) + uri->server = STRNDUP(host, cur - host); + else + uri->server = xmlURIUnescapeString(host, cur - host, NULL); + } + } + /* + * finish by checking for a port presence. + */ + if (*cur == ':') { + cur++; + if (IS_DIGIT(*cur)) { + if (uri != NULL) + uri->port = 0; + while (IS_DIGIT(*cur)) { + if (uri != NULL) + uri->port = uri->port * 10 + (*cur - '0'); + cur++; + } + } + } + *str = cur; + return(0); +} + +/** + * xmlParseURIRelSegment: + * @uri: pointer to an URI structure + * @str: pointer to the string to analyze + * + * Parse an URI relative segment + * + * rel_segment = 1*( unreserved | escaped | ";" | "@" | "&" | "=" | + * "+" | "$" | "," ) + * + * Returns 0 or the error code + */ +static int +xmlParseURIRelSegment(xmlURIPtr uri, const char **str) +{ + const char *cur; + + if (str == NULL) + return (-1); + + cur = *str; + if (!((IS_SEGMENT(cur)) || + ((uri != NULL) && (uri->cleanup & 1) && (IS_UNWISE(cur))))) { + return (3); + } + NEXT(cur); + while ((IS_SEGMENT(cur)) || + ((uri != NULL) && (uri->cleanup & 1) && (IS_UNWISE(cur)))) + NEXT(cur); + if (uri != NULL) { + if (uri->path != NULL) + xmlFree(uri->path); + if (uri->cleanup & 2) + uri->path = STRNDUP(*str, cur - *str); + else + uri->path = xmlURIUnescapeString(*str, cur - *str, NULL); + } + *str = cur; + return (0); +} + +/** + * xmlParseURIPathSegments: + * @uri: pointer to an URI structure + * @str: pointer to the string to analyze + * @slash: should we add a leading slash + * + * Parse an URI set of path segments + * + * path_segments = segment *( "/" segment ) + * segment = *pchar *( ";" param ) + * param = *pchar + * + * Returns 0 or the error code + */ +static int +xmlParseURIPathSegments(xmlURIPtr uri, const char **str, int slash) +{ + const char *cur; + + if (str == NULL) + return (-1); + + cur = *str; + + do { + while ((IS_PCHAR(cur)) || + ((uri != NULL) && (uri->cleanup & 1) && (IS_UNWISE(cur)))) + NEXT(cur); + while (*cur == ';') { + cur++; + while ((IS_PCHAR(cur)) || + ((uri != NULL) && (uri->cleanup & 1) && (IS_UNWISE(cur)))) + NEXT(cur); + } + if (*cur != '/') + break; + cur++; + } while (1); + if (uri != NULL) { + int len, len2 = 0; + char *path; + + /* + * Concat the set of path segments to the current path + */ + len = cur - *str; + if (slash) + len++; + + if (uri->path != NULL) { + len2 = strlen(uri->path); + len += len2; + } + path = (char *) xmlMallocAtomic(len + 1); + if (path == NULL) { + xmlGenericError(xmlGenericErrorContext, + "xmlParseURIPathSegments: out of memory\n"); + *str = cur; + return (-1); + } + if (uri->path != NULL) + memcpy(path, uri->path, len2); + if (slash) { + path[len2] = '/'; + len2++; + } + path[len2] = 0; + if (cur - *str > 0) { + if (uri->cleanup & 2) { + memcpy(&path[len2], *str, cur - *str); + path[len2 + (cur - *str)] = 0; + } else + xmlURIUnescapeString(*str, cur - *str, &path[len2]); + } + if (uri->path != NULL) + xmlFree(uri->path); + uri->path = path; + } + *str = cur; + return (0); +} + +/** + * xmlParseURIAuthority: + * @uri: pointer to an URI structure + * @str: pointer to the string to analyze + * + * Parse the authority part of an URI. + * + * authority = server | reg_name + * server = [ [ userinfo "@" ] hostport ] + * reg_name = 1*( unreserved | escaped | "$" | "," | ";" | ":" | + * "@" | "&" | "=" | "+" ) + * + * Note : this is completely ambiguous since reg_name is allowed to + * use the full set of chars in use by server: + * + * 3.2.1. Registry-based Naming Authority + * + * The structure of a registry-based naming authority is specific + * to the URI scheme, but constrained to the allowed characters + * for an authority component. + * + * Returns 0 or the error code + */ +static int +xmlParseURIAuthority(xmlURIPtr uri, const char **str) { + const char *cur; + int ret; + + if (str == NULL) + return(-1); + + cur = *str; + + /* + * try first to parse it as a server string. + */ + ret = xmlParseURIServer(uri, str); + if ((ret == 0) && (*str != NULL) && + ((**str == 0) || (**str == '/') || (**str == '?'))) + return(0); + *str = cur; + + /* + * failed, fallback to reg_name + */ + if (!IS_REG_NAME(cur)) { + return(5); + } + NEXT(cur); + while (IS_REG_NAME(cur)) NEXT(cur); + if (uri != NULL) { + if (uri->server != NULL) xmlFree(uri->server); + uri->server = NULL; + if (uri->user != NULL) xmlFree(uri->user); + uri->user = NULL; + if (uri->authority != NULL) xmlFree(uri->authority); + if (uri->cleanup & 2) + uri->authority = STRNDUP(*str, cur - *str); + else + uri->authority = xmlURIUnescapeString(*str, cur - *str, NULL); + } + *str = cur; + return(0); +} + +/** + * xmlParseURIHierPart: + * @uri: pointer to an URI structure + * @str: pointer to the string to analyze + * + * Parse an URI hierarchical part + * + * hier_part = ( net_path | abs_path ) [ "?" query ] + * abs_path = "/" path_segments + * net_path = "//" authority [ abs_path ] + * + * Returns 0 or the error code + */ +static int +xmlParseURIHierPart(xmlURIPtr uri, const char **str) { + int ret; + const char *cur; + + if (str == NULL) + return(-1); + + cur = *str; + + if ((cur[0] == '/') && (cur[1] == '/')) { + cur += 2; + ret = xmlParseURIAuthority(uri, &cur); + if (ret != 0) + return(ret); + if (cur[0] == '/') { + cur++; + ret = xmlParseURIPathSegments(uri, &cur, 1); + } + } else if (cur[0] == '/') { + cur++; + ret = xmlParseURIPathSegments(uri, &cur, 1); + } else { + return(4); + } + if (ret != 0) + return(ret); + if (*cur == '?') { + cur++; + ret = xmlParseURIQuery(uri, &cur); + if (ret != 0) + return(ret); + } + *str = cur; + return(0); +} + +/** + * xmlParseAbsoluteURI: + * @uri: pointer to an URI structure + * @str: pointer to the string to analyze + * + * Parse an URI reference string and fills in the appropriate fields + * of the @uri structure + * + * absoluteURI = scheme ":" ( hier_part | opaque_part ) + * + * Returns 0 or the error code + */ +static int +xmlParseAbsoluteURI(xmlURIPtr uri, const char **str) { + int ret; + const char *cur; + + if (str == NULL) + return(-1); + + cur = *str; + + ret = xmlParseURIScheme(uri, str); + if (ret != 0) return(ret); + if (**str != ':') { + *str = cur; + return(1); + } + (*str)++; + if (**str == '/') + return(xmlParseURIHierPart(uri, str)); + return(xmlParseURIOpaquePart(uri, str)); +} + +/** + * xmlParseRelativeURI: + * @uri: pointer to an URI structure + * @str: pointer to the string to analyze + * + * Parse an relative URI string and fills in the appropriate fields + * of the @uri structure + * + * relativeURI = ( net_path | abs_path | rel_path ) [ "?" query ] + * abs_path = "/" path_segments + * net_path = "//" authority [ abs_path ] + * rel_path = rel_segment [ abs_path ] + * + * Returns 0 or the error code + */ +static int +xmlParseRelativeURI(xmlURIPtr uri, const char **str) { + int ret = 0; + const char *cur; + + if (str == NULL) + return(-1); + + cur = *str; + if ((cur[0] == '/') && (cur[1] == '/')) { + cur += 2; + ret = xmlParseURIAuthority(uri, &cur); + if (ret != 0) + return(ret); + if (cur[0] == '/') { + cur++; + ret = xmlParseURIPathSegments(uri, &cur, 1); + } + } else if (cur[0] == '/') { + cur++; + ret = xmlParseURIPathSegments(uri, &cur, 1); + } else if (cur[0] != '#' && cur[0] != '?') { + ret = xmlParseURIRelSegment(uri, &cur); + if (ret != 0) + return(ret); + if (cur[0] == '/') { + cur++; + ret = xmlParseURIPathSegments(uri, &cur, 1); + } + } + if (ret != 0) + return(ret); + if (*cur == '?') { + cur++; + ret = xmlParseURIQuery(uri, &cur); + if (ret != 0) + return(ret); + } + *str = cur; + return(ret); +} + +/** + * xmlParseURIReference: + * @uri: pointer to an URI structure + * @str: the string to analyze + * + * Parse an URI reference string and fills in the appropriate fields + * of the @uri structure + * + * URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ] + * + * Returns 0 or the error code + */ +int +xmlParseURIReference(xmlURIPtr uri, const char *str) { + int ret; + const char *tmp = str; + + if (str == NULL) + return(-1); + xmlCleanURI(uri); + + /* + * Try first to parse absolute refs, then fallback to relative if + * it fails. + */ + ret = xmlParseAbsoluteURI(uri, &str); + if (ret != 0) { + xmlCleanURI(uri); + str = tmp; + ret = xmlParseRelativeURI(uri, &str); + } + if (ret != 0) { + xmlCleanURI(uri); + return(ret); + } + + if (*str == '#') { + str++; + ret = xmlParseURIFragment(uri, &str); + if (ret != 0) return(ret); + } + if (*str != 0) { + xmlCleanURI(uri); + return(1); + } + return(0); +} + +/** + * xmlParseURI: + * @str: the URI string to analyze + * + * Parse an URI + * + * URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ] + * + * Returns a newly built xmlURIPtr or NULL in case of error + */ +xmlURIPtr +xmlParseURI(const char *str) { + xmlURIPtr uri; + int ret; + + if (str == NULL) + return(NULL); + uri = xmlCreateURI(); + if (uri != NULL) { + ret = xmlParseURIReference(uri, str); + if (ret) { + xmlFreeURI(uri); + return(NULL); + } + } + return(uri); +} + +/** + * xmlParseURIRaw: + * @str: the URI string to analyze + * @raw: if 1 unescaping of URI pieces are disabled + * + * Parse an URI but allows to keep intact the original fragments. + * + * URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ] + * + * Returns a newly built xmlURIPtr or NULL in case of error + */ +xmlURIPtr +xmlParseURIRaw(const char *str, int raw) { + xmlURIPtr uri; + int ret; + + if (str == NULL) + return(NULL); + uri = xmlCreateURI(); + if (uri != NULL) { + if (raw) { + uri->cleanup |= 2; + } + ret = xmlParseURIReference(uri, str); + if (ret) { + xmlFreeURI(uri); + return(NULL); + } + } + return(uri); +} + +/************************************************************************ + * * + * Public functions * + * * + ************************************************************************/ + +/** + * xmlBuildURI: + * @URI: the URI instance found in the document + * @base: the base value + * + * Computes he final URI of the reference done by checking that + * the given URI is valid, and building the final URI using the + * base URI. This is processed according to section 5.2 of the + * RFC 2396 + * + * 5.2. Resolving Relative References to Absolute Form + * + * Returns a new URI string (to be freed by the caller) or NULL in case + * of error. + */ +xmlChar * +xmlBuildURI(const xmlChar *URI, const xmlChar *base) { + xmlChar *val = NULL; + int ret, len, indx, cur, out; + xmlURIPtr ref = NULL; + xmlURIPtr bas = NULL; + xmlURIPtr res = NULL; + + /* + * 1) The URI reference is parsed into the potential four components and + * fragment identifier, as described in Section 4.3. + * + * NOTE that a completely empty URI is treated by modern browsers + * as a reference to "." rather than as a synonym for the current + * URI. Should we do that here? + */ + if (URI == NULL) + ret = -1; + else { + if (*URI) { + ref = xmlCreateURI(); + if (ref == NULL) + goto done; + ret = xmlParseURIReference(ref, (const char *) URI); + } + else + ret = 0; + } + if (ret != 0) + goto done; + if ((ref != NULL) && (ref->scheme != NULL)) { + /* + * The URI is absolute don't modify. + */ + val = xmlStrdup(URI); + goto done; + } + if (base == NULL) + ret = -1; + else { + bas = xmlCreateURI(); + if (bas == NULL) + goto done; + ret = xmlParseURIReference(bas, (const char *) base); + } + if (ret != 0) { + if (ref) + val = xmlSaveUri(ref); + goto done; + } + if (ref == NULL) { + /* + * the base fragment must be ignored + */ + if (bas->fragment != NULL) { + xmlFree(bas->fragment); + bas->fragment = NULL; + } + val = xmlSaveUri(bas); + goto done; + } + + /* + * 2) If the path component is empty and the scheme, authority, and + * query components are undefined, then it is a reference to the + * current document and we are done. Otherwise, the reference URI's + * query and fragment components are defined as found (or not found) + * within the URI reference and not inherited from the base URI. + * + * NOTE that in modern browsers, the parsing differs from the above + * in the following aspect: the query component is allowed to be + * defined while still treating this as a reference to the current + * document. + */ + res = xmlCreateURI(); + if (res == NULL) + goto done; + if ((ref->scheme == NULL) && (ref->path == NULL) && + ((ref->authority == NULL) && (ref->server == NULL))) { + if (bas->scheme != NULL) + res->scheme = xmlMemStrdup(bas->scheme); + if (bas->authority != NULL) + res->authority = xmlMemStrdup(bas->authority); + else if (bas->server != NULL) { + res->server = xmlMemStrdup(bas->server); + if (bas->user != NULL) + res->user = xmlMemStrdup(bas->user); + res->port = bas->port; + } + if (bas->path != NULL) + res->path = xmlMemStrdup(bas->path); + if (ref->query != NULL) + res->query = xmlMemStrdup(ref->query); + else if (bas->query != NULL) + res->query = xmlMemStrdup(bas->query); + if (ref->fragment != NULL) + res->fragment = xmlMemStrdup(ref->fragment); + goto step_7; + } + + /* + * 3) If the scheme component is defined, indicating that the reference + * starts with a scheme name, then the reference is interpreted as an + * absolute URI and we are done. Otherwise, the reference URI's + * scheme is inherited from the base URI's scheme component. + */ + if (ref->scheme != NULL) { + val = xmlSaveUri(ref); + goto done; + } + if (bas->scheme != NULL) + res->scheme = xmlMemStrdup(bas->scheme); + + if (ref->query != NULL) + res->query = xmlMemStrdup(ref->query); + if (ref->fragment != NULL) + res->fragment = xmlMemStrdup(ref->fragment); + + /* + * 4) If the authority component is defined, then the reference is a + * network-path and we skip to step 7. Otherwise, the reference + * URI's authority is inherited from the base URI's authority + * component, which will also be undefined if the URI scheme does not + * use an authority component. + */ + if ((ref->authority != NULL) || (ref->server != NULL)) { + if (ref->authority != NULL) + res->authority = xmlMemStrdup(ref->authority); + else { + res->server = xmlMemStrdup(ref->server); + if (ref->user != NULL) + res->user = xmlMemStrdup(ref->user); + res->port = ref->port; + } + if (ref->path != NULL) + res->path = xmlMemStrdup(ref->path); + goto step_7; + } + if (bas->authority != NULL) + res->authority = xmlMemStrdup(bas->authority); + else if (bas->server != NULL) { + res->server = xmlMemStrdup(bas->server); + if (bas->user != NULL) + res->user = xmlMemStrdup(bas->user); + res->port = bas->port; + } + + /* + * 5) If the path component begins with a slash character ("/"), then + * the reference is an absolute-path and we skip to step 7. + */ + if ((ref->path != NULL) && (ref->path[0] == '/')) { + res->path = xmlMemStrdup(ref->path); + goto step_7; + } + + + /* + * 6) If this step is reached, then we are resolving a relative-path + * reference. The relative path needs to be merged with the base + * URI's path. Although there are many ways to do this, we will + * describe a simple method using a separate string buffer. + * + * Allocate a buffer large enough for the result string. + */ + len = 2; /* extra / and 0 */ + if (ref->path != NULL) + len += strlen(ref->path); + if (bas->path != NULL) + len += strlen(bas->path); + res->path = (char *) xmlMallocAtomic(len); + if (res->path == NULL) { + xmlGenericError(xmlGenericErrorContext, + "xmlBuildURI: out of memory\n"); + goto done; + } + res->path[0] = 0; + + /* + * a) All but the last segment of the base URI's path component is + * copied to the buffer. In other words, any characters after the + * last (right-most) slash character, if any, are excluded. + */ + cur = 0; + out = 0; + if (bas->path != NULL) { + while (bas->path[cur] != 0) { + while ((bas->path[cur] != 0) && (bas->path[cur] != '/')) + cur++; + if (bas->path[cur] == 0) + break; + + cur++; + while (out < cur) { + res->path[out] = bas->path[out]; + out++; + } + } + } + res->path[out] = 0; + + /* + * b) The reference's path component is appended to the buffer + * string. + */ + if (ref->path != NULL && ref->path[0] != 0) { + indx = 0; + /* + * Ensure the path includes a '/' + */ + if ((out == 0) && (bas->server != NULL)) + res->path[out++] = '/'; + while (ref->path[indx] != 0) { + res->path[out++] = ref->path[indx++]; + } + } + res->path[out] = 0; + + /* + * Steps c) to h) are really path normalization steps + */ + xmlNormalizeURIPath(res->path); + +step_7: + + /* + * 7) The resulting URI components, including any inherited from the + * base URI, are recombined to give the absolute form of the URI + * reference. + */ + val = xmlSaveUri(res); + +done: + if (ref != NULL) + xmlFreeURI(ref); + if (bas != NULL) + xmlFreeURI(bas); + if (res != NULL) + xmlFreeURI(res); + return(val); +} + +/** + * xmlBuildRelativeURI: + * @URI: the URI reference under consideration + * @base: the base value + * + * Expresses the URI of the reference in terms relative to the + * base. Some examples of this operation include: + * base = "http://site1.com/docs/book1.html" + * URI input URI returned + * docs/pic1.gif pic1.gif + * docs/img/pic1.gif img/pic1.gif + * img/pic1.gif ../img/pic1.gif + * http://site1.com/docs/pic1.gif pic1.gif + * http://site2.com/docs/pic1.gif http://site2.com/docs/pic1.gif + * + * base = "docs/book1.html" + * URI input URI returned + * docs/pic1.gif pic1.gif + * docs/img/pic1.gif img/pic1.gif + * img/pic1.gif ../img/pic1.gif + * http://site1.com/docs/pic1.gif http://site1.com/docs/pic1.gif + * + * + * Note: if the URI reference is really wierd or complicated, it may be + * worthwhile to first convert it into a "nice" one by calling + * xmlBuildURI (using 'base') before calling this routine, + * since this routine (for reasonable efficiency) assumes URI has + * already been through some validation. + * + * Returns a new URI string (to be freed by the caller) or NULL in case + * error. + */ +xmlChar * +xmlBuildRelativeURI (const xmlChar * URI, const xmlChar * base) +{ + xmlChar *val = NULL; + int ret; + int ix; + int pos = 0; + int nbslash = 0; + int len; + xmlURIPtr ref = NULL; + xmlURIPtr bas = NULL; + xmlChar *bptr, *uptr, *vptr; + int remove_path = 0; + + if ((URI == NULL) || (*URI == 0)) + return NULL; + + /* + * First parse URI into a standard form + */ + ref = xmlCreateURI (); + if (ref == NULL) + return NULL; + /* If URI not already in "relative" form */ + if (URI[0] != '.') { + ret = xmlParseURIReference (ref, (const char *) URI); + if (ret != 0) + goto done; /* Error in URI, return NULL */ + } else + ref->path = (char *)xmlStrdup(URI); + + /* + * Next parse base into the same standard form + */ + if ((base == NULL) || (*base == 0)) { + val = xmlStrdup (URI); + goto done; + } + bas = xmlCreateURI (); + if (bas == NULL) + goto done; + if (base[0] != '.') { + ret = xmlParseURIReference (bas, (const char *) base); + if (ret != 0) + goto done; /* Error in base, return NULL */ + } else + bas->path = (char *)xmlStrdup(base); + + /* + * If the scheme / server on the URI differs from the base, + * just return the URI + */ + if ((ref->scheme != NULL) && + ((bas->scheme == NULL) || + (xmlStrcmp ((xmlChar *)bas->scheme, (xmlChar *)ref->scheme)) || + (xmlStrcmp ((xmlChar *)bas->server, (xmlChar *)ref->server)))) { + val = xmlStrdup (URI); + goto done; + } + if (xmlStrEqual((xmlChar *)bas->path, (xmlChar *)ref->path)) { + val = xmlStrdup(BAD_CAST ""); + goto done; + } + if (bas->path == NULL) { + val = xmlStrdup((xmlChar *)ref->path); + goto done; + } + if (ref->path == NULL) { + ref->path = (char *) "/"; + remove_path = 1; + } + + /* + * At this point (at last!) we can compare the two paths + * + * First we take care of the special case where either of the + * two path components may be missing (bug 316224) + */ + if (bas->path == NULL) { + if (ref->path != NULL) { + uptr = (xmlChar *) ref->path; + if (*uptr == '/') + uptr++; + val = xmlStrdup(uptr); + } + goto done; + } + bptr = (xmlChar *)bas->path; + if (ref->path == NULL) { + for (ix = 0; bptr[ix] != 0; ix++) { + if (bptr[ix] == '/') + nbslash++; + } + uptr = NULL; + len = 1; /* this is for a string terminator only */ + } else { + /* + * Next we compare the two strings and find where they first differ + */ + if ((ref->path[pos] == '.') && (ref->path[pos+1] == '/')) + pos += 2; + if ((*bptr == '.') && (bptr[1] == '/')) + bptr += 2; + else if ((*bptr == '/') && (ref->path[pos] != '/')) + bptr++; + while ((bptr[pos] == ref->path[pos]) && (bptr[pos] != 0)) + pos++; + + if (bptr[pos] == ref->path[pos]) { + val = xmlStrdup(BAD_CAST ""); + goto done; /* (I can't imagine why anyone would do this) */ + } + + /* + * In URI, "back up" to the last '/' encountered. This will be the + * beginning of the "unique" suffix of URI + */ + ix = pos; + if ((ref->path[ix] == '/') && (ix > 0)) + ix--; + else if ((ref->path[ix] == 0) && (ix > 1) && (ref->path[ix - 1] == '/')) + ix -= 2; + for (; ix > 0; ix--) { + if (ref->path[ix] == '/') + break; + } + if (ix == 0) { + uptr = (xmlChar *)ref->path; + } else { + ix++; + uptr = (xmlChar *)&ref->path[ix]; + } + + /* + * In base, count the number of '/' from the differing point + */ + if (bptr[pos] != ref->path[pos]) {/* check for trivial URI == base */ + for (; bptr[ix] != 0; ix++) { + if (bptr[ix] == '/') + nbslash++; + } + } + len = xmlStrlen (uptr) + 1; + } + + if (nbslash == 0) { + if (uptr != NULL) + val = xmlStrdup (uptr); + goto done; + } + + /* + * Allocate just enough space for the returned string - + * length of the remainder of the URI, plus enough space + * for the "../" groups, plus one for the terminator + */ + val = (xmlChar *) xmlMalloc (len + 3 * nbslash); + if (val == NULL) { + xmlGenericError(xmlGenericErrorContext, + "xmlBuildRelativeURI: out of memory\n"); + goto done; + } + vptr = val; + /* + * Put in as many "../" as needed + */ + for (; nbslash>0; nbslash--) { + *vptr++ = '.'; + *vptr++ = '.'; + *vptr++ = '/'; + } + /* + * Finish up with the end of the URI + */ + if (uptr != NULL) { + if ((vptr > val) && (len > 0) && + (uptr[0] == '/') && (vptr[-1] == '/')) { + memcpy (vptr, uptr + 1, len - 1); + vptr[len - 2] = 0; + } else { + memcpy (vptr, uptr, len); + vptr[len - 1] = 0; + } + } else { + vptr[len - 1] = 0; + } + +done: + /* + * Free the working variables + */ + if (remove_path != 0) + ref->path = NULL; + if (ref != NULL) + xmlFreeURI (ref); + if (bas != NULL) + xmlFreeURI (bas); + + return val; +} + +/** + * xmlCanonicPath: + * @path: the resource locator in a filesystem notation + * + * Constructs a canonic path from the specified path. + * + * Returns a new canonic path, or a duplicate of the path parameter if the + * construction fails. The caller is responsible for freeing the memory occupied + * by the returned string. If there is insufficient memory available, or the + * argument is NULL, the function returns NULL. + */ +#define IS_WINDOWS_PATH(p) \ + ((p != NULL) && \ + (((p[0] >= 'a') && (p[0] <= 'z')) || \ + ((p[0] >= 'A') && (p[0] <= 'Z'))) && \ + (p[1] == ':') && ((p[2] == '/') || (p[2] == '\\'))) +xmlChar * +xmlCanonicPath(const xmlChar *path) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + int len = 0; + int i = 0; + xmlChar *p = NULL; +#endif + xmlURIPtr uri; + xmlChar *ret; + const xmlChar *absuri; + + if (path == NULL) + return(NULL); + if ((uri = xmlParseURI((const char *) path)) != NULL) { + xmlFreeURI(uri); + return xmlStrdup(path); + } + + absuri = xmlStrstr(path, BAD_CAST "://"); + if (absuri != NULL) { + int l, j; + unsigned char c; + xmlChar *escURI; + + /* + * this looks like an URI where some parts have not been + * escaped leading to a parsing problem check that the first + * part matches a protocol. + */ + l = absuri - path; + if ((l <= 0) || (l > 20)) + goto path_processing; + for (j = 0;j < l;j++) { + c = path[j]; + if (!(((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')))) + goto path_processing; + } + + escURI = xmlURIEscapeStr(path, BAD_CAST ":/?_.#&;="); + if (escURI != NULL) { + uri = xmlParseURI((const char *) escURI); + if (uri != NULL) { + xmlFreeURI(uri); + return escURI; + } + xmlFreeURI(uri); + } + } + +path_processing: +#if defined(_WIN32) && !defined(__CYGWIN__) + /* + * This really need to be cleaned up by someone with a Windows box + */ + uri = xmlCreateURI(); + if (uri == NULL) { + return(NULL); + } + + len = xmlStrlen(path); + if ((len > 2) && IS_WINDOWS_PATH(path)) { + uri->scheme = xmlStrdup(BAD_CAST "file"); + uri->path = xmlMallocAtomic(len + 2); + if (uri->path == NULL) { + xmlFreeURI(uri); + return(NULL); + } + uri->path[0] = '/'; + p = uri->path + 1; + strncpy(p, path, len + 1); + } else { + uri->path = xmlStrdup(path); + if (uri->path == NULL) { + xmlFreeURI(uri); + return(NULL); + } + p = uri->path; + } + while (*p != '\0') { + if (*p == '\\') + *p = '/'; + p++; + } + if (uri->path == NULL) { + xmlFreeURI(uri); + return(NULL); + } + + if (uri->scheme == NULL) { + ret = xmlStrdup((const xmlChar *) path); + } else { + ret = xmlSaveUri(uri); + } + + xmlFreeURI(uri); +#else + ret = xmlStrdup((const xmlChar *) path); +#endif + return(ret); +} + +/** + * xmlPathToURI: + * @path: the resource locator in a filesystem notation + * + * Constructs an URI expressing the existing path + * + * Returns a new URI, or a duplicate of the path parameter if the + * construction fails. The caller is responsible for freeing the memory + * occupied by the returned string. If there is insufficient memory available, + * or the argument is NULL, the function returns NULL. + */ +xmlChar * +xmlPathToURI(const xmlChar *path) +{ + xmlURIPtr uri; + xmlURI temp; + xmlChar *ret, *cal; + + if (path == NULL) + return(NULL); + + if ((uri = xmlParseURI((const char *) path)) != NULL) { + xmlFreeURI(uri); + return xmlStrdup(path); + } + cal = xmlCanonicPath(path); + if (cal == NULL) + return(NULL); + memset(&temp, 0, sizeof(temp)); + temp.path = (char *) cal; + ret = xmlSaveUri(&temp); + xmlFree(cal); + return(ret); +} +#define bottom_uri +#include "elfgcchack.h" diff --git a/gettext-tools/gnulib-lib/libxml/uri.in.h b/gettext-tools/gnulib-lib/libxml/uri.in.h new file mode 100644 index 0000000..5e29671 --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/uri.in.h @@ -0,0 +1,89 @@ +/** + * Summary: library of generic URI related routines + * Description: library of generic URI related routines + * Implements RFC 2396 + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + +#ifndef __XML_URI_H__ +#define __XML_URI_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * xmlURI: + * + * A parsed URI reference. This is a struct containing the various fields + * as described in RFC 2396 but separated for further processing. + */ +typedef struct _xmlURI xmlURI; +typedef xmlURI *xmlURIPtr; +struct _xmlURI { + char *scheme; /* the URI scheme */ + char *opaque; /* opaque part */ + char *authority; /* the authority part */ + char *server; /* the server part */ + char *user; /* the user part */ + int port; /* the port number */ + char *path; /* the path string */ + char *query; /* the query string */ + char *fragment; /* the fragment identifier */ + int cleanup; /* parsing potentially unclean URI */ +}; + +/* + * This function is in tree.h: + * xmlChar * xmlNodeGetBase (xmlDocPtr doc, + * xmlNodePtr cur); + */ +XMLPUBFUN xmlURIPtr XMLCALL + xmlCreateURI (void); +XMLPUBFUN xmlChar * XMLCALL + xmlBuildURI (const xmlChar *URI, + const xmlChar *base); +XMLPUBFUN xmlChar * XMLCALL + xmlBuildRelativeURI (const xmlChar *URI, + const xmlChar *base); +XMLPUBFUN xmlURIPtr XMLCALL + xmlParseURI (const char *str); +XMLPUBFUN xmlURIPtr XMLCALL + xmlParseURIRaw (const char *str, + int raw); +XMLPUBFUN int XMLCALL + xmlParseURIReference (xmlURIPtr uri, + const char *str); +XMLPUBFUN xmlChar * XMLCALL + xmlSaveUri (xmlURIPtr uri); +XMLPUBFUN void XMLCALL + xmlPrintURI (FILE *stream, + xmlURIPtr uri); +XMLPUBFUN xmlChar * XMLCALL + xmlURIEscapeStr (const xmlChar *str, + const xmlChar *list); +XMLPUBFUN char * XMLCALL + xmlURIUnescapeString (const char *str, + int len, + char *target); +XMLPUBFUN int XMLCALL + xmlNormalizeURIPath (char *path); +XMLPUBFUN xmlChar * XMLCALL + xmlURIEscape (const xmlChar *str); +XMLPUBFUN void XMLCALL + xmlFreeURI (xmlURIPtr uri); +XMLPUBFUN xmlChar* XMLCALL + xmlCanonicPath (const xmlChar *path); +XMLPUBFUN xmlChar* XMLCALL + xmlPathToURI (const xmlChar *path); + +#ifdef __cplusplus +} +#endif +#endif /* __XML_URI_H__ */ diff --git a/gettext-tools/gnulib-lib/libxml/valid.c b/gettext-tools/gnulib-lib/libxml/valid.c new file mode 100644 index 0000000..a239e68 --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/valid.c @@ -0,0 +1,6955 @@ +/* + * valid.c : part of the code use to do the DTD handling and the validity + * checking + * + * See Copyright for the status of this software. + * + * daniel@veillard.com + */ + +#define IN_LIBXML +#include "libxml.h" + +#include + +#ifdef HAVE_STDLIB_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static xmlElementPtr xmlGetDtdElementDesc2(xmlDtdPtr dtd, const xmlChar *name, + int create); +/* #define DEBUG_VALID_ALGO */ +/* #define DEBUG_REGEXP_ALGO */ + +#define TODO \ + xmlGenericError(xmlGenericErrorContext, \ + "Unimplemented block at %s:%d\n", \ + __FILE__, __LINE__); + +/************************************************************************ + * * + * Error handling routines * + * * + ************************************************************************/ + +/** + * xmlVErrMemory: + * @ctxt: an XML validation parser context + * @extra: extra informations + * + * Handle an out of memory error + */ +static void +xmlVErrMemory(xmlValidCtxtPtr ctxt, const char *extra) +{ + xmlGenericErrorFunc channel = NULL; + xmlParserCtxtPtr pctxt = NULL; + void *data = NULL; + + if (ctxt != NULL) { + channel = ctxt->error; + data = ctxt->userData; + /* Use the special values to detect if it is part of a parsing + context */ + if ((ctxt->finishDtd == XML_CTXT_FINISH_DTD_0) || + (ctxt->finishDtd == XML_CTXT_FINISH_DTD_1)) { + long delta = (char *) ctxt - (char *) ctxt->userData; + if ((delta > 0) && (delta < 250)) + pctxt = ctxt->userData; + } + } + if (extra) + __xmlRaiseError(NULL, channel, data, + pctxt, NULL, XML_FROM_VALID, XML_ERR_NO_MEMORY, + XML_ERR_FATAL, NULL, 0, extra, NULL, NULL, 0, 0, + "Memory allocation failed : %s\n", extra); + else + __xmlRaiseError(NULL, channel, data, + pctxt, NULL, XML_FROM_VALID, XML_ERR_NO_MEMORY, + XML_ERR_FATAL, NULL, 0, NULL, NULL, NULL, 0, 0, + "Memory allocation failed\n"); +} + +/** + * xmlErrValid: + * @ctxt: an XML validation parser context + * @error: the error number + * @extra: extra informations + * + * Handle a validation error + */ +static void +xmlErrValid(xmlValidCtxtPtr ctxt, xmlParserErrors error, + const char *msg, const char *extra) +{ + xmlGenericErrorFunc channel = NULL; + xmlParserCtxtPtr pctxt = NULL; + void *data = NULL; + + if (ctxt != NULL) { + channel = ctxt->error; + data = ctxt->userData; + /* Use the special values to detect if it is part of a parsing + context */ + if ((ctxt->finishDtd == XML_CTXT_FINISH_DTD_0) || + (ctxt->finishDtd == XML_CTXT_FINISH_DTD_1)) { + long delta = (char *) ctxt - (char *) ctxt->userData; + if ((delta > 0) && (delta < 250)) + pctxt = ctxt->userData; + } + } + if (extra) + __xmlRaiseError(NULL, channel, data, + pctxt, NULL, XML_FROM_VALID, error, + XML_ERR_ERROR, NULL, 0, extra, NULL, NULL, 0, 0, + msg, extra); + else + __xmlRaiseError(NULL, channel, data, + pctxt, NULL, XML_FROM_VALID, error, + XML_ERR_ERROR, NULL, 0, NULL, NULL, NULL, 0, 0, + msg); +} + +#if defined(LIBXML_VALID_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) +/** + * xmlErrValidNode: + * @ctxt: an XML validation parser context + * @node: the node raising the error + * @error: the error number + * @str1: extra informations + * @str2: extra informations + * @str3: extra informations + * + * Handle a validation error, provide contextual informations + */ +static void +xmlErrValidNode(xmlValidCtxtPtr ctxt, + xmlNodePtr node, xmlParserErrors error, + const char *msg, const xmlChar * str1, + const xmlChar * str2, const xmlChar * str3) +{ + xmlStructuredErrorFunc schannel = NULL; + xmlGenericErrorFunc channel = NULL; + xmlParserCtxtPtr pctxt = NULL; + void *data = NULL; + + if (ctxt != NULL) { + channel = ctxt->error; + data = ctxt->userData; + /* Use the special values to detect if it is part of a parsing + context */ + if ((ctxt->finishDtd == XML_CTXT_FINISH_DTD_0) || + (ctxt->finishDtd == XML_CTXT_FINISH_DTD_1)) { + long delta = (char *) ctxt - (char *) ctxt->userData; + if ((delta > 0) && (delta < 250)) + pctxt = ctxt->userData; + } + } + __xmlRaiseError(schannel, channel, data, pctxt, node, XML_FROM_VALID, error, + XML_ERR_ERROR, NULL, 0, + (const char *) str1, + (const char *) str1, + (const char *) str3, 0, 0, msg, str1, str2, str3); +} +#endif /* LIBXML_VALID_ENABLED or LIBXML_SCHEMAS_ENABLED */ + +#ifdef LIBXML_VALID_ENABLED +/** + * xmlErrValidNodeNr: + * @ctxt: an XML validation parser context + * @node: the node raising the error + * @error: the error number + * @str1: extra informations + * @int2: extra informations + * @str3: extra informations + * + * Handle a validation error, provide contextual informations + */ +static void +xmlErrValidNodeNr(xmlValidCtxtPtr ctxt, + xmlNodePtr node, xmlParserErrors error, + const char *msg, const xmlChar * str1, + int int2, const xmlChar * str3) +{ + xmlStructuredErrorFunc schannel = NULL; + xmlGenericErrorFunc channel = NULL; + xmlParserCtxtPtr pctxt = NULL; + void *data = NULL; + + if (ctxt != NULL) { + channel = ctxt->error; + data = ctxt->userData; + /* Use the special values to detect if it is part of a parsing + context */ + if ((ctxt->finishDtd == XML_CTXT_FINISH_DTD_0) || + (ctxt->finishDtd == XML_CTXT_FINISH_DTD_1)) { + long delta = (char *) ctxt - (char *) ctxt->userData; + if ((delta > 0) && (delta < 250)) + pctxt = ctxt->userData; + } + } + __xmlRaiseError(schannel, channel, data, pctxt, node, XML_FROM_VALID, error, + XML_ERR_ERROR, NULL, 0, + (const char *) str1, + (const char *) str3, + NULL, int2, 0, msg, str1, int2, str3); +} + +/** + * xmlErrValidWarning: + * @ctxt: an XML validation parser context + * @node: the node raising the error + * @error: the error number + * @str1: extra information + * @str2: extra information + * @str3: extra information + * + * Handle a validation error, provide contextual information + */ +static void +xmlErrValidWarning(xmlValidCtxtPtr ctxt, + xmlNodePtr node, xmlParserErrors error, + const char *msg, const xmlChar * str1, + const xmlChar * str2, const xmlChar * str3) +{ + xmlStructuredErrorFunc schannel = NULL; + xmlGenericErrorFunc channel = NULL; + xmlParserCtxtPtr pctxt = NULL; + void *data = NULL; + + if (ctxt != NULL) { + channel = ctxt->warning; + data = ctxt->userData; + /* Use the special values to detect if it is part of a parsing + context */ + if ((ctxt->finishDtd == XML_CTXT_FINISH_DTD_0) || + (ctxt->finishDtd == XML_CTXT_FINISH_DTD_1)) { + long delta = (char *) ctxt - (char *) ctxt->userData; + if ((delta > 0) && (delta < 250)) + pctxt = ctxt->userData; + } + } + __xmlRaiseError(schannel, channel, data, pctxt, node, XML_FROM_VALID, error, + XML_ERR_WARNING, NULL, 0, + (const char *) str1, + (const char *) str1, + (const char *) str3, 0, 0, msg, str1, str2, str3); +} + + + +#ifdef LIBXML_REGEXP_ENABLED +/* + * If regexp are enabled we can do continuous validation without the + * need of a tree to validate the content model. this is done in each + * callbacks. + * Each xmlValidState represent the validation state associated to the + * set of nodes currently open from the document root to the current element. + */ + + +typedef struct _xmlValidState { + xmlElementPtr elemDecl; /* pointer to the content model */ + xmlNodePtr node; /* pointer to the current node */ + xmlRegExecCtxtPtr exec; /* regexp runtime */ +} _xmlValidState; + + +static int +vstateVPush(xmlValidCtxtPtr ctxt, xmlElementPtr elemDecl, xmlNodePtr node) { + if ((ctxt->vstateMax == 0) || (ctxt->vstateTab == NULL)) { + ctxt->vstateMax = 10; + ctxt->vstateTab = (xmlValidState *) xmlMalloc(ctxt->vstateMax * + sizeof(ctxt->vstateTab[0])); + if (ctxt->vstateTab == NULL) { + xmlVErrMemory(ctxt, "malloc failed"); + return(-1); + } + } + + if (ctxt->vstateNr >= ctxt->vstateMax) { + xmlValidState *tmp; + + tmp = (xmlValidState *) xmlRealloc(ctxt->vstateTab, + 2 * ctxt->vstateMax * sizeof(ctxt->vstateTab[0])); + if (tmp == NULL) { + xmlVErrMemory(ctxt, "realloc failed"); + return(-1); + } + ctxt->vstateMax *= 2; + ctxt->vstateTab = tmp; + } + ctxt->vstate = &ctxt->vstateTab[ctxt->vstateNr]; + ctxt->vstateTab[ctxt->vstateNr].elemDecl = elemDecl; + ctxt->vstateTab[ctxt->vstateNr].node = node; + if ((elemDecl != NULL) && (elemDecl->etype == XML_ELEMENT_TYPE_ELEMENT)) { + if (elemDecl->contModel == NULL) + xmlValidBuildContentModel(ctxt, elemDecl); + if (elemDecl->contModel != NULL) { + ctxt->vstateTab[ctxt->vstateNr].exec = + xmlRegNewExecCtxt(elemDecl->contModel, NULL, NULL); + } else { + ctxt->vstateTab[ctxt->vstateNr].exec = NULL; + xmlErrValidNode(ctxt, (xmlNodePtr) elemDecl, + XML_ERR_INTERNAL_ERROR, + "Failed to build content model regexp for %s\n", + node->name, NULL, NULL); + } + } + return(ctxt->vstateNr++); +} + +static int +vstateVPop(xmlValidCtxtPtr ctxt) { + xmlElementPtr elemDecl; + + if (ctxt->vstateNr < 1) return(-1); + ctxt->vstateNr--; + elemDecl = ctxt->vstateTab[ctxt->vstateNr].elemDecl; + ctxt->vstateTab[ctxt->vstateNr].elemDecl = NULL; + ctxt->vstateTab[ctxt->vstateNr].node = NULL; + if ((elemDecl != NULL) && (elemDecl->etype == XML_ELEMENT_TYPE_ELEMENT)) { + xmlRegFreeExecCtxt(ctxt->vstateTab[ctxt->vstateNr].exec); + } + ctxt->vstateTab[ctxt->vstateNr].exec = NULL; + if (ctxt->vstateNr >= 1) + ctxt->vstate = &ctxt->vstateTab[ctxt->vstateNr - 1]; + else + ctxt->vstate = NULL; + return(ctxt->vstateNr); +} + +#else /* not LIBXML_REGEXP_ENABLED */ +/* + * If regexp are not enabled, it uses a home made algorithm less + * complex and easier to + * debug/maintain than a generic NFA -> DFA state based algo. The + * only restriction is on the deepness of the tree limited by the + * size of the occurs bitfield + * + * this is the content of a saved state for rollbacks + */ + +#define ROLLBACK_OR 0 +#define ROLLBACK_PARENT 1 + +typedef struct _xmlValidState { + xmlElementContentPtr cont; /* pointer to the content model subtree */ + xmlNodePtr node; /* pointer to the current node in the list */ + long occurs;/* bitfield for multiple occurrences */ + unsigned char depth; /* current depth in the overall tree */ + unsigned char state; /* ROLLBACK_XXX */ +} _xmlValidState; + +#define MAX_RECURSE 25000 +#define MAX_DEPTH ((sizeof(_xmlValidState.occurs)) * 8) +#define CONT ctxt->vstate->cont +#define NODE ctxt->vstate->node +#define DEPTH ctxt->vstate->depth +#define OCCURS ctxt->vstate->occurs +#define STATE ctxt->vstate->state + +#define OCCURRENCE (ctxt->vstate->occurs & (1 << DEPTH)) +#define PARENT_OCCURRENCE (ctxt->vstate->occurs & ((1 << DEPTH) - 1)) + +#define SET_OCCURRENCE ctxt->vstate->occurs |= (1 << DEPTH) +#define RESET_OCCURRENCE ctxt->vstate->occurs &= ((1 << DEPTH) - 1) + +static int +vstateVPush(xmlValidCtxtPtr ctxt, xmlElementContentPtr cont, + xmlNodePtr node, unsigned char depth, long occurs, + unsigned char state) { + int i = ctxt->vstateNr - 1; + + if (ctxt->vstateNr > MAX_RECURSE) { + return(-1); + } + if (ctxt->vstateTab == NULL) { + ctxt->vstateMax = 8; + ctxt->vstateTab = (xmlValidState *) xmlMalloc( + ctxt->vstateMax * sizeof(ctxt->vstateTab[0])); + if (ctxt->vstateTab == NULL) { + xmlVErrMemory(ctxt, "malloc failed"); + return(-1); + } + } + if (ctxt->vstateNr >= ctxt->vstateMax) { + xmlValidState *tmp; + + tmp = (xmlValidState *) xmlRealloc(ctxt->vstateTab, + 2 * ctxt->vstateMax * sizeof(ctxt->vstateTab[0])); + if (tmp == NULL) { + xmlVErrMemory(ctxt, "malloc failed"); + return(-1); + } + ctxt->vstateMax *= 2; + ctxt->vstateTab = tmp; + ctxt->vstate = &ctxt->vstateTab[0]; + } + /* + * Don't push on the stack a state already here + */ + if ((i >= 0) && (ctxt->vstateTab[i].cont == cont) && + (ctxt->vstateTab[i].node == node) && + (ctxt->vstateTab[i].depth == depth) && + (ctxt->vstateTab[i].occurs == occurs) && + (ctxt->vstateTab[i].state == state)) + return(ctxt->vstateNr); + ctxt->vstateTab[ctxt->vstateNr].cont = cont; + ctxt->vstateTab[ctxt->vstateNr].node = node; + ctxt->vstateTab[ctxt->vstateNr].depth = depth; + ctxt->vstateTab[ctxt->vstateNr].occurs = occurs; + ctxt->vstateTab[ctxt->vstateNr].state = state; + return(ctxt->vstateNr++); +} + +static int +vstateVPop(xmlValidCtxtPtr ctxt) { + if (ctxt->vstateNr <= 1) return(-1); + ctxt->vstateNr--; + ctxt->vstate = &ctxt->vstateTab[0]; + ctxt->vstate->cont = ctxt->vstateTab[ctxt->vstateNr].cont; + ctxt->vstate->node = ctxt->vstateTab[ctxt->vstateNr].node; + ctxt->vstate->depth = ctxt->vstateTab[ctxt->vstateNr].depth; + ctxt->vstate->occurs = ctxt->vstateTab[ctxt->vstateNr].occurs; + ctxt->vstate->state = ctxt->vstateTab[ctxt->vstateNr].state; + return(ctxt->vstateNr); +} + +#endif /* LIBXML_REGEXP_ENABLED */ + +static int +nodeVPush(xmlValidCtxtPtr ctxt, xmlNodePtr value) +{ + if (ctxt->nodeMax <= 0) { + ctxt->nodeMax = 4; + ctxt->nodeTab = + (xmlNodePtr *) xmlMalloc(ctxt->nodeMax * + sizeof(ctxt->nodeTab[0])); + if (ctxt->nodeTab == NULL) { + xmlVErrMemory(ctxt, "malloc failed"); + ctxt->nodeMax = 0; + return (0); + } + } + if (ctxt->nodeNr >= ctxt->nodeMax) { + xmlNodePtr *tmp; + tmp = (xmlNodePtr *) xmlRealloc(ctxt->nodeTab, + ctxt->nodeMax * 2 * sizeof(ctxt->nodeTab[0])); + if (tmp == NULL) { + xmlVErrMemory(ctxt, "realloc failed"); + return (0); + } + ctxt->nodeMax *= 2; + ctxt->nodeTab = tmp; + } + ctxt->nodeTab[ctxt->nodeNr] = value; + ctxt->node = value; + return (ctxt->nodeNr++); +} +static xmlNodePtr +nodeVPop(xmlValidCtxtPtr ctxt) +{ + xmlNodePtr ret; + + if (ctxt->nodeNr <= 0) + return (NULL); + ctxt->nodeNr--; + if (ctxt->nodeNr > 0) + ctxt->node = ctxt->nodeTab[ctxt->nodeNr - 1]; + else + ctxt->node = NULL; + ret = ctxt->nodeTab[ctxt->nodeNr]; + ctxt->nodeTab[ctxt->nodeNr] = NULL; + return (ret); +} + +#ifdef DEBUG_VALID_ALGO +static void +xmlValidPrintNode(xmlNodePtr cur) { + if (cur == NULL) { + xmlGenericError(xmlGenericErrorContext, "null"); + return; + } + switch (cur->type) { + case XML_ELEMENT_NODE: + xmlGenericError(xmlGenericErrorContext, "%s ", cur->name); + break; + case XML_TEXT_NODE: + xmlGenericError(xmlGenericErrorContext, "text "); + break; + case XML_CDATA_SECTION_NODE: + xmlGenericError(xmlGenericErrorContext, "cdata "); + break; + case XML_ENTITY_REF_NODE: + xmlGenericError(xmlGenericErrorContext, "&%s; ", cur->name); + break; + case XML_PI_NODE: + xmlGenericError(xmlGenericErrorContext, "pi(%s) ", cur->name); + break; + case XML_COMMENT_NODE: + xmlGenericError(xmlGenericErrorContext, "comment "); + break; + case XML_ATTRIBUTE_NODE: + xmlGenericError(xmlGenericErrorContext, "?attr? "); + break; + case XML_ENTITY_NODE: + xmlGenericError(xmlGenericErrorContext, "?ent? "); + break; + case XML_DOCUMENT_NODE: + xmlGenericError(xmlGenericErrorContext, "?doc? "); + break; + case XML_DOCUMENT_TYPE_NODE: + xmlGenericError(xmlGenericErrorContext, "?doctype? "); + break; + case XML_DOCUMENT_FRAG_NODE: + xmlGenericError(xmlGenericErrorContext, "?frag? "); + break; + case XML_NOTATION_NODE: + xmlGenericError(xmlGenericErrorContext, "?nota? "); + break; + case XML_HTML_DOCUMENT_NODE: + xmlGenericError(xmlGenericErrorContext, "?html? "); + break; +#ifdef LIBXML_DOCB_ENABLED + case XML_DOCB_DOCUMENT_NODE: + xmlGenericError(xmlGenericErrorContext, "?docb? "); + break; +#endif + case XML_DTD_NODE: + xmlGenericError(xmlGenericErrorContext, "?dtd? "); + break; + case XML_ELEMENT_DECL: + xmlGenericError(xmlGenericErrorContext, "?edecl? "); + break; + case XML_ATTRIBUTE_DECL: + xmlGenericError(xmlGenericErrorContext, "?adecl? "); + break; + case XML_ENTITY_DECL: + xmlGenericError(xmlGenericErrorContext, "?entdecl? "); + break; + case XML_NAMESPACE_DECL: + xmlGenericError(xmlGenericErrorContext, "?nsdecl? "); + break; + case XML_XINCLUDE_START: + xmlGenericError(xmlGenericErrorContext, "incstart "); + break; + case XML_XINCLUDE_END: + xmlGenericError(xmlGenericErrorContext, "incend "); + break; + } +} + +static void +xmlValidPrintNodeList(xmlNodePtr cur) { + if (cur == NULL) + xmlGenericError(xmlGenericErrorContext, "null "); + while (cur != NULL) { + xmlValidPrintNode(cur); + cur = cur->next; + } +} + +static void +xmlValidDebug(xmlNodePtr cur, xmlElementContentPtr cont) { + char expr[5000]; + + expr[0] = 0; + xmlGenericError(xmlGenericErrorContext, "valid: "); + xmlValidPrintNodeList(cur); + xmlGenericError(xmlGenericErrorContext, "against "); + xmlSnprintfElementContent(expr, 5000, cont, 1); + xmlGenericError(xmlGenericErrorContext, "%s\n", expr); +} + +static void +xmlValidDebugState(xmlValidStatePtr state) { + xmlGenericError(xmlGenericErrorContext, "("); + if (state->cont == NULL) + xmlGenericError(xmlGenericErrorContext, "null,"); + else + switch (state->cont->type) { + case XML_ELEMENT_CONTENT_PCDATA: + xmlGenericError(xmlGenericErrorContext, "pcdata,"); + break; + case XML_ELEMENT_CONTENT_ELEMENT: + xmlGenericError(xmlGenericErrorContext, "%s,", + state->cont->name); + break; + case XML_ELEMENT_CONTENT_SEQ: + xmlGenericError(xmlGenericErrorContext, "seq,"); + break; + case XML_ELEMENT_CONTENT_OR: + xmlGenericError(xmlGenericErrorContext, "or,"); + break; + } + xmlValidPrintNode(state->node); + xmlGenericError(xmlGenericErrorContext, ",%d,%X,%d)", + state->depth, state->occurs, state->state); +} + +static void +xmlValidStateDebug(xmlValidCtxtPtr ctxt) { + int i, j; + + xmlGenericError(xmlGenericErrorContext, "state: "); + xmlValidDebugState(ctxt->vstate); + xmlGenericError(xmlGenericErrorContext, " stack: %d ", + ctxt->vstateNr - 1); + for (i = 0, j = ctxt->vstateNr - 1;(i < 3) && (j > 0);i++,j--) + xmlValidDebugState(&ctxt->vstateTab[j]); + xmlGenericError(xmlGenericErrorContext, "\n"); +} + +/***** +#define DEBUG_VALID_STATE(n,c) xmlValidDebug(n,c); + *****/ + +#define DEBUG_VALID_STATE(n,c) xmlValidStateDebug(ctxt); +#define DEBUG_VALID_MSG(m) \ + xmlGenericError(xmlGenericErrorContext, "%s\n", m); + +#else +#define DEBUG_VALID_STATE(n,c) +#define DEBUG_VALID_MSG(m) +#endif + +/* TODO: use hash table for accesses to elem and attribute definitions */ + + +#define CHECK_DTD \ + if (doc == NULL) return(0); \ + else if ((doc->intSubset == NULL) && \ + (doc->extSubset == NULL)) return(0) + +xmlAttributePtr xmlScanAttributeDecl(xmlDtdPtr dtd, const xmlChar *elem); + +#ifdef LIBXML_REGEXP_ENABLED + +/************************************************************************ + * * + * Content model validation based on the regexps * + * * + ************************************************************************/ + +/** + * xmlValidBuildAContentModel: + * @content: the content model + * @ctxt: the schema parser context + * @name: the element name whose content is being built + * + * Generate the automata sequence needed for that type + * + * Returns 1 if successful or 0 in case of error. + */ +static int +xmlValidBuildAContentModel(xmlElementContentPtr content, + xmlValidCtxtPtr ctxt, + const xmlChar *name) { + if (content == NULL) { + xmlErrValidNode(ctxt, NULL, XML_ERR_INTERNAL_ERROR, + "Found NULL content in content model of %s\n", + name, NULL, NULL); + return(0); + } + switch (content->type) { + case XML_ELEMENT_CONTENT_PCDATA: + xmlErrValidNode(ctxt, NULL, XML_ERR_INTERNAL_ERROR, + "Found PCDATA in content model of %s\n", + name, NULL, NULL); + return(0); + break; + case XML_ELEMENT_CONTENT_ELEMENT: { + xmlAutomataStatePtr oldstate = ctxt->state; + xmlChar fn[50]; + xmlChar *fullname; + + fullname = xmlBuildQName(content->name, content->prefix, fn, 50); + if (fullname == NULL) { + xmlVErrMemory(ctxt, "Building content model"); + return(0); + } + + switch (content->ocur) { + case XML_ELEMENT_CONTENT_ONCE: + ctxt->state = xmlAutomataNewTransition(ctxt->am, + ctxt->state, NULL, fullname, NULL); + break; + case XML_ELEMENT_CONTENT_OPT: + ctxt->state = xmlAutomataNewTransition(ctxt->am, + ctxt->state, NULL, fullname, NULL); + xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state); + break; + case XML_ELEMENT_CONTENT_PLUS: + ctxt->state = xmlAutomataNewTransition(ctxt->am, + ctxt->state, NULL, fullname, NULL); + xmlAutomataNewTransition(ctxt->am, ctxt->state, + ctxt->state, fullname, NULL); + break; + case XML_ELEMENT_CONTENT_MULT: + ctxt->state = xmlAutomataNewEpsilon(ctxt->am, + ctxt->state, NULL); + xmlAutomataNewTransition(ctxt->am, + ctxt->state, ctxt->state, fullname, NULL); + break; + } + if ((fullname != fn) && (fullname != content->name)) + xmlFree(fullname); + break; + } + case XML_ELEMENT_CONTENT_SEQ: { + xmlAutomataStatePtr oldstate, oldend; + xmlElementContentOccur ocur; + + /* + * Simply iterate over the content + */ + oldstate = ctxt->state; + ocur = content->ocur; + if (ocur != XML_ELEMENT_CONTENT_ONCE) { + ctxt->state = xmlAutomataNewEpsilon(ctxt->am, oldstate, NULL); + oldstate = ctxt->state; + } + do { + xmlValidBuildAContentModel(content->c1, ctxt, name); + content = content->c2; + } while ((content->type == XML_ELEMENT_CONTENT_SEQ) && + (content->ocur == XML_ELEMENT_CONTENT_ONCE)); + xmlValidBuildAContentModel(content, ctxt, name); + oldend = ctxt->state; + ctxt->state = xmlAutomataNewEpsilon(ctxt->am, oldend, NULL); + switch (ocur) { + case XML_ELEMENT_CONTENT_ONCE: + break; + case XML_ELEMENT_CONTENT_OPT: + xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state); + break; + case XML_ELEMENT_CONTENT_MULT: + xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state); + xmlAutomataNewEpsilon(ctxt->am, oldend, oldstate); + break; + case XML_ELEMENT_CONTENT_PLUS: + xmlAutomataNewEpsilon(ctxt->am, oldend, oldstate); + break; + } + break; + } + case XML_ELEMENT_CONTENT_OR: { + xmlAutomataStatePtr oldstate, oldend; + xmlElementContentOccur ocur; + + ocur = content->ocur; + if ((ocur == XML_ELEMENT_CONTENT_PLUS) || + (ocur == XML_ELEMENT_CONTENT_MULT)) { + ctxt->state = xmlAutomataNewEpsilon(ctxt->am, + ctxt->state, NULL); + } + oldstate = ctxt->state; + oldend = xmlAutomataNewState(ctxt->am); + + /* + * iterate over the subtypes and remerge the end with an + * epsilon transition + */ + do { + ctxt->state = oldstate; + xmlValidBuildAContentModel(content->c1, ctxt, name); + xmlAutomataNewEpsilon(ctxt->am, ctxt->state, oldend); + content = content->c2; + } while ((content->type == XML_ELEMENT_CONTENT_OR) && + (content->ocur == XML_ELEMENT_CONTENT_ONCE)); + ctxt->state = oldstate; + xmlValidBuildAContentModel(content, ctxt, name); + xmlAutomataNewEpsilon(ctxt->am, ctxt->state, oldend); + ctxt->state = xmlAutomataNewEpsilon(ctxt->am, oldend, NULL); + switch (ocur) { + case XML_ELEMENT_CONTENT_ONCE: + break; + case XML_ELEMENT_CONTENT_OPT: + xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state); + break; + case XML_ELEMENT_CONTENT_MULT: + xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state); + xmlAutomataNewEpsilon(ctxt->am, oldend, oldstate); + break; + case XML_ELEMENT_CONTENT_PLUS: + xmlAutomataNewEpsilon(ctxt->am, oldend, oldstate); + break; + } + break; + } + default: + xmlErrValid(ctxt, XML_ERR_INTERNAL_ERROR, + "ContentModel broken for element %s\n", + (const char *) name); + return(0); + } + return(1); +} +/** + * xmlValidBuildContentModel: + * @ctxt: a validation context + * @elem: an element declaration node + * + * (Re)Build the automata associated to the content model of this + * element + * + * Returns 1 in case of success, 0 in case of error + */ +int +xmlValidBuildContentModel(xmlValidCtxtPtr ctxt, xmlElementPtr elem) { + + if ((ctxt == NULL) || (elem == NULL)) + return(0); + if (elem->type != XML_ELEMENT_DECL) + return(0); + if (elem->etype != XML_ELEMENT_TYPE_ELEMENT) + return(1); + /* TODO: should we rebuild in this case ? */ + if (elem->contModel != NULL) { + if (!xmlRegexpIsDeterminist(elem->contModel)) { + ctxt->valid = 0; + return(0); + } + return(1); + } + + ctxt->am = xmlNewAutomata(); + if (ctxt->am == NULL) { + xmlErrValidNode(ctxt, (xmlNodePtr) elem, + XML_ERR_INTERNAL_ERROR, + "Cannot create automata for element %s\n", + elem->name, NULL, NULL); + return(0); + } + ctxt->state = xmlAutomataGetInitState(ctxt->am); + xmlValidBuildAContentModel(elem->content, ctxt, elem->name); + xmlAutomataSetFinalState(ctxt->am, ctxt->state); + elem->contModel = xmlAutomataCompile(ctxt->am); + if (xmlRegexpIsDeterminist(elem->contModel) != 1) { + char expr[5000]; + expr[0] = 0; + xmlSnprintfElementContent(expr, 5000, elem->content, 1); + xmlErrValidNode(ctxt, (xmlNodePtr) elem, + XML_DTD_CONTENT_NOT_DETERMINIST, + "Content model of %s is not determinist: %s\n", + elem->name, BAD_CAST expr, NULL); +#ifdef DEBUG_REGEXP_ALGO + xmlRegexpPrint(stderr, elem->contModel); +#endif + ctxt->valid = 0; + ctxt->state = NULL; + xmlFreeAutomata(ctxt->am); + ctxt->am = NULL; + return(0); + } + ctxt->state = NULL; + xmlFreeAutomata(ctxt->am); + ctxt->am = NULL; + return(1); +} + +#endif /* LIBXML_REGEXP_ENABLED */ + +/**************************************************************** + * * + * Util functions for data allocation/deallocation * + * * + ****************************************************************/ + +/** + * xmlNewValidCtxt: + * + * Allocate a validation context structure. + * + * Returns NULL if not, otherwise the new validation context structure + */ +xmlValidCtxtPtr xmlNewValidCtxt(void) { + xmlValidCtxtPtr ret; + + if ((ret = xmlMalloc(sizeof (xmlValidCtxt))) == NULL) { + xmlVErrMemory(NULL, "malloc failed"); + return (NULL); + } + + (void) memset(ret, 0, sizeof (xmlValidCtxt)); + + return (ret); +} + +/** + * xmlFreeValidCtxt: + * @cur: the validation context to free + * + * Free a validation context structure. + */ +void +xmlFreeValidCtxt(xmlValidCtxtPtr cur) { + if (cur->vstateTab != NULL) + xmlFree(cur->vstateTab); + if (cur->nodeTab != NULL) + xmlFree(cur->nodeTab); + xmlFree(cur); +} + +#endif /* LIBXML_VALID_ENABLED */ + +/** + * xmlNewDocElementContent: + * @doc: the document + * @name: the subelement name or NULL + * @type: the type of element content decl + * + * Allocate an element content structure for the document. + * + * Returns NULL if not, otherwise the new element content structure + */ +xmlElementContentPtr +xmlNewDocElementContent(xmlDocPtr doc, const xmlChar *name, + xmlElementContentType type) { + xmlElementContentPtr ret; + xmlDictPtr dict = NULL; + + if (doc != NULL) + dict = doc->dict; + + switch(type) { + case XML_ELEMENT_CONTENT_ELEMENT: + if (name == NULL) { + xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR, + "xmlNewElementContent : name == NULL !\n", + NULL); + } + break; + case XML_ELEMENT_CONTENT_PCDATA: + case XML_ELEMENT_CONTENT_SEQ: + case XML_ELEMENT_CONTENT_OR: + if (name != NULL) { + xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR, + "xmlNewElementContent : name != NULL !\n", + NULL); + } + break; + default: + xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR, + "Internal: ELEMENT content corrupted invalid type\n", + NULL); + return(NULL); + } + ret = (xmlElementContentPtr) xmlMalloc(sizeof(xmlElementContent)); + if (ret == NULL) { + xmlVErrMemory(NULL, "malloc failed"); + return(NULL); + } + memset(ret, 0, sizeof(xmlElementContent)); + ret->type = type; + ret->ocur = XML_ELEMENT_CONTENT_ONCE; + if (name != NULL) { + int l; + const xmlChar *tmp; + + tmp = xmlSplitQName3(name, &l); + if (tmp == NULL) { + if (dict == NULL) + ret->name = xmlStrdup(name); + else + ret->name = xmlDictLookup(dict, name, -1); + } else { + if (dict == NULL) { + ret->prefix = xmlStrndup(name, l); + ret->name = xmlStrdup(tmp); + } else { + ret->prefix = xmlDictLookup(dict, name, l); + ret->name = xmlDictLookup(dict, tmp, -1); + } + } + } + return(ret); +} + +/** + * xmlNewElementContent: + * @name: the subelement name or NULL + * @type: the type of element content decl + * + * Allocate an element content structure. + * Deprecated in favor of xmlNewDocElementContent + * + * Returns NULL if not, otherwise the new element content structure + */ +xmlElementContentPtr +xmlNewElementContent(const xmlChar *name, xmlElementContentType type) { + return(xmlNewDocElementContent(NULL, name, type)); +} + +/** + * xmlCopyDocElementContent: + * @doc: the document owning the element declaration + * @cur: An element content pointer. + * + * Build a copy of an element content description. + * + * Returns the new xmlElementContentPtr or NULL in case of error. + */ +xmlElementContentPtr +xmlCopyDocElementContent(xmlDocPtr doc, xmlElementContentPtr cur) { + xmlElementContentPtr ret = NULL, prev = NULL, tmp; + xmlDictPtr dict = NULL; + + if (cur == NULL) return(NULL); + + if (doc != NULL) + dict = doc->dict; + + ret = (xmlElementContentPtr) xmlMalloc(sizeof(xmlElementContent)); + if (ret == NULL) { + xmlVErrMemory(NULL, "malloc failed"); + return(NULL); + } + memset(ret, 0, sizeof(xmlElementContent)); + ret->type = cur->type; + ret->ocur = cur->ocur; + if (cur->name != NULL) { + if (dict) + ret->name = xmlDictLookup(dict, cur->name, -1); + else + ret->name = xmlStrdup(cur->name); + } + + if (cur->prefix != NULL) { + if (dict) + ret->prefix = xmlDictLookup(dict, cur->prefix, -1); + else + ret->prefix = xmlStrdup(cur->prefix); + } + if (cur->c1 != NULL) + ret->c1 = xmlCopyDocElementContent(doc, cur->c1); + if (ret->c1 != NULL) + ret->c1->parent = ret; + if (cur->c2 != NULL) { + prev = ret; + cur = cur->c2; + while (cur != NULL) { + tmp = (xmlElementContentPtr) xmlMalloc(sizeof(xmlElementContent)); + if (tmp == NULL) { + xmlVErrMemory(NULL, "malloc failed"); + return(ret); + } + memset(tmp, 0, sizeof(xmlElementContent)); + tmp->type = cur->type; + tmp->ocur = cur->ocur; + prev->c2 = tmp; + if (cur->name != NULL) { + if (dict) + tmp->name = xmlDictLookup(dict, cur->name, -1); + else + tmp->name = xmlStrdup(cur->name); + } + + if (cur->prefix != NULL) { + if (dict) + tmp->prefix = xmlDictLookup(dict, cur->prefix, -1); + else + tmp->prefix = xmlStrdup(cur->prefix); + } + if (cur->c1 != NULL) + tmp->c1 = xmlCopyDocElementContent(doc,cur->c1); + if (tmp->c1 != NULL) + tmp->c1->parent = ret; + prev = tmp; + cur = cur->c2; + } + } + return(ret); +} + +/** + * xmlCopyElementContent: + * @cur: An element content pointer. + * + * Build a copy of an element content description. + * Deprecated, use xmlCopyDocElementContent instead + * + * Returns the new xmlElementContentPtr or NULL in case of error. + */ +xmlElementContentPtr +xmlCopyElementContent(xmlElementContentPtr cur) { + return(xmlCopyDocElementContent(NULL, cur)); +} + +/** + * xmlFreeDocElementContent: + * @doc: the document owning the element declaration + * @cur: the element content tree to free + * + * Free an element content structure. The whole subtree is removed. + */ +void +xmlFreeDocElementContent(xmlDocPtr doc, xmlElementContentPtr cur) { + xmlElementContentPtr next; + xmlDictPtr dict = NULL; + + if (doc != NULL) + dict = doc->dict; + + while (cur != NULL) { + next = cur->c2; + switch (cur->type) { + case XML_ELEMENT_CONTENT_PCDATA: + case XML_ELEMENT_CONTENT_ELEMENT: + case XML_ELEMENT_CONTENT_SEQ: + case XML_ELEMENT_CONTENT_OR: + break; + default: + xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR, + "Internal: ELEMENT content corrupted invalid type\n", + NULL); + return; + } + if (cur->c1 != NULL) xmlFreeDocElementContent(doc, cur->c1); + if (dict) { + if ((cur->name != NULL) && (!xmlDictOwns(dict, cur->name))) + xmlFree((xmlChar *) cur->name); + if ((cur->prefix != NULL) && (!xmlDictOwns(dict, cur->prefix))) + xmlFree((xmlChar *) cur->prefix); + } else { + if (cur->name != NULL) xmlFree((xmlChar *) cur->name); + if (cur->prefix != NULL) xmlFree((xmlChar *) cur->prefix); + } + xmlFree(cur); + cur = next; + } +} + +/** + * xmlFreeElementContent: + * @cur: the element content tree to free + * + * Free an element content structure. The whole subtree is removed. + * Deprecated, use xmlFreeDocElementContent instead + */ +void +xmlFreeElementContent(xmlElementContentPtr cur) { + xmlFreeDocElementContent(NULL, cur); +} + +#ifdef LIBXML_OUTPUT_ENABLED +/** + * xmlDumpElementContent: + * @buf: An XML buffer + * @content: An element table + * @glob: 1 if one must print the englobing parenthesis, 0 otherwise + * + * This will dump the content of the element table as an XML DTD definition + */ +static void +xmlDumpElementContent(xmlBufferPtr buf, xmlElementContentPtr content, int glob) { + if (content == NULL) return; + + if (glob) xmlBufferWriteChar(buf, "("); + switch (content->type) { + case XML_ELEMENT_CONTENT_PCDATA: + xmlBufferWriteChar(buf, "#PCDATA"); + break; + case XML_ELEMENT_CONTENT_ELEMENT: + if (content->prefix != NULL) { + xmlBufferWriteCHAR(buf, content->prefix); + xmlBufferWriteChar(buf, ":"); + } + xmlBufferWriteCHAR(buf, content->name); + break; + case XML_ELEMENT_CONTENT_SEQ: + if ((content->c1->type == XML_ELEMENT_CONTENT_OR) || + (content->c1->type == XML_ELEMENT_CONTENT_SEQ)) + xmlDumpElementContent(buf, content->c1, 1); + else + xmlDumpElementContent(buf, content->c1, 0); + xmlBufferWriteChar(buf, " , "); + if ((content->c2->type == XML_ELEMENT_CONTENT_OR) || + ((content->c2->type == XML_ELEMENT_CONTENT_SEQ) && + (content->c2->ocur != XML_ELEMENT_CONTENT_ONCE))) + xmlDumpElementContent(buf, content->c2, 1); + else + xmlDumpElementContent(buf, content->c2, 0); + break; + case XML_ELEMENT_CONTENT_OR: + if ((content->c1->type == XML_ELEMENT_CONTENT_OR) || + (content->c1->type == XML_ELEMENT_CONTENT_SEQ)) + xmlDumpElementContent(buf, content->c1, 1); + else + xmlDumpElementContent(buf, content->c1, 0); + xmlBufferWriteChar(buf, " | "); + if ((content->c2->type == XML_ELEMENT_CONTENT_SEQ) || + ((content->c2->type == XML_ELEMENT_CONTENT_OR) && + (content->c2->ocur != XML_ELEMENT_CONTENT_ONCE))) + xmlDumpElementContent(buf, content->c2, 1); + else + xmlDumpElementContent(buf, content->c2, 0); + break; + default: + xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR, + "Internal: ELEMENT content corrupted invalid type\n", + NULL); + } + if (glob) + xmlBufferWriteChar(buf, ")"); + switch (content->ocur) { + case XML_ELEMENT_CONTENT_ONCE: + break; + case XML_ELEMENT_CONTENT_OPT: + xmlBufferWriteChar(buf, "?"); + break; + case XML_ELEMENT_CONTENT_MULT: + xmlBufferWriteChar(buf, "*"); + break; + case XML_ELEMENT_CONTENT_PLUS: + xmlBufferWriteChar(buf, "+"); + break; + } +} + +/** + * xmlSprintfElementContent: + * @buf: an output buffer + * @content: An element table + * @englob: 1 if one must print the englobing parenthesis, 0 otherwise + * + * Deprecated, unsafe, use xmlSnprintfElementContent + */ +void +xmlSprintfElementContent(char *buf ATTRIBUTE_UNUSED, + xmlElementContentPtr content ATTRIBUTE_UNUSED, + int englob ATTRIBUTE_UNUSED) { +} +#endif /* LIBXML_OUTPUT_ENABLED */ + +/** + * xmlSnprintfElementContent: + * @buf: an output buffer + * @size: the buffer size + * @content: An element table + * @englob: 1 if one must print the englobing parenthesis, 0 otherwise + * + * This will dump the content of the element content definition + * Intended just for the debug routine + */ +void +xmlSnprintfElementContent(char *buf, int size, xmlElementContentPtr content, int englob) { + int len; + + if (content == NULL) return; + len = strlen(buf); + if (size - len < 50) { + if ((size - len > 4) && (buf[len - 1] != '.')) + strcat(buf, " ..."); + return; + } + if (englob) strcat(buf, "("); + switch (content->type) { + case XML_ELEMENT_CONTENT_PCDATA: + strcat(buf, "#PCDATA"); + break; + case XML_ELEMENT_CONTENT_ELEMENT: + if (content->prefix != NULL) { + if (size - len < xmlStrlen(content->prefix) + 10) { + strcat(buf, " ..."); + return; + } + strcat(buf, (char *) content->prefix); + strcat(buf, ":"); + } + if (size - len < xmlStrlen(content->name) + 10) { + strcat(buf, " ..."); + return; + } + if (content->name != NULL) + strcat(buf, (char *) content->name); + break; + case XML_ELEMENT_CONTENT_SEQ: + if ((content->c1->type == XML_ELEMENT_CONTENT_OR) || + (content->c1->type == XML_ELEMENT_CONTENT_SEQ)) + xmlSnprintfElementContent(buf, size, content->c1, 1); + else + xmlSnprintfElementContent(buf, size, content->c1, 0); + len = strlen(buf); + if (size - len < 50) { + if ((size - len > 4) && (buf[len - 1] != '.')) + strcat(buf, " ..."); + return; + } + strcat(buf, " , "); + if (((content->c2->type == XML_ELEMENT_CONTENT_OR) || + (content->c2->ocur != XML_ELEMENT_CONTENT_ONCE)) && + (content->c2->type != XML_ELEMENT_CONTENT_ELEMENT)) + xmlSnprintfElementContent(buf, size, content->c2, 1); + else + xmlSnprintfElementContent(buf, size, content->c2, 0); + break; + case XML_ELEMENT_CONTENT_OR: + if ((content->c1->type == XML_ELEMENT_CONTENT_OR) || + (content->c1->type == XML_ELEMENT_CONTENT_SEQ)) + xmlSnprintfElementContent(buf, size, content->c1, 1); + else + xmlSnprintfElementContent(buf, size, content->c1, 0); + len = strlen(buf); + if (size - len < 50) { + if ((size - len > 4) && (buf[len - 1] != '.')) + strcat(buf, " ..."); + return; + } + strcat(buf, " | "); + if (((content->c2->type == XML_ELEMENT_CONTENT_SEQ) || + (content->c2->ocur != XML_ELEMENT_CONTENT_ONCE)) && + (content->c2->type != XML_ELEMENT_CONTENT_ELEMENT)) + xmlSnprintfElementContent(buf, size, content->c2, 1); + else + xmlSnprintfElementContent(buf, size, content->c2, 0); + break; + } + if (englob) + strcat(buf, ")"); + switch (content->ocur) { + case XML_ELEMENT_CONTENT_ONCE: + break; + case XML_ELEMENT_CONTENT_OPT: + strcat(buf, "?"); + break; + case XML_ELEMENT_CONTENT_MULT: + strcat(buf, "*"); + break; + case XML_ELEMENT_CONTENT_PLUS: + strcat(buf, "+"); + break; + } +} + +/**************************************************************** + * * + * Registration of DTD declarations * + * * + ****************************************************************/ + +/** + * xmlFreeElement: + * @elem: An element + * + * Deallocate the memory used by an element definition + */ +static void +xmlFreeElement(xmlElementPtr elem) { + if (elem == NULL) return; + xmlUnlinkNode((xmlNodePtr) elem); + xmlFreeDocElementContent(elem->doc, elem->content); + if (elem->name != NULL) + xmlFree((xmlChar *) elem->name); + if (elem->prefix != NULL) + xmlFree((xmlChar *) elem->prefix); +#ifdef LIBXML_REGEXP_ENABLED + if (elem->contModel != NULL) + xmlRegFreeRegexp(elem->contModel); +#endif + xmlFree(elem); +} + + +/** + * xmlAddElementDecl: + * @ctxt: the validation context + * @dtd: pointer to the DTD + * @name: the entity name + * @type: the element type + * @content: the element content tree or NULL + * + * Register a new element declaration + * + * Returns NULL if not, otherwise the entity + */ +xmlElementPtr +xmlAddElementDecl(xmlValidCtxtPtr ctxt, + xmlDtdPtr dtd, const xmlChar *name, + xmlElementTypeVal type, + xmlElementContentPtr content) { + xmlElementPtr ret; + xmlElementTablePtr table; + xmlAttributePtr oldAttributes = NULL; + xmlChar *ns, *uqname; + + if (dtd == NULL) { + return(NULL); + } + if (name == NULL) { + return(NULL); + } + + switch (type) { + case XML_ELEMENT_TYPE_EMPTY: + if (content != NULL) { + xmlErrValid(ctxt, XML_ERR_INTERNAL_ERROR, + "xmlAddElementDecl: content != NULL for EMPTY\n", + NULL); + return(NULL); + } + break; + case XML_ELEMENT_TYPE_ANY: + if (content != NULL) { + xmlErrValid(ctxt, XML_ERR_INTERNAL_ERROR, + "xmlAddElementDecl: content != NULL for ANY\n", + NULL); + return(NULL); + } + break; + case XML_ELEMENT_TYPE_MIXED: + if (content == NULL) { + xmlErrValid(ctxt, XML_ERR_INTERNAL_ERROR, + "xmlAddElementDecl: content == NULL for MIXED\n", + NULL); + return(NULL); + } + break; + case XML_ELEMENT_TYPE_ELEMENT: + if (content == NULL) { + xmlErrValid(ctxt, XML_ERR_INTERNAL_ERROR, + "xmlAddElementDecl: content == NULL for ELEMENT\n", + NULL); + return(NULL); + } + break; + default: + xmlErrValid(ctxt, XML_ERR_INTERNAL_ERROR, + "Internal: ELEMENT decl corrupted invalid type\n", + NULL); + return(NULL); + } + + /* + * check if name is a QName + */ + uqname = xmlSplitQName2(name, &ns); + if (uqname != NULL) + name = uqname; + + /* + * Create the Element table if needed. + */ + table = (xmlElementTablePtr) dtd->elements; + if (table == NULL) { + xmlDictPtr dict = NULL; + + if (dtd->doc != NULL) + dict = dtd->doc->dict; + table = xmlHashCreateDict(0, dict); + dtd->elements = (void *) table; + } + if (table == NULL) { + xmlVErrMemory(ctxt, + "xmlAddElementDecl: Table creation failed!\n"); + if (uqname != NULL) + xmlFree(uqname); + if (ns != NULL) + xmlFree(ns); + return(NULL); + } + + /* + * lookup old attributes inserted on an undefined element in the + * internal subset. + */ + if ((dtd->doc != NULL) && (dtd->doc->intSubset != NULL)) { + ret = xmlHashLookup2(dtd->doc->intSubset->elements, name, ns); + if ((ret != NULL) && (ret->etype == XML_ELEMENT_TYPE_UNDEFINED)) { + oldAttributes = ret->attributes; + ret->attributes = NULL; + xmlHashRemoveEntry2(dtd->doc->intSubset->elements, name, ns, NULL); + xmlFreeElement(ret); + } + } + + /* + * The element may already be present if one of its attribute + * was registered first + */ + ret = xmlHashLookup2(table, name, ns); + if (ret != NULL) { + if (ret->etype != XML_ELEMENT_TYPE_UNDEFINED) { +#ifdef LIBXML_VALID_ENABLED + /* + * The element is already defined in this DTD. + */ + xmlErrValidNode(ctxt, (xmlNodePtr) dtd, XML_DTD_ELEM_REDEFINED, + "Redefinition of element %s\n", + name, NULL, NULL); +#endif /* LIBXML_VALID_ENABLED */ + if (uqname != NULL) + xmlFree(uqname); + if (ns != NULL) + xmlFree(ns); + return(NULL); + } + if (ns != NULL) { + xmlFree(ns); + ns = NULL; + } + } else { + ret = (xmlElementPtr) xmlMalloc(sizeof(xmlElement)); + if (ret == NULL) { + xmlVErrMemory(ctxt, "malloc failed"); + if (uqname != NULL) + xmlFree(uqname); + if (ns != NULL) + xmlFree(ns); + return(NULL); + } + memset(ret, 0, sizeof(xmlElement)); + ret->type = XML_ELEMENT_DECL; + + /* + * fill the structure. + */ + ret->name = xmlStrdup(name); + if (ret->name == NULL) { + xmlVErrMemory(ctxt, "malloc failed"); + if (uqname != NULL) + xmlFree(uqname); + if (ns != NULL) + xmlFree(ns); + xmlFree(ret); + return(NULL); + } + ret->prefix = ns; + + /* + * Validity Check: + * Insertion must not fail + */ + if (xmlHashAddEntry2(table, name, ns, ret)) { +#ifdef LIBXML_VALID_ENABLED + /* + * The element is already defined in this DTD. + */ + xmlErrValidNode(ctxt, (xmlNodePtr) dtd, XML_DTD_ELEM_REDEFINED, + "Redefinition of element %s\n", + name, NULL, NULL); +#endif /* LIBXML_VALID_ENABLED */ + xmlFreeElement(ret); + if (uqname != NULL) + xmlFree(uqname); + return(NULL); + } + /* + * For new element, may have attributes from earlier + * definition in internal subset + */ + ret->attributes = oldAttributes; + } + + /* + * Finish to fill the structure. + */ + ret->etype = type; + /* + * Avoid a stupid copy when called by the parser + * and flag it by setting a special parent value + * so the parser doesn't unallocate it. + */ + if ((ctxt != NULL) && + ((ctxt->finishDtd == XML_CTXT_FINISH_DTD_0) || + (ctxt->finishDtd == XML_CTXT_FINISH_DTD_1))) { + ret->content = content; + if (content != NULL) + content->parent = (xmlElementContentPtr) 1; + } else { + ret->content = xmlCopyDocElementContent(dtd->doc, content); + } + + /* + * Link it to the DTD + */ + ret->parent = dtd; + ret->doc = dtd->doc; + if (dtd->last == NULL) { + dtd->children = dtd->last = (xmlNodePtr) ret; + } else { + dtd->last->next = (xmlNodePtr) ret; + ret->prev = dtd->last; + dtd->last = (xmlNodePtr) ret; + } + if (uqname != NULL) + xmlFree(uqname); + return(ret); +} + +/** + * xmlFreeElementTable: + * @table: An element table + * + * Deallocate the memory used by an element hash table. + */ +void +xmlFreeElementTable(xmlElementTablePtr table) { + xmlHashFree(table, (xmlHashDeallocator) xmlFreeElement); +} + +#ifdef LIBXML_TREE_ENABLED +/** + * xmlCopyElement: + * @elem: An element + * + * Build a copy of an element. + * + * Returns the new xmlElementPtr or NULL in case of error. + */ +static xmlElementPtr +xmlCopyElement(xmlElementPtr elem) { + xmlElementPtr cur; + + cur = (xmlElementPtr) xmlMalloc(sizeof(xmlElement)); + if (cur == NULL) { + xmlVErrMemory(NULL, "malloc failed"); + return(NULL); + } + memset(cur, 0, sizeof(xmlElement)); + cur->type = XML_ELEMENT_DECL; + cur->etype = elem->etype; + if (elem->name != NULL) + cur->name = xmlStrdup(elem->name); + else + cur->name = NULL; + if (elem->prefix != NULL) + cur->prefix = xmlStrdup(elem->prefix); + else + cur->prefix = NULL; + cur->content = xmlCopyElementContent(elem->content); + /* TODO : rebuild the attribute list on the copy */ + cur->attributes = NULL; + return(cur); +} + +/** + * xmlCopyElementTable: + * @table: An element table + * + * Build a copy of an element table. + * + * Returns the new xmlElementTablePtr or NULL in case of error. + */ +xmlElementTablePtr +xmlCopyElementTable(xmlElementTablePtr table) { + return((xmlElementTablePtr) xmlHashCopy(table, + (xmlHashCopier) xmlCopyElement)); +} +#endif /* LIBXML_TREE_ENABLED */ + +#ifdef LIBXML_OUTPUT_ENABLED +/** + * xmlDumpElementDecl: + * @buf: the XML buffer output + * @elem: An element table + * + * This will dump the content of the element declaration as an XML + * DTD definition + */ +void +xmlDumpElementDecl(xmlBufferPtr buf, xmlElementPtr elem) { + if ((buf == NULL) || (elem == NULL)) + return; + switch (elem->etype) { + case XML_ELEMENT_TYPE_EMPTY: + xmlBufferWriteChar(buf, "prefix != NULL) { + xmlBufferWriteCHAR(buf, elem->prefix); + xmlBufferWriteChar(buf, ":"); + } + xmlBufferWriteCHAR(buf, elem->name); + xmlBufferWriteChar(buf, " EMPTY>\n"); + break; + case XML_ELEMENT_TYPE_ANY: + xmlBufferWriteChar(buf, "prefix != NULL) { + xmlBufferWriteCHAR(buf, elem->prefix); + xmlBufferWriteChar(buf, ":"); + } + xmlBufferWriteCHAR(buf, elem->name); + xmlBufferWriteChar(buf, " ANY>\n"); + break; + case XML_ELEMENT_TYPE_MIXED: + xmlBufferWriteChar(buf, "prefix != NULL) { + xmlBufferWriteCHAR(buf, elem->prefix); + xmlBufferWriteChar(buf, ":"); + } + xmlBufferWriteCHAR(buf, elem->name); + xmlBufferWriteChar(buf, " "); + xmlDumpElementContent(buf, elem->content, 1); + xmlBufferWriteChar(buf, ">\n"); + break; + case XML_ELEMENT_TYPE_ELEMENT: + xmlBufferWriteChar(buf, "prefix != NULL) { + xmlBufferWriteCHAR(buf, elem->prefix); + xmlBufferWriteChar(buf, ":"); + } + xmlBufferWriteCHAR(buf, elem->name); + xmlBufferWriteChar(buf, " "); + xmlDumpElementContent(buf, elem->content, 1); + xmlBufferWriteChar(buf, ">\n"); + break; + default: + xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR, + "Internal: ELEMENT struct corrupted invalid type\n", + NULL); + } +} + +/** + * xmlDumpElementDeclScan: + * @elem: An element table + * @buf: the XML buffer output + * + * This routine is used by the hash scan function. It just reverses + * the arguments. + */ +static void +xmlDumpElementDeclScan(xmlElementPtr elem, xmlBufferPtr buf) { + xmlDumpElementDecl(buf, elem); +} + +/** + * xmlDumpElementTable: + * @buf: the XML buffer output + * @table: An element table + * + * This will dump the content of the element table as an XML DTD definition + */ +void +xmlDumpElementTable(xmlBufferPtr buf, xmlElementTablePtr table) { + if ((buf == NULL) || (table == NULL)) + return; + xmlHashScan(table, (xmlHashScanner) xmlDumpElementDeclScan, buf); +} +#endif /* LIBXML_OUTPUT_ENABLED */ + +/** + * xmlCreateEnumeration: + * @name: the enumeration name or NULL + * + * create and initialize an enumeration attribute node. + * + * Returns the xmlEnumerationPtr just created or NULL in case + * of error. + */ +xmlEnumerationPtr +xmlCreateEnumeration(const xmlChar *name) { + xmlEnumerationPtr ret; + + ret = (xmlEnumerationPtr) xmlMalloc(sizeof(xmlEnumeration)); + if (ret == NULL) { + xmlVErrMemory(NULL, "malloc failed"); + return(NULL); + } + memset(ret, 0, sizeof(xmlEnumeration)); + + if (name != NULL) + ret->name = xmlStrdup(name); + return(ret); +} + +/** + * xmlFreeEnumeration: + * @cur: the tree to free. + * + * free an enumeration attribute node (recursive). + */ +void +xmlFreeEnumeration(xmlEnumerationPtr cur) { + if (cur == NULL) return; + + if (cur->next != NULL) xmlFreeEnumeration(cur->next); + + if (cur->name != NULL) xmlFree((xmlChar *) cur->name); + xmlFree(cur); +} + +#ifdef LIBXML_TREE_ENABLED +/** + * xmlCopyEnumeration: + * @cur: the tree to copy. + * + * Copy an enumeration attribute node (recursive). + * + * Returns the xmlEnumerationPtr just created or NULL in case + * of error. + */ +xmlEnumerationPtr +xmlCopyEnumeration(xmlEnumerationPtr cur) { + xmlEnumerationPtr ret; + + if (cur == NULL) return(NULL); + ret = xmlCreateEnumeration((xmlChar *) cur->name); + + if (cur->next != NULL) ret->next = xmlCopyEnumeration(cur->next); + else ret->next = NULL; + + return(ret); +} +#endif /* LIBXML_TREE_ENABLED */ + +#ifdef LIBXML_OUTPUT_ENABLED +/** + * xmlDumpEnumeration: + * @buf: the XML buffer output + * @enum: An enumeration + * + * This will dump the content of the enumeration + */ +static void +xmlDumpEnumeration(xmlBufferPtr buf, xmlEnumerationPtr cur) { + if ((buf == NULL) || (cur == NULL)) + return; + + xmlBufferWriteCHAR(buf, cur->name); + if (cur->next == NULL) + xmlBufferWriteChar(buf, ")"); + else { + xmlBufferWriteChar(buf, " | "); + xmlDumpEnumeration(buf, cur->next); + } +} +#endif /* LIBXML_OUTPUT_ENABLED */ + +#ifdef LIBXML_VALID_ENABLED +/** + * xmlScanAttributeDeclCallback: + * @attr: the attribute decl + * @list: the list to update + * + * Callback called by xmlScanAttributeDecl when a new attribute + * has to be entered in the list. + */ +static void +xmlScanAttributeDeclCallback(xmlAttributePtr attr, xmlAttributePtr *list, + const xmlChar* name ATTRIBUTE_UNUSED) { + attr->nexth = *list; + *list = attr; +} + +/** + * xmlScanAttributeDecl: + * @dtd: pointer to the DTD + * @elem: the element name + * + * When inserting a new element scan the DtD for existing attributes + * for that element and initialize the Attribute chain + * + * Returns the pointer to the first attribute decl in the chain, + * possibly NULL. + */ +xmlAttributePtr +xmlScanAttributeDecl(xmlDtdPtr dtd, const xmlChar *elem) { + xmlAttributePtr ret = NULL; + xmlAttributeTablePtr table; + + if (dtd == NULL) { + return(NULL); + } + if (elem == NULL) { + return(NULL); + } + table = (xmlAttributeTablePtr) dtd->attributes; + if (table == NULL) + return(NULL); + + /* WRONG !!! */ + xmlHashScan3(table, NULL, NULL, elem, + (xmlHashScanner) xmlScanAttributeDeclCallback, &ret); + return(ret); +} + +/** + * xmlScanIDAttributeDecl: + * @ctxt: the validation context + * @elem: the element name + * @err: whether to raise errors here + * + * Verify that the element don't have too many ID attributes + * declared. + * + * Returns the number of ID attributes found. + */ +static int +xmlScanIDAttributeDecl(xmlValidCtxtPtr ctxt, xmlElementPtr elem, int err) { + xmlAttributePtr cur; + int ret = 0; + + if (elem == NULL) return(0); + cur = elem->attributes; + while (cur != NULL) { + if (cur->atype == XML_ATTRIBUTE_ID) { + ret ++; + if ((ret > 1) && (err)) + xmlErrValidNode(ctxt, (xmlNodePtr) elem, XML_DTD_MULTIPLE_ID, + "Element %s has too many ID attributes defined : %s\n", + elem->name, cur->name, NULL); + } + cur = cur->nexth; + } + return(ret); +} +#endif /* LIBXML_VALID_ENABLED */ + +/** + * xmlFreeAttribute: + * @elem: An attribute + * + * Deallocate the memory used by an attribute definition + */ +static void +xmlFreeAttribute(xmlAttributePtr attr) { + xmlDictPtr dict; + + if (attr == NULL) return; + if (attr->doc != NULL) + dict = attr->doc->dict; + else + dict = NULL; + xmlUnlinkNode((xmlNodePtr) attr); + if (attr->tree != NULL) + xmlFreeEnumeration(attr->tree); + if (dict) { + if ((attr->elem != NULL) && (!xmlDictOwns(dict, attr->elem))) + xmlFree((xmlChar *) attr->elem); + if ((attr->name != NULL) && (!xmlDictOwns(dict, attr->name))) + xmlFree((xmlChar *) attr->name); + if ((attr->prefix != NULL) && (!xmlDictOwns(dict, attr->prefix))) + xmlFree((xmlChar *) attr->prefix); + if ((attr->defaultValue != NULL) && + (!xmlDictOwns(dict, attr->defaultValue))) + xmlFree((xmlChar *) attr->defaultValue); + } else { + if (attr->elem != NULL) + xmlFree((xmlChar *) attr->elem); + if (attr->name != NULL) + xmlFree((xmlChar *) attr->name); + if (attr->defaultValue != NULL) + xmlFree((xmlChar *) attr->defaultValue); + if (attr->prefix != NULL) + xmlFree((xmlChar *) attr->prefix); + } + xmlFree(attr); +} + + +/** + * xmlAddAttributeDecl: + * @ctxt: the validation context + * @dtd: pointer to the DTD + * @elem: the element name + * @name: the attribute name + * @ns: the attribute namespace prefix + * @type: the attribute type + * @def: the attribute default type + * @defaultValue: the attribute default value + * @tree: if it's an enumeration, the associated list + * + * Register a new attribute declaration + * Note that @tree becomes the ownership of the DTD + * + * Returns NULL if not new, otherwise the attribute decl + */ +xmlAttributePtr +xmlAddAttributeDecl(xmlValidCtxtPtr ctxt, + xmlDtdPtr dtd, const xmlChar *elem, + const xmlChar *name, const xmlChar *ns, + xmlAttributeType type, xmlAttributeDefault def, + const xmlChar *defaultValue, xmlEnumerationPtr tree) { + xmlAttributePtr ret; + xmlAttributeTablePtr table; + xmlElementPtr elemDef; + xmlDictPtr dict = NULL; + + if (dtd == NULL) { + xmlFreeEnumeration(tree); + return(NULL); + } + if (name == NULL) { + xmlFreeEnumeration(tree); + return(NULL); + } + if (elem == NULL) { + xmlFreeEnumeration(tree); + return(NULL); + } + if (dtd->doc != NULL) + dict = dtd->doc->dict; + +#ifdef LIBXML_VALID_ENABLED + /* + * Check the type and possibly the default value. + */ + switch (type) { + case XML_ATTRIBUTE_CDATA: + break; + case XML_ATTRIBUTE_ID: + break; + case XML_ATTRIBUTE_IDREF: + break; + case XML_ATTRIBUTE_IDREFS: + break; + case XML_ATTRIBUTE_ENTITY: + break; + case XML_ATTRIBUTE_ENTITIES: + break; + case XML_ATTRIBUTE_NMTOKEN: + break; + case XML_ATTRIBUTE_NMTOKENS: + break; + case XML_ATTRIBUTE_ENUMERATION: + break; + case XML_ATTRIBUTE_NOTATION: + break; + default: + xmlErrValid(ctxt, XML_ERR_INTERNAL_ERROR, + "Internal: ATTRIBUTE struct corrupted invalid type\n", + NULL); + xmlFreeEnumeration(tree); + return(NULL); + } + if ((defaultValue != NULL) && + (!xmlValidateAttributeValue(type, defaultValue))) { + xmlErrValidNode(ctxt, (xmlNodePtr) dtd, XML_DTD_ATTRIBUTE_DEFAULT, + "Attribute %s of %s: invalid default value\n", + elem, name, defaultValue); + defaultValue = NULL; + if (ctxt != NULL) + ctxt->valid = 0; + } +#endif /* LIBXML_VALID_ENABLED */ + + /* + * Check first that an attribute defined in the external subset wasn't + * already defined in the internal subset + */ + if ((dtd->doc != NULL) && (dtd->doc->extSubset == dtd) && + (dtd->doc->intSubset != NULL) && + (dtd->doc->intSubset->attributes != NULL)) { + ret = xmlHashLookup3(dtd->doc->intSubset->attributes, name, ns, elem); + if (ret != NULL) + return(NULL); + } + + /* + * Create the Attribute table if needed. + */ + table = (xmlAttributeTablePtr) dtd->attributes; + if (table == NULL) { + table = xmlHashCreateDict(0, dict); + dtd->attributes = (void *) table; + } + if (table == NULL) { + xmlVErrMemory(ctxt, + "xmlAddAttributeDecl: Table creation failed!\n"); + return(NULL); + } + + + ret = (xmlAttributePtr) xmlMalloc(sizeof(xmlAttribute)); + if (ret == NULL) { + xmlVErrMemory(ctxt, "malloc failed"); + return(NULL); + } + memset(ret, 0, sizeof(xmlAttribute)); + ret->type = XML_ATTRIBUTE_DECL; + + /* + * fill the structure. + */ + ret->atype = type; + /* + * doc must be set before possible error causes call + * to xmlFreeAttribute (because it's used to check on + * dict use) + */ + ret->doc = dtd->doc; + if (dict) { + ret->name = xmlDictLookup(dict, name, -1); + ret->prefix = xmlDictLookup(dict, ns, -1); + ret->elem = xmlDictLookup(dict, elem, -1); + } else { + ret->name = xmlStrdup(name); + ret->prefix = xmlStrdup(ns); + ret->elem = xmlStrdup(elem); + } + ret->def = def; + ret->tree = tree; + if (defaultValue != NULL) { + if (dict) + ret->defaultValue = xmlDictLookup(dict, defaultValue, -1); + else + ret->defaultValue = xmlStrdup(defaultValue); + } + + /* + * Validity Check: + * Search the DTD for previous declarations of the ATTLIST + */ + if (xmlHashAddEntry3(table, ret->name, ret->prefix, ret->elem, ret) < 0) { +#ifdef LIBXML_VALID_ENABLED + /* + * The attribute is already defined in this DTD. + */ + xmlErrValidWarning(ctxt, (xmlNodePtr) dtd, XML_DTD_ATTRIBUTE_REDEFINED, + "Attribute %s of element %s: already defined\n", + name, elem, NULL); +#endif /* LIBXML_VALID_ENABLED */ + xmlFreeAttribute(ret); + return(NULL); + } + + /* + * Validity Check: + * Multiple ID per element + */ + elemDef = xmlGetDtdElementDesc2(dtd, elem, 1); + if (elemDef != NULL) { + +#ifdef LIBXML_VALID_ENABLED + if ((type == XML_ATTRIBUTE_ID) && + (xmlScanIDAttributeDecl(NULL, elemDef, 1) != 0)) { + xmlErrValidNode(ctxt, (xmlNodePtr) dtd, XML_DTD_MULTIPLE_ID, + "Element %s has too may ID attributes defined : %s\n", + elem, name, NULL); + if (ctxt != NULL) + ctxt->valid = 0; + } +#endif /* LIBXML_VALID_ENABLED */ + + /* + * Insert namespace default def first they need to be + * processed first. + */ + if ((xmlStrEqual(ret->name, BAD_CAST "xmlns")) || + ((ret->prefix != NULL && + (xmlStrEqual(ret->prefix, BAD_CAST "xmlns"))))) { + ret->nexth = elemDef->attributes; + elemDef->attributes = ret; + } else { + xmlAttributePtr tmp = elemDef->attributes; + + while ((tmp != NULL) && + ((xmlStrEqual(tmp->name, BAD_CAST "xmlns")) || + ((ret->prefix != NULL && + (xmlStrEqual(ret->prefix, BAD_CAST "xmlns")))))) { + if (tmp->nexth == NULL) + break; + tmp = tmp->nexth; + } + if (tmp != NULL) { + ret->nexth = tmp->nexth; + tmp->nexth = ret; + } else { + ret->nexth = elemDef->attributes; + elemDef->attributes = ret; + } + } + } + + /* + * Link it to the DTD + */ + ret->parent = dtd; + if (dtd->last == NULL) { + dtd->children = dtd->last = (xmlNodePtr) ret; + } else { + dtd->last->next = (xmlNodePtr) ret; + ret->prev = dtd->last; + dtd->last = (xmlNodePtr) ret; + } + return(ret); +} + +/** + * xmlFreeAttributeTable: + * @table: An attribute table + * + * Deallocate the memory used by an entities hash table. + */ +void +xmlFreeAttributeTable(xmlAttributeTablePtr table) { + xmlHashFree(table, (xmlHashDeallocator) xmlFreeAttribute); +} + +#ifdef LIBXML_TREE_ENABLED +/** + * xmlCopyAttribute: + * @attr: An attribute + * + * Build a copy of an attribute. + * + * Returns the new xmlAttributePtr or NULL in case of error. + */ +static xmlAttributePtr +xmlCopyAttribute(xmlAttributePtr attr) { + xmlAttributePtr cur; + + cur = (xmlAttributePtr) xmlMalloc(sizeof(xmlAttribute)); + if (cur == NULL) { + xmlVErrMemory(NULL, "malloc failed"); + return(NULL); + } + memset(cur, 0, sizeof(xmlAttribute)); + cur->type = XML_ATTRIBUTE_DECL; + cur->atype = attr->atype; + cur->def = attr->def; + cur->tree = xmlCopyEnumeration(attr->tree); + if (attr->elem != NULL) + cur->elem = xmlStrdup(attr->elem); + if (attr->name != NULL) + cur->name = xmlStrdup(attr->name); + if (attr->prefix != NULL) + cur->prefix = xmlStrdup(attr->prefix); + if (attr->defaultValue != NULL) + cur->defaultValue = xmlStrdup(attr->defaultValue); + return(cur); +} + +/** + * xmlCopyAttributeTable: + * @table: An attribute table + * + * Build a copy of an attribute table. + * + * Returns the new xmlAttributeTablePtr or NULL in case of error. + */ +xmlAttributeTablePtr +xmlCopyAttributeTable(xmlAttributeTablePtr table) { + return((xmlAttributeTablePtr) xmlHashCopy(table, + (xmlHashCopier) xmlCopyAttribute)); +} +#endif /* LIBXML_TREE_ENABLED */ + +#ifdef LIBXML_OUTPUT_ENABLED +/** + * xmlDumpAttributeDecl: + * @buf: the XML buffer output + * @attr: An attribute declaration + * + * This will dump the content of the attribute declaration as an XML + * DTD definition + */ +void +xmlDumpAttributeDecl(xmlBufferPtr buf, xmlAttributePtr attr) { + if ((buf == NULL) || (attr == NULL)) + return; + xmlBufferWriteChar(buf, "elem); + xmlBufferWriteChar(buf, " "); + if (attr->prefix != NULL) { + xmlBufferWriteCHAR(buf, attr->prefix); + xmlBufferWriteChar(buf, ":"); + } + xmlBufferWriteCHAR(buf, attr->name); + switch (attr->atype) { + case XML_ATTRIBUTE_CDATA: + xmlBufferWriteChar(buf, " CDATA"); + break; + case XML_ATTRIBUTE_ID: + xmlBufferWriteChar(buf, " ID"); + break; + case XML_ATTRIBUTE_IDREF: + xmlBufferWriteChar(buf, " IDREF"); + break; + case XML_ATTRIBUTE_IDREFS: + xmlBufferWriteChar(buf, " IDREFS"); + break; + case XML_ATTRIBUTE_ENTITY: + xmlBufferWriteChar(buf, " ENTITY"); + break; + case XML_ATTRIBUTE_ENTITIES: + xmlBufferWriteChar(buf, " ENTITIES"); + break; + case XML_ATTRIBUTE_NMTOKEN: + xmlBufferWriteChar(buf, " NMTOKEN"); + break; + case XML_ATTRIBUTE_NMTOKENS: + xmlBufferWriteChar(buf, " NMTOKENS"); + break; + case XML_ATTRIBUTE_ENUMERATION: + xmlBufferWriteChar(buf, " ("); + xmlDumpEnumeration(buf, attr->tree); + break; + case XML_ATTRIBUTE_NOTATION: + xmlBufferWriteChar(buf, " NOTATION ("); + xmlDumpEnumeration(buf, attr->tree); + break; + default: + xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR, + "Internal: ATTRIBUTE struct corrupted invalid type\n", + NULL); + } + switch (attr->def) { + case XML_ATTRIBUTE_NONE: + break; + case XML_ATTRIBUTE_REQUIRED: + xmlBufferWriteChar(buf, " #REQUIRED"); + break; + case XML_ATTRIBUTE_IMPLIED: + xmlBufferWriteChar(buf, " #IMPLIED"); + break; + case XML_ATTRIBUTE_FIXED: + xmlBufferWriteChar(buf, " #FIXED"); + break; + default: + xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR, + "Internal: ATTRIBUTE struct corrupted invalid def\n", + NULL); + } + if (attr->defaultValue != NULL) { + xmlBufferWriteChar(buf, " "); + xmlBufferWriteQuotedString(buf, attr->defaultValue); + } + xmlBufferWriteChar(buf, ">\n"); +} + +/** + * xmlDumpAttributeDeclScan: + * @attr: An attribute declaration + * @buf: the XML buffer output + * + * This is used with the hash scan function - just reverses arguments + */ +static void +xmlDumpAttributeDeclScan(xmlAttributePtr attr, xmlBufferPtr buf) { + xmlDumpAttributeDecl(buf, attr); +} + +/** + * xmlDumpAttributeTable: + * @buf: the XML buffer output + * @table: An attribute table + * + * This will dump the content of the attribute table as an XML DTD definition + */ +void +xmlDumpAttributeTable(xmlBufferPtr buf, xmlAttributeTablePtr table) { + if ((buf == NULL) || (table == NULL)) + return; + xmlHashScan(table, (xmlHashScanner) xmlDumpAttributeDeclScan, buf); +} +#endif /* LIBXML_OUTPUT_ENABLED */ + +/************************************************************************ + * * + * NOTATIONs * + * * + ************************************************************************/ +/** + * xmlFreeNotation: + * @not: A notation + * + * Deallocate the memory used by an notation definition + */ +static void +xmlFreeNotation(xmlNotationPtr nota) { + if (nota == NULL) return; + if (nota->name != NULL) + xmlFree((xmlChar *) nota->name); + if (nota->PublicID != NULL) + xmlFree((xmlChar *) nota->PublicID); + if (nota->SystemID != NULL) + xmlFree((xmlChar *) nota->SystemID); + xmlFree(nota); +} + + +/** + * xmlAddNotationDecl: + * @dtd: pointer to the DTD + * @ctxt: the validation context + * @name: the entity name + * @PublicID: the public identifier or NULL + * @SystemID: the system identifier or NULL + * + * Register a new notation declaration + * + * Returns NULL if not, otherwise the entity + */ +xmlNotationPtr +xmlAddNotationDecl(xmlValidCtxtPtr ctxt, xmlDtdPtr dtd, + const xmlChar *name, + const xmlChar *PublicID, const xmlChar *SystemID) { + xmlNotationPtr ret; + xmlNotationTablePtr table; + + if (dtd == NULL) { + return(NULL); + } + if (name == NULL) { + return(NULL); + } + if ((PublicID == NULL) && (SystemID == NULL)) { + return(NULL); + } + + /* + * Create the Notation table if needed. + */ + table = (xmlNotationTablePtr) dtd->notations; + if (table == NULL) { + xmlDictPtr dict = NULL; + if (dtd->doc != NULL) + dict = dtd->doc->dict; + + dtd->notations = table = xmlHashCreateDict(0, dict); + } + if (table == NULL) { + xmlVErrMemory(ctxt, + "xmlAddNotationDecl: Table creation failed!\n"); + return(NULL); + } + + ret = (xmlNotationPtr) xmlMalloc(sizeof(xmlNotation)); + if (ret == NULL) { + xmlVErrMemory(ctxt, "malloc failed"); + return(NULL); + } + memset(ret, 0, sizeof(xmlNotation)); + + /* + * fill the structure. + */ + ret->name = xmlStrdup(name); + if (SystemID != NULL) + ret->SystemID = xmlStrdup(SystemID); + if (PublicID != NULL) + ret->PublicID = xmlStrdup(PublicID); + + /* + * Validity Check: + * Check the DTD for previous declarations of the ATTLIST + */ + if (xmlHashAddEntry(table, name, ret)) { +#ifdef LIBXML_VALID_ENABLED + xmlErrValid(NULL, XML_DTD_NOTATION_REDEFINED, + "xmlAddNotationDecl: %s already defined\n", + (const char *) name); +#endif /* LIBXML_VALID_ENABLED */ + xmlFreeNotation(ret); + return(NULL); + } + return(ret); +} + +/** + * xmlFreeNotationTable: + * @table: An notation table + * + * Deallocate the memory used by an entities hash table. + */ +void +xmlFreeNotationTable(xmlNotationTablePtr table) { + xmlHashFree(table, (xmlHashDeallocator) xmlFreeNotation); +} + +#ifdef LIBXML_TREE_ENABLED +/** + * xmlCopyNotation: + * @nota: A notation + * + * Build a copy of a notation. + * + * Returns the new xmlNotationPtr or NULL in case of error. + */ +static xmlNotationPtr +xmlCopyNotation(xmlNotationPtr nota) { + xmlNotationPtr cur; + + cur = (xmlNotationPtr) xmlMalloc(sizeof(xmlNotation)); + if (cur == NULL) { + xmlVErrMemory(NULL, "malloc failed"); + return(NULL); + } + if (nota->name != NULL) + cur->name = xmlStrdup(nota->name); + else + cur->name = NULL; + if (nota->PublicID != NULL) + cur->PublicID = xmlStrdup(nota->PublicID); + else + cur->PublicID = NULL; + if (nota->SystemID != NULL) + cur->SystemID = xmlStrdup(nota->SystemID); + else + cur->SystemID = NULL; + return(cur); +} + +/** + * xmlCopyNotationTable: + * @table: A notation table + * + * Build a copy of a notation table. + * + * Returns the new xmlNotationTablePtr or NULL in case of error. + */ +xmlNotationTablePtr +xmlCopyNotationTable(xmlNotationTablePtr table) { + return((xmlNotationTablePtr) xmlHashCopy(table, + (xmlHashCopier) xmlCopyNotation)); +} +#endif /* LIBXML_TREE_ENABLED */ + +#ifdef LIBXML_OUTPUT_ENABLED +/** + * xmlDumpNotationDecl: + * @buf: the XML buffer output + * @nota: A notation declaration + * + * This will dump the content the notation declaration as an XML DTD definition + */ +void +xmlDumpNotationDecl(xmlBufferPtr buf, xmlNotationPtr nota) { + if ((buf == NULL) || (nota == NULL)) + return; + xmlBufferWriteChar(buf, "name); + if (nota->PublicID != NULL) { + xmlBufferWriteChar(buf, " PUBLIC "); + xmlBufferWriteQuotedString(buf, nota->PublicID); + if (nota->SystemID != NULL) { + xmlBufferWriteChar(buf, " "); + xmlBufferWriteQuotedString(buf, nota->SystemID); + } + } else { + xmlBufferWriteChar(buf, " SYSTEM "); + xmlBufferWriteQuotedString(buf, nota->SystemID); + } + xmlBufferWriteChar(buf, " >\n"); +} + +/** + * xmlDumpNotationDeclScan: + * @nota: A notation declaration + * @buf: the XML buffer output + * + * This is called with the hash scan function, and just reverses args + */ +static void +xmlDumpNotationDeclScan(xmlNotationPtr nota, xmlBufferPtr buf) { + xmlDumpNotationDecl(buf, nota); +} + +/** + * xmlDumpNotationTable: + * @buf: the XML buffer output + * @table: A notation table + * + * This will dump the content of the notation table as an XML DTD definition + */ +void +xmlDumpNotationTable(xmlBufferPtr buf, xmlNotationTablePtr table) { + if ((buf == NULL) || (table == NULL)) + return; + xmlHashScan(table, (xmlHashScanner) xmlDumpNotationDeclScan, buf); +} +#endif /* LIBXML_OUTPUT_ENABLED */ + +/************************************************************************ + * * + * IDs * + * * + ************************************************************************/ +/** + * DICT_FREE: + * @str: a string + * + * Free a string if it is not owned by the "dict" dictionnary in the + * current scope + */ +#define DICT_FREE(str) \ + if ((str) && ((!dict) || \ + (xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \ + xmlFree((char *)(str)); + +/** + * xmlFreeID: + * @not: A id + * + * Deallocate the memory used by an id definition + */ +static void +xmlFreeID(xmlIDPtr id) { + xmlDictPtr dict = NULL; + + if (id == NULL) return; + + if (id->doc != NULL) + dict = id->doc->dict; + + if (id->value != NULL) + DICT_FREE(id->value) + if (id->name != NULL) + DICT_FREE(id->name) + xmlFree(id); +} + + +/** + * xmlAddID: + * @ctxt: the validation context + * @doc: pointer to the document + * @value: the value name + * @attr: the attribute holding the ID + * + * Register a new id declaration + * + * Returns NULL if not, otherwise the new xmlIDPtr + */ +xmlIDPtr +xmlAddID(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value, + xmlAttrPtr attr) { + xmlIDPtr ret; + xmlIDTablePtr table; + + if (doc == NULL) { + return(NULL); + } + if (value == NULL) { + return(NULL); + } + if (attr == NULL) { + return(NULL); + } + + /* + * Create the ID table if needed. + */ + table = (xmlIDTablePtr) doc->ids; + if (table == NULL) { + doc->ids = table = xmlHashCreateDict(0, doc->dict); + } + if (table == NULL) { + xmlVErrMemory(ctxt, + "xmlAddID: Table creation failed!\n"); + return(NULL); + } + + ret = (xmlIDPtr) xmlMalloc(sizeof(xmlID)); + if (ret == NULL) { + xmlVErrMemory(ctxt, "malloc failed"); + return(NULL); + } + + /* + * fill the structure. + */ + ret->value = xmlStrdup(value); + ret->doc = doc; + if ((ctxt != NULL) && (ctxt->vstateNr != 0)) { + /* + * Operating in streaming mode, attr is gonna disapear + */ + if (doc->dict != NULL) + ret->name = xmlDictLookup(doc->dict, attr->name, -1); + else + ret->name = xmlStrdup(attr->name); + ret->attr = NULL; + } else { + ret->attr = attr; + ret->name = NULL; + } + ret->lineno = xmlGetLineNo(attr->parent); + + if (xmlHashAddEntry(table, value, ret) < 0) { +#ifdef LIBXML_VALID_ENABLED + /* + * The id is already defined in this DTD. + */ + if ((ctxt != NULL) && (ctxt->error != NULL)) { + xmlErrValidNode(ctxt, attr->parent, XML_DTD_ID_REDEFINED, + "ID %s already defined\n", + value, NULL, NULL); + } +#endif /* LIBXML_VALID_ENABLED */ + xmlFreeID(ret); + return(NULL); + } + if (attr != NULL) + attr->atype = XML_ATTRIBUTE_ID; + return(ret); +} + +/** + * xmlFreeIDTable: + * @table: An id table + * + * Deallocate the memory used by an ID hash table. + */ +void +xmlFreeIDTable(xmlIDTablePtr table) { + xmlHashFree(table, (xmlHashDeallocator) xmlFreeID); +} + +/** + * xmlIsID: + * @doc: the document + * @elem: the element carrying the attribute + * @attr: the attribute + * + * Determine whether an attribute is of type ID. In case we have DTD(s) + * then this is done if DTD loading has been requested. In the case + * of HTML documents parsed with the HTML parser, then ID detection is + * done systematically. + * + * Returns 0 or 1 depending on the lookup result + */ +int +xmlIsID(xmlDocPtr doc, xmlNodePtr elem, xmlAttrPtr attr) { + if ((attr == NULL) || (attr->name == NULL)) return(0); + if ((attr->ns != NULL) && (attr->ns->prefix != NULL) && + (!strcmp((char *) attr->name, "id")) && + (!strcmp((char *) attr->ns->prefix, "xml"))) + return(1); + if (doc == NULL) return(0); + if ((doc->intSubset == NULL) && (doc->extSubset == NULL)) { + return(0); + } else if (doc->type == XML_HTML_DOCUMENT_NODE) { + if ((xmlStrEqual(BAD_CAST "id", attr->name)) || + ((xmlStrEqual(BAD_CAST "name", attr->name)) && + ((elem == NULL) || (!xmlStrEqual(elem->name, BAD_CAST "input"))))) + return(1); + return(0); + } else if (elem == NULL) { + return(0); + } else { + xmlAttributePtr attrDecl = NULL; + + xmlChar felem[50], fattr[50]; + xmlChar *fullelemname, *fullattrname; + + fullelemname = (elem->ns != NULL && elem->ns->prefix != NULL) ? + xmlBuildQName(elem->name, elem->ns->prefix, felem, 50) : + (xmlChar *)elem->name; + + fullattrname = (attr->ns != NULL && attr->ns->prefix != NULL) ? + xmlBuildQName(attr->name, attr->ns->prefix, fattr, 50) : + (xmlChar *)attr->name; + + if (fullelemname != NULL && fullattrname != NULL) { + attrDecl = xmlGetDtdAttrDesc(doc->intSubset, fullelemname, + fullattrname); + if ((attrDecl == NULL) && (doc->extSubset != NULL)) + attrDecl = xmlGetDtdAttrDesc(doc->extSubset, fullelemname, + fullattrname); + } + + if ((fullattrname != fattr) && (fullattrname != attr->name)) + xmlFree(fullattrname); + if ((fullelemname != felem) && (fullelemname != elem->name)) + xmlFree(fullelemname); + + if ((attrDecl != NULL) && (attrDecl->atype == XML_ATTRIBUTE_ID)) + return(1); + } + return(0); +} + +/** + * xmlRemoveID: + * @doc: the document + * @attr: the attribute + * + * Remove the given attribute from the ID table maintained internally. + * + * Returns -1 if the lookup failed and 0 otherwise + */ +int +xmlRemoveID(xmlDocPtr doc, xmlAttrPtr attr) { + xmlIDTablePtr table; + xmlIDPtr id; + xmlChar *ID; + + if (doc == NULL) return(-1); + if (attr == NULL) return(-1); + table = (xmlIDTablePtr) doc->ids; + if (table == NULL) + return(-1); + + if (attr == NULL) + return(-1); + ID = xmlNodeListGetString(doc, attr->children, 1); + if (ID == NULL) + return(-1); + id = xmlHashLookup(table, ID); + if (id == NULL || id->attr != attr) { + xmlFree(ID); + return(-1); + } + xmlHashRemoveEntry(table, ID, (xmlHashDeallocator) xmlFreeID); + xmlFree(ID); + attr->atype = 0; + return(0); +} + +/** + * xmlGetID: + * @doc: pointer to the document + * @ID: the ID value + * + * Search the attribute declaring the given ID + * + * Returns NULL if not found, otherwise the xmlAttrPtr defining the ID + */ +xmlAttrPtr +xmlGetID(xmlDocPtr doc, const xmlChar *ID) { + xmlIDTablePtr table; + xmlIDPtr id; + + if (doc == NULL) { + return(NULL); + } + + if (ID == NULL) { + return(NULL); + } + + table = (xmlIDTablePtr) doc->ids; + if (table == NULL) + return(NULL); + + id = xmlHashLookup(table, ID); + if (id == NULL) + return(NULL); + if (id->attr == NULL) { + /* + * We are operating on a stream, return a well known reference + * since the attribute node doesn't exist anymore + */ + return((xmlAttrPtr) doc); + } + return(id->attr); +} + +/************************************************************************ + * * + * Refs * + * * + ************************************************************************/ +typedef struct xmlRemoveMemo_t +{ + xmlListPtr l; + xmlAttrPtr ap; +} xmlRemoveMemo; + +typedef xmlRemoveMemo *xmlRemoveMemoPtr; + +typedef struct xmlValidateMemo_t +{ + xmlValidCtxtPtr ctxt; + const xmlChar *name; +} xmlValidateMemo; + +typedef xmlValidateMemo *xmlValidateMemoPtr; + +/** + * xmlFreeRef: + * @lk: A list link + * + * Deallocate the memory used by a ref definition + */ +static void +xmlFreeRef(xmlLinkPtr lk) { + xmlRefPtr ref = (xmlRefPtr)xmlLinkGetData(lk); + if (ref == NULL) return; + if (ref->value != NULL) + xmlFree((xmlChar *)ref->value); + if (ref->name != NULL) + xmlFree((xmlChar *)ref->name); + xmlFree(ref); +} + +/** + * xmlFreeRefList: + * @list_ref: A list of references. + * + * Deallocate the memory used by a list of references + */ +static void +xmlFreeRefList(xmlListPtr list_ref) { + if (list_ref == NULL) return; + xmlListDelete(list_ref); +} + +/** + * xmlWalkRemoveRef: + * @data: Contents of current link + * @user: Value supplied by the user + * + * Returns 0 to abort the walk or 1 to continue + */ +static int +xmlWalkRemoveRef(const void *data, const void *user) +{ + xmlAttrPtr attr0 = ((xmlRefPtr)data)->attr; + xmlAttrPtr attr1 = ((xmlRemoveMemoPtr)user)->ap; + xmlListPtr ref_list = ((xmlRemoveMemoPtr)user)->l; + + if (attr0 == attr1) { /* Matched: remove and terminate walk */ + xmlListRemoveFirst(ref_list, (void *)data); + return 0; + } + return 1; +} + +/** + * xmlDummyCompare + * @data0: Value supplied by the user + * @data1: Value supplied by the user + * + * Do nothing, return 0. Used to create unordered lists. + */ +static int +xmlDummyCompare(const void *data0 ATTRIBUTE_UNUSED, + const void *data1 ATTRIBUTE_UNUSED) +{ + return (0); +} + +/** + * xmlAddRef: + * @ctxt: the validation context + * @doc: pointer to the document + * @value: the value name + * @attr: the attribute holding the Ref + * + * Register a new ref declaration + * + * Returns NULL if not, otherwise the new xmlRefPtr + */ +xmlRefPtr +xmlAddRef(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value, + xmlAttrPtr attr) { + xmlRefPtr ret; + xmlRefTablePtr table; + xmlListPtr ref_list; + + if (doc == NULL) { + return(NULL); + } + if (value == NULL) { + return(NULL); + } + if (attr == NULL) { + return(NULL); + } + + /* + * Create the Ref table if needed. + */ + table = (xmlRefTablePtr) doc->refs; + if (table == NULL) { + doc->refs = table = xmlHashCreateDict(0, doc->dict); + } + if (table == NULL) { + xmlVErrMemory(ctxt, + "xmlAddRef: Table creation failed!\n"); + return(NULL); + } + + ret = (xmlRefPtr) xmlMalloc(sizeof(xmlRef)); + if (ret == NULL) { + xmlVErrMemory(ctxt, "malloc failed"); + return(NULL); + } + + /* + * fill the structure. + */ + ret->value = xmlStrdup(value); + if ((ctxt != NULL) && (ctxt->vstateNr != 0)) { + /* + * Operating in streaming mode, attr is gonna disapear + */ + ret->name = xmlStrdup(attr->name); + ret->attr = NULL; + } else { + ret->name = NULL; + ret->attr = attr; + } + ret->lineno = xmlGetLineNo(attr->parent); + + /* To add a reference :- + * References are maintained as a list of references, + * Lookup the entry, if no entry create new nodelist + * Add the owning node to the NodeList + * Return the ref + */ + + if (NULL == (ref_list = xmlHashLookup(table, value))) { + if (NULL == (ref_list = xmlListCreate(xmlFreeRef, xmlDummyCompare))) { + xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR, + "xmlAddRef: Reference list creation failed!\n", + NULL); + return(NULL); + } + if (xmlHashAddEntry(table, value, ref_list) < 0) { + xmlListDelete(ref_list); + xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR, + "xmlAddRef: Reference list insertion failed!\n", + NULL); + return(NULL); + } + } +/* xmlListInsert(ref_list, ret); */ + xmlListAppend(ref_list, ret); + return(ret); +} + +/** + * xmlFreeRefTable: + * @table: An ref table + * + * Deallocate the memory used by an Ref hash table. + */ +void +xmlFreeRefTable(xmlRefTablePtr table) { + xmlHashFree(table, (xmlHashDeallocator) xmlFreeRefList); +} + +/** + * xmlIsRef: + * @doc: the document + * @elem: the element carrying the attribute + * @attr: the attribute + * + * Determine whether an attribute is of type Ref. In case we have DTD(s) + * then this is simple, otherwise we use an heuristic: name Ref (upper + * or lowercase). + * + * Returns 0 or 1 depending on the lookup result + */ +int +xmlIsRef(xmlDocPtr doc, xmlNodePtr elem, xmlAttrPtr attr) { + if (attr == NULL) + return(0); + if (doc == NULL) { + doc = attr->doc; + if (doc == NULL) return(0); + } + + if ((doc->intSubset == NULL) && (doc->extSubset == NULL)) { + return(0); + } else if (doc->type == XML_HTML_DOCUMENT_NODE) { + /* TODO @@@ */ + return(0); + } else { + xmlAttributePtr attrDecl; + + if (elem == NULL) return(0); + attrDecl = xmlGetDtdAttrDesc(doc->intSubset, elem->name, attr->name); + if ((attrDecl == NULL) && (doc->extSubset != NULL)) + attrDecl = xmlGetDtdAttrDesc(doc->extSubset, + elem->name, attr->name); + + if ((attrDecl != NULL) && + (attrDecl->atype == XML_ATTRIBUTE_IDREF || + attrDecl->atype == XML_ATTRIBUTE_IDREFS)) + return(1); + } + return(0); +} + +/** + * xmlRemoveRef: + * @doc: the document + * @attr: the attribute + * + * Remove the given attribute from the Ref table maintained internally. + * + * Returns -1 if the lookup failed and 0 otherwise + */ +int +xmlRemoveRef(xmlDocPtr doc, xmlAttrPtr attr) { + xmlListPtr ref_list; + xmlRefTablePtr table; + xmlChar *ID; + xmlRemoveMemo target; + + if (doc == NULL) return(-1); + if (attr == NULL) return(-1); + table = (xmlRefTablePtr) doc->refs; + if (table == NULL) + return(-1); + + if (attr == NULL) + return(-1); + ID = xmlNodeListGetString(doc, attr->children, 1); + if (ID == NULL) + return(-1); + ref_list = xmlHashLookup(table, ID); + + if(ref_list == NULL) { + xmlFree(ID); + return (-1); + } + /* At this point, ref_list refers to a list of references which + * have the same key as the supplied attr. Our list of references + * is ordered by reference address and we don't have that information + * here to use when removing. We'll have to walk the list and + * check for a matching attribute, when we find one stop the walk + * and remove the entry. + * The list is ordered by reference, so that means we don't have the + * key. Passing the list and the reference to the walker means we + * will have enough data to be able to remove the entry. + */ + target.l = ref_list; + target.ap = attr; + + /* Remove the supplied attr from our list */ + xmlListWalk(ref_list, xmlWalkRemoveRef, &target); + + /*If the list is empty then remove the list entry in the hash */ + if (xmlListEmpty(ref_list)) + xmlHashUpdateEntry(table, ID, NULL, (xmlHashDeallocator) + xmlFreeRefList); + xmlFree(ID); + return(0); +} + +/** + * xmlGetRefs: + * @doc: pointer to the document + * @ID: the ID value + * + * Find the set of references for the supplied ID. + * + * Returns NULL if not found, otherwise node set for the ID. + */ +xmlListPtr +xmlGetRefs(xmlDocPtr doc, const xmlChar *ID) { + xmlRefTablePtr table; + + if (doc == NULL) { + return(NULL); + } + + if (ID == NULL) { + return(NULL); + } + + table = (xmlRefTablePtr) doc->refs; + if (table == NULL) + return(NULL); + + return (xmlHashLookup(table, ID)); +} + +/************************************************************************ + * * + * Routines for validity checking * + * * + ************************************************************************/ + +/** + * xmlGetDtdElementDesc: + * @dtd: a pointer to the DtD to search + * @name: the element name + * + * Search the DTD for the description of this element + * + * returns the xmlElementPtr if found or NULL + */ + +xmlElementPtr +xmlGetDtdElementDesc(xmlDtdPtr dtd, const xmlChar *name) { + xmlElementTablePtr table; + xmlElementPtr cur; + xmlChar *uqname = NULL, *prefix = NULL; + + if ((dtd == NULL) || (name == NULL)) return(NULL); + if (dtd->elements == NULL) + return(NULL); + table = (xmlElementTablePtr) dtd->elements; + + uqname = xmlSplitQName2(name, &prefix); + if (uqname != NULL) + name = uqname; + cur = xmlHashLookup2(table, name, prefix); + if (prefix != NULL) xmlFree(prefix); + if (uqname != NULL) xmlFree(uqname); + return(cur); +} +/** + * xmlGetDtdElementDesc2: + * @dtd: a pointer to the DtD to search + * @name: the element name + * @create: create an empty description if not found + * + * Search the DTD for the description of this element + * + * returns the xmlElementPtr if found or NULL + */ + +static xmlElementPtr +xmlGetDtdElementDesc2(xmlDtdPtr dtd, const xmlChar *name, int create) { + xmlElementTablePtr table; + xmlElementPtr cur; + xmlChar *uqname = NULL, *prefix = NULL; + + if (dtd == NULL) return(NULL); + if (dtd->elements == NULL) { + xmlDictPtr dict = NULL; + + if (dtd->doc != NULL) + dict = dtd->doc->dict; + + if (!create) + return(NULL); + /* + * Create the Element table if needed. + */ + table = (xmlElementTablePtr) dtd->elements; + if (table == NULL) { + table = xmlHashCreateDict(0, dict); + dtd->elements = (void *) table; + } + if (table == NULL) { + xmlVErrMemory(NULL, "element table allocation failed"); + return(NULL); + } + } + table = (xmlElementTablePtr) dtd->elements; + + uqname = xmlSplitQName2(name, &prefix); + if (uqname != NULL) + name = uqname; + cur = xmlHashLookup2(table, name, prefix); + if ((cur == NULL) && (create)) { + cur = (xmlElementPtr) xmlMalloc(sizeof(xmlElement)); + if (cur == NULL) { + xmlVErrMemory(NULL, "malloc failed"); + return(NULL); + } + memset(cur, 0, sizeof(xmlElement)); + cur->type = XML_ELEMENT_DECL; + + /* + * fill the structure. + */ + cur->name = xmlStrdup(name); + cur->prefix = xmlStrdup(prefix); + cur->etype = XML_ELEMENT_TYPE_UNDEFINED; + + xmlHashAddEntry2(table, name, prefix, cur); + } + if (prefix != NULL) xmlFree(prefix); + if (uqname != NULL) xmlFree(uqname); + return(cur); +} + +/** + * xmlGetDtdQElementDesc: + * @dtd: a pointer to the DtD to search + * @name: the element name + * @prefix: the element namespace prefix + * + * Search the DTD for the description of this element + * + * returns the xmlElementPtr if found or NULL + */ + +xmlElementPtr +xmlGetDtdQElementDesc(xmlDtdPtr dtd, const xmlChar *name, + const xmlChar *prefix) { + xmlElementTablePtr table; + + if (dtd == NULL) return(NULL); + if (dtd->elements == NULL) return(NULL); + table = (xmlElementTablePtr) dtd->elements; + + return(xmlHashLookup2(table, name, prefix)); +} + +/** + * xmlGetDtdAttrDesc: + * @dtd: a pointer to the DtD to search + * @elem: the element name + * @name: the attribute name + * + * Search the DTD for the description of this attribute on + * this element. + * + * returns the xmlAttributePtr if found or NULL + */ + +xmlAttributePtr +xmlGetDtdAttrDesc(xmlDtdPtr dtd, const xmlChar *elem, const xmlChar *name) { + xmlAttributeTablePtr table; + xmlAttributePtr cur; + xmlChar *uqname = NULL, *prefix = NULL; + + if (dtd == NULL) return(NULL); + if (dtd->attributes == NULL) return(NULL); + + table = (xmlAttributeTablePtr) dtd->attributes; + if (table == NULL) + return(NULL); + + uqname = xmlSplitQName2(name, &prefix); + + if (uqname != NULL) { + cur = xmlHashLookup3(table, uqname, prefix, elem); + if (prefix != NULL) xmlFree(prefix); + if (uqname != NULL) xmlFree(uqname); + } else + cur = xmlHashLookup3(table, name, NULL, elem); + return(cur); +} + +/** + * xmlGetDtdQAttrDesc: + * @dtd: a pointer to the DtD to search + * @elem: the element name + * @name: the attribute name + * @prefix: the attribute namespace prefix + * + * Search the DTD for the description of this qualified attribute on + * this element. + * + * returns the xmlAttributePtr if found or NULL + */ + +xmlAttributePtr +xmlGetDtdQAttrDesc(xmlDtdPtr dtd, const xmlChar *elem, const xmlChar *name, + const xmlChar *prefix) { + xmlAttributeTablePtr table; + + if (dtd == NULL) return(NULL); + if (dtd->attributes == NULL) return(NULL); + table = (xmlAttributeTablePtr) dtd->attributes; + + return(xmlHashLookup3(table, name, prefix, elem)); +} + +/** + * xmlGetDtdNotationDesc: + * @dtd: a pointer to the DtD to search + * @name: the notation name + * + * Search the DTD for the description of this notation + * + * returns the xmlNotationPtr if found or NULL + */ + +xmlNotationPtr +xmlGetDtdNotationDesc(xmlDtdPtr dtd, const xmlChar *name) { + xmlNotationTablePtr table; + + if (dtd == NULL) return(NULL); + if (dtd->notations == NULL) return(NULL); + table = (xmlNotationTablePtr) dtd->notations; + + return(xmlHashLookup(table, name)); +} + +#if defined(LIBXML_VALID_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) +/** + * xmlValidateNotationUse: + * @ctxt: the validation context + * @doc: the document + * @notationName: the notation name to check + * + * Validate that the given name match a notation declaration. + * - [ VC: Notation Declared ] + * + * returns 1 if valid or 0 otherwise + */ + +int +xmlValidateNotationUse(xmlValidCtxtPtr ctxt, xmlDocPtr doc, + const xmlChar *notationName) { + xmlNotationPtr notaDecl; + if ((doc == NULL) || (doc->intSubset == NULL)) return(-1); + + notaDecl = xmlGetDtdNotationDesc(doc->intSubset, notationName); + if ((notaDecl == NULL) && (doc->extSubset != NULL)) + notaDecl = xmlGetDtdNotationDesc(doc->extSubset, notationName); + + if ((notaDecl == NULL) && (ctxt != NULL)) { + xmlErrValidNode(ctxt, (xmlNodePtr) doc, XML_DTD_UNKNOWN_NOTATION, + "NOTATION %s is not declared\n", + notationName, NULL, NULL); + return(0); + } + return(1); +} +#endif /* LIBXML_VALID_ENABLED or LIBXML_SCHEMAS_ENABLED */ + +/** + * xmlIsMixedElement: + * @doc: the document + * @name: the element name + * + * Search in the DtDs whether an element accept Mixed content (or ANY) + * basically if it is supposed to accept text childs + * + * returns 0 if no, 1 if yes, and -1 if no element description is available + */ + +int +xmlIsMixedElement(xmlDocPtr doc, const xmlChar *name) { + xmlElementPtr elemDecl; + + if ((doc == NULL) || (doc->intSubset == NULL)) return(-1); + + elemDecl = xmlGetDtdElementDesc(doc->intSubset, name); + if ((elemDecl == NULL) && (doc->extSubset != NULL)) + elemDecl = xmlGetDtdElementDesc(doc->extSubset, name); + if (elemDecl == NULL) return(-1); + switch (elemDecl->etype) { + case XML_ELEMENT_TYPE_UNDEFINED: + return(-1); + case XML_ELEMENT_TYPE_ELEMENT: + return(0); + case XML_ELEMENT_TYPE_EMPTY: + /* + * return 1 for EMPTY since we want VC error to pop up + * on for example + */ + case XML_ELEMENT_TYPE_ANY: + case XML_ELEMENT_TYPE_MIXED: + return(1); + } + return(1); +} + +#ifdef LIBXML_VALID_ENABLED +/** + * xmlValidateNameValue: + * @value: an Name value + * + * Validate that the given value match Name production + * + * returns 1 if valid or 0 otherwise + */ + +int +xmlValidateNameValue(const xmlChar *value) { + const xmlChar *cur; + int val, len; + + if (value == NULL) return(0); + cur = value; + val = xmlStringCurrentChar(NULL, cur, &len); + cur += len; + if (!IS_LETTER(val) && (val != '_') && + (val != ':')) { + return(0); + } + + val = xmlStringCurrentChar(NULL, cur, &len); + cur += len; + while ((IS_LETTER(val)) || (IS_DIGIT(val)) || + (val == '.') || (val == '-') || + (val == '_') || (val == ':') || + (IS_COMBINING(val)) || + (IS_EXTENDER(val))) { + val = xmlStringCurrentChar(NULL, cur, &len); + cur += len; + } + + if (val != 0) return(0); + + return(1); +} + +/** + * xmlValidateNamesValue: + * @value: an Names value + * + * Validate that the given value match Names production + * + * returns 1 if valid or 0 otherwise + */ + +int +xmlValidateNamesValue(const xmlChar *value) { + const xmlChar *cur; + int val, len; + + if (value == NULL) return(0); + cur = value; + val = xmlStringCurrentChar(NULL, cur, &len); + cur += len; + + if (!IS_LETTER(val) && (val != '_') && + (val != ':')) { + return(0); + } + + val = xmlStringCurrentChar(NULL, cur, &len); + cur += len; + while ((IS_LETTER(val)) || (IS_DIGIT(val)) || + (val == '.') || (val == '-') || + (val == '_') || (val == ':') || + (IS_COMBINING(val)) || + (IS_EXTENDER(val))) { + val = xmlStringCurrentChar(NULL, cur, &len); + cur += len; + } + + /* Should not test IS_BLANK(val) here -- see erratum E20*/ + while (val == 0x20) { + while (val == 0x20) { + val = xmlStringCurrentChar(NULL, cur, &len); + cur += len; + } + + if (!IS_LETTER(val) && (val != '_') && + (val != ':')) { + return(0); + } + val = xmlStringCurrentChar(NULL, cur, &len); + cur += len; + + while ((IS_LETTER(val)) || (IS_DIGIT(val)) || + (val == '.') || (val == '-') || + (val == '_') || (val == ':') || + (IS_COMBINING(val)) || + (IS_EXTENDER(val))) { + val = xmlStringCurrentChar(NULL, cur, &len); + cur += len; + } + } + + if (val != 0) return(0); + + return(1); +} + +/** + * xmlValidateNmtokenValue: + * @value: an Nmtoken value + * + * Validate that the given value match Nmtoken production + * + * [ VC: Name Token ] + * + * returns 1 if valid or 0 otherwise + */ + +int +xmlValidateNmtokenValue(const xmlChar *value) { + const xmlChar *cur; + int val, len; + + if (value == NULL) return(0); + cur = value; + val = xmlStringCurrentChar(NULL, cur, &len); + cur += len; + + if (!IS_LETTER(val) && !IS_DIGIT(val) && + (val != '.') && (val != '-') && + (val != '_') && (val != ':') && + (!IS_COMBINING(val)) && + (!IS_EXTENDER(val))) + return(0); + + while ((IS_LETTER(val)) || (IS_DIGIT(val)) || + (val == '.') || (val == '-') || + (val == '_') || (val == ':') || + (IS_COMBINING(val)) || + (IS_EXTENDER(val))) { + val = xmlStringCurrentChar(NULL, cur, &len); + cur += len; + } + + if (val != 0) return(0); + + return(1); +} + +/** + * xmlValidateNmtokensValue: + * @value: an Nmtokens value + * + * Validate that the given value match Nmtokens production + * + * [ VC: Name Token ] + * + * returns 1 if valid or 0 otherwise + */ + +int +xmlValidateNmtokensValue(const xmlChar *value) { + const xmlChar *cur; + int val, len; + + if (value == NULL) return(0); + cur = value; + val = xmlStringCurrentChar(NULL, cur, &len); + cur += len; + + while (IS_BLANK(val)) { + val = xmlStringCurrentChar(NULL, cur, &len); + cur += len; + } + + if (!IS_LETTER(val) && !IS_DIGIT(val) && + (val != '.') && (val != '-') && + (val != '_') && (val != ':') && + (!IS_COMBINING(val)) && + (!IS_EXTENDER(val))) + return(0); + + while ((IS_LETTER(val)) || (IS_DIGIT(val)) || + (val == '.') || (val == '-') || + (val == '_') || (val == ':') || + (IS_COMBINING(val)) || + (IS_EXTENDER(val))) { + val = xmlStringCurrentChar(NULL, cur, &len); + cur += len; + } + + /* Should not test IS_BLANK(val) here -- see erratum E20*/ + while (val == 0x20) { + while (val == 0x20) { + val = xmlStringCurrentChar(NULL, cur, &len); + cur += len; + } + if (val == 0) return(1); + + if (!IS_LETTER(val) && !IS_DIGIT(val) && + (val != '.') && (val != '-') && + (val != '_') && (val != ':') && + (!IS_COMBINING(val)) && + (!IS_EXTENDER(val))) + return(0); + + while ((IS_LETTER(val)) || (IS_DIGIT(val)) || + (val == '.') || (val == '-') || + (val == '_') || (val == ':') || + (IS_COMBINING(val)) || + (IS_EXTENDER(val))) { + val = xmlStringCurrentChar(NULL, cur, &len); + cur += len; + } + } + + if (val != 0) return(0); + + return(1); +} + +/** + * xmlValidateNotationDecl: + * @ctxt: the validation context + * @doc: a document instance + * @nota: a notation definition + * + * Try to validate a single notation definition + * basically it does the following checks as described by the + * XML-1.0 recommendation: + * - it seems that no validity constraint exists on notation declarations + * But this function get called anyway ... + * + * returns 1 if valid or 0 otherwise + */ + +int +xmlValidateNotationDecl(xmlValidCtxtPtr ctxt ATTRIBUTE_UNUSED, xmlDocPtr doc ATTRIBUTE_UNUSED, + xmlNotationPtr nota ATTRIBUTE_UNUSED) { + int ret = 1; + + return(ret); +} + +/** + * xmlValidateAttributeValue: + * @type: an attribute type + * @value: an attribute value + * + * Validate that the given attribute value match the proper production + * + * [ VC: ID ] + * Values of type ID must match the Name production.... + * + * [ VC: IDREF ] + * Values of type IDREF must match the Name production, and values + * of type IDREFS must match Names ... + * + * [ VC: Entity Name ] + * Values of type ENTITY must match the Name production, values + * of type ENTITIES must match Names ... + * + * [ VC: Name Token ] + * Values of type NMTOKEN must match the Nmtoken production; values + * of type NMTOKENS must match Nmtokens. + * + * returns 1 if valid or 0 otherwise + */ + +int +xmlValidateAttributeValue(xmlAttributeType type, const xmlChar *value) { + switch (type) { + case XML_ATTRIBUTE_ENTITIES: + case XML_ATTRIBUTE_IDREFS: + return(xmlValidateNamesValue(value)); + case XML_ATTRIBUTE_ENTITY: + case XML_ATTRIBUTE_IDREF: + case XML_ATTRIBUTE_ID: + case XML_ATTRIBUTE_NOTATION: + return(xmlValidateNameValue(value)); + case XML_ATTRIBUTE_NMTOKENS: + case XML_ATTRIBUTE_ENUMERATION: + return(xmlValidateNmtokensValue(value)); + case XML_ATTRIBUTE_NMTOKEN: + return(xmlValidateNmtokenValue(value)); + case XML_ATTRIBUTE_CDATA: + break; + } + return(1); +} + +/** + * xmlValidateAttributeValue2: + * @ctxt: the validation context + * @doc: the document + * @name: the attribute name (used for error reporting only) + * @type: the attribute type + * @value: the attribute value + * + * Validate that the given attribute value match a given type. + * This typically cannot be done before having finished parsing + * the subsets. + * + * [ VC: IDREF ] + * Values of type IDREF must match one of the declared IDs + * Values of type IDREFS must match a sequence of the declared IDs + * each Name must match the value of an ID attribute on some element + * in the XML document; i.e. IDREF values must match the value of + * some ID attribute + * + * [ VC: Entity Name ] + * Values of type ENTITY must match one declared entity + * Values of type ENTITIES must match a sequence of declared entities + * + * [ VC: Notation Attributes ] + * all notation names in the declaration must be declared. + * + * returns 1 if valid or 0 otherwise + */ + +static int +xmlValidateAttributeValue2(xmlValidCtxtPtr ctxt, xmlDocPtr doc, + const xmlChar *name, xmlAttributeType type, const xmlChar *value) { + int ret = 1; + switch (type) { + case XML_ATTRIBUTE_IDREFS: + case XML_ATTRIBUTE_IDREF: + case XML_ATTRIBUTE_ID: + case XML_ATTRIBUTE_NMTOKENS: + case XML_ATTRIBUTE_ENUMERATION: + case XML_ATTRIBUTE_NMTOKEN: + case XML_ATTRIBUTE_CDATA: + break; + case XML_ATTRIBUTE_ENTITY: { + xmlEntityPtr ent; + + ent = xmlGetDocEntity(doc, value); + /* yeah it's a bit messy... */ + if ((ent == NULL) && (doc->standalone == 1)) { + doc->standalone = 0; + ent = xmlGetDocEntity(doc, value); + } + if (ent == NULL) { + xmlErrValidNode(ctxt, (xmlNodePtr) doc, + XML_DTD_UNKNOWN_ENTITY, + "ENTITY attribute %s reference an unknown entity \"%s\"\n", + name, value, NULL); + ret = 0; + } else if (ent->etype != XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) { + xmlErrValidNode(ctxt, (xmlNodePtr) doc, + XML_DTD_ENTITY_TYPE, + "ENTITY attribute %s reference an entity \"%s\" of wrong type\n", + name, value, NULL); + ret = 0; + } + break; + } + case XML_ATTRIBUTE_ENTITIES: { + xmlChar *dup, *nam = NULL, *cur, save; + xmlEntityPtr ent; + + dup = xmlStrdup(value); + if (dup == NULL) + return(0); + cur = dup; + while (*cur != 0) { + nam = cur; + while ((*cur != 0) && (!IS_BLANK_CH(*cur))) cur++; + save = *cur; + *cur = 0; + ent = xmlGetDocEntity(doc, nam); + if (ent == NULL) { + xmlErrValidNode(ctxt, (xmlNodePtr) doc, + XML_DTD_UNKNOWN_ENTITY, + "ENTITIES attribute %s reference an unknown entity \"%s\"\n", + name, nam, NULL); + ret = 0; + } else if (ent->etype != XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) { + xmlErrValidNode(ctxt, (xmlNodePtr) doc, + XML_DTD_ENTITY_TYPE, + "ENTITIES attribute %s reference an entity \"%s\" of wrong type\n", + name, nam, NULL); + ret = 0; + } + if (save == 0) + break; + *cur = save; + while (IS_BLANK_CH(*cur)) cur++; + } + xmlFree(dup); + break; + } + case XML_ATTRIBUTE_NOTATION: { + xmlNotationPtr nota; + + nota = xmlGetDtdNotationDesc(doc->intSubset, value); + if ((nota == NULL) && (doc->extSubset != NULL)) + nota = xmlGetDtdNotationDesc(doc->extSubset, value); + + if (nota == NULL) { + xmlErrValidNode(ctxt, (xmlNodePtr) doc, + XML_DTD_UNKNOWN_NOTATION, + "NOTATION attribute %s reference an unknown notation \"%s\"\n", + name, value, NULL); + ret = 0; + } + break; + } + } + return(ret); +} + +/** + * xmlValidCtxtNormalizeAttributeValue: + * @ctxt: the validation context + * @doc: the document + * @elem: the parent + * @name: the attribute name + * @value: the attribute value + * @ctxt: the validation context or NULL + * + * Does the validation related extra step of the normalization of attribute + * values: + * + * If the declared value is not CDATA, then the XML processor must further + * process the normalized attribute value by discarding any leading and + * trailing space (#x20) characters, and by replacing sequences of space + * (#x20) characters by single space (#x20) character. + * + * Also check VC: Standalone Document Declaration in P32, and update + * ctxt->valid accordingly + * + * returns a new normalized string if normalization is needed, NULL otherwise + * the caller must free the returned value. + */ + +xmlChar * +xmlValidCtxtNormalizeAttributeValue(xmlValidCtxtPtr ctxt, xmlDocPtr doc, + xmlNodePtr elem, const xmlChar *name, const xmlChar *value) { + xmlChar *ret, *dst; + const xmlChar *src; + xmlAttributePtr attrDecl = NULL; + int extsubset = 0; + + if (doc == NULL) return(NULL); + if (elem == NULL) return(NULL); + if (name == NULL) return(NULL); + if (value == NULL) return(NULL); + + if ((elem->ns != NULL) && (elem->ns->prefix != NULL)) { + xmlChar fn[50]; + xmlChar *fullname; + + fullname = xmlBuildQName(elem->name, elem->ns->prefix, fn, 50); + if (fullname == NULL) + return(NULL); + attrDecl = xmlGetDtdAttrDesc(doc->intSubset, fullname, name); + if ((attrDecl == NULL) && (doc->extSubset != NULL)) { + attrDecl = xmlGetDtdAttrDesc(doc->extSubset, fullname, name); + if (attrDecl != NULL) + extsubset = 1; + } + if ((fullname != fn) && (fullname != elem->name)) + xmlFree(fullname); + } + if ((attrDecl == NULL) && (doc->intSubset != NULL)) + attrDecl = xmlGetDtdAttrDesc(doc->intSubset, elem->name, name); + if ((attrDecl == NULL) && (doc->extSubset != NULL)) { + attrDecl = xmlGetDtdAttrDesc(doc->extSubset, elem->name, name); + if (attrDecl != NULL) + extsubset = 1; + } + + if (attrDecl == NULL) + return(NULL); + if (attrDecl->atype == XML_ATTRIBUTE_CDATA) + return(NULL); + + ret = xmlStrdup(value); + if (ret == NULL) + return(NULL); + src = value; + dst = ret; + while (*src == 0x20) src++; + while (*src != 0) { + if (*src == 0x20) { + while (*src == 0x20) src++; + if (*src != 0) + *dst++ = 0x20; + } else { + *dst++ = *src++; + } + } + *dst = 0; + if ((doc->standalone) && (extsubset == 1) && (!xmlStrEqual(value, ret))) { + xmlErrValidNode(ctxt, elem, XML_DTD_NOT_STANDALONE, +"standalone: %s on %s value had to be normalized based on external subset declaration\n", + name, elem->name, NULL); + ctxt->valid = 0; + } + return(ret); +} + +/** + * xmlValidNormalizeAttributeValue: + * @doc: the document + * @elem: the parent + * @name: the attribute name + * @value: the attribute value + * + * Does the validation related extra step of the normalization of attribute + * values: + * + * If the declared value is not CDATA, then the XML processor must further + * process the normalized attribute value by discarding any leading and + * trailing space (#x20) characters, and by replacing sequences of space + * (#x20) characters by single space (#x20) character. + * + * Returns a new normalized string if normalization is needed, NULL otherwise + * the caller must free the returned value. + */ + +xmlChar * +xmlValidNormalizeAttributeValue(xmlDocPtr doc, xmlNodePtr elem, + const xmlChar *name, const xmlChar *value) { + xmlChar *ret, *dst; + const xmlChar *src; + xmlAttributePtr attrDecl = NULL; + + if (doc == NULL) return(NULL); + if (elem == NULL) return(NULL); + if (name == NULL) return(NULL); + if (value == NULL) return(NULL); + + if ((elem->ns != NULL) && (elem->ns->prefix != NULL)) { + xmlChar fn[50]; + xmlChar *fullname; + + fullname = xmlBuildQName(elem->name, elem->ns->prefix, fn, 50); + if (fullname == NULL) + return(NULL); + attrDecl = xmlGetDtdAttrDesc(doc->intSubset, fullname, name); + if ((attrDecl == NULL) && (doc->extSubset != NULL)) + attrDecl = xmlGetDtdAttrDesc(doc->extSubset, fullname, name); + if ((fullname != fn) && (fullname != elem->name)) + xmlFree(fullname); + } + attrDecl = xmlGetDtdAttrDesc(doc->intSubset, elem->name, name); + if ((attrDecl == NULL) && (doc->extSubset != NULL)) + attrDecl = xmlGetDtdAttrDesc(doc->extSubset, elem->name, name); + + if (attrDecl == NULL) + return(NULL); + if (attrDecl->atype == XML_ATTRIBUTE_CDATA) + return(NULL); + + ret = xmlStrdup(value); + if (ret == NULL) + return(NULL); + src = value; + dst = ret; + while (*src == 0x20) src++; + while (*src != 0) { + if (*src == 0x20) { + while (*src == 0x20) src++; + if (*src != 0) + *dst++ = 0x20; + } else { + *dst++ = *src++; + } + } + *dst = 0; + return(ret); +} + +static void +xmlValidateAttributeIdCallback(xmlAttributePtr attr, int *count, + const xmlChar* name ATTRIBUTE_UNUSED) { + if (attr->atype == XML_ATTRIBUTE_ID) (*count)++; +} + +/** + * xmlValidateAttributeDecl: + * @ctxt: the validation context + * @doc: a document instance + * @attr: an attribute definition + * + * Try to validate a single attribute definition + * basically it does the following checks as described by the + * XML-1.0 recommendation: + * - [ VC: Attribute Default Legal ] + * - [ VC: Enumeration ] + * - [ VC: ID Attribute Default ] + * + * The ID/IDREF uniqueness and matching are done separately + * + * returns 1 if valid or 0 otherwise + */ + +int +xmlValidateAttributeDecl(xmlValidCtxtPtr ctxt, xmlDocPtr doc, + xmlAttributePtr attr) { + int ret = 1; + int val; + CHECK_DTD; + if(attr == NULL) return(1); + + /* Attribute Default Legal */ + /* Enumeration */ + if (attr->defaultValue != NULL) { + val = xmlValidateAttributeValue(attr->atype, attr->defaultValue); + if (val == 0) { + xmlErrValidNode(ctxt, (xmlNodePtr) attr, XML_DTD_ATTRIBUTE_DEFAULT, + "Syntax of default value for attribute %s of %s is not valid\n", + attr->name, attr->elem, NULL); + } + ret &= val; + } + + /* ID Attribute Default */ + if ((attr->atype == XML_ATTRIBUTE_ID)&& + (attr->def != XML_ATTRIBUTE_IMPLIED) && + (attr->def != XML_ATTRIBUTE_REQUIRED)) { + xmlErrValidNode(ctxt, (xmlNodePtr) attr, XML_DTD_ID_FIXED, + "ID attribute %s of %s is not valid must be #IMPLIED or #REQUIRED\n", + attr->name, attr->elem, NULL); + ret = 0; + } + + /* One ID per Element Type */ + if (attr->atype == XML_ATTRIBUTE_ID) { + int nbId; + + /* the trick is that we parse DtD as their own internal subset */ + xmlElementPtr elem = xmlGetDtdElementDesc(doc->intSubset, + attr->elem); + if (elem != NULL) { + nbId = xmlScanIDAttributeDecl(NULL, elem, 0); + } else { + xmlAttributeTablePtr table; + + /* + * The attribute may be declared in the internal subset and the + * element in the external subset. + */ + nbId = 0; + if (doc->intSubset != NULL) { + table = (xmlAttributeTablePtr) doc->intSubset->attributes; + xmlHashScan3(table, NULL, NULL, attr->elem, (xmlHashScanner) + xmlValidateAttributeIdCallback, &nbId); + } + } + if (nbId > 1) { + + xmlErrValidNodeNr(ctxt, (xmlNodePtr) attr, XML_DTD_ID_SUBSET, + "Element %s has %d ID attribute defined in the internal subset : %s\n", + attr->elem, nbId, attr->name); + } else if (doc->extSubset != NULL) { + int extId = 0; + elem = xmlGetDtdElementDesc(doc->extSubset, attr->elem); + if (elem != NULL) { + extId = xmlScanIDAttributeDecl(NULL, elem, 0); + } + if (extId > 1) { + xmlErrValidNodeNr(ctxt, (xmlNodePtr) attr, XML_DTD_ID_SUBSET, + "Element %s has %d ID attribute defined in the external subset : %s\n", + attr->elem, extId, attr->name); + } else if (extId + nbId > 1) { + xmlErrValidNode(ctxt, (xmlNodePtr) attr, XML_DTD_ID_SUBSET, +"Element %s has ID attributes defined in the internal and external subset : %s\n", + attr->elem, attr->name, NULL); + } + } + } + + /* Validity Constraint: Enumeration */ + if ((attr->defaultValue != NULL) && (attr->tree != NULL)) { + xmlEnumerationPtr tree = attr->tree; + while (tree != NULL) { + if (xmlStrEqual(tree->name, attr->defaultValue)) break; + tree = tree->next; + } + if (tree == NULL) { + xmlErrValidNode(ctxt, (xmlNodePtr) attr, XML_DTD_ATTRIBUTE_VALUE, +"Default value \"%s\" for attribute %s of %s is not among the enumerated set\n", + attr->defaultValue, attr->name, attr->elem); + ret = 0; + } + } + + return(ret); +} + +/** + * xmlValidateElementDecl: + * @ctxt: the validation context + * @doc: a document instance + * @elem: an element definition + * + * Try to validate a single element definition + * basically it does the following checks as described by the + * XML-1.0 recommendation: + * - [ VC: One ID per Element Type ] + * - [ VC: No Duplicate Types ] + * - [ VC: Unique Element Type Declaration ] + * + * returns 1 if valid or 0 otherwise + */ + +int +xmlValidateElementDecl(xmlValidCtxtPtr ctxt, xmlDocPtr doc, + xmlElementPtr elem) { + int ret = 1; + xmlElementPtr tst; + + CHECK_DTD; + + if (elem == NULL) return(1); + +#if 0 +#ifdef LIBXML_REGEXP_ENABLED + /* Build the regexp associated to the content model */ + ret = xmlValidBuildContentModel(ctxt, elem); +#endif +#endif + + /* No Duplicate Types */ + if (elem->etype == XML_ELEMENT_TYPE_MIXED) { + xmlElementContentPtr cur, next; + const xmlChar *name; + + cur = elem->content; + while (cur != NULL) { + if (cur->type != XML_ELEMENT_CONTENT_OR) break; + if (cur->c1 == NULL) break; + if (cur->c1->type == XML_ELEMENT_CONTENT_ELEMENT) { + name = cur->c1->name; + next = cur->c2; + while (next != NULL) { + if (next->type == XML_ELEMENT_CONTENT_ELEMENT) { + if ((xmlStrEqual(next->name, name)) && + (xmlStrEqual(next->prefix, cur->prefix))) { + if (cur->prefix == NULL) { + xmlErrValidNode(ctxt, (xmlNodePtr) elem, XML_DTD_CONTENT_ERROR, + "Definition of %s has duplicate references of %s\n", + elem->name, name, NULL); + } else { + xmlErrValidNode(ctxt, (xmlNodePtr) elem, XML_DTD_CONTENT_ERROR, + "Definition of %s has duplicate references of %s:%s\n", + elem->name, cur->prefix, name); + } + ret = 0; + } + break; + } + if (next->c1 == NULL) break; + if (next->c1->type != XML_ELEMENT_CONTENT_ELEMENT) break; + if ((xmlStrEqual(next->c1->name, name)) && + (xmlStrEqual(next->c1->prefix, cur->prefix))) { + if (cur->prefix == NULL) { + xmlErrValidNode(ctxt, (xmlNodePtr) elem, XML_DTD_CONTENT_ERROR, + "Definition of %s has duplicate references to %s\n", + elem->name, name, NULL); + } else { + xmlErrValidNode(ctxt, (xmlNodePtr) elem, XML_DTD_CONTENT_ERROR, + "Definition of %s has duplicate references to %s:%s\n", + elem->name, cur->prefix, name); + } + ret = 0; + } + next = next->c2; + } + } + cur = cur->c2; + } + } + + /* VC: Unique Element Type Declaration */ + tst = xmlGetDtdElementDesc(doc->intSubset, elem->name); + if ((tst != NULL ) && (tst != elem) && + ((tst->prefix == elem->prefix) || + (xmlStrEqual(tst->prefix, elem->prefix))) && + (tst->etype != XML_ELEMENT_TYPE_UNDEFINED)) { + xmlErrValidNode(ctxt, (xmlNodePtr) elem, XML_DTD_ELEM_REDEFINED, + "Redefinition of element %s\n", + elem->name, NULL, NULL); + ret = 0; + } + tst = xmlGetDtdElementDesc(doc->extSubset, elem->name); + if ((tst != NULL ) && (tst != elem) && + ((tst->prefix == elem->prefix) || + (xmlStrEqual(tst->prefix, elem->prefix))) && + (tst->etype != XML_ELEMENT_TYPE_UNDEFINED)) { + xmlErrValidNode(ctxt, (xmlNodePtr) elem, XML_DTD_ELEM_REDEFINED, + "Redefinition of element %s\n", + elem->name, NULL, NULL); + ret = 0; + } + /* One ID per Element Type + * already done when registering the attribute + if (xmlScanIDAttributeDecl(ctxt, elem) > 1) { + ret = 0; + } */ + return(ret); +} + +/** + * xmlValidateOneAttribute: + * @ctxt: the validation context + * @doc: a document instance + * @elem: an element instance + * @attr: an attribute instance + * @value: the attribute value (without entities processing) + * + * Try to validate a single attribute for an element + * basically it does the following checks as described by the + * XML-1.0 recommendation: + * - [ VC: Attribute Value Type ] + * - [ VC: Fixed Attribute Default ] + * - [ VC: Entity Name ] + * - [ VC: Name Token ] + * - [ VC: ID ] + * - [ VC: IDREF ] + * - [ VC: Entity Name ] + * - [ VC: Notation Attributes ] + * + * The ID/IDREF uniqueness and matching are done separately + * + * returns 1 if valid or 0 otherwise + */ + +int +xmlValidateOneAttribute(xmlValidCtxtPtr ctxt, xmlDocPtr doc, + xmlNodePtr elem, xmlAttrPtr attr, const xmlChar *value) +{ + xmlAttributePtr attrDecl = NULL; + int val; + int ret = 1; + + CHECK_DTD; + if ((elem == NULL) || (elem->name == NULL)) return(0); + if ((attr == NULL) || (attr->name == NULL)) return(0); + + if ((elem->ns != NULL) && (elem->ns->prefix != NULL)) { + xmlChar fn[50]; + xmlChar *fullname; + + fullname = xmlBuildQName(elem->name, elem->ns->prefix, fn, 50); + if (fullname == NULL) + return(0); + if (attr->ns != NULL) { + attrDecl = xmlGetDtdQAttrDesc(doc->intSubset, fullname, + attr->name, attr->ns->prefix); + if ((attrDecl == NULL) && (doc->extSubset != NULL)) + attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, fullname, + attr->name, attr->ns->prefix); + } else { + attrDecl = xmlGetDtdAttrDesc(doc->intSubset, fullname, attr->name); + if ((attrDecl == NULL) && (doc->extSubset != NULL)) + attrDecl = xmlGetDtdAttrDesc(doc->extSubset, + fullname, attr->name); + } + if ((fullname != fn) && (fullname != elem->name)) + xmlFree(fullname); + } + if (attrDecl == NULL) { + if (attr->ns != NULL) { + attrDecl = xmlGetDtdQAttrDesc(doc->intSubset, elem->name, + attr->name, attr->ns->prefix); + if ((attrDecl == NULL) && (doc->extSubset != NULL)) + attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, elem->name, + attr->name, attr->ns->prefix); + } else { + attrDecl = xmlGetDtdAttrDesc(doc->intSubset, + elem->name, attr->name); + if ((attrDecl == NULL) && (doc->extSubset != NULL)) + attrDecl = xmlGetDtdAttrDesc(doc->extSubset, + elem->name, attr->name); + } + } + + + /* Validity Constraint: Attribute Value Type */ + if (attrDecl == NULL) { + xmlErrValidNode(ctxt, elem, XML_DTD_UNKNOWN_ATTRIBUTE, + "No declaration for attribute %s of element %s\n", + attr->name, elem->name, NULL); + return(0); + } + attr->atype = attrDecl->atype; + + val = xmlValidateAttributeValue(attrDecl->atype, value); + if (val == 0) { + xmlErrValidNode(ctxt, elem, XML_DTD_ATTRIBUTE_VALUE, + "Syntax of value for attribute %s of %s is not valid\n", + attr->name, elem->name, NULL); + ret = 0; + } + + /* Validity constraint: Fixed Attribute Default */ + if (attrDecl->def == XML_ATTRIBUTE_FIXED) { + if (!xmlStrEqual(value, attrDecl->defaultValue)) { + xmlErrValidNode(ctxt, elem, XML_DTD_ATTRIBUTE_DEFAULT, + "Value for attribute %s of %s is different from default \"%s\"\n", + attr->name, elem->name, attrDecl->defaultValue); + ret = 0; + } + } + + /* Validity Constraint: ID uniqueness */ + if (attrDecl->atype == XML_ATTRIBUTE_ID) { + if (xmlAddID(ctxt, doc, value, attr) == NULL) + ret = 0; + } + + if ((attrDecl->atype == XML_ATTRIBUTE_IDREF) || + (attrDecl->atype == XML_ATTRIBUTE_IDREFS)) { + if (xmlAddRef(ctxt, doc, value, attr) == NULL) + ret = 0; + } + + /* Validity Constraint: Notation Attributes */ + if (attrDecl->atype == XML_ATTRIBUTE_NOTATION) { + xmlEnumerationPtr tree = attrDecl->tree; + xmlNotationPtr nota; + + /* First check that the given NOTATION was declared */ + nota = xmlGetDtdNotationDesc(doc->intSubset, value); + if (nota == NULL) + nota = xmlGetDtdNotationDesc(doc->extSubset, value); + + if (nota == NULL) { + xmlErrValidNode(ctxt, elem, XML_DTD_UNKNOWN_NOTATION, + "Value \"%s\" for attribute %s of %s is not a declared Notation\n", + value, attr->name, elem->name); + ret = 0; + } + + /* Second, verify that it's among the list */ + while (tree != NULL) { + if (xmlStrEqual(tree->name, value)) break; + tree = tree->next; + } + if (tree == NULL) { + xmlErrValidNode(ctxt, elem, XML_DTD_NOTATION_VALUE, +"Value \"%s\" for attribute %s of %s is not among the enumerated notations\n", + value, attr->name, elem->name); + ret = 0; + } + } + + /* Validity Constraint: Enumeration */ + if (attrDecl->atype == XML_ATTRIBUTE_ENUMERATION) { + xmlEnumerationPtr tree = attrDecl->tree; + while (tree != NULL) { + if (xmlStrEqual(tree->name, value)) break; + tree = tree->next; + } + if (tree == NULL) { + xmlErrValidNode(ctxt, elem, XML_DTD_ATTRIBUTE_VALUE, + "Value \"%s\" for attribute %s of %s is not among the enumerated set\n", + value, attr->name, elem->name); + ret = 0; + } + } + + /* Fixed Attribute Default */ + if ((attrDecl->def == XML_ATTRIBUTE_FIXED) && + (!xmlStrEqual(attrDecl->defaultValue, value))) { + xmlErrValidNode(ctxt, elem, XML_DTD_ATTRIBUTE_VALUE, + "Value for attribute %s of %s must be \"%s\"\n", + attr->name, elem->name, attrDecl->defaultValue); + ret = 0; + } + + /* Extra check for the attribute value */ + ret &= xmlValidateAttributeValue2(ctxt, doc, attr->name, + attrDecl->atype, value); + + return(ret); +} + +/** + * xmlValidateOneNamespace: + * @ctxt: the validation context + * @doc: a document instance + * @elem: an element instance + * @prefix: the namespace prefix + * @ns: an namespace declaration instance + * @value: the attribute value (without entities processing) + * + * Try to validate a single namespace declaration for an element + * basically it does the following checks as described by the + * XML-1.0 recommendation: + * - [ VC: Attribute Value Type ] + * - [ VC: Fixed Attribute Default ] + * - [ VC: Entity Name ] + * - [ VC: Name Token ] + * - [ VC: ID ] + * - [ VC: IDREF ] + * - [ VC: Entity Name ] + * - [ VC: Notation Attributes ] + * + * The ID/IDREF uniqueness and matching are done separately + * + * returns 1 if valid or 0 otherwise + */ + +int +xmlValidateOneNamespace(xmlValidCtxtPtr ctxt, xmlDocPtr doc, +xmlNodePtr elem, const xmlChar *prefix, xmlNsPtr ns, const xmlChar *value) { + /* xmlElementPtr elemDecl; */ + xmlAttributePtr attrDecl = NULL; + int val; + int ret = 1; + + CHECK_DTD; + if ((elem == NULL) || (elem->name == NULL)) return(0); + if ((ns == NULL) || (ns->href == NULL)) return(0); + + if (prefix != NULL) { + xmlChar fn[50]; + xmlChar *fullname; + + fullname = xmlBuildQName(elem->name, prefix, fn, 50); + if (fullname == NULL) { + xmlVErrMemory(ctxt, "Validating namespace"); + return(0); + } + if (ns->prefix != NULL) { + attrDecl = xmlGetDtdQAttrDesc(doc->intSubset, fullname, + ns->prefix, BAD_CAST "xmlns"); + if ((attrDecl == NULL) && (doc->extSubset != NULL)) + attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, fullname, + ns->prefix, BAD_CAST "xmlns"); + } else { + attrDecl = xmlGetDtdAttrDesc(doc->intSubset, fullname, + BAD_CAST "xmlns"); + if ((attrDecl == NULL) && (doc->extSubset != NULL)) + attrDecl = xmlGetDtdAttrDesc(doc->extSubset, fullname, + BAD_CAST "xmlns"); + } + if ((fullname != fn) && (fullname != elem->name)) + xmlFree(fullname); + } + if (attrDecl == NULL) { + if (ns->prefix != NULL) { + attrDecl = xmlGetDtdQAttrDesc(doc->intSubset, elem->name, + ns->prefix, BAD_CAST "xmlns"); + if ((attrDecl == NULL) && (doc->extSubset != NULL)) + attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, elem->name, + ns->prefix, BAD_CAST "xmlns"); + } else { + attrDecl = xmlGetDtdAttrDesc(doc->intSubset, + elem->name, BAD_CAST "xmlns"); + if ((attrDecl == NULL) && (doc->extSubset != NULL)) + attrDecl = xmlGetDtdAttrDesc(doc->extSubset, + elem->name, BAD_CAST "xmlns"); + } + } + + + /* Validity Constraint: Attribute Value Type */ + if (attrDecl == NULL) { + if (ns->prefix != NULL) { + xmlErrValidNode(ctxt, elem, XML_DTD_UNKNOWN_ATTRIBUTE, + "No declaration for attribute xmlns:%s of element %s\n", + ns->prefix, elem->name, NULL); + } else { + xmlErrValidNode(ctxt, elem, XML_DTD_UNKNOWN_ATTRIBUTE, + "No declaration for attribute xmlns of element %s\n", + elem->name, NULL, NULL); + } + return(0); + } + + val = xmlValidateAttributeValue(attrDecl->atype, value); + if (val == 0) { + if (ns->prefix != NULL) { + xmlErrValidNode(ctxt, elem, XML_DTD_INVALID_DEFAULT, + "Syntax of value for attribute xmlns:%s of %s is not valid\n", + ns->prefix, elem->name, NULL); + } else { + xmlErrValidNode(ctxt, elem, XML_DTD_INVALID_DEFAULT, + "Syntax of value for attribute xmlns of %s is not valid\n", + elem->name, NULL, NULL); + } + ret = 0; + } + + /* Validity constraint: Fixed Attribute Default */ + if (attrDecl->def == XML_ATTRIBUTE_FIXED) { + if (!xmlStrEqual(value, attrDecl->defaultValue)) { + if (ns->prefix != NULL) { + xmlErrValidNode(ctxt, elem, XML_DTD_ATTRIBUTE_DEFAULT, + "Value for attribute xmlns:%s of %s is different from default \"%s\"\n", + ns->prefix, elem->name, attrDecl->defaultValue); + } else { + xmlErrValidNode(ctxt, elem, XML_DTD_ATTRIBUTE_DEFAULT, + "Value for attribute xmlns of %s is different from default \"%s\"\n", + elem->name, attrDecl->defaultValue, NULL); + } + ret = 0; + } + } + + /* Validity Constraint: ID uniqueness */ + if (attrDecl->atype == XML_ATTRIBUTE_ID) { + if (xmlAddID(ctxt, doc, value, (xmlAttrPtr) ns) == NULL) + ret = 0; + } + + if ((attrDecl->atype == XML_ATTRIBUTE_IDREF) || + (attrDecl->atype == XML_ATTRIBUTE_IDREFS)) { + if (xmlAddRef(ctxt, doc, value, (xmlAttrPtr) ns) == NULL) + ret = 0; + } + + /* Validity Constraint: Notation Attributes */ + if (attrDecl->atype == XML_ATTRIBUTE_NOTATION) { + xmlEnumerationPtr tree = attrDecl->tree; + xmlNotationPtr nota; + + /* First check that the given NOTATION was declared */ + nota = xmlGetDtdNotationDesc(doc->intSubset, value); + if (nota == NULL) + nota = xmlGetDtdNotationDesc(doc->extSubset, value); + + if (nota == NULL) { + if (ns->prefix != NULL) { + xmlErrValidNode(ctxt, elem, XML_DTD_UNKNOWN_NOTATION, + "Value \"%s\" for attribute xmlns:%s of %s is not a declared Notation\n", + value, ns->prefix, elem->name); + } else { + xmlErrValidNode(ctxt, elem, XML_DTD_UNKNOWN_NOTATION, + "Value \"%s\" for attribute xmlns of %s is not a declared Notation\n", + value, elem->name, NULL); + } + ret = 0; + } + + /* Second, verify that it's among the list */ + while (tree != NULL) { + if (xmlStrEqual(tree->name, value)) break; + tree = tree->next; + } + if (tree == NULL) { + if (ns->prefix != NULL) { + xmlErrValidNode(ctxt, elem, XML_DTD_NOTATION_VALUE, +"Value \"%s\" for attribute xmlns:%s of %s is not among the enumerated notations\n", + value, ns->prefix, elem->name); + } else { + xmlErrValidNode(ctxt, elem, XML_DTD_NOTATION_VALUE, +"Value \"%s\" for attribute xmlns of %s is not among the enumerated notations\n", + value, elem->name, NULL); + } + ret = 0; + } + } + + /* Validity Constraint: Enumeration */ + if (attrDecl->atype == XML_ATTRIBUTE_ENUMERATION) { + xmlEnumerationPtr tree = attrDecl->tree; + while (tree != NULL) { + if (xmlStrEqual(tree->name, value)) break; + tree = tree->next; + } + if (tree == NULL) { + if (ns->prefix != NULL) { + xmlErrValidNode(ctxt, elem, XML_DTD_ATTRIBUTE_VALUE, +"Value \"%s\" for attribute xmlns:%s of %s is not among the enumerated set\n", + value, ns->prefix, elem->name); + } else { + xmlErrValidNode(ctxt, elem, XML_DTD_ATTRIBUTE_VALUE, +"Value \"%s\" for attribute xmlns of %s is not among the enumerated set\n", + value, elem->name, NULL); + } + ret = 0; + } + } + + /* Fixed Attribute Default */ + if ((attrDecl->def == XML_ATTRIBUTE_FIXED) && + (!xmlStrEqual(attrDecl->defaultValue, value))) { + if (ns->prefix != NULL) { + xmlErrValidNode(ctxt, elem, XML_DTD_ELEM_NAMESPACE, + "Value for attribute xmlns:%s of %s must be \"%s\"\n", + ns->prefix, elem->name, attrDecl->defaultValue); + } else { + xmlErrValidNode(ctxt, elem, XML_DTD_ELEM_NAMESPACE, + "Value for attribute xmlns of %s must be \"%s\"\n", + elem->name, attrDecl->defaultValue, NULL); + } + ret = 0; + } + + /* Extra check for the attribute value */ + if (ns->prefix != NULL) { + ret &= xmlValidateAttributeValue2(ctxt, doc, ns->prefix, + attrDecl->atype, value); + } else { + ret &= xmlValidateAttributeValue2(ctxt, doc, BAD_CAST "xmlns", + attrDecl->atype, value); + } + + return(ret); +} + +#ifndef LIBXML_REGEXP_ENABLED +/** + * xmlValidateSkipIgnorable: + * @ctxt: the validation context + * @child: the child list + * + * Skip ignorable elements w.r.t. the validation process + * + * returns the first element to consider for validation of the content model + */ + +static xmlNodePtr +xmlValidateSkipIgnorable(xmlNodePtr child) { + while (child != NULL) { + switch (child->type) { + /* These things are ignored (skipped) during validation. */ + case XML_PI_NODE: + case XML_COMMENT_NODE: + case XML_XINCLUDE_START: + case XML_XINCLUDE_END: + child = child->next; + break; + case XML_TEXT_NODE: + if (xmlIsBlankNode(child)) + child = child->next; + else + return(child); + break; + /* keep current node */ + default: + return(child); + } + } + return(child); +} + +/** + * xmlValidateElementType: + * @ctxt: the validation context + * + * Try to validate the content model of an element internal function + * + * returns 1 if valid or 0 ,-1 in case of error, -2 if an entity + * reference is found and -3 if the validation succeeded but + * the content model is not determinist. + */ + +static int +xmlValidateElementType(xmlValidCtxtPtr ctxt) { + int ret = -1; + int determinist = 1; + + NODE = xmlValidateSkipIgnorable(NODE); + if ((NODE == NULL) && (CONT == NULL)) + return(1); + if ((NODE == NULL) && + ((CONT->ocur == XML_ELEMENT_CONTENT_MULT) || + (CONT->ocur == XML_ELEMENT_CONTENT_OPT))) { + return(1); + } + if (CONT == NULL) return(-1); + if ((NODE != NULL) && (NODE->type == XML_ENTITY_REF_NODE)) + return(-2); + + /* + * We arrive here when more states need to be examined + */ +cont: + + /* + * We just recovered from a rollback generated by a possible + * epsilon transition, go directly to the analysis phase + */ + if (STATE == ROLLBACK_PARENT) { + DEBUG_VALID_MSG("restored parent branch"); + DEBUG_VALID_STATE(NODE, CONT) + ret = 1; + goto analyze; + } + + DEBUG_VALID_STATE(NODE, CONT) + /* + * we may have to save a backup state here. This is the equivalent + * of handling epsilon transition in NFAs. + */ + if ((CONT != NULL) && + ((CONT->parent == NULL) || + (CONT->parent->type != XML_ELEMENT_CONTENT_OR)) && + ((CONT->ocur == XML_ELEMENT_CONTENT_MULT) || + (CONT->ocur == XML_ELEMENT_CONTENT_OPT) || + ((CONT->ocur == XML_ELEMENT_CONTENT_PLUS) && (OCCURRENCE)))) { + DEBUG_VALID_MSG("saving parent branch"); + if (vstateVPush(ctxt, CONT, NODE, DEPTH, OCCURS, ROLLBACK_PARENT) < 0) + return(0); + } + + + /* + * Check first if the content matches + */ + switch (CONT->type) { + case XML_ELEMENT_CONTENT_PCDATA: + if (NODE == NULL) { + DEBUG_VALID_MSG("pcdata failed no node"); + ret = 0; + break; + } + if (NODE->type == XML_TEXT_NODE) { + DEBUG_VALID_MSG("pcdata found, skip to next"); + /* + * go to next element in the content model + * skipping ignorable elems + */ + do { + NODE = NODE->next; + NODE = xmlValidateSkipIgnorable(NODE); + if ((NODE != NULL) && + (NODE->type == XML_ENTITY_REF_NODE)) + return(-2); + } while ((NODE != NULL) && + ((NODE->type != XML_ELEMENT_NODE) && + (NODE->type != XML_TEXT_NODE) && + (NODE->type != XML_CDATA_SECTION_NODE))); + ret = 1; + break; + } else { + DEBUG_VALID_MSG("pcdata failed"); + ret = 0; + break; + } + break; + case XML_ELEMENT_CONTENT_ELEMENT: + if (NODE == NULL) { + DEBUG_VALID_MSG("element failed no node"); + ret = 0; + break; + } + ret = ((NODE->type == XML_ELEMENT_NODE) && + (xmlStrEqual(NODE->name, CONT->name))); + if (ret == 1) { + if ((NODE->ns == NULL) || (NODE->ns->prefix == NULL)) { + ret = (CONT->prefix == NULL); + } else if (CONT->prefix == NULL) { + ret = 0; + } else { + ret = xmlStrEqual(NODE->ns->prefix, CONT->prefix); + } + } + if (ret == 1) { + DEBUG_VALID_MSG("element found, skip to next"); + /* + * go to next element in the content model + * skipping ignorable elems + */ + do { + NODE = NODE->next; + NODE = xmlValidateSkipIgnorable(NODE); + if ((NODE != NULL) && + (NODE->type == XML_ENTITY_REF_NODE)) + return(-2); + } while ((NODE != NULL) && + ((NODE->type != XML_ELEMENT_NODE) && + (NODE->type != XML_TEXT_NODE) && + (NODE->type != XML_CDATA_SECTION_NODE))); + } else { + DEBUG_VALID_MSG("element failed"); + ret = 0; + break; + } + break; + case XML_ELEMENT_CONTENT_OR: + /* + * Small optimization. + */ + if (CONT->c1->type == XML_ELEMENT_CONTENT_ELEMENT) { + if ((NODE == NULL) || + (!xmlStrEqual(NODE->name, CONT->c1->name))) { + DEPTH++; + CONT = CONT->c2; + goto cont; + } + if ((NODE->ns == NULL) || (NODE->ns->prefix == NULL)) { + ret = (CONT->c1->prefix == NULL); + } else if (CONT->c1->prefix == NULL) { + ret = 0; + } else { + ret = xmlStrEqual(NODE->ns->prefix, CONT->c1->prefix); + } + if (ret == 0) { + DEPTH++; + CONT = CONT->c2; + goto cont; + } + } + + /* + * save the second branch 'or' branch + */ + DEBUG_VALID_MSG("saving 'or' branch"); + if (vstateVPush(ctxt, CONT->c2, NODE, (unsigned char)(DEPTH + 1), + OCCURS, ROLLBACK_OR) < 0) + return(-1); + DEPTH++; + CONT = CONT->c1; + goto cont; + case XML_ELEMENT_CONTENT_SEQ: + /* + * Small optimization. + */ + if ((CONT->c1->type == XML_ELEMENT_CONTENT_ELEMENT) && + ((CONT->c1->ocur == XML_ELEMENT_CONTENT_OPT) || + (CONT->c1->ocur == XML_ELEMENT_CONTENT_MULT))) { + if ((NODE == NULL) || + (!xmlStrEqual(NODE->name, CONT->c1->name))) { + DEPTH++; + CONT = CONT->c2; + goto cont; + } + if ((NODE->ns == NULL) || (NODE->ns->prefix == NULL)) { + ret = (CONT->c1->prefix == NULL); + } else if (CONT->c1->prefix == NULL) { + ret = 0; + } else { + ret = xmlStrEqual(NODE->ns->prefix, CONT->c1->prefix); + } + if (ret == 0) { + DEPTH++; + CONT = CONT->c2; + goto cont; + } + } + DEPTH++; + CONT = CONT->c1; + goto cont; + } + + /* + * At this point handle going up in the tree + */ + if (ret == -1) { + DEBUG_VALID_MSG("error found returning"); + return(ret); + } +analyze: + while (CONT != NULL) { + /* + * First do the analysis depending on the occurrence model at + * this level. + */ + if (ret == 0) { + switch (CONT->ocur) { + xmlNodePtr cur; + + case XML_ELEMENT_CONTENT_ONCE: + cur = ctxt->vstate->node; + DEBUG_VALID_MSG("Once branch failed, rollback"); + if (vstateVPop(ctxt) < 0 ) { + DEBUG_VALID_MSG("exhaustion, failed"); + return(0); + } + if (cur != ctxt->vstate->node) + determinist = -3; + goto cont; + case XML_ELEMENT_CONTENT_PLUS: + if (OCCURRENCE == 0) { + cur = ctxt->vstate->node; + DEBUG_VALID_MSG("Plus branch failed, rollback"); + if (vstateVPop(ctxt) < 0 ) { + DEBUG_VALID_MSG("exhaustion, failed"); + return(0); + } + if (cur != ctxt->vstate->node) + determinist = -3; + goto cont; + } + DEBUG_VALID_MSG("Plus branch found"); + ret = 1; + break; + case XML_ELEMENT_CONTENT_MULT: +#ifdef DEBUG_VALID_ALGO + if (OCCURRENCE == 0) { + DEBUG_VALID_MSG("Mult branch failed"); + } else { + DEBUG_VALID_MSG("Mult branch found"); + } +#endif + ret = 1; + break; + case XML_ELEMENT_CONTENT_OPT: + DEBUG_VALID_MSG("Option branch failed"); + ret = 1; + break; + } + } else { + switch (CONT->ocur) { + case XML_ELEMENT_CONTENT_OPT: + DEBUG_VALID_MSG("Option branch succeeded"); + ret = 1; + break; + case XML_ELEMENT_CONTENT_ONCE: + DEBUG_VALID_MSG("Once branch succeeded"); + ret = 1; + break; + case XML_ELEMENT_CONTENT_PLUS: + if (STATE == ROLLBACK_PARENT) { + DEBUG_VALID_MSG("Plus branch rollback"); + ret = 1; + break; + } + if (NODE == NULL) { + DEBUG_VALID_MSG("Plus branch exhausted"); + ret = 1; + break; + } + DEBUG_VALID_MSG("Plus branch succeeded, continuing"); + SET_OCCURRENCE; + goto cont; + case XML_ELEMENT_CONTENT_MULT: + if (STATE == ROLLBACK_PARENT) { + DEBUG_VALID_MSG("Mult branch rollback"); + ret = 1; + break; + } + if (NODE == NULL) { + DEBUG_VALID_MSG("Mult branch exhausted"); + ret = 1; + break; + } + DEBUG_VALID_MSG("Mult branch succeeded, continuing"); + /* SET_OCCURRENCE; */ + goto cont; + } + } + STATE = 0; + + /* + * Then act accordingly at the parent level + */ + RESET_OCCURRENCE; + if (CONT->parent == NULL) + break; + + switch (CONT->parent->type) { + case XML_ELEMENT_CONTENT_PCDATA: + DEBUG_VALID_MSG("Error: parent pcdata"); + return(-1); + case XML_ELEMENT_CONTENT_ELEMENT: + DEBUG_VALID_MSG("Error: parent element"); + return(-1); + case XML_ELEMENT_CONTENT_OR: + if (ret == 1) { + DEBUG_VALID_MSG("Or succeeded"); + CONT = CONT->parent; + DEPTH--; + } else { + DEBUG_VALID_MSG("Or failed"); + CONT = CONT->parent; + DEPTH--; + } + break; + case XML_ELEMENT_CONTENT_SEQ: + if (ret == 0) { + DEBUG_VALID_MSG("Sequence failed"); + CONT = CONT->parent; + DEPTH--; + } else if (CONT == CONT->parent->c1) { + DEBUG_VALID_MSG("Sequence testing 2nd branch"); + CONT = CONT->parent->c2; + goto cont; + } else { + DEBUG_VALID_MSG("Sequence succeeded"); + CONT = CONT->parent; + DEPTH--; + } + } + } + if (NODE != NULL) { + xmlNodePtr cur; + + cur = ctxt->vstate->node; + DEBUG_VALID_MSG("Failed, remaining input, rollback"); + if (vstateVPop(ctxt) < 0 ) { + DEBUG_VALID_MSG("exhaustion, failed"); + return(0); + } + if (cur != ctxt->vstate->node) + determinist = -3; + goto cont; + } + if (ret == 0) { + xmlNodePtr cur; + + cur = ctxt->vstate->node; + DEBUG_VALID_MSG("Failure, rollback"); + if (vstateVPop(ctxt) < 0 ) { + DEBUG_VALID_MSG("exhaustion, failed"); + return(0); + } + if (cur != ctxt->vstate->node) + determinist = -3; + goto cont; + } + return(determinist); +} +#endif + +/** + * xmlSnprintfElements: + * @buf: an output buffer + * @size: the size of the buffer + * @content: An element + * @glob: 1 if one must print the englobing parenthesis, 0 otherwise + * + * This will dump the list of elements to the buffer + * Intended just for the debug routine + */ +static void +xmlSnprintfElements(char *buf, int size, xmlNodePtr node, int glob) { + xmlNodePtr cur; + int len; + + if (node == NULL) return; + if (glob) strcat(buf, "("); + cur = node; + while (cur != NULL) { + len = strlen(buf); + if (size - len < 50) { + if ((size - len > 4) && (buf[len - 1] != '.')) + strcat(buf, " ..."); + return; + } + switch (cur->type) { + case XML_ELEMENT_NODE: + if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) { + if (size - len < xmlStrlen(cur->ns->prefix) + 10) { + if ((size - len > 4) && (buf[len - 1] != '.')) + strcat(buf, " ..."); + return; + } + strcat(buf, (char *) cur->ns->prefix); + strcat(buf, ":"); + } + if (size - len < xmlStrlen(cur->name) + 10) { + if ((size - len > 4) && (buf[len - 1] != '.')) + strcat(buf, " ..."); + return; + } + strcat(buf, (char *) cur->name); + if (cur->next != NULL) + strcat(buf, " "); + break; + case XML_TEXT_NODE: + if (xmlIsBlankNode(cur)) + break; + case XML_CDATA_SECTION_NODE: + case XML_ENTITY_REF_NODE: + strcat(buf, "CDATA"); + if (cur->next != NULL) + strcat(buf, " "); + break; + case XML_ATTRIBUTE_NODE: + case XML_DOCUMENT_NODE: +#ifdef LIBXML_DOCB_ENABLED + case XML_DOCB_DOCUMENT_NODE: +#endif + case XML_HTML_DOCUMENT_NODE: + case XML_DOCUMENT_TYPE_NODE: + case XML_DOCUMENT_FRAG_NODE: + case XML_NOTATION_NODE: + case XML_NAMESPACE_DECL: + strcat(buf, "???"); + if (cur->next != NULL) + strcat(buf, " "); + break; + case XML_ENTITY_NODE: + case XML_PI_NODE: + case XML_DTD_NODE: + case XML_COMMENT_NODE: + case XML_ELEMENT_DECL: + case XML_ATTRIBUTE_DECL: + case XML_ENTITY_DECL: + case XML_XINCLUDE_START: + case XML_XINCLUDE_END: + break; + } + cur = cur->next; + } + if (glob) strcat(buf, ")"); +} + +/** + * xmlValidateElementContent: + * @ctxt: the validation context + * @child: the child list + * @elemDecl: pointer to the element declaration + * @warn: emit the error message + * @parent: the parent element (for error reporting) + * + * Try to validate the content model of an element + * + * returns 1 if valid or 0 if not and -1 in case of error + */ + +static int +xmlValidateElementContent(xmlValidCtxtPtr ctxt, xmlNodePtr child, + xmlElementPtr elemDecl, int warn, xmlNodePtr parent) { + int ret = 1; +#ifndef LIBXML_REGEXP_ENABLED + xmlNodePtr repl = NULL, last = NULL, tmp; +#endif + xmlNodePtr cur; + xmlElementContentPtr cont; + const xmlChar *name; + + if (elemDecl == NULL) + return(-1); + cont = elemDecl->content; + name = elemDecl->name; + +#ifdef LIBXML_REGEXP_ENABLED + /* Build the regexp associated to the content model */ + if (elemDecl->contModel == NULL) + ret = xmlValidBuildContentModel(ctxt, elemDecl); + if (elemDecl->contModel == NULL) { + return(-1); + } else { + xmlRegExecCtxtPtr exec; + + if (!xmlRegexpIsDeterminist(elemDecl->contModel)) { + return(-1); + } + ctxt->nodeMax = 0; + ctxt->nodeNr = 0; + ctxt->nodeTab = NULL; + exec = xmlRegNewExecCtxt(elemDecl->contModel, NULL, NULL); + if (exec != NULL) { + cur = child; + while (cur != NULL) { + switch (cur->type) { + case XML_ENTITY_REF_NODE: + /* + * Push the current node to be able to roll back + * and process within the entity + */ + if ((cur->children != NULL) && + (cur->children->children != NULL)) { + nodeVPush(ctxt, cur); + cur = cur->children->children; + continue; + } + break; + case XML_TEXT_NODE: + if (xmlIsBlankNode(cur)) + break; + ret = 0; + goto fail; + case XML_CDATA_SECTION_NODE: + /* TODO */ + ret = 0; + goto fail; + case XML_ELEMENT_NODE: + if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) { + xmlChar fn[50]; + xmlChar *fullname; + + fullname = xmlBuildQName(cur->name, + cur->ns->prefix, fn, 50); + if (fullname == NULL) { + ret = -1; + goto fail; + } + ret = xmlRegExecPushString(exec, fullname, NULL); + if ((fullname != fn) && (fullname != cur->name)) + xmlFree(fullname); + } else { + ret = xmlRegExecPushString(exec, cur->name, NULL); + } + break; + default: + break; + } + /* + * Switch to next element + */ + cur = cur->next; + while (cur == NULL) { + cur = nodeVPop(ctxt); + if (cur == NULL) + break; + cur = cur->next; + } + } + ret = xmlRegExecPushString(exec, NULL, NULL); +fail: + xmlRegFreeExecCtxt(exec); + } + } +#else /* LIBXML_REGEXP_ENABLED */ + /* + * Allocate the stack + */ + ctxt->vstateMax = 8; + ctxt->vstateTab = (xmlValidState *) xmlMalloc( + ctxt->vstateMax * sizeof(ctxt->vstateTab[0])); + if (ctxt->vstateTab == NULL) { + xmlVErrMemory(ctxt, "malloc failed"); + return(-1); + } + /* + * The first entry in the stack is reserved to the current state + */ + ctxt->nodeMax = 0; + ctxt->nodeNr = 0; + ctxt->nodeTab = NULL; + ctxt->vstate = &ctxt->vstateTab[0]; + ctxt->vstateNr = 1; + CONT = cont; + NODE = child; + DEPTH = 0; + OCCURS = 0; + STATE = 0; + ret = xmlValidateElementType(ctxt); + if ((ret == -3) && (warn)) { + xmlErrValidWarning(ctxt, child, XML_DTD_CONTENT_NOT_DETERMINIST, + "Content model for Element %s is ambiguous\n", + name, NULL, NULL); + } else if (ret == -2) { + /* + * An entities reference appeared at this level. + * Buid a minimal representation of this node content + * sufficient to run the validation process on it + */ + DEBUG_VALID_MSG("Found an entity reference, linearizing"); + cur = child; + while (cur != NULL) { + switch (cur->type) { + case XML_ENTITY_REF_NODE: + /* + * Push the current node to be able to roll back + * and process within the entity + */ + if ((cur->children != NULL) && + (cur->children->children != NULL)) { + nodeVPush(ctxt, cur); + cur = cur->children->children; + continue; + } + break; + case XML_TEXT_NODE: + if (xmlIsBlankNode(cur)) + break; + /* no break on purpose */ + case XML_CDATA_SECTION_NODE: + /* no break on purpose */ + case XML_ELEMENT_NODE: + /* + * Allocate a new node and minimally fills in + * what's required + */ + tmp = (xmlNodePtr) xmlMalloc(sizeof(xmlNode)); + if (tmp == NULL) { + xmlVErrMemory(ctxt, "malloc failed"); + xmlFreeNodeList(repl); + ret = -1; + goto done; + } + tmp->type = cur->type; + tmp->name = cur->name; + tmp->ns = cur->ns; + tmp->next = NULL; + tmp->content = NULL; + if (repl == NULL) + repl = last = tmp; + else { + last->next = tmp; + last = tmp; + } + if (cur->type == XML_CDATA_SECTION_NODE) { + /* + * E59 spaces in CDATA does not match the + * nonterminal S + */ + tmp->content = xmlStrdup(BAD_CAST "CDATA"); + } + break; + default: + break; + } + /* + * Switch to next element + */ + cur = cur->next; + while (cur == NULL) { + cur = nodeVPop(ctxt); + if (cur == NULL) + break; + cur = cur->next; + } + } + + /* + * Relaunch the validation + */ + ctxt->vstate = &ctxt->vstateTab[0]; + ctxt->vstateNr = 1; + CONT = cont; + NODE = repl; + DEPTH = 0; + OCCURS = 0; + STATE = 0; + ret = xmlValidateElementType(ctxt); + } +#endif /* LIBXML_REGEXP_ENABLED */ + if ((warn) && ((ret != 1) && (ret != -3))) { + if (ctxt != NULL) { + char expr[5000]; + char list[5000]; + + expr[0] = 0; + xmlSnprintfElementContent(&expr[0], 5000, cont, 1); + list[0] = 0; +#ifndef LIBXML_REGEXP_ENABLED + if (repl != NULL) + xmlSnprintfElements(&list[0], 5000, repl, 1); + else +#endif /* LIBXML_REGEXP_ENABLED */ + xmlSnprintfElements(&list[0], 5000, child, 1); + + if (name != NULL) { + xmlErrValidNode(ctxt, parent, XML_DTD_CONTENT_MODEL, + "Element %s content does not follow the DTD, expecting %s, got %s\n", + name, BAD_CAST expr, BAD_CAST list); + } else { + xmlErrValidNode(ctxt, parent, XML_DTD_CONTENT_MODEL, + "Element content does not follow the DTD, expecting %s, got %s\n", + BAD_CAST expr, BAD_CAST list, NULL); + } + } else { + if (name != NULL) { + xmlErrValidNode(ctxt, parent, XML_DTD_CONTENT_MODEL, + "Element %s content does not follow the DTD\n", + name, NULL, NULL); + } else { + xmlErrValidNode(ctxt, parent, XML_DTD_CONTENT_MODEL, + "Element content does not follow the DTD\n", + NULL, NULL, NULL); + } + } + ret = 0; + } + if (ret == -3) + ret = 1; + +#ifndef LIBXML_REGEXP_ENABLED +done: + /* + * Deallocate the copy if done, and free up the validation stack + */ + while (repl != NULL) { + tmp = repl->next; + xmlFree(repl); + repl = tmp; + } + ctxt->vstateMax = 0; + if (ctxt->vstateTab != NULL) { + xmlFree(ctxt->vstateTab); + ctxt->vstateTab = NULL; + } +#endif + ctxt->nodeMax = 0; + ctxt->nodeNr = 0; + if (ctxt->nodeTab != NULL) { + xmlFree(ctxt->nodeTab); + ctxt->nodeTab = NULL; + } + return(ret); + +} + +/** + * xmlValidateCdataElement: + * @ctxt: the validation context + * @doc: a document instance + * @elem: an element instance + * + * Check that an element follows #CDATA + * + * returns 1 if valid or 0 otherwise + */ +static int +xmlValidateOneCdataElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc, + xmlNodePtr elem) { + int ret = 1; + xmlNodePtr cur, child; + + if ((ctxt == NULL) || (doc == NULL) || (elem == NULL)) + return(0); + + child = elem->children; + + cur = child; + while (cur != NULL) { + switch (cur->type) { + case XML_ENTITY_REF_NODE: + /* + * Push the current node to be able to roll back + * and process within the entity + */ + if ((cur->children != NULL) && + (cur->children->children != NULL)) { + nodeVPush(ctxt, cur); + cur = cur->children->children; + continue; + } + break; + case XML_COMMENT_NODE: + case XML_PI_NODE: + case XML_TEXT_NODE: + case XML_CDATA_SECTION_NODE: + break; + default: + ret = 0; + goto done; + } + /* + * Switch to next element + */ + cur = cur->next; + while (cur == NULL) { + cur = nodeVPop(ctxt); + if (cur == NULL) + break; + cur = cur->next; + } + } +done: + ctxt->nodeMax = 0; + ctxt->nodeNr = 0; + if (ctxt->nodeTab != NULL) { + xmlFree(ctxt->nodeTab); + ctxt->nodeTab = NULL; + } + return(ret); +} + +/** + * xmlValidateCheckMixed: + * @ctxt: the validation context + * @cont: the mixed content model + * @qname: the qualified name as appearing in the serialization + * + * Check if the given node is part of the content model. + * + * Returns 1 if yes, 0 if no, -1 in case of error + */ +static int +xmlValidateCheckMixed(xmlValidCtxtPtr ctxt, + xmlElementContentPtr cont, const xmlChar *qname) { + const xmlChar *name; + int plen; + name = xmlSplitQName3(qname, &plen); + + if (name == NULL) { + while (cont != NULL) { + if (cont->type == XML_ELEMENT_CONTENT_ELEMENT) { + if ((cont->prefix == NULL) && (xmlStrEqual(cont->name, qname))) + return(1); + } else if ((cont->type == XML_ELEMENT_CONTENT_OR) && + (cont->c1 != NULL) && + (cont->c1->type == XML_ELEMENT_CONTENT_ELEMENT)){ + if ((cont->c1->prefix == NULL) && + (xmlStrEqual(cont->c1->name, qname))) + return(1); + } else if ((cont->type != XML_ELEMENT_CONTENT_OR) || + (cont->c1 == NULL) || + (cont->c1->type != XML_ELEMENT_CONTENT_PCDATA)){ + xmlErrValid(NULL, XML_DTD_MIXED_CORRUPT, + "Internal: MIXED struct corrupted\n", + NULL); + break; + } + cont = cont->c2; + } + } else { + while (cont != NULL) { + if (cont->type == XML_ELEMENT_CONTENT_ELEMENT) { + if ((cont->prefix != NULL) && + (xmlStrncmp(cont->prefix, qname, plen) == 0) && + (xmlStrEqual(cont->name, name))) + return(1); + } else if ((cont->type == XML_ELEMENT_CONTENT_OR) && + (cont->c1 != NULL) && + (cont->c1->type == XML_ELEMENT_CONTENT_ELEMENT)){ + if ((cont->c1->prefix != NULL) && + (xmlStrncmp(cont->c1->prefix, qname, plen) == 0) && + (xmlStrEqual(cont->c1->name, name))) + return(1); + } else if ((cont->type != XML_ELEMENT_CONTENT_OR) || + (cont->c1 == NULL) || + (cont->c1->type != XML_ELEMENT_CONTENT_PCDATA)){ + xmlErrValid(ctxt, XML_DTD_MIXED_CORRUPT, + "Internal: MIXED struct corrupted\n", + NULL); + break; + } + cont = cont->c2; + } + } + return(0); +} + +/** + * xmlValidGetElemDecl: + * @ctxt: the validation context + * @doc: a document instance + * @elem: an element instance + * @extsubset: pointer, (out) indicate if the declaration was found + * in the external subset. + * + * Finds a declaration associated to an element in the document. + * + * returns the pointer to the declaration or NULL if not found. + */ +static xmlElementPtr +xmlValidGetElemDecl(xmlValidCtxtPtr ctxt, xmlDocPtr doc, + xmlNodePtr elem, int *extsubset) { + xmlElementPtr elemDecl = NULL; + const xmlChar *prefix = NULL; + + if ((ctxt == NULL) || (doc == NULL) || + (elem == NULL) || (elem->name == NULL)) + return(NULL); + if (extsubset != NULL) + *extsubset = 0; + + /* + * Fetch the declaration for the qualified name + */ + if ((elem->ns != NULL) && (elem->ns->prefix != NULL)) + prefix = elem->ns->prefix; + + if (prefix != NULL) { + elemDecl = xmlGetDtdQElementDesc(doc->intSubset, + elem->name, prefix); + if ((elemDecl == NULL) && (doc->extSubset != NULL)) { + elemDecl = xmlGetDtdQElementDesc(doc->extSubset, + elem->name, prefix); + if ((elemDecl != NULL) && (extsubset != NULL)) + *extsubset = 1; + } + } + + /* + * Fetch the declaration for the non qualified name + * This is "non-strict" validation should be done on the + * full QName but in that case being flexible makes sense. + */ + if (elemDecl == NULL) { + elemDecl = xmlGetDtdElementDesc(doc->intSubset, elem->name); + if ((elemDecl == NULL) && (doc->extSubset != NULL)) { + elemDecl = xmlGetDtdElementDesc(doc->extSubset, elem->name); + if ((elemDecl != NULL) && (extsubset != NULL)) + *extsubset = 1; + } + } + if (elemDecl == NULL) { + xmlErrValidNode(ctxt, elem, + XML_DTD_UNKNOWN_ELEM, + "No declaration for element %s\n", + elem->name, NULL, NULL); + } + return(elemDecl); +} + +#ifdef LIBXML_REGEXP_ENABLED +/** + * xmlValidatePushElement: + * @ctxt: the validation context + * @doc: a document instance + * @elem: an element instance + * @qname: the qualified name as appearing in the serialization + * + * Push a new element start on the validation stack. + * + * returns 1 if no validation problem was found or 0 otherwise + */ +int +xmlValidatePushElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc, + xmlNodePtr elem, const xmlChar *qname) { + int ret = 1; + xmlElementPtr eDecl; + int extsubset = 0; + + if (ctxt == NULL) + return(0); +/* printf("PushElem %s\n", qname); */ + if ((ctxt->vstateNr > 0) && (ctxt->vstate != NULL)) { + xmlValidStatePtr state = ctxt->vstate; + xmlElementPtr elemDecl; + + /* + * Check the new element agaisnt the content model of the new elem. + */ + if (state->elemDecl != NULL) { + elemDecl = state->elemDecl; + + switch(elemDecl->etype) { + case XML_ELEMENT_TYPE_UNDEFINED: + ret = 0; + break; + case XML_ELEMENT_TYPE_EMPTY: + xmlErrValidNode(ctxt, state->node, + XML_DTD_NOT_EMPTY, + "Element %s was declared EMPTY this one has content\n", + state->node->name, NULL, NULL); + ret = 0; + break; + case XML_ELEMENT_TYPE_ANY: + /* I don't think anything is required then */ + break; + case XML_ELEMENT_TYPE_MIXED: + /* simple case of declared as #PCDATA */ + if ((elemDecl->content != NULL) && + (elemDecl->content->type == + XML_ELEMENT_CONTENT_PCDATA)) { + xmlErrValidNode(ctxt, state->node, + XML_DTD_NOT_PCDATA, + "Element %s was declared #PCDATA but contains non text nodes\n", + state->node->name, NULL, NULL); + ret = 0; + } else { + ret = xmlValidateCheckMixed(ctxt, elemDecl->content, + qname); + if (ret != 1) { + xmlErrValidNode(ctxt, state->node, + XML_DTD_INVALID_CHILD, + "Element %s is not declared in %s list of possible children\n", + qname, state->node->name, NULL); + } + } + break; + case XML_ELEMENT_TYPE_ELEMENT: + /* + * TODO: + * VC: Standalone Document Declaration + * - element types with element content, if white space + * occurs directly within any instance of those types. + */ + if (state->exec != NULL) { + ret = xmlRegExecPushString(state->exec, qname, NULL); + if (ret < 0) { + xmlErrValidNode(ctxt, state->node, + XML_DTD_CONTENT_MODEL, + "Element %s content does not follow the DTD, Misplaced %s\n", + state->node->name, qname, NULL); + ret = 0; + } else { + ret = 1; + } + } + break; + } + } + } + eDecl = xmlValidGetElemDecl(ctxt, doc, elem, &extsubset); + vstateVPush(ctxt, eDecl, elem); + return(ret); +} + +/** + * xmlValidatePushCData: + * @ctxt: the validation context + * @data: some character data read + * @len: the lenght of the data + * + * check the CData parsed for validation in the current stack + * + * returns 1 if no validation problem was found or 0 otherwise + */ +int +xmlValidatePushCData(xmlValidCtxtPtr ctxt, const xmlChar *data, int len) { + int ret = 1; + +/* printf("CDATA %s %d\n", data, len); */ + if (ctxt == NULL) + return(0); + if (len <= 0) + return(ret); + if ((ctxt->vstateNr > 0) && (ctxt->vstate != NULL)) { + xmlValidStatePtr state = ctxt->vstate; + xmlElementPtr elemDecl; + + /* + * Check the new element agaisnt the content model of the new elem. + */ + if (state->elemDecl != NULL) { + elemDecl = state->elemDecl; + + switch(elemDecl->etype) { + case XML_ELEMENT_TYPE_UNDEFINED: + ret = 0; + break; + case XML_ELEMENT_TYPE_EMPTY: + xmlErrValidNode(ctxt, state->node, + XML_DTD_NOT_EMPTY, + "Element %s was declared EMPTY this one has content\n", + state->node->name, NULL, NULL); + ret = 0; + break; + case XML_ELEMENT_TYPE_ANY: + break; + case XML_ELEMENT_TYPE_MIXED: + break; + case XML_ELEMENT_TYPE_ELEMENT: + if (len > 0) { + int i; + + for (i = 0;i < len;i++) { + if (!IS_BLANK_CH(data[i])) { + xmlErrValidNode(ctxt, state->node, + XML_DTD_CONTENT_MODEL, + "Element %s content does not follow the DTD, Text not allowed\n", + state->node->name, NULL, NULL); + ret = 0; + goto done; + } + } + /* + * TODO: + * VC: Standalone Document Declaration + * element types with element content, if white space + * occurs directly within any instance of those types. + */ + } + break; + } + } + } +done: + return(ret); +} + +/** + * xmlValidatePopElement: + * @ctxt: the validation context + * @doc: a document instance + * @elem: an element instance + * @qname: the qualified name as appearing in the serialization + * + * Pop the element end from the validation stack. + * + * returns 1 if no validation problem was found or 0 otherwise + */ +int +xmlValidatePopElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc ATTRIBUTE_UNUSED, + xmlNodePtr elem ATTRIBUTE_UNUSED, + const xmlChar *qname ATTRIBUTE_UNUSED) { + int ret = 1; + + if (ctxt == NULL) + return(0); +/* printf("PopElem %s\n", qname); */ + if ((ctxt->vstateNr > 0) && (ctxt->vstate != NULL)) { + xmlValidStatePtr state = ctxt->vstate; + xmlElementPtr elemDecl; + + /* + * Check the new element agaisnt the content model of the new elem. + */ + if (state->elemDecl != NULL) { + elemDecl = state->elemDecl; + + if (elemDecl->etype == XML_ELEMENT_TYPE_ELEMENT) { + if (state->exec != NULL) { + ret = xmlRegExecPushString(state->exec, NULL, NULL); + if (ret == 0) { + xmlErrValidNode(ctxt, state->node, + XML_DTD_CONTENT_MODEL, + "Element %s content does not follow the DTD, Expecting more child\n", + state->node->name, NULL,NULL); + } else { + /* + * previous validation errors should not generate + * a new one here + */ + ret = 1; + } + } + } + } + vstateVPop(ctxt); + } + return(ret); +} +#endif /* LIBXML_REGEXP_ENABLED */ + +/** + * xmlValidateOneElement: + * @ctxt: the validation context + * @doc: a document instance + * @elem: an element instance + * + * Try to validate a single element and it's attributes, + * basically it does the following checks as described by the + * XML-1.0 recommendation: + * - [ VC: Element Valid ] + * - [ VC: Required Attribute ] + * Then call xmlValidateOneAttribute() for each attribute present. + * + * The ID/IDREF checkings are done separately + * + * returns 1 if valid or 0 otherwise + */ + +int +xmlValidateOneElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc, + xmlNodePtr elem) { + xmlElementPtr elemDecl = NULL; + xmlElementContentPtr cont; + xmlAttributePtr attr; + xmlNodePtr child; + int ret = 1, tmp; + const xmlChar *name; + int extsubset = 0; + + CHECK_DTD; + + if (elem == NULL) return(0); + switch (elem->type) { + case XML_ATTRIBUTE_NODE: + xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR, + "Attribute element not expected\n", NULL, NULL ,NULL); + return(0); + case XML_TEXT_NODE: + if (elem->children != NULL) { + xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR, + "Text element has children !\n", + NULL,NULL,NULL); + return(0); + } + if (elem->ns != NULL) { + xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR, + "Text element has namespace !\n", + NULL,NULL,NULL); + return(0); + } + if (elem->content == NULL) { + xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR, + "Text element has no content !\n", + NULL,NULL,NULL); + return(0); + } + return(1); + case XML_XINCLUDE_START: + case XML_XINCLUDE_END: + return(1); + case XML_CDATA_SECTION_NODE: + case XML_ENTITY_REF_NODE: + case XML_PI_NODE: + case XML_COMMENT_NODE: + return(1); + case XML_ENTITY_NODE: + xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR, + "Entity element not expected\n", NULL, NULL ,NULL); + return(0); + case XML_NOTATION_NODE: + xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR, + "Notation element not expected\n", NULL, NULL ,NULL); + return(0); + case XML_DOCUMENT_NODE: + case XML_DOCUMENT_TYPE_NODE: + case XML_DOCUMENT_FRAG_NODE: + xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR, + "Document element not expected\n", NULL, NULL ,NULL); + return(0); + case XML_HTML_DOCUMENT_NODE: + xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR, + "HTML Document not expected\n", NULL, NULL ,NULL); + return(0); + case XML_ELEMENT_NODE: + break; + default: + xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR, + "unknown element type\n", NULL, NULL ,NULL); + return(0); + } + + /* + * Fetch the declaration + */ + elemDecl = xmlValidGetElemDecl(ctxt, doc, elem, &extsubset); + if (elemDecl == NULL) + return(0); + + /* + * If vstateNr is not zero that means continuous validation is + * activated, do not try to check the content model at that level. + */ + if (ctxt->vstateNr == 0) { + /* Check that the element content matches the definition */ + switch (elemDecl->etype) { + case XML_ELEMENT_TYPE_UNDEFINED: + xmlErrValidNode(ctxt, elem, XML_DTD_UNKNOWN_ELEM, + "No declaration for element %s\n", + elem->name, NULL, NULL); + return(0); + case XML_ELEMENT_TYPE_EMPTY: + if (elem->children != NULL) { + xmlErrValidNode(ctxt, elem, XML_DTD_NOT_EMPTY, + "Element %s was declared EMPTY this one has content\n", + elem->name, NULL, NULL); + ret = 0; + } + break; + case XML_ELEMENT_TYPE_ANY: + /* I don't think anything is required then */ + break; + case XML_ELEMENT_TYPE_MIXED: + + /* simple case of declared as #PCDATA */ + if ((elemDecl->content != NULL) && + (elemDecl->content->type == XML_ELEMENT_CONTENT_PCDATA)) { + ret = xmlValidateOneCdataElement(ctxt, doc, elem); + if (!ret) { + xmlErrValidNode(ctxt, elem, XML_DTD_NOT_PCDATA, + "Element %s was declared #PCDATA but contains non text nodes\n", + elem->name, NULL, NULL); + } + break; + } + child = elem->children; + /* Hum, this start to get messy */ + while (child != NULL) { + if (child->type == XML_ELEMENT_NODE) { + name = child->name; + if ((child->ns != NULL) && (child->ns->prefix != NULL)) { + xmlChar fn[50]; + xmlChar *fullname; + + fullname = xmlBuildQName(child->name, child->ns->prefix, + fn, 50); + if (fullname == NULL) + return(0); + cont = elemDecl->content; + while (cont != NULL) { + if (cont->type == XML_ELEMENT_CONTENT_ELEMENT) { + if (xmlStrEqual(cont->name, fullname)) + break; + } else if ((cont->type == XML_ELEMENT_CONTENT_OR) && + (cont->c1 != NULL) && + (cont->c1->type == XML_ELEMENT_CONTENT_ELEMENT)){ + if (xmlStrEqual(cont->c1->name, fullname)) + break; + } else if ((cont->type != XML_ELEMENT_CONTENT_OR) || + (cont->c1 == NULL) || + (cont->c1->type != XML_ELEMENT_CONTENT_PCDATA)){ + xmlErrValid(NULL, XML_DTD_MIXED_CORRUPT, + "Internal: MIXED struct corrupted\n", + NULL); + break; + } + cont = cont->c2; + } + if ((fullname != fn) && (fullname != child->name)) + xmlFree(fullname); + if (cont != NULL) + goto child_ok; + } + cont = elemDecl->content; + while (cont != NULL) { + if (cont->type == XML_ELEMENT_CONTENT_ELEMENT) { + if (xmlStrEqual(cont->name, name)) break; + } else if ((cont->type == XML_ELEMENT_CONTENT_OR) && + (cont->c1 != NULL) && + (cont->c1->type == XML_ELEMENT_CONTENT_ELEMENT)) { + if (xmlStrEqual(cont->c1->name, name)) break; + } else if ((cont->type != XML_ELEMENT_CONTENT_OR) || + (cont->c1 == NULL) || + (cont->c1->type != XML_ELEMENT_CONTENT_PCDATA)) { + xmlErrValid(ctxt, XML_DTD_MIXED_CORRUPT, + "Internal: MIXED struct corrupted\n", + NULL); + break; + } + cont = cont->c2; + } + if (cont == NULL) { + xmlErrValidNode(ctxt, elem, XML_DTD_INVALID_CHILD, + "Element %s is not declared in %s list of possible children\n", + name, elem->name, NULL); + ret = 0; + } + } +child_ok: + child = child->next; + } + break; + case XML_ELEMENT_TYPE_ELEMENT: + if ((doc->standalone == 1) && (extsubset == 1)) { + /* + * VC: Standalone Document Declaration + * - element types with element content, if white space + * occurs directly within any instance of those types. + */ + child = elem->children; + while (child != NULL) { + if (child->type == XML_TEXT_NODE) { + const xmlChar *content = child->content; + + while (IS_BLANK_CH(*content)) + content++; + if (*content == 0) { + xmlErrValidNode(ctxt, elem, + XML_DTD_STANDALONE_WHITE_SPACE, +"standalone: %s declared in the external subset contains white spaces nodes\n", + elem->name, NULL, NULL); + ret = 0; + break; + } + } + child =child->next; + } + } + child = elem->children; + cont = elemDecl->content; + tmp = xmlValidateElementContent(ctxt, child, elemDecl, 1, elem); + if (tmp <= 0) + ret = tmp; + break; + } + } /* not continuous */ + + /* [ VC: Required Attribute ] */ + attr = elemDecl->attributes; + while (attr != NULL) { + if (attr->def == XML_ATTRIBUTE_REQUIRED) { + int qualified = -1; + + if ((attr->prefix == NULL) && + (xmlStrEqual(attr->name, BAD_CAST "xmlns"))) { + xmlNsPtr ns; + + ns = elem->nsDef; + while (ns != NULL) { + if (ns->prefix == NULL) + goto found; + ns = ns->next; + } + } else if (xmlStrEqual(attr->prefix, BAD_CAST "xmlns")) { + xmlNsPtr ns; + + ns = elem->nsDef; + while (ns != NULL) { + if (xmlStrEqual(attr->name, ns->prefix)) + goto found; + ns = ns->next; + } + } else { + xmlAttrPtr attrib; + + attrib = elem->properties; + while (attrib != NULL) { + if (xmlStrEqual(attrib->name, attr->name)) { + if (attr->prefix != NULL) { + xmlNsPtr nameSpace = attrib->ns; + + if (nameSpace == NULL) + nameSpace = elem->ns; + /* + * qualified names handling is problematic, having a + * different prefix should be possible but DTDs don't + * allow to define the URI instead of the prefix :-( + */ + if (nameSpace == NULL) { + if (qualified < 0) + qualified = 0; + } else if (!xmlStrEqual(nameSpace->prefix, + attr->prefix)) { + if (qualified < 1) + qualified = 1; + } else + goto found; + } else { + /* + * We should allow applications to define namespaces + * for their application even if the DTD doesn't + * carry one, otherwise, basically we would always + * break. + */ + goto found; + } + } + attrib = attrib->next; + } + } + if (qualified == -1) { + if (attr->prefix == NULL) { + xmlErrValidNode(ctxt, elem, XML_DTD_MISSING_ATTRIBUTE, + "Element %s does not carry attribute %s\n", + elem->name, attr->name, NULL); + ret = 0; + } else { + xmlErrValidNode(ctxt, elem, XML_DTD_MISSING_ATTRIBUTE, + "Element %s does not carry attribute %s:%s\n", + elem->name, attr->prefix,attr->name); + ret = 0; + } + } else if (qualified == 0) { + xmlErrValidWarning(ctxt, elem, XML_DTD_NO_PREFIX, + "Element %s required attribute %s:%s has no prefix\n", + elem->name, attr->prefix, attr->name); + } else if (qualified == 1) { + xmlErrValidWarning(ctxt, elem, XML_DTD_DIFFERENT_PREFIX, + "Element %s required attribute %s:%s has different prefix\n", + elem->name, attr->prefix, attr->name); + } + } else if (attr->def == XML_ATTRIBUTE_FIXED) { + /* + * Special tests checking #FIXED namespace declarations + * have the right value since this is not done as an + * attribute checking + */ + if ((attr->prefix == NULL) && + (xmlStrEqual(attr->name, BAD_CAST "xmlns"))) { + xmlNsPtr ns; + + ns = elem->nsDef; + while (ns != NULL) { + if (ns->prefix == NULL) { + if (!xmlStrEqual(attr->defaultValue, ns->href)) { + xmlErrValidNode(ctxt, elem, + XML_DTD_ELEM_DEFAULT_NAMESPACE, + "Element %s namespace name for default namespace does not match the DTD\n", + elem->name, NULL, NULL); + ret = 0; + } + goto found; + } + ns = ns->next; + } + } else if (xmlStrEqual(attr->prefix, BAD_CAST "xmlns")) { + xmlNsPtr ns; + + ns = elem->nsDef; + while (ns != NULL) { + if (xmlStrEqual(attr->name, ns->prefix)) { + if (!xmlStrEqual(attr->defaultValue, ns->href)) { + xmlErrValidNode(ctxt, elem, XML_DTD_ELEM_NAMESPACE, + "Element %s namespace name for %s does not match the DTD\n", + elem->name, ns->prefix, NULL); + ret = 0; + } + goto found; + } + ns = ns->next; + } + } + } +found: + attr = attr->nexth; + } + return(ret); +} + +/** + * xmlValidateRoot: + * @ctxt: the validation context + * @doc: a document instance + * + * Try to validate a the root element + * basically it does the following check as described by the + * XML-1.0 recommendation: + * - [ VC: Root Element Type ] + * it doesn't try to recurse or apply other check to the element + * + * returns 1 if valid or 0 otherwise + */ + +int +xmlValidateRoot(xmlValidCtxtPtr ctxt, xmlDocPtr doc) { + xmlNodePtr root; + int ret; + + if (doc == NULL) return(0); + + root = xmlDocGetRootElement(doc); + if ((root == NULL) || (root->name == NULL)) { + xmlErrValid(ctxt, XML_DTD_NO_ROOT, + "no root element\n", NULL); + return(0); + } + + /* + * When doing post validation against a separate DTD, those may + * no internal subset has been generated + */ + if ((doc->intSubset != NULL) && + (doc->intSubset->name != NULL)) { + /* + * Check first the document root against the NQName + */ + if (!xmlStrEqual(doc->intSubset->name, root->name)) { + if ((root->ns != NULL) && (root->ns->prefix != NULL)) { + xmlChar fn[50]; + xmlChar *fullname; + + fullname = xmlBuildQName(root->name, root->ns->prefix, fn, 50); + if (fullname == NULL) { + xmlVErrMemory(ctxt, NULL); + return(0); + } + ret = xmlStrEqual(doc->intSubset->name, fullname); + if ((fullname != fn) && (fullname != root->name)) + xmlFree(fullname); + if (ret == 1) + goto name_ok; + } + if ((xmlStrEqual(doc->intSubset->name, BAD_CAST "HTML")) && + (xmlStrEqual(root->name, BAD_CAST "html"))) + goto name_ok; + xmlErrValidNode(ctxt, root, XML_DTD_ROOT_NAME, + "root and DTD name do not match '%s' and '%s'\n", + root->name, doc->intSubset->name, NULL); + return(0); + } + } +name_ok: + return(1); +} + + +/** + * xmlValidateElement: + * @ctxt: the validation context + * @doc: a document instance + * @elem: an element instance + * + * Try to validate the subtree under an element + * + * returns 1 if valid or 0 otherwise + */ + +int +xmlValidateElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr elem) { + xmlNodePtr child; + xmlAttrPtr attr; + xmlNsPtr ns; + const xmlChar *value; + int ret = 1; + + if (elem == NULL) return(0); + + /* + * XInclude elements were added after parsing in the infoset, + * they don't really mean anything validation wise. + */ + if ((elem->type == XML_XINCLUDE_START) || + (elem->type == XML_XINCLUDE_END)) + return(1); + + CHECK_DTD; + + /* + * Entities references have to be handled separately + */ + if (elem->type == XML_ENTITY_REF_NODE) { + return(1); + } + + ret &= xmlValidateOneElement(ctxt, doc, elem); + if (elem->type == XML_ELEMENT_NODE) { + attr = elem->properties; + while (attr != NULL) { + value = xmlNodeListGetString(doc, attr->children, 0); + ret &= xmlValidateOneAttribute(ctxt, doc, elem, attr, value); + if (value != NULL) + xmlFree((char *)value); + attr= attr->next; + } + ns = elem->nsDef; + while (ns != NULL) { + if (elem->ns == NULL) + ret &= xmlValidateOneNamespace(ctxt, doc, elem, NULL, + ns, ns->href); + else + ret &= xmlValidateOneNamespace(ctxt, doc, elem, + elem->ns->prefix, ns, ns->href); + ns = ns->next; + } + } + child = elem->children; + while (child != NULL) { + ret &= xmlValidateElement(ctxt, doc, child); + child = child->next; + } + + return(ret); +} + +/** + * xmlValidateRef: + * @ref: A reference to be validated + * @ctxt: Validation context + * @name: Name of ID we are searching for + * + */ +static void +xmlValidateRef(xmlRefPtr ref, xmlValidCtxtPtr ctxt, + const xmlChar *name) { + xmlAttrPtr id; + xmlAttrPtr attr; + + if (ref == NULL) + return; + if ((ref->attr == NULL) && (ref->name == NULL)) + return; + attr = ref->attr; + if (attr == NULL) { + xmlChar *dup, *str = NULL, *cur, save; + + dup = xmlStrdup(name); + if (dup == NULL) { + ctxt->valid = 0; + return; + } + cur = dup; + while (*cur != 0) { + str = cur; + while ((*cur != 0) && (!IS_BLANK_CH(*cur))) cur++; + save = *cur; + *cur = 0; + id = xmlGetID(ctxt->doc, str); + if (id == NULL) { + xmlErrValidNodeNr(ctxt, NULL, XML_DTD_UNKNOWN_ID, + "attribute %s line %d references an unknown ID \"%s\"\n", + ref->name, ref->lineno, str); + ctxt->valid = 0; + } + if (save == 0) + break; + *cur = save; + while (IS_BLANK_CH(*cur)) cur++; + } + xmlFree(dup); + } else if (attr->atype == XML_ATTRIBUTE_IDREF) { + id = xmlGetID(ctxt->doc, name); + if (id == NULL) { + xmlErrValidNode(ctxt, attr->parent, XML_DTD_UNKNOWN_ID, + "IDREF attribute %s references an unknown ID \"%s\"\n", + attr->name, name, NULL); + ctxt->valid = 0; + } + } else if (attr->atype == XML_ATTRIBUTE_IDREFS) { + xmlChar *dup, *str = NULL, *cur, save; + + dup = xmlStrdup(name); + if (dup == NULL) { + xmlVErrMemory(ctxt, "IDREFS split"); + ctxt->valid = 0; + return; + } + cur = dup; + while (*cur != 0) { + str = cur; + while ((*cur != 0) && (!IS_BLANK_CH(*cur))) cur++; + save = *cur; + *cur = 0; + id = xmlGetID(ctxt->doc, str); + if (id == NULL) { + xmlErrValidNode(ctxt, attr->parent, XML_DTD_UNKNOWN_ID, + "IDREFS attribute %s references an unknown ID \"%s\"\n", + attr->name, str, NULL); + ctxt->valid = 0; + } + if (save == 0) + break; + *cur = save; + while (IS_BLANK_CH(*cur)) cur++; + } + xmlFree(dup); + } +} + +/** + * xmlWalkValidateList: + * @data: Contents of current link + * @user: Value supplied by the user + * + * Returns 0 to abort the walk or 1 to continue + */ +static int +xmlWalkValidateList(const void *data, const void *user) +{ + xmlValidateMemoPtr memo = (xmlValidateMemoPtr)user; + xmlValidateRef((xmlRefPtr)data, memo->ctxt, memo->name); + return 1; +} + +/** + * xmlValidateCheckRefCallback: + * @ref_list: List of references + * @ctxt: Validation context + * @name: Name of ID we are searching for + * + */ +static void +xmlValidateCheckRefCallback(xmlListPtr ref_list, xmlValidCtxtPtr ctxt, + const xmlChar *name) { + xmlValidateMemo memo; + + if (ref_list == NULL) + return; + memo.ctxt = ctxt; + memo.name = name; + + xmlListWalk(ref_list, xmlWalkValidateList, &memo); + +} + +/** + * xmlValidateDocumentFinal: + * @ctxt: the validation context + * @doc: a document instance + * + * Does the final step for the document validation once all the + * incremental validation steps have been completed + * + * basically it does the following checks described by the XML Rec + * + * Check all the IDREF/IDREFS attributes definition for validity + * + * returns 1 if valid or 0 otherwise + */ + +int +xmlValidateDocumentFinal(xmlValidCtxtPtr ctxt, xmlDocPtr doc) { + xmlRefTablePtr table; + + if (ctxt == NULL) + return(0); + if (doc == NULL) { + xmlErrValid(ctxt, XML_DTD_NO_DOC, + "xmlValidateDocumentFinal: doc == NULL\n", NULL); + return(0); + } + + /* + * Check all the NOTATION/NOTATIONS attributes + */ + /* + * Check all the ENTITY/ENTITIES attributes definition for validity + */ + /* + * Check all the IDREF/IDREFS attributes definition for validity + */ + table = (xmlRefTablePtr) doc->refs; + ctxt->doc = doc; + ctxt->valid = 1; + xmlHashScan(table, (xmlHashScanner) xmlValidateCheckRefCallback, ctxt); + return(ctxt->valid); +} + +/** + * xmlValidateDtd: + * @ctxt: the validation context + * @doc: a document instance + * @dtd: a dtd instance + * + * Try to validate the document against the dtd instance + * + * Basically it does check all the definitions in the DtD. + * Note the the internal subset (if present) is de-coupled + * (i.e. not used), which could give problems if ID or IDREF + * is present. + * + * returns 1 if valid or 0 otherwise + */ + +int +xmlValidateDtd(xmlValidCtxtPtr ctxt, xmlDocPtr doc, xmlDtdPtr dtd) { + int ret; + xmlDtdPtr oldExt, oldInt; + xmlNodePtr root; + + if (dtd == NULL) return(0); + if (doc == NULL) return(0); + oldExt = doc->extSubset; + oldInt = doc->intSubset; + doc->extSubset = dtd; + doc->intSubset = NULL; + ret = xmlValidateRoot(ctxt, doc); + if (ret == 0) { + doc->extSubset = oldExt; + doc->intSubset = oldInt; + return(ret); + } + if (doc->ids != NULL) { + xmlFreeIDTable(doc->ids); + doc->ids = NULL; + } + if (doc->refs != NULL) { + xmlFreeRefTable(doc->refs); + doc->refs = NULL; + } + root = xmlDocGetRootElement(doc); + ret = xmlValidateElement(ctxt, doc, root); + ret &= xmlValidateDocumentFinal(ctxt, doc); + doc->extSubset = oldExt; + doc->intSubset = oldInt; + return(ret); +} + +static void +xmlValidateNotationCallback(xmlEntityPtr cur, xmlValidCtxtPtr ctxt, + const xmlChar *name ATTRIBUTE_UNUSED) { + if (cur == NULL) + return; + if (cur->etype == XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) { + xmlChar *notation = cur->content; + + if (notation != NULL) { + int ret; + + ret = xmlValidateNotationUse(ctxt, cur->doc, notation); + if (ret != 1) { + ctxt->valid = 0; + } + } + } +} + +static void +xmlValidateAttributeCallback(xmlAttributePtr cur, xmlValidCtxtPtr ctxt, + const xmlChar *name ATTRIBUTE_UNUSED) { + int ret; + xmlDocPtr doc; + xmlElementPtr elem = NULL; + + if (cur == NULL) + return; + switch (cur->atype) { + case XML_ATTRIBUTE_CDATA: + case XML_ATTRIBUTE_ID: + case XML_ATTRIBUTE_IDREF : + case XML_ATTRIBUTE_IDREFS: + case XML_ATTRIBUTE_NMTOKEN: + case XML_ATTRIBUTE_NMTOKENS: + case XML_ATTRIBUTE_ENUMERATION: + break; + case XML_ATTRIBUTE_ENTITY: + case XML_ATTRIBUTE_ENTITIES: + case XML_ATTRIBUTE_NOTATION: + if (cur->defaultValue != NULL) { + + ret = xmlValidateAttributeValue2(ctxt, ctxt->doc, cur->name, + cur->atype, cur->defaultValue); + if ((ret == 0) && (ctxt->valid == 1)) + ctxt->valid = 0; + } + if (cur->tree != NULL) { + xmlEnumerationPtr tree = cur->tree; + while (tree != NULL) { + ret = xmlValidateAttributeValue2(ctxt, ctxt->doc, + cur->name, cur->atype, tree->name); + if ((ret == 0) && (ctxt->valid == 1)) + ctxt->valid = 0; + tree = tree->next; + } + } + } + if (cur->atype == XML_ATTRIBUTE_NOTATION) { + doc = cur->doc; + if (cur->elem == NULL) { + xmlErrValid(ctxt, XML_ERR_INTERNAL_ERROR, + "xmlValidateAttributeCallback(%s): internal error\n", + (const char *) cur->name); + return; + } + + if (doc != NULL) + elem = xmlGetDtdElementDesc(doc->intSubset, cur->elem); + if ((elem == NULL) && (doc != NULL)) + elem = xmlGetDtdElementDesc(doc->extSubset, cur->elem); + if ((elem == NULL) && (cur->parent != NULL) && + (cur->parent->type == XML_DTD_NODE)) + elem = xmlGetDtdElementDesc((xmlDtdPtr) cur->parent, cur->elem); + if (elem == NULL) { + xmlErrValidNode(ctxt, NULL, XML_DTD_UNKNOWN_ELEM, + "attribute %s: could not find decl for element %s\n", + cur->name, cur->elem, NULL); + return; + } + if (elem->etype == XML_ELEMENT_TYPE_EMPTY) { + xmlErrValidNode(ctxt, NULL, XML_DTD_EMPTY_NOTATION, + "NOTATION attribute %s declared for EMPTY element %s\n", + cur->name, cur->elem, NULL); + ctxt->valid = 0; + } + } +} + +/** + * xmlValidateDtdFinal: + * @ctxt: the validation context + * @doc: a document instance + * + * Does the final step for the dtds validation once all the + * subsets have been parsed + * + * basically it does the following checks described by the XML Rec + * - check that ENTITY and ENTITIES type attributes default or + * possible values matches one of the defined entities. + * - check that NOTATION type attributes default or + * possible values matches one of the defined notations. + * + * returns 1 if valid or 0 if invalid and -1 if not well-formed + */ + +int +xmlValidateDtdFinal(xmlValidCtxtPtr ctxt, xmlDocPtr doc) { + xmlDtdPtr dtd; + xmlAttributeTablePtr table; + xmlEntitiesTablePtr entities; + + if (doc == NULL) return(0); + if ((doc->intSubset == NULL) && (doc->extSubset == NULL)) + return(0); + ctxt->doc = doc; + ctxt->valid = 1; + dtd = doc->intSubset; + if ((dtd != NULL) && (dtd->attributes != NULL)) { + table = (xmlAttributeTablePtr) dtd->attributes; + xmlHashScan(table, (xmlHashScanner) xmlValidateAttributeCallback, ctxt); + } + if ((dtd != NULL) && (dtd->entities != NULL)) { + entities = (xmlEntitiesTablePtr) dtd->entities; + xmlHashScan(entities, (xmlHashScanner) xmlValidateNotationCallback, + ctxt); + } + dtd = doc->extSubset; + if ((dtd != NULL) && (dtd->attributes != NULL)) { + table = (xmlAttributeTablePtr) dtd->attributes; + xmlHashScan(table, (xmlHashScanner) xmlValidateAttributeCallback, ctxt); + } + if ((dtd != NULL) && (dtd->entities != NULL)) { + entities = (xmlEntitiesTablePtr) dtd->entities; + xmlHashScan(entities, (xmlHashScanner) xmlValidateNotationCallback, + ctxt); + } + return(ctxt->valid); +} + +/** + * xmlValidateDocument: + * @ctxt: the validation context + * @doc: a document instance + * + * Try to validate the document instance + * + * basically it does the all the checks described by the XML Rec + * i.e. validates the internal and external subset (if present) + * and validate the document tree. + * + * returns 1 if valid or 0 otherwise + */ + +int +xmlValidateDocument(xmlValidCtxtPtr ctxt, xmlDocPtr doc) { + int ret; + xmlNodePtr root; + + if (doc == NULL) + return(0); + if ((doc->intSubset == NULL) && (doc->extSubset == NULL)) { + xmlErrValid(ctxt, XML_DTD_NO_DTD, + "no DTD found!\n", NULL); + return(0); + } + if ((doc->intSubset != NULL) && ((doc->intSubset->SystemID != NULL) || + (doc->intSubset->ExternalID != NULL)) && (doc->extSubset == NULL)) { + xmlChar *sysID; + if (doc->intSubset->SystemID != NULL) { + sysID = xmlBuildURI(doc->intSubset->SystemID, + doc->URL); + if (sysID == NULL) { + xmlErrValid(ctxt, XML_DTD_LOAD_ERROR, + "Could not build URI for external subset \"%s\"\n", + (const char *) doc->intSubset->SystemID); + return 0; + } + } else + sysID = NULL; + doc->extSubset = xmlParseDTD(doc->intSubset->ExternalID, + (const xmlChar *)sysID); + if (sysID != NULL) + xmlFree(sysID); + if (doc->extSubset == NULL) { + if (doc->intSubset->SystemID != NULL) { + xmlErrValid(ctxt, XML_DTD_LOAD_ERROR, + "Could not load the external subset \"%s\"\n", + (const char *) doc->intSubset->SystemID); + } else { + xmlErrValid(ctxt, XML_DTD_LOAD_ERROR, + "Could not load the external subset \"%s\"\n", + (const char *) doc->intSubset->ExternalID); + } + return(0); + } + } + + if (doc->ids != NULL) { + xmlFreeIDTable(doc->ids); + doc->ids = NULL; + } + if (doc->refs != NULL) { + xmlFreeRefTable(doc->refs); + doc->refs = NULL; + } + ret = xmlValidateDtdFinal(ctxt, doc); + if (!xmlValidateRoot(ctxt, doc)) return(0); + + root = xmlDocGetRootElement(doc); + ret &= xmlValidateElement(ctxt, doc, root); + ret &= xmlValidateDocumentFinal(ctxt, doc); + return(ret); +} + +/************************************************************************ + * * + * Routines for dynamic validation editing * + * * + ************************************************************************/ + +/** + * xmlValidGetPotentialChildren: + * @ctree: an element content tree + * @names: an array to store the list of child names + * @len: a pointer to the number of element in the list + * @max: the size of the array + * + * Build/extend a list of potential children allowed by the content tree + * + * returns the number of element in the list, or -1 in case of error. + */ + +int +xmlValidGetPotentialChildren(xmlElementContent *ctree, + const xmlChar **names, + int *len, int max) { + int i; + + if ((ctree == NULL) || (names == NULL) || (len == NULL)) + return(-1); + if (*len >= max) return(*len); + + switch (ctree->type) { + case XML_ELEMENT_CONTENT_PCDATA: + for (i = 0; i < *len;i++) + if (xmlStrEqual(BAD_CAST "#PCDATA", names[i])) return(*len); + names[(*len)++] = BAD_CAST "#PCDATA"; + break; + case XML_ELEMENT_CONTENT_ELEMENT: + for (i = 0; i < *len;i++) + if (xmlStrEqual(ctree->name, names[i])) return(*len); + names[(*len)++] = ctree->name; + break; + case XML_ELEMENT_CONTENT_SEQ: + xmlValidGetPotentialChildren(ctree->c1, names, len, max); + xmlValidGetPotentialChildren(ctree->c2, names, len, max); + break; + case XML_ELEMENT_CONTENT_OR: + xmlValidGetPotentialChildren(ctree->c1, names, len, max); + xmlValidGetPotentialChildren(ctree->c2, names, len, max); + break; + } + + return(*len); +} + +/* + * Dummy function to suppress messages while we try out valid elements + */ +static void XMLCDECL xmlNoValidityErr(void *ctx ATTRIBUTE_UNUSED, + const char *msg ATTRIBUTE_UNUSED, ...) { + return; +} + +/** + * xmlValidGetValidElements: + * @prev: an element to insert after + * @next: an element to insert next + * @names: an array to store the list of child names + * @max: the size of the array + * + * This function returns the list of authorized children to insert + * within an existing tree while respecting the validity constraints + * forced by the Dtd. The insertion point is defined using @prev and + * @next in the following ways: + * to insert before 'node': xmlValidGetValidElements(node->prev, node, ... + * to insert next 'node': xmlValidGetValidElements(node, node->next, ... + * to replace 'node': xmlValidGetValidElements(node->prev, node->next, ... + * to prepend a child to 'node': xmlValidGetValidElements(NULL, node->childs, + * to append a child to 'node': xmlValidGetValidElements(node->last, NULL, ... + * + * pointers to the element names are inserted at the beginning of the array + * and do not need to be freed. + * + * returns the number of element in the list, or -1 in case of error. If + * the function returns the value @max the caller is invited to grow the + * receiving array and retry. + */ + +int +xmlValidGetValidElements(xmlNode *prev, xmlNode *next, const xmlChar **names, + int max) { + xmlValidCtxt vctxt; + int nb_valid_elements = 0; + const xmlChar *elements[256]; + int nb_elements = 0, i; + const xmlChar *name; + + xmlNode *ref_node; + xmlNode *parent; + xmlNode *test_node; + + xmlNode *prev_next; + xmlNode *next_prev; + xmlNode *parent_childs; + xmlNode *parent_last; + + xmlElement *element_desc; + + if (prev == NULL && next == NULL) + return(-1); + + if (names == NULL) return(-1); + if (max <= 0) return(-1); + + memset(&vctxt, 0, sizeof (xmlValidCtxt)); + vctxt.error = xmlNoValidityErr; /* this suppresses err/warn output */ + + nb_valid_elements = 0; + ref_node = prev ? prev : next; + parent = ref_node->parent; + + /* + * Retrieves the parent element declaration + */ + element_desc = xmlGetDtdElementDesc(parent->doc->intSubset, + parent->name); + if ((element_desc == NULL) && (parent->doc->extSubset != NULL)) + element_desc = xmlGetDtdElementDesc(parent->doc->extSubset, + parent->name); + if (element_desc == NULL) return(-1); + + /* + * Do a backup of the current tree structure + */ + prev_next = prev ? prev->next : NULL; + next_prev = next ? next->prev : NULL; + parent_childs = parent->children; + parent_last = parent->last; + + /* + * Creates a dummy node and insert it into the tree + */ + test_node = xmlNewDocNode (ref_node->doc, NULL, BAD_CAST "", NULL); + test_node->parent = parent; + test_node->prev = prev; + test_node->next = next; + name = test_node->name; + + if (prev) prev->next = test_node; + else parent->children = test_node; + + if (next) next->prev = test_node; + else parent->last = test_node; + + /* + * Insert each potential child node and check if the parent is + * still valid + */ + nb_elements = xmlValidGetPotentialChildren(element_desc->content, + elements, &nb_elements, 256); + + for (i = 0;i < nb_elements;i++) { + test_node->name = elements[i]; + if (xmlValidateOneElement(&vctxt, parent->doc, parent)) { + int j; + + for (j = 0; j < nb_valid_elements;j++) + if (xmlStrEqual(elements[i], names[j])) break; + names[nb_valid_elements++] = elements[i]; + if (nb_valid_elements >= max) break; + } + } + + /* + * Restore the tree structure + */ + if (prev) prev->next = prev_next; + if (next) next->prev = next_prev; + parent->children = parent_childs; + parent->last = parent_last; + + /* + * Free up the dummy node + */ + test_node->name = name; + xmlFreeNode(test_node); + + return(nb_valid_elements); +} +#endif /* LIBXML_VALID_ENABLED */ + +#define bottom_valid +#include "elfgcchack.h" diff --git a/gettext-tools/gnulib-lib/libxml/valid.in.h b/gettext-tools/gnulib-lib/libxml/valid.in.h new file mode 100644 index 0000000..7492d28 --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/valid.in.h @@ -0,0 +1,458 @@ +/* + * Summary: The DTD validation + * Description: API for the DTD handling and the validity checking + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + + +#ifndef __XML_VALID_H__ +#define __XML_VALID_H__ + +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Validation state added for non-determinist content model. + */ +typedef struct _xmlValidState xmlValidState; +typedef xmlValidState *xmlValidStatePtr; + +/** + * xmlValidityErrorFunc: + * @ctx: usually an xmlValidCtxtPtr to a validity error context, + * but comes from ctxt->userData (which normally contains such + * a pointer); ctxt->userData can be changed by the user. + * @msg: the string to format *printf like vararg + * @...: remaining arguments to the format + * + * Callback called when a validity error is found. This is a message + * oriented function similar to an *printf function. + */ +typedef void (XMLCDECL *xmlValidityErrorFunc) (void *ctx, + const char *msg, + ...); + +/** + * xmlValidityWarningFunc: + * @ctx: usually an xmlValidCtxtPtr to a validity error context, + * but comes from ctxt->userData (which normally contains such + * a pointer); ctxt->userData can be changed by the user. + * @msg: the string to format *printf like vararg + * @...: remaining arguments to the format + * + * Callback called when a validity warning is found. This is a message + * oriented function similar to an *printf function. + */ +typedef void (XMLCDECL *xmlValidityWarningFunc) (void *ctx, + const char *msg, + ...); + +#ifdef IN_LIBXML +/** + * XML_CTXT_FINISH_DTD_0: + * + * Special value for finishDtd field when embedded in an xmlParserCtxt + */ +#define XML_CTXT_FINISH_DTD_0 0xabcd1234 +/** + * XML_CTXT_FINISH_DTD_1: + * + * Special value for finishDtd field when embedded in an xmlParserCtxt + */ +#define XML_CTXT_FINISH_DTD_1 0xabcd1235 +#endif + +/* + * xmlValidCtxt: + * An xmlValidCtxt is used for error reporting when validating. + */ +typedef struct _xmlValidCtxt xmlValidCtxt; +typedef xmlValidCtxt *xmlValidCtxtPtr; +struct _xmlValidCtxt { + void *userData; /* user specific data block */ + xmlValidityErrorFunc error; /* the callback in case of errors */ + xmlValidityWarningFunc warning; /* the callback in case of warning */ + + /* Node analysis stack used when validating within entities */ + xmlNodePtr node; /* Current parsed Node */ + int nodeNr; /* Depth of the parsing stack */ + int nodeMax; /* Max depth of the parsing stack */ + xmlNodePtr *nodeTab; /* array of nodes */ + + unsigned int finishDtd; /* finished validating the Dtd ? */ + xmlDocPtr doc; /* the document */ + int valid; /* temporary validity check result */ + + /* state state used for non-determinist content validation */ + xmlValidState *vstate; /* current state */ + int vstateNr; /* Depth of the validation stack */ + int vstateMax; /* Max depth of the validation stack */ + xmlValidState *vstateTab; /* array of validation states */ + +#ifdef LIBXML_REGEXP_ENABLED + xmlAutomataPtr am; /* the automata */ + xmlAutomataStatePtr state; /* used to build the automata */ +#else + void *am; + void *state; +#endif +}; + +/* + * ALL notation declarations are stored in a table. + * There is one table per DTD. + */ + +typedef struct _xmlHashTable xmlNotationTable; +typedef xmlNotationTable *xmlNotationTablePtr; + +/* + * ALL element declarations are stored in a table. + * There is one table per DTD. + */ + +typedef struct _xmlHashTable xmlElementTable; +typedef xmlElementTable *xmlElementTablePtr; + +/* + * ALL attribute declarations are stored in a table. + * There is one table per DTD. + */ + +typedef struct _xmlHashTable xmlAttributeTable; +typedef xmlAttributeTable *xmlAttributeTablePtr; + +/* + * ALL IDs attributes are stored in a table. + * There is one table per document. + */ + +typedef struct _xmlHashTable xmlIDTable; +typedef xmlIDTable *xmlIDTablePtr; + +/* + * ALL Refs attributes are stored in a table. + * There is one table per document. + */ + +typedef struct _xmlHashTable xmlRefTable; +typedef xmlRefTable *xmlRefTablePtr; + +/* Notation */ +XMLPUBFUN xmlNotationPtr XMLCALL + xmlAddNotationDecl (xmlValidCtxtPtr ctxt, + xmlDtdPtr dtd, + const xmlChar *name, + const xmlChar *PublicID, + const xmlChar *SystemID); +#ifdef LIBXML_TREE_ENABLED +XMLPUBFUN xmlNotationTablePtr XMLCALL + xmlCopyNotationTable (xmlNotationTablePtr table); +#endif /* LIBXML_TREE_ENABLED */ +XMLPUBFUN void XMLCALL + xmlFreeNotationTable (xmlNotationTablePtr table); +#ifdef LIBXML_OUTPUT_ENABLED +XMLPUBFUN void XMLCALL + xmlDumpNotationDecl (xmlBufferPtr buf, + xmlNotationPtr nota); +XMLPUBFUN void XMLCALL + xmlDumpNotationTable (xmlBufferPtr buf, + xmlNotationTablePtr table); +#endif /* LIBXML_OUTPUT_ENABLED */ + +/* Element Content */ +/* the non Doc version are being deprecated */ +XMLPUBFUN xmlElementContentPtr XMLCALL + xmlNewElementContent (const xmlChar *name, + xmlElementContentType type); +XMLPUBFUN xmlElementContentPtr XMLCALL + xmlCopyElementContent (xmlElementContentPtr content); +XMLPUBFUN void XMLCALL + xmlFreeElementContent (xmlElementContentPtr cur); +/* the new versions with doc argument */ +XMLPUBFUN xmlElementContentPtr XMLCALL + xmlNewDocElementContent (xmlDocPtr doc, + const xmlChar *name, + xmlElementContentType type); +XMLPUBFUN xmlElementContentPtr XMLCALL + xmlCopyDocElementContent(xmlDocPtr doc, + xmlElementContentPtr content); +XMLPUBFUN void XMLCALL + xmlFreeDocElementContent(xmlDocPtr doc, + xmlElementContentPtr cur); +XMLPUBFUN void XMLCALL + xmlSnprintfElementContent(char *buf, + int size, + xmlElementContentPtr content, + int englob); +#ifdef LIBXML_OUTPUT_ENABLED +/* DEPRECATED */ +XMLPUBFUN void XMLCALL + xmlSprintfElementContent(char *buf, + xmlElementContentPtr content, + int englob); +#endif /* LIBXML_OUTPUT_ENABLED */ +/* DEPRECATED */ + +/* Element */ +XMLPUBFUN xmlElementPtr XMLCALL + xmlAddElementDecl (xmlValidCtxtPtr ctxt, + xmlDtdPtr dtd, + const xmlChar *name, + xmlElementTypeVal type, + xmlElementContentPtr content); +#ifdef LIBXML_TREE_ENABLED +XMLPUBFUN xmlElementTablePtr XMLCALL + xmlCopyElementTable (xmlElementTablePtr table); +#endif /* LIBXML_TREE_ENABLED */ +XMLPUBFUN void XMLCALL + xmlFreeElementTable (xmlElementTablePtr table); +#ifdef LIBXML_OUTPUT_ENABLED +XMLPUBFUN void XMLCALL + xmlDumpElementTable (xmlBufferPtr buf, + xmlElementTablePtr table); +XMLPUBFUN void XMLCALL + xmlDumpElementDecl (xmlBufferPtr buf, + xmlElementPtr elem); +#endif /* LIBXML_OUTPUT_ENABLED */ + +/* Enumeration */ +XMLPUBFUN xmlEnumerationPtr XMLCALL + xmlCreateEnumeration (const xmlChar *name); +XMLPUBFUN void XMLCALL + xmlFreeEnumeration (xmlEnumerationPtr cur); +#ifdef LIBXML_TREE_ENABLED +XMLPUBFUN xmlEnumerationPtr XMLCALL + xmlCopyEnumeration (xmlEnumerationPtr cur); +#endif /* LIBXML_TREE_ENABLED */ + +/* Attribute */ +XMLPUBFUN xmlAttributePtr XMLCALL + xmlAddAttributeDecl (xmlValidCtxtPtr ctxt, + xmlDtdPtr dtd, + const xmlChar *elem, + const xmlChar *name, + const xmlChar *ns, + xmlAttributeType type, + xmlAttributeDefault def, + const xmlChar *defaultValue, + xmlEnumerationPtr tree); +#ifdef LIBXML_TREE_ENABLED +XMLPUBFUN xmlAttributeTablePtr XMLCALL + xmlCopyAttributeTable (xmlAttributeTablePtr table); +#endif /* LIBXML_TREE_ENABLED */ +XMLPUBFUN void XMLCALL + xmlFreeAttributeTable (xmlAttributeTablePtr table); +#ifdef LIBXML_OUTPUT_ENABLED +XMLPUBFUN void XMLCALL + xmlDumpAttributeTable (xmlBufferPtr buf, + xmlAttributeTablePtr table); +XMLPUBFUN void XMLCALL + xmlDumpAttributeDecl (xmlBufferPtr buf, + xmlAttributePtr attr); +#endif /* LIBXML_OUTPUT_ENABLED */ + +/* IDs */ +XMLPUBFUN xmlIDPtr XMLCALL + xmlAddID (xmlValidCtxtPtr ctxt, + xmlDocPtr doc, + const xmlChar *value, + xmlAttrPtr attr); +XMLPUBFUN void XMLCALL + xmlFreeIDTable (xmlIDTablePtr table); +XMLPUBFUN xmlAttrPtr XMLCALL + xmlGetID (xmlDocPtr doc, + const xmlChar *ID); +XMLPUBFUN int XMLCALL + xmlIsID (xmlDocPtr doc, + xmlNodePtr elem, + xmlAttrPtr attr); +XMLPUBFUN int XMLCALL + xmlRemoveID (xmlDocPtr doc, + xmlAttrPtr attr); + +/* IDREFs */ +XMLPUBFUN xmlRefPtr XMLCALL + xmlAddRef (xmlValidCtxtPtr ctxt, + xmlDocPtr doc, + const xmlChar *value, + xmlAttrPtr attr); +XMLPUBFUN void XMLCALL + xmlFreeRefTable (xmlRefTablePtr table); +XMLPUBFUN int XMLCALL + xmlIsRef (xmlDocPtr doc, + xmlNodePtr elem, + xmlAttrPtr attr); +XMLPUBFUN int XMLCALL + xmlRemoveRef (xmlDocPtr doc, + xmlAttrPtr attr); +XMLPUBFUN xmlListPtr XMLCALL + xmlGetRefs (xmlDocPtr doc, + const xmlChar *ID); + +/** + * The public function calls related to validity checking. + */ +#ifdef LIBXML_VALID_ENABLED +/* Allocate/Release Validation Contexts */ +XMLPUBFUN xmlValidCtxtPtr XMLCALL + xmlNewValidCtxt(void); +XMLPUBFUN void XMLCALL + xmlFreeValidCtxt(xmlValidCtxtPtr); + +XMLPUBFUN int XMLCALL + xmlValidateRoot (xmlValidCtxtPtr ctxt, + xmlDocPtr doc); +XMLPUBFUN int XMLCALL + xmlValidateElementDecl (xmlValidCtxtPtr ctxt, + xmlDocPtr doc, + xmlElementPtr elem); +XMLPUBFUN xmlChar * XMLCALL + xmlValidNormalizeAttributeValue(xmlDocPtr doc, + xmlNodePtr elem, + const xmlChar *name, + const xmlChar *value); +XMLPUBFUN xmlChar * XMLCALL + xmlValidCtxtNormalizeAttributeValue(xmlValidCtxtPtr ctxt, + xmlDocPtr doc, + xmlNodePtr elem, + const xmlChar *name, + const xmlChar *value); +XMLPUBFUN int XMLCALL + xmlValidateAttributeDecl(xmlValidCtxtPtr ctxt, + xmlDocPtr doc, + xmlAttributePtr attr); +XMLPUBFUN int XMLCALL + xmlValidateAttributeValue(xmlAttributeType type, + const xmlChar *value); +XMLPUBFUN int XMLCALL + xmlValidateNotationDecl (xmlValidCtxtPtr ctxt, + xmlDocPtr doc, + xmlNotationPtr nota); +XMLPUBFUN int XMLCALL + xmlValidateDtd (xmlValidCtxtPtr ctxt, + xmlDocPtr doc, + xmlDtdPtr dtd); +XMLPUBFUN int XMLCALL + xmlValidateDtdFinal (xmlValidCtxtPtr ctxt, + xmlDocPtr doc); +XMLPUBFUN int XMLCALL + xmlValidateDocument (xmlValidCtxtPtr ctxt, + xmlDocPtr doc); +XMLPUBFUN int XMLCALL + xmlValidateElement (xmlValidCtxtPtr ctxt, + xmlDocPtr doc, + xmlNodePtr elem); +XMLPUBFUN int XMLCALL + xmlValidateOneElement (xmlValidCtxtPtr ctxt, + xmlDocPtr doc, + xmlNodePtr elem); +XMLPUBFUN int XMLCALL + xmlValidateOneAttribute (xmlValidCtxtPtr ctxt, + xmlDocPtr doc, + xmlNodePtr elem, + xmlAttrPtr attr, + const xmlChar *value); +XMLPUBFUN int XMLCALL + xmlValidateOneNamespace (xmlValidCtxtPtr ctxt, + xmlDocPtr doc, + xmlNodePtr elem, + const xmlChar *prefix, + xmlNsPtr ns, + const xmlChar *value); +XMLPUBFUN int XMLCALL + xmlValidateDocumentFinal(xmlValidCtxtPtr ctxt, + xmlDocPtr doc); +#endif /* LIBXML_VALID_ENABLED */ + +#if defined(LIBXML_VALID_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) +XMLPUBFUN int XMLCALL + xmlValidateNotationUse (xmlValidCtxtPtr ctxt, + xmlDocPtr doc, + const xmlChar *notationName); +#endif /* LIBXML_VALID_ENABLED or LIBXML_SCHEMAS_ENABLED */ + +XMLPUBFUN int XMLCALL + xmlIsMixedElement (xmlDocPtr doc, + const xmlChar *name); +XMLPUBFUN xmlAttributePtr XMLCALL + xmlGetDtdAttrDesc (xmlDtdPtr dtd, + const xmlChar *elem, + const xmlChar *name); +XMLPUBFUN xmlAttributePtr XMLCALL + xmlGetDtdQAttrDesc (xmlDtdPtr dtd, + const xmlChar *elem, + const xmlChar *name, + const xmlChar *prefix); +XMLPUBFUN xmlNotationPtr XMLCALL + xmlGetDtdNotationDesc (xmlDtdPtr dtd, + const xmlChar *name); +XMLPUBFUN xmlElementPtr XMLCALL + xmlGetDtdQElementDesc (xmlDtdPtr dtd, + const xmlChar *name, + const xmlChar *prefix); +XMLPUBFUN xmlElementPtr XMLCALL + xmlGetDtdElementDesc (xmlDtdPtr dtd, + const xmlChar *name); + +#ifdef LIBXML_VALID_ENABLED + +XMLPUBFUN int XMLCALL + xmlValidGetPotentialChildren(xmlElementContent *ctree, + const xmlChar **names, + int *len, + int max); + +XMLPUBFUN int XMLCALL + xmlValidGetValidElements(xmlNode *prev, + xmlNode *next, + const xmlChar **names, + int max); +XMLPUBFUN int XMLCALL + xmlValidateNameValue (const xmlChar *value); +XMLPUBFUN int XMLCALL + xmlValidateNamesValue (const xmlChar *value); +XMLPUBFUN int XMLCALL + xmlValidateNmtokenValue (const xmlChar *value); +XMLPUBFUN int XMLCALL + xmlValidateNmtokensValue(const xmlChar *value); + +#ifdef LIBXML_REGEXP_ENABLED +/* + * Validation based on the regexp support + */ +XMLPUBFUN int XMLCALL + xmlValidBuildContentModel(xmlValidCtxtPtr ctxt, + xmlElementPtr elem); + +XMLPUBFUN int XMLCALL + xmlValidatePushElement (xmlValidCtxtPtr ctxt, + xmlDocPtr doc, + xmlNodePtr elem, + const xmlChar *qname); +XMLPUBFUN int XMLCALL + xmlValidatePushCData (xmlValidCtxtPtr ctxt, + const xmlChar *data, + int len); +XMLPUBFUN int XMLCALL + xmlValidatePopElement (xmlValidCtxtPtr ctxt, + xmlDocPtr doc, + xmlNodePtr elem, + const xmlChar *qname); +#endif /* LIBXML_REGEXP_ENABLED */ +#endif /* LIBXML_VALID_ENABLED */ +#ifdef __cplusplus +} +#endif +#endif /* __XML_VALID_H__ */ diff --git a/gettext-tools/gnulib-lib/libxml/xinclude.c b/gettext-tools/gnulib-lib/libxml/xinclude.c new file mode 100644 index 0000000..c58bbcf --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/xinclude.c @@ -0,0 +1,2555 @@ +/* + * xinclude.c : Code to implement XInclude processing + * + * World Wide Web Consortium W3C Last Call Working Draft 10 November 2003 + * http://www.w3.org/TR/2003/WD-xinclude-20031110 + * + * See Copyright for the status of this software. + * + * daniel@veillard.com + */ + +#define IN_LIBXML +#include "libxml.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef LIBXML_XINCLUDE_ENABLED +#include + + +#define XINCLUDE_MAX_DEPTH 40 + +/* #define DEBUG_XINCLUDE */ +#ifdef DEBUG_XINCLUDE +#ifdef LIBXML_DEBUG_ENABLED +#include +#endif +#endif + +/************************************************************************ + * * + * XInclude context handling * + * * + ************************************************************************/ + +/* + * An XInclude context + */ +typedef xmlChar *xmlURL; + +typedef struct _xmlXIncludeRef xmlXIncludeRef; +typedef xmlXIncludeRef *xmlXIncludeRefPtr; +struct _xmlXIncludeRef { + xmlChar *URI; /* the fully resolved resource URL */ + xmlChar *fragment; /* the fragment in the URI */ + xmlDocPtr doc; /* the parsed document */ + xmlNodePtr ref; /* the node making the reference in the source */ + xmlNodePtr inc; /* the included copy */ + int xml; /* xml or txt */ + int count; /* how many refs use that specific doc */ + xmlXPathObjectPtr xptr; /* the xpointer if needed */ + int emptyFb; /* flag to show fallback empty */ +}; + +struct _xmlXIncludeCtxt { + xmlDocPtr doc; /* the source document */ + int incBase; /* the first include for this document */ + int incNr; /* number of includes */ + int incMax; /* size of includes tab */ + xmlXIncludeRefPtr *incTab; /* array of included references */ + + int txtNr; /* number of unparsed documents */ + int txtMax; /* size of unparsed documents tab */ + xmlNodePtr *txtTab; /* array of unparsed text nodes */ + xmlURL *txturlTab; /* array of unparsed text URLs */ + + xmlChar * url; /* the current URL processed */ + int urlNr; /* number of URLs stacked */ + int urlMax; /* size of URL stack */ + xmlChar * *urlTab; /* URL stack */ + + int nbErrors; /* the number of errors detected */ + int legacy; /* using XINCLUDE_OLD_NS */ + int parseFlags; /* the flags used for parsing XML documents */ + xmlChar * base; /* the current xml:base */ + + void *_private; /* application data */ +}; + +static int +xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr tree); + + +/************************************************************************ + * * + * XInclude error handler * + * * + ************************************************************************/ + +/** + * xmlXIncludeErrMemory: + * @extra: extra information + * + * Handle an out of memory condition + */ +static void +xmlXIncludeErrMemory(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node, + const char *extra) +{ + if (ctxt != NULL) + ctxt->nbErrors++; + __xmlRaiseError(NULL, NULL, NULL, ctxt, node, XML_FROM_XINCLUDE, + XML_ERR_NO_MEMORY, XML_ERR_ERROR, NULL, 0, + extra, NULL, NULL, 0, 0, + "Memory allocation failed : %s\n", extra); +} + +/** + * xmlXIncludeErr: + * @ctxt: the XInclude context + * @node: the context node + * @msg: the error message + * @extra: extra information + * + * Handle an XInclude error + */ +static void +xmlXIncludeErr(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node, int error, + const char *msg, const xmlChar *extra) +{ + if (ctxt != NULL) + ctxt->nbErrors++; + __xmlRaiseError(NULL, NULL, NULL, ctxt, node, XML_FROM_XINCLUDE, + error, XML_ERR_ERROR, NULL, 0, + (const char *) extra, NULL, NULL, 0, 0, + msg, (const char *) extra); +} + +#if 0 +/** + * xmlXIncludeWarn: + * @ctxt: the XInclude context + * @node: the context node + * @msg: the error message + * @extra: extra information + * + * Emit an XInclude warning. + */ +static void +xmlXIncludeWarn(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node, int error, + const char *msg, const xmlChar *extra) +{ + __xmlRaiseError(NULL, NULL, NULL, ctxt, node, XML_FROM_XINCLUDE, + error, XML_ERR_WARNING, NULL, 0, + (const char *) extra, NULL, NULL, 0, 0, + msg, (const char *) extra); +} +#endif + +/** + * xmlXIncludeGetProp: + * @ctxt: the XInclude context + * @cur: the node + * @name: the attribute name + * + * Get an XInclude attribute + * + * Returns the value (to be freed) or NULL if not found + */ +static xmlChar * +xmlXIncludeGetProp(xmlXIncludeCtxtPtr ctxt, xmlNodePtr cur, + const xmlChar *name) { + xmlChar *ret; + + ret = xmlGetNsProp(cur, XINCLUDE_NS, name); + if (ret != NULL) + return(ret); + if (ctxt->legacy != 0) { + ret = xmlGetNsProp(cur, XINCLUDE_OLD_NS, name); + if (ret != NULL) + return(ret); + } + ret = xmlGetProp(cur, name); + return(ret); +} +/** + * xmlXIncludeFreeRef: + * @ref: the XInclude reference + * + * Free an XInclude reference + */ +static void +xmlXIncludeFreeRef(xmlXIncludeRefPtr ref) { + if (ref == NULL) + return; +#ifdef DEBUG_XINCLUDE + xmlGenericError(xmlGenericErrorContext, "Freeing ref\n"); +#endif + if (ref->doc != NULL) { +#ifdef DEBUG_XINCLUDE + xmlGenericError(xmlGenericErrorContext, "Freeing doc %s\n", ref->URI); +#endif + xmlFreeDoc(ref->doc); + } + if (ref->URI != NULL) + xmlFree(ref->URI); + if (ref->fragment != NULL) + xmlFree(ref->fragment); + if (ref->xptr != NULL) + xmlXPathFreeObject(ref->xptr); + xmlFree(ref); +} + +/** + * xmlXIncludeNewRef: + * @ctxt: the XInclude context + * @URI: the resource URI + * + * Creates a new reference within an XInclude context + * + * Returns the new set + */ +static xmlXIncludeRefPtr +xmlXIncludeNewRef(xmlXIncludeCtxtPtr ctxt, const xmlChar *URI, + xmlNodePtr ref) { + xmlXIncludeRefPtr ret; + +#ifdef DEBUG_XINCLUDE + xmlGenericError(xmlGenericErrorContext, "New ref %s\n", URI); +#endif + ret = (xmlXIncludeRefPtr) xmlMalloc(sizeof(xmlXIncludeRef)); + if (ret == NULL) { + xmlXIncludeErrMemory(ctxt, ref, "growing XInclude context"); + return(NULL); + } + memset(ret, 0, sizeof(xmlXIncludeRef)); + if (URI == NULL) + ret->URI = NULL; + else + ret->URI = xmlStrdup(URI); + ret->fragment = NULL; + ret->ref = ref; + ret->doc = NULL; + ret->count = 0; + ret->xml = 0; + ret->inc = NULL; + if (ctxt->incMax == 0) { + ctxt->incMax = 4; + ctxt->incTab = (xmlXIncludeRefPtr *) xmlMalloc(ctxt->incMax * + sizeof(ctxt->incTab[0])); + if (ctxt->incTab == NULL) { + xmlXIncludeErrMemory(ctxt, ref, "growing XInclude context"); + xmlXIncludeFreeRef(ret); + return(NULL); + } + } + if (ctxt->incNr >= ctxt->incMax) { + ctxt->incMax *= 2; + ctxt->incTab = (xmlXIncludeRefPtr *) xmlRealloc(ctxt->incTab, + ctxt->incMax * sizeof(ctxt->incTab[0])); + if (ctxt->incTab == NULL) { + xmlXIncludeErrMemory(ctxt, ref, "growing XInclude context"); + xmlXIncludeFreeRef(ret); + return(NULL); + } + } + ctxt->incTab[ctxt->incNr++] = ret; + return(ret); +} + +/** + * xmlXIncludeNewContext: + * @doc: an XML Document + * + * Creates a new XInclude context + * + * Returns the new set + */ +xmlXIncludeCtxtPtr +xmlXIncludeNewContext(xmlDocPtr doc) { + xmlXIncludeCtxtPtr ret; + +#ifdef DEBUG_XINCLUDE + xmlGenericError(xmlGenericErrorContext, "New context\n"); +#endif + if (doc == NULL) + return(NULL); + ret = (xmlXIncludeCtxtPtr) xmlMalloc(sizeof(xmlXIncludeCtxt)); + if (ret == NULL) { + xmlXIncludeErrMemory(NULL, (xmlNodePtr) doc, + "creating XInclude context"); + return(NULL); + } + memset(ret, 0, sizeof(xmlXIncludeCtxt)); + ret->doc = doc; + ret->incNr = 0; + ret->incBase = 0; + ret->incMax = 0; + ret->incTab = NULL; + ret->nbErrors = 0; + return(ret); +} + +/** + * xmlXIncludeURLPush: + * @ctxt: the parser context + * @value: the url + * + * Pushes a new url on top of the url stack + * + * Returns -1 in case of error, the index in the stack otherwise + */ +static int +xmlXIncludeURLPush(xmlXIncludeCtxtPtr ctxt, + const xmlChar *value) +{ + if (ctxt->urlNr > XINCLUDE_MAX_DEPTH) { + xmlXIncludeErr(ctxt, NULL, XML_XINCLUDE_RECURSION, + "detected a recursion in %s\n", value); + return(-1); + } + if (ctxt->urlTab == NULL) { + ctxt->urlMax = 4; + ctxt->urlNr = 0; + ctxt->urlTab = (xmlChar * *) xmlMalloc( + ctxt->urlMax * sizeof(ctxt->urlTab[0])); + if (ctxt->urlTab == NULL) { + xmlXIncludeErrMemory(ctxt, NULL, "adding URL"); + return (-1); + } + } + if (ctxt->urlNr >= ctxt->urlMax) { + ctxt->urlMax *= 2; + ctxt->urlTab = + (xmlChar * *) xmlRealloc(ctxt->urlTab, + ctxt->urlMax * + sizeof(ctxt->urlTab[0])); + if (ctxt->urlTab == NULL) { + xmlXIncludeErrMemory(ctxt, NULL, "adding URL"); + return (-1); + } + } + ctxt->url = ctxt->urlTab[ctxt->urlNr] = xmlStrdup(value); + return (ctxt->urlNr++); +} + +/** + * xmlXIncludeURLPop: + * @ctxt: the parser context + * + * Pops the top URL from the URL stack + */ +static void +xmlXIncludeURLPop(xmlXIncludeCtxtPtr ctxt) +{ + xmlChar * ret; + + if (ctxt->urlNr <= 0) + return; + ctxt->urlNr--; + if (ctxt->urlNr > 0) + ctxt->url = ctxt->urlTab[ctxt->urlNr - 1]; + else + ctxt->url = NULL; + ret = ctxt->urlTab[ctxt->urlNr]; + ctxt->urlTab[ctxt->urlNr] = NULL; + if (ret != NULL) + xmlFree(ret); +} + +/** + * xmlXIncludeFreeContext: + * @ctxt: the XInclude context + * + * Free an XInclude context + */ +void +xmlXIncludeFreeContext(xmlXIncludeCtxtPtr ctxt) { + int i; + +#ifdef DEBUG_XINCLUDE + xmlGenericError(xmlGenericErrorContext, "Freeing context\n"); +#endif + if (ctxt == NULL) + return; + while (ctxt->urlNr > 0) + xmlXIncludeURLPop(ctxt); + if (ctxt->urlTab != NULL) + xmlFree(ctxt->urlTab); + for (i = 0;i < ctxt->incNr;i++) { + if (ctxt->incTab[i] != NULL) + xmlXIncludeFreeRef(ctxt->incTab[i]); + } + if (ctxt->txturlTab != NULL) { + for (i = 0;i < ctxt->txtNr;i++) { + if (ctxt->txturlTab[i] != NULL) + xmlFree(ctxt->txturlTab[i]); + } + } + if (ctxt->incTab != NULL) + xmlFree(ctxt->incTab); + if (ctxt->txtTab != NULL) + xmlFree(ctxt->txtTab); + if (ctxt->txturlTab != NULL) + xmlFree(ctxt->txturlTab); + if (ctxt->base != NULL) { + xmlFree(ctxt->base); + } + xmlFree(ctxt); +} + +/** + * xmlXIncludeParseFile: + * @ctxt: the XInclude context + * @URL: the URL or file path + * + * parse a document for XInclude + */ +static xmlDocPtr +xmlXIncludeParseFile(xmlXIncludeCtxtPtr ctxt, const char *URL) { + xmlDocPtr ret; + xmlParserCtxtPtr pctxt; + char *directory = NULL; + xmlParserInputPtr inputStream; + + xmlInitParser(); + + pctxt = xmlNewParserCtxt(); + if (pctxt == NULL) { + xmlXIncludeErrMemory(ctxt, NULL, "cannot allocate parser context"); + return(NULL); + } + + /* + * pass in the application data to the parser context. + */ + pctxt->_private = ctxt->_private; + + /* + * try to ensure that new documents included are actually + * built with the same dictionary as the including document. + */ + if ((ctxt->doc != NULL) && (ctxt->doc->dict != NULL) && + (pctxt->dict != NULL)) { + xmlDictFree(pctxt->dict); + pctxt->dict = ctxt->doc->dict; + xmlDictReference(pctxt->dict); + } + + xmlCtxtUseOptions(pctxt, ctxt->parseFlags | XML_PARSE_DTDLOAD); + + inputStream = xmlLoadExternalEntity(URL, NULL, pctxt); + if (inputStream == NULL) { + xmlFreeParserCtxt(pctxt); + return(NULL); + } + + inputPush(pctxt, inputStream); + + if ((pctxt->directory == NULL) && (directory == NULL)) + directory = xmlParserGetDirectory(URL); + if ((pctxt->directory == NULL) && (directory != NULL)) + pctxt->directory = (char *) xmlStrdup((xmlChar *) directory); + + pctxt->loadsubset |= XML_DETECT_IDS; + + xmlParseDocument(pctxt); + + if (pctxt->wellFormed) { + ret = pctxt->myDoc; + } + else { + ret = NULL; + if (pctxt->myDoc != NULL) + xmlFreeDoc(pctxt->myDoc); + pctxt->myDoc = NULL; + } + xmlFreeParserCtxt(pctxt); + + return(ret); +} + +/** + * xmlXIncludeAddNode: + * @ctxt: the XInclude context + * @cur: the new node + * + * Add a new node to process to an XInclude context + */ +static int +xmlXIncludeAddNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr cur) { + xmlXIncludeRefPtr ref; + xmlURIPtr uri; + xmlChar *URL; + xmlChar *fragment = NULL; + xmlChar *href; + xmlChar *parse; + xmlChar *base; + xmlChar *URI; + int xml = 1, i; /* default Issue 64 */ + int local = 0; + + + if (ctxt == NULL) + return(-1); + if (cur == NULL) + return(-1); + +#ifdef DEBUG_XINCLUDE + xmlGenericError(xmlGenericErrorContext, "Add node\n"); +#endif + /* + * read the attributes + */ + href = xmlXIncludeGetProp(ctxt, cur, XINCLUDE_HREF); + if (href == NULL) { + href = xmlStrdup(BAD_CAST ""); /* @@@@ href is now optional */ + if (href == NULL) + return(-1); + local = 1; + } + if (href[0] == '#') + local = 1; + parse = xmlXIncludeGetProp(ctxt, cur, XINCLUDE_PARSE); + if (parse != NULL) { + if (xmlStrEqual(parse, XINCLUDE_PARSE_XML)) + xml = 1; + else if (xmlStrEqual(parse, XINCLUDE_PARSE_TEXT)) + xml = 0; + else { + xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_PARSE_VALUE, + "invalid value %s for 'parse'\n", parse); + if (href != NULL) + xmlFree(href); + if (parse != NULL) + xmlFree(parse); + return(-1); + } + } + + /* + * compute the URI + */ + base = xmlNodeGetBase(ctxt->doc, cur); + if (base == NULL) { + URI = xmlBuildURI(href, ctxt->doc->URL); + } else { + URI = xmlBuildURI(href, base); + } + if (URI == NULL) { + xmlChar *escbase; + xmlChar *eschref; + /* + * Some escaping may be needed + */ + escbase = xmlURIEscape(base); + eschref = xmlURIEscape(href); + URI = xmlBuildURI(eschref, escbase); + if (escbase != NULL) + xmlFree(escbase); + if (eschref != NULL) + xmlFree(eschref); + } + if (parse != NULL) + xmlFree(parse); + if (href != NULL) + xmlFree(href); + if (base != NULL) + xmlFree(base); + if (URI == NULL) { + xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_HREF_URI, + "failed build URL\n", NULL); + return(-1); + } + fragment = xmlXIncludeGetProp(ctxt, cur, XINCLUDE_PARSE_XPOINTER); + + /* + * Check the URL and remove any fragment identifier + */ + uri = xmlParseURI((const char *)URI); + if (uri == NULL) { + xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_HREF_URI, + "invalid value URI %s\n", URI); + if (fragment != NULL) + xmlFree(fragment); + xmlFree(URI); + return(-1); + } + + if (uri->fragment != NULL) { + if (ctxt->legacy != 0) { + if (fragment == NULL) { + fragment = (xmlChar *) uri->fragment; + } else { + xmlFree(uri->fragment); + } + } else { + xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_FRAGMENT_ID, + "Invalid fragment identifier in URI %s use the xpointer attribute\n", + URI); + if (fragment != NULL) + xmlFree(fragment); + xmlFreeURI(uri); + xmlFree(URI); + return(-1); + } + uri->fragment = NULL; + } + URL = xmlSaveUri(uri); + xmlFreeURI(uri); + xmlFree(URI); + if (URL == NULL) { + xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_HREF_URI, + "invalid value URI %s\n", URI); + if (fragment != NULL) + xmlFree(fragment); + return(-1); + } + + /* + * Check the URL against the stack for recursions + */ + if ((!local) && (xml == 1)) { + for (i = 0;i < ctxt->urlNr;i++) { + if (xmlStrEqual(URL, ctxt->urlTab[i])) { + xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_RECURSION, + "detected a recursion in %s\n", URL); + return(-1); + } + } + } + + ref = xmlXIncludeNewRef(ctxt, URL, cur); + if (ref == NULL) { + return(-1); + } + ref->fragment = fragment; + ref->doc = NULL; + ref->xml = xml; + ref->count = 1; + xmlFree(URL); + return(0); +} + +/** + * xmlXIncludeRecurseDoc: + * @ctxt: the XInclude context + * @doc: the new document + * @url: the associated URL + * + * The XInclude recursive nature is handled at this point. + */ +static void +xmlXIncludeRecurseDoc(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, + const xmlURL url ATTRIBUTE_UNUSED) { + xmlXIncludeCtxtPtr newctxt; + int i; + + /* + * Avoid recursion in already substitued resources + for (i = 0;i < ctxt->urlNr;i++) { + if (xmlStrEqual(doc->URL, ctxt->urlTab[i])) + return; + } + */ + +#ifdef DEBUG_XINCLUDE + xmlGenericError(xmlGenericErrorContext, "Recursing in doc %s\n", doc->URL); +#endif + /* + * Handle recursion here. + */ + + newctxt = xmlXIncludeNewContext(doc); + if (newctxt != NULL) { + /* + * Copy the existing document set + */ + newctxt->incMax = ctxt->incMax; + newctxt->incNr = ctxt->incNr; + newctxt->incTab = (xmlXIncludeRefPtr *) xmlMalloc(newctxt->incMax * + sizeof(newctxt->incTab[0])); + if (newctxt->incTab == NULL) { + xmlXIncludeErrMemory(ctxt, (xmlNodePtr) doc, "processing doc"); + xmlFree(newctxt); + return; + } + /* + * copy the urlTab + */ + newctxt->urlMax = ctxt->urlMax; + newctxt->urlNr = ctxt->urlNr; + newctxt->urlTab = ctxt->urlTab; + + /* + * Inherit the existing base + */ + newctxt->base = xmlStrdup(ctxt->base); + + /* + * Inherit the documents already in use by other includes + */ + newctxt->incBase = ctxt->incNr; + for (i = 0;i < ctxt->incNr;i++) { + newctxt->incTab[i] = ctxt->incTab[i]; + newctxt->incTab[i]->count++; /* prevent the recursion from + freeing it */ + } + /* + * The new context should also inherit the Parse Flags + * (bug 132597) + */ + newctxt->parseFlags = ctxt->parseFlags; + xmlXIncludeDoProcess(newctxt, doc, xmlDocGetRootElement(doc)); + for (i = 0;i < ctxt->incNr;i++) { + newctxt->incTab[i]->count--; + newctxt->incTab[i] = NULL; + } + + /* urlTab may have been reallocated */ + ctxt->urlTab = newctxt->urlTab; + ctxt->urlMax = newctxt->urlMax; + + newctxt->urlMax = 0; + newctxt->urlNr = 0; + newctxt->urlTab = NULL; + + xmlXIncludeFreeContext(newctxt); + } +#ifdef DEBUG_XINCLUDE + xmlGenericError(xmlGenericErrorContext, "Done recursing in doc %s\n", url); +#endif +} + +/** + * xmlXIncludeAddTxt: + * @ctxt: the XInclude context + * @txt: the new text node + * @url: the associated URL + * + * Add a new txtument to the list + */ +static void +xmlXIncludeAddTxt(xmlXIncludeCtxtPtr ctxt, xmlNodePtr txt, const xmlURL url) { +#ifdef DEBUG_XINCLUDE + xmlGenericError(xmlGenericErrorContext, "Adding text %s\n", url); +#endif + if (ctxt->txtMax == 0) { + ctxt->txtMax = 4; + ctxt->txtTab = (xmlNodePtr *) xmlMalloc(ctxt->txtMax * + sizeof(ctxt->txtTab[0])); + if (ctxt->txtTab == NULL) { + xmlXIncludeErrMemory(ctxt, NULL, "processing text"); + return; + } + ctxt->txturlTab = (xmlURL *) xmlMalloc(ctxt->txtMax * + sizeof(ctxt->txturlTab[0])); + if (ctxt->txturlTab == NULL) { + xmlXIncludeErrMemory(ctxt, NULL, "processing text"); + return; + } + } + if (ctxt->txtNr >= ctxt->txtMax) { + ctxt->txtMax *= 2; + ctxt->txtTab = (xmlNodePtr *) xmlRealloc(ctxt->txtTab, + ctxt->txtMax * sizeof(ctxt->txtTab[0])); + if (ctxt->txtTab == NULL) { + xmlXIncludeErrMemory(ctxt, NULL, "processing text"); + return; + } + ctxt->txturlTab = (xmlURL *) xmlRealloc(ctxt->txturlTab, + ctxt->txtMax * sizeof(ctxt->txturlTab[0])); + if (ctxt->txturlTab == NULL) { + xmlXIncludeErrMemory(ctxt, NULL, "processing text"); + return; + } + } + ctxt->txtTab[ctxt->txtNr] = txt; + ctxt->txturlTab[ctxt->txtNr] = xmlStrdup(url); + ctxt->txtNr++; +} + +/************************************************************************ + * * + * Node copy with specific semantic * + * * + ************************************************************************/ + +/** + * xmlXIncludeCopyNode: + * @ctxt: the XInclude context + * @target: the document target + * @source: the document source + * @elem: the element + * + * Make a copy of the node while preserving the XInclude semantic + * of the Infoset copy + */ +static xmlNodePtr +xmlXIncludeCopyNode(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target, + xmlDocPtr source, xmlNodePtr elem) { + xmlNodePtr result = NULL; + + if ((ctxt == NULL) || (target == NULL) || (source == NULL) || + (elem == NULL)) + return(NULL); + if (elem->type == XML_DTD_NODE) + return(NULL); + result = xmlDocCopyNode(elem, target, 1); + return(result); +} + +/** + * xmlXIncludeCopyNodeList: + * @ctxt: the XInclude context + * @target: the document target + * @source: the document source + * @elem: the element list + * + * Make a copy of the node list while preserving the XInclude semantic + * of the Infoset copy + */ +static xmlNodePtr +xmlXIncludeCopyNodeList(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target, + xmlDocPtr source, xmlNodePtr elem) { + xmlNodePtr cur, res, result = NULL, last = NULL; + + if ((ctxt == NULL) || (target == NULL) || (source == NULL) || + (elem == NULL)) + return(NULL); + cur = elem; + while (cur != NULL) { + res = xmlXIncludeCopyNode(ctxt, target, source, cur); + if (res != NULL) { + if (result == NULL) { + result = last = res; + } else { + last->next = res; + res->prev = last; + last = res; + } + } + cur = cur->next; + } + return(result); +} + +/** + * xmlXIncludeGetNthChild: + * @cur: the node + * @no: the child number + * + * Returns the @n'th element child of @cur or NULL + */ +static xmlNodePtr +xmlXIncludeGetNthChild(xmlNodePtr cur, int no) { + int i; + if (cur == NULL) + return(cur); + cur = cur->children; + for (i = 0;i <= no;cur = cur->next) { + if (cur == NULL) + return(cur); + if ((cur->type == XML_ELEMENT_NODE) || + (cur->type == XML_DOCUMENT_NODE) || + (cur->type == XML_HTML_DOCUMENT_NODE)) { + i++; + if (i == no) + break; + } + } + return(cur); +} + +xmlNodePtr xmlXPtrAdvanceNode(xmlNodePtr cur, int *level); /* in xpointer.c */ +/** + * xmlXIncludeCopyRange: + * @ctxt: the XInclude context + * @target: the document target + * @source: the document source + * @obj: the XPointer result from the evaluation. + * + * Build a node list tree copy of the XPointer result. + * + * Returns an xmlNodePtr list or NULL. + * The caller has to free the node tree. + */ +static xmlNodePtr +xmlXIncludeCopyRange(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target, + xmlDocPtr source, xmlXPathObjectPtr range) { + /* pointers to generated nodes */ + xmlNodePtr list = NULL, last = NULL, listParent = NULL; + xmlNodePtr tmp, tmp2; + /* pointers to traversal nodes */ + xmlNodePtr start, cur, end; + int index1, index2; + int level = 0, lastLevel = 0, endLevel = 0, endFlag = 0; + + if ((ctxt == NULL) || (target == NULL) || (source == NULL) || + (range == NULL)) + return(NULL); + if (range->type != XPATH_RANGE) + return(NULL); + start = (xmlNodePtr) range->user; + + if (start == NULL) + return(NULL); + end = range->user2; + if (end == NULL) + return(xmlDocCopyNode(start, target, 1)); + + cur = start; + index1 = range->index; + index2 = range->index2; + /* + * level is depth of the current node under consideration + * list is the pointer to the root of the output tree + * listParent is a pointer to the parent of output tree (within + the included file) in case we need to add another level + * last is a pointer to the last node added to the output tree + * lastLevel is the depth of last (relative to the root) + */ + while (cur != NULL) { + /* + * Check if our output tree needs a parent + */ + if (level < 0) { + while (level < 0) { + /* copy must include namespaces and properties */ + tmp2 = xmlDocCopyNode(listParent, target, 2); + xmlAddChild(tmp2, list); + list = tmp2; + listParent = listParent->parent; + level++; + } + last = list; + lastLevel = 0; + } + /* + * Check whether we need to change our insertion point + */ + while (level < lastLevel) { + last = last->parent; + lastLevel --; + } + if (cur == end) { /* Are we at the end of the range? */ + if (cur->type == XML_TEXT_NODE) { + const xmlChar *content = cur->content; + int len; + + if (content == NULL) { + tmp = xmlNewTextLen(NULL, 0); + } else { + len = index2; + if ((cur == start) && (index1 > 1)) { + content += (index1 - 1); + len -= (index1 - 1); + index1 = 0; + } else { + len = index2; + } + tmp = xmlNewTextLen(content, len); + } + /* single sub text node selection */ + if (list == NULL) + return(tmp); + /* prune and return full set */ + if (level == lastLevel) + xmlAddNextSibling(last, tmp); + else + xmlAddChild(last, tmp); + return(list); + } else { /* ending node not a text node */ + endLevel = level; /* remember the level of the end node */ + endFlag = 1; + /* last node - need to take care of properties + namespaces */ + tmp = xmlDocCopyNode(cur, target, 2); + if (list == NULL) { + list = tmp; + listParent = cur->parent; + } else { + if (level == lastLevel) + xmlAddNextSibling(last, tmp); + else { + xmlAddChild(last, tmp); + lastLevel = level; + } + } + last = tmp; + + if (index2 > 1) { + end = xmlXIncludeGetNthChild(cur, index2 - 1); + index2 = 0; + } + if ((cur == start) && (index1 > 1)) { + cur = xmlXIncludeGetNthChild(cur, index1 - 1); + index1 = 0; + } else { + cur = cur->children; + } + level++; /* increment level to show change */ + /* + * Now gather the remaining nodes from cur to end + */ + continue; /* while */ + } + } else if (cur == start) { /* Not at the end, are we at start? */ + if ((cur->type == XML_TEXT_NODE) || + (cur->type == XML_CDATA_SECTION_NODE)) { + const xmlChar *content = cur->content; + + if (content == NULL) { + tmp = xmlNewTextLen(NULL, 0); + } else { + if (index1 > 1) { + content += (index1 - 1); + index1 = 0; + } + tmp = xmlNewText(content); + } + last = list = tmp; + listParent = cur->parent; + } else { /* Not text node */ + /* + * start of the range - need to take care of + * properties and namespaces + */ + tmp = xmlDocCopyNode(cur, target, 2); + list = last = tmp; + listParent = cur->parent; + if (index1 > 1) { /* Do we need to position? */ + cur = xmlXIncludeGetNthChild(cur, index1 - 1); + level = lastLevel = 1; + index1 = 0; + /* + * Now gather the remaining nodes from cur to end + */ + continue; /* while */ + } + } + } else { + tmp = NULL; + switch (cur->type) { + case XML_DTD_NODE: + case XML_ELEMENT_DECL: + case XML_ATTRIBUTE_DECL: + case XML_ENTITY_NODE: + /* Do not copy DTD informations */ + break; + case XML_ENTITY_DECL: + /* handle crossing entities -> stack needed */ + break; + case XML_XINCLUDE_START: + case XML_XINCLUDE_END: + /* don't consider it part of the tree content */ + break; + case XML_ATTRIBUTE_NODE: + /* Humm, should not happen ! */ + break; + default: + /* + * Middle of the range - need to take care of + * properties and namespaces + */ + tmp = xmlDocCopyNode(cur, target, 2); + break; + } + if (tmp != NULL) { + if (level == lastLevel) + xmlAddNextSibling(last, tmp); + else { + xmlAddChild(last, tmp); + lastLevel = level; + } + last = tmp; + } + } + /* + * Skip to next node in document order + */ + cur = xmlXPtrAdvanceNode(cur, &level); + if (endFlag && (level >= endLevel)) + break; + } + return(list); +} + +/** + * xmlXIncludeBuildNodeList: + * @ctxt: the XInclude context + * @target: the document target + * @source: the document source + * @obj: the XPointer result from the evaluation. + * + * Build a node list tree copy of the XPointer result. + * This will drop Attributes and Namespace declarations. + * + * Returns an xmlNodePtr list or NULL. + * the caller has to free the node tree. + */ +static xmlNodePtr +xmlXIncludeCopyXPointer(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target, + xmlDocPtr source, xmlXPathObjectPtr obj) { + xmlNodePtr list = NULL, last = NULL; + int i; + + if (source == NULL) + source = ctxt->doc; + if ((ctxt == NULL) || (target == NULL) || (source == NULL) || + (obj == NULL)) + return(NULL); + switch (obj->type) { + case XPATH_NODESET: { + xmlNodeSetPtr set = obj->nodesetval; + if (set == NULL) + return(NULL); + for (i = 0;i < set->nodeNr;i++) { + if (set->nodeTab[i] == NULL) + continue; + switch (set->nodeTab[i]->type) { + case XML_TEXT_NODE: + case XML_CDATA_SECTION_NODE: + case XML_ELEMENT_NODE: + case XML_ENTITY_REF_NODE: + case XML_ENTITY_NODE: + case XML_PI_NODE: + case XML_COMMENT_NODE: + case XML_DOCUMENT_NODE: + case XML_HTML_DOCUMENT_NODE: +#ifdef LIBXML_DOCB_ENABLED + case XML_DOCB_DOCUMENT_NODE: +#endif + case XML_XINCLUDE_END: + break; + case XML_XINCLUDE_START: { + xmlNodePtr tmp, cur = set->nodeTab[i]; + + cur = cur->next; + while (cur != NULL) { + switch(cur->type) { + case XML_TEXT_NODE: + case XML_CDATA_SECTION_NODE: + case XML_ELEMENT_NODE: + case XML_ENTITY_REF_NODE: + case XML_ENTITY_NODE: + case XML_PI_NODE: + case XML_COMMENT_NODE: + tmp = xmlXIncludeCopyNode(ctxt, target, + source, cur); + if (last == NULL) { + list = last = tmp; + } else { + xmlAddNextSibling(last, tmp); + last = tmp; + } + cur = cur->next; + continue; + default: + break; + } + break; + } + continue; + } + case XML_ATTRIBUTE_NODE: + case XML_NAMESPACE_DECL: + case XML_DOCUMENT_TYPE_NODE: + case XML_DOCUMENT_FRAG_NODE: + case XML_NOTATION_NODE: + case XML_DTD_NODE: + case XML_ELEMENT_DECL: + case XML_ATTRIBUTE_DECL: + case XML_ENTITY_DECL: + continue; /* for */ + } + if (last == NULL) + list = last = xmlXIncludeCopyNode(ctxt, target, source, + set->nodeTab[i]); + else { + xmlAddNextSibling(last, + xmlXIncludeCopyNode(ctxt, target, source, + set->nodeTab[i])); + if (last->next != NULL) + last = last->next; + } + } + break; + } + case XPATH_LOCATIONSET: { + xmlLocationSetPtr set = (xmlLocationSetPtr) obj->user; + if (set == NULL) + return(NULL); + for (i = 0;i < set->locNr;i++) { + if (last == NULL) + list = last = xmlXIncludeCopyXPointer(ctxt, target, source, + set->locTab[i]); + else + xmlAddNextSibling(last, + xmlXIncludeCopyXPointer(ctxt, target, source, + set->locTab[i])); + if (last != NULL) { + while (last->next != NULL) + last = last->next; + } + } + break; + } +#ifdef LIBXML_XPTR_ENABLED + case XPATH_RANGE: + return(xmlXIncludeCopyRange(ctxt, target, source, obj)); +#endif + case XPATH_POINT: + /* points are ignored in XInclude */ + break; + default: + break; + } + return(list); +} +/************************************************************************ + * * + * XInclude I/O handling * + * * + ************************************************************************/ + +typedef struct _xmlXIncludeMergeData xmlXIncludeMergeData; +typedef xmlXIncludeMergeData *xmlXIncludeMergeDataPtr; +struct _xmlXIncludeMergeData { + xmlDocPtr doc; + xmlXIncludeCtxtPtr ctxt; +}; + +/** + * xmlXIncludeMergeOneEntity: + * @ent: the entity + * @doc: the including doc + * @nr: the entity name + * + * Inplements the merge of one entity + */ +static void +xmlXIncludeMergeEntity(xmlEntityPtr ent, xmlXIncludeMergeDataPtr data, + xmlChar *name ATTRIBUTE_UNUSED) { + xmlEntityPtr ret, prev; + xmlDocPtr doc; + xmlXIncludeCtxtPtr ctxt; + + if ((ent == NULL) || (data == NULL)) + return; + ctxt = data->ctxt; + doc = data->doc; + if ((ctxt == NULL) || (doc == NULL)) + return; + switch (ent->etype) { + case XML_INTERNAL_PARAMETER_ENTITY: + case XML_EXTERNAL_PARAMETER_ENTITY: + case XML_INTERNAL_PREDEFINED_ENTITY: + return; + case XML_INTERNAL_GENERAL_ENTITY: + case XML_EXTERNAL_GENERAL_PARSED_ENTITY: + case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY: + break; + } + ret = xmlAddDocEntity(doc, ent->name, ent->etype, ent->ExternalID, + ent->SystemID, ent->content); + if (ret != NULL) { + if (ent->URI != NULL) + ret->URI = xmlStrdup(ent->URI); + } else { + prev = xmlGetDocEntity(doc, ent->name); + if (prev != NULL) { + if (ent->etype != prev->etype) + goto error; + + if ((ent->SystemID != NULL) && (prev->SystemID != NULL)) { + if (!xmlStrEqual(ent->SystemID, prev->SystemID)) + goto error; + } else if ((ent->ExternalID != NULL) && + (prev->ExternalID != NULL)) { + if (!xmlStrEqual(ent->ExternalID, prev->ExternalID)) + goto error; + } else if ((ent->content != NULL) && (prev->content != NULL)) { + if (!xmlStrEqual(ent->content, prev->content)) + goto error; + } else { + goto error; + } + + } + } + return; +error: + switch (ent->etype) { + case XML_INTERNAL_PARAMETER_ENTITY: + case XML_EXTERNAL_PARAMETER_ENTITY: + case XML_INTERNAL_PREDEFINED_ENTITY: + case XML_INTERNAL_GENERAL_ENTITY: + case XML_EXTERNAL_GENERAL_PARSED_ENTITY: + return; + case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY: + break; + } + xmlXIncludeErr(ctxt, (xmlNodePtr) ent, XML_XINCLUDE_ENTITY_DEF_MISMATCH, + "mismatch in redefinition of entity %s\n", + ent->name); +} + +/** + * xmlXIncludeMergeEntities: + * @ctxt: an XInclude context + * @doc: the including doc + * @from: the included doc + * + * Inplements the entity merge + * + * Returns 0 if merge succeeded, -1 if some processing failed + */ +static int +xmlXIncludeMergeEntities(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, + xmlDocPtr from) { + xmlNodePtr cur; + xmlDtdPtr target, source; + + if (ctxt == NULL) + return(-1); + + if ((from == NULL) || (from->intSubset == NULL)) + return(0); + + target = doc->intSubset; + if (target == NULL) { + cur = xmlDocGetRootElement(doc); + if (cur == NULL) + return(-1); + target = xmlCreateIntSubset(doc, cur->name, NULL, NULL); + if (target == NULL) + return(-1); + } + + source = from->intSubset; + if ((source != NULL) && (source->entities != NULL)) { + xmlXIncludeMergeData data; + + data.ctxt = ctxt; + data.doc = doc; + + xmlHashScan((xmlHashTablePtr) source->entities, + (xmlHashScanner) xmlXIncludeMergeEntity, &data); + } + source = from->extSubset; + if ((source != NULL) && (source->entities != NULL)) { + xmlXIncludeMergeData data; + + data.ctxt = ctxt; + data.doc = doc; + + /* + * don't duplicate existing stuff when external subsets are the same + */ + if ((!xmlStrEqual(target->ExternalID, source->ExternalID)) && + (!xmlStrEqual(target->SystemID, source->SystemID))) { + xmlHashScan((xmlHashTablePtr) source->entities, + (xmlHashScanner) xmlXIncludeMergeEntity, &data); + } + } + return(0); +} + +/** + * xmlXIncludeLoadDoc: + * @ctxt: the XInclude context + * @url: the associated URL + * @nr: the xinclude node number + * + * Load the document, and store the result in the XInclude context + * + * Returns 0 in case of success, -1 in case of failure + */ +static int +xmlXIncludeLoadDoc(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, int nr) { + xmlDocPtr doc; + xmlURIPtr uri; + xmlChar *URL; + xmlChar *fragment = NULL; + int i = 0; +#ifdef LIBXML_XPTR_ENABLED + int saveFlags; +#endif + +#ifdef DEBUG_XINCLUDE + xmlGenericError(xmlGenericErrorContext, "Loading doc %s:%d\n", url, nr); +#endif + /* + * Check the URL and remove any fragment identifier + */ + uri = xmlParseURI((const char *)url); + if (uri == NULL) { + xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref, + XML_XINCLUDE_HREF_URI, + "invalid value URI %s\n", url); + return(-1); + } + if (uri->fragment != NULL) { + fragment = (xmlChar *) uri->fragment; + uri->fragment = NULL; + } + if ((ctxt->incTab != NULL) && (ctxt->incTab[nr] != NULL) && + (ctxt->incTab[nr]->fragment != NULL)) { + if (fragment != NULL) xmlFree(fragment); + fragment = xmlStrdup(ctxt->incTab[nr]->fragment); + } + URL = xmlSaveUri(uri); + xmlFreeURI(uri); + if (URL == NULL) { + if (ctxt->incTab != NULL) + xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref, + XML_XINCLUDE_HREF_URI, + "invalid value URI %s\n", url); + else + xmlXIncludeErr(ctxt, NULL, + XML_XINCLUDE_HREF_URI, + "invalid value URI %s\n", url); + if (fragment != NULL) + xmlFree(fragment); + return(-1); + } + + /* + * Handling of references to the local document are done + * directly through ctxt->doc. + */ + if ((URL[0] == 0) || (URL[0] == '#') || + ((ctxt->doc != NULL) && (xmlStrEqual(URL, ctxt->doc->URL)))) { + doc = NULL; + goto loaded; + } + + /* + * Prevent reloading twice the document. + */ + for (i = 0; i < ctxt->incNr; i++) { + if ((xmlStrEqual(URL, ctxt->incTab[i]->URI)) && + (ctxt->incTab[i]->doc != NULL)) { + doc = ctxt->incTab[i]->doc; +#ifdef DEBUG_XINCLUDE + printf("Already loaded %s\n", URL); +#endif + goto loaded; + } + } + + /* + * Load it. + */ +#ifdef DEBUG_XINCLUDE + printf("loading %s\n", URL); +#endif +#ifdef LIBXML_XPTR_ENABLED + /* + * If this is an XPointer evaluation, we want to assure that + * all entities have been resolved prior to processing the + * referenced document + */ + saveFlags = ctxt->parseFlags; + if (fragment != NULL) { /* if this is an XPointer eval */ + ctxt->parseFlags |= XML_PARSE_NOENT; + } +#endif + + doc = xmlXIncludeParseFile(ctxt, (const char *)URL); +#ifdef LIBXML_XPTR_ENABLED + ctxt->parseFlags = saveFlags; +#endif + if (doc == NULL) { + xmlFree(URL); + if (fragment != NULL) + xmlFree(fragment); + return(-1); + } + ctxt->incTab[nr]->doc = doc; + /* + * It's possible that the requested URL has been mapped to a + * completely different location (e.g. through a catalog entry). + * To check for this, we compare the URL with that of the doc + * and change it if they disagree (bug 146988). + */ + if (!xmlStrEqual(URL, doc->URL)) { + xmlFree(URL); + URL = xmlStrdup(doc->URL); + } + for (i = nr + 1; i < ctxt->incNr; i++) { + if (xmlStrEqual(URL, ctxt->incTab[i]->URI)) { + ctxt->incTab[nr]->count++; +#ifdef DEBUG_XINCLUDE + printf("Increasing %s count since reused\n", URL); +#endif + break; + } + } + + /* + * Make sure we have all entities fixed up + */ + xmlXIncludeMergeEntities(ctxt, ctxt->doc, doc); + + /* + * We don't need the DTD anymore, free up space + if (doc->intSubset != NULL) { + xmlUnlinkNode((xmlNodePtr) doc->intSubset); + xmlFreeNode((xmlNodePtr) doc->intSubset); + doc->intSubset = NULL; + } + if (doc->extSubset != NULL) { + xmlUnlinkNode((xmlNodePtr) doc->extSubset); + xmlFreeNode((xmlNodePtr) doc->extSubset); + doc->extSubset = NULL; + } + */ + xmlXIncludeRecurseDoc(ctxt, doc, URL); + +loaded: + if (fragment == NULL) { + /* + * Add the top children list as the replacement copy. + */ + if (doc == NULL) + { + /* Hopefully a DTD declaration won't be copied from + * the same document */ + ctxt->incTab[nr]->inc = xmlCopyNodeList(ctxt->doc->children); + } else { + ctxt->incTab[nr]->inc = xmlXIncludeCopyNodeList(ctxt, ctxt->doc, + doc, doc->children); + } + } +#ifdef LIBXML_XPTR_ENABLED + else { + /* + * Computes the XPointer expression and make a copy used + * as the replacement copy. + */ + xmlXPathObjectPtr xptr; + xmlXPathContextPtr xptrctxt; + xmlNodeSetPtr set; + + if (doc == NULL) { + xptrctxt = xmlXPtrNewContext(ctxt->doc, ctxt->incTab[nr]->ref, + NULL); + } else { + xptrctxt = xmlXPtrNewContext(doc, NULL, NULL); + } + if (xptrctxt == NULL) { + xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref, + XML_XINCLUDE_XPTR_FAILED, + "could not create XPointer context\n", NULL); + xmlFree(URL); + xmlFree(fragment); + return(-1); + } + xptr = xmlXPtrEval(fragment, xptrctxt); + if (xptr == NULL) { + xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref, + XML_XINCLUDE_XPTR_FAILED, + "XPointer evaluation failed: #%s\n", + fragment); + xmlXPathFreeContext(xptrctxt); + xmlFree(URL); + xmlFree(fragment); + return(-1); + } + switch (xptr->type) { + case XPATH_UNDEFINED: + case XPATH_BOOLEAN: + case XPATH_NUMBER: + case XPATH_STRING: + case XPATH_POINT: + case XPATH_USERS: + case XPATH_XSLT_TREE: + xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref, + XML_XINCLUDE_XPTR_RESULT, + "XPointer is not a range: #%s\n", + fragment); + xmlXPathFreeContext(xptrctxt); + xmlFree(URL); + xmlFree(fragment); + return(-1); + case XPATH_NODESET: + if ((xptr->nodesetval == NULL) || + (xptr->nodesetval->nodeNr <= 0)) { + xmlXPathFreeContext(xptrctxt); + xmlFree(URL); + xmlFree(fragment); + return(-1); + } + + case XPATH_RANGE: + case XPATH_LOCATIONSET: + break; + } + set = xptr->nodesetval; + if (set != NULL) { + for (i = 0;i < set->nodeNr;i++) { + if (set->nodeTab[i] == NULL) + continue; + switch (set->nodeTab[i]->type) { + case XML_TEXT_NODE: + case XML_CDATA_SECTION_NODE: + case XML_ENTITY_REF_NODE: + case XML_ENTITY_NODE: + case XML_PI_NODE: + case XML_COMMENT_NODE: + case XML_DOCUMENT_NODE: + case XML_HTML_DOCUMENT_NODE: +#ifdef LIBXML_DOCB_ENABLED + case XML_DOCB_DOCUMENT_NODE: +#endif + continue; + case XML_ELEMENT_NODE: { + xmlChar *nodeBase; + xmlNodePtr el = set->nodeTab[i]; + + nodeBase = xmlNodeGetBase(el->doc, el); + if (nodeBase != NULL) { + if (!xmlStrEqual(nodeBase, el->doc->URL)) + xmlNodeSetBase(el, nodeBase); + xmlFree(nodeBase); + } + continue; + } + + case XML_ATTRIBUTE_NODE: + xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref, + XML_XINCLUDE_XPTR_RESULT, + "XPointer selects an attribute: #%s\n", + fragment); + set->nodeTab[i] = NULL; + continue; + case XML_NAMESPACE_DECL: + xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref, + XML_XINCLUDE_XPTR_RESULT, + "XPointer selects a namespace: #%s\n", + fragment); + set->nodeTab[i] = NULL; + continue; + case XML_DOCUMENT_TYPE_NODE: + case XML_DOCUMENT_FRAG_NODE: + case XML_NOTATION_NODE: + case XML_DTD_NODE: + case XML_ELEMENT_DECL: + case XML_ATTRIBUTE_DECL: + case XML_ENTITY_DECL: + case XML_XINCLUDE_START: + case XML_XINCLUDE_END: + xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref, + XML_XINCLUDE_XPTR_RESULT, + "XPointer selects unexpected nodes: #%s\n", + fragment); + set->nodeTab[i] = NULL; + set->nodeTab[i] = NULL; + continue; /* for */ + } + } + } + if (doc == NULL) { + ctxt->incTab[nr]->xptr = xptr; + ctxt->incTab[nr]->inc = NULL; + } else { + ctxt->incTab[nr]->inc = + xmlXIncludeCopyXPointer(ctxt, ctxt->doc, doc, xptr); + xmlXPathFreeObject(xptr); + } + xmlXPathFreeContext(xptrctxt); + xmlFree(fragment); + } +#endif + + /* + * Do the xml:base fixup if needed + */ + if ((doc != NULL) && (URL != NULL) && (xmlStrchr(URL, (xmlChar) '/'))) { + xmlNodePtr node; + xmlChar *base; + xmlChar *curBase; + + /* + * The base is only adjusted if "necessary", i.e. if the xinclude node + * has a base specified, or the URL is relative + */ + base = xmlGetNsProp(ctxt->incTab[nr]->ref, BAD_CAST "base", + XML_XML_NAMESPACE); + if (base == NULL) { + /* + * No xml:base on the xinclude node, so we check whether the + * URI base is different than (relative to) the context base + */ + curBase = xmlBuildRelativeURI(URL, ctxt->base); + if (curBase == NULL) { /* Error return */ + xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref, + XML_XINCLUDE_HREF_URI, + "trying to build relative URI from %s\n", URL); + } else { + /* If the URI doesn't contain a slash, it's not relative */ + if (!xmlStrchr(curBase, (xmlChar) '/')) + xmlFree(curBase); + else + base = curBase; + } + } + if (base != NULL) { /* Adjustment may be needed */ + node = ctxt->incTab[nr]->inc; + while (node != NULL) { + /* Only work on element nodes */ + if (node->type == XML_ELEMENT_NODE) { + curBase = xmlNodeGetBase(node->doc, node); + /* If no current base, set it */ + if (curBase == NULL) { + xmlNodeSetBase(node, base); + } else { + /* + * If the current base is the same as the + * URL of the document, then reset it to be + * the specified xml:base or the relative URI + */ + if (xmlStrEqual(curBase, node->doc->URL)) { + xmlNodeSetBase(node, base); + } else { + /* + * If the element already has an xml:base + * set, then relativise it if necessary + */ + xmlChar *xmlBase; + xmlBase = xmlGetNsProp(node, + BAD_CAST "base", + XML_XML_NAMESPACE); + if (xmlBase != NULL) { + xmlChar *relBase; + relBase = xmlBuildURI(xmlBase, base); + if (relBase == NULL) { /* error */ + xmlXIncludeErr(ctxt, + ctxt->incTab[nr]->ref, + XML_XINCLUDE_HREF_URI, + "trying to rebuild base from %s\n", + xmlBase); + } else { + xmlNodeSetBase(node, relBase); + xmlFree(relBase); + } + xmlFree(xmlBase); + } + } + xmlFree(curBase); + } + } + node = node->next; + } + xmlFree(base); + } + } + if ((nr < ctxt->incNr) && (ctxt->incTab[nr]->doc != NULL) && + (ctxt->incTab[nr]->count <= 1)) { +#ifdef DEBUG_XINCLUDE + printf("freeing %s\n", ctxt->incTab[nr]->doc->URL); +#endif + xmlFreeDoc(ctxt->incTab[nr]->doc); + ctxt->incTab[nr]->doc = NULL; + } + xmlFree(URL); + return(0); +} + +/** + * xmlXIncludeLoadTxt: + * @ctxt: the XInclude context + * @url: the associated URL + * @nr: the xinclude node number + * + * Load the content, and store the result in the XInclude context + * + * Returns 0 in case of success, -1 in case of failure + */ +static int +xmlXIncludeLoadTxt(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, int nr) { + xmlParserInputBufferPtr buf; + xmlNodePtr node; + xmlURIPtr uri; + xmlChar *URL; + int i; + xmlChar *encoding = NULL; + xmlCharEncoding enc = (xmlCharEncoding) 0; + + /* + * Check the URL and remove any fragment identifier + */ + uri = xmlParseURI((const char *)url); + if (uri == NULL) { + xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref, XML_XINCLUDE_HREF_URI, + "invalid value URI %s\n", url); + return(-1); + } + if (uri->fragment != NULL) { + xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref, XML_XINCLUDE_TEXT_FRAGMENT, + "fragment identifier forbidden for text: %s\n", + (const xmlChar *) uri->fragment); + xmlFreeURI(uri); + return(-1); + } + URL = xmlSaveUri(uri); + xmlFreeURI(uri); + if (URL == NULL) { + xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref, XML_XINCLUDE_HREF_URI, + "invalid value URI %s\n", url); + return(-1); + } + + /* + * Handling of references to the local document are done + * directly through ctxt->doc. + */ + if (URL[0] == 0) { + xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref, + XML_XINCLUDE_TEXT_DOCUMENT, + "text serialization of document not available\n", NULL); + xmlFree(URL); + return(-1); + } + + /* + * Prevent reloading twice the document. + */ + for (i = 0; i < ctxt->txtNr; i++) { + if (xmlStrEqual(URL, ctxt->txturlTab[i])) { + node = xmlCopyNode(ctxt->txtTab[i], 1); + goto loaded; + } + } + /* + * Try to get the encoding if available + */ + if ((ctxt->incTab[nr] != NULL) && (ctxt->incTab[nr]->ref != NULL)) { + encoding = xmlGetProp(ctxt->incTab[nr]->ref, XINCLUDE_PARSE_ENCODING); + } + if (encoding != NULL) { + /* + * TODO: we should not have to remap to the xmlCharEncoding + * predefined set, a better interface than + * xmlParserInputBufferCreateFilename should allow any + * encoding supported by iconv + */ + enc = xmlParseCharEncoding((const char *) encoding); + if (enc == XML_CHAR_ENCODING_ERROR) { + xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref, + XML_XINCLUDE_UNKNOWN_ENCODING, + "encoding %s not supported\n", encoding); + xmlFree(encoding); + xmlFree(URL); + return(-1); + } + xmlFree(encoding); + } + + /* + * Load it. + */ + buf = xmlParserInputBufferCreateFilename((const char *)URL, enc); + if (buf == NULL) { + xmlFree(URL); + return(-1); + } + node = xmlNewText(NULL); + + /* + * Scan all chars from the resource and add the to the node + */ + while (xmlParserInputBufferRead(buf, 128) > 0) { + int len; + const xmlChar *content; + + content = xmlBufferContent(buf->buffer); + len = xmlBufferLength(buf->buffer); + for (i = 0;i < len;) { + int cur; + int l; + + cur = xmlStringCurrentChar(NULL, &content[i], &l); + if (!IS_CHAR(cur)) { + xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref, + XML_XINCLUDE_INVALID_CHAR, + "%s contains invalid char\n", URL); + } else { + xmlNodeAddContentLen(node, &content[i], l); + } + i += l; + } + xmlBufferShrink(buf->buffer, len); + } + xmlFreeParserInputBuffer(buf); + xmlXIncludeAddTxt(ctxt, node, URL); + +loaded: + /* + * Add the element as the replacement copy. + */ + ctxt->incTab[nr]->inc = node; + xmlFree(URL); + return(0); +} + +/** + * xmlXIncludeLoadFallback: + * @ctxt: the XInclude context + * @fallback: the fallback node + * @nr: the xinclude node number + * + * Load the content of the fallback node, and store the result + * in the XInclude context + * + * Returns 0 in case of success, -1 in case of failure + */ +static int +xmlXIncludeLoadFallback(xmlXIncludeCtxtPtr ctxt, xmlNodePtr fallback, int nr) { + xmlXIncludeCtxtPtr newctxt; + int ret = 0; + + if ((fallback == NULL) || (ctxt == NULL)) + return(-1); + if (fallback->children != NULL) { + /* + * It's possible that the fallback also has 'includes' + * (Bug 129969), so we re-process the fallback just in case + */ + newctxt = xmlXIncludeNewContext(ctxt->doc); + if (newctxt == NULL) + return (-1); + newctxt->base = xmlStrdup(ctxt->base); /* Inherit the base from the existing context */ + xmlXIncludeSetFlags(newctxt, ctxt->parseFlags); + ret = xmlXIncludeDoProcess(newctxt, ctxt->doc, fallback->children); + if (ctxt->nbErrors > 0) + ret = -1; + else if (ret > 0) + ret = 0; /* xmlXIncludeDoProcess can return +ve number */ + xmlXIncludeFreeContext(newctxt); + + ctxt->incTab[nr]->inc = xmlDocCopyNodeList(ctxt->doc, + fallback->children); + } else { + ctxt->incTab[nr]->inc = NULL; + ctxt->incTab[nr]->emptyFb = 1; /* flag empty callback */ + } + return(ret); +} + +/************************************************************************ + * * + * XInclude Processing * + * * + ************************************************************************/ + +/** + * xmlXIncludePreProcessNode: + * @ctxt: an XInclude context + * @node: an XInclude node + * + * Implement the XInclude preprocessing, currently just adding the element + * for further processing. + * + * Returns the result list or NULL in case of error + */ +static xmlNodePtr +xmlXIncludePreProcessNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node) { + xmlXIncludeAddNode(ctxt, node); + return(NULL); +} + +/** + * xmlXIncludeLoadNode: + * @ctxt: an XInclude context + * @nr: the node number + * + * Find and load the infoset replacement for the given node. + * + * Returns 0 if substitution succeeded, -1 if some processing failed + */ +static int +xmlXIncludeLoadNode(xmlXIncludeCtxtPtr ctxt, int nr) { + xmlNodePtr cur; + xmlChar *href; + xmlChar *parse; + xmlChar *base; + xmlChar *oldBase; + xmlChar *URI; + int xml = 1; /* default Issue 64 */ + int ret; + + if (ctxt == NULL) + return(-1); + if ((nr < 0) || (nr >= ctxt->incNr)) + return(-1); + cur = ctxt->incTab[nr]->ref; + if (cur == NULL) + return(-1); + + /* + * read the attributes + */ + href = xmlXIncludeGetProp(ctxt, cur, XINCLUDE_HREF); + if (href == NULL) { + href = xmlStrdup(BAD_CAST ""); /* @@@@ href is now optional */ + if (href == NULL) + return(-1); + } + parse = xmlXIncludeGetProp(ctxt, cur, XINCLUDE_PARSE); + if (parse != NULL) { + if (xmlStrEqual(parse, XINCLUDE_PARSE_XML)) + xml = 1; + else if (xmlStrEqual(parse, XINCLUDE_PARSE_TEXT)) + xml = 0; + else { + xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref, + XML_XINCLUDE_PARSE_VALUE, + "invalid value %s for 'parse'\n", parse); + if (href != NULL) + xmlFree(href); + if (parse != NULL) + xmlFree(parse); + return(-1); + } + } + + /* + * compute the URI + */ + base = xmlNodeGetBase(ctxt->doc, cur); + if (base == NULL) { + URI = xmlBuildURI(href, ctxt->doc->URL); + } else { + URI = xmlBuildURI(href, base); + } + if (URI == NULL) { + xmlChar *escbase; + xmlChar *eschref; + /* + * Some escaping may be needed + */ + escbase = xmlURIEscape(base); + eschref = xmlURIEscape(href); + URI = xmlBuildURI(eschref, escbase); + if (escbase != NULL) + xmlFree(escbase); + if (eschref != NULL) + xmlFree(eschref); + } + if (URI == NULL) { + xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref, + XML_XINCLUDE_HREF_URI, "failed build URL\n", NULL); + if (parse != NULL) + xmlFree(parse); + if (href != NULL) + xmlFree(href); + if (base != NULL) + xmlFree(base); + return(-1); + } +#ifdef DEBUG_XINCLUDE + xmlGenericError(xmlGenericErrorContext, "parse: %s\n", + xml ? "xml": "text"); + xmlGenericError(xmlGenericErrorContext, "URI: %s\n", URI); +#endif + + /* + * Save the base for this include (saving the current one) + */ + oldBase = ctxt->base; + ctxt->base = base; + + if (xml) { + ret = xmlXIncludeLoadDoc(ctxt, URI, nr); + /* xmlXIncludeGetFragment(ctxt, cur, URI); */ + } else { + ret = xmlXIncludeLoadTxt(ctxt, URI, nr); + } + + /* + * Restore the original base before checking for fallback + */ + ctxt->base = oldBase; + + if (ret < 0) { + xmlNodePtr children; + + /* + * Time to try a fallback if availble + */ +#ifdef DEBUG_XINCLUDE + xmlGenericError(xmlGenericErrorContext, "error looking for fallback\n"); +#endif + children = cur->children; + while (children != NULL) { + if ((children->type == XML_ELEMENT_NODE) && + (children->ns != NULL) && + (xmlStrEqual(children->name, XINCLUDE_FALLBACK)) && + ((xmlStrEqual(children->ns->href, XINCLUDE_NS)) || + (xmlStrEqual(children->ns->href, XINCLUDE_OLD_NS)))) { + ret = xmlXIncludeLoadFallback(ctxt, children, nr); + if (ret == 0) + break; + } + children = children->next; + } + } + if (ret < 0) { + xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref, + XML_XINCLUDE_NO_FALLBACK, + "could not load %s, and no fallback was found\n", + URI); + } + + /* + * Cleanup + */ + if (URI != NULL) + xmlFree(URI); + if (parse != NULL) + xmlFree(parse); + if (href != NULL) + xmlFree(href); + if (base != NULL) + xmlFree(base); + return(0); +} + +/** + * xmlXIncludeIncludeNode: + * @ctxt: an XInclude context + * @nr: the node number + * + * Inplement the infoset replacement for the given node + * + * Returns 0 if substitution succeeded, -1 if some processing failed + */ +static int +xmlXIncludeIncludeNode(xmlXIncludeCtxtPtr ctxt, int nr) { + xmlNodePtr cur, end, list, tmp; + + if (ctxt == NULL) + return(-1); + if ((nr < 0) || (nr >= ctxt->incNr)) + return(-1); + cur = ctxt->incTab[nr]->ref; + if (cur == NULL) + return(-1); + + /* + * If we stored an XPointer a late computation may be needed + */ + if ((ctxt->incTab[nr]->inc == NULL) && + (ctxt->incTab[nr]->xptr != NULL)) { + ctxt->incTab[nr]->inc = + xmlXIncludeCopyXPointer(ctxt, ctxt->doc, ctxt->doc, + ctxt->incTab[nr]->xptr); + xmlXPathFreeObject(ctxt->incTab[nr]->xptr); + ctxt->incTab[nr]->xptr = NULL; + } + list = ctxt->incTab[nr]->inc; + ctxt->incTab[nr]->inc = NULL; + + /* + * Check against the risk of generating a multi-rooted document + */ + if ((cur->parent != NULL) && + (cur->parent->type != XML_ELEMENT_NODE)) { + int nb_elem = 0; + + tmp = list; + while (tmp != NULL) { + if (tmp->type == XML_ELEMENT_NODE) + nb_elem++; + tmp = tmp->next; + } + if (nb_elem > 1) { + xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref, + XML_XINCLUDE_MULTIPLE_ROOT, + "XInclude error: would result in multiple root nodes\n", + NULL); + return(-1); + } + } + + if (ctxt->parseFlags & XML_PARSE_NOXINCNODE) { + /* + * Add the list of nodes + */ + while (list != NULL) { + end = list; + list = list->next; + + xmlAddPrevSibling(cur, end); + } + xmlUnlinkNode(cur); + xmlFreeNode(cur); + } else { + /* + * Change the current node as an XInclude start one, and add an + * XInclude end one + */ + cur->type = XML_XINCLUDE_START; + end = xmlNewDocNode(cur->doc, cur->ns, cur->name, NULL); + if (end == NULL) { + xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref, + XML_XINCLUDE_BUILD_FAILED, + "failed to build node\n", NULL); + return(-1); + } + end->type = XML_XINCLUDE_END; + xmlAddNextSibling(cur, end); + + /* + * Add the list of nodes + */ + while (list != NULL) { + cur = list; + list = list->next; + + xmlAddPrevSibling(end, cur); + } + } + + + return(0); +} + +/** + * xmlXIncludeTestNode: + * @ctxt: the XInclude processing context + * @node: an XInclude node + * + * test if the node is an XInclude node + * + * Returns 1 true, 0 otherwise + */ +static int +xmlXIncludeTestNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node) { + if (node == NULL) + return(0); + if (node->type != XML_ELEMENT_NODE) + return(0); + if (node->ns == NULL) + return(0); + if ((xmlStrEqual(node->ns->href, XINCLUDE_NS)) || + (xmlStrEqual(node->ns->href, XINCLUDE_OLD_NS))) { + if (xmlStrEqual(node->ns->href, XINCLUDE_OLD_NS)) { + if (ctxt->legacy == 0) { +#if 0 /* wait for the XML Core Working Group to get something stable ! */ + xmlXIncludeWarn(ctxt, node, XML_XINCLUDE_DEPRECATED_NS, + "Deprecated XInclude namespace found, use %s", + XINCLUDE_NS); +#endif + ctxt->legacy = 1; + } + } + if (xmlStrEqual(node->name, XINCLUDE_NODE)) { + xmlNodePtr child = node->children; + int nb_fallback = 0; + + while (child != NULL) { + if ((child->type == XML_ELEMENT_NODE) && + (child->ns != NULL) && + ((xmlStrEqual(child->ns->href, XINCLUDE_NS)) || + (xmlStrEqual(child->ns->href, XINCLUDE_OLD_NS)))) { + if (xmlStrEqual(child->name, XINCLUDE_NODE)) { + xmlXIncludeErr(ctxt, node, + XML_XINCLUDE_INCLUDE_IN_INCLUDE, + "%s has an 'include' child\n", + XINCLUDE_NODE); + return(0); + } + if (xmlStrEqual(child->name, XINCLUDE_FALLBACK)) { + nb_fallback++; + } + } + child = child->next; + } + if (nb_fallback > 1) { + xmlXIncludeErr(ctxt, node, XML_XINCLUDE_FALLBACKS_IN_INCLUDE, + "%s has multiple fallback children\n", + XINCLUDE_NODE); + return(0); + } + return(1); + } + if (xmlStrEqual(node->name, XINCLUDE_FALLBACK)) { + if ((node->parent == NULL) || + (node->parent->type != XML_ELEMENT_NODE) || + (node->parent->ns == NULL) || + ((!xmlStrEqual(node->parent->ns->href, XINCLUDE_NS)) && + (!xmlStrEqual(node->parent->ns->href, XINCLUDE_OLD_NS))) || + (!xmlStrEqual(node->parent->name, XINCLUDE_NODE))) { + xmlXIncludeErr(ctxt, node, + XML_XINCLUDE_FALLBACK_NOT_IN_INCLUDE, + "%s is not the child of an 'include'\n", + XINCLUDE_FALLBACK); + } + } + } + return(0); +} + +/** + * xmlXIncludeDoProcess: + * @ctxt: the XInclude processing context + * @doc: an XML document + * @tree: the top of the tree to process + * + * Implement the XInclude substitution on the XML document @doc + * + * Returns 0 if no substitution were done, -1 if some processing failed + * or the number of substitutions done. + */ +static int +xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr tree) { + xmlNodePtr cur; + int ret = 0; + int i, start; + + if ((doc == NULL) || (tree == NULL)) + return(-1); + if (ctxt == NULL) + return(-1); + + if (doc->URL != NULL) { + ret = xmlXIncludeURLPush(ctxt, doc->URL); + if (ret < 0) + return(-1); + } + start = ctxt->incNr; + + /* + * First phase: lookup the elements in the document + */ + cur = tree; + if (xmlXIncludeTestNode(ctxt, cur) == 1) + xmlXIncludePreProcessNode(ctxt, cur); + while ((cur != NULL) && (cur != tree->parent)) { + /* TODO: need to work on entities -> stack */ + if ((cur->children != NULL) && + (cur->children->type != XML_ENTITY_DECL) && + (cur->children->type != XML_XINCLUDE_START) && + (cur->children->type != XML_XINCLUDE_END)) { + cur = cur->children; + if (xmlXIncludeTestNode(ctxt, cur)) + xmlXIncludePreProcessNode(ctxt, cur); + } else if (cur->next != NULL) { + cur = cur->next; + if (xmlXIncludeTestNode(ctxt, cur)) + xmlXIncludePreProcessNode(ctxt, cur); + } else { + if (cur == tree) + break; + do { + cur = cur->parent; + if ((cur == NULL) || (cur == tree->parent)) + break; /* do */ + if (cur->next != NULL) { + cur = cur->next; + if (xmlXIncludeTestNode(ctxt, cur)) + xmlXIncludePreProcessNode(ctxt, cur); + break; /* do */ + } + } while (cur != NULL); + } + } + + /* + * Second Phase : collect the infosets fragments + */ + for (i = start;i < ctxt->incNr; i++) { + xmlXIncludeLoadNode(ctxt, i); + ret++; + } + + /* + * Third phase: extend the original document infoset. + * + * Originally we bypassed the inclusion if there were any errors + * encountered on any of the XIncludes. A bug was raised (bug + * 132588) requesting that we output the XIncludes without error, + * so the check for inc!=NULL || xptr!=NULL was put in. This may + * give some other problems in the future, but for now it seems to + * work ok. + * + */ + for (i = ctxt->incBase;i < ctxt->incNr; i++) { + if ((ctxt->incTab[i]->inc != NULL) || + (ctxt->incTab[i]->xptr != NULL) || + (ctxt->incTab[i]->emptyFb != 0)) /* (empty fallback) */ + xmlXIncludeIncludeNode(ctxt, i); + } + + if (doc->URL != NULL) + xmlXIncludeURLPop(ctxt); + return(ret); +} + +/** + * xmlXIncludeSetFlags: + * @ctxt: an XInclude processing context + * @flags: a set of xmlParserOption used for parsing XML includes + * + * Set the flags used for further processing of XML resources. + * + * Returns 0 in case of success and -1 in case of error. + */ +int +xmlXIncludeSetFlags(xmlXIncludeCtxtPtr ctxt, int flags) { + if (ctxt == NULL) + return(-1); + ctxt->parseFlags = flags; + return(0); +} + +/** + * xmlXIncludeProcessFlagsData: + * @doc: an XML document + * @flags: a set of xmlParserOption used for parsing XML includes + * @data: application data that will be passed to the parser context + * in the _private field of the parser context(s) + * + * Implement the XInclude substitution on the XML document @doc + * + * Returns 0 if no substitution were done, -1 if some processing failed + * or the number of substitutions done. + */ +int +xmlXIncludeProcessFlagsData(xmlDocPtr doc, int flags, void *data) { + xmlXIncludeCtxtPtr ctxt; + xmlNodePtr tree; + int ret = 0; + + if (doc == NULL) + return(-1); + tree = xmlDocGetRootElement(doc); + if (tree == NULL) + return(-1); + ctxt = xmlXIncludeNewContext(doc); + if (ctxt == NULL) + return(-1); + ctxt->_private = data; + ctxt->base = xmlStrdup((xmlChar *)doc->URL); + xmlXIncludeSetFlags(ctxt, flags); + ret = xmlXIncludeDoProcess(ctxt, doc, tree); + if ((ret >= 0) && (ctxt->nbErrors > 0)) + ret = -1; + + xmlXIncludeFreeContext(ctxt); + return(ret); +} + +/** + * xmlXIncludeProcessFlags: + * @doc: an XML document + * @flags: a set of xmlParserOption used for parsing XML includes + * + * Implement the XInclude substitution on the XML document @doc + * + * Returns 0 if no substitution were done, -1 if some processing failed + * or the number of substitutions done. + */ +int +xmlXIncludeProcessFlags(xmlDocPtr doc, int flags) { + return xmlXIncludeProcessFlagsData(doc, flags, NULL); +} + +/** + * xmlXIncludeProcess: + * @doc: an XML document + * + * Implement the XInclude substitution on the XML document @doc + * + * Returns 0 if no substitution were done, -1 if some processing failed + * or the number of substitutions done. + */ +int +xmlXIncludeProcess(xmlDocPtr doc) { + return(xmlXIncludeProcessFlags(doc, 0)); +} + +/** + * xmlXIncludeProcessTreeFlags: + * @tree: a node in an XML document + * @flags: a set of xmlParserOption used for parsing XML includes + * + * Implement the XInclude substitution for the given subtree + * + * Returns 0 if no substitution were done, -1 if some processing failed + * or the number of substitutions done. + */ +int +xmlXIncludeProcessTreeFlags(xmlNodePtr tree, int flags) { + xmlXIncludeCtxtPtr ctxt; + int ret = 0; + + if ((tree == NULL) || (tree->doc == NULL)) + return(-1); + ctxt = xmlXIncludeNewContext(tree->doc); + if (ctxt == NULL) + return(-1); + ctxt->base = xmlNodeGetBase(tree->doc, tree); + xmlXIncludeSetFlags(ctxt, flags); + ret = xmlXIncludeDoProcess(ctxt, tree->doc, tree); + if ((ret >= 0) && (ctxt->nbErrors > 0)) + ret = -1; + + xmlXIncludeFreeContext(ctxt); + return(ret); +} + +/** + * xmlXIncludeProcessTree: + * @tree: a node in an XML document + * + * Implement the XInclude substitution for the given subtree + * + * Returns 0 if no substitution were done, -1 if some processing failed + * or the number of substitutions done. + */ +int +xmlXIncludeProcessTree(xmlNodePtr tree) { + return(xmlXIncludeProcessTreeFlags(tree, 0)); +} + +/** + * xmlXIncludeProcessNode: + * @ctxt: an existing XInclude context + * @node: a node in an XML document + * + * Implement the XInclude substitution for the given subtree reusing + * the informations and data coming from the given context. + * + * Returns 0 if no substitution were done, -1 if some processing failed + * or the number of substitutions done. + */ +int +xmlXIncludeProcessNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node) { + int ret = 0; + + if ((node == NULL) || (node->doc == NULL) || (ctxt == NULL)) + return(-1); + ret = xmlXIncludeDoProcess(ctxt, node->doc, node); + if ((ret >= 0) && (ctxt->nbErrors > 0)) + ret = -1; + return(ret); +} + +#else /* !LIBXML_XINCLUDE_ENABLED */ +#endif +#define bottom_xinclude +#include "elfgcchack.h" diff --git a/gettext-tools/gnulib-lib/libxml/xinclude.in.h b/gettext-tools/gnulib-lib/libxml/xinclude.in.h new file mode 100644 index 0000000..ba9c9b5 --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/xinclude.in.h @@ -0,0 +1,125 @@ +/* + * Summary: implementation of XInclude + * Description: API to handle XInclude processing, + * implements the + * World Wide Web Consortium Last Call Working Draft 10 November 2003 + * http://www.w3.org/TR/2003/WD-xinclude-20031110 + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + +#ifndef __XML_XINCLUDE_H__ +#define __XML_XINCLUDE_H__ + +#include +#include + +#ifdef LIBXML_XINCLUDE_ENABLED + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * XINCLUDE_NS: + * + * Macro defining the Xinclude namespace: http://www.w3.org/2003/XInclude + */ +#define XINCLUDE_NS (const xmlChar *) "http://www.w3.org/2003/XInclude" +/** + * XINCLUDE_OLD_NS: + * + * Macro defining the draft Xinclude namespace: http://www.w3.org/2001/XInclude + */ +#define XINCLUDE_OLD_NS (const xmlChar *) "http://www.w3.org/2001/XInclude" +/** + * XINCLUDE_NODE: + * + * Macro defining "include" + */ +#define XINCLUDE_NODE (const xmlChar *) "include" +/** + * XINCLUDE_FALLBACK: + * + * Macro defining "fallback" + */ +#define XINCLUDE_FALLBACK (const xmlChar *) "fallback" +/** + * XINCLUDE_HREF: + * + * Macro defining "href" + */ +#define XINCLUDE_HREF (const xmlChar *) "href" +/** + * XINCLUDE_PARSE: + * + * Macro defining "parse" + */ +#define XINCLUDE_PARSE (const xmlChar *) "parse" +/** + * XINCLUDE_PARSE_XML: + * + * Macro defining "xml" + */ +#define XINCLUDE_PARSE_XML (const xmlChar *) "xml" +/** + * XINCLUDE_PARSE_TEXT: + * + * Macro defining "text" + */ +#define XINCLUDE_PARSE_TEXT (const xmlChar *) "text" +/** + * XINCLUDE_PARSE_ENCODING: + * + * Macro defining "encoding" + */ +#define XINCLUDE_PARSE_ENCODING (const xmlChar *) "encoding" +/** + * XINCLUDE_PARSE_XPOINTER: + * + * Macro defining "xpointer" + */ +#define XINCLUDE_PARSE_XPOINTER (const xmlChar *) "xpointer" + +typedef struct _xmlXIncludeCtxt xmlXIncludeCtxt; +typedef xmlXIncludeCtxt *xmlXIncludeCtxtPtr; + +/* + * standalone processing + */ +XMLPUBFUN int XMLCALL + xmlXIncludeProcess (xmlDocPtr doc); +XMLPUBFUN int XMLCALL + xmlXIncludeProcessFlags (xmlDocPtr doc, + int flags); +XMLPUBFUN int XMLCALL + xmlXIncludeProcessFlagsData(xmlDocPtr doc, + int flags, + void *data); +XMLPUBFUN int XMLCALL + xmlXIncludeProcessTree (xmlNodePtr tree); +XMLPUBFUN int XMLCALL + xmlXIncludeProcessTreeFlags(xmlNodePtr tree, + int flags); +/* + * contextual processing + */ +XMLPUBFUN xmlXIncludeCtxtPtr XMLCALL + xmlXIncludeNewContext (xmlDocPtr doc); +XMLPUBFUN int XMLCALL + xmlXIncludeSetFlags (xmlXIncludeCtxtPtr ctxt, + int flags); +XMLPUBFUN void XMLCALL + xmlXIncludeFreeContext (xmlXIncludeCtxtPtr ctxt); +XMLPUBFUN int XMLCALL + xmlXIncludeProcessNode (xmlXIncludeCtxtPtr ctxt, + xmlNodePtr tree); +#ifdef __cplusplus +} +#endif + +#endif /* LIBXML_XINCLUDE_ENABLED */ + +#endif /* __XML_XINCLUDE_H__ */ diff --git a/gettext-tools/gnulib-lib/libxml/xlink.c b/gettext-tools/gnulib-lib/libxml/xlink.c new file mode 100644 index 0000000..0d9be73 --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/xlink.c @@ -0,0 +1,183 @@ +/* + * xlink.c : implementation of the hyperlinks detection module + * This version supports both XML XLinks and HTML simple links + * + * See Copyright for the status of this software. + * + * daniel@veillard.com + */ + + +#define IN_LIBXML +#include "libxml.h" + +#ifdef LIBXML_XPTR_ENABLED +#include /* for memset() only */ +#ifdef HAVE_CTYPE_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_SYS_STAT_H +#include +#endif +#ifdef HAVE_FCNTL_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_ZLIB_H +#include +#endif + +#include +#include +#include +#include +#include +#include + +#define XLINK_NAMESPACE (BAD_CAST "http://www.w3.org/1999/xlink/namespace/") +#define XHTML_NAMESPACE (BAD_CAST "http://www.w3.org/1999/xhtml/") + +/**************************************************************** + * * + * Default setting and related functions * + * * + ****************************************************************/ + +static xlinkHandlerPtr xlinkDefaultHandler = NULL; +static xlinkNodeDetectFunc xlinkDefaultDetect = NULL; + +/** + * xlinkGetDefaultHandler: + * + * Get the default xlink handler. + * + * Returns the current xlinkHandlerPtr value. + */ +xlinkHandlerPtr +xlinkGetDefaultHandler(void) { + return(xlinkDefaultHandler); +} + + +/** + * xlinkSetDefaultHandler: + * @handler: the new value for the xlink handler block + * + * Set the default xlink handlers + */ +void +xlinkSetDefaultHandler(xlinkHandlerPtr handler) { + xlinkDefaultHandler = handler; +} + +/** + * xlinkGetDefaultDetect: + * + * Get the default xlink detection routine + * + * Returns the current function or NULL; + */ +xlinkNodeDetectFunc +xlinkGetDefaultDetect (void) { + return(xlinkDefaultDetect); +} + +/** + * xlinkSetDefaultDetect: + * @func: pointer to the new detection routine. + * + * Set the default xlink detection routine + */ +void +xlinkSetDefaultDetect (xlinkNodeDetectFunc func) { + xlinkDefaultDetect = func; +} + +/**************************************************************** + * * + * The detection routines * + * * + ****************************************************************/ + + +/** + * xlinkIsLink: + * @doc: the document containing the node + * @node: the node pointer itself + * + * Check whether the given node carries the attributes needed + * to be a link element (or is one of the linking elements issued + * from the (X)HTML DtDs). + * This routine don't try to do full checking of the link validity + * but tries to detect and return the appropriate link type. + * + * Returns the xlinkType of the node (XLINK_TYPE_NONE if there is no + * link detected. + */ +xlinkType +xlinkIsLink (xmlDocPtr doc, xmlNodePtr node) { + xmlChar *type = NULL, *role = NULL; + xlinkType ret = XLINK_TYPE_NONE; + + if (node == NULL) return(XLINK_TYPE_NONE); + if (doc == NULL) doc = node->doc; + if ((doc != NULL) && (doc->type == XML_HTML_DOCUMENT_NODE)) { + /* + * This is an HTML document. + */ + } else if ((node->ns != NULL) && + (xmlStrEqual(node->ns->href, XHTML_NAMESPACE))) { + /* + * !!!! We really need an IS_XHTML_ELEMENT function from HTMLtree.h @@@ + */ + /* + * This is an XHTML element within an XML document + * Check whether it's one of the element able to carry links + * and in that case if it holds the attributes. + */ + } + + /* + * We don't prevent a-priori having XML Linking constructs on + * XHTML elements + */ + type = xmlGetNsProp(node, BAD_CAST"type", XLINK_NAMESPACE); + if (type != NULL) { + if (xmlStrEqual(type, BAD_CAST "simple")) { + ret = XLINK_TYPE_SIMPLE; + } if (xmlStrEqual(type, BAD_CAST "extended")) { + role = xmlGetNsProp(node, BAD_CAST "role", XLINK_NAMESPACE); + if (role != NULL) { + xmlNsPtr xlink; + xlink = xmlSearchNs(doc, node, XLINK_NAMESPACE); + if (xlink == NULL) { + /* Humm, fallback method */ + if (xmlStrEqual(role, BAD_CAST"xlink:external-linkset")) + ret = XLINK_TYPE_EXTENDED_SET; + } else { + xmlChar buf[200]; + snprintf((char *) buf, sizeof(buf), "%s:external-linkset", + (char *) xlink->prefix); + buf[sizeof(buf) - 1] = 0; + if (xmlStrEqual(role, buf)) + ret = XLINK_TYPE_EXTENDED_SET; + + } + + } + ret = XLINK_TYPE_EXTENDED; + } + } + + if (type != NULL) xmlFree(type); + if (role != NULL) xmlFree(role); + return(ret); +} +#endif /* LIBXML_XPTR_ENABLED */ +#define bottom_xlink +#include "elfgcchack.h" diff --git a/gettext-tools/gnulib-lib/libxml/xlink.in.h b/gettext-tools/gnulib-lib/libxml/xlink.in.h new file mode 100644 index 0000000..083c7ed --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/xlink.in.h @@ -0,0 +1,189 @@ +/* + * Summary: unfinished XLink detection module + * Description: unfinished XLink detection module + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + +#ifndef __XML_XLINK_H__ +#define __XML_XLINK_H__ + +#include +#include + +#ifdef LIBXML_XPTR_ENABLED + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Various defines for the various Link properties. + * + * NOTE: the link detection layer will try to resolve QName expansion + * of namespaces. If "foo" is the prefix for "http://foo.com/" + * then the link detection layer will expand role="foo:myrole" + * to "http://foo.com/:myrole". + * NOTE: the link detection layer will expand URI-Refences found on + * href attributes by using the base mechanism if found. + */ +typedef xmlChar *xlinkHRef; +typedef xmlChar *xlinkRole; +typedef xmlChar *xlinkTitle; + +typedef enum { + XLINK_TYPE_NONE = 0, + XLINK_TYPE_SIMPLE, + XLINK_TYPE_EXTENDED, + XLINK_TYPE_EXTENDED_SET +} xlinkType; + +typedef enum { + XLINK_SHOW_NONE = 0, + XLINK_SHOW_NEW, + XLINK_SHOW_EMBED, + XLINK_SHOW_REPLACE +} xlinkShow; + +typedef enum { + XLINK_ACTUATE_NONE = 0, + XLINK_ACTUATE_AUTO, + XLINK_ACTUATE_ONREQUEST +} xlinkActuate; + +/** + * xlinkNodeDetectFunc: + * @ctx: user data pointer + * @node: the node to check + * + * This is the prototype for the link detection routine. + * It calls the default link detection callbacks upon link detection. + */ +typedef void (*xlinkNodeDetectFunc) (void *ctx, xmlNodePtr node); + +/* + * The link detection module interact with the upper layers using + * a set of callback registered at parsing time. + */ + +/** + * xlinkSimpleLinkFunk: + * @ctx: user data pointer + * @node: the node carrying the link + * @href: the target of the link + * @role: the role string + * @title: the link title + * + * This is the prototype for a simple link detection callback. + */ +typedef void +(*xlinkSimpleLinkFunk) (void *ctx, + xmlNodePtr node, + const xlinkHRef href, + const xlinkRole role, + const xlinkTitle title); + +/** + * xlinkExtendedLinkFunk: + * @ctx: user data pointer + * @node: the node carrying the link + * @nbLocators: the number of locators detected on the link + * @hrefs: pointer to the array of locator hrefs + * @roles: pointer to the array of locator roles + * @nbArcs: the number of arcs detected on the link + * @from: pointer to the array of source roles found on the arcs + * @to: pointer to the array of target roles found on the arcs + * @show: array of values for the show attributes found on the arcs + * @actuate: array of values for the actuate attributes found on the arcs + * @nbTitles: the number of titles detected on the link + * @title: array of titles detected on the link + * @langs: array of xml:lang values for the titles + * + * This is the prototype for a extended link detection callback. + */ +typedef void +(*xlinkExtendedLinkFunk)(void *ctx, + xmlNodePtr node, + int nbLocators, + const xlinkHRef *hrefs, + const xlinkRole *roles, + int nbArcs, + const xlinkRole *from, + const xlinkRole *to, + xlinkShow *show, + xlinkActuate *actuate, + int nbTitles, + const xlinkTitle *titles, + const xmlChar **langs); + +/** + * xlinkExtendedLinkSetFunk: + * @ctx: user data pointer + * @node: the node carrying the link + * @nbLocators: the number of locators detected on the link + * @hrefs: pointer to the array of locator hrefs + * @roles: pointer to the array of locator roles + * @nbTitles: the number of titles detected on the link + * @title: array of titles detected on the link + * @langs: array of xml:lang values for the titles + * + * This is the prototype for a extended link set detection callback. + */ +typedef void +(*xlinkExtendedLinkSetFunk) (void *ctx, + xmlNodePtr node, + int nbLocators, + const xlinkHRef *hrefs, + const xlinkRole *roles, + int nbTitles, + const xlinkTitle *titles, + const xmlChar **langs); + +/** + * This is the structure containing a set of Links detection callbacks. + * + * There is no default xlink callbacks, if one want to get link + * recognition activated, those call backs must be provided before parsing. + */ +typedef struct _xlinkHandler xlinkHandler; +typedef xlinkHandler *xlinkHandlerPtr; +struct _xlinkHandler { + xlinkSimpleLinkFunk simple; + xlinkExtendedLinkFunk extended; + xlinkExtendedLinkSetFunk set; +}; + +/* + * The default detection routine, can be overridden, they call the default + * detection callbacks. + */ + +XMLPUBFUN xlinkNodeDetectFunc XMLCALL + xlinkGetDefaultDetect (void); +XMLPUBFUN void XMLCALL + xlinkSetDefaultDetect (xlinkNodeDetectFunc func); + +/* + * Routines to set/get the default handlers. + */ +XMLPUBFUN xlinkHandlerPtr XMLCALL + xlinkGetDefaultHandler (void); +XMLPUBFUN void XMLCALL + xlinkSetDefaultHandler (xlinkHandlerPtr handler); + +/* + * Link detection module itself. + */ +XMLPUBFUN xlinkType XMLCALL + xlinkIsLink (xmlDocPtr doc, + xmlNodePtr node); + +#ifdef __cplusplus +} +#endif + +#endif /* LIBXML_XPTR_ENABLED */ + +#endif /* __XML_XLINK_H__ */ diff --git a/gettext-tools/gnulib-lib/libxml/xmlIO.c b/gettext-tools/gnulib-lib/libxml/xmlIO.c new file mode 100644 index 0000000..90db848 --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/xmlIO.c @@ -0,0 +1,3850 @@ +/* + * xmlIO.c : implementation of the I/O interfaces used by the parser + * + * See Copyright for the status of this software. + * + * daniel@veillard.com + * + * 14 Nov 2000 ht - for VMS, truncated name of long functions to under 32 char + */ + +#define IN_LIBXML +#include "libxml.h" + +#include +#ifdef HAVE_ERRNO_H +#include +#endif + + +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_STAT_H +#include +#endif +#ifdef HAVE_FCNTL_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_ZLIB_H +#include +#endif + +#ifdef WIN32 +#include +#endif + +/* Figure a portable way to know if a file is a directory. */ +#ifndef HAVE_STAT +# ifdef HAVE__STAT + /* MS C library seems to define stat and _stat. The definition + is identical. Still, mapping them to each other causes a warning. */ +# ifndef _MSC_VER +# define stat(x,y) _stat(x,y) +# endif +# define HAVE_STAT +# endif +#else +# ifdef HAVE__STAT +# if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__) +# define stat _stat +# endif +# endif +#endif +#ifdef HAVE_STAT +# ifndef S_ISDIR +# ifdef _S_ISDIR +# define S_ISDIR(x) _S_ISDIR(x) +# else +# ifdef S_IFDIR +# ifndef S_IFMT +# ifdef _S_IFMT +# define S_IFMT _S_IFMT +# endif +# endif +# ifdef S_IFMT +# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) +# endif +# endif +# endif +# endif +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef LIBXML_CATALOG_ENABLED +#include +#endif +#include + +/* #define VERBOSE_FAILURE */ +/* #define DEBUG_EXTERNAL_ENTITIES */ +/* #define DEBUG_INPUT */ + +#ifdef DEBUG_INPUT +#define MINLEN 40 +#else +#define MINLEN 4000 +#endif + +/* + * Input I/O callback sets + */ +typedef struct _xmlInputCallback { + xmlInputMatchCallback matchcallback; + xmlInputOpenCallback opencallback; + xmlInputReadCallback readcallback; + xmlInputCloseCallback closecallback; +} xmlInputCallback; + +#define MAX_INPUT_CALLBACK 15 + +static xmlInputCallback xmlInputCallbackTable[MAX_INPUT_CALLBACK]; +static int xmlInputCallbackNr = 0; +static int xmlInputCallbackInitialized = 0; + +#ifdef LIBXML_OUTPUT_ENABLED +/* + * Output I/O callback sets + */ +typedef struct _xmlOutputCallback { + xmlOutputMatchCallback matchcallback; + xmlOutputOpenCallback opencallback; + xmlOutputWriteCallback writecallback; + xmlOutputCloseCallback closecallback; +} xmlOutputCallback; + +#define MAX_OUTPUT_CALLBACK 15 + +static xmlOutputCallback xmlOutputCallbackTable[MAX_OUTPUT_CALLBACK]; +static int xmlOutputCallbackNr = 0; +static int xmlOutputCallbackInitialized = 0; +#endif /* LIBXML_OUTPUT_ENABLED */ + +/************************************************************************ + * * + * Tree memory error handler * + * * + ************************************************************************/ + +static const char *IOerr[] = { + "Unknown IO error", /* UNKNOWN */ + "Permission denied", /* EACCES */ + "Resource temporarily unavailable",/* EAGAIN */ + "Bad file descriptor", /* EBADF */ + "Bad message", /* EBADMSG */ + "Resource busy", /* EBUSY */ + "Operation canceled", /* ECANCELED */ + "No child processes", /* ECHILD */ + "Resource deadlock avoided",/* EDEADLK */ + "Domain error", /* EDOM */ + "File exists", /* EEXIST */ + "Bad address", /* EFAULT */ + "File too large", /* EFBIG */ + "Operation in progress", /* EINPROGRESS */ + "Interrupted function call",/* EINTR */ + "Invalid argument", /* EINVAL */ + "Input/output error", /* EIO */ + "Is a directory", /* EISDIR */ + "Too many open files", /* EMFILE */ + "Too many links", /* EMLINK */ + "Inappropriate message buffer length",/* EMSGSIZE */ + "Filename too long", /* ENAMETOOLONG */ + "Too many open files in system",/* ENFILE */ + "No such device", /* ENODEV */ + "No such file or directory",/* ENOENT */ + "Exec format error", /* ENOEXEC */ + "No locks available", /* ENOLCK */ + "Not enough space", /* ENOMEM */ + "No space left on device", /* ENOSPC */ + "Function not implemented", /* ENOSYS */ + "Not a directory", /* ENOTDIR */ + "Directory not empty", /* ENOTEMPTY */ + "Not supported", /* ENOTSUP */ + "Inappropriate I/O control operation",/* ENOTTY */ + "No such device or address",/* ENXIO */ + "Operation not permitted", /* EPERM */ + "Broken pipe", /* EPIPE */ + "Result too large", /* ERANGE */ + "Read-only file system", /* EROFS */ + "Invalid seek", /* ESPIPE */ + "No such process", /* ESRCH */ + "Operation timed out", /* ETIMEDOUT */ + "Improper link", /* EXDEV */ + "Attempt to load network entity %s", /* XML_IO_NETWORK_ATTEMPT */ + "encoder error", /* XML_IO_ENCODER */ + "flush error", + "write error", + "no input", + "buffer full", + "loading error", + "not a socket", /* ENOTSOCK */ + "already connected", /* EISCONN */ + "connection refused", /* ECONNREFUSED */ + "unreachable network", /* ENETUNREACH */ + "adddress in use", /* EADDRINUSE */ + "already in use", /* EALREADY */ + "unknown address familly", /* EAFNOSUPPORT */ +}; + +#if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__) +/** + * __xmlIOWin32UTF8ToWChar: + * @u8String: uft-8 string + * + * Convert a string from utf-8 to wchar (WINDOWS ONLY!) + */ +static wchar_t * +__xmlIOWin32UTF8ToWChar(const char *u8String) +{ + wchar_t *wString = NULL; + + if (u8String) { + int wLen = + MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, u8String, + -1, NULL, 0); + if (wLen) { + wString = xmlMalloc(wLen * sizeof(wchar_t)); + if (wString) { + if (MultiByteToWideChar + (CP_UTF8, 0, u8String, -1, wString, wLen) == 0) { + xmlFree(wString); + wString = NULL; + } + } + } + } + + return wString; +} +#endif + +/** + * xmlIOErrMemory: + * @extra: extra informations + * + * Handle an out of memory condition + */ +static void +xmlIOErrMemory(const char *extra) +{ + __xmlSimpleError(XML_FROM_IO, XML_ERR_NO_MEMORY, NULL, NULL, extra); +} + +/** + * __xmlIOErr: + * @code: the error number + * @ + * @extra: extra informations + * + * Handle an I/O error + */ +void +__xmlIOErr(int domain, int code, const char *extra) +{ + unsigned int idx; + + if (code == 0) { +#ifdef HAVE_ERRNO_H + if (errno == 0) code = 0; +#ifdef EACCES + else if (errno == EACCES) code = XML_IO_EACCES; +#endif +#ifdef EAGAIN + else if (errno == EAGAIN) code = XML_IO_EAGAIN; +#endif +#ifdef EBADF + else if (errno == EBADF) code = XML_IO_EBADF; +#endif +#ifdef EBADMSG + else if (errno == EBADMSG) code = XML_IO_EBADMSG; +#endif +#ifdef EBUSY + else if (errno == EBUSY) code = XML_IO_EBUSY; +#endif +#ifdef ECANCELED + else if (errno == ECANCELED) code = XML_IO_ECANCELED; +#endif +#ifdef ECHILD + else if (errno == ECHILD) code = XML_IO_ECHILD; +#endif +#ifdef EDEADLK + else if (errno == EDEADLK) code = XML_IO_EDEADLK; +#endif +#ifdef EDOM + else if (errno == EDOM) code = XML_IO_EDOM; +#endif +#ifdef EEXIST + else if (errno == EEXIST) code = XML_IO_EEXIST; +#endif +#ifdef EFAULT + else if (errno == EFAULT) code = XML_IO_EFAULT; +#endif +#ifdef EFBIG + else if (errno == EFBIG) code = XML_IO_EFBIG; +#endif +#ifdef EINPROGRESS + else if (errno == EINPROGRESS) code = XML_IO_EINPROGRESS; +#endif +#ifdef EINTR + else if (errno == EINTR) code = XML_IO_EINTR; +#endif +#ifdef EINVAL + else if (errno == EINVAL) code = XML_IO_EINVAL; +#endif +#ifdef EIO + else if (errno == EIO) code = XML_IO_EIO; +#endif +#ifdef EISDIR + else if (errno == EISDIR) code = XML_IO_EISDIR; +#endif +#ifdef EMFILE + else if (errno == EMFILE) code = XML_IO_EMFILE; +#endif +#ifdef EMLINK + else if (errno == EMLINK) code = XML_IO_EMLINK; +#endif +#ifdef EMSGSIZE + else if (errno == EMSGSIZE) code = XML_IO_EMSGSIZE; +#endif +#ifdef ENAMETOOLONG + else if (errno == ENAMETOOLONG) code = XML_IO_ENAMETOOLONG; +#endif +#ifdef ENFILE + else if (errno == ENFILE) code = XML_IO_ENFILE; +#endif +#ifdef ENODEV + else if (errno == ENODEV) code = XML_IO_ENODEV; +#endif +#ifdef ENOENT + else if (errno == ENOENT) code = XML_IO_ENOENT; +#endif +#ifdef ENOEXEC + else if (errno == ENOEXEC) code = XML_IO_ENOEXEC; +#endif +#ifdef ENOLCK + else if (errno == ENOLCK) code = XML_IO_ENOLCK; +#endif +#ifdef ENOMEM + else if (errno == ENOMEM) code = XML_IO_ENOMEM; +#endif +#ifdef ENOSPC + else if (errno == ENOSPC) code = XML_IO_ENOSPC; +#endif +#ifdef ENOSYS + else if (errno == ENOSYS) code = XML_IO_ENOSYS; +#endif +#ifdef ENOTDIR + else if (errno == ENOTDIR) code = XML_IO_ENOTDIR; +#endif +#ifdef ENOTEMPTY + else if (errno == ENOTEMPTY) code = XML_IO_ENOTEMPTY; +#endif +#ifdef ENOTSUP + else if (errno == ENOTSUP) code = XML_IO_ENOTSUP; +#endif +#ifdef ENOTTY + else if (errno == ENOTTY) code = XML_IO_ENOTTY; +#endif +#ifdef ENXIO + else if (errno == ENXIO) code = XML_IO_ENXIO; +#endif +#ifdef EPERM + else if (errno == EPERM) code = XML_IO_EPERM; +#endif +#ifdef EPIPE + else if (errno == EPIPE) code = XML_IO_EPIPE; +#endif +#ifdef ERANGE + else if (errno == ERANGE) code = XML_IO_ERANGE; +#endif +#ifdef EROFS + else if (errno == EROFS) code = XML_IO_EROFS; +#endif +#ifdef ESPIPE + else if (errno == ESPIPE) code = XML_IO_ESPIPE; +#endif +#ifdef ESRCH + else if (errno == ESRCH) code = XML_IO_ESRCH; +#endif +#ifdef ETIMEDOUT + else if (errno == ETIMEDOUT) code = XML_IO_ETIMEDOUT; +#endif +#ifdef EXDEV + else if (errno == EXDEV) code = XML_IO_EXDEV; +#endif +#ifdef ENOTSOCK + else if (errno == ENOTSOCK) code = XML_IO_ENOTSOCK; +#endif +#ifdef EISCONN + else if (errno == EISCONN) code = XML_IO_EISCONN; +#endif +#ifdef ECONNREFUSED + else if (errno == ECONNREFUSED) code = XML_IO_ECONNREFUSED; +#endif +#ifdef ETIMEDOUT + else if (errno == ETIMEDOUT) code = XML_IO_ETIMEDOUT; +#endif +#ifdef ENETUNREACH + else if (errno == ENETUNREACH) code = XML_IO_ENETUNREACH; +#endif +#ifdef EADDRINUSE + else if (errno == EADDRINUSE) code = XML_IO_EADDRINUSE; +#endif +#ifdef EINPROGRESS + else if (errno == EINPROGRESS) code = XML_IO_EINPROGRESS; +#endif +#ifdef EALREADY + else if (errno == EALREADY) code = XML_IO_EALREADY; +#endif +#ifdef EAFNOSUPPORT + else if (errno == EAFNOSUPPORT) code = XML_IO_EAFNOSUPPORT; +#endif + else code = XML_IO_UNKNOWN; +#endif /* HAVE_ERRNO_H */ + } + idx = 0; + if (code >= XML_IO_UNKNOWN) idx = code - XML_IO_UNKNOWN; + if (idx >= (sizeof(IOerr) / sizeof(IOerr[0]))) idx = 0; + + __xmlSimpleError(domain, code, NULL, IOerr[idx], extra); +} + +/** + * xmlIOErr: + * @code: the error number + * @extra: extra informations + * + * Handle an I/O error + */ +static void +xmlIOErr(int code, const char *extra) +{ + __xmlIOErr(XML_FROM_IO, code, extra); +} + +/** + * __xmlLoaderErr: + * @ctx: the parser context + * @extra: extra informations + * + * Handle a resource access error + */ +void +__xmlLoaderErr(void *ctx, const char *msg, const char *filename) +{ + xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; + xmlStructuredErrorFunc schannel = NULL; + xmlGenericErrorFunc channel = NULL; + void *data = NULL; + xmlErrorLevel level = XML_ERR_ERROR; + + if ((ctxt != NULL) && (ctxt->disableSAX != 0) && + (ctxt->instate == XML_PARSER_EOF)) + return; + if ((ctxt != NULL) && (ctxt->sax != NULL)) { + if (ctxt->validate) { + channel = ctxt->sax->error; + level = XML_ERR_ERROR; + } else { + channel = ctxt->sax->warning; + level = XML_ERR_WARNING; + } + if (ctxt->sax->initialized == XML_SAX2_MAGIC) + schannel = ctxt->sax->serror; + data = ctxt->userData; + } + __xmlRaiseError(schannel, channel, data, ctxt, NULL, XML_FROM_IO, + XML_IO_LOAD_ERROR, level, NULL, 0, + filename, NULL, NULL, 0, 0, + msg, filename); + +} + +/************************************************************************ + * * + * Tree memory error handler * + * * + ************************************************************************/ +/** + * xmlNormalizeWindowsPath: + * @path: the input file path + * + * This function is obsolete. Please see xmlURIFromPath in uri.c for + * a better solution. + * + * Returns a canonicalized version of the path + */ +xmlChar * +xmlNormalizeWindowsPath(const xmlChar *path) +{ + return xmlCanonicPath(path); +} + +/** + * xmlCleanupInputCallbacks: + * + * clears the entire input callback table. this includes the + * compiled-in I/O. + */ +void +xmlCleanupInputCallbacks(void) +{ + int i; + + if (!xmlInputCallbackInitialized) + return; + + for (i = xmlInputCallbackNr - 1; i >= 0; i--) { + xmlInputCallbackTable[i].matchcallback = NULL; + xmlInputCallbackTable[i].opencallback = NULL; + xmlInputCallbackTable[i].readcallback = NULL; + xmlInputCallbackTable[i].closecallback = NULL; + } + + xmlInputCallbackNr = 0; + xmlInputCallbackInitialized = 0; +} + +/** + * xmlPopInputCallbacks: + * + * Clear the top input callback from the input stack. this includes the + * compiled-in I/O. + * + * Returns the number of input callback registered or -1 in case of error. + */ +int +xmlPopInputCallbacks(void) +{ + if (!xmlInputCallbackInitialized) + return(-1); + + if (xmlInputCallbackNr <= 0) + return(-1); + + xmlInputCallbackNr--; + xmlInputCallbackTable[xmlInputCallbackNr].matchcallback = NULL; + xmlInputCallbackTable[xmlInputCallbackNr].opencallback = NULL; + xmlInputCallbackTable[xmlInputCallbackNr].readcallback = NULL; + xmlInputCallbackTable[xmlInputCallbackNr].closecallback = NULL; + + return(xmlInputCallbackNr); +} + +#ifdef LIBXML_OUTPUT_ENABLED +/** + * xmlCleanupOutputCallbacks: + * + * clears the entire output callback table. this includes the + * compiled-in I/O callbacks. + */ +void +xmlCleanupOutputCallbacks(void) +{ + int i; + + if (!xmlOutputCallbackInitialized) + return; + + for (i = xmlOutputCallbackNr - 1; i >= 0; i--) { + xmlOutputCallbackTable[i].matchcallback = NULL; + xmlOutputCallbackTable[i].opencallback = NULL; + xmlOutputCallbackTable[i].writecallback = NULL; + xmlOutputCallbackTable[i].closecallback = NULL; + } + + xmlOutputCallbackNr = 0; + xmlOutputCallbackInitialized = 0; +} +#endif /* LIBXML_OUTPUT_ENABLED */ + +/************************************************************************ + * * + * Standard I/O for file accesses * + * * + ************************************************************************/ + +#if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__) + +/** + * xmlWrapOpenUtf8: + * @path: the path in utf-8 encoding + * @mode: type of access (0 - read, 1 - write) + * + * function opens the file specified by @path + * + */ +static FILE* +xmlWrapOpenUtf8(const char *path,int mode) +{ + FILE *fd = NULL; + wchar_t *wPath; + + wPath = __xmlIOWin32UTF8ToWChar(path); + if(wPath) + { + fd = _wfopen(wPath, mode ? L"wb" : L"rb"); + xmlFree(wPath); + } + /* maybe path in native encoding */ + if(fd == NULL) + fd = fopen(path, mode ? "wb" : "rb"); + + return fd; +} + +/** + * xmlWrapStatUtf8: + * @path: the path in utf-8 encoding + * @info: structure that stores results + * + * function obtains information about the file or directory + * + */ +static int +xmlWrapStatUtf8(const char *path,struct stat *info) +{ +#ifdef HAVE_STAT + int retval = -1; + wchar_t *wPath; + + wPath = __xmlIOWin32UTF8ToWChar(path); + if (wPath) + { + retval = _wstat(wPath,info); + xmlFree(wPath); + } + /* maybe path in native encoding */ + if(retval < 0) + retval = stat(path,info); + return retval; +#else + return -1; +#endif +} + +/** + * xmlWrapOpenNative: + * @path: the path + * @mode: type of access (0 - read, 1 - write) + * + * function opens the file specified by @path + * + */ +static FILE* +xmlWrapOpenNative(const char *path,int mode) +{ + return fopen(path,mode ? "wb" : "rb"); +} + +/** + * xmlWrapStatNative: + * @path: the path + * @info: structure that stores results + * + * function obtains information about the file or directory + * + */ +static int +xmlWrapStatNative(const char *path,struct stat *info) +{ +#ifdef HAVE_STAT + return stat(path,info); +#else + return -1; +#endif +} + +typedef int (* xmlWrapStatFunc) (const char *f, struct stat *s); +static xmlWrapStatFunc xmlWrapStat = xmlWrapStatNative; +typedef FILE* (* xmlWrapOpenFunc)(const char *f,int mode); +static xmlWrapOpenFunc xmlWrapOpen = xmlWrapOpenNative; + +/** + * xmlInitPlatformSpecificIo: + * + * Initialize platform specific features. + */ +static void +xmlInitPlatformSpecificIo(void) +{ + static int xmlPlatformIoInitialized = 0; + OSVERSIONINFO osvi; + + if(xmlPlatformIoInitialized) + return; + + osvi.dwOSVersionInfoSize = sizeof(osvi); + + if(GetVersionEx(&osvi) && (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT)) { + xmlWrapStat = xmlWrapStatUtf8; + xmlWrapOpen = xmlWrapOpenUtf8; + } else { + xmlWrapStat = xmlWrapStatNative; + xmlWrapOpen = xmlWrapOpenNative; + } + + xmlPlatformIoInitialized = 1; + return; +} + +#endif + +/** + * xmlCheckFilename: + * @path: the path to check + * + * function checks to see if @path is a valid source + * (file, socket...) for XML. + * + * if stat is not available on the target machine, + * returns 1. if stat fails, returns 0 (if calling + * stat on the filename fails, it can't be right). + * if stat succeeds and the file is a directory, + * returns 2. otherwise returns 1. + */ + +int +xmlCheckFilename (const char *path) +{ +#ifdef HAVE_STAT + struct stat stat_buffer; +#endif + if (path == NULL) + return(0); + +#ifdef HAVE_STAT +#if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__) + if (xmlWrapStat(path, &stat_buffer) == -1) + return 0; +#else + if (stat(path, &stat_buffer) == -1) + return 0; +#endif +#ifdef S_ISDIR + if (S_ISDIR(stat_buffer.st_mode)) + return 2; +#endif +#endif /* HAVE_STAT */ + return 1; +} + +static int +xmlNop(void) { + return(0); +} + +/** + * xmlFdRead: + * @context: the I/O context + * @buffer: where to drop data + * @len: number of bytes to read + * + * Read @len bytes to @buffer from the I/O channel. + * + * Returns the number of bytes written + */ +static int +xmlFdRead (void * context, char * buffer, int len) { + int ret; + + ret = read((int) (long) context, &buffer[0], len); + if (ret < 0) xmlIOErr(0, "read()"); + return(ret); +} + +#ifdef LIBXML_OUTPUT_ENABLED +/** + * xmlFdWrite: + * @context: the I/O context + * @buffer: where to get data + * @len: number of bytes to write + * + * Write @len bytes from @buffer to the I/O channel. + * + * Returns the number of bytes written + */ +static int +xmlFdWrite (void * context, const char * buffer, int len) { + int ret = 0; + + if (len > 0) { + ret = write((int) (long) context, &buffer[0], len); + if (ret < 0) xmlIOErr(0, "write()"); + } + return(ret); +} +#endif /* LIBXML_OUTPUT_ENABLED */ + +/** + * xmlFdClose: + * @context: the I/O context + * + * Close an I/O channel + * + * Returns 0 in case of success and error code otherwise + */ +static int +xmlFdClose (void * context) { + int ret; + ret = close((int) (long) context); + if (ret < 0) xmlIOErr(0, "close()"); + return(ret); +} + +/** + * xmlFileMatch: + * @filename: the URI for matching + * + * input from FILE * + * + * Returns 1 if matches, 0 otherwise + */ +int +xmlFileMatch (const char *filename ATTRIBUTE_UNUSED) { + return(1); +} + +/** + * xmlFileOpen_real: + * @filename: the URI for matching + * + * input from FILE *, supports compressed input + * if @filename is " " then the standard input is used + * + * Returns an I/O context or NULL in case of error + */ +static void * +xmlFileOpen_real (const char *filename) { + const char *path = NULL; + FILE *fd; + + if (filename == NULL) + return(NULL); + + if (!strcmp(filename, "-")) { + fd = stdin; + return((void *) fd); + } + + if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file://localhost/", 17)) +#if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__) + path = &filename[17]; +#else + path = &filename[16]; +#endif + else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:///", 8)) { +#if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__) + path = &filename[8]; +#else + path = &filename[7]; +#endif + } else + path = filename; + + if (path == NULL) + return(NULL); + if (!xmlCheckFilename(path)) + return(NULL); + +#if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__) + fd = xmlWrapOpen(path, 0); +#else + fd = fopen(path, "r"); +#endif /* WIN32 */ + if (fd == NULL) xmlIOErr(0, path); + return((void *) fd); +} + +/** + * xmlFileOpen: + * @filename: the URI for matching + * + * Wrapper around xmlFileOpen_real that try it with an unescaped + * version of @filename, if this fails fallback to @filename + * + * Returns a handler or NULL in case or failure + */ +void * +xmlFileOpen (const char *filename) { + char *unescaped; + void *retval; + + unescaped = xmlURIUnescapeString(filename, 0, NULL); + if (unescaped != NULL) { + retval = xmlFileOpen_real(unescaped); + xmlFree(unescaped); + } else { + retval = xmlFileOpen_real(filename); + } + return retval; +} + +#ifdef LIBXML_OUTPUT_ENABLED +/** + * xmlFileOpenW: + * @filename: the URI for matching + * + * output to from FILE *, + * if @filename is "-" then the standard output is used + * + * Returns an I/O context or NULL in case of error + */ +static void * +xmlFileOpenW (const char *filename) { + const char *path = NULL; + FILE *fd; + + if (!strcmp(filename, "-")) { + fd = stdout; + return((void *) fd); + } + + if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file://localhost/", 17)) +#if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__) + path = &filename[17]; +#else + path = &filename[16]; +#endif + else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:///", 8)) { +#if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__) + path = &filename[8]; +#else + path = &filename[7]; +#endif + } else + path = filename; + + if (path == NULL) + return(NULL); + +#if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__) + fd = xmlWrapOpen(path, 1); +#else + fd = fopen(path, "wb"); +#endif /* WIN32 */ + + if (fd == NULL) xmlIOErr(0, path); + return((void *) fd); +} +#endif /* LIBXML_OUTPUT_ENABLED */ + +/** + * xmlFileRead: + * @context: the I/O context + * @buffer: where to drop data + * @len: number of bytes to write + * + * Read @len bytes to @buffer from the I/O channel. + * + * Returns the number of bytes written or < 0 in case of failure + */ +int +xmlFileRead (void * context, char * buffer, int len) { + int ret; + if ((context == NULL) || (buffer == NULL)) + return(-1); + ret = fread(&buffer[0], 1, len, (FILE *) context); + if (ret < 0) xmlIOErr(0, "fread()"); + return(ret); +} + +#ifdef LIBXML_OUTPUT_ENABLED +/** + * xmlFileWrite: + * @context: the I/O context + * @buffer: where to drop data + * @len: number of bytes to write + * + * Write @len bytes from @buffer to the I/O channel. + * + * Returns the number of bytes written + */ +static int +xmlFileWrite (void * context, const char * buffer, int len) { + int items; + + if ((context == NULL) || (buffer == NULL)) + return(-1); + items = fwrite(&buffer[0], len, 1, (FILE *) context); + if ((items == 0) && (ferror((FILE *) context))) { + xmlIOErr(0, "fwrite()"); + return(-1); + } + return(items * len); +} +#endif /* LIBXML_OUTPUT_ENABLED */ + +/** + * xmlFileClose: + * @context: the I/O context + * + * Close an I/O channel + * + * Returns 0 or -1 in case of error + */ +int +xmlFileClose (void * context) { + FILE *fil; + int ret; + + if (context == NULL) + return(-1); + fil = (FILE *) context; + if ((fil == stdout) || (fil == stderr)) { + ret = fflush(fil); + if (ret < 0) + xmlIOErr(0, "fflush()"); + return(0); + } + if (fil == stdin) + return(0); + ret = ( fclose((FILE *) context) == EOF ) ? -1 : 0; + if (ret < 0) + xmlIOErr(0, "fclose()"); + return(ret); +} + +/** + * xmlFileFlush: + * @context: the I/O context + * + * Flush an I/O channel + */ +static int +xmlFileFlush (void * context) { + int ret; + + if (context == NULL) + return(-1); + ret = ( fflush((FILE *) context) == EOF ) ? -1 : 0; + if (ret < 0) + xmlIOErr(0, "fflush()"); + return(ret); +} + +#ifdef LIBXML_OUTPUT_ENABLED +/** + * xmlBufferWrite: + * @context: the xmlBuffer + * @buffer: the data to write + * @len: number of bytes to write + * + * Write @len bytes from @buffer to the xml buffer + * + * Returns the number of bytes written + */ +static int +xmlBufferWrite (void * context, const char * buffer, int len) { + int ret; + + ret = xmlBufferAdd((xmlBufferPtr) context, (const xmlChar *) buffer, len); + if (ret != 0) + return(-1); + return(len); +} +#endif + +#ifdef HAVE_ZLIB_H +/************************************************************************ + * * + * I/O for compressed file accesses * + * * + ************************************************************************/ +/** + * xmlGzfileMatch: + * @filename: the URI for matching + * + * input from compressed file test + * + * Returns 1 if matches, 0 otherwise + */ +static int +xmlGzfileMatch (const char *filename ATTRIBUTE_UNUSED) { + return(1); +} + +/** + * xmlGzfileOpen_real: + * @filename: the URI for matching + * + * input from compressed file open + * if @filename is " " then the standard input is used + * + * Returns an I/O context or NULL in case of error + */ +static void * +xmlGzfileOpen_real (const char *filename) { + const char *path = NULL; + gzFile fd; + + if (!strcmp(filename, "-")) { + fd = gzdopen(dup(0), "rb"); + return((void *) fd); + } + + if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file://localhost/", 17)) +#if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__) + path = &filename[17]; +#else + path = &filename[16]; +#endif + else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:///", 8)) { +#if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__) + path = &filename[8]; +#else + path = &filename[7]; +#endif + } else + path = filename; + + if (path == NULL) + return(NULL); + if (!xmlCheckFilename(path)) + return(NULL); + + fd = gzopen(path, "rb"); + return((void *) fd); +} + +/** + * xmlGzfileOpen: + * @filename: the URI for matching + * + * Wrapper around xmlGzfileOpen if the open fais, it will + * try to unescape @filename + */ +static void * +xmlGzfileOpen (const char *filename) { + char *unescaped; + void *retval; + + retval = xmlGzfileOpen_real(filename); + if (retval == NULL) { + unescaped = xmlURIUnescapeString(filename, 0, NULL); + if (unescaped != NULL) { + retval = xmlGzfileOpen_real(unescaped); + } + xmlFree(unescaped); + } + return retval; +} + +#ifdef LIBXML_OUTPUT_ENABLED +/** + * xmlGzfileOpenW: + * @filename: the URI for matching + * @compression: the compression factor (0 - 9 included) + * + * input from compressed file open + * if @filename is " " then the standard input is used + * + * Returns an I/O context or NULL in case of error + */ +static void * +xmlGzfileOpenW (const char *filename, int compression) { + const char *path = NULL; + char mode[15]; + gzFile fd; + + snprintf(mode, sizeof(mode), "wb%d", compression); + if (!strcmp(filename, "-")) { + fd = gzdopen(dup(1), mode); + return((void *) fd); + } + + if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file://localhost/", 17)) +#if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__) + path = &filename[17]; +#else + path = &filename[16]; +#endif + else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:///", 8)) { +#if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__) + path = &filename[8]; +#else + path = &filename[7]; +#endif + } else + path = filename; + + if (path == NULL) + return(NULL); + + fd = gzopen(path, mode); + return((void *) fd); +} +#endif /* LIBXML_OUTPUT_ENABLED */ + +/** + * xmlGzfileRead: + * @context: the I/O context + * @buffer: where to drop data + * @len: number of bytes to write + * + * Read @len bytes to @buffer from the compressed I/O channel. + * + * Returns the number of bytes written + */ +static int +xmlGzfileRead (void * context, char * buffer, int len) { + int ret; + + ret = gzread((gzFile) context, &buffer[0], len); + if (ret < 0) xmlIOErr(0, "gzread()"); + return(ret); +} + +#ifdef LIBXML_OUTPUT_ENABLED +/** + * xmlGzfileWrite: + * @context: the I/O context + * @buffer: where to drop data + * @len: number of bytes to write + * + * Write @len bytes from @buffer to the compressed I/O channel. + * + * Returns the number of bytes written + */ +static int +xmlGzfileWrite (void * context, const char * buffer, int len) { + int ret; + + ret = gzwrite((gzFile) context, (char *) &buffer[0], len); + if (ret < 0) xmlIOErr(0, "gzwrite()"); + return(ret); +} +#endif /* LIBXML_OUTPUT_ENABLED */ + +/** + * xmlGzfileClose: + * @context: the I/O context + * + * Close a compressed I/O channel + */ +static int +xmlGzfileClose (void * context) { + int ret; + + ret = (gzclose((gzFile) context) == Z_OK ) ? 0 : -1; + if (ret < 0) xmlIOErr(0, "gzclose()"); + return(ret); +} +#endif /* HAVE_ZLIB_H */ + +#ifdef LIBXML_HTTP_ENABLED +/************************************************************************ + * * + * I/O for HTTP file accesses * + * * + ************************************************************************/ + +#ifdef LIBXML_OUTPUT_ENABLED +typedef struct xmlIOHTTPWriteCtxt_ +{ + int compression; + + char * uri; + + void * doc_buff; + +} xmlIOHTTPWriteCtxt, *xmlIOHTTPWriteCtxtPtr; + +#ifdef HAVE_ZLIB_H + +#define DFLT_WBITS ( -15 ) +#define DFLT_MEM_LVL ( 8 ) +#define GZ_MAGIC1 ( 0x1f ) +#define GZ_MAGIC2 ( 0x8b ) +#define LXML_ZLIB_OS_CODE ( 0x03 ) +#define INIT_HTTP_BUFF_SIZE ( 32768 ) +#define DFLT_ZLIB_RATIO ( 5 ) + +/* +** Data structure and functions to work with sending compressed data +** via HTTP. +*/ + +typedef struct xmlZMemBuff_ +{ + unsigned long size; + unsigned long crc; + + unsigned char * zbuff; + z_stream zctrl; + +} xmlZMemBuff, *xmlZMemBuffPtr; + +/** + * append_reverse_ulong + * @buff: Compressed memory buffer + * @data: Unsigned long to append + * + * Append a unsigned long in reverse byte order to the end of the + * memory buffer. + */ +static void +append_reverse_ulong( xmlZMemBuff * buff, unsigned long data ) { + + int idx; + + if ( buff == NULL ) + return; + + /* + ** This is plagiarized from putLong in gzio.c (zlib source) where + ** the number "4" is hardcoded. If zlib is ever patched to + ** support 64 bit file sizes, this code would need to be patched + ** as well. + */ + + for ( idx = 0; idx < 4; idx++ ) { + *buff->zctrl.next_out = ( data & 0xff ); + data >>= 8; + buff->zctrl.next_out++; + } + + return; +} + +/** + * + * xmlFreeZMemBuff + * @buff: The memory buffer context to clear + * + * Release all the resources associated with the compressed memory buffer. + */ +static void +xmlFreeZMemBuff( xmlZMemBuffPtr buff ) { + +#ifdef DEBUG_HTTP + int z_err; +#endif + + if ( buff == NULL ) + return; + + xmlFree( buff->zbuff ); +#ifdef DEBUG_HTTP + z_err = deflateEnd( &buff->zctrl ); + if ( z_err != Z_OK ) + xmlGenericError( xmlGenericErrorContext, + "xmlFreeZMemBuff: Error releasing zlib context: %d\n", + z_err ); +#else + deflateEnd( &buff->zctrl ); +#endif + + xmlFree( buff ); + return; +} + +/** + * xmlCreateZMemBuff + *@compression: Compression value to use + * + * Create a memory buffer to hold the compressed XML document. The + * compressed document in memory will end up being identical to what + * would be created if gzopen/gzwrite/gzclose were being used to + * write the document to disk. The code for the header/trailer data to + * the compression is plagiarized from the zlib source files. + */ +static void * +xmlCreateZMemBuff( int compression ) { + + int z_err; + int hdr_lgth; + xmlZMemBuffPtr buff = NULL; + + if ( ( compression < 1 ) || ( compression > 9 ) ) + return ( NULL ); + + /* Create the control and data areas */ + + buff = xmlMalloc( sizeof( xmlZMemBuff ) ); + if ( buff == NULL ) { + xmlIOErrMemory("creating buffer context"); + return ( NULL ); + } + + (void)memset( buff, 0, sizeof( xmlZMemBuff ) ); + buff->size = INIT_HTTP_BUFF_SIZE; + buff->zbuff = xmlMalloc( buff->size ); + if ( buff->zbuff == NULL ) { + xmlFreeZMemBuff( buff ); + xmlIOErrMemory("creating buffer"); + return ( NULL ); + } + + z_err = deflateInit2( &buff->zctrl, compression, Z_DEFLATED, + DFLT_WBITS, DFLT_MEM_LVL, Z_DEFAULT_STRATEGY ); + if ( z_err != Z_OK ) { + xmlChar msg[500]; + xmlFreeZMemBuff( buff ); + buff = NULL; + xmlStrPrintf(msg, 500, + (const xmlChar *) "xmlCreateZMemBuff: %s %d\n", + "Error initializing compression context. ZLIB error:", + z_err ); + xmlIOErr(XML_IO_WRITE, (const char *) msg); + return ( NULL ); + } + + /* Set the header data. The CRC will be needed for the trailer */ + buff->crc = crc32( 0L, NULL, 0 ); + hdr_lgth = snprintf( (char *)buff->zbuff, buff->size, + "%c%c%c%c%c%c%c%c%c%c", + GZ_MAGIC1, GZ_MAGIC2, Z_DEFLATED, + 0, 0, 0, 0, 0, 0, LXML_ZLIB_OS_CODE ); + buff->zctrl.next_out = buff->zbuff + hdr_lgth; + buff->zctrl.avail_out = buff->size - hdr_lgth; + + return ( buff ); +} + +/** + * xmlZMemBuffExtend + * @buff: Buffer used to compress and consolidate data. + * @ext_amt: Number of bytes to extend the buffer. + * + * Extend the internal buffer used to store the compressed data by the + * specified amount. + * + * Returns 0 on success or -1 on failure to extend the buffer. On failure + * the original buffer still exists at the original size. + */ +static int +xmlZMemBuffExtend( xmlZMemBuffPtr buff, size_t ext_amt ) { + + int rc = -1; + size_t new_size; + size_t cur_used; + + unsigned char * tmp_ptr = NULL; + + if ( buff == NULL ) + return ( -1 ); + + else if ( ext_amt == 0 ) + return ( 0 ); + + cur_used = buff->zctrl.next_out - buff->zbuff; + new_size = buff->size + ext_amt; + +#ifdef DEBUG_HTTP + if ( cur_used > new_size ) + xmlGenericError( xmlGenericErrorContext, + "xmlZMemBuffExtend: %s\n%s %d bytes.\n", + "Buffer overwrite detected during compressed memory", + "buffer extension. Overflowed by", + (cur_used - new_size ) ); +#endif + + tmp_ptr = xmlRealloc( buff->zbuff, new_size ); + if ( tmp_ptr != NULL ) { + rc = 0; + buff->size = new_size; + buff->zbuff = tmp_ptr; + buff->zctrl.next_out = tmp_ptr + cur_used; + buff->zctrl.avail_out = new_size - cur_used; + } + else { + xmlChar msg[500]; + xmlStrPrintf(msg, 500, + (const xmlChar *) "xmlZMemBuffExtend: %s %lu bytes.\n", + "Allocation failure extending output buffer to", + new_size ); + xmlIOErr(XML_IO_WRITE, (const char *) msg); + } + + return ( rc ); +} + +/** + * xmlZMemBuffAppend + * @buff: Buffer used to compress and consolidate data + * @src: Uncompressed source content to append to buffer + * @len: Length of source data to append to buffer + * + * Compress and append data to the internal buffer. The data buffer + * will be expanded if needed to store the additional data. + * + * Returns the number of bytes appended to the buffer or -1 on error. + */ +static int +xmlZMemBuffAppend( xmlZMemBuffPtr buff, const char * src, int len ) { + + int z_err; + size_t min_accept; + + if ( ( buff == NULL ) || ( src == NULL ) ) + return ( -1 ); + + buff->zctrl.avail_in = len; + buff->zctrl.next_in = (unsigned char *)src; + while ( buff->zctrl.avail_in > 0 ) { + /* + ** Extend the buffer prior to deflate call if a reasonable amount + ** of output buffer space is not available. + */ + min_accept = buff->zctrl.avail_in / DFLT_ZLIB_RATIO; + if ( buff->zctrl.avail_out <= min_accept ) { + if ( xmlZMemBuffExtend( buff, buff->size ) == -1 ) + return ( -1 ); + } + + z_err = deflate( &buff->zctrl, Z_NO_FLUSH ); + if ( z_err != Z_OK ) { + xmlChar msg[500]; + xmlStrPrintf(msg, 500, + (const xmlChar *) "xmlZMemBuffAppend: %s %d %s - %d", + "Compression error while appending", + len, "bytes to buffer. ZLIB error", z_err ); + xmlIOErr(XML_IO_WRITE, (const char *) msg); + return ( -1 ); + } + } + + buff->crc = crc32( buff->crc, (unsigned char *)src, len ); + + return ( len ); +} + +/** + * xmlZMemBuffGetContent + * @buff: Compressed memory content buffer + * @data_ref: Pointer reference to point to compressed content + * + * Flushes the compression buffers, appends gzip file trailers and + * returns the compressed content and length of the compressed data. + * NOTE: The gzip trailer code here is plagiarized from zlib source. + * + * Returns the length of the compressed data or -1 on error. + */ +static int +xmlZMemBuffGetContent( xmlZMemBuffPtr buff, char ** data_ref ) { + + int zlgth = -1; + int z_err; + + if ( ( buff == NULL ) || ( data_ref == NULL ) ) + return ( -1 ); + + /* Need to loop until compression output buffers are flushed */ + + do + { + z_err = deflate( &buff->zctrl, Z_FINISH ); + if ( z_err == Z_OK ) { + /* In this case Z_OK means more buffer space needed */ + + if ( xmlZMemBuffExtend( buff, buff->size ) == -1 ) + return ( -1 ); + } + } + while ( z_err == Z_OK ); + + /* If the compression state is not Z_STREAM_END, some error occurred */ + + if ( z_err == Z_STREAM_END ) { + + /* Need to append the gzip data trailer */ + + if ( buff->zctrl.avail_out < ( 2 * sizeof( unsigned long ) ) ) { + if ( xmlZMemBuffExtend(buff, (2 * sizeof(unsigned long))) == -1 ) + return ( -1 ); + } + + /* + ** For whatever reason, the CRC and length data are pushed out + ** in reverse byte order. So a memcpy can't be used here. + */ + + append_reverse_ulong( buff, buff->crc ); + append_reverse_ulong( buff, buff->zctrl.total_in ); + + zlgth = buff->zctrl.next_out - buff->zbuff; + *data_ref = (char *)buff->zbuff; + } + + else { + xmlChar msg[500]; + xmlStrPrintf(msg, 500, + (const xmlChar *) "xmlZMemBuffGetContent: %s - %d\n", + "Error flushing zlib buffers. Error code", z_err ); + xmlIOErr(XML_IO_WRITE, (const char *) msg); + } + + return ( zlgth ); +} +#endif /* LIBXML_OUTPUT_ENABLED */ +#endif /* HAVE_ZLIB_H */ + +#ifdef LIBXML_OUTPUT_ENABLED +/** + * xmlFreeHTTPWriteCtxt + * @ctxt: Context to cleanup + * + * Free allocated memory and reclaim system resources. + * + * No return value. + */ +static void +xmlFreeHTTPWriteCtxt( xmlIOHTTPWriteCtxtPtr ctxt ) +{ + if ( ctxt->uri != NULL ) + xmlFree( ctxt->uri ); + + if ( ctxt->doc_buff != NULL ) { + +#ifdef HAVE_ZLIB_H + if ( ctxt->compression > 0 ) { + xmlFreeZMemBuff( ctxt->doc_buff ); + } + else +#endif + { + xmlOutputBufferClose( ctxt->doc_buff ); + } + } + + xmlFree( ctxt ); + return; +} +#endif /* LIBXML_OUTPUT_ENABLED */ + + +/** + * xmlIOHTTPMatch: + * @filename: the URI for matching + * + * check if the URI matches an HTTP one + * + * Returns 1 if matches, 0 otherwise + */ +int +xmlIOHTTPMatch (const char *filename) { + if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "http://", 7)) + return(1); + return(0); +} + +/** + * xmlIOHTTPOpen: + * @filename: the URI for matching + * + * open an HTTP I/O channel + * + * Returns an I/O context or NULL in case of error + */ +void * +xmlIOHTTPOpen (const char *filename) { + return(xmlNanoHTTPOpen(filename, NULL)); +} + +#ifdef LIBXML_OUTPUT_ENABLED +/** + * xmlIOHTTPOpenW: + * @post_uri: The destination URI for the document + * @compression: The compression desired for the document. + * + * Open a temporary buffer to collect the document for a subsequent HTTP POST + * request. Non-static as is called from the output buffer creation routine. + * + * Returns an I/O context or NULL in case of error. + */ + +void * +xmlIOHTTPOpenW(const char *post_uri, int compression) +{ + + xmlIOHTTPWriteCtxtPtr ctxt = NULL; + + if (post_uri == NULL) + return (NULL); + + ctxt = xmlMalloc(sizeof(xmlIOHTTPWriteCtxt)); + if (ctxt == NULL) { + xmlIOErrMemory("creating HTTP output context"); + return (NULL); + } + + (void) memset(ctxt, 0, sizeof(xmlIOHTTPWriteCtxt)); + + ctxt->uri = (char *) xmlStrdup((const xmlChar *)post_uri); + if (ctxt->uri == NULL) { + xmlIOErrMemory("copying URI"); + xmlFreeHTTPWriteCtxt(ctxt); + return (NULL); + } + + /* + * ** Since the document length is required for an HTTP post, + * ** need to put the document into a buffer. A memory buffer + * ** is being used to avoid pushing the data to disk and back. + */ + +#ifdef HAVE_ZLIB_H + if ((compression > 0) && (compression <= 9)) { + + ctxt->compression = compression; + ctxt->doc_buff = xmlCreateZMemBuff(compression); + } else +#endif + { + /* Any character conversions should have been done before this */ + + ctxt->doc_buff = xmlAllocOutputBuffer(NULL); + } + + if (ctxt->doc_buff == NULL) { + xmlFreeHTTPWriteCtxt(ctxt); + ctxt = NULL; + } + + return (ctxt); +} +#endif /* LIBXML_OUTPUT_ENABLED */ + +#ifdef LIBXML_OUTPUT_ENABLED +/** + * xmlIOHTTPDfltOpenW + * @post_uri: The destination URI for this document. + * + * Calls xmlIOHTTPOpenW with no compression to set up for a subsequent + * HTTP post command. This function should generally not be used as + * the open callback is short circuited in xmlOutputBufferCreateFile. + * + * Returns a pointer to the new IO context. + */ +static void * +xmlIOHTTPDfltOpenW( const char * post_uri ) { + return ( xmlIOHTTPOpenW( post_uri, 0 ) ); +} +#endif /* LIBXML_OUTPUT_ENABLED */ + +/** + * xmlIOHTTPRead: + * @context: the I/O context + * @buffer: where to drop data + * @len: number of bytes to write + * + * Read @len bytes to @buffer from the I/O channel. + * + * Returns the number of bytes written + */ +int +xmlIOHTTPRead(void * context, char * buffer, int len) { + if ((buffer == NULL) || (len < 0)) return(-1); + return(xmlNanoHTTPRead(context, &buffer[0], len)); +} + +#ifdef LIBXML_OUTPUT_ENABLED +/** + * xmlIOHTTPWrite + * @context: previously opened writing context + * @buffer: data to output to temporary buffer + * @len: bytes to output + * + * Collect data from memory buffer into a temporary file for later + * processing. + * + * Returns number of bytes written. + */ + +static int +xmlIOHTTPWrite( void * context, const char * buffer, int len ) { + + xmlIOHTTPWriteCtxtPtr ctxt = context; + + if ( ( ctxt == NULL ) || ( ctxt->doc_buff == NULL ) || ( buffer == NULL ) ) + return ( -1 ); + + if ( len > 0 ) { + + /* Use gzwrite or fwrite as previously setup in the open call */ + +#ifdef HAVE_ZLIB_H + if ( ctxt->compression > 0 ) + len = xmlZMemBuffAppend( ctxt->doc_buff, buffer, len ); + + else +#endif + len = xmlOutputBufferWrite( ctxt->doc_buff, len, buffer ); + + if ( len < 0 ) { + xmlChar msg[500]; + xmlStrPrintf(msg, 500, + (const xmlChar *) "xmlIOHTTPWrite: %s\n%s '%s'.\n", + "Error appending to internal buffer.", + "Error sending document to URI", + ctxt->uri ); + xmlIOErr(XML_IO_WRITE, (const char *) msg); + } + } + + return ( len ); +} +#endif /* LIBXML_OUTPUT_ENABLED */ + + +/** + * xmlIOHTTPClose: + * @context: the I/O context + * + * Close an HTTP I/O channel + * + * Returns 0 + */ +int +xmlIOHTTPClose (void * context) { + xmlNanoHTTPClose(context); + return 0; +} + +#ifdef LIBXML_OUTPUT_ENABLED +/** + * xmlIOHTTCloseWrite + * @context: The I/O context + * @http_mthd: The HTTP method to be used when sending the data + * + * Close the transmit HTTP I/O channel and actually send the data. + */ +static int +xmlIOHTTPCloseWrite( void * context, const char * http_mthd ) { + + int close_rc = -1; + int http_rtn = 0; + int content_lgth = 0; + xmlIOHTTPWriteCtxtPtr ctxt = context; + + char * http_content = NULL; + char * content_encoding = NULL; + char * content_type = (char *) "text/xml"; + void * http_ctxt = NULL; + + if ( ( ctxt == NULL ) || ( http_mthd == NULL ) ) + return ( -1 ); + + /* Retrieve the content from the appropriate buffer */ + +#ifdef HAVE_ZLIB_H + + if ( ctxt->compression > 0 ) { + content_lgth = xmlZMemBuffGetContent( ctxt->doc_buff, &http_content ); + content_encoding = (char *) "Content-Encoding: gzip"; + } + else +#endif + { + /* Pull the data out of the memory output buffer */ + + xmlOutputBufferPtr dctxt = ctxt->doc_buff; + http_content = (char *)dctxt->buffer->content; + content_lgth = dctxt->buffer->use; + } + + if ( http_content == NULL ) { + xmlChar msg[500]; + xmlStrPrintf(msg, 500, + (const xmlChar *) "xmlIOHTTPCloseWrite: %s '%s' %s '%s'.\n", + "Error retrieving content.\nUnable to", + http_mthd, "data to URI", ctxt->uri ); + xmlIOErr(XML_IO_WRITE, (const char *) msg); + } + + else { + + http_ctxt = xmlNanoHTTPMethod( ctxt->uri, http_mthd, http_content, + &content_type, content_encoding, + content_lgth ); + + if ( http_ctxt != NULL ) { +#ifdef DEBUG_HTTP + /* If testing/debugging - dump reply with request content */ + + FILE * tst_file = NULL; + char buffer[ 4096 ]; + char * dump_name = NULL; + int avail; + + xmlGenericError( xmlGenericErrorContext, + "xmlNanoHTTPCloseWrite: HTTP %s to\n%s returned %d.\n", + http_mthd, ctxt->uri, + xmlNanoHTTPReturnCode( http_ctxt ) ); + + /* + ** Since either content or reply may be gzipped, + ** dump them to separate files instead of the + ** standard error context. + */ + + dump_name = tempnam( NULL, "lxml" ); + if ( dump_name != NULL ) { + (void)snprintf( buffer, sizeof(buffer), "%s.content", dump_name ); + + tst_file = fopen( buffer, "wb" ); + if ( tst_file != NULL ) { + xmlGenericError( xmlGenericErrorContext, + "Transmitted content saved in file: %s\n", buffer ); + + fwrite( http_content, sizeof( char ), + content_lgth, tst_file ); + fclose( tst_file ); + } + + (void)snprintf( buffer, sizeof(buffer), "%s.reply", dump_name ); + tst_file = fopen( buffer, "wb" ); + if ( tst_file != NULL ) { + xmlGenericError( xmlGenericErrorContext, + "Reply content saved in file: %s\n", buffer ); + + + while ( (avail = xmlNanoHTTPRead( http_ctxt, + buffer, sizeof( buffer ) )) > 0 ) { + + fwrite( buffer, sizeof( char ), avail, tst_file ); + } + + fclose( tst_file ); + } + + free( dump_name ); + } +#endif /* DEBUG_HTTP */ + + http_rtn = xmlNanoHTTPReturnCode( http_ctxt ); + if ( ( http_rtn >= 200 ) && ( http_rtn < 300 ) ) + close_rc = 0; + else { + xmlChar msg[500]; + xmlStrPrintf(msg, 500, + (const xmlChar *) "xmlIOHTTPCloseWrite: HTTP '%s' of %d %s\n'%s' %s %d\n", + http_mthd, content_lgth, + "bytes to URI", ctxt->uri, + "failed. HTTP return code:", http_rtn ); + xmlIOErr(XML_IO_WRITE, (const char *) msg); + } + + xmlNanoHTTPClose( http_ctxt ); + xmlFree( content_type ); + } + } + + /* Final cleanups */ + + xmlFreeHTTPWriteCtxt( ctxt ); + + return ( close_rc ); +} + +/** + * xmlIOHTTPClosePut + * + * @context: The I/O context + * + * Close the transmit HTTP I/O channel and actually send data using a PUT + * HTTP method. + */ +static int +xmlIOHTTPClosePut( void * ctxt ) { + return ( xmlIOHTTPCloseWrite( ctxt, "PUT" ) ); +} + + +/** + * xmlIOHTTPClosePost + * + * @context: The I/O context + * + * Close the transmit HTTP I/O channel and actually send data using a POST + * HTTP method. + */ +static int +xmlIOHTTPClosePost( void * ctxt ) { + return ( xmlIOHTTPCloseWrite( ctxt, "POST" ) ); +} +#endif /* LIBXML_OUTPUT_ENABLED */ + +#endif /* LIBXML_HTTP_ENABLED */ + +#ifdef LIBXML_FTP_ENABLED +/************************************************************************ + * * + * I/O for FTP file accesses * + * * + ************************************************************************/ +/** + * xmlIOFTPMatch: + * @filename: the URI for matching + * + * check if the URI matches an FTP one + * + * Returns 1 if matches, 0 otherwise + */ +int +xmlIOFTPMatch (const char *filename) { + if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "ftp://", 6)) + return(1); + return(0); +} + +/** + * xmlIOFTPOpen: + * @filename: the URI for matching + * + * open an FTP I/O channel + * + * Returns an I/O context or NULL in case of error + */ +void * +xmlIOFTPOpen (const char *filename) { + return(xmlNanoFTPOpen(filename)); +} + +/** + * xmlIOFTPRead: + * @context: the I/O context + * @buffer: where to drop data + * @len: number of bytes to write + * + * Read @len bytes to @buffer from the I/O channel. + * + * Returns the number of bytes written + */ +int +xmlIOFTPRead(void * context, char * buffer, int len) { + if ((buffer == NULL) || (len < 0)) return(-1); + return(xmlNanoFTPRead(context, &buffer[0], len)); +} + +/** + * xmlIOFTPClose: + * @context: the I/O context + * + * Close an FTP I/O channel + * + * Returns 0 + */ +int +xmlIOFTPClose (void * context) { + return ( xmlNanoFTPClose(context) ); +} +#endif /* LIBXML_FTP_ENABLED */ + + +/** + * xmlRegisterInputCallbacks: + * @matchFunc: the xmlInputMatchCallback + * @openFunc: the xmlInputOpenCallback + * @readFunc: the xmlInputReadCallback + * @closeFunc: the xmlInputCloseCallback + * + * Register a new set of I/O callback for handling parser input. + * + * Returns the registered handler number or -1 in case of error + */ +int +xmlRegisterInputCallbacks(xmlInputMatchCallback matchFunc, + xmlInputOpenCallback openFunc, xmlInputReadCallback readFunc, + xmlInputCloseCallback closeFunc) { + if (xmlInputCallbackNr >= MAX_INPUT_CALLBACK) { + return(-1); + } + xmlInputCallbackTable[xmlInputCallbackNr].matchcallback = matchFunc; + xmlInputCallbackTable[xmlInputCallbackNr].opencallback = openFunc; + xmlInputCallbackTable[xmlInputCallbackNr].readcallback = readFunc; + xmlInputCallbackTable[xmlInputCallbackNr].closecallback = closeFunc; + xmlInputCallbackInitialized = 1; + return(xmlInputCallbackNr++); +} + +#ifdef LIBXML_OUTPUT_ENABLED +/** + * xmlRegisterOutputCallbacks: + * @matchFunc: the xmlOutputMatchCallback + * @openFunc: the xmlOutputOpenCallback + * @writeFunc: the xmlOutputWriteCallback + * @closeFunc: the xmlOutputCloseCallback + * + * Register a new set of I/O callback for handling output. + * + * Returns the registered handler number or -1 in case of error + */ +int +xmlRegisterOutputCallbacks(xmlOutputMatchCallback matchFunc, + xmlOutputOpenCallback openFunc, xmlOutputWriteCallback writeFunc, + xmlOutputCloseCallback closeFunc) { + if (xmlOutputCallbackNr >= MAX_INPUT_CALLBACK) { + return(-1); + } + xmlOutputCallbackTable[xmlOutputCallbackNr].matchcallback = matchFunc; + xmlOutputCallbackTable[xmlOutputCallbackNr].opencallback = openFunc; + xmlOutputCallbackTable[xmlOutputCallbackNr].writecallback = writeFunc; + xmlOutputCallbackTable[xmlOutputCallbackNr].closecallback = closeFunc; + xmlOutputCallbackInitialized = 1; + return(xmlOutputCallbackNr++); +} +#endif /* LIBXML_OUTPUT_ENABLED */ + +/** + * xmlRegisterDefaultInputCallbacks: + * + * Registers the default compiled-in I/O handlers. + */ +void +xmlRegisterDefaultInputCallbacks(void) { + if (xmlInputCallbackInitialized) + return; + +#if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__) + xmlInitPlatformSpecificIo(); +#endif + + xmlRegisterInputCallbacks(xmlFileMatch, xmlFileOpen, + xmlFileRead, xmlFileClose); +#ifdef HAVE_ZLIB_H + xmlRegisterInputCallbacks(xmlGzfileMatch, xmlGzfileOpen, + xmlGzfileRead, xmlGzfileClose); +#endif /* HAVE_ZLIB_H */ + +#ifdef LIBXML_HTTP_ENABLED + xmlRegisterInputCallbacks(xmlIOHTTPMatch, xmlIOHTTPOpen, + xmlIOHTTPRead, xmlIOHTTPClose); +#endif /* LIBXML_HTTP_ENABLED */ + +#ifdef LIBXML_FTP_ENABLED + xmlRegisterInputCallbacks(xmlIOFTPMatch, xmlIOFTPOpen, + xmlIOFTPRead, xmlIOFTPClose); +#endif /* LIBXML_FTP_ENABLED */ + xmlInputCallbackInitialized = 1; +} + +#ifdef LIBXML_OUTPUT_ENABLED +/** + * xmlRegisterDefaultOutputCallbacks: + * + * Registers the default compiled-in I/O handlers. + */ +void +xmlRegisterDefaultOutputCallbacks (void) { + if (xmlOutputCallbackInitialized) + return; + +#if defined(_WIN32) || defined (__DJGPP__) && !defined (__CYGWIN__) + xmlInitPlatformSpecificIo(); +#endif + + xmlRegisterOutputCallbacks(xmlFileMatch, xmlFileOpenW, + xmlFileWrite, xmlFileClose); + +#ifdef LIBXML_HTTP_ENABLED + xmlRegisterOutputCallbacks(xmlIOHTTPMatch, xmlIOHTTPDfltOpenW, + xmlIOHTTPWrite, xmlIOHTTPClosePut); +#endif + +/********************************* + No way a-priori to distinguish between gzipped files from + uncompressed ones except opening if existing then closing + and saving with same compression ratio ... a pain. + +#ifdef HAVE_ZLIB_H + xmlRegisterOutputCallbacks(xmlGzfileMatch, xmlGzfileOpen, + xmlGzfileWrite, xmlGzfileClose); +#endif + + Nor FTP PUT .... +#ifdef LIBXML_FTP_ENABLED + xmlRegisterOutputCallbacks(xmlIOFTPMatch, xmlIOFTPOpen, + xmlIOFTPWrite, xmlIOFTPClose); +#endif + **********************************/ + xmlOutputCallbackInitialized = 1; +} + +#ifdef LIBXML_HTTP_ENABLED +/** + * xmlRegisterHTTPPostCallbacks: + * + * By default, libxml submits HTTP output requests using the "PUT" method. + * Calling this method changes the HTTP output method to use the "POST" + * method instead. + * + */ +void +xmlRegisterHTTPPostCallbacks( void ) { + + /* Register defaults if not done previously */ + + if ( xmlOutputCallbackInitialized == 0 ) + xmlRegisterDefaultOutputCallbacks( ); + + xmlRegisterOutputCallbacks(xmlIOHTTPMatch, xmlIOHTTPDfltOpenW, + xmlIOHTTPWrite, xmlIOHTTPClosePost); + return; +} +#endif +#endif /* LIBXML_OUTPUT_ENABLED */ + +/** + * xmlAllocParserInputBuffer: + * @enc: the charset encoding if known + * + * Create a buffered parser input for progressive parsing + * + * Returns the new parser input or NULL + */ +xmlParserInputBufferPtr +xmlAllocParserInputBuffer(xmlCharEncoding enc) { + xmlParserInputBufferPtr ret; + + ret = (xmlParserInputBufferPtr) xmlMalloc(sizeof(xmlParserInputBuffer)); + if (ret == NULL) { + xmlIOErrMemory("creating input buffer"); + return(NULL); + } + memset(ret, 0, (size_t) sizeof(xmlParserInputBuffer)); + ret->buffer = xmlBufferCreateSize(2 * xmlDefaultBufferSize); + if (ret->buffer == NULL) { + xmlFree(ret); + return(NULL); + } + ret->buffer->alloc = XML_BUFFER_ALLOC_DOUBLEIT; + ret->encoder = xmlGetCharEncodingHandler(enc); + if (ret->encoder != NULL) + ret->raw = xmlBufferCreateSize(2 * xmlDefaultBufferSize); + else + ret->raw = NULL; + ret->readcallback = NULL; + ret->closecallback = NULL; + ret->context = NULL; + ret->compressed = -1; + ret->rawconsumed = 0; + + return(ret); +} + +#ifdef LIBXML_OUTPUT_ENABLED +/** + * xmlAllocOutputBuffer: + * @encoder: the encoding converter or NULL + * + * Create a buffered parser output + * + * Returns the new parser output or NULL + */ +xmlOutputBufferPtr +xmlAllocOutputBuffer(xmlCharEncodingHandlerPtr encoder) { + xmlOutputBufferPtr ret; + + ret = (xmlOutputBufferPtr) xmlMalloc(sizeof(xmlOutputBuffer)); + if (ret == NULL) { + xmlIOErrMemory("creating output buffer"); + return(NULL); + } + memset(ret, 0, (size_t) sizeof(xmlOutputBuffer)); + ret->buffer = xmlBufferCreate(); + if (ret->buffer == NULL) { + xmlFree(ret); + return(NULL); + } + ret->buffer->alloc = XML_BUFFER_ALLOC_DOUBLEIT; + ret->encoder = encoder; + if (encoder != NULL) { + ret->conv = xmlBufferCreateSize(4000); + /* + * This call is designed to initiate the encoder state + */ + xmlCharEncOutFunc(encoder, ret->conv, NULL); + } else + ret->conv = NULL; + ret->writecallback = NULL; + ret->closecallback = NULL; + ret->context = NULL; + ret->written = 0; + + return(ret); +} +#endif /* LIBXML_OUTPUT_ENABLED */ + +/** + * xmlFreeParserInputBuffer: + * @in: a buffered parser input + * + * Free up the memory used by a buffered parser input + */ +void +xmlFreeParserInputBuffer(xmlParserInputBufferPtr in) { + if (in == NULL) return; + + if (in->raw) { + xmlBufferFree(in->raw); + in->raw = NULL; + } + if (in->encoder != NULL) { + xmlCharEncCloseFunc(in->encoder); + } + if (in->closecallback != NULL) { + in->closecallback(in->context); + } + if (in->buffer != NULL) { + xmlBufferFree(in->buffer); + in->buffer = NULL; + } + + xmlFree(in); +} + +#ifdef LIBXML_OUTPUT_ENABLED +/** + * xmlOutputBufferClose: + * @out: a buffered output + * + * flushes and close the output I/O channel + * and free up all the associated resources + * + * Returns the number of byte written or -1 in case of error. + */ +int +xmlOutputBufferClose(xmlOutputBufferPtr out) +{ + int written; + int err_rc = 0; + + if (out == NULL) + return (-1); + if (out->writecallback != NULL) + xmlOutputBufferFlush(out); + if (out->closecallback != NULL) { + err_rc = out->closecallback(out->context); + } + written = out->written; + if (out->conv) { + xmlBufferFree(out->conv); + out->conv = NULL; + } + if (out->encoder != NULL) { + xmlCharEncCloseFunc(out->encoder); + } + if (out->buffer != NULL) { + xmlBufferFree(out->buffer); + out->buffer = NULL; + } + + if (out->error) + err_rc = -1; + xmlFree(out); + return ((err_rc == 0) ? written : err_rc); +} +#endif /* LIBXML_OUTPUT_ENABLED */ + +xmlParserInputBufferPtr +__xmlParserInputBufferCreateFilename(const char *URI, xmlCharEncoding enc) { + xmlParserInputBufferPtr ret; + int i = 0; + void *context = NULL; + + if (xmlInputCallbackInitialized == 0) + xmlRegisterDefaultInputCallbacks(); + + if (URI == NULL) return(NULL); + + /* + * Try to find one of the input accept method accepting that scheme + * Go in reverse to give precedence to user defined handlers. + */ + if (context == NULL) { + for (i = xmlInputCallbackNr - 1;i >= 0;i--) { + if ((xmlInputCallbackTable[i].matchcallback != NULL) && + (xmlInputCallbackTable[i].matchcallback(URI) != 0)) { + context = xmlInputCallbackTable[i].opencallback(URI); + if (context != NULL) { + break; + } + } + } + } + if (context == NULL) { + return(NULL); + } + + /* + * Allocate the Input buffer front-end. + */ + ret = xmlAllocParserInputBuffer(enc); + if (ret != NULL) { + ret->context = context; + ret->readcallback = xmlInputCallbackTable[i].readcallback; + ret->closecallback = xmlInputCallbackTable[i].closecallback; +#ifdef HAVE_ZLIB_H + if ((xmlInputCallbackTable[i].opencallback == xmlGzfileOpen) && + (strcmp(URI, "-") != 0)) { + if (((z_stream *)context)->avail_in > 4) { + char *cptr, buff4[4]; + cptr = (char *) ((z_stream *)context)->next_in; + if (gzread(context, buff4, 4) == 4) { + if (strncmp(buff4, cptr, 4) == 0) + ret->compressed = 0; + else + ret->compressed = 1; + gzrewind(context); + } + } + } +#endif + } + else + xmlInputCallbackTable[i].closecallback (context); + + return(ret); +} + +/** + * xmlParserInputBufferCreateFilename: + * @URI: a C string containing the URI or filename + * @enc: the charset encoding if known + * + * Create a buffered parser input for the progressive parsing of a file + * If filename is "-' then we use stdin as the input. + * Automatic support for ZLIB/Compress compressed document is provided + * by default if found at compile-time. + * Do an encoding check if enc == XML_CHAR_ENCODING_NONE + * + * Returns the new parser input or NULL + */ +xmlParserInputBufferPtr +xmlParserInputBufferCreateFilename(const char *URI, xmlCharEncoding enc) { + if ((xmlParserInputBufferCreateFilenameValue)) { + return xmlParserInputBufferCreateFilenameValue(URI, enc); + } + return __xmlParserInputBufferCreateFilename(URI, enc); +} + +#ifdef LIBXML_OUTPUT_ENABLED +xmlOutputBufferPtr +__xmlOutputBufferCreateFilename(const char *URI, + xmlCharEncodingHandlerPtr encoder, + int compression ATTRIBUTE_UNUSED) { + xmlOutputBufferPtr ret; + xmlURIPtr puri; + int i = 0; + void *context = NULL; + char *unescaped = NULL; +#ifdef HAVE_ZLIB_H + int is_file_uri = 1; +#endif + + if (xmlOutputCallbackInitialized == 0) + xmlRegisterDefaultOutputCallbacks(); + + if (URI == NULL) return(NULL); + + puri = xmlParseURI(URI); + if (puri != NULL) { +#ifdef HAVE_ZLIB_H + if ((puri->scheme != NULL) && + (!xmlStrEqual(BAD_CAST puri->scheme, BAD_CAST "file"))) + is_file_uri = 0; +#endif + /* + * try to limit the damages of the URI unescaping code. + */ + if ((puri->scheme == NULL) || + (xmlStrEqual(BAD_CAST puri->scheme, BAD_CAST "file"))) + unescaped = xmlURIUnescapeString(URI, 0, NULL); + xmlFreeURI(puri); + } + + /* + * Try to find one of the output accept method accepting that scheme + * Go in reverse to give precedence to user defined handlers. + * try with an unescaped version of the URI + */ + if (unescaped != NULL) { +#ifdef HAVE_ZLIB_H + if ((compression > 0) && (compression <= 9) && (is_file_uri == 1)) { + context = xmlGzfileOpenW(unescaped, compression); + if (context != NULL) { + ret = xmlAllocOutputBuffer(encoder); + if (ret != NULL) { + ret->context = context; + ret->writecallback = xmlGzfileWrite; + ret->closecallback = xmlGzfileClose; + } + xmlFree(unescaped); + return(ret); + } + } +#endif + for (i = xmlOutputCallbackNr - 1;i >= 0;i--) { + if ((xmlOutputCallbackTable[i].matchcallback != NULL) && + (xmlOutputCallbackTable[i].matchcallback(unescaped) != 0)) { +#if defined(LIBXML_HTTP_ENABLED) && defined(HAVE_ZLIB_H) + /* Need to pass compression parameter into HTTP open calls */ + if (xmlOutputCallbackTable[i].matchcallback == xmlIOHTTPMatch) + context = xmlIOHTTPOpenW(unescaped, compression); + else +#endif + context = xmlOutputCallbackTable[i].opencallback(unescaped); + if (context != NULL) + break; + } + } + xmlFree(unescaped); + } + + /* + * If this failed try with a non-escaped URI this may be a strange + * filename + */ + if (context == NULL) { +#ifdef HAVE_ZLIB_H + if ((compression > 0) && (compression <= 9) && (is_file_uri == 1)) { + context = xmlGzfileOpenW(URI, compression); + if (context != NULL) { + ret = xmlAllocOutputBuffer(encoder); + if (ret != NULL) { + ret->context = context; + ret->writecallback = xmlGzfileWrite; + ret->closecallback = xmlGzfileClose; + } + return(ret); + } + } +#endif + for (i = xmlOutputCallbackNr - 1;i >= 0;i--) { + if ((xmlOutputCallbackTable[i].matchcallback != NULL) && + (xmlOutputCallbackTable[i].matchcallback(URI) != 0)) { +#if defined(LIBXML_HTTP_ENABLED) && defined(HAVE_ZLIB_H) + /* Need to pass compression parameter into HTTP open calls */ + if (xmlOutputCallbackTable[i].matchcallback == xmlIOHTTPMatch) + context = xmlIOHTTPOpenW(URI, compression); + else +#endif + context = xmlOutputCallbackTable[i].opencallback(URI); + if (context != NULL) + break; + } + } + } + + if (context == NULL) { + return(NULL); + } + + /* + * Allocate the Output buffer front-end. + */ + ret = xmlAllocOutputBuffer(encoder); + if (ret != NULL) { + ret->context = context; + ret->writecallback = xmlOutputCallbackTable[i].writecallback; + ret->closecallback = xmlOutputCallbackTable[i].closecallback; + } + return(ret); +} + +/** + * xmlOutputBufferCreateFilename: + * @URI: a C string containing the URI or filename + * @encoder: the encoding converter or NULL + * @compression: the compression ration (0 none, 9 max). + * + * Create a buffered output for the progressive saving of a file + * If filename is "-' then we use stdout as the output. + * Automatic support for ZLIB/Compress compressed document is provided + * by default if found at compile-time. + * TODO: currently if compression is set, the library only support + * writing to a local file. + * + * Returns the new output or NULL + */ +xmlOutputBufferPtr +xmlOutputBufferCreateFilename(const char *URI, + xmlCharEncodingHandlerPtr encoder, + int compression ATTRIBUTE_UNUSED) { + if ((xmlOutputBufferCreateFilenameValue)) { + return xmlOutputBufferCreateFilenameValue(URI, encoder, compression); + } + return __xmlOutputBufferCreateFilename(URI, encoder, compression); +} +#endif /* LIBXML_OUTPUT_ENABLED */ + +/** + * xmlParserInputBufferCreateFile: + * @file: a FILE* + * @enc: the charset encoding if known + * + * Create a buffered parser input for the progressive parsing of a FILE * + * buffered C I/O + * + * Returns the new parser input or NULL + */ +xmlParserInputBufferPtr +xmlParserInputBufferCreateFile(FILE *file, xmlCharEncoding enc) { + xmlParserInputBufferPtr ret; + + if (xmlInputCallbackInitialized == 0) + xmlRegisterDefaultInputCallbacks(); + + if (file == NULL) return(NULL); + + ret = xmlAllocParserInputBuffer(enc); + if (ret != NULL) { + ret->context = file; + ret->readcallback = xmlFileRead; + ret->closecallback = xmlFileFlush; + } + + return(ret); +} + +#ifdef LIBXML_OUTPUT_ENABLED +/** + * xmlOutputBufferCreateFile: + * @file: a FILE* + * @encoder: the encoding converter or NULL + * + * Create a buffered output for the progressive saving to a FILE * + * buffered C I/O + * + * Returns the new parser output or NULL + */ +xmlOutputBufferPtr +xmlOutputBufferCreateFile(FILE *file, xmlCharEncodingHandlerPtr encoder) { + xmlOutputBufferPtr ret; + + if (xmlOutputCallbackInitialized == 0) + xmlRegisterDefaultOutputCallbacks(); + + if (file == NULL) return(NULL); + + ret = xmlAllocOutputBuffer(encoder); + if (ret != NULL) { + ret->context = file; + ret->writecallback = xmlFileWrite; + ret->closecallback = xmlFileFlush; + } + + return(ret); +} + +/** + * xmlOutputBufferCreateBuffer: + * @buffer: a xmlBufferPtr + * @encoder: the encoding converter or NULL + * + * Create a buffered output for the progressive saving to a xmlBuffer + * + * Returns the new parser output or NULL + */ +xmlOutputBufferPtr +xmlOutputBufferCreateBuffer(xmlBufferPtr buffer, + xmlCharEncodingHandlerPtr encoder) { + xmlOutputBufferPtr ret; + + if (buffer == NULL) return(NULL); + + ret = xmlOutputBufferCreateIO((xmlOutputWriteCallback) + xmlBufferWrite, + (xmlOutputCloseCallback) + NULL, (void *) buffer, encoder); + + return(ret); +} + +#endif /* LIBXML_OUTPUT_ENABLED */ + +/** + * xmlParserInputBufferCreateFd: + * @fd: a file descriptor number + * @enc: the charset encoding if known + * + * Create a buffered parser input for the progressive parsing for the input + * from a file descriptor + * + * Returns the new parser input or NULL + */ +xmlParserInputBufferPtr +xmlParserInputBufferCreateFd(int fd, xmlCharEncoding enc) { + xmlParserInputBufferPtr ret; + + if (fd < 0) return(NULL); + + ret = xmlAllocParserInputBuffer(enc); + if (ret != NULL) { + ret->context = (void *) (long) fd; + ret->readcallback = xmlFdRead; + ret->closecallback = xmlFdClose; + } + + return(ret); +} + +/** + * xmlParserInputBufferCreateMem: + * @mem: the memory input + * @size: the length of the memory block + * @enc: the charset encoding if known + * + * Create a buffered parser input for the progressive parsing for the input + * from a memory area. + * + * Returns the new parser input or NULL + */ +xmlParserInputBufferPtr +xmlParserInputBufferCreateMem(const char *mem, int size, xmlCharEncoding enc) { + xmlParserInputBufferPtr ret; + int errcode; + + if (size <= 0) return(NULL); + if (mem == NULL) return(NULL); + + ret = xmlAllocParserInputBuffer(enc); + if (ret != NULL) { + ret->context = (void *) mem; + ret->readcallback = (xmlInputReadCallback) xmlNop; + ret->closecallback = NULL; + errcode = xmlBufferAdd(ret->buffer, (const xmlChar *) mem, size); + if (errcode != 0) { + xmlFree(ret); + return(NULL); + } + } + + return(ret); +} + +/** + * xmlParserInputBufferCreateStatic: + * @mem: the memory input + * @size: the length of the memory block + * @enc: the charset encoding if known + * + * Create a buffered parser input for the progressive parsing for the input + * from an immutable memory area. This will not copy the memory area to + * the buffer, but the memory is expected to be available until the end of + * the parsing, this is useful for example when using mmap'ed file. + * + * Returns the new parser input or NULL + */ +xmlParserInputBufferPtr +xmlParserInputBufferCreateStatic(const char *mem, int size, + xmlCharEncoding enc) { + xmlParserInputBufferPtr ret; + + if (size <= 0) return(NULL); + if (mem == NULL) return(NULL); + + ret = (xmlParserInputBufferPtr) xmlMalloc(sizeof(xmlParserInputBuffer)); + if (ret == NULL) { + xmlIOErrMemory("creating input buffer"); + return(NULL); + } + memset(ret, 0, (size_t) sizeof(xmlParserInputBuffer)); + ret->buffer = xmlBufferCreateStatic((void *)mem, (size_t) size); + if (ret->buffer == NULL) { + xmlFree(ret); + return(NULL); + } + ret->encoder = xmlGetCharEncodingHandler(enc); + if (ret->encoder != NULL) + ret->raw = xmlBufferCreateSize(2 * xmlDefaultBufferSize); + else + ret->raw = NULL; + ret->compressed = -1; + ret->context = (void *) mem; + ret->readcallback = NULL; + ret->closecallback = NULL; + + return(ret); +} + +#ifdef LIBXML_OUTPUT_ENABLED +/** + * xmlOutputBufferCreateFd: + * @fd: a file descriptor number + * @encoder: the encoding converter or NULL + * + * Create a buffered output for the progressive saving + * to a file descriptor + * + * Returns the new parser output or NULL + */ +xmlOutputBufferPtr +xmlOutputBufferCreateFd(int fd, xmlCharEncodingHandlerPtr encoder) { + xmlOutputBufferPtr ret; + + if (fd < 0) return(NULL); + + ret = xmlAllocOutputBuffer(encoder); + if (ret != NULL) { + ret->context = (void *) (long) fd; + ret->writecallback = xmlFdWrite; + ret->closecallback = NULL; + } + + return(ret); +} +#endif /* LIBXML_OUTPUT_ENABLED */ + +/** + * xmlParserInputBufferCreateIO: + * @ioread: an I/O read function + * @ioclose: an I/O close function + * @ioctx: an I/O handler + * @enc: the charset encoding if known + * + * Create a buffered parser input for the progressive parsing for the input + * from an I/O handler + * + * Returns the new parser input or NULL + */ +xmlParserInputBufferPtr +xmlParserInputBufferCreateIO(xmlInputReadCallback ioread, + xmlInputCloseCallback ioclose, void *ioctx, xmlCharEncoding enc) { + xmlParserInputBufferPtr ret; + + if (ioread == NULL) return(NULL); + + ret = xmlAllocParserInputBuffer(enc); + if (ret != NULL) { + ret->context = (void *) ioctx; + ret->readcallback = ioread; + ret->closecallback = ioclose; + } + + return(ret); +} + +#ifdef LIBXML_OUTPUT_ENABLED +/** + * xmlOutputBufferCreateIO: + * @iowrite: an I/O write function + * @ioclose: an I/O close function + * @ioctx: an I/O handler + * @encoder: the charset encoding if known + * + * Create a buffered output for the progressive saving + * to an I/O handler + * + * Returns the new parser output or NULL + */ +xmlOutputBufferPtr +xmlOutputBufferCreateIO(xmlOutputWriteCallback iowrite, + xmlOutputCloseCallback ioclose, void *ioctx, + xmlCharEncodingHandlerPtr encoder) { + xmlOutputBufferPtr ret; + + if (iowrite == NULL) return(NULL); + + ret = xmlAllocOutputBuffer(encoder); + if (ret != NULL) { + ret->context = (void *) ioctx; + ret->writecallback = iowrite; + ret->closecallback = ioclose; + } + + return(ret); +} +#endif /* LIBXML_OUTPUT_ENABLED */ + +/** + * xmlParserInputBufferCreateFilenameDefault: + * @func: function pointer to the new ParserInputBufferCreateFilenameFunc + * + * Registers a callback for URI input file handling + * + * Returns the old value of the registration function + */ +xmlParserInputBufferCreateFilenameFunc +xmlParserInputBufferCreateFilenameDefault(xmlParserInputBufferCreateFilenameFunc func) +{ + xmlParserInputBufferCreateFilenameFunc old = xmlParserInputBufferCreateFilenameValue; + if (old == NULL) { + old = __xmlParserInputBufferCreateFilename; + } + + xmlParserInputBufferCreateFilenameValue = func; + return(old); +} + +/** + * xmlOutputBufferCreateFilenameDefault: + * @func: function pointer to the new OutputBufferCreateFilenameFunc + * + * Registers a callback for URI output file handling + * + * Returns the old value of the registration function + */ +xmlOutputBufferCreateFilenameFunc +xmlOutputBufferCreateFilenameDefault(xmlOutputBufferCreateFilenameFunc func) +{ + xmlOutputBufferCreateFilenameFunc old = xmlOutputBufferCreateFilenameValue; +#ifdef LIBXML_OUTPUT_ENABLED + if (old == NULL) { + old = __xmlOutputBufferCreateFilename; + } +#endif + xmlOutputBufferCreateFilenameValue = func; + return(old); +} + +/** + * xmlParserInputBufferPush: + * @in: a buffered parser input + * @len: the size in bytes of the array. + * @buf: an char array + * + * Push the content of the arry in the input buffer + * This routine handle the I18N transcoding to internal UTF-8 + * This is used when operating the parser in progressive (push) mode. + * + * Returns the number of chars read and stored in the buffer, or -1 + * in case of error. + */ +int +xmlParserInputBufferPush(xmlParserInputBufferPtr in, + int len, const char *buf) { + int nbchars = 0; + int ret; + + if (len < 0) return(0); + if ((in == NULL) || (in->error)) return(-1); + if (in->encoder != NULL) { + unsigned int use; + + /* + * Store the data in the incoming raw buffer + */ + if (in->raw == NULL) { + in->raw = xmlBufferCreate(); + } + ret = xmlBufferAdd(in->raw, (const xmlChar *) buf, len); + if (ret != 0) + return(-1); + + /* + * convert as much as possible to the parser reading buffer. + */ + use = in->raw->use; + nbchars = xmlCharEncInFunc(in->encoder, in->buffer, in->raw); + if (nbchars < 0) { + xmlIOErr(XML_IO_ENCODER, NULL); + in->error = XML_IO_ENCODER; + return(-1); + } + in->rawconsumed += (use - in->raw->use); + } else { + nbchars = len; + ret = xmlBufferAdd(in->buffer, (xmlChar *) buf, nbchars); + if (ret != 0) + return(-1); + } +#ifdef DEBUG_INPUT + xmlGenericError(xmlGenericErrorContext, + "I/O: pushed %d chars, buffer %d/%d\n", + nbchars, in->buffer->use, in->buffer->size); +#endif + return(nbchars); +} + +/** + * endOfInput: + * + * When reading from an Input channel indicated end of file or error + * don't reread from it again. + */ +static int +endOfInput (void * context ATTRIBUTE_UNUSED, + char * buffer ATTRIBUTE_UNUSED, + int len ATTRIBUTE_UNUSED) { + return(0); +} + +/** + * xmlParserInputBufferGrow: + * @in: a buffered parser input + * @len: indicative value of the amount of chars to read + * + * Grow up the content of the input buffer, the old data are preserved + * This routine handle the I18N transcoding to internal UTF-8 + * This routine is used when operating the parser in normal (pull) mode + * + * TODO: one should be able to remove one extra copy by copying directly + * onto in->buffer or in->raw + * + * Returns the number of chars read and stored in the buffer, or -1 + * in case of error. + */ +int +xmlParserInputBufferGrow(xmlParserInputBufferPtr in, int len) { + char *buffer = NULL; + int res = 0; + int nbchars = 0; + int buffree; + unsigned int needSize; + + if ((in == NULL) || (in->error)) return(-1); + if ((len <= MINLEN) && (len != 4)) + len = MINLEN; + + buffree = in->buffer->size - in->buffer->use; + if (buffree <= 0) { + xmlIOErr(XML_IO_BUFFER_FULL, NULL); + in->error = XML_IO_BUFFER_FULL; + return(-1); + } + + needSize = in->buffer->use + len + 1; + if (needSize > in->buffer->size){ + if (!xmlBufferResize(in->buffer, needSize)){ + xmlIOErrMemory("growing input buffer"); + in->error = XML_ERR_NO_MEMORY; + return(-1); + } + } + buffer = (char *)&in->buffer->content[in->buffer->use]; + + /* + * Call the read method for this I/O type. + */ + if (in->readcallback != NULL) { + res = in->readcallback(in->context, &buffer[0], len); + if (res <= 0) + in->readcallback = endOfInput; + } else { + xmlIOErr(XML_IO_NO_INPUT, NULL); + in->error = XML_IO_NO_INPUT; + return(-1); + } + if (res < 0) { + return(-1); + } + len = res; + if (in->encoder != NULL) { + unsigned int use; + + /* + * Store the data in the incoming raw buffer + */ + if (in->raw == NULL) { + in->raw = xmlBufferCreate(); + } + res = xmlBufferAdd(in->raw, (const xmlChar *) buffer, len); + if (res != 0) + return(-1); + + /* + * convert as much as possible to the parser reading buffer. + */ + use = in->raw->use; + nbchars = xmlCharEncInFunc(in->encoder, in->buffer, in->raw); + if (nbchars < 0) { + xmlIOErr(XML_IO_ENCODER, NULL); + in->error = XML_IO_ENCODER; + return(-1); + } + in->rawconsumed += (use - in->raw->use); + } else { + nbchars = len; + in->buffer->use += nbchars; + buffer[nbchars] = 0; + } +#ifdef DEBUG_INPUT + xmlGenericError(xmlGenericErrorContext, + "I/O: read %d chars, buffer %d/%d\n", + nbchars, in->buffer->use, in->buffer->size); +#endif + return(nbchars); +} + +/** + * xmlParserInputBufferRead: + * @in: a buffered parser input + * @len: indicative value of the amount of chars to read + * + * Refresh the content of the input buffer, the old data are considered + * consumed + * This routine handle the I18N transcoding to internal UTF-8 + * + * Returns the number of chars read and stored in the buffer, or -1 + * in case of error. + */ +int +xmlParserInputBufferRead(xmlParserInputBufferPtr in, int len) { + if ((in == NULL) || (in->error)) return(-1); + if (in->readcallback != NULL) + return(xmlParserInputBufferGrow(in, len)); + else if ((in->buffer != NULL) && + (in->buffer->alloc == XML_BUFFER_ALLOC_IMMUTABLE)) + return(0); + else + return(-1); +} + +#ifdef LIBXML_OUTPUT_ENABLED +/** + * xmlOutputBufferWrite: + * @out: a buffered parser output + * @len: the size in bytes of the array. + * @buf: an char array + * + * Write the content of the array in the output I/O buffer + * This routine handle the I18N transcoding from internal UTF-8 + * The buffer is lossless, i.e. will store in case of partial + * or delayed writes. + * + * Returns the number of chars immediately written, or -1 + * in case of error. + */ +int +xmlOutputBufferWrite(xmlOutputBufferPtr out, int len, const char *buf) { + int nbchars = 0; /* number of chars to output to I/O */ + int ret; /* return from function call */ + int written = 0; /* number of char written to I/O so far */ + int chunk; /* number of byte curreent processed from buf */ + + if ((out == NULL) || (out->error)) return(-1); + if (len < 0) return(0); + if (out->error) return(-1); + + do { + chunk = len; + if (chunk > 4 * MINLEN) + chunk = 4 * MINLEN; + + /* + * first handle encoding stuff. + */ + if (out->encoder != NULL) { + /* + * Store the data in the incoming raw buffer + */ + if (out->conv == NULL) { + out->conv = xmlBufferCreate(); + } + ret = xmlBufferAdd(out->buffer, (const xmlChar *) buf, chunk); + if (ret != 0) + return(-1); + + if ((out->buffer->use < MINLEN) && (chunk == len)) + goto done; + + /* + * convert as much as possible to the parser reading buffer. + */ + ret = xmlCharEncOutFunc(out->encoder, out->conv, out->buffer); + if ((ret < 0) && (ret != -3)) { + xmlIOErr(XML_IO_ENCODER, NULL); + out->error = XML_IO_ENCODER; + return(-1); + } + nbchars = out->conv->use; + } else { + ret = xmlBufferAdd(out->buffer, (const xmlChar *) buf, chunk); + if (ret != 0) + return(-1); + nbchars = out->buffer->use; + } + buf += chunk; + len -= chunk; + + if ((nbchars < MINLEN) && (len <= 0)) + goto done; + + if (out->writecallback) { + /* + * second write the stuff to the I/O channel + */ + if (out->encoder != NULL) { + ret = out->writecallback(out->context, + (const char *)out->conv->content, nbchars); + if (ret >= 0) + xmlBufferShrink(out->conv, ret); + } else { + ret = out->writecallback(out->context, + (const char *)out->buffer->content, nbchars); + if (ret >= 0) + xmlBufferShrink(out->buffer, ret); + } + if (ret < 0) { + xmlIOErr(XML_IO_WRITE, NULL); + out->error = XML_IO_WRITE; + return(ret); + } + out->written += ret; + } + written += nbchars; + } while (len > 0); + +done: +#ifdef DEBUG_INPUT + xmlGenericError(xmlGenericErrorContext, + "I/O: wrote %d chars\n", written); +#endif + return(written); +} + +/** + * xmlEscapeContent: + * @out: a pointer to an array of bytes to store the result + * @outlen: the length of @out + * @in: a pointer to an array of unescaped UTF-8 bytes + * @inlen: the length of @in + * + * Take a block of UTF-8 chars in and escape them. + * Returns 0 if success, or -1 otherwise + * The value of @inlen after return is the number of octets consumed + * if the return value is positive, else unpredictable. + * The value of @outlen after return is the number of octets consumed. + */ +static int +xmlEscapeContent(unsigned char* out, int *outlen, + const xmlChar* in, int *inlen) { + unsigned char* outstart = out; + const unsigned char* base = in; + unsigned char* outend = out + *outlen; + const unsigned char* inend; + + inend = in + (*inlen); + + while ((in < inend) && (out < outend)) { + if (*in == '<') { + if (outend - out < 4) break; + *out++ = '&'; + *out++ = 'l'; + *out++ = 't'; + *out++ = ';'; + } else if (*in == '>') { + if (outend - out < 4) break; + *out++ = '&'; + *out++ = 'g'; + *out++ = 't'; + *out++ = ';'; + } else if (*in == '&') { + if (outend - out < 5) break; + *out++ = '&'; + *out++ = 'a'; + *out++ = 'm'; + *out++ = 'p'; + *out++ = ';'; + } else if (*in == '\r') { + if (outend - out < 5) break; + *out++ = '&'; + *out++ = '#'; + *out++ = '1'; + *out++ = '3'; + *out++ = ';'; + } else { + *out++ = (unsigned char) *in; + } + ++in; + } + *outlen = out - outstart; + *inlen = in - base; + return(0); +} + +/** + * xmlOutputBufferWriteEscape: + * @out: a buffered parser output + * @str: a zero terminated UTF-8 string + * @escaping: an optional escaping function (or NULL) + * + * Write the content of the string in the output I/O buffer + * This routine escapes the caracters and then handle the I18N + * transcoding from internal UTF-8 + * The buffer is lossless, i.e. will store in case of partial + * or delayed writes. + * + * Returns the number of chars immediately written, or -1 + * in case of error. + */ +int +xmlOutputBufferWriteEscape(xmlOutputBufferPtr out, const xmlChar *str, + xmlCharEncodingOutputFunc escaping) { + int nbchars = 0; /* number of chars to output to I/O */ + int ret; /* return from function call */ + int written = 0; /* number of char written to I/O so far */ + int oldwritten=0;/* loop guard */ + int chunk; /* number of byte currently processed from str */ + int len; /* number of bytes in str */ + int cons; /* byte from str consumed */ + + if ((out == NULL) || (out->error) || (str == NULL) || + (out->buffer == NULL) || + (out->buffer->alloc == XML_BUFFER_ALLOC_IMMUTABLE)) return(-1); + len = strlen((const char *)str); + if (len < 0) return(0); + if (out->error) return(-1); + if (escaping == NULL) escaping = xmlEscapeContent; + + do { + oldwritten = written; + + /* + * how many bytes to consume and how many bytes to store. + */ + cons = len; + chunk = (out->buffer->size - out->buffer->use) - 1; + + /* + * first handle encoding stuff. + */ + if (out->encoder != NULL) { + /* + * Store the data in the incoming raw buffer + */ + if (out->conv == NULL) { + out->conv = xmlBufferCreate(); + } + ret = escaping(out->buffer->content + out->buffer->use , + &chunk, str, &cons); + if ((ret < 0) || (chunk == 0)) /* chunk==0 => nothing done */ + return(-1); + out->buffer->use += chunk; + out->buffer->content[out->buffer->use] = 0; + + if ((out->buffer->use < MINLEN) && (cons == len)) + goto done; + + /* + * convert as much as possible to the output buffer. + */ + ret = xmlCharEncOutFunc(out->encoder, out->conv, out->buffer); + if ((ret < 0) && (ret != -3)) { + xmlIOErr(XML_IO_ENCODER, NULL); + out->error = XML_IO_ENCODER; + return(-1); + } + nbchars = out->conv->use; + } else { + ret = escaping(out->buffer->content + out->buffer->use , + &chunk, str, &cons); + if ((ret < 0) || (chunk == 0)) /* chunk==0 => nothing done */ + return(-1); + out->buffer->use += chunk; + out->buffer->content[out->buffer->use] = 0; + nbchars = out->buffer->use; + } + str += cons; + len -= cons; + + if ((nbchars < MINLEN) && (len <= 0)) + goto done; + + if (out->writecallback) { + /* + * second write the stuff to the I/O channel + */ + if (out->encoder != NULL) { + ret = out->writecallback(out->context, + (const char *)out->conv->content, nbchars); + if (ret >= 0) + xmlBufferShrink(out->conv, ret); + } else { + ret = out->writecallback(out->context, + (const char *)out->buffer->content, nbchars); + if (ret >= 0) + xmlBufferShrink(out->buffer, ret); + } + if (ret < 0) { + xmlIOErr(XML_IO_WRITE, NULL); + out->error = XML_IO_WRITE; + return(ret); + } + out->written += ret; + } else if (out->buffer->size - out->buffer->use < MINLEN) { + xmlBufferResize(out->buffer, out->buffer->size + MINLEN); + } + written += nbchars; + } while ((len > 0) && (oldwritten != written)); + +done: +#ifdef DEBUG_INPUT + xmlGenericError(xmlGenericErrorContext, + "I/O: wrote %d chars\n", written); +#endif + return(written); +} + +/** + * xmlOutputBufferWriteString: + * @out: a buffered parser output + * @str: a zero terminated C string + * + * Write the content of the string in the output I/O buffer + * This routine handle the I18N transcoding from internal UTF-8 + * The buffer is lossless, i.e. will store in case of partial + * or delayed writes. + * + * Returns the number of chars immediately written, or -1 + * in case of error. + */ +int +xmlOutputBufferWriteString(xmlOutputBufferPtr out, const char *str) { + int len; + + if ((out == NULL) || (out->error)) return(-1); + if (str == NULL) + return(-1); + len = strlen(str); + + if (len > 0) + return(xmlOutputBufferWrite(out, len, str)); + return(len); +} + +/** + * xmlOutputBufferFlush: + * @out: a buffered output + * + * flushes the output I/O channel + * + * Returns the number of byte written or -1 in case of error. + */ +int +xmlOutputBufferFlush(xmlOutputBufferPtr out) { + int nbchars = 0, ret = 0; + + if ((out == NULL) || (out->error)) return(-1); + /* + * first handle encoding stuff. + */ + if ((out->conv != NULL) && (out->encoder != NULL)) { + /* + * convert as much as possible to the parser reading buffer. + */ + nbchars = xmlCharEncOutFunc(out->encoder, out->conv, out->buffer); + if (nbchars < 0) { + xmlIOErr(XML_IO_ENCODER, NULL); + out->error = XML_IO_ENCODER; + return(-1); + } + } + + /* + * second flush the stuff to the I/O channel + */ + if ((out->conv != NULL) && (out->encoder != NULL) && + (out->writecallback != NULL)) { + ret = out->writecallback(out->context, + (const char *)out->conv->content, out->conv->use); + if (ret >= 0) + xmlBufferShrink(out->conv, ret); + } else if (out->writecallback != NULL) { + ret = out->writecallback(out->context, + (const char *)out->buffer->content, out->buffer->use); + if (ret >= 0) + xmlBufferShrink(out->buffer, ret); + } + if (ret < 0) { + xmlIOErr(XML_IO_FLUSH, NULL); + out->error = XML_IO_FLUSH; + return(ret); + } + out->written += ret; + +#ifdef DEBUG_INPUT + xmlGenericError(xmlGenericErrorContext, + "I/O: flushed %d chars\n", ret); +#endif + return(ret); +} +#endif /* LIBXML_OUTPUT_ENABLED */ + +/** + * xmlParserGetDirectory: + * @filename: the path to a file + * + * lookup the directory for that file + * + * Returns a new allocated string containing the directory, or NULL. + */ +char * +xmlParserGetDirectory(const char *filename) { + char *ret = NULL; + char dir[1024]; + char *cur; + char sep = '/'; + +#ifdef _WIN32_WCE /* easy way by now ... wince does not have dirs! */ + return NULL; +#endif + + if (xmlInputCallbackInitialized == 0) + xmlRegisterDefaultInputCallbacks(); + + if (filename == NULL) return(NULL); +#if defined(WIN32) && !defined(__CYGWIN__) + sep = '\\'; +#endif + + strncpy(dir, filename, 1023); + dir[1023] = 0; + cur = &dir[strlen(dir)]; + while (cur > dir) { + if (*cur == sep) break; + cur --; + } + if (*cur == sep) { + if (cur == dir) dir[1] = 0; + else *cur = 0; + ret = xmlMemStrdup(dir); + } else { + if (getcwd(dir, 1024) != NULL) { + dir[1023] = 0; + ret = xmlMemStrdup(dir); + } + } + return(ret); +} + +/**************************************************************** + * * + * External entities loading * + * * + ****************************************************************/ + +/** + * xmlCheckHTTPInput: + * @ctxt: an XML parser context + * @ret: an XML parser input + * + * Check an input in case it was created from an HTTP stream, in that + * case it will handle encoding and update of the base URL in case of + * redirection. It also checks for HTTP errors in which case the input + * is cleanly freed up and an appropriate error is raised in context + * + * Returns the input or NULL in case of HTTP error. + */ +xmlParserInputPtr +xmlCheckHTTPInput(xmlParserCtxtPtr ctxt, xmlParserInputPtr ret) { +#ifdef LIBXML_HTTP_ENABLED + if ((ret != NULL) && (ret->buf != NULL) && + (ret->buf->readcallback == xmlIOHTTPRead) && + (ret->buf->context != NULL)) { + const char *encoding; + const char *redir; + const char *mime; + int code; + + code = xmlNanoHTTPReturnCode(ret->buf->context); + if (code >= 400) { + /* fatal error */ + if (ret->filename != NULL) + __xmlLoaderErr(ctxt, "failed to load HTTP resource \"%s\"\n", + (const char *) ret->filename); + else + __xmlLoaderErr(ctxt, "failed to load HTTP resource\n", NULL); + xmlFreeInputStream(ret); + ret = NULL; + } else { + + mime = xmlNanoHTTPMimeType(ret->buf->context); + if ((xmlStrstr(BAD_CAST mime, BAD_CAST "/xml")) || + (xmlStrstr(BAD_CAST mime, BAD_CAST "+xml"))) { + encoding = xmlNanoHTTPEncoding(ret->buf->context); + if (encoding != NULL) { + xmlCharEncodingHandlerPtr handler; + + handler = xmlFindCharEncodingHandler(encoding); + if (handler != NULL) { + xmlSwitchInputEncoding(ctxt, ret, handler); + } else { + __xmlErrEncoding(ctxt, XML_ERR_UNKNOWN_ENCODING, + "Unknown encoding %s", + BAD_CAST encoding, NULL); + } + if (ret->encoding == NULL) + ret->encoding = xmlStrdup(BAD_CAST encoding); + } +#if 0 + } else if (xmlStrstr(BAD_CAST mime, BAD_CAST "html")) { +#endif + } + redir = xmlNanoHTTPRedir(ret->buf->context); + if (redir != NULL) { + if (ret->filename != NULL) + xmlFree((xmlChar *) ret->filename); + if (ret->directory != NULL) { + xmlFree((xmlChar *) ret->directory); + ret->directory = NULL; + } + ret->filename = + (char *) xmlStrdup((const xmlChar *) redir); + } + } + } +#endif + return(ret); +} + +static int xmlNoNetExists(const char *URL) { + const char *path; + + if (URL == NULL) + return(0); + + if (!xmlStrncasecmp(BAD_CAST URL, BAD_CAST "file://localhost/", 17)) +#if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__) + path = &URL[17]; +#else + path = &URL[16]; +#endif + else if (!xmlStrncasecmp(BAD_CAST URL, BAD_CAST "file:///", 8)) { +#if defined (_WIN32) || defined (__DJGPP__) && !defined(__CYGWIN__) + path = &URL[8]; +#else + path = &URL[7]; +#endif + } else + path = URL; + + return xmlCheckFilename(path); +} + +#ifdef LIBXML_CATALOG_ENABLED + +/** + * xmlResolveResourceFromCatalog: + * @URL: the URL for the entity to load + * @ID: the System ID for the entity to load + * @ctxt: the context in which the entity is called or NULL + * + * Resolves the URL and ID against the appropriate catalog. + * This function is used by xmlDefaultExternalEntityLoader and + * xmlNoNetExternalEntityLoader. + * + * Returns a new allocated URL, or NULL. + */ +xmlChar * +xmlResolveResourceFromCatalog(const char *URL, const char *ID, + xmlParserCtxtPtr ctxt) { + xmlChar *resource = NULL; + xmlCatalogAllow pref; + + /* + * If the resource doesn't exists as a file, + * try to load it from the resource pointed in the catalogs + */ + pref = xmlCatalogGetDefaults(); + + if ((pref != XML_CATA_ALLOW_NONE) && (!xmlNoNetExists(URL))) { + /* + * Do a local lookup + */ + if ((ctxt != NULL) && (ctxt->catalogs != NULL) && + ((pref == XML_CATA_ALLOW_ALL) || + (pref == XML_CATA_ALLOW_DOCUMENT))) { + resource = xmlCatalogLocalResolve(ctxt->catalogs, + (const xmlChar *)ID, + (const xmlChar *)URL); + } + /* + * Try a global lookup + */ + if ((resource == NULL) && + ((pref == XML_CATA_ALLOW_ALL) || + (pref == XML_CATA_ALLOW_GLOBAL))) { + resource = xmlCatalogResolve((const xmlChar *)ID, + (const xmlChar *)URL); + } + if ((resource == NULL) && (URL != NULL)) + resource = xmlStrdup((const xmlChar *) URL); + + /* + * TODO: do an URI lookup on the reference + */ + if ((resource != NULL) && (!xmlNoNetExists((const char *)resource))) { + xmlChar *tmp = NULL; + + if ((ctxt != NULL) && (ctxt->catalogs != NULL) && + ((pref == XML_CATA_ALLOW_ALL) || + (pref == XML_CATA_ALLOW_DOCUMENT))) { + tmp = xmlCatalogLocalResolveURI(ctxt->catalogs, resource); + } + if ((tmp == NULL) && + ((pref == XML_CATA_ALLOW_ALL) || + (pref == XML_CATA_ALLOW_GLOBAL))) { + tmp = xmlCatalogResolveURI(resource); + } + + if (tmp != NULL) { + xmlFree(resource); + resource = tmp; + } + } + } + + return resource; +} + +#endif + +/** + * xmlDefaultExternalEntityLoader: + * @URL: the URL for the entity to load + * @ID: the System ID for the entity to load + * @ctxt: the context in which the entity is called or NULL + * + * By default we don't load external entitites, yet. + * + * Returns a new allocated xmlParserInputPtr, or NULL. + */ +static xmlParserInputPtr +xmlDefaultExternalEntityLoader(const char *URL, const char *ID, + xmlParserCtxtPtr ctxt) +{ + xmlParserInputPtr ret = NULL; + xmlChar *resource = NULL; + +#ifdef DEBUG_EXTERNAL_ENTITIES + xmlGenericError(xmlGenericErrorContext, + "xmlDefaultExternalEntityLoader(%s, xxx)\n", URL); +#endif + if ((ctxt != NULL) && (ctxt->options & XML_PARSE_NONET)) { + int options = ctxt->options; + + ctxt->options -= XML_PARSE_NONET; + ret = xmlNoNetExternalEntityLoader(URL, ID, ctxt); + ctxt->options = options; + return(ret); + } +#ifdef LIBXML_CATALOG_ENABLED + resource = xmlResolveResourceFromCatalog(URL, ID, ctxt); +#endif + + if (resource == NULL) + resource = (xmlChar *) URL; + + if (resource == NULL) { + if (ID == NULL) + ID = "NULL"; + __xmlLoaderErr(ctxt, "failed to load external entity \"%s\"\n", ID); + return (NULL); + } + ret = xmlNewInputFromFile(ctxt, (const char *) resource); + if ((resource != NULL) && (resource != (xmlChar *) URL)) + xmlFree(resource); + return (ret); +} + +static xmlExternalEntityLoader xmlCurrentExternalEntityLoader = + xmlDefaultExternalEntityLoader; + +/** + * xmlSetExternalEntityLoader: + * @f: the new entity resolver function + * + * Changes the defaultexternal entity resolver function for the application + */ +void +xmlSetExternalEntityLoader(xmlExternalEntityLoader f) { + xmlCurrentExternalEntityLoader = f; +} + +/** + * xmlGetExternalEntityLoader: + * + * Get the default external entity resolver function for the application + * + * Returns the xmlExternalEntityLoader function pointer + */ +xmlExternalEntityLoader +xmlGetExternalEntityLoader(void) { + return(xmlCurrentExternalEntityLoader); +} + +/** + * xmlLoadExternalEntity: + * @URL: the URL for the entity to load + * @ID: the Public ID for the entity to load + * @ctxt: the context in which the entity is called or NULL + * + * Load an external entity, note that the use of this function for + * unparsed entities may generate problems + * + * Returns the xmlParserInputPtr or NULL + */ +xmlParserInputPtr +xmlLoadExternalEntity(const char *URL, const char *ID, + xmlParserCtxtPtr ctxt) { + if ((URL != NULL) && (xmlNoNetExists(URL) == 0)) { + char *canonicFilename; + xmlParserInputPtr ret; + + canonicFilename = (char *) xmlCanonicPath((const xmlChar *) URL); + if (canonicFilename == NULL) { + xmlIOErrMemory("building canonical path\n"); + return(NULL); + } + + ret = xmlCurrentExternalEntityLoader(canonicFilename, ID, ctxt); + xmlFree(canonicFilename); + return(ret); + } + return(xmlCurrentExternalEntityLoader(URL, ID, ctxt)); +} + +/************************************************************************ + * * + * Disabling Network access * + * * + ************************************************************************/ + +/** + * xmlNoNetExternalEntityLoader: + * @URL: the URL for the entity to load + * @ID: the System ID for the entity to load + * @ctxt: the context in which the entity is called or NULL + * + * A specific entity loader disabling network accesses, though still + * allowing local catalog accesses for resolution. + * + * Returns a new allocated xmlParserInputPtr, or NULL. + */ +xmlParserInputPtr +xmlNoNetExternalEntityLoader(const char *URL, const char *ID, + xmlParserCtxtPtr ctxt) { + xmlParserInputPtr input = NULL; + xmlChar *resource = NULL; + +#ifdef LIBXML_CATALOG_ENABLED + resource = xmlResolveResourceFromCatalog(URL, ID, ctxt); +#endif + + if (resource == NULL) + resource = (xmlChar *) URL; + + if (resource != NULL) { + if ((!xmlStrncasecmp(BAD_CAST resource, BAD_CAST "ftp://", 6)) || + (!xmlStrncasecmp(BAD_CAST resource, BAD_CAST "http://", 7))) { + xmlIOErr(XML_IO_NETWORK_ATTEMPT, (const char *) resource); + if (resource != (xmlChar *) URL) + xmlFree(resource); + return(NULL); + } + } + input = xmlDefaultExternalEntityLoader((const char *) resource, ID, ctxt); + if (resource != (xmlChar *) URL) + xmlFree(resource); + return(input); +} + +#define bottom_xmlIO +#include "elfgcchack.h" diff --git a/gettext-tools/gnulib-lib/libxml/xmlIO.in.h b/gettext-tools/gnulib-lib/libxml/xmlIO.in.h new file mode 100644 index 0000000..eea9ed6 --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/xmlIO.in.h @@ -0,0 +1,360 @@ +/* + * Summary: interface for the I/O interfaces used by the parser + * Description: interface for the I/O interfaces used by the parser + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + +#ifndef __XML_IO_H__ +#define __XML_IO_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Those are the functions and datatypes for the parser input + * I/O structures. + */ + +/** + * xmlInputMatchCallback: + * @filename: the filename or URI + * + * Callback used in the I/O Input API to detect if the current handler + * can provide input fonctionnalities for this resource. + * + * Returns 1 if yes and 0 if another Input module should be used + */ +typedef int (XMLCALL *xmlInputMatchCallback) (char const *filename); +/** + * xmlInputOpenCallback: + * @filename: the filename or URI + * + * Callback used in the I/O Input API to open the resource + * + * Returns an Input context or NULL in case or error + */ +typedef void * (XMLCALL *xmlInputOpenCallback) (char const *filename); +/** + * xmlInputReadCallback: + * @context: an Input context + * @buffer: the buffer to store data read + * @len: the length of the buffer in bytes + * + * Callback used in the I/O Input API to read the resource + * + * Returns the number of bytes read or -1 in case of error + */ +typedef int (XMLCALL *xmlInputReadCallback) (void * context, char * buffer, int len); +/** + * xmlInputCloseCallback: + * @context: an Input context + * + * Callback used in the I/O Input API to close the resource + * + * Returns 0 or -1 in case of error + */ +typedef int (XMLCALL *xmlInputCloseCallback) (void * context); + +#ifdef LIBXML_OUTPUT_ENABLED +/* + * Those are the functions and datatypes for the library output + * I/O structures. + */ + +/** + * xmlOutputMatchCallback: + * @filename: the filename or URI + * + * Callback used in the I/O Output API to detect if the current handler + * can provide output fonctionnalities for this resource. + * + * Returns 1 if yes and 0 if another Output module should be used + */ +typedef int (XMLCALL *xmlOutputMatchCallback) (char const *filename); +/** + * xmlOutputOpenCallback: + * @filename: the filename or URI + * + * Callback used in the I/O Output API to open the resource + * + * Returns an Output context or NULL in case or error + */ +typedef void * (XMLCALL *xmlOutputOpenCallback) (char const *filename); +/** + * xmlOutputWriteCallback: + * @context: an Output context + * @buffer: the buffer of data to write + * @len: the length of the buffer in bytes + * + * Callback used in the I/O Output API to write to the resource + * + * Returns the number of bytes written or -1 in case of error + */ +typedef int (XMLCALL *xmlOutputWriteCallback) (void * context, const char * buffer, + int len); +/** + * xmlOutputCloseCallback: + * @context: an Output context + * + * Callback used in the I/O Output API to close the resource + * + * Returns 0 or -1 in case of error + */ +typedef int (XMLCALL *xmlOutputCloseCallback) (void * context); +#endif /* LIBXML_OUTPUT_ENABLED */ + +#ifdef __cplusplus +} +#endif + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif +struct _xmlParserInputBuffer { + void* context; + xmlInputReadCallback readcallback; + xmlInputCloseCallback closecallback; + + xmlCharEncodingHandlerPtr encoder; /* I18N conversions to UTF-8 */ + + xmlBufferPtr buffer; /* Local buffer encoded in UTF-8 */ + xmlBufferPtr raw; /* if encoder != NULL buffer for raw input */ + int compressed; /* -1=unknown, 0=not compressed, 1=compressed */ + int error; + unsigned long rawconsumed;/* amount consumed from raw */ +}; + + +#ifdef LIBXML_OUTPUT_ENABLED +struct _xmlOutputBuffer { + void* context; + xmlOutputWriteCallback writecallback; + xmlOutputCloseCallback closecallback; + + xmlCharEncodingHandlerPtr encoder; /* I18N conversions to UTF-8 */ + + xmlBufferPtr buffer; /* Local buffer encoded in UTF-8 or ISOLatin */ + xmlBufferPtr conv; /* if encoder != NULL buffer for output */ + int written; /* total number of byte written */ + int error; +}; +#endif /* LIBXML_OUTPUT_ENABLED */ + +/* + * Interfaces for input + */ +XMLPUBFUN void XMLCALL + xmlCleanupInputCallbacks (void); + +XMLPUBFUN int XMLCALL + xmlPopInputCallbacks (void); + +XMLPUBFUN void XMLCALL + xmlRegisterDefaultInputCallbacks (void); +XMLPUBFUN xmlParserInputBufferPtr XMLCALL + xmlAllocParserInputBuffer (xmlCharEncoding enc); + +XMLPUBFUN xmlParserInputBufferPtr XMLCALL + xmlParserInputBufferCreateFilename (const char *URI, + xmlCharEncoding enc); +XMLPUBFUN xmlParserInputBufferPtr XMLCALL + xmlParserInputBufferCreateFile (FILE *file, + xmlCharEncoding enc); +XMLPUBFUN xmlParserInputBufferPtr XMLCALL + xmlParserInputBufferCreateFd (int fd, + xmlCharEncoding enc); +XMLPUBFUN xmlParserInputBufferPtr XMLCALL + xmlParserInputBufferCreateMem (const char *mem, int size, + xmlCharEncoding enc); +XMLPUBFUN xmlParserInputBufferPtr XMLCALL + xmlParserInputBufferCreateStatic (const char *mem, int size, + xmlCharEncoding enc); +XMLPUBFUN xmlParserInputBufferPtr XMLCALL + xmlParserInputBufferCreateIO (xmlInputReadCallback ioread, + xmlInputCloseCallback ioclose, + void *ioctx, + xmlCharEncoding enc); +XMLPUBFUN int XMLCALL + xmlParserInputBufferRead (xmlParserInputBufferPtr in, + int len); +XMLPUBFUN int XMLCALL + xmlParserInputBufferGrow (xmlParserInputBufferPtr in, + int len); +XMLPUBFUN int XMLCALL + xmlParserInputBufferPush (xmlParserInputBufferPtr in, + int len, + const char *buf); +XMLPUBFUN void XMLCALL + xmlFreeParserInputBuffer (xmlParserInputBufferPtr in); +XMLPUBFUN char * XMLCALL + xmlParserGetDirectory (const char *filename); + +XMLPUBFUN int XMLCALL + xmlRegisterInputCallbacks (xmlInputMatchCallback matchFunc, + xmlInputOpenCallback openFunc, + xmlInputReadCallback readFunc, + xmlInputCloseCallback closeFunc); + +xmlParserInputBufferPtr + __xmlParserInputBufferCreateFilename(const char *URI, + xmlCharEncoding enc); + +#ifdef LIBXML_OUTPUT_ENABLED +/* + * Interfaces for output + */ +XMLPUBFUN void XMLCALL + xmlCleanupOutputCallbacks (void); +XMLPUBFUN void XMLCALL + xmlRegisterDefaultOutputCallbacks(void); +XMLPUBFUN xmlOutputBufferPtr XMLCALL + xmlAllocOutputBuffer (xmlCharEncodingHandlerPtr encoder); + +XMLPUBFUN xmlOutputBufferPtr XMLCALL + xmlOutputBufferCreateFilename (const char *URI, + xmlCharEncodingHandlerPtr encoder, + int compression); + +XMLPUBFUN xmlOutputBufferPtr XMLCALL + xmlOutputBufferCreateFile (FILE *file, + xmlCharEncodingHandlerPtr encoder); + +XMLPUBFUN xmlOutputBufferPtr XMLCALL + xmlOutputBufferCreateBuffer (xmlBufferPtr buffer, + xmlCharEncodingHandlerPtr encoder); + +XMLPUBFUN xmlOutputBufferPtr XMLCALL + xmlOutputBufferCreateFd (int fd, + xmlCharEncodingHandlerPtr encoder); + +XMLPUBFUN xmlOutputBufferPtr XMLCALL + xmlOutputBufferCreateIO (xmlOutputWriteCallback iowrite, + xmlOutputCloseCallback ioclose, + void *ioctx, + xmlCharEncodingHandlerPtr encoder); + +XMLPUBFUN int XMLCALL + xmlOutputBufferWrite (xmlOutputBufferPtr out, + int len, + const char *buf); +XMLPUBFUN int XMLCALL + xmlOutputBufferWriteString (xmlOutputBufferPtr out, + const char *str); +XMLPUBFUN int XMLCALL + xmlOutputBufferWriteEscape (xmlOutputBufferPtr out, + const xmlChar *str, + xmlCharEncodingOutputFunc escaping); + +XMLPUBFUN int XMLCALL + xmlOutputBufferFlush (xmlOutputBufferPtr out); +XMLPUBFUN int XMLCALL + xmlOutputBufferClose (xmlOutputBufferPtr out); + +XMLPUBFUN int XMLCALL + xmlRegisterOutputCallbacks (xmlOutputMatchCallback matchFunc, + xmlOutputOpenCallback openFunc, + xmlOutputWriteCallback writeFunc, + xmlOutputCloseCallback closeFunc); + +xmlOutputBufferPtr + __xmlOutputBufferCreateFilename(const char *URI, + xmlCharEncodingHandlerPtr encoder, + int compression); + +#ifdef LIBXML_HTTP_ENABLED +/* This function only exists if HTTP support built into the library */ +XMLPUBFUN void XMLCALL + xmlRegisterHTTPPostCallbacks (void ); +#endif /* LIBXML_HTTP_ENABLED */ + +#endif /* LIBXML_OUTPUT_ENABLED */ + +XMLPUBFUN xmlParserInputPtr XMLCALL + xmlCheckHTTPInput (xmlParserCtxtPtr ctxt, + xmlParserInputPtr ret); + +/* + * A predefined entity loader disabling network accesses + */ +XMLPUBFUN xmlParserInputPtr XMLCALL + xmlNoNetExternalEntityLoader (const char *URL, + const char *ID, + xmlParserCtxtPtr ctxt); + +/* + * xmlNormalizeWindowsPath is obsolete, don't use it. + * Check xmlCanonicPath in uri.h for a better alternative. + */ +XMLPUBFUN xmlChar * XMLCALL + xmlNormalizeWindowsPath (const xmlChar *path); + +XMLPUBFUN int XMLCALL + xmlCheckFilename (const char *path); +/** + * Default 'file://' protocol callbacks + */ +XMLPUBFUN int XMLCALL + xmlFileMatch (const char *filename); +XMLPUBFUN void * XMLCALL + xmlFileOpen (const char *filename); +XMLPUBFUN int XMLCALL + xmlFileRead (void * context, + char * buffer, + int len); +XMLPUBFUN int XMLCALL + xmlFileClose (void * context); + +/** + * Default 'http://' protocol callbacks + */ +#ifdef LIBXML_HTTP_ENABLED +XMLPUBFUN int XMLCALL + xmlIOHTTPMatch (const char *filename); +XMLPUBFUN void * XMLCALL + xmlIOHTTPOpen (const char *filename); +#ifdef LIBXML_OUTPUT_ENABLED +XMLPUBFUN void * XMLCALL + xmlIOHTTPOpenW (const char * post_uri, + int compression ); +#endif /* LIBXML_OUTPUT_ENABLED */ +XMLPUBFUN int XMLCALL + xmlIOHTTPRead (void * context, + char * buffer, + int len); +XMLPUBFUN int XMLCALL + xmlIOHTTPClose (void * context); +#endif /* LIBXML_HTTP_ENABLED */ + +/** + * Default 'ftp://' protocol callbacks + */ +#ifdef LIBXML_FTP_ENABLED +XMLPUBFUN int XMLCALL + xmlIOFTPMatch (const char *filename); +XMLPUBFUN void * XMLCALL + xmlIOFTPOpen (const char *filename); +XMLPUBFUN int XMLCALL + xmlIOFTPRead (void * context, + char * buffer, + int len); +XMLPUBFUN int XMLCALL + xmlIOFTPClose (void * context); +#endif /* LIBXML_FTP_ENABLED */ + +#ifdef __cplusplus +} +#endif + +#endif /* __XML_IO_H__ */ diff --git a/gettext-tools/gnulib-lib/libxml/xmlautomata.in.h b/gettext-tools/gnulib-lib/libxml/xmlautomata.in.h new file mode 100644 index 0000000..f98b55e --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/xmlautomata.in.h @@ -0,0 +1,146 @@ +/* + * Summary: API to build regexp automata + * Description: the API to build regexp automata + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + +#ifndef __XML_AUTOMATA_H__ +#define __XML_AUTOMATA_H__ + +#include +#include + +#ifdef LIBXML_REGEXP_ENABLED +#ifdef LIBXML_AUTOMATA_ENABLED +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * xmlAutomataPtr: + * + * A libxml automata description, It can be compiled into a regexp + */ +typedef struct _xmlAutomata xmlAutomata; +typedef xmlAutomata *xmlAutomataPtr; + +/** + * xmlAutomataStatePtr: + * + * A state int the automata description, + */ +typedef struct _xmlAutomataState xmlAutomataState; +typedef xmlAutomataState *xmlAutomataStatePtr; + +/* + * Building API + */ +XMLPUBFUN xmlAutomataPtr XMLCALL + xmlNewAutomata (void); +XMLPUBFUN void XMLCALL + xmlFreeAutomata (xmlAutomataPtr am); + +XMLPUBFUN xmlAutomataStatePtr XMLCALL + xmlAutomataGetInitState (xmlAutomataPtr am); +XMLPUBFUN int XMLCALL + xmlAutomataSetFinalState (xmlAutomataPtr am, + xmlAutomataStatePtr state); +XMLPUBFUN xmlAutomataStatePtr XMLCALL + xmlAutomataNewState (xmlAutomataPtr am); +XMLPUBFUN xmlAutomataStatePtr XMLCALL + xmlAutomataNewTransition (xmlAutomataPtr am, + xmlAutomataStatePtr from, + xmlAutomataStatePtr to, + const xmlChar *token, + void *data); +XMLPUBFUN xmlAutomataStatePtr XMLCALL + xmlAutomataNewTransition2 (xmlAutomataPtr am, + xmlAutomataStatePtr from, + xmlAutomataStatePtr to, + const xmlChar *token, + const xmlChar *token2, + void *data); +XMLPUBFUN xmlAutomataStatePtr XMLCALL + xmlAutomataNewNegTrans (xmlAutomataPtr am, + xmlAutomataStatePtr from, + xmlAutomataStatePtr to, + const xmlChar *token, + const xmlChar *token2, + void *data); + +XMLPUBFUN xmlAutomataStatePtr XMLCALL + xmlAutomataNewCountTrans (xmlAutomataPtr am, + xmlAutomataStatePtr from, + xmlAutomataStatePtr to, + const xmlChar *token, + int min, + int max, + void *data); +XMLPUBFUN xmlAutomataStatePtr XMLCALL + xmlAutomataNewCountTrans2 (xmlAutomataPtr am, + xmlAutomataStatePtr from, + xmlAutomataStatePtr to, + const xmlChar *token, + const xmlChar *token2, + int min, + int max, + void *data); +XMLPUBFUN xmlAutomataStatePtr XMLCALL + xmlAutomataNewOnceTrans (xmlAutomataPtr am, + xmlAutomataStatePtr from, + xmlAutomataStatePtr to, + const xmlChar *token, + int min, + int max, + void *data); +XMLPUBFUN xmlAutomataStatePtr XMLCALL + xmlAutomataNewOnceTrans2 (xmlAutomataPtr am, + xmlAutomataStatePtr from, + xmlAutomataStatePtr to, + const xmlChar *token, + const xmlChar *token2, + int min, + int max, + void *data); +XMLPUBFUN xmlAutomataStatePtr XMLCALL + xmlAutomataNewAllTrans (xmlAutomataPtr am, + xmlAutomataStatePtr from, + xmlAutomataStatePtr to, + int lax); +XMLPUBFUN xmlAutomataStatePtr XMLCALL + xmlAutomataNewEpsilon (xmlAutomataPtr am, + xmlAutomataStatePtr from, + xmlAutomataStatePtr to); +XMLPUBFUN xmlAutomataStatePtr XMLCALL + xmlAutomataNewCountedTrans (xmlAutomataPtr am, + xmlAutomataStatePtr from, + xmlAutomataStatePtr to, + int counter); +XMLPUBFUN xmlAutomataStatePtr XMLCALL + xmlAutomataNewCounterTrans (xmlAutomataPtr am, + xmlAutomataStatePtr from, + xmlAutomataStatePtr to, + int counter); +XMLPUBFUN int XMLCALL + xmlAutomataNewCounter (xmlAutomataPtr am, + int min, + int max); + +XMLPUBFUN xmlRegexpPtr XMLCALL + xmlAutomataCompile (xmlAutomataPtr am); +XMLPUBFUN int XMLCALL + xmlAutomataIsDeterminist (xmlAutomataPtr am); + +#ifdef __cplusplus +} +#endif + +#endif /* LIBXML_AUTOMATA_ENABLED */ +#endif /* LIBXML_REGEXP_ENABLED */ + +#endif /* __XML_AUTOMATA_H__ */ diff --git a/gettext-tools/gnulib-lib/libxml/xmlerror.in.h b/gettext-tools/gnulib-lib/libxml/xmlerror.in.h new file mode 100644 index 0000000..c5f2164 --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/xmlerror.in.h @@ -0,0 +1,936 @@ +/* + * Summary: error handling + * Description: the API used to report errors + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + +#include + +#ifndef __XML_ERROR_H__ +#define __XML_ERROR_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * xmlErrorLevel: + * + * Indicates the level of an error + */ +typedef enum { + XML_ERR_NONE = 0, + XML_ERR_WARNING = 1, /* A simple warning */ + XML_ERR_ERROR = 2, /* A recoverable error */ + XML_ERR_FATAL = 3 /* A fatal error */ +} xmlErrorLevel; + +/** + * xmlErrorDomain: + * + * Indicates where an error may have come from + */ +typedef enum { + XML_FROM_NONE = 0, + XML_FROM_PARSER, /* The XML parser */ + XML_FROM_TREE, /* The tree module */ + XML_FROM_NAMESPACE, /* The XML Namespace module */ + XML_FROM_DTD, /* The XML DTD validation with parser context*/ + XML_FROM_HTML, /* The HTML parser */ + XML_FROM_MEMORY, /* The memory allocator */ + XML_FROM_OUTPUT, /* The serialization code */ + XML_FROM_IO, /* The Input/Output stack */ + XML_FROM_FTP, /* The FTP module */ + XML_FROM_HTTP, /* The HTTP module */ + XML_FROM_XINCLUDE, /* The XInclude processing */ + XML_FROM_XPATH, /* The XPath module */ + XML_FROM_XPOINTER, /* The XPointer module */ + XML_FROM_REGEXP, /* The regular expressions module */ + XML_FROM_DATATYPE, /* The W3C XML Schemas Datatype module */ + XML_FROM_SCHEMASP, /* The W3C XML Schemas parser module */ + XML_FROM_SCHEMASV, /* The W3C XML Schemas validation module */ + XML_FROM_RELAXNGP, /* The Relax-NG parser module */ + XML_FROM_RELAXNGV, /* The Relax-NG validator module */ + XML_FROM_CATALOG, /* The Catalog module */ + XML_FROM_C14N, /* The Canonicalization module */ + XML_FROM_XSLT, /* The XSLT engine from libxslt */ + XML_FROM_VALID, /* The XML DTD validation with valid context */ + XML_FROM_CHECK, /* The error checking module */ + XML_FROM_WRITER, /* The xmlwriter module */ + XML_FROM_MODULE, /* The dynamically loaded module module*/ + XML_FROM_I18N /* The module handling character conversion */ +} xmlErrorDomain; + +/** + * xmlError: + * + * An XML Error instance. + */ + +typedef struct _xmlError xmlError; +typedef xmlError *xmlErrorPtr; +struct _xmlError { + int domain; /* What part of the library raised this error */ + int code; /* The error code, e.g. an xmlParserError */ + char *message;/* human-readable informative error message */ + xmlErrorLevel level;/* how consequent is the error */ + char *file; /* the filename */ + int line; /* the line number if available */ + char *str1; /* extra string information */ + char *str2; /* extra string information */ + char *str3; /* extra string information */ + int int1; /* extra number information */ + int int2; /* column number of the error or 0 if N/A (todo: rename this field when we would break ABI) */ + void *ctxt; /* the parser context if available */ + void *node; /* the node in the tree */ +}; + +/** + * xmlParserError: + * + * This is an error that the XML (or HTML) parser can generate + */ +typedef enum { + XML_ERR_OK = 0, + XML_ERR_INTERNAL_ERROR, /* 1 */ + XML_ERR_NO_MEMORY, /* 2 */ + XML_ERR_DOCUMENT_START, /* 3 */ + XML_ERR_DOCUMENT_EMPTY, /* 4 */ + XML_ERR_DOCUMENT_END, /* 5 */ + XML_ERR_INVALID_HEX_CHARREF, /* 6 */ + XML_ERR_INVALID_DEC_CHARREF, /* 7 */ + XML_ERR_INVALID_CHARREF, /* 8 */ + XML_ERR_INVALID_CHAR, /* 9 */ + XML_ERR_CHARREF_AT_EOF, /* 10 */ + XML_ERR_CHARREF_IN_PROLOG, /* 11 */ + XML_ERR_CHARREF_IN_EPILOG, /* 12 */ + XML_ERR_CHARREF_IN_DTD, /* 13 */ + XML_ERR_ENTITYREF_AT_EOF, /* 14 */ + XML_ERR_ENTITYREF_IN_PROLOG, /* 15 */ + XML_ERR_ENTITYREF_IN_EPILOG, /* 16 */ + XML_ERR_ENTITYREF_IN_DTD, /* 17 */ + XML_ERR_PEREF_AT_EOF, /* 18 */ + XML_ERR_PEREF_IN_PROLOG, /* 19 */ + XML_ERR_PEREF_IN_EPILOG, /* 20 */ + XML_ERR_PEREF_IN_INT_SUBSET, /* 21 */ + XML_ERR_ENTITYREF_NO_NAME, /* 22 */ + XML_ERR_ENTITYREF_SEMICOL_MISSING, /* 23 */ + XML_ERR_PEREF_NO_NAME, /* 24 */ + XML_ERR_PEREF_SEMICOL_MISSING, /* 25 */ + XML_ERR_UNDECLARED_ENTITY, /* 26 */ + XML_WAR_UNDECLARED_ENTITY, /* 27 */ + XML_ERR_UNPARSED_ENTITY, /* 28 */ + XML_ERR_ENTITY_IS_EXTERNAL, /* 29 */ + XML_ERR_ENTITY_IS_PARAMETER, /* 30 */ + XML_ERR_UNKNOWN_ENCODING, /* 31 */ + XML_ERR_UNSUPPORTED_ENCODING, /* 32 */ + XML_ERR_STRING_NOT_STARTED, /* 33 */ + XML_ERR_STRING_NOT_CLOSED, /* 34 */ + XML_ERR_NS_DECL_ERROR, /* 35 */ + XML_ERR_ENTITY_NOT_STARTED, /* 36 */ + XML_ERR_ENTITY_NOT_FINISHED, /* 37 */ + XML_ERR_LT_IN_ATTRIBUTE, /* 38 */ + XML_ERR_ATTRIBUTE_NOT_STARTED, /* 39 */ + XML_ERR_ATTRIBUTE_NOT_FINISHED, /* 40 */ + XML_ERR_ATTRIBUTE_WITHOUT_VALUE, /* 41 */ + XML_ERR_ATTRIBUTE_REDEFINED, /* 42 */ + XML_ERR_LITERAL_NOT_STARTED, /* 43 */ + XML_ERR_LITERAL_NOT_FINISHED, /* 44 */ + XML_ERR_COMMENT_NOT_FINISHED, /* 45 */ + XML_ERR_PI_NOT_STARTED, /* 46 */ + XML_ERR_PI_NOT_FINISHED, /* 47 */ + XML_ERR_NOTATION_NOT_STARTED, /* 48 */ + XML_ERR_NOTATION_NOT_FINISHED, /* 49 */ + XML_ERR_ATTLIST_NOT_STARTED, /* 50 */ + XML_ERR_ATTLIST_NOT_FINISHED, /* 51 */ + XML_ERR_MIXED_NOT_STARTED, /* 52 */ + XML_ERR_MIXED_NOT_FINISHED, /* 53 */ + XML_ERR_ELEMCONTENT_NOT_STARTED, /* 54 */ + XML_ERR_ELEMCONTENT_NOT_FINISHED, /* 55 */ + XML_ERR_XMLDECL_NOT_STARTED, /* 56 */ + XML_ERR_XMLDECL_NOT_FINISHED, /* 57 */ + XML_ERR_CONDSEC_NOT_STARTED, /* 58 */ + XML_ERR_CONDSEC_NOT_FINISHED, /* 59 */ + XML_ERR_EXT_SUBSET_NOT_FINISHED, /* 60 */ + XML_ERR_DOCTYPE_NOT_FINISHED, /* 61 */ + XML_ERR_MISPLACED_CDATA_END, /* 62 */ + XML_ERR_CDATA_NOT_FINISHED, /* 63 */ + XML_ERR_RESERVED_XML_NAME, /* 64 */ + XML_ERR_SPACE_REQUIRED, /* 65 */ + XML_ERR_SEPARATOR_REQUIRED, /* 66 */ + XML_ERR_NMTOKEN_REQUIRED, /* 67 */ + XML_ERR_NAME_REQUIRED, /* 68 */ + XML_ERR_PCDATA_REQUIRED, /* 69 */ + XML_ERR_URI_REQUIRED, /* 70 */ + XML_ERR_PUBID_REQUIRED, /* 71 */ + XML_ERR_LT_REQUIRED, /* 72 */ + XML_ERR_GT_REQUIRED, /* 73 */ + XML_ERR_LTSLASH_REQUIRED, /* 74 */ + XML_ERR_EQUAL_REQUIRED, /* 75 */ + XML_ERR_TAG_NAME_MISMATCH, /* 76 */ + XML_ERR_TAG_NOT_FINISHED, /* 77 */ + XML_ERR_STANDALONE_VALUE, /* 78 */ + XML_ERR_ENCODING_NAME, /* 79 */ + XML_ERR_HYPHEN_IN_COMMENT, /* 80 */ + XML_ERR_INVALID_ENCODING, /* 81 */ + XML_ERR_EXT_ENTITY_STANDALONE, /* 82 */ + XML_ERR_CONDSEC_INVALID, /* 83 */ + XML_ERR_VALUE_REQUIRED, /* 84 */ + XML_ERR_NOT_WELL_BALANCED, /* 85 */ + XML_ERR_EXTRA_CONTENT, /* 86 */ + XML_ERR_ENTITY_CHAR_ERROR, /* 87 */ + XML_ERR_ENTITY_PE_INTERNAL, /* 88 */ + XML_ERR_ENTITY_LOOP, /* 89 */ + XML_ERR_ENTITY_BOUNDARY, /* 90 */ + XML_ERR_INVALID_URI, /* 91 */ + XML_ERR_URI_FRAGMENT, /* 92 */ + XML_WAR_CATALOG_PI, /* 93 */ + XML_ERR_NO_DTD, /* 94 */ + XML_ERR_CONDSEC_INVALID_KEYWORD, /* 95 */ + XML_ERR_VERSION_MISSING, /* 96 */ + XML_WAR_UNKNOWN_VERSION, /* 97 */ + XML_WAR_LANG_VALUE, /* 98 */ + XML_WAR_NS_URI, /* 99 */ + XML_WAR_NS_URI_RELATIVE, /* 100 */ + XML_ERR_MISSING_ENCODING, /* 101 */ + XML_WAR_SPACE_VALUE, /* 102 */ + XML_ERR_NOT_STANDALONE, /* 103 */ + XML_ERR_ENTITY_PROCESSING, /* 104 */ + XML_ERR_NOTATION_PROCESSING, /* 105 */ + XML_WAR_NS_COLUMN, /* 106 */ + XML_WAR_ENTITY_REDEFINED, /* 107 */ + XML_NS_ERR_XML_NAMESPACE = 200, + XML_NS_ERR_UNDEFINED_NAMESPACE, /* 201 */ + XML_NS_ERR_QNAME, /* 202 */ + XML_NS_ERR_ATTRIBUTE_REDEFINED, /* 203 */ + XML_NS_ERR_EMPTY, /* 204 */ + XML_DTD_ATTRIBUTE_DEFAULT = 500, + XML_DTD_ATTRIBUTE_REDEFINED, /* 501 */ + XML_DTD_ATTRIBUTE_VALUE, /* 502 */ + XML_DTD_CONTENT_ERROR, /* 503 */ + XML_DTD_CONTENT_MODEL, /* 504 */ + XML_DTD_CONTENT_NOT_DETERMINIST, /* 505 */ + XML_DTD_DIFFERENT_PREFIX, /* 506 */ + XML_DTD_ELEM_DEFAULT_NAMESPACE, /* 507 */ + XML_DTD_ELEM_NAMESPACE, /* 508 */ + XML_DTD_ELEM_REDEFINED, /* 509 */ + XML_DTD_EMPTY_NOTATION, /* 510 */ + XML_DTD_ENTITY_TYPE, /* 511 */ + XML_DTD_ID_FIXED, /* 512 */ + XML_DTD_ID_REDEFINED, /* 513 */ + XML_DTD_ID_SUBSET, /* 514 */ + XML_DTD_INVALID_CHILD, /* 515 */ + XML_DTD_INVALID_DEFAULT, /* 516 */ + XML_DTD_LOAD_ERROR, /* 517 */ + XML_DTD_MISSING_ATTRIBUTE, /* 518 */ + XML_DTD_MIXED_CORRUPT, /* 519 */ + XML_DTD_MULTIPLE_ID, /* 520 */ + XML_DTD_NO_DOC, /* 521 */ + XML_DTD_NO_DTD, /* 522 */ + XML_DTD_NO_ELEM_NAME, /* 523 */ + XML_DTD_NO_PREFIX, /* 524 */ + XML_DTD_NO_ROOT, /* 525 */ + XML_DTD_NOTATION_REDEFINED, /* 526 */ + XML_DTD_NOTATION_VALUE, /* 527 */ + XML_DTD_NOT_EMPTY, /* 528 */ + XML_DTD_NOT_PCDATA, /* 529 */ + XML_DTD_NOT_STANDALONE, /* 530 */ + XML_DTD_ROOT_NAME, /* 531 */ + XML_DTD_STANDALONE_WHITE_SPACE, /* 532 */ + XML_DTD_UNKNOWN_ATTRIBUTE, /* 533 */ + XML_DTD_UNKNOWN_ELEM, /* 534 */ + XML_DTD_UNKNOWN_ENTITY, /* 535 */ + XML_DTD_UNKNOWN_ID, /* 536 */ + XML_DTD_UNKNOWN_NOTATION, /* 537 */ + XML_DTD_STANDALONE_DEFAULTED, /* 538 */ + XML_DTD_XMLID_VALUE, /* 539 */ + XML_DTD_XMLID_TYPE, /* 540 */ + XML_HTML_STRUCURE_ERROR = 800, + XML_HTML_UNKNOWN_TAG, /* 801 */ + XML_RNGP_ANYNAME_ATTR_ANCESTOR = 1000, + XML_RNGP_ATTR_CONFLICT, /* 1001 */ + XML_RNGP_ATTRIBUTE_CHILDREN, /* 1002 */ + XML_RNGP_ATTRIBUTE_CONTENT, /* 1003 */ + XML_RNGP_ATTRIBUTE_EMPTY, /* 1004 */ + XML_RNGP_ATTRIBUTE_NOOP, /* 1005 */ + XML_RNGP_CHOICE_CONTENT, /* 1006 */ + XML_RNGP_CHOICE_EMPTY, /* 1007 */ + XML_RNGP_CREATE_FAILURE, /* 1008 */ + XML_RNGP_DATA_CONTENT, /* 1009 */ + XML_RNGP_DEF_CHOICE_AND_INTERLEAVE, /* 1010 */ + XML_RNGP_DEFINE_CREATE_FAILED, /* 1011 */ + XML_RNGP_DEFINE_EMPTY, /* 1012 */ + XML_RNGP_DEFINE_MISSING, /* 1013 */ + XML_RNGP_DEFINE_NAME_MISSING, /* 1014 */ + XML_RNGP_ELEM_CONTENT_EMPTY, /* 1015 */ + XML_RNGP_ELEM_CONTENT_ERROR, /* 1016 */ + XML_RNGP_ELEMENT_EMPTY, /* 1017 */ + XML_RNGP_ELEMENT_CONTENT, /* 1018 */ + XML_RNGP_ELEMENT_NAME, /* 1019 */ + XML_RNGP_ELEMENT_NO_CONTENT, /* 1020 */ + XML_RNGP_ELEM_TEXT_CONFLICT, /* 1021 */ + XML_RNGP_EMPTY, /* 1022 */ + XML_RNGP_EMPTY_CONSTRUCT, /* 1023 */ + XML_RNGP_EMPTY_CONTENT, /* 1024 */ + XML_RNGP_EMPTY_NOT_EMPTY, /* 1025 */ + XML_RNGP_ERROR_TYPE_LIB, /* 1026 */ + XML_RNGP_EXCEPT_EMPTY, /* 1027 */ + XML_RNGP_EXCEPT_MISSING, /* 1028 */ + XML_RNGP_EXCEPT_MULTIPLE, /* 1029 */ + XML_RNGP_EXCEPT_NO_CONTENT, /* 1030 */ + XML_RNGP_EXTERNALREF_EMTPY, /* 1031 */ + XML_RNGP_EXTERNAL_REF_FAILURE, /* 1032 */ + XML_RNGP_EXTERNALREF_RECURSE, /* 1033 */ + XML_RNGP_FORBIDDEN_ATTRIBUTE, /* 1034 */ + XML_RNGP_FOREIGN_ELEMENT, /* 1035 */ + XML_RNGP_GRAMMAR_CONTENT, /* 1036 */ + XML_RNGP_GRAMMAR_EMPTY, /* 1037 */ + XML_RNGP_GRAMMAR_MISSING, /* 1038 */ + XML_RNGP_GRAMMAR_NO_START, /* 1039 */ + XML_RNGP_GROUP_ATTR_CONFLICT, /* 1040 */ + XML_RNGP_HREF_ERROR, /* 1041 */ + XML_RNGP_INCLUDE_EMPTY, /* 1042 */ + XML_RNGP_INCLUDE_FAILURE, /* 1043 */ + XML_RNGP_INCLUDE_RECURSE, /* 1044 */ + XML_RNGP_INTERLEAVE_ADD, /* 1045 */ + XML_RNGP_INTERLEAVE_CREATE_FAILED, /* 1046 */ + XML_RNGP_INTERLEAVE_EMPTY, /* 1047 */ + XML_RNGP_INTERLEAVE_NO_CONTENT, /* 1048 */ + XML_RNGP_INVALID_DEFINE_NAME, /* 1049 */ + XML_RNGP_INVALID_URI, /* 1050 */ + XML_RNGP_INVALID_VALUE, /* 1051 */ + XML_RNGP_MISSING_HREF, /* 1052 */ + XML_RNGP_NAME_MISSING, /* 1053 */ + XML_RNGP_NEED_COMBINE, /* 1054 */ + XML_RNGP_NOTALLOWED_NOT_EMPTY, /* 1055 */ + XML_RNGP_NSNAME_ATTR_ANCESTOR, /* 1056 */ + XML_RNGP_NSNAME_NO_NS, /* 1057 */ + XML_RNGP_PARAM_FORBIDDEN, /* 1058 */ + XML_RNGP_PARAM_NAME_MISSING, /* 1059 */ + XML_RNGP_PARENTREF_CREATE_FAILED, /* 1060 */ + XML_RNGP_PARENTREF_NAME_INVALID, /* 1061 */ + XML_RNGP_PARENTREF_NO_NAME, /* 1062 */ + XML_RNGP_PARENTREF_NO_PARENT, /* 1063 */ + XML_RNGP_PARENTREF_NOT_EMPTY, /* 1064 */ + XML_RNGP_PARSE_ERROR, /* 1065 */ + XML_RNGP_PAT_ANYNAME_EXCEPT_ANYNAME, /* 1066 */ + XML_RNGP_PAT_ATTR_ATTR, /* 1067 */ + XML_RNGP_PAT_ATTR_ELEM, /* 1068 */ + XML_RNGP_PAT_DATA_EXCEPT_ATTR, /* 1069 */ + XML_RNGP_PAT_DATA_EXCEPT_ELEM, /* 1070 */ + XML_RNGP_PAT_DATA_EXCEPT_EMPTY, /* 1071 */ + XML_RNGP_PAT_DATA_EXCEPT_GROUP, /* 1072 */ + XML_RNGP_PAT_DATA_EXCEPT_INTERLEAVE, /* 1073 */ + XML_RNGP_PAT_DATA_EXCEPT_LIST, /* 1074 */ + XML_RNGP_PAT_DATA_EXCEPT_ONEMORE, /* 1075 */ + XML_RNGP_PAT_DATA_EXCEPT_REF, /* 1076 */ + XML_RNGP_PAT_DATA_EXCEPT_TEXT, /* 1077 */ + XML_RNGP_PAT_LIST_ATTR, /* 1078 */ + XML_RNGP_PAT_LIST_ELEM, /* 1079 */ + XML_RNGP_PAT_LIST_INTERLEAVE, /* 1080 */ + XML_RNGP_PAT_LIST_LIST, /* 1081 */ + XML_RNGP_PAT_LIST_REF, /* 1082 */ + XML_RNGP_PAT_LIST_TEXT, /* 1083 */ + XML_RNGP_PAT_NSNAME_EXCEPT_ANYNAME, /* 1084 */ + XML_RNGP_PAT_NSNAME_EXCEPT_NSNAME, /* 1085 */ + XML_RNGP_PAT_ONEMORE_GROUP_ATTR, /* 1086 */ + XML_RNGP_PAT_ONEMORE_INTERLEAVE_ATTR, /* 1087 */ + XML_RNGP_PAT_START_ATTR, /* 1088 */ + XML_RNGP_PAT_START_DATA, /* 1089 */ + XML_RNGP_PAT_START_EMPTY, /* 1090 */ + XML_RNGP_PAT_START_GROUP, /* 1091 */ + XML_RNGP_PAT_START_INTERLEAVE, /* 1092 */ + XML_RNGP_PAT_START_LIST, /* 1093 */ + XML_RNGP_PAT_START_ONEMORE, /* 1094 */ + XML_RNGP_PAT_START_TEXT, /* 1095 */ + XML_RNGP_PAT_START_VALUE, /* 1096 */ + XML_RNGP_PREFIX_UNDEFINED, /* 1097 */ + XML_RNGP_REF_CREATE_FAILED, /* 1098 */ + XML_RNGP_REF_CYCLE, /* 1099 */ + XML_RNGP_REF_NAME_INVALID, /* 1100 */ + XML_RNGP_REF_NO_DEF, /* 1101 */ + XML_RNGP_REF_NO_NAME, /* 1102 */ + XML_RNGP_REF_NOT_EMPTY, /* 1103 */ + XML_RNGP_START_CHOICE_AND_INTERLEAVE, /* 1104 */ + XML_RNGP_START_CONTENT, /* 1105 */ + XML_RNGP_START_EMPTY, /* 1106 */ + XML_RNGP_START_MISSING, /* 1107 */ + XML_RNGP_TEXT_EXPECTED, /* 1108 */ + XML_RNGP_TEXT_HAS_CHILD, /* 1109 */ + XML_RNGP_TYPE_MISSING, /* 1110 */ + XML_RNGP_TYPE_NOT_FOUND, /* 1111 */ + XML_RNGP_TYPE_VALUE, /* 1112 */ + XML_RNGP_UNKNOWN_ATTRIBUTE, /* 1113 */ + XML_RNGP_UNKNOWN_COMBINE, /* 1114 */ + XML_RNGP_UNKNOWN_CONSTRUCT, /* 1115 */ + XML_RNGP_UNKNOWN_TYPE_LIB, /* 1116 */ + XML_RNGP_URI_FRAGMENT, /* 1117 */ + XML_RNGP_URI_NOT_ABSOLUTE, /* 1118 */ + XML_RNGP_VALUE_EMPTY, /* 1119 */ + XML_RNGP_VALUE_NO_CONTENT, /* 1120 */ + XML_RNGP_XMLNS_NAME, /* 1121 */ + XML_RNGP_XML_NS, /* 1122 */ + XML_XPATH_EXPRESSION_OK = 1200, + XML_XPATH_NUMBER_ERROR, /* 1201 */ + XML_XPATH_UNFINISHED_LITERAL_ERROR, /* 1202 */ + XML_XPATH_START_LITERAL_ERROR, /* 1203 */ + XML_XPATH_VARIABLE_REF_ERROR, /* 1204 */ + XML_XPATH_UNDEF_VARIABLE_ERROR, /* 1205 */ + XML_XPATH_INVALID_PREDICATE_ERROR, /* 1206 */ + XML_XPATH_EXPR_ERROR, /* 1207 */ + XML_XPATH_UNCLOSED_ERROR, /* 1208 */ + XML_XPATH_UNKNOWN_FUNC_ERROR, /* 1209 */ + XML_XPATH_INVALID_OPERAND, /* 1210 */ + XML_XPATH_INVALID_TYPE, /* 1211 */ + XML_XPATH_INVALID_ARITY, /* 1212 */ + XML_XPATH_INVALID_CTXT_SIZE, /* 1213 */ + XML_XPATH_INVALID_CTXT_POSITION, /* 1214 */ + XML_XPATH_MEMORY_ERROR, /* 1215 */ + XML_XPTR_SYNTAX_ERROR, /* 1216 */ + XML_XPTR_RESOURCE_ERROR, /* 1217 */ + XML_XPTR_SUB_RESOURCE_ERROR, /* 1218 */ + XML_XPATH_UNDEF_PREFIX_ERROR, /* 1219 */ + XML_XPATH_ENCODING_ERROR, /* 1220 */ + XML_XPATH_INVALID_CHAR_ERROR, /* 1221 */ + XML_TREE_INVALID_HEX = 1300, + XML_TREE_INVALID_DEC, /* 1301 */ + XML_TREE_UNTERMINATED_ENTITY, /* 1302 */ + XML_SAVE_NOT_UTF8 = 1400, + XML_SAVE_CHAR_INVALID, /* 1401 */ + XML_SAVE_NO_DOCTYPE, /* 1402 */ + XML_SAVE_UNKNOWN_ENCODING, /* 1403 */ + XML_REGEXP_COMPILE_ERROR = 1450, + XML_IO_UNKNOWN = 1500, + XML_IO_EACCES, /* 1501 */ + XML_IO_EAGAIN, /* 1502 */ + XML_IO_EBADF, /* 1503 */ + XML_IO_EBADMSG, /* 1504 */ + XML_IO_EBUSY, /* 1505 */ + XML_IO_ECANCELED, /* 1506 */ + XML_IO_ECHILD, /* 1507 */ + XML_IO_EDEADLK, /* 1508 */ + XML_IO_EDOM, /* 1509 */ + XML_IO_EEXIST, /* 1510 */ + XML_IO_EFAULT, /* 1511 */ + XML_IO_EFBIG, /* 1512 */ + XML_IO_EINPROGRESS, /* 1513 */ + XML_IO_EINTR, /* 1514 */ + XML_IO_EINVAL, /* 1515 */ + XML_IO_EIO, /* 1516 */ + XML_IO_EISDIR, /* 1517 */ + XML_IO_EMFILE, /* 1518 */ + XML_IO_EMLINK, /* 1519 */ + XML_IO_EMSGSIZE, /* 1520 */ + XML_IO_ENAMETOOLONG, /* 1521 */ + XML_IO_ENFILE, /* 1522 */ + XML_IO_ENODEV, /* 1523 */ + XML_IO_ENOENT, /* 1524 */ + XML_IO_ENOEXEC, /* 1525 */ + XML_IO_ENOLCK, /* 1526 */ + XML_IO_ENOMEM, /* 1527 */ + XML_IO_ENOSPC, /* 1528 */ + XML_IO_ENOSYS, /* 1529 */ + XML_IO_ENOTDIR, /* 1530 */ + XML_IO_ENOTEMPTY, /* 1531 */ + XML_IO_ENOTSUP, /* 1532 */ + XML_IO_ENOTTY, /* 1533 */ + XML_IO_ENXIO, /* 1534 */ + XML_IO_EPERM, /* 1535 */ + XML_IO_EPIPE, /* 1536 */ + XML_IO_ERANGE, /* 1537 */ + XML_IO_EROFS, /* 1538 */ + XML_IO_ESPIPE, /* 1539 */ + XML_IO_ESRCH, /* 1540 */ + XML_IO_ETIMEDOUT, /* 1541 */ + XML_IO_EXDEV, /* 1542 */ + XML_IO_NETWORK_ATTEMPT, /* 1543 */ + XML_IO_ENCODER, /* 1544 */ + XML_IO_FLUSH, /* 1545 */ + XML_IO_WRITE, /* 1546 */ + XML_IO_NO_INPUT, /* 1547 */ + XML_IO_BUFFER_FULL, /* 1548 */ + XML_IO_LOAD_ERROR, /* 1549 */ + XML_IO_ENOTSOCK, /* 1550 */ + XML_IO_EISCONN, /* 1551 */ + XML_IO_ECONNREFUSED, /* 1552 */ + XML_IO_ENETUNREACH, /* 1553 */ + XML_IO_EADDRINUSE, /* 1554 */ + XML_IO_EALREADY, /* 1555 */ + XML_IO_EAFNOSUPPORT, /* 1556 */ + XML_XINCLUDE_RECURSION=1600, + XML_XINCLUDE_PARSE_VALUE, /* 1601 */ + XML_XINCLUDE_ENTITY_DEF_MISMATCH, /* 1602 */ + XML_XINCLUDE_NO_HREF, /* 1603 */ + XML_XINCLUDE_NO_FALLBACK, /* 1604 */ + XML_XINCLUDE_HREF_URI, /* 1605 */ + XML_XINCLUDE_TEXT_FRAGMENT, /* 1606 */ + XML_XINCLUDE_TEXT_DOCUMENT, /* 1607 */ + XML_XINCLUDE_INVALID_CHAR, /* 1608 */ + XML_XINCLUDE_BUILD_FAILED, /* 1609 */ + XML_XINCLUDE_UNKNOWN_ENCODING, /* 1610 */ + XML_XINCLUDE_MULTIPLE_ROOT, /* 1611 */ + XML_XINCLUDE_XPTR_FAILED, /* 1612 */ + XML_XINCLUDE_XPTR_RESULT, /* 1613 */ + XML_XINCLUDE_INCLUDE_IN_INCLUDE, /* 1614 */ + XML_XINCLUDE_FALLBACKS_IN_INCLUDE, /* 1615 */ + XML_XINCLUDE_FALLBACK_NOT_IN_INCLUDE, /* 1616 */ + XML_XINCLUDE_DEPRECATED_NS, /* 1617 */ + XML_XINCLUDE_FRAGMENT_ID, /* 1618 */ + XML_CATALOG_MISSING_ATTR = 1650, + XML_CATALOG_ENTRY_BROKEN, /* 1651 */ + XML_CATALOG_PREFER_VALUE, /* 1652 */ + XML_CATALOG_NOT_CATALOG, /* 1653 */ + XML_CATALOG_RECURSION, /* 1654 */ + XML_SCHEMAP_PREFIX_UNDEFINED = 1700, + XML_SCHEMAP_ATTRFORMDEFAULT_VALUE, /* 1701 */ + XML_SCHEMAP_ATTRGRP_NONAME_NOREF, /* 1702 */ + XML_SCHEMAP_ATTR_NONAME_NOREF, /* 1703 */ + XML_SCHEMAP_COMPLEXTYPE_NONAME_NOREF, /* 1704 */ + XML_SCHEMAP_ELEMFORMDEFAULT_VALUE, /* 1705 */ + XML_SCHEMAP_ELEM_NONAME_NOREF, /* 1706 */ + XML_SCHEMAP_EXTENSION_NO_BASE, /* 1707 */ + XML_SCHEMAP_FACET_NO_VALUE, /* 1708 */ + XML_SCHEMAP_FAILED_BUILD_IMPORT, /* 1709 */ + XML_SCHEMAP_GROUP_NONAME_NOREF, /* 1710 */ + XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI, /* 1711 */ + XML_SCHEMAP_IMPORT_REDEFINE_NSNAME, /* 1712 */ + XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI, /* 1713 */ + XML_SCHEMAP_INVALID_BOOLEAN, /* 1714 */ + XML_SCHEMAP_INVALID_ENUM, /* 1715 */ + XML_SCHEMAP_INVALID_FACET, /* 1716 */ + XML_SCHEMAP_INVALID_FACET_VALUE, /* 1717 */ + XML_SCHEMAP_INVALID_MAXOCCURS, /* 1718 */ + XML_SCHEMAP_INVALID_MINOCCURS, /* 1719 */ + XML_SCHEMAP_INVALID_REF_AND_SUBTYPE, /* 1720 */ + XML_SCHEMAP_INVALID_WHITE_SPACE, /* 1721 */ + XML_SCHEMAP_NOATTR_NOREF, /* 1722 */ + XML_SCHEMAP_NOTATION_NO_NAME, /* 1723 */ + XML_SCHEMAP_NOTYPE_NOREF, /* 1724 */ + XML_SCHEMAP_REF_AND_SUBTYPE, /* 1725 */ + XML_SCHEMAP_RESTRICTION_NONAME_NOREF, /* 1726 */ + XML_SCHEMAP_SIMPLETYPE_NONAME, /* 1727 */ + XML_SCHEMAP_TYPE_AND_SUBTYPE, /* 1728 */ + XML_SCHEMAP_UNKNOWN_ALL_CHILD, /* 1729 */ + XML_SCHEMAP_UNKNOWN_ANYATTRIBUTE_CHILD, /* 1730 */ + XML_SCHEMAP_UNKNOWN_ATTR_CHILD, /* 1731 */ + XML_SCHEMAP_UNKNOWN_ATTRGRP_CHILD, /* 1732 */ + XML_SCHEMAP_UNKNOWN_ATTRIBUTE_GROUP, /* 1733 */ + XML_SCHEMAP_UNKNOWN_BASE_TYPE, /* 1734 */ + XML_SCHEMAP_UNKNOWN_CHOICE_CHILD, /* 1735 */ + XML_SCHEMAP_UNKNOWN_COMPLEXCONTENT_CHILD, /* 1736 */ + XML_SCHEMAP_UNKNOWN_COMPLEXTYPE_CHILD, /* 1737 */ + XML_SCHEMAP_UNKNOWN_ELEM_CHILD, /* 1738 */ + XML_SCHEMAP_UNKNOWN_EXTENSION_CHILD, /* 1739 */ + XML_SCHEMAP_UNKNOWN_FACET_CHILD, /* 1740 */ + XML_SCHEMAP_UNKNOWN_FACET_TYPE, /* 1741 */ + XML_SCHEMAP_UNKNOWN_GROUP_CHILD, /* 1742 */ + XML_SCHEMAP_UNKNOWN_IMPORT_CHILD, /* 1743 */ + XML_SCHEMAP_UNKNOWN_LIST_CHILD, /* 1744 */ + XML_SCHEMAP_UNKNOWN_NOTATION_CHILD, /* 1745 */ + XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD, /* 1746 */ + XML_SCHEMAP_UNKNOWN_REF, /* 1747 */ + XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD, /* 1748 */ + XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD, /* 1749 */ + XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD, /* 1750 */ + XML_SCHEMAP_UNKNOWN_SIMPLECONTENT_CHILD, /* 1751 */ + XML_SCHEMAP_UNKNOWN_SIMPLETYPE_CHILD, /* 1752 */ + XML_SCHEMAP_UNKNOWN_TYPE, /* 1753 */ + XML_SCHEMAP_UNKNOWN_UNION_CHILD, /* 1754 */ + XML_SCHEMAP_ELEM_DEFAULT_FIXED, /* 1755 */ + XML_SCHEMAP_REGEXP_INVALID, /* 1756 */ + XML_SCHEMAP_FAILED_LOAD, /* 1757 */ + XML_SCHEMAP_NOTHING_TO_PARSE, /* 1758 */ + XML_SCHEMAP_NOROOT, /* 1759 */ + XML_SCHEMAP_REDEFINED_GROUP, /* 1760 */ + XML_SCHEMAP_REDEFINED_TYPE, /* 1761 */ + XML_SCHEMAP_REDEFINED_ELEMENT, /* 1762 */ + XML_SCHEMAP_REDEFINED_ATTRGROUP, /* 1763 */ + XML_SCHEMAP_REDEFINED_ATTR, /* 1764 */ + XML_SCHEMAP_REDEFINED_NOTATION, /* 1765 */ + XML_SCHEMAP_FAILED_PARSE, /* 1766 */ + XML_SCHEMAP_UNKNOWN_PREFIX, /* 1767 */ + XML_SCHEMAP_DEF_AND_PREFIX, /* 1768 */ + XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD, /* 1769 */ + XML_SCHEMAP_INCLUDE_SCHEMA_NOT_URI, /* 1770 */ + XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI, /* 1771 */ + XML_SCHEMAP_NOT_SCHEMA, /* 1772 */ + XML_SCHEMAP_UNKNOWN_MEMBER_TYPE, /* 1773 */ + XML_SCHEMAP_INVALID_ATTR_USE, /* 1774 */ + XML_SCHEMAP_RECURSIVE, /* 1775 */ + XML_SCHEMAP_SUPERNUMEROUS_LIST_ITEM_TYPE, /* 1776 */ + XML_SCHEMAP_INVALID_ATTR_COMBINATION, /* 1777 */ + XML_SCHEMAP_INVALID_ATTR_INLINE_COMBINATION, /* 1778 */ + XML_SCHEMAP_MISSING_SIMPLETYPE_CHILD, /* 1779 */ + XML_SCHEMAP_INVALID_ATTR_NAME, /* 1780 */ + XML_SCHEMAP_REF_AND_CONTENT, /* 1781 */ + XML_SCHEMAP_CT_PROPS_CORRECT_1, /* 1782 */ + XML_SCHEMAP_CT_PROPS_CORRECT_2, /* 1783 */ + XML_SCHEMAP_CT_PROPS_CORRECT_3, /* 1784 */ + XML_SCHEMAP_CT_PROPS_CORRECT_4, /* 1785 */ + XML_SCHEMAP_CT_PROPS_CORRECT_5, /* 1786 */ + XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1, /* 1787 */ + XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1, /* 1788 */ + XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2, /* 1789 */ + XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2, /* 1790 */ + XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3, /* 1791 */ + XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER, /* 1792 */ + XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE, /* 1793 */ + XML_SCHEMAP_UNION_NOT_EXPRESSIBLE, /* 1794 */ + XML_SCHEMAP_SRC_IMPORT_3_1, /* 1795 */ + XML_SCHEMAP_SRC_IMPORT_3_2, /* 1796 */ + XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1, /* 1797 */ + XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2, /* 1798 */ + XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3, /* 1799 */ + XML_SCHEMAP_COS_CT_EXTENDS_1_3, /* 1800 */ + XML_SCHEMAV_NOROOT = 1801, + XML_SCHEMAV_UNDECLAREDELEM, /* 1802 */ + XML_SCHEMAV_NOTTOPLEVEL, /* 1803 */ + XML_SCHEMAV_MISSING, /* 1804 */ + XML_SCHEMAV_WRONGELEM, /* 1805 */ + XML_SCHEMAV_NOTYPE, /* 1806 */ + XML_SCHEMAV_NOROLLBACK, /* 1807 */ + XML_SCHEMAV_ISABSTRACT, /* 1808 */ + XML_SCHEMAV_NOTEMPTY, /* 1809 */ + XML_SCHEMAV_ELEMCONT, /* 1810 */ + XML_SCHEMAV_HAVEDEFAULT, /* 1811 */ + XML_SCHEMAV_NOTNILLABLE, /* 1812 */ + XML_SCHEMAV_EXTRACONTENT, /* 1813 */ + XML_SCHEMAV_INVALIDATTR, /* 1814 */ + XML_SCHEMAV_INVALIDELEM, /* 1815 */ + XML_SCHEMAV_NOTDETERMINIST, /* 1816 */ + XML_SCHEMAV_CONSTRUCT, /* 1817 */ + XML_SCHEMAV_INTERNAL, /* 1818 */ + XML_SCHEMAV_NOTSIMPLE, /* 1819 */ + XML_SCHEMAV_ATTRUNKNOWN, /* 1820 */ + XML_SCHEMAV_ATTRINVALID, /* 1821 */ + XML_SCHEMAV_VALUE, /* 1822 */ + XML_SCHEMAV_FACET, /* 1823 */ + XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, /* 1824 */ + XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2, /* 1825 */ + XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3, /* 1826 */ + XML_SCHEMAV_CVC_TYPE_3_1_1, /* 1827 */ + XML_SCHEMAV_CVC_TYPE_3_1_2, /* 1828 */ + XML_SCHEMAV_CVC_FACET_VALID, /* 1829 */ + XML_SCHEMAV_CVC_LENGTH_VALID, /* 1830 */ + XML_SCHEMAV_CVC_MINLENGTH_VALID, /* 1831 */ + XML_SCHEMAV_CVC_MAXLENGTH_VALID, /* 1832 */ + XML_SCHEMAV_CVC_MININCLUSIVE_VALID, /* 1833 */ + XML_SCHEMAV_CVC_MAXINCLUSIVE_VALID, /* 1834 */ + XML_SCHEMAV_CVC_MINEXCLUSIVE_VALID, /* 1835 */ + XML_SCHEMAV_CVC_MAXEXCLUSIVE_VALID, /* 1836 */ + XML_SCHEMAV_CVC_TOTALDIGITS_VALID, /* 1837 */ + XML_SCHEMAV_CVC_FRACTIONDIGITS_VALID, /* 1838 */ + XML_SCHEMAV_CVC_PATTERN_VALID, /* 1839 */ + XML_SCHEMAV_CVC_ENUMERATION_VALID, /* 1840 */ + XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, /* 1841 */ + XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2, /* 1842 */ + XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, /* 1843 */ + XML_SCHEMAV_CVC_COMPLEX_TYPE_2_4, /* 1844 */ + XML_SCHEMAV_CVC_ELT_1, /* 1845 */ + XML_SCHEMAV_CVC_ELT_2, /* 1846 */ + XML_SCHEMAV_CVC_ELT_3_1, /* 1847 */ + XML_SCHEMAV_CVC_ELT_3_2_1, /* 1848 */ + XML_SCHEMAV_CVC_ELT_3_2_2, /* 1849 */ + XML_SCHEMAV_CVC_ELT_4_1, /* 1850 */ + XML_SCHEMAV_CVC_ELT_4_2, /* 1851 */ + XML_SCHEMAV_CVC_ELT_4_3, /* 1852 */ + XML_SCHEMAV_CVC_ELT_5_1_1, /* 1853 */ + XML_SCHEMAV_CVC_ELT_5_1_2, /* 1854 */ + XML_SCHEMAV_CVC_ELT_5_2_1, /* 1855 */ + XML_SCHEMAV_CVC_ELT_5_2_2_1, /* 1856 */ + XML_SCHEMAV_CVC_ELT_5_2_2_2_1, /* 1857 */ + XML_SCHEMAV_CVC_ELT_5_2_2_2_2, /* 1858 */ + XML_SCHEMAV_CVC_ELT_6, /* 1859 */ + XML_SCHEMAV_CVC_ELT_7, /* 1860 */ + XML_SCHEMAV_CVC_ATTRIBUTE_1, /* 1861 */ + XML_SCHEMAV_CVC_ATTRIBUTE_2, /* 1862 */ + XML_SCHEMAV_CVC_ATTRIBUTE_3, /* 1863 */ + XML_SCHEMAV_CVC_ATTRIBUTE_4, /* 1864 */ + XML_SCHEMAV_CVC_COMPLEX_TYPE_3_1, /* 1865 */ + XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, /* 1866 */ + XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, /* 1867 */ + XML_SCHEMAV_CVC_COMPLEX_TYPE_4, /* 1868 */ + XML_SCHEMAV_CVC_COMPLEX_TYPE_5_1, /* 1869 */ + XML_SCHEMAV_CVC_COMPLEX_TYPE_5_2, /* 1870 */ + XML_SCHEMAV_ELEMENT_CONTENT, /* 1871 */ + XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING, /* 1872 */ + XML_SCHEMAV_CVC_COMPLEX_TYPE_1, /* 1873 */ + XML_SCHEMAV_CVC_AU, /* 1874 */ + XML_SCHEMAV_CVC_TYPE_1, /* 1875 */ + XML_SCHEMAV_CVC_TYPE_2, /* 1876 */ + XML_SCHEMAV_CVC_IDC, /* 1877 */ + XML_SCHEMAV_CVC_WILDCARD, /* 1878 */ + XML_SCHEMAV_MISC, /* 1879 */ + XML_XPTR_UNKNOWN_SCHEME = 1900, + XML_XPTR_CHILDSEQ_START, /* 1901 */ + XML_XPTR_EVAL_FAILED, /* 1902 */ + XML_XPTR_EXTRA_OBJECTS, /* 1903 */ + XML_C14N_CREATE_CTXT = 1950, + XML_C14N_REQUIRES_UTF8, /* 1951 */ + XML_C14N_CREATE_STACK, /* 1952 */ + XML_C14N_INVALID_NODE, /* 1953 */ + XML_C14N_UNKNOW_NODE, /* 1954 */ + XML_C14N_RELATIVE_NAMESPACE, /* 1955 */ + XML_FTP_PASV_ANSWER = 2000, + XML_FTP_EPSV_ANSWER, /* 2001 */ + XML_FTP_ACCNT, /* 2002 */ + XML_FTP_URL_SYNTAX, /* 2003 */ + XML_HTTP_URL_SYNTAX = 2020, + XML_HTTP_USE_IP, /* 2021 */ + XML_HTTP_UNKNOWN_HOST, /* 2022 */ + XML_SCHEMAP_SRC_SIMPLE_TYPE_1 = 3000, + XML_SCHEMAP_SRC_SIMPLE_TYPE_2, /* 3001 */ + XML_SCHEMAP_SRC_SIMPLE_TYPE_3, /* 3002 */ + XML_SCHEMAP_SRC_SIMPLE_TYPE_4, /* 3003 */ + XML_SCHEMAP_SRC_RESOLVE, /* 3004 */ + XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE, /* 3005 */ + XML_SCHEMAP_SRC_LIST_ITEMTYPE_OR_SIMPLETYPE, /* 3006 */ + XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES, /* 3007 */ + XML_SCHEMAP_ST_PROPS_CORRECT_1, /* 3008 */ + XML_SCHEMAP_ST_PROPS_CORRECT_2, /* 3009 */ + XML_SCHEMAP_ST_PROPS_CORRECT_3, /* 3010 */ + XML_SCHEMAP_COS_ST_RESTRICTS_1_1, /* 3011 */ + XML_SCHEMAP_COS_ST_RESTRICTS_1_2, /* 3012 */ + XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1, /* 3013 */ + XML_SCHEMAP_COS_ST_RESTRICTS_1_3_2, /* 3014 */ + XML_SCHEMAP_COS_ST_RESTRICTS_2_1, /* 3015 */ + XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1, /* 3016 */ + XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2, /* 3017 */ + XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1, /* 3018 */ + XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2, /* 3019 */ + XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3, /* 3020 */ + XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4, /* 3021 */ + XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_5, /* 3022 */ + XML_SCHEMAP_COS_ST_RESTRICTS_3_1, /* 3023 */ + XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1, /* 3024 */ + XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2, /* 3025 */ + XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2, /* 3026 */ + XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1, /* 3027 */ + XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3, /* 3028 */ + XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4, /* 3029 */ + XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_5, /* 3030 */ + XML_SCHEMAP_COS_ST_DERIVED_OK_2_1, /* 3031 */ + XML_SCHEMAP_COS_ST_DERIVED_OK_2_2, /* 3032 */ + XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, /* 3033 */ + XML_SCHEMAP_S4S_ELEM_MISSING, /* 3034 */ + XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, /* 3035 */ + XML_SCHEMAP_S4S_ATTR_MISSING, /* 3036 */ + XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, /* 3037 */ + XML_SCHEMAP_SRC_ELEMENT_1, /* 3038 */ + XML_SCHEMAP_SRC_ELEMENT_2_1, /* 3039 */ + XML_SCHEMAP_SRC_ELEMENT_2_2, /* 3040 */ + XML_SCHEMAP_SRC_ELEMENT_3, /* 3041 */ + XML_SCHEMAP_P_PROPS_CORRECT_1, /* 3042 */ + XML_SCHEMAP_P_PROPS_CORRECT_2_1, /* 3043 */ + XML_SCHEMAP_P_PROPS_CORRECT_2_2, /* 3044 */ + XML_SCHEMAP_E_PROPS_CORRECT_2, /* 3045 */ + XML_SCHEMAP_E_PROPS_CORRECT_3, /* 3046 */ + XML_SCHEMAP_E_PROPS_CORRECT_4, /* 3047 */ + XML_SCHEMAP_E_PROPS_CORRECT_5, /* 3048 */ + XML_SCHEMAP_E_PROPS_CORRECT_6, /* 3049 */ + XML_SCHEMAP_SRC_INCLUDE, /* 3050 */ + XML_SCHEMAP_SRC_ATTRIBUTE_1, /* 3051 */ + XML_SCHEMAP_SRC_ATTRIBUTE_2, /* 3052 */ + XML_SCHEMAP_SRC_ATTRIBUTE_3_1, /* 3053 */ + XML_SCHEMAP_SRC_ATTRIBUTE_3_2, /* 3054 */ + XML_SCHEMAP_SRC_ATTRIBUTE_4, /* 3055 */ + XML_SCHEMAP_NO_XMLNS, /* 3056 */ + XML_SCHEMAP_NO_XSI, /* 3057 */ + XML_SCHEMAP_COS_VALID_DEFAULT_1, /* 3058 */ + XML_SCHEMAP_COS_VALID_DEFAULT_2_1, /* 3059 */ + XML_SCHEMAP_COS_VALID_DEFAULT_2_2_1, /* 3060 */ + XML_SCHEMAP_COS_VALID_DEFAULT_2_2_2, /* 3061 */ + XML_SCHEMAP_CVC_SIMPLE_TYPE, /* 3062 */ + XML_SCHEMAP_COS_CT_EXTENDS_1_1, /* 3063 */ + XML_SCHEMAP_SRC_IMPORT_1_1, /* 3064 */ + XML_SCHEMAP_SRC_IMPORT_1_2, /* 3065 */ + XML_SCHEMAP_SRC_IMPORT_2, /* 3066 */ + XML_SCHEMAP_SRC_IMPORT_2_1, /* 3067 */ + XML_SCHEMAP_SRC_IMPORT_2_2, /* 3068 */ + XML_SCHEMAP_INTERNAL, /* 3069 non-W3C */ + XML_SCHEMAP_NOT_DETERMINISTIC, /* 3070 non-W3C */ + XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_1, /* 3071 */ + XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_2, /* 3072 */ + XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3, /* 3073 */ + XML_SCHEMAP_MG_PROPS_CORRECT_1, /* 3074 */ + XML_SCHEMAP_MG_PROPS_CORRECT_2, /* 3075 */ + XML_SCHEMAP_SRC_CT_1, /* 3076 */ + XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3, /* 3077 */ + XML_SCHEMAP_AU_PROPS_CORRECT_2, /* 3078 */ + XML_SCHEMAP_A_PROPS_CORRECT_2, /* 3079 */ + XML_SCHEMAP_C_PROPS_CORRECT, /* 3080 */ + XML_SCHEMAP_SRC_REDEFINE, /* 3081 */ + XML_SCHEMAP_SRC_IMPORT, /* 3082 */ + XML_SCHEMAP_WARN_SKIP_SCHEMA, /* 3083 */ + XML_SCHEMAP_WARN_UNLOCATED_SCHEMA, /* 3084 */ + XML_SCHEMAP_WARN_ATTR_REDECL_PROH, /* 3085 */ + XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH, /* 3085 */ + XML_SCHEMAP_AG_PROPS_CORRECT, /* 3086 */ + XML_SCHEMAP_COS_CT_EXTENDS_1_2, /* 3087 */ + XML_SCHEMAP_AU_PROPS_CORRECT, /* 3088 */ + XML_SCHEMAP_A_PROPS_CORRECT_3, /* 3089 */ + XML_SCHEMAP_COS_ALL_LIMITED, /* 3090 */ + XML_MODULE_OPEN = 4900, /* 4900 */ + XML_MODULE_CLOSE, /* 4901 */ + XML_CHECK_FOUND_ELEMENT = 5000, + XML_CHECK_FOUND_ATTRIBUTE, /* 5001 */ + XML_CHECK_FOUND_TEXT, /* 5002 */ + XML_CHECK_FOUND_CDATA, /* 5003 */ + XML_CHECK_FOUND_ENTITYREF, /* 5004 */ + XML_CHECK_FOUND_ENTITY, /* 5005 */ + XML_CHECK_FOUND_PI, /* 5006 */ + XML_CHECK_FOUND_COMMENT, /* 5007 */ + XML_CHECK_FOUND_DOCTYPE, /* 5008 */ + XML_CHECK_FOUND_FRAGMENT, /* 5009 */ + XML_CHECK_FOUND_NOTATION, /* 5010 */ + XML_CHECK_UNKNOWN_NODE, /* 5011 */ + XML_CHECK_ENTITY_TYPE, /* 5012 */ + XML_CHECK_NO_PARENT, /* 5013 */ + XML_CHECK_NO_DOC, /* 5014 */ + XML_CHECK_NO_NAME, /* 5015 */ + XML_CHECK_NO_ELEM, /* 5016 */ + XML_CHECK_WRONG_DOC, /* 5017 */ + XML_CHECK_NO_PREV, /* 5018 */ + XML_CHECK_WRONG_PREV, /* 5019 */ + XML_CHECK_NO_NEXT, /* 5020 */ + XML_CHECK_WRONG_NEXT, /* 5021 */ + XML_CHECK_NOT_DTD, /* 5022 */ + XML_CHECK_NOT_ATTR, /* 5023 */ + XML_CHECK_NOT_ATTR_DECL, /* 5024 */ + XML_CHECK_NOT_ELEM_DECL, /* 5025 */ + XML_CHECK_NOT_ENTITY_DECL, /* 5026 */ + XML_CHECK_NOT_NS_DECL, /* 5027 */ + XML_CHECK_NO_HREF, /* 5028 */ + XML_CHECK_WRONG_PARENT,/* 5029 */ + XML_CHECK_NS_SCOPE, /* 5030 */ + XML_CHECK_NS_ANCESTOR, /* 5031 */ + XML_CHECK_NOT_UTF8, /* 5032 */ + XML_CHECK_NO_DICT, /* 5033 */ + XML_CHECK_NOT_NCNAME, /* 5034 */ + XML_CHECK_OUTSIDE_DICT, /* 5035 */ + XML_CHECK_WRONG_NAME, /* 5036 */ + XML_CHECK_NAME_NOT_NULL, /* 5037 */ + XML_I18N_NO_NAME = 6000, + XML_I18N_NO_HANDLER, /* 6001 */ + XML_I18N_EXCESS_HANDLER, /* 6002 */ + XML_I18N_CONV_FAILED, /* 6003 */ + XML_I18N_NO_OUTPUT /* 6004 */ +#if 0 + XML_CHECK_, /* 5033 */ + XML_CHECK_X /* 503 */ +#endif +} xmlParserErrors; + +/** + * xmlGenericErrorFunc: + * @ctx: a parsing context + * @msg: the message + * @...: the extra arguments of the varags to format the message + * + * Signature of the function to use when there is an error and + * no parsing or validity context available . + */ +typedef void (XMLCDECL *xmlGenericErrorFunc) (void *ctx, + const char *msg, + ...); +/** + * xmlStructuredErrorFunc: + * @userData: user provided data for the error callback + * @error: the error being raised. + * + * Signature of the function to use when there is an error and + * the module handles the new error reporting mechanism. + */ +typedef void (XMLCALL *xmlStructuredErrorFunc) (void *userData, xmlErrorPtr error); + +/* + * Use the following function to reset the two global variables + * xmlGenericError and xmlGenericErrorContext. + */ +XMLPUBFUN void XMLCALL + xmlSetGenericErrorFunc (void *ctx, + xmlGenericErrorFunc handler); +XMLPUBFUN void XMLCALL + initGenericErrorDefaultFunc (xmlGenericErrorFunc *handler); + +XMLPUBFUN void XMLCALL + xmlSetStructuredErrorFunc (void *ctx, + xmlStructuredErrorFunc handler); +/* + * Default message routines used by SAX and Valid context for error + * and warning reporting. + */ +XMLPUBFUN void XMLCDECL + xmlParserError (void *ctx, + const char *msg, + ...); +XMLPUBFUN void XMLCDECL + xmlParserWarning (void *ctx, + const char *msg, + ...); +XMLPUBFUN void XMLCDECL + xmlParserValidityError (void *ctx, + const char *msg, + ...); +XMLPUBFUN void XMLCDECL + xmlParserValidityWarning (void *ctx, + const char *msg, + ...); +XMLPUBFUN void XMLCALL + xmlParserPrintFileInfo (xmlParserInputPtr input); +XMLPUBFUN void XMLCALL + xmlParserPrintFileContext (xmlParserInputPtr input); + +/* + * Extended error information routines + */ +XMLPUBFUN xmlErrorPtr XMLCALL + xmlGetLastError (void); +XMLPUBFUN void XMLCALL + xmlResetLastError (void); +XMLPUBFUN xmlErrorPtr XMLCALL + xmlCtxtGetLastError (void *ctx); +XMLPUBFUN void XMLCALL + xmlCtxtResetLastError (void *ctx); +XMLPUBFUN void XMLCALL + xmlResetError (xmlErrorPtr err); +XMLPUBFUN int XMLCALL + xmlCopyError (xmlErrorPtr from, + xmlErrorPtr to); + +#ifdef IN_LIBXML +/* + * Internal callback reporting routine + */ +XMLPUBFUN void XMLCALL + __xmlRaiseError (xmlStructuredErrorFunc schannel, + xmlGenericErrorFunc channel, + void *data, + void *ctx, + void *node, + int domain, + int code, + xmlErrorLevel level, + const char *file, + int line, + const char *str1, + const char *str2, + const char *str3, + int int1, + int col, + const char *msg, + ...); +XMLPUBFUN void XMLCALL + __xmlSimpleError (int domain, + int code, + xmlNodePtr node, + const char *msg, + const char *extra); +#endif +#ifdef __cplusplus +} +#endif +#endif /* __XML_ERROR_H__ */ diff --git a/gettext-tools/gnulib-lib/libxml/xmlexports.in.h b/gettext-tools/gnulib-lib/libxml/xmlexports.in.h new file mode 100644 index 0000000..29a6f54 --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/xmlexports.in.h @@ -0,0 +1,157 @@ +/* + * Summary: macros for marking symbols as exportable/importable. + * Description: macros for marking symbols as exportable/importable. + * + * Copy: See Copyright for the status of this software. + * + * Author: Igor Zlatovic + */ + +#ifndef __XML_EXPORTS_H__ +#define __XML_EXPORTS_H__ + +/** + * XMLPUBFUN, XMLPUBVAR, XMLCALL + * + * Macros which declare an exportable function, an exportable variable and + * the calling convention used for functions. + * + * Please use an extra block for every platform/compiler combination when + * modifying this, rather than overlong #ifdef lines. This helps + * readability as well as the fact that different compilers on the same + * platform might need different definitions. + */ + +/** + * XMLPUBFUN: + * + * Macros which declare an exportable function + */ +#define XMLPUBFUN +/** + * XMLPUBVAR: + * + * Macros which declare an exportable variable + */ +#define XMLPUBVAR extern +/** + * XMLCALL: + * + * Macros which declare the called convention for exported functions + */ +#define XMLCALL +/** + * XMLCDECL: + * + * Macro which declares the calling convention for exported functions that + * use '...'. + */ +#define XMLCDECL + +/** DOC_DISABLE */ + +/* Windows platform with MS compiler */ +#if defined(_WIN32) && defined(_MSC_VER) + #undef XMLPUBFUN + #undef XMLPUBVAR + #undef XMLCALL + #undef XMLCDECL + #if defined(IN_LIBXML) && !defined(LIBXML_STATIC) + #define XMLPUBFUN __declspec(dllexport) + #define XMLPUBVAR __declspec(dllexport) + #else + #define XMLPUBFUN + #if !defined(LIBXML_STATIC) + #define XMLPUBVAR __declspec(dllimport) extern + #else + #define XMLPUBVAR extern + #endif + #endif + #if defined(LIBXML_FASTCALL) + #define XMLCALL __fastcall + #else + #define XMLCALL __cdecl + #endif + #define XMLCDECL __cdecl + #if !defined _REENTRANT + #define _REENTRANT + #endif +#endif + +/* Windows platform with Borland compiler */ +#if defined(_WIN32) && defined(__BORLANDC__) + #undef XMLPUBFUN + #undef XMLPUBVAR + #undef XMLCALL + #undef XMLCDECL + #if defined(IN_LIBXML) && !defined(LIBXML_STATIC) + #define XMLPUBFUN __declspec(dllexport) + #define XMLPUBVAR __declspec(dllexport) extern + #else + #define XMLPUBFUN + #if !defined(LIBXML_STATIC) + #define XMLPUBVAR __declspec(dllimport) extern + #else + #define XMLPUBVAR extern + #endif + #endif + #define XMLCALL __cdecl + #define XMLCDECL __cdecl + #if !defined _REENTRANT + #define _REENTRANT + #endif +#endif + +/* Windows platform with GNU compiler (Mingw) */ +#if defined(_WIN32) && defined(__MINGW32__) + #undef XMLPUBFUN + #undef XMLPUBVAR + #undef XMLCALL + #undef XMLCDECL + #if defined(IN_LIBXML) && !defined(LIBXML_STATIC) + #define XMLPUBFUN __declspec(dllexport) + #define XMLPUBVAR __declspec(dllexport) + #else + #define XMLPUBFUN + #if !defined(LIBXML_STATIC) + #define XMLPUBVAR __declspec(dllimport) extern + #else + #define XMLPUBVAR extern + #endif + #endif + #define XMLCALL __cdecl + #define XMLCDECL __cdecl + #if !defined _REENTRANT + #define _REENTRANT + #endif +#endif + +/* Cygwin platform, GNU compiler */ +#if defined(_WIN32) && defined(__CYGWIN__) + #undef XMLPUBFUN + #undef XMLPUBVAR + #undef XMLCALL + #undef XMLCDECL + #if defined(IN_LIBXML) && !defined(LIBXML_STATIC) + #define XMLPUBFUN __declspec(dllexport) + #define XMLPUBVAR __declspec(dllexport) + #else + #define XMLPUBFUN + #if !defined(LIBXML_STATIC) + #define XMLPUBVAR __declspec(dllimport) extern + #else + #define XMLPUBVAR + #endif + #endif + #define XMLCALL __cdecl + #define XMLCDECL __cdecl +#endif + +/* Compatibility */ +#if !defined(LIBXML_DLL_IMPORT) +#define LIBXML_DLL_IMPORT XMLPUBVAR +#endif + +#endif /* __XML_EXPORTS_H__ */ + + diff --git a/gettext-tools/gnulib-lib/libxml/xmlmemory.c b/gettext-tools/gnulib-lib/libxml/xmlmemory.c new file mode 100644 index 0000000..362a0b0 --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/xmlmemory.c @@ -0,0 +1,1044 @@ +/* + * xmlmemory.c: libxml memory allocator wrapper. + * + * daniel@veillard.com + */ + +#define IN_LIBXML +#include "libxml.h" + +#include + +#ifdef HAVE_SYS_TYPES_H +#include +#endif + +#ifdef HAVE_TIME_H +#include +#endif + +#ifdef HAVE_STDLIB_H +#include +#else +#ifdef HAVE_MALLOC_H +#include +#endif +#endif + +#ifdef HAVE_CTYPE_H +#include +#endif + +/* #define DEBUG_MEMORY */ + +/** + * MEM_LIST: + * + * keep track of all allocated blocks for error reporting + * Always build the memory list ! + */ +#ifdef DEBUG_MEMORY_LOCATION +#ifndef MEM_LIST +#define MEM_LIST /* keep a list of all the allocated memory blocks */ +#endif +#endif + +#include /* must come before xmlmemory.h */ +#include +#include +#include + +static int xmlMemInitialized = 0; +static unsigned long debugMemSize = 0; +static unsigned long debugMemBlocks = 0; +static unsigned long debugMaxMemSize = 0; +static xmlMutexPtr xmlMemMutex = NULL; + +void xmlMallocBreakpoint(void); + +/************************************************************************ + * * + * Macros, variables and associated types * + * * + ************************************************************************/ + +#if !defined(LIBXML_THREAD_ENABLED) && !defined(LIBXML_THREAD_ALLOC_ENABLED) +#ifdef xmlMalloc +#undef xmlMalloc +#endif +#ifdef xmlRealloc +#undef xmlRealloc +#endif +#ifdef xmlMemStrdup +#undef xmlMemStrdup +#endif +#endif + +/* + * Each of the blocks allocated begin with a header containing informations + */ + +#define MEMTAG 0x5aa5 + +#define MALLOC_TYPE 1 +#define REALLOC_TYPE 2 +#define STRDUP_TYPE 3 +#define MALLOC_ATOMIC_TYPE 4 +#define REALLOC_ATOMIC_TYPE 5 + +typedef struct memnod { + unsigned int mh_tag; + unsigned int mh_type; + unsigned long mh_number; + size_t mh_size; +#ifdef MEM_LIST + struct memnod *mh_next; + struct memnod *mh_prev; +#endif + const char *mh_file; + unsigned int mh_line; +} MEMHDR; + + +#ifdef SUN4 +#define ALIGN_SIZE 16 +#else +#define ALIGN_SIZE sizeof(double) +#endif +#define HDR_SIZE sizeof(MEMHDR) +#define RESERVE_SIZE (((HDR_SIZE + (ALIGN_SIZE-1)) \ + / ALIGN_SIZE ) * ALIGN_SIZE) + + +#define CLIENT_2_HDR(a) ((MEMHDR *) (((char *) (a)) - RESERVE_SIZE)) +#define HDR_2_CLIENT(a) ((void *) (((char *) (a)) + RESERVE_SIZE)) + + +static unsigned int block=0; +static unsigned int xmlMemStopAtBlock = 0; +static void *xmlMemTraceBlockAt = NULL; +#ifdef MEM_LIST +static MEMHDR *memlist = NULL; +#endif + +static void debugmem_tag_error(void *addr); +#ifdef MEM_LIST +static void debugmem_list_add(MEMHDR *); +static void debugmem_list_delete(MEMHDR *); +#endif +#define Mem_Tag_Err(a) debugmem_tag_error(a); + +#ifndef TEST_POINT +#define TEST_POINT +#endif + +/** + * xmlMallocBreakpoint: + * + * Breakpoint to use in conjunction with xmlMemStopAtBlock. When the block + * number reaches the specified value this function is called. One need to add a breakpoint + * to it to get the context in which the given block is allocated. + */ + +void +xmlMallocBreakpoint(void) { + xmlGenericError(xmlGenericErrorContext, + "xmlMallocBreakpoint reached on block %d\n", xmlMemStopAtBlock); +} + +/** + * xmlMallocLoc: + * @size: an int specifying the size in byte to allocate. + * @file: the file name or NULL + * @line: the line number + * + * a malloc() equivalent, with logging of the allocation info. + * + * Returns a pointer to the allocated area or NULL in case of lack of memory. + */ + +void * +xmlMallocLoc(size_t size, const char * file, int line) +{ + MEMHDR *p; + void *ret; + + if (!xmlMemInitialized) xmlInitMemory(); +#ifdef DEBUG_MEMORY + xmlGenericError(xmlGenericErrorContext, + "Malloc(%d)\n",size); +#endif + + TEST_POINT + + p = (MEMHDR *) malloc(RESERVE_SIZE+size); + + if (!p) { + xmlGenericError(xmlGenericErrorContext, + "xmlMallocLoc : Out of free space\n"); + xmlMemoryDump(); + return(NULL); + } + p->mh_tag = MEMTAG; + p->mh_size = size; + p->mh_type = MALLOC_TYPE; + p->mh_file = file; + p->mh_line = line; + xmlMutexLock(xmlMemMutex); + p->mh_number = ++block; + debugMemSize += size; + debugMemBlocks++; + if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize; +#ifdef MEM_LIST + debugmem_list_add(p); +#endif + xmlMutexUnlock(xmlMemMutex); + +#ifdef DEBUG_MEMORY + xmlGenericError(xmlGenericErrorContext, + "Malloc(%d) Ok\n",size); +#endif + + if (xmlMemStopAtBlock == p->mh_number) xmlMallocBreakpoint(); + + ret = HDR_2_CLIENT(p); + + if (xmlMemTraceBlockAt == ret) { + xmlGenericError(xmlGenericErrorContext, + "%p : Malloc(%d) Ok\n", xmlMemTraceBlockAt, size); + xmlMallocBreakpoint(); + } + + TEST_POINT + + return(ret); +} + +/** + * xmlMallocAtomicLoc: + * @size: an int specifying the size in byte to allocate. + * @file: the file name or NULL + * @line: the line number + * + * a malloc() equivalent, with logging of the allocation info. + * + * Returns a pointer to the allocated area or NULL in case of lack of memory. + */ + +void * +xmlMallocAtomicLoc(size_t size, const char * file, int line) +{ + MEMHDR *p; + void *ret; + + if (!xmlMemInitialized) xmlInitMemory(); +#ifdef DEBUG_MEMORY + xmlGenericError(xmlGenericErrorContext, + "Malloc(%d)\n",size); +#endif + + TEST_POINT + + p = (MEMHDR *) malloc(RESERVE_SIZE+size); + + if (!p) { + xmlGenericError(xmlGenericErrorContext, + "xmlMallocLoc : Out of free space\n"); + xmlMemoryDump(); + return(NULL); + } + p->mh_tag = MEMTAG; + p->mh_size = size; + p->mh_type = MALLOC_ATOMIC_TYPE; + p->mh_file = file; + p->mh_line = line; + xmlMutexLock(xmlMemMutex); + p->mh_number = ++block; + debugMemSize += size; + debugMemBlocks++; + if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize; +#ifdef MEM_LIST + debugmem_list_add(p); +#endif + xmlMutexUnlock(xmlMemMutex); + +#ifdef DEBUG_MEMORY + xmlGenericError(xmlGenericErrorContext, + "Malloc(%d) Ok\n",size); +#endif + + if (xmlMemStopAtBlock == p->mh_number) xmlMallocBreakpoint(); + + ret = HDR_2_CLIENT(p); + + if (xmlMemTraceBlockAt == ret) { + xmlGenericError(xmlGenericErrorContext, + "%p : Malloc(%d) Ok\n", xmlMemTraceBlockAt, size); + xmlMallocBreakpoint(); + } + + TEST_POINT + + return(ret); +} +/** + * xmlMemMalloc: + * @size: an int specifying the size in byte to allocate. + * + * a malloc() equivalent, with logging of the allocation info. + * + * Returns a pointer to the allocated area or NULL in case of lack of memory. + */ + +void * +xmlMemMalloc(size_t size) +{ + return(xmlMallocLoc(size, "none", 0)); +} + +/** + * xmlReallocLoc: + * @ptr: the initial memory block pointer + * @size: an int specifying the size in byte to allocate. + * @file: the file name or NULL + * @line: the line number + * + * a realloc() equivalent, with logging of the allocation info. + * + * Returns a pointer to the allocated area or NULL in case of lack of memory. + */ + +void * +xmlReallocLoc(void *ptr,size_t size, const char * file, int line) +{ + MEMHDR *p; + unsigned long number; +#ifdef DEBUG_MEMORY + size_t oldsize; +#endif + + if (ptr == NULL) + return(xmlMallocLoc(size, file, line)); + + if (!xmlMemInitialized) xmlInitMemory(); + TEST_POINT + + p = CLIENT_2_HDR(ptr); + number = p->mh_number; + if (xmlMemStopAtBlock == number) xmlMallocBreakpoint(); + if (p->mh_tag != MEMTAG) { + Mem_Tag_Err(p); + goto error; + } + p->mh_tag = ~MEMTAG; + xmlMutexLock(xmlMemMutex); + debugMemSize -= p->mh_size; + debugMemBlocks--; +#ifdef DEBUG_MEMORY + oldsize = p->mh_size; +#endif +#ifdef MEM_LIST + debugmem_list_delete(p); +#endif + xmlMutexUnlock(xmlMemMutex); + + p = (MEMHDR *) realloc(p,RESERVE_SIZE+size); + if (!p) { + goto error; + } + if (xmlMemTraceBlockAt == ptr) { + xmlGenericError(xmlGenericErrorContext, + "%p : Realloced(%d -> %d) Ok\n", + xmlMemTraceBlockAt, p->mh_size, size); + xmlMallocBreakpoint(); + } + p->mh_tag = MEMTAG; + p->mh_number = number; + p->mh_type = REALLOC_TYPE; + p->mh_size = size; + p->mh_file = file; + p->mh_line = line; + xmlMutexLock(xmlMemMutex); + debugMemSize += size; + debugMemBlocks++; + if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize; +#ifdef MEM_LIST + debugmem_list_add(p); +#endif + xmlMutexUnlock(xmlMemMutex); + + TEST_POINT + +#ifdef DEBUG_MEMORY + xmlGenericError(xmlGenericErrorContext, + "Realloced(%d to %d) Ok\n", oldsize, size); +#endif + return(HDR_2_CLIENT(p)); + +error: + return(NULL); +} + +/** + * xmlMemRealloc: + * @ptr: the initial memory block pointer + * @size: an int specifying the size in byte to allocate. + * + * a realloc() equivalent, with logging of the allocation info. + * + * Returns a pointer to the allocated area or NULL in case of lack of memory. + */ + +void * +xmlMemRealloc(void *ptr,size_t size) { + return(xmlReallocLoc(ptr, size, "none", 0)); +} + +/** + * xmlMemFree: + * @ptr: the memory block pointer + * + * a free() equivalent, with error checking. + */ +void +xmlMemFree(void *ptr) +{ + MEMHDR *p; + char *target; +#ifdef DEBUG_MEMORY + size_t size; +#endif + + if (ptr == (void *) -1) { + xmlGenericError(xmlGenericErrorContext, + "trying to free pointer from freed area\n"); + goto error; + } + + if (xmlMemTraceBlockAt == ptr) { + xmlGenericError(xmlGenericErrorContext, + "%p : Freed()\n", xmlMemTraceBlockAt); + xmlMallocBreakpoint(); + } + + TEST_POINT + + target = (char *) ptr; + + p = CLIENT_2_HDR(ptr); + if (p->mh_tag != MEMTAG) { + Mem_Tag_Err(p); + goto error; + } + if (xmlMemStopAtBlock == p->mh_number) xmlMallocBreakpoint(); + p->mh_tag = ~MEMTAG; + memset(target, -1, p->mh_size); + xmlMutexLock(xmlMemMutex); + debugMemSize -= p->mh_size; + debugMemBlocks--; +#ifdef DEBUG_MEMORY + size = p->mh_size; +#endif +#ifdef MEM_LIST + debugmem_list_delete(p); +#endif + xmlMutexUnlock(xmlMemMutex); + + free(p); + + TEST_POINT + +#ifdef DEBUG_MEMORY + xmlGenericError(xmlGenericErrorContext, + "Freed(%d) Ok\n", size); +#endif + + return; + +error: + xmlGenericError(xmlGenericErrorContext, + "xmlMemFree(%lX) error\n", (unsigned long) ptr); + xmlMallocBreakpoint(); + return; +} + +/** + * xmlMemStrdupLoc: + * @str: the initial string pointer + * @file: the file name or NULL + * @line: the line number + * + * a strdup() equivalent, with logging of the allocation info. + * + * Returns a pointer to the new string or NULL if allocation error occurred. + */ + +char * +xmlMemStrdupLoc(const char *str, const char *file, int line) +{ + char *s; + size_t size = strlen(str) + 1; + MEMHDR *p; + + if (!xmlMemInitialized) xmlInitMemory(); + TEST_POINT + + p = (MEMHDR *) malloc(RESERVE_SIZE+size); + if (!p) { + goto error; + } + p->mh_tag = MEMTAG; + p->mh_size = size; + p->mh_type = STRDUP_TYPE; + p->mh_file = file; + p->mh_line = line; + xmlMutexLock(xmlMemMutex); + p->mh_number = ++block; + debugMemSize += size; + debugMemBlocks++; + if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize; +#ifdef MEM_LIST + debugmem_list_add(p); +#endif + xmlMutexUnlock(xmlMemMutex); + + s = (char *) HDR_2_CLIENT(p); + + if (xmlMemStopAtBlock == p->mh_number) xmlMallocBreakpoint(); + + if (s != NULL) + strcpy(s,str); + else + goto error; + + TEST_POINT + + if (xmlMemTraceBlockAt == s) { + xmlGenericError(xmlGenericErrorContext, + "%p : Strdup() Ok\n", xmlMemTraceBlockAt); + xmlMallocBreakpoint(); + } + + return(s); + +error: + return(NULL); +} + +/** + * xmlMemoryStrdup: + * @str: the initial string pointer + * + * a strdup() equivalent, with logging of the allocation info. + * + * Returns a pointer to the new string or NULL if allocation error occurred. + */ + +char * +xmlMemoryStrdup(const char *str) { + return(xmlMemStrdupLoc(str, "none", 0)); +} + +/** + * xmlMemUsed: + * + * Provides the amount of memory currently allocated + * + * Returns an int representing the amount of memory allocated. + */ + +int +xmlMemUsed(void) { + return(debugMemSize); +} + +/** + * xmlMemBlocks: + * + * Provides the number of memory areas currently allocated + * + * Returns an int representing the number of blocks + */ + +int +xmlMemBlocks(void) { + return(debugMemBlocks); +} + +#ifdef MEM_LIST +/** + * xmlMemContentShow: + * @fp: a FILE descriptor used as the output file + * @p: a memory block header + * + * tries to show some content from the memory block + */ + +static void +xmlMemContentShow(FILE *fp, MEMHDR *p) +{ + int i,j,k,len = p->mh_size; + const char *buf = (const char *) HDR_2_CLIENT(p); + + if (p == NULL) { + fprintf(fp, " NULL"); + return; + } + + for (i = 0;i < len;i++) { + if (buf[i] == 0) break; + if (!isprint((unsigned char) buf[i])) break; + } + if ((i < 4) && ((buf[i] != 0) || (i == 0))) { + if (len >= 4) { + MEMHDR *q; + void *cur; + + for (j = 0;(j < len -3) && (j < 40);j += 4) { + cur = *((void **) &buf[j]); + q = CLIENT_2_HDR(cur); + p = memlist; + k = 0; + while (p != NULL) { + if (p == q) break; + p = p->mh_next; + if (k++ > 100) break; + } + if ((p != NULL) && (p == q)) { + fprintf(fp, " pointer to #%lu at index %d", + p->mh_number, j); + return; + } + } + } + } else if ((i == 0) && (buf[i] == 0)) { + fprintf(fp," null"); + } else { + if (buf[i] == 0) fprintf(fp," \"%.25s\"", buf); + else { + fprintf(fp," ["); + for (j = 0;j < i;j++) + fprintf(fp,"%c", buf[j]); + fprintf(fp,"]"); + } + } +} +#endif + +/** + * xmlMemDisplay: + * @fp: a FILE descriptor used as the output file, if NULL, the result is + * written to the file .memorylist + * + * show in-extenso the memory blocks allocated + */ + +void +xmlMemDisplay(FILE *fp) +{ +#ifdef MEM_LIST + MEMHDR *p; + unsigned idx; + int nb = 0; +#if defined(HAVE_LOCALTIME) && defined(HAVE_STRFTIME) + time_t currentTime; + char buf[500]; + struct tm * tstruct; +#endif +#endif + FILE *old_fp = fp; + + if (fp == NULL) { + fp = fopen(".memorylist", "w"); + if (fp == NULL) + return; + } + +#ifdef MEM_LIST +#if defined(HAVE_LOCALTIME) && defined(HAVE_STRFTIME) + currentTime = time(NULL); + tstruct = localtime(¤tTime); + strftime(buf, sizeof(buf) - 1, "%I:%M:%S %p", tstruct); + fprintf(fp," %s\n\n", buf); +#endif + + + fprintf(fp," MEMORY ALLOCATED : %lu, MAX was %lu\n", + debugMemSize, debugMaxMemSize); + fprintf(fp,"BLOCK NUMBER SIZE TYPE\n"); + idx = 0; + xmlMutexLock(xmlMemMutex); + p = memlist; + while (p) { + fprintf(fp,"%-5u %6lu %6lu ",idx++,p->mh_number, + (unsigned long)p->mh_size); + switch (p->mh_type) { + case STRDUP_TYPE:fprintf(fp,"strdup() in ");break; + case MALLOC_TYPE:fprintf(fp,"malloc() in ");break; + case REALLOC_TYPE:fprintf(fp,"realloc() in ");break; + case MALLOC_ATOMIC_TYPE:fprintf(fp,"atomicmalloc() in ");break; + case REALLOC_ATOMIC_TYPE:fprintf(fp,"atomicrealloc() in ");break; + default: + fprintf(fp,"Unknown memory block, may be corrupted"); + xmlMutexUnlock(xmlMemMutex); + if (old_fp == NULL) + fclose(fp); + return; + } + if (p->mh_file != NULL) fprintf(fp,"%s(%u)", p->mh_file, p->mh_line); + if (p->mh_tag != MEMTAG) + fprintf(fp," INVALID"); + nb++; + if (nb < 100) + xmlMemContentShow(fp, p); + else + fprintf(fp," skip"); + + fprintf(fp,"\n"); + p = p->mh_next; + } + xmlMutexUnlock(xmlMemMutex); +#else + fprintf(fp,"Memory list not compiled (MEM_LIST not defined !)\n"); +#endif + if (old_fp == NULL) + fclose(fp); +} + +#ifdef MEM_LIST + +static void debugmem_list_add(MEMHDR *p) +{ + p->mh_next = memlist; + p->mh_prev = NULL; + if (memlist) memlist->mh_prev = p; + memlist = p; +#ifdef MEM_LIST_DEBUG + if (stderr) + Mem_Display(stderr); +#endif +} + +static void debugmem_list_delete(MEMHDR *p) +{ + if (p->mh_next) + p->mh_next->mh_prev = p->mh_prev; + if (p->mh_prev) + p->mh_prev->mh_next = p->mh_next; + else memlist = p->mh_next; +#ifdef MEM_LIST_DEBUG + if (stderr) + Mem_Display(stderr); +#endif +} + +#endif + +/* + * debugmem_tag_error: + * + * internal error function. + */ + +static void debugmem_tag_error(void *p) +{ + xmlGenericError(xmlGenericErrorContext, + "Memory tag error occurs :%p \n\t bye\n", p); +#ifdef MEM_LIST + if (stderr) + xmlMemDisplay(stderr); +#endif +} + +#ifdef MEM_LIST +static FILE *xmlMemoryDumpFile = NULL; +#endif + +/** + * xmlMemShow: + * @fp: a FILE descriptor used as the output file + * @nr: number of entries to dump + * + * show a show display of the memory allocated, and dump + * the @nr last allocated areas which were not freed + */ + +void +xmlMemShow(FILE *fp, int nr ATTRIBUTE_UNUSED) +{ +#ifdef MEM_LIST + MEMHDR *p; +#endif + + if (fp != NULL) + fprintf(fp," MEMORY ALLOCATED : %lu, MAX was %lu\n", + debugMemSize, debugMaxMemSize); +#ifdef MEM_LIST + xmlMutexLock(xmlMemMutex); + if (nr > 0) { + fprintf(fp,"NUMBER SIZE TYPE WHERE\n"); + p = memlist; + while ((p) && nr > 0) { + fprintf(fp,"%6lu %6lu ",p->mh_number,(unsigned long)p->mh_size); + switch (p->mh_type) { + case STRDUP_TYPE:fprintf(fp,"strdup() in ");break; + case MALLOC_TYPE:fprintf(fp,"malloc() in ");break; + case MALLOC_ATOMIC_TYPE:fprintf(fp,"atomicmalloc() in ");break; + case REALLOC_TYPE:fprintf(fp,"realloc() in ");break; + case REALLOC_ATOMIC_TYPE:fprintf(fp,"atomicrealloc() in ");break; + default:fprintf(fp," ??? in ");break; + } + if (p->mh_file != NULL) + fprintf(fp,"%s(%u)", p->mh_file, p->mh_line); + if (p->mh_tag != MEMTAG) + fprintf(fp," INVALID"); + xmlMemContentShow(fp, p); + fprintf(fp,"\n"); + nr--; + p = p->mh_next; + } + } + xmlMutexUnlock(xmlMemMutex); +#endif /* MEM_LIST */ +} + +/** + * xmlMemoryDump: + * + * Dump in-extenso the memory blocks allocated to the file .memorylist + */ + +void +xmlMemoryDump(void) +{ +#ifdef MEM_LIST + FILE *dump; + + if (debugMaxMemSize == 0) + return; + dump = fopen(".memdump", "w"); + if (dump == NULL) + xmlMemoryDumpFile = stderr; + else xmlMemoryDumpFile = dump; + + xmlMemDisplay(xmlMemoryDumpFile); + + if (dump != NULL) fclose(dump); +#endif /* MEM_LIST */ +} + + +/**************************************************************** + * * + * Initialization Routines * + * * + ****************************************************************/ + +/** + * xmlInitMemory: + * + * Initialize the memory layer. + * + * Returns 0 on success + */ +int +xmlInitMemory(void) +{ +#ifdef HAVE_STDLIB_H + char *breakpoint; +#endif +#ifdef DEBUG_MEMORY + xmlGenericError(xmlGenericErrorContext, + "xmlInitMemory()\n"); +#endif + /* + This is really not good code (see Bug 130419). Suggestions for + improvement will be welcome! + */ + if (xmlMemInitialized) return(-1); + xmlMemInitialized = 1; + xmlMemMutex = xmlNewMutex(); + +#ifdef HAVE_STDLIB_H + breakpoint = getenv("XML_MEM_BREAKPOINT"); + if (breakpoint != NULL) { + sscanf(breakpoint, "%ud", &xmlMemStopAtBlock); + } +#endif +#ifdef HAVE_STDLIB_H + breakpoint = getenv("XML_MEM_TRACE"); + if (breakpoint != NULL) { + sscanf(breakpoint, "%p", &xmlMemTraceBlockAt); + } +#endif + +#ifdef DEBUG_MEMORY + xmlGenericError(xmlGenericErrorContext, + "xmlInitMemory() Ok\n"); +#endif + return(0); +} + +/** + * xmlCleanupMemory: + * + * Free up all the memory allocated by the library for its own + * use. This should not be called by user level code. + */ +void +xmlCleanupMemory(void) { +#ifdef DEBUG_MEMORY + xmlGenericError(xmlGenericErrorContext, + "xmlCleanupMemory()\n"); +#endif + if (xmlMemInitialized == 0) + return; + + xmlFreeMutex(xmlMemMutex); + xmlMemMutex = NULL; + xmlMemInitialized = 0; +#ifdef DEBUG_MEMORY + xmlGenericError(xmlGenericErrorContext, + "xmlCleanupMemory() Ok\n"); +#endif +} + +/** + * xmlMemSetup: + * @freeFunc: the free() function to use + * @mallocFunc: the malloc() function to use + * @reallocFunc: the realloc() function to use + * @strdupFunc: the strdup() function to use + * + * Override the default memory access functions with a new set + * This has to be called before any other libxml routines ! + * + * Should this be blocked if there was already some allocations + * done ? + * + * Returns 0 on success + */ +int +xmlMemSetup(xmlFreeFunc freeFunc, xmlMallocFunc mallocFunc, + xmlReallocFunc reallocFunc, xmlStrdupFunc strdupFunc) { +#ifdef DEBUG_MEMORY + xmlGenericError(xmlGenericErrorContext, + "xmlMemSetup()\n"); +#endif + if (freeFunc == NULL) + return(-1); + if (mallocFunc == NULL) + return(-1); + if (reallocFunc == NULL) + return(-1); + if (strdupFunc == NULL) + return(-1); + xmlFree = freeFunc; + xmlMalloc = mallocFunc; + xmlMallocAtomic = mallocFunc; + xmlRealloc = reallocFunc; + xmlMemStrdup = strdupFunc; +#ifdef DEBUG_MEMORY + xmlGenericError(xmlGenericErrorContext, + "xmlMemSetup() Ok\n"); +#endif + return(0); +} + +/** + * xmlMemGet: + * @freeFunc: place to save the free() function in use + * @mallocFunc: place to save the malloc() function in use + * @reallocFunc: place to save the realloc() function in use + * @strdupFunc: place to save the strdup() function in use + * + * Provides the memory access functions set currently in use + * + * Returns 0 on success + */ +int +xmlMemGet(xmlFreeFunc *freeFunc, xmlMallocFunc *mallocFunc, + xmlReallocFunc *reallocFunc, xmlStrdupFunc *strdupFunc) { + if (freeFunc != NULL) *freeFunc = xmlFree; + if (mallocFunc != NULL) *mallocFunc = xmlMalloc; + if (reallocFunc != NULL) *reallocFunc = xmlRealloc; + if (strdupFunc != NULL) *strdupFunc = xmlMemStrdup; + return(0); +} + +/** + * xmlGcMemSetup: + * @freeFunc: the free() function to use + * @mallocFunc: the malloc() function to use + * @mallocAtomicFunc: the malloc() function to use for atomic allocations + * @reallocFunc: the realloc() function to use + * @strdupFunc: the strdup() function to use + * + * Override the default memory access functions with a new set + * This has to be called before any other libxml routines ! + * The mallocAtomicFunc is specialized for atomic block + * allocations (i.e. of areas useful for garbage collected memory allocators + * + * Should this be blocked if there was already some allocations + * done ? + * + * Returns 0 on success + */ +int +xmlGcMemSetup(xmlFreeFunc freeFunc, xmlMallocFunc mallocFunc, + xmlMallocFunc mallocAtomicFunc, xmlReallocFunc reallocFunc, + xmlStrdupFunc strdupFunc) { +#ifdef DEBUG_MEMORY + xmlGenericError(xmlGenericErrorContext, + "xmlGcMemSetup()\n"); +#endif + if (freeFunc == NULL) + return(-1); + if (mallocFunc == NULL) + return(-1); + if (mallocAtomicFunc == NULL) + return(-1); + if (reallocFunc == NULL) + return(-1); + if (strdupFunc == NULL) + return(-1); + xmlFree = freeFunc; + xmlMalloc = mallocFunc; + xmlMallocAtomic = mallocAtomicFunc; + xmlRealloc = reallocFunc; + xmlMemStrdup = strdupFunc; +#ifdef DEBUG_MEMORY + xmlGenericError(xmlGenericErrorContext, + "xmlGcMemSetup() Ok\n"); +#endif + return(0); +} + +/** + * xmlGcMemGet: + * @freeFunc: place to save the free() function in use + * @mallocFunc: place to save the malloc() function in use + * @mallocAtomicFunc: place to save the atomic malloc() function in use + * @reallocFunc: place to save the realloc() function in use + * @strdupFunc: place to save the strdup() function in use + * + * Provides the memory access functions set currently in use + * The mallocAtomicFunc is specialized for atomic block + * allocations (i.e. of areas useful for garbage collected memory allocators + * + * Returns 0 on success + */ +int +xmlGcMemGet(xmlFreeFunc *freeFunc, xmlMallocFunc *mallocFunc, + xmlMallocFunc *mallocAtomicFunc, xmlReallocFunc *reallocFunc, + xmlStrdupFunc *strdupFunc) { + if (freeFunc != NULL) *freeFunc = xmlFree; + if (mallocFunc != NULL) *mallocFunc = xmlMalloc; + if (mallocAtomicFunc != NULL) *mallocAtomicFunc = xmlMallocAtomic; + if (reallocFunc != NULL) *reallocFunc = xmlRealloc; + if (strdupFunc != NULL) *strdupFunc = xmlMemStrdup; + return(0); +} + +#define bottom_xmlmemory +#include "elfgcchack.h" diff --git a/gettext-tools/gnulib-lib/libxml/xmlmemory.in.h b/gettext-tools/gnulib-lib/libxml/xmlmemory.in.h new file mode 100644 index 0000000..235721c --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/xmlmemory.in.h @@ -0,0 +1,222 @@ +/* + * Summary: interface for the memory allocator + * Description: provides interfaces for the memory allocator, + * including debugging capabilities. + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + + +#ifndef __DEBUG_MEMORY_ALLOC__ +#define __DEBUG_MEMORY_ALLOC__ + +#include +#include + +/** + * DEBUG_MEMORY: + * + * DEBUG_MEMORY replaces the allocator with a collect and debug + * shell to the libc allocator. + * DEBUG_MEMORY should only be activated when debugging + * libxml i.e. if libxml has been configured with --with-debug-mem too. + */ +/* #define DEBUG_MEMORY_FREED */ +/* #define DEBUG_MEMORY_LOCATION */ + +#ifdef DEBUG +#ifndef DEBUG_MEMORY +#define DEBUG_MEMORY +#endif +#endif + +/** + * DEBUG_MEMORY_LOCATION: + * + * DEBUG_MEMORY_LOCATION should be activated only when debugging + * libxml i.e. if libxml has been configured with --with-debug-mem too. + */ +#ifdef DEBUG_MEMORY_LOCATION +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * The XML memory wrapper support 4 basic overloadable functions. + */ +/** + * xmlFreeFunc: + * @mem: an already allocated block of memory + * + * Signature for a free() implementation. + */ +typedef void (XMLCALL *xmlFreeFunc)(void *mem); +/** + * xmlMallocFunc: + * @size: the size requested in bytes + * + * Signature for a malloc() implementation. + * + * Returns a pointer to the newly allocated block or NULL in case of error. + */ +typedef void *(XMLCALL *xmlMallocFunc)(size_t size); + +/** + * xmlReallocFunc: + * @mem: an already allocated block of memory + * @size: the new size requested in bytes + * + * Signature for a realloc() implementation. + * + * Returns a pointer to the newly reallocated block or NULL in case of error. + */ +typedef void *(XMLCALL *xmlReallocFunc)(void *mem, size_t size); + +/** + * xmlStrdupFunc: + * @str: a zero terminated string + * + * Signature for an strdup() implementation. + * + * Returns the copy of the string or NULL in case of error. + */ +typedef char *(XMLCALL *xmlStrdupFunc)(const char *str); + +/* + * The 4 interfaces used for all memory handling within libxml. +LIBXML_DLL_IMPORT extern xmlFreeFunc xmlFree; +LIBXML_DLL_IMPORT extern xmlMallocFunc xmlMalloc; +LIBXML_DLL_IMPORT extern xmlMallocFunc xmlMallocAtomic; +LIBXML_DLL_IMPORT extern xmlReallocFunc xmlRealloc; +LIBXML_DLL_IMPORT extern xmlStrdupFunc xmlMemStrdup; + */ + +/* + * The way to overload the existing functions. + * The xmlGc function have an extra entry for atomic block + * allocations useful for garbage collected memory allocators + */ +XMLPUBFUN int XMLCALL + xmlMemSetup (xmlFreeFunc freeFunc, + xmlMallocFunc mallocFunc, + xmlReallocFunc reallocFunc, + xmlStrdupFunc strdupFunc); +XMLPUBFUN int XMLCALL + xmlMemGet (xmlFreeFunc *freeFunc, + xmlMallocFunc *mallocFunc, + xmlReallocFunc *reallocFunc, + xmlStrdupFunc *strdupFunc); +XMLPUBFUN int XMLCALL + xmlGcMemSetup (xmlFreeFunc freeFunc, + xmlMallocFunc mallocFunc, + xmlMallocFunc mallocAtomicFunc, + xmlReallocFunc reallocFunc, + xmlStrdupFunc strdupFunc); +XMLPUBFUN int XMLCALL + xmlGcMemGet (xmlFreeFunc *freeFunc, + xmlMallocFunc *mallocFunc, + xmlMallocFunc *mallocAtomicFunc, + xmlReallocFunc *reallocFunc, + xmlStrdupFunc *strdupFunc); + +/* + * Initialization of the memory layer. + */ +XMLPUBFUN int XMLCALL + xmlInitMemory (void); + +/* + * Cleanup of the memory layer. + */ +XMLPUBFUN void XMLCALL + xmlCleanupMemory (void); +/* + * These are specific to the XML debug memory wrapper. + */ +XMLPUBFUN int XMLCALL + xmlMemUsed (void); +XMLPUBFUN int XMLCALL + xmlMemBlocks (void); +XMLPUBFUN void XMLCALL + xmlMemDisplay (FILE *fp); +XMLPUBFUN void XMLCALL + xmlMemShow (FILE *fp, int nr); +XMLPUBFUN void XMLCALL + xmlMemoryDump (void); +XMLPUBFUN void * XMLCALL + xmlMemMalloc (size_t size); +XMLPUBFUN void * XMLCALL + xmlMemRealloc (void *ptr,size_t size); +XMLPUBFUN void XMLCALL + xmlMemFree (void *ptr); +XMLPUBFUN char * XMLCALL + xmlMemoryStrdup (const char *str); +XMLPUBFUN void * XMLCALL + xmlMallocLoc (size_t size, const char *file, int line); +XMLPUBFUN void * XMLCALL + xmlReallocLoc (void *ptr, size_t size, const char *file, int line); +XMLPUBFUN void * XMLCALL + xmlMallocAtomicLoc (size_t size, const char *file, int line); +XMLPUBFUN char * XMLCALL + xmlMemStrdupLoc (const char *str, const char *file, int line); + + +#ifdef DEBUG_MEMORY_LOCATION +/** + * xmlMalloc: + * @size: number of bytes to allocate + * + * Wrapper for the malloc() function used in the XML library. + * + * Returns the pointer to the allocated area or NULL in case of error. + */ +#define xmlMalloc(size) xmlMallocLoc((size), __FILE__, __LINE__) +/** + * xmlMallocAtomic: + * @size: number of bytes to allocate + * + * Wrapper for the malloc() function used in the XML library for allocation + * of block not containing pointers to other areas. + * + * Returns the pointer to the allocated area or NULL in case of error. + */ +#define xmlMallocAtomic(size) xmlMallocAtomicLoc((size), __FILE__, __LINE__) +/** + * xmlRealloc: + * @ptr: pointer to the existing allocated area + * @size: number of bytes to allocate + * + * Wrapper for the realloc() function used in the XML library. + * + * Returns the pointer to the allocated area or NULL in case of error. + */ +#define xmlRealloc(ptr, size) xmlReallocLoc((ptr), (size), __FILE__, __LINE__) +/** + * xmlMemStrdup: + * @str: pointer to the existing string + * + * Wrapper for the strdup() function, xmlStrdup() is usually preferred. + * + * Returns the pointer to the allocated area or NULL in case of error. + */ +#define xmlMemStrdup(str) xmlMemStrdupLoc((str), __FILE__, __LINE__) + +#endif /* DEBUG_MEMORY_LOCATION */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#ifndef __XML_GLOBALS_H +#ifndef __XML_THREADS_H__ +#include +#include +#endif +#endif + +#endif /* __DEBUG_MEMORY_ALLOC__ */ + diff --git a/gettext-tools/gnulib-lib/libxml/xmlmodule.c b/gettext-tools/gnulib-lib/libxml/xmlmodule.c new file mode 100644 index 0000000..15bcf07 --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/xmlmodule.c @@ -0,0 +1,445 @@ +/* + * xmlmodule.c : basic API for dynamic module loading added 2.6.17 + * + * See Copyright for the status of this software. + * + * joelwreed@comcast.net + * + * http://www.fortran-2000.com/ArnaudRecipes/sharedlib.html + */ + +#define IN_LIBXML +#include "libxml.h" + +#include +#include +#include +#include +#include + +#ifdef LIBXML_MODULES_ENABLED + +struct _xmlModule { + unsigned char *name; + void *handle; +}; + +static void *xmlModulePlatformOpen(const char *name); +static int xmlModulePlatformClose(void *handle); +static int xmlModulePlatformSymbol(void *handle, const char *name, void **result); + +/************************************************************************ + * * + * module memory error handler * + * * + ************************************************************************/ + +/** + * xmlModuleErrMemory: + * @extra: extra information + * + * Handle an out of memory condition + */ +static void +xmlModuleErrMemory(xmlModulePtr module, const char *extra) +{ + const char *name = NULL; + + if (module != NULL) { + name = (const char *) module->name; + } + + __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE, + XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, extra, + name, NULL, 0, 0, + "Memory allocation failed : %s\n", extra); +} + +/** + * xmlModuleOpen: + * @name: the module name + * @options: a set of xmlModuleOption + * + * Opens a module/shared library given its name or path + * TODO: options are not yet implemented. + * + * Returns a handle for the module or NULL in case of error + */ +xmlModulePtr +xmlModuleOpen(const char *name, int options ATTRIBUTE_UNUSED) +{ + xmlModulePtr module; + + module = (xmlModulePtr) xmlMalloc(sizeof(xmlModule)); + if (module == NULL) { + xmlModuleErrMemory(NULL, "creating module"); + return (NULL); + } + + memset(module, 0, sizeof(xmlModule)); + + module->handle = xmlModulePlatformOpen(name); + + if (module->handle == NULL) { + xmlFree(module); + __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE, + XML_MODULE_OPEN, XML_ERR_FATAL, NULL, 0, 0, + name, NULL, 0, 0, "failed to open %s\n", name); + return(NULL); + } + + module->name = xmlStrdup((const xmlChar *) name); + return (module); +} + +/** + * xmlModuleSymbol: + * @module: the module + * @name: the name of the symbol + * @symbol: the resulting symbol address + * + * Lookup for a symbol address in the given module + * + * Returns 0 if the symbol was found, or -1 in case of error + */ +int +xmlModuleSymbol(xmlModulePtr module, const char *name, void **symbol) +{ + int rc = -1; + + if ((NULL == module) || (symbol == NULL)) { + __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE, + XML_MODULE_OPEN, XML_ERR_FATAL, NULL, 0, 0, + NULL, NULL, 0, 0, "null parameter\n"); + return rc; + } + + rc = xmlModulePlatformSymbol(module->handle, name, symbol); + + if (rc == -1) { + __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE, + XML_MODULE_OPEN, XML_ERR_FATAL, NULL, 0, 0, + name, NULL, 0, 0, + "failed to find symbol: %s\n", + (name == NULL ? "NULL" : name)); + return rc; + } + + return rc; +} + +/** + * xmlModuleClose: + * @module: the module handle + * + * The close operations unload the associated module and free the + * data associated to the module. + * + * Returns 0 in case of success, -1 in case of argument error and -2 + * if the module could not be closed/unloaded. + */ +int +xmlModuleClose(xmlModulePtr module) +{ + int rc; + + if (NULL == module) { + __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE, + XML_MODULE_CLOSE, XML_ERR_FATAL, NULL, 0, 0, + NULL, NULL, 0, 0, "null module pointer\n"); + return -1; + } + + rc = xmlModulePlatformClose(module->handle); + + if (rc != 0) { + __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE, + XML_MODULE_CLOSE, XML_ERR_FATAL, NULL, 0, 0, + (const char *) module->name, NULL, 0, 0, + "failed to close: %s\n", module->name); + return -2; + } + + rc = xmlModuleFree(module); + return (rc); +} + +/** + * xmlModuleFree: + * @module: the module handle + * + * The free operations free the data associated to the module + * but does not unload the associated shared library which may still + * be in use. + * + * Returns 0 in case of success, -1 in case of argument error + */ +int +xmlModuleFree(xmlModulePtr module) +{ + if (NULL == module) { + __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE, + XML_MODULE_CLOSE, XML_ERR_FATAL, NULL, 0, NULL, + NULL, NULL, 0, 0, "null module pointer\n"); + return -1; + } + + xmlFree(module->name); + xmlFree(module); + + return (0); +} + +#ifdef HAVE_DLOPEN +#ifdef HAVE_DLFCN_H +#include +#endif + +#ifndef RTLD_GLOBAL /* For Tru64 UNIX 4.0 */ +#define RTLD_GLOBAL 0 +#endif + +/** + * xmlModulePlatformOpen: + * @name: path to the module + * + * returns a handle on success, and zero on error. + */ + +static void * +xmlModulePlatformOpen(const char *name) +{ + return dlopen(name, RTLD_GLOBAL | RTLD_NOW); +} + +/* + * xmlModulePlatformClose: + * @handle: handle to the module + * + * returns 0 on success, and non-zero on error. + */ + +static int +xmlModulePlatformClose(void *handle) +{ + return dlclose(handle); +} + +/* + * xmlModulePlatformSymbol: + * http://www.opengroup.org/onlinepubs/009695399/functions/dlsym.html + * returns 0 on success and the loaded symbol in result, and -1 on error. + */ + +static int +xmlModulePlatformSymbol(void *handle, const char *name, void **symbol) +{ + *symbol = dlsym(handle, name); + if (dlerror() != NULL) { + return -1; + } + return 0; +} + +#else /* ! HAVE_DLOPEN */ + +#ifdef HAVE_SHLLOAD /* HAVE_SHLLOAD */ +#ifdef HAVE_DL_H +#include +#endif +/* + * xmlModulePlatformOpen: + * returns a handle on success, and zero on error. + */ + +static void * +xmlModulePlatformOpen(const char *name) +{ + return shl_load(name, BIND_IMMEDIATE, 0L); +} + +/* + * xmlModulePlatformClose: + * returns 0 on success, and non-zero on error. + */ + +static int +xmlModulePlatformClose(void *handle) +{ + return shl_unload(handle); +} + +/* + * xmlModulePlatformSymbol: + * http://docs.hp.com/en/B2355-90683/shl_load.3X.html + * returns 0 on success and the loaded symbol in result, and -1 on error. + */ + +static int +xmlModulePlatformSymbol(void *handle, const char *name, void **symbol) +{ + int rc; + + errno = 0; + rc = shl_findsym(&handle, name, TYPE_UNDEFINED, symbol); + return rc; +} + +#endif /* HAVE_SHLLOAD */ +#endif /* ! HAVE_DLOPEN */ + +#ifdef _WIN32 + +#include + +/* + * xmlModulePlatformOpen: + * returns a handle on success, and zero on error. + */ + +static void * +xmlModulePlatformOpen(const char *name) +{ + return LoadLibrary(name); +} + +/* + * xmlModulePlatformClose: + * returns 0 on success, and non-zero on error. + */ + +static int +xmlModulePlatformClose(void *handle) +{ + int rc; + + rc = FreeLibrary(handle); + return (0 == rc); +} + +/* + * xmlModulePlatformSymbol: + * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/getprocaddress.asp + * returns 0 on success and the loaded symbol in result, and -1 on error. + */ + +static int +xmlModulePlatformSymbol(void *handle, const char *name, void **symbol) +{ + *symbol = GetProcAddress(handle, name); + return (NULL == *symbol) ? -1 : 0; +} + +#endif /* _WIN32 */ + +#ifdef HAVE_BEOS + +#include + +/* + * xmlModulePlatformOpen: + * beos api info: http://www.beunited.org/bebook/The%20Kernel%20Kit/Images.html + * returns a handle on success, and zero on error. + */ + +static void * +xmlModulePlatformOpen(const char *name) +{ + return (void *) load_add_on(name); +} + +/* + * xmlModulePlatformClose: + * beos api info: http://www.beunited.org/bebook/The%20Kernel%20Kit/Images.html + * returns 0 on success, and non-zero on error. + */ + +static int +xmlModulePlatformClose(void *handle) +{ + status_t rc; + + rc = unload_add_on((image_id) handle); + + if (rc == B_OK) + return 0; + else + return -1; +} + +/* + * xmlModulePlatformSymbol: + * beos api info: http://www.beunited.org/bebook/The%20Kernel%20Kit/Images.html + * returns 0 on success and the loaded symbol in result, and -1 on error. + */ + +static int +xmlModulePlatformSymbol(void *handle, const char *name, void **symbol) +{ + status_t rc; + + rc = get_image_symbol((image_id) handle, name, B_SYMBOL_TYPE_ANY, symbol); + + return (rc == B_OK) ? 0 : -1; +} + +#endif /* HAVE_BEOS */ + +#ifdef HAVE_OS2 + +#include + +/* + * xmlModulePlatformOpen: + * os2 api info: http://www.edm2.com/os2api/Dos/DosLoadModule.html + * returns a handle on success, and zero on error. + */ + +static void * +xmlModulePlatformOpen(const char *name) +{ + char errbuf[256]; + void *handle; + int rc; + + rc = DosLoadModule(errbuf, sizeof(errbuf) - 1, name, &handle); + + if (rc) + return 0; + else + return (handle); +} + +/* + * xmlModulePlatformClose: + * os2 api info: http://www.edm2.com/os2api/Dos/DosFreeModule.html + * returns 0 on success, and non-zero on error. + */ + +static int +xmlModulePlatformClose(void *handle) +{ + return DosFreeModule(handle); +} + +/* + * xmlModulePlatformSymbol: + * os2 api info: http://www.edm2.com/os2api/Dos/DosQueryProcAddr.html + * returns 0 on success and the loaded symbol in result, and -1 on error. + */ + +static int +xmlModulePlatformSymbol(void *handle, const char *name, void **symbol) +{ + int rc; + + rc = DosQueryProcAddr(handle, 0, name, symbol); + + return (rc == NO_ERROR) ? 0 : -1; +} + +#endif /* HAVE_OS2 */ + +#define bottom_xmlmodule +#include "elfgcchack.h" +#endif /* LIBXML_MODULES_ENABLED */ diff --git a/gettext-tools/gnulib-lib/libxml/xmlmodule.in.h b/gettext-tools/gnulib-lib/libxml/xmlmodule.in.h new file mode 100644 index 0000000..8f4a560 --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/xmlmodule.in.h @@ -0,0 +1,57 @@ +/* + * Summary: dynamic module loading + * Description: basic API for dynamic module loading, used by + * libexslt added in 2.6.17 + * + * Copy: See Copyright for the status of this software. + * + * Author: Joel W. Reed + */ + +#ifndef __XML_MODULE_H__ +#define __XML_MODULE_H__ + +#include + +#ifdef LIBXML_MODULES_ENABLED + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * xmlModulePtr: + * + * A handle to a dynamically loaded module + */ +typedef struct _xmlModule xmlModule; +typedef xmlModule *xmlModulePtr; + +/** + * xmlModuleOption: + * + * enumeration of options that can be passed down to xmlModuleOpen() + */ +typedef enum { + XML_MODULE_LAZY = 1, /* lazy binding */ + XML_MODULE_LOCAL= 2 /* local binding */ +} xmlModuleOption; + +XMLPUBFUN xmlModulePtr XMLCALL xmlModuleOpen (const char *filename, + int options); + +XMLPUBFUN int XMLCALL xmlModuleSymbol (xmlModulePtr module, + const char* name, + void **result); + +XMLPUBFUN int XMLCALL xmlModuleClose (xmlModulePtr module); + +XMLPUBFUN int XMLCALL xmlModuleFree (xmlModulePtr module); + +#ifdef __cplusplus +} +#endif + +#endif /* LIBXML_MODULES_ENABLED */ + +#endif /*__XML_MODULE_H__ */ diff --git a/gettext-tools/gnulib-lib/libxml/xmlreader.c b/gettext-tools/gnulib-lib/libxml/xmlreader.c new file mode 100644 index 0000000..c8bcf7b --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/xmlreader.c @@ -0,0 +1,5659 @@ +/* + * xmlreader.c: implements the xmlTextReader streaming node API + * + * NOTE: + * XmlTextReader.Normalization Property won't be supported, since + * it makes the parser non compliant to the XML recommendation + * + * See Copyright for the status of this software. + * + * daniel@veillard.com + */ + +/* + * TODOs: + * - XML Schemas validation + */ +#define IN_LIBXML +#include "libxml.h" + +#ifdef LIBXML_READER_ENABLED +#include /* for memset() only ! */ +#include + +#ifdef HAVE_CTYPE_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif + +#include +#include +#include +#include +#ifdef LIBXML_SCHEMAS_ENABLED +#include +#include +#endif +#include +#ifdef LIBXML_XINCLUDE_ENABLED +#include +#endif +#ifdef LIBXML_PATTERN_ENABLED +#include +#endif + +/* #define DEBUG_CALLBACKS */ +/* #define DEBUG_READER */ + +/** + * TODO: + * + * macro to flag unimplemented blocks + */ +#define TODO \ + xmlGenericError(xmlGenericErrorContext, \ + "Unimplemented block at %s:%d\n", \ + __FILE__, __LINE__); + +#ifdef DEBUG_READER +#define DUMP_READER xmlTextReaderDebug(reader); +#else +#define DUMP_READER +#endif + +#define CHUNK_SIZE 512 +/************************************************************************ + * * + * The parser: maps the Text Reader API on top of the existing * + * parsing routines building a tree * + * * + ************************************************************************/ + +#define XML_TEXTREADER_INPUT 1 +#define XML_TEXTREADER_CTXT 2 + +typedef enum { + XML_TEXTREADER_NONE = -1, + XML_TEXTREADER_START= 0, + XML_TEXTREADER_ELEMENT= 1, + XML_TEXTREADER_END= 2, + XML_TEXTREADER_EMPTY= 3, + XML_TEXTREADER_BACKTRACK= 4, + XML_TEXTREADER_DONE= 5, + XML_TEXTREADER_ERROR= 6 +} xmlTextReaderState; + +typedef enum { + XML_TEXTREADER_NOT_VALIDATE = 0, + XML_TEXTREADER_VALIDATE_DTD = 1, + XML_TEXTREADER_VALIDATE_RNG = 2, + XML_TEXTREADER_VALIDATE_XSD = 4 +} xmlTextReaderValidate; + +struct _xmlTextReader { + int mode; /* the parsing mode */ + xmlDocPtr doc; /* when walking an existing doc */ + xmlTextReaderValidate validate;/* is there any validation */ + int allocs; /* what structure were deallocated */ + xmlTextReaderState state; + xmlParserCtxtPtr ctxt; /* the parser context */ + xmlSAXHandlerPtr sax; /* the parser SAX callbacks */ + xmlParserInputBufferPtr input; /* the input */ + startElementSAXFunc startElement;/* initial SAX callbacks */ + endElementSAXFunc endElement; /* idem */ + startElementNsSAX2Func startElementNs;/* idem */ + endElementNsSAX2Func endElementNs; /* idem */ + charactersSAXFunc characters; + cdataBlockSAXFunc cdataBlock; + unsigned int base; /* base of the segment in the input */ + unsigned int cur; /* current position in the input */ + xmlNodePtr node; /* current node */ + xmlNodePtr curnode;/* current attribute node */ + int depth; /* depth of the current node */ + xmlNodePtr faketext;/* fake xmlNs chld */ + int preserve;/* preserve the resulting document */ + xmlBufferPtr buffer; /* used to return const xmlChar * */ + xmlDictPtr dict; /* the context dictionnary */ + + /* entity stack when traversing entities content */ + xmlNodePtr ent; /* Current Entity Ref Node */ + int entNr; /* Depth of the entities stack */ + int entMax; /* Max depth of the entities stack */ + xmlNodePtr *entTab; /* array of entities */ + + /* error handling */ + xmlTextReaderErrorFunc errorFunc; /* callback function */ + void *errorFuncArg; /* callback function user argument */ + +#ifdef LIBXML_SCHEMAS_ENABLED + /* Handling of RelaxNG validation */ + xmlRelaxNGPtr rngSchemas; /* The Relax NG schemas */ + xmlRelaxNGValidCtxtPtr rngValidCtxt;/* The Relax NG validation context */ + int rngValidErrors;/* The number of errors detected */ + xmlNodePtr rngFullNode; /* the node if RNG not progressive */ + /* Handling of Schemas validation */ + xmlSchemaPtr xsdSchemas; /* The Schemas schemas */ + xmlSchemaValidCtxtPtr xsdValidCtxt;/* The Schemas validation context */ + int xsdPreserveCtxt; /* 1 if the context was provided by the user */ + int xsdValidErrors;/* The number of errors detected */ + xmlSchemaSAXPlugPtr xsdPlug; /* the schemas plug in SAX pipeline */ +#endif +#ifdef LIBXML_XINCLUDE_ENABLED + /* Handling of XInclude processing */ + int xinclude; /* is xinclude asked for */ + const xmlChar * xinclude_name; /* the xinclude name from dict */ + xmlXIncludeCtxtPtr xincctxt; /* the xinclude context */ + int in_xinclude; /* counts for xinclude */ +#endif +#ifdef LIBXML_PATTERN_ENABLED + int patternNr; /* number of preserve patterns */ + int patternMax; /* max preserve patterns */ + xmlPatternPtr *patternTab; /* array of preserve patterns */ +#endif + int preserves; /* level of preserves */ + int parserFlags; /* the set of options set */ + /* Structured error handling */ + xmlStructuredErrorFunc sErrorFunc; /* callback function */ +}; + +#define NODE_IS_EMPTY 0x1 +#define NODE_IS_PRESERVED 0x2 +#define NODE_IS_SPRESERVED 0x4 + +/** + * CONSTSTR: + * + * Macro used to return an interned string + */ +#define CONSTSTR(str) xmlDictLookup(reader->dict, (str), -1) +#define CONSTQSTR(p, str) xmlDictQLookup(reader->dict, (p), (str)) + +static int xmlTextReaderReadTree(xmlTextReaderPtr reader); +static int xmlTextReaderNextTree(xmlTextReaderPtr reader); + +/************************************************************************ + * * + * Our own version of the freeing routines as we recycle nodes * + * * + ************************************************************************/ +/** + * DICT_FREE: + * @str: a string + * + * Free a string if it is not owned by the "dict" dictionnary in the + * current scope + */ +#define DICT_FREE(str) \ + if ((str) && ((!dict) || \ + (xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \ + xmlFree((char *)(str)); + +static void xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur); +static void xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur); + +/** + * xmlFreeID: + * @not: A id + * + * Deallocate the memory used by an id definition + */ +static void +xmlFreeID(xmlIDPtr id) { + xmlDictPtr dict = NULL; + + if (id == NULL) return; + + if (id->doc != NULL) + dict = id->doc->dict; + + if (id->value != NULL) + DICT_FREE(id->value) + xmlFree(id); +} + +/** + * xmlTextReaderRemoveID: + * @doc: the document + * @attr: the attribute + * + * Remove the given attribute from the ID table maintained internally. + * + * Returns -1 if the lookup failed and 0 otherwise + */ +static int +xmlTextReaderRemoveID(xmlDocPtr doc, xmlAttrPtr attr) { + xmlIDTablePtr table; + xmlIDPtr id; + xmlChar *ID; + + if (doc == NULL) return(-1); + if (attr == NULL) return(-1); + table = (xmlIDTablePtr) doc->ids; + if (table == NULL) + return(-1); + + if (attr == NULL) + return(-1); + ID = xmlNodeListGetString(doc, attr->children, 1); + if (ID == NULL) + return(-1); + id = xmlHashLookup(table, ID); + xmlFree(ID); + if (id == NULL || id->attr != attr) { + return(-1); + } + id->name = attr->name; + id->attr = NULL; + return(0); +} + +/** + * xmlTextReaderFreeProp: + * @reader: the xmlTextReaderPtr used + * @cur: the node + * + * Free a node. + */ +static void +xmlTextReaderFreeProp(xmlTextReaderPtr reader, xmlAttrPtr cur) { + xmlDictPtr dict; + + dict = reader->ctxt->dict; + if (cur == NULL) return; + + if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue)) + xmlDeregisterNodeDefaultValue((xmlNodePtr) cur); + + /* Check for ID removal -> leading to invalid references ! */ + if ((cur->parent != NULL) && (cur->parent->doc != NULL) && + ((cur->parent->doc->intSubset != NULL) || + (cur->parent->doc->extSubset != NULL))) { + if (xmlIsID(cur->parent->doc, cur->parent, cur)) + xmlTextReaderRemoveID(cur->parent->doc, cur); + } + if (cur->children != NULL) + xmlTextReaderFreeNodeList(reader, cur->children); + + DICT_FREE(cur->name); + if ((reader != NULL) && (reader->ctxt != NULL) && + (reader->ctxt->freeAttrsNr < 100)) { + cur->next = reader->ctxt->freeAttrs; + reader->ctxt->freeAttrs = cur; + reader->ctxt->freeAttrsNr++; + } else { + xmlFree(cur); + } +} + +/** + * xmlTextReaderFreePropList: + * @reader: the xmlTextReaderPtr used + * @cur: the first property in the list + * + * Free a property and all its siblings, all the children are freed too. + */ +static void +xmlTextReaderFreePropList(xmlTextReaderPtr reader, xmlAttrPtr cur) { + xmlAttrPtr next; + if (cur == NULL) return; + while (cur != NULL) { + next = cur->next; + xmlTextReaderFreeProp(reader, cur); + cur = next; + } +} + +/** + * xmlTextReaderFreeNodeList: + * @reader: the xmlTextReaderPtr used + * @cur: the first node in the list + * + * Free a node and all its siblings, this is a recursive behaviour, all + * the children are freed too. + */ +static void +xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur) { + xmlNodePtr next; + xmlDictPtr dict; + + dict = reader->ctxt->dict; + if (cur == NULL) return; + if (cur->type == XML_NAMESPACE_DECL) { + xmlFreeNsList((xmlNsPtr) cur); + return; + } + if ((cur->type == XML_DOCUMENT_NODE) || + (cur->type == XML_HTML_DOCUMENT_NODE)) { + xmlFreeDoc((xmlDocPtr) cur); + return; + } + while (cur != NULL) { + next = cur->next; + /* unroll to speed up freeing the document */ + if (cur->type != XML_DTD_NODE) { + + if ((cur->children != NULL) && + (cur->type != XML_ENTITY_REF_NODE)) { + if (cur->children->parent == cur) + xmlTextReaderFreeNodeList(reader, cur->children); + cur->children = NULL; + } + + if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue)) + xmlDeregisterNodeDefaultValue(cur); + + if (((cur->type == XML_ELEMENT_NODE) || + (cur->type == XML_XINCLUDE_START) || + (cur->type == XML_XINCLUDE_END)) && + (cur->properties != NULL)) + xmlTextReaderFreePropList(reader, cur->properties); + if ((cur->content != (xmlChar *) &(cur->properties)) && + (cur->type != XML_ELEMENT_NODE) && + (cur->type != XML_XINCLUDE_START) && + (cur->type != XML_XINCLUDE_END) && + (cur->type != XML_ENTITY_REF_NODE)) { + DICT_FREE(cur->content); + } + if (((cur->type == XML_ELEMENT_NODE) || + (cur->type == XML_XINCLUDE_START) || + (cur->type == XML_XINCLUDE_END)) && + (cur->nsDef != NULL)) + xmlFreeNsList(cur->nsDef); + + /* + * we don't free element names here they are interned now + */ + if ((cur->type != XML_TEXT_NODE) && + (cur->type != XML_COMMENT_NODE)) + DICT_FREE(cur->name); + if (((cur->type == XML_ELEMENT_NODE) || + (cur->type == XML_TEXT_NODE)) && + (reader != NULL) && (reader->ctxt != NULL) && + (reader->ctxt->freeElemsNr < 100)) { + cur->next = reader->ctxt->freeElems; + reader->ctxt->freeElems = cur; + reader->ctxt->freeElemsNr++; + } else { + xmlFree(cur); + } + } + cur = next; + } +} + +/** + * xmlTextReaderFreeNode: + * @reader: the xmlTextReaderPtr used + * @cur: the node + * + * Free a node, this is a recursive behaviour, all the children are freed too. + * This doesn't unlink the child from the list, use xmlUnlinkNode() first. + */ +static void +xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur) { + xmlDictPtr dict; + + dict = reader->ctxt->dict; + if (cur->type == XML_DTD_NODE) { + xmlFreeDtd((xmlDtdPtr) cur); + return; + } + if (cur->type == XML_NAMESPACE_DECL) { + xmlFreeNs((xmlNsPtr) cur); + return; + } + if (cur->type == XML_ATTRIBUTE_NODE) { + xmlTextReaderFreeProp(reader, (xmlAttrPtr) cur); + return; + } + + if ((cur->children != NULL) && + (cur->type != XML_ENTITY_REF_NODE)) { + if (cur->children->parent == cur) + xmlTextReaderFreeNodeList(reader, cur->children); + cur->children = NULL; + } + + if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue)) + xmlDeregisterNodeDefaultValue(cur); + + if (((cur->type == XML_ELEMENT_NODE) || + (cur->type == XML_XINCLUDE_START) || + (cur->type == XML_XINCLUDE_END)) && + (cur->properties != NULL)) + xmlTextReaderFreePropList(reader, cur->properties); + if ((cur->content != (xmlChar *) &(cur->properties)) && + (cur->type != XML_ELEMENT_NODE) && + (cur->type != XML_XINCLUDE_START) && + (cur->type != XML_XINCLUDE_END) && + (cur->type != XML_ENTITY_REF_NODE)) { + DICT_FREE(cur->content); + } + if (((cur->type == XML_ELEMENT_NODE) || + (cur->type == XML_XINCLUDE_START) || + (cur->type == XML_XINCLUDE_END)) && + (cur->nsDef != NULL)) + xmlFreeNsList(cur->nsDef); + + /* + * we don't free names here they are interned now + */ + if ((cur->type != XML_TEXT_NODE) && + (cur->type != XML_COMMENT_NODE)) + DICT_FREE(cur->name); + + if (((cur->type == XML_ELEMENT_NODE) || + (cur->type == XML_TEXT_NODE)) && + (reader != NULL) && (reader->ctxt != NULL) && + (reader->ctxt->freeElemsNr < 100)) { + cur->next = reader->ctxt->freeElems; + reader->ctxt->freeElems = cur; + reader->ctxt->freeElemsNr++; + } else { + xmlFree(cur); + } +} + +/** + * xmlTextReaderFreeIDTable: + * @table: An id table + * + * Deallocate the memory used by an ID hash table. + */ +static void +xmlTextReaderFreeIDTable(xmlIDTablePtr table) { + xmlHashFree(table, (xmlHashDeallocator) xmlFreeID); +} + +/** + * xmlTextReaderFreeDoc: + * @reader: the xmlTextReaderPtr used + * @cur: pointer to the document + * + * Free up all the structures used by a document, tree included. + */ +static void +xmlTextReaderFreeDoc(xmlTextReaderPtr reader, xmlDocPtr cur) { + xmlDtdPtr extSubset, intSubset; + + if (cur == NULL) return; + + if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue)) + xmlDeregisterNodeDefaultValue((xmlNodePtr) cur); + + /* + * Do this before freeing the children list to avoid ID lookups + */ + if (cur->ids != NULL) xmlTextReaderFreeIDTable((xmlIDTablePtr) cur->ids); + cur->ids = NULL; + if (cur->refs != NULL) xmlFreeRefTable((xmlRefTablePtr) cur->refs); + cur->refs = NULL; + extSubset = cur->extSubset; + intSubset = cur->intSubset; + if (intSubset == extSubset) + extSubset = NULL; + if (extSubset != NULL) { + xmlUnlinkNode((xmlNodePtr) cur->extSubset); + cur->extSubset = NULL; + xmlFreeDtd(extSubset); + } + if (intSubset != NULL) { + xmlUnlinkNode((xmlNodePtr) cur->intSubset); + cur->intSubset = NULL; + xmlFreeDtd(intSubset); + } + + if (cur->children != NULL) xmlTextReaderFreeNodeList(reader, cur->children); + + if (cur->version != NULL) xmlFree((char *) cur->version); + if (cur->name != NULL) xmlFree((char *) cur->name); + if (cur->encoding != NULL) xmlFree((char *) cur->encoding); + if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs); + if (cur->URL != NULL) xmlFree((char *) cur->URL); + if (cur->dict != NULL) xmlDictFree(cur->dict); + + xmlFree(cur); +} + +/************************************************************************ + * * + * The reader core parser * + * * + ************************************************************************/ +#ifdef DEBUG_READER +static void +xmlTextReaderDebug(xmlTextReaderPtr reader) { + if ((reader == NULL) || (reader->ctxt == NULL)) { + fprintf(stderr, "xmlTextReader NULL\n"); + return; + } + fprintf(stderr, "xmlTextReader: state %d depth %d ", + reader->state, reader->depth); + if (reader->node == NULL) { + fprintf(stderr, "node = NULL\n"); + } else { + fprintf(stderr, "node %s\n", reader->node->name); + } + fprintf(stderr, " input: base %d, cur %d, depth %d: ", + reader->base, reader->cur, reader->ctxt->nodeNr); + if (reader->input->buffer == NULL) { + fprintf(stderr, "buffer is NULL\n"); + } else { +#ifdef LIBXML_DEBUG_ENABLED + xmlDebugDumpString(stderr, + &reader->input->buffer->content[reader->cur]); +#endif + fprintf(stderr, "\n"); + } +} +#endif + +/** + * xmlTextReaderEntPush: + * @reader: the xmlTextReaderPtr used + * @value: the entity reference node + * + * Pushes a new entity reference node on top of the entities stack + * + * Returns 0 in case of error, the index in the stack otherwise + */ +static int +xmlTextReaderEntPush(xmlTextReaderPtr reader, xmlNodePtr value) +{ + if (reader->entMax <= 0) { + reader->entMax = 10; + reader->entTab = (xmlNodePtr *) xmlMalloc(reader->entMax * + sizeof(reader->entTab[0])); + if (reader->entTab == NULL) { + xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n"); + return (0); + } + } + if (reader->entNr >= reader->entMax) { + reader->entMax *= 2; + reader->entTab = + (xmlNodePtr *) xmlRealloc(reader->entTab, + reader->entMax * + sizeof(reader->entTab[0])); + if (reader->entTab == NULL) { + xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n"); + return (0); + } + } + reader->entTab[reader->entNr] = value; + reader->ent = value; + return (reader->entNr++); +} + +/** + * xmlTextReaderEntPop: + * @reader: the xmlTextReaderPtr used + * + * Pops the top element entity from the entities stack + * + * Returns the entity just removed + */ +static xmlNodePtr +xmlTextReaderEntPop(xmlTextReaderPtr reader) +{ + xmlNodePtr ret; + + if (reader->entNr <= 0) + return (NULL); + reader->entNr--; + if (reader->entNr > 0) + reader->ent = reader->entTab[reader->entNr - 1]; + else + reader->ent = NULL; + ret = reader->entTab[reader->entNr]; + reader->entTab[reader->entNr] = NULL; + return (ret); +} + +/** + * xmlTextReaderStartElement: + * @ctx: the user data (XML parser context) + * @fullname: The element name, including namespace prefix + * @atts: An array of name/value attributes pairs, NULL terminated + * + * called when an opening tag has been processed. + */ +static void +xmlTextReaderStartElement(void *ctx, const xmlChar *fullname, + const xmlChar **atts) { + xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; + xmlTextReaderPtr reader = ctxt->_private; + +#ifdef DEBUG_CALLBACKS + printf("xmlTextReaderStartElement(%s)\n", fullname); +#endif + if ((reader != NULL) && (reader->startElement != NULL)) { + reader->startElement(ctx, fullname, atts); + if ((ctxt->node != NULL) && (ctxt->input != NULL) && + (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') && + (ctxt->input->cur[1] == '>')) + ctxt->node->extra = NODE_IS_EMPTY; + } + if (reader != NULL) + reader->state = XML_TEXTREADER_ELEMENT; +} + +/** + * xmlTextReaderEndElement: + * @ctx: the user data (XML parser context) + * @fullname: The element name, including namespace prefix + * + * called when an ending tag has been processed. + */ +static void +xmlTextReaderEndElement(void *ctx, const xmlChar *fullname) { + xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; + xmlTextReaderPtr reader = ctxt->_private; + +#ifdef DEBUG_CALLBACKS + printf("xmlTextReaderEndElement(%s)\n", fullname); +#endif + if ((reader != NULL) && (reader->endElement != NULL)) { + reader->endElement(ctx, fullname); + } +} + +/** + * xmlTextReaderStartElementNs: + * @ctx: the user data (XML parser context) + * @localname: the local name of the element + * @prefix: the element namespace prefix if available + * @URI: the element namespace name if available + * @nb_namespaces: number of namespace definitions on that node + * @namespaces: pointer to the array of prefix/URI pairs namespace definitions + * @nb_attributes: the number of attributes on that node + * nb_defaulted: the number of defaulted attributes. + * @attributes: pointer to the array of (localname/prefix/URI/value/end) + * attribute values. + * + * called when an opening tag has been processed. + */ +static void +xmlTextReaderStartElementNs(void *ctx, + const xmlChar *localname, + const xmlChar *prefix, + const xmlChar *URI, + int nb_namespaces, + const xmlChar **namespaces, + int nb_attributes, + int nb_defaulted, + const xmlChar **attributes) +{ + xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; + xmlTextReaderPtr reader = ctxt->_private; + +#ifdef DEBUG_CALLBACKS + printf("xmlTextReaderStartElementNs(%s)\n", localname); +#endif + if ((reader != NULL) && (reader->startElementNs != NULL)) { + reader->startElementNs(ctx, localname, prefix, URI, nb_namespaces, + namespaces, nb_attributes, nb_defaulted, + attributes); + if ((ctxt->node != NULL) && (ctxt->input != NULL) && + (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') && + (ctxt->input->cur[1] == '>')) + ctxt->node->extra = NODE_IS_EMPTY; + } + if (reader != NULL) + reader->state = XML_TEXTREADER_ELEMENT; +} + +/** + * xmlTextReaderEndElementNs: + * @ctx: the user data (XML parser context) + * @localname: the local name of the element + * @prefix: the element namespace prefix if available + * @URI: the element namespace name if available + * + * called when an ending tag has been processed. + */ +static void +xmlTextReaderEndElementNs(void *ctx, + const xmlChar * localname, + const xmlChar * prefix, + const xmlChar * URI) +{ + xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; + xmlTextReaderPtr reader = ctxt->_private; + +#ifdef DEBUG_CALLBACKS + printf("xmlTextReaderEndElementNs(%s)\n", localname); +#endif + if ((reader != NULL) && (reader->endElementNs != NULL)) { + reader->endElementNs(ctx, localname, prefix, URI); + } +} + + +/** + * xmlTextReaderCharacters: + * @ctx: the user data (XML parser context) + * @ch: a xmlChar string + * @len: the number of xmlChar + * + * receiving some chars from the parser. + */ +static void +xmlTextReaderCharacters(void *ctx, const xmlChar *ch, int len) +{ + xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; + xmlTextReaderPtr reader = ctxt->_private; + +#ifdef DEBUG_CALLBACKS + printf("xmlTextReaderCharacters()\n"); +#endif + if ((reader != NULL) && (reader->characters != NULL)) { + reader->characters(ctx, ch, len); + } +} + +/** + * xmlTextReaderCDataBlock: + * @ctx: the user data (XML parser context) + * @value: The pcdata content + * @len: the block length + * + * called when a pcdata block has been parsed + */ +static void +xmlTextReaderCDataBlock(void *ctx, const xmlChar *ch, int len) +{ + xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; + xmlTextReaderPtr reader = ctxt->_private; + +#ifdef DEBUG_CALLBACKS + printf("xmlTextReaderCDataBlock()\n"); +#endif + if ((reader != NULL) && (reader->cdataBlock != NULL)) { + reader->cdataBlock(ctx, ch, len); + } +} + +/** + * xmlTextReaderPushData: + * @reader: the xmlTextReaderPtr used + * + * Push data down the progressive parser until a significant callback + * got raised. + * + * Returns -1 in case of failure, 0 otherwise + */ +static int +xmlTextReaderPushData(xmlTextReaderPtr reader) { + xmlBufferPtr inbuf; + int val, s; + xmlTextReaderState oldstate; + + if ((reader->input == NULL) || (reader->input->buffer == NULL)) + return(-1); + + oldstate = reader->state; + reader->state = XML_TEXTREADER_NONE; + inbuf = reader->input->buffer; + + while (reader->state == XML_TEXTREADER_NONE) { + if (inbuf->use < reader->cur + CHUNK_SIZE) { + /* + * Refill the buffer unless we are at the end of the stream + */ + if (reader->mode != XML_TEXTREADER_MODE_EOF) { + val = xmlParserInputBufferRead(reader->input, 4096); + if ((val == 0) && + (inbuf->alloc == XML_BUFFER_ALLOC_IMMUTABLE)) { + if (inbuf->use == reader->cur) { + reader->mode = XML_TEXTREADER_MODE_EOF; + reader->state = oldstate; + } + } else if (val < 0) { + reader->mode = XML_TEXTREADER_MODE_EOF; + reader->state = oldstate; + if ((oldstate != XML_TEXTREADER_START) || + (reader->ctxt->myDoc != NULL)) + return(val); + } else if (val == 0) { + /* mark the end of the stream and process the remains */ + reader->mode = XML_TEXTREADER_MODE_EOF; + break; + } + + } else + break; + } + /* + * parse by block of CHUNK_SIZE bytes, various tests show that + * it's the best tradeoff at least on a 1.2GH Duron + */ + if (inbuf->use >= reader->cur + CHUNK_SIZE) { + val = xmlParseChunk(reader->ctxt, + (const char *) &inbuf->content[reader->cur], + CHUNK_SIZE, 0); + reader->cur += CHUNK_SIZE; + if ((val != 0) || (reader->ctxt->wellFormed == 0)) + return(-1); + } else { + s = inbuf->use - reader->cur; + val = xmlParseChunk(reader->ctxt, + (const char *) &inbuf->content[reader->cur], + s, 0); + reader->cur += s; + if ((val != 0) || (reader->ctxt->wellFormed == 0)) + return(-1); + break; + } + } + + /* + * Discard the consumed input when needed and possible + */ + if (reader->mode == XML_TEXTREADER_MODE_INTERACTIVE) { + if (inbuf->alloc != XML_BUFFER_ALLOC_IMMUTABLE) { + if ((reader->cur >= 4096) && + (inbuf->use - reader->cur <= CHUNK_SIZE)) { + val = xmlBufferShrink(inbuf, reader->cur); + if (val >= 0) { + reader->cur -= val; + } + } + } + } + + /* + * At the end of the stream signal that the work is done to the Push + * parser. + */ + else if (reader->mode == XML_TEXTREADER_MODE_EOF) { + if (reader->mode != XML_TEXTREADER_DONE) { + s = inbuf->use - reader->cur; + val = xmlParseChunk(reader->ctxt, + (const char *) &inbuf->content[reader->cur], + s, 1); + reader->cur = inbuf->use; + reader->mode = XML_TEXTREADER_DONE; + if ((val != 0) || (reader->ctxt->wellFormed == 0)) + return(-1); + } + } + reader->state = oldstate; + return(0); +} + +#ifdef LIBXML_REGEXP_ENABLED +/** + * xmlTextReaderValidatePush: + * @reader: the xmlTextReaderPtr used + * + * Push the current node for validation + */ +static void +xmlTextReaderValidatePush(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) { + xmlNodePtr node = reader->node; + +#ifdef LIBXML_VALID_ENABLED + if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) && + (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) { + if ((node->ns == NULL) || (node->ns->prefix == NULL)) { + reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt, + reader->ctxt->myDoc, node, node->name); + } else { + /* TODO use the BuildQName interface */ + xmlChar *qname; + + qname = xmlStrdup(node->ns->prefix); + qname = xmlStrcat(qname, BAD_CAST ":"); + qname = xmlStrcat(qname, node->name); + reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt, + reader->ctxt->myDoc, node, qname); + if (qname != NULL) + xmlFree(qname); + } + } +#endif /* LIBXML_VALID_ENABLED */ +#ifdef LIBXML_SCHEMAS_ENABLED + if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) && + (reader->rngValidCtxt != NULL)) { + int ret; + + if (reader->rngFullNode != NULL) return; + ret = xmlRelaxNGValidatePushElement(reader->rngValidCtxt, + reader->ctxt->myDoc, + node); + if (ret == 0) { + /* + * this element requires a full tree + */ + node = xmlTextReaderExpand(reader); + if (node == NULL) { +printf("Expand failed !\n"); + ret = -1; + } else { + ret = xmlRelaxNGValidateFullElement(reader->rngValidCtxt, + reader->ctxt->myDoc, + node); + reader->rngFullNode = node; + } + } + if (ret != 1) + reader->rngValidErrors++; + } +#endif +} + +/** + * xmlTextReaderValidateCData: + * @reader: the xmlTextReaderPtr used + * @data: pointer to the CData + * @len: lenght of the CData block in bytes. + * + * Push some CData for validation + */ +static void +xmlTextReaderValidateCData(xmlTextReaderPtr reader, + const xmlChar *data, int len) { +#ifdef LIBXML_VALID_ENABLED + if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) && + (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) { + reader->ctxt->valid &= xmlValidatePushCData(&reader->ctxt->vctxt, + data, len); + } +#endif /* LIBXML_VALID_ENABLED */ +#ifdef LIBXML_SCHEMAS_ENABLED + if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) && + (reader->rngValidCtxt != NULL)) { + int ret; + + if (reader->rngFullNode != NULL) return; + ret = xmlRelaxNGValidatePushCData(reader->rngValidCtxt, data, len); + if (ret != 1) + reader->rngValidErrors++; + } +#endif +} + +/** + * xmlTextReaderValidatePop: + * @reader: the xmlTextReaderPtr used + * + * Pop the current node from validation + */ +static void +xmlTextReaderValidatePop(xmlTextReaderPtr reader) { + xmlNodePtr node = reader->node; + +#ifdef LIBXML_VALID_ENABLED + if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) && + (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) { + if ((node->ns == NULL) || (node->ns->prefix == NULL)) { + reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt, + reader->ctxt->myDoc, node, node->name); + } else { + /* TODO use the BuildQName interface */ + xmlChar *qname; + + qname = xmlStrdup(node->ns->prefix); + qname = xmlStrcat(qname, BAD_CAST ":"); + qname = xmlStrcat(qname, node->name); + reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt, + reader->ctxt->myDoc, node, qname); + if (qname != NULL) + xmlFree(qname); + } + } +#endif /* LIBXML_VALID_ENABLED */ +#ifdef LIBXML_SCHEMAS_ENABLED + if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) && + (reader->rngValidCtxt != NULL)) { + int ret; + + if (reader->rngFullNode != NULL) { + if (node == reader->rngFullNode) + reader->rngFullNode = NULL; + return; + } + ret = xmlRelaxNGValidatePopElement(reader->rngValidCtxt, + reader->ctxt->myDoc, + node); + if (ret != 1) + reader->rngValidErrors++; + } +#endif +} + +/** + * xmlTextReaderValidateEntity: + * @reader: the xmlTextReaderPtr used + * + * Handle the validation when an entity reference is encountered and + * entity substitution is not activated. As a result the parser interface + * must walk through the entity and do the validation calls + */ +static void +xmlTextReaderValidateEntity(xmlTextReaderPtr reader) { + xmlNodePtr oldnode = reader->node; + xmlNodePtr node = reader->node; + xmlParserCtxtPtr ctxt = reader->ctxt; + + do { + if (node->type == XML_ENTITY_REF_NODE) { + /* + * Case where the underlying tree is not availble, lookup the entity + * and walk it. + */ + if ((node->children == NULL) && (ctxt->sax != NULL) && + (ctxt->sax->getEntity != NULL)) { + node->children = (xmlNodePtr) + ctxt->sax->getEntity(ctxt, node->name); + } + + if ((node->children != NULL) && + (node->children->type == XML_ENTITY_DECL) && + (node->children->children != NULL)) { + xmlTextReaderEntPush(reader, node); + node = node->children->children; + continue; + } else { + /* + * The error has probably be raised already. + */ + if (node == oldnode) + break; + node = node->next; + } +#ifdef LIBXML_REGEXP_ENABLED + } else if (node->type == XML_ELEMENT_NODE) { + reader->node = node; + xmlTextReaderValidatePush(reader); + } else if ((node->type == XML_TEXT_NODE) || + (node->type == XML_CDATA_SECTION_NODE)) { + xmlTextReaderValidateCData(reader, node->content, + xmlStrlen(node->content)); +#endif + } + + /* + * go to next node + */ + if (node->children != NULL) { + node = node->children; + continue; + } else if (node->type == XML_ELEMENT_NODE) { + xmlTextReaderValidatePop(reader); + } + if (node->next != NULL) { + node = node->next; + continue; + } + do { + node = node->parent; + if (node->type == XML_ELEMENT_NODE) { + xmlNodePtr tmp; + if (reader->entNr == 0) { + while ((tmp = node->last) != NULL) { + if ((tmp->extra & NODE_IS_PRESERVED) == 0) { + xmlUnlinkNode(tmp); + xmlTextReaderFreeNode(reader, tmp); + } else + break; + } + } + reader->node = node; + xmlTextReaderValidatePop(reader); + } + if ((node->type == XML_ENTITY_DECL) && + (reader->ent != NULL) && (reader->ent->children == node)) { + node = xmlTextReaderEntPop(reader); + } + if (node == oldnode) + break; + if (node->next != NULL) { + node = node->next; + break; + } + } while ((node != NULL) && (node != oldnode)); + } while ((node != NULL) && (node != oldnode)); + reader->node = oldnode; +} +#endif /* LIBXML_REGEXP_ENABLED */ + + +/** + * xmlTextReaderGetSuccessor: + * @cur: the current node + * + * Get the successor of a node if available. + * + * Returns the successor node or NULL + */ +static xmlNodePtr +xmlTextReaderGetSuccessor(xmlNodePtr cur) { + if (cur == NULL) return(NULL) ; /* ERROR */ + if (cur->next != NULL) return(cur->next) ; + do { + cur = cur->parent; + if (cur == NULL) break; + if (cur->next != NULL) return(cur->next); + } while (cur != NULL); + return(cur); +} + +/** + * xmlTextReaderDoExpand: + * @reader: the xmlTextReaderPtr used + * + * Makes sure that the current node is fully read as well as all its + * descendant. It means the full DOM subtree must be available at the + * end of the call. + * + * Returns 1 if the node was expanded successfully, 0 if there is no more + * nodes to read, or -1 in case of error + */ +static int +xmlTextReaderDoExpand(xmlTextReaderPtr reader) { + int val; + + if ((reader == NULL) || (reader->node == NULL) || (reader->ctxt == NULL)) + return(-1); + do { + if (reader->ctxt->instate == XML_PARSER_EOF) return(1); + + if (xmlTextReaderGetSuccessor(reader->node) != NULL) + return(1); + if (reader->ctxt->nodeNr < reader->depth) + return(1); + if (reader->mode == XML_TEXTREADER_MODE_EOF) + return(1); + val = xmlTextReaderPushData(reader); + if (val < 0) + return(-1); + } while(reader->mode != XML_TEXTREADER_MODE_EOF); + return(1); +} + +/** + * xmlTextReaderCollectSiblings: + * @node: the first child + * + * Traverse depth-first through all sibling nodes and their children + * nodes and concatenate their content. This is an auxiliary function + * to xmlTextReaderReadString. + * + * Returns a string containing the content, or NULL in case of error. + */ +static xmlChar * +xmlTextReaderCollectSiblings(xmlNodePtr node) +{ + xmlBufferPtr buffer; + xmlChar *ret; + + buffer = xmlBufferCreate(); + if (buffer == NULL) + return NULL; + + for ( ; node != NULL; node = node->next) { + switch (node->type) { + case XML_TEXT_NODE: + case XML_CDATA_SECTION_NODE: + xmlBufferCat(buffer, node->content); + break; + case XML_ELEMENT_NODE: { + xmlChar *tmp; + + tmp = xmlTextReaderCollectSiblings(node->children); + xmlBufferCat(buffer, tmp); + xmlFree(tmp); + break; + } + default: + break; + } + } + ret = buffer->content; + buffer->content = NULL; + xmlBufferFree(buffer); + return(ret); +} + +/** + * xmlTextReaderRead: + * @reader: the xmlTextReaderPtr used + * + * Moves the position of the current instance to the next node in + * the stream, exposing its properties. + * + * Returns 1 if the node was read successfully, 0 if there is no more + * nodes to read, or -1 in case of error + */ +int +xmlTextReaderRead(xmlTextReaderPtr reader) { + int val, olddepth = 0; + xmlTextReaderState oldstate = XML_TEXTREADER_START; + xmlNodePtr oldnode = NULL; + + + if (reader == NULL) + return(-1); + reader->curnode = NULL; + if (reader->doc != NULL) + return(xmlTextReaderReadTree(reader)); + if (reader->ctxt == NULL) + return(-1); + if (reader->ctxt->wellFormed != 1) + return(-1); + +#ifdef DEBUG_READER + fprintf(stderr, "\nREAD "); + DUMP_READER +#endif + if (reader->mode == XML_TEXTREADER_MODE_INITIAL) { + reader->mode = XML_TEXTREADER_MODE_INTERACTIVE; + /* + * Initial state + */ + do { + val = xmlTextReaderPushData(reader); + if (val < 0) + return(-1); + } while ((reader->ctxt->node == NULL) && + ((reader->mode != XML_TEXTREADER_MODE_EOF) && + (reader->mode != XML_TEXTREADER_DONE))); + if (reader->ctxt->node == NULL) { + if (reader->ctxt->myDoc != NULL) { + reader->node = reader->ctxt->myDoc->children; + } + if (reader->node == NULL) + return(-1); + reader->state = XML_TEXTREADER_ELEMENT; + } else { + if (reader->ctxt->myDoc != NULL) { + reader->node = reader->ctxt->myDoc->children; + } + if (reader->node == NULL) + reader->node = reader->ctxt->nodeTab[0]; + reader->state = XML_TEXTREADER_ELEMENT; + } + reader->depth = 0; + reader->ctxt->parseMode = XML_PARSE_READER; + goto node_found; + } + oldstate = reader->state; + olddepth = reader->ctxt->nodeNr; + oldnode = reader->node; + +get_next_node: + if (reader->node == NULL) { + if (reader->mode == XML_TEXTREADER_DONE) + return(0); + else + return(-1); + } + + /* + * If we are not backtracking on ancestors or examined nodes, + * that the parser didn't finished or that we arent at the end + * of stream, continue processing. + */ + while ((reader->node != NULL) && (reader->node->next == NULL) && + (reader->ctxt->nodeNr == olddepth) && + ((oldstate == XML_TEXTREADER_BACKTRACK) || + (reader->node->children == NULL) || + (reader->node->type == XML_ENTITY_REF_NODE) || + ((reader->node->children != NULL) && + (reader->node->children->type == XML_TEXT_NODE) && + (reader->node->children->next == NULL)) || + (reader->node->type == XML_DTD_NODE) || + (reader->node->type == XML_DOCUMENT_NODE) || + (reader->node->type == XML_HTML_DOCUMENT_NODE)) && + ((reader->ctxt->node == NULL) || + (reader->ctxt->node == reader->node) || + (reader->ctxt->node == reader->node->parent)) && + (reader->ctxt->instate != XML_PARSER_EOF)) { + val = xmlTextReaderPushData(reader); + if (val < 0) + return(-1); + if (reader->node == NULL) + goto node_end; + } + if (oldstate != XML_TEXTREADER_BACKTRACK) { + if ((reader->node->children != NULL) && + (reader->node->type != XML_ENTITY_REF_NODE) && + (reader->node->type != XML_XINCLUDE_START) && + (reader->node->type != XML_DTD_NODE)) { + reader->node = reader->node->children; + reader->depth++; + reader->state = XML_TEXTREADER_ELEMENT; + goto node_found; + } + } + if (reader->node->next != NULL) { + if ((oldstate == XML_TEXTREADER_ELEMENT) && + (reader->node->type == XML_ELEMENT_NODE) && + (reader->node->children == NULL) && + ((reader->node->extra & NODE_IS_EMPTY) == 0) +#ifdef LIBXML_XINCLUDE_ENABLED + && (reader->in_xinclude <= 0) +#endif + ) { + reader->state = XML_TEXTREADER_END; + goto node_found; + } +#ifdef LIBXML_REGEXP_ENABLED + if ((reader->validate) && + (reader->node->type == XML_ELEMENT_NODE)) + xmlTextReaderValidatePop(reader); +#endif /* LIBXML_REGEXP_ENABLED */ + if ((reader->preserves > 0) && + (reader->node->extra & NODE_IS_SPRESERVED)) + reader->preserves--; + reader->node = reader->node->next; + reader->state = XML_TEXTREADER_ELEMENT; + + /* + * Cleanup of the old node + */ + if ((reader->preserves == 0) && +#ifdef LIBXML_XINCLUDE_ENABLED + (reader->in_xinclude == 0) && +#endif + (reader->entNr == 0) && + (reader->node->prev != NULL) && + (reader->node->prev->type != XML_DTD_NODE) && + (reader->entNr == 0)) { + xmlNodePtr tmp = reader->node->prev; + if ((tmp->extra & NODE_IS_PRESERVED) == 0) { + xmlUnlinkNode(tmp); + xmlTextReaderFreeNode(reader, tmp); + } + } + + goto node_found; + } + if ((oldstate == XML_TEXTREADER_ELEMENT) && + (reader->node->type == XML_ELEMENT_NODE) && + (reader->node->children == NULL) && + ((reader->node->extra & NODE_IS_EMPTY) == 0)) {; + reader->state = XML_TEXTREADER_END; + goto node_found; + } +#ifdef LIBXML_REGEXP_ENABLED + if ((reader->validate) && (reader->node->type == XML_ELEMENT_NODE)) + xmlTextReaderValidatePop(reader); +#endif /* LIBXML_REGEXP_ENABLED */ + if ((reader->preserves > 0) && + (reader->node->extra & NODE_IS_SPRESERVED)) + reader->preserves--; + reader->node = reader->node->parent; + if ((reader->node == NULL) || + (reader->node->type == XML_DOCUMENT_NODE) || +#ifdef LIBXML_DOCB_ENABLED + (reader->node->type == XML_DOCB_DOCUMENT_NODE) || +#endif + (reader->node->type == XML_HTML_DOCUMENT_NODE)) { + if (reader->mode != XML_TEXTREADER_DONE) { + val = xmlParseChunk(reader->ctxt, "", 0, 1); + reader->mode = XML_TEXTREADER_DONE; + if (val != 0) + return(-1); + } + reader->node = NULL; + reader->depth = -1; + + /* + * Cleanup of the old node + */ + if ((reader->preserves == 0) && +#ifdef LIBXML_XINCLUDE_ENABLED + (reader->in_xinclude == 0) && +#endif + (reader->entNr == 0) && + (oldnode->type != XML_DTD_NODE) && + ((oldnode->extra & NODE_IS_PRESERVED) == 0) && + (reader->entNr == 0)) { + xmlUnlinkNode(oldnode); + xmlTextReaderFreeNode(reader, oldnode); + } + + goto node_end; + } + if ((reader->preserves == 0) && +#ifdef LIBXML_XINCLUDE_ENABLED + (reader->in_xinclude == 0) && +#endif + (reader->entNr == 0) && + (reader->node->last != NULL) && + ((reader->node->last->extra & NODE_IS_PRESERVED) == 0)) { + xmlNodePtr tmp = reader->node->last; + xmlUnlinkNode(tmp); + xmlTextReaderFreeNode(reader, tmp); + } + reader->depth--; + reader->state = XML_TEXTREADER_BACKTRACK; + +node_found: + DUMP_READER + + /* + * If we are in the middle of a piece of CDATA make sure it's finished + */ + if ((reader->node != NULL) && + (reader->node->next == NULL) && + ((reader->node->type == XML_TEXT_NODE) || + (reader->node->type == XML_CDATA_SECTION_NODE))) { + if (xmlTextReaderExpand(reader) == NULL) + return -1; + } + +#ifdef LIBXML_XINCLUDE_ENABLED + /* + * Handle XInclude if asked for + */ + if ((reader->xinclude) && (reader->node != NULL) && + (reader->node->type == XML_ELEMENT_NODE) && + (reader->node->ns != NULL) && + ((xmlStrEqual(reader->node->ns->href, XINCLUDE_NS)) || + (xmlStrEqual(reader->node->ns->href, XINCLUDE_OLD_NS)))) { + if (reader->xincctxt == NULL) { + reader->xincctxt = xmlXIncludeNewContext(reader->ctxt->myDoc); + xmlXIncludeSetFlags(reader->xincctxt, + reader->parserFlags & (~XML_PARSE_NOXINCNODE)); + } + /* + * expand that node and process it + */ + if (xmlTextReaderExpand(reader) == NULL) + return -1; + xmlXIncludeProcessNode(reader->xincctxt, reader->node); + } + if ((reader->node != NULL) && (reader->node->type == XML_XINCLUDE_START)) { + reader->in_xinclude++; + goto get_next_node; + } + if ((reader->node != NULL) && (reader->node->type == XML_XINCLUDE_END)) { + reader->in_xinclude--; + goto get_next_node; + } +#endif + /* + * Handle entities enter and exit when in entity replacement mode + */ + if ((reader->node != NULL) && + (reader->node->type == XML_ENTITY_REF_NODE) && + (reader->ctxt != NULL) && (reader->ctxt->replaceEntities == 1)) { + /* + * Case where the underlying tree is not availble, lookup the entity + * and walk it. + */ + if ((reader->node->children == NULL) && (reader->ctxt->sax != NULL) && + (reader->ctxt->sax->getEntity != NULL)) { + reader->node->children = (xmlNodePtr) + reader->ctxt->sax->getEntity(reader->ctxt, reader->node->name); + } + + if ((reader->node->children != NULL) && + (reader->node->children->type == XML_ENTITY_DECL) && + (reader->node->children->children != NULL)) { + xmlTextReaderEntPush(reader, reader->node); + reader->node = reader->node->children->children; + } +#ifdef LIBXML_REGEXP_ENABLED + } else if ((reader->node != NULL) && + (reader->node->type == XML_ENTITY_REF_NODE) && + (reader->ctxt != NULL) && (reader->validate)) { + xmlTextReaderValidateEntity(reader); +#endif /* LIBXML_REGEXP_ENABLED */ + } + if ((reader->node != NULL) && + (reader->node->type == XML_ENTITY_DECL) && + (reader->ent != NULL) && (reader->ent->children == reader->node)) { + reader->node = xmlTextReaderEntPop(reader); + reader->depth++; + goto get_next_node; + } +#ifdef LIBXML_REGEXP_ENABLED + if ((reader->validate) && (reader->node != NULL)) { + xmlNodePtr node = reader->node; + + if ((node->type == XML_ELEMENT_NODE) && + ((reader->state != XML_TEXTREADER_END) && + (reader->state != XML_TEXTREADER_BACKTRACK))) { + xmlTextReaderValidatePush(reader); + } else if ((node->type == XML_TEXT_NODE) || + (node->type == XML_CDATA_SECTION_NODE)) { + xmlTextReaderValidateCData(reader, node->content, + xmlStrlen(node->content)); + } + } +#endif /* LIBXML_REGEXP_ENABLED */ +#ifdef LIBXML_PATTERN_ENABLED + if ((reader->patternNr > 0) && (reader->state != XML_TEXTREADER_END) && + (reader->state != XML_TEXTREADER_BACKTRACK)) { + int i; + for (i = 0;i < reader->patternNr;i++) { + if (xmlPatternMatch(reader->patternTab[i], reader->node) == 1) { + xmlTextReaderPreserve(reader); + break; + } + } + } +#endif /* LIBXML_PATTERN_ENABLED */ +#ifdef LIBXML_SCHEMAS_ENABLED + if ((reader->validate == XML_TEXTREADER_VALIDATE_XSD) && + (reader->xsdValidErrors == 0) && + (reader->xsdValidCtxt != NULL)) { + reader->xsdValidErrors = !xmlSchemaIsValid(reader->xsdValidCtxt); + } +#endif /* LIBXML_PATTERN_ENABLED */ + return(1); +node_end: + reader->mode = XML_TEXTREADER_DONE; + return(0); +} + +/** + * xmlTextReaderReadState: + * @reader: the xmlTextReaderPtr used + * + * Gets the read state of the reader. + * + * Returns the state value, or -1 in case of error + */ +int +xmlTextReaderReadState(xmlTextReaderPtr reader) { + if (reader == NULL) + return(-1); + return(reader->mode); +} + +/** + * xmlTextReaderExpand: + * @reader: the xmlTextReaderPtr used + * + * Reads the contents of the current node and the full subtree. It then makes + * the subtree available until the next xmlTextReaderRead() call + * + * Returns a node pointer valid until the next xmlTextReaderRead() call + * or NULL in case of error. + */ +xmlNodePtr +xmlTextReaderExpand(xmlTextReaderPtr reader) { + if ((reader == NULL) || (reader->node == NULL)) + return(NULL); + if (reader->doc != NULL) + return(reader->node); + if (reader->ctxt == NULL) + return(NULL); + if (xmlTextReaderDoExpand(reader) < 0) + return(NULL); + return(reader->node); +} + +/** + * xmlTextReaderNext: + * @reader: the xmlTextReaderPtr used + * + * Skip to the node following the current one in document order while + * avoiding the subtree if any. + * + * Returns 1 if the node was read successfully, 0 if there is no more + * nodes to read, or -1 in case of error + */ +int +xmlTextReaderNext(xmlTextReaderPtr reader) { + int ret; + xmlNodePtr cur; + + if (reader == NULL) + return(-1); + if (reader->doc != NULL) + return(xmlTextReaderNextTree(reader)); + cur = reader->node; + if ((cur == NULL) || (cur->type != XML_ELEMENT_NODE)) + return(xmlTextReaderRead(reader)); + if (reader->state == XML_TEXTREADER_END || reader->state == XML_TEXTREADER_BACKTRACK) + return(xmlTextReaderRead(reader)); + if (cur->extra & NODE_IS_EMPTY) + return(xmlTextReaderRead(reader)); + do { + ret = xmlTextReaderRead(reader); + if (ret != 1) + return(ret); + } while (reader->node != cur); + return(xmlTextReaderRead(reader)); +} + +#ifdef LIBXML_WRITER_ENABLED +/** + * xmlTextReaderReadInnerXml: + * @reader: the xmlTextReaderPtr used + * + * Reads the contents of the current node, including child nodes and markup. + * + * Returns a string containing the XML content, or NULL if the current node + * is neither an element nor attribute, or has no child nodes. The + * string must be deallocated by the caller. + */ +xmlChar * +xmlTextReaderReadInnerXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) +{ + xmlChar *resbuf; + xmlNodePtr node, cur_node; + xmlBufferPtr buff, buff2; + xmlDocPtr doc; + + if (xmlTextReaderExpand(reader) == NULL) { + return NULL; + } + doc = reader->doc; + buff = xmlBufferCreate(); + for (cur_node = reader->node->children; cur_node != NULL; + cur_node = cur_node->next) { + node = xmlDocCopyNode(cur_node, doc, 1); + buff2 = xmlBufferCreate(); + if (xmlNodeDump(buff2, doc, node, 0, 0) == -1) { + xmlFreeNode(node); + xmlBufferFree(buff2); + xmlBufferFree(buff); + return NULL; + } + xmlBufferCat(buff, buff2->content); + xmlFreeNode(node); + xmlBufferFree(buff2); + } + resbuf = buff->content; + buff->content = NULL; + + xmlBufferFree(buff); + return resbuf; +} +#endif + +#ifdef LIBXML_WRITER_ENABLED +/** + * xmlTextReaderReadOuterXml: + * @reader: the xmlTextReaderPtr used + * + * Reads the contents of the current node, including child nodes and markup. + * + * Returns a string containing the XML content, or NULL if the current node + * is neither an element nor attribute, or has no child nodes. The + * string must be deallocated by the caller. + */ +xmlChar * +xmlTextReaderReadOuterXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) +{ + xmlChar *resbuf; + xmlNodePtr node; + xmlBufferPtr buff; + xmlDocPtr doc; + + node = reader->node; + doc = reader->doc; + if (xmlTextReaderExpand(reader) == NULL) { + return NULL; + } + node = xmlDocCopyNode(node, doc, 1); + buff = xmlBufferCreate(); + if (xmlNodeDump(buff, doc, node, 0, 0) == -1) { + xmlFreeNode(node); + xmlBufferFree(buff); + return NULL; + } + + resbuf = buff->content; + buff->content = NULL; + + xmlFreeNode(node); + xmlBufferFree(buff); + return resbuf; +} +#endif + +/** + * xmlTextReaderReadString: + * @reader: the xmlTextReaderPtr used + * + * Reads the contents of an element or a text node as a string. + * + * Returns a string containing the contents of the Element or Text node, + * or NULL if the reader is positioned on any other type of node. + * The string must be deallocated by the caller. + */ +xmlChar * +xmlTextReaderReadString(xmlTextReaderPtr reader) +{ + xmlNodePtr node; + + if ((reader == NULL) || (reader->node == NULL)) + return(NULL); + + node = (reader->curnode != NULL) ? reader->curnode : reader->node; + switch (node->type) { + case XML_TEXT_NODE: + if (node->content != NULL) + return(xmlStrdup(node->content)); + break; + case XML_ELEMENT_NODE: + if (xmlTextReaderDoExpand(reader) != -1) { + return xmlTextReaderCollectSiblings(node->children); + } + case XML_ATTRIBUTE_NODE: + TODO + break; + default: + break; + } + return(NULL); +} + +#if 0 +/** + * xmlTextReaderReadBase64: + * @reader: the xmlTextReaderPtr used + * @array: a byte array to store the content. + * @offset: the zero-based index into array where the method should + * begin to write. + * @len: the number of bytes to write. + * + * Reads and decodes the Base64 encoded contents of an element and + * stores the result in a byte buffer. + * + * Returns the number of bytes written to array, or zero if the current + * instance is not positioned on an element or -1 in case of error. + */ +int +xmlTextReaderReadBase64(xmlTextReaderPtr reader, + unsigned char *array ATTRIBUTE_UNUSED, + int offset ATTRIBUTE_UNUSED, + int len ATTRIBUTE_UNUSED) { + if ((reader == NULL) || (reader->ctxt == NULL)) + return(-1); + if (reader->ctxt->wellFormed != 1) + return(-1); + + if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE)) + return(0); + TODO + return(0); +} + +/** + * xmlTextReaderReadBinHex: + * @reader: the xmlTextReaderPtr used + * @array: a byte array to store the content. + * @offset: the zero-based index into array where the method should + * begin to write. + * @len: the number of bytes to write. + * + * Reads and decodes the BinHex encoded contents of an element and + * stores the result in a byte buffer. + * + * Returns the number of bytes written to array, or zero if the current + * instance is not positioned on an element or -1 in case of error. + */ +int +xmlTextReaderReadBinHex(xmlTextReaderPtr reader, + unsigned char *array ATTRIBUTE_UNUSED, + int offset ATTRIBUTE_UNUSED, + int len ATTRIBUTE_UNUSED) { + if ((reader == NULL) || (reader->ctxt == NULL)) + return(-1); + if (reader->ctxt->wellFormed != 1) + return(-1); + + if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE)) + return(0); + TODO + return(0); +} +#endif + +/************************************************************************ + * * + * Operating on a preparsed tree * + * * + ************************************************************************/ +static int +xmlTextReaderNextTree(xmlTextReaderPtr reader) +{ + if (reader == NULL) + return(-1); + + if (reader->state == XML_TEXTREADER_END) + return(0); + + if (reader->node == NULL) { + if (reader->doc->children == NULL) { + reader->state = XML_TEXTREADER_END; + return(0); + } + + reader->node = reader->doc->children; + reader->state = XML_TEXTREADER_START; + return(1); + } + + if (reader->state != XML_TEXTREADER_BACKTRACK) { + if (reader->node->children != 0) { + reader->node = reader->node->children; + reader->depth++; + reader->state = XML_TEXTREADER_START; + return(1); + } + + if ((reader->node->type == XML_ELEMENT_NODE) || + (reader->node->type == XML_ATTRIBUTE_NODE)) { + reader->state = XML_TEXTREADER_BACKTRACK; + return(1); + } + } + + if (reader->node->next != 0) { + reader->node = reader->node->next; + reader->state = XML_TEXTREADER_START; + return(1); + } + + if (reader->node->parent != 0) { + if (reader->node->parent->type == XML_DOCUMENT_NODE) { + reader->state = XML_TEXTREADER_END; + return(0); + } + + reader->node = reader->node->parent; + reader->depth--; + reader->state = XML_TEXTREADER_BACKTRACK; + return(1); + } + + reader->state = XML_TEXTREADER_END; + + return(1); +} + +/** + * xmlTextReaderReadTree: + * @reader: the xmlTextReaderPtr used + * + * Moves the position of the current instance to the next node in + * the stream, exposing its properties. + * + * Returns 1 if the node was read successfully, 0 if there is no more + * nodes to read, or -1 in case of error + */ +static int +xmlTextReaderReadTree(xmlTextReaderPtr reader) { + if (reader->state == XML_TEXTREADER_END) + return(0); + +next_node: + if (reader->node == NULL) { + if (reader->doc->children == NULL) { + reader->state = XML_TEXTREADER_END; + return(0); + } + + reader->node = reader->doc->children; + reader->state = XML_TEXTREADER_START; + goto found_node; + } + + if ((reader->state != XML_TEXTREADER_BACKTRACK) && + (reader->node->type != XML_DTD_NODE) && + (reader->node->type != XML_XINCLUDE_START) && + (reader->node->type != XML_ENTITY_REF_NODE)) { + if (reader->node->children != NULL) { + reader->node = reader->node->children; + reader->depth++; + reader->state = XML_TEXTREADER_START; + goto found_node; + } + + if (reader->node->type == XML_ATTRIBUTE_NODE) { + reader->state = XML_TEXTREADER_BACKTRACK; + goto found_node; + } + } + + if (reader->node->next != NULL) { + reader->node = reader->node->next; + reader->state = XML_TEXTREADER_START; + goto found_node; + } + + if (reader->node->parent != NULL) { + if ((reader->node->parent->type == XML_DOCUMENT_NODE) || + (reader->node->parent->type == XML_HTML_DOCUMENT_NODE)) { + reader->state = XML_TEXTREADER_END; + return(0); + } + + reader->node = reader->node->parent; + reader->depth--; + reader->state = XML_TEXTREADER_BACKTRACK; + goto found_node; + } + + reader->state = XML_TEXTREADER_END; + +found_node: + if ((reader->node->type == XML_XINCLUDE_START) || + (reader->node->type == XML_XINCLUDE_END)) + goto next_node; + + return(1); +} + +/** + * xmlTextReaderNextSibling: + * @reader: the xmlTextReaderPtr used + * + * Skip to the node following the current one in document order while + * avoiding the subtree if any. + * Currently implemented only for Readers built on a document + * + * Returns 1 if the node was read successfully, 0 if there is no more + * nodes to read, or -1 in case of error + */ +int +xmlTextReaderNextSibling(xmlTextReaderPtr reader) { + if (reader == NULL) + return(-1); + if (reader->doc == NULL) { + /* TODO */ + return(-1); + } + + if (reader->state == XML_TEXTREADER_END) + return(0); + + if (reader->node == NULL) + return(xmlTextReaderNextTree(reader)); + + if (reader->node->next != NULL) { + reader->node = reader->node->next; + reader->state = XML_TEXTREADER_START; + return(1); + } + + return(0); +} + +/************************************************************************ + * * + * Constructor and destructors * + * * + ************************************************************************/ +/** + * xmlNewTextReader: + * @input: the xmlParserInputBufferPtr used to read data + * @URI: the URI information for the source if available + * + * Create an xmlTextReader structure fed with @input + * + * Returns the new xmlTextReaderPtr or NULL in case of error + */ +xmlTextReaderPtr +xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) { + xmlTextReaderPtr ret; + + if (input == NULL) + return(NULL); + ret = xmlMalloc(sizeof(xmlTextReader)); + if (ret == NULL) { + xmlGenericError(xmlGenericErrorContext, + "xmlNewTextReader : malloc failed\n"); + return(NULL); + } + memset(ret, 0, sizeof(xmlTextReader)); + ret->doc = NULL; + ret->entTab = NULL; + ret->entMax = 0; + ret->entNr = 0; + ret->input = input; + ret->buffer = xmlBufferCreateSize(100); + if (ret->buffer == NULL) { + xmlFree(ret); + xmlGenericError(xmlGenericErrorContext, + "xmlNewTextReader : malloc failed\n"); + return(NULL); + } + ret->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler)); + if (ret->sax == NULL) { + xmlBufferFree(ret->buffer); + xmlFree(ret); + xmlGenericError(xmlGenericErrorContext, + "xmlNewTextReader : malloc failed\n"); + return(NULL); + } + xmlSAXVersion(ret->sax, 2); + ret->startElement = ret->sax->startElement; + ret->sax->startElement = xmlTextReaderStartElement; + ret->endElement = ret->sax->endElement; + ret->sax->endElement = xmlTextReaderEndElement; +#ifdef LIBXML_SAX1_ENABLED + if (ret->sax->initialized == XML_SAX2_MAGIC) { +#endif /* LIBXML_SAX1_ENABLED */ + ret->startElementNs = ret->sax->startElementNs; + ret->sax->startElementNs = xmlTextReaderStartElementNs; + ret->endElementNs = ret->sax->endElementNs; + ret->sax->endElementNs = xmlTextReaderEndElementNs; +#ifdef LIBXML_SAX1_ENABLED + } else { + ret->startElementNs = NULL; + ret->endElementNs = NULL; + } +#endif /* LIBXML_SAX1_ENABLED */ + ret->characters = ret->sax->characters; + ret->sax->characters = xmlTextReaderCharacters; + ret->sax->ignorableWhitespace = xmlTextReaderCharacters; + ret->cdataBlock = ret->sax->cdataBlock; + ret->sax->cdataBlock = xmlTextReaderCDataBlock; + + ret->mode = XML_TEXTREADER_MODE_INITIAL; + ret->node = NULL; + ret->curnode = NULL; + if (ret->input->buffer->use < 4) { + xmlParserInputBufferRead(input, 4); + } + if (ret->input->buffer->use >= 4) { + ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL, + (const char *) ret->input->buffer->content, 4, URI); + ret->base = 0; + ret->cur = 4; + } else { + ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL, NULL, 0, URI); + ret->base = 0; + ret->cur = 0; + } + + if (ret->ctxt == NULL) { + xmlGenericError(xmlGenericErrorContext, + "xmlNewTextReader : malloc failed\n"); + xmlBufferFree(ret->buffer); + xmlFree(ret->sax); + xmlFree(ret); + return(NULL); + } + ret->ctxt->parseMode = XML_PARSE_READER; + ret->ctxt->_private = ret; + ret->ctxt->linenumbers = 1; + ret->ctxt->dictNames = 1; + ret->allocs = XML_TEXTREADER_CTXT; + /* + * use the parser dictionnary to allocate all elements and attributes names + */ + ret->ctxt->docdict = 1; + ret->dict = ret->ctxt->dict; +#ifdef LIBXML_XINCLUDE_ENABLED + ret->xinclude = 0; +#endif +#ifdef LIBXML_PATTERN_ENABLED + ret->patternMax = 0; + ret->patternTab = NULL; +#endif + return(ret); +} + +/** + * xmlNewTextReaderFilename: + * @URI: the URI of the resource to process + * + * Create an xmlTextReader structure fed with the resource at @URI + * + * Returns the new xmlTextReaderPtr or NULL in case of error + */ +xmlTextReaderPtr +xmlNewTextReaderFilename(const char *URI) { + xmlParserInputBufferPtr input; + xmlTextReaderPtr ret; + char *directory = NULL; + + input = xmlParserInputBufferCreateFilename(URI, XML_CHAR_ENCODING_NONE); + if (input == NULL) + return(NULL); + ret = xmlNewTextReader(input, URI); + if (ret == NULL) { + xmlFreeParserInputBuffer(input); + return(NULL); + } + ret->allocs |= XML_TEXTREADER_INPUT; + if (ret->ctxt->directory == NULL) + directory = xmlParserGetDirectory(URI); + if ((ret->ctxt->directory == NULL) && (directory != NULL)) + ret->ctxt->directory = (char *) xmlStrdup((xmlChar *) directory); + if (directory != NULL) + xmlFree(directory); + return(ret); +} + +/** + * xmlFreeTextReader: + * @reader: the xmlTextReaderPtr + * + * Deallocate all the resources associated to the reader + */ +void +xmlFreeTextReader(xmlTextReaderPtr reader) { + if (reader == NULL) + return; +#ifdef LIBXML_SCHEMAS_ENABLED + if (reader->rngSchemas != NULL) { + xmlRelaxNGFree(reader->rngSchemas); + reader->rngSchemas = NULL; + } + if (reader->rngValidCtxt != NULL) { + xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt); + reader->rngValidCtxt = NULL; + } + if (reader->xsdPlug != NULL) { + xmlSchemaSAXUnplug(reader->xsdPlug); + reader->xsdPlug = NULL; + } + if (reader->xsdValidCtxt != NULL) { + if (! reader->xsdPreserveCtxt) + xmlSchemaFreeValidCtxt(reader->xsdValidCtxt); + reader->xsdValidCtxt = NULL; + } + if (reader->xsdSchemas != NULL) { + xmlSchemaFree(reader->xsdSchemas); + reader->xsdSchemas = NULL; + } +#endif +#ifdef LIBXML_XINCLUDE_ENABLED + if (reader->xincctxt != NULL) + xmlXIncludeFreeContext(reader->xincctxt); +#endif +#ifdef LIBXML_PATTERN_ENABLED + if (reader->patternTab != NULL) { + int i; + for (i = 0;i < reader->patternNr;i++) { + if (reader->patternTab[i] != NULL) + xmlFreePattern(reader->patternTab[i]); + } + xmlFree(reader->patternTab); + } +#endif + if (reader->ctxt != NULL) { + if (reader->dict == reader->ctxt->dict) + reader->dict = NULL; + if (reader->ctxt->myDoc != NULL) { + if (reader->preserve == 0) + xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc); + reader->ctxt->myDoc = NULL; + } + if ((reader->ctxt->vctxt.vstateTab != NULL) && + (reader->ctxt->vctxt.vstateMax > 0)){ + xmlFree(reader->ctxt->vctxt.vstateTab); + reader->ctxt->vctxt.vstateTab = NULL; + reader->ctxt->vctxt.vstateMax = 0; + } + if (reader->allocs & XML_TEXTREADER_CTXT) + xmlFreeParserCtxt(reader->ctxt); + } + if (reader->sax != NULL) + xmlFree(reader->sax); + if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT)) + xmlFreeParserInputBuffer(reader->input); + if (reader->faketext != NULL) { + xmlFreeNode(reader->faketext); + } + if (reader->buffer != NULL) + xmlBufferFree(reader->buffer); + if (reader->entTab != NULL) + xmlFree(reader->entTab); + if (reader->dict != NULL) + xmlDictFree(reader->dict); + xmlFree(reader); +} + +/************************************************************************ + * * + * Methods for XmlTextReader * + * * + ************************************************************************/ +/** + * xmlTextReaderClose: + * @reader: the xmlTextReaderPtr used + * + * This method releases any resources allocated by the current instance + * changes the state to Closed and close any underlying input. + * + * Returns 0 or -1 in case of error + */ +int +xmlTextReaderClose(xmlTextReaderPtr reader) { + if (reader == NULL) + return(-1); + reader->node = NULL; + reader->curnode = NULL; + reader->mode = XML_TEXTREADER_MODE_CLOSED; + if (reader->ctxt != NULL) { + xmlStopParser(reader->ctxt); + if (reader->ctxt->myDoc != NULL) { + if (reader->preserve == 0) + xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc); + reader->ctxt->myDoc = NULL; + } + } + if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT)) { + xmlFreeParserInputBuffer(reader->input); + reader->allocs -= XML_TEXTREADER_INPUT; + } + return(0); +} + +/** + * xmlTextReaderGetAttributeNo: + * @reader: the xmlTextReaderPtr used + * @no: the zero-based index of the attribute relative to the containing element + * + * Provides the value of the attribute with the specified index relative + * to the containing element. + * + * Returns a string containing the value of the specified attribute, or NULL + * in case of error. The string must be deallocated by the caller. + */ +xmlChar * +xmlTextReaderGetAttributeNo(xmlTextReaderPtr reader, int no) { + xmlChar *ret; + int i; + xmlAttrPtr cur; + xmlNsPtr ns; + + if (reader == NULL) + return(NULL); + if (reader->node == NULL) + return(NULL); + if (reader->curnode != NULL) + return(NULL); + /* TODO: handle the xmlDecl */ + if (reader->node->type != XML_ELEMENT_NODE) + return(NULL); + + ns = reader->node->nsDef; + for (i = 0;(i < no) && (ns != NULL);i++) { + ns = ns->next; + } + if (ns != NULL) + return(xmlStrdup(ns->href)); + + cur = reader->node->properties; + if (cur == NULL) + return(NULL); + for (;i < no;i++) { + cur = cur->next; + if (cur == NULL) + return(NULL); + } + /* TODO walk the DTD if present */ + + ret = xmlNodeListGetString(reader->node->doc, cur->children, 1); + if (ret == NULL) return(xmlStrdup((xmlChar *)"")); + return(ret); +} + +/** + * xmlTextReaderGetAttribute: + * @reader: the xmlTextReaderPtr used + * @name: the qualified name of the attribute. + * + * Provides the value of the attribute with the specified qualified name. + * + * Returns a string containing the value of the specified attribute, or NULL + * in case of error. The string must be deallocated by the caller. + */ +xmlChar * +xmlTextReaderGetAttribute(xmlTextReaderPtr reader, const xmlChar *name) { + xmlChar *prefix = NULL; + xmlChar *localname; + xmlNsPtr ns; + xmlChar *ret = NULL; + + if ((reader == NULL) || (name == NULL)) + return(NULL); + if (reader->node == NULL) + return(NULL); + if (reader->curnode != NULL) + return(NULL); + + /* TODO: handle the xmlDecl */ + if (reader->node->type != XML_ELEMENT_NODE) + return(NULL); + + localname = xmlSplitQName2(name, &prefix); + if (localname == NULL) { + /* + * Namespace default decl + */ + if (xmlStrEqual(name, BAD_CAST "xmlns")) { + ns = reader->node->nsDef; + while (ns != NULL) { + if (ns->prefix == NULL) { + return(xmlStrdup(ns->href)); + } + ns = ns->next; + } + return NULL; + } + return(xmlGetNoNsProp(reader->node, name)); + } + + /* + * Namespace default decl + */ + if (xmlStrEqual(prefix, BAD_CAST "xmlns")) { + ns = reader->node->nsDef; + while (ns != NULL) { + if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) { + ret = xmlStrdup(ns->href); + break; + } + ns = ns->next; + } + } else { + ns = xmlSearchNs(reader->node->doc, reader->node, prefix); + if (ns != NULL) + ret = xmlGetNsProp(reader->node, localname, ns->href); + } + + xmlFree(localname); + if (prefix != NULL) + xmlFree(prefix); + return(ret); +} + + +/** + * xmlTextReaderGetAttributeNs: + * @reader: the xmlTextReaderPtr used + * @localName: the local name of the attribute. + * @namespaceURI: the namespace URI of the attribute. + * + * Provides the value of the specified attribute + * + * Returns a string containing the value of the specified attribute, or NULL + * in case of error. The string must be deallocated by the caller. + */ +xmlChar * +xmlTextReaderGetAttributeNs(xmlTextReaderPtr reader, const xmlChar *localName, + const xmlChar *namespaceURI) { + xmlChar *prefix = NULL; + xmlNsPtr ns; + + if ((reader == NULL) || (localName == NULL)) + return(NULL); + if (reader->node == NULL) + return(NULL); + if (reader->curnode != NULL) + return(NULL); + + /* TODO: handle the xmlDecl */ + if (reader->node->type != XML_ELEMENT_NODE) + return(NULL); + + if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) { + if (! xmlStrEqual(localName, BAD_CAST "xmlns")) { + prefix = BAD_CAST localName; + } + ns = reader->node->nsDef; + while (ns != NULL) { + if ((prefix == NULL && ns->prefix == NULL) || + ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) { + return xmlStrdup(ns->href); + } + ns = ns->next; + } + return NULL; + } + + return(xmlGetNsProp(reader->node, localName, namespaceURI)); +} + +/** + * xmlTextReaderGetRemainder: + * @reader: the xmlTextReaderPtr used + * + * Method to get the remainder of the buffered XML. this method stops the + * parser, set its state to End Of File and return the input stream with + * what is left that the parser did not use. + * + * The implementation is not good, the parser certainly procgressed past + * what's left in reader->input, and there is an allocation problem. Best + * would be to rewrite it differently. + * + * Returns the xmlParserInputBufferPtr attached to the XML or NULL + * in case of error. + */ +xmlParserInputBufferPtr +xmlTextReaderGetRemainder(xmlTextReaderPtr reader) { + xmlParserInputBufferPtr ret = NULL; + + if (reader == NULL) + return(NULL); + if (reader->node == NULL) + return(NULL); + + reader->node = NULL; + reader->curnode = NULL; + reader->mode = XML_TEXTREADER_MODE_EOF; + if (reader->ctxt != NULL) { + xmlStopParser(reader->ctxt); + if (reader->ctxt->myDoc != NULL) { + if (reader->preserve == 0) + xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc); + reader->ctxt->myDoc = NULL; + } + } + if (reader->allocs & XML_TEXTREADER_INPUT) { + ret = reader->input; + reader->input = NULL; + reader->allocs -= XML_TEXTREADER_INPUT; + } else { + /* + * Hum, one may need to duplicate the data structure because + * without reference counting the input may be freed twice: + * - by the layer which allocated it. + * - by the layer to which would have been returned to. + */ + TODO + return(NULL); + } + return(ret); +} + +/** + * xmlTextReaderLookupNamespace: + * @reader: the xmlTextReaderPtr used + * @prefix: the prefix whose namespace URI is to be resolved. To return + * the default namespace, specify NULL + * + * Resolves a namespace prefix in the scope of the current element. + * + * Returns a string containing the namespace URI to which the prefix maps + * or NULL in case of error. The string must be deallocated by the caller. + */ +xmlChar * +xmlTextReaderLookupNamespace(xmlTextReaderPtr reader, const xmlChar *prefix) { + xmlNsPtr ns; + + if (reader == NULL) + return(NULL); + if (reader->node == NULL) + return(NULL); + + ns = xmlSearchNs(reader->node->doc, reader->node, prefix); + if (ns == NULL) + return(NULL); + return(xmlStrdup(ns->href)); +} + +/** + * xmlTextReaderMoveToAttributeNo: + * @reader: the xmlTextReaderPtr used + * @no: the zero-based index of the attribute relative to the containing + * element. + * + * Moves the position of the current instance to the attribute with + * the specified index relative to the containing element. + * + * Returns 1 in case of success, -1 in case of error, 0 if not found + */ +int +xmlTextReaderMoveToAttributeNo(xmlTextReaderPtr reader, int no) { + int i; + xmlAttrPtr cur; + xmlNsPtr ns; + + if (reader == NULL) + return(-1); + if (reader->node == NULL) + return(-1); + /* TODO: handle the xmlDecl */ + if (reader->node->type != XML_ELEMENT_NODE) + return(-1); + + reader->curnode = NULL; + + ns = reader->node->nsDef; + for (i = 0;(i < no) && (ns != NULL);i++) { + ns = ns->next; + } + if (ns != NULL) { + reader->curnode = (xmlNodePtr) ns; + return(1); + } + + cur = reader->node->properties; + if (cur == NULL) + return(0); + for (;i < no;i++) { + cur = cur->next; + if (cur == NULL) + return(0); + } + /* TODO walk the DTD if present */ + + reader->curnode = (xmlNodePtr) cur; + return(1); +} + +/** + * xmlTextReaderMoveToAttribute: + * @reader: the xmlTextReaderPtr used + * @name: the qualified name of the attribute. + * + * Moves the position of the current instance to the attribute with + * the specified qualified name. + * + * Returns 1 in case of success, -1 in case of error, 0 if not found + */ +int +xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader, const xmlChar *name) { + xmlChar *prefix = NULL; + xmlChar *localname; + xmlNsPtr ns; + xmlAttrPtr prop; + + if ((reader == NULL) || (name == NULL)) + return(-1); + if (reader->node == NULL) + return(-1); + + /* TODO: handle the xmlDecl */ + if (reader->node->type != XML_ELEMENT_NODE) + return(0); + + localname = xmlSplitQName2(name, &prefix); + if (localname == NULL) { + /* + * Namespace default decl + */ + if (xmlStrEqual(name, BAD_CAST "xmlns")) { + ns = reader->node->nsDef; + while (ns != NULL) { + if (ns->prefix == NULL) { + reader->curnode = (xmlNodePtr) ns; + return(1); + } + ns = ns->next; + } + return(0); + } + + prop = reader->node->properties; + while (prop != NULL) { + /* + * One need to have + * - same attribute names + * - and the attribute carrying that namespace + */ + if ((xmlStrEqual(prop->name, name)) && + ((prop->ns == NULL) || (prop->ns->prefix == NULL))) { + reader->curnode = (xmlNodePtr) prop; + return(1); + } + prop = prop->next; + } + return(0); + } + + /* + * Namespace default decl + */ + if (xmlStrEqual(prefix, BAD_CAST "xmlns")) { + ns = reader->node->nsDef; + while (ns != NULL) { + if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) { + reader->curnode = (xmlNodePtr) ns; + goto found; + } + ns = ns->next; + } + goto not_found; + } + prop = reader->node->properties; + while (prop != NULL) { + /* + * One need to have + * - same attribute names + * - and the attribute carrying that namespace + */ + if ((xmlStrEqual(prop->name, localname)) && + (prop->ns != NULL) && (xmlStrEqual(prop->ns->prefix, prefix))) { + reader->curnode = (xmlNodePtr) prop; + goto found; + } + prop = prop->next; + } +not_found: + if (localname != NULL) + xmlFree(localname); + if (prefix != NULL) + xmlFree(prefix); + return(0); + +found: + if (localname != NULL) + xmlFree(localname); + if (prefix != NULL) + xmlFree(prefix); + return(1); +} + +/** + * xmlTextReaderMoveToAttributeNs: + * @reader: the xmlTextReaderPtr used + * @localName: the local name of the attribute. + * @namespaceURI: the namespace URI of the attribute. + * + * Moves the position of the current instance to the attribute with the + * specified local name and namespace URI. + * + * Returns 1 in case of success, -1 in case of error, 0 if not found + */ +int +xmlTextReaderMoveToAttributeNs(xmlTextReaderPtr reader, + const xmlChar *localName, const xmlChar *namespaceURI) { + xmlAttrPtr prop; + xmlNodePtr node; + xmlNsPtr ns; + xmlChar *prefix = NULL; + + if ((reader == NULL) || (localName == NULL) || (namespaceURI == NULL)) + return(-1); + if (reader->node == NULL) + return(-1); + if (reader->node->type != XML_ELEMENT_NODE) + return(0); + node = reader->node; + + if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) { + if (! xmlStrEqual(localName, BAD_CAST "xmlns")) { + prefix = BAD_CAST localName; + } + ns = reader->node->nsDef; + while (ns != NULL) { + if ((prefix == NULL && ns->prefix == NULL) || + ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) { + reader->curnode = (xmlNodePtr) ns; + return(1); + } + ns = ns->next; + } + return(0); + } + + prop = node->properties; + while (prop != NULL) { + /* + * One need to have + * - same attribute names + * - and the attribute carrying that namespace + */ + if (xmlStrEqual(prop->name, localName) && + ((prop->ns != NULL) && + (xmlStrEqual(prop->ns->href, namespaceURI)))) { + reader->curnode = (xmlNodePtr) prop; + return(1); + } + prop = prop->next; + } + return(0); +} + +/** + * xmlTextReaderMoveToFirstAttribute: + * @reader: the xmlTextReaderPtr used + * + * Moves the position of the current instance to the first attribute + * associated with the current node. + * + * Returns 1 in case of success, -1 in case of error, 0 if not found + */ +int +xmlTextReaderMoveToFirstAttribute(xmlTextReaderPtr reader) { + if (reader == NULL) + return(-1); + if (reader->node == NULL) + return(-1); + if (reader->node->type != XML_ELEMENT_NODE) + return(0); + + if (reader->node->nsDef != NULL) { + reader->curnode = (xmlNodePtr) reader->node->nsDef; + return(1); + } + if (reader->node->properties != NULL) { + reader->curnode = (xmlNodePtr) reader->node->properties; + return(1); + } + return(0); +} + +/** + * xmlTextReaderMoveToNextAttribute: + * @reader: the xmlTextReaderPtr used + * + * Moves the position of the current instance to the next attribute + * associated with the current node. + * + * Returns 1 in case of success, -1 in case of error, 0 if not found + */ +int +xmlTextReaderMoveToNextAttribute(xmlTextReaderPtr reader) { + if (reader == NULL) + return(-1); + if (reader->node == NULL) + return(-1); + if (reader->node->type != XML_ELEMENT_NODE) + return(0); + if (reader->curnode == NULL) + return(xmlTextReaderMoveToFirstAttribute(reader)); + + if (reader->curnode->type == XML_NAMESPACE_DECL) { + xmlNsPtr ns = (xmlNsPtr) reader->curnode; + if (ns->next != NULL) { + reader->curnode = (xmlNodePtr) ns->next; + return(1); + } + if (reader->node->properties != NULL) { + reader->curnode = (xmlNodePtr) reader->node->properties; + return(1); + } + return(0); + } else if ((reader->curnode->type == XML_ATTRIBUTE_NODE) && + (reader->curnode->next != NULL)) { + reader->curnode = reader->curnode->next; + return(1); + } + return(0); +} + +/** + * xmlTextReaderMoveToElement: + * @reader: the xmlTextReaderPtr used + * + * Moves the position of the current instance to the node that + * contains the current Attribute node. + * + * Returns 1 in case of success, -1 in case of error, 0 if not moved + */ +int +xmlTextReaderMoveToElement(xmlTextReaderPtr reader) { + if (reader == NULL) + return(-1); + if (reader->node == NULL) + return(-1); + if (reader->node->type != XML_ELEMENT_NODE) + return(0); + if (reader->curnode != NULL) { + reader->curnode = NULL; + return(1); + } + return(0); +} + +/** + * xmlTextReaderReadAttributeValue: + * @reader: the xmlTextReaderPtr used + * + * Parses an attribute value into one or more Text and EntityReference nodes. + * + * Returns 1 in case of success, 0 if the reader was not positionned on an + * ttribute node or all the attribute values have been read, or -1 + * in case of error. + */ +int +xmlTextReaderReadAttributeValue(xmlTextReaderPtr reader) { + if (reader == NULL) + return(-1); + if (reader->node == NULL) + return(-1); + if (reader->curnode == NULL) + return(0); + if (reader->curnode->type == XML_ATTRIBUTE_NODE) { + if (reader->curnode->children == NULL) + return(0); + reader->curnode = reader->curnode->children; + } else if (reader->curnode->type == XML_NAMESPACE_DECL) { + xmlNsPtr ns = (xmlNsPtr) reader->curnode; + + if (reader->faketext == NULL) { + reader->faketext = xmlNewDocText(reader->node->doc, + ns->href); + } else { + if ((reader->faketext->content != NULL) && + (reader->faketext->content != + (xmlChar *) &(reader->faketext->properties))) + xmlFree(reader->faketext->content); + reader->faketext->content = xmlStrdup(ns->href); + } + reader->curnode = reader->faketext; + } else { + if (reader->curnode->next == NULL) + return(0); + reader->curnode = reader->curnode->next; + } + return(1); +} + +/** + * xmlTextReaderConstEncoding: + * @reader: the xmlTextReaderPtr used + * + * Determine the encoding of the document being read. + * + * Returns a string containing the encoding of the document or NULL in + * case of error. The string is deallocated with the reader. + */ +const xmlChar * +xmlTextReaderConstEncoding(xmlTextReaderPtr reader) { + xmlDocPtr doc = NULL; + if (reader == NULL) + return(NULL); + if (reader->doc != NULL) + doc = reader->doc; + else if (reader->ctxt != NULL) + doc = reader->ctxt->myDoc; + if (doc == NULL) + return(NULL); + + if (doc->encoding == NULL) + return(NULL); + else + return(CONSTSTR(doc->encoding)); +} + + +/************************************************************************ + * * + * Acces API to the current node * + * * + ************************************************************************/ +/** + * xmlTextReaderAttributeCount: + * @reader: the xmlTextReaderPtr used + * + * Provides the number of attributes of the current node + * + * Returns 0 i no attributes, -1 in case of error or the attribute count + */ +int +xmlTextReaderAttributeCount(xmlTextReaderPtr reader) { + int ret; + xmlAttrPtr attr; + xmlNsPtr ns; + xmlNodePtr node; + + if (reader == NULL) + return(-1); + if (reader->node == NULL) + return(0); + + if (reader->curnode != NULL) + node = reader->curnode; + else + node = reader->node; + + if (node->type != XML_ELEMENT_NODE) + return(0); + if ((reader->state == XML_TEXTREADER_END) || + (reader->state == XML_TEXTREADER_BACKTRACK)) + return(0); + ret = 0; + attr = node->properties; + while (attr != NULL) { + ret++; + attr = attr->next; + } + ns = node->nsDef; + while (ns != NULL) { + ret++; + ns = ns->next; + } + return(ret); +} + +/** + * xmlTextReaderNodeType: + * @reader: the xmlTextReaderPtr used + * + * Get the node type of the current node + * Reference: + * http://dotgnu.org/pnetlib-doc/System/Xml/XmlNodeType.html + * + * Returns the xmlNodeType of the current node or -1 in case of error + */ +int +xmlTextReaderNodeType(xmlTextReaderPtr reader) { + xmlNodePtr node; + + if (reader == NULL) + return(-1); + if (reader->node == NULL) + return(XML_READER_TYPE_NONE); + if (reader->curnode != NULL) + node = reader->curnode; + else + node = reader->node; + switch (node->type) { + case XML_ELEMENT_NODE: + if ((reader->state == XML_TEXTREADER_END) || + (reader->state == XML_TEXTREADER_BACKTRACK)) + return(XML_READER_TYPE_END_ELEMENT); + return(XML_READER_TYPE_ELEMENT); + case XML_NAMESPACE_DECL: + case XML_ATTRIBUTE_NODE: + return(XML_READER_TYPE_ATTRIBUTE); + case XML_TEXT_NODE: + if (xmlIsBlankNode(reader->node)) { + if (xmlNodeGetSpacePreserve(reader->node)) + return(XML_READER_TYPE_SIGNIFICANT_WHITESPACE); + else + return(XML_READER_TYPE_WHITESPACE); + } else { + return(XML_READER_TYPE_TEXT); + } + case XML_CDATA_SECTION_NODE: + return(XML_READER_TYPE_CDATA); + case XML_ENTITY_REF_NODE: + return(XML_READER_TYPE_ENTITY_REFERENCE); + case XML_ENTITY_NODE: + return(XML_READER_TYPE_ENTITY); + case XML_PI_NODE: + return(XML_READER_TYPE_PROCESSING_INSTRUCTION); + case XML_COMMENT_NODE: + return(XML_READER_TYPE_COMMENT); + case XML_DOCUMENT_NODE: + case XML_HTML_DOCUMENT_NODE: +#ifdef LIBXML_DOCB_ENABLED + case XML_DOCB_DOCUMENT_NODE: +#endif + return(XML_READER_TYPE_DOCUMENT); + case XML_DOCUMENT_FRAG_NODE: + return(XML_READER_TYPE_DOCUMENT_FRAGMENT); + case XML_NOTATION_NODE: + return(XML_READER_TYPE_NOTATION); + case XML_DOCUMENT_TYPE_NODE: + case XML_DTD_NODE: + return(XML_READER_TYPE_DOCUMENT_TYPE); + + case XML_ELEMENT_DECL: + case XML_ATTRIBUTE_DECL: + case XML_ENTITY_DECL: + case XML_XINCLUDE_START: + case XML_XINCLUDE_END: + return(XML_READER_TYPE_NONE); + } + return(-1); +} + +/** + * xmlTextReaderIsEmptyElement: + * @reader: the xmlTextReaderPtr used + * + * Check if the current node is empty + * + * Returns 1 if empty, 0 if not and -1 in case of error + */ +int +xmlTextReaderIsEmptyElement(xmlTextReaderPtr reader) { + if ((reader == NULL) || (reader->node == NULL)) + return(-1); + if (reader->node->type != XML_ELEMENT_NODE) + return(0); + if (reader->curnode != NULL) + return(0); + if (reader->node->children != NULL) + return(0); + if (reader->state == XML_TEXTREADER_END) + return(0); + if (reader->doc != NULL) + return(1); +#ifdef LIBXML_XINCLUDE_ENABLED + if (reader->in_xinclude > 0) + return(1); +#endif + return((reader->node->extra & NODE_IS_EMPTY) != 0); +} + +/** + * xmlTextReaderLocalName: + * @reader: the xmlTextReaderPtr used + * + * The local name of the node. + * + * Returns the local name or NULL if not available + */ +xmlChar * +xmlTextReaderLocalName(xmlTextReaderPtr reader) { + xmlNodePtr node; + if ((reader == NULL) || (reader->node == NULL)) + return(NULL); + if (reader->curnode != NULL) + node = reader->curnode; + else + node = reader->node; + if (node->type == XML_NAMESPACE_DECL) { + xmlNsPtr ns = (xmlNsPtr) node; + if (ns->prefix == NULL) + return(xmlStrdup(BAD_CAST "xmlns")); + else + return(xmlStrdup(ns->prefix)); + } + if ((node->type != XML_ELEMENT_NODE) && + (node->type != XML_ATTRIBUTE_NODE)) + return(xmlTextReaderName(reader)); + return(xmlStrdup(node->name)); +} + +/** + * xmlTextReaderConstLocalName: + * @reader: the xmlTextReaderPtr used + * + * The local name of the node. + * + * Returns the local name or NULL if not available, the + * string will be deallocated with the reader. + */ +const xmlChar * +xmlTextReaderConstLocalName(xmlTextReaderPtr reader) { + xmlNodePtr node; + if ((reader == NULL) || (reader->node == NULL)) + return(NULL); + if (reader->curnode != NULL) + node = reader->curnode; + else + node = reader->node; + if (node->type == XML_NAMESPACE_DECL) { + xmlNsPtr ns = (xmlNsPtr) node; + if (ns->prefix == NULL) + return(CONSTSTR(BAD_CAST "xmlns")); + else + return(ns->prefix); + } + if ((node->type != XML_ELEMENT_NODE) && + (node->type != XML_ATTRIBUTE_NODE)) + return(xmlTextReaderConstName(reader)); + return(node->name); +} + +/** + * xmlTextReaderName: + * @reader: the xmlTextReaderPtr used + * + * The qualified name of the node, equal to Prefix :LocalName. + * + * Returns the local name or NULL if not available + */ +xmlChar * +xmlTextReaderName(xmlTextReaderPtr reader) { + xmlNodePtr node; + xmlChar *ret; + + if ((reader == NULL) || (reader->node == NULL)) + return(NULL); + if (reader->curnode != NULL) + node = reader->curnode; + else + node = reader->node; + switch (node->type) { + case XML_ELEMENT_NODE: + case XML_ATTRIBUTE_NODE: + if ((node->ns == NULL) || + (node->ns->prefix == NULL)) + return(xmlStrdup(node->name)); + + ret = xmlStrdup(node->ns->prefix); + ret = xmlStrcat(ret, BAD_CAST ":"); + ret = xmlStrcat(ret, node->name); + return(ret); + case XML_TEXT_NODE: + return(xmlStrdup(BAD_CAST "#text")); + case XML_CDATA_SECTION_NODE: + return(xmlStrdup(BAD_CAST "#cdata-section")); + case XML_ENTITY_NODE: + case XML_ENTITY_REF_NODE: + return(xmlStrdup(node->name)); + case XML_PI_NODE: + return(xmlStrdup(node->name)); + case XML_COMMENT_NODE: + return(xmlStrdup(BAD_CAST "#comment")); + case XML_DOCUMENT_NODE: + case XML_HTML_DOCUMENT_NODE: +#ifdef LIBXML_DOCB_ENABLED + case XML_DOCB_DOCUMENT_NODE: +#endif + return(xmlStrdup(BAD_CAST "#document")); + case XML_DOCUMENT_FRAG_NODE: + return(xmlStrdup(BAD_CAST "#document-fragment")); + case XML_NOTATION_NODE: + return(xmlStrdup(node->name)); + case XML_DOCUMENT_TYPE_NODE: + case XML_DTD_NODE: + return(xmlStrdup(node->name)); + case XML_NAMESPACE_DECL: { + xmlNsPtr ns = (xmlNsPtr) node; + + ret = xmlStrdup(BAD_CAST "xmlns"); + if (ns->prefix == NULL) + return(ret); + ret = xmlStrcat(ret, BAD_CAST ":"); + ret = xmlStrcat(ret, ns->prefix); + return(ret); + } + + case XML_ELEMENT_DECL: + case XML_ATTRIBUTE_DECL: + case XML_ENTITY_DECL: + case XML_XINCLUDE_START: + case XML_XINCLUDE_END: + return(NULL); + } + return(NULL); +} + +/** + * xmlTextReaderConstName: + * @reader: the xmlTextReaderPtr used + * + * The qualified name of the node, equal to Prefix :LocalName. + * + * Returns the local name or NULL if not available, the string is + * deallocated with the reader. + */ +const xmlChar * +xmlTextReaderConstName(xmlTextReaderPtr reader) { + xmlNodePtr node; + + if ((reader == NULL) || (reader->node == NULL)) + return(NULL); + if (reader->curnode != NULL) + node = reader->curnode; + else + node = reader->node; + switch (node->type) { + case XML_ELEMENT_NODE: + case XML_ATTRIBUTE_NODE: + if ((node->ns == NULL) || + (node->ns->prefix == NULL)) + return(node->name); + return(CONSTQSTR(node->ns->prefix, node->name)); + case XML_TEXT_NODE: + return(CONSTSTR(BAD_CAST "#text")); + case XML_CDATA_SECTION_NODE: + return(CONSTSTR(BAD_CAST "#cdata-section")); + case XML_ENTITY_NODE: + case XML_ENTITY_REF_NODE: + return(CONSTSTR(node->name)); + case XML_PI_NODE: + return(CONSTSTR(node->name)); + case XML_COMMENT_NODE: + return(CONSTSTR(BAD_CAST "#comment")); + case XML_DOCUMENT_NODE: + case XML_HTML_DOCUMENT_NODE: +#ifdef LIBXML_DOCB_ENABLED + case XML_DOCB_DOCUMENT_NODE: +#endif + return(CONSTSTR(BAD_CAST "#document")); + case XML_DOCUMENT_FRAG_NODE: + return(CONSTSTR(BAD_CAST "#document-fragment")); + case XML_NOTATION_NODE: + return(CONSTSTR(node->name)); + case XML_DOCUMENT_TYPE_NODE: + case XML_DTD_NODE: + return(CONSTSTR(node->name)); + case XML_NAMESPACE_DECL: { + xmlNsPtr ns = (xmlNsPtr) node; + + if (ns->prefix == NULL) + return(CONSTSTR(BAD_CAST "xmlns")); + return(CONSTQSTR(BAD_CAST "xmlns", ns->prefix)); + } + + case XML_ELEMENT_DECL: + case XML_ATTRIBUTE_DECL: + case XML_ENTITY_DECL: + case XML_XINCLUDE_START: + case XML_XINCLUDE_END: + return(NULL); + } + return(NULL); +} + +/** + * xmlTextReaderPrefix: + * @reader: the xmlTextReaderPtr used + * + * A shorthand reference to the namespace associated with the node. + * + * Returns the prefix or NULL if not available + */ +xmlChar * +xmlTextReaderPrefix(xmlTextReaderPtr reader) { + xmlNodePtr node; + if ((reader == NULL) || (reader->node == NULL)) + return(NULL); + if (reader->curnode != NULL) + node = reader->curnode; + else + node = reader->node; + if (node->type == XML_NAMESPACE_DECL) { + xmlNsPtr ns = (xmlNsPtr) node; + if (ns->prefix == NULL) + return(NULL); + return(xmlStrdup(BAD_CAST "xmlns")); + } + if ((node->type != XML_ELEMENT_NODE) && + (node->type != XML_ATTRIBUTE_NODE)) + return(NULL); + if ((node->ns != NULL) && (node->ns->prefix != NULL)) + return(xmlStrdup(node->ns->prefix)); + return(NULL); +} + +/** + * xmlTextReaderConstPrefix: + * @reader: the xmlTextReaderPtr used + * + * A shorthand reference to the namespace associated with the node. + * + * Returns the prefix or NULL if not available, the string is deallocated + * with the reader. + */ +const xmlChar * +xmlTextReaderConstPrefix(xmlTextReaderPtr reader) { + xmlNodePtr node; + if ((reader == NULL) || (reader->node == NULL)) + return(NULL); + if (reader->curnode != NULL) + node = reader->curnode; + else + node = reader->node; + if (node->type == XML_NAMESPACE_DECL) { + xmlNsPtr ns = (xmlNsPtr) node; + if (ns->prefix == NULL) + return(NULL); + return(CONSTSTR(BAD_CAST "xmlns")); + } + if ((node->type != XML_ELEMENT_NODE) && + (node->type != XML_ATTRIBUTE_NODE)) + return(NULL); + if ((node->ns != NULL) && (node->ns->prefix != NULL)) + return(CONSTSTR(node->ns->prefix)); + return(NULL); +} + +/** + * xmlTextReaderNamespaceUri: + * @reader: the xmlTextReaderPtr used + * + * The URI defining the namespace associated with the node. + * + * Returns the namespace URI or NULL if not available + */ +xmlChar * +xmlTextReaderNamespaceUri(xmlTextReaderPtr reader) { + xmlNodePtr node; + if ((reader == NULL) || (reader->node == NULL)) + return(NULL); + if (reader->curnode != NULL) + node = reader->curnode; + else + node = reader->node; + if (node->type == XML_NAMESPACE_DECL) + return(xmlStrdup(BAD_CAST "http://www.w3.org/2000/xmlns/")); + if ((node->type != XML_ELEMENT_NODE) && + (node->type != XML_ATTRIBUTE_NODE)) + return(NULL); + if (node->ns != NULL) + return(xmlStrdup(node->ns->href)); + return(NULL); +} + +/** + * xmlTextReaderConstNamespaceUri: + * @reader: the xmlTextReaderPtr used + * + * The URI defining the namespace associated with the node. + * + * Returns the namespace URI or NULL if not available, the string + * will be deallocated with the reader + */ +const xmlChar * +xmlTextReaderConstNamespaceUri(xmlTextReaderPtr reader) { + xmlNodePtr node; + if ((reader == NULL) || (reader->node == NULL)) + return(NULL); + if (reader->curnode != NULL) + node = reader->curnode; + else + node = reader->node; + if (node->type == XML_NAMESPACE_DECL) + return(CONSTSTR(BAD_CAST "http://www.w3.org/2000/xmlns/")); + if ((node->type != XML_ELEMENT_NODE) && + (node->type != XML_ATTRIBUTE_NODE)) + return(NULL); + if (node->ns != NULL) + return(CONSTSTR(node->ns->href)); + return(NULL); +} + +/** + * xmlTextReaderBaseUri: + * @reader: the xmlTextReaderPtr used + * + * The base URI of the node. + * + * Returns the base URI or NULL if not available + */ +xmlChar * +xmlTextReaderBaseUri(xmlTextReaderPtr reader) { + if ((reader == NULL) || (reader->node == NULL)) + return(NULL); + return(xmlNodeGetBase(NULL, reader->node)); +} + +/** + * xmlTextReaderConstBaseUri: + * @reader: the xmlTextReaderPtr used + * + * The base URI of the node. + * + * Returns the base URI or NULL if not available, the string + * will be deallocated with the reader + */ +const xmlChar * +xmlTextReaderConstBaseUri(xmlTextReaderPtr reader) { + xmlChar *tmp; + const xmlChar *ret; + + if ((reader == NULL) || (reader->node == NULL)) + return(NULL); + tmp = xmlNodeGetBase(NULL, reader->node); + if (tmp == NULL) + return(NULL); + ret = CONSTSTR(tmp); + xmlFree(tmp); + return(ret); +} + +/** + * xmlTextReaderDepth: + * @reader: the xmlTextReaderPtr used + * + * The depth of the node in the tree. + * + * Returns the depth or -1 in case of error + */ +int +xmlTextReaderDepth(xmlTextReaderPtr reader) { + if (reader == NULL) + return(-1); + if (reader->node == NULL) + return(0); + + if (reader->curnode != NULL) { + if ((reader->curnode->type == XML_ATTRIBUTE_NODE) || + (reader->curnode->type == XML_NAMESPACE_DECL)) + return(reader->depth + 1); + return(reader->depth + 2); + } + return(reader->depth); +} + +/** + * xmlTextReaderHasAttributes: + * @reader: the xmlTextReaderPtr used + * + * Whether the node has attributes. + * + * Returns 1 if true, 0 if false, and -1 in case or error + */ +int +xmlTextReaderHasAttributes(xmlTextReaderPtr reader) { + xmlNodePtr node; + if (reader == NULL) + return(-1); + if (reader->node == NULL) + return(0); + if (reader->curnode != NULL) + node = reader->curnode; + else + node = reader->node; + + if ((node->type == XML_ELEMENT_NODE) && + ((node->properties != NULL) || (node->nsDef != NULL))) + return(1); + /* TODO: handle the xmlDecl */ + return(0); +} + +/** + * xmlTextReaderHasValue: + * @reader: the xmlTextReaderPtr used + * + * Whether the node can have a text value. + * + * Returns 1 if true, 0 if false, and -1 in case or error + */ +int +xmlTextReaderHasValue(xmlTextReaderPtr reader) { + xmlNodePtr node; + if (reader == NULL) + return(-1); + if (reader->node == NULL) + return(0); + if (reader->curnode != NULL) + node = reader->curnode; + else + node = reader->node; + + switch (node->type) { + case XML_ATTRIBUTE_NODE: + case XML_TEXT_NODE: + case XML_CDATA_SECTION_NODE: + case XML_PI_NODE: + case XML_COMMENT_NODE: + case XML_NAMESPACE_DECL: + return(1); + default: + break; + } + return(0); +} + +/** + * xmlTextReaderValue: + * @reader: the xmlTextReaderPtr used + * + * Provides the text value of the node if present + * + * Returns the string or NULL if not available. The result must be deallocated + * with xmlFree() + */ +xmlChar * +xmlTextReaderValue(xmlTextReaderPtr reader) { + xmlNodePtr node; + if (reader == NULL) + return(NULL); + if (reader->node == NULL) + return(NULL); + if (reader->curnode != NULL) + node = reader->curnode; + else + node = reader->node; + + switch (node->type) { + case XML_NAMESPACE_DECL: + return(xmlStrdup(((xmlNsPtr) node)->href)); + case XML_ATTRIBUTE_NODE:{ + xmlAttrPtr attr = (xmlAttrPtr) node; + + if (attr->parent != NULL) + return (xmlNodeListGetString + (attr->parent->doc, attr->children, 1)); + else + return (xmlNodeListGetString(NULL, attr->children, 1)); + break; + } + case XML_TEXT_NODE: + case XML_CDATA_SECTION_NODE: + case XML_PI_NODE: + case XML_COMMENT_NODE: + if (node->content != NULL) + return (xmlStrdup(node->content)); + default: + break; + } + return(NULL); +} + +/** + * xmlTextReaderConstValue: + * @reader: the xmlTextReaderPtr used + * + * Provides the text value of the node if present + * + * Returns the string or NULL if not available. The result will be + * deallocated on the next Read() operation. + */ +const xmlChar * +xmlTextReaderConstValue(xmlTextReaderPtr reader) { + xmlNodePtr node; + if (reader == NULL) + return(NULL); + if (reader->node == NULL) + return(NULL); + if (reader->curnode != NULL) + node = reader->curnode; + else + node = reader->node; + + switch (node->type) { + case XML_NAMESPACE_DECL: + return(((xmlNsPtr) node)->href); + case XML_ATTRIBUTE_NODE:{ + xmlAttrPtr attr = (xmlAttrPtr) node; + + if ((attr->children != NULL) && + (attr->children->type == XML_TEXT_NODE) && + (attr->children->next == NULL)) + return(attr->children->content); + else { + if (reader->buffer == NULL) + reader->buffer = xmlBufferCreateSize(100); + if (reader->buffer == NULL) { + xmlGenericError(xmlGenericErrorContext, + "xmlTextReaderSetup : malloc failed\n"); + return (NULL); + } + reader->buffer->use = 0; + xmlNodeBufGetContent(reader->buffer, node); + return(reader->buffer->content); + } + break; + } + case XML_TEXT_NODE: + case XML_CDATA_SECTION_NODE: + case XML_PI_NODE: + case XML_COMMENT_NODE: + return(node->content); + default: + break; + } + return(NULL); +} + +/** + * xmlTextReaderIsDefault: + * @reader: the xmlTextReaderPtr used + * + * Whether an Attribute node was generated from the default value + * defined in the DTD or schema. + * + * Returns 0 if not defaulted, 1 if defaulted, and -1 in case of error + */ +int +xmlTextReaderIsDefault(xmlTextReaderPtr reader) { + if (reader == NULL) + return(-1); + return(0); +} + +/** + * xmlTextReaderQuoteChar: + * @reader: the xmlTextReaderPtr used + * + * The quotation mark character used to enclose the value of an attribute. + * + * Returns " or ' and -1 in case of error + */ +int +xmlTextReaderQuoteChar(xmlTextReaderPtr reader) { + if (reader == NULL) + return(-1); + /* TODO maybe lookup the attribute value for " first */ + return((int) '"'); +} + +/** + * xmlTextReaderXmlLang: + * @reader: the xmlTextReaderPtr used + * + * The xml:lang scope within which the node resides. + * + * Returns the xml:lang value or NULL if none exists. + */ +xmlChar * +xmlTextReaderXmlLang(xmlTextReaderPtr reader) { + if (reader == NULL) + return(NULL); + if (reader->node == NULL) + return(NULL); + return(xmlNodeGetLang(reader->node)); +} + +/** + * xmlTextReaderConstXmlLang: + * @reader: the xmlTextReaderPtr used + * + * The xml:lang scope within which the node resides. + * + * Returns the xml:lang value or NULL if none exists. + */ +const xmlChar * +xmlTextReaderConstXmlLang(xmlTextReaderPtr reader) { + xmlChar *tmp; + const xmlChar *ret; + + if (reader == NULL) + return(NULL); + if (reader->node == NULL) + return(NULL); + tmp = xmlNodeGetLang(reader->node); + if (tmp == NULL) + return(NULL); + ret = CONSTSTR(tmp); + xmlFree(tmp); + return(ret); +} + +/** + * xmlTextReaderConstString: + * @reader: the xmlTextReaderPtr used + * @str: the string to intern. + * + * Get an interned string from the reader, allows for example to + * speedup string name comparisons + * + * Returns an interned copy of the string or NULL in case of error. The + * string will be deallocated with the reader. + */ +const xmlChar * +xmlTextReaderConstString(xmlTextReaderPtr reader, const xmlChar *str) { + if (reader == NULL) + return(NULL); + return(CONSTSTR(str)); +} + +/** + * xmlTextReaderNormalization: + * @reader: the xmlTextReaderPtr used + * + * The value indicating whether to normalize white space and attribute values. + * Since attribute value and end of line normalizations are a MUST in the XML + * specification only the value true is accepted. The broken bahaviour of + * accepting out of range character entities like � is of course not + * supported either. + * + * Returns 1 or -1 in case of error. + */ +int +xmlTextReaderNormalization(xmlTextReaderPtr reader) { + if (reader == NULL) + return(-1); + return(1); +} + +/************************************************************************ + * * + * Extensions to the base APIs * + * * + ************************************************************************/ + +/** + * xmlTextReaderSetParserProp: + * @reader: the xmlTextReaderPtr used + * @prop: the xmlParserProperties to set + * @value: usually 0 or 1 to (de)activate it + * + * Change the parser processing behaviour by changing some of its internal + * properties. Note that some properties can only be changed before any + * read has been done. + * + * Returns 0 if the call was successful, or -1 in case of error + */ +int +xmlTextReaderSetParserProp(xmlTextReaderPtr reader, int prop, int value) { + xmlParserProperties p = (xmlParserProperties) prop; + xmlParserCtxtPtr ctxt; + + if ((reader == NULL) || (reader->ctxt == NULL)) + return(-1); + ctxt = reader->ctxt; + + switch (p) { + case XML_PARSER_LOADDTD: + if (value != 0) { + if (ctxt->loadsubset == 0) { + if (reader->mode != XML_TEXTREADER_MODE_INITIAL) + return(-1); + ctxt->loadsubset = XML_DETECT_IDS; + } + } else { + ctxt->loadsubset = 0; + } + return(0); + case XML_PARSER_DEFAULTATTRS: + if (value != 0) { + ctxt->loadsubset |= XML_COMPLETE_ATTRS; + } else { + if (ctxt->loadsubset & XML_COMPLETE_ATTRS) + ctxt->loadsubset -= XML_COMPLETE_ATTRS; + } + return(0); + case XML_PARSER_VALIDATE: + if (value != 0) { + ctxt->validate = 1; + reader->validate = XML_TEXTREADER_VALIDATE_DTD; + } else { + ctxt->validate = 0; + } + return(0); + case XML_PARSER_SUBST_ENTITIES: + if (value != 0) { + ctxt->replaceEntities = 1; + } else { + ctxt->replaceEntities = 0; + } + return(0); + } + return(-1); +} + +/** + * xmlTextReaderGetParserProp: + * @reader: the xmlTextReaderPtr used + * @prop: the xmlParserProperties to get + * + * Read the parser internal property. + * + * Returns the value, usually 0 or 1, or -1 in case of error. + */ +int +xmlTextReaderGetParserProp(xmlTextReaderPtr reader, int prop) { + xmlParserProperties p = (xmlParserProperties) prop; + xmlParserCtxtPtr ctxt; + + if ((reader == NULL) || (reader->ctxt == NULL)) + return(-1); + ctxt = reader->ctxt; + + switch (p) { + case XML_PARSER_LOADDTD: + if ((ctxt->loadsubset != 0) || (ctxt->validate != 0)) + return(1); + return(0); + case XML_PARSER_DEFAULTATTRS: + if (ctxt->loadsubset & XML_COMPLETE_ATTRS) + return(1); + return(0); + case XML_PARSER_VALIDATE: + return(reader->validate); + case XML_PARSER_SUBST_ENTITIES: + return(ctxt->replaceEntities); + } + return(-1); +} + + +/** + * xmlTextReaderGetParserLineNumber: + * @reader: the user data (XML reader context) + * + * Provide the line number of the current parsing point. + * + * Returns an int or 0 if not available + */ +int +xmlTextReaderGetParserLineNumber(xmlTextReaderPtr reader) +{ + if ((reader == NULL) || (reader->ctxt == NULL) || + (reader->ctxt->input == NULL)) { + return (0); + } + return (reader->ctxt->input->line); +} + +/** + * xmlTextReaderGetParserColumnNumber: + * @reader: the user data (XML reader context) + * + * Provide the column number of the current parsing point. + * + * Returns an int or 0 if not available + */ +int +xmlTextReaderGetParserColumnNumber(xmlTextReaderPtr reader) +{ + if ((reader == NULL) || (reader->ctxt == NULL) || + (reader->ctxt->input == NULL)) { + return (0); + } + return (reader->ctxt->input->col); +} + +/** + * xmlTextReaderCurrentNode: + * @reader: the xmlTextReaderPtr used + * + * Hacking interface allowing to get the xmlNodePtr correponding to the + * current node being accessed by the xmlTextReader. This is dangerous + * because the underlying node may be destroyed on the next Reads. + * + * Returns the xmlNodePtr or NULL in case of error. + */ +xmlNodePtr +xmlTextReaderCurrentNode(xmlTextReaderPtr reader) { + if (reader == NULL) + return(NULL); + + if (reader->curnode != NULL) + return(reader->curnode); + return(reader->node); +} + +/** + * xmlTextReaderPreserve: + * @reader: the xmlTextReaderPtr used + * + * This tells the XML Reader to preserve the current node. + * The caller must also use xmlTextReaderCurrentDoc() to + * keep an handle on the resulting document once parsing has finished + * + * Returns the xmlNodePtr or NULL in case of error. + */ +xmlNodePtr +xmlTextReaderPreserve(xmlTextReaderPtr reader) { + xmlNodePtr cur, parent; + + if (reader == NULL) + return(NULL); + + if (reader->curnode != NULL) + cur = reader->curnode; + else + cur = reader->node; + if (cur == NULL) + return(NULL); + + if ((cur->type != XML_DOCUMENT_NODE) && (cur->type != XML_DTD_NODE)) { + cur->extra |= NODE_IS_PRESERVED; + cur->extra |= NODE_IS_SPRESERVED; + } + reader->preserves++; + + parent = cur->parent;; + while (parent != NULL) { + if (parent->type == XML_ELEMENT_NODE) + parent->extra |= NODE_IS_PRESERVED; + parent = parent->parent; + } + return(cur); +} + +#ifdef LIBXML_PATTERN_ENABLED +/** + * xmlTextReaderPreservePattern: + * @reader: the xmlTextReaderPtr used + * @pattern: an XPath subset pattern + * @namespaces: the prefix definitions, array of [URI, prefix] or NULL + * + * This tells the XML Reader to preserve all nodes matched by the + * pattern. The caller must also use xmlTextReaderCurrentDoc() to + * keep an handle on the resulting document once parsing has finished + * + * Returns a positive number in case of success and -1 in case of error + */ +int +xmlTextReaderPreservePattern(xmlTextReaderPtr reader, const xmlChar *pattern, + const xmlChar **namespaces) +{ + xmlPatternPtr comp; + + if ((reader == NULL) || (pattern == NULL)) + return(-1); + + comp = xmlPatterncompile(pattern, reader->dict, 0, namespaces); + if (comp == NULL) + return(-1); + + if (reader->patternMax <= 0) { + reader->patternMax = 4; + reader->patternTab = (xmlPatternPtr *) xmlMalloc(reader->patternMax * + sizeof(reader->patternTab[0])); + if (reader->patternTab == NULL) { + xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n"); + return (-1); + } + } + if (reader->patternNr >= reader->patternMax) { + xmlPatternPtr *tmp; + reader->patternMax *= 2; + tmp = (xmlPatternPtr *) xmlRealloc(reader->patternTab, + reader->patternMax * + sizeof(reader->patternTab[0])); + if (tmp == NULL) { + xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n"); + reader->patternMax /= 2; + return (-1); + } + reader->patternTab = tmp; + } + reader->patternTab[reader->patternNr] = comp; + return(reader->patternNr++); +} +#endif + +/** + * xmlTextReaderCurrentDoc: + * @reader: the xmlTextReaderPtr used + * + * Hacking interface allowing to get the xmlDocPtr correponding to the + * current document being accessed by the xmlTextReader. + * NOTE: as a result of this call, the reader will not destroy the + * associated XML document and calling xmlFreeDoc() on the result + * is needed once the reader parsing has finished. + * + * Returns the xmlDocPtr or NULL in case of error. + */ +xmlDocPtr +xmlTextReaderCurrentDoc(xmlTextReaderPtr reader) { + if (reader == NULL) + return(NULL); + if (reader->doc != NULL) + return(reader->doc); + if ((reader == NULL) || (reader->ctxt == NULL) || + (reader->ctxt->myDoc == NULL)) + return(NULL); + + reader->preserve = 1; + return(reader->ctxt->myDoc); +} + +#ifdef LIBXML_SCHEMAS_ENABLED + +static char * +xmlTextReaderBuildMessage(const char *msg, va_list ap); + +static void XMLCDECL +xmlTextReaderValidityError(void *ctxt, const char *msg, ...); + +static void XMLCDECL +xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...); + +static void XMLCDECL xmlTextReaderValidityErrorRelay(void *ctx, const char *msg, ...) +{ + xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx; + char * str; + va_list ap; + + va_start(ap,msg); + str = xmlTextReaderBuildMessage(msg,ap); + if (!reader->errorFunc) { + xmlTextReaderValidityError(ctx, "%s", str); + } else { + reader->errorFunc(reader->errorFuncArg, str, XML_PARSER_SEVERITY_VALIDITY_ERROR, NULL /* locator */); + } + if (str != NULL) + xmlFree(str); + va_end(ap); +} + +static void XMLCDECL xmlTextReaderValidityWarningRelay(void *ctx, const char *msg, ...) +{ + xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx; + char * str; + va_list ap; + + va_start(ap,msg); + str = xmlTextReaderBuildMessage(msg,ap); + if (!reader->errorFunc) { + xmlTextReaderValidityWarning(ctx, "%s", str); + } else { + reader->errorFunc(reader->errorFuncArg, str, XML_PARSER_SEVERITY_VALIDITY_WARNING, NULL /* locator */); + } + if (str != NULL) + xmlFree(str); + va_end(ap); +} + +static void +xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error); + +static void xmlTextReaderValidityStructuredRelay(void * userData, xmlErrorPtr error) +{ + xmlTextReaderPtr reader = (xmlTextReaderPtr) userData; + + if (reader->sErrorFunc) { + reader->sErrorFunc(reader->errorFuncArg, error); + } else { + xmlTextReaderStructuredError(reader, error); + } +} + +/** + * xmlTextReaderRelaxNGSetSchema: + * @reader: the xmlTextReaderPtr used + * @schema: a precompiled RelaxNG schema + * + * Use RelaxNG to validate the document as it is processed. + * Activation is only possible before the first Read(). + * if @schema is NULL, then RelaxNG validation is desactivated. + @ The @schema should not be freed until the reader is deallocated + * or its use has been deactivated. + * + * Returns 0 in case the RelaxNG validation could be (des)activated and + * -1 in case of error. + */ +int +xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, xmlRelaxNGPtr schema) { + if (reader == NULL) + return(-1); + if (schema == NULL) { + if (reader->rngSchemas != NULL) { + xmlRelaxNGFree(reader->rngSchemas); + reader->rngSchemas = NULL; + } + if (reader->rngValidCtxt != NULL) { + xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt); + reader->rngValidCtxt = NULL; + } + return(0); + } + if (reader->mode != XML_TEXTREADER_MODE_INITIAL) + return(-1); + if (reader->rngSchemas != NULL) { + xmlRelaxNGFree(reader->rngSchemas); + reader->rngSchemas = NULL; + } + if (reader->rngValidCtxt != NULL) { + xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt); + reader->rngValidCtxt = NULL; + } + reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(schema); + if (reader->rngValidCtxt == NULL) + return(-1); + if (reader->errorFunc != NULL) { + xmlRelaxNGSetValidErrors(reader->rngValidCtxt, + xmlTextReaderValidityErrorRelay, + xmlTextReaderValidityWarningRelay, + reader); + } + if (reader->sErrorFunc != NULL) { + xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, + xmlTextReaderValidityStructuredRelay, + reader); + } + reader->rngValidErrors = 0; + reader->rngFullNode = NULL; + reader->validate = XML_TEXTREADER_VALIDATE_RNG; + return(0); +} + +/** + * xmlTextReaderSetSchema: + * @reader: the xmlTextReaderPtr used + * @schema: a precompiled Schema schema + * + * Use XSD Schema to validate the document as it is processed. + * Activation is only possible before the first Read(). + * if @schema is NULL, then Schema validation is desactivated. + @ The @schema should not be freed until the reader is deallocated + * or its use has been deactivated. + * + * Returns 0 in case the Schema validation could be (des)activated and + * -1 in case of error. + */ +int +xmlTextReaderSetSchema(xmlTextReaderPtr reader, xmlSchemaPtr schema) { + if (reader == NULL) + return(-1); + if (schema == NULL) { + if (reader->xsdPlug != NULL) { + xmlSchemaSAXUnplug(reader->xsdPlug); + reader->xsdPlug = NULL; + } + if (reader->xsdValidCtxt != NULL) { + if (! reader->xsdPreserveCtxt) + xmlSchemaFreeValidCtxt(reader->xsdValidCtxt); + reader->xsdValidCtxt = NULL; + } + reader->xsdPreserveCtxt = 0; + if (reader->xsdSchemas != NULL) { + xmlSchemaFree(reader->xsdSchemas); + reader->xsdSchemas = NULL; + } + return(0); + } + if (reader->mode != XML_TEXTREADER_MODE_INITIAL) + return(-1); + if (reader->xsdPlug != NULL) { + xmlSchemaSAXUnplug(reader->xsdPlug); + reader->xsdPlug = NULL; + } + if (reader->xsdValidCtxt != NULL) { + if (! reader->xsdPreserveCtxt) + xmlSchemaFreeValidCtxt(reader->xsdValidCtxt); + reader->xsdValidCtxt = NULL; + } + reader->xsdPreserveCtxt = 0; + if (reader->xsdSchemas != NULL) { + xmlSchemaFree(reader->xsdSchemas); + reader->xsdSchemas = NULL; + } + reader->xsdValidCtxt = xmlSchemaNewValidCtxt(schema); + if (reader->xsdValidCtxt == NULL) { + xmlSchemaFree(reader->xsdSchemas); + reader->xsdSchemas = NULL; + return(-1); + } + reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt, + &(reader->ctxt->sax), + &(reader->ctxt->userData)); + if (reader->xsdPlug == NULL) { + xmlSchemaFree(reader->xsdSchemas); + reader->xsdSchemas = NULL; + xmlSchemaFreeValidCtxt(reader->xsdValidCtxt); + reader->xsdValidCtxt = NULL; + return(-1); + } + if (reader->errorFunc != NULL) { + xmlSchemaSetValidErrors(reader->xsdValidCtxt, + xmlTextReaderValidityErrorRelay, + xmlTextReaderValidityWarningRelay, + reader); + } + if (reader->sErrorFunc != NULL) { + xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, + xmlTextReaderValidityStructuredRelay, + reader); + } + reader->xsdValidErrors = 0; + reader->validate = XML_TEXTREADER_VALIDATE_XSD; + return(0); +} + +/** + * xmlTextReaderRelaxNGValidate: + * @reader: the xmlTextReaderPtr used + * @rng: the path to a RelaxNG schema or NULL + * + * Use RelaxNG to validate the document as it is processed. + * Activation is only possible before the first Read(). + * if @rng is NULL, then RelaxNG validation is desactivated. + * + * Returns 0 in case the RelaxNG validation could be (des)activated and + * -1 in case of error. + */ +int +xmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader, const char *rng) { + xmlRelaxNGParserCtxtPtr ctxt; + + if (reader == NULL) + return(-1); + + if (rng == NULL) { + if (reader->rngValidCtxt != NULL) { + xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt); + reader->rngValidCtxt = NULL; + } + if (reader->rngSchemas != NULL) { + xmlRelaxNGFree(reader->rngSchemas); + reader->rngSchemas = NULL; + } + return(0); + } + if (reader->mode != XML_TEXTREADER_MODE_INITIAL) + return(-1); + if (reader->rngSchemas != NULL) { + xmlRelaxNGFree(reader->rngSchemas); + reader->rngSchemas = NULL; + } + if (reader->rngValidCtxt != NULL) { + xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt); + reader->rngValidCtxt = NULL; + } + ctxt = xmlRelaxNGNewParserCtxt(rng); + if (reader->errorFunc != NULL) { + xmlRelaxNGSetParserErrors(ctxt, + xmlTextReaderValidityErrorRelay, + xmlTextReaderValidityWarningRelay, + reader); + } + if (reader->sErrorFunc != NULL) { + xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, + xmlTextReaderValidityStructuredRelay, + reader); + } + reader->rngSchemas = xmlRelaxNGParse(ctxt); + xmlRelaxNGFreeParserCtxt(ctxt); + if (reader->rngSchemas == NULL) + return(-1); + reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(reader->rngSchemas); + if (reader->rngValidCtxt == NULL) { + xmlRelaxNGFree(reader->rngSchemas); + reader->rngSchemas = NULL; + return(-1); + } + if (reader->errorFunc != NULL) { + xmlRelaxNGSetValidErrors(reader->rngValidCtxt, + xmlTextReaderValidityErrorRelay, + xmlTextReaderValidityWarningRelay, + reader); + } + if (reader->sErrorFunc != NULL) { + xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, + xmlTextReaderValidityStructuredRelay, + reader); + } + reader->rngValidErrors = 0; + reader->rngFullNode = NULL; + reader->validate = XML_TEXTREADER_VALIDATE_RNG; + return(0); +} + +/** + * xmlTextReaderSchemaValidateInternal: + * @reader: the xmlTextReaderPtr used + * @xsd: the path to a W3C XSD schema or NULL + * @ctxt: the XML Schema validation context or NULL + * @options: options (not used yet) + * + * Validate the document as it is processed using XML Schema. + * Activation is only possible before the first Read(). + * If both @xsd and @ctxt are NULL then XML Schema validation is deactivated. + * + * Returns 0 in case the schemas validation could be (de)activated and + * -1 in case of error. + */ +static int +xmlTextReaderSchemaValidateInternal(xmlTextReaderPtr reader, + const char *xsd, + xmlSchemaValidCtxtPtr ctxt, + int options ATTRIBUTE_UNUSED) +{ + if (reader == NULL) + return(-1); + + if ((xsd != NULL) && (ctxt != NULL)) + return(-1); + + if (((xsd != NULL) || (ctxt != NULL)) && + ((reader->mode != XML_TEXTREADER_MODE_INITIAL) || + (reader->ctxt == NULL))) + return(-1); + + /* Cleanup previous validation stuff. */ + if (reader->xsdPlug != NULL) { + xmlSchemaSAXUnplug(reader->xsdPlug); + reader->xsdPlug = NULL; + } + if (reader->xsdValidCtxt != NULL) { + if (! reader->xsdPreserveCtxt) + xmlSchemaFreeValidCtxt(reader->xsdValidCtxt); + reader->xsdValidCtxt = NULL; + } + reader->xsdPreserveCtxt = 0; + if (reader->xsdSchemas != NULL) { + xmlSchemaFree(reader->xsdSchemas); + reader->xsdSchemas = NULL; + } + + if ((xsd == NULL) && (ctxt == NULL)) { + /* We just want to deactivate the validation, so get out. */ + return(0); + } + + if (xsd != NULL) { + xmlSchemaParserCtxtPtr pctxt; + /* Parse the schema and create validation environment. */ + pctxt = xmlSchemaNewParserCtxt(xsd); + if (reader->errorFunc != NULL) { + xmlSchemaSetParserErrors(pctxt, + xmlTextReaderValidityErrorRelay, + xmlTextReaderValidityWarningRelay, + reader); + } + reader->xsdSchemas = xmlSchemaParse(pctxt); + xmlSchemaFreeParserCtxt(pctxt); + if (reader->xsdSchemas == NULL) + return(-1); + reader->xsdValidCtxt = xmlSchemaNewValidCtxt(reader->xsdSchemas); + if (reader->xsdValidCtxt == NULL) { + xmlSchemaFree(reader->xsdSchemas); + reader->xsdSchemas = NULL; + return(-1); + } + reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt, + &(reader->ctxt->sax), + &(reader->ctxt->userData)); + if (reader->xsdPlug == NULL) { + xmlSchemaFree(reader->xsdSchemas); + reader->xsdSchemas = NULL; + xmlSchemaFreeValidCtxt(reader->xsdValidCtxt); + reader->xsdValidCtxt = NULL; + return(-1); + } + } else { + /* Use the given validation context. */ + reader->xsdValidCtxt = ctxt; + reader->xsdPreserveCtxt = 1; + reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt, + &(reader->ctxt->sax), + &(reader->ctxt->userData)); + if (reader->xsdPlug == NULL) { + reader->xsdValidCtxt = NULL; + reader->xsdPreserveCtxt = 0; + return(-1); + } + } + /* + * Redirect the validation context's error channels to use + * the reader channels. + * TODO: In case the user provides the validation context we + * could make this redirection optional. + */ + if (reader->errorFunc != NULL) { + xmlSchemaSetValidErrors(reader->xsdValidCtxt, + xmlTextReaderValidityErrorRelay, + xmlTextReaderValidityWarningRelay, + reader); + } + if (reader->sErrorFunc != NULL) { + xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, + xmlTextReaderValidityStructuredRelay, + reader); + } + reader->xsdValidErrors = 0; + reader->validate = XML_TEXTREADER_VALIDATE_XSD; + return(0); +} + +/** + * xmlTextReaderSchemaValidateCtxt: + * @reader: the xmlTextReaderPtr used + * @ctxt: the XML Schema validation context or NULL + * @options: options (not used yet) + * + * Use W3C XSD schema context to validate the document as it is processed. + * Activation is only possible before the first Read(). + * If @ctxt is NULL, then XML Schema validation is deactivated. + * + * Returns 0 in case the schemas validation could be (de)activated and + * -1 in case of error. + */ +int +xmlTextReaderSchemaValidateCtxt(xmlTextReaderPtr reader, + xmlSchemaValidCtxtPtr ctxt, + int options) +{ + return(xmlTextReaderSchemaValidateInternal(reader, NULL, ctxt, options)); +} + +/** + * xmlTextReaderSchemaValidate: + * @reader: the xmlTextReaderPtr used + * @xsd: the path to a W3C XSD schema or NULL + * + * Use W3C XSD schema to validate the document as it is processed. + * Activation is only possible before the first Read(). + * If @xsd is NULL, then XML Schema validation is deactivated. + * + * Returns 0 in case the schemas validation could be (de)activated and + * -1 in case of error. + */ +int +xmlTextReaderSchemaValidate(xmlTextReaderPtr reader, const char *xsd) +{ + return(xmlTextReaderSchemaValidateInternal(reader, xsd, NULL, 0)); +} +#endif + +/** + * xmlTextReaderIsNamespaceDecl: + * @reader: the xmlTextReaderPtr used + * + * Determine whether the current node is a namespace declaration + * rather than a regular attribute. + * + * Returns 1 if the current node is a namespace declaration, 0 if it + * is a regular attribute or other type of node, or -1 in case of + * error. + */ +int +xmlTextReaderIsNamespaceDecl(xmlTextReaderPtr reader) { + xmlNodePtr node; + if (reader == NULL) + return(-1); + if (reader->node == NULL) + return(-1); + if (reader->curnode != NULL) + node = reader->curnode; + else + node = reader->node; + + if (XML_NAMESPACE_DECL == node->type) + return(1); + else + return(0); +} + +/** + * xmlTextReaderConstXmlVersion: + * @reader: the xmlTextReaderPtr used + * + * Determine the XML version of the document being read. + * + * Returns a string containing the XML version of the document or NULL + * in case of error. The string is deallocated with the reader. + */ +const xmlChar * +xmlTextReaderConstXmlVersion(xmlTextReaderPtr reader) { + xmlDocPtr doc = NULL; + if (reader == NULL) + return(NULL); + if (reader->doc != NULL) + doc = reader->doc; + else if (reader->ctxt != NULL) + doc = reader->ctxt->myDoc; + if (doc == NULL) + return(NULL); + + if (doc->version == NULL) + return(NULL); + else + return(CONSTSTR(doc->version)); +} + +/** + * xmlTextReaderStandalone: + * @reader: the xmlTextReaderPtr used + * + * Determine the standalone status of the document being read. + * + * Returns 1 if the document was declared to be standalone, 0 if it + * was declared to be not standalone, or -1 if the document did not + * specify its standalone status or in case of error. + */ +int +xmlTextReaderStandalone(xmlTextReaderPtr reader) { + xmlDocPtr doc = NULL; + if (reader == NULL) + return(-1); + if (reader->doc != NULL) + doc = reader->doc; + else if (reader->ctxt != NULL) + doc = reader->ctxt->myDoc; + if (doc == NULL) + return(-1); + + return(doc->standalone); +} + +/************************************************************************ + * * + * Error Handling Extensions * + * * + ************************************************************************/ + +/* helper to build a xmlMalloc'ed string from a format and va_list */ +static char * +xmlTextReaderBuildMessage(const char *msg, va_list ap) { + int size; + int chars; + char *larger; + char *str; + + str = (char *) xmlMallocAtomic(150); + if (str == NULL) { + xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n"); + return NULL; + } + + size = 150; + + while (1) { + chars = vsnprintf(str, size, msg, ap); + if ((chars > -1) && (chars < size)) + break; + if (chars > -1) + size += chars + 1; + else + size += 100; + if ((larger = (char *) xmlRealloc(str, size)) == NULL) { + xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n"); + xmlFree(str); + return NULL; + } + str = larger; + } + + return str; +} + +/** + * xmlTextReaderLocatorLineNumber: + * @locator: the xmlTextReaderLocatorPtr used + * + * Obtain the line number for the given locator. + * + * Returns the line number or -1 in case of error. + */ +int +xmlTextReaderLocatorLineNumber(xmlTextReaderLocatorPtr locator) { + /* we know that locator is a xmlParserCtxtPtr */ + xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator; + int ret = -1; + + if (locator == NULL) + return(-1); + if (ctx->node != NULL) { + ret = xmlGetLineNo(ctx->node); + } + else { + /* inspired from error.c */ + xmlParserInputPtr input; + input = ctx->input; + if ((input->filename == NULL) && (ctx->inputNr > 1)) + input = ctx->inputTab[ctx->inputNr - 2]; + if (input != NULL) { + ret = input->line; + } + else { + ret = -1; + } + } + + return ret; +} + +/** + * xmlTextReaderLocatorBaseURI: + * @locator: the xmlTextReaderLocatorPtr used + * + * Obtain the base URI for the given locator. + * + * Returns the base URI or NULL in case of error. + */ +xmlChar * +xmlTextReaderLocatorBaseURI(xmlTextReaderLocatorPtr locator) { + /* we know that locator is a xmlParserCtxtPtr */ + xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator; + xmlChar *ret = NULL; + + if (locator == NULL) + return(NULL); + if (ctx->node != NULL) { + ret = xmlNodeGetBase(NULL,ctx->node); + } + else { + /* inspired from error.c */ + xmlParserInputPtr input; + input = ctx->input; + if ((input->filename == NULL) && (ctx->inputNr > 1)) + input = ctx->inputTab[ctx->inputNr - 2]; + if (input != NULL) { + ret = xmlStrdup(BAD_CAST input->filename); + } + else { + ret = NULL; + } + } + + return ret; +} + +static void +xmlTextReaderGenericError(void *ctxt, xmlParserSeverities severity, char *str) { + xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)ctxt; + xmlTextReaderPtr reader = (xmlTextReaderPtr)ctx->_private; + + if (str != NULL) { + if (reader->errorFunc) + reader->errorFunc(reader->errorFuncArg, + str, + severity, + (xmlTextReaderLocatorPtr)ctx); + xmlFree(str); + } +} + +static void +xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error) { + xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt; + xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private; + + if (error && reader->sErrorFunc) { + reader->sErrorFunc(reader->errorFuncArg, + (xmlErrorPtr) error); + } +} + +static void XMLCDECL +xmlTextReaderError(void *ctxt, const char *msg, ...) { + va_list ap; + + va_start(ap,msg); + xmlTextReaderGenericError(ctxt, + XML_PARSER_SEVERITY_ERROR, + xmlTextReaderBuildMessage(msg,ap)); + va_end(ap); + +} + +static void XMLCDECL +xmlTextReaderWarning(void *ctxt, const char *msg, ...) { + va_list ap; + + va_start(ap,msg); + xmlTextReaderGenericError(ctxt, + XML_PARSER_SEVERITY_WARNING, + xmlTextReaderBuildMessage(msg,ap)); + va_end(ap); +} + +static void XMLCDECL +xmlTextReaderValidityError(void *ctxt, const char *msg, ...) { + va_list ap; + int len = xmlStrlen((const xmlChar *) msg); + + if ((len > 1) && (msg[len - 2] != ':')) { + /* + * some callbacks only report locator information: + * skip them (mimicking behaviour in error.c) + */ + va_start(ap,msg); + xmlTextReaderGenericError(ctxt, + XML_PARSER_SEVERITY_VALIDITY_ERROR, + xmlTextReaderBuildMessage(msg,ap)); + va_end(ap); + } +} + +static void XMLCDECL +xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...) { + va_list ap; + int len = xmlStrlen((const xmlChar *) msg); + + if ((len != 0) && (msg[len - 1] != ':')) { + /* + * some callbacks only report locator information: + * skip them (mimicking behaviour in error.c) + */ + va_start(ap,msg); + xmlTextReaderGenericError(ctxt, + XML_PARSER_SEVERITY_VALIDITY_WARNING, + xmlTextReaderBuildMessage(msg,ap)); + va_end(ap); + } +} + +/** + * xmlTextReaderSetErrorHandler: + * @reader: the xmlTextReaderPtr used + * @f: the callback function to call on error and warnings + * @arg: a user argument to pass to the callback function + * + * Register a callback function that will be called on error and warnings. + * + * If @f is NULL, the default error and warning handlers are restored. + */ +void +xmlTextReaderSetErrorHandler(xmlTextReaderPtr reader, + xmlTextReaderErrorFunc f, + void *arg) { + if (f != NULL) { + reader->ctxt->sax->error = xmlTextReaderError; + reader->ctxt->sax->serror = NULL; + reader->ctxt->vctxt.error = xmlTextReaderValidityError; + reader->ctxt->sax->warning = xmlTextReaderWarning; + reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning; + reader->errorFunc = f; + reader->sErrorFunc = NULL; + reader->errorFuncArg = arg; +#ifdef LIBXML_SCHEMAS_ENABLED + if (reader->rngValidCtxt) { + xmlRelaxNGSetValidErrors(reader->rngValidCtxt, + xmlTextReaderValidityErrorRelay, + xmlTextReaderValidityWarningRelay, + reader); + xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL, reader); + } + if (reader->xsdValidCtxt) { + xmlSchemaSetValidErrors(reader->xsdValidCtxt, + xmlTextReaderValidityErrorRelay, + xmlTextReaderValidityWarningRelay, + reader); + xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL, reader); + } +#endif + } + else { + /* restore defaults */ + reader->ctxt->sax->error = xmlParserError; + reader->ctxt->vctxt.error = xmlParserValidityError; + reader->ctxt->sax->warning = xmlParserWarning; + reader->ctxt->vctxt.warning = xmlParserValidityWarning; + reader->errorFunc = NULL; + reader->sErrorFunc = NULL; + reader->errorFuncArg = NULL; +#ifdef LIBXML_SCHEMAS_ENABLED + if (reader->rngValidCtxt) { + xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL, reader); + xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL, reader); + } + if (reader->xsdValidCtxt) { + xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL, reader); + xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL, reader); + } +#endif + } +} + +/** +* xmlTextReaderSetStructuredErrorHandler: + * @reader: the xmlTextReaderPtr used + * @f: the callback function to call on error and warnings + * @arg: a user argument to pass to the callback function + * + * Register a callback function that will be called on error and warnings. + * + * If @f is NULL, the default error and warning handlers are restored. + */ +void +xmlTextReaderSetStructuredErrorHandler(xmlTextReaderPtr reader, + xmlStructuredErrorFunc f, + void *arg) { + if (f != NULL) { + reader->ctxt->sax->error = NULL; + reader->ctxt->sax->serror = xmlTextReaderStructuredError; + reader->ctxt->vctxt.error = xmlTextReaderValidityError; + reader->ctxt->sax->warning = xmlTextReaderWarning; + reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning; + reader->sErrorFunc = f; + reader->errorFunc = NULL; + reader->errorFuncArg = arg; +#ifdef LIBXML_SCHEMAS_ENABLED + if (reader->rngValidCtxt) { + xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL, reader); + xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, + xmlTextReaderValidityStructuredRelay, + reader); + } + if (reader->xsdValidCtxt) { + xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL, reader); + xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, + xmlTextReaderValidityStructuredRelay, + reader); + } +#endif + } + else { + /* restore defaults */ + reader->ctxt->sax->error = xmlParserError; + reader->ctxt->sax->serror = NULL; + reader->ctxt->vctxt.error = xmlParserValidityError; + reader->ctxt->sax->warning = xmlParserWarning; + reader->ctxt->vctxt.warning = xmlParserValidityWarning; + reader->errorFunc = NULL; + reader->sErrorFunc = NULL; + reader->errorFuncArg = NULL; +#ifdef LIBXML_SCHEMAS_ENABLED + if (reader->rngValidCtxt) { + xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL, reader); + xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL, reader); + } + if (reader->xsdValidCtxt) { + xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL, reader); + xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL, reader); + } +#endif + } +} + +/** + * xmlTextReaderIsValid: + * @reader: the xmlTextReaderPtr used + * + * Retrieve the validity status from the parser context + * + * Returns the flag value 1 if valid, 0 if no, and -1 in case of error + */ +int +xmlTextReaderIsValid(xmlTextReaderPtr reader) { + if (reader == NULL) return(-1); +#ifdef LIBXML_SCHEMAS_ENABLED + if (reader->validate == XML_TEXTREADER_VALIDATE_RNG) + return(reader->rngValidErrors == 0); + if (reader->validate == XML_TEXTREADER_VALIDATE_XSD) + return(reader->xsdValidErrors == 0); +#endif + if ((reader->ctxt != NULL) && (reader->ctxt->validate == 1)) + return(reader->ctxt->valid); + return(0); +} + +/** + * xmlTextReaderGetErrorHandler: + * @reader: the xmlTextReaderPtr used + * @f: the callback function or NULL is no callback has been registered + * @arg: a user argument + * + * Retrieve the error callback function and user argument. + */ +void +xmlTextReaderGetErrorHandler(xmlTextReaderPtr reader, + xmlTextReaderErrorFunc *f, + void **arg) { + if (f != NULL) *f = reader->errorFunc; + if (arg != NULL) *arg = reader->errorFuncArg; +} + + +/************************************************************************ + * * + * New set (2.6.0) of simpler and more flexible APIs * + * * + ************************************************************************/ + +/** + * xmlTextReaderSetup: + * @reader: an XML reader + * @URL: the base URL to use for the document + * @encoding: the document encoding, or NULL + * @options: a combination of xmlParserOption + * @reuse: keep the context for reuse + * + * Setup an XML reader with new options + * + * Returns 0 in case of success and -1 in case of error. + */ +static int +xmlTextReaderSetup(xmlTextReaderPtr reader, + xmlParserInputBufferPtr input, const char *URL, + const char *encoding, int options) +{ + if (reader == NULL) + return (-1); + + /* + * we force the generation of compact text nodes on the reader + * since usr applications should never modify the tree + */ + options |= XML_PARSE_COMPACT; + + reader->doc = NULL; + reader->entNr = 0; + reader->parserFlags = options; + reader->validate = XML_TEXTREADER_NOT_VALIDATE; + if ((input != NULL) && (reader->input != NULL) && + (reader->allocs & XML_TEXTREADER_INPUT)) { + xmlFreeParserInputBuffer(reader->input); + reader->input = NULL; + reader->allocs -= XML_TEXTREADER_INPUT; + } + if (input != NULL) { + reader->input = input; + reader->allocs |= XML_TEXTREADER_INPUT; + } + if (reader->buffer == NULL) + reader->buffer = xmlBufferCreateSize(100); + if (reader->buffer == NULL) { + xmlGenericError(xmlGenericErrorContext, + "xmlTextReaderSetup : malloc failed\n"); + return (-1); + } + if (reader->sax == NULL) + reader->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler)); + if (reader->sax == NULL) { + xmlGenericError(xmlGenericErrorContext, + "xmlTextReaderSetup : malloc failed\n"); + return (-1); + } + xmlSAXVersion(reader->sax, 2); + reader->startElement = reader->sax->startElement; + reader->sax->startElement = xmlTextReaderStartElement; + reader->endElement = reader->sax->endElement; + reader->sax->endElement = xmlTextReaderEndElement; +#ifdef LIBXML_SAX1_ENABLED + if (reader->sax->initialized == XML_SAX2_MAGIC) { +#endif /* LIBXML_SAX1_ENABLED */ + reader->startElementNs = reader->sax->startElementNs; + reader->sax->startElementNs = xmlTextReaderStartElementNs; + reader->endElementNs = reader->sax->endElementNs; + reader->sax->endElementNs = xmlTextReaderEndElementNs; +#ifdef LIBXML_SAX1_ENABLED + } else { + reader->startElementNs = NULL; + reader->endElementNs = NULL; + } +#endif /* LIBXML_SAX1_ENABLED */ + reader->characters = reader->sax->characters; + reader->sax->characters = xmlTextReaderCharacters; + reader->sax->ignorableWhitespace = xmlTextReaderCharacters; + reader->cdataBlock = reader->sax->cdataBlock; + reader->sax->cdataBlock = xmlTextReaderCDataBlock; + + reader->mode = XML_TEXTREADER_MODE_INITIAL; + reader->node = NULL; + reader->curnode = NULL; + if (input != NULL) { + if (reader->input->buffer->use < 4) { + xmlParserInputBufferRead(input, 4); + } + if (reader->ctxt == NULL) { + if (reader->input->buffer->use >= 4) { + reader->ctxt = xmlCreatePushParserCtxt(reader->sax, NULL, + (const char *) reader->input->buffer->content, 4, URL); + reader->base = 0; + reader->cur = 4; + } else { + reader->ctxt = + xmlCreatePushParserCtxt(reader->sax, NULL, NULL, 0, URL); + reader->base = 0; + reader->cur = 0; + } + } else { + xmlParserInputPtr inputStream; + xmlParserInputBufferPtr buf; + xmlCharEncoding enc = XML_CHAR_ENCODING_NONE; + + xmlCtxtReset(reader->ctxt); + buf = xmlAllocParserInputBuffer(enc); + if (buf == NULL) return(-1); + inputStream = xmlNewInputStream(reader->ctxt); + if (inputStream == NULL) { + xmlFreeParserInputBuffer(buf); + return(-1); + } + + if (URL == NULL) + inputStream->filename = NULL; + else + inputStream->filename = (char *) + xmlCanonicPath((const xmlChar *) URL); + inputStream->buf = buf; + inputStream->base = inputStream->buf->buffer->content; + inputStream->cur = inputStream->buf->buffer->content; + inputStream->end = + &inputStream->buf->buffer->content[inputStream->buf->buffer->use]; + + inputPush(reader->ctxt, inputStream); + reader->cur = 0; + } + if (reader->ctxt == NULL) { + xmlGenericError(xmlGenericErrorContext, + "xmlTextReaderSetup : malloc failed\n"); + return (-1); + } + } + if (reader->dict != NULL) { + if (reader->ctxt->dict != NULL) { + if (reader->dict != reader->ctxt->dict) { + xmlDictFree(reader->dict); + reader->dict = reader->ctxt->dict; + } + } else { + reader->ctxt->dict = reader->dict; + } + } else { + if (reader->ctxt->dict == NULL) + reader->ctxt->dict = xmlDictCreate(); + reader->dict = reader->ctxt->dict; + } + reader->ctxt->_private = reader; + reader->ctxt->linenumbers = 1; + reader->ctxt->dictNames = 1; + /* + * use the parser dictionnary to allocate all elements and attributes names + */ + reader->ctxt->docdict = 1; + reader->ctxt->parseMode = XML_PARSE_READER; + +#ifdef LIBXML_XINCLUDE_ENABLED + if (reader->xincctxt != NULL) { + xmlXIncludeFreeContext(reader->xincctxt); + reader->xincctxt = NULL; + } + if (options & XML_PARSE_XINCLUDE) { + reader->xinclude = 1; + reader->xinclude_name = xmlDictLookup(reader->dict, XINCLUDE_NODE, -1); + options -= XML_PARSE_XINCLUDE; + } else + reader->xinclude = 0; + reader->in_xinclude = 0; +#endif +#ifdef LIBXML_PATTERN_ENABLED + if (reader->patternTab == NULL) { + reader->patternNr = 0; + reader->patternMax = 0; + } + while (reader->patternNr > 0) { + reader->patternNr--; + if (reader->patternTab[reader->patternNr] != NULL) { + xmlFreePattern(reader->patternTab[reader->patternNr]); + reader->patternTab[reader->patternNr] = NULL; + } + } +#endif + + if (options & XML_PARSE_DTDVALID) + reader->validate = XML_TEXTREADER_VALIDATE_DTD; + + xmlCtxtUseOptions(reader->ctxt, options); + if (encoding != NULL) { + xmlCharEncodingHandlerPtr hdlr; + + hdlr = xmlFindCharEncodingHandler(encoding); + if (hdlr != NULL) + xmlSwitchToEncoding(reader->ctxt, hdlr); + } + if ((URL != NULL) && (reader->ctxt->input != NULL) && + (reader->ctxt->input->filename == NULL)) + reader->ctxt->input->filename = (char *) + xmlStrdup((const xmlChar *) URL); + + reader->doc = NULL; + + return (0); +} + +/** + * xmlTextReaderByteConsumed: + * @reader: an XML reader + * + * This function provides the current index of the parser used + * by the reader, relative to the start of the current entity. + * This function actually just wraps a call to xmlBytesConsumed() + * for the parser context associated with the reader. + * See xmlBytesConsumed() for more information. + * + * Returns the index in bytes from the beginning of the entity or -1 + * in case the index could not be computed. + */ +long +xmlTextReaderByteConsumed(xmlTextReaderPtr reader) { + if ((reader == NULL) || (reader->ctxt == NULL)) + return(-1); + return(xmlByteConsumed(reader->ctxt)); +} + + +/** + * xmlReaderWalker: + * @doc: a preparsed document + * + * Create an xmltextReader for a preparsed document. + * + * Returns the new reader or NULL in case of error. + */ +xmlTextReaderPtr +xmlReaderWalker(xmlDocPtr doc) +{ + xmlTextReaderPtr ret; + + if (doc == NULL) + return(NULL); + + ret = xmlMalloc(sizeof(xmlTextReader)); + if (ret == NULL) { + xmlGenericError(xmlGenericErrorContext, + "xmlNewTextReader : malloc failed\n"); + return(NULL); + } + memset(ret, 0, sizeof(xmlTextReader)); + ret->entNr = 0; + ret->input = NULL; + ret->mode = XML_TEXTREADER_MODE_INITIAL; + ret->node = NULL; + ret->curnode = NULL; + ret->base = 0; + ret->cur = 0; + ret->allocs = XML_TEXTREADER_CTXT; + ret->doc = doc; + ret->state = XML_TEXTREADER_START; + ret->dict = xmlDictCreate(); + return(ret); +} + +/** + * xmlReaderForDoc: + * @cur: a pointer to a zero terminated string + * @URL: the base URL to use for the document + * @encoding: the document encoding, or NULL + * @options: a combination of xmlParserOption + * + * Create an xmltextReader for an XML in-memory document. + * The parsing flags @options are a combination of xmlParserOption. + * + * Returns the new reader or NULL in case of error. + */ +xmlTextReaderPtr +xmlReaderForDoc(const xmlChar * cur, const char *URL, const char *encoding, + int options) +{ + int len; + + if (cur == NULL) + return (NULL); + len = xmlStrlen(cur); + + return (xmlReaderForMemory + ((const char *) cur, len, URL, encoding, options)); +} + +/** + * xmlReaderForFile: + * @filename: a file or URL + * @encoding: the document encoding, or NULL + * @options: a combination of xmlParserOption + * + * parse an XML file from the filesystem or the network. + * The parsing flags @options are a combination of xmlParserOption. + * + * Returns the new reader or NULL in case of error. + */ +xmlTextReaderPtr +xmlReaderForFile(const char *filename, const char *encoding, int options) +{ + xmlTextReaderPtr reader; + + reader = xmlNewTextReaderFilename(filename); + if (reader == NULL) + return (NULL); + xmlTextReaderSetup(reader, NULL, NULL, encoding, options); + return (reader); +} + +/** + * xmlReaderForMemory: + * @buffer: a pointer to a char array + * @size: the size of the array + * @URL: the base URL to use for the document + * @encoding: the document encoding, or NULL + * @options: a combination of xmlParserOption + * + * Create an xmltextReader for an XML in-memory document. + * The parsing flags @options are a combination of xmlParserOption. + * + * Returns the new reader or NULL in case of error. + */ +xmlTextReaderPtr +xmlReaderForMemory(const char *buffer, int size, const char *URL, + const char *encoding, int options) +{ + xmlTextReaderPtr reader; + xmlParserInputBufferPtr buf; + + buf = xmlParserInputBufferCreateStatic(buffer, size, + XML_CHAR_ENCODING_NONE); + if (buf == NULL) { + return (NULL); + } + reader = xmlNewTextReader(buf, URL); + if (reader == NULL) { + xmlFreeParserInputBuffer(buf); + return (NULL); + } + reader->allocs |= XML_TEXTREADER_INPUT; + xmlTextReaderSetup(reader, NULL, URL, encoding, options); + return (reader); +} + +/** + * xmlReaderForFd: + * @fd: an open file descriptor + * @URL: the base URL to use for the document + * @encoding: the document encoding, or NULL + * @options: a combination of xmlParserOption + * + * Create an xmltextReader for an XML from a file descriptor. + * The parsing flags @options are a combination of xmlParserOption. + * NOTE that the file descriptor will not be closed when the + * reader is closed or reset. + * + * Returns the new reader or NULL in case of error. + */ +xmlTextReaderPtr +xmlReaderForFd(int fd, const char *URL, const char *encoding, int options) +{ + xmlTextReaderPtr reader; + xmlParserInputBufferPtr input; + + if (fd < 0) + return (NULL); + + input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE); + if (input == NULL) + return (NULL); + input->closecallback = NULL; + reader = xmlNewTextReader(input, URL); + if (reader == NULL) { + xmlFreeParserInputBuffer(input); + return (NULL); + } + reader->allocs |= XML_TEXTREADER_INPUT; + xmlTextReaderSetup(reader, NULL, URL, encoding, options); + return (reader); +} + +/** + * xmlReaderForIO: + * @ioread: an I/O read function + * @ioclose: an I/O close function + * @ioctx: an I/O handler + * @URL: the base URL to use for the document + * @encoding: the document encoding, or NULL + * @options: a combination of xmlParserOption + * + * Create an xmltextReader for an XML document from I/O functions and source. + * The parsing flags @options are a combination of xmlParserOption. + * + * Returns the new reader or NULL in case of error. + */ +xmlTextReaderPtr +xmlReaderForIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose, + void *ioctx, const char *URL, const char *encoding, + int options) +{ + xmlTextReaderPtr reader; + xmlParserInputBufferPtr input; + + if (ioread == NULL) + return (NULL); + + input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx, + XML_CHAR_ENCODING_NONE); + if (input == NULL) + return (NULL); + reader = xmlNewTextReader(input, URL); + if (reader == NULL) { + xmlFreeParserInputBuffer(input); + return (NULL); + } + reader->allocs |= XML_TEXTREADER_INPUT; + xmlTextReaderSetup(reader, NULL, URL, encoding, options); + return (reader); +} + +/** + * xmlReaderNewWalker: + * @reader: an XML reader + * @doc: a preparsed document + * + * Setup an xmltextReader to parse a preparsed XML document. + * This reuses the existing @reader xmlTextReader. + * + * Returns 0 in case of success and -1 in case of error + */ +int +xmlReaderNewWalker(xmlTextReaderPtr reader, xmlDocPtr doc) +{ + if (doc == NULL) + return (-1); + if (reader == NULL) + return (-1); + + if (reader->input != NULL) { + xmlFreeParserInputBuffer(reader->input); + } + if (reader->ctxt != NULL) { + xmlCtxtReset(reader->ctxt); + } + + reader->entNr = 0; + reader->input = NULL; + reader->mode = XML_TEXTREADER_MODE_INITIAL; + reader->node = NULL; + reader->curnode = NULL; + reader->base = 0; + reader->cur = 0; + reader->allocs = XML_TEXTREADER_CTXT; + reader->doc = doc; + reader->state = XML_TEXTREADER_START; + if (reader->dict == NULL) { + if ((reader->ctxt != NULL) && (reader->ctxt->dict != NULL)) + reader->dict = reader->ctxt->dict; + else + reader->dict = xmlDictCreate(); + } + return(0); +} + +/** + * xmlReaderNewDoc: + * @reader: an XML reader + * @cur: a pointer to a zero terminated string + * @URL: the base URL to use for the document + * @encoding: the document encoding, or NULL + * @options: a combination of xmlParserOption + * + * Setup an xmltextReader to parse an XML in-memory document. + * The parsing flags @options are a combination of xmlParserOption. + * This reuses the existing @reader xmlTextReader. + * + * Returns 0 in case of success and -1 in case of error + */ +int +xmlReaderNewDoc(xmlTextReaderPtr reader, const xmlChar * cur, + const char *URL, const char *encoding, int options) +{ + + int len; + + if (cur == NULL) + return (-1); + if (reader == NULL) + return (-1); + + len = xmlStrlen(cur); + return (xmlReaderNewMemory(reader, (const char *)cur, len, + URL, encoding, options)); +} + +/** + * xmlReaderNewFile: + * @reader: an XML reader + * @filename: a file or URL + * @encoding: the document encoding, or NULL + * @options: a combination of xmlParserOption + * + * parse an XML file from the filesystem or the network. + * The parsing flags @options are a combination of xmlParserOption. + * This reuses the existing @reader xmlTextReader. + * + * Returns 0 in case of success and -1 in case of error + */ +int +xmlReaderNewFile(xmlTextReaderPtr reader, const char *filename, + const char *encoding, int options) +{ + xmlParserInputBufferPtr input; + + if (filename == NULL) + return (-1); + if (reader == NULL) + return (-1); + + input = + xmlParserInputBufferCreateFilename(filename, + XML_CHAR_ENCODING_NONE); + if (input == NULL) + return (-1); + return (xmlTextReaderSetup(reader, input, filename, encoding, options)); +} + +/** + * xmlReaderNewMemory: + * @reader: an XML reader + * @buffer: a pointer to a char array + * @size: the size of the array + * @URL: the base URL to use for the document + * @encoding: the document encoding, or NULL + * @options: a combination of xmlParserOption + * + * Setup an xmltextReader to parse an XML in-memory document. + * The parsing flags @options are a combination of xmlParserOption. + * This reuses the existing @reader xmlTextReader. + * + * Returns 0 in case of success and -1 in case of error + */ +int +xmlReaderNewMemory(xmlTextReaderPtr reader, const char *buffer, int size, + const char *URL, const char *encoding, int options) +{ + xmlParserInputBufferPtr input; + + if (reader == NULL) + return (-1); + if (buffer == NULL) + return (-1); + + input = xmlParserInputBufferCreateStatic(buffer, size, + XML_CHAR_ENCODING_NONE); + if (input == NULL) { + return (-1); + } + return (xmlTextReaderSetup(reader, input, URL, encoding, options)); +} + +/** + * xmlReaderNewFd: + * @reader: an XML reader + * @fd: an open file descriptor + * @URL: the base URL to use for the document + * @encoding: the document encoding, or NULL + * @options: a combination of xmlParserOption + * + * Setup an xmltextReader to parse an XML from a file descriptor. + * NOTE that the file descriptor will not be closed when the + * reader is closed or reset. + * The parsing flags @options are a combination of xmlParserOption. + * This reuses the existing @reader xmlTextReader. + * + * Returns 0 in case of success and -1 in case of error + */ +int +xmlReaderNewFd(xmlTextReaderPtr reader, int fd, + const char *URL, const char *encoding, int options) +{ + xmlParserInputBufferPtr input; + + if (fd < 0) + return (-1); + if (reader == NULL) + return (-1); + + input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE); + if (input == NULL) + return (-1); + input->closecallback = NULL; + return (xmlTextReaderSetup(reader, input, URL, encoding, options)); +} + +/** + * xmlReaderNewIO: + * @reader: an XML reader + * @ioread: an I/O read function + * @ioclose: an I/O close function + * @ioctx: an I/O handler + * @URL: the base URL to use for the document + * @encoding: the document encoding, or NULL + * @options: a combination of xmlParserOption + * + * Setup an xmltextReader to parse an XML document from I/O functions + * and source. + * The parsing flags @options are a combination of xmlParserOption. + * This reuses the existing @reader xmlTextReader. + * + * Returns 0 in case of success and -1 in case of error + */ +int +xmlReaderNewIO(xmlTextReaderPtr reader, xmlInputReadCallback ioread, + xmlInputCloseCallback ioclose, void *ioctx, + const char *URL, const char *encoding, int options) +{ + xmlParserInputBufferPtr input; + + if (ioread == NULL) + return (-1); + if (reader == NULL) + return (-1); + + input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx, + XML_CHAR_ENCODING_NONE); + if (input == NULL) + return (-1); + return (xmlTextReaderSetup(reader, input, URL, encoding, options)); +} +/************************************************************************ + * * + * Utilities * + * * + ************************************************************************/ +#ifdef NOT_USED_YET +/** + * xmlBase64Decode: + * @in: the input buffer + * @inlen: the size of the input (in), the size read from it (out) + * @to: the output buffer + * @tolen: the size of the output (in), the size written to (out) + * + * Base64 decoder, reads from @in and save in @to + * TODO: tell jody when this is actually exported + * + * Returns 0 if all the input was consumer, 1 if the Base64 end was reached, + * 2 if there wasn't enough space on the output or -1 in case of error. + */ +static int +xmlBase64Decode(const unsigned char *in, unsigned long *inlen, + unsigned char *to, unsigned long *tolen) { + unsigned long incur; /* current index in in[] */ + unsigned long inblk; /* last block index in in[] */ + unsigned long outcur; /* current index in out[] */ + unsigned long inmax; /* size of in[] */ + unsigned long outmax; /* size of out[] */ + unsigned char cur; /* the current value read from in[] */ + unsigned char intmp[4], outtmp[4]; /* temporary buffers for the convert */ + int nbintmp; /* number of byte in intmp[] */ + int is_ignore; /* cur should be ignored */ + int is_end = 0; /* the end of the base64 was found */ + int retval = 1; + int i; + + if ((in == NULL) || (inlen == NULL) || (to == NULL) || (tolen == NULL)) + return(-1); + + incur = 0; + inblk = 0; + outcur = 0; + inmax = *inlen; + outmax = *tolen; + nbintmp = 0; + + while (1) { + if (incur >= inmax) + break; + cur = in[incur++]; + is_ignore = 0; + if ((cur >= 'A') && (cur <= 'Z')) + cur = cur - 'A'; + else if ((cur >= 'a') && (cur <= 'z')) + cur = cur - 'a' + 26; + else if ((cur >= '0') && (cur <= '9')) + cur = cur - '0' + 52; + else if (cur == '+') + cur = 62; + else if (cur == '/') + cur = 63; + else if (cur == '.') + cur = 0; + else if (cur == '=') /*no op , end of the base64 stream */ + is_end = 1; + else { + is_ignore = 1; + if (nbintmp == 0) + inblk = incur; + } + + if (!is_ignore) { + int nbouttmp = 3; + int is_break = 0; + + if (is_end) { + if (nbintmp == 0) + break; + if ((nbintmp == 1) || (nbintmp == 2)) + nbouttmp = 1; + else + nbouttmp = 2; + nbintmp = 3; + is_break = 1; + } + intmp[nbintmp++] = cur; + /* + * if intmp is full, push the 4byte sequence as a 3 byte + * sequence out + */ + if (nbintmp == 4) { + nbintmp = 0; + outtmp[0] = (intmp[0] << 2) | ((intmp[1] & 0x30) >> 4); + outtmp[1] = + ((intmp[1] & 0x0F) << 4) | ((intmp[2] & 0x3C) >> 2); + outtmp[2] = ((intmp[2] & 0x03) << 6) | (intmp[3] & 0x3F); + if (outcur + 3 >= outmax) { + retval = 2; + break; + } + + for (i = 0; i < nbouttmp; i++) + to[outcur++] = outtmp[i]; + inblk = incur; + } + + if (is_break) { + retval = 0; + break; + } + } + } + + *tolen = outcur; + *inlen = inblk; + return (retval); +} + +/* + * Test routine for the xmlBase64Decode function + */ +#if 0 +int main(int argc, char **argv) { + char *input = " VW4 gcGV0 \n aXQgdGVzdCAuCg== "; + char output[100]; + char output2[100]; + char output3[100]; + unsigned long inlen = strlen(input); + unsigned long outlen = 100; + int ret; + unsigned long cons, tmp, tmp2, prod; + + /* + * Direct + */ + ret = xmlBase64Decode(input, &inlen, output, &outlen); + + output[outlen] = 0; + printf("ret: %d, inlen: %ld , outlen: %ld, output: '%s'\n", ret, inlen, outlen, output); + + /* + * output chunking + */ + cons = 0; + prod = 0; + while (cons < inlen) { + tmp = 5; + tmp2 = inlen - cons; + + printf("%ld %ld\n", cons, prod); + ret = xmlBase64Decode(&input[cons], &tmp2, &output2[prod], &tmp); + cons += tmp2; + prod += tmp; + printf("%ld %ld\n", cons, prod); + } + output2[outlen] = 0; + printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, prod, output2); + + /* + * input chunking + */ + cons = 0; + prod = 0; + while (cons < inlen) { + tmp = 100 - prod; + tmp2 = inlen - cons; + if (tmp2 > 5) + tmp2 = 5; + + printf("%ld %ld\n", cons, prod); + ret = xmlBase64Decode(&input[cons], &tmp2, &output3[prod], &tmp); + cons += tmp2; + prod += tmp; + printf("%ld %ld\n", cons, prod); + } + output3[outlen] = 0; + printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, prod, output3); + return(0); + +} +#endif +#endif /* NOT_USED_YET */ +#define bottom_xmlreader +#include "elfgcchack.h" +#endif /* LIBXML_READER_ENABLED */ diff --git a/gettext-tools/gnulib-lib/libxml/xmlreader.in.h b/gettext-tools/gnulib-lib/libxml/xmlreader.in.h new file mode 100644 index 0000000..1d12988 --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/xmlreader.in.h @@ -0,0 +1,408 @@ +/* + * Summary: the XMLReader implementation + * Description: API of the XML streaming API based on C# interfaces. + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + +#ifndef __XML_XMLREADER_H__ +#define __XML_XMLREADER_H__ + +#include +#include +#include +#ifdef LIBXML_SCHEMAS_ENABLED +#include +#include +#endif + +#ifdef LIBXML_READER_ENABLED + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * xmlTextReaderMode: + * + * Internal state values for the reader. + */ +typedef enum { + XML_TEXTREADER_MODE_INITIAL = 0, + XML_TEXTREADER_MODE_INTERACTIVE = 1, + XML_TEXTREADER_MODE_ERROR = 2, + XML_TEXTREADER_MODE_EOF =3, + XML_TEXTREADER_MODE_CLOSED = 4, + XML_TEXTREADER_MODE_READING = 5 +} xmlTextReaderMode; + +/** + * xmlParserProperties: + * + * Some common options to use with xmlTextReaderSetParserProp, but it + * is better to use xmlParserOption and the xmlReaderNewxxx and + * xmlReaderForxxx APIs now. + */ +typedef enum { + XML_PARSER_LOADDTD = 1, + XML_PARSER_DEFAULTATTRS = 2, + XML_PARSER_VALIDATE = 3, + XML_PARSER_SUBST_ENTITIES = 4 +} xmlParserProperties; + +/** + * xmlParserSeverities: + * + * How severe an error callback is when the per-reader error callback API + * is used. + */ +typedef enum { + XML_PARSER_SEVERITY_VALIDITY_WARNING = 1, + XML_PARSER_SEVERITY_VALIDITY_ERROR = 2, + XML_PARSER_SEVERITY_WARNING = 3, + XML_PARSER_SEVERITY_ERROR = 4 +} xmlParserSeverities; + +/** + * xmlReaderTypes: + * + * Predefined constants for the different types of nodes. + */ +typedef enum { + XML_READER_TYPE_NONE = 0, + XML_READER_TYPE_ELEMENT = 1, + XML_READER_TYPE_ATTRIBUTE = 2, + XML_READER_TYPE_TEXT = 3, + XML_READER_TYPE_CDATA = 4, + XML_READER_TYPE_ENTITY_REFERENCE = 5, + XML_READER_TYPE_ENTITY = 6, + XML_READER_TYPE_PROCESSING_INSTRUCTION = 7, + XML_READER_TYPE_COMMENT = 8, + XML_READER_TYPE_DOCUMENT = 9, + XML_READER_TYPE_DOCUMENT_TYPE = 10, + XML_READER_TYPE_DOCUMENT_FRAGMENT = 11, + XML_READER_TYPE_NOTATION = 12, + XML_READER_TYPE_WHITESPACE = 13, + XML_READER_TYPE_SIGNIFICANT_WHITESPACE = 14, + XML_READER_TYPE_END_ELEMENT = 15, + XML_READER_TYPE_END_ENTITY = 16, + XML_READER_TYPE_XML_DECLARATION = 17 +} xmlReaderTypes; + +/** + * xmlTextReader: + * + * Structure for an xmlReader context. + */ +typedef struct _xmlTextReader xmlTextReader; + +/** + * xmlTextReaderPtr: + * + * Pointer to an xmlReader context. + */ +typedef xmlTextReader *xmlTextReaderPtr; + +/* + * Constructors & Destructor + */ +XMLPUBFUN xmlTextReaderPtr XMLCALL + xmlNewTextReader (xmlParserInputBufferPtr input, + const char *URI); +XMLPUBFUN xmlTextReaderPtr XMLCALL + xmlNewTextReaderFilename(const char *URI); +XMLPUBFUN void XMLCALL + xmlFreeTextReader (xmlTextReaderPtr reader); + +/* + * Iterators + */ +XMLPUBFUN int XMLCALL + xmlTextReaderRead (xmlTextReaderPtr reader); + +#ifdef LIBXML_WRITER_ENABLED +XMLPUBFUN xmlChar * XMLCALL + xmlTextReaderReadInnerXml (xmlTextReaderPtr reader); + +XMLPUBFUN xmlChar * XMLCALL + xmlTextReaderReadOuterXml (xmlTextReaderPtr reader); +#endif + +XMLPUBFUN xmlChar * XMLCALL + xmlTextReaderReadString (xmlTextReaderPtr reader); +XMLPUBFUN int XMLCALL + xmlTextReaderReadAttributeValue (xmlTextReaderPtr reader); + +/* + * Attributes of the node + */ +XMLPUBFUN int XMLCALL + xmlTextReaderAttributeCount(xmlTextReaderPtr reader); +XMLPUBFUN int XMLCALL + xmlTextReaderDepth (xmlTextReaderPtr reader); +XMLPUBFUN int XMLCALL + xmlTextReaderHasAttributes(xmlTextReaderPtr reader); +XMLPUBFUN int XMLCALL + xmlTextReaderHasValue(xmlTextReaderPtr reader); +XMLPUBFUN int XMLCALL + xmlTextReaderIsDefault (xmlTextReaderPtr reader); +XMLPUBFUN int XMLCALL + xmlTextReaderIsEmptyElement(xmlTextReaderPtr reader); +XMLPUBFUN int XMLCALL + xmlTextReaderNodeType (xmlTextReaderPtr reader); +XMLPUBFUN int XMLCALL + xmlTextReaderQuoteChar (xmlTextReaderPtr reader); +XMLPUBFUN int XMLCALL + xmlTextReaderReadState (xmlTextReaderPtr reader); +XMLPUBFUN int XMLCALL + xmlTextReaderIsNamespaceDecl(xmlTextReaderPtr reader); + +XMLPUBFUN const xmlChar * XMLCALL + xmlTextReaderConstBaseUri (xmlTextReaderPtr reader); +XMLPUBFUN const xmlChar * XMLCALL + xmlTextReaderConstLocalName (xmlTextReaderPtr reader); +XMLPUBFUN const xmlChar * XMLCALL + xmlTextReaderConstName (xmlTextReaderPtr reader); +XMLPUBFUN const xmlChar * XMLCALL + xmlTextReaderConstNamespaceUri(xmlTextReaderPtr reader); +XMLPUBFUN const xmlChar * XMLCALL + xmlTextReaderConstPrefix (xmlTextReaderPtr reader); +XMLPUBFUN const xmlChar * XMLCALL + xmlTextReaderConstXmlLang (xmlTextReaderPtr reader); +XMLPUBFUN const xmlChar * XMLCALL + xmlTextReaderConstString (xmlTextReaderPtr reader, + const xmlChar *str); +XMLPUBFUN const xmlChar * XMLCALL + xmlTextReaderConstValue (xmlTextReaderPtr reader); + +/* + * use the Const version of the routine for + * better performance and simpler code + */ +XMLPUBFUN xmlChar * XMLCALL + xmlTextReaderBaseUri (xmlTextReaderPtr reader); +XMLPUBFUN xmlChar * XMLCALL + xmlTextReaderLocalName (xmlTextReaderPtr reader); +XMLPUBFUN xmlChar * XMLCALL + xmlTextReaderName (xmlTextReaderPtr reader); +XMLPUBFUN xmlChar * XMLCALL + xmlTextReaderNamespaceUri(xmlTextReaderPtr reader); +XMLPUBFUN xmlChar * XMLCALL + xmlTextReaderPrefix (xmlTextReaderPtr reader); +XMLPUBFUN xmlChar * XMLCALL + xmlTextReaderXmlLang (xmlTextReaderPtr reader); +XMLPUBFUN xmlChar * XMLCALL + xmlTextReaderValue (xmlTextReaderPtr reader); + +/* + * Methods of the XmlTextReader + */ +XMLPUBFUN int XMLCALL + xmlTextReaderClose (xmlTextReaderPtr reader); +XMLPUBFUN xmlChar * XMLCALL + xmlTextReaderGetAttributeNo (xmlTextReaderPtr reader, + int no); +XMLPUBFUN xmlChar * XMLCALL + xmlTextReaderGetAttribute (xmlTextReaderPtr reader, + const xmlChar *name); +XMLPUBFUN xmlChar * XMLCALL + xmlTextReaderGetAttributeNs (xmlTextReaderPtr reader, + const xmlChar *localName, + const xmlChar *namespaceURI); +XMLPUBFUN xmlParserInputBufferPtr XMLCALL + xmlTextReaderGetRemainder (xmlTextReaderPtr reader); +XMLPUBFUN xmlChar * XMLCALL + xmlTextReaderLookupNamespace(xmlTextReaderPtr reader, + const xmlChar *prefix); +XMLPUBFUN int XMLCALL + xmlTextReaderMoveToAttributeNo(xmlTextReaderPtr reader, + int no); +XMLPUBFUN int XMLCALL + xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader, + const xmlChar *name); +XMLPUBFUN int XMLCALL + xmlTextReaderMoveToAttributeNs(xmlTextReaderPtr reader, + const xmlChar *localName, + const xmlChar *namespaceURI); +XMLPUBFUN int XMLCALL + xmlTextReaderMoveToFirstAttribute(xmlTextReaderPtr reader); +XMLPUBFUN int XMLCALL + xmlTextReaderMoveToNextAttribute(xmlTextReaderPtr reader); +XMLPUBFUN int XMLCALL + xmlTextReaderMoveToElement (xmlTextReaderPtr reader); +XMLPUBFUN int XMLCALL + xmlTextReaderNormalization (xmlTextReaderPtr reader); +XMLPUBFUN const xmlChar * XMLCALL + xmlTextReaderConstEncoding (xmlTextReaderPtr reader); + +/* + * Extensions + */ +XMLPUBFUN int XMLCALL + xmlTextReaderSetParserProp (xmlTextReaderPtr reader, + int prop, + int value); +XMLPUBFUN int XMLCALL + xmlTextReaderGetParserProp (xmlTextReaderPtr reader, + int prop); +XMLPUBFUN xmlNodePtr XMLCALL + xmlTextReaderCurrentNode (xmlTextReaderPtr reader); + +XMLPUBFUN int XMLCALL + xmlTextReaderGetParserLineNumber(xmlTextReaderPtr reader); + +XMLPUBFUN int XMLCALL + xmlTextReaderGetParserColumnNumber(xmlTextReaderPtr reader); + +XMLPUBFUN xmlNodePtr XMLCALL + xmlTextReaderPreserve (xmlTextReaderPtr reader); +#ifdef LIBXML_PATTERN_ENABLED +XMLPUBFUN int XMLCALL + xmlTextReaderPreservePattern(xmlTextReaderPtr reader, + const xmlChar *pattern, + const xmlChar **namespaces); +#endif /* LIBXML_PATTERN_ENABLED */ +XMLPUBFUN xmlDocPtr XMLCALL + xmlTextReaderCurrentDoc (xmlTextReaderPtr reader); +XMLPUBFUN xmlNodePtr XMLCALL + xmlTextReaderExpand (xmlTextReaderPtr reader); +XMLPUBFUN int XMLCALL + xmlTextReaderNext (xmlTextReaderPtr reader); +XMLPUBFUN int XMLCALL + xmlTextReaderNextSibling (xmlTextReaderPtr reader); +XMLPUBFUN int XMLCALL + xmlTextReaderIsValid (xmlTextReaderPtr reader); +#ifdef LIBXML_SCHEMAS_ENABLED +XMLPUBFUN int XMLCALL + xmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader, + const char *rng); +XMLPUBFUN int XMLCALL + xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, + xmlRelaxNGPtr schema); +XMLPUBFUN int XMLCALL + xmlTextReaderSchemaValidate (xmlTextReaderPtr reader, + const char *xsd); +XMLPUBFUN int XMLCALL + xmlTextReaderSchemaValidateCtxt(xmlTextReaderPtr reader, + xmlSchemaValidCtxtPtr ctxt, + int options); +XMLPUBFUN int XMLCALL + xmlTextReaderSetSchema (xmlTextReaderPtr reader, + xmlSchemaPtr schema); +#endif +XMLPUBFUN const xmlChar * XMLCALL + xmlTextReaderConstXmlVersion(xmlTextReaderPtr reader); +XMLPUBFUN int XMLCALL + xmlTextReaderStandalone (xmlTextReaderPtr reader); + + +/* + * Index lookup + */ +XMLPUBFUN long XMLCALL + xmlTextReaderByteConsumed (xmlTextReaderPtr reader); + +/* + * New more complete APIs for simpler creation and reuse of readers + */ +XMLPUBFUN xmlTextReaderPtr XMLCALL + xmlReaderWalker (xmlDocPtr doc); +XMLPUBFUN xmlTextReaderPtr XMLCALL + xmlReaderForDoc (const xmlChar * cur, + const char *URL, + const char *encoding, + int options); +XMLPUBFUN xmlTextReaderPtr XMLCALL + xmlReaderForFile (const char *filename, + const char *encoding, + int options); +XMLPUBFUN xmlTextReaderPtr XMLCALL + xmlReaderForMemory (const char *buffer, + int size, + const char *URL, + const char *encoding, + int options); +XMLPUBFUN xmlTextReaderPtr XMLCALL + xmlReaderForFd (int fd, + const char *URL, + const char *encoding, + int options); +XMLPUBFUN xmlTextReaderPtr XMLCALL + xmlReaderForIO (xmlInputReadCallback ioread, + xmlInputCloseCallback ioclose, + void *ioctx, + const char *URL, + const char *encoding, + int options); + +XMLPUBFUN int XMLCALL + xmlReaderNewWalker (xmlTextReaderPtr reader, + xmlDocPtr doc); +XMLPUBFUN int XMLCALL + xmlReaderNewDoc (xmlTextReaderPtr reader, + const xmlChar * cur, + const char *URL, + const char *encoding, + int options); +XMLPUBFUN int XMLCALL + xmlReaderNewFile (xmlTextReaderPtr reader, + const char *filename, + const char *encoding, + int options); +XMLPUBFUN int XMLCALL + xmlReaderNewMemory (xmlTextReaderPtr reader, + const char *buffer, + int size, + const char *URL, + const char *encoding, + int options); +XMLPUBFUN int XMLCALL + xmlReaderNewFd (xmlTextReaderPtr reader, + int fd, + const char *URL, + const char *encoding, + int options); +XMLPUBFUN int XMLCALL + xmlReaderNewIO (xmlTextReaderPtr reader, + xmlInputReadCallback ioread, + xmlInputCloseCallback ioclose, + void *ioctx, + const char *URL, + const char *encoding, + int options); +/* + * Error handling extensions + */ +typedef void * xmlTextReaderLocatorPtr; +typedef void (XMLCALL *xmlTextReaderErrorFunc) (void *arg, + const char *msg, + xmlParserSeverities severity, + xmlTextReaderLocatorPtr locator); +XMLPUBFUN int XMLCALL + xmlTextReaderLocatorLineNumber(xmlTextReaderLocatorPtr locator); +/*int xmlTextReaderLocatorLinePosition(xmlTextReaderLocatorPtr locator);*/ +XMLPUBFUN xmlChar * XMLCALL + xmlTextReaderLocatorBaseURI (xmlTextReaderLocatorPtr locator); +XMLPUBFUN void XMLCALL + xmlTextReaderSetErrorHandler(xmlTextReaderPtr reader, + xmlTextReaderErrorFunc f, + void *arg); +XMLPUBFUN void XMLCALL + xmlTextReaderSetStructuredErrorHandler(xmlTextReaderPtr reader, + xmlStructuredErrorFunc f, + void *arg); +XMLPUBFUN void XMLCALL + xmlTextReaderGetErrorHandler(xmlTextReaderPtr reader, + xmlTextReaderErrorFunc *f, + void **arg); + +#ifdef __cplusplus +} +#endif + +#endif /* LIBXML_READER_ENABLED */ + +#endif /* __XML_XMLREADER_H__ */ + diff --git a/gettext-tools/gnulib-lib/libxml/xmlregexp.c b/gettext-tools/gnulib-lib/libxml/xmlregexp.c new file mode 100644 index 0000000..e7d519e --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/xmlregexp.c @@ -0,0 +1,7959 @@ +/* + * regexp.c: generic and extensible Regular Expression engine + * + * Basically designed with the purpose of compiling regexps for + * the variety of validation/shemas mechanisms now available in + * XML related specifications these include: + * - XML-1.0 DTD validation + * - XML Schemas structure part 1 + * - XML Schemas Datatypes part 2 especially Appendix F + * - RELAX-NG/TREX i.e. the counter proposal + * + * See Copyright for the status of this software. + * + * Daniel Veillard + */ + +#define IN_LIBXML +#include "libxml.h" + +#ifdef LIBXML_REGEXP_ENABLED + +/* #define DEBUG_ERR */ + +#include +#include +#ifdef HAVE_LIMITS_H +#include +#endif + +#include +#include +#include +#include +#include + +#ifndef INT_MAX +#define INT_MAX 123456789 /* easy to flag and big enough for our needs */ +#endif + +/* #define DEBUG_REGEXP_GRAPH */ +/* #define DEBUG_REGEXP_EXEC */ +/* #define DEBUG_PUSH */ +/* #define DEBUG_COMPACTION */ + +#define MAX_PUSH 10000000 + +#define ERROR(str) \ + ctxt->error = XML_REGEXP_COMPILE_ERROR; \ + xmlRegexpErrCompile(ctxt, str); +#define NEXT ctxt->cur++ +#define CUR (*(ctxt->cur)) +#define NXT(index) (ctxt->cur[index]) + +#define CUR_SCHAR(s, l) xmlStringCurrentChar(NULL, s, &l) +#define NEXTL(l) ctxt->cur += l; +#define XML_REG_STRING_SEPARATOR '|' + +/** + * TODO: + * + * macro to flag unimplemented blocks + */ +#define TODO \ + xmlGenericError(xmlGenericErrorContext, \ + "Unimplemented block at %s:%d\n", \ + __FILE__, __LINE__); + +/************************************************************************ + * * + * Datatypes and structures * + * * + ************************************************************************/ + +/* + * Note: the order of the enums below is significant, do not shuffle + */ +typedef enum { + XML_REGEXP_EPSILON = 1, + XML_REGEXP_CHARVAL, + XML_REGEXP_RANGES, + XML_REGEXP_SUBREG, /* used for () sub regexps */ + XML_REGEXP_STRING, + XML_REGEXP_ANYCHAR, /* . */ + XML_REGEXP_ANYSPACE, /* \s */ + XML_REGEXP_NOTSPACE, /* \S */ + XML_REGEXP_INITNAME, /* \l */ + XML_REGEXP_NOTINITNAME, /* \L */ + XML_REGEXP_NAMECHAR, /* \c */ + XML_REGEXP_NOTNAMECHAR, /* \C */ + XML_REGEXP_DECIMAL, /* \d */ + XML_REGEXP_NOTDECIMAL, /* \D */ + XML_REGEXP_REALCHAR, /* \w */ + XML_REGEXP_NOTREALCHAR, /* \W */ + XML_REGEXP_LETTER = 100, + XML_REGEXP_LETTER_UPPERCASE, + XML_REGEXP_LETTER_LOWERCASE, + XML_REGEXP_LETTER_TITLECASE, + XML_REGEXP_LETTER_MODIFIER, + XML_REGEXP_LETTER_OTHERS, + XML_REGEXP_MARK, + XML_REGEXP_MARK_NONSPACING, + XML_REGEXP_MARK_SPACECOMBINING, + XML_REGEXP_MARK_ENCLOSING, + XML_REGEXP_NUMBER, + XML_REGEXP_NUMBER_DECIMAL, + XML_REGEXP_NUMBER_LETTER, + XML_REGEXP_NUMBER_OTHERS, + XML_REGEXP_PUNCT, + XML_REGEXP_PUNCT_CONNECTOR, + XML_REGEXP_PUNCT_DASH, + XML_REGEXP_PUNCT_OPEN, + XML_REGEXP_PUNCT_CLOSE, + XML_REGEXP_PUNCT_INITQUOTE, + XML_REGEXP_PUNCT_FINQUOTE, + XML_REGEXP_PUNCT_OTHERS, + XML_REGEXP_SEPAR, + XML_REGEXP_SEPAR_SPACE, + XML_REGEXP_SEPAR_LINE, + XML_REGEXP_SEPAR_PARA, + XML_REGEXP_SYMBOL, + XML_REGEXP_SYMBOL_MATH, + XML_REGEXP_SYMBOL_CURRENCY, + XML_REGEXP_SYMBOL_MODIFIER, + XML_REGEXP_SYMBOL_OTHERS, + XML_REGEXP_OTHER, + XML_REGEXP_OTHER_CONTROL, + XML_REGEXP_OTHER_FORMAT, + XML_REGEXP_OTHER_PRIVATE, + XML_REGEXP_OTHER_NA, + XML_REGEXP_BLOCK_NAME +} xmlRegAtomType; + +typedef enum { + XML_REGEXP_QUANT_EPSILON = 1, + XML_REGEXP_QUANT_ONCE, + XML_REGEXP_QUANT_OPT, + XML_REGEXP_QUANT_MULT, + XML_REGEXP_QUANT_PLUS, + XML_REGEXP_QUANT_ONCEONLY, + XML_REGEXP_QUANT_ALL, + XML_REGEXP_QUANT_RANGE +} xmlRegQuantType; + +typedef enum { + XML_REGEXP_START_STATE = 1, + XML_REGEXP_FINAL_STATE, + XML_REGEXP_TRANS_STATE, + XML_REGEXP_SINK_STATE +} xmlRegStateType; + +typedef enum { + XML_REGEXP_MARK_NORMAL = 0, + XML_REGEXP_MARK_START, + XML_REGEXP_MARK_VISITED +} xmlRegMarkedType; + +typedef struct _xmlRegRange xmlRegRange; +typedef xmlRegRange *xmlRegRangePtr; + +struct _xmlRegRange { + int neg; /* 0 normal, 1 not, 2 exclude */ + xmlRegAtomType type; + int start; + int end; + xmlChar *blockName; +}; + +typedef struct _xmlRegAtom xmlRegAtom; +typedef xmlRegAtom *xmlRegAtomPtr; + +typedef struct _xmlAutomataState xmlRegState; +typedef xmlRegState *xmlRegStatePtr; + +struct _xmlRegAtom { + int no; + xmlRegAtomType type; + xmlRegQuantType quant; + int min; + int max; + + void *valuep; + void *valuep2; + int neg; + int codepoint; + xmlRegStatePtr start; + xmlRegStatePtr stop; + int maxRanges; + int nbRanges; + xmlRegRangePtr *ranges; + void *data; +}; + +typedef struct _xmlRegCounter xmlRegCounter; +typedef xmlRegCounter *xmlRegCounterPtr; + +struct _xmlRegCounter { + int min; + int max; +}; + +typedef struct _xmlRegTrans xmlRegTrans; +typedef xmlRegTrans *xmlRegTransPtr; + +struct _xmlRegTrans { + xmlRegAtomPtr atom; + int to; + int counter; + int count; + int nd; +}; + +struct _xmlAutomataState { + xmlRegStateType type; + xmlRegMarkedType mark; + xmlRegMarkedType reached; + int no; + int maxTrans; + int nbTrans; + xmlRegTrans *trans; + /* knowing states ponting to us can speed things up */ + int maxTransTo; + int nbTransTo; + int *transTo; +}; + +typedef struct _xmlAutomata xmlRegParserCtxt; +typedef xmlRegParserCtxt *xmlRegParserCtxtPtr; + +struct _xmlAutomata { + xmlChar *string; + xmlChar *cur; + + int error; + int neg; + + xmlRegStatePtr start; + xmlRegStatePtr end; + xmlRegStatePtr state; + + xmlRegAtomPtr atom; + + int maxAtoms; + int nbAtoms; + xmlRegAtomPtr *atoms; + + int maxStates; + int nbStates; + xmlRegStatePtr *states; + + int maxCounters; + int nbCounters; + xmlRegCounter *counters; + + int determinist; + int negs; +}; + +struct _xmlRegexp { + xmlChar *string; + int nbStates; + xmlRegStatePtr *states; + int nbAtoms; + xmlRegAtomPtr *atoms; + int nbCounters; + xmlRegCounter *counters; + int determinist; + /* + * That's the compact form for determinists automatas + */ + int nbstates; + int *compact; + void **transdata; + int nbstrings; + xmlChar **stringMap; +}; + +typedef struct _xmlRegExecRollback xmlRegExecRollback; +typedef xmlRegExecRollback *xmlRegExecRollbackPtr; + +struct _xmlRegExecRollback { + xmlRegStatePtr state;/* the current state */ + int index; /* the index in the input stack */ + int nextbranch; /* the next transition to explore in that state */ + int *counts; /* save the automata state if it has some */ +}; + +typedef struct _xmlRegInputToken xmlRegInputToken; +typedef xmlRegInputToken *xmlRegInputTokenPtr; + +struct _xmlRegInputToken { + xmlChar *value; + void *data; +}; + +struct _xmlRegExecCtxt { + int status; /* execution status != 0 indicate an error */ + int determinist; /* did we find an indeterministic behaviour */ + xmlRegexpPtr comp; /* the compiled regexp */ + xmlRegExecCallbacks callback; + void *data; + + xmlRegStatePtr state;/* the current state */ + int transno; /* the current transition on that state */ + int transcount; /* the number of chars in char counted transitions */ + + /* + * A stack of rollback states + */ + int maxRollbacks; + int nbRollbacks; + xmlRegExecRollback *rollbacks; + + /* + * The state of the automata if any + */ + int *counts; + + /* + * The input stack + */ + int inputStackMax; + int inputStackNr; + int index; + int *charStack; + const xmlChar *inputString; /* when operating on characters */ + xmlRegInputTokenPtr inputStack;/* when operating on strings */ + + /* + * error handling + */ + int errStateNo; /* the error state number */ + xmlRegStatePtr errState; /* the error state */ + xmlChar *errString; /* the string raising the error */ + int *errCounts; /* counters at the error state */ + int nbPush; +}; + +#define REGEXP_ALL_COUNTER 0x123456 +#define REGEXP_ALL_LAX_COUNTER 0x123457 + +static void xmlFAParseRegExp(xmlRegParserCtxtPtr ctxt, int top); +static void xmlRegFreeState(xmlRegStatePtr state); +static void xmlRegFreeAtom(xmlRegAtomPtr atom); +static int xmlRegStrEqualWildcard(const xmlChar *expStr, const xmlChar *valStr); +static int xmlRegCheckCharacter(xmlRegAtomPtr atom, int codepoint); +static int xmlRegCheckCharacterRange(xmlRegAtomType type, int codepoint, + int neg, int start, int end, const xmlChar *blockName); + +/************************************************************************ + * * + * Regexp memory error handler * + * * + ************************************************************************/ +/** + * xmlRegexpErrMemory: + * @extra: extra information + * + * Handle an out of memory condition + */ +static void +xmlRegexpErrMemory(xmlRegParserCtxtPtr ctxt, const char *extra) +{ + const char *regexp = NULL; + if (ctxt != NULL) { + regexp = (const char *) ctxt->string; + ctxt->error = XML_ERR_NO_MEMORY; + } + __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_REGEXP, + XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, extra, + regexp, NULL, 0, 0, + "Memory allocation failed : %s\n", extra); +} + +/** + * xmlRegexpErrCompile: + * @extra: extra information + * + * Handle a compilation failure + */ +static void +xmlRegexpErrCompile(xmlRegParserCtxtPtr ctxt, const char *extra) +{ + const char *regexp = NULL; + int idx = 0; + + if (ctxt != NULL) { + regexp = (const char *) ctxt->string; + idx = ctxt->cur - ctxt->string; + ctxt->error = XML_REGEXP_COMPILE_ERROR; + } + __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_REGEXP, + XML_REGEXP_COMPILE_ERROR, XML_ERR_FATAL, NULL, 0, extra, + regexp, NULL, idx, 0, + "failed to compile: %s\n", extra); +} + +/************************************************************************ + * * + * Allocation/Deallocation * + * * + ************************************************************************/ + +static int xmlFAComputesDeterminism(xmlRegParserCtxtPtr ctxt); +/** + * xmlRegEpxFromParse: + * @ctxt: the parser context used to build it + * + * Allocate a new regexp and fill it with the result from the parser + * + * Returns the new regexp or NULL in case of error + */ +static xmlRegexpPtr +xmlRegEpxFromParse(xmlRegParserCtxtPtr ctxt) { + xmlRegexpPtr ret; + + ret = (xmlRegexpPtr) xmlMalloc(sizeof(xmlRegexp)); + if (ret == NULL) { + xmlRegexpErrMemory(ctxt, "compiling regexp"); + return(NULL); + } + memset(ret, 0, sizeof(xmlRegexp)); + ret->string = ctxt->string; + ret->nbStates = ctxt->nbStates; + ret->states = ctxt->states; + ret->nbAtoms = ctxt->nbAtoms; + ret->atoms = ctxt->atoms; + ret->nbCounters = ctxt->nbCounters; + ret->counters = ctxt->counters; + ret->determinist = ctxt->determinist; + if (ret->determinist == -1) { + xmlRegexpIsDeterminist(ret); + } + + if ((ret->determinist != 0) && + (ret->nbCounters == 0) && + (ctxt->negs == 0) && + (ret->atoms != NULL) && + (ret->atoms[0] != NULL) && + (ret->atoms[0]->type == XML_REGEXP_STRING)) { + int i, j, nbstates = 0, nbatoms = 0; + int *stateRemap; + int *stringRemap; + int *transitions; + void **transdata; + xmlChar **stringMap; + xmlChar *value; + + /* + * Switch to a compact representation + * 1/ counting the effective number of states left + * 2/ counting the unique number of atoms, and check that + * they are all of the string type + * 3/ build a table state x atom for the transitions + */ + + stateRemap = xmlMalloc(ret->nbStates * sizeof(int)); + if (stateRemap == NULL) { + xmlRegexpErrMemory(ctxt, "compiling regexp"); + xmlFree(ret); + return(NULL); + } + for (i = 0;i < ret->nbStates;i++) { + if (ret->states[i] != NULL) { + stateRemap[i] = nbstates; + nbstates++; + } else { + stateRemap[i] = -1; + } + } +#ifdef DEBUG_COMPACTION + printf("Final: %d states\n", nbstates); +#endif + stringMap = xmlMalloc(ret->nbAtoms * sizeof(char *)); + if (stringMap == NULL) { + xmlRegexpErrMemory(ctxt, "compiling regexp"); + xmlFree(stateRemap); + xmlFree(ret); + return(NULL); + } + stringRemap = xmlMalloc(ret->nbAtoms * sizeof(int)); + if (stringRemap == NULL) { + xmlRegexpErrMemory(ctxt, "compiling regexp"); + xmlFree(stringMap); + xmlFree(stateRemap); + xmlFree(ret); + return(NULL); + } + for (i = 0;i < ret->nbAtoms;i++) { + if ((ret->atoms[i]->type == XML_REGEXP_STRING) && + (ret->atoms[i]->quant == XML_REGEXP_QUANT_ONCE)) { + value = ret->atoms[i]->valuep; + for (j = 0;j < nbatoms;j++) { + if (xmlStrEqual(stringMap[j], value)) { + stringRemap[i] = j; + break; + } + } + if (j >= nbatoms) { + stringRemap[i] = nbatoms; + stringMap[nbatoms] = xmlStrdup(value); + if (stringMap[nbatoms] == NULL) { + for (i = 0;i < nbatoms;i++) + xmlFree(stringMap[i]); + xmlFree(stringRemap); + xmlFree(stringMap); + xmlFree(stateRemap); + xmlFree(ret); + return(NULL); + } + nbatoms++; + } + } else { + xmlFree(stateRemap); + xmlFree(stringRemap); + for (i = 0;i < nbatoms;i++) + xmlFree(stringMap[i]); + xmlFree(stringMap); + xmlFree(ret); + return(NULL); + } + } +#ifdef DEBUG_COMPACTION + printf("Final: %d atoms\n", nbatoms); +#endif + transitions = (int *) xmlMalloc((nbstates + 1) * + (nbatoms + 1) * sizeof(int)); + if (transitions == NULL) { + xmlFree(stateRemap); + xmlFree(stringRemap); + xmlFree(stringMap); + xmlFree(ret); + return(NULL); + } + memset(transitions, 0, (nbstates + 1) * (nbatoms + 1) * sizeof(int)); + + /* + * Allocate the transition table. The first entry for each + * state corresponds to the state type. + */ + transdata = NULL; + + for (i = 0;i < ret->nbStates;i++) { + int stateno, atomno, targetno, prev; + xmlRegStatePtr state; + xmlRegTransPtr trans; + + stateno = stateRemap[i]; + if (stateno == -1) + continue; + state = ret->states[i]; + + transitions[stateno * (nbatoms + 1)] = state->type; + + for (j = 0;j < state->nbTrans;j++) { + trans = &(state->trans[j]); + if ((trans->to == -1) || (trans->atom == NULL)) + continue; + atomno = stringRemap[trans->atom->no]; + if ((trans->atom->data != NULL) && (transdata == NULL)) { + transdata = (void **) xmlMalloc(nbstates * nbatoms * + sizeof(void *)); + if (transdata != NULL) + memset(transdata, 0, + nbstates * nbatoms * sizeof(void *)); + else { + xmlRegexpErrMemory(ctxt, "compiling regexp"); + break; + } + } + targetno = stateRemap[trans->to]; + /* + * if the same atom can generate transitions to 2 different + * states then it means the automata is not determinist and + * the compact form can't be used ! + */ + prev = transitions[stateno * (nbatoms + 1) + atomno + 1]; + if (prev != 0) { + if (prev != targetno + 1) { + ret->determinist = 0; +#ifdef DEBUG_COMPACTION + printf("Indet: state %d trans %d, atom %d to %d : %d to %d\n", + i, j, trans->atom->no, trans->to, atomno, targetno); + printf(" previous to is %d\n", prev); +#endif + if (transdata != NULL) + xmlFree(transdata); + xmlFree(transitions); + xmlFree(stateRemap); + xmlFree(stringRemap); + for (i = 0;i < nbatoms;i++) + xmlFree(stringMap[i]); + xmlFree(stringMap); + goto not_determ; + } + } else { +#if 0 + printf("State %d trans %d: atom %d to %d : %d to %d\n", + i, j, trans->atom->no, trans->to, atomno, targetno); +#endif + transitions[stateno * (nbatoms + 1) + atomno + 1] = + targetno + 1; /* to avoid 0 */ + if (transdata != NULL) + transdata[stateno * nbatoms + atomno] = + trans->atom->data; + } + } + } + ret->determinist = 1; +#ifdef DEBUG_COMPACTION + /* + * Debug + */ + for (i = 0;i < nbstates;i++) { + for (j = 0;j < nbatoms + 1;j++) { + printf("%02d ", transitions[i * (nbatoms + 1) + j]); + } + printf("\n"); + } + printf("\n"); +#endif + /* + * Cleanup of the old data + */ + if (ret->states != NULL) { + for (i = 0;i < ret->nbStates;i++) + xmlRegFreeState(ret->states[i]); + xmlFree(ret->states); + } + ret->states = NULL; + ret->nbStates = 0; + if (ret->atoms != NULL) { + for (i = 0;i < ret->nbAtoms;i++) + xmlRegFreeAtom(ret->atoms[i]); + xmlFree(ret->atoms); + } + ret->atoms = NULL; + ret->nbAtoms = 0; + + ret->compact = transitions; + ret->transdata = transdata; + ret->stringMap = stringMap; + ret->nbstrings = nbatoms; + ret->nbstates = nbstates; + xmlFree(stateRemap); + xmlFree(stringRemap); + } +not_determ: + ctxt->string = NULL; + ctxt->nbStates = 0; + ctxt->states = NULL; + ctxt->nbAtoms = 0; + ctxt->atoms = NULL; + ctxt->nbCounters = 0; + ctxt->counters = NULL; + return(ret); +} + +/** + * xmlRegNewParserCtxt: + * @string: the string to parse + * + * Allocate a new regexp parser context + * + * Returns the new context or NULL in case of error + */ +static xmlRegParserCtxtPtr +xmlRegNewParserCtxt(const xmlChar *string) { + xmlRegParserCtxtPtr ret; + + ret = (xmlRegParserCtxtPtr) xmlMalloc(sizeof(xmlRegParserCtxt)); + if (ret == NULL) + return(NULL); + memset(ret, 0, sizeof(xmlRegParserCtxt)); + if (string != NULL) + ret->string = xmlStrdup(string); + ret->cur = ret->string; + ret->neg = 0; + ret->negs = 0; + ret->error = 0; + ret->determinist = -1; + return(ret); +} + +/** + * xmlRegNewRange: + * @ctxt: the regexp parser context + * @neg: is that negative + * @type: the type of range + * @start: the start codepoint + * @end: the end codepoint + * + * Allocate a new regexp range + * + * Returns the new range or NULL in case of error + */ +static xmlRegRangePtr +xmlRegNewRange(xmlRegParserCtxtPtr ctxt, + int neg, xmlRegAtomType type, int start, int end) { + xmlRegRangePtr ret; + + ret = (xmlRegRangePtr) xmlMalloc(sizeof(xmlRegRange)); + if (ret == NULL) { + xmlRegexpErrMemory(ctxt, "allocating range"); + return(NULL); + } + ret->neg = neg; + ret->type = type; + ret->start = start; + ret->end = end; + return(ret); +} + +/** + * xmlRegFreeRange: + * @range: the regexp range + * + * Free a regexp range + */ +static void +xmlRegFreeRange(xmlRegRangePtr range) { + if (range == NULL) + return; + + if (range->blockName != NULL) + xmlFree(range->blockName); + xmlFree(range); +} + +/** + * xmlRegNewAtom: + * @ctxt: the regexp parser context + * @type: the type of atom + * + * Allocate a new regexp range + * + * Returns the new atom or NULL in case of error + */ +static xmlRegAtomPtr +xmlRegNewAtom(xmlRegParserCtxtPtr ctxt, xmlRegAtomType type) { + xmlRegAtomPtr ret; + + ret = (xmlRegAtomPtr) xmlMalloc(sizeof(xmlRegAtom)); + if (ret == NULL) { + xmlRegexpErrMemory(ctxt, "allocating atom"); + return(NULL); + } + memset(ret, 0, sizeof(xmlRegAtom)); + ret->type = type; + ret->quant = XML_REGEXP_QUANT_ONCE; + ret->min = 0; + ret->max = 0; + return(ret); +} + +/** + * xmlRegFreeAtom: + * @atom: the regexp atom + * + * Free a regexp atom + */ +static void +xmlRegFreeAtom(xmlRegAtomPtr atom) { + int i; + + if (atom == NULL) + return; + + for (i = 0;i < atom->nbRanges;i++) + xmlRegFreeRange(atom->ranges[i]); + if (atom->ranges != NULL) + xmlFree(atom->ranges); + if ((atom->type == XML_REGEXP_STRING) && (atom->valuep != NULL)) + xmlFree(atom->valuep); + if ((atom->type == XML_REGEXP_STRING) && (atom->valuep2 != NULL)) + xmlFree(atom->valuep2); + if ((atom->type == XML_REGEXP_BLOCK_NAME) && (atom->valuep != NULL)) + xmlFree(atom->valuep); + xmlFree(atom); +} + +static xmlRegStatePtr +xmlRegNewState(xmlRegParserCtxtPtr ctxt) { + xmlRegStatePtr ret; + + ret = (xmlRegStatePtr) xmlMalloc(sizeof(xmlRegState)); + if (ret == NULL) { + xmlRegexpErrMemory(ctxt, "allocating state"); + return(NULL); + } + memset(ret, 0, sizeof(xmlRegState)); + ret->type = XML_REGEXP_TRANS_STATE; + ret->mark = XML_REGEXP_MARK_NORMAL; + return(ret); +} + +/** + * xmlRegFreeState: + * @state: the regexp state + * + * Free a regexp state + */ +static void +xmlRegFreeState(xmlRegStatePtr state) { + if (state == NULL) + return; + + if (state->trans != NULL) + xmlFree(state->trans); + if (state->transTo != NULL) + xmlFree(state->transTo); + xmlFree(state); +} + +/** + * xmlRegFreeParserCtxt: + * @ctxt: the regexp parser context + * + * Free a regexp parser context + */ +static void +xmlRegFreeParserCtxt(xmlRegParserCtxtPtr ctxt) { + int i; + if (ctxt == NULL) + return; + + if (ctxt->string != NULL) + xmlFree(ctxt->string); + if (ctxt->states != NULL) { + for (i = 0;i < ctxt->nbStates;i++) + xmlRegFreeState(ctxt->states[i]); + xmlFree(ctxt->states); + } + if (ctxt->atoms != NULL) { + for (i = 0;i < ctxt->nbAtoms;i++) + xmlRegFreeAtom(ctxt->atoms[i]); + xmlFree(ctxt->atoms); + } + if (ctxt->counters != NULL) + xmlFree(ctxt->counters); + xmlFree(ctxt); +} + +/************************************************************************ + * * + * Display of Data structures * + * * + ************************************************************************/ + +static void +xmlRegPrintAtomType(FILE *output, xmlRegAtomType type) { + switch (type) { + case XML_REGEXP_EPSILON: + fprintf(output, "epsilon "); break; + case XML_REGEXP_CHARVAL: + fprintf(output, "charval "); break; + case XML_REGEXP_RANGES: + fprintf(output, "ranges "); break; + case XML_REGEXP_SUBREG: + fprintf(output, "subexpr "); break; + case XML_REGEXP_STRING: + fprintf(output, "string "); break; + case XML_REGEXP_ANYCHAR: + fprintf(output, "anychar "); break; + case XML_REGEXP_ANYSPACE: + fprintf(output, "anyspace "); break; + case XML_REGEXP_NOTSPACE: + fprintf(output, "notspace "); break; + case XML_REGEXP_INITNAME: + fprintf(output, "initname "); break; + case XML_REGEXP_NOTINITNAME: + fprintf(output, "notinitname "); break; + case XML_REGEXP_NAMECHAR: + fprintf(output, "namechar "); break; + case XML_REGEXP_NOTNAMECHAR: + fprintf(output, "notnamechar "); break; + case XML_REGEXP_DECIMAL: + fprintf(output, "decimal "); break; + case XML_REGEXP_NOTDECIMAL: + fprintf(output, "notdecimal "); break; + case XML_REGEXP_REALCHAR: + fprintf(output, "realchar "); break; + case XML_REGEXP_NOTREALCHAR: + fprintf(output, "notrealchar "); break; + case XML_REGEXP_LETTER: + fprintf(output, "LETTER "); break; + case XML_REGEXP_LETTER_UPPERCASE: + fprintf(output, "LETTER_UPPERCASE "); break; + case XML_REGEXP_LETTER_LOWERCASE: + fprintf(output, "LETTER_LOWERCASE "); break; + case XML_REGEXP_LETTER_TITLECASE: + fprintf(output, "LETTER_TITLECASE "); break; + case XML_REGEXP_LETTER_MODIFIER: + fprintf(output, "LETTER_MODIFIER "); break; + case XML_REGEXP_LETTER_OTHERS: + fprintf(output, "LETTER_OTHERS "); break; + case XML_REGEXP_MARK: + fprintf(output, "MARK "); break; + case XML_REGEXP_MARK_NONSPACING: + fprintf(output, "MARK_NONSPACING "); break; + case XML_REGEXP_MARK_SPACECOMBINING: + fprintf(output, "MARK_SPACECOMBINING "); break; + case XML_REGEXP_MARK_ENCLOSING: + fprintf(output, "MARK_ENCLOSING "); break; + case XML_REGEXP_NUMBER: + fprintf(output, "NUMBER "); break; + case XML_REGEXP_NUMBER_DECIMAL: + fprintf(output, "NUMBER_DECIMAL "); break; + case XML_REGEXP_NUMBER_LETTER: + fprintf(output, "NUMBER_LETTER "); break; + case XML_REGEXP_NUMBER_OTHERS: + fprintf(output, "NUMBER_OTHERS "); break; + case XML_REGEXP_PUNCT: + fprintf(output, "PUNCT "); break; + case XML_REGEXP_PUNCT_CONNECTOR: + fprintf(output, "PUNCT_CONNECTOR "); break; + case XML_REGEXP_PUNCT_DASH: + fprintf(output, "PUNCT_DASH "); break; + case XML_REGEXP_PUNCT_OPEN: + fprintf(output, "PUNCT_OPEN "); break; + case XML_REGEXP_PUNCT_CLOSE: + fprintf(output, "PUNCT_CLOSE "); break; + case XML_REGEXP_PUNCT_INITQUOTE: + fprintf(output, "PUNCT_INITQUOTE "); break; + case XML_REGEXP_PUNCT_FINQUOTE: + fprintf(output, "PUNCT_FINQUOTE "); break; + case XML_REGEXP_PUNCT_OTHERS: + fprintf(output, "PUNCT_OTHERS "); break; + case XML_REGEXP_SEPAR: + fprintf(output, "SEPAR "); break; + case XML_REGEXP_SEPAR_SPACE: + fprintf(output, "SEPAR_SPACE "); break; + case XML_REGEXP_SEPAR_LINE: + fprintf(output, "SEPAR_LINE "); break; + case XML_REGEXP_SEPAR_PARA: + fprintf(output, "SEPAR_PARA "); break; + case XML_REGEXP_SYMBOL: + fprintf(output, "SYMBOL "); break; + case XML_REGEXP_SYMBOL_MATH: + fprintf(output, "SYMBOL_MATH "); break; + case XML_REGEXP_SYMBOL_CURRENCY: + fprintf(output, "SYMBOL_CURRENCY "); break; + case XML_REGEXP_SYMBOL_MODIFIER: + fprintf(output, "SYMBOL_MODIFIER "); break; + case XML_REGEXP_SYMBOL_OTHERS: + fprintf(output, "SYMBOL_OTHERS "); break; + case XML_REGEXP_OTHER: + fprintf(output, "OTHER "); break; + case XML_REGEXP_OTHER_CONTROL: + fprintf(output, "OTHER_CONTROL "); break; + case XML_REGEXP_OTHER_FORMAT: + fprintf(output, "OTHER_FORMAT "); break; + case XML_REGEXP_OTHER_PRIVATE: + fprintf(output, "OTHER_PRIVATE "); break; + case XML_REGEXP_OTHER_NA: + fprintf(output, "OTHER_NA "); break; + case XML_REGEXP_BLOCK_NAME: + fprintf(output, "BLOCK "); break; + } +} + +static void +xmlRegPrintQuantType(FILE *output, xmlRegQuantType type) { + switch (type) { + case XML_REGEXP_QUANT_EPSILON: + fprintf(output, "epsilon "); break; + case XML_REGEXP_QUANT_ONCE: + fprintf(output, "once "); break; + case XML_REGEXP_QUANT_OPT: + fprintf(output, "? "); break; + case XML_REGEXP_QUANT_MULT: + fprintf(output, "* "); break; + case XML_REGEXP_QUANT_PLUS: + fprintf(output, "+ "); break; + case XML_REGEXP_QUANT_RANGE: + fprintf(output, "range "); break; + case XML_REGEXP_QUANT_ONCEONLY: + fprintf(output, "onceonly "); break; + case XML_REGEXP_QUANT_ALL: + fprintf(output, "all "); break; + } +} +static void +xmlRegPrintRange(FILE *output, xmlRegRangePtr range) { + fprintf(output, " range: "); + if (range->neg) + fprintf(output, "negative "); + xmlRegPrintAtomType(output, range->type); + fprintf(output, "%c - %c\n", range->start, range->end); +} + +static void +xmlRegPrintAtom(FILE *output, xmlRegAtomPtr atom) { + fprintf(output, " atom: "); + if (atom == NULL) { + fprintf(output, "NULL\n"); + return; + } + if (atom->neg) + fprintf(output, "not "); + xmlRegPrintAtomType(output, atom->type); + xmlRegPrintQuantType(output, atom->quant); + if (atom->quant == XML_REGEXP_QUANT_RANGE) + fprintf(output, "%d-%d ", atom->min, atom->max); + if (atom->type == XML_REGEXP_STRING) + fprintf(output, "'%s' ", (char *) atom->valuep); + if (atom->type == XML_REGEXP_CHARVAL) + fprintf(output, "char %c\n", atom->codepoint); + else if (atom->type == XML_REGEXP_RANGES) { + int i; + fprintf(output, "%d entries\n", atom->nbRanges); + for (i = 0; i < atom->nbRanges;i++) + xmlRegPrintRange(output, atom->ranges[i]); + } else if (atom->type == XML_REGEXP_SUBREG) { + fprintf(output, "start %d end %d\n", atom->start->no, atom->stop->no); + } else { + fprintf(output, "\n"); + } +} + +static void +xmlRegPrintTrans(FILE *output, xmlRegTransPtr trans) { + fprintf(output, " trans: "); + if (trans == NULL) { + fprintf(output, "NULL\n"); + return; + } + if (trans->to < 0) { + fprintf(output, "removed\n"); + return; + } + if (trans->nd != 0) { + if (trans->nd == 2) + fprintf(output, "last not determinist, "); + else + fprintf(output, "not determinist, "); + } + if (trans->counter >= 0) { + fprintf(output, "counted %d, ", trans->counter); + } + if (trans->count == REGEXP_ALL_COUNTER) { + fprintf(output, "all transition, "); + } else if (trans->count >= 0) { + fprintf(output, "count based %d, ", trans->count); + } + if (trans->atom == NULL) { + fprintf(output, "epsilon to %d\n", trans->to); + return; + } + if (trans->atom->type == XML_REGEXP_CHARVAL) + fprintf(output, "char %c ", trans->atom->codepoint); + fprintf(output, "atom %d, to %d\n", trans->atom->no, trans->to); +} + +static void +xmlRegPrintState(FILE *output, xmlRegStatePtr state) { + int i; + + fprintf(output, " state: "); + if (state == NULL) { + fprintf(output, "NULL\n"); + return; + } + if (state->type == XML_REGEXP_START_STATE) + fprintf(output, "START "); + if (state->type == XML_REGEXP_FINAL_STATE) + fprintf(output, "FINAL "); + + fprintf(output, "%d, %d transitions:\n", state->no, state->nbTrans); + for (i = 0;i < state->nbTrans; i++) { + xmlRegPrintTrans(output, &(state->trans[i])); + } +} + +#ifdef DEBUG_REGEXP_GRAPH +static void +xmlRegPrintCtxt(FILE *output, xmlRegParserCtxtPtr ctxt) { + int i; + + fprintf(output, " ctxt: "); + if (ctxt == NULL) { + fprintf(output, "NULL\n"); + return; + } + fprintf(output, "'%s' ", ctxt->string); + if (ctxt->error) + fprintf(output, "error "); + if (ctxt->neg) + fprintf(output, "neg "); + fprintf(output, "\n"); + fprintf(output, "%d atoms:\n", ctxt->nbAtoms); + for (i = 0;i < ctxt->nbAtoms; i++) { + fprintf(output, " %02d ", i); + xmlRegPrintAtom(output, ctxt->atoms[i]); + } + if (ctxt->atom != NULL) { + fprintf(output, "current atom:\n"); + xmlRegPrintAtom(output, ctxt->atom); + } + fprintf(output, "%d states:", ctxt->nbStates); + if (ctxt->start != NULL) + fprintf(output, " start: %d", ctxt->start->no); + if (ctxt->end != NULL) + fprintf(output, " end: %d", ctxt->end->no); + fprintf(output, "\n"); + for (i = 0;i < ctxt->nbStates; i++) { + xmlRegPrintState(output, ctxt->states[i]); + } + fprintf(output, "%d counters:\n", ctxt->nbCounters); + for (i = 0;i < ctxt->nbCounters; i++) { + fprintf(output, " %d: min %d max %d\n", i, ctxt->counters[i].min, + ctxt->counters[i].max); + } +} +#endif + +/************************************************************************ + * * + * Finite Automata structures manipulations * + * * + ************************************************************************/ + +static void +xmlRegAtomAddRange(xmlRegParserCtxtPtr ctxt, xmlRegAtomPtr atom, + int neg, xmlRegAtomType type, int start, int end, + xmlChar *blockName) { + xmlRegRangePtr range; + + if (atom == NULL) { + ERROR("add range: atom is NULL"); + return; + } + if (atom->type != XML_REGEXP_RANGES) { + ERROR("add range: atom is not ranges"); + return; + } + if (atom->maxRanges == 0) { + atom->maxRanges = 4; + atom->ranges = (xmlRegRangePtr *) xmlMalloc(atom->maxRanges * + sizeof(xmlRegRangePtr)); + if (atom->ranges == NULL) { + xmlRegexpErrMemory(ctxt, "adding ranges"); + atom->maxRanges = 0; + return; + } + } else if (atom->nbRanges >= atom->maxRanges) { + xmlRegRangePtr *tmp; + atom->maxRanges *= 2; + tmp = (xmlRegRangePtr *) xmlRealloc(atom->ranges, atom->maxRanges * + sizeof(xmlRegRangePtr)); + if (tmp == NULL) { + xmlRegexpErrMemory(ctxt, "adding ranges"); + atom->maxRanges /= 2; + return; + } + atom->ranges = tmp; + } + range = xmlRegNewRange(ctxt, neg, type, start, end); + if (range == NULL) + return; + range->blockName = blockName; + atom->ranges[atom->nbRanges++] = range; + +} + +static int +xmlRegGetCounter(xmlRegParserCtxtPtr ctxt) { + if (ctxt->maxCounters == 0) { + ctxt->maxCounters = 4; + ctxt->counters = (xmlRegCounter *) xmlMalloc(ctxt->maxCounters * + sizeof(xmlRegCounter)); + if (ctxt->counters == NULL) { + xmlRegexpErrMemory(ctxt, "allocating counter"); + ctxt->maxCounters = 0; + return(-1); + } + } else if (ctxt->nbCounters >= ctxt->maxCounters) { + xmlRegCounter *tmp; + ctxt->maxCounters *= 2; + tmp = (xmlRegCounter *) xmlRealloc(ctxt->counters, ctxt->maxCounters * + sizeof(xmlRegCounter)); + if (tmp == NULL) { + xmlRegexpErrMemory(ctxt, "allocating counter"); + ctxt->maxCounters /= 2; + return(-1); + } + ctxt->counters = tmp; + } + ctxt->counters[ctxt->nbCounters].min = -1; + ctxt->counters[ctxt->nbCounters].max = -1; + return(ctxt->nbCounters++); +} + +static int +xmlRegAtomPush(xmlRegParserCtxtPtr ctxt, xmlRegAtomPtr atom) { + if (atom == NULL) { + ERROR("atom push: atom is NULL"); + return(-1); + } + if (ctxt->maxAtoms == 0) { + ctxt->maxAtoms = 4; + ctxt->atoms = (xmlRegAtomPtr *) xmlMalloc(ctxt->maxAtoms * + sizeof(xmlRegAtomPtr)); + if (ctxt->atoms == NULL) { + xmlRegexpErrMemory(ctxt, "pushing atom"); + ctxt->maxAtoms = 0; + return(-1); + } + } else if (ctxt->nbAtoms >= ctxt->maxAtoms) { + xmlRegAtomPtr *tmp; + ctxt->maxAtoms *= 2; + tmp = (xmlRegAtomPtr *) xmlRealloc(ctxt->atoms, ctxt->maxAtoms * + sizeof(xmlRegAtomPtr)); + if (tmp == NULL) { + xmlRegexpErrMemory(ctxt, "allocating counter"); + ctxt->maxAtoms /= 2; + return(-1); + } + ctxt->atoms = tmp; + } + atom->no = ctxt->nbAtoms; + ctxt->atoms[ctxt->nbAtoms++] = atom; + return(0); +} + +static void +xmlRegStateAddTransTo(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr target, + int from) { + if (target->maxTransTo == 0) { + target->maxTransTo = 8; + target->transTo = (int *) xmlMalloc(target->maxTransTo * + sizeof(int)); + if (target->transTo == NULL) { + xmlRegexpErrMemory(ctxt, "adding transition"); + target->maxTransTo = 0; + return; + } + } else if (target->nbTransTo >= target->maxTransTo) { + int *tmp; + target->maxTransTo *= 2; + tmp = (int *) xmlRealloc(target->transTo, target->maxTransTo * + sizeof(int)); + if (tmp == NULL) { + xmlRegexpErrMemory(ctxt, "adding transition"); + target->maxTransTo /= 2; + return; + } + target->transTo = tmp; + } + target->transTo[target->nbTransTo] = from; + target->nbTransTo++; +} + +static void +xmlRegStateAddTrans(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr state, + xmlRegAtomPtr atom, xmlRegStatePtr target, + int counter, int count) { + + int nrtrans; + + if (state == NULL) { + ERROR("add state: state is NULL"); + return; + } + if (target == NULL) { + ERROR("add state: target is NULL"); + return; + } + /* + * Other routines follow the philosophy 'When in doubt, add a transition' + * so we check here whether such a transition is already present and, if + * so, silently ignore this request. + */ + + for (nrtrans = state->nbTrans - 1; nrtrans >= 0; nrtrans--) { + xmlRegTransPtr trans = &(state->trans[nrtrans]); + if ((trans->atom == atom) && + (trans->to == target->no) && + (trans->counter == counter) && + (trans->count == count)) { +#ifdef DEBUG_REGEXP_GRAPH + printf("Ignoring duplicate transition from %d to %d\n", + state->no, target->no); +#endif + return; + } + } + + if (state->maxTrans == 0) { + state->maxTrans = 8; + state->trans = (xmlRegTrans *) xmlMalloc(state->maxTrans * + sizeof(xmlRegTrans)); + if (state->trans == NULL) { + xmlRegexpErrMemory(ctxt, "adding transition"); + state->maxTrans = 0; + return; + } + } else if (state->nbTrans >= state->maxTrans) { + xmlRegTrans *tmp; + state->maxTrans *= 2; + tmp = (xmlRegTrans *) xmlRealloc(state->trans, state->maxTrans * + sizeof(xmlRegTrans)); + if (tmp == NULL) { + xmlRegexpErrMemory(ctxt, "adding transition"); + state->maxTrans /= 2; + return; + } + state->trans = tmp; + } +#ifdef DEBUG_REGEXP_GRAPH + printf("Add trans from %d to %d ", state->no, target->no); + if (count == REGEXP_ALL_COUNTER) + printf("all transition\n"); + else if (count >= 0) + printf("count based %d\n", count); + else if (counter >= 0) + printf("counted %d\n", counter); + else if (atom == NULL) + printf("epsilon transition\n"); + else if (atom != NULL) + xmlRegPrintAtom(stdout, atom); +#endif + + state->trans[state->nbTrans].atom = atom; + state->trans[state->nbTrans].to = target->no; + state->trans[state->nbTrans].counter = counter; + state->trans[state->nbTrans].count = count; + state->trans[state->nbTrans].nd = 0; + state->nbTrans++; + xmlRegStateAddTransTo(ctxt, target, state->no); +} + +static int +xmlRegStatePush(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr state) { + if (state == NULL) return(-1); + if (ctxt->maxStates == 0) { + ctxt->maxStates = 4; + ctxt->states = (xmlRegStatePtr *) xmlMalloc(ctxt->maxStates * + sizeof(xmlRegStatePtr)); + if (ctxt->states == NULL) { + xmlRegexpErrMemory(ctxt, "adding state"); + ctxt->maxStates = 0; + return(-1); + } + } else if (ctxt->nbStates >= ctxt->maxStates) { + xmlRegStatePtr *tmp; + ctxt->maxStates *= 2; + tmp = (xmlRegStatePtr *) xmlRealloc(ctxt->states, ctxt->maxStates * + sizeof(xmlRegStatePtr)); + if (tmp == NULL) { + xmlRegexpErrMemory(ctxt, "adding state"); + ctxt->maxStates /= 2; + return(-1); + } + ctxt->states = tmp; + } + state->no = ctxt->nbStates; + ctxt->states[ctxt->nbStates++] = state; + return(0); +} + +/** + * xmlFAGenerateAllTransition: + * @ctxt: a regexp parser context + * @from: the from state + * @to: the target state or NULL for building a new one + * @lax: + * + */ +static void +xmlFAGenerateAllTransition(xmlRegParserCtxtPtr ctxt, + xmlRegStatePtr from, xmlRegStatePtr to, + int lax) { + if (to == NULL) { + to = xmlRegNewState(ctxt); + xmlRegStatePush(ctxt, to); + ctxt->state = to; + } + if (lax) + xmlRegStateAddTrans(ctxt, from, NULL, to, -1, REGEXP_ALL_LAX_COUNTER); + else + xmlRegStateAddTrans(ctxt, from, NULL, to, -1, REGEXP_ALL_COUNTER); +} + +/** + * xmlFAGenerateEpsilonTransition: + * @ctxt: a regexp parser context + * @from: the from state + * @to: the target state or NULL for building a new one + * + */ +static void +xmlFAGenerateEpsilonTransition(xmlRegParserCtxtPtr ctxt, + xmlRegStatePtr from, xmlRegStatePtr to) { + if (to == NULL) { + to = xmlRegNewState(ctxt); + xmlRegStatePush(ctxt, to); + ctxt->state = to; + } + xmlRegStateAddTrans(ctxt, from, NULL, to, -1, -1); +} + +/** + * xmlFAGenerateCountedEpsilonTransition: + * @ctxt: a regexp parser context + * @from: the from state + * @to: the target state or NULL for building a new one + * counter: the counter for that transition + * + */ +static void +xmlFAGenerateCountedEpsilonTransition(xmlRegParserCtxtPtr ctxt, + xmlRegStatePtr from, xmlRegStatePtr to, int counter) { + if (to == NULL) { + to = xmlRegNewState(ctxt); + xmlRegStatePush(ctxt, to); + ctxt->state = to; + } + xmlRegStateAddTrans(ctxt, from, NULL, to, counter, -1); +} + +/** + * xmlFAGenerateCountedTransition: + * @ctxt: a regexp parser context + * @from: the from state + * @to: the target state or NULL for building a new one + * counter: the counter for that transition + * + */ +static void +xmlFAGenerateCountedTransition(xmlRegParserCtxtPtr ctxt, + xmlRegStatePtr from, xmlRegStatePtr to, int counter) { + if (to == NULL) { + to = xmlRegNewState(ctxt); + xmlRegStatePush(ctxt, to); + ctxt->state = to; + } + xmlRegStateAddTrans(ctxt, from, NULL, to, -1, counter); +} + +/** + * xmlFAGenerateTransitions: + * @ctxt: a regexp parser context + * @from: the from state + * @to: the target state or NULL for building a new one + * @atom: the atom generating the transition + * + * Returns 0 if success and -1 in case of error. + */ +static int +xmlFAGenerateTransitions(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr from, + xmlRegStatePtr to, xmlRegAtomPtr atom) { + if (atom == NULL) { + ERROR("genrate transition: atom == NULL"); + return(-1); + } + if (atom->type == XML_REGEXP_SUBREG) { + /* + * this is a subexpression handling one should not need to + * create a new node except for XML_REGEXP_QUANT_RANGE. + */ + if (xmlRegAtomPush(ctxt, atom) < 0) { + return(-1); + } + if ((to != NULL) && (atom->stop != to) && + (atom->quant != XML_REGEXP_QUANT_RANGE)) { + /* + * Generate an epsilon transition to link to the target + */ + xmlFAGenerateEpsilonTransition(ctxt, atom->stop, to); +#ifdef DV + } else if ((to == NULL) && (atom->quant != XML_REGEXP_QUANT_RANGE) && + (atom->quant != XML_REGEXP_QUANT_ONCE)) { + to = xmlRegNewState(ctxt); + xmlRegStatePush(ctxt, to); + ctxt->state = to; + xmlFAGenerateEpsilonTransition(ctxt, atom->stop, to); +#endif + } + switch (atom->quant) { + case XML_REGEXP_QUANT_OPT: + atom->quant = XML_REGEXP_QUANT_ONCE; + /* + * transition done to the state after end of atom. + * 1. set transition from atom start to new state + * 2. set transition from atom end to this state. + */ + xmlFAGenerateEpsilonTransition(ctxt, atom->start, 0); + xmlFAGenerateEpsilonTransition(ctxt, atom->stop, ctxt->state); + break; + case XML_REGEXP_QUANT_MULT: + atom->quant = XML_REGEXP_QUANT_ONCE; + xmlFAGenerateEpsilonTransition(ctxt, atom->start, atom->stop); + xmlFAGenerateEpsilonTransition(ctxt, atom->stop, atom->start); + break; + case XML_REGEXP_QUANT_PLUS: + atom->quant = XML_REGEXP_QUANT_ONCE; + xmlFAGenerateEpsilonTransition(ctxt, atom->stop, atom->start); + break; + case XML_REGEXP_QUANT_RANGE: { + int counter; + xmlRegStatePtr newstate; + + /* + * This one is nasty: + * 1/ if range has minOccurs == 0, create a new state + * and create epsilon transitions from atom->start + * to atom->stop, as well as atom->start to the new + * state + * 2/ register a new counter + * 3/ register an epsilon transition associated to + * this counter going from atom->stop to atom->start + * 4/ create a new state + * 5/ generate a counted transition from atom->stop to + * that state + */ + if (atom->min == 0) { + xmlFAGenerateEpsilonTransition(ctxt, atom->start, + atom->stop); + newstate = xmlRegNewState(ctxt); + xmlRegStatePush(ctxt, newstate); + ctxt->state = newstate; + xmlFAGenerateEpsilonTransition(ctxt, atom->start, + newstate); + } + counter = xmlRegGetCounter(ctxt); + ctxt->counters[counter].min = atom->min - 1; + ctxt->counters[counter].max = atom->max - 1; + atom->min = 0; + atom->max = 0; + atom->quant = XML_REGEXP_QUANT_ONCE; + if (to != NULL) { + newstate = to; + } else { + newstate = xmlRegNewState(ctxt); + xmlRegStatePush(ctxt, newstate); + } + ctxt->state = newstate; + xmlFAGenerateCountedTransition(ctxt, atom->stop, + newstate, counter); + + /* + * first check count and if OK jump forward; + * if checking fail increment count and jump back + */ + xmlFAGenerateCountedEpsilonTransition(ctxt, atom->stop, + atom->start, counter); + } + default: + break; + } + return(0); + } + if ((atom->min == 0) && (atom->max == 0) && + (atom->quant == XML_REGEXP_QUANT_RANGE)) { + /* + * we can discard the atom and generate an epsilon transition instead + */ + if (to == NULL) { + to = xmlRegNewState(ctxt); + if (to != NULL) + xmlRegStatePush(ctxt, to); + else { + return(-1); + } + } + xmlFAGenerateEpsilonTransition(ctxt, from, to); + ctxt->state = to; + xmlRegFreeAtom(atom); + return(0); + } + if (to == NULL) { + to = xmlRegNewState(ctxt); + if (to != NULL) + xmlRegStatePush(ctxt, to); + else { + return(-1); + } + } + if (xmlRegAtomPush(ctxt, atom) < 0) { + return(-1); + } + xmlRegStateAddTrans(ctxt, from, atom, to, -1, -1); + ctxt->state = to; + switch (atom->quant) { + case XML_REGEXP_QUANT_OPT: + atom->quant = XML_REGEXP_QUANT_ONCE; + xmlFAGenerateEpsilonTransition(ctxt, from, to); + break; + case XML_REGEXP_QUANT_MULT: + atom->quant = XML_REGEXP_QUANT_ONCE; + xmlFAGenerateEpsilonTransition(ctxt, from, to); + xmlRegStateAddTrans(ctxt, to, atom, to, -1, -1); + break; + case XML_REGEXP_QUANT_PLUS: + atom->quant = XML_REGEXP_QUANT_ONCE; + xmlRegStateAddTrans(ctxt, to, atom, to, -1, -1); + break; + default: + break; + } + return(0); +} + +/** + * xmlFAReduceEpsilonTransitions: + * @ctxt: a regexp parser context + * @fromnr: the from state + * @tonr: the to state + * @counter: should that transition be associated to a counted + * + */ +static void +xmlFAReduceEpsilonTransitions(xmlRegParserCtxtPtr ctxt, int fromnr, + int tonr, int counter) { + int transnr; + xmlRegStatePtr from; + xmlRegStatePtr to; + +#ifdef DEBUG_REGEXP_GRAPH + printf("xmlFAReduceEpsilonTransitions(%d, %d)\n", fromnr, tonr); +#endif + from = ctxt->states[fromnr]; + if (from == NULL) + return; + to = ctxt->states[tonr]; + if (to == NULL) + return; + if ((to->mark == XML_REGEXP_MARK_START) || + (to->mark == XML_REGEXP_MARK_VISITED)) + return; + + to->mark = XML_REGEXP_MARK_VISITED; + if (to->type == XML_REGEXP_FINAL_STATE) { +#ifdef DEBUG_REGEXP_GRAPH + printf("State %d is final, so %d becomes final\n", tonr, fromnr); +#endif + from->type = XML_REGEXP_FINAL_STATE; + } + for (transnr = 0;transnr < to->nbTrans;transnr++) { + if (to->trans[transnr].to < 0) + continue; + if (to->trans[transnr].atom == NULL) { + /* + * Don't remove counted transitions + * Don't loop either + */ + if (to->trans[transnr].to != fromnr) { + if (to->trans[transnr].count >= 0) { + int newto = to->trans[transnr].to; + + xmlRegStateAddTrans(ctxt, from, NULL, + ctxt->states[newto], + -1, to->trans[transnr].count); + } else { +#ifdef DEBUG_REGEXP_GRAPH + printf("Found epsilon trans %d from %d to %d\n", + transnr, tonr, to->trans[transnr].to); +#endif + if (to->trans[transnr].counter >= 0) { + xmlFAReduceEpsilonTransitions(ctxt, fromnr, + to->trans[transnr].to, + to->trans[transnr].counter); + } else { + xmlFAReduceEpsilonTransitions(ctxt, fromnr, + to->trans[transnr].to, + counter); + } + } + } + } else { + int newto = to->trans[transnr].to; + + if (to->trans[transnr].counter >= 0) { + xmlRegStateAddTrans(ctxt, from, to->trans[transnr].atom, + ctxt->states[newto], + to->trans[transnr].counter, -1); + } else { + xmlRegStateAddTrans(ctxt, from, to->trans[transnr].atom, + ctxt->states[newto], counter, -1); + } + } + } + to->mark = XML_REGEXP_MARK_NORMAL; +} + +/** + * xmlFAEliminateSimpleEpsilonTransitions: + * @ctxt: a regexp parser context + * + * Eliminating general epsilon transitions can get costly in the general + * algorithm due to the large amount of generated new transitions and + * associated comparisons. However for simple epsilon transition used just + * to separate building blocks when generating the automata this can be + * reduced to state elimination: + * - if there exists an epsilon from X to Y + * - if there is no other transition from X + * then X and Y are semantically equivalent and X can be eliminated + * If X is the start state then make Y the start state, else replace the + * target of all transitions to X by transitions to Y. + */ +static void +xmlFAEliminateSimpleEpsilonTransitions(xmlRegParserCtxtPtr ctxt) { + int statenr, i, j, newto; + xmlRegStatePtr state, tmp; + + for (statenr = 0;statenr < ctxt->nbStates;statenr++) { + state = ctxt->states[statenr]; + if (state == NULL) + continue; + if (state->nbTrans != 1) + continue; + /* is the only transition out a basic transition */ + if ((state->trans[0].atom == NULL) && + (state->trans[0].to >= 0) && + (state->trans[0].to != statenr) && + (state->trans[0].counter < 0) && + (state->trans[0].count < 0)) { + newto = state->trans[0].to; + + if (state->type == XML_REGEXP_START_STATE) { +#ifdef DEBUG_REGEXP_GRAPH + printf("Found simple epsilon trans from start %d to %d\n", + statenr, newto); +#endif + } else { +#ifdef DEBUG_REGEXP_GRAPH + printf("Found simple epsilon trans from %d to %d\n", + statenr, newto); +#endif + for (i = 0;i < state->nbTransTo;i++) { + tmp = ctxt->states[state->transTo[i]]; + for (j = 0;j < tmp->nbTrans;j++) { + if (tmp->trans[j].to == statenr) { + tmp->trans[j].to = newto; +#ifdef DEBUG_REGEXP_GRAPH + printf("Changed transition %d on %d to go to %d\n", + j, tmp->no, newto); +#endif + xmlRegStateAddTransTo(ctxt, ctxt->states[newto], + tmp->no); + } + } + } +#if 0 + for (i = 0;i < ctxt->nbStates;i++) { + tmp = ctxt->states[i]; + for (j = 0;j < tmp->nbTrans;j++) { + if (tmp->trans[j].to == statenr) { + tmp->trans[j].to = newto; +#ifdef DEBUG_REGEXP_GRAPH + printf("Changed transition %d on %d to go to %d\n", + j, tmp->no, newto); +#endif + } + } + } +#endif + if (state->type == XML_REGEXP_FINAL_STATE) + ctxt->states[newto]->type = XML_REGEXP_FINAL_STATE; + /* eliminate the transition completely */ + state->nbTrans = 0; + + + } + + } + } +} +/** + * xmlFAEliminateEpsilonTransitions: + * @ctxt: a regexp parser context + * + */ +static void +xmlFAEliminateEpsilonTransitions(xmlRegParserCtxtPtr ctxt) { + int statenr, transnr; + xmlRegStatePtr state; + int has_epsilon; + + if (ctxt->states == NULL) return; + + xmlFAEliminateSimpleEpsilonTransitions(ctxt); + + has_epsilon = 0; + + /* + * build the completed transitions bypassing the epsilons + * Use a marking algorithm to avoid loops + * mark sink states too. + */ + for (statenr = 0;statenr < ctxt->nbStates;statenr++) { + state = ctxt->states[statenr]; + if (state == NULL) + continue; + if ((state->nbTrans == 0) && + (state->type != XML_REGEXP_FINAL_STATE)) { + state->type = XML_REGEXP_SINK_STATE; + } + for (transnr = 0;transnr < state->nbTrans;transnr++) { + if ((state->trans[transnr].atom == NULL) && + (state->trans[transnr].to >= 0)) { + if (state->trans[transnr].to == statenr) { + state->trans[transnr].to = -1; +#ifdef DEBUG_REGEXP_GRAPH + printf("Removed loopback epsilon trans %d on %d\n", + transnr, statenr); +#endif + } else if (state->trans[transnr].count < 0) { + int newto = state->trans[transnr].to; + +#ifdef DEBUG_REGEXP_GRAPH + printf("Found epsilon trans %d from %d to %d\n", + transnr, statenr, newto); +#endif + state->mark = XML_REGEXP_MARK_START; + has_epsilon = 1; + xmlFAReduceEpsilonTransitions(ctxt, statenr, + newto, state->trans[transnr].counter); + state->mark = XML_REGEXP_MARK_NORMAL; +#ifdef DEBUG_REGEXP_GRAPH + } else { + printf("Found counted transition %d on %d\n", + transnr, statenr); +#endif + } + } + } + } + /* + * Eliminate the epsilon transitions + */ + if (has_epsilon) { + for (statenr = 0;statenr < ctxt->nbStates;statenr++) { + state = ctxt->states[statenr]; + if (state == NULL) + continue; + for (transnr = 0;transnr < state->nbTrans;transnr++) { + xmlRegTransPtr trans = &(state->trans[transnr]); + if ((trans->atom == NULL) && + (trans->count < 0) && + (trans->to >= 0)) { + trans->to = -1; + } + } + } + } + + /* + * Use this pass to detect unreachable states too + */ + for (statenr = 0;statenr < ctxt->nbStates;statenr++) { + state = ctxt->states[statenr]; + if (state != NULL) + state->reached = XML_REGEXP_MARK_NORMAL; + } + state = ctxt->states[0]; + if (state != NULL) + state->reached = XML_REGEXP_MARK_START; + while (state != NULL) { + xmlRegStatePtr target = NULL; + state->reached = XML_REGEXP_MARK_VISITED; + /* + * Mark all states reachable from the current reachable state + */ + for (transnr = 0;transnr < state->nbTrans;transnr++) { + if ((state->trans[transnr].to >= 0) && + ((state->trans[transnr].atom != NULL) || + (state->trans[transnr].count >= 0))) { + int newto = state->trans[transnr].to; + + if (ctxt->states[newto] == NULL) + continue; + if (ctxt->states[newto]->reached == XML_REGEXP_MARK_NORMAL) { + ctxt->states[newto]->reached = XML_REGEXP_MARK_START; + target = ctxt->states[newto]; + } + } + } + + /* + * find the next accessible state not explored + */ + if (target == NULL) { + for (statenr = 1;statenr < ctxt->nbStates;statenr++) { + state = ctxt->states[statenr]; + if ((state != NULL) && (state->reached == + XML_REGEXP_MARK_START)) { + target = state; + break; + } + } + } + state = target; + } + for (statenr = 0;statenr < ctxt->nbStates;statenr++) { + state = ctxt->states[statenr]; + if ((state != NULL) && (state->reached == XML_REGEXP_MARK_NORMAL)) { +#ifdef DEBUG_REGEXP_GRAPH + printf("Removed unreachable state %d\n", statenr); +#endif + xmlRegFreeState(state); + ctxt->states[statenr] = NULL; + } + } + +} + +static int +xmlFACompareRanges(xmlRegRangePtr range1, xmlRegRangePtr range2) { + int ret = 0; + + if ((range1->type == XML_REGEXP_RANGES) || + (range2->type == XML_REGEXP_RANGES) || + (range2->type == XML_REGEXP_SUBREG) || + (range1->type == XML_REGEXP_SUBREG) || + (range1->type == XML_REGEXP_STRING) || + (range2->type == XML_REGEXP_STRING)) + return(-1); + + /* put them in order */ + if (range1->type > range2->type) { + xmlRegRangePtr tmp; + + tmp = range1; + range1 = range2; + range2 = tmp; + } + if ((range1->type == XML_REGEXP_ANYCHAR) || + (range2->type == XML_REGEXP_ANYCHAR)) { + ret = 1; + } else if ((range1->type == XML_REGEXP_EPSILON) || + (range2->type == XML_REGEXP_EPSILON)) { + return(0); + } else if (range1->type == range2->type) { + if ((range1->type != XML_REGEXP_CHARVAL) || + (range1->end < range2->start) || + (range2->end < range1->start)) + ret = 1; + else + ret = 0; + } else if (range1->type == XML_REGEXP_CHARVAL) { + int codepoint; + int neg = 0; + + /* + * just check all codepoints in the range for acceptance, + * this is usually way cheaper since done only once at + * compilation than testing over and over at runtime or + * pushing too many states when evaluating. + */ + if (((range1->neg == 0) && (range2->neg != 0)) || + ((range1->neg != 0) && (range2->neg == 0))) + neg = 1; + + for (codepoint = range1->start;codepoint <= range1->end ;codepoint++) { + ret = xmlRegCheckCharacterRange(range2->type, codepoint, + 0, range2->start, range2->end, + range2->blockName); + if (ret < 0) + return(-1); + if (((neg == 1) && (ret == 0)) || + ((neg == 0) && (ret == 1))) + return(1); + } + return(0); + } else if ((range1->type == XML_REGEXP_BLOCK_NAME) || + (range2->type == XML_REGEXP_BLOCK_NAME)) { + if (range1->type == range2->type) { + ret = xmlStrEqual(range1->blockName, range2->blockName); + } else { + /* + * comparing a block range with anything else is way + * too costly, and maintining the table is like too much + * memory too, so let's force the automata to save state + * here. + */ + return(1); + } + } else if ((range1->type < XML_REGEXP_LETTER) || + (range2->type < XML_REGEXP_LETTER)) { + if ((range1->type == XML_REGEXP_ANYSPACE) && + (range2->type == XML_REGEXP_NOTSPACE)) + ret = 0; + else if ((range1->type == XML_REGEXP_INITNAME) && + (range2->type == XML_REGEXP_NOTINITNAME)) + ret = 0; + else if ((range1->type == XML_REGEXP_NAMECHAR) && + (range2->type == XML_REGEXP_NOTNAMECHAR)) + ret = 0; + else if ((range1->type == XML_REGEXP_DECIMAL) && + (range2->type == XML_REGEXP_NOTDECIMAL)) + ret = 0; + else if ((range1->type == XML_REGEXP_REALCHAR) && + (range2->type == XML_REGEXP_NOTREALCHAR)) + ret = 0; + else { + /* same thing to limit complexity */ + return(1); + } + } else { + ret = 0; + /* range1->type < range2->type here */ + switch (range1->type) { + case XML_REGEXP_LETTER: + /* all disjoint except in the subgroups */ + if ((range2->type == XML_REGEXP_LETTER_UPPERCASE) || + (range2->type == XML_REGEXP_LETTER_LOWERCASE) || + (range2->type == XML_REGEXP_LETTER_TITLECASE) || + (range2->type == XML_REGEXP_LETTER_MODIFIER) || + (range2->type == XML_REGEXP_LETTER_OTHERS)) + ret = 1; + break; + case XML_REGEXP_MARK: + if ((range2->type == XML_REGEXP_MARK_NONSPACING) || + (range2->type == XML_REGEXP_MARK_SPACECOMBINING) || + (range2->type == XML_REGEXP_MARK_ENCLOSING)) + ret = 1; + break; + case XML_REGEXP_NUMBER: + if ((range2->type == XML_REGEXP_NUMBER_DECIMAL) || + (range2->type == XML_REGEXP_NUMBER_LETTER) || + (range2->type == XML_REGEXP_NUMBER_OTHERS)) + ret = 1; + break; + case XML_REGEXP_PUNCT: + if ((range2->type == XML_REGEXP_PUNCT_CONNECTOR) || + (range2->type == XML_REGEXP_PUNCT_DASH) || + (range2->type == XML_REGEXP_PUNCT_OPEN) || + (range2->type == XML_REGEXP_PUNCT_CLOSE) || + (range2->type == XML_REGEXP_PUNCT_INITQUOTE) || + (range2->type == XML_REGEXP_PUNCT_FINQUOTE) || + (range2->type == XML_REGEXP_PUNCT_OTHERS)) + ret = 1; + break; + case XML_REGEXP_SEPAR: + if ((range2->type == XML_REGEXP_SEPAR_SPACE) || + (range2->type == XML_REGEXP_SEPAR_LINE) || + (range2->type == XML_REGEXP_SEPAR_PARA)) + ret = 1; + break; + case XML_REGEXP_SYMBOL: + if ((range2->type == XML_REGEXP_SYMBOL_MATH) || + (range2->type == XML_REGEXP_SYMBOL_CURRENCY) || + (range2->type == XML_REGEXP_SYMBOL_MODIFIER) || + (range2->type == XML_REGEXP_SYMBOL_OTHERS)) + ret = 1; + break; + case XML_REGEXP_OTHER: + if ((range2->type == XML_REGEXP_OTHER_CONTROL) || + (range2->type == XML_REGEXP_OTHER_FORMAT) || + (range2->type == XML_REGEXP_OTHER_PRIVATE)) + ret = 1; + break; + default: + if ((range2->type >= XML_REGEXP_LETTER) && + (range2->type < XML_REGEXP_BLOCK_NAME)) + ret = 0; + else { + /* safety net ! */ + return(1); + } + } + } + if (((range1->neg == 0) && (range2->neg != 0)) || + ((range1->neg != 0) && (range2->neg == 0))) + ret = !ret; + return(1); +} + +/** + * xmlFACompareAtomTypes: + * @type1: an atom type + * @type2: an atom type + * + * Compares two atoms type to check whether they intersect in some ways, + * this is used by xmlFACompareAtoms only + * + * Returns 1 if they may intersect and 0 otherwise + */ +static int +xmlFACompareAtomTypes(xmlRegAtomType type1, xmlRegAtomType type2) { + if ((type1 == XML_REGEXP_EPSILON) || + (type1 == XML_REGEXP_CHARVAL) || + (type1 == XML_REGEXP_RANGES) || + (type1 == XML_REGEXP_SUBREG) || + (type1 == XML_REGEXP_STRING) || + (type1 == XML_REGEXP_ANYCHAR)) + return(1); + if ((type2 == XML_REGEXP_EPSILON) || + (type2 == XML_REGEXP_CHARVAL) || + (type2 == XML_REGEXP_RANGES) || + (type2 == XML_REGEXP_SUBREG) || + (type2 == XML_REGEXP_STRING) || + (type2 == XML_REGEXP_ANYCHAR)) + return(1); + + if (type1 == type2) return(1); + + /* simplify subsequent compares by making sure type1 < type2 */ + if (type1 > type2) { + xmlRegAtomType tmp = type1; + type1 = type2; + type2 = tmp; + } + switch (type1) { + case XML_REGEXP_ANYSPACE: /* \s */ + /* can't be a letter, number, mark, pontuation, symbol */ + if ((type2 == XML_REGEXP_NOTSPACE) || + ((type2 >= XML_REGEXP_LETTER) && + (type2 <= XML_REGEXP_LETTER_OTHERS)) || + ((type2 >= XML_REGEXP_NUMBER) && + (type2 <= XML_REGEXP_NUMBER_OTHERS)) || + ((type2 >= XML_REGEXP_MARK) && + (type2 <= XML_REGEXP_MARK_ENCLOSING)) || + ((type2 >= XML_REGEXP_PUNCT) && + (type2 <= XML_REGEXP_PUNCT_OTHERS)) || + ((type2 >= XML_REGEXP_SYMBOL) && + (type2 <= XML_REGEXP_SYMBOL_OTHERS)) + ) return(0); + break; + case XML_REGEXP_NOTSPACE: /* \S */ + break; + case XML_REGEXP_INITNAME: /* \l */ + /* can't be a number, mark, separator, pontuation, symbol or other */ + if ((type2 == XML_REGEXP_NOTINITNAME) || + ((type2 >= XML_REGEXP_NUMBER) && + (type2 <= XML_REGEXP_NUMBER_OTHERS)) || + ((type2 >= XML_REGEXP_MARK) && + (type2 <= XML_REGEXP_MARK_ENCLOSING)) || + ((type2 >= XML_REGEXP_SEPAR) && + (type2 <= XML_REGEXP_SEPAR_PARA)) || + ((type2 >= XML_REGEXP_PUNCT) && + (type2 <= XML_REGEXP_PUNCT_OTHERS)) || + ((type2 >= XML_REGEXP_SYMBOL) && + (type2 <= XML_REGEXP_SYMBOL_OTHERS)) || + ((type2 >= XML_REGEXP_OTHER) && + (type2 <= XML_REGEXP_OTHER_NA)) + ) return(0); + break; + case XML_REGEXP_NOTINITNAME: /* \L */ + break; + case XML_REGEXP_NAMECHAR: /* \c */ + /* can't be a mark, separator, pontuation, symbol or other */ + if ((type2 == XML_REGEXP_NOTNAMECHAR) || + ((type2 >= XML_REGEXP_MARK) && + (type2 <= XML_REGEXP_MARK_ENCLOSING)) || + ((type2 >= XML_REGEXP_PUNCT) && + (type2 <= XML_REGEXP_PUNCT_OTHERS)) || + ((type2 >= XML_REGEXP_SEPAR) && + (type2 <= XML_REGEXP_SEPAR_PARA)) || + ((type2 >= XML_REGEXP_SYMBOL) && + (type2 <= XML_REGEXP_SYMBOL_OTHERS)) || + ((type2 >= XML_REGEXP_OTHER) && + (type2 <= XML_REGEXP_OTHER_NA)) + ) return(0); + break; + case XML_REGEXP_NOTNAMECHAR: /* \C */ + break; + case XML_REGEXP_DECIMAL: /* \d */ + /* can't be a letter, mark, separator, pontuation, symbol or other */ + if ((type2 == XML_REGEXP_NOTDECIMAL) || + (type2 == XML_REGEXP_REALCHAR) || + ((type2 >= XML_REGEXP_LETTER) && + (type2 <= XML_REGEXP_LETTER_OTHERS)) || + ((type2 >= XML_REGEXP_MARK) && + (type2 <= XML_REGEXP_MARK_ENCLOSING)) || + ((type2 >= XML_REGEXP_PUNCT) && + (type2 <= XML_REGEXP_PUNCT_OTHERS)) || + ((type2 >= XML_REGEXP_SEPAR) && + (type2 <= XML_REGEXP_SEPAR_PARA)) || + ((type2 >= XML_REGEXP_SYMBOL) && + (type2 <= XML_REGEXP_SYMBOL_OTHERS)) || + ((type2 >= XML_REGEXP_OTHER) && + (type2 <= XML_REGEXP_OTHER_NA)) + )return(0); + break; + case XML_REGEXP_NOTDECIMAL: /* \D */ + break; + case XML_REGEXP_REALCHAR: /* \w */ + /* can't be a mark, separator, pontuation, symbol or other */ + if ((type2 == XML_REGEXP_NOTDECIMAL) || + ((type2 >= XML_REGEXP_MARK) && + (type2 <= XML_REGEXP_MARK_ENCLOSING)) || + ((type2 >= XML_REGEXP_PUNCT) && + (type2 <= XML_REGEXP_PUNCT_OTHERS)) || + ((type2 >= XML_REGEXP_SEPAR) && + (type2 <= XML_REGEXP_SEPAR_PARA)) || + ((type2 >= XML_REGEXP_SYMBOL) && + (type2 <= XML_REGEXP_SYMBOL_OTHERS)) || + ((type2 >= XML_REGEXP_OTHER) && + (type2 <= XML_REGEXP_OTHER_NA)) + )return(0); + break; + case XML_REGEXP_NOTREALCHAR: /* \W */ + break; + /* + * at that point we know both type 1 and type2 are from + * character categories are ordered and are different, + * it becomes simple because this is a partition + */ + case XML_REGEXP_LETTER: + if (type2 <= XML_REGEXP_LETTER_OTHERS) + return(1); + return(0); + case XML_REGEXP_LETTER_UPPERCASE: + case XML_REGEXP_LETTER_LOWERCASE: + case XML_REGEXP_LETTER_TITLECASE: + case XML_REGEXP_LETTER_MODIFIER: + case XML_REGEXP_LETTER_OTHERS: + return(0); + case XML_REGEXP_MARK: + if (type2 <= XML_REGEXP_MARK_ENCLOSING) + return(1); + return(0); + case XML_REGEXP_MARK_NONSPACING: + case XML_REGEXP_MARK_SPACECOMBINING: + case XML_REGEXP_MARK_ENCLOSING: + return(0); + case XML_REGEXP_NUMBER: + if (type2 <= XML_REGEXP_NUMBER_OTHERS) + return(1); + return(0); + case XML_REGEXP_NUMBER_DECIMAL: + case XML_REGEXP_NUMBER_LETTER: + case XML_REGEXP_NUMBER_OTHERS: + return(0); + case XML_REGEXP_PUNCT: + if (type2 <= XML_REGEXP_PUNCT_OTHERS) + return(1); + return(0); + case XML_REGEXP_PUNCT_CONNECTOR: + case XML_REGEXP_PUNCT_DASH: + case XML_REGEXP_PUNCT_OPEN: + case XML_REGEXP_PUNCT_CLOSE: + case XML_REGEXP_PUNCT_INITQUOTE: + case XML_REGEXP_PUNCT_FINQUOTE: + case XML_REGEXP_PUNCT_OTHERS: + return(0); + case XML_REGEXP_SEPAR: + if (type2 <= XML_REGEXP_SEPAR_PARA) + return(1); + return(0); + case XML_REGEXP_SEPAR_SPACE: + case XML_REGEXP_SEPAR_LINE: + case XML_REGEXP_SEPAR_PARA: + return(0); + case XML_REGEXP_SYMBOL: + if (type2 <= XML_REGEXP_SYMBOL_OTHERS) + return(1); + return(0); + case XML_REGEXP_SYMBOL_MATH: + case XML_REGEXP_SYMBOL_CURRENCY: + case XML_REGEXP_SYMBOL_MODIFIER: + case XML_REGEXP_SYMBOL_OTHERS: + return(0); + case XML_REGEXP_OTHER: + if (type2 <= XML_REGEXP_OTHER_NA) + return(1); + return(0); + case XML_REGEXP_OTHER_CONTROL: + case XML_REGEXP_OTHER_FORMAT: + case XML_REGEXP_OTHER_PRIVATE: + case XML_REGEXP_OTHER_NA: + return(0); + default: + break; + } + return(1); +} + +/** + * xmlFAEqualAtoms: + * @atom1: an atom + * @atom2: an atom + * + * Compares two atoms to check whether they are the same exactly + * this is used to remove equivalent transitions + * + * Returns 1 if same and 0 otherwise + */ +static int +xmlFAEqualAtoms(xmlRegAtomPtr atom1, xmlRegAtomPtr atom2) { + int ret = 0; + + if (atom1 == atom2) + return(1); + if ((atom1 == NULL) || (atom2 == NULL)) + return(0); + + if (atom1->type != atom2->type) + return(0); + switch (atom1->type) { + case XML_REGEXP_EPSILON: + ret = 0; + break; + case XML_REGEXP_STRING: + ret = xmlStrEqual((xmlChar *)atom1->valuep, + (xmlChar *)atom2->valuep); + break; + case XML_REGEXP_CHARVAL: + ret = (atom1->codepoint == atom2->codepoint); + break; + case XML_REGEXP_RANGES: + /* too hard to do in the general case */ + ret = 0; + default: + break; + } + return(ret); +} + +/** + * xmlFACompareAtoms: + * @atom1: an atom + * @atom2: an atom + * + * Compares two atoms to check whether they intersect in some ways, + * this is used by xmlFAComputesDeterminism and xmlFARecurseDeterminism only + * + * Returns 1 if yes and 0 otherwise + */ +static int +xmlFACompareAtoms(xmlRegAtomPtr atom1, xmlRegAtomPtr atom2) { + int ret = 1; + + if (atom1 == atom2) + return(1); + if ((atom1 == NULL) || (atom2 == NULL)) + return(0); + + if ((atom1->type == XML_REGEXP_ANYCHAR) || + (atom2->type == XML_REGEXP_ANYCHAR)) + return(1); + + if (atom1->type > atom2->type) { + xmlRegAtomPtr tmp; + tmp = atom1; + atom1 = atom2; + atom2 = tmp; + } + if (atom1->type != atom2->type) { + ret = xmlFACompareAtomTypes(atom1->type, atom2->type); + /* if they can't intersect at the type level break now */ + if (ret == 0) + return(0); + } + switch (atom1->type) { + case XML_REGEXP_STRING: + ret = xmlRegStrEqualWildcard((xmlChar *)atom1->valuep, + (xmlChar *)atom2->valuep); + break; + case XML_REGEXP_EPSILON: + goto not_determinist; + case XML_REGEXP_CHARVAL: + if (atom2->type == XML_REGEXP_CHARVAL) { + ret = (atom1->codepoint == atom2->codepoint); + } else { + ret = xmlRegCheckCharacter(atom2, atom1->codepoint); + if (ret < 0) + ret = 1; + } + break; + case XML_REGEXP_RANGES: + if (atom2->type == XML_REGEXP_RANGES) { + int i, j, res; + xmlRegRangePtr r1, r2; + + /* + * need to check that none of the ranges eventually matches + */ + for (i = 0;i < atom1->nbRanges;i++) { + for (j = 0;j < atom2->nbRanges;j++) { + r1 = atom1->ranges[i]; + r2 = atom2->ranges[j]; + res = xmlFACompareRanges(r1, r2); + if (res == 1) { + ret = 1; + goto done; + } + } + } + ret = 0; + } + break; + default: + goto not_determinist; + } +done: + if (atom1->neg != atom2->neg) { + ret = !ret; + } + if (ret == 0) + return(0); +not_determinist: + return(1); +} + +/** + * xmlFARecurseDeterminism: + * @ctxt: a regexp parser context + * + * Check whether the associated regexp is determinist, + * should be called after xmlFAEliminateEpsilonTransitions() + * + */ +static int +xmlFARecurseDeterminism(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr state, + int to, xmlRegAtomPtr atom) { + int ret = 1; + int res; + int transnr, nbTrans; + xmlRegTransPtr t1; + + if (state == NULL) + return(ret); + /* + * don't recurse on transitions potentially added in the course of + * the elimination. + */ + nbTrans = state->nbTrans; + for (transnr = 0;transnr < nbTrans;transnr++) { + t1 = &(state->trans[transnr]); + /* + * check transitions conflicting with the one looked at + */ + if (t1->atom == NULL) { + if (t1->to == -1) + continue; + res = xmlFARecurseDeterminism(ctxt, ctxt->states[t1->to], + to, atom); + if (res == 0) { + ret = 0; + /* t1->nd = 1; */ + } + continue; + } + if (t1->to != to) + continue; + if (xmlFACompareAtoms(t1->atom, atom)) { + ret = 0; + /* mark the transition as non-deterministic */ + t1->nd = 1; + } + } + return(ret); +} + +/** + * xmlFAComputesDeterminism: + * @ctxt: a regexp parser context + * + * Check whether the associated regexp is determinist, + * should be called after xmlFAEliminateEpsilonTransitions() + * + */ +static int +xmlFAComputesDeterminism(xmlRegParserCtxtPtr ctxt) { + int statenr, transnr; + xmlRegStatePtr state; + xmlRegTransPtr t1, t2, last; + int i; + int ret = 1; + +#ifdef DEBUG_REGEXP_GRAPH + printf("xmlFAComputesDeterminism\n"); + xmlRegPrintCtxt(stdout, ctxt); +#endif + if (ctxt->determinist != -1) + return(ctxt->determinist); + + /* + * First cleanup the automata removing cancelled transitions + */ + for (statenr = 0;statenr < ctxt->nbStates;statenr++) { + state = ctxt->states[statenr]; + if (state == NULL) + continue; + if (state->nbTrans < 2) + continue; + for (transnr = 0;transnr < state->nbTrans;transnr++) { + t1 = &(state->trans[transnr]); + /* + * Determinism checks in case of counted or all transitions + * will have to be handled separately + */ + if (t1->atom == NULL) { + /* t1->nd = 1; */ + continue; + } + if (t1->to == -1) /* eliminated */ + continue; + for (i = 0;i < transnr;i++) { + t2 = &(state->trans[i]); + if (t2->to == -1) /* eliminated */ + continue; + if (t2->atom != NULL) { + if (t1->to == t2->to) { + if (xmlFAEqualAtoms(t1->atom, t2->atom)) + t2->to = -1; /* eliminated */ + } + } + } + } + } + + /* + * Check for all states that there aren't 2 transitions + * with the same atom and a different target. + */ + for (statenr = 0;statenr < ctxt->nbStates;statenr++) { + state = ctxt->states[statenr]; + if (state == NULL) + continue; + if (state->nbTrans < 2) + continue; + last = NULL; + for (transnr = 0;transnr < state->nbTrans;transnr++) { + t1 = &(state->trans[transnr]); + /* + * Determinism checks in case of counted or all transitions + * will have to be handled separately + */ + if (t1->atom == NULL) { + continue; + } + if (t1->to == -1) /* eliminated */ + continue; + for (i = 0;i < transnr;i++) { + t2 = &(state->trans[i]); + if (t2->to == -1) /* eliminated */ + continue; + if (t2->atom != NULL) { + /* not determinist ! */ + if (xmlFACompareAtoms(t1->atom, t2->atom)) { + ret = 0; + /* mark the transitions as non-deterministic ones */ + t1->nd = 1; + t2->nd = 1; + last = t1; + } + } else if (t1->to != -1) { + /* + * do the closure in case of remaining specific + * epsilon transitions like choices or all + */ + ret = xmlFARecurseDeterminism(ctxt, ctxt->states[t1->to], + t2->to, t2->atom); + /* don't shortcut the computation so all non deterministic + transition get marked down + if (ret == 0) + return(0); + */ + if (ret == 0) { + t1->nd = 1; + /* t2->nd = 1; */ + last = t1; + } + } + } + /* don't shortcut the computation so all non deterministic + transition get marked down + if (ret == 0) + break; */ + } + + /* + * mark specifically the last non-deterministic transition + * from a state since there is no need to set-up rollback + * from it + */ + if (last != NULL) { + last->nd = 2; + } + + /* don't shortcut the computation so all non deterministic + transition get marked down + if (ret == 0) + break; */ + } + + ctxt->determinist = ret; + return(ret); +} + +/************************************************************************ + * * + * Routines to check input against transition atoms * + * * + ************************************************************************/ + +static int +xmlRegCheckCharacterRange(xmlRegAtomType type, int codepoint, int neg, + int start, int end, const xmlChar *blockName) { + int ret = 0; + + switch (type) { + case XML_REGEXP_STRING: + case XML_REGEXP_SUBREG: + case XML_REGEXP_RANGES: + case XML_REGEXP_EPSILON: + return(-1); + case XML_REGEXP_ANYCHAR: + ret = ((codepoint != '\n') && (codepoint != '\r')); + break; + case XML_REGEXP_CHARVAL: + ret = ((codepoint >= start) && (codepoint <= end)); + break; + case XML_REGEXP_NOTSPACE: + neg = !neg; + case XML_REGEXP_ANYSPACE: + ret = ((codepoint == '\n') || (codepoint == '\r') || + (codepoint == '\t') || (codepoint == ' ')); + break; + case XML_REGEXP_NOTINITNAME: + neg = !neg; + case XML_REGEXP_INITNAME: + ret = (IS_LETTER(codepoint) || + (codepoint == '_') || (codepoint == ':')); + break; + case XML_REGEXP_NOTNAMECHAR: + neg = !neg; + case XML_REGEXP_NAMECHAR: + ret = (IS_LETTER(codepoint) || IS_DIGIT(codepoint) || + (codepoint == '.') || (codepoint == '-') || + (codepoint == '_') || (codepoint == ':') || + IS_COMBINING(codepoint) || IS_EXTENDER(codepoint)); + break; + case XML_REGEXP_NOTDECIMAL: + neg = !neg; + case XML_REGEXP_DECIMAL: + ret = xmlUCSIsCatNd(codepoint); + break; + case XML_REGEXP_REALCHAR: + neg = !neg; + case XML_REGEXP_NOTREALCHAR: + ret = xmlUCSIsCatP(codepoint); + if (ret == 0) + ret = xmlUCSIsCatZ(codepoint); + if (ret == 0) + ret = xmlUCSIsCatC(codepoint); + break; + case XML_REGEXP_LETTER: + ret = xmlUCSIsCatL(codepoint); + break; + case XML_REGEXP_LETTER_UPPERCASE: + ret = xmlUCSIsCatLu(codepoint); + break; + case XML_REGEXP_LETTER_LOWERCASE: + ret = xmlUCSIsCatLl(codepoint); + break; + case XML_REGEXP_LETTER_TITLECASE: + ret = xmlUCSIsCatLt(codepoint); + break; + case XML_REGEXP_LETTER_MODIFIER: + ret = xmlUCSIsCatLm(codepoint); + break; + case XML_REGEXP_LETTER_OTHERS: + ret = xmlUCSIsCatLo(codepoint); + break; + case XML_REGEXP_MARK: + ret = xmlUCSIsCatM(codepoint); + break; + case XML_REGEXP_MARK_NONSPACING: + ret = xmlUCSIsCatMn(codepoint); + break; + case XML_REGEXP_MARK_SPACECOMBINING: + ret = xmlUCSIsCatMc(codepoint); + break; + case XML_REGEXP_MARK_ENCLOSING: + ret = xmlUCSIsCatMe(codepoint); + break; + case XML_REGEXP_NUMBER: + ret = xmlUCSIsCatN(codepoint); + break; + case XML_REGEXP_NUMBER_DECIMAL: + ret = xmlUCSIsCatNd(codepoint); + break; + case XML_REGEXP_NUMBER_LETTER: + ret = xmlUCSIsCatNl(codepoint); + break; + case XML_REGEXP_NUMBER_OTHERS: + ret = xmlUCSIsCatNo(codepoint); + break; + case XML_REGEXP_PUNCT: + ret = xmlUCSIsCatP(codepoint); + break; + case XML_REGEXP_PUNCT_CONNECTOR: + ret = xmlUCSIsCatPc(codepoint); + break; + case XML_REGEXP_PUNCT_DASH: + ret = xmlUCSIsCatPd(codepoint); + break; + case XML_REGEXP_PUNCT_OPEN: + ret = xmlUCSIsCatPs(codepoint); + break; + case XML_REGEXP_PUNCT_CLOSE: + ret = xmlUCSIsCatPe(codepoint); + break; + case XML_REGEXP_PUNCT_INITQUOTE: + ret = xmlUCSIsCatPi(codepoint); + break; + case XML_REGEXP_PUNCT_FINQUOTE: + ret = xmlUCSIsCatPf(codepoint); + break; + case XML_REGEXP_PUNCT_OTHERS: + ret = xmlUCSIsCatPo(codepoint); + break; + case XML_REGEXP_SEPAR: + ret = xmlUCSIsCatZ(codepoint); + break; + case XML_REGEXP_SEPAR_SPACE: + ret = xmlUCSIsCatZs(codepoint); + break; + case XML_REGEXP_SEPAR_LINE: + ret = xmlUCSIsCatZl(codepoint); + break; + case XML_REGEXP_SEPAR_PARA: + ret = xmlUCSIsCatZp(codepoint); + break; + case XML_REGEXP_SYMBOL: + ret = xmlUCSIsCatS(codepoint); + break; + case XML_REGEXP_SYMBOL_MATH: + ret = xmlUCSIsCatSm(codepoint); + break; + case XML_REGEXP_SYMBOL_CURRENCY: + ret = xmlUCSIsCatSc(codepoint); + break; + case XML_REGEXP_SYMBOL_MODIFIER: + ret = xmlUCSIsCatSk(codepoint); + break; + case XML_REGEXP_SYMBOL_OTHERS: + ret = xmlUCSIsCatSo(codepoint); + break; + case XML_REGEXP_OTHER: + ret = xmlUCSIsCatC(codepoint); + break; + case XML_REGEXP_OTHER_CONTROL: + ret = xmlUCSIsCatCc(codepoint); + break; + case XML_REGEXP_OTHER_FORMAT: + ret = xmlUCSIsCatCf(codepoint); + break; + case XML_REGEXP_OTHER_PRIVATE: + ret = xmlUCSIsCatCo(codepoint); + break; + case XML_REGEXP_OTHER_NA: + /* ret = xmlUCSIsCatCn(codepoint); */ + /* Seems it doesn't exist anymore in recent Unicode releases */ + ret = 0; + break; + case XML_REGEXP_BLOCK_NAME: + ret = xmlUCSIsBlock(codepoint, (const char *) blockName); + break; + } + if (neg) + return(!ret); + return(ret); +} + +static int +xmlRegCheckCharacter(xmlRegAtomPtr atom, int codepoint) { + int i, ret = 0; + xmlRegRangePtr range; + + if ((atom == NULL) || (!IS_CHAR(codepoint))) + return(-1); + + switch (atom->type) { + case XML_REGEXP_SUBREG: + case XML_REGEXP_EPSILON: + return(-1); + case XML_REGEXP_CHARVAL: + return(codepoint == atom->codepoint); + case XML_REGEXP_RANGES: { + int accept = 0; + + for (i = 0;i < atom->nbRanges;i++) { + range = atom->ranges[i]; + if (range->neg == 2) { + ret = xmlRegCheckCharacterRange(range->type, codepoint, + 0, range->start, range->end, + range->blockName); + if (ret != 0) + return(0); /* excluded char */ + } else if (range->neg) { + ret = xmlRegCheckCharacterRange(range->type, codepoint, + 0, range->start, range->end, + range->blockName); + if (ret == 0) + accept = 1; + else + return(0); + } else { + ret = xmlRegCheckCharacterRange(range->type, codepoint, + 0, range->start, range->end, + range->blockName); + if (ret != 0) + accept = 1; /* might still be excluded */ + } + } + return(accept); + } + case XML_REGEXP_STRING: + printf("TODO: XML_REGEXP_STRING\n"); + return(-1); + case XML_REGEXP_ANYCHAR: + case XML_REGEXP_ANYSPACE: + case XML_REGEXP_NOTSPACE: + case XML_REGEXP_INITNAME: + case XML_REGEXP_NOTINITNAME: + case XML_REGEXP_NAMECHAR: + case XML_REGEXP_NOTNAMECHAR: + case XML_REGEXP_DECIMAL: + case XML_REGEXP_NOTDECIMAL: + case XML_REGEXP_REALCHAR: + case XML_REGEXP_NOTREALCHAR: + case XML_REGEXP_LETTER: + case XML_REGEXP_LETTER_UPPERCASE: + case XML_REGEXP_LETTER_LOWERCASE: + case XML_REGEXP_LETTER_TITLECASE: + case XML_REGEXP_LETTER_MODIFIER: + case XML_REGEXP_LETTER_OTHERS: + case XML_REGEXP_MARK: + case XML_REGEXP_MARK_NONSPACING: + case XML_REGEXP_MARK_SPACECOMBINING: + case XML_REGEXP_MARK_ENCLOSING: + case XML_REGEXP_NUMBER: + case XML_REGEXP_NUMBER_DECIMAL: + case XML_REGEXP_NUMBER_LETTER: + case XML_REGEXP_NUMBER_OTHERS: + case XML_REGEXP_PUNCT: + case XML_REGEXP_PUNCT_CONNECTOR: + case XML_REGEXP_PUNCT_DASH: + case XML_REGEXP_PUNCT_OPEN: + case XML_REGEXP_PUNCT_CLOSE: + case XML_REGEXP_PUNCT_INITQUOTE: + case XML_REGEXP_PUNCT_FINQUOTE: + case XML_REGEXP_PUNCT_OTHERS: + case XML_REGEXP_SEPAR: + case XML_REGEXP_SEPAR_SPACE: + case XML_REGEXP_SEPAR_LINE: + case XML_REGEXP_SEPAR_PARA: + case XML_REGEXP_SYMBOL: + case XML_REGEXP_SYMBOL_MATH: + case XML_REGEXP_SYMBOL_CURRENCY: + case XML_REGEXP_SYMBOL_MODIFIER: + case XML_REGEXP_SYMBOL_OTHERS: + case XML_REGEXP_OTHER: + case XML_REGEXP_OTHER_CONTROL: + case XML_REGEXP_OTHER_FORMAT: + case XML_REGEXP_OTHER_PRIVATE: + case XML_REGEXP_OTHER_NA: + case XML_REGEXP_BLOCK_NAME: + ret = xmlRegCheckCharacterRange(atom->type, codepoint, 0, 0, 0, + (const xmlChar *)atom->valuep); + if (atom->neg) + ret = !ret; + break; + } + return(ret); +} + +/************************************************************************ + * * + * Saving and restoring state of an execution context * + * * + ************************************************************************/ + +#ifdef DEBUG_REGEXP_EXEC +static void +xmlFARegDebugExec(xmlRegExecCtxtPtr exec) { + printf("state: %d:%d:idx %d", exec->state->no, exec->transno, exec->index); + if (exec->inputStack != NULL) { + int i; + printf(": "); + for (i = 0;(i < 3) && (i < exec->inputStackNr);i++) + printf("%s ", exec->inputStack[exec->inputStackNr - (i + 1)]); + } else { + printf(": %s", &(exec->inputString[exec->index])); + } + printf("\n"); +} +#endif + +static void +xmlFARegExecSave(xmlRegExecCtxtPtr exec) { +#ifdef DEBUG_REGEXP_EXEC + printf("saving "); + exec->transno++; + xmlFARegDebugExec(exec); + exec->transno--; +#endif +#ifdef MAX_PUSH + if (exec->nbPush > MAX_PUSH) { + return; + } + exec->nbPush++; +#endif + + if (exec->maxRollbacks == 0) { + exec->maxRollbacks = 4; + exec->rollbacks = (xmlRegExecRollback *) xmlMalloc(exec->maxRollbacks * + sizeof(xmlRegExecRollback)); + if (exec->rollbacks == NULL) { + xmlRegexpErrMemory(NULL, "saving regexp"); + exec->maxRollbacks = 0; + return; + } + memset(exec->rollbacks, 0, + exec->maxRollbacks * sizeof(xmlRegExecRollback)); + } else if (exec->nbRollbacks >= exec->maxRollbacks) { + xmlRegExecRollback *tmp; + int len = exec->maxRollbacks; + + exec->maxRollbacks *= 2; + tmp = (xmlRegExecRollback *) xmlRealloc(exec->rollbacks, + exec->maxRollbacks * sizeof(xmlRegExecRollback)); + if (tmp == NULL) { + xmlRegexpErrMemory(NULL, "saving regexp"); + exec->maxRollbacks /= 2; + return; + } + exec->rollbacks = tmp; + tmp = &exec->rollbacks[len]; + memset(tmp, 0, (exec->maxRollbacks - len) * sizeof(xmlRegExecRollback)); + } + exec->rollbacks[exec->nbRollbacks].state = exec->state; + exec->rollbacks[exec->nbRollbacks].index = exec->index; + exec->rollbacks[exec->nbRollbacks].nextbranch = exec->transno + 1; + if (exec->comp->nbCounters > 0) { + if (exec->rollbacks[exec->nbRollbacks].counts == NULL) { + exec->rollbacks[exec->nbRollbacks].counts = (int *) + xmlMalloc(exec->comp->nbCounters * sizeof(int)); + if (exec->rollbacks[exec->nbRollbacks].counts == NULL) { + xmlRegexpErrMemory(NULL, "saving regexp"); + exec->status = -5; + return; + } + } + memcpy(exec->rollbacks[exec->nbRollbacks].counts, exec->counts, + exec->comp->nbCounters * sizeof(int)); + } + exec->nbRollbacks++; +} + +static void +xmlFARegExecRollBack(xmlRegExecCtxtPtr exec) { + if (exec->nbRollbacks <= 0) { + exec->status = -1; +#ifdef DEBUG_REGEXP_EXEC + printf("rollback failed on empty stack\n"); +#endif + return; + } + exec->nbRollbacks--; + exec->state = exec->rollbacks[exec->nbRollbacks].state; + exec->index = exec->rollbacks[exec->nbRollbacks].index; + exec->transno = exec->rollbacks[exec->nbRollbacks].nextbranch; + if (exec->comp->nbCounters > 0) { + if (exec->rollbacks[exec->nbRollbacks].counts == NULL) { + fprintf(stderr, "exec save: allocation failed"); + exec->status = -6; + return; + } + memcpy(exec->counts, exec->rollbacks[exec->nbRollbacks].counts, + exec->comp->nbCounters * sizeof(int)); + } + +#ifdef DEBUG_REGEXP_EXEC + printf("restored "); + xmlFARegDebugExec(exec); +#endif +} + +/************************************************************************ + * * + * Verifier, running an input against a compiled regexp * + * * + ************************************************************************/ + +static int +xmlFARegExec(xmlRegexpPtr comp, const xmlChar *content) { + xmlRegExecCtxt execval; + xmlRegExecCtxtPtr exec = &execval; + int ret, codepoint = 0, len, deter; + + exec->inputString = content; + exec->index = 0; + exec->nbPush = 0; + exec->determinist = 1; + exec->maxRollbacks = 0; + exec->nbRollbacks = 0; + exec->rollbacks = NULL; + exec->status = 0; + exec->comp = comp; + exec->state = comp->states[0]; + exec->transno = 0; + exec->transcount = 0; + exec->inputStack = NULL; + exec->inputStackMax = 0; + if (comp->nbCounters > 0) { + exec->counts = (int *) xmlMalloc(comp->nbCounters * sizeof(int)); + if (exec->counts == NULL) { + xmlRegexpErrMemory(NULL, "running regexp"); + return(-1); + } + memset(exec->counts, 0, comp->nbCounters * sizeof(int)); + } else + exec->counts = NULL; + while ((exec->status == 0) && + ((exec->inputString[exec->index] != 0) || + (exec->state->type != XML_REGEXP_FINAL_STATE))) { + xmlRegTransPtr trans; + xmlRegAtomPtr atom; + + /* + * If end of input on non-terminal state, rollback, however we may + * still have epsilon like transition for counted transitions + * on counters, in that case don't break too early. Additionally, + * if we are working on a range like "AB{0,2}", where B is not present, + * we don't want to break. + */ + len = 1; + if ((exec->inputString[exec->index] == 0) && (exec->counts == NULL)) { + /* + * if there is a transition, we must check if + * atom allows minOccurs of 0 + */ + if (exec->transno < exec->state->nbTrans) { + trans = &exec->state->trans[exec->transno]; + if (trans->to >=0) { + atom = trans->atom; + if (!((atom->min == 0) && (atom->max > 0))) + goto rollback; + } + } else + goto rollback; + } + + exec->transcount = 0; + for (;exec->transno < exec->state->nbTrans;exec->transno++) { + trans = &exec->state->trans[exec->transno]; + if (trans->to < 0) + continue; + atom = trans->atom; + ret = 0; + deter = 1; + if (trans->count >= 0) { + int count; + xmlRegCounterPtr counter; + + if (exec->counts == NULL) { + exec->status = -1; + goto error; + } + /* + * A counted transition. + */ + + count = exec->counts[trans->count]; + counter = &exec->comp->counters[trans->count]; +#ifdef DEBUG_REGEXP_EXEC + printf("testing count %d: val %d, min %d, max %d\n", + trans->count, count, counter->min, counter->max); +#endif + ret = ((count >= counter->min) && (count <= counter->max)); + if ((ret) && (counter->min != counter->max)) + deter = 0; + } else if (atom == NULL) { + fprintf(stderr, "epsilon transition left at runtime\n"); + exec->status = -2; + break; + } else if (exec->inputString[exec->index] != 0) { + codepoint = CUR_SCHAR(&(exec->inputString[exec->index]), len); + ret = xmlRegCheckCharacter(atom, codepoint); + if ((ret == 1) && (atom->min >= 0) && (atom->max > 0)) { + xmlRegStatePtr to = comp->states[trans->to]; + + /* + * this is a multiple input sequence + * If there is a counter associated increment it now. + * before potentially saving and rollback + */ + if (trans->counter >= 0) { + if (exec->counts == NULL) { + exec->status = -1; + goto error; + } +#ifdef DEBUG_REGEXP_EXEC + printf("Increasing count %d\n", trans->counter); +#endif + exec->counts[trans->counter]++; + } + if (exec->state->nbTrans > exec->transno + 1) { + xmlFARegExecSave(exec); + } + exec->transcount = 1; + do { + /* + * Try to progress as much as possible on the input + */ + if (exec->transcount == atom->max) { + break; + } + exec->index += len; + /* + * End of input: stop here + */ + if (exec->inputString[exec->index] == 0) { + exec->index -= len; + break; + } + if (exec->transcount >= atom->min) { + int transno = exec->transno; + xmlRegStatePtr state = exec->state; + + /* + * The transition is acceptable save it + */ + exec->transno = -1; /* trick */ + exec->state = to; + xmlFARegExecSave(exec); + exec->transno = transno; + exec->state = state; + } + codepoint = CUR_SCHAR(&(exec->inputString[exec->index]), + len); + ret = xmlRegCheckCharacter(atom, codepoint); + exec->transcount++; + } while (ret == 1); + if (exec->transcount < atom->min) + ret = 0; + + /* + * If the last check failed but one transition was found + * possible, rollback + */ + if (ret < 0) + ret = 0; + if (ret == 0) { + goto rollback; + } + if (trans->counter >= 0) { + if (exec->counts == NULL) { + exec->status = -1; + goto error; + } +#ifdef DEBUG_REGEXP_EXEC + printf("Decreasing count %d\n", trans->counter); +#endif + exec->counts[trans->counter]--; + } + } else if ((ret == 0) && (atom->min == 0) && (atom->max > 0)) { + /* + * we don't match on the codepoint, but minOccurs of 0 + * says that's ok. Setting len to 0 inhibits stepping + * over the codepoint. + */ + exec->transcount = 1; + len = 0; + ret = 1; + } + } else if ((atom->min == 0) && (atom->max > 0)) { + /* another spot to match when minOccurs is 0 */ + exec->transcount = 1; + len = 0; + ret = 1; + } + if (ret == 1) { + if ((trans->nd == 1) || + ((trans->count >= 0) && (deter == 0) && + (exec->state->nbTrans > exec->transno + 1))) { +#ifdef DEBUG_REGEXP_EXEC + if (trans->nd == 1) + printf("Saving on nd transition atom %d for %c at %d\n", + trans->atom->no, codepoint, exec->index); + else + printf("Saving on counted transition count %d for %c at %d\n", + trans->count, codepoint, exec->index); +#endif + xmlFARegExecSave(exec); + } + if (trans->counter >= 0) { + if (exec->counts == NULL) { + exec->status = -1; + goto error; + } +#ifdef DEBUG_REGEXP_EXEC + printf("Increasing count %d\n", trans->counter); +#endif + exec->counts[trans->counter]++; + } + if ((trans->count >= 0) && + (trans->count < REGEXP_ALL_COUNTER)) { + if (exec->counts == NULL) { + exec->status = -1; + goto error; + } +#ifdef DEBUG_REGEXP_EXEC + printf("resetting count %d on transition\n", + trans->count); +#endif + exec->counts[trans->count] = 0; + } +#ifdef DEBUG_REGEXP_EXEC + printf("entering state %d\n", trans->to); +#endif + exec->state = comp->states[trans->to]; + exec->transno = 0; + if (trans->atom != NULL) { + exec->index += len; + } + goto progress; + } else if (ret < 0) { + exec->status = -4; + break; + } + } + if ((exec->transno != 0) || (exec->state->nbTrans == 0)) { +rollback: + /* + * Failed to find a way out + */ + exec->determinist = 0; +#ifdef DEBUG_REGEXP_EXEC + printf("rollback from state %d on %d:%c\n", exec->state->no, + codepoint,codepoint); +#endif + xmlFARegExecRollBack(exec); + } +progress: + continue; + } +error: + if (exec->rollbacks != NULL) { + if (exec->counts != NULL) { + int i; + + for (i = 0;i < exec->maxRollbacks;i++) + if (exec->rollbacks[i].counts != NULL) + xmlFree(exec->rollbacks[i].counts); + } + xmlFree(exec->rollbacks); + } + if (exec->counts != NULL) + xmlFree(exec->counts); + if (exec->status == 0) + return(1); + if (exec->status == -1) { + if (exec->nbPush > MAX_PUSH) + return(-1); + return(0); + } + return(exec->status); +} + +/************************************************************************ + * * + * Progressive interface to the verifier one atom at a time * + * * + ************************************************************************/ +#ifdef DEBUG_ERR +static void testerr(xmlRegExecCtxtPtr exec); +#endif + +/** + * xmlRegNewExecCtxt: + * @comp: a precompiled regular expression + * @callback: a callback function used for handling progresses in the + * automata matching phase + * @data: the context data associated to the callback in this context + * + * Build a context used for progressive evaluation of a regexp. + * + * Returns the new context + */ +xmlRegExecCtxtPtr +xmlRegNewExecCtxt(xmlRegexpPtr comp, xmlRegExecCallbacks callback, void *data) { + xmlRegExecCtxtPtr exec; + + if (comp == NULL) + return(NULL); + if ((comp->compact == NULL) && (comp->states == NULL)) + return(NULL); + exec = (xmlRegExecCtxtPtr) xmlMalloc(sizeof(xmlRegExecCtxt)); + if (exec == NULL) { + xmlRegexpErrMemory(NULL, "creating execution context"); + return(NULL); + } + memset(exec, 0, sizeof(xmlRegExecCtxt)); + exec->inputString = NULL; + exec->index = 0; + exec->determinist = 1; + exec->maxRollbacks = 0; + exec->nbRollbacks = 0; + exec->rollbacks = NULL; + exec->status = 0; + exec->comp = comp; + if (comp->compact == NULL) + exec->state = comp->states[0]; + exec->transno = 0; + exec->transcount = 0; + exec->callback = callback; + exec->data = data; + if (comp->nbCounters > 0) { + /* + * For error handling, exec->counts is allocated twice the size + * the second half is used to store the data in case of rollback + */ + exec->counts = (int *) xmlMalloc(comp->nbCounters * sizeof(int) + * 2); + if (exec->counts == NULL) { + xmlRegexpErrMemory(NULL, "creating execution context"); + xmlFree(exec); + return(NULL); + } + memset(exec->counts, 0, comp->nbCounters * sizeof(int) * 2); + exec->errCounts = &exec->counts[comp->nbCounters]; + } else { + exec->counts = NULL; + exec->errCounts = NULL; + } + exec->inputStackMax = 0; + exec->inputStackNr = 0; + exec->inputStack = NULL; + exec->errStateNo = -1; + exec->errString = NULL; + exec->nbPush = 0; + return(exec); +} + +/** + * xmlRegFreeExecCtxt: + * @exec: a regular expression evaulation context + * + * Free the structures associated to a regular expression evaulation context. + */ +void +xmlRegFreeExecCtxt(xmlRegExecCtxtPtr exec) { + if (exec == NULL) + return; + + if (exec->rollbacks != NULL) { + if (exec->counts != NULL) { + int i; + + for (i = 0;i < exec->maxRollbacks;i++) + if (exec->rollbacks[i].counts != NULL) + xmlFree(exec->rollbacks[i].counts); + } + xmlFree(exec->rollbacks); + } + if (exec->counts != NULL) + xmlFree(exec->counts); + if (exec->inputStack != NULL) { + int i; + + for (i = 0;i < exec->inputStackNr;i++) { + if (exec->inputStack[i].value != NULL) + xmlFree(exec->inputStack[i].value); + } + xmlFree(exec->inputStack); + } + if (exec->errString != NULL) + xmlFree(exec->errString); + xmlFree(exec); +} + +static void +xmlFARegExecSaveInputString(xmlRegExecCtxtPtr exec, const xmlChar *value, + void *data) { +#ifdef DEBUG_PUSH + printf("saving value: %d:%s\n", exec->inputStackNr, value); +#endif + if (exec->inputStackMax == 0) { + exec->inputStackMax = 4; + exec->inputStack = (xmlRegInputTokenPtr) + xmlMalloc(exec->inputStackMax * sizeof(xmlRegInputToken)); + if (exec->inputStack == NULL) { + xmlRegexpErrMemory(NULL, "pushing input string"); + exec->inputStackMax = 0; + return; + } + } else if (exec->inputStackNr + 1 >= exec->inputStackMax) { + xmlRegInputTokenPtr tmp; + + exec->inputStackMax *= 2; + tmp = (xmlRegInputTokenPtr) xmlRealloc(exec->inputStack, + exec->inputStackMax * sizeof(xmlRegInputToken)); + if (tmp == NULL) { + xmlRegexpErrMemory(NULL, "pushing input string"); + exec->inputStackMax /= 2; + return; + } + exec->inputStack = tmp; + } + exec->inputStack[exec->inputStackNr].value = xmlStrdup(value); + exec->inputStack[exec->inputStackNr].data = data; + exec->inputStackNr++; + exec->inputStack[exec->inputStackNr].value = NULL; + exec->inputStack[exec->inputStackNr].data = NULL; +} + +/** + * xmlRegStrEqualWildcard: + * @expStr: the string to be evaluated + * @valStr: the validation string + * + * Checks if both strings are equal or have the same content. "*" + * can be used as a wildcard in @valStr; "|" is used as a seperator of + * substrings in both @expStr and @valStr. + * + * Returns 1 if the comparison is satisfied and the number of substrings + * is equal, 0 otherwise. + */ + +static int +xmlRegStrEqualWildcard(const xmlChar *expStr, const xmlChar *valStr) { + if (expStr == valStr) return(1); + if (expStr == NULL) return(0); + if (valStr == NULL) return(0); + do { + /* + * Eval if we have a wildcard for the current item. + */ + if (*expStr != *valStr) { + /* if one of them starts with a wildcard make valStr be it */ + if (*valStr == '*') { + const xmlChar *tmp; + + tmp = valStr; + valStr = expStr; + expStr = tmp; + } + if ((*valStr != 0) && (*expStr != 0) && (*expStr++ == '*')) { + do { + if (*valStr == XML_REG_STRING_SEPARATOR) + break; + valStr++; + } while (*valStr != 0); + continue; + } else + return(0); + } + expStr++; + valStr++; + } while (*valStr != 0); + if (*expStr != 0) + return (0); + else + return (1); +} + +/** + * xmlRegCompactPushString: + * @exec: a regexp execution context + * @comp: the precompiled exec with a compact table + * @value: a string token input + * @data: data associated to the token to reuse in callbacks + * + * Push one input token in the execution context + * + * Returns: 1 if the regexp reached a final state, 0 if non-final, and + * a negative value in case of error. + */ +static int +xmlRegCompactPushString(xmlRegExecCtxtPtr exec, + xmlRegexpPtr comp, + const xmlChar *value, + void *data) { + int state = exec->index; + int i, target; + + if ((comp == NULL) || (comp->compact == NULL) || (comp->stringMap == NULL)) + return(-1); + + if (value == NULL) { + /* + * are we at a final state ? + */ + if (comp->compact[state * (comp->nbstrings + 1)] == + XML_REGEXP_FINAL_STATE) + return(1); + return(0); + } + +#ifdef DEBUG_PUSH + printf("value pushed: %s\n", value); +#endif + + /* + * Examine all outside transitions from current state + */ + for (i = 0;i < comp->nbstrings;i++) { + target = comp->compact[state * (comp->nbstrings + 1) + i + 1]; + if ((target > 0) && (target <= comp->nbstates)) { + target--; /* to avoid 0 */ + if (xmlRegStrEqualWildcard(comp->stringMap[i], value)) { + exec->index = target; + if ((exec->callback != NULL) && (comp->transdata != NULL)) { + exec->callback(exec->data, value, + comp->transdata[state * comp->nbstrings + i], data); + } +#ifdef DEBUG_PUSH + printf("entering state %d\n", target); +#endif + if (comp->compact[target * (comp->nbstrings + 1)] == + XML_REGEXP_SINK_STATE) + goto error; + + if (comp->compact[target * (comp->nbstrings + 1)] == + XML_REGEXP_FINAL_STATE) + return(1); + return(0); + } + } + } + /* + * Failed to find an exit transition out from current state for the + * current token + */ +#ifdef DEBUG_PUSH + printf("failed to find a transition for %s on state %d\n", value, state); +#endif +error: + if (exec->errString != NULL) + xmlFree(exec->errString); + exec->errString = xmlStrdup(value); + exec->errStateNo = state; + exec->status = -1; +#ifdef DEBUG_ERR + testerr(exec); +#endif + return(-1); +} + +/** + * xmlRegExecPushStringInternal: + * @exec: a regexp execution context or NULL to indicate the end + * @value: a string token input + * @data: data associated to the token to reuse in callbacks + * @compound: value was assembled from 2 strings + * + * Push one input token in the execution context + * + * Returns: 1 if the regexp reached a final state, 0 if non-final, and + * a negative value in case of error. + */ +static int +xmlRegExecPushStringInternal(xmlRegExecCtxtPtr exec, const xmlChar *value, + void *data, int compound) { + xmlRegTransPtr trans; + xmlRegAtomPtr atom; + int ret; + int final = 0; + int progress = 1; + + if (exec == NULL) + return(-1); + if (exec->comp == NULL) + return(-1); + if (exec->status != 0) + return(exec->status); + + if (exec->comp->compact != NULL) + return(xmlRegCompactPushString(exec, exec->comp, value, data)); + + if (value == NULL) { + if (exec->state->type == XML_REGEXP_FINAL_STATE) + return(1); + final = 1; + } + +#ifdef DEBUG_PUSH + printf("value pushed: %s\n", value); +#endif + /* + * If we have an active rollback stack push the new value there + * and get back to where we were left + */ + if ((value != NULL) && (exec->inputStackNr > 0)) { + xmlFARegExecSaveInputString(exec, value, data); + value = exec->inputStack[exec->index].value; + data = exec->inputStack[exec->index].data; +#ifdef DEBUG_PUSH + printf("value loaded: %s\n", value); +#endif + } + + while ((exec->status == 0) && + ((value != NULL) || + ((final == 1) && + (exec->state->type != XML_REGEXP_FINAL_STATE)))) { + + /* + * End of input on non-terminal state, rollback, however we may + * still have epsilon like transition for counted transitions + * on counters, in that case don't break too early. + */ + if ((value == NULL) && (exec->counts == NULL)) + goto rollback; + + exec->transcount = 0; + for (;exec->transno < exec->state->nbTrans;exec->transno++) { + trans = &exec->state->trans[exec->transno]; + if (trans->to < 0) + continue; + atom = trans->atom; + ret = 0; + if (trans->count == REGEXP_ALL_LAX_COUNTER) { + int i; + int count; + xmlRegTransPtr t; + xmlRegCounterPtr counter; + + ret = 0; + +#ifdef DEBUG_PUSH + printf("testing all lax %d\n", trans->count); +#endif + /* + * Check all counted transitions from the current state + */ + if ((value == NULL) && (final)) { + ret = 1; + } else if (value != NULL) { + for (i = 0;i < exec->state->nbTrans;i++) { + t = &exec->state->trans[i]; + if ((t->counter < 0) || (t == trans)) + continue; + counter = &exec->comp->counters[t->counter]; + count = exec->counts[t->counter]; + if ((count < counter->max) && + (t->atom != NULL) && + (xmlStrEqual(value, t->atom->valuep))) { + ret = 0; + break; + } + if ((count >= counter->min) && + (count < counter->max) && + (t->atom != NULL) && + (xmlStrEqual(value, t->atom->valuep))) { + ret = 1; + break; + } + } + } + } else if (trans->count == REGEXP_ALL_COUNTER) { + int i; + int count; + xmlRegTransPtr t; + xmlRegCounterPtr counter; + + ret = 1; + +#ifdef DEBUG_PUSH + printf("testing all %d\n", trans->count); +#endif + /* + * Check all counted transitions from the current state + */ + for (i = 0;i < exec->state->nbTrans;i++) { + t = &exec->state->trans[i]; + if ((t->counter < 0) || (t == trans)) + continue; + counter = &exec->comp->counters[t->counter]; + count = exec->counts[t->counter]; + if ((count < counter->min) || (count > counter->max)) { + ret = 0; + break; + } + } + } else if (trans->count >= 0) { + int count; + xmlRegCounterPtr counter; + + /* + * A counted transition. + */ + + count = exec->counts[trans->count]; + counter = &exec->comp->counters[trans->count]; +#ifdef DEBUG_PUSH + printf("testing count %d: val %d, min %d, max %d\n", + trans->count, count, counter->min, counter->max); +#endif + ret = ((count >= counter->min) && (count <= counter->max)); + } else if (atom == NULL) { + fprintf(stderr, "epsilon transition left at runtime\n"); + exec->status = -2; + break; + } else if (value != NULL) { + ret = xmlRegStrEqualWildcard(atom->valuep, value); + if (atom->neg) { + ret = !ret; + if (!compound) + ret = 0; + } + if ((ret == 1) && (trans->counter >= 0)) { + xmlRegCounterPtr counter; + int count; + + count = exec->counts[trans->counter]; + counter = &exec->comp->counters[trans->counter]; + if (count >= counter->max) + ret = 0; + } + + if ((ret == 1) && (atom->min > 0) && (atom->max > 0)) { + xmlRegStatePtr to = exec->comp->states[trans->to]; + + /* + * this is a multiple input sequence + */ + if (exec->state->nbTrans > exec->transno + 1) { + if (exec->inputStackNr <= 0) { + xmlFARegExecSaveInputString(exec, value, data); + } + xmlFARegExecSave(exec); + } + exec->transcount = 1; + do { + /* + * Try to progress as much as possible on the input + */ + if (exec->transcount == atom->max) { + break; + } + exec->index++; + value = exec->inputStack[exec->index].value; + data = exec->inputStack[exec->index].data; +#ifdef DEBUG_PUSH + printf("value loaded: %s\n", value); +#endif + + /* + * End of input: stop here + */ + if (value == NULL) { + exec->index --; + break; + } + if (exec->transcount >= atom->min) { + int transno = exec->transno; + xmlRegStatePtr state = exec->state; + + /* + * The transition is acceptable save it + */ + exec->transno = -1; /* trick */ + exec->state = to; + if (exec->inputStackNr <= 0) { + xmlFARegExecSaveInputString(exec, value, data); + } + xmlFARegExecSave(exec); + exec->transno = transno; + exec->state = state; + } + ret = xmlStrEqual(value, atom->valuep); + exec->transcount++; + } while (ret == 1); + if (exec->transcount < atom->min) + ret = 0; + + /* + * If the last check failed but one transition was found + * possible, rollback + */ + if (ret < 0) + ret = 0; + if (ret == 0) { + goto rollback; + } + } + } + if (ret == 1) { + if ((exec->callback != NULL) && (atom != NULL) && + (data != NULL)) { + exec->callback(exec->data, atom->valuep, + atom->data, data); + } + if (exec->state->nbTrans > exec->transno + 1) { + if (exec->inputStackNr <= 0) { + xmlFARegExecSaveInputString(exec, value, data); + } + xmlFARegExecSave(exec); + } + if (trans->counter >= 0) { +#ifdef DEBUG_PUSH + printf("Increasing count %d\n", trans->counter); +#endif + exec->counts[trans->counter]++; + } + if ((trans->count >= 0) && + (trans->count < REGEXP_ALL_COUNTER)) { +#ifdef DEBUG_REGEXP_EXEC + printf("resetting count %d on transition\n", + trans->count); +#endif + exec->counts[trans->count] = 0; + } +#ifdef DEBUG_PUSH + printf("entering state %d\n", trans->to); +#endif + if ((exec->comp->states[trans->to] != NULL) && + (exec->comp->states[trans->to]->type == + XML_REGEXP_SINK_STATE)) { + /* + * entering a sink state, save the current state as error + * state. + */ + if (exec->errString != NULL) + xmlFree(exec->errString); + exec->errString = xmlStrdup(value); + exec->errState = exec->state; + memcpy(exec->errCounts, exec->counts, + exec->comp->nbCounters * sizeof(int)); + } + exec->state = exec->comp->states[trans->to]; + exec->transno = 0; + if (trans->atom != NULL) { + if (exec->inputStack != NULL) { + exec->index++; + if (exec->index < exec->inputStackNr) { + value = exec->inputStack[exec->index].value; + data = exec->inputStack[exec->index].data; +#ifdef DEBUG_PUSH + printf("value loaded: %s\n", value); +#endif + } else { + value = NULL; + data = NULL; +#ifdef DEBUG_PUSH + printf("end of input\n"); +#endif + } + } else { + value = NULL; + data = NULL; +#ifdef DEBUG_PUSH + printf("end of input\n"); +#endif + } + } + goto progress; + } else if (ret < 0) { + exec->status = -4; + break; + } + } + if ((exec->transno != 0) || (exec->state->nbTrans == 0)) { +rollback: + /* + * if we didn't yet rollback on the current input + * store the current state as the error state. + */ + if ((progress) && (exec->state != NULL) && + (exec->state->type != XML_REGEXP_SINK_STATE)) { + progress = 0; + if (exec->errString != NULL) + xmlFree(exec->errString); + exec->errString = xmlStrdup(value); + exec->errState = exec->state; + memcpy(exec->errCounts, exec->counts, + exec->comp->nbCounters * sizeof(int)); + } + + /* + * Failed to find a way out + */ + exec->determinist = 0; + xmlFARegExecRollBack(exec); + if (exec->status == 0) { + value = exec->inputStack[exec->index].value; + data = exec->inputStack[exec->index].data; +#ifdef DEBUG_PUSH + printf("value loaded: %s\n", value); +#endif + } + } + continue; +progress: + progress = 1; + continue; + } + if (exec->status == 0) { + return(exec->state->type == XML_REGEXP_FINAL_STATE); + } +#ifdef DEBUG_ERR + if (exec->status < 0) { + testerr(exec); + } +#endif + return(exec->status); +} + +/** + * xmlRegExecPushString: + * @exec: a regexp execution context or NULL to indicate the end + * @value: a string token input + * @data: data associated to the token to reuse in callbacks + * + * Push one input token in the execution context + * + * Returns: 1 if the regexp reached a final state, 0 if non-final, and + * a negative value in case of error. + */ +int +xmlRegExecPushString(xmlRegExecCtxtPtr exec, const xmlChar *value, + void *data) { + return(xmlRegExecPushStringInternal(exec, value, data, 0)); +} + +/** + * xmlRegExecPushString2: + * @exec: a regexp execution context or NULL to indicate the end + * @value: the first string token input + * @value2: the second string token input + * @data: data associated to the token to reuse in callbacks + * + * Push one input token in the execution context + * + * Returns: 1 if the regexp reached a final state, 0 if non-final, and + * a negative value in case of error. + */ +int +xmlRegExecPushString2(xmlRegExecCtxtPtr exec, const xmlChar *value, + const xmlChar *value2, void *data) { + xmlChar buf[150]; + int lenn, lenp, ret; + xmlChar *str; + + if (exec == NULL) + return(-1); + if (exec->comp == NULL) + return(-1); + if (exec->status != 0) + return(exec->status); + + if (value2 == NULL) + return(xmlRegExecPushString(exec, value, data)); + + lenn = strlen((char *) value2); + lenp = strlen((char *) value); + + if (150 < lenn + lenp + 2) { + str = (xmlChar *) xmlMallocAtomic(lenn + lenp + 2); + if (str == NULL) { + exec->status = -1; + return(-1); + } + } else { + str = buf; + } + memcpy(&str[0], value, lenp); + str[lenp] = XML_REG_STRING_SEPARATOR; + memcpy(&str[lenp + 1], value2, lenn); + str[lenn + lenp + 1] = 0; + + if (exec->comp->compact != NULL) + ret = xmlRegCompactPushString(exec, exec->comp, str, data); + else + ret = xmlRegExecPushStringInternal(exec, str, data, 1); + + if (str != buf) + xmlFree(str); + return(ret); +} + +/** + * xmlRegExecGetValues: + * @exec: a regexp execution context + * @err: error extraction or normal one + * @nbval: pointer to the number of accepted values IN/OUT + * @nbneg: return number of negative transitions + * @values: pointer to the array of acceptable values + * @terminal: return value if this was a terminal state + * + * Extract informations from the regexp execution, internal routine to + * implement xmlRegExecNextValues() and xmlRegExecErrInfo() + * + * Returns: 0 in case of success or -1 in case of error. + */ +static int +xmlRegExecGetValues(xmlRegExecCtxtPtr exec, int err, + int *nbval, int *nbneg, + xmlChar **values, int *terminal) { + int maxval; + int nb = 0; + + if ((exec == NULL) || (nbval == NULL) || (nbneg == NULL) || + (values == NULL) || (*nbval <= 0)) + return(-1); + + maxval = *nbval; + *nbval = 0; + *nbneg = 0; + if ((exec->comp != NULL) && (exec->comp->compact != NULL)) { + xmlRegexpPtr comp; + int target, i, state; + + comp = exec->comp; + + if (err) { + if (exec->errStateNo == -1) return(-1); + state = exec->errStateNo; + } else { + state = exec->index; + } + if (terminal != NULL) { + if (comp->compact[state * (comp->nbstrings + 1)] == + XML_REGEXP_FINAL_STATE) + *terminal = 1; + else + *terminal = 0; + } + for (i = 0;(i < comp->nbstrings) && (nb < maxval);i++) { + target = comp->compact[state * (comp->nbstrings + 1) + i + 1]; + if ((target > 0) && (target <= comp->nbstates) && + (comp->compact[(target - 1) * (comp->nbstrings + 1)] != + XML_REGEXP_SINK_STATE)) { + values[nb++] = comp->stringMap[i]; + (*nbval)++; + } + } + for (i = 0;(i < comp->nbstrings) && (nb < maxval);i++) { + target = comp->compact[state * (comp->nbstrings + 1) + i + 1]; + if ((target > 0) && (target <= comp->nbstates) && + (comp->compact[(target - 1) * (comp->nbstrings + 1)] == + XML_REGEXP_SINK_STATE)) { + values[nb++] = comp->stringMap[i]; + (*nbneg)++; + } + } + } else { + int transno; + xmlRegTransPtr trans; + xmlRegAtomPtr atom; + xmlRegStatePtr state; + + if (terminal != NULL) { + if (exec->state->type == XML_REGEXP_FINAL_STATE) + *terminal = 1; + else + *terminal = 0; + } + + if (err) { + if (exec->errState == NULL) return(-1); + state = exec->errState; + } else { + if (exec->state == NULL) return(-1); + state = exec->state; + } + for (transno = 0; + (transno < state->nbTrans) && (nb < maxval); + transno++) { + trans = &state->trans[transno]; + if (trans->to < 0) + continue; + atom = trans->atom; + if ((atom == NULL) || (atom->valuep == NULL)) + continue; + if (trans->count == REGEXP_ALL_LAX_COUNTER) { + /* this should not be reached but ... */ + TODO; + } else if (trans->count == REGEXP_ALL_COUNTER) { + /* this should not be reached but ... */ + TODO; + } else if (trans->counter >= 0) { + xmlRegCounterPtr counter = NULL; + int count; + + if (err) + count = exec->errCounts[trans->counter]; + else + count = exec->counts[trans->counter]; + if (exec->comp != NULL) + counter = &exec->comp->counters[trans->counter]; + if ((counter == NULL) || (count < counter->max)) { + if (atom->neg) + values[nb++] = (xmlChar *) atom->valuep2; + else + values[nb++] = (xmlChar *) atom->valuep; + (*nbval)++; + } + } else { + if ((exec->comp->states[trans->to] != NULL) && + (exec->comp->states[trans->to]->type != + XML_REGEXP_SINK_STATE)) { + if (atom->neg) + values[nb++] = (xmlChar *) atom->valuep2; + else + values[nb++] = (xmlChar *) atom->valuep; + (*nbval)++; + } + } + } + for (transno = 0; + (transno < state->nbTrans) && (nb < maxval); + transno++) { + trans = &state->trans[transno]; + if (trans->to < 0) + continue; + atom = trans->atom; + if ((atom == NULL) || (atom->valuep == NULL)) + continue; + if (trans->count == REGEXP_ALL_LAX_COUNTER) { + continue; + } else if (trans->count == REGEXP_ALL_COUNTER) { + continue; + } else if (trans->counter >= 0) { + continue; + } else { + if ((exec->comp->states[trans->to] != NULL) && + (exec->comp->states[trans->to]->type == + XML_REGEXP_SINK_STATE)) { + if (atom->neg) + values[nb++] = (xmlChar *) atom->valuep2; + else + values[nb++] = (xmlChar *) atom->valuep; + (*nbneg)++; + } + } + } + } + return(0); +} + +/** + * xmlRegExecNextValues: + * @exec: a regexp execution context + * @nbval: pointer to the number of accepted values IN/OUT + * @nbneg: return number of negative transitions + * @values: pointer to the array of acceptable values + * @terminal: return value if this was a terminal state + * + * Extract informations from the regexp execution, + * the parameter @values must point to an array of @nbval string pointers + * on return nbval will contain the number of possible strings in that + * state and the @values array will be updated with them. The string values + * returned will be freed with the @exec context and don't need to be + * deallocated. + * + * Returns: 0 in case of success or -1 in case of error. + */ +int +xmlRegExecNextValues(xmlRegExecCtxtPtr exec, int *nbval, int *nbneg, + xmlChar **values, int *terminal) { + return(xmlRegExecGetValues(exec, 0, nbval, nbneg, values, terminal)); +} + +/** + * xmlRegExecErrInfo: + * @exec: a regexp execution context generating an error + * @string: return value for the error string + * @nbval: pointer to the number of accepted values IN/OUT + * @nbneg: return number of negative transitions + * @values: pointer to the array of acceptable values + * @terminal: return value if this was a terminal state + * + * Extract error informations from the regexp execution, the parameter + * @string will be updated with the value pushed and not accepted, + * the parameter @values must point to an array of @nbval string pointers + * on return nbval will contain the number of possible strings in that + * state and the @values array will be updated with them. The string values + * returned will be freed with the @exec context and don't need to be + * deallocated. + * + * Returns: 0 in case of success or -1 in case of error. + */ +int +xmlRegExecErrInfo(xmlRegExecCtxtPtr exec, const xmlChar **string, + int *nbval, int *nbneg, xmlChar **values, int *terminal) { + if (exec == NULL) + return(-1); + if (string != NULL) { + if (exec->status != 0) + *string = exec->errString; + else + *string = NULL; + } + return(xmlRegExecGetValues(exec, 1, nbval, nbneg, values, terminal)); +} + +#ifdef DEBUG_ERR +static void testerr(xmlRegExecCtxtPtr exec) { + const xmlChar *string; + xmlChar *values[5]; + int nb = 5; + int nbneg; + int terminal; + xmlRegExecErrInfo(exec, &string, &nb, &nbneg, &values[0], &terminal); +} +#endif + +#if 0 +static int +xmlRegExecPushChar(xmlRegExecCtxtPtr exec, int UCS) { + xmlRegTransPtr trans; + xmlRegAtomPtr atom; + int ret; + int codepoint, len; + + if (exec == NULL) + return(-1); + if (exec->status != 0) + return(exec->status); + + while ((exec->status == 0) && + ((exec->inputString[exec->index] != 0) || + (exec->state->type != XML_REGEXP_FINAL_STATE))) { + + /* + * End of input on non-terminal state, rollback, however we may + * still have epsilon like transition for counted transitions + * on counters, in that case don't break too early. + */ + if ((exec->inputString[exec->index] == 0) && (exec->counts == NULL)) + goto rollback; + + exec->transcount = 0; + for (;exec->transno < exec->state->nbTrans;exec->transno++) { + trans = &exec->state->trans[exec->transno]; + if (trans->to < 0) + continue; + atom = trans->atom; + ret = 0; + if (trans->count >= 0) { + int count; + xmlRegCounterPtr counter; + + /* + * A counted transition. + */ + + count = exec->counts[trans->count]; + counter = &exec->comp->counters[trans->count]; +#ifdef DEBUG_REGEXP_EXEC + printf("testing count %d: val %d, min %d, max %d\n", + trans->count, count, counter->min, counter->max); +#endif + ret = ((count >= counter->min) && (count <= counter->max)); + } else if (atom == NULL) { + fprintf(stderr, "epsilon transition left at runtime\n"); + exec->status = -2; + break; + } else if (exec->inputString[exec->index] != 0) { + codepoint = CUR_SCHAR(&(exec->inputString[exec->index]), len); + ret = xmlRegCheckCharacter(atom, codepoint); + if ((ret == 1) && (atom->min > 0) && (atom->max > 0)) { + xmlRegStatePtr to = exec->comp->states[trans->to]; + + /* + * this is a multiple input sequence + */ + if (exec->state->nbTrans > exec->transno + 1) { + xmlFARegExecSave(exec); + } + exec->transcount = 1; + do { + /* + * Try to progress as much as possible on the input + */ + if (exec->transcount == atom->max) { + break; + } + exec->index += len; + /* + * End of input: stop here + */ + if (exec->inputString[exec->index] == 0) { + exec->index -= len; + break; + } + if (exec->transcount >= atom->min) { + int transno = exec->transno; + xmlRegStatePtr state = exec->state; + + /* + * The transition is acceptable save it + */ + exec->transno = -1; /* trick */ + exec->state = to; + xmlFARegExecSave(exec); + exec->transno = transno; + exec->state = state; + } + codepoint = CUR_SCHAR(&(exec->inputString[exec->index]), + len); + ret = xmlRegCheckCharacter(atom, codepoint); + exec->transcount++; + } while (ret == 1); + if (exec->transcount < atom->min) + ret = 0; + + /* + * If the last check failed but one transition was found + * possible, rollback + */ + if (ret < 0) + ret = 0; + if (ret == 0) { + goto rollback; + } + } + } + if (ret == 1) { + if (exec->state->nbTrans > exec->transno + 1) { + xmlFARegExecSave(exec); + } + /* + * restart count for expressions like this ((abc){2})* + */ + if (trans->count >= 0) { +#ifdef DEBUG_REGEXP_EXEC + printf("Reset count %d\n", trans->count); +#endif + exec->counts[trans->count] = 0; + } + if (trans->counter >= 0) { +#ifdef DEBUG_REGEXP_EXEC + printf("Increasing count %d\n", trans->counter); +#endif + exec->counts[trans->counter]++; + } +#ifdef DEBUG_REGEXP_EXEC + printf("entering state %d\n", trans->to); +#endif + exec->state = exec->comp->states[trans->to]; + exec->transno = 0; + if (trans->atom != NULL) { + exec->index += len; + } + goto progress; + } else if (ret < 0) { + exec->status = -4; + break; + } + } + if ((exec->transno != 0) || (exec->state->nbTrans == 0)) { +rollback: + /* + * Failed to find a way out + */ + exec->determinist = 0; + xmlFARegExecRollBack(exec); + } +progress: + continue; + } +} +#endif +/************************************************************************ + * * + * Parser for the Schemas Datatype Regular Expressions * + * http://www.w3.org/TR/2001/REC-xmlschema-2-20010502/#regexs * + * * + ************************************************************************/ + +/** + * xmlFAIsChar: + * @ctxt: a regexp parser context + * + * [10] Char ::= [^.\?*+()|#x5B#x5D] + */ +static int +xmlFAIsChar(xmlRegParserCtxtPtr ctxt) { + int cur; + int len; + + cur = CUR_SCHAR(ctxt->cur, len); + if ((cur == '.') || (cur == '\\') || (cur == '?') || + (cur == '*') || (cur == '+') || (cur == '(') || + (cur == ')') || (cur == '|') || (cur == 0x5B) || + (cur == 0x5D) || (cur == 0)) + return(-1); + return(cur); +} + +/** + * xmlFAParseCharProp: + * @ctxt: a regexp parser context + * + * [27] charProp ::= IsCategory | IsBlock + * [28] IsCategory ::= Letters | Marks | Numbers | Punctuation | + * Separators | Symbols | Others + * [29] Letters ::= 'L' [ultmo]? + * [30] Marks ::= 'M' [nce]? + * [31] Numbers ::= 'N' [dlo]? + * [32] Punctuation ::= 'P' [cdseifo]? + * [33] Separators ::= 'Z' [slp]? + * [34] Symbols ::= 'S' [mcko]? + * [35] Others ::= 'C' [cfon]? + * [36] IsBlock ::= 'Is' [a-zA-Z0-9#x2D]+ + */ +static void +xmlFAParseCharProp(xmlRegParserCtxtPtr ctxt) { + int cur; + xmlRegAtomType type = (xmlRegAtomType) 0; + xmlChar *blockName = NULL; + + cur = CUR; + if (cur == 'L') { + NEXT; + cur = CUR; + if (cur == 'u') { + NEXT; + type = XML_REGEXP_LETTER_UPPERCASE; + } else if (cur == 'l') { + NEXT; + type = XML_REGEXP_LETTER_LOWERCASE; + } else if (cur == 't') { + NEXT; + type = XML_REGEXP_LETTER_TITLECASE; + } else if (cur == 'm') { + NEXT; + type = XML_REGEXP_LETTER_MODIFIER; + } else if (cur == 'o') { + NEXT; + type = XML_REGEXP_LETTER_OTHERS; + } else { + type = XML_REGEXP_LETTER; + } + } else if (cur == 'M') { + NEXT; + cur = CUR; + if (cur == 'n') { + NEXT; + /* nonspacing */ + type = XML_REGEXP_MARK_NONSPACING; + } else if (cur == 'c') { + NEXT; + /* spacing combining */ + type = XML_REGEXP_MARK_SPACECOMBINING; + } else if (cur == 'e') { + NEXT; + /* enclosing */ + type = XML_REGEXP_MARK_ENCLOSING; + } else { + /* all marks */ + type = XML_REGEXP_MARK; + } + } else if (cur == 'N') { + NEXT; + cur = CUR; + if (cur == 'd') { + NEXT; + /* digital */ + type = XML_REGEXP_NUMBER_DECIMAL; + } else if (cur == 'l') { + NEXT; + /* letter */ + type = XML_REGEXP_NUMBER_LETTER; + } else if (cur == 'o') { + NEXT; + /* other */ + type = XML_REGEXP_NUMBER_OTHERS; + } else { + /* all numbers */ + type = XML_REGEXP_NUMBER; + } + } else if (cur == 'P') { + NEXT; + cur = CUR; + if (cur == 'c') { + NEXT; + /* connector */ + type = XML_REGEXP_PUNCT_CONNECTOR; + } else if (cur == 'd') { + NEXT; + /* dash */ + type = XML_REGEXP_PUNCT_DASH; + } else if (cur == 's') { + NEXT; + /* open */ + type = XML_REGEXP_PUNCT_OPEN; + } else if (cur == 'e') { + NEXT; + /* close */ + type = XML_REGEXP_PUNCT_CLOSE; + } else if (cur == 'i') { + NEXT; + /* initial quote */ + type = XML_REGEXP_PUNCT_INITQUOTE; + } else if (cur == 'f') { + NEXT; + /* final quote */ + type = XML_REGEXP_PUNCT_FINQUOTE; + } else if (cur == 'o') { + NEXT; + /* other */ + type = XML_REGEXP_PUNCT_OTHERS; + } else { + /* all punctuation */ + type = XML_REGEXP_PUNCT; + } + } else if (cur == 'Z') { + NEXT; + cur = CUR; + if (cur == 's') { + NEXT; + /* space */ + type = XML_REGEXP_SEPAR_SPACE; + } else if (cur == 'l') { + NEXT; + /* line */ + type = XML_REGEXP_SEPAR_LINE; + } else if (cur == 'p') { + NEXT; + /* paragraph */ + type = XML_REGEXP_SEPAR_PARA; + } else { + /* all separators */ + type = XML_REGEXP_SEPAR; + } + } else if (cur == 'S') { + NEXT; + cur = CUR; + if (cur == 'm') { + NEXT; + type = XML_REGEXP_SYMBOL_MATH; + /* math */ + } else if (cur == 'c') { + NEXT; + type = XML_REGEXP_SYMBOL_CURRENCY; + /* currency */ + } else if (cur == 'k') { + NEXT; + type = XML_REGEXP_SYMBOL_MODIFIER; + /* modifiers */ + } else if (cur == 'o') { + NEXT; + type = XML_REGEXP_SYMBOL_OTHERS; + /* other */ + } else { + /* all symbols */ + type = XML_REGEXP_SYMBOL; + } + } else if (cur == 'C') { + NEXT; + cur = CUR; + if (cur == 'c') { + NEXT; + /* control */ + type = XML_REGEXP_OTHER_CONTROL; + } else if (cur == 'f') { + NEXT; + /* format */ + type = XML_REGEXP_OTHER_FORMAT; + } else if (cur == 'o') { + NEXT; + /* private use */ + type = XML_REGEXP_OTHER_PRIVATE; + } else if (cur == 'n') { + NEXT; + /* not assigned */ + type = XML_REGEXP_OTHER_NA; + } else { + /* all others */ + type = XML_REGEXP_OTHER; + } + } else if (cur == 'I') { + const xmlChar *start; + NEXT; + cur = CUR; + if (cur != 's') { + ERROR("IsXXXX expected"); + return; + } + NEXT; + start = ctxt->cur; + cur = CUR; + if (((cur >= 'a') && (cur <= 'z')) || + ((cur >= 'A') && (cur <= 'Z')) || + ((cur >= '0') && (cur <= '9')) || + (cur == 0x2D)) { + NEXT; + cur = CUR; + while (((cur >= 'a') && (cur <= 'z')) || + ((cur >= 'A') && (cur <= 'Z')) || + ((cur >= '0') && (cur <= '9')) || + (cur == 0x2D)) { + NEXT; + cur = CUR; + } + } + type = XML_REGEXP_BLOCK_NAME; + blockName = xmlStrndup(start, ctxt->cur - start); + } else { + ERROR("Unknown char property"); + return; + } + if (ctxt->atom == NULL) { + ctxt->atom = xmlRegNewAtom(ctxt, type); + if (ctxt->atom != NULL) + ctxt->atom->valuep = blockName; + } else if (ctxt->atom->type == XML_REGEXP_RANGES) { + xmlRegAtomAddRange(ctxt, ctxt->atom, ctxt->neg, + type, 0, 0, blockName); + } +} + +/** + * xmlFAParseCharClassEsc: + * @ctxt: a regexp parser context + * + * [23] charClassEsc ::= ( SingleCharEsc | MultiCharEsc | catEsc | complEsc ) + * [24] SingleCharEsc ::= '\' [nrt\|.?*+(){}#x2D#x5B#x5D#x5E] + * [25] catEsc ::= '\p{' charProp '}' + * [26] complEsc ::= '\P{' charProp '}' + * [37] MultiCharEsc ::= '.' | ('\' [sSiIcCdDwW]) + */ +static void +xmlFAParseCharClassEsc(xmlRegParserCtxtPtr ctxt) { + int cur; + + if (CUR == '.') { + if (ctxt->atom == NULL) { + ctxt->atom = xmlRegNewAtom(ctxt, XML_REGEXP_ANYCHAR); + } else if (ctxt->atom->type == XML_REGEXP_RANGES) { + xmlRegAtomAddRange(ctxt, ctxt->atom, ctxt->neg, + XML_REGEXP_ANYCHAR, 0, 0, NULL); + } + NEXT; + return; + } + if (CUR != '\\') { + ERROR("Escaped sequence: expecting \\"); + return; + } + NEXT; + cur = CUR; + if (cur == 'p') { + NEXT; + if (CUR != '{') { + ERROR("Expecting '{'"); + return; + } + NEXT; + xmlFAParseCharProp(ctxt); + if (CUR != '}') { + ERROR("Expecting '}'"); + return; + } + NEXT; + } else if (cur == 'P') { + NEXT; + if (CUR != '{') { + ERROR("Expecting '{'"); + return; + } + NEXT; + xmlFAParseCharProp(ctxt); + ctxt->atom->neg = 1; + if (CUR != '}') { + ERROR("Expecting '}'"); + return; + } + NEXT; + } else if ((cur == 'n') || (cur == 'r') || (cur == 't') || (cur == '\\') || + (cur == '|') || (cur == '.') || (cur == '?') || (cur == '*') || + (cur == '+') || (cur == '(') || (cur == ')') || (cur == '{') || + (cur == '}') || (cur == 0x2D) || (cur == 0x5B) || (cur == 0x5D) || + (cur == 0x5E)) { + if (ctxt->atom == NULL) { + ctxt->atom = xmlRegNewAtom(ctxt, XML_REGEXP_CHARVAL); + if (ctxt->atom != NULL) { + switch (cur) { + case 'n': + ctxt->atom->codepoint = '\n'; + break; + case 'r': + ctxt->atom->codepoint = '\r'; + break; + case 't': + ctxt->atom->codepoint = '\t'; + break; + default: + ctxt->atom->codepoint = cur; + } + } + } else if (ctxt->atom->type == XML_REGEXP_RANGES) { + xmlRegAtomAddRange(ctxt, ctxt->atom, ctxt->neg, + XML_REGEXP_CHARVAL, cur, cur, NULL); + } + NEXT; + } else if ((cur == 's') || (cur == 'S') || (cur == 'i') || (cur == 'I') || + (cur == 'c') || (cur == 'C') || (cur == 'd') || (cur == 'D') || + (cur == 'w') || (cur == 'W')) { + xmlRegAtomType type = XML_REGEXP_ANYSPACE; + + switch (cur) { + case 's': + type = XML_REGEXP_ANYSPACE; + break; + case 'S': + type = XML_REGEXP_NOTSPACE; + break; + case 'i': + type = XML_REGEXP_INITNAME; + break; + case 'I': + type = XML_REGEXP_NOTINITNAME; + break; + case 'c': + type = XML_REGEXP_NAMECHAR; + break; + case 'C': + type = XML_REGEXP_NOTNAMECHAR; + break; + case 'd': + type = XML_REGEXP_DECIMAL; + break; + case 'D': + type = XML_REGEXP_NOTDECIMAL; + break; + case 'w': + type = XML_REGEXP_REALCHAR; + break; + case 'W': + type = XML_REGEXP_NOTREALCHAR; + break; + } + NEXT; + if (ctxt->atom == NULL) { + ctxt->atom = xmlRegNewAtom(ctxt, type); + } else if (ctxt->atom->type == XML_REGEXP_RANGES) { + xmlRegAtomAddRange(ctxt, ctxt->atom, ctxt->neg, + type, 0, 0, NULL); + } + } +} + +/** + * xmlFAParseCharRef: + * @ctxt: a regexp parser context + * + * [19] XmlCharRef ::= ( '&#' [0-9]+ ';' ) | (' &#x' [0-9a-fA-F]+ ';' ) + */ +static int +xmlFAParseCharRef(xmlRegParserCtxtPtr ctxt) { + int ret = 0, cur; + + if ((CUR != '&') || (NXT(1) != '#')) + return(-1); + NEXT; + NEXT; + cur = CUR; + if (cur == 'x') { + NEXT; + cur = CUR; + if (((cur >= '0') && (cur <= '9')) || + ((cur >= 'a') && (cur <= 'f')) || + ((cur >= 'A') && (cur <= 'F'))) { + while (((cur >= '0') && (cur <= '9')) || + ((cur >= 'a') && (cur <= 'f')) || + ((cur >= 'A') && (cur <= 'F'))) { + if ((cur >= '0') && (cur <= '9')) + ret = ret * 16 + cur - '0'; + else if ((cur >= 'a') && (cur <= 'f')) + ret = ret * 16 + 10 + (cur - 'a'); + else + ret = ret * 16 + 10 + (cur - 'A'); + NEXT; + cur = CUR; + } + } else { + ERROR("Char ref: expecting [0-9A-F]"); + return(-1); + } + } else { + if ((cur >= '0') && (cur <= '9')) { + while ((cur >= '0') && (cur <= '9')) { + ret = ret * 10 + cur - '0'; + NEXT; + cur = CUR; + } + } else { + ERROR("Char ref: expecting [0-9]"); + return(-1); + } + } + if (cur != ';') { + ERROR("Char ref: expecting ';'"); + return(-1); + } else { + NEXT; + } + return(ret); +} + +/** + * xmlFAParseCharRange: + * @ctxt: a regexp parser context + * + * [17] charRange ::= seRange | XmlCharRef | XmlCharIncDash + * [18] seRange ::= charOrEsc '-' charOrEsc + * [20] charOrEsc ::= XmlChar | SingleCharEsc + * [21] XmlChar ::= [^\#x2D#x5B#x5D] + * [22] XmlCharIncDash ::= [^\#x5B#x5D] + */ +static void +xmlFAParseCharRange(xmlRegParserCtxtPtr ctxt) { + int cur, len; + int start = -1; + int end = -1; + + if (CUR == '\0') { + ERROR("Expecting ']'"); + return; + } + + if ((CUR == '&') && (NXT(1) == '#')) { + end = start = xmlFAParseCharRef(ctxt); + xmlRegAtomAddRange(ctxt, ctxt->atom, ctxt->neg, + XML_REGEXP_CHARVAL, start, end, NULL); + return; + } + cur = CUR; + if (cur == '\\') { + NEXT; + cur = CUR; + switch (cur) { + case 'n': start = 0xA; break; + case 'r': start = 0xD; break; + case 't': start = 0x9; break; + case '\\': case '|': case '.': case '-': case '^': case '?': + case '*': case '+': case '{': case '}': case '(': case ')': + case '[': case ']': + start = cur; break; + default: + ERROR("Invalid escape value"); + return; + } + end = start; + len = 1; + } else if ((cur != 0x5B) && (cur != 0x5D)) { + end = start = CUR_SCHAR(ctxt->cur, len); + } else { + ERROR("Expecting a char range"); + return; + } + NEXTL(len); + if (start == '-') { + return; + } + cur = CUR; + if ((cur != '-') || (NXT(1) == ']')) { + xmlRegAtomAddRange(ctxt, ctxt->atom, ctxt->neg, + XML_REGEXP_CHARVAL, start, end, NULL); + return; + } + NEXT; + cur = CUR; + if (cur == '\\') { + NEXT; + cur = CUR; + switch (cur) { + case 'n': end = 0xA; break; + case 'r': end = 0xD; break; + case 't': end = 0x9; break; + case '\\': case '|': case '.': case '-': case '^': case '?': + case '*': case '+': case '{': case '}': case '(': case ')': + case '[': case ']': + end = cur; break; + default: + ERROR("Invalid escape value"); + return; + } + len = 1; + } else if ((cur != 0x5B) && (cur != 0x5D)) { + end = CUR_SCHAR(ctxt->cur, len); + } else { + ERROR("Expecting the end of a char range"); + return; + } + NEXTL(len); + /* TODO check that the values are acceptable character ranges for XML */ + if (end < start) { + ERROR("End of range is before start of range"); + } else { + xmlRegAtomAddRange(ctxt, ctxt->atom, ctxt->neg, + XML_REGEXP_CHARVAL, start, end, NULL); + } + return; +} + +/** + * xmlFAParsePosCharGroup: + * @ctxt: a regexp parser context + * + * [14] posCharGroup ::= ( charRange | charClassEsc )+ + */ +static void +xmlFAParsePosCharGroup(xmlRegParserCtxtPtr ctxt) { + do { + if ((CUR == '\\') || (CUR == '.')) { + xmlFAParseCharClassEsc(ctxt); + } else { + xmlFAParseCharRange(ctxt); + } + } while ((CUR != ']') && (CUR != '^') && (CUR != '-') && + (CUR != 0) && (ctxt->error == 0)); +} + +/** + * xmlFAParseCharGroup: + * @ctxt: a regexp parser context + * + * [13] charGroup ::= posCharGroup | negCharGroup | charClassSub + * [15] negCharGroup ::= '^' posCharGroup + * [16] charClassSub ::= ( posCharGroup | negCharGroup ) '-' charClassExpr + * [12] charClassExpr ::= '[' charGroup ']' + */ +static void +xmlFAParseCharGroup(xmlRegParserCtxtPtr ctxt) { + int n = ctxt->neg; + while ((CUR != ']') && (ctxt->error == 0)) { + if (CUR == '^') { + int neg = ctxt->neg; + + NEXT; + ctxt->neg = !ctxt->neg; + xmlFAParsePosCharGroup(ctxt); + ctxt->neg = neg; + } else if ((CUR == '-') && (NXT(1) == '[')) { + int neg = ctxt->neg; + ctxt->neg = 2; + NEXT; /* eat the '-' */ + NEXT; /* eat the '[' */ + xmlFAParseCharGroup(ctxt); + if (CUR == ']') { + NEXT; + } else { + ERROR("charClassExpr: ']' expected"); + break; + } + ctxt->neg = neg; + break; + } else if (CUR != ']') { + xmlFAParsePosCharGroup(ctxt); + } + } + ctxt->neg = n; +} + +/** + * xmlFAParseCharClass: + * @ctxt: a regexp parser context + * + * [11] charClass ::= charClassEsc | charClassExpr + * [12] charClassExpr ::= '[' charGroup ']' + */ +static void +xmlFAParseCharClass(xmlRegParserCtxtPtr ctxt) { + if (CUR == '[') { + NEXT; + ctxt->atom = xmlRegNewAtom(ctxt, XML_REGEXP_RANGES); + if (ctxt->atom == NULL) + return; + xmlFAParseCharGroup(ctxt); + if (CUR == ']') { + NEXT; + } else { + ERROR("xmlFAParseCharClass: ']' expected"); + } + } else { + xmlFAParseCharClassEsc(ctxt); + } +} + +/** + * xmlFAParseQuantExact: + * @ctxt: a regexp parser context + * + * [8] QuantExact ::= [0-9]+ + * + * Returns 0 if success or -1 in case of error + */ +static int +xmlFAParseQuantExact(xmlRegParserCtxtPtr ctxt) { + int ret = 0; + int ok = 0; + + while ((CUR >= '0') && (CUR <= '9')) { + ret = ret * 10 + (CUR - '0'); + ok = 1; + NEXT; + } + if (ok != 1) { + return(-1); + } + return(ret); +} + +/** + * xmlFAParseQuantifier: + * @ctxt: a regexp parser context + * + * [4] quantifier ::= [?*+] | ( '{' quantity '}' ) + * [5] quantity ::= quantRange | quantMin | QuantExact + * [6] quantRange ::= QuantExact ',' QuantExact + * [7] quantMin ::= QuantExact ',' + * [8] QuantExact ::= [0-9]+ + */ +static int +xmlFAParseQuantifier(xmlRegParserCtxtPtr ctxt) { + int cur; + + cur = CUR; + if ((cur == '?') || (cur == '*') || (cur == '+')) { + if (ctxt->atom != NULL) { + if (cur == '?') + ctxt->atom->quant = XML_REGEXP_QUANT_OPT; + else if (cur == '*') + ctxt->atom->quant = XML_REGEXP_QUANT_MULT; + else if (cur == '+') + ctxt->atom->quant = XML_REGEXP_QUANT_PLUS; + } + NEXT; + return(1); + } + if (cur == '{') { + int min = 0, max = 0; + + NEXT; + cur = xmlFAParseQuantExact(ctxt); + if (cur >= 0) + min = cur; + if (CUR == ',') { + NEXT; + if (CUR == '}') + max = INT_MAX; + else { + cur = xmlFAParseQuantExact(ctxt); + if (cur >= 0) + max = cur; + else { + ERROR("Improper quantifier"); + } + } + } + if (CUR == '}') { + NEXT; + } else { + ERROR("Unterminated quantifier"); + } + if (max == 0) + max = min; + if (ctxt->atom != NULL) { + ctxt->atom->quant = XML_REGEXP_QUANT_RANGE; + ctxt->atom->min = min; + ctxt->atom->max = max; + } + return(1); + } + return(0); +} + +/** + * xmlFAParseAtom: + * @ctxt: a regexp parser context + * + * [9] atom ::= Char | charClass | ( '(' regExp ')' ) + */ +static int +xmlFAParseAtom(xmlRegParserCtxtPtr ctxt) { + int codepoint, len; + + codepoint = xmlFAIsChar(ctxt); + if (codepoint > 0) { + ctxt->atom = xmlRegNewAtom(ctxt, XML_REGEXP_CHARVAL); + if (ctxt->atom == NULL) + return(-1); + codepoint = CUR_SCHAR(ctxt->cur, len); + ctxt->atom->codepoint = codepoint; + NEXTL(len); + return(1); + } else if (CUR == '|') { + return(0); + } else if (CUR == 0) { + return(0); + } else if (CUR == ')') { + return(0); + } else if (CUR == '(') { + xmlRegStatePtr start, oldend; + + NEXT; + xmlFAGenerateEpsilonTransition(ctxt, ctxt->state, NULL); + start = ctxt->state; + oldend = ctxt->end; + ctxt->end = NULL; + ctxt->atom = NULL; + xmlFAParseRegExp(ctxt, 0); + if (CUR == ')') { + NEXT; + } else { + ERROR("xmlFAParseAtom: expecting ')'"); + } + ctxt->atom = xmlRegNewAtom(ctxt, XML_REGEXP_SUBREG); + if (ctxt->atom == NULL) + return(-1); + ctxt->atom->start = start; + ctxt->atom->stop = ctxt->state; + ctxt->end = oldend; + return(1); + } else if ((CUR == '[') || (CUR == '\\') || (CUR == '.')) { + xmlFAParseCharClass(ctxt); + return(1); + } + return(0); +} + +/** + * xmlFAParsePiece: + * @ctxt: a regexp parser context + * + * [3] piece ::= atom quantifier? + */ +static int +xmlFAParsePiece(xmlRegParserCtxtPtr ctxt) { + int ret; + + ctxt->atom = NULL; + ret = xmlFAParseAtom(ctxt); + if (ret == 0) + return(0); + if (ctxt->atom == NULL) { + ERROR("internal: no atom generated"); + } + xmlFAParseQuantifier(ctxt); + return(1); +} + +/** + * xmlFAParseBranch: + * @ctxt: a regexp parser context + * @to: optional target to the end of the branch + * + * @to is used to optimize by removing duplicate path in automata + * in expressions like (a|b)(c|d) + * + * [2] branch ::= piece* + */ +static int +xmlFAParseBranch(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr to) { + xmlRegStatePtr previous; + int ret; + + previous = ctxt->state; + ret = xmlFAParsePiece(ctxt); + if (ret != 0) { + if (xmlFAGenerateTransitions(ctxt, previous, + (CUR=='|' || CUR==')') ? to : NULL, ctxt->atom) < 0) + return(-1); + previous = ctxt->state; + ctxt->atom = NULL; + } + while ((ret != 0) && (ctxt->error == 0)) { + ret = xmlFAParsePiece(ctxt); + if (ret != 0) { + if (xmlFAGenerateTransitions(ctxt, previous, + (CUR=='|' || CUR==')') ? to : NULL, ctxt->atom) < 0) + return(-1); + previous = ctxt->state; + ctxt->atom = NULL; + } + } + return(0); +} + +/** + * xmlFAParseRegExp: + * @ctxt: a regexp parser context + * @top: is this the top-level expression ? + * + * [1] regExp ::= branch ( '|' branch )* + */ +static void +xmlFAParseRegExp(xmlRegParserCtxtPtr ctxt, int top) { + xmlRegStatePtr start, end; + + /* if not top start should have been generated by an epsilon trans */ + start = ctxt->state; + ctxt->end = NULL; + xmlFAParseBranch(ctxt, NULL); + if (top) { +#ifdef DEBUG_REGEXP_GRAPH + printf("State %d is final\n", ctxt->state->no); +#endif + ctxt->state->type = XML_REGEXP_FINAL_STATE; + } + if (CUR != '|') { + ctxt->end = ctxt->state; + return; + } + end = ctxt->state; + while ((CUR == '|') && (ctxt->error == 0)) { + NEXT; + ctxt->state = start; + ctxt->end = NULL; + xmlFAParseBranch(ctxt, end); + } + if (!top) { + ctxt->state = end; + ctxt->end = end; + } +} + +/************************************************************************ + * * + * The basic API * + * * + ************************************************************************/ + +/** + * xmlRegexpPrint: + * @output: the file for the output debug + * @regexp: the compiled regexp + * + * Print the content of the compiled regular expression + */ +void +xmlRegexpPrint(FILE *output, xmlRegexpPtr regexp) { + int i; + + if (output == NULL) + return; + fprintf(output, " regexp: "); + if (regexp == NULL) { + fprintf(output, "NULL\n"); + return; + } + fprintf(output, "'%s' ", regexp->string); + fprintf(output, "\n"); + fprintf(output, "%d atoms:\n", regexp->nbAtoms); + for (i = 0;i < regexp->nbAtoms; i++) { + fprintf(output, " %02d ", i); + xmlRegPrintAtom(output, regexp->atoms[i]); + } + fprintf(output, "%d states:", regexp->nbStates); + fprintf(output, "\n"); + for (i = 0;i < regexp->nbStates; i++) { + xmlRegPrintState(output, regexp->states[i]); + } + fprintf(output, "%d counters:\n", regexp->nbCounters); + for (i = 0;i < regexp->nbCounters; i++) { + fprintf(output, " %d: min %d max %d\n", i, regexp->counters[i].min, + regexp->counters[i].max); + } +} + +/** + * xmlRegexpCompile: + * @regexp: a regular expression string + * + * Parses a regular expression conforming to XML Schemas Part 2 Datatype + * Appendix F and builds an automata suitable for testing strings against + * that regular expression + * + * Returns the compiled expression or NULL in case of error + */ +xmlRegexpPtr +xmlRegexpCompile(const xmlChar *regexp) { + xmlRegexpPtr ret; + xmlRegParserCtxtPtr ctxt; + + ctxt = xmlRegNewParserCtxt(regexp); + if (ctxt == NULL) + return(NULL); + + /* initialize the parser */ + ctxt->end = NULL; + ctxt->start = ctxt->state = xmlRegNewState(ctxt); + xmlRegStatePush(ctxt, ctxt->start); + + /* parse the expression building an automata */ + xmlFAParseRegExp(ctxt, 1); + if (CUR != 0) { + ERROR("xmlFAParseRegExp: extra characters"); + } + ctxt->end = ctxt->state; + ctxt->start->type = XML_REGEXP_START_STATE; + ctxt->end->type = XML_REGEXP_FINAL_STATE; + + /* remove the Epsilon except for counted transitions */ + xmlFAEliminateEpsilonTransitions(ctxt); + + + if (ctxt->error != 0) { + xmlRegFreeParserCtxt(ctxt); + return(NULL); + } + ret = xmlRegEpxFromParse(ctxt); + xmlRegFreeParserCtxt(ctxt); + return(ret); +} + +/** + * xmlRegexpExec: + * @comp: the compiled regular expression + * @content: the value to check against the regular expression + * + * Check if the regular expression generates the value + * + * Returns 1 if it matches, 0 if not and a negative value in case of error + */ +int +xmlRegexpExec(xmlRegexpPtr comp, const xmlChar *content) { + if ((comp == NULL) || (content == NULL)) + return(-1); + return(xmlFARegExec(comp, content)); +} + +/** + * xmlRegexpIsDeterminist: + * @comp: the compiled regular expression + * + * Check if the regular expression is determinist + * + * Returns 1 if it yes, 0 if not and a negative value in case of error + */ +int +xmlRegexpIsDeterminist(xmlRegexpPtr comp) { + xmlAutomataPtr am; + int ret; + + if (comp == NULL) + return(-1); + if (comp->determinist != -1) + return(comp->determinist); + + am = xmlNewAutomata(); + if (am->states != NULL) { + int i; + + for (i = 0;i < am->nbStates;i++) + xmlRegFreeState(am->states[i]); + xmlFree(am->states); + } + am->nbAtoms = comp->nbAtoms; + am->atoms = comp->atoms; + am->nbStates = comp->nbStates; + am->states = comp->states; + am->determinist = -1; + ret = xmlFAComputesDeterminism(am); + am->atoms = NULL; + am->states = NULL; + xmlFreeAutomata(am); + return(ret); +} + +/** + * xmlRegFreeRegexp: + * @regexp: the regexp + * + * Free a regexp + */ +void +xmlRegFreeRegexp(xmlRegexpPtr regexp) { + int i; + if (regexp == NULL) + return; + + if (regexp->string != NULL) + xmlFree(regexp->string); + if (regexp->states != NULL) { + for (i = 0;i < regexp->nbStates;i++) + xmlRegFreeState(regexp->states[i]); + xmlFree(regexp->states); + } + if (regexp->atoms != NULL) { + for (i = 0;i < regexp->nbAtoms;i++) + xmlRegFreeAtom(regexp->atoms[i]); + xmlFree(regexp->atoms); + } + if (regexp->counters != NULL) + xmlFree(regexp->counters); + if (regexp->compact != NULL) + xmlFree(regexp->compact); + if (regexp->transdata != NULL) + xmlFree(regexp->transdata); + if (regexp->stringMap != NULL) { + for (i = 0; i < regexp->nbstrings;i++) + xmlFree(regexp->stringMap[i]); + xmlFree(regexp->stringMap); + } + + xmlFree(regexp); +} + +#ifdef LIBXML_AUTOMATA_ENABLED +/************************************************************************ + * * + * The Automata interface * + * * + ************************************************************************/ + +/** + * xmlNewAutomata: + * + * Create a new automata + * + * Returns the new object or NULL in case of failure + */ +xmlAutomataPtr +xmlNewAutomata(void) { + xmlAutomataPtr ctxt; + + ctxt = xmlRegNewParserCtxt(NULL); + if (ctxt == NULL) + return(NULL); + + /* initialize the parser */ + ctxt->end = NULL; + ctxt->start = ctxt->state = xmlRegNewState(ctxt); + if (ctxt->start == NULL) { + xmlFreeAutomata(ctxt); + return(NULL); + } + ctxt->start->type = XML_REGEXP_START_STATE; + if (xmlRegStatePush(ctxt, ctxt->start) < 0) { + xmlRegFreeState(ctxt->start); + xmlFreeAutomata(ctxt); + return(NULL); + } + + return(ctxt); +} + +/** + * xmlFreeAutomata: + * @am: an automata + * + * Free an automata + */ +void +xmlFreeAutomata(xmlAutomataPtr am) { + if (am == NULL) + return; + xmlRegFreeParserCtxt(am); +} + +/** + * xmlAutomataGetInitState: + * @am: an automata + * + * Initial state lookup + * + * Returns the initial state of the automata + */ +xmlAutomataStatePtr +xmlAutomataGetInitState(xmlAutomataPtr am) { + if (am == NULL) + return(NULL); + return(am->start); +} + +/** + * xmlAutomataSetFinalState: + * @am: an automata + * @state: a state in this automata + * + * Makes that state a final state + * + * Returns 0 or -1 in case of error + */ +int +xmlAutomataSetFinalState(xmlAutomataPtr am, xmlAutomataStatePtr state) { + if ((am == NULL) || (state == NULL)) + return(-1); + state->type = XML_REGEXP_FINAL_STATE; + return(0); +} + +/** + * xmlAutomataNewTransition: + * @am: an automata + * @from: the starting point of the transition + * @to: the target point of the transition or NULL + * @token: the input string associated to that transition + * @data: data passed to the callback function if the transition is activated + * + * If @to is NULL, this creates first a new target state in the automata + * and then adds a transition from the @from state to the target state + * activated by the value of @token + * + * Returns the target state or NULL in case of error + */ +xmlAutomataStatePtr +xmlAutomataNewTransition(xmlAutomataPtr am, xmlAutomataStatePtr from, + xmlAutomataStatePtr to, const xmlChar *token, + void *data) { + xmlRegAtomPtr atom; + + if ((am == NULL) || (from == NULL) || (token == NULL)) + return(NULL); + atom = xmlRegNewAtom(am, XML_REGEXP_STRING); + if (atom == NULL) + return(NULL); + atom->data = data; + if (atom == NULL) + return(NULL); + atom->valuep = xmlStrdup(token); + + if (xmlFAGenerateTransitions(am, from, to, atom) < 0) { + xmlRegFreeAtom(atom); + return(NULL); + } + if (to == NULL) + return(am->state); + return(to); +} + +/** + * xmlAutomataNewTransition2: + * @am: an automata + * @from: the starting point of the transition + * @to: the target point of the transition or NULL + * @token: the first input string associated to that transition + * @token2: the second input string associated to that transition + * @data: data passed to the callback function if the transition is activated + * + * If @to is NULL, this creates first a new target state in the automata + * and then adds a transition from the @from state to the target state + * activated by the value of @token + * + * Returns the target state or NULL in case of error + */ +xmlAutomataStatePtr +xmlAutomataNewTransition2(xmlAutomataPtr am, xmlAutomataStatePtr from, + xmlAutomataStatePtr to, const xmlChar *token, + const xmlChar *token2, void *data) { + xmlRegAtomPtr atom; + + if ((am == NULL) || (from == NULL) || (token == NULL)) + return(NULL); + atom = xmlRegNewAtom(am, XML_REGEXP_STRING); + if (atom == NULL) + return(NULL); + atom->data = data; + if ((token2 == NULL) || (*token2 == 0)) { + atom->valuep = xmlStrdup(token); + } else { + int lenn, lenp; + xmlChar *str; + + lenn = strlen((char *) token2); + lenp = strlen((char *) token); + + str = (xmlChar *) xmlMallocAtomic(lenn + lenp + 2); + if (str == NULL) { + xmlRegFreeAtom(atom); + return(NULL); + } + memcpy(&str[0], token, lenp); + str[lenp] = '|'; + memcpy(&str[lenp + 1], token2, lenn); + str[lenn + lenp + 1] = 0; + + atom->valuep = str; + } + + if (xmlFAGenerateTransitions(am, from, to, atom) < 0) { + xmlRegFreeAtom(atom); + return(NULL); + } + if (to == NULL) + return(am->state); + return(to); +} + +/** + * xmlAutomataNewNegTrans: + * @am: an automata + * @from: the starting point of the transition + * @to: the target point of the transition or NULL + * @token: the first input string associated to that transition + * @token2: the second input string associated to that transition + * @data: data passed to the callback function if the transition is activated + * + * If @to is NULL, this creates first a new target state in the automata + * and then adds a transition from the @from state to the target state + * activated by any value except (@token,@token2) + * Note that if @token2 is not NULL, then (X, NULL) won't match to follow + # the semantic of XSD ##other + * + * Returns the target state or NULL in case of error + */ +xmlAutomataStatePtr +xmlAutomataNewNegTrans(xmlAutomataPtr am, xmlAutomataStatePtr from, + xmlAutomataStatePtr to, const xmlChar *token, + const xmlChar *token2, void *data) { + xmlRegAtomPtr atom; + xmlChar err_msg[200]; + + if ((am == NULL) || (from == NULL) || (token == NULL)) + return(NULL); + atom = xmlRegNewAtom(am, XML_REGEXP_STRING); + if (atom == NULL) + return(NULL); + atom->data = data; + atom->neg = 1; + if ((token2 == NULL) || (*token2 == 0)) { + atom->valuep = xmlStrdup(token); + } else { + int lenn, lenp; + xmlChar *str; + + lenn = strlen((char *) token2); + lenp = strlen((char *) token); + + str = (xmlChar *) xmlMallocAtomic(lenn + lenp + 2); + if (str == NULL) { + xmlRegFreeAtom(atom); + return(NULL); + } + memcpy(&str[0], token, lenp); + str[lenp] = '|'; + memcpy(&str[lenp + 1], token2, lenn); + str[lenn + lenp + 1] = 0; + + atom->valuep = str; + } + snprintf((char *) err_msg, 199, "not %s", (const char *) atom->valuep); + err_msg[199] = 0; + atom->valuep2 = xmlStrdup(err_msg); + + if (xmlFAGenerateTransitions(am, from, to, atom) < 0) { + xmlRegFreeAtom(atom); + return(NULL); + } + am->negs++; + if (to == NULL) + return(am->state); + return(to); +} + +/** + * xmlAutomataNewCountTrans2: + * @am: an automata + * @from: the starting point of the transition + * @to: the target point of the transition or NULL + * @token: the input string associated to that transition + * @token2: the second input string associated to that transition + * @min: the minimum successive occurences of token + * @max: the maximum successive occurences of token + * @data: data associated to the transition + * + * If @to is NULL, this creates first a new target state in the automata + * and then adds a transition from the @from state to the target state + * activated by a succession of input of value @token and @token2 and + * whose number is between @min and @max + * + * Returns the target state or NULL in case of error + */ +xmlAutomataStatePtr +xmlAutomataNewCountTrans2(xmlAutomataPtr am, xmlAutomataStatePtr from, + xmlAutomataStatePtr to, const xmlChar *token, + const xmlChar *token2, + int min, int max, void *data) { + xmlRegAtomPtr atom; + int counter; + + if ((am == NULL) || (from == NULL) || (token == NULL)) + return(NULL); + if (min < 0) + return(NULL); + if ((max < min) || (max < 1)) + return(NULL); + atom = xmlRegNewAtom(am, XML_REGEXP_STRING); + if (atom == NULL) + return(NULL); + if ((token2 == NULL) || (*token2 == 0)) { + atom->valuep = xmlStrdup(token); + } else { + int lenn, lenp; + xmlChar *str; + + lenn = strlen((char *) token2); + lenp = strlen((char *) token); + + str = (xmlChar *) xmlMallocAtomic(lenn + lenp + 2); + if (str == NULL) { + xmlRegFreeAtom(atom); + return(NULL); + } + memcpy(&str[0], token, lenp); + str[lenp] = '|'; + memcpy(&str[lenp + 1], token2, lenn); + str[lenn + lenp + 1] = 0; + + atom->valuep = str; + } + atom->data = data; + if (min == 0) + atom->min = 1; + else + atom->min = min; + atom->max = max; + + /* + * associate a counter to the transition. + */ + counter = xmlRegGetCounter(am); + am->counters[counter].min = min; + am->counters[counter].max = max; + + /* xmlFAGenerateTransitions(am, from, to, atom); */ + if (to == NULL) { + to = xmlRegNewState(am); + xmlRegStatePush(am, to); + } + xmlRegStateAddTrans(am, from, atom, to, counter, -1); + xmlRegAtomPush(am, atom); + am->state = to; + + if (to == NULL) + to = am->state; + if (to == NULL) + return(NULL); + if (min == 0) + xmlFAGenerateEpsilonTransition(am, from, to); + return(to); +} + +/** + * xmlAutomataNewCountTrans: + * @am: an automata + * @from: the starting point of the transition + * @to: the target point of the transition or NULL + * @token: the input string associated to that transition + * @min: the minimum successive occurences of token + * @max: the maximum successive occurences of token + * @data: data associated to the transition + * + * If @to is NULL, this creates first a new target state in the automata + * and then adds a transition from the @from state to the target state + * activated by a succession of input of value @token and whose number + * is between @min and @max + * + * Returns the target state or NULL in case of error + */ +xmlAutomataStatePtr +xmlAutomataNewCountTrans(xmlAutomataPtr am, xmlAutomataStatePtr from, + xmlAutomataStatePtr to, const xmlChar *token, + int min, int max, void *data) { + xmlRegAtomPtr atom; + int counter; + + if ((am == NULL) || (from == NULL) || (token == NULL)) + return(NULL); + if (min < 0) + return(NULL); + if ((max < min) || (max < 1)) + return(NULL); + atom = xmlRegNewAtom(am, XML_REGEXP_STRING); + if (atom == NULL) + return(NULL); + atom->valuep = xmlStrdup(token); + atom->data = data; + if (min == 0) + atom->min = 1; + else + atom->min = min; + atom->max = max; + + /* + * associate a counter to the transition. + */ + counter = xmlRegGetCounter(am); + am->counters[counter].min = min; + am->counters[counter].max = max; + + /* xmlFAGenerateTransitions(am, from, to, atom); */ + if (to == NULL) { + to = xmlRegNewState(am); + xmlRegStatePush(am, to); + } + xmlRegStateAddTrans(am, from, atom, to, counter, -1); + xmlRegAtomPush(am, atom); + am->state = to; + + if (to == NULL) + to = am->state; + if (to == NULL) + return(NULL); + if (min == 0) + xmlFAGenerateEpsilonTransition(am, from, to); + return(to); +} + +/** + * xmlAutomataNewOnceTrans2: + * @am: an automata + * @from: the starting point of the transition + * @to: the target point of the transition or NULL + * @token: the input string associated to that transition + * @token2: the second input string associated to that transition + * @min: the minimum successive occurences of token + * @max: the maximum successive occurences of token + * @data: data associated to the transition + * + * If @to is NULL, this creates first a new target state in the automata + * and then adds a transition from the @from state to the target state + * activated by a succession of input of value @token and @token2 and whose + * number is between @min and @max, moreover that transition can only be + * crossed once. + * + * Returns the target state or NULL in case of error + */ +xmlAutomataStatePtr +xmlAutomataNewOnceTrans2(xmlAutomataPtr am, xmlAutomataStatePtr from, + xmlAutomataStatePtr to, const xmlChar *token, + const xmlChar *token2, + int min, int max, void *data) { + xmlRegAtomPtr atom; + int counter; + + if ((am == NULL) || (from == NULL) || (token == NULL)) + return(NULL); + if (min < 1) + return(NULL); + if ((max < min) || (max < 1)) + return(NULL); + atom = xmlRegNewAtom(am, XML_REGEXP_STRING); + if (atom == NULL) + return(NULL); + if ((token2 == NULL) || (*token2 == 0)) { + atom->valuep = xmlStrdup(token); + } else { + int lenn, lenp; + xmlChar *str; + + lenn = strlen((char *) token2); + lenp = strlen((char *) token); + + str = (xmlChar *) xmlMallocAtomic(lenn + lenp + 2); + if (str == NULL) { + xmlRegFreeAtom(atom); + return(NULL); + } + memcpy(&str[0], token, lenp); + str[lenp] = '|'; + memcpy(&str[lenp + 1], token2, lenn); + str[lenn + lenp + 1] = 0; + + atom->valuep = str; + } + atom->data = data; + atom->quant = XML_REGEXP_QUANT_ONCEONLY; + atom->min = min; + atom->max = max; + /* + * associate a counter to the transition. + */ + counter = xmlRegGetCounter(am); + am->counters[counter].min = 1; + am->counters[counter].max = 1; + + /* xmlFAGenerateTransitions(am, from, to, atom); */ + if (to == NULL) { + to = xmlRegNewState(am); + xmlRegStatePush(am, to); + } + xmlRegStateAddTrans(am, from, atom, to, counter, -1); + xmlRegAtomPush(am, atom); + am->state = to; + return(to); +} + + + +/** + * xmlAutomataNewOnceTrans: + * @am: an automata + * @from: the starting point of the transition + * @to: the target point of the transition or NULL + * @token: the input string associated to that transition + * @min: the minimum successive occurences of token + * @max: the maximum successive occurences of token + * @data: data associated to the transition + * + * If @to is NULL, this creates first a new target state in the automata + * and then adds a transition from the @from state to the target state + * activated by a succession of input of value @token and whose number + * is between @min and @max, moreover that transition can only be crossed + * once. + * + * Returns the target state or NULL in case of error + */ +xmlAutomataStatePtr +xmlAutomataNewOnceTrans(xmlAutomataPtr am, xmlAutomataStatePtr from, + xmlAutomataStatePtr to, const xmlChar *token, + int min, int max, void *data) { + xmlRegAtomPtr atom; + int counter; + + if ((am == NULL) || (from == NULL) || (token == NULL)) + return(NULL); + if (min < 1) + return(NULL); + if ((max < min) || (max < 1)) + return(NULL); + atom = xmlRegNewAtom(am, XML_REGEXP_STRING); + if (atom == NULL) + return(NULL); + atom->valuep = xmlStrdup(token); + atom->data = data; + atom->quant = XML_REGEXP_QUANT_ONCEONLY; + atom->min = min; + atom->max = max; + /* + * associate a counter to the transition. + */ + counter = xmlRegGetCounter(am); + am->counters[counter].min = 1; + am->counters[counter].max = 1; + + /* xmlFAGenerateTransitions(am, from, to, atom); */ + if (to == NULL) { + to = xmlRegNewState(am); + xmlRegStatePush(am, to); + } + xmlRegStateAddTrans(am, from, atom, to, counter, -1); + xmlRegAtomPush(am, atom); + am->state = to; + return(to); +} + +/** + * xmlAutomataNewState: + * @am: an automata + * + * Create a new disconnected state in the automata + * + * Returns the new state or NULL in case of error + */ +xmlAutomataStatePtr +xmlAutomataNewState(xmlAutomataPtr am) { + xmlAutomataStatePtr to; + + if (am == NULL) + return(NULL); + to = xmlRegNewState(am); + xmlRegStatePush(am, to); + return(to); +} + +/** + * xmlAutomataNewEpsilon: + * @am: an automata + * @from: the starting point of the transition + * @to: the target point of the transition or NULL + * + * If @to is NULL, this creates first a new target state in the automata + * and then adds an epsilon transition from the @from state to the + * target state + * + * Returns the target state or NULL in case of error + */ +xmlAutomataStatePtr +xmlAutomataNewEpsilon(xmlAutomataPtr am, xmlAutomataStatePtr from, + xmlAutomataStatePtr to) { + if ((am == NULL) || (from == NULL)) + return(NULL); + xmlFAGenerateEpsilonTransition(am, from, to); + if (to == NULL) + return(am->state); + return(to); +} + +/** + * xmlAutomataNewAllTrans: + * @am: an automata + * @from: the starting point of the transition + * @to: the target point of the transition or NULL + * @lax: allow to transition if not all all transitions have been activated + * + * If @to is NULL, this creates first a new target state in the automata + * and then adds a an ALL transition from the @from state to the + * target state. That transition is an epsilon transition allowed only when + * all transitions from the @from node have been activated. + * + * Returns the target state or NULL in case of error + */ +xmlAutomataStatePtr +xmlAutomataNewAllTrans(xmlAutomataPtr am, xmlAutomataStatePtr from, + xmlAutomataStatePtr to, int lax) { + if ((am == NULL) || (from == NULL)) + return(NULL); + xmlFAGenerateAllTransition(am, from, to, lax); + if (to == NULL) + return(am->state); + return(to); +} + +/** + * xmlAutomataNewCounter: + * @am: an automata + * @min: the minimal value on the counter + * @max: the maximal value on the counter + * + * Create a new counter + * + * Returns the counter number or -1 in case of error + */ +int +xmlAutomataNewCounter(xmlAutomataPtr am, int min, int max) { + int ret; + + if (am == NULL) + return(-1); + + ret = xmlRegGetCounter(am); + if (ret < 0) + return(-1); + am->counters[ret].min = min; + am->counters[ret].max = max; + return(ret); +} + +/** + * xmlAutomataNewCountedTrans: + * @am: an automata + * @from: the starting point of the transition + * @to: the target point of the transition or NULL + * @counter: the counter associated to that transition + * + * If @to is NULL, this creates first a new target state in the automata + * and then adds an epsilon transition from the @from state to the target state + * which will increment the counter provided + * + * Returns the target state or NULL in case of error + */ +xmlAutomataStatePtr +xmlAutomataNewCountedTrans(xmlAutomataPtr am, xmlAutomataStatePtr from, + xmlAutomataStatePtr to, int counter) { + if ((am == NULL) || (from == NULL) || (counter < 0)) + return(NULL); + xmlFAGenerateCountedEpsilonTransition(am, from, to, counter); + if (to == NULL) + return(am->state); + return(to); +} + +/** + * xmlAutomataNewCounterTrans: + * @am: an automata + * @from: the starting point of the transition + * @to: the target point of the transition or NULL + * @counter: the counter associated to that transition + * + * If @to is NULL, this creates first a new target state in the automata + * and then adds an epsilon transition from the @from state to the target state + * which will be allowed only if the counter is within the right range. + * + * Returns the target state or NULL in case of error + */ +xmlAutomataStatePtr +xmlAutomataNewCounterTrans(xmlAutomataPtr am, xmlAutomataStatePtr from, + xmlAutomataStatePtr to, int counter) { + if ((am == NULL) || (from == NULL) || (counter < 0)) + return(NULL); + xmlFAGenerateCountedTransition(am, from, to, counter); + if (to == NULL) + return(am->state); + return(to); +} + +/** + * xmlAutomataCompile: + * @am: an automata + * + * Compile the automata into a Reg Exp ready for being executed. + * The automata should be free after this point. + * + * Returns the compiled regexp or NULL in case of error + */ +xmlRegexpPtr +xmlAutomataCompile(xmlAutomataPtr am) { + xmlRegexpPtr ret; + + if ((am == NULL) || (am->error != 0)) return(NULL); + xmlFAEliminateEpsilonTransitions(am); + /* xmlFAComputesDeterminism(am); */ + ret = xmlRegEpxFromParse(am); + + return(ret); +} + +/** + * xmlAutomataIsDeterminist: + * @am: an automata + * + * Checks if an automata is determinist. + * + * Returns 1 if true, 0 if not, and -1 in case of error + */ +int +xmlAutomataIsDeterminist(xmlAutomataPtr am) { + int ret; + + if (am == NULL) + return(-1); + + ret = xmlFAComputesDeterminism(am); + return(ret); +} +#endif /* LIBXML_AUTOMATA_ENABLED */ + +#ifdef LIBXML_EXPR_ENABLED +/************************************************************************ + * * + * Formal Expression handling code * + * * + ************************************************************************/ +/************************************************************************ + * * + * Expression handling context * + * * + ************************************************************************/ + +struct _xmlExpCtxt { + xmlDictPtr dict; + xmlExpNodePtr *table; + int size; + int nbElems; + int nb_nodes; + const char *expr; + const char *cur; + int nb_cons; + int tabSize; +}; + +/** + * xmlExpNewCtxt: + * @maxNodes: the maximum number of nodes + * @dict: optional dictionnary to use internally + * + * Creates a new context for manipulating expressions + * + * Returns the context or NULL in case of error + */ +xmlExpCtxtPtr +xmlExpNewCtxt(int maxNodes, xmlDictPtr dict) { + xmlExpCtxtPtr ret; + int size = 256; + + if (maxNodes <= 4096) + maxNodes = 4096; + + ret = (xmlExpCtxtPtr) xmlMalloc(sizeof(xmlExpCtxt)); + if (ret == NULL) + return(NULL); + memset(ret, 0, sizeof(xmlExpCtxt)); + ret->size = size; + ret->nbElems = 0; + ret->table = xmlMalloc(size * sizeof(xmlExpNodePtr)); + if (ret->table == NULL) { + xmlFree(ret); + return(NULL); + } + memset(ret->table, 0, size * sizeof(xmlExpNodePtr)); + if (dict == NULL) { + ret->dict = xmlDictCreate(); + if (ret->dict == NULL) { + xmlFree(ret->table); + xmlFree(ret); + return(NULL); + } + } else { + ret->dict = dict; + xmlDictReference(ret->dict); + } + return(ret); +} + +/** + * xmlExpFreeCtxt: + * @ctxt: an expression context + * + * Free an expression context + */ +void +xmlExpFreeCtxt(xmlExpCtxtPtr ctxt) { + if (ctxt == NULL) + return; + xmlDictFree(ctxt->dict); + if (ctxt->table != NULL) + xmlFree(ctxt->table); + xmlFree(ctxt); +} + +/************************************************************************ + * * + * Structure associated to an expression node * + * * + ************************************************************************/ +#define MAX_NODES 10000 + +/* #define DEBUG_DERIV */ + +/* + * TODO: + * - Wildcards + * - public API for creation + * + * Started + * - regression testing + * + * Done + * - split into module and test tool + * - memleaks + */ + +typedef enum { + XML_EXP_NILABLE = (1 << 0) +} xmlExpNodeInfo; + +#define IS_NILLABLE(node) ((node)->info & XML_EXP_NILABLE) + +struct _xmlExpNode { + unsigned char type;/* xmlExpNodeType */ + unsigned char info;/* OR of xmlExpNodeInfo */ + unsigned short key; /* the hash key */ + unsigned int ref; /* The number of references */ + int c_max; /* the maximum length it can consume */ + xmlExpNodePtr exp_left; + xmlExpNodePtr next;/* the next node in the hash table or free list */ + union { + struct { + int f_min; + int f_max; + } count; + struct { + xmlExpNodePtr f_right; + } children; + const xmlChar *f_str; + } field; +}; + +#define exp_min field.count.f_min +#define exp_max field.count.f_max +/* #define exp_left field.children.f_left */ +#define exp_right field.children.f_right +#define exp_str field.f_str + +static xmlExpNodePtr xmlExpNewNode(xmlExpCtxtPtr ctxt, xmlExpNodeType type); +static xmlExpNode forbiddenExpNode = { + XML_EXP_FORBID, 0, 0, 0, 0, NULL, NULL, {{ 0, 0}} +}; +xmlExpNodePtr forbiddenExp = &forbiddenExpNode; +static xmlExpNode emptyExpNode = { + XML_EXP_EMPTY, 1, 0, 0, 0, NULL, NULL, {{ 0, 0}} +}; +xmlExpNodePtr emptyExp = &emptyExpNode; + +/************************************************************************ + * * + * The custom hash table for unicity and canonicalization * + * of sub-expressions pointers * + * * + ************************************************************************/ +/* + * xmlExpHashNameComputeKey: + * Calculate the hash key for a token + */ +static unsigned short +xmlExpHashNameComputeKey(const xmlChar *name) { + unsigned short value = 0L; + char ch; + + if (name != NULL) { + value += 30 * (*name); + while ((ch = *name++) != 0) { + value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch); + } + } + return (value); +} + +/* + * xmlExpHashComputeKey: + * Calculate the hash key for a compound expression + */ +static unsigned short +xmlExpHashComputeKey(xmlExpNodeType type, xmlExpNodePtr left, + xmlExpNodePtr right) { + unsigned long value; + unsigned short ret; + + switch (type) { + case XML_EXP_SEQ: + value = left->key; + value += right->key; + value *= 3; + ret = (unsigned short) value; + break; + case XML_EXP_OR: + value = left->key; + value += right->key; + value *= 7; + ret = (unsigned short) value; + break; + case XML_EXP_COUNT: + value = left->key; + value += right->key; + ret = (unsigned short) value; + break; + default: + ret = 0; + } + return(ret); +} + + +static xmlExpNodePtr +xmlExpNewNode(xmlExpCtxtPtr ctxt, xmlExpNodeType type) { + xmlExpNodePtr ret; + + if (ctxt->nb_nodes >= MAX_NODES) + return(NULL); + ret = (xmlExpNodePtr) xmlMalloc(sizeof(xmlExpNode)); + if (ret == NULL) + return(NULL); + memset(ret, 0, sizeof(xmlExpNode)); + ret->type = type; + ret->next = NULL; + ctxt->nb_nodes++; + ctxt->nb_cons++; + return(ret); +} + +/** + * xmlExpHashGetEntry: + * @table: the hash table + * + * Get the unique entry from the hash table. The entry is created if + * needed. @left and @right are consumed, i.e. their ref count will + * be decremented by the operation. + * + * Returns the pointer or NULL in case of error + */ +static xmlExpNodePtr +xmlExpHashGetEntry(xmlExpCtxtPtr ctxt, xmlExpNodeType type, + xmlExpNodePtr left, xmlExpNodePtr right, + const xmlChar *name, int min, int max) { + unsigned short kbase, key; + xmlExpNodePtr entry; + xmlExpNodePtr insert; + + if (ctxt == NULL) + return(NULL); + + /* + * Check for duplicate and insertion location. + */ + if (type == XML_EXP_ATOM) { + kbase = xmlExpHashNameComputeKey(name); + } else if (type == XML_EXP_COUNT) { + /* COUNT reduction rule 1 */ + /* a{1} -> a */ + if (min == max) { + if (min == 1) { + return(left); + } + if (min == 0) { + xmlExpFree(ctxt, left); + return(emptyExp); + } + } + if (min < 0) { + xmlExpFree(ctxt, left); + return(forbiddenExp); + } + if (max == -1) + kbase = min + 79; + else + kbase = max - min; + kbase += left->key; + } else if (type == XML_EXP_OR) { + /* Forbid reduction rules */ + if (left->type == XML_EXP_FORBID) { + xmlExpFree(ctxt, left); + return(right); + } + if (right->type == XML_EXP_FORBID) { + xmlExpFree(ctxt, right); + return(left); + } + + /* OR reduction rule 1 */ + /* a | a reduced to a */ + if (left == right) { + left->ref--; + return(left); + } + /* OR canonicalization rule 1 */ + /* linearize (a | b) | c into a | (b | c) */ + if ((left->type == XML_EXP_OR) && (right->type != XML_EXP_OR)) { + xmlExpNodePtr tmp = left; + left = right; + right = tmp; + } + /* OR reduction rule 2 */ + /* a | (a | b) and b | (a | b) are reduced to a | b */ + if (right->type == XML_EXP_OR) { + if ((left == right->exp_left) || + (left == right->exp_right)) { + xmlExpFree(ctxt, left); + return(right); + } + } + /* OR canonicalization rule 2 */ + /* linearize (a | b) | c into a | (b | c) */ + if (left->type == XML_EXP_OR) { + xmlExpNodePtr tmp; + + /* OR canonicalization rule 2 */ + if ((left->exp_right->type != XML_EXP_OR) && + (left->exp_right->key < left->exp_left->key)) { + tmp = left->exp_right; + left->exp_right = left->exp_left; + left->exp_left = tmp; + } + left->exp_right->ref++; + tmp = xmlExpHashGetEntry(ctxt, XML_EXP_OR, left->exp_right, right, + NULL, 0, 0); + left->exp_left->ref++; + tmp = xmlExpHashGetEntry(ctxt, XML_EXP_OR, left->exp_left, tmp, + NULL, 0, 0); + + xmlExpFree(ctxt, left); + return(tmp); + } + if (right->type == XML_EXP_OR) { + /* Ordering in the tree */ + /* C | (A | B) -> A | (B | C) */ + if (left->key > right->exp_right->key) { + xmlExpNodePtr tmp; + right->exp_right->ref++; + tmp = xmlExpHashGetEntry(ctxt, XML_EXP_OR, right->exp_right, + left, NULL, 0, 0); + right->exp_left->ref++; + tmp = xmlExpHashGetEntry(ctxt, XML_EXP_OR, right->exp_left, + tmp, NULL, 0, 0); + xmlExpFree(ctxt, right); + return(tmp); + } + /* Ordering in the tree */ + /* B | (A | C) -> A | (B | C) */ + if (left->key > right->exp_left->key) { + xmlExpNodePtr tmp; + right->exp_right->ref++; + tmp = xmlExpHashGetEntry(ctxt, XML_EXP_OR, left, + right->exp_right, NULL, 0, 0); + right->exp_left->ref++; + tmp = xmlExpHashGetEntry(ctxt, XML_EXP_OR, right->exp_left, + tmp, NULL, 0, 0); + xmlExpFree(ctxt, right); + return(tmp); + } + } + /* we know both types are != XML_EXP_OR here */ + else if (left->key > right->key) { + xmlExpNodePtr tmp = left; + left = right; + right = tmp; + } + kbase = xmlExpHashComputeKey(type, left, right); + } else if (type == XML_EXP_SEQ) { + /* Forbid reduction rules */ + if (left->type == XML_EXP_FORBID) { + xmlExpFree(ctxt, right); + return(left); + } + if (right->type == XML_EXP_FORBID) { + xmlExpFree(ctxt, left); + return(right); + } + /* Empty reduction rules */ + if (right->type == XML_EXP_EMPTY) { + return(left); + } + if (left->type == XML_EXP_EMPTY) { + return(right); + } + kbase = xmlExpHashComputeKey(type, left, right); + } else + return(NULL); + + key = kbase % ctxt->size; + if (ctxt->table[key] != NULL) { + for (insert = ctxt->table[key]; insert != NULL; + insert = insert->next) { + if ((insert->key == kbase) && + (insert->type == type)) { + if (type == XML_EXP_ATOM) { + if (name == insert->exp_str) { + insert->ref++; + return(insert); + } + } else if (type == XML_EXP_COUNT) { + if ((insert->exp_min == min) && (insert->exp_max == max) && + (insert->exp_left == left)) { + insert->ref++; + left->ref--; + return(insert); + } + } else if ((insert->exp_left == left) && + (insert->exp_right == right)) { + insert->ref++; + left->ref--; + right->ref--; + return(insert); + } + } + } + } + + entry = xmlExpNewNode(ctxt, type); + if (entry == NULL) + return(NULL); + entry->key = kbase; + if (type == XML_EXP_ATOM) { + entry->exp_str = name; + entry->c_max = 1; + } else if (type == XML_EXP_COUNT) { + entry->exp_min = min; + entry->exp_max = max; + entry->exp_left = left; + if ((min == 0) || (IS_NILLABLE(left))) + entry->info |= XML_EXP_NILABLE; + if (max < 0) + entry->c_max = -1; + else + entry->c_max = max * entry->exp_left->c_max; + } else { + entry->exp_left = left; + entry->exp_right = right; + if (type == XML_EXP_OR) { + if ((IS_NILLABLE(left)) || (IS_NILLABLE(right))) + entry->info |= XML_EXP_NILABLE; + if ((entry->exp_left->c_max == -1) || + (entry->exp_right->c_max == -1)) + entry->c_max = -1; + else if (entry->exp_left->c_max > entry->exp_right->c_max) + entry->c_max = entry->exp_left->c_max; + else + entry->c_max = entry->exp_right->c_max; + } else { + if ((IS_NILLABLE(left)) && (IS_NILLABLE(right))) + entry->info |= XML_EXP_NILABLE; + if ((entry->exp_left->c_max == -1) || + (entry->exp_right->c_max == -1)) + entry->c_max = -1; + else + entry->c_max = entry->exp_left->c_max + entry->exp_right->c_max; + } + } + entry->ref = 1; + if (ctxt->table[key] != NULL) + entry->next = ctxt->table[key]; + + ctxt->table[key] = entry; + ctxt->nbElems++; + + return(entry); +} + +/** + * xmlExpFree: + * @ctxt: the expression context + * @exp: the expression + * + * Dereference the expression + */ +void +xmlExpFree(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp) { + if ((exp == NULL) || (exp == forbiddenExp) || (exp == emptyExp)) + return; + exp->ref--; + if (exp->ref == 0) { + unsigned short key; + + /* Unlink it first from the hash table */ + key = exp->key % ctxt->size; + if (ctxt->table[key] == exp) { + ctxt->table[key] = exp->next; + } else { + xmlExpNodePtr tmp; + + tmp = ctxt->table[key]; + while (tmp != NULL) { + if (tmp->next == exp) { + tmp->next = exp->next; + break; + } + tmp = tmp->next; + } + } + + if ((exp->type == XML_EXP_SEQ) || (exp->type == XML_EXP_OR)) { + xmlExpFree(ctxt, exp->exp_left); + xmlExpFree(ctxt, exp->exp_right); + } else if (exp->type == XML_EXP_COUNT) { + xmlExpFree(ctxt, exp->exp_left); + } + xmlFree(exp); + ctxt->nb_nodes--; + } +} + +/** + * xmlExpRef: + * @exp: the expression + * + * Increase the reference count of the expression + */ +void +xmlExpRef(xmlExpNodePtr exp) { + if (exp != NULL) + exp->ref++; +} + +/** + * xmlExpNewAtom: + * @ctxt: the expression context + * @name: the atom name + * @len: the atom name lenght in byte (or -1); + * + * Get the atom associated to this name from that context + * + * Returns the node or NULL in case of error + */ +xmlExpNodePtr +xmlExpNewAtom(xmlExpCtxtPtr ctxt, const xmlChar *name, int len) { + if ((ctxt == NULL) || (name == NULL)) + return(NULL); + name = xmlDictLookup(ctxt->dict, name, len); + if (name == NULL) + return(NULL); + return(xmlExpHashGetEntry(ctxt, XML_EXP_ATOM, NULL, NULL, name, 0, 0)); +} + +/** + * xmlExpNewOr: + * @ctxt: the expression context + * @left: left expression + * @right: right expression + * + * Get the atom associated to the choice @left | @right + * Note that @left and @right are consumed in the operation, to keep + * an handle on them use xmlExpRef() and use xmlExpFree() to release them, + * this is true even in case of failure (unless ctxt == NULL). + * + * Returns the node or NULL in case of error + */ +xmlExpNodePtr +xmlExpNewOr(xmlExpCtxtPtr ctxt, xmlExpNodePtr left, xmlExpNodePtr right) { + if (ctxt == NULL) + return(NULL); + if ((left == NULL) || (right == NULL)) { + xmlExpFree(ctxt, left); + xmlExpFree(ctxt, right); + return(NULL); + } + return(xmlExpHashGetEntry(ctxt, XML_EXP_OR, left, right, NULL, 0, 0)); +} + +/** + * xmlExpNewSeq: + * @ctxt: the expression context + * @left: left expression + * @right: right expression + * + * Get the atom associated to the sequence @left , @right + * Note that @left and @right are consumed in the operation, to keep + * an handle on them use xmlExpRef() and use xmlExpFree() to release them, + * this is true even in case of failure (unless ctxt == NULL). + * + * Returns the node or NULL in case of error + */ +xmlExpNodePtr +xmlExpNewSeq(xmlExpCtxtPtr ctxt, xmlExpNodePtr left, xmlExpNodePtr right) { + if (ctxt == NULL) + return(NULL); + if ((left == NULL) || (right == NULL)) { + xmlExpFree(ctxt, left); + xmlExpFree(ctxt, right); + return(NULL); + } + return(xmlExpHashGetEntry(ctxt, XML_EXP_SEQ, left, right, NULL, 0, 0)); +} + +/** + * xmlExpNewRange: + * @ctxt: the expression context + * @subset: the expression to be repeated + * @min: the lower bound for the repetition + * @max: the upper bound for the repetition, -1 means infinite + * + * Get the atom associated to the range (@subset){@min, @max} + * Note that @subset is consumed in the operation, to keep + * an handle on it use xmlExpRef() and use xmlExpFree() to release it, + * this is true even in case of failure (unless ctxt == NULL). + * + * Returns the node or NULL in case of error + */ +xmlExpNodePtr +xmlExpNewRange(xmlExpCtxtPtr ctxt, xmlExpNodePtr subset, int min, int max) { + if (ctxt == NULL) + return(NULL); + if ((subset == NULL) || (min < 0) || (max < -1) || + ((max >= 0) && (min > max))) { + xmlExpFree(ctxt, subset); + return(NULL); + } + return(xmlExpHashGetEntry(ctxt, XML_EXP_COUNT, subset, + NULL, NULL, min, max)); +} + +/************************************************************************ + * * + * Public API for operations on expressions * + * * + ************************************************************************/ + +static int +xmlExpGetLanguageInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, + const xmlChar**list, int len, int nb) { + int tmp, tmp2; +tail: + switch (exp->type) { + case XML_EXP_EMPTY: + return(0); + case XML_EXP_ATOM: + for (tmp = 0;tmp < nb;tmp++) + if (list[tmp] == exp->exp_str) + return(0); + if (nb >= len) + return(-2); + list[nb++] = exp->exp_str; + return(1); + case XML_EXP_COUNT: + exp = exp->exp_left; + goto tail; + case XML_EXP_SEQ: + case XML_EXP_OR: + tmp = xmlExpGetLanguageInt(ctxt, exp->exp_left, list, len, nb); + if (tmp < 0) + return(tmp); + tmp2 = xmlExpGetLanguageInt(ctxt, exp->exp_right, list, len, + nb + tmp); + if (tmp2 < 0) + return(tmp2); + return(tmp + tmp2); + } + return(-1); +} + +/** + * xmlExpGetLanguage: + * @ctxt: the expression context + * @exp: the expression + * @langList: where to store the tokens + * @len: the allocated lenght of @list + * + * Find all the strings used in @exp and store them in @list + * + * Returns the number of unique strings found, -1 in case of errors and + * -2 if there is more than @len strings + */ +int +xmlExpGetLanguage(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, + const xmlChar**langList, int len) { + if ((ctxt == NULL) || (exp == NULL) || (langList == NULL) || (len <= 0)) + return(-1); + return(xmlExpGetLanguageInt(ctxt, exp, langList, len, 0)); +} + +static int +xmlExpGetStartInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, + const xmlChar**list, int len, int nb) { + int tmp, tmp2; +tail: + switch (exp->type) { + case XML_EXP_FORBID: + return(0); + case XML_EXP_EMPTY: + return(0); + case XML_EXP_ATOM: + for (tmp = 0;tmp < nb;tmp++) + if (list[tmp] == exp->exp_str) + return(0); + if (nb >= len) + return(-2); + list[nb++] = exp->exp_str; + return(1); + case XML_EXP_COUNT: + exp = exp->exp_left; + goto tail; + case XML_EXP_SEQ: + tmp = xmlExpGetStartInt(ctxt, exp->exp_left, list, len, nb); + if (tmp < 0) + return(tmp); + if (IS_NILLABLE(exp->exp_left)) { + tmp2 = xmlExpGetStartInt(ctxt, exp->exp_right, list, len, + nb + tmp); + if (tmp2 < 0) + return(tmp2); + tmp += tmp2; + } + return(tmp); + case XML_EXP_OR: + tmp = xmlExpGetStartInt(ctxt, exp->exp_left, list, len, nb); + if (tmp < 0) + return(tmp); + tmp2 = xmlExpGetStartInt(ctxt, exp->exp_right, list, len, + nb + tmp); + if (tmp2 < 0) + return(tmp2); + return(tmp + tmp2); + } + return(-1); +} + +/** + * xmlExpGetStart: + * @ctxt: the expression context + * @exp: the expression + * @tokList: where to store the tokens + * @len: the allocated lenght of @list + * + * Find all the strings that appears at the start of the languages + * accepted by @exp and store them in @list. E.g. for (a, b) | c + * it will return the list [a, c] + * + * Returns the number of unique strings found, -1 in case of errors and + * -2 if there is more than @len strings + */ +int +xmlExpGetStart(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, + const xmlChar**tokList, int len) { + if ((ctxt == NULL) || (exp == NULL) || (tokList == NULL) || (len <= 0)) + return(-1); + return(xmlExpGetStartInt(ctxt, exp, tokList, len, 0)); +} + +/** + * xmlExpIsNillable: + * @exp: the expression + * + * Finds if the expression is nillable, i.e. if it accepts the empty sequqnce + * + * Returns 1 if nillable, 0 if not and -1 in case of error + */ +int +xmlExpIsNillable(xmlExpNodePtr exp) { + if (exp == NULL) + return(-1); + return(IS_NILLABLE(exp) != 0); +} + +static xmlExpNodePtr +xmlExpStringDeriveInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, const xmlChar *str) +{ + xmlExpNodePtr ret; + + switch (exp->type) { + case XML_EXP_EMPTY: + return(forbiddenExp); + case XML_EXP_FORBID: + return(forbiddenExp); + case XML_EXP_ATOM: + if (exp->exp_str == str) { +#ifdef DEBUG_DERIV + printf("deriv atom: equal => Empty\n"); +#endif + ret = emptyExp; + } else { +#ifdef DEBUG_DERIV + printf("deriv atom: mismatch => forbid\n"); +#endif + /* TODO wildcards here */ + ret = forbiddenExp; + } + return(ret); + case XML_EXP_OR: { + xmlExpNodePtr tmp; + +#ifdef DEBUG_DERIV + printf("deriv or: => or(derivs)\n"); +#endif + tmp = xmlExpStringDeriveInt(ctxt, exp->exp_left, str); + if (tmp == NULL) { + return(NULL); + } + ret = xmlExpStringDeriveInt(ctxt, exp->exp_right, str); + if (ret == NULL) { + xmlExpFree(ctxt, tmp); + return(NULL); + } + ret = xmlExpHashGetEntry(ctxt, XML_EXP_OR, tmp, ret, + NULL, 0, 0); + return(ret); + } + case XML_EXP_SEQ: +#ifdef DEBUG_DERIV + printf("deriv seq: starting with left\n"); +#endif + ret = xmlExpStringDeriveInt(ctxt, exp->exp_left, str); + if (ret == NULL) { + return(NULL); + } else if (ret == forbiddenExp) { + if (IS_NILLABLE(exp->exp_left)) { +#ifdef DEBUG_DERIV + printf("deriv seq: left failed but nillable\n"); +#endif + ret = xmlExpStringDeriveInt(ctxt, exp->exp_right, str); + } + } else { +#ifdef DEBUG_DERIV + printf("deriv seq: left match => sequence\n"); +#endif + exp->exp_right->ref++; + ret = xmlExpHashGetEntry(ctxt, XML_EXP_SEQ, ret, exp->exp_right, + NULL, 0, 0); + } + return(ret); + case XML_EXP_COUNT: { + int min, max; + xmlExpNodePtr tmp; + + if (exp->exp_max == 0) + return(forbiddenExp); + ret = xmlExpStringDeriveInt(ctxt, exp->exp_left, str); + if (ret == NULL) + return(NULL); + if (ret == forbiddenExp) { +#ifdef DEBUG_DERIV + printf("deriv count: pattern mismatch => forbid\n"); +#endif + return(ret); + } + if (exp->exp_max == 1) + return(ret); + if (exp->exp_max < 0) /* unbounded */ + max = -1; + else + max = exp->exp_max - 1; + if (exp->exp_min > 0) + min = exp->exp_min - 1; + else + min = 0; + exp->exp_left->ref++; + tmp = xmlExpHashGetEntry(ctxt, XML_EXP_COUNT, exp->exp_left, NULL, + NULL, min, max); + if (ret == emptyExp) { +#ifdef DEBUG_DERIV + printf("deriv count: match to empty => new count\n"); +#endif + return(tmp); + } +#ifdef DEBUG_DERIV + printf("deriv count: match => sequence with new count\n"); +#endif + return(xmlExpHashGetEntry(ctxt, XML_EXP_SEQ, ret, tmp, + NULL, 0, 0)); + } + } + return(NULL); +} + +/** + * xmlExpStringDerive: + * @ctxt: the expression context + * @exp: the expression + * @str: the string + * @len: the string len in bytes if available + * + * Do one step of Brzozowski derivation of the expression @exp with + * respect to the input string + * + * Returns the resulting expression or NULL in case of internal error + */ +xmlExpNodePtr +xmlExpStringDerive(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, + const xmlChar *str, int len) { + const xmlChar *input; + + if ((exp == NULL) || (ctxt == NULL) || (str == NULL)) { + return(NULL); + } + /* + * check the string is in the dictionnary, if yes use an interned + * copy, otherwise we know it's not an acceptable input + */ + input = xmlDictExists(ctxt->dict, str, len); + if (input == NULL) { + return(forbiddenExp); + } + return(xmlExpStringDeriveInt(ctxt, exp, input)); +} + +static int +xmlExpCheckCard(xmlExpNodePtr exp, xmlExpNodePtr sub) { + int ret = 1; + + if (sub->c_max == -1) { + if (exp->c_max != -1) + ret = 0; + } else if ((exp->c_max >= 0) && (exp->c_max < sub->c_max)) { + ret = 0; + } +#if 0 + if ((IS_NILLABLE(sub)) && (!IS_NILLABLE(exp))) + ret = 0; +#endif + return(ret); +} + +static xmlExpNodePtr xmlExpExpDeriveInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, + xmlExpNodePtr sub); +/** + * xmlExpDivide: + * @ctxt: the expressions context + * @exp: the englobing expression + * @sub: the subexpression + * @mult: the multiple expression + * @remain: the remain from the derivation of the multiple + * + * Check if exp is a multiple of sub, i.e. if there is a finite number n + * so that sub{n} subsume exp + * + * Returns the multiple value if successful, 0 if it is not a multiple + * and -1 in case of internel error. + */ + +static int +xmlExpDivide(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, xmlExpNodePtr sub, + xmlExpNodePtr *mult, xmlExpNodePtr *remain) { + int i; + xmlExpNodePtr tmp, tmp2; + + if (mult != NULL) *mult = NULL; + if (remain != NULL) *remain = NULL; + if (exp->c_max == -1) return(0); + if (IS_NILLABLE(exp) && (!IS_NILLABLE(sub))) return(0); + + for (i = 1;i <= exp->c_max;i++) { + sub->ref++; + tmp = xmlExpHashGetEntry(ctxt, XML_EXP_COUNT, + sub, NULL, NULL, i, i); + if (tmp == NULL) { + return(-1); + } + if (!xmlExpCheckCard(tmp, exp)) { + xmlExpFree(ctxt, tmp); + continue; + } + tmp2 = xmlExpExpDeriveInt(ctxt, tmp, exp); + if (tmp2 == NULL) { + xmlExpFree(ctxt, tmp); + return(-1); + } + if ((tmp2 != forbiddenExp) && (IS_NILLABLE(tmp2))) { + if (remain != NULL) + *remain = tmp2; + else + xmlExpFree(ctxt, tmp2); + if (mult != NULL) + *mult = tmp; + else + xmlExpFree(ctxt, tmp); +#ifdef DEBUG_DERIV + printf("Divide succeeded %d\n", i); +#endif + return(i); + } + xmlExpFree(ctxt, tmp); + xmlExpFree(ctxt, tmp2); + } +#ifdef DEBUG_DERIV + printf("Divide failed\n"); +#endif + return(0); +} + +/** + * xmlExpExpDeriveInt: + * @ctxt: the expressions context + * @exp: the englobing expression + * @sub: the subexpression + * + * Try to do a step of Brzozowski derivation but at a higher level + * the input being a subexpression. + * + * Returns the resulting expression or NULL in case of internal error + */ +static xmlExpNodePtr +xmlExpExpDeriveInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, xmlExpNodePtr sub) { + xmlExpNodePtr ret, tmp, tmp2, tmp3; + const xmlChar **tab; + int len, i; + + /* + * In case of equality and if the expression can only consume a finite + * amount, then the derivation is empty + */ + if ((exp == sub) && (exp->c_max >= 0)) { +#ifdef DEBUG_DERIV + printf("Equal(exp, sub) and finite -> Empty\n"); +#endif + return(emptyExp); + } + /* + * decompose sub sequence first + */ + if (sub->type == XML_EXP_EMPTY) { +#ifdef DEBUG_DERIV + printf("Empty(sub) -> Empty\n"); +#endif + exp->ref++; + return(exp); + } + if (sub->type == XML_EXP_SEQ) { +#ifdef DEBUG_DERIV + printf("Seq(sub) -> decompose\n"); +#endif + tmp = xmlExpExpDeriveInt(ctxt, exp, sub->exp_left); + if (tmp == NULL) + return(NULL); + if (tmp == forbiddenExp) + return(tmp); + ret = xmlExpExpDeriveInt(ctxt, tmp, sub->exp_right); + xmlExpFree(ctxt, tmp); + return(ret); + } + if (sub->type == XML_EXP_OR) { +#ifdef DEBUG_DERIV + printf("Or(sub) -> decompose\n"); +#endif + tmp = xmlExpExpDeriveInt(ctxt, exp, sub->exp_left); + if (tmp == forbiddenExp) + return(tmp); + if (tmp == NULL) + return(NULL); + ret = xmlExpExpDeriveInt(ctxt, exp, sub->exp_right); + if ((ret == NULL) || (ret == forbiddenExp)) { + xmlExpFree(ctxt, tmp); + return(ret); + } + return(xmlExpHashGetEntry(ctxt, XML_EXP_OR, tmp, ret, NULL, 0, 0)); + } + if (!xmlExpCheckCard(exp, sub)) { +#ifdef DEBUG_DERIV + printf("CheckCard(exp, sub) failed -> Forbid\n"); +#endif + return(forbiddenExp); + } + switch (exp->type) { + case XML_EXP_EMPTY: + if (sub == emptyExp) + return(emptyExp); +#ifdef DEBUG_DERIV + printf("Empty(exp) -> Forbid\n"); +#endif + return(forbiddenExp); + case XML_EXP_FORBID: +#ifdef DEBUG_DERIV + printf("Forbid(exp) -> Forbid\n"); +#endif + return(forbiddenExp); + case XML_EXP_ATOM: + if (sub->type == XML_EXP_ATOM) { + /* TODO: handle wildcards */ + if (exp->exp_str == sub->exp_str) { +#ifdef DEBUG_DERIV + printf("Atom match -> Empty\n"); +#endif + return(emptyExp); + } +#ifdef DEBUG_DERIV + printf("Atom mismatch -> Forbid\n"); +#endif + return(forbiddenExp); + } + if ((sub->type == XML_EXP_COUNT) && + (sub->exp_max == 1) && + (sub->exp_left->type == XML_EXP_ATOM)) { + /* TODO: handle wildcards */ + if (exp->exp_str == sub->exp_left->exp_str) { +#ifdef DEBUG_DERIV + printf("Atom match -> Empty\n"); +#endif + return(emptyExp); + } +#ifdef DEBUG_DERIV + printf("Atom mismatch -> Forbid\n"); +#endif + return(forbiddenExp); + } +#ifdef DEBUG_DERIV + printf("Compex exp vs Atom -> Forbid\n"); +#endif + return(forbiddenExp); + case XML_EXP_SEQ: + /* try to get the sequence consumed only if possible */ + if (xmlExpCheckCard(exp->exp_left, sub)) { + /* See if the sequence can be consumed directly */ +#ifdef DEBUG_DERIV + printf("Seq trying left only\n"); +#endif + ret = xmlExpExpDeriveInt(ctxt, exp->exp_left, sub); + if ((ret != forbiddenExp) && (ret != NULL)) { +#ifdef DEBUG_DERIV + printf("Seq trying left only worked\n"); +#endif + /* + * TODO: assumption here that we are determinist + * i.e. we won't get to a nillable exp left + * subset which could be matched by the right + * part too. + * e.g.: (a | b)+,(a | c) and 'a+,a' + */ + exp->exp_right->ref++; + return(xmlExpHashGetEntry(ctxt, XML_EXP_SEQ, ret, + exp->exp_right, NULL, 0, 0)); + } +#ifdef DEBUG_DERIV + } else { + printf("Seq: left too short\n"); +#endif + } + /* Try instead to decompose */ + if (sub->type == XML_EXP_COUNT) { + int min, max; + +#ifdef DEBUG_DERIV + printf("Seq: sub is a count\n"); +#endif + ret = xmlExpExpDeriveInt(ctxt, exp->exp_left, sub->exp_left); + if (ret == NULL) + return(NULL); + if (ret != forbiddenExp) { +#ifdef DEBUG_DERIV + printf("Seq , Count match on left\n"); +#endif + if (sub->exp_max < 0) + max = -1; + else + max = sub->exp_max -1; + if (sub->exp_min > 0) + min = sub->exp_min -1; + else + min = 0; + exp->exp_right->ref++; + tmp = xmlExpHashGetEntry(ctxt, XML_EXP_SEQ, ret, + exp->exp_right, NULL, 0, 0); + if (tmp == NULL) + return(NULL); + + sub->exp_left->ref++; + tmp2 = xmlExpHashGetEntry(ctxt, XML_EXP_COUNT, + sub->exp_left, NULL, NULL, min, max); + if (tmp2 == NULL) { + xmlExpFree(ctxt, tmp); + return(NULL); + } + ret = xmlExpExpDeriveInt(ctxt, tmp, tmp2); + xmlExpFree(ctxt, tmp); + xmlExpFree(ctxt, tmp2); + return(ret); + } + } + /* we made no progress on structured operations */ + break; + case XML_EXP_OR: +#ifdef DEBUG_DERIV + printf("Or , trying both side\n"); +#endif + ret = xmlExpExpDeriveInt(ctxt, exp->exp_left, sub); + if (ret == NULL) + return(NULL); + tmp = xmlExpExpDeriveInt(ctxt, exp->exp_right, sub); + if (tmp == NULL) { + xmlExpFree(ctxt, ret); + return(NULL); + } + return(xmlExpHashGetEntry(ctxt, XML_EXP_OR, ret, tmp, NULL, 0, 0)); + case XML_EXP_COUNT: { + int min, max; + + if (sub->type == XML_EXP_COUNT) { + /* + * Try to see if the loop is completely subsumed + */ + tmp = xmlExpExpDeriveInt(ctxt, exp->exp_left, sub->exp_left); + if (tmp == NULL) + return(NULL); + if (tmp == forbiddenExp) { + int mult; + +#ifdef DEBUG_DERIV + printf("Count, Count inner don't subsume\n"); +#endif + mult = xmlExpDivide(ctxt, sub->exp_left, exp->exp_left, + NULL, &tmp); + if (mult <= 0) { +#ifdef DEBUG_DERIV + printf("Count, Count not multiple => forbidden\n"); +#endif + return(forbiddenExp); + } + if (sub->exp_max == -1) { + max = -1; + if (exp->exp_max == -1) { + if (exp->exp_min <= sub->exp_min * mult) + min = 0; + else + min = exp->exp_min - sub->exp_min * mult; + } else { +#ifdef DEBUG_DERIV + printf("Count, Count finite can't subsume infinite\n"); +#endif + xmlExpFree(ctxt, tmp); + return(forbiddenExp); + } + } else { + if (exp->exp_max == -1) { +#ifdef DEBUG_DERIV + printf("Infinite loop consume mult finite loop\n"); +#endif + if (exp->exp_min > sub->exp_min * mult) { + max = -1; + min = exp->exp_min - sub->exp_min * mult; + } else { + max = -1; + min = 0; + } + } else { + if (exp->exp_max < sub->exp_max * mult) { +#ifdef DEBUG_DERIV + printf("loops max mult mismatch => forbidden\n"); +#endif + xmlExpFree(ctxt, tmp); + return(forbiddenExp); + } + if (sub->exp_max * mult > exp->exp_min) + min = 0; + else + min = exp->exp_min - sub->exp_max * mult; + max = exp->exp_max - sub->exp_max * mult; + } + } + } else if (!IS_NILLABLE(tmp)) { + /* + * TODO: loop here to try to grow if working on finite + * blocks. + */ +#ifdef DEBUG_DERIV + printf("Count, Count remain not nillable => forbidden\n"); +#endif + xmlExpFree(ctxt, tmp); + return(forbiddenExp); + } else if (sub->exp_max == -1) { + if (exp->exp_max == -1) { + if (exp->exp_min <= sub->exp_min) { +#ifdef DEBUG_DERIV + printf("Infinite loops Okay => COUNT(0,Inf)\n"); +#endif + max = -1; + min = 0; + } else { +#ifdef DEBUG_DERIV + printf("Infinite loops min => Count(X,Inf)\n"); +#endif + max = -1; + min = exp->exp_min - sub->exp_min; + } + } else if (exp->exp_min > sub->exp_min) { +#ifdef DEBUG_DERIV + printf("loops min mismatch 1 => forbidden ???\n"); +#endif + xmlExpFree(ctxt, tmp); + return(forbiddenExp); + } else { + max = -1; + min = 0; + } + } else { + if (exp->exp_max == -1) { +#ifdef DEBUG_DERIV + printf("Infinite loop consume finite loop\n"); +#endif + if (exp->exp_min > sub->exp_min) { + max = -1; + min = exp->exp_min - sub->exp_min; + } else { + max = -1; + min = 0; + } + } else { + if (exp->exp_max < sub->exp_max) { +#ifdef DEBUG_DERIV + printf("loops max mismatch => forbidden\n"); +#endif + xmlExpFree(ctxt, tmp); + return(forbiddenExp); + } + if (sub->exp_max > exp->exp_min) + min = 0; + else + min = exp->exp_min - sub->exp_max; + max = exp->exp_max - sub->exp_max; + } + } +#ifdef DEBUG_DERIV + printf("loops match => SEQ(COUNT())\n"); +#endif + exp->exp_left->ref++; + tmp2 = xmlExpHashGetEntry(ctxt, XML_EXP_COUNT, exp->exp_left, + NULL, NULL, min, max); + if (tmp2 == NULL) { + return(NULL); + } + ret = xmlExpHashGetEntry(ctxt, XML_EXP_SEQ, tmp, tmp2, + NULL, 0, 0); + return(ret); + } + tmp = xmlExpExpDeriveInt(ctxt, exp->exp_left, sub); + if (tmp == NULL) + return(NULL); + if (tmp == forbiddenExp) { +#ifdef DEBUG_DERIV + printf("loop mismatch => forbidden\n"); +#endif + return(forbiddenExp); + } + if (exp->exp_min > 0) + min = exp->exp_min - 1; + else + min = 0; + if (exp->exp_max < 0) + max = -1; + else + max = exp->exp_max - 1; + +#ifdef DEBUG_DERIV + printf("loop match => SEQ(COUNT())\n"); +#endif + exp->exp_left->ref++; + tmp2 = xmlExpHashGetEntry(ctxt, XML_EXP_COUNT, exp->exp_left, + NULL, NULL, min, max); + if (tmp2 == NULL) + return(NULL); + ret = xmlExpHashGetEntry(ctxt, XML_EXP_SEQ, tmp, tmp2, + NULL, 0, 0); + return(ret); + } + } + +#ifdef DEBUG_DERIV + printf("Fallback to derivative\n"); +#endif + if (IS_NILLABLE(sub)) { + if (!(IS_NILLABLE(exp))) + return(forbiddenExp); + else + ret = emptyExp; + } else + ret = NULL; + /* + * here the structured derivation made no progress so + * we use the default token based derivation to force one more step + */ + if (ctxt->tabSize == 0) + ctxt->tabSize = 40; + + tab = (const xmlChar **) xmlMalloc(ctxt->tabSize * + sizeof(const xmlChar *)); + if (tab == NULL) { + return(NULL); + } + + /* + * collect all the strings accepted by the subexpression on input + */ + len = xmlExpGetStartInt(ctxt, sub, tab, ctxt->tabSize, 0); + while (len < 0) { + const xmlChar **temp; + temp = (const xmlChar **) xmlRealloc((xmlChar **) tab, ctxt->tabSize * 2 * + sizeof(const xmlChar *)); + if (temp == NULL) { + xmlFree((xmlChar **) tab); + return(NULL); + } + tab = temp; + ctxt->tabSize *= 2; + len = xmlExpGetStartInt(ctxt, sub, tab, ctxt->tabSize, 0); + } + for (i = 0;i < len;i++) { + tmp = xmlExpStringDeriveInt(ctxt, exp, tab[i]); + if ((tmp == NULL) || (tmp == forbiddenExp)) { + xmlExpFree(ctxt, ret); + xmlFree((xmlChar **) tab); + return(tmp); + } + tmp2 = xmlExpStringDeriveInt(ctxt, sub, tab[i]); + if ((tmp2 == NULL) || (tmp2 == forbiddenExp)) { + xmlExpFree(ctxt, tmp); + xmlExpFree(ctxt, ret); + xmlFree((xmlChar **) tab); + return(tmp); + } + tmp3 = xmlExpExpDeriveInt(ctxt, tmp, tmp2); + xmlExpFree(ctxt, tmp); + xmlExpFree(ctxt, tmp2); + + if ((tmp3 == NULL) || (tmp3 == forbiddenExp)) { + xmlExpFree(ctxt, ret); + xmlFree((xmlChar **) tab); + return(tmp3); + } + + if (ret == NULL) + ret = tmp3; + else { + ret = xmlExpHashGetEntry(ctxt, XML_EXP_OR, ret, tmp3, NULL, 0, 0); + if (ret == NULL) { + xmlFree((xmlChar **) tab); + return(NULL); + } + } + } + xmlFree((xmlChar **) tab); + return(ret); +} + +/** + * xmlExpExpDerive: + * @ctxt: the expressions context + * @exp: the englobing expression + * @sub: the subexpression + * + * Evaluates the expression resulting from @exp consuming a sub expression @sub + * Based on algebraic derivation and sometimes direct Brzozowski derivation + * it usually tatkes less than linear time and can handle expressions generating + * infinite languages. + * + * Returns the resulting expression or NULL in case of internal error, the + * result must be freed + */ +xmlExpNodePtr +xmlExpExpDerive(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, xmlExpNodePtr sub) { + if ((exp == NULL) || (ctxt == NULL) || (sub == NULL)) + return(NULL); + + /* + * O(1) speedups + */ + if (IS_NILLABLE(sub) && (!IS_NILLABLE(exp))) { +#ifdef DEBUG_DERIV + printf("Sub nillable and not exp : can't subsume\n"); +#endif + return(forbiddenExp); + } + if (xmlExpCheckCard(exp, sub) == 0) { +#ifdef DEBUG_DERIV + printf("sub generate longuer sequances than exp : can't subsume\n"); +#endif + return(forbiddenExp); + } + return(xmlExpExpDeriveInt(ctxt, exp, sub)); +} + +/** + * xmlExpSubsume: + * @ctxt: the expressions context + * @exp: the englobing expression + * @sub: the subexpression + * + * Check whether @exp accepts all the languages accexpted by @sub + * the input being a subexpression. + * + * Returns 1 if true 0 if false and -1 in case of failure. + */ +int +xmlExpSubsume(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, xmlExpNodePtr sub) { + xmlExpNodePtr tmp; + + if ((exp == NULL) || (ctxt == NULL) || (sub == NULL)) + return(-1); + + /* + * TODO: speedup by checking the language of sub is a subset of the + * language of exp + */ + /* + * O(1) speedups + */ + if (IS_NILLABLE(sub) && (!IS_NILLABLE(exp))) { +#ifdef DEBUG_DERIV + printf("Sub nillable and not exp : can't subsume\n"); +#endif + return(0); + } + if (xmlExpCheckCard(exp, sub) == 0) { +#ifdef DEBUG_DERIV + printf("sub generate longuer sequances than exp : can't subsume\n"); +#endif + return(0); + } + tmp = xmlExpExpDeriveInt(ctxt, exp, sub); +#ifdef DEBUG_DERIV + printf("Result derivation :\n"); + PRINT_EXP(tmp); +#endif + if (tmp == NULL) + return(-1); + if (tmp == forbiddenExp) + return(0); + if (tmp == emptyExp) + return(1); + if ((tmp != NULL) && (IS_NILLABLE(tmp))) { + xmlExpFree(ctxt, tmp); + return(1); + } + xmlExpFree(ctxt, tmp); + return(0); +} + +/************************************************************************ + * * + * Parsing expression * + * * + ************************************************************************/ + +static xmlExpNodePtr xmlExpParseExpr(xmlExpCtxtPtr ctxt); + +#undef CUR +#define CUR (*ctxt->cur) +#undef NEXT +#define NEXT ctxt->cur++; +#undef IS_BLANK +#define IS_BLANK(c) ((c == ' ') || (c == '\n') || (c == '\r') || (c == '\t')) +#define SKIP_BLANKS while (IS_BLANK(*ctxt->cur)) ctxt->cur++; + +static int +xmlExpParseNumber(xmlExpCtxtPtr ctxt) { + int ret = 0; + + SKIP_BLANKS + if (CUR == '*') { + NEXT + return(-1); + } + if ((CUR < '0') || (CUR > '9')) + return(-1); + while ((CUR >= '0') && (CUR <= '9')) { + ret = ret * 10 + (CUR - '0'); + NEXT + } + return(ret); +} + +static xmlExpNodePtr +xmlExpParseOr(xmlExpCtxtPtr ctxt) { + const char *base; + xmlExpNodePtr ret; + const xmlChar *val; + + SKIP_BLANKS + base = ctxt->cur; + if (*ctxt->cur == '(') { + NEXT + ret = xmlExpParseExpr(ctxt); + SKIP_BLANKS + if (*ctxt->cur != ')') { + fprintf(stderr, "unbalanced '(' : %s\n", base); + xmlExpFree(ctxt, ret); + return(NULL); + } + NEXT; + SKIP_BLANKS + goto parse_quantifier; + } + while ((CUR != 0) && (!(IS_BLANK(CUR))) && (CUR != '(') && + (CUR != ')') && (CUR != '|') && (CUR != ',') && (CUR != '{') && + (CUR != '*') && (CUR != '+') && (CUR != '?') && (CUR != '}')) + NEXT; + val = xmlDictLookup(ctxt->dict, BAD_CAST base, ctxt->cur - base); + if (val == NULL) + return(NULL); + ret = xmlExpHashGetEntry(ctxt, XML_EXP_ATOM, NULL, NULL, val, 0, 0); + if (ret == NULL) + return(NULL); + SKIP_BLANKS +parse_quantifier: + if (CUR == '{') { + int min, max; + + NEXT + min = xmlExpParseNumber(ctxt); + if (min < 0) { + xmlExpFree(ctxt, ret); + return(NULL); + } + SKIP_BLANKS + if (CUR == ',') { + NEXT + max = xmlExpParseNumber(ctxt); + SKIP_BLANKS + } else + max = min; + if (CUR != '}') { + xmlExpFree(ctxt, ret); + return(NULL); + } + NEXT + ret = xmlExpHashGetEntry(ctxt, XML_EXP_COUNT, ret, NULL, NULL, + min, max); + SKIP_BLANKS + } else if (CUR == '?') { + NEXT + ret = xmlExpHashGetEntry(ctxt, XML_EXP_COUNT, ret, NULL, NULL, + 0, 1); + SKIP_BLANKS + } else if (CUR == '+') { + NEXT + ret = xmlExpHashGetEntry(ctxt, XML_EXP_COUNT, ret, NULL, NULL, + 1, -1); + SKIP_BLANKS + } else if (CUR == '*') { + NEXT + ret = xmlExpHashGetEntry(ctxt, XML_EXP_COUNT, ret, NULL, NULL, + 0, -1); + SKIP_BLANKS + } + return(ret); +} + + +static xmlExpNodePtr +xmlExpParseSeq(xmlExpCtxtPtr ctxt) { + xmlExpNodePtr ret, right; + + ret = xmlExpParseOr(ctxt); + SKIP_BLANKS + while (CUR == '|') { + NEXT + right = xmlExpParseOr(ctxt); + if (right == NULL) { + xmlExpFree(ctxt, ret); + return(NULL); + } + ret = xmlExpHashGetEntry(ctxt, XML_EXP_OR, ret, right, NULL, 0, 0); + if (ret == NULL) + return(NULL); + } + return(ret); +} + +static xmlExpNodePtr +xmlExpParseExpr(xmlExpCtxtPtr ctxt) { + xmlExpNodePtr ret, right; + + ret = xmlExpParseSeq(ctxt); + SKIP_BLANKS + while (CUR == ',') { + NEXT + right = xmlExpParseSeq(ctxt); + if (right == NULL) { + xmlExpFree(ctxt, ret); + return(NULL); + } + ret = xmlExpHashGetEntry(ctxt, XML_EXP_SEQ, ret, right, NULL, 0, 0); + if (ret == NULL) + return(NULL); + } + return(ret); +} + +/** + * xmlExpParse: + * @ctxt: the expressions context + * @expr: the 0 terminated string + * + * Minimal parser for regexps, it understand the following constructs + * - string terminals + * - choice operator | + * - sequence operator , + * - subexpressions (...) + * - usual cardinality operators + * and ? + * - finite sequences { min, max } + * - infinite sequences { min, * } + * There is minimal checkings made especially no checking on strings values + * + * Returns a new expression or NULL in case of failure + */ +xmlExpNodePtr +xmlExpParse(xmlExpCtxtPtr ctxt, const char *expr) { + xmlExpNodePtr ret; + + ctxt->expr = expr; + ctxt->cur = expr; + + ret = xmlExpParseExpr(ctxt); + SKIP_BLANKS + if (*ctxt->cur != 0) { + xmlExpFree(ctxt, ret); + return(NULL); + } + return(ret); +} + +static void +xmlExpDumpInt(xmlBufferPtr buf, xmlExpNodePtr expr, int glob) { + xmlExpNodePtr c; + + if (expr == NULL) return; + if (glob) xmlBufferWriteChar(buf, "("); + switch (expr->type) { + case XML_EXP_EMPTY: + xmlBufferWriteChar(buf, "empty"); + break; + case XML_EXP_FORBID: + xmlBufferWriteChar(buf, "forbidden"); + break; + case XML_EXP_ATOM: + xmlBufferWriteCHAR(buf, expr->exp_str); + break; + case XML_EXP_SEQ: + c = expr->exp_left; + if ((c->type == XML_EXP_SEQ) || (c->type == XML_EXP_OR)) + xmlExpDumpInt(buf, c, 1); + else + xmlExpDumpInt(buf, c, 0); + xmlBufferWriteChar(buf, " , "); + c = expr->exp_right; + if ((c->type == XML_EXP_SEQ) || (c->type == XML_EXP_OR)) + xmlExpDumpInt(buf, c, 1); + else + xmlExpDumpInt(buf, c, 0); + break; + case XML_EXP_OR: + c = expr->exp_left; + if ((c->type == XML_EXP_SEQ) || (c->type == XML_EXP_OR)) + xmlExpDumpInt(buf, c, 1); + else + xmlExpDumpInt(buf, c, 0); + xmlBufferWriteChar(buf, " | "); + c = expr->exp_right; + if ((c->type == XML_EXP_SEQ) || (c->type == XML_EXP_OR)) + xmlExpDumpInt(buf, c, 1); + else + xmlExpDumpInt(buf, c, 0); + break; + case XML_EXP_COUNT: { + char rep[40]; + + c = expr->exp_left; + if ((c->type == XML_EXP_SEQ) || (c->type == XML_EXP_OR)) + xmlExpDumpInt(buf, c, 1); + else + xmlExpDumpInt(buf, c, 0); + if ((expr->exp_min == 0) && (expr->exp_max == 1)) { + rep[0] = '?'; + rep[1] = 0; + } else if ((expr->exp_min == 0) && (expr->exp_max == -1)) { + rep[0] = '*'; + rep[1] = 0; + } else if ((expr->exp_min == 1) && (expr->exp_max == -1)) { + rep[0] = '+'; + rep[1] = 0; + } else if (expr->exp_max == expr->exp_min) { + snprintf(rep, 39, "{%d}", expr->exp_min); + } else if (expr->exp_max < 0) { + snprintf(rep, 39, "{%d,inf}", expr->exp_min); + } else { + snprintf(rep, 39, "{%d,%d}", expr->exp_min, expr->exp_max); + } + rep[39] = 0; + xmlBufferWriteChar(buf, rep); + break; + } + default: + fprintf(stderr, "Error in tree\n"); + } + if (glob) + xmlBufferWriteChar(buf, ")"); +} +/** + * xmlExpDump: + * @buf: a buffer to receive the output + * @expr: the compiled expression + * + * Serialize the expression as compiled to the buffer + */ +void +xmlExpDump(xmlBufferPtr buf, xmlExpNodePtr expr) { + if ((buf == NULL) || (expr == NULL)) + return; + xmlExpDumpInt(buf, expr, 0); +} + +/** + * xmlExpMaxToken: + * @expr: a compiled expression + * + * Indicate the maximum number of input a expression can accept + * + * Returns the maximum length or -1 in case of error + */ +int +xmlExpMaxToken(xmlExpNodePtr expr) { + if (expr == NULL) + return(-1); + return(expr->c_max); +} + +/** + * xmlExpCtxtNbNodes: + * @ctxt: an expression context + * + * Debugging facility provides the number of allocated nodes at a that point + * + * Returns the number of nodes in use or -1 in case of error + */ +int +xmlExpCtxtNbNodes(xmlExpCtxtPtr ctxt) { + if (ctxt == NULL) + return(-1); + return(ctxt->nb_nodes); +} + +/** + * xmlExpCtxtNbCons: + * @ctxt: an expression context + * + * Debugging facility provides the number of allocated nodes over lifetime + * + * Returns the number of nodes ever allocated or -1 in case of error + */ +int +xmlExpCtxtNbCons(xmlExpCtxtPtr ctxt) { + if (ctxt == NULL) + return(-1); + return(ctxt->nb_cons); +} + +#endif /* LIBXML_EXPR_ENABLED */ +#define bottom_xmlregexp +#include "elfgcchack.h" +#endif /* LIBXML_REGEXP_ENABLED */ diff --git a/gettext-tools/gnulib-lib/libxml/xmlregexp.in.h b/gettext-tools/gnulib-lib/libxml/xmlregexp.in.h new file mode 100644 index 0000000..022cd6a --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/xmlregexp.in.h @@ -0,0 +1,216 @@ +/* + * Summary: regular expressions handling + * Description: basic API for libxml regular expressions handling used + * for XML Schemas and validation. + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + +#ifndef __XML_REGEXP_H__ +#define __XML_REGEXP_H__ + +#include + +#ifdef LIBXML_REGEXP_ENABLED + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * xmlRegexpPtr: + * + * A libxml regular expression, they can actually be far more complex + * thank the POSIX regex expressions. + */ +typedef struct _xmlRegexp xmlRegexp; +typedef xmlRegexp *xmlRegexpPtr; + +/** + * xmlRegExecCtxtPtr: + * + * A libxml progressive regular expression evaluation context + */ +typedef struct _xmlRegExecCtxt xmlRegExecCtxt; +typedef xmlRegExecCtxt *xmlRegExecCtxtPtr; + +#ifdef __cplusplus +} +#endif +#include +#include +#ifdef __cplusplus +extern "C" { +#endif + +/* + * The POSIX like API + */ +XMLPUBFUN xmlRegexpPtr XMLCALL + xmlRegexpCompile (const xmlChar *regexp); +XMLPUBFUN void XMLCALL xmlRegFreeRegexp(xmlRegexpPtr regexp); +XMLPUBFUN int XMLCALL + xmlRegexpExec (xmlRegexpPtr comp, + const xmlChar *value); +XMLPUBFUN void XMLCALL + xmlRegexpPrint (FILE *output, + xmlRegexpPtr regexp); +XMLPUBFUN int XMLCALL + xmlRegexpIsDeterminist(xmlRegexpPtr comp); + +/* + * Callback function when doing a transition in the automata + */ +typedef void (*xmlRegExecCallbacks) (xmlRegExecCtxtPtr exec, + const xmlChar *token, + void *transdata, + void *inputdata); + +/* + * The progressive API + */ +XMLPUBFUN xmlRegExecCtxtPtr XMLCALL + xmlRegNewExecCtxt (xmlRegexpPtr comp, + xmlRegExecCallbacks callback, + void *data); +XMLPUBFUN void XMLCALL + xmlRegFreeExecCtxt (xmlRegExecCtxtPtr exec); +XMLPUBFUN int XMLCALL + xmlRegExecPushString(xmlRegExecCtxtPtr exec, + const xmlChar *value, + void *data); +XMLPUBFUN int XMLCALL + xmlRegExecPushString2(xmlRegExecCtxtPtr exec, + const xmlChar *value, + const xmlChar *value2, + void *data); + +XMLPUBFUN int XMLCALL + xmlRegExecNextValues(xmlRegExecCtxtPtr exec, + int *nbval, + int *nbneg, + xmlChar **values, + int *terminal); +XMLPUBFUN int XMLCALL + xmlRegExecErrInfo (xmlRegExecCtxtPtr exec, + const xmlChar **string, + int *nbval, + int *nbneg, + xmlChar **values, + int *terminal); +#ifdef LIBXML_EXPR_ENABLED +/* + * Formal regular expression handling + * Its goal is to do some formal work on content models + */ + +/* expressions are used within a context */ +typedef struct _xmlExpCtxt xmlExpCtxt; +typedef xmlExpCtxt *xmlExpCtxtPtr; + +XMLPUBFUN void XMLCALL + xmlExpFreeCtxt (xmlExpCtxtPtr ctxt); +XMLPUBFUN xmlExpCtxtPtr XMLCALL + xmlExpNewCtxt (int maxNodes, + xmlDictPtr dict); + +XMLPUBFUN int XMLCALL + xmlExpCtxtNbNodes(xmlExpCtxtPtr ctxt); +XMLPUBFUN int XMLCALL + xmlExpCtxtNbCons(xmlExpCtxtPtr ctxt); + +/* Expressions are trees but the tree is opaque */ +typedef struct _xmlExpNode xmlExpNode; +typedef xmlExpNode *xmlExpNodePtr; + +typedef enum { + XML_EXP_EMPTY = 0, + XML_EXP_FORBID = 1, + XML_EXP_ATOM = 2, + XML_EXP_SEQ = 3, + XML_EXP_OR = 4, + XML_EXP_COUNT = 5 +} xmlExpNodeType; + +/* + * 2 core expressions shared by all for the empty language set + * and for the set with just the empty token + */ +XMLPUBVAR xmlExpNodePtr forbiddenExp; +XMLPUBVAR xmlExpNodePtr emptyExp; + +/* + * Expressions are reference counted internally + */ +XMLPUBFUN void XMLCALL + xmlExpFree (xmlExpCtxtPtr ctxt, + xmlExpNodePtr expr); +XMLPUBFUN void XMLCALL + xmlExpRef (xmlExpNodePtr expr); + +/* + * constructors can be either manual or from a string + */ +XMLPUBFUN xmlExpNodePtr XMLCALL + xmlExpParse (xmlExpCtxtPtr ctxt, + const char *expr); +XMLPUBFUN xmlExpNodePtr XMLCALL + xmlExpNewAtom (xmlExpCtxtPtr ctxt, + const xmlChar *name, + int len); +XMLPUBFUN xmlExpNodePtr XMLCALL + xmlExpNewOr (xmlExpCtxtPtr ctxt, + xmlExpNodePtr left, + xmlExpNodePtr right); +XMLPUBFUN xmlExpNodePtr XMLCALL + xmlExpNewSeq (xmlExpCtxtPtr ctxt, + xmlExpNodePtr left, + xmlExpNodePtr right); +XMLPUBFUN xmlExpNodePtr XMLCALL + xmlExpNewRange (xmlExpCtxtPtr ctxt, + xmlExpNodePtr subset, + int min, + int max); +/* + * The really interesting APIs + */ +XMLPUBFUN int XMLCALL + xmlExpIsNillable(xmlExpNodePtr expr); +XMLPUBFUN int XMLCALL + xmlExpMaxToken (xmlExpNodePtr expr); +XMLPUBFUN int XMLCALL + xmlExpGetLanguage(xmlExpCtxtPtr ctxt, + xmlExpNodePtr expr, + const xmlChar**langList, + int len); +XMLPUBFUN int XMLCALL + xmlExpGetStart (xmlExpCtxtPtr ctxt, + xmlExpNodePtr expr, + const xmlChar**tokList, + int len); +XMLPUBFUN xmlExpNodePtr XMLCALL + xmlExpStringDerive(xmlExpCtxtPtr ctxt, + xmlExpNodePtr expr, + const xmlChar *str, + int len); +XMLPUBFUN xmlExpNodePtr XMLCALL + xmlExpExpDerive (xmlExpCtxtPtr ctxt, + xmlExpNodePtr expr, + xmlExpNodePtr sub); +XMLPUBFUN int XMLCALL + xmlExpSubsume (xmlExpCtxtPtr ctxt, + xmlExpNodePtr expr, + xmlExpNodePtr sub); +XMLPUBFUN void XMLCALL + xmlExpDump (xmlBufferPtr buf, + xmlExpNodePtr expr); +#endif /* LIBXML_EXPR_ENABLED */ +#ifdef __cplusplus +} +#endif + +#endif /* LIBXML_REGEXP_ENABLED */ + +#endif /*__XML_REGEXP_H__ */ diff --git a/gettext-tools/gnulib-lib/libxml/xmlsave.c b/gettext-tools/gnulib-lib/libxml/xmlsave.c new file mode 100644 index 0000000..6963e7b --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/xmlsave.c @@ -0,0 +1,2406 @@ +/* + * xmlsave.c: Implemetation of the document serializer + * + * See Copyright for the status of this software. + * + * daniel@veillard.com + */ + +#define IN_LIBXML +#include "libxml.h" + +#include +#include +#include +#include +#include + +#define MAX_INDENT 60 + +#include + +/************************************************************************ + * * + * XHTML detection * + * * + ************************************************************************/ +#define XHTML_STRICT_PUBLIC_ID BAD_CAST \ + "-//W3C//DTD XHTML 1.0 Strict//EN" +#define XHTML_STRICT_SYSTEM_ID BAD_CAST \ + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" +#define XHTML_FRAME_PUBLIC_ID BAD_CAST \ + "-//W3C//DTD XHTML 1.0 Frameset//EN" +#define XHTML_FRAME_SYSTEM_ID BAD_CAST \ + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd" +#define XHTML_TRANS_PUBLIC_ID BAD_CAST \ + "-//W3C//DTD XHTML 1.0 Transitional//EN" +#define XHTML_TRANS_SYSTEM_ID BAD_CAST \ + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" + +#define XHTML_NS_NAME BAD_CAST "http://www.w3.org/1999/xhtml" +/** + * xmlIsXHTML: + * @systemID: the system identifier + * @publicID: the public identifier + * + * Try to find if the document correspond to an XHTML DTD + * + * Returns 1 if true, 0 if not and -1 in case of error + */ +int +xmlIsXHTML(const xmlChar *systemID, const xmlChar *publicID) { + if ((systemID == NULL) && (publicID == NULL)) + return(-1); + if (publicID != NULL) { + if (xmlStrEqual(publicID, XHTML_STRICT_PUBLIC_ID)) return(1); + if (xmlStrEqual(publicID, XHTML_FRAME_PUBLIC_ID)) return(1); + if (xmlStrEqual(publicID, XHTML_TRANS_PUBLIC_ID)) return(1); + } + if (systemID != NULL) { + if (xmlStrEqual(systemID, XHTML_STRICT_SYSTEM_ID)) return(1); + if (xmlStrEqual(systemID, XHTML_FRAME_SYSTEM_ID)) return(1); + if (xmlStrEqual(systemID, XHTML_TRANS_SYSTEM_ID)) return(1); + } + return(0); +} + +#ifdef LIBXML_OUTPUT_ENABLED + +#define TODO \ + xmlGenericError(xmlGenericErrorContext, \ + "Unimplemented block at %s:%d\n", \ + __FILE__, __LINE__); + +struct _xmlSaveCtxt { + void *_private; + int type; + int fd; + const xmlChar *filename; + const xmlChar *encoding; + xmlCharEncodingHandlerPtr handler; + xmlOutputBufferPtr buf; + xmlDocPtr doc; + int options; + int level; + int format; + char indent[MAX_INDENT + 1]; /* array for indenting output */ + int indent_nr; + int indent_size; + xmlCharEncodingOutputFunc escape; /* used for element content */ + xmlCharEncodingOutputFunc escapeAttr;/* used for attribute content */ +}; + +/************************************************************************ + * * + * Output error handlers * + * * + ************************************************************************/ +/** + * xmlSaveErrMemory: + * @extra: extra informations + * + * Handle an out of memory condition + */ +static void +xmlSaveErrMemory(const char *extra) +{ + __xmlSimpleError(XML_FROM_OUTPUT, XML_ERR_NO_MEMORY, NULL, NULL, extra); +} + +/** + * xmlSaveErr: + * @code: the error number + * @node: the location of the error. + * @extra: extra informations + * + * Handle an out of memory condition + */ +static void +xmlSaveErr(int code, xmlNodePtr node, const char *extra) +{ + const char *msg = NULL; + + switch(code) { + case XML_SAVE_NOT_UTF8: + msg = "string is not in UTF-8\n"; + break; + case XML_SAVE_CHAR_INVALID: + msg = "invalid character value\n"; + break; + case XML_SAVE_UNKNOWN_ENCODING: + msg = "unknown encoding %s\n"; + break; + case XML_SAVE_NO_DOCTYPE: + msg = "document has no DOCTYPE\n"; + break; + default: + msg = "unexpected error number\n"; + } + __xmlSimpleError(XML_FROM_OUTPUT, code, node, msg, extra); +} + +/************************************************************************ + * * + * Special escaping routines * + * * + ************************************************************************/ +static unsigned char * +xmlSerializeHexCharRef(unsigned char *out, int val) { + unsigned char *ptr; + + *out++ = '&'; + *out++ = '#'; + *out++ = 'x'; + if (val < 0x10) ptr = out; + else if (val < 0x100) ptr = out + 1; + else if (val < 0x1000) ptr = out + 2; + else if (val < 0x10000) ptr = out + 3; + else if (val < 0x100000) ptr = out + 4; + else ptr = out + 5; + out = ptr + 1; + while (val > 0) { + switch (val & 0xF) { + case 0: *ptr-- = '0'; break; + case 1: *ptr-- = '1'; break; + case 2: *ptr-- = '2'; break; + case 3: *ptr-- = '3'; break; + case 4: *ptr-- = '4'; break; + case 5: *ptr-- = '5'; break; + case 6: *ptr-- = '6'; break; + case 7: *ptr-- = '7'; break; + case 8: *ptr-- = '8'; break; + case 9: *ptr-- = '9'; break; + case 0xA: *ptr-- = 'A'; break; + case 0xB: *ptr-- = 'B'; break; + case 0xC: *ptr-- = 'C'; break; + case 0xD: *ptr-- = 'D'; break; + case 0xE: *ptr-- = 'E'; break; + case 0xF: *ptr-- = 'F'; break; + default: *ptr-- = '0'; break; + } + val >>= 4; + } + *out++ = ';'; + *out = 0; + return(out); +} + +/** + * xmlEscapeEntities: + * @out: a pointer to an array of bytes to store the result + * @outlen: the length of @out + * @in: a pointer to an array of unescaped UTF-8 bytes + * @inlen: the length of @in + * + * Take a block of UTF-8 chars in and escape them. Used when there is no + * encoding specified. + * + * Returns 0 if success, or -1 otherwise + * The value of @inlen after return is the number of octets consumed + * if the return value is positive, else unpredictable. + * The value of @outlen after return is the number of octets consumed. + */ +static int +xmlEscapeEntities(unsigned char* out, int *outlen, + const xmlChar* in, int *inlen) { + unsigned char* outstart = out; + const unsigned char* base = in; + unsigned char* outend = out + *outlen; + const unsigned char* inend; + int val; + + inend = in + (*inlen); + + while ((in < inend) && (out < outend)) { + if (*in == '<') { + if (outend - out < 4) break; + *out++ = '&'; + *out++ = 'l'; + *out++ = 't'; + *out++ = ';'; + in++; + continue; + } else if (*in == '>') { + if (outend - out < 4) break; + *out++ = '&'; + *out++ = 'g'; + *out++ = 't'; + *out++ = ';'; + in++; + continue; + } else if (*in == '&') { + if (outend - out < 5) break; + *out++ = '&'; + *out++ = 'a'; + *out++ = 'm'; + *out++ = 'p'; + *out++ = ';'; + in++; + continue; + } else if (((*in >= 0x20) && (*in < 0x80)) || + (*in == '\n') || (*in == '\t')) { + /* + * default case, just copy ! + */ + *out++ = *in++; + continue; + } else if (*in >= 0x80) { + /* + * We assume we have UTF-8 input. + */ + if (outend - out < 10) break; + + if (*in < 0xC0) { + xmlSaveErr(XML_SAVE_NOT_UTF8, NULL, NULL); + in++; + goto error; + } else if (*in < 0xE0) { + if (inend - in < 2) break; + val = (in[0]) & 0x1F; + val <<= 6; + val |= (in[1]) & 0x3F; + in += 2; + } else if (*in < 0xF0) { + if (inend - in < 3) break; + val = (in[0]) & 0x0F; + val <<= 6; + val |= (in[1]) & 0x3F; + val <<= 6; + val |= (in[2]) & 0x3F; + in += 3; + } else if (*in < 0xF8) { + if (inend - in < 4) break; + val = (in[0]) & 0x07; + val <<= 6; + val |= (in[1]) & 0x3F; + val <<= 6; + val |= (in[2]) & 0x3F; + val <<= 6; + val |= (in[3]) & 0x3F; + in += 4; + } else { + xmlSaveErr(XML_SAVE_CHAR_INVALID, NULL, NULL); + in++; + goto error; + } + if (!IS_CHAR(val)) { + xmlSaveErr(XML_SAVE_CHAR_INVALID, NULL, NULL); + in++; + goto error; + } + + /* + * We could do multiple things here. Just save as a char ref + */ + out = xmlSerializeHexCharRef(out, val); + } else if (IS_BYTE_CHAR(*in)) { + if (outend - out < 6) break; + out = xmlSerializeHexCharRef(out, *in++); + } else { + xmlGenericError(xmlGenericErrorContext, + "xmlEscapeEntities : char out of range\n"); + in++; + goto error; + } + } + *outlen = out - outstart; + *inlen = in - base; + return(0); +error: + *outlen = out - outstart; + *inlen = in - base; + return(-1); +} + +/************************************************************************ + * * + * Allocation and deallocation * + * * + ************************************************************************/ +/** + * xmlSaveCtxtInit: + * @ctxt: the saving context + * + * Initialize a saving context + */ +static void +xmlSaveCtxtInit(xmlSaveCtxtPtr ctxt) +{ + int i; + int len; + + if (ctxt == NULL) return; + if ((ctxt->encoding == NULL) && (ctxt->escape == NULL)) + ctxt->escape = xmlEscapeEntities; + len = xmlStrlen((xmlChar *)xmlTreeIndentString); + if ((xmlTreeIndentString == NULL) || (len == 0)) { + memset(&ctxt->indent[0], 0, MAX_INDENT + 1); + } else { + ctxt->indent_size = len; + ctxt->indent_nr = MAX_INDENT / ctxt->indent_size; + for (i = 0;i < ctxt->indent_nr;i++) + memcpy(&ctxt->indent[i * ctxt->indent_size], xmlTreeIndentString, + ctxt->indent_size); + ctxt->indent[ctxt->indent_nr * ctxt->indent_size] = 0; + } + + if (xmlSaveNoEmptyTags) { + ctxt->options |= XML_SAVE_NO_EMPTY; + } +} + +/** + * xmlFreeSaveCtxt: + * + * Free a saving context, destroying the ouptut in any remaining buffer + */ +static void +xmlFreeSaveCtxt(xmlSaveCtxtPtr ctxt) +{ + if (ctxt == NULL) return; + if (ctxt->encoding != NULL) + xmlFree((char *) ctxt->encoding); + if (ctxt->buf != NULL) + xmlOutputBufferClose(ctxt->buf); + xmlFree(ctxt); +} + +/** + * xmlNewSaveCtxt: + * + * Create a new saving context + * + * Returns the new structure or NULL in case of error + */ +static xmlSaveCtxtPtr +xmlNewSaveCtxt(const char *encoding, int options) +{ + xmlSaveCtxtPtr ret; + + ret = (xmlSaveCtxtPtr) xmlMalloc(sizeof(xmlSaveCtxt)); + if (ret == NULL) { + xmlSaveErrMemory("creating saving context"); + return ( NULL ); + } + memset(ret, 0, sizeof(xmlSaveCtxt)); + + if (encoding != NULL) { + ret->handler = xmlFindCharEncodingHandler(encoding); + if (ret->handler == NULL) { + xmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, NULL, encoding); + xmlFreeSaveCtxt(ret); + return(NULL); + } + ret->encoding = xmlStrdup((const xmlChar *)encoding); + ret->escape = NULL; + } + xmlSaveCtxtInit(ret); + + /* + * Use the options + */ + + /* Re-check this option as it may already have been set */ + if ((ret->options & XML_SAVE_NO_EMPTY) && ! (options & XML_SAVE_NO_EMPTY)) { + options |= XML_SAVE_NO_EMPTY; + } + + ret->options = options; + if (options & XML_SAVE_FORMAT) + ret->format = 1; + + return(ret); +} + +/************************************************************************ + * * + * Dumping XML tree content to a simple buffer * + * * + ************************************************************************/ +/** + * xmlAttrSerializeContent: + * @buf: the XML buffer output + * @doc: the document + * @attr: the attribute pointer + * + * Serialize the attribute in the buffer + */ +static void +xmlAttrSerializeContent(xmlOutputBufferPtr buf, xmlAttrPtr attr) +{ + xmlNodePtr children; + + children = attr->children; + while (children != NULL) { + switch (children->type) { + case XML_TEXT_NODE: + xmlAttrSerializeTxtContent(buf->buffer, attr->doc, + attr, children->content); + break; + case XML_ENTITY_REF_NODE: + xmlBufferAdd(buf->buffer, BAD_CAST "&", 1); + xmlBufferAdd(buf->buffer, children->name, + xmlStrlen(children->name)); + xmlBufferAdd(buf->buffer, BAD_CAST ";", 1); + break; + default: + /* should not happen unless we have a badly built tree */ + break; + } + children = children->next; + } +} + +/************************************************************************ + * * + * Dumping XML tree content to an I/O output buffer * + * * + ************************************************************************/ + +#ifdef LIBXML_HTML_ENABLED +static void +xhtmlNodeDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur); +#endif +static void xmlNodeListDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur); +static void xmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur); +void xmlNsListDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur); +static int xmlDocContentDumpOutput(xmlSaveCtxtPtr ctxt, xmlDocPtr cur); + +/** + * xmlNsDumpOutput: + * @buf: the XML buffer output + * @cur: a namespace + * + * Dump a local Namespace definition. + * Should be called in the context of attributes dumps. + */ +static void +xmlNsDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur) { + if ((cur == NULL) || (buf == NULL)) return; + if ((cur->type == XML_LOCAL_NAMESPACE) && (cur->href != NULL)) { + if (xmlStrEqual(cur->prefix, BAD_CAST "xml")) + return; + + /* Within the context of an element attributes */ + if (cur->prefix != NULL) { + xmlOutputBufferWrite(buf, 7, " xmlns:"); + xmlOutputBufferWriteString(buf, (const char *)cur->prefix); + } else + xmlOutputBufferWrite(buf, 6, " xmlns"); + xmlOutputBufferWrite(buf, 1, "="); + xmlBufferWriteQuotedString(buf->buffer, cur->href); + } +} + +/** + * xmlNsListDumpOutput: + * @buf: the XML buffer output + * @cur: the first namespace + * + * Dump a list of local Namespace definitions. + * Should be called in the context of attributes dumps. + */ +void +xmlNsListDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur) { + while (cur != NULL) { + xmlNsDumpOutput(buf, cur); + cur = cur->next; + } +} + +/** + * xmlDtdDumpOutput: + * @buf: the XML buffer output + * @dtd: the pointer to the DTD + * + * Dump the XML document DTD, if any. + */ +static void +xmlDtdDumpOutput(xmlSaveCtxtPtr ctxt, xmlDtdPtr dtd) { + xmlOutputBufferPtr buf; + int format, level; + xmlDocPtr doc; + + if (dtd == NULL) return; + if ((ctxt == NULL) || (ctxt->buf == NULL)) + return; + buf = ctxt->buf; + xmlOutputBufferWrite(buf, 10, "name); + if (dtd->ExternalID != NULL) { + xmlOutputBufferWrite(buf, 8, " PUBLIC "); + xmlBufferWriteQuotedString(buf->buffer, dtd->ExternalID); + xmlOutputBufferWrite(buf, 1, " "); + xmlBufferWriteQuotedString(buf->buffer, dtd->SystemID); + } else if (dtd->SystemID != NULL) { + xmlOutputBufferWrite(buf, 8, " SYSTEM "); + xmlBufferWriteQuotedString(buf->buffer, dtd->SystemID); + } + if ((dtd->entities == NULL) && (dtd->elements == NULL) && + (dtd->attributes == NULL) && (dtd->notations == NULL) && + (dtd->pentities == NULL)) { + xmlOutputBufferWrite(buf, 1, ">"); + return; + } + xmlOutputBufferWrite(buf, 3, " [\n"); + /* + * Dump the notations first they are not in the DTD children list + * Do this only on a standalone DTD or on the internal subset though. + */ + if ((dtd->notations != NULL) && ((dtd->doc == NULL) || + (dtd->doc->intSubset == dtd))) { + xmlDumpNotationTable(buf->buffer, (xmlNotationTablePtr) dtd->notations); + } + format = ctxt->format; + level = ctxt->level; + doc = ctxt->doc; + ctxt->format = 0; + ctxt->level = -1; + ctxt->doc = dtd->doc; + xmlNodeListDumpOutput(ctxt, dtd->children); + ctxt->format = format; + ctxt->level = level; + ctxt->doc = doc; + xmlOutputBufferWrite(buf, 2, "]>"); +} + +/** + * xmlAttrDumpOutput: + * @buf: the XML buffer output + * @cur: the attribute pointer + * + * Dump an XML attribute + */ +static void +xmlAttrDumpOutput(xmlSaveCtxtPtr ctxt, xmlAttrPtr cur) { + xmlOutputBufferPtr buf; + + if (cur == NULL) return; + buf = ctxt->buf; + if (buf == NULL) return; + xmlOutputBufferWrite(buf, 1, " "); + if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) { + xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix); + xmlOutputBufferWrite(buf, 1, ":"); + } + xmlOutputBufferWriteString(buf, (const char *)cur->name); + xmlOutputBufferWrite(buf, 2, "=\""); + xmlAttrSerializeContent(buf, cur); + xmlOutputBufferWrite(buf, 1, "\""); +} + +/** + * xmlAttrListDumpOutput: + * @buf: the XML buffer output + * @doc: the document + * @cur: the first attribute pointer + * @encoding: an optional encoding string + * + * Dump a list of XML attributes + */ +static void +xmlAttrListDumpOutput(xmlSaveCtxtPtr ctxt, xmlAttrPtr cur) { + if (cur == NULL) return; + while (cur != NULL) { + xmlAttrDumpOutput(ctxt, cur); + cur = cur->next; + } +} + + + +/** + * xmlNodeListDumpOutput: + * @cur: the first node + * + * Dump an XML node list, recursive behaviour, children are printed too. + */ +static void +xmlNodeListDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) { + xmlOutputBufferPtr buf; + + if (cur == NULL) return; + buf = ctxt->buf; + while (cur != NULL) { + if ((ctxt->format) && (xmlIndentTreeOutput) && + (cur->type == XML_ELEMENT_NODE)) + xmlOutputBufferWrite(buf, ctxt->indent_size * + (ctxt->level > ctxt->indent_nr ? + ctxt->indent_nr : ctxt->level), + ctxt->indent); + xmlNodeDumpOutputInternal(ctxt, cur); + if (ctxt->format) { + xmlOutputBufferWrite(buf, 1, "\n"); + } + cur = cur->next; + } +} + +/** + * xmlNodeDumpOutputInternal: + * @cur: the current node + * + * Dump an XML node, recursive behaviour, children are printed too. + */ +static void +xmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) { + int format; + xmlNodePtr tmp; + xmlChar *start, *end; + xmlOutputBufferPtr buf; + + if (cur == NULL) return; + buf = ctxt->buf; + if (cur->type == XML_XINCLUDE_START) + return; + if (cur->type == XML_XINCLUDE_END) + return; + if ((cur->type == XML_DOCUMENT_NODE) || + (cur->type == XML_HTML_DOCUMENT_NODE)) { + xmlDocContentDumpOutput(ctxt, (xmlDocPtr) cur); + return; + } + if (cur->type == XML_DTD_NODE) { + xmlDtdDumpOutput(ctxt, (xmlDtdPtr) cur); + return; + } + if (cur->type == XML_DOCUMENT_FRAG_NODE) { + xmlNodeListDumpOutput(ctxt, cur->children); + return; + } + if (cur->type == XML_ELEMENT_DECL) { + xmlDumpElementDecl(buf->buffer, (xmlElementPtr) cur); + return; + } + if (cur->type == XML_ATTRIBUTE_DECL) { + xmlDumpAttributeDecl(buf->buffer, (xmlAttributePtr) cur); + return; + } + if (cur->type == XML_ENTITY_DECL) { + xmlDumpEntityDecl(buf->buffer, (xmlEntityPtr) cur); + return; + } + if (cur->type == XML_TEXT_NODE) { + if (cur->content != NULL) { + if (cur->name != xmlStringTextNoenc) { + xmlOutputBufferWriteEscape(buf, cur->content, ctxt->escape); + } else { + /* + * Disable escaping, needed for XSLT + */ + xmlOutputBufferWriteString(buf, (const char *) cur->content); + } + } + + return; + } + if (cur->type == XML_PI_NODE) { + if (cur->content != NULL) { + xmlOutputBufferWrite(buf, 2, "name); + if (cur->content != NULL) { + xmlOutputBufferWrite(buf, 1, " "); + xmlOutputBufferWriteString(buf, (const char *)cur->content); + } + xmlOutputBufferWrite(buf, 2, "?>"); + } else { + xmlOutputBufferWrite(buf, 2, "name); + xmlOutputBufferWrite(buf, 2, "?>"); + } + return; + } + if (cur->type == XML_COMMENT_NODE) { + if (cur->content != NULL) { + xmlOutputBufferWrite(buf, 4, ""); + } + return; + } + if (cur->type == XML_ENTITY_REF_NODE) { + xmlOutputBufferWrite(buf, 1, "&"); + xmlOutputBufferWriteString(buf, (const char *)cur->name); + xmlOutputBufferWrite(buf, 1, ";"); + return; + } + if (cur->type == XML_CDATA_SECTION_NODE) { + if (cur->content == NULL) { + xmlOutputBufferWrite(buf, 12, ""); + } else { + start = end = cur->content; + while (*end != '\0') { + if ((*end == ']') && (*(end + 1) == ']') && + (*(end + 2) == '>')) { + end = end + 2; + xmlOutputBufferWrite(buf, 9, ""); + start = end; + } + end++; + } + if (start != end) { + xmlOutputBufferWrite(buf, 9, ""); + } + } + return; + } + if (cur->type == XML_ATTRIBUTE_NODE) { + xmlAttrDumpOutput(ctxt, (xmlAttrPtr) cur); + return; + } + if (cur->type == XML_NAMESPACE_DECL) { + xmlNsDumpOutput(buf, (xmlNsPtr) cur); + return; + } + + format = ctxt->format; + if (format == 1) { + tmp = cur->children; + while (tmp != NULL) { + if ((tmp->type == XML_TEXT_NODE) || + (tmp->type == XML_CDATA_SECTION_NODE) || + (tmp->type == XML_ENTITY_REF_NODE)) { + ctxt->format = 0; + break; + } + tmp = tmp->next; + } + } + xmlOutputBufferWrite(buf, 1, "<"); + if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) { + xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix); + xmlOutputBufferWrite(buf, 1, ":"); + } + + xmlOutputBufferWriteString(buf, (const char *)cur->name); + if (cur->nsDef) + xmlNsListDumpOutput(buf, cur->nsDef); + if (cur->properties != NULL) + xmlAttrListDumpOutput(ctxt, cur->properties); + + if (((cur->type == XML_ELEMENT_NODE) || (cur->content == NULL)) && + (cur->children == NULL) && ((ctxt->options & XML_SAVE_NO_EMPTY) == 0)) { + xmlOutputBufferWrite(buf, 2, "/>"); + ctxt->format = format; + return; + } + xmlOutputBufferWrite(buf, 1, ">"); + if ((cur->type != XML_ELEMENT_NODE) && (cur->content != NULL)) { + xmlOutputBufferWriteEscape(buf, cur->content, ctxt->escape); + } + if (cur->children != NULL) { + if (ctxt->format) xmlOutputBufferWrite(buf, 1, "\n"); + if (ctxt->level >= 0) ctxt->level++; + xmlNodeListDumpOutput(ctxt, cur->children); + if (ctxt->level > 0) ctxt->level--; + if ((xmlIndentTreeOutput) && (ctxt->format)) + xmlOutputBufferWrite(buf, ctxt->indent_size * + (ctxt->level > ctxt->indent_nr ? + ctxt->indent_nr : ctxt->level), + ctxt->indent); + } + xmlOutputBufferWrite(buf, 2, "ns != NULL) && (cur->ns->prefix != NULL)) { + xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix); + xmlOutputBufferWrite(buf, 1, ":"); + } + + xmlOutputBufferWriteString(buf, (const char *)cur->name); + xmlOutputBufferWrite(buf, 1, ">"); + ctxt->format = format; +} + +/** + * xmlDocContentDumpOutput: + * @cur: the document + * + * Dump an XML document. + */ +static int +xmlDocContentDumpOutput(xmlSaveCtxtPtr ctxt, xmlDocPtr cur) { +#ifdef LIBXML_HTML_ENABLED + xmlDtdPtr dtd; + int is_xhtml = 0; +#endif + const xmlChar *oldenc = cur->encoding; + const xmlChar *oldctxtenc = ctxt->encoding; + const xmlChar *encoding = ctxt->encoding; + xmlCharEncodingOutputFunc oldescape = ctxt->escape; + xmlCharEncodingOutputFunc oldescapeAttr = ctxt->escapeAttr; + xmlOutputBufferPtr buf = ctxt->buf; + xmlCharEncodingHandlerPtr handler = NULL; + xmlCharEncoding enc; + + xmlInitParser(); + + if (ctxt->encoding != NULL) { + cur->encoding = BAD_CAST ctxt->encoding; + } else if (cur->encoding != NULL) { + encoding = cur->encoding; + } else if (cur->charset != XML_CHAR_ENCODING_UTF8) { + encoding = (const xmlChar *) + xmlGetCharEncodingName((xmlCharEncoding) cur->charset); + } + + enc = xmlParseCharEncoding((const char*) encoding); + if ((encoding != NULL) && (oldctxtenc == NULL) && + (buf->encoder == NULL) && (buf->conv == NULL) && + ((ctxt->options & XML_SAVE_NO_DECL) == 0)) { + if ((enc != XML_CHAR_ENCODING_UTF8) && + (enc != XML_CHAR_ENCODING_NONE) && + (enc != XML_CHAR_ENCODING_ASCII)) { + /* + * we need to switch to this encoding but just for this document + * since we output the XMLDecl the conversion must be done to not + * generate not well formed documents. + */ + buf->encoder = xmlFindCharEncodingHandler((const char *)encoding); + if (buf->encoder == NULL) { + xmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, NULL, + (const char *)encoding); + return(-1); + } + buf->conv = xmlBufferCreate(); + if (buf->conv == NULL) { + xmlCharEncCloseFunc(buf->encoder); + xmlSaveErrMemory("creating encoding buffer"); + return(-1); + } + /* + * initialize the state, e.g. if outputting a BOM + */ + xmlCharEncOutFunc(buf->encoder, buf->conv, NULL); + } + if (ctxt->escape == xmlEscapeEntities) + ctxt->escape = NULL; + if (ctxt->escapeAttr == xmlEscapeEntities) + ctxt->escapeAttr = NULL; + } + + + /* + * Save the XML declaration + */ + if ((ctxt->options & XML_SAVE_NO_DECL) == 0) { + xmlOutputBufferWrite(buf, 14, "version != NULL) + xmlBufferWriteQuotedString(buf->buffer, cur->version); + else + xmlOutputBufferWrite(buf, 5, "\"1.0\""); + if (encoding != NULL) { + xmlOutputBufferWrite(buf, 10, " encoding="); + xmlBufferWriteQuotedString(buf->buffer, (xmlChar *) encoding); + } + switch (cur->standalone) { + case 0: + xmlOutputBufferWrite(buf, 16, " standalone=\"no\""); + break; + case 1: + xmlOutputBufferWrite(buf, 17, " standalone=\"yes\""); + break; + } + xmlOutputBufferWrite(buf, 3, "?>\n"); + } + +#ifdef LIBXML_HTML_ENABLED + if ((ctxt->options & XML_SAVE_NO_XHTML) == 0) { + dtd = xmlGetIntSubset(cur); + if (dtd != NULL) { + is_xhtml = xmlIsXHTML(dtd->SystemID, dtd->ExternalID); + if (is_xhtml < 0) is_xhtml = 0; + } + } +#endif + if (cur->children != NULL) { + xmlNodePtr child = cur->children; + + while (child != NULL) { + ctxt->level = 0; +#ifdef LIBXML_HTML_ENABLED + if (is_xhtml) + xhtmlNodeDumpOutput(ctxt, child); + else +#endif + xmlNodeDumpOutputInternal(ctxt, child); + xmlOutputBufferWrite(buf, 1, "\n"); + child = child->next; + } + } + if (ctxt->encoding != NULL) + cur->encoding = oldenc; + + /* + * Restore the state of the saving context at the end of the document + */ + if ((encoding != NULL) && (oldctxtenc == NULL) && + ((ctxt->options & XML_SAVE_NO_DECL) == 0)) { + if ((enc != XML_CHAR_ENCODING_UTF8) && + (enc != XML_CHAR_ENCODING_NONE) && + (enc != XML_CHAR_ENCODING_ASCII)) { + xmlOutputBufferFlush(buf); + xmlCharEncCloseFunc(buf->encoder); + xmlBufferFree(buf->conv); + buf->encoder = NULL; + buf->conv = NULL; + } + ctxt->escape = oldescape; + ctxt->escapeAttr = oldescapeAttr; + } + return(0); +} + +#ifdef LIBXML_HTML_ENABLED +/************************************************************************ + * * + * Functions specific to XHTML serialization * + * * + ************************************************************************/ + +/** + * xhtmlIsEmpty: + * @node: the node + * + * Check if a node is an empty xhtml node + * + * Returns 1 if the node is an empty node, 0 if not and -1 in case of error + */ +static int +xhtmlIsEmpty(xmlNodePtr node) { + if (node == NULL) + return(-1); + if (node->type != XML_ELEMENT_NODE) + return(0); + if ((node->ns != NULL) && (!xmlStrEqual(node->ns->href, XHTML_NS_NAME))) + return(0); + if (node->children != NULL) + return(0); + switch (node->name[0]) { + case 'a': + if (xmlStrEqual(node->name, BAD_CAST "area")) + return(1); + return(0); + case 'b': + if (xmlStrEqual(node->name, BAD_CAST "br")) + return(1); + if (xmlStrEqual(node->name, BAD_CAST "base")) + return(1); + if (xmlStrEqual(node->name, BAD_CAST "basefont")) + return(1); + return(0); + case 'c': + if (xmlStrEqual(node->name, BAD_CAST "col")) + return(1); + return(0); + case 'f': + if (xmlStrEqual(node->name, BAD_CAST "frame")) + return(1); + return(0); + case 'h': + if (xmlStrEqual(node->name, BAD_CAST "hr")) + return(1); + return(0); + case 'i': + if (xmlStrEqual(node->name, BAD_CAST "img")) + return(1); + if (xmlStrEqual(node->name, BAD_CAST "input")) + return(1); + if (xmlStrEqual(node->name, BAD_CAST "isindex")) + return(1); + return(0); + case 'l': + if (xmlStrEqual(node->name, BAD_CAST "link")) + return(1); + return(0); + case 'm': + if (xmlStrEqual(node->name, BAD_CAST "meta")) + return(1); + return(0); + case 'p': + if (xmlStrEqual(node->name, BAD_CAST "param")) + return(1); + return(0); + } + return(0); +} + +/** + * xhtmlAttrListDumpOutput: + * @cur: the first attribute pointer + * + * Dump a list of XML attributes + */ +static void +xhtmlAttrListDumpOutput(xmlSaveCtxtPtr ctxt, xmlAttrPtr cur) { + xmlAttrPtr xml_lang = NULL; + xmlAttrPtr lang = NULL; + xmlAttrPtr name = NULL; + xmlAttrPtr id = NULL; + xmlNodePtr parent; + xmlOutputBufferPtr buf; + + if (cur == NULL) return; + buf = ctxt->buf; + parent = cur->parent; + while (cur != NULL) { + if ((cur->ns == NULL) && (xmlStrEqual(cur->name, BAD_CAST "id"))) + id = cur; + else + if ((cur->ns == NULL) && (xmlStrEqual(cur->name, BAD_CAST "name"))) + name = cur; + else + if ((cur->ns == NULL) && (xmlStrEqual(cur->name, BAD_CAST "lang"))) + lang = cur; + else + if ((cur->ns != NULL) && (xmlStrEqual(cur->name, BAD_CAST "lang")) && + (xmlStrEqual(cur->ns->prefix, BAD_CAST "xml"))) + xml_lang = cur; + else if ((cur->ns == NULL) && + ((cur->children == NULL) || + (cur->children->content == NULL) || + (cur->children->content[0] == 0)) && + (htmlIsBooleanAttr(cur->name))) { + if (cur->children != NULL) + xmlFreeNode(cur->children); + cur->children = xmlNewText(cur->name); + if (cur->children != NULL) + cur->children->parent = (xmlNodePtr) cur; + } + xmlAttrDumpOutput(ctxt, cur); + cur = cur->next; + } + /* + * C.8 + */ + if ((name != NULL) && (id == NULL)) { + if ((parent != NULL) && (parent->name != NULL) && + ((xmlStrEqual(parent->name, BAD_CAST "a")) || + (xmlStrEqual(parent->name, BAD_CAST "p")) || + (xmlStrEqual(parent->name, BAD_CAST "div")) || + (xmlStrEqual(parent->name, BAD_CAST "img")) || + (xmlStrEqual(parent->name, BAD_CAST "map")) || + (xmlStrEqual(parent->name, BAD_CAST "applet")) || + (xmlStrEqual(parent->name, BAD_CAST "form")) || + (xmlStrEqual(parent->name, BAD_CAST "frame")) || + (xmlStrEqual(parent->name, BAD_CAST "iframe")))) { + xmlOutputBufferWrite(buf, 5, " id=\""); + xmlAttrSerializeContent(buf, name); + xmlOutputBufferWrite(buf, 1, "\""); + } + } + /* + * C.7. + */ + if ((lang != NULL) && (xml_lang == NULL)) { + xmlOutputBufferWrite(buf, 11, " xml:lang=\""); + xmlAttrSerializeContent(buf, lang); + xmlOutputBufferWrite(buf, 1, "\""); + } else + if ((xml_lang != NULL) && (lang == NULL)) { + xmlOutputBufferWrite(buf, 7, " lang=\""); + xmlAttrSerializeContent(buf, xml_lang); + xmlOutputBufferWrite(buf, 1, "\""); + } +} + +/** + * xhtmlNodeListDumpOutput: + * @buf: the XML buffer output + * @doc: the XHTML document + * @cur: the first node + * @level: the imbrication level for indenting + * @format: is formatting allowed + * @encoding: an optional encoding string + * + * Dump an XML node list, recursive behaviour, children are printed too. + * Note that @format = 1 provide node indenting only if xmlIndentTreeOutput = 1 + * or xmlKeepBlanksDefault(0) was called + */ +static void +xhtmlNodeListDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) { + xmlOutputBufferPtr buf; + + if (cur == NULL) return; + buf = ctxt->buf; + while (cur != NULL) { + if ((ctxt->format) && (xmlIndentTreeOutput) && + (cur->type == XML_ELEMENT_NODE)) + xmlOutputBufferWrite(buf, ctxt->indent_size * + (ctxt->level > ctxt->indent_nr ? + ctxt->indent_nr : ctxt->level), + ctxt->indent); + xhtmlNodeDumpOutput(ctxt, cur); + if (ctxt->format) { + xmlOutputBufferWrite(buf, 1, "\n"); + } + cur = cur->next; + } +} + +/** + * xhtmlNodeDumpOutput: + * @buf: the XML buffer output + * @doc: the XHTML document + * @cur: the current node + * @level: the imbrication level for indenting + * @format: is formatting allowed + * @encoding: an optional encoding string + * + * Dump an XHTML node, recursive behaviour, children are printed too. + */ +static void +xhtmlNodeDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) { + int format, addmeta = 0; + xmlNodePtr tmp; + xmlChar *start, *end; + xmlOutputBufferPtr buf; + + if (cur == NULL) return; + if ((cur->type == XML_DOCUMENT_NODE) || + (cur->type == XML_HTML_DOCUMENT_NODE)) { + xmlDocContentDumpOutput(ctxt, (xmlDocPtr) cur); + return; + } + if (cur->type == XML_XINCLUDE_START) + return; + if (cur->type == XML_XINCLUDE_END) + return; + if (cur->type == XML_DTD_NODE) { + xmlDtdDumpOutput(ctxt, (xmlDtdPtr) cur); + return; + } + if (cur->type == XML_DOCUMENT_FRAG_NODE) { + xhtmlNodeListDumpOutput(ctxt, cur->children); + return; + } + buf = ctxt->buf; + if (cur->type == XML_ELEMENT_DECL) { + xmlDumpElementDecl(buf->buffer, (xmlElementPtr) cur); + return; + } + if (cur->type == XML_ATTRIBUTE_DECL) { + xmlDumpAttributeDecl(buf->buffer, (xmlAttributePtr) cur); + return; + } + if (cur->type == XML_ENTITY_DECL) { + xmlDumpEntityDecl(buf->buffer, (xmlEntityPtr) cur); + return; + } + if (cur->type == XML_TEXT_NODE) { + if (cur->content != NULL) { + if ((cur->name == xmlStringText) || + (cur->name != xmlStringTextNoenc)) { + xmlOutputBufferWriteEscape(buf, cur->content, ctxt->escape); + } else { + /* + * Disable escaping, needed for XSLT + */ + xmlOutputBufferWriteString(buf, (const char *) cur->content); + } + } + + return; + } + if (cur->type == XML_PI_NODE) { + if (cur->content != NULL) { + xmlOutputBufferWrite(buf, 2, "name); + if (cur->content != NULL) { + xmlOutputBufferWrite(buf, 1, " "); + xmlOutputBufferWriteString(buf, (const char *)cur->content); + } + xmlOutputBufferWrite(buf, 2, "?>"); + } else { + xmlOutputBufferWrite(buf, 2, "name); + xmlOutputBufferWrite(buf, 2, "?>"); + } + return; + } + if (cur->type == XML_COMMENT_NODE) { + if (cur->content != NULL) { + xmlOutputBufferWrite(buf, 4, ""); + } + return; + } + if (cur->type == XML_ENTITY_REF_NODE) { + xmlOutputBufferWrite(buf, 1, "&"); + xmlOutputBufferWriteString(buf, (const char *)cur->name); + xmlOutputBufferWrite(buf, 1, ";"); + return; + } + if (cur->type == XML_CDATA_SECTION_NODE) { + start = end = cur->content; + while (*end != '\0') { + if (*end == ']' && *(end + 1) == ']' && *(end + 2) == '>') { + end = end + 2; + xmlOutputBufferWrite(buf, 9, ""); + start = end; + } + end++; + } + if (start != end) { + xmlOutputBufferWrite(buf, 9, ""); + } + return; + } + + format = ctxt->format; + if (format == 1) { + tmp = cur->children; + while (tmp != NULL) { + if ((tmp->type == XML_TEXT_NODE) || + (tmp->type == XML_ENTITY_REF_NODE)) { + format = 0; + break; + } + tmp = tmp->next; + } + } + xmlOutputBufferWrite(buf, 1, "<"); + if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) { + xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix); + xmlOutputBufferWrite(buf, 1, ":"); + } + + xmlOutputBufferWriteString(buf, (const char *)cur->name); + if (cur->nsDef) + xmlNsListDumpOutput(buf, cur->nsDef); + if ((xmlStrEqual(cur->name, BAD_CAST "html") && + (cur->ns == NULL) && (cur->nsDef == NULL))) { + /* + * 3.1.1. Strictly Conforming Documents A.3.1.1 3/ + */ + xmlOutputBufferWriteString(buf, + " xmlns=\"http://www.w3.org/1999/xhtml\""); + } + if (cur->properties != NULL) + xhtmlAttrListDumpOutput(ctxt, cur->properties); + + if ((cur->type == XML_ELEMENT_NODE) && + (cur->parent != NULL) && + (cur->parent->parent == (xmlNodePtr) cur->doc) && + xmlStrEqual(cur->name, BAD_CAST"head") && + xmlStrEqual(cur->parent->name, BAD_CAST"html")) { + + tmp = cur->children; + while (tmp != NULL) { + if (xmlStrEqual(tmp->name, BAD_CAST"meta")) { + xmlChar *httpequiv; + + httpequiv = xmlGetProp(tmp, BAD_CAST"http-equiv"); + if (httpequiv != NULL) { + if (xmlStrcasecmp(httpequiv, BAD_CAST"Content-Type") == 0) { + xmlFree(httpequiv); + break; + } + xmlFree(httpequiv); + } + } + tmp = tmp->next; + } + if (tmp == NULL) + addmeta = 1; + } + + if ((cur->type == XML_ELEMENT_NODE) && (cur->children == NULL)) { + if (((cur->ns == NULL) || (cur->ns->prefix == NULL)) && + ((xhtmlIsEmpty(cur) == 1) && (addmeta == 0))) { + /* + * C.2. Empty Elements + */ + xmlOutputBufferWrite(buf, 3, " />"); + } else { + if (addmeta == 1) { + xmlOutputBufferWrite(buf, 1, ">"); + if (ctxt->format) { + xmlOutputBufferWrite(buf, 1, "\n"); + if (xmlIndentTreeOutput) + xmlOutputBufferWrite(buf, ctxt->indent_size * + (ctxt->level + 1 > ctxt->indent_nr ? + ctxt->indent_nr : ctxt->level + 1), ctxt->indent); + } + xmlOutputBufferWriteString(buf, + ""); + if (ctxt->format) + xmlOutputBufferWrite(buf, 1, "\n"); + } else { + xmlOutputBufferWrite(buf, 1, ">"); + } + /* + * C.3. Element Minimization and Empty Element Content + */ + xmlOutputBufferWrite(buf, 2, "ns != NULL) && (cur->ns->prefix != NULL)) { + xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix); + xmlOutputBufferWrite(buf, 1, ":"); + } + xmlOutputBufferWriteString(buf, (const char *)cur->name); + xmlOutputBufferWrite(buf, 1, ">"); + } + return; + } + xmlOutputBufferWrite(buf, 1, ">"); + if (addmeta == 1) { + if (ctxt->format) { + xmlOutputBufferWrite(buf, 1, "\n"); + if (xmlIndentTreeOutput) + xmlOutputBufferWrite(buf, ctxt->indent_size * + (ctxt->level + 1 > ctxt->indent_nr ? + ctxt->indent_nr : ctxt->level + 1), ctxt->indent); + } + xmlOutputBufferWriteString(buf, + ""); + } + if ((cur->type != XML_ELEMENT_NODE) && (cur->content != NULL)) { + xmlOutputBufferWriteEscape(buf, cur->content, ctxt->escape); + } + +#if 0 + /* + * This was removed due to problems with HTML processors. + * See bug #345147. + */ + /* + * 4.8. Script and Style elements + */ + if ((cur->type == XML_ELEMENT_NODE) && + ((xmlStrEqual(cur->name, BAD_CAST "script")) || + (xmlStrEqual(cur->name, BAD_CAST "style"))) && + ((cur->ns == NULL) || + (xmlStrEqual(cur->ns->href, XHTML_NS_NAME)))) { + xmlNodePtr child = cur->children; + + while (child != NULL) { + if (child->type == XML_TEXT_NODE) { + if ((xmlStrchr(child->content, '<') == NULL) && + (xmlStrchr(child->content, '&') == NULL) && + (xmlStrstr(child->content, BAD_CAST "]]>") == NULL)) { + /* Nothing to escape, so just output as is... */ + /* FIXME: Should we do something about "--" also? */ + int level = ctxt->level; + int indent = ctxt->format; + + ctxt->level = 0; + ctxt->format = 0; + xmlOutputBufferWriteString(buf, (const char *) child->content); + /* (We cannot use xhtmlNodeDumpOutput() here because + * we wish to leave '>' unescaped!) */ + ctxt->level = level; + ctxt->format = indent; + } else { + /* We must use a CDATA section. Unfortunately, + * this will break CSS and JavaScript when read by + * a browser in HTML4-compliant mode. :-( */ + start = end = child->content; + while (*end != '\0') { + if (*end == ']' && + *(end + 1) == ']' && + *(end + 2) == '>') { + end = end + 2; + xmlOutputBufferWrite(buf, 9, ""); + start = end; + } + end++; + } + if (start != end) { + xmlOutputBufferWrite(buf, 9, ""); + } + } + } else { + int level = ctxt->level; + int indent = ctxt->format; + + ctxt->level = 0; + ctxt->format = 0; + xhtmlNodeDumpOutput(ctxt, child); + ctxt->level = level; + ctxt->format = indent; + } + child = child->next; + } + } +#endif + + if (cur->children != NULL) { + int indent = ctxt->format; + + if (format) xmlOutputBufferWrite(buf, 1, "\n"); + if (ctxt->level >= 0) ctxt->level++; + ctxt->format = format; + xhtmlNodeListDumpOutput(ctxt, cur->children); + if (ctxt->level > 0) ctxt->level--; + ctxt->format = indent; + if ((xmlIndentTreeOutput) && (format)) + xmlOutputBufferWrite(buf, ctxt->indent_size * + (ctxt->level > ctxt->indent_nr ? + ctxt->indent_nr : ctxt->level), + ctxt->indent); + } + xmlOutputBufferWrite(buf, 2, "ns != NULL) && (cur->ns->prefix != NULL)) { + xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix); + xmlOutputBufferWrite(buf, 1, ":"); + } + + xmlOutputBufferWriteString(buf, (const char *)cur->name); + xmlOutputBufferWrite(buf, 1, ">"); +} +#endif + +/************************************************************************ + * * + * Public entry points * + * * + ************************************************************************/ + +/** + * xmlSaveToFd: + * @fd: a file descriptor number + * @encoding: the encoding name to use or NULL + * @options: a set of xmlSaveOptions + * + * Create a document saving context serializing to a file descriptor + * with the encoding and the options given. + * + * Returns a new serialization context or NULL in case of error. + */ +xmlSaveCtxtPtr +xmlSaveToFd(int fd, const char *encoding, int options) +{ + xmlSaveCtxtPtr ret; + + ret = xmlNewSaveCtxt(encoding, options); + if (ret == NULL) return(NULL); + ret->buf = xmlOutputBufferCreateFd(fd, ret->handler); + if (ret->buf == NULL) { + xmlFreeSaveCtxt(ret); + return(NULL); + } + return(ret); +} + +/** + * xmlSaveToFilename: + * @filename: a file name or an URL + * @encoding: the encoding name to use or NULL + * @options: a set of xmlSaveOptions + * + * Create a document saving context serializing to a filename or possibly + * to an URL (but this is less reliable) with the encoding and the options + * given. + * + * Returns a new serialization context or NULL in case of error. + */ +xmlSaveCtxtPtr +xmlSaveToFilename(const char *filename, const char *encoding, int options) +{ + xmlSaveCtxtPtr ret; + int compression = 0; /* TODO handle compression option */ + + ret = xmlNewSaveCtxt(encoding, options); + if (ret == NULL) return(NULL); + ret->buf = xmlOutputBufferCreateFilename(filename, ret->handler, + compression); + if (ret->buf == NULL) { + xmlFreeSaveCtxt(ret); + return(NULL); + } + return(ret); +} + +/** + * xmlSaveToBuffer: + * @buffer: a buffer + * @encoding: the encoding name to use or NULL + * @options: a set of xmlSaveOptions + * + * Create a document saving context serializing to a buffer + * with the encoding and the options given + * + * Returns a new serialization context or NULL in case of error. + */ + +xmlSaveCtxtPtr +xmlSaveToBuffer(xmlBufferPtr buffer, const char *encoding, int options) +{ + xmlSaveCtxtPtr ret; + xmlOutputBufferPtr out_buff; + xmlCharEncodingHandlerPtr handler; + + ret = xmlNewSaveCtxt(encoding, options); + if (ret == NULL) return(NULL); + + if (encoding != NULL) { + handler = xmlFindCharEncodingHandler(encoding); + if (handler == NULL) { + xmlFree(ret); + return(NULL); + } + } else + handler = NULL; + out_buff = xmlOutputBufferCreateBuffer(buffer, handler); + if (out_buff == NULL) { + xmlFree(ret); + if (handler) xmlCharEncCloseFunc(handler); + return(NULL); + } + + ret->buf = out_buff; + return(ret); +} + +/** + * xmlSaveToIO: + * @iowrite: an I/O write function + * @ioclose: an I/O close function + * @ioctx: an I/O handler + * @encoding: the encoding name to use or NULL + * @options: a set of xmlSaveOptions + * + * Create a document saving context serializing to a file descriptor + * with the encoding and the options given + * + * Returns a new serialization context or NULL in case of error. + */ +xmlSaveCtxtPtr +xmlSaveToIO(xmlOutputWriteCallback iowrite, + xmlOutputCloseCallback ioclose, + void *ioctx, const char *encoding, int options) +{ + xmlSaveCtxtPtr ret; + + ret = xmlNewSaveCtxt(encoding, options); + if (ret == NULL) return(NULL); + ret->buf = xmlOutputBufferCreateIO(iowrite, ioclose, ioctx, ret->handler); + if (ret->buf == NULL) { + xmlFreeSaveCtxt(ret); + return(NULL); + } + return(ret); +} + +/** + * xmlSaveDoc: + * @ctxt: a document saving context + * @doc: a document + * + * Save a full document to a saving context + * TODO: The function is not fully implemented yet as it does not return the + * byte count but 0 instead + * + * Returns the number of byte written or -1 in case of error + */ +long +xmlSaveDoc(xmlSaveCtxtPtr ctxt, xmlDocPtr doc) +{ + long ret = 0; + + if ((ctxt == NULL) || (doc == NULL)) return(-1); + if (xmlDocContentDumpOutput(ctxt, doc) < 0) + return(-1); + return(ret); +} + +/** + * xmlSaveTree: + * @ctxt: a document saving context + * @node: the top node of the subtree to save + * + * Save a subtree starting at the node parameter to a saving context + * TODO: The function is not fully implemented yet as it does not return the + * byte count but 0 instead + * + * Returns the number of byte written or -1 in case of error + */ +long +xmlSaveTree(xmlSaveCtxtPtr ctxt, xmlNodePtr node) +{ + long ret = 0; + + if ((ctxt == NULL) || (node == NULL)) return(-1); + xmlNodeDumpOutputInternal(ctxt, node); + return(ret); +} + +/** + * xmlSaveFlush: + * @ctxt: a document saving context + * + * Flush a document saving context, i.e. make sure that all bytes have + * been output. + * + * Returns the number of byte written or -1 in case of error. + */ +int +xmlSaveFlush(xmlSaveCtxtPtr ctxt) +{ + if (ctxt == NULL) return(-1); + if (ctxt->buf == NULL) return(-1); + return(xmlOutputBufferFlush(ctxt->buf)); +} + +/** + * xmlSaveClose: + * @ctxt: a document saving context + * + * Close a document saving context, i.e. make sure that all bytes have + * been output and free the associated data. + * + * Returns the number of byte written or -1 in case of error. + */ +int +xmlSaveClose(xmlSaveCtxtPtr ctxt) +{ + int ret; + + if (ctxt == NULL) return(-1); + ret = xmlSaveFlush(ctxt); + xmlFreeSaveCtxt(ctxt); + return(ret); +} + +/** + * xmlSaveSetEscape: + * @ctxt: a document saving context + * @escape: the escaping function + * + * Set a custom escaping function to be used for text in element content + * + * Returns 0 if successful or -1 in case of error. + */ +int +xmlSaveSetEscape(xmlSaveCtxtPtr ctxt, xmlCharEncodingOutputFunc escape) +{ + if (ctxt == NULL) return(-1); + ctxt->escape = escape; + return(0); +} + +/** + * xmlSaveSetAttrEscape: + * @ctxt: a document saving context + * @escape: the escaping function + * + * Set a custom escaping function to be used for text in attribute content + * + * Returns 0 if successful or -1 in case of error. + */ +int +xmlSaveSetAttrEscape(xmlSaveCtxtPtr ctxt, xmlCharEncodingOutputFunc escape) +{ + if (ctxt == NULL) return(-1); + ctxt->escapeAttr = escape; + return(0); +} + +/************************************************************************ + * * + * Public entry points based on buffers * + * * + ************************************************************************/ +/** + * xmlAttrSerializeTxtContent: + * @buf: the XML buffer output + * @doc: the document + * @attr: the attribute node + * @string: the text content + * + * Serialize text attribute values to an xml simple buffer + */ +void +xmlAttrSerializeTxtContent(xmlBufferPtr buf, xmlDocPtr doc, + xmlAttrPtr attr, const xmlChar * string) +{ + xmlChar *base, *cur; + + if (string == NULL) + return; + base = cur = (xmlChar *) string; + while (*cur != 0) { + if (*cur == '\n') { + if (base != cur) + xmlBufferAdd(buf, base, cur - base); + xmlBufferAdd(buf, BAD_CAST " ", 5); + cur++; + base = cur; + } else if (*cur == '\r') { + if (base != cur) + xmlBufferAdd(buf, base, cur - base); + xmlBufferAdd(buf, BAD_CAST " ", 5); + cur++; + base = cur; + } else if (*cur == '\t') { + if (base != cur) + xmlBufferAdd(buf, base, cur - base); + xmlBufferAdd(buf, BAD_CAST " ", 4); + cur++; + base = cur; + } else if (*cur == '"') { + if (base != cur) + xmlBufferAdd(buf, base, cur - base); + xmlBufferAdd(buf, BAD_CAST """, 6); + cur++; + base = cur; + } else if (*cur == '<') { + if (base != cur) + xmlBufferAdd(buf, base, cur - base); + xmlBufferAdd(buf, BAD_CAST "<", 4); + cur++; + base = cur; + } else if (*cur == '>') { + if (base != cur) + xmlBufferAdd(buf, base, cur - base); + xmlBufferAdd(buf, BAD_CAST ">", 4); + cur++; + base = cur; + } else if (*cur == '&') { + if (base != cur) + xmlBufferAdd(buf, base, cur - base); + xmlBufferAdd(buf, BAD_CAST "&", 5); + cur++; + base = cur; + } else if ((*cur >= 0x80) && ((doc == NULL) || + (doc->encoding == NULL))) { + /* + * We assume we have UTF-8 content. + */ + unsigned char tmp[10]; + int val = 0, l = 1; + + if (base != cur) + xmlBufferAdd(buf, base, cur - base); + if (*cur < 0xC0) { + xmlSaveErr(XML_SAVE_NOT_UTF8, (xmlNodePtr) attr, NULL); + if (doc != NULL) + doc->encoding = xmlStrdup(BAD_CAST "ISO-8859-1"); + xmlSerializeHexCharRef(tmp, *cur); + xmlBufferAdd(buf, (xmlChar *) tmp, -1); + cur++; + base = cur; + continue; + } else if (*cur < 0xE0) { + val = (cur[0]) & 0x1F; + val <<= 6; + val |= (cur[1]) & 0x3F; + l = 2; + } else if (*cur < 0xF0) { + val = (cur[0]) & 0x0F; + val <<= 6; + val |= (cur[1]) & 0x3F; + val <<= 6; + val |= (cur[2]) & 0x3F; + l = 3; + } else if (*cur < 0xF8) { + val = (cur[0]) & 0x07; + val <<= 6; + val |= (cur[1]) & 0x3F; + val <<= 6; + val |= (cur[2]) & 0x3F; + val <<= 6; + val |= (cur[3]) & 0x3F; + l = 4; + } + if ((l == 1) || (!IS_CHAR(val))) { + xmlSaveErr(XML_SAVE_CHAR_INVALID, (xmlNodePtr) attr, NULL); + if (doc != NULL) + doc->encoding = xmlStrdup(BAD_CAST "ISO-8859-1"); + + xmlSerializeHexCharRef(tmp, *cur); + xmlBufferAdd(buf, (xmlChar *) tmp, -1); + cur++; + base = cur; + continue; + } + /* + * We could do multiple things here. Just save + * as a char ref + */ + xmlSerializeHexCharRef(tmp, val); + xmlBufferAdd(buf, (xmlChar *) tmp, -1); + cur += l; + base = cur; + } else { + cur++; + } + } + if (base != cur) + xmlBufferAdd(buf, base, cur - base); +} + +/** + * xmlNodeDump: + * @buf: the XML buffer output + * @doc: the document + * @cur: the current node + * @level: the imbrication level for indenting + * @format: is formatting allowed + * + * Dump an XML node, recursive behaviour,children are printed too. + * Note that @format = 1 provide node indenting only if xmlIndentTreeOutput = 1 + * or xmlKeepBlanksDefault(0) was called + * + * Returns the number of bytes written to the buffer or -1 in case of error + */ +int +xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level, + int format) +{ + unsigned int use; + int ret; + xmlOutputBufferPtr outbuf; + + xmlInitParser(); + + if (cur == NULL) { +#ifdef DEBUG_TREE + xmlGenericError(xmlGenericErrorContext, + "xmlNodeDump : node == NULL\n"); +#endif + return (-1); + } + if (buf == NULL) { +#ifdef DEBUG_TREE + xmlGenericError(xmlGenericErrorContext, + "xmlNodeDump : buf == NULL\n"); +#endif + return (-1); + } + outbuf = (xmlOutputBufferPtr) xmlMalloc(sizeof(xmlOutputBuffer)); + if (outbuf == NULL) { + xmlSaveErrMemory("creating buffer"); + return (-1); + } + memset(outbuf, 0, (size_t) sizeof(xmlOutputBuffer)); + outbuf->buffer = buf; + outbuf->encoder = NULL; + outbuf->writecallback = NULL; + outbuf->closecallback = NULL; + outbuf->context = NULL; + outbuf->written = 0; + + use = buf->use; + xmlNodeDumpOutput(outbuf, doc, cur, level, format, NULL); + xmlFree(outbuf); + ret = buf->use - use; + return (ret); +} + +/** + * xmlElemDump: + * @f: the FILE * for the output + * @doc: the document + * @cur: the current node + * + * Dump an XML/HTML node, recursive behaviour, children are printed too. + */ +void +xmlElemDump(FILE * f, xmlDocPtr doc, xmlNodePtr cur) +{ + xmlOutputBufferPtr outbuf; + + xmlInitParser(); + + if (cur == NULL) { +#ifdef DEBUG_TREE + xmlGenericError(xmlGenericErrorContext, + "xmlElemDump : cur == NULL\n"); +#endif + return; + } +#ifdef DEBUG_TREE + if (doc == NULL) { + xmlGenericError(xmlGenericErrorContext, + "xmlElemDump : doc == NULL\n"); + } +#endif + + outbuf = xmlOutputBufferCreateFile(f, NULL); + if (outbuf == NULL) + return; + if ((doc != NULL) && (doc->type == XML_HTML_DOCUMENT_NODE)) { +#ifdef LIBXML_HTML_ENABLED + htmlNodeDumpOutput(outbuf, doc, cur, NULL); +#else + xmlSaveErr(XML_ERR_INTERNAL_ERROR, cur, "HTML support not compiled in\n"); +#endif /* LIBXML_HTML_ENABLED */ + } else + xmlNodeDumpOutput(outbuf, doc, cur, 0, 1, NULL); + xmlOutputBufferClose(outbuf); +} + +/************************************************************************ + * * + * Saving functions front-ends * + * * + ************************************************************************/ + +/** + * xmlNodeDumpOutput: + * @buf: the XML buffer output + * @doc: the document + * @cur: the current node + * @level: the imbrication level for indenting + * @format: is formatting allowed + * @encoding: an optional encoding string + * + * Dump an XML node, recursive behaviour, children are printed too. + * Note that @format = 1 provide node indenting only if xmlIndentTreeOutput = 1 + * or xmlKeepBlanksDefault(0) was called + */ +void +xmlNodeDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, + int level, int format, const char *encoding) +{ + xmlSaveCtxt ctxt; +#ifdef LIBXML_HTML_ENABLED + xmlDtdPtr dtd; + int is_xhtml = 0; +#endif + + xmlInitParser(); + + if ((buf == NULL) || (cur == NULL)) return; + + if (encoding == NULL) + encoding = "UTF-8"; + + memset(&ctxt, 0, sizeof(ctxt)); + ctxt.doc = doc; + ctxt.buf = buf; + ctxt.level = level; + ctxt.format = format; + ctxt.encoding = (const xmlChar *) encoding; + xmlSaveCtxtInit(&ctxt); + +#ifdef LIBXML_HTML_ENABLED + dtd = xmlGetIntSubset(doc); + if (dtd != NULL) { + is_xhtml = xmlIsXHTML(dtd->SystemID, dtd->ExternalID); + if (is_xhtml < 0) + is_xhtml = 0; + } + + if (is_xhtml) + xhtmlNodeDumpOutput(&ctxt, cur); + else +#endif + xmlNodeDumpOutputInternal(&ctxt, cur); +} + +/** + * xmlDocDumpFormatMemoryEnc: + * @out_doc: Document to generate XML text from + * @doc_txt_ptr: Memory pointer for allocated XML text + * @doc_txt_len: Length of the generated XML text + * @txt_encoding: Character encoding to use when generating XML text + * @format: should formatting spaces been added + * + * Dump the current DOM tree into memory using the character encoding specified + * by the caller. Note it is up to the caller of this function to free the + * allocated memory with xmlFree(). + * Note that @format = 1 provide node indenting only if xmlIndentTreeOutput = 1 + * or xmlKeepBlanksDefault(0) was called + */ + +void +xmlDocDumpFormatMemoryEnc(xmlDocPtr out_doc, xmlChar **doc_txt_ptr, + int * doc_txt_len, const char * txt_encoding, + int format) { + xmlSaveCtxt ctxt; + int dummy = 0; + xmlOutputBufferPtr out_buff = NULL; + xmlCharEncodingHandlerPtr conv_hdlr = NULL; + + if (doc_txt_len == NULL) { + doc_txt_len = &dummy; /* Continue, caller just won't get length */ + } + + if (doc_txt_ptr == NULL) { + *doc_txt_len = 0; + return; + } + + *doc_txt_ptr = NULL; + *doc_txt_len = 0; + + if (out_doc == NULL) { + /* No document, no output */ + return; + } + + /* + * Validate the encoding value, if provided. + * This logic is copied from xmlSaveFileEnc. + */ + + if (txt_encoding == NULL) + txt_encoding = (const char *) out_doc->encoding; + if (txt_encoding != NULL) { + conv_hdlr = xmlFindCharEncodingHandler(txt_encoding); + if ( conv_hdlr == NULL ) { + xmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, (xmlNodePtr) out_doc, + txt_encoding); + return; + } + } + + if ((out_buff = xmlAllocOutputBuffer(conv_hdlr)) == NULL ) { + xmlSaveErrMemory("creating buffer"); + return; + } + + memset(&ctxt, 0, sizeof(ctxt)); + ctxt.doc = out_doc; + ctxt.buf = out_buff; + ctxt.level = 0; + ctxt.format = format; + ctxt.encoding = (const xmlChar *) txt_encoding; + xmlSaveCtxtInit(&ctxt); + xmlDocContentDumpOutput(&ctxt, out_doc); + xmlOutputBufferFlush(out_buff); + if (out_buff->conv != NULL) { + *doc_txt_len = out_buff->conv->use; + *doc_txt_ptr = xmlStrndup(out_buff->conv->content, *doc_txt_len); + } else { + *doc_txt_len = out_buff->buffer->use; + *doc_txt_ptr = xmlStrndup(out_buff->buffer->content, *doc_txt_len); + } + (void)xmlOutputBufferClose(out_buff); + + if ((*doc_txt_ptr == NULL) && (*doc_txt_len > 0)) { + *doc_txt_len = 0; + xmlSaveErrMemory("creating output"); + } + + return; +} + +/** + * xmlDocDumpMemory: + * @cur: the document + * @mem: OUT: the memory pointer + * @size: OUT: the memory length + * + * Dump an XML document in memory and return the #xmlChar * and it's size + * in bytes. It's up to the caller to free the memory with xmlFree(). + * The resulting byte array is zero terminated, though the last 0 is not + * included in the returned size. + */ +void +xmlDocDumpMemory(xmlDocPtr cur, xmlChar**mem, int *size) { + xmlDocDumpFormatMemoryEnc(cur, mem, size, NULL, 0); +} + +/** + * xmlDocDumpFormatMemory: + * @cur: the document + * @mem: OUT: the memory pointer + * @size: OUT: the memory length + * @format: should formatting spaces been added + * + * + * Dump an XML document in memory and return the #xmlChar * and it's size. + * It's up to the caller to free the memory with xmlFree(). + * Note that @format = 1 provide node indenting only if xmlIndentTreeOutput = 1 + * or xmlKeepBlanksDefault(0) was called + */ +void +xmlDocDumpFormatMemory(xmlDocPtr cur, xmlChar**mem, int *size, int format) { + xmlDocDumpFormatMemoryEnc(cur, mem, size, NULL, format); +} + +/** + * xmlDocDumpMemoryEnc: + * @out_doc: Document to generate XML text from + * @doc_txt_ptr: Memory pointer for allocated XML text + * @doc_txt_len: Length of the generated XML text + * @txt_encoding: Character encoding to use when generating XML text + * + * Dump the current DOM tree into memory using the character encoding specified + * by the caller. Note it is up to the caller of this function to free the + * allocated memory with xmlFree(). + */ + +void +xmlDocDumpMemoryEnc(xmlDocPtr out_doc, xmlChar **doc_txt_ptr, + int * doc_txt_len, const char * txt_encoding) { + xmlDocDumpFormatMemoryEnc(out_doc, doc_txt_ptr, doc_txt_len, + txt_encoding, 0); +} + +/** + * xmlDocFormatDump: + * @f: the FILE* + * @cur: the document + * @format: should formatting spaces been added + * + * Dump an XML document to an open FILE. + * + * returns: the number of bytes written or -1 in case of failure. + * Note that @format = 1 provide node indenting only if xmlIndentTreeOutput = 1 + * or xmlKeepBlanksDefault(0) was called + */ +int +xmlDocFormatDump(FILE *f, xmlDocPtr cur, int format) { + xmlSaveCtxt ctxt; + xmlOutputBufferPtr buf; + const char * encoding; + xmlCharEncodingHandlerPtr handler = NULL; + int ret; + + if (cur == NULL) { +#ifdef DEBUG_TREE + xmlGenericError(xmlGenericErrorContext, + "xmlDocDump : document == NULL\n"); +#endif + return(-1); + } + encoding = (const char *) cur->encoding; + + if (encoding != NULL) { + handler = xmlFindCharEncodingHandler(encoding); + if (handler == NULL) { + xmlFree((char *) cur->encoding); + cur->encoding = NULL; + } + } + buf = xmlOutputBufferCreateFile(f, handler); + if (buf == NULL) return(-1); + memset(&ctxt, 0, sizeof(ctxt)); + ctxt.doc = cur; + ctxt.buf = buf; + ctxt.level = 0; + ctxt.format = format; + ctxt.encoding = (const xmlChar *) encoding; + xmlSaveCtxtInit(&ctxt); + xmlDocContentDumpOutput(&ctxt, cur); + + ret = xmlOutputBufferClose(buf); + return(ret); +} + +/** + * xmlDocDump: + * @f: the FILE* + * @cur: the document + * + * Dump an XML document to an open FILE. + * + * returns: the number of bytes written or -1 in case of failure. + */ +int +xmlDocDump(FILE *f, xmlDocPtr cur) { + return(xmlDocFormatDump (f, cur, 0)); +} + +/** + * xmlSaveFileTo: + * @buf: an output I/O buffer + * @cur: the document + * @encoding: the encoding if any assuming the I/O layer handles the trancoding + * + * Dump an XML document to an I/O buffer. + * Warning ! This call xmlOutputBufferClose() on buf which is not available + * after this call. + * + * returns: the number of bytes written or -1 in case of failure. + */ +int +xmlSaveFileTo(xmlOutputBufferPtr buf, xmlDocPtr cur, const char *encoding) { + xmlSaveCtxt ctxt; + int ret; + + if (buf == NULL) return(-1); + if (cur == NULL) { + xmlOutputBufferClose(buf); + return(-1); + } + memset(&ctxt, 0, sizeof(ctxt)); + ctxt.doc = cur; + ctxt.buf = buf; + ctxt.level = 0; + ctxt.format = 0; + ctxt.encoding = (const xmlChar *) encoding; + xmlSaveCtxtInit(&ctxt); + xmlDocContentDumpOutput(&ctxt, cur); + ret = xmlOutputBufferClose(buf); + return(ret); +} + +/** + * xmlSaveFormatFileTo: + * @buf: an output I/O buffer + * @cur: the document + * @encoding: the encoding if any assuming the I/O layer handles the trancoding + * @format: should formatting spaces been added + * + * Dump an XML document to an I/O buffer. + * Warning ! This call xmlOutputBufferClose() on buf which is not available + * after this call. + * + * returns: the number of bytes written or -1 in case of failure. + */ +int +xmlSaveFormatFileTo(xmlOutputBufferPtr buf, xmlDocPtr cur, + const char *encoding, int format) +{ + xmlSaveCtxt ctxt; + int ret; + + if (buf == NULL) return(-1); + if ((cur == NULL) || + ((cur->type != XML_DOCUMENT_NODE) && + (cur->type != XML_HTML_DOCUMENT_NODE))) { + xmlOutputBufferClose(buf); + return(-1); + } + memset(&ctxt, 0, sizeof(ctxt)); + ctxt.doc = cur; + ctxt.buf = buf; + ctxt.level = 0; + ctxt.format = format; + ctxt.encoding = (const xmlChar *) encoding; + xmlSaveCtxtInit(&ctxt); + xmlDocContentDumpOutput(&ctxt, cur); + ret = xmlOutputBufferClose(buf); + return (ret); +} + +/** + * xmlSaveFormatFileEnc: + * @filename: the filename or URL to output + * @cur: the document being saved + * @encoding: the name of the encoding to use or NULL. + * @format: should formatting spaces be added. + * + * Dump an XML document to a file or an URL. + * + * Returns the number of bytes written or -1 in case of error. + * Note that @format = 1 provide node indenting only if xmlIndentTreeOutput = 1 + * or xmlKeepBlanksDefault(0) was called + */ +int +xmlSaveFormatFileEnc( const char * filename, xmlDocPtr cur, + const char * encoding, int format ) { + xmlSaveCtxt ctxt; + xmlOutputBufferPtr buf; + xmlCharEncodingHandlerPtr handler = NULL; + int ret; + + if (cur == NULL) + return(-1); + + if (encoding == NULL) + encoding = (const char *) cur->encoding; + + if (encoding != NULL) { + + handler = xmlFindCharEncodingHandler(encoding); + if (handler == NULL) + return(-1); + } + +#ifdef HAVE_ZLIB_H + if (cur->compression < 0) cur->compression = xmlGetCompressMode(); +#endif + /* + * save the content to a temp buffer. + */ + buf = xmlOutputBufferCreateFilename(filename, handler, cur->compression); + if (buf == NULL) return(-1); + memset(&ctxt, 0, sizeof(ctxt)); + ctxt.doc = cur; + ctxt.buf = buf; + ctxt.level = 0; + ctxt.format = format; + ctxt.encoding = (const xmlChar *) encoding; + xmlSaveCtxtInit(&ctxt); + + xmlDocContentDumpOutput(&ctxt, cur); + + ret = xmlOutputBufferClose(buf); + return(ret); +} + + +/** + * xmlSaveFileEnc: + * @filename: the filename (or URL) + * @cur: the document + * @encoding: the name of an encoding (or NULL) + * + * Dump an XML document, converting it to the given encoding + * + * returns: the number of bytes written or -1 in case of failure. + */ +int +xmlSaveFileEnc(const char *filename, xmlDocPtr cur, const char *encoding) { + return ( xmlSaveFormatFileEnc( filename, cur, encoding, 0 ) ); +} + +/** + * xmlSaveFormatFile: + * @filename: the filename (or URL) + * @cur: the document + * @format: should formatting spaces been added + * + * Dump an XML document to a file. Will use compression if + * compiled in and enabled. If @filename is "-" the stdout file is + * used. If @format is set then the document will be indented on output. + * Note that @format = 1 provide node indenting only if xmlIndentTreeOutput = 1 + * or xmlKeepBlanksDefault(0) was called + * + * returns: the number of bytes written or -1 in case of failure. + */ +int +xmlSaveFormatFile(const char *filename, xmlDocPtr cur, int format) { + return ( xmlSaveFormatFileEnc( filename, cur, NULL, format ) ); +} + +/** + * xmlSaveFile: + * @filename: the filename (or URL) + * @cur: the document + * + * Dump an XML document to a file. Will use compression if + * compiled in and enabled. If @filename is "-" the stdout file is + * used. + * returns: the number of bytes written or -1 in case of failure. + */ +int +xmlSaveFile(const char *filename, xmlDocPtr cur) { + return(xmlSaveFormatFileEnc(filename, cur, NULL, 0)); +} + +#endif /* LIBXML_OUTPUT_ENABLED */ + +#define bottom_xmlsave +#include "elfgcchack.h" diff --git a/gettext-tools/gnulib-lib/libxml/xmlsave.in.h b/gettext-tools/gnulib-lib/libxml/xmlsave.in.h new file mode 100644 index 0000000..c71c71a --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/xmlsave.in.h @@ -0,0 +1,84 @@ +/* + * Summary: the XML document serializer + * Description: API to save document or subtree of document + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + +#ifndef __XML_XMLSAVE_H__ +#define __XML_XMLSAVE_H__ + +#include +#include +#include +#include + +#ifdef LIBXML_OUTPUT_ENABLED +#ifdef __cplusplus +extern "C" { +#endif + +/** + * xmlSaveOption: + * + * This is the set of XML save options that can be passed down + * to the xmlSaveToFd() and similar calls. + */ +typedef enum { + XML_SAVE_FORMAT = 1<<0, /* format save output */ + XML_SAVE_NO_DECL = 1<<1, /* drop the xml declaration */ + XML_SAVE_NO_EMPTY = 1<<2, /* no empty tags */ + XML_SAVE_NO_XHTML = 1<<3 /* disable XHTML1 specific rules */ +} xmlSaveOption; + + +typedef struct _xmlSaveCtxt xmlSaveCtxt; +typedef xmlSaveCtxt *xmlSaveCtxtPtr; + +XMLPUBFUN xmlSaveCtxtPtr XMLCALL + xmlSaveToFd (int fd, + const char *encoding, + int options); +XMLPUBFUN xmlSaveCtxtPtr XMLCALL + xmlSaveToFilename (const char *filename, + const char *encoding, + int options); + +XMLPUBFUN xmlSaveCtxtPtr XMLCALL + xmlSaveToBuffer (xmlBufferPtr buffer, + const char *encoding, + int options); + +XMLPUBFUN xmlSaveCtxtPtr XMLCALL + xmlSaveToIO (xmlOutputWriteCallback iowrite, + xmlOutputCloseCallback ioclose, + void *ioctx, + const char *encoding, + int options); + +XMLPUBFUN long XMLCALL + xmlSaveDoc (xmlSaveCtxtPtr ctxt, + xmlDocPtr doc); +XMLPUBFUN long XMLCALL + xmlSaveTree (xmlSaveCtxtPtr ctxt, + xmlNodePtr node); + +XMLPUBFUN int XMLCALL + xmlSaveFlush (xmlSaveCtxtPtr ctxt); +XMLPUBFUN int XMLCALL + xmlSaveClose (xmlSaveCtxtPtr ctxt); +XMLPUBFUN int XMLCALL + xmlSaveSetEscape (xmlSaveCtxtPtr ctxt, + xmlCharEncodingOutputFunc escape); +XMLPUBFUN int XMLCALL + xmlSaveSetAttrEscape (xmlSaveCtxtPtr ctxt, + xmlCharEncodingOutputFunc escape); +#ifdef __cplusplus +} +#endif +#endif /* LIBXML_OUTPUT_ENABLED */ +#endif /* __XML_XMLSAVE_H__ */ + + diff --git a/gettext-tools/gnulib-lib/libxml/xmlschemas.c b/gettext-tools/gnulib-lib/libxml/xmlschemas.c new file mode 100644 index 0000000..11e3eac --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/xmlschemas.c @@ -0,0 +1,28654 @@ +/* + * schemas.c : implementation of the XML Schema handling and + * schema validity checking + * + * See Copyright for the status of this software. + * + * Daniel Veillard + */ + +/* + * TODO: + * - when types are redefined in includes, check that all + * types in the redef list are equal + * -> need a type equality operation. + * - if we don't intend to use the schema for schemas, we + * need to validate all schema attributes (ref, type, name) + * against their types. + * - Eliminate item creation for: ?? + * + * URGENT TODO: + * - For xsi-driven schema acquisition, augment the IDCs after every + * acquisition episode (xmlSchemaAugmentIDC). + * + * NOTES: + * - Elimated item creation for: , , + * , , , + * + * PROBLEMS: + * - http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0337.html + * IDC XPath expression and chameleon includes: the targetNamespace is changed, so + * XPath will have trouble to resolve to this namespace, since not known. + * + * + * CONSTRAINTS: + * + * Schema Component Constraint: + * All Group Limited (cos-all-limited) + * Status: complete + * (1.2) + * In xmlSchemaGroupDefReferenceTermFixup() and + * (2) + * In xmlSchemaParseModelGroup() + * TODO: Actually this should go to component-level checks, + * but is done here due to performance. Move it to an other layer + * is schema construction via an API is implemented. + */ +#define IN_LIBXML +#include "libxml.h" + +#ifdef LIBXML_SCHEMAS_ENABLED + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef LIBXML_PATTERN_ENABLED +#include +#endif +#ifdef LIBXML_READER_ENABLED +#include +#endif + +/* #define DEBUG 1 */ + +/* #define DEBUG_CONTENT 1 */ + +/* #define DEBUG_TYPE 1 */ + +/* #define DEBUG_CONTENT_REGEXP 1 */ + +/* #define DEBUG_AUTOMATA 1 */ + +/* #define DEBUG_IDC */ + +/* #define DEBUG_IDC_NODE_TABLE */ + +/* #define WXS_ELEM_DECL_CONS_ENABLED */ + +#ifdef DEBUG_IDC + #ifndef DEBUG_IDC_NODE_TABLE + #define DEBUG_IDC_NODE_TABLE + #endif +#endif + +/* #define ENABLE_PARTICLE_RESTRICTION 1 */ + +#define ENABLE_REDEFINE + +/* #define ENABLE_NAMED_LOCALS */ + +/* #define ENABLE_IDC_NODE_TABLES_TEST */ + +#define DUMP_CONTENT_MODEL + +#ifdef LIBXML_READER_ENABLED +/* #define XML_SCHEMA_READER_ENABLED */ +#endif + +#define UNBOUNDED (1 << 30) +#define TODO \ + xmlGenericError(xmlGenericErrorContext, \ + "Unimplemented block at %s:%d\n", \ + __FILE__, __LINE__); + +#define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##" + +/* + * The XML Schemas namespaces + */ +static const xmlChar *xmlSchemaNs = (const xmlChar *) + "http://www.w3.org/2001/XMLSchema"; + +static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *) + "http://www.w3.org/2001/XMLSchema-instance"; + +static const xmlChar *xmlNamespaceNs = (const xmlChar *) + "http://www.w3.org/2000/xmlns/"; + +/* +* Come casting macros. +*/ +#define ACTXT_CAST (xmlSchemaAbstractCtxtPtr) +#define PCTXT_CAST (xmlSchemaParserCtxtPtr) +#define VCTXT_CAST (xmlSchemaValidCtxtPtr) +#define WXS_BASIC_CAST (xmlSchemaBasicItemPtr) +#define WXS_TREE_CAST (xmlSchemaTreeItemPtr) +#define WXS_PTC_CAST (xmlSchemaParticlePtr) +#define WXS_TYPE_CAST (xmlSchemaTypePtr) +#define WXS_ELEM_CAST (xmlSchemaElementPtr) +#define WXS_ATTR_GROUP_CAST (xmlSchemaAttributeGroupPtr) +#define WXS_ATTR_CAST (xmlSchemaAttributePtr) +#define WXS_ATTR_USE_CAST (xmlSchemaAttributeUsePtr) +#define WXS_ATTR_PROHIB_CAST (xmlSchemaAttributeUseProhibPtr) +#define WXS_MODEL_GROUPDEF_CAST (xmlSchemaModelGroupDefPtr) +#define WXS_MODEL_GROUP_CAST (xmlSchemaModelGroupPtr) +#define WXS_IDC_CAST (xmlSchemaIDCPtr) +#define WXS_QNAME_CAST (xmlSchemaQNameRefPtr) +#define WXS_LIST_CAST (xmlSchemaItemListPtr) + +/* +* Macros to query common properties of components. +*/ +#define WXS_ITEM_NODE(i) xmlSchemaGetComponentNode(WXS_BASIC_CAST (i)) + +#define WXS_ITEM_TYPE_NAME(i) xmlSchemaGetComponentTypeStr(WXS_BASIC_CAST (i)) +/* +* Macros for element declarations. +*/ +#define WXS_ELEM_TYPEDEF(e) (e)->subtypes + +#define WXS_SUBST_HEAD(item) (item)->refDecl +/* +* Macros for attribute declarations. +*/ +#define WXS_ATTR_TYPEDEF(a) (a)->subtypes +/* +* Macros for attribute uses. +*/ +#define WXS_ATTRUSE_DECL(au) WXS_ATTR_CAST (WXS_ATTR_USE_CAST (au))->attrDecl + +#define WXS_ATTRUSE_TYPEDEF(au) WXS_ATTR_TYPEDEF(WXS_ATTRUSE_DECL( WXS_ATTR_USE_CAST au)) + +#define WXS_ATTRUSE_DECL_NAME(au) (WXS_ATTRUSE_DECL(au))->name + +#define WXS_ATTRUSE_DECL_TNS(au) (WXS_ATTRUSE_DECL(au))->targetNamespace +/* +* Macros for attribute groups. +*/ +#define WXS_ATTR_GROUP_HAS_REFS(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS) +#define WXS_ATTR_GROUP_EXPANDED(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) +/* +* Macros for particles. +*/ +#define WXS_PARTICLE(p) WXS_PTC_CAST (p) + +#define WXS_PARTICLE_TERM(p) (WXS_PARTICLE(p))->children + +#define WXS_PARTICLE_TERM_AS_ELEM(p) (WXS_ELEM_CAST WXS_PARTICLE_TERM(p)) + +#define WXS_PARTICLE_MODEL(p) WXS_MODEL_GROUP_CAST WXS_PARTICLE(p)->children +/* +* Macros for model groups definitions. +*/ +#define WXS_MODELGROUPDEF_MODEL(mgd) (WXS_MODEL_GROUP_CAST (mgd))->children +/* +* Macros for model groups. +*/ +#define WXS_IS_MODEL_GROUP(i) \ + (((i)->type == XML_SCHEMA_TYPE_SEQUENCE) || \ + ((i)->type == XML_SCHEMA_TYPE_CHOICE) || \ + ((i)->type == XML_SCHEMA_TYPE_ALL)) + +#define WXS_MODELGROUP_PARTICLE(mg) WXS_PTC_CAST (mg)->children +/* +* Macros for schema buckets. +*/ +#define WXS_IS_BUCKET_INCREDEF(t) (((t) == XML_SCHEMA_SCHEMA_INCLUDE) || \ + ((t) == XML_SCHEMA_SCHEMA_REDEFINE)) + +#define WXS_IS_BUCKET_IMPMAIN(t) (((t) == XML_SCHEMA_SCHEMA_MAIN) || \ + ((t) == XML_SCHEMA_SCHEMA_IMPORT)) + +#define WXS_IMPBUCKET(b) ((xmlSchemaImportPtr) (b)) + +#define WXS_INCBUCKET(b) ((xmlSchemaIncludePtr) (b)) +/* +* Macros for complex/simple types. +*/ +#define WXS_IS_ANYTYPE(i) \ + (( (i)->type == XML_SCHEMA_TYPE_BASIC) && \ + ( (WXS_TYPE_CAST (i))->builtInType == XML_SCHEMAS_ANYTYPE)) + +#define WXS_IS_COMPLEX(i) \ + (((i)->type == XML_SCHEMA_TYPE_COMPLEX) || \ + ((i)->builtInType == XML_SCHEMAS_ANYTYPE)) + +#define WXS_IS_SIMPLE(item) \ + ((item->type == XML_SCHEMA_TYPE_SIMPLE) || \ + ((item->type == XML_SCHEMA_TYPE_BASIC) && \ + (item->builtInType != XML_SCHEMAS_ANYTYPE))) + +#define WXS_IS_ANY_SIMPLE_TYPE(i) \ + (((i)->type == XML_SCHEMA_TYPE_BASIC) && \ + ((i)->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) + +#define WXS_IS_RESTRICTION(t) \ + ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) + +#define WXS_IS_EXTENSION(t) \ + ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) + +#define WXS_IS_TYPE_NOT_FIXED(i) \ + (((i)->type != XML_SCHEMA_TYPE_BASIC) && \ + (((i)->flags & XML_SCHEMAS_TYPE_INTERNAL_RESOLVED) == 0)) + +#define WXS_IS_TYPE_NOT_FIXED_1(item) \ + (((item)->type != XML_SCHEMA_TYPE_BASIC) && \ + (((item)->flags & XML_SCHEMAS_TYPE_FIXUP_1) == 0)) + +#define WXS_TYPE_IS_GLOBAL(t) ((t)->flags & XML_SCHEMAS_TYPE_GLOBAL) + +#define WXS_TYPE_IS_LOCAL(t) (((t)->flags & XML_SCHEMAS_TYPE_GLOBAL) == 0) +/* +* Macros for exclusively for complex types. +*/ +#define WXS_HAS_COMPLEX_CONTENT(item) \ + ((item->contentType == XML_SCHEMA_CONTENT_MIXED) || \ + (item->contentType == XML_SCHEMA_CONTENT_EMPTY) || \ + (item->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) + +#define WXS_HAS_SIMPLE_CONTENT(item) \ + ((item->contentType == XML_SCHEMA_CONTENT_SIMPLE) || \ + (item->contentType == XML_SCHEMA_CONTENT_BASIC)) + +#define WXS_HAS_MIXED_CONTENT(item) \ + (item->contentType == XML_SCHEMA_CONTENT_MIXED) + +#define WXS_EMPTIABLE(t) \ + (xmlSchemaIsParticleEmptiable(WXS_PTC_CAST (t)->subtypes)) + +#define WXS_TYPE_CONTENTTYPE(t) (t)->subtypes + +#define WXS_TYPE_PARTICLE(t) WXS_PTC_CAST (t)->subtypes + +#define WXS_TYPE_PARTICLE_TERM(t) WXS_PARTICLE_TERM(WXS_TYPE_PARTICLE(t)) +/* +* Macros for exclusively for simple types. +*/ +#define WXS_LIST_ITEMTYPE(t) (t)->subtypes + +#define WXS_IS_ATOMIC(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) + +#define WXS_IS_LIST(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) + +#define WXS_IS_UNION(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) +/* +* Misc parser context macros. +*/ +#define WXS_CONSTRUCTOR(ctx) (ctx)->constructor + +#define WXS_HAS_BUCKETS(ctx) \ +( (WXS_CONSTRUCTOR((ctx))->buckets != NULL) && \ +(WXS_CONSTRUCTOR((ctx))->buckets->nbItems > 0) ) + +#define WXS_SUBST_GROUPS(ctx) WXS_CONSTRUCTOR((ctx))->substGroups + +#define WXS_BUCKET(ctx) WXS_CONSTRUCTOR((ctx))->bucket + +#define WXS_SCHEMA(ctx) (ctx)->schema + +#define WXS_ADD_LOCAL(ctx, item) \ + xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->locals), 10, item) + +#define WXS_ADD_GLOBAL(ctx, item) \ + xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->globals), 5, item) + +#define WXS_ADD_PENDING(ctx, item) \ + xmlSchemaAddItemSize(&((ctx)->constructor->pending), 10, item) +/* +* xmlSchemaItemList macros. +*/ +#define WXS_ILIST_IS_EMPTY(l) ((l == NULL) || ((l)->nbItems == 0)) +/* +* Misc macros. +*/ +#define IS_SCHEMA(node, type) \ + ((node != NULL) && (node->ns != NULL) && \ + (xmlStrEqual(node->name, (const xmlChar *) type)) && \ + (xmlStrEqual(node->ns->href, xmlSchemaNs))) + +#define FREE_AND_NULL(str) if ((str) != NULL) { xmlFree((xmlChar *) (str)); str = NULL; } + +/* +* Since we put the default/fixed values into the dict, we can +* use pointer comparison for those values. +* REMOVED: (xmlStrEqual((v1), (v2))) +*/ +#define WXS_ARE_DEFAULT_STR_EQUAL(v1, v2) ((v1) == (v2)) + +#define INODE_NILLED(item) (item->flags & XML_SCHEMA_ELEM_INFO_NILLED) + +#define CAN_PARSE_SCHEMA(b) (((b)->doc != NULL) && ((b)->parsed == 0)) + +#define HFAILURE if (res == -1) goto exit_failure; + +#define HERROR if (res != 0) goto exit_error; + +#define HSTOP(ctx) if ((ctx)->stop) goto exit; +/* +* Some flags used for various schema constraints. +*/ +#define SUBSET_RESTRICTION 1<<0 +#define SUBSET_EXTENSION 1<<1 +#define SUBSET_SUBSTITUTION 1<<2 +#define SUBSET_LIST 1<<3 +#define SUBSET_UNION 1<<4 + +typedef struct _xmlSchemaNodeInfo xmlSchemaNodeInfo; +typedef xmlSchemaNodeInfo *xmlSchemaNodeInfoPtr; + +typedef struct _xmlSchemaItemList xmlSchemaItemList; +typedef xmlSchemaItemList *xmlSchemaItemListPtr; +struct _xmlSchemaItemList { + void **items; /* used for dynamic addition of schemata */ + int nbItems; /* used for dynamic addition of schemata */ + int sizeItems; /* used for dynamic addition of schemata */ +}; + +#define XML_SCHEMA_CTXT_PARSER 1 +#define XML_SCHEMA_CTXT_VALIDATOR 2 + +typedef struct _xmlSchemaAbstractCtxt xmlSchemaAbstractCtxt; +typedef xmlSchemaAbstractCtxt *xmlSchemaAbstractCtxtPtr; +struct _xmlSchemaAbstractCtxt { + int type; /* E.g. XML_SCHEMA_CTXT_VALIDATOR */ +}; + +typedef struct _xmlSchemaBucket xmlSchemaBucket; +typedef xmlSchemaBucket *xmlSchemaBucketPtr; + +#define XML_SCHEMA_SCHEMA_MAIN 0 +#define XML_SCHEMA_SCHEMA_IMPORT 1 +#define XML_SCHEMA_SCHEMA_INCLUDE 2 +#define XML_SCHEMA_SCHEMA_REDEFINE 3 + +/** + * xmlSchemaSchemaRelation: + * + * Used to create a graph of schema relationships. + */ +typedef struct _xmlSchemaSchemaRelation xmlSchemaSchemaRelation; +typedef xmlSchemaSchemaRelation *xmlSchemaSchemaRelationPtr; +struct _xmlSchemaSchemaRelation { + xmlSchemaSchemaRelationPtr next; + int type; /* E.g. XML_SCHEMA_SCHEMA_IMPORT */ + const xmlChar *importNamespace; + xmlSchemaBucketPtr bucket; +}; + +#define XML_SCHEMA_BUCKET_MARKED 1<<0 +#define XML_SCHEMA_BUCKET_COMPS_ADDED 1<<1 + +struct _xmlSchemaBucket { + int type; + int flags; + const xmlChar *schemaLocation; + const xmlChar *origTargetNamespace; + const xmlChar *targetNamespace; + xmlDocPtr doc; + xmlSchemaSchemaRelationPtr relations; + int located; + int parsed; + int imported; + int preserveDoc; + xmlSchemaItemListPtr globals; /* Global components. */ + xmlSchemaItemListPtr locals; /* Local components. */ +}; + +/** + * xmlSchemaImport: + * (extends xmlSchemaBucket) + * + * Reflects a schema. Holds some information + * about the schema and its toplevel components. Duplicate + * toplevel components are not checked at this level. + */ +typedef struct _xmlSchemaImport xmlSchemaImport; +typedef xmlSchemaImport *xmlSchemaImportPtr; +struct _xmlSchemaImport { + int type; /* Main OR import OR include. */ + int flags; + const xmlChar *schemaLocation; /* The URI of the schema document. */ + /* For chameleon includes, @origTargetNamespace will be NULL */ + const xmlChar *origTargetNamespace; + /* + * For chameleon includes, @targetNamespace will be the + * targetNamespace of the including schema. + */ + const xmlChar *targetNamespace; + xmlDocPtr doc; /* The schema node-tree. */ + /* @relations will hold any included/imported/redefined schemas. */ + xmlSchemaSchemaRelationPtr relations; + int located; + int parsed; + int imported; + int preserveDoc; + xmlSchemaItemListPtr globals; + xmlSchemaItemListPtr locals; + /* The imported schema. */ + xmlSchemaPtr schema; +}; + +/* +* (extends xmlSchemaBucket) +*/ +typedef struct _xmlSchemaInclude xmlSchemaInclude; +typedef xmlSchemaInclude *xmlSchemaIncludePtr; +struct _xmlSchemaInclude { + int type; + int flags; + const xmlChar *schemaLocation; + const xmlChar *origTargetNamespace; + const xmlChar *targetNamespace; + xmlDocPtr doc; + xmlSchemaSchemaRelationPtr relations; + int located; + int parsed; + int imported; + int preserveDoc; + xmlSchemaItemListPtr globals; /* Global components. */ + xmlSchemaItemListPtr locals; /* Local components. */ + + /* The owning main or import schema bucket. */ + xmlSchemaImportPtr ownerImport; +}; + +/** + * xmlSchemaBasicItem: + * + * The abstract base type for schema components. + */ +typedef struct _xmlSchemaBasicItem xmlSchemaBasicItem; +typedef xmlSchemaBasicItem *xmlSchemaBasicItemPtr; +struct _xmlSchemaBasicItem { + xmlSchemaTypeType type; +}; + +/** + * xmlSchemaAnnotItem: + * + * The abstract base type for annotated schema components. + * (Extends xmlSchemaBasicItem) + */ +typedef struct _xmlSchemaAnnotItem xmlSchemaAnnotItem; +typedef xmlSchemaAnnotItem *xmlSchemaAnnotItemPtr; +struct _xmlSchemaAnnotItem { + xmlSchemaTypeType type; + xmlSchemaAnnotPtr annot; +}; + +/** + * xmlSchemaTreeItem: + * + * The abstract base type for tree-like structured schema components. + * (Extends xmlSchemaAnnotItem) + */ +typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem; +typedef xmlSchemaTreeItem *xmlSchemaTreeItemPtr; +struct _xmlSchemaTreeItem { + xmlSchemaTypeType type; + xmlSchemaAnnotPtr annot; + xmlSchemaTreeItemPtr next; + xmlSchemaTreeItemPtr children; +}; + + +#define XML_SCHEMA_ATTR_USE_FIXED 1<<0 +/** + * xmlSchemaAttributeUsePtr: + * + * The abstract base type for tree-like structured schema components. + * (Extends xmlSchemaTreeItem) + */ +typedef struct _xmlSchemaAttributeUse xmlSchemaAttributeUse; +typedef xmlSchemaAttributeUse *xmlSchemaAttributeUsePtr; +struct _xmlSchemaAttributeUse { + xmlSchemaTypeType type; + xmlSchemaAnnotPtr annot; + xmlSchemaAttributeUsePtr next; /* The next attr. use. */ + /* + * The attr. decl. OR a QName-ref. to an attr. decl. OR + * a QName-ref. to an attribute group definition. + */ + xmlSchemaAttributePtr attrDecl; + + int flags; + xmlNodePtr node; + int occurs; /* required, optional */ + const xmlChar * defValue; + xmlSchemaValPtr defVal; +}; + +/** + * xmlSchemaAttributeUseProhibPtr: + * + * A helper component to reflect attribute prohibitions. + * (Extends xmlSchemaBasicItem) + */ +typedef struct _xmlSchemaAttributeUseProhib xmlSchemaAttributeUseProhib; +typedef xmlSchemaAttributeUseProhib *xmlSchemaAttributeUseProhibPtr; +struct _xmlSchemaAttributeUseProhib { + xmlSchemaTypeType type; /* == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB */ + xmlNodePtr node; + const xmlChar *name; + const xmlChar *targetNamespace; + int isRef; +}; + +/** + * xmlSchemaRedef: + */ +typedef struct _xmlSchemaRedef xmlSchemaRedef; +typedef xmlSchemaRedef *xmlSchemaRedefPtr; +struct _xmlSchemaRedef { + xmlSchemaRedefPtr next; + xmlSchemaBasicItemPtr item; /* The redefining component. */ + xmlSchemaBasicItemPtr reference; /* The referencing component. */ + xmlSchemaBasicItemPtr target; /* The to-be-redefined component. */ + const xmlChar *refName; /* The name of the to-be-redefined component. */ + const xmlChar *refTargetNs; /* The target namespace of the + to-be-redefined comp. */ + xmlSchemaBucketPtr targetBucket; /* The redefined schema. */ +}; + +/** + * xmlSchemaConstructionCtxt: + */ +typedef struct _xmlSchemaConstructionCtxt xmlSchemaConstructionCtxt; +typedef xmlSchemaConstructionCtxt *xmlSchemaConstructionCtxtPtr; +struct _xmlSchemaConstructionCtxt { + xmlSchemaPtr mainSchema; /* The main schema. */ + xmlSchemaBucketPtr mainBucket; /* The main schema bucket */ + xmlDictPtr dict; + xmlSchemaItemListPtr buckets; /* List of schema buckets. */ + /* xmlSchemaItemListPtr relations; */ /* List of schema relations. */ + xmlSchemaBucketPtr bucket; /* The current schema bucket */ + xmlSchemaItemListPtr pending; /* All Components of all schemas that + need to be fixed. */ + xmlHashTablePtr substGroups; + xmlSchemaRedefPtr redefs; + xmlSchemaRedefPtr lastRedef; +}; + +#define XML_SCHEMAS_PARSE_ERROR 1 +#define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT + +struct _xmlSchemaParserCtxt { + int type; + void *errCtxt; /* user specific error context */ + xmlSchemaValidityErrorFunc error; /* the callback in case of errors */ + xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */ + int err; + int nberrors; + xmlStructuredErrorFunc serror; + + xmlSchemaConstructionCtxtPtr constructor; + int ownsConstructor; /* TODO: Move this to parser *flags*. */ + + /* xmlSchemaPtr topschema; */ + /* xmlHashTablePtr namespaces; */ + + xmlSchemaPtr schema; /* The main schema in use */ + int counter; + + const xmlChar *URL; + xmlDocPtr doc; + int preserve; /* Whether the doc should be freed */ + + const char *buffer; + int size; + + /* + * Used to build complex element content models + */ + xmlAutomataPtr am; + xmlAutomataStatePtr start; + xmlAutomataStatePtr end; + xmlAutomataStatePtr state; + + xmlDictPtr dict; /* dictionnary for interned string names */ + xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */ + int options; + xmlSchemaValidCtxtPtr vctxt; + int isS4S; + int isRedefine; + int xsiAssemble; + int stop; /* If the parser should stop; i.e. a critical error. */ + const xmlChar *targetNamespace; + xmlSchemaBucketPtr redefined; /* The schema to be redefined. */ + + xmlSchemaRedefPtr redef; /* Used for redefinitions. */ + int redefCounter; /* Used for redefinitions. */ + xmlSchemaItemListPtr attrProhibs; +}; + +/** + * xmlSchemaQNameRef: + * + * A component reference item (not a schema component) + * (Extends xmlSchemaBasicItem) + */ +typedef struct _xmlSchemaQNameRef xmlSchemaQNameRef; +typedef xmlSchemaQNameRef *xmlSchemaQNameRefPtr; +struct _xmlSchemaQNameRef { + xmlSchemaTypeType type; + xmlSchemaBasicItemPtr item; /* The resolved referenced item. */ + xmlSchemaTypeType itemType; + const xmlChar *name; + const xmlChar *targetNamespace; + xmlNodePtr node; +}; + +/** + * xmlSchemaParticle: + * + * A particle component. + * (Extends xmlSchemaTreeItem) + */ +typedef struct _xmlSchemaParticle xmlSchemaParticle; +typedef xmlSchemaParticle *xmlSchemaParticlePtr; +struct _xmlSchemaParticle { + xmlSchemaTypeType type; + xmlSchemaAnnotPtr annot; + xmlSchemaTreeItemPtr next; /* next particle */ + xmlSchemaTreeItemPtr children; /* the "term" (e.g. a model group, + a group definition, a XML_SCHEMA_EXTRA_QNAMEREF (if a reference), + etc.) */ + int minOccurs; + int maxOccurs; + xmlNodePtr node; +}; + +/** + * xmlSchemaModelGroup: + * + * A model group component. + * (Extends xmlSchemaTreeItem) + */ +typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup; +typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr; +struct _xmlSchemaModelGroup { + xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_SEQUENCE, XML_SCHEMA_TYPE_CHOICE, XML_SCHEMA_TYPE_ALL */ + xmlSchemaAnnotPtr annot; + xmlSchemaTreeItemPtr next; /* not used */ + xmlSchemaTreeItemPtr children; /* first particle (OR "element decl" OR "wildcard") */ + xmlNodePtr node; +}; + +#define XML_SCHEMA_MODEL_GROUP_DEF_MARKED 1<<0 +#define XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED 1<<1 +/** + * xmlSchemaModelGroupDef: + * + * A model group definition component. + * (Extends xmlSchemaTreeItem) + */ +typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef; +typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr; +struct _xmlSchemaModelGroupDef { + xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_GROUP */ + xmlSchemaAnnotPtr annot; + xmlSchemaTreeItemPtr next; /* not used */ + xmlSchemaTreeItemPtr children; /* the "model group" */ + const xmlChar *name; + const xmlChar *targetNamespace; + xmlNodePtr node; + int flags; +}; + +typedef struct _xmlSchemaIDC xmlSchemaIDC; +typedef xmlSchemaIDC *xmlSchemaIDCPtr; + +/** + * xmlSchemaIDCSelect: + * + * The identity-constraint "field" and "selector" item, holding the + * XPath expression. + */ +typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect; +typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr; +struct _xmlSchemaIDCSelect { + xmlSchemaIDCSelectPtr next; + xmlSchemaIDCPtr idc; + int index; /* an index position if significant for IDC key-sequences */ + const xmlChar *xpath; /* the XPath expression */ + void *xpathComp; /* the compiled XPath expression */ +}; + +/** + * xmlSchemaIDC: + * + * The identity-constraint definition component. + * (Extends xmlSchemaAnnotItem) + */ + +struct _xmlSchemaIDC { + xmlSchemaTypeType type; + xmlSchemaAnnotPtr annot; + xmlSchemaIDCPtr next; + xmlNodePtr node; + const xmlChar *name; + const xmlChar *targetNamespace; + xmlSchemaIDCSelectPtr selector; + xmlSchemaIDCSelectPtr fields; + int nbFields; + xmlSchemaQNameRefPtr ref; +}; + +/** + * xmlSchemaIDCAug: + * + * The augmented IDC information used for validation. + */ +typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug; +typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr; +struct _xmlSchemaIDCAug { + xmlSchemaIDCAugPtr next; /* next in a list */ + xmlSchemaIDCPtr def; /* the IDC definition */ + int keyrefDepth; /* the lowest tree level to which IDC + tables need to be bubbled upwards */ +}; + +/** + * xmlSchemaPSVIIDCKeySequence: + * + * The key sequence of a node table item. + */ +typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey; +typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr; +struct _xmlSchemaPSVIIDCKey { + xmlSchemaTypePtr type; + xmlSchemaValPtr val; +}; + +/** + * xmlSchemaPSVIIDCNode: + * + * The node table item of a node table. + */ +typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode; +typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr; +struct _xmlSchemaPSVIIDCNode { + xmlNodePtr node; + xmlSchemaPSVIIDCKeyPtr *keys; + int nodeLine; + int nodeQNameID; + +}; + +/** + * xmlSchemaPSVIIDCBinding: + * + * The identity-constraint binding item of the [identity-constraint table]. + */ +typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding; +typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr; +struct _xmlSchemaPSVIIDCBinding { + xmlSchemaPSVIIDCBindingPtr next; /* next binding of a specific node */ + xmlSchemaIDCPtr definition; /* the IDC definition */ + xmlSchemaPSVIIDCNodePtr *nodeTable; /* array of key-sequences */ + int nbNodes; /* number of entries in the node table */ + int sizeNodes; /* size of the node table */ + xmlSchemaItemListPtr dupls; +}; + + +#define XPATH_STATE_OBJ_TYPE_IDC_SELECTOR 1 +#define XPATH_STATE_OBJ_TYPE_IDC_FIELD 2 + +#define XPATH_STATE_OBJ_MATCHES -2 +#define XPATH_STATE_OBJ_BLOCKED -3 + +typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher; +typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr; + +/** + * xmlSchemaIDCStateObj: + * + * The state object used to evaluate XPath expressions. + */ +typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj; +typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr; +struct _xmlSchemaIDCStateObj { + int type; + xmlSchemaIDCStateObjPtr next; /* next if in a list */ + int depth; /* depth of creation */ + int *history; /* list of (depth, state-id) tuples */ + int nbHistory; + int sizeHistory; + xmlSchemaIDCMatcherPtr matcher; /* the correspondent field/selector + matcher */ + xmlSchemaIDCSelectPtr sel; + void *xpathCtxt; +}; + +#define IDC_MATCHER 0 + +/** + * xmlSchemaIDCMatcher: + * + * Used to evaluate IDC selectors (and fields). + */ +struct _xmlSchemaIDCMatcher { + int type; + int depth; /* the tree depth at creation time */ + xmlSchemaIDCMatcherPtr next; /* next in the list */ + xmlSchemaIDCMatcherPtr nextCached; /* next in the cache list */ + xmlSchemaIDCAugPtr aidc; /* the augmented IDC item */ + int idcType; + xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target + elements */ + int sizeKeySeqs; + xmlSchemaItemListPtr targets; /* list of target-node + (xmlSchemaPSVIIDCNodePtr) entries */ +}; + +/* +* Element info flags. +*/ +#define XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES 1<<0 +#define XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES 1<<1 +#define XML_SCHEMA_ELEM_INFO_NILLED 1<<2 +#define XML_SCHEMA_ELEM_INFO_LOCAL_TYPE 1<<3 + +#define XML_SCHEMA_NODE_INFO_VALUE_NEEDED 1<<4 +#define XML_SCHEMA_ELEM_INFO_EMPTY 1<<5 +#define XML_SCHEMA_ELEM_INFO_HAS_CONTENT 1<<6 + +#define XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT 1<<7 +#define XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT 1<<8 +#define XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED 1<<9 +#define XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE 1<<10 + +/** + * xmlSchemaNodeInfo: + * + * Holds information of an element node. + */ +struct _xmlSchemaNodeInfo { + int nodeType; + xmlNodePtr node; + int nodeLine; + const xmlChar *localName; + const xmlChar *nsName; + const xmlChar *value; + xmlSchemaValPtr val; /* the pre-computed value if any */ + xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */ + + int flags; /* combination of node info flags */ + + int valNeeded; + int normVal; + + xmlSchemaElementPtr decl; /* the element/attribute declaration */ + int depth; + xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings + for the scope element*/ + xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope + element */ + xmlRegExecCtxtPtr regexCtxt; + + const xmlChar **nsBindings; /* Namespace bindings on this element */ + int nbNsBindings; + int sizeNsBindings; + + int hasKeyrefs; + int appliedXPath; /* Indicates that an XPath has been applied. */ +}; + +#define XML_SCHEMAS_ATTR_UNKNOWN 1 +#define XML_SCHEMAS_ATTR_ASSESSED 2 +#define XML_SCHEMAS_ATTR_PROHIBITED 3 +#define XML_SCHEMAS_ATTR_ERR_MISSING 4 +#define XML_SCHEMAS_ATTR_INVALID_VALUE 5 +#define XML_SCHEMAS_ATTR_ERR_NO_TYPE 6 +#define XML_SCHEMAS_ATTR_ERR_FIXED_VALUE 7 +#define XML_SCHEMAS_ATTR_DEFAULT 8 +#define XML_SCHEMAS_ATTR_VALIDATE_VALUE 9 +#define XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL 10 +#define XML_SCHEMAS_ATTR_HAS_ATTR_USE 11 +#define XML_SCHEMAS_ATTR_HAS_ATTR_DECL 12 +#define XML_SCHEMAS_ATTR_WILD_SKIP 13 +#define XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL 14 +#define XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID 15 +#define XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID 16 +#define XML_SCHEMAS_ATTR_META 17 +/* +* @metaType values of xmlSchemaAttrInfo. +*/ +#define XML_SCHEMA_ATTR_INFO_META_XSI_TYPE 1 +#define XML_SCHEMA_ATTR_INFO_META_XSI_NIL 2 +#define XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC 3 +#define XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC 4 +#define XML_SCHEMA_ATTR_INFO_META_XMLNS 5 + +typedef struct _xmlSchemaAttrInfo xmlSchemaAttrInfo; +typedef xmlSchemaAttrInfo *xmlSchemaAttrInfoPtr; +struct _xmlSchemaAttrInfo { + int nodeType; + xmlNodePtr node; + int nodeLine; + const xmlChar *localName; + const xmlChar *nsName; + const xmlChar *value; + xmlSchemaValPtr val; /* the pre-computed value if any */ + xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */ + int flags; /* combination of node info flags */ + + xmlSchemaAttributePtr decl; /* the attribute declaration */ + xmlSchemaAttributeUsePtr use; /* the attribute use */ + int state; + int metaType; + const xmlChar *vcValue; /* the value constraint value */ + xmlSchemaNodeInfoPtr parent; +}; + + +#define XML_SCHEMA_VALID_CTXT_FLAG_STREAM 1 +/** + * xmlSchemaValidCtxt: + * + * A Schemas validation context + */ +struct _xmlSchemaValidCtxt { + int type; + void *errCtxt; /* user specific data block */ + xmlSchemaValidityErrorFunc error; /* the callback in case of errors */ + xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */ + xmlStructuredErrorFunc serror; + + xmlSchemaPtr schema; /* The schema in use */ + xmlDocPtr doc; + xmlParserInputBufferPtr input; + xmlCharEncoding enc; + xmlSAXHandlerPtr sax; + xmlParserCtxtPtr parserCtxt; + void *user_data; /* TODO: What is this for? */ + + int err; + int nberrors; + + xmlNodePtr node; + xmlNodePtr cur; + /* xmlSchemaTypePtr type; */ + + xmlRegExecCtxtPtr regexp; + xmlSchemaValPtr value; + + int valueWS; + int options; + xmlNodePtr validationRoot; + xmlSchemaParserCtxtPtr pctxt; + int xsiAssemble; + + int depth; + xmlSchemaNodeInfoPtr *elemInfos; /* array of element informations */ + int sizeElemInfos; + xmlSchemaNodeInfoPtr inode; /* the current element information */ + + xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC informations */ + + xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */ + xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */ + xmlSchemaIDCMatcherPtr idcMatcherCache; /* Cache for IDC matcher objects. */ + + xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/ + int nbIdcNodes; + int sizeIdcNodes; + + xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */ + int nbIdcKeys; + int sizeIdcKeys; + + int flags; + + xmlDictPtr dict; + +#ifdef LIBXML_READER_ENABLED + xmlTextReaderPtr reader; +#endif + + xmlSchemaAttrInfoPtr *attrInfos; + int nbAttrInfos; + int sizeAttrInfos; + + int skipDepth; + xmlSchemaItemListPtr nodeQNames; + int hasKeyrefs; + int createIDCNodeTables; + int psviExposeIDCNodeTables; +}; + +/** + * xmlSchemaSubstGroup: + * + * + */ +typedef struct _xmlSchemaSubstGroup xmlSchemaSubstGroup; +typedef xmlSchemaSubstGroup *xmlSchemaSubstGroupPtr; +struct _xmlSchemaSubstGroup { + xmlSchemaElementPtr head; + xmlSchemaItemListPtr members; +}; + +/************************************************************************ + * * + * Some predeclarations * + * * + ************************************************************************/ + +static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, + xmlSchemaPtr schema, + xmlNodePtr node); +static int xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr ctxt, + xmlSchemaPtr schema, + xmlNodePtr node); +static int +xmlSchemaTypeFixup(xmlSchemaTypePtr type, + xmlSchemaAbstractCtxtPtr ctxt); +static const xmlChar * +xmlSchemaFacetTypeToString(xmlSchemaTypeType type); +static int +xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, + xmlNodePtr node); +static int +xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl, + xmlSchemaParserCtxtPtr ctxt); +static void +xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt); +static xmlSchemaWhitespaceValueType +xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type); +static xmlSchemaTreeItemPtr +xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, + xmlNodePtr node, xmlSchemaTypeType type, + int withParticle); +static const xmlChar * +xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item); +static xmlSchemaTypeLinkPtr +xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type); +static void +xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt, + const char *funcName, + const char *message); +static int +xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr ctxt, + xmlSchemaTypePtr type, + xmlSchemaTypePtr baseType, + int subset); +static void +xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl, + xmlSchemaParserCtxtPtr ctxt); +static void +xmlSchemaComponentListFree(xmlSchemaItemListPtr list); +static xmlSchemaQNameRefPtr +xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt, + xmlSchemaPtr schema, + xmlNodePtr node); + +/************************************************************************ + * * + * Helper functions * + * * + ************************************************************************/ + +/** + * xmlSchemaItemTypeToStr: + * @type: the type of the schema item + * + * Returns the component name of a schema item. + */ +static const xmlChar * +xmlSchemaItemTypeToStr(xmlSchemaTypeType type) +{ + switch (type) { + case XML_SCHEMA_TYPE_BASIC: + return(BAD_CAST "simple type definition"); + case XML_SCHEMA_TYPE_SIMPLE: + return(BAD_CAST "simple type definition"); + case XML_SCHEMA_TYPE_COMPLEX: + return(BAD_CAST "complex type definition"); + case XML_SCHEMA_TYPE_ELEMENT: + return(BAD_CAST "element declaration"); + case XML_SCHEMA_TYPE_ATTRIBUTE_USE: + return(BAD_CAST "attribute use"); + case XML_SCHEMA_TYPE_ATTRIBUTE: + return(BAD_CAST "attribute declaration"); + case XML_SCHEMA_TYPE_GROUP: + return(BAD_CAST "model group definition"); + case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: + return(BAD_CAST "attribute group definition"); + case XML_SCHEMA_TYPE_NOTATION: + return(BAD_CAST "notation declaration"); + case XML_SCHEMA_TYPE_SEQUENCE: + return(BAD_CAST "model group (sequence)"); + case XML_SCHEMA_TYPE_CHOICE: + return(BAD_CAST "model group (choice)"); + case XML_SCHEMA_TYPE_ALL: + return(BAD_CAST "model group (all)"); + case XML_SCHEMA_TYPE_PARTICLE: + return(BAD_CAST "particle"); + case XML_SCHEMA_TYPE_IDC_UNIQUE: + return(BAD_CAST "unique identity-constraint"); + /* return(BAD_CAST "IDC (unique)"); */ + case XML_SCHEMA_TYPE_IDC_KEY: + return(BAD_CAST "key identity-constraint"); + /* return(BAD_CAST "IDC (key)"); */ + case XML_SCHEMA_TYPE_IDC_KEYREF: + return(BAD_CAST "keyref identity-constraint"); + /* return(BAD_CAST "IDC (keyref)"); */ + case XML_SCHEMA_TYPE_ANY: + return(BAD_CAST "wildcard (any)"); + case XML_SCHEMA_EXTRA_QNAMEREF: + return(BAD_CAST "[helper component] QName reference"); + case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB: + return(BAD_CAST "[helper component] attribute use prohibition"); + default: + return(BAD_CAST "Not a schema component"); + } +} + +/** + * xmlSchemaGetComponentTypeStr: + * @type: the type of the schema item + * + * Returns the component name of a schema item. + */ +static const xmlChar * +xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item) +{ + switch (item->type) { + case XML_SCHEMA_TYPE_BASIC: + if (WXS_IS_COMPLEX(WXS_TYPE_CAST item)) + return(BAD_CAST "complex type definition"); + else + return(BAD_CAST "simple type definition"); + default: + return(xmlSchemaItemTypeToStr(item->type)); + } +} + +/** + * xmlSchemaGetComponentNode: + * @item: a schema component + * + * Returns node associated with the schema component. + * NOTE that such a node need not be available; plus, a component's + * node need not to reflect the component directly, since there is no + * one-to-one relationship between the XML Schema representation and + * the component representation. + */ +static xmlNodePtr +xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item) +{ + switch (item->type) { + case XML_SCHEMA_TYPE_ELEMENT: + return (((xmlSchemaElementPtr) item)->node); + case XML_SCHEMA_TYPE_ATTRIBUTE: + return (((xmlSchemaAttributePtr) item)->node); + case XML_SCHEMA_TYPE_COMPLEX: + case XML_SCHEMA_TYPE_SIMPLE: + return (((xmlSchemaTypePtr) item)->node); + case XML_SCHEMA_TYPE_ANY: + case XML_SCHEMA_TYPE_ANY_ATTRIBUTE: + return (((xmlSchemaWildcardPtr) item)->node); + case XML_SCHEMA_TYPE_PARTICLE: + return (((xmlSchemaParticlePtr) item)->node); + case XML_SCHEMA_TYPE_SEQUENCE: + case XML_SCHEMA_TYPE_CHOICE: + case XML_SCHEMA_TYPE_ALL: + return (((xmlSchemaModelGroupPtr) item)->node); + case XML_SCHEMA_TYPE_GROUP: + return (((xmlSchemaModelGroupDefPtr) item)->node); + case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: + return (((xmlSchemaAttributeGroupPtr) item)->node); + case XML_SCHEMA_TYPE_IDC_UNIQUE: + case XML_SCHEMA_TYPE_IDC_KEY: + case XML_SCHEMA_TYPE_IDC_KEYREF: + return (((xmlSchemaIDCPtr) item)->node); + case XML_SCHEMA_EXTRA_QNAMEREF: + return(((xmlSchemaQNameRefPtr) item)->node); + /* TODO: What to do with NOTATIONs? + case XML_SCHEMA_TYPE_NOTATION: + return (((xmlSchemaNotationPtr) item)->node); + */ + case XML_SCHEMA_TYPE_ATTRIBUTE_USE: + return (((xmlSchemaAttributeUsePtr) item)->node); + default: + return (NULL); + } +} + +#if 0 +/** + * xmlSchemaGetNextComponent: + * @item: a schema component + * + * Returns the next sibling of the schema component. + */ +static xmlSchemaBasicItemPtr +xmlSchemaGetNextComponent(xmlSchemaBasicItemPtr item) +{ + switch (item->type) { + case XML_SCHEMA_TYPE_ELEMENT: + return ((xmlSchemaBasicItemPtr) ((xmlSchemaElementPtr) item)->next); + case XML_SCHEMA_TYPE_ATTRIBUTE: + return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributePtr) item)->next); + case XML_SCHEMA_TYPE_COMPLEX: + case XML_SCHEMA_TYPE_SIMPLE: + return ((xmlSchemaBasicItemPtr) ((xmlSchemaTypePtr) item)->next); + case XML_SCHEMA_TYPE_ANY: + case XML_SCHEMA_TYPE_ANY_ATTRIBUTE: + return (NULL); + case XML_SCHEMA_TYPE_PARTICLE: + return ((xmlSchemaBasicItemPtr) ((xmlSchemaParticlePtr) item)->next); + case XML_SCHEMA_TYPE_SEQUENCE: + case XML_SCHEMA_TYPE_CHOICE: + case XML_SCHEMA_TYPE_ALL: + return (NULL); + case XML_SCHEMA_TYPE_GROUP: + return (NULL); + case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: + return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributeGroupPtr) item)->next); + case XML_SCHEMA_TYPE_IDC_UNIQUE: + case XML_SCHEMA_TYPE_IDC_KEY: + case XML_SCHEMA_TYPE_IDC_KEYREF: + return ((xmlSchemaBasicItemPtr) ((xmlSchemaIDCPtr) item)->next); + default: + return (NULL); + } +} +#endif + + +/** + * xmlSchemaFormatQName: + * @buf: the string buffer + * @namespaceName: the namespace name + * @localName: the local name + * + * Returns the given QName in the format "{namespaceName}localName" or + * just "localName" if @namespaceName is NULL. + * + * Returns the localName if @namespaceName is NULL, a formatted + * string otherwise. + */ +static const xmlChar* +xmlSchemaFormatQName(xmlChar **buf, + const xmlChar *namespaceName, + const xmlChar *localName) +{ + FREE_AND_NULL(*buf) + if (namespaceName != NULL) { + *buf = xmlStrdup(BAD_CAST "{"); + *buf = xmlStrcat(*buf, namespaceName); + *buf = xmlStrcat(*buf, BAD_CAST "}"); + } + if (localName != NULL) { + if (namespaceName == NULL) + return(localName); + *buf = xmlStrcat(*buf, localName); + } else { + *buf = xmlStrcat(*buf, BAD_CAST "(NULL)"); + } + return ((const xmlChar *) *buf); +} + +static const xmlChar* +xmlSchemaFormatQNameNs(xmlChar **buf, xmlNsPtr ns, const xmlChar *localName) +{ + if (ns != NULL) + return (xmlSchemaFormatQName(buf, ns->href, localName)); + else + return (xmlSchemaFormatQName(buf, NULL, localName)); +} + +static const xmlChar * +xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item) +{ + switch (item->type) { + case XML_SCHEMA_TYPE_ELEMENT: + return (((xmlSchemaElementPtr) item)->name); + case XML_SCHEMA_TYPE_ATTRIBUTE: + return (((xmlSchemaAttributePtr) item)->name); + case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: + return (((xmlSchemaAttributeGroupPtr) item)->name); + case XML_SCHEMA_TYPE_BASIC: + case XML_SCHEMA_TYPE_SIMPLE: + case XML_SCHEMA_TYPE_COMPLEX: + return (((xmlSchemaTypePtr) item)->name); + case XML_SCHEMA_TYPE_GROUP: + return (((xmlSchemaModelGroupDefPtr) item)->name); + case XML_SCHEMA_TYPE_IDC_KEY: + case XML_SCHEMA_TYPE_IDC_UNIQUE: + case XML_SCHEMA_TYPE_IDC_KEYREF: + return (((xmlSchemaIDCPtr) item)->name); + case XML_SCHEMA_TYPE_ATTRIBUTE_USE: + if (WXS_ATTRUSE_DECL(item) != NULL) { + return(xmlSchemaGetComponentName( + WXS_BASIC_CAST WXS_ATTRUSE_DECL(item))); + } else + return(NULL); + case XML_SCHEMA_EXTRA_QNAMEREF: + return (((xmlSchemaQNameRefPtr) item)->name); + case XML_SCHEMA_TYPE_NOTATION: + return (((xmlSchemaNotationPtr) item)->name); + default: + /* + * Other components cannot have names. + */ + break; + } + return (NULL); +} + +#define xmlSchemaGetQNameRefName(r) (WXS_QNAME_CAST (r))->name +#define xmlSchemaGetQNameRefTargetNs(r) (WXS_QNAME_CAST (r))->targetNamespace +/* +static const xmlChar * +xmlSchemaGetQNameRefName(void *ref) +{ + return(((xmlSchemaQNameRefPtr) ref)->name); +} + +static const xmlChar * +xmlSchemaGetQNameRefTargetNs(void *ref) +{ + return(((xmlSchemaQNameRefPtr) ref)->targetNamespace); +} +*/ + +static const xmlChar * +xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item) +{ + switch (item->type) { + case XML_SCHEMA_TYPE_ELEMENT: + return (((xmlSchemaElementPtr) item)->targetNamespace); + case XML_SCHEMA_TYPE_ATTRIBUTE: + return (((xmlSchemaAttributePtr) item)->targetNamespace); + case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: + return (((xmlSchemaAttributeGroupPtr) item)->targetNamespace); + case XML_SCHEMA_TYPE_BASIC: + return (BAD_CAST "http://www.w3.org/2001/XMLSchema"); + case XML_SCHEMA_TYPE_SIMPLE: + case XML_SCHEMA_TYPE_COMPLEX: + return (((xmlSchemaTypePtr) item)->targetNamespace); + case XML_SCHEMA_TYPE_GROUP: + return (((xmlSchemaModelGroupDefPtr) item)->targetNamespace); + case XML_SCHEMA_TYPE_IDC_KEY: + case XML_SCHEMA_TYPE_IDC_UNIQUE: + case XML_SCHEMA_TYPE_IDC_KEYREF: + return (((xmlSchemaIDCPtr) item)->targetNamespace); + case XML_SCHEMA_TYPE_ATTRIBUTE_USE: + if (WXS_ATTRUSE_DECL(item) != NULL) { + return(xmlSchemaGetComponentTargetNs( + WXS_BASIC_CAST WXS_ATTRUSE_DECL(item))); + } + /* TODO: Will returning NULL break something? */ + break; + case XML_SCHEMA_EXTRA_QNAMEREF: + return (((xmlSchemaQNameRefPtr) item)->targetNamespace); + case XML_SCHEMA_TYPE_NOTATION: + return (((xmlSchemaNotationPtr) item)->targetNamespace); + default: + /* + * Other components cannot have names. + */ + break; + } + return (NULL); +} + +static const xmlChar* +xmlSchemaGetComponentQName(xmlChar **buf, + void *item) +{ + return (xmlSchemaFormatQName(buf, + xmlSchemaGetComponentTargetNs((xmlSchemaBasicItemPtr) item), + xmlSchemaGetComponentName((xmlSchemaBasicItemPtr) item))); +} + +static const xmlChar* +xmlSchemaGetComponentDesignation(xmlChar **buf, void *item) +{ + xmlChar *str = NULL; + + *buf = xmlStrcat(*buf, WXS_ITEM_TYPE_NAME(item)); + *buf = xmlStrcat(*buf, BAD_CAST " '"); + *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, + (xmlSchemaBasicItemPtr) item)); + *buf = xmlStrcat(*buf, BAD_CAST "'"); + FREE_AND_NULL(str); + return(*buf); +} + +static const xmlChar* +xmlSchemaGetIDCDesignation(xmlChar **buf, xmlSchemaIDCPtr idc) +{ + return(xmlSchemaGetComponentDesignation(buf, idc)); +} + +/** + * xmlSchemaWildcardPCToString: + * @pc: the type of processContents + * + * Returns a string representation of the type of + * processContents. + */ +static const xmlChar * +xmlSchemaWildcardPCToString(int pc) +{ + switch (pc) { + case XML_SCHEMAS_ANY_SKIP: + return (BAD_CAST "skip"); + case XML_SCHEMAS_ANY_LAX: + return (BAD_CAST "lax"); + case XML_SCHEMAS_ANY_STRICT: + return (BAD_CAST "strict"); + default: + return (BAD_CAST "invalid process contents"); + } +} + +/** + * xmlSchemaGetCanonValueWhtspExt: + * @val: the precomputed value + * @retValue: the returned value + * @ws: the whitespace type of the value + * + * Get a the cononical representation of the value. + * The caller has to free the returned retValue. + * + * Returns 0 if the value could be built and -1 in case of + * API errors or if the value type is not supported yet. + */ +static int +xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val, + xmlSchemaWhitespaceValueType ws, + xmlChar **retValue) +{ + int list; + xmlSchemaValType valType; + const xmlChar *value, *value2 = NULL; + + + if ((retValue == NULL) || (val == NULL)) + return (-1); + list = xmlSchemaValueGetNext(val) ? 1 : 0; + *retValue = NULL; + do { + value = NULL; + valType = xmlSchemaGetValType(val); + switch (valType) { + case XML_SCHEMAS_STRING: + case XML_SCHEMAS_NORMSTRING: + case XML_SCHEMAS_ANYSIMPLETYPE: + value = xmlSchemaValueGetAsString(val); + if (value != NULL) { + if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE) + value2 = xmlSchemaCollapseString(value); + else if (ws == XML_SCHEMA_WHITESPACE_REPLACE) + value2 = xmlSchemaWhiteSpaceReplace(value); + if (value2 != NULL) + value = value2; + } + break; + default: + if (xmlSchemaGetCanonValue(val, &value2) == -1) { + if (value2 != NULL) + xmlFree((xmlChar *) value2); + goto internal_error; + } + value = value2; + } + if (*retValue == NULL) + if (value == NULL) { + if (! list) + *retValue = xmlStrdup(BAD_CAST ""); + } else + *retValue = xmlStrdup(value); + else if (value != NULL) { + /* List. */ + *retValue = xmlStrcat((xmlChar *) *retValue, BAD_CAST " "); + *retValue = xmlStrcat((xmlChar *) *retValue, value); + } + FREE_AND_NULL(value2) + val = xmlSchemaValueGetNext(val); + } while (val != NULL); + + return (0); +internal_error: + if (*retValue != NULL) + xmlFree((xmlChar *) (*retValue)); + if (value2 != NULL) + xmlFree((xmlChar *) value2); + return (-1); +} + +/** + * xmlSchemaFormatItemForReport: + * @buf: the string buffer + * @itemDes: the designation of the item + * @itemName: the name of the item + * @item: the item as an object + * @itemNode: the node of the item + * @local: the local name + * @parsing: if the function is used during the parse + * + * Returns a representation of the given item used + * for error reports. + * + * The following order is used to build the resulting + * designation if the arguments are not NULL: + * 1a. If itemDes not NULL -> itemDes + * 1b. If (itemDes not NULL) and (itemName not NULL) + * -> itemDes + itemName + * 2. If the preceding was NULL and (item not NULL) -> item + * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode + * + * If the itemNode is an attribute node, the name of the attribute + * will be appended to the result. + * + * Returns the formatted string and sets @buf to the resulting value. + */ +static xmlChar* +xmlSchemaFormatItemForReport(xmlChar **buf, + const xmlChar *itemDes, + xmlSchemaBasicItemPtr item, + xmlNodePtr itemNode) +{ + xmlChar *str = NULL; + int named = 1; + + if (*buf != NULL) { + xmlFree(*buf); + *buf = NULL; + } + + if (itemDes != NULL) { + *buf = xmlStrdup(itemDes); + } else if (item != NULL) { + switch (item->type) { + case XML_SCHEMA_TYPE_BASIC: { + xmlSchemaTypePtr type = WXS_TYPE_CAST item; + + if (WXS_IS_ATOMIC(type)) + *buf = xmlStrdup(BAD_CAST "atomic type 'xs:"); + else if (WXS_IS_LIST(type)) + *buf = xmlStrdup(BAD_CAST "list type 'xs:"); + else if (WXS_IS_UNION(type)) + *buf = xmlStrdup(BAD_CAST "union type 'xs:"); + else + *buf = xmlStrdup(BAD_CAST "simple type 'xs:"); + *buf = xmlStrcat(*buf, type->name); + *buf = xmlStrcat(*buf, BAD_CAST "'"); + } + break; + case XML_SCHEMA_TYPE_SIMPLE: { + xmlSchemaTypePtr type = WXS_TYPE_CAST item; + + if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) { + *buf = xmlStrdup(BAD_CAST""); + } else { + *buf = xmlStrdup(BAD_CAST "local "); + } + if (WXS_IS_ATOMIC(type)) + *buf = xmlStrcat(*buf, BAD_CAST "atomic type"); + else if (WXS_IS_LIST(type)) + *buf = xmlStrcat(*buf, BAD_CAST "list type"); + else if (WXS_IS_UNION(type)) + *buf = xmlStrcat(*buf, BAD_CAST "union type"); + else + *buf = xmlStrcat(*buf, BAD_CAST "simple type"); + if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) { + *buf = xmlStrcat(*buf, BAD_CAST " '"); + *buf = xmlStrcat(*buf, type->name); + *buf = xmlStrcat(*buf, BAD_CAST "'"); + } + } + break; + case XML_SCHEMA_TYPE_COMPLEX: { + xmlSchemaTypePtr type = WXS_TYPE_CAST item; + + if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) + *buf = xmlStrdup(BAD_CAST ""); + else + *buf = xmlStrdup(BAD_CAST "local "); + *buf = xmlStrcat(*buf, BAD_CAST "complex type"); + if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) { + *buf = xmlStrcat(*buf, BAD_CAST " '"); + *buf = xmlStrcat(*buf, type->name); + *buf = xmlStrcat(*buf, BAD_CAST "'"); + } + } + break; + case XML_SCHEMA_TYPE_ATTRIBUTE_USE: { + xmlSchemaAttributeUsePtr ause; + + ause = WXS_ATTR_USE_CAST item; + *buf = xmlStrdup(BAD_CAST "attribute use "); + if (WXS_ATTRUSE_DECL(ause) != NULL) { + *buf = xmlStrcat(*buf, BAD_CAST "'"); + *buf = xmlStrcat(*buf, + xmlSchemaGetComponentQName(&str, WXS_ATTRUSE_DECL(ause))); + FREE_AND_NULL(str) + *buf = xmlStrcat(*buf, BAD_CAST "'"); + } else { + *buf = xmlStrcat(*buf, BAD_CAST "(unknown)"); + } + } + break; + case XML_SCHEMA_TYPE_ATTRIBUTE: { + xmlSchemaAttributePtr attr; + + attr = (xmlSchemaAttributePtr) item; + *buf = xmlStrdup(BAD_CAST "attribute decl."); + *buf = xmlStrcat(*buf, BAD_CAST " '"); + *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str, + attr->targetNamespace, attr->name)); + FREE_AND_NULL(str) + *buf = xmlStrcat(*buf, BAD_CAST "'"); + } + break; + case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: + xmlSchemaGetComponentDesignation(buf, item); + break; + case XML_SCHEMA_TYPE_ELEMENT: { + xmlSchemaElementPtr elem; + + elem = (xmlSchemaElementPtr) item; + *buf = xmlStrdup(BAD_CAST "element decl."); + *buf = xmlStrcat(*buf, BAD_CAST " '"); + *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str, + elem->targetNamespace, elem->name)); + *buf = xmlStrcat(*buf, BAD_CAST "'"); + } + break; + case XML_SCHEMA_TYPE_IDC_UNIQUE: + case XML_SCHEMA_TYPE_IDC_KEY: + case XML_SCHEMA_TYPE_IDC_KEYREF: + if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE) + *buf = xmlStrdup(BAD_CAST "unique '"); + else if (item->type == XML_SCHEMA_TYPE_IDC_KEY) + *buf = xmlStrdup(BAD_CAST "key '"); + else + *buf = xmlStrdup(BAD_CAST "keyRef '"); + *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name); + *buf = xmlStrcat(*buf, BAD_CAST "'"); + break; + case XML_SCHEMA_TYPE_ANY: + case XML_SCHEMA_TYPE_ANY_ATTRIBUTE: + *buf = xmlStrdup(xmlSchemaWildcardPCToString( + ((xmlSchemaWildcardPtr) item)->processContents)); + *buf = xmlStrcat(*buf, BAD_CAST " wildcard"); + break; + case XML_SCHEMA_FACET_MININCLUSIVE: + case XML_SCHEMA_FACET_MINEXCLUSIVE: + case XML_SCHEMA_FACET_MAXINCLUSIVE: + case XML_SCHEMA_FACET_MAXEXCLUSIVE: + case XML_SCHEMA_FACET_TOTALDIGITS: + case XML_SCHEMA_FACET_FRACTIONDIGITS: + case XML_SCHEMA_FACET_PATTERN: + case XML_SCHEMA_FACET_ENUMERATION: + case XML_SCHEMA_FACET_WHITESPACE: + case XML_SCHEMA_FACET_LENGTH: + case XML_SCHEMA_FACET_MAXLENGTH: + case XML_SCHEMA_FACET_MINLENGTH: + *buf = xmlStrdup(BAD_CAST "facet '"); + *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type)); + *buf = xmlStrcat(*buf, BAD_CAST "'"); + break; + case XML_SCHEMA_TYPE_GROUP: { + *buf = xmlStrdup(BAD_CAST "model group def."); + *buf = xmlStrcat(*buf, BAD_CAST " '"); + *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item)); + *buf = xmlStrcat(*buf, BAD_CAST "'"); + FREE_AND_NULL(str) + } + break; + case XML_SCHEMA_TYPE_SEQUENCE: + case XML_SCHEMA_TYPE_CHOICE: + case XML_SCHEMA_TYPE_ALL: + case XML_SCHEMA_TYPE_PARTICLE: + *buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item)); + break; + case XML_SCHEMA_TYPE_NOTATION: { + *buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item)); + *buf = xmlStrcat(*buf, BAD_CAST " '"); + *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item)); + *buf = xmlStrcat(*buf, BAD_CAST "'"); + FREE_AND_NULL(str); + } + default: + named = 0; + } + } else + named = 0; + + if ((named == 0) && (itemNode != NULL)) { + xmlNodePtr elem; + + if (itemNode->type == XML_ATTRIBUTE_NODE) + elem = itemNode->parent; + else + elem = itemNode; + *buf = xmlStrdup(BAD_CAST "Element '"); + if (elem->ns != NULL) { + *buf = xmlStrcat(*buf, + xmlSchemaFormatQName(&str, elem->ns->href, elem->name)); + FREE_AND_NULL(str) + } else + *buf = xmlStrcat(*buf, elem->name); + *buf = xmlStrcat(*buf, BAD_CAST "'"); + + } + if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) { + *buf = xmlStrcat(*buf, BAD_CAST ", attribute '"); + if (itemNode->ns != NULL) { + *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str, + itemNode->ns->href, itemNode->name)); + FREE_AND_NULL(str) + } else + *buf = xmlStrcat(*buf, itemNode->name); + *buf = xmlStrcat(*buf, BAD_CAST "'"); + } + FREE_AND_NULL(str) + + return (*buf); +} + +/** + * xmlSchemaFormatFacetEnumSet: + * @buf: the string buffer + * @type: the type holding the enumeration facets + * + * Builds a string consisting of all enumeration elements. + * + * Returns a string of all enumeration elements. + */ +static const xmlChar * +xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt, + xmlChar **buf, xmlSchemaTypePtr type) +{ + xmlSchemaFacetPtr facet; + xmlSchemaWhitespaceValueType ws; + xmlChar *value = NULL; + int res, found = 0; + + if (*buf != NULL) + xmlFree(*buf); + *buf = NULL; + + do { + /* + * Use the whitespace type of the base type. + */ + ws = xmlSchemaGetWhiteSpaceFacetValue(type->baseType); + for (facet = type->facets; facet != NULL; facet = facet->next) { + if (facet->type != XML_SCHEMA_FACET_ENUMERATION) + continue; + found = 1; + res = xmlSchemaGetCanonValueWhtspExt(facet->val, + ws, &value); + if (res == -1) { + xmlSchemaInternalErr(actxt, + "xmlSchemaFormatFacetEnumSet", + "compute the canonical lexical representation"); + if (*buf != NULL) + xmlFree(*buf); + *buf = NULL; + return (NULL); + } + if (*buf == NULL) + *buf = xmlStrdup(BAD_CAST "'"); + else + *buf = xmlStrcat(*buf, BAD_CAST ", '"); + *buf = xmlStrcat(*buf, BAD_CAST value); + *buf = xmlStrcat(*buf, BAD_CAST "'"); + if (value != NULL) { + xmlFree((xmlChar *)value); + value = NULL; + } + } + /* + * The enumeration facet of a type restricts the enumeration + * facet of the ancestor type; i.e., such restricted enumerations + * do not belong to the set of the given type. Thus we break + * on the first found enumeration. + */ + if (found) + break; + type = type->baseType; + } while ((type != NULL) && (type->type != XML_SCHEMA_TYPE_BASIC)); + + return ((const xmlChar *) *buf); +} + +/************************************************************************ + * * + * Error functions * + * * + ************************************************************************/ + +#if 0 +static void +xmlSchemaErrMemory(const char *msg) +{ + __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL, + msg); +} +#endif + +static void +xmlSchemaPSimpleErr(const char *msg) +{ + __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL, + msg); +} + +/** + * xmlSchemaPErrMemory: + * @node: a context node + * @extra: extra informations + * + * Handle an out of memory condition + */ +static void +xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt, + const char *extra, xmlNodePtr node) +{ + if (ctxt != NULL) + ctxt->nberrors++; + __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL, + extra); +} + +/** + * xmlSchemaPErr: + * @ctxt: the parsing context + * @node: the context node + * @error: the error code + * @msg: the error message + * @str1: extra data + * @str2: extra data + * + * Handle a parser error + */ +static void +xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error, + const char *msg, const xmlChar * str1, const xmlChar * str2) +{ + xmlGenericErrorFunc channel = NULL; + xmlStructuredErrorFunc schannel = NULL; + void *data = NULL; + + if (ctxt != NULL) { + ctxt->nberrors++; + ctxt->err = error; + channel = ctxt->error; + data = ctxt->errCtxt; + schannel = ctxt->serror; + } + __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP, + error, XML_ERR_ERROR, NULL, 0, + (const char *) str1, (const char *) str2, NULL, 0, 0, + msg, str1, str2); +} + +/** + * xmlSchemaPErr2: + * @ctxt: the parsing context + * @node: the context node + * @node: the current child + * @error: the error code + * @msg: the error message + * @str1: extra data + * @str2: extra data + * + * Handle a parser error + */ +static void +xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, + xmlNodePtr child, int error, + const char *msg, const xmlChar * str1, const xmlChar * str2) +{ + if (child != NULL) + xmlSchemaPErr(ctxt, child, error, msg, str1, str2); + else + xmlSchemaPErr(ctxt, node, error, msg, str1, str2); +} + + +/** + * xmlSchemaPErrExt: + * @ctxt: the parsing context + * @node: the context node + * @error: the error code + * @strData1: extra data + * @strData2: extra data + * @strData3: extra data + * @msg: the message + * @str1: extra parameter for the message display + * @str2: extra parameter for the message display + * @str3: extra parameter for the message display + * @str4: extra parameter for the message display + * @str5: extra parameter for the message display + * + * Handle a parser error + */ +static void +xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error, + const xmlChar * strData1, const xmlChar * strData2, + const xmlChar * strData3, const char *msg, const xmlChar * str1, + const xmlChar * str2, const xmlChar * str3, const xmlChar * str4, + const xmlChar * str5) +{ + + xmlGenericErrorFunc channel = NULL; + xmlStructuredErrorFunc schannel = NULL; + void *data = NULL; + + if (ctxt != NULL) { + ctxt->nberrors++; + ctxt->err = error; + channel = ctxt->error; + data = ctxt->errCtxt; + schannel = ctxt->serror; + } + __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP, + error, XML_ERR_ERROR, NULL, 0, + (const char *) strData1, (const char *) strData2, + (const char *) strData3, 0, 0, msg, str1, str2, + str3, str4, str5); +} + +/************************************************************************ + * * + * Allround error functions * + * * + ************************************************************************/ + +/** + * xmlSchemaVTypeErrMemory: + * @node: a context node + * @extra: extra informations + * + * Handle an out of memory condition + */ +static void +xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt, + const char *extra, xmlNodePtr node) +{ + if (ctxt != NULL) { + ctxt->nberrors++; + ctxt->err = XML_SCHEMAV_INTERNAL; + } + __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL, + extra); +} + +static void +xmlSchemaPSimpleInternalErr(xmlNodePtr node, + const char *msg, const xmlChar *str) +{ + __xmlSimpleError(XML_FROM_SCHEMASP, XML_SCHEMAP_INTERNAL, node, + msg, (const char *) str); +} + +#define WXS_ERROR_TYPE_ERROR 1 +#define WXS_ERROR_TYPE_WARNING 2 +/** + * xmlSchemaErr3: + * @ctxt: the validation context + * @node: the context node + * @error: the error code + * @msg: the error message + * @str1: extra data + * @str2: extra data + * @str3: extra data + * + * Handle a validation error + */ +static void +xmlSchemaErr4Line(xmlSchemaAbstractCtxtPtr ctxt, + xmlErrorLevel errorLevel, + int error, xmlNodePtr node, int line, const char *msg, + const xmlChar *str1, const xmlChar *str2, + const xmlChar *str3, const xmlChar *str4) +{ + xmlStructuredErrorFunc schannel = NULL; + xmlGenericErrorFunc channel = NULL; + void *data = NULL; + + if (ctxt != NULL) { + if (ctxt->type == XML_SCHEMA_CTXT_VALIDATOR) { + xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctxt; + const char *file = NULL; + if (errorLevel != XML_ERR_WARNING) { + vctxt->nberrors++; + vctxt->err = error; + channel = vctxt->error; + } else { + channel = vctxt->warning; + } + schannel = vctxt->serror; + data = vctxt->errCtxt; + + /* + * Error node. If we specify a line number, then + * do not channel any node to the error function. + */ + if (line == 0) { + if ((node == NULL) && + (vctxt->depth >= 0) && + (vctxt->inode != NULL)) { + node = vctxt->inode->node; + } + /* + * Get filename and line if no node-tree. + */ + if ((node == NULL) && + (vctxt->parserCtxt != NULL) && + (vctxt->parserCtxt->input != NULL)) { + file = vctxt->parserCtxt->input->filename; + line = vctxt->parserCtxt->input->line; + } + } else { + /* + * Override the given node's (if any) position + * and channel only the given line number. + */ + node = NULL; + /* + * Get filename. + */ + if (vctxt->doc != NULL) + file = (const char *) vctxt->doc->URL; + else if ((vctxt->parserCtxt != NULL) && + (vctxt->parserCtxt->input != NULL)) + file = vctxt->parserCtxt->input->filename; + } + __xmlRaiseError(schannel, channel, data, ctxt, + node, XML_FROM_SCHEMASV, + error, errorLevel, file, line, + (const char *) str1, (const char *) str2, + (const char *) str3, 0, 0, msg, str1, str2, str3, str4); + + } else if (ctxt->type == XML_SCHEMA_CTXT_PARSER) { + xmlSchemaParserCtxtPtr pctxt = (xmlSchemaParserCtxtPtr) ctxt; + if (errorLevel != XML_ERR_WARNING) { + pctxt->nberrors++; + pctxt->err = error; + channel = pctxt->error; + } else { + channel = pctxt->warning; + } + schannel = pctxt->serror; + data = pctxt->errCtxt; + __xmlRaiseError(schannel, channel, data, ctxt, + node, XML_FROM_SCHEMASP, error, + errorLevel, NULL, 0, + (const char *) str1, (const char *) str2, + (const char *) str3, 0, 0, msg, str1, str2, str3, str4); + } else { + TODO + } + } +} + +/** + * xmlSchemaErr3: + * @ctxt: the validation context + * @node: the context node + * @error: the error code + * @msg: the error message + * @str1: extra data + * @str2: extra data + * @str3: extra data + * + * Handle a validation error + */ +static void +xmlSchemaErr3(xmlSchemaAbstractCtxtPtr actxt, + int error, xmlNodePtr node, const char *msg, + const xmlChar *str1, const xmlChar *str2, const xmlChar *str3) +{ + xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0, + msg, str1, str2, str3, NULL); +} + +static void +xmlSchemaErr4(xmlSchemaAbstractCtxtPtr actxt, + int error, xmlNodePtr node, const char *msg, + const xmlChar *str1, const xmlChar *str2, + const xmlChar *str3, const xmlChar *str4) +{ + xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0, + msg, str1, str2, str3, str4); +} + +static void +xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt, + int error, xmlNodePtr node, const char *msg, + const xmlChar *str1, const xmlChar *str2) +{ + xmlSchemaErr4(actxt, error, node, msg, str1, str2, NULL, NULL); +} + +static xmlChar * +xmlSchemaFormatNodeForError(xmlChar ** msg, + xmlSchemaAbstractCtxtPtr actxt, + xmlNodePtr node) +{ + xmlChar *str = NULL; + + *msg = NULL; + if ((node != NULL) && + (node->type != XML_ELEMENT_NODE) && + (node->type != XML_ATTRIBUTE_NODE)) + { + /* + * Don't try to format other nodes than element and + * attribute nodes. + * Play save and return an empty string. + */ + *msg = xmlStrdup(BAD_CAST ""); + return(*msg); + } + if (node != NULL) { + /* + * Work on tree nodes. + */ + if (node->type == XML_ATTRIBUTE_NODE) { + xmlNodePtr elem = node->parent; + + *msg = xmlStrdup(BAD_CAST "Element '"); + if (elem->ns != NULL) + *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str, + elem->ns->href, elem->name)); + else + *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str, + NULL, elem->name)); + FREE_AND_NULL(str); + *msg = xmlStrcat(*msg, BAD_CAST "', "); + *msg = xmlStrcat(*msg, BAD_CAST "attribute '"); + } else { + *msg = xmlStrdup(BAD_CAST "Element '"); + } + if (node->ns != NULL) + *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str, + node->ns->href, node->name)); + else + *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str, + NULL, node->name)); + FREE_AND_NULL(str); + *msg = xmlStrcat(*msg, BAD_CAST "': "); + } else if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) { + xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) actxt; + /* + * Work on node infos. + */ + if (vctxt->inode->nodeType == XML_ATTRIBUTE_NODE) { + xmlSchemaNodeInfoPtr ielem = + vctxt->elemInfos[vctxt->depth]; + + *msg = xmlStrdup(BAD_CAST "Element '"); + *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str, + ielem->nsName, ielem->localName)); + FREE_AND_NULL(str); + *msg = xmlStrcat(*msg, BAD_CAST "', "); + *msg = xmlStrcat(*msg, BAD_CAST "attribute '"); + } else { + *msg = xmlStrdup(BAD_CAST "Element '"); + } + *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str, + vctxt->inode->nsName, vctxt->inode->localName)); + FREE_AND_NULL(str); + *msg = xmlStrcat(*msg, BAD_CAST "': "); + } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) { + /* + * Hmm, no node while parsing? + * Return an empty string, in case NULL will break something. + */ + *msg = xmlStrdup(BAD_CAST ""); + } else { + TODO + return (NULL); + } + /* + * VAL TODO: The output of the given schema component is currently + * disabled. + */ +#if 0 + if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) { + *msg = xmlStrcat(*msg, BAD_CAST " ["); + *msg = xmlStrcat(*msg, xmlSchemaFormatItemForReport(&str, + NULL, type, NULL, 0)); + FREE_AND_NULL(str) + *msg = xmlStrcat(*msg, BAD_CAST "]"); + } +#endif + return (*msg); +} + +static void +xmlSchemaInternalErr2(xmlSchemaAbstractCtxtPtr actxt, + const char *funcName, + const char *message, + const xmlChar *str1, + const xmlChar *str2) +{ + xmlChar *msg = NULL; + + if (actxt == NULL) + return; + msg = xmlStrdup(BAD_CAST "Internal error: "); + msg = xmlStrcat(msg, BAD_CAST funcName); + msg = xmlStrcat(msg, BAD_CAST ", "); + msg = xmlStrcat(msg, BAD_CAST message); + msg = xmlStrcat(msg, BAD_CAST ".\n"); + + if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) + xmlSchemaErr(actxt, XML_SCHEMAV_INTERNAL, NULL, + (const char *) msg, str1, str2); + + else if (actxt->type == XML_SCHEMA_CTXT_PARSER) + xmlSchemaErr(actxt, XML_SCHEMAP_INTERNAL, NULL, + (const char *) msg, str1, str2); + + FREE_AND_NULL(msg) +} + +static void +xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt, + const char *funcName, + const char *message) +{ + xmlSchemaInternalErr2(actxt, funcName, message, NULL, NULL); +} + +#if 0 +static void +xmlSchemaPInternalErr(xmlSchemaParserCtxtPtr pctxt, + const char *funcName, + const char *message, + const xmlChar *str1, + const xmlChar *str2) +{ + xmlSchemaInternalErr2(ACTXT_CAST pctxt, funcName, message, + str1, str2); +} +#endif + +static void +xmlSchemaCustomErr4(xmlSchemaAbstractCtxtPtr actxt, + xmlParserErrors error, + xmlNodePtr node, + xmlSchemaBasicItemPtr item, + const char *message, + const xmlChar *str1, const xmlChar *str2, + const xmlChar *str3, const xmlChar *str4) +{ + xmlChar *msg = NULL; + + if ((node == NULL) && (item != NULL) && + (actxt->type == XML_SCHEMA_CTXT_PARSER)) { + node = WXS_ITEM_NODE(item); + xmlSchemaFormatItemForReport(&msg, NULL, item, NULL); + msg = xmlStrcat(msg, BAD_CAST ": "); + } else + xmlSchemaFormatNodeForError(&msg, actxt, node); + msg = xmlStrcat(msg, (const xmlChar *) message); + msg = xmlStrcat(msg, BAD_CAST ".\n"); + xmlSchemaErr4(actxt, error, node, + (const char *) msg, str1, str2, str3, str4); + FREE_AND_NULL(msg) +} + +static void +xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt, + xmlParserErrors error, + xmlNodePtr node, + xmlSchemaBasicItemPtr item, + const char *message, + const xmlChar *str1, + const xmlChar *str2) +{ + xmlSchemaCustomErr4(actxt, error, node, item, + message, str1, str2, NULL, NULL); +} + + + +static void +xmlSchemaCustomWarning(xmlSchemaAbstractCtxtPtr actxt, + xmlParserErrors error, + xmlNodePtr node, + xmlSchemaTypePtr type ATTRIBUTE_UNUSED, + const char *message, + const xmlChar *str1, + const xmlChar *str2, + const xmlChar *str3) +{ + xmlChar *msg = NULL; + + xmlSchemaFormatNodeForError(&msg, actxt, node); + msg = xmlStrcat(msg, (const xmlChar *) message); + msg = xmlStrcat(msg, BAD_CAST ".\n"); + + /* URGENT TODO: Set the error code to something sane. */ + xmlSchemaErr4Line(actxt, XML_ERR_WARNING, error, node, 0, + (const char *) msg, str1, str2, str3, NULL); + + FREE_AND_NULL(msg) +} + + + +static void +xmlSchemaKeyrefErr(xmlSchemaValidCtxtPtr vctxt, + xmlParserErrors error, + xmlSchemaPSVIIDCNodePtr idcNode, + xmlSchemaTypePtr type ATTRIBUTE_UNUSED, + const char *message, + const xmlChar *str1, + const xmlChar *str2) +{ + xmlChar *msg = NULL, *qname = NULL; + + msg = xmlStrdup(BAD_CAST "Element '%s': "); + msg = xmlStrcat(msg, (const xmlChar *) message); + msg = xmlStrcat(msg, BAD_CAST ".\n"); + xmlSchemaErr4Line(ACTXT_CAST vctxt, XML_ERR_ERROR, + error, NULL, idcNode->nodeLine, (const char *) msg, + xmlSchemaFormatQName(&qname, + vctxt->nodeQNames->items[idcNode->nodeQNameID +1], + vctxt->nodeQNames->items[idcNode->nodeQNameID]), + str1, str2, NULL); + FREE_AND_NULL(qname); + FREE_AND_NULL(msg); +} + +static int +xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt, + xmlNodePtr node) +{ + if (node != NULL) + return (node->type); + if ((actxt->type == XML_SCHEMA_CTXT_VALIDATOR) && + (((xmlSchemaValidCtxtPtr) actxt)->inode != NULL)) + return ( ((xmlSchemaValidCtxtPtr) actxt)->inode->nodeType); + return (-1); +} + +static int +xmlSchemaIsGlobalItem(xmlSchemaTypePtr item) +{ + switch (item->type) { + case XML_SCHEMA_TYPE_COMPLEX: + case XML_SCHEMA_TYPE_SIMPLE: + if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) + return(1); + break; + case XML_SCHEMA_TYPE_GROUP: + return (1); + case XML_SCHEMA_TYPE_ELEMENT: + if ( ((xmlSchemaElementPtr) item)->flags & + XML_SCHEMAS_ELEM_GLOBAL) + return(1); + break; + case XML_SCHEMA_TYPE_ATTRIBUTE: + if ( ((xmlSchemaAttributePtr) item)->flags & + XML_SCHEMAS_ATTR_GLOBAL) + return(1); + break; + /* Note that attribute groups are always global. */ + default: + return(1); + } + return (0); +} + +static void +xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt, + xmlParserErrors error, + xmlNodePtr node, + const xmlChar *value, + xmlSchemaTypePtr type, + int displayValue) +{ + xmlChar *msg = NULL; + + xmlSchemaFormatNodeForError(&msg, actxt, node); + + if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) == + XML_ATTRIBUTE_NODE)) + msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of "); + else + msg = xmlStrcat(msg, BAD_CAST "The character content is not a valid " + "value of "); + + if (! xmlSchemaIsGlobalItem(type)) + msg = xmlStrcat(msg, BAD_CAST "the local "); + else + msg = xmlStrcat(msg, BAD_CAST "the "); + + if (WXS_IS_ATOMIC(type)) + msg = xmlStrcat(msg, BAD_CAST "atomic type"); + else if (WXS_IS_LIST(type)) + msg = xmlStrcat(msg, BAD_CAST "list type"); + else if (WXS_IS_UNION(type)) + msg = xmlStrcat(msg, BAD_CAST "union type"); + + if (xmlSchemaIsGlobalItem(type)) { + xmlChar *str = NULL; + msg = xmlStrcat(msg, BAD_CAST " '"); + if (type->builtInType != 0) { + msg = xmlStrcat(msg, BAD_CAST "xs:"); + msg = xmlStrcat(msg, type->name); + } else + msg = xmlStrcat(msg, + xmlSchemaFormatQName(&str, + type->targetNamespace, type->name)); + msg = xmlStrcat(msg, BAD_CAST "'"); + FREE_AND_NULL(str); + } + msg = xmlStrcat(msg, BAD_CAST ".\n"); + if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) == + XML_ATTRIBUTE_NODE)) + xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL); + else + xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL); + FREE_AND_NULL(msg) +} + +static const xmlChar * +xmlSchemaFormatErrorNodeQName(xmlChar ** str, + xmlSchemaNodeInfoPtr ni, + xmlNodePtr node) +{ + if (node != NULL) { + if (node->ns != NULL) + return (xmlSchemaFormatQName(str, node->ns->href, node->name)); + else + return (xmlSchemaFormatQName(str, NULL, node->name)); + } else if (ni != NULL) + return (xmlSchemaFormatQName(str, ni->nsName, ni->localName)); + return (NULL); +} + +static void +xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt, + xmlParserErrors error, + xmlSchemaAttrInfoPtr ni, + xmlNodePtr node) +{ + xmlChar *msg = NULL, *str = NULL; + + xmlSchemaFormatNodeForError(&msg, actxt, node); + msg = xmlStrcat(msg, BAD_CAST "The attribute '%s' is not allowed.\n"); + xmlSchemaErr(actxt, error, node, (const char *) msg, + xmlSchemaFormatErrorNodeQName(&str, (xmlSchemaNodeInfoPtr) ni, node), + NULL); + FREE_AND_NULL(str) + FREE_AND_NULL(msg) +} + +static void +xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt, + xmlParserErrors error, + xmlNodePtr node, + xmlSchemaTypePtr type ATTRIBUTE_UNUSED, + const char *message, + int nbval, + int nbneg, + xmlChar **values) +{ + xmlChar *str = NULL, *msg = NULL; + xmlChar *localName, *nsName; + const xmlChar *cur, *end; + int i; + + xmlSchemaFormatNodeForError(&msg, actxt, node); + msg = xmlStrcat(msg, (const xmlChar *) message); + msg = xmlStrcat(msg, BAD_CAST "."); + /* + * Note that is does not make sense to report that we have a + * wildcard here, since the wildcard might be unfolded into + * multiple transitions. + */ + if (nbval + nbneg > 0) { + if (nbval + nbneg > 1) { + str = xmlStrdup(BAD_CAST " Expected is one of ( "); + } else + str = xmlStrdup(BAD_CAST " Expected is ( "); + nsName = NULL; + + for (i = 0; i < nbval + nbneg; i++) { + cur = values[i]; + if (cur == NULL) + continue; + if ((cur[0] == 'n') && (cur[1] == 'o') && (cur[2] == 't') && + (cur[3] == ' ')) { + cur += 4; + str = xmlStrcat(str, BAD_CAST "##other"); + } + /* + * Get the local name. + */ + localName = NULL; + + end = cur; + if (*end == '*') { + localName = xmlStrdup(BAD_CAST "*"); + end++; + } else { + while ((*end != 0) && (*end != '|')) + end++; + localName = xmlStrncat(localName, BAD_CAST cur, end - cur); + } + if (*end != 0) { + end++; + /* + * Skip "*|*" if they come with negated expressions, since + * they represent the same negated wildcard. + */ + if ((nbneg == 0) || (*end != '*') || (*localName != '*')) { + /* + * Get the namespace name. + */ + cur = end; + if (*end == '*') { + nsName = xmlStrdup(BAD_CAST "{*}"); + } else { + while (*end != 0) + end++; + + if (i >= nbval) + nsName = xmlStrdup(BAD_CAST "{##other:"); + else + nsName = xmlStrdup(BAD_CAST "{"); + + nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur); + nsName = xmlStrcat(nsName, BAD_CAST "}"); + } + str = xmlStrcat(str, BAD_CAST nsName); + FREE_AND_NULL(nsName) + } else { + FREE_AND_NULL(localName); + continue; + } + } + str = xmlStrcat(str, BAD_CAST localName); + FREE_AND_NULL(localName); + + if (i < nbval + nbneg -1) + str = xmlStrcat(str, BAD_CAST ", "); + } + str = xmlStrcat(str, BAD_CAST " ).\n"); + msg = xmlStrcat(msg, BAD_CAST str); + FREE_AND_NULL(str) + } else + msg = xmlStrcat(msg, BAD_CAST "\n"); + xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL); + xmlFree(msg); +} + +static void +xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt, + xmlParserErrors error, + xmlNodePtr node, + const xmlChar *value, + unsigned long length, + xmlSchemaTypePtr type, + xmlSchemaFacetPtr facet, + const char *message, + const xmlChar *str1, + const xmlChar *str2) +{ + xmlChar *str = NULL, *msg = NULL; + xmlSchemaTypeType facetType; + int nodeType = xmlSchemaEvalErrorNodeType(actxt, node); + + xmlSchemaFormatNodeForError(&msg, actxt, node); + if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) { + facetType = XML_SCHEMA_FACET_ENUMERATION; + /* + * If enumerations are validated, one must not expect the + * facet to be given. + */ + } else + facetType = facet->type; + msg = xmlStrcat(msg, BAD_CAST "["); + msg = xmlStrcat(msg, BAD_CAST "facet '"); + msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType)); + msg = xmlStrcat(msg, BAD_CAST "'] "); + if (message == NULL) { + /* + * Use a default message. + */ + if ((facetType == XML_SCHEMA_FACET_LENGTH) || + (facetType == XML_SCHEMA_FACET_MINLENGTH) || + (facetType == XML_SCHEMA_FACET_MAXLENGTH)) { + + char len[25], actLen[25]; + + /* FIXME, TODO: What is the max expected string length of the + * this value? + */ + if (nodeType == XML_ATTRIBUTE_NODE) + msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; "); + else + msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; "); + + snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet)); + snprintf(actLen, 24, "%lu", length); + + if (facetType == XML_SCHEMA_FACET_LENGTH) + msg = xmlStrcat(msg, + BAD_CAST "this differs from the allowed length of '%s'.\n"); + else if (facetType == XML_SCHEMA_FACET_MAXLENGTH) + msg = xmlStrcat(msg, + BAD_CAST "this exceeds the allowed maximum length of '%s'.\n"); + else if (facetType == XML_SCHEMA_FACET_MINLENGTH) + msg = xmlStrcat(msg, + BAD_CAST "this underruns the allowed minimum length of '%s'.\n"); + + if (nodeType == XML_ATTRIBUTE_NODE) + xmlSchemaErr3(actxt, error, node, (const char *) msg, + value, (const xmlChar *) actLen, (const xmlChar *) len); + else + xmlSchemaErr(actxt, error, node, (const char *) msg, + (const xmlChar *) actLen, (const xmlChar *) len); + + } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) { + msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element " + "of the set {%s}.\n"); + xmlSchemaErr(actxt, error, node, (const char *) msg, value, + xmlSchemaFormatFacetEnumSet(actxt, &str, type)); + } else if (facetType == XML_SCHEMA_FACET_PATTERN) { + msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted " + "by the pattern '%s'.\n"); + xmlSchemaErr(actxt, error, node, (const char *) msg, value, + facet->value); + } else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) { + msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the " + "minimum value allowed ('%s').\n"); + xmlSchemaErr(actxt, error, node, (const char *) msg, value, + facet->value); + } else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) { + msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the " + "maximum value allowed ('%s').\n"); + xmlSchemaErr(actxt, error, node, (const char *) msg, value, + facet->value); + } else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) { + msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be greater than " + "'%s'.\n"); + xmlSchemaErr(actxt, error, node, (const char *) msg, value, + facet->value); + } else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) { + msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than " + "'%s'.\n"); + xmlSchemaErr(actxt, error, node, (const char *) msg, value, + facet->value); + } else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) { + msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more " + "digits than are allowed ('%s').\n"); + xmlSchemaErr(actxt, error, node, (const char*) msg, value, + facet->value); + } else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) { + msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional " + "digits than are allowed ('%s').\n"); + xmlSchemaErr(actxt, error, node, (const char*) msg, value, + facet->value); + } else if (nodeType == XML_ATTRIBUTE_NODE) { + msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n"); + xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL); + } else { + msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n"); + xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL); + } + } else { + msg = xmlStrcat(msg, (const xmlChar *) message); + msg = xmlStrcat(msg, BAD_CAST ".\n"); + xmlSchemaErr(actxt, error, node, (const char *) msg, str1, str2); + } + FREE_AND_NULL(str) + xmlFree(msg); +} + +#define VERROR(err, type, msg) \ + xmlSchemaCustomErr(ACTXT_CAST vctxt, err, NULL, type, msg, NULL, NULL); + +#define VERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST vctxt, func, msg); + +#define PERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST pctxt, func, msg); +#define PERROR_INT2(func, msg) xmlSchemaInternalErr(ACTXT_CAST ctxt, func, msg); + +#define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg); + + +/** + * xmlSchemaPMissingAttrErr: + * @ctxt: the schema validation context + * @ownerDes: the designation of the owner + * @ownerName: the name of the owner + * @ownerItem: the owner as a schema object + * @ownerElem: the owner as an element node + * @node: the parent element node of the missing attribute node + * @type: the corresponding type of the attribute node + * + * Reports an illegal attribute. + */ +static void +xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt, + xmlParserErrors error, + xmlSchemaBasicItemPtr ownerItem, + xmlNodePtr ownerElem, + const char *name, + const char *message) +{ + xmlChar *des = NULL; + + xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem); + + if (message != NULL) + xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message); + else + xmlSchemaPErr(ctxt, ownerElem, error, + "%s: The attribute '%s' is required but missing.\n", + BAD_CAST des, BAD_CAST name); + FREE_AND_NULL(des); +} + + +/** + * xmlSchemaPResCompAttrErr: + * @ctxt: the schema validation context + * @error: the error code + * @ownerDes: the designation of the owner + * @ownerItem: the owner as a schema object + * @ownerElem: the owner as an element node + * @name: the name of the attribute holding the QName + * @refName: the referenced local name + * @refURI: the referenced namespace URI + * @message: optional message + * + * Used to report QName attribute values that failed to resolve + * to schema components. + */ +static void +xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt, + xmlParserErrors error, + xmlSchemaBasicItemPtr ownerItem, + xmlNodePtr ownerElem, + const char *name, + const xmlChar *refName, + const xmlChar *refURI, + xmlSchemaTypeType refType, + const char *refTypeStr) +{ + xmlChar *des = NULL, *strA = NULL; + + xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem); + if (refTypeStr == NULL) + refTypeStr = (const char *) xmlSchemaItemTypeToStr(refType); + xmlSchemaPErrExt(ctxt, ownerElem, error, + NULL, NULL, NULL, + "%s, attribute '%s': The QName value '%s' does not resolve to a(n) " + "%s.\n", BAD_CAST des, BAD_CAST name, + xmlSchemaFormatQName(&strA, refURI, refName), + BAD_CAST refTypeStr, NULL); + FREE_AND_NULL(des) + FREE_AND_NULL(strA) +} + +/** + * xmlSchemaPCustomAttrErr: + * @ctxt: the schema parser context + * @error: the error code + * @ownerDes: the designation of the owner + * @ownerItem: the owner as a schema object + * @attr: the illegal attribute node + * + * Reports an illegal attribute during the parse. + */ +static void +xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt, + xmlParserErrors error, + xmlChar **ownerDes, + xmlSchemaBasicItemPtr ownerItem, + xmlAttrPtr attr, + const char *msg) +{ + xmlChar *des = NULL; + + if (ownerDes == NULL) + xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent); + else if (*ownerDes == NULL) { + xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent); + des = *ownerDes; + } else + des = *ownerDes; + if (attr == NULL) { + xmlSchemaPErrExt(ctxt, NULL, error, NULL, NULL, NULL, + "%s, attribute '%s': %s.\n", + BAD_CAST des, (const xmlChar *) "Unknown", + (const xmlChar *) msg, NULL, NULL); + } else { + xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL, + "%s, attribute '%s': %s.\n", + BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL); + } + if (ownerDes == NULL) + FREE_AND_NULL(des); +} + +/** + * xmlSchemaPIllegalAttrErr: + * @ctxt: the schema parser context + * @error: the error code + * @ownerDes: the designation of the attribute's owner + * @ownerItem: the attribute's owner item + * @attr: the illegal attribute node + * + * Reports an illegal attribute during the parse. + */ +static void +xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt, + xmlParserErrors error, + xmlSchemaBasicItemPtr ownerComp ATTRIBUTE_UNUSED, + xmlAttrPtr attr) +{ + xmlChar *strA = NULL, *strB = NULL; + + xmlSchemaFormatNodeForError(&strA, ACTXT_CAST ctxt, attr->parent); + xmlSchemaErr4(ACTXT_CAST ctxt, error, (xmlNodePtr) attr, + "%sThe attribute '%s' is not allowed.\n", BAD_CAST strA, + xmlSchemaFormatQNameNs(&strB, attr->ns, attr->name), + NULL, NULL); + FREE_AND_NULL(strA); + FREE_AND_NULL(strB); +} + +/** + * xmlSchemaPCustomErr: + * @ctxt: the schema parser context + * @error: the error code + * @itemDes: the designation of the schema item + * @item: the schema item + * @itemElem: the node of the schema item + * @message: the error message + * @str1: an optional param for the error message + * @str2: an optional param for the error message + * @str3: an optional param for the error message + * + * Reports an error during parsing. + */ +static void +xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt, + xmlParserErrors error, + xmlSchemaBasicItemPtr item, + xmlNodePtr itemElem, + const char *message, + const xmlChar *str1, + const xmlChar *str2, + const xmlChar *str3) +{ + xmlChar *des = NULL, *msg = NULL; + + xmlSchemaFormatItemForReport(&des, NULL, item, itemElem); + msg = xmlStrdup(BAD_CAST "%s: "); + msg = xmlStrcat(msg, (const xmlChar *) message); + msg = xmlStrcat(msg, BAD_CAST ".\n"); + if ((itemElem == NULL) && (item != NULL)) + itemElem = WXS_ITEM_NODE(item); + xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL, + (const char *) msg, BAD_CAST des, str1, str2, str3, NULL); + FREE_AND_NULL(des); + FREE_AND_NULL(msg); +} + +/** + * xmlSchemaPCustomErr: + * @ctxt: the schema parser context + * @error: the error code + * @itemDes: the designation of the schema item + * @item: the schema item + * @itemElem: the node of the schema item + * @message: the error message + * @str1: the optional param for the error message + * + * Reports an error during parsing. + */ +static void +xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt, + xmlParserErrors error, + xmlSchemaBasicItemPtr item, + xmlNodePtr itemElem, + const char *message, + const xmlChar *str1) +{ + xmlSchemaPCustomErrExt(ctxt, error, item, itemElem, message, + str1, NULL, NULL); +} + +/** + * xmlSchemaPAttrUseErr: + * @ctxt: the schema parser context + * @error: the error code + * @itemDes: the designation of the schema type + * @item: the schema type + * @itemElem: the node of the schema type + * @attr: the invalid schema attribute + * @message: the error message + * @str1: the optional param for the error message + * + * Reports an attribute use error during parsing. + */ +static void +xmlSchemaPAttrUseErr4(xmlSchemaParserCtxtPtr ctxt, + xmlParserErrors error, + xmlNodePtr node, + xmlSchemaBasicItemPtr ownerItem, + const xmlSchemaAttributeUsePtr attruse, + const char *message, + const xmlChar *str1, const xmlChar *str2, + const xmlChar *str3,const xmlChar *str4) +{ + xmlChar *str = NULL, *msg = NULL; + + xmlSchemaFormatItemForReport(&msg, NULL, ownerItem, NULL); + msg = xmlStrcat(msg, BAD_CAST ", "); + msg = xmlStrcat(msg, + BAD_CAST xmlSchemaFormatItemForReport(&str, NULL, + WXS_BASIC_CAST attruse, NULL)); + FREE_AND_NULL(str); + msg = xmlStrcat(msg, BAD_CAST ": "); + msg = xmlStrcat(msg, (const xmlChar *) message); + msg = xmlStrcat(msg, BAD_CAST ".\n"); + xmlSchemaErr4(ACTXT_CAST ctxt, error, node, + (const char *) msg, str1, str2, str3, str4); + xmlFree(msg); +} + +/** + * xmlSchemaPIllegalFacetAtomicErr: + * @ctxt: the schema parser context + * @error: the error code + * @type: the schema type + * @baseType: the base type of type + * @facet: the illegal facet + * + * Reports an illegal facet for atomic simple types. + */ +static void +xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt, + xmlParserErrors error, + xmlSchemaTypePtr type, + xmlSchemaTypePtr baseType, + xmlSchemaFacetPtr facet) +{ + xmlChar *des = NULL, *strT = NULL; + + xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type, type->node); + xmlSchemaPErrExt(ctxt, type->node, error, NULL, NULL, NULL, + "%s: The facet '%s' is not allowed on types derived from the " + "type %s.\n", + BAD_CAST des, xmlSchemaFacetTypeToString(facet->type), + xmlSchemaFormatItemForReport(&strT, NULL, WXS_BASIC_CAST baseType, NULL), + NULL, NULL); + FREE_AND_NULL(des); + FREE_AND_NULL(strT); +} + +/** + * xmlSchemaPIllegalFacetListUnionErr: + * @ctxt: the schema parser context + * @error: the error code + * @itemDes: the designation of the schema item involved + * @item: the schema item involved + * @facet: the illegal facet + * + * Reports an illegal facet for and . + */ +static void +xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt, + xmlParserErrors error, + xmlSchemaTypePtr type, + xmlSchemaFacetPtr facet) +{ + xmlChar *des = NULL; + + xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type, + type->node); + xmlSchemaPErr(ctxt, type->node, error, + "%s: The facet '%s' is not allowed.\n", + BAD_CAST des, xmlSchemaFacetTypeToString(facet->type)); + FREE_AND_NULL(des); +} + +/** + * xmlSchemaPMutualExclAttrErr: + * @ctxt: the schema validation context + * @error: the error code + * @elemDes: the designation of the parent element node + * @attr: the bad attribute node + * @type: the corresponding type of the attribute node + * + * Reports an illegal attribute. + */ +static void +xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt, + xmlParserErrors error, + xmlSchemaBasicItemPtr ownerItem, + xmlAttrPtr attr, + const char *name1, + const char *name2) +{ + xmlChar *des = NULL; + + xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST ownerItem, attr->parent); + xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL, + "%s: The attributes '%s' and '%s' are mutually exclusive.\n", + BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL); + FREE_AND_NULL(des); +} + +/** + * xmlSchemaPSimpleTypeErr: + * @ctxt: the schema validation context + * @error: the error code + * @type: the type specifier + * @ownerDes: the designation of the owner + * @ownerItem: the schema object if existent + * @node: the validated node + * @value: the validated value + * + * Reports a simple type validation error. + * TODO: Should this report the value of an element as well? + */ +static void +xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt, + xmlParserErrors error, + xmlSchemaBasicItemPtr ownerItem ATTRIBUTE_UNUSED, + xmlNodePtr node, + xmlSchemaTypePtr type, + const char *expected, + const xmlChar *value, + const char *message, + const xmlChar *str1, + const xmlChar *str2) +{ + xmlChar *msg = NULL; + + xmlSchemaFormatNodeForError(&msg, ACTXT_CAST ctxt, node); + if (message == NULL) { + /* + * Use default messages. + */ + if (type != NULL) { + if (node->type == XML_ATTRIBUTE_NODE) + msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of "); + else + msg = xmlStrcat(msg, BAD_CAST "The character content is not a " + "valid value of "); + if (! xmlSchemaIsGlobalItem(type)) + msg = xmlStrcat(msg, BAD_CAST "the local "); + else + msg = xmlStrcat(msg, BAD_CAST "the "); + + if (WXS_IS_ATOMIC(type)) + msg = xmlStrcat(msg, BAD_CAST "atomic type"); + else if (WXS_IS_LIST(type)) + msg = xmlStrcat(msg, BAD_CAST "list type"); + else if (WXS_IS_UNION(type)) + msg = xmlStrcat(msg, BAD_CAST "union type"); + + if (xmlSchemaIsGlobalItem(type)) { + xmlChar *str = NULL; + msg = xmlStrcat(msg, BAD_CAST " '"); + if (type->builtInType != 0) { + msg = xmlStrcat(msg, BAD_CAST "xs:"); + msg = xmlStrcat(msg, type->name); + } else + msg = xmlStrcat(msg, + xmlSchemaFormatQName(&str, + type->targetNamespace, type->name)); + msg = xmlStrcat(msg, BAD_CAST "'."); + FREE_AND_NULL(str); + } + } else { + if (node->type == XML_ATTRIBUTE_NODE) + msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not valid."); + else + msg = xmlStrcat(msg, BAD_CAST "The character content is not " + "valid."); + } + if (expected) { + msg = xmlStrcat(msg, BAD_CAST " Expected is '"); + msg = xmlStrcat(msg, BAD_CAST expected); + msg = xmlStrcat(msg, BAD_CAST "'.\n"); + } else + msg = xmlStrcat(msg, BAD_CAST "\n"); + if (node->type == XML_ATTRIBUTE_NODE) + xmlSchemaPErr(ctxt, node, error, (const char *) msg, value, NULL); + else + xmlSchemaPErr(ctxt, node, error, (const char *) msg, NULL, NULL); + } else { + msg = xmlStrcat(msg, BAD_CAST message); + msg = xmlStrcat(msg, BAD_CAST ".\n"); + xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL, + (const char*) msg, str1, str2, NULL, NULL, NULL); + } + /* Cleanup. */ + FREE_AND_NULL(msg) +} + +/** + * xmlSchemaPContentErr: + * @ctxt: the schema parser context + * @error: the error code + * @onwerDes: the designation of the holder of the content + * @ownerItem: the owner item of the holder of the content + * @ownerElem: the node of the holder of the content + * @child: the invalid child node + * @message: the optional error message + * @content: the optional string describing the correct content + * + * Reports an error concerning the content of a schema element. + */ +static void +xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt, + xmlParserErrors error, + xmlSchemaBasicItemPtr ownerItem, + xmlNodePtr ownerElem, + xmlNodePtr child, + const char *message, + const char *content) +{ + xmlChar *des = NULL; + + xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem); + if (message != NULL) + xmlSchemaPErr2(ctxt, ownerElem, child, error, + "%s: %s.\n", + BAD_CAST des, BAD_CAST message); + else { + if (content != NULL) { + xmlSchemaPErr2(ctxt, ownerElem, child, error, + "%s: The content is not valid. Expected is %s.\n", + BAD_CAST des, BAD_CAST content); + } else { + xmlSchemaPErr2(ctxt, ownerElem, child, error, + "%s: The content is not valid.\n", + BAD_CAST des, NULL); + } + } + FREE_AND_NULL(des) +} + +/************************************************************************ + * * + * Streamable error functions * + * * + ************************************************************************/ + + + + +/************************************************************************ + * * + * Validation helper functions * + * * + ************************************************************************/ + + +/************************************************************************ + * * + * Allocation functions * + * * + ************************************************************************/ + +/** + * xmlSchemaNewSchemaForParserCtxt: + * @ctxt: a schema validation context + * + * Allocate a new Schema structure. + * + * Returns the newly allocated structure or NULL in case or error + */ +static xmlSchemaPtr +xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt) +{ + xmlSchemaPtr ret; + + ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema)); + if (ret == NULL) { + xmlSchemaPErrMemory(ctxt, "allocating schema", NULL); + return (NULL); + } + memset(ret, 0, sizeof(xmlSchema)); + ret->dict = ctxt->dict; + xmlDictReference(ret->dict); + + return (ret); +} + +/** + * xmlSchemaNewFacet: + * + * Allocate a new Facet structure. + * + * Returns the newly allocated structure or NULL in case or error + */ +xmlSchemaFacetPtr +xmlSchemaNewFacet(void) +{ + xmlSchemaFacetPtr ret; + + ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet)); + if (ret == NULL) { + return (NULL); + } + memset(ret, 0, sizeof(xmlSchemaFacet)); + + return (ret); +} + +/** + * xmlSchemaNewAnnot: + * @ctxt: a schema validation context + * @node: a node + * + * Allocate a new annotation structure. + * + * Returns the newly allocated structure or NULL in case or error + */ +static xmlSchemaAnnotPtr +xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node) +{ + xmlSchemaAnnotPtr ret; + + ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot)); + if (ret == NULL) { + xmlSchemaPErrMemory(ctxt, "allocating annotation", node); + return (NULL); + } + memset(ret, 0, sizeof(xmlSchemaAnnot)); + ret->content = node; + return (ret); +} + +static xmlSchemaItemListPtr +xmlSchemaItemListCreate(void) +{ + xmlSchemaItemListPtr ret; + + ret = xmlMalloc(sizeof(xmlSchemaItemList)); + if (ret == NULL) { + xmlSchemaPErrMemory(NULL, + "allocating an item list structure", NULL); + return (NULL); + } + memset(ret, 0, sizeof(xmlSchemaItemList)); + return (ret); +} + +static void +xmlSchemaItemListClear(xmlSchemaItemListPtr list) +{ + if (list->items != NULL) { + xmlFree(list->items); + list->items = NULL; + } + list->nbItems = 0; + list->sizeItems = 0; +} + +static int +xmlSchemaItemListAdd(xmlSchemaItemListPtr list, void *item) +{ + if (list->items == NULL) { + list->items = (void **) xmlMalloc( + 20 * sizeof(void *)); + if (list->items == NULL) { + xmlSchemaPErrMemory(NULL, "allocating new item list", NULL); + return(-1); + } + list->sizeItems = 20; + } else if (list->sizeItems <= list->nbItems) { + list->sizeItems *= 2; + list->items = (void **) xmlRealloc(list->items, + list->sizeItems * sizeof(void *)); + if (list->items == NULL) { + xmlSchemaPErrMemory(NULL, "growing item list", NULL); + list->sizeItems = 0; + return(-1); + } + } + list->items[list->nbItems++] = item; + return(0); +} + +static int +xmlSchemaItemListAddSize(xmlSchemaItemListPtr list, + int initialSize, + void *item) +{ + if (list->items == NULL) { + if (initialSize <= 0) + initialSize = 1; + list->items = (void **) xmlMalloc( + initialSize * sizeof(void *)); + if (list->items == NULL) { + xmlSchemaPErrMemory(NULL, "allocating new item list", NULL); + return(-1); + } + list->sizeItems = initialSize; + } else if (list->sizeItems <= list->nbItems) { + list->sizeItems *= 2; + list->items = (void **) xmlRealloc(list->items, + list->sizeItems * sizeof(void *)); + if (list->items == NULL) { + xmlSchemaPErrMemory(NULL, "growing item list", NULL); + list->sizeItems = 0; + return(-1); + } + } + list->items[list->nbItems++] = item; + return(0); +} + +static int +xmlSchemaItemListInsert(xmlSchemaItemListPtr list, void *item, int idx) +{ + if (list->items == NULL) { + list->items = (void **) xmlMalloc( + 20 * sizeof(void *)); + if (list->items == NULL) { + xmlSchemaPErrMemory(NULL, "allocating new item list", NULL); + return(-1); + } + list->sizeItems = 20; + } else if (list->sizeItems <= list->nbItems) { + list->sizeItems *= 2; + list->items = (void **) xmlRealloc(list->items, + list->sizeItems * sizeof(void *)); + if (list->items == NULL) { + xmlSchemaPErrMemory(NULL, "growing item list", NULL); + list->sizeItems = 0; + return(-1); + } + } + /* + * Just append if the index is greater/equal than the item count. + */ + if (idx >= list->nbItems) { + list->items[list->nbItems++] = item; + } else { + int i; + for (i = list->nbItems; i > idx; i--) + list->items[i] = list->items[i-1]; + list->items[idx] = item; + list->nbItems++; + } + return(0); +} + +#if 0 /* enable if ever needed */ +static int +xmlSchemaItemListInsertSize(xmlSchemaItemListPtr list, + int initialSize, + void *item, + int idx) +{ + if (list->items == NULL) { + if (initialSize <= 0) + initialSize = 1; + list->items = (void **) xmlMalloc( + initialSize * sizeof(void *)); + if (list->items == NULL) { + xmlSchemaPErrMemory(NULL, "allocating new item list", NULL); + return(-1); + } + list->sizeItems = initialSize; + } else if (list->sizeItems <= list->nbItems) { + list->sizeItems *= 2; + list->items = (void **) xmlRealloc(list->items, + list->sizeItems * sizeof(void *)); + if (list->items == NULL) { + xmlSchemaPErrMemory(NULL, "growing item list", NULL); + list->sizeItems = 0; + return(-1); + } + } + /* + * Just append if the index is greater/equal than the item count. + */ + if (idx >= list->nbItems) { + list->items[list->nbItems++] = item; + } else { + int i; + for (i = list->nbItems; i > idx; i--) + list->items[i] = list->items[i-1]; + list->items[idx] = item; + list->nbItems++; + } + return(0); +} +#endif + +static int +xmlSchemaItemListRemove(xmlSchemaItemListPtr list, int idx) +{ + int i; + if ((list->items == NULL) || (idx >= list->nbItems)) { + xmlSchemaPSimpleErr("Internal error: xmlSchemaItemListRemove, " + "index error.\n"); + return(-1); + } + + if (list->nbItems == 1) { + /* TODO: Really free the list? */ + xmlFree(list->items); + list->items = NULL; + list->nbItems = 0; + list->sizeItems = 0; + } else if (list->nbItems -1 == idx) { + list->nbItems--; + } else { + for (i = idx; i < list->nbItems -1; i++) + list->items[i] = list->items[i+1]; + list->nbItems--; + } + return(0); +} + +/** + * xmlSchemaItemListFree: + * @annot: a schema type structure + * + * Deallocate a annotation structure + */ +static void +xmlSchemaItemListFree(xmlSchemaItemListPtr list) +{ + if (list == NULL) + return; + if (list->items != NULL) + xmlFree(list->items); + xmlFree(list); +} + +static void +xmlSchemaBucketFree(xmlSchemaBucketPtr bucket) +{ + if (bucket == NULL) + return; + if (bucket->globals != NULL) { + xmlSchemaComponentListFree(bucket->globals); + xmlSchemaItemListFree(bucket->globals); + } + if (bucket->locals != NULL) { + xmlSchemaComponentListFree(bucket->locals); + xmlSchemaItemListFree(bucket->locals); + } + if (bucket->relations != NULL) { + xmlSchemaSchemaRelationPtr prev, cur = bucket->relations; + do { + prev = cur; + cur = cur->next; + xmlFree(prev); + } while (cur != NULL); + } + if ((! bucket->preserveDoc) && (bucket->doc != NULL)) { + xmlFreeDoc(bucket->doc); + } + if (bucket->type == XML_SCHEMA_SCHEMA_IMPORT) { + if (WXS_IMPBUCKET(bucket)->schema != NULL) + xmlSchemaFree(WXS_IMPBUCKET(bucket)->schema); + } + xmlFree(bucket); +} + +static xmlSchemaBucketPtr +xmlSchemaBucketCreate(xmlSchemaParserCtxtPtr pctxt, + int type, const xmlChar *targetNamespace) +{ + xmlSchemaBucketPtr ret; + int size; + xmlSchemaPtr mainSchema; + + if (WXS_CONSTRUCTOR(pctxt)->mainSchema == NULL) { + PERROR_INT("xmlSchemaBucketCreate", + "no main schema on constructor"); + return(NULL); + } + mainSchema = WXS_CONSTRUCTOR(pctxt)->mainSchema; + /* Create the schema bucket. */ + if (WXS_IS_BUCKET_INCREDEF(type)) + size = sizeof(xmlSchemaInclude); + else + size = sizeof(xmlSchemaImport); + ret = (xmlSchemaBucketPtr) xmlMalloc(size); + if (ret == NULL) { + xmlSchemaPErrMemory(NULL, "allocating schema bucket", NULL); + return(NULL); + } + memset(ret, 0, size); + ret->targetNamespace = targetNamespace; + ret->type = type; + ret->globals = xmlSchemaItemListCreate(); + if (ret->globals == NULL) { + xmlFree(ret); + return(NULL); + } + ret->locals = xmlSchemaItemListCreate(); + if (ret->locals == NULL) { + xmlFree(ret); + return(NULL); + } + /* + * The following will assure that only the first bucket is marked as + * XML_SCHEMA_SCHEMA_MAIN and it points to the *main* schema. + * For each following import buckets an xmlSchema will be created. + * An xmlSchema will be created for every distinct targetNamespace. + * We assign the targetNamespace to the schemata here. + */ + if (! WXS_HAS_BUCKETS(pctxt)) { + if (WXS_IS_BUCKET_INCREDEF(type)) { + PERROR_INT("xmlSchemaBucketCreate", + "first bucket but it's an include or redefine"); + xmlSchemaBucketFree(ret); + return(NULL); + } + /* Force the type to be XML_SCHEMA_SCHEMA_MAIN. */ + ret->type = XML_SCHEMA_SCHEMA_MAIN; + /* Point to the *main* schema. */ + WXS_CONSTRUCTOR(pctxt)->mainBucket = ret; + WXS_IMPBUCKET(ret)->schema = mainSchema; + /* + * Ensure that the main schema gets a targetNamespace. + */ + mainSchema->targetNamespace = targetNamespace; + } else { + if (type == XML_SCHEMA_SCHEMA_MAIN) { + PERROR_INT("xmlSchemaBucketCreate", + "main bucket but it's not the first one"); + xmlSchemaBucketFree(ret); + return(NULL); + } else if (type == XML_SCHEMA_SCHEMA_IMPORT) { + /* + * Create a schema for imports and assign the + * targetNamespace. + */ + WXS_IMPBUCKET(ret)->schema = xmlSchemaNewSchema(pctxt); + if (WXS_IMPBUCKET(ret)->schema == NULL) { + xmlSchemaBucketFree(ret); + return(NULL); + } + WXS_IMPBUCKET(ret)->schema->targetNamespace = targetNamespace; + } + } + if (WXS_IS_BUCKET_IMPMAIN(type)) { + int res; + /* + * Imports go into the "schemasImports" slot of the main *schema*. + * Note that we create an import entry for the main schema as well; i.e., + * even if there's only one schema, we'll get an import. + */ + if (mainSchema->schemasImports == NULL) { + mainSchema->schemasImports = xmlHashCreateDict(5, + WXS_CONSTRUCTOR(pctxt)->dict); + if (mainSchema->schemasImports == NULL) { + xmlSchemaBucketFree(ret); + return(NULL); + } + } + if (targetNamespace == NULL) + res = xmlHashAddEntry(mainSchema->schemasImports, + XML_SCHEMAS_NO_NAMESPACE, ret); + else + res = xmlHashAddEntry(mainSchema->schemasImports, + targetNamespace, ret); + if (res != 0) { + PERROR_INT("xmlSchemaBucketCreate", + "failed to add the schema bucket to the hash"); + xmlSchemaBucketFree(ret); + return(NULL); + } + } else { + /* Set the @ownerImport of an include bucket. */ + if (WXS_IS_BUCKET_IMPMAIN(WXS_CONSTRUCTOR(pctxt)->bucket->type)) + WXS_INCBUCKET(ret)->ownerImport = + WXS_IMPBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket); + else + WXS_INCBUCKET(ret)->ownerImport = + WXS_INCBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket)->ownerImport; + + /* Includes got into the "includes" slot of the *main* schema. */ + if (mainSchema->includes == NULL) { + mainSchema->includes = xmlSchemaItemListCreate(); + if (mainSchema->includes == NULL) { + xmlSchemaBucketFree(ret); + return(NULL); + } + } + xmlSchemaItemListAdd(mainSchema->includes, ret); + } + /* + * Add to list of all buckets; this is used for lookup + * during schema construction time only. + */ + if (xmlSchemaItemListAdd(WXS_CONSTRUCTOR(pctxt)->buckets, ret) == -1) + return(NULL); + return(ret); +} + +static int +xmlSchemaAddItemSize(xmlSchemaItemListPtr *list, int initialSize, void *item) +{ + if (*list == NULL) { + *list = xmlSchemaItemListCreate(); + if (*list == NULL) + return(-1); + } + xmlSchemaItemListAddSize(*list, initialSize, item); + return(0); +} + +/** + * xmlSchemaFreeAnnot: + * @annot: a schema type structure + * + * Deallocate a annotation structure + */ +static void +xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot) +{ + if (annot == NULL) + return; + if (annot->next == NULL) { + xmlFree(annot); + } else { + xmlSchemaAnnotPtr prev; + + do { + prev = annot; + annot = annot->next; + xmlFree(prev); + } while (annot != NULL); + } +} + +/** + * xmlSchemaFreeNotation: + * @schema: a schema notation structure + * + * Deallocate a Schema Notation structure. + */ +static void +xmlSchemaFreeNotation(xmlSchemaNotationPtr nota) +{ + if (nota == NULL) + return; + xmlFree(nota); +} + +/** + * xmlSchemaFreeAttribute: + * @attr: an attribute declaration + * + * Deallocates an attribute declaration structure. + */ +static void +xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr) +{ + if (attr == NULL) + return; + if (attr->annot != NULL) + xmlSchemaFreeAnnot(attr->annot); + if (attr->defVal != NULL) + xmlSchemaFreeValue(attr->defVal); + xmlFree(attr); +} + +/** + * xmlSchemaFreeAttributeUse: + * @use: an attribute use + * + * Deallocates an attribute use structure. + */ +static void +xmlSchemaFreeAttributeUse(xmlSchemaAttributeUsePtr use) +{ + if (use == NULL) + return; + if (use->annot != NULL) + xmlSchemaFreeAnnot(use->annot); + if (use->defVal != NULL) + xmlSchemaFreeValue(use->defVal); + xmlFree(use); +} + +/** + * xmlSchemaFreeAttributeUseProhib: + * @prohib: an attribute use prohibition + * + * Deallocates an attribute use structure. + */ +static void +xmlSchemaFreeAttributeUseProhib(xmlSchemaAttributeUseProhibPtr prohib) +{ + if (prohib == NULL) + return; + xmlFree(prohib); +} + +/** + * xmlSchemaFreeWildcardNsSet: + * set: a schema wildcard namespace + * + * Deallocates a list of wildcard constraint structures. + */ +static void +xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set) +{ + xmlSchemaWildcardNsPtr next; + + while (set != NULL) { + next = set->next; + xmlFree(set); + set = next; + } +} + +/** + * xmlSchemaFreeWildcard: + * @wildcard: a wildcard structure + * + * Deallocates a wildcard structure. + */ +void +xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard) +{ + if (wildcard == NULL) + return; + if (wildcard->annot != NULL) + xmlSchemaFreeAnnot(wildcard->annot); + if (wildcard->nsSet != NULL) + xmlSchemaFreeWildcardNsSet(wildcard->nsSet); + if (wildcard->negNsSet != NULL) + xmlFree(wildcard->negNsSet); + xmlFree(wildcard); +} + +/** + * xmlSchemaFreeAttributeGroup: + * @schema: a schema attribute group structure + * + * Deallocate a Schema Attribute Group structure. + */ +static void +xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attrGr) +{ + if (attrGr == NULL) + return; + if (attrGr->annot != NULL) + xmlSchemaFreeAnnot(attrGr->annot); + if (attrGr->attrUses != NULL) + xmlSchemaItemListFree(WXS_LIST_CAST attrGr->attrUses); + xmlFree(attrGr); +} + +/** + * xmlSchemaFreeQNameRef: + * @item: a QName reference structure + * + * Deallocatea a QName reference structure. + */ +static void +xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item) +{ + xmlFree(item); +} + +/** + * xmlSchemaFreeTypeLinkList: + * @alink: a type link + * + * Deallocate a list of types. + */ +static void +xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link) +{ + xmlSchemaTypeLinkPtr next; + + while (link != NULL) { + next = link->next; + xmlFree(link); + link = next; + } +} + +static void +xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto) +{ + xmlSchemaIDCStateObjPtr next; + while (sto != NULL) { + next = sto->next; + if (sto->history != NULL) + xmlFree(sto->history); + if (sto->xpathCtxt != NULL) + xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt); + xmlFree(sto); + sto = next; + } +} + +/** + * xmlSchemaFreeIDC: + * @idc: a identity-constraint definition + * + * Deallocates an identity-constraint definition. + */ +static void +xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef) +{ + xmlSchemaIDCSelectPtr cur, prev; + + if (idcDef == NULL) + return; + if (idcDef->annot != NULL) + xmlSchemaFreeAnnot(idcDef->annot); + /* Selector */ + if (idcDef->selector != NULL) { + if (idcDef->selector->xpathComp != NULL) + xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp); + xmlFree(idcDef->selector); + } + /* Fields */ + if (idcDef->fields != NULL) { + cur = idcDef->fields; + do { + prev = cur; + cur = cur->next; + if (prev->xpathComp != NULL) + xmlFreePattern((xmlPatternPtr) prev->xpathComp); + xmlFree(prev); + } while (cur != NULL); + } + xmlFree(idcDef); +} + +/** + * xmlSchemaFreeElement: + * @schema: a schema element structure + * + * Deallocate a Schema Element structure. + */ +static void +xmlSchemaFreeElement(xmlSchemaElementPtr elem) +{ + if (elem == NULL) + return; + if (elem->annot != NULL) + xmlSchemaFreeAnnot(elem->annot); + if (elem->contModel != NULL) + xmlRegFreeRegexp(elem->contModel); + if (elem->defVal != NULL) + xmlSchemaFreeValue(elem->defVal); + xmlFree(elem); +} + +/** + * xmlSchemaFreeFacet: + * @facet: a schema facet structure + * + * Deallocate a Schema Facet structure. + */ +void +xmlSchemaFreeFacet(xmlSchemaFacetPtr facet) +{ + if (facet == NULL) + return; + if (facet->val != NULL) + xmlSchemaFreeValue(facet->val); + if (facet->regexp != NULL) + xmlRegFreeRegexp(facet->regexp); + if (facet->annot != NULL) + xmlSchemaFreeAnnot(facet->annot); + xmlFree(facet); +} + +/** + * xmlSchemaFreeType: + * @type: a schema type structure + * + * Deallocate a Schema Type structure. + */ +void +xmlSchemaFreeType(xmlSchemaTypePtr type) +{ + if (type == NULL) + return; + if (type->annot != NULL) + xmlSchemaFreeAnnot(type->annot); + if (type->facets != NULL) { + xmlSchemaFacetPtr facet, next; + + facet = type->facets; + while (facet != NULL) { + next = facet->next; + xmlSchemaFreeFacet(facet); + facet = next; + } + } + if (type->attrUses != NULL) + xmlSchemaItemListFree((xmlSchemaItemListPtr) type->attrUses); + if (type->memberTypes != NULL) + xmlSchemaFreeTypeLinkList(type->memberTypes); + if (type->facetSet != NULL) { + xmlSchemaFacetLinkPtr next, link; + + link = type->facetSet; + do { + next = link->next; + xmlFree(link); + link = next; + } while (link != NULL); + } + if (type->contModel != NULL) + xmlRegFreeRegexp(type->contModel); + xmlFree(type); +} + +/** + * xmlSchemaFreeModelGroupDef: + * @item: a schema model group definition + * + * Deallocates a schema model group definition. + */ +static void +xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item) +{ + if (item->annot != NULL) + xmlSchemaFreeAnnot(item->annot); + xmlFree(item); +} + +/** + * xmlSchemaFreeModelGroup: + * @item: a schema model group + * + * Deallocates a schema model group structure. + */ +static void +xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item) +{ + if (item->annot != NULL) + xmlSchemaFreeAnnot(item->annot); + xmlFree(item); +} + +static void +xmlSchemaComponentListFree(xmlSchemaItemListPtr list) +{ + if ((list == NULL) || (list->nbItems == 0)) + return; + { + xmlSchemaTreeItemPtr item; + xmlSchemaTreeItemPtr *items = (xmlSchemaTreeItemPtr *) list->items; + int i; + + for (i = 0; i < list->nbItems; i++) { + item = items[i]; + if (item == NULL) + continue; + switch (item->type) { + case XML_SCHEMA_TYPE_SIMPLE: + case XML_SCHEMA_TYPE_COMPLEX: + xmlSchemaFreeType((xmlSchemaTypePtr) item); + break; + case XML_SCHEMA_TYPE_ATTRIBUTE: + xmlSchemaFreeAttribute((xmlSchemaAttributePtr) item); + break; + case XML_SCHEMA_TYPE_ATTRIBUTE_USE: + xmlSchemaFreeAttributeUse((xmlSchemaAttributeUsePtr) item); + break; + case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB: + xmlSchemaFreeAttributeUseProhib( + (xmlSchemaAttributeUseProhibPtr) item); + break; + case XML_SCHEMA_TYPE_ELEMENT: + xmlSchemaFreeElement((xmlSchemaElementPtr) item); + break; + case XML_SCHEMA_TYPE_PARTICLE: + if (item->annot != NULL) + xmlSchemaFreeAnnot(item->annot); + xmlFree(item); + break; + case XML_SCHEMA_TYPE_SEQUENCE: + case XML_SCHEMA_TYPE_CHOICE: + case XML_SCHEMA_TYPE_ALL: + xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item); + break; + case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: + xmlSchemaFreeAttributeGroup( + (xmlSchemaAttributeGroupPtr) item); + break; + case XML_SCHEMA_TYPE_GROUP: + xmlSchemaFreeModelGroupDef( + (xmlSchemaModelGroupDefPtr) item); + break; + case XML_SCHEMA_TYPE_ANY: + case XML_SCHEMA_TYPE_ANY_ATTRIBUTE: + xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item); + break; + case XML_SCHEMA_TYPE_IDC_KEY: + case XML_SCHEMA_TYPE_IDC_UNIQUE: + case XML_SCHEMA_TYPE_IDC_KEYREF: + xmlSchemaFreeIDC((xmlSchemaIDCPtr) item); + break; + case XML_SCHEMA_TYPE_NOTATION: + xmlSchemaFreeNotation((xmlSchemaNotationPtr) item); + break; + case XML_SCHEMA_EXTRA_QNAMEREF: + xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item); + break; + default: { + /* TODO: This should never be hit. */ + xmlSchemaPSimpleInternalErr(NULL, + "Internal error: xmlSchemaComponentListFree, " + "unexpected component type '%s'\n", + (const xmlChar *) WXS_ITEM_TYPE_NAME(item)); + } + break; + } + } + list->nbItems = 0; + } +} + +/** + * xmlSchemaFree: + * @schema: a schema structure + * + * Deallocate a Schema structure. + */ +void +xmlSchemaFree(xmlSchemaPtr schema) +{ + if (schema == NULL) + return; + /* @volatiles is not used anymore :-/ */ + if (schema->volatiles != NULL) + TODO + /* + * Note that those slots are not responsible for freeing + * schema components anymore; this will now be done by + * the schema buckets. + */ + if (schema->notaDecl != NULL) + xmlHashFree(schema->notaDecl, NULL); + if (schema->attrDecl != NULL) + xmlHashFree(schema->attrDecl, NULL); + if (schema->attrgrpDecl != NULL) + xmlHashFree(schema->attrgrpDecl, NULL); + if (schema->elemDecl != NULL) + xmlHashFree(schema->elemDecl, NULL); + if (schema->typeDecl != NULL) + xmlHashFree(schema->typeDecl, NULL); + if (schema->groupDecl != NULL) + xmlHashFree(schema->groupDecl, NULL); + if (schema->idcDef != NULL) + xmlHashFree(schema->idcDef, NULL); + + if (schema->schemasImports != NULL) + xmlHashFree(schema->schemasImports, + (xmlHashDeallocator) xmlSchemaBucketFree); + if (schema->includes != NULL) { + xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->includes; + int i; + for (i = 0; i < list->nbItems; i++) { + xmlSchemaBucketFree((xmlSchemaBucketPtr) list->items[i]); + } + xmlSchemaItemListFree(list); + } + if (schema->annot != NULL) + xmlSchemaFreeAnnot(schema->annot); + /* Never free the doc here, since this will be done by the buckets. */ + + xmlDictFree(schema->dict); + xmlFree(schema); +} + +/************************************************************************ + * * + * Debug functions * + * * + ************************************************************************/ + +#ifdef LIBXML_OUTPUT_ENABLED + +static void +xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output); /* forward */ + +/** + * xmlSchemaElementDump: + * @elem: an element + * @output: the file output + * + * Dump the element + */ +static void +xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output, + const xmlChar * name ATTRIBUTE_UNUSED, + const xmlChar * namespace ATTRIBUTE_UNUSED, + const xmlChar * context ATTRIBUTE_UNUSED) +{ + if (elem == NULL) + return; + + + fprintf(output, "Element"); + if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL) + fprintf(output, " (global)"); + fprintf(output, ": '%s' ", elem->name); + if (namespace != NULL) + fprintf(output, "ns '%s'", namespace); + fprintf(output, "\n"); +#if 0 + if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) { + fprintf(output, " min %d ", elem->minOccurs); + if (elem->maxOccurs >= UNBOUNDED) + fprintf(output, "max: unbounded\n"); + else if (elem->maxOccurs != 1) + fprintf(output, "max: %d\n", elem->maxOccurs); + else + fprintf(output, "\n"); + } +#endif + /* + * Misc other properties. + */ + if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) || + (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) || + (elem->flags & XML_SCHEMAS_ELEM_FIXED) || + (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)) { + fprintf(output, " props: "); + if (elem->flags & XML_SCHEMAS_ELEM_FIXED) + fprintf(output, "[fixed] "); + if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT) + fprintf(output, "[default] "); + if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) + fprintf(output, "[abstract] "); + if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE) + fprintf(output, "[nillable] "); + fprintf(output, "\n"); + } + /* + * Default/fixed value. + */ + if (elem->value != NULL) + fprintf(output, " value: '%s'\n", elem->value); + /* + * Type. + */ + if (elem->namedType != NULL) { + fprintf(output, " type: '%s' ", elem->namedType); + if (elem->namedTypeNs != NULL) + fprintf(output, "ns '%s'\n", elem->namedTypeNs); + else + fprintf(output, "\n"); + } else if (elem->subtypes != NULL) { + /* + * Dump local types. + */ + xmlSchemaTypeDump(elem->subtypes, output); + } + /* + * Substitution group. + */ + if (elem->substGroup != NULL) { + fprintf(output, " substitutionGroup: '%s' ", elem->substGroup); + if (elem->substGroupNs != NULL) + fprintf(output, "ns '%s'\n", elem->substGroupNs); + else + fprintf(output, "\n"); + } +} + +/** + * xmlSchemaAnnotDump: + * @output: the file output + * @annot: a annotation + * + * Dump the annotation + */ +static void +xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot) +{ + xmlChar *content; + + if (annot == NULL) + return; + + content = xmlNodeGetContent(annot->content); + if (content != NULL) { + fprintf(output, " Annot: %s\n", content); + xmlFree(content); + } else + fprintf(output, " Annot: empty\n"); +} + +/** + * xmlSchemaContentModelDump: + * @particle: the schema particle + * @output: the file output + * @depth: the depth used for intentation + * + * Dump a SchemaType structure + */ +static void +xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth) +{ + xmlChar *str = NULL; + xmlSchemaTreeItemPtr term; + char shift[100]; + int i; + + if (particle == NULL) + return; + for (i = 0;((i < depth) && (i < 25));i++) + shift[2 * i] = shift[2 * i + 1] = ' '; + shift[2 * i] = shift[2 * i + 1] = 0; + fprintf(output, shift); + if (particle->children == NULL) { + fprintf(output, "MISSING particle term\n"); + return; + } + term = particle->children; + if (term == NULL) { + fprintf(output, "(NULL)"); + } else { + switch (term->type) { + case XML_SCHEMA_TYPE_ELEMENT: + fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str, + ((xmlSchemaElementPtr)term)->targetNamespace, + ((xmlSchemaElementPtr)term)->name)); + FREE_AND_NULL(str); + break; + case XML_SCHEMA_TYPE_SEQUENCE: + fprintf(output, "SEQUENCE"); + break; + case XML_SCHEMA_TYPE_CHOICE: + fprintf(output, "CHOICE"); + break; + case XML_SCHEMA_TYPE_ALL: + fprintf(output, "ALL"); + break; + case XML_SCHEMA_TYPE_ANY: + fprintf(output, "ANY"); + break; + default: + fprintf(output, "UNKNOWN\n"); + return; + } + } + if (particle->minOccurs != 1) + fprintf(output, " min: %d", particle->minOccurs); + if (particle->maxOccurs >= UNBOUNDED) + fprintf(output, " max: unbounded"); + else if (particle->maxOccurs != 1) + fprintf(output, " max: %d", particle->maxOccurs); + fprintf(output, "\n"); + if (term && + ((term->type == XML_SCHEMA_TYPE_SEQUENCE) || + (term->type == XML_SCHEMA_TYPE_CHOICE) || + (term->type == XML_SCHEMA_TYPE_ALL)) && + (term->children != NULL)) { + xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children, + output, depth +1); + } + if (particle->next != NULL) + xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next, + output, depth); +} + +/** + * xmlSchemaAttrUsesDump: + * @uses: attribute uses list + * @output: the file output + * + * Dumps a list of attribute use components. + */ +static void +xmlSchemaAttrUsesDump(xmlSchemaItemListPtr uses, FILE * output) +{ + xmlSchemaAttributeUsePtr use; + xmlSchemaAttributeUseProhibPtr prohib; + xmlSchemaQNameRefPtr ref; + const xmlChar *name, *tns; + xmlChar *str = NULL; + int i; + + if ((uses == NULL) || (uses->nbItems == 0)) + return; + + fprintf(output, " attributes:\n"); + for (i = 0; i < uses->nbItems; i++) { + use = uses->items[i]; + if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) { + fprintf(output, " [prohibition] "); + prohib = (xmlSchemaAttributeUseProhibPtr) use; + name = prohib->name; + tns = prohib->targetNamespace; + } else if (use->type == XML_SCHEMA_EXTRA_QNAMEREF) { + fprintf(output, " [reference] "); + ref = (xmlSchemaQNameRefPtr) use; + name = ref->name; + tns = ref->targetNamespace; + } else { + fprintf(output, " [use] "); + name = WXS_ATTRUSE_DECL_NAME(use); + tns = WXS_ATTRUSE_DECL_TNS(use); + } + fprintf(output, "'%s'\n", + (const char *) xmlSchemaFormatQName(&str, tns, name)); + FREE_AND_NULL(str); + } +} + +/** + * xmlSchemaTypeDump: + * @output: the file output + * @type: a type structure + * + * Dump a SchemaType structure + */ +static void +xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output) +{ + if (type == NULL) { + fprintf(output, "Type: NULL\n"); + return; + } + fprintf(output, "Type: "); + if (type->name != NULL) + fprintf(output, "'%s' ", type->name); + else + fprintf(output, "(no name) "); + if (type->targetNamespace != NULL) + fprintf(output, "ns '%s' ", type->targetNamespace); + switch (type->type) { + case XML_SCHEMA_TYPE_BASIC: + fprintf(output, "[basic] "); + break; + case XML_SCHEMA_TYPE_SIMPLE: + fprintf(output, "[simple] "); + break; + case XML_SCHEMA_TYPE_COMPLEX: + fprintf(output, "[complex] "); + break; + case XML_SCHEMA_TYPE_SEQUENCE: + fprintf(output, "[sequence] "); + break; + case XML_SCHEMA_TYPE_CHOICE: + fprintf(output, "[choice] "); + break; + case XML_SCHEMA_TYPE_ALL: + fprintf(output, "[all] "); + break; + case XML_SCHEMA_TYPE_UR: + fprintf(output, "[ur] "); + break; + case XML_SCHEMA_TYPE_RESTRICTION: + fprintf(output, "[restriction] "); + break; + case XML_SCHEMA_TYPE_EXTENSION: + fprintf(output, "[extension] "); + break; + default: + fprintf(output, "[unknown type %d] ", type->type); + break; + } + fprintf(output, "content: "); + switch (type->contentType) { + case XML_SCHEMA_CONTENT_UNKNOWN: + fprintf(output, "[unknown] "); + break; + case XML_SCHEMA_CONTENT_EMPTY: + fprintf(output, "[empty] "); + break; + case XML_SCHEMA_CONTENT_ELEMENTS: + fprintf(output, "[element] "); + break; + case XML_SCHEMA_CONTENT_MIXED: + fprintf(output, "[mixed] "); + break; + case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS: + /* not used. */ + break; + case XML_SCHEMA_CONTENT_BASIC: + fprintf(output, "[basic] "); + break; + case XML_SCHEMA_CONTENT_SIMPLE: + fprintf(output, "[simple] "); + break; + case XML_SCHEMA_CONTENT_ANY: + fprintf(output, "[any] "); + break; + } + fprintf(output, "\n"); + if (type->base != NULL) { + fprintf(output, " base type: '%s'", type->base); + if (type->baseNs != NULL) + fprintf(output, " ns '%s'\n", type->baseNs); + else + fprintf(output, "\n"); + } + if (type->attrUses != NULL) + xmlSchemaAttrUsesDump(type->attrUses, output); + if (type->annot != NULL) + xmlSchemaAnnotDump(output, type->annot); +#ifdef DUMP_CONTENT_MODEL + if ((type->type == XML_SCHEMA_TYPE_COMPLEX) && + (type->subtypes != NULL)) { + xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes, + output, 1); + } +#endif +} + +/** + * xmlSchemaDump: + * @output: the file output + * @schema: a schema structure + * + * Dump a Schema structure. + */ +void +xmlSchemaDump(FILE * output, xmlSchemaPtr schema) +{ + if (output == NULL) + return; + if (schema == NULL) { + fprintf(output, "Schemas: NULL\n"); + return; + } + fprintf(output, "Schemas: "); + if (schema->name != NULL) + fprintf(output, "%s, ", schema->name); + else + fprintf(output, "no name, "); + if (schema->targetNamespace != NULL) + fprintf(output, "%s", (const char *) schema->targetNamespace); + else + fprintf(output, "no target namespace"); + fprintf(output, "\n"); + if (schema->annot != NULL) + xmlSchemaAnnotDump(output, schema->annot); + xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump, + output); + xmlHashScanFull(schema->elemDecl, + (xmlHashScannerFull) xmlSchemaElementDump, output); +} + +#ifdef DEBUG_IDC_NODE_TABLE +/** + * xmlSchemaDebugDumpIDCTable: + * @vctxt: the WXS validation context + * + * Displays the current IDC table for debug purposes. + */ +static void +xmlSchemaDebugDumpIDCTable(FILE * output, + const xmlChar *namespaceName, + const xmlChar *localName, + xmlSchemaPSVIIDCBindingPtr bind) +{ + xmlChar *str = NULL; + const xmlChar *value; + xmlSchemaPSVIIDCNodePtr tab; + xmlSchemaPSVIIDCKeyPtr key; + int i, j, res; + + fprintf(output, "IDC: TABLES on '%s'\n", + xmlSchemaFormatQName(&str, namespaceName, localName)); + FREE_AND_NULL(str) + + if (bind == NULL) + return; + do { + fprintf(output, "IDC: BINDING '%s' (%d)\n", + xmlSchemaGetComponentQName(&str, + bind->definition), bind->nbNodes); + FREE_AND_NULL(str) + for (i = 0; i < bind->nbNodes; i++) { + tab = bind->nodeTable[i]; + fprintf(output, " ( "); + for (j = 0; j < bind->definition->nbFields; j++) { + key = tab->keys[j]; + if ((key != NULL) && (key->val != NULL)) { + res = xmlSchemaGetCanonValue(key->val, &value); + if (res >= 0) + fprintf(output, "'%s' ", value); + else + fprintf(output, "CANON-VALUE-FAILED "); + if (res == 0) + FREE_AND_NULL(value) + } else if (key != NULL) + fprintf(output, "(no val), "); + else + fprintf(output, "(key missing), "); + } + fprintf(output, ")\n"); + } + if (bind->dupls && bind->dupls->nbItems) { + fprintf(output, "IDC: dupls (%d):\n", bind->dupls->nbItems); + for (i = 0; i < bind->dupls->nbItems; i++) { + tab = bind->dupls->items[i]; + fprintf(output, " ( "); + for (j = 0; j < bind->definition->nbFields; j++) { + key = tab->keys[j]; + if ((key != NULL) && (key->val != NULL)) { + res = xmlSchemaGetCanonValue(key->val, &value); + if (res >= 0) + fprintf(output, "'%s' ", value); + else + fprintf(output, "CANON-VALUE-FAILED "); + if (res == 0) + FREE_AND_NULL(value) + } else if (key != NULL) + fprintf(output, "(no val), "); + else + fprintf(output, "(key missing), "); + } + fprintf(output, ")\n"); + } + } + bind = bind->next; + } while (bind != NULL); +} +#endif /* DEBUG_IDC */ +#endif /* LIBXML_OUTPUT_ENABLED */ + +/************************************************************************ + * * + * Utilities * + * * + ************************************************************************/ + +/** + * xmlSchemaGetPropNode: + * @node: the element node + * @name: the name of the attribute + * + * Seeks an attribute with a name of @name in + * no namespace. + * + * Returns the attribute or NULL if not present. + */ +static xmlAttrPtr +xmlSchemaGetPropNode(xmlNodePtr node, const char *name) +{ + xmlAttrPtr prop; + + if ((node == NULL) || (name == NULL)) + return(NULL); + prop = node->properties; + while (prop != NULL) { + if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name)) + return(prop); + prop = prop->next; + } + return (NULL); +} + +/** + * xmlSchemaGetPropNodeNs: + * @node: the element node + * @uri: the uri + * @name: the name of the attribute + * + * Seeks an attribute with a local name of @name and + * a namespace URI of @uri. + * + * Returns the attribute or NULL if not present. + */ +static xmlAttrPtr +xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name) +{ + xmlAttrPtr prop; + + if ((node == NULL) || (name == NULL)) + return(NULL); + prop = node->properties; + while (prop != NULL) { + if ((prop->ns != NULL) && + xmlStrEqual(prop->name, BAD_CAST name) && + xmlStrEqual(prop->ns->href, BAD_CAST uri)) + return(prop); + prop = prop->next; + } + return (NULL); +} + +static const xmlChar * +xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node) +{ + xmlChar *val; + const xmlChar *ret; + + val = xmlNodeGetContent(node); + if (val == NULL) + val = xmlStrdup((xmlChar *)""); + ret = xmlDictLookup(ctxt->dict, val, -1); + xmlFree(val); + return(ret); +} + +static const xmlChar * +xmlSchemaGetNodeContentNoDict(xmlNodePtr node) +{ + return((const xmlChar*) xmlNodeGetContent(node)); +} + +/** + * xmlSchemaGetProp: + * @ctxt: the parser context + * @node: the node + * @name: the property name + * + * Read a attribute value and internalize the string + * + * Returns the string or NULL if not present. + */ +static const xmlChar * +xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, + const char *name) +{ + xmlChar *val; + const xmlChar *ret; + + val = xmlGetNoNsProp(node, BAD_CAST name); + if (val == NULL) + return(NULL); + ret = xmlDictLookup(ctxt->dict, val, -1); + xmlFree(val); + return(ret); +} + +/************************************************************************ + * * + * Parsing functions * + * * + ************************************************************************/ + +#define WXS_FIND_GLOBAL_ITEM(slot) \ + if (xmlStrEqual(nsName, schema->targetNamespace)) { \ + ret = xmlHashLookup(schema->slot, name); \ + if (ret != NULL) goto exit; \ + } \ + if (xmlHashSize(schema->schemasImports) > 1) { \ + xmlSchemaImportPtr import; \ + if (nsName == NULL) \ + import = xmlHashLookup(schema->schemasImports, \ + XML_SCHEMAS_NO_NAMESPACE); \ + else \ + import = xmlHashLookup(schema->schemasImports, nsName); \ + if (import == NULL) \ + goto exit; \ + ret = xmlHashLookup(import->schema->slot, name); \ + } + +/** + * xmlSchemaGetElem: + * @schema: the schema context + * @name: the element name + * @ns: the element namespace + * + * Lookup a global element declaration in the schema. + * + * Returns the element declaration or NULL if not found. + */ +static xmlSchemaElementPtr +xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name, + const xmlChar * nsName) +{ + xmlSchemaElementPtr ret = NULL; + + if ((name == NULL) || (schema == NULL)) + return(NULL); + if (schema != NULL) { + WXS_FIND_GLOBAL_ITEM(elemDecl) + } +exit: +#ifdef DEBUG + if (ret == NULL) { + if (nsName == NULL) + fprintf(stderr, "Unable to lookup element decl. %s", name); + else + fprintf(stderr, "Unable to lookup element decl. %s:%s", name, + nsName); + } +#endif + return (ret); +} + +/** + * xmlSchemaGetType: + * @schema: the main schema + * @name: the type's name + * nsName: the type's namespace + * + * Lookup a type in the schemas or the predefined types + * + * Returns the group definition or NULL if not found. + */ +static xmlSchemaTypePtr +xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name, + const xmlChar * nsName) +{ + xmlSchemaTypePtr ret = NULL; + + if (name == NULL) + return (NULL); + /* First try the built-in types. */ + if ((nsName != NULL) && xmlStrEqual(nsName, xmlSchemaNs)) { + ret = xmlSchemaGetPredefinedType(name, nsName); + if (ret != NULL) + goto exit; + /* + * Note that we try the parsed schemas as well here + * since one might have parsed the S4S, which contain more + * than the built-in types. + * TODO: Can we optimize this? + */ + } + if (schema != NULL) { + WXS_FIND_GLOBAL_ITEM(typeDecl) + } +exit: + +#ifdef DEBUG + if (ret == NULL) { + if (nsName == NULL) + fprintf(stderr, "Unable to lookup type %s", name); + else + fprintf(stderr, "Unable to lookup type %s:%s", name, + nsName); + } +#endif + return (ret); +} + +/** + * xmlSchemaGetAttributeDecl: + * @schema: the context of the schema + * @name: the name of the attribute + * @ns: the target namespace of the attribute + * + * Lookup a an attribute in the schema or imported schemas + * + * Returns the attribute declaration or NULL if not found. + */ +static xmlSchemaAttributePtr +xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name, + const xmlChar * nsName) +{ + xmlSchemaAttributePtr ret = NULL; + + if ((name == NULL) || (schema == NULL)) + return (NULL); + if (schema != NULL) { + WXS_FIND_GLOBAL_ITEM(attrDecl) + } +exit: +#ifdef DEBUG + if (ret == NULL) { + if (nsName == NULL) + fprintf(stderr, "Unable to lookup attribute %s", name); + else + fprintf(stderr, "Unable to lookup attribute %s:%s", name, + nsName); + } +#endif + return (ret); +} + +/** + * xmlSchemaGetAttributeGroup: + * @schema: the context of the schema + * @name: the name of the attribute group + * @ns: the target namespace of the attribute group + * + * Lookup a an attribute group in the schema or imported schemas + * + * Returns the attribute group definition or NULL if not found. + */ +static xmlSchemaAttributeGroupPtr +xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name, + const xmlChar * nsName) +{ + xmlSchemaAttributeGroupPtr ret = NULL; + + if ((name == NULL) || (schema == NULL)) + return (NULL); + if (schema != NULL) { + WXS_FIND_GLOBAL_ITEM(attrgrpDecl) + } +exit: + /* TODO: + if ((ret != NULL) && (ret->redef != NULL)) { + * Return the last redefinition. * + ret = ret->redef; + } + */ +#ifdef DEBUG + if (ret == NULL) { + if (nsName == NULL) + fprintf(stderr, "Unable to lookup attribute group %s", name); + else + fprintf(stderr, "Unable to lookup attribute group %s:%s", name, + nsName); + } +#endif + return (ret); +} + +/** + * xmlSchemaGetGroup: + * @schema: the context of the schema + * @name: the name of the group + * @ns: the target namespace of the group + * + * Lookup a group in the schema or imported schemas + * + * Returns the group definition or NULL if not found. + */ +static xmlSchemaModelGroupDefPtr +xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name, + const xmlChar * nsName) +{ + xmlSchemaModelGroupDefPtr ret = NULL; + + if ((name == NULL) || (schema == NULL)) + return (NULL); + if (schema != NULL) { + WXS_FIND_GLOBAL_ITEM(groupDecl) + } +exit: + +#ifdef DEBUG + if (ret == NULL) { + if (nsName == NULL) + fprintf(stderr, "Unable to lookup group %s", name); + else + fprintf(stderr, "Unable to lookup group %s:%s", name, + nsName); + } +#endif + return (ret); +} + +static xmlSchemaNotationPtr +xmlSchemaGetNotation(xmlSchemaPtr schema, + const xmlChar *name, + const xmlChar *nsName) +{ + xmlSchemaNotationPtr ret = NULL; + + if ((name == NULL) || (schema == NULL)) + return (NULL); + if (schema != NULL) { + WXS_FIND_GLOBAL_ITEM(notaDecl) + } +exit: + return (ret); +} + +static xmlSchemaIDCPtr +xmlSchemaGetIDC(xmlSchemaPtr schema, + const xmlChar *name, + const xmlChar *nsName) +{ + xmlSchemaIDCPtr ret = NULL; + + if ((name == NULL) || (schema == NULL)) + return (NULL); + if (schema != NULL) { + WXS_FIND_GLOBAL_ITEM(idcDef) + } +exit: + return (ret); +} + +/** + * xmlSchemaGetNamedComponent: + * @schema: the schema + * @name: the name of the group + * @ns: the target namespace of the group + * + * Lookup a group in the schema or imported schemas + * + * Returns the group definition or NULL if not found. + */ +static xmlSchemaBasicItemPtr +xmlSchemaGetNamedComponent(xmlSchemaPtr schema, + xmlSchemaTypeType itemType, + const xmlChar *name, + const xmlChar *targetNs) +{ + switch (itemType) { + case XML_SCHEMA_TYPE_GROUP: + return ((xmlSchemaBasicItemPtr) xmlSchemaGetGroup(schema, + name, targetNs)); + case XML_SCHEMA_TYPE_ELEMENT: + return ((xmlSchemaBasicItemPtr) xmlSchemaGetElem(schema, + name, targetNs)); + default: + TODO + return (NULL); + } +} + +/************************************************************************ + * * + * Parsing functions * + * * + ************************************************************************/ + +#define IS_BLANK_NODE(n) \ + (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content, -1))) + +/** + * xmlSchemaIsBlank: + * @str: a string + * @len: the length of the string or -1 + * + * Check if a string is ignorable + * + * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise + */ +static int +xmlSchemaIsBlank(xmlChar * str, int len) +{ + if (str == NULL) + return (1); + if (len < 0) { + while (*str != 0) { + if (!(IS_BLANK_CH(*str))) + return (0); + str++; + } + } else while ((*str != 0) && (len != 0)) { + if (!(IS_BLANK_CH(*str))) + return (0); + str++; + len--; + } + + return (1); +} + +#define WXS_COMP_NAME(c, t) ((t) (c))->name +#define WXS_COMP_TNS(c, t) ((t) (c))->targetNamespace +/* +* xmlSchemaFindRedefCompInGraph: +* ATTENTION TODO: This uses pointer comp. for strings. +*/ +static xmlSchemaBasicItemPtr +xmlSchemaFindRedefCompInGraph(xmlSchemaBucketPtr bucket, + xmlSchemaTypeType type, + const xmlChar *name, + const xmlChar *nsName) +{ + xmlSchemaBasicItemPtr ret; + int i; + + if ((bucket == NULL) || (name == NULL)) + return(NULL); + if ((bucket->globals == NULL) || + (bucket->globals->nbItems == 0)) + goto subschemas; + /* + * Search in global components. + */ + for (i = 0; i < bucket->globals->nbItems; i++) { + ret = bucket->globals->items[i]; + if (ret->type == type) { + switch (type) { + case XML_SCHEMA_TYPE_COMPLEX: + case XML_SCHEMA_TYPE_SIMPLE: + if ((WXS_COMP_NAME(ret, xmlSchemaTypePtr) == name) && + (WXS_COMP_TNS(ret, xmlSchemaTypePtr) == + nsName)) + { + return(ret); + } + break; + case XML_SCHEMA_TYPE_GROUP: + if ((WXS_COMP_NAME(ret, + xmlSchemaModelGroupDefPtr) == name) && + (WXS_COMP_TNS(ret, + xmlSchemaModelGroupDefPtr) == nsName)) + { + return(ret); + } + break; + case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: + if ((WXS_COMP_NAME(ret, + xmlSchemaAttributeGroupPtr) == name) && + (WXS_COMP_TNS(ret, + xmlSchemaAttributeGroupPtr) == nsName)) + { + return(ret); + } + break; + default: + /* Should not be hit. */ + return(NULL); + } + } + } +subschemas: + /* + * Process imported/included schemas. + */ + if (bucket->relations != NULL) { + xmlSchemaSchemaRelationPtr rel = bucket->relations; + + /* + * TODO: Marking the bucket will not avoid multiple searches + * in the same schema, but avoids at least circularity. + */ + bucket->flags |= XML_SCHEMA_BUCKET_MARKED; + do { + if ((rel->bucket != NULL) && + ((rel->bucket->flags & XML_SCHEMA_BUCKET_MARKED) == 0)) { + ret = xmlSchemaFindRedefCompInGraph(rel->bucket, + type, name, nsName); + if (ret != NULL) + return(ret); + } + rel = rel->next; + } while (rel != NULL); + bucket->flags ^= XML_SCHEMA_BUCKET_MARKED; + } + return(NULL); +} + +/** + * xmlSchemaAddNotation: + * @ctxt: a schema parser context + * @schema: the schema being built + * @name: the item name + * + * Add an XML schema annotation declaration + * *WARNING* this interface is highly subject to change + * + * Returns the new struture or NULL in case of error + */ +static xmlSchemaNotationPtr +xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, + const xmlChar *name, const xmlChar *nsName, + xmlNodePtr node ATTRIBUTE_UNUSED) +{ + xmlSchemaNotationPtr ret = NULL; + + if ((ctxt == NULL) || (schema == NULL) || (name == NULL)) + return (NULL); + + ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation)); + if (ret == NULL) { + xmlSchemaPErrMemory(ctxt, "add annotation", NULL); + return (NULL); + } + memset(ret, 0, sizeof(xmlSchemaNotation)); + ret->type = XML_SCHEMA_TYPE_NOTATION; + ret->name = name; + ret->targetNamespace = nsName; + /* TODO: do we need the node to be set? + * ret->node = node;*/ + WXS_ADD_GLOBAL(ctxt, ret); + return (ret); +} + +/** + * xmlSchemaAddAttribute: + * @ctxt: a schema parser context + * @schema: the schema being built + * @name: the item name + * @namespace: the namespace + * + * Add an XML schema Attrribute declaration + * *WARNING* this interface is highly subject to change + * + * Returns the new struture or NULL in case of error + */ +static xmlSchemaAttributePtr +xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, + const xmlChar * name, const xmlChar * nsName, + xmlNodePtr node, int topLevel) +{ + xmlSchemaAttributePtr ret = NULL; + + if ((ctxt == NULL) || (schema == NULL)) + return (NULL); + + ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute)); + if (ret == NULL) { + xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL); + return (NULL); + } + memset(ret, 0, sizeof(xmlSchemaAttribute)); + ret->type = XML_SCHEMA_TYPE_ATTRIBUTE; + ret->node = node; + ret->name = name; + ret->targetNamespace = nsName; + + if (topLevel) + WXS_ADD_GLOBAL(ctxt, ret); + else + WXS_ADD_LOCAL(ctxt, ret); + WXS_ADD_PENDING(ctxt, ret); + return (ret); +} + +/** + * xmlSchemaAddAttributeUse: + * @ctxt: a schema parser context + * @schema: the schema being built + * @name: the item name + * @namespace: the namespace + * + * Add an XML schema Attrribute declaration + * *WARNING* this interface is highly subject to change + * + * Returns the new struture or NULL in case of error + */ +static xmlSchemaAttributeUsePtr +xmlSchemaAddAttributeUse(xmlSchemaParserCtxtPtr pctxt, + xmlNodePtr node) +{ + xmlSchemaAttributeUsePtr ret = NULL; + + if (pctxt == NULL) + return (NULL); + + ret = (xmlSchemaAttributeUsePtr) xmlMalloc(sizeof(xmlSchemaAttributeUse)); + if (ret == NULL) { + xmlSchemaPErrMemory(pctxt, "allocating attribute", NULL); + return (NULL); + } + memset(ret, 0, sizeof(xmlSchemaAttributeUse)); + ret->type = XML_SCHEMA_TYPE_ATTRIBUTE_USE; + ret->node = node; + + WXS_ADD_LOCAL(pctxt, ret); + return (ret); +} + +/* +* xmlSchemaAddRedef: +* +* Adds a redefinition information. This is used at a later stage to: +* resolve references to the redefined components and to check constraints. +*/ +static xmlSchemaRedefPtr +xmlSchemaAddRedef(xmlSchemaParserCtxtPtr pctxt, + xmlSchemaBucketPtr targetBucket, + void *item, + const xmlChar *refName, + const xmlChar *refTargetNs) +{ + xmlSchemaRedefPtr ret; + + ret = (xmlSchemaRedefPtr) + xmlMalloc(sizeof(xmlSchemaRedef)); + if (ret == NULL) { + xmlSchemaPErrMemory(pctxt, + "allocating redefinition info", NULL); + return (NULL); + } + memset(ret, 0, sizeof(xmlSchemaRedef)); + ret->item = item; + ret->targetBucket = targetBucket; + ret->refName = refName; + ret->refTargetNs = refTargetNs; + if (WXS_CONSTRUCTOR(pctxt)->redefs == NULL) + WXS_CONSTRUCTOR(pctxt)->redefs = ret; + else + WXS_CONSTRUCTOR(pctxt)->lastRedef->next = ret; + WXS_CONSTRUCTOR(pctxt)->lastRedef = ret; + + return (ret); +} + +/** + * xmlSchemaAddAttributeGroupDefinition: + * @ctxt: a schema parser context + * @schema: the schema being built + * @name: the item name + * @nsName: the target namespace + * @node: the corresponding node + * + * Add an XML schema Attrribute Group definition. + * + * Returns the new struture or NULL in case of error + */ +static xmlSchemaAttributeGroupPtr +xmlSchemaAddAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt, + xmlSchemaPtr schema ATTRIBUTE_UNUSED, + const xmlChar *name, + const xmlChar *nsName, + xmlNodePtr node) +{ + xmlSchemaAttributeGroupPtr ret = NULL; + + if ((pctxt == NULL) || (name == NULL)) + return (NULL); + + ret = (xmlSchemaAttributeGroupPtr) + xmlMalloc(sizeof(xmlSchemaAttributeGroup)); + if (ret == NULL) { + xmlSchemaPErrMemory(pctxt, "allocating attribute group", NULL); + return (NULL); + } + memset(ret, 0, sizeof(xmlSchemaAttributeGroup)); + ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP; + ret->name = name; + ret->targetNamespace = nsName; + ret->node = node; + + /* TODO: Remove the flag. */ + ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL; + if (pctxt->isRedefine) { + pctxt->redef = xmlSchemaAddRedef(pctxt, pctxt->redefined, + ret, name, nsName); + if (pctxt->redef == NULL) { + xmlFree(ret); + return(NULL); + } + pctxt->redefCounter = 0; + } + WXS_ADD_GLOBAL(pctxt, ret); + WXS_ADD_PENDING(pctxt, ret); + return (ret); +} + +/** + * xmlSchemaAddElement: + * @ctxt: a schema parser context + * @schema: the schema being built + * @name: the type name + * @namespace: the type namespace + * + * Add an XML schema Element declaration + * *WARNING* this interface is highly subject to change + * + * Returns the new struture or NULL in case of error + */ +static xmlSchemaElementPtr +xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, + const xmlChar * name, const xmlChar * nsName, + xmlNodePtr node, int topLevel) +{ + xmlSchemaElementPtr ret = NULL; + + if ((ctxt == NULL) || (name == NULL)) + return (NULL); + + ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement)); + if (ret == NULL) { + xmlSchemaPErrMemory(ctxt, "allocating element", NULL); + return (NULL); + } + memset(ret, 0, sizeof(xmlSchemaElement)); + ret->type = XML_SCHEMA_TYPE_ELEMENT; + ret->name = name; + ret->targetNamespace = nsName; + ret->node = node; + + if (topLevel) + WXS_ADD_GLOBAL(ctxt, ret); + else + WXS_ADD_LOCAL(ctxt, ret); + WXS_ADD_PENDING(ctxt, ret); + return (ret); +} + +/** + * xmlSchemaAddType: + * @ctxt: a schema parser context + * @schema: the schema being built + * @name: the item name + * @namespace: the namespace + * + * Add an XML schema item + * *WARNING* this interface is highly subject to change + * + * Returns the new struture or NULL in case of error + */ +static xmlSchemaTypePtr +xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, + xmlSchemaTypeType type, + const xmlChar * name, const xmlChar * nsName, + xmlNodePtr node, int topLevel) +{ + xmlSchemaTypePtr ret = NULL; + + if ((ctxt == NULL) || (schema == NULL)) + return (NULL); + + ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType)); + if (ret == NULL) { + xmlSchemaPErrMemory(ctxt, "allocating type", NULL); + return (NULL); + } + memset(ret, 0, sizeof(xmlSchemaType)); + ret->type = type; + ret->name = name; + ret->targetNamespace = nsName; + ret->node = node; + if (topLevel) { + if (ctxt->isRedefine) { + ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined, + ret, name, nsName); + if (ctxt->redef == NULL) { + xmlFree(ret); + return(NULL); + } + ctxt->redefCounter = 0; + } + WXS_ADD_GLOBAL(ctxt, ret); + } else + WXS_ADD_LOCAL(ctxt, ret); + WXS_ADD_PENDING(ctxt, ret); + return (ret); +} + +static xmlSchemaQNameRefPtr +xmlSchemaNewQNameRef(xmlSchemaParserCtxtPtr pctxt, + xmlSchemaTypeType refType, + const xmlChar *refName, + const xmlChar *refNs) +{ + xmlSchemaQNameRefPtr ret; + + ret = (xmlSchemaQNameRefPtr) + xmlMalloc(sizeof(xmlSchemaQNameRef)); + if (ret == NULL) { + xmlSchemaPErrMemory(pctxt, + "allocating QName reference item", NULL); + return (NULL); + } + ret->node = NULL; + ret->type = XML_SCHEMA_EXTRA_QNAMEREF; + ret->name = refName; + ret->targetNamespace = refNs; + ret->item = NULL; + ret->itemType = refType; + /* + * Store the reference item in the schema. + */ + WXS_ADD_LOCAL(pctxt, ret); + return (ret); +} + +static xmlSchemaAttributeUseProhibPtr +xmlSchemaAddAttributeUseProhib(xmlSchemaParserCtxtPtr pctxt) +{ + xmlSchemaAttributeUseProhibPtr ret; + + ret = (xmlSchemaAttributeUseProhibPtr) + xmlMalloc(sizeof(xmlSchemaAttributeUseProhib)); + if (ret == NULL) { + xmlSchemaPErrMemory(pctxt, + "allocating attribute use prohibition", NULL); + return (NULL); + } + memset(ret, 0, sizeof(xmlSchemaAttributeUseProhib)); + ret->type = XML_SCHEMA_EXTRA_ATTR_USE_PROHIB; + WXS_ADD_LOCAL(pctxt, ret); + return (ret); +} + + +/** + * xmlSchemaAddModelGroup: + * @ctxt: a schema parser context + * @schema: the schema being built + * @type: the "compositor" type of the model group + * @node: the node in the schema doc + * + * Adds a schema model group + * *WARNING* this interface is highly subject to change + * + * Returns the new struture or NULL in case of error + */ +static xmlSchemaModelGroupPtr +xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt, + xmlSchemaPtr schema, + xmlSchemaTypeType type, + xmlNodePtr node) +{ + xmlSchemaModelGroupPtr ret = NULL; + + if ((ctxt == NULL) || (schema == NULL)) + return (NULL); + + ret = (xmlSchemaModelGroupPtr) + xmlMalloc(sizeof(xmlSchemaModelGroup)); + if (ret == NULL) { + xmlSchemaPErrMemory(ctxt, "allocating model group component", + NULL); + return (NULL); + } + memset(ret, 0, sizeof(xmlSchemaModelGroup)); + ret->type = type; + ret->node = node; + WXS_ADD_LOCAL(ctxt, ret); + if ((type == XML_SCHEMA_TYPE_SEQUENCE) || + (type == XML_SCHEMA_TYPE_CHOICE)) + WXS_ADD_PENDING(ctxt, ret); + return (ret); +} + + +/** + * xmlSchemaAddParticle: + * @ctxt: a schema parser context + * @schema: the schema being built + * @node: the corresponding node in the schema doc + * @min: the minOccurs + * @max: the maxOccurs + * + * Adds an XML schema particle component. + * *WARNING* this interface is highly subject to change + * + * Returns the new struture or NULL in case of error + */ +static xmlSchemaParticlePtr +xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt, + xmlNodePtr node, int min, int max) +{ + xmlSchemaParticlePtr ret = NULL; + if (ctxt == NULL) + return (NULL); + +#ifdef DEBUG + fprintf(stderr, "Adding particle component\n"); +#endif + ret = (xmlSchemaParticlePtr) + xmlMalloc(sizeof(xmlSchemaParticle)); + if (ret == NULL) { + xmlSchemaPErrMemory(ctxt, "allocating particle component", + NULL); + return (NULL); + } + ret->type = XML_SCHEMA_TYPE_PARTICLE; + ret->annot = NULL; + ret->node = node; + ret->minOccurs = min; + ret->maxOccurs = max; + ret->next = NULL; + ret->children = NULL; + + WXS_ADD_LOCAL(ctxt, ret); + /* + * Note that addition to pending components will be done locally + * to the specific parsing function, since the most particles + * need not to be fixed up (i.e. the reference to be resolved). + * REMOVED: WXS_ADD_PENDING(ctxt, ret); + */ + return (ret); +} + +/** + * xmlSchemaAddModelGroupDefinition: + * @ctxt: a schema validation context + * @schema: the schema being built + * @name: the group name + * + * Add an XML schema Group definition + * + * Returns the new struture or NULL in case of error + */ +static xmlSchemaModelGroupDefPtr +xmlSchemaAddModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt, + xmlSchemaPtr schema, + const xmlChar *name, + const xmlChar *nsName, + xmlNodePtr node) +{ + xmlSchemaModelGroupDefPtr ret = NULL; + + if ((ctxt == NULL) || (schema == NULL) || (name == NULL)) + return (NULL); + + ret = (xmlSchemaModelGroupDefPtr) + xmlMalloc(sizeof(xmlSchemaModelGroupDef)); + if (ret == NULL) { + xmlSchemaPErrMemory(ctxt, "adding group", NULL); + return (NULL); + } + memset(ret, 0, sizeof(xmlSchemaModelGroupDef)); + ret->name = name; + ret->type = XML_SCHEMA_TYPE_GROUP; + ret->node = node; + ret->targetNamespace = nsName; + + if (ctxt->isRedefine) { + ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined, + ret, name, nsName); + if (ctxt->redef == NULL) { + xmlFree(ret); + return(NULL); + } + ctxt->redefCounter = 0; + } + WXS_ADD_GLOBAL(ctxt, ret); + WXS_ADD_PENDING(ctxt, ret); + return (ret); +} + +/** + * xmlSchemaNewWildcardNs: + * @ctxt: a schema validation context + * + * Creates a new wildcard namespace constraint. + * + * Returns the new struture or NULL in case of error + */ +static xmlSchemaWildcardNsPtr +xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt) +{ + xmlSchemaWildcardNsPtr ret; + + ret = (xmlSchemaWildcardNsPtr) + xmlMalloc(sizeof(xmlSchemaWildcardNs)); + if (ret == NULL) { + xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL); + return (NULL); + } + ret->value = NULL; + ret->next = NULL; + return (ret); +} + +static xmlSchemaIDCPtr +xmlSchemaAddIDC(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, + const xmlChar *name, const xmlChar *nsName, + int category, xmlNodePtr node) +{ + xmlSchemaIDCPtr ret = NULL; + + if ((ctxt == NULL) || (schema == NULL) || (name == NULL)) + return (NULL); + + ret = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC)); + if (ret == NULL) { + xmlSchemaPErrMemory(ctxt, + "allocating an identity-constraint definition", NULL); + return (NULL); + } + memset(ret, 0, sizeof(xmlSchemaIDC)); + /* The target namespace of the parent element declaration. */ + ret->targetNamespace = nsName; + ret->name = name; + ret->type = category; + ret->node = node; + + WXS_ADD_GLOBAL(ctxt, ret); + /* + * Only keyrefs need to be fixup up. + */ + if (category == XML_SCHEMA_TYPE_IDC_KEYREF) + WXS_ADD_PENDING(ctxt, ret); + return (ret); +} + +/** + * xmlSchemaAddWildcard: + * @ctxt: a schema validation context + * @schema: a schema + * + * Adds a wildcard. + * It corresponds to a xsd:anyAttribute and xsd:any. + * + * Returns the new struture or NULL in case of error + */ +static xmlSchemaWildcardPtr +xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, + xmlSchemaTypeType type, xmlNodePtr node) +{ + xmlSchemaWildcardPtr ret = NULL; + + if ((ctxt == NULL) || (schema == NULL)) + return (NULL); + + ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard)); + if (ret == NULL) { + xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL); + return (NULL); + } + memset(ret, 0, sizeof(xmlSchemaWildcard)); + ret->type = type; + ret->node = node; + WXS_ADD_LOCAL(ctxt, ret); + return (ret); +} + +static void +xmlSchemaSubstGroupFree(xmlSchemaSubstGroupPtr group) +{ + if (group == NULL) + return; + if (group->members != NULL) + xmlSchemaItemListFree(group->members); + xmlFree(group); +} + +static xmlSchemaSubstGroupPtr +xmlSchemaSubstGroupAdd(xmlSchemaParserCtxtPtr pctxt, + xmlSchemaElementPtr head) +{ + xmlSchemaSubstGroupPtr ret; + + /* Init subst group hash. */ + if (WXS_SUBST_GROUPS(pctxt) == NULL) { + WXS_SUBST_GROUPS(pctxt) = xmlHashCreateDict(10, pctxt->dict); + if (WXS_SUBST_GROUPS(pctxt) == NULL) + return(NULL); + } + /* Create a new substitution group. */ + ret = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup)); + if (ret == NULL) { + xmlSchemaPErrMemory(NULL, + "allocating a substitution group container", NULL); + return(NULL); + } + memset(ret, 0, sizeof(xmlSchemaSubstGroup)); + ret->head = head; + /* Create list of members. */ + ret->members = xmlSchemaItemListCreate(); + if (ret->members == NULL) { + xmlSchemaSubstGroupFree(ret); + return(NULL); + } + /* Add subst group to hash. */ + if (xmlHashAddEntry2(WXS_SUBST_GROUPS(pctxt), + head->name, head->targetNamespace, ret) != 0) { + PERROR_INT("xmlSchemaSubstGroupAdd", + "failed to add a new substitution container"); + xmlSchemaSubstGroupFree(ret); + return(NULL); + } + return(ret); +} + +static xmlSchemaSubstGroupPtr +xmlSchemaSubstGroupGet(xmlSchemaParserCtxtPtr pctxt, + xmlSchemaElementPtr head) +{ + if (WXS_SUBST_GROUPS(pctxt) == NULL) + return(NULL); + return(xmlHashLookup2(WXS_SUBST_GROUPS(pctxt), + head->name, head->targetNamespace)); + +} + +/** + * xmlSchemaAddElementSubstitutionMember: + * @pctxt: a schema parser context + * @head: the head of the substitution group + * @member: the new member of the substitution group + * + * Allocate a new annotation structure. + * + * Returns the newly allocated structure or NULL in case or error + */ +static int +xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt, + xmlSchemaElementPtr head, + xmlSchemaElementPtr member) +{ + xmlSchemaSubstGroupPtr substGroup = NULL; + + if ((pctxt == NULL) || (head == NULL) || (member == NULL)) + return (-1); + + substGroup = xmlSchemaSubstGroupGet(pctxt, head); + if (substGroup == NULL) + substGroup = xmlSchemaSubstGroupAdd(pctxt, head); + if (substGroup == NULL) + return(-1); + if (xmlSchemaItemListAdd(substGroup->members, member) == -1) + return(-1); + return(0); +} + +/************************************************************************ + * * + * Utilities for parsing * + * * + ************************************************************************/ + +/** + * xmlSchemaPValAttrNodeQNameValue: + * @ctxt: a schema parser context + * @schema: the schema context + * @ownerDes: the designation of the parent element + * @ownerItem: the parent as a schema object + * @value: the QName value + * @local: the resulting local part if found, the attribute value otherwise + * @uri: the resulting namespace URI if found + * + * Extracts the local name and the URI of a QName value and validates it. + * This one is intended to be used on attribute values that + * should resolve to schema components. + * + * Returns 0, in case the QName is valid, a positive error code + * if not valid and -1 if an internal error occurs. + */ +static int +xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt, + xmlSchemaPtr schema, + xmlSchemaBasicItemPtr ownerItem, + xmlAttrPtr attr, + const xmlChar *value, + const xmlChar **uri, + const xmlChar **local) +{ + const xmlChar *pref; + xmlNsPtr ns; + int len, ret; + + *uri = NULL; + *local = NULL; + ret = xmlValidateQName(value, 1); + if (ret > 0) { + xmlSchemaPSimpleTypeErr(ctxt, + XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, + ownerItem, (xmlNodePtr) attr, + xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), + NULL, value, NULL, NULL, NULL); + *local = value; + return (ctxt->err); + } else if (ret < 0) + return (-1); + + if (!strchr((char *) value, ':')) { + ns = xmlSearchNs(attr->doc, attr->parent, NULL); + if (ns) + *uri = xmlDictLookup(ctxt->dict, ns->href, -1); + else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) { + /* TODO: move XML_SCHEMAS_INCLUDING_CONVERT_NS to the + * parser context. */ + /* + * This one takes care of included schemas with no + * target namespace. + */ + *uri = ctxt->targetNamespace; + } + *local = xmlDictLookup(ctxt->dict, value, -1); + return (0); + } + /* + * At this point xmlSplitQName3 has to return a local name. + */ + *local = xmlSplitQName3(value, &len); + *local = xmlDictLookup(ctxt->dict, *local, -1); + pref = xmlDictLookup(ctxt->dict, value, len); + ns = xmlSearchNs(attr->doc, attr->parent, pref); + if (ns == NULL) { + xmlSchemaPSimpleTypeErr(ctxt, + XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, + ownerItem, (xmlNodePtr) attr, + xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, value, + "The value '%s' of simple type 'xs:QName' has no " + "corresponding namespace declaration in scope", value, NULL); + return (ctxt->err); + } else { + *uri = xmlDictLookup(ctxt->dict, ns->href, -1); + } + return (0); +} + +/** + * xmlSchemaPValAttrNodeQName: + * @ctxt: a schema parser context + * @schema: the schema context + * @ownerDes: the designation of the owner element + * @ownerItem: the owner as a schema object + * @attr: the attribute node + * @local: the resulting local part if found, the attribute value otherwise + * @uri: the resulting namespace URI if found + * + * Extracts and validates the QName of an attribute value. + * This one is intended to be used on attribute values that + * should resolve to schema components. + * + * Returns 0, in case the QName is valid, a positive error code + * if not valid and -1 if an internal error occurs. + */ +static int +xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt, + xmlSchemaPtr schema, + xmlSchemaBasicItemPtr ownerItem, + xmlAttrPtr attr, + const xmlChar **uri, + const xmlChar **local) +{ + const xmlChar *value; + + value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr); + return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema, + ownerItem, attr, value, uri, local)); +} + +/** + * xmlSchemaPValAttrQName: + * @ctxt: a schema parser context + * @schema: the schema context + * @ownerDes: the designation of the parent element + * @ownerItem: the owner as a schema object + * @ownerElem: the parent node of the attribute + * @name: the name of the attribute + * @local: the resulting local part if found, the attribute value otherwise + * @uri: the resulting namespace URI if found + * + * Extracts and validates the QName of an attribute value. + * + * Returns 0, in case the QName is valid, a positive error code + * if not valid and -1 if an internal error occurs. + */ +static int +xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt, + xmlSchemaPtr schema, + xmlSchemaBasicItemPtr ownerItem, + xmlNodePtr ownerElem, + const char *name, + const xmlChar **uri, + const xmlChar **local) +{ + xmlAttrPtr attr; + + attr = xmlSchemaGetPropNode(ownerElem, name); + if (attr == NULL) { + *local = NULL; + *uri = NULL; + return (0); + } + return (xmlSchemaPValAttrNodeQName(ctxt, schema, + ownerItem, attr, uri, local)); +} + +/** + * xmlSchemaPValAttrID: + * @ctxt: a schema parser context + * @schema: the schema context + * @ownerDes: the designation of the parent element + * @ownerItem: the owner as a schema object + * @ownerElem: the parent node of the attribute + * @name: the name of the attribute + * + * Extracts and validates the ID of an attribute value. + * + * Returns 0, in case the ID is valid, a positive error code + * if not valid and -1 if an internal error occurs. + */ +static int +xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt, xmlAttrPtr attr) +{ + int ret; + const xmlChar *value; + + if (attr == NULL) + return(0); + value = xmlSchemaGetNodeContentNoDict((xmlNodePtr) attr); + ret = xmlValidateNCName(value, 1); + if (ret == 0) { + /* + * NOTE: the IDness might have already be declared in the DTD + */ + if (attr->atype != XML_ATTRIBUTE_ID) { + xmlIDPtr res; + xmlChar *strip; + + /* + * TODO: Use xmlSchemaStrip here; it's not exported at this + * moment. + */ + strip = xmlSchemaCollapseString(value); + if (strip != NULL) { + xmlFree((xmlChar *) value); + value = strip; + } + res = xmlAddID(NULL, attr->doc, value, attr); + if (res == NULL) { + ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE; + xmlSchemaPSimpleTypeErr(ctxt, + XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, + NULL, (xmlNodePtr) attr, + xmlSchemaGetBuiltInType(XML_SCHEMAS_ID), + NULL, NULL, "Duplicate value '%s' of simple " + "type 'xs:ID'", value, NULL); + } else + attr->atype = XML_ATTRIBUTE_ID; + } + } else if (ret > 0) { + ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE; + xmlSchemaPSimpleTypeErr(ctxt, + XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, + NULL, (xmlNodePtr) attr, + xmlSchemaGetBuiltInType(XML_SCHEMAS_ID), + NULL, NULL, "The value '%s' of simple type 'xs:ID' is " + "not a valid 'xs:NCName'", + value, NULL); + } + if (value != NULL) + xmlFree((xmlChar *)value); + + return (ret); +} + +static int +xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt, + xmlNodePtr ownerElem, + const xmlChar *name) +{ + xmlAttrPtr attr; + + attr = xmlSchemaGetPropNode(ownerElem, (const char *) name); + if (attr == NULL) + return(0); + return(xmlSchemaPValAttrNodeID(ctxt, attr)); + +} + +/** + * xmlGetMaxOccurs: + * @ctxt: a schema validation context + * @node: a subtree containing XML Schema informations + * + * Get the maxOccurs property + * + * Returns the default if not found, or the value + */ +static int +xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, + int min, int max, int def, const char *expected) +{ + const xmlChar *val, *cur; + int ret = 0; + xmlAttrPtr attr; + + attr = xmlSchemaGetPropNode(node, "maxOccurs"); + if (attr == NULL) + return (def); + val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr); + + if (xmlStrEqual(val, (const xmlChar *) "unbounded")) { + if (max != UNBOUNDED) { + xmlSchemaPSimpleTypeErr(ctxt, + XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, + /* XML_SCHEMAP_INVALID_MINOCCURS, */ + NULL, (xmlNodePtr) attr, NULL, expected, + val, NULL, NULL, NULL); + return (def); + } else + return (UNBOUNDED); /* encoding it with -1 might be another option */ + } + + cur = val; + while (IS_BLANK_CH(*cur)) + cur++; + if (*cur == 0) { + xmlSchemaPSimpleTypeErr(ctxt, + XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, + /* XML_SCHEMAP_INVALID_MINOCCURS, */ + NULL, (xmlNodePtr) attr, NULL, expected, + val, NULL, NULL, NULL); + return (def); + } + while ((*cur >= '0') && (*cur <= '9')) { + ret = ret * 10 + (*cur - '0'); + cur++; + } + while (IS_BLANK_CH(*cur)) + cur++; + /* + * TODO: Restrict the maximal value to Integer. + */ + if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) { + xmlSchemaPSimpleTypeErr(ctxt, + XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, + /* XML_SCHEMAP_INVALID_MINOCCURS, */ + NULL, (xmlNodePtr) attr, NULL, expected, + val, NULL, NULL, NULL); + return (def); + } + return (ret); +} + +/** + * xmlGetMinOccurs: + * @ctxt: a schema validation context + * @node: a subtree containing XML Schema informations + * + * Get the minOccurs property + * + * Returns the default if not found, or the value + */ +static int +xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, + int min, int max, int def, const char *expected) +{ + const xmlChar *val, *cur; + int ret = 0; + xmlAttrPtr attr; + + attr = xmlSchemaGetPropNode(node, "minOccurs"); + if (attr == NULL) + return (def); + val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr); + cur = val; + while (IS_BLANK_CH(*cur)) + cur++; + if (*cur == 0) { + xmlSchemaPSimpleTypeErr(ctxt, + XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, + /* XML_SCHEMAP_INVALID_MINOCCURS, */ + NULL, (xmlNodePtr) attr, NULL, expected, + val, NULL, NULL, NULL); + return (def); + } + while ((*cur >= '0') && (*cur <= '9')) { + ret = ret * 10 + (*cur - '0'); + cur++; + } + while (IS_BLANK_CH(*cur)) + cur++; + /* + * TODO: Restrict the maximal value to Integer. + */ + if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) { + xmlSchemaPSimpleTypeErr(ctxt, + XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, + /* XML_SCHEMAP_INVALID_MINOCCURS, */ + NULL, (xmlNodePtr) attr, NULL, expected, + val, NULL, NULL, NULL); + return (def); + } + return (ret); +} + +/** + * xmlSchemaPGetBoolNodeValue: + * @ctxt: a schema validation context + * @ownerDes: owner designation + * @ownerItem: the owner as a schema item + * @node: the node holding the value + * + * Converts a boolean string value into 1 or 0. + * + * Returns 0 or 1. + */ +static int +xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt, + xmlSchemaBasicItemPtr ownerItem, + xmlNodePtr node) +{ + xmlChar *value = NULL; + int res = 0; + + value = xmlNodeGetContent(node); + /* + * 3.2.2.1 Lexical representation + * An instance of a datatype that is defined as ·boolean· + * can have the following legal literals {true, false, 1, 0}. + */ + if (xmlStrEqual(BAD_CAST value, BAD_CAST "true")) + res = 1; + else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false")) + res = 0; + else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1")) + res = 1; + else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0")) + res = 0; + else { + xmlSchemaPSimpleTypeErr(ctxt, + XML_SCHEMAP_INVALID_BOOLEAN, + ownerItem, node, + xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN), + NULL, BAD_CAST value, + NULL, NULL, NULL); + } + if (value != NULL) + xmlFree(value); + return (res); +} + +/** + * xmlGetBooleanProp: + * @ctxt: a schema validation context + * @node: a subtree containing XML Schema informations + * @name: the attribute name + * @def: the default value + * + * Evaluate if a boolean property is set + * + * Returns the default if not found, 0 if found to be false, + * 1 if found to be true + */ +static int +xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt, + xmlNodePtr node, + const char *name, int def) +{ + const xmlChar *val; + + val = xmlSchemaGetProp(ctxt, node, name); + if (val == NULL) + return (def); + /* + * 3.2.2.1 Lexical representation + * An instance of a datatype that is defined as ·boolean· + * can have the following legal literals {true, false, 1, 0}. + */ + if (xmlStrEqual(val, BAD_CAST "true")) + def = 1; + else if (xmlStrEqual(val, BAD_CAST "false")) + def = 0; + else if (xmlStrEqual(val, BAD_CAST "1")) + def = 1; + else if (xmlStrEqual(val, BAD_CAST "0")) + def = 0; + else { + xmlSchemaPSimpleTypeErr(ctxt, + XML_SCHEMAP_INVALID_BOOLEAN, + NULL, + (xmlNodePtr) xmlSchemaGetPropNode(node, name), + xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN), + NULL, val, NULL, NULL, NULL); + } + return (def); +} + +/************************************************************************ + * * + * Shema extraction from an Infoset * + * * + ************************************************************************/ +static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr + ctxt, xmlSchemaPtr schema, + xmlNodePtr node, + int topLevel); +static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr + ctxt, + xmlSchemaPtr schema, + xmlNodePtr node, + int topLevel); +static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr + ctxt, + xmlSchemaPtr schema, + xmlNodePtr node, + xmlSchemaTypeType parentType); +static xmlSchemaBasicItemPtr +xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt, + xmlSchemaPtr schema, + xmlNodePtr node, + xmlSchemaItemListPtr uses, + int parentType); +static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, + xmlSchemaPtr schema, + xmlNodePtr node); +static xmlSchemaWildcardPtr +xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt, + xmlSchemaPtr schema, xmlNodePtr node); + +/** + * xmlSchemaPValAttrNodeValue: + * + * @ctxt: a schema parser context + * @ownerDes: the designation of the parent element + * @ownerItem: the schema object owner if existent + * @attr: the schema attribute node being validated + * @value: the value + * @type: the built-in type to be validated against + * + * Validates a value against the given built-in type. + * This one is intended to be used internally for validation + * of schema attribute values during parsing of the schema. + * + * Returns 0 if the value is valid, a positive error code + * number otherwise and -1 in case of an internal or API error. + */ +static int +xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt, + xmlSchemaBasicItemPtr ownerItem, + xmlAttrPtr attr, + const xmlChar *value, + xmlSchemaTypePtr type) +{ + + int ret = 0; + + /* + * NOTE: Should we move this to xmlschematypes.c? Hmm, but this + * one is really meant to be used internally, so better not. + */ + if ((pctxt == NULL) || (type == NULL) || (attr == NULL)) + return (-1); + if (type->type != XML_SCHEMA_TYPE_BASIC) { + PERROR_INT("xmlSchemaPValAttrNodeValue", + "the given type is not a built-in type"); + return (-1); + } + switch (type->builtInType) { + case XML_SCHEMAS_NCNAME: + case XML_SCHEMAS_QNAME: + case XML_SCHEMAS_ANYURI: + case XML_SCHEMAS_TOKEN: + case XML_SCHEMAS_LANGUAGE: + ret = xmlSchemaValPredefTypeNode(type, value, NULL, + (xmlNodePtr) attr); + break; + default: { + PERROR_INT("xmlSchemaPValAttrNodeValue", + "validation using the given type is not supported while " + "parsing a schema"); + return (-1); + } + } + /* + * TODO: Should we use the S4S error codes instead? + */ + if (ret < 0) { + PERROR_INT("xmlSchemaPValAttrNodeValue", + "failed to validate a schema attribute value"); + return (-1); + } else if (ret > 0) { + if (WXS_IS_LIST(type)) + ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2; + else + ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1; + xmlSchemaPSimpleTypeErr(pctxt, + ret, ownerItem, (xmlNodePtr) attr, + type, NULL, value, NULL, NULL, NULL); + } + return (ret); +} + +/** + * xmlSchemaPValAttrNode: + * + * @ctxt: a schema parser context + * @ownerDes: the designation of the parent element + * @ownerItem: the schema object owner if existent + * @attr: the schema attribute node being validated + * @type: the built-in type to be validated against + * @value: the resulting value if any + * + * Extracts and validates a value against the given built-in type. + * This one is intended to be used internally for validation + * of schema attribute values during parsing of the schema. + * + * Returns 0 if the value is valid, a positive error code + * number otherwise and -1 in case of an internal or API error. + */ +static int +xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt, + xmlSchemaBasicItemPtr ownerItem, + xmlAttrPtr attr, + xmlSchemaTypePtr type, + const xmlChar **value) +{ + const xmlChar *val; + + if ((ctxt == NULL) || (type == NULL) || (attr == NULL)) + return (-1); + + val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr); + if (value != NULL) + *value = val; + + return (xmlSchemaPValAttrNodeValue(ctxt, ownerItem, attr, + val, type)); +} + +/** + * xmlSchemaPValAttr: + * + * @ctxt: a schema parser context + * @node: the element node of the attribute + * @ownerDes: the designation of the parent element + * @ownerItem: the schema object owner if existent + * @ownerElem: the owner element node + * @name: the name of the schema attribute node + * @type: the built-in type to be validated against + * @value: the resulting value if any + * + * Extracts and validates a value against the given built-in type. + * This one is intended to be used internally for validation + * of schema attribute values during parsing of the schema. + * + * Returns 0 if the value is valid, a positive error code + * number otherwise and -1 in case of an internal or API error. + */ +static int +xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt, + xmlSchemaBasicItemPtr ownerItem, + xmlNodePtr ownerElem, + const char *name, + xmlSchemaTypePtr type, + const xmlChar **value) +{ + xmlAttrPtr attr; + + if ((ctxt == NULL) || (type == NULL)) { + if (value != NULL) + *value = NULL; + return (-1); + } + if (type->type != XML_SCHEMA_TYPE_BASIC) { + if (value != NULL) + *value = NULL; + xmlSchemaPErr(ctxt, ownerElem, + XML_SCHEMAP_INTERNAL, + "Internal error: xmlSchemaPValAttr, the given " + "type '%s' is not a built-in type.\n", + type->name, NULL); + return (-1); + } + attr = xmlSchemaGetPropNode(ownerElem, name); + if (attr == NULL) { + if (value != NULL) + *value = NULL; + return (0); + } + return (xmlSchemaPValAttrNode(ctxt, ownerItem, attr, + type, value)); +} + +static int +xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt, + xmlSchemaPtr schema ATTRIBUTE_UNUSED, + xmlNodePtr node, + xmlAttrPtr attr, + const xmlChar *namespaceName) +{ + /* TODO: Pointer comparison instead? */ + if (xmlStrEqual(pctxt->targetNamespace, namespaceName)) + return (0); + if (xmlStrEqual(xmlSchemaNs, namespaceName)) + return (0); + /* + * Check if the referenced namespace was ed. + */ + if (WXS_BUCKET(pctxt)->relations != NULL) { + xmlSchemaSchemaRelationPtr rel; + + rel = WXS_BUCKET(pctxt)->relations; + do { + if (WXS_IS_BUCKET_IMPMAIN(rel->type) && + xmlStrEqual(namespaceName, rel->importNamespace)) + return (0); + rel = rel->next; + } while (rel != NULL); + } + /* + * No matching ed namespace found. + */ + { + xmlNodePtr n = (attr != NULL) ? (xmlNodePtr) attr : node; + + if (namespaceName == NULL) + xmlSchemaCustomErr(ACTXT_CAST pctxt, + XML_SCHEMAP_SRC_RESOLVE, n, NULL, + "References from this schema to components in no " + "namespace are not allowed, since not indicated by an " + "import statement", NULL, NULL); + else + xmlSchemaCustomErr(ACTXT_CAST pctxt, + XML_SCHEMAP_SRC_RESOLVE, n, NULL, + "References from this schema to components in the " + "namespace '%s' are not allowed, since not indicated by an " + "import statement", namespaceName, NULL); + } + return (XML_SCHEMAP_SRC_RESOLVE); +} + +/** + * xmlSchemaParseLocalAttributes: + * @ctxt: a schema validation context + * @schema: the schema being built + * @node: a subtree containing XML Schema informations + * @type: the hosting type where the attributes will be anchored + * + * Parses attribute uses and attribute declarations and + * attribute group references. + */ +static int +xmlSchemaParseLocalAttributes(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, + xmlNodePtr *child, xmlSchemaItemListPtr *list, + int parentType, int *hasRefs) +{ + void *item; + + while ((IS_SCHEMA((*child), "attribute")) || + (IS_SCHEMA((*child), "attributeGroup"))) { + if (IS_SCHEMA((*child), "attribute")) { + item = xmlSchemaParseLocalAttribute(ctxt, schema, *child, + *list, parentType); + } else { + item = xmlSchemaParseAttributeGroupRef(ctxt, schema, *child); + if ((item != NULL) && (hasRefs != NULL)) + *hasRefs = 1; + } + if (item != NULL) { + if (*list == NULL) { + /* TODO: Customize grow factor. */ + *list = xmlSchemaItemListCreate(); + if (*list == NULL) + return(-1); + } + if (xmlSchemaItemListAddSize(*list, 2, item) == -1) + return(-1); + } + *child = (*child)->next; + } + return (0); +} + +/** + * xmlSchemaParseAnnotation: + * @ctxt: a schema validation context + * @schema: the schema being built + * @node: a subtree containing XML Schema informations + * + * parse a XML schema Attrribute declaration + * *WARNING* this interface is highly subject to change + * + * Returns -1 in case of error, 0 if the declaration is improper and + * 1 in case of success. + */ +static xmlSchemaAnnotPtr +xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int needed) +{ + xmlSchemaAnnotPtr ret; + xmlNodePtr child = NULL; + xmlAttrPtr attr; + int barked = 0; + + /* + * INFO: S4S completed. + */ + /* + * id = ID + * {any attributes with non-schema namespace . . .}> + * Content: (appinfo | documentation)* + */ + if ((ctxt == NULL) || (node == NULL)) + return (NULL); + if (needed) + ret = xmlSchemaNewAnnot(ctxt, node); + else + ret = NULL; + attr = node->properties; + while (attr != NULL) { + if (((attr->ns == NULL) && + (!xmlStrEqual(attr->name, BAD_CAST "id"))) || + ((attr->ns != NULL) && + xmlStrEqual(attr->ns->href, xmlSchemaNs))) { + + xmlSchemaPIllegalAttrErr(ctxt, + XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); + } + attr = attr->next; + } + xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); + /* + * And now for the children... + */ + child = node->children; + while (child != NULL) { + if (IS_SCHEMA(child, "appinfo")) { + /* TODO: make available the content of "appinfo". */ + /* + * source = anyURI + * {any attributes with non-schema namespace . . .}> + * Content: ({any})* + */ + attr = child->properties; + while (attr != NULL) { + if (((attr->ns == NULL) && + (!xmlStrEqual(attr->name, BAD_CAST "source"))) || + ((attr->ns != NULL) && + xmlStrEqual(attr->ns->href, xmlSchemaNs))) { + + xmlSchemaPIllegalAttrErr(ctxt, + XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); + } + attr = attr->next; + } + xmlSchemaPValAttr(ctxt, NULL, child, "source", + xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL); + child = child->next; + } else if (IS_SCHEMA(child, "documentation")) { + /* TODO: make available the content of "documentation". */ + /* + * source = anyURI + * {any attributes with non-schema namespace . . .}> + * Content: ({any})* + */ + attr = child->properties; + while (attr != NULL) { + if (attr->ns == NULL) { + if (!xmlStrEqual(attr->name, BAD_CAST "source")) { + xmlSchemaPIllegalAttrErr(ctxt, + XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); + } + } else { + if (xmlStrEqual(attr->ns->href, xmlSchemaNs) || + (xmlStrEqual(attr->name, BAD_CAST "lang") && + (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) { + + xmlSchemaPIllegalAttrErr(ctxt, + XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); + } + } + attr = attr->next; + } + /* + * Attribute "xml:lang". + */ + attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang"); + if (attr != NULL) + xmlSchemaPValAttrNode(ctxt, NULL, attr, + xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL); + child = child->next; + } else { + if (!barked) + xmlSchemaPContentErr(ctxt, + XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, + NULL, node, child, NULL, "(appinfo | documentation)*"); + barked = 1; + child = child->next; + } + } + + return (ret); +} + +/** + * xmlSchemaParseFacet: + * @ctxt: a schema validation context + * @schema: the schema being built + * @node: a subtree containing XML Schema informations + * + * parse a XML schema Facet declaration + * *WARNING* this interface is highly subject to change + * + * Returns the new type structure or NULL in case of error + */ +static xmlSchemaFacetPtr +xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, + xmlNodePtr node) +{ + xmlSchemaFacetPtr facet; + xmlNodePtr child = NULL; + const xmlChar *value; + + if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) + return (NULL); + + facet = xmlSchemaNewFacet(); + if (facet == NULL) { + xmlSchemaPErrMemory(ctxt, "allocating facet", node); + return (NULL); + } + facet->node = node; + value = xmlSchemaGetProp(ctxt, node, "value"); + if (value == NULL) { + xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE, + "Facet %s has no value\n", node->name, NULL); + xmlSchemaFreeFacet(facet); + return (NULL); + } + if (IS_SCHEMA(node, "minInclusive")) { + facet->type = XML_SCHEMA_FACET_MININCLUSIVE; + } else if (IS_SCHEMA(node, "minExclusive")) { + facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE; + } else if (IS_SCHEMA(node, "maxInclusive")) { + facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE; + } else if (IS_SCHEMA(node, "maxExclusive")) { + facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE; + } else if (IS_SCHEMA(node, "totalDigits")) { + facet->type = XML_SCHEMA_FACET_TOTALDIGITS; + } else if (IS_SCHEMA(node, "fractionDigits")) { + facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS; + } else if (IS_SCHEMA(node, "pattern")) { + facet->type = XML_SCHEMA_FACET_PATTERN; + } else if (IS_SCHEMA(node, "enumeration")) { + facet->type = XML_SCHEMA_FACET_ENUMERATION; + } else if (IS_SCHEMA(node, "whiteSpace")) { + facet->type = XML_SCHEMA_FACET_WHITESPACE; + } else if (IS_SCHEMA(node, "length")) { + facet->type = XML_SCHEMA_FACET_LENGTH; + } else if (IS_SCHEMA(node, "maxLength")) { + facet->type = XML_SCHEMA_FACET_MAXLENGTH; + } else if (IS_SCHEMA(node, "minLength")) { + facet->type = XML_SCHEMA_FACET_MINLENGTH; + } else { + xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE, + "Unknown facet type %s\n", node->name, NULL); + xmlSchemaFreeFacet(facet); + return (NULL); + } + xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); + facet->value = value; + if ((facet->type != XML_SCHEMA_FACET_PATTERN) && + (facet->type != XML_SCHEMA_FACET_ENUMERATION)) { + const xmlChar *fixed; + + fixed = xmlSchemaGetProp(ctxt, node, "fixed"); + if (fixed != NULL) { + if (xmlStrEqual(fixed, BAD_CAST "true")) + facet->fixed = 1; + } + } + child = node->children; + + if (IS_SCHEMA(child, "annotation")) { + facet->annot = xmlSchemaParseAnnotation(ctxt, child, 1); + child = child->next; + } + if (child != NULL) { + xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD, + "Facet %s has unexpected child content\n", + node->name, NULL); + } + return (facet); +} + +/** + * xmlSchemaParseWildcardNs: + * @ctxt: a schema parser context + * @wildc: the wildcard, already created + * @node: a subtree containing XML Schema informations + * + * Parses the attribute "processContents" and "namespace" + * of a xsd:anyAttribute and xsd:any. + * *WARNING* this interface is highly subject to change + * + * Returns 0 if everything goes fine, a positive error code + * if something is not valid and -1 if an internal error occurs. + */ +static int +xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt, + xmlSchemaPtr schema ATTRIBUTE_UNUSED, + xmlSchemaWildcardPtr wildc, + xmlNodePtr node) +{ + const xmlChar *pc, *ns, *dictnsItem; + int ret = 0; + xmlChar *nsItem; + xmlSchemaWildcardNsPtr tmp, lastNs = NULL; + xmlAttrPtr attr; + + pc = xmlSchemaGetProp(ctxt, node, "processContents"); + if ((pc == NULL) + || (xmlStrEqual(pc, (const xmlChar *) "strict"))) { + wildc->processContents = XML_SCHEMAS_ANY_STRICT; + } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) { + wildc->processContents = XML_SCHEMAS_ANY_SKIP; + } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) { + wildc->processContents = XML_SCHEMAS_ANY_LAX; + } else { + xmlSchemaPSimpleTypeErr(ctxt, + XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, + NULL, node, + NULL, "(strict | skip | lax)", pc, + NULL, NULL, NULL); + wildc->processContents = XML_SCHEMAS_ANY_STRICT; + ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE; + } + /* + * Build the namespace constraints. + */ + attr = xmlSchemaGetPropNode(node, "namespace"); + ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr); + if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any"))) + wildc->any = 1; + else if (xmlStrEqual(ns, BAD_CAST "##other")) { + wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt); + if (wildc->negNsSet == NULL) { + return (-1); + } + wildc->negNsSet->value = ctxt->targetNamespace; + } else { + const xmlChar *end, *cur; + + cur = ns; + do { + while (IS_BLANK_CH(*cur)) + cur++; + end = cur; + while ((*end != 0) && (!(IS_BLANK_CH(*end)))) + end++; + if (end == cur) + break; + nsItem = xmlStrndup(cur, end - cur); + if ((xmlStrEqual(nsItem, BAD_CAST "##other")) || + (xmlStrEqual(nsItem, BAD_CAST "##any"))) { + xmlSchemaPSimpleTypeErr(ctxt, + XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER, + NULL, (xmlNodePtr) attr, + NULL, + "((##any | ##other) | List of (xs:anyURI | " + "(##targetNamespace | ##local)))", + nsItem, NULL, NULL, NULL); + ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER; + } else { + if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) { + dictnsItem = ctxt->targetNamespace; + } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) { + dictnsItem = NULL; + } else { + /* + * Validate the item (anyURI). + */ + xmlSchemaPValAttrNodeValue(ctxt, NULL, attr, + nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI)); + dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1); + } + /* + * Avoid dublicate namespaces. + */ + tmp = wildc->nsSet; + while (tmp != NULL) { + if (dictnsItem == tmp->value) + break; + tmp = tmp->next; + } + if (tmp == NULL) { + tmp = xmlSchemaNewWildcardNsConstraint(ctxt); + if (tmp == NULL) { + xmlFree(nsItem); + return (-1); + } + tmp->value = dictnsItem; + tmp->next = NULL; + if (wildc->nsSet == NULL) + wildc->nsSet = tmp; + else + lastNs->next = tmp; + lastNs = tmp; + } + + } + xmlFree(nsItem); + cur = end; + } while (*cur != 0); + } + return (ret); +} + +static int +xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt, + xmlSchemaParticlePtr item ATTRIBUTE_UNUSED, + xmlNodePtr node, + int minOccurs, + int maxOccurs) { + + if ((maxOccurs == 0) && ( minOccurs == 0)) + return (0); + if (maxOccurs != UNBOUNDED) { + /* + * TODO: Maybe we should better not create the particle, + * if min/max is invalid, since it could confuse the build of the + * content model. + */ + /* + * 3.9.6 Schema Component Constraint: Particle Correct + * + */ + if (maxOccurs < 1) { + /* + * 2.2 {max occurs} must be greater than or equal to 1. + */ + xmlSchemaPCustomAttrErr(ctxt, + XML_SCHEMAP_P_PROPS_CORRECT_2_2, + NULL, NULL, + xmlSchemaGetPropNode(node, "maxOccurs"), + "The value must be greater than or equal to 1"); + return (XML_SCHEMAP_P_PROPS_CORRECT_2_2); + } else if (minOccurs > maxOccurs) { + /* + * 2.1 {min occurs} must not be greater than {max occurs}. + */ + xmlSchemaPCustomAttrErr(ctxt, + XML_SCHEMAP_P_PROPS_CORRECT_2_1, + NULL, NULL, + xmlSchemaGetPropNode(node, "minOccurs"), + "The value must not be greater than the value of 'maxOccurs'"); + return (XML_SCHEMAP_P_PROPS_CORRECT_2_1); + } + } + return (0); +} + +/** + * xmlSchemaParseAny: + * @ctxt: a schema validation context + * @schema: the schema being built + * @node: a subtree containing XML Schema informations + * + * Parsea a XML schema element. A particle and wildcard + * will be created (except if minOccurs==maxOccurs==0, in this case + * nothing will be created). + * *WARNING* this interface is highly subject to change + * + * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0 + */ +static xmlSchemaParticlePtr +xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, + xmlNodePtr node) +{ + xmlSchemaParticlePtr particle; + xmlNodePtr child = NULL; + xmlSchemaWildcardPtr wild; + int min, max; + xmlAttrPtr attr; + xmlSchemaAnnotPtr annot = NULL; + + if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) + return (NULL); + /* + * Check for illegal attributes. + */ + attr = node->properties; + while (attr != NULL) { + if (attr->ns == NULL) { + if ((!xmlStrEqual(attr->name, BAD_CAST "id")) && + (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) && + (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) && + (!xmlStrEqual(attr->name, BAD_CAST "namespace")) && + (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) { + xmlSchemaPIllegalAttrErr(ctxt, + XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); + } + } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { + xmlSchemaPIllegalAttrErr(ctxt, + XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); + } + attr = attr->next; + } + xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); + /* + * minOccurs/maxOccurs. + */ + max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, + "(xs:nonNegativeInteger | unbounded)"); + min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, + "xs:nonNegativeInteger"); + xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max); + /* + * Create & parse the wildcard. + */ + wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node); + if (wild == NULL) + return (NULL); + xmlSchemaParseWildcardNs(ctxt, schema, wild, node); + /* + * And now for the children... + */ + child = node->children; + if (IS_SCHEMA(child, "annotation")) { + annot = xmlSchemaParseAnnotation(ctxt, child, 1); + child = child->next; + } + if (child != NULL) { + xmlSchemaPContentErr(ctxt, + XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, + NULL, node, child, + NULL, "(annotation?)"); + } + /* + * No component if minOccurs==maxOccurs==0. + */ + if ((min == 0) && (max == 0)) { + /* Don't free the wildcard, since it's already on the list. */ + return (NULL); + } + /* + * Create the particle. + */ + particle = xmlSchemaAddParticle(ctxt, node, min, max); + if (particle == NULL) + return (NULL); + particle->annot = annot; + particle->children = (xmlSchemaTreeItemPtr) wild; + + return (particle); +} + +/** + * xmlSchemaParseNotation: + * @ctxt: a schema validation context + * @schema: the schema being built + * @node: a subtree containing XML Schema informations + * + * parse a XML schema Notation declaration + * + * Returns the new structure or NULL in case of error + */ +static xmlSchemaNotationPtr +xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, + xmlNodePtr node) +{ + const xmlChar *name; + xmlSchemaNotationPtr ret; + xmlNodePtr child = NULL; + + if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) + return (NULL); + name = xmlSchemaGetProp(ctxt, node, "name"); + if (name == NULL) { + xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME, + "Notation has no name\n", NULL, NULL); + return (NULL); + } + ret = xmlSchemaAddNotation(ctxt, schema, name, + ctxt->targetNamespace, node); + if (ret == NULL) + return (NULL); + xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); + + child = node->children; + if (IS_SCHEMA(child, "annotation")) { + ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1); + child = child->next; + } + if (child != NULL) { + xmlSchemaPContentErr(ctxt, + XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, + NULL, node, child, + NULL, "(annotation?)"); + } + + return (ret); +} + +/** + * xmlSchemaParseAnyAttribute: + * @ctxt: a schema validation context + * @schema: the schema being built + * @node: a subtree containing XML Schema informations + * + * parse a XML schema AnyAttrribute declaration + * *WARNING* this interface is highly subject to change + * + * Returns a wildcard or NULL. + */ +static xmlSchemaWildcardPtr +xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt, + xmlSchemaPtr schema, xmlNodePtr node) +{ + xmlSchemaWildcardPtr ret; + xmlNodePtr child = NULL; + xmlAttrPtr attr; + + if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) + return (NULL); + + ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE, + node); + if (ret == NULL) { + return (NULL); + } + /* + * Check for illegal attributes. + */ + attr = node->properties; + while (attr != NULL) { + if (attr->ns == NULL) { + if ((!xmlStrEqual(attr->name, BAD_CAST "id")) && + (!xmlStrEqual(attr->name, BAD_CAST "namespace")) && + (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) { + xmlSchemaPIllegalAttrErr(ctxt, + XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); + } + } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { + xmlSchemaPIllegalAttrErr(ctxt, + XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); + } + attr = attr->next; + } + xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); + /* + * Parse the namespace list. + */ + if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0) + return (NULL); + /* + * And now for the children... + */ + child = node->children; + if (IS_SCHEMA(child, "annotation")) { + ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1); + child = child->next; + } + if (child != NULL) { + xmlSchemaPContentErr(ctxt, + XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, + NULL, node, child, + NULL, "(annotation?)"); + } + + return (ret); +} + + +/** + * xmlSchemaParseAttribute: + * @ctxt: a schema validation context + * @schema: the schema being built + * @node: a subtree containing XML Schema informations + * + * parse a XML schema Attrribute declaration + * *WARNING* this interface is highly subject to change + * + * Returns the attribute declaration. + */ +static xmlSchemaBasicItemPtr +xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt, + xmlSchemaPtr schema, + xmlNodePtr node, + xmlSchemaItemListPtr uses, + int parentType) +{ + const xmlChar *attrValue, *name = NULL, *ns = NULL; + xmlSchemaAttributeUsePtr use = NULL; + xmlNodePtr child = NULL; + xmlAttrPtr attr; + const xmlChar *tmpNs = NULL, *tmpName = NULL, *defValue = NULL; + int isRef = 0, occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL; + int nberrors, hasForm = 0, defValueType = 0; + +#define WXS_ATTR_DEF_VAL_DEFAULT 1 +#define WXS_ATTR_DEF_VAL_FIXED 2 + + /* + * 3.2.3 Constraints on XML Representations of Attribute Declarations + */ + + if ((pctxt == NULL) || (schema == NULL) || (node == NULL)) + return (NULL); + attr = xmlSchemaGetPropNode(node, "ref"); + if (attr != NULL) { + if (xmlSchemaPValAttrNodeQName(pctxt, schema, + NULL, attr, &tmpNs, &tmpName) != 0) { + return (NULL); + } + if (xmlSchemaCheckReference(pctxt, schema, node, attr, tmpNs) != 0) + return(NULL); + isRef = 1; + } + nberrors = pctxt->nberrors; + /* + * Check for illegal attributes. + */ + attr = node->properties; + while (attr != NULL) { + if (attr->ns == NULL) { + if (isRef) { + if (xmlStrEqual(attr->name, BAD_CAST "id")) { + xmlSchemaPValAttrNodeID(pctxt, attr); + goto attr_next; + } else if (xmlStrEqual(attr->name, BAD_CAST "ref")) { + goto attr_next; + } + } else { + if (xmlStrEqual(attr->name, BAD_CAST "name")) { + goto attr_next; + } else if (xmlStrEqual(attr->name, BAD_CAST "id")) { + xmlSchemaPValAttrNodeID(pctxt, attr); + goto attr_next; + } else if (xmlStrEqual(attr->name, BAD_CAST "type")) { + xmlSchemaPValAttrNodeQName(pctxt, schema, NULL, + attr, &tmpNs, &tmpName); + goto attr_next; + } else if (xmlStrEqual(attr->name, BAD_CAST "form")) { + /* + * Evaluate the target namespace + */ + hasForm = 1; + attrValue = xmlSchemaGetNodeContent(pctxt, + (xmlNodePtr) attr); + if (xmlStrEqual(attrValue, BAD_CAST "qualified")) { + ns = pctxt->targetNamespace; + } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) + { + xmlSchemaPSimpleTypeErr(pctxt, + XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, + NULL, (xmlNodePtr) attr, + NULL, "(qualified | unqualified)", + attrValue, NULL, NULL, NULL); + } + goto attr_next; + } + } + if (xmlStrEqual(attr->name, BAD_CAST "use")) { + + attrValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr); + /* TODO: Maybe we need to normalize the value beforehand. */ + if (xmlStrEqual(attrValue, BAD_CAST "optional")) + occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL; + else if (xmlStrEqual(attrValue, BAD_CAST "prohibited")) + occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED; + else if (xmlStrEqual(attrValue, BAD_CAST "required")) + occurs = XML_SCHEMAS_ATTR_USE_REQUIRED; + else { + xmlSchemaPSimpleTypeErr(pctxt, + XML_SCHEMAP_INVALID_ATTR_USE, + NULL, (xmlNodePtr) attr, + NULL, "(optional | prohibited | required)", + attrValue, NULL, NULL, NULL); + } + goto attr_next; + } else if (xmlStrEqual(attr->name, BAD_CAST "default")) { + /* + * 3.2.3 : 1 + * default and fixed must not both be present. + */ + if (defValue) { + xmlSchemaPMutualExclAttrErr(pctxt, + XML_SCHEMAP_SRC_ATTRIBUTE_1, + NULL, attr, "default", "fixed"); + } else { + defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr); + defValueType = WXS_ATTR_DEF_VAL_DEFAULT; + } + goto attr_next; + } else if (xmlStrEqual(attr->name, BAD_CAST "fixed")) { + /* + * 3.2.3 : 1 + * default and fixed must not both be present. + */ + if (defValue) { + xmlSchemaPMutualExclAttrErr(pctxt, + XML_SCHEMAP_SRC_ATTRIBUTE_1, + NULL, attr, "default", "fixed"); + } else { + defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr); + defValueType = WXS_ATTR_DEF_VAL_FIXED; + } + goto attr_next; + } + } else if (! xmlStrEqual(attr->ns->href, xmlSchemaNs)) + goto attr_next; + + xmlSchemaPIllegalAttrErr(pctxt, + XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); + +attr_next: + attr = attr->next; + } + /* + * 3.2.3 : 2 + * If default and use are both present, use must have + * the actual value optional. + */ + if ((defValueType == WXS_ATTR_DEF_VAL_DEFAULT) && + (occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL)) { + xmlSchemaPSimpleTypeErr(pctxt, + XML_SCHEMAP_SRC_ATTRIBUTE_2, + NULL, node, NULL, + "(optional | prohibited | required)", NULL, + "The value of the attribute 'use' must be 'optional' " + "if the attribute 'default' is present", + NULL, NULL); + } + /* + * We want correct attributes. + */ + if (nberrors != pctxt->nberrors) + return(NULL); + if (! isRef) { + xmlSchemaAttributePtr attrDecl; + + /* TODO: move XML_SCHEMAS_QUALIF_ATTR to the parser. */ + if ((! hasForm) && (schema->flags & XML_SCHEMAS_QUALIF_ATTR)) + ns = pctxt->targetNamespace; + /* + * 3.2.6 Schema Component Constraint: xsi: Not Allowed + * TODO: Move this to the component layer. + */ + if (xmlStrEqual(ns, xmlSchemaInstanceNs)) { + xmlSchemaCustomErr(ACTXT_CAST pctxt, + XML_SCHEMAP_NO_XSI, + node, NULL, + "The target namespace must not match '%s'", + xmlSchemaInstanceNs, NULL); + } + attr = xmlSchemaGetPropNode(node, "name"); + if (attr == NULL) { + xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING, + NULL, node, "name", NULL); + return (NULL); + } + if (xmlSchemaPValAttrNode(pctxt, NULL, attr, + xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) { + return (NULL); + } + /* + * 3.2.6 Schema Component Constraint: xmlns Not Allowed + * TODO: Move this to the component layer. + */ + if (xmlStrEqual(name, BAD_CAST "xmlns")) { + xmlSchemaPSimpleTypeErr(pctxt, + XML_SCHEMAP_NO_XMLNS, + NULL, (xmlNodePtr) attr, + xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL, + "The value of the attribute must not match 'xmlns'", + NULL, NULL); + return (NULL); + } + if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) + goto check_children; + /* + * Create the attribute use component. + */ + use = xmlSchemaAddAttributeUse(pctxt, node); + if (use == NULL) + return(NULL); + use->occurs = occurs; + /* + * Create the attribute declaration. + */ + attrDecl = xmlSchemaAddAttribute(pctxt, schema, name, ns, node, 0); + if (attrDecl == NULL) + return (NULL); + if (tmpName != NULL) { + attrDecl->typeName = tmpName; + attrDecl->typeNs = tmpNs; + } + use->attrDecl = attrDecl; + /* + * Value constraint. + */ + if (defValue != NULL) { + attrDecl->defValue = defValue; + if (defValueType == WXS_ATTR_DEF_VAL_FIXED) + attrDecl->flags |= XML_SCHEMAS_ATTR_FIXED; + } + } else if (occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) { + xmlSchemaQNameRefPtr ref; + + /* + * Create the attribute use component. + */ + use = xmlSchemaAddAttributeUse(pctxt, node); + if (use == NULL) + return(NULL); + /* + * We need to resolve the reference at later stage. + */ + WXS_ADD_PENDING(pctxt, use); + use->occurs = occurs; + /* + * Create a QName reference to the attribute declaration. + */ + ref = xmlSchemaNewQNameRef(pctxt, XML_SCHEMA_TYPE_ATTRIBUTE, + tmpName, tmpNs); + if (ref == NULL) + return(NULL); + /* + * Assign the reference. This will be substituted for the + * referenced attribute declaration when the QName is resolved. + */ + use->attrDecl = WXS_ATTR_CAST ref; + /* + * Value constraint. + */ + if (defValue != NULL) + use->defValue = defValue; + if (defValueType == WXS_ATTR_DEF_VAL_FIXED) + use->flags |= XML_SCHEMA_ATTR_USE_FIXED; + } + +check_children: + /* + * And now for the children... + */ + child = node->children; + if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) { + xmlSchemaAttributeUseProhibPtr prohib; + + if (IS_SCHEMA(child, "annotation")) { + xmlSchemaParseAnnotation(pctxt, child, 0); + child = child->next; + } + if (child != NULL) { + xmlSchemaPContentErr(pctxt, + XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, + NULL, node, child, NULL, + "(annotation?)"); + } + /* + * Check for pointlessness of attribute prohibitions. + */ + if (parentType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) { + xmlSchemaCustomWarning(ACTXT_CAST pctxt, + XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH, + node, NULL, + "Skipping attribute use prohibition, since it is " + "pointless inside an ", + NULL, NULL, NULL); + return(NULL); + } else if (parentType == XML_SCHEMA_TYPE_EXTENSION) { + xmlSchemaCustomWarning(ACTXT_CAST pctxt, + XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH, + node, NULL, + "Skipping attribute use prohibition, since it is " + "pointless when extending a type", + NULL, NULL, NULL); + return(NULL); + } + if (! isRef) { + tmpName = name; + tmpNs = ns; + } + /* + * Check for duplicate attribute prohibitions. + */ + if (uses) { + int i; + + for (i = 0; i < uses->nbItems; i++) { + use = uses->items[i]; + if ((use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) && + (tmpName == (WXS_ATTR_PROHIB_CAST use)->name) && + (tmpNs == (WXS_ATTR_PROHIB_CAST use)->targetNamespace)) + { + xmlChar *str = NULL; + + xmlSchemaCustomWarning(ACTXT_CAST pctxt, + XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH, + node, NULL, + "Skipping duplicate attribute use prohibition '%s'", + xmlSchemaFormatQName(&str, tmpNs, tmpName), + NULL, NULL); + FREE_AND_NULL(str) + return(NULL); + } + } + } + /* + * Create the attribute prohibition helper component. + */ + prohib = xmlSchemaAddAttributeUseProhib(pctxt); + if (prohib == NULL) + return(NULL); + prohib->node = node; + prohib->name = tmpName; + prohib->targetNamespace = tmpNs; + if (isRef) { + /* + * We need at least to resolve to the attribute declaration. + */ + WXS_ADD_PENDING(pctxt, prohib); + } + return(WXS_BASIC_CAST prohib); + } else { + if (IS_SCHEMA(child, "annotation")) { + /* + * TODO: Should this go into the attr decl? + */ + use->annot = xmlSchemaParseAnnotation(pctxt, child, 1); + child = child->next; + } + if (isRef) { + if (child != NULL) { + if (IS_SCHEMA(child, "simpleType")) + /* + * 3.2.3 : 3.2 + * If ref is present, then all of , + * form and type must be absent. + */ + xmlSchemaPContentErr(pctxt, + XML_SCHEMAP_SRC_ATTRIBUTE_3_2, + NULL, node, child, NULL, + "(annotation?)"); + else + xmlSchemaPContentErr(pctxt, + XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, + NULL, node, child, NULL, + "(annotation?)"); + } + } else { + if (IS_SCHEMA(child, "simpleType")) { + if (WXS_ATTRUSE_DECL(use)->typeName != NULL) { + /* + * 3.2.3 : 4 + * type and must not both be present. + */ + xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4, + NULL, node, child, + "The attribute 'type' and the child " + "are mutually exclusive", NULL); + } else + WXS_ATTRUSE_TYPEDEF(use) = + xmlSchemaParseSimpleType(pctxt, schema, child, 0); + child = child->next; + } + if (child != NULL) + xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, + NULL, node, child, NULL, + "(annotation?, simpleType?)"); + } + } + return (WXS_BASIC_CAST use); +} + + +static xmlSchemaAttributePtr +xmlSchemaParseGlobalAttribute(xmlSchemaParserCtxtPtr pctxt, + xmlSchemaPtr schema, + xmlNodePtr node) +{ + const xmlChar *attrValue; + xmlSchemaAttributePtr ret; + xmlNodePtr child = NULL; + xmlAttrPtr attr; + + /* + * Note that the w3c spec assumes the schema to be validated with schema + * for schemas beforehand. + * + * 3.2.3 Constraints on XML Representations of Attribute Declarations + */ + if ((pctxt == NULL) || (schema == NULL) || (node == NULL)) + return (NULL); + /* + * 3.2.3 : 3.1 + * One of ref or name must be present, but not both + */ + attr = xmlSchemaGetPropNode(node, "name"); + if (attr == NULL) { + xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING, + NULL, node, "name", NULL); + return (NULL); + } + if (xmlSchemaPValAttrNode(pctxt, NULL, attr, + xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) { + return (NULL); + } + /* + * 3.2.6 Schema Component Constraint: xmlns Not Allowed + * TODO: Move this to the component layer. + */ + if (xmlStrEqual(attrValue, BAD_CAST "xmlns")) { + xmlSchemaPSimpleTypeErr(pctxt, + XML_SCHEMAP_NO_XMLNS, + NULL, (xmlNodePtr) attr, + xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL, + "The value of the attribute must not match 'xmlns'", + NULL, NULL); + return (NULL); + } + /* + * 3.2.6 Schema Component Constraint: xsi: Not Allowed + * TODO: Move this to the component layer. + * Or better leave it here and add it to the component layer + * if we have a schema construction API. + */ + if (xmlStrEqual(pctxt->targetNamespace, xmlSchemaInstanceNs)) { + xmlSchemaCustomErr(ACTXT_CAST pctxt, + XML_SCHEMAP_NO_XSI, node, NULL, + "The target namespace must not match '%s'", + xmlSchemaInstanceNs, NULL); + } + + ret = xmlSchemaAddAttribute(pctxt, schema, attrValue, + pctxt->targetNamespace, node, 1); + if (ret == NULL) + return (NULL); + ret->flags |= XML_SCHEMAS_ATTR_GLOBAL; + + /* + * Check for illegal attributes. + */ + attr = node->properties; + while (attr != NULL) { + if (attr->ns == NULL) { + if ((!xmlStrEqual(attr->name, BAD_CAST "id")) && + (!xmlStrEqual(attr->name, BAD_CAST "default")) && + (!xmlStrEqual(attr->name, BAD_CAST "fixed")) && + (!xmlStrEqual(attr->name, BAD_CAST "name")) && + (!xmlStrEqual(attr->name, BAD_CAST "type"))) + { + xmlSchemaPIllegalAttrErr(pctxt, + XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); + } + } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { + xmlSchemaPIllegalAttrErr(pctxt, + XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); + } + attr = attr->next; + } + xmlSchemaPValAttrQName(pctxt, schema, NULL, + node, "type", &ret->typeNs, &ret->typeName); + + xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id"); + /* + * Attribute "fixed". + */ + ret->defValue = xmlSchemaGetProp(pctxt, node, "fixed"); + if (ret->defValue != NULL) + ret->flags |= XML_SCHEMAS_ATTR_FIXED; + /* + * Attribute "default". + */ + attr = xmlSchemaGetPropNode(node, "default"); + if (attr != NULL) { + /* + * 3.2.3 : 1 + * default and fixed must not both be present. + */ + if (ret->flags & XML_SCHEMAS_ATTR_FIXED) { + xmlSchemaPMutualExclAttrErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1, + WXS_BASIC_CAST ret, attr, "default", "fixed"); + } else + ret->defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr); + } + /* + * And now for the children... + */ + child = node->children; + if (IS_SCHEMA(child, "annotation")) { + ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1); + child = child->next; + } + if (IS_SCHEMA(child, "simpleType")) { + if (ret->typeName != NULL) { + /* + * 3.2.3 : 4 + * type and must not both be present. + */ + xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4, + NULL, node, child, + "The attribute 'type' and the child " + "are mutually exclusive", NULL); + } else + ret->subtypes = xmlSchemaParseSimpleType(pctxt, schema, child, 0); + child = child->next; + } + if (child != NULL) + xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, + NULL, node, child, NULL, + "(annotation?, simpleType?)"); + + return (ret); +} + +/** + * xmlSchemaParseAttributeGroupRef: + * @ctxt: a schema validation context + * @schema: the schema being built + * @node: a subtree containing XML Schema informations + * + * Parse an attribute group definition reference. + * Note that a reference to an attribute group does not + * correspond to any component at all. + * *WARNING* this interface is highly subject to change + * + * Returns the attribute group or NULL in case of error. + */ +static xmlSchemaQNameRefPtr +xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt, + xmlSchemaPtr schema, + xmlNodePtr node) +{ + xmlSchemaQNameRefPtr ret; + xmlNodePtr child = NULL; + xmlAttrPtr attr; + const xmlChar *refNs = NULL, *ref = NULL; + + if ((pctxt == NULL) || (schema == NULL) || (node == NULL)) + return (NULL); + + attr = xmlSchemaGetPropNode(node, "ref"); + if (attr == NULL) { + xmlSchemaPMissingAttrErr(pctxt, + XML_SCHEMAP_S4S_ATTR_MISSING, + NULL, node, "ref", NULL); + return (NULL); + } + xmlSchemaPValAttrNodeQName(pctxt, schema, + NULL, attr, &refNs, &ref); + if (xmlSchemaCheckReference(pctxt, schema, node, attr, refNs) != 0) + return(NULL); + + /* + * Check for illegal attributes. + */ + attr = node->properties; + while (attr != NULL) { + if (attr->ns == NULL) { + if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) && + (!xmlStrEqual(attr->name, BAD_CAST "id"))) + { + xmlSchemaPIllegalAttrErr(pctxt, + XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); + } + } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { + xmlSchemaPIllegalAttrErr(pctxt, + XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); + } + attr = attr->next; + } + /* Attribute ID */ + xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id"); + + /* + * And now for the children... + */ + child = node->children; + if (IS_SCHEMA(child, "annotation")) { + /* + * TODO: We do not have a place to store the annotation, do we? + */ + xmlSchemaParseAnnotation(pctxt, child, 0); + child = child->next; + } + if (child != NULL) { + xmlSchemaPContentErr(pctxt, + XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, + NULL, node, child, NULL, + "(annotation?)"); + } + + /* + * Handle attribute group redefinitions. + */ + if (pctxt->isRedefine && pctxt->redef && + (pctxt->redef->item->type == + XML_SCHEMA_TYPE_ATTRIBUTEGROUP) && + (ref == pctxt->redef->refName) && + (refNs == pctxt->redef->refTargetNs)) + { + /* + * SPEC src-redefine: + * (7.1) "If it has an among its contents + * the ·actual value· of whose ref [attribute] is the same + * as the ·actual value· of its own name attribute plus + * target namespace, then it must have exactly one such group." + */ + if (pctxt->redefCounter != 0) { + xmlChar *str = NULL; + + xmlSchemaCustomErr(ACTXT_CAST pctxt, + XML_SCHEMAP_SRC_REDEFINE, node, NULL, + "The redefining attribute group definition " + "'%s' must not contain more than one " + "reference to the redefined definition", + xmlSchemaFormatQName(&str, refNs, ref), NULL); + FREE_AND_NULL(str); + return(NULL); + } + pctxt->redefCounter++; + /* + * URGENT TODO: How to ensure that the reference will not be + * handled by the normal component resolution mechanism? + */ + ret = xmlSchemaNewQNameRef(pctxt, + XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs); + if (ret == NULL) + return(NULL); + ret->node = node; + pctxt->redef->reference = WXS_BASIC_CAST ret; + } else { + /* + * Create a QName-reference helper component. We will substitute this + * component for the attribute uses of the referenced attribute group + * definition. + */ + ret = xmlSchemaNewQNameRef(pctxt, + XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs); + if (ret == NULL) + return(NULL); + ret->node = node; + /* Add to pending items, to be able to resolve the reference. */ + WXS_ADD_PENDING(pctxt, ret); + } + return (ret); +} + +/** + * xmlSchemaParseAttributeGroupDefinition: + * @pctxt: a schema validation context + * @schema: the schema being built + * @node: a subtree containing XML Schema informations + * + * parse a XML schema Attribute Group declaration + * *WARNING* this interface is highly subject to change + * + * Returns the attribute group definition or NULL in case of error. + */ +static xmlSchemaAttributeGroupPtr +xmlSchemaParseAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt, + xmlSchemaPtr schema, + xmlNodePtr node) +{ + const xmlChar *name; + xmlSchemaAttributeGroupPtr ret; + xmlNodePtr child = NULL; + xmlAttrPtr attr; + int hasRefs = 0; + + if ((pctxt == NULL) || (schema == NULL) || (node == NULL)) + return (NULL); + + attr = xmlSchemaGetPropNode(node, "name"); + if (attr == NULL) { + xmlSchemaPMissingAttrErr(pctxt, + XML_SCHEMAP_S4S_ATTR_MISSING, + NULL, node, "name", NULL); + return (NULL); + } + /* + * The name is crucial, exit if invalid. + */ + if (xmlSchemaPValAttrNode(pctxt, + NULL, attr, + xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) { + return (NULL); + } + ret = xmlSchemaAddAttributeGroupDefinition(pctxt, schema, + name, pctxt->targetNamespace, node); + if (ret == NULL) + return (NULL); + /* + * Check for illegal attributes. + */ + attr = node->properties; + while (attr != NULL) { + if (attr->ns == NULL) { + if ((!xmlStrEqual(attr->name, BAD_CAST "name")) && + (!xmlStrEqual(attr->name, BAD_CAST "id"))) + { + xmlSchemaPIllegalAttrErr(pctxt, + XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); + } + } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { + xmlSchemaPIllegalAttrErr(pctxt, + XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); + } + attr = attr->next; + } + /* Attribute ID */ + xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id"); + /* + * And now for the children... + */ + child = node->children; + if (IS_SCHEMA(child, "annotation")) { + ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1); + child = child->next; + } + /* + * Parse contained attribute decls/refs. + */ + if (xmlSchemaParseLocalAttributes(pctxt, schema, &child, + (xmlSchemaItemListPtr *) &(ret->attrUses), + XML_SCHEMA_TYPE_ATTRIBUTEGROUP, &hasRefs) == -1) + return(NULL); + if (hasRefs) + ret->flags |= XML_SCHEMAS_ATTRGROUP_HAS_REFS; + /* + * Parse the attribute wildcard. + */ + if (IS_SCHEMA(child, "anyAttribute")) { + ret->attributeWildcard = xmlSchemaParseAnyAttribute(pctxt, + schema, child); + child = child->next; + } + if (child != NULL) { + xmlSchemaPContentErr(pctxt, + XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, + NULL, node, child, NULL, + "(annotation?, ((attribute | attributeGroup)*, anyAttribute?))"); + } + return (ret); +} + +/** + * xmlSchemaPValAttrFormDefault: + * @value: the value + * @flags: the flags to be modified + * @flagQualified: the specific flag for "qualified" + * + * Returns 0 if the value is valid, 1 otherwise. + */ +static int +xmlSchemaPValAttrFormDefault(const xmlChar *value, + int *flags, + int flagQualified) +{ + if (xmlStrEqual(value, BAD_CAST "qualified")) { + if ((*flags & flagQualified) == 0) + *flags |= flagQualified; + } else if (!xmlStrEqual(value, BAD_CAST "unqualified")) + return (1); + + return (0); +} + +/** + * xmlSchemaPValAttrBlockFinal: + * @value: the value + * @flags: the flags to be modified + * @flagAll: the specific flag for "#all" + * @flagExtension: the specific flag for "extension" + * @flagRestriction: the specific flag for "restriction" + * @flagSubstitution: the specific flag for "substitution" + * @flagList: the specific flag for "list" + * @flagUnion: the specific flag for "union" + * + * Validates the value of the attribute "final" and "block". The value + * is converted into the specified flag values and returned in @flags. + * + * Returns 0 if the value is valid, 1 otherwise. + */ + +static int +xmlSchemaPValAttrBlockFinal(const xmlChar *value, + int *flags, + int flagAll, + int flagExtension, + int flagRestriction, + int flagSubstitution, + int flagList, + int flagUnion) +{ + int ret = 0; + + /* + * TODO: This does not check for dublicate entries. + */ + if ((flags == NULL) || (value == NULL)) + return (-1); + if (value[0] == 0) + return (0); + if (xmlStrEqual(value, BAD_CAST "#all")) { + if (flagAll != -1) + *flags |= flagAll; + else { + if (flagExtension != -1) + *flags |= flagExtension; + if (flagRestriction != -1) + *flags |= flagRestriction; + if (flagSubstitution != -1) + *flags |= flagSubstitution; + if (flagList != -1) + *flags |= flagList; + if (flagUnion != -1) + *flags |= flagUnion; + } + } else { + const xmlChar *end, *cur = value; + xmlChar *item; + + do { + while (IS_BLANK_CH(*cur)) + cur++; + end = cur; + while ((*end != 0) && (!(IS_BLANK_CH(*end)))) + end++; + if (end == cur) + break; + item = xmlStrndup(cur, end - cur); + if (xmlStrEqual(item, BAD_CAST "extension")) { + if (flagExtension != -1) { + if ((*flags & flagExtension) == 0) + *flags |= flagExtension; + } else + ret = 1; + } else if (xmlStrEqual(item, BAD_CAST "restriction")) { + if (flagRestriction != -1) { + if ((*flags & flagRestriction) == 0) + *flags |= flagRestriction; + } else + ret = 1; + } else if (xmlStrEqual(item, BAD_CAST "substitution")) { + if (flagSubstitution != -1) { + if ((*flags & flagSubstitution) == 0) + *flags |= flagSubstitution; + } else + ret = 1; + } else if (xmlStrEqual(item, BAD_CAST "list")) { + if (flagList != -1) { + if ((*flags & flagList) == 0) + *flags |= flagList; + } else + ret = 1; + } else if (xmlStrEqual(item, BAD_CAST "union")) { + if (flagUnion != -1) { + if ((*flags & flagUnion) == 0) + *flags |= flagUnion; + } else + ret = 1; + } else + ret = 1; + if (item != NULL) + xmlFree(item); + cur = end; + } while ((ret == 0) && (*cur != 0)); + } + + return (ret); +} + +static int +xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt, + xmlSchemaIDCPtr idc, + xmlSchemaIDCSelectPtr selector, + xmlAttrPtr attr, + int isField) +{ + xmlNodePtr node; + + /* + * c-selector-xpath: + * Schema Component Constraint: Selector Value OK + * + * TODO: 1 The {selector} must be a valid XPath expression, as defined + * in [XPath]. + */ + if (selector == NULL) { + xmlSchemaPErr(ctxt, idc->node, + XML_SCHEMAP_INTERNAL, + "Internal error: xmlSchemaCheckCSelectorXPath, " + "the selector is not specified.\n", NULL, NULL); + return (-1); + } + if (attr == NULL) + node = idc->node; + else + node = (xmlNodePtr) attr; + if (selector->xpath == NULL) { + xmlSchemaPCustomErr(ctxt, + /* TODO: Adjust error code. */ + XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, + NULL, node, + "The XPath expression of the selector is not valid", NULL); + return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE); + } else { + const xmlChar **nsArray = NULL; + xmlNsPtr *nsList = NULL; + /* + * Compile the XPath expression. + */ + /* + * TODO: We need the array of in-scope namespaces for compilation. + * TODO: Call xmlPatterncompile with different options for selector/ + * field. + */ + if (attr == NULL) + nsList = NULL; + else + nsList = xmlGetNsList(attr->doc, attr->parent); + /* + * Build an array of prefixes and namespaces. + */ + if (nsList != NULL) { + int i, count = 0; + + for (i = 0; nsList[i] != NULL; i++) + count++; + + nsArray = (const xmlChar **) xmlMalloc( + (count * 2 + 1) * sizeof(const xmlChar *)); + if (nsArray == NULL) { + xmlSchemaPErrMemory(ctxt, "allocating a namespace array", + NULL); + xmlFree(nsList); + return (-1); + } + for (i = 0; i < count; i++) { + nsArray[2 * i] = nsList[i]->href; + nsArray[2 * i + 1] = nsList[i]->prefix; + } + nsArray[count * 2] = NULL; + xmlFree(nsList); + } + /* + * TODO: Differentiate between "selector" and "field". + */ + if (isField) + selector->xpathComp = (void *) xmlPatterncompile(selector->xpath, + NULL, XML_PATTERN_XSFIELD, nsArray); + else + selector->xpathComp = (void *) xmlPatterncompile(selector->xpath, + NULL, XML_PATTERN_XSSEL, nsArray); + if (nsArray != NULL) + xmlFree((xmlChar **) nsArray); + + if (selector->xpathComp == NULL) { + xmlSchemaPCustomErr(ctxt, + /* TODO: Adjust error code? */ + XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, + NULL, node, + "The XPath expression '%s' could not be " + "compiled", selector->xpath); + return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE); + } + } + return (0); +} + +#define ADD_ANNOTATION(annot) \ + xmlSchemaAnnotPtr cur = item->annot; \ + if (item->annot == NULL) { \ + item->annot = annot; \ + return (annot); \ + } \ + cur = item->annot; \ + if (cur->next != NULL) { \ + cur = cur->next; \ + } \ + cur->next = annot; + +/** + * xmlSchemaAssignAnnotation: + * @item: the schema component + * @annot: the annotation + * + * Adds the annotation to the given schema component. + * + * Returns the given annotaion. + */ +static xmlSchemaAnnotPtr +xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem, + xmlSchemaAnnotPtr annot) +{ + if ((annItem == NULL) || (annot == NULL)) + return (NULL); + switch (annItem->type) { + case XML_SCHEMA_TYPE_ELEMENT: { + xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem; + ADD_ANNOTATION(annot) + } + break; + case XML_SCHEMA_TYPE_ATTRIBUTE: { + xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem; + ADD_ANNOTATION(annot) + } + break; + case XML_SCHEMA_TYPE_ANY_ATTRIBUTE: + case XML_SCHEMA_TYPE_ANY: { + xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem; + ADD_ANNOTATION(annot) + } + break; + case XML_SCHEMA_TYPE_PARTICLE: + case XML_SCHEMA_TYPE_IDC_KEY: + case XML_SCHEMA_TYPE_IDC_KEYREF: + case XML_SCHEMA_TYPE_IDC_UNIQUE: { + xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem; + ADD_ANNOTATION(annot) + } + break; + case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: { + xmlSchemaAttributeGroupPtr item = + (xmlSchemaAttributeGroupPtr) annItem; + ADD_ANNOTATION(annot) + } + break; + case XML_SCHEMA_TYPE_NOTATION: { + xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem; + ADD_ANNOTATION(annot) + } + break; + case XML_SCHEMA_FACET_MININCLUSIVE: + case XML_SCHEMA_FACET_MINEXCLUSIVE: + case XML_SCHEMA_FACET_MAXINCLUSIVE: + case XML_SCHEMA_FACET_MAXEXCLUSIVE: + case XML_SCHEMA_FACET_TOTALDIGITS: + case XML_SCHEMA_FACET_FRACTIONDIGITS: + case XML_SCHEMA_FACET_PATTERN: + case XML_SCHEMA_FACET_ENUMERATION: + case XML_SCHEMA_FACET_WHITESPACE: + case XML_SCHEMA_FACET_LENGTH: + case XML_SCHEMA_FACET_MAXLENGTH: + case XML_SCHEMA_FACET_MINLENGTH: { + xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem; + ADD_ANNOTATION(annot) + } + break; + case XML_SCHEMA_TYPE_SIMPLE: + case XML_SCHEMA_TYPE_COMPLEX: { + xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem; + ADD_ANNOTATION(annot) + } + break; + case XML_SCHEMA_TYPE_GROUP: { + xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem; + ADD_ANNOTATION(annot) + } + break; + case XML_SCHEMA_TYPE_SEQUENCE: + case XML_SCHEMA_TYPE_CHOICE: + case XML_SCHEMA_TYPE_ALL: { + xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem; + ADD_ANNOTATION(annot) + } + break; + default: + xmlSchemaPCustomErr(NULL, + XML_SCHEMAP_INTERNAL, + NULL, NULL, + "Internal error: xmlSchemaAddAnnotation, " + "The item is not a annotated schema component", NULL); + break; + } + return (annot); +} + +/** + * xmlSchemaParseIDCSelectorAndField: + * @ctxt: a schema validation context + * @schema: the schema being built + * @node: a subtree containing XML Schema informations + * + * Parses a XML Schema identity-contraint definition's + * and elements. + * + * Returns the parsed identity-constraint definition. + */ +static xmlSchemaIDCSelectPtr +xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt, + xmlSchemaIDCPtr idc, + xmlNodePtr node, + int isField) +{ + xmlSchemaIDCSelectPtr item; + xmlNodePtr child = NULL; + xmlAttrPtr attr; + + /* + * Check for illegal attributes. + */ + attr = node->properties; + while (attr != NULL) { + if (attr->ns == NULL) { + if ((!xmlStrEqual(attr->name, BAD_CAST "id")) && + (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) { + xmlSchemaPIllegalAttrErr(ctxt, + XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); + } + } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { + xmlSchemaPIllegalAttrErr(ctxt, + XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); + } + attr = attr->next; + } + /* + * Create the item. + */ + item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect)); + if (item == NULL) { + xmlSchemaPErrMemory(ctxt, + "allocating a 'selector' of an identity-constraint definition", + NULL); + return (NULL); + } + memset(item, 0, sizeof(xmlSchemaIDCSelect)); + /* + * Attribute "xpath" (mandatory). + */ + attr = xmlSchemaGetPropNode(node, "xpath"); + if (attr == NULL) { + xmlSchemaPMissingAttrErr(ctxt, + XML_SCHEMAP_S4S_ATTR_MISSING, + NULL, node, + "name", NULL); + } else { + item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr); + /* + * URGENT TODO: "field"s have an other syntax than "selector"s. + */ + + if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr, + isField) == -1) { + xmlSchemaPErr(ctxt, + (xmlNodePtr) attr, + XML_SCHEMAP_INTERNAL, + "Internal error: xmlSchemaParseIDCSelectorAndField, " + "validating the XPath expression of a IDC selector.\n", + NULL, NULL); + } + + } + xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); + /* + * And now for the children... + */ + child = node->children; + if (IS_SCHEMA(child, "annotation")) { + /* + * Add the annotation to the parent IDC. + */ + xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc, + xmlSchemaParseAnnotation(ctxt, child, 1)); + child = child->next; + } + if (child != NULL) { + xmlSchemaPContentErr(ctxt, + XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, + NULL, node, child, + NULL, "(annotation?)"); + } + + return (item); +} + +/** + * xmlSchemaParseIDC: + * @ctxt: a schema validation context + * @schema: the schema being built + * @node: a subtree containing XML Schema informations + * + * Parses a XML Schema identity-contraint definition. + * + * Returns the parsed identity-constraint definition. + */ +static xmlSchemaIDCPtr +xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt, + xmlSchemaPtr schema, + xmlNodePtr node, + xmlSchemaTypeType idcCategory, + const xmlChar *targetNamespace) +{ + xmlSchemaIDCPtr item = NULL; + xmlNodePtr child = NULL; + xmlAttrPtr attr; + const xmlChar *name = NULL; + xmlSchemaIDCSelectPtr field = NULL, lastField = NULL; + + /* + * Check for illegal attributes. + */ + attr = node->properties; + while (attr != NULL) { + if (attr->ns == NULL) { + if ((!xmlStrEqual(attr->name, BAD_CAST "id")) && + (!xmlStrEqual(attr->name, BAD_CAST "name")) && + ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) || + (!xmlStrEqual(attr->name, BAD_CAST "refer")))) { + xmlSchemaPIllegalAttrErr(ctxt, + XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); + } + } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { + xmlSchemaPIllegalAttrErr(ctxt, + XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); + } + attr = attr->next; + } + /* + * Attribute "name" (mandatory). + */ + attr = xmlSchemaGetPropNode(node, "name"); + if (attr == NULL) { + xmlSchemaPMissingAttrErr(ctxt, + XML_SCHEMAP_S4S_ATTR_MISSING, + NULL, node, + "name", NULL); + return (NULL); + } else if (xmlSchemaPValAttrNode(ctxt, + NULL, attr, + xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) { + return (NULL); + } + /* Create the component. */ + item = xmlSchemaAddIDC(ctxt, schema, name, targetNamespace, + idcCategory, node); + if (item == NULL) + return(NULL); + + xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); + if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) { + /* + * Attribute "refer" (mandatory). + */ + attr = xmlSchemaGetPropNode(node, "refer"); + if (attr == NULL) { + xmlSchemaPMissingAttrErr(ctxt, + XML_SCHEMAP_S4S_ATTR_MISSING, + NULL, node, + "refer", NULL); + } else { + /* + * Create a reference item. + */ + item->ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_IDC_KEY, + NULL, NULL); + if (item->ref == NULL) + return (NULL); + xmlSchemaPValAttrNodeQName(ctxt, schema, + NULL, attr, + &(item->ref->targetNamespace), + &(item->ref->name)); + xmlSchemaCheckReference(ctxt, schema, node, attr, + item->ref->targetNamespace); + } + } + /* + * And now for the children... + */ + child = node->children; + if (IS_SCHEMA(child, "annotation")) { + item->annot = xmlSchemaParseAnnotation(ctxt, child, 1); + child = child->next; + } + if (child == NULL) { + xmlSchemaPContentErr(ctxt, + XML_SCHEMAP_S4S_ELEM_MISSING, + NULL, node, child, + "A child element is missing", + "(annotation?, (selector, field+))"); + } + /* + * Child element . + */ + if (IS_SCHEMA(child, "selector")) { + item->selector = xmlSchemaParseIDCSelectorAndField(ctxt, + item, child, 0); + child = child->next; + /* + * Child elements . + */ + if (IS_SCHEMA(child, "field")) { + do { + field = xmlSchemaParseIDCSelectorAndField(ctxt, + item, child, 1); + if (field != NULL) { + field->index = item->nbFields; + item->nbFields++; + if (lastField != NULL) + lastField->next = field; + else + item->fields = field; + lastField = field; + } + child = child->next; + } while (IS_SCHEMA(child, "field")); + } else { + xmlSchemaPContentErr(ctxt, + XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, + NULL, node, child, + NULL, "(annotation?, (selector, field+))"); + } + } + if (child != NULL) { + xmlSchemaPContentErr(ctxt, + XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, + NULL, node, child, + NULL, "(annotation?, (selector, field+))"); + } + + return (item); +} + +/** + * xmlSchemaParseElement: + * @ctxt: a schema validation context + * @schema: the schema being built + * @node: a subtree containing XML Schema informations + * @topLevel: indicates if this is global declaration + * + * Parses a XML schema element declaration. + * *WARNING* this interface is highly subject to change + * + * Returns the element declaration or a particle; NULL in case + * of an error or if the particle has minOccurs==maxOccurs==0. + */ +static xmlSchemaBasicItemPtr +xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, + xmlNodePtr node, int *isElemRef, int topLevel) +{ + xmlSchemaElementPtr decl = NULL; + xmlSchemaParticlePtr particle = NULL; + xmlSchemaAnnotPtr annot = NULL; + xmlNodePtr child = NULL; + xmlAttrPtr attr, nameAttr; + int min, max, isRef = 0; + xmlChar *des = NULL; + + /* 3.3.3 Constraints on XML Representations of Element Declarations */ + /* TODO: Complete implementation of 3.3.6 */ + + if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) + return (NULL); + + if (isElemRef != NULL) + *isElemRef = 0; + /* + * If we get a "ref" attribute on a local we will assume it's + * a reference - even if there's a "name" attribute; this seems to be more + * robust. + */ + nameAttr = xmlSchemaGetPropNode(node, "name"); + attr = xmlSchemaGetPropNode(node, "ref"); + if ((topLevel) || (attr == NULL)) { + if (nameAttr == NULL) { + xmlSchemaPMissingAttrErr(ctxt, + XML_SCHEMAP_S4S_ATTR_MISSING, + NULL, node, "name", NULL); + return (NULL); + } + } else + isRef = 1; + + xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); + child = node->children; + if (IS_SCHEMA(child, "annotation")) { + annot = xmlSchemaParseAnnotation(ctxt, child, 1); + child = child->next; + } + /* + * Skip particle part if a global declaration. + */ + if (topLevel) + goto declaration_part; + /* + * The particle part ================================================== + */ + min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger"); + max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(xs:nonNegativeInteger | unbounded)"); + xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max); + particle = xmlSchemaAddParticle(ctxt, node, min, max); + if (particle == NULL) + goto return_null; + + /* ret->flags |= XML_SCHEMAS_ELEM_REF; */ + + if (isRef) { + const xmlChar *refNs = NULL, *ref = NULL; + xmlSchemaQNameRefPtr refer = NULL; + /* + * The reference part ============================================= + */ + if (isElemRef != NULL) + *isElemRef = 1; + + xmlSchemaPValAttrNodeQName(ctxt, schema, + NULL, attr, &refNs, &ref); + xmlSchemaCheckReference(ctxt, schema, node, attr, refNs); + /* + * SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both" + */ + if (nameAttr != NULL) { + xmlSchemaPMutualExclAttrErr(ctxt, + XML_SCHEMAP_SRC_ELEMENT_2_1, NULL, nameAttr, "ref", "name"); + } + /* + * Check for illegal attributes. + */ + attr = node->properties; + while (attr != NULL) { + if (attr->ns == NULL) { + if (xmlStrEqual(attr->name, BAD_CAST "ref") || + xmlStrEqual(attr->name, BAD_CAST "name") || + xmlStrEqual(attr->name, BAD_CAST "id") || + xmlStrEqual(attr->name, BAD_CAST "maxOccurs") || + xmlStrEqual(attr->name, BAD_CAST "minOccurs")) + { + attr = attr->next; + continue; + } else { + /* SPEC (3.3.3 : 2.2) */ + xmlSchemaPCustomAttrErr(ctxt, + XML_SCHEMAP_SRC_ELEMENT_2_2, + NULL, NULL, attr, + "Only the attributes 'minOccurs', 'maxOccurs' and " + "'id' are allowed in addition to 'ref'"); + break; + } + } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { + xmlSchemaPIllegalAttrErr(ctxt, + XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); + } + attr = attr->next; + } + /* + * No children except expected. + */ + if (child != NULL) { + xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, + NULL, node, child, NULL, "(annotation?)"); + } + if ((min == 0) && (max == 0)) + goto return_null; + /* + * Create the reference item and attach it to the particle. + */ + refer = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_ELEMENT, + ref, refNs); + if (refer == NULL) + goto return_null; + particle->children = (xmlSchemaTreeItemPtr) refer; + particle->annot = annot; + /* + * Add the particle to pending components, since the reference + * need to be resolved. + */ + WXS_ADD_PENDING(ctxt, particle); + return ((xmlSchemaBasicItemPtr) particle); + } + /* + * The declaration part =============================================== + */ +declaration_part: + { + const xmlChar *ns = NULL, *fixed, *name, *attrValue; + xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL; + + if (xmlSchemaPValAttrNode(ctxt, NULL, nameAttr, + xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) + goto return_null; + /* + * Evaluate the target namespace. + */ + if (topLevel) { + ns = ctxt->targetNamespace; + } else { + attr = xmlSchemaGetPropNode(node, "form"); + if (attr != NULL) { + attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr); + if (xmlStrEqual(attrValue, BAD_CAST "qualified")) { + ns = ctxt->targetNamespace; + } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) { + xmlSchemaPSimpleTypeErr(ctxt, + XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, + NULL, (xmlNodePtr) attr, + NULL, "(qualified | unqualified)", + attrValue, NULL, NULL, NULL); + } + } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM) + ns = ctxt->targetNamespace; + } + decl = xmlSchemaAddElement(ctxt, name, ns, node, topLevel); + if (decl == NULL) { + goto return_null; + } + /* + * Check for illegal attributes. + */ + attr = node->properties; + while (attr != NULL) { + if (attr->ns == NULL) { + if ((!xmlStrEqual(attr->name, BAD_CAST "name")) && + (!xmlStrEqual(attr->name, BAD_CAST "type")) && + (!xmlStrEqual(attr->name, BAD_CAST "id")) && + (!xmlStrEqual(attr->name, BAD_CAST "default")) && + (!xmlStrEqual(attr->name, BAD_CAST "fixed")) && + (!xmlStrEqual(attr->name, BAD_CAST "block")) && + (!xmlStrEqual(attr->name, BAD_CAST "nillable"))) + { + if (topLevel == 0) { + if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) && + (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) && + (!xmlStrEqual(attr->name, BAD_CAST "form"))) + { + xmlSchemaPIllegalAttrErr(ctxt, + XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); + } + } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) && + (!xmlStrEqual(attr->name, BAD_CAST "abstract")) && + (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) { + + xmlSchemaPIllegalAttrErr(ctxt, + XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); + } + } + } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { + + xmlSchemaPIllegalAttrErr(ctxt, + XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); + } + attr = attr->next; + } + /* + * Extract/validate attributes. + */ + if (topLevel) { + /* + * Process top attributes of global element declarations here. + */ + decl->flags |= XML_SCHEMAS_ELEM_GLOBAL; + decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL; + xmlSchemaPValAttrQName(ctxt, schema, + NULL, node, "substitutionGroup", + &(decl->substGroupNs), &(decl->substGroup)); + if (xmlGetBooleanProp(ctxt, node, "abstract", 0)) + decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT; + /* + * Attribute "final". + */ + attr = xmlSchemaGetPropNode(node, "final"); + if (attr == NULL) { + if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION) + decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION; + if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION) + decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION; + } else { + attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr); + if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags), + -1, + XML_SCHEMAS_ELEM_FINAL_EXTENSION, + XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) { + xmlSchemaPSimpleTypeErr(ctxt, + XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, + NULL, (xmlNodePtr) attr, + NULL, "(#all | List of (extension | restriction))", + attrValue, NULL, NULL, NULL); + } + } + } + /* + * Attribute "block". + */ + attr = xmlSchemaGetPropNode(node, "block"); + if (attr == NULL) { + /* + * Apply default "block" values. + */ + if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION) + decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION; + if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION) + decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION; + if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION) + decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION; + } else { + attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr); + if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags), + -1, + XML_SCHEMAS_ELEM_BLOCK_EXTENSION, + XML_SCHEMAS_ELEM_BLOCK_RESTRICTION, + XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) { + xmlSchemaPSimpleTypeErr(ctxt, + XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, + NULL, (xmlNodePtr) attr, + NULL, "(#all | List of (extension | " + "restriction | substitution))", attrValue, + NULL, NULL, NULL); + } + } + if (xmlGetBooleanProp(ctxt, node, "nillable", 0)) + decl->flags |= XML_SCHEMAS_ELEM_NILLABLE; + + attr = xmlSchemaGetPropNode(node, "type"); + if (attr != NULL) { + xmlSchemaPValAttrNodeQName(ctxt, schema, + NULL, attr, + &(decl->namedTypeNs), &(decl->namedType)); + xmlSchemaCheckReference(ctxt, schema, node, + attr, decl->namedTypeNs); + } + decl->value = xmlSchemaGetProp(ctxt, node, "default"); + attr = xmlSchemaGetPropNode(node, "fixed"); + if (attr != NULL) { + fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr); + if (decl->value != NULL) { + /* + * 3.3.3 : 1 + * default and fixed must not both be present. + */ + xmlSchemaPMutualExclAttrErr(ctxt, + XML_SCHEMAP_SRC_ELEMENT_1, + NULL, attr, "default", "fixed"); + } else { + decl->flags |= XML_SCHEMAS_ELEM_FIXED; + decl->value = fixed; + } + } + /* + * And now for the children... + */ + if (IS_SCHEMA(child, "complexType")) { + /* + * 3.3.3 : 3 + * "type" and either or are mutually + * exclusive + */ + if (decl->namedType != NULL) { + xmlSchemaPContentErr(ctxt, + XML_SCHEMAP_SRC_ELEMENT_3, + NULL, node, child, + "The attribute 'type' and the child are " + "mutually exclusive", NULL); + } else + WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0); + child = child->next; + } else if (IS_SCHEMA(child, "simpleType")) { + /* + * 3.3.3 : 3 + * "type" and either or are + * mutually exclusive + */ + if (decl->namedType != NULL) { + xmlSchemaPContentErr(ctxt, + XML_SCHEMAP_SRC_ELEMENT_3, + NULL, node, child, + "The attribute 'type' and the child are " + "mutually exclusive", NULL); + } else + WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0); + child = child->next; + } + while ((IS_SCHEMA(child, "unique")) || + (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) { + if (IS_SCHEMA(child, "unique")) { + curIDC = xmlSchemaParseIDC(ctxt, schema, child, + XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace); + } else if (IS_SCHEMA(child, "key")) { + curIDC = xmlSchemaParseIDC(ctxt, schema, child, + XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace); + } else if (IS_SCHEMA(child, "keyref")) { + curIDC = xmlSchemaParseIDC(ctxt, schema, child, + XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace); + } + if (lastIDC != NULL) + lastIDC->next = curIDC; + else + decl->idcs = (void *) curIDC; + lastIDC = curIDC; + child = child->next; + } + if (child != NULL) { + xmlSchemaPContentErr(ctxt, + XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, + NULL, node, child, + NULL, "(annotation?, ((simpleType | complexType)?, " + "(unique | key | keyref)*))"); + } + decl->annot = annot; + } + /* + * NOTE: Element Declaration Representation OK 4. will be checked at a + * different layer. + */ + FREE_AND_NULL(des) + if (topLevel) + return ((xmlSchemaBasicItemPtr) decl); + else { + particle->children = (xmlSchemaTreeItemPtr) decl; + return ((xmlSchemaBasicItemPtr) particle); + } + +return_null: + FREE_AND_NULL(des); + if (annot != NULL) { + if (particle != NULL) + particle->annot = NULL; + if (decl != NULL) + decl->annot = NULL; + xmlSchemaFreeAnnot(annot); + } + return (NULL); +} + +/** + * xmlSchemaParseUnion: + * @ctxt: a schema validation context + * @schema: the schema being built + * @node: a subtree containing XML Schema informations + * + * parse a XML schema Union definition + * *WARNING* this interface is highly subject to change + * + * Returns -1 in case of internal error, 0 in case of success and a positive + * error code otherwise. + */ +static int +xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, + xmlNodePtr node) +{ + xmlSchemaTypePtr type; + xmlNodePtr child = NULL; + xmlAttrPtr attr; + const xmlChar *cur = NULL; + + if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) + return (-1); + /* Not a component, don't create it. */ + type = ctxt->ctxtType; + /* + * Mark the simple type as being of variety "union". + */ + type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION; + /* + * SPEC (Base type) (2) "If the or alternative is chosen, + * then the ·simple ur-type definition·." + */ + type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE); + /* + * Check for illegal attributes. + */ + attr = node->properties; + while (attr != NULL) { + if (attr->ns == NULL) { + if ((!xmlStrEqual(attr->name, BAD_CAST "id")) && + (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) { + xmlSchemaPIllegalAttrErr(ctxt, + XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); + } + } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { + xmlSchemaPIllegalAttrErr(ctxt, + XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); + } + attr = attr->next; + } + xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); + /* + * Attribute "memberTypes". This is a list of QNames. + * TODO: Check the value to contain anything. + */ + attr = xmlSchemaGetPropNode(node, "memberTypes"); + if (attr != NULL) { + const xmlChar *end; + xmlChar *tmp; + const xmlChar *localName, *nsName; + xmlSchemaTypeLinkPtr link, lastLink = NULL; + xmlSchemaQNameRefPtr ref; + + cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr); + type->base = cur; + do { + while (IS_BLANK_CH(*cur)) + cur++; + end = cur; + while ((*end != 0) && (!(IS_BLANK_CH(*end)))) + end++; + if (end == cur) + break; + tmp = xmlStrndup(cur, end - cur); + if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema, + NULL, attr, BAD_CAST tmp, &nsName, &localName) == 0) { + /* + * Create the member type link. + */ + link = (xmlSchemaTypeLinkPtr) + xmlMalloc(sizeof(xmlSchemaTypeLink)); + if (link == NULL) { + xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, " + "allocating a type link", NULL); + return (-1); + } + link->type = NULL; + link->next = NULL; + if (lastLink == NULL) + type->memberTypes = link; + else + lastLink->next = link; + lastLink = link; + /* + * Create a reference item. + */ + ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_SIMPLE, + localName, nsName); + if (ref == NULL) { + FREE_AND_NULL(tmp) + return (-1); + } + /* + * Assign the reference to the link, it will be resolved + * later during fixup of the union simple type. + */ + link->type = (xmlSchemaTypePtr) ref; + } + FREE_AND_NULL(tmp) + cur = end; + } while (*cur != 0); + + } + /* + * And now for the children... + */ + child = node->children; + if (IS_SCHEMA(child, "annotation")) { + /* + * Add the annotation to the simple type ancestor. + */ + xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type, + xmlSchemaParseAnnotation(ctxt, child, 1)); + child = child->next; + } + if (IS_SCHEMA(child, "simpleType")) { + xmlSchemaTypePtr subtype, last = NULL; + + /* + * Anchor the member types in the "subtypes" field of the + * simple type. + */ + while (IS_SCHEMA(child, "simpleType")) { + subtype = (xmlSchemaTypePtr) + xmlSchemaParseSimpleType(ctxt, schema, child, 0); + if (subtype != NULL) { + if (last == NULL) { + type->subtypes = subtype; + last = subtype; + } else { + last->next = subtype; + last = subtype; + } + last->next = NULL; + } + child = child->next; + } + } + if (child != NULL) { + xmlSchemaPContentErr(ctxt, + XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, + NULL, node, child, NULL, "(annotation?, simpleType*)"); + } + if ((attr == NULL) && (type->subtypes == NULL)) { + /* + * src-union-memberTypes-or-simpleTypes + * Either the memberTypes [attribute] of the element must + * be non-empty or there must be at least one simpleType [child]. + */ + xmlSchemaPCustomErr(ctxt, + XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES, + NULL, node, + "Either the attribute 'memberTypes' or " + "at least one child must be present", NULL); + } + return (0); +} + +/** + * xmlSchemaParseList: + * @ctxt: a schema validation context + * @schema: the schema being built + * @node: a subtree containing XML Schema informations + * + * parse a XML schema List definition + * *WARNING* this interface is highly subject to change + * + * Returns -1 in case of error, 0 if the declaration is improper and + * 1 in case of success. + */ +static xmlSchemaTypePtr +xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, + xmlNodePtr node) +{ + xmlSchemaTypePtr type; + xmlNodePtr child = NULL; + xmlAttrPtr attr; + + if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) + return (NULL); + /* Not a component, don't create it. */ + type = ctxt->ctxtType; + /* + * Mark the type as being of variety "list". + */ + type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST; + /* + * SPEC (Base type) (2) "If the or alternative is chosen, + * then the ·simple ur-type definition·." + */ + type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE); + /* + * Check for illegal attributes. + */ + attr = node->properties; + while (attr != NULL) { + if (attr->ns == NULL) { + if ((!xmlStrEqual(attr->name, BAD_CAST "id")) && + (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) { + xmlSchemaPIllegalAttrErr(ctxt, + XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); + } + } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { + xmlSchemaPIllegalAttrErr(ctxt, + XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); + } + attr = attr->next; + } + + xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); + + /* + * Attribute "itemType". NOTE that we will use the "ref" and "refNs" + * fields for holding the reference to the itemType. + * + * REVAMP TODO: Use the "base" and "baseNs" fields, since we will remove + * the "ref" fields. + */ + xmlSchemaPValAttrQName(ctxt, schema, NULL, + node, "itemType", &(type->baseNs), &(type->base)); + /* + * And now for the children... + */ + child = node->children; + if (IS_SCHEMA(child, "annotation")) { + xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type, + xmlSchemaParseAnnotation(ctxt, child, 1)); + child = child->next; + } + if (IS_SCHEMA(child, "simpleType")) { + /* + * src-list-itemType-or-simpleType + * Either the itemType [attribute] or the [child] of + * the element must be present, but not both. + */ + if (type->base != NULL) { + xmlSchemaPCustomErr(ctxt, + XML_SCHEMAP_SRC_SIMPLE_TYPE_1, + NULL, node, + "The attribute 'itemType' and the child " + "are mutually exclusive", NULL); + } else { + type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0); + } + child = child->next; + } else if (type->base == NULL) { + xmlSchemaPCustomErr(ctxt, + XML_SCHEMAP_SRC_SIMPLE_TYPE_1, + NULL, node, + "Either the attribute 'itemType' or the child " + "must be present", NULL); + } + if (child != NULL) { + xmlSchemaPContentErr(ctxt, + XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, + NULL, node, child, NULL, "(annotation?, simpleType?)"); + } + if ((type->base == NULL) && + (type->subtypes == NULL) && + (xmlSchemaGetPropNode(node, "itemType") == NULL)) { + xmlSchemaPCustomErr(ctxt, + XML_SCHEMAP_SRC_SIMPLE_TYPE_1, + NULL, node, + "Either the attribute 'itemType' or the child " + "must be present", NULL); + } + return (NULL); +} + +/** + * xmlSchemaParseSimpleType: + * @ctxt: a schema validation context + * @schema: the schema being built + * @node: a subtree containing XML Schema informations + * + * parse a XML schema Simple Type definition + * *WARNING* this interface is highly subject to change + * + * Returns -1 in case of error, 0 if the declaration is improper and + * 1 in case of success. + */ +static xmlSchemaTypePtr +xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, + xmlNodePtr node, int topLevel) +{ + xmlSchemaTypePtr type, oldCtxtType; + xmlNodePtr child = NULL; + const xmlChar *attrValue = NULL; + xmlAttrPtr attr; + int hasRestriction = 0; + + if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) + return (NULL); + + if (topLevel) { + attr = xmlSchemaGetPropNode(node, "name"); + if (attr == NULL) { + xmlSchemaPMissingAttrErr(ctxt, + XML_SCHEMAP_S4S_ATTR_MISSING, + NULL, node, + "name", NULL); + return (NULL); + } else { + if (xmlSchemaPValAttrNode(ctxt, + NULL, attr, + xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) + return (NULL); + /* + * Skip built-in types. + */ + if (ctxt->isS4S) { + xmlSchemaTypePtr biType; + + if (ctxt->isRedefine) { + /* + * REDEFINE: Disallow redefinition of built-in-types. + * TODO: It seems that the spec does not say anything + * about this case. + */ + xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE, + NULL, node, + "Redefinition of built-in simple types is not " + "supported", NULL); + return(NULL); + } + biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs); + if (biType != NULL) + return (biType); + } + } + } + /* + * TargetNamespace: + * SPEC "The ·actual value· of the targetNamespace [attribute] + * of the ancestor element information item if present, + * otherwise ·absent·. + */ + if (topLevel == 0) { +#ifdef ENABLE_NAMED_LOCALS + char buf[40]; +#endif + /* + * Parse as local simple type definition. + */ +#ifdef ENABLE_NAMED_LOCALS + snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1); + type = xmlSchemaAddType(ctxt, schema, + XML_SCHEMA_TYPE_SIMPLE, + xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1), + ctxt->targetNamespace, node, 0); +#else + type = xmlSchemaAddType(ctxt, schema, + XML_SCHEMA_TYPE_SIMPLE, + NULL, ctxt->targetNamespace, node, 0); +#endif + if (type == NULL) + return (NULL); + type->type = XML_SCHEMA_TYPE_SIMPLE; + type->contentType = XML_SCHEMA_CONTENT_SIMPLE; + /* + * Check for illegal attributes. + */ + attr = node->properties; + while (attr != NULL) { + if (attr->ns == NULL) { + if (!xmlStrEqual(attr->name, BAD_CAST "id")) { + xmlSchemaPIllegalAttrErr(ctxt, + XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); + } + } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { + xmlSchemaPIllegalAttrErr(ctxt, + XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); + } + attr = attr->next; + } + } else { + /* + * Parse as global simple type definition. + * + * Note that attrValue is the value of the attribute "name" here. + */ + type = xmlSchemaAddType(ctxt, schema, XML_SCHEMA_TYPE_SIMPLE, + attrValue, ctxt->targetNamespace, node, 1); + if (type == NULL) + return (NULL); + type->type = XML_SCHEMA_TYPE_SIMPLE; + type->contentType = XML_SCHEMA_CONTENT_SIMPLE; + type->flags |= XML_SCHEMAS_TYPE_GLOBAL; + /* + * Check for illegal attributes. + */ + attr = node->properties; + while (attr != NULL) { + if (attr->ns == NULL) { + if ((!xmlStrEqual(attr->name, BAD_CAST "id")) && + (!xmlStrEqual(attr->name, BAD_CAST "name")) && + (!xmlStrEqual(attr->name, BAD_CAST "final"))) { + xmlSchemaPIllegalAttrErr(ctxt, + XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); + } + } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { + xmlSchemaPIllegalAttrErr(ctxt, + XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); + } + attr = attr->next; + } + /* + * Attribute "final". + */ + attr = xmlSchemaGetPropNode(node, "final"); + if (attr == NULL) { + if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION) + type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION; + if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST) + type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST; + if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION) + type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION; + } else { + attrValue = xmlSchemaGetProp(ctxt, node, "final"); + if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags), + -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1, + XML_SCHEMAS_TYPE_FINAL_LIST, + XML_SCHEMAS_TYPE_FINAL_UNION) != 0) { + + xmlSchemaPSimpleTypeErr(ctxt, + XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, + WXS_BASIC_CAST type, (xmlNodePtr) attr, + NULL, "(#all | List of (list | union | restriction)", + attrValue, NULL, NULL, NULL); + } + } + } + type->targetNamespace = ctxt->targetNamespace; + xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); + /* + * And now for the children... + */ + oldCtxtType = ctxt->ctxtType; + + ctxt->ctxtType = type; + + child = node->children; + if (IS_SCHEMA(child, "annotation")) { + type->annot = xmlSchemaParseAnnotation(ctxt, child, 1); + child = child->next; + } + if (child == NULL) { + xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING, + NULL, node, child, NULL, + "(annotation?, (restriction | list | union))"); + } else if (IS_SCHEMA(child, "restriction")) { + xmlSchemaParseRestriction(ctxt, schema, child, + XML_SCHEMA_TYPE_SIMPLE); + hasRestriction = 1; + child = child->next; + } else if (IS_SCHEMA(child, "list")) { + xmlSchemaParseList(ctxt, schema, child); + child = child->next; + } else if (IS_SCHEMA(child, "union")) { + xmlSchemaParseUnion(ctxt, schema, child); + child = child->next; + } + if (child != NULL) { + xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, + NULL, node, child, NULL, + "(annotation?, (restriction | list | union))"); + } + /* + * REDEFINE: SPEC src-redefine (5) + * "Within the [children], each must have a + * among its [children] ... the ·actual value· of whose + * base [attribute] must be the same as the ·actual value· of its own + * name attribute plus target namespace;" + */ + if (topLevel && ctxt->isRedefine && (! hasRestriction)) { + xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE, + NULL, node, "This is a redefinition, thus the " + " must have a child", NULL); + } + + ctxt->ctxtType = oldCtxtType; + return (type); +} + +/** + * xmlSchemaParseModelGroupDefRef: + * @ctxt: the parser context + * @schema: the schema being built + * @node: the node + * + * Parses a reference to a model group definition. + * + * We will return a particle component with a qname-component or + * NULL in case of an error. + */ +static xmlSchemaTreeItemPtr +xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt, + xmlSchemaPtr schema, + xmlNodePtr node) +{ + xmlSchemaParticlePtr item; + xmlNodePtr child = NULL; + xmlAttrPtr attr; + const xmlChar *ref = NULL, *refNs = NULL; + int min, max; + + if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) + return (NULL); + + attr = xmlSchemaGetPropNode(node, "ref"); + if (attr == NULL) { + xmlSchemaPMissingAttrErr(ctxt, + XML_SCHEMAP_S4S_ATTR_MISSING, + NULL, node, "ref", NULL); + return (NULL); + } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL, + attr, &refNs, &ref) != 0) { + return (NULL); + } + xmlSchemaCheckReference(ctxt, schema, node, attr, refNs); + min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger"); + max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, + "(xs:nonNegativeInteger | unbounded)"); + /* + * Check for illegal attributes. + */ + attr = node->properties; + while (attr != NULL) { + if (attr->ns == NULL) { + if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) && + (!xmlStrEqual(attr->name, BAD_CAST "id")) && + (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) && + (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) { + xmlSchemaPIllegalAttrErr(ctxt, + XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); + } + } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { + xmlSchemaPIllegalAttrErr(ctxt, + XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); + } + attr = attr->next; + } + xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); + item = xmlSchemaAddParticle(ctxt, node, min, max); + if (item == NULL) + return (NULL); + /* + * Create a qname-reference and set as the term; it will be substituted + * for the model group after the reference has been resolved. + */ + item->children = (xmlSchemaTreeItemPtr) + xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_GROUP, ref, refNs); + xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max); + /* + * And now for the children... + */ + child = node->children; + /* TODO: Is annotation even allowed for a model group reference? */ + if (IS_SCHEMA(child, "annotation")) { + /* + * TODO: What to do exactly with the annotation? + */ + item->annot = xmlSchemaParseAnnotation(ctxt, child, 1); + child = child->next; + } + if (child != NULL) { + xmlSchemaPContentErr(ctxt, + XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, + NULL, node, child, NULL, + "(annotation?)"); + } + /* + * Corresponds to no component at all if minOccurs==maxOccurs==0. + */ + if ((min == 0) && (max == 0)) + return (NULL); + + return ((xmlSchemaTreeItemPtr) item); +} + +/** + * xmlSchemaParseModelGroupDefinition: + * @ctxt: a schema validation context + * @schema: the schema being built + * @node: a subtree containing XML Schema informations + * + * Parses a XML schema model group definition. + * + * Note that the contraint src-redefine (6.2) can't be applied until + * references have been resolved. So we will do this at the + * component fixup level. + * + * *WARNING* this interface is highly subject to change + * + * Returns -1 in case of error, 0 if the declaration is improper and + * 1 in case of success. + */ +static xmlSchemaModelGroupDefPtr +xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt, + xmlSchemaPtr schema, + xmlNodePtr node) +{ + xmlSchemaModelGroupDefPtr item; + xmlNodePtr child = NULL; + xmlAttrPtr attr; + const xmlChar *name; + + if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) + return (NULL); + + attr = xmlSchemaGetPropNode(node, "name"); + if (attr == NULL) { + xmlSchemaPMissingAttrErr(ctxt, + XML_SCHEMAP_S4S_ATTR_MISSING, + NULL, node, + "name", NULL); + return (NULL); + } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr, + xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) { + return (NULL); + } + item = xmlSchemaAddModelGroupDefinition(ctxt, schema, name, + ctxt->targetNamespace, node); + if (item == NULL) + return (NULL); + /* + * Check for illegal attributes. + */ + attr = node->properties; + while (attr != NULL) { + if (attr->ns == NULL) { + if ((!xmlStrEqual(attr->name, BAD_CAST "name")) && + (!xmlStrEqual(attr->name, BAD_CAST "id"))) { + xmlSchemaPIllegalAttrErr(ctxt, + XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); + } + } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { + xmlSchemaPIllegalAttrErr(ctxt, + XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); + } + attr = attr->next; + } + xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); + /* + * And now for the children... + */ + child = node->children; + if (IS_SCHEMA(child, "annotation")) { + item->annot = xmlSchemaParseAnnotation(ctxt, child, 1); + child = child->next; + } + if (IS_SCHEMA(child, "all")) { + item->children = xmlSchemaParseModelGroup(ctxt, schema, child, + XML_SCHEMA_TYPE_ALL, 0); + child = child->next; + } else if (IS_SCHEMA(child, "choice")) { + item->children = xmlSchemaParseModelGroup(ctxt, schema, child, + XML_SCHEMA_TYPE_CHOICE, 0); + child = child->next; + } else if (IS_SCHEMA(child, "sequence")) { + item->children = xmlSchemaParseModelGroup(ctxt, schema, child, + XML_SCHEMA_TYPE_SEQUENCE, 0); + child = child->next; + } + + + + if (child != NULL) { + xmlSchemaPContentErr(ctxt, + XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, + NULL, node, child, NULL, + "(annotation?, (all | choice | sequence)?)"); + } + return (item); +} + +/** + * xmlSchemaCleanupDoc: + * @ctxt: a schema validation context + * @node: the root of the document. + * + * removes unwanted nodes in a schemas document tree + */ +static void +xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root) +{ + xmlNodePtr delete, cur; + + if ((ctxt == NULL) || (root == NULL)) return; + + /* + * Remove all the blank text nodes + */ + delete = NULL; + cur = root; + while (cur != NULL) { + if (delete != NULL) { + xmlUnlinkNode(delete); + xmlFreeNode(delete); + delete = NULL; + } + if (cur->type == XML_TEXT_NODE) { + if (IS_BLANK_NODE(cur)) { + if (xmlNodeGetSpacePreserve(cur) != 1) { + delete = cur; + } + } + } else if ((cur->type != XML_ELEMENT_NODE) && + (cur->type != XML_CDATA_SECTION_NODE)) { + delete = cur; + goto skip_children; + } + + /* + * Skip to next node + */ + if (cur->children != NULL) { + if ((cur->children->type != XML_ENTITY_DECL) && + (cur->children->type != XML_ENTITY_REF_NODE) && + (cur->children->type != XML_ENTITY_NODE)) { + cur = cur->children; + continue; + } + } + skip_children: + if (cur->next != NULL) { + cur = cur->next; + continue; + } + + do { + cur = cur->parent; + if (cur == NULL) + break; + if (cur == root) { + cur = NULL; + break; + } + if (cur->next != NULL) { + cur = cur->next; + break; + } + } while (cur != NULL); + } + if (delete != NULL) { + xmlUnlinkNode(delete); + xmlFreeNode(delete); + delete = NULL; + } +} + + +static void +xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema) +{ + if (schema->flags & XML_SCHEMAS_QUALIF_ELEM) + schema->flags ^= XML_SCHEMAS_QUALIF_ELEM; + + if (schema->flags & XML_SCHEMAS_QUALIF_ATTR) + schema->flags ^= XML_SCHEMAS_QUALIF_ATTR; + + if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION) + schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION; + if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION) + schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION; + if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST) + schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST; + if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION) + schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION; + + if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION) + schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION; + if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION) + schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION; + if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION) + schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION; +} + +static int +xmlSchemaParseSchemaElement(xmlSchemaParserCtxtPtr ctxt, + xmlSchemaPtr schema, + xmlNodePtr node) +{ + xmlAttrPtr attr; + const xmlChar *val; + int res = 0, oldErrs = ctxt->nberrors; + + /* + * Those flags should be moved to the parser context flags, + * since they are not visible at the component level. I.e. + * they are used if processing schema *documents* only. + */ + res = xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); + HFAILURE; + + /* + * Since the version is of type xs:token, we won't bother to + * check it. + */ + /* REMOVED: + attr = xmlSchemaGetPropNode(node, "version"); + if (attr != NULL) { + res = xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr, + xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &val); + HFAILURE; + } + */ + attr = xmlSchemaGetPropNode(node, "targetNamespace"); + if (attr != NULL) { + res = xmlSchemaPValAttrNode(ctxt, NULL, attr, + xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL); + HFAILURE; + if (res != 0) { + ctxt->stop = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE; + goto exit; + } + } + attr = xmlSchemaGetPropNode(node, "elementFormDefault"); + if (attr != NULL) { + val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr); + res = xmlSchemaPValAttrFormDefault(val, &schema->flags, + XML_SCHEMAS_QUALIF_ELEM); + HFAILURE; + if (res != 0) { + xmlSchemaPSimpleTypeErr(ctxt, + XML_SCHEMAP_ELEMFORMDEFAULT_VALUE, + NULL, (xmlNodePtr) attr, NULL, + "(qualified | unqualified)", val, NULL, NULL, NULL); + } + } + attr = xmlSchemaGetPropNode(node, "attributeFormDefault"); + if (attr != NULL) { + val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr); + res = xmlSchemaPValAttrFormDefault(val, &schema->flags, + XML_SCHEMAS_QUALIF_ATTR); + HFAILURE; + if (res != 0) { + xmlSchemaPSimpleTypeErr(ctxt, + XML_SCHEMAP_ATTRFORMDEFAULT_VALUE, + NULL, (xmlNodePtr) attr, NULL, + "(qualified | unqualified)", val, NULL, NULL, NULL); + } + } + attr = xmlSchemaGetPropNode(node, "finalDefault"); + if (attr != NULL) { + val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr); + res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1, + XML_SCHEMAS_FINAL_DEFAULT_EXTENSION, + XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION, + -1, + XML_SCHEMAS_FINAL_DEFAULT_LIST, + XML_SCHEMAS_FINAL_DEFAULT_UNION); + HFAILURE; + if (res != 0) { + xmlSchemaPSimpleTypeErr(ctxt, + XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, + NULL, (xmlNodePtr) attr, NULL, + "(#all | List of (extension | restriction | list | union))", + val, NULL, NULL, NULL); + } + } + attr = xmlSchemaGetPropNode(node, "blockDefault"); + if (attr != NULL) { + val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr); + res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1, + XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION, + XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION, + XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1); + HFAILURE; + if (res != 0) { + xmlSchemaPSimpleTypeErr(ctxt, + XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, + NULL, (xmlNodePtr) attr, NULL, + "(#all | List of (extension | restriction | substitution))", + val, NULL, NULL, NULL); + } + } + +exit: + if (oldErrs != ctxt->nberrors) + res = ctxt->err; + return(res); +exit_failure: + return(-1); +} + +/** + * xmlSchemaParseSchemaTopLevel: + * @ctxt: a schema validation context + * @schema: the schemas + * @nodes: the list of top level nodes + * + * Returns the internal XML Schema structure built from the resource or + * NULL in case of error + */ +static int +xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt, + xmlSchemaPtr schema, xmlNodePtr nodes) +{ + xmlNodePtr child; + xmlSchemaAnnotPtr annot; + int res = 0, oldErrs, tmpOldErrs; + + if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL)) + return(-1); + + oldErrs = ctxt->nberrors; + child = nodes; + while ((IS_SCHEMA(child, "include")) || + (IS_SCHEMA(child, "import")) || + (IS_SCHEMA(child, "redefine")) || + (IS_SCHEMA(child, "annotation"))) { + if (IS_SCHEMA(child, "annotation")) { + annot = xmlSchemaParseAnnotation(ctxt, child, 1); + if (schema->annot == NULL) + schema->annot = annot; + else + xmlSchemaFreeAnnot(annot); + } else if (IS_SCHEMA(child, "import")) { + tmpOldErrs = ctxt->nberrors; + res = xmlSchemaParseImport(ctxt, schema, child); + HFAILURE; + HSTOP(ctxt); + if (tmpOldErrs != ctxt->nberrors) + goto exit; + } else if (IS_SCHEMA(child, "include")) { + tmpOldErrs = ctxt->nberrors; + res = xmlSchemaParseInclude(ctxt, schema, child); + HFAILURE; + HSTOP(ctxt); + if (tmpOldErrs != ctxt->nberrors) + goto exit; + } else if (IS_SCHEMA(child, "redefine")) { + tmpOldErrs = ctxt->nberrors; + res = xmlSchemaParseRedefine(ctxt, schema, child); + HFAILURE; + HSTOP(ctxt); + if (tmpOldErrs != ctxt->nberrors) + goto exit; + } + child = child->next; + } + /* + * URGENT TODO: Change the functions to return int results. + * We need especially to catch internal errors. + */ + while (child != NULL) { + if (IS_SCHEMA(child, "complexType")) { + xmlSchemaParseComplexType(ctxt, schema, child, 1); + child = child->next; + } else if (IS_SCHEMA(child, "simpleType")) { + xmlSchemaParseSimpleType(ctxt, schema, child, 1); + child = child->next; + } else if (IS_SCHEMA(child, "element")) { + xmlSchemaParseElement(ctxt, schema, child, NULL, 1); + child = child->next; + } else if (IS_SCHEMA(child, "attribute")) { + xmlSchemaParseGlobalAttribute(ctxt, schema, child); + child = child->next; + } else if (IS_SCHEMA(child, "attributeGroup")) { + xmlSchemaParseAttributeGroupDefinition(ctxt, schema, child); + child = child->next; + } else if (IS_SCHEMA(child, "group")) { + xmlSchemaParseModelGroupDefinition(ctxt, schema, child); + child = child->next; + } else if (IS_SCHEMA(child, "notation")) { + xmlSchemaParseNotation(ctxt, schema, child); + child = child->next; + } else { + xmlSchemaPContentErr(ctxt, + XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, + NULL, child->parent, child, + NULL, "((include | import | redefine | annotation)*, " + "(((simpleType | complexType | group | attributeGroup) " + "| element | attribute | notation), annotation*)*)"); + child = child->next; + } + while (IS_SCHEMA(child, "annotation")) { + /* + * TODO: We should add all annotations. + */ + annot = xmlSchemaParseAnnotation(ctxt, child, 1); + if (schema->annot == NULL) + schema->annot = annot; + else + xmlSchemaFreeAnnot(annot); + child = child->next; + } + } +exit: + ctxt->ctxtType = NULL; + if (oldErrs != ctxt->nberrors) + res = ctxt->err; + return(res); +exit_failure: + return(-1); +} + +static xmlSchemaSchemaRelationPtr +xmlSchemaSchemaRelationCreate(void) +{ + xmlSchemaSchemaRelationPtr ret; + + ret = (xmlSchemaSchemaRelationPtr) + xmlMalloc(sizeof(xmlSchemaSchemaRelation)); + if (ret == NULL) { + xmlSchemaPErrMemory(NULL, "allocating schema relation", NULL); + return(NULL); + } + memset(ret, 0, sizeof(xmlSchemaSchemaRelation)); + return(ret); +} + +#if 0 +static void +xmlSchemaSchemaRelationFree(xmlSchemaSchemaRelationPtr rel) +{ + xmlFree(rel); +} +#endif + +static void +xmlSchemaRedefListFree(xmlSchemaRedefPtr redef) +{ + xmlSchemaRedefPtr prev; + + while (redef != NULL) { + prev = redef; + redef = redef->next; + xmlFree(prev); + } +} + +static void +xmlSchemaConstructionCtxtFree(xmlSchemaConstructionCtxtPtr con) +{ + /* + * After the construction context has been freed, there will be + * no schema graph available any more. Only the schema buckets + * will stay alive, which are put into the "schemasImports" and + * "includes" slots of the xmlSchema. + */ + if (con->buckets != NULL) + xmlSchemaItemListFree(con->buckets); + if (con->pending != NULL) + xmlSchemaItemListFree(con->pending); + if (con->substGroups != NULL) + xmlHashFree(con->substGroups, + (xmlHashDeallocator) xmlSchemaSubstGroupFree); + if (con->redefs != NULL) + xmlSchemaRedefListFree(con->redefs); + if (con->dict != NULL) + xmlDictFree(con->dict); + xmlFree(con); +} + +static xmlSchemaConstructionCtxtPtr +xmlSchemaConstructionCtxtCreate(xmlDictPtr dict) +{ + xmlSchemaConstructionCtxtPtr ret; + + ret = (xmlSchemaConstructionCtxtPtr) + xmlMalloc(sizeof(xmlSchemaConstructionCtxt)); + if (ret == NULL) { + xmlSchemaPErrMemory(NULL, + "allocating schema construction context", NULL); + return (NULL); + } + memset(ret, 0, sizeof(xmlSchemaConstructionCtxt)); + + ret->buckets = xmlSchemaItemListCreate(); + if (ret->buckets == NULL) { + xmlSchemaPErrMemory(NULL, + "allocating list of schema buckets", NULL); + xmlFree(ret); + return (NULL); + } + ret->pending = xmlSchemaItemListCreate(); + if (ret->pending == NULL) { + xmlSchemaPErrMemory(NULL, + "allocating list of pending global components", NULL); + xmlSchemaConstructionCtxtFree(ret); + return (NULL); + } + ret->dict = dict; + xmlDictReference(dict); + return(ret); +} + +static xmlSchemaParserCtxtPtr +xmlSchemaParserCtxtCreate(void) +{ + xmlSchemaParserCtxtPtr ret; + + ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt)); + if (ret == NULL) { + xmlSchemaPErrMemory(NULL, "allocating schema parser context", + NULL); + return (NULL); + } + memset(ret, 0, sizeof(xmlSchemaParserCtxt)); + ret->type = XML_SCHEMA_CTXT_PARSER; + ret->attrProhibs = xmlSchemaItemListCreate(); + if (ret->attrProhibs == NULL) { + xmlFree(ret); + return(NULL); + } + return(ret); +} + +/** + * xmlSchemaNewParserCtxtUseDict: + * @URL: the location of the schema + * @dict: the dictionary to be used + * + * Create an XML Schemas parse context for that file/resource expected + * to contain an XML Schemas file. + * + * Returns the parser context or NULL in case of error + */ +static xmlSchemaParserCtxtPtr +xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict) +{ + xmlSchemaParserCtxtPtr ret; + + ret = xmlSchemaParserCtxtCreate(); + if (ret == NULL) + return (NULL); + ret->dict = dict; + xmlDictReference(dict); + if (URL != NULL) + ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1); + return (ret); +} + +static int +xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt) +{ + if (vctxt->pctxt == NULL) { + if (vctxt->schema != NULL) + vctxt->pctxt = + xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict); + else + vctxt->pctxt = xmlSchemaNewParserCtxt("*"); + if (vctxt->pctxt == NULL) { + VERROR_INT("xmlSchemaCreatePCtxtOnVCtxt", + "failed to create a temp. parser context"); + return (-1); + } + /* TODO: Pass user data. */ + xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error, + vctxt->warning, vctxt->errCtxt); + xmlSchemaSetParserStructuredErrors(vctxt->pctxt, vctxt->serror, + vctxt->errCtxt); + } + return (0); +} + +/** + * xmlSchemaGetSchemaBucket: + * @pctxt: the schema parser context + * @schemaLocation: the URI of the schema document + * + * Returns a schema bucket if it was already parsed. + * + * Returns a schema bucket if it was already parsed from + * @schemaLocation, NULL otherwise. + */ +static xmlSchemaBucketPtr +xmlSchemaGetSchemaBucket(xmlSchemaParserCtxtPtr pctxt, + const xmlChar *schemaLocation) +{ + xmlSchemaBucketPtr cur; + xmlSchemaItemListPtr list; + + list = pctxt->constructor->buckets; + if (list->nbItems == 0) + return(NULL); + else { + int i; + for (i = 0; i < list->nbItems; i++) { + cur = (xmlSchemaBucketPtr) list->items[i]; + /* Pointer comparison! */ + if (cur->schemaLocation == schemaLocation) + return(cur); + } + } + return(NULL); +} + +static xmlSchemaBucketPtr +xmlSchemaGetChameleonSchemaBucket(xmlSchemaParserCtxtPtr pctxt, + const xmlChar *schemaLocation, + const xmlChar *targetNamespace) +{ + xmlSchemaBucketPtr cur; + xmlSchemaItemListPtr list; + + list = pctxt->constructor->buckets; + if (list->nbItems == 0) + return(NULL); + else { + int i; + for (i = 0; i < list->nbItems; i++) { + cur = (xmlSchemaBucketPtr) list->items[i]; + /* Pointer comparison! */ + if ((cur->origTargetNamespace == NULL) && + (cur->schemaLocation == schemaLocation) && + (cur->targetNamespace == targetNamespace)) + return(cur); + } + } + return(NULL); +} + + +#define IS_BAD_SCHEMA_DOC(b) \ + (((b)->doc == NULL) && ((b)->schemaLocation != NULL)) + +static xmlSchemaBucketPtr +xmlSchemaGetSchemaBucketByTNS(xmlSchemaParserCtxtPtr pctxt, + const xmlChar *targetNamespace, + int imported) +{ + xmlSchemaBucketPtr cur; + xmlSchemaItemListPtr list; + + list = pctxt->constructor->buckets; + if (list->nbItems == 0) + return(NULL); + else { + int i; + for (i = 0; i < list->nbItems; i++) { + cur = (xmlSchemaBucketPtr) list->items[i]; + if ((! IS_BAD_SCHEMA_DOC(cur)) && + (cur->origTargetNamespace == targetNamespace) && + ((imported && cur->imported) || + ((!imported) && (!cur->imported)))) + return(cur); + } + } + return(NULL); +} + +static int +xmlSchemaParseNewDocWithContext(xmlSchemaParserCtxtPtr pctxt, + xmlSchemaPtr schema, + xmlSchemaBucketPtr bucket) +{ + int oldFlags; + xmlDocPtr oldDoc; + xmlNodePtr node; + int ret, oldErrs; + xmlSchemaBucketPtr oldbucket = pctxt->constructor->bucket; + + /* + * Save old values; reset the *main* schema. + * URGENT TODO: This is not good; move the per-document information + * to the parser. Get rid of passing the main schema to the + * parsing functions. + */ + oldFlags = schema->flags; + oldDoc = schema->doc; + if (schema->flags != 0) + xmlSchemaClearSchemaDefaults(schema); + schema->doc = bucket->doc; + pctxt->schema = schema; + /* + * Keep the current target namespace on the parser *not* on the + * main schema. + */ + pctxt->targetNamespace = bucket->targetNamespace; + WXS_CONSTRUCTOR(pctxt)->bucket = bucket; + + if ((bucket->targetNamespace != NULL) && + xmlStrEqual(bucket->targetNamespace, xmlSchemaNs)) { + /* + * We are parsing the schema for schemas! + */ + pctxt->isS4S = 1; + } + /* Mark it as parsed, even if parsing fails. */ + bucket->parsed++; + /* Compile the schema doc. */ + node = xmlDocGetRootElement(bucket->doc); + ret = xmlSchemaParseSchemaElement(pctxt, schema, node); + if (ret != 0) + goto exit; + /* An empty schema; just get out. */ + if (node->children == NULL) + goto exit; + oldErrs = pctxt->nberrors; + ret = xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children); + if (ret != 0) + goto exit; + /* + * TODO: Not nice, but I'm not 100% sure we will get always an error + * as a result of the obove functions; so better rely on pctxt->err + * as well. + */ + if ((ret == 0) && (oldErrs != pctxt->nberrors)) { + ret = pctxt->err; + goto exit; + } + +exit: + WXS_CONSTRUCTOR(pctxt)->bucket = oldbucket; + /* Restore schema values. */ + schema->doc = oldDoc; + schema->flags = oldFlags; + return(ret); +} + +static int +xmlSchemaParseNewDoc(xmlSchemaParserCtxtPtr pctxt, + xmlSchemaPtr schema, + xmlSchemaBucketPtr bucket) +{ + xmlSchemaParserCtxtPtr newpctxt; + int res = 0; + + if (bucket == NULL) + return(0); + if (bucket->parsed) { + PERROR_INT("xmlSchemaParseNewDoc", + "reparsing a schema doc"); + return(-1); + } + if (bucket->doc == NULL) { + PERROR_INT("xmlSchemaParseNewDoc", + "parsing a schema doc, but there's no doc"); + return(-1); + } + if (pctxt->constructor == NULL) { + PERROR_INT("xmlSchemaParseNewDoc", + "no constructor"); + return(-1); + } + /* Create and init the temporary parser context. */ + newpctxt = xmlSchemaNewParserCtxtUseDict( + (const char *) bucket->schemaLocation, pctxt->dict); + if (newpctxt == NULL) + return(-1); + newpctxt->constructor = pctxt->constructor; + /* + * TODO: Can we avoid that the parser knows about the main schema? + * It would be better if he knows about the current schema bucket + * only. + */ + newpctxt->schema = schema; + xmlSchemaSetParserErrors(newpctxt, pctxt->error, pctxt->warning, + pctxt->errCtxt); + xmlSchemaSetParserStructuredErrors(newpctxt, pctxt->serror, + pctxt->errCtxt); + newpctxt->counter = pctxt->counter; + + + res = xmlSchemaParseNewDocWithContext(newpctxt, schema, bucket); + + /* Channel back errors and cleanup the temporary parser context. */ + if (res != 0) + pctxt->err = res; + pctxt->nberrors += newpctxt->nberrors; + pctxt->counter = newpctxt->counter; + newpctxt->constructor = NULL; + /* Free the parser context. */ + xmlSchemaFreeParserCtxt(newpctxt); + return(res); +} + +static void +xmlSchemaSchemaRelationAddChild(xmlSchemaBucketPtr bucket, + xmlSchemaSchemaRelationPtr rel) +{ + xmlSchemaSchemaRelationPtr cur = bucket->relations; + + if (cur == NULL) { + bucket->relations = rel; + return; + } + while (cur->next != NULL) + cur = cur->next; + cur->next = rel; +} + + +static const xmlChar * +xmlSchemaBuildAbsoluteURI(xmlDictPtr dict, const xmlChar* location, + xmlNodePtr ctxtNode) +{ + /* + * Build an absolue location URI. + */ + if (location != NULL) { + if (ctxtNode == NULL) + return(location); + else { + xmlChar *base, *URI; + const xmlChar *ret = NULL; + + base = xmlNodeGetBase(ctxtNode->doc, ctxtNode); + if (base == NULL) { + URI = xmlBuildURI(location, ctxtNode->doc->URL); + } else { + URI = xmlBuildURI(location, base); + xmlFree(base); + } + if (URI != NULL) { + ret = xmlDictLookup(dict, URI, -1); + xmlFree(URI); + return(ret); + } + } + } + return(NULL); +} + + + +/** + * xmlSchemaAddSchemaDoc: + * @pctxt: a schema validation context + * @schema: the schema being built + * @node: a subtree containing XML Schema informations + * + * Parse an included (and to-be-redefined) XML schema document. + * + * Returns 0 on success, a positive error code on errors and + * -1 in case of an internal or API error. + */ + +static int +xmlSchemaAddSchemaDoc(xmlSchemaParserCtxtPtr pctxt, + int type, /* import or include or redefine */ + const xmlChar *schemaLocation, + xmlDocPtr schemaDoc, + const char *schemaBuffer, + int schemaBufferLen, + xmlNodePtr invokingNode, + const xmlChar *sourceTargetNamespace, + const xmlChar *importNamespace, + xmlSchemaBucketPtr *bucket) +{ + const xmlChar *targetNamespace = NULL; + xmlSchemaSchemaRelationPtr relation = NULL; + xmlDocPtr doc = NULL; + int res = 0, err = 0, located = 0, preserveDoc = 0; + xmlSchemaBucketPtr bkt = NULL; + + if (bucket != NULL) + *bucket = NULL; + + switch (type) { + case XML_SCHEMA_SCHEMA_IMPORT: + case XML_SCHEMA_SCHEMA_MAIN: + err = XML_SCHEMAP_SRC_IMPORT; + break; + case XML_SCHEMA_SCHEMA_INCLUDE: + err = XML_SCHEMAP_SRC_INCLUDE; + break; + case XML_SCHEMA_SCHEMA_REDEFINE: + err = XML_SCHEMAP_SRC_REDEFINE; + break; + } + + + /* Special handling for the main schema: + * skip the location and relation logic and just parse the doc. + * We need just a bucket to be returned in this case. + */ + if ((type == XML_SCHEMA_SCHEMA_MAIN) || (! WXS_HAS_BUCKETS(pctxt))) + goto doc_load; + + /* Note that we expect the location to be an absulute URI. */ + if (schemaLocation != NULL) { + bkt = xmlSchemaGetSchemaBucket(pctxt, schemaLocation); + if ((bkt != NULL) && + (pctxt->constructor->bucket == bkt)) { + /* Report self-imports/inclusions/redefinitions. */ + + xmlSchemaCustomErr(ACTXT_CAST pctxt, err, + invokingNode, NULL, + "The schema must not import/include/redefine itself", + NULL, NULL); + goto exit; + } + } + /* + * Create a relation for the graph of schemas. + */ + relation = xmlSchemaSchemaRelationCreate(); + if (relation == NULL) + return(-1); + xmlSchemaSchemaRelationAddChild(pctxt->constructor->bucket, + relation); + relation->type = type; + + /* + * Save the namespace import information. + */ + if (WXS_IS_BUCKET_IMPMAIN(type)) { + relation->importNamespace = importNamespace; + if (schemaLocation == NULL) { + /* + * No location; this is just an import of the namespace. + * Note that we don't assign a bucket to the relation + * in this case. + */ + goto exit; + } + targetNamespace = importNamespace; + } + + /* Did we already fetch the doc? */ + if (bkt != NULL) { + /* TODO: The following nasty cases will produce an error. */ + if ((WXS_IS_BUCKET_IMPMAIN(type)) && (! bkt->imported)) { + /* We included/redefined and then try to import a schema. */ + xmlSchemaCustomErr(ACTXT_CAST pctxt, err, + invokingNode, NULL, + "The schema document '%s' cannot be imported, since " + "it was already included or redefined", + schemaLocation, NULL); + goto exit; + } else if ((! WXS_IS_BUCKET_IMPMAIN(type)) && (bkt->imported)) { + /* We imported and then try to include/redefine a schema. */ + xmlSchemaCustomErr(ACTXT_CAST pctxt, err, + invokingNode, NULL, + "The schema document '%s' cannot be included or " + "redefined, since it was already imported", + schemaLocation, NULL); + goto exit; + } + } + + if (WXS_IS_BUCKET_IMPMAIN(type)) { + /* + * Given that the schemaLocation [attribute] is only a hint, it is open + * to applications to ignore all but the first for a given + * namespace, regardless of the ·actual value· of schemaLocation, but + * such a strategy risks missing useful information when new + * schemaLocations are offered. + * + * We will use the first that comes with a location. + * Further s *with* a location, will result in an error. + * TODO: Better would be to just report a warning here, but + * we'll try it this way until someone complains. + * + * Schema Document Location Strategy: + * 3 Based on the namespace name, identify an existing schema document, + * either as a resource which is an XML document or a element + * information item, in some local schema repository; + * 5 Attempt to resolve the namespace name to locate such a resource. + * + * NOTE: (3) and (5) are not supported. + */ + if (bkt != NULL) { + relation->bucket = bkt; + goto exit; + } + bkt = xmlSchemaGetSchemaBucketByTNS(pctxt, + importNamespace, 1); + + if (bkt != NULL) { + relation->bucket = bkt; + if (bkt->schemaLocation == NULL) { + /* First given location of the schema; load the doc. */ + bkt->schemaLocation = schemaLocation; + } else { + if (!xmlStrEqual(schemaLocation, + bkt->schemaLocation)) { + /* + * Additional location given; just skip it. + * URGENT TODO: We should report a warning here. + * res = XML_SCHEMAP_SRC_IMPORT; + */ + xmlSchemaCustomWarning(ACTXT_CAST pctxt, + XML_SCHEMAP_WARN_SKIP_SCHEMA, + invokingNode, NULL, + "Skipping import of schema located at '%s' for the " + "namespace '%s', since this namespace was already " + "imported with the schema located at '%s'", + schemaLocation, importNamespace, bkt->schemaLocation); + } + goto exit; + } + } + /* + * No bucket + first location: load the doc and create a + * bucket. + */ + } else { + /* and */ + if (bkt != NULL) { + + if ((bkt->origTargetNamespace == NULL) && + (bkt->targetNamespace != sourceTargetNamespace)) { + xmlSchemaBucketPtr chamel; + + /* + * Chameleon include/redefine: skip loading only if it was + * aleady build for the targetNamespace of the including + * schema. + */ + /* + * URGENT TODO: If the schema is a chameleon-include then copy + * the components into the including schema and modify the + * targetNamespace of those components, do nothing otherwise. + * NOTE: This is currently worked-around by compiling the + * chameleon for every destinct including targetNamespace; thus + * not performant at the moment. + * TODO: Check when the namespace in wildcards for chameleons + * needs to be converted: before we built wildcard intersections + * or after. + * Answer: after! + */ + chamel = xmlSchemaGetChameleonSchemaBucket(pctxt, + schemaLocation, sourceTargetNamespace); + if (chamel != NULL) { + /* A fitting chameleon was already parsed; NOP. */ + relation->bucket = chamel; + goto exit; + } + /* + * We need to parse the chameleon again for a different + * targetNamespace. + * CHAMELEON TODO: Optimize this by only parsing the + * chameleon once, and then copying the components to + * the new targetNamespace. + */ + bkt = NULL; + } else { + relation->bucket = bkt; + goto exit; + } + } + } + if ((bkt != NULL) && (bkt->doc != NULL)) { + PERROR_INT("xmlSchemaAddSchemaDoc", + "trying to load a schema doc, but a doc is already " + "assigned to the schema bucket"); + goto exit_failure; + } + +doc_load: + /* + * Load the document. + */ + if (schemaDoc != NULL) { + doc = schemaDoc; + /* Don' free this one, since it was provided by the caller. */ + preserveDoc = 1; + /* TODO: Does the context or the doc hold the location? */ + if (schemaDoc->URL != NULL) + schemaLocation = xmlDictLookup(pctxt->dict, + schemaDoc->URL, -1); + + } else if ((schemaLocation != NULL) || (schemaBuffer != NULL)) { + xmlParserCtxtPtr parserCtxt; + + parserCtxt = xmlNewParserCtxt(); + if (parserCtxt == NULL) { + xmlSchemaPErrMemory(NULL, "xmlSchemaGetDoc, " + "allocating a parser context", NULL); + goto exit_failure; + } + if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) { + /* + * TODO: Do we have to burden the schema parser dict with all + * the content of the schema doc? + */ + xmlDictFree(parserCtxt->dict); + parserCtxt->dict = pctxt->dict; + xmlDictReference(parserCtxt->dict); + } + if (schemaLocation != NULL) { + /* Parse from file. */ + doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation, + NULL, SCHEMAS_PARSE_OPTIONS); + } else if (schemaBuffer != NULL) { + /* Parse from memory buffer. */ + doc = xmlCtxtReadMemory(parserCtxt, schemaBuffer, schemaBufferLen, + NULL, NULL, SCHEMAS_PARSE_OPTIONS); + schemaLocation = xmlStrdup(BAD_CAST "in_memory_buffer"); + if (doc != NULL) + doc->URL = schemaLocation; + } + /* + * For : + * 2.1 The referent is (a fragment of) a resource which is an + * XML document (see clause 1.1), which in turn corresponds to + * a element information item in a well-formed information + * set, which in turn corresponds to a valid schema. + * TODO: (2.1) fragments of XML documents are not supported. + * + * 2.2 The referent is a element information item in + * a well-formed information set, which in turn corresponds + * to a valid schema. + * TODO: (2.2) is not supported. + */ + if (doc == NULL) { + xmlErrorPtr lerr; + lerr = xmlGetLastError(); + /* + * Check if this a parser error, or if the document could + * just not be located. + * TODO: Try to find specific error codes to react only on + * localisation failures. + */ + if ((lerr == NULL) || (lerr->domain != XML_FROM_IO)) { + /* + * We assume a parser error here. + */ + located = 1; + /* TODO: Error code ?? */ + res = XML_SCHEMAP_SRC_IMPORT_2_1; + xmlSchemaCustomErr(ACTXT_CAST pctxt, res, + invokingNode, NULL, + "Failed to parse the XML resource '%s'", + schemaLocation, NULL); + } + } + xmlFreeParserCtxt(parserCtxt); + if ((doc == NULL) && located) + goto exit_error; + } else { + xmlSchemaPErr(pctxt, NULL, + XML_SCHEMAP_NOTHING_TO_PARSE, + "No information for parsing was provided with the " + "given schema parser context.\n", + NULL, NULL); + goto exit_failure; + } + /* + * Preprocess the document. + */ + if (doc != NULL) { + xmlNodePtr docElem = NULL; + + located = 1; + docElem = xmlDocGetRootElement(doc); + if (docElem == NULL) { + xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOROOT, + invokingNode, NULL, + "The document '%s' has no document element", + schemaLocation, NULL); + goto exit_error; + } + /* + * Remove all the blank text nodes. + */ + xmlSchemaCleanupDoc(pctxt, docElem); + /* + * Check the schema's top level element. + */ + if (!IS_SCHEMA(docElem, "schema")) { + xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOT_SCHEMA, + invokingNode, NULL, + "The XML document '%s' is not a schema document", + schemaLocation, NULL); + goto exit_error; + } + /* + * Note that we don't apply a type check for the + * targetNamespace value here. + */ + targetNamespace = xmlSchemaGetProp(pctxt, docElem, + "targetNamespace"); + } + +/* after_doc_loading: */ + if ((bkt == NULL) && located) { + /* Only create a bucket if the schema was located. */ + bkt = xmlSchemaBucketCreate(pctxt, type, + targetNamespace); + if (bkt == NULL) + goto exit_failure; + } + if (bkt != NULL) { + bkt->schemaLocation = schemaLocation; + bkt->located = located; + if (doc != NULL) { + bkt->doc = doc; + bkt->targetNamespace = targetNamespace; + bkt->origTargetNamespace = targetNamespace; + if (preserveDoc) + bkt->preserveDoc = 1; + } + if (WXS_IS_BUCKET_IMPMAIN(type)) + bkt->imported++; + /* + * Add it to the graph of schemas. + */ + if (relation != NULL) + relation->bucket = bkt; + } + +exit: + /* + * Return the bucket explicitely; this is needed for the + * main schema. + */ + if (bucket != NULL) + *bucket = bkt; + return (0); + +exit_error: + if ((doc != NULL) && (! preserveDoc)) { + xmlFreeDoc(doc); + if (bkt != NULL) + bkt->doc = NULL; + } + return(pctxt->err); + +exit_failure: + if ((doc != NULL) && (! preserveDoc)) { + xmlFreeDoc(doc); + if (bkt != NULL) + bkt->doc = NULL; + } + return (-1); +} + +/** + * xmlSchemaParseImport: + * @ctxt: a schema validation context + * @schema: the schema being built + * @node: a subtree containing XML Schema informations + * + * parse a XML schema Import definition + * *WARNING* this interface is highly subject to change + * + * Returns 0 in case of success, a positive error code if + * not valid and -1 in case of an internal error. + */ +static int +xmlSchemaParseImport(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema, + xmlNodePtr node) +{ + xmlNodePtr child; + const xmlChar *namespaceName = NULL, *schemaLocation = NULL; + const xmlChar *thisTargetNamespace; + xmlAttrPtr attr; + int ret = 0; + xmlSchemaBucketPtr bucket = NULL; + + if ((pctxt == NULL) || (schema == NULL) || (node == NULL)) + return (-1); + + /* + * Check for illegal attributes. + */ + attr = node->properties; + while (attr != NULL) { + if (attr->ns == NULL) { + if ((!xmlStrEqual(attr->name, BAD_CAST "id")) && + (!xmlStrEqual(attr->name, BAD_CAST "namespace")) && + (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) { + xmlSchemaPIllegalAttrErr(pctxt, + XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); + } + } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { + xmlSchemaPIllegalAttrErr(pctxt, + XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); + } + attr = attr->next; + } + /* + * Extract and validate attributes. + */ + if (xmlSchemaPValAttr(pctxt, NULL, node, + "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), + &namespaceName) != 0) { + xmlSchemaPSimpleTypeErr(pctxt, + XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, + NULL, node, + xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), + NULL, namespaceName, NULL, NULL, NULL); + return (pctxt->err); + } + + if (xmlSchemaPValAttr(pctxt, NULL, node, + "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), + &schemaLocation) != 0) { + xmlSchemaPSimpleTypeErr(pctxt, + XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, + NULL, node, + xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), + NULL, namespaceName, NULL, NULL, NULL); + return (pctxt->err); + } + /* + * And now for the children... + */ + child = node->children; + if (IS_SCHEMA(child, "annotation")) { + /* + * the annotation here is simply discarded ... + * TODO: really? + */ + child = child->next; + } + if (child != NULL) { + xmlSchemaPContentErr(pctxt, + XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, + NULL, node, child, NULL, + "(annotation?)"); + } + /* + * Apply additional constraints. + * + * Note that it is important to use the original @targetNamespace + * (or none at all), to rule out imports of schemas _with_ a + * @targetNamespace if the importing schema is a chameleon schema + * (with no @targetNamespace). + */ + thisTargetNamespace = WXS_BUCKET(pctxt)->origTargetNamespace; + if (namespaceName != NULL) { + /* + * 1.1 If the namespace [attribute] is present, then its ·actual value· + * must not match the ·actual value· of the enclosing 's + * targetNamespace [attribute]. + */ + if (xmlStrEqual(thisTargetNamespace, namespaceName)) { + xmlSchemaPCustomErr(pctxt, + XML_SCHEMAP_SRC_IMPORT_1_1, + NULL, node, + "The value of the attribute 'namespace' must not match " + "the target namespace '%s' of the importing schema", + thisTargetNamespace); + return (pctxt->err); + } + } else { + /* + * 1.2 If the namespace [attribute] is not present, then the enclosing + * must have a targetNamespace [attribute]. + */ + if (thisTargetNamespace == NULL) { + xmlSchemaPCustomErr(pctxt, + XML_SCHEMAP_SRC_IMPORT_1_2, + NULL, node, + "The attribute 'namespace' must be existent if " + "the importing schema has no target namespace", + NULL); + return (pctxt->err); + } + } + /* + * Locate and acquire the schema document. + */ + if (schemaLocation != NULL) + schemaLocation = xmlSchemaBuildAbsoluteURI(pctxt->dict, + schemaLocation, node); + ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT, + schemaLocation, NULL, NULL, 0, node, thisTargetNamespace, + namespaceName, &bucket); + + if (ret != 0) + return(ret); + + /* + * For : "It is *not* an error for the application + * schema reference strategy to fail." + * So just don't parse if no schema document was found. + * Note that we will get no bucket if the schema could not be + * located or if there was no schemaLocation. + */ + if ((bucket == NULL) && (schemaLocation != NULL)) { + xmlSchemaCustomWarning(ACTXT_CAST pctxt, + XML_SCHEMAP_WARN_UNLOCATED_SCHEMA, + node, NULL, + "Failed to locate a schema at location '%s'. " + "Skipping the import", schemaLocation, NULL, NULL); + } + + if ((bucket != NULL) && CAN_PARSE_SCHEMA(bucket)) { + ret = xmlSchemaParseNewDoc(pctxt, schema, bucket); + } + + return (ret); +} + +static int +xmlSchemaParseIncludeOrRedefineAttrs(xmlSchemaParserCtxtPtr pctxt, + xmlSchemaPtr schema, + xmlNodePtr node, + xmlChar **schemaLocation, + int type) +{ + xmlAttrPtr attr; + + if ((pctxt == NULL) || (schema == NULL) || (node == NULL) || + (schemaLocation == NULL)) + return (-1); + + *schemaLocation = NULL; + /* + * Check for illegal attributes. + * Applies for both and . + */ + attr = node->properties; + while (attr != NULL) { + if (attr->ns == NULL) { + if ((!xmlStrEqual(attr->name, BAD_CAST "id")) && + (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) { + xmlSchemaPIllegalAttrErr(pctxt, + XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); + } + } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { + xmlSchemaPIllegalAttrErr(pctxt, + XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); + } + attr = attr->next; + } + xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id"); + /* + * Preliminary step, extract the URI-Reference and make an URI + * from the base. + */ + /* + * Attribute "schemaLocation" is mandatory. + */ + attr = xmlSchemaGetPropNode(node, "schemaLocation"); + if (attr != NULL) { + xmlChar *base = NULL; + xmlChar *uri = NULL; + + if (xmlSchemaPValAttrNode(pctxt, NULL, attr, + xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), + (const xmlChar **) schemaLocation) != 0) + goto exit_error; + base = xmlNodeGetBase(node->doc, node); + if (base == NULL) { + uri = xmlBuildURI(*schemaLocation, node->doc->URL); + } else { + uri = xmlBuildURI(*schemaLocation, base); + xmlFree(base); + } + if (uri == NULL) { + PERROR_INT("xmlSchemaParseIncludeOrRedefine", + "could not build an URI from the schemaLocation") + goto exit_failure; + } + (*schemaLocation) = (xmlChar *) xmlDictLookup(pctxt->dict, uri, -1); + xmlFree(uri); + } else { + xmlSchemaPMissingAttrErr(pctxt, + XML_SCHEMAP_S4S_ATTR_MISSING, + NULL, node, "schemaLocation", NULL); + goto exit_error; + } + /* + * Report self-inclusion and self-redefinition. + */ + if (xmlStrEqual(*schemaLocation, pctxt->URL)) { + if (type == XML_SCHEMA_SCHEMA_REDEFINE) { + xmlSchemaPCustomErr(pctxt, + XML_SCHEMAP_SRC_REDEFINE, + NULL, node, + "The schema document '%s' cannot redefine itself.", + *schemaLocation); + } else { + xmlSchemaPCustomErr(pctxt, + XML_SCHEMAP_SRC_INCLUDE, + NULL, node, + "The schema document '%s' cannot include itself.", + *schemaLocation); + } + goto exit_error; + } + + return(0); +exit_error: + return(pctxt->err); +exit_failure: + return(-1); +} + +static int +xmlSchemaParseIncludeOrRedefine(xmlSchemaParserCtxtPtr pctxt, + xmlSchemaPtr schema, + xmlNodePtr node, + int type) +{ + xmlNodePtr child = NULL; + const xmlChar *schemaLocation = NULL; + int res = 0; /* hasRedefinitions = 0 */ + int isChameleon = 0, wasChameleon = 0; + xmlSchemaBucketPtr bucket = NULL; + + if ((pctxt == NULL) || (schema == NULL) || (node == NULL)) + return (-1); + + /* + * Parse attributes. Note that the returned schemaLocation will + * be already converted to an absolute URI. + */ + res = xmlSchemaParseIncludeOrRedefineAttrs(pctxt, schema, + node, (xmlChar **) (&schemaLocation), type); + if (res != 0) + return(res); + /* + * Load and add the schema document. + */ + res = xmlSchemaAddSchemaDoc(pctxt, type, schemaLocation, NULL, + NULL, 0, node, pctxt->targetNamespace, NULL, &bucket); + if (res != 0) + return(res); + /* + * If we get no schema bucket back, then this means that the schema + * document could not be located or was broken XML or was not + * a schema document. + */ + if ((bucket == NULL) || (bucket->doc == NULL)) { + if (type == XML_SCHEMA_SCHEMA_INCLUDE) { + /* + * WARNING for : + * We will raise an error if the schema cannot be located + * for inclusions, since the that was the feedback from the + * schema people. I.e. the following spec piece will *not* be + * satisfied: + * SPEC src-include: "It is not an error for the ·actual value· of the + * schemaLocation [attribute] to fail to resolve it all, in which + * case no corresponding inclusion is performed. + * So do we need a warning report here?" + */ + res = XML_SCHEMAP_SRC_INCLUDE; + xmlSchemaCustomErr(ACTXT_CAST pctxt, res, + node, NULL, + "Failed to load the document '%s' for inclusion", + schemaLocation, NULL); + } else { + /* + * NOTE: This was changed to raise an error even if no redefinitions + * are specified. + * + * SPEC src-redefine (1) + * "If there are any element information items among the [children] + * other than then the ·actual value· of the + * schemaLocation [attribute] must successfully resolve." + * TODO: Ask the WG if a the location has always to resolve + * here as well! + */ + res = XML_SCHEMAP_SRC_REDEFINE; + xmlSchemaCustomErr(ACTXT_CAST pctxt, res, + node, NULL, + "Failed to load the document '%s' for redefinition", + schemaLocation, NULL); + } + } else { + /* + * Check targetNamespace sanity before parsing the new schema. + * TODO: Note that we won't check further content if the + * targetNamespace was bad. + */ + if (bucket->origTargetNamespace != NULL) { + /* + * SPEC src-include (2.1) + * "SII has a targetNamespace [attribute], and its ·actual + * value· is identical to the ·actual value· of the targetNamespace + * [attribute] of SII’ (which must have such an [attribute])." + */ + if (pctxt->targetNamespace == NULL) { + xmlSchemaCustomErr(ACTXT_CAST pctxt, + XML_SCHEMAP_SRC_INCLUDE, + node, NULL, + "The target namespace of the included/redefined schema " + "'%s' has to be absent, since the including/redefining " + "schema has no target namespace", + schemaLocation, NULL); + goto exit_error; + } else if (!xmlStrEqual(bucket->origTargetNamespace, + pctxt->targetNamespace)) { + /* TODO: Change error function. */ + xmlSchemaPCustomErrExt(pctxt, + XML_SCHEMAP_SRC_INCLUDE, + NULL, node, + "The target namespace '%s' of the included/redefined " + "schema '%s' differs from '%s' of the " + "including/redefining schema", + bucket->origTargetNamespace, schemaLocation, + pctxt->targetNamespace); + goto exit_error; + } + } else if (pctxt->targetNamespace != NULL) { + /* + * Chameleons: the original target namespace will + * differ from the resulting namespace. + */ + isChameleon = 1; + if (bucket->parsed && + (bucket->targetNamespace != pctxt->targetNamespace)) { + /* + * This is a sanity check, I dunno yet if this can happen. + */ + PERROR_INT("xmlSchemaParseIncludeOrRedefine", + "trying to use an already parsed schema for a " + "different targetNamespace"); + return(-1); + } + bucket->targetNamespace = pctxt->targetNamespace; + } + } + /* + * Parse the schema. + */ + if (bucket && (!bucket->parsed) && (bucket->doc != NULL)) { + if (isChameleon) { + /* TODO: Get rid of this flag on the schema itself. */ + if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) { + schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS; + } else + wasChameleon = 1; + } + xmlSchemaParseNewDoc(pctxt, schema, bucket); + /* Restore chameleon flag. */ + if (isChameleon && (!wasChameleon)) + schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS; + } + /* + * And now for the children... + */ + child = node->children; + if (type == XML_SCHEMA_SCHEMA_REDEFINE) { + /* + * Parse (simpleType | complexType | group | attributeGroup))* + */ + pctxt->redefined = bucket; + /* + * How to proceed if the redefined schema was not located? + */ + pctxt->isRedefine = 1; + while (IS_SCHEMA(child, "annotation") || + IS_SCHEMA(child, "simpleType") || + IS_SCHEMA(child, "complexType") || + IS_SCHEMA(child, "group") || + IS_SCHEMA(child, "attributeGroup")) { + if (IS_SCHEMA(child, "annotation")) { + /* + * TODO: discard or not? + */ + } else if (IS_SCHEMA(child, "simpleType")) { + xmlSchemaParseSimpleType(pctxt, schema, child, 1); + } else if (IS_SCHEMA(child, "complexType")) { + xmlSchemaParseComplexType(pctxt, schema, child, 1); + /* hasRedefinitions = 1; */ + } else if (IS_SCHEMA(child, "group")) { + /* hasRedefinitions = 1; */ + xmlSchemaParseModelGroupDefinition(pctxt, + schema, child); + } else if (IS_SCHEMA(child, "attributeGroup")) { + /* hasRedefinitions = 1; */ + xmlSchemaParseAttributeGroupDefinition(pctxt, schema, + child); + } + child = child->next; + } + pctxt->redefined = NULL; + pctxt->isRedefine = 0; + } else { + if (IS_SCHEMA(child, "annotation")) { + /* + * TODO: discard or not? + */ + child = child->next; + } + } + if (child != NULL) { + res = XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED; + if (type == XML_SCHEMA_SCHEMA_REDEFINE) { + xmlSchemaPContentErr(pctxt, res, + NULL, node, child, NULL, + "(annotation | (simpleType | complexType | group | attributeGroup))*"); + } else { + xmlSchemaPContentErr(pctxt, res, + NULL, node, child, NULL, + "(annotation?)"); + } + } + return(res); + +exit_error: + return(pctxt->err); +} + +static int +xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema, + xmlNodePtr node) +{ + int res; +#ifndef ENABLE_REDEFINE + TODO + return(0); +#endif + res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node, + XML_SCHEMA_SCHEMA_REDEFINE); + if (res != 0) + return(res); + return(0); +} + +static int +xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema, + xmlNodePtr node) +{ + int res; + + res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node, + XML_SCHEMA_SCHEMA_INCLUDE); + if (res != 0) + return(res); + return(0); +} + +/** + * xmlSchemaParseModelGroup: + * @ctxt: a schema validation context + * @schema: the schema being built + * @node: a subtree containing XML Schema informations + * @type: the "compositor" type + * @particleNeeded: if a a model group with a particle + * + * parse a XML schema Sequence definition. + * Applies parts of: + * Schema Representation Constraint: + * Redefinition Constraints and Semantics (src-redefine) + * (6.1), (6.1.1), (6.1.2) + * + * Schema Component Constraint: + * All Group Limited (cos-all-limited) (2) + * TODO: Actually this should go to component-level checks, + * but is done here due to performance. Move it to an other layer + * is schema construction via an API is implemented. + * + * *WARNING* this interface is highly subject to change + * + * Returns -1 in case of error, 0 if the declaration is improper and + * 1 in case of success. + */ +static xmlSchemaTreeItemPtr +xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, + xmlNodePtr node, xmlSchemaTypeType type, + int withParticle) +{ + xmlSchemaModelGroupPtr item; + xmlSchemaParticlePtr particle = NULL; + xmlNodePtr child = NULL; + xmlAttrPtr attr; + int min = 1, max = 1, isElemRef, hasRefs = 0; + + if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) + return (NULL); + /* + * Create a model group with the given compositor. + */ + item = xmlSchemaAddModelGroup(ctxt, schema, type, node); + if (item == NULL) + return (NULL); + + if (withParticle) { + if (type == XML_SCHEMA_TYPE_ALL) { + min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)"); + max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1"); + } else { + /* choice + sequence */ + min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger"); + max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, + "(xs:nonNegativeInteger | unbounded)"); + } + xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max); + /* + * Create a particle + */ + particle = xmlSchemaAddParticle(ctxt, node, min, max); + if (particle == NULL) + return (NULL); + particle->children = (xmlSchemaTreeItemPtr) item; + /* + * Check for illegal attributes. + */ + attr = node->properties; + while (attr != NULL) { + if (attr->ns == NULL) { + if ((!xmlStrEqual(attr->name, BAD_CAST "id")) && + (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) && + (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) { + xmlSchemaPIllegalAttrErr(ctxt, + XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); + } + } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { + xmlSchemaPIllegalAttrErr(ctxt, + XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); + } + attr = attr->next; + } + } else { + /* + * Check for illegal attributes. + */ + attr = node->properties; + while (attr != NULL) { + if (attr->ns == NULL) { + if (!xmlStrEqual(attr->name, BAD_CAST "id")) { + xmlSchemaPIllegalAttrErr(ctxt, + XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); + } + } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { + xmlSchemaPIllegalAttrErr(ctxt, + XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); + } + attr = attr->next; + } + } + + /* + * Extract and validate attributes. + */ + xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); + /* + * And now for the children... + */ + child = node->children; + if (IS_SCHEMA(child, "annotation")) { + item->annot = xmlSchemaParseAnnotation(ctxt, child, 1); + child = child->next; + } + if (type == XML_SCHEMA_TYPE_ALL) { + xmlSchemaParticlePtr part, last = NULL; + + while (IS_SCHEMA(child, "element")) { + part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt, + schema, child, &isElemRef, 0); + /* + * SPEC cos-all-limited (2) + * "The {max occurs} of all the particles in the {particles} + * of the ('all') group must be 0 or 1. + */ + if (part != NULL) { + if (isElemRef) + hasRefs++; + if (part->minOccurs > 1) { + xmlSchemaPCustomErr(ctxt, + XML_SCHEMAP_COS_ALL_LIMITED, + NULL, child, + "Invalid value for minOccurs (must be 0 or 1)", + NULL); + /* Reset to 1. */ + part->minOccurs = 1; + } + if (part->maxOccurs > 1) { + xmlSchemaPCustomErr(ctxt, + XML_SCHEMAP_COS_ALL_LIMITED, + NULL, child, + "Invalid value for maxOccurs (must be 0 or 1)", + NULL); + /* Reset to 1. */ + part->maxOccurs = 1; + } + if (last == NULL) + item->children = (xmlSchemaTreeItemPtr) part; + else + last->next = (xmlSchemaTreeItemPtr) part; + last = part; + } + child = child->next; + } + if (child != NULL) { + xmlSchemaPContentErr(ctxt, + XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, + NULL, node, child, NULL, + "(annotation?, (annotation?, element*)"); + } + } else { + /* choice + sequence */ + xmlSchemaTreeItemPtr part = NULL, last = NULL; + + while ((IS_SCHEMA(child, "element")) || + (IS_SCHEMA(child, "group")) || + (IS_SCHEMA(child, "any")) || + (IS_SCHEMA(child, "choice")) || + (IS_SCHEMA(child, "sequence"))) { + + if (IS_SCHEMA(child, "element")) { + part = (xmlSchemaTreeItemPtr) + xmlSchemaParseElement(ctxt, schema, child, &isElemRef, 0); + if (part && isElemRef) + hasRefs++; + } else if (IS_SCHEMA(child, "group")) { + part = + xmlSchemaParseModelGroupDefRef(ctxt, schema, child); + if (part != NULL) + hasRefs++; + /* + * Handle redefinitions. + */ + if (ctxt->isRedefine && ctxt->redef && + (ctxt->redef->item->type == XML_SCHEMA_TYPE_GROUP) && + part && part->children) + { + if ((xmlSchemaGetQNameRefName(part->children) == + ctxt->redef->refName) && + (xmlSchemaGetQNameRefTargetNs(part->children) == + ctxt->redef->refTargetNs)) + { + /* + * SPEC src-redefine: + * (6.1) "If it has a among its contents at + * some level the ·actual value· of whose ref + * [attribute] is the same as the ·actual value· of + * its own name attribute plus target namespace, then + * all of the following must be true:" + * (6.1.1) "It must have exactly one such group." + */ + if (ctxt->redefCounter != 0) { + xmlChar *str = NULL; + + xmlSchemaCustomErr(ACTXT_CAST ctxt, + XML_SCHEMAP_SRC_REDEFINE, child, NULL, + "The redefining model group definition " + "'%s' must not contain more than one " + "reference to the redefined definition", + xmlSchemaFormatQName(&str, + ctxt->redef->refTargetNs, + ctxt->redef->refName), + NULL); + FREE_AND_NULL(str) + part = NULL; + } else if (((WXS_PARTICLE(part))->minOccurs != 1) || + ((WXS_PARTICLE(part))->maxOccurs != 1)) + { + xmlChar *str = NULL; + /* + * SPEC src-redefine: + * (6.1.2) "The ·actual value· of both that + * group's minOccurs and maxOccurs [attribute] + * must be 1 (or ·absent·). + */ + xmlSchemaCustomErr(ACTXT_CAST ctxt, + XML_SCHEMAP_SRC_REDEFINE, child, NULL, + "The redefining model group definition " + "'%s' must not contain a reference to the " + "redefined definition with a " + "maxOccurs/minOccurs other than 1", + xmlSchemaFormatQName(&str, + ctxt->redef->refTargetNs, + ctxt->redef->refName), + NULL); + FREE_AND_NULL(str) + part = NULL; + } + ctxt->redef->reference = WXS_BASIC_CAST part; + ctxt->redefCounter++; + } + } + } else if (IS_SCHEMA(child, "any")) { + part = (xmlSchemaTreeItemPtr) + xmlSchemaParseAny(ctxt, schema, child); + } else if (IS_SCHEMA(child, "choice")) { + part = xmlSchemaParseModelGroup(ctxt, schema, child, + XML_SCHEMA_TYPE_CHOICE, 1); + } else if (IS_SCHEMA(child, "sequence")) { + part = xmlSchemaParseModelGroup(ctxt, schema, child, + XML_SCHEMA_TYPE_SEQUENCE, 1); + } + if (part != NULL) { + if (last == NULL) + item->children = part; + else + last->next = part; + last = part; + } + child = child->next; + } + if (child != NULL) { + xmlSchemaPContentErr(ctxt, + XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, + NULL, node, child, NULL, + "(annotation?, (element | group | choice | sequence | any)*)"); + } + } + if ((max == 0) && (min == 0)) + return (NULL); + if (hasRefs) { + /* + * We need to resolve references. + */ + WXS_ADD_PENDING(ctxt, item); + } + if (withParticle) + return ((xmlSchemaTreeItemPtr) particle); + else + return ((xmlSchemaTreeItemPtr) item); +} + +/** + * xmlSchemaParseRestriction: + * @ctxt: a schema validation context + * @schema: the schema being built + * @node: a subtree containing XML Schema informations + * + * parse a XML schema Restriction definition + * *WARNING* this interface is highly subject to change + * + * Returns the type definition or NULL in case of error + */ +static xmlSchemaTypePtr +xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, + xmlNodePtr node, xmlSchemaTypeType parentType) +{ + xmlSchemaTypePtr type; + xmlNodePtr child = NULL; + xmlAttrPtr attr; + + if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) + return (NULL); + /* Not a component, don't create it. */ + type = ctxt->ctxtType; + type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION; + + /* + * Check for illegal attributes. + */ + attr = node->properties; + while (attr != NULL) { + if (attr->ns == NULL) { + if ((!xmlStrEqual(attr->name, BAD_CAST "id")) && + (!xmlStrEqual(attr->name, BAD_CAST "base"))) { + xmlSchemaPIllegalAttrErr(ctxt, + XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); + } + } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { + xmlSchemaPIllegalAttrErr(ctxt, + XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); + } + attr = attr->next; + } + /* + * Extract and validate attributes. + */ + xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); + /* + * Attribute + */ + /* + * Extract the base type. The "base" attribute is mandatory if inside + * a complex type or if redefining. + * + * SPEC (1.2) "...otherwise ( has no " + * among its [children]), the simple type definition which is + * the {content type} of the type definition ·resolved· to by + * the ·actual value· of the base [attribute]" + */ + if (xmlSchemaPValAttrQName(ctxt, schema, NULL, node, "base", + &(type->baseNs), &(type->base)) == 0) + { + if ((type->base == NULL) && (type->type == XML_SCHEMA_TYPE_COMPLEX)) { + xmlSchemaPMissingAttrErr(ctxt, + XML_SCHEMAP_S4S_ATTR_MISSING, + NULL, node, "base", NULL); + } else if ((ctxt->isRedefine) && + (type->flags & XML_SCHEMAS_TYPE_GLOBAL)) + { + if (type->base == NULL) { + xmlSchemaPMissingAttrErr(ctxt, + XML_SCHEMAP_S4S_ATTR_MISSING, + NULL, node, "base", NULL); + } else if ((! xmlStrEqual(type->base, type->name)) || + (! xmlStrEqual(type->baseNs, type->targetNamespace))) + { + xmlChar *str1 = NULL, *str2 = NULL; + /* + * REDEFINE: SPEC src-redefine (5) + * "Within the [children], each must have a + * among its [children] ... the ·actual value· of + * whose base [attribute] must be the same as the ·actual value· + * of its own name attribute plus target namespace;" + */ + xmlSchemaPCustomErrExt(ctxt, XML_SCHEMAP_SRC_REDEFINE, + NULL, node, "This is a redefinition, but the QName " + "value '%s' of the 'base' attribute does not match the " + "type's designation '%s'", + xmlSchemaFormatQName(&str1, type->baseNs, type->base), + xmlSchemaFormatQName(&str2, type->targetNamespace, + type->name), NULL); + FREE_AND_NULL(str1); + FREE_AND_NULL(str2); + /* Avoid confusion and erase the values. */ + type->base = NULL; + type->baseNs = NULL; + } + } + } + /* + * And now for the children... + */ + child = node->children; + if (IS_SCHEMA(child, "annotation")) { + /* + * Add the annotation to the simple type ancestor. + */ + xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type, + xmlSchemaParseAnnotation(ctxt, child, 1)); + child = child->next; + } + if (parentType == XML_SCHEMA_TYPE_SIMPLE) { + /* + * Corresponds to . + */ + if (IS_SCHEMA(child, "simpleType")) { + if (type->base != NULL) { + /* + * src-restriction-base-or-simpleType + * Either the base [attribute] or the simpleType [child] of the + * element must be present, but not both. + */ + xmlSchemaPContentErr(ctxt, + XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE, + NULL, node, child, + "The attribute 'base' and the child are " + "mutually exclusive", NULL); + } else { + type->baseType = (xmlSchemaTypePtr) + xmlSchemaParseSimpleType(ctxt, schema, child, 0); + } + child = child->next; + } else if (type->base == NULL) { + xmlSchemaPContentErr(ctxt, + XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE, + NULL, node, child, + "Either the attribute 'base' or a child " + "must be present", NULL); + } + } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) { + /* + * Corresponds to ... + * followed by: + * + * Model groups , and . + */ + if (IS_SCHEMA(child, "all")) { + type->subtypes = (xmlSchemaTypePtr) + xmlSchemaParseModelGroup(ctxt, schema, child, + XML_SCHEMA_TYPE_ALL, 1); + child = child->next; + } else if (IS_SCHEMA(child, "choice")) { + type->subtypes = (xmlSchemaTypePtr) + xmlSchemaParseModelGroup(ctxt, + schema, child, XML_SCHEMA_TYPE_CHOICE, 1); + child = child->next; + } else if (IS_SCHEMA(child, "sequence")) { + type->subtypes = (xmlSchemaTypePtr) + xmlSchemaParseModelGroup(ctxt, schema, child, + XML_SCHEMA_TYPE_SEQUENCE, 1); + child = child->next; + /* + * Model group reference . + */ + } else if (IS_SCHEMA(child, "group")) { + type->subtypes = (xmlSchemaTypePtr) + xmlSchemaParseModelGroupDefRef(ctxt, schema, child); + /* + * Note that the reference will be resolved in + * xmlSchemaResolveTypeReferences(); + */ + child = child->next; + } + } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) { + /* + * Corresponds to ... + * + * "1.1 the simple type definition corresponding to the + * among the [children] of if there is one;" + */ + if (IS_SCHEMA(child, "simpleType")) { + /* + * We will store the to-be-restricted simple type in + * type->contentTypeDef *temporarily*. + */ + type->contentTypeDef = (xmlSchemaTypePtr) + xmlSchemaParseSimpleType(ctxt, schema, child, 0); + if ( type->contentTypeDef == NULL) + return (NULL); + child = child->next; + } + } + + if ((parentType == XML_SCHEMA_TYPE_SIMPLE) || + (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) { + xmlSchemaFacetPtr facet, lastfacet = NULL; + /* + * Corresponds to ... + * ... + */ + + /* + * Add the facets to the simple type ancestor. + */ + /* + * TODO: Datatypes: 4.1.3 Constraints on XML Representation of + * Simple Type Definition Schema Representation Constraint: + * *Single Facet Value* + */ + while ((IS_SCHEMA(child, "minInclusive")) || + (IS_SCHEMA(child, "minExclusive")) || + (IS_SCHEMA(child, "maxInclusive")) || + (IS_SCHEMA(child, "maxExclusive")) || + (IS_SCHEMA(child, "totalDigits")) || + (IS_SCHEMA(child, "fractionDigits")) || + (IS_SCHEMA(child, "pattern")) || + (IS_SCHEMA(child, "enumeration")) || + (IS_SCHEMA(child, "whiteSpace")) || + (IS_SCHEMA(child, "length")) || + (IS_SCHEMA(child, "maxLength")) || + (IS_SCHEMA(child, "minLength"))) { + facet = xmlSchemaParseFacet(ctxt, schema, child); + if (facet != NULL) { + if (lastfacet == NULL) + type->facets = facet; + else + lastfacet->next = facet; + lastfacet = facet; + lastfacet->next = NULL; + } + child = child->next; + } + /* + * Create links for derivation and validation. + */ + if (type->facets != NULL) { + xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL; + + facet = type->facets; + do { + facetLink = (xmlSchemaFacetLinkPtr) + xmlMalloc(sizeof(xmlSchemaFacetLink)); + if (facetLink == NULL) { + xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL); + xmlFree(facetLink); + return (NULL); + } + facetLink->facet = facet; + facetLink->next = NULL; + if (lastFacetLink == NULL) + type->facetSet = facetLink; + else + lastFacetLink->next = facetLink; + lastFacetLink = facetLink; + facet = facet->next; + } while (facet != NULL); + } + } + if (type->type == XML_SCHEMA_TYPE_COMPLEX) { + /* + * Attribute uses/declarations. + */ + if (xmlSchemaParseLocalAttributes(ctxt, schema, &child, + (xmlSchemaItemListPtr *) &(type->attrUses), + XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1) + return(NULL); + /* + * Attribute wildcard. + */ + if (IS_SCHEMA(child, "anyAttribute")) { + type->attributeWildcard = + xmlSchemaParseAnyAttribute(ctxt, schema, child); + child = child->next; + } + } + if (child != NULL) { + if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) { + xmlSchemaPContentErr(ctxt, + XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, + NULL, node, child, NULL, + "annotation?, (group | all | choice | sequence)?, " + "((attribute | attributeGroup)*, anyAttribute?))"); + } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) { + xmlSchemaPContentErr(ctxt, + XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, + NULL, node, child, NULL, + "(annotation?, (simpleType?, (minExclusive | minInclusive | " + "maxExclusive | maxInclusive | totalDigits | fractionDigits | " + "length | minLength | maxLength | enumeration | whiteSpace | " + "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))"); + } else { + /* Simple type */ + xmlSchemaPContentErr(ctxt, + XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, + NULL, node, child, NULL, + "(annotation?, (simpleType?, (minExclusive | minInclusive | " + "maxExclusive | maxInclusive | totalDigits | fractionDigits | " + "length | minLength | maxLength | enumeration | whiteSpace | " + "pattern)*))"); + } + } + return (NULL); +} + +/** + * xmlSchemaParseExtension: + * @ctxt: a schema validation context + * @schema: the schema being built + * @node: a subtree containing XML Schema informations + * + * Parses an , which is found inside a + * or . + * *WARNING* this interface is highly subject to change. + * + * TODO: Returns the type definition or NULL in case of error + */ +static xmlSchemaTypePtr +xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, + xmlNodePtr node, xmlSchemaTypeType parentType) +{ + xmlSchemaTypePtr type; + xmlNodePtr child = NULL; + xmlAttrPtr attr; + + if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) + return (NULL); + /* Not a component, don't create it. */ + type = ctxt->ctxtType; + type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION; + + /* + * Check for illegal attributes. + */ + attr = node->properties; + while (attr != NULL) { + if (attr->ns == NULL) { + if ((!xmlStrEqual(attr->name, BAD_CAST "id")) && + (!xmlStrEqual(attr->name, BAD_CAST "base"))) { + xmlSchemaPIllegalAttrErr(ctxt, + XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); + } + } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { + xmlSchemaPIllegalAttrErr(ctxt, + XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); + } + attr = attr->next; + } + + xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); + + /* + * Attribute "base" - mandatory. + */ + if ((xmlSchemaPValAttrQName(ctxt, schema, NULL, node, + "base", &(type->baseNs), &(type->base)) == 0) && + (type->base == NULL)) { + xmlSchemaPMissingAttrErr(ctxt, + XML_SCHEMAP_S4S_ATTR_MISSING, + NULL, node, "base", NULL); + } + /* + * And now for the children... + */ + child = node->children; + if (IS_SCHEMA(child, "annotation")) { + /* + * Add the annotation to the type ancestor. + */ + xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type, + xmlSchemaParseAnnotation(ctxt, child, 1)); + child = child->next; + } + if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) { + /* + * Corresponds to ... and: + * + * Model groups , , and . + */ + if (IS_SCHEMA(child, "all")) { + type->subtypes = (xmlSchemaTypePtr) + xmlSchemaParseModelGroup(ctxt, schema, + child, XML_SCHEMA_TYPE_ALL, 1); + child = child->next; + } else if (IS_SCHEMA(child, "choice")) { + type->subtypes = (xmlSchemaTypePtr) + xmlSchemaParseModelGroup(ctxt, schema, + child, XML_SCHEMA_TYPE_CHOICE, 1); + child = child->next; + } else if (IS_SCHEMA(child, "sequence")) { + type->subtypes = (xmlSchemaTypePtr) + xmlSchemaParseModelGroup(ctxt, schema, + child, XML_SCHEMA_TYPE_SEQUENCE, 1); + child = child->next; + } else if (IS_SCHEMA(child, "group")) { + type->subtypes = (xmlSchemaTypePtr) + xmlSchemaParseModelGroupDefRef(ctxt, schema, child); + /* + * Note that the reference will be resolved in + * xmlSchemaResolveTypeReferences(); + */ + child = child->next; + } + } + if (child != NULL) { + /* + * Attribute uses/declarations. + */ + if (xmlSchemaParseLocalAttributes(ctxt, schema, &child, + (xmlSchemaItemListPtr *) &(type->attrUses), + XML_SCHEMA_TYPE_EXTENSION, NULL) == -1) + return(NULL); + /* + * Attribute wildcard. + */ + if (IS_SCHEMA(child, "anyAttribute")) { + ctxt->ctxtType->attributeWildcard = + xmlSchemaParseAnyAttribute(ctxt, schema, child); + child = child->next; + } + } + if (child != NULL) { + if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) { + /* Complex content extension. */ + xmlSchemaPContentErr(ctxt, + XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, + NULL, node, child, NULL, + "(annotation?, ((group | all | choice | sequence)?, " + "((attribute | attributeGroup)*, anyAttribute?)))"); + } else { + /* Simple content extension. */ + xmlSchemaPContentErr(ctxt, + XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, + NULL, node, child, NULL, + "(annotation?, ((attribute | attributeGroup)*, " + "anyAttribute?))"); + } + } + return (NULL); +} + +/** + * xmlSchemaParseSimpleContent: + * @ctxt: a schema validation context + * @schema: the schema being built + * @node: a subtree containing XML Schema informations + * + * parse a XML schema SimpleContent definition + * *WARNING* this interface is highly subject to change + * + * Returns the type definition or NULL in case of error + */ +static int +xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt, + xmlSchemaPtr schema, xmlNodePtr node, + int *hasRestrictionOrExtension) +{ + xmlSchemaTypePtr type; + xmlNodePtr child = NULL; + xmlAttrPtr attr; + + if ((ctxt == NULL) || (schema == NULL) || (node == NULL) || + (hasRestrictionOrExtension == NULL)) + return (-1); + *hasRestrictionOrExtension = 0; + /* Not a component, don't create it. */ + type = ctxt->ctxtType; + type->contentType = XML_SCHEMA_CONTENT_SIMPLE; + /* + * Check for illegal attributes. + */ + attr = node->properties; + while (attr != NULL) { + if (attr->ns == NULL) { + if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) { + xmlSchemaPIllegalAttrErr(ctxt, + XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); + } + } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { + xmlSchemaPIllegalAttrErr(ctxt, + XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); + } + attr = attr->next; + } + + xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); + + /* + * And now for the children... + */ + child = node->children; + if (IS_SCHEMA(child, "annotation")) { + /* + * Add the annotation to the complex type ancestor. + */ + xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type, + xmlSchemaParseAnnotation(ctxt, child, 1)); + child = child->next; + } + if (child == NULL) { + xmlSchemaPContentErr(ctxt, + XML_SCHEMAP_S4S_ELEM_MISSING, + NULL, node, NULL, NULL, + "(annotation?, (restriction | extension))"); + } + if (child == NULL) { + xmlSchemaPContentErr(ctxt, + XML_SCHEMAP_S4S_ELEM_MISSING, + NULL, node, NULL, NULL, + "(annotation?, (restriction | extension))"); + } + if (IS_SCHEMA(child, "restriction")) { + xmlSchemaParseRestriction(ctxt, schema, child, + XML_SCHEMA_TYPE_SIMPLE_CONTENT); + (*hasRestrictionOrExtension) = 1; + child = child->next; + } else if (IS_SCHEMA(child, "extension")) { + xmlSchemaParseExtension(ctxt, schema, child, + XML_SCHEMA_TYPE_SIMPLE_CONTENT); + (*hasRestrictionOrExtension) = 1; + child = child->next; + } + if (child != NULL) { + xmlSchemaPContentErr(ctxt, + XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, + NULL, node, child, NULL, + "(annotation?, (restriction | extension))"); + } + return (0); +} + +/** + * xmlSchemaParseComplexContent: + * @ctxt: a schema validation context + * @schema: the schema being built + * @node: a subtree containing XML Schema informations + * + * parse a XML schema ComplexContent definition + * *WARNING* this interface is highly subject to change + * + * Returns the type definition or NULL in case of error + */ +static int +xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt, + xmlSchemaPtr schema, xmlNodePtr node, + int *hasRestrictionOrExtension) +{ + xmlSchemaTypePtr type; + xmlNodePtr child = NULL; + xmlAttrPtr attr; + + if ((ctxt == NULL) || (schema == NULL) || (node == NULL) || + (hasRestrictionOrExtension == NULL)) + return (-1); + *hasRestrictionOrExtension = 0; + /* Not a component, don't create it. */ + type = ctxt->ctxtType; + /* + * Check for illegal attributes. + */ + attr = node->properties; + while (attr != NULL) { + if (attr->ns == NULL) { + if ((!xmlStrEqual(attr->name, BAD_CAST "id")) && + (!xmlStrEqual(attr->name, BAD_CAST "mixed"))) + { + xmlSchemaPIllegalAttrErr(ctxt, + XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); + } + } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { + xmlSchemaPIllegalAttrErr(ctxt, + XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); + } + attr = attr->next; + } + + xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); + + /* + * Set the 'mixed' on the complex type ancestor. + */ + if (xmlGetBooleanProp(ctxt, node, "mixed", 0)) { + if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0) + type->flags |= XML_SCHEMAS_TYPE_MIXED; + } + child = node->children; + if (IS_SCHEMA(child, "annotation")) { + /* + * Add the annotation to the complex type ancestor. + */ + xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type, + xmlSchemaParseAnnotation(ctxt, child, 1)); + child = child->next; + } + if (child == NULL) { + xmlSchemaPContentErr(ctxt, + XML_SCHEMAP_S4S_ELEM_MISSING, + NULL, node, NULL, + NULL, "(annotation?, (restriction | extension))"); + } + if (child == NULL) { + xmlSchemaPContentErr(ctxt, + XML_SCHEMAP_S4S_ELEM_MISSING, + NULL, node, NULL, + NULL, "(annotation?, (restriction | extension))"); + } + if (IS_SCHEMA(child, "restriction")) { + xmlSchemaParseRestriction(ctxt, schema, child, + XML_SCHEMA_TYPE_COMPLEX_CONTENT); + (*hasRestrictionOrExtension) = 1; + child = child->next; + } else if (IS_SCHEMA(child, "extension")) { + xmlSchemaParseExtension(ctxt, schema, child, + XML_SCHEMA_TYPE_COMPLEX_CONTENT); + (*hasRestrictionOrExtension) = 1; + child = child->next; + } + if (child != NULL) { + xmlSchemaPContentErr(ctxt, + XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, + NULL, node, child, + NULL, "(annotation?, (restriction | extension))"); + } + return (0); +} + +/** + * xmlSchemaParseComplexType: + * @ctxt: a schema validation context + * @schema: the schema being built + * @node: a subtree containing XML Schema informations + * + * parse a XML schema Complex Type definition + * *WARNING* this interface is highly subject to change + * + * Returns the type definition or NULL in case of error + */ +static xmlSchemaTypePtr +xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, + xmlNodePtr node, int topLevel) +{ + xmlSchemaTypePtr type, ctxtType; + xmlNodePtr child = NULL; + const xmlChar *name = NULL; + xmlAttrPtr attr; + const xmlChar *attrValue; +#ifdef ENABLE_NAMED_LOCALS + char buf[40]; +#endif + int final = 0, block = 0, hasRestrictionOrExtension = 0; + + + if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) + return (NULL); + + ctxtType = ctxt->ctxtType; + + if (topLevel) { + attr = xmlSchemaGetPropNode(node, "name"); + if (attr == NULL) { + xmlSchemaPMissingAttrErr(ctxt, + XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL); + return (NULL); + } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr, + xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) { + return (NULL); + } + } + + if (topLevel == 0) { + /* + * Parse as local complex type definition. + */ +#ifdef ENABLE_NAMED_LOCALS + snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1); + type = xmlSchemaAddType(ctxt, schema, + XML_SCHEMA_TYPE_COMPLEX, + xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1), + ctxt->targetNamespace, node, 0); +#else + type = xmlSchemaAddType(ctxt, schema, + XML_SCHEMA_TYPE_COMPLEX, + NULL, ctxt->targetNamespace, node, 0); +#endif + if (type == NULL) + return (NULL); + name = type->name; + type->node = node; + type->type = XML_SCHEMA_TYPE_COMPLEX; + /* + * TODO: We need the target namespace. + */ + } else { + /* + * Parse as global complex type definition. + */ + type = xmlSchemaAddType(ctxt, schema, + XML_SCHEMA_TYPE_COMPLEX, + name, ctxt->targetNamespace, node, 1); + if (type == NULL) + return (NULL); + type->node = node; + type->type = XML_SCHEMA_TYPE_COMPLEX; + type->flags |= XML_SCHEMAS_TYPE_GLOBAL; + } + type->targetNamespace = ctxt->targetNamespace; + /* + * Handle attributes. + */ + attr = node->properties; + while (attr != NULL) { + if (attr->ns == NULL) { + if (xmlStrEqual(attr->name, BAD_CAST "id")) { + /* + * Attribute "id". + */ + xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); + } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) { + /* + * Attribute "mixed". + */ + if (xmlSchemaPGetBoolNodeValue(ctxt, + NULL, (xmlNodePtr) attr)) + type->flags |= XML_SCHEMAS_TYPE_MIXED; + } else if (topLevel) { + /* + * Attributes of global complex type definitions. + */ + if (xmlStrEqual(attr->name, BAD_CAST "name")) { + /* Pass. */ + } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) { + /* + * Attribute "abstract". + */ + if (xmlSchemaPGetBoolNodeValue(ctxt, + NULL, (xmlNodePtr) attr)) + type->flags |= XML_SCHEMAS_TYPE_ABSTRACT; + } else if (xmlStrEqual(attr->name, BAD_CAST "final")) { + /* + * Attribute "final". + */ + attrValue = xmlSchemaGetNodeContent(ctxt, + (xmlNodePtr) attr); + if (xmlSchemaPValAttrBlockFinal(attrValue, + &(type->flags), + -1, + XML_SCHEMAS_TYPE_FINAL_EXTENSION, + XML_SCHEMAS_TYPE_FINAL_RESTRICTION, + -1, -1, -1) != 0) + { + xmlSchemaPSimpleTypeErr(ctxt, + XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, + NULL, (xmlNodePtr) attr, NULL, + "(#all | List of (extension | restriction))", + attrValue, NULL, NULL, NULL); + } else + final = 1; + } else if (xmlStrEqual(attr->name, BAD_CAST "block")) { + /* + * Attribute "block". + */ + attrValue = xmlSchemaGetNodeContent(ctxt, + (xmlNodePtr) attr); + if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags), + -1, + XML_SCHEMAS_TYPE_BLOCK_EXTENSION, + XML_SCHEMAS_TYPE_BLOCK_RESTRICTION, + -1, -1, -1) != 0) { + xmlSchemaPSimpleTypeErr(ctxt, + XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, + NULL, (xmlNodePtr) attr, NULL, + "(#all | List of (extension | restriction)) ", + attrValue, NULL, NULL, NULL); + } else + block = 1; + } else { + xmlSchemaPIllegalAttrErr(ctxt, + XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); + } + } else { + xmlSchemaPIllegalAttrErr(ctxt, + XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); + } + } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { + xmlSchemaPIllegalAttrErr(ctxt, + XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); + } + attr = attr->next; + } + if (! block) { + /* + * Apply default "block" values. + */ + if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION) + type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION; + if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION) + type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION; + } + if (! final) { + /* + * Apply default "block" values. + */ + if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION) + type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION; + if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION) + type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION; + } + /* + * And now for the children... + */ + child = node->children; + if (IS_SCHEMA(child, "annotation")) { + type->annot = xmlSchemaParseAnnotation(ctxt, child, 1); + child = child->next; + } + ctxt->ctxtType = type; + if (IS_SCHEMA(child, "simpleContent")) { + /* + * ... + * 3.4.3 : 2.2 + * Specifying mixed='true' when the + * alternative is chosen has no effect + */ + if (type->flags & XML_SCHEMAS_TYPE_MIXED) + type->flags ^= XML_SCHEMAS_TYPE_MIXED; + xmlSchemaParseSimpleContent(ctxt, schema, child, + &hasRestrictionOrExtension); + child = child->next; + } else if (IS_SCHEMA(child, "complexContent")) { + /* + * ... + */ + type->contentType = XML_SCHEMA_CONTENT_EMPTY; + xmlSchemaParseComplexContent(ctxt, schema, child, + &hasRestrictionOrExtension); + child = child->next; + } else { + /* + * E.g ... or ... etc. + * + * SPEC + * "...the third alternative (neither nor + * ) is chosen. This case is understood as shorthand + * for complex content restricting the ·ur-type definition·, and the + * details of the mappings should be modified as necessary. + */ + type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE); + type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION; + /* + * Parse model groups. + */ + if (IS_SCHEMA(child, "all")) { + type->subtypes = (xmlSchemaTypePtr) + xmlSchemaParseModelGroup(ctxt, schema, child, + XML_SCHEMA_TYPE_ALL, 1); + child = child->next; + } else if (IS_SCHEMA(child, "choice")) { + type->subtypes = (xmlSchemaTypePtr) + xmlSchemaParseModelGroup(ctxt, schema, child, + XML_SCHEMA_TYPE_CHOICE, 1); + child = child->next; + } else if (IS_SCHEMA(child, "sequence")) { + type->subtypes = (xmlSchemaTypePtr) + xmlSchemaParseModelGroup(ctxt, schema, child, + XML_SCHEMA_TYPE_SEQUENCE, 1); + child = child->next; + } else if (IS_SCHEMA(child, "group")) { + type->subtypes = (xmlSchemaTypePtr) + xmlSchemaParseModelGroupDefRef(ctxt, schema, child); + /* + * Note that the reference will be resolved in + * xmlSchemaResolveTypeReferences(); + */ + child = child->next; + } + /* + * Parse attribute decls/refs. + */ + if (xmlSchemaParseLocalAttributes(ctxt, schema, &child, + (xmlSchemaItemListPtr *) &(type->attrUses), + XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1) + return(NULL); + /* + * Parse attribute wildcard. + */ + if (IS_SCHEMA(child, "anyAttribute")) { + type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child); + child = child->next; + } + } + if (child != NULL) { + xmlSchemaPContentErr(ctxt, + XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, + NULL, node, child, + NULL, "(annotation?, (simpleContent | complexContent | " + "((group | all | choice | sequence)?, ((attribute | " + "attributeGroup)*, anyAttribute?))))"); + } + /* + * REDEFINE: SPEC src-redefine (5) + */ + if (topLevel && ctxt->isRedefine && (! hasRestrictionOrExtension)) { + xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE, + NULL, node, "This is a redefinition, thus the " + " must have a or " + "grand-child", NULL); + } + ctxt->ctxtType = ctxtType; + return (type); +} + +/************************************************************************ + * * + * Validating using Schemas * + * * + ************************************************************************/ + +/************************************************************************ + * * + * Reading/Writing Schemas * + * * + ************************************************************************/ + +#if 0 /* Will be enabled if it is clear what options are needed. */ +/** + * xmlSchemaParserCtxtSetOptions: + * @ctxt: a schema parser context + * @options: a combination of xmlSchemaParserOption + * + * Sets the options to be used during the parse. + * + * Returns 0 in case of success, -1 in case of an + * API error. + */ +static int +xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt, + int options) + +{ + int i; + + if (ctxt == NULL) + return (-1); + /* + * WARNING: Change the start value if adding to the + * xmlSchemaParseOption. + */ + for (i = 1; i < (int) sizeof(int) * 8; i++) { + if (options & 1<options = options; + return (0); +} + +/** + * xmlSchemaValidCtxtGetOptions: + * @ctxt: a schema parser context + * + * Returns the option combination of the parser context. + */ +static int +xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt) + +{ + if (ctxt == NULL) + return (-1); + else + return (ctxt->options); +} +#endif + +/** + * xmlSchemaNewParserCtxt: + * @URL: the location of the schema + * + * Create an XML Schemas parse context for that file/resource expected + * to contain an XML Schemas file. + * + * Returns the parser context or NULL in case of error + */ +xmlSchemaParserCtxtPtr +xmlSchemaNewParserCtxt(const char *URL) +{ + xmlSchemaParserCtxtPtr ret; + + if (URL == NULL) + return (NULL); + + ret = xmlSchemaParserCtxtCreate(); + if (ret == NULL) + return(NULL); + ret->dict = xmlDictCreate(); + ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1); + return (ret); +} + +/** + * xmlSchemaNewMemParserCtxt: + * @buffer: a pointer to a char array containing the schemas + * @size: the size of the array + * + * Create an XML Schemas parse context for that memory buffer expected + * to contain an XML Schemas file. + * + * Returns the parser context or NULL in case of error + */ +xmlSchemaParserCtxtPtr +xmlSchemaNewMemParserCtxt(const char *buffer, int size) +{ + xmlSchemaParserCtxtPtr ret; + + if ((buffer == NULL) || (size <= 0)) + return (NULL); + ret = xmlSchemaParserCtxtCreate(); + if (ret == NULL) + return(NULL); + ret->buffer = buffer; + ret->size = size; + ret->dict = xmlDictCreate(); + return (ret); +} + +/** + * xmlSchemaNewDocParserCtxt: + * @doc: a preparsed document tree + * + * Create an XML Schemas parse context for that document. + * NB. The document may be modified during the parsing process. + * + * Returns the parser context or NULL in case of error + */ +xmlSchemaParserCtxtPtr +xmlSchemaNewDocParserCtxt(xmlDocPtr doc) +{ + xmlSchemaParserCtxtPtr ret; + + if (doc == NULL) + return (NULL); + ret = xmlSchemaParserCtxtCreate(); + if (ret == NULL) + return(NULL); + ret->doc = doc; + ret->dict = xmlDictCreate(); + /* The application has responsibility for the document */ + ret->preserve = 1; + + return (ret); +} + +/** + * xmlSchemaFreeParserCtxt: + * @ctxt: the schema parser context + * + * Free the resources associated to the schema parser context + */ +void +xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt) +{ + if (ctxt == NULL) + return; + if (ctxt->doc != NULL && !ctxt->preserve) + xmlFreeDoc(ctxt->doc); + if (ctxt->vctxt != NULL) { + xmlSchemaFreeValidCtxt(ctxt->vctxt); + } + if (ctxt->ownsConstructor && (ctxt->constructor != NULL)) { + xmlSchemaConstructionCtxtFree(ctxt->constructor); + ctxt->constructor = NULL; + ctxt->ownsConstructor = 0; + } + if (ctxt->attrProhibs != NULL) + xmlSchemaItemListFree(ctxt->attrProhibs); + xmlDictFree(ctxt->dict); + xmlFree(ctxt); +} + +/************************************************************************ + * * + * Building the content models * + * * + ************************************************************************/ + +static void +xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt, + xmlSchemaParticlePtr particle, int counter, xmlAutomataStatePtr end) +{ + xmlAutomataStatePtr start, tmp; + xmlSchemaElementPtr elemDecl, member; + xmlSchemaSubstGroupPtr substGroup; + int i; + + elemDecl = (xmlSchemaElementPtr) particle->children; + /* + * Wrap the substitution group with a CHOICE. + */ + start = pctxt->state; + if (end == NULL) + end = xmlAutomataNewState(pctxt->am); + substGroup = xmlSchemaSubstGroupGet(pctxt, elemDecl); + if (substGroup == NULL) { + xmlSchemaPErr(pctxt, WXS_ITEM_NODE(particle), + XML_SCHEMAP_INTERNAL, + "Internal error: xmlSchemaBuildContentModelForSubstGroup, " + "declaration is marked having a subst. group but none " + "available.\n", elemDecl->name, NULL); + return; + } + if (counter >= 0) { + /* + * NOTE that we put the declaration in, even if it's abstract. + * However, an error will be raised during *validation* if an element + * information item shall be validated against an abstract element + * declaration. + */ + tmp = xmlAutomataNewCountedTrans(pctxt->am, start, NULL, counter); + xmlAutomataNewTransition2(pctxt->am, tmp, end, + elemDecl->name, elemDecl->targetNamespace, elemDecl); + /* + * Add subst. group members. + */ + for (i = 0; i < substGroup->members->nbItems; i++) { + member = (xmlSchemaElementPtr) substGroup->members->items[i]; + xmlAutomataNewTransition2(pctxt->am, tmp, end, + member->name, member->targetNamespace, member); + } + } else if (particle->maxOccurs == 1) { + /* + * NOTE that we put the declaration in, even if it's abstract, + */ + xmlAutomataNewEpsilon(pctxt->am, + xmlAutomataNewTransition2(pctxt->am, + start, NULL, + elemDecl->name, elemDecl->targetNamespace, elemDecl), end); + /* + * Add subst. group members. + */ + for (i = 0; i < substGroup->members->nbItems; i++) { + member = (xmlSchemaElementPtr) substGroup->members->items[i]; + /* + * NOTE: This fixes bug #341150. xmlAutomataNewOnceTrans2() + * was incorrectly used instead of xmlAutomataNewTransition2() + * (seems like a copy&paste bug from the XML_SCHEMA_TYPE_ALL + * section in xmlSchemaBuildAContentModel() ). + * TODO: Check if xmlAutomataNewOnceTrans2() was instead + * intended for the above "counter" section originally. I.e., + * check xs:all with subst-groups. + * + * tmp = xmlAutomataNewOnceTrans2(pctxt->am, start, NULL, + * member->name, member->targetNamespace, + * 1, 1, member); + */ + tmp = xmlAutomataNewTransition2(pctxt->am, start, NULL, + member->name, member->targetNamespace, member); + xmlAutomataNewEpsilon(pctxt->am, tmp, end); + } + } else { + xmlAutomataStatePtr hop; + int maxOccurs = particle->maxOccurs == UNBOUNDED ? + UNBOUNDED : particle->maxOccurs - 1; + int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1; + + counter = + xmlAutomataNewCounter(pctxt->am, minOccurs, + maxOccurs); + hop = xmlAutomataNewState(pctxt->am); + + xmlAutomataNewEpsilon(pctxt->am, + xmlAutomataNewTransition2(pctxt->am, + start, NULL, + elemDecl->name, elemDecl->targetNamespace, elemDecl), + hop); + /* + * Add subst. group members. + */ + for (i = 0; i < substGroup->members->nbItems; i++) { + member = (xmlSchemaElementPtr) substGroup->members->items[i]; + xmlAutomataNewEpsilon(pctxt->am, + xmlAutomataNewTransition2(pctxt->am, + start, NULL, + member->name, member->targetNamespace, member), + hop); + } + xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter); + xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter); + } + if (particle->minOccurs == 0) + xmlAutomataNewEpsilon(pctxt->am, start, end); + pctxt->state = end; +} + +static void +xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt, + xmlSchemaParticlePtr particle) +{ + if (((xmlSchemaElementPtr) particle->children)->flags & + XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) { + /* + * Substitution groups. + */ + xmlSchemaBuildContentModelForSubstGroup(ctxt, particle, -1, NULL); + } else { + xmlSchemaElementPtr elemDecl; + xmlAutomataStatePtr start; + + elemDecl = (xmlSchemaElementPtr) particle->children; + + if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) + return; + if (particle->maxOccurs == 1) { + start = ctxt->state; + ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL, + elemDecl->name, elemDecl->targetNamespace, elemDecl); + } else if ((particle->maxOccurs >= UNBOUNDED) && + (particle->minOccurs < 2)) { + /* Special case. */ + start = ctxt->state; + ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL, + elemDecl->name, elemDecl->targetNamespace, elemDecl); + ctxt->state = xmlAutomataNewTransition2(ctxt->am, ctxt->state, ctxt->state, + elemDecl->name, elemDecl->targetNamespace, elemDecl); + } else { + int counter; + int maxOccurs = particle->maxOccurs == UNBOUNDED ? + UNBOUNDED : particle->maxOccurs - 1; + int minOccurs = particle->minOccurs < 1 ? + 0 : particle->minOccurs - 1; + + start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL); + counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs); + ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL, + elemDecl->name, elemDecl->targetNamespace, elemDecl); + xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter); + ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state, + NULL, counter); + } + if (particle->minOccurs == 0) + xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state); + } +} + +/** + * xmlSchemaBuildAContentModel: + * @ctxt: the schema parser context + * @particle: the particle component + * @name: the complex type's name whose content is being built + * + * Create the automaton for the {content type} of a complex type. + * + */ +static void +xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt, + xmlSchemaParticlePtr particle) +{ + if (particle == NULL) { + PERROR_INT("xmlSchemaBuildAContentModel", "particle is NULL"); + return; + } + if (particle->children == NULL) { + /* + * Just return in this case. A missing "term" of the particle + * might arise due to an invalid "term" component. + */ + return; + } + + switch (particle->children->type) { + case XML_SCHEMA_TYPE_ANY: { + xmlAutomataStatePtr start, end; + xmlSchemaWildcardPtr wild; + xmlSchemaWildcardNsPtr ns; + + wild = (xmlSchemaWildcardPtr) particle->children; + + start = pctxt->state; + end = xmlAutomataNewState(pctxt->am); + + if (particle->maxOccurs == 1) { + if (wild->any == 1) { + /* + * We need to add both transitions: + * + * 1. the {"*", "*"} for elements in a namespace. + */ + pctxt->state = + xmlAutomataNewTransition2(pctxt->am, + start, NULL, BAD_CAST "*", BAD_CAST "*", wild); + xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end); + /* + * 2. the {"*"} for elements in no namespace. + */ + pctxt->state = + xmlAutomataNewTransition2(pctxt->am, + start, NULL, BAD_CAST "*", NULL, wild); + xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end); + + } else if (wild->nsSet != NULL) { + ns = wild->nsSet; + do { + pctxt->state = start; + pctxt->state = xmlAutomataNewTransition2(pctxt->am, + pctxt->state, NULL, BAD_CAST "*", ns->value, wild); + xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end); + ns = ns->next; + } while (ns != NULL); + + } else if (wild->negNsSet != NULL) { + pctxt->state = xmlAutomataNewNegTrans(pctxt->am, + start, end, BAD_CAST "*", wild->negNsSet->value, + wild); + } + } else { + int counter; + xmlAutomataStatePtr hop; + int maxOccurs = + particle->maxOccurs == UNBOUNDED ? UNBOUNDED : particle->maxOccurs - 1; + int minOccurs = + particle->minOccurs < 1 ? 0 : particle->minOccurs - 1; + + counter = xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs); + hop = xmlAutomataNewState(pctxt->am); + if (wild->any == 1) { + pctxt->state = + xmlAutomataNewTransition2(pctxt->am, + start, NULL, BAD_CAST "*", BAD_CAST "*", wild); + xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop); + pctxt->state = + xmlAutomataNewTransition2(pctxt->am, + start, NULL, BAD_CAST "*", NULL, wild); + xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop); + } else if (wild->nsSet != NULL) { + ns = wild->nsSet; + do { + pctxt->state = + xmlAutomataNewTransition2(pctxt->am, + start, NULL, BAD_CAST "*", ns->value, wild); + xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop); + ns = ns->next; + } while (ns != NULL); + + } else if (wild->negNsSet != NULL) { + pctxt->state = xmlAutomataNewNegTrans(pctxt->am, + start, hop, BAD_CAST "*", wild->negNsSet->value, + wild); + } + xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter); + xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter); + } + if (particle->minOccurs == 0) { + xmlAutomataNewEpsilon(pctxt->am, start, end); + } + pctxt->state = end; + break; + } + case XML_SCHEMA_TYPE_ELEMENT: + xmlSchemaBuildContentModelForElement(pctxt, particle); + break; + case XML_SCHEMA_TYPE_SEQUENCE:{ + xmlSchemaTreeItemPtr sub; + + /* + * If max and min occurances are default (1) then + * simply iterate over the particles of the . + */ + if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) { + sub = particle->children->children; + while (sub != NULL) { + xmlSchemaBuildAContentModel(pctxt, + (xmlSchemaParticlePtr) sub); + sub = sub->next; + } + } else { + xmlAutomataStatePtr oldstate = pctxt->state; + + if (particle->maxOccurs >= UNBOUNDED) { + if (particle->minOccurs > 1) { + xmlAutomataStatePtr tmp; + int counter; + + pctxt->state = xmlAutomataNewEpsilon(pctxt->am, + oldstate, NULL); + oldstate = pctxt->state; + + counter = xmlAutomataNewCounter(pctxt->am, + particle->minOccurs - 1, UNBOUNDED); + + sub = particle->children->children; + while (sub != NULL) { + xmlSchemaBuildAContentModel(pctxt, + (xmlSchemaParticlePtr) sub); + sub = sub->next; + } + tmp = pctxt->state; + xmlAutomataNewCountedTrans(pctxt->am, tmp, + oldstate, counter); + pctxt->state = + xmlAutomataNewCounterTrans(pctxt->am, tmp, + NULL, counter); + + } else { + pctxt->state = xmlAutomataNewEpsilon(pctxt->am, + oldstate, NULL); + oldstate = pctxt->state; + + sub = particle->children->children; + while (sub != NULL) { + xmlSchemaBuildAContentModel(pctxt, + (xmlSchemaParticlePtr) sub); + sub = sub->next; + } + xmlAutomataNewEpsilon(pctxt->am, pctxt->state, + oldstate); + /* + * epsilon needed to block previous trans from + * being allowed to enter back from another + * construct + */ + pctxt->state = xmlAutomataNewEpsilon(pctxt->am, + pctxt->state, NULL); + if (particle->minOccurs == 0) { + xmlAutomataNewEpsilon(pctxt->am, + oldstate, pctxt->state); + } + } + } else if ((particle->maxOccurs > 1) + || (particle->minOccurs > 1)) { + xmlAutomataStatePtr tmp; + int counter; + + pctxt->state = xmlAutomataNewEpsilon(pctxt->am, + oldstate, NULL); + oldstate = pctxt->state; + + counter = xmlAutomataNewCounter(pctxt->am, + particle->minOccurs - 1, + particle->maxOccurs - 1); + + sub = particle->children->children; + while (sub != NULL) { + xmlSchemaBuildAContentModel(pctxt, + (xmlSchemaParticlePtr) sub); + sub = sub->next; + } + tmp = pctxt->state; + xmlAutomataNewCountedTrans(pctxt->am, + tmp, oldstate, counter); + pctxt->state = + xmlAutomataNewCounterTrans(pctxt->am, tmp, NULL, + counter); + if (particle->minOccurs == 0) { + xmlAutomataNewEpsilon(pctxt->am, + oldstate, pctxt->state); + } + } else { + sub = particle->children->children; + while (sub != NULL) { + xmlSchemaBuildAContentModel(pctxt, + (xmlSchemaParticlePtr) sub); + sub = sub->next; + } + if (particle->minOccurs == 0) { + xmlAutomataNewEpsilon(pctxt->am, oldstate, + pctxt->state); + } + } + } + break; + } + case XML_SCHEMA_TYPE_CHOICE:{ + xmlSchemaTreeItemPtr sub; + xmlAutomataStatePtr start, end; + + start = pctxt->state; + end = xmlAutomataNewState(pctxt->am); + + /* + * iterate over the subtypes and remerge the end with an + * epsilon transition + */ + if (particle->maxOccurs == 1) { + sub = particle->children->children; + while (sub != NULL) { + pctxt->state = start; + xmlSchemaBuildAContentModel(pctxt, + (xmlSchemaParticlePtr) sub); + xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end); + sub = sub->next; + } + } else { + int counter; + xmlAutomataStatePtr hop, base; + int maxOccurs = particle->maxOccurs == UNBOUNDED ? + UNBOUNDED : particle->maxOccurs - 1; + int minOccurs = + particle->minOccurs < 1 ? 0 : particle->minOccurs - 1; + + /* + * use a counter to keep track of the number of transtions + * which went through the choice. + */ + counter = + xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs); + hop = xmlAutomataNewState(pctxt->am); + base = xmlAutomataNewState(pctxt->am); + + sub = particle->children->children; + while (sub != NULL) { + pctxt->state = base; + xmlSchemaBuildAContentModel(pctxt, + (xmlSchemaParticlePtr) sub); + xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop); + sub = sub->next; + } + xmlAutomataNewEpsilon(pctxt->am, start, base); + xmlAutomataNewCountedTrans(pctxt->am, hop, base, counter); + xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter); + } + if (particle->minOccurs == 0) { + xmlAutomataNewEpsilon(pctxt->am, start, end); + } + pctxt->state = end; + break; + } + case XML_SCHEMA_TYPE_ALL:{ + xmlAutomataStatePtr start; + xmlSchemaParticlePtr sub; + xmlSchemaElementPtr elemDecl; + int lax; + + sub = (xmlSchemaParticlePtr) particle->children->children; + if (sub == NULL) + break; + start = pctxt->state; + while (sub != NULL) { + pctxt->state = start; + + elemDecl = (xmlSchemaElementPtr) sub->children; + if (elemDecl == NULL) { + PERROR_INT("xmlSchemaBuildAContentModel", + " particle has no term"); + return; + }; + /* + * NOTE: The {max occurs} of all the particles in the + * {particles} of the group must be 0 or 1; this is + * already ensured during the parse of the content of + * . + */ + if (elemDecl->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) { + int counter; + + /* + * This is an abstract group, we need to share + * the same counter for all the element transitions + * derived from the group + */ + counter = xmlAutomataNewCounter(pctxt->am, + sub->minOccurs, sub->maxOccurs); + xmlSchemaBuildContentModelForSubstGroup(pctxt, + sub, counter, pctxt->state); + } else { + if ((sub->minOccurs == 1) && + (sub->maxOccurs == 1)) { + xmlAutomataNewOnceTrans2(pctxt->am, pctxt->state, + pctxt->state, + elemDecl->name, + elemDecl->targetNamespace, + 1, 1, elemDecl); + } else if ((sub->minOccurs == 0) && + (sub->maxOccurs == 1)) { + + xmlAutomataNewCountTrans2(pctxt->am, pctxt->state, + pctxt->state, + elemDecl->name, + elemDecl->targetNamespace, + 0, + 1, + elemDecl); + } + } + sub = (xmlSchemaParticlePtr) sub->next; + } + lax = particle->minOccurs == 0; + pctxt->state = + xmlAutomataNewAllTrans(pctxt->am, pctxt->state, NULL, lax); + break; + } + case XML_SCHEMA_TYPE_GROUP: + /* + * If we hit a model group definition, then this means that + * it was empty, thus was not substituted for the containing + * model group. Just do nothing in this case. + * TODO: But the group should be substituted and not occur at + * all in the content model at this point. Fix this. + */ + break; + default: + xmlSchemaInternalErr2(ACTXT_CAST pctxt, + "xmlSchemaBuildAContentModel", + "found unexpected term of type '%s' in content model", + WXS_ITEM_TYPE_NAME(particle->children), NULL); + return; + } +} + +/** + * xmlSchemaBuildContentModel: + * @ctxt: the schema parser context + * @type: the complex type definition + * @name: the element name + * + * Builds the content model of the complex type. + */ +static void +xmlSchemaBuildContentModel(xmlSchemaTypePtr type, + xmlSchemaParserCtxtPtr ctxt) +{ + if ((type->type != XML_SCHEMA_TYPE_COMPLEX) || + (type->contModel != NULL) || + ((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) && + (type->contentType != XML_SCHEMA_CONTENT_MIXED))) + return; + +#ifdef DEBUG_CONTENT + xmlGenericError(xmlGenericErrorContext, + "Building content model for %s\n", name); +#endif + ctxt->am = NULL; + ctxt->am = xmlNewAutomata(); + if (ctxt->am == NULL) { + xmlGenericError(xmlGenericErrorContext, + "Cannot create automata for complex type %s\n", type->name); + return; + } + ctxt->state = xmlAutomataGetInitState(ctxt->am); + /* + * Build the automaton. + */ + xmlSchemaBuildAContentModel(ctxt, WXS_TYPE_PARTICLE(type)); + xmlAutomataSetFinalState(ctxt->am, ctxt->state); + type->contModel = xmlAutomataCompile(ctxt->am); + if (type->contModel == NULL) { + xmlSchemaPCustomErr(ctxt, + XML_SCHEMAP_INTERNAL, + WXS_BASIC_CAST type, type->node, + "Failed to compile the content model", NULL); + } else if (xmlRegexpIsDeterminist(type->contModel) != 1) { + xmlSchemaPCustomErr(ctxt, + XML_SCHEMAP_NOT_DETERMINISTIC, + /* XML_SCHEMAS_ERR_NOTDETERMINIST, */ + WXS_BASIC_CAST type, type->node, + "The content model is not determinist", NULL); + } else { +#ifdef DEBUG_CONTENT_REGEXP + xmlGenericError(xmlGenericErrorContext, + "Content model of %s:\n", type->name); + xmlRegexpPrint(stderr, type->contModel); +#endif + } + ctxt->state = NULL; + xmlFreeAutomata(ctxt->am); + ctxt->am = NULL; +} + +/** + * xmlSchemaResolveElementReferences: + * @elem: the schema element context + * @ctxt: the schema parser context + * + * Resolves the references of an element declaration + * or particle, which has an element declaration as it's + * term. + */ +static void +xmlSchemaResolveElementReferences(xmlSchemaElementPtr elemDecl, + xmlSchemaParserCtxtPtr ctxt) +{ + if ((ctxt == NULL) || (elemDecl == NULL) || + ((elemDecl != NULL) && + (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED))) + return; + elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED; + + if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) { + xmlSchemaTypePtr type; + + /* (type definition) ... otherwise the type definition ·resolved· + * to by the ·actual value· of the type [attribute] ... + */ + type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType, + elemDecl->namedTypeNs); + if (type == NULL) { + xmlSchemaPResCompAttrErr(ctxt, + XML_SCHEMAP_SRC_RESOLVE, + WXS_BASIC_CAST elemDecl, elemDecl->node, + "type", elemDecl->namedType, elemDecl->namedTypeNs, + XML_SCHEMA_TYPE_BASIC, "type definition"); + } else + elemDecl->subtypes = type; + } + if (elemDecl->substGroup != NULL) { + xmlSchemaElementPtr substHead; + + /* + * FIXME TODO: Do we need a new field in _xmlSchemaElement for + * substitutionGroup? + */ + substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup, + elemDecl->substGroupNs); + if (substHead == NULL) { + xmlSchemaPResCompAttrErr(ctxt, + XML_SCHEMAP_SRC_RESOLVE, + WXS_BASIC_CAST elemDecl, NULL, + "substitutionGroup", elemDecl->substGroup, + elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL); + } else { + xmlSchemaResolveElementReferences(substHead, ctxt); + /* + * Set the "substitution group affiliation". + * NOTE that now we use the "refDecl" field for this. + */ + WXS_SUBST_HEAD(elemDecl) = substHead; + /* + * The type definitions is set to: + * SPEC "...the {type definition} of the element + * declaration ·resolved· to by the ·actual value· + * of the substitutionGroup [attribute], if present" + */ + if (elemDecl->subtypes == NULL) + elemDecl->subtypes = substHead->subtypes; + } + } + /* + * SPEC "The definition of anyType serves as the default type definition + * for element declarations whose XML representation does not specify one." + */ + if ((elemDecl->subtypes == NULL) && + (elemDecl->namedType == NULL) && + (elemDecl->substGroup == NULL)) + elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE); +} + +/** + * xmlSchemaResolveUnionMemberTypes: + * @ctxt: the schema parser context + * @type: the schema simple type definition + * + * Checks and builds the "member type definitions" property of the union + * simple type. This handles part (1), part (2) is done in + * xmlSchemaFinishMemberTypeDefinitionsProperty() + * + * Returns -1 in case of an internal error, 0 otherwise. + */ +static int +xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt, + xmlSchemaTypePtr type) +{ + + xmlSchemaTypeLinkPtr link, lastLink, newLink; + xmlSchemaTypePtr memberType; + + /* + * SPEC (1) "If the alternative is chosen, then [Definition:] + * define the explicit members as the type definitions ·resolved· + * to by the items in the ·actual value· of the memberTypes [attribute], + * if any, followed by the type definitions corresponding to the + * s among the [children] of , if any." + */ + /* + * Resolve references. + */ + link = type->memberTypes; + lastLink = NULL; + while (link != NULL) { + const xmlChar *name, *nsName; + + name = ((xmlSchemaQNameRefPtr) link->type)->name; + nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace; + + memberType = xmlSchemaGetType(ctxt->schema, name, nsName); + if ((memberType == NULL) || (! WXS_IS_SIMPLE(memberType))) { + xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE, + WXS_BASIC_CAST type, type->node, "memberTypes", + name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL); + /* + * Remove the member type link. + */ + if (lastLink == NULL) + type->memberTypes = link->next; + else + lastLink->next = link->next; + newLink = link; + link = link->next; + xmlFree(newLink); + } else { + link->type = memberType; + lastLink = link; + link = link->next; + } + } + /* + * Add local simple types, + */ + memberType = type->subtypes; + while (memberType != NULL) { + link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink)); + if (link == NULL) { + xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL); + return (-1); + } + link->type = memberType; + link->next = NULL; + if (lastLink == NULL) + type->memberTypes = link; + else + lastLink->next = link; + lastLink = link; + memberType = memberType->next; + } + return (0); +} + +/** + * xmlSchemaIsDerivedFromBuiltInType: + * @ctxt: the schema parser context + * @type: the type definition + * @valType: the value type + * + * + * Returns 1 if the type has the given value type, or + * is derived from such a type. + */ +static int +xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType) +{ + if (type == NULL) + return (0); + if (WXS_IS_COMPLEX(type)) + return (0); + if (type->type == XML_SCHEMA_TYPE_BASIC) { + if (type->builtInType == valType) + return(1); + if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) || + (type->builtInType == XML_SCHEMAS_ANYTYPE)) + return (0); + return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType)); + } + return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType)); +} + +#if 0 +/** + * xmlSchemaIsDerivedFromBuiltInType: + * @ctxt: the schema parser context + * @type: the type definition + * @valType: the value type + * + * + * Returns 1 if the type has the given value type, or + * is derived from such a type. + */ +static int +xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType) +{ + if (type == NULL) + return (0); + if (WXS_IS_COMPLEX(type)) + return (0); + if (type->type == XML_SCHEMA_TYPE_BASIC) { + if (type->builtInType == valType) + return(1); + return (0); + } else + return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType)); + + return (0); +} +#endif + +static xmlSchemaTypePtr +xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type) +{ + if (type == NULL) + return (NULL); + if (WXS_IS_COMPLEX(type)) + return (NULL); + if (type->type == XML_SCHEMA_TYPE_BASIC) + return(type); + return(xmlSchemaQueryBuiltInType(type->subtypes)); +} + +/** + * xmlSchemaGetPrimitiveType: + * @type: the simpleType definition + * + * Returns the primitive type of the given type or + * NULL in case of error. + */ +static xmlSchemaTypePtr +xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type) +{ + + while (type != NULL) { + /* + * Note that anySimpleType is actually not a primitive type + * but we need that here. + */ + if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) || + (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE)) + return (type); + type = type->baseType; + } + + return (NULL); +} + +#if 0 +/** + * xmlSchemaGetBuiltInTypeAncestor: + * @type: the simpleType definition + * + * Returns the primitive type of the given type or + * NULL in case of error. + */ +static xmlSchemaTypePtr +xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type) +{ + if (WXS_IS_LIST(type) || WXS_IS_UNION(type)) + return (0); + while (type != NULL) { + if (type->type == XML_SCHEMA_TYPE_BASIC) + return (type); + type = type->baseType; + } + + return (NULL); +} +#endif + +/** + * xmlSchemaCloneWildcardNsConstraints: + * @ctxt: the schema parser context + * @dest: the destination wildcard + * @source: the source wildcard + * + * Clones the namespace constraints of source + * and assignes them to dest. + * Returns -1 on internal error, 0 otherwise. + */ +static int +xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt, + xmlSchemaWildcardPtr dest, + xmlSchemaWildcardPtr source) +{ + xmlSchemaWildcardNsPtr cur, tmp, last; + + if ((source == NULL) || (dest == NULL)) + return(-1); + dest->any = source->any; + cur = source->nsSet; + last = NULL; + while (cur != NULL) { + tmp = xmlSchemaNewWildcardNsConstraint(ctxt); + if (tmp == NULL) + return(-1); + tmp->value = cur->value; + if (last == NULL) + dest->nsSet = tmp; + else + last->next = tmp; + last = tmp; + cur = cur->next; + } + if (dest->negNsSet != NULL) + xmlSchemaFreeWildcardNsSet(dest->negNsSet); + if (source->negNsSet != NULL) { + dest->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt); + if (dest->negNsSet == NULL) + return(-1); + dest->negNsSet->value = source->negNsSet->value; + } else + dest->negNsSet = NULL; + return(0); +} + +/** + * xmlSchemaUnionWildcards: + * @ctxt: the schema parser context + * @completeWild: the first wildcard + * @curWild: the second wildcard + * + * Unions the namespace constraints of the given wildcards. + * @completeWild will hold the resulting union. + * Returns a positive error code on failure, -1 in case of an + * internal error, 0 otherwise. + */ +static int +xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt, + xmlSchemaWildcardPtr completeWild, + xmlSchemaWildcardPtr curWild) +{ + xmlSchemaWildcardNsPtr cur, curB, tmp; + + /* + * 1 If O1 and O2 are the same value, then that value must be the + * value. + */ + if ((completeWild->any == curWild->any) && + ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) && + ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) { + + if ((completeWild->negNsSet == NULL) || + (completeWild->negNsSet->value == curWild->negNsSet->value)) { + + if (completeWild->nsSet != NULL) { + int found = 0; + + /* + * Check equality of sets. + */ + cur = completeWild->nsSet; + while (cur != NULL) { + found = 0; + curB = curWild->nsSet; + while (curB != NULL) { + if (cur->value == curB->value) { + found = 1; + break; + } + curB = curB->next; + } + if (!found) + break; + cur = cur->next; + } + if (found) + return(0); + } else + return(0); + } + } + /* + * 2 If either O1 or O2 is any, then any must be the value + */ + if (completeWild->any != curWild->any) { + if (completeWild->any == 0) { + completeWild->any = 1; + if (completeWild->nsSet != NULL) { + xmlSchemaFreeWildcardNsSet(completeWild->nsSet); + completeWild->nsSet = NULL; + } + if (completeWild->negNsSet != NULL) { + xmlFree(completeWild->negNsSet); + completeWild->negNsSet = NULL; + } + } + return (0); + } + /* + * 3 If both O1 and O2 are sets of (namespace names or ·absent·), + * then the union of those sets must be the value. + */ + if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) { + int found; + xmlSchemaWildcardNsPtr start; + + cur = curWild->nsSet; + start = completeWild->nsSet; + while (cur != NULL) { + found = 0; + curB = start; + while (curB != NULL) { + if (cur->value == curB->value) { + found = 1; + break; + } + curB = curB->next; + } + if (!found) { + tmp = xmlSchemaNewWildcardNsConstraint(ctxt); + if (tmp == NULL) + return (-1); + tmp->value = cur->value; + tmp->next = completeWild->nsSet; + completeWild->nsSet = tmp; + } + cur = cur->next; + } + + return(0); + } + /* + * 4 If the two are negations of different values (namespace names + * or ·absent·), then a pair of not and ·absent· must be the value. + */ + if ((completeWild->negNsSet != NULL) && + (curWild->negNsSet != NULL) && + (completeWild->negNsSet->value != curWild->negNsSet->value)) { + completeWild->negNsSet->value = NULL; + + return(0); + } + /* + * 5. + */ + if (((completeWild->negNsSet != NULL) && + (completeWild->negNsSet->value != NULL) && + (curWild->nsSet != NULL)) || + ((curWild->negNsSet != NULL) && + (curWild->negNsSet->value != NULL) && + (completeWild->nsSet != NULL))) { + + int nsFound, absentFound = 0; + + if (completeWild->nsSet != NULL) { + cur = completeWild->nsSet; + curB = curWild->negNsSet; + } else { + cur = curWild->nsSet; + curB = completeWild->negNsSet; + } + nsFound = 0; + while (cur != NULL) { + if (cur->value == NULL) + absentFound = 1; + else if (cur->value == curB->value) + nsFound = 1; + if (nsFound && absentFound) + break; + cur = cur->next; + } + + if (nsFound && absentFound) { + /* + * 5.1 If the set S includes both the negated namespace + * name and ·absent·, then any must be the value. + */ + completeWild->any = 1; + if (completeWild->nsSet != NULL) { + xmlSchemaFreeWildcardNsSet(completeWild->nsSet); + completeWild->nsSet = NULL; + } + if (completeWild->negNsSet != NULL) { + xmlFree(completeWild->negNsSet); + completeWild->negNsSet = NULL; + } + } else if (nsFound && (!absentFound)) { + /* + * 5.2 If the set S includes the negated namespace name + * but not ·absent·, then a pair of not and ·absent· must + * be the value. + */ + if (completeWild->nsSet != NULL) { + xmlSchemaFreeWildcardNsSet(completeWild->nsSet); + completeWild->nsSet = NULL; + } + if (completeWild->negNsSet == NULL) { + completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt); + if (completeWild->negNsSet == NULL) + return (-1); + } + completeWild->negNsSet->value = NULL; + } else if ((!nsFound) && absentFound) { + /* + * 5.3 If the set S includes ·absent· but not the negated + * namespace name, then the union is not expressible. + */ + xmlSchemaPErr(ctxt, completeWild->node, + XML_SCHEMAP_UNION_NOT_EXPRESSIBLE, + "The union of the wilcard is not expressible.\n", + NULL, NULL); + return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE); + } else if ((!nsFound) && (!absentFound)) { + /* + * 5.4 If the set S does not include either the negated namespace + * name or ·absent·, then whichever of O1 or O2 is a pair of not + * and a namespace name must be the value. + */ + if (completeWild->negNsSet == NULL) { + if (completeWild->nsSet != NULL) { + xmlSchemaFreeWildcardNsSet(completeWild->nsSet); + completeWild->nsSet = NULL; + } + completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt); + if (completeWild->negNsSet == NULL) + return (-1); + completeWild->negNsSet->value = curWild->negNsSet->value; + } + } + return (0); + } + /* + * 6. + */ + if (((completeWild->negNsSet != NULL) && + (completeWild->negNsSet->value == NULL) && + (curWild->nsSet != NULL)) || + ((curWild->negNsSet != NULL) && + (curWild->negNsSet->value == NULL) && + (completeWild->nsSet != NULL))) { + + if (completeWild->nsSet != NULL) { + cur = completeWild->nsSet; + } else { + cur = curWild->nsSet; + } + while (cur != NULL) { + if (cur->value == NULL) { + /* + * 6.1 If the set S includes ·absent·, then any must be the + * value. + */ + completeWild->any = 1; + if (completeWild->nsSet != NULL) { + xmlSchemaFreeWildcardNsSet(completeWild->nsSet); + completeWild->nsSet = NULL; + } + if (completeWild->negNsSet != NULL) { + xmlFree(completeWild->negNsSet); + completeWild->negNsSet = NULL; + } + return (0); + } + cur = cur->next; + } + if (completeWild->negNsSet == NULL) { + /* + * 6.2 If the set S does not include ·absent·, then a pair of not + * and ·absent· must be the value. + */ + if (completeWild->nsSet != NULL) { + xmlSchemaFreeWildcardNsSet(completeWild->nsSet); + completeWild->nsSet = NULL; + } + completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt); + if (completeWild->negNsSet == NULL) + return (-1); + completeWild->negNsSet->value = NULL; + } + return (0); + } + return (0); + +} + +/** + * xmlSchemaIntersectWildcards: + * @ctxt: the schema parser context + * @completeWild: the first wildcard + * @curWild: the second wildcard + * + * Intersects the namespace constraints of the given wildcards. + * @completeWild will hold the resulting intersection. + * Returns a positive error code on failure, -1 in case of an + * internal error, 0 otherwise. + */ +static int +xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt, + xmlSchemaWildcardPtr completeWild, + xmlSchemaWildcardPtr curWild) +{ + xmlSchemaWildcardNsPtr cur, curB, prev, tmp; + + /* + * 1 If O1 and O2 are the same value, then that value must be the + * value. + */ + if ((completeWild->any == curWild->any) && + ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) && + ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) { + + if ((completeWild->negNsSet == NULL) || + (completeWild->negNsSet->value == curWild->negNsSet->value)) { + + if (completeWild->nsSet != NULL) { + int found = 0; + + /* + * Check equality of sets. + */ + cur = completeWild->nsSet; + while (cur != NULL) { + found = 0; + curB = curWild->nsSet; + while (curB != NULL) { + if (cur->value == curB->value) { + found = 1; + break; + } + curB = curB->next; + } + if (!found) + break; + cur = cur->next; + } + if (found) + return(0); + } else + return(0); + } + } + /* + * 2 If either O1 or O2 is any, then the other must be the value. + */ + if ((completeWild->any != curWild->any) && (completeWild->any)) { + if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1) + return(-1); + return(0); + } + /* + * 3 If either O1 or O2 is a pair of not and a value (a namespace + * name or ·absent·) and the other is a set of (namespace names or + * ·absent·), then that set, minus the negated value if it was in + * the set, minus ·absent· if it was in the set, must be the value. + */ + if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) || + ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) { + const xmlChar *neg; + + if (completeWild->nsSet == NULL) { + neg = completeWild->negNsSet->value; + if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1) + return(-1); + } else + neg = curWild->negNsSet->value; + /* + * Remove absent and negated. + */ + prev = NULL; + cur = completeWild->nsSet; + while (cur != NULL) { + if (cur->value == NULL) { + if (prev == NULL) + completeWild->nsSet = cur->next; + else + prev->next = cur->next; + xmlFree(cur); + break; + } + prev = cur; + cur = cur->next; + } + if (neg != NULL) { + prev = NULL; + cur = completeWild->nsSet; + while (cur != NULL) { + if (cur->value == neg) { + if (prev == NULL) + completeWild->nsSet = cur->next; + else + prev->next = cur->next; + xmlFree(cur); + break; + } + prev = cur; + cur = cur->next; + } + } + + return(0); + } + /* + * 4 If both O1 and O2 are sets of (namespace names or ·absent·), + * then the intersection of those sets must be the value. + */ + if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) { + int found; + + cur = completeWild->nsSet; + prev = NULL; + while (cur != NULL) { + found = 0; + curB = curWild->nsSet; + while (curB != NULL) { + if (cur->value == curB->value) { + found = 1; + break; + } + curB = curB->next; + } + if (!found) { + if (prev == NULL) + completeWild->nsSet = cur->next; + else + prev->next = cur->next; + tmp = cur->next; + xmlFree(cur); + cur = tmp; + continue; + } + prev = cur; + cur = cur->next; + } + + return(0); + } + /* 5 If the two are negations of different namespace names, + * then the intersection is not expressible + */ + if ((completeWild->negNsSet != NULL) && + (curWild->negNsSet != NULL) && + (completeWild->negNsSet->value != curWild->negNsSet->value) && + (completeWild->negNsSet->value != NULL) && + (curWild->negNsSet->value != NULL)) { + + xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE, + "The intersection of the wilcard is not expressible.\n", + NULL, NULL); + return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE); + } + /* + * 6 If the one is a negation of a namespace name and the other + * is a negation of ·absent·, then the one which is the negation + * of a namespace name must be the value. + */ + if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) && + (completeWild->negNsSet->value != curWild->negNsSet->value) && + (completeWild->negNsSet->value == NULL)) { + completeWild->negNsSet->value = curWild->negNsSet->value; + } + return(0); +} + +/** + * xmlSchemaIsWildcardNsConstraintSubset: + * @ctxt: the schema parser context + * @sub: the first wildcard + * @super: the second wildcard + * + * Schema Component Constraint: Wildcard Subset (cos-ns-subset) + * + * Returns 0 if the namespace constraint of @sub is an intensional + * subset of @super, 1 otherwise. + */ +static int +xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub, + xmlSchemaWildcardPtr super) +{ + /* + * 1 super must be any. + */ + if (super->any) + return (0); + /* + * 2.1 sub must be a pair of not and a namespace name or ·absent·. + * 2.2 super must be a pair of not and the same value. + */ + if ((sub->negNsSet != NULL) && + (super->negNsSet != NULL) && + (sub->negNsSet->value == sub->negNsSet->value)) + return (0); + /* + * 3.1 sub must be a set whose members are either namespace names or ·absent·. + */ + if (sub->nsSet != NULL) { + /* + * 3.2.1 super must be the same set or a superset thereof. + */ + if (super->nsSet != NULL) { + xmlSchemaWildcardNsPtr cur, curB; + int found = 0; + + cur = sub->nsSet; + while (cur != NULL) { + found = 0; + curB = super->nsSet; + while (curB != NULL) { + if (cur->value == curB->value) { + found = 1; + break; + } + curB = curB->next; + } + if (!found) + return (1); + cur = cur->next; + } + if (found) + return (0); + } else if (super->negNsSet != NULL) { + xmlSchemaWildcardNsPtr cur; + /* + * 3.2.2 super must be a pair of not and a namespace name or + * ·absent· and that value must not be in sub's set. + */ + cur = sub->nsSet; + while (cur != NULL) { + if (cur->value == super->negNsSet->value) + return (1); + cur = cur->next; + } + return (0); + } + } + return (1); +} + +static int +xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributeUsePtr attruse, + int *fixed, + const xmlChar **value, + xmlSchemaValPtr *val) +{ + *fixed = 0; + *value = NULL; + if (val != 0) + *val = NULL; + + if (attruse->defValue != NULL) { + *value = attruse->defValue; + if (val != NULL) + *val = attruse->defVal; + if (attruse->flags & XML_SCHEMA_ATTR_USE_FIXED) + *fixed = 1; + return(1); + } else if ((attruse->attrDecl != NULL) && + (attruse->attrDecl->defValue != NULL)) { + *value = attruse->attrDecl->defValue; + if (val != NULL) + *val = attruse->attrDecl->defVal; + if (attruse->attrDecl->flags & XML_SCHEMAS_ATTR_FIXED) + *fixed = 1; + return(1); + } + return(0); +} +/** + * xmlSchemaCheckCVCWildcardNamespace: + * @wild: the wildcard + * @ns: the namespace + * + * Validation Rule: Wildcard allows Namespace Name + * (cvc-wildcard-namespace) + * + * Returns 0 if the given namespace matches the wildcard, + * 1 otherwise and -1 on API errors. + */ +static int +xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild, + const xmlChar* ns) +{ + if (wild == NULL) + return(-1); + + if (wild->any) + return(0); + else if (wild->nsSet != NULL) { + xmlSchemaWildcardNsPtr cur; + + cur = wild->nsSet; + while (cur != NULL) { + if (xmlStrEqual(cur->value, ns)) + return(0); + cur = cur->next; + } + } else if ((wild->negNsSet != NULL) && (ns != NULL) && + (!xmlStrEqual(wild->negNsSet->value, ns))) + return(0); + + return(1); +} + +#define XML_SCHEMA_ACTION_DERIVE 0 +#define XML_SCHEMA_ACTION_REDEFINE 1 + +#define WXS_ACTION_STR(a) \ +((a) == XML_SCHEMA_ACTION_DERIVE) ? (const xmlChar *) "base" : (const xmlChar *) "redefined" + +/* +* Schema Component Constraint: +* Derivation Valid (Restriction, Complex) +* derivation-ok-restriction (2) - (4) +* +* ATTENTION: +* In XML Schema 1.1 this will be: +* Validation Rule: +* Checking complex type subsumption (practicalSubsumption) (1, 2 and 3) +* +*/ +static int +xmlSchemaCheckDerivationOKRestriction2to4(xmlSchemaParserCtxtPtr pctxt, + int action, + xmlSchemaBasicItemPtr item, + xmlSchemaBasicItemPtr baseItem, + xmlSchemaItemListPtr uses, + xmlSchemaItemListPtr baseUses, + xmlSchemaWildcardPtr wild, + xmlSchemaWildcardPtr baseWild) +{ + xmlSchemaAttributeUsePtr cur = NULL, bcur; + int i, j, found; /* err = 0; */ + const xmlChar *bEffValue; + int effFixed; + + if (uses != NULL) { + for (i = 0; i < uses->nbItems; i++) { + cur = uses->items[i]; + found = 0; + if (baseUses == NULL) + goto not_found; + for (j = 0; j < baseUses->nbItems; j++) { + bcur = baseUses->items[j]; + if ((WXS_ATTRUSE_DECL_NAME(cur) == + WXS_ATTRUSE_DECL_NAME(bcur)) && + (WXS_ATTRUSE_DECL_TNS(cur) == + WXS_ATTRUSE_DECL_TNS(bcur))) + { + /* + * (2.1) "If there is an attribute use in the {attribute + * uses} of the {base type definition} (call this B) whose + * {attribute declaration} has the same {name} and {target + * namespace}, then all of the following must be true:" + */ + found = 1; + + if ((cur->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) && + (bcur->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) + { + xmlChar *str = NULL; + /* + * (2.1.1) "one of the following must be true:" + * (2.1.1.1) "B's {required} is false." + * (2.1.1.2) "R's {required} is true." + */ + xmlSchemaPAttrUseErr4(pctxt, + XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1, + WXS_ITEM_NODE(item), item, cur, + "The 'optional' attribute use is inconsistent " + "with the corresponding 'required' attribute use of " + "the %s %s", + WXS_ACTION_STR(action), + xmlSchemaGetComponentDesignation(&str, baseItem), + NULL, NULL); + FREE_AND_NULL(str); + /* err = pctxt->err; */ + } else if (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt, + WXS_ATTRUSE_TYPEDEF(cur), + WXS_ATTRUSE_TYPEDEF(bcur), 0) != 0) + { + xmlChar *strA = NULL, *strB = NULL, *strC = NULL; + + /* + * SPEC (2.1.2) "R's {attribute declaration}'s + * {type definition} must be validly derived from + * B's {type definition} given the empty set as + * defined in Type Derivation OK (Simple) (§3.14.6)." + */ + xmlSchemaPAttrUseErr4(pctxt, + XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2, + WXS_ITEM_NODE(item), item, cur, + "The attribute declaration's %s " + "is not validly derived from " + "the corresponding %s of the " + "attribute declaration in the %s %s", + xmlSchemaGetComponentDesignation(&strA, + WXS_ATTRUSE_TYPEDEF(cur)), + xmlSchemaGetComponentDesignation(&strB, + WXS_ATTRUSE_TYPEDEF(bcur)), + WXS_ACTION_STR(action), + xmlSchemaGetComponentDesignation(&strC, baseItem)); + /* xmlSchemaGetComponentDesignation(&str, baseItem), */ + FREE_AND_NULL(strA); + FREE_AND_NULL(strB); + FREE_AND_NULL(strC); + /* err = pctxt->err; */ + } else { + /* + * 2.1.3 [Definition:] Let the effective value + * constraint of an attribute use be its {value + * constraint}, if present, otherwise its {attribute + * declaration}'s {value constraint} . + */ + xmlSchemaGetEffectiveValueConstraint(bcur, + &effFixed, &bEffValue, NULL); + /* + * 2.1.3 ... one of the following must be true + * + * 2.1.3.1 B's ·effective value constraint· is + * ·absent· or default. + */ + if ((bEffValue != NULL) && + (effFixed == 1)) { + const xmlChar *rEffValue = NULL; + + xmlSchemaGetEffectiveValueConstraint(bcur, + &effFixed, &rEffValue, NULL); + /* + * 2.1.3.2 R's ·effective value constraint· is + * fixed with the same string as B's. + * MAYBE TODO: Compare the computed values. + * Hmm, it says "same string" so + * string-equality might really be sufficient. + */ + if ((effFixed == 0) || + (! WXS_ARE_DEFAULT_STR_EQUAL(rEffValue, bEffValue))) + { + xmlChar *str = NULL; + + xmlSchemaPAttrUseErr4(pctxt, + XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3, + WXS_ITEM_NODE(item), item, cur, + "The effective value constraint of the " + "attribute use is inconsistent with " + "its correspondent in the %s %s", + WXS_ACTION_STR(action), + xmlSchemaGetComponentDesignation(&str, + baseItem), + NULL, NULL); + FREE_AND_NULL(str); + /* err = pctxt->err; */ + } + } + } + break; + } + } +not_found: + if (!found) { + /* + * (2.2) "otherwise the {base type definition} must have an + * {attribute wildcard} and the {target namespace} of the + * R's {attribute declaration} must be ·valid· with respect + * to that wildcard, as defined in Wildcard allows Namespace + * Name (§3.10.4)." + */ + if ((baseWild == NULL) || + (xmlSchemaCheckCVCWildcardNamespace(baseWild, + (WXS_ATTRUSE_DECL(cur))->targetNamespace) != 0)) + { + xmlChar *str = NULL; + + xmlSchemaPAttrUseErr4(pctxt, + XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2, + WXS_ITEM_NODE(item), item, cur, + "Neither a matching attribute use, " + "nor a matching wildcard exists in the %s %s", + WXS_ACTION_STR(action), + xmlSchemaGetComponentDesignation(&str, baseItem), + NULL, NULL); + FREE_AND_NULL(str); + /* err = pctxt->err; */ + } + } + } + } + /* + * SPEC derivation-ok-restriction (3): + * (3) "For each attribute use in the {attribute uses} of the {base type + * definition} whose {required} is true, there must be an attribute + * use with an {attribute declaration} with the same {name} and + * {target namespace} as its {attribute declaration} in the {attribute + * uses} of the complex type definition itself whose {required} is true. + */ + if (baseUses != NULL) { + for (j = 0; j < baseUses->nbItems; j++) { + bcur = baseUses->items[j]; + if (bcur->occurs != XML_SCHEMAS_ATTR_USE_REQUIRED) + continue; + found = 0; + if (uses != NULL) { + for (i = 0; i < uses->nbItems; i++) { + cur = uses->items[i]; + if ((WXS_ATTRUSE_DECL_NAME(cur) == + WXS_ATTRUSE_DECL_NAME(bcur)) && + (WXS_ATTRUSE_DECL_TNS(cur) == + WXS_ATTRUSE_DECL_TNS(bcur))) { + found = 1; + break; + } + } + } + if (!found) { + xmlChar *strA = NULL, *strB = NULL; + + xmlSchemaCustomErr4(ACTXT_CAST pctxt, + XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3, + NULL, item, + "A matching attribute use for the " + "'required' %s of the %s %s is missing", + xmlSchemaGetComponentDesignation(&strA, bcur), + WXS_ACTION_STR(action), + xmlSchemaGetComponentDesignation(&strB, baseItem), + NULL); + FREE_AND_NULL(strA); + FREE_AND_NULL(strB); + } + } + } + /* + * derivation-ok-restriction (4) + */ + if (wild != NULL) { + /* + * (4) "If there is an {attribute wildcard}, all of the + * following must be true:" + */ + if (baseWild == NULL) { + xmlChar *str = NULL; + + /* + * (4.1) "The {base type definition} must also have one." + */ + xmlSchemaCustomErr4(ACTXT_CAST pctxt, + XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1, + NULL, item, + "The %s has an attribute wildcard, " + "but the %s %s '%s' does not have one", + WXS_ITEM_TYPE_NAME(item), + WXS_ACTION_STR(action), + WXS_ITEM_TYPE_NAME(baseItem), + xmlSchemaGetComponentQName(&str, baseItem)); + FREE_AND_NULL(str); + return(pctxt->err); + } else if ((baseWild->any == 0) && + xmlSchemaCheckCOSNSSubset(wild, baseWild)) + { + xmlChar *str = NULL; + /* + * (4.2) "The complex type definition's {attribute wildcard}'s + * {namespace constraint} must be a subset of the {base type + * definition}'s {attribute wildcard}'s {namespace constraint}, + * as defined by Wildcard Subset (§3.10.6)." + */ + xmlSchemaCustomErr4(ACTXT_CAST pctxt, + XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2, + NULL, item, + "The attribute wildcard is not a valid " + "subset of the wildcard in the %s %s '%s'", + WXS_ACTION_STR(action), + WXS_ITEM_TYPE_NAME(baseItem), + xmlSchemaGetComponentQName(&str, baseItem), + NULL); + FREE_AND_NULL(str); + return(pctxt->err); + } + /* 4.3 Unless the {base type definition} is the ·ur-type + * definition·, the complex type definition's {attribute + * wildcard}'s {process contents} must be identical to or + * stronger than the {base type definition}'s {attribute + * wildcard}'s {process contents}, where strict is stronger + * than lax is stronger than skip. + */ + if ((! WXS_IS_ANYTYPE(baseItem)) && + (wild->processContents < baseWild->processContents)) { + xmlChar *str = NULL; + xmlSchemaCustomErr4(ACTXT_CAST pctxt, + XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3, + NULL, baseItem, + "The {process contents} of the attribute wildcard is " + "weaker than the one in the %s %s '%s'", + WXS_ACTION_STR(action), + WXS_ITEM_TYPE_NAME(baseItem), + xmlSchemaGetComponentQName(&str, baseItem), + NULL); + FREE_AND_NULL(str) + return(pctxt->err); + } + } + return(0); +} + + +static int +xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt, + xmlSchemaBasicItemPtr item, + xmlSchemaWildcardPtr *completeWild, + xmlSchemaItemListPtr list, + xmlSchemaItemListPtr prohibs); +/** + * xmlSchemaFixupTypeAttributeUses: + * @ctxt: the schema parser context + * @type: the complex type definition + * + * + * Builds the wildcard and the attribute uses on the given complex type. + * Returns -1 if an internal error occurs, 0 otherwise. + * + * ATTENTION TODO: Experimantally this uses pointer comparisons for + * strings, so recheck this if we start to hardcode some schemata, since + * they might not be in the same dict. + * NOTE: It is allowed to "extend" the xs:anyType type. + */ +static int +xmlSchemaFixupTypeAttributeUses(xmlSchemaParserCtxtPtr pctxt, + xmlSchemaTypePtr type) +{ + xmlSchemaTypePtr baseType = NULL; + xmlSchemaAttributeUsePtr use; + xmlSchemaItemListPtr uses, baseUses, prohibs = NULL; + + if (type->baseType == NULL) { + PERROR_INT("xmlSchemaFixupTypeAttributeUses", + "no base type"); + return (-1); + } + baseType = type->baseType; + if (WXS_IS_TYPE_NOT_FIXED(baseType)) + if (xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt) == -1) + return(-1); + + uses = type->attrUses; + baseUses = baseType->attrUses; + /* + * Expand attribute group references. And build the 'complete' + * wildcard, i.e. intersect multiple wildcards. + * Move attribute prohibitions into a separate list. + */ + if (uses != NULL) { + if (WXS_IS_RESTRICTION(type)) { + /* + * This one will transfer all attr. prohibitions + * into pctxt->attrProhibs. + */ + if (xmlSchemaExpandAttributeGroupRefs(pctxt, + WXS_BASIC_CAST type, &(type->attributeWildcard), uses, + pctxt->attrProhibs) == -1) + { + PERROR_INT("xmlSchemaFixupTypeAttributeUses", + "failed to expand attributes"); + } + if (pctxt->attrProhibs->nbItems != 0) + prohibs = pctxt->attrProhibs; + } else { + if (xmlSchemaExpandAttributeGroupRefs(pctxt, + WXS_BASIC_CAST type, &(type->attributeWildcard), uses, + NULL) == -1) + { + PERROR_INT("xmlSchemaFixupTypeAttributeUses", + "failed to expand attributes"); + } + } + } + /* + * Inherit the attribute uses of the base type. + */ + if (baseUses != NULL) { + int i, j; + xmlSchemaAttributeUseProhibPtr pro; + + if (WXS_IS_RESTRICTION(type)) { + int usesCount; + xmlSchemaAttributeUsePtr tmp; + + if (uses != NULL) + usesCount = uses->nbItems; + else + usesCount = 0; + + /* Restriction. */ + for (i = 0; i < baseUses->nbItems; i++) { + use = baseUses->items[i]; + if (prohibs) { + /* + * Filter out prohibited uses. + */ + for (j = 0; j < prohibs->nbItems; j++) { + pro = prohibs->items[j]; + if ((WXS_ATTRUSE_DECL_NAME(use) == pro->name) && + (WXS_ATTRUSE_DECL_TNS(use) == + pro->targetNamespace)) + { + goto inherit_next; + } + } + } + if (usesCount) { + /* + * Filter out existing uses. + */ + for (j = 0; j < usesCount; j++) { + tmp = uses->items[j]; + if ((WXS_ATTRUSE_DECL_NAME(use) == + WXS_ATTRUSE_DECL_NAME(tmp)) && + (WXS_ATTRUSE_DECL_TNS(use) == + WXS_ATTRUSE_DECL_TNS(tmp))) + { + goto inherit_next; + } + } + } + if (uses == NULL) { + type->attrUses = xmlSchemaItemListCreate(); + if (type->attrUses == NULL) + goto exit_failure; + uses = type->attrUses; + } + xmlSchemaItemListAddSize(uses, 2, use); +inherit_next: {} + } + } else { + /* Extension. */ + for (i = 0; i < baseUses->nbItems; i++) { + use = baseUses->items[i]; + if (uses == NULL) { + type->attrUses = xmlSchemaItemListCreate(); + if (type->attrUses == NULL) + goto exit_failure; + uses = type->attrUses; + } + xmlSchemaItemListAddSize(uses, baseUses->nbItems, use); + } + } + } + /* + * Shrink attr. uses. + */ + if (uses) { + if (uses->nbItems == 0) { + xmlSchemaItemListFree(uses); + type->attrUses = NULL; + } + /* + * TODO: We could shrink the size of the array + * to fit the actual number of items. + */ + } + /* + * Compute the complete wildcard. + */ + if (WXS_IS_EXTENSION(type)) { + if (baseType->attributeWildcard != NULL) { + /* + * (3.2.2.1) "If the ·base wildcard· is non-·absent·, then + * the appropriate case among the following:" + */ + if (type->attributeWildcard != NULL) { + /* + * Union the complete wildcard with the base wildcard. + * SPEC {attribute wildcard} + * (3.2.2.1.2) "otherwise a wildcard whose {process contents} + * and {annotation} are those of the ·complete wildcard·, + * and whose {namespace constraint} is the intensional union + * of the {namespace constraint} of the ·complete wildcard· + * and of the ·base wildcard·, as defined in Attribute + * Wildcard Union (§3.10.6)." + */ + if (xmlSchemaUnionWildcards(pctxt, type->attributeWildcard, + baseType->attributeWildcard) == -1) + goto exit_failure; + } else { + /* + * (3.2.2.1.1) "If the ·complete wildcard· is ·absent·, + * then the ·base wildcard·." + */ + type->attributeWildcard = baseType->attributeWildcard; + } + } else { + /* + * (3.2.2.2) "otherwise (the ·base wildcard· is ·absent·) the + * ·complete wildcard" + * NOOP + */ + } + } else { + /* + * SPEC {attribute wildcard} + * (3.1) "If the alternative is chosen, then the + * ·complete wildcard·;" + * NOOP + */ + } + + return (0); + +exit_failure: + return(-1); +} + +/** + * xmlSchemaTypeFinalContains: + * @schema: the schema + * @type: the type definition + * @final: the final + * + * Evaluates if a type definition contains the given "final". + * This does take "finalDefault" into account as well. + * + * Returns 1 if the type does containt the given "final", + * 0 otherwise. + */ +static int +xmlSchemaTypeFinalContains(xmlSchemaTypePtr type, int final) +{ + if (type == NULL) + return (0); + if (type->flags & final) + return (1); + else + return (0); +} + +/** + * xmlSchemaGetUnionSimpleTypeMemberTypes: + * @type: the Union Simple Type + * + * Returns a list of member types of @type if existing, + * returns NULL otherwise. + */ +static xmlSchemaTypeLinkPtr +xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type) +{ + while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) { + if (type->memberTypes != NULL) + return (type->memberTypes); + else + type = type->baseType; + } + return (NULL); +} + +/** + * xmlSchemaGetParticleTotalRangeMin: + * @particle: the particle + * + * Schema Component Constraint: Effective Total Range + * (all and sequence) + (choice) + * + * Returns the minimun Effective Total Range. + */ +static int +xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle) +{ + if ((particle->children == NULL) || + (particle->minOccurs == 0)) + return (0); + if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) { + int min = -1, cur; + xmlSchemaParticlePtr part = + (xmlSchemaParticlePtr) particle->children->children; + + if (part == NULL) + return (0); + while (part != NULL) { + if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) || + (part->children->type == XML_SCHEMA_TYPE_ANY)) + cur = part->minOccurs; + else + cur = xmlSchemaGetParticleTotalRangeMin(part); + if (cur == 0) + return (0); + if ((min > cur) || (min == -1)) + min = cur; + part = (xmlSchemaParticlePtr) part->next; + } + return (particle->minOccurs * min); + } else { + /* and */ + int sum = 0; + xmlSchemaParticlePtr part = + (xmlSchemaParticlePtr) particle->children->children; + + if (part == NULL) + return (0); + do { + if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) || + (part->children->type == XML_SCHEMA_TYPE_ANY)) + sum += part->minOccurs; + else + sum += xmlSchemaGetParticleTotalRangeMin(part); + part = (xmlSchemaParticlePtr) part->next; + } while (part != NULL); + return (particle->minOccurs * sum); + } +} + +/** + * xmlSchemaGetParticleTotalRangeMax: + * @particle: the particle + * + * Schema Component Constraint: Effective Total Range + * (all and sequence) + (choice) + * + * Returns the maximum Effective Total Range. + */ +static int +xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle) +{ + if ((particle->children == NULL) || + (particle->children->children == NULL)) + return (0); + if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) { + int max = -1, cur; + xmlSchemaParticlePtr part = + (xmlSchemaParticlePtr) particle->children->children; + + for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) { + if (part->children == NULL) + continue; + if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) || + (part->children->type == XML_SCHEMA_TYPE_ANY)) + cur = part->maxOccurs; + else + cur = xmlSchemaGetParticleTotalRangeMax(part); + if (cur == UNBOUNDED) + return (UNBOUNDED); + if ((max < cur) || (max == -1)) + max = cur; + } + /* TODO: Handle overflows? */ + return (particle->maxOccurs * max); + } else { + /* and */ + int sum = 0, cur; + xmlSchemaParticlePtr part = + (xmlSchemaParticlePtr) particle->children->children; + + for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) { + if (part->children == NULL) + continue; + if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) || + (part->children->type == XML_SCHEMA_TYPE_ANY)) + cur = part->maxOccurs; + else + cur = xmlSchemaGetParticleTotalRangeMax(part); + if (cur == UNBOUNDED) + return (UNBOUNDED); + if ((cur > 0) && (particle->maxOccurs == UNBOUNDED)) + return (UNBOUNDED); + sum += cur; + } + /* TODO: Handle overflows? */ + return (particle->maxOccurs * sum); + } +} + +/** + * xmlSchemaIsParticleEmptiable: + * @particle: the particle + * + * Schema Component Constraint: Particle Emptiable + * Checks whether the given particle is emptiable. + * + * Returns 1 if emptiable, 0 otherwise. + */ +static int +xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle) +{ + /* + * SPEC (1) "Its {min occurs} is 0." + */ + if ((particle == NULL) || (particle->minOccurs == 0) || + (particle->children == NULL)) + return (1); + /* + * SPEC (2) "Its {term} is a group and the minimum part of the + * effective total range of that group, [...] is 0." + */ + if (WXS_IS_MODEL_GROUP(particle->children)) { + if (xmlSchemaGetParticleTotalRangeMin(particle) == 0) + return (1); + } + return (0); +} + +/** + * xmlSchemaCheckCOSSTDerivedOK: + * @actxt: a context + * @type: the derived simple type definition + * @baseType: the base type definition + * @subset: the subset of ('restriction', ect.) + * + * Schema Component Constraint: + * Type Derivation OK (Simple) (cos-st-derived-OK) + * + * Checks wheter @type can be validly + * derived from @baseType. + * + * Returns 0 on success, an positive error code otherwise. + */ +static int +xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr actxt, + xmlSchemaTypePtr type, + xmlSchemaTypePtr baseType, + int subset) +{ + /* + * 1 They are the same type definition. + * TODO: The identy check might have to be more complex than this. + */ + if (type == baseType) + return (0); + /* + * 2.1 restriction is not in the subset, or in the {final} + * of its own {base type definition}; + * + * NOTE that this will be used also via "xsi:type". + * + * TODO: Revise this, it looks strange. How can the "type" + * not be fixed or *in* fixing? + */ + if (WXS_IS_TYPE_NOT_FIXED(type)) + if (xmlSchemaTypeFixup(type, actxt) == -1) + return(-1); + if (WXS_IS_TYPE_NOT_FIXED(baseType)) + if (xmlSchemaTypeFixup(baseType, actxt) == -1) + return(-1); + if ((subset & SUBSET_RESTRICTION) || + (xmlSchemaTypeFinalContains(type->baseType, + XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) { + return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1); + } + /* 2.2 */ + if (type->baseType == baseType) { + /* + * 2.2.1 D's ·base type definition· is B. + */ + return (0); + } + /* + * 2.2.2 D's ·base type definition· is not the ·ur-type definition· + * and is validly derived from B given the subset, as defined by this + * constraint. + */ + if ((! WXS_IS_ANYTYPE(type->baseType)) && + (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType, + baseType, subset) == 0)) { + return (0); + } + /* + * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type + * definition·. + */ + if (WXS_IS_ANY_SIMPLE_TYPE(baseType) && + (WXS_IS_LIST(type) || WXS_IS_UNION(type))) { + return (0); + } + /* + * 2.2.4 B's {variety} is union and D is validly derived from a type + * definition in B's {member type definitions} given the subset, as + * defined by this constraint. + * + * NOTE: This seems not to involve built-in types, since there is no + * built-in Union Simple Type. + */ + if (WXS_IS_UNION(baseType)) { + xmlSchemaTypeLinkPtr cur; + + cur = baseType->memberTypes; + while (cur != NULL) { + if (WXS_IS_TYPE_NOT_FIXED(cur->type)) + if (xmlSchemaTypeFixup(cur->type, actxt) == -1) + return(-1); + if (xmlSchemaCheckCOSSTDerivedOK(actxt, + type, cur->type, subset) == 0) + { + /* + * It just has to be validly derived from at least one + * member-type. + */ + return (0); + } + cur = cur->next; + } + } + return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2); +} + +/** + * xmlSchemaCheckTypeDefCircularInternal: + * @pctxt: the schema parser context + * @ctxtType: the type definition + * @ancestor: an ancestor of @ctxtType + * + * Checks st-props-correct (2) + ct-props-correct (3). + * Circular type definitions are not allowed. + * + * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is + * circular, 0 otherwise. + */ +static int +xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt, + xmlSchemaTypePtr ctxtType, + xmlSchemaTypePtr ancestor) +{ + int ret; + + if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC)) + return (0); + + if (ctxtType == ancestor) { + xmlSchemaPCustomErr(pctxt, + XML_SCHEMAP_ST_PROPS_CORRECT_2, + WXS_BASIC_CAST ctxtType, WXS_ITEM_NODE(ctxtType), + "The definition is circular", NULL); + return (XML_SCHEMAP_ST_PROPS_CORRECT_2); + } + if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) { + /* + * Avoid inifinite recursion on circular types not yet checked. + */ + return (0); + } + ancestor->flags |= XML_SCHEMAS_TYPE_MARKED; + ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType, + ancestor->baseType); + ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED; + return (ret); +} + +/** + * xmlSchemaCheckTypeDefCircular: + * @item: the complex/simple type definition + * @ctxt: the parser context + * @name: the name + * + * Checks for circular type definitions. + */ +static void +xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item, + xmlSchemaParserCtxtPtr ctxt) +{ + if ((item == NULL) || + (item->type == XML_SCHEMA_TYPE_BASIC) || + (item->baseType == NULL)) + return; + xmlSchemaCheckTypeDefCircularInternal(ctxt, item, + item->baseType); +} + +/* +* Simple Type Definition Representation OK (src-simple-type) 4 +* +* "4 Circular union type definition is disallowed. That is, if the +* alternative is chosen, there must not be any entries in the +* memberTypes [attribute] at any depth which resolve to the component +* corresponding to the ." +* +* Note that this should work on the *representation* of a component, +* thus assumes any union types in the member types not being yet +* substituted. At this stage we need the variety of the types +* to be already computed. +*/ +static int +xmlSchemaCheckUnionTypeDefCircularRecur(xmlSchemaParserCtxtPtr pctxt, + xmlSchemaTypePtr ctxType, + xmlSchemaTypeLinkPtr members) +{ + xmlSchemaTypeLinkPtr member; + xmlSchemaTypePtr memberType; + + member = members; + while (member != NULL) { + memberType = member->type; + while ((memberType != NULL) && + (memberType->type != XML_SCHEMA_TYPE_BASIC)) { + if (memberType == ctxType) { + xmlSchemaPCustomErr(pctxt, + XML_SCHEMAP_SRC_SIMPLE_TYPE_4, + WXS_BASIC_CAST ctxType, NULL, + "The union type definition is circular", NULL); + return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4); + } + if ((WXS_IS_UNION(memberType)) && + ((memberType->flags & XML_SCHEMAS_TYPE_MARKED) == 0)) + { + int res; + memberType->flags |= XML_SCHEMAS_TYPE_MARKED; + res = xmlSchemaCheckUnionTypeDefCircularRecur(pctxt, + ctxType, + xmlSchemaGetUnionSimpleTypeMemberTypes(memberType)); + memberType->flags ^= XML_SCHEMAS_TYPE_MARKED; + if (res != 0) + return(res); + } + memberType = memberType->baseType; + } + member = member->next; + } + return(0); +} + +static int +xmlSchemaCheckUnionTypeDefCircular(xmlSchemaParserCtxtPtr pctxt, + xmlSchemaTypePtr type) +{ + if (! WXS_IS_UNION(type)) + return(0); + return(xmlSchemaCheckUnionTypeDefCircularRecur(pctxt, type, + type->memberTypes)); +} + +/** + * xmlSchemaResolveTypeReferences: + * @item: the complex/simple type definition + * @ctxt: the parser context + * @name: the name + * + * Resolvese type definition references + */ +static void +xmlSchemaResolveTypeReferences(xmlSchemaTypePtr typeDef, + xmlSchemaParserCtxtPtr ctxt) +{ + if (typeDef == NULL) + return; + + /* + * Resolve the base type. + */ + if (typeDef->baseType == NULL) { + typeDef->baseType = xmlSchemaGetType(ctxt->schema, + typeDef->base, typeDef->baseNs); + if (typeDef->baseType == NULL) { + xmlSchemaPResCompAttrErr(ctxt, + XML_SCHEMAP_SRC_RESOLVE, + WXS_BASIC_CAST typeDef, typeDef->node, + "base", typeDef->base, typeDef->baseNs, + XML_SCHEMA_TYPE_SIMPLE, NULL); + return; + } + } + if (WXS_IS_SIMPLE(typeDef)) { + if (WXS_IS_UNION(typeDef)) { + /* + * Resolve the memberTypes. + */ + xmlSchemaResolveUnionMemberTypes(ctxt, typeDef); + return; + } else if (WXS_IS_LIST(typeDef)) { + /* + * Resolve the itemType. + */ + if ((typeDef->subtypes == NULL) && (typeDef->base != NULL)) { + + typeDef->subtypes = xmlSchemaGetType(ctxt->schema, + typeDef->base, typeDef->baseNs); + + if ((typeDef->subtypes == NULL) || + (! WXS_IS_SIMPLE(typeDef->subtypes))) + { + typeDef->subtypes = NULL; + xmlSchemaPResCompAttrErr(ctxt, + XML_SCHEMAP_SRC_RESOLVE, + WXS_BASIC_CAST typeDef, typeDef->node, + "itemType", typeDef->base, typeDef->baseNs, + XML_SCHEMA_TYPE_SIMPLE, NULL); + } + } + return; + } + } + /* + * The ball of letters below means, that if we have a particle + * which has a QName-helper component as its {term}, we want + * to resolve it... + */ + else if ((WXS_TYPE_CONTENTTYPE(typeDef) != NULL) && + ((WXS_TYPE_CONTENTTYPE(typeDef))->type == + XML_SCHEMA_TYPE_PARTICLE) && + (WXS_TYPE_PARTICLE_TERM(typeDef) != NULL) && + ((WXS_TYPE_PARTICLE_TERM(typeDef))->type == + XML_SCHEMA_EXTRA_QNAMEREF)) + { + xmlSchemaQNameRefPtr ref = + WXS_QNAME_CAST WXS_TYPE_PARTICLE_TERM(typeDef); + xmlSchemaModelGroupDefPtr groupDef; + + /* + * URGENT TODO: Test this. + */ + WXS_TYPE_PARTICLE_TERM(typeDef) = NULL; + /* + * Resolve the MG definition reference. + */ + groupDef = + WXS_MODEL_GROUPDEF_CAST xmlSchemaGetNamedComponent(ctxt->schema, + ref->itemType, ref->name, ref->targetNamespace); + if (groupDef == NULL) { + xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE, + NULL, WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)), + "ref", ref->name, ref->targetNamespace, ref->itemType, + NULL); + /* Remove the particle. */ + WXS_TYPE_CONTENTTYPE(typeDef) = NULL; + } else if (WXS_MODELGROUPDEF_MODEL(groupDef) == NULL) + /* Remove the particle. */ + WXS_TYPE_CONTENTTYPE(typeDef) = NULL; + else { + /* + * Assign the MG definition's {model group} to the + * particle's {term}. + */ + WXS_TYPE_PARTICLE_TERM(typeDef) = WXS_MODELGROUPDEF_MODEL(groupDef); + + if (WXS_MODELGROUPDEF_MODEL(groupDef)->type == XML_SCHEMA_TYPE_ALL) { + /* + * SPEC cos-all-limited (1.2) + * "1.2 the {term} property of a particle with + * {max occurs}=1 which is part of a pair which constitutes + * the {content type} of a complex type definition." + */ + if ((WXS_TYPE_PARTICLE(typeDef))->maxOccurs != 1) { + xmlSchemaCustomErr(ACTXT_CAST ctxt, + /* TODO: error code */ + XML_SCHEMAP_COS_ALL_LIMITED, + WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)), NULL, + "The particle's {max occurs} must be 1, since the " + "reference resolves to an 'all' model group", + NULL, NULL); + } + } + } + } +} + + + +/** + * xmlSchemaCheckSTPropsCorrect: + * @ctxt: the schema parser context + * @type: the simple type definition + * + * Checks st-props-correct. + * + * Returns 0 if the properties are correct, + * if not, a positive error code and -1 on internal + * errors. + */ +static int +xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt, + xmlSchemaTypePtr type) +{ + xmlSchemaTypePtr baseType = type->baseType; + xmlChar *str = NULL; + + /* STATE: error funcs converted. */ + /* + * Schema Component Constraint: Simple Type Definition Properties Correct + * + * NOTE: This is somehow redundant, since we actually built a simple type + * to have all the needed information; this acts as an self test. + */ + /* Base type: If the datatype has been ·derived· by ·restriction· + * then the Simple Type Definition component from which it is ·derived·, + * otherwise the Simple Type Definition for anySimpleType (§4.1.6). + */ + if (baseType == NULL) { + /* + * TODO: Think about: "modulo the impact of Missing + * Sub-components (§5.3)." + */ + xmlSchemaPCustomErr(ctxt, + XML_SCHEMAP_ST_PROPS_CORRECT_1, + WXS_BASIC_CAST type, NULL, + "No base type existent", NULL); + return (XML_SCHEMAP_ST_PROPS_CORRECT_1); + + } + if (! WXS_IS_SIMPLE(baseType)) { + xmlSchemaPCustomErr(ctxt, + XML_SCHEMAP_ST_PROPS_CORRECT_1, + WXS_BASIC_CAST type, NULL, + "The base type '%s' is not a simple type", + xmlSchemaGetComponentQName(&str, baseType)); + FREE_AND_NULL(str) + return (XML_SCHEMAP_ST_PROPS_CORRECT_1); + } + if ( (WXS_IS_LIST(type) || WXS_IS_UNION(type)) && + (WXS_IS_RESTRICTION(type) == 0) && + (! WXS_IS_ANY_SIMPLE_TYPE(baseType))) { + xmlSchemaPCustomErr(ctxt, + XML_SCHEMAP_ST_PROPS_CORRECT_1, + WXS_BASIC_CAST type, NULL, + "A type, derived by list or union, must have" + "the simple ur-type definition as base type, not '%s'", + xmlSchemaGetComponentQName(&str, baseType)); + FREE_AND_NULL(str) + return (XML_SCHEMAP_ST_PROPS_CORRECT_1); + } + /* + * Variety: One of {atomic, list, union}. + */ + if ((! WXS_IS_ATOMIC(type)) && (! WXS_IS_UNION(type)) && + (! WXS_IS_LIST(type))) { + xmlSchemaPCustomErr(ctxt, + XML_SCHEMAP_ST_PROPS_CORRECT_1, + WXS_BASIC_CAST type, NULL, + "The variety is absent", NULL); + return (XML_SCHEMAP_ST_PROPS_CORRECT_1); + } + /* TODO: Finish this. Hmm, is this finished? */ + + /* + * 3 The {final} of the {base type definition} must not contain restriction. + */ + if (xmlSchemaTypeFinalContains(baseType, + XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) { + xmlSchemaPCustomErr(ctxt, + XML_SCHEMAP_ST_PROPS_CORRECT_3, + WXS_BASIC_CAST type, NULL, + "The 'final' of its base type '%s' must not contain " + "'restriction'", + xmlSchemaGetComponentQName(&str, baseType)); + FREE_AND_NULL(str) + return (XML_SCHEMAP_ST_PROPS_CORRECT_3); + } + + /* + * 2 All simple type definitions must be derived ultimately from the ·simple + * ur-type definition (so· circular definitions are disallowed). That is, it + * must be possible to reach a built-in primitive datatype or the ·simple + * ur-type definition· by repeatedly following the {base type definition}. + * + * NOTE: this is done in xmlSchemaCheckTypeDefCircular(). + */ + return (0); +} + +/** + * xmlSchemaCheckCOSSTRestricts: + * @ctxt: the schema parser context + * @type: the simple type definition + * + * Schema Component Constraint: + * Derivation Valid (Restriction, Simple) (cos-st-restricts) + + * Checks if the given @type (simpleType) is derived validly by restriction. + * STATUS: + * + * Returns -1 on internal errors, 0 if the type is validly derived, + * a positive error code otherwise. + */ +static int +xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt, + xmlSchemaTypePtr type) +{ + xmlChar *str = NULL; + + if (type->type != XML_SCHEMA_TYPE_SIMPLE) { + PERROR_INT("xmlSchemaCheckCOSSTRestricts", + "given type is not a user-derived simpleType"); + return (-1); + } + + if (WXS_IS_ATOMIC(type)) { + xmlSchemaTypePtr primitive; + /* + * 1.1 The {base type definition} must be an atomic simple + * type definition or a built-in primitive datatype. + */ + if (! WXS_IS_ATOMIC(type->baseType)) { + xmlSchemaPCustomErr(pctxt, + XML_SCHEMAP_COS_ST_RESTRICTS_1_1, + WXS_BASIC_CAST type, NULL, + "The base type '%s' is not an atomic simple type", + xmlSchemaGetComponentQName(&str, type->baseType)); + FREE_AND_NULL(str) + return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1); + } + /* 1.2 The {final} of the {base type definition} must not contain + * restriction. + */ + /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */ + if (xmlSchemaTypeFinalContains(type->baseType, + XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) { + xmlSchemaPCustomErr(pctxt, + XML_SCHEMAP_COS_ST_RESTRICTS_1_2, + WXS_BASIC_CAST type, NULL, + "The final of its base type '%s' must not contain 'restriction'", + xmlSchemaGetComponentQName(&str, type->baseType)); + FREE_AND_NULL(str) + return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2); + } + + /* + * 1.3.1 DF must be an allowed constraining facet for the {primitive + * type definition}, as specified in the appropriate subsection of 3.2 + * Primitive datatypes. + */ + if (type->facets != NULL) { + xmlSchemaFacetPtr facet; + int ok = 1; + + primitive = xmlSchemaGetPrimitiveType(type); + if (primitive == NULL) { + PERROR_INT("xmlSchemaCheckCOSSTRestricts", + "failed to get primitive type"); + return (-1); + } + facet = type->facets; + do { + if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) { + ok = 0; + xmlSchemaPIllegalFacetAtomicErr(pctxt, + XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1, + type, primitive, facet); + } + facet = facet->next; + } while (facet != NULL); + if (ok == 0) + return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1); + } + /* + * SPEC (1.3.2) "If there is a facet of the same kind in the {facets} + * of the {base type definition} (call this BF),then the DF's {value} + * must be a valid restriction of BF's {value} as defined in + * [XML Schemas: Datatypes]." + * + * NOTE (1.3.2) Facet derivation constraints are currently handled in + * xmlSchemaDeriveAndValidateFacets() + */ + } else if (WXS_IS_LIST(type)) { + xmlSchemaTypePtr itemType = NULL; + + itemType = type->subtypes; + if ((itemType == NULL) || (! WXS_IS_SIMPLE(itemType))) { + PERROR_INT("xmlSchemaCheckCOSSTRestricts", + "failed to evaluate the item type"); + return (-1); + } + if (WXS_IS_TYPE_NOT_FIXED(itemType)) + xmlSchemaTypeFixup(itemType, ACTXT_CAST pctxt); + /* + * 2.1 The {item type definition} must have a {variety} of atomic or + * union (in which case all the {member type definitions} + * must be atomic). + */ + if ((! WXS_IS_ATOMIC(itemType)) && + (! WXS_IS_UNION(itemType))) { + xmlSchemaPCustomErr(pctxt, + XML_SCHEMAP_COS_ST_RESTRICTS_2_1, + WXS_BASIC_CAST type, NULL, + "The item type '%s' does not have a variety of atomic or union", + xmlSchemaGetComponentQName(&str, itemType)); + FREE_AND_NULL(str) + return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1); + } else if (WXS_IS_UNION(itemType)) { + xmlSchemaTypeLinkPtr member; + + member = itemType->memberTypes; + while (member != NULL) { + if (! WXS_IS_ATOMIC(member->type)) { + xmlSchemaPCustomErr(pctxt, + XML_SCHEMAP_COS_ST_RESTRICTS_2_1, + WXS_BASIC_CAST type, NULL, + "The item type is a union type, but the " + "member type '%s' of this item type is not atomic", + xmlSchemaGetComponentQName(&str, member->type)); + FREE_AND_NULL(str) + return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1); + } + member = member->next; + } + } + + if (WXS_IS_ANY_SIMPLE_TYPE(type->baseType)) { + xmlSchemaFacetPtr facet; + /* + * This is the case if we have: facets != NULL) { + facet = type->facets; + do { + if (facet->type != XML_SCHEMA_FACET_WHITESPACE) { + xmlSchemaPIllegalFacetListUnionErr(pctxt, + XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2, + type, facet); + return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2); + } + facet = facet->next; + } while (facet != NULL); + } + /* + * MAYBE TODO: (Hmm, not really) Datatypes states: + * A ·list· datatype can be ·derived· from an ·atomic· datatype + * whose ·lexical space· allows space (such as string or anyURI)or + * a ·union· datatype any of whose {member type definitions}'s + * ·lexical space· allows space. + */ + } else { + /* + * This is the case if we have: baseType)) { + xmlSchemaPCustomErr(pctxt, + XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1, + WXS_BASIC_CAST type, NULL, + "The base type '%s' must be a list type", + xmlSchemaGetComponentQName(&str, type->baseType)); + FREE_AND_NULL(str) + return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1); + } + /* + * 2.3.2.2 The {final} of the {base type definition} must not + * contain restriction. + */ + if (xmlSchemaTypeFinalContains(type->baseType, + XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) { + xmlSchemaPCustomErr(pctxt, + XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2, + WXS_BASIC_CAST type, NULL, + "The 'final' of the base type '%s' must not contain 'restriction'", + xmlSchemaGetComponentQName(&str, type->baseType)); + FREE_AND_NULL(str) + return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2); + } + /* + * 2.3.2.3 The {item type definition} must be validly derived + * from the {base type definition}'s {item type definition} given + * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6). + */ + { + xmlSchemaTypePtr baseItemType; + + baseItemType = type->baseType->subtypes; + if ((baseItemType == NULL) || (! WXS_IS_SIMPLE(baseItemType))) { + PERROR_INT("xmlSchemaCheckCOSSTRestricts", + "failed to eval the item type of a base type"); + return (-1); + } + if ((itemType != baseItemType) && + (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt, itemType, + baseItemType, 0) != 0)) { + xmlChar *strBIT = NULL, *strBT = NULL; + xmlSchemaPCustomErrExt(pctxt, + XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3, + WXS_BASIC_CAST type, NULL, + "The item type '%s' is not validly derived from " + "the item type '%s' of the base type '%s'", + xmlSchemaGetComponentQName(&str, itemType), + xmlSchemaGetComponentQName(&strBIT, baseItemType), + xmlSchemaGetComponentQName(&strBT, type->baseType)); + + FREE_AND_NULL(str) + FREE_AND_NULL(strBIT) + FREE_AND_NULL(strBT) + return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3); + } + } + + if (type->facets != NULL) { + xmlSchemaFacetPtr facet; + int ok = 1; + /* + * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern + * and enumeration facet components are allowed among the {facets}. + */ + facet = type->facets; + do { + switch (facet->type) { + case XML_SCHEMA_FACET_LENGTH: + case XML_SCHEMA_FACET_MINLENGTH: + case XML_SCHEMA_FACET_MAXLENGTH: + case XML_SCHEMA_FACET_WHITESPACE: + /* + * TODO: 2.5.1.2 List datatypes + * The value of ·whiteSpace· is fixed to the value collapse. + */ + case XML_SCHEMA_FACET_PATTERN: + case XML_SCHEMA_FACET_ENUMERATION: + break; + default: { + xmlSchemaPIllegalFacetListUnionErr(pctxt, + XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4, + type, facet); + /* + * We could return, but it's nicer to report all + * invalid facets. + */ + ok = 0; + } + } + facet = facet->next; + } while (facet != NULL); + if (ok == 0) + return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4); + /* + * SPEC (2.3.2.5) (same as 1.3.2) + * + * NOTE (2.3.2.5) This is currently done in + * xmlSchemaDeriveAndValidateFacets() + */ + } + } + } else if (WXS_IS_UNION(type)) { + /* + * 3.1 The {member type definitions} must all have {variety} of + * atomic or list. + */ + xmlSchemaTypeLinkPtr member; + + member = type->memberTypes; + while (member != NULL) { + if (WXS_IS_TYPE_NOT_FIXED(member->type)) + xmlSchemaTypeFixup(member->type, ACTXT_CAST pctxt); + + if ((! WXS_IS_ATOMIC(member->type)) && + (! WXS_IS_LIST(member->type))) { + xmlSchemaPCustomErr(pctxt, + XML_SCHEMAP_COS_ST_RESTRICTS_3_1, + WXS_BASIC_CAST type, NULL, + "The member type '%s' is neither an atomic, nor a list type", + xmlSchemaGetComponentQName(&str, member->type)); + FREE_AND_NULL(str) + return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1); + } + member = member->next; + } + /* + * 3.3.1 If the {base type definition} is the ·simple ur-type + * definition· + */ + if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) { + /* + * 3.3.1.1 All of the {member type definitions} must have a + * {final} which does not contain union. + */ + member = type->memberTypes; + while (member != NULL) { + if (xmlSchemaTypeFinalContains(member->type, + XML_SCHEMAS_TYPE_FINAL_UNION)) { + xmlSchemaPCustomErr(pctxt, + XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1, + WXS_BASIC_CAST type, NULL, + "The 'final' of member type '%s' contains 'union'", + xmlSchemaGetComponentQName(&str, member->type)); + FREE_AND_NULL(str) + return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1); + } + member = member->next; + } + /* + * 3.3.1.2 The {facets} must be empty. + */ + if (type->facetSet != NULL) { + xmlSchemaPCustomErr(pctxt, + XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2, + WXS_BASIC_CAST type, NULL, + "No facets allowed", NULL); + return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2); + } + } else { + /* + * 3.3.2.1 The {base type definition} must have a {variety} of union. + * I.e. the variety of "list" is inherited. + */ + if (! WXS_IS_UNION(type->baseType)) { + xmlSchemaPCustomErr(pctxt, + XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1, + WXS_BASIC_CAST type, NULL, + "The base type '%s' is not a union type", + xmlSchemaGetComponentQName(&str, type->baseType)); + FREE_AND_NULL(str) + return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1); + } + /* + * 3.3.2.2 The {final} of the {base type definition} must not contain restriction. + */ + if (xmlSchemaTypeFinalContains(type->baseType, + XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) { + xmlSchemaPCustomErr(pctxt, + XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2, + WXS_BASIC_CAST type, NULL, + "The 'final' of its base type '%s' must not contain 'restriction'", + xmlSchemaGetComponentQName(&str, type->baseType)); + FREE_AND_NULL(str) + return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2); + } + /* + * 3.3.2.3 The {member type definitions}, in order, must be validly + * derived from the corresponding type definitions in the {base + * type definition}'s {member type definitions} given the empty set, + * as defined in Type Derivation OK (Simple) (§3.14.6). + */ + { + xmlSchemaTypeLinkPtr baseMember; + + /* + * OPTIMIZE: if the type is restricting, it has no local defined + * member types and inherits the member types of the base type; + * thus a check for equality can be skipped. + */ + /* + * Even worse: I cannot see a scenario where a restricting + * union simple type can have other member types as the member + * types of it's base type. This check seems not necessary with + * respect to the derivation process in libxml2. + * But necessary if constructing types with an API. + */ + if (type->memberTypes != NULL) { + member = type->memberTypes; + baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType); + if ((member == NULL) && (baseMember != NULL)) { + PERROR_INT("xmlSchemaCheckCOSSTRestricts", + "different number of member types in base"); + } + while (member != NULL) { + if (baseMember == NULL) { + PERROR_INT("xmlSchemaCheckCOSSTRestricts", + "different number of member types in base"); + } else if ((member->type != baseMember->type) && + (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt, + member->type, baseMember->type, 0) != 0)) { + xmlChar *strBMT = NULL, *strBT = NULL; + + xmlSchemaPCustomErrExt(pctxt, + XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3, + WXS_BASIC_CAST type, NULL, + "The member type %s is not validly " + "derived from its corresponding member " + "type %s of the base type %s", + xmlSchemaGetComponentQName(&str, member->type), + xmlSchemaGetComponentQName(&strBMT, baseMember->type), + xmlSchemaGetComponentQName(&strBT, type->baseType)); + FREE_AND_NULL(str) + FREE_AND_NULL(strBMT) + FREE_AND_NULL(strBT) + return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3); + } + member = member->next; + baseMember = baseMember->next; + } + } + } + /* + * 3.3.2.4 Only pattern and enumeration facet components are + * allowed among the {facets}. + */ + if (type->facets != NULL) { + xmlSchemaFacetPtr facet; + int ok = 1; + + facet = type->facets; + do { + if ((facet->type != XML_SCHEMA_FACET_PATTERN) && + (facet->type != XML_SCHEMA_FACET_ENUMERATION)) { + xmlSchemaPIllegalFacetListUnionErr(pctxt, + XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4, + type, facet); + ok = 0; + } + facet = facet->next; + } while (facet != NULL); + if (ok == 0) + return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4); + + } + /* + * SPEC (3.3.2.5) (same as 1.3.2) + * + * NOTE (3.3.2.5) This is currently done in + * xmlSchemaDeriveAndValidateFacets() + */ + } + } + + return (0); +} + +/** + * xmlSchemaCheckSRCSimpleType: + * @ctxt: the schema parser context + * @type: the simple type definition + * + * Checks crc-simple-type constraints. + * + * Returns 0 if the constraints are satisfied, + * if not a positive error code and -1 on internal + * errors. + */ +#if 0 +static int +xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt, + xmlSchemaTypePtr type) +{ + /* + * src-simple-type.1 The corresponding simple type definition, if any, + * must satisfy the conditions set out in Constraints on Simple Type + * Definition Schema Components (§3.14.6). + */ + if (WXS_IS_RESTRICTION(type)) { + /* + * src-simple-type.2 "If the alternative is chosen, + * either it must have a base [attribute] or a among its + * [children], but not both." + * NOTE: This is checked in the parse function of . + */ + /* + * + */ + } else if (WXS_IS_LIST(type)) { + /* src-simple-type.3 "If the alternative is chosen, either it must have + * an itemType [attribute] or a among its [children], + * but not both." + * + * NOTE: This is checked in the parse function of . + */ + } else if (WXS_IS_UNION(type)) { + /* + * src-simple-type.4 is checked in xmlSchemaCheckUnionTypeDefCircular(). + */ + } + return (0); +} +#endif + +static int +xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt) +{ + if (ctxt->vctxt == NULL) { + ctxt->vctxt = xmlSchemaNewValidCtxt(NULL); + if (ctxt->vctxt == NULL) { + xmlSchemaPErr(ctxt, NULL, + XML_SCHEMAP_INTERNAL, + "Internal error: xmlSchemaCreateVCtxtOnPCtxt, " + "failed to create a temp. validation context.\n", + NULL, NULL); + return (-1); + } + /* TODO: Pass user data. */ + xmlSchemaSetValidErrors(ctxt->vctxt, + ctxt->error, ctxt->warning, ctxt->errCtxt); + xmlSchemaSetValidStructuredErrors(ctxt->vctxt, + ctxt->serror, ctxt->errCtxt); + } + return (0); +} + +static int +xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt, + xmlNodePtr node, + xmlSchemaTypePtr type, + const xmlChar *value, + xmlSchemaValPtr *retVal, + int fireErrors, + int normalize, + int isNormalized); + +/** + * xmlSchemaParseCheckCOSValidDefault: + * @pctxt: the schema parser context + * @type: the simple type definition + * @value: the default value + * @node: an optional node (the holder of the value) + * + * Schema Component Constraint: Element Default Valid (Immediate) + * (cos-valid-default) + * This will be used by the parser only. For the validator there's + * an other version. + * + * Returns 0 if the constraints are satisfied, + * if not, a positive error code and -1 on internal + * errors. + */ +static int +xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt, + xmlNodePtr node, + xmlSchemaTypePtr type, + const xmlChar *value, + xmlSchemaValPtr *val) +{ + int ret = 0; + + /* + * cos-valid-default: + * Schema Component Constraint: Element Default Valid (Immediate) + * For a string to be a valid default with respect to a type + * definition the appropriate case among the following must be true: + */ + if WXS_IS_COMPLEX(type) { + /* + * Complex type. + * + * SPEC (2.1) "its {content type} must be a simple type definition + * or mixed." + * SPEC (2.2.2) "If the {content type} is mixed, then the {content + * type}'s particle must be ·emptiable· as defined by + * Particle Emptiable (§3.9.6)." + */ + if ((! WXS_HAS_SIMPLE_CONTENT(type)) && + ((! WXS_HAS_MIXED_CONTENT(type)) || (! WXS_EMPTIABLE(type)))) { + /* NOTE that this covers (2.2.2) as well. */ + xmlSchemaPCustomErr(pctxt, + XML_SCHEMAP_COS_VALID_DEFAULT_2_1, + WXS_BASIC_CAST type, type->node, + "For a string to be a valid default, the type definition " + "must be a simple type or a complex type with mixed content " + "and a particle emptiable", NULL); + return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1); + } + } + /* + * 1 If the type definition is a simple type definition, then the string + * must be ·valid· with respect to that definition as defined by String + * Valid (§3.14.4). + * + * AND + * + * 2.2.1 If the {content type} is a simple type definition, then the + * string must be ·valid· with respect to that simple type definition + * as defined by String Valid (§3.14.4). + */ + if (WXS_IS_SIMPLE(type)) + ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node, + type, value, val, 1, 1, 0); + else if (WXS_HAS_SIMPLE_CONTENT(type)) + ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node, + type->contentTypeDef, value, val, 1, 1, 0); + else + return (ret); + + if (ret < 0) { + PERROR_INT("xmlSchemaParseCheckCOSValidDefault", + "calling xmlSchemaVCheckCVCSimpleType()"); + } + + return (ret); +} + +/** + * xmlSchemaCheckCTPropsCorrect: + * @ctxt: the schema parser context + * @type: the complex type definition + * + *.(4.6) Constraints on Complex Type Definition Schema Components + * Schema Component Constraint: + * Complex Type Definition Properties Correct (ct-props-correct) + * STATUS: (seems) complete + * + * Returns 0 if the constraints are satisfied, a positive + * error code if not and -1 if an internal error occured. + */ +static int +xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt, + xmlSchemaTypePtr type) +{ + /* + * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily. + * + * SPEC (1) "The values of the properties of a complex type definition must + * be as described in the property tableau in The Complex Type Definition + * Schema Component (§3.4.1), modulo the impact of Missing + * Sub-components (§5.3)." + */ + if ((type->baseType != NULL) && + (WXS_IS_SIMPLE(type->baseType)) && + (WXS_IS_EXTENSION(type) == 0)) { + /* + * SPEC (2) "If the {base type definition} is a simple type definition, + * the {derivation method} must be extension." + */ + xmlSchemaCustomErr(ACTXT_CAST pctxt, + XML_SCHEMAP_SRC_CT_1, + NULL, WXS_BASIC_CAST type, + "If the base type is a simple type, the derivation method must be " + "'extension'", NULL, NULL); + return (XML_SCHEMAP_SRC_CT_1); + } + /* + * SPEC (3) "Circular definitions are disallowed, except for the ·ur-type + * definition·. That is, it must be possible to reach the ·ur-type + * definition by repeatedly following the {base type definition}." + * + * NOTE (3) is done in xmlSchemaCheckTypeDefCircular(). + */ + /* + * NOTE that (4) and (5) need the following: + * - attribute uses need to be already inherited (apply attr. prohibitions) + * - attribute group references need to be expanded already + * - simple types need to be typefixed already + */ + if (type->attrUses && + (((xmlSchemaItemListPtr) type->attrUses)->nbItems > 1)) + { + xmlSchemaItemListPtr uses = (xmlSchemaItemListPtr) type->attrUses; + xmlSchemaAttributeUsePtr use, tmp; + int i, j, hasId = 0; + + for (i = uses->nbItems -1; i >= 0; i--) { + use = uses->items[i]; + + /* + * SPEC ct-props-correct + * (4) "Two distinct attribute declarations in the + * {attribute uses} must not have identical {name}s and + * {target namespace}s." + */ + if (i > 0) { + for (j = i -1; j >= 0; j--) { + tmp = uses->items[j]; + if ((WXS_ATTRUSE_DECL_NAME(use) == + WXS_ATTRUSE_DECL_NAME(tmp)) && + (WXS_ATTRUSE_DECL_TNS(use) == + WXS_ATTRUSE_DECL_TNS(tmp))) + { + xmlChar *str = NULL; + + xmlSchemaCustomErr(ACTXT_CAST pctxt, + XML_SCHEMAP_AG_PROPS_CORRECT, + NULL, WXS_BASIC_CAST type, + "Duplicate %s", + xmlSchemaGetComponentDesignation(&str, use), + NULL); + FREE_AND_NULL(str); + /* + * Remove the duplicate. + */ + if (xmlSchemaItemListRemove(uses, i) == -1) + goto exit_failure; + goto next_use; + } + } + } + /* + * SPEC ct-props-correct + * (5) "Two distinct attribute declarations in the + * {attribute uses} must not have {type definition}s which + * are or are derived from ID." + */ + if (WXS_ATTRUSE_TYPEDEF(use) != NULL) { + if (xmlSchemaIsDerivedFromBuiltInType( + WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID)) + { + if (hasId) { + xmlChar *str = NULL; + + xmlSchemaCustomErr(ACTXT_CAST pctxt, + XML_SCHEMAP_AG_PROPS_CORRECT, + NULL, WXS_BASIC_CAST type, + "There must not exist more than one attribute " + "declaration of type 'xs:ID' " + "(or derived from 'xs:ID'). The %s violates this " + "constraint", + xmlSchemaGetComponentDesignation(&str, use), + NULL); + FREE_AND_NULL(str); + if (xmlSchemaItemListRemove(uses, i) == -1) + goto exit_failure; + } + + hasId = 1; + } + } +next_use: {} + } + } + return (0); +exit_failure: + return(-1); +} + +static int +xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA, + xmlSchemaTypePtr typeB) +{ + /* + * TODO: This should implement component-identity + * in the future. + */ + if ((typeA == NULL) || (typeB == NULL)) + return (0); + return (typeA == typeB); +} + +/** + * xmlSchemaCheckCOSCTDerivedOK: + * @ctxt: the schema parser context + * @type: the to-be derived complex type definition + * @baseType: the base complex type definition + * @set: the given set + * + * Schema Component Constraint: + * Type Derivation OK (Complex) (cos-ct-derived-ok) + * + * STATUS: completed + * + * Returns 0 if the constraints are satisfied, or 1 + * if not. + */ +static int +xmlSchemaCheckCOSCTDerivedOK(xmlSchemaAbstractCtxtPtr actxt, + xmlSchemaTypePtr type, + xmlSchemaTypePtr baseType, + int set) +{ + int equal = xmlSchemaAreEqualTypes(type, baseType); + /* TODO: Error codes. */ + /* + * SPEC "For a complex type definition (call it D, for derived) + * to be validly derived from a type definition (call this + * B, for base) given a subset of {extension, restriction} + * all of the following must be true:" + */ + if (! equal) { + /* + * SPEC (1) "If B and D are not the same type definition, then the + * {derivation method} of D must not be in the subset." + */ + if (((set & SUBSET_EXTENSION) && (WXS_IS_EXTENSION(type))) || + ((set & SUBSET_RESTRICTION) && (WXS_IS_RESTRICTION(type)))) + return (1); + } else { + /* + * SPEC (2.1) "B and D must be the same type definition." + */ + return (0); + } + /* + * SPEC (2.2) "B must be D's {base type definition}." + */ + if (type->baseType == baseType) + return (0); + /* + * SPEC (2.3.1) "D's {base type definition} must not be the ·ur-type + * definition·." + */ + if (WXS_IS_ANYTYPE(type->baseType)) + return (1); + + if (WXS_IS_COMPLEX(type->baseType)) { + /* + * SPEC (2.3.2.1) "If D's {base type definition} is complex, then it + * must be validly derived from B given the subset as defined by this + * constraint." + */ + return (xmlSchemaCheckCOSCTDerivedOK(actxt, type->baseType, + baseType, set)); + } else { + /* + * SPEC (2.3.2.2) "If D's {base type definition} is simple, then it + * must be validly derived from B given the subset as defined in Type + * Derivation OK (Simple) (§3.14.6). + */ + return (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType, + baseType, set)); + } +} + +/** + * xmlSchemaCheckCOSDerivedOK: + * @type: the derived simple type definition + * @baseType: the base type definition + * + * Calls: + * Type Derivation OK (Simple) AND Type Derivation OK (Complex) + * + * Checks wheter @type can be validly derived from @baseType. + * + * Returns 0 on success, an positive error code otherwise. + */ +static int +xmlSchemaCheckCOSDerivedOK(xmlSchemaAbstractCtxtPtr actxt, + xmlSchemaTypePtr type, + xmlSchemaTypePtr baseType, + int set) +{ + if (WXS_IS_SIMPLE(type)) + return (xmlSchemaCheckCOSSTDerivedOK(actxt, type, baseType, set)); + else + return (xmlSchemaCheckCOSCTDerivedOK(actxt, type, baseType, set)); +} + +/** + * xmlSchemaCheckCOSCTExtends: + * @ctxt: the schema parser context + * @type: the complex type definition + * + * (3.4.6) Constraints on Complex Type Definition Schema Components + * Schema Component Constraint: + * Derivation Valid (Extension) (cos-ct-extends) + * + * STATUS: + * missing: + * (1.5) + * (1.4.3.2.2.2) "Particle Valid (Extension)" + * + * Returns 0 if the constraints are satisfied, a positive + * error code if not and -1 if an internal error occured. + */ +static int +xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt, + xmlSchemaTypePtr type) +{ + xmlSchemaTypePtr base = type->baseType; + /* + * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used + * temporarily only. + */ + /* + * SPEC (1) "If the {base type definition} is a complex type definition, + * then all of the following must be true:" + */ + if (WXS_IS_COMPLEX(base)) { + /* + * SPEC (1.1) "The {final} of the {base type definition} must not + * contain extension." + */ + if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) { + xmlSchemaPCustomErr(ctxt, + XML_SCHEMAP_COS_CT_EXTENDS_1_1, + WXS_BASIC_CAST type, NULL, + "The 'final' of the base type definition " + "contains 'extension'", NULL); + return (XML_SCHEMAP_COS_CT_EXTENDS_1_1); + } + + /* + * ATTENTION: The constrains (1.2) and (1.3) are not applied, + * since they are automatically satisfied through the + * inheriting mechanism. + * Note that even if redefining components, the inheriting mechanism + * is used. + */ +#if 0 + /* + * SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute + * uses} + * of the complex type definition itself, that is, for every attribute + * use in the {attribute uses} of the {base type definition}, there + * must be an attribute use in the {attribute uses} of the complex + * type definition itself whose {attribute declaration} has the same + * {name}, {target namespace} and {type definition} as its attribute + * declaration" + */ + if (base->attrUses != NULL) { + int i, j, found; + xmlSchemaAttributeUsePtr use, buse; + + for (i = 0; i < (WXS_LIST_CAST base->attrUses)->nbItems; i ++) { + buse = (WXS_LIST_CAST base->attrUses)->items[i]; + found = 0; + if (type->attrUses != NULL) { + use = (WXS_LIST_CAST type->attrUses)->items[j]; + for (j = 0; j < (WXS_LIST_CAST type->attrUses)->nbItems; j ++) + { + if ((WXS_ATTRUSE_DECL_NAME(use) == + WXS_ATTRUSE_DECL_NAME(buse)) && + (WXS_ATTRUSE_DECL_TNS(use) == + WXS_ATTRUSE_DECL_TNS(buse)) && + (WXS_ATTRUSE_TYPEDEF(use) == + WXS_ATTRUSE_TYPEDEF(buse)) + { + found = 1; + break; + } + } + } + if (! found) { + xmlChar *str = NULL; + + xmlSchemaCustomErr(ACTXT_CAST ctxt, + XML_SCHEMAP_COS_CT_EXTENDS_1_2, + NULL, WXS_BASIC_CAST type, + /* + * TODO: The report does not indicate that also the + * type needs to be the same. + */ + "This type is missing a matching correspondent " + "for its {base type}'s %s in its {attribute uses}", + xmlSchemaGetComponentDesignation(&str, + buse->children), + NULL); + FREE_AND_NULL(str) + } + } + } + /* + * SPEC (1.3) "If it has an {attribute wildcard}, the complex type + * definition must also have one, and the base type definition's + * {attribute wildcard}'s {namespace constraint} must be a subset + * of the complex type definition's {attribute wildcard}'s {namespace + * constraint}, as defined by Wildcard Subset (§3.10.6)." + */ + + /* + * MAYBE TODO: Enable if ever needed. But this will be needed only + * if created the type via a schema construction API. + */ + if (base->attributeWildcard != NULL) { + if (type->attributeWilcard == NULL) { + xmlChar *str = NULL; + + xmlSchemaCustomErr(ACTXT_CAST pctxt, + XML_SCHEMAP_COS_CT_EXTENDS_1_3, + NULL, type, + "The base %s has an attribute wildcard, " + "but this type is missing an attribute wildcard", + xmlSchemaGetComponentDesignation(&str, base)); + FREE_AND_NULL(str) + + } else if (xmlSchemaCheckCOSNSSubset( + base->attributeWildcard, type->attributeWildcard)) + { + xmlChar *str = NULL; + + xmlSchemaCustomErr(ACTXT_CAST pctxt, + XML_SCHEMAP_COS_CT_EXTENDS_1_3, + NULL, type, + "The attribute wildcard is not a valid " + "superset of the one in the base %s", + xmlSchemaGetComponentDesignation(&str, base)); + FREE_AND_NULL(str) + } + } +#endif + /* + * SPEC (1.4) "One of the following must be true:" + */ + if ((type->contentTypeDef != NULL) && + (type->contentTypeDef == base->contentTypeDef)) { + /* + * SPEC (1.4.1) "The {content type} of the {base type definition} + * and the {content type} of the complex type definition itself + * must be the same simple type definition" + * PASS + */ + } else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) && + (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) { + /* + * SPEC (1.4.2) "The {content type} of both the {base type + * definition} and the complex type definition itself must + * be empty." + * PASS + */ + } else { + /* + * SPEC (1.4.3) "All of the following must be true:" + */ + if (type->subtypes == NULL) { + /* + * SPEC 1.4.3.1 The {content type} of the complex type + * definition itself must specify a particle. + */ + xmlSchemaPCustomErr(ctxt, + XML_SCHEMAP_COS_CT_EXTENDS_1_1, + WXS_BASIC_CAST type, NULL, + "The content type must specify a particle", NULL); + return (XML_SCHEMAP_COS_CT_EXTENDS_1_1); + } + /* + * SPEC (1.4.3.2) "One of the following must be true:" + */ + if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) { + /* + * SPEC (1.4.3.2.1) "The {content type} of the {base type + * definition} must be empty. + * PASS + */ + } else { + /* + * SPEC (1.4.3.2.2) "All of the following must be true:" + */ + if ((type->contentType != base->contentType) || + ((type->contentType != XML_SCHEMA_CONTENT_MIXED) && + (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) { + /* + * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed + * or both must be element-only." + */ + xmlSchemaPCustomErr(ctxt, + XML_SCHEMAP_COS_CT_EXTENDS_1_1, + WXS_BASIC_CAST type, NULL, + "The content type of both, the type and its base " + "type, must either 'mixed' or 'element-only'", NULL); + return (XML_SCHEMAP_COS_CT_EXTENDS_1_1); + } + /* + * URGENT TODO SPEC (1.4.3.2.2.2) "The particle of the + * complex type definition must be a ·valid extension· + * of the {base type definition}'s particle, as defined + * in Particle Valid (Extension) (§3.9.6)." + * + * NOTE that we won't check "Particle Valid (Extension)", + * since it is ensured by the derivation process in + * xmlSchemaTypeFixup(). We need to implement this when heading + * for a construction API + * TODO: !! This is needed to be checked if redefining a type !! + */ + } + /* + * URGENT TODO (1.5) + */ + } + } else { + /* + * SPEC (2) "If the {base type definition} is a simple type definition, + * then all of the following must be true:" + */ + if (type->contentTypeDef != base) { + /* + * SPEC (2.1) "The {content type} must be the same simple type + * definition." + */ + xmlSchemaPCustomErr(ctxt, + XML_SCHEMAP_COS_CT_EXTENDS_1_1, + WXS_BASIC_CAST type, NULL, + "The content type must be the simple base type", NULL); + return (XML_SCHEMAP_COS_CT_EXTENDS_1_1); + } + if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) { + /* + * SPEC (2.2) "The {final} of the {base type definition} must not + * contain extension" + * NOTE that this is the same as (1.1). + */ + xmlSchemaPCustomErr(ctxt, + XML_SCHEMAP_COS_CT_EXTENDS_1_1, + WXS_BASIC_CAST type, NULL, + "The 'final' of the base type definition " + "contains 'extension'", NULL); + return (XML_SCHEMAP_COS_CT_EXTENDS_1_1); + } + } + return (0); +} + +/** + * xmlSchemaCheckDerivationOKRestriction: + * @ctxt: the schema parser context + * @type: the complex type definition + * + * (3.4.6) Constraints on Complex Type Definition Schema Components + * Schema Component Constraint: + * Derivation Valid (Restriction, Complex) (derivation-ok-restriction) + * + * STATUS: + * missing: + * (5.4.2) ??? + * + * ATTENTION: + * In XML Schema 1.1 this will be: + * Validation Rule: Checking complex type subsumption + * + * Returns 0 if the constraints are satisfied, a positive + * error code if not and -1 if an internal error occured. + */ +static int +xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt, + xmlSchemaTypePtr type) +{ + xmlSchemaTypePtr base; + + /* + * TODO: Correct the error code; XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1 is used + * temporarily only. + */ + base = type->baseType; + if (! WXS_IS_COMPLEX(base)) { + xmlSchemaCustomErr(ACTXT_CAST ctxt, + XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1, + type->node, WXS_BASIC_CAST type, + "The base type must be a complex type", NULL, NULL); + return(ctxt->err); + } + if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) { + /* + * SPEC (1) "The {base type definition} must be a complex type + * definition whose {final} does not contain restriction." + */ + xmlSchemaCustomErr(ACTXT_CAST ctxt, + XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1, + type->node, WXS_BASIC_CAST type, + "The 'final' of the base type definition " + "contains 'restriction'", NULL, NULL); + return (ctxt->err); + } + /* + * SPEC (2), (3) and (4) + * Those are handled in a separate function, since the + * same constraints are needed for redefinition of + * attribute groups as well. + */ + if (xmlSchemaCheckDerivationOKRestriction2to4(ctxt, + XML_SCHEMA_ACTION_DERIVE, + WXS_BASIC_CAST type, WXS_BASIC_CAST base, + type->attrUses, base->attrUses, + type->attributeWildcard, + base->attributeWildcard) == -1) + { + return(-1); + } + /* + * SPEC (5) "One of the following must be true:" + */ + if (base->builtInType == XML_SCHEMAS_ANYTYPE) { + /* + * SPEC (5.1) "The {base type definition} must be the + * ·ur-type definition·." + * PASS + */ + } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) || + (type->contentType == XML_SCHEMA_CONTENT_BASIC)) { + /* + * SPEC (5.2.1) "The {content type} of the complex type definition + * must be a simple type definition" + * + * SPEC (5.2.2) "One of the following must be true:" + */ + if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) || + (base->contentType == XML_SCHEMA_CONTENT_BASIC)) + { + int err; + /* + * SPEC (5.2.2.1) "The {content type} of the {base type + * definition} must be a simple type definition from which + * the {content type} is validly derived given the empty + * set as defined in Type Derivation OK (Simple) (§3.14.6)." + * + * ATTENTION TODO: This seems not needed if the type implicitely + * derived from the base type. + * + */ + err = xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST ctxt, + type->contentTypeDef, base->contentTypeDef, 0); + if (err != 0) { + xmlChar *strA = NULL, *strB = NULL; + + if (err == -1) + return(-1); + xmlSchemaCustomErr(ACTXT_CAST ctxt, + XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1, + NULL, WXS_BASIC_CAST type, + "The {content type} %s is not validly derived from the " + "base type's {content type} %s", + xmlSchemaGetComponentDesignation(&strA, + type->contentTypeDef), + xmlSchemaGetComponentDesignation(&strB, + base->contentTypeDef)); + FREE_AND_NULL(strA); + FREE_AND_NULL(strB); + return(ctxt->err); + } + } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) && + (xmlSchemaIsParticleEmptiable( + (xmlSchemaParticlePtr) base->subtypes))) { + /* + * SPEC (5.2.2.2) "The {base type definition} must be mixed + * and have a particle which is ·emptiable· as defined in + * Particle Emptiable (§3.9.6)." + * PASS + */ + } else { + xmlSchemaPCustomErr(ctxt, + XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1, + WXS_BASIC_CAST type, NULL, + "The content type of the base type must be either " + "a simple type or 'mixed' and an emptiable particle", NULL); + return (ctxt->err); + } + } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) { + /* + * SPEC (5.3.1) "The {content type} of the complex type itself must + * be empty" + */ + if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) { + /* + * SPEC (5.3.2.1) "The {content type} of the {base type + * definition} must also be empty." + * PASS + */ + } else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) || + (base->contentType == XML_SCHEMA_CONTENT_MIXED)) && + xmlSchemaIsParticleEmptiable( + (xmlSchemaParticlePtr) base->subtypes)) { + /* + * SPEC (5.3.2.2) "The {content type} of the {base type + * definition} must be elementOnly or mixed and have a particle + * which is ·emptiable· as defined in Particle Emptiable (§3.9.6)." + * PASS + */ + } else { + xmlSchemaPCustomErr(ctxt, + XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1, + WXS_BASIC_CAST type, NULL, + "The content type of the base type must be either " + "empty or 'mixed' (or 'elements-only') and an emptiable " + "particle", NULL); + return (ctxt->err); + } + } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) || + WXS_HAS_MIXED_CONTENT(type)) { + /* + * SPEC (5.4.1.1) "The {content type} of the complex type definition + * itself must be element-only" + */ + if (WXS_HAS_MIXED_CONTENT(type) && (! WXS_HAS_MIXED_CONTENT(base))) { + /* + * SPEC (5.4.1.2) "The {content type} of the complex type + * definition itself and of the {base type definition} must be + * mixed" + */ + xmlSchemaPCustomErr(ctxt, + XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1, + WXS_BASIC_CAST type, NULL, + "If the content type is 'mixed', then the content type of the " + "base type must also be 'mixed'", NULL); + return (ctxt->err); + } + /* + * SPEC (5.4.2) "The particle of the complex type definition itself + * must be a ·valid restriction· of the particle of the {content + * type} of the {base type definition} as defined in Particle Valid + * (Restriction) (§3.9.6). + * + * URGENT TODO: (5.4.2) + */ + } else { + xmlSchemaPCustomErr(ctxt, + XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1, + WXS_BASIC_CAST type, NULL, + "The type is not a valid restriction of its base type", NULL); + return (ctxt->err); + } + return (0); +} + +/** + * xmlSchemaCheckCTComponent: + * @ctxt: the schema parser context + * @type: the complex type definition + * + * (3.4.6) Constraints on Complex Type Definition Schema Components + * + * Returns 0 if the constraints are satisfied, a positive + * error code if not and -1 if an internal error occured. + */ +static int +xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt, + xmlSchemaTypePtr type) +{ + int ret; + /* + * Complex Type Definition Properties Correct + */ + ret = xmlSchemaCheckCTPropsCorrect(ctxt, type); + if (ret != 0) + return (ret); + if (WXS_IS_EXTENSION(type)) + ret = xmlSchemaCheckCOSCTExtends(ctxt, type); + else + ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type); + return (ret); +} + +/** + * xmlSchemaCheckSRCCT: + * @ctxt: the schema parser context + * @type: the complex type definition + * + * (3.4.3) Constraints on XML Representations of Complex Type Definitions: + * Schema Representation Constraint: + * Complex Type Definition Representation OK (src-ct) + * + * Returns 0 if the constraints are satisfied, a positive + * error code if not and -1 if an internal error occured. + */ +static int +xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt, + xmlSchemaTypePtr type) +{ + xmlSchemaTypePtr base; + int ret = 0; + + /* + * TODO: Adjust the error codes here, as I used + * XML_SCHEMAP_SRC_CT_1 only yet. + */ + base = type->baseType; + if (! WXS_HAS_SIMPLE_CONTENT(type)) { + /* + * 1 If the alternative is chosen, the type definition + * ·resolved· to by the ·actual value· of the base [attribute] + * must be a complex type definition; + */ + if (! WXS_IS_COMPLEX(base)) { + xmlChar *str = NULL; + xmlSchemaPCustomErr(ctxt, + XML_SCHEMAP_SRC_CT_1, + WXS_BASIC_CAST type, type->node, + "If using , the base type is expected to be " + "a complex type. The base type '%s' is a simple type", + xmlSchemaFormatQName(&str, base->targetNamespace, + base->name)); + FREE_AND_NULL(str) + return (XML_SCHEMAP_SRC_CT_1); + } + } else { + /* + * SPEC + * 2 If the alternative is chosen, all of the + * following must be true: + * 2.1 The type definition ·resolved· to by the ·actual value· of the + * base [attribute] must be one of the following: + */ + if (WXS_IS_SIMPLE(base)) { + if (WXS_IS_EXTENSION(type) == 0) { + xmlChar *str = NULL; + /* + * 2.1.3 only if the alternative is also + * chosen, a simple type definition. + */ + /* TODO: Change error code to ..._SRC_CT_2_1_3. */ + xmlSchemaPCustomErr(ctxt, + XML_SCHEMAP_SRC_CT_1, + WXS_BASIC_CAST type, NULL, + "If using and , the base " + "type must be a complex type. The base type '%s' is " + "a simple type", + xmlSchemaFormatQName(&str, base->targetNamespace, + base->name)); + FREE_AND_NULL(str) + return (XML_SCHEMAP_SRC_CT_1); + } + } else { + /* Base type is a complex type. */ + if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) || + (base->contentType == XML_SCHEMA_CONTENT_BASIC)) { + /* + * 2.1.1 a complex type definition whose {content type} is a + * simple type definition; + * PASS + */ + if (base->contentTypeDef == NULL) { + xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL, + WXS_BASIC_CAST type, NULL, + "Internal error: xmlSchemaCheckSRCCT, " + "'%s', base type has no content type", + type->name); + return (-1); + } + } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) && + (WXS_IS_RESTRICTION(type))) { + + /* + * 2.1.2 only if the alternative is also + * chosen, a complex type definition whose {content type} + * is mixed and a particle emptiable. + */ + if (! xmlSchemaIsParticleEmptiable( + (xmlSchemaParticlePtr) base->subtypes)) { + ret = XML_SCHEMAP_SRC_CT_1; + } else + /* + * Attention: at this point the child is in + * ->contentTypeDef (put there during parsing). + */ + if (type->contentTypeDef == NULL) { + xmlChar *str = NULL; + /* + * 2.2 If clause 2.1.2 above is satisfied, then there + * must be a among the [children] of + * . + */ + /* TODO: Change error code to ..._SRC_CT_2_2. */ + xmlSchemaPCustomErr(ctxt, + XML_SCHEMAP_SRC_CT_1, + WXS_BASIC_CAST type, NULL, + "A is expected among the children " + "of , if is used and " + "the base type '%s' is a complex type", + xmlSchemaFormatQName(&str, base->targetNamespace, + base->name)); + FREE_AND_NULL(str) + return (XML_SCHEMAP_SRC_CT_1); + } + } else { + ret = XML_SCHEMAP_SRC_CT_1; + } + } + if (ret > 0) { + xmlChar *str = NULL; + if (WXS_IS_RESTRICTION(type)) { + xmlSchemaPCustomErr(ctxt, + XML_SCHEMAP_SRC_CT_1, + WXS_BASIC_CAST type, NULL, + "If and is used, the " + "base type must be a simple type or a complex type with " + "mixed content and particle emptiable. The base type " + "'%s' is none of those", + xmlSchemaFormatQName(&str, base->targetNamespace, + base->name)); + } else { + xmlSchemaPCustomErr(ctxt, + XML_SCHEMAP_SRC_CT_1, + WXS_BASIC_CAST type, NULL, + "If and is used, the " + "base type must be a simple type. The base type '%s' " + "is a complex type", + xmlSchemaFormatQName(&str, base->targetNamespace, + base->name)); + } + FREE_AND_NULL(str) + } + } + /* + * SPEC (3) "The corresponding complex type definition component must + * satisfy the conditions set out in Constraints on Complex Type + * Definition Schema Components (§3.4.6);" + * NOTE (3) will be done in xmlSchemaTypeFixup(). + */ + /* + * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification + * above for {attribute wildcard} is satisfied, the intensional + * intersection must be expressible, as defined in Attribute Wildcard + * Intersection (§3.10.6). + * NOTE (4) is done in xmlSchemaFixupTypeAttributeUses(). + */ + return (ret); +} + +#ifdef ENABLE_PARTICLE_RESTRICTION +/** + * xmlSchemaCheckParticleRangeOK: + * @ctxt: the schema parser context + * @type: the complex type definition + * + * (3.9.6) Constraints on Particle Schema Components + * Schema Component Constraint: + * Occurrence Range OK (range-ok) + * + * STATUS: complete + * + * Returns 0 if the constraints are satisfied, a positive + * error code if not and -1 if an internal error occured. + */ +static int +xmlSchemaCheckParticleRangeOK(int rmin, int rmax, + int bmin, int bmax) +{ + if (rmin < bmin) + return (1); + if ((bmax != UNBOUNDED) && + (rmax > bmax)) + return (1); + return (0); +} + +/** + * xmlSchemaCheckRCaseNameAndTypeOK: + * @ctxt: the schema parser context + * @r: the restricting element declaration particle + * @b: the base element declaration particle + * + * (3.9.6) Constraints on Particle Schema Components + * Schema Component Constraint: + * Particle Restriction OK (Elt:Elt -- NameAndTypeOK) + * (rcase-NameAndTypeOK) + * + * STATUS: + * MISSING (3.2.3) + * CLARIFY: (3.2.2) + * + * Returns 0 if the constraints are satisfied, a positive + * error code if not and -1 if an internal error occured. + */ +static int +xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt, + xmlSchemaParticlePtr r, + xmlSchemaParticlePtr b) +{ + xmlSchemaElementPtr elemR, elemB; + + /* TODO: Error codes (rcase-NameAndTypeOK). */ + elemR = (xmlSchemaElementPtr) r->children; + elemB = (xmlSchemaElementPtr) b->children; + /* + * SPEC (1) "The declarations' {name}s and {target namespace}s are + * the same." + */ + if ((elemR != elemB) && + ((! xmlStrEqual(elemR->name, elemB->name)) || + (! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace)))) + return (1); + /* + * SPEC (2) "R's occurrence range is a valid restriction of B's + * occurrence range as defined by Occurrence Range OK (§3.9.6)." + */ + if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs, + b->minOccurs, b->maxOccurs) != 0) + return (1); + /* + * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's + * {scope} are global." + */ + if (elemR == elemB) + return (0); + /* + * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false." + */ + if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) && + (elemR->flags & XML_SCHEMAS_ELEM_NILLABLE)) + return (1); + /* + * SPEC (3.2.2) "either B's declaration's {value constraint} is absent, + * or is not fixed, or R's declaration's {value constraint} is fixed + * with the same value." + */ + if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) && + ((elemR->value == NULL) || + ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) || + /* TODO: Equality of the initial value or normalized or canonical? */ + (! xmlStrEqual(elemR->value, elemB->value)))) + return (1); + /* + * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint + * definitions} is a subset of B's declaration's {identity-constraint + * definitions}, if any." + */ + if (elemB->idcs != NULL) { + /* TODO */ + } + /* + * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a + * superset of B's declaration's {disallowed substitutions}." + */ + if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) && + ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) || + ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) && + ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) || + ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) && + ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0))) + return (1); + /* + * SPEC (3.2.5) "R's {type definition} is validly derived given + * {extension, list, union} from B's {type definition}" + * + * BADSPEC TODO: What's the point of adding "list" and "union" to the + * set, if the corresponding constraints handle "restriction" and + * "extension" only? + * + */ + { + int set = 0; + + set |= SUBSET_EXTENSION; + set |= SUBSET_LIST; + set |= SUBSET_UNION; + if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST ctxt, elemR->subtypes, + elemB->subtypes, set) != 0) + return (1); + } + return (0); +} + +/** + * xmlSchemaCheckRCaseNSCompat: + * @ctxt: the schema parser context + * @r: the restricting element declaration particle + * @b: the base wildcard particle + * + * (3.9.6) Constraints on Particle Schema Components + * Schema Component Constraint: + * Particle Derivation OK (Elt:Any -- NSCompat) + * (rcase-NSCompat) + * + * STATUS: complete + * + * Returns 0 if the constraints are satisfied, a positive + * error code if not and -1 if an internal error occured. + */ +static int +xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt, + xmlSchemaParticlePtr r, + xmlSchemaParticlePtr b) +{ + /* TODO:Error codes (rcase-NSCompat). */ + /* + * SPEC "For an element declaration particle to be a ·valid restriction· + * of a wildcard particle all of the following must be true:" + * + * SPEC (1) "The element declaration's {target namespace} is ·valid· + * with respect to the wildcard's {namespace constraint} as defined by + * Wildcard allows Namespace Name (§3.10.4)." + */ + if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children, + ((xmlSchemaElementPtr) r->children)->targetNamespace) != 0) + return (1); + /* + * SPEC (2) "R's occurrence range is a valid restriction of B's + * occurrence range as defined by Occurrence Range OK (§3.9.6)." + */ + if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs, + b->minOccurs, b->maxOccurs) != 0) + return (1); + + return (0); +} + +/** + * xmlSchemaCheckRCaseRecurseAsIfGroup: + * @ctxt: the schema parser context + * @r: the restricting element declaration particle + * @b: the base model group particle + * + * (3.9.6) Constraints on Particle Schema Components + * Schema Component Constraint: + * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup) + * (rcase-RecurseAsIfGroup) + * + * STATUS: TODO + * + * Returns 0 if the constraints are satisfied, a positive + * error code if not and -1 if an internal error occured. + */ +static int +xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt, + xmlSchemaParticlePtr r, + xmlSchemaParticlePtr b) +{ + /* TODO: Error codes (rcase-RecurseAsIfGroup). */ + TODO + return (0); +} + +/** + * xmlSchemaCheckRCaseNSSubset: + * @ctxt: the schema parser context + * @r: the restricting wildcard particle + * @b: the base wildcard particle + * + * (3.9.6) Constraints on Particle Schema Components + * Schema Component Constraint: + * Particle Derivation OK (Any:Any -- NSSubset) + * (rcase-NSSubset) + * + * STATUS: complete + * + * Returns 0 if the constraints are satisfied, a positive + * error code if not and -1 if an internal error occured. + */ +static int +xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt, + xmlSchemaParticlePtr r, + xmlSchemaParticlePtr b, + int isAnyTypeBase) +{ + /* TODO: Error codes (rcase-NSSubset). */ + /* + * SPEC (1) "R's occurrence range is a valid restriction of B's + * occurrence range as defined by Occurrence Range OK (§3.9.6)." + */ + if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs, + b->minOccurs, b->maxOccurs)) + return (1); + /* + * SPEC (2) "R's {namespace constraint} must be an intensional subset + * of B's {namespace constraint} as defined by Wildcard Subset (§3.10.6)." + */ + if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children, + (xmlSchemaWildcardPtr) b->children)) + return (1); + /* + * SPEC (3) "Unless B is the content model wildcard of the ·ur-type + * definition·, R's {process contents} must be identical to or stronger + * than B's {process contents}, where strict is stronger than lax is + * stronger than skip." + */ + if (! isAnyTypeBase) { + if ( ((xmlSchemaWildcardPtr) r->children)->processContents < + ((xmlSchemaWildcardPtr) b->children)->processContents) + return (1); + } + + return (0); +} + +/** + * xmlSchemaCheckCOSParticleRestrict: + * @ctxt: the schema parser context + * @type: the complex type definition + * + * (3.9.6) Constraints on Particle Schema Components + * Schema Component Constraint: + * Particle Valid (Restriction) (cos-particle-restrict) + * + * STATUS: TODO + * + * Returns 0 if the constraints are satisfied, a positive + * error code if not and -1 if an internal error occured. + */ +static int +xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt, + xmlSchemaParticlePtr r, + xmlSchemaParticlePtr b) +{ + int ret = 0; + + /*part = WXS_TYPE_PARTICLE(type); + basePart = WXS_TYPE_PARTICLE(base); + */ + + TODO + + /* + * SPEC (1) "They are the same particle." + */ + if (r == b) + return (0); + + + return (0); +} + +/** + * xmlSchemaCheckRCaseNSRecurseCheckCardinality: + * @ctxt: the schema parser context + * @r: the model group particle + * @b: the base wildcard particle + * + * (3.9.6) Constraints on Particle Schema Components + * Schema Component Constraint: + * Particle Derivation OK (All/Choice/Sequence:Any -- + * NSRecurseCheckCardinality) + * (rcase-NSRecurseCheckCardinality) + * + * STATUS: TODO: subst-groups + * + * Returns 0 if the constraints are satisfied, a positive + * error code if not and -1 if an internal error occured. + */ +static int +xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt, + xmlSchemaParticlePtr r, + xmlSchemaParticlePtr b) +{ + xmlSchemaParticlePtr part; + /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */ + if ((r->children == NULL) || (r->children->children == NULL)) + return (-1); + /* + * SPEC "For a group particle to be a ·valid restriction· of a + * wildcard particle..." + * + * SPEC (1) "Every member of the {particles} of the group is a ·valid + * restriction· of the wildcard as defined by + * Particle Valid (Restriction) (§3.9.6)." + */ + part = (xmlSchemaParticlePtr) r->children->children; + do { + if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b)) + return (1); + part = (xmlSchemaParticlePtr) part->next; + } while (part != NULL); + /* + * SPEC (2) "The effective total range of the group [...] is a + * valid restriction of B's occurrence range as defined by + * Occurrence Range OK (§3.9.6)." + */ + if (xmlSchemaCheckParticleRangeOK( + xmlSchemaGetParticleTotalRangeMin(r), + xmlSchemaGetParticleTotalRangeMax(r), + b->minOccurs, b->maxOccurs) != 0) + return (1); + return (0); +} + +/** + * xmlSchemaCheckRCaseRecurse: + * @ctxt: the schema parser context + * @r: the or model group particle + * @b: the base or model group particle + * + * (3.9.6) Constraints on Particle Schema Components + * Schema Component Constraint: + * Particle Derivation OK (All:All,Sequence:Sequence -- + Recurse) + * (rcase-Recurse) + * + * STATUS: ? + * TODO: subst-groups + * + * Returns 0 if the constraints are satisfied, a positive + * error code if not and -1 if an internal error occured. + */ +static int +xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt, + xmlSchemaParticlePtr r, + xmlSchemaParticlePtr b) +{ + /* xmlSchemaParticlePtr part; */ + /* TODO: Error codes (rcase-Recurse). */ + if ((r->children == NULL) || (b->children == NULL) || + (r->children->type != b->children->type)) + return (-1); + /* + * SPEC "For an all or sequence group particle to be a ·valid + * restriction· of another group particle with the same {compositor}..." + * + * SPEC (1) "R's occurrence range is a valid restriction of B's + * occurrence range as defined by Occurrence Range OK (§3.9.6)." + */ + if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs, + b->minOccurs, b->maxOccurs)) + return (1); + + + return (0); +} + +#endif + +#define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \ + xmlSchemaPCustomErrExt(pctxt, \ + XML_SCHEMAP_INVALID_FACET_VALUE, \ + WXS_BASIC_CAST fac1, fac1->node, \ + "It is an error for both '%s' and '%s' to be specified on the "\ + "same type definition", \ + BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \ + BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL); + +#define FACET_RESTR_ERR(fac1, msg) \ + xmlSchemaPCustomErr(pctxt, \ + XML_SCHEMAP_INVALID_FACET_VALUE, \ + WXS_BASIC_CAST fac1, fac1->node, \ + msg, NULL); + +#define FACET_RESTR_FIXED_ERR(fac) \ + xmlSchemaPCustomErr(pctxt, \ + XML_SCHEMAP_INVALID_FACET_VALUE, \ + WXS_BASIC_CAST fac, fac->node, \ + "The base type's facet is 'fixed', thus the value must not " \ + "differ", NULL); + +static void +xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt, + xmlSchemaFacetPtr facet1, + xmlSchemaFacetPtr facet2, + int lessGreater, + int orEqual, + int ofBase) +{ + xmlChar *msg = NULL; + + msg = xmlStrdup(BAD_CAST "'"); + msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type)); + msg = xmlStrcat(msg, BAD_CAST "' has to be"); + if (lessGreater == 0) + msg = xmlStrcat(msg, BAD_CAST " equal to"); + if (lessGreater == 1) + msg = xmlStrcat(msg, BAD_CAST " greater than"); + else + msg = xmlStrcat(msg, BAD_CAST " less than"); + + if (orEqual) + msg = xmlStrcat(msg, BAD_CAST " or equal to"); + msg = xmlStrcat(msg, BAD_CAST " '"); + msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type)); + if (ofBase) + msg = xmlStrcat(msg, BAD_CAST "' of the base type"); + else + msg = xmlStrcat(msg, BAD_CAST "'"); + + xmlSchemaPCustomErr(pctxt, + XML_SCHEMAP_INVALID_FACET_VALUE, + WXS_BASIC_CAST facet1, NULL, + (const char *) msg, NULL); + + if (msg != NULL) + xmlFree(msg); +} + +/* +* xmlSchemaDeriveAndValidateFacets: +* +* Schema Component Constraint: Simple Type Restriction (Facets) +* (st-restrict-facets) +*/ +static int +xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt, + xmlSchemaTypePtr type) +{ + xmlSchemaTypePtr base = type->baseType; + xmlSchemaFacetLinkPtr link, cur, last = NULL; + xmlSchemaFacetPtr facet, bfacet, + flength = NULL, ftotdig = NULL, ffracdig = NULL, + fmaxlen = NULL, fminlen = NULL, /* facets of the current type */ + fmininc = NULL, fmaxinc = NULL, + fminexc = NULL, fmaxexc = NULL, + bflength = NULL, bftotdig = NULL, bffracdig = NULL, + bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */ + bfmininc = NULL, bfmaxinc = NULL, + bfminexc = NULL, bfmaxexc = NULL; + int res; /* err = 0, fixedErr; */ + + /* + * SPEC st-restrict-facets 1: + * "The {variety} of R is the same as that of B." + */ + /* + * SPEC st-restrict-facets 2: + * "If {variety} is atomic, the {primitive type definition} + * of R is the same as that of B." + * + * NOTE: we leave 1 & 2 out for now, since this will be + * satisfied by the derivation process. + * CONSTRUCTION TODO: Maybe needed if using a construction API. + */ + /* + * SPEC st-restrict-facets 3: + * "The {facets} of R are the union of S and the {facets} + * of B, eliminating duplicates. To eliminate duplicates, + * when a facet of the same kind occurs in both S and the + * {facets} of B, the one in the {facets} of B is not + * included, with the exception of enumeration and pattern + * facets, for which multiple occurrences with distinct values + * are allowed." + */ + + if ((type->facetSet == NULL) && (base->facetSet == NULL)) + return (0); + + last = type->facetSet; + if (last != NULL) + while (last->next != NULL) + last = last->next; + + for (cur = type->facetSet; cur != NULL; cur = cur->next) { + facet = cur->facet; + switch (facet->type) { + case XML_SCHEMA_FACET_LENGTH: + flength = facet; break; + case XML_SCHEMA_FACET_MINLENGTH: + fminlen = facet; break; + case XML_SCHEMA_FACET_MININCLUSIVE: + fmininc = facet; break; + case XML_SCHEMA_FACET_MINEXCLUSIVE: + fminexc = facet; break; + case XML_SCHEMA_FACET_MAXLENGTH: + fmaxlen = facet; break; + case XML_SCHEMA_FACET_MAXINCLUSIVE: + fmaxinc = facet; break; + case XML_SCHEMA_FACET_MAXEXCLUSIVE: + fmaxexc = facet; break; + case XML_SCHEMA_FACET_TOTALDIGITS: + ftotdig = facet; break; + case XML_SCHEMA_FACET_FRACTIONDIGITS: + ffracdig = facet; break; + default: + break; + } + } + for (cur = base->facetSet; cur != NULL; cur = cur->next) { + facet = cur->facet; + switch (facet->type) { + case XML_SCHEMA_FACET_LENGTH: + bflength = facet; break; + case XML_SCHEMA_FACET_MINLENGTH: + bfminlen = facet; break; + case XML_SCHEMA_FACET_MININCLUSIVE: + bfmininc = facet; break; + case XML_SCHEMA_FACET_MINEXCLUSIVE: + bfminexc = facet; break; + case XML_SCHEMA_FACET_MAXLENGTH: + bfmaxlen = facet; break; + case XML_SCHEMA_FACET_MAXINCLUSIVE: + bfmaxinc = facet; break; + case XML_SCHEMA_FACET_MAXEXCLUSIVE: + bfmaxexc = facet; break; + case XML_SCHEMA_FACET_TOTALDIGITS: + bftotdig = facet; break; + case XML_SCHEMA_FACET_FRACTIONDIGITS: + bffracdig = facet; break; + default: + break; + } + } + /* + * length and minLength or maxLength (2.2) + (3.2) + */ + if (flength && (fminlen || fmaxlen)) { + FACET_RESTR_ERR(flength, "It is an error for both 'length' and " + "either of 'minLength' or 'maxLength' to be specified on " + "the same type definition") + } + /* + * Mutual exclusions in the same derivation step. + */ + if ((fmaxinc) && (fmaxexc)) { + /* + * SCC "maxInclusive and maxExclusive" + */ + FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc) + } + if ((fmininc) && (fminexc)) { + /* + * SCC "minInclusive and minExclusive" + */ + FACET_RESTR_MUTUAL_ERR(fmininc, fminexc) + } + + if (flength && bflength) { + /* + * SCC "length valid restriction" + * The values have to be equal. + */ + res = xmlSchemaCompareValues(flength->val, bflength->val); + if (res == -2) + goto internal_error; + if (res != 0) + xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1); + if ((res != 0) && (bflength->fixed)) { + FACET_RESTR_FIXED_ERR(flength) + } + + } + if (fminlen && bfminlen) { + /* + * SCC "minLength valid restriction" + * minLength >= BASE minLength + */ + res = xmlSchemaCompareValues(fminlen->val, bfminlen->val); + if (res == -2) + goto internal_error; + if (res == -1) + xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1); + if ((res != 0) && (bfminlen->fixed)) { + FACET_RESTR_FIXED_ERR(fminlen) + } + } + if (fmaxlen && bfmaxlen) { + /* + * SCC "maxLength valid restriction" + * maxLength <= BASE minLength + */ + res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val); + if (res == -2) + goto internal_error; + if (res == 1) + xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1); + if ((res != 0) && (bfmaxlen->fixed)) { + FACET_RESTR_FIXED_ERR(fmaxlen) + } + } + /* + * SCC "length and minLength or maxLength" + */ + if (! flength) + flength = bflength; + if (flength) { + if (! fminlen) + flength = bflength; + if (fminlen) { + /* (1.1) length >= minLength */ + res = xmlSchemaCompareValues(flength->val, fminlen->val); + if (res == -2) + goto internal_error; + if (res == -1) + xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0); + } + if (! fmaxlen) + fmaxlen = bfmaxlen; + if (fmaxlen) { + /* (2.1) length <= maxLength */ + res = xmlSchemaCompareValues(flength->val, fmaxlen->val); + if (res == -2) + goto internal_error; + if (res == 1) + xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0); + } + } + if (fmaxinc) { + /* + * "maxInclusive" + */ + if (fmininc) { + /* SCC "maxInclusive >= minInclusive" */ + res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val); + if (res == -2) + goto internal_error; + if (res == -1) { + xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0); + } + } + /* + * SCC "maxInclusive valid restriction" + */ + if (bfmaxinc) { + /* maxInclusive <= BASE maxInclusive */ + res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val); + if (res == -2) + goto internal_error; + if (res == 1) + xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1); + if ((res != 0) && (bfmaxinc->fixed)) { + FACET_RESTR_FIXED_ERR(fmaxinc) + } + } + if (bfmaxexc) { + /* maxInclusive < BASE maxExclusive */ + res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val); + if (res == -2) + goto internal_error; + if (res != -1) { + xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1); + } + } + if (bfmininc) { + /* maxInclusive >= BASE minInclusive */ + res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val); + if (res == -2) + goto internal_error; + if (res == -1) { + xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1); + } + } + if (bfminexc) { + /* maxInclusive > BASE minExclusive */ + res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val); + if (res == -2) + goto internal_error; + if (res != 1) { + xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1); + } + } + } + if (fmaxexc) { + /* + * "maxExclusive >= minExclusive" + */ + if (fminexc) { + res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val); + if (res == -2) + goto internal_error; + if (res == -1) { + xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0); + } + } + /* + * "maxExclusive valid restriction" + */ + if (bfmaxexc) { + /* maxExclusive <= BASE maxExclusive */ + res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val); + if (res == -2) + goto internal_error; + if (res == 1) { + xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1); + } + if ((res != 0) && (bfmaxexc->fixed)) { + FACET_RESTR_FIXED_ERR(fmaxexc) + } + } + if (bfmaxinc) { + /* maxExclusive <= BASE maxInclusive */ + res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val); + if (res == -2) + goto internal_error; + if (res == 1) { + xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1); + } + } + if (bfmininc) { + /* maxExclusive > BASE minInclusive */ + res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val); + if (res == -2) + goto internal_error; + if (res != 1) { + xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1); + } + } + if (bfminexc) { + /* maxExclusive > BASE minExclusive */ + res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val); + if (res == -2) + goto internal_error; + if (res != 1) { + xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1); + } + } + } + if (fminexc) { + /* + * "minExclusive < maxInclusive" + */ + if (fmaxinc) { + res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val); + if (res == -2) + goto internal_error; + if (res != -1) { + xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0); + } + } + /* + * "minExclusive valid restriction" + */ + if (bfminexc) { + /* minExclusive >= BASE minExclusive */ + res = xmlSchemaCompareValues(fminexc->val, bfminexc->val); + if (res == -2) + goto internal_error; + if (res == -1) { + xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1); + } + if ((res != 0) && (bfminexc->fixed)) { + FACET_RESTR_FIXED_ERR(fminexc) + } + } + if (bfmaxinc) { + /* minExclusive <= BASE maxInclusive */ + res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val); + if (res == -2) + goto internal_error; + if (res == 1) { + xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1); + } + } + if (bfmininc) { + /* minExclusive >= BASE minInclusive */ + res = xmlSchemaCompareValues(fminexc->val, bfmininc->val); + if (res == -2) + goto internal_error; + if (res == -1) { + xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1); + } + } + if (bfmaxexc) { + /* minExclusive < BASE maxExclusive */ + res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val); + if (res == -2) + goto internal_error; + if (res != -1) { + xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1); + } + } + } + if (fmininc) { + /* + * "minInclusive < maxExclusive" + */ + if (fmaxexc) { + res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val); + if (res == -2) + goto internal_error; + if (res != -1) { + xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0); + } + } + /* + * "minExclusive valid restriction" + */ + if (bfmininc) { + /* minInclusive >= BASE minInclusive */ + res = xmlSchemaCompareValues(fmininc->val, bfmininc->val); + if (res == -2) + goto internal_error; + if (res == -1) { + xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1); + } + if ((res != 0) && (bfmininc->fixed)) { + FACET_RESTR_FIXED_ERR(fmininc) + } + } + if (bfmaxinc) { + /* minInclusive <= BASE maxInclusive */ + res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val); + if (res == -2) + goto internal_error; + if (res == 1) { + xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1); + } + } + if (bfminexc) { + /* minInclusive > BASE minExclusive */ + res = xmlSchemaCompareValues(fmininc->val, bfminexc->val); + if (res == -2) + goto internal_error; + if (res != 1) + xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1); + } + if (bfmaxexc) { + /* minInclusive < BASE maxExclusive */ + res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val); + if (res == -2) + goto internal_error; + if (res != -1) + xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1); + } + } + if (ftotdig && bftotdig) { + /* + * SCC " totalDigits valid restriction" + * totalDigits <= BASE totalDigits + */ + res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val); + if (res == -2) + goto internal_error; + if (res == 1) + xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig, + -1, 1, 1); + if ((res != 0) && (bftotdig->fixed)) { + FACET_RESTR_FIXED_ERR(ftotdig) + } + } + if (ffracdig && bffracdig) { + /* + * SCC "fractionDigits valid restriction" + * fractionDigits <= BASE fractionDigits + */ + res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val); + if (res == -2) + goto internal_error; + if (res == 1) + xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig, + -1, 1, 1); + if ((res != 0) && (bffracdig->fixed)) { + FACET_RESTR_FIXED_ERR(ffracdig) + } + } + /* + * SCC "fractionDigits less than or equal to totalDigits" + */ + if (! ftotdig) + ftotdig = bftotdig; + if (! ffracdig) + ffracdig = bffracdig; + if (ftotdig && ffracdig) { + res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val); + if (res == -2) + goto internal_error; + if (res == 1) + xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig, + -1, 1, 0); + } + /* + * *Enumerations* won' be added here, since only the first set + * of enumerations in the ancestor-or-self axis is used + * for validation, plus we need to use the base type of those + * enumerations for whitespace. + * + * *Patterns*: won't be add here, since they are ORed at + * type level and ANDed at ancestor level. This will + * happed during validation by walking the base axis + * of the type. + */ + for (cur = base->facetSet; cur != NULL; cur = cur->next) { + bfacet = cur->facet; + /* + * Special handling of enumerations and patterns. + * TODO: hmm, they should not appear in the set, so remove this. + */ + if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) || + (bfacet->type == XML_SCHEMA_FACET_ENUMERATION)) + continue; + /* + * Search for a duplicate facet in the current type. + */ + link = type->facetSet; + /* err = 0; */ + /* fixedErr = 0; */ + while (link != NULL) { + facet = link->facet; + if (facet->type == bfacet->type) { + switch (facet->type) { + case XML_SCHEMA_FACET_WHITESPACE: + /* + * The whitespace must be stronger. + */ + if (facet->whitespace < bfacet->whitespace) { + FACET_RESTR_ERR(flength, + "The 'whitespace' value has to be equal to " + "or stronger than the 'whitespace' value of " + "the base type") + } + if ((bfacet->fixed) && + (facet->whitespace != bfacet->whitespace)) { + FACET_RESTR_FIXED_ERR(facet) + } + break; + default: + break; + } + /* Duplicate found. */ + break; + } + link = link->next; + } + /* + * If no duplicate was found: add the base types's facet + * to the set. + */ + if (link == NULL) { + link = (xmlSchemaFacetLinkPtr) + xmlMalloc(sizeof(xmlSchemaFacetLink)); + if (link == NULL) { + xmlSchemaPErrMemory(pctxt, + "deriving facets, creating a facet link", NULL); + return (-1); + } + link->facet = cur->facet; + link->next = NULL; + if (last == NULL) + type->facetSet = link; + else + last->next = link; + last = link; + } + + } + + return (0); +internal_error: + PERROR_INT("xmlSchemaDeriveAndValidateFacets", + "an error occured"); + return (-1); +} + +static int +xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt, + xmlSchemaTypePtr type) +{ + xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink; + /* + * The actual value is then formed by replacing any union type + * definition in the ·explicit members· with the members of their + * {member type definitions}, in order. + * + * TODO: There's a bug entry at + * "http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0287.html" + * which indicates that we'll keep the union types the future. + */ + link = type->memberTypes; + while (link != NULL) { + + if (WXS_IS_TYPE_NOT_FIXED(link->type)) + xmlSchemaTypeFixup(link->type, ACTXT_CAST pctxt); + + if (WXS_IS_UNION(link->type)) { + subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type); + if (subLink != NULL) { + link->type = subLink->type; + if (subLink->next != NULL) { + lastLink = link->next; + subLink = subLink->next; + prevLink = link; + while (subLink != NULL) { + newLink = (xmlSchemaTypeLinkPtr) + xmlMalloc(sizeof(xmlSchemaTypeLink)); + if (newLink == NULL) { + xmlSchemaPErrMemory(pctxt, "allocating a type link", + NULL); + return (-1); + } + newLink->type = subLink->type; + prevLink->next = newLink; + prevLink = newLink; + newLink->next = lastLink; + + subLink = subLink->next; + } + } + } + } + link = link->next; + } + return (0); +} + +static void +xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type) +{ + int has = 0, needVal = 0, normVal = 0; + + has = (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0; + if (has) { + needVal = (type->baseType->flags & + XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0; + normVal = (type->baseType->flags & + XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0; + } + if (type->facets != NULL) { + xmlSchemaFacetPtr fac; + + for (fac = type->facets; fac != NULL; fac = fac->next) { + switch (fac->type) { + case XML_SCHEMA_FACET_WHITESPACE: + break; + case XML_SCHEMA_FACET_PATTERN: + normVal = 1; + has = 1; + break; + case XML_SCHEMA_FACET_ENUMERATION: + needVal = 1; + normVal = 1; + has = 1; + break; + default: + has = 1; + break; + } + } + } + if (normVal) + type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED; + if (needVal) + type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE; + if (has) + type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS; + + if (has && (! needVal) && WXS_IS_ATOMIC(type)) { + xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type); + /* + * OPTIMIZE VAL TODO: Some facets need a computed value. + */ + if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) && + (prim->builtInType != XML_SCHEMAS_STRING)) { + type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE; + } + } +} + +static int +xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type) +{ + + + /* + * Evaluate the whitespace-facet value. + */ + if (WXS_IS_LIST(type)) { + type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE; + return (0); + } else if (WXS_IS_UNION(type)) + return (0); + + if (type->facetSet != NULL) { + xmlSchemaFacetLinkPtr lin; + + for (lin = type->facetSet; lin != NULL; lin = lin->next) { + if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) { + switch (lin->facet->whitespace) { + case XML_SCHEMAS_FACET_PRESERVE: + type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE; + break; + case XML_SCHEMAS_FACET_REPLACE: + type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE; + break; + case XML_SCHEMAS_FACET_COLLAPSE: + type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE; + break; + default: + return (-1); + } + return (0); + } + } + } + /* + * For all ·atomic· datatypes other than string (and types ·derived· + * by ·restriction· from it) the value of whiteSpace is fixed to + * collapse + */ + { + xmlSchemaTypePtr anc; + + for (anc = type->baseType; anc != NULL && + anc->builtInType != XML_SCHEMAS_ANYTYPE; + anc = anc->baseType) { + + if (anc->type == XML_SCHEMA_TYPE_BASIC) { + if (anc->builtInType == XML_SCHEMAS_NORMSTRING) { + type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE; + + } else if ((anc->builtInType == XML_SCHEMAS_STRING) || + (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) { + type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE; + + } else + type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE; + break; + } + } + } + return (0); +} + +static int +xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt, + xmlSchemaTypePtr type) +{ + if (type->type != XML_SCHEMA_TYPE_SIMPLE) + return(0); + if (! WXS_IS_TYPE_NOT_FIXED_1(type)) + return(0); + type->flags |= XML_SCHEMAS_TYPE_FIXUP_1; + + if (WXS_IS_LIST(type)) { + /* + * Corresponds to ... + */ + if (type->subtypes == NULL) { + /* + * This one is really needed, so get out. + */ + PERROR_INT("xmlSchemaFixupSimpleTypeStageOne", + "list type has no item-type assigned"); + return(-1); + } + } else if (WXS_IS_UNION(type)) { + /* + * Corresponds to ... + */ + if (type->memberTypes == NULL) { + /* + * This one is really needed, so get out. + */ + PERROR_INT("xmlSchemaFixupSimpleTypeStageOne", + "union type has no member-types assigned"); + return(-1); + } + } else { + /* + * Corresponds to ... + */ + if (type->baseType == NULL) { + PERROR_INT("xmlSchemaFixupSimpleTypeStageOne", + "type has no base-type assigned"); + return(-1); + } + if (WXS_IS_TYPE_NOT_FIXED_1(type->baseType)) + if (xmlSchemaFixupSimpleTypeStageOne(pctxt, type->baseType) == -1) + return(-1); + /* + * Variety + * If the alternative is chosen, then the + * {variety} of the {base type definition}. + */ + if (WXS_IS_ATOMIC(type->baseType)) + type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC; + else if (WXS_IS_LIST(type->baseType)) { + type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST; + /* + * Inherit the itemType. + */ + type->subtypes = type->baseType->subtypes; + } else if (WXS_IS_UNION(type->baseType)) { + type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION; + /* + * NOTE that we won't assign the memberTypes of the base, + * since this will make trouble when freeing them; we will + * use a lookup function to access them instead. + */ + } + } + return(0); +} + +#ifdef DEBUG_TYPE +static void +xmlSchemaDebugFixedType(xmlSchemaParserCtxtPtr pctxt, + xmlSchemaTypePtr type) +{ + if (type->node != NULL) { + xmlGenericError(xmlGenericErrorContext, + "Type of %s : %s:%d :", name, + type->node->doc->URL, + xmlGetLineNo(type->node)); + } else { + xmlGenericError(xmlGenericErrorContext, "Type of %s :", name); + } + if ((WXS_IS_SIMPLE(type)) || (WXS_IS_COMPLEX(type))) { + switch (type->contentType) { + case XML_SCHEMA_CONTENT_SIMPLE: + xmlGenericError(xmlGenericErrorContext, "simple\n"); + break; + case XML_SCHEMA_CONTENT_ELEMENTS: + xmlGenericError(xmlGenericErrorContext, "elements\n"); + break; + case XML_SCHEMA_CONTENT_UNKNOWN: + xmlGenericError(xmlGenericErrorContext, "unknown !!!\n"); + break; + case XML_SCHEMA_CONTENT_EMPTY: + xmlGenericError(xmlGenericErrorContext, "empty\n"); + break; + case XML_SCHEMA_CONTENT_MIXED: + if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr) + type->subtypes)) + xmlGenericError(xmlGenericErrorContext, + "mixed as emptiable particle\n"); + else + xmlGenericError(xmlGenericErrorContext, "mixed\n"); + break; + /* Removed, since not used. */ + /* + case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS: + xmlGenericError(xmlGenericErrorContext, "mixed or elems\n"); + break; + */ + case XML_SCHEMA_CONTENT_BASIC: + xmlGenericError(xmlGenericErrorContext, "basic\n"); + break; + default: + xmlGenericError(xmlGenericErrorContext, + "not registered !!!\n"); + break; + } + } +} +#endif + +/* +* 3.14.6 Constraints on Simple Type Definition Schema Components +*/ +static int +xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt, + xmlSchemaTypePtr type) +{ + int res, olderrs = pctxt->nberrors; + + if (type->type != XML_SCHEMA_TYPE_SIMPLE) + return(-1); + + if (! WXS_IS_TYPE_NOT_FIXED(type)) + return(0); + + type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED; + type->contentType = XML_SCHEMA_CONTENT_SIMPLE; + + if (type->baseType == NULL) { + PERROR_INT("xmlSchemaFixupSimpleTypeStageTwo", + "missing baseType"); + goto exit_failure; + } + if (WXS_IS_TYPE_NOT_FIXED(type->baseType)) + xmlSchemaTypeFixup(type->baseType, ACTXT_CAST pctxt); + /* + * If a member type of a union is a union itself, we need to substitute + * that member type for its member types. + * NOTE that this might change in WXS 1.1; i.e. we will keep the union + * types in WXS 1.1. + */ + if ((type->memberTypes != NULL) && + (xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1)) + return(-1); + /* + * SPEC src-simple-type 1 + * "The corresponding simple type definition, if any, must satisfy + * the conditions set out in Constraints on Simple Type Definition + * Schema Components (§3.14.6)." + */ + /* + * Schema Component Constraint: Simple Type Definition Properties Correct + * (st-props-correct) + */ + res = xmlSchemaCheckSTPropsCorrect(pctxt, type); + HFAILURE HERROR + /* + * Schema Component Constraint: Derivation Valid (Restriction, Simple) + * (cos-st-restricts) + */ + res = xmlSchemaCheckCOSSTRestricts(pctxt, type); + HFAILURE HERROR + /* + * TODO: Removed the error report, since it got annoying to get an + * extra error report, if anything failed until now. + * Enable this if needed. + * + * xmlSchemaPErr(ctxt, type->node, + * XML_SCHEMAP_SRC_SIMPLE_TYPE_1, + * "Simple type '%s' does not satisfy the constraints " + * "on simple type definitions.\n", + * type->name, NULL); + */ + /* + * Schema Component Constraint: Simple Type Restriction (Facets) + * (st-restrict-facets) + */ + res = xmlSchemaCheckFacetValues(type, pctxt); + HFAILURE HERROR + if ((type->facetSet != NULL) || + (type->baseType->facetSet != NULL)) { + res = xmlSchemaDeriveAndValidateFacets(pctxt, type); + HFAILURE HERROR + } + /* + * Whitespace value. + */ + res = xmlSchemaTypeFixupWhitespace(type); + HFAILURE HERROR + xmlSchemaTypeFixupOptimFacets(type); + +exit_error: +#ifdef DEBUG_TYPE + xmlSchemaDebugFixedType(pctxt, type); +#endif + if (olderrs != pctxt->nberrors) + return(pctxt->err); + return(0); + +exit_failure: +#ifdef DEBUG_TYPE + xmlSchemaDebugFixedType(pctxt, type); +#endif + return(-1); +} + +static int +xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt, + xmlSchemaTypePtr type) +{ + int res = 0, olderrs = pctxt->nberrors; + xmlSchemaTypePtr baseType = type->baseType; + + if (! WXS_IS_TYPE_NOT_FIXED(type)) + return(0); + type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED; + if (baseType == NULL) { + PERROR_INT("xmlSchemaFixupComplexType", + "missing baseType"); + goto exit_failure; + } + /* + * Fixup the base type. + */ + if (WXS_IS_TYPE_NOT_FIXED(baseType)) + xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt); + if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) { + /* + * Skip fixup if the base type is invalid. + * TODO: Generate a warning! + */ + return(0); + } + /* + * This basically checks if the base type can be derived. + */ + res = xmlSchemaCheckSRCCT(pctxt, type); + HFAILURE HERROR + /* + * Fixup the content type. + */ + if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) { + /* + * Corresponds to ... + */ + if ((WXS_IS_COMPLEX(baseType)) && + (baseType->contentTypeDef != NULL) && + (WXS_IS_RESTRICTION(type))) { + xmlSchemaTypePtr contentBase, content; +#ifdef ENABLE_NAMED_LOCALS + char buf[30]; + const xmlChar *tmpname; +#endif + /* + * SPEC (1) If + base type is , + * "whose own {content type} is a simple type..." + */ + if (type->contentTypeDef != NULL) { + /* + * SPEC (1.1) "the simple type definition corresponding to the + * among the [children] of if there + * is one;" + * Note that this " among the [children]" was put + * into ->contentTypeDef during parsing. + */ + contentBase = type->contentTypeDef; + type->contentTypeDef = NULL; + } else { + /* + * (1.2) "...otherwise ( has no + * among its [children]), the simple type definition which + * is the {content type} of the ... base type." + */ + contentBase = baseType->contentTypeDef; + } + /* + * SPEC + * "... a simple type definition which restricts the simple + * type definition identified in clause 1.1 or clause 1.2 + * with a set of facet components" + * + * Create the anonymous simple type, which will be the content + * type of the complex type. + */ +#ifdef ENABLE_NAMED_LOCALS + snprintf(buf, 29, "#scST%d", ++(pctxt->counter)); + tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1); + content = xmlSchemaAddType(pctxt, pctxt->schema, + XML_SCHEMA_TYPE_SIMPLE, tmpname, type->targetNamespace, + type->node, 0); +#else + content = xmlSchemaAddType(pctxt, pctxt->schema, + XML_SCHEMA_TYPE_SIMPLE, NULL, type->targetNamespace, + type->node, 0); +#endif + if (content == NULL) + goto exit_failure; + /* + * We will use the same node as for the + * to have it somehow anchored in the schema doc. + */ + content->type = XML_SCHEMA_TYPE_SIMPLE; + content->baseType = contentBase; + /* + * Move the facets, previously anchored on the + * complexType during parsing. + */ + content->facets = type->facets; + type->facets = NULL; + content->facetSet = type->facetSet; + type->facetSet = NULL; + + type->contentTypeDef = content; + if (WXS_IS_TYPE_NOT_FIXED(contentBase)) + xmlSchemaTypeFixup(contentBase, ACTXT_CAST pctxt); + /* + * Fixup the newly created type. We don't need to check + * for circularity here. + */ + res = xmlSchemaFixupSimpleTypeStageOne(pctxt, content); + HFAILURE HERROR + res = xmlSchemaFixupSimpleTypeStageTwo(pctxt, content); + HFAILURE HERROR + + } else if ((WXS_IS_COMPLEX(baseType)) && + (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) && + (WXS_IS_RESTRICTION(type))) { + /* + * SPEC (2) If + base is a mixed with + * an emptiable particle, then a simple type definition which + * restricts the 's child. + */ + if ((type->contentTypeDef == NULL) || + (type->contentTypeDef->baseType == NULL)) { + /* + * TODO: Check if this ever happens. + */ + xmlSchemaPCustomErr(pctxt, + XML_SCHEMAP_INTERNAL, + WXS_BASIC_CAST type, NULL, + "Internal error: xmlSchemaTypeFixup, " + "complex type '%s': the " + "is missing a child, but was not catched " + "by xmlSchemaCheckSRCCT()", type->name); + goto exit_failure; + } + } else if ((WXS_IS_COMPLEX(baseType)) && WXS_IS_EXTENSION(type)) { + /* + * SPEC (3) If + base is with + * content, "...then the {content type} of that + * complex type definition" + */ + if (baseType->contentTypeDef == NULL) { + /* + * TODO: Check if this ever happens. xmlSchemaCheckSRCCT + * should have catched this already. + */ + xmlSchemaPCustomErr(pctxt, + XML_SCHEMAP_INTERNAL, + WXS_BASIC_CAST type, NULL, + "Internal error: xmlSchemaTypeFixup, " + "complex type '%s': the ed base type is " + "a complex type with no simple content type", + type->name); + goto exit_failure; + } + type->contentTypeDef = baseType->contentTypeDef; + } else if ((WXS_IS_SIMPLE(baseType)) && WXS_IS_EXTENSION(type)) { + /* + * SPEC (4) + base is + * "... then that simple type definition" + */ + type->contentTypeDef = baseType; + } else { + /* + * TODO: Check if this ever happens. + */ + xmlSchemaPCustomErr(pctxt, + XML_SCHEMAP_INTERNAL, + WXS_BASIC_CAST type, NULL, + "Internal error: xmlSchemaTypeFixup, " + "complex type '%s' with : unhandled " + "derivation case", type->name); + goto exit_failure; + } + } else { + int dummySequence = 0; + xmlSchemaParticlePtr particle = + (xmlSchemaParticlePtr) type->subtypes; + /* + * Corresponds to ... + * + * NOTE that the effective mixed was already set during parsing of + * and ; its flag value is + * XML_SCHEMAS_TYPE_MIXED. + * + * Compute the "effective content": + * (2.1.1) + (2.1.2) + (2.1.3) + */ + if ((particle == NULL) || + ((particle->type == XML_SCHEMA_TYPE_PARTICLE) && + ((particle->children->type == XML_SCHEMA_TYPE_ALL) || + (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) || + ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) && + (particle->minOccurs == 0))) && + ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) { + if (type->flags & XML_SCHEMAS_TYPE_MIXED) { + /* + * SPEC (2.1.4) "If the ·effective mixed· is true, then + * a particle whose properties are as follows:..." + * + * Empty sequence model group with + * minOccurs/maxOccurs = 1 (i.e. a "particle emptiable"). + * NOTE that we sill assign it the node to + * somehow anchor it in the doc. + */ + if ((particle == NULL) || + (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) { + /* + * Create the particle. + */ + particle = xmlSchemaAddParticle(pctxt, + type->node, 1, 1); + if (particle == NULL) + goto exit_failure; + /* + * Create the model group. + */ /* URGENT TODO: avoid adding to pending items. */ + particle->children = (xmlSchemaTreeItemPtr) + xmlSchemaAddModelGroup(pctxt, pctxt->schema, + XML_SCHEMA_TYPE_SEQUENCE, type->node); + if (particle->children == NULL) + goto exit_failure; + + type->subtypes = (xmlSchemaTypePtr) particle; + } + dummySequence = 1; + type->contentType = XML_SCHEMA_CONTENT_ELEMENTS; + } else { + /* + * SPEC (2.1.5) "otherwise empty" + */ + type->contentType = XML_SCHEMA_CONTENT_EMPTY; + } + } else { + /* + * SPEC (2.2) "otherwise the particle corresponding to the + * , , or among the + * [children]." + */ + type->contentType = XML_SCHEMA_CONTENT_ELEMENTS; + } + /* + * Compute the "content type". + */ + if (WXS_IS_RESTRICTION(type)) { + /* + * SPEC (3.1) "If ..." + * (3.1.1) + (3.1.2) */ + if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) { + if (type->flags & XML_SCHEMAS_TYPE_MIXED) + type->contentType = XML_SCHEMA_CONTENT_MIXED; + } + } else { + /* + * SPEC (3.2) "If ..." + */ + if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) { + /* + * SPEC (3.2.1) + * "If the ·effective content· is empty, then the + * {content type} of the [...] base ..." + */ + type->contentType = baseType->contentType; + type->subtypes = baseType->subtypes; + /* + * Fixes bug #347316: + * This is the case when the base type has a simple + * type definition as content. + */ + type->contentTypeDef = baseType->contentTypeDef; + /* + * NOTE that the effective mixed is ignored here. + */ + } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) { + /* + * SPEC (3.2.2) + */ + if (type->flags & XML_SCHEMAS_TYPE_MIXED) + type->contentType = XML_SCHEMA_CONTENT_MIXED; + } else { + /* + * SPEC (3.2.3) + */ + if (type->flags & XML_SCHEMAS_TYPE_MIXED) + type->contentType = XML_SCHEMA_CONTENT_MIXED; + /* + * "A model group whose {compositor} is sequence and whose + * {particles} are..." + */ + if ((WXS_TYPE_PARTICLE(type) != NULL) && + (WXS_TYPE_PARTICLE_TERM(type) != NULL) && + ((WXS_TYPE_PARTICLE_TERM(type))->type == + XML_SCHEMA_TYPE_ALL)) + { + /* + * SPEC cos-all-limited (1) + */ + xmlSchemaCustomErr(ACTXT_CAST pctxt, + /* TODO: error code */ + XML_SCHEMAP_COS_ALL_LIMITED, + WXS_ITEM_NODE(type), NULL, + "The type has an 'all' model group in its " + "{content type} and thus cannot be derived from " + "a non-empty type, since this would produce a " + "'sequence' model group containing the 'all' " + "model group; 'all' model groups are not " + "allowed to appear inside other model groups", + NULL, NULL); + + } else if ((WXS_TYPE_PARTICLE(baseType) != NULL) && + (WXS_TYPE_PARTICLE_TERM(baseType) != NULL) && + ((WXS_TYPE_PARTICLE_TERM(baseType))->type == + XML_SCHEMA_TYPE_ALL)) + { + /* + * SPEC cos-all-limited (1) + */ + xmlSchemaCustomErr(ACTXT_CAST pctxt, + /* TODO: error code */ + XML_SCHEMAP_COS_ALL_LIMITED, + WXS_ITEM_NODE(type), NULL, + "A type cannot be derived by extension from a type " + "which has an 'all' model group in its " + "{content type}, since this would produce a " + "'sequence' model group containing the 'all' " + "model group; 'all' model groups are not " + "allowed to appear inside other model groups", + NULL, NULL); + + } else if (! dummySequence) { + xmlSchemaTreeItemPtr effectiveContent = + (xmlSchemaTreeItemPtr) type->subtypes; + /* + * Create the particle. + */ + particle = xmlSchemaAddParticle(pctxt, + type->node, 1, 1); + if (particle == NULL) + goto exit_failure; + /* + * Create the "sequence" model group. + */ + particle->children = (xmlSchemaTreeItemPtr) + xmlSchemaAddModelGroup(pctxt, pctxt->schema, + XML_SCHEMA_TYPE_SEQUENCE, type->node); + if (particle->children == NULL) + goto exit_failure; + WXS_TYPE_CONTENTTYPE(type) = (xmlSchemaTypePtr) particle; + /* + * SPEC "the particle of the {content type} of + * the ... base ..." + * Create a duplicate of the base type's particle + * and assign its "term" to it. + */ + particle->children->children = + (xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt, + type->node, + ((xmlSchemaParticlePtr) type->subtypes)->minOccurs, + ((xmlSchemaParticlePtr) type->subtypes)->maxOccurs); + if (particle->children->children == NULL) + goto exit_failure; + particle = (xmlSchemaParticlePtr) + particle->children->children; + particle->children = + ((xmlSchemaParticlePtr) baseType->subtypes)->children; + /* + * SPEC "followed by the ·effective content·." + */ + particle->next = effectiveContent; + /* + * This all will result in: + * new-particle + * --> new-sequence( + * new-particle + * --> base-model, + * this-particle + * --> this-model + * ) + */ + } else { + /* + * This is the case when there is already an empty + * with minOccurs==maxOccurs==1. + * Just add the base types's content type. + * NOTE that, although we miss to add an intermediate + * , this should produce no difference to + * neither the regex compilation of the content model, + * nor to the complex type contraints. + */ + particle->children->children = + (xmlSchemaTreeItemPtr) baseType->subtypes; + } + } + } + } + /* + * Now fixup attribute uses: + * - expand attr. group references + * - intersect attribute wildcards + * - inherit attribute uses of the base type + * - inherit or union attr. wildcards if extending + * - apply attr. use prohibitions if restricting + */ + res = xmlSchemaFixupTypeAttributeUses(pctxt, type); + HFAILURE HERROR + /* + * Apply the complex type component constraints; this will not + * check attributes, since this is done in + * xmlSchemaFixupTypeAttributeUses(). + */ + res = xmlSchemaCheckCTComponent(pctxt, type); + HFAILURE HERROR + +#ifdef DEBUG_TYPE + xmlSchemaDebugFixedType(pctxt, type); +#endif + if (olderrs != pctxt->nberrors) + return(pctxt->err); + else + return(0); + +exit_error: + type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID; +#ifdef DEBUG_TYPE + xmlSchemaDebugFixedType(pctxt, type); +#endif + return(pctxt->err); + +exit_failure: + type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID; +#ifdef DEBUG_TYPE + xmlSchemaDebugFixedType(pctxt, type); +#endif + return(-1); +} + + +/** + * xmlSchemaTypeFixup: + * @typeDecl: the schema type definition + * @ctxt: the schema parser context + * + * Fixes the content model of the type. + * URGENT TODO: We need an int result! + */ +static int +xmlSchemaTypeFixup(xmlSchemaTypePtr type, + xmlSchemaAbstractCtxtPtr actxt) +{ + if (type == NULL) + return(0); + if (actxt->type != XML_SCHEMA_CTXT_PARSER) { + AERROR_INT("xmlSchemaTypeFixup", + "this function needs a parser context"); + return(-1); + } + if (! WXS_IS_TYPE_NOT_FIXED(type)) + return(0); + if (type->type == XML_SCHEMA_TYPE_COMPLEX) + return(xmlSchemaFixupComplexType(PCTXT_CAST actxt, type)); + else if (type->type == XML_SCHEMA_TYPE_SIMPLE) + return(xmlSchemaFixupSimpleTypeStageTwo(PCTXT_CAST actxt, type)); + return(0); +} + +/** + * xmlSchemaCheckFacet: + * @facet: the facet + * @typeDecl: the schema type definition + * @pctxt: the schema parser context or NULL + * @name: the optional name of the type + * + * Checks and computes the values of facets. + * + * Returns 0 if valid, a positive error code if not valid and + * -1 in case of an internal or API error. + */ +int +xmlSchemaCheckFacet(xmlSchemaFacetPtr facet, + xmlSchemaTypePtr typeDecl, + xmlSchemaParserCtxtPtr pctxt, + const xmlChar * name ATTRIBUTE_UNUSED) +{ + int ret = 0, ctxtGiven; + + if ((facet == NULL) || (typeDecl == NULL)) + return(-1); + /* + * TODO: will the parser context be given if used from + * the relaxNG module? + */ + if (pctxt == NULL) + ctxtGiven = 0; + else + ctxtGiven = 1; + + switch (facet->type) { + case XML_SCHEMA_FACET_MININCLUSIVE: + case XML_SCHEMA_FACET_MINEXCLUSIVE: + case XML_SCHEMA_FACET_MAXINCLUSIVE: + case XML_SCHEMA_FACET_MAXEXCLUSIVE: + case XML_SCHEMA_FACET_ENUMERATION: { + /* + * Okay we need to validate the value + * at that point. + */ + xmlSchemaTypePtr base; + + /* 4.3.5.5 Constraints on enumeration Schema Components + * Schema Component Constraint: enumeration valid restriction + * It is an ·error· if any member of {value} is not in the + * ·value space· of {base type definition}. + * + * minInclusive, maxInclusive, minExclusive, maxExclusive: + * The value ·must· be in the + * ·value space· of the ·base type·. + */ + /* + * This function is intended to deliver a compiled value + * on the facet. In this implementation of XML Schemata the + * type holding a facet, won't be a built-in type. + * Thus to ensure that other API + * calls (relaxng) do work, if the given type is a built-in + * type, we will assume that the given built-in type *is + * already* the base type. + */ + if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) { + base = typeDecl->baseType; + if (base == NULL) { + PERROR_INT("xmlSchemaCheckFacet", + "a type user derived type has no base type"); + return (-1); + } + } else + base = typeDecl; + + if (! ctxtGiven) { + /* + * A context is needed if called from RelaxNG. + */ + pctxt = xmlSchemaNewParserCtxt("*"); + if (pctxt == NULL) + return (-1); + } + /* + * NOTE: This call does not check the content nodes, + * since they are not available: + * facet->node is just the node holding the facet + * definition, *not* the attribute holding the *value* + * of the facet. + */ + ret = xmlSchemaVCheckCVCSimpleType( + ACTXT_CAST pctxt, facet->node, base, + facet->value, &(facet->val), 1, 1, 0); + if (ret != 0) { + if (ret < 0) { + /* No error message for RelaxNG. */ + if (ctxtGiven) { + xmlSchemaCustomErr(ACTXT_CAST pctxt, + XML_SCHEMAP_INTERNAL, facet->node, NULL, + "Internal error: xmlSchemaCheckFacet, " + "failed to validate the value '%s' of the " + "facet '%s' against the base type", + facet->value, xmlSchemaFacetTypeToString(facet->type)); + } + goto internal_error; + } + ret = XML_SCHEMAP_INVALID_FACET_VALUE; + /* No error message for RelaxNG. */ + if (ctxtGiven) { + xmlChar *str = NULL; + + xmlSchemaCustomErr(ACTXT_CAST pctxt, + ret, facet->node, WXS_BASIC_CAST facet, + "The value '%s' of the facet does not validate " + "against the base type '%s'", + facet->value, + xmlSchemaFormatQName(&str, + base->targetNamespace, base->name)); + FREE_AND_NULL(str); + } + goto exit; + } else if (facet->val == NULL) { + if (ctxtGiven) { + PERROR_INT("xmlSchemaCheckFacet", + "value was not computed"); + } + TODO + } + break; + } + case XML_SCHEMA_FACET_PATTERN: + facet->regexp = xmlRegexpCompile(facet->value); + if (facet->regexp == NULL) { + ret = XML_SCHEMAP_REGEXP_INVALID; + /* No error message for RelaxNG. */ + if (ctxtGiven) { + xmlSchemaCustomErr(ACTXT_CAST pctxt, + ret, facet->node, WXS_BASIC_CAST typeDecl, + "The value '%s' of the facet 'pattern' is not a " + "valid regular expression", + facet->value, NULL); + } + } + break; + case XML_SCHEMA_FACET_TOTALDIGITS: + case XML_SCHEMA_FACET_FRACTIONDIGITS: + case XML_SCHEMA_FACET_LENGTH: + case XML_SCHEMA_FACET_MAXLENGTH: + case XML_SCHEMA_FACET_MINLENGTH: + + if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) { + ret = xmlSchemaValidatePredefinedType( + xmlSchemaGetBuiltInType(XML_SCHEMAS_PINTEGER), + facet->value, &(facet->val)); + } else { + ret = xmlSchemaValidatePredefinedType( + xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER), + facet->value, &(facet->val)); + } + if (ret != 0) { + if (ret < 0) { + /* No error message for RelaxNG. */ + if (ctxtGiven) { + PERROR_INT("xmlSchemaCheckFacet", + "validating facet value"); + } + goto internal_error; + } + ret = XML_SCHEMAP_INVALID_FACET_VALUE; + /* No error message for RelaxNG. */ + if (ctxtGiven) { + /* error code */ + xmlSchemaCustomErr4(ACTXT_CAST pctxt, + ret, facet->node, WXS_BASIC_CAST typeDecl, + "The value '%s' of the facet '%s' is not a valid '%s'", + facet->value, + xmlSchemaFacetTypeToString(facet->type), + (facet->type != XML_SCHEMA_FACET_TOTALDIGITS) ? + BAD_CAST "nonNegativeInteger" : + BAD_CAST "positiveInteger", + NULL); + } + } + break; + + case XML_SCHEMA_FACET_WHITESPACE:{ + if (xmlStrEqual(facet->value, BAD_CAST "preserve")) { + facet->whitespace = XML_SCHEMAS_FACET_PRESERVE; + } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) { + facet->whitespace = XML_SCHEMAS_FACET_REPLACE; + } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) { + facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE; + } else { + ret = XML_SCHEMAP_INVALID_FACET_VALUE; + /* No error message for RelaxNG. */ + if (ctxtGiven) { + /* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */ + xmlSchemaCustomErr(ACTXT_CAST pctxt, + ret, facet->node, WXS_BASIC_CAST typeDecl, + "The value '%s' of the facet 'whitespace' is not " + "valid", facet->value, NULL); + } + } + } + default: + break; + } +exit: + if ((! ctxtGiven) && (pctxt != NULL)) + xmlSchemaFreeParserCtxt(pctxt); + return (ret); +internal_error: + if ((! ctxtGiven) && (pctxt != NULL)) + xmlSchemaFreeParserCtxt(pctxt); + return (-1); +} + +/** + * xmlSchemaCheckFacetValues: + * @typeDecl: the schema type definition + * @ctxt: the schema parser context + * + * Checks the default values types, especially for facets + */ +static int +xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl, + xmlSchemaParserCtxtPtr pctxt) +{ + int res, olderrs = pctxt->nberrors; + const xmlChar *name = typeDecl->name; + /* + * NOTE: It is intended to use the facets list, instead + * of facetSet. + */ + if (typeDecl->facets != NULL) { + xmlSchemaFacetPtr facet = typeDecl->facets; + + /* + * Temporarily assign the "schema" to the validation context + * of the parser context. This is needed for NOTATION validation. + */ + if (pctxt->vctxt == NULL) { + if (xmlSchemaCreateVCtxtOnPCtxt(pctxt) == -1) + return(-1); + } + pctxt->vctxt->schema = pctxt->schema; + while (facet != NULL) { + res = xmlSchemaCheckFacet(facet, typeDecl, pctxt, name); + HFAILURE + facet = facet->next; + } + pctxt->vctxt->schema = NULL; + } + if (olderrs != pctxt->nberrors) + return(pctxt->err); + return(0); +exit_failure: + return(-1); +} + +/** + * xmlSchemaGetCircModelGrDefRef: + * @ctxtMGroup: the searched model group + * @selfMGroup: the second searched model group + * @particle: the first particle + * + * This one is intended to be used by + * xmlSchemaCheckGroupDefCircular only. + * + * Returns the particle with the circular model group definition reference, + * otherwise NULL. + */ +static xmlSchemaTreeItemPtr +xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef, + xmlSchemaTreeItemPtr particle) +{ + xmlSchemaTreeItemPtr circ = NULL; + xmlSchemaTreeItemPtr term; + xmlSchemaModelGroupDefPtr gdef; + + for (; particle != NULL; particle = particle->next) { + term = particle->children; + if (term == NULL) + continue; + switch (term->type) { + case XML_SCHEMA_TYPE_GROUP: + gdef = (xmlSchemaModelGroupDefPtr) term; + if (gdef == groupDef) + return (particle); + /* + * Mark this model group definition to avoid infinite + * recursion on circular references not yet examined. + */ + if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED) + continue; + if (gdef->children != NULL) { + gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED; + circ = xmlSchemaGetCircModelGrDefRef(groupDef, + gdef->children->children); + gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED; + if (circ != NULL) + return (circ); + } + break; + case XML_SCHEMA_TYPE_SEQUENCE: + case XML_SCHEMA_TYPE_CHOICE: + case XML_SCHEMA_TYPE_ALL: + circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children); + if (circ != NULL) + return (circ); + break; + default: + break; + } + } + return (NULL); +} + +/** + * xmlSchemaCheckGroupDefCircular: + * @item: the model group definition + * @ctxt: the parser context + * @name: the name + * + * Checks for circular references to model group definitions. + */ +static void +xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item, + xmlSchemaParserCtxtPtr ctxt) +{ + /* + * Schema Component Constraint: Model Group Correct + * 2 Circular groups are disallowed. That is, within the {particles} + * of a group there must not be at any depth a particle whose {term} + * is the group itself. + */ + if ((item == NULL) || + (item->type != XML_SCHEMA_TYPE_GROUP) || + (item->children == NULL)) + return; + { + xmlSchemaTreeItemPtr circ; + + circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children); + if (circ != NULL) { + xmlChar *str = NULL; + /* + * TODO: The error report is not adequate: this constraint + * is defined for model groups but not definitions, but since + * there cannot be any circular model groups without a model group + * definition (if not using a construction API), we check those + * defintions only. + */ + xmlSchemaPCustomErr(ctxt, + XML_SCHEMAP_MG_PROPS_CORRECT_2, + NULL, WXS_ITEM_NODE(circ), + "Circular reference to the model group definition '%s' " + "defined", xmlSchemaFormatQName(&str, + item->targetNamespace, item->name)); + FREE_AND_NULL(str) + /* + * NOTE: We will cut the reference to avoid further + * confusion of the processor. This is a fatal error. + */ + circ->children = NULL; + } + } +} + +/** + * xmlSchemaModelGroupToModelGroupDefFixup: + * @ctxt: the parser context + * @mg: the model group + * + * Assigns the model group of model group definitions to the "term" + * of the referencing particle. + * In xmlSchemaResolveModelGroupParticleReferences the model group + * definitions were assigned to the "term", since needed for the + * circularity check. + * + * Schema Component Constraint: + * All Group Limited (cos-all-limited) (1.2) + */ +static void +xmlSchemaModelGroupToModelGroupDefFixup( + xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED, + xmlSchemaModelGroupPtr mg) +{ + xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg); + + while (particle != NULL) { + if ((WXS_PARTICLE_TERM(particle) == NULL) || + ((WXS_PARTICLE_TERM(particle))->type != + XML_SCHEMA_TYPE_GROUP)) + { + particle = WXS_PTC_CAST particle->next; + continue; + } + if (WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle)) == NULL) { + /* + * TODO: Remove the particle. + */ + WXS_PARTICLE_TERM(particle) = NULL; + particle = WXS_PTC_CAST particle->next; + continue; + } + /* + * Assign the model group to the {term} of the particle. + */ + WXS_PARTICLE_TERM(particle) = + WXS_TREE_CAST WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle)); + + particle = WXS_PTC_CAST particle->next; + } +} + +/** + * xmlSchemaCheckAttrGroupCircularRecur: + * @ctxtGr: the searched attribute group + * @attr: the current attribute list to be processed + * + * This one is intended to be used by + * xmlSchemaCheckAttrGroupCircular only. + * + * Returns the circular attribute grou reference, otherwise NULL. + */ +static xmlSchemaQNameRefPtr +xmlSchemaCheckAttrGroupCircularRecur(xmlSchemaAttributeGroupPtr ctxtGr, + xmlSchemaItemListPtr list) +{ + xmlSchemaAttributeGroupPtr gr; + xmlSchemaQNameRefPtr ref, circ; + int i; + /* + * We will search for an attribute group reference which + * references the context attribute group. + */ + for (i = 0; i < list->nbItems; i++) { + ref = list->items[i]; + if ((ref->type == XML_SCHEMA_EXTRA_QNAMEREF) && + (ref->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) && + (ref->item != NULL)) + { + gr = WXS_ATTR_GROUP_CAST ref->item; + if (gr == ctxtGr) + return(ref); + if (gr->flags & XML_SCHEMAS_ATTRGROUP_MARKED) + continue; + /* + * Mark as visited to avoid infinite recursion on + * circular references not yet examined. + */ + if ((gr->attrUses) && + (gr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS)) + { + gr->flags |= XML_SCHEMAS_ATTRGROUP_MARKED; + circ = xmlSchemaCheckAttrGroupCircularRecur(ctxtGr, + (xmlSchemaItemListPtr) gr->attrUses); + gr->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED; + if (circ != NULL) + return (circ); + } + + } + } + return (NULL); +} + +/** + * xmlSchemaCheckAttrGroupCircular: + * attrGr: the attribute group definition + * @ctxt: the parser context + * @name: the name + * + * Checks for circular references of attribute groups. + */ +static int +xmlSchemaCheckAttrGroupCircular(xmlSchemaAttributeGroupPtr attrGr, + xmlSchemaParserCtxtPtr ctxt) +{ + /* + * Schema Representation Constraint: + * Attribute Group Definition Representation OK + * 3 Circular group reference is disallowed outside . + * That is, unless this element information item's parent is + * , then among the [children], if any, there must + * not be an with ref [attribute] which resolves + * to the component corresponding to this . Indirect + * circularity is also ruled out. That is, when QName resolution + * (Schema Document) (§3.15.3) is applied to a ·QName· arising from + * any s with a ref [attribute] among the [children], + * it must not be the case that a ·QName· is encountered at any depth + * which resolves to the component corresponding to this . + */ + if (attrGr->attrUses == NULL) + return(0); + else if ((attrGr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS) == 0) + return(0); + else { + xmlSchemaQNameRefPtr circ; + + circ = xmlSchemaCheckAttrGroupCircularRecur(attrGr, + (xmlSchemaItemListPtr) attrGr->attrUses); + if (circ != NULL) { + xmlChar *str = NULL; + /* + * TODO: Report the referenced attr group as QName. + */ + xmlSchemaPCustomErr(ctxt, + XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3, + NULL, WXS_ITEM_NODE(WXS_BASIC_CAST circ), + "Circular reference to the attribute group '%s' " + "defined", xmlSchemaGetComponentQName(&str, attrGr)); + FREE_AND_NULL(str); + /* + * NOTE: We will cut the reference to avoid further + * confusion of the processor. + * BADSPEC TODO: The spec should define how to process in this case. + */ + circ->item = NULL; + return(ctxt->err); + } + } + return(0); +} + +static int +xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt, + xmlSchemaAttributeGroupPtr attrGr); + +/** + * xmlSchemaExpandAttributeGroupRefs: + * @pctxt: the parser context + * @node: the node of the component holding the attribute uses + * @completeWild: the intersected wildcard to be returned + * @list: the attribute uses + * + * Substitutes contained attribute group references + * for their attribute uses. Wilcards are intersected. + * Attribute use prohibitions are removed from the list + * and returned via the @prohibs list. + * Pointlessness of attr. prohibs, if a matching attr. decl + * is existent a well, are checked. + */ +static int +xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt, + xmlSchemaBasicItemPtr item, + xmlSchemaWildcardPtr *completeWild, + xmlSchemaItemListPtr list, + xmlSchemaItemListPtr prohibs) +{ + xmlSchemaAttributeGroupPtr gr; + xmlSchemaAttributeUsePtr use; + xmlSchemaItemListPtr sublist; + int i, j; + int created = (*completeWild == NULL) ? 0 : 1; + + if (prohibs) + prohibs->nbItems = 0; + + for (i = 0; i < list->nbItems; i++) { + use = list->items[i]; + + if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) { + if (prohibs == NULL) { + PERROR_INT("xmlSchemaExpandAttributeGroupRefs", + "unexpected attr prohibition found"); + return(-1); + } + /* + * Remove from attribute uses. + */ + if (xmlSchemaItemListRemove(list, i) == -1) + return(-1); + i--; + /* + * Note that duplicate prohibitions were already + * handled at parsing time. + */ + /* + * Add to list of prohibitions. + */ + xmlSchemaItemListAddSize(prohibs, 2, use); + continue; + } + if ((use->type == XML_SCHEMA_EXTRA_QNAMEREF) && + ((WXS_QNAME_CAST use)->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)) + { + if ((WXS_QNAME_CAST use)->item == NULL) + return(-1); + gr = WXS_ATTR_GROUP_CAST (WXS_QNAME_CAST use)->item; + /* + * Expand the referenced attr. group. + * TODO: remove this, this is done in a previous step, so + * already done here. + */ + if ((gr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) { + if (xmlSchemaAttributeGroupExpandRefs(pctxt, gr) == -1) + return(-1); + } + /* + * Build the 'complete' wildcard; i.e. intersect multiple + * wildcards. + */ + if (gr->attributeWildcard != NULL) { + if (*completeWild == NULL) { + *completeWild = gr->attributeWildcard; + } else { + if (! created) { + xmlSchemaWildcardPtr tmpWild; + + /* + * Copy the first encountered wildcard as context, + * except for the annotation. + * + * Although the complete wildcard might not correspond + * to any node in the schema, we will anchor it on + * the node of the owner component. + */ + tmpWild = xmlSchemaAddWildcard(pctxt, pctxt->schema, + XML_SCHEMA_TYPE_ANY_ATTRIBUTE, + WXS_ITEM_NODE(item)); + if (tmpWild == NULL) + return(-1); + if (xmlSchemaCloneWildcardNsConstraints(pctxt, + tmpWild, *completeWild) == -1) + return (-1); + tmpWild->processContents = (*completeWild)->processContents; + *completeWild = tmpWild; + created = 1; + } + + if (xmlSchemaIntersectWildcards(pctxt, *completeWild, + gr->attributeWildcard) == -1) + return(-1); + } + } + /* + * Just remove the reference if the referenced group does not + * contain any attribute uses. + */ + if (gr->attrUses == NULL) { + if (xmlSchemaItemListRemove(list, i) == -1) + return(-1); + i--; + continue; + } + /* + * Add the attribute uses. + */ + sublist = ((xmlSchemaItemListPtr) gr->attrUses); + if (sublist->nbItems != 0) { + list->items[i] = sublist->items[0]; + if (sublist->nbItems != 1) { + for (j = 1; j < sublist->nbItems; j++) { + i++; + if (xmlSchemaItemListInsert(list, + sublist->items[j], i) == -1) + return(-1); + } + } + } + } + + } + /* + * Handle pointless prohibitions of declared attributes. + */ + if (prohibs && (prohibs->nbItems != 0) && (list->nbItems != 0)) { + xmlSchemaAttributeUseProhibPtr prohib; + + for (i = prohibs->nbItems -1; i >= 0; i--) { + prohib = prohibs->items[i]; + for (j = 0; j < list->nbItems; j++) { + use = list->items[j]; + + if ((prohib->name == WXS_ATTRUSE_DECL_NAME(use)) && + (prohib->targetNamespace == WXS_ATTRUSE_DECL_TNS(use))) + { + xmlChar *str = NULL; + + xmlSchemaCustomWarning(ACTXT_CAST pctxt, + XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH, + prohib->node, NULL, + "Skipping pointless attribute use prohibition " + "'%s', since a corresponding attribute use " + "exists already in the type definition", + xmlSchemaFormatQName(&str, + prohib->targetNamespace, prohib->name), + NULL, NULL); + FREE_AND_NULL(str); + /* + * Remove the prohibition. + */ + if (xmlSchemaItemListRemove(prohibs, i) == -1) + return(-1); + break; + } + } + } + } + return(0); +} + +/** + * xmlSchemaAttributeGroupExpandRefs: + * @pctxt: the parser context + * @attrGr: the attribute group definition + * + * Computation of: + * {attribute uses} property + * {attribute wildcard} property + * + * Substitutes contained attribute group references + * for their attribute uses. Wilcards are intersected. + */ +static int +xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt, + xmlSchemaAttributeGroupPtr attrGr) +{ + if ((attrGr->attrUses == NULL) || + (attrGr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED)) + return(0); + + attrGr->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED; + if (xmlSchemaExpandAttributeGroupRefs(pctxt, WXS_BASIC_CAST attrGr, + &(attrGr->attributeWildcard), attrGr->attrUses, NULL) == -1) + return(-1); + return(0); +} + +/** + * xmlSchemaAttributeGroupExpandRefs: + * @pctxt: the parser context + * @attrGr: the attribute group definition + * + * Substitutes contained attribute group references + * for their attribute uses. Wilcards are intersected. + * + * Schema Component Constraint: + * Attribute Group Definition Properties Correct (ag-props-correct) + */ +static int +xmlSchemaCheckAGPropsCorrect(xmlSchemaParserCtxtPtr pctxt, + xmlSchemaAttributeGroupPtr attrGr) +{ + /* + * SPEC ag-props-correct + * (1) "The values of the properties of an attribute group definition + * must be as described in the property tableau in The Attribute + * Group Definition Schema Component (§3.6.1), modulo the impact of + * Missing Sub-components (§5.3);" + */ + + if ((attrGr->attrUses != NULL) && + (WXS_LIST_CAST attrGr->attrUses)->nbItems > 1) + { + xmlSchemaItemListPtr uses = WXS_LIST_CAST attrGr->attrUses; + xmlSchemaAttributeUsePtr use, tmp; + int i, j, hasId = 0; + + for (i = uses->nbItems -1; i >= 0; i--) { + use = uses->items[i]; + /* + * SPEC ag-props-correct + * (2) "Two distinct members of the {attribute uses} must not have + * {attribute declaration}s both of whose {name}s match and whose + * {target namespace}s are identical." + */ + if (i > 0) { + for (j = i -1; j >= 0; j--) { + tmp = uses->items[j]; + if ((WXS_ATTRUSE_DECL_NAME(use) == + WXS_ATTRUSE_DECL_NAME(tmp)) && + (WXS_ATTRUSE_DECL_TNS(use) == + WXS_ATTRUSE_DECL_TNS(tmp))) + { + xmlChar *str = NULL; + + xmlSchemaCustomErr(ACTXT_CAST pctxt, + XML_SCHEMAP_AG_PROPS_CORRECT, + attrGr->node, WXS_BASIC_CAST attrGr, + "Duplicate %s", + xmlSchemaGetComponentDesignation(&str, use), + NULL); + FREE_AND_NULL(str); + /* + * Remove the duplicate. + */ + if (xmlSchemaItemListRemove(uses, i) == -1) + return(-1); + goto next_use; + } + } + } + /* + * SPEC ag-props-correct + * (3) "Two distinct members of the {attribute uses} must not have + * {attribute declaration}s both of whose {type definition}s are or + * are derived from ID." + * TODO: Does 'derived' include member-types of unions? + */ + if (WXS_ATTRUSE_TYPEDEF(use) != NULL) { + if (xmlSchemaIsDerivedFromBuiltInType( + WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID)) + { + if (hasId) { + xmlChar *str = NULL; + + xmlSchemaCustomErr(ACTXT_CAST pctxt, + XML_SCHEMAP_AG_PROPS_CORRECT, + attrGr->node, WXS_BASIC_CAST attrGr, + "There must not exist more than one attribute " + "declaration of type 'xs:ID' " + "(or derived from 'xs:ID'). The %s violates this " + "constraint", + xmlSchemaGetComponentDesignation(&str, use), + NULL); + FREE_AND_NULL(str); + if (xmlSchemaItemListRemove(uses, i) == -1) + return(-1); + } + hasId = 1; + } + } +next_use: {} + } + } + return(0); +} + +/** + * xmlSchemaResolveAttrGroupReferences: + * @attrgrpDecl: the schema attribute definition + * @ctxt: the schema parser context + * @name: the attribute name + * + * Resolves references to attribute group definitions. + */ +static int +xmlSchemaResolveAttrGroupReferences(xmlSchemaQNameRefPtr ref, + xmlSchemaParserCtxtPtr ctxt) +{ + xmlSchemaAttributeGroupPtr group; + + if (ref->item != NULL) + return(0); + group = xmlSchemaGetAttributeGroup(ctxt->schema, + ref->name, + ref->targetNamespace); + if (group == NULL) { + xmlSchemaPResCompAttrErr(ctxt, + XML_SCHEMAP_SRC_RESOLVE, + NULL, ref->node, + "ref", ref->name, ref->targetNamespace, + ref->itemType, NULL); + return(ctxt->err); + } + ref->item = WXS_BASIC_CAST group; + return(0); +} + +/** + * xmlSchemaCheckAttrPropsCorrect: + * @item: an schema attribute declaration/use + * @ctxt: a schema parser context + * @name: the name of the attribute + * + * + * Schema Component Constraint: + * Attribute Declaration Properties Correct (a-props-correct) + * + * Validates the value constraints of an attribute declaration/use. + * NOTE that this needs the simle type definitions to be already + * builded and checked. + */ +static int +xmlSchemaCheckAttrPropsCorrect(xmlSchemaParserCtxtPtr pctxt, + xmlSchemaAttributePtr attr) +{ + + /* + * SPEC a-props-correct (1) + * "The values of the properties of an attribute declaration must + * be as described in the property tableau in The Attribute + * Declaration Schema Component (§3.2.1), modulo the impact of + * Missing Sub-components (§5.3)." + */ + + if (WXS_ATTR_TYPEDEF(attr) == NULL) + return(0); + + if (attr->defValue != NULL) { + int ret; + + /* + * SPEC a-props-correct (3) + * "If the {type definition} is or is derived from ID then there + * must not be a {value constraint}." + */ + if (xmlSchemaIsDerivedFromBuiltInType( + WXS_ATTR_TYPEDEF(attr), XML_SCHEMAS_ID)) + { + xmlSchemaCustomErr(ACTXT_CAST pctxt, + XML_SCHEMAP_A_PROPS_CORRECT_3, + NULL, WXS_BASIC_CAST attr, + "Value constraints are not allowed if the type definition " + "is or is derived from xs:ID", + NULL, NULL); + return(pctxt->err); + } + /* + * SPEC a-props-correct (2) + * "if there is a {value constraint}, the canonical lexical + * representation of its value must be ·valid· with respect + * to the {type definition} as defined in String Valid (§3.14.4)." + * TODO: Don't care about the *cononical* stuff here, this requirement + * will be removed in WXS 1.1 anyway. + */ + ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, + attr->node, WXS_ATTR_TYPEDEF(attr), + attr->defValue, &(attr->defVal), + 1, 1, 0); + if (ret != 0) { + if (ret < 0) { + PERROR_INT("xmlSchemaCheckAttrPropsCorrect", + "calling xmlSchemaVCheckCVCSimpleType()"); + return(-1); + } + xmlSchemaCustomErr(ACTXT_CAST pctxt, + XML_SCHEMAP_A_PROPS_CORRECT_2, + NULL, WXS_BASIC_CAST attr, + "The value of the value constraint is not valid", + NULL, NULL); + return(pctxt->err); + } + } + + return(0); +} + +static xmlSchemaElementPtr +xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl, + xmlSchemaElementPtr ancestor) +{ + xmlSchemaElementPtr ret; + + if (WXS_SUBST_HEAD(ancestor) == NULL) + return (NULL); + if (WXS_SUBST_HEAD(ancestor) == elemDecl) + return (ancestor); + + if (WXS_SUBST_HEAD(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR) + return (NULL); + WXS_SUBST_HEAD(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR; + ret = xmlSchemaCheckSubstGroupCircular(elemDecl, + WXS_SUBST_HEAD(ancestor)); + WXS_SUBST_HEAD(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR; + + return (ret); +} + +/** + * xmlSchemaCheckElemPropsCorrect: + * @ctxt: a schema parser context + * @decl: the element declaration + * @name: the name of the attribute + * + * Schema Component Constraint: + * Element Declaration Properties Correct (e-props-correct) + * + * STATUS: + * missing: (6) + */ +static int +xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt, + xmlSchemaElementPtr elemDecl) +{ + int ret = 0; + xmlSchemaTypePtr typeDef = WXS_ELEM_TYPEDEF(elemDecl); + /* + * SPEC (1) "The values of the properties of an element declaration + * must be as described in the property tableau in The Element + * Declaration Schema Component (§3.3.1), modulo the impact of Missing + * Sub-components (§5.3)." + */ + if (WXS_SUBST_HEAD(elemDecl) != NULL) { + xmlSchemaElementPtr head = WXS_SUBST_HEAD(elemDecl), circ; + + xmlSchemaCheckElementDeclComponent(head, pctxt); + /* + * SPEC (3) "If there is a non-·absent· {substitution group + * affiliation}, then {scope} must be global." + */ + if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) { + xmlSchemaPCustomErr(pctxt, + XML_SCHEMAP_E_PROPS_CORRECT_3, + WXS_BASIC_CAST elemDecl, NULL, + "Only global element declarations can have a " + "substitution group affiliation", NULL); + ret = XML_SCHEMAP_E_PROPS_CORRECT_3; + } + /* + * TODO: SPEC (6) "Circular substitution groups are disallowed. + * That is, it must not be possible to return to an element declaration + * by repeatedly following the {substitution group affiliation} + * property." + */ + if (head == elemDecl) + circ = head; + else if (WXS_SUBST_HEAD(head) != NULL) + circ = xmlSchemaCheckSubstGroupCircular(head, head); + else + circ = NULL; + if (circ != NULL) { + xmlChar *strA = NULL, *strB = NULL; + + xmlSchemaPCustomErrExt(pctxt, + XML_SCHEMAP_E_PROPS_CORRECT_6, + WXS_BASIC_CAST circ, NULL, + "The element declaration '%s' defines a circular " + "substitution group to element declaration '%s'", + xmlSchemaGetComponentQName(&strA, circ), + xmlSchemaGetComponentQName(&strB, head), + NULL); + FREE_AND_NULL(strA) + FREE_AND_NULL(strB) + ret = XML_SCHEMAP_E_PROPS_CORRECT_6; + } + /* + * SPEC (4) "If there is a {substitution group affiliation}, + * the {type definition} + * of the element declaration must be validly derived from the {type + * definition} of the {substitution group affiliation}, given the value + * of the {substitution group exclusions} of the {substitution group + * affiliation}, as defined in Type Derivation OK (Complex) (§3.4.6) + * (if the {type definition} is complex) or as defined in + * Type Derivation OK (Simple) (§3.14.6) (if the {type definition} is + * simple)." + * + * NOTE: {substitution group exclusions} means the values of the + * attribute "final". + */ + + if (typeDef != WXS_ELEM_TYPEDEF(WXS_SUBST_HEAD(elemDecl))) { + int set = 0; + + if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION) + set |= SUBSET_EXTENSION; + if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION) + set |= SUBSET_RESTRICTION; + + if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST pctxt, typeDef, + WXS_ELEM_TYPEDEF(head), set) != 0) { + xmlChar *strA = NULL, *strB = NULL, *strC = NULL; + + ret = XML_SCHEMAP_E_PROPS_CORRECT_4; + xmlSchemaPCustomErrExt(pctxt, + XML_SCHEMAP_E_PROPS_CORRECT_4, + WXS_BASIC_CAST elemDecl, NULL, + "The type definition '%s' was " + "either rejected by the substitution group " + "affiliation '%s', or not validly derived from its type " + "definition '%s'", + xmlSchemaGetComponentQName(&strA, typeDef), + xmlSchemaGetComponentQName(&strB, head), + xmlSchemaGetComponentQName(&strC, WXS_ELEM_TYPEDEF(head))); + FREE_AND_NULL(strA) + FREE_AND_NULL(strB) + FREE_AND_NULL(strC) + } + } + } + /* + * SPEC (5) "If the {type definition} or {type definition}'s + * {content type} + * is or is derived from ID then there must not be a {value constraint}. + * Note: The use of ID as a type definition for elements goes beyond + * XML 1.0, and should be avoided if backwards compatibility is desired" + */ + if ((elemDecl->value != NULL) && + ((WXS_IS_SIMPLE(typeDef) && + xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) || + (WXS_IS_COMPLEX(typeDef) && + WXS_HAS_SIMPLE_CONTENT(typeDef) && + xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef, + XML_SCHEMAS_ID)))) { + + ret = XML_SCHEMAP_E_PROPS_CORRECT_5; + xmlSchemaPCustomErr(pctxt, + XML_SCHEMAP_E_PROPS_CORRECT_5, + WXS_BASIC_CAST elemDecl, NULL, + "The type definition (or type definition's content type) is or " + "is derived from ID; value constraints are not allowed in " + "conjunction with such a type definition", NULL); + } else if (elemDecl->value != NULL) { + int vcret; + xmlNodePtr node = NULL; + + /* + * SPEC (2) "If there is a {value constraint}, the canonical lexical + * representation of its value must be ·valid· with respect to the + * {type definition} as defined in Element Default Valid (Immediate) + * (§3.3.6)." + */ + if (typeDef == NULL) { + xmlSchemaPErr(pctxt, elemDecl->node, + XML_SCHEMAP_INTERNAL, + "Internal error: xmlSchemaCheckElemPropsCorrect, " + "type is missing... skipping validation of " + "the value constraint", NULL, NULL); + return (-1); + } + if (elemDecl->node != NULL) { + if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) + node = (xmlNodePtr) xmlHasProp(elemDecl->node, + BAD_CAST "fixed"); + else + node = (xmlNodePtr) xmlHasProp(elemDecl->node, + BAD_CAST "default"); + } + vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node, + typeDef, elemDecl->value, &(elemDecl->defVal)); + if (vcret != 0) { + if (vcret < 0) { + PERROR_INT("xmlSchemaElemCheckValConstr", + "failed to validate the value constraint of an " + "element declaration"); + return (-1); + } + return (vcret); + } + } + + return (ret); +} + +/** + * xmlSchemaCheckElemSubstGroup: + * @ctxt: a schema parser context + * @decl: the element declaration + * @name: the name of the attribute + * + * Schema Component Constraint: + * Substitution Group (cos-equiv-class) + * + * In Libxml2 the subst. groups will be precomputed, in terms of that + * a list will be built for each subst. group head, holding all direct + * referents to this head. + * NOTE that this function needs: + * 1. circular subst. groups to be checked beforehand + * 2. the declaration's type to be derived from the head's type + * + * STATUS: + * + */ +static void +xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt, + xmlSchemaElementPtr elemDecl) +{ + if ((WXS_SUBST_HEAD(elemDecl) == NULL) || + /* SPEC (1) "Its {abstract} is false." */ + (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)) + return; + { + xmlSchemaElementPtr head; + xmlSchemaTypePtr headType, type; + int set, methSet; + /* + * SPEC (2) "It is validly substitutable for HEAD subject to HEAD's + * {disallowed substitutions} as the blocking constraint, as defined in + * Substitution Group OK (Transitive) (§3.3.6)." + */ + for (head = WXS_SUBST_HEAD(elemDecl); head != NULL; + head = WXS_SUBST_HEAD(head)) { + set = 0; + methSet = 0; + /* + * The blocking constraints. + */ + if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) + continue; + headType = head->subtypes; + type = elemDecl->subtypes; + if (headType == type) + goto add_member; + if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) + set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION; + if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) + set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION; + /* + * SPEC: Substitution Group OK (Transitive) (2.3) + * "The set of all {derivation method}s involved in the + * derivation of D's {type definition} from C's {type definition} + * does not intersect with the union of the blocking constraint, + * C's {prohibited substitutions} (if C is complex, otherwise the + * empty set) and the {prohibited substitutions} (respectively the + * empty set) of any intermediate {type definition}s in the + * derivation of D's {type definition} from C's {type definition}." + */ + /* + * OPTIMIZE TODO: Optimize this a bit, since, if traversing the + * subst.head axis, the methSet does not need to be computed for + * the full depth over and over. + */ + /* + * The set of all {derivation method}s involved in the derivation + */ + while ((type != NULL) && (type != headType)) { + if ((WXS_IS_EXTENSION(type)) && + ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0)) + methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION; + + if (WXS_IS_RESTRICTION(type) && + ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0)) + methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION; + + type = type->baseType; + } + /* + * The {prohibited substitutions} of all intermediate types + + * the head's type. + */ + type = elemDecl->subtypes->baseType; + while (type != NULL) { + if (WXS_IS_COMPLEX(type)) { + if ((type->flags & + XML_SCHEMAS_TYPE_BLOCK_EXTENSION) && + ((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0)) + set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION; + if ((type->flags & + XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) && + ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0)) + set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION; + } else + break; + if (type == headType) + break; + type = type->baseType; + } + if ((set != 0) && + (((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) && + (methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) || + ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) && + (methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) { + continue; + } +add_member: + xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl); + if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0) + head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD; + } + } +} + +#ifdef WXS_ELEM_DECL_CONS_ENABLED /* enable when finished */ +/** + * xmlSchemaCheckElementDeclComponent + * @pctxt: the schema parser context + * @ctxtComponent: the context component (an element declaration) + * @ctxtParticle: the first particle of the context component + * @searchParticle: the element declaration particle to be analysed + * + * Schema Component Constraint: Element Declarations Consistent + */ +static int +xmlSchemaCheckElementDeclConsistent(xmlSchemaParserCtxtPtr pctxt, + xmlSchemaBasicItemPtr ctxtComponent, + xmlSchemaParticlePtr ctxtParticle, + xmlSchemaParticlePtr searchParticle, + xmlSchemaParticlePtr curParticle, + int search) +{ + return(0); + + int ret = 0; + xmlSchemaParticlePtr cur = curParticle; + if (curParticle == NULL) { + return(0); + } + if (WXS_PARTICLE_TERM(curParticle) == NULL) { + /* + * Just return in this case. A missing "term" of the particle + * might arise due to an invalid "term" component. + */ + return(0); + } + while (cur != NULL) { + switch (WXS_PARTICLE_TERM(cur)->type) { + case XML_SCHEMA_TYPE_ANY: + break; + case XML_SCHEMA_TYPE_ELEMENT: + if (search == 0) { + ret = xmlSchemaCheckElementDeclConsistent(pctxt, + ctxtComponent, ctxtParticle, cur, ctxtParticle, 1); + if (ret != 0) + return(ret); + } else { + xmlSchemaElementPtr elem = + WXS_ELEM_CAST(WXS_PARTICLE_TERM(cur)); + /* + * SPEC Element Declarations Consistent: + * "If the {particles} contains, either directly, + * indirectly (that is, within the {particles} of a + * contained model group, recursively) or ·implicitly· + * two or more element declaration particles with + * the same {name} and {target namespace}, then + * all their type definitions must be the same + * top-level definition [...]" + */ + if (xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->name, + WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->name) && + xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace, + WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->targetNamespace)) + { + xmlChar *strA = NULL, *strB = NULL; + + xmlSchemaCustomErr(ACTXT_CAST pctxt, + /* TODO: error code */ + XML_SCHEMAP_COS_NONAMBIG, + WXS_ITEM_NODE(cur), NULL, + "In the content model of %s, there are multiple " + "element declarations for '%s' with different " + "type definitions", + xmlSchemaGetComponentDesignation(&strA, + ctxtComponent), + xmlSchemaFormatQName(&strB, + WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace, + WXS_PARTICLE_TERM_AS_ELEM(cur)->name)); + FREE_AND_NULL(strA); + FREE_AND_NULL(strB); + return(XML_SCHEMAP_COS_NONAMBIG); + } + } + break; + case XML_SCHEMA_TYPE_SEQUENCE: { + break; + } + case XML_SCHEMA_TYPE_CHOICE:{ + /* + xmlSchemaTreeItemPtr sub; + + sub = WXS_PARTICLE_TERM(particle)->children; (xmlSchemaParticlePtr) + while (sub != NULL) { + ret = xmlSchemaCheckElementDeclConsistent(pctxt, ctxtComponent, + ctxtParticle, ctxtElem); + if (ret != 0) + return(ret); + sub = sub->next; + } + */ + break; + } + case XML_SCHEMA_TYPE_ALL: + break; + case XML_SCHEMA_TYPE_GROUP: + break; + default: + xmlSchemaInternalErr2(ACTXT_CAST pctxt, + "xmlSchemaCheckElementDeclConsistent", + "found unexpected term of type '%s' in content model", + WXS_ITEM_TYPE_NAME(WXS_PARTICLE_TERM(cur)), NULL); + return(-1); + } + cur = (xmlSchemaParticlePtr) cur->next; + } + +exit: + return(ret); +} +#endif + +/** + * xmlSchemaCheckElementDeclComponent + * @item: an schema element declaration/particle + * @ctxt: a schema parser context + * @name: the name of the attribute + * + * Validates the value constraints of an element declaration. + * Adds substitution group members. + */ +static void +xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl, + xmlSchemaParserCtxtPtr ctxt) +{ + if (elemDecl == NULL) + return; + if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED) + return; + elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED; + if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0) { + /* + * Adds substitution group members. + */ + xmlSchemaCheckElemSubstGroup(ctxt, elemDecl); + } +} + +/** + * xmlSchemaResolveModelGroupParticleReferences: + * @particle: a particle component + * @ctxt: a parser context + * + * Resolves references of a model group's {particles} to + * model group definitions and to element declarations. + */ +static void +xmlSchemaResolveModelGroupParticleReferences( + xmlSchemaParserCtxtPtr ctxt, + xmlSchemaModelGroupPtr mg) +{ + xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg); + xmlSchemaQNameRefPtr ref; + xmlSchemaBasicItemPtr refItem; + + /* + * URGENT TODO: Test this. + */ + while (particle != NULL) { + if ((WXS_PARTICLE_TERM(particle) == NULL) || + ((WXS_PARTICLE_TERM(particle))->type != + XML_SCHEMA_EXTRA_QNAMEREF)) + { + goto next_particle; + } + ref = WXS_QNAME_CAST WXS_PARTICLE_TERM(particle); + /* + * Resolve the reference. + * NULL the {term} by default. + */ + particle->children = NULL; + + refItem = xmlSchemaGetNamedComponent(ctxt->schema, + ref->itemType, ref->name, ref->targetNamespace); + if (refItem == NULL) { + xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE, + NULL, WXS_ITEM_NODE(particle), "ref", ref->name, + ref->targetNamespace, ref->itemType, NULL); + /* TODO: remove the particle. */ + goto next_particle; + } + if (refItem->type == XML_SCHEMA_TYPE_GROUP) { + if (WXS_MODELGROUPDEF_MODEL(refItem) == NULL) + /* TODO: remove the particle. */ + goto next_particle; + /* + * NOTE that we will assign the model group definition + * itself to the "term" of the particle. This will ease + * the check for circular model group definitions. After + * that the "term" will be assigned the model group of the + * model group definition. + */ + if ((WXS_MODELGROUPDEF_MODEL(refItem))->type == + XML_SCHEMA_TYPE_ALL) { + /* + * SPEC cos-all-limited (1) + * SPEC cos-all-limited (1.2) + * "It appears only as the value of one or both of the + * following properties:" + * (1.1) "the {model group} property of a model group + * definition." + * (1.2) "the {term} property of a particle [... of] the " + * {content type} of a complex type definition." + */ + xmlSchemaCustomErr(ACTXT_CAST ctxt, + /* TODO: error code */ + XML_SCHEMAP_COS_ALL_LIMITED, + WXS_ITEM_NODE(particle), NULL, + "A model group definition is referenced, but " + "it contains an 'all' model group, which " + "cannot be contained by model groups", + NULL, NULL); + /* TODO: remove the particle. */ + goto next_particle; + } + particle->children = (xmlSchemaTreeItemPtr) refItem; + } else { + /* + * TODO: Are referenced element declarations the only + * other components we expect here? + */ + particle->children = (xmlSchemaTreeItemPtr) refItem; + } +next_particle: + particle = WXS_PTC_CAST particle->next; + } +} + +static int +xmlSchemaAreValuesEqual(xmlSchemaValPtr x, + xmlSchemaValPtr y) +{ + xmlSchemaTypePtr tx, ty, ptx, pty; + int ret; + + while (x != NULL) { + /* Same types. */ + tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x)); + ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y)); + ptx = xmlSchemaGetPrimitiveType(tx); + pty = xmlSchemaGetPrimitiveType(ty); + /* + * (1) if a datatype T' is ·derived· by ·restriction· from an + * atomic datatype T then the ·value space· of T' is a subset of + * the ·value space· of T. */ + /* + * (2) if datatypes T' and T'' are ·derived· by ·restriction· + * from a common atomic ancestor T then the ·value space·s of T' + * and T'' may overlap. + */ + if (ptx != pty) + return(0); + /* + * We assume computed values to be normalized, so do a fast + * string comparison for string based types. + */ + if ((ptx->builtInType == XML_SCHEMAS_STRING) || + WXS_IS_ANY_SIMPLE_TYPE(ptx)) { + if (! xmlStrEqual( + xmlSchemaValueGetAsString(x), + xmlSchemaValueGetAsString(y))) + return (0); + } else { + ret = xmlSchemaCompareValuesWhtsp( + x, XML_SCHEMA_WHITESPACE_PRESERVE, + y, XML_SCHEMA_WHITESPACE_PRESERVE); + if (ret == -2) + return(-1); + if (ret != 0) + return(0); + } + /* + * Lists. + */ + x = xmlSchemaValueGetNext(x); + if (x != NULL) { + y = xmlSchemaValueGetNext(y); + if (y == NULL) + return (0); + } else if (xmlSchemaValueGetNext(y) != NULL) + return (0); + else + return (1); + } + return (0); +} + +/** + * xmlSchemaResolveAttrUseReferences: + * @item: an attribute use + * @ctxt: a parser context + * + * Resolves the referenced attribute declaration. + */ +static int +xmlSchemaResolveAttrUseReferences(xmlSchemaAttributeUsePtr ause, + xmlSchemaParserCtxtPtr ctxt) +{ + if ((ctxt == NULL) || (ause == NULL)) + return(-1); + if ((ause->attrDecl == NULL) || + (ause->attrDecl->type != XML_SCHEMA_EXTRA_QNAMEREF)) + return(0); + + { + xmlSchemaQNameRefPtr ref = WXS_QNAME_CAST ause->attrDecl; + + /* + * TODO: Evaluate, what errors could occur if the declaration is not + * found. + */ + ause->attrDecl = xmlSchemaGetAttributeDecl(ctxt->schema, + ref->name, ref->targetNamespace); + if (ause->attrDecl == NULL) { + xmlSchemaPResCompAttrErr(ctxt, + XML_SCHEMAP_SRC_RESOLVE, + WXS_BASIC_CAST ause, ause->node, + "ref", ref->name, ref->targetNamespace, + XML_SCHEMA_TYPE_ATTRIBUTE, NULL); + return(ctxt->err);; + } + } + return(0); +} + +/** + * xmlSchemaCheckAttrUsePropsCorrect: + * @ctxt: a parser context + * @use: an attribute use + * + * Schema Component Constraint: + * Attribute Use Correct (au-props-correct) + * + */ +static int +xmlSchemaCheckAttrUsePropsCorrect(xmlSchemaParserCtxtPtr ctxt, + xmlSchemaAttributeUsePtr use) +{ + if ((ctxt == NULL) || (use == NULL)) + return(-1); + if ((use->defValue == NULL) || (WXS_ATTRUSE_DECL(use) == NULL) || + ((WXS_ATTRUSE_DECL(use))->type != XML_SCHEMA_TYPE_ATTRIBUTE)) + return(0); + + /* + * SPEC au-props-correct (1) + * "The values of the properties of an attribute use must be as + * described in the property tableau in The Attribute Use Schema + * Component (§3.5.1), modulo the impact of Missing + * Sub-components (§5.3)." + */ + + if (((WXS_ATTRUSE_DECL(use))->defValue != NULL) && + ((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMAS_ATTR_FIXED) && + ((use->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0)) + { + xmlSchemaPCustomErr(ctxt, + XML_SCHEMAP_AU_PROPS_CORRECT_2, + WXS_BASIC_CAST use, NULL, + "The attribute declaration has a 'fixed' value constraint " + ", thus the attribute use must also have a 'fixed' value " + "constraint", + NULL); + return(ctxt->err); + } + /* + * Compute and check the value constraint's value. + */ + if ((use->defVal != NULL) && (WXS_ATTRUSE_TYPEDEF(use) != NULL)) { + int ret; + /* + * TODO: The spec seems to be missing a check of the + * value constraint of the attribute use. We will do it here. + */ + /* + * SPEC a-props-correct (3) + */ + if (xmlSchemaIsDerivedFromBuiltInType( + WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID)) + { + xmlSchemaCustomErr(ACTXT_CAST ctxt, + XML_SCHEMAP_AU_PROPS_CORRECT, + NULL, WXS_BASIC_CAST use, + "Value constraints are not allowed if the type definition " + "is or is derived from xs:ID", + NULL, NULL); + return(ctxt->err); + } + + ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST ctxt, + use->node, WXS_ATTRUSE_TYPEDEF(use), + use->defValue, &(use->defVal), + 1, 1, 0); + if (ret != 0) { + if (ret < 0) { + PERROR_INT2("xmlSchemaCheckAttrUsePropsCorrect", + "calling xmlSchemaVCheckCVCSimpleType()"); + return(-1); + } + xmlSchemaCustomErr(ACTXT_CAST ctxt, + XML_SCHEMAP_AU_PROPS_CORRECT, + NULL, WXS_BASIC_CAST use, + "The value of the value constraint is not valid", + NULL, NULL); + return(ctxt->err); + } + } + /* + * SPEC au-props-correct (2) + * "If the {attribute declaration} has a fixed + * {value constraint}, then if the attribute use itself has a + * {value constraint}, it must also be fixed and its value must match + * that of the {attribute declaration}'s {value constraint}." + */ + if (((WXS_ATTRUSE_DECL(use))->defVal != NULL) && + (((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0)) + { + if (! xmlSchemaAreValuesEqual(use->defVal, + (WXS_ATTRUSE_DECL(use))->defVal)) + { + xmlSchemaPCustomErr(ctxt, + XML_SCHEMAP_AU_PROPS_CORRECT_2, + WXS_BASIC_CAST use, NULL, + "The 'fixed' value constraint of the attribute use " + "must match the attribute declaration's value " + "constraint '%s'", + (WXS_ATTRUSE_DECL(use))->defValue); + } + return(ctxt->err); + } + return(0); +} + + + + +/** + * xmlSchemaResolveAttrTypeReferences: + * @item: an attribute declaration + * @ctxt: a parser context + * + * Resolves the referenced type definition component. + */ +static int +xmlSchemaResolveAttrTypeReferences(xmlSchemaAttributePtr item, + xmlSchemaParserCtxtPtr ctxt) +{ + /* + * The simple type definition corresponding to the element + * information item in the [children], if present, otherwise the simple + * type definition ·resolved· to by the ·actual value· of the type + * [attribute], if present, otherwise the ·simple ur-type definition·. + */ + if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED) + return(0); + item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED; + if (item->subtypes != NULL) + return(0); + if (item->typeName != NULL) { + xmlSchemaTypePtr type; + + type = xmlSchemaGetType(ctxt->schema, item->typeName, + item->typeNs); + if ((type == NULL) || (! WXS_IS_SIMPLE(type))) { + xmlSchemaPResCompAttrErr(ctxt, + XML_SCHEMAP_SRC_RESOLVE, + WXS_BASIC_CAST item, item->node, + "type", item->typeName, item->typeNs, + XML_SCHEMA_TYPE_SIMPLE, NULL); + return(ctxt->err); + } else + item->subtypes = type; + + } else { + /* + * The type defaults to the xs:anySimpleType. + */ + item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE); + } + return(0); +} + +/** + * xmlSchemaResolveIDCKeyReferences: + * @idc: the identity-constraint definition + * @ctxt: the schema parser context + * @name: the attribute name + * + * Resolve keyRef references to key/unique IDCs. + * Schema Component Constraint: + * Identity-constraint Definition Properties Correct (c-props-correct) + */ +static int +xmlSchemaResolveIDCKeyReferences(xmlSchemaIDCPtr idc, + xmlSchemaParserCtxtPtr pctxt) +{ + if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) + return(0); + if (idc->ref->name != NULL) { + idc->ref->item = (xmlSchemaBasicItemPtr) + xmlSchemaGetIDC(pctxt->schema, idc->ref->name, + idc->ref->targetNamespace); + if (idc->ref->item == NULL) { + /* + * TODO: It is actually not an error to fail to resolve + * at this stage. BUT we need to be that strict! + */ + xmlSchemaPResCompAttrErr(pctxt, + XML_SCHEMAP_SRC_RESOLVE, + WXS_BASIC_CAST idc, idc->node, + "refer", idc->ref->name, + idc->ref->targetNamespace, + XML_SCHEMA_TYPE_IDC_KEY, NULL); + return(pctxt->err); + } else if (idc->ref->item->type == XML_SCHEMA_TYPE_IDC_KEYREF) { + /* + * SPEC c-props-correct (1) + */ + xmlSchemaCustomErr(ACTXT_CAST pctxt, + XML_SCHEMAP_C_PROPS_CORRECT, + NULL, WXS_BASIC_CAST idc, + "The keyref references a keyref", + NULL, NULL); + idc->ref->item = NULL; + return(pctxt->err); + } else { + if (idc->nbFields != + ((xmlSchemaIDCPtr) idc->ref->item)->nbFields) { + xmlChar *str = NULL; + xmlSchemaIDCPtr refer; + + refer = (xmlSchemaIDCPtr) idc->ref->item; + /* + * SPEC c-props-correct(2) + * "If the {identity-constraint category} is keyref, + * the cardinality of the {fields} must equal that of + * the {fields} of the {referenced key}. + */ + xmlSchemaCustomErr(ACTXT_CAST pctxt, + XML_SCHEMAP_C_PROPS_CORRECT, + NULL, WXS_BASIC_CAST idc, + "The cardinality of the keyref differs from the " + "cardinality of the referenced key/unique '%s'", + xmlSchemaFormatQName(&str, refer->targetNamespace, + refer->name), + NULL); + FREE_AND_NULL(str) + return(pctxt->err); + } + } + } + return(0); +} + +static int +xmlSchemaResolveAttrUseProhibReferences(xmlSchemaAttributeUseProhibPtr prohib, + xmlSchemaParserCtxtPtr pctxt) +{ + if (xmlSchemaGetAttributeDecl(pctxt->schema, prohib->name, + prohib->targetNamespace) == NULL) { + + xmlSchemaPResCompAttrErr(pctxt, + XML_SCHEMAP_SRC_RESOLVE, + NULL, prohib->node, + "ref", prohib->name, prohib->targetNamespace, + XML_SCHEMA_TYPE_ATTRIBUTE, NULL); + return(XML_SCHEMAP_SRC_RESOLVE); + } + return(0); +} + +#define WXS_REDEFINED_TYPE(c) \ +(((xmlSchemaTypePtr) item)->flags & XML_SCHEMAS_TYPE_REDEFINED) + +#define WXS_REDEFINED_MODEL_GROUP_DEF(c) \ +(((xmlSchemaModelGroupDefPtr) item)->flags & XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED) + +#define WXS_REDEFINED_ATTR_GROUP(c) \ +(((xmlSchemaAttributeGroupPtr) item)->flags & XML_SCHEMAS_ATTRGROUP_REDEFINED) + +static int +xmlSchemaCheckSRCRedefineFirst(xmlSchemaParserCtxtPtr pctxt) +{ + int err = 0; + xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs; + xmlSchemaBasicItemPtr prev, item; + int wasRedefined; + + if (redef == NULL) + return(0); + + do { + item = redef->item; + /* + * First try to locate the redefined component in the + * schema graph starting with the redefined schema. + * NOTE: According to this schema bug entry: + * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005OctDec/0019.html + * it's not clear if the referenced component needs to originate + * from the d schema _document_ or the schema; the latter + * would include all imported and included sub-schemas of the + * d schema. Currenlty we latter approach is used. + * SUPPLEMENT: It seems that the WG moves towards the latter + * approach, so we are doing it right. + * + */ + prev = xmlSchemaFindRedefCompInGraph( + redef->targetBucket, item->type, + redef->refName, redef->refTargetNs); + if (prev == NULL) { + xmlChar *str = NULL; + xmlNodePtr node; + + /* + * SPEC src-redefine: + * (6.2.1) "The ·actual value· of its own name attribute plus + * target namespace must successfully ·resolve· to a model + * group definition in I." + * (7.2.1) "The ·actual value· of its own name attribute plus + * target namespace must successfully ·resolve· to an attribute + * group definition in I." + + * + * Note that, if we are redefining with the use of references + * to components, the spec assumes the src-resolve to be used; + * but this won't assure that we search only *inside* the + * redefined schema. + */ + if (redef->reference) + node = WXS_ITEM_NODE(redef->reference); + else + node = WXS_ITEM_NODE(item); + xmlSchemaCustomErr(ACTXT_CAST pctxt, + /* + * TODO: error code. + * Probably XML_SCHEMAP_SRC_RESOLVE, if this is using the + * reference kind. + */ + XML_SCHEMAP_SRC_REDEFINE, node, NULL, + "The %s '%s' to be redefined could not be found in " + "the redefined schema", + WXS_ITEM_TYPE_NAME(item), + xmlSchemaFormatQName(&str, redef->refTargetNs, + redef->refName)); + FREE_AND_NULL(str); + err = pctxt->err; + redef = redef->next; + continue; + } + /* + * TODO: Obtaining and setting the redefinition state is really + * clumsy. + */ + wasRedefined = 0; + switch (item->type) { + case XML_SCHEMA_TYPE_COMPLEX: + case XML_SCHEMA_TYPE_SIMPLE: + if ((WXS_TYPE_CAST prev)->flags & + XML_SCHEMAS_TYPE_REDEFINED) + { + wasRedefined = 1; + break; + } + /* Mark it as redefined. */ + (WXS_TYPE_CAST prev)->flags |= XML_SCHEMAS_TYPE_REDEFINED; + /* + * Assign the redefined type to the + * base type of the redefining type. + * TODO: How + */ + ((xmlSchemaTypePtr) item)->baseType = + (xmlSchemaTypePtr) prev; + break; + case XML_SCHEMA_TYPE_GROUP: + if ((WXS_MODEL_GROUPDEF_CAST prev)->flags & + XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED) + { + wasRedefined = 1; + break; + } + /* Mark it as redefined. */ + (WXS_MODEL_GROUPDEF_CAST prev)->flags |= + XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED; + if (redef->reference != NULL) { + /* + * Overwrite the QName-reference with the + * referenced model group def. + */ + (WXS_PTC_CAST redef->reference)->children = + WXS_TREE_CAST prev; + } + redef->target = prev; + break; + case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: + if ((WXS_ATTR_GROUP_CAST prev)->flags & + XML_SCHEMAS_ATTRGROUP_REDEFINED) + { + wasRedefined = 1; + break; + } + (WXS_ATTR_GROUP_CAST prev)->flags |= + XML_SCHEMAS_ATTRGROUP_REDEFINED; + if (redef->reference != NULL) { + /* + * Assign the redefined attribute group to the + * QName-reference component. + * This is the easy case, since we will just + * expand the redefined group. + */ + (WXS_QNAME_CAST redef->reference)->item = prev; + redef->target = NULL; + } else { + /* + * This is the complicated case: we need + * to apply src-redefine (7.2.2) at a later + * stage, i.e. when attribute group references + * have beed expanded and simple types have + * beed fixed. + */ + redef->target = prev; + } + break; + default: + PERROR_INT("xmlSchemaResolveRedefReferences", + "Unexpected redefined component type"); + return(-1); + } + if (wasRedefined) { + xmlChar *str = NULL; + xmlNodePtr node; + + if (redef->reference) + node = WXS_ITEM_NODE(redef->reference); + else + node = WXS_ITEM_NODE(redef->item); + + xmlSchemaCustomErr(ACTXT_CAST pctxt, + /* TODO: error code. */ + XML_SCHEMAP_SRC_REDEFINE, + node, NULL, + "The referenced %s was already redefined. Multiple " + "redefinition of the same component is not supported", + xmlSchemaGetComponentDesignation(&str, prev), + NULL); + FREE_AND_NULL(str) + err = pctxt->err; + redef = redef->next; + continue; + } + redef = redef->next; + } while (redef != NULL); + + return(err); +} + +static int +xmlSchemaCheckSRCRedefineSecond(xmlSchemaParserCtxtPtr pctxt) +{ + int err = 0; + xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs; + xmlSchemaBasicItemPtr item; + + if (redef == NULL) + return(0); + + do { + if (redef->target == NULL) { + redef = redef->next; + continue; + } + item = redef->item; + + switch (item->type) { + case XML_SCHEMA_TYPE_SIMPLE: + case XML_SCHEMA_TYPE_COMPLEX: + /* + * Since the spec wants the {name} of the redefined + * type to be 'absent', we'll NULL it. + */ + (WXS_TYPE_CAST redef->target)->name = NULL; + + /* + * TODO: Seems like there's nothing more to do. The normal + * inheritance mechanism is used. But not 100% sure. + */ + break; + case XML_SCHEMA_TYPE_GROUP: + /* + * URGENT TODO: + * SPEC src-redefine: + * (6.2.2) "The {model group} of the model group definition + * which corresponds to it per XML Representation of Model + * Group Definition Schema Components (§3.7.2) must be a + * ·valid restriction· of the {model group} of that model + * group definition in I, as defined in Particle Valid + * (Restriction) (§3.9.6)." + */ + break; + case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: + /* + * SPEC src-redefine: + * (7.2.2) "The {attribute uses} and {attribute wildcard} of + * the attribute group definition which corresponds to it + * per XML Representation of Attribute Group Definition Schema + * Components (§3.6.2) must be ·valid restrictions· of the + * {attribute uses} and {attribute wildcard} of that attribute + * group definition in I, as defined in clause 2, clause 3 and + * clause 4 of Derivation Valid (Restriction, Complex) + * (§3.4.6) (where references to the base type definition are + * understood as references to the attribute group definition + * in I)." + */ + err = xmlSchemaCheckDerivationOKRestriction2to4(pctxt, + XML_SCHEMA_ACTION_REDEFINE, + item, redef->target, + (WXS_ATTR_GROUP_CAST item)->attrUses, + (WXS_ATTR_GROUP_CAST redef->target)->attrUses, + (WXS_ATTR_GROUP_CAST item)->attributeWildcard, + (WXS_ATTR_GROUP_CAST redef->target)->attributeWildcard); + if (err == -1) + return(-1); + break; + default: + break; + } + redef = redef->next; + } while (redef != NULL); + return(0); +} + + +static int +xmlSchemaAddComponents(xmlSchemaParserCtxtPtr pctxt, + xmlSchemaBucketPtr bucket) +{ + xmlSchemaBasicItemPtr item; + int err; + xmlHashTablePtr *table; + const xmlChar *name; + int i; + +#define WXS_GET_GLOBAL_HASH(c, slot) { \ + if (WXS_IS_BUCKET_IMPMAIN((c)->type)) \ + table = &(WXS_IMPBUCKET((c))->schema->slot); \ + else \ + table = &(WXS_INCBUCKET((c))->ownerImport->schema->slot); } + + /* + * Add global components to the schema's hash tables. + * This is the place where duplicate components will be + * detected. + * TODO: I think normally we should support imports of the + * same namespace from multiple locations. We don't do currently, + * but if we do then according to: + * http://www.w3.org/Bugs/Public/show_bug.cgi?id=2224 + * we would need, if imported directly, to import redefined + * components as well to be able to catch clashing components. + * (I hope I'll still know what this means after some months :-() + */ + if (bucket == NULL) + return(-1); + if (bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED) + return(0); + bucket->flags |= XML_SCHEMA_BUCKET_COMPS_ADDED; + + for (i = 0; i < bucket->globals->nbItems; i++) { + item = bucket->globals->items[i]; + table = NULL; + switch (item->type) { + case XML_SCHEMA_TYPE_COMPLEX: + case XML_SCHEMA_TYPE_SIMPLE: + if (WXS_REDEFINED_TYPE(item)) + continue; + name = (WXS_TYPE_CAST item)->name; + WXS_GET_GLOBAL_HASH(bucket, typeDecl) + break; + case XML_SCHEMA_TYPE_ELEMENT: + name = (WXS_ELEM_CAST item)->name; + WXS_GET_GLOBAL_HASH(bucket, elemDecl) + break; + case XML_SCHEMA_TYPE_ATTRIBUTE: + name = (WXS_ATTR_CAST item)->name; + WXS_GET_GLOBAL_HASH(bucket, attrDecl) + break; + case XML_SCHEMA_TYPE_GROUP: + if (WXS_REDEFINED_MODEL_GROUP_DEF(item)) + continue; + name = (WXS_MODEL_GROUPDEF_CAST item)->name; + WXS_GET_GLOBAL_HASH(bucket, groupDecl) + break; + case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: + if (WXS_REDEFINED_ATTR_GROUP(item)) + continue; + name = (WXS_ATTR_GROUP_CAST item)->name; + WXS_GET_GLOBAL_HASH(bucket, attrgrpDecl) + break; + case XML_SCHEMA_TYPE_IDC_KEY: + case XML_SCHEMA_TYPE_IDC_UNIQUE: + case XML_SCHEMA_TYPE_IDC_KEYREF: + name = (WXS_IDC_CAST item)->name; + WXS_GET_GLOBAL_HASH(bucket, idcDef) + break; + case XML_SCHEMA_TYPE_NOTATION: + name = ((xmlSchemaNotationPtr) item)->name; + WXS_GET_GLOBAL_HASH(bucket, notaDecl) + break; + default: + PERROR_INT("xmlSchemaAddComponents", + "Unexpected global component type"); + continue; + } + if (*table == NULL) { + *table = xmlHashCreateDict(10, pctxt->dict); + if (*table == NULL) { + PERROR_INT("xmlSchemaAddComponents", + "failed to create a component hash table"); + return(-1); + } + } + err = xmlHashAddEntry(*table, name, item); + if (err != 0) { + xmlChar *str = NULL; + + xmlSchemaCustomErr(ACTXT_CAST pctxt, + XML_SCHEMAP_REDEFINED_TYPE, + WXS_ITEM_NODE(item), + WXS_BASIC_CAST item, + "A global %s '%s' does already exist", + WXS_ITEM_TYPE_NAME(item), + xmlSchemaGetComponentQName(&str, item)); + FREE_AND_NULL(str); + } + } + /* + * Process imported/included schemas. + */ + if (bucket->relations != NULL) { + xmlSchemaSchemaRelationPtr rel = bucket->relations; + do { + if ((rel->bucket != NULL) && + ((rel->bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED) == 0)) { + if (xmlSchemaAddComponents(pctxt, rel->bucket) == -1) + return(-1); + } + rel = rel->next; + } while (rel != NULL); + } + return(0); +} + +static int +xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt, + xmlSchemaBucketPtr rootBucket) +{ + xmlSchemaConstructionCtxtPtr con = pctxt->constructor; + xmlSchemaTreeItemPtr item, *items; + int nbItems, i, ret = 0; + xmlSchemaBucketPtr oldbucket = con->bucket; + xmlSchemaElementPtr elemDecl; + +#define FIXHFAILURE if (pctxt->err == XML_SCHEMAP_INTERNAL) goto exit_failure; + + if ((con->pending == NULL) || + (con->pending->nbItems == 0)) + return(0); + + /* + * Since xmlSchemaFixupComplexType() will create new particles + * (local components), and those particle components need a bucket + * on the constructor, we'll assure here that the constructor has + * a bucket. + * TODO: Think about storing locals _only_ on the main bucket. + */ + if (con->bucket == NULL) + con->bucket = rootBucket; + + /* TODO: + * SPEC (src-redefine): + * (6.2) "If it has no such self-reference, then all of the + * following must be true:" + + * (6.2.2) The {model group} of the model group definition which + * corresponds to it per XML Representation of Model Group + * Definition Schema Components (§3.7.2) must be a ·valid + * restriction· of the {model group} of that model group definition + * in I, as defined in Particle Valid (Restriction) (§3.9.6)." + */ + xmlSchemaCheckSRCRedefineFirst(pctxt); + + /* + * Add global components to the schemata's hash tables. + */ + xmlSchemaAddComponents(pctxt, rootBucket); + + pctxt->ctxtType = NULL; + items = (xmlSchemaTreeItemPtr *) con->pending->items; + nbItems = con->pending->nbItems; + /* + * Now that we have parsed *all* the schema document(s) and converted + * them to schema components, we can resolve references, apply component + * constraints, create the FSA from the content model, etc. + */ + /* + * Resolve references of.. + * + * 1. element declarations: + * - the type definition + * - the substitution group affiliation + * 2. simple/complex types: + * - the base type definition + * - the memberTypes of union types + * - the itemType of list types + * 3. attributes declarations and attribute uses: + * - the type definition + * - if an attribute use, then the attribute declaration + * 4. attribute group references: + * - the attribute group definition + * 5. particles: + * - the term of the particle (e.g. a model group) + * 6. IDC key-references: + * - the referenced IDC 'key' or 'unique' definition + * 7. Attribute prohibitions which had a "ref" attribute. + */ + for (i = 0; i < nbItems; i++) { + item = items[i]; + switch (item->type) { + case XML_SCHEMA_TYPE_ELEMENT: + xmlSchemaResolveElementReferences( + (xmlSchemaElementPtr) item, pctxt); + FIXHFAILURE; + break; + case XML_SCHEMA_TYPE_COMPLEX: + case XML_SCHEMA_TYPE_SIMPLE: + xmlSchemaResolveTypeReferences( + (xmlSchemaTypePtr) item, pctxt); + FIXHFAILURE; + break; + case XML_SCHEMA_TYPE_ATTRIBUTE: + xmlSchemaResolveAttrTypeReferences( + (xmlSchemaAttributePtr) item, pctxt); + FIXHFAILURE; + break; + case XML_SCHEMA_TYPE_ATTRIBUTE_USE: + xmlSchemaResolveAttrUseReferences( + (xmlSchemaAttributeUsePtr) item, pctxt); + FIXHFAILURE; + break; + case XML_SCHEMA_EXTRA_QNAMEREF: + if ((WXS_QNAME_CAST item)->itemType == + XML_SCHEMA_TYPE_ATTRIBUTEGROUP) + { + xmlSchemaResolveAttrGroupReferences( + WXS_QNAME_CAST item, pctxt); + } + FIXHFAILURE; + break; + case XML_SCHEMA_TYPE_SEQUENCE: + case XML_SCHEMA_TYPE_CHOICE: + case XML_SCHEMA_TYPE_ALL: + xmlSchemaResolveModelGroupParticleReferences(pctxt, + WXS_MODEL_GROUP_CAST item); + FIXHFAILURE; + break; + case XML_SCHEMA_TYPE_IDC_KEY: + case XML_SCHEMA_TYPE_IDC_UNIQUE: + case XML_SCHEMA_TYPE_IDC_KEYREF: + xmlSchemaResolveIDCKeyReferences( + (xmlSchemaIDCPtr) item, pctxt); + FIXHFAILURE; + break; + case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB: + /* + * Handle attribue prohibition which had a + * "ref" attribute. + */ + xmlSchemaResolveAttrUseProhibReferences( + WXS_ATTR_PROHIB_CAST item, pctxt); + FIXHFAILURE; + break; + default: + break; + } + } + if (pctxt->nberrors != 0) + goto exit_error; + + /* + * Now that all references are resolved we + * can check for circularity of... + * 1. the base axis of type definitions + * 2. nested model group definitions + * 3. nested attribute group definitions + * TODO: check for circual substitution groups. + */ + for (i = 0; i < nbItems; i++) { + item = items[i]; + /* + * Let's better stop on the first error here. + */ + switch (item->type) { + case XML_SCHEMA_TYPE_COMPLEX: + case XML_SCHEMA_TYPE_SIMPLE: + xmlSchemaCheckTypeDefCircular( + (xmlSchemaTypePtr) item, pctxt); + FIXHFAILURE; + if (pctxt->nberrors != 0) + goto exit_error; + break; + case XML_SCHEMA_TYPE_GROUP: + xmlSchemaCheckGroupDefCircular( + (xmlSchemaModelGroupDefPtr) item, pctxt); + FIXHFAILURE; + if (pctxt->nberrors != 0) + goto exit_error; + break; + case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: + xmlSchemaCheckAttrGroupCircular( + (xmlSchemaAttributeGroupPtr) item, pctxt); + FIXHFAILURE; + if (pctxt->nberrors != 0) + goto exit_error; + break; + default: + break; + } + } + if (pctxt->nberrors != 0) + goto exit_error; + /* + * Model group definition references: + * Such a reference is reflected by a particle at the component + * level. Until now the 'term' of such particles pointed + * to the model group definition; this was done, in order to + * ease circularity checks. Now we need to set the 'term' of + * such particles to the model group of the model group definition. + */ + for (i = 0; i < nbItems; i++) { + item = items[i]; + switch (item->type) { + case XML_SCHEMA_TYPE_SEQUENCE: + case XML_SCHEMA_TYPE_CHOICE: + xmlSchemaModelGroupToModelGroupDefFixup(pctxt, + WXS_MODEL_GROUP_CAST item); + break; + default: + break; + } + } + if (pctxt->nberrors != 0) + goto exit_error; + /* + * Expand attribute group references of attribute group definitions. + */ + for (i = 0; i < nbItems; i++) { + item = items[i]; + switch (item->type) { + case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: + if ((! WXS_ATTR_GROUP_EXPANDED(item)) && + WXS_ATTR_GROUP_HAS_REFS(item)) + { + xmlSchemaAttributeGroupExpandRefs(pctxt, + WXS_ATTR_GROUP_CAST item); + FIXHFAILURE; + } + break; + default: + break; + } + } + if (pctxt->nberrors != 0) + goto exit_error; + /* + * First compute the variety of simple types. This is needed as + * a seperate step, since otherwise we won't be able to detect + * circular union types in all cases. + */ + for (i = 0; i < nbItems; i++) { + item = items[i]; + switch (item->type) { + case XML_SCHEMA_TYPE_SIMPLE: + if (WXS_IS_TYPE_NOT_FIXED_1((xmlSchemaTypePtr) item)) { + xmlSchemaFixupSimpleTypeStageOne(pctxt, + (xmlSchemaTypePtr) item); + FIXHFAILURE; + } + break; + default: + break; + } + } + if (pctxt->nberrors != 0) + goto exit_error; + /* + * Detect circular union types. Note that this needs the variety to + * be already computed. + */ + for (i = 0; i < nbItems; i++) { + item = items[i]; + switch (item->type) { + case XML_SCHEMA_TYPE_SIMPLE: + if (((xmlSchemaTypePtr) item)->memberTypes != NULL) { + xmlSchemaCheckUnionTypeDefCircular(pctxt, + (xmlSchemaTypePtr) item); + FIXHFAILURE; + } + break; + default: + break; + } + } + if (pctxt->nberrors != 0) + goto exit_error; + + /* + * Do the complete type fixup for simple types. + */ + for (i = 0; i < nbItems; i++) { + item = items[i]; + switch (item->type) { + case XML_SCHEMA_TYPE_SIMPLE: + if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) { + xmlSchemaFixupSimpleTypeStageTwo(pctxt, WXS_TYPE_CAST item); + FIXHFAILURE; + } + break; + default: + break; + } + } + if (pctxt->nberrors != 0) + goto exit_error; + /* + * At this point we need build and check all simple types. + */ + /* + * Apply contraints for attribute declarations. + */ + for (i = 0; i < nbItems; i++) { + item = items[i]; + switch (item->type) { + case XML_SCHEMA_TYPE_ATTRIBUTE: + xmlSchemaCheckAttrPropsCorrect(pctxt, WXS_ATTR_CAST item); + FIXHFAILURE; + break; + default: + break; + } + } + if (pctxt->nberrors != 0) + goto exit_error; + /* + * Apply constraints for attribute uses. + */ + for (i = 0; i < nbItems; i++) { + item = items[i]; + switch (item->type) { + case XML_SCHEMA_TYPE_ATTRIBUTE_USE: + if (((xmlSchemaAttributeUsePtr)item)->defValue != NULL) { + xmlSchemaCheckAttrUsePropsCorrect(pctxt, + WXS_ATTR_USE_CAST item); + FIXHFAILURE; + } + break; + default: + break; + } + } + if (pctxt->nberrors != 0) + goto exit_error; + + /* + * Apply constraints for attribute group definitions. + */ + for (i = 0; i < nbItems; i++) { + item = items[i]; + switch (item->type) { + case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: + if (( (WXS_ATTR_GROUP_CAST item)->attrUses != NULL) && + ( (WXS_LIST_CAST (WXS_ATTR_GROUP_CAST item)->attrUses)->nbItems > 1)) + { + xmlSchemaCheckAGPropsCorrect(pctxt, WXS_ATTR_GROUP_CAST item); + FIXHFAILURE; + } + break; + default: + break; + } + } + if (pctxt->nberrors != 0) + goto exit_error; + + /* + * Apply constraints for redefinitions. + */ + if (WXS_CONSTRUCTOR(pctxt)->redefs != NULL) + xmlSchemaCheckSRCRedefineSecond(pctxt); + if (pctxt->nberrors != 0) + goto exit_error; + + /* + * Complex types are builded and checked. + */ + for (i = 0; i < nbItems; i++) { + item = con->pending->items[i]; + switch (item->type) { + case XML_SCHEMA_TYPE_COMPLEX: + if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) { + xmlSchemaFixupComplexType(pctxt, WXS_TYPE_CAST item); + FIXHFAILURE; + } + break; + default: + break; + } + } + if (pctxt->nberrors != 0) + goto exit_error; + + /* + * The list could have changed, since xmlSchemaFixupComplexType() + * will create particles and model groups in some cases. + */ + items = (xmlSchemaTreeItemPtr *) con->pending->items; + nbItems = con->pending->nbItems; + + /* + * Apply some constraints for element declarations. + */ + for (i = 0; i < nbItems; i++) { + item = items[i]; + switch (item->type) { + case XML_SCHEMA_TYPE_ELEMENT: + elemDecl = (xmlSchemaElementPtr) item; + + if ((elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED) == 0) + { + xmlSchemaCheckElementDeclComponent( + (xmlSchemaElementPtr) elemDecl, pctxt); + FIXHFAILURE; + } + +#ifdef WXS_ELEM_DECL_CONS_ENABLED + /* + * Schema Component Constraint: Element Declarations Consistent + * Apply this constraint to local types of element declarations. + */ + if ((WXS_ELEM_TYPEDEF(elemDecl) != NULL) && + (WXS_IS_COMPLEX(WXS_ELEM_TYPEDEF(elemDecl))) && + (WXS_TYPE_IS_LOCAL(WXS_ELEM_TYPEDEF(elemDecl)))) + { + xmlSchemaCheckElementDeclConsistent(pctxt, + WXS_BASIC_CAST elemDecl, + WXS_TYPE_PARTICLE(WXS_ELEM_TYPEDEF(elemDecl)), + NULL, NULL, 0); + } +#endif + break; + default: + break; + } + } + if (pctxt->nberrors != 0) + goto exit_error; + + /* + * Finally we can build the automaton from the content model of + * complex types. + */ + + for (i = 0; i < nbItems; i++) { + item = items[i]; + switch (item->type) { + case XML_SCHEMA_TYPE_COMPLEX: + xmlSchemaBuildContentModel((xmlSchemaTypePtr) item, pctxt); + /* FIXHFAILURE; */ + break; + default: + break; + } + } + if (pctxt->nberrors != 0) + goto exit_error; + /* + * URGENT TODO: cos-element-consistent + */ + goto exit; + +exit_error: + ret = pctxt->err; + goto exit; + +exit_failure: + ret = -1; + +exit: + /* + * Reset the constructor. This is needed for XSI acquisition, since + * those items will be processed over and over again for every XSI + * if not cleared here. + */ + con->bucket = oldbucket; + con->pending->nbItems = 0; + if (con->substGroups != NULL) { + xmlHashFree(con->substGroups, + (xmlHashDeallocator) xmlSchemaSubstGroupFree); + con->substGroups = NULL; + } + if (con->redefs != NULL) { + xmlSchemaRedefListFree(con->redefs); + con->redefs = NULL; + } + return(ret); +} +/** + * xmlSchemaParse: + * @ctxt: a schema validation context + * + * parse a schema definition resource and build an internal + * XML Shema struture which can be used to validate instances. + * + * Returns the internal XML Schema structure built from the resource or + * NULL in case of error + */ +xmlSchemaPtr +xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt) +{ + xmlSchemaPtr mainSchema = NULL; + xmlSchemaBucketPtr bucket = NULL; + int res; + + /* + * This one is used if the schema to be parsed was specified via + * the API; i.e. not automatically by the validated instance document. + */ + + xmlSchemaInitTypes(); + + if (ctxt == NULL) + return (NULL); + + /* TODO: Init the context. Is this all we need?*/ + ctxt->nberrors = 0; + ctxt->err = 0; + ctxt->counter = 0; + + /* Create the *main* schema. */ + mainSchema = xmlSchemaNewSchema(ctxt); + if (mainSchema == NULL) + goto exit_failure; + /* + * Create the schema constructor. + */ + if (ctxt->constructor == NULL) { + ctxt->constructor = xmlSchemaConstructionCtxtCreate(ctxt->dict); + if (ctxt->constructor == NULL) + return(NULL); + /* Take ownership of the constructor to be able to free it. */ + ctxt->ownsConstructor = 1; + } + ctxt->constructor->mainSchema = mainSchema; + /* + * Locate and add the schema document. + */ + res = xmlSchemaAddSchemaDoc(ctxt, XML_SCHEMA_SCHEMA_MAIN, + ctxt->URL, ctxt->doc, ctxt->buffer, ctxt->size, NULL, + NULL, NULL, &bucket); + if (res == -1) + goto exit_failure; + if (res != 0) + goto exit; + + if (bucket == NULL) { + /* TODO: Error code, actually we failed to *locate* the schema. */ + if (ctxt->URL) + xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD, + NULL, NULL, + "Failed to locate the main schema resource at '%s'", + ctxt->URL, NULL); + else + xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD, + NULL, NULL, + "Failed to locate the main schema resource", + NULL, NULL); + goto exit; + } + /* Then do the parsing for good. */ + if (xmlSchemaParseNewDocWithContext(ctxt, mainSchema, bucket) == -1) + goto exit_failure; + if (ctxt->nberrors != 0) + goto exit; + + mainSchema->doc = bucket->doc; + mainSchema->preserve = ctxt->preserve; + + ctxt->schema = mainSchema; + + if (xmlSchemaFixupComponents(ctxt, WXS_CONSTRUCTOR(ctxt)->mainBucket) == -1) + goto exit_failure; + + /* + * TODO: This is not nice, since we cannot distinguish from the + * result if there was an internal error or not. + */ +exit: + if (ctxt->nberrors != 0) { + if (mainSchema) { + xmlSchemaFree(mainSchema); + mainSchema = NULL; + } + if (ctxt->constructor) { + xmlSchemaConstructionCtxtFree(ctxt->constructor); + ctxt->constructor = NULL; + ctxt->ownsConstructor = 0; + } + } + ctxt->schema = NULL; + return(mainSchema); +exit_failure: + /* + * Quite verbose, but should catch internal errors, which were + * not communitated. + */ + if (mainSchema) { + xmlSchemaFree(mainSchema); + mainSchema = NULL; + } + if (ctxt->constructor) { + xmlSchemaConstructionCtxtFree(ctxt->constructor); + ctxt->constructor = NULL; + ctxt->ownsConstructor = 0; + } + PERROR_INT2("xmlSchemaParse", + "An internal error occured"); + ctxt->schema = NULL; + return(NULL); +} + +/** + * xmlSchemaSetParserErrors: + * @ctxt: a schema validation context + * @err: the error callback + * @warn: the warning callback + * @ctx: contextual data for the callbacks + * + * Set the callback functions used to handle errors for a validation context + */ +void +xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt, + xmlSchemaValidityErrorFunc err, + xmlSchemaValidityWarningFunc warn, void *ctx) +{ + if (ctxt == NULL) + return; + ctxt->error = err; + ctxt->warning = warn; + ctxt->errCtxt = ctx; + if (ctxt->vctxt != NULL) + xmlSchemaSetValidErrors(ctxt->vctxt, err, warn, ctx); +} + +/** + * xmlSchemaSetParserStructuredErrors: + * @ctxt: a schema parser context + * @serror: the structured error function + * @ctx: the functions context + * + * Set the structured error callback + */ +void +xmlSchemaSetParserStructuredErrors(xmlSchemaParserCtxtPtr ctxt, + xmlStructuredErrorFunc serror, + void *ctx) +{ + if (ctxt == NULL) + return; + ctxt->serror = serror; + ctxt->errCtxt = ctx; + if (ctxt->vctxt != NULL) + xmlSchemaSetValidStructuredErrors(ctxt->vctxt, serror, ctx); +} + +/** + * xmlSchemaGetParserErrors: + * @ctxt: a XMl-Schema parser context + * @err: the error callback result + * @warn: the warning callback result + * @ctx: contextual data for the callbacks result + * + * Get the callback information used to handle errors for a parser context + * + * Returns -1 in case of failure, 0 otherwise + */ +int +xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt, + xmlSchemaValidityErrorFunc * err, + xmlSchemaValidityWarningFunc * warn, void **ctx) +{ + if (ctxt == NULL) + return(-1); + if (err != NULL) + *err = ctxt->error; + if (warn != NULL) + *warn = ctxt->warning; + if (ctx != NULL) + *ctx = ctxt->errCtxt; + return(0); +} + +/** + * xmlSchemaFacetTypeToString: + * @type: the facet type + * + * Convert the xmlSchemaTypeType to a char string. + * + * Returns the char string representation of the facet type if the + * type is a facet and an "Internal Error" string otherwise. + */ +static const xmlChar * +xmlSchemaFacetTypeToString(xmlSchemaTypeType type) +{ + switch (type) { + case XML_SCHEMA_FACET_PATTERN: + return (BAD_CAST "pattern"); + case XML_SCHEMA_FACET_MAXEXCLUSIVE: + return (BAD_CAST "maxExclusive"); + case XML_SCHEMA_FACET_MAXINCLUSIVE: + return (BAD_CAST "maxInclusive"); + case XML_SCHEMA_FACET_MINEXCLUSIVE: + return (BAD_CAST "minExclusive"); + case XML_SCHEMA_FACET_MININCLUSIVE: + return (BAD_CAST "minInclusive"); + case XML_SCHEMA_FACET_WHITESPACE: + return (BAD_CAST "whiteSpace"); + case XML_SCHEMA_FACET_ENUMERATION: + return (BAD_CAST "enumeration"); + case XML_SCHEMA_FACET_LENGTH: + return (BAD_CAST "length"); + case XML_SCHEMA_FACET_MAXLENGTH: + return (BAD_CAST "maxLength"); + case XML_SCHEMA_FACET_MINLENGTH: + return (BAD_CAST "minLength"); + case XML_SCHEMA_FACET_TOTALDIGITS: + return (BAD_CAST "totalDigits"); + case XML_SCHEMA_FACET_FRACTIONDIGITS: + return (BAD_CAST "fractionDigits"); + default: + break; + } + return (BAD_CAST "Internal Error"); +} + +static xmlSchemaWhitespaceValueType +xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type) +{ + /* + * The normalization type can be changed only for types which are derived + * from xsd:string. + */ + if (type->type == XML_SCHEMA_TYPE_BASIC) { + /* + * Note that we assume a whitespace of preserve for anySimpleType. + */ + if ((type->builtInType == XML_SCHEMAS_STRING) || + (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) + return(XML_SCHEMA_WHITESPACE_PRESERVE); + else if (type->builtInType == XML_SCHEMAS_NORMSTRING) + return(XML_SCHEMA_WHITESPACE_REPLACE); + else { + /* + * For all ·atomic· datatypes other than string (and types ·derived· + * by ·restriction· from it) the value of whiteSpace is fixed to + * collapse + * Note that this includes built-in list datatypes. + */ + return(XML_SCHEMA_WHITESPACE_COLLAPSE); + } + } else if (WXS_IS_LIST(type)) { + /* + * For list types the facet "whiteSpace" is fixed to "collapse". + */ + return (XML_SCHEMA_WHITESPACE_COLLAPSE); + } else if (WXS_IS_UNION(type)) { + return (XML_SCHEMA_WHITESPACE_UNKNOWN); + } else if (WXS_IS_ATOMIC(type)) { + if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE) + return (XML_SCHEMA_WHITESPACE_PRESERVE); + else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE) + return (XML_SCHEMA_WHITESPACE_REPLACE); + else + return (XML_SCHEMA_WHITESPACE_COLLAPSE); + } + return (-1); +} + +/************************************************************************ + * * + * Simple type validation * + * * + ************************************************************************/ + + +/************************************************************************ + * * + * DOM Validation code * + * * + ************************************************************************/ + +/** + * xmlSchemaAssembleByLocation: + * @pctxt: a schema parser context + * @vctxt: a schema validation context + * @schema: the existing schema + * @node: the node that fired the assembling + * @nsName: the namespace name of the new schema + * @location: the location of the schema + * + * Expands an existing schema by an additional schema. + * + * Returns 0 if the new schema is correct, a positive error code + * number otherwise and -1 in case of an internal or API error. + */ +static int +xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt, + xmlSchemaPtr schema, + xmlNodePtr node, + const xmlChar *nsName, + const xmlChar *location) +{ + int ret = 0; + xmlSchemaParserCtxtPtr pctxt; + xmlSchemaBucketPtr bucket = NULL; + + if ((vctxt == NULL) || (schema == NULL)) + return (-1); + + if (vctxt->pctxt == NULL) { + VERROR_INT("xmlSchemaAssembleByLocation", + "no parser context available"); + return(-1); + } + pctxt = vctxt->pctxt; + if (pctxt->constructor == NULL) { + PERROR_INT("xmlSchemaAssembleByLocation", + "no constructor"); + return(-1); + } + /* + * Acquire the schema document. + */ + location = xmlSchemaBuildAbsoluteURI(pctxt->dict, + location, node); + /* + * Note that we pass XML_SCHEMA_SCHEMA_IMPORT here; + * the process will automatically change this to + * XML_SCHEMA_SCHEMA_MAIN if it is the first schema document. + */ + ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT, + location, NULL, NULL, 0, node, NULL, nsName, + &bucket); + if (ret != 0) + return(ret); + if (bucket == NULL) { + /* + * Generate a warning that the document could not be located. + */ + xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC, + node, NULL, + "The document at location '%s' could not be acquired", + location, NULL, NULL); + return(ret); + } + /* + * The first located schema will be handled as if all other + * schemas imported by XSI were imported by this first schema. + */ + if ((bucket != NULL) && + (WXS_CONSTRUCTOR(pctxt)->bucket == NULL)) + WXS_CONSTRUCTOR(pctxt)->bucket = bucket; + /* + * TODO: Is this handled like an import? I.e. is it not an error + * if the schema cannot be located? + */ + if ((bucket == NULL) || (! CAN_PARSE_SCHEMA(bucket))) + return(0); + /* + * We will reuse the parser context for every schema imported + * directly via XSI. So reset the context. + */ + pctxt->nberrors = 0; + pctxt->err = 0; + pctxt->doc = bucket->doc; + + ret = xmlSchemaParseNewDocWithContext(pctxt, schema, bucket); + if (ret == -1) { + pctxt->doc = NULL; + goto exit_failure; + } + /* Paranoid error channelling. */ + if ((ret == 0) && (pctxt->nberrors != 0)) + ret = pctxt->err; + if (pctxt->nberrors == 0) { + /* + * Only bother to fixup pending components, if there was + * no error yet. + * For every XSI acquired schema (and its sub-schemata) we will + * fixup the components. + */ + xmlSchemaFixupComponents(pctxt, bucket); + ret = pctxt->err; + /* + * Not nice, but we need somehow to channel the schema parser + * error to the validation context. + */ + if ((ret != 0) && (vctxt->err == 0)) + vctxt->err = ret; + vctxt->nberrors += pctxt->nberrors; + } else { + /* Add to validation error sum. */ + vctxt->nberrors += pctxt->nberrors; + } + pctxt->doc = NULL; + return(ret); +exit_failure: + pctxt->doc = NULL; + return (-1); +} + +static xmlSchemaAttrInfoPtr +xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt, + int metaType) +{ + if (vctxt->nbAttrInfos == 0) + return (NULL); + { + int i; + xmlSchemaAttrInfoPtr iattr; + + for (i = 0; i < vctxt->nbAttrInfos; i++) { + iattr = vctxt->attrInfos[i]; + if (iattr->metaType == metaType) + return (iattr); + } + + } + return (NULL); +} + +/** + * xmlSchemaAssembleByXSI: + * @vctxt: a schema validation context + * + * Expands an existing schema by an additional schema using + * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute + * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace + * must be set to 1. + * + * Returns 0 if the new schema is correct, a positive error code + * number otherwise and -1 in case of an internal or API error. + */ +static int +xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt) +{ + const xmlChar *cur, *end; + const xmlChar *nsname = NULL, *location; + int count = 0; + int ret = 0; + xmlSchemaAttrInfoPtr iattr; + + /* + * Parse the value; we will assume an even number of values + * to be given (this is how Xerces and XSV work). + * + * URGENT TODO: !! This needs to work for both + * @noNamespaceSchemaLocation AND @schemaLocation on the same + * element !! + */ + iattr = xmlSchemaGetMetaAttrInfo(vctxt, + XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC); + if (iattr == NULL) + iattr = xmlSchemaGetMetaAttrInfo(vctxt, + XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC); + if (iattr == NULL) + return (0); + cur = iattr->value; + do { + /* + * TODO: Move the string parsing mechanism away from here. + */ + if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) { + /* + * Get the namespace name. + */ + while (IS_BLANK_CH(*cur)) + cur++; + end = cur; + while ((*end != 0) && (!(IS_BLANK_CH(*end)))) + end++; + if (end == cur) + break; + count++; /* TODO: Don't use the schema's dict. */ + nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur); + cur = end; + } + /* + * Get the URI. + */ + while (IS_BLANK_CH(*cur)) + cur++; + end = cur; + while ((*end != 0) && (!(IS_BLANK_CH(*end)))) + end++; + if (end == cur) { + if (iattr->metaType == + XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) + { + /* + * If using @schemaLocation then tuples are expected. + * I.e. the namespace name *and* the document's URI. + */ + xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC, + iattr->node, NULL, + "The value must consist of tuples: the target namespace " + "name and the document's URI", NULL, NULL, NULL); + } + break; + } + count++; /* TODO: Don't use the schema's dict. */ + location = xmlDictLookup(vctxt->schema->dict, cur, end - cur); + cur = end; + ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema, + iattr->node, nsname, location); + if (ret == -1) { + VERROR_INT("xmlSchemaAssembleByXSI", + "assembling schemata"); + return (-1); + } + } while (*cur != 0); + return (ret); +} + +static const xmlChar * +xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt, + const xmlChar *prefix) +{ + if (vctxt->sax != NULL) { + int i, j; + xmlSchemaNodeInfoPtr inode; + + for (i = vctxt->depth; i >= 0; i--) { + if (vctxt->elemInfos[i]->nbNsBindings != 0) { + inode = vctxt->elemInfos[i]; + for (j = 0; j < inode->nbNsBindings * 2; j += 2) { + if (((prefix == NULL) && + (inode->nsBindings[j] == NULL)) || + ((prefix != NULL) && xmlStrEqual(prefix, + inode->nsBindings[j]))) { + + /* + * Note that the namespace bindings are already + * in a string dict. + */ + return (inode->nsBindings[j+1]); + } + } + } + } + return (NULL); +#ifdef LIBXML_WRITER_ENABLED + } else if (vctxt->reader != NULL) { + xmlChar *nsName; + + nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix); + if (nsName != NULL) { + const xmlChar *ret; + + ret = xmlDictLookup(vctxt->dict, nsName, -1); + xmlFree(nsName); + return (ret); + } else + return (NULL); +#endif + } else { + xmlNsPtr ns; + + if ((vctxt->inode->node == NULL) || + (vctxt->inode->node->doc == NULL)) { + VERROR_INT("xmlSchemaLookupNamespace", + "no node or node's doc avaliable"); + return (NULL); + } + ns = xmlSearchNs(vctxt->inode->node->doc, + vctxt->inode->node, prefix); + if (ns != NULL) + return (ns->href); + return (NULL); + } +} + +/* +* This one works on the schema of the validation context. +*/ +static int +xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt, + xmlSchemaPtr schema, + xmlNodePtr node, + const xmlChar *value, + xmlSchemaValPtr *val, + int valNeeded) +{ + int ret; + + if (vctxt && (vctxt->schema == NULL)) { + VERROR_INT("xmlSchemaValidateNotation", + "a schema is needed on the validation context"); + return (-1); + } + ret = xmlValidateQName(value, 1); + if (ret != 0) + return (ret); + { + xmlChar *localName = NULL; + xmlChar *prefix = NULL; + + localName = xmlSplitQName2(value, &prefix); + if (prefix != NULL) { + const xmlChar *nsName = NULL; + + if (vctxt != NULL) + nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix); + else if (node != NULL) { + xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix); + if (ns != NULL) + nsName = ns->href; + } else { + xmlFree(prefix); + xmlFree(localName); + return (1); + } + if (nsName == NULL) { + xmlFree(prefix); + xmlFree(localName); + return (1); + } + if (xmlSchemaGetNotation(schema, localName, nsName) != NULL) { + if (valNeeded && (val != NULL)) { + (*val) = xmlSchemaNewNOTATIONValue(BAD_CAST localName, + BAD_CAST xmlStrdup(nsName)); + if (*val == NULL) + ret = -1; + } + } else + ret = 1; + xmlFree(prefix); + xmlFree(localName); + } else { + if (xmlSchemaGetNotation(schema, value, NULL) != NULL) { + if (valNeeded && (val != NULL)) { + (*val) = xmlSchemaNewNOTATIONValue( + BAD_CAST xmlStrdup(value), NULL); + if (*val == NULL) + ret = -1; + } + } else + return (1); + } + } + return (ret); +} + +static int +xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt, + const xmlChar* lname, + const xmlChar* nsname) +{ + int i; + + lname = xmlDictLookup(vctxt->dict, lname, -1); + if (lname == NULL) + return(-1); + if (nsname != NULL) { + nsname = xmlDictLookup(vctxt->dict, nsname, -1); + if (nsname == NULL) + return(-1); + } + for (i = 0; i < vctxt->nodeQNames->nbItems; i += 2) { + if ((vctxt->nodeQNames->items [i] == lname) && + (vctxt->nodeQNames->items[i +1] == nsname)) + /* Already there */ + return(i); + } + /* Add new entry. */ + i = vctxt->nodeQNames->nbItems; + xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) lname); + xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) nsname); + return(i); +} + +/************************************************************************ + * * + * Validation of identity-constraints (IDC) * + * * + ************************************************************************/ + +/** + * xmlSchemaAugmentIDC: + * @idcDef: the IDC definition + * + * Creates an augmented IDC definition item. + * + * Returns the item, or NULL on internal errors. + */ +static void +xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef, + xmlSchemaValidCtxtPtr vctxt) +{ + xmlSchemaIDCAugPtr aidc; + + aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug)); + if (aidc == NULL) { + xmlSchemaVErrMemory(vctxt, + "xmlSchemaAugmentIDC: allocating an augmented IDC definition", + NULL); + return; + } + aidc->keyrefDepth = -1; + aidc->def = idcDef; + aidc->next = NULL; + if (vctxt->aidcs == NULL) + vctxt->aidcs = aidc; + else { + aidc->next = vctxt->aidcs; + vctxt->aidcs = aidc; + } + /* + * Save if we have keyrefs at all. + */ + if ((vctxt->hasKeyrefs == 0) && + (idcDef->type == XML_SCHEMA_TYPE_IDC_KEYREF)) + vctxt->hasKeyrefs = 1; +} + +/** + * xmlSchemaIDCNewBinding: + * @idcDef: the IDC definition of this binding + * + * Creates a new IDC binding. + * + * Returns the new IDC binding, NULL on internal errors. + */ +static xmlSchemaPSVIIDCBindingPtr +xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef) +{ + xmlSchemaPSVIIDCBindingPtr ret; + + ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc( + sizeof(xmlSchemaPSVIIDCBinding)); + if (ret == NULL) { + xmlSchemaVErrMemory(NULL, + "allocating a PSVI IDC binding item", NULL); + return (NULL); + } + memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding)); + ret->definition = idcDef; + return (ret); +} + +/** + * xmlSchemaIDCStoreNodeTableItem: + * @vctxt: the WXS validation context + * @item: the IDC node table item + * + * The validation context is used to store IDC node table items. + * They are stored to avoid copying them if IDC node-tables are merged + * with corresponding parent IDC node-tables (bubbling). + * + * Returns 0 if succeeded, -1 on internal errors. + */ +static int +xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt, + xmlSchemaPSVIIDCNodePtr item) +{ + /* + * Add to gobal list. + */ + if (vctxt->idcNodes == NULL) { + vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *) + xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr)); + if (vctxt->idcNodes == NULL) { + xmlSchemaVErrMemory(vctxt, + "allocating the IDC node table item list", NULL); + return (-1); + } + vctxt->sizeIdcNodes = 20; + } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) { + vctxt->sizeIdcNodes *= 2; + vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *) + xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes * + sizeof(xmlSchemaPSVIIDCNodePtr)); + if (vctxt->idcNodes == NULL) { + xmlSchemaVErrMemory(vctxt, + "re-allocating the IDC node table item list", NULL); + return (-1); + } + } + vctxt->idcNodes[vctxt->nbIdcNodes++] = item; + + return (0); +} + +/** + * xmlSchemaIDCStoreKey: + * @vctxt: the WXS validation context + * @item: the IDC key + * + * The validation context is used to store an IDC key. + * + * Returns 0 if succeeded, -1 on internal errors. + */ +static int +xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt, + xmlSchemaPSVIIDCKeyPtr key) +{ + /* + * Add to gobal list. + */ + if (vctxt->idcKeys == NULL) { + vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *) + xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr)); + if (vctxt->idcKeys == NULL) { + xmlSchemaVErrMemory(vctxt, + "allocating the IDC key storage list", NULL); + return (-1); + } + vctxt->sizeIdcKeys = 40; + } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) { + vctxt->sizeIdcKeys *= 2; + vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *) + xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys * + sizeof(xmlSchemaPSVIIDCKeyPtr)); + if (vctxt->idcKeys == NULL) { + xmlSchemaVErrMemory(vctxt, + "re-allocating the IDC key storage list", NULL); + return (-1); + } + } + vctxt->idcKeys[vctxt->nbIdcKeys++] = key; + + return (0); +} + +/** + * xmlSchemaIDCAppendNodeTableItem: + * @bind: the IDC binding + * @ntItem: the node-table item + * + * Appends the IDC node-table item to the binding. + * + * Returns 0 on success and -1 on internal errors. + */ +static int +xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind, + xmlSchemaPSVIIDCNodePtr ntItem) +{ + if (bind->nodeTable == NULL) { + bind->sizeNodes = 10; + bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *) + xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr)); + if (bind->nodeTable == NULL) { + xmlSchemaVErrMemory(NULL, + "allocating an array of IDC node-table items", NULL); + return(-1); + } + } else if (bind->sizeNodes <= bind->nbNodes) { + bind->sizeNodes *= 2; + bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *) + xmlRealloc(bind->nodeTable, bind->sizeNodes * + sizeof(xmlSchemaPSVIIDCNodePtr)); + if (bind->nodeTable == NULL) { + xmlSchemaVErrMemory(NULL, + "re-allocating an array of IDC node-table items", NULL); + return(-1); + } + } + bind->nodeTable[bind->nbNodes++] = ntItem; + return(0); +} + +/** + * xmlSchemaIDCAcquireBinding: + * @vctxt: the WXS validation context + * @matcher: the IDC matcher + * + * Looks up an PSVI IDC binding, for the IDC definition and + * of the given matcher. If none found, a new one is created + * and added to the IDC table. + * + * Returns an IDC binding or NULL on internal errors. + */ +static xmlSchemaPSVIIDCBindingPtr +xmlSchemaIDCAcquireBinding(xmlSchemaValidCtxtPtr vctxt, + xmlSchemaIDCMatcherPtr matcher) +{ + xmlSchemaNodeInfoPtr ielem; + + ielem = vctxt->elemInfos[matcher->depth]; + + if (ielem->idcTable == NULL) { + ielem->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def); + if (ielem->idcTable == NULL) + return (NULL); + return(ielem->idcTable); + } else { + xmlSchemaPSVIIDCBindingPtr bind = NULL; + + bind = ielem->idcTable; + do { + if (bind->definition == matcher->aidc->def) + return(bind); + if (bind->next == NULL) { + bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def); + if (bind->next == NULL) + return (NULL); + return(bind->next); + } + bind = bind->next; + } while (bind != NULL); + } + return (NULL); +} + +static xmlSchemaItemListPtr +xmlSchemaIDCAcquireTargetList(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED, + xmlSchemaIDCMatcherPtr matcher) +{ + if (matcher->targets == NULL) + matcher->targets = xmlSchemaItemListCreate(); + return(matcher->targets); +} + +/** + * xmlSchemaIDCFreeKey: + * @key: the IDC key + * + * Frees an IDC key together with its compiled value. + */ +static void +xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key) +{ + if (key->val != NULL) + xmlSchemaFreeValue(key->val); + xmlFree(key); +} + +/** + * xmlSchemaIDCFreeBinding: + * + * Frees an IDC binding. Note that the node table-items + * are not freed. + */ +static void +xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind) +{ + if (bind->nodeTable != NULL) + xmlFree(bind->nodeTable); + if (bind->dupls != NULL) + xmlSchemaItemListFree(bind->dupls); + xmlFree(bind); +} + +/** + * xmlSchemaIDCFreeIDCTable: + * @bind: the first IDC binding in the list + * + * Frees an IDC table, i.e. all the IDC bindings in the list. + */ +static void +xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind) +{ + xmlSchemaPSVIIDCBindingPtr prev; + + while (bind != NULL) { + prev = bind; + bind = bind->next; + xmlSchemaIDCFreeBinding(prev); + } +} + +/** + * xmlSchemaIDCFreeMatcherList: + * @matcher: the first IDC matcher in the list + * + * Frees a list of IDC matchers. + */ +static void +xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher) +{ + xmlSchemaIDCMatcherPtr next; + + while (matcher != NULL) { + next = matcher->next; + if (matcher->keySeqs != NULL) { + int i; + for (i = 0; i < matcher->sizeKeySeqs; i++) + if (matcher->keySeqs[i] != NULL) + xmlFree(matcher->keySeqs[i]); + xmlFree(matcher->keySeqs); + } + if (matcher->targets != NULL) { + if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) { + int i; + xmlSchemaPSVIIDCNodePtr idcNode; + /* + * Node-table items for keyrefs are not stored globally + * to the validation context, since they are not bubbled. + * We need to free them here. + */ + for (i = 0; i < matcher->targets->nbItems; i++) { + idcNode = + (xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i]; + xmlFree(idcNode->keys); + xmlFree(idcNode); + } + } + xmlSchemaItemListFree(matcher->targets); + } + xmlFree(matcher); + matcher = next; + } +} + +/** + * xmlSchemaIDCReleaseMatcherList: + * @vctxt: the WXS validation context + * @matcher: the first IDC matcher in the list + * + * Caches a list of IDC matchers for reuse. + */ +static void +xmlSchemaIDCReleaseMatcherList(xmlSchemaValidCtxtPtr vctxt, + xmlSchemaIDCMatcherPtr matcher) +{ + xmlSchemaIDCMatcherPtr next; + + while (matcher != NULL) { + next = matcher->next; + if (matcher->keySeqs != NULL) { + int i; + /* + * Don't free the array, but only the content. + */ + for (i = 0; i < matcher->sizeKeySeqs; i++) + if (matcher->keySeqs[i] != NULL) { + xmlFree(matcher->keySeqs[i]); + matcher->keySeqs[i] = NULL; + } + } + if (matcher->targets) { + if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) { + int i; + xmlSchemaPSVIIDCNodePtr idcNode; + /* + * Node-table items for keyrefs are not stored globally + * to the validation context, since they are not bubbled. + * We need to free them here. + */ + for (i = 0; i < matcher->targets->nbItems; i++) { + idcNode = + (xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i]; + xmlFree(idcNode->keys); + xmlFree(idcNode); + } + } + xmlSchemaItemListFree(matcher->targets); + matcher->targets = NULL; + } + matcher->next = NULL; + /* + * Cache the matcher. + */ + if (vctxt->idcMatcherCache != NULL) + matcher->nextCached = vctxt->idcMatcherCache; + vctxt->idcMatcherCache = matcher; + + matcher = next; + } +} + +/** + * xmlSchemaIDCAddStateObject: + * @vctxt: the WXS validation context + * @matcher: the IDC matcher + * @sel: the XPath information + * @parent: the parent "selector" state object if any + * @type: "selector" or "field" + * + * Creates/reuses and activates state objects for the given + * XPath information; if the XPath expression consists of unions, + * multiple state objects are created for every unioned expression. + * + * Returns 0 on success and -1 on internal errors. + */ +static int +xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt, + xmlSchemaIDCMatcherPtr matcher, + xmlSchemaIDCSelectPtr sel, + int type) +{ + xmlSchemaIDCStateObjPtr sto; + + /* + * Reuse the state objects from the pool. + */ + if (vctxt->xpathStatePool != NULL) { + sto = vctxt->xpathStatePool; + vctxt->xpathStatePool = sto->next; + sto->next = NULL; + } else { + /* + * Create a new state object. + */ + sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj)); + if (sto == NULL) { + xmlSchemaVErrMemory(NULL, + "allocating an IDC state object", NULL); + return (-1); + } + memset(sto, 0, sizeof(xmlSchemaIDCStateObj)); + } + /* + * Add to global list. + */ + if (vctxt->xpathStates != NULL) + sto->next = vctxt->xpathStates; + vctxt->xpathStates = sto; + + /* + * Free the old xpath validation context. + */ + if (sto->xpathCtxt != NULL) + xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt); + + /* + * Create a new XPath (pattern) validation context. + */ + sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt( + (xmlPatternPtr) sel->xpathComp); + if (sto->xpathCtxt == NULL) { + VERROR_INT("xmlSchemaIDCAddStateObject", + "failed to create an XPath validation context"); + return (-1); + } + sto->type = type; + sto->depth = vctxt->depth; + sto->matcher = matcher; + sto->sel = sel; + sto->nbHistory = 0; + +#ifdef DEBUG_IDC + xmlGenericError(xmlGenericErrorContext, "IDC: STO push '%s'\n", + sto->sel->xpath); +#endif + return (0); +} + +/** + * xmlSchemaXPathEvaluate: + * @vctxt: the WXS validation context + * @nodeType: the nodeType of the current node + * + * Evaluates all active XPath state objects. + * + * Returns the number of IC "field" state objects which resolved to + * this node, 0 if none resolved and -1 on internal errors. + */ +static int +xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt, + xmlElementType nodeType) +{ + xmlSchemaIDCStateObjPtr sto, head = NULL, first; + int res, resolved = 0, depth = vctxt->depth; + + if (vctxt->xpathStates == NULL) + return (0); + + if (nodeType == XML_ATTRIBUTE_NODE) + depth++; +#ifdef DEBUG_IDC + { + xmlChar *str = NULL; + xmlGenericError(xmlGenericErrorContext, + "IDC: EVAL on %s, depth %d, type %d\n", + xmlSchemaFormatQName(&str, vctxt->inode->nsName, + vctxt->inode->localName), depth, nodeType); + FREE_AND_NULL(str) + } +#endif + /* + * Process all active XPath state objects. + */ + first = vctxt->xpathStates; + sto = first; + while (sto != head) { +#ifdef DEBUG_IDC + if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) + xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] selector '%s'\n", + sto->matcher->aidc->def->name, sto->sel->xpath); + else + xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] field '%s'\n", + sto->matcher->aidc->def->name, sto->sel->xpath); +#endif + if (nodeType == XML_ELEMENT_NODE) + res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt, + vctxt->inode->localName, vctxt->inode->nsName); + else + res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt, + vctxt->inode->localName, vctxt->inode->nsName); + + if (res == -1) { + VERROR_INT("xmlSchemaXPathEvaluate", + "calling xmlStreamPush()"); + return (-1); + } + if (res == 0) + goto next_sto; + /* + * Full match. + */ +#ifdef DEBUG_IDC + xmlGenericError(xmlGenericErrorContext, "IDC: " + "MATCH\n"); +#endif + /* + * Register a match in the state object history. + */ + if (sto->history == NULL) { + sto->history = (int *) xmlMalloc(5 * sizeof(int)); + if (sto->history == NULL) { + xmlSchemaVErrMemory(NULL, + "allocating the state object history", NULL); + return(-1); + } + sto->sizeHistory = 5; + } else if (sto->sizeHistory <= sto->nbHistory) { + sto->sizeHistory *= 2; + sto->history = (int *) xmlRealloc(sto->history, + sto->sizeHistory * sizeof(int)); + if (sto->history == NULL) { + xmlSchemaVErrMemory(NULL, + "re-allocating the state object history", NULL); + return(-1); + } + } + sto->history[sto->nbHistory++] = depth; + +#ifdef DEBUG_IDC + xmlGenericError(xmlGenericErrorContext, "IDC: push match '%d'\n", + vctxt->depth); +#endif + + if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) { + xmlSchemaIDCSelectPtr sel; + /* + * Activate state objects for the IDC fields of + * the IDC selector. + */ +#ifdef DEBUG_IDC + xmlGenericError(xmlGenericErrorContext, "IDC: " + "activating field states\n"); +#endif + sel = sto->matcher->aidc->def->fields; + while (sel != NULL) { + if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher, + sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1) + return (-1); + sel = sel->next; + } + } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) { + /* + * An IDC key node was found by the IDC field. + */ +#ifdef DEBUG_IDC + xmlGenericError(xmlGenericErrorContext, + "IDC: key found\n"); +#endif + /* + * Notify that the character value of this node is + * needed. + */ + if (resolved == 0) { + if ((vctxt->inode->flags & + XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0) + vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED; + } + resolved++; + } +next_sto: + if (sto->next == NULL) { + /* + * Evaluate field state objects created on this node as well. + */ + head = first; + sto = vctxt->xpathStates; + } else + sto = sto->next; + } + return (resolved); +} + +static const xmlChar * +xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt, + xmlChar **buf, + xmlSchemaPSVIIDCKeyPtr *seq, + int count) +{ + int i, res; + xmlChar *value = NULL; + + *buf = xmlStrdup(BAD_CAST "["); + for (i = 0; i < count; i++) { + *buf = xmlStrcat(*buf, BAD_CAST "'"); + res = xmlSchemaGetCanonValueWhtspExt(seq[i]->val, + xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type), + &value); + if (res == 0) + *buf = xmlStrcat(*buf, BAD_CAST value); + else { + VERROR_INT("xmlSchemaFormatIDCKeySequence", + "failed to compute a canonical value"); + *buf = xmlStrcat(*buf, BAD_CAST "???"); + } + if (i < count -1) + *buf = xmlStrcat(*buf, BAD_CAST "', "); + else + *buf = xmlStrcat(*buf, BAD_CAST "'"); + if (value != NULL) { + xmlFree(value); + value = NULL; + } + } + *buf = xmlStrcat(*buf, BAD_CAST "]"); + + return (BAD_CAST *buf); +} + +/** + * xmlSchemaXPathPop: + * @vctxt: the WXS validation context + * + * Pops all XPath states. + * + * Returns 0 on success and -1 on internal errors. + */ +static int +xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt) +{ + xmlSchemaIDCStateObjPtr sto; + int res; + + if (vctxt->xpathStates == NULL) + return(0); + sto = vctxt->xpathStates; + do { + res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt); + if (res == -1) + return (-1); + sto = sto->next; + } while (sto != NULL); + return(0); +} + +/** + * xmlSchemaXPathProcessHistory: + * @vctxt: the WXS validation context + * @type: the simple/complex type of the current node if any at all + * @val: the precompiled value + * + * Processes and pops the history items of the IDC state objects. + * IDC key-sequences are validated/created on IDC bindings. + * + * Returns 0 on success and -1 on internal errors. + */ +static int +xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt, + int depth) +{ + xmlSchemaIDCStateObjPtr sto, nextsto; + int res, matchDepth; + xmlSchemaPSVIIDCKeyPtr key = NULL; + xmlSchemaTypePtr type = vctxt->inode->typeDef, simpleType = NULL; + + if (vctxt->xpathStates == NULL) + return (0); + sto = vctxt->xpathStates; + +#ifdef DEBUG_IDC + { + xmlChar *str = NULL; + xmlGenericError(xmlGenericErrorContext, + "IDC: BACK on %s, depth %d\n", + xmlSchemaFormatQName(&str, vctxt->inode->nsName, + vctxt->inode->localName), vctxt->depth); + FREE_AND_NULL(str) + } +#endif + /* + * Evaluate the state objects. + */ + while (sto != NULL) { + res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt); + if (res == -1) { + VERROR_INT("xmlSchemaXPathProcessHistory", + "calling xmlStreamPop()"); + return (-1); + } +#ifdef DEBUG_IDC + xmlGenericError(xmlGenericErrorContext, "IDC: stream pop '%s'\n", + sto->sel->xpath); +#endif + if (sto->nbHistory == 0) + goto deregister_check; + + matchDepth = sto->history[sto->nbHistory -1]; + + /* + * Only matches at the current depth are of interest. + */ + if (matchDepth != depth) { + sto = sto->next; + continue; + } + if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) { + /* + * NOTE: According to + * http://www.w3.org/Bugs/Public/show_bug.cgi?id=2198 + * ... the simple-content of complex types is also allowed. + */ + + if (WXS_IS_COMPLEX(type)) { + if (WXS_HAS_SIMPLE_CONTENT(type)) { + /* + * Sanity check for complex types with simple content. + */ + simpleType = type->contentTypeDef; + if (simpleType == NULL) { + VERROR_INT("xmlSchemaXPathProcessHistory", + "field resolves to a CT with simple content " + "but the CT is missing the ST definition"); + return (-1); + } + } else + simpleType = NULL; + } else + simpleType = type; + if (simpleType == NULL) { + xmlChar *str = NULL; + + /* + * Not qualified if the field resolves to a node of non + * simple type. + */ + xmlSchemaCustomErr(ACTXT_CAST vctxt, + XML_SCHEMAV_CVC_IDC, NULL, + WXS_BASIC_CAST sto->matcher->aidc->def, + "The XPath '%s' of a field of %s does evaluate to a node of " + "non-simple type", + sto->sel->xpath, + xmlSchemaGetIDCDesignation(&str, sto->matcher->aidc->def)); + FREE_AND_NULL(str); + sto->nbHistory--; + goto deregister_check; + } + + if ((key == NULL) && (vctxt->inode->val == NULL)) { + /* + * Failed to provide the normalized value; maybe + * the value was invalid. + */ + VERROR(XML_SCHEMAV_CVC_IDC, + WXS_BASIC_CAST sto->matcher->aidc->def, + "Warning: No precomputed value available, the value " + "was either invalid or something strange happend"); + sto->nbHistory--; + goto deregister_check; + } else { + xmlSchemaIDCMatcherPtr matcher = sto->matcher; + xmlSchemaPSVIIDCKeyPtr *keySeq; + int pos, idx; + + /* + * The key will be anchored on the matcher's list of + * key-sequences. The position in this list is determined + * by the target node's depth relative to the matcher's + * depth of creation (i.e. the depth of the scope element). + * + * Element Depth Pos List-entries + * 0 NULL + * 1 NULL + * 2 2 target + * + * + * + * The size of the list is only dependant on the depth of + * the tree. + * An entry will be NULLed in selector_leave, i.e. when + * we hit the target's + */ + pos = sto->depth - matcher->depth; + idx = sto->sel->index; + + /* + * Create/grow the array of key-sequences. + */ + if (matcher->keySeqs == NULL) { + if (pos > 9) + matcher->sizeKeySeqs = pos * 2; + else + matcher->sizeKeySeqs = 10; + matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **) + xmlMalloc(matcher->sizeKeySeqs * + sizeof(xmlSchemaPSVIIDCKeyPtr *)); + if (matcher->keySeqs == NULL) { + xmlSchemaVErrMemory(NULL, + "allocating an array of key-sequences", + NULL); + return(-1); + } + memset(matcher->keySeqs, 0, + matcher->sizeKeySeqs * + sizeof(xmlSchemaPSVIIDCKeyPtr *)); + } else if (pos >= matcher->sizeKeySeqs) { + int i = matcher->sizeKeySeqs; + + matcher->sizeKeySeqs *= 2; + matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **) + xmlRealloc(matcher->keySeqs, + matcher->sizeKeySeqs * + sizeof(xmlSchemaPSVIIDCKeyPtr *)); + if (matcher->keySeqs == NULL) { + xmlSchemaVErrMemory(NULL, + "reallocating an array of key-sequences", + NULL); + return (-1); + } + /* + * The array needs to be NULLed. + * TODO: Use memset? + */ + for (; i < matcher->sizeKeySeqs; i++) + matcher->keySeqs[i] = NULL; + } + + /* + * Get/create the key-sequence. + */ + keySeq = matcher->keySeqs[pos]; + if (keySeq == NULL) { + goto create_sequence; + } else if (keySeq[idx] != NULL) { + xmlChar *str = NULL; + /* + * cvc-identity-constraint: + * 3 For each node in the ·target node set· all + * of the {fields}, with that node as the context + * node, evaluate to either an empty node-set or + * a node-set with exactly one member, which must + * have a simple type. + * + * The key was already set; report an error. + */ + xmlSchemaCustomErr(ACTXT_CAST vctxt, + XML_SCHEMAV_CVC_IDC, NULL, + WXS_BASIC_CAST matcher->aidc->def, + "The XPath '%s' of a field of %s evaluates to a " + "node-set with more than one member", + sto->sel->xpath, + xmlSchemaGetIDCDesignation(&str, matcher->aidc->def)); + FREE_AND_NULL(str); + sto->nbHistory--; + goto deregister_check; + } else + goto create_key; + +create_sequence: + /* + * Create a key-sequence. + */ + keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc( + matcher->aidc->def->nbFields * + sizeof(xmlSchemaPSVIIDCKeyPtr)); + if (keySeq == NULL) { + xmlSchemaVErrMemory(NULL, + "allocating an IDC key-sequence", NULL); + return(-1); + } + memset(keySeq, 0, matcher->aidc->def->nbFields * + sizeof(xmlSchemaPSVIIDCKeyPtr)); + matcher->keySeqs[pos] = keySeq; +create_key: + /* + * Create a key once per node only. + */ + if (key == NULL) { + key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc( + sizeof(xmlSchemaPSVIIDCKey)); + if (key == NULL) { + xmlSchemaVErrMemory(NULL, + "allocating a IDC key", NULL); + xmlFree(keySeq); + matcher->keySeqs[pos] = NULL; + return(-1); + } + /* + * Consume the compiled value. + */ + key->type = simpleType; + key->val = vctxt->inode->val; + vctxt->inode->val = NULL; + /* + * Store the key in a global list. + */ + if (xmlSchemaIDCStoreKey(vctxt, key) == -1) { + xmlSchemaIDCFreeKey(key); + return (-1); + } + } + keySeq[idx] = key; + } + } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) { + + xmlSchemaPSVIIDCKeyPtr **keySeq = NULL; + /* xmlSchemaPSVIIDCBindingPtr bind; */ + xmlSchemaPSVIIDCNodePtr ntItem; + xmlSchemaIDCMatcherPtr matcher; + xmlSchemaIDCPtr idc; + xmlSchemaItemListPtr targets; + int pos, i, j, nbKeys; + /* + * Here we have the following scenario: + * An IDC 'selector' state object resolved to a target node, + * during the time this target node was in the + * ancestor-or-self axis, the 'field' state object(s) looked + * out for matching nodes to create a key-sequence for this + * target node. Now we are back to this target node and need + * to put the key-sequence, together with the target node + * itself, into the node-table of the corresponding IDC + * binding. + */ + matcher = sto->matcher; + idc = matcher->aidc->def; + nbKeys = idc->nbFields; + pos = depth - matcher->depth; + /* + * Check if the matcher has any key-sequences at all, plus + * if it has a key-sequence for the current target node. + */ + if ((matcher->keySeqs == NULL) || + (matcher->sizeKeySeqs <= pos)) { + if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) + goto selector_key_error; + else + goto selector_leave; + } + + keySeq = &(matcher->keySeqs[pos]); + if (*keySeq == NULL) { + if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) + goto selector_key_error; + else + goto selector_leave; + } + + for (i = 0; i < nbKeys; i++) { + if ((*keySeq)[i] == NULL) { + /* + * Not qualified, if not all fields did resolve. + */ + if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) { + /* + * All fields of a "key" IDC must resolve. + */ + goto selector_key_error; + } + goto selector_leave; + } + } + /* + * All fields did resolve. + */ + + /* + * 4.1 If the {identity-constraint category} is unique(/key), + * then no two members of the ·qualified node set· have + * ·key-sequences· whose members are pairwise equal, as + * defined by Equal in [XML Schemas: Datatypes]. + * + * Get the IDC binding from the matcher and check for + * duplicate key-sequences. + */ +#if 0 + bind = xmlSchemaIDCAcquireBinding(vctxt, matcher); +#endif + targets = xmlSchemaIDCAcquireTargetList(vctxt, matcher); + if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) && + (targets->nbItems != 0)) { + xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq; + + i = 0; + res = 0; + /* + * Compare the key-sequences, key by key. + */ + do { + bkeySeq = + ((xmlSchemaPSVIIDCNodePtr) targets->items[i])->keys; + for (j = 0; j < nbKeys; j++) { + ckey = (*keySeq)[j]; + bkey = bkeySeq[j]; + res = xmlSchemaAreValuesEqual(ckey->val, bkey->val); + if (res == -1) { + return (-1); + } else if (res == 0) { + /* + * One of the keys differs, so the key-sequence + * won't be equal; get out. + */ + break; + } + } + if (res == 1) { + /* + * Duplicate key-sequence found. + */ + break; + } + i++; + } while (i < targets->nbItems); + if (i != targets->nbItems) { + xmlChar *str = NULL, *strB = NULL; + /* + * TODO: Try to report the key-sequence. + */ + xmlSchemaCustomErr(ACTXT_CAST vctxt, + XML_SCHEMAV_CVC_IDC, NULL, + WXS_BASIC_CAST idc, + "Duplicate key-sequence %s in %s", + xmlSchemaFormatIDCKeySequence(vctxt, &str, + (*keySeq), nbKeys), + xmlSchemaGetIDCDesignation(&strB, idc)); + FREE_AND_NULL(str); + FREE_AND_NULL(strB); + goto selector_leave; + } + } + /* + * Add a node-table item to the IDC binding. + */ + ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc( + sizeof(xmlSchemaPSVIIDCNode)); + if (ntItem == NULL) { + xmlSchemaVErrMemory(NULL, + "allocating an IDC node-table item", NULL); + xmlFree(*keySeq); + *keySeq = NULL; + return(-1); + } + memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode)); + + /* + * Store the node-table item in a global list. + */ + if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) { + if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) { + xmlFree(ntItem); + xmlFree(*keySeq); + *keySeq = NULL; + return (-1); + } + ntItem->nodeQNameID = -1; + } else { + /* + * Save a cached QName for this node on the IDC node, to be + * able to report it, even if the node is not saved. + */ + ntItem->nodeQNameID = xmlSchemaVAddNodeQName(vctxt, + vctxt->inode->localName, vctxt->inode->nsName); + if (ntItem->nodeQNameID == -1) { + xmlFree(ntItem); + xmlFree(*keySeq); + *keySeq = NULL; + return (-1); + } + } + /* + * Init the node-table item: Save the node, position and + * consume the key-sequence. + */ + ntItem->node = vctxt->node; + ntItem->nodeLine = vctxt->inode->nodeLine; + ntItem->keys = *keySeq; + *keySeq = NULL; +#if 0 + if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1) { +#endif + if (xmlSchemaItemListAdd(targets, ntItem) == -1) { + if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) { + /* + * Free the item, since keyref items won't be + * put on a global list. + */ + xmlFree(ntItem->keys); + xmlFree(ntItem); + } + return (-1); + } + + goto selector_leave; +selector_key_error: + { + xmlChar *str = NULL; + /* + * 4.2.1 (KEY) The ·target node set· and the + * ·qualified node set· are equal, that is, every + * member of the ·target node set· is also a member + * of the ·qualified node set· and vice versa. + */ + xmlSchemaCustomErr(ACTXT_CAST vctxt, + XML_SCHEMAV_CVC_IDC, NULL, + WXS_BASIC_CAST idc, + "Not all fields of %s evaluate to a node", + xmlSchemaGetIDCDesignation(&str, idc), NULL); + FREE_AND_NULL(str); + } +selector_leave: + /* + * Free the key-sequence if not added to the IDC table. + */ + if ((keySeq != NULL) && (*keySeq != NULL)) { + xmlFree(*keySeq); + *keySeq = NULL; + } + } /* if selector */ + + sto->nbHistory--; + +deregister_check: + /* + * Deregister state objects if they reach the depth of creation. + */ + if ((sto->nbHistory == 0) && (sto->depth == depth)) { +#ifdef DEBUG_IDC + xmlGenericError(xmlGenericErrorContext, "IDC: STO pop '%s'\n", + sto->sel->xpath); +#endif + if (vctxt->xpathStates != sto) { + VERROR_INT("xmlSchemaXPathProcessHistory", + "The state object to be removed is not the first " + "in the list"); + } + nextsto = sto->next; + /* + * Unlink from the list of active XPath state objects. + */ + vctxt->xpathStates = sto->next; + sto->next = vctxt->xpathStatePool; + /* + * Link it to the pool of reusable state objects. + */ + vctxt->xpathStatePool = sto; + sto = nextsto; + } else + sto = sto->next; + } /* while (sto != NULL) */ + return (0); +} + +/** + * xmlSchemaIDCRegisterMatchers: + * @vctxt: the WXS validation context + * @elemDecl: the element declaration + * + * Creates helper objects to evaluate IDC selectors/fields + * successively. + * + * Returns 0 if OK and -1 on internal errors. + */ +static int +xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt, + xmlSchemaElementPtr elemDecl) +{ + xmlSchemaIDCMatcherPtr matcher, last = NULL; + xmlSchemaIDCPtr idc, refIdc; + xmlSchemaIDCAugPtr aidc; + + idc = (xmlSchemaIDCPtr) elemDecl->idcs; + if (idc == NULL) + return (0); + +#ifdef DEBUG_IDC + { + xmlChar *str = NULL; + xmlGenericError(xmlGenericErrorContext, + "IDC: REGISTER on %s, depth %d\n", + (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName, + vctxt->inode->localName), vctxt->depth); + FREE_AND_NULL(str) + } +#endif + if (vctxt->inode->idcMatchers != NULL) { + VERROR_INT("xmlSchemaIDCRegisterMatchers", + "The chain of IDC matchers is expected to be empty"); + return (-1); + } + do { + if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) { + /* + * Since IDCs bubbles are expensive we need to know the + * depth at which the bubbles should stop; this will be + * the depth of the top-most keyref IDC. If no keyref + * references a key/unique IDC, the keyrefDepth will + * be -1, indicating that no bubbles are needed. + */ + refIdc = (xmlSchemaIDCPtr) idc->ref->item; + if (refIdc != NULL) { + /* + * Remember that we have keyrefs on this node. + */ + vctxt->inode->hasKeyrefs = 1; + /* + * Lookup the referenced augmented IDC info. + */ + aidc = vctxt->aidcs; + while (aidc != NULL) { + if (aidc->def == refIdc) + break; + aidc = aidc->next; + } + if (aidc == NULL) { + VERROR_INT("xmlSchemaIDCRegisterMatchers", + "Could not find an augmented IDC item for an IDC " + "definition"); + return (-1); + } + if ((aidc->keyrefDepth == -1) || + (vctxt->depth < aidc->keyrefDepth)) + aidc->keyrefDepth = vctxt->depth; + } + } + /* + * Lookup the augmented IDC item for the IDC definition. + */ + aidc = vctxt->aidcs; + while (aidc != NULL) { + if (aidc->def == idc) + break; + aidc = aidc->next; + } + if (aidc == NULL) { + VERROR_INT("xmlSchemaIDCRegisterMatchers", + "Could not find an augmented IDC item for an IDC definition"); + return (-1); + } + /* + * Create an IDC matcher for every IDC definition. + */ + if (vctxt->idcMatcherCache != NULL) { + /* + * Reuse a cached matcher. + */ + matcher = vctxt->idcMatcherCache; + vctxt->idcMatcherCache = matcher->nextCached; + matcher->nextCached = NULL; + } else { + matcher = (xmlSchemaIDCMatcherPtr) + xmlMalloc(sizeof(xmlSchemaIDCMatcher)); + if (matcher == NULL) { + xmlSchemaVErrMemory(vctxt, + "allocating an IDC matcher", NULL); + return (-1); + } + memset(matcher, 0, sizeof(xmlSchemaIDCMatcher)); + } + if (last == NULL) + vctxt->inode->idcMatchers = matcher; + else + last->next = matcher; + last = matcher; + + matcher->type = IDC_MATCHER; + matcher->depth = vctxt->depth; + matcher->aidc = aidc; + matcher->idcType = aidc->def->type; +#ifdef DEBUG_IDC + xmlGenericError(xmlGenericErrorContext, "IDC: register matcher\n"); +#endif + /* + * Init the automaton state object. + */ + if (xmlSchemaIDCAddStateObject(vctxt, matcher, + idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1) + return (-1); + + idc = idc->next; + } while (idc != NULL); + return (0); +} + +static int +xmlSchemaIDCFillNodeTables(xmlSchemaValidCtxtPtr vctxt, + xmlSchemaNodeInfoPtr ielem) +{ + xmlSchemaPSVIIDCBindingPtr bind; + int res, i, j, k, nbTargets, nbFields, nbDupls, nbNodeTable; + xmlSchemaPSVIIDCKeyPtr *keys, *ntkeys; + xmlSchemaPSVIIDCNodePtr *targets, *dupls; + + xmlSchemaIDCMatcherPtr matcher = ielem->idcMatchers; + /* vctxt->createIDCNodeTables */ + while (matcher != NULL) { + /* + * Skip keyref IDCs and empty IDC target-lists. + */ + if ((matcher->aidc->def->type == XML_SCHEMA_TYPE_IDC_KEYREF) || + WXS_ILIST_IS_EMPTY(matcher->targets)) + { + matcher = matcher->next; + continue; + } + /* + * If we _want_ the IDC node-table to be created in any case + * then do so. Otherwise create them only if keyrefs need them. + */ + if ((! vctxt->createIDCNodeTables) && + ((matcher->aidc->keyrefDepth == -1) || + (matcher->aidc->keyrefDepth > vctxt->depth))) + { + matcher = matcher->next; + continue; + } + /* + * Get/create the IDC binding on this element for the IDC definition. + */ + bind = xmlSchemaIDCAcquireBinding(vctxt, matcher); + + if (! WXS_ILIST_IS_EMPTY(bind->dupls)) { + dupls = (xmlSchemaPSVIIDCNodePtr *) bind->dupls->items; + nbDupls = bind->dupls->nbItems; + } else { + dupls = NULL; + nbDupls = 0; + } + if (bind->nodeTable != NULL) { + nbNodeTable = bind->nbNodes; + } else { + nbNodeTable = 0; + } + + if ((nbNodeTable == 0) && (nbDupls == 0)) { + /* + * Transfer all IDC target-nodes to the IDC node-table. + */ + bind->nodeTable = + (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items; + bind->sizeNodes = matcher->targets->sizeItems; + bind->nbNodes = matcher->targets->nbItems; + + matcher->targets->items = NULL; + matcher->targets->sizeItems = 0; + matcher->targets->nbItems = 0; + } else { + /* + * Compare the key-sequences and add to the IDC node-table. + */ + nbTargets = matcher->targets->nbItems; + targets = (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items; + nbFields = matcher->aidc->def->nbFields; + i = 0; + do { + keys = targets[i]->keys; + if (nbDupls) { + /* + * Search in already found duplicates first. + */ + j = 0; + do { + if (nbFields == 1) { + res = xmlSchemaAreValuesEqual(keys[0]->val, + dupls[j]->keys[0]->val); + if (res == -1) + goto internal_error; + if (res == 1) { + /* + * Equal key-sequence. + */ + goto next_target; + } + } else { + res = 0; + ntkeys = dupls[j]->keys; + for (k = 0; k < nbFields; k++) { + res = xmlSchemaAreValuesEqual(keys[k]->val, + ntkeys[k]->val); + if (res == -1) + goto internal_error; + if (res == 0) { + /* + * One of the keys differs. + */ + break; + } + } + if (res == 1) { + /* + * Equal key-sequence found. + */ + goto next_target; + } + } + j++; + } while (j < nbDupls); + } + if (nbNodeTable) { + j = 0; + do { + if (nbFields == 1) { + res = xmlSchemaAreValuesEqual(keys[0]->val, + bind->nodeTable[j]->keys[0]->val); + if (res == -1) + goto internal_error; + if (res == 0) { + /* + * The key-sequence differs. + */ + goto next_node_table_entry; + } + } else { + res = 0; + ntkeys = bind->nodeTable[j]->keys; + for (k = 0; k < nbFields; k++) { + res = xmlSchemaAreValuesEqual(keys[k]->val, + ntkeys[k]->val); + if (res == -1) + goto internal_error; + if (res == 0) { + /* + * One of the keys differs. + */ + goto next_node_table_entry; + } + } + } + /* + * Add the duplicate to the list of duplicates. + */ + if (bind->dupls == NULL) { + bind->dupls = xmlSchemaItemListCreate(); + if (bind->dupls == NULL) + goto internal_error; + } + if (xmlSchemaItemListAdd(bind->dupls, bind->nodeTable[j]) == -1) + goto internal_error; + /* + * Remove the duplicate entry from the IDC node-table. + */ + bind->nodeTable[j] = bind->nodeTable[bind->nbNodes -1]; + bind->nbNodes--; + + goto next_target; + +next_node_table_entry: + j++; + } while (j < nbNodeTable); + } + /* + * If everything is fine, then add the IDC target-node to + * the IDC node-table. + */ + if (xmlSchemaIDCAppendNodeTableItem(bind, targets[i]) == -1) + goto internal_error; + +next_target: + i++; + } while (i < nbTargets); + } + matcher = matcher->next; + } + return(0); + +internal_error: + return(-1); +} + +/** + * xmlSchemaBubbleIDCNodeTables: + * @depth: the current tree depth + * + * Merges IDC bindings of an element at @depth into the corresponding IDC + * bindings of its parent element. If a duplicate note-table entry is found, + * both, the parent node-table entry and child entry are discarded from the + * node-table of the parent. + * + * Returns 0 if OK and -1 on internal errors. + */ +static int +xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt) +{ + xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */ + xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL; /* parent IDC bindings. */ + xmlSchemaPSVIIDCNodePtr node, parNode = NULL, *dupls, *parNodes; /* node-table entries. */ + xmlSchemaIDCAugPtr aidc; + int i, j, k, ret = 0, nbFields, oldNum, oldDupls; + + bind = vctxt->inode->idcTable; + if (bind == NULL) { + /* Fine, no table, no bubbles. */ + return (0); + } + + parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable); + /* + * Walk all bindings; create new or add to existing bindings. + * Remove duplicate key-sequences. + */ + while (bind != NULL) { + + if ((bind->nbNodes == 0) && WXS_ILIST_IS_EMPTY(bind->dupls)) + goto next_binding; + /* + * Check if the key/unique IDC table needs to be bubbled. + */ + if (! vctxt->createIDCNodeTables) { + aidc = vctxt->aidcs; + do { + if (aidc->def == bind->definition) { + if ((aidc->keyrefDepth == -1) || + (aidc->keyrefDepth >= vctxt->depth)) { + goto next_binding; + } + break; + } + aidc = aidc->next; + } while (aidc != NULL); + } + + if (parTable != NULL) + parBind = *parTable; + /* + * Search a matching parent binding for the + * IDC definition. + */ + while (parBind != NULL) { + if (parBind->definition == bind->definition) + break; + parBind = parBind->next; + } + + if (parBind != NULL) { + /* + * Compare every node-table entry of the child node, + * i.e. the key-sequence within, ... + */ + oldNum = parBind->nbNodes; /* Skip newly added items. */ + + if (! WXS_ILIST_IS_EMPTY(parBind->dupls)) { + oldDupls = parBind->dupls->nbItems; + dupls = (xmlSchemaPSVIIDCNodePtr *) parBind->dupls->items; + } else { + dupls = NULL; + oldDupls = 0; + } + + parNodes = parBind->nodeTable; + nbFields = bind->definition->nbFields; + + for (i = 0; i < bind->nbNodes; i++) { + node = bind->nodeTable[i]; + if (node == NULL) + continue; + /* + * ...with every key-sequence of the parent node, already + * evaluated to be a duplicate key-sequence. + */ + if (oldDupls) { + j = 0; + while (j < oldDupls) { + if (nbFields == 1) { + ret = xmlSchemaAreValuesEqual( + node->keys[0]->val, + dupls[j]->keys[0]->val); + if (ret == -1) + goto internal_error; + if (ret == 0) { + j++; + continue; + } + } else { + parNode = dupls[j]; + for (k = 0; k < nbFields; k++) { + ret = xmlSchemaAreValuesEqual( + node->keys[k]->val, + parNode->keys[k]->val); + if (ret == -1) + goto internal_error; + if (ret == 0) + break; + } + } + if (ret == 1) + /* Duplicate found. */ + break; + j++; + } + if (j != oldDupls) { + /* Duplicate found. Skip this entry. */ + continue; + } + } + /* + * ... and with every key-sequence of the parent node. + */ + if (oldNum) { + j = 0; + while (j < oldNum) { + parNode = parNodes[j]; + if (nbFields == 1) { + ret = xmlSchemaAreValuesEqual( + node->keys[0]->val, + parNode->keys[0]->val); + if (ret == -1) + goto internal_error; + if (ret == 0) { + j++; + continue; + } + } else { + for (k = 0; k < nbFields; k++) { + ret = xmlSchemaAreValuesEqual( + node->keys[k]->val, + parNode->keys[k]->val); + if (ret == -1) + goto internal_error; + if (ret == 0) + break; + } + } + if (ret == 1) + /* Duplicate found. */ + break; + j++; + } + if (j != oldNum) { + /* + * Handle duplicates. Move the duplicate in + * the parent's node-table to the list of + * duplicates. + */ + oldNum--; + parBind->nbNodes--; + /* + * Move last old item to pos of duplicate. + */ + parNodes[j] = parNodes[oldNum]; + + if (parBind->nbNodes != oldNum) { + /* + * If new items exist, move last new item to + * last of old items. + */ + parNodes[oldNum] = + parNodes[parBind->nbNodes]; + } + if (parBind->dupls == NULL) { + parBind->dupls = xmlSchemaItemListCreate(); + if (parBind->dupls == NULL) + goto internal_error; + } + xmlSchemaItemListAdd(parBind->dupls, parNode); + } else { + /* + * Add the node-table entry (node and key-sequence) of + * the child node to the node table of the parent node. + */ + if (parBind->nodeTable == NULL) { + parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *) + xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr)); + if (parBind->nodeTable == NULL) { + xmlSchemaVErrMemory(NULL, + "allocating IDC list of node-table items", NULL); + goto internal_error; + } + parBind->sizeNodes = 1; + } else if (parBind->nbNodes >= parBind->sizeNodes) { + parBind->sizeNodes *= 2; + parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *) + xmlRealloc(parBind->nodeTable, parBind->sizeNodes * + sizeof(xmlSchemaPSVIIDCNodePtr)); + if (parBind->nodeTable == NULL) { + xmlSchemaVErrMemory(NULL, + "re-allocating IDC list of node-table items", NULL); + goto internal_error; + } + } + parNodes = parBind->nodeTable; + /* + * Append the new node-table entry to the 'new node-table + * entries' section. + */ + parNodes[parBind->nbNodes++] = node; + } + + } + + } + } else { + /* + * No binding for the IDC was found: create a new one and + * copy all node-tables. + */ + parBind = xmlSchemaIDCNewBinding(bind->definition); + if (parBind == NULL) + goto internal_error; + + /* + * TODO: Hmm, how to optimize the initial number of + * allocated entries? + */ + if (bind->nbNodes != 0) { + /* + * Add all IDC node-table entries. + */ + if (! vctxt->psviExposeIDCNodeTables) { + /* + * Just move the entries. + * NOTE: this is quite save here, since + * all the keyref lookups have already been + * performed. + */ + parBind->nodeTable = bind->nodeTable; + bind->nodeTable = NULL; + parBind->sizeNodes = bind->sizeNodes; + bind->sizeNodes = 0; + parBind->nbNodes = bind->nbNodes; + bind->nbNodes = 0; + } else { + /* + * Copy the entries. + */ + parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *) + xmlMalloc(bind->nbNodes * + sizeof(xmlSchemaPSVIIDCNodePtr)); + if (parBind->nodeTable == NULL) { + xmlSchemaVErrMemory(NULL, + "allocating an array of IDC node-table " + "items", NULL); + xmlSchemaIDCFreeBinding(parBind); + goto internal_error; + } + parBind->sizeNodes = bind->nbNodes; + parBind->nbNodes = bind->nbNodes; + memcpy(parBind->nodeTable, bind->nodeTable, + bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr)); + } + } + if (bind->dupls) { + /* + * Move the duplicates. + */ + if (parBind->dupls != NULL) + xmlSchemaItemListFree(parBind->dupls); + parBind->dupls = bind->dupls; + bind->dupls = NULL; + } + if (*parTable == NULL) + *parTable = parBind; + else { + parBind->next = *parTable; + *parTable = parBind; + } + } + +next_binding: + bind = bind->next; + } + return (0); + +internal_error: + return(-1); +} + +/** + * xmlSchemaCheckCVCIDCKeyRef: + * @vctxt: the WXS validation context + * @elemDecl: the element declaration + * + * Check the cvc-idc-keyref constraints. + */ +static int +xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt) +{ + xmlSchemaIDCMatcherPtr matcher; + xmlSchemaPSVIIDCBindingPtr bind; + + matcher = vctxt->inode->idcMatchers; + /* + * Find a keyref. + */ + while (matcher != NULL) { + if ((matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) && + matcher->targets && + matcher->targets->nbItems) + { + int i, j, k, res, nbFields, hasDupls; + xmlSchemaPSVIIDCKeyPtr *refKeys, *keys; + xmlSchemaPSVIIDCNodePtr refNode = NULL; + + nbFields = matcher->aidc->def->nbFields; + + /* + * Find the IDC node-table for the referenced IDC key/unique. + */ + bind = vctxt->inode->idcTable; + while (bind != NULL) { + if ((xmlSchemaIDCPtr) matcher->aidc->def->ref->item == + bind->definition) + break; + bind = bind->next; + } + hasDupls = (bind && bind->dupls && bind->dupls->nbItems) ? 1 : 0; + /* + * Search for a matching key-sequences. + */ + for (i = 0; i < matcher->targets->nbItems; i++) { + res = 0; + refNode = matcher->targets->items[i]; + if (bind != NULL) { + refKeys = refNode->keys; + for (j = 0; j < bind->nbNodes; j++) { + keys = bind->nodeTable[j]->keys; + for (k = 0; k < nbFields; k++) { + res = xmlSchemaAreValuesEqual(keys[k]->val, + refKeys[k]->val); + if (res == 0) + break; + else if (res == -1) { + return (-1); + } + } + if (res == 1) { + /* + * Match found. + */ + break; + } + } + if ((res == 0) && hasDupls) { + /* + * Search in duplicates + */ + for (j = 0; j < bind->dupls->nbItems; j++) { + keys = ((xmlSchemaPSVIIDCNodePtr) + bind->dupls->items[j])->keys; + for (k = 0; k < nbFields; k++) { + res = xmlSchemaAreValuesEqual(keys[k]->val, + refKeys[k]->val); + if (res == 0) + break; + else if (res == -1) { + return (-1); + } + } + if (res == 1) { + /* + * Match in duplicates found. + */ + xmlChar *str = NULL, *strB = NULL; + xmlSchemaKeyrefErr(vctxt, + XML_SCHEMAV_CVC_IDC, refNode, + (xmlSchemaTypePtr) matcher->aidc->def, + "More than one match found for " + "key-sequence %s of keyref '%s'", + xmlSchemaFormatIDCKeySequence(vctxt, &str, + refNode->keys, nbFields), + xmlSchemaGetComponentQName(&strB, + matcher->aidc->def)); + FREE_AND_NULL(str); + FREE_AND_NULL(strB); + break; + } + } + } + } + + if (res == 0) { + xmlChar *str = NULL, *strB = NULL; + xmlSchemaKeyrefErr(vctxt, + XML_SCHEMAV_CVC_IDC, refNode, + (xmlSchemaTypePtr) matcher->aidc->def, + "No match found for key-sequence %s of keyref '%s'", + xmlSchemaFormatIDCKeySequence(vctxt, &str, + refNode->keys, nbFields), + xmlSchemaGetComponentQName(&strB, matcher->aidc->def)); + FREE_AND_NULL(str); + FREE_AND_NULL(strB); + } + } + } + matcher = matcher->next; + } + /* TODO: Return an error if any error encountered. */ + return (0); +} + +/************************************************************************ + * * + * XML Reader validation code * + * * + ************************************************************************/ + +static xmlSchemaAttrInfoPtr +xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt) +{ + xmlSchemaAttrInfoPtr iattr; + /* + * Grow/create list of attribute infos. + */ + if (vctxt->attrInfos == NULL) { + vctxt->attrInfos = (xmlSchemaAttrInfoPtr *) + xmlMalloc(sizeof(xmlSchemaAttrInfoPtr)); + vctxt->sizeAttrInfos = 1; + if (vctxt->attrInfos == NULL) { + xmlSchemaVErrMemory(vctxt, + "allocating attribute info list", NULL); + return (NULL); + } + } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) { + vctxt->sizeAttrInfos++; + vctxt->attrInfos = (xmlSchemaAttrInfoPtr *) + xmlRealloc(vctxt->attrInfos, + vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr)); + if (vctxt->attrInfos == NULL) { + xmlSchemaVErrMemory(vctxt, + "re-allocating attribute info list", NULL); + return (NULL); + } + } else { + iattr = vctxt->attrInfos[vctxt->nbAttrInfos++]; + if (iattr->localName != NULL) { + VERROR_INT("xmlSchemaGetFreshAttrInfo", + "attr info not cleared"); + return (NULL); + } + iattr->nodeType = XML_ATTRIBUTE_NODE; + return (iattr); + } + /* + * Create an attribute info. + */ + iattr = (xmlSchemaAttrInfoPtr) + xmlMalloc(sizeof(xmlSchemaAttrInfo)); + if (iattr == NULL) { + xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL); + return (NULL); + } + memset(iattr, 0, sizeof(xmlSchemaAttrInfo)); + iattr->nodeType = XML_ATTRIBUTE_NODE; + vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr; + + return (iattr); +} + +static int +xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt, + xmlNodePtr attrNode, + int nodeLine, + const xmlChar *localName, + const xmlChar *nsName, + int ownedNames, + xmlChar *value, + int ownedValue) +{ + xmlSchemaAttrInfoPtr attr; + + attr = xmlSchemaGetFreshAttrInfo(vctxt); + if (attr == NULL) { + VERROR_INT("xmlSchemaPushAttribute", + "calling xmlSchemaGetFreshAttrInfo()"); + return (-1); + } + attr->node = attrNode; + attr->nodeLine = nodeLine; + attr->state = XML_SCHEMAS_ATTR_UNKNOWN; + attr->localName = localName; + attr->nsName = nsName; + if (ownedNames) + attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES; + /* + * Evaluate if it's an XSI attribute. + */ + if (nsName != NULL) { + if (xmlStrEqual(localName, BAD_CAST "nil")) { + if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) { + attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL; + } + } else if (xmlStrEqual(localName, BAD_CAST "type")) { + if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) { + attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE; + } + } else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) { + if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) { + attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC; + } + } else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) { + if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) { + attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC; + } + } else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) { + attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS; + } + } + attr->value = value; + if (ownedValue) + attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES; + if (attr->metaType != 0) + attr->state = XML_SCHEMAS_ATTR_META; + return (0); +} + +/** + * xmlSchemaClearElemInfo: + * @vctxt: the WXS validation context + * @ielem: the element information item + */ +static void +xmlSchemaClearElemInfo(xmlSchemaValidCtxtPtr vctxt, + xmlSchemaNodeInfoPtr ielem) +{ + ielem->hasKeyrefs = 0; + ielem->appliedXPath = 0; + if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) { + FREE_AND_NULL(ielem->localName); + FREE_AND_NULL(ielem->nsName); + } else { + ielem->localName = NULL; + ielem->nsName = NULL; + } + if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) { + FREE_AND_NULL(ielem->value); + } else { + ielem->value = NULL; + } + if (ielem->val != NULL) { + /* + * PSVI TODO: Be careful not to free it when the value is + * exposed via PSVI. + */ + xmlSchemaFreeValue(ielem->val); + ielem->val = NULL; + } + if (ielem->idcMatchers != NULL) { + /* + * REVISIT OPTIMIZE TODO: Use a pool of IDC matchers. + * Does it work? + */ + xmlSchemaIDCReleaseMatcherList(vctxt, ielem->idcMatchers); +#if 0 + xmlSchemaIDCFreeMatcherList(ielem->idcMatchers); +#endif + ielem->idcMatchers = NULL; + } + if (ielem->idcTable != NULL) { + /* + * OPTIMIZE TODO: Use a pool of IDC tables??. + */ + xmlSchemaIDCFreeIDCTable(ielem->idcTable); + ielem->idcTable = NULL; + } + if (ielem->regexCtxt != NULL) { + xmlRegFreeExecCtxt(ielem->regexCtxt); + ielem->regexCtxt = NULL; + } + if (ielem->nsBindings != NULL) { + xmlFree((xmlChar **)ielem->nsBindings); + ielem->nsBindings = NULL; + ielem->nbNsBindings = 0; + ielem->sizeNsBindings = 0; + } +} + +/** + * xmlSchemaGetFreshElemInfo: + * @vctxt: the schema validation context + * + * Creates/reuses and initializes the element info item for + * the currect tree depth. + * + * Returns the element info item or NULL on API or internal errors. + */ +static xmlSchemaNodeInfoPtr +xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt) +{ + xmlSchemaNodeInfoPtr info = NULL; + + if (vctxt->depth > vctxt->sizeElemInfos) { + VERROR_INT("xmlSchemaGetFreshElemInfo", + "inconsistent depth encountered"); + return (NULL); + } + if (vctxt->elemInfos == NULL) { + vctxt->elemInfos = (xmlSchemaNodeInfoPtr *) + xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr)); + if (vctxt->elemInfos == NULL) { + xmlSchemaVErrMemory(vctxt, + "allocating the element info array", NULL); + return (NULL); + } + memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr)); + vctxt->sizeElemInfos = 10; + } else if (vctxt->sizeElemInfos <= vctxt->depth) { + int i = vctxt->sizeElemInfos; + + vctxt->sizeElemInfos *= 2; + vctxt->elemInfos = (xmlSchemaNodeInfoPtr *) + xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos * + sizeof(xmlSchemaNodeInfoPtr)); + if (vctxt->elemInfos == NULL) { + xmlSchemaVErrMemory(vctxt, + "re-allocating the element info array", NULL); + return (NULL); + } + /* + * We need the new memory to be NULLed. + * TODO: Use memset instead? + */ + for (; i < vctxt->sizeElemInfos; i++) + vctxt->elemInfos[i] = NULL; + } else + info = vctxt->elemInfos[vctxt->depth]; + + if (info == NULL) { + info = (xmlSchemaNodeInfoPtr) + xmlMalloc(sizeof(xmlSchemaNodeInfo)); + if (info == NULL) { + xmlSchemaVErrMemory(vctxt, + "allocating an element info", NULL); + return (NULL); + } + vctxt->elemInfos[vctxt->depth] = info; + } else { + if (info->localName != NULL) { + VERROR_INT("xmlSchemaGetFreshElemInfo", + "elem info has not been cleared"); + return (NULL); + } + } + memset(info, 0, sizeof(xmlSchemaNodeInfo)); + info->nodeType = XML_ELEMENT_NODE; + info->depth = vctxt->depth; + + return (info); +} + +#define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item; +#define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth]; +#define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1]; + +static int +xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt, + xmlNodePtr node, + xmlSchemaTypePtr type, + xmlSchemaValType valType, + const xmlChar * value, + xmlSchemaValPtr val, + unsigned long length, + int fireErrors) +{ + int ret, error = 0; + + xmlSchemaTypePtr tmpType; + xmlSchemaFacetLinkPtr facetLink; + xmlSchemaFacetPtr facet; + unsigned long len = 0; + xmlSchemaWhitespaceValueType ws; + + /* + * In Libxml2, derived built-in types have currently no explicit facets. + */ + if (type->type == XML_SCHEMA_TYPE_BASIC) + return (0); + + /* + * NOTE: Do not jump away, if the facetSet of the given type is + * empty: until now, "pattern" and "enumeration" facets of the + * *base types* need to be checked as well. + */ + if (type->facetSet == NULL) + goto pattern_and_enum; + + if (! WXS_IS_ATOMIC(type)) { + if (WXS_IS_LIST(type)) + goto WXS_IS_LIST; + else + goto pattern_and_enum; + } + /* + * Whitespace handling is only of importance for string-based + * types. + */ + tmpType = xmlSchemaGetPrimitiveType(type); + if ((tmpType->builtInType == XML_SCHEMAS_STRING) || + WXS_IS_ANY_SIMPLE_TYPE(tmpType)) { + ws = xmlSchemaGetWhiteSpaceFacetValue(type); + } else + ws = XML_SCHEMA_WHITESPACE_COLLAPSE; + /* + * If the value was not computed (for string or + * anySimpleType based types), then use the provided + * type. + */ + if (val == NULL) + valType = valType; + else + valType = xmlSchemaGetValType(val); + + ret = 0; + for (facetLink = type->facetSet; facetLink != NULL; + facetLink = facetLink->next) { + /* + * Skip the pattern "whiteSpace": it is used to + * format the character content beforehand. + */ + switch (facetLink->facet->type) { + case XML_SCHEMA_FACET_WHITESPACE: + case XML_SCHEMA_FACET_PATTERN: + case XML_SCHEMA_FACET_ENUMERATION: + continue; + case XML_SCHEMA_FACET_LENGTH: + case XML_SCHEMA_FACET_MINLENGTH: + case XML_SCHEMA_FACET_MAXLENGTH: + ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet, + valType, value, val, &len, ws); + break; + default: + ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws, + valType, value, val, ws); + break; + } + if (ret < 0) { + AERROR_INT("xmlSchemaValidateFacets", + "validating against a atomic type facet"); + return (-1); + } else if (ret > 0) { + if (fireErrors) + xmlSchemaFacetErr(actxt, ret, node, + value, len, type, facetLink->facet, NULL, NULL, NULL); + else + return (ret); + if (error == 0) + error = ret; + } + ret = 0; + } + +WXS_IS_LIST: + if (! WXS_IS_LIST(type)) + goto pattern_and_enum; + /* + * "length", "minLength" and "maxLength" of list types. + */ + ret = 0; + for (facetLink = type->facetSet; facetLink != NULL; + facetLink = facetLink->next) { + + switch (facetLink->facet->type) { + case XML_SCHEMA_FACET_LENGTH: + case XML_SCHEMA_FACET_MINLENGTH: + case XML_SCHEMA_FACET_MAXLENGTH: + ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet, + value, length, NULL); + break; + default: + continue; + } + if (ret < 0) { + AERROR_INT("xmlSchemaValidateFacets", + "validating against a list type facet"); + return (-1); + } else if (ret > 0) { + if (fireErrors) + xmlSchemaFacetErr(actxt, ret, node, + value, length, type, facetLink->facet, NULL, NULL, NULL); + else + return (ret); + if (error == 0) + error = ret; + } + ret = 0; + } + +pattern_and_enum: + if (error >= 0) { + int found = 0; + /* + * Process enumerations. Facet values are in the value space + * of the defining type's base type. This seems to be a bug in the + * XML Schema 1.0 spec. Use the whitespace type of the base type. + * Only the first set of enumerations in the ancestor-or-self axis + * is used for validation. + */ + ret = 0; + tmpType = type; + do { + for (facet = tmpType->facets; facet != NULL; facet = facet->next) { + if (facet->type != XML_SCHEMA_FACET_ENUMERATION) + continue; + found = 1; + ret = xmlSchemaAreValuesEqual(facet->val, val); + if (ret == 1) + break; + else if (ret < 0) { + AERROR_INT("xmlSchemaValidateFacets", + "validating against an enumeration facet"); + return (-1); + } + } + if (ret != 0) + break; + /* + * Break on the first set of enumerations. Any additional + * enumerations which might be existent on the ancestors + * of the current type are restricted by this set; thus + * *must* *not* be taken into account. + */ + if (found) + break; + tmpType = tmpType->baseType; + } while ((tmpType != NULL) && + (tmpType->type != XML_SCHEMA_TYPE_BASIC)); + if (found && (ret == 0)) { + ret = XML_SCHEMAV_CVC_ENUMERATION_VALID; + if (fireErrors) { + xmlSchemaFacetErr(actxt, ret, node, + value, 0, type, NULL, NULL, NULL, NULL); + } else + return (ret); + if (error == 0) + error = ret; + } + } + + if (error >= 0) { + int found; + /* + * Process patters. Pattern facets are ORed at type level + * and ANDed if derived. Walk the base type axis. + */ + tmpType = type; + facet = NULL; + do { + found = 0; + for (facetLink = tmpType->facetSet; facetLink != NULL; + facetLink = facetLink->next) { + if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN) + continue; + found = 1; + /* + * NOTE that for patterns, @value needs to be the + * normalized vaule. + */ + ret = xmlRegexpExec(facetLink->facet->regexp, value); + if (ret == 1) + break; + else if (ret < 0) { + AERROR_INT("xmlSchemaValidateFacets", + "validating against a pattern facet"); + return (-1); + } else { + /* + * Save the last non-validating facet. + */ + facet = facetLink->facet; + } + } + if (found && (ret != 1)) { + ret = XML_SCHEMAV_CVC_PATTERN_VALID; + if (fireErrors) { + xmlSchemaFacetErr(actxt, ret, node, + value, 0, type, facet, NULL, NULL, NULL); + } else + return (ret); + if (error == 0) + error = ret; + break; + } + tmpType = tmpType->baseType; + } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC)); + } + + return (error); +} + +static xmlChar * +xmlSchemaNormalizeValue(xmlSchemaTypePtr type, + const xmlChar *value) +{ + switch (xmlSchemaGetWhiteSpaceFacetValue(type)) { + case XML_SCHEMA_WHITESPACE_COLLAPSE: + return (xmlSchemaCollapseString(value)); + case XML_SCHEMA_WHITESPACE_REPLACE: + return (xmlSchemaWhiteSpaceReplace(value)); + default: + return (NULL); + } +} + +static int +xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt, + const xmlChar *value, + xmlSchemaValPtr *val, + int valNeeded) +{ + int ret; + const xmlChar *nsName; + xmlChar *local, *prefix = NULL; + + ret = xmlValidateQName(value, 1); + if (ret != 0) { + if (ret == -1) { + VERROR_INT("xmlSchemaValidateQName", + "calling xmlValidateQName()"); + return (-1); + } + return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1); + } + /* + * NOTE: xmlSplitQName2 will always return a duplicated + * strings. + */ + local = xmlSplitQName2(value, &prefix); + if (local == NULL) + local = xmlStrdup(value); + /* + * OPTIMIZE TODO: Use flags for: + * - is there any namespace binding? + * - is there a default namespace? + */ + nsName = xmlSchemaLookupNamespace(vctxt, prefix); + + if (prefix != NULL) { + xmlFree(prefix); + /* + * A namespace must be found if the prefix is + * NOT NULL. + */ + if (nsName == NULL) { + ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1; + xmlSchemaCustomErr(ACTXT_CAST vctxt, ret, NULL, + WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), + "The QName value '%s' has no " + "corresponding namespace declaration in " + "scope", value, NULL); + if (local != NULL) + xmlFree(local); + return (ret); + } + } + if (valNeeded && val) { + if (nsName != NULL) + *val = xmlSchemaNewQNameValue( + BAD_CAST xmlStrdup(nsName), BAD_CAST local); + else + *val = xmlSchemaNewQNameValue(NULL, + BAD_CAST local); + } else + xmlFree(local); + return (0); +} + +/* +* cvc-simple-type +*/ +static int +xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt, + xmlNodePtr node, + xmlSchemaTypePtr type, + const xmlChar *value, + xmlSchemaValPtr *retVal, + int fireErrors, + int normalize, + int isNormalized) +{ + int ret = 0, valNeeded = (retVal) ? 1 : 0; + xmlSchemaValPtr val = NULL; + /* xmlSchemaWhitespaceValueType ws; */ + xmlChar *normValue = NULL; + +#define NORMALIZE(atype) \ + if ((! isNormalized) && \ + (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \ + normValue = xmlSchemaNormalizeValue(atype, value); \ + if (normValue != NULL) \ + value = normValue; \ + isNormalized = 1; \ + } + + if ((retVal != NULL) && (*retVal != NULL)) { + xmlSchemaFreeValue(*retVal); + *retVal = NULL; + } + /* + * 3.14.4 Simple Type Definition Validation Rules + * Validation Rule: String Valid + */ + /* + * 1 It is schema-valid with respect to that definition as defined + * by Datatype Valid in [XML Schemas: Datatypes]. + */ + /* + * 2.1 If The definition is ENTITY or is validly derived from ENTITY given + * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then + * the string must be a ·declared entity name·. + */ + /* + * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES + * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), + * then every whitespace-delimited substring of the string must be a ·declared + * entity name·. + */ + /* + * 2.3 otherwise no further condition applies. + */ + if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE)) + valNeeded = 1; + if (value == NULL) + value = BAD_CAST ""; + if (WXS_IS_ANY_SIMPLE_TYPE(type) || WXS_IS_ATOMIC(type)) { + xmlSchemaTypePtr biType; /* The built-in type. */ + /* + * SPEC (1.2.1) "if {variety} is ·atomic· then the string must ·match· + * a literal in the ·lexical space· of {base type definition}" + */ + /* + * Whitespace-normalize. + */ + NORMALIZE(type); + if (type->type != XML_SCHEMA_TYPE_BASIC) { + /* + * Get the built-in type. + */ + biType = type->baseType; + while ((biType != NULL) && + (biType->type != XML_SCHEMA_TYPE_BASIC)) + biType = biType->baseType; + + if (biType == NULL) { + AERROR_INT("xmlSchemaVCheckCVCSimpleType", + "could not get the built-in type"); + goto internal_error; + } + } else + biType = type; + /* + * NOTATIONs need to be processed here, since they need + * to lookup in the hashtable of NOTATION declarations of the schema. + */ + if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) { + switch (biType->builtInType) { + case XML_SCHEMAS_NOTATION: + ret = xmlSchemaValidateNotation( + (xmlSchemaValidCtxtPtr) actxt, + ((xmlSchemaValidCtxtPtr) actxt)->schema, + NULL, value, &val, valNeeded); + break; + case XML_SCHEMAS_QNAME: + ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt, + value, &val, valNeeded); + break; + default: + /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */ + if (valNeeded) + ret = xmlSchemaValPredefTypeNodeNoNorm(biType, + value, &val, NULL); + else + ret = xmlSchemaValPredefTypeNodeNoNorm(biType, + value, NULL, NULL); + break; + } + } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) { + switch (biType->builtInType) { + case XML_SCHEMAS_NOTATION: + ret = xmlSchemaValidateNotation(NULL, + ((xmlSchemaParserCtxtPtr) actxt)->schema, node, + value, &val, valNeeded); + break; + default: + /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */ + if (valNeeded) + ret = xmlSchemaValPredefTypeNodeNoNorm(biType, + value, &val, node); + else + ret = xmlSchemaValPredefTypeNodeNoNorm(biType, + value, NULL, node); + break; + } + } else { + /* + * Validation via a public API is not implemented yet. + */ + TODO + goto internal_error; + } + if (ret != 0) { + if (ret < 0) { + AERROR_INT("xmlSchemaVCheckCVCSimpleType", + "validating against a built-in type"); + goto internal_error; + } + if (WXS_IS_LIST(type)) + ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2; + else + ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1; + } + if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) { + /* + * Check facets. + */ + ret = xmlSchemaValidateFacets(actxt, node, type, + (xmlSchemaValType) biType->builtInType, value, val, + 0, fireErrors); + if (ret != 0) { + if (ret < 0) { + AERROR_INT("xmlSchemaVCheckCVCSimpleType", + "validating facets of atomic simple type"); + goto internal_error; + } + if (WXS_IS_LIST(type)) + ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2; + else + ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1; + } + } + if (fireErrors && (ret > 0)) + xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1); + } else if (WXS_IS_LIST(type)) { + + xmlSchemaTypePtr itemType; + const xmlChar *cur, *end; + xmlChar *tmpValue = NULL; + unsigned long len = 0; + xmlSchemaValPtr prevVal = NULL, curVal = NULL; + /* 1.2.2 if {variety} is ·list· then the string must be a sequence + * of white space separated tokens, each of which ·match·es a literal + * in the ·lexical space· of {item type definition} + */ + /* + * Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if + * the list type has an enum or pattern facet. + */ + NORMALIZE(type); + /* + * VAL TODO: Optimize validation of empty values. + * VAL TODO: We do not have computed values for lists. + */ + itemType = WXS_LIST_ITEMTYPE(type); + cur = value; + do { + while (IS_BLANK_CH(*cur)) + cur++; + end = cur; + while ((*end != 0) && (!(IS_BLANK_CH(*end)))) + end++; + if (end == cur) + break; + tmpValue = xmlStrndup(cur, end - cur); + len++; + + if (valNeeded) + ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType, + tmpValue, &curVal, fireErrors, 0, 1); + else + ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType, + tmpValue, NULL, fireErrors, 0, 1); + FREE_AND_NULL(tmpValue); + if (curVal != NULL) { + /* + * Add to list of computed values. + */ + if (val == NULL) + val = curVal; + else + xmlSchemaValueAppend(prevVal, curVal); + prevVal = curVal; + curVal = NULL; + } + if (ret != 0) { + if (ret < 0) { + AERROR_INT("xmlSchemaVCheckCVCSimpleType", + "validating an item of list simple type"); + goto internal_error; + } + ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2; + break; + } + cur = end; + } while (*cur != 0); + FREE_AND_NULL(tmpValue); + if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) { + /* + * Apply facets (pattern, enumeration). + */ + ret = xmlSchemaValidateFacets(actxt, node, type, + XML_SCHEMAS_UNKNOWN, value, val, + len, fireErrors); + if (ret != 0) { + if (ret < 0) { + AERROR_INT("xmlSchemaVCheckCVCSimpleType", + "validating facets of list simple type"); + goto internal_error; + } + ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2; + } + } + if (fireErrors && (ret > 0)) { + /* + * Report the normalized value. + */ + normalize = 1; + NORMALIZE(type); + xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1); + } + } else if (WXS_IS_UNION(type)) { + xmlSchemaTypeLinkPtr memberLink; + /* + * TODO: For all datatypes ·derived· by ·union· whiteSpace does + * not apply directly; however, the normalization behavior of ·union· + * types is controlled by the value of whiteSpace on that one of the + * ·memberTypes· against which the ·union· is successfully validated. + * + * This means that the value is normalized by the first validating + * member type, then the facets of the union type are applied. This + * needs changing of the value! + */ + + /* + * 1.2.3 if {variety} is ·union· then the string must ·match· a + * literal in the ·lexical space· of at least one member of + * {member type definitions} + */ + memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type); + if (memberLink == NULL) { + AERROR_INT("xmlSchemaVCheckCVCSimpleType", + "union simple type has no member types"); + goto internal_error; + } + /* + * Always normalize union type values, since we currently + * cannot store the whitespace information with the value + * itself; otherwise a later value-comparison would be + * not possible. + */ + while (memberLink != NULL) { + if (valNeeded) + ret = xmlSchemaVCheckCVCSimpleType(actxt, node, + memberLink->type, value, &val, 0, 1, 0); + else + ret = xmlSchemaVCheckCVCSimpleType(actxt, node, + memberLink->type, value, NULL, 0, 1, 0); + if (ret <= 0) + break; + memberLink = memberLink->next; + } + if (ret != 0) { + if (ret < 0) { + AERROR_INT("xmlSchemaVCheckCVCSimpleType", + "validating members of union simple type"); + goto internal_error; + } + ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3; + } + /* + * Apply facets (pattern, enumeration). + */ + if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) { + /* + * The normalization behavior of ·union· types is controlled by + * the value of whiteSpace on that one of the ·memberTypes· + * against which the ·union· is successfully validated. + */ + NORMALIZE(memberLink->type); + ret = xmlSchemaValidateFacets(actxt, node, type, + XML_SCHEMAS_UNKNOWN, value, val, + 0, fireErrors); + if (ret != 0) { + if (ret < 0) { + AERROR_INT("xmlSchemaVCheckCVCSimpleType", + "validating facets of union simple type"); + goto internal_error; + } + ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3; + } + } + if (fireErrors && (ret > 0)) + xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1); + } + + if (normValue != NULL) + xmlFree(normValue); + if (ret == 0) { + if (retVal != NULL) + *retVal = val; + else if (val != NULL) + xmlSchemaFreeValue(val); + } else if (val != NULL) + xmlSchemaFreeValue(val); + return (ret); +internal_error: + if (normValue != NULL) + xmlFree(normValue); + if (val != NULL) + xmlSchemaFreeValue(val); + return (-1); +} + +static int +xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt, + const xmlChar *value, + const xmlChar **nsName, + const xmlChar **localName) +{ + int ret = 0; + + if ((nsName == NULL) || (localName == NULL)) + return (-1); + *nsName = NULL; + *localName = NULL; + + ret = xmlValidateQName(value, 1); + if (ret == -1) + return (-1); + if (ret > 0) { + xmlSchemaSimpleTypeErr(ACTXT_CAST vctxt, + XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL, + value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1); + return (1); + } + { + xmlChar *local = NULL; + xmlChar *prefix; + + /* + * NOTE: xmlSplitQName2 will return a duplicated + * string. + */ + local = xmlSplitQName2(value, &prefix); + if (local == NULL) + *localName = xmlDictLookup(vctxt->dict, value, -1); + else { + *localName = xmlDictLookup(vctxt->dict, local, -1); + xmlFree(local); + } + + *nsName = xmlSchemaLookupNamespace(vctxt, prefix); + + if (prefix != NULL) { + xmlFree(prefix); + /* + * A namespace must be found if the prefix is NOT NULL. + */ + if (*nsName == NULL) { + xmlSchemaCustomErr(ACTXT_CAST vctxt, + XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL, + WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), + "The QName value '%s' has no " + "corresponding namespace declaration in scope", + value, NULL); + return (2); + } + } + } + return (0); +} + +static int +xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt, + xmlSchemaAttrInfoPtr iattr, + xmlSchemaTypePtr *localType, + xmlSchemaElementPtr elemDecl) +{ + int ret = 0; + /* + * cvc-elt (3.3.4) : (4) + * AND + * Schema-Validity Assessment (Element) (cvc-assess-elt) + * (1.2.1.2.1) - (1.2.1.2.4) + * Handle 'xsi:type'. + */ + if (localType == NULL) + return (-1); + *localType = NULL; + if (iattr == NULL) + return (0); + else { + const xmlChar *nsName = NULL, *local = NULL; + /* + * TODO: We should report a *warning* that the type was overriden + * by the instance. + */ + ACTIVATE_ATTRIBUTE(iattr); + /* + * (cvc-elt) (3.3.4) : (4.1) + * (cvc-assess-elt) (1.2.1.2.2) + */ + ret = xmlSchemaVExpandQName(vctxt, iattr->value, + &nsName, &local); + if (ret != 0) { + if (ret < 0) { + VERROR_INT("xmlSchemaValidateElementByDeclaration", + "calling xmlSchemaQNameExpand() to validate the " + "attribute 'xsi:type'"); + goto internal_error; + } + goto exit; + } + /* + * (cvc-elt) (3.3.4) : (4.2) + * (cvc-assess-elt) (1.2.1.2.3) + */ + *localType = xmlSchemaGetType(vctxt->schema, local, nsName); + if (*localType == NULL) { + xmlChar *str = NULL; + + xmlSchemaCustomErr(ACTXT_CAST vctxt, + XML_SCHEMAV_CVC_ELT_4_2, NULL, + WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), + "The QName value '%s' of the xsi:type attribute does not " + "resolve to a type definition", + xmlSchemaFormatQName(&str, nsName, local), NULL); + FREE_AND_NULL(str); + ret = vctxt->err; + goto exit; + } + if (elemDecl != NULL) { + int set = 0; + + /* + * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK) + * "The ·local type definition· must be validly + * derived from the {type definition} given the union of + * the {disallowed substitutions} and the {type definition}'s + * {prohibited substitutions}, as defined in + * Type Derivation OK (Complex) (§3.4.6) + * (if it is a complex type definition), + * or given {disallowed substitutions} as defined in Type + * Derivation OK (Simple) (§3.14.6) (if it is a simple type + * definition)." + * + * {disallowed substitutions}: the "block" on the element decl. + * {prohibited substitutions}: the "block" on the type def. + */ + /* + * OPTIMIZE TODO: We could map types already evaluated + * to be validly derived from other types to avoid checking + * this over and over for the same types. + */ + if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) || + (elemDecl->subtypes->flags & + XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) + set |= SUBSET_EXTENSION; + + if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) || + (elemDecl->subtypes->flags & + XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)) + set |= SUBSET_RESTRICTION; + + /* + * REMOVED and CHANGED since this produced a parser context + * which adds to the string dict of the schema. So this would + * change the schema and we don't want this. We don't need + * the parser context anymore. + * + * if ((vctxt->pctxt == NULL) && + * (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1)) + * return (-1); + */ + + if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST vctxt, *localType, + elemDecl->subtypes, set) != 0) { + xmlChar *str = NULL; + + xmlSchemaCustomErr(ACTXT_CAST vctxt, + XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL, + "The type definition '%s', specified by xsi:type, is " + "blocked or not validly derived from the type definition " + "of the element declaration", + xmlSchemaFormatQName(&str, + (*localType)->targetNamespace, + (*localType)->name), + NULL); + FREE_AND_NULL(str); + ret = vctxt->err; + *localType = NULL; + } + } + } +exit: + ACTIVATE_ELEM; + return (ret); +internal_error: + ACTIVATE_ELEM; + return (-1); +} + +static int +xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt) +{ + xmlSchemaElementPtr elemDecl = vctxt->inode->decl; + xmlSchemaTypePtr actualType; + + /* + * cvc-elt (3.3.4) : 1 + */ + if (elemDecl == NULL) { + VERROR(XML_SCHEMAV_CVC_ELT_1, NULL, + "No matching declaration available"); + return (vctxt->err); + } + actualType = WXS_ELEM_TYPEDEF(elemDecl); + /* + * cvc-elt (3.3.4) : 2 + */ + if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) { + VERROR(XML_SCHEMAV_CVC_ELT_2, NULL, + "The element declaration is abstract"); + return (vctxt->err); + } + if (actualType == NULL) { + VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL, + "The type definition is absent"); + return (XML_SCHEMAV_CVC_TYPE_1); + } + if (vctxt->nbAttrInfos != 0) { + int ret; + xmlSchemaAttrInfoPtr iattr; + /* + * cvc-elt (3.3.4) : 3 + * Handle 'xsi:nil'. + */ + iattr = xmlSchemaGetMetaAttrInfo(vctxt, + XML_SCHEMA_ATTR_INFO_META_XSI_NIL); + if (iattr) { + ACTIVATE_ATTRIBUTE(iattr); + /* + * Validate the value. + */ + ret = xmlSchemaVCheckCVCSimpleType( + ACTXT_CAST vctxt, NULL, + xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN), + iattr->value, &(iattr->val), 1, 0, 0); + ACTIVATE_ELEM; + if (ret < 0) { + VERROR_INT("xmlSchemaValidateElemDecl", + "calling xmlSchemaVCheckCVCSimpleType() to " + "validate the attribute 'xsi:nil'"); + return (-1); + } + if (ret == 0) { + if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) { + /* + * cvc-elt (3.3.4) : 3.1 + */ + VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL, + "The element is not 'nillable'"); + /* Does not return an error on purpose. */ + } else { + if (xmlSchemaValueGetAsBoolean(iattr->val)) { + /* + * cvc-elt (3.3.4) : 3.2.2 + */ + if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) && + (elemDecl->value != NULL)) { + VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL, + "The element cannot be 'nilled' because " + "there is a fixed value constraint defined " + "for it"); + /* Does not return an error on purpose. */ + } else + vctxt->inode->flags |= + XML_SCHEMA_ELEM_INFO_NILLED; + } + } + } + } + /* + * cvc-elt (3.3.4) : 4 + * Handle 'xsi:type'. + */ + iattr = xmlSchemaGetMetaAttrInfo(vctxt, + XML_SCHEMA_ATTR_INFO_META_XSI_TYPE); + if (iattr) { + xmlSchemaTypePtr localType = NULL; + + ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType, + elemDecl); + if (ret != 0) { + if (ret == -1) { + VERROR_INT("xmlSchemaValidateElemDecl", + "calling xmlSchemaProcessXSIType() to " + "process the attribute 'xsi:type'"); + return (-1); + } + /* Does not return an error on purpose. */ + } + if (localType != NULL) { + vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE; + actualType = localType; + } + } + } + /* + * IDC: Register identity-constraint XPath matchers. + */ + if ((elemDecl->idcs != NULL) && + (xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1)) + return (-1); + /* + * No actual type definition. + */ + if (actualType == NULL) { + VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL, + "The type definition is absent"); + return (XML_SCHEMAV_CVC_TYPE_1); + } + /* + * Remember the actual type definition. + */ + vctxt->inode->typeDef = actualType; + + return (0); +} + +static int +xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt) +{ + xmlSchemaAttrInfoPtr iattr; + int ret = 0, i; + + /* + * SPEC cvc-type (3.1.1) + * "The attributes of must be empty, excepting those whose namespace + * name is identical to http://www.w3.org/2001/XMLSchema-instance and + * whose local name is one of type, nil, schemaLocation or + * noNamespaceSchemaLocation." + */ + if (vctxt->nbAttrInfos == 0) + return (0); + for (i = 0; i < vctxt->nbAttrInfos; i++) { + iattr = vctxt->attrInfos[i]; + if (! iattr->metaType) { + ACTIVATE_ATTRIBUTE(iattr) + xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt, + XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL); + ret = XML_SCHEMAV_CVC_TYPE_3_1_1; + } + } + ACTIVATE_ELEM + return (ret); +} + +/* +* Cleanup currently used attribute infos. +*/ +static void +xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt) +{ + int i; + xmlSchemaAttrInfoPtr attr; + + if (vctxt->nbAttrInfos == 0) + return; + for (i = 0; i < vctxt->nbAttrInfos; i++) { + attr = vctxt->attrInfos[i]; + if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) { + if (attr->localName != NULL) + xmlFree((xmlChar *) attr->localName); + if (attr->nsName != NULL) + xmlFree((xmlChar *) attr->nsName); + } + if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) { + if (attr->value != NULL) + xmlFree((xmlChar *) attr->value); + } + if (attr->val != NULL) { + xmlSchemaFreeValue(attr->val); + attr->val = NULL; + } + memset(attr, 0, sizeof(xmlSchemaAttrInfo)); + } + vctxt->nbAttrInfos = 0; +} + +/* +* 3.4.4 Complex Type Definition Validation Rules +* Element Locally Valid (Complex Type) (cvc-complex-type) +* 3.2.4 Attribute Declaration Validation Rules +* Validation Rule: Attribute Locally Valid (cvc-attribute) +* Attribute Locally Valid (Use) (cvc-au) +* +* Only "assessed" attribute information items will be visible to +* IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes. +*/ +static int +xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt) +{ + xmlSchemaTypePtr type = vctxt->inode->typeDef; + xmlSchemaItemListPtr attrUseList; + xmlSchemaAttributeUsePtr attrUse = NULL; + xmlSchemaAttributePtr attrDecl = NULL; + xmlSchemaAttrInfoPtr iattr, tmpiattr; + int i, j, found, nbAttrs, nbUses; + int xpathRes = 0, res, wildIDs = 0, fixed; + xmlNodePtr defAttrOwnerElem = NULL; + + /* + * SPEC (cvc-attribute) + * (1) "The declaration must not be ·absent· (see Missing + * Sub-components (§5.3) for how this can fail to be + * the case)." + * (2) "Its {type definition} must not be absent." + * + * NOTE (1) + (2): This is not handled here, since we currently do not + * allow validation against schemas which have missing sub-components. + * + * SPEC (cvc-complex-type) + * (3) "For each attribute information item in the element information + * item's [attributes] excepting those whose [namespace name] is + * identical to http://www.w3.org/2001/XMLSchema-instance and whose + * [local name] is one of type, nil, schemaLocation or + * noNamespaceSchemaLocation, the appropriate case among the following + * must be true: + * + */ + attrUseList = (xmlSchemaItemListPtr) type->attrUses; + /* + * @nbAttrs is the number of attributes present in the instance. + */ + nbAttrs = vctxt->nbAttrInfos; + if (attrUseList != NULL) + nbUses = attrUseList->nbItems; + else + nbUses = 0; + for (i = 0; i < nbUses; i++) { + found = 0; + attrUse = attrUseList->items[i]; + attrDecl = WXS_ATTRUSE_DECL(attrUse); + for (j = 0; j < nbAttrs; j++) { + iattr = vctxt->attrInfos[j]; + /* + * SPEC (cvc-complex-type) (3) + * Skip meta attributes. + */ + if (iattr->metaType) + continue; + if (iattr->localName[0] != attrDecl->name[0]) + continue; + if (!xmlStrEqual(iattr->localName, attrDecl->name)) + continue; + if (!xmlStrEqual(iattr->nsName, attrDecl->targetNamespace)) + continue; + found = 1; + /* + * SPEC (cvc-complex-type) + * (3.1) "If there is among the {attribute uses} an attribute + * use with an {attribute declaration} whose {name} matches + * the attribute information item's [local name] and whose + * {target namespace} is identical to the attribute information + * item's [namespace name] (where an ·absent· {target namespace} + * is taken to be identical to a [namespace name] with no value), + * then the attribute information must be ·valid· with respect + * to that attribute use as per Attribute Locally Valid (Use) + * (§3.5.4). In this case the {attribute declaration} of that + * attribute use is the ·context-determined declaration· for the + * attribute information item with respect to Schema-Validity + * Assessment (Attribute) (§3.2.4) and + * Assessment Outcome (Attribute) (§3.2.5). + */ + iattr->state = XML_SCHEMAS_ATTR_ASSESSED; + iattr->use = attrUse; + /* + * Context-determined declaration. + */ + iattr->decl = attrDecl; + iattr->typeDef = attrDecl->subtypes; + break; + } + + if (found) + continue; + + if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) { + /* + * Handle non-existent, required attributes. + * + * SPEC (cvc-complex-type) + * (4) "The {attribute declaration} of each attribute use in + * the {attribute uses} whose {required} is true matches one + * of the attribute information items in the element information + * item's [attributes] as per clause 3.1 above." + */ + tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt); + if (tmpiattr == NULL) { + VERROR_INT( + "xmlSchemaVAttributesComplex", + "calling xmlSchemaGetFreshAttrInfo()"); + return (-1); + } + tmpiattr->state = XML_SCHEMAS_ATTR_ERR_MISSING; + tmpiattr->use = attrUse; + tmpiattr->decl = attrDecl; + } else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) && + ((attrUse->defValue != NULL) || + (attrDecl->defValue != NULL))) { + /* + * Handle non-existent, optional, default/fixed attributes. + */ + tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt); + if (tmpiattr == NULL) { + VERROR_INT( + "xmlSchemaVAttributesComplex", + "calling xmlSchemaGetFreshAttrInfo()"); + return (-1); + } + tmpiattr->state = XML_SCHEMAS_ATTR_DEFAULT; + tmpiattr->use = attrUse; + tmpiattr->decl = attrDecl; + tmpiattr->typeDef = attrDecl->subtypes; + tmpiattr->localName = attrDecl->name; + tmpiattr->nsName = attrDecl->targetNamespace; + } + } + + if (vctxt->nbAttrInfos == 0) + return (0); + nbUses = vctxt->nbAttrInfos; + /* + * Validate against the wildcard. + */ + if (type->attributeWildcard != NULL) { + /* + * SPEC (cvc-complex-type) + * (3.2.1) "There must be an {attribute wildcard}." + */ + for (i = 0; i < nbAttrs; i++) { + iattr = vctxt->attrInfos[i]; + /* + * SPEC (cvc-complex-type) (3) + * Skip meta attributes. + */ + if (iattr->state != XML_SCHEMAS_ATTR_UNKNOWN) + continue; + /* + * SPEC (cvc-complex-type) + * (3.2.2) "The attribute information item must be ·valid· with + * respect to it as defined in Item Valid (Wildcard) (§3.10.4)." + * + * SPEC Item Valid (Wildcard) (cvc-wildcard) + * "... its [namespace name] must be ·valid· with respect to + * the wildcard constraint, as defined in Wildcard allows + * Namespace Name (§3.10.4)." + */ + if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard, + iattr->nsName) == 0) { + /* + * Handle processContents. + * + * SPEC (cvc-wildcard): + * processContents | context-determined declaration: + * "strict" "mustFind" + * "lax" "none" + * "skip" "skip" + */ + if (type->attributeWildcard->processContents == + XML_SCHEMAS_ANY_SKIP) { + /* + * context-determined declaration = "skip" + * + * SPEC PSVI Assessment Outcome (Attribute) + * [validity] = "notKnown" + * [validation attempted] = "none" + */ + iattr->state = XML_SCHEMAS_ATTR_WILD_SKIP; + continue; + } + /* + * Find an attribute declaration. + */ + iattr->decl = xmlSchemaGetAttributeDecl(vctxt->schema, + iattr->localName, iattr->nsName); + if (iattr->decl != NULL) { + iattr->state = XML_SCHEMAS_ATTR_ASSESSED; + /* + * SPEC (cvc-complex-type) + * (5) "Let [Definition:] the wild IDs be the set of + * all attribute information item to which clause 3.2 + * applied and whose ·validation· resulted in a + * ·context-determined declaration· of mustFind or no + * ·context-determined declaration· at all, and whose + * [local name] and [namespace name] resolve (as + * defined by QName resolution (Instance) (§3.15.4)) to + * an attribute declaration whose {type definition} is + * or is derived from ID. Then all of the following + * must be true:" + */ + iattr->typeDef = WXS_ATTR_TYPEDEF(iattr->decl); + if (xmlSchemaIsDerivedFromBuiltInType( + iattr->typeDef, XML_SCHEMAS_ID)) { + /* + * SPEC (5.1) "There must be no more than one + * item in ·wild IDs·." + */ + if (wildIDs != 0) { + /* VAL TODO */ + iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID; + TODO + continue; + } + wildIDs++; + /* + * SPEC (cvc-complex-type) + * (5.2) "If ·wild IDs· is non-empty, there must not + * be any attribute uses among the {attribute uses} + * whose {attribute declaration}'s {type definition} + * is or is derived from ID." + */ + for (j = 0; j < attrUseList->nbItems; j++) { + if (xmlSchemaIsDerivedFromBuiltInType( + WXS_ATTRUSE_TYPEDEF(attrUseList->items[j]), + XML_SCHEMAS_ID)) { + /* URGENT VAL TODO: implement */ + iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID; + TODO + break; + } + } + } + } else if (type->attributeWildcard->processContents == + XML_SCHEMAS_ANY_LAX) { + iattr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL; + /* + * SPEC PSVI Assessment Outcome (Attribute) + * [validity] = "notKnown" + * [validation attempted] = "none" + */ + } else { + iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL; + } + } + } + } + + if (vctxt->nbAttrInfos == 0) + return (0); + + /* + * Get the owner element; needed for creation of default attributes. + * This fixes bug #341337, reported by David Grohmann. + */ + if (vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) { + xmlSchemaNodeInfoPtr ielem = vctxt->elemInfos[vctxt->depth]; + if (ielem && ielem->node && ielem->node->doc) + defAttrOwnerElem = ielem->node; + } + /* + * Validate values, create default attributes, evaluate IDCs. + */ + for (i = 0; i < vctxt->nbAttrInfos; i++) { + iattr = vctxt->attrInfos[i]; + /* + * VAL TODO: Note that we won't try to resolve IDCs to + * "lax" and "skip" validated attributes. Check what to + * do in this case. + */ + if ((iattr->state != XML_SCHEMAS_ATTR_ASSESSED) && + (iattr->state != XML_SCHEMAS_ATTR_DEFAULT)) + continue; + /* + * VAL TODO: What to do if the type definition is missing? + */ + if (iattr->typeDef == NULL) { + iattr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE; + continue; + } + + ACTIVATE_ATTRIBUTE(iattr); + fixed = 0; + xpathRes = 0; + + if (vctxt->xpathStates != NULL) { + /* + * Evaluate IDCs. + */ + xpathRes = xmlSchemaXPathEvaluate(vctxt, + XML_ATTRIBUTE_NODE); + if (xpathRes == -1) { + VERROR_INT("xmlSchemaVAttributesComplex", + "calling xmlSchemaXPathEvaluate()"); + goto internal_error; + } + } + + if (iattr->state == XML_SCHEMAS_ATTR_DEFAULT) { + /* + * Default/fixed attributes. + * We need the value only if we need to resolve IDCs or + * will create default attributes. + */ + if ((xpathRes) || (defAttrOwnerElem)) { + if (iattr->use->defValue != NULL) { + iattr->value = (xmlChar *) iattr->use->defValue; + iattr->val = iattr->use->defVal; + } else { + iattr->value = (xmlChar *) iattr->decl->defValue; + iattr->val = iattr->decl->defVal; + } + /* + * IDCs will consume the precomputed default value, + * so we need to clone it. + */ + if (iattr->val == NULL) { + VERROR_INT("xmlSchemaVAttributesComplex", + "default/fixed value on an attribute use was " + "not precomputed"); + goto internal_error; + } + iattr->val = xmlSchemaCopyValue(iattr->val); + if (iattr->val == NULL) { + VERROR_INT("xmlSchemaVAttributesComplex", + "calling xmlSchemaCopyValue()"); + goto internal_error; + } + } + /* + * PSVI: Add the default attribute to the current element. + * VAL TODO: Should we use the *normalized* value? This currently + * uses the *initial* value. + */ + + if (defAttrOwnerElem) { + xmlChar *normValue; + const xmlChar *value; + + value = iattr->value; + /* + * Normalize the value. + */ + normValue = xmlSchemaNormalizeValue(iattr->typeDef, + iattr->value); + if (normValue != NULL) + value = BAD_CAST normValue; + + if (iattr->nsName == NULL) { + if (xmlNewProp(defAttrOwnerElem, + iattr->localName, value) == NULL) { + VERROR_INT("xmlSchemaVAttributesComplex", + "callling xmlNewProp()"); + if (normValue != NULL) + xmlFree(normValue); + goto internal_error; + } + } else { + xmlNsPtr ns; + + ns = xmlSearchNsByHref(defAttrOwnerElem->doc, + defAttrOwnerElem, iattr->nsName); + if (ns == NULL) { + xmlChar prefix[12]; + int counter = 0; + + /* + * Create a namespace declaration on the validation + * root node if no namespace declaration is in scope. + */ + do { + snprintf((char *) prefix, 12, "p%d", counter++); + ns = xmlSearchNs(defAttrOwnerElem->doc, + defAttrOwnerElem, BAD_CAST prefix); + if (counter > 1000) { + VERROR_INT( + "xmlSchemaVAttributesComplex", + "could not compute a ns prefix for a " + "default/fixed attribute"); + if (normValue != NULL) + xmlFree(normValue); + goto internal_error; + } + } while (ns != NULL); + ns = xmlNewNs(vctxt->validationRoot, + iattr->nsName, BAD_CAST prefix); + } + /* + * TODO: + * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0406.html + * If we have QNames: do we need to ensure there's a + * prefix defined for the QName? + */ + xmlNewNsProp(defAttrOwnerElem, ns, iattr->localName, value); + } + if (normValue != NULL) + xmlFree(normValue); + } + /* + * Go directly to IDC evaluation. + */ + goto eval_idcs; + } + /* + * Validate the value. + */ + if (vctxt->value != NULL) { + /* + * Free last computed value; just for safety reasons. + */ + xmlSchemaFreeValue(vctxt->value); + vctxt->value = NULL; + } + /* + * Note that the attribute *use* can be unavailable, if + * the attribute was a wild attribute. + */ + if ((iattr->decl->flags & XML_SCHEMAS_ATTR_FIXED) || + ((iattr->use != NULL) && + (iattr->use->flags & XML_SCHEMAS_ATTR_FIXED))) + fixed = 1; + else + fixed = 0; + /* + * SPEC (cvc-attribute) + * (3) "The item's ·normalized value· must be locally ·valid· + * with respect to that {type definition} as per + * String Valid (§3.14.4)." + * + * VAL TODO: Do we already have the + * "normalized attribute value" here? + */ + if (xpathRes || fixed) { + iattr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED; + /* + * Request a computed value. + */ + res = xmlSchemaVCheckCVCSimpleType( + ACTXT_CAST vctxt, + iattr->node, iattr->typeDef, iattr->value, &(iattr->val), + 1, 1, 0); + } else { + res = xmlSchemaVCheckCVCSimpleType( + ACTXT_CAST vctxt, + iattr->node, iattr->typeDef, iattr->value, NULL, + 1, 0, 0); + } + + if (res != 0) { + if (res == -1) { + VERROR_INT("xmlSchemaVAttributesComplex", + "calling xmlSchemaStreamValidateSimpleTypeValue()"); + goto internal_error; + } + iattr->state = XML_SCHEMAS_ATTR_INVALID_VALUE; + /* + * SPEC PSVI Assessment Outcome (Attribute) + * [validity] = "invalid" + */ + goto eval_idcs; + } + + if (fixed) { + /* + * SPEC Attribute Locally Valid (Use) (cvc-au) + * "For an attribute information item to be·valid· + * with respect to an attribute use its *normalized* + * value· must match the *canonical* lexical + * representation of the attribute use's {value + * constraint}value, if it is present and fixed." + * + * VAL TODO: The requirement for the *canonical* value + * will be removed in XML Schema 1.1. + */ + /* + * SPEC Attribute Locally Valid (cvc-attribute) + * (4) "The item's *actual* value· must match the *value* of + * the {value constraint}, if it is present and fixed." + */ + if (iattr->val == NULL) { + /* VAL TODO: A value was not precomputed. */ + TODO + goto eval_idcs; + } + if ((iattr->use != NULL) && + (iattr->use->defValue != NULL)) { + if (iattr->use->defVal == NULL) { + /* VAL TODO: A default value was not precomputed. */ + TODO + goto eval_idcs; + } + iattr->vcValue = iattr->use->defValue; + /* + if (xmlSchemaCompareValuesWhtsp(attr->val, + (xmlSchemaWhitespaceValueType) ws, + attr->use->defVal, + (xmlSchemaWhitespaceValueType) ws) != 0) { + */ + if (! xmlSchemaAreValuesEqual(iattr->val, iattr->use->defVal)) + iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE; + } else { + if (iattr->decl->defVal == NULL) { + /* VAL TODO: A default value was not precomputed. */ + TODO + goto eval_idcs; + } + iattr->vcValue = iattr->decl->defValue; + /* + if (xmlSchemaCompareValuesWhtsp(attr->val, + (xmlSchemaWhitespaceValueType) ws, + attrDecl->defVal, + (xmlSchemaWhitespaceValueType) ws) != 0) { + */ + if (! xmlSchemaAreValuesEqual(iattr->val, iattr->decl->defVal)) + iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE; + } + /* + * [validity] = "valid" + */ + } +eval_idcs: + /* + * Evaluate IDCs. + */ + if (xpathRes) { + if (xmlSchemaXPathProcessHistory(vctxt, + vctxt->depth +1) == -1) { + VERROR_INT("xmlSchemaVAttributesComplex", + "calling xmlSchemaXPathEvaluate()"); + goto internal_error; + } + } else if (vctxt->xpathStates != NULL) + xmlSchemaXPathPop(vctxt); + } + + /* + * Report errors. + */ + for (i = 0; i < vctxt->nbAttrInfos; i++) { + iattr = vctxt->attrInfos[i]; + if ((iattr->state == XML_SCHEMAS_ATTR_META) || + (iattr->state == XML_SCHEMAS_ATTR_ASSESSED) || + (iattr->state == XML_SCHEMAS_ATTR_WILD_SKIP) || + (iattr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL)) + continue; + ACTIVATE_ATTRIBUTE(iattr); + switch (iattr->state) { + case XML_SCHEMAS_ATTR_ERR_MISSING: { + xmlChar *str = NULL; + ACTIVATE_ELEM; + xmlSchemaCustomErr(ACTXT_CAST vctxt, + XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL, + "The attribute '%s' is required but missing", + xmlSchemaFormatQName(&str, + iattr->decl->targetNamespace, + iattr->decl->name), + NULL); + FREE_AND_NULL(str) + break; + } + case XML_SCHEMAS_ATTR_ERR_NO_TYPE: + VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL, + "The type definition is absent"); + break; + case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE: + xmlSchemaCustomErr(ACTXT_CAST vctxt, + XML_SCHEMAV_CVC_AU, NULL, NULL, + "The value '%s' does not match the fixed " + "value constraint '%s'", + iattr->value, iattr->vcValue); + break; + case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL: + VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL, + "No matching global attribute declaration available, but " + "demanded by the strict wildcard"); + break; + case XML_SCHEMAS_ATTR_UNKNOWN: + if (iattr->metaType) + break; + /* + * MAYBE VAL TODO: One might report different error messages + * for the following errors. + */ + if (type->attributeWildcard == NULL) { + xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt, + XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, iattr, NULL); + } else { + xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt, + XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, iattr, NULL); + } + break; + default: + break; + } + } + + ACTIVATE_ELEM; + return (0); +internal_error: + ACTIVATE_ELEM; + return (-1); +} + +static int +xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt, + int *skip) +{ + xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl; + /* + * The namespace of the element was already identified to be + * matching the wildcard. + */ + if ((skip == NULL) || (wild == NULL) || + (wild->type != XML_SCHEMA_TYPE_ANY)) { + VERROR_INT("xmlSchemaValidateElemWildcard", + "bad arguments"); + return (-1); + } + *skip = 0; + if (wild->processContents == XML_SCHEMAS_ANY_SKIP) { + /* + * URGENT VAL TODO: Either we need to position the stream to the + * next sibling, or walk the whole subtree. + */ + *skip = 1; + return (0); + } + { + xmlSchemaElementPtr decl = NULL; + + decl = xmlSchemaGetElem(vctxt->schema, + vctxt->inode->localName, vctxt->inode->nsName); + if (decl != NULL) { + vctxt->inode->decl = decl; + return (0); + } + } + if (wild->processContents == XML_SCHEMAS_ANY_STRICT) { + /* VAL TODO: Change to proper error code. */ + VERROR(XML_SCHEMAV_CVC_ELT_1, NULL, /* WXS_BASIC_CAST wild */ + "No matching global element declaration available, but " + "demanded by the strict wildcard"); + return (vctxt->err); + } + if (vctxt->nbAttrInfos != 0) { + xmlSchemaAttrInfoPtr iattr; + /* + * SPEC Validation Rule: Schema-Validity Assessment (Element) + * (1.2.1.2.1) - (1.2.1.2.3 ) + * + * Use the xsi:type attribute for the type definition. + */ + iattr = xmlSchemaGetMetaAttrInfo(vctxt, + XML_SCHEMA_ATTR_INFO_META_XSI_TYPE); + if (iattr != NULL) { + if (xmlSchemaProcessXSIType(vctxt, iattr, + &(vctxt->inode->typeDef), NULL) == -1) { + VERROR_INT("xmlSchemaValidateElemWildcard", + "calling xmlSchemaProcessXSIType() to " + "process the attribute 'xsi:nil'"); + return (-1); + } + /* + * Don't return an error on purpose. + */ + return (0); + } + } + /* + * SPEC Validation Rule: Schema-Validity Assessment (Element) + * + * Fallback to "anyType". + */ + vctxt->inode->typeDef = + xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE); + return (0); +} + +/* +* xmlSchemaCheckCOSValidDefault: +* +* This will be called if: not nilled, no content and a default/fixed +* value is provided. +*/ + +static int +xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt, + const xmlChar *value, + xmlSchemaValPtr *val) +{ + int ret = 0; + xmlSchemaNodeInfoPtr inode = vctxt->inode; + + /* + * cos-valid-default: + * Schema Component Constraint: Element Default Valid (Immediate) + * For a string to be a valid default with respect to a type + * definition the appropriate case among the following must be true: + */ + if WXS_IS_COMPLEX(inode->typeDef) { + /* + * Complex type. + * + * SPEC (2.1) "its {content type} must be a simple type definition + * or mixed." + * SPEC (2.2.2) "If the {content type} is mixed, then the {content + * type}'s particle must be ·emptiable· as defined by + * Particle Emptiable (§3.9.6)." + */ + if ((! WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) && + ((! WXS_HAS_MIXED_CONTENT(inode->typeDef)) || + (! WXS_EMPTIABLE(inode->typeDef)))) { + ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1; + /* NOTE that this covers (2.2.2) as well. */ + VERROR(ret, NULL, + "For a string to be a valid default, the type definition " + "must be a simple type or a complex type with simple content " + "or mixed content and a particle emptiable"); + return(ret); + } + } + /* + * 1 If the type definition is a simple type definition, then the string + * must be ·valid· with respect to that definition as defined by String + * Valid (§3.14.4). + * + * AND + * + * 2.2.1 If the {content type} is a simple type definition, then the + * string must be ·valid· with respect to that simple type definition + * as defined by String Valid (§3.14.4). + */ + if (WXS_IS_SIMPLE(inode->typeDef)) { + + ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt, + NULL, inode->typeDef, value, val, 1, 1, 0); + + } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) { + + ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt, + NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0); + } + if (ret < 0) { + VERROR_INT("xmlSchemaCheckCOSValidDefault", + "calling xmlSchemaVCheckCVCSimpleType()"); + } + return (ret); +} + +static void +xmlSchemaVContentModelCallback(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED, + const xmlChar * name ATTRIBUTE_UNUSED, + xmlSchemaElementPtr item, + xmlSchemaNodeInfoPtr inode) +{ + inode->decl = item; +#ifdef DEBUG_CONTENT + { + xmlChar *str = NULL; + + if (item->type == XML_SCHEMA_TYPE_ELEMENT) { + xmlGenericError(xmlGenericErrorContext, + "AUTOMATON callback for '%s' [declaration]\n", + xmlSchemaFormatQName(&str, + inode->localName, inode->nsName)); + } else { + xmlGenericError(xmlGenericErrorContext, + "AUTOMATON callback for '%s' [wildcard]\n", + xmlSchemaFormatQName(&str, + inode->localName, inode->nsName)); + + } + FREE_AND_NULL(str) + } +#endif +} + +static int +xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt) +{ + vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt); + if (vctxt->inode == NULL) { + VERROR_INT("xmlSchemaValidatorPushElem", + "calling xmlSchemaGetFreshElemInfo()"); + return (-1); + } + vctxt->nbAttrInfos = 0; + return (0); +} + +static int +xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt, + xmlSchemaNodeInfoPtr inode, + xmlSchemaTypePtr type, + const xmlChar *value) +{ + if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED) + return (xmlSchemaVCheckCVCSimpleType( + ACTXT_CAST vctxt, NULL, + type, value, &(inode->val), 1, 1, 0)); + else + return (xmlSchemaVCheckCVCSimpleType( + ACTXT_CAST vctxt, NULL, + type, value, NULL, 1, 0, 0)); +} + + + +/* +* Process END of element. +*/ +static int +xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt) +{ + int ret = 0; + xmlSchemaNodeInfoPtr inode = vctxt->inode; + + if (vctxt->nbAttrInfos != 0) + xmlSchemaClearAttrInfos(vctxt); + if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) { + /* + * This element was not expected; + * we will not validate child elements of broken parents. + * Skip validation of all content of the parent. + */ + vctxt->skipDepth = vctxt->depth -1; + goto end_elem; + } + if ((inode->typeDef == NULL) || + (inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) { + /* + * 1. the type definition might be missing if the element was + * error prone + * 2. it might be abstract. + */ + goto end_elem; + } + /* + * Check the content model. + */ + if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) || + (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) { + + /* + * Workaround for "anyType". + */ + if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE) + goto character_content; + + if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) { + xmlChar *values[10]; + int terminal, nbval = 10, nbneg; + + if (inode->regexCtxt == NULL) { + /* + * Create the regex context. + */ + inode->regexCtxt = + xmlRegNewExecCtxt(inode->typeDef->contModel, + (xmlRegExecCallbacks) xmlSchemaVContentModelCallback, + vctxt); + if (inode->regexCtxt == NULL) { + VERROR_INT("xmlSchemaValidatorPopElem", + "failed to create a regex context"); + goto internal_error; + } +#ifdef DEBUG_AUTOMATA + xmlGenericError(xmlGenericErrorContext, + "AUTOMATON create on '%s'\n", inode->localName); +#endif + } + /* + * Get hold of the still expected content, since a further + * call to xmlRegExecPushString() will loose this information. + */ + xmlRegExecNextValues(inode->regexCtxt, + &nbval, &nbneg, &values[0], &terminal); + ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL); + if (ret <= 0) { + /* + * Still missing something. + */ + ret = 1; + inode->flags |= + XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT; + xmlSchemaComplexTypeErr(ACTXT_CAST vctxt, + XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL, + "Missing child element(s)", + nbval, nbneg, values); +#ifdef DEBUG_AUTOMATA + xmlGenericError(xmlGenericErrorContext, + "AUTOMATON missing ERROR on '%s'\n", + inode->localName); +#endif + } else { + /* + * Content model is satisfied. + */ + ret = 0; +#ifdef DEBUG_AUTOMATA + xmlGenericError(xmlGenericErrorContext, + "AUTOMATON succeeded on '%s'\n", + inode->localName); +#endif + } + + } + } + if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS) + goto end_elem; + +character_content: + + if (vctxt->value != NULL) { + xmlSchemaFreeValue(vctxt->value); + vctxt->value = NULL; + } + /* + * Check character content. + */ + if (inode->decl == NULL) { + /* + * Speedup if no declaration exists. + */ + if (WXS_IS_SIMPLE(inode->typeDef)) { + ret = xmlSchemaVCheckINodeDataType(vctxt, + inode, inode->typeDef, inode->value); + } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) { + ret = xmlSchemaVCheckINodeDataType(vctxt, + inode, inode->typeDef->contentTypeDef, + inode->value); + } + if (ret < 0) { + VERROR_INT("xmlSchemaValidatorPopElem", + "calling xmlSchemaVCheckCVCSimpleType()"); + goto internal_error; + } + goto end_elem; + } + /* + * cvc-elt (3.3.4) : 5 + * The appropriate case among the following must be true: + */ + /* + * cvc-elt (3.3.4) : 5.1 + * If the declaration has a {value constraint}, + * the item has neither element nor character [children] and + * clause 3.2 has not applied, then all of the following must be true: + */ + if ((inode->decl->value != NULL) && + (inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) && + (! INODE_NILLED(inode))) { + /* + * cvc-elt (3.3.4) : 5.1.1 + * If the ·actual type definition· is a ·local type definition· + * then the canonical lexical representation of the {value constraint} + * value must be a valid default for the ·actual type definition· as + * defined in Element Default Valid (Immediate) (§3.3.6). + */ + /* + * NOTE: 'local' above means types acquired by xsi:type. + * NOTE: Although the *canonical* value is stated, it is not + * relevant if canonical or not. Additionally XML Schema 1.1 + * will removed this requirement as well. + */ + if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) { + + ret = xmlSchemaCheckCOSValidDefault(vctxt, + inode->decl->value, &(inode->val)); + if (ret != 0) { + if (ret < 0) { + VERROR_INT("xmlSchemaValidatorPopElem", + "calling xmlSchemaCheckCOSValidDefault()"); + goto internal_error; + } + goto end_elem; + } + /* + * Stop here, to avoid redundant validation of the value + * (see following). + */ + goto default_psvi; + } + /* + * cvc-elt (3.3.4) : 5.1.2 + * The element information item with the canonical lexical + * representation of the {value constraint} value used as its + * ·normalized value· must be ·valid· with respect to the + * ·actual type definition· as defined by Element Locally Valid (Type) + * (§3.3.4). + */ + if (WXS_IS_SIMPLE(inode->typeDef)) { + ret = xmlSchemaVCheckINodeDataType(vctxt, + inode, inode->typeDef, inode->decl->value); + } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) { + ret = xmlSchemaVCheckINodeDataType(vctxt, + inode, inode->typeDef->contentTypeDef, + inode->decl->value); + } + if (ret != 0) { + if (ret < 0) { + VERROR_INT("xmlSchemaValidatorPopElem", + "calling xmlSchemaVCheckCVCSimpleType()"); + goto internal_error; + } + goto end_elem; + } + +default_psvi: + /* + * PSVI: Create a text node on the instance element. + */ + if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) && + (inode->node != NULL)) { + xmlNodePtr textChild; + xmlChar *normValue; + /* + * VAL TODO: Normalize the value. + */ + normValue = xmlSchemaNormalizeValue(inode->typeDef, + inode->decl->value); + if (normValue != NULL) { + textChild = xmlNewText(BAD_CAST normValue); + xmlFree(normValue); + } else + textChild = xmlNewText(inode->decl->value); + if (textChild == NULL) { + VERROR_INT("xmlSchemaValidatorPopElem", + "calling xmlNewText()"); + goto internal_error; + } else + xmlAddChild(inode->node, textChild); + } + + } else if (! INODE_NILLED(inode)) { + /* + * 5.2.1 The element information item must be ·valid· with respect + * to the ·actual type definition· as defined by Element Locally + * Valid (Type) (§3.3.4). + */ + if (WXS_IS_SIMPLE(inode->typeDef)) { + /* + * SPEC (cvc-type) (3.1) + * "If the type definition is a simple type definition, ..." + * (3.1.3) "If clause 3.2 of Element Locally Valid + * (Element) (§3.3.4) did not apply, then the ·normalized value· + * must be ·valid· with respect to the type definition as defined + * by String Valid (§3.14.4). + */ + ret = xmlSchemaVCheckINodeDataType(vctxt, + inode, inode->typeDef, inode->value); + } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) { + /* + * SPEC (cvc-type) (3.2) "If the type definition is a complex type + * definition, then the element information item must be + * ·valid· with respect to the type definition as per + * Element Locally Valid (Complex Type) (§3.4.4);" + * + * SPEC (cvc-complex-type) (2.2) + * "If the {content type} is a simple type definition, ... + * the ·normalized value· of the element information item is + * ·valid· with respect to that simple type definition as + * defined by String Valid (§3.14.4)." + */ + ret = xmlSchemaVCheckINodeDataType(vctxt, + inode, inode->typeDef->contentTypeDef, inode->value); + } + if (ret != 0) { + if (ret < 0) { + VERROR_INT("xmlSchemaValidatorPopElem", + "calling xmlSchemaVCheckCVCSimpleType()"); + goto internal_error; + } + goto end_elem; + } + /* + * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has + * not applied, all of the following must be true: + */ + if ((inode->decl->value != NULL) && + (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) { + + /* + * TODO: We will need a computed value, when comparison is + * done on computed values. + */ + /* + * 5.2.2.1 The element information item must have no element + * information item [children]. + */ + if (inode->flags & + XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) { + ret = XML_SCHEMAV_CVC_ELT_5_2_2_1; + VERROR(ret, NULL, + "The content must not containt element nodes since " + "there is a fixed value constraint"); + goto end_elem; + } else { + /* + * 5.2.2.2 The appropriate case among the following must + * be true: + */ + if (WXS_HAS_MIXED_CONTENT(inode->typeDef)) { + /* + * 5.2.2.2.1 If the {content type} of the ·actual type + * definition· is mixed, then the *initial value* of the + * item must match the canonical lexical representation + * of the {value constraint} value. + * + * ... the *initial value* of an element information + * item is the string composed of, in order, the + * [character code] of each character information item in + * the [children] of that element information item. + */ + if (! xmlStrEqual(inode->value, inode->decl->value)){ + /* + * VAL TODO: Report invalid & expected values as well. + * VAL TODO: Implement the canonical stuff. + */ + ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1; + xmlSchemaCustomErr(ACTXT_CAST vctxt, + ret, NULL, NULL, + "The initial value '%s' does not match the fixed " + "value constraint '%s'", + inode->value, inode->decl->value); + goto end_elem; + } + } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) { + /* + * 5.2.2.2.2 If the {content type} of the ·actual type + * definition· is a simple type definition, then the + * *actual value* of the item must match the canonical + * lexical representation of the {value constraint} value. + */ + /* + * VAL TODO: *actual value* is the normalized value, impl. + * this. + * VAL TODO: Report invalid & expected values as well. + * VAL TODO: Implement a comparison with the computed values. + */ + if (! xmlStrEqual(inode->value, + inode->decl->value)) { + ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2; + xmlSchemaCustomErr(ACTXT_CAST vctxt, + ret, NULL, NULL, + "The actual value '%s' does not match the fixed " + "value constraint '%s'", + inode->value, + inode->decl->value); + goto end_elem; + } + } + } + } + } + +end_elem: + if (vctxt->depth < 0) { + /* TODO: raise error? */ + return (0); + } + if (vctxt->depth == vctxt->skipDepth) + vctxt->skipDepth = -1; + /* + * Evaluate the history of XPath state objects. + */ + if (inode->appliedXPath && + (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1)) + goto internal_error; + /* + * MAYBE TODO: + * SPEC (6) "The element information item must be ·valid· with + * respect to each of the {identity-constraint definitions} as per + * Identity-constraint Satisfied (§3.11.4)." + */ + /* + * PSVI TODO: If we expose IDC node-tables via PSVI then the tables + * need to be built in any case. + * We will currently build IDC node-tables and bubble them only if + * keyrefs do exist. + */ + + /* + * Add the current IDC target-nodes to the IDC node-tables. + */ + if ((inode->idcMatchers != NULL) && + (vctxt->hasKeyrefs || vctxt->createIDCNodeTables)) + { + if (xmlSchemaIDCFillNodeTables(vctxt, inode) == -1) + goto internal_error; + } + /* + * Validate IDC keyrefs. + */ + if (vctxt->inode->hasKeyrefs) + if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1) + goto internal_error; + /* + * Merge/free the IDC table. + */ + if (inode->idcTable != NULL) { +#ifdef DEBUG_IDC_NODE_TABLE + xmlSchemaDebugDumpIDCTable(stdout, + inode->nsName, + inode->localName, + inode->idcTable); +#endif + if ((vctxt->depth > 0) && + (vctxt->hasKeyrefs || vctxt->createIDCNodeTables)) + { + /* + * Merge the IDC node table with the table of the parent node. + */ + if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1) + goto internal_error; + } + } + /* + * Clear the current ielem. + * VAL TODO: Don't free the PSVI IDC tables if they are + * requested for the PSVI. + */ + xmlSchemaClearElemInfo(vctxt, inode); + /* + * Skip further processing if we are on the validation root. + */ + if (vctxt->depth == 0) { + vctxt->depth--; + vctxt->inode = NULL; + return (0); + } + /* + * Reset the keyrefDepth if needed. + */ + if (vctxt->aidcs != NULL) { + xmlSchemaIDCAugPtr aidc = vctxt->aidcs; + do { + if (aidc->keyrefDepth == vctxt->depth) { + /* + * A 'keyrefDepth' of a key/unique IDC matches the current + * depth, this means that we are leaving the scope of the + * top-most keyref IDC which refers to this IDC. + */ + aidc->keyrefDepth = -1; + } + aidc = aidc->next; + } while (aidc != NULL); + } + vctxt->depth--; + vctxt->inode = vctxt->elemInfos[vctxt->depth]; + /* + * VAL TODO: 7 If the element information item is the ·validation root·, it must be + * ·valid· per Validation Root Valid (ID/IDREF) (§3.3.4). + */ + return (ret); + +internal_error: + vctxt->err = -1; + return (-1); +} + +/* +* 3.4.4 Complex Type Definition Validation Rules +* Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type) +*/ +static int +xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt) +{ + xmlSchemaNodeInfoPtr pielem; + xmlSchemaTypePtr ptype; + int ret = 0; + + if (vctxt->depth <= 0) { + VERROR_INT("xmlSchemaValidateChildElem", + "not intended for the validation root"); + return (-1); + } + pielem = vctxt->elemInfos[vctxt->depth -1]; + if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) + pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY; + /* + * Handle 'nilled' elements. + */ + if (INODE_NILLED(pielem)) { + /* + * SPEC (cvc-elt) (3.3.4) : (3.2.1) + */ + ACTIVATE_PARENT_ELEM; + ret = XML_SCHEMAV_CVC_ELT_3_2_1; + VERROR(ret, NULL, + "Neither character nor element content is allowed, " + "because the element was 'nilled'"); + ACTIVATE_ELEM; + goto unexpected_elem; + } + + ptype = pielem->typeDef; + + if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) { + /* + * Workaround for "anyType": we have currently no content model + * assigned for "anyType", so handle it explicitely. + * "anyType" has an unbounded, lax "any" wildcard. + */ + vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema, + vctxt->inode->localName, + vctxt->inode->nsName); + + if (vctxt->inode->decl == NULL) { + xmlSchemaAttrInfoPtr iattr; + /* + * Process "xsi:type". + * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3) + */ + iattr = xmlSchemaGetMetaAttrInfo(vctxt, + XML_SCHEMA_ATTR_INFO_META_XSI_TYPE); + if (iattr != NULL) { + ret = xmlSchemaProcessXSIType(vctxt, iattr, + &(vctxt->inode->typeDef), NULL); + if (ret != 0) { + if (ret == -1) { + VERROR_INT("xmlSchemaValidateChildElem", + "calling xmlSchemaProcessXSIType() to " + "process the attribute 'xsi:nil'"); + return (-1); + } + return (ret); + } + } else { + /* + * Fallback to "anyType". + * + * SPEC (cvc-assess-elt) + * "If the item cannot be ·strictly assessed·, [...] + * an element information item's schema validity may be laxly + * assessed if its ·context-determined declaration· is not + * skip by ·validating· with respect to the ·ur-type + * definition· as per Element Locally Valid (Type) (§3.3.4)." + */ + vctxt->inode->typeDef = + xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE); + } + } + return (0); + } + + switch (ptype->contentType) { + case XML_SCHEMA_CONTENT_EMPTY: + /* + * SPEC (2.1) "If the {content type} is empty, then the + * element information item has no character or element + * information item [children]." + */ + ACTIVATE_PARENT_ELEM + ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1; + VERROR(ret, NULL, + "Element content is not allowed, " + "because the content type is empty"); + ACTIVATE_ELEM + goto unexpected_elem; + break; + + case XML_SCHEMA_CONTENT_MIXED: + case XML_SCHEMA_CONTENT_ELEMENTS: { + xmlRegExecCtxtPtr regexCtxt; + xmlChar *values[10]; + int terminal, nbval = 10, nbneg; + + /* VAL TODO: Optimized "anyType" validation.*/ + + if (ptype->contModel == NULL) { + VERROR_INT("xmlSchemaValidateChildElem", + "type has elem content but no content model"); + return (-1); + } + /* + * Safety belf for evaluation if the cont. model was already + * examined to be invalid. + */ + if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) { + VERROR_INT("xmlSchemaValidateChildElem", + "validating elem, but elem content is already invalid"); + return (-1); + } + + regexCtxt = pielem->regexCtxt; + if (regexCtxt == NULL) { + /* + * Create the regex context. + */ + regexCtxt = xmlRegNewExecCtxt(ptype->contModel, + (xmlRegExecCallbacks) xmlSchemaVContentModelCallback, + vctxt); + if (regexCtxt == NULL) { + VERROR_INT("xmlSchemaValidateChildElem", + "failed to create a regex context"); + return (-1); + } + pielem->regexCtxt = regexCtxt; +#ifdef DEBUG_AUTOMATA + xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'\n", + pielem->localName); +#endif + } + + /* + * SPEC (2.4) "If the {content type} is element-only or mixed, + * then the sequence of the element information item's + * element information item [children], if any, taken in + * order, is ·valid· with respect to the {content type}'s + * particle, as defined in Element Sequence Locally Valid + * (Particle) (§3.9.4)." + */ + ret = xmlRegExecPushString2(regexCtxt, + vctxt->inode->localName, + vctxt->inode->nsName, + vctxt->inode); +#ifdef DEBUG_AUTOMATA + if (ret < 0) + xmlGenericError(xmlGenericErrorContext, + "AUTOMATON push ERROR for '%s' on '%s'\n", + vctxt->inode->localName, pielem->localName); + else + xmlGenericError(xmlGenericErrorContext, + "AUTOMATON push OK for '%s' on '%s'\n", + vctxt->inode->localName, pielem->localName); +#endif + if (vctxt->err == XML_SCHEMAV_INTERNAL) { + VERROR_INT("xmlSchemaValidateChildElem", + "calling xmlRegExecPushString2()"); + return (-1); + } + if (ret < 0) { + xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg, + &values[0], &terminal); + xmlSchemaComplexTypeErr(ACTXT_CAST vctxt, + XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL, + "This element is not expected", + nbval, nbneg, values); + ret = vctxt->err; + goto unexpected_elem; + } else + ret = 0; + } + break; + case XML_SCHEMA_CONTENT_SIMPLE: + case XML_SCHEMA_CONTENT_BASIC: + ACTIVATE_PARENT_ELEM + if (WXS_IS_COMPLEX(ptype)) { + /* + * SPEC (cvc-complex-type) (2.2) + * "If the {content type} is a simple type definition, then + * the element information item has no element information + * item [children], ..." + */ + ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2; + VERROR(ret, NULL, "Element content is not allowed, " + "because the content type is a simple type definition"); + } else { + /* + * SPEC (cvc-type) (3.1.2) "The element information item must + * have no element information item [children]." + */ + ret = XML_SCHEMAV_CVC_TYPE_3_1_2; + VERROR(ret, NULL, "Element content is not allowed, " + "because the type definition is simple"); + } + ACTIVATE_ELEM + ret = vctxt->err; + goto unexpected_elem; + break; + + default: + break; + } + return (ret); +unexpected_elem: + /* + * Pop this element and set the skipDepth to skip + * all further content of the parent element. + */ + vctxt->skipDepth = vctxt->depth; + vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED; + pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT; + return (ret); +} + +#define XML_SCHEMA_PUSH_TEXT_PERSIST 1 +#define XML_SCHEMA_PUSH_TEXT_CREATED 2 +#define XML_SCHEMA_PUSH_TEXT_VOLATILE 3 + +static int +xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt, + int nodeType, const xmlChar *value, int len, + int mode, int *consumed) +{ + /* + * Unfortunately we have to duplicate the text sometimes. + * OPTIMIZE: Maybe we could skip it, if: + * 1. content type is simple + * 2. whitespace is "collapse" + * 3. it consists of whitespace only + * + * Process character content. + */ + if (consumed != NULL) + *consumed = 0; + if (INODE_NILLED(vctxt->inode)) { + /* + * SPEC cvc-elt (3.3.4 - 3.2.1) + * "The element information item must have no character or + * element information item [children]." + */ + VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL, + "Neither character nor element content is allowed " + "because the element is 'nilled'"); + return (vctxt->err); + } + /* + * SPEC (2.1) "If the {content type} is empty, then the + * element information item has no character or element + * information item [children]." + */ + if (vctxt->inode->typeDef->contentType == + XML_SCHEMA_CONTENT_EMPTY) { + VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL, + "Character content is not allowed, " + "because the content type is empty"); + return (vctxt->err); + } + + if (vctxt->inode->typeDef->contentType == + XML_SCHEMA_CONTENT_ELEMENTS) { + if ((nodeType != XML_TEXT_NODE) || + (! xmlSchemaIsBlank((xmlChar *) value, len))) { + /* + * SPEC cvc-complex-type (2.3) + * "If the {content type} is element-only, then the + * element information item has no character information + * item [children] other than those whose [character + * code] is defined as a white space in [XML 1.0 (Second + * Edition)]." + */ + VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL, + "Character content other than whitespace is not allowed " + "because the content type is 'element-only'"); + return (vctxt->err); + } + return (0); + } + + if ((value == NULL) || (value[0] == 0)) + return (0); + /* + * Save the value. + * NOTE that even if the content type is *mixed*, we need the + * *initial value* for default/fixed value constraints. + */ + if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) && + ((vctxt->inode->decl == NULL) || + (vctxt->inode->decl->value == NULL))) + return (0); + + if (vctxt->inode->value == NULL) { + /* + * Set the value. + */ + switch (mode) { + case XML_SCHEMA_PUSH_TEXT_PERSIST: + /* + * When working on a tree. + */ + vctxt->inode->value = value; + break; + case XML_SCHEMA_PUSH_TEXT_CREATED: + /* + * When working with the reader. + * The value will be freed by the element info. + */ + vctxt->inode->value = value; + if (consumed != NULL) + *consumed = 1; + vctxt->inode->flags |= + XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES; + break; + case XML_SCHEMA_PUSH_TEXT_VOLATILE: + /* + * When working with SAX. + * The value will be freed by the element info. + */ + if (len != -1) + vctxt->inode->value = BAD_CAST xmlStrndup(value, len); + else + vctxt->inode->value = BAD_CAST xmlStrdup(value); + vctxt->inode->flags |= + XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES; + break; + default: + break; + } + } else { + if (len < 0) + len = xmlStrlen(value); + /* + * Concat the value. + */ + if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) { + vctxt->inode->value = BAD_CAST xmlStrncat( + (xmlChar *) vctxt->inode->value, value, len); + } else { + vctxt->inode->value = + BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len); + vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES; + } + } + + return (0); +} + +static int +xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt) +{ + int ret = 0; + + if ((vctxt->skipDepth != -1) && + (vctxt->depth >= vctxt->skipDepth)) { + VERROR_INT("xmlSchemaValidateElem", + "in skip-state"); + goto internal_error; + } + if (vctxt->xsiAssemble) { + /* + * We will stop validation if there was an error during + * dynamic schema construction. + * Note that we simply set @skipDepth to 0, this could + * mean that a streaming document via SAX would be + * still read to the end but it won't be validated any more. + * TODO: If we are sure how to stop the validation at once + * for all input scenarios, then this should be changed to + * instantly stop the validation. + */ + ret = xmlSchemaAssembleByXSI(vctxt); + if (ret != 0) { + if (ret == -1) + goto internal_error; + vctxt->skipDepth = 0; + return(ret); + } + } + if (vctxt->depth > 0) { + /* + * Validate this element against the content model + * of the parent. + */ + ret = xmlSchemaValidateChildElem(vctxt); + if (ret != 0) { + if (ret < 0) { + VERROR_INT("xmlSchemaValidateElem", + "calling xmlSchemaStreamValidateChildElement()"); + goto internal_error; + } + goto exit; + } + if (vctxt->depth == vctxt->skipDepth) + goto exit; + if ((vctxt->inode->decl == NULL) && + (vctxt->inode->typeDef == NULL)) { + VERROR_INT("xmlSchemaValidateElem", + "the child element was valid but neither the " + "declaration nor the type was set"); + goto internal_error; + } + } else { + /* + * Get the declaration of the validation root. + */ + vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema, + vctxt->inode->localName, + vctxt->inode->nsName); + if (vctxt->inode->decl == NULL) { + ret = XML_SCHEMAV_CVC_ELT_1; + VERROR(ret, NULL, + "No matching global declaration available " + "for the validation root"); + goto exit; + } + } + + if (vctxt->inode->decl == NULL) + goto type_validation; + + if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) { + int skip; + /* + * Wildcards. + */ + ret = xmlSchemaValidateElemWildcard(vctxt, &skip); + if (ret != 0) { + if (ret < 0) { + VERROR_INT("xmlSchemaValidateElem", + "calling xmlSchemaValidateElemWildcard()"); + goto internal_error; + } + goto exit; + } + if (skip) { + vctxt->skipDepth = vctxt->depth; + goto exit; + } + /* + * The declaration might be set by the wildcard validation, + * when the processContents is "lax" or "strict". + */ + if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) { + /* + * Clear the "decl" field to not confuse further processing. + */ + vctxt->inode->decl = NULL; + goto type_validation; + } + } + /* + * Validate against the declaration. + */ + ret = xmlSchemaValidateElemDecl(vctxt); + if (ret != 0) { + if (ret < 0) { + VERROR_INT("xmlSchemaValidateElem", + "calling xmlSchemaValidateElemDecl()"); + goto internal_error; + } + goto exit; + } + /* + * Validate against the type definition. + */ +type_validation: + + if (vctxt->inode->typeDef == NULL) { + vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE; + ret = XML_SCHEMAV_CVC_TYPE_1; + VERROR(ret, NULL, + "The type definition is absent"); + goto exit; + } + if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) { + vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE; + ret = XML_SCHEMAV_CVC_TYPE_2; + VERROR(ret, NULL, + "The type definition is abstract"); + goto exit; + } + /* + * Evaluate IDCs. Do it here, since new IDC matchers are registered + * during validation against the declaration. This must be done + * _before_ attribute validation. + */ + if (vctxt->xpathStates != NULL) { + ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE); + vctxt->inode->appliedXPath = 1; + if (ret == -1) { + VERROR_INT("xmlSchemaValidateElem", + "calling xmlSchemaXPathEvaluate()"); + goto internal_error; + } + } + /* + * Validate attributes. + */ + if (WXS_IS_COMPLEX(vctxt->inode->typeDef)) { + if ((vctxt->nbAttrInfos != 0) || + (vctxt->inode->typeDef->attrUses != NULL)) { + + ret = xmlSchemaVAttributesComplex(vctxt); + } + } else if (vctxt->nbAttrInfos != 0) { + + ret = xmlSchemaVAttributesSimple(vctxt); + } + /* + * Clear registered attributes. + */ + if (vctxt->nbAttrInfos != 0) + xmlSchemaClearAttrInfos(vctxt); + if (ret == -1) { + VERROR_INT("xmlSchemaValidateElem", + "calling attributes validation"); + goto internal_error; + } + /* + * Don't return an error if attributes are invalid on purpose. + */ + ret = 0; + +exit: + if (ret != 0) + vctxt->skipDepth = vctxt->depth; + return (ret); +internal_error: + return (-1); +} + +#ifdef XML_SCHEMA_READER_ENABLED +static int +xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt) +{ + const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15; + int depth, nodeType, ret = 0, consumed; + xmlSchemaNodeInfoPtr ielem; + + vctxt->depth = -1; + ret = xmlTextReaderRead(vctxt->reader); + /* + * Move to the document element. + */ + while (ret == 1) { + nodeType = xmlTextReaderNodeType(vctxt->reader); + if (nodeType == XML_ELEMENT_NODE) + goto root_found; + ret = xmlTextReaderRead(vctxt->reader); + } + goto exit; + +root_found: + + do { + depth = xmlTextReaderDepth(vctxt->reader); + nodeType = xmlTextReaderNodeType(vctxt->reader); + + if (nodeType == XML_ELEMENT_NODE) { + + vctxt->depth++; + if (xmlSchemaValidatorPushElem(vctxt) == -1) { + VERROR_INT("xmlSchemaVReaderWalk", + "calling xmlSchemaValidatorPushElem()"); + goto internal_error; + } + ielem = vctxt->inode; + ielem->localName = xmlTextReaderLocalName(vctxt->reader); + ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader); + ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES; + /* + * Is the element empty? + */ + ret = xmlTextReaderIsEmptyElement(vctxt->reader); + if (ret == -1) { + VERROR_INT("xmlSchemaVReaderWalk", + "calling xmlTextReaderIsEmptyElement()"); + goto internal_error; + } + if (ret) { + ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY; + } + /* + * Register attributes. + */ + vctxt->nbAttrInfos = 0; + ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader); + if (ret == -1) { + VERROR_INT("xmlSchemaVReaderWalk", + "calling xmlTextReaderMoveToFirstAttribute()"); + goto internal_error; + } + if (ret == 1) { + do { + /* + * VAL TODO: How do we know that the reader works on a + * node tree, to be able to pass a node here? + */ + if (xmlSchemaValidatorPushAttribute(vctxt, NULL, + (const xmlChar *) xmlTextReaderLocalName(vctxt->reader), + xmlTextReaderNamespaceUri(vctxt->reader), 1, + xmlTextReaderValue(vctxt->reader), 1) == -1) { + + VERROR_INT("xmlSchemaVReaderWalk", + "calling xmlSchemaValidatorPushAttribute()"); + goto internal_error; + } + ret = xmlTextReaderMoveToNextAttribute(vctxt->reader); + if (ret == -1) { + VERROR_INT("xmlSchemaVReaderWalk", + "calling xmlTextReaderMoveToFirstAttribute()"); + goto internal_error; + } + } while (ret == 1); + /* + * Back to element position. + */ + ret = xmlTextReaderMoveToElement(vctxt->reader); + if (ret == -1) { + VERROR_INT("xmlSchemaVReaderWalk", + "calling xmlTextReaderMoveToElement()"); + goto internal_error; + } + } + /* + * Validate the element. + */ + ret= xmlSchemaValidateElem(vctxt); + if (ret != 0) { + if (ret == -1) { + VERROR_INT("xmlSchemaVReaderWalk", + "calling xmlSchemaValidateElem()"); + goto internal_error; + } + goto exit; + } + if (vctxt->depth == vctxt->skipDepth) { + int curDepth; + /* + * Skip all content. + */ + if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) { + ret = xmlTextReaderRead(vctxt->reader); + curDepth = xmlTextReaderDepth(vctxt->reader); + while ((ret == 1) && (curDepth != depth)) { + ret = xmlTextReaderRead(vctxt->reader); + curDepth = xmlTextReaderDepth(vctxt->reader); + } + if (ret < 0) { + /* + * VAL TODO: A reader error occured; what to do here? + */ + ret = 1; + goto exit; + } + } + goto leave_elem; + } + /* + * READER VAL TODO: Is an END_ELEM really never called + * if the elem is empty? + */ + if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) + goto leave_elem; + } else if (nodeType == END_ELEM) { + /* + * Process END of element. + */ +leave_elem: + ret = xmlSchemaValidatorPopElem(vctxt); + if (ret != 0) { + if (ret < 0) { + VERROR_INT("xmlSchemaVReaderWalk", + "calling xmlSchemaValidatorPopElem()"); + goto internal_error; + } + goto exit; + } + if (vctxt->depth >= 0) + ielem = vctxt->inode; + else + ielem = NULL; + } else if ((nodeType == XML_TEXT_NODE) || + (nodeType == XML_CDATA_SECTION_NODE) || + (nodeType == WHTSP) || + (nodeType == SIGN_WHTSP)) { + /* + * Process character content. + */ + xmlChar *value; + + if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP)) + nodeType = XML_TEXT_NODE; + + value = xmlTextReaderValue(vctxt->reader); + ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value, + -1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed); + if (! consumed) + xmlFree(value); + if (ret == -1) { + VERROR_INT("xmlSchemaVReaderWalk", + "calling xmlSchemaVPushText()"); + goto internal_error; + } + } else if ((nodeType == XML_ENTITY_NODE) || + (nodeType == XML_ENTITY_REF_NODE)) { + /* + * VAL TODO: What to do with entities? + */ + TODO + } + /* + * Read next node. + */ + ret = xmlTextReaderRead(vctxt->reader); + } while (ret == 1); + +exit: + return (ret); +internal_error: + return (-1); +} +#endif + +/************************************************************************ + * * + * SAX validation handlers * + * * + ************************************************************************/ + +/* +* Process text content. +*/ +static void +xmlSchemaSAXHandleText(void *ctx, + const xmlChar * ch, + int len) +{ + xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx; + + if (vctxt->depth < 0) + return; + if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth)) + return; + if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) + vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY; + if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len, + XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) { + VERROR_INT("xmlSchemaSAXHandleCDataSection", + "calling xmlSchemaVPushText()"); + vctxt->err = -1; + xmlStopParser(vctxt->parserCtxt); + } +} + +/* +* Process CDATA content. +*/ +static void +xmlSchemaSAXHandleCDataSection(void *ctx, + const xmlChar * ch, + int len) +{ + xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx; + + if (vctxt->depth < 0) + return; + if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth)) + return; + if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) + vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY; + if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len, + XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) { + VERROR_INT("xmlSchemaSAXHandleCDataSection", + "calling xmlSchemaVPushText()"); + vctxt->err = -1; + xmlStopParser(vctxt->parserCtxt); + } +} + +static void +xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED, + const xmlChar * name ATTRIBUTE_UNUSED) +{ + xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx; + + if (vctxt->depth < 0) + return; + if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth)) + return; + /* SAX VAL TODO: What to do here? */ + TODO +} + +static void +xmlSchemaSAXHandleStartElementNs(void *ctx, + const xmlChar * localname, + const xmlChar * prefix ATTRIBUTE_UNUSED, + const xmlChar * URI, + int nb_namespaces, + const xmlChar ** namespaces, + int nb_attributes, + int nb_defaulted ATTRIBUTE_UNUSED, + const xmlChar ** attributes) +{ + xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx; + int ret; + xmlSchemaNodeInfoPtr ielem; + int i, j; + + /* + * SAX VAL TODO: What to do with nb_defaulted? + */ + /* + * Skip elements if inside a "skip" wildcard or invalid. + */ + vctxt->depth++; + if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth)) + return; + /* + * Push the element. + */ + if (xmlSchemaValidatorPushElem(vctxt) == -1) { + VERROR_INT("xmlSchemaSAXHandleStartElementNs", + "calling xmlSchemaValidatorPushElem()"); + goto internal_error; + } + ielem = vctxt->inode; + /* + * TODO: Is this OK? + */ + ielem->nodeLine = xmlSAX2GetLineNumber(vctxt->parserCtxt); + ielem->localName = localname; + ielem->nsName = URI; + ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY; + /* + * Register namespaces on the elem info. + */ + if (nb_namespaces != 0) { + /* + * Although the parser builds its own namespace list, + * we have no access to it, so we'll use an own one. + */ + for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) { + /* + * Store prefix and namespace name. + */ + if (ielem->nsBindings == NULL) { + ielem->nsBindings = + (const xmlChar **) xmlMalloc(10 * + sizeof(const xmlChar *)); + if (ielem->nsBindings == NULL) { + xmlSchemaVErrMemory(vctxt, + "allocating namespace bindings for SAX validation", + NULL); + goto internal_error; + } + ielem->nbNsBindings = 0; + ielem->sizeNsBindings = 5; + } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) { + ielem->sizeNsBindings *= 2; + ielem->nsBindings = + (const xmlChar **) xmlRealloc( + (void *) ielem->nsBindings, + ielem->sizeNsBindings * 2 * sizeof(const xmlChar *)); + if (ielem->nsBindings == NULL) { + xmlSchemaVErrMemory(vctxt, + "re-allocating namespace bindings for SAX validation", + NULL); + goto internal_error; + } + } + + ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j]; + if (namespaces[j+1][0] == 0) { + /* + * Handle xmlns="". + */ + ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL; + } else + ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = + namespaces[j+1]; + ielem->nbNsBindings++; + } + } + /* + * Register attributes. + * SAX VAL TODO: We are not adding namespace declaration + * attributes yet. + */ + if (nb_attributes != 0) { + xmlChar *value; + + for (j = 0, i = 0; i < nb_attributes; i++, j += 5) { + /* + * Duplicate the value. + */ + value = xmlStrndup(attributes[j+3], + attributes[j+4] - attributes[j+3]); + /* + * TODO: Set the node line. + */ + ret = xmlSchemaValidatorPushAttribute(vctxt, + NULL, ielem->nodeLine, attributes[j], attributes[j+2], 0, + value, 1); + if (ret == -1) { + VERROR_INT("xmlSchemaSAXHandleStartElementNs", + "calling xmlSchemaValidatorPushAttribute()"); + goto internal_error; + } + } + } + /* + * Validate the element. + */ + ret = xmlSchemaValidateElem(vctxt); + if (ret != 0) { + if (ret == -1) { + VERROR_INT("xmlSchemaSAXHandleStartElementNs", + "calling xmlSchemaValidateElem()"); + goto internal_error; + } + goto exit; + } + +exit: + return; +internal_error: + vctxt->err = -1; + xmlStopParser(vctxt->parserCtxt); + return; +} + +static void +xmlSchemaSAXHandleEndElementNs(void *ctx, + const xmlChar * localname ATTRIBUTE_UNUSED, + const xmlChar * prefix ATTRIBUTE_UNUSED, + const xmlChar * URI ATTRIBUTE_UNUSED) +{ + xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx; + int res; + + /* + * Skip elements if inside a "skip" wildcard or if invalid. + */ + if (vctxt->skipDepth != -1) { + if (vctxt->depth > vctxt->skipDepth) { + vctxt->depth--; + return; + } else + vctxt->skipDepth = -1; + } + /* + * SAX VAL TODO: Just a temporary check. + */ + if ((!xmlStrEqual(vctxt->inode->localName, localname)) || + (!xmlStrEqual(vctxt->inode->nsName, URI))) { + VERROR_INT("xmlSchemaSAXHandleEndElementNs", + "elem pop mismatch"); + } + res = xmlSchemaValidatorPopElem(vctxt); + if (res != 0) { + if (res < 0) { + VERROR_INT("xmlSchemaSAXHandleEndElementNs", + "calling xmlSchemaValidatorPopElem()"); + goto internal_error; + } + goto exit; + } +exit: + return; +internal_error: + vctxt->err = -1; + xmlStopParser(vctxt->parserCtxt); + return; +} + +/************************************************************************ + * * + * Validation interfaces * + * * + ************************************************************************/ + +/** + * xmlSchemaNewValidCtxt: + * @schema: a precompiled XML Schemas + * + * Create an XML Schemas validation context based on the given schema. + * + * Returns the validation context or NULL in case of error + */ +xmlSchemaValidCtxtPtr +xmlSchemaNewValidCtxt(xmlSchemaPtr schema) +{ + xmlSchemaValidCtxtPtr ret; + + ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt)); + if (ret == NULL) { + xmlSchemaVErrMemory(NULL, "allocating validation context", NULL); + return (NULL); + } + memset(ret, 0, sizeof(xmlSchemaValidCtxt)); + ret->type = XML_SCHEMA_CTXT_VALIDATOR; + ret->dict = xmlDictCreate(); + ret->nodeQNames = xmlSchemaItemListCreate(); + ret->schema = schema; + return (ret); +} + +/** + * xmlSchemaClearValidCtxt: + * @ctxt: the schema validation context + * + * Free the resources associated to the schema validation context; + * leaves some fields alive intended for reuse of the context. + */ +static void +xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt) +{ + if (vctxt == NULL) + return; + + /* + * TODO: Should we clear the flags? + * Might be problematic if one reuses the context + * and assumes that the options remain the same. + */ + vctxt->flags = 0; + vctxt->validationRoot = NULL; + vctxt->doc = NULL; +#ifdef LIBXML_READER_ENABLED + vctxt->reader = NULL; +#endif + vctxt->hasKeyrefs = 0; + + if (vctxt->value != NULL) { + xmlSchemaFreeValue(vctxt->value); + vctxt->value = NULL; + } + /* + * Augmented IDC information. + */ + if (vctxt->aidcs != NULL) { + xmlSchemaIDCAugPtr cur = vctxt->aidcs, next; + do { + next = cur->next; + xmlFree(cur); + cur = next; + } while (cur != NULL); + vctxt->aidcs = NULL; + } + if (vctxt->idcMatcherCache != NULL) { + xmlSchemaIDCMatcherPtr matcher = vctxt->idcMatcherCache, tmp; + + while (matcher) { + tmp = matcher; + matcher = matcher->nextCached; + xmlSchemaIDCFreeMatcherList(tmp); + } + vctxt->idcMatcherCache = NULL; + } + + + if (vctxt->idcNodes != NULL) { + int i; + xmlSchemaPSVIIDCNodePtr item; + + for (i = 0; i < vctxt->nbIdcNodes; i++) { + item = vctxt->idcNodes[i]; + xmlFree(item->keys); + xmlFree(item); + } + xmlFree(vctxt->idcNodes); + vctxt->idcNodes = NULL; + vctxt->nbIdcNodes = 0; + vctxt->sizeIdcNodes = 0; + } + /* + * Note that we won't delete the XPath state pool here. + */ + if (vctxt->xpathStates != NULL) { + xmlSchemaFreeIDCStateObjList(vctxt->xpathStates); + vctxt->xpathStates = NULL; + } + /* + * Attribute info. + */ + if (vctxt->nbAttrInfos != 0) { + xmlSchemaClearAttrInfos(vctxt); + } + /* + * Element info. + */ + if (vctxt->elemInfos != NULL) { + int i; + xmlSchemaNodeInfoPtr ei; + + for (i = 0; i < vctxt->sizeElemInfos; i++) { + ei = vctxt->elemInfos[i]; + if (ei == NULL) + break; + xmlSchemaClearElemInfo(vctxt, ei); + } + } + xmlSchemaItemListClear(vctxt->nodeQNames); + /* Recreate the dict. */ + xmlDictFree(vctxt->dict); + /* + * TODO: Is is save to recreate it? Do we have a scenario + * where the user provides the dict? + */ + vctxt->dict = xmlDictCreate(); +} + +/** + * xmlSchemaFreeValidCtxt: + * @ctxt: the schema validation context + * + * Free the resources associated to the schema validation context + */ +void +xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt) +{ + if (ctxt == NULL) + return; + if (ctxt->value != NULL) + xmlSchemaFreeValue(ctxt->value); + if (ctxt->pctxt != NULL) + xmlSchemaFreeParserCtxt(ctxt->pctxt); + if (ctxt->idcNodes != NULL) { + int i; + xmlSchemaPSVIIDCNodePtr item; + + for (i = 0; i < ctxt->nbIdcNodes; i++) { + item = ctxt->idcNodes[i]; + xmlFree(item->keys); + xmlFree(item); + } + xmlFree(ctxt->idcNodes); + } + if (ctxt->idcKeys != NULL) { + int i; + for (i = 0; i < ctxt->nbIdcKeys; i++) + xmlSchemaIDCFreeKey(ctxt->idcKeys[i]); + xmlFree(ctxt->idcKeys); + } + + if (ctxt->xpathStates != NULL) { + xmlSchemaFreeIDCStateObjList(ctxt->xpathStates); + ctxt->xpathStates = NULL; + } + if (ctxt->xpathStatePool != NULL) { + xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool); + ctxt->xpathStatePool = NULL; + } + + /* + * Augmented IDC information. + */ + if (ctxt->aidcs != NULL) { + xmlSchemaIDCAugPtr cur = ctxt->aidcs, next; + do { + next = cur->next; + xmlFree(cur); + cur = next; + } while (cur != NULL); + } + if (ctxt->attrInfos != NULL) { + int i; + xmlSchemaAttrInfoPtr attr; + + /* Just a paranoid call to the cleanup. */ + if (ctxt->nbAttrInfos != 0) + xmlSchemaClearAttrInfos(ctxt); + for (i = 0; i < ctxt->sizeAttrInfos; i++) { + attr = ctxt->attrInfos[i]; + xmlFree(attr); + } + xmlFree(ctxt->attrInfos); + } + if (ctxt->elemInfos != NULL) { + int i; + xmlSchemaNodeInfoPtr ei; + + for (i = 0; i < ctxt->sizeElemInfos; i++) { + ei = ctxt->elemInfos[i]; + if (ei == NULL) + break; + xmlSchemaClearElemInfo(ctxt, ei); + xmlFree(ei); + } + xmlFree(ctxt->elemInfos); + } + if (ctxt->nodeQNames != NULL) + xmlSchemaItemListFree(ctxt->nodeQNames); + if (ctxt->dict != NULL) + xmlDictFree(ctxt->dict); + xmlFree(ctxt); +} + +/** + * xmlSchemaIsValid: + * @ctxt: the schema validation context + * + * Check if any error was detected during validation. + * + * Returns 1 if valid so far, 0 if errors were detected, and -1 in case + * of internal error. + */ +int +xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt) +{ + if (ctxt == NULL) + return(-1); + return(ctxt->err == 0); +} + +/** + * xmlSchemaSetValidErrors: + * @ctxt: a schema validation context + * @err: the error function + * @warn: the warning function + * @ctx: the functions context + * + * Set the error and warning callback informations + */ +void +xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt, + xmlSchemaValidityErrorFunc err, + xmlSchemaValidityWarningFunc warn, void *ctx) +{ + if (ctxt == NULL) + return; + ctxt->error = err; + ctxt->warning = warn; + ctxt->errCtxt = ctx; + if (ctxt->pctxt != NULL) + xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx); +} + +/** + * xmlSchemaSetValidStructuredErrors: + * @ctxt: a schema validation context + * @serror: the structured error function + * @ctx: the functions context + * + * Set the structured error callback + */ +void +xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt, + xmlStructuredErrorFunc serror, void *ctx) +{ + if (ctxt == NULL) + return; + ctxt->serror = serror; + ctxt->error = NULL; + ctxt->warning = NULL; + ctxt->errCtxt = ctx; + if (ctxt->pctxt != NULL) + xmlSchemaSetParserStructuredErrors(ctxt->pctxt, serror, ctx); +} + +/** + * xmlSchemaGetValidErrors: + * @ctxt: a XML-Schema validation context + * @err: the error function result + * @warn: the warning function result + * @ctx: the functions context result + * + * Get the error and warning callback informations + * + * Returns -1 in case of error and 0 otherwise + */ +int +xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt, + xmlSchemaValidityErrorFunc * err, + xmlSchemaValidityWarningFunc * warn, void **ctx) +{ + if (ctxt == NULL) + return (-1); + if (err != NULL) + *err = ctxt->error; + if (warn != NULL) + *warn = ctxt->warning; + if (ctx != NULL) + *ctx = ctxt->errCtxt; + return (0); +} + + +/** + * xmlSchemaSetValidOptions: + * @ctxt: a schema validation context + * @options: a combination of xmlSchemaValidOption + * + * Sets the options to be used during the validation. + * + * Returns 0 in case of success, -1 in case of an + * API error. + */ +int +xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt, + int options) + +{ + int i; + + if (ctxt == NULL) + return (-1); + /* + * WARNING: Change the start value if adding to the + * xmlSchemaValidOption. + * TODO: Is there an other, more easy to maintain, + * way? + */ + for (i = 1; i < (int) sizeof(int) * 8; i++) { + if (options & 1<options = options; + return (0); +} + +/** + * xmlSchemaValidCtxtGetOptions: + * @ctxt: a schema validation context + * + * Get the validation context options. + * + * Returns the option combination or -1 on error. + */ +int +xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt) + +{ + if (ctxt == NULL) + return (-1); + else + return (ctxt->options); +} + +static int +xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt) +{ + xmlAttrPtr attr; + int ret = 0; + xmlSchemaNodeInfoPtr ielem = NULL; + xmlNodePtr node, valRoot; + const xmlChar *nsName; + + /* DOC VAL TODO: Move this to the start function. */ + valRoot = xmlDocGetRootElement(vctxt->doc); + if (valRoot == NULL) { + /* VAL TODO: Error code? */ + VERROR(1, NULL, "The document has no document element"); + return (1); + } + vctxt->depth = -1; + vctxt->validationRoot = valRoot; + node = valRoot; + while (node != NULL) { + if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth)) + goto next_sibling; + if (node->type == XML_ELEMENT_NODE) { + + /* + * Init the node-info. + */ + vctxt->depth++; + if (xmlSchemaValidatorPushElem(vctxt) == -1) + goto internal_error; + ielem = vctxt->inode; + ielem->node = node; + ielem->nodeLine = node->line; + ielem->localName = node->name; + if (node->ns != NULL) + ielem->nsName = node->ns->href; + ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY; + /* + * Register attributes. + * DOC VAL TODO: We do not register namespace declaration + * attributes yet. + */ + vctxt->nbAttrInfos = 0; + if (node->properties != NULL) { + attr = node->properties; + do { + if (attr->ns != NULL) + nsName = attr->ns->href; + else + nsName = NULL; + ret = xmlSchemaValidatorPushAttribute(vctxt, + (xmlNodePtr) attr, + /* + * Note that we give it the line number of the + * parent element. + */ + ielem->nodeLine, + attr->name, nsName, 0, + xmlNodeListGetString(attr->doc, attr->children, 1), 1); + if (ret == -1) { + VERROR_INT("xmlSchemaDocWalk", + "calling xmlSchemaValidatorPushAttribute()"); + goto internal_error; + } + attr = attr->next; + } while (attr); + } + /* + * Validate the element. + */ + ret = xmlSchemaValidateElem(vctxt); + if (ret != 0) { + if (ret == -1) { + VERROR_INT("xmlSchemaDocWalk", + "calling xmlSchemaValidateElem()"); + goto internal_error; + } + /* + * Don't stop validation; just skip the content + * of this element. + */ + goto leave_node; + } + if ((vctxt->skipDepth != -1) && + (vctxt->depth >= vctxt->skipDepth)) + goto leave_node; + } else if ((node->type == XML_TEXT_NODE) || + (node->type == XML_CDATA_SECTION_NODE)) { + /* + * Process character content. + */ + if ((ielem != NULL) && (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)) + ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY; + ret = xmlSchemaVPushText(vctxt, node->type, node->content, + -1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL); + if (ret < 0) { + VERROR_INT("xmlSchemaVDocWalk", + "calling xmlSchemaVPushText()"); + goto internal_error; + } + /* + * DOC VAL TODO: Should we skip further validation of the + * element content here? + */ + } else if ((node->type == XML_ENTITY_NODE) || + (node->type == XML_ENTITY_REF_NODE)) { + /* + * DOC VAL TODO: What to do with entities? + */ + VERROR_INT("xmlSchemaVDocWalk", + "there is at least one entity reference in the node-tree " + "currently being validated. Processing of entities with " + "this XML Schema processor is not supported (yet). Please " + "substitute entities before validation."); + goto internal_error; + } else { + goto leave_node; + /* + * DOC VAL TODO: XInclude nodes, etc. + */ + } + /* + * Walk the doc. + */ + if (node->children != NULL) { + node = node->children; + continue; + } +leave_node: + if (node->type == XML_ELEMENT_NODE) { + /* + * Leaving the scope of an element. + */ + if (node != vctxt->inode->node) { + VERROR_INT("xmlSchemaVDocWalk", + "element position mismatch"); + goto internal_error; + } + ret = xmlSchemaValidatorPopElem(vctxt); + if (ret != 0) { + if (ret < 0) { + VERROR_INT("xmlSchemaVDocWalk", + "calling xmlSchemaValidatorPopElem()"); + goto internal_error; + } + } + if (node == valRoot) + goto exit; + } +next_sibling: + if (node->next != NULL) + node = node->next; + else { + node = node->parent; + goto leave_node; + } + } + +exit: + return (ret); +internal_error: + return (-1); +} + +static int +xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt) { + /* + * Some initialization. + */ + vctxt->err = 0; + vctxt->nberrors = 0; + vctxt->depth = -1; + vctxt->skipDepth = -1; + vctxt->xsiAssemble = 0; + vctxt->hasKeyrefs = 0; +#ifdef ENABLE_IDC_NODE_TABLES_TEST + vctxt->createIDCNodeTables = 1; +#else + vctxt->createIDCNodeTables = 0; +#endif + /* + * Create a schema + parser if necessary. + */ + if (vctxt->schema == NULL) { + xmlSchemaParserCtxtPtr pctxt; + + vctxt->xsiAssemble = 1; + /* + * If not schema was given then we will create a schema + * dynamically using XSI schema locations. + * + * Create the schema parser context. + */ + if ((vctxt->pctxt == NULL) && + (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1)) + return (-1); + pctxt = vctxt->pctxt; + pctxt->xsiAssemble = 1; + /* + * Create the schema. + */ + vctxt->schema = xmlSchemaNewSchema(pctxt); + if (vctxt->schema == NULL) + return (-1); + /* + * Create the schema construction context. + */ + pctxt->constructor = xmlSchemaConstructionCtxtCreate(pctxt->dict); + if (pctxt->constructor == NULL) + return(-1); + pctxt->constructor->mainSchema = vctxt->schema; + /* + * Take ownership of the constructor to be able to free it. + */ + pctxt->ownsConstructor = 1; + } + /* + * Augment the IDC definitions. + */ + if (vctxt->schema->idcDef != NULL) { + xmlHashScan(vctxt->schema->idcDef, + (xmlHashScanner) xmlSchemaAugmentIDC, vctxt); + } + return(0); +} + +static void +xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt) { + if (vctxt->xsiAssemble) { + if (vctxt->schema != NULL) { + xmlSchemaFree(vctxt->schema); + vctxt->schema = NULL; + } + } + xmlSchemaClearValidCtxt(vctxt); +} + +static int +xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt) +{ + int ret = 0; + + if (xmlSchemaPreRun(vctxt) < 0) + return(-1); + + if (vctxt->doc != NULL) { + /* + * Tree validation. + */ + ret = xmlSchemaVDocWalk(vctxt); +#ifdef LIBXML_READER_ENABLED + } else if (vctxt->reader != NULL) { + /* + * XML Reader validation. + */ +#ifdef XML_SCHEMA_READER_ENABLED + ret = xmlSchemaVReaderWalk(vctxt); +#endif +#endif + } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) { + /* + * SAX validation. + */ + ret = xmlParseDocument(vctxt->parserCtxt); + } else { + VERROR_INT("xmlSchemaVStart", + "no instance to validate"); + ret = -1; + } + + xmlSchemaPostRun(vctxt); + if (ret == 0) + ret = vctxt->err; + return (ret); +} + +/** + * xmlSchemaValidateOneElement: + * @ctxt: a schema validation context + * @elem: an element node + * + * Validate a branch of a tree, starting with the given @elem. + * + * Returns 0 if the element and its subtree is valid, a positive error + * code number otherwise and -1 in case of an internal or API error. + */ +int +xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem) +{ + if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE)) + return (-1); + + if (ctxt->schema == NULL) + return (-1); + + ctxt->doc = elem->doc; + ctxt->node = elem; + ctxt->validationRoot = elem; + return(xmlSchemaVStart(ctxt)); +} + +/** + * xmlSchemaValidateDoc: + * @ctxt: a schema validation context + * @doc: a parsed document tree + * + * Validate a document tree in memory. + * + * Returns 0 if the document is schemas valid, a positive error code + * number otherwise and -1 in case of internal or API error. + */ +int +xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc) +{ + if ((ctxt == NULL) || (doc == NULL)) + return (-1); + + ctxt->doc = doc; + ctxt->node = xmlDocGetRootElement(doc); + if (ctxt->node == NULL) { + xmlSchemaCustomErr(ACTXT_CAST ctxt, + XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING, + (xmlNodePtr) doc, NULL, + "The document has no document element", NULL, NULL); + return (ctxt->err); + } + ctxt->validationRoot = ctxt->node; + return (xmlSchemaVStart(ctxt)); +} + + +/************************************************************************ + * * + * Function and data for SAX streaming API * + * * + ************************************************************************/ +typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData; +typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr; + +struct _xmlSchemaSplitSAXData { + xmlSAXHandlerPtr user_sax; + void *user_data; + xmlSchemaValidCtxtPtr ctxt; + xmlSAXHandlerPtr schemas_sax; +}; + +#define XML_SAX_PLUG_MAGIC 0xdc43ba21 + +struct _xmlSchemaSAXPlug { + unsigned int magic; + + /* the original callbacks informations */ + xmlSAXHandlerPtr *user_sax_ptr; + xmlSAXHandlerPtr user_sax; + void **user_data_ptr; + void *user_data; + + /* the block plugged back and validation informations */ + xmlSAXHandler schemas_sax; + xmlSchemaValidCtxtPtr ctxt; +}; + +/* All those functions just bounces to the user provided SAX handlers */ +static void +internalSubsetSplit(void *ctx, const xmlChar *name, + const xmlChar *ExternalID, const xmlChar *SystemID) +{ + xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; + if ((ctxt != NULL) && (ctxt->user_sax != NULL) && + (ctxt->user_sax->internalSubset != NULL)) + ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID, + SystemID); +} + +static int +isStandaloneSplit(void *ctx) +{ + xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; + if ((ctxt != NULL) && (ctxt->user_sax != NULL) && + (ctxt->user_sax->isStandalone != NULL)) + return(ctxt->user_sax->isStandalone(ctxt->user_data)); + return(0); +} + +static int +hasInternalSubsetSplit(void *ctx) +{ + xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; + if ((ctxt != NULL) && (ctxt->user_sax != NULL) && + (ctxt->user_sax->hasInternalSubset != NULL)) + return(ctxt->user_sax->hasInternalSubset(ctxt->user_data)); + return(0); +} + +static int +hasExternalSubsetSplit(void *ctx) +{ + xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; + if ((ctxt != NULL) && (ctxt->user_sax != NULL) && + (ctxt->user_sax->hasExternalSubset != NULL)) + return(ctxt->user_sax->hasExternalSubset(ctxt->user_data)); + return(0); +} + +static void +externalSubsetSplit(void *ctx, const xmlChar *name, + const xmlChar *ExternalID, const xmlChar *SystemID) +{ + xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; + if ((ctxt != NULL) && (ctxt->user_sax != NULL) && + (ctxt->user_sax->internalSubset != NULL)) + ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID, + SystemID); +} + +static xmlParserInputPtr +resolveEntitySplit(void *ctx, const xmlChar *publicId, const xmlChar *systemId) +{ + xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; + if ((ctxt != NULL) && (ctxt->user_sax != NULL) && + (ctxt->user_sax->resolveEntity != NULL)) + return(ctxt->user_sax->resolveEntity(ctxt->user_data, publicId, + systemId)); + return(NULL); +} + +static xmlEntityPtr +getEntitySplit(void *ctx, const xmlChar *name) +{ + xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; + if ((ctxt != NULL) && (ctxt->user_sax != NULL) && + (ctxt->user_sax->getEntity != NULL)) + return(ctxt->user_sax->getEntity(ctxt->user_data, name)); + return(NULL); +} + +static xmlEntityPtr +getParameterEntitySplit(void *ctx, const xmlChar *name) +{ + xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; + if ((ctxt != NULL) && (ctxt->user_sax != NULL) && + (ctxt->user_sax->getParameterEntity != NULL)) + return(ctxt->user_sax->getParameterEntity(ctxt->user_data, name)); + return(NULL); +} + + +static void +entityDeclSplit(void *ctx, const xmlChar *name, int type, + const xmlChar *publicId, const xmlChar *systemId, xmlChar *content) +{ + xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; + if ((ctxt != NULL) && (ctxt->user_sax != NULL) && + (ctxt->user_sax->entityDecl != NULL)) + ctxt->user_sax->entityDecl(ctxt->user_data, name, type, publicId, + systemId, content); +} + +static void +attributeDeclSplit(void *ctx, const xmlChar * elem, + const xmlChar * name, int type, int def, + const xmlChar * defaultValue, xmlEnumerationPtr tree) +{ + xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; + if ((ctxt != NULL) && (ctxt->user_sax != NULL) && + (ctxt->user_sax->attributeDecl != NULL)) { + ctxt->user_sax->attributeDecl(ctxt->user_data, elem, name, type, + def, defaultValue, tree); + } else { + xmlFreeEnumeration(tree); + } +} + +static void +elementDeclSplit(void *ctx, const xmlChar *name, int type, + xmlElementContentPtr content) +{ + xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; + if ((ctxt != NULL) && (ctxt->user_sax != NULL) && + (ctxt->user_sax->elementDecl != NULL)) + ctxt->user_sax->elementDecl(ctxt->user_data, name, type, content); +} + +static void +notationDeclSplit(void *ctx, const xmlChar *name, + const xmlChar *publicId, const xmlChar *systemId) +{ + xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; + if ((ctxt != NULL) && (ctxt->user_sax != NULL) && + (ctxt->user_sax->notationDecl != NULL)) + ctxt->user_sax->notationDecl(ctxt->user_data, name, publicId, + systemId); +} + +static void +unparsedEntityDeclSplit(void *ctx, const xmlChar *name, + const xmlChar *publicId, const xmlChar *systemId, + const xmlChar *notationName) +{ + xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; + if ((ctxt != NULL) && (ctxt->user_sax != NULL) && + (ctxt->user_sax->unparsedEntityDecl != NULL)) + ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId, + systemId, notationName); +} + +static void +setDocumentLocatorSplit(void *ctx, xmlSAXLocatorPtr loc) +{ + xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; + if ((ctxt != NULL) && (ctxt->user_sax != NULL) && + (ctxt->user_sax->setDocumentLocator != NULL)) + ctxt->user_sax->setDocumentLocator(ctxt->user_data, loc); +} + +static void +startDocumentSplit(void *ctx) +{ + xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; + if ((ctxt != NULL) && (ctxt->user_sax != NULL) && + (ctxt->user_sax->startDocument != NULL)) + ctxt->user_sax->startDocument(ctxt->user_data); +} + +static void +endDocumentSplit(void *ctx) +{ + xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; + if ((ctxt != NULL) && (ctxt->user_sax != NULL) && + (ctxt->user_sax->endDocument != NULL)) + ctxt->user_sax->endDocument(ctxt->user_data); +} + +static void +processingInstructionSplit(void *ctx, const xmlChar *target, + const xmlChar *data) +{ + xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; + if ((ctxt != NULL) && (ctxt->user_sax != NULL) && + (ctxt->user_sax->processingInstruction != NULL)) + ctxt->user_sax->processingInstruction(ctxt->user_data, target, data); +} + +static void +commentSplit(void *ctx, const xmlChar *value) +{ + xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; + if ((ctxt != NULL) && (ctxt->user_sax != NULL) && + (ctxt->user_sax->comment != NULL)) + ctxt->user_sax->comment(ctxt->user_data, value); +} + +/* + * Varargs error callbacks to the user application, harder ... + */ + +static void XMLCDECL +warningSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) { + xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; + if ((ctxt != NULL) && (ctxt->user_sax != NULL) && + (ctxt->user_sax->warning != NULL)) { + TODO + } +} +static void XMLCDECL +errorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) { + xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; + if ((ctxt != NULL) && (ctxt->user_sax != NULL) && + (ctxt->user_sax->error != NULL)) { + TODO + } +} +static void XMLCDECL +fatalErrorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) { + xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; + if ((ctxt != NULL) && (ctxt->user_sax != NULL) && + (ctxt->user_sax->fatalError != NULL)) { + TODO + } +} + +/* + * Those are function where both the user handler and the schemas handler + * need to be called. + */ +static void +charactersSplit(void *ctx, const xmlChar *ch, int len) +{ + xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; + if (ctxt == NULL) + return; + if ((ctxt->user_sax != NULL) && (ctxt->user_sax->characters != NULL)) + ctxt->user_sax->characters(ctxt->user_data, ch, len); + if (ctxt->ctxt != NULL) + xmlSchemaSAXHandleText(ctxt->ctxt, ch, len); +} + +static void +ignorableWhitespaceSplit(void *ctx, const xmlChar *ch, int len) +{ + xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; + if (ctxt == NULL) + return; + if ((ctxt->user_sax != NULL) && + (ctxt->user_sax->ignorableWhitespace != NULL)) + ctxt->user_sax->ignorableWhitespace(ctxt->user_data, ch, len); + if (ctxt->ctxt != NULL) + xmlSchemaSAXHandleText(ctxt->ctxt, ch, len); +} + +static void +cdataBlockSplit(void *ctx, const xmlChar *value, int len) +{ + xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; + if (ctxt == NULL) + return; + if ((ctxt->user_sax != NULL) && + (ctxt->user_sax->ignorableWhitespace != NULL)) + ctxt->user_sax->ignorableWhitespace(ctxt->user_data, value, len); + if (ctxt->ctxt != NULL) + xmlSchemaSAXHandleCDataSection(ctxt->ctxt, value, len); +} + +static void +referenceSplit(void *ctx, const xmlChar *name) +{ + xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; + if (ctxt == NULL) + return; + if ((ctxt != NULL) && (ctxt->user_sax != NULL) && + (ctxt->user_sax->reference != NULL)) + ctxt->user_sax->reference(ctxt->user_data, name); + if (ctxt->ctxt != NULL) + xmlSchemaSAXHandleReference(ctxt->user_data, name); +} + +static void +startElementNsSplit(void *ctx, const xmlChar * localname, + const xmlChar * prefix, const xmlChar * URI, + int nb_namespaces, const xmlChar ** namespaces, + int nb_attributes, int nb_defaulted, + const xmlChar ** attributes) { + xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; + if (ctxt == NULL) + return; + if ((ctxt->user_sax != NULL) && + (ctxt->user_sax->startElementNs != NULL)) + ctxt->user_sax->startElementNs(ctxt->user_data, localname, prefix, + URI, nb_namespaces, namespaces, + nb_attributes, nb_defaulted, + attributes); + if (ctxt->ctxt != NULL) + xmlSchemaSAXHandleStartElementNs(ctxt->ctxt, localname, prefix, + URI, nb_namespaces, namespaces, + nb_attributes, nb_defaulted, + attributes); +} + +static void +endElementNsSplit(void *ctx, const xmlChar * localname, + const xmlChar * prefix, const xmlChar * URI) { + xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; + if (ctxt == NULL) + return; + if ((ctxt->user_sax != NULL) && + (ctxt->user_sax->endElementNs != NULL)) + ctxt->user_sax->endElementNs(ctxt->user_data, localname, prefix, URI); + if (ctxt->ctxt != NULL) + xmlSchemaSAXHandleEndElementNs(ctxt->ctxt, localname, prefix, URI); +} + +/** + * xmlSchemaSAXPlug: + * @ctxt: a schema validation context + * @sax: a pointer to the original xmlSAXHandlerPtr + * @user_data: a pointer to the original SAX user data pointer + * + * Plug a SAX based validation layer in a SAX parsing event flow. + * The original @saxptr and @dataptr data are replaced by new pointers + * but the calls to the original will be maintained. + * + * Returns a pointer to a data structure needed to unplug the validation layer + * or NULL in case of errors. + */ +xmlSchemaSAXPlugPtr +xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt, + xmlSAXHandlerPtr *sax, void **user_data) +{ + xmlSchemaSAXPlugPtr ret; + xmlSAXHandlerPtr old_sax; + + if ((ctxt == NULL) || (sax == NULL) || (user_data == NULL)) + return(NULL); + + /* + * We only allow to plug into SAX2 event streams + */ + old_sax = *sax; + if ((old_sax != NULL) && (old_sax->initialized != XML_SAX2_MAGIC)) + return(NULL); + if ((old_sax != NULL) && + (old_sax->startElementNs == NULL) && (old_sax->endElementNs == NULL) && + ((old_sax->startElement != NULL) || (old_sax->endElement != NULL))) + return(NULL); + + /* + * everything seems right allocate the local data needed for that layer + */ + ret = (xmlSchemaSAXPlugPtr) xmlMalloc(sizeof(xmlSchemaSAXPlugStruct)); + if (ret == NULL) { + return(NULL); + } + memset(ret, 0, sizeof(xmlSchemaSAXPlugStruct)); + ret->magic = XML_SAX_PLUG_MAGIC; + ret->schemas_sax.initialized = XML_SAX2_MAGIC; + ret->ctxt = ctxt; + ret->user_sax_ptr = sax; + ret->user_sax = old_sax; + if (old_sax == NULL) { + /* + * go direct, no need for the split block and functions. + */ + ret->schemas_sax.startElementNs = xmlSchemaSAXHandleStartElementNs; + ret->schemas_sax.endElementNs = xmlSchemaSAXHandleEndElementNs; + /* + * Note that we use the same text-function for both, to prevent + * the parser from testing for ignorable whitespace. + */ + ret->schemas_sax.ignorableWhitespace = xmlSchemaSAXHandleText; + ret->schemas_sax.characters = xmlSchemaSAXHandleText; + + ret->schemas_sax.cdataBlock = xmlSchemaSAXHandleCDataSection; + ret->schemas_sax.reference = xmlSchemaSAXHandleReference; + + ret->user_data = ctxt; + *user_data = ctxt; + } else { + /* + * for each callback unused by Schemas initialize it to the Split + * routine only if non NULL in the user block, this can speed up + * things at the SAX level. + */ + if (old_sax->internalSubset != NULL) + ret->schemas_sax.internalSubset = internalSubsetSplit; + if (old_sax->isStandalone != NULL) + ret->schemas_sax.isStandalone = isStandaloneSplit; + if (old_sax->hasInternalSubset != NULL) + ret->schemas_sax.hasInternalSubset = hasInternalSubsetSplit; + if (old_sax->hasExternalSubset != NULL) + ret->schemas_sax.hasExternalSubset = hasExternalSubsetSplit; + if (old_sax->resolveEntity != NULL) + ret->schemas_sax.resolveEntity = resolveEntitySplit; + if (old_sax->getEntity != NULL) + ret->schemas_sax.getEntity = getEntitySplit; + if (old_sax->entityDecl != NULL) + ret->schemas_sax.entityDecl = entityDeclSplit; + if (old_sax->notationDecl != NULL) + ret->schemas_sax.notationDecl = notationDeclSplit; + if (old_sax->attributeDecl != NULL) + ret->schemas_sax.attributeDecl = attributeDeclSplit; + if (old_sax->elementDecl != NULL) + ret->schemas_sax.elementDecl = elementDeclSplit; + if (old_sax->unparsedEntityDecl != NULL) + ret->schemas_sax.unparsedEntityDecl = unparsedEntityDeclSplit; + if (old_sax->setDocumentLocator != NULL) + ret->schemas_sax.setDocumentLocator = setDocumentLocatorSplit; + if (old_sax->startDocument != NULL) + ret->schemas_sax.startDocument = startDocumentSplit; + if (old_sax->endDocument != NULL) + ret->schemas_sax.endDocument = endDocumentSplit; + if (old_sax->processingInstruction != NULL) + ret->schemas_sax.processingInstruction = processingInstructionSplit; + if (old_sax->comment != NULL) + ret->schemas_sax.comment = commentSplit; + if (old_sax->warning != NULL) + ret->schemas_sax.warning = warningSplit; + if (old_sax->error != NULL) + ret->schemas_sax.error = errorSplit; + if (old_sax->fatalError != NULL) + ret->schemas_sax.fatalError = fatalErrorSplit; + if (old_sax->getParameterEntity != NULL) + ret->schemas_sax.getParameterEntity = getParameterEntitySplit; + if (old_sax->externalSubset != NULL) + ret->schemas_sax.externalSubset = externalSubsetSplit; + + /* + * the 6 schemas callback have to go to the splitter functions + * Note that we use the same text-function for ignorableWhitespace + * if possible, to prevent the parser from testing for ignorable + * whitespace. + */ + ret->schemas_sax.characters = charactersSplit; + if ((old_sax->ignorableWhitespace != NULL) && + (old_sax->ignorableWhitespace != old_sax->characters)) + ret->schemas_sax.ignorableWhitespace = ignorableWhitespaceSplit; + else + ret->schemas_sax.ignorableWhitespace = charactersSplit; + ret->schemas_sax.cdataBlock = cdataBlockSplit; + ret->schemas_sax.reference = referenceSplit; + ret->schemas_sax.startElementNs = startElementNsSplit; + ret->schemas_sax.endElementNs = endElementNsSplit; + + ret->user_data_ptr = user_data; + ret->user_data = *user_data; + *user_data = ret; + } + + /* + * plug the pointers back. + */ + *sax = &(ret->schemas_sax); + ctxt->sax = *sax; + ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM; + xmlSchemaPreRun(ctxt); + return(ret); +} + +/** + * xmlSchemaSAXUnplug: + * @plug: a data structure returned by xmlSchemaSAXPlug + * + * Unplug a SAX based validation layer in a SAX parsing event flow. + * The original pointers used in the call are restored. + * + * Returns 0 in case of success and -1 in case of failure. + */ +int +xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug) +{ + xmlSAXHandlerPtr *sax; + void **user_data; + + if ((plug == NULL) || (plug->magic != XML_SAX_PLUG_MAGIC)) + return(-1); + plug->magic = 0; + + xmlSchemaPostRun(plug->ctxt); + /* restore the data */ + sax = plug->user_sax_ptr; + *sax = plug->user_sax; + if (plug->user_sax != NULL) { + user_data = plug->user_data_ptr; + *user_data = plug->user_data; + } + + /* free and return */ + xmlFree(plug); + return(0); +} + +/** + * xmlSchemaValidateStream: + * @ctxt: a schema validation context + * @input: the input to use for reading the data + * @enc: an optional encoding information + * @sax: a SAX handler for the resulting events + * @user_data: the context to provide to the SAX handler. + * + * Validate an input based on a flow of SAX event from the parser + * and forward the events to the @sax handler with the provided @user_data + * the user provided @sax handler must be a SAX2 one. + * + * Returns 0 if the document is schemas valid, a positive error code + * number otherwise and -1 in case of internal or API error. + */ +int +xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt, + xmlParserInputBufferPtr input, xmlCharEncoding enc, + xmlSAXHandlerPtr sax, void *user_data) +{ + xmlSchemaSAXPlugPtr plug = NULL; + xmlSAXHandlerPtr old_sax = NULL; + xmlParserCtxtPtr pctxt = NULL; + xmlParserInputPtr inputStream = NULL; + int ret; + + if ((ctxt == NULL) || (input == NULL)) + return (-1); + + /* + * prepare the parser + */ + pctxt = xmlNewParserCtxt(); + if (pctxt == NULL) + return (-1); + old_sax = pctxt->sax; + pctxt->sax = sax; + pctxt->userData = user_data; +#if 0 + if (options) + xmlCtxtUseOptions(pctxt, options); +#endif + pctxt->linenumbers = 1; + + inputStream = xmlNewIOInputStream(pctxt, input, enc);; + if (inputStream == NULL) { + ret = -1; + goto done; + } + inputPush(pctxt, inputStream); + ctxt->parserCtxt = pctxt; + ctxt->input = input; + + /* + * Plug the validation and launch the parsing + */ + plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData)); + if (plug == NULL) { + ret = -1; + goto done; + } + ctxt->input = input; + ctxt->enc = enc; + ctxt->sax = pctxt->sax; + ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM; + ret = xmlSchemaVStart(ctxt); + + if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) { + ret = ctxt->parserCtxt->errNo; + if (ret == 0) + ret = 1; + } + +done: + ctxt->parserCtxt = NULL; + ctxt->sax = NULL; + ctxt->input = NULL; + if (plug != NULL) { + xmlSchemaSAXUnplug(plug); + } + /* cleanup */ + if (pctxt != NULL) { + pctxt->sax = old_sax; + xmlFreeParserCtxt(pctxt); + } + return (ret); +} + +/** + * xmlSchemaValidateFile: + * @ctxt: a schema validation context + * @filename: the URI of the instance + * @options: a future set of options, currently unused + * + * Do a schemas validation of the given resource, it will use the + * SAX streamable validation internally. + * + * Returns 0 if the document is valid, a positive error code + * number otherwise and -1 in case of an internal or API error. + */ +int +xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt, + const char * filename, + int options ATTRIBUTE_UNUSED) +{ + int ret; + xmlParserInputBufferPtr input; + + if ((ctxt == NULL) || (filename == NULL)) + return (-1); + + input = xmlParserInputBufferCreateFilename(filename, + XML_CHAR_ENCODING_NONE); + if (input == NULL) + return (-1); + ret = xmlSchemaValidateStream(ctxt, input, XML_CHAR_ENCODING_NONE, + NULL, NULL); + return (ret); +} + +#define bottom_xmlschemas +#include "elfgcchack.h" +#endif /* LIBXML_SCHEMAS_ENABLED */ diff --git a/gettext-tools/gnulib-lib/libxml/xmlschemas.in.h b/gettext-tools/gnulib-lib/libxml/xmlschemas.in.h new file mode 100644 index 0000000..15faef5 --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/xmlschemas.in.h @@ -0,0 +1,198 @@ +/* + * Summary: incomplete XML Schemas structure implementation + * Description: interface to the XML Schemas handling and schema validity + * checking, it is incomplete right now. + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + + +#ifndef __XML_SCHEMA_H__ +#define __XML_SCHEMA_H__ + +#include + +#ifdef LIBXML_SCHEMAS_ENABLED + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * This error codes are obsolete; not used any more. + */ +typedef enum { + XML_SCHEMAS_ERR_OK = 0, + XML_SCHEMAS_ERR_NOROOT = 1, + XML_SCHEMAS_ERR_UNDECLAREDELEM, + XML_SCHEMAS_ERR_NOTTOPLEVEL, + XML_SCHEMAS_ERR_MISSING, + XML_SCHEMAS_ERR_WRONGELEM, + XML_SCHEMAS_ERR_NOTYPE, + XML_SCHEMAS_ERR_NOROLLBACK, + XML_SCHEMAS_ERR_ISABSTRACT, + XML_SCHEMAS_ERR_NOTEMPTY, + XML_SCHEMAS_ERR_ELEMCONT, + XML_SCHEMAS_ERR_HAVEDEFAULT, + XML_SCHEMAS_ERR_NOTNILLABLE, + XML_SCHEMAS_ERR_EXTRACONTENT, + XML_SCHEMAS_ERR_INVALIDATTR, + XML_SCHEMAS_ERR_INVALIDELEM, + XML_SCHEMAS_ERR_NOTDETERMINIST, + XML_SCHEMAS_ERR_CONSTRUCT, + XML_SCHEMAS_ERR_INTERNAL, + XML_SCHEMAS_ERR_NOTSIMPLE, + XML_SCHEMAS_ERR_ATTRUNKNOWN, + XML_SCHEMAS_ERR_ATTRINVALID, + XML_SCHEMAS_ERR_VALUE, + XML_SCHEMAS_ERR_FACET, + XML_SCHEMAS_ERR_, + XML_SCHEMAS_ERR_XXX +} xmlSchemaValidError; + +/* +* ATTENTION: Change xmlSchemaSetValidOptions's check +* for invalid values, if adding to the validation +* options below. +*/ +/** + * xmlSchemaValidOption: + * + * This is the set of XML Schema validation options. + */ +typedef enum { + XML_SCHEMA_VAL_VC_I_CREATE = 1<<0 + /* Default/fixed: create an attribute node + * or an element's text node on the instance. + */ +} xmlSchemaValidOption; + +/* + XML_SCHEMA_VAL_XSI_ASSEMBLE = 1<<1, + * assemble schemata using + * xsi:schemaLocation and + * xsi:noNamespaceSchemaLocation +*/ + +/** + * The schemas related types are kept internal + */ +typedef struct _xmlSchema xmlSchema; +typedef xmlSchema *xmlSchemaPtr; + +/** + * A schemas validation context + */ +typedef void (XMLCDECL *xmlSchemaValidityErrorFunc) (void *ctx, const char *msg, ...); +typedef void (XMLCDECL *xmlSchemaValidityWarningFunc) (void *ctx, const char *msg, ...); + +typedef struct _xmlSchemaParserCtxt xmlSchemaParserCtxt; +typedef xmlSchemaParserCtxt *xmlSchemaParserCtxtPtr; + +typedef struct _xmlSchemaValidCtxt xmlSchemaValidCtxt; +typedef xmlSchemaValidCtxt *xmlSchemaValidCtxtPtr; + +/* + * Interfaces for parsing. + */ +XMLPUBFUN xmlSchemaParserCtxtPtr XMLCALL + xmlSchemaNewParserCtxt (const char *URL); +XMLPUBFUN xmlSchemaParserCtxtPtr XMLCALL + xmlSchemaNewMemParserCtxt (const char *buffer, + int size); +XMLPUBFUN xmlSchemaParserCtxtPtr XMLCALL + xmlSchemaNewDocParserCtxt (xmlDocPtr doc); +XMLPUBFUN void XMLCALL + xmlSchemaFreeParserCtxt (xmlSchemaParserCtxtPtr ctxt); +XMLPUBFUN void XMLCALL + xmlSchemaSetParserErrors (xmlSchemaParserCtxtPtr ctxt, + xmlSchemaValidityErrorFunc err, + xmlSchemaValidityWarningFunc warn, + void *ctx); +XMLPUBFUN void XMLCALL + xmlSchemaSetParserStructuredErrors(xmlSchemaParserCtxtPtr ctxt, + xmlStructuredErrorFunc serror, + void *ctx); +XMLPUBFUN int XMLCALL + xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt, + xmlSchemaValidityErrorFunc * err, + xmlSchemaValidityWarningFunc * warn, + void **ctx); +XMLPUBFUN int XMLCALL + xmlSchemaIsValid (xmlSchemaValidCtxtPtr ctxt); + +XMLPUBFUN xmlSchemaPtr XMLCALL + xmlSchemaParse (xmlSchemaParserCtxtPtr ctxt); +XMLPUBFUN void XMLCALL + xmlSchemaFree (xmlSchemaPtr schema); +#ifdef LIBXML_OUTPUT_ENABLED +XMLPUBFUN void XMLCALL + xmlSchemaDump (FILE *output, + xmlSchemaPtr schema); +#endif /* LIBXML_OUTPUT_ENABLED */ +/* + * Interfaces for validating + */ +XMLPUBFUN void XMLCALL + xmlSchemaSetValidErrors (xmlSchemaValidCtxtPtr ctxt, + xmlSchemaValidityErrorFunc err, + xmlSchemaValidityWarningFunc warn, + void *ctx); +XMLPUBFUN void XMLCALL + xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt, + xmlStructuredErrorFunc serror, + void *ctx); +XMLPUBFUN int XMLCALL + xmlSchemaGetValidErrors (xmlSchemaValidCtxtPtr ctxt, + xmlSchemaValidityErrorFunc *err, + xmlSchemaValidityWarningFunc *warn, + void **ctx); +XMLPUBFUN int XMLCALL + xmlSchemaSetValidOptions (xmlSchemaValidCtxtPtr ctxt, + int options); +XMLPUBFUN int XMLCALL + xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt); + +XMLPUBFUN xmlSchemaValidCtxtPtr XMLCALL + xmlSchemaNewValidCtxt (xmlSchemaPtr schema); +XMLPUBFUN void XMLCALL + xmlSchemaFreeValidCtxt (xmlSchemaValidCtxtPtr ctxt); +XMLPUBFUN int XMLCALL + xmlSchemaValidateDoc (xmlSchemaValidCtxtPtr ctxt, + xmlDocPtr instance); +XMLPUBFUN int XMLCALL + xmlSchemaValidateOneElement (xmlSchemaValidCtxtPtr ctxt, + xmlNodePtr elem); +XMLPUBFUN int XMLCALL + xmlSchemaValidateStream (xmlSchemaValidCtxtPtr ctxt, + xmlParserInputBufferPtr input, + xmlCharEncoding enc, + xmlSAXHandlerPtr sax, + void *user_data); +XMLPUBFUN int XMLCALL + xmlSchemaValidateFile (xmlSchemaValidCtxtPtr ctxt, + const char * filename, + int options); + +/* + * Interface to insert Schemas SAX velidation in a SAX stream + */ +typedef struct _xmlSchemaSAXPlug xmlSchemaSAXPlugStruct; +typedef xmlSchemaSAXPlugStruct *xmlSchemaSAXPlugPtr; + +XMLPUBFUN xmlSchemaSAXPlugPtr XMLCALL + xmlSchemaSAXPlug (xmlSchemaValidCtxtPtr ctxt, + xmlSAXHandlerPtr *sax, + void **user_data); +XMLPUBFUN int XMLCALL + xmlSchemaSAXUnplug (xmlSchemaSAXPlugPtr plug); +#ifdef __cplusplus +} +#endif + +#endif /* LIBXML_SCHEMAS_ENABLED */ +#endif /* __XML_SCHEMA_H__ */ diff --git a/gettext-tools/gnulib-lib/libxml/xmlschemastypes.c b/gettext-tools/gnulib-lib/libxml/xmlschemastypes.c new file mode 100644 index 0000000..a35c539 --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/xmlschemastypes.c @@ -0,0 +1,6113 @@ +/* + * schemastypes.c : implementation of the XML Schema Datatypes + * definition and validity checking + * + * See Copyright for the status of this software. + * + * Daniel Veillard + */ + +#define IN_LIBXML +#include "libxml.h" + +#ifdef LIBXML_SCHEMAS_ENABLED + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#ifdef HAVE_MATH_H +#include +#endif +#ifdef HAVE_FLOAT_H +#include +#endif + +#define DEBUG + +#ifndef LIBXML_XPATH_ENABLED +extern double xmlXPathNAN; +extern double xmlXPathPINF; +extern double xmlXPathNINF; +#endif + +#define TODO \ + xmlGenericError(xmlGenericErrorContext, \ + "Unimplemented block at %s:%d\n", \ + __FILE__, __LINE__); + +#define XML_SCHEMAS_NAMESPACE_NAME \ + (const xmlChar *)"http://www.w3.org/2001/XMLSchema" + +#define IS_WSP_REPLACE_CH(c) ((((c) == 0x9) || ((c) == 0xa)) || \ + ((c) == 0xd)) + +#define IS_WSP_SPACE_CH(c) ((c) == 0x20) + +#define IS_WSP_BLANK_CH(c) IS_BLANK_CH(c) + +/* Date value */ +typedef struct _xmlSchemaValDate xmlSchemaValDate; +typedef xmlSchemaValDate *xmlSchemaValDatePtr; +struct _xmlSchemaValDate { + long year; + unsigned int mon :4; /* 1 <= mon <= 12 */ + unsigned int day :5; /* 1 <= day <= 31 */ + unsigned int hour :5; /* 0 <= hour <= 23 */ + unsigned int min :6; /* 0 <= min <= 59 */ + double sec; + unsigned int tz_flag :1; /* is tzo explicitely set? */ + signed int tzo :12; /* -1440 <= tzo <= 1440; + currently only -840 to +840 are needed */ +}; + +/* Duration value */ +typedef struct _xmlSchemaValDuration xmlSchemaValDuration; +typedef xmlSchemaValDuration *xmlSchemaValDurationPtr; +struct _xmlSchemaValDuration { + long mon; /* mon stores years also */ + long day; + double sec; /* sec stores min and hour also */ +}; + +typedef struct _xmlSchemaValDecimal xmlSchemaValDecimal; +typedef xmlSchemaValDecimal *xmlSchemaValDecimalPtr; +struct _xmlSchemaValDecimal { + /* would use long long but not portable */ + unsigned long lo; + unsigned long mi; + unsigned long hi; + unsigned int extra; + unsigned int sign:1; + unsigned int frac:7; + unsigned int total:8; +}; + +typedef struct _xmlSchemaValQName xmlSchemaValQName; +typedef xmlSchemaValQName *xmlSchemaValQNamePtr; +struct _xmlSchemaValQName { + xmlChar *name; + xmlChar *uri; +}; + +typedef struct _xmlSchemaValHex xmlSchemaValHex; +typedef xmlSchemaValHex *xmlSchemaValHexPtr; +struct _xmlSchemaValHex { + xmlChar *str; + unsigned int total; +}; + +typedef struct _xmlSchemaValBase64 xmlSchemaValBase64; +typedef xmlSchemaValBase64 *xmlSchemaValBase64Ptr; +struct _xmlSchemaValBase64 { + xmlChar *str; + unsigned int total; +}; + +struct _xmlSchemaVal { + xmlSchemaValType type; + struct _xmlSchemaVal *next; + union { + xmlSchemaValDecimal decimal; + xmlSchemaValDate date; + xmlSchemaValDuration dur; + xmlSchemaValQName qname; + xmlSchemaValHex hex; + xmlSchemaValBase64 base64; + float f; + double d; + int b; + xmlChar *str; + } value; +}; + +static int xmlSchemaTypesInitialized = 0; +static xmlHashTablePtr xmlSchemaTypesBank = NULL; + +/* + * Basic types + */ +static xmlSchemaTypePtr xmlSchemaTypeStringDef = NULL; +static xmlSchemaTypePtr xmlSchemaTypeAnyTypeDef = NULL; +static xmlSchemaTypePtr xmlSchemaTypeAnySimpleTypeDef = NULL; +static xmlSchemaTypePtr xmlSchemaTypeDecimalDef = NULL; +static xmlSchemaTypePtr xmlSchemaTypeDatetimeDef = NULL; +static xmlSchemaTypePtr xmlSchemaTypeDateDef = NULL; +static xmlSchemaTypePtr xmlSchemaTypeTimeDef = NULL; +static xmlSchemaTypePtr xmlSchemaTypeGYearDef = NULL; +static xmlSchemaTypePtr xmlSchemaTypeGYearMonthDef = NULL; +static xmlSchemaTypePtr xmlSchemaTypeGDayDef = NULL; +static xmlSchemaTypePtr xmlSchemaTypeGMonthDayDef = NULL; +static xmlSchemaTypePtr xmlSchemaTypeGMonthDef = NULL; +static xmlSchemaTypePtr xmlSchemaTypeDurationDef = NULL; +static xmlSchemaTypePtr xmlSchemaTypeFloatDef = NULL; +static xmlSchemaTypePtr xmlSchemaTypeBooleanDef = NULL; +static xmlSchemaTypePtr xmlSchemaTypeDoubleDef = NULL; +static xmlSchemaTypePtr xmlSchemaTypeHexBinaryDef = NULL; +static xmlSchemaTypePtr xmlSchemaTypeBase64BinaryDef = NULL; +static xmlSchemaTypePtr xmlSchemaTypeAnyURIDef = NULL; + +/* + * Derived types + */ +static xmlSchemaTypePtr xmlSchemaTypePositiveIntegerDef = NULL; +static xmlSchemaTypePtr xmlSchemaTypeNonPositiveIntegerDef = NULL; +static xmlSchemaTypePtr xmlSchemaTypeNegativeIntegerDef = NULL; +static xmlSchemaTypePtr xmlSchemaTypeNonNegativeIntegerDef = NULL; +static xmlSchemaTypePtr xmlSchemaTypeIntegerDef = NULL; +static xmlSchemaTypePtr xmlSchemaTypeLongDef = NULL; +static xmlSchemaTypePtr xmlSchemaTypeIntDef = NULL; +static xmlSchemaTypePtr xmlSchemaTypeShortDef = NULL; +static xmlSchemaTypePtr xmlSchemaTypeByteDef = NULL; +static xmlSchemaTypePtr xmlSchemaTypeUnsignedLongDef = NULL; +static xmlSchemaTypePtr xmlSchemaTypeUnsignedIntDef = NULL; +static xmlSchemaTypePtr xmlSchemaTypeUnsignedShortDef = NULL; +static xmlSchemaTypePtr xmlSchemaTypeUnsignedByteDef = NULL; +static xmlSchemaTypePtr xmlSchemaTypeNormStringDef = NULL; +static xmlSchemaTypePtr xmlSchemaTypeTokenDef = NULL; +static xmlSchemaTypePtr xmlSchemaTypeLanguageDef = NULL; +static xmlSchemaTypePtr xmlSchemaTypeNameDef = NULL; +static xmlSchemaTypePtr xmlSchemaTypeQNameDef = NULL; +static xmlSchemaTypePtr xmlSchemaTypeNCNameDef = NULL; +static xmlSchemaTypePtr xmlSchemaTypeIdDef = NULL; +static xmlSchemaTypePtr xmlSchemaTypeIdrefDef = NULL; +static xmlSchemaTypePtr xmlSchemaTypeIdrefsDef = NULL; +static xmlSchemaTypePtr xmlSchemaTypeEntityDef = NULL; +static xmlSchemaTypePtr xmlSchemaTypeEntitiesDef = NULL; +static xmlSchemaTypePtr xmlSchemaTypeNotationDef = NULL; +static xmlSchemaTypePtr xmlSchemaTypeNmtokenDef = NULL; +static xmlSchemaTypePtr xmlSchemaTypeNmtokensDef = NULL; + +/************************************************************************ + * * + * Datatype error handlers * + * * + ************************************************************************/ +/** + * xmlSchemaTypeErrMemory: + * @extra: extra informations + * + * Handle an out of memory condition + */ +static void +xmlSchemaTypeErrMemory(xmlNodePtr node, const char *extra) +{ + __xmlSimpleError(XML_FROM_DATATYPE, XML_ERR_NO_MEMORY, node, NULL, extra); +} + +/************************************************************************ + * * + * Base types support * + * * + ************************************************************************/ + +/** + * xmlSchemaNewValue: + * @type: the value type + * + * Allocate a new simple type value + * + * Returns a pointer to the new value or NULL in case of error + */ +static xmlSchemaValPtr +xmlSchemaNewValue(xmlSchemaValType type) { + xmlSchemaValPtr value; + + value = (xmlSchemaValPtr) xmlMalloc(sizeof(xmlSchemaVal)); + if (value == NULL) { + return(NULL); + } + memset(value, 0, sizeof(xmlSchemaVal)); + value->type = type; + return(value); +} + +static xmlSchemaFacetPtr +xmlSchemaNewMinLengthFacet(int value) +{ + xmlSchemaFacetPtr ret; + + ret = xmlSchemaNewFacet(); + if (ret == NULL) { + return(NULL); + } + ret->type = XML_SCHEMA_FACET_MINLENGTH; + ret->val = xmlSchemaNewValue(XML_SCHEMAS_NNINTEGER); + ret->val->value.decimal.lo = value; + return (ret); +} + +/* + * xmlSchemaInitBasicType: + * @name: the type name + * @type: the value type associated + * + * Initialize one primitive built-in type + */ +static xmlSchemaTypePtr +xmlSchemaInitBasicType(const char *name, xmlSchemaValType type, + xmlSchemaTypePtr baseType) { + xmlSchemaTypePtr ret; + + ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType)); + if (ret == NULL) { + xmlSchemaTypeErrMemory(NULL, "could not initialize basic types"); + return(NULL); + } + memset(ret, 0, sizeof(xmlSchemaType)); + ret->name = (const xmlChar *)name; + ret->targetNamespace = XML_SCHEMAS_NAMESPACE_NAME; + ret->type = XML_SCHEMA_TYPE_BASIC; + ret->baseType = baseType; + ret->contentType = XML_SCHEMA_CONTENT_BASIC; + /* + * Primitive types. + */ + switch (type) { + case XML_SCHEMAS_STRING: + case XML_SCHEMAS_DECIMAL: + case XML_SCHEMAS_DATE: + case XML_SCHEMAS_DATETIME: + case XML_SCHEMAS_TIME: + case XML_SCHEMAS_GYEAR: + case XML_SCHEMAS_GYEARMONTH: + case XML_SCHEMAS_GMONTH: + case XML_SCHEMAS_GMONTHDAY: + case XML_SCHEMAS_GDAY: + case XML_SCHEMAS_DURATION: + case XML_SCHEMAS_FLOAT: + case XML_SCHEMAS_DOUBLE: + case XML_SCHEMAS_BOOLEAN: + case XML_SCHEMAS_ANYURI: + case XML_SCHEMAS_HEXBINARY: + case XML_SCHEMAS_BASE64BINARY: + case XML_SCHEMAS_QNAME: + case XML_SCHEMAS_NOTATION: + ret->flags |= XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE; + break; + default: + break; + } + /* + * Set variety. + */ + switch (type) { + case XML_SCHEMAS_ANYTYPE: + case XML_SCHEMAS_ANYSIMPLETYPE: + break; + case XML_SCHEMAS_IDREFS: + case XML_SCHEMAS_NMTOKENS: + case XML_SCHEMAS_ENTITIES: + ret->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST; + ret->facets = xmlSchemaNewMinLengthFacet(1); + ret->flags |= XML_SCHEMAS_TYPE_HAS_FACETS; + break; + default: + ret->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC; + break; + } + xmlHashAddEntry2(xmlSchemaTypesBank, ret->name, + XML_SCHEMAS_NAMESPACE_NAME, ret); + ret->builtInType = type; + return(ret); +} + +/* +* WARNING: Those type reside normally in xmlschemas.c but are +* redefined here locally in oder of being able to use them for xs:anyType- +* TODO: Remove those definition if we move the types to a header file. +* TODO: Always keep those structs up-to-date with the originals. +*/ +#define UNBOUNDED (1 << 30) + +typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem; +typedef xmlSchemaTreeItem *xmlSchemaTreeItemPtr; +struct _xmlSchemaTreeItem { + xmlSchemaTypeType type; + xmlSchemaAnnotPtr annot; + xmlSchemaTreeItemPtr next; + xmlSchemaTreeItemPtr children; +}; + +typedef struct _xmlSchemaParticle xmlSchemaParticle; +typedef xmlSchemaParticle *xmlSchemaParticlePtr; +struct _xmlSchemaParticle { + xmlSchemaTypeType type; + xmlSchemaAnnotPtr annot; + xmlSchemaTreeItemPtr next; + xmlSchemaTreeItemPtr children; + int minOccurs; + int maxOccurs; + xmlNodePtr node; +}; + +typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup; +typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr; +struct _xmlSchemaModelGroup { + xmlSchemaTypeType type; + xmlSchemaAnnotPtr annot; + xmlSchemaTreeItemPtr next; + xmlSchemaTreeItemPtr children; + xmlNodePtr node; +}; + +static xmlSchemaParticlePtr +xmlSchemaAddParticle(void) +{ + xmlSchemaParticlePtr ret = NULL; + + ret = (xmlSchemaParticlePtr) + xmlMalloc(sizeof(xmlSchemaParticle)); + if (ret == NULL) { + xmlSchemaTypeErrMemory(NULL, "allocating particle component"); + return (NULL); + } + memset(ret, 0, sizeof(xmlSchemaParticle)); + ret->type = XML_SCHEMA_TYPE_PARTICLE; + ret->minOccurs = 1; + ret->maxOccurs = 1; + return (ret); +} + +/* + * xmlSchemaInitTypes: + * + * Initialize the default XML Schemas type library + */ +void +xmlSchemaInitTypes(void) +{ + if (xmlSchemaTypesInitialized != 0) + return; + xmlSchemaTypesBank = xmlHashCreate(40); + + + /* + * 3.4.7 Built-in Complex Type Definition + */ + xmlSchemaTypeAnyTypeDef = xmlSchemaInitBasicType("anyType", + XML_SCHEMAS_ANYTYPE, + NULL); + xmlSchemaTypeAnyTypeDef->baseType = xmlSchemaTypeAnyTypeDef; + xmlSchemaTypeAnyTypeDef->contentType = XML_SCHEMA_CONTENT_MIXED; + /* + * Init the content type. + */ + xmlSchemaTypeAnyTypeDef->contentType = XML_SCHEMA_CONTENT_MIXED; + { + xmlSchemaParticlePtr particle; + xmlSchemaModelGroupPtr sequence; + xmlSchemaWildcardPtr wild; + /* First particle. */ + particle = xmlSchemaAddParticle(); + if (particle == NULL) + return; + xmlSchemaTypeAnyTypeDef->subtypes = (xmlSchemaTypePtr) particle; + /* Sequence model group. */ + sequence = (xmlSchemaModelGroupPtr) + xmlMalloc(sizeof(xmlSchemaModelGroup)); + if (sequence == NULL) { + xmlSchemaTypeErrMemory(NULL, "allocating model group component"); + return; + } + memset(sequence, 0, sizeof(xmlSchemaModelGroup)); + sequence->type = XML_SCHEMA_TYPE_SEQUENCE; + particle->children = (xmlSchemaTreeItemPtr) sequence; + /* Second particle. */ + particle = xmlSchemaAddParticle(); + if (particle == NULL) + return; + particle->minOccurs = 0; + particle->maxOccurs = UNBOUNDED; + sequence->children = (xmlSchemaTreeItemPtr) particle; + /* The wildcard */ + wild = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard)); + if (wild == NULL) { + xmlSchemaTypeErrMemory(NULL, "allocating wildcard component"); + return; + } + memset(wild, 0, sizeof(xmlSchemaWildcard)); + wild->type = XML_SCHEMA_TYPE_ANY; + wild->any = 1; + wild->processContents = XML_SCHEMAS_ANY_LAX; + particle->children = (xmlSchemaTreeItemPtr) wild; + /* + * Create the attribute wildcard. + */ + wild = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard)); + if (wild == NULL) { + xmlSchemaTypeErrMemory(NULL, "could not create an attribute " + "wildcard on anyType"); + return; + } + memset(wild, 0, sizeof(xmlSchemaWildcard)); + wild->any = 1; + wild->processContents = XML_SCHEMAS_ANY_LAX; + xmlSchemaTypeAnyTypeDef->attributeWildcard = wild; + } + xmlSchemaTypeAnySimpleTypeDef = xmlSchemaInitBasicType("anySimpleType", + XML_SCHEMAS_ANYSIMPLETYPE, + xmlSchemaTypeAnyTypeDef); + /* + * primitive datatypes + */ + xmlSchemaTypeStringDef = xmlSchemaInitBasicType("string", + XML_SCHEMAS_STRING, + xmlSchemaTypeAnySimpleTypeDef); + xmlSchemaTypeDecimalDef = xmlSchemaInitBasicType("decimal", + XML_SCHEMAS_DECIMAL, + xmlSchemaTypeAnySimpleTypeDef); + xmlSchemaTypeDateDef = xmlSchemaInitBasicType("date", + XML_SCHEMAS_DATE, + xmlSchemaTypeAnySimpleTypeDef); + xmlSchemaTypeDatetimeDef = xmlSchemaInitBasicType("dateTime", + XML_SCHEMAS_DATETIME, + xmlSchemaTypeAnySimpleTypeDef); + xmlSchemaTypeTimeDef = xmlSchemaInitBasicType("time", + XML_SCHEMAS_TIME, + xmlSchemaTypeAnySimpleTypeDef); + xmlSchemaTypeGYearDef = xmlSchemaInitBasicType("gYear", + XML_SCHEMAS_GYEAR, + xmlSchemaTypeAnySimpleTypeDef); + xmlSchemaTypeGYearMonthDef = xmlSchemaInitBasicType("gYearMonth", + XML_SCHEMAS_GYEARMONTH, + xmlSchemaTypeAnySimpleTypeDef); + xmlSchemaTypeGMonthDef = xmlSchemaInitBasicType("gMonth", + XML_SCHEMAS_GMONTH, + xmlSchemaTypeAnySimpleTypeDef); + xmlSchemaTypeGMonthDayDef = xmlSchemaInitBasicType("gMonthDay", + XML_SCHEMAS_GMONTHDAY, + xmlSchemaTypeAnySimpleTypeDef); + xmlSchemaTypeGDayDef = xmlSchemaInitBasicType("gDay", + XML_SCHEMAS_GDAY, + xmlSchemaTypeAnySimpleTypeDef); + xmlSchemaTypeDurationDef = xmlSchemaInitBasicType("duration", + XML_SCHEMAS_DURATION, + xmlSchemaTypeAnySimpleTypeDef); + xmlSchemaTypeFloatDef = xmlSchemaInitBasicType("float", + XML_SCHEMAS_FLOAT, + xmlSchemaTypeAnySimpleTypeDef); + xmlSchemaTypeDoubleDef = xmlSchemaInitBasicType("double", + XML_SCHEMAS_DOUBLE, + xmlSchemaTypeAnySimpleTypeDef); + xmlSchemaTypeBooleanDef = xmlSchemaInitBasicType("boolean", + XML_SCHEMAS_BOOLEAN, + xmlSchemaTypeAnySimpleTypeDef); + xmlSchemaTypeAnyURIDef = xmlSchemaInitBasicType("anyURI", + XML_SCHEMAS_ANYURI, + xmlSchemaTypeAnySimpleTypeDef); + xmlSchemaTypeHexBinaryDef = xmlSchemaInitBasicType("hexBinary", + XML_SCHEMAS_HEXBINARY, + xmlSchemaTypeAnySimpleTypeDef); + xmlSchemaTypeBase64BinaryDef + = xmlSchemaInitBasicType("base64Binary", XML_SCHEMAS_BASE64BINARY, + xmlSchemaTypeAnySimpleTypeDef); + xmlSchemaTypeNotationDef = xmlSchemaInitBasicType("NOTATION", + XML_SCHEMAS_NOTATION, + xmlSchemaTypeAnySimpleTypeDef); + xmlSchemaTypeQNameDef = xmlSchemaInitBasicType("QName", + XML_SCHEMAS_QNAME, + xmlSchemaTypeAnySimpleTypeDef); + + /* + * derived datatypes + */ + xmlSchemaTypeIntegerDef = xmlSchemaInitBasicType("integer", + XML_SCHEMAS_INTEGER, + xmlSchemaTypeDecimalDef); + xmlSchemaTypeNonPositiveIntegerDef = + xmlSchemaInitBasicType("nonPositiveInteger", + XML_SCHEMAS_NPINTEGER, + xmlSchemaTypeIntegerDef); + xmlSchemaTypeNegativeIntegerDef = + xmlSchemaInitBasicType("negativeInteger", XML_SCHEMAS_NINTEGER, + xmlSchemaTypeNonPositiveIntegerDef); + xmlSchemaTypeLongDef = + xmlSchemaInitBasicType("long", XML_SCHEMAS_LONG, + xmlSchemaTypeIntegerDef); + xmlSchemaTypeIntDef = xmlSchemaInitBasicType("int", XML_SCHEMAS_INT, + xmlSchemaTypeLongDef); + xmlSchemaTypeShortDef = xmlSchemaInitBasicType("short", + XML_SCHEMAS_SHORT, + xmlSchemaTypeIntDef); + xmlSchemaTypeByteDef = xmlSchemaInitBasicType("byte", + XML_SCHEMAS_BYTE, + xmlSchemaTypeShortDef); + xmlSchemaTypeNonNegativeIntegerDef = + xmlSchemaInitBasicType("nonNegativeInteger", + XML_SCHEMAS_NNINTEGER, + xmlSchemaTypeIntegerDef); + xmlSchemaTypeUnsignedLongDef = + xmlSchemaInitBasicType("unsignedLong", XML_SCHEMAS_ULONG, + xmlSchemaTypeNonNegativeIntegerDef); + xmlSchemaTypeUnsignedIntDef = + xmlSchemaInitBasicType("unsignedInt", XML_SCHEMAS_UINT, + xmlSchemaTypeUnsignedLongDef); + xmlSchemaTypeUnsignedShortDef = + xmlSchemaInitBasicType("unsignedShort", XML_SCHEMAS_USHORT, + xmlSchemaTypeUnsignedIntDef); + xmlSchemaTypeUnsignedByteDef = + xmlSchemaInitBasicType("unsignedByte", XML_SCHEMAS_UBYTE, + xmlSchemaTypeUnsignedShortDef); + xmlSchemaTypePositiveIntegerDef = + xmlSchemaInitBasicType("positiveInteger", XML_SCHEMAS_PINTEGER, + xmlSchemaTypeNonNegativeIntegerDef); + xmlSchemaTypeNormStringDef = xmlSchemaInitBasicType("normalizedString", + XML_SCHEMAS_NORMSTRING, + xmlSchemaTypeStringDef); + xmlSchemaTypeTokenDef = xmlSchemaInitBasicType("token", + XML_SCHEMAS_TOKEN, + xmlSchemaTypeNormStringDef); + xmlSchemaTypeLanguageDef = xmlSchemaInitBasicType("language", + XML_SCHEMAS_LANGUAGE, + xmlSchemaTypeTokenDef); + xmlSchemaTypeNameDef = xmlSchemaInitBasicType("Name", + XML_SCHEMAS_NAME, + xmlSchemaTypeTokenDef); + xmlSchemaTypeNmtokenDef = xmlSchemaInitBasicType("NMTOKEN", + XML_SCHEMAS_NMTOKEN, + xmlSchemaTypeTokenDef); + xmlSchemaTypeNCNameDef = xmlSchemaInitBasicType("NCName", + XML_SCHEMAS_NCNAME, + xmlSchemaTypeNameDef); + xmlSchemaTypeIdDef = xmlSchemaInitBasicType("ID", XML_SCHEMAS_ID, + xmlSchemaTypeNCNameDef); + xmlSchemaTypeIdrefDef = xmlSchemaInitBasicType("IDREF", + XML_SCHEMAS_IDREF, + xmlSchemaTypeNCNameDef); + xmlSchemaTypeEntityDef = xmlSchemaInitBasicType("ENTITY", + XML_SCHEMAS_ENTITY, + xmlSchemaTypeNCNameDef); + /* + * Derived list types. + */ + /* ENTITIES */ + xmlSchemaTypeEntitiesDef = xmlSchemaInitBasicType("ENTITIES", + XML_SCHEMAS_ENTITIES, + xmlSchemaTypeAnySimpleTypeDef); + xmlSchemaTypeEntitiesDef->subtypes = xmlSchemaTypeEntityDef; + /* IDREFS */ + xmlSchemaTypeIdrefsDef = xmlSchemaInitBasicType("IDREFS", + XML_SCHEMAS_IDREFS, + xmlSchemaTypeAnySimpleTypeDef); + xmlSchemaTypeIdrefsDef->subtypes = xmlSchemaTypeIdrefDef; + + /* NMTOKENS */ + xmlSchemaTypeNmtokensDef = xmlSchemaInitBasicType("NMTOKENS", + XML_SCHEMAS_NMTOKENS, + xmlSchemaTypeAnySimpleTypeDef); + xmlSchemaTypeNmtokensDef->subtypes = xmlSchemaTypeNmtokenDef; + + xmlSchemaTypesInitialized = 1; +} + +/** + * xmlSchemaCleanupTypes: + * + * Cleanup the default XML Schemas type library + */ +void +xmlSchemaCleanupTypes(void) { + if (xmlSchemaTypesInitialized == 0) + return; + /* + * Free xs:anyType. + */ + { + xmlSchemaParticlePtr particle; + /* Attribute wildcard. */ + xmlSchemaFreeWildcard(xmlSchemaTypeAnyTypeDef->attributeWildcard); + /* Content type. */ + particle = (xmlSchemaParticlePtr) xmlSchemaTypeAnyTypeDef->subtypes; + /* Wildcard. */ + xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) + particle->children->children->children); + xmlFree((xmlSchemaParticlePtr) particle->children->children); + /* Sequence model group. */ + xmlFree((xmlSchemaModelGroupPtr) particle->children); + xmlFree((xmlSchemaParticlePtr) particle); + xmlSchemaTypeAnyTypeDef->subtypes = NULL; + } + xmlHashFree(xmlSchemaTypesBank, (xmlHashDeallocator) xmlSchemaFreeType); + xmlSchemaTypesInitialized = 0; +} + +/** + * xmlSchemaIsBuiltInTypeFacet: + * @type: the built-in type + * @facetType: the facet type + * + * Evaluates if a specific facet can be + * used in conjunction with a type. + * + * Returns 1 if the facet can be used with the given built-in type, + * 0 otherwise and -1 in case the type is not a built-in type. + */ +int +xmlSchemaIsBuiltInTypeFacet(xmlSchemaTypePtr type, int facetType) +{ + if (type == NULL) + return (-1); + if (type->type != XML_SCHEMA_TYPE_BASIC) + return (-1); + switch (type->builtInType) { + case XML_SCHEMAS_BOOLEAN: + if ((facetType == XML_SCHEMA_FACET_PATTERN) || + (facetType == XML_SCHEMA_FACET_WHITESPACE)) + return (1); + else + return (0); + case XML_SCHEMAS_STRING: + case XML_SCHEMAS_NOTATION: + case XML_SCHEMAS_QNAME: + case XML_SCHEMAS_ANYURI: + case XML_SCHEMAS_BASE64BINARY: + case XML_SCHEMAS_HEXBINARY: + if ((facetType == XML_SCHEMA_FACET_LENGTH) || + (facetType == XML_SCHEMA_FACET_MINLENGTH) || + (facetType == XML_SCHEMA_FACET_MAXLENGTH) || + (facetType == XML_SCHEMA_FACET_PATTERN) || + (facetType == XML_SCHEMA_FACET_ENUMERATION) || + (facetType == XML_SCHEMA_FACET_WHITESPACE)) + return (1); + else + return (0); + case XML_SCHEMAS_DECIMAL: + if ((facetType == XML_SCHEMA_FACET_TOTALDIGITS) || + (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) || + (facetType == XML_SCHEMA_FACET_PATTERN) || + (facetType == XML_SCHEMA_FACET_WHITESPACE) || + (facetType == XML_SCHEMA_FACET_ENUMERATION) || + (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) || + (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) || + (facetType == XML_SCHEMA_FACET_MININCLUSIVE) || + (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE)) + return (1); + else + return (0); + case XML_SCHEMAS_TIME: + case XML_SCHEMAS_GDAY: + case XML_SCHEMAS_GMONTH: + case XML_SCHEMAS_GMONTHDAY: + case XML_SCHEMAS_GYEAR: + case XML_SCHEMAS_GYEARMONTH: + case XML_SCHEMAS_DATE: + case XML_SCHEMAS_DATETIME: + case XML_SCHEMAS_DURATION: + case XML_SCHEMAS_FLOAT: + case XML_SCHEMAS_DOUBLE: + if ((facetType == XML_SCHEMA_FACET_PATTERN) || + (facetType == XML_SCHEMA_FACET_ENUMERATION) || + (facetType == XML_SCHEMA_FACET_WHITESPACE) || + (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) || + (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) || + (facetType == XML_SCHEMA_FACET_MININCLUSIVE) || + (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE)) + return (1); + else + return (0); + default: + break; + } + return (0); +} + +/** + * xmlSchemaGetBuiltInType: + * @type: the type of the built in type + * + * Gives you the type struct for a built-in + * type by its type id. + * + * Returns the type if found, NULL otherwise. + */ +xmlSchemaTypePtr +xmlSchemaGetBuiltInType(xmlSchemaValType type) +{ + if (xmlSchemaTypesInitialized == 0) + xmlSchemaInitTypes(); + switch (type) { + + case XML_SCHEMAS_ANYSIMPLETYPE: + return (xmlSchemaTypeAnySimpleTypeDef); + case XML_SCHEMAS_STRING: + return (xmlSchemaTypeStringDef); + case XML_SCHEMAS_NORMSTRING: + return (xmlSchemaTypeNormStringDef); + case XML_SCHEMAS_DECIMAL: + return (xmlSchemaTypeDecimalDef); + case XML_SCHEMAS_TIME: + return (xmlSchemaTypeTimeDef); + case XML_SCHEMAS_GDAY: + return (xmlSchemaTypeGDayDef); + case XML_SCHEMAS_GMONTH: + return (xmlSchemaTypeGMonthDef); + case XML_SCHEMAS_GMONTHDAY: + return (xmlSchemaTypeGMonthDayDef); + case XML_SCHEMAS_GYEAR: + return (xmlSchemaTypeGYearDef); + case XML_SCHEMAS_GYEARMONTH: + return (xmlSchemaTypeGYearMonthDef); + case XML_SCHEMAS_DATE: + return (xmlSchemaTypeDateDef); + case XML_SCHEMAS_DATETIME: + return (xmlSchemaTypeDatetimeDef); + case XML_SCHEMAS_DURATION: + return (xmlSchemaTypeDurationDef); + case XML_SCHEMAS_FLOAT: + return (xmlSchemaTypeFloatDef); + case XML_SCHEMAS_DOUBLE: + return (xmlSchemaTypeDoubleDef); + case XML_SCHEMAS_BOOLEAN: + return (xmlSchemaTypeBooleanDef); + case XML_SCHEMAS_TOKEN: + return (xmlSchemaTypeTokenDef); + case XML_SCHEMAS_LANGUAGE: + return (xmlSchemaTypeLanguageDef); + case XML_SCHEMAS_NMTOKEN: + return (xmlSchemaTypeNmtokenDef); + case XML_SCHEMAS_NMTOKENS: + return (xmlSchemaTypeNmtokensDef); + case XML_SCHEMAS_NAME: + return (xmlSchemaTypeNameDef); + case XML_SCHEMAS_QNAME: + return (xmlSchemaTypeQNameDef); + case XML_SCHEMAS_NCNAME: + return (xmlSchemaTypeNCNameDef); + case XML_SCHEMAS_ID: + return (xmlSchemaTypeIdDef); + case XML_SCHEMAS_IDREF: + return (xmlSchemaTypeIdrefDef); + case XML_SCHEMAS_IDREFS: + return (xmlSchemaTypeIdrefsDef); + case XML_SCHEMAS_ENTITY: + return (xmlSchemaTypeEntityDef); + case XML_SCHEMAS_ENTITIES: + return (xmlSchemaTypeEntitiesDef); + case XML_SCHEMAS_NOTATION: + return (xmlSchemaTypeNotationDef); + case XML_SCHEMAS_ANYURI: + return (xmlSchemaTypeAnyURIDef); + case XML_SCHEMAS_INTEGER: + return (xmlSchemaTypeIntegerDef); + case XML_SCHEMAS_NPINTEGER: + return (xmlSchemaTypeNonPositiveIntegerDef); + case XML_SCHEMAS_NINTEGER: + return (xmlSchemaTypeNegativeIntegerDef); + case XML_SCHEMAS_NNINTEGER: + return (xmlSchemaTypeNonNegativeIntegerDef); + case XML_SCHEMAS_PINTEGER: + return (xmlSchemaTypePositiveIntegerDef); + case XML_SCHEMAS_INT: + return (xmlSchemaTypeIntDef); + case XML_SCHEMAS_UINT: + return (xmlSchemaTypeUnsignedIntDef); + case XML_SCHEMAS_LONG: + return (xmlSchemaTypeLongDef); + case XML_SCHEMAS_ULONG: + return (xmlSchemaTypeUnsignedLongDef); + case XML_SCHEMAS_SHORT: + return (xmlSchemaTypeShortDef); + case XML_SCHEMAS_USHORT: + return (xmlSchemaTypeUnsignedShortDef); + case XML_SCHEMAS_BYTE: + return (xmlSchemaTypeByteDef); + case XML_SCHEMAS_UBYTE: + return (xmlSchemaTypeUnsignedByteDef); + case XML_SCHEMAS_HEXBINARY: + return (xmlSchemaTypeHexBinaryDef); + case XML_SCHEMAS_BASE64BINARY: + return (xmlSchemaTypeBase64BinaryDef); + case XML_SCHEMAS_ANYTYPE: + return (xmlSchemaTypeAnyTypeDef); + default: + return (NULL); + } +} + +/** + * xmlSchemaValueAppend: + * @prev: the value + * @cur: the value to be appended + * + * Appends a next sibling to a list of computed values. + * + * Returns 0 if succeeded and -1 on API errors. + */ +int +xmlSchemaValueAppend(xmlSchemaValPtr prev, xmlSchemaValPtr cur) { + + if ((prev == NULL) || (cur == NULL)) + return (-1); + prev->next = cur; + return (0); +} + +/** + * xmlSchemaValueGetNext: + * @cur: the value + * + * Accessor for the next sibling of a list of computed values. + * + * Returns the next value or NULL if there was none, or on + * API errors. + */ +xmlSchemaValPtr +xmlSchemaValueGetNext(xmlSchemaValPtr cur) { + + if (cur == NULL) + return (NULL); + return (cur->next); +} + +/** + * xmlSchemaValueGetAsString: + * @val: the value + * + * Accessor for the string value of a computed value. + * + * Returns the string value or NULL if there was none, or on + * API errors. + */ +const xmlChar * +xmlSchemaValueGetAsString(xmlSchemaValPtr val) +{ + if (val == NULL) + return (NULL); + switch (val->type) { + case XML_SCHEMAS_STRING: + case XML_SCHEMAS_NORMSTRING: + case XML_SCHEMAS_ANYSIMPLETYPE: + case XML_SCHEMAS_TOKEN: + case XML_SCHEMAS_LANGUAGE: + case XML_SCHEMAS_NMTOKEN: + case XML_SCHEMAS_NAME: + case XML_SCHEMAS_NCNAME: + case XML_SCHEMAS_ID: + case XML_SCHEMAS_IDREF: + case XML_SCHEMAS_ENTITY: + case XML_SCHEMAS_ANYURI: + return (BAD_CAST val->value.str); + default: + break; + } + return (NULL); +} + +/** + * xmlSchemaValueGetAsBoolean: + * @val: the value + * + * Accessor for the boolean value of a computed value. + * + * Returns 1 if true and 0 if false, or in case of an error. Hmm. + */ +int +xmlSchemaValueGetAsBoolean(xmlSchemaValPtr val) +{ + if ((val == NULL) || (val->type != XML_SCHEMAS_BOOLEAN)) + return (0); + return (val->value.b); +} + +/** + * xmlSchemaNewStringValue: + * @type: the value type + * @value: the value + * + * Allocate a new simple type value. The type can be + * of XML_SCHEMAS_STRING. + * WARNING: This one is intended to be expanded for other + * string based types. We need this for anySimpleType as well. + * The given value is consumed and freed with the struct. + * + * Returns a pointer to the new value or NULL in case of error + */ +xmlSchemaValPtr +xmlSchemaNewStringValue(xmlSchemaValType type, + const xmlChar *value) +{ + xmlSchemaValPtr val; + + if (type != XML_SCHEMAS_STRING) + return(NULL); + val = (xmlSchemaValPtr) xmlMalloc(sizeof(xmlSchemaVal)); + if (val == NULL) { + return(NULL); + } + memset(val, 0, sizeof(xmlSchemaVal)); + val->type = type; + val->value.str = (xmlChar *) value; + return(val); +} + +/** + * xmlSchemaNewNOTATIONValue: + * @name: the notation name + * @ns: the notation namespace name or NULL + * + * Allocate a new NOTATION value. + * The given values are consumed and freed with the struct. + * + * Returns a pointer to the new value or NULL in case of error + */ +xmlSchemaValPtr +xmlSchemaNewNOTATIONValue(const xmlChar *name, + const xmlChar *ns) +{ + xmlSchemaValPtr val; + + val = xmlSchemaNewValue(XML_SCHEMAS_NOTATION); + if (val == NULL) + return (NULL); + + val->value.qname.name = (xmlChar *)name; + if (ns != NULL) + val->value.qname.uri = (xmlChar *)ns; + return(val); +} + +/** + * xmlSchemaNewQNameValue: + * @namespaceName: the namespace name + * @localName: the local name + * + * Allocate a new QName value. + * The given values are consumed and freed with the struct. + * + * Returns a pointer to the new value or NULL in case of an error. + */ +xmlSchemaValPtr +xmlSchemaNewQNameValue(const xmlChar *namespaceName, + const xmlChar *localName) +{ + xmlSchemaValPtr val; + + val = xmlSchemaNewValue(XML_SCHEMAS_QNAME); + if (val == NULL) + return (NULL); + + val->value.qname.name = (xmlChar *) localName; + val->value.qname.uri = (xmlChar *) namespaceName; + return(val); +} + +/** + * xmlSchemaFreeValue: + * @value: the value to free + * + * Cleanup the default XML Schemas type library + */ +void +xmlSchemaFreeValue(xmlSchemaValPtr value) { + xmlSchemaValPtr prev; + + while (value != NULL) { + switch (value->type) { + case XML_SCHEMAS_STRING: + case XML_SCHEMAS_NORMSTRING: + case XML_SCHEMAS_TOKEN: + case XML_SCHEMAS_LANGUAGE: + case XML_SCHEMAS_NMTOKEN: + case XML_SCHEMAS_NMTOKENS: + case XML_SCHEMAS_NAME: + case XML_SCHEMAS_NCNAME: + case XML_SCHEMAS_ID: + case XML_SCHEMAS_IDREF: + case XML_SCHEMAS_IDREFS: + case XML_SCHEMAS_ENTITY: + case XML_SCHEMAS_ENTITIES: + case XML_SCHEMAS_ANYURI: + case XML_SCHEMAS_ANYSIMPLETYPE: + if (value->value.str != NULL) + xmlFree(value->value.str); + break; + case XML_SCHEMAS_NOTATION: + case XML_SCHEMAS_QNAME: + if (value->value.qname.uri != NULL) + xmlFree(value->value.qname.uri); + if (value->value.qname.name != NULL) + xmlFree(value->value.qname.name); + break; + case XML_SCHEMAS_HEXBINARY: + if (value->value.hex.str != NULL) + xmlFree(value->value.hex.str); + break; + case XML_SCHEMAS_BASE64BINARY: + if (value->value.base64.str != NULL) + xmlFree(value->value.base64.str); + break; + default: + break; + } + prev = value; + value = value->next; + xmlFree(prev); + } +} + +/** + * xmlSchemaGetPredefinedType: + * @name: the type name + * @ns: the URI of the namespace usually "http://www.w3.org/2001/XMLSchema" + * + * Lookup a type in the default XML Schemas type library + * + * Returns the type if found, NULL otherwise + */ +xmlSchemaTypePtr +xmlSchemaGetPredefinedType(const xmlChar *name, const xmlChar *ns) { + if (xmlSchemaTypesInitialized == 0) + xmlSchemaInitTypes(); + if (name == NULL) + return(NULL); + return((xmlSchemaTypePtr) xmlHashLookup2(xmlSchemaTypesBank, name, ns)); +} + +/** + * xmlSchemaGetBuiltInListSimpleTypeItemType: + * @type: the built-in simple type. + * + * Lookup function + * + * Returns the item type of @type as defined by the built-in datatype + * hierarchy of XML Schema Part 2: Datatypes, or NULL in case of an error. + */ +xmlSchemaTypePtr +xmlSchemaGetBuiltInListSimpleTypeItemType(xmlSchemaTypePtr type) +{ + if ((type == NULL) || (type->type != XML_SCHEMA_TYPE_BASIC)) + return (NULL); + switch (type->builtInType) { + case XML_SCHEMAS_NMTOKENS: + return (xmlSchemaTypeNmtokenDef ); + case XML_SCHEMAS_IDREFS: + return (xmlSchemaTypeIdrefDef); + case XML_SCHEMAS_ENTITIES: + return (xmlSchemaTypeEntityDef); + default: + return (NULL); + } +} + +/**************************************************************** + * * + * Convenience macros and functions * + * * + ****************************************************************/ + +#define IS_TZO_CHAR(c) \ + ((c == 0) || (c == 'Z') || (c == '+') || (c == '-')) + +#define VALID_YEAR(yr) (yr != 0) +#define VALID_MONTH(mon) ((mon >= 1) && (mon <= 12)) +/* VALID_DAY should only be used when month is unknown */ +#define VALID_DAY(day) ((day >= 1) && (day <= 31)) +#define VALID_HOUR(hr) ((hr >= 0) && (hr <= 23)) +#define VALID_MIN(min) ((min >= 0) && (min <= 59)) +#define VALID_SEC(sec) ((sec >= 0) && (sec < 60)) +#define VALID_TZO(tzo) ((tzo > -840) && (tzo < 840)) +#define IS_LEAP(y) \ + (((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0)) + +static const unsigned int daysInMonth[12] = + { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; +static const unsigned int daysInMonthLeap[12] = + { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + +#define MAX_DAYINMONTH(yr,mon) \ + (IS_LEAP(yr) ? daysInMonthLeap[mon - 1] : daysInMonth[mon - 1]) + +#define VALID_MDAY(dt) \ + (IS_LEAP(dt->year) ? \ + (dt->day <= daysInMonthLeap[dt->mon - 1]) : \ + (dt->day <= daysInMonth[dt->mon - 1])) + +#define VALID_DATE(dt) \ + (VALID_YEAR(dt->year) && VALID_MONTH(dt->mon) && VALID_MDAY(dt)) + +#define VALID_TIME(dt) \ + (VALID_HOUR(dt->hour) && VALID_MIN(dt->min) && \ + VALID_SEC(dt->sec) && VALID_TZO(dt->tzo)) + +#define VALID_DATETIME(dt) \ + (VALID_DATE(dt) && VALID_TIME(dt)) + +#define SECS_PER_MIN (60) +#define SECS_PER_HOUR (60 * SECS_PER_MIN) +#define SECS_PER_DAY (24 * SECS_PER_HOUR) + +static const long dayInYearByMonth[12] = + { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; +static const long dayInLeapYearByMonth[12] = + { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 }; + +#define DAY_IN_YEAR(day, month, year) \ + ((IS_LEAP(year) ? \ + dayInLeapYearByMonth[month - 1] : \ + dayInYearByMonth[month - 1]) + day) + +#ifdef DEBUG +#define DEBUG_DATE(dt) \ + xmlGenericError(xmlGenericErrorContext, \ + "type=%o %04ld-%02u-%02uT%02u:%02u:%03f", \ + dt->type,dt->value.date.year,dt->value.date.mon, \ + dt->value.date.day,dt->value.date.hour,dt->value.date.min, \ + dt->value.date.sec); \ + if (dt->value.date.tz_flag) \ + if (dt->value.date.tzo != 0) \ + xmlGenericError(xmlGenericErrorContext, \ + "%+05d\n",dt->value.date.tzo); \ + else \ + xmlGenericError(xmlGenericErrorContext, "Z\n"); \ + else \ + xmlGenericError(xmlGenericErrorContext,"\n") +#else +#define DEBUG_DATE(dt) +#endif + +/** + * _xmlSchemaParseGYear: + * @dt: pointer to a date structure + * @str: pointer to the string to analyze + * + * Parses a xs:gYear without time zone and fills in the appropriate + * field of the @dt structure. @str is updated to point just after the + * xs:gYear. It is supposed that @dt->year is big enough to contain + * the year. + * + * Returns 0 or the error code + */ +static int +_xmlSchemaParseGYear (xmlSchemaValDatePtr dt, const xmlChar **str) { + const xmlChar *cur = *str, *firstChar; + int isneg = 0, digcnt = 0; + + if (((*cur < '0') || (*cur > '9')) && + (*cur != '-') && (*cur != '+')) + return -1; + + if (*cur == '-') { + isneg = 1; + cur++; + } + + firstChar = cur; + + while ((*cur >= '0') && (*cur <= '9')) { + dt->year = dt->year * 10 + (*cur - '0'); + cur++; + digcnt++; + } + + /* year must be at least 4 digits (CCYY); over 4 + * digits cannot have a leading zero. */ + if ((digcnt < 4) || ((digcnt > 4) && (*firstChar == '0'))) + return 1; + + if (isneg) + dt->year = - dt->year; + + if (!VALID_YEAR(dt->year)) + return 2; + + *str = cur; + return 0; +} + +/** + * PARSE_2_DIGITS: + * @num: the integer to fill in + * @cur: an #xmlChar * + * @invalid: an integer + * + * Parses a 2-digits integer and updates @num with the value. @cur is + * updated to point just after the integer. + * In case of error, @invalid is set to %TRUE, values of @num and + * @cur are undefined. + */ +#define PARSE_2_DIGITS(num, cur, invalid) \ + if ((cur[0] < '0') || (cur[0] > '9') || \ + (cur[1] < '0') || (cur[1] > '9')) \ + invalid = 1; \ + else \ + num = (cur[0] - '0') * 10 + (cur[1] - '0'); \ + cur += 2; + +/** + * PARSE_FLOAT: + * @num: the double to fill in + * @cur: an #xmlChar * + * @invalid: an integer + * + * Parses a float and updates @num with the value. @cur is + * updated to point just after the float. The float must have a + * 2-digits integer part and may or may not have a decimal part. + * In case of error, @invalid is set to %TRUE, values of @num and + * @cur are undefined. + */ +#define PARSE_FLOAT(num, cur, invalid) \ + PARSE_2_DIGITS(num, cur, invalid); \ + if (!invalid && (*cur == '.')) { \ + double mult = 1; \ + cur++; \ + if ((*cur < '0') || (*cur > '9')) \ + invalid = 1; \ + while ((*cur >= '0') && (*cur <= '9')) { \ + mult /= 10; \ + num += (*cur - '0') * mult; \ + cur++; \ + } \ + } + +/** + * _xmlSchemaParseGMonth: + * @dt: pointer to a date structure + * @str: pointer to the string to analyze + * + * Parses a xs:gMonth without time zone and fills in the appropriate + * field of the @dt structure. @str is updated to point just after the + * xs:gMonth. + * + * Returns 0 or the error code + */ +static int +_xmlSchemaParseGMonth (xmlSchemaValDatePtr dt, const xmlChar **str) { + const xmlChar *cur = *str; + int ret = 0; + unsigned int value = 0; + + PARSE_2_DIGITS(value, cur, ret); + if (ret != 0) + return ret; + + if (!VALID_MONTH(value)) + return 2; + + dt->mon = value; + + *str = cur; + return 0; +} + +/** + * _xmlSchemaParseGDay: + * @dt: pointer to a date structure + * @str: pointer to the string to analyze + * + * Parses a xs:gDay without time zone and fills in the appropriate + * field of the @dt structure. @str is updated to point just after the + * xs:gDay. + * + * Returns 0 or the error code + */ +static int +_xmlSchemaParseGDay (xmlSchemaValDatePtr dt, const xmlChar **str) { + const xmlChar *cur = *str; + int ret = 0; + unsigned int value = 0; + + PARSE_2_DIGITS(value, cur, ret); + if (ret != 0) + return ret; + + if (!VALID_DAY(value)) + return 2; + + dt->day = value; + *str = cur; + return 0; +} + +/** + * _xmlSchemaParseTime: + * @dt: pointer to a date structure + * @str: pointer to the string to analyze + * + * Parses a xs:time without time zone and fills in the appropriate + * fields of the @dt structure. @str is updated to point just after the + * xs:time. + * In case of error, values of @dt fields are undefined. + * + * Returns 0 or the error code + */ +static int +_xmlSchemaParseTime (xmlSchemaValDatePtr dt, const xmlChar **str) { + const xmlChar *cur = *str; + int ret = 0; + int value = 0; + + PARSE_2_DIGITS(value, cur, ret); + if (ret != 0) + return ret; + if (*cur != ':') + return 1; + if (!VALID_HOUR(value)) + return 2; + cur++; + + /* the ':' insures this string is xs:time */ + dt->hour = value; + + PARSE_2_DIGITS(value, cur, ret); + if (ret != 0) + return ret; + if (!VALID_MIN(value)) + return 2; + dt->min = value; + + if (*cur != ':') + return 1; + cur++; + + PARSE_FLOAT(dt->sec, cur, ret); + if (ret != 0) + return ret; + + if ((!VALID_SEC(dt->sec)) || (!VALID_TZO(dt->tzo))) + return 2; + + *str = cur; + return 0; +} + +/** + * _xmlSchemaParseTimeZone: + * @dt: pointer to a date structure + * @str: pointer to the string to analyze + * + * Parses a time zone without time zone and fills in the appropriate + * field of the @dt structure. @str is updated to point just after the + * time zone. + * + * Returns 0 or the error code + */ +static int +_xmlSchemaParseTimeZone (xmlSchemaValDatePtr dt, const xmlChar **str) { + const xmlChar *cur; + int ret = 0; + + if (str == NULL) + return -1; + cur = *str; + + switch (*cur) { + case 0: + dt->tz_flag = 0; + dt->tzo = 0; + break; + + case 'Z': + dt->tz_flag = 1; + dt->tzo = 0; + cur++; + break; + + case '+': + case '-': { + int isneg = 0, tmp = 0; + isneg = (*cur == '-'); + + cur++; + + PARSE_2_DIGITS(tmp, cur, ret); + if (ret != 0) + return ret; + if (!VALID_HOUR(tmp)) + return 2; + + if (*cur != ':') + return 1; + cur++; + + dt->tzo = tmp * 60; + + PARSE_2_DIGITS(tmp, cur, ret); + if (ret != 0) + return ret; + if (!VALID_MIN(tmp)) + return 2; + + dt->tzo += tmp; + if (isneg) + dt->tzo = - dt->tzo; + + if (!VALID_TZO(dt->tzo)) + return 2; + + dt->tz_flag = 1; + break; + } + default: + return 1; + } + + *str = cur; + return 0; +} + +/** + * _xmlSchemaBase64Decode: + * @ch: a character + * + * Converts a base64 encoded character to its base 64 value. + * + * Returns 0-63 (value), 64 (pad), or -1 (not recognized) + */ +static int +_xmlSchemaBase64Decode (const xmlChar ch) { + if (('A' <= ch) && (ch <= 'Z')) return ch - 'A'; + if (('a' <= ch) && (ch <= 'z')) return ch - 'a' + 26; + if (('0' <= ch) && (ch <= '9')) return ch - '0' + 52; + if ('+' == ch) return 62; + if ('/' == ch) return 63; + if ('=' == ch) return 64; + return -1; +} + +/**************************************************************** + * * + * XML Schema Dates/Times Datatypes Handling * + * * + ****************************************************************/ + +/** + * PARSE_DIGITS: + * @num: the integer to fill in + * @cur: an #xmlChar * + * @num_type: an integer flag + * + * Parses a digits integer and updates @num with the value. @cur is + * updated to point just after the integer. + * In case of error, @num_type is set to -1, values of @num and + * @cur are undefined. + */ +#define PARSE_DIGITS(num, cur, num_type) \ + if ((*cur < '0') || (*cur > '9')) \ + num_type = -1; \ + else \ + while ((*cur >= '0') && (*cur <= '9')) { \ + num = num * 10 + (*cur - '0'); \ + cur++; \ + } + +/** + * PARSE_NUM: + * @num: the double to fill in + * @cur: an #xmlChar * + * @num_type: an integer flag + * + * Parses a float or integer and updates @num with the value. @cur is + * updated to point just after the number. If the number is a float, + * then it must have an integer part and a decimal part; @num_type will + * be set to 1. If there is no decimal part, @num_type is set to zero. + * In case of error, @num_type is set to -1, values of @num and + * @cur are undefined. + */ +#define PARSE_NUM(num, cur, num_type) \ + num = 0; \ + PARSE_DIGITS(num, cur, num_type); \ + if (!num_type && (*cur == '.')) { \ + double mult = 1; \ + cur++; \ + if ((*cur < '0') || (*cur > '9')) \ + num_type = -1; \ + else \ + num_type = 1; \ + while ((*cur >= '0') && (*cur <= '9')) { \ + mult /= 10; \ + num += (*cur - '0') * mult; \ + cur++; \ + } \ + } + +/** + * xmlSchemaValidateDates: + * @type: the expected type or XML_SCHEMAS_UNKNOWN + * @dateTime: string to analyze + * @val: the return computed value + * + * Check that @dateTime conforms to the lexical space of one of the date types. + * if true a value is computed and returned in @val. + * + * Returns 0 if this validates, a positive error code number otherwise + * and -1 in case of internal or API error. + */ +static int +xmlSchemaValidateDates (xmlSchemaValType type, + const xmlChar *dateTime, xmlSchemaValPtr *val, + int collapse) { + xmlSchemaValPtr dt; + int ret; + const xmlChar *cur = dateTime; + +#define RETURN_TYPE_IF_VALID(t) \ + if (IS_TZO_CHAR(*cur)) { \ + ret = _xmlSchemaParseTimeZone(&(dt->value.date), &cur); \ + if (ret == 0) { \ + if (*cur != 0) \ + goto error; \ + dt->type = t; \ + goto done; \ + } \ + } + + if (dateTime == NULL) + return -1; + + if (collapse) + while IS_WSP_BLANK_CH(*cur) cur++; + + if ((*cur != '-') && (*cur < '0') && (*cur > '9')) + return 1; + + dt = xmlSchemaNewValue(XML_SCHEMAS_UNKNOWN); + if (dt == NULL) + return -1; + + if ((cur[0] == '-') && (cur[1] == '-')) { + /* + * It's an incomplete date (xs:gMonthDay, xs:gMonth or + * xs:gDay) + */ + cur += 2; + + /* is it an xs:gDay? */ + if (*cur == '-') { + if (type == XML_SCHEMAS_GMONTH) + goto error; + ++cur; + ret = _xmlSchemaParseGDay(&(dt->value.date), &cur); + if (ret != 0) + goto error; + + RETURN_TYPE_IF_VALID(XML_SCHEMAS_GDAY); + + goto error; + } + + /* + * it should be an xs:gMonthDay or xs:gMonth + */ + ret = _xmlSchemaParseGMonth(&(dt->value.date), &cur); + if (ret != 0) + goto error; + + /* + * a '-' char could indicate this type is xs:gMonthDay or + * a negative time zone offset. Check for xs:gMonthDay first. + * Also the first three char's of a negative tzo (-MM:SS) can + * appear to be a valid day; so even if the day portion + * of the xs:gMonthDay verifies, we must insure it was not + * a tzo. + */ + if (*cur == '-') { + const xmlChar *rewnd = cur; + cur++; + + ret = _xmlSchemaParseGDay(&(dt->value.date), &cur); + if ((ret == 0) && ((*cur == 0) || (*cur != ':'))) { + + /* + * we can use the VALID_MDAY macro to validate the month + * and day because the leap year test will flag year zero + * as a leap year (even though zero is an invalid year). + * FUTURE TODO: Zero will become valid in XML Schema 1.1 + * probably. + */ + if (VALID_MDAY((&(dt->value.date)))) { + + RETURN_TYPE_IF_VALID(XML_SCHEMAS_GMONTHDAY); + + goto error; + } + } + + /* + * not xs:gMonthDay so rewind and check if just xs:gMonth + * with an optional time zone. + */ + cur = rewnd; + } + + RETURN_TYPE_IF_VALID(XML_SCHEMAS_GMONTH); + + goto error; + } + + /* + * It's a right-truncated date or an xs:time. + * Try to parse an xs:time then fallback on right-truncated dates. + */ + if ((*cur >= '0') && (*cur <= '9')) { + ret = _xmlSchemaParseTime(&(dt->value.date), &cur); + if (ret == 0) { + /* it's an xs:time */ + RETURN_TYPE_IF_VALID(XML_SCHEMAS_TIME); + } + } + + /* fallback on date parsing */ + cur = dateTime; + + ret = _xmlSchemaParseGYear(&(dt->value.date), &cur); + if (ret != 0) + goto error; + + /* is it an xs:gYear? */ + RETURN_TYPE_IF_VALID(XML_SCHEMAS_GYEAR); + + if (*cur != '-') + goto error; + cur++; + + ret = _xmlSchemaParseGMonth(&(dt->value.date), &cur); + if (ret != 0) + goto error; + + /* is it an xs:gYearMonth? */ + RETURN_TYPE_IF_VALID(XML_SCHEMAS_GYEARMONTH); + + if (*cur != '-') + goto error; + cur++; + + ret = _xmlSchemaParseGDay(&(dt->value.date), &cur); + if ((ret != 0) || !VALID_DATE((&(dt->value.date)))) + goto error; + + /* is it an xs:date? */ + RETURN_TYPE_IF_VALID(XML_SCHEMAS_DATE); + + if (*cur != 'T') + goto error; + cur++; + + /* it should be an xs:dateTime */ + ret = _xmlSchemaParseTime(&(dt->value.date), &cur); + if (ret != 0) + goto error; + + ret = _xmlSchemaParseTimeZone(&(dt->value.date), &cur); + if (collapse) + while IS_WSP_BLANK_CH(*cur) cur++; + if ((ret != 0) || (*cur != 0) || (!(VALID_DATETIME((&(dt->value.date)))))) + goto error; + + + dt->type = XML_SCHEMAS_DATETIME; + +done: +#if 1 + if ((type != XML_SCHEMAS_UNKNOWN) && (type != dt->type)) + goto error; +#else + /* + * insure the parsed type is equal to or less significant (right + * truncated) than the desired type. + */ + if ((type != XML_SCHEMAS_UNKNOWN) && (type != dt->type)) { + + /* time only matches time */ + if ((type == XML_SCHEMAS_TIME) && (dt->type == XML_SCHEMAS_TIME)) + goto error; + + if ((type == XML_SCHEMAS_DATETIME) && + ((dt->type != XML_SCHEMAS_DATE) || + (dt->type != XML_SCHEMAS_GYEARMONTH) || + (dt->type != XML_SCHEMAS_GYEAR))) + goto error; + + if ((type == XML_SCHEMAS_DATE) && + ((dt->type != XML_SCHEMAS_GYEAR) || + (dt->type != XML_SCHEMAS_GYEARMONTH))) + goto error; + + if ((type == XML_SCHEMAS_GYEARMONTH) && (dt->type != XML_SCHEMAS_GYEAR)) + goto error; + + if ((type == XML_SCHEMAS_GMONTHDAY) && (dt->type != XML_SCHEMAS_GMONTH)) + goto error; + } +#endif + + if (val != NULL) + *val = dt; + else + xmlSchemaFreeValue(dt); + + return 0; + +error: + if (dt != NULL) + xmlSchemaFreeValue(dt); + return 1; +} + +/** + * xmlSchemaValidateDuration: + * @type: the predefined type + * @duration: string to analyze + * @val: the return computed value + * + * Check that @duration conforms to the lexical space of the duration type. + * if true a value is computed and returned in @val. + * + * Returns 0 if this validates, a positive error code number otherwise + * and -1 in case of internal or API error. + */ +static int +xmlSchemaValidateDuration (xmlSchemaTypePtr type ATTRIBUTE_UNUSED, + const xmlChar *duration, xmlSchemaValPtr *val, + int collapse) { + const xmlChar *cur = duration; + xmlSchemaValPtr dur; + int isneg = 0; + unsigned int seq = 0; + double num; + int num_type = 0; /* -1 = invalid, 0 = int, 1 = floating */ + const xmlChar desig[] = {'Y', 'M', 'D', 'H', 'M', 'S'}; + const double multi[] = { 0.0, 0.0, 86400.0, 3600.0, 60.0, 1.0, 0.0}; + + if (duration == NULL) + return -1; + + if (collapse) + while IS_WSP_BLANK_CH(*cur) cur++; + + if (*cur == '-') { + isneg = 1; + cur++; + } + + /* duration must start with 'P' (after sign) */ + if (*cur++ != 'P') + return 1; + + if (*cur == 0) + return 1; + + dur = xmlSchemaNewValue(XML_SCHEMAS_DURATION); + if (dur == NULL) + return -1; + + while (*cur != 0) { + + /* input string should be empty or invalid date/time item */ + if (seq >= sizeof(desig)) + goto error; + + /* T designator must be present for time items */ + if (*cur == 'T') { + if (seq <= 3) { + seq = 3; + cur++; + } else + return 1; + } else if (seq == 3) + goto error; + + /* parse the number portion of the item */ + PARSE_NUM(num, cur, num_type); + + if ((num_type == -1) || (*cur == 0)) + goto error; + + /* update duration based on item type */ + while (seq < sizeof(desig)) { + if (*cur == desig[seq]) { + + /* verify numeric type; only seconds can be float */ + if ((num_type != 0) && (seq < (sizeof(desig)-1))) + goto error; + + switch (seq) { + case 0: + dur->value.dur.mon = (long)num * 12; + break; + case 1: + dur->value.dur.mon += (long)num; + break; + default: + /* convert to seconds using multiplier */ + dur->value.dur.sec += num * multi[seq]; + seq++; + break; + } + + break; /* exit loop */ + } + /* no date designators found? */ + if ((++seq == 3) || (seq == 6)) + goto error; + } + cur++; + if (collapse) + while IS_WSP_BLANK_CH(*cur) cur++; + } + + if (isneg) { + dur->value.dur.mon = -dur->value.dur.mon; + dur->value.dur.day = -dur->value.dur.day; + dur->value.dur.sec = -dur->value.dur.sec; + } + + if (val != NULL) + *val = dur; + else + xmlSchemaFreeValue(dur); + + return 0; + +error: + if (dur != NULL) + xmlSchemaFreeValue(dur); + return 1; +} + +/** + * xmlSchemaStrip: + * @value: a value + * + * Removes the leading and ending spaces of a string + * + * Returns the new string or NULL if no change was required. + */ +static xmlChar * +xmlSchemaStrip(const xmlChar *value) { + const xmlChar *start = value, *end, *f; + + if (value == NULL) return(NULL); + while ((*start != 0) && (IS_BLANK_CH(*start))) start++; + end = start; + while (*end != 0) end++; + f = end; + end--; + while ((end > start) && (IS_BLANK_CH(*end))) end--; + end++; + if ((start == value) && (f == end)) return(NULL); + return(xmlStrndup(start, end - start)); +} + +/** + * xmlSchemaWhiteSpaceReplace: + * @value: a value + * + * Replaces 0xd, 0x9 and 0xa with a space. + * + * Returns the new string or NULL if no change was required. + */ +xmlChar * +xmlSchemaWhiteSpaceReplace(const xmlChar *value) { + const xmlChar *cur = value; + xmlChar *ret = NULL, *mcur; + + if (value == NULL) + return(NULL); + + while ((*cur != 0) && + (((*cur) != 0xd) && ((*cur) != 0x9) && ((*cur) != 0xa))) { + cur++; + } + if (*cur == 0) + return (NULL); + ret = xmlStrdup(value); + /* TODO FIXME: I guess gcc will bark at this. */ + mcur = (xmlChar *) (ret + (cur - value)); + do { + if ( ((*mcur) == 0xd) || ((*mcur) == 0x9) || ((*mcur) == 0xa) ) + *mcur = ' '; + mcur++; + } while (*mcur != 0); + return(ret); +} + +/** + * xmlSchemaCollapseString: + * @value: a value + * + * Removes and normalize white spaces in the string + * + * Returns the new string or NULL if no change was required. + */ +xmlChar * +xmlSchemaCollapseString(const xmlChar *value) { + const xmlChar *start = value, *end, *f; + xmlChar *g; + int col = 0; + + if (value == NULL) return(NULL); + while ((*start != 0) && (IS_BLANK_CH(*start))) start++; + end = start; + while (*end != 0) { + if ((*end == ' ') && (IS_BLANK_CH(end[1]))) { + col = end - start; + break; + } else if ((*end == 0xa) || (*end == 0x9) || (*end == 0xd)) { + col = end - start; + break; + } + end++; + } + if (col == 0) { + f = end; + end--; + while ((end > start) && (IS_BLANK_CH(*end))) end--; + end++; + if ((start == value) && (f == end)) return(NULL); + return(xmlStrndup(start, end - start)); + } + start = xmlStrdup(start); + if (start == NULL) return(NULL); + g = (xmlChar *) (start + col); + end = g; + while (*end != 0) { + if (IS_BLANK_CH(*end)) { + end++; + while (IS_BLANK_CH(*end)) end++; + if (*end != 0) + *g++ = ' '; + } else + *g++ = *end++; + } + *g = 0; + return((xmlChar *) start); +} + +/** + * xmlSchemaValAtomicListNode: + * @type: the predefined atomic type for a token in the list + * @value: the list value to check + * @ret: the return computed value + * @node: the node containing the value + * + * Check that a value conforms to the lexical space of the predefined + * list type. if true a value is computed and returned in @ret. + * + * Returns the number of items if this validates, a negative error code + * number otherwise + */ +static int +xmlSchemaValAtomicListNode(xmlSchemaTypePtr type, const xmlChar *value, + xmlSchemaValPtr *ret, xmlNodePtr node) { + xmlChar *val, *cur, *endval; + int nb_values = 0; + int tmp = 0; + + if (value == NULL) { + return(-1); + } + val = xmlStrdup(value); + if (val == NULL) { + return(-1); + } + if (ret != NULL) { + *ret = NULL; + } + cur = val; + /* + * Split the list + */ + while (IS_BLANK_CH(*cur)) *cur++ = 0; + while (*cur != 0) { + if (IS_BLANK_CH(*cur)) { + *cur = 0; + cur++; + while (IS_BLANK_CH(*cur)) *cur++ = 0; + } else { + nb_values++; + cur++; + while ((*cur != 0) && (!IS_BLANK_CH(*cur))) cur++; + } + } + if (nb_values == 0) { + xmlFree(val); + return(nb_values); + } + endval = cur; + cur = val; + while ((*cur == 0) && (cur != endval)) cur++; + while (cur != endval) { + tmp = xmlSchemaValPredefTypeNode(type, cur, NULL, node); + if (tmp != 0) + break; + while (*cur != 0) cur++; + while ((*cur == 0) && (cur != endval)) cur++; + } + /* TODO what return value ? c.f. bug #158628 + if (ret != NULL) { + TODO + } */ + xmlFree(val); + if (tmp == 0) + return(nb_values); + return(-1); +} + +/** + * xmlSchemaParseUInt: + * @str: pointer to the string R/W + * @llo: pointer to the low result + * @lmi: pointer to the mid result + * @lhi: pointer to the high result + * + * Parse an unsigned long into 3 fields. + * + * Returns the number of significant digits in the number or + * -1 if overflow of the capacity + */ +static int +xmlSchemaParseUInt(const xmlChar **str, unsigned long *llo, + unsigned long *lmi, unsigned long *lhi) { + unsigned long lo = 0, mi = 0, hi = 0; + const xmlChar *tmp, *cur = *str; + int ret = 0, i = 0; + + while (*cur == '0') { /* ignore leading zeroes */ + cur++; + } + tmp = cur; + while ((*tmp != 0) && (*tmp >= '0') && (*tmp <= '9')) { + i++;tmp++;ret++; + } + if (i > 24) { + *str = tmp; + return(-1); + } + while (i > 16) { + hi = hi * 10 + (*cur++ - '0'); + i--; + } + while (i > 8) { + mi = mi * 10 + (*cur++ - '0'); + i--; + } + while (i > 0) { + lo = lo * 10 + (*cur++ - '0'); + i--; + } + + *str = cur; + *llo = lo; + *lmi = mi; + *lhi = hi; + return(ret); +} + +/** + * xmlSchemaValAtomicType: + * @type: the predefined type + * @value: the value to check + * @val: the return computed value + * @node: the node containing the value + * flags: flags to control the vlidation + * + * Check that a value conforms to the lexical space of the atomic type. + * if true a value is computed and returned in @val. + * This checks the value space for list types as well (IDREFS, NMTOKENS). + * + * Returns 0 if this validates, a positive error code number otherwise + * and -1 in case of internal or API error. + */ +static int +xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar * value, + xmlSchemaValPtr * val, xmlNodePtr node, int flags, + xmlSchemaWhitespaceValueType ws, + int normOnTheFly, int applyNorm, int createStringValue) +{ + xmlSchemaValPtr v; + xmlChar *norm = NULL; + int ret = 0; + + if (xmlSchemaTypesInitialized == 0) + xmlSchemaInitTypes(); + if (type == NULL) + return (-1); + + /* + * validating a non existant text node is similar to validating + * an empty one. + */ + if (value == NULL) + value = BAD_CAST ""; + + if (val != NULL) + *val = NULL; + if ((flags == 0) && (value != NULL)) { + + if ((type->builtInType != XML_SCHEMAS_STRING) && + (type->builtInType != XML_SCHEMAS_ANYTYPE) && + (type->builtInType != XML_SCHEMAS_ANYSIMPLETYPE)) { + if (type->builtInType == XML_SCHEMAS_NORMSTRING) + norm = xmlSchemaWhiteSpaceReplace(value); + else + norm = xmlSchemaCollapseString(value); + if (norm != NULL) + value = norm; + } + } + + switch (type->builtInType) { + case XML_SCHEMAS_UNKNOWN: + goto error; + case XML_SCHEMAS_ANYTYPE: + case XML_SCHEMAS_ANYSIMPLETYPE: + if ((createStringValue) && (val != NULL)) { + v = xmlSchemaNewValue(XML_SCHEMAS_ANYSIMPLETYPE); + if (v != NULL) { + v->value.str = xmlStrdup(value); + *val = v; + } else { + goto error; + } + } + goto return0; + case XML_SCHEMAS_STRING: + if (! normOnTheFly) { + const xmlChar *cur = value; + + if (ws == XML_SCHEMA_WHITESPACE_REPLACE) { + while (*cur != 0) { + if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) { + goto return1; + } else { + cur++; + } + } + } else if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE) { + while (*cur != 0) { + if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) { + goto return1; + } else if IS_WSP_SPACE_CH(*cur) { + cur++; + if IS_WSP_SPACE_CH(*cur) + goto return1; + } else { + cur++; + } + } + } + } + if (createStringValue && (val != NULL)) { + if (applyNorm) { + if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE) + norm = xmlSchemaCollapseString(value); + else if (ws == XML_SCHEMA_WHITESPACE_REPLACE) + norm = xmlSchemaWhiteSpaceReplace(value); + if (norm != NULL) + value = norm; + } + v = xmlSchemaNewValue(XML_SCHEMAS_STRING); + if (v != NULL) { + v->value.str = xmlStrdup(value); + *val = v; + } else { + goto error; + } + } + goto return0; + case XML_SCHEMAS_NORMSTRING:{ + if (normOnTheFly) { + if (applyNorm) { + if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE) + norm = xmlSchemaCollapseString(value); + else + norm = xmlSchemaWhiteSpaceReplace(value); + if (norm != NULL) + value = norm; + } + } else { + const xmlChar *cur = value; + while (*cur != 0) { + if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) { + goto return1; + } else { + cur++; + } + } + } + if (val != NULL) { + v = xmlSchemaNewValue(XML_SCHEMAS_NORMSTRING); + if (v != NULL) { + v->value.str = xmlStrdup(value); + *val = v; + } else { + goto error; + } + } + goto return0; + } + case XML_SCHEMAS_DECIMAL:{ + const xmlChar *cur = value; + unsigned int len, neg, integ, hasLeadingZeroes; + xmlChar cval[25]; + xmlChar *cptr = cval; + + if ((cur == NULL) || (*cur == 0)) + goto return1; + + /* + * xs:decimal has a whitespace-facet value of 'collapse'. + */ + if (normOnTheFly) + while IS_WSP_BLANK_CH(*cur) cur++; + + /* + * First we handle an optional sign. + */ + neg = 0; + if (*cur == '-') { + neg = 1; + cur++; + } else if (*cur == '+') + cur++; + /* + * Disallow: "", "-", "- " + */ + if (*cur == 0) + goto return1; + /* + * Next we "pre-parse" the number, in preparation for calling + * the common routine xmlSchemaParseUInt. We get rid of any + * leading zeroes (because we have reserved only 25 chars), + * and note the position of a decimal point. + */ + len = 0; + integ = ~0u; + hasLeadingZeroes = 0; + /* + * Skip leading zeroes. + */ + while (*cur == '0') { + cur++; + hasLeadingZeroes = 1; + } + if (*cur != 0) { + do { + if ((*cur >= '0') && (*cur <= '9')) { + *cptr++ = *cur++; + len++; + } else if (*cur == '.') { + cur++; + integ = len; + do { + if ((*cur >= '0') && (*cur <= '9')) { + *cptr++ = *cur++; + len++; + } else + break; + } while (len < 24); + /* + * Disallow "." but allow "00." + */ + if ((len == 0) && (!hasLeadingZeroes)) + goto return1; + break; + } else + break; + } while (len < 24); + } + if (normOnTheFly) + while IS_WSP_BLANK_CH(*cur) cur++; + if (*cur != 0) + goto return1; /* error if any extraneous chars */ + if (val != NULL) { + v = xmlSchemaNewValue(XML_SCHEMAS_DECIMAL); + if (v != NULL) { + /* + * Now evaluate the significant digits of the number + */ + if (len != 0) { + + if (integ != ~0u) { + /* + * Get rid of trailing zeroes in the + * fractional part. + */ + while ((len != integ) && (*(cptr-1) == '0')) { + cptr--; + len--; + } + } + /* + * Terminate the (preparsed) string. + */ + if (len != 0) { + *cptr = 0; + cptr = cval; + + xmlSchemaParseUInt((const xmlChar **)&cptr, + &v->value.decimal.lo, + &v->value.decimal.mi, + &v->value.decimal.hi); + } + } + /* + * Set the total digits to 1 if a zero value. + */ + v->value.decimal.sign = neg; + if (len == 0) { + /* Speedup for zero values. */ + v->value.decimal.total = 1; + } else { + v->value.decimal.total = len; + if (integ == ~0u) + v->value.decimal.frac = 0; + else + v->value.decimal.frac = len - integ; + } + *val = v; + } + } + goto return0; + } + case XML_SCHEMAS_TIME: + case XML_SCHEMAS_GDAY: + case XML_SCHEMAS_GMONTH: + case XML_SCHEMAS_GMONTHDAY: + case XML_SCHEMAS_GYEAR: + case XML_SCHEMAS_GYEARMONTH: + case XML_SCHEMAS_DATE: + case XML_SCHEMAS_DATETIME: + ret = xmlSchemaValidateDates(type->builtInType, value, val, + normOnTheFly); + break; + case XML_SCHEMAS_DURATION: + ret = xmlSchemaValidateDuration(type, value, val, + normOnTheFly); + break; + case XML_SCHEMAS_FLOAT: + case XML_SCHEMAS_DOUBLE:{ + const xmlChar *cur = value; + int neg = 0; + + if (normOnTheFly) + while IS_WSP_BLANK_CH(*cur) cur++; + + if ((cur[0] == 'N') && (cur[1] == 'a') && (cur[2] == 'N')) { + cur += 3; + if (*cur != 0) + goto return1; + if (val != NULL) { + if (type == xmlSchemaTypeFloatDef) { + v = xmlSchemaNewValue(XML_SCHEMAS_FLOAT); + if (v != NULL) { + v->value.f = (float) xmlXPathNAN; + } else { + xmlSchemaFreeValue(v); + goto error; + } + } else { + v = xmlSchemaNewValue(XML_SCHEMAS_DOUBLE); + if (v != NULL) { + v->value.d = xmlXPathNAN; + } else { + xmlSchemaFreeValue(v); + goto error; + } + } + *val = v; + } + goto return0; + } + if (*cur == '-') { + neg = 1; + cur++; + } + if ((cur[0] == 'I') && (cur[1] == 'N') && (cur[2] == 'F')) { + cur += 3; + if (*cur != 0) + goto return1; + if (val != NULL) { + if (type == xmlSchemaTypeFloatDef) { + v = xmlSchemaNewValue(XML_SCHEMAS_FLOAT); + if (v != NULL) { + if (neg) + v->value.f = (float) xmlXPathNINF; + else + v->value.f = (float) xmlXPathPINF; + } else { + xmlSchemaFreeValue(v); + goto error; + } + } else { + v = xmlSchemaNewValue(XML_SCHEMAS_DOUBLE); + if (v != NULL) { + if (neg) + v->value.d = xmlXPathNINF; + else + v->value.d = xmlXPathPINF; + } else { + xmlSchemaFreeValue(v); + goto error; + } + } + *val = v; + } + goto return0; + } + if ((neg == 0) && (*cur == '+')) + cur++; + if ((cur[0] == 0) || (cur[0] == '+') || (cur[0] == '-')) + goto return1; + while ((*cur >= '0') && (*cur <= '9')) { + cur++; + } + if (*cur == '.') { + cur++; + while ((*cur >= '0') && (*cur <= '9')) + cur++; + } + if ((*cur == 'e') || (*cur == 'E')) { + cur++; + if ((*cur == '-') || (*cur == '+')) + cur++; + while ((*cur >= '0') && (*cur <= '9')) + cur++; + } + if (normOnTheFly) + while IS_WSP_BLANK_CH(*cur) cur++; + + if (*cur != 0) + goto return1; + if (val != NULL) { + if (type == xmlSchemaTypeFloatDef) { + v = xmlSchemaNewValue(XML_SCHEMAS_FLOAT); + if (v != NULL) { + /* + * TODO: sscanf seems not to give the correct + * value for extremely high/low values. + * E.g. "1E-149" results in zero. + */ + if (sscanf((const char *) value, "%f", + &(v->value.f)) == 1) { + *val = v; + } else { + xmlSchemaFreeValue(v); + goto return1; + } + } else { + goto error; + } + } else { + v = xmlSchemaNewValue(XML_SCHEMAS_DOUBLE); + if (v != NULL) { + /* + * TODO: sscanf seems not to give the correct + * value for extremely high/low values. + */ + if (sscanf((const char *) value, "%lf", + &(v->value.d)) == 1) { + *val = v; + } else { + xmlSchemaFreeValue(v); + goto return1; + } + } else { + goto error; + } + } + } + goto return0; + } + case XML_SCHEMAS_BOOLEAN:{ + const xmlChar *cur = value; + + if (normOnTheFly) { + while IS_WSP_BLANK_CH(*cur) cur++; + if (*cur == '0') { + ret = 0; + cur++; + } else if (*cur == '1') { + ret = 1; + cur++; + } else if (*cur == 't') { + cur++; + if ((*cur++ == 'r') && (*cur++ == 'u') && + (*cur++ == 'e')) { + ret = 1; + } else + goto return1; + } else if (*cur == 'f') { + cur++; + if ((*cur++ == 'a') && (*cur++ == 'l') && + (*cur++ == 's') && (*cur++ == 'e')) { + ret = 0; + } else + goto return1; + } else + goto return1; + if (*cur != 0) { + while IS_WSP_BLANK_CH(*cur) cur++; + if (*cur != 0) + goto return1; + } + } else { + if ((cur[0] == '0') && (cur[1] == 0)) + ret = 0; + else if ((cur[0] == '1') && (cur[1] == 0)) + ret = 1; + else if ((cur[0] == 't') && (cur[1] == 'r') + && (cur[2] == 'u') && (cur[3] == 'e') + && (cur[4] == 0)) + ret = 1; + else if ((cur[0] == 'f') && (cur[1] == 'a') + && (cur[2] == 'l') && (cur[3] == 's') + && (cur[4] == 'e') && (cur[5] == 0)) + ret = 0; + else + goto return1; + } + if (val != NULL) { + v = xmlSchemaNewValue(XML_SCHEMAS_BOOLEAN); + if (v != NULL) { + v->value.b = ret; + *val = v; + } else { + goto error; + } + } + goto return0; + } + case XML_SCHEMAS_TOKEN:{ + const xmlChar *cur = value; + + if (! normOnTheFly) { + while (*cur != 0) { + if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) { + goto return1; + } else if (*cur == ' ') { + cur++; + if (*cur == 0) + goto return1; + if (*cur == ' ') + goto return1; + } else { + cur++; + } + } + } + if (val != NULL) { + v = xmlSchemaNewValue(XML_SCHEMAS_TOKEN); + if (v != NULL) { + v->value.str = xmlStrdup(value); + *val = v; + } else { + goto error; + } + } + goto return0; + } + case XML_SCHEMAS_LANGUAGE: + if (normOnTheFly) { + norm = xmlSchemaCollapseString(value); + if (norm != NULL) + value = norm; + } + if (xmlCheckLanguageID(value) == 1) { + if (val != NULL) { + v = xmlSchemaNewValue(XML_SCHEMAS_LANGUAGE); + if (v != NULL) { + v->value.str = xmlStrdup(value); + *val = v; + } else { + goto error; + } + } + goto return0; + } + goto return1; + case XML_SCHEMAS_NMTOKEN: + if (xmlValidateNMToken(value, 1) == 0) { + if (val != NULL) { + v = xmlSchemaNewValue(XML_SCHEMAS_NMTOKEN); + if (v != NULL) { + v->value.str = xmlStrdup(value); + *val = v; + } else { + goto error; + } + } + goto return0; + } + goto return1; + case XML_SCHEMAS_NMTOKENS: + ret = xmlSchemaValAtomicListNode(xmlSchemaTypeNmtokenDef, + value, val, node); + if (ret > 0) + ret = 0; + else + ret = 1; + goto done; + case XML_SCHEMAS_NAME: + ret = xmlValidateName(value, 1); + if ((ret == 0) && (val != NULL) && (value != NULL)) { + v = xmlSchemaNewValue(XML_SCHEMAS_NAME); + if (v != NULL) { + const xmlChar *start = value, *end; + while (IS_BLANK_CH(*start)) start++; + end = start; + while ((*end != 0) && (!IS_BLANK_CH(*end))) end++; + v->value.str = xmlStrndup(start, end - start); + *val = v; + } else { + goto error; + } + } + goto done; + case XML_SCHEMAS_QNAME:{ + const xmlChar *uri = NULL; + xmlChar *local = NULL; + + ret = xmlValidateQName(value, 1); + if (ret != 0) + goto done; + if (node != NULL) { + xmlChar *prefix; + xmlNsPtr ns; + + local = xmlSplitQName2(value, &prefix); + ns = xmlSearchNs(node->doc, node, prefix); + if ((ns == NULL) && (prefix != NULL)) { + xmlFree(prefix); + if (local != NULL) + xmlFree(local); + goto return1; + } + if (ns != NULL) + uri = ns->href; + if (prefix != NULL) + xmlFree(prefix); + } + if (val != NULL) { + v = xmlSchemaNewValue(XML_SCHEMAS_QNAME); + if (v == NULL) { + if (local != NULL) + xmlFree(local); + goto error; + } + if (local != NULL) + v->value.qname.name = local; + else + v->value.qname.name = xmlStrdup(value); + if (uri != NULL) + v->value.qname.uri = xmlStrdup(uri); + *val = v; + } else + if (local != NULL) + xmlFree(local); + goto done; + } + case XML_SCHEMAS_NCNAME: + ret = xmlValidateNCName(value, 1); + if ((ret == 0) && (val != NULL)) { + v = xmlSchemaNewValue(XML_SCHEMAS_NCNAME); + if (v != NULL) { + v->value.str = xmlStrdup(value); + *val = v; + } else { + goto error; + } + } + goto done; + case XML_SCHEMAS_ID: + ret = xmlValidateNCName(value, 1); + if ((ret == 0) && (val != NULL)) { + v = xmlSchemaNewValue(XML_SCHEMAS_ID); + if (v != NULL) { + v->value.str = xmlStrdup(value); + *val = v; + } else { + goto error; + } + } + if ((ret == 0) && (node != NULL) && + (node->type == XML_ATTRIBUTE_NODE)) { + xmlAttrPtr attr = (xmlAttrPtr) node; + + /* + * NOTE: the IDness might have already be declared in the DTD + */ + if (attr->atype != XML_ATTRIBUTE_ID) { + xmlIDPtr res; + xmlChar *strip; + + strip = xmlSchemaStrip(value); + if (strip != NULL) { + res = xmlAddID(NULL, node->doc, strip, attr); + xmlFree(strip); + } else + res = xmlAddID(NULL, node->doc, value, attr); + if (res == NULL) { + ret = 2; + } else { + attr->atype = XML_ATTRIBUTE_ID; + } + } + } + goto done; + case XML_SCHEMAS_IDREF: + ret = xmlValidateNCName(value, 1); + if ((ret == 0) && (val != NULL)) { + v = xmlSchemaNewValue(XML_SCHEMAS_IDREF); + if (v == NULL) + goto error; + v->value.str = xmlStrdup(value); + *val = v; + } + if ((ret == 0) && (node != NULL) && + (node->type == XML_ATTRIBUTE_NODE)) { + xmlAttrPtr attr = (xmlAttrPtr) node; + xmlChar *strip; + + strip = xmlSchemaStrip(value); + if (strip != NULL) { + xmlAddRef(NULL, node->doc, strip, attr); + xmlFree(strip); + } else + xmlAddRef(NULL, node->doc, value, attr); + attr->atype = XML_ATTRIBUTE_IDREF; + } + goto done; + case XML_SCHEMAS_IDREFS: + ret = xmlSchemaValAtomicListNode(xmlSchemaTypeIdrefDef, + value, val, node); + if (ret < 0) + ret = 2; + else + ret = 0; + if ((ret == 0) && (node != NULL) && + (node->type == XML_ATTRIBUTE_NODE)) { + xmlAttrPtr attr = (xmlAttrPtr) node; + + attr->atype = XML_ATTRIBUTE_IDREFS; + } + goto done; + case XML_SCHEMAS_ENTITY:{ + xmlChar *strip; + + ret = xmlValidateNCName(value, 1); + if ((node == NULL) || (node->doc == NULL)) + ret = 3; + if (ret == 0) { + xmlEntityPtr ent; + + strip = xmlSchemaStrip(value); + if (strip != NULL) { + ent = xmlGetDocEntity(node->doc, strip); + xmlFree(strip); + } else { + ent = xmlGetDocEntity(node->doc, value); + } + if ((ent == NULL) || + (ent->etype != + XML_EXTERNAL_GENERAL_UNPARSED_ENTITY)) + ret = 4; + } + if ((ret == 0) && (val != NULL)) { + TODO; + } + if ((ret == 0) && (node != NULL) && + (node->type == XML_ATTRIBUTE_NODE)) { + xmlAttrPtr attr = (xmlAttrPtr) node; + + attr->atype = XML_ATTRIBUTE_ENTITY; + } + goto done; + } + case XML_SCHEMAS_ENTITIES: + if ((node == NULL) || (node->doc == NULL)) + goto return3; + ret = xmlSchemaValAtomicListNode(xmlSchemaTypeEntityDef, + value, val, node); + if (ret <= 0) + ret = 1; + else + ret = 0; + if ((ret == 0) && (node != NULL) && + (node->type == XML_ATTRIBUTE_NODE)) { + xmlAttrPtr attr = (xmlAttrPtr) node; + + attr->atype = XML_ATTRIBUTE_ENTITIES; + } + goto done; + case XML_SCHEMAS_NOTATION:{ + xmlChar *uri = NULL; + xmlChar *local = NULL; + + ret = xmlValidateQName(value, 1); + if ((ret == 0) && (node != NULL)) { + xmlChar *prefix; + + local = xmlSplitQName2(value, &prefix); + if (prefix != NULL) { + xmlNsPtr ns; + + ns = xmlSearchNs(node->doc, node, prefix); + if (ns == NULL) + ret = 1; + else if (val != NULL) + uri = xmlStrdup(ns->href); + } + if ((local != NULL) && ((val == NULL) || (ret != 0))) + xmlFree(local); + if (prefix != NULL) + xmlFree(prefix); + } + if ((node == NULL) || (node->doc == NULL)) + ret = 3; + if (ret == 0) { + ret = xmlValidateNotationUse(NULL, node->doc, value); + if (ret == 1) + ret = 0; + else + ret = 1; + } + if ((ret == 0) && (val != NULL)) { + v = xmlSchemaNewValue(XML_SCHEMAS_NOTATION); + if (v != NULL) { + if (local != NULL) + v->value.qname.name = local; + else + v->value.qname.name = xmlStrdup(value); + if (uri != NULL) + v->value.qname.uri = uri; + + *val = v; + } else { + if (local != NULL) + xmlFree(local); + if (uri != NULL) + xmlFree(uri); + goto error; + } + } + goto done; + } + case XML_SCHEMAS_ANYURI:{ + if (*value != 0) { + xmlURIPtr uri; + if (normOnTheFly) { + norm = xmlSchemaCollapseString(value); + if (norm != NULL) + value = norm; + } + uri = xmlParseURI((const char *) value); + if (uri == NULL) + goto return1; + xmlFreeURI(uri); + } + + if (val != NULL) { + v = xmlSchemaNewValue(XML_SCHEMAS_ANYURI); + if (v == NULL) + goto error; + v->value.str = xmlStrdup(value); + *val = v; + } + goto return0; + } + case XML_SCHEMAS_HEXBINARY:{ + const xmlChar *cur = value, *start; + xmlChar *base; + int total, i = 0; + + if (cur == NULL) + goto return1; + + if (normOnTheFly) + while IS_WSP_BLANK_CH(*cur) cur++; + + start = cur; + while (((*cur >= '0') && (*cur <= '9')) || + ((*cur >= 'A') && (*cur <= 'F')) || + ((*cur >= 'a') && (*cur <= 'f'))) { + i++; + cur++; + } + if (normOnTheFly) + while IS_WSP_BLANK_CH(*cur) cur++; + + if (*cur != 0) + goto return1; + if ((i % 2) != 0) + goto return1; + + if (val != NULL) { + + v = xmlSchemaNewValue(XML_SCHEMAS_HEXBINARY); + if (v == NULL) + goto error; + /* + * Copy only the normalized piece. + * CRITICAL TODO: Check this. + */ + cur = xmlStrndup(start, i); + if (cur == NULL) { + xmlSchemaTypeErrMemory(node, "allocating hexbin data"); + xmlFree(v); + goto return1; + } + + total = i / 2; /* number of octets */ + + base = (xmlChar *) cur; + while (i-- > 0) { + if (*base >= 'a') + *base = *base - ('a' - 'A'); + base++; + } + + v->value.hex.str = (xmlChar *) cur; + v->value.hex.total = total; + *val = v; + } + goto return0; + } + case XML_SCHEMAS_BASE64BINARY:{ + /* ISSUE: + * + * Ignore all stray characters? (yes, currently) + * Worry about long lines? (no, currently) + * + * rfc2045.txt: + * + * "The encoded output stream must be represented in lines of + * no more than 76 characters each. All line breaks or other + * characters not found in Table 1 must be ignored by decoding + * software. In base64 data, characters other than those in + * Table 1, line breaks, and other white space probably + * indicate a transmission error, about which a warning + * message or even a message rejection might be appropriate + * under some circumstances." */ + const xmlChar *cur = value; + xmlChar *base; + int total, i = 0, pad = 0; + + if (cur == NULL) + goto return1; + + for (; *cur; ++cur) { + int decc; + + decc = _xmlSchemaBase64Decode(*cur); + if (decc < 0) ; + else if (decc < 64) + i++; + else + break; + } + for (; *cur; ++cur) { + int decc; + + decc = _xmlSchemaBase64Decode(*cur); + if (decc < 0) ; + else if (decc < 64) + goto return1; + if (decc == 64) + pad++; + } + + /* rfc2045.txt: "Special processing is performed if fewer than + * 24 bits are available at the end of the data being encoded. + * A full encoding quantum is always completed at the end of a + * body. When fewer than 24 input bits are available in an + * input group, zero bits are added (on the right) to form an + * integral number of 6-bit groups. Padding at the end of the + * data is performed using the "=" character. Since all + * base64 input is an integral number of octets, only the + * following cases can arise: (1) the final quantum of + * encoding input is an integral multiple of 24 bits; here, + * the final unit of encoded output will be an integral + * multiple ofindent: Standard input:701: Warning:old style + * assignment ambiguity in "=*". Assuming "= *" 4 characters + * with no "=" padding, (2) the final + * quantum of encoding input is exactly 8 bits; here, the + * final unit of encoded output will be two characters + * followed by two "=" padding characters, or (3) the final + * quantum of encoding input is exactly 16 bits; here, the + * final unit of encoded output will be three characters + * followed by one "=" padding character." */ + + total = 3 * (i / 4); + if (pad == 0) { + if (i % 4 != 0) + goto return1; + } else if (pad == 1) { + int decc; + + if (i % 4 != 3) + goto return1; + for (decc = _xmlSchemaBase64Decode(*cur); + (decc < 0) || (decc > 63); + decc = _xmlSchemaBase64Decode(*cur)) + --cur; + /* 16bits in 24bits means 2 pad bits: nnnnnn nnmmmm mmmm00*/ + /* 00111100 -> 0x3c */ + if (decc & ~0x3c) + goto return1; + total += 2; + } else if (pad == 2) { + int decc; + + if (i % 4 != 2) + goto return1; + for (decc = _xmlSchemaBase64Decode(*cur); + (decc < 0) || (decc > 63); + decc = _xmlSchemaBase64Decode(*cur)) + --cur; + /* 8bits in 12bits means 4 pad bits: nnnnnn nn0000 */ + /* 00110000 -> 0x30 */ + if (decc & ~0x30) + goto return1; + total += 1; + } else + goto return1; + + if (val != NULL) { + v = xmlSchemaNewValue(XML_SCHEMAS_BASE64BINARY); + if (v == NULL) + goto error; + base = + (xmlChar *) xmlMallocAtomic((i + pad + 1) * + sizeof(xmlChar)); + if (base == NULL) { + xmlSchemaTypeErrMemory(node, "allocating base64 data"); + xmlFree(v); + goto return1; + } + v->value.base64.str = base; + for (cur = value; *cur; ++cur) + if (_xmlSchemaBase64Decode(*cur) >= 0) { + *base = *cur; + ++base; + } + *base = 0; + v->value.base64.total = total; + *val = v; + } + goto return0; + } + case XML_SCHEMAS_INTEGER: + case XML_SCHEMAS_PINTEGER: + case XML_SCHEMAS_NPINTEGER: + case XML_SCHEMAS_NINTEGER: + case XML_SCHEMAS_NNINTEGER:{ + const xmlChar *cur = value; + unsigned long lo, mi, hi; + int sign = 0; + + if (cur == NULL) + goto return1; + if (normOnTheFly) + while IS_WSP_BLANK_CH(*cur) cur++; + if (*cur == '-') { + sign = 1; + cur++; + } else if (*cur == '+') + cur++; + ret = xmlSchemaParseUInt(&cur, &lo, &mi, &hi); + if (ret == -1) + goto return1; + if (normOnTheFly) + while IS_WSP_BLANK_CH(*cur) cur++; + if (*cur != 0) + goto return1; + if (type->builtInType == XML_SCHEMAS_NPINTEGER) { + if ((sign == 0) && + ((hi != 0) || (mi != 0) || (lo != 0))) + goto return1; + } else if (type->builtInType == XML_SCHEMAS_PINTEGER) { + if (sign == 1) + goto return1; + if ((hi == 0) && (mi == 0) && (lo == 0)) + goto return1; + } else if (type->builtInType == XML_SCHEMAS_NINTEGER) { + if (sign == 0) + goto return1; + if ((hi == 0) && (mi == 0) && (lo == 0)) + goto return1; + } else if (type->builtInType == XML_SCHEMAS_NNINTEGER) { + if ((sign == 1) && + ((hi != 0) || (mi != 0) || (lo != 0))) + goto return1; + } + if (val != NULL) { + v = xmlSchemaNewValue(type->builtInType); + if (v != NULL) { + if (ret == 0) + ret++; + v->value.decimal.lo = lo; + v->value.decimal.mi = mi; + v->value.decimal.hi = hi; + v->value.decimal.sign = sign; + v->value.decimal.frac = 0; + v->value.decimal.total = ret; + *val = v; + } + } + goto return0; + } + case XML_SCHEMAS_LONG: + case XML_SCHEMAS_BYTE: + case XML_SCHEMAS_SHORT: + case XML_SCHEMAS_INT:{ + const xmlChar *cur = value; + unsigned long lo, mi, hi; + int sign = 0; + + if (cur == NULL) + goto return1; + if (*cur == '-') { + sign = 1; + cur++; + } else if (*cur == '+') + cur++; + ret = xmlSchemaParseUInt(&cur, &lo, &mi, &hi); + if (ret < 0) + goto return1; + if (*cur != 0) + goto return1; + if (type->builtInType == XML_SCHEMAS_LONG) { + if (hi >= 922) { + if (hi > 922) + goto return1; + if (mi >= 33720368) { + if (mi > 33720368) + goto return1; + if ((sign == 0) && (lo > 54775807)) + goto return1; + if ((sign == 1) && (lo > 54775808)) + goto return1; + } + } + } else if (type->builtInType == XML_SCHEMAS_INT) { + if (hi != 0) + goto return1; + if (mi >= 21) { + if (mi > 21) + goto return1; + if ((sign == 0) && (lo > 47483647)) + goto return1; + if ((sign == 1) && (lo > 47483648)) + goto return1; + } + } else if (type->builtInType == XML_SCHEMAS_SHORT) { + if ((mi != 0) || (hi != 0)) + goto return1; + if ((sign == 1) && (lo > 32768)) + goto return1; + if ((sign == 0) && (lo > 32767)) + goto return1; + } else if (type->builtInType == XML_SCHEMAS_BYTE) { + if ((mi != 0) || (hi != 0)) + goto return1; + if ((sign == 1) && (lo > 128)) + goto return1; + if ((sign == 0) && (lo > 127)) + goto return1; + } + if (val != NULL) { + v = xmlSchemaNewValue(type->builtInType); + if (v != NULL) { + v->value.decimal.lo = lo; + v->value.decimal.mi = mi; + v->value.decimal.hi = hi; + v->value.decimal.sign = sign; + v->value.decimal.frac = 0; + v->value.decimal.total = ret; + *val = v; + } + } + goto return0; + } + case XML_SCHEMAS_UINT: + case XML_SCHEMAS_ULONG: + case XML_SCHEMAS_USHORT: + case XML_SCHEMAS_UBYTE:{ + const xmlChar *cur = value; + unsigned long lo, mi, hi; + + if (cur == NULL) + goto return1; + ret = xmlSchemaParseUInt(&cur, &lo, &mi, &hi); + if (ret < 0) + goto return1; + if (*cur != 0) + goto return1; + if (type->builtInType == XML_SCHEMAS_ULONG) { + if (hi >= 1844) { + if (hi > 1844) + goto return1; + if (mi >= 67440737) { + if (mi > 67440737) + goto return1; + if (lo > 9551615) + goto return1; + } + } + } else if (type->builtInType == XML_SCHEMAS_UINT) { + if (hi != 0) + goto return1; + if (mi >= 42) { + if (mi > 42) + goto return1; + if (lo > 94967295) + goto return1; + } + } else if (type->builtInType == XML_SCHEMAS_USHORT) { + if ((mi != 0) || (hi != 0)) + goto return1; + if (lo > 65535) + goto return1; + } else if (type->builtInType == XML_SCHEMAS_UBYTE) { + if ((mi != 0) || (hi != 0)) + goto return1; + if (lo > 255) + goto return1; + } + if (val != NULL) { + v = xmlSchemaNewValue(type->builtInType); + if (v != NULL) { + v->value.decimal.lo = lo; + v->value.decimal.mi = mi; + v->value.decimal.hi = hi; + v->value.decimal.sign = 0; + v->value.decimal.frac = 0; + v->value.decimal.total = ret; + *val = v; + } + } + goto return0; + } + } + + done: + if (norm != NULL) + xmlFree(norm); + return (ret); + return3: + if (norm != NULL) + xmlFree(norm); + return (3); + return1: + if (norm != NULL) + xmlFree(norm); + return (1); + return0: + if (norm != NULL) + xmlFree(norm); + return (0); + error: + if (norm != NULL) + xmlFree(norm); + return (-1); +} + +/** + * xmlSchemaValPredefTypeNode: + * @type: the predefined type + * @value: the value to check + * @val: the return computed value + * @node: the node containing the value + * + * Check that a value conforms to the lexical space of the predefined type. + * if true a value is computed and returned in @val. + * + * Returns 0 if this validates, a positive error code number otherwise + * and -1 in case of internal or API error. + */ +int +xmlSchemaValPredefTypeNode(xmlSchemaTypePtr type, const xmlChar *value, + xmlSchemaValPtr *val, xmlNodePtr node) { + return(xmlSchemaValAtomicType(type, value, val, node, 0, + XML_SCHEMA_WHITESPACE_UNKNOWN, 1, 1, 0)); +} + +/** + * xmlSchemaValPredefTypeNodeNoNorm: + * @type: the predefined type + * @value: the value to check + * @val: the return computed value + * @node: the node containing the value + * + * Check that a value conforms to the lexical space of the predefined type. + * if true a value is computed and returned in @val. + * This one does apply any normalization to the value. + * + * Returns 0 if this validates, a positive error code number otherwise + * and -1 in case of internal or API error. + */ +int +xmlSchemaValPredefTypeNodeNoNorm(xmlSchemaTypePtr type, const xmlChar *value, + xmlSchemaValPtr *val, xmlNodePtr node) { + return(xmlSchemaValAtomicType(type, value, val, node, 1, + XML_SCHEMA_WHITESPACE_UNKNOWN, 1, 0, 1)); +} + +/** + * xmlSchemaValidatePredefinedType: + * @type: the predefined type + * @value: the value to check + * @val: the return computed value + * + * Check that a value conforms to the lexical space of the predefined type. + * if true a value is computed and returned in @val. + * + * Returns 0 if this validates, a positive error code number otherwise + * and -1 in case of internal or API error. + */ +int +xmlSchemaValidatePredefinedType(xmlSchemaTypePtr type, const xmlChar *value, + xmlSchemaValPtr *val) { + return(xmlSchemaValPredefTypeNode(type, value, val, NULL)); +} + +/** + * xmlSchemaCompareDecimals: + * @x: a first decimal value + * @y: a second decimal value + * + * Compare 2 decimals + * + * Returns -1 if x < y, 0 if x == y, 1 if x > y and -2 in case of error + */ +static int +xmlSchemaCompareDecimals(xmlSchemaValPtr x, xmlSchemaValPtr y) +{ + xmlSchemaValPtr swp; + int order = 1, integx, integy, dlen; + unsigned long hi, mi, lo; + + /* + * First test: If x is -ve and not zero + */ + if ((x->value.decimal.sign) && + ((x->value.decimal.lo != 0) || + (x->value.decimal.mi != 0) || + (x->value.decimal.hi != 0))) { + /* + * Then if y is -ve and not zero reverse the compare + */ + if ((y->value.decimal.sign) && + ((y->value.decimal.lo != 0) || + (y->value.decimal.mi != 0) || + (y->value.decimal.hi != 0))) + order = -1; + /* + * Otherwise (y >= 0) we have the answer + */ + else + return (-1); + /* + * If x is not -ve and y is -ve we have the answer + */ + } else if ((y->value.decimal.sign) && + ((y->value.decimal.lo != 0) || + (y->value.decimal.mi != 0) || + (y->value.decimal.hi != 0))) { + return (1); + } + /* + * If it's not simply determined by a difference in sign, + * then we need to compare the actual values of the two nums. + * To do this, we start by looking at the integral parts. + * If the number of integral digits differ, then we have our + * answer. + */ + integx = x->value.decimal.total - x->value.decimal.frac; + integy = y->value.decimal.total - y->value.decimal.frac; + /* + * NOTE: We changed the "total" for values like "0.1" + * (or "-0.1" or ".1") to be 1, which was 2 previously. + * Therefore the special case, when such values are + * compared with 0, needs to be handled separately; + * otherwise a zero would be recognized incorrectly as + * greater than those values. This has the nice side effect + * that we gain an overall optimized comparison with zeroes. + * Note that a "0" has a "total" of 1 already. + */ + if (integx == 1) { + if (x->value.decimal.lo == 0) { + if (integy != 1) + return -order; + else if (y->value.decimal.lo != 0) + return -order; + else + return(0); + } + } + if (integy == 1) { + if (y->value.decimal.lo == 0) { + if (integx != 1) + return order; + else if (x->value.decimal.lo != 0) + return order; + else + return(0); + } + } + + if (integx > integy) + return order; + else if (integy > integx) + return -order; + + /* + * If the number of integral digits is the same for both numbers, + * then things get a little more complicated. We need to "normalize" + * the numbers in order to properly compare them. To do this, we + * look at the total length of each number (length => number of + * significant digits), and divide the "shorter" by 10 (decreasing + * the length) until they are of equal length. + */ + dlen = x->value.decimal.total - y->value.decimal.total; + if (dlen < 0) { /* y has more digits than x */ + swp = x; + hi = y->value.decimal.hi; + mi = y->value.decimal.mi; + lo = y->value.decimal.lo; + dlen = -dlen; + order = -order; + } else { /* x has more digits than y */ + swp = y; + hi = x->value.decimal.hi; + mi = x->value.decimal.mi; + lo = x->value.decimal.lo; + } + while (dlen > 8) { /* in effect, right shift by 10**8 */ + lo = mi; + mi = hi; + hi = 0; + dlen -= 8; + } + while (dlen > 0) { + unsigned long rem1, rem2; + rem1 = (hi % 10) * 100000000L; + hi = hi / 10; + rem2 = (mi % 10) * 100000000L; + mi = (mi + rem1) / 10; + lo = (lo + rem2) / 10; + dlen--; + } + if (hi > swp->value.decimal.hi) { + return order; + } else if (hi == swp->value.decimal.hi) { + if (mi > swp->value.decimal.mi) { + return order; + } else if (mi == swp->value.decimal.mi) { + if (lo > swp->value.decimal.lo) { + return order; + } else if (lo == swp->value.decimal.lo) { + if (x->value.decimal.total == y->value.decimal.total) { + return 0; + } else { + return order; + } + } + } + } + return -order; +} + +/** + * xmlSchemaCompareDurations: + * @x: a first duration value + * @y: a second duration value + * + * Compare 2 durations + * + * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in + * case of error + */ +static int +xmlSchemaCompareDurations(xmlSchemaValPtr x, xmlSchemaValPtr y) +{ + long carry, mon, day; + double sec; + int invert = 1; + long xmon, xday, myear, minday, maxday; + static const long dayRange [2][12] = { + { 0, 28, 59, 89, 120, 150, 181, 212, 242, 273, 303, 334, }, + { 0, 31, 62, 92, 123, 153, 184, 215, 245, 276, 306, 337} }; + + if ((x == NULL) || (y == NULL)) + return -2; + + /* months */ + mon = x->value.dur.mon - y->value.dur.mon; + + /* seconds */ + sec = x->value.dur.sec - y->value.dur.sec; + carry = (long)sec / SECS_PER_DAY; + sec -= (double)(carry * SECS_PER_DAY); + + /* days */ + day = x->value.dur.day - y->value.dur.day + carry; + + /* easy test */ + if (mon == 0) { + if (day == 0) + if (sec == 0.0) + return 0; + else if (sec < 0.0) + return -1; + else + return 1; + else if (day < 0) + return -1; + else + return 1; + } + + if (mon > 0) { + if ((day >= 0) && (sec >= 0.0)) + return 1; + else { + xmon = mon; + xday = -day; + } + } else if ((day <= 0) && (sec <= 0.0)) { + return -1; + } else { + invert = -1; + xmon = -mon; + xday = day; + } + + myear = xmon / 12; + if (myear == 0) { + minday = 0; + maxday = 0; + } else { + maxday = 366 * ((myear + 3) / 4) + + 365 * ((myear - 1) % 4); + minday = maxday - 1; + } + + xmon = xmon % 12; + minday += dayRange[0][xmon]; + maxday += dayRange[1][xmon]; + + if ((maxday == minday) && (maxday == xday)) + return(0); /* can this really happen ? */ + if (maxday < xday) + return(-invert); + if (minday > xday) + return(invert); + + /* indeterminate */ + return 2; +} + +/* + * macros for adding date/times and durations + */ +#define FQUOTIENT(a,b) (floor(((double)a/(double)b))) +#define MODULO(a,b) (a - FQUOTIENT(a,b) * b) +#define FQUOTIENT_RANGE(a,low,high) (FQUOTIENT((a-low),(high-low))) +#define MODULO_RANGE(a,low,high) ((MODULO((a-low),(high-low)))+low) + +/** + * xmlSchemaDupVal: + * @v: the #xmlSchemaValPtr value to duplicate + * + * Makes a copy of @v. The calling program is responsible for freeing + * the returned value. + * + * returns a pointer to a duplicated #xmlSchemaValPtr or NULL if error. + */ +static xmlSchemaValPtr +xmlSchemaDupVal (xmlSchemaValPtr v) +{ + xmlSchemaValPtr ret = xmlSchemaNewValue(v->type); + if (ret == NULL) + return NULL; + + memcpy(ret, v, sizeof(xmlSchemaVal)); + ret->next = NULL; + return ret; +} + +/** + * xmlSchemaCopyValue: + * @val: the precomputed value to be copied + * + * Copies the precomputed value. This duplicates any string within. + * + * Returns the copy or NULL if a copy for a data-type is not implemented. + */ +xmlSchemaValPtr +xmlSchemaCopyValue(xmlSchemaValPtr val) +{ + xmlSchemaValPtr ret = NULL, prev = NULL, cur; + + /* + * Copy the string values. + */ + while (val != NULL) { + switch (val->type) { + case XML_SCHEMAS_ANYTYPE: + case XML_SCHEMAS_IDREFS: + case XML_SCHEMAS_ENTITIES: + case XML_SCHEMAS_NMTOKENS: + xmlSchemaFreeValue(ret); + return (NULL); + case XML_SCHEMAS_ANYSIMPLETYPE: + case XML_SCHEMAS_STRING: + case XML_SCHEMAS_NORMSTRING: + case XML_SCHEMAS_TOKEN: + case XML_SCHEMAS_LANGUAGE: + case XML_SCHEMAS_NAME: + case XML_SCHEMAS_NCNAME: + case XML_SCHEMAS_ID: + case XML_SCHEMAS_IDREF: + case XML_SCHEMAS_ENTITY: + case XML_SCHEMAS_NMTOKEN: + case XML_SCHEMAS_ANYURI: + cur = xmlSchemaDupVal(val); + if (val->value.str != NULL) + cur->value.str = xmlStrdup(BAD_CAST val->value.str); + break; + case XML_SCHEMAS_QNAME: + case XML_SCHEMAS_NOTATION: + cur = xmlSchemaDupVal(val); + if (val->value.qname.name != NULL) + cur->value.qname.name = + xmlStrdup(BAD_CAST val->value.qname.name); + if (val->value.qname.uri != NULL) + cur->value.qname.uri = + xmlStrdup(BAD_CAST val->value.qname.uri); + break; + case XML_SCHEMAS_HEXBINARY: + cur = xmlSchemaDupVal(val); + if (val->value.hex.str != NULL) + cur->value.hex.str = xmlStrdup(BAD_CAST val->value.hex.str); + break; + case XML_SCHEMAS_BASE64BINARY: + cur = xmlSchemaDupVal(val); + if (val->value.base64.str != NULL) + cur->value.base64.str = + xmlStrdup(BAD_CAST val->value.base64.str); + break; + default: + cur = xmlSchemaDupVal(val); + break; + } + if (ret == NULL) + ret = cur; + else + prev->next = cur; + prev = cur; + val = val->next; + } + return (ret); +} + +/** + * _xmlSchemaDateAdd: + * @dt: an #xmlSchemaValPtr + * @dur: an #xmlSchemaValPtr of type #XS_DURATION + * + * Compute a new date/time from @dt and @dur. This function assumes @dt + * is either #XML_SCHEMAS_DATETIME, #XML_SCHEMAS_DATE, #XML_SCHEMAS_GYEARMONTH, + * or #XML_SCHEMAS_GYEAR. The returned #xmlSchemaVal is the same type as + * @dt. The calling program is responsible for freeing the returned value. + * + * Returns a pointer to a new #xmlSchemaVal or NULL if error. + */ +static xmlSchemaValPtr +_xmlSchemaDateAdd (xmlSchemaValPtr dt, xmlSchemaValPtr dur) +{ + xmlSchemaValPtr ret, tmp; + long carry, tempdays, temp; + xmlSchemaValDatePtr r, d; + xmlSchemaValDurationPtr u; + + if ((dt == NULL) || (dur == NULL)) + return NULL; + + ret = xmlSchemaNewValue(dt->type); + if (ret == NULL) + return NULL; + + /* make a copy so we don't alter the original value */ + tmp = xmlSchemaDupVal(dt); + if (tmp == NULL) { + xmlSchemaFreeValue(ret); + return NULL; + } + + r = &(ret->value.date); + d = &(tmp->value.date); + u = &(dur->value.dur); + + /* normalization */ + if (d->mon == 0) + d->mon = 1; + + /* normalize for time zone offset */ + u->sec -= (d->tzo * 60); + d->tzo = 0; + + /* normalization */ + if (d->day == 0) + d->day = 1; + + /* month */ + carry = d->mon + u->mon; + r->mon = (unsigned int) MODULO_RANGE(carry, 1, 13); + carry = (long) FQUOTIENT_RANGE(carry, 1, 13); + + /* year (may be modified later) */ + r->year = d->year + carry; + if (r->year == 0) { + if (d->year > 0) + r->year--; + else + r->year++; + } + + /* time zone */ + r->tzo = d->tzo; + r->tz_flag = d->tz_flag; + + /* seconds */ + r->sec = d->sec + u->sec; + carry = (long) FQUOTIENT((long)r->sec, 60); + if (r->sec != 0.0) { + r->sec = MODULO(r->sec, 60.0); + } + + /* minute */ + carry += d->min; + r->min = (unsigned int) MODULO(carry, 60); + carry = (long) FQUOTIENT(carry, 60); + + /* hours */ + carry += d->hour; + r->hour = (unsigned int) MODULO(carry, 24); + carry = (long)FQUOTIENT(carry, 24); + + /* + * days + * Note we use tempdays because the temporary values may need more + * than 5 bits + */ + if ((VALID_YEAR(r->year)) && (VALID_MONTH(r->mon)) && + (d->day > MAX_DAYINMONTH(r->year, r->mon))) + tempdays = MAX_DAYINMONTH(r->year, r->mon); + else if (d->day < 1) + tempdays = 1; + else + tempdays = d->day; + + tempdays += u->day + carry; + + while (1) { + if (tempdays < 1) { + long tmon = (long) MODULO_RANGE((int)r->mon-1, 1, 13); + long tyr = r->year + (long)FQUOTIENT_RANGE((int)r->mon-1, 1, 13); + if (tyr == 0) + tyr--; + /* + * Coverity detected an overrun in daysInMonth + * of size 12 at position 12 with index variable "((r)->mon - 1)" + */ + if (tmon < 0) + tmon = 0; + if (tmon > 12) + tmon = 12; + tempdays += MAX_DAYINMONTH(tyr, tmon); + carry = -1; + } else if (tempdays > (long) MAX_DAYINMONTH(r->year, r->mon)) { + tempdays = tempdays - MAX_DAYINMONTH(r->year, r->mon); + carry = 1; + } else + break; + + temp = r->mon + carry; + r->mon = (unsigned int) MODULO_RANGE(temp, 1, 13); + r->year = r->year + (unsigned int) FQUOTIENT_RANGE(temp, 1, 13); + if (r->year == 0) { + if (temp < 1) + r->year--; + else + r->year++; + } + } + + r->day = tempdays; + + /* + * adjust the date/time type to the date values + */ + if (ret->type != XML_SCHEMAS_DATETIME) { + if ((r->hour) || (r->min) || (r->sec)) + ret->type = XML_SCHEMAS_DATETIME; + else if (ret->type != XML_SCHEMAS_DATE) { + if ((r->mon != 1) && (r->day != 1)) + ret->type = XML_SCHEMAS_DATE; + else if ((ret->type != XML_SCHEMAS_GYEARMONTH) && (r->mon != 1)) + ret->type = XML_SCHEMAS_GYEARMONTH; + } + } + + xmlSchemaFreeValue(tmp); + + return ret; +} + +/** + * xmlSchemaDateNormalize: + * @dt: an #xmlSchemaValPtr of a date/time type value. + * @offset: number of seconds to adjust @dt by. + * + * Normalize @dt to GMT time. The @offset parameter is subtracted from + * the return value is a time-zone offset is present on @dt. + * + * Returns a normalized copy of @dt or NULL if error. + */ +static xmlSchemaValPtr +xmlSchemaDateNormalize (xmlSchemaValPtr dt, double offset) +{ + xmlSchemaValPtr dur, ret; + + if (dt == NULL) + return NULL; + + if (((dt->type != XML_SCHEMAS_TIME) && + (dt->type != XML_SCHEMAS_DATETIME) && + (dt->type != XML_SCHEMAS_DATE)) || (dt->value.date.tzo == 0)) + return xmlSchemaDupVal(dt); + + dur = xmlSchemaNewValue(XML_SCHEMAS_DURATION); + if (dur == NULL) + return NULL; + + dur->value.date.sec -= offset; + + ret = _xmlSchemaDateAdd(dt, dur); + if (ret == NULL) + return NULL; + + xmlSchemaFreeValue(dur); + + /* ret->value.date.tzo = 0; */ + return ret; +} + +/** + * _xmlSchemaDateCastYMToDays: + * @dt: an #xmlSchemaValPtr + * + * Convert mon and year of @dt to total number of days. Take the + * number of years since (or before) 1 AD and add the number of leap + * years. This is a function because negative + * years must be handled a little differently and there is no zero year. + * + * Returns number of days. + */ +static long +_xmlSchemaDateCastYMToDays (const xmlSchemaValPtr dt) +{ + long ret; + int mon; + + mon = dt->value.date.mon; + if (mon <= 0) mon = 1; /* normalization */ + + if (dt->value.date.year <= 0) + ret = (dt->value.date.year * 365) + + (((dt->value.date.year+1)/4)-((dt->value.date.year+1)/100)+ + ((dt->value.date.year+1)/400)) + + DAY_IN_YEAR(0, mon, dt->value.date.year); + else + ret = ((dt->value.date.year-1) * 365) + + (((dt->value.date.year-1)/4)-((dt->value.date.year-1)/100)+ + ((dt->value.date.year-1)/400)) + + DAY_IN_YEAR(0, mon, dt->value.date.year); + + return ret; +} + +/** + * TIME_TO_NUMBER: + * @dt: an #xmlSchemaValPtr + * + * Calculates the number of seconds in the time portion of @dt. + * + * Returns seconds. + */ +#define TIME_TO_NUMBER(dt) \ + ((double)((dt->value.date.hour * SECS_PER_HOUR) + \ + (dt->value.date.min * SECS_PER_MIN) + \ + (dt->value.date.tzo * SECS_PER_MIN)) + \ + dt->value.date.sec) + +/** + * xmlSchemaCompareDates: + * @x: a first date/time value + * @y: a second date/time value + * + * Compare 2 date/times + * + * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in + * case of error + */ +static int +xmlSchemaCompareDates (xmlSchemaValPtr x, xmlSchemaValPtr y) +{ + unsigned char xmask, ymask, xor_mask, and_mask; + xmlSchemaValPtr p1, p2, q1, q2; + long p1d, p2d, q1d, q2d; + + if ((x == NULL) || (y == NULL)) + return -2; + + if (x->value.date.tz_flag) { + + if (!y->value.date.tz_flag) { + p1 = xmlSchemaDateNormalize(x, 0); + p1d = _xmlSchemaDateCastYMToDays(p1) + p1->value.date.day; + /* normalize y + 14:00 */ + q1 = xmlSchemaDateNormalize(y, (14 * SECS_PER_HOUR)); + + q1d = _xmlSchemaDateCastYMToDays(q1) + q1->value.date.day; + if (p1d < q1d) { + xmlSchemaFreeValue(p1); + xmlSchemaFreeValue(q1); + return -1; + } else if (p1d == q1d) { + double sec; + + sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q1); + if (sec < 0.0) { + xmlSchemaFreeValue(p1); + xmlSchemaFreeValue(q1); + return -1; + } else { + int ret = 0; + /* normalize y - 14:00 */ + q2 = xmlSchemaDateNormalize(y, -(14 * SECS_PER_HOUR)); + q2d = _xmlSchemaDateCastYMToDays(q2) + q2->value.date.day; + if (p1d > q2d) + ret = 1; + else if (p1d == q2d) { + sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q2); + if (sec > 0.0) + ret = 1; + else + ret = 2; /* indeterminate */ + } + xmlSchemaFreeValue(p1); + xmlSchemaFreeValue(q1); + xmlSchemaFreeValue(q2); + if (ret != 0) + return(ret); + } + } else { + xmlSchemaFreeValue(p1); + xmlSchemaFreeValue(q1); + } + } + } else if (y->value.date.tz_flag) { + q1 = xmlSchemaDateNormalize(y, 0); + q1d = _xmlSchemaDateCastYMToDays(q1) + q1->value.date.day; + + /* normalize x - 14:00 */ + p1 = xmlSchemaDateNormalize(x, -(14 * SECS_PER_HOUR)); + p1d = _xmlSchemaDateCastYMToDays(p1) + p1->value.date.day; + + if (p1d < q1d) { + xmlSchemaFreeValue(p1); + xmlSchemaFreeValue(q1); + return -1; + } else if (p1d == q1d) { + double sec; + + sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q1); + if (sec < 0.0) { + xmlSchemaFreeValue(p1); + xmlSchemaFreeValue(q1); + return -1; + } else { + int ret = 0; + /* normalize x + 14:00 */ + p2 = xmlSchemaDateNormalize(x, (14 * SECS_PER_HOUR)); + p2d = _xmlSchemaDateCastYMToDays(p2) + p2->value.date.day; + + if (p2d > q1d) { + ret = 1; + } else if (p2d == q1d) { + sec = TIME_TO_NUMBER(p2) - TIME_TO_NUMBER(q1); + if (sec > 0.0) + ret = 1; + else + ret = 2; /* indeterminate */ + } + xmlSchemaFreeValue(p1); + xmlSchemaFreeValue(q1); + xmlSchemaFreeValue(p2); + if (ret != 0) + return(ret); + } + } else { + xmlSchemaFreeValue(p1); + xmlSchemaFreeValue(q1); + } + } + + /* + * if the same type then calculate the difference + */ + if (x->type == y->type) { + int ret = 0; + q1 = xmlSchemaDateNormalize(y, 0); + q1d = _xmlSchemaDateCastYMToDays(q1) + q1->value.date.day; + + p1 = xmlSchemaDateNormalize(x, 0); + p1d = _xmlSchemaDateCastYMToDays(p1) + p1->value.date.day; + + if (p1d < q1d) { + ret = -1; + } else if (p1d > q1d) { + ret = 1; + } else { + double sec; + + sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q1); + if (sec < 0.0) + ret = -1; + else if (sec > 0.0) + ret = 1; + + } + xmlSchemaFreeValue(p1); + xmlSchemaFreeValue(q1); + return(ret); + } + + switch (x->type) { + case XML_SCHEMAS_DATETIME: + xmask = 0xf; + break; + case XML_SCHEMAS_DATE: + xmask = 0x7; + break; + case XML_SCHEMAS_GYEAR: + xmask = 0x1; + break; + case XML_SCHEMAS_GMONTH: + xmask = 0x2; + break; + case XML_SCHEMAS_GDAY: + xmask = 0x3; + break; + case XML_SCHEMAS_GYEARMONTH: + xmask = 0x3; + break; + case XML_SCHEMAS_GMONTHDAY: + xmask = 0x6; + break; + case XML_SCHEMAS_TIME: + xmask = 0x8; + break; + default: + xmask = 0; + break; + } + + switch (y->type) { + case XML_SCHEMAS_DATETIME: + ymask = 0xf; + break; + case XML_SCHEMAS_DATE: + ymask = 0x7; + break; + case XML_SCHEMAS_GYEAR: + ymask = 0x1; + break; + case XML_SCHEMAS_GMONTH: + ymask = 0x2; + break; + case XML_SCHEMAS_GDAY: + ymask = 0x3; + break; + case XML_SCHEMAS_GYEARMONTH: + ymask = 0x3; + break; + case XML_SCHEMAS_GMONTHDAY: + ymask = 0x6; + break; + case XML_SCHEMAS_TIME: + ymask = 0x8; + break; + default: + ymask = 0; + break; + } + + xor_mask = xmask ^ ymask; /* mark type differences */ + and_mask = xmask & ymask; /* mark field specification */ + + /* year */ + if (xor_mask & 1) + return 2; /* indeterminate */ + else if (and_mask & 1) { + if (x->value.date.year < y->value.date.year) + return -1; + else if (x->value.date.year > y->value.date.year) + return 1; + } + + /* month */ + if (xor_mask & 2) + return 2; /* indeterminate */ + else if (and_mask & 2) { + if (x->value.date.mon < y->value.date.mon) + return -1; + else if (x->value.date.mon > y->value.date.mon) + return 1; + } + + /* day */ + if (xor_mask & 4) + return 2; /* indeterminate */ + else if (and_mask & 4) { + if (x->value.date.day < y->value.date.day) + return -1; + else if (x->value.date.day > y->value.date.day) + return 1; + } + + /* time */ + if (xor_mask & 8) + return 2; /* indeterminate */ + else if (and_mask & 8) { + if (x->value.date.hour < y->value.date.hour) + return -1; + else if (x->value.date.hour > y->value.date.hour) + return 1; + else if (x->value.date.min < y->value.date.min) + return -1; + else if (x->value.date.min > y->value.date.min) + return 1; + else if (x->value.date.sec < y->value.date.sec) + return -1; + else if (x->value.date.sec > y->value.date.sec) + return 1; + } + + return 0; +} + +/** + * xmlSchemaComparePreserveReplaceStrings: + * @x: a first string value + * @y: a second string value + * @invert: inverts the result if x < y or x > y. + * + * Compare 2 string for their normalized values. + * @x is a string with whitespace of "preserve", @y is + * a string with a whitespace of "replace". I.e. @x could + * be an "xsd:string" and @y an "xsd:normalizedString". + * + * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in + * case of error + */ +static int +xmlSchemaComparePreserveReplaceStrings(const xmlChar *x, + const xmlChar *y, + int invert) +{ + int tmp; + + while ((*x != 0) && (*y != 0)) { + if (IS_WSP_REPLACE_CH(*y)) { + if (! IS_WSP_SPACE_CH(*x)) { + if ((*x - 0x20) < 0) { + if (invert) + return(1); + else + return(-1); + } else { + if (invert) + return(-1); + else + return(1); + } + } + } else { + tmp = *x - *y; + if (tmp < 0) { + if (invert) + return(1); + else + return(-1); + } + if (tmp > 0) { + if (invert) + return(-1); + else + return(1); + } + } + x++; + y++; + } + if (*x != 0) { + if (invert) + return(-1); + else + return(1); + } + if (*y != 0) { + if (invert) + return(1); + else + return(-1); + } + return(0); +} + +/** + * xmlSchemaComparePreserveCollapseStrings: + * @x: a first string value + * @y: a second string value + * + * Compare 2 string for their normalized values. + * @x is a string with whitespace of "preserve", @y is + * a string with a whitespace of "collapse". I.e. @x could + * be an "xsd:string" and @y an "xsd:normalizedString". + * + * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in + * case of error + */ +static int +xmlSchemaComparePreserveCollapseStrings(const xmlChar *x, + const xmlChar *y, + int invert) +{ + int tmp; + + /* + * Skip leading blank chars of the collapsed string. + */ + while IS_WSP_BLANK_CH(*y) + y++; + + while ((*x != 0) && (*y != 0)) { + if IS_WSP_BLANK_CH(*y) { + if (! IS_WSP_SPACE_CH(*x)) { + /* + * The yv character would have been replaced to 0x20. + */ + if ((*x - 0x20) < 0) { + if (invert) + return(1); + else + return(-1); + } else { + if (invert) + return(-1); + else + return(1); + } + } + x++; + y++; + /* + * Skip contiguous blank chars of the collapsed string. + */ + while IS_WSP_BLANK_CH(*y) + y++; + } else { + tmp = *x++ - *y++; + if (tmp < 0) { + if (invert) + return(1); + else + return(-1); + } + if (tmp > 0) { + if (invert) + return(-1); + else + return(1); + } + } + } + if (*x != 0) { + if (invert) + return(-1); + else + return(1); + } + if (*y != 0) { + /* + * Skip trailing blank chars of the collapsed string. + */ + while IS_WSP_BLANK_CH(*y) + y++; + if (*y != 0) { + if (invert) + return(1); + else + return(-1); + } + } + return(0); +} + +/** + * xmlSchemaComparePreserveCollapseStrings: + * @x: a first string value + * @y: a second string value + * + * Compare 2 string for their normalized values. + * @x is a string with whitespace of "preserve", @y is + * a string with a whitespace of "collapse". I.e. @x could + * be an "xsd:string" and @y an "xsd:normalizedString". + * + * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in + * case of error + */ +static int +xmlSchemaCompareReplaceCollapseStrings(const xmlChar *x, + const xmlChar *y, + int invert) +{ + int tmp; + + /* + * Skip leading blank chars of the collapsed string. + */ + while IS_WSP_BLANK_CH(*y) + y++; + + while ((*x != 0) && (*y != 0)) { + if IS_WSP_BLANK_CH(*y) { + if (! IS_WSP_BLANK_CH(*x)) { + /* + * The yv character would have been replaced to 0x20. + */ + if ((*x - 0x20) < 0) { + if (invert) + return(1); + else + return(-1); + } else { + if (invert) + return(-1); + else + return(1); + } + } + x++; + y++; + /* + * Skip contiguous blank chars of the collapsed string. + */ + while IS_WSP_BLANK_CH(*y) + y++; + } else { + if IS_WSP_BLANK_CH(*x) { + /* + * The xv character would have been replaced to 0x20. + */ + if ((0x20 - *y) < 0) { + if (invert) + return(1); + else + return(-1); + } else { + if (invert) + return(-1); + else + return(1); + } + } + tmp = *x++ - *y++; + if (tmp < 0) + return(-1); + if (tmp > 0) + return(1); + } + } + if (*x != 0) { + if (invert) + return(-1); + else + return(1); + } + if (*y != 0) { + /* + * Skip trailing blank chars of the collapsed string. + */ + while IS_WSP_BLANK_CH(*y) + y++; + if (*y != 0) { + if (invert) + return(1); + else + return(-1); + } + } + return(0); +} + + +/** + * xmlSchemaCompareReplacedStrings: + * @x: a first string value + * @y: a second string value + * + * Compare 2 string for their normalized values. + * + * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in + * case of error + */ +static int +xmlSchemaCompareReplacedStrings(const xmlChar *x, + const xmlChar *y) +{ + int tmp; + + while ((*x != 0) && (*y != 0)) { + if IS_WSP_BLANK_CH(*y) { + if (! IS_WSP_BLANK_CH(*x)) { + if ((*x - 0x20) < 0) + return(-1); + else + return(1); + } + } else { + if IS_WSP_BLANK_CH(*x) { + if ((0x20 - *y) < 0) + return(-1); + else + return(1); + } + tmp = *x - *y; + if (tmp < 0) + return(-1); + if (tmp > 0) + return(1); + } + x++; + y++; + } + if (*x != 0) + return(1); + if (*y != 0) + return(-1); + return(0); +} + +/** + * xmlSchemaCompareNormStrings: + * @x: a first string value + * @y: a second string value + * + * Compare 2 string for their normalized values. + * + * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in + * case of error + */ +static int +xmlSchemaCompareNormStrings(const xmlChar *x, + const xmlChar *y) { + int tmp; + + while (IS_BLANK_CH(*x)) x++; + while (IS_BLANK_CH(*y)) y++; + while ((*x != 0) && (*y != 0)) { + if (IS_BLANK_CH(*x)) { + if (!IS_BLANK_CH(*y)) { + tmp = *x - *y; + return(tmp); + } + while (IS_BLANK_CH(*x)) x++; + while (IS_BLANK_CH(*y)) y++; + } else { + tmp = *x++ - *y++; + if (tmp < 0) + return(-1); + if (tmp > 0) + return(1); + } + } + if (*x != 0) { + while (IS_BLANK_CH(*x)) x++; + if (*x != 0) + return(1); + } + if (*y != 0) { + while (IS_BLANK_CH(*y)) y++; + if (*y != 0) + return(-1); + } + return(0); +} + +/** + * xmlSchemaCompareFloats: + * @x: a first float or double value + * @y: a second float or double value + * + * Compare 2 values + * + * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in + * case of error + */ +static int +xmlSchemaCompareFloats(xmlSchemaValPtr x, xmlSchemaValPtr y) { + double d1, d2; + + if ((x == NULL) || (y == NULL)) + return(-2); + + /* + * Cast everything to doubles. + */ + if (x->type == XML_SCHEMAS_DOUBLE) + d1 = x->value.d; + else if (x->type == XML_SCHEMAS_FLOAT) + d1 = x->value.f; + else + return(-2); + + if (y->type == XML_SCHEMAS_DOUBLE) + d2 = y->value.d; + else if (y->type == XML_SCHEMAS_FLOAT) + d2 = y->value.f; + else + return(-2); + + /* + * Check for special cases. + */ + if (xmlXPathIsNaN(d1)) { + if (xmlXPathIsNaN(d2)) + return(0); + return(1); + } + if (xmlXPathIsNaN(d2)) + return(-1); + if (d1 == xmlXPathPINF) { + if (d2 == xmlXPathPINF) + return(0); + return(1); + } + if (d2 == xmlXPathPINF) + return(-1); + if (d1 == xmlXPathNINF) { + if (d2 == xmlXPathNINF) + return(0); + return(-1); + } + if (d2 == xmlXPathNINF) + return(1); + + /* + * basic tests, the last one we should have equality, but + * portability is more important than speed and handling + * NaN or Inf in a portable way is always a challenge, so ... + */ + if (d1 < d2) + return(-1); + if (d1 > d2) + return(1); + if (d1 == d2) + return(0); + return(2); +} + +/** + * xmlSchemaCompareValues: + * @x: a first value + * @xvalue: the first value as a string (optional) + * @xwtsp: the whitespace type + * @y: a second value + * @xvalue: the second value as a string (optional) + * @ywtsp: the whitespace type + * + * Compare 2 values + * + * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, 3 if not + * comparable and -2 in case of error + */ +static int +xmlSchemaCompareValuesInternal(xmlSchemaValType xtype, + xmlSchemaValPtr x, + const xmlChar *xvalue, + xmlSchemaWhitespaceValueType xws, + xmlSchemaValType ytype, + xmlSchemaValPtr y, + const xmlChar *yvalue, + xmlSchemaWhitespaceValueType yws) +{ + switch (xtype) { + case XML_SCHEMAS_UNKNOWN: + case XML_SCHEMAS_ANYTYPE: + return(-2); + case XML_SCHEMAS_INTEGER: + case XML_SCHEMAS_NPINTEGER: + case XML_SCHEMAS_NINTEGER: + case XML_SCHEMAS_NNINTEGER: + case XML_SCHEMAS_PINTEGER: + case XML_SCHEMAS_INT: + case XML_SCHEMAS_UINT: + case XML_SCHEMAS_LONG: + case XML_SCHEMAS_ULONG: + case XML_SCHEMAS_SHORT: + case XML_SCHEMAS_USHORT: + case XML_SCHEMAS_BYTE: + case XML_SCHEMAS_UBYTE: + case XML_SCHEMAS_DECIMAL: + if ((x == NULL) || (y == NULL)) + return(-2); + if (ytype == xtype) + return(xmlSchemaCompareDecimals(x, y)); + if ((ytype == XML_SCHEMAS_DECIMAL) || + (ytype == XML_SCHEMAS_INTEGER) || + (ytype == XML_SCHEMAS_NPINTEGER) || + (ytype == XML_SCHEMAS_NINTEGER) || + (ytype == XML_SCHEMAS_NNINTEGER) || + (ytype == XML_SCHEMAS_PINTEGER) || + (ytype == XML_SCHEMAS_INT) || + (ytype == XML_SCHEMAS_UINT) || + (ytype == XML_SCHEMAS_LONG) || + (ytype == XML_SCHEMAS_ULONG) || + (ytype == XML_SCHEMAS_SHORT) || + (ytype == XML_SCHEMAS_USHORT) || + (ytype == XML_SCHEMAS_BYTE) || + (ytype == XML_SCHEMAS_UBYTE)) + return(xmlSchemaCompareDecimals(x, y)); + return(-2); + case XML_SCHEMAS_DURATION: + if ((x == NULL) || (y == NULL)) + return(-2); + if (ytype == XML_SCHEMAS_DURATION) + return(xmlSchemaCompareDurations(x, y)); + return(-2); + case XML_SCHEMAS_TIME: + case XML_SCHEMAS_GDAY: + case XML_SCHEMAS_GMONTH: + case XML_SCHEMAS_GMONTHDAY: + case XML_SCHEMAS_GYEAR: + case XML_SCHEMAS_GYEARMONTH: + case XML_SCHEMAS_DATE: + case XML_SCHEMAS_DATETIME: + if ((x == NULL) || (y == NULL)) + return(-2); + if ((ytype == XML_SCHEMAS_DATETIME) || + (ytype == XML_SCHEMAS_TIME) || + (ytype == XML_SCHEMAS_GDAY) || + (ytype == XML_SCHEMAS_GMONTH) || + (ytype == XML_SCHEMAS_GMONTHDAY) || + (ytype == XML_SCHEMAS_GYEAR) || + (ytype == XML_SCHEMAS_DATE) || + (ytype == XML_SCHEMAS_GYEARMONTH)) + return (xmlSchemaCompareDates(x, y)); + return (-2); + /* + * Note that we will support comparison of string types against + * anySimpleType as well. + */ + case XML_SCHEMAS_ANYSIMPLETYPE: + case XML_SCHEMAS_STRING: + case XML_SCHEMAS_NORMSTRING: + case XML_SCHEMAS_TOKEN: + case XML_SCHEMAS_LANGUAGE: + case XML_SCHEMAS_NMTOKEN: + case XML_SCHEMAS_NAME: + case XML_SCHEMAS_NCNAME: + case XML_SCHEMAS_ID: + case XML_SCHEMAS_IDREF: + case XML_SCHEMAS_ENTITY: + case XML_SCHEMAS_ANYURI: + { + const xmlChar *xv, *yv; + + if (x == NULL) + xv = xvalue; + else + xv = x->value.str; + if (y == NULL) + yv = yvalue; + else + yv = y->value.str; + /* + * TODO: Compare those against QName. + */ + if (ytype == XML_SCHEMAS_QNAME) { + TODO + if (y == NULL) + return(-2); + return (-2); + } + if ((ytype == XML_SCHEMAS_ANYSIMPLETYPE) || + (ytype == XML_SCHEMAS_STRING) || + (ytype == XML_SCHEMAS_NORMSTRING) || + (ytype == XML_SCHEMAS_TOKEN) || + (ytype == XML_SCHEMAS_LANGUAGE) || + (ytype == XML_SCHEMAS_NMTOKEN) || + (ytype == XML_SCHEMAS_NAME) || + (ytype == XML_SCHEMAS_NCNAME) || + (ytype == XML_SCHEMAS_ID) || + (ytype == XML_SCHEMAS_IDREF) || + (ytype == XML_SCHEMAS_ENTITY) || + (ytype == XML_SCHEMAS_ANYURI)) { + + if (xws == XML_SCHEMA_WHITESPACE_PRESERVE) { + + if (yws == XML_SCHEMA_WHITESPACE_PRESERVE) { + /* TODO: What about x < y or x > y. */ + if (xmlStrEqual(xv, yv)) + return (0); + else + return (2); + } else if (yws == XML_SCHEMA_WHITESPACE_REPLACE) + return (xmlSchemaComparePreserveReplaceStrings(xv, yv, 0)); + else if (yws == XML_SCHEMA_WHITESPACE_COLLAPSE) + return (xmlSchemaComparePreserveCollapseStrings(xv, yv, 0)); + + } else if (xws == XML_SCHEMA_WHITESPACE_REPLACE) { + + if (yws == XML_SCHEMA_WHITESPACE_PRESERVE) + return (xmlSchemaComparePreserveReplaceStrings(yv, xv, 1)); + if (yws == XML_SCHEMA_WHITESPACE_REPLACE) + return (xmlSchemaCompareReplacedStrings(xv, yv)); + if (yws == XML_SCHEMA_WHITESPACE_COLLAPSE) + return (xmlSchemaCompareReplaceCollapseStrings(xv, yv, 0)); + + } else if (xws == XML_SCHEMA_WHITESPACE_COLLAPSE) { + + if (yws == XML_SCHEMA_WHITESPACE_PRESERVE) + return (xmlSchemaComparePreserveCollapseStrings(yv, xv, 1)); + if (yws == XML_SCHEMA_WHITESPACE_REPLACE) + return (xmlSchemaCompareReplaceCollapseStrings(yv, xv, 1)); + if (yws == XML_SCHEMA_WHITESPACE_COLLAPSE) + return (xmlSchemaCompareNormStrings(xv, yv)); + } else + return (-2); + + } + return (-2); + } + case XML_SCHEMAS_QNAME: + case XML_SCHEMAS_NOTATION: + if ((x == NULL) || (y == NULL)) + return(-2); + if ((ytype == XML_SCHEMAS_QNAME) || + (ytype == XML_SCHEMAS_NOTATION)) { + if ((xmlStrEqual(x->value.qname.name, y->value.qname.name)) && + (xmlStrEqual(x->value.qname.uri, y->value.qname.uri))) + return(0); + return(2); + } + return (-2); + case XML_SCHEMAS_FLOAT: + case XML_SCHEMAS_DOUBLE: + if ((x == NULL) || (y == NULL)) + return(-2); + if ((ytype == XML_SCHEMAS_FLOAT) || + (ytype == XML_SCHEMAS_DOUBLE)) + return (xmlSchemaCompareFloats(x, y)); + return (-2); + case XML_SCHEMAS_BOOLEAN: + if ((x == NULL) || (y == NULL)) + return(-2); + if (ytype == XML_SCHEMAS_BOOLEAN) { + if (x->value.b == y->value.b) + return(0); + if (x->value.b == 0) + return(-1); + return(1); + } + return (-2); + case XML_SCHEMAS_HEXBINARY: + if ((x == NULL) || (y == NULL)) + return(-2); + if (ytype == XML_SCHEMAS_HEXBINARY) { + if (x->value.hex.total == y->value.hex.total) { + int ret = xmlStrcmp(x->value.hex.str, y->value.hex.str); + if (ret > 0) + return(1); + else if (ret == 0) + return(0); + } + else if (x->value.hex.total > y->value.hex.total) + return(1); + + return(-1); + } + return (-2); + case XML_SCHEMAS_BASE64BINARY: + if ((x == NULL) || (y == NULL)) + return(-2); + if (ytype == XML_SCHEMAS_BASE64BINARY) { + if (x->value.base64.total == y->value.base64.total) { + int ret = xmlStrcmp(x->value.base64.str, + y->value.base64.str); + if (ret > 0) + return(1); + else if (ret == 0) + return(0); + else + return(-1); + } + else if (x->value.base64.total > y->value.base64.total) + return(1); + else + return(-1); + } + return (-2); + case XML_SCHEMAS_IDREFS: + case XML_SCHEMAS_ENTITIES: + case XML_SCHEMAS_NMTOKENS: + TODO + break; + } + return -2; +} + +/** + * xmlSchemaCompareValues: + * @x: a first value + * @y: a second value + * + * Compare 2 values + * + * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in + * case of error + */ +int +xmlSchemaCompareValues(xmlSchemaValPtr x, xmlSchemaValPtr y) { + xmlSchemaWhitespaceValueType xws, yws; + + if ((x == NULL) || (y == NULL)) + return(-2); + if (x->type == XML_SCHEMAS_STRING) + xws = XML_SCHEMA_WHITESPACE_PRESERVE; + else if (x->type == XML_SCHEMAS_NORMSTRING) + xws = XML_SCHEMA_WHITESPACE_REPLACE; + else + xws = XML_SCHEMA_WHITESPACE_COLLAPSE; + + if (y->type == XML_SCHEMAS_STRING) + yws = XML_SCHEMA_WHITESPACE_PRESERVE; + else if (x->type == XML_SCHEMAS_NORMSTRING) + yws = XML_SCHEMA_WHITESPACE_REPLACE; + else + yws = XML_SCHEMA_WHITESPACE_COLLAPSE; + + return(xmlSchemaCompareValuesInternal(x->type, x, NULL, xws, y->type, + y, NULL, yws)); +} + +/** + * xmlSchemaCompareValuesWhtsp: + * @x: a first value + * @xws: the whitespace value of x + * @y: a second value + * @yws: the whitespace value of y + * + * Compare 2 values + * + * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in + * case of error + */ +int +xmlSchemaCompareValuesWhtsp(xmlSchemaValPtr x, + xmlSchemaWhitespaceValueType xws, + xmlSchemaValPtr y, + xmlSchemaWhitespaceValueType yws) +{ + if ((x == NULL) || (y == NULL)) + return(-2); + return(xmlSchemaCompareValuesInternal(x->type, x, NULL, xws, y->type, + y, NULL, yws)); +} + +/** + * xmlSchemaCompareValuesWhtspExt: + * @x: a first value + * @xws: the whitespace value of x + * @y: a second value + * @yws: the whitespace value of y + * + * Compare 2 values + * + * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in + * case of error + */ +static int +xmlSchemaCompareValuesWhtspExt(xmlSchemaValType xtype, + xmlSchemaValPtr x, + const xmlChar *xvalue, + xmlSchemaWhitespaceValueType xws, + xmlSchemaValType ytype, + xmlSchemaValPtr y, + const xmlChar *yvalue, + xmlSchemaWhitespaceValueType yws) +{ + return(xmlSchemaCompareValuesInternal(xtype, x, xvalue, xws, ytype, y, + yvalue, yws)); +} + +/** + * xmlSchemaNormLen: + * @value: a string + * + * Computes the UTF8 length of the normalized value of the string + * + * Returns the length or -1 in case of error. + */ +static int +xmlSchemaNormLen(const xmlChar *value) { + const xmlChar *utf; + int ret = 0; + + if (value == NULL) + return(-1); + utf = value; + while (IS_BLANK_CH(*utf)) utf++; + while (*utf != 0) { + if (utf[0] & 0x80) { + if ((utf[1] & 0xc0) != 0x80) + return(-1); + if ((utf[0] & 0xe0) == 0xe0) { + if ((utf[2] & 0xc0) != 0x80) + return(-1); + if ((utf[0] & 0xf0) == 0xf0) { + if ((utf[0] & 0xf8) != 0xf0 || (utf[3] & 0xc0) != 0x80) + return(-1); + utf += 4; + } else { + utf += 3; + } + } else { + utf += 2; + } + } else if (IS_BLANK_CH(*utf)) { + while (IS_BLANK_CH(*utf)) utf++; + if (*utf == 0) + break; + } else { + utf++; + } + ret++; + } + return(ret); +} + +/** + * xmlSchemaGetFacetValueAsULong: + * @facet: an schemas type facet + * + * Extract the value of a facet + * + * Returns the value as a long + */ +unsigned long +xmlSchemaGetFacetValueAsULong(xmlSchemaFacetPtr facet) +{ + /* + * TODO: Check if this is a decimal. + */ + if (facet == NULL) + return 0; + return ((unsigned long) facet->val->value.decimal.lo); +} + +/** + * xmlSchemaValidateListSimpleTypeFacet: + * @facet: the facet to check + * @value: the lexical repr of the value to validate + * @actualLen: the number of list items + * @expectedLen: the resulting expected number of list items + * + * Checks the value of a list simple type against a facet. + * + * Returns 0 if the value is valid, a positive error code + * number otherwise and -1 in case of an internal error. + */ +int +xmlSchemaValidateListSimpleTypeFacet(xmlSchemaFacetPtr facet, + const xmlChar *value, + unsigned long actualLen, + unsigned long *expectedLen) +{ + if (facet == NULL) + return(-1); + /* + * TODO: Check if this will work with large numbers. + * (compare value.decimal.mi and value.decimal.hi as well?). + */ + if (facet->type == XML_SCHEMA_FACET_LENGTH) { + if (actualLen != facet->val->value.decimal.lo) { + if (expectedLen != NULL) + *expectedLen = facet->val->value.decimal.lo; + return (XML_SCHEMAV_CVC_LENGTH_VALID); + } + } else if (facet->type == XML_SCHEMA_FACET_MINLENGTH) { + if (actualLen < facet->val->value.decimal.lo) { + if (expectedLen != NULL) + *expectedLen = facet->val->value.decimal.lo; + return (XML_SCHEMAV_CVC_MINLENGTH_VALID); + } + } else if (facet->type == XML_SCHEMA_FACET_MAXLENGTH) { + if (actualLen > facet->val->value.decimal.lo) { + if (expectedLen != NULL) + *expectedLen = facet->val->value.decimal.lo; + return (XML_SCHEMAV_CVC_MAXLENGTH_VALID); + } + } else + /* + * NOTE: That we can pass NULL as xmlSchemaValPtr to + * xmlSchemaValidateFacet, since the remaining facet types + * are: XML_SCHEMA_FACET_PATTERN, XML_SCHEMA_FACET_ENUMERATION. + */ + return(xmlSchemaValidateFacet(NULL, facet, value, NULL)); + return (0); +} + +/** + * xmlSchemaValidateLengthFacet: + * @type: the built-in type + * @facet: the facet to check + * @value: the lexical repr. of the value to be validated + * @val: the precomputed value + * @ws: the whitespace type of the value + * @length: the actual length of the value + * + * Checka a value against a "length", "minLength" and "maxLength" + * facet; sets @length to the computed length of @value. + * + * Returns 0 if the value is valid, a positive error code + * otherwise and -1 in case of an internal or API error. + */ +static int +xmlSchemaValidateLengthFacetInternal(xmlSchemaFacetPtr facet, + xmlSchemaTypeType valType, + const xmlChar *value, + xmlSchemaValPtr val, + unsigned long *length, + xmlSchemaWhitespaceValueType ws) +{ + unsigned int len = 0; + + if ((length == NULL) || (facet == NULL)) + return (-1); + *length = 0; + if ((facet->type != XML_SCHEMA_FACET_LENGTH) && + (facet->type != XML_SCHEMA_FACET_MAXLENGTH) && + (facet->type != XML_SCHEMA_FACET_MINLENGTH)) + return (-1); + + /* + * TODO: length, maxLength and minLength must be of type + * nonNegativeInteger only. Check if decimal is used somehow. + */ + if ((facet->val == NULL) || + ((facet->val->type != XML_SCHEMAS_DECIMAL) && + (facet->val->type != XML_SCHEMAS_NNINTEGER)) || + (facet->val->value.decimal.frac != 0)) { + return(-1); + } + if ((val != NULL) && (val->type == XML_SCHEMAS_HEXBINARY)) + len = val->value.hex.total; + else if ((val != NULL) && (val->type == XML_SCHEMAS_BASE64BINARY)) + len = val->value.base64.total; + else { + switch (valType) { + case XML_SCHEMAS_STRING: + case XML_SCHEMAS_NORMSTRING: + if (ws == XML_SCHEMA_WHITESPACE_UNKNOWN) { + /* + * This is to ensure API compatibility with the old + * xmlSchemaValidateLengthFacet(). Anyway, this was and + * is not the correct handling. + * TODO: Get rid of this case somehow. + */ + if (valType == XML_SCHEMAS_STRING) + len = xmlUTF8Strlen(value); + else + len = xmlSchemaNormLen(value); + } else if (value != NULL) { + if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE) + len = xmlSchemaNormLen(value); + else + /* + * Should be OK for "preserve" as well. + */ + len = xmlUTF8Strlen(value); + } + break; + case XML_SCHEMAS_IDREF: + case XML_SCHEMAS_TOKEN: + case XML_SCHEMAS_LANGUAGE: + case XML_SCHEMAS_NMTOKEN: + case XML_SCHEMAS_NAME: + case XML_SCHEMAS_NCNAME: + case XML_SCHEMAS_ID: + /* + * FIXME: What exactly to do with anyURI? + */ + case XML_SCHEMAS_ANYURI: + if (value != NULL) + len = xmlSchemaNormLen(value); + break; + case XML_SCHEMAS_QNAME: + case XML_SCHEMAS_NOTATION: + /* + * For QName and NOTATION, those facets are + * deprecated and should be ignored. + */ + return (0); + default: + TODO + } + } + *length = (unsigned long) len; + /* + * TODO: Return the whole expected value, i.e. "lo", "mi" and "hi". + */ + if (facet->type == XML_SCHEMA_FACET_LENGTH) { + if (len != facet->val->value.decimal.lo) + return(XML_SCHEMAV_CVC_LENGTH_VALID); + } else if (facet->type == XML_SCHEMA_FACET_MINLENGTH) { + if (len < facet->val->value.decimal.lo) + return(XML_SCHEMAV_CVC_MINLENGTH_VALID); + } else { + if (len > facet->val->value.decimal.lo) + return(XML_SCHEMAV_CVC_MAXLENGTH_VALID); + } + + return (0); +} + +/** + * xmlSchemaValidateLengthFacet: + * @type: the built-in type + * @facet: the facet to check + * @value: the lexical repr. of the value to be validated + * @val: the precomputed value + * @length: the actual length of the value + * + * Checka a value against a "length", "minLength" and "maxLength" + * facet; sets @length to the computed length of @value. + * + * Returns 0 if the value is valid, a positive error code + * otherwise and -1 in case of an internal or API error. + */ +int +xmlSchemaValidateLengthFacet(xmlSchemaTypePtr type, + xmlSchemaFacetPtr facet, + const xmlChar *value, + xmlSchemaValPtr val, + unsigned long *length) +{ + if (type == NULL) + return(-1); + return (xmlSchemaValidateLengthFacetInternal(facet, + type->builtInType, value, val, length, + XML_SCHEMA_WHITESPACE_UNKNOWN)); +} + +/** + * xmlSchemaValidateLengthFacetWhtsp: + * @facet: the facet to check + * @valType: the built-in type + * @value: the lexical repr. of the value to be validated + * @val: the precomputed value + * @ws: the whitespace type of the value + * @length: the actual length of the value + * + * Checka a value against a "length", "minLength" and "maxLength" + * facet; sets @length to the computed length of @value. + * + * Returns 0 if the value is valid, a positive error code + * otherwise and -1 in case of an internal or API error. + */ +int +xmlSchemaValidateLengthFacetWhtsp(xmlSchemaFacetPtr facet, + xmlSchemaValType valType, + const xmlChar *value, + xmlSchemaValPtr val, + unsigned long *length, + xmlSchemaWhitespaceValueType ws) +{ + return (xmlSchemaValidateLengthFacetInternal(facet, valType, value, val, + length, ws)); +} + +/** + * xmlSchemaValidateFacetInternal: + * @facet: the facet to check + * @fws: the whitespace type of the facet's value + * @valType: the built-in type of the value + * @value: the lexical repr of the value to validate + * @val: the precomputed value + * @ws: the whitespace type of the value + * + * Check a value against a facet condition + * + * Returns 0 if the element is schemas valid, a positive error code + * number otherwise and -1 in case of internal or API error. + */ +static int +xmlSchemaValidateFacetInternal(xmlSchemaFacetPtr facet, + xmlSchemaWhitespaceValueType fws, + xmlSchemaValType valType, + const xmlChar *value, + xmlSchemaValPtr val, + xmlSchemaWhitespaceValueType ws) +{ + int ret; + + if (facet == NULL) + return(-1); + + switch (facet->type) { + case XML_SCHEMA_FACET_PATTERN: + /* + * NOTE that for patterns, the @value needs to be the normalized + * value, *not* the lexical initial value or the canonical value. + */ + if (value == NULL) + return(-1); + ret = xmlRegexpExec(facet->regexp, value); + if (ret == 1) + return(0); + if (ret == 0) + return(XML_SCHEMAV_CVC_PATTERN_VALID); + return(ret); + case XML_SCHEMA_FACET_MAXEXCLUSIVE: + ret = xmlSchemaCompareValues(val, facet->val); + if (ret == -2) + return(-1); + if (ret == -1) + return(0); + return(XML_SCHEMAV_CVC_MAXEXCLUSIVE_VALID); + case XML_SCHEMA_FACET_MAXINCLUSIVE: + ret = xmlSchemaCompareValues(val, facet->val); + if (ret == -2) + return(-1); + if ((ret == -1) || (ret == 0)) + return(0); + return(XML_SCHEMAV_CVC_MAXINCLUSIVE_VALID); + case XML_SCHEMA_FACET_MINEXCLUSIVE: + ret = xmlSchemaCompareValues(val, facet->val); + if (ret == -2) + return(-1); + if (ret == 1) + return(0); + return(XML_SCHEMAV_CVC_MINEXCLUSIVE_VALID); + case XML_SCHEMA_FACET_MININCLUSIVE: + ret = xmlSchemaCompareValues(val, facet->val); + if (ret == -2) + return(-1); + if ((ret == 1) || (ret == 0)) + return(0); + return(XML_SCHEMAV_CVC_MININCLUSIVE_VALID); + case XML_SCHEMA_FACET_WHITESPACE: + /* TODO whitespaces */ + /* + * NOTE: Whitespace should be handled to normalize + * the value to be validated against a the facets; + * not to normalize the value in-between. + */ + return(0); + case XML_SCHEMA_FACET_ENUMERATION: + if (ws == XML_SCHEMA_WHITESPACE_UNKNOWN) { + /* + * This is to ensure API compatibility with the old + * xmlSchemaValidateFacet(). + * TODO: Get rid of this case. + */ + if ((facet->value != NULL) && + (xmlStrEqual(facet->value, value))) + return(0); + } else { + ret = xmlSchemaCompareValuesWhtspExt(facet->val->type, + facet->val, facet->value, fws, valType, val, + value, ws); + if (ret == -2) + return(-1); + if (ret == 0) + return(0); + } + return(XML_SCHEMAV_CVC_ENUMERATION_VALID); + case XML_SCHEMA_FACET_LENGTH: + /* + * SPEC (1.3) "if {primitive type definition} is QName or NOTATION, + * then any {value} is facet-valid." + */ + if ((valType == XML_SCHEMAS_QNAME) || + (valType == XML_SCHEMAS_NOTATION)) + return (0); + /* No break on purpose. */ + case XML_SCHEMA_FACET_MAXLENGTH: + case XML_SCHEMA_FACET_MINLENGTH: { + unsigned int len = 0; + + if ((valType == XML_SCHEMAS_QNAME) || + (valType == XML_SCHEMAS_NOTATION)) + return (0); + /* + * TODO: length, maxLength and minLength must be of type + * nonNegativeInteger only. Check if decimal is used somehow. + */ + if ((facet->val == NULL) || + ((facet->val->type != XML_SCHEMAS_DECIMAL) && + (facet->val->type != XML_SCHEMAS_NNINTEGER)) || + (facet->val->value.decimal.frac != 0)) { + return(-1); + } + if ((val != NULL) && (val->type == XML_SCHEMAS_HEXBINARY)) + len = val->value.hex.total; + else if ((val != NULL) && (val->type == XML_SCHEMAS_BASE64BINARY)) + len = val->value.base64.total; + else { + switch (valType) { + case XML_SCHEMAS_STRING: + case XML_SCHEMAS_NORMSTRING: + if (ws == XML_SCHEMA_WHITESPACE_UNKNOWN) { + /* + * This is to ensure API compatibility with the old + * xmlSchemaValidateFacet(). Anyway, this was and + * is not the correct handling. + * TODO: Get rid of this case somehow. + */ + if (valType == XML_SCHEMAS_STRING) + len = xmlUTF8Strlen(value); + else + len = xmlSchemaNormLen(value); + } else if (value != NULL) { + if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE) + len = xmlSchemaNormLen(value); + else + /* + * Should be OK for "preserve" as well. + */ + len = xmlUTF8Strlen(value); + } + break; + case XML_SCHEMAS_IDREF: + case XML_SCHEMAS_TOKEN: + case XML_SCHEMAS_LANGUAGE: + case XML_SCHEMAS_NMTOKEN: + case XML_SCHEMAS_NAME: + case XML_SCHEMAS_NCNAME: + case XML_SCHEMAS_ID: + case XML_SCHEMAS_ANYURI: + if (value != NULL) + len = xmlSchemaNormLen(value); + break; + default: + TODO + } + } + if (facet->type == XML_SCHEMA_FACET_LENGTH) { + if (len != facet->val->value.decimal.lo) + return(XML_SCHEMAV_CVC_LENGTH_VALID); + } else if (facet->type == XML_SCHEMA_FACET_MINLENGTH) { + if (len < facet->val->value.decimal.lo) + return(XML_SCHEMAV_CVC_MINLENGTH_VALID); + } else { + if (len > facet->val->value.decimal.lo) + return(XML_SCHEMAV_CVC_MAXLENGTH_VALID); + } + break; + } + case XML_SCHEMA_FACET_TOTALDIGITS: + case XML_SCHEMA_FACET_FRACTIONDIGITS: + + if ((facet->val == NULL) || + ((facet->val->type != XML_SCHEMAS_PINTEGER) && + (facet->val->type != XML_SCHEMAS_NNINTEGER)) || + (facet->val->value.decimal.frac != 0)) { + return(-1); + } + if ((val == NULL) || + ((val->type != XML_SCHEMAS_DECIMAL) && + (val->type != XML_SCHEMAS_INTEGER) && + (val->type != XML_SCHEMAS_NPINTEGER) && + (val->type != XML_SCHEMAS_NINTEGER) && + (val->type != XML_SCHEMAS_NNINTEGER) && + (val->type != XML_SCHEMAS_PINTEGER) && + (val->type != XML_SCHEMAS_INT) && + (val->type != XML_SCHEMAS_UINT) && + (val->type != XML_SCHEMAS_LONG) && + (val->type != XML_SCHEMAS_ULONG) && + (val->type != XML_SCHEMAS_SHORT) && + (val->type != XML_SCHEMAS_USHORT) && + (val->type != XML_SCHEMAS_BYTE) && + (val->type != XML_SCHEMAS_UBYTE))) { + return(-1); + } + if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) { + if (val->value.decimal.total > facet->val->value.decimal.lo) + return(XML_SCHEMAV_CVC_TOTALDIGITS_VALID); + + } else if (facet->type == XML_SCHEMA_FACET_FRACTIONDIGITS) { + if (val->value.decimal.frac > facet->val->value.decimal.lo) + return(XML_SCHEMAV_CVC_FRACTIONDIGITS_VALID); + } + break; + default: + TODO + } + return(0); + +} + +/** + * xmlSchemaValidateFacet: + * @base: the base type + * @facet: the facet to check + * @value: the lexical repr of the value to validate + * @val: the precomputed value + * + * Check a value against a facet condition + * + * Returns 0 if the element is schemas valid, a positive error code + * number otherwise and -1 in case of internal or API error. + */ +int +xmlSchemaValidateFacet(xmlSchemaTypePtr base, + xmlSchemaFacetPtr facet, + const xmlChar *value, + xmlSchemaValPtr val) +{ + /* + * This tries to ensure API compatibility regarding the old + * xmlSchemaValidateFacet() and the new xmlSchemaValidateFacetInternal() and + * xmlSchemaValidateFacetWhtsp(). + */ + if (val != NULL) + return(xmlSchemaValidateFacetInternal(facet, + XML_SCHEMA_WHITESPACE_UNKNOWN, val->type, value, val, + XML_SCHEMA_WHITESPACE_UNKNOWN)); + else if (base != NULL) + return(xmlSchemaValidateFacetInternal(facet, + XML_SCHEMA_WHITESPACE_UNKNOWN, base->builtInType, value, val, + XML_SCHEMA_WHITESPACE_UNKNOWN)); + return(-1); +} + +/** + * xmlSchemaValidateFacetWhtsp: + * @facet: the facet to check + * @fws: the whitespace type of the facet's value + * @valType: the built-in type of the value + * @value: the lexical (or normalized for pattern) repr of the value to validate + * @val: the precomputed value + * @ws: the whitespace type of the value + * + * Check a value against a facet condition. This takes value normalization + * according to the specified whitespace types into account. + * Note that @value needs to be the *normalized* value if the facet + * is of type "pattern". + * + * Returns 0 if the element is schemas valid, a positive error code + * number otherwise and -1 in case of internal or API error. + */ +int +xmlSchemaValidateFacetWhtsp(xmlSchemaFacetPtr facet, + xmlSchemaWhitespaceValueType fws, + xmlSchemaValType valType, + const xmlChar *value, + xmlSchemaValPtr val, + xmlSchemaWhitespaceValueType ws) +{ + return(xmlSchemaValidateFacetInternal(facet, fws, valType, + value, val, ws)); +} + +#if 0 +#ifndef DBL_DIG +#define DBL_DIG 16 +#endif +#ifndef DBL_EPSILON +#define DBL_EPSILON 1E-9 +#endif + +#define INTEGER_DIGITS DBL_DIG +#define FRACTION_DIGITS (DBL_DIG + 1) +#define EXPONENT_DIGITS (3 + 2) + +/** + * xmlXPathFormatNumber: + * @number: number to format + * @buffer: output buffer + * @buffersize: size of output buffer + * + * Convert the number into a string representation. + */ +static void +xmlSchemaFormatFloat(double number, char buffer[], int buffersize) +{ + switch (xmlXPathIsInf(number)) { + case 1: + if (buffersize > (int)sizeof("INF")) + snprintf(buffer, buffersize, "INF"); + break; + case -1: + if (buffersize > (int)sizeof("-INF")) + snprintf(buffer, buffersize, "-INF"); + break; + default: + if (xmlXPathIsNaN(number)) { + if (buffersize > (int)sizeof("NaN")) + snprintf(buffer, buffersize, "NaN"); + } else if (number == 0) { + snprintf(buffer, buffersize, "0.0E0"); + } else { + /* 3 is sign, decimal point, and terminating zero */ + char work[DBL_DIG + EXPONENT_DIGITS + 3]; + int integer_place, fraction_place; + char *ptr; + char *after_fraction; + double absolute_value; + int size; + + absolute_value = fabs(number); + + /* + * Result is in work, and after_fraction points + * just past the fractional part. + * Use scientific notation + */ + integer_place = DBL_DIG + EXPONENT_DIGITS + 1; + fraction_place = DBL_DIG - 1; + snprintf(work, sizeof(work),"%*.*e", + integer_place, fraction_place, number); + after_fraction = strchr(work + DBL_DIG, 'e'); + /* Remove fractional trailing zeroes */ + ptr = after_fraction; + while (*(--ptr) == '0') + ; + if (*ptr != '.') + ptr++; + while ((*ptr++ = *after_fraction++) != 0); + + /* Finally copy result back to caller */ + size = strlen(work) + 1; + if (size > buffersize) { + work[buffersize - 1] = 0; + size = buffersize; + } + memmove(buffer, work, size); + } + break; + } +} +#endif + +/** + * xmlSchemaGetCanonValue: + * @val: the precomputed value + * @retValue: the returned value + * + * Get a the cononical lexical representation of the value. + * The caller has to FREE the returned retValue. + * + * WARNING: Some value types are not supported yet, resulting + * in a @retValue of "???". + * + * TODO: XML Schema 1.0 does not define canonical representations + * for: duration, gYearMonth, gYear, gMonthDay, gMonth, gDay, + * anyURI, QName, NOTATION. This will be fixed in XML Schema 1.1. + * + * + * Returns 0 if the value could be built, 1 if the value type is + * not supported yet and -1 in case of API errors. + */ +int +xmlSchemaGetCanonValue(xmlSchemaValPtr val, const xmlChar **retValue) +{ + if ((retValue == NULL) || (val == NULL)) + return (-1); + *retValue = NULL; + switch (val->type) { + case XML_SCHEMAS_STRING: + if (val->value.str == NULL) + *retValue = BAD_CAST xmlStrdup(BAD_CAST ""); + else + *retValue = + BAD_CAST xmlStrdup((const xmlChar *) val->value.str); + break; + case XML_SCHEMAS_NORMSTRING: + if (val->value.str == NULL) + *retValue = BAD_CAST xmlStrdup(BAD_CAST ""); + else { + *retValue = xmlSchemaWhiteSpaceReplace( + (const xmlChar *) val->value.str); + if ((*retValue) == NULL) + *retValue = BAD_CAST xmlStrdup( + (const xmlChar *) val->value.str); + } + break; + case XML_SCHEMAS_TOKEN: + case XML_SCHEMAS_LANGUAGE: + case XML_SCHEMAS_NMTOKEN: + case XML_SCHEMAS_NAME: + case XML_SCHEMAS_NCNAME: + case XML_SCHEMAS_ID: + case XML_SCHEMAS_IDREF: + case XML_SCHEMAS_ENTITY: + case XML_SCHEMAS_NOTATION: /* Unclear */ + case XML_SCHEMAS_ANYURI: /* Unclear */ + if (val->value.str == NULL) + return (-1); + *retValue = + BAD_CAST xmlSchemaCollapseString(BAD_CAST val->value.str); + if (*retValue == NULL) + *retValue = + BAD_CAST xmlStrdup((const xmlChar *) val->value.str); + break; + case XML_SCHEMAS_QNAME: + /* TODO: Unclear in XML Schema 1.0. */ + if (val->value.qname.uri == NULL) { + *retValue = BAD_CAST xmlStrdup(BAD_CAST val->value.qname.name); + return (0); + } else { + *retValue = BAD_CAST xmlStrdup(BAD_CAST "{"); + *retValue = BAD_CAST xmlStrcat((xmlChar *) (*retValue), + BAD_CAST val->value.qname.uri); + *retValue = BAD_CAST xmlStrcat((xmlChar *) (*retValue), + BAD_CAST "}"); + *retValue = BAD_CAST xmlStrcat((xmlChar *) (*retValue), + BAD_CAST val->value.qname.uri); + } + break; + case XML_SCHEMAS_DECIMAL: + /* + * TODO: Lookout for a more simple implementation. + */ + if ((val->value.decimal.total == 1) && + (val->value.decimal.lo == 0)) { + *retValue = xmlStrdup(BAD_CAST "0.0"); + } else { + xmlSchemaValDecimal dec = val->value.decimal; + int bufsize; + char *buf = NULL, *offs; + + /* Add room for the decimal point as well. */ + bufsize = dec.total + 2; + if (dec.sign) + bufsize++; + /* Add room for leading/trailing zero. */ + if ((dec.frac == 0) || (dec.frac == dec.total)) + bufsize++; + buf = xmlMalloc(bufsize); + if (buf == NULL) + return(-1); + offs = buf; + if (dec.sign) + *offs++ = '-'; + if (dec.frac == dec.total) { + *offs++ = '0'; + *offs++ = '.'; + } + if (dec.hi != 0) + snprintf(offs, bufsize - (offs - buf), + "%lu%lu%lu", dec.hi, dec.mi, dec.lo); + else if (dec.mi != 0) + snprintf(offs, bufsize - (offs - buf), + "%lu%lu", dec.mi, dec.lo); + else + snprintf(offs, bufsize - (offs - buf), + "%lu", dec.lo); + + if (dec.frac != 0) { + if (dec.frac != dec.total) { + int diff = dec.total - dec.frac; + /* + * Insert the decimal point. + */ + memmove(offs + diff + 1, offs + diff, dec.frac +1); + offs[diff] = '.'; + } else { + unsigned int i = 0; + /* + * Insert missing zeroes behind the decimal point. + */ + while (*(offs + i) != 0) + i++; + if (i < dec.total) { + memmove(offs + (dec.total - i), offs, i +1); + memset(offs, '0', dec.total - i); + } + } + } else { + /* + * Append decimal point and zero. + */ + offs = buf + bufsize - 1; + *offs-- = 0; + *offs-- = '0'; + *offs-- = '.'; + } + *retValue = BAD_CAST buf; + } + break; + case XML_SCHEMAS_INTEGER: + case XML_SCHEMAS_PINTEGER: + case XML_SCHEMAS_NPINTEGER: + case XML_SCHEMAS_NINTEGER: + case XML_SCHEMAS_NNINTEGER: + case XML_SCHEMAS_LONG: + case XML_SCHEMAS_BYTE: + case XML_SCHEMAS_SHORT: + case XML_SCHEMAS_INT: + case XML_SCHEMAS_UINT: + case XML_SCHEMAS_ULONG: + case XML_SCHEMAS_USHORT: + case XML_SCHEMAS_UBYTE: + if ((val->value.decimal.total == 1) && + (val->value.decimal.lo == 0)) + *retValue = xmlStrdup(BAD_CAST "0"); + else { + xmlSchemaValDecimal dec = val->value.decimal; + int bufsize = dec.total + 1; + + /* Add room for the decimal point as well. */ + if (dec.sign) + bufsize++; + *retValue = xmlMalloc(bufsize); + if (*retValue == NULL) + return(-1); + if (dec.hi != 0) { + if (dec.sign) + snprintf((char *) *retValue, bufsize, + "-%lu%lu%lu", dec.hi, dec.mi, dec.lo); + else + snprintf((char *) *retValue, bufsize, + "%lu%lu%lu", dec.hi, dec.mi, dec.lo); + } else if (dec.mi != 0) { + if (dec.sign) + snprintf((char *) *retValue, bufsize, + "-%lu%lu", dec.mi, dec.lo); + else + snprintf((char *) *retValue, bufsize, + "%lu%lu", dec.mi, dec.lo); + } else { + if (dec.sign) + snprintf((char *) *retValue, bufsize, "-%lu", dec.lo); + else + snprintf((char *) *retValue, bufsize, "%lu", dec.lo); + } + } + break; + case XML_SCHEMAS_BOOLEAN: + if (val->value.b) + *retValue = BAD_CAST xmlStrdup(BAD_CAST "true"); + else + *retValue = BAD_CAST xmlStrdup(BAD_CAST "false"); + break; + case XML_SCHEMAS_DURATION: { + char buf[100]; + unsigned long year; + unsigned long mon, day, hour = 0, min = 0; + double sec = 0, left; + + /* TODO: Unclear in XML Schema 1.0 */ + /* + * TODO: This results in a normalized output of the value + * - which is NOT conformant to the spec - + * since the exact values of each property are not + * recoverable. Think about extending the structure to + * provide a field for every property. + */ + year = (unsigned long) FQUOTIENT(labs(val->value.dur.mon), 12); + mon = labs(val->value.dur.mon) - 12 * year; + + day = (unsigned long) FQUOTIENT(fabs(val->value.dur.sec), 86400); + left = fabs(val->value.dur.sec) - day * 86400; + if (left > 0) { + hour = (unsigned long) FQUOTIENT(left, 3600); + left = left - (hour * 3600); + if (left > 0) { + min = (unsigned long) FQUOTIENT(left, 60); + sec = left - (min * 60); + } + } + if ((val->value.dur.mon < 0) || (val->value.dur.sec < 0)) + snprintf(buf, 100, "P%luY%luM%luDT%luH%luM%.14gS", + year, mon, day, hour, min, sec); + else + snprintf(buf, 100, "-P%luY%luM%luDT%luH%luM%.14gS", + year, mon, day, hour, min, sec); + *retValue = BAD_CAST xmlStrdup(BAD_CAST buf); + } + break; + case XML_SCHEMAS_GYEAR: { + char buf[30]; + /* TODO: Unclear in XML Schema 1.0 */ + /* TODO: What to do with the timezone? */ + snprintf(buf, 30, "%04ld", val->value.date.year); + *retValue = BAD_CAST xmlStrdup(BAD_CAST buf); + } + break; + case XML_SCHEMAS_GMONTH: { + /* TODO: Unclear in XML Schema 1.0 */ + /* TODO: What to do with the timezone? */ + *retValue = xmlMalloc(6); + if (*retValue == NULL) + return(-1); + snprintf((char *) *retValue, 6, "--%02u", + val->value.date.mon); + } + break; + case XML_SCHEMAS_GDAY: { + /* TODO: Unclear in XML Schema 1.0 */ + /* TODO: What to do with the timezone? */ + *retValue = xmlMalloc(6); + if (*retValue == NULL) + return(-1); + snprintf((char *) *retValue, 6, "---%02u", + val->value.date.day); + } + break; + case XML_SCHEMAS_GMONTHDAY: { + /* TODO: Unclear in XML Schema 1.0 */ + /* TODO: What to do with the timezone? */ + *retValue = xmlMalloc(8); + if (*retValue == NULL) + return(-1); + snprintf((char *) *retValue, 8, "--%02u-%02u", + val->value.date.mon, val->value.date.day); + } + break; + case XML_SCHEMAS_GYEARMONTH: { + char buf[35]; + /* TODO: Unclear in XML Schema 1.0 */ + /* TODO: What to do with the timezone? */ + if (val->value.date.year < 0) + snprintf(buf, 35, "-%04ld-%02u", + labs(val->value.date.year), + val->value.date.mon); + else + snprintf(buf, 35, "%04ld-%02u", + val->value.date.year, val->value.date.mon); + *retValue = BAD_CAST xmlStrdup(BAD_CAST buf); + } + break; + case XML_SCHEMAS_TIME: + { + char buf[30]; + + if (val->value.date.tz_flag) { + xmlSchemaValPtr norm; + + norm = xmlSchemaDateNormalize(val, 0); + if (norm == NULL) + return (-1); + /* + * TODO: Check if "%.14g" is portable. + */ + snprintf(buf, 30, + "%02u:%02u:%02.14gZ", + norm->value.date.hour, + norm->value.date.min, + norm->value.date.sec); + xmlSchemaFreeValue(norm); + } else { + snprintf(buf, 30, + "%02u:%02u:%02.14g", + val->value.date.hour, + val->value.date.min, + val->value.date.sec); + } + *retValue = BAD_CAST xmlStrdup(BAD_CAST buf); + } + break; + case XML_SCHEMAS_DATE: + { + char buf[30]; + + if (val->value.date.tz_flag) { + xmlSchemaValPtr norm; + + norm = xmlSchemaDateNormalize(val, 0); + if (norm == NULL) + return (-1); + /* + * TODO: Append the canonical value of the + * recoverable timezone and not "Z". + */ + snprintf(buf, 30, + "%04ld:%02u:%02uZ", + norm->value.date.year, norm->value.date.mon, + norm->value.date.day); + xmlSchemaFreeValue(norm); + } else { + snprintf(buf, 30, + "%04ld:%02u:%02u", + val->value.date.year, val->value.date.mon, + val->value.date.day); + } + *retValue = BAD_CAST xmlStrdup(BAD_CAST buf); + } + break; + case XML_SCHEMAS_DATETIME: + { + char buf[50]; + + if (val->value.date.tz_flag) { + xmlSchemaValPtr norm; + + norm = xmlSchemaDateNormalize(val, 0); + if (norm == NULL) + return (-1); + /* + * TODO: Check if "%.14g" is portable. + */ + snprintf(buf, 50, + "%04ld:%02u:%02uT%02u:%02u:%02.14gZ", + norm->value.date.year, norm->value.date.mon, + norm->value.date.day, norm->value.date.hour, + norm->value.date.min, norm->value.date.sec); + xmlSchemaFreeValue(norm); + } else { + snprintf(buf, 50, + "%04ld:%02u:%02uT%02u:%02u:%02.14g", + val->value.date.year, val->value.date.mon, + val->value.date.day, val->value.date.hour, + val->value.date.min, val->value.date.sec); + } + *retValue = BAD_CAST xmlStrdup(BAD_CAST buf); + } + break; + case XML_SCHEMAS_HEXBINARY: + *retValue = BAD_CAST xmlStrdup(BAD_CAST val->value.hex.str); + break; + case XML_SCHEMAS_BASE64BINARY: + /* + * TODO: Is the following spec piece implemented?: + * SPEC: "Note: For some values the canonical form defined + * above does not conform to [RFC 2045], which requires breaking + * with linefeeds at appropriate intervals." + */ + *retValue = BAD_CAST xmlStrdup(BAD_CAST val->value.base64.str); + break; + case XML_SCHEMAS_FLOAT: { + char buf[30]; + /* + * |m| < 16777216, -149 <= e <= 104. + * TODO: Handle, NaN, INF, -INF. The format is not + * yet conformant. The c type float does not cover + * the whole range. + */ + snprintf(buf, 30, "%01.14e", val->value.f); + *retValue = BAD_CAST xmlStrdup(BAD_CAST buf); + } + break; + case XML_SCHEMAS_DOUBLE: { + char buf[40]; + /* |m| < 9007199254740992, -1075 <= e <= 970 */ + /* + * TODO: Handle, NaN, INF, -INF. The format is not + * yet conformant. The c type float does not cover + * the whole range. + */ + snprintf(buf, 40, "%01.14e", val->value.d); + *retValue = BAD_CAST xmlStrdup(BAD_CAST buf); + } + break; + default: + *retValue = BAD_CAST xmlStrdup(BAD_CAST "???"); + return (1); + } + if (*retValue == NULL) + return(-1); + return (0); +} + +/** + * xmlSchemaGetCanonValueWhtsp: + * @val: the precomputed value + * @retValue: the returned value + * @ws: the whitespace type of the value + * + * Get a the cononical representation of the value. + * The caller has to free the returned @retValue. + * + * Returns 0 if the value could be built, 1 if the value type is + * not supported yet and -1 in case of API errors. + */ +int +xmlSchemaGetCanonValueWhtsp(xmlSchemaValPtr val, + const xmlChar **retValue, + xmlSchemaWhitespaceValueType ws) +{ + if ((retValue == NULL) || (val == NULL)) + return (-1); + if ((ws == XML_SCHEMA_WHITESPACE_UNKNOWN) || + (ws > XML_SCHEMA_WHITESPACE_COLLAPSE)) + return (-1); + + *retValue = NULL; + switch (val->type) { + case XML_SCHEMAS_STRING: + if (val->value.str == NULL) + *retValue = BAD_CAST xmlStrdup(BAD_CAST ""); + else if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE) + *retValue = xmlSchemaCollapseString(val->value.str); + else if (ws == XML_SCHEMA_WHITESPACE_REPLACE) + *retValue = xmlSchemaWhiteSpaceReplace(val->value.str); + if ((*retValue) == NULL) + *retValue = BAD_CAST xmlStrdup(val->value.str); + break; + case XML_SCHEMAS_NORMSTRING: + if (val->value.str == NULL) + *retValue = BAD_CAST xmlStrdup(BAD_CAST ""); + else { + if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE) + *retValue = xmlSchemaCollapseString(val->value.str); + else + *retValue = xmlSchemaWhiteSpaceReplace(val->value.str); + if ((*retValue) == NULL) + *retValue = BAD_CAST xmlStrdup(val->value.str); + } + break; + default: + return (xmlSchemaGetCanonValue(val, retValue)); + } + return (0); +} + +/** + * xmlSchemaGetValType: + * @val: a schemas value + * + * Accessor for the type of a value + * + * Returns the xmlSchemaValType of the value + */ +xmlSchemaValType +xmlSchemaGetValType(xmlSchemaValPtr val) +{ + if (val == NULL) + return(XML_SCHEMAS_UNKNOWN); + return (val->type); +} + +#define bottom_xmlschemastypes +#include "elfgcchack.h" +#endif /* LIBXML_SCHEMAS_ENABLED */ diff --git a/gettext-tools/gnulib-lib/libxml/xmlschemastypes.in.h b/gettext-tools/gnulib-lib/libxml/xmlschemastypes.in.h new file mode 100644 index 0000000..9a3a7a1 --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/xmlschemastypes.in.h @@ -0,0 +1,151 @@ +/* + * Summary: implementation of XML Schema Datatypes + * Description: module providing the XML Schema Datatypes implementation + * both definition and validity checking + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + + +#ifndef __XML_SCHEMA_TYPES_H__ +#define __XML_SCHEMA_TYPES_H__ + +#include + +#ifdef LIBXML_SCHEMAS_ENABLED + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + XML_SCHEMA_WHITESPACE_UNKNOWN = 0, + XML_SCHEMA_WHITESPACE_PRESERVE = 1, + XML_SCHEMA_WHITESPACE_REPLACE = 2, + XML_SCHEMA_WHITESPACE_COLLAPSE = 3 +} xmlSchemaWhitespaceValueType; + +XMLPUBFUN void XMLCALL + xmlSchemaInitTypes (void); +XMLPUBFUN void XMLCALL + xmlSchemaCleanupTypes (void); +XMLPUBFUN xmlSchemaTypePtr XMLCALL + xmlSchemaGetPredefinedType (const xmlChar *name, + const xmlChar *ns); +XMLPUBFUN int XMLCALL + xmlSchemaValidatePredefinedType (xmlSchemaTypePtr type, + const xmlChar *value, + xmlSchemaValPtr *val); +XMLPUBFUN int XMLCALL + xmlSchemaValPredefTypeNode (xmlSchemaTypePtr type, + const xmlChar *value, + xmlSchemaValPtr *val, + xmlNodePtr node); +XMLPUBFUN int XMLCALL + xmlSchemaValidateFacet (xmlSchemaTypePtr base, + xmlSchemaFacetPtr facet, + const xmlChar *value, + xmlSchemaValPtr val); +XMLPUBFUN int XMLCALL + xmlSchemaValidateFacetWhtsp (xmlSchemaFacetPtr facet, + xmlSchemaWhitespaceValueType fws, + xmlSchemaValType valType, + const xmlChar *value, + xmlSchemaValPtr val, + xmlSchemaWhitespaceValueType ws); +XMLPUBFUN void XMLCALL + xmlSchemaFreeValue (xmlSchemaValPtr val); +XMLPUBFUN xmlSchemaFacetPtr XMLCALL + xmlSchemaNewFacet (void); +XMLPUBFUN int XMLCALL + xmlSchemaCheckFacet (xmlSchemaFacetPtr facet, + xmlSchemaTypePtr typeDecl, + xmlSchemaParserCtxtPtr ctxt, + const xmlChar *name); +XMLPUBFUN void XMLCALL + xmlSchemaFreeFacet (xmlSchemaFacetPtr facet); +XMLPUBFUN int XMLCALL + xmlSchemaCompareValues (xmlSchemaValPtr x, + xmlSchemaValPtr y); +XMLPUBFUN xmlSchemaTypePtr XMLCALL + xmlSchemaGetBuiltInListSimpleTypeItemType (xmlSchemaTypePtr type); +XMLPUBFUN int XMLCALL + xmlSchemaValidateListSimpleTypeFacet (xmlSchemaFacetPtr facet, + const xmlChar *value, + unsigned long actualLen, + unsigned long *expectedLen); +XMLPUBFUN xmlSchemaTypePtr XMLCALL + xmlSchemaGetBuiltInType (xmlSchemaValType type); +XMLPUBFUN int XMLCALL + xmlSchemaIsBuiltInTypeFacet (xmlSchemaTypePtr type, + int facetType); +XMLPUBFUN xmlChar * XMLCALL + xmlSchemaCollapseString (const xmlChar *value); +XMLPUBFUN xmlChar * XMLCALL + xmlSchemaWhiteSpaceReplace (const xmlChar *value); +XMLPUBFUN unsigned long XMLCALL + xmlSchemaGetFacetValueAsULong (xmlSchemaFacetPtr facet); +XMLPUBFUN int XMLCALL + xmlSchemaValidateLengthFacet (xmlSchemaTypePtr type, + xmlSchemaFacetPtr facet, + const xmlChar *value, + xmlSchemaValPtr val, + unsigned long *length); +XMLPUBFUN int XMLCALL + xmlSchemaValidateLengthFacetWhtsp(xmlSchemaFacetPtr facet, + xmlSchemaValType valType, + const xmlChar *value, + xmlSchemaValPtr val, + unsigned long *length, + xmlSchemaWhitespaceValueType ws); +XMLPUBFUN int XMLCALL + xmlSchemaValPredefTypeNodeNoNorm(xmlSchemaTypePtr type, + const xmlChar *value, + xmlSchemaValPtr *val, + xmlNodePtr node); +XMLPUBFUN int XMLCALL + xmlSchemaGetCanonValue (xmlSchemaValPtr val, + const xmlChar **retValue); +XMLPUBFUN int XMLCALL + xmlSchemaGetCanonValueWhtsp (xmlSchemaValPtr val, + const xmlChar **retValue, + xmlSchemaWhitespaceValueType ws); +XMLPUBFUN int XMLCALL + xmlSchemaValueAppend (xmlSchemaValPtr prev, + xmlSchemaValPtr cur); +XMLPUBFUN xmlSchemaValPtr XMLCALL + xmlSchemaValueGetNext (xmlSchemaValPtr cur); +XMLPUBFUN const xmlChar * XMLCALL + xmlSchemaValueGetAsString (xmlSchemaValPtr val); +XMLPUBFUN int XMLCALL + xmlSchemaValueGetAsBoolean (xmlSchemaValPtr val); +XMLPUBFUN xmlSchemaValPtr XMLCALL + xmlSchemaNewStringValue (xmlSchemaValType type, + const xmlChar *value); +XMLPUBFUN xmlSchemaValPtr XMLCALL + xmlSchemaNewNOTATIONValue (const xmlChar *name, + const xmlChar *ns); +XMLPUBFUN xmlSchemaValPtr XMLCALL + xmlSchemaNewQNameValue (const xmlChar *namespaceName, + const xmlChar *localName); +XMLPUBFUN int XMLCALL + xmlSchemaCompareValuesWhtsp (xmlSchemaValPtr x, + xmlSchemaWhitespaceValueType xws, + xmlSchemaValPtr y, + xmlSchemaWhitespaceValueType yws); +XMLPUBFUN xmlSchemaValPtr XMLCALL + xmlSchemaCopyValue (xmlSchemaValPtr val); +XMLPUBFUN xmlSchemaValType XMLCALL + xmlSchemaGetValType (xmlSchemaValPtr val); + +#ifdef __cplusplus +} +#endif + +#endif /* LIBXML_SCHEMAS_ENABLED */ +#endif /* __XML_SCHEMA_TYPES_H__ */ diff --git a/gettext-tools/gnulib-lib/libxml/xmlstring.c b/gettext-tools/gnulib-lib/libxml/xmlstring.c new file mode 100644 index 0000000..4f3b373 --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/xmlstring.c @@ -0,0 +1,984 @@ +/* + * string.c : an XML string utilities module + * + * This module provides various utility functions for manipulating + * the xmlChar* type. All functions named xmlStr* have been moved here + * from the parser.c file (their original home). + * + * See Copyright for the status of this software. + * + * UTF8 string routines from: + * William Brack + * + * daniel@veillard.com + */ + +#define IN_LIBXML +#include "libxml.h" + +#include +#include +#include +#include +#include + +/************************************************************************ + * * + * Commodity functions to handle xmlChars * + * * + ************************************************************************/ + +/** + * xmlStrndup: + * @cur: the input xmlChar * + * @len: the len of @cur + * + * a strndup for array of xmlChar's + * + * Returns a new xmlChar * or NULL + */ +xmlChar * +xmlStrndup(const xmlChar *cur, int len) { + xmlChar *ret; + + if ((cur == NULL) || (len < 0)) return(NULL); + ret = (xmlChar *) xmlMallocAtomic((len + 1) * sizeof(xmlChar)); + if (ret == NULL) { + xmlErrMemory(NULL, NULL); + return(NULL); + } + memcpy(ret, cur, len * sizeof(xmlChar)); + ret[len] = 0; + return(ret); +} + +/** + * xmlStrdup: + * @cur: the input xmlChar * + * + * a strdup for array of xmlChar's. Since they are supposed to be + * encoded in UTF-8 or an encoding with 8bit based chars, we assume + * a termination mark of '0'. + * + * Returns a new xmlChar * or NULL + */ +xmlChar * +xmlStrdup(const xmlChar *cur) { + const xmlChar *p = cur; + + if (cur == NULL) return(NULL); + while (*p != 0) p++; /* non input consuming */ + return(xmlStrndup(cur, p - cur)); +} + +/** + * xmlCharStrndup: + * @cur: the input char * + * @len: the len of @cur + * + * a strndup for char's to xmlChar's + * + * Returns a new xmlChar * or NULL + */ + +xmlChar * +xmlCharStrndup(const char *cur, int len) { + int i; + xmlChar *ret; + + if ((cur == NULL) || (len < 0)) return(NULL); + ret = (xmlChar *) xmlMallocAtomic((len + 1) * sizeof(xmlChar)); + if (ret == NULL) { + xmlErrMemory(NULL, NULL); + return(NULL); + } + for (i = 0;i < len;i++) { + ret[i] = (xmlChar) cur[i]; + if (ret[i] == 0) return(ret); + } + ret[len] = 0; + return(ret); +} + +/** + * xmlCharStrdup: + * @cur: the input char * + * + * a strdup for char's to xmlChar's + * + * Returns a new xmlChar * or NULL + */ + +xmlChar * +xmlCharStrdup(const char *cur) { + const char *p = cur; + + if (cur == NULL) return(NULL); + while (*p != '\0') p++; /* non input consuming */ + return(xmlCharStrndup(cur, p - cur)); +} + +/** + * xmlStrcmp: + * @str1: the first xmlChar * + * @str2: the second xmlChar * + * + * a strcmp for xmlChar's + * + * Returns the integer result of the comparison + */ + +int +xmlStrcmp(const xmlChar *str1, const xmlChar *str2) { + register int tmp; + + if (str1 == str2) return(0); + if (str1 == NULL) return(-1); + if (str2 == NULL) return(1); + do { + tmp = *str1++ - *str2; + if (tmp != 0) return(tmp); + } while (*str2++ != 0); + return 0; +} + +/** + * xmlStrEqual: + * @str1: the first xmlChar * + * @str2: the second xmlChar * + * + * Check if both strings are equal of have same content. + * Should be a bit more readable and faster than xmlStrcmp() + * + * Returns 1 if they are equal, 0 if they are different + */ + +int +xmlStrEqual(const xmlChar *str1, const xmlChar *str2) { + if (str1 == str2) return(1); + if (str1 == NULL) return(0); + if (str2 == NULL) return(0); + do { + if (*str1++ != *str2) return(0); + } while (*str2++); + return(1); +} + +/** + * xmlStrQEqual: + * @pref: the prefix of the QName + * @name: the localname of the QName + * @str: the second xmlChar * + * + * Check if a QName is Equal to a given string + * + * Returns 1 if they are equal, 0 if they are different + */ + +int +xmlStrQEqual(const xmlChar *pref, const xmlChar *name, const xmlChar *str) { + if (pref == NULL) return(xmlStrEqual(name, str)); + if (name == NULL) return(0); + if (str == NULL) return(0); + + do { + if (*pref++ != *str) return(0); + } while ((*str++) && (*pref)); + if (*str++ != ':') return(0); + do { + if (*name++ != *str) return(0); + } while (*str++); + return(1); +} + +/** + * xmlStrncmp: + * @str1: the first xmlChar * + * @str2: the second xmlChar * + * @len: the max comparison length + * + * a strncmp for xmlChar's + * + * Returns the integer result of the comparison + */ + +int +xmlStrncmp(const xmlChar *str1, const xmlChar *str2, int len) { + register int tmp; + + if (len <= 0) return(0); + if (str1 == str2) return(0); + if (str1 == NULL) return(-1); + if (str2 == NULL) return(1); +#ifdef __GNUC__ + tmp = strncmp((const char *)str1, (const char *)str2, len); + return tmp; +#else + do { + tmp = *str1++ - *str2; + if (tmp != 0 || --len == 0) return(tmp); + } while (*str2++ != 0); + return 0; +#endif +} + +static const xmlChar casemap[256] = { + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F, + 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, + 0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F, + 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27, + 0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F, + 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37, + 0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F, + 0x40,0x61,0x62,0x63,0x64,0x65,0x66,0x67, + 0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F, + 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77, + 0x78,0x79,0x7A,0x7B,0x5C,0x5D,0x5E,0x5F, + 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67, + 0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F, + 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77, + 0x78,0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x7F, + 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87, + 0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, + 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97, + 0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, + 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7, + 0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7, + 0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7, + 0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, + 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7, + 0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7, + 0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7, + 0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF +}; + +/** + * xmlStrcasecmp: + * @str1: the first xmlChar * + * @str2: the second xmlChar * + * + * a strcasecmp for xmlChar's + * + * Returns the integer result of the comparison + */ + +int +xmlStrcasecmp(const xmlChar *str1, const xmlChar *str2) { + register int tmp; + + if (str1 == str2) return(0); + if (str1 == NULL) return(-1); + if (str2 == NULL) return(1); + do { + tmp = casemap[*str1++] - casemap[*str2]; + if (tmp != 0) return(tmp); + } while (*str2++ != 0); + return 0; +} + +/** + * xmlStrncasecmp: + * @str1: the first xmlChar * + * @str2: the second xmlChar * + * @len: the max comparison length + * + * a strncasecmp for xmlChar's + * + * Returns the integer result of the comparison + */ + +int +xmlStrncasecmp(const xmlChar *str1, const xmlChar *str2, int len) { + register int tmp; + + if (len <= 0) return(0); + if (str1 == str2) return(0); + if (str1 == NULL) return(-1); + if (str2 == NULL) return(1); + do { + tmp = casemap[*str1++] - casemap[*str2]; + if (tmp != 0 || --len == 0) return(tmp); + } while (*str2++ != 0); + return 0; +} + +/** + * xmlStrchr: + * @str: the xmlChar * array + * @val: the xmlChar to search + * + * a strchr for xmlChar's + * + * Returns the xmlChar * for the first occurrence or NULL. + */ + +const xmlChar * +xmlStrchr(const xmlChar *str, xmlChar val) { + if (str == NULL) return(NULL); + while (*str != 0) { /* non input consuming */ + if (*str == val) return((xmlChar *) str); + str++; + } + return(NULL); +} + +/** + * xmlStrstr: + * @str: the xmlChar * array (haystack) + * @val: the xmlChar to search (needle) + * + * a strstr for xmlChar's + * + * Returns the xmlChar * for the first occurrence or NULL. + */ + +const xmlChar * +xmlStrstr(const xmlChar *str, const xmlChar *val) { + int n; + + if (str == NULL) return(NULL); + if (val == NULL) return(NULL); + n = xmlStrlen(val); + + if (n == 0) return(str); + while (*str != 0) { /* non input consuming */ + if (*str == *val) { + if (!xmlStrncmp(str, val, n)) return((const xmlChar *) str); + } + str++; + } + return(NULL); +} + +/** + * xmlStrcasestr: + * @str: the xmlChar * array (haystack) + * @val: the xmlChar to search (needle) + * + * a case-ignoring strstr for xmlChar's + * + * Returns the xmlChar * for the first occurrence or NULL. + */ + +const xmlChar * +xmlStrcasestr(const xmlChar *str, xmlChar *val) { + int n; + + if (str == NULL) return(NULL); + if (val == NULL) return(NULL); + n = xmlStrlen(val); + + if (n == 0) return(str); + while (*str != 0) { /* non input consuming */ + if (casemap[*str] == casemap[*val]) + if (!xmlStrncasecmp(str, val, n)) return(str); + str++; + } + return(NULL); +} + +/** + * xmlStrsub: + * @str: the xmlChar * array (haystack) + * @start: the index of the first char (zero based) + * @len: the length of the substring + * + * Extract a substring of a given string + * + * Returns the xmlChar * for the first occurrence or NULL. + */ + +xmlChar * +xmlStrsub(const xmlChar *str, int start, int len) { + int i; + + if (str == NULL) return(NULL); + if (start < 0) return(NULL); + if (len < 0) return(NULL); + + for (i = 0;i < start;i++) { + if (*str == 0) return(NULL); + str++; + } + if (*str == 0) return(NULL); + return(xmlStrndup(str, len)); +} + +/** + * xmlStrlen: + * @str: the xmlChar * array + * + * length of a xmlChar's string + * + * Returns the number of xmlChar contained in the ARRAY. + */ + +int +xmlStrlen(const xmlChar *str) { + int len = 0; + + if (str == NULL) return(0); + while (*str != 0) { /* non input consuming */ + str++; + len++; + } + return(len); +} + +/** + * xmlStrncat: + * @cur: the original xmlChar * array + * @add: the xmlChar * array added + * @len: the length of @add + * + * a strncat for array of xmlChar's, it will extend @cur with the len + * first bytes of @add. Note that if @len < 0 then this is an API error + * and NULL will be returned. + * + * Returns a new xmlChar *, the original @cur is reallocated if needed + * and should not be freed + */ + +xmlChar * +xmlStrncat(xmlChar *cur, const xmlChar *add, int len) { + int size; + xmlChar *ret; + + if ((add == NULL) || (len == 0)) + return(cur); + if (len < 0) + return(NULL); + if (cur == NULL) + return(xmlStrndup(add, len)); + + size = xmlStrlen(cur); + ret = (xmlChar *) xmlRealloc(cur, (size + len + 1) * sizeof(xmlChar)); + if (ret == NULL) { + xmlErrMemory(NULL, NULL); + return(cur); + } + memcpy(&ret[size], add, len * sizeof(xmlChar)); + ret[size + len] = 0; + return(ret); +} + +/** + * xmlStrncatNew: + * @str1: first xmlChar string + * @str2: second xmlChar string + * @len: the len of @str2 or < 0 + * + * same as xmlStrncat, but creates a new string. The original + * two strings are not freed. If @len is < 0 then the length + * will be calculated automatically. + * + * Returns a new xmlChar * or NULL + */ +xmlChar * +xmlStrncatNew(const xmlChar *str1, const xmlChar *str2, int len) { + int size; + xmlChar *ret; + + if (len < 0) + len = xmlStrlen(str2); + if ((str2 == NULL) || (len == 0)) + return(xmlStrdup(str1)); + if (str1 == NULL) + return(xmlStrndup(str2, len)); + + size = xmlStrlen(str1); + ret = (xmlChar *) xmlMalloc((size + len + 1) * sizeof(xmlChar)); + if (ret == NULL) { + xmlErrMemory(NULL, NULL); + return(xmlStrndup(str1, size)); + } + memcpy(ret, str1, size * sizeof(xmlChar)); + memcpy(&ret[size], str2, len * sizeof(xmlChar)); + ret[size + len] = 0; + return(ret); +} + +/** + * xmlStrcat: + * @cur: the original xmlChar * array + * @add: the xmlChar * array added + * + * a strcat for array of xmlChar's. Since they are supposed to be + * encoded in UTF-8 or an encoding with 8bit based chars, we assume + * a termination mark of '0'. + * + * Returns a new xmlChar * containing the concatenated string. + */ +xmlChar * +xmlStrcat(xmlChar *cur, const xmlChar *add) { + const xmlChar *p = add; + + if (add == NULL) return(cur); + if (cur == NULL) + return(xmlStrdup(add)); + + while (*p != 0) p++; /* non input consuming */ + return(xmlStrncat(cur, add, p - add)); +} + +/** + * xmlStrPrintf: + * @buf: the result buffer. + * @len: the result buffer length. + * @msg: the message with printf formatting. + * @...: extra parameters for the message. + * + * Formats @msg and places result into @buf. + * + * Returns the number of characters written to @buf or -1 if an error occurs. + */ +int XMLCDECL +xmlStrPrintf(xmlChar *buf, int len, const xmlChar *msg, ...) { + va_list args; + int ret; + + if((buf == NULL) || (msg == NULL)) { + return(-1); + } + + va_start(args, msg); + ret = vsnprintf((char *) buf, len, (const char *) msg, args); + va_end(args); + buf[len - 1] = 0; /* be safe ! */ + + return(ret); +} + +/** + * xmlStrVPrintf: + * @buf: the result buffer. + * @len: the result buffer length. + * @msg: the message with printf formatting. + * @ap: extra parameters for the message. + * + * Formats @msg and places result into @buf. + * + * Returns the number of characters written to @buf or -1 if an error occurs. + */ +int +xmlStrVPrintf(xmlChar *buf, int len, const xmlChar *msg, va_list ap) { + int ret; + + if((buf == NULL) || (msg == NULL)) { + return(-1); + } + + ret = vsnprintf((char *) buf, len, (const char *) msg, ap); + buf[len - 1] = 0; /* be safe ! */ + + return(ret); +} + +/************************************************************************ + * * + * Generic UTF8 handling routines * + * * + * From rfc2044: encoding of the Unicode values on UTF-8: * + * * + * UCS-4 range (hex.) UTF-8 octet sequence (binary) * + * 0000 0000-0000 007F 0xxxxxxx * + * 0000 0080-0000 07FF 110xxxxx 10xxxxxx * + * 0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx * + * * + * I hope we won't use values > 0xFFFF anytime soon ! * + * * + ************************************************************************/ + + +/** + * xmlUTF8Size: + * @utf: pointer to the UTF8 character + * + * calculates the internal size of a UTF8 character + * + * returns the numbers of bytes in the character, -1 on format error + */ +int +xmlUTF8Size(const xmlChar *utf) { + xmlChar mask; + int len; + + if (utf == NULL) + return -1; + if (*utf < 0x80) + return 1; + /* check valid UTF8 character */ + if (!(*utf & 0x40)) + return -1; + /* determine number of bytes in char */ + len = 2; + for (mask=0x20; mask != 0; mask>>=1) { + if (!(*utf & mask)) + return len; + len++; + } + return -1; +} + +/** + * xmlUTF8Charcmp: + * @utf1: pointer to first UTF8 char + * @utf2: pointer to second UTF8 char + * + * compares the two UCS4 values + * + * returns result of the compare as with xmlStrncmp + */ +int +xmlUTF8Charcmp(const xmlChar *utf1, const xmlChar *utf2) { + + if (utf1 == NULL ) { + if (utf2 == NULL) + return 0; + return -1; + } + return xmlStrncmp(utf1, utf2, xmlUTF8Size(utf1)); +} + +/** + * xmlUTF8Strlen: + * @utf: a sequence of UTF-8 encoded bytes + * + * compute the length of an UTF8 string, it doesn't do a full UTF8 + * checking of the content of the string. + * + * Returns the number of characters in the string or -1 in case of error + */ +int +xmlUTF8Strlen(const xmlChar *utf) { + int ret = 0; + + if (utf == NULL) + return(-1); + + while (*utf != 0) { + if (utf[0] & 0x80) { + if ((utf[1] & 0xc0) != 0x80) + return(-1); + if ((utf[0] & 0xe0) == 0xe0) { + if ((utf[2] & 0xc0) != 0x80) + return(-1); + if ((utf[0] & 0xf0) == 0xf0) { + if ((utf[0] & 0xf8) != 0xf0 || (utf[3] & 0xc0) != 0x80) + return(-1); + utf += 4; + } else { + utf += 3; + } + } else { + utf += 2; + } + } else { + utf++; + } + ret++; + } + return(ret); +} + +/** + * xmlGetUTF8Char: + * @utf: a sequence of UTF-8 encoded bytes + * @len: a pointer to the minimum number of bytes present in + * the sequence. This is used to assure the next character + * is completely contained within the sequence. + * + * Read the first UTF8 character from @utf + * + * Returns the char value or -1 in case of error, and sets *len to + * the actual number of bytes consumed (0 in case of error) + */ +int +xmlGetUTF8Char(const unsigned char *utf, int *len) { + unsigned int c; + + if (utf == NULL) + goto error; + if (len == NULL) + goto error; + if (*len < 1) + goto error; + + c = utf[0]; + if (c & 0x80) { + if (*len < 2) + goto error; + if ((utf[1] & 0xc0) != 0x80) + goto error; + if ((c & 0xe0) == 0xe0) { + if (*len < 3) + goto error; + if ((utf[2] & 0xc0) != 0x80) + goto error; + if ((c & 0xf0) == 0xf0) { + if (*len < 4) + goto error; + if ((c & 0xf8) != 0xf0 || (utf[3] & 0xc0) != 0x80) + goto error; + *len = 4; + /* 4-byte code */ + c = (utf[0] & 0x7) << 18; + c |= (utf[1] & 0x3f) << 12; + c |= (utf[2] & 0x3f) << 6; + c |= utf[3] & 0x3f; + } else { + /* 3-byte code */ + *len = 3; + c = (utf[0] & 0xf) << 12; + c |= (utf[1] & 0x3f) << 6; + c |= utf[2] & 0x3f; + } + } else { + /* 2-byte code */ + *len = 2; + c = (utf[0] & 0x1f) << 6; + c |= utf[1] & 0x3f; + } + } else { + /* 1-byte code */ + *len = 1; + } + return(c); + +error: + if (len != NULL) + *len = 0; + return(-1); +} + +/** + * xmlCheckUTF8: + * @utf: Pointer to putative UTF-8 encoded string. + * + * Checks @utf for being valid UTF-8. @utf is assumed to be + * null-terminated. This function is not super-strict, as it will + * allow longer UTF-8 sequences than necessary. Note that Java is + * capable of producing these sequences if provoked. Also note, this + * routine checks for the 4-byte maximum size, but does not check for + * 0x10ffff maximum value. + * + * Return value: true if @utf is valid. + **/ +int +xmlCheckUTF8(const unsigned char *utf) +{ + int ix; + unsigned char c; + + if (utf == NULL) + return(0); + /* + * utf is a string of 1, 2, 3 or 4 bytes. The valid strings + * are as follows (in "bit format"): + * 0xxxxxxx valid 1-byte + * 110xxxxx 10xxxxxx valid 2-byte + * 1110xxxx 10xxxxxx 10xxxxxx valid 3-byte + * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx valid 4-byte + */ + for (ix = 0; (c = utf[ix]);) { /* string is 0-terminated */ + if ((c & 0x80) == 0x00) { /* 1-byte code, starts with 10 */ + ix++; + } else if ((c & 0xe0) == 0xc0) {/* 2-byte code, starts with 110 */ + if ((utf[ix+1] & 0xc0 ) != 0x80) + return 0; + ix += 2; + } else if ((c & 0xf0) == 0xe0) {/* 3-byte code, starts with 1110 */ + if (((utf[ix+1] & 0xc0) != 0x80) || + ((utf[ix+2] & 0xc0) != 0x80)) + return 0; + ix += 3; + } else if ((c & 0xf8) == 0xf0) {/* 4-byte code, starts with 11110 */ + if (((utf[ix+1] & 0xc0) != 0x80) || + ((utf[ix+2] & 0xc0) != 0x80) || + ((utf[ix+3] & 0xc0) != 0x80)) + return 0; + ix += 4; + } else /* unknown encoding */ + return 0; + } + return(1); +} + +/** + * xmlUTF8Strsize: + * @utf: a sequence of UTF-8 encoded bytes + * @len: the number of characters in the array + * + * storage size of an UTF8 string + * the behaviour is not garanteed if the input string is not UTF-8 + * + * Returns the storage size of + * the first 'len' characters of ARRAY + */ + +int +xmlUTF8Strsize(const xmlChar *utf, int len) { + const xmlChar *ptr=utf; + xmlChar ch; + + if (utf == NULL) + return(0); + + if (len <= 0) + return(0); + + while ( len-- > 0) { + if ( !*ptr ) + break; + if ( (ch = *ptr++) & 0x80) + while ((ch<<=1) & 0x80 ) { + ptr++; + if (*ptr == 0) break; + } + } + return (ptr - utf); +} + + +/** + * xmlUTF8Strndup: + * @utf: the input UTF8 * + * @len: the len of @utf (in chars) + * + * a strndup for array of UTF8's + * + * Returns a new UTF8 * or NULL + */ +xmlChar * +xmlUTF8Strndup(const xmlChar *utf, int len) { + xmlChar *ret; + int i; + + if ((utf == NULL) || (len < 0)) return(NULL); + i = xmlUTF8Strsize(utf, len); + ret = (xmlChar *) xmlMallocAtomic((i + 1) * sizeof(xmlChar)); + if (ret == NULL) { + xmlGenericError(xmlGenericErrorContext, + "malloc of %ld byte failed\n", + (len + 1) * (long)sizeof(xmlChar)); + return(NULL); + } + memcpy(ret, utf, i * sizeof(xmlChar)); + ret[i] = 0; + return(ret); +} + +/** + * xmlUTF8Strpos: + * @utf: the input UTF8 * + * @pos: the position of the desired UTF8 char (in chars) + * + * a function to provide the equivalent of fetching a + * character from a string array + * + * Returns a pointer to the UTF8 character or NULL + */ +const xmlChar * +xmlUTF8Strpos(const xmlChar *utf, int pos) { + xmlChar ch; + + if (utf == NULL) return(NULL); + if (pos < 0) + return(NULL); + while (pos--) { + if ((ch=*utf++) == 0) return(NULL); + if ( ch & 0x80 ) { + /* if not simple ascii, verify proper format */ + if ( (ch & 0xc0) != 0xc0 ) + return(NULL); + /* then skip over remaining bytes for this char */ + while ( (ch <<= 1) & 0x80 ) + if ( (*utf++ & 0xc0) != 0x80 ) + return(NULL); + } + } + return((xmlChar *)utf); +} + +/** + * xmlUTF8Strloc: + * @utf: the input UTF8 * + * @utfchar: the UTF8 character to be found + * + * a function to provide the relative location of a UTF8 char + * + * Returns the relative character position of the desired char + * or -1 if not found + */ +int +xmlUTF8Strloc(const xmlChar *utf, const xmlChar *utfchar) { + int i, size; + xmlChar ch; + + if (utf==NULL || utfchar==NULL) return -1; + size = xmlUTF8Strsize(utfchar, 1); + for(i=0; (ch=*utf) != 0; i++) { + if (xmlStrncmp(utf, utfchar, size)==0) + return(i); + utf++; + if ( ch & 0x80 ) { + /* if not simple ascii, verify proper format */ + if ( (ch & 0xc0) != 0xc0 ) + return(-1); + /* then skip over remaining bytes for this char */ + while ( (ch <<= 1) & 0x80 ) + if ( (*utf++ & 0xc0) != 0x80 ) + return(-1); + } + } + + return(-1); +} +/** + * xmlUTF8Strsub: + * @utf: a sequence of UTF-8 encoded bytes + * @start: relative pos of first char + * @len: total number to copy + * + * Create a substring from a given UTF-8 string + * Note: positions are given in units of UTF-8 chars + * + * Returns a pointer to a newly created string + * or NULL if any problem + */ + +xmlChar * +xmlUTF8Strsub(const xmlChar *utf, int start, int len) { + int i; + xmlChar ch; + + if (utf == NULL) return(NULL); + if (start < 0) return(NULL); + if (len < 0) return(NULL); + + /* + * Skip over any leading chars + */ + for (i = 0;i < start;i++) { + if ((ch=*utf++) == 0) return(NULL); + if ( ch & 0x80 ) { + /* if not simple ascii, verify proper format */ + if ( (ch & 0xc0) != 0xc0 ) + return(NULL); + /* then skip over remaining bytes for this char */ + while ( (ch <<= 1) & 0x80 ) + if ( (*utf++ & 0xc0) != 0x80 ) + return(NULL); + } + } + + return(xmlUTF8Strndup(utf, len)); +} + +#define bottom_xmlstring +#include "elfgcchack.h" diff --git a/gettext-tools/gnulib-lib/libxml/xmlstring.in.h b/gettext-tools/gnulib-lib/libxml/xmlstring.in.h new file mode 100644 index 0000000..1dfc5ea --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/xmlstring.in.h @@ -0,0 +1,140 @@ +/* + * Summary: set of routines to process strings + * Description: type and interfaces needed for the internal string handling + * of the library, especially UTF8 processing. + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + +#ifndef __XML_STRING_H__ +#define __XML_STRING_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * xmlChar: + * + * This is a basic byte in an UTF-8 encoded string. + * It's unsigned allowing to pinpoint case where char * are assigned + * to xmlChar * (possibly making serialization back impossible). + */ +typedef unsigned char xmlChar; + +/** + * BAD_CAST: + * + * Macro to cast a string to an xmlChar * when one know its safe. + */ +#define BAD_CAST (xmlChar *) + +/* + * xmlChar handling + */ +XMLPUBFUN xmlChar * XMLCALL + xmlStrdup (const xmlChar *cur); +XMLPUBFUN xmlChar * XMLCALL + xmlStrndup (const xmlChar *cur, + int len); +XMLPUBFUN xmlChar * XMLCALL + xmlCharStrndup (const char *cur, + int len); +XMLPUBFUN xmlChar * XMLCALL + xmlCharStrdup (const char *cur); +XMLPUBFUN xmlChar * XMLCALL + xmlStrsub (const xmlChar *str, + int start, + int len); +XMLPUBFUN const xmlChar * XMLCALL + xmlStrchr (const xmlChar *str, + xmlChar val); +XMLPUBFUN const xmlChar * XMLCALL + xmlStrstr (const xmlChar *str, + const xmlChar *val); +XMLPUBFUN const xmlChar * XMLCALL + xmlStrcasestr (const xmlChar *str, + xmlChar *val); +XMLPUBFUN int XMLCALL + xmlStrcmp (const xmlChar *str1, + const xmlChar *str2); +XMLPUBFUN int XMLCALL + xmlStrncmp (const xmlChar *str1, + const xmlChar *str2, + int len); +XMLPUBFUN int XMLCALL + xmlStrcasecmp (const xmlChar *str1, + const xmlChar *str2); +XMLPUBFUN int XMLCALL + xmlStrncasecmp (const xmlChar *str1, + const xmlChar *str2, + int len); +XMLPUBFUN int XMLCALL + xmlStrEqual (const xmlChar *str1, + const xmlChar *str2); +XMLPUBFUN int XMLCALL + xmlStrQEqual (const xmlChar *pref, + const xmlChar *name, + const xmlChar *str); +XMLPUBFUN int XMLCALL + xmlStrlen (const xmlChar *str); +XMLPUBFUN xmlChar * XMLCALL + xmlStrcat (xmlChar *cur, + const xmlChar *add); +XMLPUBFUN xmlChar * XMLCALL + xmlStrncat (xmlChar *cur, + const xmlChar *add, + int len); +XMLPUBFUN xmlChar * XMLCALL + xmlStrncatNew (const xmlChar *str1, + const xmlChar *str2, + int len); +XMLPUBFUN int XMLCALL + xmlStrPrintf (xmlChar *buf, + int len, + const xmlChar *msg, + ...); +XMLPUBFUN int XMLCALL + xmlStrVPrintf (xmlChar *buf, + int len, + const xmlChar *msg, + va_list ap); + +XMLPUBFUN int XMLCALL + xmlGetUTF8Char (const unsigned char *utf, + int *len); +XMLPUBFUN int XMLCALL + xmlCheckUTF8 (const unsigned char *utf); +XMLPUBFUN int XMLCALL + xmlUTF8Strsize (const xmlChar *utf, + int len); +XMLPUBFUN xmlChar * XMLCALL + xmlUTF8Strndup (const xmlChar *utf, + int len); +XMLPUBFUN const xmlChar * XMLCALL + xmlUTF8Strpos (const xmlChar *utf, + int pos); +XMLPUBFUN int XMLCALL + xmlUTF8Strloc (const xmlChar *utf, + const xmlChar *utfchar); +XMLPUBFUN xmlChar * XMLCALL + xmlUTF8Strsub (const xmlChar *utf, + int start, + int len); +XMLPUBFUN int XMLCALL + xmlUTF8Strlen (const xmlChar *utf); +XMLPUBFUN int XMLCALL + xmlUTF8Size (const xmlChar *utf); +XMLPUBFUN int XMLCALL + xmlUTF8Charcmp (const xmlChar *utf1, + const xmlChar *utf2); + +#ifdef __cplusplus +} +#endif +#endif /* __XML_STRING_H__ */ diff --git a/gettext-tools/gnulib-lib/libxml/xmlunicode.c b/gettext-tools/gnulib-lib/libxml/xmlunicode.c new file mode 100644 index 0000000..450d0f0 --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/xmlunicode.c @@ -0,0 +1,3179 @@ +/* + * xmlunicode.c: this module implements the Unicode character APIs + * + * This file is automatically generated from the + * UCS description files of the Unicode Character Database + * http://www.unicode.org/Public/4.0-Update1/UCD-4.0.1.html + * using the genUnicode.py Python script. + * + * Generation date: Mon Mar 27 11:09:52 2006 + * Sources: Blocks-4.0.1.txt UnicodeData-4.0.1.txt + * Daniel Veillard + */ + +#define IN_LIBXML +#include "libxml.h" + +#ifdef LIBXML_UNICODE_ENABLED + +#include +#include +#include +#include + +typedef int (xmlIntFunc)(int); /* just to keep one's mind untwisted */ + +typedef struct { + const char *rangename; + xmlIntFunc *func; +} xmlUnicodeRange; + +typedef struct { + xmlUnicodeRange *table; + int numentries; +} xmlUnicodeNameTable; + + +static xmlIntFunc *xmlUnicodeLookup(xmlUnicodeNameTable *tptr, const char *tname); + +static xmlUnicodeRange xmlUnicodeBlocks[] = { + {"AegeanNumbers", xmlUCSIsAegeanNumbers}, + {"AlphabeticPresentationForms", xmlUCSIsAlphabeticPresentationForms}, + {"Arabic", xmlUCSIsArabic}, + {"ArabicPresentationForms-A", xmlUCSIsArabicPresentationFormsA}, + {"ArabicPresentationForms-B", xmlUCSIsArabicPresentationFormsB}, + {"Armenian", xmlUCSIsArmenian}, + {"Arrows", xmlUCSIsArrows}, + {"BasicLatin", xmlUCSIsBasicLatin}, + {"Bengali", xmlUCSIsBengali}, + {"BlockElements", xmlUCSIsBlockElements}, + {"Bopomofo", xmlUCSIsBopomofo}, + {"BopomofoExtended", xmlUCSIsBopomofoExtended}, + {"BoxDrawing", xmlUCSIsBoxDrawing}, + {"BraillePatterns", xmlUCSIsBraillePatterns}, + {"Buhid", xmlUCSIsBuhid}, + {"ByzantineMusicalSymbols", xmlUCSIsByzantineMusicalSymbols}, + {"CJKCompatibility", xmlUCSIsCJKCompatibility}, + {"CJKCompatibilityForms", xmlUCSIsCJKCompatibilityForms}, + {"CJKCompatibilityIdeographs", xmlUCSIsCJKCompatibilityIdeographs}, + {"CJKCompatibilityIdeographsSupplement", xmlUCSIsCJKCompatibilityIdeographsSupplement}, + {"CJKRadicalsSupplement", xmlUCSIsCJKRadicalsSupplement}, + {"CJKSymbolsandPunctuation", xmlUCSIsCJKSymbolsandPunctuation}, + {"CJKUnifiedIdeographs", xmlUCSIsCJKUnifiedIdeographs}, + {"CJKUnifiedIdeographsExtensionA", xmlUCSIsCJKUnifiedIdeographsExtensionA}, + {"CJKUnifiedIdeographsExtensionB", xmlUCSIsCJKUnifiedIdeographsExtensionB}, + {"Cherokee", xmlUCSIsCherokee}, + {"CombiningDiacriticalMarks", xmlUCSIsCombiningDiacriticalMarks}, + {"CombiningDiacriticalMarksforSymbols", xmlUCSIsCombiningDiacriticalMarksforSymbols}, + {"CombiningHalfMarks", xmlUCSIsCombiningHalfMarks}, + {"CombiningMarksforSymbols", xmlUCSIsCombiningMarksforSymbols}, + {"ControlPictures", xmlUCSIsControlPictures}, + {"CurrencySymbols", xmlUCSIsCurrencySymbols}, + {"CypriotSyllabary", xmlUCSIsCypriotSyllabary}, + {"Cyrillic", xmlUCSIsCyrillic}, + {"CyrillicSupplement", xmlUCSIsCyrillicSupplement}, + {"Deseret", xmlUCSIsDeseret}, + {"Devanagari", xmlUCSIsDevanagari}, + {"Dingbats", xmlUCSIsDingbats}, + {"EnclosedAlphanumerics", xmlUCSIsEnclosedAlphanumerics}, + {"EnclosedCJKLettersandMonths", xmlUCSIsEnclosedCJKLettersandMonths}, + {"Ethiopic", xmlUCSIsEthiopic}, + {"GeneralPunctuation", xmlUCSIsGeneralPunctuation}, + {"GeometricShapes", xmlUCSIsGeometricShapes}, + {"Georgian", xmlUCSIsGeorgian}, + {"Gothic", xmlUCSIsGothic}, + {"Greek", xmlUCSIsGreek}, + {"GreekExtended", xmlUCSIsGreekExtended}, + {"GreekandCoptic", xmlUCSIsGreekandCoptic}, + {"Gujarati", xmlUCSIsGujarati}, + {"Gurmukhi", xmlUCSIsGurmukhi}, + {"HalfwidthandFullwidthForms", xmlUCSIsHalfwidthandFullwidthForms}, + {"HangulCompatibilityJamo", xmlUCSIsHangulCompatibilityJamo}, + {"HangulJamo", xmlUCSIsHangulJamo}, + {"HangulSyllables", xmlUCSIsHangulSyllables}, + {"Hanunoo", xmlUCSIsHanunoo}, + {"Hebrew", xmlUCSIsHebrew}, + {"HighPrivateUseSurrogates", xmlUCSIsHighPrivateUseSurrogates}, + {"HighSurrogates", xmlUCSIsHighSurrogates}, + {"Hiragana", xmlUCSIsHiragana}, + {"IPAExtensions", xmlUCSIsIPAExtensions}, + {"IdeographicDescriptionCharacters", xmlUCSIsIdeographicDescriptionCharacters}, + {"Kanbun", xmlUCSIsKanbun}, + {"KangxiRadicals", xmlUCSIsKangxiRadicals}, + {"Kannada", xmlUCSIsKannada}, + {"Katakana", xmlUCSIsKatakana}, + {"KatakanaPhoneticExtensions", xmlUCSIsKatakanaPhoneticExtensions}, + {"Khmer", xmlUCSIsKhmer}, + {"KhmerSymbols", xmlUCSIsKhmerSymbols}, + {"Lao", xmlUCSIsLao}, + {"Latin-1Supplement", xmlUCSIsLatin1Supplement}, + {"LatinExtended-A", xmlUCSIsLatinExtendedA}, + {"LatinExtended-B", xmlUCSIsLatinExtendedB}, + {"LatinExtendedAdditional", xmlUCSIsLatinExtendedAdditional}, + {"LetterlikeSymbols", xmlUCSIsLetterlikeSymbols}, + {"Limbu", xmlUCSIsLimbu}, + {"LinearBIdeograms", xmlUCSIsLinearBIdeograms}, + {"LinearBSyllabary", xmlUCSIsLinearBSyllabary}, + {"LowSurrogates", xmlUCSIsLowSurrogates}, + {"Malayalam", xmlUCSIsMalayalam}, + {"MathematicalAlphanumericSymbols", xmlUCSIsMathematicalAlphanumericSymbols}, + {"MathematicalOperators", xmlUCSIsMathematicalOperators}, + {"MiscellaneousMathematicalSymbols-A", xmlUCSIsMiscellaneousMathematicalSymbolsA}, + {"MiscellaneousMathematicalSymbols-B", xmlUCSIsMiscellaneousMathematicalSymbolsB}, + {"MiscellaneousSymbols", xmlUCSIsMiscellaneousSymbols}, + {"MiscellaneousSymbolsandArrows", xmlUCSIsMiscellaneousSymbolsandArrows}, + {"MiscellaneousTechnical", xmlUCSIsMiscellaneousTechnical}, + {"Mongolian", xmlUCSIsMongolian}, + {"MusicalSymbols", xmlUCSIsMusicalSymbols}, + {"Myanmar", xmlUCSIsMyanmar}, + {"NumberForms", xmlUCSIsNumberForms}, + {"Ogham", xmlUCSIsOgham}, + {"OldItalic", xmlUCSIsOldItalic}, + {"OpticalCharacterRecognition", xmlUCSIsOpticalCharacterRecognition}, + {"Oriya", xmlUCSIsOriya}, + {"Osmanya", xmlUCSIsOsmanya}, + {"PhoneticExtensions", xmlUCSIsPhoneticExtensions}, + {"PrivateUse", xmlUCSIsPrivateUse}, + {"PrivateUseArea", xmlUCSIsPrivateUseArea}, + {"Runic", xmlUCSIsRunic}, + {"Shavian", xmlUCSIsShavian}, + {"Sinhala", xmlUCSIsSinhala}, + {"SmallFormVariants", xmlUCSIsSmallFormVariants}, + {"SpacingModifierLetters", xmlUCSIsSpacingModifierLetters}, + {"Specials", xmlUCSIsSpecials}, + {"SuperscriptsandSubscripts", xmlUCSIsSuperscriptsandSubscripts}, + {"SupplementalArrows-A", xmlUCSIsSupplementalArrowsA}, + {"SupplementalArrows-B", xmlUCSIsSupplementalArrowsB}, + {"SupplementalMathematicalOperators", xmlUCSIsSupplementalMathematicalOperators}, + {"SupplementaryPrivateUseArea-A", xmlUCSIsSupplementaryPrivateUseAreaA}, + {"SupplementaryPrivateUseArea-B", xmlUCSIsSupplementaryPrivateUseAreaB}, + {"Syriac", xmlUCSIsSyriac}, + {"Tagalog", xmlUCSIsTagalog}, + {"Tagbanwa", xmlUCSIsTagbanwa}, + {"Tags", xmlUCSIsTags}, + {"TaiLe", xmlUCSIsTaiLe}, + {"TaiXuanJingSymbols", xmlUCSIsTaiXuanJingSymbols}, + {"Tamil", xmlUCSIsTamil}, + {"Telugu", xmlUCSIsTelugu}, + {"Thaana", xmlUCSIsThaana}, + {"Thai", xmlUCSIsThai}, + {"Tibetan", xmlUCSIsTibetan}, + {"Ugaritic", xmlUCSIsUgaritic}, + {"UnifiedCanadianAboriginalSyllabics", xmlUCSIsUnifiedCanadianAboriginalSyllabics}, + {"VariationSelectors", xmlUCSIsVariationSelectors}, + {"VariationSelectorsSupplement", xmlUCSIsVariationSelectorsSupplement}, + {"YiRadicals", xmlUCSIsYiRadicals}, + {"YiSyllables", xmlUCSIsYiSyllables}, + {"YijingHexagramSymbols", xmlUCSIsYijingHexagramSymbols}}; + +static xmlUnicodeRange xmlUnicodeCats[] = { + {"C", xmlUCSIsCatC}, + {"Cc", xmlUCSIsCatCc}, + {"Cf", xmlUCSIsCatCf}, + {"Co", xmlUCSIsCatCo}, + {"Cs", xmlUCSIsCatCs}, + {"L", xmlUCSIsCatL}, + {"Ll", xmlUCSIsCatLl}, + {"Lm", xmlUCSIsCatLm}, + {"Lo", xmlUCSIsCatLo}, + {"Lt", xmlUCSIsCatLt}, + {"Lu", xmlUCSIsCatLu}, + {"M", xmlUCSIsCatM}, + {"Mc", xmlUCSIsCatMc}, + {"Me", xmlUCSIsCatMe}, + {"Mn", xmlUCSIsCatMn}, + {"N", xmlUCSIsCatN}, + {"Nd", xmlUCSIsCatNd}, + {"Nl", xmlUCSIsCatNl}, + {"No", xmlUCSIsCatNo}, + {"P", xmlUCSIsCatP}, + {"Pc", xmlUCSIsCatPc}, + {"Pd", xmlUCSIsCatPd}, + {"Pe", xmlUCSIsCatPe}, + {"Pf", xmlUCSIsCatPf}, + {"Pi", xmlUCSIsCatPi}, + {"Po", xmlUCSIsCatPo}, + {"Ps", xmlUCSIsCatPs}, + {"S", xmlUCSIsCatS}, + {"Sc", xmlUCSIsCatSc}, + {"Sk", xmlUCSIsCatSk}, + {"Sm", xmlUCSIsCatSm}, + {"So", xmlUCSIsCatSo}, + {"Z", xmlUCSIsCatZ}, + {"Zl", xmlUCSIsCatZl}, + {"Zp", xmlUCSIsCatZp}, + {"Zs", xmlUCSIsCatZs}}; + +static const xmlChSRange xmlCS[] = {{0x0, 0x1f}, {0x7f, 0x9f}, + {0xad, 0xad}, {0x600, 0x603}, {0x6dd, 0x6dd}, {0x70f, 0x70f}, + {0x17b4, 0x17b5}, {0x200b, 0x200f}, {0x202a, 0x202e}, {0x2060, 0x2063}, + {0x206a, 0x206f}, {0xd800, 0xd800}, {0xdb7f, 0xdb80}, {0xdbff, 0xdc00}, + {0xdfff, 0xe000}, {0xf8ff, 0xf8ff}, {0xfeff, 0xfeff}, {0xfff9, 0xfffb} }; +static const xmlChLRange xmlCL[] = {{0x1d173, 0x1d17a}, {0xe0001, 0xe0001}, + {0xe0020, 0xe007f}, {0xf0000, 0xf0000}, {0xffffd, 0xffffd}, + {0x100000, 0x100000}, {0x10fffd, 0x10fffd} }; +static xmlChRangeGroup xmlCG = {18,7,xmlCS,xmlCL}; + +static const xmlChSRange xmlCfS[] = {{0xad, 0xad}, {0x600, 0x603}, + {0x6dd, 0x6dd}, {0x70f, 0x70f}, {0x17b4, 0x17b5}, {0x200b, 0x200f}, + {0x202a, 0x202e}, {0x2060, 0x2063}, {0x206a, 0x206f}, {0xfeff, 0xfeff}, + {0xfff9, 0xfffb} }; +static const xmlChLRange xmlCfL[] = {{0x1d173, 0x1d17a}, {0xe0001, 0xe0001}, + {0xe0020, 0xe007f} }; +static xmlChRangeGroup xmlCfG = {11,3,xmlCfS,xmlCfL}; + +static const xmlChSRange xmlLS[] = {{0x41, 0x5a}, {0x61, 0x7a}, + {0xaa, 0xaa}, {0xb5, 0xb5}, {0xba, 0xba}, {0xc0, 0xd6}, {0xd8, 0xf6}, + {0xf8, 0x236}, {0x250, 0x2c1}, {0x2c6, 0x2d1}, {0x2e0, 0x2e4}, + {0x2ee, 0x2ee}, {0x37a, 0x37a}, {0x386, 0x386}, {0x388, 0x38a}, + {0x38c, 0x38c}, {0x38e, 0x3a1}, {0x3a3, 0x3ce}, {0x3d0, 0x3f5}, + {0x3f7, 0x3fb}, {0x400, 0x481}, {0x48a, 0x4ce}, {0x4d0, 0x4f5}, + {0x4f8, 0x4f9}, {0x500, 0x50f}, {0x531, 0x556}, {0x559, 0x559}, + {0x561, 0x587}, {0x5d0, 0x5ea}, {0x5f0, 0x5f2}, {0x621, 0x63a}, + {0x640, 0x64a}, {0x66e, 0x66f}, {0x671, 0x6d3}, {0x6d5, 0x6d5}, + {0x6e5, 0x6e6}, {0x6ee, 0x6ef}, {0x6fa, 0x6fc}, {0x6ff, 0x6ff}, + {0x710, 0x710}, {0x712, 0x72f}, {0x74d, 0x74f}, {0x780, 0x7a5}, + {0x7b1, 0x7b1}, {0x904, 0x939}, {0x93d, 0x93d}, {0x950, 0x950}, + {0x958, 0x961}, {0x985, 0x98c}, {0x98f, 0x990}, {0x993, 0x9a8}, + {0x9aa, 0x9b0}, {0x9b2, 0x9b2}, {0x9b6, 0x9b9}, {0x9bd, 0x9bd}, + {0x9dc, 0x9dd}, {0x9df, 0x9e1}, {0x9f0, 0x9f1}, {0xa05, 0xa0a}, + {0xa0f, 0xa10}, {0xa13, 0xa28}, {0xa2a, 0xa30}, {0xa32, 0xa33}, + {0xa35, 0xa36}, {0xa38, 0xa39}, {0xa59, 0xa5c}, {0xa5e, 0xa5e}, + {0xa72, 0xa74}, {0xa85, 0xa8d}, {0xa8f, 0xa91}, {0xa93, 0xaa8}, + {0xaaa, 0xab0}, {0xab2, 0xab3}, {0xab5, 0xab9}, {0xabd, 0xabd}, + {0xad0, 0xad0}, {0xae0, 0xae1}, {0xb05, 0xb0c}, {0xb0f, 0xb10}, + {0xb13, 0xb28}, {0xb2a, 0xb30}, {0xb32, 0xb33}, {0xb35, 0xb39}, + {0xb3d, 0xb3d}, {0xb5c, 0xb5d}, {0xb5f, 0xb61}, {0xb71, 0xb71}, + {0xb83, 0xb83}, {0xb85, 0xb8a}, {0xb8e, 0xb90}, {0xb92, 0xb95}, + {0xb99, 0xb9a}, {0xb9c, 0xb9c}, {0xb9e, 0xb9f}, {0xba3, 0xba4}, + {0xba8, 0xbaa}, {0xbae, 0xbb5}, {0xbb7, 0xbb9}, {0xc05, 0xc0c}, + {0xc0e, 0xc10}, {0xc12, 0xc28}, {0xc2a, 0xc33}, {0xc35, 0xc39}, + {0xc60, 0xc61}, {0xc85, 0xc8c}, {0xc8e, 0xc90}, {0xc92, 0xca8}, + {0xcaa, 0xcb3}, {0xcb5, 0xcb9}, {0xcbd, 0xcbd}, {0xcde, 0xcde}, + {0xce0, 0xce1}, {0xd05, 0xd0c}, {0xd0e, 0xd10}, {0xd12, 0xd28}, + {0xd2a, 0xd39}, {0xd60, 0xd61}, {0xd85, 0xd96}, {0xd9a, 0xdb1}, + {0xdb3, 0xdbb}, {0xdbd, 0xdbd}, {0xdc0, 0xdc6}, {0xe01, 0xe30}, + {0xe32, 0xe33}, {0xe40, 0xe46}, {0xe81, 0xe82}, {0xe84, 0xe84}, + {0xe87, 0xe88}, {0xe8a, 0xe8a}, {0xe8d, 0xe8d}, {0xe94, 0xe97}, + {0xe99, 0xe9f}, {0xea1, 0xea3}, {0xea5, 0xea5}, {0xea7, 0xea7}, + {0xeaa, 0xeab}, {0xead, 0xeb0}, {0xeb2, 0xeb3}, {0xebd, 0xebd}, + {0xec0, 0xec4}, {0xec6, 0xec6}, {0xedc, 0xedd}, {0xf00, 0xf00}, + {0xf40, 0xf47}, {0xf49, 0xf6a}, {0xf88, 0xf8b}, {0x1000, 0x1021}, + {0x1023, 0x1027}, {0x1029, 0x102a}, {0x1050, 0x1055}, {0x10a0, 0x10c5}, + {0x10d0, 0x10f8}, {0x1100, 0x1159}, {0x115f, 0x11a2}, {0x11a8, 0x11f9}, + {0x1200, 0x1206}, {0x1208, 0x1246}, {0x1248, 0x1248}, {0x124a, 0x124d}, + {0x1250, 0x1256}, {0x1258, 0x1258}, {0x125a, 0x125d}, {0x1260, 0x1286}, + {0x1288, 0x1288}, {0x128a, 0x128d}, {0x1290, 0x12ae}, {0x12b0, 0x12b0}, + {0x12b2, 0x12b5}, {0x12b8, 0x12be}, {0x12c0, 0x12c0}, {0x12c2, 0x12c5}, + {0x12c8, 0x12ce}, {0x12d0, 0x12d6}, {0x12d8, 0x12ee}, {0x12f0, 0x130e}, + {0x1310, 0x1310}, {0x1312, 0x1315}, {0x1318, 0x131e}, {0x1320, 0x1346}, + {0x1348, 0x135a}, {0x13a0, 0x13f4}, {0x1401, 0x166c}, {0x166f, 0x1676}, + {0x1681, 0x169a}, {0x16a0, 0x16ea}, {0x1700, 0x170c}, {0x170e, 0x1711}, + {0x1720, 0x1731}, {0x1740, 0x1751}, {0x1760, 0x176c}, {0x176e, 0x1770}, + {0x1780, 0x17b3}, {0x17d7, 0x17d7}, {0x17dc, 0x17dc}, {0x1820, 0x1877}, + {0x1880, 0x18a8}, {0x1900, 0x191c}, {0x1950, 0x196d}, {0x1970, 0x1974}, + {0x1d00, 0x1d6b}, {0x1e00, 0x1e9b}, {0x1ea0, 0x1ef9}, {0x1f00, 0x1f15}, + {0x1f18, 0x1f1d}, {0x1f20, 0x1f45}, {0x1f48, 0x1f4d}, {0x1f50, 0x1f57}, + {0x1f59, 0x1f59}, {0x1f5b, 0x1f5b}, {0x1f5d, 0x1f5d}, {0x1f5f, 0x1f7d}, + {0x1f80, 0x1fb4}, {0x1fb6, 0x1fbc}, {0x1fbe, 0x1fbe}, {0x1fc2, 0x1fc4}, + {0x1fc6, 0x1fcc}, {0x1fd0, 0x1fd3}, {0x1fd6, 0x1fdb}, {0x1fe0, 0x1fec}, + {0x1ff2, 0x1ff4}, {0x1ff6, 0x1ffc}, {0x2071, 0x2071}, {0x207f, 0x207f}, + {0x2102, 0x2102}, {0x2107, 0x2107}, {0x210a, 0x2113}, {0x2115, 0x2115}, + {0x2119, 0x211d}, {0x2124, 0x2124}, {0x2126, 0x2126}, {0x2128, 0x2128}, + {0x212a, 0x212d}, {0x212f, 0x2131}, {0x2133, 0x2139}, {0x213d, 0x213f}, + {0x2145, 0x2149}, {0x3005, 0x3006}, {0x3031, 0x3035}, {0x303b, 0x303c}, + {0x3041, 0x3096}, {0x309d, 0x309f}, {0x30a1, 0x30fa}, {0x30fc, 0x30ff}, + {0x3105, 0x312c}, {0x3131, 0x318e}, {0x31a0, 0x31b7}, {0x31f0, 0x31ff}, + {0x3400, 0x3400}, {0x4db5, 0x4db5}, {0x4e00, 0x4e00}, {0x9fa5, 0x9fa5}, + {0xa000, 0xa48c}, {0xac00, 0xac00}, {0xd7a3, 0xd7a3}, {0xf900, 0xfa2d}, + {0xfa30, 0xfa6a}, {0xfb00, 0xfb06}, {0xfb13, 0xfb17}, {0xfb1d, 0xfb1d}, + {0xfb1f, 0xfb28}, {0xfb2a, 0xfb36}, {0xfb38, 0xfb3c}, {0xfb3e, 0xfb3e}, + {0xfb40, 0xfb41}, {0xfb43, 0xfb44}, {0xfb46, 0xfbb1}, {0xfbd3, 0xfd3d}, + {0xfd50, 0xfd8f}, {0xfd92, 0xfdc7}, {0xfdf0, 0xfdfb}, {0xfe70, 0xfe74}, + {0xfe76, 0xfefc}, {0xff21, 0xff3a}, {0xff41, 0xff5a}, {0xff66, 0xffbe}, + {0xffc2, 0xffc7}, {0xffca, 0xffcf}, {0xffd2, 0xffd7}, {0xffda, 0xffdc} }; +static const xmlChLRange xmlLL[] = {{0x10000, 0x1000b}, {0x1000d, 0x10026}, + {0x10028, 0x1003a}, {0x1003c, 0x1003d}, {0x1003f, 0x1004d}, + {0x10050, 0x1005d}, {0x10080, 0x100fa}, {0x10300, 0x1031e}, + {0x10330, 0x10349}, {0x10380, 0x1039d}, {0x10400, 0x1049d}, + {0x10800, 0x10805}, {0x10808, 0x10808}, {0x1080a, 0x10835}, + {0x10837, 0x10838}, {0x1083c, 0x1083c}, {0x1083f, 0x1083f}, + {0x1d400, 0x1d454}, {0x1d456, 0x1d49c}, {0x1d49e, 0x1d49f}, + {0x1d4a2, 0x1d4a2}, {0x1d4a5, 0x1d4a6}, {0x1d4a9, 0x1d4ac}, + {0x1d4ae, 0x1d4b9}, {0x1d4bb, 0x1d4bb}, {0x1d4bd, 0x1d4c3}, + {0x1d4c5, 0x1d505}, {0x1d507, 0x1d50a}, {0x1d50d, 0x1d514}, + {0x1d516, 0x1d51c}, {0x1d51e, 0x1d539}, {0x1d53b, 0x1d53e}, + {0x1d540, 0x1d544}, {0x1d546, 0x1d546}, {0x1d54a, 0x1d550}, + {0x1d552, 0x1d6a3}, {0x1d6a8, 0x1d6c0}, {0x1d6c2, 0x1d6da}, + {0x1d6dc, 0x1d6fa}, {0x1d6fc, 0x1d714}, {0x1d716, 0x1d734}, + {0x1d736, 0x1d74e}, {0x1d750, 0x1d76e}, {0x1d770, 0x1d788}, + {0x1d78a, 0x1d7a8}, {0x1d7aa, 0x1d7c2}, {0x1d7c4, 0x1d7c9}, + {0x20000, 0x20000}, {0x2a6d6, 0x2a6d6}, {0x2f800, 0x2fa1d} }; +static xmlChRangeGroup xmlLG = {279,50,xmlLS,xmlLL}; + +static const xmlChSRange xmlLlS[] = {{0x61, 0x7a}, {0xaa, 0xaa}, + {0xb5, 0xb5}, {0xba, 0xba}, {0xdf, 0xf6}, {0xf8, 0xff}, {0x101, 0x101}, + {0x103, 0x103}, {0x105, 0x105}, {0x107, 0x107}, {0x109, 0x109}, + {0x10b, 0x10b}, {0x10d, 0x10d}, {0x10f, 0x10f}, {0x111, 0x111}, + {0x113, 0x113}, {0x115, 0x115}, {0x117, 0x117}, {0x119, 0x119}, + {0x11b, 0x11b}, {0x11d, 0x11d}, {0x11f, 0x11f}, {0x121, 0x121}, + {0x123, 0x123}, {0x125, 0x125}, {0x127, 0x127}, {0x129, 0x129}, + {0x12b, 0x12b}, {0x12d, 0x12d}, {0x12f, 0x12f}, {0x131, 0x131}, + {0x133, 0x133}, {0x135, 0x135}, {0x137, 0x138}, {0x13a, 0x13a}, + {0x13c, 0x13c}, {0x13e, 0x13e}, {0x140, 0x140}, {0x142, 0x142}, + {0x144, 0x144}, {0x146, 0x146}, {0x148, 0x149}, {0x14b, 0x14b}, + {0x14d, 0x14d}, {0x14f, 0x14f}, {0x151, 0x151}, {0x153, 0x153}, + {0x155, 0x155}, {0x157, 0x157}, {0x159, 0x159}, {0x15b, 0x15b}, + {0x15d, 0x15d}, {0x15f, 0x15f}, {0x161, 0x161}, {0x163, 0x163}, + {0x165, 0x165}, {0x167, 0x167}, {0x169, 0x169}, {0x16b, 0x16b}, + {0x16d, 0x16d}, {0x16f, 0x16f}, {0x171, 0x171}, {0x173, 0x173}, + {0x175, 0x175}, {0x177, 0x177}, {0x17a, 0x17a}, {0x17c, 0x17c}, + {0x17e, 0x180}, {0x183, 0x183}, {0x185, 0x185}, {0x188, 0x188}, + {0x18c, 0x18d}, {0x192, 0x192}, {0x195, 0x195}, {0x199, 0x19b}, + {0x19e, 0x19e}, {0x1a1, 0x1a1}, {0x1a3, 0x1a3}, {0x1a5, 0x1a5}, + {0x1a8, 0x1a8}, {0x1aa, 0x1ab}, {0x1ad, 0x1ad}, {0x1b0, 0x1b0}, + {0x1b4, 0x1b4}, {0x1b6, 0x1b6}, {0x1b9, 0x1ba}, {0x1bd, 0x1bf}, + {0x1c6, 0x1c6}, {0x1c9, 0x1c9}, {0x1cc, 0x1cc}, {0x1ce, 0x1ce}, + {0x1d0, 0x1d0}, {0x1d2, 0x1d2}, {0x1d4, 0x1d4}, {0x1d6, 0x1d6}, + {0x1d8, 0x1d8}, {0x1da, 0x1da}, {0x1dc, 0x1dd}, {0x1df, 0x1df}, + {0x1e1, 0x1e1}, {0x1e3, 0x1e3}, {0x1e5, 0x1e5}, {0x1e7, 0x1e7}, + {0x1e9, 0x1e9}, {0x1eb, 0x1eb}, {0x1ed, 0x1ed}, {0x1ef, 0x1f0}, + {0x1f3, 0x1f3}, {0x1f5, 0x1f5}, {0x1f9, 0x1f9}, {0x1fb, 0x1fb}, + {0x1fd, 0x1fd}, {0x1ff, 0x1ff}, {0x201, 0x201}, {0x203, 0x203}, + {0x205, 0x205}, {0x207, 0x207}, {0x209, 0x209}, {0x20b, 0x20b}, + {0x20d, 0x20d}, {0x20f, 0x20f}, {0x211, 0x211}, {0x213, 0x213}, + {0x215, 0x215}, {0x217, 0x217}, {0x219, 0x219}, {0x21b, 0x21b}, + {0x21d, 0x21d}, {0x21f, 0x21f}, {0x221, 0x221}, {0x223, 0x223}, + {0x225, 0x225}, {0x227, 0x227}, {0x229, 0x229}, {0x22b, 0x22b}, + {0x22d, 0x22d}, {0x22f, 0x22f}, {0x231, 0x231}, {0x233, 0x236}, + {0x250, 0x2af}, {0x390, 0x390}, {0x3ac, 0x3ce}, {0x3d0, 0x3d1}, + {0x3d5, 0x3d7}, {0x3d9, 0x3d9}, {0x3db, 0x3db}, {0x3dd, 0x3dd}, + {0x3df, 0x3df}, {0x3e1, 0x3e1}, {0x3e3, 0x3e3}, {0x3e5, 0x3e5}, + {0x3e7, 0x3e7}, {0x3e9, 0x3e9}, {0x3eb, 0x3eb}, {0x3ed, 0x3ed}, + {0x3ef, 0x3f3}, {0x3f5, 0x3f5}, {0x3f8, 0x3f8}, {0x3fb, 0x3fb}, + {0x430, 0x45f}, {0x461, 0x461}, {0x463, 0x463}, {0x465, 0x465}, + {0x467, 0x467}, {0x469, 0x469}, {0x46b, 0x46b}, {0x46d, 0x46d}, + {0x46f, 0x46f}, {0x471, 0x471}, {0x473, 0x473}, {0x475, 0x475}, + {0x477, 0x477}, {0x479, 0x479}, {0x47b, 0x47b}, {0x47d, 0x47d}, + {0x47f, 0x47f}, {0x481, 0x481}, {0x48b, 0x48b}, {0x48d, 0x48d}, + {0x48f, 0x48f}, {0x491, 0x491}, {0x493, 0x493}, {0x495, 0x495}, + {0x497, 0x497}, {0x499, 0x499}, {0x49b, 0x49b}, {0x49d, 0x49d}, + {0x49f, 0x49f}, {0x4a1, 0x4a1}, {0x4a3, 0x4a3}, {0x4a5, 0x4a5}, + {0x4a7, 0x4a7}, {0x4a9, 0x4a9}, {0x4ab, 0x4ab}, {0x4ad, 0x4ad}, + {0x4af, 0x4af}, {0x4b1, 0x4b1}, {0x4b3, 0x4b3}, {0x4b5, 0x4b5}, + {0x4b7, 0x4b7}, {0x4b9, 0x4b9}, {0x4bb, 0x4bb}, {0x4bd, 0x4bd}, + {0x4bf, 0x4bf}, {0x4c2, 0x4c2}, {0x4c4, 0x4c4}, {0x4c6, 0x4c6}, + {0x4c8, 0x4c8}, {0x4ca, 0x4ca}, {0x4cc, 0x4cc}, {0x4ce, 0x4ce}, + {0x4d1, 0x4d1}, {0x4d3, 0x4d3}, {0x4d5, 0x4d5}, {0x4d7, 0x4d7}, + {0x4d9, 0x4d9}, {0x4db, 0x4db}, {0x4dd, 0x4dd}, {0x4df, 0x4df}, + {0x4e1, 0x4e1}, {0x4e3, 0x4e3}, {0x4e5, 0x4e5}, {0x4e7, 0x4e7}, + {0x4e9, 0x4e9}, {0x4eb, 0x4eb}, {0x4ed, 0x4ed}, {0x4ef, 0x4ef}, + {0x4f1, 0x4f1}, {0x4f3, 0x4f3}, {0x4f5, 0x4f5}, {0x4f9, 0x4f9}, + {0x501, 0x501}, {0x503, 0x503}, {0x505, 0x505}, {0x507, 0x507}, + {0x509, 0x509}, {0x50b, 0x50b}, {0x50d, 0x50d}, {0x50f, 0x50f}, + {0x561, 0x587}, {0x1d00, 0x1d2b}, {0x1d62, 0x1d6b}, {0x1e01, 0x1e01}, + {0x1e03, 0x1e03}, {0x1e05, 0x1e05}, {0x1e07, 0x1e07}, {0x1e09, 0x1e09}, + {0x1e0b, 0x1e0b}, {0x1e0d, 0x1e0d}, {0x1e0f, 0x1e0f}, {0x1e11, 0x1e11}, + {0x1e13, 0x1e13}, {0x1e15, 0x1e15}, {0x1e17, 0x1e17}, {0x1e19, 0x1e19}, + {0x1e1b, 0x1e1b}, {0x1e1d, 0x1e1d}, {0x1e1f, 0x1e1f}, {0x1e21, 0x1e21}, + {0x1e23, 0x1e23}, {0x1e25, 0x1e25}, {0x1e27, 0x1e27}, {0x1e29, 0x1e29}, + {0x1e2b, 0x1e2b}, {0x1e2d, 0x1e2d}, {0x1e2f, 0x1e2f}, {0x1e31, 0x1e31}, + {0x1e33, 0x1e33}, {0x1e35, 0x1e35}, {0x1e37, 0x1e37}, {0x1e39, 0x1e39}, + {0x1e3b, 0x1e3b}, {0x1e3d, 0x1e3d}, {0x1e3f, 0x1e3f}, {0x1e41, 0x1e41}, + {0x1e43, 0x1e43}, {0x1e45, 0x1e45}, {0x1e47, 0x1e47}, {0x1e49, 0x1e49}, + {0x1e4b, 0x1e4b}, {0x1e4d, 0x1e4d}, {0x1e4f, 0x1e4f}, {0x1e51, 0x1e51}, + {0x1e53, 0x1e53}, {0x1e55, 0x1e55}, {0x1e57, 0x1e57}, {0x1e59, 0x1e59}, + {0x1e5b, 0x1e5b}, {0x1e5d, 0x1e5d}, {0x1e5f, 0x1e5f}, {0x1e61, 0x1e61}, + {0x1e63, 0x1e63}, {0x1e65, 0x1e65}, {0x1e67, 0x1e67}, {0x1e69, 0x1e69}, + {0x1e6b, 0x1e6b}, {0x1e6d, 0x1e6d}, {0x1e6f, 0x1e6f}, {0x1e71, 0x1e71}, + {0x1e73, 0x1e73}, {0x1e75, 0x1e75}, {0x1e77, 0x1e77}, {0x1e79, 0x1e79}, + {0x1e7b, 0x1e7b}, {0x1e7d, 0x1e7d}, {0x1e7f, 0x1e7f}, {0x1e81, 0x1e81}, + {0x1e83, 0x1e83}, {0x1e85, 0x1e85}, {0x1e87, 0x1e87}, {0x1e89, 0x1e89}, + {0x1e8b, 0x1e8b}, {0x1e8d, 0x1e8d}, {0x1e8f, 0x1e8f}, {0x1e91, 0x1e91}, + {0x1e93, 0x1e93}, {0x1e95, 0x1e9b}, {0x1ea1, 0x1ea1}, {0x1ea3, 0x1ea3}, + {0x1ea5, 0x1ea5}, {0x1ea7, 0x1ea7}, {0x1ea9, 0x1ea9}, {0x1eab, 0x1eab}, + {0x1ead, 0x1ead}, {0x1eaf, 0x1eaf}, {0x1eb1, 0x1eb1}, {0x1eb3, 0x1eb3}, + {0x1eb5, 0x1eb5}, {0x1eb7, 0x1eb7}, {0x1eb9, 0x1eb9}, {0x1ebb, 0x1ebb}, + {0x1ebd, 0x1ebd}, {0x1ebf, 0x1ebf}, {0x1ec1, 0x1ec1}, {0x1ec3, 0x1ec3}, + {0x1ec5, 0x1ec5}, {0x1ec7, 0x1ec7}, {0x1ec9, 0x1ec9}, {0x1ecb, 0x1ecb}, + {0x1ecd, 0x1ecd}, {0x1ecf, 0x1ecf}, {0x1ed1, 0x1ed1}, {0x1ed3, 0x1ed3}, + {0x1ed5, 0x1ed5}, {0x1ed7, 0x1ed7}, {0x1ed9, 0x1ed9}, {0x1edb, 0x1edb}, + {0x1edd, 0x1edd}, {0x1edf, 0x1edf}, {0x1ee1, 0x1ee1}, {0x1ee3, 0x1ee3}, + {0x1ee5, 0x1ee5}, {0x1ee7, 0x1ee7}, {0x1ee9, 0x1ee9}, {0x1eeb, 0x1eeb}, + {0x1eed, 0x1eed}, {0x1eef, 0x1eef}, {0x1ef1, 0x1ef1}, {0x1ef3, 0x1ef3}, + {0x1ef5, 0x1ef5}, {0x1ef7, 0x1ef7}, {0x1ef9, 0x1ef9}, {0x1f00, 0x1f07}, + {0x1f10, 0x1f15}, {0x1f20, 0x1f27}, {0x1f30, 0x1f37}, {0x1f40, 0x1f45}, + {0x1f50, 0x1f57}, {0x1f60, 0x1f67}, {0x1f70, 0x1f7d}, {0x1f80, 0x1f87}, + {0x1f90, 0x1f97}, {0x1fa0, 0x1fa7}, {0x1fb0, 0x1fb4}, {0x1fb6, 0x1fb7}, + {0x1fbe, 0x1fbe}, {0x1fc2, 0x1fc4}, {0x1fc6, 0x1fc7}, {0x1fd0, 0x1fd3}, + {0x1fd6, 0x1fd7}, {0x1fe0, 0x1fe7}, {0x1ff2, 0x1ff4}, {0x1ff6, 0x1ff7}, + {0x2071, 0x2071}, {0x207f, 0x207f}, {0x210a, 0x210a}, {0x210e, 0x210f}, + {0x2113, 0x2113}, {0x212f, 0x212f}, {0x2134, 0x2134}, {0x2139, 0x2139}, + {0x213d, 0x213d}, {0x2146, 0x2149}, {0xfb00, 0xfb06}, {0xfb13, 0xfb17}, + {0xff41, 0xff5a} }; +static const xmlChLRange xmlLlL[] = {{0x10428, 0x1044f}, {0x1d41a, 0x1d433}, + {0x1d44e, 0x1d454}, {0x1d456, 0x1d467}, {0x1d482, 0x1d49b}, + {0x1d4b6, 0x1d4b9}, {0x1d4bb, 0x1d4bb}, {0x1d4bd, 0x1d4c3}, + {0x1d4c5, 0x1d4cf}, {0x1d4ea, 0x1d503}, {0x1d51e, 0x1d537}, + {0x1d552, 0x1d56b}, {0x1d586, 0x1d59f}, {0x1d5ba, 0x1d5d3}, + {0x1d5ee, 0x1d607}, {0x1d622, 0x1d63b}, {0x1d656, 0x1d66f}, + {0x1d68a, 0x1d6a3}, {0x1d6c2, 0x1d6da}, {0x1d6dc, 0x1d6e1}, + {0x1d6fc, 0x1d714}, {0x1d716, 0x1d71b}, {0x1d736, 0x1d74e}, + {0x1d750, 0x1d755}, {0x1d770, 0x1d788}, {0x1d78a, 0x1d78f}, + {0x1d7aa, 0x1d7c2}, {0x1d7c4, 0x1d7c9} }; +static xmlChRangeGroup xmlLlG = {396,28,xmlLlS,xmlLlL}; + +static const xmlChSRange xmlLmS[] = {{0x2b0, 0x2c1}, {0x2c6, 0x2d1}, + {0x2e0, 0x2e4}, {0x2ee, 0x2ee}, {0x37a, 0x37a}, {0x559, 0x559}, + {0x640, 0x640}, {0x6e5, 0x6e6}, {0xe46, 0xe46}, {0xec6, 0xec6}, + {0x17d7, 0x17d7}, {0x1843, 0x1843}, {0x1d2c, 0x1d61}, {0x3005, 0x3005}, + {0x3031, 0x3035}, {0x303b, 0x303b}, {0x309d, 0x309e}, {0x30fc, 0x30fe}, + {0xff70, 0xff70}, {0xff9e, 0xff9f} }; +static xmlChRangeGroup xmlLmG = {20,0,xmlLmS,NULL}; + +static const xmlChSRange xmlLoS[] = {{0x1bb, 0x1bb}, {0x1c0, 0x1c3}, + {0x5d0, 0x5ea}, {0x5f0, 0x5f2}, {0x621, 0x63a}, {0x641, 0x64a}, + {0x66e, 0x66f}, {0x671, 0x6d3}, {0x6d5, 0x6d5}, {0x6ee, 0x6ef}, + {0x6fa, 0x6fc}, {0x6ff, 0x6ff}, {0x710, 0x710}, {0x712, 0x72f}, + {0x74d, 0x74f}, {0x780, 0x7a5}, {0x7b1, 0x7b1}, {0x904, 0x939}, + {0x93d, 0x93d}, {0x950, 0x950}, {0x958, 0x961}, {0x985, 0x98c}, + {0x98f, 0x990}, {0x993, 0x9a8}, {0x9aa, 0x9b0}, {0x9b2, 0x9b2}, + {0x9b6, 0x9b9}, {0x9bd, 0x9bd}, {0x9dc, 0x9dd}, {0x9df, 0x9e1}, + {0x9f0, 0x9f1}, {0xa05, 0xa0a}, {0xa0f, 0xa10}, {0xa13, 0xa28}, + {0xa2a, 0xa30}, {0xa32, 0xa33}, {0xa35, 0xa36}, {0xa38, 0xa39}, + {0xa59, 0xa5c}, {0xa5e, 0xa5e}, {0xa72, 0xa74}, {0xa85, 0xa8d}, + {0xa8f, 0xa91}, {0xa93, 0xaa8}, {0xaaa, 0xab0}, {0xab2, 0xab3}, + {0xab5, 0xab9}, {0xabd, 0xabd}, {0xad0, 0xad0}, {0xae0, 0xae1}, + {0xb05, 0xb0c}, {0xb0f, 0xb10}, {0xb13, 0xb28}, {0xb2a, 0xb30}, + {0xb32, 0xb33}, {0xb35, 0xb39}, {0xb3d, 0xb3d}, {0xb5c, 0xb5d}, + {0xb5f, 0xb61}, {0xb71, 0xb71}, {0xb83, 0xb83}, {0xb85, 0xb8a}, + {0xb8e, 0xb90}, {0xb92, 0xb95}, {0xb99, 0xb9a}, {0xb9c, 0xb9c}, + {0xb9e, 0xb9f}, {0xba3, 0xba4}, {0xba8, 0xbaa}, {0xbae, 0xbb5}, + {0xbb7, 0xbb9}, {0xc05, 0xc0c}, {0xc0e, 0xc10}, {0xc12, 0xc28}, + {0xc2a, 0xc33}, {0xc35, 0xc39}, {0xc60, 0xc61}, {0xc85, 0xc8c}, + {0xc8e, 0xc90}, {0xc92, 0xca8}, {0xcaa, 0xcb3}, {0xcb5, 0xcb9}, + {0xcbd, 0xcbd}, {0xcde, 0xcde}, {0xce0, 0xce1}, {0xd05, 0xd0c}, + {0xd0e, 0xd10}, {0xd12, 0xd28}, {0xd2a, 0xd39}, {0xd60, 0xd61}, + {0xd85, 0xd96}, {0xd9a, 0xdb1}, {0xdb3, 0xdbb}, {0xdbd, 0xdbd}, + {0xdc0, 0xdc6}, {0xe01, 0xe30}, {0xe32, 0xe33}, {0xe40, 0xe45}, + {0xe81, 0xe82}, {0xe84, 0xe84}, {0xe87, 0xe88}, {0xe8a, 0xe8a}, + {0xe8d, 0xe8d}, {0xe94, 0xe97}, {0xe99, 0xe9f}, {0xea1, 0xea3}, + {0xea5, 0xea5}, {0xea7, 0xea7}, {0xeaa, 0xeab}, {0xead, 0xeb0}, + {0xeb2, 0xeb3}, {0xebd, 0xebd}, {0xec0, 0xec4}, {0xedc, 0xedd}, + {0xf00, 0xf00}, {0xf40, 0xf47}, {0xf49, 0xf6a}, {0xf88, 0xf8b}, + {0x1000, 0x1021}, {0x1023, 0x1027}, {0x1029, 0x102a}, {0x1050, 0x1055}, + {0x10d0, 0x10f8}, {0x1100, 0x1159}, {0x115f, 0x11a2}, {0x11a8, 0x11f9}, + {0x1200, 0x1206}, {0x1208, 0x1246}, {0x1248, 0x1248}, {0x124a, 0x124d}, + {0x1250, 0x1256}, {0x1258, 0x1258}, {0x125a, 0x125d}, {0x1260, 0x1286}, + {0x1288, 0x1288}, {0x128a, 0x128d}, {0x1290, 0x12ae}, {0x12b0, 0x12b0}, + {0x12b2, 0x12b5}, {0x12b8, 0x12be}, {0x12c0, 0x12c0}, {0x12c2, 0x12c5}, + {0x12c8, 0x12ce}, {0x12d0, 0x12d6}, {0x12d8, 0x12ee}, {0x12f0, 0x130e}, + {0x1310, 0x1310}, {0x1312, 0x1315}, {0x1318, 0x131e}, {0x1320, 0x1346}, + {0x1348, 0x135a}, {0x13a0, 0x13f4}, {0x1401, 0x166c}, {0x166f, 0x1676}, + {0x1681, 0x169a}, {0x16a0, 0x16ea}, {0x1700, 0x170c}, {0x170e, 0x1711}, + {0x1720, 0x1731}, {0x1740, 0x1751}, {0x1760, 0x176c}, {0x176e, 0x1770}, + {0x1780, 0x17b3}, {0x17dc, 0x17dc}, {0x1820, 0x1842}, {0x1844, 0x1877}, + {0x1880, 0x18a8}, {0x1900, 0x191c}, {0x1950, 0x196d}, {0x1970, 0x1974}, + {0x2135, 0x2138}, {0x3006, 0x3006}, {0x303c, 0x303c}, {0x3041, 0x3096}, + {0x309f, 0x309f}, {0x30a1, 0x30fa}, {0x30ff, 0x30ff}, {0x3105, 0x312c}, + {0x3131, 0x318e}, {0x31a0, 0x31b7}, {0x31f0, 0x31ff}, {0x3400, 0x3400}, + {0x4db5, 0x4db5}, {0x4e00, 0x4e00}, {0x9fa5, 0x9fa5}, {0xa000, 0xa48c}, + {0xac00, 0xac00}, {0xd7a3, 0xd7a3}, {0xf900, 0xfa2d}, {0xfa30, 0xfa6a}, + {0xfb1d, 0xfb1d}, {0xfb1f, 0xfb28}, {0xfb2a, 0xfb36}, {0xfb38, 0xfb3c}, + {0xfb3e, 0xfb3e}, {0xfb40, 0xfb41}, {0xfb43, 0xfb44}, {0xfb46, 0xfbb1}, + {0xfbd3, 0xfd3d}, {0xfd50, 0xfd8f}, {0xfd92, 0xfdc7}, {0xfdf0, 0xfdfb}, + {0xfe70, 0xfe74}, {0xfe76, 0xfefc}, {0xff66, 0xff6f}, {0xff71, 0xff9d}, + {0xffa0, 0xffbe}, {0xffc2, 0xffc7}, {0xffca, 0xffcf}, {0xffd2, 0xffd7}, + {0xffda, 0xffdc} }; +static const xmlChLRange xmlLoL[] = {{0x10000, 0x1000b}, {0x1000d, 0x10026}, + {0x10028, 0x1003a}, {0x1003c, 0x1003d}, {0x1003f, 0x1004d}, + {0x10050, 0x1005d}, {0x10080, 0x100fa}, {0x10300, 0x1031e}, + {0x10330, 0x10349}, {0x10380, 0x1039d}, {0x10450, 0x1049d}, + {0x10800, 0x10805}, {0x10808, 0x10808}, {0x1080a, 0x10835}, + {0x10837, 0x10838}, {0x1083c, 0x1083c}, {0x1083f, 0x1083f}, + {0x20000, 0x20000}, {0x2a6d6, 0x2a6d6}, {0x2f800, 0x2fa1d} }; +static xmlChRangeGroup xmlLoG = {211,20,xmlLoS,xmlLoL}; + +static const xmlChSRange xmlLtS[] = {{0x1c5, 0x1c5}, {0x1c8, 0x1c8}, + {0x1cb, 0x1cb}, {0x1f2, 0x1f2}, {0x1f88, 0x1f8f}, {0x1f98, 0x1f9f}, + {0x1fa8, 0x1faf}, {0x1fbc, 0x1fbc}, {0x1fcc, 0x1fcc}, {0x1ffc, 0x1ffc} }; +static xmlChRangeGroup xmlLtG = {10,0,xmlLtS,NULL}; + +static const xmlChSRange xmlLuS[] = {{0x41, 0x5a}, {0xc0, 0xd6}, + {0xd8, 0xde}, {0x100, 0x100}, {0x102, 0x102}, {0x104, 0x104}, + {0x106, 0x106}, {0x108, 0x108}, {0x10a, 0x10a}, {0x10c, 0x10c}, + {0x10e, 0x10e}, {0x110, 0x110}, {0x112, 0x112}, {0x114, 0x114}, + {0x116, 0x116}, {0x118, 0x118}, {0x11a, 0x11a}, {0x11c, 0x11c}, + {0x11e, 0x11e}, {0x120, 0x120}, {0x122, 0x122}, {0x124, 0x124}, + {0x126, 0x126}, {0x128, 0x128}, {0x12a, 0x12a}, {0x12c, 0x12c}, + {0x12e, 0x12e}, {0x130, 0x130}, {0x132, 0x132}, {0x134, 0x134}, + {0x136, 0x136}, {0x139, 0x139}, {0x13b, 0x13b}, {0x13d, 0x13d}, + {0x13f, 0x13f}, {0x141, 0x141}, {0x143, 0x143}, {0x145, 0x145}, + {0x147, 0x147}, {0x14a, 0x14a}, {0x14c, 0x14c}, {0x14e, 0x14e}, + {0x150, 0x150}, {0x152, 0x152}, {0x154, 0x154}, {0x156, 0x156}, + {0x158, 0x158}, {0x15a, 0x15a}, {0x15c, 0x15c}, {0x15e, 0x15e}, + {0x160, 0x160}, {0x162, 0x162}, {0x164, 0x164}, {0x166, 0x166}, + {0x168, 0x168}, {0x16a, 0x16a}, {0x16c, 0x16c}, {0x16e, 0x16e}, + {0x170, 0x170}, {0x172, 0x172}, {0x174, 0x174}, {0x176, 0x176}, + {0x178, 0x179}, {0x17b, 0x17b}, {0x17d, 0x17d}, {0x181, 0x182}, + {0x184, 0x184}, {0x186, 0x187}, {0x189, 0x18b}, {0x18e, 0x191}, + {0x193, 0x194}, {0x196, 0x198}, {0x19c, 0x19d}, {0x19f, 0x1a0}, + {0x1a2, 0x1a2}, {0x1a4, 0x1a4}, {0x1a6, 0x1a7}, {0x1a9, 0x1a9}, + {0x1ac, 0x1ac}, {0x1ae, 0x1af}, {0x1b1, 0x1b3}, {0x1b5, 0x1b5}, + {0x1b7, 0x1b8}, {0x1bc, 0x1bc}, {0x1c4, 0x1c4}, {0x1c7, 0x1c7}, + {0x1ca, 0x1ca}, {0x1cd, 0x1cd}, {0x1cf, 0x1cf}, {0x1d1, 0x1d1}, + {0x1d3, 0x1d3}, {0x1d5, 0x1d5}, {0x1d7, 0x1d7}, {0x1d9, 0x1d9}, + {0x1db, 0x1db}, {0x1de, 0x1de}, {0x1e0, 0x1e0}, {0x1e2, 0x1e2}, + {0x1e4, 0x1e4}, {0x1e6, 0x1e6}, {0x1e8, 0x1e8}, {0x1ea, 0x1ea}, + {0x1ec, 0x1ec}, {0x1ee, 0x1ee}, {0x1f1, 0x1f1}, {0x1f4, 0x1f4}, + {0x1f6, 0x1f8}, {0x1fa, 0x1fa}, {0x1fc, 0x1fc}, {0x1fe, 0x1fe}, + {0x200, 0x200}, {0x202, 0x202}, {0x204, 0x204}, {0x206, 0x206}, + {0x208, 0x208}, {0x20a, 0x20a}, {0x20c, 0x20c}, {0x20e, 0x20e}, + {0x210, 0x210}, {0x212, 0x212}, {0x214, 0x214}, {0x216, 0x216}, + {0x218, 0x218}, {0x21a, 0x21a}, {0x21c, 0x21c}, {0x21e, 0x21e}, + {0x220, 0x220}, {0x222, 0x222}, {0x224, 0x224}, {0x226, 0x226}, + {0x228, 0x228}, {0x22a, 0x22a}, {0x22c, 0x22c}, {0x22e, 0x22e}, + {0x230, 0x230}, {0x232, 0x232}, {0x386, 0x386}, {0x388, 0x38a}, + {0x38c, 0x38c}, {0x38e, 0x38f}, {0x391, 0x3a1}, {0x3a3, 0x3ab}, + {0x3d2, 0x3d4}, {0x3d8, 0x3d8}, {0x3da, 0x3da}, {0x3dc, 0x3dc}, + {0x3de, 0x3de}, {0x3e0, 0x3e0}, {0x3e2, 0x3e2}, {0x3e4, 0x3e4}, + {0x3e6, 0x3e6}, {0x3e8, 0x3e8}, {0x3ea, 0x3ea}, {0x3ec, 0x3ec}, + {0x3ee, 0x3ee}, {0x3f4, 0x3f4}, {0x3f7, 0x3f7}, {0x3f9, 0x3fa}, + {0x400, 0x42f}, {0x460, 0x460}, {0x462, 0x462}, {0x464, 0x464}, + {0x466, 0x466}, {0x468, 0x468}, {0x46a, 0x46a}, {0x46c, 0x46c}, + {0x46e, 0x46e}, {0x470, 0x470}, {0x472, 0x472}, {0x474, 0x474}, + {0x476, 0x476}, {0x478, 0x478}, {0x47a, 0x47a}, {0x47c, 0x47c}, + {0x47e, 0x47e}, {0x480, 0x480}, {0x48a, 0x48a}, {0x48c, 0x48c}, + {0x48e, 0x48e}, {0x490, 0x490}, {0x492, 0x492}, {0x494, 0x494}, + {0x496, 0x496}, {0x498, 0x498}, {0x49a, 0x49a}, {0x49c, 0x49c}, + {0x49e, 0x49e}, {0x4a0, 0x4a0}, {0x4a2, 0x4a2}, {0x4a4, 0x4a4}, + {0x4a6, 0x4a6}, {0x4a8, 0x4a8}, {0x4aa, 0x4aa}, {0x4ac, 0x4ac}, + {0x4ae, 0x4ae}, {0x4b0, 0x4b0}, {0x4b2, 0x4b2}, {0x4b4, 0x4b4}, + {0x4b6, 0x4b6}, {0x4b8, 0x4b8}, {0x4ba, 0x4ba}, {0x4bc, 0x4bc}, + {0x4be, 0x4be}, {0x4c0, 0x4c1}, {0x4c3, 0x4c3}, {0x4c5, 0x4c5}, + {0x4c7, 0x4c7}, {0x4c9, 0x4c9}, {0x4cb, 0x4cb}, {0x4cd, 0x4cd}, + {0x4d0, 0x4d0}, {0x4d2, 0x4d2}, {0x4d4, 0x4d4}, {0x4d6, 0x4d6}, + {0x4d8, 0x4d8}, {0x4da, 0x4da}, {0x4dc, 0x4dc}, {0x4de, 0x4de}, + {0x4e0, 0x4e0}, {0x4e2, 0x4e2}, {0x4e4, 0x4e4}, {0x4e6, 0x4e6}, + {0x4e8, 0x4e8}, {0x4ea, 0x4ea}, {0x4ec, 0x4ec}, {0x4ee, 0x4ee}, + {0x4f0, 0x4f0}, {0x4f2, 0x4f2}, {0x4f4, 0x4f4}, {0x4f8, 0x4f8}, + {0x500, 0x500}, {0x502, 0x502}, {0x504, 0x504}, {0x506, 0x506}, + {0x508, 0x508}, {0x50a, 0x50a}, {0x50c, 0x50c}, {0x50e, 0x50e}, + {0x531, 0x556}, {0x10a0, 0x10c5}, {0x1e00, 0x1e00}, {0x1e02, 0x1e02}, + {0x1e04, 0x1e04}, {0x1e06, 0x1e06}, {0x1e08, 0x1e08}, {0x1e0a, 0x1e0a}, + {0x1e0c, 0x1e0c}, {0x1e0e, 0x1e0e}, {0x1e10, 0x1e10}, {0x1e12, 0x1e12}, + {0x1e14, 0x1e14}, {0x1e16, 0x1e16}, {0x1e18, 0x1e18}, {0x1e1a, 0x1e1a}, + {0x1e1c, 0x1e1c}, {0x1e1e, 0x1e1e}, {0x1e20, 0x1e20}, {0x1e22, 0x1e22}, + {0x1e24, 0x1e24}, {0x1e26, 0x1e26}, {0x1e28, 0x1e28}, {0x1e2a, 0x1e2a}, + {0x1e2c, 0x1e2c}, {0x1e2e, 0x1e2e}, {0x1e30, 0x1e30}, {0x1e32, 0x1e32}, + {0x1e34, 0x1e34}, {0x1e36, 0x1e36}, {0x1e38, 0x1e38}, {0x1e3a, 0x1e3a}, + {0x1e3c, 0x1e3c}, {0x1e3e, 0x1e3e}, {0x1e40, 0x1e40}, {0x1e42, 0x1e42}, + {0x1e44, 0x1e44}, {0x1e46, 0x1e46}, {0x1e48, 0x1e48}, {0x1e4a, 0x1e4a}, + {0x1e4c, 0x1e4c}, {0x1e4e, 0x1e4e}, {0x1e50, 0x1e50}, {0x1e52, 0x1e52}, + {0x1e54, 0x1e54}, {0x1e56, 0x1e56}, {0x1e58, 0x1e58}, {0x1e5a, 0x1e5a}, + {0x1e5c, 0x1e5c}, {0x1e5e, 0x1e5e}, {0x1e60, 0x1e60}, {0x1e62, 0x1e62}, + {0x1e64, 0x1e64}, {0x1e66, 0x1e66}, {0x1e68, 0x1e68}, {0x1e6a, 0x1e6a}, + {0x1e6c, 0x1e6c}, {0x1e6e, 0x1e6e}, {0x1e70, 0x1e70}, {0x1e72, 0x1e72}, + {0x1e74, 0x1e74}, {0x1e76, 0x1e76}, {0x1e78, 0x1e78}, {0x1e7a, 0x1e7a}, + {0x1e7c, 0x1e7c}, {0x1e7e, 0x1e7e}, {0x1e80, 0x1e80}, {0x1e82, 0x1e82}, + {0x1e84, 0x1e84}, {0x1e86, 0x1e86}, {0x1e88, 0x1e88}, {0x1e8a, 0x1e8a}, + {0x1e8c, 0x1e8c}, {0x1e8e, 0x1e8e}, {0x1e90, 0x1e90}, {0x1e92, 0x1e92}, + {0x1e94, 0x1e94}, {0x1ea0, 0x1ea0}, {0x1ea2, 0x1ea2}, {0x1ea4, 0x1ea4}, + {0x1ea6, 0x1ea6}, {0x1ea8, 0x1ea8}, {0x1eaa, 0x1eaa}, {0x1eac, 0x1eac}, + {0x1eae, 0x1eae}, {0x1eb0, 0x1eb0}, {0x1eb2, 0x1eb2}, {0x1eb4, 0x1eb4}, + {0x1eb6, 0x1eb6}, {0x1eb8, 0x1eb8}, {0x1eba, 0x1eba}, {0x1ebc, 0x1ebc}, + {0x1ebe, 0x1ebe}, {0x1ec0, 0x1ec0}, {0x1ec2, 0x1ec2}, {0x1ec4, 0x1ec4}, + {0x1ec6, 0x1ec6}, {0x1ec8, 0x1ec8}, {0x1eca, 0x1eca}, {0x1ecc, 0x1ecc}, + {0x1ece, 0x1ece}, {0x1ed0, 0x1ed0}, {0x1ed2, 0x1ed2}, {0x1ed4, 0x1ed4}, + {0x1ed6, 0x1ed6}, {0x1ed8, 0x1ed8}, {0x1eda, 0x1eda}, {0x1edc, 0x1edc}, + {0x1ede, 0x1ede}, {0x1ee0, 0x1ee0}, {0x1ee2, 0x1ee2}, {0x1ee4, 0x1ee4}, + {0x1ee6, 0x1ee6}, {0x1ee8, 0x1ee8}, {0x1eea, 0x1eea}, {0x1eec, 0x1eec}, + {0x1eee, 0x1eee}, {0x1ef0, 0x1ef0}, {0x1ef2, 0x1ef2}, {0x1ef4, 0x1ef4}, + {0x1ef6, 0x1ef6}, {0x1ef8, 0x1ef8}, {0x1f08, 0x1f0f}, {0x1f18, 0x1f1d}, + {0x1f28, 0x1f2f}, {0x1f38, 0x1f3f}, {0x1f48, 0x1f4d}, {0x1f59, 0x1f59}, + {0x1f5b, 0x1f5b}, {0x1f5d, 0x1f5d}, {0x1f5f, 0x1f5f}, {0x1f68, 0x1f6f}, + {0x1fb8, 0x1fbb}, {0x1fc8, 0x1fcb}, {0x1fd8, 0x1fdb}, {0x1fe8, 0x1fec}, + {0x1ff8, 0x1ffb}, {0x2102, 0x2102}, {0x2107, 0x2107}, {0x210b, 0x210d}, + {0x2110, 0x2112}, {0x2115, 0x2115}, {0x2119, 0x211d}, {0x2124, 0x2124}, + {0x2126, 0x2126}, {0x2128, 0x2128}, {0x212a, 0x212d}, {0x2130, 0x2131}, + {0x2133, 0x2133}, {0x213e, 0x213f}, {0x2145, 0x2145}, {0xff21, 0xff3a} }; +static const xmlChLRange xmlLuL[] = {{0x10400, 0x10427}, {0x1d400, 0x1d419}, + {0x1d434, 0x1d44d}, {0x1d468, 0x1d481}, {0x1d49c, 0x1d49c}, + {0x1d49e, 0x1d49f}, {0x1d4a2, 0x1d4a2}, {0x1d4a5, 0x1d4a6}, + {0x1d4a9, 0x1d4ac}, {0x1d4ae, 0x1d4b5}, {0x1d4d0, 0x1d4e9}, + {0x1d504, 0x1d505}, {0x1d507, 0x1d50a}, {0x1d50d, 0x1d514}, + {0x1d516, 0x1d51c}, {0x1d538, 0x1d539}, {0x1d53b, 0x1d53e}, + {0x1d540, 0x1d544}, {0x1d546, 0x1d546}, {0x1d54a, 0x1d550}, + {0x1d56c, 0x1d585}, {0x1d5a0, 0x1d5b9}, {0x1d5d4, 0x1d5ed}, + {0x1d608, 0x1d621}, {0x1d63c, 0x1d655}, {0x1d670, 0x1d689}, + {0x1d6a8, 0x1d6c0}, {0x1d6e2, 0x1d6fa}, {0x1d71c, 0x1d734}, + {0x1d756, 0x1d76e}, {0x1d790, 0x1d7a8} }; +static xmlChRangeGroup xmlLuG = {390,31,xmlLuS,xmlLuL}; + +static const xmlChSRange xmlMS[] = {{0x300, 0x357}, {0x35d, 0x36f}, + {0x483, 0x486}, {0x488, 0x489}, {0x591, 0x5a1}, {0x5a3, 0x5b9}, + {0x5bb, 0x5bd}, {0x5bf, 0x5bf}, {0x5c1, 0x5c2}, {0x5c4, 0x5c4}, + {0x610, 0x615}, {0x64b, 0x658}, {0x670, 0x670}, {0x6d6, 0x6dc}, + {0x6de, 0x6e4}, {0x6e7, 0x6e8}, {0x6ea, 0x6ed}, {0x711, 0x711}, + {0x730, 0x74a}, {0x7a6, 0x7b0}, {0x901, 0x903}, {0x93c, 0x93c}, + {0x93e, 0x94d}, {0x951, 0x954}, {0x962, 0x963}, {0x981, 0x983}, + {0x9bc, 0x9bc}, {0x9be, 0x9c4}, {0x9c7, 0x9c8}, {0x9cb, 0x9cd}, + {0x9d7, 0x9d7}, {0x9e2, 0x9e3}, {0xa01, 0xa03}, {0xa3c, 0xa3c}, + {0xa3e, 0xa42}, {0xa47, 0xa48}, {0xa4b, 0xa4d}, {0xa70, 0xa71}, + {0xa81, 0xa83}, {0xabc, 0xabc}, {0xabe, 0xac5}, {0xac7, 0xac9}, + {0xacb, 0xacd}, {0xae2, 0xae3}, {0xb01, 0xb03}, {0xb3c, 0xb3c}, + {0xb3e, 0xb43}, {0xb47, 0xb48}, {0xb4b, 0xb4d}, {0xb56, 0xb57}, + {0xb82, 0xb82}, {0xbbe, 0xbc2}, {0xbc6, 0xbc8}, {0xbca, 0xbcd}, + {0xbd7, 0xbd7}, {0xc01, 0xc03}, {0xc3e, 0xc44}, {0xc46, 0xc48}, + {0xc4a, 0xc4d}, {0xc55, 0xc56}, {0xc82, 0xc83}, {0xcbc, 0xcbc}, + {0xcbe, 0xcc4}, {0xcc6, 0xcc8}, {0xcca, 0xccd}, {0xcd5, 0xcd6}, + {0xd02, 0xd03}, {0xd3e, 0xd43}, {0xd46, 0xd48}, {0xd4a, 0xd4d}, + {0xd57, 0xd57}, {0xd82, 0xd83}, {0xdca, 0xdca}, {0xdcf, 0xdd4}, + {0xdd6, 0xdd6}, {0xdd8, 0xddf}, {0xdf2, 0xdf3}, {0xe31, 0xe31}, + {0xe34, 0xe3a}, {0xe47, 0xe4e}, {0xeb1, 0xeb1}, {0xeb4, 0xeb9}, + {0xebb, 0xebc}, {0xec8, 0xecd}, {0xf18, 0xf19}, {0xf35, 0xf35}, + {0xf37, 0xf37}, {0xf39, 0xf39}, {0xf3e, 0xf3f}, {0xf71, 0xf84}, + {0xf86, 0xf87}, {0xf90, 0xf97}, {0xf99, 0xfbc}, {0xfc6, 0xfc6}, + {0x102c, 0x1032}, {0x1036, 0x1039}, {0x1056, 0x1059}, {0x1712, 0x1714}, + {0x1732, 0x1734}, {0x1752, 0x1753}, {0x1772, 0x1773}, {0x17b6, 0x17d3}, + {0x17dd, 0x17dd}, {0x180b, 0x180d}, {0x18a9, 0x18a9}, {0x1920, 0x192b}, + {0x1930, 0x193b}, {0x20d0, 0x20ea}, {0x302a, 0x302f}, {0x3099, 0x309a}, + {0xfb1e, 0xfb1e}, {0xfe00, 0xfe0f}, {0xfe20, 0xfe23} }; +static const xmlChLRange xmlML[] = {{0x1d165, 0x1d169}, {0x1d16d, 0x1d172}, + {0x1d17b, 0x1d182}, {0x1d185, 0x1d18b}, {0x1d1aa, 0x1d1ad}, + {0xe0100, 0xe01ef} }; +static xmlChRangeGroup xmlMG = {113,6,xmlMS,xmlML}; + +static const xmlChSRange xmlMcS[] = {{0x903, 0x903}, {0x93e, 0x940}, + {0x949, 0x94c}, {0x982, 0x983}, {0x9be, 0x9c0}, {0x9c7, 0x9c8}, + {0x9cb, 0x9cc}, {0x9d7, 0x9d7}, {0xa03, 0xa03}, {0xa3e, 0xa40}, + {0xa83, 0xa83}, {0xabe, 0xac0}, {0xac9, 0xac9}, {0xacb, 0xacc}, + {0xb02, 0xb03}, {0xb3e, 0xb3e}, {0xb40, 0xb40}, {0xb47, 0xb48}, + {0xb4b, 0xb4c}, {0xb57, 0xb57}, {0xbbe, 0xbbf}, {0xbc1, 0xbc2}, + {0xbc6, 0xbc8}, {0xbca, 0xbcc}, {0xbd7, 0xbd7}, {0xc01, 0xc03}, + {0xc41, 0xc44}, {0xc82, 0xc83}, {0xcbe, 0xcbe}, {0xcc0, 0xcc4}, + {0xcc7, 0xcc8}, {0xcca, 0xccb}, {0xcd5, 0xcd6}, {0xd02, 0xd03}, + {0xd3e, 0xd40}, {0xd46, 0xd48}, {0xd4a, 0xd4c}, {0xd57, 0xd57}, + {0xd82, 0xd83}, {0xdcf, 0xdd1}, {0xdd8, 0xddf}, {0xdf2, 0xdf3}, + {0xf3e, 0xf3f}, {0xf7f, 0xf7f}, {0x102c, 0x102c}, {0x1031, 0x1031}, + {0x1038, 0x1038}, {0x1056, 0x1057}, {0x17b6, 0x17b6}, {0x17be, 0x17c5}, + {0x17c7, 0x17c8}, {0x1923, 0x1926}, {0x1929, 0x192b}, {0x1930, 0x1931}, + {0x1933, 0x1938} }; +static const xmlChLRange xmlMcL[] = {{0x1d165, 0x1d166}, {0x1d16d, 0x1d172} }; +static xmlChRangeGroup xmlMcG = {55,2,xmlMcS,xmlMcL}; + +static const xmlChSRange xmlMnS[] = {{0x300, 0x357}, {0x35d, 0x36f}, + {0x483, 0x486}, {0x591, 0x5a1}, {0x5a3, 0x5b9}, {0x5bb, 0x5bd}, + {0x5bf, 0x5bf}, {0x5c1, 0x5c2}, {0x5c4, 0x5c4}, {0x610, 0x615}, + {0x64b, 0x658}, {0x670, 0x670}, {0x6d6, 0x6dc}, {0x6df, 0x6e4}, + {0x6e7, 0x6e8}, {0x6ea, 0x6ed}, {0x711, 0x711}, {0x730, 0x74a}, + {0x7a6, 0x7b0}, {0x901, 0x902}, {0x93c, 0x93c}, {0x941, 0x948}, + {0x94d, 0x94d}, {0x951, 0x954}, {0x962, 0x963}, {0x981, 0x981}, + {0x9bc, 0x9bc}, {0x9c1, 0x9c4}, {0x9cd, 0x9cd}, {0x9e2, 0x9e3}, + {0xa01, 0xa02}, {0xa3c, 0xa3c}, {0xa41, 0xa42}, {0xa47, 0xa48}, + {0xa4b, 0xa4d}, {0xa70, 0xa71}, {0xa81, 0xa82}, {0xabc, 0xabc}, + {0xac1, 0xac5}, {0xac7, 0xac8}, {0xacd, 0xacd}, {0xae2, 0xae3}, + {0xb01, 0xb01}, {0xb3c, 0xb3c}, {0xb3f, 0xb3f}, {0xb41, 0xb43}, + {0xb4d, 0xb4d}, {0xb56, 0xb56}, {0xb82, 0xb82}, {0xbc0, 0xbc0}, + {0xbcd, 0xbcd}, {0xc3e, 0xc40}, {0xc46, 0xc48}, {0xc4a, 0xc4d}, + {0xc55, 0xc56}, {0xcbc, 0xcbc}, {0xcbf, 0xcbf}, {0xcc6, 0xcc6}, + {0xccc, 0xccd}, {0xd41, 0xd43}, {0xd4d, 0xd4d}, {0xdca, 0xdca}, + {0xdd2, 0xdd4}, {0xdd6, 0xdd6}, {0xe31, 0xe31}, {0xe34, 0xe3a}, + {0xe47, 0xe4e}, {0xeb1, 0xeb1}, {0xeb4, 0xeb9}, {0xebb, 0xebc}, + {0xec8, 0xecd}, {0xf18, 0xf19}, {0xf35, 0xf35}, {0xf37, 0xf37}, + {0xf39, 0xf39}, {0xf71, 0xf7e}, {0xf80, 0xf84}, {0xf86, 0xf87}, + {0xf90, 0xf97}, {0xf99, 0xfbc}, {0xfc6, 0xfc6}, {0x102d, 0x1030}, + {0x1032, 0x1032}, {0x1036, 0x1037}, {0x1039, 0x1039}, {0x1058, 0x1059}, + {0x1712, 0x1714}, {0x1732, 0x1734}, {0x1752, 0x1753}, {0x1772, 0x1773}, + {0x17b7, 0x17bd}, {0x17c6, 0x17c6}, {0x17c9, 0x17d3}, {0x17dd, 0x17dd}, + {0x180b, 0x180d}, {0x18a9, 0x18a9}, {0x1920, 0x1922}, {0x1927, 0x1928}, + {0x1932, 0x1932}, {0x1939, 0x193b}, {0x20d0, 0x20dc}, {0x20e1, 0x20e1}, + {0x20e5, 0x20ea}, {0x302a, 0x302f}, {0x3099, 0x309a}, {0xfb1e, 0xfb1e}, + {0xfe00, 0xfe0f}, {0xfe20, 0xfe23} }; +static const xmlChLRange xmlMnL[] = {{0x1d167, 0x1d169}, {0x1d17b, 0x1d182}, + {0x1d185, 0x1d18b}, {0x1d1aa, 0x1d1ad}, {0xe0100, 0xe01ef} }; +static xmlChRangeGroup xmlMnG = {108,5,xmlMnS,xmlMnL}; + +static const xmlChSRange xmlNS[] = {{0x30, 0x39}, {0xb2, 0xb3}, + {0xb9, 0xb9}, {0xbc, 0xbe}, {0x660, 0x669}, {0x6f0, 0x6f9}, + {0x966, 0x96f}, {0x9e6, 0x9ef}, {0x9f4, 0x9f9}, {0xa66, 0xa6f}, + {0xae6, 0xaef}, {0xb66, 0xb6f}, {0xbe7, 0xbf2}, {0xc66, 0xc6f}, + {0xce6, 0xcef}, {0xd66, 0xd6f}, {0xe50, 0xe59}, {0xed0, 0xed9}, + {0xf20, 0xf33}, {0x1040, 0x1049}, {0x1369, 0x137c}, {0x16ee, 0x16f0}, + {0x17e0, 0x17e9}, {0x17f0, 0x17f9}, {0x1810, 0x1819}, {0x1946, 0x194f}, + {0x2070, 0x2070}, {0x2074, 0x2079}, {0x2080, 0x2089}, {0x2153, 0x2183}, + {0x2460, 0x249b}, {0x24ea, 0x24ff}, {0x2776, 0x2793}, {0x3007, 0x3007}, + {0x3021, 0x3029}, {0x3038, 0x303a}, {0x3192, 0x3195}, {0x3220, 0x3229}, + {0x3251, 0x325f}, {0x3280, 0x3289}, {0x32b1, 0x32bf}, {0xff10, 0xff19} }; +static const xmlChLRange xmlNL[] = {{0x10107, 0x10133}, {0x10320, 0x10323}, + {0x1034a, 0x1034a}, {0x104a0, 0x104a9}, {0x1d7ce, 0x1d7ff} }; +static xmlChRangeGroup xmlNG = {42,5,xmlNS,xmlNL}; + +static const xmlChSRange xmlNdS[] = {{0x30, 0x39}, {0x660, 0x669}, + {0x6f0, 0x6f9}, {0x966, 0x96f}, {0x9e6, 0x9ef}, {0xa66, 0xa6f}, + {0xae6, 0xaef}, {0xb66, 0xb6f}, {0xbe7, 0xbef}, {0xc66, 0xc6f}, + {0xce6, 0xcef}, {0xd66, 0xd6f}, {0xe50, 0xe59}, {0xed0, 0xed9}, + {0xf20, 0xf29}, {0x1040, 0x1049}, {0x1369, 0x1371}, {0x17e0, 0x17e9}, + {0x1810, 0x1819}, {0x1946, 0x194f}, {0xff10, 0xff19} }; +static const xmlChLRange xmlNdL[] = {{0x104a0, 0x104a9}, {0x1d7ce, 0x1d7ff} }; +static xmlChRangeGroup xmlNdG = {21,2,xmlNdS,xmlNdL}; + +static const xmlChSRange xmlNoS[] = {{0xb2, 0xb3}, {0xb9, 0xb9}, + {0xbc, 0xbe}, {0x9f4, 0x9f9}, {0xbf0, 0xbf2}, {0xf2a, 0xf33}, + {0x1372, 0x137c}, {0x17f0, 0x17f9}, {0x2070, 0x2070}, {0x2074, 0x2079}, + {0x2080, 0x2089}, {0x2153, 0x215f}, {0x2460, 0x249b}, {0x24ea, 0x24ff}, + {0x2776, 0x2793}, {0x3192, 0x3195}, {0x3220, 0x3229}, {0x3251, 0x325f}, + {0x3280, 0x3289}, {0x32b1, 0x32bf} }; +static const xmlChLRange xmlNoL[] = {{0x10107, 0x10133}, {0x10320, 0x10323} }; +static xmlChRangeGroup xmlNoG = {20,2,xmlNoS,xmlNoL}; + +static const xmlChSRange xmlPS[] = {{0x21, 0x23}, {0x25, 0x2a}, + {0x2c, 0x2f}, {0x3a, 0x3b}, {0x3f, 0x40}, {0x5b, 0x5d}, {0x5f, 0x5f}, + {0x7b, 0x7b}, {0x7d, 0x7d}, {0xa1, 0xa1}, {0xab, 0xab}, {0xb7, 0xb7}, + {0xbb, 0xbb}, {0xbf, 0xbf}, {0x37e, 0x37e}, {0x387, 0x387}, + {0x55a, 0x55f}, {0x589, 0x58a}, {0x5be, 0x5be}, {0x5c0, 0x5c0}, + {0x5c3, 0x5c3}, {0x5f3, 0x5f4}, {0x60c, 0x60d}, {0x61b, 0x61b}, + {0x61f, 0x61f}, {0x66a, 0x66d}, {0x6d4, 0x6d4}, {0x700, 0x70d}, + {0x964, 0x965}, {0x970, 0x970}, {0xdf4, 0xdf4}, {0xe4f, 0xe4f}, + {0xe5a, 0xe5b}, {0xf04, 0xf12}, {0xf3a, 0xf3d}, {0xf85, 0xf85}, + {0x104a, 0x104f}, {0x10fb, 0x10fb}, {0x1361, 0x1368}, {0x166d, 0x166e}, + {0x169b, 0x169c}, {0x16eb, 0x16ed}, {0x1735, 0x1736}, {0x17d4, 0x17d6}, + {0x17d8, 0x17da}, {0x1800, 0x180a}, {0x1944, 0x1945}, {0x2010, 0x2027}, + {0x2030, 0x2043}, {0x2045, 0x2051}, {0x2053, 0x2054}, {0x2057, 0x2057}, + {0x207d, 0x207e}, {0x208d, 0x208e}, {0x2329, 0x232a}, {0x23b4, 0x23b6}, + {0x2768, 0x2775}, {0x27e6, 0x27eb}, {0x2983, 0x2998}, {0x29d8, 0x29db}, + {0x29fc, 0x29fd}, {0x3001, 0x3003}, {0x3008, 0x3011}, {0x3014, 0x301f}, + {0x3030, 0x3030}, {0x303d, 0x303d}, {0x30a0, 0x30a0}, {0x30fb, 0x30fb}, + {0xfd3e, 0xfd3f}, {0xfe30, 0xfe52}, {0xfe54, 0xfe61}, {0xfe63, 0xfe63}, + {0xfe68, 0xfe68}, {0xfe6a, 0xfe6b}, {0xff01, 0xff03}, {0xff05, 0xff0a}, + {0xff0c, 0xff0f}, {0xff1a, 0xff1b}, {0xff1f, 0xff20}, {0xff3b, 0xff3d}, + {0xff3f, 0xff3f}, {0xff5b, 0xff5b}, {0xff5d, 0xff5d}, {0xff5f, 0xff65} }; +static const xmlChLRange xmlPL[] = {{0x10100, 0x10101}, {0x1039f, 0x1039f} }; +static xmlChRangeGroup xmlPG = {84,2,xmlPS,xmlPL}; + +static const xmlChSRange xmlPdS[] = {{0x2d, 0x2d}, {0x58a, 0x58a}, + {0x1806, 0x1806}, {0x2010, 0x2015}, {0x301c, 0x301c}, {0x3030, 0x3030}, + {0x30a0, 0x30a0}, {0xfe31, 0xfe32}, {0xfe58, 0xfe58}, {0xfe63, 0xfe63}, + {0xff0d, 0xff0d} }; +static xmlChRangeGroup xmlPdG = {11,0,xmlPdS,NULL}; + +static const xmlChSRange xmlPeS[] = {{0x29, 0x29}, {0x5d, 0x5d}, + {0x7d, 0x7d}, {0xf3b, 0xf3b}, {0xf3d, 0xf3d}, {0x169c, 0x169c}, + {0x2046, 0x2046}, {0x207e, 0x207e}, {0x208e, 0x208e}, {0x232a, 0x232a}, + {0x23b5, 0x23b5}, {0x2769, 0x2769}, {0x276b, 0x276b}, {0x276d, 0x276d}, + {0x276f, 0x276f}, {0x2771, 0x2771}, {0x2773, 0x2773}, {0x2775, 0x2775}, + {0x27e7, 0x27e7}, {0x27e9, 0x27e9}, {0x27eb, 0x27eb}, {0x2984, 0x2984}, + {0x2986, 0x2986}, {0x2988, 0x2988}, {0x298a, 0x298a}, {0x298c, 0x298c}, + {0x298e, 0x298e}, {0x2990, 0x2990}, {0x2992, 0x2992}, {0x2994, 0x2994}, + {0x2996, 0x2996}, {0x2998, 0x2998}, {0x29d9, 0x29d9}, {0x29db, 0x29db}, + {0x29fd, 0x29fd}, {0x3009, 0x3009}, {0x300b, 0x300b}, {0x300d, 0x300d}, + {0x300f, 0x300f}, {0x3011, 0x3011}, {0x3015, 0x3015}, {0x3017, 0x3017}, + {0x3019, 0x3019}, {0x301b, 0x301b}, {0x301e, 0x301f}, {0xfd3f, 0xfd3f}, + {0xfe36, 0xfe36}, {0xfe38, 0xfe38}, {0xfe3a, 0xfe3a}, {0xfe3c, 0xfe3c}, + {0xfe3e, 0xfe3e}, {0xfe40, 0xfe40}, {0xfe42, 0xfe42}, {0xfe44, 0xfe44}, + {0xfe48, 0xfe48}, {0xfe5a, 0xfe5a}, {0xfe5c, 0xfe5c}, {0xfe5e, 0xfe5e}, + {0xff09, 0xff09}, {0xff3d, 0xff3d}, {0xff5d, 0xff5d}, {0xff60, 0xff60}, + {0xff63, 0xff63} }; +static xmlChRangeGroup xmlPeG = {63,0,xmlPeS,NULL}; + +static const xmlChSRange xmlPoS[] = {{0x21, 0x23}, {0x25, 0x27}, + {0x2a, 0x2a}, {0x2c, 0x2c}, {0x2e, 0x2f}, {0x3a, 0x3b}, {0x3f, 0x40}, + {0x5c, 0x5c}, {0xa1, 0xa1}, {0xb7, 0xb7}, {0xbf, 0xbf}, {0x37e, 0x37e}, + {0x387, 0x387}, {0x55a, 0x55f}, {0x589, 0x589}, {0x5be, 0x5be}, + {0x5c0, 0x5c0}, {0x5c3, 0x5c3}, {0x5f3, 0x5f4}, {0x60c, 0x60d}, + {0x61b, 0x61b}, {0x61f, 0x61f}, {0x66a, 0x66d}, {0x6d4, 0x6d4}, + {0x700, 0x70d}, {0x964, 0x965}, {0x970, 0x970}, {0xdf4, 0xdf4}, + {0xe4f, 0xe4f}, {0xe5a, 0xe5b}, {0xf04, 0xf12}, {0xf85, 0xf85}, + {0x104a, 0x104f}, {0x10fb, 0x10fb}, {0x1361, 0x1368}, {0x166d, 0x166e}, + {0x16eb, 0x16ed}, {0x1735, 0x1736}, {0x17d4, 0x17d6}, {0x17d8, 0x17da}, + {0x1800, 0x1805}, {0x1807, 0x180a}, {0x1944, 0x1945}, {0x2016, 0x2017}, + {0x2020, 0x2027}, {0x2030, 0x2038}, {0x203b, 0x203e}, {0x2041, 0x2043}, + {0x2047, 0x2051}, {0x2053, 0x2053}, {0x2057, 0x2057}, {0x23b6, 0x23b6}, + {0x3001, 0x3003}, {0x303d, 0x303d}, {0xfe30, 0xfe30}, {0xfe45, 0xfe46}, + {0xfe49, 0xfe4c}, {0xfe50, 0xfe52}, {0xfe54, 0xfe57}, {0xfe5f, 0xfe61}, + {0xfe68, 0xfe68}, {0xfe6a, 0xfe6b}, {0xff01, 0xff03}, {0xff05, 0xff07}, + {0xff0a, 0xff0a}, {0xff0c, 0xff0c}, {0xff0e, 0xff0f}, {0xff1a, 0xff1b}, + {0xff1f, 0xff20}, {0xff3c, 0xff3c}, {0xff61, 0xff61}, {0xff64, 0xff64} }; +static const xmlChLRange xmlPoL[] = {{0x10100, 0x10101}, {0x1039f, 0x1039f} }; +static xmlChRangeGroup xmlPoG = {72,2,xmlPoS,xmlPoL}; + +static const xmlChSRange xmlPsS[] = {{0x28, 0x28}, {0x5b, 0x5b}, + {0x7b, 0x7b}, {0xf3a, 0xf3a}, {0xf3c, 0xf3c}, {0x169b, 0x169b}, + {0x201a, 0x201a}, {0x201e, 0x201e}, {0x2045, 0x2045}, {0x207d, 0x207d}, + {0x208d, 0x208d}, {0x2329, 0x2329}, {0x23b4, 0x23b4}, {0x2768, 0x2768}, + {0x276a, 0x276a}, {0x276c, 0x276c}, {0x276e, 0x276e}, {0x2770, 0x2770}, + {0x2772, 0x2772}, {0x2774, 0x2774}, {0x27e6, 0x27e6}, {0x27e8, 0x27e8}, + {0x27ea, 0x27ea}, {0x2983, 0x2983}, {0x2985, 0x2985}, {0x2987, 0x2987}, + {0x2989, 0x2989}, {0x298b, 0x298b}, {0x298d, 0x298d}, {0x298f, 0x298f}, + {0x2991, 0x2991}, {0x2993, 0x2993}, {0x2995, 0x2995}, {0x2997, 0x2997}, + {0x29d8, 0x29d8}, {0x29da, 0x29da}, {0x29fc, 0x29fc}, {0x3008, 0x3008}, + {0x300a, 0x300a}, {0x300c, 0x300c}, {0x300e, 0x300e}, {0x3010, 0x3010}, + {0x3014, 0x3014}, {0x3016, 0x3016}, {0x3018, 0x3018}, {0x301a, 0x301a}, + {0x301d, 0x301d}, {0xfd3e, 0xfd3e}, {0xfe35, 0xfe35}, {0xfe37, 0xfe37}, + {0xfe39, 0xfe39}, {0xfe3b, 0xfe3b}, {0xfe3d, 0xfe3d}, {0xfe3f, 0xfe3f}, + {0xfe41, 0xfe41}, {0xfe43, 0xfe43}, {0xfe47, 0xfe47}, {0xfe59, 0xfe59}, + {0xfe5b, 0xfe5b}, {0xfe5d, 0xfe5d}, {0xff08, 0xff08}, {0xff3b, 0xff3b}, + {0xff5b, 0xff5b}, {0xff5f, 0xff5f}, {0xff62, 0xff62} }; +static xmlChRangeGroup xmlPsG = {65,0,xmlPsS,NULL}; + +static const xmlChSRange xmlSS[] = {{0x24, 0x24}, {0x2b, 0x2b}, + {0x3c, 0x3e}, {0x5e, 0x5e}, {0x60, 0x60}, {0x7c, 0x7c}, {0x7e, 0x7e}, + {0xa2, 0xa9}, {0xac, 0xac}, {0xae, 0xb1}, {0xb4, 0xb4}, {0xb6, 0xb6}, + {0xb8, 0xb8}, {0xd7, 0xd7}, {0xf7, 0xf7}, {0x2c2, 0x2c5}, + {0x2d2, 0x2df}, {0x2e5, 0x2ed}, {0x2ef, 0x2ff}, {0x374, 0x375}, + {0x384, 0x385}, {0x3f6, 0x3f6}, {0x482, 0x482}, {0x60e, 0x60f}, + {0x6e9, 0x6e9}, {0x6fd, 0x6fe}, {0x9f2, 0x9f3}, {0x9fa, 0x9fa}, + {0xaf1, 0xaf1}, {0xb70, 0xb70}, {0xbf3, 0xbfa}, {0xe3f, 0xe3f}, + {0xf01, 0xf03}, {0xf13, 0xf17}, {0xf1a, 0xf1f}, {0xf34, 0xf34}, + {0xf36, 0xf36}, {0xf38, 0xf38}, {0xfbe, 0xfc5}, {0xfc7, 0xfcc}, + {0xfcf, 0xfcf}, {0x17db, 0x17db}, {0x1940, 0x1940}, {0x19e0, 0x19ff}, + {0x1fbd, 0x1fbd}, {0x1fbf, 0x1fc1}, {0x1fcd, 0x1fcf}, {0x1fdd, 0x1fdf}, + {0x1fed, 0x1fef}, {0x1ffd, 0x1ffe}, {0x2044, 0x2044}, {0x2052, 0x2052}, + {0x207a, 0x207c}, {0x208a, 0x208c}, {0x20a0, 0x20b1}, {0x2100, 0x2101}, + {0x2103, 0x2106}, {0x2108, 0x2109}, {0x2114, 0x2114}, {0x2116, 0x2118}, + {0x211e, 0x2123}, {0x2125, 0x2125}, {0x2127, 0x2127}, {0x2129, 0x2129}, + {0x212e, 0x212e}, {0x2132, 0x2132}, {0x213a, 0x213b}, {0x2140, 0x2144}, + {0x214a, 0x214b}, {0x2190, 0x2328}, {0x232b, 0x23b3}, {0x23b7, 0x23d0}, + {0x2400, 0x2426}, {0x2440, 0x244a}, {0x249c, 0x24e9}, {0x2500, 0x2617}, + {0x2619, 0x267d}, {0x2680, 0x2691}, {0x26a0, 0x26a1}, {0x2701, 0x2704}, + {0x2706, 0x2709}, {0x270c, 0x2727}, {0x2729, 0x274b}, {0x274d, 0x274d}, + {0x274f, 0x2752}, {0x2756, 0x2756}, {0x2758, 0x275e}, {0x2761, 0x2767}, + {0x2794, 0x2794}, {0x2798, 0x27af}, {0x27b1, 0x27be}, {0x27d0, 0x27e5}, + {0x27f0, 0x2982}, {0x2999, 0x29d7}, {0x29dc, 0x29fb}, {0x29fe, 0x2b0d}, + {0x2e80, 0x2e99}, {0x2e9b, 0x2ef3}, {0x2f00, 0x2fd5}, {0x2ff0, 0x2ffb}, + {0x3004, 0x3004}, {0x3012, 0x3013}, {0x3020, 0x3020}, {0x3036, 0x3037}, + {0x303e, 0x303f}, {0x309b, 0x309c}, {0x3190, 0x3191}, {0x3196, 0x319f}, + {0x3200, 0x321e}, {0x322a, 0x3243}, {0x3250, 0x3250}, {0x3260, 0x327d}, + {0x327f, 0x327f}, {0x328a, 0x32b0}, {0x32c0, 0x32fe}, {0x3300, 0x33ff}, + {0x4dc0, 0x4dff}, {0xa490, 0xa4c6}, {0xfb29, 0xfb29}, {0xfdfc, 0xfdfd}, + {0xfe62, 0xfe62}, {0xfe64, 0xfe66}, {0xfe69, 0xfe69}, {0xff04, 0xff04}, + {0xff0b, 0xff0b}, {0xff1c, 0xff1e}, {0xff3e, 0xff3e}, {0xff40, 0xff40}, + {0xff5c, 0xff5c}, {0xff5e, 0xff5e}, {0xffe0, 0xffe6}, {0xffe8, 0xffee}, + {0xfffc, 0xfffd} }; +static const xmlChLRange xmlSL[] = {{0x10102, 0x10102}, {0x10137, 0x1013f}, + {0x1d000, 0x1d0f5}, {0x1d100, 0x1d126}, {0x1d12a, 0x1d164}, + {0x1d16a, 0x1d16c}, {0x1d183, 0x1d184}, {0x1d18c, 0x1d1a9}, + {0x1d1ae, 0x1d1dd}, {0x1d300, 0x1d356}, {0x1d6c1, 0x1d6c1}, + {0x1d6db, 0x1d6db}, {0x1d6fb, 0x1d6fb}, {0x1d715, 0x1d715}, + {0x1d735, 0x1d735}, {0x1d74f, 0x1d74f}, {0x1d76f, 0x1d76f}, + {0x1d789, 0x1d789}, {0x1d7a9, 0x1d7a9}, {0x1d7c3, 0x1d7c3} }; +static xmlChRangeGroup xmlSG = {133,20,xmlSS,xmlSL}; + +static const xmlChSRange xmlScS[] = {{0x24, 0x24}, {0xa2, 0xa5}, + {0x9f2, 0x9f3}, {0xaf1, 0xaf1}, {0xbf9, 0xbf9}, {0xe3f, 0xe3f}, + {0x17db, 0x17db}, {0x20a0, 0x20b1}, {0xfdfc, 0xfdfc}, {0xfe69, 0xfe69}, + {0xff04, 0xff04}, {0xffe0, 0xffe1}, {0xffe5, 0xffe6} }; +static xmlChRangeGroup xmlScG = {13,0,xmlScS,NULL}; + +static const xmlChSRange xmlSkS[] = {{0x5e, 0x5e}, {0x60, 0x60}, + {0xa8, 0xa8}, {0xaf, 0xaf}, {0xb4, 0xb4}, {0xb8, 0xb8}, {0x2c2, 0x2c5}, + {0x2d2, 0x2df}, {0x2e5, 0x2ed}, {0x2ef, 0x2ff}, {0x374, 0x375}, + {0x384, 0x385}, {0x1fbd, 0x1fbd}, {0x1fbf, 0x1fc1}, {0x1fcd, 0x1fcf}, + {0x1fdd, 0x1fdf}, {0x1fed, 0x1fef}, {0x1ffd, 0x1ffe}, {0x309b, 0x309c}, + {0xff3e, 0xff3e}, {0xff40, 0xff40}, {0xffe3, 0xffe3} }; +static xmlChRangeGroup xmlSkG = {22,0,xmlSkS,NULL}; + +static const xmlChSRange xmlSmS[] = {{0x2b, 0x2b}, {0x3c, 0x3e}, + {0x7c, 0x7c}, {0x7e, 0x7e}, {0xac, 0xac}, {0xb1, 0xb1}, {0xd7, 0xd7}, + {0xf7, 0xf7}, {0x3f6, 0x3f6}, {0x2044, 0x2044}, {0x2052, 0x2052}, + {0x207a, 0x207c}, {0x208a, 0x208c}, {0x2140, 0x2144}, {0x214b, 0x214b}, + {0x2190, 0x2194}, {0x219a, 0x219b}, {0x21a0, 0x21a0}, {0x21a3, 0x21a3}, + {0x21a6, 0x21a6}, {0x21ae, 0x21ae}, {0x21ce, 0x21cf}, {0x21d2, 0x21d2}, + {0x21d4, 0x21d4}, {0x21f4, 0x22ff}, {0x2308, 0x230b}, {0x2320, 0x2321}, + {0x237c, 0x237c}, {0x239b, 0x23b3}, {0x25b7, 0x25b7}, {0x25c1, 0x25c1}, + {0x25f8, 0x25ff}, {0x266f, 0x266f}, {0x27d0, 0x27e5}, {0x27f0, 0x27ff}, + {0x2900, 0x2982}, {0x2999, 0x29d7}, {0x29dc, 0x29fb}, {0x29fe, 0x2aff}, + {0xfb29, 0xfb29}, {0xfe62, 0xfe62}, {0xfe64, 0xfe66}, {0xff0b, 0xff0b}, + {0xff1c, 0xff1e}, {0xff5c, 0xff5c}, {0xff5e, 0xff5e}, {0xffe2, 0xffe2}, + {0xffe9, 0xffec} }; +static const xmlChLRange xmlSmL[] = {{0x1d6c1, 0x1d6c1}, {0x1d6db, 0x1d6db}, + {0x1d6fb, 0x1d6fb}, {0x1d715, 0x1d715}, {0x1d735, 0x1d735}, + {0x1d74f, 0x1d74f}, {0x1d76f, 0x1d76f}, {0x1d789, 0x1d789}, + {0x1d7a9, 0x1d7a9}, {0x1d7c3, 0x1d7c3} }; +static xmlChRangeGroup xmlSmG = {48,10,xmlSmS,xmlSmL}; + +static const xmlChSRange xmlSoS[] = {{0xa6, 0xa7}, {0xa9, 0xa9}, + {0xae, 0xae}, {0xb0, 0xb0}, {0xb6, 0xb6}, {0x482, 0x482}, + {0x60e, 0x60f}, {0x6e9, 0x6e9}, {0x6fd, 0x6fe}, {0x9fa, 0x9fa}, + {0xb70, 0xb70}, {0xbf3, 0xbf8}, {0xbfa, 0xbfa}, {0xf01, 0xf03}, + {0xf13, 0xf17}, {0xf1a, 0xf1f}, {0xf34, 0xf34}, {0xf36, 0xf36}, + {0xf38, 0xf38}, {0xfbe, 0xfc5}, {0xfc7, 0xfcc}, {0xfcf, 0xfcf}, + {0x1940, 0x1940}, {0x19e0, 0x19ff}, {0x2100, 0x2101}, {0x2103, 0x2106}, + {0x2108, 0x2109}, {0x2114, 0x2114}, {0x2116, 0x2118}, {0x211e, 0x2123}, + {0x2125, 0x2125}, {0x2127, 0x2127}, {0x2129, 0x2129}, {0x212e, 0x212e}, + {0x2132, 0x2132}, {0x213a, 0x213b}, {0x214a, 0x214a}, {0x2195, 0x2199}, + {0x219c, 0x219f}, {0x21a1, 0x21a2}, {0x21a4, 0x21a5}, {0x21a7, 0x21ad}, + {0x21af, 0x21cd}, {0x21d0, 0x21d1}, {0x21d3, 0x21d3}, {0x21d5, 0x21f3}, + {0x2300, 0x2307}, {0x230c, 0x231f}, {0x2322, 0x2328}, {0x232b, 0x237b}, + {0x237d, 0x239a}, {0x23b7, 0x23d0}, {0x2400, 0x2426}, {0x2440, 0x244a}, + {0x249c, 0x24e9}, {0x2500, 0x25b6}, {0x25b8, 0x25c0}, {0x25c2, 0x25f7}, + {0x2600, 0x2617}, {0x2619, 0x266e}, {0x2670, 0x267d}, {0x2680, 0x2691}, + {0x26a0, 0x26a1}, {0x2701, 0x2704}, {0x2706, 0x2709}, {0x270c, 0x2727}, + {0x2729, 0x274b}, {0x274d, 0x274d}, {0x274f, 0x2752}, {0x2756, 0x2756}, + {0x2758, 0x275e}, {0x2761, 0x2767}, {0x2794, 0x2794}, {0x2798, 0x27af}, + {0x27b1, 0x27be}, {0x2800, 0x28ff}, {0x2b00, 0x2b0d}, {0x2e80, 0x2e99}, + {0x2e9b, 0x2ef3}, {0x2f00, 0x2fd5}, {0x2ff0, 0x2ffb}, {0x3004, 0x3004}, + {0x3012, 0x3013}, {0x3020, 0x3020}, {0x3036, 0x3037}, {0x303e, 0x303f}, + {0x3190, 0x3191}, {0x3196, 0x319f}, {0x3200, 0x321e}, {0x322a, 0x3243}, + {0x3250, 0x3250}, {0x3260, 0x327d}, {0x327f, 0x327f}, {0x328a, 0x32b0}, + {0x32c0, 0x32fe}, {0x3300, 0x33ff}, {0x4dc0, 0x4dff}, {0xa490, 0xa4c6}, + {0xfdfd, 0xfdfd}, {0xffe4, 0xffe4}, {0xffe8, 0xffe8}, {0xffed, 0xffee}, + {0xfffc, 0xfffd} }; +static const xmlChLRange xmlSoL[] = {{0x10102, 0x10102}, {0x10137, 0x1013f}, + {0x1d000, 0x1d0f5}, {0x1d100, 0x1d126}, {0x1d12a, 0x1d164}, + {0x1d16a, 0x1d16c}, {0x1d183, 0x1d184}, {0x1d18c, 0x1d1a9}, + {0x1d1ae, 0x1d1dd}, {0x1d300, 0x1d356} }; +static xmlChRangeGroup xmlSoG = {103,10,xmlSoS,xmlSoL}; + +static const xmlChSRange xmlZS[] = {{0x20, 0x20}, {0xa0, 0xa0}, + {0x1680, 0x1680}, {0x180e, 0x180e}, {0x2000, 0x200a}, {0x2028, 0x2029}, + {0x202f, 0x202f}, {0x205f, 0x205f}, {0x3000, 0x3000} }; +static xmlChRangeGroup xmlZG = {9,0,xmlZS,NULL}; + +static xmlUnicodeNameTable xmlUnicodeBlockTbl = {xmlUnicodeBlocks, 128}; +static xmlUnicodeNameTable xmlUnicodeCatTbl = {xmlUnicodeCats, 36}; + +/** + * xmlUnicodeLookup: + * @tptr: pointer to the name table + * @name: name to be found + * + * binary table lookup for user-supplied name + * + * Returns pointer to range function if found, otherwise NULL + */ +static xmlIntFunc +*xmlUnicodeLookup(xmlUnicodeNameTable *tptr, const char *tname) { + int low, high, mid, cmp; + xmlUnicodeRange *sptr; + + if ((tptr == NULL) || (tname == NULL)) return(NULL); + + low = 0; + high = tptr->numentries - 1; + sptr = tptr->table; + while (low <= high) { + mid = (low + high) / 2; + if ((cmp=strcmp(tname, sptr[mid].rangename)) == 0) + return (sptr[mid].func); + if (cmp < 0) + high = mid - 1; + else + low = mid + 1; + } + return (NULL); +} + +/** + * xmlUCSIsAegeanNumbers: + * @code: UCS code point + * + * Check whether the character is part of AegeanNumbers UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsAegeanNumbers(int code) { + return(((code >= 0x10100) && (code <= 0x1013F))); +} + +/** + * xmlUCSIsAlphabeticPresentationForms: + * @code: UCS code point + * + * Check whether the character is part of AlphabeticPresentationForms UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsAlphabeticPresentationForms(int code) { + return(((code >= 0xFB00) && (code <= 0xFB4F))); +} + +/** + * xmlUCSIsArabic: + * @code: UCS code point + * + * Check whether the character is part of Arabic UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsArabic(int code) { + return(((code >= 0x0600) && (code <= 0x06FF))); +} + +/** + * xmlUCSIsArabicPresentationFormsA: + * @code: UCS code point + * + * Check whether the character is part of ArabicPresentationForms-A UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsArabicPresentationFormsA(int code) { + return(((code >= 0xFB50) && (code <= 0xFDFF))); +} + +/** + * xmlUCSIsArabicPresentationFormsB: + * @code: UCS code point + * + * Check whether the character is part of ArabicPresentationForms-B UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsArabicPresentationFormsB(int code) { + return(((code >= 0xFE70) && (code <= 0xFEFF))); +} + +/** + * xmlUCSIsArmenian: + * @code: UCS code point + * + * Check whether the character is part of Armenian UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsArmenian(int code) { + return(((code >= 0x0530) && (code <= 0x058F))); +} + +/** + * xmlUCSIsArrows: + * @code: UCS code point + * + * Check whether the character is part of Arrows UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsArrows(int code) { + return(((code >= 0x2190) && (code <= 0x21FF))); +} + +/** + * xmlUCSIsBasicLatin: + * @code: UCS code point + * + * Check whether the character is part of BasicLatin UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsBasicLatin(int code) { + return(((code >= 0x0000) && (code <= 0x007F))); +} + +/** + * xmlUCSIsBengali: + * @code: UCS code point + * + * Check whether the character is part of Bengali UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsBengali(int code) { + return(((code >= 0x0980) && (code <= 0x09FF))); +} + +/** + * xmlUCSIsBlockElements: + * @code: UCS code point + * + * Check whether the character is part of BlockElements UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsBlockElements(int code) { + return(((code >= 0x2580) && (code <= 0x259F))); +} + +/** + * xmlUCSIsBopomofo: + * @code: UCS code point + * + * Check whether the character is part of Bopomofo UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsBopomofo(int code) { + return(((code >= 0x3100) && (code <= 0x312F))); +} + +/** + * xmlUCSIsBopomofoExtended: + * @code: UCS code point + * + * Check whether the character is part of BopomofoExtended UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsBopomofoExtended(int code) { + return(((code >= 0x31A0) && (code <= 0x31BF))); +} + +/** + * xmlUCSIsBoxDrawing: + * @code: UCS code point + * + * Check whether the character is part of BoxDrawing UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsBoxDrawing(int code) { + return(((code >= 0x2500) && (code <= 0x257F))); +} + +/** + * xmlUCSIsBraillePatterns: + * @code: UCS code point + * + * Check whether the character is part of BraillePatterns UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsBraillePatterns(int code) { + return(((code >= 0x2800) && (code <= 0x28FF))); +} + +/** + * xmlUCSIsBuhid: + * @code: UCS code point + * + * Check whether the character is part of Buhid UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsBuhid(int code) { + return(((code >= 0x1740) && (code <= 0x175F))); +} + +/** + * xmlUCSIsByzantineMusicalSymbols: + * @code: UCS code point + * + * Check whether the character is part of ByzantineMusicalSymbols UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsByzantineMusicalSymbols(int code) { + return(((code >= 0x1D000) && (code <= 0x1D0FF))); +} + +/** + * xmlUCSIsCJKCompatibility: + * @code: UCS code point + * + * Check whether the character is part of CJKCompatibility UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsCJKCompatibility(int code) { + return(((code >= 0x3300) && (code <= 0x33FF))); +} + +/** + * xmlUCSIsCJKCompatibilityForms: + * @code: UCS code point + * + * Check whether the character is part of CJKCompatibilityForms UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsCJKCompatibilityForms(int code) { + return(((code >= 0xFE30) && (code <= 0xFE4F))); +} + +/** + * xmlUCSIsCJKCompatibilityIdeographs: + * @code: UCS code point + * + * Check whether the character is part of CJKCompatibilityIdeographs UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsCJKCompatibilityIdeographs(int code) { + return(((code >= 0xF900) && (code <= 0xFAFF))); +} + +/** + * xmlUCSIsCJKCompatibilityIdeographsSupplement: + * @code: UCS code point + * + * Check whether the character is part of CJKCompatibilityIdeographsSupplement UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsCJKCompatibilityIdeographsSupplement(int code) { + return(((code >= 0x2F800) && (code <= 0x2FA1F))); +} + +/** + * xmlUCSIsCJKRadicalsSupplement: + * @code: UCS code point + * + * Check whether the character is part of CJKRadicalsSupplement UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsCJKRadicalsSupplement(int code) { + return(((code >= 0x2E80) && (code <= 0x2EFF))); +} + +/** + * xmlUCSIsCJKSymbolsandPunctuation: + * @code: UCS code point + * + * Check whether the character is part of CJKSymbolsandPunctuation UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsCJKSymbolsandPunctuation(int code) { + return(((code >= 0x3000) && (code <= 0x303F))); +} + +/** + * xmlUCSIsCJKUnifiedIdeographs: + * @code: UCS code point + * + * Check whether the character is part of CJKUnifiedIdeographs UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsCJKUnifiedIdeographs(int code) { + return(((code >= 0x4E00) && (code <= 0x9FFF))); +} + +/** + * xmlUCSIsCJKUnifiedIdeographsExtensionA: + * @code: UCS code point + * + * Check whether the character is part of CJKUnifiedIdeographsExtensionA UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsCJKUnifiedIdeographsExtensionA(int code) { + return(((code >= 0x3400) && (code <= 0x4DBF))); +} + +/** + * xmlUCSIsCJKUnifiedIdeographsExtensionB: + * @code: UCS code point + * + * Check whether the character is part of CJKUnifiedIdeographsExtensionB UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsCJKUnifiedIdeographsExtensionB(int code) { + return(((code >= 0x20000) && (code <= 0x2A6DF))); +} + +/** + * xmlUCSIsCherokee: + * @code: UCS code point + * + * Check whether the character is part of Cherokee UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsCherokee(int code) { + return(((code >= 0x13A0) && (code <= 0x13FF))); +} + +/** + * xmlUCSIsCombiningDiacriticalMarks: + * @code: UCS code point + * + * Check whether the character is part of CombiningDiacriticalMarks UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsCombiningDiacriticalMarks(int code) { + return(((code >= 0x0300) && (code <= 0x036F))); +} + +/** + * xmlUCSIsCombiningDiacriticalMarksforSymbols: + * @code: UCS code point + * + * Check whether the character is part of CombiningDiacriticalMarksforSymbols UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsCombiningDiacriticalMarksforSymbols(int code) { + return(((code >= 0x20D0) && (code <= 0x20FF))); +} + +/** + * xmlUCSIsCombiningHalfMarks: + * @code: UCS code point + * + * Check whether the character is part of CombiningHalfMarks UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsCombiningHalfMarks(int code) { + return(((code >= 0xFE20) && (code <= 0xFE2F))); +} + +/** + * xmlUCSIsCombiningMarksforSymbols: + * @code: UCS code point + * + * Check whether the character is part of CombiningMarksforSymbols UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsCombiningMarksforSymbols(int code) { + return(((code >= 0x20D0) && (code <= 0x20FF))); +} + +/** + * xmlUCSIsControlPictures: + * @code: UCS code point + * + * Check whether the character is part of ControlPictures UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsControlPictures(int code) { + return(((code >= 0x2400) && (code <= 0x243F))); +} + +/** + * xmlUCSIsCurrencySymbols: + * @code: UCS code point + * + * Check whether the character is part of CurrencySymbols UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsCurrencySymbols(int code) { + return(((code >= 0x20A0) && (code <= 0x20CF))); +} + +/** + * xmlUCSIsCypriotSyllabary: + * @code: UCS code point + * + * Check whether the character is part of CypriotSyllabary UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsCypriotSyllabary(int code) { + return(((code >= 0x10800) && (code <= 0x1083F))); +} + +/** + * xmlUCSIsCyrillic: + * @code: UCS code point + * + * Check whether the character is part of Cyrillic UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsCyrillic(int code) { + return(((code >= 0x0400) && (code <= 0x04FF))); +} + +/** + * xmlUCSIsCyrillicSupplement: + * @code: UCS code point + * + * Check whether the character is part of CyrillicSupplement UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsCyrillicSupplement(int code) { + return(((code >= 0x0500) && (code <= 0x052F))); +} + +/** + * xmlUCSIsDeseret: + * @code: UCS code point + * + * Check whether the character is part of Deseret UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsDeseret(int code) { + return(((code >= 0x10400) && (code <= 0x1044F))); +} + +/** + * xmlUCSIsDevanagari: + * @code: UCS code point + * + * Check whether the character is part of Devanagari UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsDevanagari(int code) { + return(((code >= 0x0900) && (code <= 0x097F))); +} + +/** + * xmlUCSIsDingbats: + * @code: UCS code point + * + * Check whether the character is part of Dingbats UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsDingbats(int code) { + return(((code >= 0x2700) && (code <= 0x27BF))); +} + +/** + * xmlUCSIsEnclosedAlphanumerics: + * @code: UCS code point + * + * Check whether the character is part of EnclosedAlphanumerics UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsEnclosedAlphanumerics(int code) { + return(((code >= 0x2460) && (code <= 0x24FF))); +} + +/** + * xmlUCSIsEnclosedCJKLettersandMonths: + * @code: UCS code point + * + * Check whether the character is part of EnclosedCJKLettersandMonths UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsEnclosedCJKLettersandMonths(int code) { + return(((code >= 0x3200) && (code <= 0x32FF))); +} + +/** + * xmlUCSIsEthiopic: + * @code: UCS code point + * + * Check whether the character is part of Ethiopic UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsEthiopic(int code) { + return(((code >= 0x1200) && (code <= 0x137F))); +} + +/** + * xmlUCSIsGeneralPunctuation: + * @code: UCS code point + * + * Check whether the character is part of GeneralPunctuation UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsGeneralPunctuation(int code) { + return(((code >= 0x2000) && (code <= 0x206F))); +} + +/** + * xmlUCSIsGeometricShapes: + * @code: UCS code point + * + * Check whether the character is part of GeometricShapes UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsGeometricShapes(int code) { + return(((code >= 0x25A0) && (code <= 0x25FF))); +} + +/** + * xmlUCSIsGeorgian: + * @code: UCS code point + * + * Check whether the character is part of Georgian UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsGeorgian(int code) { + return(((code >= 0x10A0) && (code <= 0x10FF))); +} + +/** + * xmlUCSIsGothic: + * @code: UCS code point + * + * Check whether the character is part of Gothic UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsGothic(int code) { + return(((code >= 0x10330) && (code <= 0x1034F))); +} + +/** + * xmlUCSIsGreek: + * @code: UCS code point + * + * Check whether the character is part of Greek UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsGreek(int code) { + return(((code >= 0x0370) && (code <= 0x03FF))); +} + +/** + * xmlUCSIsGreekExtended: + * @code: UCS code point + * + * Check whether the character is part of GreekExtended UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsGreekExtended(int code) { + return(((code >= 0x1F00) && (code <= 0x1FFF))); +} + +/** + * xmlUCSIsGreekandCoptic: + * @code: UCS code point + * + * Check whether the character is part of GreekandCoptic UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsGreekandCoptic(int code) { + return(((code >= 0x0370) && (code <= 0x03FF))); +} + +/** + * xmlUCSIsGujarati: + * @code: UCS code point + * + * Check whether the character is part of Gujarati UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsGujarati(int code) { + return(((code >= 0x0A80) && (code <= 0x0AFF))); +} + +/** + * xmlUCSIsGurmukhi: + * @code: UCS code point + * + * Check whether the character is part of Gurmukhi UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsGurmukhi(int code) { + return(((code >= 0x0A00) && (code <= 0x0A7F))); +} + +/** + * xmlUCSIsHalfwidthandFullwidthForms: + * @code: UCS code point + * + * Check whether the character is part of HalfwidthandFullwidthForms UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsHalfwidthandFullwidthForms(int code) { + return(((code >= 0xFF00) && (code <= 0xFFEF))); +} + +/** + * xmlUCSIsHangulCompatibilityJamo: + * @code: UCS code point + * + * Check whether the character is part of HangulCompatibilityJamo UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsHangulCompatibilityJamo(int code) { + return(((code >= 0x3130) && (code <= 0x318F))); +} + +/** + * xmlUCSIsHangulJamo: + * @code: UCS code point + * + * Check whether the character is part of HangulJamo UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsHangulJamo(int code) { + return(((code >= 0x1100) && (code <= 0x11FF))); +} + +/** + * xmlUCSIsHangulSyllables: + * @code: UCS code point + * + * Check whether the character is part of HangulSyllables UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsHangulSyllables(int code) { + return(((code >= 0xAC00) && (code <= 0xD7AF))); +} + +/** + * xmlUCSIsHanunoo: + * @code: UCS code point + * + * Check whether the character is part of Hanunoo UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsHanunoo(int code) { + return(((code >= 0x1720) && (code <= 0x173F))); +} + +/** + * xmlUCSIsHebrew: + * @code: UCS code point + * + * Check whether the character is part of Hebrew UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsHebrew(int code) { + return(((code >= 0x0590) && (code <= 0x05FF))); +} + +/** + * xmlUCSIsHighPrivateUseSurrogates: + * @code: UCS code point + * + * Check whether the character is part of HighPrivateUseSurrogates UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsHighPrivateUseSurrogates(int code) { + return(((code >= 0xDB80) && (code <= 0xDBFF))); +} + +/** + * xmlUCSIsHighSurrogates: + * @code: UCS code point + * + * Check whether the character is part of HighSurrogates UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsHighSurrogates(int code) { + return(((code >= 0xD800) && (code <= 0xDB7F))); +} + +/** + * xmlUCSIsHiragana: + * @code: UCS code point + * + * Check whether the character is part of Hiragana UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsHiragana(int code) { + return(((code >= 0x3040) && (code <= 0x309F))); +} + +/** + * xmlUCSIsIPAExtensions: + * @code: UCS code point + * + * Check whether the character is part of IPAExtensions UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsIPAExtensions(int code) { + return(((code >= 0x0250) && (code <= 0x02AF))); +} + +/** + * xmlUCSIsIdeographicDescriptionCharacters: + * @code: UCS code point + * + * Check whether the character is part of IdeographicDescriptionCharacters UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsIdeographicDescriptionCharacters(int code) { + return(((code >= 0x2FF0) && (code <= 0x2FFF))); +} + +/** + * xmlUCSIsKanbun: + * @code: UCS code point + * + * Check whether the character is part of Kanbun UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsKanbun(int code) { + return(((code >= 0x3190) && (code <= 0x319F))); +} + +/** + * xmlUCSIsKangxiRadicals: + * @code: UCS code point + * + * Check whether the character is part of KangxiRadicals UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsKangxiRadicals(int code) { + return(((code >= 0x2F00) && (code <= 0x2FDF))); +} + +/** + * xmlUCSIsKannada: + * @code: UCS code point + * + * Check whether the character is part of Kannada UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsKannada(int code) { + return(((code >= 0x0C80) && (code <= 0x0CFF))); +} + +/** + * xmlUCSIsKatakana: + * @code: UCS code point + * + * Check whether the character is part of Katakana UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsKatakana(int code) { + return(((code >= 0x30A0) && (code <= 0x30FF))); +} + +/** + * xmlUCSIsKatakanaPhoneticExtensions: + * @code: UCS code point + * + * Check whether the character is part of KatakanaPhoneticExtensions UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsKatakanaPhoneticExtensions(int code) { + return(((code >= 0x31F0) && (code <= 0x31FF))); +} + +/** + * xmlUCSIsKhmer: + * @code: UCS code point + * + * Check whether the character is part of Khmer UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsKhmer(int code) { + return(((code >= 0x1780) && (code <= 0x17FF))); +} + +/** + * xmlUCSIsKhmerSymbols: + * @code: UCS code point + * + * Check whether the character is part of KhmerSymbols UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsKhmerSymbols(int code) { + return(((code >= 0x19E0) && (code <= 0x19FF))); +} + +/** + * xmlUCSIsLao: + * @code: UCS code point + * + * Check whether the character is part of Lao UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsLao(int code) { + return(((code >= 0x0E80) && (code <= 0x0EFF))); +} + +/** + * xmlUCSIsLatin1Supplement: + * @code: UCS code point + * + * Check whether the character is part of Latin-1Supplement UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsLatin1Supplement(int code) { + return(((code >= 0x0080) && (code <= 0x00FF))); +} + +/** + * xmlUCSIsLatinExtendedA: + * @code: UCS code point + * + * Check whether the character is part of LatinExtended-A UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsLatinExtendedA(int code) { + return(((code >= 0x0100) && (code <= 0x017F))); +} + +/** + * xmlUCSIsLatinExtendedB: + * @code: UCS code point + * + * Check whether the character is part of LatinExtended-B UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsLatinExtendedB(int code) { + return(((code >= 0x0180) && (code <= 0x024F))); +} + +/** + * xmlUCSIsLatinExtendedAdditional: + * @code: UCS code point + * + * Check whether the character is part of LatinExtendedAdditional UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsLatinExtendedAdditional(int code) { + return(((code >= 0x1E00) && (code <= 0x1EFF))); +} + +/** + * xmlUCSIsLetterlikeSymbols: + * @code: UCS code point + * + * Check whether the character is part of LetterlikeSymbols UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsLetterlikeSymbols(int code) { + return(((code >= 0x2100) && (code <= 0x214F))); +} + +/** + * xmlUCSIsLimbu: + * @code: UCS code point + * + * Check whether the character is part of Limbu UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsLimbu(int code) { + return(((code >= 0x1900) && (code <= 0x194F))); +} + +/** + * xmlUCSIsLinearBIdeograms: + * @code: UCS code point + * + * Check whether the character is part of LinearBIdeograms UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsLinearBIdeograms(int code) { + return(((code >= 0x10080) && (code <= 0x100FF))); +} + +/** + * xmlUCSIsLinearBSyllabary: + * @code: UCS code point + * + * Check whether the character is part of LinearBSyllabary UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsLinearBSyllabary(int code) { + return(((code >= 0x10000) && (code <= 0x1007F))); +} + +/** + * xmlUCSIsLowSurrogates: + * @code: UCS code point + * + * Check whether the character is part of LowSurrogates UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsLowSurrogates(int code) { + return(((code >= 0xDC00) && (code <= 0xDFFF))); +} + +/** + * xmlUCSIsMalayalam: + * @code: UCS code point + * + * Check whether the character is part of Malayalam UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsMalayalam(int code) { + return(((code >= 0x0D00) && (code <= 0x0D7F))); +} + +/** + * xmlUCSIsMathematicalAlphanumericSymbols: + * @code: UCS code point + * + * Check whether the character is part of MathematicalAlphanumericSymbols UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsMathematicalAlphanumericSymbols(int code) { + return(((code >= 0x1D400) && (code <= 0x1D7FF))); +} + +/** + * xmlUCSIsMathematicalOperators: + * @code: UCS code point + * + * Check whether the character is part of MathematicalOperators UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsMathematicalOperators(int code) { + return(((code >= 0x2200) && (code <= 0x22FF))); +} + +/** + * xmlUCSIsMiscellaneousMathematicalSymbolsA: + * @code: UCS code point + * + * Check whether the character is part of MiscellaneousMathematicalSymbols-A UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsMiscellaneousMathematicalSymbolsA(int code) { + return(((code >= 0x27C0) && (code <= 0x27EF))); +} + +/** + * xmlUCSIsMiscellaneousMathematicalSymbolsB: + * @code: UCS code point + * + * Check whether the character is part of MiscellaneousMathematicalSymbols-B UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsMiscellaneousMathematicalSymbolsB(int code) { + return(((code >= 0x2980) && (code <= 0x29FF))); +} + +/** + * xmlUCSIsMiscellaneousSymbols: + * @code: UCS code point + * + * Check whether the character is part of MiscellaneousSymbols UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsMiscellaneousSymbols(int code) { + return(((code >= 0x2600) && (code <= 0x26FF))); +} + +/** + * xmlUCSIsMiscellaneousSymbolsandArrows: + * @code: UCS code point + * + * Check whether the character is part of MiscellaneousSymbolsandArrows UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsMiscellaneousSymbolsandArrows(int code) { + return(((code >= 0x2B00) && (code <= 0x2BFF))); +} + +/** + * xmlUCSIsMiscellaneousTechnical: + * @code: UCS code point + * + * Check whether the character is part of MiscellaneousTechnical UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsMiscellaneousTechnical(int code) { + return(((code >= 0x2300) && (code <= 0x23FF))); +} + +/** + * xmlUCSIsMongolian: + * @code: UCS code point + * + * Check whether the character is part of Mongolian UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsMongolian(int code) { + return(((code >= 0x1800) && (code <= 0x18AF))); +} + +/** + * xmlUCSIsMusicalSymbols: + * @code: UCS code point + * + * Check whether the character is part of MusicalSymbols UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsMusicalSymbols(int code) { + return(((code >= 0x1D100) && (code <= 0x1D1FF))); +} + +/** + * xmlUCSIsMyanmar: + * @code: UCS code point + * + * Check whether the character is part of Myanmar UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsMyanmar(int code) { + return(((code >= 0x1000) && (code <= 0x109F))); +} + +/** + * xmlUCSIsNumberForms: + * @code: UCS code point + * + * Check whether the character is part of NumberForms UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsNumberForms(int code) { + return(((code >= 0x2150) && (code <= 0x218F))); +} + +/** + * xmlUCSIsOgham: + * @code: UCS code point + * + * Check whether the character is part of Ogham UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsOgham(int code) { + return(((code >= 0x1680) && (code <= 0x169F))); +} + +/** + * xmlUCSIsOldItalic: + * @code: UCS code point + * + * Check whether the character is part of OldItalic UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsOldItalic(int code) { + return(((code >= 0x10300) && (code <= 0x1032F))); +} + +/** + * xmlUCSIsOpticalCharacterRecognition: + * @code: UCS code point + * + * Check whether the character is part of OpticalCharacterRecognition UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsOpticalCharacterRecognition(int code) { + return(((code >= 0x2440) && (code <= 0x245F))); +} + +/** + * xmlUCSIsOriya: + * @code: UCS code point + * + * Check whether the character is part of Oriya UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsOriya(int code) { + return(((code >= 0x0B00) && (code <= 0x0B7F))); +} + +/** + * xmlUCSIsOsmanya: + * @code: UCS code point + * + * Check whether the character is part of Osmanya UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsOsmanya(int code) { + return(((code >= 0x10480) && (code <= 0x104AF))); +} + +/** + * xmlUCSIsPhoneticExtensions: + * @code: UCS code point + * + * Check whether the character is part of PhoneticExtensions UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsPhoneticExtensions(int code) { + return(((code >= 0x1D00) && (code <= 0x1D7F))); +} + +/** + * xmlUCSIsPrivateUse: + * @code: UCS code point + * + * Check whether the character is part of PrivateUse UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsPrivateUse(int code) { + return(((code >= 0xE000) && (code <= 0xF8FF)) || + ((code >= 0xF0000) && (code <= 0xFFFFF)) || + ((code >= 0x100000) && (code <= 0x10FFFF))); +} + +/** + * xmlUCSIsPrivateUseArea: + * @code: UCS code point + * + * Check whether the character is part of PrivateUseArea UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsPrivateUseArea(int code) { + return(((code >= 0xE000) && (code <= 0xF8FF))); +} + +/** + * xmlUCSIsRunic: + * @code: UCS code point + * + * Check whether the character is part of Runic UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsRunic(int code) { + return(((code >= 0x16A0) && (code <= 0x16FF))); +} + +/** + * xmlUCSIsShavian: + * @code: UCS code point + * + * Check whether the character is part of Shavian UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsShavian(int code) { + return(((code >= 0x10450) && (code <= 0x1047F))); +} + +/** + * xmlUCSIsSinhala: + * @code: UCS code point + * + * Check whether the character is part of Sinhala UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsSinhala(int code) { + return(((code >= 0x0D80) && (code <= 0x0DFF))); +} + +/** + * xmlUCSIsSmallFormVariants: + * @code: UCS code point + * + * Check whether the character is part of SmallFormVariants UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsSmallFormVariants(int code) { + return(((code >= 0xFE50) && (code <= 0xFE6F))); +} + +/** + * xmlUCSIsSpacingModifierLetters: + * @code: UCS code point + * + * Check whether the character is part of SpacingModifierLetters UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsSpacingModifierLetters(int code) { + return(((code >= 0x02B0) && (code <= 0x02FF))); +} + +/** + * xmlUCSIsSpecials: + * @code: UCS code point + * + * Check whether the character is part of Specials UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsSpecials(int code) { + return(((code >= 0xFFF0) && (code <= 0xFFFF))); +} + +/** + * xmlUCSIsSuperscriptsandSubscripts: + * @code: UCS code point + * + * Check whether the character is part of SuperscriptsandSubscripts UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsSuperscriptsandSubscripts(int code) { + return(((code >= 0x2070) && (code <= 0x209F))); +} + +/** + * xmlUCSIsSupplementalArrowsA: + * @code: UCS code point + * + * Check whether the character is part of SupplementalArrows-A UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsSupplementalArrowsA(int code) { + return(((code >= 0x27F0) && (code <= 0x27FF))); +} + +/** + * xmlUCSIsSupplementalArrowsB: + * @code: UCS code point + * + * Check whether the character is part of SupplementalArrows-B UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsSupplementalArrowsB(int code) { + return(((code >= 0x2900) && (code <= 0x297F))); +} + +/** + * xmlUCSIsSupplementalMathematicalOperators: + * @code: UCS code point + * + * Check whether the character is part of SupplementalMathematicalOperators UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsSupplementalMathematicalOperators(int code) { + return(((code >= 0x2A00) && (code <= 0x2AFF))); +} + +/** + * xmlUCSIsSupplementaryPrivateUseAreaA: + * @code: UCS code point + * + * Check whether the character is part of SupplementaryPrivateUseArea-A UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsSupplementaryPrivateUseAreaA(int code) { + return(((code >= 0xF0000) && (code <= 0xFFFFF))); +} + +/** + * xmlUCSIsSupplementaryPrivateUseAreaB: + * @code: UCS code point + * + * Check whether the character is part of SupplementaryPrivateUseArea-B UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsSupplementaryPrivateUseAreaB(int code) { + return(((code >= 0x100000) && (code <= 0x10FFFF))); +} + +/** + * xmlUCSIsSyriac: + * @code: UCS code point + * + * Check whether the character is part of Syriac UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsSyriac(int code) { + return(((code >= 0x0700) && (code <= 0x074F))); +} + +/** + * xmlUCSIsTagalog: + * @code: UCS code point + * + * Check whether the character is part of Tagalog UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsTagalog(int code) { + return(((code >= 0x1700) && (code <= 0x171F))); +} + +/** + * xmlUCSIsTagbanwa: + * @code: UCS code point + * + * Check whether the character is part of Tagbanwa UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsTagbanwa(int code) { + return(((code >= 0x1760) && (code <= 0x177F))); +} + +/** + * xmlUCSIsTags: + * @code: UCS code point + * + * Check whether the character is part of Tags UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsTags(int code) { + return(((code >= 0xE0000) && (code <= 0xE007F))); +} + +/** + * xmlUCSIsTaiLe: + * @code: UCS code point + * + * Check whether the character is part of TaiLe UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsTaiLe(int code) { + return(((code >= 0x1950) && (code <= 0x197F))); +} + +/** + * xmlUCSIsTaiXuanJingSymbols: + * @code: UCS code point + * + * Check whether the character is part of TaiXuanJingSymbols UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsTaiXuanJingSymbols(int code) { + return(((code >= 0x1D300) && (code <= 0x1D35F))); +} + +/** + * xmlUCSIsTamil: + * @code: UCS code point + * + * Check whether the character is part of Tamil UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsTamil(int code) { + return(((code >= 0x0B80) && (code <= 0x0BFF))); +} + +/** + * xmlUCSIsTelugu: + * @code: UCS code point + * + * Check whether the character is part of Telugu UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsTelugu(int code) { + return(((code >= 0x0C00) && (code <= 0x0C7F))); +} + +/** + * xmlUCSIsThaana: + * @code: UCS code point + * + * Check whether the character is part of Thaana UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsThaana(int code) { + return(((code >= 0x0780) && (code <= 0x07BF))); +} + +/** + * xmlUCSIsThai: + * @code: UCS code point + * + * Check whether the character is part of Thai UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsThai(int code) { + return(((code >= 0x0E00) && (code <= 0x0E7F))); +} + +/** + * xmlUCSIsTibetan: + * @code: UCS code point + * + * Check whether the character is part of Tibetan UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsTibetan(int code) { + return(((code >= 0x0F00) && (code <= 0x0FFF))); +} + +/** + * xmlUCSIsUgaritic: + * @code: UCS code point + * + * Check whether the character is part of Ugaritic UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsUgaritic(int code) { + return(((code >= 0x10380) && (code <= 0x1039F))); +} + +/** + * xmlUCSIsUnifiedCanadianAboriginalSyllabics: + * @code: UCS code point + * + * Check whether the character is part of UnifiedCanadianAboriginalSyllabics UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsUnifiedCanadianAboriginalSyllabics(int code) { + return(((code >= 0x1400) && (code <= 0x167F))); +} + +/** + * xmlUCSIsVariationSelectors: + * @code: UCS code point + * + * Check whether the character is part of VariationSelectors UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsVariationSelectors(int code) { + return(((code >= 0xFE00) && (code <= 0xFE0F))); +} + +/** + * xmlUCSIsVariationSelectorsSupplement: + * @code: UCS code point + * + * Check whether the character is part of VariationSelectorsSupplement UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsVariationSelectorsSupplement(int code) { + return(((code >= 0xE0100) && (code <= 0xE01EF))); +} + +/** + * xmlUCSIsYiRadicals: + * @code: UCS code point + * + * Check whether the character is part of YiRadicals UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsYiRadicals(int code) { + return(((code >= 0xA490) && (code <= 0xA4CF))); +} + +/** + * xmlUCSIsYiSyllables: + * @code: UCS code point + * + * Check whether the character is part of YiSyllables UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsYiSyllables(int code) { + return(((code >= 0xA000) && (code <= 0xA48F))); +} + +/** + * xmlUCSIsYijingHexagramSymbols: + * @code: UCS code point + * + * Check whether the character is part of YijingHexagramSymbols UCS Block + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsYijingHexagramSymbols(int code) { + return(((code >= 0x4DC0) && (code <= 0x4DFF))); +} + +/** + * xmlUCSIsBlock: + * @code: UCS code point + * @block: UCS block name + * + * Check whether the character is part of the UCS Block + * + * Returns 1 if true, 0 if false and -1 on unknown block + */ +int +xmlUCSIsBlock(int code, const char *block) { + xmlIntFunc *func; + + func = xmlUnicodeLookup(&xmlUnicodeBlockTbl, block); + if (func == NULL) + return (-1); + return (func(code)); +} + +/** + * xmlUCSIsCatC: + * @code: UCS code point + * + * Check whether the character is part of C UCS Category + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsCatC(int code) { + return(xmlCharInRange((unsigned int)code, &xmlCG)); +} + +/** + * xmlUCSIsCatCc: + * @code: UCS code point + * + * Check whether the character is part of Cc UCS Category + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsCatCc(int code) { + return(((code >= 0x0) && (code <= 0x1f)) || + ((code >= 0x7f) && (code <= 0x9f))); +} + +/** + * xmlUCSIsCatCf: + * @code: UCS code point + * + * Check whether the character is part of Cf UCS Category + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsCatCf(int code) { + return(xmlCharInRange((unsigned int)code, &xmlCfG)); +} + +/** + * xmlUCSIsCatCo: + * @code: UCS code point + * + * Check whether the character is part of Co UCS Category + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsCatCo(int code) { + return((code == 0xe000) || + (code == 0xf8ff) || + (code == 0xf0000) || + (code == 0xffffd) || + (code == 0x100000) || + (code == 0x10fffd)); +} + +/** + * xmlUCSIsCatCs: + * @code: UCS code point + * + * Check whether the character is part of Cs UCS Category + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsCatCs(int code) { + return((code == 0xd800) || + ((code >= 0xdb7f) && (code <= 0xdb80)) || + ((code >= 0xdbff) && (code <= 0xdc00)) || + (code == 0xdfff)); +} + +/** + * xmlUCSIsCatL: + * @code: UCS code point + * + * Check whether the character is part of L UCS Category + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsCatL(int code) { + return(xmlCharInRange((unsigned int)code, &xmlLG)); +} + +/** + * xmlUCSIsCatLl: + * @code: UCS code point + * + * Check whether the character is part of Ll UCS Category + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsCatLl(int code) { + return(xmlCharInRange((unsigned int)code, &xmlLlG)); +} + +/** + * xmlUCSIsCatLm: + * @code: UCS code point + * + * Check whether the character is part of Lm UCS Category + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsCatLm(int code) { + return(xmlCharInRange((unsigned int)code, &xmlLmG)); +} + +/** + * xmlUCSIsCatLo: + * @code: UCS code point + * + * Check whether the character is part of Lo UCS Category + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsCatLo(int code) { + return(xmlCharInRange((unsigned int)code, &xmlLoG)); +} + +/** + * xmlUCSIsCatLt: + * @code: UCS code point + * + * Check whether the character is part of Lt UCS Category + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsCatLt(int code) { + return(xmlCharInRange((unsigned int)code, &xmlLtG)); +} + +/** + * xmlUCSIsCatLu: + * @code: UCS code point + * + * Check whether the character is part of Lu UCS Category + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsCatLu(int code) { + return(xmlCharInRange((unsigned int)code, &xmlLuG)); +} + +/** + * xmlUCSIsCatM: + * @code: UCS code point + * + * Check whether the character is part of M UCS Category + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsCatM(int code) { + return(xmlCharInRange((unsigned int)code, &xmlMG)); +} + +/** + * xmlUCSIsCatMc: + * @code: UCS code point + * + * Check whether the character is part of Mc UCS Category + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsCatMc(int code) { + return(xmlCharInRange((unsigned int)code, &xmlMcG)); +} + +/** + * xmlUCSIsCatMe: + * @code: UCS code point + * + * Check whether the character is part of Me UCS Category + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsCatMe(int code) { + return(((code >= 0x488) && (code <= 0x489)) || + (code == 0x6de) || + ((code >= 0x20dd) && (code <= 0x20e0)) || + ((code >= 0x20e2) && (code <= 0x20e4))); +} + +/** + * xmlUCSIsCatMn: + * @code: UCS code point + * + * Check whether the character is part of Mn UCS Category + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsCatMn(int code) { + return(xmlCharInRange((unsigned int)code, &xmlMnG)); +} + +/** + * xmlUCSIsCatN: + * @code: UCS code point + * + * Check whether the character is part of N UCS Category + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsCatN(int code) { + return(xmlCharInRange((unsigned int)code, &xmlNG)); +} + +/** + * xmlUCSIsCatNd: + * @code: UCS code point + * + * Check whether the character is part of Nd UCS Category + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsCatNd(int code) { + return(xmlCharInRange((unsigned int)code, &xmlNdG)); +} + +/** + * xmlUCSIsCatNl: + * @code: UCS code point + * + * Check whether the character is part of Nl UCS Category + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsCatNl(int code) { + return(((code >= 0x16ee) && (code <= 0x16f0)) || + ((code >= 0x2160) && (code <= 0x2183)) || + (code == 0x3007) || + ((code >= 0x3021) && (code <= 0x3029)) || + ((code >= 0x3038) && (code <= 0x303a)) || + (code == 0x1034a)); +} + +/** + * xmlUCSIsCatNo: + * @code: UCS code point + * + * Check whether the character is part of No UCS Category + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsCatNo(int code) { + return(xmlCharInRange((unsigned int)code, &xmlNoG)); +} + +/** + * xmlUCSIsCatP: + * @code: UCS code point + * + * Check whether the character is part of P UCS Category + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsCatP(int code) { + return(xmlCharInRange((unsigned int)code, &xmlPG)); +} + +/** + * xmlUCSIsCatPc: + * @code: UCS code point + * + * Check whether the character is part of Pc UCS Category + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsCatPc(int code) { + return((code == 0x5f) || + ((code >= 0x203f) && (code <= 0x2040)) || + (code == 0x2054) || + (code == 0x30fb) || + ((code >= 0xfe33) && (code <= 0xfe34)) || + ((code >= 0xfe4d) && (code <= 0xfe4f)) || + (code == 0xff3f) || + (code == 0xff65)); +} + +/** + * xmlUCSIsCatPd: + * @code: UCS code point + * + * Check whether the character is part of Pd UCS Category + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsCatPd(int code) { + return(xmlCharInRange((unsigned int)code, &xmlPdG)); +} + +/** + * xmlUCSIsCatPe: + * @code: UCS code point + * + * Check whether the character is part of Pe UCS Category + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsCatPe(int code) { + return(xmlCharInRange((unsigned int)code, &xmlPeG)); +} + +/** + * xmlUCSIsCatPf: + * @code: UCS code point + * + * Check whether the character is part of Pf UCS Category + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsCatPf(int code) { + return((code == 0xbb) || + (code == 0x2019) || + (code == 0x201d) || + (code == 0x203a)); +} + +/** + * xmlUCSIsCatPi: + * @code: UCS code point + * + * Check whether the character is part of Pi UCS Category + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsCatPi(int code) { + return((code == 0xab) || + (code == 0x2018) || + ((code >= 0x201b) && (code <= 0x201c)) || + (code == 0x201f) || + (code == 0x2039)); +} + +/** + * xmlUCSIsCatPo: + * @code: UCS code point + * + * Check whether the character is part of Po UCS Category + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsCatPo(int code) { + return(xmlCharInRange((unsigned int)code, &xmlPoG)); +} + +/** + * xmlUCSIsCatPs: + * @code: UCS code point + * + * Check whether the character is part of Ps UCS Category + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsCatPs(int code) { + return(xmlCharInRange((unsigned int)code, &xmlPsG)); +} + +/** + * xmlUCSIsCatS: + * @code: UCS code point + * + * Check whether the character is part of S UCS Category + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsCatS(int code) { + return(xmlCharInRange((unsigned int)code, &xmlSG)); +} + +/** + * xmlUCSIsCatSc: + * @code: UCS code point + * + * Check whether the character is part of Sc UCS Category + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsCatSc(int code) { + return(xmlCharInRange((unsigned int)code, &xmlScG)); +} + +/** + * xmlUCSIsCatSk: + * @code: UCS code point + * + * Check whether the character is part of Sk UCS Category + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsCatSk(int code) { + return(xmlCharInRange((unsigned int)code, &xmlSkG)); +} + +/** + * xmlUCSIsCatSm: + * @code: UCS code point + * + * Check whether the character is part of Sm UCS Category + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsCatSm(int code) { + return(xmlCharInRange((unsigned int)code, &xmlSmG)); +} + +/** + * xmlUCSIsCatSo: + * @code: UCS code point + * + * Check whether the character is part of So UCS Category + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsCatSo(int code) { + return(xmlCharInRange((unsigned int)code, &xmlSoG)); +} + +/** + * xmlUCSIsCatZ: + * @code: UCS code point + * + * Check whether the character is part of Z UCS Category + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsCatZ(int code) { + return(xmlCharInRange((unsigned int)code, &xmlZG)); +} + +/** + * xmlUCSIsCatZl: + * @code: UCS code point + * + * Check whether the character is part of Zl UCS Category + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsCatZl(int code) { + return((code == 0x2028)); +} + +/** + * xmlUCSIsCatZp: + * @code: UCS code point + * + * Check whether the character is part of Zp UCS Category + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsCatZp(int code) { + return((code == 0x2029)); +} + +/** + * xmlUCSIsCatZs: + * @code: UCS code point + * + * Check whether the character is part of Zs UCS Category + * + * Returns 1 if true 0 otherwise + */ +int +xmlUCSIsCatZs(int code) { + return((code == 0x20) || + (code == 0xa0) || + (code == 0x1680) || + (code == 0x180e) || + ((code >= 0x2000) && (code <= 0x200a)) || + (code == 0x202f) || + (code == 0x205f) || + (code == 0x3000)); +} + +/** + * xmlUCSIsCat: + * @code: UCS code point + * @cat: UCS Category name + * + * Check whether the character is part of the UCS Category + * + * Returns 1 if true, 0 if false and -1 on unknown category + */ +int +xmlUCSIsCat(int code, const char *cat) { + xmlIntFunc *func; + + func = xmlUnicodeLookup(&xmlUnicodeCatTbl, cat); + if (func == NULL) + return (-1); + return (func(code)); +} + +#define bottom_xmlunicode +#include "elfgcchack.h" +#endif /* LIBXML_UNICODE_ENABLED */ diff --git a/gettext-tools/gnulib-lib/libxml/xmlunicode.in.h b/gettext-tools/gnulib-lib/libxml/xmlunicode.in.h new file mode 100644 index 0000000..01ac8b6 --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/xmlunicode.in.h @@ -0,0 +1,202 @@ +/* + * Summary: Unicode character APIs + * Description: API for the Unicode character APIs + * + * This file is automatically generated from the + * UCS description files of the Unicode Character Database + * http://www.unicode.org/Public/4.0-Update1/UCD-4.0.1.html + * using the genUnicode.py Python script. + * + * Generation date: Mon Mar 27 11:09:52 2006 + * Sources: Blocks-4.0.1.txt UnicodeData-4.0.1.txt + * Author: Daniel Veillard + */ + +#ifndef __XML_UNICODE_H__ +#define __XML_UNICODE_H__ + +#include + +#ifdef LIBXML_UNICODE_ENABLED + +#ifdef __cplusplus +extern "C" { +#endif + +XMLPUBFUN int XMLCALL xmlUCSIsAegeanNumbers (int code); +XMLPUBFUN int XMLCALL xmlUCSIsAlphabeticPresentationForms (int code); +XMLPUBFUN int XMLCALL xmlUCSIsArabic (int code); +XMLPUBFUN int XMLCALL xmlUCSIsArabicPresentationFormsA (int code); +XMLPUBFUN int XMLCALL xmlUCSIsArabicPresentationFormsB (int code); +XMLPUBFUN int XMLCALL xmlUCSIsArmenian (int code); +XMLPUBFUN int XMLCALL xmlUCSIsArrows (int code); +XMLPUBFUN int XMLCALL xmlUCSIsBasicLatin (int code); +XMLPUBFUN int XMLCALL xmlUCSIsBengali (int code); +XMLPUBFUN int XMLCALL xmlUCSIsBlockElements (int code); +XMLPUBFUN int XMLCALL xmlUCSIsBopomofo (int code); +XMLPUBFUN int XMLCALL xmlUCSIsBopomofoExtended (int code); +XMLPUBFUN int XMLCALL xmlUCSIsBoxDrawing (int code); +XMLPUBFUN int XMLCALL xmlUCSIsBraillePatterns (int code); +XMLPUBFUN int XMLCALL xmlUCSIsBuhid (int code); +XMLPUBFUN int XMLCALL xmlUCSIsByzantineMusicalSymbols (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCJKCompatibility (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCJKCompatibilityForms (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCJKCompatibilityIdeographs (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCJKCompatibilityIdeographsSupplement (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCJKRadicalsSupplement (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCJKSymbolsandPunctuation (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCJKUnifiedIdeographs (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCJKUnifiedIdeographsExtensionA (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCJKUnifiedIdeographsExtensionB (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCherokee (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCombiningDiacriticalMarks (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCombiningDiacriticalMarksforSymbols (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCombiningHalfMarks (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCombiningMarksforSymbols (int code); +XMLPUBFUN int XMLCALL xmlUCSIsControlPictures (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCurrencySymbols (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCypriotSyllabary (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCyrillic (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCyrillicSupplement (int code); +XMLPUBFUN int XMLCALL xmlUCSIsDeseret (int code); +XMLPUBFUN int XMLCALL xmlUCSIsDevanagari (int code); +XMLPUBFUN int XMLCALL xmlUCSIsDingbats (int code); +XMLPUBFUN int XMLCALL xmlUCSIsEnclosedAlphanumerics (int code); +XMLPUBFUN int XMLCALL xmlUCSIsEnclosedCJKLettersandMonths (int code); +XMLPUBFUN int XMLCALL xmlUCSIsEthiopic (int code); +XMLPUBFUN int XMLCALL xmlUCSIsGeneralPunctuation (int code); +XMLPUBFUN int XMLCALL xmlUCSIsGeometricShapes (int code); +XMLPUBFUN int XMLCALL xmlUCSIsGeorgian (int code); +XMLPUBFUN int XMLCALL xmlUCSIsGothic (int code); +XMLPUBFUN int XMLCALL xmlUCSIsGreek (int code); +XMLPUBFUN int XMLCALL xmlUCSIsGreekExtended (int code); +XMLPUBFUN int XMLCALL xmlUCSIsGreekandCoptic (int code); +XMLPUBFUN int XMLCALL xmlUCSIsGujarati (int code); +XMLPUBFUN int XMLCALL xmlUCSIsGurmukhi (int code); +XMLPUBFUN int XMLCALL xmlUCSIsHalfwidthandFullwidthForms (int code); +XMLPUBFUN int XMLCALL xmlUCSIsHangulCompatibilityJamo (int code); +XMLPUBFUN int XMLCALL xmlUCSIsHangulJamo (int code); +XMLPUBFUN int XMLCALL xmlUCSIsHangulSyllables (int code); +XMLPUBFUN int XMLCALL xmlUCSIsHanunoo (int code); +XMLPUBFUN int XMLCALL xmlUCSIsHebrew (int code); +XMLPUBFUN int XMLCALL xmlUCSIsHighPrivateUseSurrogates (int code); +XMLPUBFUN int XMLCALL xmlUCSIsHighSurrogates (int code); +XMLPUBFUN int XMLCALL xmlUCSIsHiragana (int code); +XMLPUBFUN int XMLCALL xmlUCSIsIPAExtensions (int code); +XMLPUBFUN int XMLCALL xmlUCSIsIdeographicDescriptionCharacters (int code); +XMLPUBFUN int XMLCALL xmlUCSIsKanbun (int code); +XMLPUBFUN int XMLCALL xmlUCSIsKangxiRadicals (int code); +XMLPUBFUN int XMLCALL xmlUCSIsKannada (int code); +XMLPUBFUN int XMLCALL xmlUCSIsKatakana (int code); +XMLPUBFUN int XMLCALL xmlUCSIsKatakanaPhoneticExtensions (int code); +XMLPUBFUN int XMLCALL xmlUCSIsKhmer (int code); +XMLPUBFUN int XMLCALL xmlUCSIsKhmerSymbols (int code); +XMLPUBFUN int XMLCALL xmlUCSIsLao (int code); +XMLPUBFUN int XMLCALL xmlUCSIsLatin1Supplement (int code); +XMLPUBFUN int XMLCALL xmlUCSIsLatinExtendedA (int code); +XMLPUBFUN int XMLCALL xmlUCSIsLatinExtendedB (int code); +XMLPUBFUN int XMLCALL xmlUCSIsLatinExtendedAdditional (int code); +XMLPUBFUN int XMLCALL xmlUCSIsLetterlikeSymbols (int code); +XMLPUBFUN int XMLCALL xmlUCSIsLimbu (int code); +XMLPUBFUN int XMLCALL xmlUCSIsLinearBIdeograms (int code); +XMLPUBFUN int XMLCALL xmlUCSIsLinearBSyllabary (int code); +XMLPUBFUN int XMLCALL xmlUCSIsLowSurrogates (int code); +XMLPUBFUN int XMLCALL xmlUCSIsMalayalam (int code); +XMLPUBFUN int XMLCALL xmlUCSIsMathematicalAlphanumericSymbols (int code); +XMLPUBFUN int XMLCALL xmlUCSIsMathematicalOperators (int code); +XMLPUBFUN int XMLCALL xmlUCSIsMiscellaneousMathematicalSymbolsA (int code); +XMLPUBFUN int XMLCALL xmlUCSIsMiscellaneousMathematicalSymbolsB (int code); +XMLPUBFUN int XMLCALL xmlUCSIsMiscellaneousSymbols (int code); +XMLPUBFUN int XMLCALL xmlUCSIsMiscellaneousSymbolsandArrows (int code); +XMLPUBFUN int XMLCALL xmlUCSIsMiscellaneousTechnical (int code); +XMLPUBFUN int XMLCALL xmlUCSIsMongolian (int code); +XMLPUBFUN int XMLCALL xmlUCSIsMusicalSymbols (int code); +XMLPUBFUN int XMLCALL xmlUCSIsMyanmar (int code); +XMLPUBFUN int XMLCALL xmlUCSIsNumberForms (int code); +XMLPUBFUN int XMLCALL xmlUCSIsOgham (int code); +XMLPUBFUN int XMLCALL xmlUCSIsOldItalic (int code); +XMLPUBFUN int XMLCALL xmlUCSIsOpticalCharacterRecognition (int code); +XMLPUBFUN int XMLCALL xmlUCSIsOriya (int code); +XMLPUBFUN int XMLCALL xmlUCSIsOsmanya (int code); +XMLPUBFUN int XMLCALL xmlUCSIsPhoneticExtensions (int code); +XMLPUBFUN int XMLCALL xmlUCSIsPrivateUse (int code); +XMLPUBFUN int XMLCALL xmlUCSIsPrivateUseArea (int code); +XMLPUBFUN int XMLCALL xmlUCSIsRunic (int code); +XMLPUBFUN int XMLCALL xmlUCSIsShavian (int code); +XMLPUBFUN int XMLCALL xmlUCSIsSinhala (int code); +XMLPUBFUN int XMLCALL xmlUCSIsSmallFormVariants (int code); +XMLPUBFUN int XMLCALL xmlUCSIsSpacingModifierLetters (int code); +XMLPUBFUN int XMLCALL xmlUCSIsSpecials (int code); +XMLPUBFUN int XMLCALL xmlUCSIsSuperscriptsandSubscripts (int code); +XMLPUBFUN int XMLCALL xmlUCSIsSupplementalArrowsA (int code); +XMLPUBFUN int XMLCALL xmlUCSIsSupplementalArrowsB (int code); +XMLPUBFUN int XMLCALL xmlUCSIsSupplementalMathematicalOperators (int code); +XMLPUBFUN int XMLCALL xmlUCSIsSupplementaryPrivateUseAreaA (int code); +XMLPUBFUN int XMLCALL xmlUCSIsSupplementaryPrivateUseAreaB (int code); +XMLPUBFUN int XMLCALL xmlUCSIsSyriac (int code); +XMLPUBFUN int XMLCALL xmlUCSIsTagalog (int code); +XMLPUBFUN int XMLCALL xmlUCSIsTagbanwa (int code); +XMLPUBFUN int XMLCALL xmlUCSIsTags (int code); +XMLPUBFUN int XMLCALL xmlUCSIsTaiLe (int code); +XMLPUBFUN int XMLCALL xmlUCSIsTaiXuanJingSymbols (int code); +XMLPUBFUN int XMLCALL xmlUCSIsTamil (int code); +XMLPUBFUN int XMLCALL xmlUCSIsTelugu (int code); +XMLPUBFUN int XMLCALL xmlUCSIsThaana (int code); +XMLPUBFUN int XMLCALL xmlUCSIsThai (int code); +XMLPUBFUN int XMLCALL xmlUCSIsTibetan (int code); +XMLPUBFUN int XMLCALL xmlUCSIsUgaritic (int code); +XMLPUBFUN int XMLCALL xmlUCSIsUnifiedCanadianAboriginalSyllabics (int code); +XMLPUBFUN int XMLCALL xmlUCSIsVariationSelectors (int code); +XMLPUBFUN int XMLCALL xmlUCSIsVariationSelectorsSupplement (int code); +XMLPUBFUN int XMLCALL xmlUCSIsYiRadicals (int code); +XMLPUBFUN int XMLCALL xmlUCSIsYiSyllables (int code); +XMLPUBFUN int XMLCALL xmlUCSIsYijingHexagramSymbols (int code); + +XMLPUBFUN int XMLCALL xmlUCSIsBlock (int code, const char *block); + +XMLPUBFUN int XMLCALL xmlUCSIsCatC (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatCc (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatCf (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatCo (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatCs (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatL (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatLl (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatLm (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatLo (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatLt (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatLu (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatM (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatMc (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatMe (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatMn (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatN (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatNd (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatNl (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatNo (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatP (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatPc (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatPd (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatPe (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatPf (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatPi (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatPo (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatPs (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatS (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatSc (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatSk (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatSm (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatSo (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatZ (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatZl (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatZp (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatZs (int code); + +XMLPUBFUN int XMLCALL xmlUCSIsCat (int code, const char *cat); + +#ifdef __cplusplus +} +#endif + +#endif /* LIBXML_UNICODE_ENABLED */ + +#endif /* __XML_UNICODE_H__ */ diff --git a/gettext-tools/gnulib-lib/libxml/xmlversion.in.h b/gettext-tools/gnulib-lib/libxml/xmlversion.in.h new file mode 100644 index 0000000..4c6d2bd --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/xmlversion.in.h @@ -0,0 +1,405 @@ +/* + * Summary: compile-time version informations + * Description: compile-time version informations for the XML library + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + +#ifndef __XML_VERSION_H__ +#define __XML_VERSION_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * use those to be sure nothing nasty will happen if + * your library and includes mismatch + */ +#ifndef LIBXML2_COMPILING_MSCCDEF +XMLPUBFUN void XMLCALL xmlCheckVersion(int version); +#endif /* LIBXML2_COMPILING_MSCCDEF */ + +/** + * LIBXML_DOTTED_VERSION: + * + * the version string like "1.2.3" + */ +#define LIBXML_DOTTED_VERSION "2.6.27" + +/** + * LIBXML_VERSION: + * + * the version number: 1.2.3 value is 10203 + */ +#define LIBXML_VERSION 20627 + +/** + * LIBXML_VERSION_STRING: + * + * the version number string, 1.2.3 value is "10203" + */ +#define LIBXML_VERSION_STRING "20627" + +/** + * LIBXML_VERSION_EXTRA: + * + * extra version information, used to show a CVS compilation + */ +#define LIBXML_VERSION_EXTRA "-CVS2872" + +/** + * LIBXML_TEST_VERSION: + * + * Macro to check that the libxml version in use is compatible with + * the version the software has been compiled against + */ +#define LIBXML_TEST_VERSION xmlCheckVersion(20627); + +#ifndef VMS +#if 0 +/** + * WITH_TRIO: + * + * defined if the trio support need to be configured in + */ +#define WITH_TRIO +#else +/** + * WITHOUT_TRIO: + * + * defined if the trio support should not be configured in + */ +#define WITHOUT_TRIO +#endif +#else /* VMS */ +/** + * WITH_TRIO: + * + * defined if the trio support need to be configured in + */ +#define WITH_TRIO 1 +#endif /* VMS */ + +/** + * LIBXML_THREAD_ENABLED: + * + * Whether the thread support is configured in + */ +#if 0 +#if defined(_REENTRANT) || defined(__MT__) || (_POSIX_C_SOURCE - 0 >= 199506L) +#define LIBXML_THREAD_ENABLED +#endif +#endif + +/** + * LIBXML_TREE_ENABLED: + * + * Whether the DOM like tree manipulation API support is configured in + */ +#if 1 +#define LIBXML_TREE_ENABLED +#endif + +/** + * LIBXML_OUTPUT_ENABLED: + * + * Whether the serialization/saving support is configured in + */ +#if 1 +#define LIBXML_OUTPUT_ENABLED +#endif + +/** + * LIBXML_PUSH_ENABLED: + * + * Whether the push parsing interfaces are configured in + */ +#if 1 +#define LIBXML_PUSH_ENABLED +#endif + +/** + * LIBXML_READER_ENABLED: + * + * Whether the xmlReader parsing interface is configured in + */ +#if 1 +#define LIBXML_READER_ENABLED +#endif + +/** + * LIBXML_PATTERN_ENABLED: + * + * Whether the xmlPattern node selection interface is configured in + */ +#if 0 +#define LIBXML_PATTERN_ENABLED +#endif + +/** + * LIBXML_WRITER_ENABLED: + * + * Whether the xmlWriter saving interface is configured in + */ +#if 1 +#define LIBXML_WRITER_ENABLED +#endif + +/** + * LIBXML_SAX1_ENABLED: + * + * Whether the older SAX1 interface is configured in + */ +#if 0 +#define LIBXML_SAX1_ENABLED +#endif + +/** + * LIBXML_FTP_ENABLED: + * + * Whether the FTP support is configured in + */ +#if 0 +#define LIBXML_FTP_ENABLED +#endif + +/** + * LIBXML_HTTP_ENABLED: + * + * Whether the HTTP support is configured in + */ +#if 0 +#define LIBXML_HTTP_ENABLED +#endif + +/** + * LIBXML_VALID_ENABLED: + * + * Whether the DTD validation support is configured in + */ +#if 0 +#define LIBXML_VALID_ENABLED +#endif + +/** + * LIBXML_HTML_ENABLED: + * + * Whether the HTML support is configured in + */ +#if 0 +#define LIBXML_HTML_ENABLED +#endif + +/** + * LIBXML_LEGACY_ENABLED: + * + * Whether the deprecated APIs are compiled in for compatibility + */ +#if 0 +#define LIBXML_LEGACY_ENABLED +#endif + +/** + * LIBXML_C14N_ENABLED: + * + * Whether the Canonicalization support is configured in + */ +#if 0 +#define LIBXML_C14N_ENABLED +#endif + +/** + * LIBXML_CATALOG_ENABLED: + * + * Whether the Catalog support is configured in + */ +#if 0 +#define LIBXML_CATALOG_ENABLED +#endif + +/** + * LIBXML_DOCB_ENABLED: + * + * Whether the SGML Docbook support is configured in + */ +#if 0 +#define LIBXML_DOCB_ENABLED +#endif + +/** + * LIBXML_XPATH_ENABLED: + * + * Whether XPath is configured in + */ +#if 0 +#define LIBXML_XPATH_ENABLED +#endif + +/** + * LIBXML_XPTR_ENABLED: + * + * Whether XPointer is configured in + */ +#if 0 +#define LIBXML_XPTR_ENABLED +#endif + +/** + * LIBXML_XINCLUDE_ENABLED: + * + * Whether XInclude is configured in + */ +#if 0 +#define LIBXML_XINCLUDE_ENABLED +#endif + +/** + * LIBXML_ICONV_ENABLED: + * + * Whether iconv support is available + */ +#if 1 +#define LIBXML_ICONV_ENABLED +#endif + +/** + * LIBXML_ISO8859X_ENABLED: + * + * Whether ISO-8859-* support is made available in case iconv is not + */ +#if 1 +#define LIBXML_ISO8859X_ENABLED +#endif + +/** + * LIBXML_DEBUG_ENABLED: + * + * Whether Debugging module is configured in + */ +#if 0 +#define LIBXML_DEBUG_ENABLED +#endif + +/** + * DEBUG_MEMORY_LOCATION: + * + * Whether the memory debugging is configured in + */ +#if 0 +#define DEBUG_MEMORY_LOCATION +#endif + +/** + * LIBXML_DEBUG_RUNTIME: + * + * Whether the runtime debugging is configured in + */ +#if 0 +#define LIBXML_DEBUG_RUNTIME +#endif + +/** + * LIBXML_UNICODE_ENABLED: + * + * Whether the Unicode related interfaces are compiled in + */ +#if 0 +#define LIBXML_UNICODE_ENABLED +#endif + +/** + * LIBXML_REGEXP_ENABLED: + * + * Whether the regular expressions interfaces are compiled in + */ +#if 0 +#define LIBXML_REGEXP_ENABLED +#endif + +/** + * LIBXML_AUTOMATA_ENABLED: + * + * Whether the automata interfaces are compiled in + */ +#if 0 +#define LIBXML_AUTOMATA_ENABLED +#endif + +/** + * LIBXML_EXPR_ENABLED: + * + * Whether the formal expressions interfaces are compiled in + */ +#if 0 +#define LIBXML_EXPR_ENABLED +#endif + +/** + * LIBXML_SCHEMAS_ENABLED: + * + * Whether the Schemas validation interfaces are compiled in + */ +#if 0 +#define LIBXML_SCHEMAS_ENABLED +#endif + +/** + * LIBXML_SCHEMATRON_ENABLED: + * + * Whether the Schematron validation interfaces are compiled in + */ +#if 0 +#define LIBXML_SCHEMATRON_ENABLED +#endif + +/** + * LIBXML_MODULES_ENABLED: + * + * Whether the module interfaces are compiled in + */ +#if 0 +#define LIBXML_MODULES_ENABLED +/** + * LIBXML_MODULE_EXTENSION: + * + * the string suffix used by dynamic modules (usually shared libraries) + */ +#define LIBXML_MODULE_EXTENSION ".so" +#endif + +/** + * LIBXML_ZLIB_ENABLED: + * + * Whether the Zlib support is compiled in + */ +#if 0 +#define LIBXML_ZLIB_ENABLED +#endif + +/** + * ATTRIBUTE_UNUSED: + * + * Macro used to signal to GCC unused function parameters + */ +#ifdef __GNUC__ +#ifdef HAVE_ANSIDECL_H +#include +#endif +#ifndef ATTRIBUTE_UNUSED +#define ATTRIBUTE_UNUSED __attribute__((unused)) +#endif +#else +#define ATTRIBUTE_UNUSED +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif + + diff --git a/gettext-tools/gnulib-lib/libxml/xmlwriter.c b/gettext-tools/gnulib-lib/libxml/xmlwriter.c new file mode 100644 index 0000000..5821056 --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/xmlwriter.c @@ -0,0 +1,4615 @@ + +/* + * xmlwriter.c: XML text writer implementation + * + * For license and disclaimer see the license and disclaimer of + * libxml2. + * + * alfred@mickautsch.de + */ + +#define IN_LIBXML +#include "libxml.h" + +#include + +#include +#include +#include +#include + +#ifdef LIBXML_WRITER_ENABLED + +#include + +#define B64LINELEN 72 +#define B64CRLF "\r\n" + +/* + * The following VA_COPY was coded following an example in + * the Samba project. It may not be sufficient for some + * esoteric implementations of va_list (i.e. it may need + * something involving a memcpy) but (hopefully) will be + * sufficient for libxml2. + */ +#ifndef VA_COPY + #ifdef HAVE_VA_COPY + #define VA_COPY(dest, src) va_copy(dest, src) + #else + #ifdef HAVE___VA_COPY + #define VA_COPY(dest,src) __va_copy(dest, src) + #else + #define VA_COPY(dest,src) (dest) = (src) + #endif + #endif +#endif + +/* + * Types are kept private + */ +typedef enum { + XML_TEXTWRITER_NONE = 0, + XML_TEXTWRITER_NAME, + XML_TEXTWRITER_ATTRIBUTE, + XML_TEXTWRITER_TEXT, + XML_TEXTWRITER_PI, + XML_TEXTWRITER_PI_TEXT, + XML_TEXTWRITER_CDATA, + XML_TEXTWRITER_DTD, + XML_TEXTWRITER_DTD_TEXT, + XML_TEXTWRITER_DTD_ELEM, + XML_TEXTWRITER_DTD_ELEM_TEXT, + XML_TEXTWRITER_DTD_ATTL, + XML_TEXTWRITER_DTD_ATTL_TEXT, + XML_TEXTWRITER_DTD_ENTY, /* entity */ + XML_TEXTWRITER_DTD_ENTY_TEXT, + XML_TEXTWRITER_DTD_PENT, /* parameter entity */ + XML_TEXTWRITER_COMMENT +} xmlTextWriterState; + +typedef struct _xmlTextWriterStackEntry xmlTextWriterStackEntry; + +struct _xmlTextWriterStackEntry { + xmlChar *name; + xmlTextWriterState state; +}; + +typedef struct _xmlTextWriterNsStackEntry xmlTextWriterNsStackEntry; +struct _xmlTextWriterNsStackEntry { + xmlChar *prefix; + xmlChar *uri; + xmlLinkPtr elem; +}; + +struct _xmlTextWriter { + xmlOutputBufferPtr out; /* output buffer */ + xmlListPtr nodes; /* element name stack */ + xmlListPtr nsstack; /* name spaces stack */ + int level; + int indent; /* enable indent */ + int doindent; /* internal indent flag */ + xmlChar *ichar; /* indent character */ + char qchar; /* character used for quoting attribute values */ + xmlParserCtxtPtr ctxt; + int no_doc_free; + xmlDocPtr doc; +}; + +static void xmlFreeTextWriterStackEntry(xmlLinkPtr lk); +static int xmlCmpTextWriterStackEntry(const void *data0, + const void *data1); +static void xmlFreeTextWriterNsStackEntry(xmlLinkPtr lk); +static int xmlCmpTextWriterNsStackEntry(const void *data0, + const void *data1); +static int xmlTextWriterWriteDocCallback(void *context, + const xmlChar * str, int len); +static int xmlTextWriterCloseDocCallback(void *context); + +static xmlChar *xmlTextWriterVSprintf(const char *format, va_list argptr); +static int xmlOutputBufferWriteBase64(xmlOutputBufferPtr out, int len, + const unsigned char *data); +static void xmlTextWriterStartDocumentCallback(void *ctx); +static int xmlTextWriterWriteIndent(xmlTextWriterPtr writer); +static int + xmlTextWriterHandleStateDependencies(xmlTextWriterPtr writer, + xmlTextWriterStackEntry * p); + +/** + * xmlWriterErrMsg: + * @ctxt: a writer context + * @error: the error number + * @msg: the error message + * + * Handle a writer error + */ +static void +xmlWriterErrMsg(xmlTextWriterPtr ctxt, xmlParserErrors error, + const char *msg) +{ + if (ctxt != NULL) { + __xmlRaiseError(NULL, NULL, NULL, ctxt->ctxt, + NULL, XML_FROM_WRITER, error, XML_ERR_FATAL, + NULL, 0, NULL, NULL, NULL, 0, 0, msg); + } else { + __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_WRITER, error, + XML_ERR_FATAL, NULL, 0, NULL, NULL, NULL, 0, 0, msg); + } +} + +/** + * xmlWriterErrMsgInt: + * @ctxt: a writer context + * @error: the error number + * @msg: the error message + * @val: an int + * + * Handle a writer error + */ +static void +xmlWriterErrMsgInt(xmlTextWriterPtr ctxt, xmlParserErrors error, + const char *msg, int val) +{ + if (ctxt != NULL) { + __xmlRaiseError(NULL, NULL, NULL, ctxt->ctxt, + NULL, XML_FROM_WRITER, error, XML_ERR_FATAL, + NULL, 0, NULL, NULL, NULL, val, 0, msg, val); + } else { + __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_WRITER, error, + XML_ERR_FATAL, NULL, 0, NULL, NULL, NULL, val, 0, msg, val); + } +} + +/** + * xmlNewTextWriter: + * @out: an xmlOutputBufferPtr + * + * Create a new xmlNewTextWriter structure using an xmlOutputBufferPtr + * NOTE: the @out parameter will be deallocated when the writer is closed + * (if the call succeed.) + * + * Returns the new xmlTextWriterPtr or NULL in case of error + */ +xmlTextWriterPtr +xmlNewTextWriter(xmlOutputBufferPtr out) +{ + xmlTextWriterPtr ret; + + ret = (xmlTextWriterPtr) xmlMalloc(sizeof(xmlTextWriter)); + if (ret == NULL) { + xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY, + "xmlNewTextWriter : out of memory!\n"); + return NULL; + } + memset(ret, 0, (size_t) sizeof(xmlTextWriter)); + + ret->nodes = xmlListCreate((xmlListDeallocator) + xmlFreeTextWriterStackEntry, + (xmlListDataCompare) + xmlCmpTextWriterStackEntry); + if (ret->nodes == NULL) { + xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY, + "xmlNewTextWriter : out of memory!\n"); + xmlFree(ret); + return NULL; + } + + ret->nsstack = xmlListCreate((xmlListDeallocator) + xmlFreeTextWriterNsStackEntry, + (xmlListDataCompare) + xmlCmpTextWriterNsStackEntry); + if (ret->nsstack == NULL) { + xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY, + "xmlNewTextWriter : out of memory!\n"); + xmlListDelete(ret->nodes); + xmlFree(ret); + return NULL; + } + + ret->out = out; + ret->ichar = xmlStrdup(BAD_CAST " "); + ret->qchar = '"'; + + if (!ret->ichar) { + xmlListDelete(ret->nodes); + xmlListDelete(ret->nsstack); + xmlFree(ret); + xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY, + "xmlNewTextWriter : out of memory!\n"); + return NULL; + } + + ret->doc = xmlNewDoc(NULL); + + ret->no_doc_free = 0; + + return ret; +} + +/** + * xmlNewTextWriterFilename: + * @uri: the URI of the resource for the output + * @compression: compress the output? + * + * Create a new xmlNewTextWriter structure with @uri as output + * + * Returns the new xmlTextWriterPtr or NULL in case of error + */ +xmlTextWriterPtr +xmlNewTextWriterFilename(const char *uri, int compression) +{ + xmlTextWriterPtr ret; + xmlOutputBufferPtr out; + + out = xmlOutputBufferCreateFilename(uri, NULL, compression); + if (out == NULL) { + xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY, + "xmlNewTextWriterFilename : out of memory!\n"); + return NULL; + } + + ret = xmlNewTextWriter(out); + if (ret == NULL) { + xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY, + "xmlNewTextWriterFilename : out of memory!\n"); + xmlOutputBufferClose(out); + return NULL; + } + + ret->indent = 0; + ret->doindent = 0; + return ret; +} + +/** + * xmlNewTextWriterMemory: + * @buf: xmlBufferPtr + * @compression: compress the output? + * + * Create a new xmlNewTextWriter structure with @buf as output + * TODO: handle compression + * + * Returns the new xmlTextWriterPtr or NULL in case of error + */ +xmlTextWriterPtr +xmlNewTextWriterMemory(xmlBufferPtr buf, int compression ATTRIBUTE_UNUSED) +{ + xmlTextWriterPtr ret; + xmlOutputBufferPtr out; + +/*::todo handle compression */ + out = xmlOutputBufferCreateBuffer(buf, NULL); + + if (out == NULL) { + xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY, + "xmlNewTextWriterMemory : out of memory!\n"); + return NULL; + } + + ret = xmlNewTextWriter(out); + if (ret == NULL) { + xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY, + "xmlNewTextWriterMemory : out of memory!\n"); + xmlOutputBufferClose(out); + return NULL; + } + + return ret; +} + +/** + * xmlNewTextWriterPushParser: + * @ctxt: xmlParserCtxtPtr to hold the new XML document tree + * @compression: compress the output? + * + * Create a new xmlNewTextWriter structure with @ctxt as output + * NOTE: the @ctxt context will be freed with the resulting writer + * (if the call succeeds). + * TODO: handle compression + * + * Returns the new xmlTextWriterPtr or NULL in case of error + */ +xmlTextWriterPtr +xmlNewTextWriterPushParser(xmlParserCtxtPtr ctxt, + int compression ATTRIBUTE_UNUSED) +{ + xmlTextWriterPtr ret; + xmlOutputBufferPtr out; + + if (ctxt == NULL) { + xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR, + "xmlNewTextWriterPushParser : invalid context!\n"); + return NULL; + } + + out = xmlOutputBufferCreateIO((xmlOutputWriteCallback) + xmlTextWriterWriteDocCallback, + (xmlOutputCloseCallback) + xmlTextWriterCloseDocCallback, + (void *) ctxt, NULL); + if (out == NULL) { + xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR, + "xmlNewTextWriterPushParser : error at xmlOutputBufferCreateIO!\n"); + return NULL; + } + + ret = xmlNewTextWriter(out); + if (ret == NULL) { + xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR, + "xmlNewTextWriterPushParser : error at xmlNewTextWriter!\n"); + xmlOutputBufferClose(out); + return NULL; + } + + ret->ctxt = ctxt; + + return ret; +} + +/** + * xmlNewTextWriterDoc: + * @doc: address of a xmlDocPtr to hold the new XML document tree + * @compression: compress the output? + * + * Create a new xmlNewTextWriter structure with @*doc as output + * + * Returns the new xmlTextWriterPtr or NULL in case of error + */ +xmlTextWriterPtr +xmlNewTextWriterDoc(xmlDocPtr * doc, int compression) +{ + xmlTextWriterPtr ret; + xmlSAXHandler saxHandler; + xmlParserCtxtPtr ctxt; + + memset(&saxHandler, '\0', sizeof(saxHandler)); + xmlSAX2InitDefaultSAXHandler(&saxHandler, 1); + saxHandler.startDocument = xmlTextWriterStartDocumentCallback; + saxHandler.startElement = xmlSAX2StartElement; + saxHandler.endElement = xmlSAX2EndElement; + + ctxt = xmlCreatePushParserCtxt(&saxHandler, NULL, NULL, 0, NULL); + if (ctxt == NULL) { + xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR, + "xmlNewTextWriterDoc : error at xmlCreatePushParserCtxt!\n"); + return NULL; + } + /* + * For some reason this seems to completely break if node names + * are interned. + */ + ctxt->dictNames = 0; + + ctxt->myDoc = xmlNewDoc(BAD_CAST XML_DEFAULT_VERSION); + if (ctxt->myDoc == NULL) { + xmlFreeParserCtxt(ctxt); + xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR, + "xmlNewTextWriterDoc : error at xmlNewDoc!\n"); + return NULL; + } + + ret = xmlNewTextWriterPushParser(ctxt, compression); + if (ret == NULL) { + xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR, + "xmlNewTextWriterDoc : error at xmlNewTextWriterPushParser!\n"); + return NULL; + } + + xmlSetDocCompressMode(ctxt->myDoc, compression); + + if (doc != NULL) { + *doc = ctxt->myDoc; + ret->no_doc_free = 1; + } + + return ret; +} + +/** + * xmlNewTextWriterTree: + * @doc: xmlDocPtr + * @node: xmlNodePtr or NULL for doc->children + * @compression: compress the output? + * + * Create a new xmlNewTextWriter structure with @doc as output + * starting at @node + * + * Returns the new xmlTextWriterPtr or NULL in case of error + */ +xmlTextWriterPtr +xmlNewTextWriterTree(xmlDocPtr doc, xmlNodePtr node, int compression) +{ + xmlTextWriterPtr ret; + xmlSAXHandler saxHandler; + xmlParserCtxtPtr ctxt; + + if (doc == NULL) { + xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR, + "xmlNewTextWriterTree : invalid document tree!\n"); + return NULL; + } + + memset(&saxHandler, '\0', sizeof(saxHandler)); + xmlSAX2InitDefaultSAXHandler(&saxHandler, 1); + saxHandler.startDocument = xmlTextWriterStartDocumentCallback; + saxHandler.startElement = xmlSAX2StartElement; + saxHandler.endElement = xmlSAX2EndElement; + + ctxt = xmlCreatePushParserCtxt(&saxHandler, NULL, NULL, 0, NULL); + if (ctxt == NULL) { + xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR, + "xmlNewTextWriterDoc : error at xmlCreatePushParserCtxt!\n"); + return NULL; + } + /* + * For some reason this seems to completely break if node names + * are interned. + */ + ctxt->dictNames = 0; + + ret = xmlNewTextWriterPushParser(ctxt, compression); + if (ret == NULL) { + xmlFreeParserCtxt(ctxt); + xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR, + "xmlNewTextWriterDoc : error at xmlNewTextWriterPushParser!\n"); + return NULL; + } + + ctxt->myDoc = doc; + ctxt->node = node; + ret->no_doc_free = 1; + + xmlSetDocCompressMode(doc, compression); + + return ret; +} + +/** + * xmlFreeTextWriter: + * @writer: the xmlTextWriterPtr + * + * Deallocate all the resources associated to the writer + */ +void +xmlFreeTextWriter(xmlTextWriterPtr writer) +{ + if (writer == NULL) + return; + + if (writer->out != NULL) + xmlOutputBufferClose(writer->out); + + if (writer->nodes != NULL) + xmlListDelete(writer->nodes); + + if (writer->nsstack != NULL) + xmlListDelete(writer->nsstack); + + if (writer->ctxt != NULL) { + if ((writer->ctxt->myDoc != NULL) && (writer->no_doc_free == 0)) { + xmlFreeDoc(writer->ctxt->myDoc); + writer->ctxt->myDoc = NULL; + } + xmlFreeParserCtxt(writer->ctxt); + } + + if (writer->doc != NULL) + xmlFreeDoc(writer->doc); + + if (writer->ichar != NULL) + xmlFree(writer->ichar); + xmlFree(writer); +} + +/** + * xmlTextWriterStartDocument: + * @writer: the xmlTextWriterPtr + * @version: the xml version ("1.0") or NULL for default ("1.0") + * @encoding: the encoding or NULL for default + * @standalone: "yes" or "no" or NULL for default + * + * Start a new xml document + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int +xmlTextWriterStartDocument(xmlTextWriterPtr writer, const char *version, + const char *encoding, const char *standalone) +{ + int count; + int sum; + xmlLinkPtr lk; + xmlCharEncodingHandlerPtr encoder; + + if ((writer == NULL) || (writer->out == NULL)) { + xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR, + "xmlTextWriterStartDocument : invalid writer!\n"); + return -1; + } + + lk = xmlListFront(writer->nodes); + if ((lk != NULL) && (xmlLinkGetData(lk) != NULL)) { + xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR, + "xmlTextWriterStartDocument : not allowed in this context!\n"); + return -1; + } + + encoder = NULL; + if (encoding != NULL) { + encoder = xmlFindCharEncodingHandler(encoding); + if (encoder == NULL) { + xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY, + "xmlTextWriterStartDocument : out of memory!\n"); + return -1; + } + } + + writer->out->encoder = encoder; + if (encoder != NULL) { + writer->out->conv = xmlBufferCreateSize(4000); + xmlCharEncOutFunc(encoder, writer->out->conv, NULL); + if ((writer->doc != NULL) && (writer->doc->encoding == NULL)) + writer->doc->encoding = xmlStrdup((xmlChar *)writer->out->encoder->name); + } else + writer->out->conv = NULL; + + sum = 0; + count = xmlOutputBufferWriteString(writer->out, "out, 1, &writer->qchar); + if (count < 0) + return -1; + sum += count; + if (version != 0) + count = xmlOutputBufferWriteString(writer->out, version); + else + count = xmlOutputBufferWriteString(writer->out, "1.0"); + if (count < 0) + return -1; + sum += count; + count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar); + if (count < 0) + return -1; + sum += count; + if (writer->out->encoder != 0) { + count = xmlOutputBufferWriteString(writer->out, " encoding="); + if (count < 0) + return -1; + sum += count; + count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar); + if (count < 0) + return -1; + sum += count; + count = + xmlOutputBufferWriteString(writer->out, + writer->out->encoder->name); + if (count < 0) + return -1; + sum += count; + count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar); + if (count < 0) + return -1; + sum += count; + } + + if (standalone != 0) { + count = xmlOutputBufferWriteString(writer->out, " standalone="); + if (count < 0) + return -1; + sum += count; + count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar); + if (count < 0) + return -1; + sum += count; + count = xmlOutputBufferWriteString(writer->out, standalone); + if (count < 0) + return -1; + sum += count; + count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar); + if (count < 0) + return -1; + sum += count; + } + + count = xmlOutputBufferWriteString(writer->out, "?>\n"); + if (count < 0) + return -1; + sum += count; + + return sum; +} + +/** + * xmlTextWriterEndDocument: + * @writer: the xmlTextWriterPtr + * + * End an xml document. All open elements are closed + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int +xmlTextWriterEndDocument(xmlTextWriterPtr writer) +{ + int count; + int sum; + xmlLinkPtr lk; + xmlTextWriterStackEntry *p; + + if (writer == NULL) { + xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR, + "xmlTextWriterEndDocument : invalid writer!\n"); + return -1; + } + + sum = 0; + while ((lk = xmlListFront(writer->nodes)) != NULL) { + p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk); + if (p == 0) + break; + switch (p->state) { + case XML_TEXTWRITER_NAME: + case XML_TEXTWRITER_ATTRIBUTE: + case XML_TEXTWRITER_TEXT: + count = xmlTextWriterEndElement(writer); + if (count < 0) + return -1; + sum += count; + break; + case XML_TEXTWRITER_PI: + case XML_TEXTWRITER_PI_TEXT: + count = xmlTextWriterEndPI(writer); + if (count < 0) + return -1; + sum += count; + break; + case XML_TEXTWRITER_CDATA: + count = xmlTextWriterEndCDATA(writer); + if (count < 0) + return -1; + sum += count; + break; + case XML_TEXTWRITER_DTD: + case XML_TEXTWRITER_DTD_TEXT: + case XML_TEXTWRITER_DTD_ELEM: + case XML_TEXTWRITER_DTD_ELEM_TEXT: + case XML_TEXTWRITER_DTD_ATTL: + case XML_TEXTWRITER_DTD_ATTL_TEXT: + case XML_TEXTWRITER_DTD_ENTY: + case XML_TEXTWRITER_DTD_ENTY_TEXT: + case XML_TEXTWRITER_DTD_PENT: + count = xmlTextWriterEndDTD(writer); + if (count < 0) + return -1; + sum += count; + break; + case XML_TEXTWRITER_COMMENT: + count = xmlTextWriterEndComment(writer); + if (count < 0) + return -1; + sum += count; + break; + default: + break; + } + } + + if (!writer->indent) { + count = xmlOutputBufferWriteString(writer->out, "\n"); + if (count < 0) + return -1; + sum += count; + } + return sum; +} + +/** + * xmlTextWriterStartComment: + * @writer: the xmlTextWriterPtr + * + * Start an xml comment. + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int +xmlTextWriterStartComment(xmlTextWriterPtr writer) +{ + int count; + int sum; + xmlLinkPtr lk; + xmlTextWriterStackEntry *p; + + if (writer == NULL) { + xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR, + "xmlTextWriterStartComment : invalid writer!\n"); + return -1; + } + + sum = 0; + lk = xmlListFront(writer->nodes); + if (lk != 0) { + p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk); + if (p != 0) { + switch (p->state) { + case XML_TEXTWRITER_TEXT: + case XML_TEXTWRITER_NONE: + break; + case XML_TEXTWRITER_NAME: + count = xmlOutputBufferWriteString(writer->out, ">"); + if (count < 0) + return -1; + sum += count; + if (writer->indent) { + count = + xmlOutputBufferWriteString(writer->out, "\n"); + if (count < 0) + return -1; + sum += count; + } + p->state = XML_TEXTWRITER_TEXT; + break; + default: + return -1; + } + } + } + + p = (xmlTextWriterStackEntry *) + xmlMalloc(sizeof(xmlTextWriterStackEntry)); + if (p == 0) { + xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY, + "xmlTextWriterStartElement : out of memory!\n"); + return -1; + } + + p->name = NULL; + p->state = XML_TEXTWRITER_COMMENT; + + xmlListPushFront(writer->nodes, p); + + if (writer->indent) { + count = xmlTextWriterWriteIndent(writer); + if (count < 0) + return -1; + sum += count; + } + + count = xmlOutputBufferWriteString(writer->out, ""); + if (count < 0) + return -1; + sum += count; + break; + default: + return -1; + } + + if (writer->indent) { + count = xmlOutputBufferWriteString(writer->out, "\n"); + if (count < 0) + return -1; + sum += count; + } + + xmlListPopFront(writer->nodes); + return sum; +} + +/** + * xmlTextWriterWriteFormatComment: + * @writer: the xmlTextWriterPtr + * @format: format string (see printf) + * @...: extra parameters for the format + * + * Write an xml comment. + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int XMLCDECL +xmlTextWriterWriteFormatComment(xmlTextWriterPtr writer, + const char *format, ...) +{ + int rc; + va_list ap; + + va_start(ap, format); + + rc = xmlTextWriterWriteVFormatComment(writer, format, ap); + + va_end(ap); + return rc; +} + +/** + * xmlTextWriterWriteVFormatComment: + * @writer: the xmlTextWriterPtr + * @format: format string (see printf) + * @argptr: pointer to the first member of the variable argument list. + * + * Write an xml comment. + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int +xmlTextWriterWriteVFormatComment(xmlTextWriterPtr writer, + const char *format, va_list argptr) +{ + int rc; + xmlChar *buf; + + if (writer == NULL) { + xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR, + "xmlTextWriterWriteVFormatComment : invalid writer!\n"); + return -1; + } + + buf = xmlTextWriterVSprintf(format, argptr); + if (buf == 0) + return 0; + + rc = xmlTextWriterWriteComment(writer, buf); + + xmlFree(buf); + return rc; +} + +/** + * xmlTextWriterWriteComment: + * @writer: the xmlTextWriterPtr + * @content: comment string + * + * Write an xml comment. + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int +xmlTextWriterWriteComment(xmlTextWriterPtr writer, const xmlChar * content) +{ + int count; + int sum; + + sum = 0; + count = xmlTextWriterStartComment(writer); + if (count < 0) + return -1; + sum += count; + count = xmlTextWriterWriteString(writer, content); + if (count < 0) + return -1; + sum += count; + count = xmlTextWriterEndComment(writer); + if (count < 0) + return -1; + sum += count; + + return sum; +} + +/** + * xmlTextWriterStartElement: + * @writer: the xmlTextWriterPtr + * @name: element name + * + * Start an xml element. + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int +xmlTextWriterStartElement(xmlTextWriterPtr writer, const xmlChar * name) +{ + int count; + int sum; + xmlLinkPtr lk; + xmlTextWriterStackEntry *p; + + if ((writer == NULL) || (name == NULL) || (*name == '\0')) + return -1; + + sum = 0; + lk = xmlListFront(writer->nodes); + if (lk != 0) { + p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk); + if (p != 0) { + switch (p->state) { + case XML_TEXTWRITER_PI: + case XML_TEXTWRITER_PI_TEXT: + return -1; + case XML_TEXTWRITER_NONE: + break; + case XML_TEXTWRITER_ATTRIBUTE: + count = xmlTextWriterEndAttribute(writer); + if (count < 0) + return -1; + sum += count; + /* fallthrough */ + case XML_TEXTWRITER_NAME: + count = xmlOutputBufferWriteString(writer->out, ">"); + if (count < 0) + return -1; + sum += count; + if (writer->indent) + count = + xmlOutputBufferWriteString(writer->out, "\n"); + p->state = XML_TEXTWRITER_TEXT; + break; + default: + break; + } + } + } + + p = (xmlTextWriterStackEntry *) + xmlMalloc(sizeof(xmlTextWriterStackEntry)); + if (p == 0) { + xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY, + "xmlTextWriterStartElement : out of memory!\n"); + return -1; + } + + p->name = xmlStrdup(name); + if (p->name == 0) { + xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY, + "xmlTextWriterStartElement : out of memory!\n"); + xmlFree(p); + return -1; + } + p->state = XML_TEXTWRITER_NAME; + + xmlListPushFront(writer->nodes, p); + + if (writer->indent) { + count = xmlTextWriterWriteIndent(writer); + sum += count; + } + + count = xmlOutputBufferWriteString(writer->out, "<"); + if (count < 0) + return -1; + sum += count; + count = + xmlOutputBufferWriteString(writer->out, (const char *) p->name); + if (count < 0) + return -1; + sum += count; + + return sum; +} + +/** + * xmlTextWriterStartElementNS: + * @writer: the xmlTextWriterPtr + * @prefix: namespace prefix or NULL + * @name: element local name + * @namespaceURI: namespace URI or NULL + * + * Start an xml element with namespace support. + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int +xmlTextWriterStartElementNS(xmlTextWriterPtr writer, + const xmlChar * prefix, const xmlChar * name, + const xmlChar * namespaceURI) +{ + int count; + int sum; + xmlChar *buf; + + if ((writer == NULL) || (name == NULL) || (*name == '\0')) + return -1; + + buf = NULL; + if (prefix != 0) { + buf = xmlStrdup(prefix); + buf = xmlStrcat(buf, BAD_CAST ":"); + } + buf = xmlStrcat(buf, name); + + sum = 0; + count = xmlTextWriterStartElement(writer, buf); + xmlFree(buf); + if (count < 0) + return -1; + sum += count; + + if (namespaceURI != 0) { + buf = xmlStrdup(BAD_CAST "xmlns"); + if (prefix != 0) { + buf = xmlStrcat(buf, BAD_CAST ":"); + buf = xmlStrcat(buf, prefix); + } + + count = xmlTextWriterWriteAttribute(writer, buf, namespaceURI); + xmlFree(buf); + if (count < 0) + return -1; + sum += count; + } + + return sum; +} + +/** + * xmlTextWriterEndElement: + * @writer: the xmlTextWriterPtr + * + * End the current xml element. + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int +xmlTextWriterEndElement(xmlTextWriterPtr writer) +{ + int count; + int sum; + xmlLinkPtr lk; + xmlTextWriterStackEntry *p; + + if (writer == NULL) + return -1; + + lk = xmlListFront(writer->nodes); + if (lk == 0) + return -1; + + p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk); + if (p == 0) + return -1; + + sum = 0; + switch (p->state) { + case XML_TEXTWRITER_ATTRIBUTE: + count = xmlTextWriterEndAttribute(writer); + if (count < 0) + return -1; + sum += count; + /* fallthrough */ + case XML_TEXTWRITER_NAME: + if (writer->indent) /* next element needs indent */ + writer->doindent = 1; + count = xmlOutputBufferWriteString(writer->out, "/>"); + if (count < 0) + return -1; + sum += count; + break; + case XML_TEXTWRITER_TEXT: + if ((writer->indent) && (writer->doindent)) { + count = xmlTextWriterWriteIndent(writer); + sum += count; + writer->doindent = 1; + } else + writer->doindent = 1; + count = xmlOutputBufferWriteString(writer->out, "out, + (const char *) p->name); + if (count < 0) + return -1; + sum += count; + count = xmlOutputBufferWriteString(writer->out, ">"); + if (count < 0) + return -1; + sum += count; + break; + default: + return -1; + } + + if (writer->indent) { + count = xmlOutputBufferWriteString(writer->out, "\n"); + sum += count; + } + + xmlListPopFront(writer->nodes); + return sum; +} + +/** + * xmlTextWriterFullEndElement: + * @writer: the xmlTextWriterPtr + * + * End the current xml element. Writes an end tag even if the element is empty + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int +xmlTextWriterFullEndElement(xmlTextWriterPtr writer) +{ + int count; + int sum; + xmlLinkPtr lk; + xmlTextWriterStackEntry *p; + + if (writer == NULL) + return -1; + + lk = xmlListFront(writer->nodes); + if (lk == 0) + return -1; + + p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk); + if (p == 0) + return -1; + + sum = 0; + switch (p->state) { + case XML_TEXTWRITER_ATTRIBUTE: + count = xmlTextWriterEndAttribute(writer); + if (count < 0) + return -1; + sum += count; + /* fallthrough */ + case XML_TEXTWRITER_NAME: + count = xmlOutputBufferWriteString(writer->out, ">"); + if (count < 0) + return -1; + sum += count; + /* fallthrough */ + case XML_TEXTWRITER_TEXT: + count = xmlOutputBufferWriteString(writer->out, "out, + (const char *) p->name); + if (count < 0) + return -1; + sum += count; + count = xmlOutputBufferWriteString(writer->out, ">"); + if (count < 0) + return -1; + sum += count; + break; + default: + return -1; + } + + xmlListPopFront(writer->nodes); + return sum; +} + +/** + * xmlTextWriterWriteFormatRaw: + * @writer: the xmlTextWriterPtr + * @format: format string (see printf) + * @...: extra parameters for the format + * + * Write a formatted raw xml text. + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int XMLCDECL +xmlTextWriterWriteFormatRaw(xmlTextWriterPtr writer, const char *format, + ...) +{ + int rc; + va_list ap; + + va_start(ap, format); + + rc = xmlTextWriterWriteVFormatRaw(writer, format, ap); + + va_end(ap); + return rc; +} + +/** + * xmlTextWriterWriteVFormatRaw: + * @writer: the xmlTextWriterPtr + * @format: format string (see printf) + * @argptr: pointer to the first member of the variable argument list. + * + * Write a formatted raw xml text. + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int +xmlTextWriterWriteVFormatRaw(xmlTextWriterPtr writer, const char *format, + va_list argptr) +{ + int rc; + xmlChar *buf; + + if (writer == NULL) + return -1; + + buf = xmlTextWriterVSprintf(format, argptr); + if (buf == 0) + return 0; + + rc = xmlTextWriterWriteRaw(writer, buf); + + xmlFree(buf); + return rc; +} + +/** + * xmlTextWriterWriteRawLen: + * @writer: the xmlTextWriterPtr + * @content: text string + * @len: length of the text string + * + * Write an xml text. + * TODO: what about entities and special chars?? + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int +xmlTextWriterWriteRawLen(xmlTextWriterPtr writer, const xmlChar * content, + int len) +{ + int count; + int sum; + xmlLinkPtr lk; + xmlTextWriterStackEntry *p; + + if (writer == NULL) { + xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR, + "xmlTextWriterWriteRawLen : invalid writer!\n"); + return -1; + } + + if ((content == NULL) || (len < 0)) { + xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR, + "xmlTextWriterWriteRawLen : invalid content!\n"); + return -1; + } + + sum = 0; + lk = xmlListFront(writer->nodes); + if (lk != 0) { + p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk); + count = xmlTextWriterHandleStateDependencies(writer, p); + if (count < 0) + return -1; + sum += count; + } + + if (writer->indent) + writer->doindent = 0; + + if (content != NULL) { + count = + xmlOutputBufferWrite(writer->out, len, (const char *) content); + if (count < 0) + return -1; + sum += count; + } + + return sum; +} + +/** + * xmlTextWriterWriteRaw: + * @writer: the xmlTextWriterPtr + * @content: text string + * + * Write a raw xml text. + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int +xmlTextWriterWriteRaw(xmlTextWriterPtr writer, const xmlChar * content) +{ + return xmlTextWriterWriteRawLen(writer, content, xmlStrlen(content)); +} + +/** + * xmlTextWriterWriteFormatString: + * @writer: the xmlTextWriterPtr + * @format: format string (see printf) + * @...: extra parameters for the format + * + * Write a formatted xml text. + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int XMLCDECL +xmlTextWriterWriteFormatString(xmlTextWriterPtr writer, const char *format, + ...) +{ + int rc; + va_list ap; + + if ((writer == NULL) || (format == NULL)) + return -1; + + va_start(ap, format); + + rc = xmlTextWriterWriteVFormatString(writer, format, ap); + + va_end(ap); + return rc; +} + +/** + * xmlTextWriterWriteVFormatString: + * @writer: the xmlTextWriterPtr + * @format: format string (see printf) + * @argptr: pointer to the first member of the variable argument list. + * + * Write a formatted xml text. + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int +xmlTextWriterWriteVFormatString(xmlTextWriterPtr writer, + const char *format, va_list argptr) +{ + int rc; + xmlChar *buf; + + if ((writer == NULL) || (format == NULL)) + return -1; + + buf = xmlTextWriterVSprintf(format, argptr); + if (buf == 0) + return 0; + + rc = xmlTextWriterWriteString(writer, buf); + + xmlFree(buf); + return rc; +} + +/** + * xmlTextWriterWriteString: + * @writer: the xmlTextWriterPtr + * @content: text string + * + * Write an xml text. + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int +xmlTextWriterWriteString(xmlTextWriterPtr writer, const xmlChar * content) +{ + int count; + int sum; + xmlLinkPtr lk; + xmlTextWriterStackEntry *p; + xmlChar *buf; + + if ((writer == NULL) || (content == NULL)) + return -1; + + sum = 0; + buf = (xmlChar *) content; + lk = xmlListFront(writer->nodes); + if (lk != 0) { + p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk); + if (p != 0) { + switch (p->state) { + case XML_TEXTWRITER_NAME: + case XML_TEXTWRITER_TEXT: +#if 0 + buf = NULL; + xmlOutputBufferWriteEscape(writer->out, content, NULL); +#endif + buf = xmlEncodeSpecialChars(NULL, content); + break; + case XML_TEXTWRITER_ATTRIBUTE: + buf = NULL; + xmlAttrSerializeTxtContent(writer->out->buffer, writer->doc, + NULL, content); + break; + default: + break; + } + } + } + + if (buf != NULL) { + count = xmlTextWriterWriteRaw(writer, buf); + if (count < 0) + return -1; + sum += count; + + if (buf != content) /* buf was allocated by us, so free it */ + xmlFree(buf); + } + + return sum; +} + +/** + * xmlOutputBufferWriteBase64: + * @out: the xmlOutputBufferPtr + * @data: binary data + * @len: the number of bytes to encode + * + * Write base64 encoded data to an xmlOutputBuffer. + * Adapted from John Walker's base64.c (http://www.fourmilab.ch/). + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +static int +xmlOutputBufferWriteBase64(xmlOutputBufferPtr out, int len, + const unsigned char *data) +{ + static unsigned char dtable[64] = + {'A','B','C','D','E','F','G','H','I','J','K','L','M', + 'N','O','P','Q','R','S','T','U','V','W','X','Y','Z', + 'a','b','c','d','e','f','g','h','i','j','k','l','m', + 'n','o','p','q','r','s','t','u','v','w','x','y','z', + '0','1','2','3','4','5','6','7','8','9','+','/'}; + + int i; + int linelen; + int count; + int sum; + + if ((out == NULL) || (len < 0) || (data == NULL)) + return(-1); + + linelen = 0; + sum = 0; + + i = 0; + while (1) { + unsigned char igroup[3]; + unsigned char ogroup[4]; + int c; + int n; + + igroup[0] = igroup[1] = igroup[2] = 0; + for (n = 0; n < 3 && i < len; n++, i++) { + c = data[i]; + igroup[n] = (unsigned char) c; + } + + if (n > 0) { + ogroup[0] = dtable[igroup[0] >> 2]; + ogroup[1] = dtable[((igroup[0] & 3) << 4) | (igroup[1] >> 4)]; + ogroup[2] = + dtable[((igroup[1] & 0xF) << 2) | (igroup[2] >> 6)]; + ogroup[3] = dtable[igroup[2] & 0x3F]; + + if (n < 3) { + ogroup[3] = '='; + if (n < 2) { + ogroup[2] = '='; + } + } + + if (linelen >= B64LINELEN) { + count = xmlOutputBufferWrite(out, 2, B64CRLF); + if (count == -1) + return -1; + sum += count; + linelen = 0; + } + count = xmlOutputBufferWrite(out, 4, (const char *) ogroup); + if (count == -1) + return -1; + sum += count; + + linelen += 4; + } + + if (i >= len) + break; + } + + return sum; +} + +/** + * xmlTextWriterWriteBase64: + * @writer: the xmlTextWriterPtr + * @data: binary data + * @start: the position within the data of the first byte to encode + * @len: the number of bytes to encode + * + * Write an base64 encoded xml text. + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int +xmlTextWriterWriteBase64(xmlTextWriterPtr writer, const char *data, + int start, int len) +{ + int count; + int sum; + xmlLinkPtr lk; + xmlTextWriterStackEntry *p; + + if ((writer == NULL) || (data == NULL) || (start < 0) || (len < 0)) + return -1; + + sum = 0; + lk = xmlListFront(writer->nodes); + if (lk != 0) { + p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk); + if (p != 0) { + count = xmlTextWriterHandleStateDependencies(writer, p); + if (count < 0) + return -1; + sum += count; + } + } + + if (writer->indent) + writer->doindent = 0; + + count = + xmlOutputBufferWriteBase64(writer->out, len, + (unsigned char *) data + start); + if (count < 0) + return -1; + sum += count; + + return sum; +} + +/** + * xmlOutputBufferWriteBinHex: + * @out: the xmlOutputBufferPtr + * @data: binary data + * @len: the number of bytes to encode + * + * Write hqx encoded data to an xmlOutputBuffer. + * ::todo + * + * Returns the bytes written (may be 0 because of buffering) + * or -1 in case of error + */ +static int +xmlOutputBufferWriteBinHex(xmlOutputBufferPtr out, + int len, const unsigned char *data) +{ + int count; + int sum; + static char hex[16] = + {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; + int i; + + if ((out == NULL) || (data == NULL) || (len < 0)) { + return -1; + } + + sum = 0; + for (i = 0; i < len; i++) { + count = + xmlOutputBufferWrite(out, 1, + (const char *) &hex[data[i] >> 4]); + if (count == -1) + return -1; + sum += count; + count = + xmlOutputBufferWrite(out, 1, + (const char *) &hex[data[i] & 0xF]); + if (count == -1) + return -1; + sum += count; + } + + return sum; +} + +/** + * xmlTextWriterWriteBinHex: + * @writer: the xmlTextWriterPtr + * @data: binary data + * @start: the position within the data of the first byte to encode + * @len: the number of bytes to encode + * + * Write a BinHex encoded xml text. + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int +xmlTextWriterWriteBinHex(xmlTextWriterPtr writer, const char *data, + int start, int len) +{ + int count; + int sum; + xmlLinkPtr lk; + xmlTextWriterStackEntry *p; + + if ((writer == NULL) || (data == NULL) || (start < 0) || (len < 0)) + return -1; + + sum = 0; + lk = xmlListFront(writer->nodes); + if (lk != 0) { + p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk); + if (p != 0) { + count = xmlTextWriterHandleStateDependencies(writer, p); + if (count < 0) + return -1; + sum += count; + } + } + + if (writer->indent) + writer->doindent = 0; + + count = + xmlOutputBufferWriteBinHex(writer->out, len, + (unsigned char *) data + start); + if (count < 0) + return -1; + sum += count; + + return sum; +} + +/** + * xmlTextWriterStartAttribute: + * @writer: the xmlTextWriterPtr + * @name: element name + * + * Start an xml attribute. + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int +xmlTextWriterStartAttribute(xmlTextWriterPtr writer, const xmlChar * name) +{ + int count; + int sum; + xmlLinkPtr lk; + xmlTextWriterStackEntry *p; + + if ((writer == NULL) || (name == NULL) || (*name == '\0')) + return -1; + + sum = 0; + lk = xmlListFront(writer->nodes); + if (lk == 0) + return -1; + + p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk); + if (p == 0) + return -1; + + switch (p->state) { + case XML_TEXTWRITER_ATTRIBUTE: + count = xmlTextWriterEndAttribute(writer); + if (count < 0) + return -1; + sum += count; + /* fallthrough */ + case XML_TEXTWRITER_NAME: + count = xmlOutputBufferWriteString(writer->out, " "); + if (count < 0) + return -1; + sum += count; + count = + xmlOutputBufferWriteString(writer->out, + (const char *) name); + if (count < 0) + return -1; + sum += count; + count = xmlOutputBufferWriteString(writer->out, "="); + if (count < 0) + return -1; + sum += count; + count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar); + if (count < 0) + return -1; + sum += count; + p->state = XML_TEXTWRITER_ATTRIBUTE; + break; + default: + return -1; + } + + return sum; +} + +/** + * xmlTextWriterStartAttributeNS: + * @writer: the xmlTextWriterPtr + * @prefix: namespace prefix or NULL + * @name: element local name + * @namespaceURI: namespace URI or NULL + * + * Start an xml attribute with namespace support. + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int +xmlTextWriterStartAttributeNS(xmlTextWriterPtr writer, + const xmlChar * prefix, const xmlChar * name, + const xmlChar * namespaceURI) +{ + int count; + int sum; + xmlChar *buf; + xmlTextWriterNsStackEntry *p; + + if ((writer == NULL) || (name == NULL) || (*name == '\0')) + return -1; + + buf = NULL; + if (prefix != 0) { + buf = xmlStrdup(prefix); + buf = xmlStrcat(buf, BAD_CAST ":"); + } + buf = xmlStrcat(buf, name); + + sum = 0; + count = xmlTextWriterStartAttribute(writer, buf); + xmlFree(buf); + if (count < 0) + return -1; + sum += count; + + if (namespaceURI != 0) { + buf = xmlStrdup(BAD_CAST "xmlns"); + if (prefix != 0) { + buf = xmlStrcat(buf, BAD_CAST ":"); + buf = xmlStrcat(buf, prefix); + } + + p = (xmlTextWriterNsStackEntry *) + xmlMalloc(sizeof(xmlTextWriterNsStackEntry)); + if (p == 0) { + xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY, + "xmlTextWriterStartAttributeNS : out of memory!\n"); + return -1; + } + + p->prefix = buf; + p->uri = xmlStrdup(namespaceURI); + if (p->uri == 0) { + xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY, + "xmlTextWriterStartAttributeNS : out of memory!\n"); + xmlFree(p); + return -1; + } + p->elem = xmlListFront(writer->nodes); + + xmlListPushFront(writer->nsstack, p); + } + + return sum; +} + +/** + * xmlTextWriterEndAttribute: + * @writer: the xmlTextWriterPtr + * + * End the current xml element. + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int +xmlTextWriterEndAttribute(xmlTextWriterPtr writer) +{ + int count; + int sum; + xmlLinkPtr lk; + xmlTextWriterStackEntry *p; + xmlTextWriterNsStackEntry *np; + + if (writer == NULL) + return -1; + + lk = xmlListFront(writer->nodes); + if (lk == 0) { + xmlListDelete(writer->nsstack); + writer->nsstack = NULL; + return -1; + } + + p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk); + if (p == 0) { + xmlListDelete(writer->nsstack); + writer->nsstack = NULL; + return -1; + } + + sum = 0; + switch (p->state) { + case XML_TEXTWRITER_ATTRIBUTE: + p->state = XML_TEXTWRITER_NAME; + + count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar); + if (count < 0) { + xmlListDelete(writer->nsstack); + writer->nsstack = NULL; + return -1; + } + sum += count; + + while (!xmlListEmpty(writer->nsstack)) { + xmlChar *namespaceURI = NULL; + xmlChar *prefix = NULL; + + lk = xmlListFront(writer->nsstack); + np = (xmlTextWriterNsStackEntry *) xmlLinkGetData(lk); + + if (np != 0) { + namespaceURI = xmlStrdup(np->uri); + prefix = xmlStrdup(np->prefix); + } + + xmlListPopFront(writer->nsstack); + + if (np != 0) { + count = + xmlTextWriterWriteAttribute(writer, prefix, + namespaceURI); + xmlFree(namespaceURI); + xmlFree(prefix); + + if (count < 0) { + xmlListDelete(writer->nsstack); + writer->nsstack = NULL; + return -1; + } + sum += count; + } + } + break; + + default: + xmlListClear(writer->nsstack); + return -1; + } + + return sum; +} + +/** + * xmlTextWriterWriteFormatAttribute: + * @writer: the xmlTextWriterPtr + * @name: attribute name + * @format: format string (see printf) + * @...: extra parameters for the format + * + * Write a formatted xml attribute. + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int XMLCDECL +xmlTextWriterWriteFormatAttribute(xmlTextWriterPtr writer, + const xmlChar * name, const char *format, + ...) +{ + int rc; + va_list ap; + + va_start(ap, format); + + rc = xmlTextWriterWriteVFormatAttribute(writer, name, format, ap); + + va_end(ap); + return rc; +} + +/** + * xmlTextWriterWriteVFormatAttribute: + * @writer: the xmlTextWriterPtr + * @name: attribute name + * @format: format string (see printf) + * @argptr: pointer to the first member of the variable argument list. + * + * Write a formatted xml attribute. + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int +xmlTextWriterWriteVFormatAttribute(xmlTextWriterPtr writer, + const xmlChar * name, + const char *format, va_list argptr) +{ + int rc; + xmlChar *buf; + + if (writer == NULL) + return -1; + + buf = xmlTextWriterVSprintf(format, argptr); + if (buf == 0) + return 0; + + rc = xmlTextWriterWriteAttribute(writer, name, buf); + + xmlFree(buf); + return rc; +} + +/** + * xmlTextWriterWriteAttribute: + * @writer: the xmlTextWriterPtr + * @name: attribute name + * @content: attribute content + * + * Write an xml attribute. + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int +xmlTextWriterWriteAttribute(xmlTextWriterPtr writer, const xmlChar * name, + const xmlChar * content) +{ + int count; + int sum; + + sum = 0; + count = xmlTextWriterStartAttribute(writer, name); + if (count < 0) + return -1; + sum += count; + count = xmlTextWriterWriteString(writer, content); + if (count < 0) + return -1; + sum += count; + count = xmlTextWriterEndAttribute(writer); + if (count < 0) + return -1; + sum += count; + + return sum; +} + +/** + * xmlTextWriterWriteFormatAttributeNS: + * @writer: the xmlTextWriterPtr + * @prefix: namespace prefix + * @name: attribute local name + * @namespaceURI: namespace URI + * @format: format string (see printf) + * @...: extra parameters for the format + * + * Write a formatted xml attribute.with namespace support + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int XMLCDECL +xmlTextWriterWriteFormatAttributeNS(xmlTextWriterPtr writer, + const xmlChar * prefix, + const xmlChar * name, + const xmlChar * namespaceURI, + const char *format, ...) +{ + int rc; + va_list ap; + + va_start(ap, format); + + rc = xmlTextWriterWriteVFormatAttributeNS(writer, prefix, name, + namespaceURI, format, ap); + + va_end(ap); + return rc; +} + +/** + * xmlTextWriterWriteVFormatAttributeNS: + * @writer: the xmlTextWriterPtr + * @prefix: namespace prefix + * @name: attribute local name + * @namespaceURI: namespace URI + * @format: format string (see printf) + * @argptr: pointer to the first member of the variable argument list. + * + * Write a formatted xml attribute.with namespace support + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int +xmlTextWriterWriteVFormatAttributeNS(xmlTextWriterPtr writer, + const xmlChar * prefix, + const xmlChar * name, + const xmlChar * namespaceURI, + const char *format, va_list argptr) +{ + int rc; + xmlChar *buf; + + if (writer == NULL) + return -1; + + buf = xmlTextWriterVSprintf(format, argptr); + if (buf == 0) + return 0; + + rc = xmlTextWriterWriteAttributeNS(writer, prefix, name, namespaceURI, + buf); + + xmlFree(buf); + return rc; +} + +/** + * xmlTextWriterWriteAttributeNS: + * @writer: the xmlTextWriterPtr + * @prefix: namespace prefix + * @name: attribute local name + * @namespaceURI: namespace URI + * @content: attribute content + * + * Write an xml attribute. + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int +xmlTextWriterWriteAttributeNS(xmlTextWriterPtr writer, + const xmlChar * prefix, const xmlChar * name, + const xmlChar * namespaceURI, + const xmlChar * content) +{ + int count; + int sum; + xmlChar *buf; + + if ((writer == NULL) || (name == NULL) || (*name == '\0')) + return -1; + + buf = NULL; + if (prefix != NULL) { + buf = xmlStrdup(prefix); + buf = xmlStrcat(buf, BAD_CAST ":"); + } + buf = xmlStrcat(buf, name); + + sum = 0; + count = xmlTextWriterWriteAttribute(writer, buf, content); + xmlFree(buf); + if (count < 0) + return -1; + sum += count; + + if (namespaceURI != NULL) { + buf = NULL; + buf = xmlStrdup(BAD_CAST "xmlns"); + if (prefix != NULL) { + buf = xmlStrcat(buf, BAD_CAST ":"); + buf = xmlStrcat(buf, prefix); + } + count = xmlTextWriterWriteAttribute(writer, buf, namespaceURI); + xmlFree(buf); + if (count < 0) + return -1; + sum += count; + } + return sum; +} + +/** + * xmlTextWriterWriteFormatElement: + * @writer: the xmlTextWriterPtr + * @name: element name + * @format: format string (see printf) + * @...: extra parameters for the format + * + * Write a formatted xml element. + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int XMLCDECL +xmlTextWriterWriteFormatElement(xmlTextWriterPtr writer, + const xmlChar * name, const char *format, + ...) +{ + int rc; + va_list ap; + + va_start(ap, format); + + rc = xmlTextWriterWriteVFormatElement(writer, name, format, ap); + + va_end(ap); + return rc; +} + +/** + * xmlTextWriterWriteVFormatElement: + * @writer: the xmlTextWriterPtr + * @name: element name + * @format: format string (see printf) + * @argptr: pointer to the first member of the variable argument list. + * + * Write a formatted xml element. + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int +xmlTextWriterWriteVFormatElement(xmlTextWriterPtr writer, + const xmlChar * name, const char *format, + va_list argptr) +{ + int rc; + xmlChar *buf; + + if (writer == NULL) + return -1; + + buf = xmlTextWriterVSprintf(format, argptr); + if (buf == 0) + return 0; + + rc = xmlTextWriterWriteElement(writer, name, buf); + + xmlFree(buf); + return rc; +} + +/** + * xmlTextWriterWriteElement: + * @writer: the xmlTextWriterPtr + * @name: element name + * @content: element content + * + * Write an xml element. + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int +xmlTextWriterWriteElement(xmlTextWriterPtr writer, const xmlChar * name, + const xmlChar * content) +{ + int count; + int sum; + + sum = 0; + count = xmlTextWriterStartElement(writer, name); + if (count == -1) + return -1; + sum += count; + count = xmlTextWriterWriteString(writer, content); + if (count == -1) + return -1; + sum += count; + count = xmlTextWriterEndElement(writer); + if (count == -1) + return -1; + sum += count; + + return sum; +} + +/** + * xmlTextWriterWriteFormatElementNS: + * @writer: the xmlTextWriterPtr + * @prefix: namespace prefix + * @name: element local name + * @namespaceURI: namespace URI + * @format: format string (see printf) + * @...: extra parameters for the format + * + * Write a formatted xml element with namespace support. + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int XMLCDECL +xmlTextWriterWriteFormatElementNS(xmlTextWriterPtr writer, + const xmlChar * prefix, + const xmlChar * name, + const xmlChar * namespaceURI, + const char *format, ...) +{ + int rc; + va_list ap; + + va_start(ap, format); + + rc = xmlTextWriterWriteVFormatElementNS(writer, prefix, name, + namespaceURI, format, ap); + + va_end(ap); + return rc; +} + +/** + * xmlTextWriterWriteVFormatElementNS: + * @writer: the xmlTextWriterPtr + * @prefix: namespace prefix + * @name: element local name + * @namespaceURI: namespace URI + * @format: format string (see printf) + * @argptr: pointer to the first member of the variable argument list. + * + * Write a formatted xml element with namespace support. + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int +xmlTextWriterWriteVFormatElementNS(xmlTextWriterPtr writer, + const xmlChar * prefix, + const xmlChar * name, + const xmlChar * namespaceURI, + const char *format, va_list argptr) +{ + int rc; + xmlChar *buf; + + if (writer == NULL) + return -1; + + buf = xmlTextWriterVSprintf(format, argptr); + if (buf == 0) + return 0; + + rc = xmlTextWriterWriteElementNS(writer, prefix, name, namespaceURI, + buf); + + xmlFree(buf); + return rc; +} + +/** + * xmlTextWriterWriteElementNS: + * @writer: the xmlTextWriterPtr + * @prefix: namespace prefix + * @name: element local name + * @namespaceURI: namespace URI + * @content: element content + * + * Write an xml element with namespace support. + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int +xmlTextWriterWriteElementNS(xmlTextWriterPtr writer, + const xmlChar * prefix, const xmlChar * name, + const xmlChar * namespaceURI, + const xmlChar * content) +{ + int count; + int sum; + + if ((writer == NULL) || (name == NULL) || (*name == '\0')) + return -1; + + sum = 0; + count = + xmlTextWriterStartElementNS(writer, prefix, name, namespaceURI); + if (count < 0) + return -1; + sum += count; + count = xmlTextWriterWriteString(writer, content); + if (count == -1) + return -1; + sum += count; + count = xmlTextWriterEndElement(writer); + if (count == -1) + return -1; + sum += count; + + return sum; +} + +/** + * xmlTextWriterStartPI: + * @writer: the xmlTextWriterPtr + * @target: PI target + * + * Start an xml PI. + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int +xmlTextWriterStartPI(xmlTextWriterPtr writer, const xmlChar * target) +{ + int count; + int sum; + xmlLinkPtr lk; + xmlTextWriterStackEntry *p; + + if ((writer == NULL) || (target == NULL) || (*target == '\0')) + return -1; + + if (xmlStrcasecmp(target, (const xmlChar *) "xml") == 0) { + xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR, + "xmlTextWriterStartPI : target name [Xx][Mm][Ll] is reserved for xml standardization!\n"); + return -1; + } + + sum = 0; + lk = xmlListFront(writer->nodes); + if (lk != 0) { + p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk); + if (p != 0) { + switch (p->state) { + case XML_TEXTWRITER_ATTRIBUTE: + count = xmlTextWriterEndAttribute(writer); + if (count < 0) + return -1; + sum += count; + /* fallthrough */ + case XML_TEXTWRITER_NAME: + count = xmlOutputBufferWriteString(writer->out, ">"); + if (count < 0) + return -1; + sum += count; + p->state = XML_TEXTWRITER_TEXT; + break; + case XML_TEXTWRITER_NONE: + case XML_TEXTWRITER_TEXT: + case XML_TEXTWRITER_DTD: + break; + case XML_TEXTWRITER_PI: + case XML_TEXTWRITER_PI_TEXT: + xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR, + "xmlTextWriterStartPI : nested PI!\n"); + return -1; + default: + return -1; + } + } + } + + p = (xmlTextWriterStackEntry *) + xmlMalloc(sizeof(xmlTextWriterStackEntry)); + if (p == 0) { + xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY, + "xmlTextWriterStartPI : out of memory!\n"); + return -1; + } + + p->name = xmlStrdup(target); + if (p->name == 0) { + xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY, + "xmlTextWriterStartPI : out of memory!\n"); + xmlFree(p); + return -1; + } + p->state = XML_TEXTWRITER_PI; + + xmlListPushFront(writer->nodes, p); + + count = xmlOutputBufferWriteString(writer->out, "out, (const char *) p->name); + if (count < 0) + return -1; + sum += count; + + return sum; +} + +/** + * xmlTextWriterEndPI: + * @writer: the xmlTextWriterPtr + * + * End the current xml PI. + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int +xmlTextWriterEndPI(xmlTextWriterPtr writer) +{ + int count; + int sum; + xmlLinkPtr lk; + xmlTextWriterStackEntry *p; + + if (writer == NULL) + return -1; + + lk = xmlListFront(writer->nodes); + if (lk == 0) + return 0; + + p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk); + if (p == 0) + return 0; + + sum = 0; + switch (p->state) { + case XML_TEXTWRITER_PI: + case XML_TEXTWRITER_PI_TEXT: + count = xmlOutputBufferWriteString(writer->out, "?>"); + if (count < 0) + return -1; + sum += count; + break; + default: + return -1; + } + + if (writer->indent) { + count = xmlOutputBufferWriteString(writer->out, "\n"); + if (count < 0) + return -1; + sum += count; + } + + xmlListPopFront(writer->nodes); + return sum; +} + +/** + * xmlTextWriterWriteFormatPI: + * @writer: the xmlTextWriterPtr + * @target: PI target + * @format: format string (see printf) + * @...: extra parameters for the format + * + * Write a formatted PI. + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int XMLCDECL +xmlTextWriterWriteFormatPI(xmlTextWriterPtr writer, const xmlChar * target, + const char *format, ...) +{ + int rc; + va_list ap; + + va_start(ap, format); + + rc = xmlTextWriterWriteVFormatPI(writer, target, format, ap); + + va_end(ap); + return rc; +} + +/** + * xmlTextWriterWriteVFormatPI: + * @writer: the xmlTextWriterPtr + * @target: PI target + * @format: format string (see printf) + * @argptr: pointer to the first member of the variable argument list. + * + * Write a formatted xml PI. + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int +xmlTextWriterWriteVFormatPI(xmlTextWriterPtr writer, + const xmlChar * target, const char *format, + va_list argptr) +{ + int rc; + xmlChar *buf; + + if (writer == NULL) + return -1; + + buf = xmlTextWriterVSprintf(format, argptr); + if (buf == 0) + return 0; + + rc = xmlTextWriterWritePI(writer, target, buf); + + xmlFree(buf); + return rc; +} + +/** + * xmlTextWriterWritePI: + * @writer: the xmlTextWriterPtr + * @target: PI target + * @content: PI content + * + * Write an xml PI. + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int +xmlTextWriterWritePI(xmlTextWriterPtr writer, const xmlChar * target, + const xmlChar * content) +{ + int count; + int sum; + + sum = 0; + count = xmlTextWriterStartPI(writer, target); + if (count == -1) + return -1; + sum += count; + if (content != 0) { + count = xmlTextWriterWriteString(writer, content); + if (count == -1) + return -1; + sum += count; + } + count = xmlTextWriterEndPI(writer); + if (count == -1) + return -1; + sum += count; + + return sum; +} + +/** + * xmlTextWriterStartCDATA: + * @writer: the xmlTextWriterPtr + * + * Start an xml CDATA section. + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int +xmlTextWriterStartCDATA(xmlTextWriterPtr writer) +{ + int count; + int sum; + xmlLinkPtr lk; + xmlTextWriterStackEntry *p; + + if (writer == NULL) + return -1; + + sum = 0; + lk = xmlListFront(writer->nodes); + if (lk != 0) { + p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk); + if (p != 0) { + switch (p->state) { + case XML_TEXTWRITER_NONE: + case XML_TEXTWRITER_PI: + case XML_TEXTWRITER_PI_TEXT: + break; + case XML_TEXTWRITER_ATTRIBUTE: + count = xmlTextWriterEndAttribute(writer); + if (count < 0) + return -1; + sum += count; + /* fallthrough */ + case XML_TEXTWRITER_NAME: + count = xmlOutputBufferWriteString(writer->out, ">"); + if (count < 0) + return -1; + sum += count; + p->state = XML_TEXTWRITER_TEXT; + break; + case XML_TEXTWRITER_CDATA: + xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR, + "xmlTextWriterStartCDATA : CDATA not allowed in this context!\n"); + return -1; + default: + return -1; + } + } + } + + p = (xmlTextWriterStackEntry *) + xmlMalloc(sizeof(xmlTextWriterStackEntry)); + if (p == 0) { + xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY, + "xmlTextWriterStartCDATA : out of memory!\n"); + return -1; + } + + p->name = NULL; + p->state = XML_TEXTWRITER_CDATA; + + xmlListPushFront(writer->nodes, p); + + count = xmlOutputBufferWriteString(writer->out, "nodes); + if (lk == 0) + return -1; + + p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk); + if (p == 0) + return -1; + + sum = 0; + switch (p->state) { + case XML_TEXTWRITER_CDATA: + count = xmlOutputBufferWriteString(writer->out, "]]>"); + if (count < 0) + return -1; + sum += count; + break; + default: + return -1; + } + + xmlListPopFront(writer->nodes); + return sum; +} + +/** + * xmlTextWriterWriteFormatCDATA: + * @writer: the xmlTextWriterPtr + * @format: format string (see printf) + * @...: extra parameters for the format + * + * Write a formatted xml CDATA. + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int XMLCDECL +xmlTextWriterWriteFormatCDATA(xmlTextWriterPtr writer, const char *format, + ...) +{ + int rc; + va_list ap; + + va_start(ap, format); + + rc = xmlTextWriterWriteVFormatCDATA(writer, format, ap); + + va_end(ap); + return rc; +} + +/** + * xmlTextWriterWriteVFormatCDATA: + * @writer: the xmlTextWriterPtr + * @format: format string (see printf) + * @argptr: pointer to the first member of the variable argument list. + * + * Write a formatted xml CDATA. + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int +xmlTextWriterWriteVFormatCDATA(xmlTextWriterPtr writer, const char *format, + va_list argptr) +{ + int rc; + xmlChar *buf; + + if (writer == NULL) + return -1; + + buf = xmlTextWriterVSprintf(format, argptr); + if (buf == 0) + return 0; + + rc = xmlTextWriterWriteCDATA(writer, buf); + + xmlFree(buf); + return rc; +} + +/** + * xmlTextWriterWriteCDATA: + * @writer: the xmlTextWriterPtr + * @content: CDATA content + * + * Write an xml CDATA. + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int +xmlTextWriterWriteCDATA(xmlTextWriterPtr writer, const xmlChar * content) +{ + int count; + int sum; + + sum = 0; + count = xmlTextWriterStartCDATA(writer); + if (count == -1) + return -1; + sum += count; + if (content != 0) { + count = xmlTextWriterWriteString(writer, content); + if (count == -1) + return -1; + sum += count; + } + count = xmlTextWriterEndCDATA(writer); + if (count == -1) + return -1; + sum += count; + + return sum; +} + +/** + * xmlTextWriterStartDTD: + * @writer: the xmlTextWriterPtr + * @name: the name of the DTD + * @pubid: the public identifier, which is an alternative to the system identifier + * @sysid: the system identifier, which is the URI of the DTD + * + * Start an xml DTD. + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int +xmlTextWriterStartDTD(xmlTextWriterPtr writer, + const xmlChar * name, + const xmlChar * pubid, const xmlChar * sysid) +{ + int count; + int sum; + xmlLinkPtr lk; + xmlTextWriterStackEntry *p; + + if (writer == NULL || name == NULL || *name == '\0') + return -1; + + sum = 0; + lk = xmlListFront(writer->nodes); + if ((lk != NULL) && (xmlLinkGetData(lk) != NULL)) { + xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR, + "xmlTextWriterStartDTD : DTD allowed only in prolog!\n"); + return -1; + } + + p = (xmlTextWriterStackEntry *) + xmlMalloc(sizeof(xmlTextWriterStackEntry)); + if (p == 0) { + xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY, + "xmlTextWriterStartDTD : out of memory!\n"); + return -1; + } + + p->name = xmlStrdup(name); + if (p->name == 0) { + xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY, + "xmlTextWriterStartDTD : out of memory!\n"); + xmlFree(p); + return -1; + } + p->state = XML_TEXTWRITER_DTD; + + xmlListPushFront(writer->nodes, p); + + count = xmlOutputBufferWriteString(writer->out, "out, (const char *) name); + if (count < 0) + return -1; + sum += count; + + if (pubid != 0) { + if (sysid == 0) { + xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR, + "xmlTextWriterStartDTD : system identifier needed!\n"); + return -1; + } + + if (writer->indent) + count = xmlOutputBufferWrite(writer->out, 1, "\n"); + else + count = xmlOutputBufferWrite(writer->out, 1, " "); + if (count < 0) + return -1; + sum += count; + + count = xmlOutputBufferWriteString(writer->out, "PUBLIC "); + if (count < 0) + return -1; + sum += count; + + count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar); + if (count < 0) + return -1; + sum += count; + + count = + xmlOutputBufferWriteString(writer->out, (const char *) pubid); + if (count < 0) + return -1; + sum += count; + + count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar); + if (count < 0) + return -1; + sum += count; + } + + if (sysid != 0) { + if (pubid == 0) { + if (writer->indent) + count = xmlOutputBufferWrite(writer->out, 1, "\n"); + else + count = xmlOutputBufferWrite(writer->out, 1, " "); + if (count < 0) + return -1; + sum += count; + count = xmlOutputBufferWriteString(writer->out, "SYSTEM "); + if (count < 0) + return -1; + sum += count; + } else { + if (writer->indent) + count = xmlOutputBufferWriteString(writer->out, "\n "); + else + count = xmlOutputBufferWrite(writer->out, 1, " "); + if (count < 0) + return -1; + sum += count; + } + + count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar); + if (count < 0) + return -1; + sum += count; + + count = + xmlOutputBufferWriteString(writer->out, (const char *) sysid); + if (count < 0) + return -1; + sum += count; + + count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar); + if (count < 0) + return -1; + sum += count; + } + + return sum; +} + +/** + * xmlTextWriterEndDTD: + * @writer: the xmlTextWriterPtr + * + * End an xml DTD. + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int +xmlTextWriterEndDTD(xmlTextWriterPtr writer) +{ + int loop; + int count; + int sum; + xmlLinkPtr lk; + xmlTextWriterStackEntry *p; + + if (writer == NULL) + return -1; + + sum = 0; + loop = 1; + while (loop) { + lk = xmlListFront(writer->nodes); + if (lk == NULL) + break; + p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk); + if (p == 0) + break; + switch (p->state) { + case XML_TEXTWRITER_DTD_TEXT: + count = xmlOutputBufferWriteString(writer->out, "]"); + if (count < 0) + return -1; + sum += count; + /* fallthrough */ + case XML_TEXTWRITER_DTD: + count = xmlOutputBufferWriteString(writer->out, ">"); + + if (writer->indent) { + if (count < 0) + return -1; + sum += count; + count = xmlOutputBufferWriteString(writer->out, "\n"); + } + + xmlListPopFront(writer->nodes); + break; + case XML_TEXTWRITER_DTD_ELEM: + case XML_TEXTWRITER_DTD_ELEM_TEXT: + count = xmlTextWriterEndDTDElement(writer); + break; + case XML_TEXTWRITER_DTD_ATTL: + case XML_TEXTWRITER_DTD_ATTL_TEXT: + count = xmlTextWriterEndDTDAttlist(writer); + break; + case XML_TEXTWRITER_DTD_ENTY: + case XML_TEXTWRITER_DTD_PENT: + case XML_TEXTWRITER_DTD_ENTY_TEXT: + count = xmlTextWriterEndDTDEntity(writer); + break; + case XML_TEXTWRITER_COMMENT: + count = xmlTextWriterEndComment(writer); + break; + default: + loop = 0; + continue; + } + + if (count < 0) + return -1; + sum += count; + } + + return sum; +} + +/** + * xmlTextWriterWriteFormatDTD: + * @writer: the xmlTextWriterPtr + * @name: the name of the DTD + * @pubid: the public identifier, which is an alternative to the system identifier + * @sysid: the system identifier, which is the URI of the DTD + * @format: format string (see printf) + * @...: extra parameters for the format + * + * Write a DTD with a formatted markup declarations part. + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int XMLCDECL +xmlTextWriterWriteFormatDTD(xmlTextWriterPtr writer, + const xmlChar * name, + const xmlChar * pubid, + const xmlChar * sysid, const char *format, ...) +{ + int rc; + va_list ap; + + va_start(ap, format); + + rc = xmlTextWriterWriteVFormatDTD(writer, name, pubid, sysid, format, + ap); + + va_end(ap); + return rc; +} + +/** + * xmlTextWriterWriteVFormatDTD: + * @writer: the xmlTextWriterPtr + * @name: the name of the DTD + * @pubid: the public identifier, which is an alternative to the system identifier + * @sysid: the system identifier, which is the URI of the DTD + * @format: format string (see printf) + * @argptr: pointer to the first member of the variable argument list. + * + * Write a DTD with a formatted markup declarations part. + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int +xmlTextWriterWriteVFormatDTD(xmlTextWriterPtr writer, + const xmlChar * name, + const xmlChar * pubid, + const xmlChar * sysid, + const char *format, va_list argptr) +{ + int rc; + xmlChar *buf; + + if (writer == NULL) + return -1; + + buf = xmlTextWriterVSprintf(format, argptr); + if (buf == 0) + return 0; + + rc = xmlTextWriterWriteDTD(writer, name, pubid, sysid, buf); + + xmlFree(buf); + return rc; +} + +/** + * xmlTextWriterWriteDTD: + * @writer: the xmlTextWriterPtr + * @name: the name of the DTD + * @pubid: the public identifier, which is an alternative to the system identifier + * @sysid: the system identifier, which is the URI of the DTD + * @subset: string content of the DTD + * + * Write a DTD. + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int +xmlTextWriterWriteDTD(xmlTextWriterPtr writer, + const xmlChar * name, + const xmlChar * pubid, + const xmlChar * sysid, const xmlChar * subset) +{ + int count; + int sum; + + sum = 0; + count = xmlTextWriterStartDTD(writer, name, pubid, sysid); + if (count == -1) + return -1; + sum += count; + if (subset != 0) { + count = xmlTextWriterWriteString(writer, subset); + if (count == -1) + return -1; + sum += count; + } + count = xmlTextWriterEndDTD(writer); + if (count == -1) + return -1; + sum += count; + + return sum; +} + +/** + * xmlTextWriterStartDTDElement: + * @writer: the xmlTextWriterPtr + * @name: the name of the DTD element + * + * Start an xml DTD element. + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int +xmlTextWriterStartDTDElement(xmlTextWriterPtr writer, const xmlChar * name) +{ + int count; + int sum; + xmlLinkPtr lk; + xmlTextWriterStackEntry *p; + + if (writer == NULL || name == NULL || *name == '\0') + return -1; + + sum = 0; + lk = xmlListFront(writer->nodes); + if (lk == 0) { + return -1; + } + + p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk); + if (p != 0) { + switch (p->state) { + case XML_TEXTWRITER_DTD: + count = xmlOutputBufferWriteString(writer->out, " ["); + if (count < 0) + return -1; + sum += count; + if (writer->indent) { + count = xmlOutputBufferWriteString(writer->out, "\n"); + if (count < 0) + return -1; + sum += count; + } + p->state = XML_TEXTWRITER_DTD_TEXT; + /* fallthrough */ + case XML_TEXTWRITER_DTD_TEXT: + case XML_TEXTWRITER_NONE: + break; + default: + return -1; + } + } + + p = (xmlTextWriterStackEntry *) + xmlMalloc(sizeof(xmlTextWriterStackEntry)); + if (p == 0) { + xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY, + "xmlTextWriterStartDTDElement : out of memory!\n"); + return -1; + } + + p->name = xmlStrdup(name); + if (p->name == 0) { + xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY, + "xmlTextWriterStartDTDElement : out of memory!\n"); + xmlFree(p); + return -1; + } + p->state = XML_TEXTWRITER_DTD_ELEM; + + xmlListPushFront(writer->nodes, p); + + if (writer->indent) { + count = xmlTextWriterWriteIndent(writer); + if (count < 0) + return -1; + sum += count; + } + + count = xmlOutputBufferWriteString(writer->out, "out, (const char *) name); + if (count < 0) + return -1; + sum += count; + + return sum; +} + +/** + * xmlTextWriterEndDTDElement: + * @writer: the xmlTextWriterPtr + * + * End an xml DTD element. + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int +xmlTextWriterEndDTDElement(xmlTextWriterPtr writer) +{ + int count; + int sum; + xmlLinkPtr lk; + xmlTextWriterStackEntry *p; + + if (writer == NULL) + return -1; + + sum = 0; + lk = xmlListFront(writer->nodes); + if (lk == 0) + return -1; + + p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk); + if (p == 0) + return -1; + + switch (p->state) { + case XML_TEXTWRITER_DTD_ELEM: + case XML_TEXTWRITER_DTD_ELEM_TEXT: + count = xmlOutputBufferWriteString(writer->out, ">"); + if (count < 0) + return -1; + sum += count; + break; + default: + return -1; + } + + if (writer->indent) { + count = xmlOutputBufferWriteString(writer->out, "\n"); + if (count < 0) + return -1; + sum += count; + } + + xmlListPopFront(writer->nodes); + return sum; +} + +/** + * xmlTextWriterWriteFormatDTDElement: + * @writer: the xmlTextWriterPtr + * @name: the name of the DTD element + * @format: format string (see printf) + * @...: extra parameters for the format + * + * Write a formatted DTD element. + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int XMLCDECL +xmlTextWriterWriteFormatDTDElement(xmlTextWriterPtr writer, + const xmlChar * name, + const char *format, ...) +{ + int rc; + va_list ap; + + va_start(ap, format); + + rc = xmlTextWriterWriteVFormatDTDElement(writer, name, format, ap); + + va_end(ap); + return rc; +} + +/** + * xmlTextWriterWriteVFormatDTDElement: + * @writer: the xmlTextWriterPtr + * @name: the name of the DTD element + * @format: format string (see printf) + * @argptr: pointer to the first member of the variable argument list. + * + * Write a formatted DTD element. + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int +xmlTextWriterWriteVFormatDTDElement(xmlTextWriterPtr writer, + const xmlChar * name, + const char *format, va_list argptr) +{ + int rc; + xmlChar *buf; + + if (writer == NULL) + return -1; + + buf = xmlTextWriterVSprintf(format, argptr); + if (buf == 0) + return 0; + + rc = xmlTextWriterWriteDTDElement(writer, name, buf); + + xmlFree(buf); + return rc; +} + +/** + * xmlTextWriterWriteDTDElement: + * @writer: the xmlTextWriterPtr + * @name: the name of the DTD element + * @content: content of the element + * + * Write a DTD element. + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int +xmlTextWriterWriteDTDElement(xmlTextWriterPtr writer, + const xmlChar * name, const xmlChar * content) +{ + int count; + int sum; + + if (content == NULL) + return -1; + + sum = 0; + count = xmlTextWriterStartDTDElement(writer, name); + if (count == -1) + return -1; + sum += count; + + count = xmlTextWriterWriteString(writer, content); + if (count == -1) + return -1; + sum += count; + + count = xmlTextWriterEndDTDElement(writer); + if (count == -1) + return -1; + sum += count; + + return sum; +} + +/** + * xmlTextWriterStartDTDAttlist: + * @writer: the xmlTextWriterPtr + * @name: the name of the DTD ATTLIST + * + * Start an xml DTD ATTLIST. + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int +xmlTextWriterStartDTDAttlist(xmlTextWriterPtr writer, const xmlChar * name) +{ + int count; + int sum; + xmlLinkPtr lk; + xmlTextWriterStackEntry *p; + + if (writer == NULL || name == NULL || *name == '\0') + return -1; + + sum = 0; + lk = xmlListFront(writer->nodes); + if (lk == 0) { + return -1; + } + + p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk); + if (p != 0) { + switch (p->state) { + case XML_TEXTWRITER_DTD: + count = xmlOutputBufferWriteString(writer->out, " ["); + if (count < 0) + return -1; + sum += count; + if (writer->indent) { + count = xmlOutputBufferWriteString(writer->out, "\n"); + if (count < 0) + return -1; + sum += count; + } + p->state = XML_TEXTWRITER_DTD_TEXT; + /* fallthrough */ + case XML_TEXTWRITER_DTD_TEXT: + case XML_TEXTWRITER_NONE: + break; + default: + return -1; + } + } + + p = (xmlTextWriterStackEntry *) + xmlMalloc(sizeof(xmlTextWriterStackEntry)); + if (p == 0) { + xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY, + "xmlTextWriterStartDTDAttlist : out of memory!\n"); + return -1; + } + + p->name = xmlStrdup(name); + if (p->name == 0) { + xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY, + "xmlTextWriterStartDTDAttlist : out of memory!\n"); + xmlFree(p); + return -1; + } + p->state = XML_TEXTWRITER_DTD_ATTL; + + xmlListPushFront(writer->nodes, p); + + if (writer->indent) { + count = xmlTextWriterWriteIndent(writer); + if (count < 0) + return -1; + sum += count; + } + + count = xmlOutputBufferWriteString(writer->out, "out, (const char *) name); + if (count < 0) + return -1; + sum += count; + + return sum; +} + +/** + * xmlTextWriterEndDTDAttlist: + * @writer: the xmlTextWriterPtr + * + * End an xml DTD attribute list. + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int +xmlTextWriterEndDTDAttlist(xmlTextWriterPtr writer) +{ + int count; + int sum; + xmlLinkPtr lk; + xmlTextWriterStackEntry *p; + + if (writer == NULL) + return -1; + + sum = 0; + lk = xmlListFront(writer->nodes); + if (lk == 0) + return -1; + + p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk); + if (p == 0) + return -1; + + switch (p->state) { + case XML_TEXTWRITER_DTD_ATTL: + case XML_TEXTWRITER_DTD_ATTL_TEXT: + count = xmlOutputBufferWriteString(writer->out, ">"); + if (count < 0) + return -1; + sum += count; + break; + default: + return -1; + } + + if (writer->indent) { + count = xmlOutputBufferWriteString(writer->out, "\n"); + if (count < 0) + return -1; + sum += count; + } + + xmlListPopFront(writer->nodes); + return sum; +} + +/** + * xmlTextWriterWriteFormatDTDAttlist: + * @writer: the xmlTextWriterPtr + * @name: the name of the DTD ATTLIST + * @format: format string (see printf) + * @...: extra parameters for the format + * + * Write a formatted DTD ATTLIST. + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int XMLCDECL +xmlTextWriterWriteFormatDTDAttlist(xmlTextWriterPtr writer, + const xmlChar * name, + const char *format, ...) +{ + int rc; + va_list ap; + + va_start(ap, format); + + rc = xmlTextWriterWriteVFormatDTDAttlist(writer, name, format, ap); + + va_end(ap); + return rc; +} + +/** + * xmlTextWriterWriteVFormatDTDAttlist: + * @writer: the xmlTextWriterPtr + * @name: the name of the DTD ATTLIST + * @format: format string (see printf) + * @argptr: pointer to the first member of the variable argument list. + * + * Write a formatted DTD ATTLIST. + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int +xmlTextWriterWriteVFormatDTDAttlist(xmlTextWriterPtr writer, + const xmlChar * name, + const char *format, va_list argptr) +{ + int rc; + xmlChar *buf; + + if (writer == NULL) + return -1; + + buf = xmlTextWriterVSprintf(format, argptr); + if (buf == 0) + return 0; + + rc = xmlTextWriterWriteDTDAttlist(writer, name, buf); + + xmlFree(buf); + return rc; +} + +/** + * xmlTextWriterWriteDTDAttlist: + * @writer: the xmlTextWriterPtr + * @name: the name of the DTD ATTLIST + * @content: content of the ATTLIST + * + * Write a DTD ATTLIST. + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int +xmlTextWriterWriteDTDAttlist(xmlTextWriterPtr writer, + const xmlChar * name, const xmlChar * content) +{ + int count; + int sum; + + if (content == NULL) + return -1; + + sum = 0; + count = xmlTextWriterStartDTDAttlist(writer, name); + if (count == -1) + return -1; + sum += count; + + count = xmlTextWriterWriteString(writer, content); + if (count == -1) + return -1; + sum += count; + + count = xmlTextWriterEndDTDAttlist(writer); + if (count == -1) + return -1; + sum += count; + + return sum; +} + +/** + * xmlTextWriterStartDTDEntity: + * @writer: the xmlTextWriterPtr + * @pe: TRUE if this is a parameter entity, FALSE if not + * @name: the name of the DTD ATTLIST + * + * Start an xml DTD ATTLIST. + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int +xmlTextWriterStartDTDEntity(xmlTextWriterPtr writer, + int pe, const xmlChar * name) +{ + int count; + int sum; + xmlLinkPtr lk; + xmlTextWriterStackEntry *p; + + if (writer == NULL || name == NULL || *name == '\0') + return -1; + + sum = 0; + lk = xmlListFront(writer->nodes); + if (lk != 0) { + + p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk); + if (p != 0) { + switch (p->state) { + case XML_TEXTWRITER_DTD: + count = xmlOutputBufferWriteString(writer->out, " ["); + if (count < 0) + return -1; + sum += count; + if (writer->indent) { + count = + xmlOutputBufferWriteString(writer->out, "\n"); + if (count < 0) + return -1; + sum += count; + } + p->state = XML_TEXTWRITER_DTD_TEXT; + /* fallthrough */ + case XML_TEXTWRITER_DTD_TEXT: + case XML_TEXTWRITER_NONE: + break; + default: + return -1; + } + } + } + + p = (xmlTextWriterStackEntry *) + xmlMalloc(sizeof(xmlTextWriterStackEntry)); + if (p == 0) { + xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY, + "xmlTextWriterStartDTDElement : out of memory!\n"); + return -1; + } + + p->name = xmlStrdup(name); + if (p->name == 0) { + xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY, + "xmlTextWriterStartDTDElement : out of memory!\n"); + xmlFree(p); + return -1; + } + + if (pe != 0) + p->state = XML_TEXTWRITER_DTD_PENT; + else + p->state = XML_TEXTWRITER_DTD_ENTY; + + xmlListPushFront(writer->nodes, p); + + if (writer->indent) { + count = xmlTextWriterWriteIndent(writer); + if (count < 0) + return -1; + sum += count; + } + + count = xmlOutputBufferWriteString(writer->out, "out, "% "); + if (count < 0) + return -1; + sum += count; + } + + count = xmlOutputBufferWriteString(writer->out, (const char *) name); + if (count < 0) + return -1; + sum += count; + + return sum; +} + +/** + * xmlTextWriterEndDTDEntity: + * @writer: the xmlTextWriterPtr + * + * End an xml DTD entity. + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int +xmlTextWriterEndDTDEntity(xmlTextWriterPtr writer) +{ + int count; + int sum; + xmlLinkPtr lk; + xmlTextWriterStackEntry *p; + + if (writer == NULL) + return -1; + + sum = 0; + lk = xmlListFront(writer->nodes); + if (lk == 0) + return -1; + + p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk); + if (p == 0) + return -1; + + switch (p->state) { + case XML_TEXTWRITER_DTD_ENTY_TEXT: + count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar); + if (count < 0) + return -1; + sum += count; + case XML_TEXTWRITER_DTD_ENTY: + case XML_TEXTWRITER_DTD_PENT: + count = xmlOutputBufferWriteString(writer->out, ">"); + if (count < 0) + return -1; + sum += count; + break; + default: + return -1; + } + + if (writer->indent) { + count = xmlOutputBufferWriteString(writer->out, "\n"); + if (count < 0) + return -1; + sum += count; + } + + xmlListPopFront(writer->nodes); + return sum; +} + +/** + * xmlTextWriterWriteFormatDTDInternalEntity: + * @writer: the xmlTextWriterPtr + * @pe: TRUE if this is a parameter entity, FALSE if not + * @name: the name of the DTD entity + * @format: format string (see printf) + * @...: extra parameters for the format + * + * Write a formatted DTD internal entity. + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int XMLCDECL +xmlTextWriterWriteFormatDTDInternalEntity(xmlTextWriterPtr writer, + int pe, + const xmlChar * name, + const char *format, ...) +{ + int rc; + va_list ap; + + va_start(ap, format); + + rc = xmlTextWriterWriteVFormatDTDInternalEntity(writer, pe, name, + format, ap); + + va_end(ap); + return rc; +} + +/** + * xmlTextWriterWriteVFormatDTDInternalEntity: + * @writer: the xmlTextWriterPtr + * @pe: TRUE if this is a parameter entity, FALSE if not + * @name: the name of the DTD entity + * @format: format string (see printf) + * @argptr: pointer to the first member of the variable argument list. + * + * Write a formatted DTD internal entity. + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int +xmlTextWriterWriteVFormatDTDInternalEntity(xmlTextWriterPtr writer, + int pe, + const xmlChar * name, + const char *format, + va_list argptr) +{ + int rc; + xmlChar *buf; + + if (writer == NULL) + return -1; + + buf = xmlTextWriterVSprintf(format, argptr); + if (buf == 0) + return 0; + + rc = xmlTextWriterWriteDTDInternalEntity(writer, pe, name, buf); + + xmlFree(buf); + return rc; +} + +/** + * xmlTextWriterWriteDTDEntity: + * @writer: the xmlTextWriterPtr + * @pe: TRUE if this is a parameter entity, FALSE if not + * @name: the name of the DTD entity + * @pubid: the public identifier, which is an alternative to the system identifier + * @sysid: the system identifier, which is the URI of the DTD + * @ndataid: the xml notation name. + * @content: content of the entity + * + * Write a DTD entity. + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int +xmlTextWriterWriteDTDEntity(xmlTextWriterPtr writer, + int pe, + const xmlChar * name, + const xmlChar * pubid, + const xmlChar * sysid, + const xmlChar * ndataid, + const xmlChar * content) +{ + if ((content == NULL) && (pubid == NULL) && (sysid == NULL)) + return -1; + if ((pe != 0) && (ndataid != NULL)) + return -1; + + if ((pubid == NULL) && (sysid == NULL)) + return xmlTextWriterWriteDTDInternalEntity(writer, pe, name, + content); + + return xmlTextWriterWriteDTDExternalEntity(writer, pe, name, pubid, + sysid, ndataid); +} + +/** + * xmlTextWriterWriteDTDInternalEntity: + * @writer: the xmlTextWriterPtr + * @pe: TRUE if this is a parameter entity, FALSE if not + * @name: the name of the DTD entity + * @content: content of the entity + * + * Write a DTD internal entity. + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int +xmlTextWriterWriteDTDInternalEntity(xmlTextWriterPtr writer, + int pe, + const xmlChar * name, + const xmlChar * content) +{ + int count; + int sum; + + if ((name == NULL) || (*name == '\0') || (content == NULL)) + return -1; + + sum = 0; + count = xmlTextWriterStartDTDEntity(writer, pe, name); + if (count == -1) + return -1; + sum += count; + + count = xmlTextWriterWriteString(writer, content); + if (count == -1) + return -1; + sum += count; + + count = xmlTextWriterEndDTDEntity(writer); + if (count == -1) + return -1; + sum += count; + + return sum; +} + +/** + * xmlTextWriterWriteDTDExternalEntity: + * @writer: the xmlTextWriterPtr + * @pe: TRUE if this is a parameter entity, FALSE if not + * @name: the name of the DTD entity + * @pubid: the public identifier, which is an alternative to the system identifier + * @sysid: the system identifier, which is the URI of the DTD + * @ndataid: the xml notation name. + * + * Write a DTD external entity. The entity must have been started with xmlTextWriterStartDTDEntity + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int +xmlTextWriterWriteDTDExternalEntity(xmlTextWriterPtr writer, + int pe, + const xmlChar * name, + const xmlChar * pubid, + const xmlChar * sysid, + const xmlChar * ndataid) +{ + int count; + int sum; + + if (((pubid == NULL) && (sysid == NULL))) + return -1; + if ((pe != 0) && (ndataid != NULL)) + return -1; + + sum = 0; + count = xmlTextWriterStartDTDEntity(writer, pe, name); + if (count == -1) + return -1; + sum += count; + + count = + xmlTextWriterWriteDTDExternalEntityContents(writer, pubid, sysid, + ndataid); + if (count < 0) + return -1; + sum += count; + + count = xmlTextWriterEndDTDEntity(writer); + if (count == -1) + return -1; + sum += count; + + return sum; +} + +/** + * xmlTextWriterWriteDTDExternalEntityContents: + * @writer: the xmlTextWriterPtr + * @pubid: the public identifier, which is an alternative to the system identifier + * @sysid: the system identifier, which is the URI of the DTD + * @ndataid: the xml notation name. + * + * Write the contents of a DTD external entity. + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int +xmlTextWriterWriteDTDExternalEntityContents(xmlTextWriterPtr writer, + const xmlChar * pubid, + const xmlChar * sysid, + const xmlChar * ndataid) +{ + int count; + int sum; + xmlLinkPtr lk; + xmlTextWriterStackEntry *p; + + if (writer == NULL) { + xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR, + "xmlTextWriterWriteDTDExternalEntityContents: xmlTextWriterPtr invalid!\n"); + return -1; + } + + sum = 0; + lk = xmlListFront(writer->nodes); + if (lk == 0) { + xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR, + "xmlTextWriterWriteDTDExternalEntityContents: you must call xmlTextWriterStartDTDEntity before the call to this function!\n"); + return -1; + } + + p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk); + if (p == 0) + return -1; + + switch (p->state) { + case XML_TEXTWRITER_DTD_ENTY: + break; + case XML_TEXTWRITER_DTD_PENT: + if (ndataid != NULL) { + xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR, + "xmlTextWriterWriteDTDExternalEntityContents: notation not allowed with parameter entities!\n"); + return -1; + } + break; + default: + xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR, + "xmlTextWriterWriteDTDExternalEntityContents: you must call xmlTextWriterStartDTDEntity before the call to this function!\n"); + return -1; + } + + if (pubid != 0) { + if (sysid == 0) { + xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR, + "xmlTextWriterWriteDTDExternalEntityContents: system identifier needed!\n"); + return -1; + } + + count = xmlOutputBufferWriteString(writer->out, " PUBLIC "); + if (count < 0) + return -1; + sum += count; + + count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar); + if (count < 0) + return -1; + sum += count; + + count = + xmlOutputBufferWriteString(writer->out, (const char *) pubid); + if (count < 0) + return -1; + sum += count; + + count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar); + if (count < 0) + return -1; + sum += count; + } + + if (sysid != 0) { + if (pubid == 0) { + count = xmlOutputBufferWriteString(writer->out, " SYSTEM"); + if (count < 0) + return -1; + sum += count; + } + + count = xmlOutputBufferWriteString(writer->out, " "); + if (count < 0) + return -1; + sum += count; + + count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar); + if (count < 0) + return -1; + sum += count; + + count = + xmlOutputBufferWriteString(writer->out, (const char *) sysid); + if (count < 0) + return -1; + sum += count; + + count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar); + if (count < 0) + return -1; + sum += count; + } + + if (ndataid != NULL) { + count = xmlOutputBufferWriteString(writer->out, " NDATA "); + if (count < 0) + return -1; + sum += count; + + count = + xmlOutputBufferWriteString(writer->out, + (const char *) ndataid); + if (count < 0) + return -1; + sum += count; + } + + return sum; +} + +/** + * xmlTextWriterWriteDTDNotation: + * @writer: the xmlTextWriterPtr + * @name: the name of the xml notation + * @pubid: the public identifier, which is an alternative to the system identifier + * @sysid: the system identifier, which is the URI of the DTD + * + * Write a DTD entity. + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int +xmlTextWriterWriteDTDNotation(xmlTextWriterPtr writer, + const xmlChar * name, + const xmlChar * pubid, const xmlChar * sysid) +{ + int count; + int sum; + xmlLinkPtr lk; + xmlTextWriterStackEntry *p; + + if (writer == NULL || name == NULL || *name == '\0') + return -1; + + sum = 0; + lk = xmlListFront(writer->nodes); + if (lk == 0) { + return -1; + } + + p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk); + if (p != 0) { + switch (p->state) { + case XML_TEXTWRITER_DTD: + count = xmlOutputBufferWriteString(writer->out, " ["); + if (count < 0) + return -1; + sum += count; + if (writer->indent) { + count = xmlOutputBufferWriteString(writer->out, "\n"); + if (count < 0) + return -1; + sum += count; + } + p->state = XML_TEXTWRITER_DTD_TEXT; + /* fallthrough */ + case XML_TEXTWRITER_DTD_TEXT: + break; + default: + return -1; + } + } + + if (writer->indent) { + count = xmlTextWriterWriteIndent(writer); + if (count < 0) + return -1; + sum += count; + } + + count = xmlOutputBufferWriteString(writer->out, "out, (const char *) name); + if (count < 0) + return -1; + sum += count; + + if (pubid != 0) { + count = xmlOutputBufferWriteString(writer->out, " PUBLIC "); + if (count < 0) + return -1; + sum += count; + count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar); + if (count < 0) + return -1; + sum += count; + count = + xmlOutputBufferWriteString(writer->out, (const char *) pubid); + if (count < 0) + return -1; + sum += count; + count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar); + if (count < 0) + return -1; + sum += count; + } + + if (sysid != 0) { + if (pubid == 0) { + count = xmlOutputBufferWriteString(writer->out, " SYSTEM"); + if (count < 0) + return -1; + sum += count; + } + count = xmlOutputBufferWriteString(writer->out, " "); + if (count < 0) + return -1; + sum += count; + count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar); + if (count < 0) + return -1; + sum += count; + count = + xmlOutputBufferWriteString(writer->out, (const char *) sysid); + if (count < 0) + return -1; + sum += count; + count = xmlOutputBufferWrite(writer->out, 1, &writer->qchar); + if (count < 0) + return -1; + sum += count; + } + + count = xmlOutputBufferWriteString(writer->out, ">"); + if (count < 0) + return -1; + sum += count; + + return sum; +} + +/** + * xmlTextWriterFlush: + * @writer: the xmlTextWriterPtr + * + * Flush the output buffer. + * + * Returns the bytes written (may be 0 because of buffering) or -1 in case of error + */ +int +xmlTextWriterFlush(xmlTextWriterPtr writer) +{ + int count; + + if (writer == NULL) + return -1; + + if (writer->out == NULL) + count = 0; + else + count = xmlOutputBufferFlush(writer->out); + + return count; +} + +/** + * misc + */ + +/** + * xmlFreeTextWriterStackEntry: + * @lk: the xmlLinkPtr + * + * Free callback for the xmlList. + */ +static void +xmlFreeTextWriterStackEntry(xmlLinkPtr lk) +{ + xmlTextWriterStackEntry *p; + + p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk); + if (p == 0) + return; + + if (p->name != 0) + xmlFree(p->name); + xmlFree(p); +} + +/** + * xmlCmpTextWriterStackEntry: + * @data0: the first data + * @data1: the second data + * + * Compare callback for the xmlList. + * + * Returns -1, 0, 1 + */ +static int +xmlCmpTextWriterStackEntry(const void *data0, const void *data1) +{ + xmlTextWriterStackEntry *p0; + xmlTextWriterStackEntry *p1; + + if (data0 == data1) + return 0; + + if (data0 == 0) + return -1; + + if (data1 == 0) + return 1; + + p0 = (xmlTextWriterStackEntry *) data0; + p1 = (xmlTextWriterStackEntry *) data1; + + return xmlStrcmp(p0->name, p1->name); +} + +/** + * misc + */ + +/** + * xmlFreeTextWriterNsStackEntry: + * @lk: the xmlLinkPtr + * + * Free callback for the xmlList. + */ +static void +xmlFreeTextWriterNsStackEntry(xmlLinkPtr lk) +{ + xmlTextWriterNsStackEntry *p; + + p = (xmlTextWriterNsStackEntry *) xmlLinkGetData(lk); + if (p == 0) + return; + + if (p->prefix != 0) + xmlFree(p->prefix); + if (p->uri != 0) + xmlFree(p->uri); + + xmlFree(p); +} + +/** + * xmlCmpTextWriterNsStackEntry: + * @data0: the first data + * @data1: the second data + * + * Compare callback for the xmlList. + * + * Returns -1, 0, 1 + */ +static int +xmlCmpTextWriterNsStackEntry(const void *data0, const void *data1) +{ + xmlTextWriterNsStackEntry *p0; + xmlTextWriterNsStackEntry *p1; + int rc; + + if (data0 == data1) + return 0; + + if (data0 == 0) + return -1; + + if (data1 == 0) + return 1; + + p0 = (xmlTextWriterNsStackEntry *) data0; + p1 = (xmlTextWriterNsStackEntry *) data1; + + rc = xmlStrcmp(p0->prefix, p1->prefix); + + if (rc == 0) + rc = p0->elem == p1->elem; + + return rc; +} + +/** + * xmlTextWriterWriteDocCallback: + * @context: the xmlBufferPtr + * @str: the data to write + * @len: the length of the data + * + * Write callback for the xmlOutputBuffer with target xmlBuffer + * + * Returns -1, 0, 1 + */ +static int +xmlTextWriterWriteDocCallback(void *context, const xmlChar * str, int len) +{ + xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) context; + int rc; + + if ((rc = xmlParseChunk(ctxt, (const char *) str, len, 0)) != 0) { + xmlWriterErrMsgInt(NULL, XML_ERR_INTERNAL_ERROR, + "xmlTextWriterWriteDocCallback : XML error %d !\n", + rc); + return -1; + } + + return len; +} + +/** + * xmlTextWriterCloseDocCallback: + * @context: the xmlBufferPtr + * + * Close callback for the xmlOutputBuffer with target xmlBuffer + * + * Returns -1, 0, 1 + */ +static int +xmlTextWriterCloseDocCallback(void *context) +{ + xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) context; + int rc; + + if ((rc = xmlParseChunk(ctxt, NULL, 0, 1)) != 0) { + xmlWriterErrMsgInt(NULL, XML_ERR_INTERNAL_ERROR, + "xmlTextWriterWriteDocCallback : XML error %d !\n", + rc); + return -1; + } + + return 0; +} + +/** + * xmlTextWriterVSprintf: + * @format: see printf + * @argptr: pointer to the first member of the variable argument list. + * + * Utility function for formatted output + * + * Returns a new xmlChar buffer with the data or NULL on error. This buffer must be freed. + */ +static xmlChar * +xmlTextWriterVSprintf(const char *format, va_list argptr) +{ + int size; + int count; + xmlChar *buf; + va_list locarg; + + size = BUFSIZ; + buf = (xmlChar *) xmlMalloc(size); + if (buf == NULL) { + xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY, + "xmlTextWriterVSprintf : out of memory!\n"); + return NULL; + } + + VA_COPY(locarg, argptr); + while (((count = vsnprintf((char *) buf, size, format, locarg)) < 0) + || (count == size - 1) || (count == size) || (count > size)) { + va_end(locarg); + xmlFree(buf); + size += BUFSIZ; + buf = (xmlChar *) xmlMalloc(size); + if (buf == NULL) { + xmlWriterErrMsg(NULL, XML_ERR_NO_MEMORY, + "xmlTextWriterVSprintf : out of memory!\n"); + return NULL; + } + VA_COPY(locarg, argptr); + } + va_end(locarg); + + return buf; +} + +/** + * xmlTextWriterStartDocumentCallback: + * @ctx: the user data (XML parser context) + * + * called at the start of document processing. + */ +static void +xmlTextWriterStartDocumentCallback(void *ctx) +{ + xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; + xmlDocPtr doc; + + if (ctxt->html) { +#ifdef LIBXML_HTML_ENABLED + if (ctxt->myDoc == NULL) + ctxt->myDoc = htmlNewDocNoDtD(NULL, NULL); + if (ctxt->myDoc == NULL) { + if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) + ctxt->sax->error(ctxt->userData, + "SAX.startDocument(): out of memory\n"); + ctxt->errNo = XML_ERR_NO_MEMORY; + ctxt->instate = XML_PARSER_EOF; + ctxt->disableSAX = 1; + return; + } +#else + xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR, + "libxml2 built without HTML support\n"); + ctxt->errNo = XML_ERR_INTERNAL_ERROR; + ctxt->instate = XML_PARSER_EOF; + ctxt->disableSAX = 1; + return; +#endif + } else { + doc = ctxt->myDoc; + if (doc == NULL) + doc = ctxt->myDoc = xmlNewDoc(ctxt->version); + if (doc != NULL) { + if (doc->children == NULL) { + if (ctxt->encoding != NULL) + doc->encoding = xmlStrdup(ctxt->encoding); + else + doc->encoding = NULL; + doc->standalone = ctxt->standalone; + } + } else { + if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) + ctxt->sax->error(ctxt->userData, + "SAX.startDocument(): out of memory\n"); + ctxt->errNo = XML_ERR_NO_MEMORY; + ctxt->instate = XML_PARSER_EOF; + ctxt->disableSAX = 1; + return; + } + } + if ((ctxt->myDoc != NULL) && (ctxt->myDoc->URL == NULL) && + (ctxt->input != NULL) && (ctxt->input->filename != NULL)) { + ctxt->myDoc->URL = + xmlCanonicPath((const xmlChar *) ctxt->input->filename); + if (ctxt->myDoc->URL == NULL) + ctxt->myDoc->URL = + xmlStrdup((const xmlChar *) ctxt->input->filename); + } +} + +/** + * xmlTextWriterSetIndent: + * @writer: the xmlTextWriterPtr + * @indent: do indentation? + * + * Set indentation output. indent = 0 do not indentation. indent > 0 do indentation. + * + * Returns -1 on error or 0 otherwise. + */ +int +xmlTextWriterSetIndent(xmlTextWriterPtr writer, int indent) +{ + if ((writer == NULL) || (indent < 0)) + return -1; + + writer->indent = indent; + writer->doindent = 1; + + return 0; +} + +/** + * xmlTextWriterSetIndentString: + * @writer: the xmlTextWriterPtr + * @str: the xmlChar string + * + * Set string indentation. + * + * Returns -1 on error or 0 otherwise. + */ +int +xmlTextWriterSetIndentString(xmlTextWriterPtr writer, const xmlChar * str) +{ + if ((writer == NULL) || (!str)) + return -1; + + if (writer->ichar != NULL) + xmlFree(writer->ichar); + writer->ichar = xmlStrdup(str); + + if (!writer->ichar) + return -1; + else + return 0; +} + +/** + * xmlTextWriterWriteIndent: + * @writer: the xmlTextWriterPtr + * + * Write indent string. + * + * Returns -1 on error or the number of strings written. + */ +static int +xmlTextWriterWriteIndent(xmlTextWriterPtr writer) +{ + int lksize; + int i; + int ret; + + lksize = xmlListSize(writer->nodes); + if (lksize < 1) + return (-1); /* list is empty */ + for (i = 0; i < (lksize - 1); i++) { + ret = xmlOutputBufferWriteString(writer->out, + (const char *) writer->ichar); + if (ret == -1) + return (-1); + } + + return (lksize - 1); +} + +/** + * xmlTextWriterHandleStateDependencies: + * @writer: the xmlTextWriterPtr + * @p: the xmlTextWriterStackEntry + * + * Write state dependent strings. + * + * Returns -1 on error or the number of characters written. + */ +static int +xmlTextWriterHandleStateDependencies(xmlTextWriterPtr writer, + xmlTextWriterStackEntry * p) +{ + int count; + int sum; + char extra[3]; + + if (writer == NULL) + return -1; + + if (p == NULL) + return 0; + + sum = 0; + extra[0] = extra[1] = extra[2] = '\0'; + if (p != 0) { + sum = 0; + switch (p->state) { + case XML_TEXTWRITER_NAME: + extra[0] = '>'; + p->state = XML_TEXTWRITER_TEXT; + break; + case XML_TEXTWRITER_PI: + extra[0] = ' '; + p->state = XML_TEXTWRITER_PI_TEXT; + break; + case XML_TEXTWRITER_DTD: + extra[0] = ' '; + extra[1] = '['; + p->state = XML_TEXTWRITER_DTD_TEXT; + break; + case XML_TEXTWRITER_DTD_ELEM: + extra[0] = ' '; + p->state = XML_TEXTWRITER_DTD_ELEM_TEXT; + break; + case XML_TEXTWRITER_DTD_ATTL: + extra[0] = ' '; + p->state = XML_TEXTWRITER_DTD_ATTL_TEXT; + break; + case XML_TEXTWRITER_DTD_ENTY: + case XML_TEXTWRITER_DTD_PENT: + extra[0] = ' '; + extra[1] = writer->qchar; + p->state = XML_TEXTWRITER_DTD_ENTY_TEXT; + break; + default: + break; + } + } + + if (*extra != '\0') { + count = xmlOutputBufferWriteString(writer->out, extra); + if (count < 0) + return -1; + sum += count; + } + + return sum; +} + +#define bottom_xmlwriter +#include "elfgcchack.h" +#endif diff --git a/gettext-tools/gnulib-lib/libxml/xmlwriter.in.h b/gettext-tools/gnulib-lib/libxml/xmlwriter.in.h new file mode 100644 index 0000000..31ceb5f --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/xmlwriter.in.h @@ -0,0 +1,459 @@ + +/* + * Summary: text writing API for XML + * Description: text writing API for XML + * + * Copy: See Copyright for the status of this software. + * + * Author: Alfred Mickautsch + */ + +#ifndef __XML_XMLWRITER_H__ +#define __XML_XMLWRITER_H__ + +#include + +#ifdef LIBXML_WRITER_ENABLED + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + typedef struct _xmlTextWriter xmlTextWriter; + typedef xmlTextWriter *xmlTextWriterPtr; + +/* + * Constructors & Destructor + */ + XMLPUBFUN xmlTextWriterPtr XMLCALL + xmlNewTextWriter(xmlOutputBufferPtr out); + XMLPUBFUN xmlTextWriterPtr XMLCALL + xmlNewTextWriterFilename(const char *uri, int compression); + XMLPUBFUN xmlTextWriterPtr XMLCALL + xmlNewTextWriterMemory(xmlBufferPtr buf, int compression); + XMLPUBFUN xmlTextWriterPtr XMLCALL + xmlNewTextWriterPushParser(xmlParserCtxtPtr ctxt, int compression); + XMLPUBFUN xmlTextWriterPtr XMLCALL + xmlNewTextWriterDoc(xmlDocPtr * doc, int compression); + XMLPUBFUN xmlTextWriterPtr XMLCALL + xmlNewTextWriterTree(xmlDocPtr doc, xmlNodePtr node, + int compression); + XMLPUBFUN void XMLCALL xmlFreeTextWriter(xmlTextWriterPtr writer); + +/* + * Functions + */ + + +/* + * Document + */ + XMLPUBFUN int XMLCALL + xmlTextWriterStartDocument(xmlTextWriterPtr writer, + const char *version, + const char *encoding, + const char *standalone); + XMLPUBFUN int XMLCALL xmlTextWriterEndDocument(xmlTextWriterPtr + writer); + +/* + * Comments + */ + XMLPUBFUN int XMLCALL xmlTextWriterStartComment(xmlTextWriterPtr + writer); + XMLPUBFUN int XMLCALL xmlTextWriterEndComment(xmlTextWriterPtr writer); + XMLPUBFUN int XMLCALL + xmlTextWriterWriteFormatComment(xmlTextWriterPtr writer, + const char *format, ...); + XMLPUBFUN int XMLCALL + xmlTextWriterWriteVFormatComment(xmlTextWriterPtr writer, + const char *format, + va_list argptr); + XMLPUBFUN int XMLCALL xmlTextWriterWriteComment(xmlTextWriterPtr + writer, + const xmlChar * + content); + +/* + * Elements + */ + XMLPUBFUN int XMLCALL + xmlTextWriterStartElement(xmlTextWriterPtr writer, + const xmlChar * name); + XMLPUBFUN int XMLCALL xmlTextWriterStartElementNS(xmlTextWriterPtr + writer, + const xmlChar * + prefix, + const xmlChar * name, + const xmlChar * + namespaceURI); + XMLPUBFUN int XMLCALL xmlTextWriterEndElement(xmlTextWriterPtr writer); + XMLPUBFUN int XMLCALL xmlTextWriterFullEndElement(xmlTextWriterPtr + writer); + +/* + * Elements conveniency functions + */ + XMLPUBFUN int XMLCALL + xmlTextWriterWriteFormatElement(xmlTextWriterPtr writer, + const xmlChar * name, + const char *format, ...); + XMLPUBFUN int XMLCALL + xmlTextWriterWriteVFormatElement(xmlTextWriterPtr writer, + const xmlChar * name, + const char *format, + va_list argptr); + XMLPUBFUN int XMLCALL xmlTextWriterWriteElement(xmlTextWriterPtr + writer, + const xmlChar * name, + const xmlChar * + content); + XMLPUBFUN int XMLCALL + xmlTextWriterWriteFormatElementNS(xmlTextWriterPtr writer, + const xmlChar * prefix, + const xmlChar * name, + const xmlChar * namespaceURI, + const char *format, ...); + XMLPUBFUN int XMLCALL + xmlTextWriterWriteVFormatElementNS(xmlTextWriterPtr writer, + const xmlChar * prefix, + const xmlChar * name, + const xmlChar * namespaceURI, + const char *format, + va_list argptr); + XMLPUBFUN int XMLCALL xmlTextWriterWriteElementNS(xmlTextWriterPtr + writer, + const xmlChar * + prefix, + const xmlChar * name, + const xmlChar * + namespaceURI, + const xmlChar * + content); + +/* + * Text + */ + XMLPUBFUN int XMLCALL + xmlTextWriterWriteFormatRaw(xmlTextWriterPtr writer, + const char *format, ...); + XMLPUBFUN int XMLCALL + xmlTextWriterWriteVFormatRaw(xmlTextWriterPtr writer, + const char *format, va_list argptr); + XMLPUBFUN int XMLCALL + xmlTextWriterWriteRawLen(xmlTextWriterPtr writer, + const xmlChar * content, int len); + XMLPUBFUN int XMLCALL + xmlTextWriterWriteRaw(xmlTextWriterPtr writer, + const xmlChar * content); + XMLPUBFUN int XMLCALL xmlTextWriterWriteFormatString(xmlTextWriterPtr + writer, + const char + *format, ...); + XMLPUBFUN int XMLCALL xmlTextWriterWriteVFormatString(xmlTextWriterPtr + writer, + const char + *format, + va_list argptr); + XMLPUBFUN int XMLCALL xmlTextWriterWriteString(xmlTextWriterPtr writer, + const xmlChar * + content); + XMLPUBFUN int XMLCALL xmlTextWriterWriteBase64(xmlTextWriterPtr writer, + const char *data, + int start, int len); + XMLPUBFUN int XMLCALL xmlTextWriterWriteBinHex(xmlTextWriterPtr writer, + const char *data, + int start, int len); + +/* + * Attributes + */ + XMLPUBFUN int XMLCALL + xmlTextWriterStartAttribute(xmlTextWriterPtr writer, + const xmlChar * name); + XMLPUBFUN int XMLCALL xmlTextWriterStartAttributeNS(xmlTextWriterPtr + writer, + const xmlChar * + prefix, + const xmlChar * + name, + const xmlChar * + namespaceURI); + XMLPUBFUN int XMLCALL xmlTextWriterEndAttribute(xmlTextWriterPtr + writer); + +/* + * Attributes conveniency functions + */ + XMLPUBFUN int XMLCALL + xmlTextWriterWriteFormatAttribute(xmlTextWriterPtr writer, + const xmlChar * name, + const char *format, ...); + XMLPUBFUN int XMLCALL + xmlTextWriterWriteVFormatAttribute(xmlTextWriterPtr writer, + const xmlChar * name, + const char *format, + va_list argptr); + XMLPUBFUN int XMLCALL xmlTextWriterWriteAttribute(xmlTextWriterPtr + writer, + const xmlChar * name, + const xmlChar * + content); + XMLPUBFUN int XMLCALL + xmlTextWriterWriteFormatAttributeNS(xmlTextWriterPtr writer, + const xmlChar * prefix, + const xmlChar * name, + const xmlChar * namespaceURI, + const char *format, ...); + XMLPUBFUN int XMLCALL + xmlTextWriterWriteVFormatAttributeNS(xmlTextWriterPtr writer, + const xmlChar * prefix, + const xmlChar * name, + const xmlChar * namespaceURI, + const char *format, + va_list argptr); + XMLPUBFUN int XMLCALL xmlTextWriterWriteAttributeNS(xmlTextWriterPtr + writer, + const xmlChar * + prefix, + const xmlChar * + name, + const xmlChar * + namespaceURI, + const xmlChar * + content); + +/* + * PI's + */ + XMLPUBFUN int XMLCALL + xmlTextWriterStartPI(xmlTextWriterPtr writer, + const xmlChar * target); + XMLPUBFUN int XMLCALL xmlTextWriterEndPI(xmlTextWriterPtr writer); + +/* + * PI conveniency functions + */ + XMLPUBFUN int XMLCALL + xmlTextWriterWriteFormatPI(xmlTextWriterPtr writer, + const xmlChar * target, + const char *format, ...); + XMLPUBFUN int XMLCALL + xmlTextWriterWriteVFormatPI(xmlTextWriterPtr writer, + const xmlChar * target, + const char *format, va_list argptr); + XMLPUBFUN int XMLCALL + xmlTextWriterWritePI(xmlTextWriterPtr writer, + const xmlChar * target, + const xmlChar * content); + +/** + * xmlTextWriterWriteProcessingInstruction: + * + * This macro maps to xmlTextWriterWritePI + */ +#define xmlTextWriterWriteProcessingInstruction xmlTextWriterWritePI + +/* + * CDATA + */ + XMLPUBFUN int XMLCALL xmlTextWriterStartCDATA(xmlTextWriterPtr writer); + XMLPUBFUN int XMLCALL xmlTextWriterEndCDATA(xmlTextWriterPtr writer); + +/* + * CDATA conveniency functions + */ + XMLPUBFUN int XMLCALL + xmlTextWriterWriteFormatCDATA(xmlTextWriterPtr writer, + const char *format, ...); + XMLPUBFUN int XMLCALL + xmlTextWriterWriteVFormatCDATA(xmlTextWriterPtr writer, + const char *format, va_list argptr); + XMLPUBFUN int XMLCALL + xmlTextWriterWriteCDATA(xmlTextWriterPtr writer, + const xmlChar * content); + +/* + * DTD + */ + XMLPUBFUN int XMLCALL + xmlTextWriterStartDTD(xmlTextWriterPtr writer, + const xmlChar * name, + const xmlChar * pubid, + const xmlChar * sysid); + XMLPUBFUN int XMLCALL xmlTextWriterEndDTD(xmlTextWriterPtr writer); + +/* + * DTD conveniency functions + */ + XMLPUBFUN int XMLCALL + xmlTextWriterWriteFormatDTD(xmlTextWriterPtr writer, + const xmlChar * name, + const xmlChar * pubid, + const xmlChar * sysid, + const char *format, ...); + XMLPUBFUN int XMLCALL + xmlTextWriterWriteVFormatDTD(xmlTextWriterPtr writer, + const xmlChar * name, + const xmlChar * pubid, + const xmlChar * sysid, + const char *format, va_list argptr); + XMLPUBFUN int XMLCALL + xmlTextWriterWriteDTD(xmlTextWriterPtr writer, + const xmlChar * name, + const xmlChar * pubid, + const xmlChar * sysid, + const xmlChar * subset); + +/** + * xmlTextWriterWriteDocType: + * + * this macro maps to xmlTextWriterWriteDTD + */ +#define xmlTextWriterWriteDocType xmlTextWriterWriteDTD + +/* + * DTD element definition + */ + XMLPUBFUN int XMLCALL + xmlTextWriterStartDTDElement(xmlTextWriterPtr writer, + const xmlChar * name); + XMLPUBFUN int XMLCALL xmlTextWriterEndDTDElement(xmlTextWriterPtr + writer); + +/* + * DTD element definition conveniency functions + */ + XMLPUBFUN int XMLCALL + xmlTextWriterWriteFormatDTDElement(xmlTextWriterPtr writer, + const xmlChar * name, + const char *format, ...); + XMLPUBFUN int XMLCALL + xmlTextWriterWriteVFormatDTDElement(xmlTextWriterPtr writer, + const xmlChar * name, + const char *format, + va_list argptr); + XMLPUBFUN int XMLCALL xmlTextWriterWriteDTDElement(xmlTextWriterPtr + writer, + const xmlChar * + name, + const xmlChar * + content); + +/* + * DTD attribute list definition + */ + XMLPUBFUN int XMLCALL + xmlTextWriterStartDTDAttlist(xmlTextWriterPtr writer, + const xmlChar * name); + XMLPUBFUN int XMLCALL xmlTextWriterEndDTDAttlist(xmlTextWriterPtr + writer); + +/* + * DTD attribute list definition conveniency functions + */ + XMLPUBFUN int XMLCALL + xmlTextWriterWriteFormatDTDAttlist(xmlTextWriterPtr writer, + const xmlChar * name, + const char *format, ...); + XMLPUBFUN int XMLCALL + xmlTextWriterWriteVFormatDTDAttlist(xmlTextWriterPtr writer, + const xmlChar * name, + const char *format, + va_list argptr); + XMLPUBFUN int XMLCALL xmlTextWriterWriteDTDAttlist(xmlTextWriterPtr + writer, + const xmlChar * + name, + const xmlChar * + content); + +/* + * DTD entity definition + */ + XMLPUBFUN int XMLCALL + xmlTextWriterStartDTDEntity(xmlTextWriterPtr writer, + int pe, const xmlChar * name); + XMLPUBFUN int XMLCALL xmlTextWriterEndDTDEntity(xmlTextWriterPtr + writer); + +/* + * DTD entity definition conveniency functions + */ + XMLPUBFUN int XMLCALL + xmlTextWriterWriteFormatDTDInternalEntity(xmlTextWriterPtr writer, + int pe, + const xmlChar * name, + const char *format, ...); + XMLPUBFUN int XMLCALL + xmlTextWriterWriteVFormatDTDInternalEntity(xmlTextWriterPtr writer, + int pe, + const xmlChar * name, + const char *format, + va_list argptr); + XMLPUBFUN int XMLCALL + xmlTextWriterWriteDTDInternalEntity(xmlTextWriterPtr writer, + int pe, + const xmlChar * name, + const xmlChar * content); + XMLPUBFUN int XMLCALL + xmlTextWriterWriteDTDExternalEntity(xmlTextWriterPtr writer, + int pe, + const xmlChar * name, + const xmlChar * pubid, + const xmlChar * sysid, + const xmlChar * ndataid); + XMLPUBFUN int XMLCALL + xmlTextWriterWriteDTDExternalEntityContents(xmlTextWriterPtr + writer, + const xmlChar * pubid, + const xmlChar * sysid, + const xmlChar * + ndataid); + XMLPUBFUN int XMLCALL xmlTextWriterWriteDTDEntity(xmlTextWriterPtr + writer, int pe, + const xmlChar * name, + const xmlChar * + pubid, + const xmlChar * + sysid, + const xmlChar * + ndataid, + const xmlChar * + content); + +/* + * DTD notation definition + */ + XMLPUBFUN int XMLCALL + xmlTextWriterWriteDTDNotation(xmlTextWriterPtr writer, + const xmlChar * name, + const xmlChar * pubid, + const xmlChar * sysid); + +/* + * Indentation + */ + XMLPUBFUN int XMLCALL + xmlTextWriterSetIndent(xmlTextWriterPtr writer, int indent); + XMLPUBFUN int XMLCALL + xmlTextWriterSetIndentString(xmlTextWriterPtr writer, + const xmlChar * str); + +/* + * misc + */ + XMLPUBFUN int XMLCALL xmlTextWriterFlush(xmlTextWriterPtr writer); + +#ifdef __cplusplus +} +#endif + +#endif /* LIBXML_WRITER_ENABLED */ + +#endif /* __XML_XMLWRITER_H__ */ diff --git a/gettext-tools/gnulib-lib/libxml/xpath.c b/gettext-tools/gnulib-lib/libxml/xpath.c new file mode 100644 index 0000000..8964628 --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/xpath.c @@ -0,0 +1,15066 @@ +/* + * xpath.c: XML Path Language implementation + * XPath is a language for addressing parts of an XML document, + * designed to be used by both XSLT and XPointer + *f + * Reference: W3C Recommendation 16 November 1999 + * http://www.w3.org/TR/1999/REC-xpath-19991116 + * Public reference: + * http://www.w3.org/TR/xpath + * + * See Copyright for the status of this software + * + * Author: daniel@veillard.com + * + */ + +#define IN_LIBXML +#include "libxml.h" + +#include + +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_MATH_H +#include +#endif +#ifdef HAVE_FLOAT_H +#include +#endif +#ifdef HAVE_CTYPE_H +#include +#endif +#ifdef HAVE_SIGNAL_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#ifdef LIBXML_XPTR_ENABLED +#include +#endif +#ifdef LIBXML_DEBUG_ENABLED +#include +#endif +#include +#include +#include +#ifdef LIBXML_PATTERN_ENABLED +#include +#endif + +#ifdef LIBXML_PATTERN_ENABLED +#define XPATH_STREAMING +#endif + +#define TODO \ + xmlGenericError(xmlGenericErrorContext, \ + "Unimplemented block at %s:%d\n", \ + __FILE__, __LINE__); + +/* +* XP_OPTIMIZED_NON_ELEM_COMPARISON: +* If defined, this will use xmlXPathCmpNodesExt() instead of +* xmlXPathCmpNodes(). The new function is optimized comparison of +* non-element nodes; actually it will speed up comparison only if +* xmlXPathOrderDocElems() was called in order to index the elements of +* a tree in document order; Libxslt does such an indexing, thus it will +* benefit from this optimization. +*/ +#define XP_OPTIMIZED_NON_ELEM_COMPARISON + +/* +* XP_OPTIMIZED_FILTER_FIRST: +* If defined, this will optimize expressions like "key('foo', 'val')[b][1]" +* in a way, that it stop evaluation at the first node. +*/ +#define XP_OPTIMIZED_FILTER_FIRST + +/* +* XP_DEBUG_OBJ_USAGE: +* Internal flag to enable tracking of how much XPath objects have been +* created. +*/ +/* #define XP_DEBUG_OBJ_USAGE */ + +/* + * TODO: + * There are a few spots where some tests are done which depend upon ascii + * data. These should be enhanced for full UTF8 support (see particularly + * any use of the macros IS_ASCII_CHARACTER and IS_ASCII_DIGIT) + */ + +#if defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) + +/************************************************************************ + * * + * Floating point stuff * + * * + ************************************************************************/ + +#ifndef TRIO_REPLACE_STDIO +#define TRIO_PUBLIC static +#endif +#include "trionan.c" + +/* + * The lack of portability of this section of the libc is annoying ! + */ +double xmlXPathNAN = 0; +double xmlXPathPINF = 1; +double xmlXPathNINF = -1; +static double xmlXPathNZERO = 0; /* not exported from headers */ +static int xmlXPathInitialized = 0; + +/** + * xmlXPathInit: + * + * Initialize the XPath environment + */ +void +xmlXPathInit(void) { + if (xmlXPathInitialized) return; + + xmlXPathPINF = trio_pinf(); + xmlXPathNINF = trio_ninf(); + xmlXPathNAN = trio_nan(); + xmlXPathNZERO = trio_nzero(); + + xmlXPathInitialized = 1; +} + +/** + * xmlXPathIsNaN: + * @val: a double value + * + * Provides a portable isnan() function to detect whether a double + * is a NotaNumber. Based on trio code + * http://sourceforge.net/projects/ctrio/ + * + * Returns 1 if the value is a NaN, 0 otherwise + */ +int +xmlXPathIsNaN(double val) { + return(trio_isnan(val)); +} + +/** + * xmlXPathIsInf: + * @val: a double value + * + * Provides a portable isinf() function to detect whether a double + * is a +Infinite or -Infinite. Based on trio code + * http://sourceforge.net/projects/ctrio/ + * + * Returns 1 vi the value is +Infinite, -1 if -Infinite, 0 otherwise + */ +int +xmlXPathIsInf(double val) { + return(trio_isinf(val)); +} + +#endif /* SCHEMAS or XPATH */ +#ifdef LIBXML_XPATH_ENABLED +/** + * xmlXPathGetSign: + * @val: a double value + * + * Provides a portable function to detect the sign of a double + * Modified from trio code + * http://sourceforge.net/projects/ctrio/ + * + * Returns 1 if the value is Negative, 0 if positive + */ +static int +xmlXPathGetSign(double val) { + return(trio_signbit(val)); +} + + +/* + * TODO: when compatibility allows remove all "fake node libxslt" strings + * the test should just be name[0] = ' ' + */ +/* #define DEBUG */ +/* #define DEBUG_STEP */ +/* #define DEBUG_STEP_NTH */ +/* #define DEBUG_EXPR */ +/* #define DEBUG_EVAL_COUNTS */ + +static xmlNs xmlXPathXMLNamespaceStruct = { + NULL, + XML_NAMESPACE_DECL, + XML_XML_NAMESPACE, + BAD_CAST "xml", + NULL +}; +static xmlNsPtr xmlXPathXMLNamespace = &xmlXPathXMLNamespaceStruct; +#ifndef LIBXML_THREAD_ENABLED +/* + * Optimizer is disabled only when threaded apps are detected while + * the library ain't compiled for thread safety. + */ +static int xmlXPathDisableOptimizer = 0; +#endif + +/************************************************************************ + * * + * Error handling routines * + * * + ************************************************************************/ + +/** + * XP_ERRORNULL: + * @X: the error code + * + * Macro to raise an XPath error and return NULL. + */ +#define XP_ERRORNULL(X) \ + { xmlXPathErr(ctxt, X); return(NULL); } + +/* + * The array xmlXPathErrorMessages corresponds to the enum xmlXPathError + */ +static const char *xmlXPathErrorMessages[] = { + "Ok\n", + "Number encoding\n", + "Unfinished literal\n", + "Start of literal\n", + "Expected $ for variable reference\n", + "Undefined variable\n", + "Invalid predicate\n", + "Invalid expression\n", + "Missing closing curly brace\n", + "Unregistered function\n", + "Invalid operand\n", + "Invalid type\n", + "Invalid number of arguments\n", + "Invalid context size\n", + "Invalid context position\n", + "Memory allocation error\n", + "Syntax error\n", + "Resource error\n", + "Sub resource error\n", + "Undefined namespace prefix\n", + "Encoding error\n", + "Char out of XML range\n", + "Invalid or incomplete context\n", + "?? Unknown error ??\n" /* Must be last in the list! */ +}; +#define MAXERRNO ((int)(sizeof(xmlXPathErrorMessages) / \ + sizeof(xmlXPathErrorMessages[0])) - 1) +/** + * xmlXPathErrMemory: + * @ctxt: an XPath context + * @extra: extra informations + * + * Handle a redefinition of attribute error + */ +static void +xmlXPathErrMemory(xmlXPathContextPtr ctxt, const char *extra) +{ + if (ctxt != NULL) { + if (extra) { + xmlChar buf[200]; + + xmlStrPrintf(buf, 200, + BAD_CAST "Memory allocation failed : %s\n", + extra); + ctxt->lastError.message = (char *) xmlStrdup(buf); + } else { + ctxt->lastError.message = (char *) + xmlStrdup(BAD_CAST "Memory allocation failed\n"); + } + ctxt->lastError.domain = XML_FROM_XPATH; + ctxt->lastError.code = XML_ERR_NO_MEMORY; + if (ctxt->error != NULL) + ctxt->error(ctxt->userData, &ctxt->lastError); + } else { + if (extra) + __xmlRaiseError(NULL, NULL, NULL, + NULL, NULL, XML_FROM_XPATH, + XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, + extra, NULL, NULL, 0, 0, + "Memory allocation failed : %s\n", extra); + else + __xmlRaiseError(NULL, NULL, NULL, + NULL, NULL, XML_FROM_XPATH, + XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, + NULL, NULL, NULL, 0, 0, + "Memory allocation failed\n"); + } +} + +/** + * xmlXPathPErrMemory: + * @ctxt: an XPath parser context + * @extra: extra informations + * + * Handle a redefinition of attribute error + */ +static void +xmlXPathPErrMemory(xmlXPathParserContextPtr ctxt, const char *extra) +{ + if (ctxt == NULL) + xmlXPathErrMemory(NULL, extra); + else { + ctxt->error = XPATH_MEMORY_ERROR; + xmlXPathErrMemory(ctxt->context, extra); + } +} + +/** + * xmlXPathErr: + * @ctxt: a XPath parser context + * @error: the error code + * + * Handle an XPath error + */ +void +xmlXPathErr(xmlXPathParserContextPtr ctxt, int error) +{ + if ((error < 0) || (error > MAXERRNO)) + error = MAXERRNO; + if (ctxt == NULL) { + __xmlRaiseError(NULL, NULL, NULL, + NULL, NULL, XML_FROM_XPATH, + error + XML_XPATH_EXPRESSION_OK - XPATH_EXPRESSION_OK, + XML_ERR_ERROR, NULL, 0, + NULL, NULL, NULL, 0, 0, + xmlXPathErrorMessages[error]); + return; + } + ctxt->error = error; + if (ctxt->context == NULL) { + __xmlRaiseError(NULL, NULL, NULL, + NULL, NULL, XML_FROM_XPATH, + error + XML_XPATH_EXPRESSION_OK - XPATH_EXPRESSION_OK, + XML_ERR_ERROR, NULL, 0, + (const char *) ctxt->base, NULL, NULL, + ctxt->cur - ctxt->base, 0, + xmlXPathErrorMessages[error]); + return; + } + + /* cleanup current last error */ + xmlResetError(&ctxt->context->lastError); + + ctxt->context->lastError.domain = XML_FROM_XPATH; + ctxt->context->lastError.code = error + XML_XPATH_EXPRESSION_OK - + XPATH_EXPRESSION_OK; + ctxt->context->lastError.level = XML_ERR_ERROR; + ctxt->context->lastError.str1 = (char *) xmlStrdup(ctxt->base); + ctxt->context->lastError.int1 = ctxt->cur - ctxt->base; + ctxt->context->lastError.node = ctxt->context->debugNode; + if (ctxt->context->error != NULL) { + ctxt->context->error(ctxt->context->userData, + &ctxt->context->lastError); + } else { + __xmlRaiseError(NULL, NULL, NULL, + NULL, ctxt->context->debugNode, XML_FROM_XPATH, + error + XML_XPATH_EXPRESSION_OK - XPATH_EXPRESSION_OK, + XML_ERR_ERROR, NULL, 0, + (const char *) ctxt->base, NULL, NULL, + ctxt->cur - ctxt->base, 0, + xmlXPathErrorMessages[error]); + } + +} + +/** + * xmlXPatherror: + * @ctxt: the XPath Parser context + * @file: the file name + * @line: the line number + * @no: the error number + * + * Formats an error message. + */ +void +xmlXPatherror(xmlXPathParserContextPtr ctxt, const char *file ATTRIBUTE_UNUSED, + int line ATTRIBUTE_UNUSED, int no) { + xmlXPathErr(ctxt, no); +} + +/************************************************************************ + * * + * Utilities * + * * + ************************************************************************/ + +/** + * xsltPointerList: + * + * Pointer-list for various purposes. + */ +typedef struct _xmlPointerList xmlPointerList; +typedef xmlPointerList *xmlPointerListPtr; +struct _xmlPointerList { + void **items; + int number; + int size; +}; +/* +* TODO: Since such a list-handling is used in xmlschemas.c and libxslt +* and here, we should make the functions public. +*/ +static int +xmlPointerListAddSize(xmlPointerListPtr list, + void *item, + int initialSize) +{ + if (list->items == NULL) { + if (initialSize <= 0) + initialSize = 1; + list->items = (void **) xmlMalloc( + initialSize * sizeof(void *)); + if (list->items == NULL) { + xmlXPathErrMemory(NULL, + "xmlPointerListCreate: allocating item\n"); + return(-1); + } + list->number = 0; + list->size = initialSize; + } else if (list->size <= list->number) { + list->size *= 2; + list->items = (void **) xmlRealloc(list->items, + list->size * sizeof(void *)); + if (list->items == NULL) { + xmlXPathErrMemory(NULL, + "xmlPointerListCreate: re-allocating item\n"); + list->size = 0; + return(-1); + } + } + list->items[list->number++] = item; + return(0); +} + +/** + * xsltPointerListCreate: + * + * Creates an xsltPointerList structure. + * + * Returns a xsltPointerList structure or NULL in case of an error. + */ +static xmlPointerListPtr +xmlPointerListCreate(int initialSize) +{ + xmlPointerListPtr ret; + + ret = xmlMalloc(sizeof(xmlPointerList)); + if (ret == NULL) { + xmlXPathErrMemory(NULL, + "xmlPointerListCreate: allocating item\n"); + return (NULL); + } + memset(ret, 0, sizeof(xmlPointerList)); + if (initialSize > 0) { + xmlPointerListAddSize(ret, NULL, initialSize); + ret->number = 0; + } + return (ret); +} + +/** + * xsltPointerListFree: + * + * Frees the xsltPointerList structure. This does not free + * the content of the list. + */ +static void +xmlPointerListFree(xmlPointerListPtr list) +{ + if (list == NULL) + return; + if (list->items != NULL) + xmlFree(list->items); + xmlFree(list); +} + +/************************************************************************ + * * + * Parser Types * + * * + ************************************************************************/ + +/* + * Types are private: + */ + +typedef enum { + XPATH_OP_END=0, + XPATH_OP_AND, + XPATH_OP_OR, + XPATH_OP_EQUAL, + XPATH_OP_CMP, + XPATH_OP_PLUS, + XPATH_OP_MULT, + XPATH_OP_UNION, + XPATH_OP_ROOT, + XPATH_OP_NODE, + XPATH_OP_RESET, /* 10 */ + XPATH_OP_COLLECT, + XPATH_OP_VALUE, /* 12 */ + XPATH_OP_VARIABLE, + XPATH_OP_FUNCTION, + XPATH_OP_ARG, + XPATH_OP_PREDICATE, + XPATH_OP_FILTER, /* 17 */ + XPATH_OP_SORT /* 18 */ +#ifdef LIBXML_XPTR_ENABLED + ,XPATH_OP_RANGETO +#endif +} xmlXPathOp; + +typedef enum { + AXIS_ANCESTOR = 1, + AXIS_ANCESTOR_OR_SELF, + AXIS_ATTRIBUTE, + AXIS_CHILD, + AXIS_DESCENDANT, + AXIS_DESCENDANT_OR_SELF, + AXIS_FOLLOWING, + AXIS_FOLLOWING_SIBLING, + AXIS_NAMESPACE, + AXIS_PARENT, + AXIS_PRECEDING, + AXIS_PRECEDING_SIBLING, + AXIS_SELF +} xmlXPathAxisVal; + +typedef enum { + NODE_TEST_NONE = 0, + NODE_TEST_TYPE = 1, + NODE_TEST_PI = 2, + NODE_TEST_ALL = 3, + NODE_TEST_NS = 4, + NODE_TEST_NAME = 5 +} xmlXPathTestVal; + +typedef enum { + NODE_TYPE_NODE = 0, + NODE_TYPE_COMMENT = XML_COMMENT_NODE, + NODE_TYPE_TEXT = XML_TEXT_NODE, + NODE_TYPE_PI = XML_PI_NODE +} xmlXPathTypeVal; + +#define XP_REWRITE_DOS_CHILD_ELEM 1 + +typedef struct _xmlXPathStepOp xmlXPathStepOp; +typedef xmlXPathStepOp *xmlXPathStepOpPtr; +struct _xmlXPathStepOp { + xmlXPathOp op; /* The identifier of the operation */ + int ch1; /* First child */ + int ch2; /* Second child */ + int value; + int value2; + int value3; + void *value4; + void *value5; + void *cache; + void *cacheURI; + int rewriteType; +}; + +struct _xmlXPathCompExpr { + int nbStep; /* Number of steps in this expression */ + int maxStep; /* Maximum number of steps allocated */ + xmlXPathStepOp *steps; /* ops for computation of this expression */ + int last; /* index of last step in expression */ + xmlChar *expr; /* the expression being computed */ + xmlDictPtr dict; /* the dictionnary to use if any */ +#ifdef DEBUG_EVAL_COUNTS + int nb; + xmlChar *string; +#endif +#ifdef XPATH_STREAMING + xmlPatternPtr stream; +#endif +}; + +/************************************************************************ + * * + * Forward declarations * + * * + ************************************************************************/ +static void +xmlXPathFreeValueTree(xmlNodeSetPtr obj); +static void +xmlXPathReleaseObject(xmlXPathContextPtr ctxt, xmlXPathObjectPtr obj); +static int +xmlXPathCompOpEvalFirst(xmlXPathParserContextPtr ctxt, + xmlXPathStepOpPtr op, xmlNodePtr *first); +static int +xmlXPathCompOpEvalToBoolean(xmlXPathParserContextPtr ctxt, + xmlXPathStepOpPtr op, + int isPredicate); + +/************************************************************************ + * * + * Parser Type functions * + * * + ************************************************************************/ + +/** + * xmlXPathNewCompExpr: + * + * Create a new Xpath component + * + * Returns the newly allocated xmlXPathCompExprPtr or NULL in case of error + */ +static xmlXPathCompExprPtr +xmlXPathNewCompExpr(void) { + xmlXPathCompExprPtr cur; + + cur = (xmlXPathCompExprPtr) xmlMalloc(sizeof(xmlXPathCompExpr)); + if (cur == NULL) { + xmlXPathErrMemory(NULL, "allocating component\n"); + return(NULL); + } + memset(cur, 0, sizeof(xmlXPathCompExpr)); + cur->maxStep = 10; + cur->nbStep = 0; + cur->steps = (xmlXPathStepOp *) xmlMalloc(cur->maxStep * + sizeof(xmlXPathStepOp)); + if (cur->steps == NULL) { + xmlXPathErrMemory(NULL, "allocating steps\n"); + xmlFree(cur); + return(NULL); + } + memset(cur->steps, 0, cur->maxStep * sizeof(xmlXPathStepOp)); + cur->last = -1; +#ifdef DEBUG_EVAL_COUNTS + cur->nb = 0; +#endif + return(cur); +} + +/** + * xmlXPathFreeCompExpr: + * @comp: an XPATH comp + * + * Free up the memory allocated by @comp + */ +void +xmlXPathFreeCompExpr(xmlXPathCompExprPtr comp) +{ + xmlXPathStepOpPtr op; + int i; + + if (comp == NULL) + return; + if (comp->dict == NULL) { + for (i = 0; i < comp->nbStep; i++) { + op = &comp->steps[i]; + if (op->value4 != NULL) { + if (op->op == XPATH_OP_VALUE) + xmlXPathFreeObject(op->value4); + else + xmlFree(op->value4); + } + if (op->value5 != NULL) + xmlFree(op->value5); + } + } else { + for (i = 0; i < comp->nbStep; i++) { + op = &comp->steps[i]; + if (op->value4 != NULL) { + if (op->op == XPATH_OP_VALUE) + xmlXPathFreeObject(op->value4); + } + } + xmlDictFree(comp->dict); + } + if (comp->steps != NULL) { + xmlFree(comp->steps); + } +#ifdef DEBUG_EVAL_COUNTS + if (comp->string != NULL) { + xmlFree(comp->string); + } +#endif +#ifdef XPATH_STREAMING + if (comp->stream != NULL) { + xmlFreePatternList(comp->stream); + } +#endif + if (comp->expr != NULL) { + xmlFree(comp->expr); + } + + xmlFree(comp); +} + +/** + * xmlXPathCompExprAdd: + * @comp: the compiled expression + * @ch1: first child index + * @ch2: second child index + * @op: an op + * @value: the first int value + * @value2: the second int value + * @value3: the third int value + * @value4: the first string value + * @value5: the second string value + * + * Add a step to an XPath Compiled Expression + * + * Returns -1 in case of failure, the index otherwise + */ +static int +xmlXPathCompExprAdd(xmlXPathCompExprPtr comp, int ch1, int ch2, + xmlXPathOp op, int value, + int value2, int value3, void *value4, void *value5) { + if (comp->nbStep >= comp->maxStep) { + xmlXPathStepOp *real; + + comp->maxStep *= 2; + real = (xmlXPathStepOp *) xmlRealloc(comp->steps, + comp->maxStep * sizeof(xmlXPathStepOp)); + if (real == NULL) { + comp->maxStep /= 2; + xmlXPathErrMemory(NULL, "adding step\n"); + return(-1); + } + comp->steps = real; + } + comp->last = comp->nbStep; + comp->steps[comp->nbStep].rewriteType = 0; + comp->steps[comp->nbStep].ch1 = ch1; + comp->steps[comp->nbStep].ch2 = ch2; + comp->steps[comp->nbStep].op = op; + comp->steps[comp->nbStep].value = value; + comp->steps[comp->nbStep].value2 = value2; + comp->steps[comp->nbStep].value3 = value3; + if ((comp->dict != NULL) && + ((op == XPATH_OP_FUNCTION) || (op == XPATH_OP_VARIABLE) || + (op == XPATH_OP_COLLECT))) { + if (value4 != NULL) { + comp->steps[comp->nbStep].value4 = (xmlChar *) + (void *)xmlDictLookup(comp->dict, value4, -1); + xmlFree(value4); + } else + comp->steps[comp->nbStep].value4 = NULL; + if (value5 != NULL) { + comp->steps[comp->nbStep].value5 = (xmlChar *) + (void *)xmlDictLookup(comp->dict, value5, -1); + xmlFree(value5); + } else + comp->steps[comp->nbStep].value5 = NULL; + } else { + comp->steps[comp->nbStep].value4 = value4; + comp->steps[comp->nbStep].value5 = value5; + } + comp->steps[comp->nbStep].cache = NULL; + return(comp->nbStep++); +} + +/** + * xmlXPathCompSwap: + * @comp: the compiled expression + * @op: operation index + * + * Swaps 2 operations in the compiled expression + */ +static void +xmlXPathCompSwap(xmlXPathStepOpPtr op) { + int tmp; + +#ifndef LIBXML_THREAD_ENABLED + /* + * Since this manipulates possibly shared variables, this is + * disabled if one detects that the library is used in a multithreaded + * application + */ + if (xmlXPathDisableOptimizer) + return; +#endif + + tmp = op->ch1; + op->ch1 = op->ch2; + op->ch2 = tmp; +} + +#define PUSH_FULL_EXPR(op, op1, op2, val, val2, val3, val4, val5) \ + xmlXPathCompExprAdd(ctxt->comp, (op1), (op2), \ + (op), (val), (val2), (val3), (val4), (val5)) +#define PUSH_LONG_EXPR(op, val, val2, val3, val4, val5) \ + xmlXPathCompExprAdd(ctxt->comp, ctxt->comp->last, -1, \ + (op), (val), (val2), (val3), (val4), (val5)) + +#define PUSH_LEAVE_EXPR(op, val, val2) \ +xmlXPathCompExprAdd(ctxt->comp, -1, -1, (op), (val), (val2), 0 ,NULL ,NULL) + +#define PUSH_UNARY_EXPR(op, ch, val, val2) \ +xmlXPathCompExprAdd(ctxt->comp, (ch), -1, (op), (val), (val2), 0 ,NULL ,NULL) + +#define PUSH_BINARY_EXPR(op, ch1, ch2, val, val2) \ +xmlXPathCompExprAdd(ctxt->comp, (ch1), (ch2), (op), \ + (val), (val2), 0 ,NULL ,NULL) + +/************************************************************************ + * * + * XPath object cache structures * + * * + ************************************************************************/ + +/* #define XP_DEFAULT_CACHE_ON */ + +#define XP_HAS_CACHE(c) ((c != NULL) && ((c)->cache != NULL)) + +typedef struct _xmlXPathContextCache xmlXPathContextCache; +typedef xmlXPathContextCache *xmlXPathContextCachePtr; +struct _xmlXPathContextCache { + xmlPointerListPtr nodesetObjs; /* contains xmlXPathObjectPtr */ + xmlPointerListPtr stringObjs; /* contains xmlXPathObjectPtr */ + xmlPointerListPtr booleanObjs; /* contains xmlXPathObjectPtr */ + xmlPointerListPtr numberObjs; /* contains xmlXPathObjectPtr */ + xmlPointerListPtr miscObjs; /* contains xmlXPathObjectPtr */ + int maxNodeset; + int maxString; + int maxBoolean; + int maxNumber; + int maxMisc; +#ifdef XP_DEBUG_OBJ_USAGE + int dbgCachedAll; + int dbgCachedNodeset; + int dbgCachedString; + int dbgCachedBool; + int dbgCachedNumber; + int dbgCachedPoint; + int dbgCachedRange; + int dbgCachedLocset; + int dbgCachedUsers; + int dbgCachedXSLTTree; + int dbgCachedUndefined; + + + int dbgReusedAll; + int dbgReusedNodeset; + int dbgReusedString; + int dbgReusedBool; + int dbgReusedNumber; + int dbgReusedPoint; + int dbgReusedRange; + int dbgReusedLocset; + int dbgReusedUsers; + int dbgReusedXSLTTree; + int dbgReusedUndefined; + +#endif +}; + +/************************************************************************ + * * + * Debugging related functions * + * * + ************************************************************************/ + +#define STRANGE \ + xmlGenericError(xmlGenericErrorContext, \ + "Internal error at %s:%d\n", \ + __FILE__, __LINE__); + +#ifdef LIBXML_DEBUG_ENABLED +static void +xmlXPathDebugDumpNode(FILE *output, xmlNodePtr cur, int depth) { + int i; + char shift[100]; + + for (i = 0;((i < depth) && (i < 25));i++) + shift[2 * i] = shift[2 * i + 1] = ' '; + shift[2 * i] = shift[2 * i + 1] = 0; + if (cur == NULL) { + fprintf(output, shift); + fprintf(output, "Node is NULL !\n"); + return; + + } + + if ((cur->type == XML_DOCUMENT_NODE) || + (cur->type == XML_HTML_DOCUMENT_NODE)) { + fprintf(output, shift); + fprintf(output, " /\n"); + } else if (cur->type == XML_ATTRIBUTE_NODE) + xmlDebugDumpAttr(output, (xmlAttrPtr)cur, depth); + else + xmlDebugDumpOneNode(output, cur, depth); +} +static void +xmlXPathDebugDumpNodeList(FILE *output, xmlNodePtr cur, int depth) { + xmlNodePtr tmp; + int i; + char shift[100]; + + for (i = 0;((i < depth) && (i < 25));i++) + shift[2 * i] = shift[2 * i + 1] = ' '; + shift[2 * i] = shift[2 * i + 1] = 0; + if (cur == NULL) { + fprintf(output, shift); + fprintf(output, "Node is NULL !\n"); + return; + + } + + while (cur != NULL) { + tmp = cur; + cur = cur->next; + xmlDebugDumpOneNode(output, tmp, depth); + } +} + +static void +xmlXPathDebugDumpNodeSet(FILE *output, xmlNodeSetPtr cur, int depth) { + int i; + char shift[100]; + + for (i = 0;((i < depth) && (i < 25));i++) + shift[2 * i] = shift[2 * i + 1] = ' '; + shift[2 * i] = shift[2 * i + 1] = 0; + + if (cur == NULL) { + fprintf(output, shift); + fprintf(output, "NodeSet is NULL !\n"); + return; + + } + + if (cur != NULL) { + fprintf(output, "Set contains %d nodes:\n", cur->nodeNr); + for (i = 0;i < cur->nodeNr;i++) { + fprintf(output, shift); + fprintf(output, "%d", i + 1); + xmlXPathDebugDumpNode(output, cur->nodeTab[i], depth + 1); + } + } +} + +static void +xmlXPathDebugDumpValueTree(FILE *output, xmlNodeSetPtr cur, int depth) { + int i; + char shift[100]; + + for (i = 0;((i < depth) && (i < 25));i++) + shift[2 * i] = shift[2 * i + 1] = ' '; + shift[2 * i] = shift[2 * i + 1] = 0; + + if ((cur == NULL) || (cur->nodeNr == 0) || (cur->nodeTab[0] == NULL)) { + fprintf(output, shift); + fprintf(output, "Value Tree is NULL !\n"); + return; + + } + + fprintf(output, shift); + fprintf(output, "%d", i + 1); + xmlXPathDebugDumpNodeList(output, cur->nodeTab[0]->children, depth + 1); +} +#if defined(LIBXML_XPTR_ENABLED) +static void +xmlXPathDebugDumpLocationSet(FILE *output, xmlLocationSetPtr cur, int depth) { + int i; + char shift[100]; + + for (i = 0;((i < depth) && (i < 25));i++) + shift[2 * i] = shift[2 * i + 1] = ' '; + shift[2 * i] = shift[2 * i + 1] = 0; + + if (cur == NULL) { + fprintf(output, shift); + fprintf(output, "LocationSet is NULL !\n"); + return; + + } + + for (i = 0;i < cur->locNr;i++) { + fprintf(output, shift); + fprintf(output, "%d : ", i + 1); + xmlXPathDebugDumpObject(output, cur->locTab[i], depth + 1); + } +} +#endif /* LIBXML_XPTR_ENABLED */ + +/** + * xmlXPathDebugDumpObject: + * @output: the FILE * to dump the output + * @cur: the object to inspect + * @depth: indentation level + * + * Dump the content of the object for debugging purposes + */ +void +xmlXPathDebugDumpObject(FILE *output, xmlXPathObjectPtr cur, int depth) { + int i; + char shift[100]; + + if (output == NULL) return; + + for (i = 0;((i < depth) && (i < 25));i++) + shift[2 * i] = shift[2 * i + 1] = ' '; + shift[2 * i] = shift[2 * i + 1] = 0; + + + fprintf(output, shift); + + if (cur == NULL) { + fprintf(output, "Object is empty (NULL)\n"); + return; + } + switch(cur->type) { + case XPATH_UNDEFINED: + fprintf(output, "Object is uninitialized\n"); + break; + case XPATH_NODESET: + fprintf(output, "Object is a Node Set :\n"); + xmlXPathDebugDumpNodeSet(output, cur->nodesetval, depth); + break; + case XPATH_XSLT_TREE: + fprintf(output, "Object is an XSLT value tree :\n"); + xmlXPathDebugDumpValueTree(output, cur->nodesetval, depth); + break; + case XPATH_BOOLEAN: + fprintf(output, "Object is a Boolean : "); + if (cur->boolval) fprintf(output, "true\n"); + else fprintf(output, "false\n"); + break; + case XPATH_NUMBER: + switch (xmlXPathIsInf(cur->floatval)) { + case 1: + fprintf(output, "Object is a number : Infinity\n"); + break; + case -1: + fprintf(output, "Object is a number : -Infinity\n"); + break; + default: + if (xmlXPathIsNaN(cur->floatval)) { + fprintf(output, "Object is a number : NaN\n"); + } else if (cur->floatval == 0 && xmlXPathGetSign(cur->floatval) != 0) { + fprintf(output, "Object is a number : 0\n"); + } else { + fprintf(output, "Object is a number : %0g\n", cur->floatval); + } + } + break; + case XPATH_STRING: + fprintf(output, "Object is a string : "); + xmlDebugDumpString(output, cur->stringval); + fprintf(output, "\n"); + break; + case XPATH_POINT: + fprintf(output, "Object is a point : index %d in node", cur->index); + xmlXPathDebugDumpNode(output, (xmlNodePtr) cur->user, depth + 1); + fprintf(output, "\n"); + break; + case XPATH_RANGE: + if ((cur->user2 == NULL) || + ((cur->user2 == cur->user) && (cur->index == cur->index2))) { + fprintf(output, "Object is a collapsed range :\n"); + fprintf(output, shift); + if (cur->index >= 0) + fprintf(output, "index %d in ", cur->index); + fprintf(output, "node\n"); + xmlXPathDebugDumpNode(output, (xmlNodePtr) cur->user, + depth + 1); + } else { + fprintf(output, "Object is a range :\n"); + fprintf(output, shift); + fprintf(output, "From "); + if (cur->index >= 0) + fprintf(output, "index %d in ", cur->index); + fprintf(output, "node\n"); + xmlXPathDebugDumpNode(output, (xmlNodePtr) cur->user, + depth + 1); + fprintf(output, shift); + fprintf(output, "To "); + if (cur->index2 >= 0) + fprintf(output, "index %d in ", cur->index2); + fprintf(output, "node\n"); + xmlXPathDebugDumpNode(output, (xmlNodePtr) cur->user2, + depth + 1); + fprintf(output, "\n"); + } + break; + case XPATH_LOCATIONSET: +#if defined(LIBXML_XPTR_ENABLED) + fprintf(output, "Object is a Location Set:\n"); + xmlXPathDebugDumpLocationSet(output, + (xmlLocationSetPtr) cur->user, depth); +#endif + break; + case XPATH_USERS: + fprintf(output, "Object is user defined\n"); + break; + } +} + +static void +xmlXPathDebugDumpStepOp(FILE *output, xmlXPathCompExprPtr comp, + xmlXPathStepOpPtr op, int depth) { + int i; + char shift[100]; + + for (i = 0;((i < depth) && (i < 25));i++) + shift[2 * i] = shift[2 * i + 1] = ' '; + shift[2 * i] = shift[2 * i + 1] = 0; + + fprintf(output, shift); + if (op == NULL) { + fprintf(output, "Step is NULL\n"); + return; + } + switch (op->op) { + case XPATH_OP_END: + fprintf(output, "END"); break; + case XPATH_OP_AND: + fprintf(output, "AND"); break; + case XPATH_OP_OR: + fprintf(output, "OR"); break; + case XPATH_OP_EQUAL: + if (op->value) + fprintf(output, "EQUAL ="); + else + fprintf(output, "EQUAL !="); + break; + case XPATH_OP_CMP: + if (op->value) + fprintf(output, "CMP <"); + else + fprintf(output, "CMP >"); + if (!op->value2) + fprintf(output, "="); + break; + case XPATH_OP_PLUS: + if (op->value == 0) + fprintf(output, "PLUS -"); + else if (op->value == 1) + fprintf(output, "PLUS +"); + else if (op->value == 2) + fprintf(output, "PLUS unary -"); + else if (op->value == 3) + fprintf(output, "PLUS unary - -"); + break; + case XPATH_OP_MULT: + if (op->value == 0) + fprintf(output, "MULT *"); + else if (op->value == 1) + fprintf(output, "MULT div"); + else + fprintf(output, "MULT mod"); + break; + case XPATH_OP_UNION: + fprintf(output, "UNION"); break; + case XPATH_OP_ROOT: + fprintf(output, "ROOT"); break; + case XPATH_OP_NODE: + fprintf(output, "NODE"); break; + case XPATH_OP_RESET: + fprintf(output, "RESET"); break; + case XPATH_OP_SORT: + fprintf(output, "SORT"); break; + case XPATH_OP_COLLECT: { + xmlXPathAxisVal axis = (xmlXPathAxisVal)op->value; + xmlXPathTestVal test = (xmlXPathTestVal)op->value2; + xmlXPathTypeVal type = (xmlXPathTypeVal)op->value3; + const xmlChar *prefix = op->value4; + const xmlChar *name = op->value5; + + fprintf(output, "COLLECT "); + switch (axis) { + case AXIS_ANCESTOR: + fprintf(output, " 'ancestors' "); break; + case AXIS_ANCESTOR_OR_SELF: + fprintf(output, " 'ancestors-or-self' "); break; + case AXIS_ATTRIBUTE: + fprintf(output, " 'attributes' "); break; + case AXIS_CHILD: + fprintf(output, " 'child' "); break; + case AXIS_DESCENDANT: + fprintf(output, " 'descendant' "); break; + case AXIS_DESCENDANT_OR_SELF: + fprintf(output, " 'descendant-or-self' "); break; + case AXIS_FOLLOWING: + fprintf(output, " 'following' "); break; + case AXIS_FOLLOWING_SIBLING: + fprintf(output, " 'following-siblings' "); break; + case AXIS_NAMESPACE: + fprintf(output, " 'namespace' "); break; + case AXIS_PARENT: + fprintf(output, " 'parent' "); break; + case AXIS_PRECEDING: + fprintf(output, " 'preceding' "); break; + case AXIS_PRECEDING_SIBLING: + fprintf(output, " 'preceding-sibling' "); break; + case AXIS_SELF: + fprintf(output, " 'self' "); break; + } + switch (test) { + case NODE_TEST_NONE: + fprintf(output, "'none' "); break; + case NODE_TEST_TYPE: + fprintf(output, "'type' "); break; + case NODE_TEST_PI: + fprintf(output, "'PI' "); break; + case NODE_TEST_ALL: + fprintf(output, "'all' "); break; + case NODE_TEST_NS: + fprintf(output, "'namespace' "); break; + case NODE_TEST_NAME: + fprintf(output, "'name' "); break; + } + switch (type) { + case NODE_TYPE_NODE: + fprintf(output, "'node' "); break; + case NODE_TYPE_COMMENT: + fprintf(output, "'comment' "); break; + case NODE_TYPE_TEXT: + fprintf(output, "'text' "); break; + case NODE_TYPE_PI: + fprintf(output, "'PI' "); break; + } + if (prefix != NULL) + fprintf(output, "%s:", prefix); + if (name != NULL) + fprintf(output, "%s", (const char *) name); + break; + + } + case XPATH_OP_VALUE: { + xmlXPathObjectPtr object = (xmlXPathObjectPtr) op->value4; + + fprintf(output, "ELEM "); + xmlXPathDebugDumpObject(output, object, 0); + goto finish; + } + case XPATH_OP_VARIABLE: { + const xmlChar *prefix = op->value5; + const xmlChar *name = op->value4; + + if (prefix != NULL) + fprintf(output, "VARIABLE %s:%s", prefix, name); + else + fprintf(output, "VARIABLE %s", name); + break; + } + case XPATH_OP_FUNCTION: { + int nbargs = op->value; + const xmlChar *prefix = op->value5; + const xmlChar *name = op->value4; + + if (prefix != NULL) + fprintf(output, "FUNCTION %s:%s(%d args)", + prefix, name, nbargs); + else + fprintf(output, "FUNCTION %s(%d args)", name, nbargs); + break; + } + case XPATH_OP_ARG: fprintf(output, "ARG"); break; + case XPATH_OP_PREDICATE: fprintf(output, "PREDICATE"); break; + case XPATH_OP_FILTER: fprintf(output, "FILTER"); break; +#ifdef LIBXML_XPTR_ENABLED + case XPATH_OP_RANGETO: fprintf(output, "RANGETO"); break; +#endif + default: + fprintf(output, "UNKNOWN %d\n", op->op); return; + } + fprintf(output, "\n"); +finish: + if (op->ch1 >= 0) + xmlXPathDebugDumpStepOp(output, comp, &comp->steps[op->ch1], depth + 1); + if (op->ch2 >= 0) + xmlXPathDebugDumpStepOp(output, comp, &comp->steps[op->ch2], depth + 1); +} + +/** + * xmlXPathDebugDumpCompExpr: + * @output: the FILE * for the output + * @comp: the precompiled XPath expression + * @depth: the indentation level. + * + * Dumps the tree of the compiled XPath expression. + */ +void +xmlXPathDebugDumpCompExpr(FILE *output, xmlXPathCompExprPtr comp, + int depth) { + int i; + char shift[100]; + + if ((output == NULL) || (comp == NULL)) return; + + for (i = 0;((i < depth) && (i < 25));i++) + shift[2 * i] = shift[2 * i + 1] = ' '; + shift[2 * i] = shift[2 * i + 1] = 0; + + fprintf(output, shift); + + fprintf(output, "Compiled Expression : %d elements\n", + comp->nbStep); + i = comp->last; + xmlXPathDebugDumpStepOp(output, comp, &comp->steps[i], depth + 1); +} + +#ifdef XP_DEBUG_OBJ_USAGE + +/* +* XPath object usage related debugging variables. +*/ +static int xmlXPathDebugObjCounterUndefined = 0; +static int xmlXPathDebugObjCounterNodeset = 0; +static int xmlXPathDebugObjCounterBool = 0; +static int xmlXPathDebugObjCounterNumber = 0; +static int xmlXPathDebugObjCounterString = 0; +static int xmlXPathDebugObjCounterPoint = 0; +static int xmlXPathDebugObjCounterRange = 0; +static int xmlXPathDebugObjCounterLocset = 0; +static int xmlXPathDebugObjCounterUsers = 0; +static int xmlXPathDebugObjCounterXSLTTree = 0; +static int xmlXPathDebugObjCounterAll = 0; + +static int xmlXPathDebugObjTotalUndefined = 0; +static int xmlXPathDebugObjTotalNodeset = 0; +static int xmlXPathDebugObjTotalBool = 0; +static int xmlXPathDebugObjTotalNumber = 0; +static int xmlXPathDebugObjTotalString = 0; +static int xmlXPathDebugObjTotalPoint = 0; +static int xmlXPathDebugObjTotalRange = 0; +static int xmlXPathDebugObjTotalLocset = 0; +static int xmlXPathDebugObjTotalUsers = 0; +static int xmlXPathDebugObjTotalXSLTTree = 0; +static int xmlXPathDebugObjTotalAll = 0; + +static int xmlXPathDebugObjMaxUndefined = 0; +static int xmlXPathDebugObjMaxNodeset = 0; +static int xmlXPathDebugObjMaxBool = 0; +static int xmlXPathDebugObjMaxNumber = 0; +static int xmlXPathDebugObjMaxString = 0; +static int xmlXPathDebugObjMaxPoint = 0; +static int xmlXPathDebugObjMaxRange = 0; +static int xmlXPathDebugObjMaxLocset = 0; +static int xmlXPathDebugObjMaxUsers = 0; +static int xmlXPathDebugObjMaxXSLTTree = 0; +static int xmlXPathDebugObjMaxAll = 0; + +/* REVISIT TODO: Make this static when committing */ +static void +xmlXPathDebugObjUsageReset(xmlXPathContextPtr ctxt) +{ + if (ctxt != NULL) { + if (ctxt->cache != NULL) { + xmlXPathContextCachePtr cache = + (xmlXPathContextCachePtr) ctxt->cache; + + cache->dbgCachedAll = 0; + cache->dbgCachedNodeset = 0; + cache->dbgCachedString = 0; + cache->dbgCachedBool = 0; + cache->dbgCachedNumber = 0; + cache->dbgCachedPoint = 0; + cache->dbgCachedRange = 0; + cache->dbgCachedLocset = 0; + cache->dbgCachedUsers = 0; + cache->dbgCachedXSLTTree = 0; + cache->dbgCachedUndefined = 0; + + cache->dbgReusedAll = 0; + cache->dbgReusedNodeset = 0; + cache->dbgReusedString = 0; + cache->dbgReusedBool = 0; + cache->dbgReusedNumber = 0; + cache->dbgReusedPoint = 0; + cache->dbgReusedRange = 0; + cache->dbgReusedLocset = 0; + cache->dbgReusedUsers = 0; + cache->dbgReusedXSLTTree = 0; + cache->dbgReusedUndefined = 0; + } + } + + xmlXPathDebugObjCounterUndefined = 0; + xmlXPathDebugObjCounterNodeset = 0; + xmlXPathDebugObjCounterBool = 0; + xmlXPathDebugObjCounterNumber = 0; + xmlXPathDebugObjCounterString = 0; + xmlXPathDebugObjCounterPoint = 0; + xmlXPathDebugObjCounterRange = 0; + xmlXPathDebugObjCounterLocset = 0; + xmlXPathDebugObjCounterUsers = 0; + xmlXPathDebugObjCounterXSLTTree = 0; + xmlXPathDebugObjCounterAll = 0; + + xmlXPathDebugObjTotalUndefined = 0; + xmlXPathDebugObjTotalNodeset = 0; + xmlXPathDebugObjTotalBool = 0; + xmlXPathDebugObjTotalNumber = 0; + xmlXPathDebugObjTotalString = 0; + xmlXPathDebugObjTotalPoint = 0; + xmlXPathDebugObjTotalRange = 0; + xmlXPathDebugObjTotalLocset = 0; + xmlXPathDebugObjTotalUsers = 0; + xmlXPathDebugObjTotalXSLTTree = 0; + xmlXPathDebugObjTotalAll = 0; + + xmlXPathDebugObjMaxUndefined = 0; + xmlXPathDebugObjMaxNodeset = 0; + xmlXPathDebugObjMaxBool = 0; + xmlXPathDebugObjMaxNumber = 0; + xmlXPathDebugObjMaxString = 0; + xmlXPathDebugObjMaxPoint = 0; + xmlXPathDebugObjMaxRange = 0; + xmlXPathDebugObjMaxLocset = 0; + xmlXPathDebugObjMaxUsers = 0; + xmlXPathDebugObjMaxXSLTTree = 0; + xmlXPathDebugObjMaxAll = 0; + +} + +static void +xmlXPathDebugObjUsageRequested(xmlXPathContextPtr ctxt, + xmlXPathObjectType objType) +{ + int isCached = 0; + + if (ctxt != NULL) { + if (ctxt->cache != NULL) { + xmlXPathContextCachePtr cache = + (xmlXPathContextCachePtr) ctxt->cache; + + isCached = 1; + + cache->dbgReusedAll++; + switch (objType) { + case XPATH_UNDEFINED: + cache->dbgReusedUndefined++; + break; + case XPATH_NODESET: + cache->dbgReusedNodeset++; + break; + case XPATH_BOOLEAN: + cache->dbgReusedBool++; + break; + case XPATH_NUMBER: + cache->dbgReusedNumber++; + break; + case XPATH_STRING: + cache->dbgReusedString++; + break; + case XPATH_POINT: + cache->dbgReusedPoint++; + break; + case XPATH_RANGE: + cache->dbgReusedRange++; + break; + case XPATH_LOCATIONSET: + cache->dbgReusedLocset++; + break; + case XPATH_USERS: + cache->dbgReusedUsers++; + break; + case XPATH_XSLT_TREE: + cache->dbgReusedXSLTTree++; + break; + default: + break; + } + } + } + + switch (objType) { + case XPATH_UNDEFINED: + if (! isCached) + xmlXPathDebugObjTotalUndefined++; + xmlXPathDebugObjCounterUndefined++; + if (xmlXPathDebugObjCounterUndefined > + xmlXPathDebugObjMaxUndefined) + xmlXPathDebugObjMaxUndefined = + xmlXPathDebugObjCounterUndefined; + break; + case XPATH_NODESET: + if (! isCached) + xmlXPathDebugObjTotalNodeset++; + xmlXPathDebugObjCounterNodeset++; + if (xmlXPathDebugObjCounterNodeset > + xmlXPathDebugObjMaxNodeset) + xmlXPathDebugObjMaxNodeset = + xmlXPathDebugObjCounterNodeset; + break; + case XPATH_BOOLEAN: + if (! isCached) + xmlXPathDebugObjTotalBool++; + xmlXPathDebugObjCounterBool++; + if (xmlXPathDebugObjCounterBool > + xmlXPathDebugObjMaxBool) + xmlXPathDebugObjMaxBool = + xmlXPathDebugObjCounterBool; + break; + case XPATH_NUMBER: + if (! isCached) + xmlXPathDebugObjTotalNumber++; + xmlXPathDebugObjCounterNumber++; + if (xmlXPathDebugObjCounterNumber > + xmlXPathDebugObjMaxNumber) + xmlXPathDebugObjMaxNumber = + xmlXPathDebugObjCounterNumber; + break; + case XPATH_STRING: + if (! isCached) + xmlXPathDebugObjTotalString++; + xmlXPathDebugObjCounterString++; + if (xmlXPathDebugObjCounterString > + xmlXPathDebugObjMaxString) + xmlXPathDebugObjMaxString = + xmlXPathDebugObjCounterString; + break; + case XPATH_POINT: + if (! isCached) + xmlXPathDebugObjTotalPoint++; + xmlXPathDebugObjCounterPoint++; + if (xmlXPathDebugObjCounterPoint > + xmlXPathDebugObjMaxPoint) + xmlXPathDebugObjMaxPoint = + xmlXPathDebugObjCounterPoint; + break; + case XPATH_RANGE: + if (! isCached) + xmlXPathDebugObjTotalRange++; + xmlXPathDebugObjCounterRange++; + if (xmlXPathDebugObjCounterRange > + xmlXPathDebugObjMaxRange) + xmlXPathDebugObjMaxRange = + xmlXPathDebugObjCounterRange; + break; + case XPATH_LOCATIONSET: + if (! isCached) + xmlXPathDebugObjTotalLocset++; + xmlXPathDebugObjCounterLocset++; + if (xmlXPathDebugObjCounterLocset > + xmlXPathDebugObjMaxLocset) + xmlXPathDebugObjMaxLocset = + xmlXPathDebugObjCounterLocset; + break; + case XPATH_USERS: + if (! isCached) + xmlXPathDebugObjTotalUsers++; + xmlXPathDebugObjCounterUsers++; + if (xmlXPathDebugObjCounterUsers > + xmlXPathDebugObjMaxUsers) + xmlXPathDebugObjMaxUsers = + xmlXPathDebugObjCounterUsers; + break; + case XPATH_XSLT_TREE: + if (! isCached) + xmlXPathDebugObjTotalXSLTTree++; + xmlXPathDebugObjCounterXSLTTree++; + if (xmlXPathDebugObjCounterXSLTTree > + xmlXPathDebugObjMaxXSLTTree) + xmlXPathDebugObjMaxXSLTTree = + xmlXPathDebugObjCounterXSLTTree; + break; + default: + break; + } + if (! isCached) + xmlXPathDebugObjTotalAll++; + xmlXPathDebugObjCounterAll++; + if (xmlXPathDebugObjCounterAll > + xmlXPathDebugObjMaxAll) + xmlXPathDebugObjMaxAll = + xmlXPathDebugObjCounterAll; +} + +static void +xmlXPathDebugObjUsageReleased(xmlXPathContextPtr ctxt, + xmlXPathObjectType objType) +{ + int isCached = 0; + + if (ctxt != NULL) { + if (ctxt->cache != NULL) { + xmlXPathContextCachePtr cache = + (xmlXPathContextCachePtr) ctxt->cache; + + isCached = 1; + + cache->dbgCachedAll++; + switch (objType) { + case XPATH_UNDEFINED: + cache->dbgCachedUndefined++; + break; + case XPATH_NODESET: + cache->dbgCachedNodeset++; + break; + case XPATH_BOOLEAN: + cache->dbgCachedBool++; + break; + case XPATH_NUMBER: + cache->dbgCachedNumber++; + break; + case XPATH_STRING: + cache->dbgCachedString++; + break; + case XPATH_POINT: + cache->dbgCachedPoint++; + break; + case XPATH_RANGE: + cache->dbgCachedRange++; + break; + case XPATH_LOCATIONSET: + cache->dbgCachedLocset++; + break; + case XPATH_USERS: + cache->dbgCachedUsers++; + break; + case XPATH_XSLT_TREE: + cache->dbgCachedXSLTTree++; + break; + default: + break; + } + + } + } + switch (objType) { + case XPATH_UNDEFINED: + xmlXPathDebugObjCounterUndefined--; + break; + case XPATH_NODESET: + xmlXPathDebugObjCounterNodeset--; + break; + case XPATH_BOOLEAN: + xmlXPathDebugObjCounterBool--; + break; + case XPATH_NUMBER: + xmlXPathDebugObjCounterNumber--; + break; + case XPATH_STRING: + xmlXPathDebugObjCounterString--; + break; + case XPATH_POINT: + xmlXPathDebugObjCounterPoint--; + break; + case XPATH_RANGE: + xmlXPathDebugObjCounterRange--; + break; + case XPATH_LOCATIONSET: + xmlXPathDebugObjCounterLocset--; + break; + case XPATH_USERS: + xmlXPathDebugObjCounterUsers--; + break; + case XPATH_XSLT_TREE: + xmlXPathDebugObjCounterXSLTTree--; + break; + default: + break; + } + xmlXPathDebugObjCounterAll--; +} + +/* REVISIT TODO: Make this static when committing */ +static void +xmlXPathDebugObjUsageDisplay(xmlXPathContextPtr ctxt) +{ + int reqAll, reqNodeset, reqString, reqBool, reqNumber, + reqXSLTTree, reqUndefined; + int caAll = 0, caNodeset = 0, caString = 0, caBool = 0, + caNumber = 0, caXSLTTree = 0, caUndefined = 0; + int reAll = 0, reNodeset = 0, reString = 0, reBool = 0, + reNumber = 0, reXSLTTree = 0, reUndefined = 0; + int leftObjs = xmlXPathDebugObjCounterAll; + + reqAll = xmlXPathDebugObjTotalAll; + reqNodeset = xmlXPathDebugObjTotalNodeset; + reqString = xmlXPathDebugObjTotalString; + reqBool = xmlXPathDebugObjTotalBool; + reqNumber = xmlXPathDebugObjTotalNumber; + reqXSLTTree = xmlXPathDebugObjTotalXSLTTree; + reqUndefined = xmlXPathDebugObjTotalUndefined; + + printf("# XPath object usage:\n"); + + if (ctxt != NULL) { + if (ctxt->cache != NULL) { + xmlXPathContextCachePtr cache = + (xmlXPathContextCachePtr) ctxt->cache; + + reAll = cache->dbgReusedAll; + reqAll += reAll; + reNodeset = cache->dbgReusedNodeset; + reqNodeset += reNodeset; + reString = cache->dbgReusedString; + reqString += reString; + reBool = cache->dbgReusedBool; + reqBool += reBool; + reNumber = cache->dbgReusedNumber; + reqNumber += reNumber; + reXSLTTree = cache->dbgReusedXSLTTree; + reqXSLTTree += reXSLTTree; + reUndefined = cache->dbgReusedUndefined; + reqUndefined += reUndefined; + + caAll = cache->dbgCachedAll; + caBool = cache->dbgCachedBool; + caNodeset = cache->dbgCachedNodeset; + caString = cache->dbgCachedString; + caNumber = cache->dbgCachedNumber; + caXSLTTree = cache->dbgCachedXSLTTree; + caUndefined = cache->dbgCachedUndefined; + + if (cache->nodesetObjs) + leftObjs -= cache->nodesetObjs->number; + if (cache->stringObjs) + leftObjs -= cache->stringObjs->number; + if (cache->booleanObjs) + leftObjs -= cache->booleanObjs->number; + if (cache->numberObjs) + leftObjs -= cache->numberObjs->number; + if (cache->miscObjs) + leftObjs -= cache->miscObjs->number; + } + } + + printf("# all\n"); + printf("# total : %d\n", reqAll); + printf("# left : %d\n", leftObjs); + printf("# created: %d\n", xmlXPathDebugObjTotalAll); + printf("# reused : %d\n", reAll); + printf("# max : %d\n", xmlXPathDebugObjMaxAll); + + printf("# node-sets\n"); + printf("# total : %d\n", reqNodeset); + printf("# created: %d\n", xmlXPathDebugObjTotalNodeset); + printf("# reused : %d\n", reNodeset); + printf("# max : %d\n", xmlXPathDebugObjMaxNodeset); + + printf("# strings\n"); + printf("# total : %d\n", reqString); + printf("# created: %d\n", xmlXPathDebugObjTotalString); + printf("# reused : %d\n", reString); + printf("# max : %d\n", xmlXPathDebugObjMaxString); + + printf("# booleans\n"); + printf("# total : %d\n", reqBool); + printf("# created: %d\n", xmlXPathDebugObjTotalBool); + printf("# reused : %d\n", reBool); + printf("# max : %d\n", xmlXPathDebugObjMaxBool); + + printf("# numbers\n"); + printf("# total : %d\n", reqNumber); + printf("# created: %d\n", xmlXPathDebugObjTotalNumber); + printf("# reused : %d\n", reNumber); + printf("# max : %d\n", xmlXPathDebugObjMaxNumber); + + printf("# XSLT result tree fragments\n"); + printf("# total : %d\n", reqXSLTTree); + printf("# created: %d\n", xmlXPathDebugObjTotalXSLTTree); + printf("# reused : %d\n", reXSLTTree); + printf("# max : %d\n", xmlXPathDebugObjMaxXSLTTree); + + printf("# undefined\n"); + printf("# total : %d\n", reqUndefined); + printf("# created: %d\n", xmlXPathDebugObjTotalUndefined); + printf("# reused : %d\n", reUndefined); + printf("# max : %d\n", xmlXPathDebugObjMaxUndefined); + +} + +#endif /* XP_DEBUG_OBJ_USAGE */ + +#endif /* LIBXML_DEBUG_ENABLED */ + +/************************************************************************ + * * + * XPath object caching * + * * + ************************************************************************/ + +/** + * xmlXPathNewCache: + * + * Create a new object cache + * + * Returns the xmlXPathCache just allocated. + */ +static xmlXPathContextCachePtr +xmlXPathNewCache(void) +{ + xmlXPathContextCachePtr ret; + + ret = (xmlXPathContextCachePtr) xmlMalloc(sizeof(xmlXPathContextCache)); + if (ret == NULL) { + xmlXPathErrMemory(NULL, "creating object cache\n"); + return(NULL); + } + memset(ret, 0 , (size_t) sizeof(xmlXPathContextCache)); + ret->maxNodeset = 100; + ret->maxString = 100; + ret->maxBoolean = 100; + ret->maxNumber = 100; + ret->maxMisc = 100; + return(ret); +} + +static void +xmlXPathCacheFreeObjectList(xmlPointerListPtr list) +{ + int i; + xmlXPathObjectPtr obj; + + if (list == NULL) + return; + + for (i = 0; i < list->number; i++) { + obj = list->items[i]; + /* + * Note that it is already assured that we don't need to + * look out for namespace nodes in the node-set. + */ + if (obj->nodesetval != NULL) { + if (obj->nodesetval->nodeTab != NULL) + xmlFree(obj->nodesetval->nodeTab); + xmlFree(obj->nodesetval); + } + xmlFree(obj); +#ifdef XP_DEBUG_OBJ_USAGE + xmlXPathDebugObjCounterAll--; +#endif + } + xmlPointerListFree(list); +} + +static void +xmlXPathFreeCache(xmlXPathContextCachePtr cache) +{ + if (cache == NULL) + return; + if (cache->nodesetObjs) + xmlXPathCacheFreeObjectList(cache->nodesetObjs); + if (cache->stringObjs) + xmlXPathCacheFreeObjectList(cache->stringObjs); + if (cache->booleanObjs) + xmlXPathCacheFreeObjectList(cache->booleanObjs); + if (cache->numberObjs) + xmlXPathCacheFreeObjectList(cache->numberObjs); + if (cache->miscObjs) + xmlXPathCacheFreeObjectList(cache->miscObjs); + xmlFree(cache); +} + +/** + * xmlXPathContextSetCache: + * + * @ctxt: the XPath context + * @active: enables/disables (creates/frees) the cache + * @value: a value with semantics dependant on @options + * @options: options (currently only the value 0 is used) + * + * Creates/frees an object cache on the XPath context. + * If activates XPath objects (xmlXPathObject) will be cached internally + * to be reused. + * @options: + * 0: This will set the XPath object caching: + * @value: + * This will set the maximum number of XPath objects + * to be cached per slot + * There are 5 slots for: node-set, string, number, boolean, and + * misc objects. Use <0 for the default number (100). + * Other values for @options have currently no effect. + * + * Returns 0 if the setting succeeded, and -1 on API or internal errors. + */ +int +xmlXPathContextSetCache(xmlXPathContextPtr ctxt, + int active, + int value, + int options) +{ + if (ctxt == NULL) + return(-1); + if (active) { + xmlXPathContextCachePtr cache; + + if (ctxt->cache == NULL) { + ctxt->cache = xmlXPathNewCache(); + if (ctxt->cache == NULL) + return(-1); + } + cache = (xmlXPathContextCachePtr) ctxt->cache; + if (options == 0) { + if (value < 0) + value = 100; + cache->maxNodeset = value; + cache->maxString = value; + cache->maxNumber = value; + cache->maxBoolean = value; + cache->maxMisc = value; + } + } else if (ctxt->cache != NULL) { + xmlXPathFreeCache((xmlXPathContextCachePtr) ctxt->cache); + ctxt->cache = NULL; + } + return(0); +} + +/** + * xmlXPathCacheWrapNodeSet: + * @ctxt: the XPath context + * @val: the NodePtr value + * + * This is the cached version of xmlXPathWrapNodeSet(). + * Wrap the Nodeset @val in a new xmlXPathObjectPtr + * + * Returns the created or reused object. + */ +static xmlXPathObjectPtr +xmlXPathCacheWrapNodeSet(xmlXPathContextPtr ctxt, xmlNodeSetPtr val) +{ + if ((ctxt != NULL) && (ctxt->cache != NULL)) { + xmlXPathContextCachePtr cache = + (xmlXPathContextCachePtr) ctxt->cache; + + if ((cache->miscObjs != NULL) && + (cache->miscObjs->number != 0)) + { + xmlXPathObjectPtr ret; + + ret = (xmlXPathObjectPtr) + cache->miscObjs->items[--cache->miscObjs->number]; + ret->type = XPATH_NODESET; + ret->nodesetval = val; +#ifdef XP_DEBUG_OBJ_USAGE + xmlXPathDebugObjUsageRequested(ctxt, XPATH_NODESET); +#endif + return(ret); + } + } + + return(xmlXPathWrapNodeSet(val)); + +} + +/** + * xmlXPathCacheWrapString: + * @ctxt: the XPath context + * @val: the xmlChar * value + * + * This is the cached version of xmlXPathWrapString(). + * Wraps the @val string into an XPath object. + * + * Returns the created or reused object. + */ +static xmlXPathObjectPtr +xmlXPathCacheWrapString(xmlXPathContextPtr ctxt, xmlChar *val) +{ + if ((ctxt != NULL) && (ctxt->cache != NULL)) { + xmlXPathContextCachePtr cache = (xmlXPathContextCachePtr) ctxt->cache; + + if ((cache->stringObjs != NULL) && + (cache->stringObjs->number != 0)) + { + + xmlXPathObjectPtr ret; + + ret = (xmlXPathObjectPtr) + cache->stringObjs->items[--cache->stringObjs->number]; + ret->type = XPATH_STRING; + ret->stringval = val; +#ifdef XP_DEBUG_OBJ_USAGE + xmlXPathDebugObjUsageRequested(ctxt, XPATH_STRING); +#endif + return(ret); + } else if ((cache->miscObjs != NULL) && + (cache->miscObjs->number != 0)) + { + xmlXPathObjectPtr ret; + /* + * Fallback to misc-cache. + */ + ret = (xmlXPathObjectPtr) + cache->miscObjs->items[--cache->miscObjs->number]; + + ret->type = XPATH_STRING; + ret->stringval = val; +#ifdef XP_DEBUG_OBJ_USAGE + xmlXPathDebugObjUsageRequested(ctxt, XPATH_STRING); +#endif + return(ret); + } + } + return(xmlXPathWrapString(val)); +} + +/** + * xmlXPathCacheNewNodeSet: + * @ctxt: the XPath context + * @val: the NodePtr value + * + * This is the cached version of xmlXPathNewNodeSet(). + * Acquire an xmlXPathObjectPtr of type NodeSet and initialize + * it with the single Node @val + * + * Returns the created or reused object. + */ +static xmlXPathObjectPtr +xmlXPathCacheNewNodeSet(xmlXPathContextPtr ctxt, xmlNodePtr val) +{ + if ((ctxt != NULL) && (ctxt->cache)) { + xmlXPathContextCachePtr cache = (xmlXPathContextCachePtr) ctxt->cache; + + if ((cache->nodesetObjs != NULL) && + (cache->nodesetObjs->number != 0)) + { + xmlXPathObjectPtr ret; + /* + * Use the nodset-cache. + */ + ret = (xmlXPathObjectPtr) + cache->nodesetObjs->items[--cache->nodesetObjs->number]; + ret->type = XPATH_NODESET; + ret->boolval = 0; + if (val) { + if ((ret->nodesetval->nodeMax == 0) || + (val->type == XML_NAMESPACE_DECL)) + { + xmlXPathNodeSetAddUnique(ret->nodesetval, val); + } else { + ret->nodesetval->nodeTab[0] = val; + ret->nodesetval->nodeNr = 1; + } + } +#ifdef XP_DEBUG_OBJ_USAGE + xmlXPathDebugObjUsageRequested(ctxt, XPATH_NODESET); +#endif + return(ret); + } else if ((cache->miscObjs != NULL) && + (cache->miscObjs->number != 0)) + { + xmlXPathObjectPtr ret; + /* + * Fallback to misc-cache. + */ + + ret = (xmlXPathObjectPtr) + cache->miscObjs->items[--cache->miscObjs->number]; + + ret->type = XPATH_NODESET; + ret->boolval = 0; + ret->nodesetval = xmlXPathNodeSetCreate(val); +#ifdef XP_DEBUG_OBJ_USAGE + xmlXPathDebugObjUsageRequested(ctxt, XPATH_NODESET); +#endif + return(ret); + } + } + return(xmlXPathNewNodeSet(val)); +} + +/** + * xmlXPathCacheNewCString: + * @ctxt: the XPath context + * @val: the char * value + * + * This is the cached version of xmlXPathNewCString(). + * Acquire an xmlXPathObjectPtr of type string and of value @val + * + * Returns the created or reused object. + */ +static xmlXPathObjectPtr +xmlXPathCacheNewCString(xmlXPathContextPtr ctxt, const char *val) +{ + if ((ctxt != NULL) && (ctxt->cache)) { + xmlXPathContextCachePtr cache = (xmlXPathContextCachePtr) ctxt->cache; + + if ((cache->stringObjs != NULL) && + (cache->stringObjs->number != 0)) + { + xmlXPathObjectPtr ret; + + ret = (xmlXPathObjectPtr) + cache->stringObjs->items[--cache->stringObjs->number]; + + ret->type = XPATH_STRING; + ret->stringval = xmlStrdup(BAD_CAST val); +#ifdef XP_DEBUG_OBJ_USAGE + xmlXPathDebugObjUsageRequested(ctxt, XPATH_STRING); +#endif + return(ret); + } else if ((cache->miscObjs != NULL) && + (cache->miscObjs->number != 0)) + { + xmlXPathObjectPtr ret; + + ret = (xmlXPathObjectPtr) + cache->miscObjs->items[--cache->miscObjs->number]; + + ret->type = XPATH_STRING; + ret->stringval = xmlStrdup(BAD_CAST val); +#ifdef XP_DEBUG_OBJ_USAGE + xmlXPathDebugObjUsageRequested(ctxt, XPATH_STRING); +#endif + return(ret); + } + } + return(xmlXPathNewCString(val)); +} + +/** + * xmlXPathCacheNewString: + * @ctxt: the XPath context + * @val: the xmlChar * value + * + * This is the cached version of xmlXPathNewString(). + * Acquire an xmlXPathObjectPtr of type string and of value @val + * + * Returns the created or reused object. + */ +static xmlXPathObjectPtr +xmlXPathCacheNewString(xmlXPathContextPtr ctxt, const xmlChar *val) +{ + if ((ctxt != NULL) && (ctxt->cache)) { + xmlXPathContextCachePtr cache = (xmlXPathContextCachePtr) ctxt->cache; + + if ((cache->stringObjs != NULL) && + (cache->stringObjs->number != 0)) + { + xmlXPathObjectPtr ret; + + ret = (xmlXPathObjectPtr) + cache->stringObjs->items[--cache->stringObjs->number]; + ret->type = XPATH_STRING; + if (val != NULL) + ret->stringval = xmlStrdup(val); + else + ret->stringval = xmlStrdup((const xmlChar *)""); +#ifdef XP_DEBUG_OBJ_USAGE + xmlXPathDebugObjUsageRequested(ctxt, XPATH_STRING); +#endif + return(ret); + } else if ((cache->miscObjs != NULL) && + (cache->miscObjs->number != 0)) + { + xmlXPathObjectPtr ret; + + ret = (xmlXPathObjectPtr) + cache->miscObjs->items[--cache->miscObjs->number]; + + ret->type = XPATH_STRING; + if (val != NULL) + ret->stringval = xmlStrdup(val); + else + ret->stringval = xmlStrdup((const xmlChar *)""); +#ifdef XP_DEBUG_OBJ_USAGE + xmlXPathDebugObjUsageRequested(ctxt, XPATH_STRING); +#endif + return(ret); + } + } + return(xmlXPathNewString(val)); +} + +/** + * xmlXPathCacheNewBoolean: + * @ctxt: the XPath context + * @val: the boolean value + * + * This is the cached version of xmlXPathNewBoolean(). + * Acquires an xmlXPathObjectPtr of type boolean and of value @val + * + * Returns the created or reused object. + */ +static xmlXPathObjectPtr +xmlXPathCacheNewBoolean(xmlXPathContextPtr ctxt, int val) +{ + if ((ctxt != NULL) && (ctxt->cache)) { + xmlXPathContextCachePtr cache = (xmlXPathContextCachePtr) ctxt->cache; + + if ((cache->booleanObjs != NULL) && + (cache->booleanObjs->number != 0)) + { + xmlXPathObjectPtr ret; + + ret = (xmlXPathObjectPtr) + cache->booleanObjs->items[--cache->booleanObjs->number]; + ret->type = XPATH_BOOLEAN; + ret->boolval = (val != 0); +#ifdef XP_DEBUG_OBJ_USAGE + xmlXPathDebugObjUsageRequested(ctxt, XPATH_BOOLEAN); +#endif + return(ret); + } else if ((cache->miscObjs != NULL) && + (cache->miscObjs->number != 0)) + { + xmlXPathObjectPtr ret; + + ret = (xmlXPathObjectPtr) + cache->miscObjs->items[--cache->miscObjs->number]; + + ret->type = XPATH_BOOLEAN; + ret->boolval = (val != 0); +#ifdef XP_DEBUG_OBJ_USAGE + xmlXPathDebugObjUsageRequested(ctxt, XPATH_BOOLEAN); +#endif + return(ret); + } + } + return(xmlXPathNewBoolean(val)); +} + +/** + * xmlXPathCacheNewFloat: + * @ctxt: the XPath context + * @val: the double value + * + * This is the cached version of xmlXPathNewFloat(). + * Acquires an xmlXPathObjectPtr of type double and of value @val + * + * Returns the created or reused object. + */ +static xmlXPathObjectPtr +xmlXPathCacheNewFloat(xmlXPathContextPtr ctxt, double val) +{ + if ((ctxt != NULL) && (ctxt->cache)) { + xmlXPathContextCachePtr cache = (xmlXPathContextCachePtr) ctxt->cache; + + if ((cache->numberObjs != NULL) && + (cache->numberObjs->number != 0)) + { + xmlXPathObjectPtr ret; + + ret = (xmlXPathObjectPtr) + cache->numberObjs->items[--cache->numberObjs->number]; + ret->type = XPATH_NUMBER; + ret->floatval = val; +#ifdef XP_DEBUG_OBJ_USAGE + xmlXPathDebugObjUsageRequested(ctxt, XPATH_NUMBER); +#endif + return(ret); + } else if ((cache->miscObjs != NULL) && + (cache->miscObjs->number != 0)) + { + xmlXPathObjectPtr ret; + + ret = (xmlXPathObjectPtr) + cache->miscObjs->items[--cache->miscObjs->number]; + + ret->type = XPATH_NUMBER; + ret->floatval = val; +#ifdef XP_DEBUG_OBJ_USAGE + xmlXPathDebugObjUsageRequested(ctxt, XPATH_NUMBER); +#endif + return(ret); + } + } + return(xmlXPathNewFloat(val)); +} + +/** + * xmlXPathCacheConvertString: + * @ctxt: the XPath context + * @val: an XPath object + * + * This is the cached version of xmlXPathConvertString(). + * Converts an existing object to its string() equivalent + * + * Returns a created or reused object, the old one is freed (cached) + * (or the operation is done directly on @val) + */ + +static xmlXPathObjectPtr +xmlXPathCacheConvertString(xmlXPathContextPtr ctxt, xmlXPathObjectPtr val) { + xmlChar *res = NULL; + + if (val == NULL) + return(xmlXPathCacheNewCString(ctxt, "")); + + switch (val->type) { + case XPATH_UNDEFINED: +#ifdef DEBUG_EXPR + xmlGenericError(xmlGenericErrorContext, "STRING: undefined\n"); +#endif + break; + case XPATH_NODESET: + case XPATH_XSLT_TREE: + res = xmlXPathCastNodeSetToString(val->nodesetval); + break; + case XPATH_STRING: + return(val); + case XPATH_BOOLEAN: + res = xmlXPathCastBooleanToString(val->boolval); + break; + case XPATH_NUMBER: + res = xmlXPathCastNumberToString(val->floatval); + break; + case XPATH_USERS: + case XPATH_POINT: + case XPATH_RANGE: + case XPATH_LOCATIONSET: + TODO; + break; + } + xmlXPathReleaseObject(ctxt, val); + if (res == NULL) + return(xmlXPathCacheNewCString(ctxt, "")); + return(xmlXPathCacheWrapString(ctxt, res)); +} + +/** + * xmlXPathCacheObjectCopy: + * @ctxt: the XPath context + * @val: the original object + * + * This is the cached version of xmlXPathObjectCopy(). + * Acquire a copy of a given object + * + * Returns a created or reused created object. + */ +static xmlXPathObjectPtr +xmlXPathCacheObjectCopy(xmlXPathContextPtr ctxt, xmlXPathObjectPtr val) +{ + if (val == NULL) + return(NULL); + + if (XP_HAS_CACHE(ctxt)) { + switch (val->type) { + case XPATH_NODESET: + return(xmlXPathCacheWrapNodeSet(ctxt, + xmlXPathNodeSetMerge(NULL, val->nodesetval))); + case XPATH_STRING: + return(xmlXPathCacheNewString(ctxt, val->stringval)); + case XPATH_BOOLEAN: + return(xmlXPathCacheNewBoolean(ctxt, val->boolval)); + case XPATH_NUMBER: + return(xmlXPathCacheNewFloat(ctxt, val->floatval)); + default: + break; + } + } + return(xmlXPathObjectCopy(val)); +} + +/** + * xmlXPathCacheConvertBoolean: + * @ctxt: the XPath context + * @val: an XPath object + * + * This is the cached version of xmlXPathConvertBoolean(). + * Converts an existing object to its boolean() equivalent + * + * Returns a created or reused object, the old one is freed (or the operation + * is done directly on @val) + */ +static xmlXPathObjectPtr +xmlXPathCacheConvertBoolean(xmlXPathContextPtr ctxt, xmlXPathObjectPtr val) { + xmlXPathObjectPtr ret; + + if (val == NULL) + return(xmlXPathCacheNewBoolean(ctxt, 0)); + if (val->type == XPATH_BOOLEAN) + return(val); + ret = xmlXPathCacheNewBoolean(ctxt, xmlXPathCastToBoolean(val)); + xmlXPathReleaseObject(ctxt, val); + return(ret); +} + +/** + * xmlXPathCacheConvertNumber: + * @ctxt: the XPath context + * @val: an XPath object + * + * This is the cached version of xmlXPathConvertNumber(). + * Converts an existing object to its number() equivalent + * + * Returns a created or reused object, the old one is freed (or the operation + * is done directly on @val) + */ +static xmlXPathObjectPtr +xmlXPathCacheConvertNumber(xmlXPathContextPtr ctxt, xmlXPathObjectPtr val) { + xmlXPathObjectPtr ret; + + if (val == NULL) + return(xmlXPathCacheNewFloat(ctxt, 0.0)); + if (val->type == XPATH_NUMBER) + return(val); + ret = xmlXPathCacheNewFloat(ctxt, xmlXPathCastToNumber(val)); + xmlXPathReleaseObject(ctxt, val); + return(ret); +} + +/************************************************************************ + * * + * Parser stacks related functions and macros * + * * + ************************************************************************/ + +/** + * valuePop: + * @ctxt: an XPath evaluation context + * + * Pops the top XPath object from the value stack + * + * Returns the XPath object just removed + */ +xmlXPathObjectPtr +valuePop(xmlXPathParserContextPtr ctxt) +{ + xmlXPathObjectPtr ret; + + if ((ctxt == NULL) || (ctxt->valueNr <= 0)) + return (NULL); + ctxt->valueNr--; + if (ctxt->valueNr > 0) + ctxt->value = ctxt->valueTab[ctxt->valueNr - 1]; + else + ctxt->value = NULL; + ret = ctxt->valueTab[ctxt->valueNr]; + ctxt->valueTab[ctxt->valueNr] = NULL; + return (ret); +} +/** + * valuePush: + * @ctxt: an XPath evaluation context + * @value: the XPath object + * + * Pushes a new XPath object on top of the value stack + * + * returns the number of items on the value stack + */ +int +valuePush(xmlXPathParserContextPtr ctxt, xmlXPathObjectPtr value) +{ + if ((ctxt == NULL) || (value == NULL)) return(-1); + if (ctxt->valueNr >= ctxt->valueMax) { + xmlXPathObjectPtr *tmp; + + tmp = (xmlXPathObjectPtr *) xmlRealloc(ctxt->valueTab, + 2 * ctxt->valueMax * + sizeof(ctxt->valueTab[0])); + if (tmp == NULL) { + xmlGenericError(xmlGenericErrorContext, "realloc failed !\n"); + return (0); + } + ctxt->valueMax *= 2; + ctxt->valueTab = tmp; + } + ctxt->valueTab[ctxt->valueNr] = value; + ctxt->value = value; + return (ctxt->valueNr++); +} + +/** + * xmlXPathPopBoolean: + * @ctxt: an XPath parser context + * + * Pops a boolean from the stack, handling conversion if needed. + * Check error with #xmlXPathCheckError. + * + * Returns the boolean + */ +int +xmlXPathPopBoolean (xmlXPathParserContextPtr ctxt) { + xmlXPathObjectPtr obj; + int ret; + + obj = valuePop(ctxt); + if (obj == NULL) { + xmlXPathSetError(ctxt, XPATH_INVALID_OPERAND); + return(0); + } + if (obj->type != XPATH_BOOLEAN) + ret = xmlXPathCastToBoolean(obj); + else + ret = obj->boolval; + xmlXPathReleaseObject(ctxt->context, obj); + return(ret); +} + +/** + * xmlXPathPopNumber: + * @ctxt: an XPath parser context + * + * Pops a number from the stack, handling conversion if needed. + * Check error with #xmlXPathCheckError. + * + * Returns the number + */ +double +xmlXPathPopNumber (xmlXPathParserContextPtr ctxt) { + xmlXPathObjectPtr obj; + double ret; + + obj = valuePop(ctxt); + if (obj == NULL) { + xmlXPathSetError(ctxt, XPATH_INVALID_OPERAND); + return(0); + } + if (obj->type != XPATH_NUMBER) + ret = xmlXPathCastToNumber(obj); + else + ret = obj->floatval; + xmlXPathReleaseObject(ctxt->context, obj); + return(ret); +} + +/** + * xmlXPathPopString: + * @ctxt: an XPath parser context + * + * Pops a string from the stack, handling conversion if needed. + * Check error with #xmlXPathCheckError. + * + * Returns the string + */ +xmlChar * +xmlXPathPopString (xmlXPathParserContextPtr ctxt) { + xmlXPathObjectPtr obj; + xmlChar * ret; + + obj = valuePop(ctxt); + if (obj == NULL) { + xmlXPathSetError(ctxt, XPATH_INVALID_OPERAND); + return(NULL); + } + ret = xmlXPathCastToString(obj); /* this does required strdup */ + /* TODO: needs refactoring somewhere else */ + if (obj->stringval == ret) + obj->stringval = NULL; + xmlXPathReleaseObject(ctxt->context, obj); + return(ret); +} + +/** + * xmlXPathPopNodeSet: + * @ctxt: an XPath parser context + * + * Pops a node-set from the stack, handling conversion if needed. + * Check error with #xmlXPathCheckError. + * + * Returns the node-set + */ +xmlNodeSetPtr +xmlXPathPopNodeSet (xmlXPathParserContextPtr ctxt) { + xmlXPathObjectPtr obj; + xmlNodeSetPtr ret; + + if (ctxt == NULL) return(NULL); + if (ctxt->value == NULL) { + xmlXPathSetError(ctxt, XPATH_INVALID_OPERAND); + return(NULL); + } + if (!xmlXPathStackIsNodeSet(ctxt)) { + xmlXPathSetTypeError(ctxt); + return(NULL); + } + obj = valuePop(ctxt); + ret = obj->nodesetval; +#if 0 + /* to fix memory leak of not clearing obj->user */ + if (obj->boolval && obj->user != NULL) + xmlFreeNodeList((xmlNodePtr) obj->user); +#endif + obj->nodesetval = NULL; + xmlXPathReleaseObject(ctxt->context, obj); + return(ret); +} + +/** + * xmlXPathPopExternal: + * @ctxt: an XPath parser context + * + * Pops an external object from the stack, handling conversion if needed. + * Check error with #xmlXPathCheckError. + * + * Returns the object + */ +void * +xmlXPathPopExternal (xmlXPathParserContextPtr ctxt) { + xmlXPathObjectPtr obj; + void * ret; + + if ((ctxt == NULL) || (ctxt->value == NULL)) { + xmlXPathSetError(ctxt, XPATH_INVALID_OPERAND); + return(NULL); + } + if (ctxt->value->type != XPATH_USERS) { + xmlXPathSetTypeError(ctxt); + return(NULL); + } + obj = valuePop(ctxt); + ret = obj->user; + obj->user = NULL; + xmlXPathReleaseObject(ctxt->context, obj); + return(ret); +} + +/* + * Macros for accessing the content. Those should be used only by the parser, + * and not exported. + * + * Dirty macros, i.e. one need to make assumption on the context to use them + * + * CUR_PTR return the current pointer to the xmlChar to be parsed. + * CUR returns the current xmlChar value, i.e. a 8 bit value + * in ISO-Latin or UTF-8. + * This should be used internally by the parser + * only to compare to ASCII values otherwise it would break when + * running with UTF-8 encoding. + * NXT(n) returns the n'th next xmlChar. Same as CUR is should be used only + * to compare on ASCII based substring. + * SKIP(n) Skip n xmlChar, and must also be used only to skip ASCII defined + * strings within the parser. + * CURRENT Returns the current char value, with the full decoding of + * UTF-8 if we are using this mode. It returns an int. + * NEXT Skip to the next character, this does the proper decoding + * in UTF-8 mode. It also pop-up unfinished entities on the fly. + * It returns the pointer to the current xmlChar. + */ + +#define CUR (*ctxt->cur) +#define SKIP(val) ctxt->cur += (val) +#define NXT(val) ctxt->cur[(val)] +#define CUR_PTR ctxt->cur +#define CUR_CHAR(l) xmlXPathCurrentChar(ctxt, &l) + +#define COPY_BUF(l,b,i,v) \ + if (l == 1) b[i++] = (xmlChar) v; \ + else i += xmlCopyChar(l,&b[i],v) + +#define NEXTL(l) ctxt->cur += l + +#define SKIP_BLANKS \ + while (IS_BLANK_CH(*(ctxt->cur))) NEXT + +#define CURRENT (*ctxt->cur) +#define NEXT ((*ctxt->cur) ? ctxt->cur++: ctxt->cur) + + +#ifndef DBL_DIG +#define DBL_DIG 16 +#endif +#ifndef DBL_EPSILON +#define DBL_EPSILON 1E-9 +#endif + +#define UPPER_DOUBLE 1E9 +#define LOWER_DOUBLE 1E-5 + +#define INTEGER_DIGITS DBL_DIG +#define FRACTION_DIGITS (DBL_DIG + 1) +#define EXPONENT_DIGITS (3 + 2) + +/** + * xmlXPathFormatNumber: + * @number: number to format + * @buffer: output buffer + * @buffersize: size of output buffer + * + * Convert the number into a string representation. + */ +static void +xmlXPathFormatNumber(double number, char buffer[], int buffersize) +{ + switch (xmlXPathIsInf(number)) { + case 1: + if (buffersize > (int)sizeof("Infinity")) + snprintf(buffer, buffersize, "Infinity"); + break; + case -1: + if (buffersize > (int)sizeof("-Infinity")) + snprintf(buffer, buffersize, "-Infinity"); + break; + default: + if (xmlXPathIsNaN(number)) { + if (buffersize > (int)sizeof("NaN")) + snprintf(buffer, buffersize, "NaN"); + } else if (number == 0 && xmlXPathGetSign(number) != 0) { + snprintf(buffer, buffersize, "0"); + } else if (number == ((int) number)) { + char work[30]; + char *ptr, *cur; + int value = (int) number; + + ptr = &buffer[0]; + if (value == 0) { + *ptr++ = '0'; + } else { + snprintf(work, 29, "%d", value); + cur = &work[0]; + while ((*cur) && (ptr - buffer < buffersize)) { + *ptr++ = *cur++; + } + } + if (ptr - buffer < buffersize) { + *ptr = 0; + } else if (buffersize > 0) { + ptr--; + *ptr = 0; + } + } else { + /* 3 is sign, decimal point, and terminating zero */ + char work[DBL_DIG + EXPONENT_DIGITS + 3]; + int integer_place, fraction_place; + char *ptr; + char *after_fraction; + double absolute_value; + int size; + + absolute_value = fabs(number); + + /* + * First choose format - scientific or regular floating point. + * In either case, result is in work, and after_fraction points + * just past the fractional part. + */ + if ( ((absolute_value > UPPER_DOUBLE) || + (absolute_value < LOWER_DOUBLE)) && + (absolute_value != 0.0) ) { + /* Use scientific notation */ + integer_place = DBL_DIG + EXPONENT_DIGITS + 1; + fraction_place = DBL_DIG - 1; + size = snprintf(work, sizeof(work),"%*.*e", + integer_place, fraction_place, number); + while ((size > 0) && (work[size] != 'e')) size--; + after_fraction = work + size; + + } + else { + /* Use regular notation */ + if (absolute_value > 0.0) + integer_place = 1 + (int)log10(absolute_value); + else + integer_place = 0; + fraction_place = (integer_place > 0) + ? DBL_DIG - integer_place + : DBL_DIG; + size = snprintf(work, sizeof(work), "%0.*f", + fraction_place, number); + after_fraction = work + size; + } + + /* Remove fractional trailing zeroes */ + ptr = after_fraction; + while (*(--ptr) == '0') + ; + if (*ptr != '.') + ptr++; + while ((*ptr++ = *after_fraction++) != 0); + + /* Finally copy result back to caller */ + size = strlen(work) + 1; + if (size > buffersize) { + work[buffersize - 1] = 0; + size = buffersize; + } + memmove(buffer, work, size); + } + break; + } +} + + +/************************************************************************ + * * + * Routines to handle NodeSets * + * * + ************************************************************************/ + +/** + * xmlXPathOrderDocElems: + * @doc: an input document + * + * Call this routine to speed up XPath computation on static documents. + * This stamps all the element nodes with the document order + * Like for line information, the order is kept in the element->content + * field, the value stored is actually - the node number (starting at -1) + * to be able to differentiate from line numbers. + * + * Returns the number of elements found in the document or -1 in case + * of error. + */ +long +xmlXPathOrderDocElems(xmlDocPtr doc) { + long count = 0; + xmlNodePtr cur; + + if (doc == NULL) + return(-1); + cur = doc->children; + while (cur != NULL) { + if (cur->type == XML_ELEMENT_NODE) { + cur->content = (void *) (-(++count)); + if (cur->children != NULL) { + cur = cur->children; + continue; + } + } + if (cur->next != NULL) { + cur = cur->next; + continue; + } + do { + cur = cur->parent; + if (cur == NULL) + break; + if (cur == (xmlNodePtr) doc) { + cur = NULL; + break; + } + if (cur->next != NULL) { + cur = cur->next; + break; + } + } while (cur != NULL); + } + return(count); +} + +/** + * xmlXPathCmpNodes: + * @node1: the first node + * @node2: the second node + * + * Compare two nodes w.r.t document order + * + * Returns -2 in case of error 1 if first point < second point, 0 if + * it's the same node, -1 otherwise + */ +int +xmlXPathCmpNodes(xmlNodePtr node1, xmlNodePtr node2) { + int depth1, depth2; + int attr1 = 0, attr2 = 0; + xmlNodePtr attrNode1 = NULL, attrNode2 = NULL; + xmlNodePtr cur, root; + + if ((node1 == NULL) || (node2 == NULL)) + return(-2); + /* + * a couple of optimizations which will avoid computations in most cases + */ + if (node1->type == XML_ATTRIBUTE_NODE) { + attr1 = 1; + attrNode1 = node1; + node1 = node1->parent; + } + if (node2->type == XML_ATTRIBUTE_NODE) { + attr2 = 1; + attrNode2 = node2; + node2 = node2->parent; + } + if (node1 == node2) { + if (attr1 == attr2) { + /* not required, but we keep attributes in order */ + if (attr1 != 0) { + cur = attrNode2->prev; + while (cur != NULL) { + if (cur == attrNode1) + return (1); + cur = cur->prev; + } + return (-1); + } + return(0); + } + if (attr2 == 1) + return(1); + return(-1); + } + if ((node1->type == XML_NAMESPACE_DECL) || + (node2->type == XML_NAMESPACE_DECL)) + return(1); + if (node1 == node2->prev) + return(1); + if (node1 == node2->next) + return(-1); + + /* + * Speedup using document order if availble. + */ + if ((node1->type == XML_ELEMENT_NODE) && + (node2->type == XML_ELEMENT_NODE) && + (0 > (long) node1->content) && + (0 > (long) node2->content) && + (node1->doc == node2->doc)) { + long l1, l2; + + l1 = -((long) node1->content); + l2 = -((long) node2->content); + if (l1 < l2) + return(1); + if (l1 > l2) + return(-1); + } + + /* + * compute depth to root + */ + for (depth2 = 0, cur = node2;cur->parent != NULL;cur = cur->parent) { + if (cur == node1) + return(1); + depth2++; + } + root = cur; + for (depth1 = 0, cur = node1;cur->parent != NULL;cur = cur->parent) { + if (cur == node2) + return(-1); + depth1++; + } + /* + * Distinct document (or distinct entities :-( ) case. + */ + if (root != cur) { + return(-2); + } + /* + * get the nearest common ancestor. + */ + while (depth1 > depth2) { + depth1--; + node1 = node1->parent; + } + while (depth2 > depth1) { + depth2--; + node2 = node2->parent; + } + while (node1->parent != node2->parent) { + node1 = node1->parent; + node2 = node2->parent; + /* should not happen but just in case ... */ + if ((node1 == NULL) || (node2 == NULL)) + return(-2); + } + /* + * Find who's first. + */ + if (node1 == node2->prev) + return(1); + if (node1 == node2->next) + return(-1); + /* + * Speedup using document order if availble. + */ + if ((node1->type == XML_ELEMENT_NODE) && + (node2->type == XML_ELEMENT_NODE) && + (0 > (long) node1->content) && + (0 > (long) node2->content) && + (node1->doc == node2->doc)) { + long l1, l2; + + l1 = -((long) node1->content); + l2 = -((long) node2->content); + if (l1 < l2) + return(1); + if (l1 > l2) + return(-1); + } + + for (cur = node1->next;cur != NULL;cur = cur->next) + if (cur == node2) + return(1); + return(-1); /* assume there is no sibling list corruption */ +} + +#ifdef XP_OPTIMIZED_NON_ELEM_COMPARISON +/** + * xmlXPathCmpNodesExt: + * @node1: the first node + * @node2: the second node + * + * Compare two nodes w.r.t document order. + * This one is optimized for handling of non-element nodes. + * + * Returns -2 in case of error 1 if first point < second point, 0 if + * it's the same node, -1 otherwise + */ +static int +xmlXPathCmpNodesExt(xmlNodePtr node1, xmlNodePtr node2) { + int depth1, depth2; + int misc = 0, precedence1 = 0, precedence2 = 0; + xmlNodePtr miscNode1 = NULL, miscNode2 = NULL; + xmlNodePtr cur, root; + long l1, l2; + + if ((node1 == NULL) || (node2 == NULL)) + return(-2); + + if (node1 == node2) + return(0); + + /* + * a couple of optimizations which will avoid computations in most cases + */ + switch (node1->type) { + case XML_ELEMENT_NODE: + if (node2->type == XML_ELEMENT_NODE) { + if ((0 > (long) node1->content) && /* TODO: Would a != 0 suffice here? */ + (0 > (long) node2->content) && + (node1->doc == node2->doc)) + { + l1 = -((long) node1->content); + l2 = -((long) node2->content); + if (l1 < l2) + return(1); + if (l1 > l2) + return(-1); + } else + goto turtle_comparison; + } + break; + case XML_ATTRIBUTE_NODE: + precedence1 = 1; /* element is owner */ + miscNode1 = node1; + node1 = node1->parent; + misc = 1; + break; + case XML_TEXT_NODE: + case XML_CDATA_SECTION_NODE: + case XML_COMMENT_NODE: + case XML_PI_NODE: { + miscNode1 = node1; + /* + * Find nearest element node. + */ + if (node1->prev != NULL) { + do { + node1 = node1->prev; + if (node1->type == XML_ELEMENT_NODE) { + precedence1 = 3; /* element in prev-sibl axis */ + break; + } + if (node1->prev == NULL) { + precedence1 = 2; /* element is parent */ + /* + * URGENT TODO: Are there any cases, where the + * parent of such a node is not an element node? + */ + node1 = node1->parent; + break; + } + } while (1); + } else { + precedence1 = 2; /* element is parent */ + node1 = node1->parent; + } + if ((node1 == NULL) || (node1->type != XML_ELEMENT_NODE)) { + /* + * Fallback for whatever case. + */ + node1 = miscNode1; + precedence1 = 0; + } else + misc = 1; + } + break; + case XML_NAMESPACE_DECL: + /* + * TODO: why do we return 1 for namespace nodes? + */ + return(1); + default: + break; + } + switch (node2->type) { + case XML_ELEMENT_NODE: + break; + case XML_ATTRIBUTE_NODE: + precedence2 = 1; /* element is owner */ + miscNode2 = node2; + node2 = node2->parent; + misc = 1; + break; + case XML_TEXT_NODE: + case XML_CDATA_SECTION_NODE: + case XML_COMMENT_NODE: + case XML_PI_NODE: { + miscNode2 = node2; + if (node2->prev != NULL) { + do { + node2 = node2->prev; + if (node2->type == XML_ELEMENT_NODE) { + precedence2 = 3; /* element in prev-sibl axis */ + break; + } + if (node2->prev == NULL) { + precedence2 = 2; /* element is parent */ + node2 = node2->parent; + break; + } + } while (1); + } else { + precedence2 = 2; /* element is parent */ + node2 = node2->parent; + } + if ((node2 == NULL) || (node2->type != XML_ELEMENT_NODE) || + (0 <= (long) node1->content)) + { + node2 = miscNode2; + precedence2 = 0; + } else + misc = 1; + } + break; + case XML_NAMESPACE_DECL: + return(1); + default: + break; + } + if (misc) { + if (node1 == node2) { + if (precedence1 == precedence2) { + /* + * The ugly case; but normally there aren't many + * adjacent non-element nodes around. + */ + cur = miscNode2->prev; + while (cur != NULL) { + if (cur == miscNode1) + return(1); + if (cur->type == XML_ELEMENT_NODE) + return(-1); + cur = cur->prev; + } + return (-1); + } else { + /* + * Evaluate based on higher precedence wrt to the element. + * TODO: This assumes attributes are sorted before content. + * Is this 100% correct? + */ + if (precedence1 < precedence2) + return(1); + else + return(-1); + } + } + /* + * Special case: One of the helper-elements is contained by the other. + * + * + * Text-1(precedence1 == 2) + * + * Text-6(precedence2 == 3) + * + */ + if ((precedence2 == 3) && (precedence1 > 1)) { + cur = node1->parent; + while (cur) { + if (cur == node2) + return(1); + cur = cur->parent; + } + } + if ((precedence1 == 3) && (precedence2 > 1)) { + cur = node2->parent; + while (cur) { + if (cur == node1) + return(-1); + cur = cur->parent; + } + } + } + + /* + * Speedup using document order if availble. + */ + if ((node1->type == XML_ELEMENT_NODE) && + (node2->type == XML_ELEMENT_NODE) && + (0 > (long) node1->content) && + (0 > (long) node2->content) && + (node1->doc == node2->doc)) { + + l1 = -((long) node1->content); + l2 = -((long) node2->content); + if (l1 < l2) + return(1); + if (l1 > l2) + return(-1); + } + +turtle_comparison: + + if (node1 == node2->prev) + return(1); + if (node1 == node2->next) + return(-1); + /* + * compute depth to root + */ + for (depth2 = 0, cur = node2;cur->parent != NULL;cur = cur->parent) { + if (cur == node1) + return(1); + depth2++; + } + root = cur; + for (depth1 = 0, cur = node1;cur->parent != NULL;cur = cur->parent) { + if (cur == node2) + return(-1); + depth1++; + } + /* + * Distinct document (or distinct entities :-( ) case. + */ + if (root != cur) { + return(-2); + } + /* + * get the nearest common ancestor. + */ + while (depth1 > depth2) { + depth1--; + node1 = node1->parent; + } + while (depth2 > depth1) { + depth2--; + node2 = node2->parent; + } + while (node1->parent != node2->parent) { + node1 = node1->parent; + node2 = node2->parent; + /* should not happen but just in case ... */ + if ((node1 == NULL) || (node2 == NULL)) + return(-2); + } + /* + * Find who's first. + */ + if (node1 == node2->prev) + return(1); + if (node1 == node2->next) + return(-1); + /* + * Speedup using document order if availble. + */ + if ((node1->type == XML_ELEMENT_NODE) && + (node2->type == XML_ELEMENT_NODE) && + (0 > (long) node1->content) && + (0 > (long) node2->content) && + (node1->doc == node2->doc)) { + + l1 = -((long) node1->content); + l2 = -((long) node2->content); + if (l1 < l2) + return(1); + if (l1 > l2) + return(-1); + } + + for (cur = node1->next;cur != NULL;cur = cur->next) + if (cur == node2) + return(1); + return(-1); /* assume there is no sibling list corruption */ +} +#endif /* XP_OPTIMIZED_NON_ELEM_COMPARISON */ + +/** + * xmlXPathNodeSetSort: + * @set: the node set + * + * Sort the node set in document order + */ +void +xmlXPathNodeSetSort(xmlNodeSetPtr set) { + int i, j, incr, len; + xmlNodePtr tmp; + + if (set == NULL) + return; + + /* Use Shell's sort to sort the node-set */ + len = set->nodeNr; + for (incr = len / 2; incr > 0; incr /= 2) { + for (i = incr; i < len; i++) { + j = i - incr; + while (j >= 0) { +#ifdef XP_OPTIMIZED_NON_ELEM_COMPARISON + if (xmlXPathCmpNodesExt(set->nodeTab[j], + set->nodeTab[j + incr]) == -1) +#else + if (xmlXPathCmpNodes(set->nodeTab[j], + set->nodeTab[j + incr]) == -1) +#endif + { + tmp = set->nodeTab[j]; + set->nodeTab[j] = set->nodeTab[j + incr]; + set->nodeTab[j + incr] = tmp; + j -= incr; + } else + break; + } + } + } +} + +#define XML_NODESET_DEFAULT 10 +/** + * xmlXPathNodeSetDupNs: + * @node: the parent node of the namespace XPath node + * @ns: the libxml namespace declaration node. + * + * Namespace node in libxml don't match the XPath semantic. In a node set + * the namespace nodes are duplicated and the next pointer is set to the + * parent node in the XPath semantic. + * + * Returns the newly created object. + */ +static xmlNodePtr +xmlXPathNodeSetDupNs(xmlNodePtr node, xmlNsPtr ns) { + xmlNsPtr cur; + + if ((ns == NULL) || (ns->type != XML_NAMESPACE_DECL)) + return(NULL); + if ((node == NULL) || (node->type == XML_NAMESPACE_DECL)) + return((xmlNodePtr) ns); + + /* + * Allocate a new Namespace and fill the fields. + */ + cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs)); + if (cur == NULL) { + xmlXPathErrMemory(NULL, "duplicating namespace\n"); + return(NULL); + } + memset(cur, 0, sizeof(xmlNs)); + cur->type = XML_NAMESPACE_DECL; + if (ns->href != NULL) + cur->href = xmlStrdup(ns->href); + if (ns->prefix != NULL) + cur->prefix = xmlStrdup(ns->prefix); + cur->next = (xmlNsPtr) node; + return((xmlNodePtr) cur); +} + +/** + * xmlXPathNodeSetFreeNs: + * @ns: the XPath namespace node found in a nodeset. + * + * Namespace nodes in libxml don't match the XPath semantic. In a node set + * the namespace nodes are duplicated and the next pointer is set to the + * parent node in the XPath semantic. Check if such a node needs to be freed + */ +void +xmlXPathNodeSetFreeNs(xmlNsPtr ns) { + if ((ns == NULL) || (ns->type != XML_NAMESPACE_DECL)) + return; + + if ((ns->next != NULL) && (ns->next->type != XML_NAMESPACE_DECL)) { + if (ns->href != NULL) + xmlFree((xmlChar *)ns->href); + if (ns->prefix != NULL) + xmlFree((xmlChar *)ns->prefix); + xmlFree(ns); + } +} + +/** + * xmlXPathNodeSetCreate: + * @val: an initial xmlNodePtr, or NULL + * + * Create a new xmlNodeSetPtr of type double and of value @val + * + * Returns the newly created object. + */ +xmlNodeSetPtr +xmlXPathNodeSetCreate(xmlNodePtr val) { + xmlNodeSetPtr ret; + + ret = (xmlNodeSetPtr) xmlMalloc(sizeof(xmlNodeSet)); + if (ret == NULL) { + xmlXPathErrMemory(NULL, "creating nodeset\n"); + return(NULL); + } + memset(ret, 0 , (size_t) sizeof(xmlNodeSet)); + if (val != NULL) { + ret->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT * + sizeof(xmlNodePtr)); + if (ret->nodeTab == NULL) { + xmlXPathErrMemory(NULL, "creating nodeset\n"); + xmlFree(ret); + return(NULL); + } + memset(ret->nodeTab, 0 , + XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr)); + ret->nodeMax = XML_NODESET_DEFAULT; + if (val->type == XML_NAMESPACE_DECL) { + xmlNsPtr ns = (xmlNsPtr) val; + + ret->nodeTab[ret->nodeNr++] = + xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns); + } else + ret->nodeTab[ret->nodeNr++] = val; + } + return(ret); +} + +/** + * xmlXPathNodeSetCreateSize: + * @size: the initial size of the set + * + * Create a new xmlNodeSetPtr of type double and of value @val + * + * Returns the newly created object. + */ +static xmlNodeSetPtr +xmlXPathNodeSetCreateSize(int size) { + xmlNodeSetPtr ret; + + ret = (xmlNodeSetPtr) xmlMalloc(sizeof(xmlNodeSet)); + if (ret == NULL) { + xmlXPathErrMemory(NULL, "creating nodeset\n"); + return(NULL); + } + memset(ret, 0 , (size_t) sizeof(xmlNodeSet)); + if (size < XML_NODESET_DEFAULT) + size = XML_NODESET_DEFAULT; + ret->nodeTab = (xmlNodePtr *) xmlMalloc(size * sizeof(xmlNodePtr)); + if (ret->nodeTab == NULL) { + xmlXPathErrMemory(NULL, "creating nodeset\n"); + xmlFree(ret); + return(NULL); + } + memset(ret->nodeTab, 0 , size * (size_t) sizeof(xmlNodePtr)); + ret->nodeMax = size; + return(ret); +} + +/** + * xmlXPathNodeSetContains: + * @cur: the node-set + * @val: the node + * + * checks whether @cur contains @val + * + * Returns true (1) if @cur contains @val, false (0) otherwise + */ +int +xmlXPathNodeSetContains (xmlNodeSetPtr cur, xmlNodePtr val) { + int i; + + if ((cur == NULL) || (val == NULL)) return(0); + if (val->type == XML_NAMESPACE_DECL) { + for (i = 0; i < cur->nodeNr; i++) { + if (cur->nodeTab[i]->type == XML_NAMESPACE_DECL) { + xmlNsPtr ns1, ns2; + + ns1 = (xmlNsPtr) val; + ns2 = (xmlNsPtr) cur->nodeTab[i]; + if (ns1 == ns2) + return(1); + if ((ns1->next != NULL) && (ns2->next == ns1->next) && + (xmlStrEqual(ns1->prefix, ns2->prefix))) + return(1); + } + } + } else { + for (i = 0; i < cur->nodeNr; i++) { + if (cur->nodeTab[i] == val) + return(1); + } + } + return(0); +} + +/** + * xmlXPathNodeSetAddNs: + * @cur: the initial node set + * @node: the hosting node + * @ns: a the namespace node + * + * add a new namespace node to an existing NodeSet + */ +void +xmlXPathNodeSetAddNs(xmlNodeSetPtr cur, xmlNodePtr node, xmlNsPtr ns) { + int i; + + + if ((cur == NULL) || (ns == NULL) || (node == NULL) || + (ns->type != XML_NAMESPACE_DECL) || + (node->type != XML_ELEMENT_NODE)) + return; + + /* @@ with_ns to check whether namespace nodes should be looked at @@ */ + /* + * prevent duplicates + */ + for (i = 0;i < cur->nodeNr;i++) { + if ((cur->nodeTab[i] != NULL) && + (cur->nodeTab[i]->type == XML_NAMESPACE_DECL) && + (((xmlNsPtr)cur->nodeTab[i])->next == (xmlNsPtr) node) && + (xmlStrEqual(ns->prefix, ((xmlNsPtr)cur->nodeTab[i])->prefix))) + return; + } + + /* + * grow the nodeTab if needed + */ + if (cur->nodeMax == 0) { + cur->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT * + sizeof(xmlNodePtr)); + if (cur->nodeTab == NULL) { + xmlXPathErrMemory(NULL, "growing nodeset\n"); + return; + } + memset(cur->nodeTab, 0 , + XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr)); + cur->nodeMax = XML_NODESET_DEFAULT; + } else if (cur->nodeNr == cur->nodeMax) { + xmlNodePtr *temp; + + cur->nodeMax *= 2; + temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax * + sizeof(xmlNodePtr)); + if (temp == NULL) { + xmlXPathErrMemory(NULL, "growing nodeset\n"); + return; + } + cur->nodeTab = temp; + } + cur->nodeTab[cur->nodeNr++] = xmlXPathNodeSetDupNs(node, ns); +} + +/** + * xmlXPathNodeSetAdd: + * @cur: the initial node set + * @val: a new xmlNodePtr + * + * add a new xmlNodePtr to an existing NodeSet + */ +void +xmlXPathNodeSetAdd(xmlNodeSetPtr cur, xmlNodePtr val) { + int i; + + if ((cur == NULL) || (val == NULL)) return; + +#if 0 + if ((val->type == XML_ELEMENT_NODE) && (val->name[0] == ' ')) + return; /* an XSLT fake node */ +#endif + + /* @@ with_ns to check whether namespace nodes should be looked at @@ */ + /* + * prevent duplcates + */ + for (i = 0;i < cur->nodeNr;i++) + if (cur->nodeTab[i] == val) return; + + /* + * grow the nodeTab if needed + */ + if (cur->nodeMax == 0) { + cur->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT * + sizeof(xmlNodePtr)); + if (cur->nodeTab == NULL) { + xmlXPathErrMemory(NULL, "growing nodeset\n"); + return; + } + memset(cur->nodeTab, 0 , + XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr)); + cur->nodeMax = XML_NODESET_DEFAULT; + } else if (cur->nodeNr == cur->nodeMax) { + xmlNodePtr *temp; + + cur->nodeMax *= 2; + temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax * + sizeof(xmlNodePtr)); + if (temp == NULL) { + xmlXPathErrMemory(NULL, "growing nodeset\n"); + return; + } + cur->nodeTab = temp; + } + if (val->type == XML_NAMESPACE_DECL) { + xmlNsPtr ns = (xmlNsPtr) val; + + cur->nodeTab[cur->nodeNr++] = + xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns); + } else + cur->nodeTab[cur->nodeNr++] = val; +} + +/** + * xmlXPathNodeSetAddUnique: + * @cur: the initial node set + * @val: a new xmlNodePtr + * + * add a new xmlNodePtr to an existing NodeSet, optimized version + * when we are sure the node is not already in the set. + */ +void +xmlXPathNodeSetAddUnique(xmlNodeSetPtr cur, xmlNodePtr val) { + if ((cur == NULL) || (val == NULL)) return; + +#if 0 + if ((val->type == XML_ELEMENT_NODE) && (val->name[0] == ' ')) + return; /* an XSLT fake node */ +#endif + + /* @@ with_ns to check whether namespace nodes should be looked at @@ */ + /* + * grow the nodeTab if needed + */ + if (cur->nodeMax == 0) { + cur->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT * + sizeof(xmlNodePtr)); + if (cur->nodeTab == NULL) { + xmlXPathErrMemory(NULL, "growing nodeset\n"); + return; + } + memset(cur->nodeTab, 0 , + XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr)); + cur->nodeMax = XML_NODESET_DEFAULT; + } else if (cur->nodeNr == cur->nodeMax) { + xmlNodePtr *temp; + + cur->nodeMax *= 2; + temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax * + sizeof(xmlNodePtr)); + if (temp == NULL) { + xmlXPathErrMemory(NULL, "growing nodeset\n"); + return; + } + cur->nodeTab = temp; + } + if (val->type == XML_NAMESPACE_DECL) { + xmlNsPtr ns = (xmlNsPtr) val; + + cur->nodeTab[cur->nodeNr++] = + xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns); + } else + cur->nodeTab[cur->nodeNr++] = val; +} + +/** + * xmlXPathNodeSetMerge: + * @val1: the first NodeSet or NULL + * @val2: the second NodeSet + * + * Merges two nodesets, all nodes from @val2 are added to @val1 + * if @val1 is NULL, a new set is created and copied from @val2 + * + * Returns @val1 once extended or NULL in case of error. + */ +xmlNodeSetPtr +xmlXPathNodeSetMerge(xmlNodeSetPtr val1, xmlNodeSetPtr val2) { + int i, j, initNr, skip; + xmlNodePtr n1, n2; + + if (val2 == NULL) return(val1); + if (val1 == NULL) { + val1 = xmlXPathNodeSetCreate(NULL); +#if 0 + /* + * TODO: The optimization won't work in every case, since + * those nasty namespace nodes need to be added with + * xmlXPathNodeSetDupNs() to the set; thus a pure + * memcpy is not possible. + * If there was a flag on the nodesetval, indicating that + * some temporary nodes are in, that would be helpfull. + */ + /* + * Optimization: Create an equally sized node-set + * and memcpy the content. + */ + val1 = xmlXPathNodeSetCreateSize(val2->nodeNr); + if (val1 == NULL) + return(NULL); + if (val2->nodeNr != 0) { + if (val2->nodeNr == 1) + *(val1->nodeTab) = *(val2->nodeTab); + else { + memcpy(val1->nodeTab, val2->nodeTab, + val2->nodeNr * sizeof(xmlNodePtr)); + } + val1->nodeNr = val2->nodeNr; + } + return(val1); +#endif + } + + /* @@ with_ns to check whether namespace nodes should be looked at @@ */ + initNr = val1->nodeNr; + + for (i = 0;i < val2->nodeNr;i++) { + n2 = val2->nodeTab[i]; + /* + * check against duplicates + */ + skip = 0; + for (j = 0; j < initNr; j++) { + n1 = val1->nodeTab[j]; + if (n1 == n2) { + skip = 1; + break; + } else if ((n1->type == XML_NAMESPACE_DECL) && + (n2->type == XML_NAMESPACE_DECL)) { + if ((((xmlNsPtr) n1)->next == ((xmlNsPtr) n2)->next) && + (xmlStrEqual(((xmlNsPtr) n1)->prefix, + ((xmlNsPtr) n2)->prefix))) + { + skip = 1; + break; + } + } + } + if (skip) + continue; + + /* + * grow the nodeTab if needed + */ + if (val1->nodeMax == 0) { + val1->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT * + sizeof(xmlNodePtr)); + if (val1->nodeTab == NULL) { + xmlXPathErrMemory(NULL, "merging nodeset\n"); + return(NULL); + } + memset(val1->nodeTab, 0 , + XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr)); + val1->nodeMax = XML_NODESET_DEFAULT; + } else if (val1->nodeNr == val1->nodeMax) { + xmlNodePtr *temp; + + val1->nodeMax *= 2; + temp = (xmlNodePtr *) xmlRealloc(val1->nodeTab, val1->nodeMax * + sizeof(xmlNodePtr)); + if (temp == NULL) { + xmlXPathErrMemory(NULL, "merging nodeset\n"); + return(NULL); + } + val1->nodeTab = temp; + } + if (n2->type == XML_NAMESPACE_DECL) { + xmlNsPtr ns = (xmlNsPtr) n2; + + val1->nodeTab[val1->nodeNr++] = + xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns); + } else + val1->nodeTab[val1->nodeNr++] = n2; + } + + return(val1); +} + +#if 0 /* xmlXPathNodeSetMergeUnique() is currently not used anymore */ +/** + * xmlXPathNodeSetMergeUnique: + * @val1: the first NodeSet or NULL + * @val2: the second NodeSet + * + * Merges two nodesets, all nodes from @val2 are added to @val1 + * if @val1 is NULL, a new set is created and copied from @val2 + * + * Returns @val1 once extended or NULL in case of error. + */ +static xmlNodeSetPtr +xmlXPathNodeSetMergeUnique(xmlNodeSetPtr val1, xmlNodeSetPtr val2) { + int i; + + if (val2 == NULL) return(val1); + if (val1 == NULL) { + val1 = xmlXPathNodeSetCreate(NULL); + } + + /* @@ with_ns to check whether namespace nodes should be looked at @@ */ + + for (i = 0;i < val2->nodeNr;i++) { + /* + * grow the nodeTab if needed + */ + if (val1->nodeMax == 0) { + val1->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT * + sizeof(xmlNodePtr)); + if (val1->nodeTab == NULL) { + xmlXPathErrMemory(NULL, "merging nodeset\n"); + return(NULL); + } + memset(val1->nodeTab, 0 , + XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr)); + val1->nodeMax = XML_NODESET_DEFAULT; + } else if (val1->nodeNr == val1->nodeMax) { + xmlNodePtr *temp; + + val1->nodeMax *= 2; + temp = (xmlNodePtr *) xmlRealloc(val1->nodeTab, val1->nodeMax * + sizeof(xmlNodePtr)); + if (temp == NULL) { + xmlXPathErrMemory(NULL, "merging nodeset\n"); + return(NULL); + } + val1->nodeTab = temp; + } + if (val2->nodeTab[i]->type == XML_NAMESPACE_DECL) { + xmlNsPtr ns = (xmlNsPtr) val2->nodeTab[i]; + + val1->nodeTab[val1->nodeNr++] = + xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns); + } else + val1->nodeTab[val1->nodeNr++] = val2->nodeTab[i]; + } + + return(val1); +} +#endif /* xmlXPathNodeSetMergeUnique() is currently not used anymore */ + +/** + * xmlXPathNodeSetMergeAndClear: + * @set1: the first NodeSet or NULL + * @set2: the second NodeSet + * @hasSet2NsNodes: 1 if set2 contains namespaces nodes + * + * Merges two nodesets, all nodes from @set2 are added to @set1 + * if @set1 is NULL, a new set is created and copied from @set2. + * Checks for duplicate nodes. Clears set2. + * + * Returns @set1 once extended or NULL in case of error. + */ +static xmlNodeSetPtr +xmlXPathNodeSetMergeAndClear(xmlNodeSetPtr set1, xmlNodeSetPtr set2, + int hasNullEntries) +{ + if ((set1 == NULL) && (hasNullEntries == 0)) { + /* + * Note that doing a memcpy of the list, namespace nodes are + * just assigned to set1, since set2 is cleared anyway. + */ + set1 = xmlXPathNodeSetCreateSize(set2->nodeNr); + if (set1 == NULL) + return(NULL); + if (set2->nodeNr != 0) { + memcpy(set1->nodeTab, set2->nodeTab, + set2->nodeNr * sizeof(xmlNodePtr)); + set1->nodeNr = set2->nodeNr; + } + } else { + int i, j, initNbSet1; + xmlNodePtr n1, n2; + + if (set1 == NULL) + set1 = xmlXPathNodeSetCreate(NULL); + + initNbSet1 = set1->nodeNr; + for (i = 0;i < set2->nodeNr;i++) { + n2 = set2->nodeTab[i]; + /* + * Skip NULLed entries. + */ + if (n2 == NULL) + continue; + /* + * Skip duplicates. + */ + for (j = 0; j < initNbSet1; j++) { + n1 = set1->nodeTab[j]; + if (n1 == n2) { + goto skip_node; + } else if ((n1->type == XML_NAMESPACE_DECL) && + (n2->type == XML_NAMESPACE_DECL)) + { + if ((((xmlNsPtr) n1)->next == ((xmlNsPtr) n2)->next) && + (xmlStrEqual(((xmlNsPtr) n1)->prefix, + ((xmlNsPtr) n2)->prefix))) + { + /* + * Free the namespace node. + */ + set2->nodeTab[i] = NULL; + xmlXPathNodeSetFreeNs((xmlNsPtr) n2); + goto skip_node; + } + } + } + /* + * grow the nodeTab if needed + */ + if (set1->nodeMax == 0) { + set1->nodeTab = (xmlNodePtr *) xmlMalloc( + XML_NODESET_DEFAULT * sizeof(xmlNodePtr)); + if (set1->nodeTab == NULL) { + xmlXPathErrMemory(NULL, "merging nodeset\n"); + return(NULL); + } + memset(set1->nodeTab, 0, + XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr)); + set1->nodeMax = XML_NODESET_DEFAULT; + } else if (set1->nodeNr >= set1->nodeMax) { + xmlNodePtr *temp; + + set1->nodeMax *= 2; + temp = (xmlNodePtr *) xmlRealloc( + set1->nodeTab, set1->nodeMax * sizeof(xmlNodePtr)); + if (temp == NULL) { + xmlXPathErrMemory(NULL, "merging nodeset\n"); + return(NULL); + } + set1->nodeTab = temp; + } + if (n2->type == XML_NAMESPACE_DECL) { + xmlNsPtr ns = (xmlNsPtr) n2; + + set1->nodeTab[set1->nodeNr++] = + xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns); + } else + set1->nodeTab[set1->nodeNr++] = n2; +skip_node: + {} + } + } + set2->nodeNr = 0; + return(set1); +} + +/** + * xmlXPathNodeSetMergeAndClearNoDupls: + * @set1: the first NodeSet or NULL + * @set2: the second NodeSet + * @hasSet2NsNodes: 1 if set2 contains namespaces nodes + * + * Merges two nodesets, all nodes from @set2 are added to @set1 + * if @set1 is NULL, a new set is created and copied from @set2. + * Doesn't chack for duplicate nodes. Clears set2. + * + * Returns @set1 once extended or NULL in case of error. + */ +static xmlNodeSetPtr +xmlXPathNodeSetMergeAndClearNoDupls(xmlNodeSetPtr set1, xmlNodeSetPtr set2, + int hasNullEntries) +{ + if (set2 == NULL) + return(set1); + if ((set1 == NULL) && (hasNullEntries == 0)) { + /* + * Note that doing a memcpy of the list, namespace nodes are + * just assigned to set1, since set2 is cleared anyway. + */ + set1 = xmlXPathNodeSetCreateSize(set2->nodeNr); + if (set1 == NULL) + return(NULL); + if (set2->nodeNr != 0) { + memcpy(set1->nodeTab, set2->nodeTab, + set2->nodeNr * sizeof(xmlNodePtr)); + set1->nodeNr = set2->nodeNr; + } + } else { + int i; + xmlNodePtr n2; + + if (set1 == NULL) + set1 = xmlXPathNodeSetCreate(NULL); + + for (i = 0;i < set2->nodeNr;i++) { + n2 = set2->nodeTab[i]; + /* + * Skip NULLed entries. + */ + if (n2 == NULL) + continue; + if (set1->nodeMax == 0) { + set1->nodeTab = (xmlNodePtr *) xmlMalloc( + XML_NODESET_DEFAULT * sizeof(xmlNodePtr)); + if (set1->nodeTab == NULL) { + xmlXPathErrMemory(NULL, "merging nodeset\n"); + return(NULL); + } + memset(set1->nodeTab, 0, + XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr)); + set1->nodeMax = XML_NODESET_DEFAULT; + } else if (set1->nodeNr >= set1->nodeMax) { + xmlNodePtr *temp; + + set1->nodeMax *= 2; + temp = (xmlNodePtr *) xmlRealloc( + set1->nodeTab, set1->nodeMax * sizeof(xmlNodePtr)); + if (temp == NULL) { + xmlXPathErrMemory(NULL, "merging nodeset\n"); + return(NULL); + } + set1->nodeTab = temp; + } + set1->nodeTab[set1->nodeNr++] = n2; + } + } + set2->nodeNr = 0; + return(set1); +} + +/** + * xmlXPathNodeSetDel: + * @cur: the initial node set + * @val: an xmlNodePtr + * + * Removes an xmlNodePtr from an existing NodeSet + */ +void +xmlXPathNodeSetDel(xmlNodeSetPtr cur, xmlNodePtr val) { + int i; + + if (cur == NULL) return; + if (val == NULL) return; + + /* + * find node in nodeTab + */ + for (i = 0;i < cur->nodeNr;i++) + if (cur->nodeTab[i] == val) break; + + if (i >= cur->nodeNr) { /* not found */ +#ifdef DEBUG + xmlGenericError(xmlGenericErrorContext, + "xmlXPathNodeSetDel: Node %s wasn't found in NodeList\n", + val->name); +#endif + return; + } + if ((cur->nodeTab[i] != NULL) && + (cur->nodeTab[i]->type == XML_NAMESPACE_DECL)) + xmlXPathNodeSetFreeNs((xmlNsPtr) cur->nodeTab[i]); + cur->nodeNr--; + for (;i < cur->nodeNr;i++) + cur->nodeTab[i] = cur->nodeTab[i + 1]; + cur->nodeTab[cur->nodeNr] = NULL; +} + +/** + * xmlXPathNodeSetRemove: + * @cur: the initial node set + * @val: the index to remove + * + * Removes an entry from an existing NodeSet list. + */ +void +xmlXPathNodeSetRemove(xmlNodeSetPtr cur, int val) { + if (cur == NULL) return; + if (val >= cur->nodeNr) return; + if ((cur->nodeTab[val] != NULL) && + (cur->nodeTab[val]->type == XML_NAMESPACE_DECL)) + xmlXPathNodeSetFreeNs((xmlNsPtr) cur->nodeTab[val]); + cur->nodeNr--; + for (;val < cur->nodeNr;val++) + cur->nodeTab[val] = cur->nodeTab[val + 1]; + cur->nodeTab[cur->nodeNr] = NULL; +} + +/** + * xmlXPathFreeNodeSet: + * @obj: the xmlNodeSetPtr to free + * + * Free the NodeSet compound (not the actual nodes !). + */ +void +xmlXPathFreeNodeSet(xmlNodeSetPtr obj) { + if (obj == NULL) return; + if (obj->nodeTab != NULL) { + int i; + + /* @@ with_ns to check whether namespace nodes should be looked at @@ */ + for (i = 0;i < obj->nodeNr;i++) + if ((obj->nodeTab[i] != NULL) && + (obj->nodeTab[i]->type == XML_NAMESPACE_DECL)) + xmlXPathNodeSetFreeNs((xmlNsPtr) obj->nodeTab[i]); + xmlFree(obj->nodeTab); + } + xmlFree(obj); +} + +/** + * xmlXPathNodeSetClear: + * @set: the node set to clear + * + * Clears the list from all temporary XPath objects (e.g. namespace nodes + * are feed), but does *not* free the list itself. Sets the length of the + * list to 0. + */ +static void +xmlXPathNodeSetClear(xmlNodeSetPtr set, int hasNsNodes) +{ + if ((set == NULL) || (set->nodeNr <= 0)) + return; + else if (hasNsNodes) { + int i; + xmlNodePtr node; + + for (i = 0; i < set->nodeNr; i++) { + node = set->nodeTab[i]; + if ((node != NULL) && + (node->type == XML_NAMESPACE_DECL)) + xmlXPathNodeSetFreeNs((xmlNsPtr) node); + } + } + set->nodeNr = 0; +} + +/** + * xmlXPathNodeSetClearFromPos: + * @set: the node set to be cleared + * @pos: the start position to clear from + * + * Clears the list from temporary XPath objects (e.g. namespace nodes + * are feed) starting with the entry at @pos, but does *not* free the list + * itself. Sets the length of the list to @pos. + */ +static void +xmlXPathNodeSetClearFromPos(xmlNodeSetPtr set, int pos, int hasNsNodes) +{ + if ((set == NULL) || (set->nodeNr <= 0) || (pos >= set->nodeNr)) + return; + else if ((hasNsNodes)) { + int i; + xmlNodePtr node; + + for (i = pos; i < set->nodeNr; i++) { + node = set->nodeTab[i]; + if ((node != NULL) && + (node->type == XML_NAMESPACE_DECL)) + xmlXPathNodeSetFreeNs((xmlNsPtr) node); + } + } + set->nodeNr = pos; +} + +/** + * xmlXPathFreeValueTree: + * @obj: the xmlNodeSetPtr to free + * + * Free the NodeSet compound and the actual tree, this is different + * from xmlXPathFreeNodeSet() + */ +static void +xmlXPathFreeValueTree(xmlNodeSetPtr obj) { + int i; + + if (obj == NULL) return; + + if (obj->nodeTab != NULL) { + for (i = 0;i < obj->nodeNr;i++) { + if (obj->nodeTab[i] != NULL) { + if (obj->nodeTab[i]->type == XML_NAMESPACE_DECL) { + xmlXPathNodeSetFreeNs((xmlNsPtr) obj->nodeTab[i]); + } else { + xmlFreeNodeList(obj->nodeTab[i]); + } + } + } + xmlFree(obj->nodeTab); + } + xmlFree(obj); +} + +#if defined(DEBUG) || defined(DEBUG_STEP) +/** + * xmlGenericErrorContextNodeSet: + * @output: a FILE * for the output + * @obj: the xmlNodeSetPtr to display + * + * Quick display of a NodeSet + */ +void +xmlGenericErrorContextNodeSet(FILE *output, xmlNodeSetPtr obj) { + int i; + + if (output == NULL) output = xmlGenericErrorContext; + if (obj == NULL) { + fprintf(output, "NodeSet == NULL !\n"); + return; + } + if (obj->nodeNr == 0) { + fprintf(output, "NodeSet is empty\n"); + return; + } + if (obj->nodeTab == NULL) { + fprintf(output, " nodeTab == NULL !\n"); + return; + } + for (i = 0; i < obj->nodeNr; i++) { + if (obj->nodeTab[i] == NULL) { + fprintf(output, " NULL !\n"); + return; + } + if ((obj->nodeTab[i]->type == XML_DOCUMENT_NODE) || + (obj->nodeTab[i]->type == XML_HTML_DOCUMENT_NODE)) + fprintf(output, " /"); + else if (obj->nodeTab[i]->name == NULL) + fprintf(output, " noname!"); + else fprintf(output, " %s", obj->nodeTab[i]->name); + } + fprintf(output, "\n"); +} +#endif + +/** + * xmlXPathNewNodeSet: + * @val: the NodePtr value + * + * Create a new xmlXPathObjectPtr of type NodeSet and initialize + * it with the single Node @val + * + * Returns the newly created object. + */ +xmlXPathObjectPtr +xmlXPathNewNodeSet(xmlNodePtr val) { + xmlXPathObjectPtr ret; + + ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject)); + if (ret == NULL) { + xmlXPathErrMemory(NULL, "creating nodeset\n"); + return(NULL); + } + memset(ret, 0 , (size_t) sizeof(xmlXPathObject)); + ret->type = XPATH_NODESET; + ret->boolval = 0; + ret->nodesetval = xmlXPathNodeSetCreate(val); + /* @@ with_ns to check whether namespace nodes should be looked at @@ */ +#ifdef XP_DEBUG_OBJ_USAGE + xmlXPathDebugObjUsageRequested(NULL, XPATH_NODESET); +#endif + return(ret); +} + +/** + * xmlXPathNewValueTree: + * @val: the NodePtr value + * + * Create a new xmlXPathObjectPtr of type Value Tree (XSLT) and initialize + * it with the tree root @val + * + * Returns the newly created object. + */ +xmlXPathObjectPtr +xmlXPathNewValueTree(xmlNodePtr val) { + xmlXPathObjectPtr ret; + + ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject)); + if (ret == NULL) { + xmlXPathErrMemory(NULL, "creating result value tree\n"); + return(NULL); + } + memset(ret, 0 , (size_t) sizeof(xmlXPathObject)); + ret->type = XPATH_XSLT_TREE; + ret->boolval = 1; + ret->user = (void *) val; + ret->nodesetval = xmlXPathNodeSetCreate(val); +#ifdef XP_DEBUG_OBJ_USAGE + xmlXPathDebugObjUsageRequested(NULL, XPATH_XSLT_TREE); +#endif + return(ret); +} + +/** + * xmlXPathNewNodeSetList: + * @val: an existing NodeSet + * + * Create a new xmlXPathObjectPtr of type NodeSet and initialize + * it with the Nodeset @val + * + * Returns the newly created object. + */ +xmlXPathObjectPtr +xmlXPathNewNodeSetList(xmlNodeSetPtr val) +{ + xmlXPathObjectPtr ret; + int i; + + if (val == NULL) + ret = NULL; + else if (val->nodeTab == NULL) + ret = xmlXPathNewNodeSet(NULL); + else { + ret = xmlXPathNewNodeSet(val->nodeTab[0]); + for (i = 1; i < val->nodeNr; ++i) + xmlXPathNodeSetAddUnique(ret->nodesetval, val->nodeTab[i]); + } + + return (ret); +} + +/** + * xmlXPathWrapNodeSet: + * @val: the NodePtr value + * + * Wrap the Nodeset @val in a new xmlXPathObjectPtr + * + * Returns the newly created object. + */ +xmlXPathObjectPtr +xmlXPathWrapNodeSet(xmlNodeSetPtr val) { + xmlXPathObjectPtr ret; + + ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject)); + if (ret == NULL) { + xmlXPathErrMemory(NULL, "creating node set object\n"); + return(NULL); + } + memset(ret, 0 , (size_t) sizeof(xmlXPathObject)); + ret->type = XPATH_NODESET; + ret->nodesetval = val; +#ifdef XP_DEBUG_OBJ_USAGE + xmlXPathDebugObjUsageRequested(NULL, XPATH_NODESET); +#endif + return(ret); +} + +/** + * xmlXPathFreeNodeSetList: + * @obj: an existing NodeSetList object + * + * Free up the xmlXPathObjectPtr @obj but don't deallocate the objects in + * the list contrary to xmlXPathFreeObject(). + */ +void +xmlXPathFreeNodeSetList(xmlXPathObjectPtr obj) { + if (obj == NULL) return; +#ifdef XP_DEBUG_OBJ_USAGE + xmlXPathDebugObjUsageReleased(NULL, obj->type); +#endif + xmlFree(obj); +} + +/** + * xmlXPathDifference: + * @nodes1: a node-set + * @nodes2: a node-set + * + * Implements the EXSLT - Sets difference() function: + * node-set set:difference (node-set, node-set) + * + * Returns the difference between the two node sets, or nodes1 if + * nodes2 is empty + */ +xmlNodeSetPtr +xmlXPathDifference (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) { + xmlNodeSetPtr ret; + int i, l1; + xmlNodePtr cur; + + if (xmlXPathNodeSetIsEmpty(nodes2)) + return(nodes1); + + ret = xmlXPathNodeSetCreate(NULL); + if (xmlXPathNodeSetIsEmpty(nodes1)) + return(ret); + + l1 = xmlXPathNodeSetGetLength(nodes1); + + for (i = 0; i < l1; i++) { + cur = xmlXPathNodeSetItem(nodes1, i); + if (!xmlXPathNodeSetContains(nodes2, cur)) + xmlXPathNodeSetAddUnique(ret, cur); + } + return(ret); +} + +/** + * xmlXPathIntersection: + * @nodes1: a node-set + * @nodes2: a node-set + * + * Implements the EXSLT - Sets intersection() function: + * node-set set:intersection (node-set, node-set) + * + * Returns a node set comprising the nodes that are within both the + * node sets passed as arguments + */ +xmlNodeSetPtr +xmlXPathIntersection (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) { + xmlNodeSetPtr ret = xmlXPathNodeSetCreate(NULL); + int i, l1; + xmlNodePtr cur; + + if (xmlXPathNodeSetIsEmpty(nodes1)) + return(ret); + if (xmlXPathNodeSetIsEmpty(nodes2)) + return(ret); + + l1 = xmlXPathNodeSetGetLength(nodes1); + + for (i = 0; i < l1; i++) { + cur = xmlXPathNodeSetItem(nodes1, i); + if (xmlXPathNodeSetContains(nodes2, cur)) + xmlXPathNodeSetAddUnique(ret, cur); + } + return(ret); +} + +/** + * xmlXPathDistinctSorted: + * @nodes: a node-set, sorted by document order + * + * Implements the EXSLT - Sets distinct() function: + * node-set set:distinct (node-set) + * + * Returns a subset of the nodes contained in @nodes, or @nodes if + * it is empty + */ +xmlNodeSetPtr +xmlXPathDistinctSorted (xmlNodeSetPtr nodes) { + xmlNodeSetPtr ret; + xmlHashTablePtr hash; + int i, l; + xmlChar * strval; + xmlNodePtr cur; + + if (xmlXPathNodeSetIsEmpty(nodes)) + return(nodes); + + ret = xmlXPathNodeSetCreate(NULL); + l = xmlXPathNodeSetGetLength(nodes); + hash = xmlHashCreate (l); + for (i = 0; i < l; i++) { + cur = xmlXPathNodeSetItem(nodes, i); + strval = xmlXPathCastNodeToString(cur); + if (xmlHashLookup(hash, strval) == NULL) { + xmlHashAddEntry(hash, strval, strval); + xmlXPathNodeSetAddUnique(ret, cur); + } else { + xmlFree(strval); + } + } + xmlHashFree(hash, (xmlHashDeallocator) xmlFree); + return(ret); +} + +/** + * xmlXPathDistinct: + * @nodes: a node-set + * + * Implements the EXSLT - Sets distinct() function: + * node-set set:distinct (node-set) + * @nodes is sorted by document order, then #exslSetsDistinctSorted + * is called with the sorted node-set + * + * Returns a subset of the nodes contained in @nodes, or @nodes if + * it is empty + */ +xmlNodeSetPtr +xmlXPathDistinct (xmlNodeSetPtr nodes) { + if (xmlXPathNodeSetIsEmpty(nodes)) + return(nodes); + + xmlXPathNodeSetSort(nodes); + return(xmlXPathDistinctSorted(nodes)); +} + +/** + * xmlXPathHasSameNodes: + * @nodes1: a node-set + * @nodes2: a node-set + * + * Implements the EXSLT - Sets has-same-nodes function: + * boolean set:has-same-node(node-set, node-set) + * + * Returns true (1) if @nodes1 shares any node with @nodes2, false (0) + * otherwise + */ +int +xmlXPathHasSameNodes (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) { + int i, l; + xmlNodePtr cur; + + if (xmlXPathNodeSetIsEmpty(nodes1) || + xmlXPathNodeSetIsEmpty(nodes2)) + return(0); + + l = xmlXPathNodeSetGetLength(nodes1); + for (i = 0; i < l; i++) { + cur = xmlXPathNodeSetItem(nodes1, i); + if (xmlXPathNodeSetContains(nodes2, cur)) + return(1); + } + return(0); +} + +/** + * xmlXPathNodeLeadingSorted: + * @nodes: a node-set, sorted by document order + * @node: a node + * + * Implements the EXSLT - Sets leading() function: + * node-set set:leading (node-set, node-set) + * + * Returns the nodes in @nodes that precede @node in document order, + * @nodes if @node is NULL or an empty node-set if @nodes + * doesn't contain @node + */ +xmlNodeSetPtr +xmlXPathNodeLeadingSorted (xmlNodeSetPtr nodes, xmlNodePtr node) { + int i, l; + xmlNodePtr cur; + xmlNodeSetPtr ret; + + if (node == NULL) + return(nodes); + + ret = xmlXPathNodeSetCreate(NULL); + if (xmlXPathNodeSetIsEmpty(nodes) || + (!xmlXPathNodeSetContains(nodes, node))) + return(ret); + + l = xmlXPathNodeSetGetLength(nodes); + for (i = 0; i < l; i++) { + cur = xmlXPathNodeSetItem(nodes, i); + if (cur == node) + break; + xmlXPathNodeSetAddUnique(ret, cur); + } + return(ret); +} + +/** + * xmlXPathNodeLeading: + * @nodes: a node-set + * @node: a node + * + * Implements the EXSLT - Sets leading() function: + * node-set set:leading (node-set, node-set) + * @nodes is sorted by document order, then #exslSetsNodeLeadingSorted + * is called. + * + * Returns the nodes in @nodes that precede @node in document order, + * @nodes if @node is NULL or an empty node-set if @nodes + * doesn't contain @node + */ +xmlNodeSetPtr +xmlXPathNodeLeading (xmlNodeSetPtr nodes, xmlNodePtr node) { + xmlXPathNodeSetSort(nodes); + return(xmlXPathNodeLeadingSorted(nodes, node)); +} + +/** + * xmlXPathLeadingSorted: + * @nodes1: a node-set, sorted by document order + * @nodes2: a node-set, sorted by document order + * + * Implements the EXSLT - Sets leading() function: + * node-set set:leading (node-set, node-set) + * + * Returns the nodes in @nodes1 that precede the first node in @nodes2 + * in document order, @nodes1 if @nodes2 is NULL or empty or + * an empty node-set if @nodes1 doesn't contain @nodes2 + */ +xmlNodeSetPtr +xmlXPathLeadingSorted (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) { + if (xmlXPathNodeSetIsEmpty(nodes2)) + return(nodes1); + return(xmlXPathNodeLeadingSorted(nodes1, + xmlXPathNodeSetItem(nodes2, 1))); +} + +/** + * xmlXPathLeading: + * @nodes1: a node-set + * @nodes2: a node-set + * + * Implements the EXSLT - Sets leading() function: + * node-set set:leading (node-set, node-set) + * @nodes1 and @nodes2 are sorted by document order, then + * #exslSetsLeadingSorted is called. + * + * Returns the nodes in @nodes1 that precede the first node in @nodes2 + * in document order, @nodes1 if @nodes2 is NULL or empty or + * an empty node-set if @nodes1 doesn't contain @nodes2 + */ +xmlNodeSetPtr +xmlXPathLeading (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) { + if (xmlXPathNodeSetIsEmpty(nodes2)) + return(nodes1); + if (xmlXPathNodeSetIsEmpty(nodes1)) + return(xmlXPathNodeSetCreate(NULL)); + xmlXPathNodeSetSort(nodes1); + xmlXPathNodeSetSort(nodes2); + return(xmlXPathNodeLeadingSorted(nodes1, + xmlXPathNodeSetItem(nodes2, 1))); +} + +/** + * xmlXPathNodeTrailingSorted: + * @nodes: a node-set, sorted by document order + * @node: a node + * + * Implements the EXSLT - Sets trailing() function: + * node-set set:trailing (node-set, node-set) + * + * Returns the nodes in @nodes that follow @node in document order, + * @nodes if @node is NULL or an empty node-set if @nodes + * doesn't contain @node + */ +xmlNodeSetPtr +xmlXPathNodeTrailingSorted (xmlNodeSetPtr nodes, xmlNodePtr node) { + int i, l; + xmlNodePtr cur; + xmlNodeSetPtr ret; + + if (node == NULL) + return(nodes); + + ret = xmlXPathNodeSetCreate(NULL); + if (xmlXPathNodeSetIsEmpty(nodes) || + (!xmlXPathNodeSetContains(nodes, node))) + return(ret); + + l = xmlXPathNodeSetGetLength(nodes); + for (i = l; i > 0; i--) { + cur = xmlXPathNodeSetItem(nodes, i); + if (cur == node) + break; + xmlXPathNodeSetAddUnique(ret, cur); + } + return(ret); +} + +/** + * xmlXPathNodeTrailing: + * @nodes: a node-set + * @node: a node + * + * Implements the EXSLT - Sets trailing() function: + * node-set set:trailing (node-set, node-set) + * @nodes is sorted by document order, then #xmlXPathNodeTrailingSorted + * is called. + * + * Returns the nodes in @nodes that follow @node in document order, + * @nodes if @node is NULL or an empty node-set if @nodes + * doesn't contain @node + */ +xmlNodeSetPtr +xmlXPathNodeTrailing (xmlNodeSetPtr nodes, xmlNodePtr node) { + xmlXPathNodeSetSort(nodes); + return(xmlXPathNodeTrailingSorted(nodes, node)); +} + +/** + * xmlXPathTrailingSorted: + * @nodes1: a node-set, sorted by document order + * @nodes2: a node-set, sorted by document order + * + * Implements the EXSLT - Sets trailing() function: + * node-set set:trailing (node-set, node-set) + * + * Returns the nodes in @nodes1 that follow the first node in @nodes2 + * in document order, @nodes1 if @nodes2 is NULL or empty or + * an empty node-set if @nodes1 doesn't contain @nodes2 + */ +xmlNodeSetPtr +xmlXPathTrailingSorted (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) { + if (xmlXPathNodeSetIsEmpty(nodes2)) + return(nodes1); + return(xmlXPathNodeTrailingSorted(nodes1, + xmlXPathNodeSetItem(nodes2, 0))); +} + +/** + * xmlXPathTrailing: + * @nodes1: a node-set + * @nodes2: a node-set + * + * Implements the EXSLT - Sets trailing() function: + * node-set set:trailing (node-set, node-set) + * @nodes1 and @nodes2 are sorted by document order, then + * #xmlXPathTrailingSorted is called. + * + * Returns the nodes in @nodes1 that follow the first node in @nodes2 + * in document order, @nodes1 if @nodes2 is NULL or empty or + * an empty node-set if @nodes1 doesn't contain @nodes2 + */ +xmlNodeSetPtr +xmlXPathTrailing (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) { + if (xmlXPathNodeSetIsEmpty(nodes2)) + return(nodes1); + if (xmlXPathNodeSetIsEmpty(nodes1)) + return(xmlXPathNodeSetCreate(NULL)); + xmlXPathNodeSetSort(nodes1); + xmlXPathNodeSetSort(nodes2); + return(xmlXPathNodeTrailingSorted(nodes1, + xmlXPathNodeSetItem(nodes2, 0))); +} + +/************************************************************************ + * * + * Routines to handle extra functions * + * * + ************************************************************************/ + +/** + * xmlXPathRegisterFunc: + * @ctxt: the XPath context + * @name: the function name + * @f: the function implementation or NULL + * + * Register a new function. If @f is NULL it unregisters the function + * + * Returns 0 in case of success, -1 in case of error + */ +int +xmlXPathRegisterFunc(xmlXPathContextPtr ctxt, const xmlChar *name, + xmlXPathFunction f) { + return(xmlXPathRegisterFuncNS(ctxt, name, NULL, f)); +} + +/** + * xmlXPathRegisterFuncNS: + * @ctxt: the XPath context + * @name: the function name + * @ns_uri: the function namespace URI + * @f: the function implementation or NULL + * + * Register a new function. If @f is NULL it unregisters the function + * + * Returns 0 in case of success, -1 in case of error + */ +int +xmlXPathRegisterFuncNS(xmlXPathContextPtr ctxt, const xmlChar *name, + const xmlChar *ns_uri, xmlXPathFunction f) { + if (ctxt == NULL) + return(-1); + if (name == NULL) + return(-1); + + if (ctxt->funcHash == NULL) + ctxt->funcHash = xmlHashCreate(0); + if (ctxt->funcHash == NULL) + return(-1); + if (f == NULL) + return(xmlHashRemoveEntry2(ctxt->funcHash, name, ns_uri, NULL)); + return(xmlHashAddEntry2(ctxt->funcHash, name, ns_uri, XML_CAST_FPTR(f))); +} + +/** + * xmlXPathRegisterFuncLookup: + * @ctxt: the XPath context + * @f: the lookup function + * @funcCtxt: the lookup data + * + * Registers an external mechanism to do function lookup. + */ +void +xmlXPathRegisterFuncLookup (xmlXPathContextPtr ctxt, + xmlXPathFuncLookupFunc f, + void *funcCtxt) { + if (ctxt == NULL) + return; + ctxt->funcLookupFunc = f; + ctxt->funcLookupData = funcCtxt; +} + +/** + * xmlXPathFunctionLookup: + * @ctxt: the XPath context + * @name: the function name + * + * Search in the Function array of the context for the given + * function. + * + * Returns the xmlXPathFunction or NULL if not found + */ +xmlXPathFunction +xmlXPathFunctionLookup(xmlXPathContextPtr ctxt, const xmlChar *name) { + if (ctxt == NULL) + return (NULL); + + if (ctxt->funcLookupFunc != NULL) { + xmlXPathFunction ret; + xmlXPathFuncLookupFunc f; + + f = ctxt->funcLookupFunc; + ret = f(ctxt->funcLookupData, name, NULL); + if (ret != NULL) + return(ret); + } + return(xmlXPathFunctionLookupNS(ctxt, name, NULL)); +} + +/** + * xmlXPathFunctionLookupNS: + * @ctxt: the XPath context + * @name: the function name + * @ns_uri: the function namespace URI + * + * Search in the Function array of the context for the given + * function. + * + * Returns the xmlXPathFunction or NULL if not found + */ +xmlXPathFunction +xmlXPathFunctionLookupNS(xmlXPathContextPtr ctxt, const xmlChar *name, + const xmlChar *ns_uri) { + xmlXPathFunction ret; + + if (ctxt == NULL) + return(NULL); + if (name == NULL) + return(NULL); + + if (ctxt->funcLookupFunc != NULL) { + xmlXPathFuncLookupFunc f; + + f = ctxt->funcLookupFunc; + ret = f(ctxt->funcLookupData, name, ns_uri); + if (ret != NULL) + return(ret); + } + + if (ctxt->funcHash == NULL) + return(NULL); + + XML_CAST_FPTR(ret) = xmlHashLookup2(ctxt->funcHash, name, ns_uri); + return(ret); +} + +/** + * xmlXPathRegisteredFuncsCleanup: + * @ctxt: the XPath context + * + * Cleanup the XPath context data associated to registered functions + */ +void +xmlXPathRegisteredFuncsCleanup(xmlXPathContextPtr ctxt) { + if (ctxt == NULL) + return; + + xmlHashFree(ctxt->funcHash, NULL); + ctxt->funcHash = NULL; +} + +/************************************************************************ + * * + * Routines to handle Variables * + * * + ************************************************************************/ + +/** + * xmlXPathRegisterVariable: + * @ctxt: the XPath context + * @name: the variable name + * @value: the variable value or NULL + * + * Register a new variable value. If @value is NULL it unregisters + * the variable + * + * Returns 0 in case of success, -1 in case of error + */ +int +xmlXPathRegisterVariable(xmlXPathContextPtr ctxt, const xmlChar *name, + xmlXPathObjectPtr value) { + return(xmlXPathRegisterVariableNS(ctxt, name, NULL, value)); +} + +/** + * xmlXPathRegisterVariableNS: + * @ctxt: the XPath context + * @name: the variable name + * @ns_uri: the variable namespace URI + * @value: the variable value or NULL + * + * Register a new variable value. If @value is NULL it unregisters + * the variable + * + * Returns 0 in case of success, -1 in case of error + */ +int +xmlXPathRegisterVariableNS(xmlXPathContextPtr ctxt, const xmlChar *name, + const xmlChar *ns_uri, + xmlXPathObjectPtr value) { + if (ctxt == NULL) + return(-1); + if (name == NULL) + return(-1); + + if (ctxt->varHash == NULL) + ctxt->varHash = xmlHashCreate(0); + if (ctxt->varHash == NULL) + return(-1); + if (value == NULL) + return(xmlHashRemoveEntry2(ctxt->varHash, name, ns_uri, + (xmlHashDeallocator)xmlXPathFreeObject)); + return(xmlHashUpdateEntry2(ctxt->varHash, name, ns_uri, + (void *) value, + (xmlHashDeallocator)xmlXPathFreeObject)); +} + +/** + * xmlXPathRegisterVariableLookup: + * @ctxt: the XPath context + * @f: the lookup function + * @data: the lookup data + * + * register an external mechanism to do variable lookup + */ +void +xmlXPathRegisterVariableLookup(xmlXPathContextPtr ctxt, + xmlXPathVariableLookupFunc f, void *data) { + if (ctxt == NULL) + return; + ctxt->varLookupFunc = f; + ctxt->varLookupData = data; +} + +/** + * xmlXPathVariableLookup: + * @ctxt: the XPath context + * @name: the variable name + * + * Search in the Variable array of the context for the given + * variable value. + * + * Returns a copy of the value or NULL if not found + */ +xmlXPathObjectPtr +xmlXPathVariableLookup(xmlXPathContextPtr ctxt, const xmlChar *name) { + if (ctxt == NULL) + return(NULL); + + if (ctxt->varLookupFunc != NULL) { + xmlXPathObjectPtr ret; + + ret = ((xmlXPathVariableLookupFunc)ctxt->varLookupFunc) + (ctxt->varLookupData, name, NULL); + return(ret); + } + return(xmlXPathVariableLookupNS(ctxt, name, NULL)); +} + +/** + * xmlXPathVariableLookupNS: + * @ctxt: the XPath context + * @name: the variable name + * @ns_uri: the variable namespace URI + * + * Search in the Variable array of the context for the given + * variable value. + * + * Returns the a copy of the value or NULL if not found + */ +xmlXPathObjectPtr +xmlXPathVariableLookupNS(xmlXPathContextPtr ctxt, const xmlChar *name, + const xmlChar *ns_uri) { + if (ctxt == NULL) + return(NULL); + + if (ctxt->varLookupFunc != NULL) { + xmlXPathObjectPtr ret; + + ret = ((xmlXPathVariableLookupFunc)ctxt->varLookupFunc) + (ctxt->varLookupData, name, ns_uri); + if (ret != NULL) return(ret); + } + + if (ctxt->varHash == NULL) + return(NULL); + if (name == NULL) + return(NULL); + + return(xmlXPathCacheObjectCopy(ctxt, (xmlXPathObjectPtr) + xmlHashLookup2(ctxt->varHash, name, ns_uri))); +} + +/** + * xmlXPathRegisteredVariablesCleanup: + * @ctxt: the XPath context + * + * Cleanup the XPath context data associated to registered variables + */ +void +xmlXPathRegisteredVariablesCleanup(xmlXPathContextPtr ctxt) { + if (ctxt == NULL) + return; + + xmlHashFree(ctxt->varHash, (xmlHashDeallocator)xmlXPathFreeObject); + ctxt->varHash = NULL; +} + +/** + * xmlXPathRegisterNs: + * @ctxt: the XPath context + * @prefix: the namespace prefix + * @ns_uri: the namespace name + * + * Register a new namespace. If @ns_uri is NULL it unregisters + * the namespace + * + * Returns 0 in case of success, -1 in case of error + */ +int +xmlXPathRegisterNs(xmlXPathContextPtr ctxt, const xmlChar *prefix, + const xmlChar *ns_uri) { + if (ctxt == NULL) + return(-1); + if (prefix == NULL) + return(-1); + + if (ctxt->nsHash == NULL) + ctxt->nsHash = xmlHashCreate(10); + if (ctxt->nsHash == NULL) + return(-1); + if (ns_uri == NULL) + return(xmlHashRemoveEntry(ctxt->nsHash, prefix, + (xmlHashDeallocator)xmlFree)); + return(xmlHashUpdateEntry(ctxt->nsHash, prefix, (void *) xmlStrdup(ns_uri), + (xmlHashDeallocator)xmlFree)); +} + +/** + * xmlXPathNsLookup: + * @ctxt: the XPath context + * @prefix: the namespace prefix value + * + * Search in the namespace declaration array of the context for the given + * namespace name associated to the given prefix + * + * Returns the value or NULL if not found + */ +const xmlChar * +xmlXPathNsLookup(xmlXPathContextPtr ctxt, const xmlChar *prefix) { + if (ctxt == NULL) + return(NULL); + if (prefix == NULL) + return(NULL); + +#ifdef XML_XML_NAMESPACE + if (xmlStrEqual(prefix, (const xmlChar *) "xml")) + return(XML_XML_NAMESPACE); +#endif + + if (ctxt->namespaces != NULL) { + int i; + + for (i = 0;i < ctxt->nsNr;i++) { + if ((ctxt->namespaces[i] != NULL) && + (xmlStrEqual(ctxt->namespaces[i]->prefix, prefix))) + return(ctxt->namespaces[i]->href); + } + } + + return((const xmlChar *) xmlHashLookup(ctxt->nsHash, prefix)); +} + +/** + * xmlXPathRegisteredNsCleanup: + * @ctxt: the XPath context + * + * Cleanup the XPath context data associated to registered variables + */ +void +xmlXPathRegisteredNsCleanup(xmlXPathContextPtr ctxt) { + if (ctxt == NULL) + return; + + xmlHashFree(ctxt->nsHash, (xmlHashDeallocator)xmlFree); + ctxt->nsHash = NULL; +} + +/************************************************************************ + * * + * Routines to handle Values * + * * + ************************************************************************/ + +/* Allocations are terrible, one needs to optimize all this !!! */ + +/** + * xmlXPathNewFloat: + * @val: the double value + * + * Create a new xmlXPathObjectPtr of type double and of value @val + * + * Returns the newly created object. + */ +xmlXPathObjectPtr +xmlXPathNewFloat(double val) { + xmlXPathObjectPtr ret; + + ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject)); + if (ret == NULL) { + xmlXPathErrMemory(NULL, "creating float object\n"); + return(NULL); + } + memset(ret, 0 , (size_t) sizeof(xmlXPathObject)); + ret->type = XPATH_NUMBER; + ret->floatval = val; +#ifdef XP_DEBUG_OBJ_USAGE + xmlXPathDebugObjUsageRequested(NULL, XPATH_NUMBER); +#endif + return(ret); +} + +/** + * xmlXPathNewBoolean: + * @val: the boolean value + * + * Create a new xmlXPathObjectPtr of type boolean and of value @val + * + * Returns the newly created object. + */ +xmlXPathObjectPtr +xmlXPathNewBoolean(int val) { + xmlXPathObjectPtr ret; + + ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject)); + if (ret == NULL) { + xmlXPathErrMemory(NULL, "creating boolean object\n"); + return(NULL); + } + memset(ret, 0 , (size_t) sizeof(xmlXPathObject)); + ret->type = XPATH_BOOLEAN; + ret->boolval = (val != 0); +#ifdef XP_DEBUG_OBJ_USAGE + xmlXPathDebugObjUsageRequested(NULL, XPATH_BOOLEAN); +#endif + return(ret); +} + +/** + * xmlXPathNewString: + * @val: the xmlChar * value + * + * Create a new xmlXPathObjectPtr of type string and of value @val + * + * Returns the newly created object. + */ +xmlXPathObjectPtr +xmlXPathNewString(const xmlChar *val) { + xmlXPathObjectPtr ret; + + ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject)); + if (ret == NULL) { + xmlXPathErrMemory(NULL, "creating string object\n"); + return(NULL); + } + memset(ret, 0 , (size_t) sizeof(xmlXPathObject)); + ret->type = XPATH_STRING; + if (val != NULL) + ret->stringval = xmlStrdup(val); + else + ret->stringval = xmlStrdup((const xmlChar *)""); +#ifdef XP_DEBUG_OBJ_USAGE + xmlXPathDebugObjUsageRequested(NULL, XPATH_STRING); +#endif + return(ret); +} + +/** + * xmlXPathWrapString: + * @val: the xmlChar * value + * + * Wraps the @val string into an XPath object. + * + * Returns the newly created object. + */ +xmlXPathObjectPtr +xmlXPathWrapString (xmlChar *val) { + xmlXPathObjectPtr ret; + + ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject)); + if (ret == NULL) { + xmlXPathErrMemory(NULL, "creating string object\n"); + return(NULL); + } + memset(ret, 0 , (size_t) sizeof(xmlXPathObject)); + ret->type = XPATH_STRING; + ret->stringval = val; +#ifdef XP_DEBUG_OBJ_USAGE + xmlXPathDebugObjUsageRequested(NULL, XPATH_STRING); +#endif + return(ret); +} + +/** + * xmlXPathNewCString: + * @val: the char * value + * + * Create a new xmlXPathObjectPtr of type string and of value @val + * + * Returns the newly created object. + */ +xmlXPathObjectPtr +xmlXPathNewCString(const char *val) { + xmlXPathObjectPtr ret; + + ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject)); + if (ret == NULL) { + xmlXPathErrMemory(NULL, "creating string object\n"); + return(NULL); + } + memset(ret, 0 , (size_t) sizeof(xmlXPathObject)); + ret->type = XPATH_STRING; + ret->stringval = xmlStrdup(BAD_CAST val); +#ifdef XP_DEBUG_OBJ_USAGE + xmlXPathDebugObjUsageRequested(NULL, XPATH_STRING); +#endif + return(ret); +} + +/** + * xmlXPathWrapCString: + * @val: the char * value + * + * Wraps a string into an XPath object. + * + * Returns the newly created object. + */ +xmlXPathObjectPtr +xmlXPathWrapCString (char * val) { + return(xmlXPathWrapString((xmlChar *)(val))); +} + +/** + * xmlXPathWrapExternal: + * @val: the user data + * + * Wraps the @val data into an XPath object. + * + * Returns the newly created object. + */ +xmlXPathObjectPtr +xmlXPathWrapExternal (void *val) { + xmlXPathObjectPtr ret; + + ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject)); + if (ret == NULL) { + xmlXPathErrMemory(NULL, "creating user object\n"); + return(NULL); + } + memset(ret, 0 , (size_t) sizeof(xmlXPathObject)); + ret->type = XPATH_USERS; + ret->user = val; +#ifdef XP_DEBUG_OBJ_USAGE + xmlXPathDebugObjUsageRequested(NULL, XPATH_USERS); +#endif + return(ret); +} + +/** + * xmlXPathObjectCopy: + * @val: the original object + * + * allocate a new copy of a given object + * + * Returns the newly created object. + */ +xmlXPathObjectPtr +xmlXPathObjectCopy(xmlXPathObjectPtr val) { + xmlXPathObjectPtr ret; + + if (val == NULL) + return(NULL); + + ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject)); + if (ret == NULL) { + xmlXPathErrMemory(NULL, "copying object\n"); + return(NULL); + } + memcpy(ret, val , (size_t) sizeof(xmlXPathObject)); +#ifdef XP_DEBUG_OBJ_USAGE + xmlXPathDebugObjUsageRequested(NULL, val->type); +#endif + switch (val->type) { + case XPATH_BOOLEAN: + case XPATH_NUMBER: + case XPATH_POINT: + case XPATH_RANGE: + break; + case XPATH_STRING: + ret->stringval = xmlStrdup(val->stringval); + break; + case XPATH_XSLT_TREE: +#if 0 +/* + Removed 11 July 2004 - the current handling of xslt tmpRVT nodes means that + this previous handling is no longer correct, and can cause some serious + problems (ref. bug 145547) +*/ + if ((val->nodesetval != NULL) && + (val->nodesetval->nodeTab != NULL)) { + xmlNodePtr cur, tmp; + xmlDocPtr top; + + ret->boolval = 1; + top = xmlNewDoc(NULL); + top->name = (char *) + xmlStrdup(val->nodesetval->nodeTab[0]->name); + ret->user = top; + if (top != NULL) { + top->doc = top; + cur = val->nodesetval->nodeTab[0]->children; + while (cur != NULL) { + tmp = xmlDocCopyNode(cur, top, 1); + xmlAddChild((xmlNodePtr) top, tmp); + cur = cur->next; + } + } + + ret->nodesetval = xmlXPathNodeSetCreate((xmlNodePtr) top); + } else + ret->nodesetval = xmlXPathNodeSetCreate(NULL); + /* Deallocate the copied tree value */ + break; +#endif + case XPATH_NODESET: + ret->nodesetval = xmlXPathNodeSetMerge(NULL, val->nodesetval); + /* Do not deallocate the copied tree value */ + ret->boolval = 0; + break; + case XPATH_LOCATIONSET: +#ifdef LIBXML_XPTR_ENABLED + { + xmlLocationSetPtr loc = val->user; + ret->user = (void *) xmlXPtrLocationSetMerge(NULL, loc); + break; + } +#endif + case XPATH_USERS: + ret->user = val->user; + break; + case XPATH_UNDEFINED: + xmlGenericError(xmlGenericErrorContext, + "xmlXPathObjectCopy: unsupported type %d\n", + val->type); + break; + } + return(ret); +} + +/** + * xmlXPathFreeObject: + * @obj: the object to free + * + * Free up an xmlXPathObjectPtr object. + */ +void +xmlXPathFreeObject(xmlXPathObjectPtr obj) { + if (obj == NULL) return; + if ((obj->type == XPATH_NODESET) || (obj->type == XPATH_XSLT_TREE)) { + if (obj->boolval) { +#if 0 + if (obj->user != NULL) { + xmlXPathFreeNodeSet(obj->nodesetval); + xmlFreeNodeList((xmlNodePtr) obj->user); + } else +#endif + obj->type = XPATH_XSLT_TREE; /* TODO: Just for debugging. */ + if (obj->nodesetval != NULL) + xmlXPathFreeValueTree(obj->nodesetval); + } else { + if (obj->nodesetval != NULL) + xmlXPathFreeNodeSet(obj->nodesetval); + } +#ifdef LIBXML_XPTR_ENABLED + } else if (obj->type == XPATH_LOCATIONSET) { + if (obj->user != NULL) + xmlXPtrFreeLocationSet(obj->user); +#endif + } else if (obj->type == XPATH_STRING) { + if (obj->stringval != NULL) + xmlFree(obj->stringval); + } +#ifdef XP_DEBUG_OBJ_USAGE + xmlXPathDebugObjUsageReleased(NULL, obj->type); +#endif + xmlFree(obj); +} + +/** + * xmlXPathReleaseObject: + * @obj: the xmlXPathObjectPtr to free or to cache + * + * Depending on the state of the cache this frees the given + * XPath object or stores it in the cache. + */ +static void +xmlXPathReleaseObject(xmlXPathContextPtr ctxt, xmlXPathObjectPtr obj) +{ +#define XP_CACHE_ADD(sl, o) if (sl == NULL) { \ + sl = xmlPointerListCreate(10); if (sl == NULL) goto free_obj; } \ + if (xmlPointerListAddSize(sl, obj, 0) == -1) goto free_obj; + +#define XP_CACHE_WANTS(sl, n) ((sl == NULL) || ((sl)->number < n)) + + if (obj == NULL) + return; + if ((ctxt == NULL) || (ctxt->cache == NULL)) { + xmlXPathFreeObject(obj); + } else { + xmlXPathContextCachePtr cache = + (xmlXPathContextCachePtr) ctxt->cache; + + switch (obj->type) { + case XPATH_NODESET: + case XPATH_XSLT_TREE: + if (obj->nodesetval != NULL) { + if (obj->boolval) { + /* + * It looks like the @boolval is used for + * evaluation if this an XSLT Result Tree Fragment. + * TODO: Check if this assumption is correct. + */ + obj->type = XPATH_XSLT_TREE; /* just for debugging */ + xmlXPathFreeValueTree(obj->nodesetval); + obj->nodesetval = NULL; + } else if ((obj->nodesetval->nodeMax <= 40) && + (XP_CACHE_WANTS(cache->nodesetObjs, + cache->maxNodeset))) + { + XP_CACHE_ADD(cache->nodesetObjs, obj); + goto obj_cached; + } else { + xmlXPathFreeNodeSet(obj->nodesetval); + obj->nodesetval = NULL; + } + } + break; + case XPATH_STRING: + if (obj->stringval != NULL) + xmlFree(obj->stringval); + + if (XP_CACHE_WANTS(cache->stringObjs, cache->maxString)) { + XP_CACHE_ADD(cache->stringObjs, obj); + goto obj_cached; + } + break; + case XPATH_BOOLEAN: + if (XP_CACHE_WANTS(cache->booleanObjs, cache->maxBoolean)) { + XP_CACHE_ADD(cache->booleanObjs, obj); + goto obj_cached; + } + break; + case XPATH_NUMBER: + if (XP_CACHE_WANTS(cache->numberObjs, cache->maxNumber)) { + XP_CACHE_ADD(cache->numberObjs, obj); + goto obj_cached; + } + break; +#ifdef LIBXML_XPTR_ENABLED + case XPATH_LOCATIONSET: + if (obj->user != NULL) { + xmlXPtrFreeLocationSet(obj->user); + } + goto free_obj; +#endif + default: + goto free_obj; + } + + /* + * Fallback to adding to the misc-objects slot. + */ + if (XP_CACHE_WANTS(cache->miscObjs, cache->maxMisc)) { + XP_CACHE_ADD(cache->miscObjs, obj); + } else + goto free_obj; + +obj_cached: + +#ifdef XP_DEBUG_OBJ_USAGE + xmlXPathDebugObjUsageReleased(ctxt, obj->type); +#endif + + if (obj->nodesetval != NULL) { + xmlNodeSetPtr tmpset = obj->nodesetval; + + /* + * TODO: Due to those nasty ns-nodes, we need to traverse + * the list and free the ns-nodes. + * URGENT TODO: Check if it's actually slowing things down. + * Maybe we shouldn't try to preserve the list. + */ + if (tmpset->nodeNr > 1) { + int i; + xmlNodePtr node; + + for (i = 0; i < tmpset->nodeNr; i++) { + node = tmpset->nodeTab[i]; + if ((node != NULL) && + (node->type == XML_NAMESPACE_DECL)) + { + xmlXPathNodeSetFreeNs((xmlNsPtr) node); + } + } + } else if (tmpset->nodeNr == 1) { + if ((tmpset->nodeTab[0] != NULL) && + (tmpset->nodeTab[0]->type == XML_NAMESPACE_DECL)) + xmlXPathNodeSetFreeNs((xmlNsPtr) tmpset->nodeTab[0]); + } + tmpset->nodeNr = 0; + memset(obj, 0, sizeof(xmlXPathObject)); + obj->nodesetval = tmpset; + } else + memset(obj, 0, sizeof(xmlXPathObject)); + + return; + +free_obj: + /* + * Cache is full; free the object. + */ + if (obj->nodesetval != NULL) + xmlXPathFreeNodeSet(obj->nodesetval); +#ifdef XP_DEBUG_OBJ_USAGE + xmlXPathDebugObjUsageReleased(NULL, obj->type); +#endif + xmlFree(obj); + } + return; +} + + +/************************************************************************ + * * + * Type Casting Routines * + * * + ************************************************************************/ + +/** + * xmlXPathCastBooleanToString: + * @val: a boolean + * + * Converts a boolean to its string value. + * + * Returns a newly allocated string. + */ +xmlChar * +xmlXPathCastBooleanToString (int val) { + xmlChar *ret; + if (val) + ret = xmlStrdup((const xmlChar *) "true"); + else + ret = xmlStrdup((const xmlChar *) "false"); + return(ret); +} + +/** + * xmlXPathCastNumberToString: + * @val: a number + * + * Converts a number to its string value. + * + * Returns a newly allocated string. + */ +xmlChar * +xmlXPathCastNumberToString (double val) { + xmlChar *ret; + switch (xmlXPathIsInf(val)) { + case 1: + ret = xmlStrdup((const xmlChar *) "Infinity"); + break; + case -1: + ret = xmlStrdup((const xmlChar *) "-Infinity"); + break; + default: + if (xmlXPathIsNaN(val)) { + ret = xmlStrdup((const xmlChar *) "NaN"); + } else if (val == 0 && xmlXPathGetSign(val) != 0) { + ret = xmlStrdup((const xmlChar *) "0"); + } else { + /* could be improved */ + char buf[100]; + xmlXPathFormatNumber(val, buf, 99); + buf[99] = 0; + ret = xmlStrdup((const xmlChar *) buf); + } + } + return(ret); +} + +/** + * xmlXPathCastNodeToString: + * @node: a node + * + * Converts a node to its string value. + * + * Returns a newly allocated string. + */ +xmlChar * +xmlXPathCastNodeToString (xmlNodePtr node) { + return(xmlNodeGetContent(node)); +} + +/** + * xmlXPathCastNodeSetToString: + * @ns: a node-set + * + * Converts a node-set to its string value. + * + * Returns a newly allocated string. + */ +xmlChar * +xmlXPathCastNodeSetToString (xmlNodeSetPtr ns) { + if ((ns == NULL) || (ns->nodeNr == 0) || (ns->nodeTab == NULL)) + return(xmlStrdup((const xmlChar *) "")); + + if (ns->nodeNr > 1) + xmlXPathNodeSetSort(ns); + return(xmlXPathCastNodeToString(ns->nodeTab[0])); +} + +/** + * xmlXPathCastToString: + * @val: an XPath object + * + * Converts an existing object to its string() equivalent + * + * Returns the allocated string value of the object, NULL in case of error. + * It's up to the caller to free the string memory with xmlFree(). + */ +xmlChar * +xmlXPathCastToString(xmlXPathObjectPtr val) { + xmlChar *ret = NULL; + + if (val == NULL) + return(xmlStrdup((const xmlChar *) "")); + switch (val->type) { + case XPATH_UNDEFINED: +#ifdef DEBUG_EXPR + xmlGenericError(xmlGenericErrorContext, "String: undefined\n"); +#endif + ret = xmlStrdup((const xmlChar *) ""); + break; + case XPATH_NODESET: + case XPATH_XSLT_TREE: + ret = xmlXPathCastNodeSetToString(val->nodesetval); + break; + case XPATH_STRING: + return(xmlStrdup(val->stringval)); + case XPATH_BOOLEAN: + ret = xmlXPathCastBooleanToString(val->boolval); + break; + case XPATH_NUMBER: { + ret = xmlXPathCastNumberToString(val->floatval); + break; + } + case XPATH_USERS: + case XPATH_POINT: + case XPATH_RANGE: + case XPATH_LOCATIONSET: + TODO + ret = xmlStrdup((const xmlChar *) ""); + break; + } + return(ret); +} + +/** + * xmlXPathConvertString: + * @val: an XPath object + * + * Converts an existing object to its string() equivalent + * + * Returns the new object, the old one is freed (or the operation + * is done directly on @val) + */ +xmlXPathObjectPtr +xmlXPathConvertString(xmlXPathObjectPtr val) { + xmlChar *res = NULL; + + if (val == NULL) + return(xmlXPathNewCString("")); + + switch (val->type) { + case XPATH_UNDEFINED: +#ifdef DEBUG_EXPR + xmlGenericError(xmlGenericErrorContext, "STRING: undefined\n"); +#endif + break; + case XPATH_NODESET: + case XPATH_XSLT_TREE: + res = xmlXPathCastNodeSetToString(val->nodesetval); + break; + case XPATH_STRING: + return(val); + case XPATH_BOOLEAN: + res = xmlXPathCastBooleanToString(val->boolval); + break; + case XPATH_NUMBER: + res = xmlXPathCastNumberToString(val->floatval); + break; + case XPATH_USERS: + case XPATH_POINT: + case XPATH_RANGE: + case XPATH_LOCATIONSET: + TODO; + break; + } + xmlXPathFreeObject(val); + if (res == NULL) + return(xmlXPathNewCString("")); + return(xmlXPathWrapString(res)); +} + +/** + * xmlXPathCastBooleanToNumber: + * @val: a boolean + * + * Converts a boolean to its number value + * + * Returns the number value + */ +double +xmlXPathCastBooleanToNumber(int val) { + if (val) + return(1.0); + return(0.0); +} + +/** + * xmlXPathCastStringToNumber: + * @val: a string + * + * Converts a string to its number value + * + * Returns the number value + */ +double +xmlXPathCastStringToNumber(const xmlChar * val) { + return(xmlXPathStringEvalNumber(val)); +} + +/** + * xmlXPathCastNodeToNumber: + * @node: a node + * + * Converts a node to its number value + * + * Returns the number value + */ +double +xmlXPathCastNodeToNumber (xmlNodePtr node) { + xmlChar *strval; + double ret; + + if (node == NULL) + return(xmlXPathNAN); + strval = xmlXPathCastNodeToString(node); + if (strval == NULL) + return(xmlXPathNAN); + ret = xmlXPathCastStringToNumber(strval); + xmlFree(strval); + + return(ret); +} + +/** + * xmlXPathCastNodeSetToNumber: + * @ns: a node-set + * + * Converts a node-set to its number value + * + * Returns the number value + */ +double +xmlXPathCastNodeSetToNumber (xmlNodeSetPtr ns) { + xmlChar *str; + double ret; + + if (ns == NULL) + return(xmlXPathNAN); + str = xmlXPathCastNodeSetToString(ns); + ret = xmlXPathCastStringToNumber(str); + xmlFree(str); + return(ret); +} + +/** + * xmlXPathCastToNumber: + * @val: an XPath object + * + * Converts an XPath object to its number value + * + * Returns the number value + */ +double +xmlXPathCastToNumber(xmlXPathObjectPtr val) { + double ret = 0.0; + + if (val == NULL) + return(xmlXPathNAN); + switch (val->type) { + case XPATH_UNDEFINED: +#ifdef DEGUB_EXPR + xmlGenericError(xmlGenericErrorContext, "NUMBER: undefined\n"); +#endif + ret = xmlXPathNAN; + break; + case XPATH_NODESET: + case XPATH_XSLT_TREE: + ret = xmlXPathCastNodeSetToNumber(val->nodesetval); + break; + case XPATH_STRING: + ret = xmlXPathCastStringToNumber(val->stringval); + break; + case XPATH_NUMBER: + ret = val->floatval; + break; + case XPATH_BOOLEAN: + ret = xmlXPathCastBooleanToNumber(val->boolval); + break; + case XPATH_USERS: + case XPATH_POINT: + case XPATH_RANGE: + case XPATH_LOCATIONSET: + TODO; + ret = xmlXPathNAN; + break; + } + return(ret); +} + +/** + * xmlXPathConvertNumber: + * @val: an XPath object + * + * Converts an existing object to its number() equivalent + * + * Returns the new object, the old one is freed (or the operation + * is done directly on @val) + */ +xmlXPathObjectPtr +xmlXPathConvertNumber(xmlXPathObjectPtr val) { + xmlXPathObjectPtr ret; + + if (val == NULL) + return(xmlXPathNewFloat(0.0)); + if (val->type == XPATH_NUMBER) + return(val); + ret = xmlXPathNewFloat(xmlXPathCastToNumber(val)); + xmlXPathFreeObject(val); + return(ret); +} + +/** + * xmlXPathCastNumberToBoolean: + * @val: a number + * + * Converts a number to its boolean value + * + * Returns the boolean value + */ +int +xmlXPathCastNumberToBoolean (double val) { + if (xmlXPathIsNaN(val) || (val == 0.0)) + return(0); + return(1); +} + +/** + * xmlXPathCastStringToBoolean: + * @val: a string + * + * Converts a string to its boolean value + * + * Returns the boolean value + */ +int +xmlXPathCastStringToBoolean (const xmlChar *val) { + if ((val == NULL) || (xmlStrlen(val) == 0)) + return(0); + return(1); +} + +/** + * xmlXPathCastNodeSetToBoolean: + * @ns: a node-set + * + * Converts a node-set to its boolean value + * + * Returns the boolean value + */ +int +xmlXPathCastNodeSetToBoolean (xmlNodeSetPtr ns) { + if ((ns == NULL) || (ns->nodeNr == 0)) + return(0); + return(1); +} + +/** + * xmlXPathCastToBoolean: + * @val: an XPath object + * + * Converts an XPath object to its boolean value + * + * Returns the boolean value + */ +int +xmlXPathCastToBoolean (xmlXPathObjectPtr val) { + int ret = 0; + + if (val == NULL) + return(0); + switch (val->type) { + case XPATH_UNDEFINED: +#ifdef DEBUG_EXPR + xmlGenericError(xmlGenericErrorContext, "BOOLEAN: undefined\n"); +#endif + ret = 0; + break; + case XPATH_NODESET: + case XPATH_XSLT_TREE: + ret = xmlXPathCastNodeSetToBoolean(val->nodesetval); + break; + case XPATH_STRING: + ret = xmlXPathCastStringToBoolean(val->stringval); + break; + case XPATH_NUMBER: + ret = xmlXPathCastNumberToBoolean(val->floatval); + break; + case XPATH_BOOLEAN: + ret = val->boolval; + break; + case XPATH_USERS: + case XPATH_POINT: + case XPATH_RANGE: + case XPATH_LOCATIONSET: + TODO; + ret = 0; + break; + } + return(ret); +} + + +/** + * xmlXPathConvertBoolean: + * @val: an XPath object + * + * Converts an existing object to its boolean() equivalent + * + * Returns the new object, the old one is freed (or the operation + * is done directly on @val) + */ +xmlXPathObjectPtr +xmlXPathConvertBoolean(xmlXPathObjectPtr val) { + xmlXPathObjectPtr ret; + + if (val == NULL) + return(xmlXPathNewBoolean(0)); + if (val->type == XPATH_BOOLEAN) + return(val); + ret = xmlXPathNewBoolean(xmlXPathCastToBoolean(val)); + xmlXPathFreeObject(val); + return(ret); +} + +/************************************************************************ + * * + * Routines to handle XPath contexts * + * * + ************************************************************************/ + +/** + * xmlXPathNewContext: + * @doc: the XML document + * + * Create a new xmlXPathContext + * + * Returns the xmlXPathContext just allocated. The caller will need to free it. + */ +xmlXPathContextPtr +xmlXPathNewContext(xmlDocPtr doc) { + xmlXPathContextPtr ret; + + ret = (xmlXPathContextPtr) xmlMalloc(sizeof(xmlXPathContext)); + if (ret == NULL) { + xmlXPathErrMemory(NULL, "creating context\n"); + return(NULL); + } + memset(ret, 0 , (size_t) sizeof(xmlXPathContext)); + ret->doc = doc; + ret->node = NULL; + + ret->varHash = NULL; + + ret->nb_types = 0; + ret->max_types = 0; + ret->types = NULL; + + ret->funcHash = xmlHashCreate(0); + + ret->nb_axis = 0; + ret->max_axis = 0; + ret->axis = NULL; + + ret->nsHash = NULL; + ret->user = NULL; + + ret->contextSize = -1; + ret->proximityPosition = -1; + +#ifdef XP_DEFAULT_CACHE_ON + if (xmlXPathContextSetCache(ret, 1, -1, 0) == -1) { + xmlXPathFreeContext(ret); + return(NULL); + } +#endif + + xmlXPathRegisterAllFunctions(ret); + + return(ret); +} + +/** + * xmlXPathFreeContext: + * @ctxt: the context to free + * + * Free up an xmlXPathContext + */ +void +xmlXPathFreeContext(xmlXPathContextPtr ctxt) { + if (ctxt == NULL) return; + + if (ctxt->cache != NULL) + xmlXPathFreeCache((xmlXPathContextCachePtr) ctxt->cache); + xmlXPathRegisteredNsCleanup(ctxt); + xmlXPathRegisteredFuncsCleanup(ctxt); + xmlXPathRegisteredVariablesCleanup(ctxt); + xmlResetError(&ctxt->lastError); + xmlFree(ctxt); +} + +/************************************************************************ + * * + * Routines to handle XPath parser contexts * + * * + ************************************************************************/ + +#define CHECK_CTXT(ctxt) \ + if (ctxt == NULL) { \ + __xmlRaiseError(NULL, NULL, NULL, \ + NULL, NULL, XML_FROM_XPATH, \ + XML_ERR_INTERNAL_ERROR, XML_ERR_FATAL, \ + __FILE__, __LINE__, \ + NULL, NULL, NULL, 0, 0, \ + "NULL context pointer\n"); \ + return(NULL); \ + } \ + +#define CHECK_CTXT_NEG(ctxt) \ + if (ctxt == NULL) { \ + __xmlRaiseError(NULL, NULL, NULL, \ + NULL, NULL, XML_FROM_XPATH, \ + XML_ERR_INTERNAL_ERROR, XML_ERR_FATAL, \ + __FILE__, __LINE__, \ + NULL, NULL, NULL, 0, 0, \ + "NULL context pointer\n"); \ + return(-1); \ + } \ + + +#define CHECK_CONTEXT(ctxt) \ + if ((ctxt == NULL) || (ctxt->doc == NULL) || \ + (ctxt->doc->children == NULL)) { \ + xmlXPatherror(ctxt, __FILE__, __LINE__, XPATH_INVALID_CTXT); \ + return(NULL); \ + } + + +/** + * xmlXPathNewParserContext: + * @str: the XPath expression + * @ctxt: the XPath context + * + * Create a new xmlXPathParserContext + * + * Returns the xmlXPathParserContext just allocated. + */ +xmlXPathParserContextPtr +xmlXPathNewParserContext(const xmlChar *str, xmlXPathContextPtr ctxt) { + xmlXPathParserContextPtr ret; + + ret = (xmlXPathParserContextPtr) xmlMalloc(sizeof(xmlXPathParserContext)); + if (ret == NULL) { + xmlXPathErrMemory(ctxt, "creating parser context\n"); + return(NULL); + } + memset(ret, 0 , (size_t) sizeof(xmlXPathParserContext)); + ret->cur = ret->base = str; + ret->context = ctxt; + + ret->comp = xmlXPathNewCompExpr(); + if (ret->comp == NULL) { + xmlFree(ret->valueTab); + xmlFree(ret); + return(NULL); + } + if ((ctxt != NULL) && (ctxt->dict != NULL)) { + ret->comp->dict = ctxt->dict; + xmlDictReference(ret->comp->dict); + } + + return(ret); +} + +/** + * xmlXPathCompParserContext: + * @comp: the XPath compiled expression + * @ctxt: the XPath context + * + * Create a new xmlXPathParserContext when processing a compiled expression + * + * Returns the xmlXPathParserContext just allocated. + */ +static xmlXPathParserContextPtr +xmlXPathCompParserContext(xmlXPathCompExprPtr comp, xmlXPathContextPtr ctxt) { + xmlXPathParserContextPtr ret; + + ret = (xmlXPathParserContextPtr) xmlMalloc(sizeof(xmlXPathParserContext)); + if (ret == NULL) { + xmlXPathErrMemory(ctxt, "creating evaluation context\n"); + return(NULL); + } + memset(ret, 0 , (size_t) sizeof(xmlXPathParserContext)); + + /* Allocate the value stack */ + ret->valueTab = (xmlXPathObjectPtr *) + xmlMalloc(10 * sizeof(xmlXPathObjectPtr)); + if (ret->valueTab == NULL) { + xmlFree(ret); + xmlXPathErrMemory(ctxt, "creating evaluation context\n"); + return(NULL); + } + ret->valueNr = 0; + ret->valueMax = 10; + ret->value = NULL; + + ret->context = ctxt; + ret->comp = comp; + + return(ret); +} + +/** + * xmlXPathFreeParserContext: + * @ctxt: the context to free + * + * Free up an xmlXPathParserContext + */ +void +xmlXPathFreeParserContext(xmlXPathParserContextPtr ctxt) { + if (ctxt->valueTab != NULL) { + xmlFree(ctxt->valueTab); + } + if (ctxt->comp != NULL) { +#ifdef XPATH_STREAMING + if (ctxt->comp->stream != NULL) { + xmlFreePatternList(ctxt->comp->stream); + ctxt->comp->stream = NULL; + } +#endif + xmlXPathFreeCompExpr(ctxt->comp); + } + xmlFree(ctxt); +} + +/************************************************************************ + * * + * The implicit core function library * + * * + ************************************************************************/ + +/** + * xmlXPathNodeValHash: + * @node: a node pointer + * + * Function computing the beginning of the string value of the node, + * used to speed up comparisons + * + * Returns an int usable as a hash + */ +static unsigned int +xmlXPathNodeValHash(xmlNodePtr node) { + int len = 2; + const xmlChar * string = NULL; + xmlNodePtr tmp = NULL; + unsigned int ret = 0; + + if (node == NULL) + return(0); + + if (node->type == XML_DOCUMENT_NODE) { + tmp = xmlDocGetRootElement((xmlDocPtr) node); + if (tmp == NULL) + node = node->children; + else + node = tmp; + + if (node == NULL) + return(0); + } + + switch (node->type) { + case XML_COMMENT_NODE: + case XML_PI_NODE: + case XML_CDATA_SECTION_NODE: + case XML_TEXT_NODE: + string = node->content; + if (string == NULL) + return(0); + if (string[0] == 0) + return(0); + return(((unsigned int) string[0]) + + (((unsigned int) string[1]) << 8)); + case XML_NAMESPACE_DECL: + string = ((xmlNsPtr)node)->href; + if (string == NULL) + return(0); + if (string[0] == 0) + return(0); + return(((unsigned int) string[0]) + + (((unsigned int) string[1]) << 8)); + case XML_ATTRIBUTE_NODE: + tmp = ((xmlAttrPtr) node)->children; + break; + case XML_ELEMENT_NODE: + tmp = node->children; + break; + default: + return(0); + } + while (tmp != NULL) { + switch (tmp->type) { + case XML_COMMENT_NODE: + case XML_PI_NODE: + case XML_CDATA_SECTION_NODE: + case XML_TEXT_NODE: + string = tmp->content; + break; + case XML_NAMESPACE_DECL: + string = ((xmlNsPtr)tmp)->href; + break; + default: + break; + } + if ((string != NULL) && (string[0] != 0)) { + if (len == 1) { + return(ret + (((unsigned int) string[0]) << 8)); + } + if (string[1] == 0) { + len = 1; + ret = (unsigned int) string[0]; + } else { + return(((unsigned int) string[0]) + + (((unsigned int) string[1]) << 8)); + } + } + /* + * Skip to next node + */ + if ((tmp->children != NULL) && (tmp->type != XML_DTD_NODE)) { + if (tmp->children->type != XML_ENTITY_DECL) { + tmp = tmp->children; + continue; + } + } + if (tmp == node) + break; + + if (tmp->next != NULL) { + tmp = tmp->next; + continue; + } + + do { + tmp = tmp->parent; + if (tmp == NULL) + break; + if (tmp == node) { + tmp = NULL; + break; + } + if (tmp->next != NULL) { + tmp = tmp->next; + break; + } + } while (tmp != NULL); + } + return(ret); +} + +/** + * xmlXPathStringHash: + * @string: a string + * + * Function computing the beginning of the string value of the node, + * used to speed up comparisons + * + * Returns an int usable as a hash + */ +static unsigned int +xmlXPathStringHash(const xmlChar * string) { + if (string == NULL) + return((unsigned int) 0); + if (string[0] == 0) + return(0); + return(((unsigned int) string[0]) + + (((unsigned int) string[1]) << 8)); +} + +/** + * xmlXPathCompareNodeSetFloat: + * @ctxt: the XPath Parser context + * @inf: less than (1) or greater than (0) + * @strict: is the comparison strict + * @arg: the node set + * @f: the value + * + * Implement the compare operation between a nodeset and a number + * @ns < @val (1, 1, ... + * @ns <= @val (1, 0, ... + * @ns > @val (0, 1, ... + * @ns >= @val (0, 0, ... + * + * If one object to be compared is a node-set and the other is a number, + * then the comparison will be true if and only if there is a node in the + * node-set such that the result of performing the comparison on the number + * to be compared and on the result of converting the string-value of that + * node to a number using the number function is true. + * + * Returns 0 or 1 depending on the results of the test. + */ +static int +xmlXPathCompareNodeSetFloat(xmlXPathParserContextPtr ctxt, int inf, int strict, + xmlXPathObjectPtr arg, xmlXPathObjectPtr f) { + int i, ret = 0; + xmlNodeSetPtr ns; + xmlChar *str2; + + if ((f == NULL) || (arg == NULL) || + ((arg->type != XPATH_NODESET) && (arg->type != XPATH_XSLT_TREE))) { + xmlXPathReleaseObject(ctxt->context, arg); + xmlXPathReleaseObject(ctxt->context, f); + return(0); + } + ns = arg->nodesetval; + if (ns != NULL) { + for (i = 0;i < ns->nodeNr;i++) { + str2 = xmlXPathCastNodeToString(ns->nodeTab[i]); + if (str2 != NULL) { + valuePush(ctxt, + xmlXPathCacheNewString(ctxt->context, str2)); + xmlFree(str2); + xmlXPathNumberFunction(ctxt, 1); + valuePush(ctxt, xmlXPathCacheObjectCopy(ctxt->context, f)); + ret = xmlXPathCompareValues(ctxt, inf, strict); + if (ret) + break; + } + } + } + xmlXPathReleaseObject(ctxt->context, arg); + xmlXPathReleaseObject(ctxt->context, f); + return(ret); +} + +/** + * xmlXPathCompareNodeSetString: + * @ctxt: the XPath Parser context + * @inf: less than (1) or greater than (0) + * @strict: is the comparison strict + * @arg: the node set + * @s: the value + * + * Implement the compare operation between a nodeset and a string + * @ns < @val (1, 1, ... + * @ns <= @val (1, 0, ... + * @ns > @val (0, 1, ... + * @ns >= @val (0, 0, ... + * + * If one object to be compared is a node-set and the other is a string, + * then the comparison will be true if and only if there is a node in + * the node-set such that the result of performing the comparison on the + * string-value of the node and the other string is true. + * + * Returns 0 or 1 depending on the results of the test. + */ +static int +xmlXPathCompareNodeSetString(xmlXPathParserContextPtr ctxt, int inf, int strict, + xmlXPathObjectPtr arg, xmlXPathObjectPtr s) { + int i, ret = 0; + xmlNodeSetPtr ns; + xmlChar *str2; + + if ((s == NULL) || (arg == NULL) || + ((arg->type != XPATH_NODESET) && (arg->type != XPATH_XSLT_TREE))) { + xmlXPathReleaseObject(ctxt->context, arg); + xmlXPathReleaseObject(ctxt->context, s); + return(0); + } + ns = arg->nodesetval; + if (ns != NULL) { + for (i = 0;i < ns->nodeNr;i++) { + str2 = xmlXPathCastNodeToString(ns->nodeTab[i]); + if (str2 != NULL) { + valuePush(ctxt, + xmlXPathCacheNewString(ctxt->context, str2)); + xmlFree(str2); + valuePush(ctxt, xmlXPathCacheObjectCopy(ctxt->context, s)); + ret = xmlXPathCompareValues(ctxt, inf, strict); + if (ret) + break; + } + } + } + xmlXPathReleaseObject(ctxt->context, arg); + xmlXPathReleaseObject(ctxt->context, s); + return(ret); +} + +/** + * xmlXPathCompareNodeSets: + * @inf: less than (1) or greater than (0) + * @strict: is the comparison strict + * @arg1: the first node set object + * @arg2: the second node set object + * + * Implement the compare operation on nodesets: + * + * If both objects to be compared are node-sets, then the comparison + * will be true if and only if there is a node in the first node-set + * and a node in the second node-set such that the result of performing + * the comparison on the string-values of the two nodes is true. + * .... + * When neither object to be compared is a node-set and the operator + * is <=, <, >= or >, then the objects are compared by converting both + * objects to numbers and comparing the numbers according to IEEE 754. + * .... + * The number function converts its argument to a number as follows: + * - a string that consists of optional whitespace followed by an + * optional minus sign followed by a Number followed by whitespace + * is converted to the IEEE 754 number that is nearest (according + * to the IEEE 754 round-to-nearest rule) to the mathematical value + * represented by the string; any other string is converted to NaN + * + * Conclusion all nodes need to be converted first to their string value + * and then the comparison must be done when possible + */ +static int +xmlXPathCompareNodeSets(int inf, int strict, + xmlXPathObjectPtr arg1, xmlXPathObjectPtr arg2) { + int i, j, init = 0; + double val1; + double *values2; + int ret = 0; + xmlNodeSetPtr ns1; + xmlNodeSetPtr ns2; + + if ((arg1 == NULL) || + ((arg1->type != XPATH_NODESET) && (arg1->type != XPATH_XSLT_TREE))) { + xmlXPathFreeObject(arg2); + return(0); + } + if ((arg2 == NULL) || + ((arg2->type != XPATH_NODESET) && (arg2->type != XPATH_XSLT_TREE))) { + xmlXPathFreeObject(arg1); + xmlXPathFreeObject(arg2); + return(0); + } + + ns1 = arg1->nodesetval; + ns2 = arg2->nodesetval; + + if ((ns1 == NULL) || (ns1->nodeNr <= 0)) { + xmlXPathFreeObject(arg1); + xmlXPathFreeObject(arg2); + return(0); + } + if ((ns2 == NULL) || (ns2->nodeNr <= 0)) { + xmlXPathFreeObject(arg1); + xmlXPathFreeObject(arg2); + return(0); + } + + values2 = (double *) xmlMalloc(ns2->nodeNr * sizeof(double)); + if (values2 == NULL) { + xmlXPathErrMemory(NULL, "comparing nodesets\n"); + xmlXPathFreeObject(arg1); + xmlXPathFreeObject(arg2); + return(0); + } + for (i = 0;i < ns1->nodeNr;i++) { + val1 = xmlXPathCastNodeToNumber(ns1->nodeTab[i]); + if (xmlXPathIsNaN(val1)) + continue; + for (j = 0;j < ns2->nodeNr;j++) { + if (init == 0) { + values2[j] = xmlXPathCastNodeToNumber(ns2->nodeTab[j]); + } + if (xmlXPathIsNaN(values2[j])) + continue; + if (inf && strict) + ret = (val1 < values2[j]); + else if (inf && !strict) + ret = (val1 <= values2[j]); + else if (!inf && strict) + ret = (val1 > values2[j]); + else if (!inf && !strict) + ret = (val1 >= values2[j]); + if (ret) + break; + } + if (ret) + break; + init = 1; + } + xmlFree(values2); + xmlXPathFreeObject(arg1); + xmlXPathFreeObject(arg2); + return(ret); +} + +/** + * xmlXPathCompareNodeSetValue: + * @ctxt: the XPath Parser context + * @inf: less than (1) or greater than (0) + * @strict: is the comparison strict + * @arg: the node set + * @val: the value + * + * Implement the compare operation between a nodeset and a value + * @ns < @val (1, 1, ... + * @ns <= @val (1, 0, ... + * @ns > @val (0, 1, ... + * @ns >= @val (0, 0, ... + * + * If one object to be compared is a node-set and the other is a boolean, + * then the comparison will be true if and only if the result of performing + * the comparison on the boolean and on the result of converting + * the node-set to a boolean using the boolean function is true. + * + * Returns 0 or 1 depending on the results of the test. + */ +static int +xmlXPathCompareNodeSetValue(xmlXPathParserContextPtr ctxt, int inf, int strict, + xmlXPathObjectPtr arg, xmlXPathObjectPtr val) { + if ((val == NULL) || (arg == NULL) || + ((arg->type != XPATH_NODESET) && (arg->type != XPATH_XSLT_TREE))) + return(0); + + switch(val->type) { + case XPATH_NUMBER: + return(xmlXPathCompareNodeSetFloat(ctxt, inf, strict, arg, val)); + case XPATH_NODESET: + case XPATH_XSLT_TREE: + return(xmlXPathCompareNodeSets(inf, strict, arg, val)); + case XPATH_STRING: + return(xmlXPathCompareNodeSetString(ctxt, inf, strict, arg, val)); + case XPATH_BOOLEAN: + valuePush(ctxt, arg); + xmlXPathBooleanFunction(ctxt, 1); + valuePush(ctxt, val); + return(xmlXPathCompareValues(ctxt, inf, strict)); + default: + TODO + } + return(0); +} + +/** + * xmlXPathEqualNodeSetString: + * @arg: the nodeset object argument + * @str: the string to compare to. + * @neq: flag to show whether for '=' (0) or '!=' (1) + * + * Implement the equal operation on XPath objects content: @arg1 == @arg2 + * If one object to be compared is a node-set and the other is a string, + * then the comparison will be true if and only if there is a node in + * the node-set such that the result of performing the comparison on the + * string-value of the node and the other string is true. + * + * Returns 0 or 1 depending on the results of the test. + */ +static int +xmlXPathEqualNodeSetString(xmlXPathObjectPtr arg, const xmlChar * str, int neq) +{ + int i; + xmlNodeSetPtr ns; + xmlChar *str2; + unsigned int hash; + + if ((str == NULL) || (arg == NULL) || + ((arg->type != XPATH_NODESET) && (arg->type != XPATH_XSLT_TREE))) + return (0); + ns = arg->nodesetval; + /* + * A NULL nodeset compared with a string is always false + * (since there is no node equal, and no node not equal) + */ + if ((ns == NULL) || (ns->nodeNr <= 0) ) + return (0); + hash = xmlXPathStringHash(str); + for (i = 0; i < ns->nodeNr; i++) { + if (xmlXPathNodeValHash(ns->nodeTab[i]) == hash) { + str2 = xmlNodeGetContent(ns->nodeTab[i]); + if ((str2 != NULL) && (xmlStrEqual(str, str2))) { + xmlFree(str2); + if (neq) + continue; + return (1); + } else if ((str2 == NULL) && (xmlStrEqual(str, BAD_CAST ""))) { + if (neq) + continue; + return (1); + } else if (neq) { + if (str2 != NULL) + xmlFree(str2); + return (1); + } + if (str2 != NULL) + xmlFree(str2); + } else if (neq) + return (1); + } + return (0); +} + +/** + * xmlXPathEqualNodeSetFloat: + * @arg: the nodeset object argument + * @f: the float to compare to + * @neq: flag to show whether to compare '=' (0) or '!=' (1) + * + * Implement the equal operation on XPath objects content: @arg1 == @arg2 + * If one object to be compared is a node-set and the other is a number, + * then the comparison will be true if and only if there is a node in + * the node-set such that the result of performing the comparison on the + * number to be compared and on the result of converting the string-value + * of that node to a number using the number function is true. + * + * Returns 0 or 1 depending on the results of the test. + */ +static int +xmlXPathEqualNodeSetFloat(xmlXPathParserContextPtr ctxt, + xmlXPathObjectPtr arg, double f, int neq) { + int i, ret=0; + xmlNodeSetPtr ns; + xmlChar *str2; + xmlXPathObjectPtr val; + double v; + + if ((arg == NULL) || + ((arg->type != XPATH_NODESET) && (arg->type != XPATH_XSLT_TREE))) + return(0); + + ns = arg->nodesetval; + if (ns != NULL) { + for (i=0;inodeNr;i++) { + str2 = xmlXPathCastNodeToString(ns->nodeTab[i]); + if (str2 != NULL) { + valuePush(ctxt, xmlXPathCacheNewString(ctxt->context, str2)); + xmlFree(str2); + xmlXPathNumberFunction(ctxt, 1); + val = valuePop(ctxt); + v = val->floatval; + xmlXPathReleaseObject(ctxt->context, val); + if (!xmlXPathIsNaN(v)) { + if ((!neq) && (v==f)) { + ret = 1; + break; + } else if ((neq) && (v!=f)) { + ret = 1; + break; + } + } else { /* NaN is unequal to any value */ + if (neq) + ret = 1; + } + } + } + } + + return(ret); +} + + +/** + * xmlXPathEqualNodeSets: + * @arg1: first nodeset object argument + * @arg2: second nodeset object argument + * @neq: flag to show whether to test '=' (0) or '!=' (1) + * + * Implement the equal / not equal operation on XPath nodesets: + * @arg1 == @arg2 or @arg1 != @arg2 + * If both objects to be compared are node-sets, then the comparison + * will be true if and only if there is a node in the first node-set and + * a node in the second node-set such that the result of performing the + * comparison on the string-values of the two nodes is true. + * + * (needless to say, this is a costly operation) + * + * Returns 0 or 1 depending on the results of the test. + */ +static int +xmlXPathEqualNodeSets(xmlXPathObjectPtr arg1, xmlXPathObjectPtr arg2, int neq) { + int i, j; + unsigned int *hashs1; + unsigned int *hashs2; + xmlChar **values1; + xmlChar **values2; + int ret = 0; + xmlNodeSetPtr ns1; + xmlNodeSetPtr ns2; + + if ((arg1 == NULL) || + ((arg1->type != XPATH_NODESET) && (arg1->type != XPATH_XSLT_TREE))) + return(0); + if ((arg2 == NULL) || + ((arg2->type != XPATH_NODESET) && (arg2->type != XPATH_XSLT_TREE))) + return(0); + + ns1 = arg1->nodesetval; + ns2 = arg2->nodesetval; + + if ((ns1 == NULL) || (ns1->nodeNr <= 0)) + return(0); + if ((ns2 == NULL) || (ns2->nodeNr <= 0)) + return(0); + + /* + * for equal, check if there is a node pertaining to both sets + */ + if (neq == 0) + for (i = 0;i < ns1->nodeNr;i++) + for (j = 0;j < ns2->nodeNr;j++) + if (ns1->nodeTab[i] == ns2->nodeTab[j]) + return(1); + + values1 = (xmlChar **) xmlMalloc(ns1->nodeNr * sizeof(xmlChar *)); + if (values1 == NULL) { + xmlXPathErrMemory(NULL, "comparing nodesets\n"); + return(0); + } + hashs1 = (unsigned int *) xmlMalloc(ns1->nodeNr * sizeof(unsigned int)); + if (hashs1 == NULL) { + xmlXPathErrMemory(NULL, "comparing nodesets\n"); + xmlFree(values1); + return(0); + } + memset(values1, 0, ns1->nodeNr * sizeof(xmlChar *)); + values2 = (xmlChar **) xmlMalloc(ns2->nodeNr * sizeof(xmlChar *)); + if (values2 == NULL) { + xmlXPathErrMemory(NULL, "comparing nodesets\n"); + xmlFree(hashs1); + xmlFree(values1); + return(0); + } + hashs2 = (unsigned int *) xmlMalloc(ns2->nodeNr * sizeof(unsigned int)); + if (hashs2 == NULL) { + xmlXPathErrMemory(NULL, "comparing nodesets\n"); + xmlFree(hashs1); + xmlFree(values1); + xmlFree(values2); + return(0); + } + memset(values2, 0, ns2->nodeNr * sizeof(xmlChar *)); + for (i = 0;i < ns1->nodeNr;i++) { + hashs1[i] = xmlXPathNodeValHash(ns1->nodeTab[i]); + for (j = 0;j < ns2->nodeNr;j++) { + if (i == 0) + hashs2[j] = xmlXPathNodeValHash(ns2->nodeTab[j]); + if (hashs1[i] != hashs2[j]) { + if (neq) { + ret = 1; + break; + } + } + else { + if (values1[i] == NULL) + values1[i] = xmlNodeGetContent(ns1->nodeTab[i]); + if (values2[j] == NULL) + values2[j] = xmlNodeGetContent(ns2->nodeTab[j]); + ret = xmlStrEqual(values1[i], values2[j]) ^ neq; + if (ret) + break; + } + } + if (ret) + break; + } + for (i = 0;i < ns1->nodeNr;i++) + if (values1[i] != NULL) + xmlFree(values1[i]); + for (j = 0;j < ns2->nodeNr;j++) + if (values2[j] != NULL) + xmlFree(values2[j]); + xmlFree(values1); + xmlFree(values2); + xmlFree(hashs1); + xmlFree(hashs2); + return(ret); +} + +static int +xmlXPathEqualValuesCommon(xmlXPathParserContextPtr ctxt, + xmlXPathObjectPtr arg1, xmlXPathObjectPtr arg2) { + int ret = 0; + /* + *At this point we are assured neither arg1 nor arg2 + *is a nodeset, so we can just pick the appropriate routine. + */ + switch (arg1->type) { + case XPATH_UNDEFINED: +#ifdef DEBUG_EXPR + xmlGenericError(xmlGenericErrorContext, + "Equal: undefined\n"); +#endif + break; + case XPATH_BOOLEAN: + switch (arg2->type) { + case XPATH_UNDEFINED: +#ifdef DEBUG_EXPR + xmlGenericError(xmlGenericErrorContext, + "Equal: undefined\n"); +#endif + break; + case XPATH_BOOLEAN: +#ifdef DEBUG_EXPR + xmlGenericError(xmlGenericErrorContext, + "Equal: %d boolean %d \n", + arg1->boolval, arg2->boolval); +#endif + ret = (arg1->boolval == arg2->boolval); + break; + case XPATH_NUMBER: + ret = (arg1->boolval == + xmlXPathCastNumberToBoolean(arg2->floatval)); + break; + case XPATH_STRING: + if ((arg2->stringval == NULL) || + (arg2->stringval[0] == 0)) ret = 0; + else + ret = 1; + ret = (arg1->boolval == ret); + break; + case XPATH_USERS: + case XPATH_POINT: + case XPATH_RANGE: + case XPATH_LOCATIONSET: + TODO + break; + case XPATH_NODESET: + case XPATH_XSLT_TREE: + break; + } + break; + case XPATH_NUMBER: + switch (arg2->type) { + case XPATH_UNDEFINED: +#ifdef DEBUG_EXPR + xmlGenericError(xmlGenericErrorContext, + "Equal: undefined\n"); +#endif + break; + case XPATH_BOOLEAN: + ret = (arg2->boolval== + xmlXPathCastNumberToBoolean(arg1->floatval)); + break; + case XPATH_STRING: + valuePush(ctxt, arg2); + xmlXPathNumberFunction(ctxt, 1); + arg2 = valuePop(ctxt); + /* no break on purpose */ + case XPATH_NUMBER: + /* Hand check NaN and Infinity equalities */ + if (xmlXPathIsNaN(arg1->floatval) || + xmlXPathIsNaN(arg2->floatval)) { + ret = 0; + } else if (xmlXPathIsInf(arg1->floatval) == 1) { + if (xmlXPathIsInf(arg2->floatval) == 1) + ret = 1; + else + ret = 0; + } else if (xmlXPathIsInf(arg1->floatval) == -1) { + if (xmlXPathIsInf(arg2->floatval) == -1) + ret = 1; + else + ret = 0; + } else if (xmlXPathIsInf(arg2->floatval) == 1) { + if (xmlXPathIsInf(arg1->floatval) == 1) + ret = 1; + else + ret = 0; + } else if (xmlXPathIsInf(arg2->floatval) == -1) { + if (xmlXPathIsInf(arg1->floatval) == -1) + ret = 1; + else + ret = 0; + } else { + ret = (arg1->floatval == arg2->floatval); + } + break; + case XPATH_USERS: + case XPATH_POINT: + case XPATH_RANGE: + case XPATH_LOCATIONSET: + TODO + break; + case XPATH_NODESET: + case XPATH_XSLT_TREE: + break; + } + break; + case XPATH_STRING: + switch (arg2->type) { + case XPATH_UNDEFINED: +#ifdef DEBUG_EXPR + xmlGenericError(xmlGenericErrorContext, + "Equal: undefined\n"); +#endif + break; + case XPATH_BOOLEAN: + if ((arg1->stringval == NULL) || + (arg1->stringval[0] == 0)) ret = 0; + else + ret = 1; + ret = (arg2->boolval == ret); + break; + case XPATH_STRING: + ret = xmlStrEqual(arg1->stringval, arg2->stringval); + break; + case XPATH_NUMBER: + valuePush(ctxt, arg1); + xmlXPathNumberFunction(ctxt, 1); + arg1 = valuePop(ctxt); + /* Hand check NaN and Infinity equalities */ + if (xmlXPathIsNaN(arg1->floatval) || + xmlXPathIsNaN(arg2->floatval)) { + ret = 0; + } else if (xmlXPathIsInf(arg1->floatval) == 1) { + if (xmlXPathIsInf(arg2->floatval) == 1) + ret = 1; + else + ret = 0; + } else if (xmlXPathIsInf(arg1->floatval) == -1) { + if (xmlXPathIsInf(arg2->floatval) == -1) + ret = 1; + else + ret = 0; + } else if (xmlXPathIsInf(arg2->floatval) == 1) { + if (xmlXPathIsInf(arg1->floatval) == 1) + ret = 1; + else + ret = 0; + } else if (xmlXPathIsInf(arg2->floatval) == -1) { + if (xmlXPathIsInf(arg1->floatval) == -1) + ret = 1; + else + ret = 0; + } else { + ret = (arg1->floatval == arg2->floatval); + } + break; + case XPATH_USERS: + case XPATH_POINT: + case XPATH_RANGE: + case XPATH_LOCATIONSET: + TODO + break; + case XPATH_NODESET: + case XPATH_XSLT_TREE: + break; + } + break; + case XPATH_USERS: + case XPATH_POINT: + case XPATH_RANGE: + case XPATH_LOCATIONSET: + TODO + break; + case XPATH_NODESET: + case XPATH_XSLT_TREE: + break; + } + xmlXPathReleaseObject(ctxt->context, arg1); + xmlXPathReleaseObject(ctxt->context, arg2); + return(ret); +} + +/** + * xmlXPathEqualValues: + * @ctxt: the XPath Parser context + * + * Implement the equal operation on XPath objects content: @arg1 == @arg2 + * + * Returns 0 or 1 depending on the results of the test. + */ +int +xmlXPathEqualValues(xmlXPathParserContextPtr ctxt) { + xmlXPathObjectPtr arg1, arg2, argtmp; + int ret = 0; + + if ((ctxt == NULL) || (ctxt->context == NULL)) return(0); + arg2 = valuePop(ctxt); + arg1 = valuePop(ctxt); + if ((arg1 == NULL) || (arg2 == NULL)) { + if (arg1 != NULL) + xmlXPathReleaseObject(ctxt->context, arg1); + else + xmlXPathReleaseObject(ctxt->context, arg2); + XP_ERROR0(XPATH_INVALID_OPERAND); + } + + if (arg1 == arg2) { +#ifdef DEBUG_EXPR + xmlGenericError(xmlGenericErrorContext, + "Equal: by pointer\n"); +#endif + xmlXPathFreeObject(arg1); + return(1); + } + + /* + *If either argument is a nodeset, it's a 'special case' + */ + if ((arg2->type == XPATH_NODESET) || (arg2->type == XPATH_XSLT_TREE) || + (arg1->type == XPATH_NODESET) || (arg1->type == XPATH_XSLT_TREE)) { + /* + *Hack it to assure arg1 is the nodeset + */ + if ((arg1->type != XPATH_NODESET) && (arg1->type != XPATH_XSLT_TREE)) { + argtmp = arg2; + arg2 = arg1; + arg1 = argtmp; + } + switch (arg2->type) { + case XPATH_UNDEFINED: +#ifdef DEBUG_EXPR + xmlGenericError(xmlGenericErrorContext, + "Equal: undefined\n"); +#endif + break; + case XPATH_NODESET: + case XPATH_XSLT_TREE: + ret = xmlXPathEqualNodeSets(arg1, arg2, 0); + break; + case XPATH_BOOLEAN: + if ((arg1->nodesetval == NULL) || + (arg1->nodesetval->nodeNr == 0)) ret = 0; + else + ret = 1; + ret = (ret == arg2->boolval); + break; + case XPATH_NUMBER: + ret = xmlXPathEqualNodeSetFloat(ctxt, arg1, arg2->floatval, 0); + break; + case XPATH_STRING: + ret = xmlXPathEqualNodeSetString(arg1, arg2->stringval, 0); + break; + case XPATH_USERS: + case XPATH_POINT: + case XPATH_RANGE: + case XPATH_LOCATIONSET: + TODO + break; + } + xmlXPathReleaseObject(ctxt->context, arg1); + xmlXPathReleaseObject(ctxt->context, arg2); + return(ret); + } + + return (xmlXPathEqualValuesCommon(ctxt, arg1, arg2)); +} + +/** + * xmlXPathNotEqualValues: + * @ctxt: the XPath Parser context + * + * Implement the equal operation on XPath objects content: @arg1 == @arg2 + * + * Returns 0 or 1 depending on the results of the test. + */ +int +xmlXPathNotEqualValues(xmlXPathParserContextPtr ctxt) { + xmlXPathObjectPtr arg1, arg2, argtmp; + int ret = 0; + + if ((ctxt == NULL) || (ctxt->context == NULL)) return(0); + arg2 = valuePop(ctxt); + arg1 = valuePop(ctxt); + if ((arg1 == NULL) || (arg2 == NULL)) { + if (arg1 != NULL) + xmlXPathReleaseObject(ctxt->context, arg1); + else + xmlXPathReleaseObject(ctxt->context, arg2); + XP_ERROR0(XPATH_INVALID_OPERAND); + } + + if (arg1 == arg2) { +#ifdef DEBUG_EXPR + xmlGenericError(xmlGenericErrorContext, + "NotEqual: by pointer\n"); +#endif + xmlXPathReleaseObject(ctxt->context, arg1); + return(0); + } + + /* + *If either argument is a nodeset, it's a 'special case' + */ + if ((arg2->type == XPATH_NODESET) || (arg2->type == XPATH_XSLT_TREE) || + (arg1->type == XPATH_NODESET) || (arg1->type == XPATH_XSLT_TREE)) { + /* + *Hack it to assure arg1 is the nodeset + */ + if ((arg1->type != XPATH_NODESET) && (arg1->type != XPATH_XSLT_TREE)) { + argtmp = arg2; + arg2 = arg1; + arg1 = argtmp; + } + switch (arg2->type) { + case XPATH_UNDEFINED: +#ifdef DEBUG_EXPR + xmlGenericError(xmlGenericErrorContext, + "NotEqual: undefined\n"); +#endif + break; + case XPATH_NODESET: + case XPATH_XSLT_TREE: + ret = xmlXPathEqualNodeSets(arg1, arg2, 1); + break; + case XPATH_BOOLEAN: + if ((arg1->nodesetval == NULL) || + (arg1->nodesetval->nodeNr == 0)) ret = 0; + else + ret = 1; + ret = (ret != arg2->boolval); + break; + case XPATH_NUMBER: + ret = xmlXPathEqualNodeSetFloat(ctxt, arg1, arg2->floatval, 1); + break; + case XPATH_STRING: + ret = xmlXPathEqualNodeSetString(arg1, arg2->stringval,1); + break; + case XPATH_USERS: + case XPATH_POINT: + case XPATH_RANGE: + case XPATH_LOCATIONSET: + TODO + break; + } + xmlXPathReleaseObject(ctxt->context, arg1); + xmlXPathReleaseObject(ctxt->context, arg2); + return(ret); + } + + return (!xmlXPathEqualValuesCommon(ctxt, arg1, arg2)); +} + +/** + * xmlXPathCompareValues: + * @ctxt: the XPath Parser context + * @inf: less than (1) or greater than (0) + * @strict: is the comparison strict + * + * Implement the compare operation on XPath objects: + * @arg1 < @arg2 (1, 1, ... + * @arg1 <= @arg2 (1, 0, ... + * @arg1 > @arg2 (0, 1, ... + * @arg1 >= @arg2 (0, 0, ... + * + * When neither object to be compared is a node-set and the operator is + * <=, <, >=, >, then the objects are compared by converted both objects + * to numbers and comparing the numbers according to IEEE 754. The < + * comparison will be true if and only if the first number is less than the + * second number. The <= comparison will be true if and only if the first + * number is less than or equal to the second number. The > comparison + * will be true if and only if the first number is greater than the second + * number. The >= comparison will be true if and only if the first number + * is greater than or equal to the second number. + * + * Returns 1 if the comparison succeeded, 0 if it failed + */ +int +xmlXPathCompareValues(xmlXPathParserContextPtr ctxt, int inf, int strict) { + int ret = 0, arg1i = 0, arg2i = 0; + xmlXPathObjectPtr arg1, arg2; + + if ((ctxt == NULL) || (ctxt->context == NULL)) return(0); + arg2 = valuePop(ctxt); + arg1 = valuePop(ctxt); + if ((arg1 == NULL) || (arg2 == NULL)) { + if (arg1 != NULL) + xmlXPathReleaseObject(ctxt->context, arg1); + else + xmlXPathReleaseObject(ctxt->context, arg2); + XP_ERROR0(XPATH_INVALID_OPERAND); + } + + if ((arg2->type == XPATH_NODESET) || (arg2->type == XPATH_XSLT_TREE) || + (arg1->type == XPATH_NODESET) || (arg1->type == XPATH_XSLT_TREE)) { + /* + * If either argument is a XPATH_NODESET or XPATH_XSLT_TREE the two arguments + * are not freed from within this routine; they will be freed from the + * called routine, e.g. xmlXPathCompareNodeSets or xmlXPathCompareNodeSetValue + */ + if (((arg2->type == XPATH_NODESET) || (arg2->type == XPATH_XSLT_TREE)) && + ((arg1->type == XPATH_NODESET) || (arg1->type == XPATH_XSLT_TREE))){ + ret = xmlXPathCompareNodeSets(inf, strict, arg1, arg2); + } else { + if ((arg1->type == XPATH_NODESET) || (arg1->type == XPATH_XSLT_TREE)) { + ret = xmlXPathCompareNodeSetValue(ctxt, inf, strict, + arg1, arg2); + } else { + ret = xmlXPathCompareNodeSetValue(ctxt, !inf, strict, + arg2, arg1); + } + } + return(ret); + } + + if (arg1->type != XPATH_NUMBER) { + valuePush(ctxt, arg1); + xmlXPathNumberFunction(ctxt, 1); + arg1 = valuePop(ctxt); + } + if (arg1->type != XPATH_NUMBER) { + xmlXPathFreeObject(arg1); + xmlXPathFreeObject(arg2); + XP_ERROR0(XPATH_INVALID_OPERAND); + } + if (arg2->type != XPATH_NUMBER) { + valuePush(ctxt, arg2); + xmlXPathNumberFunction(ctxt, 1); + arg2 = valuePop(ctxt); + } + if (arg2->type != XPATH_NUMBER) { + xmlXPathReleaseObject(ctxt->context, arg1); + xmlXPathReleaseObject(ctxt->context, arg2); + XP_ERROR0(XPATH_INVALID_OPERAND); + } + /* + * Add tests for infinity and nan + * => feedback on 3.4 for Inf and NaN + */ + /* Hand check NaN and Infinity comparisons */ + if (xmlXPathIsNaN(arg1->floatval) || xmlXPathIsNaN(arg2->floatval)) { + ret=0; + } else { + arg1i=xmlXPathIsInf(arg1->floatval); + arg2i=xmlXPathIsInf(arg2->floatval); + if (inf && strict) { + if ((arg1i == -1 && arg2i != -1) || + (arg2i == 1 && arg1i != 1)) { + ret = 1; + } else if (arg1i == 0 && arg2i == 0) { + ret = (arg1->floatval < arg2->floatval); + } else { + ret = 0; + } + } + else if (inf && !strict) { + if (arg1i == -1 || arg2i == 1) { + ret = 1; + } else if (arg1i == 0 && arg2i == 0) { + ret = (arg1->floatval <= arg2->floatval); + } else { + ret = 0; + } + } + else if (!inf && strict) { + if ((arg1i == 1 && arg2i != 1) || + (arg2i == -1 && arg1i != -1)) { + ret = 1; + } else if (arg1i == 0 && arg2i == 0) { + ret = (arg1->floatval > arg2->floatval); + } else { + ret = 0; + } + } + else if (!inf && !strict) { + if (arg1i == 1 || arg2i == -1) { + ret = 1; + } else if (arg1i == 0 && arg2i == 0) { + ret = (arg1->floatval >= arg2->floatval); + } else { + ret = 0; + } + } + } + xmlXPathReleaseObject(ctxt->context, arg1); + xmlXPathReleaseObject(ctxt->context, arg2); + return(ret); +} + +/** + * xmlXPathValueFlipSign: + * @ctxt: the XPath Parser context + * + * Implement the unary - operation on an XPath object + * The numeric operators convert their operands to numbers as if + * by calling the number function. + */ +void +xmlXPathValueFlipSign(xmlXPathParserContextPtr ctxt) { + if ((ctxt == NULL) || (ctxt->context == NULL)) return; + CAST_TO_NUMBER; + CHECK_TYPE(XPATH_NUMBER); + if (xmlXPathIsNaN(ctxt->value->floatval)) + ctxt->value->floatval=xmlXPathNAN; + else if (xmlXPathIsInf(ctxt->value->floatval) == 1) + ctxt->value->floatval=xmlXPathNINF; + else if (xmlXPathIsInf(ctxt->value->floatval) == -1) + ctxt->value->floatval=xmlXPathPINF; + else if (ctxt->value->floatval == 0) { + if (xmlXPathGetSign(ctxt->value->floatval) == 0) + ctxt->value->floatval = xmlXPathNZERO; + else + ctxt->value->floatval = 0; + } + else + ctxt->value->floatval = - ctxt->value->floatval; +} + +/** + * xmlXPathAddValues: + * @ctxt: the XPath Parser context + * + * Implement the add operation on XPath objects: + * The numeric operators convert their operands to numbers as if + * by calling the number function. + */ +void +xmlXPathAddValues(xmlXPathParserContextPtr ctxt) { + xmlXPathObjectPtr arg; + double val; + + arg = valuePop(ctxt); + if (arg == NULL) + XP_ERROR(XPATH_INVALID_OPERAND); + val = xmlXPathCastToNumber(arg); + xmlXPathReleaseObject(ctxt->context, arg); + CAST_TO_NUMBER; + CHECK_TYPE(XPATH_NUMBER); + ctxt->value->floatval += val; +} + +/** + * xmlXPathSubValues: + * @ctxt: the XPath Parser context + * + * Implement the subtraction operation on XPath objects: + * The numeric operators convert their operands to numbers as if + * by calling the number function. + */ +void +xmlXPathSubValues(xmlXPathParserContextPtr ctxt) { + xmlXPathObjectPtr arg; + double val; + + arg = valuePop(ctxt); + if (arg == NULL) + XP_ERROR(XPATH_INVALID_OPERAND); + val = xmlXPathCastToNumber(arg); + xmlXPathReleaseObject(ctxt->context, arg); + CAST_TO_NUMBER; + CHECK_TYPE(XPATH_NUMBER); + ctxt->value->floatval -= val; +} + +/** + * xmlXPathMultValues: + * @ctxt: the XPath Parser context + * + * Implement the multiply operation on XPath objects: + * The numeric operators convert their operands to numbers as if + * by calling the number function. + */ +void +xmlXPathMultValues(xmlXPathParserContextPtr ctxt) { + xmlXPathObjectPtr arg; + double val; + + arg = valuePop(ctxt); + if (arg == NULL) + XP_ERROR(XPATH_INVALID_OPERAND); + val = xmlXPathCastToNumber(arg); + xmlXPathReleaseObject(ctxt->context, arg); + CAST_TO_NUMBER; + CHECK_TYPE(XPATH_NUMBER); + ctxt->value->floatval *= val; +} + +/** + * xmlXPathDivValues: + * @ctxt: the XPath Parser context + * + * Implement the div operation on XPath objects @arg1 / @arg2: + * The numeric operators convert their operands to numbers as if + * by calling the number function. + */ +void +xmlXPathDivValues(xmlXPathParserContextPtr ctxt) { + xmlXPathObjectPtr arg; + double val; + + arg = valuePop(ctxt); + if (arg == NULL) + XP_ERROR(XPATH_INVALID_OPERAND); + val = xmlXPathCastToNumber(arg); + xmlXPathReleaseObject(ctxt->context, arg); + CAST_TO_NUMBER; + CHECK_TYPE(XPATH_NUMBER); + if (xmlXPathIsNaN(val) || xmlXPathIsNaN(ctxt->value->floatval)) + ctxt->value->floatval = xmlXPathNAN; + else if (val == 0 && xmlXPathGetSign(val) != 0) { + if (ctxt->value->floatval == 0) + ctxt->value->floatval = xmlXPathNAN; + else if (ctxt->value->floatval > 0) + ctxt->value->floatval = xmlXPathNINF; + else if (ctxt->value->floatval < 0) + ctxt->value->floatval = xmlXPathPINF; + } + else if (val == 0) { + if (ctxt->value->floatval == 0) + ctxt->value->floatval = xmlXPathNAN; + else if (ctxt->value->floatval > 0) + ctxt->value->floatval = xmlXPathPINF; + else if (ctxt->value->floatval < 0) + ctxt->value->floatval = xmlXPathNINF; + } else + ctxt->value->floatval /= val; +} + +/** + * xmlXPathModValues: + * @ctxt: the XPath Parser context + * + * Implement the mod operation on XPath objects: @arg1 / @arg2 + * The numeric operators convert their operands to numbers as if + * by calling the number function. + */ +void +xmlXPathModValues(xmlXPathParserContextPtr ctxt) { + xmlXPathObjectPtr arg; + double arg1, arg2; + + arg = valuePop(ctxt); + if (arg == NULL) + XP_ERROR(XPATH_INVALID_OPERAND); + arg2 = xmlXPathCastToNumber(arg); + xmlXPathReleaseObject(ctxt->context, arg); + CAST_TO_NUMBER; + CHECK_TYPE(XPATH_NUMBER); + arg1 = ctxt->value->floatval; + if (arg2 == 0) + ctxt->value->floatval = xmlXPathNAN; + else { + ctxt->value->floatval = fmod(arg1, arg2); + } +} + +/************************************************************************ + * * + * The traversal functions * + * * + ************************************************************************/ + +/* + * A traversal function enumerates nodes along an axis. + * Initially it must be called with NULL, and it indicates + * termination on the axis by returning NULL. + */ +typedef xmlNodePtr (*xmlXPathTraversalFunction) + (xmlXPathParserContextPtr ctxt, xmlNodePtr cur); + +/* + * xmlXPathTraversalFunctionExt: + * A traversal function enumerates nodes along an axis. + * Initially it must be called with NULL, and it indicates + * termination on the axis by returning NULL. + * The context node of the traversal is specified via @contextNode. + */ +typedef xmlNodePtr (*xmlXPathTraversalFunctionExt) + (xmlNodePtr cur, xmlNodePtr contextNode); + +/* + * xmlXPathNodeSetMergeFunction: + * Used for merging node sets in xmlXPathCollectAndTest(). + */ +typedef xmlNodeSetPtr (*xmlXPathNodeSetMergeFunction) + (xmlNodeSetPtr, xmlNodeSetPtr, int); + + +/** + * xmlXPathNextSelf: + * @ctxt: the XPath Parser context + * @cur: the current node in the traversal + * + * Traversal function for the "self" direction + * The self axis contains just the context node itself + * + * Returns the next element following that axis + */ +xmlNodePtr +xmlXPathNextSelf(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) { + if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL); + if (cur == NULL) + return(ctxt->context->node); + return(NULL); +} + +/** + * xmlXPathNextChild: + * @ctxt: the XPath Parser context + * @cur: the current node in the traversal + * + * Traversal function for the "child" direction + * The child axis contains the children of the context node in document order. + * + * Returns the next element following that axis + */ +xmlNodePtr +xmlXPathNextChild(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) { + if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL); + if (cur == NULL) { + if (ctxt->context->node == NULL) return(NULL); + switch (ctxt->context->node->type) { + case XML_ELEMENT_NODE: + case XML_TEXT_NODE: + case XML_CDATA_SECTION_NODE: + case XML_ENTITY_REF_NODE: + case XML_ENTITY_NODE: + case XML_PI_NODE: + case XML_COMMENT_NODE: + case XML_NOTATION_NODE: + case XML_DTD_NODE: + return(ctxt->context->node->children); + case XML_DOCUMENT_NODE: + case XML_DOCUMENT_TYPE_NODE: + case XML_DOCUMENT_FRAG_NODE: + case XML_HTML_DOCUMENT_NODE: +#ifdef LIBXML_DOCB_ENABLED + case XML_DOCB_DOCUMENT_NODE: +#endif + return(((xmlDocPtr) ctxt->context->node)->children); + case XML_ELEMENT_DECL: + case XML_ATTRIBUTE_DECL: + case XML_ENTITY_DECL: + case XML_ATTRIBUTE_NODE: + case XML_NAMESPACE_DECL: + case XML_XINCLUDE_START: + case XML_XINCLUDE_END: + return(NULL); + } + return(NULL); + } + if ((cur->type == XML_DOCUMENT_NODE) || + (cur->type == XML_HTML_DOCUMENT_NODE)) + return(NULL); + return(cur->next); +} + +/** + * xmlXPathNextChildElement: + * @ctxt: the XPath Parser context + * @cur: the current node in the traversal + * + * Traversal function for the "child" direction and nodes of type element. + * The child axis contains the children of the context node in document order. + * + * Returns the next element following that axis + */ +static xmlNodePtr +xmlXPathNextChildElement(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) { + if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL); + if (cur == NULL) { + cur = ctxt->context->node; + if (cur == NULL) return(NULL); + /* + * Get the first element child. + */ + switch (cur->type) { + case XML_ELEMENT_NODE: + case XML_DOCUMENT_FRAG_NODE: + case XML_ENTITY_REF_NODE: /* URGENT TODO: entify-refs as well? */ + case XML_ENTITY_NODE: + cur = cur->children; + if (cur != NULL) { + if (cur->type == XML_ELEMENT_NODE) + return(cur); + do { + cur = cur->next; + } while ((cur != NULL) && + (cur->type != XML_ELEMENT_NODE)); + return(cur); + } + return(NULL); + case XML_DOCUMENT_NODE: + case XML_HTML_DOCUMENT_NODE: +#ifdef LIBXML_DOCB_ENABLED + case XML_DOCB_DOCUMENT_NODE: +#endif + return(xmlDocGetRootElement((xmlDocPtr) cur)); + default: + return(NULL); + } + return(NULL); + } + /* + * Get the next sibling element node. + */ + switch (cur->type) { + case XML_ELEMENT_NODE: + case XML_TEXT_NODE: + case XML_ENTITY_REF_NODE: + case XML_ENTITY_NODE: + case XML_CDATA_SECTION_NODE: + case XML_PI_NODE: + case XML_COMMENT_NODE: + case XML_XINCLUDE_END: + break; + /* case XML_DTD_NODE: */ /* URGENT TODO: DTD-node as well? */ + default: + return(NULL); + } + if (cur->next != NULL) { + if (cur->next->type == XML_ELEMENT_NODE) + return(cur->next); + cur = cur->next; + do { + cur = cur->next; + } while ((cur != NULL) && (cur->type != XML_ELEMENT_NODE)); + return(cur); + } + return(NULL); +} + +/** + * xmlXPathNextDescendantOrSelfElemParent: + * @ctxt: the XPath Parser context + * @cur: the current node in the traversal + * + * Traversal function for the "descendant-or-self" axis. + * Additionally it returns only nodes which can be parents of + * element nodes. + * + * + * Returns the next element following that axis + */ +static xmlNodePtr +xmlXPathNextDescendantOrSelfElemParent(xmlNodePtr cur, + xmlNodePtr contextNode) +{ + if (cur == NULL) { + if (contextNode == NULL) + return(NULL); + switch (contextNode->type) { + case XML_ELEMENT_NODE: + case XML_XINCLUDE_START: + case XML_DOCUMENT_FRAG_NODE: + case XML_DOCUMENT_NODE: +#ifdef LIBXML_DOCB_ENABLED + case XML_DOCB_DOCUMENT_NODE: +#endif + case XML_HTML_DOCUMENT_NODE: + return(contextNode); + default: + return(NULL); + } + return(NULL); + } else { + xmlNodePtr start = cur; + + while (cur != NULL) { + switch (cur->type) { + case XML_ELEMENT_NODE: + /* TODO: OK to have XInclude here? */ + case XML_XINCLUDE_START: + case XML_DOCUMENT_FRAG_NODE: + if (cur != start) + return(cur); + if (cur->children != NULL) { + cur = cur->children; + continue; + } + break; +#ifdef LIBXML_DOCB_ENABLED + /* Not sure if we need those here. */ + case XML_DOCUMENT_NODE: + case XML_DOCB_DOCUMENT_NODE: +#endif + case XML_HTML_DOCUMENT_NODE: + if (cur != start) + return(cur); + return(xmlDocGetRootElement((xmlDocPtr) cur)); + default: + break; + } + +next_sibling: + if ((cur == NULL) || (cur == contextNode)) + return(NULL); + if (cur->next != NULL) { + cur = cur->next; + } else { + cur = cur->parent; + goto next_sibling; + } + } + } + return(NULL); +} + +/** + * xmlXPathNextDescendant: + * @ctxt: the XPath Parser context + * @cur: the current node in the traversal + * + * Traversal function for the "descendant" direction + * the descendant axis contains the descendants of the context node in document + * order; a descendant is a child or a child of a child and so on. + * + * Returns the next element following that axis + */ +xmlNodePtr +xmlXPathNextDescendant(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) { + if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL); + if (cur == NULL) { + if (ctxt->context->node == NULL) + return(NULL); + if ((ctxt->context->node->type == XML_ATTRIBUTE_NODE) || + (ctxt->context->node->type == XML_NAMESPACE_DECL)) + return(NULL); + + if (ctxt->context->node == (xmlNodePtr) ctxt->context->doc) + return(ctxt->context->doc->children); + return(ctxt->context->node->children); + } + + if (cur->children != NULL) { + /* + * Do not descend on entities declarations + */ + if (cur->children->type != XML_ENTITY_DECL) { + cur = cur->children; + /* + * Skip DTDs + */ + if (cur->type != XML_DTD_NODE) + return(cur); + } + } + + if (cur == ctxt->context->node) return(NULL); + + while (cur->next != NULL) { + cur = cur->next; + if ((cur->type != XML_ENTITY_DECL) && + (cur->type != XML_DTD_NODE)) + return(cur); + } + + do { + cur = cur->parent; + if (cur == NULL) break; + if (cur == ctxt->context->node) return(NULL); + if (cur->next != NULL) { + cur = cur->next; + return(cur); + } + } while (cur != NULL); + return(cur); +} + +/** + * xmlXPathNextDescendantOrSelf: + * @ctxt: the XPath Parser context + * @cur: the current node in the traversal + * + * Traversal function for the "descendant-or-self" direction + * the descendant-or-self axis contains the context node and the descendants + * of the context node in document order; thus the context node is the first + * node on the axis, and the first child of the context node is the second node + * on the axis + * + * Returns the next element following that axis + */ +xmlNodePtr +xmlXPathNextDescendantOrSelf(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) { + if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL); + if (cur == NULL) { + if (ctxt->context->node == NULL) + return(NULL); + if ((ctxt->context->node->type == XML_ATTRIBUTE_NODE) || + (ctxt->context->node->type == XML_NAMESPACE_DECL)) + return(NULL); + return(ctxt->context->node); + } + + return(xmlXPathNextDescendant(ctxt, cur)); +} + +/** + * xmlXPathNextParent: + * @ctxt: the XPath Parser context + * @cur: the current node in the traversal + * + * Traversal function for the "parent" direction + * The parent axis contains the parent of the context node, if there is one. + * + * Returns the next element following that axis + */ +xmlNodePtr +xmlXPathNextParent(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) { + if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL); + /* + * the parent of an attribute or namespace node is the element + * to which the attribute or namespace node is attached + * Namespace handling !!! + */ + if (cur == NULL) { + if (ctxt->context->node == NULL) return(NULL); + switch (ctxt->context->node->type) { + case XML_ELEMENT_NODE: + case XML_TEXT_NODE: + case XML_CDATA_SECTION_NODE: + case XML_ENTITY_REF_NODE: + case XML_ENTITY_NODE: + case XML_PI_NODE: + case XML_COMMENT_NODE: + case XML_NOTATION_NODE: + case XML_DTD_NODE: + case XML_ELEMENT_DECL: + case XML_ATTRIBUTE_DECL: + case XML_XINCLUDE_START: + case XML_XINCLUDE_END: + case XML_ENTITY_DECL: + if (ctxt->context->node->parent == NULL) + return((xmlNodePtr) ctxt->context->doc); + if ((ctxt->context->node->parent->type == XML_ELEMENT_NODE) && + ((ctxt->context->node->parent->name[0] == ' ') || + (xmlStrEqual(ctxt->context->node->parent->name, + BAD_CAST "fake node libxslt")))) + return(NULL); + return(ctxt->context->node->parent); + case XML_ATTRIBUTE_NODE: { + xmlAttrPtr att = (xmlAttrPtr) ctxt->context->node; + + return(att->parent); + } + case XML_DOCUMENT_NODE: + case XML_DOCUMENT_TYPE_NODE: + case XML_DOCUMENT_FRAG_NODE: + case XML_HTML_DOCUMENT_NODE: +#ifdef LIBXML_DOCB_ENABLED + case XML_DOCB_DOCUMENT_NODE: +#endif + return(NULL); + case XML_NAMESPACE_DECL: { + xmlNsPtr ns = (xmlNsPtr) ctxt->context->node; + + if ((ns->next != NULL) && + (ns->next->type != XML_NAMESPACE_DECL)) + return((xmlNodePtr) ns->next); + return(NULL); + } + } + } + return(NULL); +} + +/** + * xmlXPathNextAncestor: + * @ctxt: the XPath Parser context + * @cur: the current node in the traversal + * + * Traversal function for the "ancestor" direction + * the ancestor axis contains the ancestors of the context node; the ancestors + * of the context node consist of the parent of context node and the parent's + * parent and so on; the nodes are ordered in reverse document order; thus the + * parent is the first node on the axis, and the parent's parent is the second + * node on the axis + * + * Returns the next element following that axis + */ +xmlNodePtr +xmlXPathNextAncestor(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) { + if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL); + /* + * the parent of an attribute or namespace node is the element + * to which the attribute or namespace node is attached + * !!!!!!!!!!!!! + */ + if (cur == NULL) { + if (ctxt->context->node == NULL) return(NULL); + switch (ctxt->context->node->type) { + case XML_ELEMENT_NODE: + case XML_TEXT_NODE: + case XML_CDATA_SECTION_NODE: + case XML_ENTITY_REF_NODE: + case XML_ENTITY_NODE: + case XML_PI_NODE: + case XML_COMMENT_NODE: + case XML_DTD_NODE: + case XML_ELEMENT_DECL: + case XML_ATTRIBUTE_DECL: + case XML_ENTITY_DECL: + case XML_NOTATION_NODE: + case XML_XINCLUDE_START: + case XML_XINCLUDE_END: + if (ctxt->context->node->parent == NULL) + return((xmlNodePtr) ctxt->context->doc); + if ((ctxt->context->node->parent->type == XML_ELEMENT_NODE) && + ((ctxt->context->node->parent->name[0] == ' ') || + (xmlStrEqual(ctxt->context->node->parent->name, + BAD_CAST "fake node libxslt")))) + return(NULL); + return(ctxt->context->node->parent); + case XML_ATTRIBUTE_NODE: { + xmlAttrPtr tmp = (xmlAttrPtr) ctxt->context->node; + + return(tmp->parent); + } + case XML_DOCUMENT_NODE: + case XML_DOCUMENT_TYPE_NODE: + case XML_DOCUMENT_FRAG_NODE: + case XML_HTML_DOCUMENT_NODE: +#ifdef LIBXML_DOCB_ENABLED + case XML_DOCB_DOCUMENT_NODE: +#endif + return(NULL); + case XML_NAMESPACE_DECL: { + xmlNsPtr ns = (xmlNsPtr) ctxt->context->node; + + if ((ns->next != NULL) && + (ns->next->type != XML_NAMESPACE_DECL)) + return((xmlNodePtr) ns->next); + /* Bad, how did that namespace end up here ? */ + return(NULL); + } + } + return(NULL); + } + if (cur == ctxt->context->doc->children) + return((xmlNodePtr) ctxt->context->doc); + if (cur == (xmlNodePtr) ctxt->context->doc) + return(NULL); + switch (cur->type) { + case XML_ELEMENT_NODE: + case XML_TEXT_NODE: + case XML_CDATA_SECTION_NODE: + case XML_ENTITY_REF_NODE: + case XML_ENTITY_NODE: + case XML_PI_NODE: + case XML_COMMENT_NODE: + case XML_NOTATION_NODE: + case XML_DTD_NODE: + case XML_ELEMENT_DECL: + case XML_ATTRIBUTE_DECL: + case XML_ENTITY_DECL: + case XML_XINCLUDE_START: + case XML_XINCLUDE_END: + if (cur->parent == NULL) + return(NULL); + if ((cur->parent->type == XML_ELEMENT_NODE) && + ((cur->parent->name[0] == ' ') || + (xmlStrEqual(cur->parent->name, + BAD_CAST "fake node libxslt")))) + return(NULL); + return(cur->parent); + case XML_ATTRIBUTE_NODE: { + xmlAttrPtr att = (xmlAttrPtr) ctxt->context->node; + + return(att->parent); + } + case XML_NAMESPACE_DECL: { + xmlNsPtr ns = (xmlNsPtr) ctxt->context->node; + + if ((ns->next != NULL) && + (ns->next->type != XML_NAMESPACE_DECL)) + return((xmlNodePtr) ns->next); + /* Bad, how did that namespace end up here ? */ + return(NULL); + } + case XML_DOCUMENT_NODE: + case XML_DOCUMENT_TYPE_NODE: + case XML_DOCUMENT_FRAG_NODE: + case XML_HTML_DOCUMENT_NODE: +#ifdef LIBXML_DOCB_ENABLED + case XML_DOCB_DOCUMENT_NODE: +#endif + return(NULL); + } + return(NULL); +} + +/** + * xmlXPathNextAncestorOrSelf: + * @ctxt: the XPath Parser context + * @cur: the current node in the traversal + * + * Traversal function for the "ancestor-or-self" direction + * he ancestor-or-self axis contains the context node and ancestors of + * the context node in reverse document order; thus the context node is + * the first node on the axis, and the context node's parent the second; + * parent here is defined the same as with the parent axis. + * + * Returns the next element following that axis + */ +xmlNodePtr +xmlXPathNextAncestorOrSelf(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) { + if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL); + if (cur == NULL) + return(ctxt->context->node); + return(xmlXPathNextAncestor(ctxt, cur)); +} + +/** + * xmlXPathNextFollowingSibling: + * @ctxt: the XPath Parser context + * @cur: the current node in the traversal + * + * Traversal function for the "following-sibling" direction + * The following-sibling axis contains the following siblings of the context + * node in document order. + * + * Returns the next element following that axis + */ +xmlNodePtr +xmlXPathNextFollowingSibling(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) { + if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL); + if ((ctxt->context->node->type == XML_ATTRIBUTE_NODE) || + (ctxt->context->node->type == XML_NAMESPACE_DECL)) + return(NULL); + if (cur == (xmlNodePtr) ctxt->context->doc) + return(NULL); + if (cur == NULL) + return(ctxt->context->node->next); + return(cur->next); +} + +/** + * xmlXPathNextPrecedingSibling: + * @ctxt: the XPath Parser context + * @cur: the current node in the traversal + * + * Traversal function for the "preceding-sibling" direction + * The preceding-sibling axis contains the preceding siblings of the context + * node in reverse document order; the first preceding sibling is first on the + * axis; the sibling preceding that node is the second on the axis and so on. + * + * Returns the next element following that axis + */ +xmlNodePtr +xmlXPathNextPrecedingSibling(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) { + if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL); + if ((ctxt->context->node->type == XML_ATTRIBUTE_NODE) || + (ctxt->context->node->type == XML_NAMESPACE_DECL)) + return(NULL); + if (cur == (xmlNodePtr) ctxt->context->doc) + return(NULL); + if (cur == NULL) + return(ctxt->context->node->prev); + if ((cur->prev != NULL) && (cur->prev->type == XML_DTD_NODE)) { + cur = cur->prev; + if (cur == NULL) + return(ctxt->context->node->prev); + } + return(cur->prev); +} + +/** + * xmlXPathNextFollowing: + * @ctxt: the XPath Parser context + * @cur: the current node in the traversal + * + * Traversal function for the "following" direction + * The following axis contains all nodes in the same document as the context + * node that are after the context node in document order, excluding any + * descendants and excluding attribute nodes and namespace nodes; the nodes + * are ordered in document order + * + * Returns the next element following that axis + */ +xmlNodePtr +xmlXPathNextFollowing(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) { + if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL); + if (cur != NULL && cur->children != NULL) + return cur->children ; + if (cur == NULL) cur = ctxt->context->node; + if (cur == NULL) return(NULL) ; /* ERROR */ + if (cur->next != NULL) return(cur->next) ; + do { + cur = cur->parent; + if (cur == NULL) break; + if (cur == (xmlNodePtr) ctxt->context->doc) return(NULL); + if (cur->next != NULL) return(cur->next); + } while (cur != NULL); + return(cur); +} + +/* + * xmlXPathIsAncestor: + * @ancestor: the ancestor node + * @node: the current node + * + * Check that @ancestor is a @node's ancestor + * + * returns 1 if @ancestor is a @node's ancestor, 0 otherwise. + */ +static int +xmlXPathIsAncestor(xmlNodePtr ancestor, xmlNodePtr node) { + if ((ancestor == NULL) || (node == NULL)) return(0); + /* nodes need to be in the same document */ + if (ancestor->doc != node->doc) return(0); + /* avoid searching if ancestor or node is the root node */ + if (ancestor == (xmlNodePtr) node->doc) return(1); + if (node == (xmlNodePtr) ancestor->doc) return(0); + while (node->parent != NULL) { + if (node->parent == ancestor) + return(1); + node = node->parent; + } + return(0); +} + +/** + * xmlXPathNextPreceding: + * @ctxt: the XPath Parser context + * @cur: the current node in the traversal + * + * Traversal function for the "preceding" direction + * the preceding axis contains all nodes in the same document as the context + * node that are before the context node in document order, excluding any + * ancestors and excluding attribute nodes and namespace nodes; the nodes are + * ordered in reverse document order + * + * Returns the next element following that axis + */ +xmlNodePtr +xmlXPathNextPreceding(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) +{ + if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL); + if (cur == NULL) + cur = ctxt->context->node; + if (cur == NULL) + return (NULL); + if ((cur->prev != NULL) && (cur->prev->type == XML_DTD_NODE)) + cur = cur->prev; + do { + if (cur->prev != NULL) { + for (cur = cur->prev; cur->last != NULL; cur = cur->last) ; + return (cur); + } + + cur = cur->parent; + if (cur == NULL) + return (NULL); + if (cur == ctxt->context->doc->children) + return (NULL); + } while (xmlXPathIsAncestor(cur, ctxt->context->node)); + return (cur); +} + +/** + * xmlXPathNextPrecedingInternal: + * @ctxt: the XPath Parser context + * @cur: the current node in the traversal + * + * Traversal function for the "preceding" direction + * the preceding axis contains all nodes in the same document as the context + * node that are before the context node in document order, excluding any + * ancestors and excluding attribute nodes and namespace nodes; the nodes are + * ordered in reverse document order + * This is a faster implementation but internal only since it requires a + * state kept in the parser context: ctxt->ancestor. + * + * Returns the next element following that axis + */ +static xmlNodePtr +xmlXPathNextPrecedingInternal(xmlXPathParserContextPtr ctxt, + xmlNodePtr cur) +{ + if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL); + if (cur == NULL) { + cur = ctxt->context->node; + if (cur == NULL) + return (NULL); + if (cur->type == XML_NAMESPACE_DECL) + cur = (xmlNodePtr)((xmlNsPtr)cur)->next; + ctxt->ancestor = cur->parent; + } + if ((cur->prev != NULL) && (cur->prev->type == XML_DTD_NODE)) + cur = cur->prev; + while (cur->prev == NULL) { + cur = cur->parent; + if (cur == NULL) + return (NULL); + if (cur == ctxt->context->doc->children) + return (NULL); + if (cur != ctxt->ancestor) + return (cur); + ctxt->ancestor = cur->parent; + } + cur = cur->prev; + while (cur->last != NULL) + cur = cur->last; + return (cur); +} + +/** + * xmlXPathNextNamespace: + * @ctxt: the XPath Parser context + * @cur: the current attribute in the traversal + * + * Traversal function for the "namespace" direction + * the namespace axis contains the namespace nodes of the context node; + * the order of nodes on this axis is implementation-defined; the axis will + * be empty unless the context node is an element + * + * We keep the XML namespace node at the end of the list. + * + * Returns the next element following that axis + */ +xmlNodePtr +xmlXPathNextNamespace(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) { + if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL); + if (ctxt->context->node->type != XML_ELEMENT_NODE) return(NULL); + if (ctxt->context->tmpNsList == NULL && cur != (xmlNodePtr) xmlXPathXMLNamespace) { + if (ctxt->context->tmpNsList != NULL) + xmlFree(ctxt->context->tmpNsList); + ctxt->context->tmpNsList = + xmlGetNsList(ctxt->context->doc, ctxt->context->node); + ctxt->context->tmpNsNr = 0; + if (ctxt->context->tmpNsList != NULL) { + while (ctxt->context->tmpNsList[ctxt->context->tmpNsNr] != NULL) { + ctxt->context->tmpNsNr++; + } + } + return((xmlNodePtr) xmlXPathXMLNamespace); + } + if (ctxt->context->tmpNsNr > 0) { + return (xmlNodePtr)ctxt->context->tmpNsList[--ctxt->context->tmpNsNr]; + } else { + if (ctxt->context->tmpNsList != NULL) + xmlFree(ctxt->context->tmpNsList); + ctxt->context->tmpNsList = NULL; + return(NULL); + } +} + +/** + * xmlXPathNextAttribute: + * @ctxt: the XPath Parser context + * @cur: the current attribute in the traversal + * + * Traversal function for the "attribute" direction + * TODO: support DTD inherited default attributes + * + * Returns the next element following that axis + */ +xmlNodePtr +xmlXPathNextAttribute(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) { + if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL); + if (ctxt->context->node == NULL) + return(NULL); + if (ctxt->context->node->type != XML_ELEMENT_NODE) + return(NULL); + if (cur == NULL) { + if (ctxt->context->node == (xmlNodePtr) ctxt->context->doc) + return(NULL); + return((xmlNodePtr)ctxt->context->node->properties); + } + return((xmlNodePtr)cur->next); +} + +/************************************************************************ + * * + * NodeTest Functions * + * * + ************************************************************************/ + +#define IS_FUNCTION 200 + + +/************************************************************************ + * * + * Implicit tree core function library * + * * + ************************************************************************/ + +/** + * xmlXPathRoot: + * @ctxt: the XPath Parser context + * + * Initialize the context to the root of the document + */ +void +xmlXPathRoot(xmlXPathParserContextPtr ctxt) { + if ((ctxt == NULL) || (ctxt->context == NULL)) + return; + ctxt->context->node = (xmlNodePtr) ctxt->context->doc; + valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt->context, + ctxt->context->node)); +} + +/************************************************************************ + * * + * The explicit core function library * + *http://www.w3.org/Style/XSL/Group/1999/07/xpath-19990705.html#corelib * + * * + ************************************************************************/ + + +/** + * xmlXPathLastFunction: + * @ctxt: the XPath Parser context + * @nargs: the number of arguments + * + * Implement the last() XPath function + * number last() + * The last function returns the number of nodes in the context node list. + */ +void +xmlXPathLastFunction(xmlXPathParserContextPtr ctxt, int nargs) { + CHECK_ARITY(0); + if (ctxt->context->contextSize >= 0) { + valuePush(ctxt, + xmlXPathCacheNewFloat(ctxt->context, + (double) ctxt->context->contextSize)); +#ifdef DEBUG_EXPR + xmlGenericError(xmlGenericErrorContext, + "last() : %d\n", ctxt->context->contextSize); +#endif + } else { + XP_ERROR(XPATH_INVALID_CTXT_SIZE); + } +} + +/** + * xmlXPathPositionFunction: + * @ctxt: the XPath Parser context + * @nargs: the number of arguments + * + * Implement the position() XPath function + * number position() + * The position function returns the position of the context node in the + * context node list. The first position is 1, and so the last position + * will be equal to last(). + */ +void +xmlXPathPositionFunction(xmlXPathParserContextPtr ctxt, int nargs) { + CHECK_ARITY(0); + if (ctxt->context->proximityPosition >= 0) { + valuePush(ctxt, + xmlXPathCacheNewFloat(ctxt->context, + (double) ctxt->context->proximityPosition)); +#ifdef DEBUG_EXPR + xmlGenericError(xmlGenericErrorContext, "position() : %d\n", + ctxt->context->proximityPosition); +#endif + } else { + XP_ERROR(XPATH_INVALID_CTXT_POSITION); + } +} + +/** + * xmlXPathCountFunction: + * @ctxt: the XPath Parser context + * @nargs: the number of arguments + * + * Implement the count() XPath function + * number count(node-set) + */ +void +xmlXPathCountFunction(xmlXPathParserContextPtr ctxt, int nargs) { + xmlXPathObjectPtr cur; + + CHECK_ARITY(1); + if ((ctxt->value == NULL) || + ((ctxt->value->type != XPATH_NODESET) && + (ctxt->value->type != XPATH_XSLT_TREE))) + XP_ERROR(XPATH_INVALID_TYPE); + cur = valuePop(ctxt); + + if ((cur == NULL) || (cur->nodesetval == NULL)) + valuePush(ctxt, xmlXPathCacheNewFloat(ctxt->context, (double) 0)); + else if ((cur->type == XPATH_NODESET) || (cur->type == XPATH_XSLT_TREE)) { + valuePush(ctxt, xmlXPathCacheNewFloat(ctxt->context, + (double) cur->nodesetval->nodeNr)); + } else { + if ((cur->nodesetval->nodeNr != 1) || + (cur->nodesetval->nodeTab == NULL)) { + valuePush(ctxt, xmlXPathCacheNewFloat(ctxt->context, (double) 0)); + } else { + xmlNodePtr tmp; + int i = 0; + + tmp = cur->nodesetval->nodeTab[0]; + if (tmp != NULL) { + tmp = tmp->children; + while (tmp != NULL) { + tmp = tmp->next; + i++; + } + } + valuePush(ctxt, xmlXPathCacheNewFloat(ctxt->context, (double) i)); + } + } + xmlXPathReleaseObject(ctxt->context, cur); +} + +/** + * xmlXPathGetElementsByIds: + * @doc: the document + * @ids: a whitespace separated list of IDs + * + * Selects elements by their unique ID. + * + * Returns a node-set of selected elements. + */ +static xmlNodeSetPtr +xmlXPathGetElementsByIds (xmlDocPtr doc, const xmlChar *ids) { + xmlNodeSetPtr ret; + const xmlChar *cur = ids; + xmlChar *ID; + xmlAttrPtr attr; + xmlNodePtr elem = NULL; + + if (ids == NULL) return(NULL); + + ret = xmlXPathNodeSetCreate(NULL); + + while (IS_BLANK_CH(*cur)) cur++; + while (*cur != 0) { + while ((!IS_BLANK_CH(*cur)) && (*cur != 0)) + cur++; + + ID = xmlStrndup(ids, cur - ids); + if (ID != NULL) { + /* + * We used to check the fact that the value passed + * was an NCName, but this generated much troubles for + * me and Aleksey Sanin, people blatantly violated that + * constaint, like Visa3D spec. + * if (xmlValidateNCName(ID, 1) == 0) + */ + attr = xmlGetID(doc, ID); + if (attr != NULL) { + if (attr->type == XML_ATTRIBUTE_NODE) + elem = attr->parent; + else if (attr->type == XML_ELEMENT_NODE) + elem = (xmlNodePtr) attr; + else + elem = NULL; + if (elem != NULL) + xmlXPathNodeSetAdd(ret, elem); + } + xmlFree(ID); + } + + while (IS_BLANK_CH(*cur)) cur++; + ids = cur; + } + return(ret); +} + +/** + * xmlXPathIdFunction: + * @ctxt: the XPath Parser context + * @nargs: the number of arguments + * + * Implement the id() XPath function + * node-set id(object) + * The id function selects elements by their unique ID + * (see [5.2.1 Unique IDs]). When the argument to id is of type node-set, + * then the result is the union of the result of applying id to the + * string value of each of the nodes in the argument node-set. When the + * argument to id is of any other type, the argument is converted to a + * string as if by a call to the string function; the string is split + * into a whitespace-separated list of tokens (whitespace is any sequence + * of characters matching the production S); the result is a node-set + * containing the elements in the same document as the context node that + * have a unique ID equal to any of the tokens in the list. + */ +void +xmlXPathIdFunction(xmlXPathParserContextPtr ctxt, int nargs) { + xmlChar *tokens; + xmlNodeSetPtr ret; + xmlXPathObjectPtr obj; + + CHECK_ARITY(1); + obj = valuePop(ctxt); + if (obj == NULL) XP_ERROR(XPATH_INVALID_OPERAND); + if ((obj->type == XPATH_NODESET) || (obj->type == XPATH_XSLT_TREE)) { + xmlNodeSetPtr ns; + int i; + + ret = xmlXPathNodeSetCreate(NULL); + + if (obj->nodesetval != NULL) { + for (i = 0; i < obj->nodesetval->nodeNr; i++) { + tokens = + xmlXPathCastNodeToString(obj->nodesetval->nodeTab[i]); + ns = xmlXPathGetElementsByIds(ctxt->context->doc, tokens); + ret = xmlXPathNodeSetMerge(ret, ns); + xmlXPathFreeNodeSet(ns); + if (tokens != NULL) + xmlFree(tokens); + } + } + xmlXPathReleaseObject(ctxt->context, obj); + valuePush(ctxt, xmlXPathCacheWrapNodeSet(ctxt->context, ret)); + return; + } + obj = xmlXPathCacheConvertString(ctxt->context, obj); + ret = xmlXPathGetElementsByIds(ctxt->context->doc, obj->stringval); + valuePush(ctxt, xmlXPathCacheWrapNodeSet(ctxt->context, ret)); + xmlXPathReleaseObject(ctxt->context, obj); + return; +} + +/** + * xmlXPathLocalNameFunction: + * @ctxt: the XPath Parser context + * @nargs: the number of arguments + * + * Implement the local-name() XPath function + * string local-name(node-set?) + * The local-name function returns a string containing the local part + * of the name of the node in the argument node-set that is first in + * document order. If the node-set is empty or the first node has no + * name, an empty string is returned. If the argument is omitted it + * defaults to the context node. + */ +void +xmlXPathLocalNameFunction(xmlXPathParserContextPtr ctxt, int nargs) { + xmlXPathObjectPtr cur; + + if (ctxt == NULL) return; + + if (nargs == 0) { + valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt->context, + ctxt->context->node)); + nargs = 1; + } + + CHECK_ARITY(1); + if ((ctxt->value == NULL) || + ((ctxt->value->type != XPATH_NODESET) && + (ctxt->value->type != XPATH_XSLT_TREE))) + XP_ERROR(XPATH_INVALID_TYPE); + cur = valuePop(ctxt); + + if ((cur->nodesetval == NULL) || (cur->nodesetval->nodeNr == 0)) { + valuePush(ctxt, xmlXPathCacheNewCString(ctxt->context, "")); + } else { + int i = 0; /* Should be first in document order !!!!! */ + switch (cur->nodesetval->nodeTab[i]->type) { + case XML_ELEMENT_NODE: + case XML_ATTRIBUTE_NODE: + case XML_PI_NODE: + if (cur->nodesetval->nodeTab[i]->name[0] == ' ') + valuePush(ctxt, xmlXPathCacheNewCString(ctxt->context, "")); + else + valuePush(ctxt, + xmlXPathCacheNewString(ctxt->context, + cur->nodesetval->nodeTab[i]->name)); + break; + case XML_NAMESPACE_DECL: + valuePush(ctxt, xmlXPathCacheNewString(ctxt->context, + ((xmlNsPtr)cur->nodesetval->nodeTab[i])->prefix)); + break; + default: + valuePush(ctxt, xmlXPathCacheNewCString(ctxt->context, "")); + } + } + xmlXPathReleaseObject(ctxt->context, cur); +} + +/** + * xmlXPathNamespaceURIFunction: + * @ctxt: the XPath Parser context + * @nargs: the number of arguments + * + * Implement the namespace-uri() XPath function + * string namespace-uri(node-set?) + * The namespace-uri function returns a string containing the + * namespace URI of the expanded name of the node in the argument + * node-set that is first in document order. If the node-set is empty, + * the first node has no name, or the expanded name has no namespace + * URI, an empty string is returned. If the argument is omitted it + * defaults to the context node. + */ +void +xmlXPathNamespaceURIFunction(xmlXPathParserContextPtr ctxt, int nargs) { + xmlXPathObjectPtr cur; + + if (ctxt == NULL) return; + + if (nargs == 0) { + valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt->context, + ctxt->context->node)); + nargs = 1; + } + CHECK_ARITY(1); + if ((ctxt->value == NULL) || + ((ctxt->value->type != XPATH_NODESET) && + (ctxt->value->type != XPATH_XSLT_TREE))) + XP_ERROR(XPATH_INVALID_TYPE); + cur = valuePop(ctxt); + + if ((cur->nodesetval == NULL) || (cur->nodesetval->nodeNr == 0)) { + valuePush(ctxt, xmlXPathCacheNewCString(ctxt->context, "")); + } else { + int i = 0; /* Should be first in document order !!!!! */ + switch (cur->nodesetval->nodeTab[i]->type) { + case XML_ELEMENT_NODE: + case XML_ATTRIBUTE_NODE: + if (cur->nodesetval->nodeTab[i]->ns == NULL) + valuePush(ctxt, xmlXPathCacheNewCString(ctxt->context, "")); + else + valuePush(ctxt, xmlXPathCacheNewString(ctxt->context, + cur->nodesetval->nodeTab[i]->ns->href)); + break; + default: + valuePush(ctxt, xmlXPathCacheNewCString(ctxt->context, "")); + } + } + xmlXPathReleaseObject(ctxt->context, cur); +} + +/** + * xmlXPathNameFunction: + * @ctxt: the XPath Parser context + * @nargs: the number of arguments + * + * Implement the name() XPath function + * string name(node-set?) + * The name function returns a string containing a QName representing + * the name of the node in the argument node-set that is first in document + * order. The QName must represent the name with respect to the namespace + * declarations in effect on the node whose name is being represented. + * Typically, this will be the form in which the name occurred in the XML + * source. This need not be the case if there are namespace declarations + * in effect on the node that associate multiple prefixes with the same + * namespace. However, an implementation may include information about + * the original prefix in its representation of nodes; in this case, an + * implementation can ensure that the returned string is always the same + * as the QName used in the XML source. If the argument it omitted it + * defaults to the context node. + * Libxml keep the original prefix so the "real qualified name" used is + * returned. + */ +static void +xmlXPathNameFunction(xmlXPathParserContextPtr ctxt, int nargs) +{ + xmlXPathObjectPtr cur; + + if (nargs == 0) { + valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt->context, + ctxt->context->node)); + nargs = 1; + } + + CHECK_ARITY(1); + if ((ctxt->value == NULL) || + ((ctxt->value->type != XPATH_NODESET) && + (ctxt->value->type != XPATH_XSLT_TREE))) + XP_ERROR(XPATH_INVALID_TYPE); + cur = valuePop(ctxt); + + if ((cur->nodesetval == NULL) || (cur->nodesetval->nodeNr == 0)) { + valuePush(ctxt, xmlXPathCacheNewCString(ctxt->context, "")); + } else { + int i = 0; /* Should be first in document order !!!!! */ + + switch (cur->nodesetval->nodeTab[i]->type) { + case XML_ELEMENT_NODE: + case XML_ATTRIBUTE_NODE: + if (cur->nodesetval->nodeTab[i]->name[0] == ' ') + valuePush(ctxt, + xmlXPathCacheNewCString(ctxt->context, "")); + else if ((cur->nodesetval->nodeTab[i]->ns == NULL) || + (cur->nodesetval->nodeTab[i]->ns->prefix == NULL)) { + valuePush(ctxt, + xmlXPathCacheNewString(ctxt->context, + cur->nodesetval->nodeTab[i]->name)); + } else { + xmlChar *fullname; + + fullname = xmlBuildQName(cur->nodesetval->nodeTab[i]->name, + cur->nodesetval->nodeTab[i]->ns->prefix, + NULL, 0); + if (fullname == cur->nodesetval->nodeTab[i]->name) + fullname = xmlStrdup(cur->nodesetval->nodeTab[i]->name); + if (fullname == NULL) { + XP_ERROR(XPATH_MEMORY_ERROR); + } + valuePush(ctxt, xmlXPathCacheWrapString( + ctxt->context, fullname)); + } + break; + default: + valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt->context, + cur->nodesetval->nodeTab[i])); + xmlXPathLocalNameFunction(ctxt, 1); + } + } + xmlXPathReleaseObject(ctxt->context, cur); +} + + +/** + * xmlXPathStringFunction: + * @ctxt: the XPath Parser context + * @nargs: the number of arguments + * + * Implement the string() XPath function + * string string(object?) + * The string function converts an object to a string as follows: + * - A node-set is converted to a string by returning the value of + * the node in the node-set that is first in document order. + * If the node-set is empty, an empty string is returned. + * - A number is converted to a string as follows + * + NaN is converted to the string NaN + * + positive zero is converted to the string 0 + * + negative zero is converted to the string 0 + * + positive infinity is converted to the string Infinity + * + negative infinity is converted to the string -Infinity + * + if the number is an integer, the number is represented in + * decimal form as a Number with no decimal point and no leading + * zeros, preceded by a minus sign (-) if the number is negative + * + otherwise, the number is represented in decimal form as a + * Number including a decimal point with at least one digit + * before the decimal point and at least one digit after the + * decimal point, preceded by a minus sign (-) if the number + * is negative; there must be no leading zeros before the decimal + * point apart possibly from the one required digit immediately + * before the decimal point; beyond the one required digit + * after the decimal point there must be as many, but only as + * many, more digits as are needed to uniquely distinguish the + * number from all other IEEE 754 numeric values. + * - The boolean false value is converted to the string false. + * The boolean true value is converted to the string true. + * + * If the argument is omitted, it defaults to a node-set with the + * context node as its only member. + */ +void +xmlXPathStringFunction(xmlXPathParserContextPtr ctxt, int nargs) { + xmlXPathObjectPtr cur; + + if (ctxt == NULL) return; + if (nargs == 0) { + valuePush(ctxt, + xmlXPathCacheWrapString(ctxt->context, + xmlXPathCastNodeToString(ctxt->context->node))); + return; + } + + CHECK_ARITY(1); + cur = valuePop(ctxt); + if (cur == NULL) XP_ERROR(XPATH_INVALID_OPERAND); + valuePush(ctxt, xmlXPathCacheConvertString(ctxt->context, cur)); +} + +/** + * xmlXPathStringLengthFunction: + * @ctxt: the XPath Parser context + * @nargs: the number of arguments + * + * Implement the string-length() XPath function + * number string-length(string?) + * The string-length returns the number of characters in the string + * (see [3.6 Strings]). If the argument is omitted, it defaults to + * the context node converted to a string, in other words the value + * of the context node. + */ +void +xmlXPathStringLengthFunction(xmlXPathParserContextPtr ctxt, int nargs) { + xmlXPathObjectPtr cur; + + if (nargs == 0) { + if ((ctxt == NULL) || (ctxt->context == NULL)) + return; + if (ctxt->context->node == NULL) { + valuePush(ctxt, xmlXPathCacheNewFloat(ctxt->context, 0)); + } else { + xmlChar *content; + + content = xmlXPathCastNodeToString(ctxt->context->node); + valuePush(ctxt, xmlXPathCacheNewFloat(ctxt->context, + xmlUTF8Strlen(content))); + xmlFree(content); + } + return; + } + CHECK_ARITY(1); + CAST_TO_STRING; + CHECK_TYPE(XPATH_STRING); + cur = valuePop(ctxt); + valuePush(ctxt, xmlXPathCacheNewFloat(ctxt->context, + xmlUTF8Strlen(cur->stringval))); + xmlXPathReleaseObject(ctxt->context, cur); +} + +/** + * xmlXPathConcatFunction: + * @ctxt: the XPath Parser context + * @nargs: the number of arguments + * + * Implement the concat() XPath function + * string concat(string, string, string*) + * The concat function returns the concatenation of its arguments. + */ +void +xmlXPathConcatFunction(xmlXPathParserContextPtr ctxt, int nargs) { + xmlXPathObjectPtr cur, newobj; + xmlChar *tmp; + + if (ctxt == NULL) return; + if (nargs < 2) { + CHECK_ARITY(2); + } + + CAST_TO_STRING; + cur = valuePop(ctxt); + if ((cur == NULL) || (cur->type != XPATH_STRING)) { + xmlXPathReleaseObject(ctxt->context, cur); + return; + } + nargs--; + + while (nargs > 0) { + CAST_TO_STRING; + newobj = valuePop(ctxt); + if ((newobj == NULL) || (newobj->type != XPATH_STRING)) { + xmlXPathReleaseObject(ctxt->context, newobj); + xmlXPathReleaseObject(ctxt->context, cur); + XP_ERROR(XPATH_INVALID_TYPE); + } + tmp = xmlStrcat(newobj->stringval, cur->stringval); + newobj->stringval = cur->stringval; + cur->stringval = tmp; + xmlXPathReleaseObject(ctxt->context, newobj); + nargs--; + } + valuePush(ctxt, cur); +} + +/** + * xmlXPathContainsFunction: + * @ctxt: the XPath Parser context + * @nargs: the number of arguments + * + * Implement the contains() XPath function + * boolean contains(string, string) + * The contains function returns true if the first argument string + * contains the second argument string, and otherwise returns false. + */ +void +xmlXPathContainsFunction(xmlXPathParserContextPtr ctxt, int nargs) { + xmlXPathObjectPtr hay, needle; + + CHECK_ARITY(2); + CAST_TO_STRING; + CHECK_TYPE(XPATH_STRING); + needle = valuePop(ctxt); + CAST_TO_STRING; + hay = valuePop(ctxt); + + if ((hay == NULL) || (hay->type != XPATH_STRING)) { + xmlXPathReleaseObject(ctxt->context, hay); + xmlXPathReleaseObject(ctxt->context, needle); + XP_ERROR(XPATH_INVALID_TYPE); + } + if (xmlStrstr(hay->stringval, needle->stringval)) + valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt->context, 1)); + else + valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt->context, 0)); + xmlXPathReleaseObject(ctxt->context, hay); + xmlXPathReleaseObject(ctxt->context, needle); +} + +/** + * xmlXPathStartsWithFunction: + * @ctxt: the XPath Parser context + * @nargs: the number of arguments + * + * Implement the starts-with() XPath function + * boolean starts-with(string, string) + * The starts-with function returns true if the first argument string + * starts with the second argument string, and otherwise returns false. + */ +void +xmlXPathStartsWithFunction(xmlXPathParserContextPtr ctxt, int nargs) { + xmlXPathObjectPtr hay, needle; + int n; + + CHECK_ARITY(2); + CAST_TO_STRING; + CHECK_TYPE(XPATH_STRING); + needle = valuePop(ctxt); + CAST_TO_STRING; + hay = valuePop(ctxt); + + if ((hay == NULL) || (hay->type != XPATH_STRING)) { + xmlXPathReleaseObject(ctxt->context, hay); + xmlXPathReleaseObject(ctxt->context, needle); + XP_ERROR(XPATH_INVALID_TYPE); + } + n = xmlStrlen(needle->stringval); + if (xmlStrncmp(hay->stringval, needle->stringval, n)) + valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt->context, 0)); + else + valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt->context, 1)); + xmlXPathReleaseObject(ctxt->context, hay); + xmlXPathReleaseObject(ctxt->context, needle); +} + +/** + * xmlXPathSubstringFunction: + * @ctxt: the XPath Parser context + * @nargs: the number of arguments + * + * Implement the substring() XPath function + * string substring(string, number, number?) + * The substring function returns the substring of the first argument + * starting at the position specified in the second argument with + * length specified in the third argument. For example, + * substring("12345",2,3) returns "234". If the third argument is not + * specified, it returns the substring starting at the position specified + * in the second argument and continuing to the end of the string. For + * example, substring("12345",2) returns "2345". More precisely, each + * character in the string (see [3.6 Strings]) is considered to have a + * numeric position: the position of the first character is 1, the position + * of the second character is 2 and so on. The returned substring contains + * those characters for which the position of the character is greater than + * or equal to the second argument and, if the third argument is specified, + * less than the sum of the second and third arguments; the comparisons + * and addition used for the above follow the standard IEEE 754 rules. Thus: + * - substring("12345", 1.5, 2.6) returns "234" + * - substring("12345", 0, 3) returns "12" + * - substring("12345", 0 div 0, 3) returns "" + * - substring("12345", 1, 0 div 0) returns "" + * - substring("12345", -42, 1 div 0) returns "12345" + * - substring("12345", -1 div 0, 1 div 0) returns "" + */ +void +xmlXPathSubstringFunction(xmlXPathParserContextPtr ctxt, int nargs) { + xmlXPathObjectPtr str, start, len; + double le=0, in; + int i, l, m; + xmlChar *ret; + + if (nargs < 2) { + CHECK_ARITY(2); + } + if (nargs > 3) { + CHECK_ARITY(3); + } + /* + * take care of possible last (position) argument + */ + if (nargs == 3) { + CAST_TO_NUMBER; + CHECK_TYPE(XPATH_NUMBER); + len = valuePop(ctxt); + le = len->floatval; + xmlXPathReleaseObject(ctxt->context, len); + } + + CAST_TO_NUMBER; + CHECK_TYPE(XPATH_NUMBER); + start = valuePop(ctxt); + in = start->floatval; + xmlXPathReleaseObject(ctxt->context, start); + CAST_TO_STRING; + CHECK_TYPE(XPATH_STRING); + str = valuePop(ctxt); + m = xmlUTF8Strlen((const unsigned char *)str->stringval); + + /* + * If last pos not present, calculate last position + */ + if (nargs != 3) { + le = (double)m; + if (in < 1.0) + in = 1.0; + } + + /* Need to check for the special cases where either + * the index is NaN, the length is NaN, or both + * arguments are infinity (relying on Inf + -Inf = NaN) + */ + if (!xmlXPathIsNaN(in + le) && !xmlXPathIsInf(in)) { + /* + * To meet the requirements of the spec, the arguments + * must be converted to integer format before + * initial index calculations are done + * + * First we go to integer form, rounding up + * and checking for special cases + */ + i = (int) in; + if (((double)i)+0.5 <= in) i++; + + if (xmlXPathIsInf(le) == 1) { + l = m; + if (i < 1) + i = 1; + } + else if (xmlXPathIsInf(le) == -1 || le < 0.0) + l = 0; + else { + l = (int) le; + if (((double)l)+0.5 <= le) l++; + } + + /* Now we normalize inidices */ + i -= 1; + l += i; + if (i < 0) + i = 0; + if (l > m) + l = m; + + /* number of chars to copy */ + l -= i; + + ret = xmlUTF8Strsub(str->stringval, i, l); + } + else { + ret = NULL; + } + if (ret == NULL) + valuePush(ctxt, xmlXPathCacheNewCString(ctxt->context, "")); + else { + valuePush(ctxt, xmlXPathCacheNewString(ctxt->context, ret)); + xmlFree(ret); + } + xmlXPathReleaseObject(ctxt->context, str); +} + +/** + * xmlXPathSubstringBeforeFunction: + * @ctxt: the XPath Parser context + * @nargs: the number of arguments + * + * Implement the substring-before() XPath function + * string substring-before(string, string) + * The substring-before function returns the substring of the first + * argument string that precedes the first occurrence of the second + * argument string in the first argument string, or the empty string + * if the first argument string does not contain the second argument + * string. For example, substring-before("1999/04/01","/") returns 1999. + */ +void +xmlXPathSubstringBeforeFunction(xmlXPathParserContextPtr ctxt, int nargs) { + xmlXPathObjectPtr str; + xmlXPathObjectPtr find; + xmlBufferPtr target; + const xmlChar *point; + int offset; + + CHECK_ARITY(2); + CAST_TO_STRING; + find = valuePop(ctxt); + CAST_TO_STRING; + str = valuePop(ctxt); + + target = xmlBufferCreate(); + if (target) { + point = xmlStrstr(str->stringval, find->stringval); + if (point) { + offset = (int)(point - str->stringval); + xmlBufferAdd(target, str->stringval, offset); + } + valuePush(ctxt, xmlXPathCacheNewString(ctxt->context, + xmlBufferContent(target))); + xmlBufferFree(target); + } + xmlXPathReleaseObject(ctxt->context, str); + xmlXPathReleaseObject(ctxt->context, find); +} + +/** + * xmlXPathSubstringAfterFunction: + * @ctxt: the XPath Parser context + * @nargs: the number of arguments + * + * Implement the substring-after() XPath function + * string substring-after(string, string) + * The substring-after function returns the substring of the first + * argument string that follows the first occurrence of the second + * argument string in the first argument string, or the empty stringi + * if the first argument string does not contain the second argument + * string. For example, substring-after("1999/04/01","/") returns 04/01, + * and substring-after("1999/04/01","19") returns 99/04/01. + */ +void +xmlXPathSubstringAfterFunction(xmlXPathParserContextPtr ctxt, int nargs) { + xmlXPathObjectPtr str; + xmlXPathObjectPtr find; + xmlBufferPtr target; + const xmlChar *point; + int offset; + + CHECK_ARITY(2); + CAST_TO_STRING; + find = valuePop(ctxt); + CAST_TO_STRING; + str = valuePop(ctxt); + + target = xmlBufferCreate(); + if (target) { + point = xmlStrstr(str->stringval, find->stringval); + if (point) { + offset = (int)(point - str->stringval) + xmlStrlen(find->stringval); + xmlBufferAdd(target, &str->stringval[offset], + xmlStrlen(str->stringval) - offset); + } + valuePush(ctxt, xmlXPathCacheNewString(ctxt->context, + xmlBufferContent(target))); + xmlBufferFree(target); + } + xmlXPathReleaseObject(ctxt->context, str); + xmlXPathReleaseObject(ctxt->context, find); +} + +/** + * xmlXPathNormalizeFunction: + * @ctxt: the XPath Parser context + * @nargs: the number of arguments + * + * Implement the normalize-space() XPath function + * string normalize-space(string?) + * The normalize-space function returns the argument string with white + * space normalized by stripping leading and trailing whitespace + * and replacing sequences of whitespace characters by a single + * space. Whitespace characters are the same allowed by the S production + * in XML. If the argument is omitted, it defaults to the context + * node converted to a string, in other words the value of the context node. + */ +void +xmlXPathNormalizeFunction(xmlXPathParserContextPtr ctxt, int nargs) { + xmlXPathObjectPtr obj = NULL; + xmlChar *source = NULL; + xmlBufferPtr target; + xmlChar blank; + + if (ctxt == NULL) return; + if (nargs == 0) { + /* Use current context node */ + valuePush(ctxt, + xmlXPathCacheWrapString(ctxt->context, + xmlXPathCastNodeToString(ctxt->context->node))); + nargs = 1; + } + + CHECK_ARITY(1); + CAST_TO_STRING; + CHECK_TYPE(XPATH_STRING); + obj = valuePop(ctxt); + source = obj->stringval; + + target = xmlBufferCreate(); + if (target && source) { + + /* Skip leading whitespaces */ + while (IS_BLANK_CH(*source)) + source++; + + /* Collapse intermediate whitespaces, and skip trailing whitespaces */ + blank = 0; + while (*source) { + if (IS_BLANK_CH(*source)) { + blank = 0x20; + } else { + if (blank) { + xmlBufferAdd(target, &blank, 1); + blank = 0; + } + xmlBufferAdd(target, source, 1); + } + source++; + } + valuePush(ctxt, xmlXPathCacheNewString(ctxt->context, + xmlBufferContent(target))); + xmlBufferFree(target); + } + xmlXPathReleaseObject(ctxt->context, obj); +} + +/** + * xmlXPathTranslateFunction: + * @ctxt: the XPath Parser context + * @nargs: the number of arguments + * + * Implement the translate() XPath function + * string translate(string, string, string) + * The translate function returns the first argument string with + * occurrences of characters in the second argument string replaced + * by the character at the corresponding position in the third argument + * string. For example, translate("bar","abc","ABC") returns the string + * BAr. If there is a character in the second argument string with no + * character at a corresponding position in the third argument string + * (because the second argument string is longer than the third argument + * string), then occurrences of that character in the first argument + * string are removed. For example, translate("--aaa--","abc-","ABC") + * returns "AAA". If a character occurs more than once in second + * argument string, then the first occurrence determines the replacement + * character. If the third argument string is longer than the second + * argument string, then excess characters are ignored. + */ +void +xmlXPathTranslateFunction(xmlXPathParserContextPtr ctxt, int nargs) { + xmlXPathObjectPtr str; + xmlXPathObjectPtr from; + xmlXPathObjectPtr to; + xmlBufferPtr target; + int offset, max; + xmlChar ch; + const xmlChar *point; + xmlChar *cptr; + + CHECK_ARITY(3); + + CAST_TO_STRING; + to = valuePop(ctxt); + CAST_TO_STRING; + from = valuePop(ctxt); + CAST_TO_STRING; + str = valuePop(ctxt); + + target = xmlBufferCreate(); + if (target) { + max = xmlUTF8Strlen(to->stringval); + for (cptr = str->stringval; (ch=*cptr); ) { + offset = xmlUTF8Strloc(from->stringval, cptr); + if (offset >= 0) { + if (offset < max) { + point = xmlUTF8Strpos(to->stringval, offset); + if (point) + xmlBufferAdd(target, point, xmlUTF8Strsize(point, 1)); + } + } else + xmlBufferAdd(target, cptr, xmlUTF8Strsize(cptr, 1)); + + /* Step to next character in input */ + cptr++; + if ( ch & 0x80 ) { + /* if not simple ascii, verify proper format */ + if ( (ch & 0xc0) != 0xc0 ) { + xmlGenericError(xmlGenericErrorContext, + "xmlXPathTranslateFunction: Invalid UTF8 string\n"); + break; + } + /* then skip over remaining bytes for this char */ + while ( (ch <<= 1) & 0x80 ) + if ( (*cptr++ & 0xc0) != 0x80 ) { + xmlGenericError(xmlGenericErrorContext, + "xmlXPathTranslateFunction: Invalid UTF8 string\n"); + break; + } + if (ch & 0x80) /* must have had error encountered */ + break; + } + } + } + valuePush(ctxt, xmlXPathCacheNewString(ctxt->context, + xmlBufferContent(target))); + xmlBufferFree(target); + xmlXPathReleaseObject(ctxt->context, str); + xmlXPathReleaseObject(ctxt->context, from); + xmlXPathReleaseObject(ctxt->context, to); +} + +/** + * xmlXPathBooleanFunction: + * @ctxt: the XPath Parser context + * @nargs: the number of arguments + * + * Implement the boolean() XPath function + * boolean boolean(object) + * The boolean function converts its argument to a boolean as follows: + * - a number is true if and only if it is neither positive or + * negative zero nor NaN + * - a node-set is true if and only if it is non-empty + * - a string is true if and only if its length is non-zero + */ +void +xmlXPathBooleanFunction(xmlXPathParserContextPtr ctxt, int nargs) { + xmlXPathObjectPtr cur; + + CHECK_ARITY(1); + cur = valuePop(ctxt); + if (cur == NULL) XP_ERROR(XPATH_INVALID_OPERAND); + cur = xmlXPathCacheConvertBoolean(ctxt->context, cur); + valuePush(ctxt, cur); +} + +/** + * xmlXPathNotFunction: + * @ctxt: the XPath Parser context + * @nargs: the number of arguments + * + * Implement the not() XPath function + * boolean not(boolean) + * The not function returns true if its argument is false, + * and false otherwise. + */ +void +xmlXPathNotFunction(xmlXPathParserContextPtr ctxt, int nargs) { + CHECK_ARITY(1); + CAST_TO_BOOLEAN; + CHECK_TYPE(XPATH_BOOLEAN); + ctxt->value->boolval = ! ctxt->value->boolval; +} + +/** + * xmlXPathTrueFunction: + * @ctxt: the XPath Parser context + * @nargs: the number of arguments + * + * Implement the true() XPath function + * boolean true() + */ +void +xmlXPathTrueFunction(xmlXPathParserContextPtr ctxt, int nargs) { + CHECK_ARITY(0); + valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt->context, 1)); +} + +/** + * xmlXPathFalseFunction: + * @ctxt: the XPath Parser context + * @nargs: the number of arguments + * + * Implement the false() XPath function + * boolean false() + */ +void +xmlXPathFalseFunction(xmlXPathParserContextPtr ctxt, int nargs) { + CHECK_ARITY(0); + valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt->context, 0)); +} + +/** + * xmlXPathLangFunction: + * @ctxt: the XPath Parser context + * @nargs: the number of arguments + * + * Implement the lang() XPath function + * boolean lang(string) + * The lang function returns true or false depending on whether the + * language of the context node as specified by xml:lang attributes + * is the same as or is a sublanguage of the language specified by + * the argument string. The language of the context node is determined + * by the value of the xml:lang attribute on the context node, or, if + * the context node has no xml:lang attribute, by the value of the + * xml:lang attribute on the nearest ancestor of the context node that + * has an xml:lang attribute. If there is no such attribute, then lang + * returns false. If there is such an attribute, then lang returns + * true if the attribute value is equal to the argument ignoring case, + * or if there is some suffix starting with - such that the attribute + * value is equal to the argument ignoring that suffix of the attribute + * value and ignoring case. + */ +void +xmlXPathLangFunction(xmlXPathParserContextPtr ctxt, int nargs) { + xmlXPathObjectPtr val = NULL; + const xmlChar *theLang = NULL; + const xmlChar *lang; + int ret = 0; + int i; + + CHECK_ARITY(1); + CAST_TO_STRING; + CHECK_TYPE(XPATH_STRING); + val = valuePop(ctxt); + lang = val->stringval; + theLang = xmlNodeGetLang(ctxt->context->node); + if ((theLang != NULL) && (lang != NULL)) { + for (i = 0;lang[i] != 0;i++) + if (toupper(lang[i]) != toupper(theLang[i])) + goto not_equal; + if ((theLang[i] == 0) || (theLang[i] == '-')) + ret = 1; + } +not_equal: + if (theLang != NULL) + xmlFree((void *)theLang); + + xmlXPathReleaseObject(ctxt->context, val); + valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt->context, ret)); +} + +/** + * xmlXPathNumberFunction: + * @ctxt: the XPath Parser context + * @nargs: the number of arguments + * + * Implement the number() XPath function + * number number(object?) + */ +void +xmlXPathNumberFunction(xmlXPathParserContextPtr ctxt, int nargs) { + xmlXPathObjectPtr cur; + double res; + + if (ctxt == NULL) return; + if (nargs == 0) { + if (ctxt->context->node == NULL) { + valuePush(ctxt, xmlXPathCacheNewFloat(ctxt->context, 0.0)); + } else { + xmlChar* content = xmlNodeGetContent(ctxt->context->node); + + res = xmlXPathStringEvalNumber(content); + valuePush(ctxt, xmlXPathCacheNewFloat(ctxt->context, res)); + xmlFree(content); + } + return; + } + + CHECK_ARITY(1); + cur = valuePop(ctxt); + valuePush(ctxt, xmlXPathCacheConvertNumber(ctxt->context, cur)); +} + +/** + * xmlXPathSumFunction: + * @ctxt: the XPath Parser context + * @nargs: the number of arguments + * + * Implement the sum() XPath function + * number sum(node-set) + * The sum function returns the sum of the values of the nodes in + * the argument node-set. + */ +void +xmlXPathSumFunction(xmlXPathParserContextPtr ctxt, int nargs) { + xmlXPathObjectPtr cur; + int i; + double res = 0.0; + + CHECK_ARITY(1); + if ((ctxt->value == NULL) || + ((ctxt->value->type != XPATH_NODESET) && + (ctxt->value->type != XPATH_XSLT_TREE))) + XP_ERROR(XPATH_INVALID_TYPE); + cur = valuePop(ctxt); + + if ((cur->nodesetval != NULL) && (cur->nodesetval->nodeNr != 0)) { + for (i = 0; i < cur->nodesetval->nodeNr; i++) { + res += xmlXPathCastNodeToNumber(cur->nodesetval->nodeTab[i]); + } + } + valuePush(ctxt, xmlXPathCacheNewFloat(ctxt->context, res)); + xmlXPathReleaseObject(ctxt->context, cur); +} + +/* + * To assure working code on multiple platforms, we want to only depend + * upon the characteristic truncation of converting a floating point value + * to an integer. Unfortunately, because of the different storage sizes + * of our internal floating point value (double) and integer (int), we + * can't directly convert (see bug 301162). This macro is a messy + * 'workaround' + */ +#define XTRUNC(f, v) \ + f = fmod((v), INT_MAX); \ + f = (v) - (f) + (double)((int)(f)); + +/** + * xmlXPathFloorFunction: + * @ctxt: the XPath Parser context + * @nargs: the number of arguments + * + * Implement the floor() XPath function + * number floor(number) + * The floor function returns the largest (closest to positive infinity) + * number that is not greater than the argument and that is an integer. + */ +void +xmlXPathFloorFunction(xmlXPathParserContextPtr ctxt, int nargs) { + double f; + + CHECK_ARITY(1); + CAST_TO_NUMBER; + CHECK_TYPE(XPATH_NUMBER); + + XTRUNC(f, ctxt->value->floatval); + if (f != ctxt->value->floatval) { + if (ctxt->value->floatval > 0) + ctxt->value->floatval = f; + else + ctxt->value->floatval = f - 1; + } +} + +/** + * xmlXPathCeilingFunction: + * @ctxt: the XPath Parser context + * @nargs: the number of arguments + * + * Implement the ceiling() XPath function + * number ceiling(number) + * The ceiling function returns the smallest (closest to negative infinity) + * number that is not less than the argument and that is an integer. + */ +void +xmlXPathCeilingFunction(xmlXPathParserContextPtr ctxt, int nargs) { + double f; + + CHECK_ARITY(1); + CAST_TO_NUMBER; + CHECK_TYPE(XPATH_NUMBER); + +#if 0 + ctxt->value->floatval = ceil(ctxt->value->floatval); +#else + XTRUNC(f, ctxt->value->floatval); + if (f != ctxt->value->floatval) { + if (ctxt->value->floatval > 0) + ctxt->value->floatval = f + 1; + else { + if (ctxt->value->floatval < 0 && f == 0) + ctxt->value->floatval = xmlXPathNZERO; + else + ctxt->value->floatval = f; + } + + } +#endif +} + +/** + * xmlXPathRoundFunction: + * @ctxt: the XPath Parser context + * @nargs: the number of arguments + * + * Implement the round() XPath function + * number round(number) + * The round function returns the number that is closest to the + * argument and that is an integer. If there are two such numbers, + * then the one that is even is returned. + */ +void +xmlXPathRoundFunction(xmlXPathParserContextPtr ctxt, int nargs) { + double f; + + CHECK_ARITY(1); + CAST_TO_NUMBER; + CHECK_TYPE(XPATH_NUMBER); + + if ((xmlXPathIsNaN(ctxt->value->floatval)) || + (xmlXPathIsInf(ctxt->value->floatval) == 1) || + (xmlXPathIsInf(ctxt->value->floatval) == -1) || + (ctxt->value->floatval == 0.0)) + return; + + XTRUNC(f, ctxt->value->floatval); + if (ctxt->value->floatval < 0) { + if (ctxt->value->floatval < f - 0.5) + ctxt->value->floatval = f - 1; + else + ctxt->value->floatval = f; + if (ctxt->value->floatval == 0) + ctxt->value->floatval = xmlXPathNZERO; + } else { + if (ctxt->value->floatval < f + 0.5) + ctxt->value->floatval = f; + else + ctxt->value->floatval = f + 1; + } +} + +/************************************************************************ + * * + * The Parser * + * * + ************************************************************************/ + +/* + * a few forward declarations since we use a recursive call based + * implementation. + */ +static void xmlXPathCompileExpr(xmlXPathParserContextPtr ctxt, int sort); +static void xmlXPathCompPredicate(xmlXPathParserContextPtr ctxt, int filter); +static void xmlXPathCompLocationPath(xmlXPathParserContextPtr ctxt); +static void xmlXPathCompRelativeLocationPath(xmlXPathParserContextPtr ctxt); +static xmlChar * xmlXPathParseNameComplex(xmlXPathParserContextPtr ctxt, + int qualified); + +/** + * xmlXPathCurrentChar: + * @ctxt: the XPath parser context + * @cur: pointer to the beginning of the char + * @len: pointer to the length of the char read + * + * The current char value, if using UTF-8 this may actually span multiple + * bytes in the input buffer. + * + * Returns the current char value and its length + */ + +static int +xmlXPathCurrentChar(xmlXPathParserContextPtr ctxt, int *len) { + unsigned char c; + unsigned int val; + const xmlChar *cur; + + if (ctxt == NULL) + return(0); + cur = ctxt->cur; + + /* + * We are supposed to handle UTF8, check it's valid + * From rfc2044: encoding of the Unicode values on UTF-8: + * + * UCS-4 range (hex.) UTF-8 octet sequence (binary) + * 0000 0000-0000 007F 0xxxxxxx + * 0000 0080-0000 07FF 110xxxxx 10xxxxxx + * 0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx + * + * Check for the 0x110000 limit too + */ + c = *cur; + if (c & 0x80) { + if ((cur[1] & 0xc0) != 0x80) + goto encoding_error; + if ((c & 0xe0) == 0xe0) { + + if ((cur[2] & 0xc0) != 0x80) + goto encoding_error; + if ((c & 0xf0) == 0xf0) { + if (((c & 0xf8) != 0xf0) || + ((cur[3] & 0xc0) != 0x80)) + goto encoding_error; + /* 4-byte code */ + *len = 4; + val = (cur[0] & 0x7) << 18; + val |= (cur[1] & 0x3f) << 12; + val |= (cur[2] & 0x3f) << 6; + val |= cur[3] & 0x3f; + } else { + /* 3-byte code */ + *len = 3; + val = (cur[0] & 0xf) << 12; + val |= (cur[1] & 0x3f) << 6; + val |= cur[2] & 0x3f; + } + } else { + /* 2-byte code */ + *len = 2; + val = (cur[0] & 0x1f) << 6; + val |= cur[1] & 0x3f; + } + if (!IS_CHAR(val)) { + XP_ERROR0(XPATH_INVALID_CHAR_ERROR); + } + return(val); + } else { + /* 1-byte code */ + *len = 1; + return((int) *cur); + } +encoding_error: + /* + * If we detect an UTF8 error that probably means that the + * input encoding didn't get properly advertised in the + * declaration header. Report the error and switch the encoding + * to ISO-Latin-1 (if you don't like this policy, just declare the + * encoding !) + */ + *len = 0; + XP_ERROR0(XPATH_ENCODING_ERROR); +} + +/** + * xmlXPathParseNCName: + * @ctxt: the XPath Parser context + * + * parse an XML namespace non qualified name. + * + * [NS 3] NCName ::= (Letter | '_') (NCNameChar)* + * + * [NS 4] NCNameChar ::= Letter | Digit | '.' | '-' | '_' | + * CombiningChar | Extender + * + * Returns the namespace name or NULL + */ + +xmlChar * +xmlXPathParseNCName(xmlXPathParserContextPtr ctxt) { + const xmlChar *in; + xmlChar *ret; + int count = 0; + + if ((ctxt == NULL) || (ctxt->cur == NULL)) return(NULL); + /* + * Accelerator for simple ASCII names + */ + in = ctxt->cur; + if (((*in >= 0x61) && (*in <= 0x7A)) || + ((*in >= 0x41) && (*in <= 0x5A)) || + (*in == '_')) { + in++; + while (((*in >= 0x61) && (*in <= 0x7A)) || + ((*in >= 0x41) && (*in <= 0x5A)) || + ((*in >= 0x30) && (*in <= 0x39)) || + (*in == '_') || (*in == '.') || + (*in == '-')) + in++; + if ((*in == ' ') || (*in == '>') || (*in == '/') || + (*in == '[') || (*in == ']') || (*in == ':') || + (*in == '@') || (*in == '*')) { + count = in - ctxt->cur; + if (count == 0) + return(NULL); + ret = xmlStrndup(ctxt->cur, count); + ctxt->cur = in; + return(ret); + } + } + return(xmlXPathParseNameComplex(ctxt, 0)); +} + + +/** + * xmlXPathParseQName: + * @ctxt: the XPath Parser context + * @prefix: a xmlChar ** + * + * parse an XML qualified name + * + * [NS 5] QName ::= (Prefix ':')? LocalPart + * + * [NS 6] Prefix ::= NCName + * + * [NS 7] LocalPart ::= NCName + * + * Returns the function returns the local part, and prefix is updated + * to get the Prefix if any. + */ + +static xmlChar * +xmlXPathParseQName(xmlXPathParserContextPtr ctxt, xmlChar **prefix) { + xmlChar *ret = NULL; + + *prefix = NULL; + ret = xmlXPathParseNCName(ctxt); + if (CUR == ':') { + *prefix = ret; + NEXT; + ret = xmlXPathParseNCName(ctxt); + } + return(ret); +} + +/** + * xmlXPathParseName: + * @ctxt: the XPath Parser context + * + * parse an XML name + * + * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' | + * CombiningChar | Extender + * + * [5] Name ::= (Letter | '_' | ':') (NameChar)* + * + * Returns the namespace name or NULL + */ + +xmlChar * +xmlXPathParseName(xmlXPathParserContextPtr ctxt) { + const xmlChar *in; + xmlChar *ret; + int count = 0; + + if ((ctxt == NULL) || (ctxt->cur == NULL)) return(NULL); + /* + * Accelerator for simple ASCII names + */ + in = ctxt->cur; + if (((*in >= 0x61) && (*in <= 0x7A)) || + ((*in >= 0x41) && (*in <= 0x5A)) || + (*in == '_') || (*in == ':')) { + in++; + while (((*in >= 0x61) && (*in <= 0x7A)) || + ((*in >= 0x41) && (*in <= 0x5A)) || + ((*in >= 0x30) && (*in <= 0x39)) || + (*in == '_') || (*in == '-') || + (*in == ':') || (*in == '.')) + in++; + if ((*in > 0) && (*in < 0x80)) { + count = in - ctxt->cur; + ret = xmlStrndup(ctxt->cur, count); + ctxt->cur = in; + return(ret); + } + } + return(xmlXPathParseNameComplex(ctxt, 1)); +} + +static xmlChar * +xmlXPathParseNameComplex(xmlXPathParserContextPtr ctxt, int qualified) { + xmlChar buf[XML_MAX_NAMELEN + 5]; + int len = 0, l; + int c; + + /* + * Handler for more complex cases + */ + c = CUR_CHAR(l); + if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */ + (c == '[') || (c == ']') || (c == '@') || /* accelerators */ + (c == '*') || /* accelerators */ + (!IS_LETTER(c) && (c != '_') && + ((qualified) && (c != ':')))) { + return(NULL); + } + + while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */ + ((IS_LETTER(c)) || (IS_DIGIT(c)) || + (c == '.') || (c == '-') || + (c == '_') || ((qualified) && (c == ':')) || + (IS_COMBINING(c)) || + (IS_EXTENDER(c)))) { + COPY_BUF(l,buf,len,c); + NEXTL(l); + c = CUR_CHAR(l); + if (len >= XML_MAX_NAMELEN) { + /* + * Okay someone managed to make a huge name, so he's ready to pay + * for the processing speed. + */ + xmlChar *buffer; + int max = len * 2; + + buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar)); + if (buffer == NULL) { + XP_ERRORNULL(XPATH_MEMORY_ERROR); + } + memcpy(buffer, buf, len); + while ((IS_LETTER(c)) || (IS_DIGIT(c)) || /* test bigname.xml */ + (c == '.') || (c == '-') || + (c == '_') || ((qualified) && (c == ':')) || + (IS_COMBINING(c)) || + (IS_EXTENDER(c))) { + if (len + 10 > max) { + max *= 2; + buffer = (xmlChar *) xmlRealloc(buffer, + max * sizeof(xmlChar)); + if (buffer == NULL) { + XP_ERRORNULL(XPATH_MEMORY_ERROR); + } + } + COPY_BUF(l,buffer,len,c); + NEXTL(l); + c = CUR_CHAR(l); + } + buffer[len] = 0; + return(buffer); + } + } + if (len == 0) + return(NULL); + return(xmlStrndup(buf, len)); +} + +#define MAX_FRAC 20 + +/* + * These are used as divisors for the fractional part of a number. + * Since the table includes 1.0 (representing '0' fractional digits), + * it must be dimensioned at MAX_FRAC+1 (bug 133921) + */ +static double my_pow10[MAX_FRAC+1] = { + 1.0, 10.0, 100.0, 1000.0, 10000.0, + 100000.0, 1000000.0, 10000000.0, 100000000.0, 1000000000.0, + 10000000000.0, 100000000000.0, 1000000000000.0, 10000000000000.0, + 100000000000000.0, + 1000000000000000.0, 10000000000000000.0, 100000000000000000.0, + 1000000000000000000.0, 10000000000000000000.0, 100000000000000000000.0 +}; + +/** + * xmlXPathStringEvalNumber: + * @str: A string to scan + * + * [30a] Float ::= Number ('e' Digits?)? + * + * [30] Number ::= Digits ('.' Digits?)? + * | '.' Digits + * [31] Digits ::= [0-9]+ + * + * Compile a Number in the string + * In complement of the Number expression, this function also handles + * negative values : '-' Number. + * + * Returns the double value. + */ +double +xmlXPathStringEvalNumber(const xmlChar *str) { + const xmlChar *cur = str; + double ret; + int ok = 0; + int isneg = 0; + int exponent = 0; + int is_exponent_negative = 0; +#ifdef __GNUC__ + unsigned long tmp = 0; + double temp; +#endif + if (cur == NULL) return(0); + while (IS_BLANK_CH(*cur)) cur++; + if ((*cur != '.') && ((*cur < '0') || (*cur > '9')) && (*cur != '-')) { + return(xmlXPathNAN); + } + if (*cur == '-') { + isneg = 1; + cur++; + } + +#ifdef __GNUC__ + /* + * tmp/temp is a workaround against a gcc compiler bug + * http://veillard.com/gcc.bug + */ + ret = 0; + while ((*cur >= '0') && (*cur <= '9')) { + ret = ret * 10; + tmp = (*cur - '0'); + ok = 1; + cur++; + temp = (double) tmp; + ret = ret + temp; + } +#else + ret = 0; + while ((*cur >= '0') && (*cur <= '9')) { + ret = ret * 10 + (*cur - '0'); + ok = 1; + cur++; + } +#endif + + if (*cur == '.') { + int v, frac = 0; + double fraction = 0; + + cur++; + if (((*cur < '0') || (*cur > '9')) && (!ok)) { + return(xmlXPathNAN); + } + while (((*cur >= '0') && (*cur <= '9')) && (frac < MAX_FRAC)) { + v = (*cur - '0'); + fraction = fraction * 10 + v; + frac = frac + 1; + cur++; + } + fraction /= my_pow10[frac]; + ret = ret + fraction; + while ((*cur >= '0') && (*cur <= '9')) + cur++; + } + if ((*cur == 'e') || (*cur == 'E')) { + cur++; + if (*cur == '-') { + is_exponent_negative = 1; + cur++; + } else if (*cur == '+') { + cur++; + } + while ((*cur >= '0') && (*cur <= '9')) { + exponent = exponent * 10 + (*cur - '0'); + cur++; + } + } + while (IS_BLANK_CH(*cur)) cur++; + if (*cur != 0) return(xmlXPathNAN); + if (isneg) ret = -ret; + if (is_exponent_negative) exponent = -exponent; + ret *= pow(10.0, (double)exponent); + return(ret); +} + +/** + * xmlXPathCompNumber: + * @ctxt: the XPath Parser context + * + * [30] Number ::= Digits ('.' Digits?)? + * | '.' Digits + * [31] Digits ::= [0-9]+ + * + * Compile a Number, then push it on the stack + * + */ +static void +xmlXPathCompNumber(xmlXPathParserContextPtr ctxt) +{ + double ret = 0.0; + double mult = 1; + int ok = 0; + int exponent = 0; + int is_exponent_negative = 0; +#ifdef __GNUC__ + unsigned long tmp = 0; + double temp; +#endif + + CHECK_ERROR; + if ((CUR != '.') && ((CUR < '0') || (CUR > '9'))) { + XP_ERROR(XPATH_NUMBER_ERROR); + } +#ifdef __GNUC__ + /* + * tmp/temp is a workaround against a gcc compiler bug + * http://veillard.com/gcc.bug + */ + ret = 0; + while ((CUR >= '0') && (CUR <= '9')) { + ret = ret * 10; + tmp = (CUR - '0'); + ok = 1; + NEXT; + temp = (double) tmp; + ret = ret + temp; + } +#else + ret = 0; + while ((CUR >= '0') && (CUR <= '9')) { + ret = ret * 10 + (CUR - '0'); + ok = 1; + NEXT; + } +#endif + if (CUR == '.') { + NEXT; + if (((CUR < '0') || (CUR > '9')) && (!ok)) { + XP_ERROR(XPATH_NUMBER_ERROR); + } + while ((CUR >= '0') && (CUR <= '9')) { + mult /= 10; + ret = ret + (CUR - '0') * mult; + NEXT; + } + } + if ((CUR == 'e') || (CUR == 'E')) { + NEXT; + if (CUR == '-') { + is_exponent_negative = 1; + NEXT; + } else if (CUR == '+') { + NEXT; + } + while ((CUR >= '0') && (CUR <= '9')) { + exponent = exponent * 10 + (CUR - '0'); + NEXT; + } + if (is_exponent_negative) + exponent = -exponent; + ret *= pow(10.0, (double) exponent); + } + PUSH_LONG_EXPR(XPATH_OP_VALUE, XPATH_NUMBER, 0, 0, + xmlXPathCacheNewFloat(ctxt->context, ret), NULL); +} + +/** + * xmlXPathParseLiteral: + * @ctxt: the XPath Parser context + * + * Parse a Literal + * + * [29] Literal ::= '"' [^"]* '"' + * | "'" [^']* "'" + * + * Returns the value found or NULL in case of error + */ +static xmlChar * +xmlXPathParseLiteral(xmlXPathParserContextPtr ctxt) { + const xmlChar *q; + xmlChar *ret = NULL; + + if (CUR == '"') { + NEXT; + q = CUR_PTR; + while ((IS_CHAR_CH(CUR)) && (CUR != '"')) + NEXT; + if (!IS_CHAR_CH(CUR)) { + XP_ERRORNULL(XPATH_UNFINISHED_LITERAL_ERROR); + } else { + ret = xmlStrndup(q, CUR_PTR - q); + NEXT; + } + } else if (CUR == '\'') { + NEXT; + q = CUR_PTR; + while ((IS_CHAR_CH(CUR)) && (CUR != '\'')) + NEXT; + if (!IS_CHAR_CH(CUR)) { + XP_ERRORNULL(XPATH_UNFINISHED_LITERAL_ERROR); + } else { + ret = xmlStrndup(q, CUR_PTR - q); + NEXT; + } + } else { + XP_ERRORNULL(XPATH_START_LITERAL_ERROR); + } + return(ret); +} + +/** + * xmlXPathCompLiteral: + * @ctxt: the XPath Parser context + * + * Parse a Literal and push it on the stack. + * + * [29] Literal ::= '"' [^"]* '"' + * | "'" [^']* "'" + * + * TODO: xmlXPathCompLiteral memory allocation could be improved. + */ +static void +xmlXPathCompLiteral(xmlXPathParserContextPtr ctxt) { + const xmlChar *q; + xmlChar *ret = NULL; + + if (CUR == '"') { + NEXT; + q = CUR_PTR; + while ((IS_CHAR_CH(CUR)) && (CUR != '"')) + NEXT; + if (!IS_CHAR_CH(CUR)) { + XP_ERROR(XPATH_UNFINISHED_LITERAL_ERROR); + } else { + ret = xmlStrndup(q, CUR_PTR - q); + NEXT; + } + } else if (CUR == '\'') { + NEXT; + q = CUR_PTR; + while ((IS_CHAR_CH(CUR)) && (CUR != '\'')) + NEXT; + if (!IS_CHAR_CH(CUR)) { + XP_ERROR(XPATH_UNFINISHED_LITERAL_ERROR); + } else { + ret = xmlStrndup(q, CUR_PTR - q); + NEXT; + } + } else { + XP_ERROR(XPATH_START_LITERAL_ERROR); + } + if (ret == NULL) return; + PUSH_LONG_EXPR(XPATH_OP_VALUE, XPATH_STRING, 0, 0, + xmlXPathCacheNewString(ctxt->context, ret), NULL); + xmlFree(ret); +} + +/** + * xmlXPathCompVariableReference: + * @ctxt: the XPath Parser context + * + * Parse a VariableReference, evaluate it and push it on the stack. + * + * The variable bindings consist of a mapping from variable names + * to variable values. The value of a variable is an object, which can be + * of any of the types that are possible for the value of an expression, + * and may also be of additional types not specified here. + * + * Early evaluation is possible since: + * The variable bindings [...] used to evaluate a subexpression are + * always the same as those used to evaluate the containing expression. + * + * [36] VariableReference ::= '$' QName + */ +static void +xmlXPathCompVariableReference(xmlXPathParserContextPtr ctxt) { + xmlChar *name; + xmlChar *prefix; + + SKIP_BLANKS; + if (CUR != '$') { + XP_ERROR(XPATH_VARIABLE_REF_ERROR); + } + NEXT; + name = xmlXPathParseQName(ctxt, &prefix); + if (name == NULL) { + XP_ERROR(XPATH_VARIABLE_REF_ERROR); + } + ctxt->comp->last = -1; + PUSH_LONG_EXPR(XPATH_OP_VARIABLE, 0, 0, 0, + name, prefix); + SKIP_BLANKS; + if ((ctxt->context != NULL) && (ctxt->context->flags & XML_XPATH_NOVAR)) { + XP_ERROR(XPATH_UNDEF_VARIABLE_ERROR); + } +} + +/** + * xmlXPathIsNodeType: + * @name: a name string + * + * Is the name given a NodeType one. + * + * [38] NodeType ::= 'comment' + * | 'text' + * | 'processing-instruction' + * | 'node' + * + * Returns 1 if true 0 otherwise + */ +int +xmlXPathIsNodeType(const xmlChar *name) { + if (name == NULL) + return(0); + + if (xmlStrEqual(name, BAD_CAST "node")) + return(1); + if (xmlStrEqual(name, BAD_CAST "text")) + return(1); + if (xmlStrEqual(name, BAD_CAST "comment")) + return(1); + if (xmlStrEqual(name, BAD_CAST "processing-instruction")) + return(1); + return(0); +} + +/** + * xmlXPathCompFunctionCall: + * @ctxt: the XPath Parser context + * + * [16] FunctionCall ::= FunctionName '(' ( Argument ( ',' Argument)*)? ')' + * [17] Argument ::= Expr + * + * Compile a function call, the evaluation of all arguments are + * pushed on the stack + */ +static void +xmlXPathCompFunctionCall(xmlXPathParserContextPtr ctxt) { + xmlChar *name; + xmlChar *prefix; + int nbargs = 0; + int sort = 1; + + name = xmlXPathParseQName(ctxt, &prefix); + if (name == NULL) { + XP_ERROR(XPATH_EXPR_ERROR); + } + SKIP_BLANKS; +#ifdef DEBUG_EXPR + if (prefix == NULL) + xmlGenericError(xmlGenericErrorContext, "Calling function %s\n", + name); + else + xmlGenericError(xmlGenericErrorContext, "Calling function %s:%s\n", + prefix, name); +#endif + + if (CUR != '(') { + XP_ERROR(XPATH_EXPR_ERROR); + } + NEXT; + SKIP_BLANKS; + + /* + * Optimization for count(): we don't need the node-set to be sorted. + */ + if ((prefix == NULL) && (name[0] == 'c') && + xmlStrEqual(name, BAD_CAST "count")) + { + sort = 0; + } + ctxt->comp->last = -1; + if (CUR != ')') { + while (CUR != 0) { + int op1 = ctxt->comp->last; + ctxt->comp->last = -1; + xmlXPathCompileExpr(ctxt, sort); + CHECK_ERROR; + PUSH_BINARY_EXPR(XPATH_OP_ARG, op1, ctxt->comp->last, 0, 0); + nbargs++; + if (CUR == ')') break; + if (CUR != ',') { + XP_ERROR(XPATH_EXPR_ERROR); + } + NEXT; + SKIP_BLANKS; + } + } + PUSH_LONG_EXPR(XPATH_OP_FUNCTION, nbargs, 0, 0, + name, prefix); + NEXT; + SKIP_BLANKS; +} + +/** + * xmlXPathCompPrimaryExpr: + * @ctxt: the XPath Parser context + * + * [15] PrimaryExpr ::= VariableReference + * | '(' Expr ')' + * | Literal + * | Number + * | FunctionCall + * + * Compile a primary expression. + */ +static void +xmlXPathCompPrimaryExpr(xmlXPathParserContextPtr ctxt) { + SKIP_BLANKS; + if (CUR == '$') xmlXPathCompVariableReference(ctxt); + else if (CUR == '(') { + NEXT; + SKIP_BLANKS; + xmlXPathCompileExpr(ctxt, 1); + CHECK_ERROR; + if (CUR != ')') { + XP_ERROR(XPATH_EXPR_ERROR); + } + NEXT; + SKIP_BLANKS; + } else if (IS_ASCII_DIGIT(CUR) || (CUR == '.' && IS_ASCII_DIGIT(NXT(1)))) { + xmlXPathCompNumber(ctxt); + } else if ((CUR == '\'') || (CUR == '"')) { + xmlXPathCompLiteral(ctxt); + } else { + xmlXPathCompFunctionCall(ctxt); + } + SKIP_BLANKS; +} + +/** + * xmlXPathCompFilterExpr: + * @ctxt: the XPath Parser context + * + * [20] FilterExpr ::= PrimaryExpr + * | FilterExpr Predicate + * + * Compile a filter expression. + * Square brackets are used to filter expressions in the same way that + * they are used in location paths. It is an error if the expression to + * be filtered does not evaluate to a node-set. The context node list + * used for evaluating the expression in square brackets is the node-set + * to be filtered listed in document order. + */ + +static void +xmlXPathCompFilterExpr(xmlXPathParserContextPtr ctxt) { + xmlXPathCompPrimaryExpr(ctxt); + CHECK_ERROR; + SKIP_BLANKS; + + while (CUR == '[') { + xmlXPathCompPredicate(ctxt, 1); + SKIP_BLANKS; + } + + +} + +/** + * xmlXPathScanName: + * @ctxt: the XPath Parser context + * + * Trickery: parse an XML name but without consuming the input flow + * Needed to avoid insanity in the parser state. + * + * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' | + * CombiningChar | Extender + * + * [5] Name ::= (Letter | '_' | ':') (NameChar)* + * + * [6] Names ::= Name (S Name)* + * + * Returns the Name parsed or NULL + */ + +static xmlChar * +xmlXPathScanName(xmlXPathParserContextPtr ctxt) { + int len = 0, l; + int c; + const xmlChar *cur; + xmlChar *ret; + + cur = ctxt->cur; + + c = CUR_CHAR(l); + if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */ + (!IS_LETTER(c) && (c != '_') && + (c != ':'))) { + return(NULL); + } + + while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */ + ((IS_LETTER(c)) || (IS_DIGIT(c)) || + (c == '.') || (c == '-') || + (c == '_') || (c == ':') || + (IS_COMBINING(c)) || + (IS_EXTENDER(c)))) { + len += l; + NEXTL(l); + c = CUR_CHAR(l); + } + ret = xmlStrndup(cur, ctxt->cur - cur); + ctxt->cur = cur; + return(ret); +} + +/** + * xmlXPathCompPathExpr: + * @ctxt: the XPath Parser context + * + * [19] PathExpr ::= LocationPath + * | FilterExpr + * | FilterExpr '/' RelativeLocationPath + * | FilterExpr '//' RelativeLocationPath + * + * Compile a path expression. + * The / operator and // operators combine an arbitrary expression + * and a relative location path. It is an error if the expression + * does not evaluate to a node-set. + * The / operator does composition in the same way as when / is + * used in a location path. As in location paths, // is short for + * /descendant-or-self::node()/. + */ + +static void +xmlXPathCompPathExpr(xmlXPathParserContextPtr ctxt) { + int lc = 1; /* Should we branch to LocationPath ? */ + xmlChar *name = NULL; /* we may have to preparse a name to find out */ + + SKIP_BLANKS; + if ((CUR == '$') || (CUR == '(') || + (IS_ASCII_DIGIT(CUR)) || + (CUR == '\'') || (CUR == '"') || + (CUR == '.' && IS_ASCII_DIGIT(NXT(1)))) { + lc = 0; + } else if (CUR == '*') { + /* relative or absolute location path */ + lc = 1; + } else if (CUR == '/') { + /* relative or absolute location path */ + lc = 1; + } else if (CUR == '@') { + /* relative abbreviated attribute location path */ + lc = 1; + } else if (CUR == '.') { + /* relative abbreviated attribute location path */ + lc = 1; + } else { + /* + * Problem is finding if we have a name here whether it's: + * - a nodetype + * - a function call in which case it's followed by '(' + * - an axis in which case it's followed by ':' + * - a element name + * We do an a priori analysis here rather than having to + * maintain parsed token content through the recursive function + * calls. This looks uglier but makes the code easier to + * read/write/debug. + */ + SKIP_BLANKS; + name = xmlXPathScanName(ctxt); + if ((name != NULL) && (xmlStrstr(name, (xmlChar *) "::") != NULL)) { +#ifdef DEBUG_STEP + xmlGenericError(xmlGenericErrorContext, + "PathExpr: Axis\n"); +#endif + lc = 1; + xmlFree(name); + } else if (name != NULL) { + int len =xmlStrlen(name); + + + while (NXT(len) != 0) { + if (NXT(len) == '/') { + /* element name */ +#ifdef DEBUG_STEP + xmlGenericError(xmlGenericErrorContext, + "PathExpr: AbbrRelLocation\n"); +#endif + lc = 1; + break; + } else if (IS_BLANK_CH(NXT(len))) { + /* ignore blanks */ + ; + } else if (NXT(len) == ':') { +#ifdef DEBUG_STEP + xmlGenericError(xmlGenericErrorContext, + "PathExpr: AbbrRelLocation\n"); +#endif + lc = 1; + break; + } else if ((NXT(len) == '(')) { + /* Note Type or Function */ + if (xmlXPathIsNodeType(name)) { +#ifdef DEBUG_STEP + xmlGenericError(xmlGenericErrorContext, + "PathExpr: Type search\n"); +#endif + lc = 1; + } else { +#ifdef DEBUG_STEP + xmlGenericError(xmlGenericErrorContext, + "PathExpr: function call\n"); +#endif + lc = 0; + } + break; + } else if ((NXT(len) == '[')) { + /* element name */ +#ifdef DEBUG_STEP + xmlGenericError(xmlGenericErrorContext, + "PathExpr: AbbrRelLocation\n"); +#endif + lc = 1; + break; + } else if ((NXT(len) == '<') || (NXT(len) == '>') || + (NXT(len) == '=')) { + lc = 1; + break; + } else { + lc = 1; + break; + } + len++; + } + if (NXT(len) == 0) { +#ifdef DEBUG_STEP + xmlGenericError(xmlGenericErrorContext, + "PathExpr: AbbrRelLocation\n"); +#endif + /* element name */ + lc = 1; + } + xmlFree(name); + } else { + /* make sure all cases are covered explicitly */ + XP_ERROR(XPATH_EXPR_ERROR); + } + } + + if (lc) { + if (CUR == '/') { + PUSH_LEAVE_EXPR(XPATH_OP_ROOT, 0, 0); + } else { + PUSH_LEAVE_EXPR(XPATH_OP_NODE, 0, 0); + } + xmlXPathCompLocationPath(ctxt); + } else { + xmlXPathCompFilterExpr(ctxt); + CHECK_ERROR; + if ((CUR == '/') && (NXT(1) == '/')) { + SKIP(2); + SKIP_BLANKS; + + PUSH_LONG_EXPR(XPATH_OP_COLLECT, AXIS_DESCENDANT_OR_SELF, + NODE_TEST_TYPE, NODE_TYPE_NODE, NULL, NULL); + PUSH_UNARY_EXPR(XPATH_OP_RESET, ctxt->comp->last, 1, 0); + + xmlXPathCompRelativeLocationPath(ctxt); + } else if (CUR == '/') { + xmlXPathCompRelativeLocationPath(ctxt); + } + } + SKIP_BLANKS; +} + +/** + * xmlXPathCompUnionExpr: + * @ctxt: the XPath Parser context + * + * [18] UnionExpr ::= PathExpr + * | UnionExpr '|' PathExpr + * + * Compile an union expression. + */ + +static void +xmlXPathCompUnionExpr(xmlXPathParserContextPtr ctxt) { + xmlXPathCompPathExpr(ctxt); + CHECK_ERROR; + SKIP_BLANKS; + while (CUR == '|') { + int op1 = ctxt->comp->last; + PUSH_LEAVE_EXPR(XPATH_OP_NODE, 0, 0); + + NEXT; + SKIP_BLANKS; + xmlXPathCompPathExpr(ctxt); + + PUSH_BINARY_EXPR(XPATH_OP_UNION, op1, ctxt->comp->last, 0, 0); + + SKIP_BLANKS; + } +} + +/** + * xmlXPathCompUnaryExpr: + * @ctxt: the XPath Parser context + * + * [27] UnaryExpr ::= UnionExpr + * | '-' UnaryExpr + * + * Compile an unary expression. + */ + +static void +xmlXPathCompUnaryExpr(xmlXPathParserContextPtr ctxt) { + int minus = 0; + int found = 0; + + SKIP_BLANKS; + while (CUR == '-') { + minus = 1 - minus; + found = 1; + NEXT; + SKIP_BLANKS; + } + + xmlXPathCompUnionExpr(ctxt); + CHECK_ERROR; + if (found) { + if (minus) + PUSH_UNARY_EXPR(XPATH_OP_PLUS, ctxt->comp->last, 2, 0); + else + PUSH_UNARY_EXPR(XPATH_OP_PLUS, ctxt->comp->last, 3, 0); + } +} + +/** + * xmlXPathCompMultiplicativeExpr: + * @ctxt: the XPath Parser context + * + * [26] MultiplicativeExpr ::= UnaryExpr + * | MultiplicativeExpr MultiplyOperator UnaryExpr + * | MultiplicativeExpr 'div' UnaryExpr + * | MultiplicativeExpr 'mod' UnaryExpr + * [34] MultiplyOperator ::= '*' + * + * Compile an Additive expression. + */ + +static void +xmlXPathCompMultiplicativeExpr(xmlXPathParserContextPtr ctxt) { + xmlXPathCompUnaryExpr(ctxt); + CHECK_ERROR; + SKIP_BLANKS; + while ((CUR == '*') || + ((CUR == 'd') && (NXT(1) == 'i') && (NXT(2) == 'v')) || + ((CUR == 'm') && (NXT(1) == 'o') && (NXT(2) == 'd'))) { + int op = -1; + int op1 = ctxt->comp->last; + + if (CUR == '*') { + op = 0; + NEXT; + } else if (CUR == 'd') { + op = 1; + SKIP(3); + } else if (CUR == 'm') { + op = 2; + SKIP(3); + } + SKIP_BLANKS; + xmlXPathCompUnaryExpr(ctxt); + CHECK_ERROR; + PUSH_BINARY_EXPR(XPATH_OP_MULT, op1, ctxt->comp->last, op, 0); + SKIP_BLANKS; + } +} + +/** + * xmlXPathCompAdditiveExpr: + * @ctxt: the XPath Parser context + * + * [25] AdditiveExpr ::= MultiplicativeExpr + * | AdditiveExpr '+' MultiplicativeExpr + * | AdditiveExpr '-' MultiplicativeExpr + * + * Compile an Additive expression. + */ + +static void +xmlXPathCompAdditiveExpr(xmlXPathParserContextPtr ctxt) { + + xmlXPathCompMultiplicativeExpr(ctxt); + CHECK_ERROR; + SKIP_BLANKS; + while ((CUR == '+') || (CUR == '-')) { + int plus; + int op1 = ctxt->comp->last; + + if (CUR == '+') plus = 1; + else plus = 0; + NEXT; + SKIP_BLANKS; + xmlXPathCompMultiplicativeExpr(ctxt); + CHECK_ERROR; + PUSH_BINARY_EXPR(XPATH_OP_PLUS, op1, ctxt->comp->last, plus, 0); + SKIP_BLANKS; + } +} + +/** + * xmlXPathCompRelationalExpr: + * @ctxt: the XPath Parser context + * + * [24] RelationalExpr ::= AdditiveExpr + * | RelationalExpr '<' AdditiveExpr + * | RelationalExpr '>' AdditiveExpr + * | RelationalExpr '<=' AdditiveExpr + * | RelationalExpr '>=' AdditiveExpr + * + * A <= B > C is allowed ? Answer from James, yes with + * (AdditiveExpr <= AdditiveExpr) > AdditiveExpr + * which is basically what got implemented. + * + * Compile a Relational expression, then push the result + * on the stack + */ + +static void +xmlXPathCompRelationalExpr(xmlXPathParserContextPtr ctxt) { + xmlXPathCompAdditiveExpr(ctxt); + CHECK_ERROR; + SKIP_BLANKS; + while ((CUR == '<') || + (CUR == '>') || + ((CUR == '<') && (NXT(1) == '=')) || + ((CUR == '>') && (NXT(1) == '='))) { + int inf, strict; + int op1 = ctxt->comp->last; + + if (CUR == '<') inf = 1; + else inf = 0; + if (NXT(1) == '=') strict = 0; + else strict = 1; + NEXT; + if (!strict) NEXT; + SKIP_BLANKS; + xmlXPathCompAdditiveExpr(ctxt); + CHECK_ERROR; + PUSH_BINARY_EXPR(XPATH_OP_CMP, op1, ctxt->comp->last, inf, strict); + SKIP_BLANKS; + } +} + +/** + * xmlXPathCompEqualityExpr: + * @ctxt: the XPath Parser context + * + * [23] EqualityExpr ::= RelationalExpr + * | EqualityExpr '=' RelationalExpr + * | EqualityExpr '!=' RelationalExpr + * + * A != B != C is allowed ? Answer from James, yes with + * (RelationalExpr = RelationalExpr) = RelationalExpr + * (RelationalExpr != RelationalExpr) != RelationalExpr + * which is basically what got implemented. + * + * Compile an Equality expression. + * + */ +static void +xmlXPathCompEqualityExpr(xmlXPathParserContextPtr ctxt) { + xmlXPathCompRelationalExpr(ctxt); + CHECK_ERROR; + SKIP_BLANKS; + while ((CUR == '=') || ((CUR == '!') && (NXT(1) == '='))) { + int eq; + int op1 = ctxt->comp->last; + + if (CUR == '=') eq = 1; + else eq = 0; + NEXT; + if (!eq) NEXT; + SKIP_BLANKS; + xmlXPathCompRelationalExpr(ctxt); + CHECK_ERROR; + PUSH_BINARY_EXPR(XPATH_OP_EQUAL, op1, ctxt->comp->last, eq, 0); + SKIP_BLANKS; + } +} + +/** + * xmlXPathCompAndExpr: + * @ctxt: the XPath Parser context + * + * [22] AndExpr ::= EqualityExpr + * | AndExpr 'and' EqualityExpr + * + * Compile an AND expression. + * + */ +static void +xmlXPathCompAndExpr(xmlXPathParserContextPtr ctxt) { + xmlXPathCompEqualityExpr(ctxt); + CHECK_ERROR; + SKIP_BLANKS; + while ((CUR == 'a') && (NXT(1) == 'n') && (NXT(2) == 'd')) { + int op1 = ctxt->comp->last; + SKIP(3); + SKIP_BLANKS; + xmlXPathCompEqualityExpr(ctxt); + CHECK_ERROR; + PUSH_BINARY_EXPR(XPATH_OP_AND, op1, ctxt->comp->last, 0, 0); + SKIP_BLANKS; + } +} + +/** + * xmlXPathCompileExpr: + * @ctxt: the XPath Parser context + * + * [14] Expr ::= OrExpr + * [21] OrExpr ::= AndExpr + * | OrExpr 'or' AndExpr + * + * Parse and compile an expression + */ +static void +xmlXPathCompileExpr(xmlXPathParserContextPtr ctxt, int sort) { + xmlXPathCompAndExpr(ctxt); + CHECK_ERROR; + SKIP_BLANKS; + while ((CUR == 'o') && (NXT(1) == 'r')) { + int op1 = ctxt->comp->last; + SKIP(2); + SKIP_BLANKS; + xmlXPathCompAndExpr(ctxt); + CHECK_ERROR; + PUSH_BINARY_EXPR(XPATH_OP_OR, op1, ctxt->comp->last, 0, 0); + op1 = ctxt->comp->nbStep; + SKIP_BLANKS; + } + if ((sort) && (ctxt->comp->steps[ctxt->comp->last].op != XPATH_OP_VALUE)) { + /* more ops could be optimized too */ + /* + * This is the main place to eliminate sorting for + * operations which don't require a sorted node-set. + * E.g. count(). + */ + PUSH_UNARY_EXPR(XPATH_OP_SORT, ctxt->comp->last , 0, 0); + } +} + +/** + * xmlXPathCompPredicate: + * @ctxt: the XPath Parser context + * @filter: act as a filter + * + * [8] Predicate ::= '[' PredicateExpr ']' + * [9] PredicateExpr ::= Expr + * + * Compile a predicate expression + */ +static void +xmlXPathCompPredicate(xmlXPathParserContextPtr ctxt, int filter) { + int op1 = ctxt->comp->last; + + SKIP_BLANKS; + if (CUR != '[') { + XP_ERROR(XPATH_INVALID_PREDICATE_ERROR); + } + NEXT; + SKIP_BLANKS; + + ctxt->comp->last = -1; + /* + * This call to xmlXPathCompileExpr() will deactivate sorting + * of the predicate result. + * TODO: Sorting is still activated for filters, since I'm not + * sure if needed. Normally sorting should not be needed, since + * a filter can only diminish the number of items in a sequence, + * but won't change its order; so if the initial sequence is sorted, + * subsequent sorting is not needed. + */ + if (! filter) + xmlXPathCompileExpr(ctxt, 0); + else + xmlXPathCompileExpr(ctxt, 1); + CHECK_ERROR; + + if (CUR != ']') { + XP_ERROR(XPATH_INVALID_PREDICATE_ERROR); + } + + if (filter) + PUSH_BINARY_EXPR(XPATH_OP_FILTER, op1, ctxt->comp->last, 0, 0); + else + PUSH_BINARY_EXPR(XPATH_OP_PREDICATE, op1, ctxt->comp->last, 0, 0); + + NEXT; + SKIP_BLANKS; +} + +/** + * xmlXPathCompNodeTest: + * @ctxt: the XPath Parser context + * @test: pointer to a xmlXPathTestVal + * @type: pointer to a xmlXPathTypeVal + * @prefix: placeholder for a possible name prefix + * + * [7] NodeTest ::= NameTest + * | NodeType '(' ')' + * | 'processing-instruction' '(' Literal ')' + * + * [37] NameTest ::= '*' + * | NCName ':' '*' + * | QName + * [38] NodeType ::= 'comment' + * | 'text' + * | 'processing-instruction' + * | 'node' + * + * Returns the name found and updates @test, @type and @prefix appropriately + */ +static xmlChar * +xmlXPathCompNodeTest(xmlXPathParserContextPtr ctxt, xmlXPathTestVal *test, + xmlXPathTypeVal *type, const xmlChar **prefix, + xmlChar *name) { + int blanks; + + if ((test == NULL) || (type == NULL) || (prefix == NULL)) { + STRANGE; + return(NULL); + } + *type = (xmlXPathTypeVal) 0; + *test = (xmlXPathTestVal) 0; + *prefix = NULL; + SKIP_BLANKS; + + if ((name == NULL) && (CUR == '*')) { + /* + * All elements + */ + NEXT; + *test = NODE_TEST_ALL; + return(NULL); + } + + if (name == NULL) + name = xmlXPathParseNCName(ctxt); + if (name == NULL) { + XP_ERRORNULL(XPATH_EXPR_ERROR); + } + + blanks = IS_BLANK_CH(CUR); + SKIP_BLANKS; + if (CUR == '(') { + NEXT; + /* + * NodeType or PI search + */ + if (xmlStrEqual(name, BAD_CAST "comment")) + *type = NODE_TYPE_COMMENT; + else if (xmlStrEqual(name, BAD_CAST "node")) + *type = NODE_TYPE_NODE; + else if (xmlStrEqual(name, BAD_CAST "processing-instruction")) + *type = NODE_TYPE_PI; + else if (xmlStrEqual(name, BAD_CAST "text")) + *type = NODE_TYPE_TEXT; + else { + if (name != NULL) + xmlFree(name); + XP_ERRORNULL(XPATH_EXPR_ERROR); + } + + *test = NODE_TEST_TYPE; + + SKIP_BLANKS; + if (*type == NODE_TYPE_PI) { + /* + * Specific case: search a PI by name. + */ + if (name != NULL) + xmlFree(name); + name = NULL; + if (CUR != ')') { + name = xmlXPathParseLiteral(ctxt); + CHECK_ERROR NULL; + *test = NODE_TEST_PI; + SKIP_BLANKS; + } + } + if (CUR != ')') { + if (name != NULL) + xmlFree(name); + XP_ERRORNULL(XPATH_UNCLOSED_ERROR); + } + NEXT; + return(name); + } + *test = NODE_TEST_NAME; + if ((!blanks) && (CUR == ':')) { + NEXT; + + /* + * Since currently the parser context don't have a + * namespace list associated: + * The namespace name for this prefix can be computed + * only at evaluation time. The compilation is done + * outside of any context. + */ +#if 0 + *prefix = xmlXPathNsLookup(ctxt->context, name); + if (name != NULL) + xmlFree(name); + if (*prefix == NULL) { + XP_ERROR0(XPATH_UNDEF_PREFIX_ERROR); + } +#else + *prefix = name; +#endif + + if (CUR == '*') { + /* + * All elements + */ + NEXT; + *test = NODE_TEST_ALL; + return(NULL); + } + + name = xmlXPathParseNCName(ctxt); + if (name == NULL) { + XP_ERRORNULL(XPATH_EXPR_ERROR); + } + } + return(name); +} + +/** + * xmlXPathIsAxisName: + * @name: a preparsed name token + * + * [6] AxisName ::= 'ancestor' + * | 'ancestor-or-self' + * | 'attribute' + * | 'child' + * | 'descendant' + * | 'descendant-or-self' + * | 'following' + * | 'following-sibling' + * | 'namespace' + * | 'parent' + * | 'preceding' + * | 'preceding-sibling' + * | 'self' + * + * Returns the axis or 0 + */ +static xmlXPathAxisVal +xmlXPathIsAxisName(const xmlChar *name) { + xmlXPathAxisVal ret = (xmlXPathAxisVal) 0; + switch (name[0]) { + case 'a': + if (xmlStrEqual(name, BAD_CAST "ancestor")) + ret = AXIS_ANCESTOR; + if (xmlStrEqual(name, BAD_CAST "ancestor-or-self")) + ret = AXIS_ANCESTOR_OR_SELF; + if (xmlStrEqual(name, BAD_CAST "attribute")) + ret = AXIS_ATTRIBUTE; + break; + case 'c': + if (xmlStrEqual(name, BAD_CAST "child")) + ret = AXIS_CHILD; + break; + case 'd': + if (xmlStrEqual(name, BAD_CAST "descendant")) + ret = AXIS_DESCENDANT; + if (xmlStrEqual(name, BAD_CAST "descendant-or-self")) + ret = AXIS_DESCENDANT_OR_SELF; + break; + case 'f': + if (xmlStrEqual(name, BAD_CAST "following")) + ret = AXIS_FOLLOWING; + if (xmlStrEqual(name, BAD_CAST "following-sibling")) + ret = AXIS_FOLLOWING_SIBLING; + break; + case 'n': + if (xmlStrEqual(name, BAD_CAST "namespace")) + ret = AXIS_NAMESPACE; + break; + case 'p': + if (xmlStrEqual(name, BAD_CAST "parent")) + ret = AXIS_PARENT; + if (xmlStrEqual(name, BAD_CAST "preceding")) + ret = AXIS_PRECEDING; + if (xmlStrEqual(name, BAD_CAST "preceding-sibling")) + ret = AXIS_PRECEDING_SIBLING; + break; + case 's': + if (xmlStrEqual(name, BAD_CAST "self")) + ret = AXIS_SELF; + break; + } + return(ret); +} + +/** + * xmlXPathCompStep: + * @ctxt: the XPath Parser context + * + * [4] Step ::= AxisSpecifier NodeTest Predicate* + * | AbbreviatedStep + * + * [12] AbbreviatedStep ::= '.' | '..' + * + * [5] AxisSpecifier ::= AxisName '::' + * | AbbreviatedAxisSpecifier + * + * [13] AbbreviatedAxisSpecifier ::= '@'? + * + * Modified for XPtr range support as: + * + * [4xptr] Step ::= AxisSpecifier NodeTest Predicate* + * | AbbreviatedStep + * | 'range-to' '(' Expr ')' Predicate* + * + * Compile one step in a Location Path + * A location step of . is short for self::node(). This is + * particularly useful in conjunction with //. For example, the + * location path .//para is short for + * self::node()/descendant-or-self::node()/child::para + * and so will select all para descendant elements of the context + * node. + * Similarly, a location step of .. is short for parent::node(). + * For example, ../title is short for parent::node()/child::title + * and so will select the title children of the parent of the context + * node. + */ +static void +xmlXPathCompStep(xmlXPathParserContextPtr ctxt) { +#ifdef LIBXML_XPTR_ENABLED + int rangeto = 0; + int op2 = -1; +#endif + + SKIP_BLANKS; + if ((CUR == '.') && (NXT(1) == '.')) { + SKIP(2); + SKIP_BLANKS; + PUSH_LONG_EXPR(XPATH_OP_COLLECT, AXIS_PARENT, + NODE_TEST_TYPE, NODE_TYPE_NODE, NULL, NULL); + } else if (CUR == '.') { + NEXT; + SKIP_BLANKS; + } else { + xmlChar *name = NULL; + const xmlChar *prefix = NULL; + xmlXPathTestVal test = (xmlXPathTestVal) 0; + xmlXPathAxisVal axis = (xmlXPathAxisVal) 0; + xmlXPathTypeVal type = (xmlXPathTypeVal) 0; + int op1; + + /* + * The modification needed for XPointer change to the production + */ +#ifdef LIBXML_XPTR_ENABLED + if (ctxt->xptr) { + name = xmlXPathParseNCName(ctxt); + if ((name != NULL) && (xmlStrEqual(name, BAD_CAST "range-to"))) { + op2 = ctxt->comp->last; + xmlFree(name); + SKIP_BLANKS; + if (CUR != '(') { + XP_ERROR(XPATH_EXPR_ERROR); + } + NEXT; + SKIP_BLANKS; + + xmlXPathCompileExpr(ctxt, 1); + /* PUSH_BINARY_EXPR(XPATH_OP_RANGETO, op2, ctxt->comp->last, 0, 0); */ + CHECK_ERROR; + + SKIP_BLANKS; + if (CUR != ')') { + XP_ERROR(XPATH_EXPR_ERROR); + } + NEXT; + rangeto = 1; + goto eval_predicates; + } + } +#endif + if (CUR == '*') { + axis = AXIS_CHILD; + } else { + if (name == NULL) + name = xmlXPathParseNCName(ctxt); + if (name != NULL) { + axis = xmlXPathIsAxisName(name); + if (axis != 0) { + SKIP_BLANKS; + if ((CUR == ':') && (NXT(1) == ':')) { + SKIP(2); + xmlFree(name); + name = NULL; + } else { + /* an element name can conflict with an axis one :-\ */ + axis = AXIS_CHILD; + } + } else { + axis = AXIS_CHILD; + } + } else if (CUR == '@') { + NEXT; + axis = AXIS_ATTRIBUTE; + } else { + axis = AXIS_CHILD; + } + } + + CHECK_ERROR; + + name = xmlXPathCompNodeTest(ctxt, &test, &type, &prefix, name); + if (test == 0) + return; + + if ((prefix != NULL) && (ctxt->context != NULL) && + (ctxt->context->flags & XML_XPATH_CHECKNS)) { + if (xmlXPathNsLookup(ctxt->context, prefix) == NULL) { + xmlXPathErr(ctxt, XPATH_UNDEF_PREFIX_ERROR); + } + } +#ifdef DEBUG_STEP + xmlGenericError(xmlGenericErrorContext, + "Basis : computing new set\n"); +#endif + +#ifdef DEBUG_STEP + xmlGenericError(xmlGenericErrorContext, "Basis : "); + if (ctxt->value == NULL) + xmlGenericError(xmlGenericErrorContext, "no value\n"); + else if (ctxt->value->nodesetval == NULL) + xmlGenericError(xmlGenericErrorContext, "Empty\n"); + else + xmlGenericErrorContextNodeSet(stdout, ctxt->value->nodesetval); +#endif + +#ifdef LIBXML_XPTR_ENABLED +eval_predicates: +#endif + op1 = ctxt->comp->last; + ctxt->comp->last = -1; + + SKIP_BLANKS; + while (CUR == '[') { + xmlXPathCompPredicate(ctxt, 0); + } + +#ifdef LIBXML_XPTR_ENABLED + if (rangeto) { + PUSH_BINARY_EXPR(XPATH_OP_RANGETO, op2, op1, 0, 0); + } else +#endif + PUSH_FULL_EXPR(XPATH_OP_COLLECT, op1, ctxt->comp->last, axis, + test, type, (void *)prefix, (void *)name); + + } +#ifdef DEBUG_STEP + xmlGenericError(xmlGenericErrorContext, "Step : "); + if (ctxt->value == NULL) + xmlGenericError(xmlGenericErrorContext, "no value\n"); + else if (ctxt->value->nodesetval == NULL) + xmlGenericError(xmlGenericErrorContext, "Empty\n"); + else + xmlGenericErrorContextNodeSet(xmlGenericErrorContext, + ctxt->value->nodesetval); +#endif +} + +/** + * xmlXPathCompRelativeLocationPath: + * @ctxt: the XPath Parser context + * + * [3] RelativeLocationPath ::= Step + * | RelativeLocationPath '/' Step + * | AbbreviatedRelativeLocationPath + * [11] AbbreviatedRelativeLocationPath ::= RelativeLocationPath '//' Step + * + * Compile a relative location path. + */ +static void +xmlXPathCompRelativeLocationPath +(xmlXPathParserContextPtr ctxt) { + SKIP_BLANKS; + if ((CUR == '/') && (NXT(1) == '/')) { + SKIP(2); + SKIP_BLANKS; + PUSH_LONG_EXPR(XPATH_OP_COLLECT, AXIS_DESCENDANT_OR_SELF, + NODE_TEST_TYPE, NODE_TYPE_NODE, NULL, NULL); + } else if (CUR == '/') { + NEXT; + SKIP_BLANKS; + } + xmlXPathCompStep(ctxt); + SKIP_BLANKS; + while (CUR == '/') { + if ((CUR == '/') && (NXT(1) == '/')) { + SKIP(2); + SKIP_BLANKS; + PUSH_LONG_EXPR(XPATH_OP_COLLECT, AXIS_DESCENDANT_OR_SELF, + NODE_TEST_TYPE, NODE_TYPE_NODE, NULL, NULL); + xmlXPathCompStep(ctxt); + } else if (CUR == '/') { + NEXT; + SKIP_BLANKS; + xmlXPathCompStep(ctxt); + } + SKIP_BLANKS; + } +} + +/** + * xmlXPathCompLocationPath: + * @ctxt: the XPath Parser context + * + * [1] LocationPath ::= RelativeLocationPath + * | AbsoluteLocationPath + * [2] AbsoluteLocationPath ::= '/' RelativeLocationPath? + * | AbbreviatedAbsoluteLocationPath + * [10] AbbreviatedAbsoluteLocationPath ::= + * '//' RelativeLocationPath + * + * Compile a location path + * + * // is short for /descendant-or-self::node()/. For example, + * //para is short for /descendant-or-self::node()/child::para and + * so will select any para element in the document (even a para element + * that is a document element will be selected by //para since the + * document element node is a child of the root node); div//para is + * short for div/descendant-or-self::node()/child::para and so will + * select all para descendants of div children. + */ +static void +xmlXPathCompLocationPath(xmlXPathParserContextPtr ctxt) { + SKIP_BLANKS; + if (CUR != '/') { + xmlXPathCompRelativeLocationPath(ctxt); + } else { + while (CUR == '/') { + if ((CUR == '/') && (NXT(1) == '/')) { + SKIP(2); + SKIP_BLANKS; + PUSH_LONG_EXPR(XPATH_OP_COLLECT, AXIS_DESCENDANT_OR_SELF, + NODE_TEST_TYPE, NODE_TYPE_NODE, NULL, NULL); + xmlXPathCompRelativeLocationPath(ctxt); + } else if (CUR == '/') { + NEXT; + SKIP_BLANKS; + if ((CUR != 0 ) && + ((IS_ASCII_LETTER(CUR)) || (CUR == '_') || (CUR == '.') || + (CUR == '@') || (CUR == '*'))) + xmlXPathCompRelativeLocationPath(ctxt); + } + } + } +} + +/************************************************************************ + * * + * XPath precompiled expression evaluation * + * * + ************************************************************************/ + +static int +xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op); + +#ifdef DEBUG_STEP +static void +xmlXPathDebugDumpStepAxis(xmlXPathAxisVal axis, + xmlXPathTestVal test, + int nbNodes) +{ + xmlGenericError(xmlGenericErrorContext, "new step : "); + switch (axis) { + case AXIS_ANCESTOR: + xmlGenericError(xmlGenericErrorContext, "axis 'ancestors' "); + break; + case AXIS_ANCESTOR_OR_SELF: + xmlGenericError(xmlGenericErrorContext, + "axis 'ancestors-or-self' "); + break; + case AXIS_ATTRIBUTE: + xmlGenericError(xmlGenericErrorContext, "axis 'attributes' "); + break; + case AXIS_CHILD: + xmlGenericError(xmlGenericErrorContext, "axis 'child' "); + break; + case AXIS_DESCENDANT: + xmlGenericError(xmlGenericErrorContext, "axis 'descendant' "); + break; + case AXIS_DESCENDANT_OR_SELF: + xmlGenericError(xmlGenericErrorContext, + "axis 'descendant-or-self' "); + break; + case AXIS_FOLLOWING: + xmlGenericError(xmlGenericErrorContext, "axis 'following' "); + break; + case AXIS_FOLLOWING_SIBLING: + xmlGenericError(xmlGenericErrorContext, + "axis 'following-siblings' "); + break; + case AXIS_NAMESPACE: + xmlGenericError(xmlGenericErrorContext, "axis 'namespace' "); + break; + case AXIS_PARENT: + xmlGenericError(xmlGenericErrorContext, "axis 'parent' "); + break; + case AXIS_PRECEDING: + xmlGenericError(xmlGenericErrorContext, "axis 'preceding' "); + break; + case AXIS_PRECEDING_SIBLING: + xmlGenericError(xmlGenericErrorContext, + "axis 'preceding-sibling' "); + break; + case AXIS_SELF: + xmlGenericError(xmlGenericErrorContext, "axis 'self' "); + break; + } + xmlGenericError(xmlGenericErrorContext, + " context contains %d nodes\n", nbNodes); + switch (test) { + case NODE_TEST_NONE: + xmlGenericError(xmlGenericErrorContext, + " searching for none !!!\n"); + break; + case NODE_TEST_TYPE: + xmlGenericError(xmlGenericErrorContext, + " searching for type %d\n", type); + break; + case NODE_TEST_PI: + xmlGenericError(xmlGenericErrorContext, + " searching for PI !!!\n"); + break; + case NODE_TEST_ALL: + xmlGenericError(xmlGenericErrorContext, + " searching for *\n"); + break; + case NODE_TEST_NS: + xmlGenericError(xmlGenericErrorContext, + " searching for namespace %s\n", + prefix); + break; + case NODE_TEST_NAME: + xmlGenericError(xmlGenericErrorContext, + " searching for name %s\n", name); + if (prefix != NULL) + xmlGenericError(xmlGenericErrorContext, + " with namespace %s\n", prefix); + break; + } + xmlGenericError(xmlGenericErrorContext, "Testing : "); +} +#endif /* DEBUG_STEP */ + +static int +xmlXPathCompOpEvalPredicate(xmlXPathParserContextPtr ctxt, + xmlXPathStepOpPtr op, + xmlNodeSetPtr set, + int contextSize, + int hasNsNodes) +{ + if (op->ch1 != -1) { + xmlXPathCompExprPtr comp = ctxt->comp; + /* + * Process inner predicates first. + */ + if (comp->steps[op->ch1].op != XPATH_OP_PREDICATE) { + /* + * TODO: raise an internal error. + */ + } + contextSize = xmlXPathCompOpEvalPredicate(ctxt, + &comp->steps[op->ch1], set, contextSize, hasNsNodes); + CHECK_ERROR0; + if (contextSize <= 0) + return(0); + } + if (op->ch2 != -1) { + xmlXPathContextPtr xpctxt = ctxt->context; + xmlNodePtr contextNode, oldContextNode; + xmlDocPtr oldContextDoc; + int i, res, contextPos = 0, newContextSize; + xmlXPathStepOpPtr exprOp; + xmlXPathObjectPtr contextObj = NULL, exprRes = NULL; + +#ifdef LIBXML_XPTR_ENABLED + /* + * URGENT TODO: Check the following: + * We don't expect location sets if evaluating prediates, right? + * Only filters should expect location sets, right? + */ +#endif + /* + * SPEC XPath 1.0: + * "For each node in the node-set to be filtered, the + * PredicateExpr is evaluated with that node as the + * context node, with the number of nodes in the + * node-set as the context size, and with the proximity + * position of the node in the node-set with respect to + * the axis as the context position;" + * @oldset is the node-set" to be filtered. + * + * SPEC XPath 1.0: + * "only predicates change the context position and + * context size (see [2.4 Predicates])." + * Example: + * node-set context pos + * nA 1 + * nB 2 + * nC 3 + * After applying predicate [position() > 1] : + * node-set context pos + * nB 1 + * nC 2 + */ + oldContextNode = xpctxt->node; + oldContextDoc = xpctxt->doc; + /* + * Get the expression of this predicate. + */ + exprOp = &ctxt->comp->steps[op->ch2]; + newContextSize = 0; + for (i = 0; i < set->nodeNr; i++) { + if (set->nodeTab[i] == NULL) + continue; + + contextNode = set->nodeTab[i]; + xpctxt->node = contextNode; + xpctxt->contextSize = contextSize; + xpctxt->proximityPosition = ++contextPos; + + /* + * Also set the xpath document in case things like + * key() are evaluated in the predicate. + */ + if ((contextNode->type != XML_NAMESPACE_DECL) && + (contextNode->doc != NULL)) + xpctxt->doc = contextNode->doc; + /* + * Evaluate the predicate expression with 1 context node + * at a time; this node is packaged into a node set; this + * node set is handed over to the evaluation mechanism. + */ + if (contextObj == NULL) + contextObj = xmlXPathCacheNewNodeSet(xpctxt, contextNode); + else + xmlXPathNodeSetAddUnique(contextObj->nodesetval, + contextNode); + + valuePush(ctxt, contextObj); + + res = xmlXPathCompOpEvalToBoolean(ctxt, exprOp, 1); + + if ((ctxt->error != XPATH_EXPRESSION_OK) || (res == -1)) + goto evaluation_error; + + if (res != 0) { + newContextSize++; + } else { + /* + * Remove the entry from the initial node set. + */ + set->nodeTab[i] = NULL; + if (contextNode->type == XML_NAMESPACE_DECL) + xmlXPathNodeSetFreeNs((xmlNsPtr) contextNode); + } + if (ctxt->value == contextObj) { + /* + * Don't free the temporary XPath object holding the + * context node, in order to avoid massive recreation + * inside this loop. + */ + valuePop(ctxt); + xmlXPathNodeSetClear(contextObj->nodesetval, hasNsNodes); + } else { + /* + * TODO: The object was lost in the evaluation machinery. + * Can this happen? Maybe in internal-error cases. + */ + contextObj = NULL; + } + } + goto evaluation_exit; + +evaluation_error: + xmlXPathNodeSetClear(set, hasNsNodes); + newContextSize = 0; + +evaluation_exit: + if (contextObj != NULL) { + if (ctxt->value == contextObj) + valuePop(ctxt); + xmlXPathReleaseObject(xpctxt, contextObj); + } + if (exprRes != NULL) + xmlXPathReleaseObject(ctxt->context, exprRes); + /* + * Reset/invalidate the context. + */ + xpctxt->node = oldContextNode; + xpctxt->doc = oldContextDoc; + xpctxt->contextSize = -1; + xpctxt->proximityPosition = -1; + return(newContextSize); + } + return(contextSize); +} + +static int +xmlXPathCompOpEvalPositionalPredicate(xmlXPathParserContextPtr ctxt, + xmlXPathStepOpPtr op, + xmlNodeSetPtr set, + int contextSize, + int minPos, + int maxPos, + int hasNsNodes) +{ + if (op->ch1 != -1) { + xmlXPathCompExprPtr comp = ctxt->comp; + if (comp->steps[op->ch1].op != XPATH_OP_PREDICATE) { + /* + * TODO: raise an internal error. + */ + } + contextSize = xmlXPathCompOpEvalPredicate(ctxt, + &comp->steps[op->ch1], set, contextSize, hasNsNodes); + CHECK_ERROR0; + if (contextSize <= 0) + return(0); + } + /* + * Check if the node set contains a sufficient number of nodes for + * the requested range. + */ + if (contextSize < minPos) { + xmlXPathNodeSetClear(set, hasNsNodes); + return(0); + } + if (op->ch2 == -1) { + /* + * TODO: Can this ever happen? + */ + return (contextSize); + } else { + xmlDocPtr oldContextDoc; + int i, pos = 0, newContextSize = 0, contextPos = 0, res; + xmlXPathStepOpPtr exprOp; + xmlXPathObjectPtr contextObj = NULL, exprRes = NULL; + xmlNodePtr oldContextNode, contextNode = NULL; + xmlXPathContextPtr xpctxt = ctxt->context; + +#ifdef LIBXML_XPTR_ENABLED + /* + * URGENT TODO: Check the following: + * We don't expect location sets if evaluating prediates, right? + * Only filters should expect location sets, right? + */ +#endif /* LIBXML_XPTR_ENABLED */ + + /* + * Save old context. + */ + oldContextNode = xpctxt->node; + oldContextDoc = xpctxt->doc; + /* + * Get the expression of this predicate. + */ + exprOp = &ctxt->comp->steps[op->ch2]; + for (i = 0; i < set->nodeNr; i++) { + if (set->nodeTab[i] == NULL) + continue; + + contextNode = set->nodeTab[i]; + xpctxt->node = contextNode; + xpctxt->contextSize = contextSize; + xpctxt->proximityPosition = ++contextPos; + + /* + * Initialize the new set. + * Also set the xpath document in case things like + * key() evaluation are attempted on the predicate + */ + if ((contextNode->type != XML_NAMESPACE_DECL) && + (contextNode->doc != NULL)) + xpctxt->doc = contextNode->doc; + /* + * Evaluate the predicate expression with 1 context node + * at a time; this node is packaged into a node set; this + * node set is handed over to the evaluation mechanism. + */ + if (contextObj == NULL) + contextObj = xmlXPathCacheNewNodeSet(xpctxt, contextNode); + else + xmlXPathNodeSetAddUnique(contextObj->nodesetval, + contextNode); + + valuePush(ctxt, contextObj); + res = xmlXPathCompOpEvalToBoolean(ctxt, exprOp, 1); + + if ((ctxt->error != XPATH_EXPRESSION_OK) || (res == -1)) + goto evaluation_error; + + if (res) + pos++; + + if (res && (pos >= minPos) && (pos <= maxPos)) { + /* + * Fits in the requested range. + */ + newContextSize++; + if (minPos == maxPos) { + /* + * Only 1 node was requested. + */ + if (contextNode->type == XML_NAMESPACE_DECL) { + /* + * As always: take care of those nasty + * namespace nodes. + */ + set->nodeTab[i] = NULL; + } + xmlXPathNodeSetClear(set, hasNsNodes); + set->nodeNr = 1; + set->nodeTab[0] = contextNode; + goto evaluation_exit; + } + if (pos == maxPos) { + /* + * We are done. + */ + xmlXPathNodeSetClearFromPos(set, i +1, hasNsNodes); + goto evaluation_exit; + } + } else { + /* + * Remove the entry from the initial node set. + */ + set->nodeTab[i] = NULL; + if (contextNode->type == XML_NAMESPACE_DECL) + xmlXPathNodeSetFreeNs((xmlNsPtr) contextNode); + } + if (exprRes != NULL) { + xmlXPathReleaseObject(ctxt->context, exprRes); + exprRes = NULL; + } + if (ctxt->value == contextObj) { + /* + * Don't free the temporary XPath object holding the + * context node, in order to avoid massive recreation + * inside this loop. + */ + valuePop(ctxt); + xmlXPathNodeSetClear(contextObj->nodesetval, hasNsNodes); + } else { + /* + * The object was lost in the evaluation machinery. + * Can this happen? Maybe in case of internal-errors. + */ + contextObj = NULL; + } + } + goto evaluation_exit; + +evaluation_error: + xmlXPathNodeSetClear(set, hasNsNodes); + newContextSize = 0; + +evaluation_exit: + if (contextObj != NULL) { + if (ctxt->value == contextObj) + valuePop(ctxt); + xmlXPathReleaseObject(xpctxt, contextObj); + } + if (exprRes != NULL) + xmlXPathReleaseObject(ctxt->context, exprRes); + /* + * Reset/invalidate the context. + */ + xpctxt->node = oldContextNode; + xpctxt->doc = oldContextDoc; + xpctxt->contextSize = -1; + xpctxt->proximityPosition = -1; + return(newContextSize); + } + return(contextSize); +} + +static int +xmlXPathIsPositionalPredicate(xmlXPathParserContextPtr ctxt, + xmlXPathStepOpPtr op, + int *maxPos) +{ + + xmlXPathStepOpPtr exprOp; + + /* + * BIG NOTE: This is not intended for XPATH_OP_FILTER yet! + */ + + /* + * If not -1, then ch1 will point to: + * 1) For predicates (XPATH_OP_PREDICATE): + * - an inner predicate operator + * 2) For filters (XPATH_OP_FILTER): + * - an inner filter operater OR + * - an expression selecting the node set. + * E.g. "key('a', 'b')" or "(//foo | //bar)". + */ + if ((op->op != XPATH_OP_PREDICATE) && (op->op != XPATH_OP_FILTER)) + return(0); + + if (op->ch2 != -1) { + exprOp = &ctxt->comp->steps[op->ch2]; + } else + return(0); + + if ((exprOp != NULL) && + (exprOp->op == XPATH_OP_VALUE) && + (exprOp->value4 != NULL) && + (((xmlXPathObjectPtr) exprOp->value4)->type == XPATH_NUMBER)) + { + /* + * We have a "[n]" predicate here. + * TODO: Unfortunately this simplistic test here is not + * able to detect a position() predicate in compound + * expressions like "[@attr = 'a" and position() = 1], + * and even not the usage of position() in + * "[position() = 1]"; thus - obviously - a position-range, + * like it "[position() < 5]", is also not detected. + * Maybe we could rewrite the AST to ease the optimization. + */ + *maxPos = (int) ((xmlXPathObjectPtr) exprOp->value4)->floatval; + + if (((xmlXPathObjectPtr) exprOp->value4)->floatval == + (float) *maxPos) + { + return(1); + } + } + return(0); +} + +static int +xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt, + xmlXPathStepOpPtr op, + xmlNodePtr * first, xmlNodePtr * last, + int toBool) +{ + +#define XP_TEST_HIT \ + if (hasAxisRange != 0) { \ + if (++pos == maxPos) { \ + addNode(seq, cur); \ + goto axis_range_end; } \ + } else { \ + addNode(seq, cur); \ + if (breakOnFirstHit) goto first_hit; } + +#define XP_TEST_HIT_NS \ + if (hasAxisRange != 0) { \ + if (++pos == maxPos) { \ + hasNsNodes = 1; \ + xmlXPathNodeSetAddNs(seq, xpctxt->node, (xmlNsPtr) cur); \ + goto axis_range_end; } \ + } else { \ + hasNsNodes = 1; \ + xmlXPathNodeSetAddNs(seq, \ + xpctxt->node, (xmlNsPtr) cur); \ + if (breakOnFirstHit) goto first_hit; } + + xmlXPathAxisVal axis = (xmlXPathAxisVal) op->value; + xmlXPathTestVal test = (xmlXPathTestVal) op->value2; + xmlXPathTypeVal type = (xmlXPathTypeVal) op->value3; + const xmlChar *prefix = op->value4; + const xmlChar *name = op->value5; + const xmlChar *URI = NULL; + +#ifdef DEBUG_STEP + int nbMatches = 0, prevMatches = 0; +#endif + int total = 0, hasNsNodes = 0; + /* The popped object holding the context nodes */ + xmlXPathObjectPtr obj; + /* The set of context nodes for the node tests */ + xmlNodeSetPtr contextSeq; + int contextIdx; + xmlNodePtr contextNode; + /* The context node for a compound traversal */ + xmlNodePtr outerContextNode; + /* The final resulting node set wrt to all context nodes */ + xmlNodeSetPtr outSeq; + /* + * The temporary resulting node set wrt 1 context node. + * Used to feed predicate evaluation. + */ + xmlNodeSetPtr seq; + xmlNodePtr cur; + /* First predicate operator */ + xmlXPathStepOpPtr predOp; + int maxPos; /* The requested position() (when a "[n]" predicate) */ + int hasPredicateRange, hasAxisRange, pos, size, newSize; + int breakOnFirstHit; + + xmlXPathTraversalFunction next = NULL; + /* compound axis traversal */ + xmlXPathTraversalFunctionExt outerNext = NULL; + void (*addNode) (xmlNodeSetPtr, xmlNodePtr); + xmlXPathNodeSetMergeFunction mergeAndClear; + xmlNodePtr oldContextNode; + xmlXPathContextPtr xpctxt = ctxt->context; + + + CHECK_TYPE0(XPATH_NODESET); + obj = valuePop(ctxt); + /* + * Setup namespaces. + */ + if (prefix != NULL) { + URI = xmlXPathNsLookup(xpctxt, prefix); + if (URI == NULL) { + xmlXPathReleaseObject(xpctxt, obj); + XP_ERROR0(XPATH_UNDEF_PREFIX_ERROR); + } + } + /* + * Setup axis. + * + * MAYBE FUTURE TODO: merging optimizations: + * - If the nodes to be traversed wrt to the initial nodes and + * the current axis cannot overlap, then we could avoid searching + * for duplicates during the merge. + * But the question is how/when to evaluate if they cannot overlap. + * Example: if we know that for two initial nodes, the one is + * not in the ancestor-or-self axis of the other, then we could safely + * avoid a duplicate-aware merge, if the axis to be traversed is e.g. + * the descendant-or-self axis. + */ + addNode = xmlXPathNodeSetAdd; + mergeAndClear = xmlXPathNodeSetMergeAndClear; + switch (axis) { + case AXIS_ANCESTOR: + first = NULL; + next = xmlXPathNextAncestor; + break; + case AXIS_ANCESTOR_OR_SELF: + first = NULL; + next = xmlXPathNextAncestorOrSelf; + break; + case AXIS_ATTRIBUTE: + first = NULL; + last = NULL; + next = xmlXPathNextAttribute; + mergeAndClear = xmlXPathNodeSetMergeAndClearNoDupls; + break; + case AXIS_CHILD: + last = NULL; + if (op->rewriteType == XP_REWRITE_DOS_CHILD_ELEM) { + /* + * This iterator will give us only nodes which can + * hold element nodes. + */ + outerNext = xmlXPathNextDescendantOrSelfElemParent; + } + if (((test == NODE_TEST_NAME) || (test == NODE_TEST_ALL)) && + (type == NODE_TYPE_NODE)) + { + /* + * Optimization if an element node type is 'element'. + */ + next = xmlXPathNextChildElement; + } else + next = xmlXPathNextChild; + mergeAndClear = xmlXPathNodeSetMergeAndClearNoDupls; + break; + case AXIS_DESCENDANT: + last = NULL; + next = xmlXPathNextDescendant; + break; + case AXIS_DESCENDANT_OR_SELF: + last = NULL; + next = xmlXPathNextDescendantOrSelf; + break; + case AXIS_FOLLOWING: + last = NULL; + next = xmlXPathNextFollowing; + break; + case AXIS_FOLLOWING_SIBLING: + last = NULL; + next = xmlXPathNextFollowingSibling; + break; + case AXIS_NAMESPACE: + first = NULL; + last = NULL; + next = (xmlXPathTraversalFunction) xmlXPathNextNamespace; + mergeAndClear = xmlXPathNodeSetMergeAndClearNoDupls; + break; + case AXIS_PARENT: + first = NULL; + next = xmlXPathNextParent; + break; + case AXIS_PRECEDING: + first = NULL; + next = xmlXPathNextPrecedingInternal; + break; + case AXIS_PRECEDING_SIBLING: + first = NULL; + next = xmlXPathNextPrecedingSibling; + break; + case AXIS_SELF: + first = NULL; + last = NULL; + next = xmlXPathNextSelf; + mergeAndClear = xmlXPathNodeSetMergeAndClearNoDupls; + break; + } + +#ifdef DEBUG_STEP + xmlXPathDebugDumpStepAxis(axis, test, + (obj->nodesetval != NULL) ? obj->nodsetval->nodeNr : 0); +#endif + + if (next == NULL) { + xmlXPathReleaseObject(xpctxt, obj); + return(0); + } + contextSeq = obj->nodesetval; + if ((contextSeq == NULL) || (contextSeq->nodeNr <= 0)) { + xmlXPathReleaseObject(xpctxt, obj); + valuePush(ctxt, xmlXPathCacheWrapNodeSet(xpctxt, NULL)); + return(0); + } + /* + * Predicate optimization --------------------------------------------- + * If this step has a last predicate, which contains a position(), + * then we'll optimize (although not exactly "position()", but only + * the short-hand form, i.e., "[n]". + * + * Example - expression "/foo[parent::bar][1]": + * + * COLLECT 'child' 'name' 'node' foo -- op (we are here) + * ROOT -- op->ch1 + * PREDICATE -- op->ch2 (predOp) + * PREDICATE -- predOp->ch1 = [parent::bar] + * SORT + * COLLECT 'parent' 'name' 'node' bar + * NODE + * ELEM Object is a number : 1 -- predOp->ch2 = [1] + * + */ + maxPos = 0; + predOp = NULL; + hasPredicateRange = 0; + hasAxisRange = 0; + if (op->ch2 != -1) { + /* + * There's at least one predicate. 16 == XPATH_OP_PREDICATE + */ + predOp = &ctxt->comp->steps[op->ch2]; + if (xmlXPathIsPositionalPredicate(ctxt, predOp, &maxPos)) { + if (predOp->ch1 != -1) { + /* + * Use the next inner predicate operator. + */ + predOp = &ctxt->comp->steps[predOp->ch1]; + hasPredicateRange = 1; + } else { + /* + * There's no other predicate than the [n] predicate. + */ + predOp = NULL; + hasAxisRange = 1; + } + } + } + breakOnFirstHit = ((toBool) && (predOp == NULL)) ? 1 : 0; + /* + * Axis traversal ----------------------------------------------------- + */ + /* + * 2.3 Node Tests + * - For the attribute axis, the principal node type is attribute. + * - For the namespace axis, the principal node type is namespace. + * - For other axes, the principal node type is element. + * + * A node test * is true for any node of the + * principal node type. For example, child::* will + * select all element children of the context node + */ + oldContextNode = xpctxt->node; + addNode = xmlXPathNodeSetAddUnique; + outSeq = NULL; + seq = NULL; + outerContextNode = NULL; + contextNode = NULL; + contextIdx = 0; + + + while ((contextIdx < contextSeq->nodeNr) || (contextNode != NULL)) { + if (outerNext != NULL) { + /* + * This is a compound traversal. + */ + if (contextNode == NULL) { + /* + * Set the context for the outer traversal. + */ + outerContextNode = contextSeq->nodeTab[contextIdx++]; + contextNode = outerNext(NULL, outerContextNode); + } else + contextNode = outerNext(contextNode, outerContextNode); + if (contextNode == NULL) + continue; + /* + * Set the context for the main traversal. + */ + xpctxt->node = contextNode; + } else + xpctxt->node = contextSeq->nodeTab[contextIdx++]; + + if (seq == NULL) { + seq = xmlXPathNodeSetCreate(NULL); + if (seq == NULL) { + total = 0; + goto error; + } + } + /* + * Traverse the axis and test the nodes. + */ + pos = 0; + cur = NULL; + hasNsNodes = 0; + do { + cur = next(ctxt, cur); + if (cur == NULL) + break; + + /* + * QUESTION TODO: What does the "first" and "last" stuff do? + */ + if ((first != NULL) && (*first != NULL)) { + if (*first == cur) + break; + if (((total % 256) == 0) && +#ifdef XP_OPTIMIZED_NON_ELEM_COMPARISON + (xmlXPathCmpNodesExt(*first, cur) >= 0)) +#else + (xmlXPathCmpNodes(*first, cur) >= 0)) +#endif + { + break; + } + } + if ((last != NULL) && (*last != NULL)) { + if (*last == cur) + break; + if (((total % 256) == 0) && +#ifdef XP_OPTIMIZED_NON_ELEM_COMPARISON + (xmlXPathCmpNodesExt(cur, *last) >= 0)) +#else + (xmlXPathCmpNodes(cur, *last) >= 0)) +#endif + { + break; + } + } + + total++; + +#ifdef DEBUG_STEP + xmlGenericError(xmlGenericErrorContext, " %s", cur->name); +#endif + switch (test) { + case NODE_TEST_NONE: + total = 0; + STRANGE + goto error; + case NODE_TEST_TYPE: + /* + * TODO: Don't we need to use + * xmlXPathNodeSetAddNs() for namespace nodes here? + * Surprisingly, some c14n tests fail, if we do this. + */ + if (type == NODE_TYPE_NODE) { + switch (cur->type) { + case XML_DOCUMENT_NODE: + case XML_HTML_DOCUMENT_NODE: +#ifdef LIBXML_DOCB_ENABLED + case XML_DOCB_DOCUMENT_NODE: +#endif + case XML_ELEMENT_NODE: + case XML_ATTRIBUTE_NODE: + case XML_PI_NODE: + case XML_COMMENT_NODE: + case XML_CDATA_SECTION_NODE: + case XML_TEXT_NODE: + case XML_NAMESPACE_DECL: + XP_TEST_HIT + break; + default: + break; + } + } else if (cur->type == type) { + if (type == XML_NAMESPACE_DECL) + XP_TEST_HIT_NS + else + XP_TEST_HIT + } else if ((type == NODE_TYPE_TEXT) && + (cur->type == XML_CDATA_SECTION_NODE)) + { + XP_TEST_HIT + } + break; + case NODE_TEST_PI: + if ((cur->type == XML_PI_NODE) && + ((name == NULL) || xmlStrEqual(name, cur->name))) + { + XP_TEST_HIT + } + break; + case NODE_TEST_ALL: + if (axis == AXIS_ATTRIBUTE) { + if (cur->type == XML_ATTRIBUTE_NODE) + { + XP_TEST_HIT + } + } else if (axis == AXIS_NAMESPACE) { + if (cur->type == XML_NAMESPACE_DECL) + { + XP_TEST_HIT_NS + } + } else { + if (cur->type == XML_ELEMENT_NODE) { + if (prefix == NULL) + { + XP_TEST_HIT + + } else if ((cur->ns != NULL) && + (xmlStrEqual(URI, cur->ns->href))) + { + XP_TEST_HIT + } + } + } + break; + case NODE_TEST_NS:{ + TODO; + break; + } + case NODE_TEST_NAME: + switch (cur->type) { + case XML_ELEMENT_NODE: + if (xmlStrEqual(name, cur->name)) { + if (prefix == NULL) { + if (cur->ns == NULL) + { + XP_TEST_HIT + } + } else { + if ((cur->ns != NULL) && + (xmlStrEqual(URI, cur->ns->href))) + { + XP_TEST_HIT + } + } + } + break; + case XML_ATTRIBUTE_NODE:{ + xmlAttrPtr attr = (xmlAttrPtr) cur; + + if (xmlStrEqual(name, attr->name)) { + if (prefix == NULL) { + if ((attr->ns == NULL) || + (attr->ns->prefix == NULL)) + { + XP_TEST_HIT + } + } else { + if ((attr->ns != NULL) && + (xmlStrEqual(URI, + attr->ns->href))) + { + XP_TEST_HIT + } + } + } + break; + } + case XML_NAMESPACE_DECL: + if (cur->type == XML_NAMESPACE_DECL) { + xmlNsPtr ns = (xmlNsPtr) cur; + + if ((ns->prefix != NULL) && (name != NULL) + && (xmlStrEqual(ns->prefix, name))) + { + XP_TEST_HIT_NS + } + } + break; + default: + break; + } + break; + } /* switch(test) */ + } while (cur != NULL); + + goto apply_predicates; + +axis_range_end: /* ----------------------------------------------------- */ + /* + * We have a "/foo[n]", and position() = n was reached. + * Note that we can have as well "/foo/::parent::foo[1]", so + * a duplicate-aware merge is still needed. + * Merge with the result. + */ + if (outSeq == NULL) { + outSeq = seq; + seq = NULL; + } else + outSeq = mergeAndClear(outSeq, seq, 0); + /* + * Break if only a true/false result was requested. + */ + if (toBool) + break; + continue; + +first_hit: /* ---------------------------------------------------------- */ + /* + * Break if only a true/false result was requested and + * no predicates existed and a node test succeeded. + */ + if (outSeq == NULL) { + outSeq = seq; + seq = NULL; + } else + outSeq = mergeAndClear(outSeq, seq, 0); + break; + +#ifdef DEBUG_STEP + if (seq != NULL) + nbMatches += seq->nodeNr; +#endif + +apply_predicates: /* --------------------------------------------------- */ + /* + * Apply predicates. + */ + if ((predOp != NULL) && (seq->nodeNr > 0)) { + /* + * E.g. when we have a "/foo[some expression][n]". + */ + /* + * QUESTION TODO: The old predicate evaluation took into + * account location-sets. + * (E.g. ctxt->value->type == XPATH_LOCATIONSET) + * Do we expect such a set here? + * All what I learned now from the evaluation semantics + * does not indicate that a location-set will be processed + * here, so this looks OK. + */ + /* + * Iterate over all predicates, starting with the outermost + * predicate. + * TODO: Problem: we cannot execute the inner predicates first + * since we cannot go back *up* the operator tree! + * Options we have: + * 1) Use of recursive functions (like is it currently done + * via xmlXPathCompOpEval()) + * 2) Add a predicate evaluation information stack to the + * context struct + * 3) Change the way the operators are linked; we need a + * "parent" field on xmlXPathStepOp + * + * For the moment, I'll try to solve this with a recursive + * function: xmlXPathCompOpEvalPredicate(). + */ + size = seq->nodeNr; + if (hasPredicateRange != 0) + newSize = xmlXPathCompOpEvalPositionalPredicate(ctxt, + predOp, seq, size, maxPos, maxPos, hasNsNodes); + else + newSize = xmlXPathCompOpEvalPredicate(ctxt, + predOp, seq, size, hasNsNodes); + + if (ctxt->error != XPATH_EXPRESSION_OK) { + total = 0; + goto error; + } + /* + * Add the filtered set of nodes to the result node set. + */ + if (newSize == 0) { + /* + * The predicates filtered all nodes out. + */ + xmlXPathNodeSetClear(seq, hasNsNodes); + } else if (seq->nodeNr > 0) { + /* + * Add to result set. + */ + if (outSeq == NULL) { + if (size != newSize) { + /* + * We need to merge and clear here, since + * the sequence will contained NULLed entries. + */ + outSeq = mergeAndClear(NULL, seq, 1); + } else { + outSeq = seq; + seq = NULL; + } + } else + outSeq = mergeAndClear(outSeq, seq, + (size != newSize) ? 1: 0); + /* + * Break if only a true/false result was requested. + */ + if (toBool) + break; + } + } else if (seq->nodeNr > 0) { + /* + * Add to result set. + */ + if (outSeq == NULL) { + outSeq = seq; + seq = NULL; + } else { + outSeq = mergeAndClear(outSeq, seq, 0); + } + } + } + +error: + if ((obj->boolval) && (obj->user != NULL)) { + /* + * QUESTION TODO: What does this do and why? + * TODO: Do we have to do this also for the "error" + * cleanup further down? + */ + ctxt->value->boolval = 1; + ctxt->value->user = obj->user; + obj->user = NULL; + obj->boolval = 0; + } + xmlXPathReleaseObject(xpctxt, obj); + + /* + * Ensure we return at least an emtpy set. + */ + if (outSeq == NULL) { + if ((seq != NULL) && (seq->nodeNr == 0)) + outSeq = seq; + else + outSeq = xmlXPathNodeSetCreate(NULL); + } + if ((seq != NULL) && (seq != outSeq)) { + xmlXPathFreeNodeSet(seq); + } + /* + * Hand over the result. Better to push the set also in + * case of errors. + */ + valuePush(ctxt, xmlXPathCacheWrapNodeSet(xpctxt, outSeq)); + /* + * Reset the context node. + */ + xpctxt->node = oldContextNode; + +#ifdef DEBUG_STEP + xmlGenericError(xmlGenericErrorContext, + "\nExamined %d nodes, found %d nodes at that step\n", + total, nbMatches); +#endif + + return(total); +} + +static int +xmlXPathCompOpEvalFilterFirst(xmlXPathParserContextPtr ctxt, + xmlXPathStepOpPtr op, xmlNodePtr * first); + +/** + * xmlXPathCompOpEvalFirst: + * @ctxt: the XPath parser context with the compiled expression + * @op: an XPath compiled operation + * @first: the first elem found so far + * + * Evaluate the Precompiled XPath operation searching only the first + * element in document order + * + * Returns the number of examined objects. + */ +static int +xmlXPathCompOpEvalFirst(xmlXPathParserContextPtr ctxt, + xmlXPathStepOpPtr op, xmlNodePtr * first) +{ + int total = 0, cur; + xmlXPathCompExprPtr comp; + xmlXPathObjectPtr arg1, arg2; + + CHECK_ERROR0; + comp = ctxt->comp; + switch (op->op) { + case XPATH_OP_END: + return (0); + case XPATH_OP_UNION: + total = + xmlXPathCompOpEvalFirst(ctxt, &comp->steps[op->ch1], + first); + CHECK_ERROR0; + if ((ctxt->value != NULL) + && (ctxt->value->type == XPATH_NODESET) + && (ctxt->value->nodesetval != NULL) + && (ctxt->value->nodesetval->nodeNr >= 1)) { + /* + * limit tree traversing to first node in the result + */ + /* + * OPTIMIZE TODO: This implicitely sorts + * the result, even if not needed. E.g. if the argument + * of the count() function, no sorting is needed. + * OPTIMIZE TODO: How do we know if the node-list wasn't + * aready sorted? + */ + if (ctxt->value->nodesetval->nodeNr > 1) + xmlXPathNodeSetSort(ctxt->value->nodesetval); + *first = ctxt->value->nodesetval->nodeTab[0]; + } + cur = + xmlXPathCompOpEvalFirst(ctxt, &comp->steps[op->ch2], + first); + CHECK_ERROR0; + CHECK_TYPE0(XPATH_NODESET); + arg2 = valuePop(ctxt); + + CHECK_TYPE0(XPATH_NODESET); + arg1 = valuePop(ctxt); + + arg1->nodesetval = xmlXPathNodeSetMerge(arg1->nodesetval, + arg2->nodesetval); + valuePush(ctxt, arg1); + xmlXPathReleaseObject(ctxt->context, arg2); + /* optimizer */ + if (total > cur) + xmlXPathCompSwap(op); + return (total + cur); + case XPATH_OP_ROOT: + xmlXPathRoot(ctxt); + return (0); + case XPATH_OP_NODE: + if (op->ch1 != -1) + total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]); + CHECK_ERROR0; + if (op->ch2 != -1) + total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]); + CHECK_ERROR0; + valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt->context, + ctxt->context->node)); + return (total); + case XPATH_OP_RESET: + if (op->ch1 != -1) + total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]); + CHECK_ERROR0; + if (op->ch2 != -1) + total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]); + CHECK_ERROR0; + ctxt->context->node = NULL; + return (total); + case XPATH_OP_COLLECT:{ + if (op->ch1 == -1) + return (total); + + total = xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]); + CHECK_ERROR0; + + total += xmlXPathNodeCollectAndTest(ctxt, op, first, NULL, 0); + return (total); + } + case XPATH_OP_VALUE: + valuePush(ctxt, + xmlXPathCacheObjectCopy(ctxt->context, + (xmlXPathObjectPtr) op->value4)); + return (0); + case XPATH_OP_SORT: + if (op->ch1 != -1) + total += + xmlXPathCompOpEvalFirst(ctxt, &comp->steps[op->ch1], + first); + CHECK_ERROR0; + if ((ctxt->value != NULL) + && (ctxt->value->type == XPATH_NODESET) + && (ctxt->value->nodesetval != NULL) + && (ctxt->value->nodesetval->nodeNr > 1)) + xmlXPathNodeSetSort(ctxt->value->nodesetval); + return (total); +#ifdef XP_OPTIMIZED_FILTER_FIRST + case XPATH_OP_FILTER: + total =+ xmlXPathCompOpEvalFilterFirst(ctxt, op, first); + return (total); +#endif + default: + return (xmlXPathCompOpEval(ctxt, op)); + } +} + +/** + * xmlXPathCompOpEvalLast: + * @ctxt: the XPath parser context with the compiled expression + * @op: an XPath compiled operation + * @last: the last elem found so far + * + * Evaluate the Precompiled XPath operation searching only the last + * element in document order + * + * Returns the number of nodes traversed + */ +static int +xmlXPathCompOpEvalLast(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op, + xmlNodePtr * last) +{ + int total = 0, cur; + xmlXPathCompExprPtr comp; + xmlXPathObjectPtr arg1, arg2; + xmlNodePtr bak; + xmlDocPtr bakd; + int pp; + int cs; + + CHECK_ERROR0; + comp = ctxt->comp; + switch (op->op) { + case XPATH_OP_END: + return (0); + case XPATH_OP_UNION: + bakd = ctxt->context->doc; + bak = ctxt->context->node; + pp = ctxt->context->proximityPosition; + cs = ctxt->context->contextSize; + total = + xmlXPathCompOpEvalLast(ctxt, &comp->steps[op->ch1], last); + CHECK_ERROR0; + if ((ctxt->value != NULL) + && (ctxt->value->type == XPATH_NODESET) + && (ctxt->value->nodesetval != NULL) + && (ctxt->value->nodesetval->nodeNr >= 1)) { + /* + * limit tree traversing to first node in the result + */ + if (ctxt->value->nodesetval->nodeNr > 1) + xmlXPathNodeSetSort(ctxt->value->nodesetval); + *last = + ctxt->value->nodesetval->nodeTab[ctxt->value-> + nodesetval->nodeNr - + 1]; + } + ctxt->context->doc = bakd; + ctxt->context->node = bak; + ctxt->context->proximityPosition = pp; + ctxt->context->contextSize = cs; + cur = + xmlXPathCompOpEvalLast(ctxt, &comp->steps[op->ch2], last); + CHECK_ERROR0; + if ((ctxt->value != NULL) + && (ctxt->value->type == XPATH_NODESET) + && (ctxt->value->nodesetval != NULL) + && (ctxt->value->nodesetval->nodeNr >= 1)) { /* TODO: NOP ? */ + } + CHECK_TYPE0(XPATH_NODESET); + arg2 = valuePop(ctxt); + + CHECK_TYPE0(XPATH_NODESET); + arg1 = valuePop(ctxt); + + arg1->nodesetval = xmlXPathNodeSetMerge(arg1->nodesetval, + arg2->nodesetval); + valuePush(ctxt, arg1); + xmlXPathReleaseObject(ctxt->context, arg2); + /* optimizer */ + if (total > cur) + xmlXPathCompSwap(op); + return (total + cur); + case XPATH_OP_ROOT: + xmlXPathRoot(ctxt); + return (0); + case XPATH_OP_NODE: + if (op->ch1 != -1) + total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]); + CHECK_ERROR0; + if (op->ch2 != -1) + total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]); + CHECK_ERROR0; + valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt->context, + ctxt->context->node)); + return (total); + case XPATH_OP_RESET: + if (op->ch1 != -1) + total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]); + CHECK_ERROR0; + if (op->ch2 != -1) + total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]); + CHECK_ERROR0; + ctxt->context->node = NULL; + return (total); + case XPATH_OP_COLLECT:{ + if (op->ch1 == -1) + return (0); + + total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]); + CHECK_ERROR0; + + total += xmlXPathNodeCollectAndTest(ctxt, op, NULL, last, 0); + return (total); + } + case XPATH_OP_VALUE: + valuePush(ctxt, + xmlXPathCacheObjectCopy(ctxt->context, + (xmlXPathObjectPtr) op->value4)); + return (0); + case XPATH_OP_SORT: + if (op->ch1 != -1) + total += + xmlXPathCompOpEvalLast(ctxt, &comp->steps[op->ch1], + last); + CHECK_ERROR0; + if ((ctxt->value != NULL) + && (ctxt->value->type == XPATH_NODESET) + && (ctxt->value->nodesetval != NULL) + && (ctxt->value->nodesetval->nodeNr > 1)) + xmlXPathNodeSetSort(ctxt->value->nodesetval); + return (total); + default: + return (xmlXPathCompOpEval(ctxt, op)); + } +} + +#ifdef XP_OPTIMIZED_FILTER_FIRST +static int +xmlXPathCompOpEvalFilterFirst(xmlXPathParserContextPtr ctxt, + xmlXPathStepOpPtr op, xmlNodePtr * first) +{ + int total = 0; + xmlXPathCompExprPtr comp; + xmlXPathObjectPtr res; + xmlXPathObjectPtr obj; + xmlNodeSetPtr oldset; + xmlNodePtr oldnode; + xmlDocPtr oldDoc; + int i; + + CHECK_ERROR0; + comp = ctxt->comp; + /* + * Optimization for ()[last()] selection i.e. the last elem + */ + if ((op->ch1 != -1) && (op->ch2 != -1) && + (comp->steps[op->ch1].op == XPATH_OP_SORT) && + (comp->steps[op->ch2].op == XPATH_OP_SORT)) { + int f = comp->steps[op->ch2].ch1; + + if ((f != -1) && + (comp->steps[f].op == XPATH_OP_FUNCTION) && + (comp->steps[f].value5 == NULL) && + (comp->steps[f].value == 0) && + (comp->steps[f].value4 != NULL) && + (xmlStrEqual + (comp->steps[f].value4, BAD_CAST "last"))) { + xmlNodePtr last = NULL; + + total += + xmlXPathCompOpEvalLast(ctxt, + &comp->steps[op->ch1], + &last); + CHECK_ERROR0; + /* + * The nodeset should be in document order, + * Keep only the last value + */ + if ((ctxt->value != NULL) && + (ctxt->value->type == XPATH_NODESET) && + (ctxt->value->nodesetval != NULL) && + (ctxt->value->nodesetval->nodeTab != NULL) && + (ctxt->value->nodesetval->nodeNr > 1)) { + ctxt->value->nodesetval->nodeTab[0] = + ctxt->value->nodesetval->nodeTab[ctxt-> + value-> + nodesetval-> + nodeNr - + 1]; + ctxt->value->nodesetval->nodeNr = 1; + *first = *(ctxt->value->nodesetval->nodeTab); + } + return (total); + } + } + + if (op->ch1 != -1) + total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]); + CHECK_ERROR0; + if (op->ch2 == -1) + return (total); + if (ctxt->value == NULL) + return (total); + +#ifdef LIBXML_XPTR_ENABLED + oldnode = ctxt->context->node; + /* + * Hum are we filtering the result of an XPointer expression + */ + if (ctxt->value->type == XPATH_LOCATIONSET) { + xmlXPathObjectPtr tmp = NULL; + xmlLocationSetPtr newlocset = NULL; + xmlLocationSetPtr oldlocset; + + /* + * Extract the old locset, and then evaluate the result of the + * expression for all the element in the locset. use it to grow + * up a new locset. + */ + CHECK_TYPE0(XPATH_LOCATIONSET); + obj = valuePop(ctxt); + oldlocset = obj->user; + ctxt->context->node = NULL; + + if ((oldlocset == NULL) || (oldlocset->locNr == 0)) { + ctxt->context->contextSize = 0; + ctxt->context->proximityPosition = 0; + if (op->ch2 != -1) + total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]); + res = valuePop(ctxt); + if (res != NULL) { + xmlXPathReleaseObject(ctxt->context, res); + } + valuePush(ctxt, obj); + CHECK_ERROR0; + return (total); + } + newlocset = xmlXPtrLocationSetCreate(NULL); + + for (i = 0; i < oldlocset->locNr; i++) { + /* + * Run the evaluation with a node list made of a + * single item in the nodelocset. + */ + ctxt->context->node = oldlocset->locTab[i]->user; + ctxt->context->contextSize = oldlocset->locNr; + ctxt->context->proximityPosition = i + 1; + if (tmp == NULL) { + tmp = xmlXPathCacheNewNodeSet(ctxt->context, + ctxt->context->node); + } else { + xmlXPathNodeSetAddUnique(tmp->nodesetval, + ctxt->context->node); + } + valuePush(ctxt, tmp); + if (op->ch2 != -1) + total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]); + if (ctxt->error != XPATH_EXPRESSION_OK) { + xmlXPathFreeObject(obj); + return(0); + } + /* + * The result of the evaluation need to be tested to + * decided whether the filter succeeded or not + */ + res = valuePop(ctxt); + if (xmlXPathEvaluatePredicateResult(ctxt, res)) { + xmlXPtrLocationSetAdd(newlocset, + xmlXPathCacheObjectCopy(ctxt->context, + oldlocset->locTab[i])); + } + /* + * Cleanup + */ + if (res != NULL) { + xmlXPathReleaseObject(ctxt->context, res); + } + if (ctxt->value == tmp) { + valuePop(ctxt); + xmlXPathNodeSetClear(tmp->nodesetval, 1); + /* + * REVISIT TODO: Don't create a temporary nodeset + * for everly iteration. + */ + /* OLD: xmlXPathFreeObject(res); */ + } else + tmp = NULL; + ctxt->context->node = NULL; + /* + * Only put the first node in the result, then leave. + */ + if (newlocset->locNr > 0) { + *first = (xmlNodePtr) oldlocset->locTab[i]->user; + break; + } + } + if (tmp != NULL) { + xmlXPathReleaseObject(ctxt->context, tmp); + } + /* + * The result is used as the new evaluation locset. + */ + xmlXPathReleaseObject(ctxt->context, obj); + ctxt->context->node = NULL; + ctxt->context->contextSize = -1; + ctxt->context->proximityPosition = -1; + valuePush(ctxt, xmlXPtrWrapLocationSet(newlocset)); + ctxt->context->node = oldnode; + return (total); + } +#endif /* LIBXML_XPTR_ENABLED */ + + /* + * Extract the old set, and then evaluate the result of the + * expression for all the element in the set. use it to grow + * up a new set. + */ + CHECK_TYPE0(XPATH_NODESET); + obj = valuePop(ctxt); + oldset = obj->nodesetval; + + oldnode = ctxt->context->node; + oldDoc = ctxt->context->doc; + ctxt->context->node = NULL; + + if ((oldset == NULL) || (oldset->nodeNr == 0)) { + ctxt->context->contextSize = 0; + ctxt->context->proximityPosition = 0; + /* QUESTION TODO: Why was this code commented out? + if (op->ch2 != -1) + total += + xmlXPathCompOpEval(ctxt, + &comp->steps[op->ch2]); + CHECK_ERROR0; + res = valuePop(ctxt); + if (res != NULL) + xmlXPathFreeObject(res); + */ + valuePush(ctxt, obj); + ctxt->context->node = oldnode; + CHECK_ERROR0; + } else { + xmlNodeSetPtr newset; + xmlXPathObjectPtr tmp = NULL; + /* + * Initialize the new set. + * Also set the xpath document in case things like + * key() evaluation are attempted on the predicate + */ + newset = xmlXPathNodeSetCreate(NULL); + + for (i = 0; i < oldset->nodeNr; i++) { + /* + * Run the evaluation with a node list made of + * a single item in the nodeset. + */ + ctxt->context->node = oldset->nodeTab[i]; + if ((oldset->nodeTab[i]->type != XML_NAMESPACE_DECL) && + (oldset->nodeTab[i]->doc != NULL)) + ctxt->context->doc = oldset->nodeTab[i]->doc; + if (tmp == NULL) { + tmp = xmlXPathCacheNewNodeSet(ctxt->context, + ctxt->context->node); + } else { + xmlXPathNodeSetAddUnique(tmp->nodesetval, + ctxt->context->node); + } + valuePush(ctxt, tmp); + ctxt->context->contextSize = oldset->nodeNr; + ctxt->context->proximityPosition = i + 1; + if (op->ch2 != -1) + total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]); + if (ctxt->error != XPATH_EXPRESSION_OK) { + xmlXPathFreeNodeSet(newset); + xmlXPathFreeObject(obj); + return(0); + } + /* + * The result of the evaluation needs to be tested to + * decide whether the filter succeeded or not + */ + res = valuePop(ctxt); + if (xmlXPathEvaluatePredicateResult(ctxt, res)) { + xmlXPathNodeSetAdd(newset, oldset->nodeTab[i]); + } + /* + * Cleanup + */ + if (res != NULL) { + xmlXPathReleaseObject(ctxt->context, res); + } + if (ctxt->value == tmp) { + valuePop(ctxt); + /* + * Don't free the temporary nodeset + * in order to avoid massive recreation inside this + * loop. + */ + xmlXPathNodeSetClear(tmp->nodesetval, 1); + } else + tmp = NULL; + ctxt->context->node = NULL; + /* + * Only put the first node in the result, then leave. + */ + if (newset->nodeNr > 0) { + *first = *(newset->nodeTab); + break; + } + } + if (tmp != NULL) { + xmlXPathReleaseObject(ctxt->context, tmp); + } + /* + * The result is used as the new evaluation set. + */ + xmlXPathReleaseObject(ctxt->context, obj); + ctxt->context->node = NULL; + ctxt->context->contextSize = -1; + ctxt->context->proximityPosition = -1; + /* may want to move this past the '}' later */ + ctxt->context->doc = oldDoc; + valuePush(ctxt, xmlXPathCacheWrapNodeSet(ctxt->context, newset)); + } + ctxt->context->node = oldnode; + return(total); +} +#endif /* XP_OPTIMIZED_FILTER_FIRST */ + +/** + * xmlXPathCompOpEval: + * @ctxt: the XPath parser context with the compiled expression + * @op: an XPath compiled operation + * + * Evaluate the Precompiled XPath operation + * Returns the number of nodes traversed + */ +static int +xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op) +{ + int total = 0; + int equal, ret; + xmlXPathCompExprPtr comp; + xmlXPathObjectPtr arg1, arg2; + xmlNodePtr bak; + xmlDocPtr bakd; + int pp; + int cs; + + CHECK_ERROR0; + comp = ctxt->comp; + switch (op->op) { + case XPATH_OP_END: + return (0); + case XPATH_OP_AND: + bakd = ctxt->context->doc; + bak = ctxt->context->node; + pp = ctxt->context->proximityPosition; + cs = ctxt->context->contextSize; + total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]); + CHECK_ERROR0; + xmlXPathBooleanFunction(ctxt, 1); + if ((ctxt->value == NULL) || (ctxt->value->boolval == 0)) + return (total); + arg2 = valuePop(ctxt); + ctxt->context->doc = bakd; + ctxt->context->node = bak; + ctxt->context->proximityPosition = pp; + ctxt->context->contextSize = cs; + total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]); + if (ctxt->error) { + xmlXPathFreeObject(arg2); + return(0); + } + xmlXPathBooleanFunction(ctxt, 1); + arg1 = valuePop(ctxt); + arg1->boolval &= arg2->boolval; + valuePush(ctxt, arg1); + xmlXPathReleaseObject(ctxt->context, arg2); + return (total); + case XPATH_OP_OR: + bakd = ctxt->context->doc; + bak = ctxt->context->node; + pp = ctxt->context->proximityPosition; + cs = ctxt->context->contextSize; + total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]); + CHECK_ERROR0; + xmlXPathBooleanFunction(ctxt, 1); + if ((ctxt->value == NULL) || (ctxt->value->boolval == 1)) + return (total); + arg2 = valuePop(ctxt); + ctxt->context->doc = bakd; + ctxt->context->node = bak; + ctxt->context->proximityPosition = pp; + ctxt->context->contextSize = cs; + total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]); + if (ctxt->error) { + xmlXPathFreeObject(arg2); + return(0); + } + xmlXPathBooleanFunction(ctxt, 1); + arg1 = valuePop(ctxt); + arg1->boolval |= arg2->boolval; + valuePush(ctxt, arg1); + xmlXPathReleaseObject(ctxt->context, arg2); + return (total); + case XPATH_OP_EQUAL: + bakd = ctxt->context->doc; + bak = ctxt->context->node; + pp = ctxt->context->proximityPosition; + cs = ctxt->context->contextSize; + total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]); + CHECK_ERROR0; + ctxt->context->doc = bakd; + ctxt->context->node = bak; + ctxt->context->proximityPosition = pp; + ctxt->context->contextSize = cs; + total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]); + CHECK_ERROR0; + if (op->value) + equal = xmlXPathEqualValues(ctxt); + else + equal = xmlXPathNotEqualValues(ctxt); + valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt->context, equal)); + return (total); + case XPATH_OP_CMP: + bakd = ctxt->context->doc; + bak = ctxt->context->node; + pp = ctxt->context->proximityPosition; + cs = ctxt->context->contextSize; + total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]); + CHECK_ERROR0; + ctxt->context->doc = bakd; + ctxt->context->node = bak; + ctxt->context->proximityPosition = pp; + ctxt->context->contextSize = cs; + total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]); + CHECK_ERROR0; + ret = xmlXPathCompareValues(ctxt, op->value, op->value2); + valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt->context, ret)); + return (total); + case XPATH_OP_PLUS: + bakd = ctxt->context->doc; + bak = ctxt->context->node; + pp = ctxt->context->proximityPosition; + cs = ctxt->context->contextSize; + total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]); + CHECK_ERROR0; + if (op->ch2 != -1) { + ctxt->context->doc = bakd; + ctxt->context->node = bak; + ctxt->context->proximityPosition = pp; + ctxt->context->contextSize = cs; + total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]); + } + CHECK_ERROR0; + if (op->value == 0) + xmlXPathSubValues(ctxt); + else if (op->value == 1) + xmlXPathAddValues(ctxt); + else if (op->value == 2) + xmlXPathValueFlipSign(ctxt); + else if (op->value == 3) { + CAST_TO_NUMBER; + CHECK_TYPE0(XPATH_NUMBER); + } + return (total); + case XPATH_OP_MULT: + bakd = ctxt->context->doc; + bak = ctxt->context->node; + pp = ctxt->context->proximityPosition; + cs = ctxt->context->contextSize; + total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]); + CHECK_ERROR0; + ctxt->context->doc = bakd; + ctxt->context->node = bak; + ctxt->context->proximityPosition = pp; + ctxt->context->contextSize = cs; + total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]); + CHECK_ERROR0; + if (op->value == 0) + xmlXPathMultValues(ctxt); + else if (op->value == 1) + xmlXPathDivValues(ctxt); + else if (op->value == 2) + xmlXPathModValues(ctxt); + return (total); + case XPATH_OP_UNION: + bakd = ctxt->context->doc; + bak = ctxt->context->node; + pp = ctxt->context->proximityPosition; + cs = ctxt->context->contextSize; + total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]); + CHECK_ERROR0; + ctxt->context->doc = bakd; + ctxt->context->node = bak; + ctxt->context->proximityPosition = pp; + ctxt->context->contextSize = cs; + total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]); + CHECK_ERROR0; + CHECK_TYPE0(XPATH_NODESET); + arg2 = valuePop(ctxt); + + CHECK_TYPE0(XPATH_NODESET); + arg1 = valuePop(ctxt); + + if ((arg1->nodesetval == NULL) || + ((arg2->nodesetval != NULL) && + (arg2->nodesetval->nodeNr != 0))) + { + arg1->nodesetval = xmlXPathNodeSetMerge(arg1->nodesetval, + arg2->nodesetval); + } + + valuePush(ctxt, arg1); + xmlXPathReleaseObject(ctxt->context, arg2); + return (total); + case XPATH_OP_ROOT: + xmlXPathRoot(ctxt); + return (total); + case XPATH_OP_NODE: + if (op->ch1 != -1) + total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]); + CHECK_ERROR0; + if (op->ch2 != -1) + total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]); + CHECK_ERROR0; + valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt->context, + ctxt->context->node)); + return (total); + case XPATH_OP_RESET: + if (op->ch1 != -1) + total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]); + CHECK_ERROR0; + if (op->ch2 != -1) + total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]); + CHECK_ERROR0; + ctxt->context->node = NULL; + return (total); + case XPATH_OP_COLLECT:{ + if (op->ch1 == -1) + return (total); + + total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]); + CHECK_ERROR0; + + total += xmlXPathNodeCollectAndTest(ctxt, op, NULL, NULL, 0); + return (total); + } + case XPATH_OP_VALUE: + valuePush(ctxt, + xmlXPathCacheObjectCopy(ctxt->context, + (xmlXPathObjectPtr) op->value4)); + return (total); + case XPATH_OP_VARIABLE:{ + xmlXPathObjectPtr val; + + if (op->ch1 != -1) + total += + xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]); + if (op->value5 == NULL) { + val = xmlXPathVariableLookup(ctxt->context, op->value4); + if (val == NULL) { + ctxt->error = XPATH_UNDEF_VARIABLE_ERROR; + return(0); + } + valuePush(ctxt, val); + } else { + const xmlChar *URI; + + URI = xmlXPathNsLookup(ctxt->context, op->value5); + if (URI == NULL) { + xmlGenericError(xmlGenericErrorContext, + "xmlXPathCompOpEval: variable %s bound to undefined prefix %s\n", + op->value4, op->value5); + return (total); + } + val = xmlXPathVariableLookupNS(ctxt->context, + op->value4, URI); + if (val == NULL) { + ctxt->error = XPATH_UNDEF_VARIABLE_ERROR; + return(0); + } + valuePush(ctxt, val); + } + return (total); + } + case XPATH_OP_FUNCTION:{ + xmlXPathFunction func; + const xmlChar *oldFunc, *oldFuncURI; + int i; + + if (op->ch1 != -1) + total += + xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]); + if (ctxt->valueNr < op->value) { + xmlGenericError(xmlGenericErrorContext, + "xmlXPathCompOpEval: parameter error\n"); + ctxt->error = XPATH_INVALID_OPERAND; + return (total); + } + for (i = 0; i < op->value; i++) + if (ctxt->valueTab[(ctxt->valueNr - 1) - i] == NULL) { + xmlGenericError(xmlGenericErrorContext, + "xmlXPathCompOpEval: parameter error\n"); + ctxt->error = XPATH_INVALID_OPERAND; + return (total); + } + if (op->cache != NULL) + XML_CAST_FPTR(func) = op->cache; + else { + const xmlChar *URI = NULL; + + if (op->value5 == NULL) + func = + xmlXPathFunctionLookup(ctxt->context, + op->value4); + else { + URI = xmlXPathNsLookup(ctxt->context, op->value5); + if (URI == NULL) { + xmlGenericError(xmlGenericErrorContext, + "xmlXPathCompOpEval: function %s bound to undefined prefix %s\n", + op->value4, op->value5); + return (total); + } + func = xmlXPathFunctionLookupNS(ctxt->context, + op->value4, URI); + } + if (func == NULL) { + xmlGenericError(xmlGenericErrorContext, + "xmlXPathCompOpEval: function %s not found\n", + op->value4); + XP_ERROR0(XPATH_UNKNOWN_FUNC_ERROR); + } + op->cache = XML_CAST_FPTR(func); + op->cacheURI = (void *) URI; + } + oldFunc = ctxt->context->function; + oldFuncURI = ctxt->context->functionURI; + ctxt->context->function = op->value4; + ctxt->context->functionURI = op->cacheURI; + func(ctxt, op->value); + ctxt->context->function = oldFunc; + ctxt->context->functionURI = oldFuncURI; + return (total); + } + case XPATH_OP_ARG: + bakd = ctxt->context->doc; + bak = ctxt->context->node; + pp = ctxt->context->proximityPosition; + cs = ctxt->context->contextSize; + if (op->ch1 != -1) + total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]); + ctxt->context->contextSize = cs; + ctxt->context->proximityPosition = pp; + ctxt->context->node = bak; + ctxt->context->doc = bakd; + CHECK_ERROR0; + if (op->ch2 != -1) { + total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]); + ctxt->context->doc = bakd; + ctxt->context->node = bak; + CHECK_ERROR0; + } + return (total); + case XPATH_OP_PREDICATE: + case XPATH_OP_FILTER:{ + xmlXPathObjectPtr res; + xmlXPathObjectPtr obj, tmp; + xmlNodeSetPtr newset = NULL; + xmlNodeSetPtr oldset; + xmlNodePtr oldnode; + xmlDocPtr oldDoc; + int i; + + /* + * Optimization for ()[1] selection i.e. the first elem + */ + if ((op->ch1 != -1) && (op->ch2 != -1) && +#ifdef XP_OPTIMIZED_FILTER_FIRST + /* + * FILTER TODO: Can we assume that the inner processing + * will result in an ordered list if we have an + * XPATH_OP_FILTER? + * What about an additional field or flag on + * xmlXPathObject like @sorted ? This way we wouln'd need + * to assume anything, so it would be more robust and + * easier to optimize. + */ + ((comp->steps[op->ch1].op == XPATH_OP_SORT) || /* 18 */ + (comp->steps[op->ch1].op == XPATH_OP_FILTER)) && /* 17 */ +#else + (comp->steps[op->ch1].op == XPATH_OP_SORT) && +#endif + (comp->steps[op->ch2].op == XPATH_OP_VALUE)) { /* 12 */ + xmlXPathObjectPtr val; + + val = comp->steps[op->ch2].value4; + if ((val != NULL) && (val->type == XPATH_NUMBER) && + (val->floatval == 1.0)) { + xmlNodePtr first = NULL; + + total += + xmlXPathCompOpEvalFirst(ctxt, + &comp->steps[op->ch1], + &first); + CHECK_ERROR0; + /* + * The nodeset should be in document order, + * Keep only the first value + */ + if ((ctxt->value != NULL) && + (ctxt->value->type == XPATH_NODESET) && + (ctxt->value->nodesetval != NULL) && + (ctxt->value->nodesetval->nodeNr > 1)) + ctxt->value->nodesetval->nodeNr = 1; + return (total); + } + } + /* + * Optimization for ()[last()] selection i.e. the last elem + */ + if ((op->ch1 != -1) && (op->ch2 != -1) && + (comp->steps[op->ch1].op == XPATH_OP_SORT) && + (comp->steps[op->ch2].op == XPATH_OP_SORT)) { + int f = comp->steps[op->ch2].ch1; + + if ((f != -1) && + (comp->steps[f].op == XPATH_OP_FUNCTION) && + (comp->steps[f].value5 == NULL) && + (comp->steps[f].value == 0) && + (comp->steps[f].value4 != NULL) && + (xmlStrEqual + (comp->steps[f].value4, BAD_CAST "last"))) { + xmlNodePtr last = NULL; + + total += + xmlXPathCompOpEvalLast(ctxt, + &comp->steps[op->ch1], + &last); + CHECK_ERROR0; + /* + * The nodeset should be in document order, + * Keep only the last value + */ + if ((ctxt->value != NULL) && + (ctxt->value->type == XPATH_NODESET) && + (ctxt->value->nodesetval != NULL) && + (ctxt->value->nodesetval->nodeTab != NULL) && + (ctxt->value->nodesetval->nodeNr > 1)) { + ctxt->value->nodesetval->nodeTab[0] = + ctxt->value->nodesetval->nodeTab[ctxt-> + value-> + nodesetval-> + nodeNr - + 1]; + ctxt->value->nodesetval->nodeNr = 1; + } + return (total); + } + } + /* + * Process inner predicates first. + * Example "index[parent::book][1]": + * ... + * PREDICATE <-- we are here "[1]" + * PREDICATE <-- process "[parent::book]" first + * SORT + * COLLECT 'parent' 'name' 'node' book + * NODE + * ELEM Object is a number : 1 + */ + if (op->ch1 != -1) + total += + xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]); + CHECK_ERROR0; + if (op->ch2 == -1) + return (total); + if (ctxt->value == NULL) + return (total); + + oldnode = ctxt->context->node; + +#ifdef LIBXML_XPTR_ENABLED + /* + * Hum are we filtering the result of an XPointer expression + */ + if (ctxt->value->type == XPATH_LOCATIONSET) { + xmlLocationSetPtr newlocset = NULL; + xmlLocationSetPtr oldlocset; + + /* + * Extract the old locset, and then evaluate the result of the + * expression for all the element in the locset. use it to grow + * up a new locset. + */ + CHECK_TYPE0(XPATH_LOCATIONSET); + obj = valuePop(ctxt); + oldlocset = obj->user; + ctxt->context->node = NULL; + + if ((oldlocset == NULL) || (oldlocset->locNr == 0)) { + ctxt->context->contextSize = 0; + ctxt->context->proximityPosition = 0; + if (op->ch2 != -1) + total += + xmlXPathCompOpEval(ctxt, + &comp->steps[op->ch2]); + res = valuePop(ctxt); + if (res != NULL) { + xmlXPathReleaseObject(ctxt->context, res); + } + valuePush(ctxt, obj); + CHECK_ERROR0; + return (total); + } + newlocset = xmlXPtrLocationSetCreate(NULL); + + for (i = 0; i < oldlocset->locNr; i++) { + /* + * Run the evaluation with a node list made of a + * single item in the nodelocset. + */ + ctxt->context->node = oldlocset->locTab[i]->user; + ctxt->context->contextSize = oldlocset->locNr; + ctxt->context->proximityPosition = i + 1; + tmp = xmlXPathCacheNewNodeSet(ctxt->context, + ctxt->context->node); + valuePush(ctxt, tmp); + + if (op->ch2 != -1) + total += + xmlXPathCompOpEval(ctxt, + &comp->steps[op->ch2]); + if (ctxt->error != XPATH_EXPRESSION_OK) { + xmlXPathFreeObject(obj); + return(0); + } + + /* + * The result of the evaluation need to be tested to + * decided whether the filter succeeded or not + */ + res = valuePop(ctxt); + if (xmlXPathEvaluatePredicateResult(ctxt, res)) { + xmlXPtrLocationSetAdd(newlocset, + xmlXPathObjectCopy + (oldlocset->locTab[i])); + } + + /* + * Cleanup + */ + if (res != NULL) { + xmlXPathReleaseObject(ctxt->context, res); + } + if (ctxt->value == tmp) { + res = valuePop(ctxt); + xmlXPathReleaseObject(ctxt->context, res); + } + + ctxt->context->node = NULL; + } + + /* + * The result is used as the new evaluation locset. + */ + xmlXPathReleaseObject(ctxt->context, obj); + ctxt->context->node = NULL; + ctxt->context->contextSize = -1; + ctxt->context->proximityPosition = -1; + valuePush(ctxt, xmlXPtrWrapLocationSet(newlocset)); + ctxt->context->node = oldnode; + return (total); + } +#endif /* LIBXML_XPTR_ENABLED */ + + /* + * Extract the old set, and then evaluate the result of the + * expression for all the element in the set. use it to grow + * up a new set. + */ + CHECK_TYPE0(XPATH_NODESET); + obj = valuePop(ctxt); + oldset = obj->nodesetval; + + oldnode = ctxt->context->node; + oldDoc = ctxt->context->doc; + ctxt->context->node = NULL; + + if ((oldset == NULL) || (oldset->nodeNr == 0)) { + ctxt->context->contextSize = 0; + ctxt->context->proximityPosition = 0; +/* + if (op->ch2 != -1) + total += + xmlXPathCompOpEval(ctxt, + &comp->steps[op->ch2]); + CHECK_ERROR0; + res = valuePop(ctxt); + if (res != NULL) + xmlXPathFreeObject(res); +*/ + valuePush(ctxt, obj); + ctxt->context->node = oldnode; + CHECK_ERROR0; + } else { + tmp = NULL; + /* + * Initialize the new set. + * Also set the xpath document in case things like + * key() evaluation are attempted on the predicate + */ + newset = xmlXPathNodeSetCreate(NULL); + /* + * SPEC XPath 1.0: + * "For each node in the node-set to be filtered, the + * PredicateExpr is evaluated with that node as the + * context node, with the number of nodes in the + * node-set as the context size, and with the proximity + * position of the node in the node-set with respect to + * the axis as the context position;" + * @oldset is the node-set" to be filtered. + * + * SPEC XPath 1.0: + * "only predicates change the context position and + * context size (see [2.4 Predicates])." + * Example: + * node-set context pos + * nA 1 + * nB 2 + * nC 3 + * After applying predicate [position() > 1] : + * node-set context pos + * nB 1 + * nC 2 + * + * removed the first node in the node-set, then + * the context position of the + */ + for (i = 0; i < oldset->nodeNr; i++) { + /* + * Run the evaluation with a node list made of + * a single item in the nodeset. + */ + ctxt->context->node = oldset->nodeTab[i]; + if ((oldset->nodeTab[i]->type != XML_NAMESPACE_DECL) && + (oldset->nodeTab[i]->doc != NULL)) + ctxt->context->doc = oldset->nodeTab[i]->doc; + if (tmp == NULL) { + tmp = xmlXPathCacheNewNodeSet(ctxt->context, + ctxt->context->node); + } else { + xmlXPathNodeSetAddUnique(tmp->nodesetval, + ctxt->context->node); + } + valuePush(ctxt, tmp); + ctxt->context->contextSize = oldset->nodeNr; + ctxt->context->proximityPosition = i + 1; + /* + * Evaluate the predicate against the context node. + * Can/should we optimize position() predicates + * here (e.g. "[1]")? + */ + if (op->ch2 != -1) + total += + xmlXPathCompOpEval(ctxt, + &comp->steps[op->ch2]); + if (ctxt->error != XPATH_EXPRESSION_OK) { + xmlXPathFreeNodeSet(newset); + xmlXPathFreeObject(obj); + return(0); + } + + /* + * The result of the evaluation needs to be tested to + * decide whether the filter succeeded or not + */ + /* + * OPTIMIZE TODO: Can we use + * xmlXPathNodeSetAdd*Unique()* instead? + */ + res = valuePop(ctxt); + if (xmlXPathEvaluatePredicateResult(ctxt, res)) { + xmlXPathNodeSetAdd(newset, oldset->nodeTab[i]); + } + + /* + * Cleanup + */ + if (res != NULL) { + xmlXPathReleaseObject(ctxt->context, res); + } + if (ctxt->value == tmp) { + valuePop(ctxt); + xmlXPathNodeSetClear(tmp->nodesetval, 1); + /* + * Don't free the temporary nodeset + * in order to avoid massive recreation inside this + * loop. + */ + } else + tmp = NULL; + ctxt->context->node = NULL; + } + if (tmp != NULL) + xmlXPathReleaseObject(ctxt->context, tmp); + /* + * The result is used as the new evaluation set. + */ + xmlXPathReleaseObject(ctxt->context, obj); + ctxt->context->node = NULL; + ctxt->context->contextSize = -1; + ctxt->context->proximityPosition = -1; + /* may want to move this past the '}' later */ + ctxt->context->doc = oldDoc; + valuePush(ctxt, + xmlXPathCacheWrapNodeSet(ctxt->context, newset)); + } + ctxt->context->node = oldnode; + return (total); + } + case XPATH_OP_SORT: + if (op->ch1 != -1) + total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]); + CHECK_ERROR0; + if ((ctxt->value != NULL) && + (ctxt->value->type == XPATH_NODESET) && + (ctxt->value->nodesetval != NULL) && + (ctxt->value->nodesetval->nodeNr > 1)) + { + xmlXPathNodeSetSort(ctxt->value->nodesetval); + } + return (total); +#ifdef LIBXML_XPTR_ENABLED + case XPATH_OP_RANGETO:{ + xmlXPathObjectPtr range; + xmlXPathObjectPtr res, obj; + xmlXPathObjectPtr tmp; + xmlLocationSetPtr newlocset = NULL; + xmlLocationSetPtr oldlocset; + xmlNodeSetPtr oldset; + int i, j; + + if (op->ch1 != -1) + total += + xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]); + if (op->ch2 == -1) + return (total); + + if (ctxt->value->type == XPATH_LOCATIONSET) { + /* + * Extract the old locset, and then evaluate the result of the + * expression for all the element in the locset. use it to grow + * up a new locset. + */ + CHECK_TYPE0(XPATH_LOCATIONSET); + obj = valuePop(ctxt); + oldlocset = obj->user; + + if ((oldlocset == NULL) || (oldlocset->locNr == 0)) { + ctxt->context->node = NULL; + ctxt->context->contextSize = 0; + ctxt->context->proximityPosition = 0; + total += xmlXPathCompOpEval(ctxt,&comp->steps[op->ch2]); + res = valuePop(ctxt); + if (res != NULL) { + xmlXPathReleaseObject(ctxt->context, res); + } + valuePush(ctxt, obj); + CHECK_ERROR0; + return (total); + } + newlocset = xmlXPtrLocationSetCreate(NULL); + + for (i = 0; i < oldlocset->locNr; i++) { + /* + * Run the evaluation with a node list made of a + * single item in the nodelocset. + */ + ctxt->context->node = oldlocset->locTab[i]->user; + ctxt->context->contextSize = oldlocset->locNr; + ctxt->context->proximityPosition = i + 1; + tmp = xmlXPathCacheNewNodeSet(ctxt->context, + ctxt->context->node); + valuePush(ctxt, tmp); + + if (op->ch2 != -1) + total += + xmlXPathCompOpEval(ctxt, + &comp->steps[op->ch2]); + if (ctxt->error != XPATH_EXPRESSION_OK) { + xmlXPathFreeObject(obj); + return(0); + } + + res = valuePop(ctxt); + if (res->type == XPATH_LOCATIONSET) { + xmlLocationSetPtr rloc = + (xmlLocationSetPtr)res->user; + for (j=0; jlocNr; j++) { + range = xmlXPtrNewRange( + oldlocset->locTab[i]->user, + oldlocset->locTab[i]->index, + rloc->locTab[j]->user2, + rloc->locTab[j]->index2); + if (range != NULL) { + xmlXPtrLocationSetAdd(newlocset, range); + } + } + } else { + range = xmlXPtrNewRangeNodeObject( + (xmlNodePtr)oldlocset->locTab[i]->user, res); + if (range != NULL) { + xmlXPtrLocationSetAdd(newlocset,range); + } + } + + /* + * Cleanup + */ + if (res != NULL) { + xmlXPathReleaseObject(ctxt->context, res); + } + if (ctxt->value == tmp) { + res = valuePop(ctxt); + xmlXPathReleaseObject(ctxt->context, res); + } + + ctxt->context->node = NULL; + } + } else { /* Not a location set */ + CHECK_TYPE0(XPATH_NODESET); + obj = valuePop(ctxt); + oldset = obj->nodesetval; + ctxt->context->node = NULL; + + newlocset = xmlXPtrLocationSetCreate(NULL); + + if (oldset != NULL) { + for (i = 0; i < oldset->nodeNr; i++) { + /* + * Run the evaluation with a node list made of a single item + * in the nodeset. + */ + ctxt->context->node = oldset->nodeTab[i]; + /* + * OPTIMIZE TODO: Avoid recreation for every iteration. + */ + tmp = xmlXPathCacheNewNodeSet(ctxt->context, + ctxt->context->node); + valuePush(ctxt, tmp); + + if (op->ch2 != -1) + total += + xmlXPathCompOpEval(ctxt, + &comp->steps[op->ch2]); + if (ctxt->error != XPATH_EXPRESSION_OK) { + xmlXPathFreeObject(obj); + return(0); + } + + res = valuePop(ctxt); + range = + xmlXPtrNewRangeNodeObject(oldset->nodeTab[i], + res); + if (range != NULL) { + xmlXPtrLocationSetAdd(newlocset, range); + } + + /* + * Cleanup + */ + if (res != NULL) { + xmlXPathReleaseObject(ctxt->context, res); + } + if (ctxt->value == tmp) { + res = valuePop(ctxt); + xmlXPathReleaseObject(ctxt->context, res); + } + + ctxt->context->node = NULL; + } + } + } + + /* + * The result is used as the new evaluation set. + */ + xmlXPathReleaseObject(ctxt->context, obj); + ctxt->context->node = NULL; + ctxt->context->contextSize = -1; + ctxt->context->proximityPosition = -1; + valuePush(ctxt, xmlXPtrWrapLocationSet(newlocset)); + return (total); + } +#endif /* LIBXML_XPTR_ENABLED */ + } + xmlGenericError(xmlGenericErrorContext, + "XPath: unknown precompiled operation %d\n", op->op); + return (total); +} + +/** + * xmlXPathCompOpEvalToBoolean: + * @ctxt: the XPath parser context + * + * Evaluates if the expression evaluates to true. + * + * Returns 1 if true, 0 if false and -1 on API or internal errors. + */ +static int +xmlXPathCompOpEvalToBoolean(xmlXPathParserContextPtr ctxt, + xmlXPathStepOpPtr op, + int isPredicate) +{ + xmlXPathObjectPtr resObj = NULL; + +start: + /* comp = ctxt->comp; */ + switch (op->op) { + case XPATH_OP_END: + return (0); + case XPATH_OP_VALUE: + resObj = (xmlXPathObjectPtr) op->value4; + if (isPredicate) + return(xmlXPathEvaluatePredicateResult(ctxt, resObj)); + return(xmlXPathCastToBoolean(resObj)); + case XPATH_OP_SORT: + /* + * We don't need sorting for boolean results. Skip this one. + */ + if (op->ch1 != -1) { + op = &ctxt->comp->steps[op->ch1]; + goto start; + } + return(0); + case XPATH_OP_COLLECT: + if (op->ch1 == -1) + return(0); + + xmlXPathCompOpEval(ctxt, &ctxt->comp->steps[op->ch1]); + if (ctxt->error != XPATH_EXPRESSION_OK) + return(-1); + + xmlXPathNodeCollectAndTest(ctxt, op, NULL, NULL, 1); + if (ctxt->error != XPATH_EXPRESSION_OK) + return(-1); + + resObj = valuePop(ctxt); + if (resObj == NULL) + return(-1); + break; + default: + /* + * Fallback to call xmlXPathCompOpEval(). + */ + xmlXPathCompOpEval(ctxt, op); + if (ctxt->error != XPATH_EXPRESSION_OK) + return(-1); + + resObj = valuePop(ctxt); + if (resObj == NULL) + return(-1); + break; + } + + if (resObj) { + int res; + + if (resObj->type == XPATH_BOOLEAN) { + res = resObj->boolval; + } else if (isPredicate) { + /* + * For predicates a result of type "number" is handled + * differently: + * SPEC XPath 1.0: + * "If the result is a number, the result will be converted + * to true if the number is equal to the context position + * and will be converted to false otherwise;" + */ + res = xmlXPathEvaluatePredicateResult(ctxt, resObj); + } else { + res = xmlXPathCastToBoolean(resObj); + } + xmlXPathReleaseObject(ctxt->context, resObj); + return(res); + } + + return(0); +} + +#ifdef XPATH_STREAMING +/** + * xmlXPathRunStreamEval: + * @ctxt: the XPath parser context with the compiled expression + * + * Evaluate the Precompiled Streamable XPath expression in the given context. + */ +static int +xmlXPathRunStreamEval(xmlXPathContextPtr ctxt, xmlPatternPtr comp, + xmlXPathObjectPtr *resultSeq, int toBool) +{ + int max_depth, min_depth; + int from_root; + int ret, depth; + int eval_all_nodes; + xmlNodePtr cur = NULL, limit = NULL; + xmlStreamCtxtPtr patstream = NULL; + + int nb_nodes = 0; + + if ((ctxt == NULL) || (comp == NULL)) + return(-1); + max_depth = xmlPatternMaxDepth(comp); + if (max_depth == -1) + return(-1); + if (max_depth == -2) + max_depth = 10000; + min_depth = xmlPatternMinDepth(comp); + if (min_depth == -1) + return(-1); + from_root = xmlPatternFromRoot(comp); + if (from_root < 0) + return(-1); +#if 0 + printf("stream eval: depth %d from root %d\n", max_depth, from_root); +#endif + + if (! toBool) { + if (resultSeq == NULL) + return(-1); + *resultSeq = xmlXPathCacheNewNodeSet(ctxt, NULL); + if (*resultSeq == NULL) + return(-1); + } + + /* + * handle the special cases of "/" amd "." being matched + */ + if (min_depth == 0) { + if (from_root) { + /* Select "/" */ + if (toBool) + return(1); + xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval, + (xmlNodePtr) ctxt->doc); + } else { + /* Select "self::node()" */ + if (toBool) + return(1); + xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval, ctxt->node); + } + } + if (max_depth == 0) { + return(0); + } + + if (from_root) { + cur = (xmlNodePtr)ctxt->doc; + } else if (ctxt->node != NULL) { + switch (ctxt->node->type) { + case XML_ELEMENT_NODE: + case XML_DOCUMENT_NODE: + case XML_DOCUMENT_FRAG_NODE: + case XML_HTML_DOCUMENT_NODE: +#ifdef LIBXML_DOCB_ENABLED + case XML_DOCB_DOCUMENT_NODE: +#endif + cur = ctxt->node; + break; + case XML_ATTRIBUTE_NODE: + case XML_TEXT_NODE: + case XML_CDATA_SECTION_NODE: + case XML_ENTITY_REF_NODE: + case XML_ENTITY_NODE: + case XML_PI_NODE: + case XML_COMMENT_NODE: + case XML_NOTATION_NODE: + case XML_DTD_NODE: + case XML_DOCUMENT_TYPE_NODE: + case XML_ELEMENT_DECL: + case XML_ATTRIBUTE_DECL: + case XML_ENTITY_DECL: + case XML_NAMESPACE_DECL: + case XML_XINCLUDE_START: + case XML_XINCLUDE_END: + break; + } + limit = cur; + } + if (cur == NULL) { + return(0); + } + + patstream = xmlPatternGetStreamCtxt(comp); + if (patstream == NULL) { + /* + * QUESTION TODO: Is this an error? + */ + return(0); + } + + eval_all_nodes = xmlStreamWantsAnyNode(patstream); + + if (from_root) { + ret = xmlStreamPush(patstream, NULL, NULL); + if (ret < 0) { + } else if (ret == 1) { + if (toBool) + goto return_1; + xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval, cur); + } + } + depth = 0; + goto scan_children; +next_node: + do { + nb_nodes++; + + switch (cur->type) { + case XML_ELEMENT_NODE: + case XML_TEXT_NODE: + case XML_CDATA_SECTION_NODE: + case XML_COMMENT_NODE: + case XML_PI_NODE: + if (cur->type == XML_ELEMENT_NODE) { + ret = xmlStreamPush(patstream, cur->name, + (cur->ns ? cur->ns->href : NULL)); + } else if (eval_all_nodes) + ret = xmlStreamPushNode(patstream, NULL, NULL, cur->type); + else + break; + + if (ret < 0) { + /* NOP. */ + } else if (ret == 1) { + if (toBool) + goto return_1; + xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval, cur); + } + if ((cur->children == NULL) || (depth >= max_depth)) { + ret = xmlStreamPop(patstream); + while (cur->next != NULL) { + cur = cur->next; + if ((cur->type != XML_ENTITY_DECL) && + (cur->type != XML_DTD_NODE)) + goto next_node; + } + } + default: + break; + } + +scan_children: + if ((cur->children != NULL) && (depth < max_depth)) { + /* + * Do not descend on entities declarations + */ + if (cur->children->type != XML_ENTITY_DECL) { + cur = cur->children; + depth++; + /* + * Skip DTDs + */ + if (cur->type != XML_DTD_NODE) + continue; + } + } + + if (cur == limit) + break; + + while (cur->next != NULL) { + cur = cur->next; + if ((cur->type != XML_ENTITY_DECL) && + (cur->type != XML_DTD_NODE)) + goto next_node; + } + + do { + cur = cur->parent; + depth--; + if ((cur == NULL) || (cur == limit)) + goto done; + if (cur->type == XML_ELEMENT_NODE) { + ret = xmlStreamPop(patstream); + } else if ((eval_all_nodes) && + ((cur->type == XML_TEXT_NODE) || + (cur->type == XML_CDATA_SECTION_NODE) || + (cur->type == XML_COMMENT_NODE) || + (cur->type == XML_PI_NODE))) + { + ret = xmlStreamPop(patstream); + } + if (cur->next != NULL) { + cur = cur->next; + break; + } + } while (cur != NULL); + + } while ((cur != NULL) && (depth >= 0)); + +done: + +#if 0 + printf("stream eval: checked %d nodes selected %d\n", + nb_nodes, retObj->nodesetval->nodeNr); +#endif + + if (patstream) + xmlFreeStreamCtxt(patstream); + return(0); + +return_1: + if (patstream) + xmlFreeStreamCtxt(patstream); + return(1); +} +#endif /* XPATH_STREAMING */ + +/** + * xmlXPathRunEval: + * @ctxt: the XPath parser context with the compiled expression + * @toBool: evaluate to a boolean result + * + * Evaluate the Precompiled XPath expression in the given context. + */ +static int +xmlXPathRunEval(xmlXPathParserContextPtr ctxt, int toBool) +{ + xmlXPathCompExprPtr comp; + + if ((ctxt == NULL) || (ctxt->comp == NULL)) + return(-1); + + if (ctxt->valueTab == NULL) { + /* Allocate the value stack */ + ctxt->valueTab = (xmlXPathObjectPtr *) + xmlMalloc(10 * sizeof(xmlXPathObjectPtr)); + if (ctxt->valueTab == NULL) { + xmlXPathPErrMemory(ctxt, "creating evaluation context\n"); + xmlFree(ctxt); + } + ctxt->valueNr = 0; + ctxt->valueMax = 10; + ctxt->value = NULL; + } +#ifdef XPATH_STREAMING + if (ctxt->comp->stream) { + int res; + + if (toBool) { + /* + * Evaluation to boolean result. + */ + res = xmlXPathRunStreamEval(ctxt->context, + ctxt->comp->stream, NULL, 1); + if (res != -1) + return(res); + } else { + xmlXPathObjectPtr resObj = NULL; + + /* + * Evaluation to a sequence. + */ + res = xmlXPathRunStreamEval(ctxt->context, + ctxt->comp->stream, &resObj, 0); + + if ((res != -1) && (resObj != NULL)) { + valuePush(ctxt, resObj); + return(0); + } + if (resObj != NULL) + xmlXPathReleaseObject(ctxt->context, resObj); + } + /* + * QUESTION TODO: This falls back to normal XPath evaluation + * if res == -1. Is this intended? + */ + } +#endif + comp = ctxt->comp; + if (comp->last < 0) { + xmlGenericError(xmlGenericErrorContext, + "xmlXPathRunEval: last is less than zero\n"); + return(-1); + } + if (toBool) + return(xmlXPathCompOpEvalToBoolean(ctxt, + &comp->steps[comp->last], 0)); + else + xmlXPathCompOpEval(ctxt, &comp->steps[comp->last]); + + return(0); +} + +/************************************************************************ + * * + * Public interfaces * + * * + ************************************************************************/ + +/** + * xmlXPathEvalPredicate: + * @ctxt: the XPath context + * @res: the Predicate Expression evaluation result + * + * Evaluate a predicate result for the current node. + * A PredicateExpr is evaluated by evaluating the Expr and converting + * the result to a boolean. If the result is a number, the result will + * be converted to true if the number is equal to the position of the + * context node in the context node list (as returned by the position + * function) and will be converted to false otherwise; if the result + * is not a number, then the result will be converted as if by a call + * to the boolean function. + * + * Returns 1 if predicate is true, 0 otherwise + */ +int +xmlXPathEvalPredicate(xmlXPathContextPtr ctxt, xmlXPathObjectPtr res) { + if ((ctxt == NULL) || (res == NULL)) return(0); + switch (res->type) { + case XPATH_BOOLEAN: + return(res->boolval); + case XPATH_NUMBER: + return(res->floatval == ctxt->proximityPosition); + case XPATH_NODESET: + case XPATH_XSLT_TREE: + if (res->nodesetval == NULL) + return(0); + return(res->nodesetval->nodeNr != 0); + case XPATH_STRING: + return((res->stringval != NULL) && + (xmlStrlen(res->stringval) != 0)); + default: + STRANGE + } + return(0); +} + +/** + * xmlXPathEvaluatePredicateResult: + * @ctxt: the XPath Parser context + * @res: the Predicate Expression evaluation result + * + * Evaluate a predicate result for the current node. + * A PredicateExpr is evaluated by evaluating the Expr and converting + * the result to a boolean. If the result is a number, the result will + * be converted to true if the number is equal to the position of the + * context node in the context node list (as returned by the position + * function) and will be converted to false otherwise; if the result + * is not a number, then the result will be converted as if by a call + * to the boolean function. + * + * Returns 1 if predicate is true, 0 otherwise + */ +int +xmlXPathEvaluatePredicateResult(xmlXPathParserContextPtr ctxt, + xmlXPathObjectPtr res) { + if ((ctxt == NULL) || (res == NULL)) return(0); + switch (res->type) { + case XPATH_BOOLEAN: + return(res->boolval); + case XPATH_NUMBER: +#if defined(__BORLANDC__) || (defined(_MSC_VER) && (_MSC_VER == 1200)) + return((res->floatval == ctxt->context->proximityPosition) && + (!xmlXPathIsNaN(res->floatval))); /* MSC pbm Mark Vakoc !*/ +#else + return(res->floatval == ctxt->context->proximityPosition); +#endif + case XPATH_NODESET: + case XPATH_XSLT_TREE: + if (res->nodesetval == NULL) + return(0); + return(res->nodesetval->nodeNr != 0); + case XPATH_STRING: + return((res->stringval != NULL) && (res->stringval[0] != 0)); +#ifdef LIBXML_XPTR_ENABLED + case XPATH_LOCATIONSET:{ + xmlLocationSetPtr ptr = res->user; + if (ptr == NULL) + return(0); + return (ptr->locNr != 0); + } +#endif + default: + STRANGE + } + return(0); +} + +#ifdef XPATH_STREAMING +/** + * xmlXPathTryStreamCompile: + * @ctxt: an XPath context + * @str: the XPath expression + * + * Try to compile the XPath expression as a streamable subset. + * + * Returns the compiled expression or NULL if failed to compile. + */ +static xmlXPathCompExprPtr +xmlXPathTryStreamCompile(xmlXPathContextPtr ctxt, const xmlChar *str) { + /* + * Optimization: use streaming patterns when the XPath expression can + * be compiled to a stream lookup + */ + xmlPatternPtr stream; + xmlXPathCompExprPtr comp; + xmlDictPtr dict = NULL; + const xmlChar **namespaces = NULL; + xmlNsPtr ns; + int i, j; + + if ((!xmlStrchr(str, '[')) && (!xmlStrchr(str, '(')) && + (!xmlStrchr(str, '@'))) { + const xmlChar *tmp; + + /* + * We don't try to handle expressions using the verbose axis + * specifiers ("::"), just the simplied form at this point. + * Additionally, if there is no list of namespaces available and + * there's a ":" in the expression, indicating a prefixed QName, + * then we won't try to compile either. xmlPatterncompile() needs + * to have a list of namespaces at compilation time in order to + * compile prefixed name tests. + */ + tmp = xmlStrchr(str, ':'); + if ((tmp != NULL) && + ((ctxt == NULL) || (ctxt->nsNr == 0) || (tmp[1] == ':'))) + return(NULL); + + if (ctxt != NULL) { + dict = ctxt->dict; + if (ctxt->nsNr > 0) { + namespaces = xmlMalloc(2 * (ctxt->nsNr + 1) * sizeof(xmlChar*)); + if (namespaces == NULL) { + xmlXPathErrMemory(ctxt, "allocating namespaces array\n"); + return(NULL); + } + for (i = 0, j = 0; (j < ctxt->nsNr); j++) { + ns = ctxt->namespaces[j]; + namespaces[i++] = ns->href; + namespaces[i++] = ns->prefix; + } + namespaces[i++] = NULL; + namespaces[i++] = NULL; + } + } + + stream = xmlPatterncompile(str, dict, XML_PATTERN_XPATH, + &namespaces[0]); + if (namespaces != NULL) { + xmlFree((xmlChar **)namespaces); + } + if ((stream != NULL) && (xmlPatternStreamable(stream) == 1)) { + comp = xmlXPathNewCompExpr(); + if (comp == NULL) { + xmlXPathErrMemory(ctxt, "allocating streamable expression\n"); + return(NULL); + } + comp->stream = stream; + comp->dict = dict; + if (comp->dict) + xmlDictReference(comp->dict); + return(comp); + } + xmlFreePattern(stream); + } + return(NULL); +} +#endif /* XPATH_STREAMING */ + +static int +xmlXPathCanRewriteDosExpression(xmlChar *expr) +{ + if (expr == NULL) + return(0); + do { + if ((*expr == '/') && (*(++expr) == '/')) + return(1); + } while (*expr++); + return(0); +} +static void +xmlXPathRewriteDOSExpression(xmlXPathCompExprPtr comp, xmlXPathStepOpPtr op) +{ + /* + * Try to rewrite "descendant-or-self::node()/foo" to an optimized + * internal representation. + */ + if (op->ch1 != -1) { + if ((op->op == XPATH_OP_COLLECT /* 11 */) && + ((xmlXPathAxisVal) op->value == AXIS_CHILD /* 4 */) && + ((xmlXPathTestVal) op->value2 == NODE_TEST_NAME /* 5 */) && + ((xmlXPathTypeVal) op->value3 == NODE_TYPE_NODE /* 0 */)) + { + /* + * This is a "child::foo" + */ + xmlXPathStepOpPtr prevop = &comp->steps[op->ch1]; + + if ((prevop->op == XPATH_OP_COLLECT /* 11 */) && + (prevop->ch1 != -1) && + ((xmlXPathAxisVal) prevop->value == + AXIS_DESCENDANT_OR_SELF) && + (prevop->ch2 == -1) && + ((xmlXPathTestVal) prevop->value2 == NODE_TEST_TYPE) && + ((xmlXPathTypeVal) prevop->value3 == NODE_TYPE_NODE) && + (comp->steps[prevop->ch1].op == XPATH_OP_ROOT)) + { + /* + * This is a "/descendant-or-self::node()" without predicates. + * Eliminate it. + */ + op->ch1 = prevop->ch1; + op->rewriteType = XP_REWRITE_DOS_CHILD_ELEM; + } + } + if (op->ch1 != -1) + xmlXPathRewriteDOSExpression(comp, &comp->steps[op->ch1]); + } + if (op->ch2 != -1) + xmlXPathRewriteDOSExpression(comp, &comp->steps[op->ch2]); +} + +/** + * xmlXPathCtxtCompile: + * @ctxt: an XPath context + * @str: the XPath expression + * + * Compile an XPath expression + * + * Returns the xmlXPathCompExprPtr resulting from the compilation or NULL. + * the caller has to free the object. + */ +xmlXPathCompExprPtr +xmlXPathCtxtCompile(xmlXPathContextPtr ctxt, const xmlChar *str) { + xmlXPathParserContextPtr pctxt; + xmlXPathCompExprPtr comp; + +#ifdef XPATH_STREAMING + comp = xmlXPathTryStreamCompile(ctxt, str); + if (comp != NULL) + return(comp); +#endif + + xmlXPathInit(); + + pctxt = xmlXPathNewParserContext(str, ctxt); + xmlXPathCompileExpr(pctxt, 1); + + if( pctxt->error != XPATH_EXPRESSION_OK ) + { + xmlXPathFreeParserContext(pctxt); + return(NULL); + } + + if (*pctxt->cur != 0) { + /* + * aleksey: in some cases this line prints *second* error message + * (see bug #78858) and probably this should be fixed. + * However, we are not sure that all error messages are printed + * out in other places. It's not critical so we leave it as-is for now + */ + xmlXPatherror(pctxt, __FILE__, __LINE__, XPATH_EXPR_ERROR); + comp = NULL; + } else { + comp = pctxt->comp; + pctxt->comp = NULL; + } + xmlXPathFreeParserContext(pctxt); + + if (comp != NULL) { + comp->expr = xmlStrdup(str); +#ifdef DEBUG_EVAL_COUNTS + comp->string = xmlStrdup(str); + comp->nb = 0; +#endif + if ((comp->expr != NULL) && + (comp->nbStep > 2) && + (comp->last >= 0) && + (xmlXPathCanRewriteDosExpression(comp->expr) == 1)) + { + xmlXPathRewriteDOSExpression(comp, &comp->steps[comp->last]); + } + } + return(comp); +} + +/** + * xmlXPathCompile: + * @str: the XPath expression + * + * Compile an XPath expression + * + * Returns the xmlXPathCompExprPtr resulting from the compilation or NULL. + * the caller has to free the object. + */ +xmlXPathCompExprPtr +xmlXPathCompile(const xmlChar *str) { + return(xmlXPathCtxtCompile(NULL, str)); +} + +/** + * xmlXPathCompiledEvalInternal: + * @comp: the compiled XPath expression + * @ctxt: the XPath context + * @resObj: the resulting XPath object or NULL + * @toBool: 1 if only a boolean result is requested + * + * Evaluate the Precompiled XPath expression in the given context. + * The caller has to free @resObj. + * + * Returns the xmlXPathObjectPtr resulting from the evaluation or NULL. + * the caller has to free the object. + */ +static int +xmlXPathCompiledEvalInternal(xmlXPathCompExprPtr comp, + xmlXPathContextPtr ctxt, + xmlXPathObjectPtr *resObj, + int toBool) +{ + xmlXPathParserContextPtr pctxt; +#ifndef LIBXML_THREAD_ENABLED + static int reentance = 0; +#endif + int res; + + CHECK_CTXT_NEG(ctxt) + + if (comp == NULL) + return(-1); + xmlXPathInit(); + +#ifndef LIBXML_THREAD_ENABLED + reentance++; + if (reentance > 1) + xmlXPathDisableOptimizer = 1; +#endif + +#ifdef DEBUG_EVAL_COUNTS + comp->nb++; + if ((comp->string != NULL) && (comp->nb > 100)) { + fprintf(stderr, "100 x %s\n", comp->string); + comp->nb = 0; + } +#endif + pctxt = xmlXPathCompParserContext(comp, ctxt); + res = xmlXPathRunEval(pctxt, toBool); + + if (resObj) { + if (pctxt->value == NULL) { + xmlGenericError(xmlGenericErrorContext, + "xmlXPathCompiledEval: evaluation failed\n"); + *resObj = NULL; + } else { + *resObj = valuePop(pctxt); + } + } + + /* + * Pop all remaining objects from the stack. + */ + if (pctxt->valueNr > 0) { + xmlXPathObjectPtr tmp; + int stack = 0; + + do { + tmp = valuePop(pctxt); + if (tmp != NULL) { + if (tmp != NULL) + stack++; + xmlXPathReleaseObject(ctxt, tmp); + } + } while (tmp != NULL); + if ((stack != 0) && + ((toBool) || ((resObj) && (*resObj)))) + { + xmlGenericError(xmlGenericErrorContext, + "xmlXPathCompiledEval: %d objects left on the stack.\n", + stack); + } + } + + if ((pctxt->error != XPATH_EXPRESSION_OK) && (resObj) && (*resObj)) { + xmlXPathFreeObject(*resObj); + *resObj = NULL; + } + pctxt->comp = NULL; + xmlXPathFreeParserContext(pctxt); +#ifndef LIBXML_THREAD_ENABLED + reentance--; +#endif + + return(res); +} + +/** + * xmlXPathCompiledEval: + * @comp: the compiled XPath expression + * @ctx: the XPath context + * + * Evaluate the Precompiled XPath expression in the given context. + * + * Returns the xmlXPathObjectPtr resulting from the evaluation or NULL. + * the caller has to free the object. + */ +xmlXPathObjectPtr +xmlXPathCompiledEval(xmlXPathCompExprPtr comp, xmlXPathContextPtr ctx) +{ + xmlXPathObjectPtr res = NULL; + + xmlXPathCompiledEvalInternal(comp, ctx, &res, 0); + return(res); +} + +/** + * xmlXPathCompiledEvalToBoolean: + * @comp: the compiled XPath expression + * @ctxt: the XPath context + * + * Applies the XPath boolean() function on the result of the given + * compiled expression. + * + * Returns 1 if the expression evaluated to true, 0 if to false and + * -1 in API and internal errors. + */ +int +xmlXPathCompiledEvalToBoolean(xmlXPathCompExprPtr comp, + xmlXPathContextPtr ctxt) +{ + return(xmlXPathCompiledEvalInternal(comp, ctxt, NULL, 1)); +} + +/** + * xmlXPathEvalExpr: + * @ctxt: the XPath Parser context + * + * Parse and evaluate an XPath expression in the given context, + * then push the result on the context stack + */ +void +xmlXPathEvalExpr(xmlXPathParserContextPtr ctxt) { +#ifdef XPATH_STREAMING + xmlXPathCompExprPtr comp; +#endif + + if (ctxt == NULL) return; + +#ifdef XPATH_STREAMING + comp = xmlXPathTryStreamCompile(ctxt->context, ctxt->base); + if (comp != NULL) { + if (ctxt->comp != NULL) + xmlXPathFreeCompExpr(ctxt->comp); + ctxt->comp = comp; + if (ctxt->cur != NULL) + while (*ctxt->cur != 0) ctxt->cur++; + } else +#endif + { + xmlXPathCompileExpr(ctxt, 1); + /* + * In this scenario the expression string will sit in ctxt->base. + */ + if ((ctxt->error == XPATH_EXPRESSION_OK) && + (ctxt->comp != NULL) && + (ctxt->base != NULL) && + (ctxt->comp->nbStep > 2) && + (ctxt->comp->last >= 0) && + (xmlXPathCanRewriteDosExpression((xmlChar *) ctxt->base) == 1)) + { + xmlXPathRewriteDOSExpression(ctxt->comp, + &ctxt->comp->steps[ctxt->comp->last]); + } + } + CHECK_ERROR; + xmlXPathRunEval(ctxt, 0); +} + +/** + * xmlXPathEval: + * @str: the XPath expression + * @ctx: the XPath context + * + * Evaluate the XPath Location Path in the given context. + * + * Returns the xmlXPathObjectPtr resulting from the evaluation or NULL. + * the caller has to free the object. + */ +xmlXPathObjectPtr +xmlXPathEval(const xmlChar *str, xmlXPathContextPtr ctx) { + xmlXPathParserContextPtr ctxt; + xmlXPathObjectPtr res, tmp, init = NULL; + int stack = 0; + + CHECK_CTXT(ctx) + + xmlXPathInit(); + + ctxt = xmlXPathNewParserContext(str, ctx); + xmlXPathEvalExpr(ctxt); + + if (ctxt->value == NULL) { + xmlGenericError(xmlGenericErrorContext, + "xmlXPathEval: evaluation failed\n"); + res = NULL; + } else if ((*ctxt->cur != 0) && (ctxt->comp != NULL) +#ifdef XPATH_STREAMING + && (ctxt->comp->stream == NULL) +#endif + ) { + xmlXPatherror(ctxt, __FILE__, __LINE__, XPATH_EXPR_ERROR); + res = NULL; + } else { + res = valuePop(ctxt); + } + + do { + tmp = valuePop(ctxt); + if (tmp != NULL) { + if (tmp != init) + stack++; + xmlXPathReleaseObject(ctx, tmp); + } + } while (tmp != NULL); + if ((stack != 0) && (res != NULL)) { + xmlGenericError(xmlGenericErrorContext, + "xmlXPathEval: %d object left on the stack\n", + stack); + } + if (ctxt->error != XPATH_EXPRESSION_OK) { + xmlXPathFreeObject(res); + res = NULL; + } + + xmlXPathFreeParserContext(ctxt); + return(res); +} + +/** + * xmlXPathEvalExpression: + * @str: the XPath expression + * @ctxt: the XPath context + * + * Evaluate the XPath expression in the given context. + * + * Returns the xmlXPathObjectPtr resulting from the evaluation or NULL. + * the caller has to free the object. + */ +xmlXPathObjectPtr +xmlXPathEvalExpression(const xmlChar *str, xmlXPathContextPtr ctxt) { + xmlXPathParserContextPtr pctxt; + xmlXPathObjectPtr res, tmp; + int stack = 0; + + CHECK_CTXT(ctxt) + + xmlXPathInit(); + + pctxt = xmlXPathNewParserContext(str, ctxt); + xmlXPathEvalExpr(pctxt); + + if ((*pctxt->cur != 0) || (pctxt->error != XPATH_EXPRESSION_OK)) { + xmlXPatherror(pctxt, __FILE__, __LINE__, XPATH_EXPR_ERROR); + res = NULL; + } else { + res = valuePop(pctxt); + } + do { + tmp = valuePop(pctxt); + if (tmp != NULL) { + xmlXPathReleaseObject(ctxt, tmp); + stack++; + } + } while (tmp != NULL); + if ((stack != 0) && (res != NULL)) { + xmlGenericError(xmlGenericErrorContext, + "xmlXPathEvalExpression: %d object left on the stack\n", + stack); + } + xmlXPathFreeParserContext(pctxt); + return(res); +} + +/************************************************************************ + * * + * Extra functions not pertaining to the XPath spec * + * * + ************************************************************************/ +/** + * xmlXPathEscapeUriFunction: + * @ctxt: the XPath Parser context + * @nargs: the number of arguments + * + * Implement the escape-uri() XPath function + * string escape-uri(string $str, bool $escape-reserved) + * + * This function applies the URI escaping rules defined in section 2 of [RFC + * 2396] to the string supplied as $uri-part, which typically represents all + * or part of a URI. The effect of the function is to replace any special + * character in the string by an escape sequence of the form %xx%yy..., + * where xxyy... is the hexadecimal representation of the octets used to + * represent the character in UTF-8. + * + * The set of characters that are escaped depends on the setting of the + * boolean argument $escape-reserved. + * + * If $escape-reserved is true, all characters are escaped other than lower + * case letters a-z, upper case letters A-Z, digits 0-9, and the characters + * referred to in [RFC 2396] as "marks": specifically, "-" | "_" | "." | "!" + * | "~" | "*" | "'" | "(" | ")". The "%" character itself is escaped only + * if it is not followed by two hexadecimal digits (that is, 0-9, a-f, and + * A-F). + * + * If $escape-reserved is false, the behavior differs in that characters + * referred to in [RFC 2396] as reserved characters are not escaped. These + * characters are ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | ",". + * + * [RFC 2396] does not define whether escaped URIs should use lower case or + * upper case for hexadecimal digits. To ensure that escaped URIs can be + * compared using string comparison functions, this function must always use + * the upper-case letters A-F. + * + * Generally, $escape-reserved should be set to true when escaping a string + * that is to form a single part of a URI, and to false when escaping an + * entire URI or URI reference. + * + * In the case of non-ascii characters, the string is encoded according to + * utf-8 and then converted according to RFC 2396. + * + * Examples + * xf:escape-uri ("gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%20Angeles#ocean"), true()) + * returns "gopher%3A%2F%2Fspinaltap.micro.umn.edu%2F00%2FWeather%2FCalifornia%2FLos%20Angeles%23ocean" + * xf:escape-uri ("gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%20Angeles#ocean"), false()) + * returns "gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%20Angeles%23ocean" + * + */ +static void +xmlXPathEscapeUriFunction(xmlXPathParserContextPtr ctxt, int nargs) { + xmlXPathObjectPtr str; + int escape_reserved; + xmlBufferPtr target; + xmlChar *cptr; + xmlChar escape[4]; + + CHECK_ARITY(2); + + escape_reserved = xmlXPathPopBoolean(ctxt); + + CAST_TO_STRING; + str = valuePop(ctxt); + + target = xmlBufferCreate(); + + escape[0] = '%'; + escape[3] = 0; + + if (target) { + for (cptr = str->stringval; *cptr; cptr++) { + if ((*cptr >= 'A' && *cptr <= 'Z') || + (*cptr >= 'a' && *cptr <= 'z') || + (*cptr >= '0' && *cptr <= '9') || + *cptr == '-' || *cptr == '_' || *cptr == '.' || + *cptr == '!' || *cptr == '~' || *cptr == '*' || + *cptr == '\''|| *cptr == '(' || *cptr == ')' || + (*cptr == '%' && + ((cptr[1] >= 'A' && cptr[1] <= 'F') || + (cptr[1] >= 'a' && cptr[1] <= 'f') || + (cptr[1] >= '0' && cptr[1] <= '9')) && + ((cptr[2] >= 'A' && cptr[2] <= 'F') || + (cptr[2] >= 'a' && cptr[2] <= 'f') || + (cptr[2] >= '0' && cptr[2] <= '9'))) || + (!escape_reserved && + (*cptr == ';' || *cptr == '/' || *cptr == '?' || + *cptr == ':' || *cptr == '@' || *cptr == '&' || + *cptr == '=' || *cptr == '+' || *cptr == '$' || + *cptr == ','))) { + xmlBufferAdd(target, cptr, 1); + } else { + if ((*cptr >> 4) < 10) + escape[1] = '0' + (*cptr >> 4); + else + escape[1] = 'A' - 10 + (*cptr >> 4); + if ((*cptr & 0xF) < 10) + escape[2] = '0' + (*cptr & 0xF); + else + escape[2] = 'A' - 10 + (*cptr & 0xF); + + xmlBufferAdd(target, &escape[0], 3); + } + } + } + valuePush(ctxt, xmlXPathCacheNewString(ctxt->context, + xmlBufferContent(target))); + xmlBufferFree(target); + xmlXPathReleaseObject(ctxt->context, str); +} + +/** + * xmlXPathRegisterAllFunctions: + * @ctxt: the XPath context + * + * Registers all default XPath functions in this context + */ +void +xmlXPathRegisterAllFunctions(xmlXPathContextPtr ctxt) +{ + xmlXPathRegisterFunc(ctxt, (const xmlChar *)"boolean", + xmlXPathBooleanFunction); + xmlXPathRegisterFunc(ctxt, (const xmlChar *)"ceiling", + xmlXPathCeilingFunction); + xmlXPathRegisterFunc(ctxt, (const xmlChar *)"count", + xmlXPathCountFunction); + xmlXPathRegisterFunc(ctxt, (const xmlChar *)"concat", + xmlXPathConcatFunction); + xmlXPathRegisterFunc(ctxt, (const xmlChar *)"contains", + xmlXPathContainsFunction); + xmlXPathRegisterFunc(ctxt, (const xmlChar *)"id", + xmlXPathIdFunction); + xmlXPathRegisterFunc(ctxt, (const xmlChar *)"false", + xmlXPathFalseFunction); + xmlXPathRegisterFunc(ctxt, (const xmlChar *)"floor", + xmlXPathFloorFunction); + xmlXPathRegisterFunc(ctxt, (const xmlChar *)"last", + xmlXPathLastFunction); + xmlXPathRegisterFunc(ctxt, (const xmlChar *)"lang", + xmlXPathLangFunction); + xmlXPathRegisterFunc(ctxt, (const xmlChar *)"local-name", + xmlXPathLocalNameFunction); + xmlXPathRegisterFunc(ctxt, (const xmlChar *)"not", + xmlXPathNotFunction); + xmlXPathRegisterFunc(ctxt, (const xmlChar *)"name", + xmlXPathNameFunction); + xmlXPathRegisterFunc(ctxt, (const xmlChar *)"namespace-uri", + xmlXPathNamespaceURIFunction); + xmlXPathRegisterFunc(ctxt, (const xmlChar *)"normalize-space", + xmlXPathNormalizeFunction); + xmlXPathRegisterFunc(ctxt, (const xmlChar *)"number", + xmlXPathNumberFunction); + xmlXPathRegisterFunc(ctxt, (const xmlChar *)"position", + xmlXPathPositionFunction); + xmlXPathRegisterFunc(ctxt, (const xmlChar *)"round", + xmlXPathRoundFunction); + xmlXPathRegisterFunc(ctxt, (const xmlChar *)"string", + xmlXPathStringFunction); + xmlXPathRegisterFunc(ctxt, (const xmlChar *)"string-length", + xmlXPathStringLengthFunction); + xmlXPathRegisterFunc(ctxt, (const xmlChar *)"starts-with", + xmlXPathStartsWithFunction); + xmlXPathRegisterFunc(ctxt, (const xmlChar *)"substring", + xmlXPathSubstringFunction); + xmlXPathRegisterFunc(ctxt, (const xmlChar *)"substring-before", + xmlXPathSubstringBeforeFunction); + xmlXPathRegisterFunc(ctxt, (const xmlChar *)"substring-after", + xmlXPathSubstringAfterFunction); + xmlXPathRegisterFunc(ctxt, (const xmlChar *)"sum", + xmlXPathSumFunction); + xmlXPathRegisterFunc(ctxt, (const xmlChar *)"true", + xmlXPathTrueFunction); + xmlXPathRegisterFunc(ctxt, (const xmlChar *)"translate", + xmlXPathTranslateFunction); + + xmlXPathRegisterFuncNS(ctxt, (const xmlChar *)"escape-uri", + (const xmlChar *)"http://www.w3.org/2002/08/xquery-functions", + xmlXPathEscapeUriFunction); +} + +#endif /* LIBXML_XPATH_ENABLED */ +#define bottom_xpath +#include "elfgcchack.h" diff --git a/gettext-tools/gnulib-lib/libxml/xpath.in.h b/gettext-tools/gnulib-lib/libxml/xpath.in.h new file mode 100644 index 0000000..89008fc --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/xpath.in.h @@ -0,0 +1,543 @@ +/* + * Summary: XML Path Language implementation + * Description: API for the XML Path Language implementation + * + * XML Path Language implementation + * XPath is a language for addressing parts of an XML document, + * designed to be used by both XSLT and XPointer + * http://www.w3.org/TR/xpath + * + * Implements + * W3C Recommendation 16 November 1999 + * http://www.w3.org/TR/1999/REC-xpath-19991116 + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + +#ifndef __XML_XPATH_H__ +#define __XML_XPATH_H__ + +#include + +#ifdef LIBXML_XPATH_ENABLED + +#include +#include +#include +#endif /* LIBXML_XPATH_ENABLED */ + +#if defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) +#ifdef __cplusplus +extern "C" { +#endif +#endif /* LIBXML_XPATH_ENABLED or LIBXML_SCHEMAS_ENABLED */ + +#ifdef LIBXML_XPATH_ENABLED + +typedef struct _xmlXPathContext xmlXPathContext; +typedef xmlXPathContext *xmlXPathContextPtr; +typedef struct _xmlXPathParserContext xmlXPathParserContext; +typedef xmlXPathParserContext *xmlXPathParserContextPtr; + +/** + * The set of XPath error codes. + */ + +typedef enum { + XPATH_EXPRESSION_OK = 0, + XPATH_NUMBER_ERROR, + XPATH_UNFINISHED_LITERAL_ERROR, + XPATH_START_LITERAL_ERROR, + XPATH_VARIABLE_REF_ERROR, + XPATH_UNDEF_VARIABLE_ERROR, + XPATH_INVALID_PREDICATE_ERROR, + XPATH_EXPR_ERROR, + XPATH_UNCLOSED_ERROR, + XPATH_UNKNOWN_FUNC_ERROR, + XPATH_INVALID_OPERAND, + XPATH_INVALID_TYPE, + XPATH_INVALID_ARITY, + XPATH_INVALID_CTXT_SIZE, + XPATH_INVALID_CTXT_POSITION, + XPATH_MEMORY_ERROR, + XPTR_SYNTAX_ERROR, + XPTR_RESOURCE_ERROR, + XPTR_SUB_RESOURCE_ERROR, + XPATH_UNDEF_PREFIX_ERROR, + XPATH_ENCODING_ERROR, + XPATH_INVALID_CHAR_ERROR, + XPATH_INVALID_CTXT +} xmlXPathError; + +/* + * A node-set (an unordered collection of nodes without duplicates). + */ +typedef struct _xmlNodeSet xmlNodeSet; +typedef xmlNodeSet *xmlNodeSetPtr; +struct _xmlNodeSet { + int nodeNr; /* number of nodes in the set */ + int nodeMax; /* size of the array as allocated */ + xmlNodePtr *nodeTab; /* array of nodes in no particular order */ + /* @@ with_ns to check wether namespace nodes should be looked at @@ */ +}; + +/* + * An expression is evaluated to yield an object, which + * has one of the following four basic types: + * - node-set + * - boolean + * - number + * - string + * + * @@ XPointer will add more types ! + */ + +typedef enum { + XPATH_UNDEFINED = 0, + XPATH_NODESET = 1, + XPATH_BOOLEAN = 2, + XPATH_NUMBER = 3, + XPATH_STRING = 4, + XPATH_POINT = 5, + XPATH_RANGE = 6, + XPATH_LOCATIONSET = 7, + XPATH_USERS = 8, + XPATH_XSLT_TREE = 9 /* An XSLT value tree, non modifiable */ +} xmlXPathObjectType; + +typedef struct _xmlXPathObject xmlXPathObject; +typedef xmlXPathObject *xmlXPathObjectPtr; +struct _xmlXPathObject { + xmlXPathObjectType type; + xmlNodeSetPtr nodesetval; + int boolval; + double floatval; + xmlChar *stringval; + void *user; + int index; + void *user2; + int index2; +}; + +/** + * xmlXPathConvertFunc: + * @obj: an XPath object + * @type: the number of the target type + * + * A conversion function is associated to a type and used to cast + * the new type to primitive values. + * + * Returns -1 in case of error, 0 otherwise + */ +typedef int (*xmlXPathConvertFunc) (xmlXPathObjectPtr obj, int type); + +/* + * Extra type: a name and a conversion function. + */ + +typedef struct _xmlXPathType xmlXPathType; +typedef xmlXPathType *xmlXPathTypePtr; +struct _xmlXPathType { + const xmlChar *name; /* the type name */ + xmlXPathConvertFunc func; /* the conversion function */ +}; + +/* + * Extra variable: a name and a value. + */ + +typedef struct _xmlXPathVariable xmlXPathVariable; +typedef xmlXPathVariable *xmlXPathVariablePtr; +struct _xmlXPathVariable { + const xmlChar *name; /* the variable name */ + xmlXPathObjectPtr value; /* the value */ +}; + +/** + * xmlXPathEvalFunc: + * @ctxt: an XPath parser context + * @nargs: the number of arguments passed to the function + * + * An XPath evaluation function, the parameters are on the XPath context stack. + */ + +typedef void (*xmlXPathEvalFunc)(xmlXPathParserContextPtr ctxt, + int nargs); + +/* + * Extra function: a name and a evaluation function. + */ + +typedef struct _xmlXPathFunct xmlXPathFunct; +typedef xmlXPathFunct *xmlXPathFuncPtr; +struct _xmlXPathFunct { + const xmlChar *name; /* the function name */ + xmlXPathEvalFunc func; /* the evaluation function */ +}; + +/** + * xmlXPathAxisFunc: + * @ctxt: the XPath interpreter context + * @cur: the previous node being explored on that axis + * + * An axis traversal function. To traverse an axis, the engine calls + * the first time with cur == NULL and repeat until the function returns + * NULL indicating the end of the axis traversal. + * + * Returns the next node in that axis or NULL if at the end of the axis. + */ + +typedef xmlXPathObjectPtr (*xmlXPathAxisFunc) (xmlXPathParserContextPtr ctxt, + xmlXPathObjectPtr cur); + +/* + * Extra axis: a name and an axis function. + */ + +typedef struct _xmlXPathAxis xmlXPathAxis; +typedef xmlXPathAxis *xmlXPathAxisPtr; +struct _xmlXPathAxis { + const xmlChar *name; /* the axis name */ + xmlXPathAxisFunc func; /* the search function */ +}; + +/** + * xmlXPathFunction: + * @ctxt: the XPath interprestation context + * @nargs: the number of arguments + * + * An XPath function. + * The arguments (if any) are popped out from the context stack + * and the result is pushed on the stack. + */ + +typedef void (*xmlXPathFunction) (xmlXPathParserContextPtr ctxt, int nargs); + +/* + * Function and Variable Lookup. + */ + +/** + * xmlXPathVariableLookupFunc: + * @ctxt: an XPath context + * @name: name of the variable + * @ns_uri: the namespace name hosting this variable + * + * Prototype for callbacks used to plug variable lookup in the XPath + * engine. + * + * Returns the XPath object value or NULL if not found. + */ +typedef xmlXPathObjectPtr (*xmlXPathVariableLookupFunc) (void *ctxt, + const xmlChar *name, + const xmlChar *ns_uri); + +/** + * xmlXPathFuncLookupFunc: + * @ctxt: an XPath context + * @name: name of the function + * @ns_uri: the namespace name hosting this function + * + * Prototype for callbacks used to plug function lookup in the XPath + * engine. + * + * Returns the XPath function or NULL if not found. + */ +typedef xmlXPathFunction (*xmlXPathFuncLookupFunc) (void *ctxt, + const xmlChar *name, + const xmlChar *ns_uri); + +/** + * xmlXPathFlags: + * Flags for XPath engine compilation and runtime + */ +/** + * XML_XPATH_CHECKNS: + * + * check namespaces at compilation + */ +#define XML_XPATH_CHECKNS (1<<0) +/** + * XML_XPATH_NOVAR: + * + * forbid variables in expression + */ +#define XML_XPATH_NOVAR (1<<1) + +/** + * xmlXPathContext: + * + * Expression evaluation occurs with respect to a context. + * he context consists of: + * - a node (the context node) + * - a node list (the context node list) + * - a set of variable bindings + * - a function library + * - the set of namespace declarations in scope for the expression + * Following the switch to hash tables, this need to be trimmed up at + * the next binary incompatible release. + */ + +struct _xmlXPathContext { + xmlDocPtr doc; /* The current document */ + xmlNodePtr node; /* The current node */ + + int nb_variables_unused; /* unused (hash table) */ + int max_variables_unused; /* unused (hash table) */ + xmlHashTablePtr varHash; /* Hash table of defined variables */ + + int nb_types; /* number of defined types */ + int max_types; /* max number of types */ + xmlXPathTypePtr types; /* Array of defined types */ + + int nb_funcs_unused; /* unused (hash table) */ + int max_funcs_unused; /* unused (hash table) */ + xmlHashTablePtr funcHash; /* Hash table of defined funcs */ + + int nb_axis; /* number of defined axis */ + int max_axis; /* max number of axis */ + xmlXPathAxisPtr axis; /* Array of defined axis */ + + /* the namespace nodes of the context node */ + xmlNsPtr *namespaces; /* Array of namespaces */ + int nsNr; /* number of namespace in scope */ + void *user; /* function to free */ + + /* extra variables */ + int contextSize; /* the context size */ + int proximityPosition; /* the proximity position */ + + /* extra stuff for XPointer */ + int xptr; /* it this an XPointer context */ + xmlNodePtr here; /* for here() */ + xmlNodePtr origin; /* for origin() */ + + /* the set of namespace declarations in scope for the expression */ + xmlHashTablePtr nsHash; /* The namespaces hash table */ + xmlXPathVariableLookupFunc varLookupFunc;/* variable lookup func */ + void *varLookupData; /* variable lookup data */ + + /* Possibility to link in an extra item */ + void *extra; /* needed for XSLT */ + + /* The function name and URI when calling a function */ + const xmlChar *function; + const xmlChar *functionURI; + + /* function lookup function and data */ + xmlXPathFuncLookupFunc funcLookupFunc;/* function lookup func */ + void *funcLookupData; /* function lookup data */ + + /* temporary namespace lists kept for walking the namespace axis */ + xmlNsPtr *tmpNsList; /* Array of namespaces */ + int tmpNsNr; /* number of namespace in scope */ + + /* error reporting mechanism */ + void *userData; /* user specific data block */ + xmlStructuredErrorFunc error; /* the callback in case of errors */ + xmlError lastError; /* the last error */ + xmlNodePtr debugNode; /* the source node XSLT */ + + /* dictionnary */ + xmlDictPtr dict; /* dictionnary if any */ + + int flags; /* flags to control compilation */ + + /* Cache for reusal of XPath objects */ + void *cache; +}; + +/* + * The structure of a compiled expression form is not public. + */ + +typedef struct _xmlXPathCompExpr xmlXPathCompExpr; +typedef xmlXPathCompExpr *xmlXPathCompExprPtr; + +/** + * xmlXPathParserContext: + * + * An XPath parser context. It contains pure parsing informations, + * an xmlXPathContext, and the stack of objects. + */ +struct _xmlXPathParserContext { + const xmlChar *cur; /* the current char being parsed */ + const xmlChar *base; /* the full expression */ + + int error; /* error code */ + + xmlXPathContextPtr context; /* the evaluation context */ + xmlXPathObjectPtr value; /* the current value */ + int valueNr; /* number of values stacked */ + int valueMax; /* max number of values stacked */ + xmlXPathObjectPtr *valueTab; /* stack of values */ + + xmlXPathCompExprPtr comp; /* the precompiled expression */ + int xptr; /* it this an XPointer expression */ + xmlNodePtr ancestor; /* used for walking preceding axis */ +}; + +/************************************************************************ + * * + * Public API * + * * + ************************************************************************/ + +/** + * Objects and Nodesets handling + */ + +XMLPUBVAR double xmlXPathNAN; +XMLPUBVAR double xmlXPathPINF; +XMLPUBVAR double xmlXPathNINF; + +/* These macros may later turn into functions */ +/** + * xmlXPathNodeSetGetLength: + * @ns: a node-set + * + * Implement a functionality similar to the DOM NodeList.length. + * + * Returns the number of nodes in the node-set. + */ +#define xmlXPathNodeSetGetLength(ns) ((ns) ? (ns)->nodeNr : 0) +/** + * xmlXPathNodeSetItem: + * @ns: a node-set + * @index: index of a node in the set + * + * Implements a functionality similar to the DOM NodeList.item(). + * + * Returns the xmlNodePtr at the given @index in @ns or NULL if + * @index is out of range (0 to length-1) + */ +#define xmlXPathNodeSetItem(ns, index) \ + ((((ns) != NULL) && \ + ((index) >= 0) && ((index) < (ns)->nodeNr)) ? \ + (ns)->nodeTab[(index)] \ + : NULL) +/** + * xmlXPathNodeSetIsEmpty: + * @ns: a node-set + * + * Checks whether @ns is empty or not. + * + * Returns %TRUE if @ns is an empty node-set. + */ +#define xmlXPathNodeSetIsEmpty(ns) \ + (((ns) == NULL) || ((ns)->nodeNr == 0) || ((ns)->nodeTab == NULL)) + + +XMLPUBFUN void XMLCALL + xmlXPathFreeObject (xmlXPathObjectPtr obj); +XMLPUBFUN xmlNodeSetPtr XMLCALL + xmlXPathNodeSetCreate (xmlNodePtr val); +XMLPUBFUN void XMLCALL + xmlXPathFreeNodeSetList (xmlXPathObjectPtr obj); +XMLPUBFUN void XMLCALL + xmlXPathFreeNodeSet (xmlNodeSetPtr obj); +XMLPUBFUN xmlXPathObjectPtr XMLCALL + xmlXPathObjectCopy (xmlXPathObjectPtr val); +XMLPUBFUN int XMLCALL + xmlXPathCmpNodes (xmlNodePtr node1, + xmlNodePtr node2); +/** + * Conversion functions to basic types. + */ +XMLPUBFUN int XMLCALL + xmlXPathCastNumberToBoolean (double val); +XMLPUBFUN int XMLCALL + xmlXPathCastStringToBoolean (const xmlChar * val); +XMLPUBFUN int XMLCALL + xmlXPathCastNodeSetToBoolean(xmlNodeSetPtr ns); +XMLPUBFUN int XMLCALL + xmlXPathCastToBoolean (xmlXPathObjectPtr val); + +XMLPUBFUN double XMLCALL + xmlXPathCastBooleanToNumber (int val); +XMLPUBFUN double XMLCALL + xmlXPathCastStringToNumber (const xmlChar * val); +XMLPUBFUN double XMLCALL + xmlXPathCastNodeToNumber (xmlNodePtr node); +XMLPUBFUN double XMLCALL + xmlXPathCastNodeSetToNumber (xmlNodeSetPtr ns); +XMLPUBFUN double XMLCALL + xmlXPathCastToNumber (xmlXPathObjectPtr val); + +XMLPUBFUN xmlChar * XMLCALL + xmlXPathCastBooleanToString (int val); +XMLPUBFUN xmlChar * XMLCALL + xmlXPathCastNumberToString (double val); +XMLPUBFUN xmlChar * XMLCALL + xmlXPathCastNodeToString (xmlNodePtr node); +XMLPUBFUN xmlChar * XMLCALL + xmlXPathCastNodeSetToString (xmlNodeSetPtr ns); +XMLPUBFUN xmlChar * XMLCALL + xmlXPathCastToString (xmlXPathObjectPtr val); + +XMLPUBFUN xmlXPathObjectPtr XMLCALL + xmlXPathConvertBoolean (xmlXPathObjectPtr val); +XMLPUBFUN xmlXPathObjectPtr XMLCALL + xmlXPathConvertNumber (xmlXPathObjectPtr val); +XMLPUBFUN xmlXPathObjectPtr XMLCALL + xmlXPathConvertString (xmlXPathObjectPtr val); + +/** + * Context handling. + */ +XMLPUBFUN xmlXPathContextPtr XMLCALL + xmlXPathNewContext (xmlDocPtr doc); +XMLPUBFUN void XMLCALL + xmlXPathFreeContext (xmlXPathContextPtr ctxt); +XMLPUBFUN int XMLCALL + xmlXPathContextSetCache(xmlXPathContextPtr ctxt, + int active, + int value, + int options); +/** + * Evaluation functions. + */ +XMLPUBFUN long XMLCALL + xmlXPathOrderDocElems (xmlDocPtr doc); +XMLPUBFUN xmlXPathObjectPtr XMLCALL + xmlXPathEval (const xmlChar *str, + xmlXPathContextPtr ctx); +XMLPUBFUN xmlXPathObjectPtr XMLCALL + xmlXPathEvalExpression (const xmlChar *str, + xmlXPathContextPtr ctxt); +XMLPUBFUN int XMLCALL + xmlXPathEvalPredicate (xmlXPathContextPtr ctxt, + xmlXPathObjectPtr res); +/** + * Separate compilation/evaluation entry points. + */ +XMLPUBFUN xmlXPathCompExprPtr XMLCALL + xmlXPathCompile (const xmlChar *str); +XMLPUBFUN xmlXPathCompExprPtr XMLCALL + xmlXPathCtxtCompile (xmlXPathContextPtr ctxt, + const xmlChar *str); +XMLPUBFUN xmlXPathObjectPtr XMLCALL + xmlXPathCompiledEval (xmlXPathCompExprPtr comp, + xmlXPathContextPtr ctx); +XMLPUBFUN int XMLCALL + xmlXPathCompiledEvalToBoolean(xmlXPathCompExprPtr comp, + xmlXPathContextPtr ctxt); +XMLPUBFUN void XMLCALL + xmlXPathFreeCompExpr (xmlXPathCompExprPtr comp); +#endif /* LIBXML_XPATH_ENABLED */ +#if defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) +XMLPUBFUN void XMLCALL + xmlXPathInit (void); +XMLPUBFUN int XMLCALL + xmlXPathIsNaN (double val); +XMLPUBFUN int XMLCALL + xmlXPathIsInf (double val); + +#ifdef __cplusplus +} +#endif + +#endif /* LIBXML_XPATH_ENABLED or LIBXML_SCHEMAS_ENABLED*/ +#endif /* ! __XML_XPATH_H__ */ diff --git a/gettext-tools/gnulib-lib/libxml/xpathInternals.in.h b/gettext-tools/gnulib-lib/libxml/xpathInternals.in.h new file mode 100644 index 0000000..dcd5243 --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/xpathInternals.in.h @@ -0,0 +1,630 @@ +/* + * Summary: internal interfaces for XML Path Language implementation + * Description: internal interfaces for XML Path Language implementation + * used to build new modules on top of XPath like XPointer and + * XSLT + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + +#ifndef __XML_XPATH_INTERNALS_H__ +#define __XML_XPATH_INTERNALS_H__ + +#include +#include + +#ifdef LIBXML_XPATH_ENABLED + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************ + * * + * Helpers * + * * + ************************************************************************/ + +/* + * Many of these macros may later turn into functions. They + * shouldn't be used in #ifdef's preprocessor instructions. + */ +/** + * xmlXPathSetError: + * @ctxt: an XPath parser context + * @err: an xmlXPathError code + * + * Raises an error. + */ +#define xmlXPathSetError(ctxt, err) \ + { xmlXPatherror((ctxt), __FILE__, __LINE__, (err)); \ + if ((ctxt) != NULL) (ctxt)->error = (err); } + +/** + * xmlXPathSetArityError: + * @ctxt: an XPath parser context + * + * Raises an XPATH_INVALID_ARITY error. + */ +#define xmlXPathSetArityError(ctxt) \ + xmlXPathSetError((ctxt), XPATH_INVALID_ARITY) + +/** + * xmlXPathSetTypeError: + * @ctxt: an XPath parser context + * + * Raises an XPATH_INVALID_TYPE error. + */ +#define xmlXPathSetTypeError(ctxt) \ + xmlXPathSetError((ctxt), XPATH_INVALID_TYPE) + +/** + * xmlXPathGetError: + * @ctxt: an XPath parser context + * + * Get the error code of an XPath context. + * + * Returns the context error. + */ +#define xmlXPathGetError(ctxt) ((ctxt)->error) + +/** + * xmlXPathCheckError: + * @ctxt: an XPath parser context + * + * Check if an XPath error was raised. + * + * Returns true if an error has been raised, false otherwise. + */ +#define xmlXPathCheckError(ctxt) ((ctxt)->error != XPATH_EXPRESSION_OK) + +/** + * xmlXPathGetDocument: + * @ctxt: an XPath parser context + * + * Get the document of an XPath context. + * + * Returns the context document. + */ +#define xmlXPathGetDocument(ctxt) ((ctxt)->context->doc) + +/** + * xmlXPathGetContextNode: + * @ctxt: an XPath parser context + * + * Get the context node of an XPath context. + * + * Returns the context node. + */ +#define xmlXPathGetContextNode(ctxt) ((ctxt)->context->node) + +XMLPUBFUN int XMLCALL + xmlXPathPopBoolean (xmlXPathParserContextPtr ctxt); +XMLPUBFUN double XMLCALL + xmlXPathPopNumber (xmlXPathParserContextPtr ctxt); +XMLPUBFUN xmlChar * XMLCALL + xmlXPathPopString (xmlXPathParserContextPtr ctxt); +XMLPUBFUN xmlNodeSetPtr XMLCALL + xmlXPathPopNodeSet (xmlXPathParserContextPtr ctxt); +XMLPUBFUN void * XMLCALL + xmlXPathPopExternal (xmlXPathParserContextPtr ctxt); + +/** + * xmlXPathReturnBoolean: + * @ctxt: an XPath parser context + * @val: a boolean + * + * Pushes the boolean @val on the context stack. + */ +#define xmlXPathReturnBoolean(ctxt, val) \ + valuePush((ctxt), xmlXPathNewBoolean(val)) + +/** + * xmlXPathReturnTrue: + * @ctxt: an XPath parser context + * + * Pushes true on the context stack. + */ +#define xmlXPathReturnTrue(ctxt) xmlXPathReturnBoolean((ctxt), 1) + +/** + * xmlXPathReturnFalse: + * @ctxt: an XPath parser context + * + * Pushes false on the context stack. + */ +#define xmlXPathReturnFalse(ctxt) xmlXPathReturnBoolean((ctxt), 0) + +/** + * xmlXPathReturnNumber: + * @ctxt: an XPath parser context + * @val: a double + * + * Pushes the double @val on the context stack. + */ +#define xmlXPathReturnNumber(ctxt, val) \ + valuePush((ctxt), xmlXPathNewFloat(val)) + +/** + * xmlXPathReturnString: + * @ctxt: an XPath parser context + * @str: a string + * + * Pushes the string @str on the context stack. + */ +#define xmlXPathReturnString(ctxt, str) \ + valuePush((ctxt), xmlXPathWrapString(str)) + +/** + * xmlXPathReturnEmptyString: + * @ctxt: an XPath parser context + * + * Pushes an empty string on the stack. + */ +#define xmlXPathReturnEmptyString(ctxt) \ + valuePush((ctxt), xmlXPathNewCString("")) + +/** + * xmlXPathReturnNodeSet: + * @ctxt: an XPath parser context + * @ns: a node-set + * + * Pushes the node-set @ns on the context stack. + */ +#define xmlXPathReturnNodeSet(ctxt, ns) \ + valuePush((ctxt), xmlXPathWrapNodeSet(ns)) + +/** + * xmlXPathReturnEmptyNodeSet: + * @ctxt: an XPath parser context + * + * Pushes an empty node-set on the context stack. + */ +#define xmlXPathReturnEmptyNodeSet(ctxt) \ + valuePush((ctxt), xmlXPathNewNodeSet(NULL)) + +/** + * xmlXPathReturnExternal: + * @ctxt: an XPath parser context + * @val: user data + * + * Pushes user data on the context stack. + */ +#define xmlXPathReturnExternal(ctxt, val) \ + valuePush((ctxt), xmlXPathWrapExternal(val)) + +/** + * xmlXPathStackIsNodeSet: + * @ctxt: an XPath parser context + * + * Check if the current value on the XPath stack is a node set or + * an XSLT value tree. + * + * Returns true if the current object on the stack is a node-set. + */ +#define xmlXPathStackIsNodeSet(ctxt) \ + (((ctxt)->value != NULL) \ + && (((ctxt)->value->type == XPATH_NODESET) \ + || ((ctxt)->value->type == XPATH_XSLT_TREE))) + +/** + * xmlXPathStackIsExternal: + * @ctxt: an XPath parser context + * + * Checks if the current value on the XPath stack is an external + * object. + * + * Returns true if the current object on the stack is an external + * object. + */ +#define xmlXPathStackIsExternal(ctxt) \ + ((ctxt->value != NULL) && (ctxt->value->type == XPATH_USERS)) + +/** + * xmlXPathEmptyNodeSet: + * @ns: a node-set + * + * Empties a node-set. + */ +#define xmlXPathEmptyNodeSet(ns) \ + { while ((ns)->nodeNr > 0) (ns)->nodeTab[(ns)->nodeNr--] = NULL; } + +/** + * CHECK_ERROR: + * + * Macro to return from the function if an XPath error was detected. + */ +#define CHECK_ERROR \ + if (ctxt->error != XPATH_EXPRESSION_OK) return + +/** + * CHECK_ERROR0: + * + * Macro to return 0 from the function if an XPath error was detected. + */ +#define CHECK_ERROR0 \ + if (ctxt->error != XPATH_EXPRESSION_OK) return(0) + +/** + * XP_ERROR: + * @X: the error code + * + * Macro to raise an XPath error and return. + */ +#define XP_ERROR(X) \ + { xmlXPathErr(ctxt, X); return; } + +/** + * XP_ERROR0: + * @X: the error code + * + * Macro to raise an XPath error and return 0. + */ +#define XP_ERROR0(X) \ + { xmlXPathErr(ctxt, X); return(0); } + +/** + * CHECK_TYPE: + * @typeval: the XPath type + * + * Macro to check that the value on top of the XPath stack is of a given + * type. + */ +#define CHECK_TYPE(typeval) \ + if ((ctxt->value == NULL) || (ctxt->value->type != typeval)) \ + XP_ERROR(XPATH_INVALID_TYPE) + +/** + * CHECK_TYPE0: + * @typeval: the XPath type + * + * Macro to check that the value on top of the XPath stack is of a given + * type. Return(0) in case of failure + */ +#define CHECK_TYPE0(typeval) \ + if ((ctxt->value == NULL) || (ctxt->value->type != typeval)) \ + XP_ERROR0(XPATH_INVALID_TYPE) + +/** + * CHECK_ARITY: + * @x: the number of expected args + * + * Macro to check that the number of args passed to an XPath function matches. + */ +#define CHECK_ARITY(x) \ + if (ctxt == NULL) return; \ + if (nargs != (x)) \ + XP_ERROR(XPATH_INVALID_ARITY); + +/** + * CAST_TO_STRING: + * + * Macro to try to cast the value on the top of the XPath stack to a string. + */ +#define CAST_TO_STRING \ + if ((ctxt->value != NULL) && (ctxt->value->type != XPATH_STRING)) \ + xmlXPathStringFunction(ctxt, 1); + +/** + * CAST_TO_NUMBER: + * + * Macro to try to cast the value on the top of the XPath stack to a number. + */ +#define CAST_TO_NUMBER \ + if ((ctxt->value != NULL) && (ctxt->value->type != XPATH_NUMBER)) \ + xmlXPathNumberFunction(ctxt, 1); + +/** + * CAST_TO_BOOLEAN: + * + * Macro to try to cast the value on the top of the XPath stack to a boolean. + */ +#define CAST_TO_BOOLEAN \ + if ((ctxt->value != NULL) && (ctxt->value->type != XPATH_BOOLEAN)) \ + xmlXPathBooleanFunction(ctxt, 1); + +/* + * Variable Lookup forwarding. + */ + +XMLPUBFUN void XMLCALL + xmlXPathRegisterVariableLookup (xmlXPathContextPtr ctxt, + xmlXPathVariableLookupFunc f, + void *data); + +/* + * Function Lookup forwarding. + */ + +XMLPUBFUN void XMLCALL + xmlXPathRegisterFuncLookup (xmlXPathContextPtr ctxt, + xmlXPathFuncLookupFunc f, + void *funcCtxt); + +/* + * Error reporting. + */ +XMLPUBFUN void XMLCALL + xmlXPatherror (xmlXPathParserContextPtr ctxt, + const char *file, + int line, + int no); + +XMLPUBFUN void XMLCALL + xmlXPathErr (xmlXPathParserContextPtr ctxt, + int error); + +#ifdef LIBXML_DEBUG_ENABLED +XMLPUBFUN void XMLCALL + xmlXPathDebugDumpObject (FILE *output, + xmlXPathObjectPtr cur, + int depth); +XMLPUBFUN void XMLCALL + xmlXPathDebugDumpCompExpr(FILE *output, + xmlXPathCompExprPtr comp, + int depth); +#endif +/** + * NodeSet handling. + */ +XMLPUBFUN int XMLCALL + xmlXPathNodeSetContains (xmlNodeSetPtr cur, + xmlNodePtr val); +XMLPUBFUN xmlNodeSetPtr XMLCALL + xmlXPathDifference (xmlNodeSetPtr nodes1, + xmlNodeSetPtr nodes2); +XMLPUBFUN xmlNodeSetPtr XMLCALL + xmlXPathIntersection (xmlNodeSetPtr nodes1, + xmlNodeSetPtr nodes2); + +XMLPUBFUN xmlNodeSetPtr XMLCALL + xmlXPathDistinctSorted (xmlNodeSetPtr nodes); +XMLPUBFUN xmlNodeSetPtr XMLCALL + xmlXPathDistinct (xmlNodeSetPtr nodes); + +XMLPUBFUN int XMLCALL + xmlXPathHasSameNodes (xmlNodeSetPtr nodes1, + xmlNodeSetPtr nodes2); + +XMLPUBFUN xmlNodeSetPtr XMLCALL + xmlXPathNodeLeadingSorted (xmlNodeSetPtr nodes, + xmlNodePtr node); +XMLPUBFUN xmlNodeSetPtr XMLCALL + xmlXPathLeadingSorted (xmlNodeSetPtr nodes1, + xmlNodeSetPtr nodes2); +XMLPUBFUN xmlNodeSetPtr XMLCALL + xmlXPathNodeLeading (xmlNodeSetPtr nodes, + xmlNodePtr node); +XMLPUBFUN xmlNodeSetPtr XMLCALL + xmlXPathLeading (xmlNodeSetPtr nodes1, + xmlNodeSetPtr nodes2); + +XMLPUBFUN xmlNodeSetPtr XMLCALL + xmlXPathNodeTrailingSorted (xmlNodeSetPtr nodes, + xmlNodePtr node); +XMLPUBFUN xmlNodeSetPtr XMLCALL + xmlXPathTrailingSorted (xmlNodeSetPtr nodes1, + xmlNodeSetPtr nodes2); +XMLPUBFUN xmlNodeSetPtr XMLCALL + xmlXPathNodeTrailing (xmlNodeSetPtr nodes, + xmlNodePtr node); +XMLPUBFUN xmlNodeSetPtr XMLCALL + xmlXPathTrailing (xmlNodeSetPtr nodes1, + xmlNodeSetPtr nodes2); + + +/** + * Extending a context. + */ + +XMLPUBFUN int XMLCALL + xmlXPathRegisterNs (xmlXPathContextPtr ctxt, + const xmlChar *prefix, + const xmlChar *ns_uri); +XMLPUBFUN const xmlChar * XMLCALL + xmlXPathNsLookup (xmlXPathContextPtr ctxt, + const xmlChar *prefix); +XMLPUBFUN void XMLCALL + xmlXPathRegisteredNsCleanup (xmlXPathContextPtr ctxt); + +XMLPUBFUN int XMLCALL + xmlXPathRegisterFunc (xmlXPathContextPtr ctxt, + const xmlChar *name, + xmlXPathFunction f); +XMLPUBFUN int XMLCALL + xmlXPathRegisterFuncNS (xmlXPathContextPtr ctxt, + const xmlChar *name, + const xmlChar *ns_uri, + xmlXPathFunction f); +XMLPUBFUN int XMLCALL + xmlXPathRegisterVariable (xmlXPathContextPtr ctxt, + const xmlChar *name, + xmlXPathObjectPtr value); +XMLPUBFUN int XMLCALL + xmlXPathRegisterVariableNS (xmlXPathContextPtr ctxt, + const xmlChar *name, + const xmlChar *ns_uri, + xmlXPathObjectPtr value); +XMLPUBFUN xmlXPathFunction XMLCALL + xmlXPathFunctionLookup (xmlXPathContextPtr ctxt, + const xmlChar *name); +XMLPUBFUN xmlXPathFunction XMLCALL + xmlXPathFunctionLookupNS (xmlXPathContextPtr ctxt, + const xmlChar *name, + const xmlChar *ns_uri); +XMLPUBFUN void XMLCALL + xmlXPathRegisteredFuncsCleanup (xmlXPathContextPtr ctxt); +XMLPUBFUN xmlXPathObjectPtr XMLCALL + xmlXPathVariableLookup (xmlXPathContextPtr ctxt, + const xmlChar *name); +XMLPUBFUN xmlXPathObjectPtr XMLCALL + xmlXPathVariableLookupNS (xmlXPathContextPtr ctxt, + const xmlChar *name, + const xmlChar *ns_uri); +XMLPUBFUN void XMLCALL + xmlXPathRegisteredVariablesCleanup(xmlXPathContextPtr ctxt); + +/** + * Utilities to extend XPath. + */ +XMLPUBFUN xmlXPathParserContextPtr XMLCALL + xmlXPathNewParserContext (const xmlChar *str, + xmlXPathContextPtr ctxt); +XMLPUBFUN void XMLCALL + xmlXPathFreeParserContext (xmlXPathParserContextPtr ctxt); + +/* TODO: remap to xmlXPathValuePop and Push. */ +XMLPUBFUN xmlXPathObjectPtr XMLCALL + valuePop (xmlXPathParserContextPtr ctxt); +XMLPUBFUN int XMLCALL + valuePush (xmlXPathParserContextPtr ctxt, + xmlXPathObjectPtr value); + +XMLPUBFUN xmlXPathObjectPtr XMLCALL + xmlXPathNewString (const xmlChar *val); +XMLPUBFUN xmlXPathObjectPtr XMLCALL + xmlXPathNewCString (const char *val); +XMLPUBFUN xmlXPathObjectPtr XMLCALL + xmlXPathWrapString (xmlChar *val); +XMLPUBFUN xmlXPathObjectPtr XMLCALL + xmlXPathWrapCString (char * val); +XMLPUBFUN xmlXPathObjectPtr XMLCALL + xmlXPathNewFloat (double val); +XMLPUBFUN xmlXPathObjectPtr XMLCALL + xmlXPathNewBoolean (int val); +XMLPUBFUN xmlXPathObjectPtr XMLCALL + xmlXPathNewNodeSet (xmlNodePtr val); +XMLPUBFUN xmlXPathObjectPtr XMLCALL + xmlXPathNewValueTree (xmlNodePtr val); +XMLPUBFUN void XMLCALL + xmlXPathNodeSetAdd (xmlNodeSetPtr cur, + xmlNodePtr val); +XMLPUBFUN void XMLCALL + xmlXPathNodeSetAddUnique (xmlNodeSetPtr cur, + xmlNodePtr val); +XMLPUBFUN void XMLCALL + xmlXPathNodeSetAddNs (xmlNodeSetPtr cur, + xmlNodePtr node, + xmlNsPtr ns); +XMLPUBFUN void XMLCALL + xmlXPathNodeSetSort (xmlNodeSetPtr set); + +XMLPUBFUN void XMLCALL + xmlXPathRoot (xmlXPathParserContextPtr ctxt); +XMLPUBFUN void XMLCALL + xmlXPathEvalExpr (xmlXPathParserContextPtr ctxt); +XMLPUBFUN xmlChar * XMLCALL + xmlXPathParseName (xmlXPathParserContextPtr ctxt); +XMLPUBFUN xmlChar * XMLCALL + xmlXPathParseNCName (xmlXPathParserContextPtr ctxt); + +/* + * Existing functions. + */ +XMLPUBFUN double XMLCALL + xmlXPathStringEvalNumber (const xmlChar *str); +XMLPUBFUN int XMLCALL + xmlXPathEvaluatePredicateResult (xmlXPathParserContextPtr ctxt, + xmlXPathObjectPtr res); +XMLPUBFUN void XMLCALL + xmlXPathRegisterAllFunctions (xmlXPathContextPtr ctxt); +XMLPUBFUN xmlNodeSetPtr XMLCALL + xmlXPathNodeSetMerge (xmlNodeSetPtr val1, + xmlNodeSetPtr val2); +XMLPUBFUN void XMLCALL + xmlXPathNodeSetDel (xmlNodeSetPtr cur, + xmlNodePtr val); +XMLPUBFUN void XMLCALL + xmlXPathNodeSetRemove (xmlNodeSetPtr cur, + int val); +XMLPUBFUN xmlXPathObjectPtr XMLCALL + xmlXPathNewNodeSetList (xmlNodeSetPtr val); +XMLPUBFUN xmlXPathObjectPtr XMLCALL + xmlXPathWrapNodeSet (xmlNodeSetPtr val); +XMLPUBFUN xmlXPathObjectPtr XMLCALL + xmlXPathWrapExternal (void *val); + +XMLPUBFUN int XMLCALL xmlXPathEqualValues(xmlXPathParserContextPtr ctxt); +XMLPUBFUN int XMLCALL xmlXPathNotEqualValues(xmlXPathParserContextPtr ctxt); +XMLPUBFUN int XMLCALL xmlXPathCompareValues(xmlXPathParserContextPtr ctxt, int inf, int strict); +XMLPUBFUN void XMLCALL xmlXPathValueFlipSign(xmlXPathParserContextPtr ctxt); +XMLPUBFUN void XMLCALL xmlXPathAddValues(xmlXPathParserContextPtr ctxt); +XMLPUBFUN void XMLCALL xmlXPathSubValues(xmlXPathParserContextPtr ctxt); +XMLPUBFUN void XMLCALL xmlXPathMultValues(xmlXPathParserContextPtr ctxt); +XMLPUBFUN void XMLCALL xmlXPathDivValues(xmlXPathParserContextPtr ctxt); +XMLPUBFUN void XMLCALL xmlXPathModValues(xmlXPathParserContextPtr ctxt); + +XMLPUBFUN int XMLCALL xmlXPathIsNodeType(const xmlChar *name); + +/* + * Some of the axis navigation routines. + */ +XMLPUBFUN xmlNodePtr XMLCALL xmlXPathNextSelf(xmlXPathParserContextPtr ctxt, + xmlNodePtr cur); +XMLPUBFUN xmlNodePtr XMLCALL xmlXPathNextChild(xmlXPathParserContextPtr ctxt, + xmlNodePtr cur); +XMLPUBFUN xmlNodePtr XMLCALL xmlXPathNextDescendant(xmlXPathParserContextPtr ctxt, + xmlNodePtr cur); +XMLPUBFUN xmlNodePtr XMLCALL xmlXPathNextDescendantOrSelf(xmlXPathParserContextPtr ctxt, + xmlNodePtr cur); +XMLPUBFUN xmlNodePtr XMLCALL xmlXPathNextParent(xmlXPathParserContextPtr ctxt, + xmlNodePtr cur); +XMLPUBFUN xmlNodePtr XMLCALL xmlXPathNextAncestorOrSelf(xmlXPathParserContextPtr ctxt, + xmlNodePtr cur); +XMLPUBFUN xmlNodePtr XMLCALL xmlXPathNextFollowingSibling(xmlXPathParserContextPtr ctxt, + xmlNodePtr cur); +XMLPUBFUN xmlNodePtr XMLCALL xmlXPathNextFollowing(xmlXPathParserContextPtr ctxt, + xmlNodePtr cur); +XMLPUBFUN xmlNodePtr XMLCALL xmlXPathNextNamespace(xmlXPathParserContextPtr ctxt, + xmlNodePtr cur); +XMLPUBFUN xmlNodePtr XMLCALL xmlXPathNextAttribute(xmlXPathParserContextPtr ctxt, + xmlNodePtr cur); +XMLPUBFUN xmlNodePtr XMLCALL xmlXPathNextPreceding(xmlXPathParserContextPtr ctxt, + xmlNodePtr cur); +XMLPUBFUN xmlNodePtr XMLCALL xmlXPathNextAncestor(xmlXPathParserContextPtr ctxt, + xmlNodePtr cur); +XMLPUBFUN xmlNodePtr XMLCALL xmlXPathNextPrecedingSibling(xmlXPathParserContextPtr ctxt, + xmlNodePtr cur); +/* + * The official core of XPath functions. + */ +XMLPUBFUN void XMLCALL xmlXPathLastFunction(xmlXPathParserContextPtr ctxt, int nargs); +XMLPUBFUN void XMLCALL xmlXPathPositionFunction(xmlXPathParserContextPtr ctxt, int nargs); +XMLPUBFUN void XMLCALL xmlXPathCountFunction(xmlXPathParserContextPtr ctxt, int nargs); +XMLPUBFUN void XMLCALL xmlXPathIdFunction(xmlXPathParserContextPtr ctxt, int nargs); +XMLPUBFUN void XMLCALL xmlXPathLocalNameFunction(xmlXPathParserContextPtr ctxt, int nargs); +XMLPUBFUN void XMLCALL xmlXPathNamespaceURIFunction(xmlXPathParserContextPtr ctxt, int nargs); +XMLPUBFUN void XMLCALL xmlXPathStringFunction(xmlXPathParserContextPtr ctxt, int nargs); +XMLPUBFUN void XMLCALL xmlXPathStringLengthFunction(xmlXPathParserContextPtr ctxt, int nargs); +XMLPUBFUN void XMLCALL xmlXPathConcatFunction(xmlXPathParserContextPtr ctxt, int nargs); +XMLPUBFUN void XMLCALL xmlXPathContainsFunction(xmlXPathParserContextPtr ctxt, int nargs); +XMLPUBFUN void XMLCALL xmlXPathStartsWithFunction(xmlXPathParserContextPtr ctxt, int nargs); +XMLPUBFUN void XMLCALL xmlXPathSubstringFunction(xmlXPathParserContextPtr ctxt, int nargs); +XMLPUBFUN void XMLCALL xmlXPathSubstringBeforeFunction(xmlXPathParserContextPtr ctxt, int nargs); +XMLPUBFUN void XMLCALL xmlXPathSubstringAfterFunction(xmlXPathParserContextPtr ctxt, int nargs); +XMLPUBFUN void XMLCALL xmlXPathNormalizeFunction(xmlXPathParserContextPtr ctxt, int nargs); +XMLPUBFUN void XMLCALL xmlXPathTranslateFunction(xmlXPathParserContextPtr ctxt, int nargs); +XMLPUBFUN void XMLCALL xmlXPathNotFunction(xmlXPathParserContextPtr ctxt, int nargs); +XMLPUBFUN void XMLCALL xmlXPathTrueFunction(xmlXPathParserContextPtr ctxt, int nargs); +XMLPUBFUN void XMLCALL xmlXPathFalseFunction(xmlXPathParserContextPtr ctxt, int nargs); +XMLPUBFUN void XMLCALL xmlXPathLangFunction(xmlXPathParserContextPtr ctxt, int nargs); +XMLPUBFUN void XMLCALL xmlXPathNumberFunction(xmlXPathParserContextPtr ctxt, int nargs); +XMLPUBFUN void XMLCALL xmlXPathSumFunction(xmlXPathParserContextPtr ctxt, int nargs); +XMLPUBFUN void XMLCALL xmlXPathFloorFunction(xmlXPathParserContextPtr ctxt, int nargs); +XMLPUBFUN void XMLCALL xmlXPathCeilingFunction(xmlXPathParserContextPtr ctxt, int nargs); +XMLPUBFUN void XMLCALL xmlXPathRoundFunction(xmlXPathParserContextPtr ctxt, int nargs); +XMLPUBFUN void XMLCALL xmlXPathBooleanFunction(xmlXPathParserContextPtr ctxt, int nargs); + +/** + * Really internal functions + */ +XMLPUBFUN void XMLCALL xmlXPathNodeSetFreeNs(xmlNsPtr ns); + +#ifdef __cplusplus +} +#endif + +#endif /* LIBXML_XPATH_ENABLED */ +#endif /* ! __XML_XPATH_INTERNALS_H__ */ diff --git a/gettext-tools/gnulib-lib/libxml/xpointer.c b/gettext-tools/gnulib-lib/libxml/xpointer.c new file mode 100644 index 0000000..5298fa5 --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/xpointer.c @@ -0,0 +1,3003 @@ +/* + * xpointer.c : Code to handle XML Pointer + * + * Base implementation was made accordingly to + * W3C Candidate Recommendation 7 June 2000 + * http://www.w3.org/TR/2000/CR-xptr-20000607 + * + * Added support for the element() scheme described in: + * W3C Proposed Recommendation 13 November 2002 + * http://www.w3.org/TR/2002/PR-xptr-element-20021113/ + * + * See Copyright for the status of this software. + * + * daniel@veillard.com + */ + +#define IN_LIBXML +#include "libxml.h" + +/* + * TODO: better handling of error cases, the full expression should + * be parsed beforehand instead of a progressive evaluation + * TODO: Access into entities references are not supported now ... + * need a start to be able to pop out of entities refs since + * parent is the endity declaration, not the ref. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef LIBXML_XPTR_ENABLED + +/* Add support of the xmlns() xpointer scheme to initialize the namespaces */ +#define XPTR_XMLNS_SCHEME + +/* #define DEBUG_RANGES */ +#ifdef DEBUG_RANGES +#ifdef LIBXML_DEBUG_ENABLED +#include +#endif +#endif + +#define TODO \ + xmlGenericError(xmlGenericErrorContext, \ + "Unimplemented block at %s:%d\n", \ + __FILE__, __LINE__); + +#define STRANGE \ + xmlGenericError(xmlGenericErrorContext, \ + "Internal error at %s:%d\n", \ + __FILE__, __LINE__); + +/************************************************************************ + * * + * Some factorized error routines * + * * + ************************************************************************/ + +/** + * xmlXPtrErrMemory: + * @extra: extra informations + * + * Handle a redefinition of attribute error + */ +static void +xmlXPtrErrMemory(const char *extra) +{ + __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_XPOINTER, + XML_ERR_NO_MEMORY, XML_ERR_ERROR, NULL, 0, extra, + NULL, NULL, 0, 0, + "Memory allocation failed : %s\n", extra); +} + +/** + * xmlXPtrErr: + * @ctxt: an XPTR evaluation context + * @extra: extra informations + * + * Handle a redefinition of attribute error + */ +static void +xmlXPtrErr(xmlXPathParserContextPtr ctxt, int error, + const char * msg, const xmlChar *extra) +{ + if (ctxt != NULL) + ctxt->error = error; + if ((ctxt == NULL) || (ctxt->context == NULL)) { + __xmlRaiseError(NULL, NULL, NULL, + NULL, NULL, XML_FROM_XPOINTER, error, + XML_ERR_ERROR, NULL, 0, + (const char *) extra, NULL, NULL, 0, 0, + msg, extra); + return; + } + ctxt->context->lastError.domain = XML_FROM_XPOINTER; + ctxt->context->lastError.code = error; + ctxt->context->lastError.level = XML_ERR_ERROR; + ctxt->context->lastError.str1 = (char *) xmlStrdup(ctxt->base); + ctxt->context->lastError.int1 = ctxt->cur - ctxt->base; + ctxt->context->lastError.node = ctxt->context->debugNode; + if (ctxt->context->error != NULL) { + ctxt->context->error(ctxt->context->userData, + &ctxt->context->lastError); + } else { + __xmlRaiseError(NULL, NULL, NULL, + NULL, ctxt->context->debugNode, XML_FROM_XPOINTER, + error, XML_ERR_ERROR, NULL, 0, + (const char *) extra, (const char *) ctxt->base, NULL, + ctxt->cur - ctxt->base, 0, + msg, extra); + } +} + +/************************************************************************ + * * + * A few helper functions for child sequences * + * * + ************************************************************************/ +/* xmlXPtrAdvanceNode is a private function, but used by xinclude.c */ +xmlNodePtr xmlXPtrAdvanceNode(xmlNodePtr cur, int *level); +/** + * xmlXPtrGetArity: + * @cur: the node + * + * Returns the number of child for an element, -1 in case of error + */ +static int +xmlXPtrGetArity(xmlNodePtr cur) { + int i; + if (cur == NULL) + return(-1); + cur = cur->children; + for (i = 0;cur != NULL;cur = cur->next) { + if ((cur->type == XML_ELEMENT_NODE) || + (cur->type == XML_DOCUMENT_NODE) || + (cur->type == XML_HTML_DOCUMENT_NODE)) { + i++; + } + } + return(i); +} + +/** + * xmlXPtrGetIndex: + * @cur: the node + * + * Returns the index of the node in its parent children list, -1 + * in case of error + */ +static int +xmlXPtrGetIndex(xmlNodePtr cur) { + int i; + if (cur == NULL) + return(-1); + for (i = 1;cur != NULL;cur = cur->prev) { + if ((cur->type == XML_ELEMENT_NODE) || + (cur->type == XML_DOCUMENT_NODE) || + (cur->type == XML_HTML_DOCUMENT_NODE)) { + i++; + } + } + return(i); +} + +/** + * xmlXPtrGetNthChild: + * @cur: the node + * @no: the child number + * + * Returns the @no'th element child of @cur or NULL + */ +static xmlNodePtr +xmlXPtrGetNthChild(xmlNodePtr cur, int no) { + int i; + if (cur == NULL) + return(cur); + cur = cur->children; + for (i = 0;i <= no;cur = cur->next) { + if (cur == NULL) + return(cur); + if ((cur->type == XML_ELEMENT_NODE) || + (cur->type == XML_DOCUMENT_NODE) || + (cur->type == XML_HTML_DOCUMENT_NODE)) { + i++; + if (i == no) + break; + } + } + return(cur); +} + +/************************************************************************ + * * + * Handling of XPointer specific types * + * * + ************************************************************************/ + +/** + * xmlXPtrCmpPoints: + * @node1: the first node + * @index1: the first index + * @node2: the second node + * @index2: the second index + * + * Compare two points w.r.t document order + * + * Returns -2 in case of error 1 if first point < second point, 0 if + * that's the same point, -1 otherwise + */ +static int +xmlXPtrCmpPoints(xmlNodePtr node1, int index1, xmlNodePtr node2, int index2) { + if ((node1 == NULL) || (node2 == NULL)) + return(-2); + /* + * a couple of optimizations which will avoid computations in most cases + */ + if (node1 == node2) { + if (index1 < index2) + return(1); + if (index1 > index2) + return(-1); + return(0); + } + return(xmlXPathCmpNodes(node1, node2)); +} + +/** + * xmlXPtrNewPoint: + * @node: the xmlNodePtr + * @indx: the indx within the node + * + * Create a new xmlXPathObjectPtr of type point + * + * Returns the newly created object. + */ +static xmlXPathObjectPtr +xmlXPtrNewPoint(xmlNodePtr node, int indx) { + xmlXPathObjectPtr ret; + + if (node == NULL) + return(NULL); + if (indx < 0) + return(NULL); + + ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject)); + if (ret == NULL) { + xmlXPtrErrMemory("allocating point"); + return(NULL); + } + memset(ret, 0 , (size_t) sizeof(xmlXPathObject)); + ret->type = XPATH_POINT; + ret->user = (void *) node; + ret->index = indx; + return(ret); +} + +/** + * xmlXPtrRangeCheckOrder: + * @range: an object range + * + * Make sure the points in the range are in the right order + */ +static void +xmlXPtrRangeCheckOrder(xmlXPathObjectPtr range) { + int tmp; + xmlNodePtr tmp2; + if (range == NULL) + return; + if (range->type != XPATH_RANGE) + return; + if (range->user2 == NULL) + return; + tmp = xmlXPtrCmpPoints(range->user, range->index, + range->user2, range->index2); + if (tmp == -1) { + tmp2 = range->user; + range->user = range->user2; + range->user2 = tmp2; + tmp = range->index; + range->index = range->index2; + range->index2 = tmp; + } +} + +/** + * xmlXPtrRangesEqual: + * @range1: the first range + * @range2: the second range + * + * Compare two ranges + * + * Returns 1 if equal, 0 otherwise + */ +static int +xmlXPtrRangesEqual(xmlXPathObjectPtr range1, xmlXPathObjectPtr range2) { + if (range1 == range2) + return(1); + if ((range1 == NULL) || (range2 == NULL)) + return(0); + if (range1->type != range2->type) + return(0); + if (range1->type != XPATH_RANGE) + return(0); + if (range1->user != range2->user) + return(0); + if (range1->index != range2->index) + return(0); + if (range1->user2 != range2->user2) + return(0); + if (range1->index2 != range2->index2) + return(0); + return(1); +} + +/** + * xmlXPtrNewRange: + * @start: the starting node + * @startindex: the start index + * @end: the ending point + * @endindex: the ending index + * + * Create a new xmlXPathObjectPtr of type range + * + * Returns the newly created object. + */ +xmlXPathObjectPtr +xmlXPtrNewRange(xmlNodePtr start, int startindex, + xmlNodePtr end, int endindex) { + xmlXPathObjectPtr ret; + + if (start == NULL) + return(NULL); + if (end == NULL) + return(NULL); + if (startindex < 0) + return(NULL); + if (endindex < 0) + return(NULL); + + ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject)); + if (ret == NULL) { + xmlXPtrErrMemory("allocating range"); + return(NULL); + } + memset(ret, 0 , (size_t) sizeof(xmlXPathObject)); + ret->type = XPATH_RANGE; + ret->user = start; + ret->index = startindex; + ret->user2 = end; + ret->index2 = endindex; + xmlXPtrRangeCheckOrder(ret); + return(ret); +} + +/** + * xmlXPtrNewRangePoints: + * @start: the starting point + * @end: the ending point + * + * Create a new xmlXPathObjectPtr of type range using 2 Points + * + * Returns the newly created object. + */ +xmlXPathObjectPtr +xmlXPtrNewRangePoints(xmlXPathObjectPtr start, xmlXPathObjectPtr end) { + xmlXPathObjectPtr ret; + + if (start == NULL) + return(NULL); + if (end == NULL) + return(NULL); + if (start->type != XPATH_POINT) + return(NULL); + if (end->type != XPATH_POINT) + return(NULL); + + ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject)); + if (ret == NULL) { + xmlXPtrErrMemory("allocating range"); + return(NULL); + } + memset(ret, 0 , (size_t) sizeof(xmlXPathObject)); + ret->type = XPATH_RANGE; + ret->user = start->user; + ret->index = start->index; + ret->user2 = end->user; + ret->index2 = end->index; + xmlXPtrRangeCheckOrder(ret); + return(ret); +} + +/** + * xmlXPtrNewRangePointNode: + * @start: the starting point + * @end: the ending node + * + * Create a new xmlXPathObjectPtr of type range from a point to a node + * + * Returns the newly created object. + */ +xmlXPathObjectPtr +xmlXPtrNewRangePointNode(xmlXPathObjectPtr start, xmlNodePtr end) { + xmlXPathObjectPtr ret; + + if (start == NULL) + return(NULL); + if (end == NULL) + return(NULL); + if (start->type != XPATH_POINT) + return(NULL); + + ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject)); + if (ret == NULL) { + xmlXPtrErrMemory("allocating range"); + return(NULL); + } + memset(ret, 0 , (size_t) sizeof(xmlXPathObject)); + ret->type = XPATH_RANGE; + ret->user = start->user; + ret->index = start->index; + ret->user2 = end; + ret->index2 = -1; + xmlXPtrRangeCheckOrder(ret); + return(ret); +} + +/** + * xmlXPtrNewRangeNodePoint: + * @start: the starting node + * @end: the ending point + * + * Create a new xmlXPathObjectPtr of type range from a node to a point + * + * Returns the newly created object. + */ +xmlXPathObjectPtr +xmlXPtrNewRangeNodePoint(xmlNodePtr start, xmlXPathObjectPtr end) { + xmlXPathObjectPtr ret; + + if (start == NULL) + return(NULL); + if (end == NULL) + return(NULL); + if (start->type != XPATH_POINT) + return(NULL); + if (end->type != XPATH_POINT) + return(NULL); + + ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject)); + if (ret == NULL) { + xmlXPtrErrMemory("allocating range"); + return(NULL); + } + memset(ret, 0 , (size_t) sizeof(xmlXPathObject)); + ret->type = XPATH_RANGE; + ret->user = start; + ret->index = -1; + ret->user2 = end->user; + ret->index2 = end->index; + xmlXPtrRangeCheckOrder(ret); + return(ret); +} + +/** + * xmlXPtrNewRangeNodes: + * @start: the starting node + * @end: the ending node + * + * Create a new xmlXPathObjectPtr of type range using 2 nodes + * + * Returns the newly created object. + */ +xmlXPathObjectPtr +xmlXPtrNewRangeNodes(xmlNodePtr start, xmlNodePtr end) { + xmlXPathObjectPtr ret; + + if (start == NULL) + return(NULL); + if (end == NULL) + return(NULL); + + ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject)); + if (ret == NULL) { + xmlXPtrErrMemory("allocating range"); + return(NULL); + } + memset(ret, 0 , (size_t) sizeof(xmlXPathObject)); + ret->type = XPATH_RANGE; + ret->user = start; + ret->index = -1; + ret->user2 = end; + ret->index2 = -1; + xmlXPtrRangeCheckOrder(ret); + return(ret); +} + +/** + * xmlXPtrNewCollapsedRange: + * @start: the starting and ending node + * + * Create a new xmlXPathObjectPtr of type range using a single nodes + * + * Returns the newly created object. + */ +xmlXPathObjectPtr +xmlXPtrNewCollapsedRange(xmlNodePtr start) { + xmlXPathObjectPtr ret; + + if (start == NULL) + return(NULL); + + ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject)); + if (ret == NULL) { + xmlXPtrErrMemory("allocating range"); + return(NULL); + } + memset(ret, 0 , (size_t) sizeof(xmlXPathObject)); + ret->type = XPATH_RANGE; + ret->user = start; + ret->index = -1; + ret->user2 = NULL; + ret->index2 = -1; + return(ret); +} + +/** + * xmlXPtrNewRangeNodeObject: + * @start: the starting node + * @end: the ending object + * + * Create a new xmlXPathObjectPtr of type range from a not to an object + * + * Returns the newly created object. + */ +xmlXPathObjectPtr +xmlXPtrNewRangeNodeObject(xmlNodePtr start, xmlXPathObjectPtr end) { + xmlXPathObjectPtr ret; + + if (start == NULL) + return(NULL); + if (end == NULL) + return(NULL); + switch (end->type) { + case XPATH_POINT: + case XPATH_RANGE: + break; + case XPATH_NODESET: + /* + * Empty set ... + */ + if (end->nodesetval->nodeNr <= 0) + return(NULL); + break; + default: + /* TODO */ + return(NULL); + } + + ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject)); + if (ret == NULL) { + xmlXPtrErrMemory("allocating range"); + return(NULL); + } + memset(ret, 0 , (size_t) sizeof(xmlXPathObject)); + ret->type = XPATH_RANGE; + ret->user = start; + ret->index = -1; + switch (end->type) { + case XPATH_POINT: + ret->user2 = end->user; + ret->index2 = end->index; + break; + case XPATH_RANGE: + ret->user2 = end->user2; + ret->index2 = end->index2; + break; + case XPATH_NODESET: { + ret->user2 = end->nodesetval->nodeTab[end->nodesetval->nodeNr - 1]; + ret->index2 = -1; + break; + } + default: + STRANGE + return(NULL); + } + xmlXPtrRangeCheckOrder(ret); + return(ret); +} + +#define XML_RANGESET_DEFAULT 10 + +/** + * xmlXPtrLocationSetCreate: + * @val: an initial xmlXPathObjectPtr, or NULL + * + * Create a new xmlLocationSetPtr of type double and of value @val + * + * Returns the newly created object. + */ +xmlLocationSetPtr +xmlXPtrLocationSetCreate(xmlXPathObjectPtr val) { + xmlLocationSetPtr ret; + + ret = (xmlLocationSetPtr) xmlMalloc(sizeof(xmlLocationSet)); + if (ret == NULL) { + xmlXPtrErrMemory("allocating locationset"); + return(NULL); + } + memset(ret, 0 , (size_t) sizeof(xmlLocationSet)); + if (val != NULL) { + ret->locTab = (xmlXPathObjectPtr *) xmlMalloc(XML_RANGESET_DEFAULT * + sizeof(xmlXPathObjectPtr)); + if (ret->locTab == NULL) { + xmlXPtrErrMemory("allocating locationset"); + xmlFree(ret); + return(NULL); + } + memset(ret->locTab, 0 , + XML_RANGESET_DEFAULT * (size_t) sizeof(xmlXPathObjectPtr)); + ret->locMax = XML_RANGESET_DEFAULT; + ret->locTab[ret->locNr++] = val; + } + return(ret); +} + +/** + * xmlXPtrLocationSetAdd: + * @cur: the initial range set + * @val: a new xmlXPathObjectPtr + * + * add a new xmlXPathObjectPtr to an existing LocationSet + * If the location already exist in the set @val is freed. + */ +void +xmlXPtrLocationSetAdd(xmlLocationSetPtr cur, xmlXPathObjectPtr val) { + int i; + + if ((cur == NULL) || (val == NULL)) return; + + /* + * check against doublons + */ + for (i = 0;i < cur->locNr;i++) { + if (xmlXPtrRangesEqual(cur->locTab[i], val)) { + xmlXPathFreeObject(val); + return; + } + } + + /* + * grow the locTab if needed + */ + if (cur->locMax == 0) { + cur->locTab = (xmlXPathObjectPtr *) xmlMalloc(XML_RANGESET_DEFAULT * + sizeof(xmlXPathObjectPtr)); + if (cur->locTab == NULL) { + xmlXPtrErrMemory("adding location to set"); + return; + } + memset(cur->locTab, 0 , + XML_RANGESET_DEFAULT * (size_t) sizeof(xmlXPathObjectPtr)); + cur->locMax = XML_RANGESET_DEFAULT; + } else if (cur->locNr == cur->locMax) { + xmlXPathObjectPtr *temp; + + cur->locMax *= 2; + temp = (xmlXPathObjectPtr *) xmlRealloc(cur->locTab, cur->locMax * + sizeof(xmlXPathObjectPtr)); + if (temp == NULL) { + xmlXPtrErrMemory("adding location to set"); + return; + } + cur->locTab = temp; + } + cur->locTab[cur->locNr++] = val; +} + +/** + * xmlXPtrLocationSetMerge: + * @val1: the first LocationSet + * @val2: the second LocationSet + * + * Merges two rangesets, all ranges from @val2 are added to @val1 + * + * Returns val1 once extended or NULL in case of error. + */ +xmlLocationSetPtr +xmlXPtrLocationSetMerge(xmlLocationSetPtr val1, xmlLocationSetPtr val2) { + int i; + + if (val1 == NULL) return(NULL); + if (val2 == NULL) return(val1); + + /* + * !!!!! this can be optimized a lot, knowing that both + * val1 and val2 already have unicity of their values. + */ + + for (i = 0;i < val2->locNr;i++) + xmlXPtrLocationSetAdd(val1, val2->locTab[i]); + + return(val1); +} + +/** + * xmlXPtrLocationSetDel: + * @cur: the initial range set + * @val: an xmlXPathObjectPtr + * + * Removes an xmlXPathObjectPtr from an existing LocationSet + */ +void +xmlXPtrLocationSetDel(xmlLocationSetPtr cur, xmlXPathObjectPtr val) { + int i; + + if (cur == NULL) return; + if (val == NULL) return; + + /* + * check against doublons + */ + for (i = 0;i < cur->locNr;i++) + if (cur->locTab[i] == val) break; + + if (i >= cur->locNr) { +#ifdef DEBUG + xmlGenericError(xmlGenericErrorContext, + "xmlXPtrLocationSetDel: Range wasn't found in RangeList\n"); +#endif + return; + } + cur->locNr--; + for (;i < cur->locNr;i++) + cur->locTab[i] = cur->locTab[i + 1]; + cur->locTab[cur->locNr] = NULL; +} + +/** + * xmlXPtrLocationSetRemove: + * @cur: the initial range set + * @val: the index to remove + * + * Removes an entry from an existing LocationSet list. + */ +void +xmlXPtrLocationSetRemove(xmlLocationSetPtr cur, int val) { + if (cur == NULL) return; + if (val >= cur->locNr) return; + cur->locNr--; + for (;val < cur->locNr;val++) + cur->locTab[val] = cur->locTab[val + 1]; + cur->locTab[cur->locNr] = NULL; +} + +/** + * xmlXPtrFreeLocationSet: + * @obj: the xmlLocationSetPtr to free + * + * Free the LocationSet compound (not the actual ranges !). + */ +void +xmlXPtrFreeLocationSet(xmlLocationSetPtr obj) { + int i; + + if (obj == NULL) return; + if (obj->locTab != NULL) { + for (i = 0;i < obj->locNr; i++) { + xmlXPathFreeObject(obj->locTab[i]); + } + xmlFree(obj->locTab); + } + xmlFree(obj); +} + +/** + * xmlXPtrNewLocationSetNodes: + * @start: the start NodePtr value + * @end: the end NodePtr value or NULL + * + * Create a new xmlXPathObjectPtr of type LocationSet and initialize + * it with the single range made of the two nodes @start and @end + * + * Returns the newly created object. + */ +xmlXPathObjectPtr +xmlXPtrNewLocationSetNodes(xmlNodePtr start, xmlNodePtr end) { + xmlXPathObjectPtr ret; + + ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject)); + if (ret == NULL) { + xmlXPtrErrMemory("allocating locationset"); + return(NULL); + } + memset(ret, 0 , (size_t) sizeof(xmlXPathObject)); + ret->type = XPATH_LOCATIONSET; + if (end == NULL) + ret->user = xmlXPtrLocationSetCreate(xmlXPtrNewCollapsedRange(start)); + else + ret->user = xmlXPtrLocationSetCreate(xmlXPtrNewRangeNodes(start,end)); + return(ret); +} + +/** + * xmlXPtrNewLocationSetNodeSet: + * @set: a node set + * + * Create a new xmlXPathObjectPtr of type LocationSet and initialize + * it with all the nodes from @set + * + * Returns the newly created object. + */ +xmlXPathObjectPtr +xmlXPtrNewLocationSetNodeSet(xmlNodeSetPtr set) { + xmlXPathObjectPtr ret; + + ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject)); + if (ret == NULL) { + xmlXPtrErrMemory("allocating locationset"); + return(NULL); + } + memset(ret, 0 , (size_t) sizeof(xmlXPathObject)); + ret->type = XPATH_LOCATIONSET; + if (set != NULL) { + int i; + xmlLocationSetPtr newset; + + newset = xmlXPtrLocationSetCreate(NULL); + if (newset == NULL) + return(ret); + + for (i = 0;i < set->nodeNr;i++) + xmlXPtrLocationSetAdd(newset, + xmlXPtrNewCollapsedRange(set->nodeTab[i])); + + ret->user = (void *) newset; + } + return(ret); +} + +/** + * xmlXPtrWrapLocationSet: + * @val: the LocationSet value + * + * Wrap the LocationSet @val in a new xmlXPathObjectPtr + * + * Returns the newly created object. + */ +xmlXPathObjectPtr +xmlXPtrWrapLocationSet(xmlLocationSetPtr val) { + xmlXPathObjectPtr ret; + + ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject)); + if (ret == NULL) { + xmlXPtrErrMemory("allocating locationset"); + return(NULL); + } + memset(ret, 0 , (size_t) sizeof(xmlXPathObject)); + ret->type = XPATH_LOCATIONSET; + ret->user = (void *) val; + return(ret); +} + +/************************************************************************ + * * + * The parser * + * * + ************************************************************************/ + +static void xmlXPtrEvalChildSeq(xmlXPathParserContextPtr ctxt, xmlChar *name); + +/* + * Macros for accessing the content. Those should be used only by the parser, + * and not exported. + * + * Dirty macros, i.e. one need to make assumption on the context to use them + * + * CUR_PTR return the current pointer to the xmlChar to be parsed. + * CUR returns the current xmlChar value, i.e. a 8 bit value + * in ISO-Latin or UTF-8. + * This should be used internally by the parser + * only to compare to ASCII values otherwise it would break when + * running with UTF-8 encoding. + * NXT(n) returns the n'th next xmlChar. Same as CUR is should be used only + * to compare on ASCII based substring. + * SKIP(n) Skip n xmlChar, and must also be used only to skip ASCII defined + * strings within the parser. + * CURRENT Returns the current char value, with the full decoding of + * UTF-8 if we are using this mode. It returns an int. + * NEXT Skip to the next character, this does the proper decoding + * in UTF-8 mode. It also pop-up unfinished entities on the fly. + * It returns the pointer to the current xmlChar. + */ + +#define CUR (*ctxt->cur) +#define SKIP(val) ctxt->cur += (val) +#define NXT(val) ctxt->cur[(val)] +#define CUR_PTR ctxt->cur + +#define SKIP_BLANKS \ + while (IS_BLANK_CH(*(ctxt->cur))) NEXT + +#define CURRENT (*ctxt->cur) +#define NEXT ((*ctxt->cur) ? ctxt->cur++: ctxt->cur) + +/* + * xmlXPtrGetChildNo: + * @ctxt: the XPointer Parser context + * @index: the child number + * + * Move the current node of the nodeset on the stack to the + * given child if found + */ +static void +xmlXPtrGetChildNo(xmlXPathParserContextPtr ctxt, int indx) { + xmlNodePtr cur = NULL; + xmlXPathObjectPtr obj; + xmlNodeSetPtr oldset; + + CHECK_TYPE(XPATH_NODESET); + obj = valuePop(ctxt); + oldset = obj->nodesetval; + if ((indx <= 0) || (oldset == NULL) || (oldset->nodeNr != 1)) { + xmlXPathFreeObject(obj); + valuePush(ctxt, xmlXPathNewNodeSet(NULL)); + return; + } + cur = xmlXPtrGetNthChild(oldset->nodeTab[0], indx); + if (cur == NULL) { + xmlXPathFreeObject(obj); + valuePush(ctxt, xmlXPathNewNodeSet(NULL)); + return; + } + oldset->nodeTab[0] = cur; + valuePush(ctxt, obj); +} + +/** + * xmlXPtrEvalXPtrPart: + * @ctxt: the XPointer Parser context + * @name: the preparsed Scheme for the XPtrPart + * + * XPtrPart ::= 'xpointer' '(' XPtrExpr ')' + * | Scheme '(' SchemeSpecificExpr ')' + * + * Scheme ::= NCName - 'xpointer' [VC: Non-XPointer schemes] + * + * SchemeSpecificExpr ::= StringWithBalancedParens + * + * StringWithBalancedParens ::= + * [^()]* ('(' StringWithBalancedParens ')' [^()]*)* + * [VC: Parenthesis escaping] + * + * XPtrExpr ::= Expr [VC: Parenthesis escaping] + * + * VC: Parenthesis escaping: + * The end of an XPointer part is signaled by the right parenthesis ")" + * character that is balanced with the left parenthesis "(" character + * that began the part. Any unbalanced parenthesis character inside the + * expression, even within literals, must be escaped with a circumflex (^) + * character preceding it. If the expression contains any literal + * occurrences of the circumflex, each must be escaped with an additional + * circumflex (that is, ^^). If the unescaped parentheses in the expression + * are not balanced, a syntax error results. + * + * Parse and evaluate an XPtrPart. Basically it generates the unescaped + * string and if the scheme is 'xpointer' it will call the XPath interpreter. + * + * TODO: there is no new scheme registration mechanism + */ + +static void +xmlXPtrEvalXPtrPart(xmlXPathParserContextPtr ctxt, xmlChar *name) { + xmlChar *buffer, *cur; + int len; + int level; + + if (name == NULL) + name = xmlXPathParseName(ctxt); + if (name == NULL) + XP_ERROR(XPATH_EXPR_ERROR); + + if (CUR != '(') + XP_ERROR(XPATH_EXPR_ERROR); + NEXT; + level = 1; + + len = xmlStrlen(ctxt->cur); + len++; + buffer = (xmlChar *) xmlMallocAtomic(len * sizeof (xmlChar)); + if (buffer == NULL) { + xmlXPtrErrMemory("allocating buffer"); + return; + } + + cur = buffer; + while (CUR != 0) { + if (CUR == ')') { + level--; + if (level == 0) { + NEXT; + break; + } + *cur++ = CUR; + } else if (CUR == '(') { + level++; + *cur++ = CUR; + } else if (CUR == '^') { + NEXT; + if ((CUR == ')') || (CUR == '(') || (CUR == '^')) { + *cur++ = CUR; + } else { + *cur++ = '^'; + *cur++ = CUR; + } + } else { + *cur++ = CUR; + } + NEXT; + } + *cur = 0; + + if ((level != 0) && (CUR == 0)) { + xmlFree(buffer); + XP_ERROR(XPTR_SYNTAX_ERROR); + } + + if (xmlStrEqual(name, (xmlChar *) "xpointer")) { + const xmlChar *left = CUR_PTR; + + CUR_PTR = buffer; + /* + * To evaluate an xpointer scheme element (4.3) we need: + * context initialized to the root + * context position initalized to 1 + * context size initialized to 1 + */ + ctxt->context->node = (xmlNodePtr)ctxt->context->doc; + ctxt->context->proximityPosition = 1; + ctxt->context->contextSize = 1; + xmlXPathEvalExpr(ctxt); + CUR_PTR=left; + } else if (xmlStrEqual(name, (xmlChar *) "element")) { + const xmlChar *left = CUR_PTR; + xmlChar *name2; + + CUR_PTR = buffer; + if (buffer[0] == '/') { + xmlXPathRoot(ctxt); + xmlXPtrEvalChildSeq(ctxt, NULL); + } else { + name2 = xmlXPathParseName(ctxt); + if (name2 == NULL) { + CUR_PTR = left; + xmlFree(buffer); + XP_ERROR(XPATH_EXPR_ERROR); + } + xmlXPtrEvalChildSeq(ctxt, name2); + } + CUR_PTR = left; +#ifdef XPTR_XMLNS_SCHEME + } else if (xmlStrEqual(name, (xmlChar *) "xmlns")) { + const xmlChar *left = CUR_PTR; + xmlChar *prefix; + xmlChar *URI; + xmlURIPtr value; + + CUR_PTR = buffer; + prefix = xmlXPathParseNCName(ctxt); + if (prefix == NULL) { + xmlFree(buffer); + xmlFree(name); + XP_ERROR(XPTR_SYNTAX_ERROR); + } + SKIP_BLANKS; + if (CUR != '=') { + xmlFree(prefix); + xmlFree(buffer); + xmlFree(name); + XP_ERROR(XPTR_SYNTAX_ERROR); + } + NEXT; + SKIP_BLANKS; + /* @@ check escaping in the XPointer WD */ + + value = xmlParseURI((const char *)ctxt->cur); + if (value == NULL) { + xmlFree(prefix); + xmlFree(buffer); + xmlFree(name); + XP_ERROR(XPTR_SYNTAX_ERROR); + } + URI = xmlSaveUri(value); + xmlFreeURI(value); + if (URI == NULL) { + xmlFree(prefix); + xmlFree(buffer); + xmlFree(name); + XP_ERROR(XPATH_MEMORY_ERROR); + } + + xmlXPathRegisterNs(ctxt->context, prefix, URI); + CUR_PTR = left; + xmlFree(URI); + xmlFree(prefix); +#endif /* XPTR_XMLNS_SCHEME */ + } else { + xmlXPtrErr(ctxt, XML_XPTR_UNKNOWN_SCHEME, + "unsupported scheme '%s'\n", name); + } + xmlFree(buffer); + xmlFree(name); +} + +/** + * xmlXPtrEvalFullXPtr: + * @ctxt: the XPointer Parser context + * @name: the preparsed Scheme for the first XPtrPart + * + * FullXPtr ::= XPtrPart (S? XPtrPart)* + * + * As the specs says: + * ----------- + * When multiple XPtrParts are provided, they must be evaluated in + * left-to-right order. If evaluation of one part fails, the nexti + * is evaluated. The following conditions cause XPointer part failure: + * + * - An unknown scheme + * - A scheme that does not locate any sub-resource present in the resource + * - A scheme that is not applicable to the media type of the resource + * + * The XPointer application must consume a failed XPointer part and + * attempt to evaluate the next one, if any. The result of the first + * XPointer part whose evaluation succeeds is taken to be the fragment + * located by the XPointer as a whole. If all the parts fail, the result + * for the XPointer as a whole is a sub-resource error. + * ----------- + * + * Parse and evaluate a Full XPtr i.e. possibly a cascade of XPath based + * expressions or other schemes. + */ +static void +xmlXPtrEvalFullXPtr(xmlXPathParserContextPtr ctxt, xmlChar *name) { + if (name == NULL) + name = xmlXPathParseName(ctxt); + if (name == NULL) + XP_ERROR(XPATH_EXPR_ERROR); + while (name != NULL) { + xmlXPtrEvalXPtrPart(ctxt, name); + + /* in case of syntax error, break here */ + if (ctxt->error != XPATH_EXPRESSION_OK) + return; + + /* + * If the returned value is a non-empty nodeset + * or location set, return here. + */ + if (ctxt->value != NULL) { + xmlXPathObjectPtr obj = ctxt->value; + + switch (obj->type) { + case XPATH_LOCATIONSET: { + xmlLocationSetPtr loc = ctxt->value->user; + if ((loc != NULL) && (loc->locNr > 0)) + return; + break; + } + case XPATH_NODESET: { + xmlNodeSetPtr loc = ctxt->value->nodesetval; + if ((loc != NULL) && (loc->nodeNr > 0)) + return; + break; + } + default: + break; + } + + /* + * Evaluating to improper values is equivalent to + * a sub-resource error, clean-up the stack + */ + do { + obj = valuePop(ctxt); + if (obj != NULL) { + xmlXPathFreeObject(obj); + } + } while (obj != NULL); + } + + /* + * Is there another XPointer part. + */ + SKIP_BLANKS; + name = xmlXPathParseName(ctxt); + } +} + +/** + * xmlXPtrEvalChildSeq: + * @ctxt: the XPointer Parser context + * @name: a possible ID name of the child sequence + * + * ChildSeq ::= '/1' ('/' [0-9]*)* + * | Name ('/' [0-9]*)+ + * + * Parse and evaluate a Child Sequence. This routine also handle the + * case of a Bare Name used to get a document ID. + */ +static void +xmlXPtrEvalChildSeq(xmlXPathParserContextPtr ctxt, xmlChar *name) { + /* + * XPointer don't allow by syntax to address in mutirooted trees + * this might prove useful in some cases, warn about it. + */ + if ((name == NULL) && (CUR == '/') && (NXT(1) != '1')) { + xmlXPtrErr(ctxt, XML_XPTR_CHILDSEQ_START, + "warning: ChildSeq not starting by /1\n", NULL); + } + + if (name != NULL) { + valuePush(ctxt, xmlXPathNewString(name)); + xmlFree(name); + xmlXPathIdFunction(ctxt, 1); + CHECK_ERROR; + } + + while (CUR == '/') { + int child = 0; + NEXT; + + while ((CUR >= '0') && (CUR <= '9')) { + child = child * 10 + (CUR - '0'); + NEXT; + } + xmlXPtrGetChildNo(ctxt, child); + } +} + + +/** + * xmlXPtrEvalXPointer: + * @ctxt: the XPointer Parser context + * + * XPointer ::= Name + * | ChildSeq + * | FullXPtr + * + * Parse and evaluate an XPointer + */ +static void +xmlXPtrEvalXPointer(xmlXPathParserContextPtr ctxt) { + if (ctxt->valueTab == NULL) { + /* Allocate the value stack */ + ctxt->valueTab = (xmlXPathObjectPtr *) + xmlMalloc(10 * sizeof(xmlXPathObjectPtr)); + if (ctxt->valueTab == NULL) { + xmlXPtrErrMemory("allocating evaluation context"); + return; + } + ctxt->valueNr = 0; + ctxt->valueMax = 10; + ctxt->value = NULL; + } + SKIP_BLANKS; + if (CUR == '/') { + xmlXPathRoot(ctxt); + xmlXPtrEvalChildSeq(ctxt, NULL); + } else { + xmlChar *name; + + name = xmlXPathParseName(ctxt); + if (name == NULL) + XP_ERROR(XPATH_EXPR_ERROR); + if (CUR == '(') { + xmlXPtrEvalFullXPtr(ctxt, name); + /* Short evaluation */ + return; + } else { + /* this handle both Bare Names and Child Sequences */ + xmlXPtrEvalChildSeq(ctxt, name); + } + } + SKIP_BLANKS; + if (CUR != 0) + XP_ERROR(XPATH_EXPR_ERROR); +} + + +/************************************************************************ + * * + * General routines * + * * + ************************************************************************/ + +void xmlXPtrStringRangeFunction(xmlXPathParserContextPtr ctxt, int nargs); +void xmlXPtrStartPointFunction(xmlXPathParserContextPtr ctxt, int nargs); +void xmlXPtrEndPointFunction(xmlXPathParserContextPtr ctxt, int nargs); +void xmlXPtrHereFunction(xmlXPathParserContextPtr ctxt, int nargs); +void xmlXPtrOriginFunction(xmlXPathParserContextPtr ctxt, int nargs); +void xmlXPtrRangeInsideFunction(xmlXPathParserContextPtr ctxt, int nargs); +void xmlXPtrRangeFunction(xmlXPathParserContextPtr ctxt, int nargs); + +/** + * xmlXPtrNewContext: + * @doc: the XML document + * @here: the node that directly contains the XPointer being evaluated or NULL + * @origin: the element from which a user or program initiated traversal of + * the link, or NULL. + * + * Create a new XPointer context + * + * Returns the xmlXPathContext just allocated. + */ +xmlXPathContextPtr +xmlXPtrNewContext(xmlDocPtr doc, xmlNodePtr here, xmlNodePtr origin) { + xmlXPathContextPtr ret; + + ret = xmlXPathNewContext(doc); + if (ret == NULL) + return(ret); + ret->xptr = 1; + ret->here = here; + ret->origin = origin; + + xmlXPathRegisterFunc(ret, (xmlChar *)"range-to", + xmlXPtrRangeToFunction); + xmlXPathRegisterFunc(ret, (xmlChar *)"range", + xmlXPtrRangeFunction); + xmlXPathRegisterFunc(ret, (xmlChar *)"range-inside", + xmlXPtrRangeInsideFunction); + xmlXPathRegisterFunc(ret, (xmlChar *)"string-range", + xmlXPtrStringRangeFunction); + xmlXPathRegisterFunc(ret, (xmlChar *)"start-point", + xmlXPtrStartPointFunction); + xmlXPathRegisterFunc(ret, (xmlChar *)"end-point", + xmlXPtrEndPointFunction); + xmlXPathRegisterFunc(ret, (xmlChar *)"here", + xmlXPtrHereFunction); + xmlXPathRegisterFunc(ret, (xmlChar *)" origin", + xmlXPtrOriginFunction); + + return(ret); +} + +/** + * xmlXPtrEval: + * @str: the XPointer expression + * @ctx: the XPointer context + * + * Evaluate the XPath Location Path in the given context. + * + * Returns the xmlXPathObjectPtr resulting from the evaluation or NULL. + * the caller has to free the object. + */ +xmlXPathObjectPtr +xmlXPtrEval(const xmlChar *str, xmlXPathContextPtr ctx) { + xmlXPathParserContextPtr ctxt; + xmlXPathObjectPtr res = NULL, tmp; + xmlXPathObjectPtr init = NULL; + int stack = 0; + + xmlXPathInit(); + + if ((ctx == NULL) || (str == NULL)) + return(NULL); + + ctxt = xmlXPathNewParserContext(str, ctx); + ctxt->xptr = 1; + xmlXPtrEvalXPointer(ctxt); + + if ((ctxt->value != NULL) && + (ctxt->value->type != XPATH_NODESET) && + (ctxt->value->type != XPATH_LOCATIONSET)) { + xmlXPtrErr(ctxt, XML_XPTR_EVAL_FAILED, + "xmlXPtrEval: evaluation failed to return a node set\n", + NULL); + } else { + res = valuePop(ctxt); + } + + do { + tmp = valuePop(ctxt); + if (tmp != NULL) { + if (tmp != init) { + if (tmp->type == XPATH_NODESET) { + /* + * Evaluation may push a root nodeset which is unused + */ + xmlNodeSetPtr set; + set = tmp->nodesetval; + if ((set->nodeNr != 1) || + (set->nodeTab[0] != (xmlNodePtr) ctx->doc)) + stack++; + } else + stack++; + } + xmlXPathFreeObject(tmp); + } + } while (tmp != NULL); + if (stack != 0) { + xmlXPtrErr(ctxt, XML_XPTR_EXTRA_OBJECTS, + "xmlXPtrEval: object(s) left on the eval stack\n", + NULL); + } + if (ctxt->error != XPATH_EXPRESSION_OK) { + xmlXPathFreeObject(res); + res = NULL; + } + + xmlXPathFreeParserContext(ctxt); + return(res); +} + +/** + * xmlXPtrBuildRangeNodeList: + * @range: a range object + * + * Build a node list tree copy of the range + * + * Returns an xmlNodePtr list or NULL. + * the caller has to free the node tree. + */ +static xmlNodePtr +xmlXPtrBuildRangeNodeList(xmlXPathObjectPtr range) { + /* pointers to generated nodes */ + xmlNodePtr list = NULL, last = NULL, parent = NULL, tmp; + /* pointers to traversal nodes */ + xmlNodePtr start, cur, end; + int index1, index2; + + if (range == NULL) + return(NULL); + if (range->type != XPATH_RANGE) + return(NULL); + start = (xmlNodePtr) range->user; + + if (start == NULL) + return(NULL); + end = range->user2; + if (end == NULL) + return(xmlCopyNode(start, 1)); + + cur = start; + index1 = range->index; + index2 = range->index2; + while (cur != NULL) { + if (cur == end) { + if (cur->type == XML_TEXT_NODE) { + const xmlChar *content = cur->content; + int len; + + if (content == NULL) { + tmp = xmlNewTextLen(NULL, 0); + } else { + len = index2; + if ((cur == start) && (index1 > 1)) { + content += (index1 - 1); + len -= (index1 - 1); + index1 = 0; + } else { + len = index2; + } + tmp = xmlNewTextLen(content, len); + } + /* single sub text node selection */ + if (list == NULL) + return(tmp); + /* prune and return full set */ + if (last != NULL) + xmlAddNextSibling(last, tmp); + else + xmlAddChild(parent, tmp); + return(list); + } else { + tmp = xmlCopyNode(cur, 0); + if (list == NULL) + list = tmp; + else { + if (last != NULL) + xmlAddNextSibling(last, tmp); + else + xmlAddChild(parent, tmp); + } + last = NULL; + parent = tmp; + + if (index2 > 1) { + end = xmlXPtrGetNthChild(cur, index2 - 1); + index2 = 0; + } + if ((cur == start) && (index1 > 1)) { + cur = xmlXPtrGetNthChild(cur, index1 - 1); + index1 = 0; + } else { + cur = cur->children; + } + /* + * Now gather the remaining nodes from cur to end + */ + continue; /* while */ + } + } else if ((cur == start) && + (list == NULL) /* looks superfluous but ... */ ) { + if ((cur->type == XML_TEXT_NODE) || + (cur->type == XML_CDATA_SECTION_NODE)) { + const xmlChar *content = cur->content; + + if (content == NULL) { + tmp = xmlNewTextLen(NULL, 0); + } else { + if (index1 > 1) { + content += (index1 - 1); + } + tmp = xmlNewText(content); + } + last = list = tmp; + } else { + if ((cur == start) && (index1 > 1)) { + tmp = xmlCopyNode(cur, 0); + list = tmp; + parent = tmp; + last = NULL; + cur = xmlXPtrGetNthChild(cur, index1 - 1); + index1 = 0; + /* + * Now gather the remaining nodes from cur to end + */ + continue; /* while */ + } + tmp = xmlCopyNode(cur, 1); + list = tmp; + parent = NULL; + last = tmp; + } + } else { + tmp = NULL; + switch (cur->type) { + case XML_DTD_NODE: + case XML_ELEMENT_DECL: + case XML_ATTRIBUTE_DECL: + case XML_ENTITY_NODE: + /* Do not copy DTD informations */ + break; + case XML_ENTITY_DECL: + TODO /* handle crossing entities -> stack needed */ + break; + case XML_XINCLUDE_START: + case XML_XINCLUDE_END: + /* don't consider it part of the tree content */ + break; + case XML_ATTRIBUTE_NODE: + /* Humm, should not happen ! */ + STRANGE + break; + default: + tmp = xmlCopyNode(cur, 1); + break; + } + if (tmp != NULL) { + if ((list == NULL) || ((last == NULL) && (parent == NULL))) { + STRANGE + return(NULL); + } + if (last != NULL) + xmlAddNextSibling(last, tmp); + else { + xmlAddChild(parent, tmp); + last = tmp; + } + } + } + /* + * Skip to next node in document order + */ + if ((list == NULL) || ((last == NULL) && (parent == NULL))) { + STRANGE + return(NULL); + } + cur = xmlXPtrAdvanceNode(cur, NULL); + } + return(list); +} + +/** + * xmlXPtrBuildNodeList: + * @obj: the XPointer result from the evaluation. + * + * Build a node list tree copy of the XPointer result. + * This will drop Attributes and Namespace declarations. + * + * Returns an xmlNodePtr list or NULL. + * the caller has to free the node tree. + */ +xmlNodePtr +xmlXPtrBuildNodeList(xmlXPathObjectPtr obj) { + xmlNodePtr list = NULL, last = NULL; + int i; + + if (obj == NULL) + return(NULL); + switch (obj->type) { + case XPATH_NODESET: { + xmlNodeSetPtr set = obj->nodesetval; + if (set == NULL) + return(NULL); + for (i = 0;i < set->nodeNr;i++) { + if (set->nodeTab[i] == NULL) + continue; + switch (set->nodeTab[i]->type) { + case XML_TEXT_NODE: + case XML_CDATA_SECTION_NODE: + case XML_ELEMENT_NODE: + case XML_ENTITY_REF_NODE: + case XML_ENTITY_NODE: + case XML_PI_NODE: + case XML_COMMENT_NODE: + case XML_DOCUMENT_NODE: + case XML_HTML_DOCUMENT_NODE: +#ifdef LIBXML_DOCB_ENABLED + case XML_DOCB_DOCUMENT_NODE: +#endif + case XML_XINCLUDE_START: + case XML_XINCLUDE_END: + break; + case XML_ATTRIBUTE_NODE: + case XML_NAMESPACE_DECL: + case XML_DOCUMENT_TYPE_NODE: + case XML_DOCUMENT_FRAG_NODE: + case XML_NOTATION_NODE: + case XML_DTD_NODE: + case XML_ELEMENT_DECL: + case XML_ATTRIBUTE_DECL: + case XML_ENTITY_DECL: + continue; /* for */ + } + if (last == NULL) + list = last = xmlCopyNode(set->nodeTab[i], 1); + else { + xmlAddNextSibling(last, xmlCopyNode(set->nodeTab[i], 1)); + if (last->next != NULL) + last = last->next; + } + } + break; + } + case XPATH_LOCATIONSET: { + xmlLocationSetPtr set = (xmlLocationSetPtr) obj->user; + if (set == NULL) + return(NULL); + for (i = 0;i < set->locNr;i++) { + if (last == NULL) + list = last = xmlXPtrBuildNodeList(set->locTab[i]); + else + xmlAddNextSibling(last, + xmlXPtrBuildNodeList(set->locTab[i])); + if (last != NULL) { + while (last->next != NULL) + last = last->next; + } + } + break; + } + case XPATH_RANGE: + return(xmlXPtrBuildRangeNodeList(obj)); + case XPATH_POINT: + return(xmlCopyNode(obj->user, 0)); + default: + break; + } + return(list); +} + +/************************************************************************ + * * + * XPointer functions * + * * + ************************************************************************/ + +/** + * xmlXPtrNbLocChildren: + * @node: an xmlNodePtr + * + * Count the number of location children of @node or the length of the + * string value in case of text/PI/Comments nodes + * + * Returns the number of location children + */ +static int +xmlXPtrNbLocChildren(xmlNodePtr node) { + int ret = 0; + if (node == NULL) + return(-1); + switch (node->type) { + case XML_HTML_DOCUMENT_NODE: + case XML_DOCUMENT_NODE: + case XML_ELEMENT_NODE: + node = node->children; + while (node != NULL) { + if (node->type == XML_ELEMENT_NODE) + ret++; + node = node->next; + } + break; + case XML_ATTRIBUTE_NODE: + return(-1); + + case XML_PI_NODE: + case XML_COMMENT_NODE: + case XML_TEXT_NODE: + case XML_CDATA_SECTION_NODE: + case XML_ENTITY_REF_NODE: + ret = xmlStrlen(node->content); + break; + default: + return(-1); + } + return(ret); +} + +/** + * xmlXPtrHereFunction: + * @ctxt: the XPointer Parser context + * @nargs: the number of args + * + * Function implementing here() operation + * as described in 5.4.3 + */ +void +xmlXPtrHereFunction(xmlXPathParserContextPtr ctxt, int nargs) { + CHECK_ARITY(0); + + if (ctxt->context->here == NULL) + XP_ERROR(XPTR_SYNTAX_ERROR); + + valuePush(ctxt, xmlXPtrNewLocationSetNodes(ctxt->context->here, NULL)); +} + +/** + * xmlXPtrOriginFunction: + * @ctxt: the XPointer Parser context + * @nargs: the number of args + * + * Function implementing origin() operation + * as described in 5.4.3 + */ +void +xmlXPtrOriginFunction(xmlXPathParserContextPtr ctxt, int nargs) { + CHECK_ARITY(0); + + if (ctxt->context->origin == NULL) + XP_ERROR(XPTR_SYNTAX_ERROR); + + valuePush(ctxt, xmlXPtrNewLocationSetNodes(ctxt->context->origin, NULL)); +} + +/** + * xmlXPtrStartPointFunction: + * @ctxt: the XPointer Parser context + * @nargs: the number of args + * + * Function implementing start-point() operation + * as described in 5.4.3 + * ---------------- + * location-set start-point(location-set) + * + * For each location x in the argument location-set, start-point adds a + * location of type point to the result location-set. That point represents + * the start point of location x and is determined by the following rules: + * + * - If x is of type point, the start point is x. + * - If x is of type range, the start point is the start point of x. + * - If x is of type root, element, text, comment, or processing instruction, + * - the container node of the start point is x and the index is 0. + * - If x is of type attribute or namespace, the function must signal a + * syntax error. + * ---------------- + * + */ +void +xmlXPtrStartPointFunction(xmlXPathParserContextPtr ctxt, int nargs) { + xmlXPathObjectPtr tmp, obj, point; + xmlLocationSetPtr newset = NULL; + xmlLocationSetPtr oldset = NULL; + + CHECK_ARITY(1); + if ((ctxt->value == NULL) || + ((ctxt->value->type != XPATH_LOCATIONSET) && + (ctxt->value->type != XPATH_NODESET))) + XP_ERROR(XPATH_INVALID_TYPE) + + obj = valuePop(ctxt); + if (obj->type == XPATH_NODESET) { + /* + * First convert to a location set + */ + tmp = xmlXPtrNewLocationSetNodeSet(obj->nodesetval); + xmlXPathFreeObject(obj); + obj = tmp; + } + + newset = xmlXPtrLocationSetCreate(NULL); + if (newset == NULL) { + xmlXPathFreeObject(obj); + XP_ERROR(XPATH_MEMORY_ERROR); + } + oldset = (xmlLocationSetPtr) obj->user; + if (oldset != NULL) { + int i; + + for (i = 0; i < oldset->locNr; i++) { + tmp = oldset->locTab[i]; + if (tmp == NULL) + continue; + point = NULL; + switch (tmp->type) { + case XPATH_POINT: + point = xmlXPtrNewPoint(tmp->user, tmp->index); + break; + case XPATH_RANGE: { + xmlNodePtr node = tmp->user; + if (node != NULL) { + if (node->type == XML_ATTRIBUTE_NODE) { + /* TODO: Namespace Nodes ??? */ + xmlXPathFreeObject(obj); + xmlXPtrFreeLocationSet(newset); + XP_ERROR(XPTR_SYNTAX_ERROR); + } + point = xmlXPtrNewPoint(node, tmp->index); + } + break; + } + default: + /*** Should we raise an error ? + xmlXPathFreeObject(obj); + xmlXPathFreeObject(newset); + XP_ERROR(XPATH_INVALID_TYPE) + ***/ + break; + } + if (point != NULL) + xmlXPtrLocationSetAdd(newset, point); + } + } + xmlXPathFreeObject(obj); + valuePush(ctxt, xmlXPtrWrapLocationSet(newset)); +} + +/** + * xmlXPtrEndPointFunction: + * @ctxt: the XPointer Parser context + * @nargs: the number of args + * + * Function implementing end-point() operation + * as described in 5.4.3 + * ---------------------------- + * location-set end-point(location-set) + * + * For each location x in the argument location-set, end-point adds a + * location of type point to the result location-set. That point represents + * the end point of location x and is determined by the following rules: + * + * - If x is of type point, the resulting point is x. + * - If x is of type range, the resulting point is the end point of x. + * - If x is of type root or element, the container node of the resulting + * point is x and the index is the number of location children of x. + * - If x is of type text, comment, or processing instruction, the container + * node of the resulting point is x and the index is the length of the + * string-value of x. + * - If x is of type attribute or namespace, the function must signal a + * syntax error. + * ---------------------------- + */ +void +xmlXPtrEndPointFunction(xmlXPathParserContextPtr ctxt, int nargs) { + xmlXPathObjectPtr tmp, obj, point; + xmlLocationSetPtr newset = NULL; + xmlLocationSetPtr oldset = NULL; + + CHECK_ARITY(1); + if ((ctxt->value == NULL) || + ((ctxt->value->type != XPATH_LOCATIONSET) && + (ctxt->value->type != XPATH_NODESET))) + XP_ERROR(XPATH_INVALID_TYPE) + + obj = valuePop(ctxt); + if (obj->type == XPATH_NODESET) { + /* + * First convert to a location set + */ + tmp = xmlXPtrNewLocationSetNodeSet(obj->nodesetval); + xmlXPathFreeObject(obj); + obj = tmp; + } + + newset = xmlXPtrLocationSetCreate(NULL); + oldset = (xmlLocationSetPtr) obj->user; + if (oldset != NULL) { + int i; + + for (i = 0; i < oldset->locNr; i++) { + tmp = oldset->locTab[i]; + if (tmp == NULL) + continue; + point = NULL; + switch (tmp->type) { + case XPATH_POINT: + point = xmlXPtrNewPoint(tmp->user, tmp->index); + break; + case XPATH_RANGE: { + xmlNodePtr node = tmp->user2; + if (node != NULL) { + if (node->type == XML_ATTRIBUTE_NODE) { + /* TODO: Namespace Nodes ??? */ + xmlXPathFreeObject(obj); + xmlXPtrFreeLocationSet(newset); + XP_ERROR(XPTR_SYNTAX_ERROR); + } + point = xmlXPtrNewPoint(node, tmp->index2); + } else if (tmp->user == NULL) { + point = xmlXPtrNewPoint(node, + xmlXPtrNbLocChildren(node)); + } + break; + } + default: + /*** Should we raise an error ? + xmlXPathFreeObject(obj); + xmlXPathFreeObject(newset); + XP_ERROR(XPATH_INVALID_TYPE) + ***/ + break; + } + if (point != NULL) + xmlXPtrLocationSetAdd(newset, point); + } + } + xmlXPathFreeObject(obj); + valuePush(ctxt, xmlXPtrWrapLocationSet(newset)); +} + + +/** + * xmlXPtrCoveringRange: + * @ctxt: the XPointer Parser context + * @loc: the location for which the covering range must be computed + * + * A covering range is a range that wholly encompasses a location + * Section 5.3.3. Covering Ranges for All Location Types + * http://www.w3.org/TR/xptr#N2267 + * + * Returns a new location or NULL in case of error + */ +static xmlXPathObjectPtr +xmlXPtrCoveringRange(xmlXPathParserContextPtr ctxt, xmlXPathObjectPtr loc) { + if (loc == NULL) + return(NULL); + if ((ctxt == NULL) || (ctxt->context == NULL) || + (ctxt->context->doc == NULL)) + return(NULL); + switch (loc->type) { + case XPATH_POINT: + return(xmlXPtrNewRange(loc->user, loc->index, + loc->user, loc->index)); + case XPATH_RANGE: + if (loc->user2 != NULL) { + return(xmlXPtrNewRange(loc->user, loc->index, + loc->user2, loc->index2)); + } else { + xmlNodePtr node = (xmlNodePtr) loc->user; + if (node == (xmlNodePtr) ctxt->context->doc) { + return(xmlXPtrNewRange(node, 0, node, + xmlXPtrGetArity(node))); + } else { + switch (node->type) { + case XML_ATTRIBUTE_NODE: + /* !!! our model is slightly different than XPath */ + return(xmlXPtrNewRange(node, 0, node, + xmlXPtrGetArity(node))); + case XML_ELEMENT_NODE: + case XML_TEXT_NODE: + case XML_CDATA_SECTION_NODE: + case XML_ENTITY_REF_NODE: + case XML_PI_NODE: + case XML_COMMENT_NODE: + case XML_DOCUMENT_NODE: + case XML_NOTATION_NODE: + case XML_HTML_DOCUMENT_NODE: { + int indx = xmlXPtrGetIndex(node); + + node = node->parent; + return(xmlXPtrNewRange(node, indx - 1, + node, indx + 1)); + } + default: + return(NULL); + } + } + } + default: + TODO /* missed one case ??? */ + } + return(NULL); +} + +/** + * xmlXPtrRangeFunction: + * @ctxt: the XPointer Parser context + * @nargs: the number of args + * + * Function implementing the range() function 5.4.3 + * location-set range(location-set ) + * + * The range function returns ranges covering the locations in + * the argument location-set. For each location x in the argument + * location-set, a range location representing the covering range of + * x is added to the result location-set. + */ +void +xmlXPtrRangeFunction(xmlXPathParserContextPtr ctxt, int nargs) { + int i; + xmlXPathObjectPtr set; + xmlLocationSetPtr oldset; + xmlLocationSetPtr newset; + + CHECK_ARITY(1); + if ((ctxt->value == NULL) || + ((ctxt->value->type != XPATH_LOCATIONSET) && + (ctxt->value->type != XPATH_NODESET))) + XP_ERROR(XPATH_INVALID_TYPE) + + set = valuePop(ctxt); + if (set->type == XPATH_NODESET) { + xmlXPathObjectPtr tmp; + + /* + * First convert to a location set + */ + tmp = xmlXPtrNewLocationSetNodeSet(set->nodesetval); + xmlXPathFreeObject(set); + set = tmp; + } + oldset = (xmlLocationSetPtr) set->user; + + /* + * The loop is to compute the covering range for each item and add it + */ + newset = xmlXPtrLocationSetCreate(NULL); + for (i = 0;i < oldset->locNr;i++) { + xmlXPtrLocationSetAdd(newset, + xmlXPtrCoveringRange(ctxt, oldset->locTab[i])); + } + + /* + * Save the new value and cleanup + */ + valuePush(ctxt, xmlXPtrWrapLocationSet(newset)); + xmlXPathFreeObject(set); +} + +/** + * xmlXPtrInsideRange: + * @ctxt: the XPointer Parser context + * @loc: the location for which the inside range must be computed + * + * A inside range is a range described in the range-inside() description + * + * Returns a new location or NULL in case of error + */ +static xmlXPathObjectPtr +xmlXPtrInsideRange(xmlXPathParserContextPtr ctxt, xmlXPathObjectPtr loc) { + if (loc == NULL) + return(NULL); + if ((ctxt == NULL) || (ctxt->context == NULL) || + (ctxt->context->doc == NULL)) + return(NULL); + switch (loc->type) { + case XPATH_POINT: { + xmlNodePtr node = (xmlNodePtr) loc->user; + switch (node->type) { + case XML_PI_NODE: + case XML_COMMENT_NODE: + case XML_TEXT_NODE: + case XML_CDATA_SECTION_NODE: { + if (node->content == NULL) { + return(xmlXPtrNewRange(node, 0, node, 0)); + } else { + return(xmlXPtrNewRange(node, 0, node, + xmlStrlen(node->content))); + } + } + case XML_ATTRIBUTE_NODE: + case XML_ELEMENT_NODE: + case XML_ENTITY_REF_NODE: + case XML_DOCUMENT_NODE: + case XML_NOTATION_NODE: + case XML_HTML_DOCUMENT_NODE: { + return(xmlXPtrNewRange(node, 0, node, + xmlXPtrGetArity(node))); + } + default: + break; + } + return(NULL); + } + case XPATH_RANGE: { + xmlNodePtr node = (xmlNodePtr) loc->user; + if (loc->user2 != NULL) { + return(xmlXPtrNewRange(node, loc->index, + loc->user2, loc->index2)); + } else { + switch (node->type) { + case XML_PI_NODE: + case XML_COMMENT_NODE: + case XML_TEXT_NODE: + case XML_CDATA_SECTION_NODE: { + if (node->content == NULL) { + return(xmlXPtrNewRange(node, 0, node, 0)); + } else { + return(xmlXPtrNewRange(node, 0, node, + xmlStrlen(node->content))); + } + } + case XML_ATTRIBUTE_NODE: + case XML_ELEMENT_NODE: + case XML_ENTITY_REF_NODE: + case XML_DOCUMENT_NODE: + case XML_NOTATION_NODE: + case XML_HTML_DOCUMENT_NODE: { + return(xmlXPtrNewRange(node, 0, node, + xmlXPtrGetArity(node))); + } + default: + break; + } + return(NULL); + } + } + default: + TODO /* missed one case ??? */ + } + return(NULL); +} + +/** + * xmlXPtrRangeInsideFunction: + * @ctxt: the XPointer Parser context + * @nargs: the number of args + * + * Function implementing the range-inside() function 5.4.3 + * location-set range-inside(location-set ) + * + * The range-inside function returns ranges covering the contents of + * the locations in the argument location-set. For each location x in + * the argument location-set, a range location is added to the result + * location-set. If x is a range location, then x is added to the + * result location-set. If x is not a range location, then x is used + * as the container location of the start and end points of the range + * location to be added; the index of the start point of the range is + * zero; if the end point is a character point then its index is the + * length of the string-value of x, and otherwise is the number of + * location children of x. + * + */ +void +xmlXPtrRangeInsideFunction(xmlXPathParserContextPtr ctxt, int nargs) { + int i; + xmlXPathObjectPtr set; + xmlLocationSetPtr oldset; + xmlLocationSetPtr newset; + + CHECK_ARITY(1); + if ((ctxt->value == NULL) || + ((ctxt->value->type != XPATH_LOCATIONSET) && + (ctxt->value->type != XPATH_NODESET))) + XP_ERROR(XPATH_INVALID_TYPE) + + set = valuePop(ctxt); + if (set->type == XPATH_NODESET) { + xmlXPathObjectPtr tmp; + + /* + * First convert to a location set + */ + tmp = xmlXPtrNewLocationSetNodeSet(set->nodesetval); + xmlXPathFreeObject(set); + set = tmp; + } + oldset = (xmlLocationSetPtr) set->user; + + /* + * The loop is to compute the covering range for each item and add it + */ + newset = xmlXPtrLocationSetCreate(NULL); + for (i = 0;i < oldset->locNr;i++) { + xmlXPtrLocationSetAdd(newset, + xmlXPtrInsideRange(ctxt, oldset->locTab[i])); + } + + /* + * Save the new value and cleanup + */ + valuePush(ctxt, xmlXPtrWrapLocationSet(newset)); + xmlXPathFreeObject(set); +} + +/** + * xmlXPtrRangeToFunction: + * @ctxt: the XPointer Parser context + * @nargs: the number of args + * + * Implement the range-to() XPointer function + */ +void +xmlXPtrRangeToFunction(xmlXPathParserContextPtr ctxt, int nargs) { + xmlXPathObjectPtr range; + const xmlChar *cur; + xmlXPathObjectPtr res, obj; + xmlXPathObjectPtr tmp; + xmlLocationSetPtr newset = NULL; + xmlNodeSetPtr oldset; + int i; + + if (ctxt == NULL) return; + CHECK_ARITY(1); + /* + * Save the expression pointer since we will have to evaluate + * it multiple times. Initialize the new set. + */ + CHECK_TYPE(XPATH_NODESET); + obj = valuePop(ctxt); + oldset = obj->nodesetval; + ctxt->context->node = NULL; + + cur = ctxt->cur; + newset = xmlXPtrLocationSetCreate(NULL); + + for (i = 0; i < oldset->nodeNr; i++) { + ctxt->cur = cur; + + /* + * Run the evaluation with a node list made of a single item + * in the nodeset. + */ + ctxt->context->node = oldset->nodeTab[i]; + tmp = xmlXPathNewNodeSet(ctxt->context->node); + valuePush(ctxt, tmp); + + xmlXPathEvalExpr(ctxt); + CHECK_ERROR; + + /* + * The result of the evaluation need to be tested to + * decided whether the filter succeeded or not + */ + res = valuePop(ctxt); + range = xmlXPtrNewRangeNodeObject(oldset->nodeTab[i], res); + if (range != NULL) { + xmlXPtrLocationSetAdd(newset, range); + } + + /* + * Cleanup + */ + if (res != NULL) + xmlXPathFreeObject(res); + if (ctxt->value == tmp) { + res = valuePop(ctxt); + xmlXPathFreeObject(res); + } + + ctxt->context->node = NULL; + } + + /* + * The result is used as the new evaluation set. + */ + xmlXPathFreeObject(obj); + ctxt->context->node = NULL; + ctxt->context->contextSize = -1; + ctxt->context->proximityPosition = -1; + valuePush(ctxt, xmlXPtrWrapLocationSet(newset)); +} + +/** + * xmlXPtrAdvanceNode: + * @cur: the node + * @level: incremented/decremented to show level in tree + * + * Advance to the next element or text node in document order + * TODO: add a stack for entering/exiting entities + * + * Returns -1 in case of failure, 0 otherwise + */ +xmlNodePtr +xmlXPtrAdvanceNode(xmlNodePtr cur, int *level) { +next: + if (cur == NULL) + return(NULL); + if (cur->children != NULL) { + cur = cur->children ; + if (level != NULL) + (*level)++; + goto found; + } +skip: /* This label should only be needed if something is wrong! */ + if (cur->next != NULL) { + cur = cur->next; + goto found; + } + do { + cur = cur->parent; + if (level != NULL) + (*level)--; + if (cur == NULL) return(NULL); + if (cur->next != NULL) { + cur = cur->next; + goto found; + } + } while (cur != NULL); + +found: + if ((cur->type != XML_ELEMENT_NODE) && + (cur->type != XML_TEXT_NODE) && + (cur->type != XML_DOCUMENT_NODE) && + (cur->type != XML_HTML_DOCUMENT_NODE) && + (cur->type != XML_CDATA_SECTION_NODE)) { + if (cur->type == XML_ENTITY_REF_NODE) { /* Shouldn't happen */ + TODO + goto skip; + } + goto next; + } + return(cur); +} + +/** + * xmlXPtrAdvanceChar: + * @node: the node + * @indx: the indx + * @bytes: the number of bytes + * + * Advance a point of the associated number of bytes (not UTF8 chars) + * + * Returns -1 in case of failure, 0 otherwise + */ +static int +xmlXPtrAdvanceChar(xmlNodePtr *node, int *indx, int bytes) { + xmlNodePtr cur; + int pos; + int len; + + if ((node == NULL) || (indx == NULL)) + return(-1); + cur = *node; + if (cur == NULL) + return(-1); + pos = *indx; + + while (bytes >= 0) { + /* + * First position to the beginning of the first text node + * corresponding to this point + */ + while ((cur != NULL) && + ((cur->type == XML_ELEMENT_NODE) || + (cur->type == XML_DOCUMENT_NODE) || + (cur->type == XML_HTML_DOCUMENT_NODE))) { + if (pos > 0) { + cur = xmlXPtrGetNthChild(cur, pos); + pos = 0; + } else { + cur = xmlXPtrAdvanceNode(cur, NULL); + pos = 0; + } + } + + if (cur == NULL) { + *node = NULL; + *indx = 0; + return(-1); + } + + /* + * if there is no move needed return the current value. + */ + if (pos == 0) pos = 1; + if (bytes == 0) { + *node = cur; + *indx = pos; + return(0); + } + /* + * We should have a text (or cdata) node ... + */ + len = 0; + if ((cur->type != XML_ELEMENT_NODE) && + (cur->content != NULL)) { + len = xmlStrlen(cur->content); + } + if (pos > len) { + /* Strange, the indx in the text node is greater than it's len */ + STRANGE + pos = len; + } + if (pos + bytes >= len) { + bytes -= (len - pos); + cur = xmlXPtrAdvanceNode(cur, NULL); + pos = 0; + } else if (pos + bytes < len) { + pos += bytes; + *node = cur; + *indx = pos; + return(0); + } + } + return(-1); +} + +/** + * xmlXPtrMatchString: + * @string: the string to search + * @start: the start textnode + * @startindex: the start index + * @end: the end textnode IN/OUT + * @endindex: the end index IN/OUT + * + * Check whether the document contains @string at the position + * (@start, @startindex) and limited by the (@end, @endindex) point + * + * Returns -1 in case of failure, 0 if not found, 1 if found in which case + * (@start, @startindex) will indicate the position of the beginning + * of the range and (@end, @endindex) will indicate the end + * of the range + */ +static int +xmlXPtrMatchString(const xmlChar *string, xmlNodePtr start, int startindex, + xmlNodePtr *end, int *endindex) { + xmlNodePtr cur; + int pos; /* 0 based */ + int len; /* in bytes */ + int stringlen; /* in bytes */ + int match; + + if (string == NULL) + return(-1); + if (start == NULL) + return(-1); + if ((end == NULL) || (endindex == NULL)) + return(-1); + cur = start; + if (cur == NULL) + return(-1); + pos = startindex - 1; + stringlen = xmlStrlen(string); + + while (stringlen > 0) { + if ((cur == *end) && (pos + stringlen > *endindex)) + return(0); + + if ((cur->type != XML_ELEMENT_NODE) && (cur->content != NULL)) { + len = xmlStrlen(cur->content); + if (len >= pos + stringlen) { + match = (!xmlStrncmp(&cur->content[pos], string, stringlen)); + if (match) { +#ifdef DEBUG_RANGES + xmlGenericError(xmlGenericErrorContext, + "found range %d bytes at index %d of ->", + stringlen, pos + 1); + xmlDebugDumpString(stdout, cur->content); + xmlGenericError(xmlGenericErrorContext, "\n"); +#endif + *end = cur; + *endindex = pos + stringlen; + return(1); + } else { + return(0); + } + } else { + int sub = len - pos; + match = (!xmlStrncmp(&cur->content[pos], string, sub)); + if (match) { +#ifdef DEBUG_RANGES + xmlGenericError(xmlGenericErrorContext, + "found subrange %d bytes at index %d of ->", + sub, pos + 1); + xmlDebugDumpString(stdout, cur->content); + xmlGenericError(xmlGenericErrorContext, "\n"); +#endif + string = &string[sub]; + stringlen -= sub; + } else { + return(0); + } + } + } + cur = xmlXPtrAdvanceNode(cur, NULL); + if (cur == NULL) + return(0); + pos = 0; + } + return(1); +} + +/** + * xmlXPtrSearchString: + * @string: the string to search + * @start: the start textnode IN/OUT + * @startindex: the start index IN/OUT + * @end: the end textnode + * @endindex: the end index + * + * Search the next occurrence of @string within the document content + * until the (@end, @endindex) point is reached + * + * Returns -1 in case of failure, 0 if not found, 1 if found in which case + * (@start, @startindex) will indicate the position of the beginning + * of the range and (@end, @endindex) will indicate the end + * of the range + */ +static int +xmlXPtrSearchString(const xmlChar *string, xmlNodePtr *start, int *startindex, + xmlNodePtr *end, int *endindex) { + xmlNodePtr cur; + const xmlChar *str; + int pos; /* 0 based */ + int len; /* in bytes */ + xmlChar first; + + if (string == NULL) + return(-1); + if ((start == NULL) || (startindex == NULL)) + return(-1); + if ((end == NULL) || (endindex == NULL)) + return(-1); + cur = *start; + if (cur == NULL) + return(-1); + pos = *startindex - 1; + first = string[0]; + + while (cur != NULL) { + if ((cur->type != XML_ELEMENT_NODE) && (cur->content != NULL)) { + len = xmlStrlen(cur->content); + while (pos <= len) { + if (first != 0) { + str = xmlStrchr(&cur->content[pos], first); + if (str != NULL) { + pos = (str - (xmlChar *)(cur->content)); +#ifdef DEBUG_RANGES + xmlGenericError(xmlGenericErrorContext, + "found '%c' at index %d of ->", + first, pos + 1); + xmlDebugDumpString(stdout, cur->content); + xmlGenericError(xmlGenericErrorContext, "\n"); +#endif + if (xmlXPtrMatchString(string, cur, pos + 1, + end, endindex)) { + *start = cur; + *startindex = pos + 1; + return(1); + } + pos++; + } else { + pos = len + 1; + } + } else { + /* + * An empty string is considered to match before each + * character of the string-value and after the final + * character. + */ +#ifdef DEBUG_RANGES + xmlGenericError(xmlGenericErrorContext, + "found '' at index %d of ->", + pos + 1); + xmlDebugDumpString(stdout, cur->content); + xmlGenericError(xmlGenericErrorContext, "\n"); +#endif + *start = cur; + *startindex = pos + 1; + *end = cur; + *endindex = pos + 1; + return(1); + } + } + } + if ((cur == *end) && (pos >= *endindex)) + return(0); + cur = xmlXPtrAdvanceNode(cur, NULL); + if (cur == NULL) + return(0); + pos = 1; + } + return(0); +} + +/** + * xmlXPtrGetLastChar: + * @node: the node + * @index: the index + * + * Computes the point coordinates of the last char of this point + * + * Returns -1 in case of failure, 0 otherwise + */ +static int +xmlXPtrGetLastChar(xmlNodePtr *node, int *indx) { + xmlNodePtr cur; + int pos, len = 0; + + if ((node == NULL) || (indx == NULL)) + return(-1); + cur = *node; + pos = *indx; + + if (cur == NULL) + return(-1); + + if ((cur->type == XML_ELEMENT_NODE) || + (cur->type == XML_DOCUMENT_NODE) || + (cur->type == XML_HTML_DOCUMENT_NODE)) { + if (pos > 0) { + cur = xmlXPtrGetNthChild(cur, pos); + pos = 0; + } + } + while (cur != NULL) { + if (cur->last != NULL) + cur = cur->last; + else if ((cur->type != XML_ELEMENT_NODE) && + (cur->content != NULL)) { + len = xmlStrlen(cur->content); + break; + } else { + return(-1); + } + } + if (cur == NULL) + return(-1); + *node = cur; + *indx = len; + return(0); +} + +/** + * xmlXPtrGetStartPoint: + * @obj: an range + * @node: the resulting node + * @indx: the resulting index + * + * read the object and return the start point coordinates. + * + * Returns -1 in case of failure, 0 otherwise + */ +static int +xmlXPtrGetStartPoint(xmlXPathObjectPtr obj, xmlNodePtr *node, int *indx) { + if ((obj == NULL) || (node == NULL) || (indx == NULL)) + return(-1); + + switch (obj->type) { + case XPATH_POINT: + *node = obj->user; + if (obj->index <= 0) + *indx = 0; + else + *indx = obj->index; + return(0); + case XPATH_RANGE: + *node = obj->user; + if (obj->index <= 0) + *indx = 0; + else + *indx = obj->index; + return(0); + default: + break; + } + return(-1); +} + +/** + * xmlXPtrGetEndPoint: + * @obj: an range + * @node: the resulting node + * @indx: the resulting indx + * + * read the object and return the end point coordinates. + * + * Returns -1 in case of failure, 0 otherwise + */ +static int +xmlXPtrGetEndPoint(xmlXPathObjectPtr obj, xmlNodePtr *node, int *indx) { + if ((obj == NULL) || (node == NULL) || (indx == NULL)) + return(-1); + + switch (obj->type) { + case XPATH_POINT: + *node = obj->user; + if (obj->index <= 0) + *indx = 0; + else + *indx = obj->index; + return(0); + case XPATH_RANGE: + *node = obj->user; + if (obj->index <= 0) + *indx = 0; + else + *indx = obj->index; + return(0); + default: + break; + } + return(-1); +} + +/** + * xmlXPtrStringRangeFunction: + * @ctxt: the XPointer Parser context + * @nargs: the number of args + * + * Function implementing the string-range() function + * range as described in 5.4.2 + * + * ------------------------------ + * [Definition: For each location in the location-set argument, + * string-range returns a set of string ranges, a set of substrings in a + * string. Specifically, the string-value of the location is searched for + * substrings that match the string argument, and the resulting location-set + * will contain a range location for each non-overlapping match.] + * An empty string is considered to match before each character of the + * string-value and after the final character. Whitespace in a string + * is matched literally, with no normalization except that provided by + * XML for line ends. The third argument gives the position of the first + * character to be in the resulting range, relative to the start of the + * match. The default value is 1, which makes the range start immediately + * before the first character of the matched string. The fourth argument + * gives the number of characters in the range; the default is that the + * range extends to the end of the matched string. + * + * Element boundaries, as well as entire embedded nodes such as processing + * instructions and comments, are ignored as defined in [XPath]. + * + * If the string in the second argument is not found in the string-value + * of the location, or if a value in the third or fourth argument indicates + * a string that is beyond the beginning or end of the document, the + * expression fails. + * + * The points of the range-locations in the returned location-set will + * all be character points. + * ------------------------------ + */ +void +xmlXPtrStringRangeFunction(xmlXPathParserContextPtr ctxt, int nargs) { + int i, startindex, endindex = 0, fendindex; + xmlNodePtr start, end = 0, fend; + xmlXPathObjectPtr set; + xmlLocationSetPtr oldset; + xmlLocationSetPtr newset; + xmlXPathObjectPtr string; + xmlXPathObjectPtr position = NULL; + xmlXPathObjectPtr number = NULL; + int found, pos = 0, num = 0; + + /* + * Grab the arguments + */ + if ((nargs < 2) || (nargs > 4)) + XP_ERROR(XPATH_INVALID_ARITY); + + if (nargs >= 4) { + CHECK_TYPE(XPATH_NUMBER); + number = valuePop(ctxt); + if (number != NULL) + num = (int) number->floatval; + } + if (nargs >= 3) { + CHECK_TYPE(XPATH_NUMBER); + position = valuePop(ctxt); + if (position != NULL) + pos = (int) position->floatval; + } + CHECK_TYPE(XPATH_STRING); + string = valuePop(ctxt); + if ((ctxt->value == NULL) || + ((ctxt->value->type != XPATH_LOCATIONSET) && + (ctxt->value->type != XPATH_NODESET))) + XP_ERROR(XPATH_INVALID_TYPE) + + set = valuePop(ctxt); + newset = xmlXPtrLocationSetCreate(NULL); + if (set->nodesetval == NULL) { + goto error; + } + if (set->type == XPATH_NODESET) { + xmlXPathObjectPtr tmp; + + /* + * First convert to a location set + */ + tmp = xmlXPtrNewLocationSetNodeSet(set->nodesetval); + xmlXPathFreeObject(set); + set = tmp; + } + oldset = (xmlLocationSetPtr) set->user; + + /* + * The loop is to search for each element in the location set + * the list of location set corresponding to that search + */ + for (i = 0;i < oldset->locNr;i++) { +#ifdef DEBUG_RANGES + xmlXPathDebugDumpObject(stdout, oldset->locTab[i], 0); +#endif + + xmlXPtrGetStartPoint(oldset->locTab[i], &start, &startindex); + xmlXPtrGetEndPoint(oldset->locTab[i], &end, &endindex); + xmlXPtrAdvanceChar(&start, &startindex, 0); + xmlXPtrGetLastChar(&end, &endindex); + +#ifdef DEBUG_RANGES + xmlGenericError(xmlGenericErrorContext, + "from index %d of ->", startindex); + xmlDebugDumpString(stdout, start->content); + xmlGenericError(xmlGenericErrorContext, "\n"); + xmlGenericError(xmlGenericErrorContext, + "to index %d of ->", endindex); + xmlDebugDumpString(stdout, end->content); + xmlGenericError(xmlGenericErrorContext, "\n"); +#endif + do { + fend = end; + fendindex = endindex; + found = xmlXPtrSearchString(string->stringval, &start, &startindex, + &fend, &fendindex); + if (found == 1) { + if (position == NULL) { + xmlXPtrLocationSetAdd(newset, + xmlXPtrNewRange(start, startindex, fend, fendindex)); + } else if (xmlXPtrAdvanceChar(&start, &startindex, + pos - 1) == 0) { + if ((number != NULL) && (num > 0)) { + int rindx; + xmlNodePtr rend; + rend = start; + rindx = startindex - 1; + if (xmlXPtrAdvanceChar(&rend, &rindx, + num) == 0) { + xmlXPtrLocationSetAdd(newset, + xmlXPtrNewRange(start, startindex, + rend, rindx)); + } + } else if ((number != NULL) && (num <= 0)) { + xmlXPtrLocationSetAdd(newset, + xmlXPtrNewRange(start, startindex, + start, startindex)); + } else { + xmlXPtrLocationSetAdd(newset, + xmlXPtrNewRange(start, startindex, + fend, fendindex)); + } + } + start = fend; + startindex = fendindex; + if (string->stringval[0] == 0) + startindex++; + } + } while (found == 1); + } + + /* + * Save the new value and cleanup + */ +error: + valuePush(ctxt, xmlXPtrWrapLocationSet(newset)); + xmlXPathFreeObject(set); + xmlXPathFreeObject(string); + if (position) xmlXPathFreeObject(position); + if (number) xmlXPathFreeObject(number); +} + +/** + * xmlXPtrEvalRangePredicate: + * @ctxt: the XPointer Parser context + * + * [8] Predicate ::= '[' PredicateExpr ']' + * [9] PredicateExpr ::= Expr + * + * Evaluate a predicate as in xmlXPathEvalPredicate() but for + * a Location Set instead of a node set + */ +void +xmlXPtrEvalRangePredicate(xmlXPathParserContextPtr ctxt) { + const xmlChar *cur; + xmlXPathObjectPtr res; + xmlXPathObjectPtr obj, tmp; + xmlLocationSetPtr newset = NULL; + xmlLocationSetPtr oldset; + int i; + + if (ctxt == NULL) return; + + SKIP_BLANKS; + if (CUR != '[') { + XP_ERROR(XPATH_INVALID_PREDICATE_ERROR); + } + NEXT; + SKIP_BLANKS; + + /* + * Extract the old set, and then evaluate the result of the + * expression for all the element in the set. use it to grow + * up a new set. + */ + CHECK_TYPE(XPATH_LOCATIONSET); + obj = valuePop(ctxt); + oldset = obj->user; + ctxt->context->node = NULL; + + if ((oldset == NULL) || (oldset->locNr == 0)) { + ctxt->context->contextSize = 0; + ctxt->context->proximityPosition = 0; + xmlXPathEvalExpr(ctxt); + res = valuePop(ctxt); + if (res != NULL) + xmlXPathFreeObject(res); + valuePush(ctxt, obj); + CHECK_ERROR; + } else { + /* + * Save the expression pointer since we will have to evaluate + * it multiple times. Initialize the new set. + */ + cur = ctxt->cur; + newset = xmlXPtrLocationSetCreate(NULL); + + for (i = 0; i < oldset->locNr; i++) { + ctxt->cur = cur; + + /* + * Run the evaluation with a node list made of a single item + * in the nodeset. + */ + ctxt->context->node = oldset->locTab[i]->user; + tmp = xmlXPathNewNodeSet(ctxt->context->node); + valuePush(ctxt, tmp); + ctxt->context->contextSize = oldset->locNr; + ctxt->context->proximityPosition = i + 1; + + xmlXPathEvalExpr(ctxt); + CHECK_ERROR; + + /* + * The result of the evaluation need to be tested to + * decided whether the filter succeeded or not + */ + res = valuePop(ctxt); + if (xmlXPathEvaluatePredicateResult(ctxt, res)) { + xmlXPtrLocationSetAdd(newset, + xmlXPathObjectCopy(oldset->locTab[i])); + } + + /* + * Cleanup + */ + if (res != NULL) + xmlXPathFreeObject(res); + if (ctxt->value == tmp) { + res = valuePop(ctxt); + xmlXPathFreeObject(res); + } + + ctxt->context->node = NULL; + } + + /* + * The result is used as the new evaluation set. + */ + xmlXPathFreeObject(obj); + ctxt->context->node = NULL; + ctxt->context->contextSize = -1; + ctxt->context->proximityPosition = -1; + valuePush(ctxt, xmlXPtrWrapLocationSet(newset)); + } + if (CUR != ']') { + XP_ERROR(XPATH_INVALID_PREDICATE_ERROR); + } + + NEXT; + SKIP_BLANKS; +} + +#define bottom_xpointer +#include "elfgcchack.h" +#endif + diff --git a/gettext-tools/gnulib-lib/libxml/xpointer.in.h b/gettext-tools/gnulib-lib/libxml/xpointer.in.h new file mode 100644 index 0000000..dde1dfb --- /dev/null +++ b/gettext-tools/gnulib-lib/libxml/xpointer.in.h @@ -0,0 +1,114 @@ +/* + * Summary: API to handle XML Pointers + * Description: API to handle XML Pointers + * Base implementation was made accordingly to + * W3C Candidate Recommendation 7 June 2000 + * http://www.w3.org/TR/2000/CR-xptr-20000607 + * + * Added support for the element() scheme described in: + * W3C Proposed Recommendation 13 November 2002 + * http://www.w3.org/TR/2002/PR-xptr-element-20021113/ + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + +#ifndef __XML_XPTR_H__ +#define __XML_XPTR_H__ + +#include + +#ifdef LIBXML_XPTR_ENABLED + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * A Location Set + */ +typedef struct _xmlLocationSet xmlLocationSet; +typedef xmlLocationSet *xmlLocationSetPtr; +struct _xmlLocationSet { + int locNr; /* number of locations in the set */ + int locMax; /* size of the array as allocated */ + xmlXPathObjectPtr *locTab;/* array of locations */ +}; + +/* + * Handling of location sets. + */ + +XMLPUBFUN xmlLocationSetPtr XMLCALL + xmlXPtrLocationSetCreate (xmlXPathObjectPtr val); +XMLPUBFUN void XMLCALL + xmlXPtrFreeLocationSet (xmlLocationSetPtr obj); +XMLPUBFUN xmlLocationSetPtr XMLCALL + xmlXPtrLocationSetMerge (xmlLocationSetPtr val1, + xmlLocationSetPtr val2); +XMLPUBFUN xmlXPathObjectPtr XMLCALL + xmlXPtrNewRange (xmlNodePtr start, + int startindex, + xmlNodePtr end, + int endindex); +XMLPUBFUN xmlXPathObjectPtr XMLCALL + xmlXPtrNewRangePoints (xmlXPathObjectPtr start, + xmlXPathObjectPtr end); +XMLPUBFUN xmlXPathObjectPtr XMLCALL + xmlXPtrNewRangeNodePoint (xmlNodePtr start, + xmlXPathObjectPtr end); +XMLPUBFUN xmlXPathObjectPtr XMLCALL + xmlXPtrNewRangePointNode (xmlXPathObjectPtr start, + xmlNodePtr end); +XMLPUBFUN xmlXPathObjectPtr XMLCALL + xmlXPtrNewRangeNodes (xmlNodePtr start, + xmlNodePtr end); +XMLPUBFUN xmlXPathObjectPtr XMLCALL + xmlXPtrNewLocationSetNodes (xmlNodePtr start, + xmlNodePtr end); +XMLPUBFUN xmlXPathObjectPtr XMLCALL + xmlXPtrNewLocationSetNodeSet(xmlNodeSetPtr set); +XMLPUBFUN xmlXPathObjectPtr XMLCALL + xmlXPtrNewRangeNodeObject (xmlNodePtr start, + xmlXPathObjectPtr end); +XMLPUBFUN xmlXPathObjectPtr XMLCALL + xmlXPtrNewCollapsedRange (xmlNodePtr start); +XMLPUBFUN void XMLCALL + xmlXPtrLocationSetAdd (xmlLocationSetPtr cur, + xmlXPathObjectPtr val); +XMLPUBFUN xmlXPathObjectPtr XMLCALL + xmlXPtrWrapLocationSet (xmlLocationSetPtr val); +XMLPUBFUN void XMLCALL + xmlXPtrLocationSetDel (xmlLocationSetPtr cur, + xmlXPathObjectPtr val); +XMLPUBFUN void XMLCALL + xmlXPtrLocationSetRemove (xmlLocationSetPtr cur, + int val); + +/* + * Functions. + */ +XMLPUBFUN xmlXPathContextPtr XMLCALL + xmlXPtrNewContext (xmlDocPtr doc, + xmlNodePtr here, + xmlNodePtr origin); +XMLPUBFUN xmlXPathObjectPtr XMLCALL + xmlXPtrEval (const xmlChar *str, + xmlXPathContextPtr ctx); +XMLPUBFUN void XMLCALL + xmlXPtrRangeToFunction (xmlXPathParserContextPtr ctxt, + int nargs); +XMLPUBFUN xmlNodePtr XMLCALL + xmlXPtrBuildNodeList (xmlXPathObjectPtr obj); +XMLPUBFUN void XMLCALL + xmlXPtrEvalRangePredicate (xmlXPathParserContextPtr ctxt); +#ifdef __cplusplus +} +#endif + +#endif /* LIBXML_XPTR_ENABLED */ +#endif /* __XML_XPTR_H__ */ diff --git a/gettext-tools/gnulib-lib/localcharset.c b/gettext-tools/gnulib-lib/localcharset.c new file mode 100644 index 0000000..ccfa993 --- /dev/null +++ b/gettext-tools/gnulib-lib/localcharset.c @@ -0,0 +1,579 @@ +/* Determine a canonical name for the current locale's character encoding. + + Copyright (C) 2000-2006, 2008-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, see . */ + +/* Written by Bruno Haible . */ + +#include + +/* Specification. */ +#include "localcharset.h" + +#include +#include +#include +#include +#include + +#if defined __APPLE__ && defined __MACH__ && HAVE_LANGINFO_CODESET +# define DARWIN7 /* Darwin 7 or newer, i.e. Mac OS X 10.3 or newer */ +#endif + +#if defined _WIN32 || defined __WIN32__ +# define WINDOWS_NATIVE +# include +#endif + +#if defined __EMX__ +/* Assume EMX program runs on OS/2, even if compiled under DOS. */ +# ifndef OS2 +# define OS2 +# endif +#endif + +#if !defined WINDOWS_NATIVE +# include +# if HAVE_LANGINFO_CODESET +# include +# else +# if 0 /* see comment below */ +# include +# endif +# endif +# ifdef __CYGWIN__ +# define WIN32_LEAN_AND_MEAN +# include +# endif +#elif defined WINDOWS_NATIVE +# define WIN32_LEAN_AND_MEAN +# include +#endif +#if defined OS2 +# define INCL_DOS +# include +#endif + +/* For MB_CUR_MAX_L */ +#if defined DARWIN7 +# include +#endif + +#if ENABLE_RELOCATABLE +# include "relocatable.h" +#else +# define relocate(pathname) (pathname) +#endif + +/* Get LIBDIR. */ +#ifndef LIBDIR +# include "configmake.h" +#endif + +/* Define O_NOFOLLOW to 0 on platforms where it does not exist. */ +#ifndef O_NOFOLLOW +# define O_NOFOLLOW 0 +#endif + +#if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__ + /* Native Windows, Cygwin, OS/2, DOS */ +# define ISSLASH(C) ((C) == '/' || (C) == '\\') +#endif + +#ifndef DIRECTORY_SEPARATOR +# define DIRECTORY_SEPARATOR '/' +#endif + +#ifndef ISSLASH +# define ISSLASH(C) ((C) == DIRECTORY_SEPARATOR) +#endif + +#if HAVE_DECL_GETC_UNLOCKED +# undef getc +# define getc getc_unlocked +#endif + +/* The following static variable is declared 'volatile' to avoid a + possible multithread problem in the function get_charset_aliases. If we + are running in a threaded environment, and if two threads initialize + 'charset_aliases' simultaneously, both will produce the same value, + and everything will be ok if the two assignments to 'charset_aliases' + are atomic. But I don't know what will happen if the two assignments mix. */ +#if __STDC__ != 1 +# define volatile /* empty */ +#endif +/* Pointer to the contents of the charset.alias file, if it has already been + read, else NULL. Its format is: + ALIAS_1 '\0' CANONICAL_1 '\0' ... ALIAS_n '\0' CANONICAL_n '\0' '\0' */ +static const char * volatile charset_aliases; + +/* Return a pointer to the contents of the charset.alias file. */ +static const char * +get_charset_aliases (void) +{ + const char *cp; + + cp = charset_aliases; + if (cp == NULL) + { +#if !(defined DARWIN7 || defined VMS || defined WINDOWS_NATIVE || defined __CYGWIN__) + const char *dir; + const char *base = "charset.alias"; + char *file_name; + + /* Make it possible to override the charset.alias location. This is + necessary for running the testsuite before "make install". */ + dir = getenv ("CHARSETALIASDIR"); + if (dir == NULL || dir[0] == '\0') + dir = relocate (LIBDIR); + + /* Concatenate dir and base into freshly allocated file_name. */ + { + size_t dir_len = strlen (dir); + size_t base_len = strlen (base); + int add_slash = (dir_len > 0 && !ISSLASH (dir[dir_len - 1])); + file_name = (char *) malloc (dir_len + add_slash + base_len + 1); + if (file_name != NULL) + { + memcpy (file_name, dir, dir_len); + if (add_slash) + file_name[dir_len] = DIRECTORY_SEPARATOR; + memcpy (file_name + dir_len + add_slash, base, base_len + 1); + } + } + + if (file_name == NULL) + /* Out of memory. Treat the file as empty. */ + cp = ""; + else + { + int fd; + + /* Open the file. Reject symbolic links on platforms that support + O_NOFOLLOW. This is a security feature. Without it, an attacker + could retrieve parts of the contents (namely, the tail of the + first line that starts with "* ") of an arbitrary file by placing + a symbolic link to that file under the name "charset.alias" in + some writable directory and defining the environment variable + CHARSETALIASDIR to point to that directory. */ + fd = open (file_name, + O_RDONLY | (HAVE_WORKING_O_NOFOLLOW ? O_NOFOLLOW : 0)); + if (fd < 0) + /* File not found. Treat it as empty. */ + cp = ""; + else + { + FILE *fp; + + fp = fdopen (fd, "r"); + if (fp == NULL) + { + /* Out of memory. Treat the file as empty. */ + close (fd); + cp = ""; + } + else + { + /* Parse the file's contents. */ + char *res_ptr = NULL; + size_t res_size = 0; + + for (;;) + { + int c; + char buf1[50+1]; + char buf2[50+1]; + size_t l1, l2; + char *old_res_ptr; + + c = getc (fp); + if (c == EOF) + break; + if (c == '\n' || c == ' ' || c == '\t') + continue; + if (c == '#') + { + /* Skip comment, to end of line. */ + do + c = getc (fp); + while (!(c == EOF || c == '\n')); + if (c == EOF) + break; + continue; + } + ungetc (c, fp); + if (fscanf (fp, "%50s %50s", buf1, buf2) < 2) + break; + l1 = strlen (buf1); + l2 = strlen (buf2); + old_res_ptr = res_ptr; + if (res_size == 0) + { + res_size = l1 + 1 + l2 + 1; + res_ptr = (char *) malloc (res_size + 1); + } + else + { + res_size += l1 + 1 + l2 + 1; + res_ptr = (char *) realloc (res_ptr, res_size + 1); + } + if (res_ptr == NULL) + { + /* Out of memory. */ + res_size = 0; + free (old_res_ptr); + break; + } + strcpy (res_ptr + res_size - (l2 + 1) - (l1 + 1), buf1); + strcpy (res_ptr + res_size - (l2 + 1), buf2); + } + fclose (fp); + if (res_size == 0) + cp = ""; + else + { + *(res_ptr + res_size) = '\0'; + cp = res_ptr; + } + } + } + + free (file_name); + } + +#else + +# if defined DARWIN7 + /* To avoid the trouble of installing a file that is shared by many + GNU packages -- many packaging systems have problems with this --, + simply inline the aliases here. */ + cp = "ISO8859-1" "\0" "ISO-8859-1" "\0" + "ISO8859-2" "\0" "ISO-8859-2" "\0" + "ISO8859-4" "\0" "ISO-8859-4" "\0" + "ISO8859-5" "\0" "ISO-8859-5" "\0" + "ISO8859-7" "\0" "ISO-8859-7" "\0" + "ISO8859-9" "\0" "ISO-8859-9" "\0" + "ISO8859-13" "\0" "ISO-8859-13" "\0" + "ISO8859-15" "\0" "ISO-8859-15" "\0" + "KOI8-R" "\0" "KOI8-R" "\0" + "KOI8-U" "\0" "KOI8-U" "\0" + "CP866" "\0" "CP866" "\0" + "CP949" "\0" "CP949" "\0" + "CP1131" "\0" "CP1131" "\0" + "CP1251" "\0" "CP1251" "\0" + "eucCN" "\0" "GB2312" "\0" + "GB2312" "\0" "GB2312" "\0" + "eucJP" "\0" "EUC-JP" "\0" + "eucKR" "\0" "EUC-KR" "\0" + "Big5" "\0" "BIG5" "\0" + "Big5HKSCS" "\0" "BIG5-HKSCS" "\0" + "GBK" "\0" "GBK" "\0" + "GB18030" "\0" "GB18030" "\0" + "SJIS" "\0" "SHIFT_JIS" "\0" + "ARMSCII-8" "\0" "ARMSCII-8" "\0" + "PT154" "\0" "PT154" "\0" + /*"ISCII-DEV" "\0" "?" "\0"*/ + "*" "\0" "UTF-8" "\0"; +# endif + +# if defined VMS + /* To avoid the troubles of an extra file charset.alias_vms in the + sources of many GNU packages, simply inline the aliases here. */ + /* The list of encodings is taken from the OpenVMS 7.3-1 documentation + "Compaq C Run-Time Library Reference Manual for OpenVMS systems" + section 10.7 "Handling Different Character Sets". */ + cp = "ISO8859-1" "\0" "ISO-8859-1" "\0" + "ISO8859-2" "\0" "ISO-8859-2" "\0" + "ISO8859-5" "\0" "ISO-8859-5" "\0" + "ISO8859-7" "\0" "ISO-8859-7" "\0" + "ISO8859-8" "\0" "ISO-8859-8" "\0" + "ISO8859-9" "\0" "ISO-8859-9" "\0" + /* Japanese */ + "eucJP" "\0" "EUC-JP" "\0" + "SJIS" "\0" "SHIFT_JIS" "\0" + "DECKANJI" "\0" "DEC-KANJI" "\0" + "SDECKANJI" "\0" "EUC-JP" "\0" + /* Chinese */ + "eucTW" "\0" "EUC-TW" "\0" + "DECHANYU" "\0" "DEC-HANYU" "\0" + "DECHANZI" "\0" "GB2312" "\0" + /* Korean */ + "DECKOREAN" "\0" "EUC-KR" "\0"; +# endif + +# if defined WINDOWS_NATIVE || defined __CYGWIN__ + /* To avoid the troubles of installing a separate file in the same + directory as the DLL and of retrieving the DLL's directory at + runtime, simply inline the aliases here. */ + + cp = "CP936" "\0" "GBK" "\0" + "CP1361" "\0" "JOHAB" "\0" + "CP20127" "\0" "ASCII" "\0" + "CP20866" "\0" "KOI8-R" "\0" + "CP20936" "\0" "GB2312" "\0" + "CP21866" "\0" "KOI8-RU" "\0" + "CP28591" "\0" "ISO-8859-1" "\0" + "CP28592" "\0" "ISO-8859-2" "\0" + "CP28593" "\0" "ISO-8859-3" "\0" + "CP28594" "\0" "ISO-8859-4" "\0" + "CP28595" "\0" "ISO-8859-5" "\0" + "CP28596" "\0" "ISO-8859-6" "\0" + "CP28597" "\0" "ISO-8859-7" "\0" + "CP28598" "\0" "ISO-8859-8" "\0" + "CP28599" "\0" "ISO-8859-9" "\0" + "CP28605" "\0" "ISO-8859-15" "\0" + "CP38598" "\0" "ISO-8859-8" "\0" + "CP51932" "\0" "EUC-JP" "\0" + "CP51936" "\0" "GB2312" "\0" + "CP51949" "\0" "EUC-KR" "\0" + "CP51950" "\0" "EUC-TW" "\0" + "CP54936" "\0" "GB18030" "\0" + "CP65001" "\0" "UTF-8" "\0"; +# endif +#endif + + charset_aliases = cp; + } + + return cp; +} + +/* Determine the current locale's character encoding, and canonicalize it + into one of the canonical names listed in config.charset. + The result must not be freed; it is statically allocated. + If the canonical name cannot be determined, the result is a non-canonical + name. */ + +#ifdef STATIC +STATIC +#endif +const char * +locale_charset (void) +{ + const char *codeset; + const char *aliases; + +#if !(defined WINDOWS_NATIVE || defined OS2) + +# if HAVE_LANGINFO_CODESET + + /* Most systems support nl_langinfo (CODESET) nowadays. */ + codeset = nl_langinfo (CODESET); + +# ifdef __CYGWIN__ + /* Cygwin < 1.7 does not have locales. nl_langinfo (CODESET) always + returns "US-ASCII". Return the suffix of the locale name from the + environment variables (if present) or the codepage as a number. */ + if (codeset != NULL && strcmp (codeset, "US-ASCII") == 0) + { + const char *locale; + static char buf[2 + 10 + 1]; + + locale = getenv ("LC_ALL"); + if (locale == NULL || locale[0] == '\0') + { + locale = getenv ("LC_CTYPE"); + if (locale == NULL || locale[0] == '\0') + locale = getenv ("LANG"); + } + if (locale != NULL && locale[0] != '\0') + { + /* If the locale name contains an encoding after the dot, return + it. */ + const char *dot = strchr (locale, '.'); + + if (dot != NULL) + { + const char *modifier; + + dot++; + /* Look for the possible @... trailer and remove it, if any. */ + modifier = strchr (dot, '@'); + if (modifier == NULL) + return dot; + if (modifier - dot < sizeof (buf)) + { + memcpy (buf, dot, modifier - dot); + buf [modifier - dot] = '\0'; + return buf; + } + } + } + + /* The Windows API has a function returning the locale's codepage as a + number: GetACP(). This encoding is used by Cygwin, unless the user + has set the environment variable CYGWIN=codepage:oem (which very few + people do). + Output directed to console windows needs to be converted (to + GetOEMCP() if the console is using a raster font, or to + GetConsoleOutputCP() if it is using a TrueType font). Cygwin does + this conversion transparently (see winsup/cygwin/fhandler_console.cc), + converting to GetConsoleOutputCP(). This leads to correct results, + except when SetConsoleOutputCP has been called and a raster font is + in use. */ + sprintf (buf, "CP%u", GetACP ()); + codeset = buf; + } +# endif + +# else + + /* On old systems which lack it, use setlocale or getenv. */ + const char *locale = NULL; + + /* But most old systems don't have a complete set of locales. Some + (like SunOS 4 or DJGPP) have only the C locale. Therefore we don't + use setlocale here; it would return "C" when it doesn't support the + locale name the user has set. */ +# if 0 + locale = setlocale (LC_CTYPE, NULL); +# endif + if (locale == NULL || locale[0] == '\0') + { + locale = getenv ("LC_ALL"); + if (locale == NULL || locale[0] == '\0') + { + locale = getenv ("LC_CTYPE"); + if (locale == NULL || locale[0] == '\0') + locale = getenv ("LANG"); + } + } + + /* On some old systems, one used to set locale = "iso8859_1". On others, + you set it to "language_COUNTRY.charset". In any case, we resolve it + through the charset.alias file. */ + codeset = locale; + +# endif + +#elif defined WINDOWS_NATIVE + + static char buf[2 + 10 + 1]; + + /* The Windows API has a function returning the locale's codepage as + a number, but the value doesn't change according to what the + 'setlocale' call specified. So we use it as a last resort, in + case the string returned by 'setlocale' doesn't specify the + codepage. */ + char *current_locale = setlocale (LC_ALL, NULL); + char *pdot; + + /* If they set different locales for different categories, + 'setlocale' will return a semi-colon separated list of locale + values. To make sure we use the correct one, we choose LC_CTYPE. */ + if (strchr (current_locale, ';')) + current_locale = setlocale (LC_CTYPE, NULL); + + pdot = strrchr (current_locale, '.'); + if (pdot) + sprintf (buf, "CP%s", pdot + 1); + else + { + /* The Windows API has a function returning the locale's codepage as a + number: GetACP(). + When the output goes to a console window, it needs to be provided in + GetOEMCP() encoding if the console is using a raster font, or in + GetConsoleOutputCP() encoding if it is using a TrueType font. + But in GUI programs and for output sent to files and pipes, GetACP() + encoding is the best bet. */ + sprintf (buf, "CP%u", GetACP ()); + } + codeset = buf; + +#elif defined OS2 + + const char *locale; + static char buf[2 + 10 + 1]; + ULONG cp[3]; + ULONG cplen; + + /* Allow user to override the codeset, as set in the operating system, + with standard language environment variables. */ + locale = getenv ("LC_ALL"); + if (locale == NULL || locale[0] == '\0') + { + locale = getenv ("LC_CTYPE"); + if (locale == NULL || locale[0] == '\0') + locale = getenv ("LANG"); + } + if (locale != NULL && locale[0] != '\0') + { + /* If the locale name contains an encoding after the dot, return it. */ + const char *dot = strchr (locale, '.'); + + if (dot != NULL) + { + const char *modifier; + + dot++; + /* Look for the possible @... trailer and remove it, if any. */ + modifier = strchr (dot, '@'); + if (modifier == NULL) + return dot; + if (modifier - dot < sizeof (buf)) + { + memcpy (buf, dot, modifier - dot); + buf [modifier - dot] = '\0'; + return buf; + } + } + + /* Resolve through the charset.alias file. */ + codeset = locale; + } + else + { + /* OS/2 has a function returning the locale's codepage as a number. */ + if (DosQueryCp (sizeof (cp), cp, &cplen)) + codeset = ""; + else + { + sprintf (buf, "CP%u", cp[0]); + codeset = buf; + } + } + +#endif + + if (codeset == NULL) + /* The canonical name cannot be determined. */ + codeset = ""; + + /* Resolve alias. */ + for (aliases = get_charset_aliases (); + *aliases != '\0'; + aliases += strlen (aliases) + 1, aliases += strlen (aliases) + 1) + if (strcmp (codeset, aliases) == 0 + || (aliases[0] == '*' && aliases[1] == '\0')) + { + codeset = aliases + strlen (aliases) + 1; + break; + } + + /* Don't return an empty string. GNU libc and GNU libiconv interpret + the empty string as denoting "the locale's character encoding", + thus GNU libiconv would call this function a second time. */ + if (codeset[0] == '\0') + codeset = "ASCII"; + +#ifdef DARWIN7 + /* Mac OS X sets MB_CUR_MAX to 1 when LC_ALL=C, and "UTF-8" + (the default codeset) does not work when MB_CUR_MAX is 1. */ + if (strcmp (codeset, "UTF-8") == 0 && MB_CUR_MAX_L (uselocale (NULL)) <= 1) + codeset = "ASCII"; +#endif + + return codeset; +} diff --git a/gettext-tools/gnulib-lib/localcharset.h b/gettext-tools/gnulib-lib/localcharset.h new file mode 100644 index 0000000..9011d58 --- /dev/null +++ b/gettext-tools/gnulib-lib/localcharset.h @@ -0,0 +1,40 @@ +/* Determine a canonical name for the current locale's character encoding. + Copyright (C) 2000-2003, 2009-2014 Free Software Foundation, Inc. + This file is part of the GNU CHARSET Library. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, see . */ + +#ifndef _LOCALCHARSET_H +#define _LOCALCHARSET_H + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Determine the current locale's character encoding, and canonicalize it + into one of the canonical names listed in config.charset. + The result must not be freed; it is statically allocated. + If the canonical name cannot be determined, the result is a non-canonical + name. */ +extern const char * locale_charset (void); + + +#ifdef __cplusplus +} +#endif + + +#endif /* _LOCALCHARSET_H */ diff --git a/gettext-tools/gnulib-lib/locale.in.h b/gettext-tools/gnulib-lib/locale.in.h new file mode 100644 index 0000000..10cc44b --- /dev/null +++ b/gettext-tools/gnulib-lib/locale.in.h @@ -0,0 +1,216 @@ +/* A POSIX . + Copyright (C) 2007-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +#ifdef _GL_ALREADY_INCLUDING_LOCALE_H + +/* Special invocation conventions to handle Solaris header files + (through Solaris 10) when combined with gettext's libintl.h. */ + +#@INCLUDE_NEXT@ @NEXT_LOCALE_H@ + +#else +/* Normal invocation convention. */ + +#ifndef _@GUARD_PREFIX@_LOCALE_H + +#define _GL_ALREADY_INCLUDING_LOCALE_H + +/* The include_next requires a split double-inclusion guard. */ +#@INCLUDE_NEXT@ @NEXT_LOCALE_H@ + +#undef _GL_ALREADY_INCLUDING_LOCALE_H + +#ifndef _@GUARD_PREFIX@_LOCALE_H +#define _@GUARD_PREFIX@_LOCALE_H + +/* NetBSD 5.0 mis-defines NULL. */ +#include + +/* Mac OS X 10.5 defines the locale_t type in . */ +#if @HAVE_XLOCALE_H@ +# include +#endif + +/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ + +/* The definition of _GL_ARG_NONNULL is copied here. */ + +/* The definition of _GL_WARN_ON_USE is copied here. */ + +/* The LC_MESSAGES locale category is specified in POSIX, but not in ISO C. + On systems that don't define it, use the same value as GNU libintl. */ +#if !defined LC_MESSAGES +# define LC_MESSAGES 1729 +#endif + +/* Bionic libc's 'struct lconv' is just a dummy. */ +#if @REPLACE_STRUCT_LCONV@ +# define lconv rpl_lconv +struct lconv +{ + /* All 'char *' are actually 'const char *'. */ + + /* Members that depend on the LC_NUMERIC category of the locale. See + */ + + /* Symbol used as decimal point. */ + char *decimal_point; + /* Symbol used to separate groups of digits to the left of the decimal + point. */ + char *thousands_sep; + /* Definition of the size of groups of digits to the left of the decimal + point. */ + char *grouping; + + /* Members that depend on the LC_MONETARY category of the locale. See + */ + + /* Symbol used as decimal point. */ + char *mon_decimal_point; + /* Symbol used to separate groups of digits to the left of the decimal + point. */ + char *mon_thousands_sep; + /* Definition of the size of groups of digits to the left of the decimal + point. */ + char *mon_grouping; + /* Sign used to indicate a value >= 0. */ + char *positive_sign; + /* Sign used to indicate a value < 0. */ + char *negative_sign; + + /* For formatting local currency. */ + /* Currency symbol (3 characters) followed by separator (1 character). */ + char *currency_symbol; + /* Number of digits after the decimal point. */ + char frac_digits; + /* For values >= 0: 1 if the currency symbol precedes the number, 0 if it + comes after the number. */ + char p_cs_precedes; + /* For values >= 0: Position of the sign. */ + char p_sign_posn; + /* For values >= 0: Placement of spaces between currency symbol, sign, and + number. */ + char p_sep_by_space; + /* For values < 0: 1 if the currency symbol precedes the number, 0 if it + comes after the number. */ + char n_cs_precedes; + /* For values < 0: Position of the sign. */ + char n_sign_posn; + /* For values < 0: Placement of spaces between currency symbol, sign, and + number. */ + char n_sep_by_space; + + /* For formatting international currency. */ + /* Currency symbol (3 characters) followed by separator (1 character). */ + char *int_curr_symbol; + /* Number of digits after the decimal point. */ + char int_frac_digits; + /* For values >= 0: 1 if the currency symbol precedes the number, 0 if it + comes after the number. */ + char int_p_cs_precedes; + /* For values >= 0: Position of the sign. */ + char int_p_sign_posn; + /* For values >= 0: Placement of spaces between currency symbol, sign, and + number. */ + char int_p_sep_by_space; + /* For values < 0: 1 if the currency symbol precedes the number, 0 if it + comes after the number. */ + char int_n_cs_precedes; + /* For values < 0: Position of the sign. */ + char int_n_sign_posn; + /* For values < 0: Placement of spaces between currency symbol, sign, and + number. */ + char int_n_sep_by_space; +}; +#endif + +#if @GNULIB_LOCALECONV@ +# if @REPLACE_LOCALECONV@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef localeconv +# define localeconv rpl_localeconv +# endif +_GL_FUNCDECL_RPL (localeconv, struct lconv *, (void)); +_GL_CXXALIAS_RPL (localeconv, struct lconv *, (void)); +# else +_GL_CXXALIAS_SYS (localeconv, struct lconv *, (void)); +# endif +_GL_CXXALIASWARN (localeconv); +#elif @REPLACE_STRUCT_LCONV@ +# undef localeconv +# define localeconv localeconv_used_without_requesting_gnulib_module_localeconv +#elif defined GNULIB_POSIXCHECK +# undef localeconv +# if HAVE_RAW_DECL_LOCALECONV +_GL_WARN_ON_USE (localeconv, + "localeconv returns too few information on some platforms - " + "use gnulib module localeconv for portability"); +# endif +#endif + +#if @GNULIB_SETLOCALE@ +# if @REPLACE_SETLOCALE@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef setlocale +# define setlocale rpl_setlocale +# define GNULIB_defined_setlocale 1 +# endif +_GL_FUNCDECL_RPL (setlocale, char *, (int category, const char *locale)); +_GL_CXXALIAS_RPL (setlocale, char *, (int category, const char *locale)); +# else +_GL_CXXALIAS_SYS (setlocale, char *, (int category, const char *locale)); +# endif +_GL_CXXALIASWARN (setlocale); +#elif defined GNULIB_POSIXCHECK +# undef setlocale +# if HAVE_RAW_DECL_SETLOCALE +_GL_WARN_ON_USE (setlocale, "setlocale works differently on native Windows - " + "use gnulib module setlocale for portability"); +# endif +#endif + +#if @GNULIB_DUPLOCALE@ +# if @REPLACE_DUPLOCALE@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef duplocale +# define duplocale rpl_duplocale +# endif +_GL_FUNCDECL_RPL (duplocale, locale_t, (locale_t locale) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (duplocale, locale_t, (locale_t locale)); +# else +# if @HAVE_DUPLOCALE@ +_GL_CXXALIAS_SYS (duplocale, locale_t, (locale_t locale)); +# endif +# endif +# if @HAVE_DUPLOCALE@ +_GL_CXXALIASWARN (duplocale); +# endif +#elif defined GNULIB_POSIXCHECK +# undef duplocale +# if HAVE_RAW_DECL_DUPLOCALE +_GL_WARN_ON_USE (duplocale, "duplocale is buggy on some glibc systems - " + "use gnulib module duplocale for portability"); +# endif +#endif + +#endif /* _@GUARD_PREFIX@_LOCALE_H */ +#endif /* ! _GL_ALREADY_INCLUDING_LOCALE_H */ +#endif /* _@GUARD_PREFIX@_LOCALE_H */ diff --git a/gettext-tools/gnulib-lib/localename.c b/gettext-tools/gnulib-lib/localename.c new file mode 100644 index 0000000..2c7bfc8 --- /dev/null +++ b/gettext-tools/gnulib-lib/localename.c @@ -0,0 +1,2958 @@ +/* Determine name of the currently selected locale. + Copyright (C) 1995-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Written by Ulrich Drepper , 1995. */ +/* Native Windows code written by Tor Lillqvist . */ +/* Mac OS X code written by Bruno Haible . */ + +#include + +/* Specification. */ +#ifdef IN_LIBINTL +# include "gettextP.h" +#else +# include "localename.h" +#endif + +#include +#include +#include +#include +#include + +#if HAVE_USELOCALE +/* Mac OS X 10.5 defines the locale_t type in . */ +# if defined __APPLE__ && defined __MACH__ +# include +# endif +# include +# if !defined IN_LIBINTL +# include "glthread/lock.h" +# endif +#endif + +#if HAVE_CFLOCALECOPYCURRENT || HAVE_CFPREFERENCESCOPYAPPVALUE +# include +# if HAVE_CFLOCALECOPYCURRENT +# include +# elif HAVE_CFPREFERENCESCOPYAPPVALUE +# include +# endif +#endif + +#if defined _WIN32 || defined __WIN32__ +# define WINDOWS_NATIVE +# if !defined IN_LIBINTL +# include "glthread/lock.h" +# endif +#endif + +#if defined WINDOWS_NATIVE || defined __CYGWIN__ /* Native Windows or Cygwin */ +# define WIN32_LEAN_AND_MEAN +# include +# include +/* List of language codes, sorted by value: + 0x01 LANG_ARABIC + 0x02 LANG_BULGARIAN + 0x03 LANG_CATALAN + 0x04 LANG_CHINESE + 0x05 LANG_CZECH + 0x06 LANG_DANISH + 0x07 LANG_GERMAN + 0x08 LANG_GREEK + 0x09 LANG_ENGLISH + 0x0a LANG_SPANISH + 0x0b LANG_FINNISH + 0x0c LANG_FRENCH + 0x0d LANG_HEBREW + 0x0e LANG_HUNGARIAN + 0x0f LANG_ICELANDIC + 0x10 LANG_ITALIAN + 0x11 LANG_JAPANESE + 0x12 LANG_KOREAN + 0x13 LANG_DUTCH + 0x14 LANG_NORWEGIAN + 0x15 LANG_POLISH + 0x16 LANG_PORTUGUESE + 0x17 LANG_ROMANSH + 0x18 LANG_ROMANIAN + 0x19 LANG_RUSSIAN + 0x1a LANG_CROATIAN == LANG_SERBIAN + 0x1b LANG_SLOVAK + 0x1c LANG_ALBANIAN + 0x1d LANG_SWEDISH + 0x1e LANG_THAI + 0x1f LANG_TURKISH + 0x20 LANG_URDU + 0x21 LANG_INDONESIAN + 0x22 LANG_UKRAINIAN + 0x23 LANG_BELARUSIAN + 0x24 LANG_SLOVENIAN + 0x25 LANG_ESTONIAN + 0x26 LANG_LATVIAN + 0x27 LANG_LITHUANIAN + 0x28 LANG_TAJIK + 0x29 LANG_FARSI + 0x2a LANG_VIETNAMESE + 0x2b LANG_ARMENIAN + 0x2c LANG_AZERI + 0x2d LANG_BASQUE + 0x2e LANG_SORBIAN + 0x2f LANG_MACEDONIAN + 0x30 LANG_SUTU + 0x31 LANG_TSONGA + 0x32 LANG_TSWANA + 0x33 LANG_VENDA + 0x34 LANG_XHOSA + 0x35 LANG_ZULU + 0x36 LANG_AFRIKAANS + 0x37 LANG_GEORGIAN + 0x38 LANG_FAEROESE + 0x39 LANG_HINDI + 0x3a LANG_MALTESE + 0x3b LANG_SAMI + 0x3c LANG_GAELIC + 0x3d LANG_YIDDISH + 0x3e LANG_MALAY + 0x3f LANG_KAZAK + 0x40 LANG_KYRGYZ + 0x41 LANG_SWAHILI + 0x42 LANG_TURKMEN + 0x43 LANG_UZBEK + 0x44 LANG_TATAR + 0x45 LANG_BENGALI + 0x46 LANG_PUNJABI + 0x47 LANG_GUJARATI + 0x48 LANG_ORIYA + 0x49 LANG_TAMIL + 0x4a LANG_TELUGU + 0x4b LANG_KANNADA + 0x4c LANG_MALAYALAM + 0x4d LANG_ASSAMESE + 0x4e LANG_MARATHI + 0x4f LANG_SANSKRIT + 0x50 LANG_MONGOLIAN + 0x51 LANG_TIBETAN + 0x52 LANG_WELSH + 0x53 LANG_CAMBODIAN + 0x54 LANG_LAO + 0x55 LANG_BURMESE + 0x56 LANG_GALICIAN + 0x57 LANG_KONKANI + 0x58 LANG_MANIPURI + 0x59 LANG_SINDHI + 0x5a LANG_SYRIAC + 0x5b LANG_SINHALESE + 0x5c LANG_CHEROKEE + 0x5d LANG_INUKTITUT + 0x5e LANG_AMHARIC + 0x5f LANG_TAMAZIGHT + 0x60 LANG_KASHMIRI + 0x61 LANG_NEPALI + 0x62 LANG_FRISIAN + 0x63 LANG_PASHTO + 0x64 LANG_TAGALOG + 0x65 LANG_DIVEHI + 0x66 LANG_EDO + 0x67 LANG_FULFULDE + 0x68 LANG_HAUSA + 0x69 LANG_IBIBIO + 0x6a LANG_YORUBA + 0x6d LANG_BASHKIR + 0x6e LANG_LUXEMBOURGISH + 0x6f LANG_GREENLANDIC + 0x70 LANG_IGBO + 0x71 LANG_KANURI + 0x72 LANG_OROMO + 0x73 LANG_TIGRINYA + 0x74 LANG_GUARANI + 0x75 LANG_HAWAIIAN + 0x76 LANG_LATIN + 0x77 LANG_SOMALI + 0x78 LANG_YI + 0x79 LANG_PAPIAMENTU + 0x7a LANG_MAPUDUNGUN + 0x7c LANG_MOHAWK + 0x7e LANG_BRETON + 0x82 LANG_OCCITAN + 0x83 LANG_CORSICAN + 0x84 LANG_ALSATIAN + 0x85 LANG_YAKUT + 0x86 LANG_KICHE + 0x87 LANG_KINYARWANDA + 0x88 LANG_WOLOF + 0x8c LANG_DARI + 0x91 LANG_SCOTTISH_GAELIC +*/ +/* Mingw headers don't have latest language and sublanguage codes. */ +# ifndef LANG_AFRIKAANS +# define LANG_AFRIKAANS 0x36 +# endif +# ifndef LANG_ALBANIAN +# define LANG_ALBANIAN 0x1c +# endif +# ifndef LANG_ALSATIAN +# define LANG_ALSATIAN 0x84 +# endif +# ifndef LANG_AMHARIC +# define LANG_AMHARIC 0x5e +# endif +# ifndef LANG_ARABIC +# define LANG_ARABIC 0x01 +# endif +# ifndef LANG_ARMENIAN +# define LANG_ARMENIAN 0x2b +# endif +# ifndef LANG_ASSAMESE +# define LANG_ASSAMESE 0x4d +# endif +# ifndef LANG_AZERI +# define LANG_AZERI 0x2c +# endif +# ifndef LANG_BASHKIR +# define LANG_BASHKIR 0x6d +# endif +# ifndef LANG_BASQUE +# define LANG_BASQUE 0x2d +# endif +# ifndef LANG_BELARUSIAN +# define LANG_BELARUSIAN 0x23 +# endif +# ifndef LANG_BENGALI +# define LANG_BENGALI 0x45 +# endif +# ifndef LANG_BRETON +# define LANG_BRETON 0x7e +# endif +# ifndef LANG_BURMESE +# define LANG_BURMESE 0x55 +# endif +# ifndef LANG_CAMBODIAN +# define LANG_CAMBODIAN 0x53 +# endif +# ifndef LANG_CATALAN +# define LANG_CATALAN 0x03 +# endif +# ifndef LANG_CHEROKEE +# define LANG_CHEROKEE 0x5c +# endif +# ifndef LANG_CORSICAN +# define LANG_CORSICAN 0x83 +# endif +# ifndef LANG_DARI +# define LANG_DARI 0x8c +# endif +# ifndef LANG_DIVEHI +# define LANG_DIVEHI 0x65 +# endif +# ifndef LANG_EDO +# define LANG_EDO 0x66 +# endif +# ifndef LANG_ESTONIAN +# define LANG_ESTONIAN 0x25 +# endif +# ifndef LANG_FAEROESE +# define LANG_FAEROESE 0x38 +# endif +# ifndef LANG_FARSI +# define LANG_FARSI 0x29 +# endif +# ifndef LANG_FRISIAN +# define LANG_FRISIAN 0x62 +# endif +# ifndef LANG_FULFULDE +# define LANG_FULFULDE 0x67 +# endif +# ifndef LANG_GAELIC +# define LANG_GAELIC 0x3c +# endif +# ifndef LANG_GALICIAN +# define LANG_GALICIAN 0x56 +# endif +# ifndef LANG_GEORGIAN +# define LANG_GEORGIAN 0x37 +# endif +# ifndef LANG_GREENLANDIC +# define LANG_GREENLANDIC 0x6f +# endif +# ifndef LANG_GUARANI +# define LANG_GUARANI 0x74 +# endif +# ifndef LANG_GUJARATI +# define LANG_GUJARATI 0x47 +# endif +# ifndef LANG_HAUSA +# define LANG_HAUSA 0x68 +# endif +# ifndef LANG_HAWAIIAN +# define LANG_HAWAIIAN 0x75 +# endif +# ifndef LANG_HEBREW +# define LANG_HEBREW 0x0d +# endif +# ifndef LANG_HINDI +# define LANG_HINDI 0x39 +# endif +# ifndef LANG_IBIBIO +# define LANG_IBIBIO 0x69 +# endif +# ifndef LANG_IGBO +# define LANG_IGBO 0x70 +# endif +# ifndef LANG_INDONESIAN +# define LANG_INDONESIAN 0x21 +# endif +# ifndef LANG_INUKTITUT +# define LANG_INUKTITUT 0x5d +# endif +# ifndef LANG_KANNADA +# define LANG_KANNADA 0x4b +# endif +# ifndef LANG_KANURI +# define LANG_KANURI 0x71 +# endif +# ifndef LANG_KASHMIRI +# define LANG_KASHMIRI 0x60 +# endif +# ifndef LANG_KAZAK +# define LANG_KAZAK 0x3f +# endif +# ifndef LANG_KICHE +# define LANG_KICHE 0x86 +# endif +# ifndef LANG_KINYARWANDA +# define LANG_KINYARWANDA 0x87 +# endif +# ifndef LANG_KONKANI +# define LANG_KONKANI 0x57 +# endif +# ifndef LANG_KYRGYZ +# define LANG_KYRGYZ 0x40 +# endif +# ifndef LANG_LAO +# define LANG_LAO 0x54 +# endif +# ifndef LANG_LATIN +# define LANG_LATIN 0x76 +# endif +# ifndef LANG_LATVIAN +# define LANG_LATVIAN 0x26 +# endif +# ifndef LANG_LITHUANIAN +# define LANG_LITHUANIAN 0x27 +# endif +# ifndef LANG_LUXEMBOURGISH +# define LANG_LUXEMBOURGISH 0x6e +# endif +# ifndef LANG_MACEDONIAN +# define LANG_MACEDONIAN 0x2f +# endif +# ifndef LANG_MALAY +# define LANG_MALAY 0x3e +# endif +# ifndef LANG_MALAYALAM +# define LANG_MALAYALAM 0x4c +# endif +# ifndef LANG_MALTESE +# define LANG_MALTESE 0x3a +# endif +# ifndef LANG_MANIPURI +# define LANG_MANIPURI 0x58 +# endif +# ifndef LANG_MAORI +# define LANG_MAORI 0x81 +# endif +# ifndef LANG_MAPUDUNGUN +# define LANG_MAPUDUNGUN 0x7a +# endif +# ifndef LANG_MARATHI +# define LANG_MARATHI 0x4e +# endif +# ifndef LANG_MOHAWK +# define LANG_MOHAWK 0x7c +# endif +# ifndef LANG_MONGOLIAN +# define LANG_MONGOLIAN 0x50 +# endif +# ifndef LANG_NEPALI +# define LANG_NEPALI 0x61 +# endif +# ifndef LANG_OCCITAN +# define LANG_OCCITAN 0x82 +# endif +# ifndef LANG_ORIYA +# define LANG_ORIYA 0x48 +# endif +# ifndef LANG_OROMO +# define LANG_OROMO 0x72 +# endif +# ifndef LANG_PAPIAMENTU +# define LANG_PAPIAMENTU 0x79 +# endif +# ifndef LANG_PASHTO +# define LANG_PASHTO 0x63 +# endif +# ifndef LANG_PUNJABI +# define LANG_PUNJABI 0x46 +# endif +# ifndef LANG_QUECHUA +# define LANG_QUECHUA 0x6b +# endif +# ifndef LANG_ROMANSH +# define LANG_ROMANSH 0x17 +# endif +# ifndef LANG_SAMI +# define LANG_SAMI 0x3b +# endif +# ifndef LANG_SANSKRIT +# define LANG_SANSKRIT 0x4f +# endif +# ifndef LANG_SCOTTISH_GAELIC +# define LANG_SCOTTISH_GAELIC 0x91 +# endif +# ifndef LANG_SERBIAN +# define LANG_SERBIAN 0x1a +# endif +# ifndef LANG_SINDHI +# define LANG_SINDHI 0x59 +# endif +# ifndef LANG_SINHALESE +# define LANG_SINHALESE 0x5b +# endif +# ifndef LANG_SLOVAK +# define LANG_SLOVAK 0x1b +# endif +# ifndef LANG_SOMALI +# define LANG_SOMALI 0x77 +# endif +# ifndef LANG_SORBIAN +# define LANG_SORBIAN 0x2e +# endif +# ifndef LANG_SOTHO +# define LANG_SOTHO 0x6c +# endif +# ifndef LANG_SUTU +# define LANG_SUTU 0x30 +# endif +# ifndef LANG_SWAHILI +# define LANG_SWAHILI 0x41 +# endif +# ifndef LANG_SYRIAC +# define LANG_SYRIAC 0x5a +# endif +# ifndef LANG_TAGALOG +# define LANG_TAGALOG 0x64 +# endif +# ifndef LANG_TAJIK +# define LANG_TAJIK 0x28 +# endif +# ifndef LANG_TAMAZIGHT +# define LANG_TAMAZIGHT 0x5f +# endif +# ifndef LANG_TAMIL +# define LANG_TAMIL 0x49 +# endif +# ifndef LANG_TATAR +# define LANG_TATAR 0x44 +# endif +# ifndef LANG_TELUGU +# define LANG_TELUGU 0x4a +# endif +# ifndef LANG_THAI +# define LANG_THAI 0x1e +# endif +# ifndef LANG_TIBETAN +# define LANG_TIBETAN 0x51 +# endif +# ifndef LANG_TIGRINYA +# define LANG_TIGRINYA 0x73 +# endif +# ifndef LANG_TSONGA +# define LANG_TSONGA 0x31 +# endif +# ifndef LANG_TSWANA +# define LANG_TSWANA 0x32 +# endif +# ifndef LANG_TURKMEN +# define LANG_TURKMEN 0x42 +# endif +# ifndef LANG_UIGHUR +# define LANG_UIGHUR 0x80 +# endif +# ifndef LANG_UKRAINIAN +# define LANG_UKRAINIAN 0x22 +# endif +# ifndef LANG_URDU +# define LANG_URDU 0x20 +# endif +# ifndef LANG_UZBEK +# define LANG_UZBEK 0x43 +# endif +# ifndef LANG_VENDA +# define LANG_VENDA 0x33 +# endif +# ifndef LANG_VIETNAMESE +# define LANG_VIETNAMESE 0x2a +# endif +# ifndef LANG_WELSH +# define LANG_WELSH 0x52 +# endif +# ifndef LANG_WOLOF +# define LANG_WOLOF 0x88 +# endif +# ifndef LANG_XHOSA +# define LANG_XHOSA 0x34 +# endif +# ifndef LANG_YAKUT +# define LANG_YAKUT 0x85 +# endif +# ifndef LANG_YI +# define LANG_YI 0x78 +# endif +# ifndef LANG_YIDDISH +# define LANG_YIDDISH 0x3d +# endif +# ifndef LANG_YORUBA +# define LANG_YORUBA 0x6a +# endif +# ifndef LANG_ZULU +# define LANG_ZULU 0x35 +# endif +# ifndef SUBLANG_AFRIKAANS_SOUTH_AFRICA +# define SUBLANG_AFRIKAANS_SOUTH_AFRICA 0x01 +# endif +# ifndef SUBLANG_ALBANIAN_ALBANIA +# define SUBLANG_ALBANIAN_ALBANIA 0x01 +# endif +# ifndef SUBLANG_ALSATIAN_FRANCE +# define SUBLANG_ALSATIAN_FRANCE 0x01 +# endif +# ifndef SUBLANG_AMHARIC_ETHIOPIA +# define SUBLANG_AMHARIC_ETHIOPIA 0x01 +# endif +# ifndef SUBLANG_ARABIC_SAUDI_ARABIA +# define SUBLANG_ARABIC_SAUDI_ARABIA 0x01 +# endif +# ifndef SUBLANG_ARABIC_IRAQ +# define SUBLANG_ARABIC_IRAQ 0x02 +# endif +# ifndef SUBLANG_ARABIC_EGYPT +# define SUBLANG_ARABIC_EGYPT 0x03 +# endif +# ifndef SUBLANG_ARABIC_LIBYA +# define SUBLANG_ARABIC_LIBYA 0x04 +# endif +# ifndef SUBLANG_ARABIC_ALGERIA +# define SUBLANG_ARABIC_ALGERIA 0x05 +# endif +# ifndef SUBLANG_ARABIC_MOROCCO +# define SUBLANG_ARABIC_MOROCCO 0x06 +# endif +# ifndef SUBLANG_ARABIC_TUNISIA +# define SUBLANG_ARABIC_TUNISIA 0x07 +# endif +# ifndef SUBLANG_ARABIC_OMAN +# define SUBLANG_ARABIC_OMAN 0x08 +# endif +# ifndef SUBLANG_ARABIC_YEMEN +# define SUBLANG_ARABIC_YEMEN 0x09 +# endif +# ifndef SUBLANG_ARABIC_SYRIA +# define SUBLANG_ARABIC_SYRIA 0x0a +# endif +# ifndef SUBLANG_ARABIC_JORDAN +# define SUBLANG_ARABIC_JORDAN 0x0b +# endif +# ifndef SUBLANG_ARABIC_LEBANON +# define SUBLANG_ARABIC_LEBANON 0x0c +# endif +# ifndef SUBLANG_ARABIC_KUWAIT +# define SUBLANG_ARABIC_KUWAIT 0x0d +# endif +# ifndef SUBLANG_ARABIC_UAE +# define SUBLANG_ARABIC_UAE 0x0e +# endif +# ifndef SUBLANG_ARABIC_BAHRAIN +# define SUBLANG_ARABIC_BAHRAIN 0x0f +# endif +# ifndef SUBLANG_ARABIC_QATAR +# define SUBLANG_ARABIC_QATAR 0x10 +# endif +# ifndef SUBLANG_ARMENIAN_ARMENIA +# define SUBLANG_ARMENIAN_ARMENIA 0x01 +# endif +# ifndef SUBLANG_ASSAMESE_INDIA +# define SUBLANG_ASSAMESE_INDIA 0x01 +# endif +# ifndef SUBLANG_AZERI_LATIN +# define SUBLANG_AZERI_LATIN 0x01 +# endif +# ifndef SUBLANG_AZERI_CYRILLIC +# define SUBLANG_AZERI_CYRILLIC 0x02 +# endif +# ifndef SUBLANG_BASHKIR_RUSSIA +# define SUBLANG_BASHKIR_RUSSIA 0x01 +# endif +# ifndef SUBLANG_BASQUE_BASQUE +# define SUBLANG_BASQUE_BASQUE 0x01 +# endif +# ifndef SUBLANG_BELARUSIAN_BELARUS +# define SUBLANG_BELARUSIAN_BELARUS 0x01 +# endif +# ifndef SUBLANG_BENGALI_INDIA +# define SUBLANG_BENGALI_INDIA 0x01 +# endif +# ifndef SUBLANG_BENGALI_BANGLADESH +# define SUBLANG_BENGALI_BANGLADESH 0x02 +# endif +# ifndef SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_LATIN +# define SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_LATIN 0x05 +# endif +# ifndef SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_CYRILLIC +# define SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_CYRILLIC 0x08 +# endif +# ifndef SUBLANG_BRETON_FRANCE +# define SUBLANG_BRETON_FRANCE 0x01 +# endif +# ifndef SUBLANG_BULGARIAN_BULGARIA +# define SUBLANG_BULGARIAN_BULGARIA 0x01 +# endif +# ifndef SUBLANG_CAMBODIAN_CAMBODIA +# define SUBLANG_CAMBODIAN_CAMBODIA 0x01 +# endif +# ifndef SUBLANG_CATALAN_SPAIN +# define SUBLANG_CATALAN_SPAIN 0x01 +# endif +# ifndef SUBLANG_CORSICAN_FRANCE +# define SUBLANG_CORSICAN_FRANCE 0x01 +# endif +# ifndef SUBLANG_CROATIAN_CROATIA +# define SUBLANG_CROATIAN_CROATIA 0x01 +# endif +# ifndef SUBLANG_CROATIAN_BOSNIA_HERZEGOVINA_LATIN +# define SUBLANG_CROATIAN_BOSNIA_HERZEGOVINA_LATIN 0x04 +# endif +# ifndef SUBLANG_CHINESE_MACAU +# define SUBLANG_CHINESE_MACAU 0x05 +# endif +# ifndef SUBLANG_CZECH_CZECH_REPUBLIC +# define SUBLANG_CZECH_CZECH_REPUBLIC 0x01 +# endif +# ifndef SUBLANG_DANISH_DENMARK +# define SUBLANG_DANISH_DENMARK 0x01 +# endif +# ifndef SUBLANG_DARI_AFGHANISTAN +# define SUBLANG_DARI_AFGHANISTAN 0x01 +# endif +# ifndef SUBLANG_DIVEHI_MALDIVES +# define SUBLANG_DIVEHI_MALDIVES 0x01 +# endif +# ifndef SUBLANG_DUTCH_SURINAM +# define SUBLANG_DUTCH_SURINAM 0x03 +# endif +# ifndef SUBLANG_ENGLISH_SOUTH_AFRICA +# define SUBLANG_ENGLISH_SOUTH_AFRICA 0x07 +# endif +# ifndef SUBLANG_ENGLISH_JAMAICA +# define SUBLANG_ENGLISH_JAMAICA 0x08 +# endif +# ifndef SUBLANG_ENGLISH_CARIBBEAN +# define SUBLANG_ENGLISH_CARIBBEAN 0x09 +# endif +# ifndef SUBLANG_ENGLISH_BELIZE +# define SUBLANG_ENGLISH_BELIZE 0x0a +# endif +# ifndef SUBLANG_ENGLISH_TRINIDAD +# define SUBLANG_ENGLISH_TRINIDAD 0x0b +# endif +# ifndef SUBLANG_ENGLISH_ZIMBABWE +# define SUBLANG_ENGLISH_ZIMBABWE 0x0c +# endif +# ifndef SUBLANG_ENGLISH_PHILIPPINES +# define SUBLANG_ENGLISH_PHILIPPINES 0x0d +# endif +# ifndef SUBLANG_ENGLISH_INDONESIA +# define SUBLANG_ENGLISH_INDONESIA 0x0e +# endif +# ifndef SUBLANG_ENGLISH_HONGKONG +# define SUBLANG_ENGLISH_HONGKONG 0x0f +# endif +# ifndef SUBLANG_ENGLISH_INDIA +# define SUBLANG_ENGLISH_INDIA 0x10 +# endif +# ifndef SUBLANG_ENGLISH_MALAYSIA +# define SUBLANG_ENGLISH_MALAYSIA 0x11 +# endif +# ifndef SUBLANG_ENGLISH_SINGAPORE +# define SUBLANG_ENGLISH_SINGAPORE 0x12 +# endif +# ifndef SUBLANG_ESTONIAN_ESTONIA +# define SUBLANG_ESTONIAN_ESTONIA 0x01 +# endif +# ifndef SUBLANG_FAEROESE_FAROE_ISLANDS +# define SUBLANG_FAEROESE_FAROE_ISLANDS 0x01 +# endif +# ifndef SUBLANG_FARSI_IRAN +# define SUBLANG_FARSI_IRAN 0x01 +# endif +# ifndef SUBLANG_FINNISH_FINLAND +# define SUBLANG_FINNISH_FINLAND 0x01 +# endif +# ifndef SUBLANG_FRENCH_LUXEMBOURG +# define SUBLANG_FRENCH_LUXEMBOURG 0x05 +# endif +# ifndef SUBLANG_FRENCH_MONACO +# define SUBLANG_FRENCH_MONACO 0x06 +# endif +# ifndef SUBLANG_FRENCH_WESTINDIES +# define SUBLANG_FRENCH_WESTINDIES 0x07 +# endif +# ifndef SUBLANG_FRENCH_REUNION +# define SUBLANG_FRENCH_REUNION 0x08 +# endif +# ifndef SUBLANG_FRENCH_CONGO +# define SUBLANG_FRENCH_CONGO 0x09 +# endif +# ifndef SUBLANG_FRENCH_SENEGAL +# define SUBLANG_FRENCH_SENEGAL 0x0a +# endif +# ifndef SUBLANG_FRENCH_CAMEROON +# define SUBLANG_FRENCH_CAMEROON 0x0b +# endif +# ifndef SUBLANG_FRENCH_COTEDIVOIRE +# define SUBLANG_FRENCH_COTEDIVOIRE 0x0c +# endif +# ifndef SUBLANG_FRENCH_MALI +# define SUBLANG_FRENCH_MALI 0x0d +# endif +# ifndef SUBLANG_FRENCH_MOROCCO +# define SUBLANG_FRENCH_MOROCCO 0x0e +# endif +# ifndef SUBLANG_FRENCH_HAITI +# define SUBLANG_FRENCH_HAITI 0x0f +# endif +# ifndef SUBLANG_FRISIAN_NETHERLANDS +# define SUBLANG_FRISIAN_NETHERLANDS 0x01 +# endif +# ifndef SUBLANG_GALICIAN_SPAIN +# define SUBLANG_GALICIAN_SPAIN 0x01 +# endif +# ifndef SUBLANG_GEORGIAN_GEORGIA +# define SUBLANG_GEORGIAN_GEORGIA 0x01 +# endif +# ifndef SUBLANG_GERMAN_LUXEMBOURG +# define SUBLANG_GERMAN_LUXEMBOURG 0x04 +# endif +# ifndef SUBLANG_GERMAN_LIECHTENSTEIN +# define SUBLANG_GERMAN_LIECHTENSTEIN 0x05 +# endif +# ifndef SUBLANG_GREEK_GREECE +# define SUBLANG_GREEK_GREECE 0x01 +# endif +# ifndef SUBLANG_GREENLANDIC_GREENLAND +# define SUBLANG_GREENLANDIC_GREENLAND 0x01 +# endif +# ifndef SUBLANG_GUJARATI_INDIA +# define SUBLANG_GUJARATI_INDIA 0x01 +# endif +# ifndef SUBLANG_HAUSA_NIGERIA_LATIN +# define SUBLANG_HAUSA_NIGERIA_LATIN 0x01 +# endif +# ifndef SUBLANG_HEBREW_ISRAEL +# define SUBLANG_HEBREW_ISRAEL 0x01 +# endif +# ifndef SUBLANG_HINDI_INDIA +# define SUBLANG_HINDI_INDIA 0x01 +# endif +# ifndef SUBLANG_HUNGARIAN_HUNGARY +# define SUBLANG_HUNGARIAN_HUNGARY 0x01 +# endif +# ifndef SUBLANG_ICELANDIC_ICELAND +# define SUBLANG_ICELANDIC_ICELAND 0x01 +# endif +# ifndef SUBLANG_IGBO_NIGERIA +# define SUBLANG_IGBO_NIGERIA 0x01 +# endif +# ifndef SUBLANG_INDONESIAN_INDONESIA +# define SUBLANG_INDONESIAN_INDONESIA 0x01 +# endif +# ifndef SUBLANG_INUKTITUT_CANADA +# define SUBLANG_INUKTITUT_CANADA 0x01 +# endif +# undef SUBLANG_INUKTITUT_CANADA_LATIN +# define SUBLANG_INUKTITUT_CANADA_LATIN 0x02 +# undef SUBLANG_IRISH_IRELAND +# define SUBLANG_IRISH_IRELAND 0x02 +# ifndef SUBLANG_JAPANESE_JAPAN +# define SUBLANG_JAPANESE_JAPAN 0x01 +# endif +# ifndef SUBLANG_KANNADA_INDIA +# define SUBLANG_KANNADA_INDIA 0x01 +# endif +# ifndef SUBLANG_KASHMIRI_INDIA +# define SUBLANG_KASHMIRI_INDIA 0x02 +# endif +# ifndef SUBLANG_KAZAK_KAZAKHSTAN +# define SUBLANG_KAZAK_KAZAKHSTAN 0x01 +# endif +# ifndef SUBLANG_KICHE_GUATEMALA +# define SUBLANG_KICHE_GUATEMALA 0x01 +# endif +# ifndef SUBLANG_KINYARWANDA_RWANDA +# define SUBLANG_KINYARWANDA_RWANDA 0x01 +# endif +# ifndef SUBLANG_KONKANI_INDIA +# define SUBLANG_KONKANI_INDIA 0x01 +# endif +# ifndef SUBLANG_KYRGYZ_KYRGYZSTAN +# define SUBLANG_KYRGYZ_KYRGYZSTAN 0x01 +# endif +# ifndef SUBLANG_LAO_LAOS +# define SUBLANG_LAO_LAOS 0x01 +# endif +# ifndef SUBLANG_LATVIAN_LATVIA +# define SUBLANG_LATVIAN_LATVIA 0x01 +# endif +# ifndef SUBLANG_LITHUANIAN_LITHUANIA +# define SUBLANG_LITHUANIAN_LITHUANIA 0x01 +# endif +# undef SUBLANG_LOWER_SORBIAN_GERMANY +# define SUBLANG_LOWER_SORBIAN_GERMANY 0x02 +# ifndef SUBLANG_LUXEMBOURGISH_LUXEMBOURG +# define SUBLANG_LUXEMBOURGISH_LUXEMBOURG 0x01 +# endif +# ifndef SUBLANG_MACEDONIAN_MACEDONIA +# define SUBLANG_MACEDONIAN_MACEDONIA 0x01 +# endif +# ifndef SUBLANG_MALAY_MALAYSIA +# define SUBLANG_MALAY_MALAYSIA 0x01 +# endif +# ifndef SUBLANG_MALAY_BRUNEI_DARUSSALAM +# define SUBLANG_MALAY_BRUNEI_DARUSSALAM 0x02 +# endif +# ifndef SUBLANG_MALAYALAM_INDIA +# define SUBLANG_MALAYALAM_INDIA 0x01 +# endif +# ifndef SUBLANG_MALTESE_MALTA +# define SUBLANG_MALTESE_MALTA 0x01 +# endif +# ifndef SUBLANG_MAORI_NEW_ZEALAND +# define SUBLANG_MAORI_NEW_ZEALAND 0x01 +# endif +# ifndef SUBLANG_MAPUDUNGUN_CHILE +# define SUBLANG_MAPUDUNGUN_CHILE 0x01 +# endif +# ifndef SUBLANG_MARATHI_INDIA +# define SUBLANG_MARATHI_INDIA 0x01 +# endif +# ifndef SUBLANG_MOHAWK_CANADA +# define SUBLANG_MOHAWK_CANADA 0x01 +# endif +# ifndef SUBLANG_MONGOLIAN_CYRILLIC_MONGOLIA +# define SUBLANG_MONGOLIAN_CYRILLIC_MONGOLIA 0x01 +# endif +# ifndef SUBLANG_MONGOLIAN_PRC +# define SUBLANG_MONGOLIAN_PRC 0x02 +# endif +# ifndef SUBLANG_NEPALI_NEPAL +# define SUBLANG_NEPALI_NEPAL 0x01 +# endif +# ifndef SUBLANG_NEPALI_INDIA +# define SUBLANG_NEPALI_INDIA 0x02 +# endif +# ifndef SUBLANG_OCCITAN_FRANCE +# define SUBLANG_OCCITAN_FRANCE 0x01 +# endif +# ifndef SUBLANG_ORIYA_INDIA +# define SUBLANG_ORIYA_INDIA 0x01 +# endif +# ifndef SUBLANG_PASHTO_AFGHANISTAN +# define SUBLANG_PASHTO_AFGHANISTAN 0x01 +# endif +# ifndef SUBLANG_POLISH_POLAND +# define SUBLANG_POLISH_POLAND 0x01 +# endif +# ifndef SUBLANG_PUNJABI_INDIA +# define SUBLANG_PUNJABI_INDIA 0x01 +# endif +# ifndef SUBLANG_PUNJABI_PAKISTAN +# define SUBLANG_PUNJABI_PAKISTAN 0x02 +# endif +# ifndef SUBLANG_QUECHUA_BOLIVIA +# define SUBLANG_QUECHUA_BOLIVIA 0x01 +# endif +# ifndef SUBLANG_QUECHUA_ECUADOR +# define SUBLANG_QUECHUA_ECUADOR 0x02 +# endif +# ifndef SUBLANG_QUECHUA_PERU +# define SUBLANG_QUECHUA_PERU 0x03 +# endif +# ifndef SUBLANG_ROMANIAN_ROMANIA +# define SUBLANG_ROMANIAN_ROMANIA 0x01 +# endif +# ifndef SUBLANG_ROMANIAN_MOLDOVA +# define SUBLANG_ROMANIAN_MOLDOVA 0x02 +# endif +# ifndef SUBLANG_ROMANSH_SWITZERLAND +# define SUBLANG_ROMANSH_SWITZERLAND 0x01 +# endif +# ifndef SUBLANG_RUSSIAN_RUSSIA +# define SUBLANG_RUSSIAN_RUSSIA 0x01 +# endif +# ifndef SUBLANG_RUSSIAN_MOLDAVIA +# define SUBLANG_RUSSIAN_MOLDAVIA 0x02 +# endif +# ifndef SUBLANG_SAMI_NORTHERN_NORWAY +# define SUBLANG_SAMI_NORTHERN_NORWAY 0x01 +# endif +# ifndef SUBLANG_SAMI_NORTHERN_SWEDEN +# define SUBLANG_SAMI_NORTHERN_SWEDEN 0x02 +# endif +# ifndef SUBLANG_SAMI_NORTHERN_FINLAND +# define SUBLANG_SAMI_NORTHERN_FINLAND 0x03 +# endif +# ifndef SUBLANG_SAMI_LULE_NORWAY +# define SUBLANG_SAMI_LULE_NORWAY 0x04 +# endif +# ifndef SUBLANG_SAMI_LULE_SWEDEN +# define SUBLANG_SAMI_LULE_SWEDEN 0x05 +# endif +# ifndef SUBLANG_SAMI_SOUTHERN_NORWAY +# define SUBLANG_SAMI_SOUTHERN_NORWAY 0x06 +# endif +# ifndef SUBLANG_SAMI_SOUTHERN_SWEDEN +# define SUBLANG_SAMI_SOUTHERN_SWEDEN 0x07 +# endif +# undef SUBLANG_SAMI_SKOLT_FINLAND +# define SUBLANG_SAMI_SKOLT_FINLAND 0x08 +# undef SUBLANG_SAMI_INARI_FINLAND +# define SUBLANG_SAMI_INARI_FINLAND 0x09 +# ifndef SUBLANG_SANSKRIT_INDIA +# define SUBLANG_SANSKRIT_INDIA 0x01 +# endif +# ifndef SUBLANG_SERBIAN_LATIN +# define SUBLANG_SERBIAN_LATIN 0x02 +# endif +# ifndef SUBLANG_SERBIAN_CYRILLIC +# define SUBLANG_SERBIAN_CYRILLIC 0x03 +# endif +# ifndef SUBLANG_SINDHI_INDIA +# define SUBLANG_SINDHI_INDIA 0x01 +# endif +# undef SUBLANG_SINDHI_PAKISTAN +# define SUBLANG_SINDHI_PAKISTAN 0x02 +# ifndef SUBLANG_SINDHI_AFGHANISTAN +# define SUBLANG_SINDHI_AFGHANISTAN 0x02 +# endif +# ifndef SUBLANG_SINHALESE_SRI_LANKA +# define SUBLANG_SINHALESE_SRI_LANKA 0x01 +# endif +# ifndef SUBLANG_SLOVAK_SLOVAKIA +# define SUBLANG_SLOVAK_SLOVAKIA 0x01 +# endif +# ifndef SUBLANG_SLOVENIAN_SLOVENIA +# define SUBLANG_SLOVENIAN_SLOVENIA 0x01 +# endif +# ifndef SUBLANG_SOTHO_SOUTH_AFRICA +# define SUBLANG_SOTHO_SOUTH_AFRICA 0x01 +# endif +# ifndef SUBLANG_SPANISH_GUATEMALA +# define SUBLANG_SPANISH_GUATEMALA 0x04 +# endif +# ifndef SUBLANG_SPANISH_COSTA_RICA +# define SUBLANG_SPANISH_COSTA_RICA 0x05 +# endif +# ifndef SUBLANG_SPANISH_PANAMA +# define SUBLANG_SPANISH_PANAMA 0x06 +# endif +# ifndef SUBLANG_SPANISH_DOMINICAN_REPUBLIC +# define SUBLANG_SPANISH_DOMINICAN_REPUBLIC 0x07 +# endif +# ifndef SUBLANG_SPANISH_VENEZUELA +# define SUBLANG_SPANISH_VENEZUELA 0x08 +# endif +# ifndef SUBLANG_SPANISH_COLOMBIA +# define SUBLANG_SPANISH_COLOMBIA 0x09 +# endif +# ifndef SUBLANG_SPANISH_PERU +# define SUBLANG_SPANISH_PERU 0x0a +# endif +# ifndef SUBLANG_SPANISH_ARGENTINA +# define SUBLANG_SPANISH_ARGENTINA 0x0b +# endif +# ifndef SUBLANG_SPANISH_ECUADOR +# define SUBLANG_SPANISH_ECUADOR 0x0c +# endif +# ifndef SUBLANG_SPANISH_CHILE +# define SUBLANG_SPANISH_CHILE 0x0d +# endif +# ifndef SUBLANG_SPANISH_URUGUAY +# define SUBLANG_SPANISH_URUGUAY 0x0e +# endif +# ifndef SUBLANG_SPANISH_PARAGUAY +# define SUBLANG_SPANISH_PARAGUAY 0x0f +# endif +# ifndef SUBLANG_SPANISH_BOLIVIA +# define SUBLANG_SPANISH_BOLIVIA 0x10 +# endif +# ifndef SUBLANG_SPANISH_EL_SALVADOR +# define SUBLANG_SPANISH_EL_SALVADOR 0x11 +# endif +# ifndef SUBLANG_SPANISH_HONDURAS +# define SUBLANG_SPANISH_HONDURAS 0x12 +# endif +# ifndef SUBLANG_SPANISH_NICARAGUA +# define SUBLANG_SPANISH_NICARAGUA 0x13 +# endif +# ifndef SUBLANG_SPANISH_PUERTO_RICO +# define SUBLANG_SPANISH_PUERTO_RICO 0x14 +# endif +# ifndef SUBLANG_SPANISH_US +# define SUBLANG_SPANISH_US 0x15 +# endif +# ifndef SUBLANG_SWAHILI_KENYA +# define SUBLANG_SWAHILI_KENYA 0x01 +# endif +# ifndef SUBLANG_SWEDISH_SWEDEN +# define SUBLANG_SWEDISH_SWEDEN 0x01 +# endif +# ifndef SUBLANG_SWEDISH_FINLAND +# define SUBLANG_SWEDISH_FINLAND 0x02 +# endif +# ifndef SUBLANG_SYRIAC_SYRIA +# define SUBLANG_SYRIAC_SYRIA 0x01 +# endif +# ifndef SUBLANG_TAGALOG_PHILIPPINES +# define SUBLANG_TAGALOG_PHILIPPINES 0x01 +# endif +# ifndef SUBLANG_TAJIK_TAJIKISTAN +# define SUBLANG_TAJIK_TAJIKISTAN 0x01 +# endif +# ifndef SUBLANG_TAMAZIGHT_ARABIC +# define SUBLANG_TAMAZIGHT_ARABIC 0x01 +# endif +# ifndef SUBLANG_TAMAZIGHT_ALGERIA_LATIN +# define SUBLANG_TAMAZIGHT_ALGERIA_LATIN 0x02 +# endif +# ifndef SUBLANG_TAMIL_INDIA +# define SUBLANG_TAMIL_INDIA 0x01 +# endif +# ifndef SUBLANG_TATAR_RUSSIA +# define SUBLANG_TATAR_RUSSIA 0x01 +# endif +# ifndef SUBLANG_TELUGU_INDIA +# define SUBLANG_TELUGU_INDIA 0x01 +# endif +# ifndef SUBLANG_THAI_THAILAND +# define SUBLANG_THAI_THAILAND 0x01 +# endif +# ifndef SUBLANG_TIBETAN_PRC +# define SUBLANG_TIBETAN_PRC 0x01 +# endif +# undef SUBLANG_TIBETAN_BHUTAN +# define SUBLANG_TIBETAN_BHUTAN 0x02 +# ifndef SUBLANG_TIGRINYA_ETHIOPIA +# define SUBLANG_TIGRINYA_ETHIOPIA 0x01 +# endif +# ifndef SUBLANG_TIGRINYA_ERITREA +# define SUBLANG_TIGRINYA_ERITREA 0x02 +# endif +# ifndef SUBLANG_TSWANA_SOUTH_AFRICA +# define SUBLANG_TSWANA_SOUTH_AFRICA 0x01 +# endif +# ifndef SUBLANG_TURKISH_TURKEY +# define SUBLANG_TURKISH_TURKEY 0x01 +# endif +# ifndef SUBLANG_TURKMEN_TURKMENISTAN +# define SUBLANG_TURKMEN_TURKMENISTAN 0x01 +# endif +# ifndef SUBLANG_UIGHUR_PRC +# define SUBLANG_UIGHUR_PRC 0x01 +# endif +# ifndef SUBLANG_UKRAINIAN_UKRAINE +# define SUBLANG_UKRAINIAN_UKRAINE 0x01 +# endif +# ifndef SUBLANG_UPPER_SORBIAN_GERMANY +# define SUBLANG_UPPER_SORBIAN_GERMANY 0x01 +# endif +# ifndef SUBLANG_URDU_PAKISTAN +# define SUBLANG_URDU_PAKISTAN 0x01 +# endif +# ifndef SUBLANG_URDU_INDIA +# define SUBLANG_URDU_INDIA 0x02 +# endif +# ifndef SUBLANG_UZBEK_LATIN +# define SUBLANG_UZBEK_LATIN 0x01 +# endif +# ifndef SUBLANG_UZBEK_CYRILLIC +# define SUBLANG_UZBEK_CYRILLIC 0x02 +# endif +# ifndef SUBLANG_VIETNAMESE_VIETNAM +# define SUBLANG_VIETNAMESE_VIETNAM 0x01 +# endif +# ifndef SUBLANG_WELSH_UNITED_KINGDOM +# define SUBLANG_WELSH_UNITED_KINGDOM 0x01 +# endif +# ifndef SUBLANG_WOLOF_SENEGAL +# define SUBLANG_WOLOF_SENEGAL 0x01 +# endif +# ifndef SUBLANG_XHOSA_SOUTH_AFRICA +# define SUBLANG_XHOSA_SOUTH_AFRICA 0x01 +# endif +# ifndef SUBLANG_YAKUT_RUSSIA +# define SUBLANG_YAKUT_RUSSIA 0x01 +# endif +# ifndef SUBLANG_YI_PRC +# define SUBLANG_YI_PRC 0x01 +# endif +# ifndef SUBLANG_YORUBA_NIGERIA +# define SUBLANG_YORUBA_NIGERIA 0x01 +# endif +# ifndef SUBLANG_ZULU_SOUTH_AFRICA +# define SUBLANG_ZULU_SOUTH_AFRICA 0x01 +# endif +/* GetLocaleInfoA operations. */ +# ifndef LOCALE_SNAME +# define LOCALE_SNAME 0x5c +# endif +# ifndef LOCALE_NAME_MAX_LENGTH +# define LOCALE_NAME_MAX_LENGTH 85 +# endif +#endif + + +#if HAVE_CFLOCALECOPYCURRENT || HAVE_CFPREFERENCESCOPYAPPVALUE +/* Mac OS X 10.2 or newer */ + +/* Canonicalize a Mac OS X locale name to a Unix locale name. + NAME is a sufficiently large buffer. + On input, it contains the Mac OS X locale name. + On output, it contains the Unix locale name. */ +# if !defined IN_LIBINTL +static +# endif +void +gl_locale_name_canonicalize (char *name) +{ + /* This conversion is based on a posting by + Deborah GoldSmith on 2005-03-08, + http://lists.apple.com/archives/carbon-dev/2005/Mar/msg00293.html */ + + /* Convert legacy (NeXTstep inherited) English names to Unix (ISO 639 and + ISO 3166) names. Prior to Mac OS X 10.3, there is no API for doing this. + Therefore we do it ourselves, using a table based on the results of the + Mac OS X 10.3.8 function + CFLocaleCreateCanonicalLocaleIdentifierFromString(). */ + typedef struct { const char legacy[21+1]; const char unixy[5+1]; } + legacy_entry; + static const legacy_entry legacy_table[] = { + { "Afrikaans", "af" }, + { "Albanian", "sq" }, + { "Amharic", "am" }, + { "Arabic", "ar" }, + { "Armenian", "hy" }, + { "Assamese", "as" }, + { "Aymara", "ay" }, + { "Azerbaijani", "az" }, + { "Basque", "eu" }, + { "Belarusian", "be" }, + { "Belorussian", "be" }, + { "Bengali", "bn" }, + { "Brazilian Portugese", "pt_BR" }, + { "Brazilian Portuguese", "pt_BR" }, + { "Breton", "br" }, + { "Bulgarian", "bg" }, + { "Burmese", "my" }, + { "Byelorussian", "be" }, + { "Catalan", "ca" }, + { "Chewa", "ny" }, + { "Chichewa", "ny" }, + { "Chinese", "zh" }, + { "Chinese, Simplified", "zh_CN" }, + { "Chinese, Traditional", "zh_TW" }, + { "Chinese, Tradtional", "zh_TW" }, + { "Croatian", "hr" }, + { "Czech", "cs" }, + { "Danish", "da" }, + { "Dutch", "nl" }, + { "Dzongkha", "dz" }, + { "English", "en" }, + { "Esperanto", "eo" }, + { "Estonian", "et" }, + { "Faroese", "fo" }, + { "Farsi", "fa" }, + { "Finnish", "fi" }, + { "Flemish", "nl_BE" }, + { "French", "fr" }, + { "Galician", "gl" }, + { "Gallegan", "gl" }, + { "Georgian", "ka" }, + { "German", "de" }, + { "Greek", "el" }, + { "Greenlandic", "kl" }, + { "Guarani", "gn" }, + { "Gujarati", "gu" }, + { "Hawaiian", "haw" }, /* Yes, "haw", not "cpe". */ + { "Hebrew", "he" }, + { "Hindi", "hi" }, + { "Hungarian", "hu" }, + { "Icelandic", "is" }, + { "Indonesian", "id" }, + { "Inuktitut", "iu" }, + { "Irish", "ga" }, + { "Italian", "it" }, + { "Japanese", "ja" }, + { "Javanese", "jv" }, + { "Kalaallisut", "kl" }, + { "Kannada", "kn" }, + { "Kashmiri", "ks" }, + { "Kazakh", "kk" }, + { "Khmer", "km" }, + { "Kinyarwanda", "rw" }, + { "Kirghiz", "ky" }, + { "Korean", "ko" }, + { "Kurdish", "ku" }, + { "Latin", "la" }, + { "Latvian", "lv" }, + { "Lithuanian", "lt" }, + { "Macedonian", "mk" }, + { "Malagasy", "mg" }, + { "Malay", "ms" }, + { "Malayalam", "ml" }, + { "Maltese", "mt" }, + { "Manx", "gv" }, + { "Marathi", "mr" }, + { "Moldavian", "mo" }, + { "Mongolian", "mn" }, + { "Nepali", "ne" }, + { "Norwegian", "nb" }, /* Yes, "nb", not the obsolete "no". */ + { "Nyanja", "ny" }, + { "Nynorsk", "nn" }, + { "Oriya", "or" }, + { "Oromo", "om" }, + { "Panjabi", "pa" }, + { "Pashto", "ps" }, + { "Persian", "fa" }, + { "Polish", "pl" }, + { "Portuguese", "pt" }, + { "Portuguese, Brazilian", "pt_BR" }, + { "Punjabi", "pa" }, + { "Pushto", "ps" }, + { "Quechua", "qu" }, + { "Romanian", "ro" }, + { "Ruanda", "rw" }, + { "Rundi", "rn" }, + { "Russian", "ru" }, + { "Sami", "se_NO" }, /* Not just "se". */ + { "Sanskrit", "sa" }, + { "Scottish", "gd" }, + { "Serbian", "sr" }, + { "Simplified Chinese", "zh_CN" }, + { "Sindhi", "sd" }, + { "Sinhalese", "si" }, + { "Slovak", "sk" }, + { "Slovenian", "sl" }, + { "Somali", "so" }, + { "Spanish", "es" }, + { "Sundanese", "su" }, + { "Swahili", "sw" }, + { "Swedish", "sv" }, + { "Tagalog", "tl" }, + { "Tajik", "tg" }, + { "Tajiki", "tg" }, + { "Tamil", "ta" }, + { "Tatar", "tt" }, + { "Telugu", "te" }, + { "Thai", "th" }, + { "Tibetan", "bo" }, + { "Tigrinya", "ti" }, + { "Tongan", "to" }, + { "Traditional Chinese", "zh_TW" }, + { "Turkish", "tr" }, + { "Turkmen", "tk" }, + { "Uighur", "ug" }, + { "Ukrainian", "uk" }, + { "Urdu", "ur" }, + { "Uzbek", "uz" }, + { "Vietnamese", "vi" }, + { "Welsh", "cy" }, + { "Yiddish", "yi" } + }; + + /* Convert new-style locale names with language tags (ISO 639 and ISO 15924) + to Unix (ISO 639 and ISO 3166) names. */ + typedef struct { const char langtag[7+1]; const char unixy[12+1]; } + langtag_entry; + static const langtag_entry langtag_table[] = { + /* Mac OS X has "az-Arab", "az-Cyrl", "az-Latn". + The default script for az on Unix is Latin. */ + { "az-Latn", "az" }, + /* Mac OS X has "ga-dots". Does not yet exist on Unix. */ + { "ga-dots", "ga" }, + /* Mac OS X has "kk-Cyrl". Does not yet exist on Unix. */ + /* Mac OS X has "mn-Cyrl", "mn-Mong". + The default script for mn on Unix is Cyrillic. */ + { "mn-Cyrl", "mn" }, + /* Mac OS X has "ms-Arab", "ms-Latn". + The default script for ms on Unix is Latin. */ + { "ms-Latn", "ms" }, + /* Mac OS X has "tg-Cyrl". + The default script for tg on Unix is Cyrillic. */ + { "tg-Cyrl", "tg" }, + /* Mac OS X has "tk-Cyrl". Does not yet exist on Unix. */ + /* Mac OS X has "tt-Cyrl". + The default script for tt on Unix is Cyrillic. */ + { "tt-Cyrl", "tt" }, + /* Mac OS X has "zh-Hans", "zh-Hant". + Country codes are used to distinguish these on Unix. */ + { "zh-Hans", "zh_CN" }, + { "zh-Hant", "zh_TW" } + }; + + /* Convert script names (ISO 15924) to Unix conventions. + See http://www.unicode.org/iso15924/iso15924-codes.html */ + typedef struct { const char script[4+1]; const char unixy[9+1]; } + script_entry; + static const script_entry script_table[] = { + { "Arab", "arabic" }, + { "Cyrl", "cyrillic" }, + { "Mong", "mongolian" } + }; + + /* Step 1: Convert using legacy_table. */ + if (name[0] >= 'A' && name[0] <= 'Z') + { + unsigned int i1, i2; + i1 = 0; + i2 = sizeof (legacy_table) / sizeof (legacy_entry); + while (i2 - i1 > 1) + { + /* At this point we know that if name occurs in legacy_table, + its index must be >= i1 and < i2. */ + unsigned int i = (i1 + i2) >> 1; + const legacy_entry *p = &legacy_table[i]; + if (strcmp (name, p->legacy) < 0) + i2 = i; + else + i1 = i; + } + if (strcmp (name, legacy_table[i1].legacy) == 0) + { + strcpy (name, legacy_table[i1].unixy); + return; + } + } + + /* Step 2: Convert using langtag_table and script_table. */ + if (strlen (name) == 7 && name[2] == '-') + { + unsigned int i1, i2; + i1 = 0; + i2 = sizeof (langtag_table) / sizeof (langtag_entry); + while (i2 - i1 > 1) + { + /* At this point we know that if name occurs in langtag_table, + its index must be >= i1 and < i2. */ + unsigned int i = (i1 + i2) >> 1; + const langtag_entry *p = &langtag_table[i]; + if (strcmp (name, p->langtag) < 0) + i2 = i; + else + i1 = i; + } + if (strcmp (name, langtag_table[i1].langtag) == 0) + { + strcpy (name, langtag_table[i1].unixy); + return; + } + + i1 = 0; + i2 = sizeof (script_table) / sizeof (script_entry); + while (i2 - i1 > 1) + { + /* At this point we know that if (name + 3) occurs in script_table, + its index must be >= i1 and < i2. */ + unsigned int i = (i1 + i2) >> 1; + const script_entry *p = &script_table[i]; + if (strcmp (name + 3, p->script) < 0) + i2 = i; + else + i1 = i; + } + if (strcmp (name + 3, script_table[i1].script) == 0) + { + name[2] = '@'; + strcpy (name + 3, script_table[i1].unixy); + return; + } + } + + /* Step 3: Convert new-style dash to Unix underscore. */ + { + char *p; + for (p = name; *p != '\0'; p++) + if (*p == '-') + *p = '_'; + } +} + +#endif + + +#if defined WINDOWS_NATIVE || defined __CYGWIN__ /* Native Windows or Cygwin */ + +/* Canonicalize a Windows native locale name to a Unix locale name. + NAME is a sufficiently large buffer. + On input, it contains the Windows locale name. + On output, it contains the Unix locale name. */ +# if !defined IN_LIBINTL +static +# endif +void +gl_locale_name_canonicalize (char *name) +{ + /* FIXME: This is probably incomplete: it does not handle "zh-Hans" and + "zh-Hant". */ + char *p; + + for (p = name; *p != '\0'; p++) + if (*p == '-') + { + *p = '_'; + p++; + for (; *p != '\0'; p++) + { + if (*p >= 'a' && *p <= 'z') + *p += 'A' - 'a'; + if (*p == '-') + { + *p = '\0'; + return; + } + } + return; + } +} + +# if !defined IN_LIBINTL +static +# endif +const char * +gl_locale_name_from_win32_LANGID (LANGID langid) +{ + /* Activate the new code only when the GETTEXT_MUI environment variable is + set, for the time being, since the new code is not well tested. */ + if (getenv ("GETTEXT_MUI") != NULL) + { + static char namebuf[256]; + + /* Query the system's notion of locale name. + On Windows95/98/ME, GetLocaleInfoA returns some incorrect results. + But we don't need to support systems that are so old. */ + if (GetLocaleInfoA (MAKELCID (langid, SORT_DEFAULT), LOCALE_SNAME, + namebuf, sizeof (namebuf) - 1)) + { + /* Convert it to a Unix locale name. */ + gl_locale_name_canonicalize (namebuf); + return namebuf; + } + } + /* Internet Explorer has an LCID to RFC3066 name mapping stored in + HKEY_CLASSES_ROOT\Mime\Database\Rfc1766. But we better don't use that + since IE's i18n subsystem is known to be inconsistent with the native + Windows base (e.g. they have different character conversion facilities + that produce different results). */ + /* Use our own table. */ + { + int primary, sub; + + /* Split into language and territory part. */ + primary = PRIMARYLANGID (langid); + sub = SUBLANGID (langid); + + /* Dispatch on language. + See also http://www.unicode.org/unicode/onlinedat/languages.html . + For details about languages, see http://www.ethnologue.com/ . */ + switch (primary) + { + case LANG_AFRIKAANS: + switch (sub) + { + case SUBLANG_AFRIKAANS_SOUTH_AFRICA: return "af_ZA"; + } + return "af"; + case LANG_ALBANIAN: + switch (sub) + { + case SUBLANG_ALBANIAN_ALBANIA: return "sq_AL"; + } + return "sq"; + case LANG_ALSATIAN: + switch (sub) + { + case SUBLANG_ALSATIAN_FRANCE: return "gsw_FR"; + } + return "gsw"; + case LANG_AMHARIC: + switch (sub) + { + case SUBLANG_AMHARIC_ETHIOPIA: return "am_ET"; + } + return "am"; + case LANG_ARABIC: + switch (sub) + { + case SUBLANG_ARABIC_SAUDI_ARABIA: return "ar_SA"; + case SUBLANG_ARABIC_IRAQ: return "ar_IQ"; + case SUBLANG_ARABIC_EGYPT: return "ar_EG"; + case SUBLANG_ARABIC_LIBYA: return "ar_LY"; + case SUBLANG_ARABIC_ALGERIA: return "ar_DZ"; + case SUBLANG_ARABIC_MOROCCO: return "ar_MA"; + case SUBLANG_ARABIC_TUNISIA: return "ar_TN"; + case SUBLANG_ARABIC_OMAN: return "ar_OM"; + case SUBLANG_ARABIC_YEMEN: return "ar_YE"; + case SUBLANG_ARABIC_SYRIA: return "ar_SY"; + case SUBLANG_ARABIC_JORDAN: return "ar_JO"; + case SUBLANG_ARABIC_LEBANON: return "ar_LB"; + case SUBLANG_ARABIC_KUWAIT: return "ar_KW"; + case SUBLANG_ARABIC_UAE: return "ar_AE"; + case SUBLANG_ARABIC_BAHRAIN: return "ar_BH"; + case SUBLANG_ARABIC_QATAR: return "ar_QA"; + } + return "ar"; + case LANG_ARMENIAN: + switch (sub) + { + case SUBLANG_ARMENIAN_ARMENIA: return "hy_AM"; + } + return "hy"; + case LANG_ASSAMESE: + switch (sub) + { + case SUBLANG_ASSAMESE_INDIA: return "as_IN"; + } + return "as"; + case LANG_AZERI: + switch (sub) + { + /* FIXME: Adjust this when Azerbaijani locales appear on Unix. */ + case 0x1e: return "az@latin"; + case SUBLANG_AZERI_LATIN: return "az_AZ@latin"; + case 0x1d: return "az@cyrillic"; + case SUBLANG_AZERI_CYRILLIC: return "az_AZ@cyrillic"; + } + return "az"; + case LANG_BASHKIR: + switch (sub) + { + case SUBLANG_BASHKIR_RUSSIA: return "ba_RU"; + } + return "ba"; + case LANG_BASQUE: + switch (sub) + { + case SUBLANG_BASQUE_BASQUE: return "eu_ES"; + } + return "eu"; /* Ambiguous: could be "eu_ES" or "eu_FR". */ + case LANG_BELARUSIAN: + switch (sub) + { + case SUBLANG_BELARUSIAN_BELARUS: return "be_BY"; + } + return "be"; + case LANG_BENGALI: + switch (sub) + { + case SUBLANG_BENGALI_INDIA: return "bn_IN"; + case SUBLANG_BENGALI_BANGLADESH: return "bn_BD"; + } + return "bn"; + case LANG_BRETON: + switch (sub) + { + case SUBLANG_BRETON_FRANCE: return "br_FR"; + } + return "br"; + case LANG_BULGARIAN: + switch (sub) + { + case SUBLANG_BULGARIAN_BULGARIA: return "bg_BG"; + } + return "bg"; + case LANG_BURMESE: + switch (sub) + { + case SUBLANG_DEFAULT: return "my_MM"; + } + return "my"; + case LANG_CAMBODIAN: + switch (sub) + { + case SUBLANG_CAMBODIAN_CAMBODIA: return "km_KH"; + } + return "km"; + case LANG_CATALAN: + switch (sub) + { + case SUBLANG_CATALAN_SPAIN: return "ca_ES"; + } + return "ca"; + case LANG_CHEROKEE: + switch (sub) + { + case SUBLANG_DEFAULT: return "chr_US"; + } + return "chr"; + case LANG_CHINESE: + switch (sub) + { + case SUBLANG_CHINESE_TRADITIONAL: case 0x1f: return "zh_TW"; + case SUBLANG_CHINESE_SIMPLIFIED: case 0x00: return "zh_CN"; + case SUBLANG_CHINESE_HONGKONG: return "zh_HK"; /* traditional */ + case SUBLANG_CHINESE_SINGAPORE: return "zh_SG"; /* simplified */ + case SUBLANG_CHINESE_MACAU: return "zh_MO"; /* traditional */ + } + return "zh"; + case LANG_CORSICAN: + switch (sub) + { + case SUBLANG_CORSICAN_FRANCE: return "co_FR"; + } + return "co"; + case LANG_CROATIAN: /* LANG_CROATIAN == LANG_SERBIAN == LANG_BOSNIAN + * What used to be called Serbo-Croatian + * should really now be two separate + * languages because of political reasons. + * (Says tml, who knows nothing about Serbian + * or Croatian.) + * (I can feel those flames coming already.) + */ + switch (sub) + { + /* Croatian */ + case 0x00: return "hr"; + case SUBLANG_CROATIAN_CROATIA: return "hr_HR"; + case SUBLANG_CROATIAN_BOSNIA_HERZEGOVINA_LATIN: return "hr_BA"; + /* Serbian */ + case 0x1f: return "sr"; + case 0x1c: return "sr"; /* latin */ + case SUBLANG_SERBIAN_LATIN: return "sr_CS"; /* latin */ + case 0x09: return "sr_RS"; /* latin */ + case 0x0b: return "sr_ME"; /* latin */ + case 0x06: return "sr_BA"; /* latin */ + case 0x1b: return "sr@cyrillic"; + case SUBLANG_SERBIAN_CYRILLIC: return "sr_CS@cyrillic"; + case 0x0a: return "sr_RS@cyrillic"; + case 0x0c: return "sr_ME@cyrillic"; + case 0x07: return "sr_BA@cyrillic"; + /* Bosnian */ + case 0x1e: return "bs"; + case 0x1a: return "bs"; /* latin */ + case SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_LATIN: return "bs_BA"; /* latin */ + case 0x19: return "bs@cyrillic"; + case SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_CYRILLIC: return "bs_BA@cyrillic"; + } + return "hr"; + case LANG_CZECH: + switch (sub) + { + case SUBLANG_CZECH_CZECH_REPUBLIC: return "cs_CZ"; + } + return "cs"; + case LANG_DANISH: + switch (sub) + { + case SUBLANG_DANISH_DENMARK: return "da_DK"; + } + return "da"; + case LANG_DARI: + /* FIXME: Adjust this when such locales appear on Unix. */ + switch (sub) + { + case SUBLANG_DARI_AFGHANISTAN: return "prs_AF"; + } + return "prs"; + case LANG_DIVEHI: + switch (sub) + { + case SUBLANG_DIVEHI_MALDIVES: return "dv_MV"; + } + return "dv"; + case LANG_DUTCH: + switch (sub) + { + case SUBLANG_DUTCH: return "nl_NL"; + case SUBLANG_DUTCH_BELGIAN: /* FLEMISH, VLAAMS */ return "nl_BE"; + case SUBLANG_DUTCH_SURINAM: return "nl_SR"; + } + return "nl"; + case LANG_EDO: + switch (sub) + { + case SUBLANG_DEFAULT: return "bin_NG"; + } + return "bin"; + case LANG_ENGLISH: + switch (sub) + { + /* SUBLANG_ENGLISH_US == SUBLANG_DEFAULT. Heh. I thought + * English was the language spoken in England. + * Oh well. + */ + case SUBLANG_ENGLISH_US: return "en_US"; + case SUBLANG_ENGLISH_UK: return "en_GB"; + case SUBLANG_ENGLISH_AUS: return "en_AU"; + case SUBLANG_ENGLISH_CAN: return "en_CA"; + case SUBLANG_ENGLISH_NZ: return "en_NZ"; + case SUBLANG_ENGLISH_EIRE: return "en_IE"; + case SUBLANG_ENGLISH_SOUTH_AFRICA: return "en_ZA"; + case SUBLANG_ENGLISH_JAMAICA: return "en_JM"; + case SUBLANG_ENGLISH_CARIBBEAN: return "en_GD"; /* Grenada? */ + case SUBLANG_ENGLISH_BELIZE: return "en_BZ"; + case SUBLANG_ENGLISH_TRINIDAD: return "en_TT"; + case SUBLANG_ENGLISH_ZIMBABWE: return "en_ZW"; + case SUBLANG_ENGLISH_PHILIPPINES: return "en_PH"; + case SUBLANG_ENGLISH_INDONESIA: return "en_ID"; + case SUBLANG_ENGLISH_HONGKONG: return "en_HK"; + case SUBLANG_ENGLISH_INDIA: return "en_IN"; + case SUBLANG_ENGLISH_MALAYSIA: return "en_MY"; + case SUBLANG_ENGLISH_SINGAPORE: return "en_SG"; + } + return "en"; + case LANG_ESTONIAN: + switch (sub) + { + case SUBLANG_ESTONIAN_ESTONIA: return "et_EE"; + } + return "et"; + case LANG_FAEROESE: + switch (sub) + { + case SUBLANG_FAEROESE_FAROE_ISLANDS: return "fo_FO"; + } + return "fo"; + case LANG_FARSI: + switch (sub) + { + case SUBLANG_FARSI_IRAN: return "fa_IR"; + } + return "fa"; + case LANG_FINNISH: + switch (sub) + { + case SUBLANG_FINNISH_FINLAND: return "fi_FI"; + } + return "fi"; + case LANG_FRENCH: + switch (sub) + { + case SUBLANG_FRENCH: return "fr_FR"; + case SUBLANG_FRENCH_BELGIAN: /* WALLOON */ return "fr_BE"; + case SUBLANG_FRENCH_CANADIAN: return "fr_CA"; + case SUBLANG_FRENCH_SWISS: return "fr_CH"; + case SUBLANG_FRENCH_LUXEMBOURG: return "fr_LU"; + case SUBLANG_FRENCH_MONACO: return "fr_MC"; + case SUBLANG_FRENCH_WESTINDIES: return "fr"; /* Caribbean? */ + case SUBLANG_FRENCH_REUNION: return "fr_RE"; + case SUBLANG_FRENCH_CONGO: return "fr_CG"; + case SUBLANG_FRENCH_SENEGAL: return "fr_SN"; + case SUBLANG_FRENCH_CAMEROON: return "fr_CM"; + case SUBLANG_FRENCH_COTEDIVOIRE: return "fr_CI"; + case SUBLANG_FRENCH_MALI: return "fr_ML"; + case SUBLANG_FRENCH_MOROCCO: return "fr_MA"; + case SUBLANG_FRENCH_HAITI: return "fr_HT"; + } + return "fr"; + case LANG_FRISIAN: + switch (sub) + { + case SUBLANG_FRISIAN_NETHERLANDS: return "fy_NL"; + } + return "fy"; + case LANG_FULFULDE: + /* Spoken in Nigeria, Guinea, Senegal, Mali, Niger, Cameroon, Benin. */ + switch (sub) + { + case SUBLANG_DEFAULT: return "ff_NG"; + } + return "ff"; + case LANG_GAELIC: + switch (sub) + { + case 0x01: /* SCOTTISH */ + /* old, superseded by LANG_SCOTTISH_GAELIC */ + return "gd_GB"; + case SUBLANG_IRISH_IRELAND: return "ga_IE"; + } + return "ga"; + case LANG_GALICIAN: + switch (sub) + { + case SUBLANG_GALICIAN_SPAIN: return "gl_ES"; + } + return "gl"; + case LANG_GEORGIAN: + switch (sub) + { + case SUBLANG_GEORGIAN_GEORGIA: return "ka_GE"; + } + return "ka"; + case LANG_GERMAN: + switch (sub) + { + case SUBLANG_GERMAN: return "de_DE"; + case SUBLANG_GERMAN_SWISS: return "de_CH"; + case SUBLANG_GERMAN_AUSTRIAN: return "de_AT"; + case SUBLANG_GERMAN_LUXEMBOURG: return "de_LU"; + case SUBLANG_GERMAN_LIECHTENSTEIN: return "de_LI"; + } + return "de"; + case LANG_GREEK: + switch (sub) + { + case SUBLANG_GREEK_GREECE: return "el_GR"; + } + return "el"; + case LANG_GREENLANDIC: + switch (sub) + { + case SUBLANG_GREENLANDIC_GREENLAND: return "kl_GL"; + } + return "kl"; + case LANG_GUARANI: + switch (sub) + { + case SUBLANG_DEFAULT: return "gn_PY"; + } + return "gn"; + case LANG_GUJARATI: + switch (sub) + { + case SUBLANG_GUJARATI_INDIA: return "gu_IN"; + } + return "gu"; + case LANG_HAUSA: + switch (sub) + { + case 0x1f: return "ha"; + case SUBLANG_HAUSA_NIGERIA_LATIN: return "ha_NG"; + } + return "ha"; + case LANG_HAWAIIAN: + /* FIXME: Do they mean Hawaiian ("haw_US", 1000 speakers) + or Hawaii Creole English ("cpe_US", 600000 speakers)? */ + switch (sub) + { + case SUBLANG_DEFAULT: return "cpe_US"; + } + return "cpe"; + case LANG_HEBREW: + switch (sub) + { + case SUBLANG_HEBREW_ISRAEL: return "he_IL"; + } + return "he"; + case LANG_HINDI: + switch (sub) + { + case SUBLANG_HINDI_INDIA: return "hi_IN"; + } + return "hi"; + case LANG_HUNGARIAN: + switch (sub) + { + case SUBLANG_HUNGARIAN_HUNGARY: return "hu_HU"; + } + return "hu"; + case LANG_IBIBIO: + switch (sub) + { + case SUBLANG_DEFAULT: return "nic_NG"; + } + return "nic"; + case LANG_ICELANDIC: + switch (sub) + { + case SUBLANG_ICELANDIC_ICELAND: return "is_IS"; + } + return "is"; + case LANG_IGBO: + switch (sub) + { + case SUBLANG_IGBO_NIGERIA: return "ig_NG"; + } + return "ig"; + case LANG_INDONESIAN: + switch (sub) + { + case SUBLANG_INDONESIAN_INDONESIA: return "id_ID"; + } + return "id"; + case LANG_INUKTITUT: + switch (sub) + { + case 0x1e: return "iu"; /* syllabic */ + case SUBLANG_INUKTITUT_CANADA: return "iu_CA"; /* syllabic */ + case 0x1f: return "iu@latin"; + case SUBLANG_INUKTITUT_CANADA_LATIN: return "iu_CA@latin"; + } + return "iu"; + case LANG_ITALIAN: + switch (sub) + { + case SUBLANG_ITALIAN: return "it_IT"; + case SUBLANG_ITALIAN_SWISS: return "it_CH"; + } + return "it"; + case LANG_JAPANESE: + switch (sub) + { + case SUBLANG_JAPANESE_JAPAN: return "ja_JP"; + } + return "ja"; + case LANG_KANNADA: + switch (sub) + { + case SUBLANG_KANNADA_INDIA: return "kn_IN"; + } + return "kn"; + case LANG_KANURI: + switch (sub) + { + case SUBLANG_DEFAULT: return "kr_NG"; + } + return "kr"; + case LANG_KASHMIRI: + switch (sub) + { + case SUBLANG_DEFAULT: return "ks_PK"; + case SUBLANG_KASHMIRI_INDIA: return "ks_IN"; + } + return "ks"; + case LANG_KAZAK: + switch (sub) + { + case SUBLANG_KAZAK_KAZAKHSTAN: return "kk_KZ"; + } + return "kk"; + case LANG_KICHE: + /* FIXME: Adjust this when such locales appear on Unix. */ + switch (sub) + { + case SUBLANG_KICHE_GUATEMALA: return "qut_GT"; + } + return "qut"; + case LANG_KINYARWANDA: + switch (sub) + { + case SUBLANG_KINYARWANDA_RWANDA: return "rw_RW"; + } + return "rw"; + case LANG_KONKANI: + /* FIXME: Adjust this when such locales appear on Unix. */ + switch (sub) + { + case SUBLANG_KONKANI_INDIA: return "kok_IN"; + } + return "kok"; + case LANG_KOREAN: + switch (sub) + { + case SUBLANG_DEFAULT: return "ko_KR"; + } + return "ko"; + case LANG_KYRGYZ: + switch (sub) + { + case SUBLANG_KYRGYZ_KYRGYZSTAN: return "ky_KG"; + } + return "ky"; + case LANG_LAO: + switch (sub) + { + case SUBLANG_LAO_LAOS: return "lo_LA"; + } + return "lo"; + case LANG_LATIN: + switch (sub) + { + case SUBLANG_DEFAULT: return "la_VA"; + } + return "la"; + case LANG_LATVIAN: + switch (sub) + { + case SUBLANG_LATVIAN_LATVIA: return "lv_LV"; + } + return "lv"; + case LANG_LITHUANIAN: + switch (sub) + { + case SUBLANG_LITHUANIAN_LITHUANIA: return "lt_LT"; + } + return "lt"; + case LANG_LUXEMBOURGISH: + switch (sub) + { + case SUBLANG_LUXEMBOURGISH_LUXEMBOURG: return "lb_LU"; + } + return "lb"; + case LANG_MACEDONIAN: + switch (sub) + { + case SUBLANG_MACEDONIAN_MACEDONIA: return "mk_MK"; + } + return "mk"; + case LANG_MALAY: + switch (sub) + { + case SUBLANG_MALAY_MALAYSIA: return "ms_MY"; + case SUBLANG_MALAY_BRUNEI_DARUSSALAM: return "ms_BN"; + } + return "ms"; + case LANG_MALAYALAM: + switch (sub) + { + case SUBLANG_MALAYALAM_INDIA: return "ml_IN"; + } + return "ml"; + case LANG_MALTESE: + switch (sub) + { + case SUBLANG_MALTESE_MALTA: return "mt_MT"; + } + return "mt"; + case LANG_MANIPURI: + /* FIXME: Adjust this when such locales appear on Unix. */ + switch (sub) + { + case SUBLANG_DEFAULT: return "mni_IN"; + } + return "mni"; + case LANG_MAORI: + switch (sub) + { + case SUBLANG_MAORI_NEW_ZEALAND: return "mi_NZ"; + } + return "mi"; + case LANG_MAPUDUNGUN: + switch (sub) + { + case SUBLANG_MAPUDUNGUN_CHILE: return "arn_CL"; + } + return "arn"; + case LANG_MARATHI: + switch (sub) + { + case SUBLANG_MARATHI_INDIA: return "mr_IN"; + } + return "mr"; + case LANG_MOHAWK: + switch (sub) + { + case SUBLANG_MOHAWK_CANADA: return "moh_CA"; + } + return "moh"; + case LANG_MONGOLIAN: + switch (sub) + { + case SUBLANG_MONGOLIAN_CYRILLIC_MONGOLIA: case 0x1e: return "mn_MN"; + case SUBLANG_MONGOLIAN_PRC: case 0x1f: return "mn_CN"; + } + return "mn"; /* Ambiguous: could be "mn_CN" or "mn_MN". */ + case LANG_NEPALI: + switch (sub) + { + case SUBLANG_NEPALI_NEPAL: return "ne_NP"; + case SUBLANG_NEPALI_INDIA: return "ne_IN"; + } + return "ne"; + case LANG_NORWEGIAN: + switch (sub) + { + case 0x1f: return "nb"; + case SUBLANG_NORWEGIAN_BOKMAL: return "nb_NO"; + case 0x1e: return "nn"; + case SUBLANG_NORWEGIAN_NYNORSK: return "nn_NO"; + } + return "no"; + case LANG_OCCITAN: + switch (sub) + { + case SUBLANG_OCCITAN_FRANCE: return "oc_FR"; + } + return "oc"; + case LANG_ORIYA: + switch (sub) + { + case SUBLANG_ORIYA_INDIA: return "or_IN"; + } + return "or"; + case LANG_OROMO: + switch (sub) + { + case SUBLANG_DEFAULT: return "om_ET"; + } + return "om"; + case LANG_PAPIAMENTU: + switch (sub) + { + case SUBLANG_DEFAULT: return "pap_AN"; + } + return "pap"; + case LANG_PASHTO: + switch (sub) + { + case SUBLANG_PASHTO_AFGHANISTAN: return "ps_AF"; + } + return "ps"; /* Ambiguous: could be "ps_PK" or "ps_AF". */ + case LANG_POLISH: + switch (sub) + { + case SUBLANG_POLISH_POLAND: return "pl_PL"; + } + return "pl"; + case LANG_PORTUGUESE: + switch (sub) + { + /* Hmm. SUBLANG_PORTUGUESE_BRAZILIAN == SUBLANG_DEFAULT. + Same phenomenon as SUBLANG_ENGLISH_US == SUBLANG_DEFAULT. */ + case SUBLANG_PORTUGUESE_BRAZILIAN: return "pt_BR"; + case SUBLANG_PORTUGUESE: return "pt_PT"; + } + return "pt"; + case LANG_PUNJABI: + switch (sub) + { + case SUBLANG_PUNJABI_INDIA: return "pa_IN"; /* Gurmukhi script */ + case SUBLANG_PUNJABI_PAKISTAN: return "pa_PK"; /* Arabic script */ + } + return "pa"; + case LANG_QUECHUA: + /* Note: Microsoft uses the non-ISO language code "quz". */ + switch (sub) + { + case SUBLANG_QUECHUA_BOLIVIA: return "qu_BO"; + case SUBLANG_QUECHUA_ECUADOR: return "qu_EC"; + case SUBLANG_QUECHUA_PERU: return "qu_PE"; + } + return "qu"; + case LANG_ROMANIAN: + switch (sub) + { + case SUBLANG_ROMANIAN_ROMANIA: return "ro_RO"; + case SUBLANG_ROMANIAN_MOLDOVA: return "ro_MD"; + } + return "ro"; + case LANG_ROMANSH: + switch (sub) + { + case SUBLANG_ROMANSH_SWITZERLAND: return "rm_CH"; + } + return "rm"; + case LANG_RUSSIAN: + switch (sub) + { + case SUBLANG_RUSSIAN_RUSSIA: return "ru_RU"; + case SUBLANG_RUSSIAN_MOLDAVIA: return "ru_MD"; + } + return "ru"; /* Ambiguous: could be "ru_RU" or "ru_UA" or "ru_MD". */ + case LANG_SAMI: + switch (sub) + { + /* Northern Sami */ + case 0x00: return "se"; + case SUBLANG_SAMI_NORTHERN_NORWAY: return "se_NO"; + case SUBLANG_SAMI_NORTHERN_SWEDEN: return "se_SE"; + case SUBLANG_SAMI_NORTHERN_FINLAND: return "se_FI"; + /* Lule Sami */ + case 0x1f: return "smj"; + case SUBLANG_SAMI_LULE_NORWAY: return "smj_NO"; + case SUBLANG_SAMI_LULE_SWEDEN: return "smj_SE"; + /* Southern Sami */ + case 0x1e: return "sma"; + case SUBLANG_SAMI_SOUTHERN_NORWAY: return "sma_NO"; + case SUBLANG_SAMI_SOUTHERN_SWEDEN: return "sma_SE"; + /* Skolt Sami */ + case 0x1d: return "sms"; + case SUBLANG_SAMI_SKOLT_FINLAND: return "sms_FI"; + /* Inari Sami */ + case 0x1c: return "smn"; + case SUBLANG_SAMI_INARI_FINLAND: return "smn_FI"; + } + return "se"; /* or "smi"? */ + case LANG_SANSKRIT: + switch (sub) + { + case SUBLANG_SANSKRIT_INDIA: return "sa_IN"; + } + return "sa"; + case LANG_SCOTTISH_GAELIC: + switch (sub) + { + case SUBLANG_DEFAULT: return "gd_GB"; + } + return "gd"; + case LANG_SINDHI: + switch (sub) + { + case SUBLANG_SINDHI_INDIA: return "sd_IN"; + case SUBLANG_SINDHI_PAKISTAN: return "sd_PK"; + /*case SUBLANG_SINDHI_AFGHANISTAN: return "sd_AF";*/ + } + return "sd"; + case LANG_SINHALESE: + switch (sub) + { + case SUBLANG_SINHALESE_SRI_LANKA: return "si_LK"; + } + return "si"; + case LANG_SLOVAK: + switch (sub) + { + case SUBLANG_SLOVAK_SLOVAKIA: return "sk_SK"; + } + return "sk"; + case LANG_SLOVENIAN: + switch (sub) + { + case SUBLANG_SLOVENIAN_SLOVENIA: return "sl_SI"; + } + return "sl"; + case LANG_SOMALI: + switch (sub) + { + case SUBLANG_DEFAULT: return "so_SO"; + } + return "so"; + case LANG_SORBIAN: + /* FIXME: Adjust this when such locales appear on Unix. */ + switch (sub) + { + /* Upper Sorbian */ + case 0x00: return "hsb"; + case SUBLANG_UPPER_SORBIAN_GERMANY: return "hsb_DE"; + /* Lower Sorbian */ + case 0x1f: return "dsb"; + case SUBLANG_LOWER_SORBIAN_GERMANY: return "dsb_DE"; + } + return "wen"; + case LANG_SOTHO: + /* calls + it "Sepedi"; according to + + + it's the same as Northern Sotho. */ + switch (sub) + { + case SUBLANG_SOTHO_SOUTH_AFRICA: return "nso_ZA"; + } + return "nso"; + case LANG_SPANISH: + switch (sub) + { + case SUBLANG_SPANISH: return "es_ES"; + case SUBLANG_SPANISH_MEXICAN: return "es_MX"; + case SUBLANG_SPANISH_MODERN: + return "es_ES@modern"; /* not seen on Unix */ + case SUBLANG_SPANISH_GUATEMALA: return "es_GT"; + case SUBLANG_SPANISH_COSTA_RICA: return "es_CR"; + case SUBLANG_SPANISH_PANAMA: return "es_PA"; + case SUBLANG_SPANISH_DOMINICAN_REPUBLIC: return "es_DO"; + case SUBLANG_SPANISH_VENEZUELA: return "es_VE"; + case SUBLANG_SPANISH_COLOMBIA: return "es_CO"; + case SUBLANG_SPANISH_PERU: return "es_PE"; + case SUBLANG_SPANISH_ARGENTINA: return "es_AR"; + case SUBLANG_SPANISH_ECUADOR: return "es_EC"; + case SUBLANG_SPANISH_CHILE: return "es_CL"; + case SUBLANG_SPANISH_URUGUAY: return "es_UY"; + case SUBLANG_SPANISH_PARAGUAY: return "es_PY"; + case SUBLANG_SPANISH_BOLIVIA: return "es_BO"; + case SUBLANG_SPANISH_EL_SALVADOR: return "es_SV"; + case SUBLANG_SPANISH_HONDURAS: return "es_HN"; + case SUBLANG_SPANISH_NICARAGUA: return "es_NI"; + case SUBLANG_SPANISH_PUERTO_RICO: return "es_PR"; + case SUBLANG_SPANISH_US: return "es_US"; + } + return "es"; + case LANG_SUTU: + switch (sub) + { + case SUBLANG_DEFAULT: return "bnt_TZ"; /* or "st_LS" or "nso_ZA"? */ + } + return "bnt"; + case LANG_SWAHILI: + switch (sub) + { + case SUBLANG_SWAHILI_KENYA: return "sw_KE"; + } + return "sw"; + case LANG_SWEDISH: + switch (sub) + { + case SUBLANG_SWEDISH_SWEDEN: return "sv_SE"; + case SUBLANG_SWEDISH_FINLAND: return "sv_FI"; + } + return "sv"; + case LANG_SYRIAC: + switch (sub) + { + case SUBLANG_SYRIAC_SYRIA: return "syr_SY"; /* An extinct language. */ + } + return "syr"; + case LANG_TAGALOG: + switch (sub) + { + case SUBLANG_TAGALOG_PHILIPPINES: return "tl_PH"; /* or "fil_PH"? */ + } + return "tl"; /* or "fil"? */ + case LANG_TAJIK: + switch (sub) + { + case 0x1f: return "tg"; + case SUBLANG_TAJIK_TAJIKISTAN: return "tg_TJ"; + } + return "tg"; + case LANG_TAMAZIGHT: + /* Note: Microsoft uses the non-ISO language code "tmz". */ + switch (sub) + { + /* FIXME: Adjust this when Tamazight locales appear on Unix. */ + case SUBLANG_TAMAZIGHT_ARABIC: return "ber_MA@arabic"; + case 0x1f: return "ber@latin"; + case SUBLANG_TAMAZIGHT_ALGERIA_LATIN: return "ber_DZ@latin"; + } + return "ber"; + case LANG_TAMIL: + switch (sub) + { + case SUBLANG_TAMIL_INDIA: return "ta_IN"; + } + return "ta"; /* Ambiguous: could be "ta_IN" or "ta_LK" or "ta_SG". */ + case LANG_TATAR: + switch (sub) + { + case SUBLANG_TATAR_RUSSIA: return "tt_RU"; + } + return "tt"; + case LANG_TELUGU: + switch (sub) + { + case SUBLANG_TELUGU_INDIA: return "te_IN"; + } + return "te"; + case LANG_THAI: + switch (sub) + { + case SUBLANG_THAI_THAILAND: return "th_TH"; + } + return "th"; + case LANG_TIBETAN: + switch (sub) + { + case SUBLANG_TIBETAN_PRC: + /* Most Tibetans would not like "bo_CN". But Tibet does not yet + have a country code of its own. */ + return "bo"; + case SUBLANG_TIBETAN_BHUTAN: return "bo_BT"; + } + return "bo"; + case LANG_TIGRINYA: + switch (sub) + { + case SUBLANG_TIGRINYA_ETHIOPIA: return "ti_ET"; + case SUBLANG_TIGRINYA_ERITREA: return "ti_ER"; + } + return "ti"; + case LANG_TSONGA: + switch (sub) + { + case SUBLANG_DEFAULT: return "ts_ZA"; + } + return "ts"; + case LANG_TSWANA: + /* Spoken in South Africa, Botswana. */ + switch (sub) + { + case SUBLANG_TSWANA_SOUTH_AFRICA: return "tn_ZA"; + } + return "tn"; + case LANG_TURKISH: + switch (sub) + { + case SUBLANG_TURKISH_TURKEY: return "tr_TR"; + } + return "tr"; + case LANG_TURKMEN: + switch (sub) + { + case SUBLANG_TURKMEN_TURKMENISTAN: return "tk_TM"; + } + return "tk"; + case LANG_UIGHUR: + switch (sub) + { + case SUBLANG_UIGHUR_PRC: return "ug_CN"; + } + return "ug"; + case LANG_UKRAINIAN: + switch (sub) + { + case SUBLANG_UKRAINIAN_UKRAINE: return "uk_UA"; + } + return "uk"; + case LANG_URDU: + switch (sub) + { + case SUBLANG_URDU_PAKISTAN: return "ur_PK"; + case SUBLANG_URDU_INDIA: return "ur_IN"; + } + return "ur"; + case LANG_UZBEK: + switch (sub) + { + case 0x1f: return "uz"; + case SUBLANG_UZBEK_LATIN: return "uz_UZ"; + case 0x1e: return "uz@cyrillic"; + case SUBLANG_UZBEK_CYRILLIC: return "uz_UZ@cyrillic"; + } + return "uz"; + case LANG_VENDA: + switch (sub) + { + case SUBLANG_DEFAULT: return "ve_ZA"; + } + return "ve"; + case LANG_VIETNAMESE: + switch (sub) + { + case SUBLANG_VIETNAMESE_VIETNAM: return "vi_VN"; + } + return "vi"; + case LANG_WELSH: + switch (sub) + { + case SUBLANG_WELSH_UNITED_KINGDOM: return "cy_GB"; + } + return "cy"; + case LANG_WOLOF: + switch (sub) + { + case SUBLANG_WOLOF_SENEGAL: return "wo_SN"; + } + return "wo"; + case LANG_XHOSA: + switch (sub) + { + case SUBLANG_XHOSA_SOUTH_AFRICA: return "xh_ZA"; + } + return "xh"; + case LANG_YAKUT: + switch (sub) + { + case SUBLANG_YAKUT_RUSSIA: return "sah_RU"; + } + return "sah"; + case LANG_YI: + switch (sub) + { + case SUBLANG_YI_PRC: return "ii_CN"; + } + return "ii"; + case LANG_YIDDISH: + switch (sub) + { + case SUBLANG_DEFAULT: return "yi_IL"; + } + return "yi"; + case LANG_YORUBA: + switch (sub) + { + case SUBLANG_YORUBA_NIGERIA: return "yo_NG"; + } + return "yo"; + case LANG_ZULU: + switch (sub) + { + case SUBLANG_ZULU_SOUTH_AFRICA: return "zu_ZA"; + } + return "zu"; + default: return "C"; + } + } +} + +# if !defined IN_LIBINTL +static +# endif +const char * +gl_locale_name_from_win32_LCID (LCID lcid) +{ + LANGID langid; + + /* Strip off the sorting rules, keep only the language part. */ + langid = LANGIDFROMLCID (lcid); + + return gl_locale_name_from_win32_LANGID (langid); +} + +# ifdef WINDOWS_NATIVE + +/* Two variables to interface between get_lcid and the EnumLocales + callback function below. */ +static LCID found_lcid; +static char lname[LC_MAX * (LOCALE_NAME_MAX_LENGTH + 1) + 1]; + +/* Callback function for EnumLocales. */ +static BOOL CALLBACK +enum_locales_fn (LPTSTR locale_num_str) +{ + char *endp; + char locval[2 * LOCALE_NAME_MAX_LENGTH + 1 + 1]; + LCID try_lcid = strtoul (locale_num_str, &endp, 16); + + if (GetLocaleInfo (try_lcid, LOCALE_SENGLANGUAGE, + locval, LOCALE_NAME_MAX_LENGTH)) + { + strcat (locval, "_"); + if (GetLocaleInfo (try_lcid, LOCALE_SENGCOUNTRY, + locval + strlen (locval), LOCALE_NAME_MAX_LENGTH)) + { + size_t locval_len = strlen (locval); + + if (strncmp (locval, lname, locval_len) == 0 + && (lname[locval_len] == '.' + || lname[locval_len] == '\0')) + { + found_lcid = try_lcid; + return FALSE; + } + } + } + return TRUE; +} + +/* This lock protects the get_lcid against multiple simultaneous calls. */ +gl_lock_define_initialized(static, get_lcid_lock) + +/* Return the Locale ID (LCID) number given the locale's name, a + string, in LOCALE_NAME. This works by enumerating all the locales + supported by the system, until we find one whose name matches + LOCALE_NAME. */ +static LCID +get_lcid (const char *locale_name) +{ + /* A simple cache. */ + static LCID last_lcid; + static char last_locale[1000]; + + /* Lock while looking for an LCID, to protect access to static + variables: last_lcid, last_locale, found_lcid, and lname. */ + gl_lock_lock (get_lcid_lock); + if (last_lcid > 0 && strcmp (locale_name, last_locale) == 0) + { + gl_lock_unlock (get_lcid_lock); + return last_lcid; + } + strncpy (lname, locale_name, sizeof (lname) - 1); + lname[sizeof (lname) - 1] = '\0'; + found_lcid = 0; + EnumSystemLocales (enum_locales_fn, LCID_SUPPORTED); + if (found_lcid > 0) + { + last_lcid = found_lcid; + strcpy (last_locale, locale_name); + } + gl_lock_unlock (get_lcid_lock); + return found_lcid; +} + +# endif +#endif + + +#if HAVE_USELOCALE /* glibc or Mac OS X */ + +/* Simple hash set of strings. We don't want to drag in lots of hash table + code here. */ + +# define SIZE_BITS (sizeof (size_t) * CHAR_BIT) + +/* A hash function for NUL-terminated char* strings using + the method described by Bruno Haible. + See http://www.haible.de/bruno/hashfunc.html. */ +static size_t _GL_ATTRIBUTE_PURE +string_hash (const void *x) +{ + const char *s = (const char *) x; + size_t h = 0; + + for (; *s; s++) + h = *s + ((h << 9) | (h >> (SIZE_BITS - 9))); + + return h; +} + +/* A hash table of fixed size. Multiple threads can access it read-only + simultaneously, but only one thread can insert into it at the same time. */ + +/* A node in a hash bucket collision list. */ +struct hash_node + { + struct hash_node * volatile next; + char contents[100]; /* has variable size */ + }; + +# define HASH_TABLE_SIZE 257 +static struct hash_node * volatile struniq_hash_table[HASH_TABLE_SIZE] + /* = { NULL, ..., NULL } */; + +/* This lock protects the struniq_hash_table against multiple simultaneous + insertions. */ +gl_lock_define_initialized(static, struniq_lock) + +/* Store a copy of the given string in a string pool with indefinite extent. + Return a pointer to this copy. */ +static const char * +struniq (const char *string) +{ + size_t hashcode = string_hash (string); + size_t slot = hashcode % HASH_TABLE_SIZE; + size_t size; + struct hash_node *new_node; + struct hash_node *p; + for (p = struniq_hash_table[slot]; p != NULL; p = p->next) + if (strcmp (p->contents, string) == 0) + return p->contents; + size = strlen (string) + 1; + new_node = + (struct hash_node *) + malloc (offsetof (struct hash_node, contents[0]) + size); + if (new_node == NULL) + /* Out of memory. Return a statically allocated string. */ + return "C"; + memcpy (new_node->contents, string, size); + /* Lock while inserting new_node. */ + gl_lock_lock (struniq_lock); + /* Check whether another thread already added the string while we were + waiting on the lock. */ + for (p = struniq_hash_table[slot]; p != NULL; p = p->next) + if (strcmp (p->contents, string) == 0) + { + free (new_node); + new_node = p; + goto done; + } + /* Really insert new_node into the hash table. Fill new_node entirely first, + because other threads may be iterating over the linked list. */ + new_node->next = struniq_hash_table[slot]; + struniq_hash_table[slot] = new_node; + done: + /* Unlock after new_node is inserted. */ + gl_lock_unlock (struniq_lock); + return new_node->contents; +} + +#endif + + +#if defined IN_LIBINTL || HAVE_USELOCALE + +/* Like gl_locale_name_thread, except that the result is not in storage of + indefinite extent. */ +# if !defined IN_LIBINTL +static +# endif +const char * +gl_locale_name_thread_unsafe (int category, const char *categoryname) +{ +# if HAVE_USELOCALE + { + locale_t thread_locale = uselocale (NULL); + if (thread_locale != LC_GLOBAL_LOCALE) + { +# if __GLIBC__ >= 2 && !defined __UCLIBC__ + /* Work around an incorrect definition of the _NL_LOCALE_NAME macro in + glibc < 2.12. + See . */ + const char *name = + nl_langinfo (_NL_ITEM ((category), _NL_ITEM_INDEX (-1))); + if (name[0] == '\0') + /* Fallback code for glibc < 2.4, which did not implement + nl_langinfo (_NL_LOCALE_NAME (category)). */ + name = thread_locale->__names[category]; + return name; +# elif defined __FreeBSD__ || (defined __APPLE__ && defined __MACH__) + /* FreeBSD, Mac OS X */ + int mask; + + switch (category) + { + case LC_CTYPE: + mask = LC_CTYPE_MASK; + break; + case LC_NUMERIC: + mask = LC_NUMERIC_MASK; + break; + case LC_TIME: + mask = LC_TIME_MASK; + break; + case LC_COLLATE: + mask = LC_COLLATE_MASK; + break; + case LC_MONETARY: + mask = LC_MONETARY_MASK; + break; + case LC_MESSAGES: + mask = LC_MESSAGES_MASK; + break; + default: /* We shouldn't get here. */ + return ""; + } + return querylocale (mask, thread_locale); +# endif + } + } +# endif + return NULL; +} + +#endif + +const char * +gl_locale_name_thread (int category, const char *categoryname) +{ +#if HAVE_USELOCALE + const char *name = gl_locale_name_thread_unsafe (category, categoryname); + if (name != NULL) + return struniq (name); +#elif defined WINDOWS_NATIVE + if (LC_MIN <= category && category <= LC_MAX) + { + char *locname = setlocale (category, NULL); + LCID lcid = 0; + + /* If CATEGORY is LC_ALL, the result might be a semi-colon + separated list of locales. We need only one, so we take the + one corresponding to LC_CTYPE, as the most important for + character translations. */ + if (strchr (locname, ';')) + locname = setlocale (LC_CTYPE, NULL); + + /* Convert locale name to LCID. We don't want to use + LocaleNameToLCID because (a) it is only available since Vista, + and (b) it doesn't accept locale names returned by 'setlocale'. */ + lcid = get_lcid (locname); + + if (lcid > 0) + return gl_locale_name_from_win32_LCID (lcid); + } +#endif + return NULL; +} + +/* XPG3 defines the result of 'setlocale (category, NULL)' as: + "Directs 'setlocale()' to query 'category' and return the current + setting of 'local'." + However it does not specify the exact format. Neither do SUSV2 and + ISO C 99. So we can use this feature only on selected systems (e.g. + those using GNU C Library). */ +#if defined _LIBC || ((defined __GLIBC__ && __GLIBC__ >= 2) && !defined __UCLIBC__) +# define HAVE_LOCALE_NULL +#endif + +const char * +gl_locale_name_posix (int category, const char *categoryname) +{ + /* Use the POSIX methods of looking to 'LC_ALL', 'LC_xxx', and 'LANG'. + On some systems this can be done by the 'setlocale' function itself. */ +#if defined HAVE_SETLOCALE && defined HAVE_LC_MESSAGES && defined HAVE_LOCALE_NULL + return setlocale (category, NULL); +#else + /* On other systems we ignore what setlocale reports and instead look at the + environment variables directly. This is necessary + 1. on systems which have a facility for customizing the default locale + (Mac OS X, native Windows, Cygwin) and where the system's setlocale() + function ignores this default locale (Mac OS X, Cygwin), in two cases: + a. when the user missed to use the setlocale() override from libintl + (for example by not including ), + b. when setlocale supports only the "C" locale, such as on Cygwin + 1.5.x. In this case even the override from libintl cannot help. + 2. on all systems where setlocale supports only the "C" locale. */ + /* Strictly speaking, it is a POSIX violation to look at the environment + variables regardless whether setlocale has been called or not. POSIX + says: + "For C-language programs, the POSIX locale shall be the + default locale when the setlocale() function is not called." + But we assume that all programs that use internationalized APIs call + setlocale (LC_ALL, ""). */ + return gl_locale_name_environ (category, categoryname); +#endif +} + +const char * +gl_locale_name_environ (int category, const char *categoryname) +{ + const char *retval; + + /* Setting of LC_ALL overrides all other. */ + retval = getenv ("LC_ALL"); + if (retval != NULL && retval[0] != '\0') + return retval; + /* Next comes the name of the desired category. */ + retval = getenv (categoryname); + if (retval != NULL && retval[0] != '\0') + return retval; + /* Last possibility is the LANG environment variable. */ + retval = getenv ("LANG"); + if (retval != NULL && retval[0] != '\0') + { +#if HAVE_CFLOCALECOPYCURRENT || HAVE_CFPREFERENCESCOPYAPPVALUE + /* Mac OS X 10.2 or newer. + Ignore invalid LANG value set by the Terminal application. */ + if (strcmp (retval, "UTF-8") != 0) +#endif +#if defined __CYGWIN__ + /* Cygwin. + Ignore dummy LANG value set by ~/.profile. */ + if (strcmp (retval, "C.UTF-8") != 0) +#endif + return retval; + } + + return NULL; +} + +const char * +gl_locale_name_default (void) +{ + /* POSIX:2001 says: + "All implementations shall define a locale as the default locale, to be + invoked when no environment variables are set, or set to the empty + string. This default locale can be the POSIX locale or any other + implementation-defined locale. Some implementations may provide + facilities for local installation administrators to set the default + locale, customizing it for each location. POSIX:2001 does not require + such a facility. + + The systems with such a facility are Mac OS X and Windows: They provide a + GUI that allows the user to choose a locale. + - On Mac OS X, by default, none of LC_* or LANG are set. Starting with + Mac OS X 10.4 or 10.5, LANG is set for processes launched by the + 'Terminal' application (but sometimes to an incorrect value "UTF-8"). + When no environment variable is set, setlocale (LC_ALL, "") uses the + "C" locale. + - On native Windows, by default, none of LC_* or LANG are set. + When no environment variable is set, setlocale (LC_ALL, "") uses the + locale chosen by the user. + - On Cygwin 1.5.x, by default, none of LC_* or LANG are set. + When no environment variable is set, setlocale (LC_ALL, "") uses the + "C" locale. + - On Cygwin 1.7, by default, LANG is set to "C.UTF-8" when the default + ~/.profile is executed. + When no environment variable is set, setlocale (LC_ALL, "") uses the + "C.UTF-8" locale, which operates in the same way as the "C" locale. + */ + +#if !(HAVE_CFLOCALECOPYCURRENT || HAVE_CFPREFERENCESCOPYAPPVALUE || defined WINDOWS_NATIVE || defined __CYGWIN__) + + /* The system does not have a way of setting the locale, other than the + POSIX specified environment variables. We use C as default locale. */ + return "C"; + +#else + + /* Return an XPG style locale name language[_territory][@modifier]. + Don't even bother determining the codeset; it's not useful in this + context, because message catalogs are not specific to a single + codeset. */ + +# if HAVE_CFLOCALECOPYCURRENT || HAVE_CFPREFERENCESCOPYAPPVALUE + /* Mac OS X 10.2 or newer */ + { + /* Cache the locale name, since CoreFoundation calls are expensive. */ + static const char *cached_localename; + + if (cached_localename == NULL) + { + char namebuf[256]; +# if HAVE_CFLOCALECOPYCURRENT /* Mac OS X 10.3 or newer */ + CFLocaleRef locale = CFLocaleCopyCurrent (); + CFStringRef name = CFLocaleGetIdentifier (locale); + + if (CFStringGetCString (name, namebuf, sizeof (namebuf), + kCFStringEncodingASCII)) + { + gl_locale_name_canonicalize (namebuf); + cached_localename = strdup (namebuf); + } + CFRelease (locale); +# elif HAVE_CFPREFERENCESCOPYAPPVALUE /* Mac OS X 10.2 or newer */ + CFTypeRef value = + CFPreferencesCopyAppValue (CFSTR ("AppleLocale"), + kCFPreferencesCurrentApplication); + if (value != NULL + && CFGetTypeID (value) == CFStringGetTypeID () + && CFStringGetCString ((CFStringRef)value, + namebuf, sizeof (namebuf), + kCFStringEncodingASCII)) + { + gl_locale_name_canonicalize (namebuf); + cached_localename = strdup (namebuf); + } +# endif + if (cached_localename == NULL) + cached_localename = "C"; + } + return cached_localename; + } + +# endif + +# if defined WINDOWS_NATIVE || defined __CYGWIN__ /* Native Windows or Cygwin */ + { + LCID lcid; + + /* Use native Windows API locale ID. */ + lcid = GetThreadLocale (); + + return gl_locale_name_from_win32_LCID (lcid); + } +# endif +#endif +} + +/* Determine the current locale's name, and canonicalize it into XPG syntax + language[_territory][.codeset][@modifier] + The codeset part in the result is not reliable; the locale_charset() + should be used for codeset information instead. + The result must not be freed; it is statically allocated. */ + +const char * +gl_locale_name (int category, const char *categoryname) +{ + const char *retval; + + retval = gl_locale_name_thread (category, categoryname); + if (retval != NULL) + return retval; + + retval = gl_locale_name_posix (category, categoryname); + if (retval != NULL) + return retval; + + return gl_locale_name_default (); +} diff --git a/gettext-tools/gnulib-lib/localename.h b/gettext-tools/gnulib-lib/localename.h new file mode 100644 index 0000000..861e6e9 --- /dev/null +++ b/gettext-tools/gnulib-lib/localename.h @@ -0,0 +1,99 @@ +/* Determine name of the currently selected locale. + Copyright (C) 2007, 2009-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _GL_LOCALENAME_H +#define _GL_LOCALENAME_H + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Determine the current locale's name. + It considers both the POSIX notion of locale name (see functions + gl_locale_name_thread and gl_locale_name_posix) and the system notion + of locale name (see function gl_locale_name_default). + CATEGORY is a locale category abbreviation, as defined in , + but not LC_ALL. E.g. LC_MESSAGES. + CATEGORYNAME is the name of CATEGORY as a string, e.g. "LC_MESSAGES". + Return the locale category's name, canonicalized into XPG syntax + language[_territory][.codeset][@modifier] + The codeset part in the result is not reliable; the locale_charset() + should be used for codeset information instead. + The result must not be freed; it is statically allocated. */ +extern const char * gl_locale_name (int category, const char *categoryname); + +/* Determine the current per-thread locale's name, as specified by uselocale() + calls. + CATEGORY is a locale category abbreviation, as defined in , + but not LC_ALL. E.g. LC_MESSAGES. + CATEGORYNAME is the name of CATEGORY as a string, e.g. "LC_MESSAGES". + Return the locale category's name, canonicalized into XPG syntax + language[_territory][.codeset][@modifier] + or NULL if no locale has been specified for the current thread. + The codeset part in the result is not reliable; the locale_charset() + should be used for codeset information instead. + The result must not be freed; it is statically allocated. */ +extern const char * gl_locale_name_thread (int category, const char *categoryname); + +/* Determine the thread-independent current locale's name, as specified by + setlocale() calls or by environment variables. + CATEGORY is a locale category abbreviation, as defined in , + but not LC_ALL. E.g. LC_MESSAGES. + CATEGORYNAME is the name of CATEGORY as a string, e.g. "LC_MESSAGES". + Return the locale category's name, canonicalized into XPG syntax + language[_territory][.codeset][@modifier] + or NULL if no locale has been specified to setlocale() or by environment + variables. + The codeset part in the result is not reliable; the locale_charset() + should be used for codeset information instead. + The result must not be freed; it is statically allocated. */ +extern const char * gl_locale_name_posix (int category, const char *categoryname); + +/* Determine the default locale's name, as specified by environment + variables. + Return the locale category's name, or NULL if no locale has been specified + by environment variables. + The result must not be freed; it is statically allocated. */ +extern const char * gl_locale_name_environ (int category, const char *categoryname); + +/* Determine the default locale's name. This is the current locale's name, + if not specified by uselocale() calls, by setlocale() calls, or by + environment variables. This locale name is usually determined by systems + settings that the user can manipulate through a GUI. + + Quoting POSIX:2001: + "All implementations shall define a locale as the default locale, + to be invoked when no environment variables are set, or set to the + empty string. This default locale can be the C locale or any other + implementation-defined locale. Some implementations may provide + facilities for local installation administrators to set the default + locale, customizing it for each location. IEEE Std 1003.1-2001 does + not require such a facility." + + The result must not be freed; it is statically allocated. */ +extern const char * gl_locale_name_default (void) +#if !(HAVE_CFLOCALECOPYCURRENT || HAVE_CFPREFERENCESCOPYAPPVALUE \ + || defined _WIN32 || defined __WIN32__ || defined __CYGWIN__) + _GL_ATTRIBUTE_CONST +#endif + ; + +#ifdef __cplusplus +} +#endif + +#endif /* _GL_LOCALENAME_H */ diff --git a/gettext-tools/gnulib-lib/lstat.c b/gettext-tools/gnulib-lib/lstat.c new file mode 100644 index 0000000..f70fd43 --- /dev/null +++ b/gettext-tools/gnulib-lib/lstat.c @@ -0,0 +1,97 @@ +/* Work around a bug of lstat on some systems + + Copyright (C) 1997-2006, 2008-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* written by Jim Meyering */ + +/* If the user's config.h happens to include , let it include only + the system's here, so that orig_lstat doesn't recurse to + rpl_lstat. */ +#define __need_system_sys_stat_h +#include + +#if !HAVE_LSTAT +/* On systems that lack symlinks, our replacement already + defined lstat as stat, so there is nothing further to do other than + avoid an empty file. */ +typedef int dummy; +#else /* HAVE_LSTAT */ + +/* Get the original definition of lstat. It might be defined as a macro. */ +# include +# include +# undef __need_system_sys_stat_h + +static int +orig_lstat (const char *filename, struct stat *buf) +{ + return lstat (filename, buf); +} + +/* Specification. */ +/* Write "sys/stat.h" here, not , otherwise OSF/1 5.1 DTK cc + eliminates this include because of the preliminary #include + above. */ +# include "sys/stat.h" + +# include +# include + +/* lstat works differently on Linux and Solaris systems. POSIX (see + "pathname resolution" in the glossary) requires that programs like + 'ls' take into consideration the fact that FILE has a trailing slash + when FILE is a symbolic link. On Linux and Solaris 10 systems, the + lstat function already has the desired semantics (in treating + 'lstat ("symlink/", sbuf)' just like 'lstat ("symlink/.", sbuf)', + but on Solaris 9 and earlier it does not. + + If FILE has a trailing slash and specifies a symbolic link, + then use stat() to get more info on the referent of FILE. + If the referent is a non-directory, then set errno to ENOTDIR + and return -1. Otherwise, return stat's result. */ + +int +rpl_lstat (const char *file, struct stat *sbuf) +{ + size_t len; + int lstat_result = orig_lstat (file, sbuf); + + if (lstat_result != 0) + return lstat_result; + + /* This replacement file can blindly check against '/' rather than + using the ISSLASH macro, because all platforms with '\\' either + lack symlinks (mingw) or have working lstat (cygwin) and thus do + not compile this file. 0 len should have already been filtered + out above, with a failure return of ENOENT. */ + len = strlen (file); + if (file[len - 1] != '/' || S_ISDIR (sbuf->st_mode)) + return 0; + + /* At this point, a trailing slash is only permitted on + symlink-to-dir; but it should have found information on the + directory, not the symlink. Call stat() to get info about the + link's referent. Our replacement stat guarantees valid results, + even if the symlink is not pointing to a directory. */ + if (!S_ISLNK (sbuf->st_mode)) + { + errno = ENOTDIR; + return -1; + } + return stat (file, sbuf); +} + +#endif /* HAVE_LSTAT */ diff --git a/gettext-tools/gnulib-lib/malloc.c b/gettext-tools/gnulib-lib/malloc.c new file mode 100644 index 0000000..bc81c54 --- /dev/null +++ b/gettext-tools/gnulib-lib/malloc.c @@ -0,0 +1,56 @@ +/* malloc() function that is glibc compatible. + + Copyright (C) 1997-1998, 2006-2007, 2009-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . */ + +/* written by Jim Meyering and Bruno Haible */ + +#define _GL_USE_STDLIB_ALLOC 1 +#include +/* Only the AC_FUNC_MALLOC macro defines 'malloc' already in config.h. */ +#ifdef malloc +# define NEED_MALLOC_GNU 1 +# undef malloc +/* Whereas the gnulib module 'malloc-gnu' defines HAVE_MALLOC_GNU. */ +#elif GNULIB_MALLOC_GNU && !HAVE_MALLOC_GNU +# define NEED_MALLOC_GNU 1 +#endif + +#include + +#include + +/* Allocate an N-byte block of memory from the heap. + If N is zero, allocate a 1-byte block. */ + +void * +rpl_malloc (size_t n) +{ + void *result; + +#if NEED_MALLOC_GNU + if (n == 0) + n = 1; +#endif + + result = malloc (n); + +#if !HAVE_MALLOC_POSIX + if (result == NULL) + errno = ENOMEM; +#endif + + return result; +} diff --git a/gettext-tools/gnulib-lib/malloca.c b/gettext-tools/gnulib-lib/malloca.c new file mode 100644 index 0000000..370551c --- /dev/null +++ b/gettext-tools/gnulib-lib/malloca.c @@ -0,0 +1,149 @@ +/* Safe automatic memory allocation. + Copyright (C) 2003, 2006-2007, 2009-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2003. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . */ + +#define _GL_USE_STDLIB_ALLOC 1 +#include + +/* Specification. */ +#include "malloca.h" + +#include + +#include "verify.h" + +/* The speed critical point in this file is freea() applied to an alloca() + result: it must be fast, to match the speed of alloca(). The speed of + mmalloca() and freea() in the other case are not critical, because they + are only invoked for big memory sizes. */ + +#if HAVE_ALLOCA + +/* Store the mmalloca() results in a hash table. This is needed to reliably + distinguish a mmalloca() result and an alloca() result. + + Although it is possible that the same pointer is returned by alloca() and + by mmalloca() at different times in the same application, it does not lead + to a bug in freea(), because: + - Before a pointer returned by alloca() can point into malloc()ed memory, + the function must return, and once this has happened the programmer must + not call freea() on it anyway. + - Before a pointer returned by mmalloca() can point into the stack, it + must be freed. The only function that can free it is freea(), and + when freea() frees it, it also removes it from the hash table. */ + +#define MAGIC_NUMBER 0x1415fb4a +#define MAGIC_SIZE sizeof (int) +/* This is how the header info would look like without any alignment + considerations. */ +struct preliminary_header { void *next; int magic; }; +/* But the header's size must be a multiple of sa_alignment_max. */ +#define HEADER_SIZE \ + (((sizeof (struct preliminary_header) + sa_alignment_max - 1) / sa_alignment_max) * sa_alignment_max) +union header { + void *next; + struct { + char room[HEADER_SIZE - MAGIC_SIZE]; + int word; + } magic; +}; +verify (HEADER_SIZE == sizeof (union header)); +/* We make the hash table quite big, so that during lookups the probability + of empty hash buckets is quite high. There is no need to make the hash + table resizable, because when the hash table gets filled so much that the + lookup becomes slow, it means that the application has memory leaks. */ +#define HASH_TABLE_SIZE 257 +static void * mmalloca_results[HASH_TABLE_SIZE]; + +#endif + +void * +mmalloca (size_t n) +{ +#if HAVE_ALLOCA + /* Allocate one more word, that serves as an indicator for malloc()ed + memory, so that freea() of an alloca() result is fast. */ + size_t nplus = n + HEADER_SIZE; + + if (nplus >= n) + { + void *p = malloc (nplus); + + if (p != NULL) + { + size_t slot; + union header *h = p; + + p = h + 1; + + /* Put a magic number into the indicator word. */ + h->magic.word = MAGIC_NUMBER; + + /* Enter p into the hash table. */ + slot = (uintptr_t) p % HASH_TABLE_SIZE; + h->next = mmalloca_results[slot]; + mmalloca_results[slot] = p; + + return p; + } + } + /* Out of memory. */ + return NULL; +#else +# if !MALLOC_0_IS_NONNULL + if (n == 0) + n = 1; +# endif + return malloc (n); +#endif +} + +#if HAVE_ALLOCA +void +freea (void *p) +{ + /* mmalloca() may have returned NULL. */ + if (p != NULL) + { + /* Attempt to quickly distinguish the mmalloca() result - which has + a magic indicator word - and the alloca() result - which has an + uninitialized indicator word. It is for this test that sa_increment + additional bytes are allocated in the alloca() case. */ + if (((int *) p)[-1] == MAGIC_NUMBER) + { + /* Looks like a mmalloca() result. To see whether it really is one, + perform a lookup in the hash table. */ + size_t slot = (uintptr_t) p % HASH_TABLE_SIZE; + void **chain = &mmalloca_results[slot]; + for (; *chain != NULL;) + { + union header *h = p; + if (*chain == p) + { + /* Found it. Remove it from the hash table and free it. */ + union header *p_begin = h - 1; + *chain = p_begin->next; + free (p_begin); + return; + } + h = *chain; + chain = &h[-1].next; + } + } + /* At this point, we know it was not a mmalloca() result. */ + } +} +#endif diff --git a/gettext-tools/gnulib-lib/malloca.h b/gettext-tools/gnulib-lib/malloca.h new file mode 100644 index 0000000..5071e46 --- /dev/null +++ b/gettext-tools/gnulib-lib/malloca.h @@ -0,0 +1,133 @@ +/* Safe automatic memory allocation. + Copyright (C) 2003-2007, 2009-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2003. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . */ + +#ifndef _MALLOCA_H +#define _MALLOCA_H + +#include +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* safe_alloca(N) is equivalent to alloca(N) when it is safe to call + alloca(N); otherwise it returns NULL. It either returns N bytes of + memory allocated on the stack, that lasts until the function returns, + or NULL. + Use of safe_alloca should be avoided: + - inside arguments of function calls - undefined behaviour, + - in inline functions - the allocation may actually last until the + calling function returns. +*/ +#if HAVE_ALLOCA +/* The OS usually guarantees only one guard page at the bottom of the stack, + and a page size can be as small as 4096 bytes. So we cannot safely + allocate anything larger than 4096 bytes. Also care for the possibility + of a few compiler-allocated temporary stack slots. + This must be a macro, not a function. */ +# define safe_alloca(N) ((N) < 4032 ? alloca (N) : NULL) +#else +# define safe_alloca(N) ((void) (N), NULL) +#endif + +/* malloca(N) is a safe variant of alloca(N). It allocates N bytes of + memory allocated on the stack, that must be freed using freea() before + the function returns. Upon failure, it returns NULL. */ +#if HAVE_ALLOCA +# define malloca(N) \ + ((N) < 4032 - sa_increment \ + ? (void *) ((char *) alloca ((N) + sa_increment) + sa_increment) \ + : mmalloca (N)) +#else +# define malloca(N) \ + mmalloca (N) +#endif +extern void * mmalloca (size_t n); + +/* Free a block of memory allocated through malloca(). */ +#if HAVE_ALLOCA +extern void freea (void *p); +#else +# define freea free +#endif + +/* nmalloca(N,S) is an overflow-safe variant of malloca (N * S). + It allocates an array of N objects, each with S bytes of memory, + on the stack. S must be positive and N must be nonnegative. + The array must be freed using freea() before the function returns. */ +#if 1 +/* Cf. the definition of xalloc_oversized. */ +# define nmalloca(n, s) \ + ((n) > (size_t) (sizeof (ptrdiff_t) <= sizeof (size_t) ? -1 : -2) / (s) \ + ? NULL \ + : malloca ((n) * (s))) +#else +extern void * nmalloca (size_t n, size_t s); +#endif + + +#ifdef __cplusplus +} +#endif + + +/* ------------------- Auxiliary, non-public definitions ------------------- */ + +/* Determine the alignment of a type at compile time. */ +#if defined __GNUC__ || defined __IBM__ALIGNOF__ +# define sa_alignof __alignof__ +#elif defined __cplusplus + template struct sa_alignof_helper { char __slot1; type __slot2; }; +# define sa_alignof(type) offsetof (sa_alignof_helper, __slot2) +#elif defined __hpux + /* Work around a HP-UX 10.20 cc bug with enums constants defined as offsetof + values. */ +# define sa_alignof(type) (sizeof (type) <= 4 ? 4 : 8) +#elif defined _AIX + /* Work around an AIX 3.2.5 xlc bug with enums constants defined as offsetof + values. */ +# define sa_alignof(type) (sizeof (type) <= 4 ? 4 : 8) +#else +# define sa_alignof(type) offsetof (struct { char __slot1; type __slot2; }, __slot2) +#endif + +enum +{ +/* The desired alignment of memory allocations is the maximum alignment + among all elementary types. */ + sa_alignment_long = sa_alignof (long), + sa_alignment_double = sa_alignof (double), +#if HAVE_LONG_LONG_INT + sa_alignment_longlong = sa_alignof (long long), +#endif + sa_alignment_longdouble = sa_alignof (long double), + sa_alignment_max = ((sa_alignment_long - 1) | (sa_alignment_double - 1) +#if HAVE_LONG_LONG_INT + | (sa_alignment_longlong - 1) +#endif + | (sa_alignment_longdouble - 1) + ) + 1, +/* The increment that guarantees room for a magic word must be >= sizeof (int) + and a multiple of sa_alignment_max. */ + sa_increment = ((sizeof (int) + sa_alignment_max - 1) / sa_alignment_max) * sa_alignment_max +}; + +#endif /* _MALLOCA_H */ diff --git a/gettext-tools/gnulib-lib/malloca.valgrind b/gettext-tools/gnulib-lib/malloca.valgrind new file mode 100644 index 0000000..52f0a50 --- /dev/null +++ b/gettext-tools/gnulib-lib/malloca.valgrind @@ -0,0 +1,7 @@ +# Suppress a valgrind message about use of uninitialized memory in freea(). +# This use is OK because it provides only a speedup. +{ + freea + Memcheck:Cond + fun:freea +} diff --git a/gettext-tools/gnulib-lib/mbchar.c b/gettext-tools/gnulib-lib/mbchar.c new file mode 100644 index 0000000..7d5bfcc --- /dev/null +++ b/gettext-tools/gnulib-lib/mbchar.c @@ -0,0 +1,37 @@ +/* Copyright (C) 2001, 2006, 2009-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + + +#include + +#define MBCHAR_INLINE _GL_EXTERN_INLINE + +#include + +#include "mbchar.h" + +#if IS_BASIC_ASCII + +/* Bit table of characters in the ISO C "basic character set". */ +const unsigned int is_basic_table [UCHAR_MAX / 32 + 1] = +{ + 0x00001a00, /* '\t' '\v' '\f' */ + 0xffffffef, /* ' '...'#' '%'...'?' */ + 0xfffffffe, /* 'A'...'Z' '[' '\\' ']' '^' '_' */ + 0x7ffffffe /* 'a'...'z' '{' '|' '}' '~' */ + /* The remaining bits are 0. */ +}; + +#endif /* IS_BASIC_ASCII */ diff --git a/gettext-tools/gnulib-lib/mbchar.h b/gettext-tools/gnulib-lib/mbchar.h new file mode 100644 index 0000000..700174c --- /dev/null +++ b/gettext-tools/gnulib-lib/mbchar.h @@ -0,0 +1,360 @@ +/* Multibyte character data type. + Copyright (C) 2001, 2005-2007, 2009-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Written by Bruno Haible . */ + +/* A multibyte character is a short subsequence of a char* string, + representing a single wide character. + + We use multibyte characters instead of wide characters because of + the following goals: + 1) correct multibyte handling, i.e. operate according to the LC_CTYPE + locale, + 2) ease of maintenance, i.e. the maintainer needs not know all details + of the ISO C 99 standard, + 3) don't fail grossly if the input is not in the encoding set by the + locale, because often different encodings are in use in the same + countries (ISO-8859-1/UTF-8, EUC-JP/Shift_JIS, ...), + 4) fast in the case of ASCII characters, + 5) portability, i.e. don't make unportable assumptions about wchar_t. + + Multibyte characters are only accessed through the mb* macros. + + mb_ptr (mbc) + return a pointer to the beginning of the multibyte sequence. + + mb_len (mbc) + returns the number of bytes occupied by the multibyte sequence. + Always > 0. + + mb_iseq (mbc, sc) + returns true if mbc is the standard ASCII character sc. + + mb_isnul (mbc) + returns true if mbc is the nul character. + + mb_cmp (mbc1, mbc2) + returns a positive, zero, or negative value depending on whether mbc1 + sorts after, same or before mbc2. + + mb_casecmp (mbc1, mbc2) + returns a positive, zero, or negative value depending on whether mbc1 + sorts after, same or before mbc2, modulo upper/lowercase conversion. + + mb_equal (mbc1, mbc2) + returns true if mbc1 and mbc2 are equal. + + mb_caseequal (mbc1, mbc2) + returns true if mbc1 and mbc2 are equal modulo upper/lowercase conversion. + + mb_isalnum (mbc) + returns true if mbc is alphanumeric. + + mb_isalpha (mbc) + returns true if mbc is alphabetic. + + mb_isascii(mbc) + returns true if mbc is plain ASCII. + + mb_isblank (mbc) + returns true if mbc is a blank. + + mb_iscntrl (mbc) + returns true if mbc is a control character. + + mb_isdigit (mbc) + returns true if mbc is a decimal digit. + + mb_isgraph (mbc) + returns true if mbc is a graphic character. + + mb_islower (mbc) + returns true if mbc is lowercase. + + mb_isprint (mbc) + returns true if mbc is a printable character. + + mb_ispunct (mbc) + returns true if mbc is a punctuation character. + + mb_isspace (mbc) + returns true if mbc is a space character. + + mb_isupper (mbc) + returns true if mbc is uppercase. + + mb_isxdigit (mbc) + returns true if mbc is a hexadecimal digit. + + mb_width (mbc) + returns the number of columns on the output device occupied by mbc. + Always >= 0. + + mb_putc (mbc, stream) + outputs mbc on stream, a byte oriented FILE stream opened for output. + + mb_setascii (&mbc, sc) + assigns the standard ASCII character sc to mbc. + + mb_copy (&destmbc, &srcmbc) + copies srcmbc to destmbc. + + Here are the function prototypes of the macros. + + extern const char * mb_ptr (const mbchar_t mbc); + extern size_t mb_len (const mbchar_t mbc); + extern bool mb_iseq (const mbchar_t mbc, char sc); + extern bool mb_isnul (const mbchar_t mbc); + extern int mb_cmp (const mbchar_t mbc1, const mbchar_t mbc2); + extern int mb_casecmp (const mbchar_t mbc1, const mbchar_t mbc2); + extern bool mb_equal (const mbchar_t mbc1, const mbchar_t mbc2); + extern bool mb_caseequal (const mbchar_t mbc1, const mbchar_t mbc2); + extern bool mb_isalnum (const mbchar_t mbc); + extern bool mb_isalpha (const mbchar_t mbc); + extern bool mb_isascii (const mbchar_t mbc); + extern bool mb_isblank (const mbchar_t mbc); + extern bool mb_iscntrl (const mbchar_t mbc); + extern bool mb_isdigit (const mbchar_t mbc); + extern bool mb_isgraph (const mbchar_t mbc); + extern bool mb_islower (const mbchar_t mbc); + extern bool mb_isprint (const mbchar_t mbc); + extern bool mb_ispunct (const mbchar_t mbc); + extern bool mb_isspace (const mbchar_t mbc); + extern bool mb_isupper (const mbchar_t mbc); + extern bool mb_isxdigit (const mbchar_t mbc); + extern int mb_width (const mbchar_t mbc); + extern void mb_putc (const mbchar_t mbc, FILE *stream); + extern void mb_setascii (mbchar_t *new, char sc); + extern void mb_copy (mbchar_t *new, const mbchar_t *old); + */ + +#ifndef _MBCHAR_H +#define _MBCHAR_H 1 + +#include +#include + +/* Tru64 with Desktop Toolkit C has a bug: must be included before + . + BSD/OS 4.1 has a bug: and must be included before + . */ +#include +#include +#include +#include + +#ifndef _GL_INLINE_HEADER_BEGIN + #error "Please include config.h first." +#endif +_GL_INLINE_HEADER_BEGIN +#ifndef MBCHAR_INLINE +# define MBCHAR_INLINE _GL_INLINE +#endif + +#define MBCHAR_BUF_SIZE 24 + +struct mbchar +{ + const char *ptr; /* pointer to current character */ + size_t bytes; /* number of bytes of current character, > 0 */ + bool wc_valid; /* true if wc is a valid wide character */ + wchar_t wc; /* if wc_valid: the current character */ + char buf[MBCHAR_BUF_SIZE]; /* room for the bytes, used for file input only */ +}; + +/* EOF (not a real character) is represented with bytes = 0 and + wc_valid = false. */ + +typedef struct mbchar mbchar_t; + +/* Access the current character. */ +#define mb_ptr(mbc) ((mbc).ptr) +#define mb_len(mbc) ((mbc).bytes) + +/* Comparison of characters. */ +#define mb_iseq(mbc, sc) ((mbc).wc_valid && (mbc).wc == (sc)) +#define mb_isnul(mbc) ((mbc).wc_valid && (mbc).wc == 0) +#define mb_cmp(mbc1, mbc2) \ + ((mbc1).wc_valid \ + ? ((mbc2).wc_valid \ + ? (int) (mbc1).wc - (int) (mbc2).wc \ + : -1) \ + : ((mbc2).wc_valid \ + ? 1 \ + : (mbc1).bytes == (mbc2).bytes \ + ? memcmp ((mbc1).ptr, (mbc2).ptr, (mbc1).bytes) \ + : (mbc1).bytes < (mbc2).bytes \ + ? (memcmp ((mbc1).ptr, (mbc2).ptr, (mbc1).bytes) > 0 ? 1 : -1) \ + : (memcmp ((mbc1).ptr, (mbc2).ptr, (mbc2).bytes) >= 0 ? 1 : -1))) +#define mb_casecmp(mbc1, mbc2) \ + ((mbc1).wc_valid \ + ? ((mbc2).wc_valid \ + ? (int) towlower ((mbc1).wc) - (int) towlower ((mbc2).wc) \ + : -1) \ + : ((mbc2).wc_valid \ + ? 1 \ + : (mbc1).bytes == (mbc2).bytes \ + ? memcmp ((mbc1).ptr, (mbc2).ptr, (mbc1).bytes) \ + : (mbc1).bytes < (mbc2).bytes \ + ? (memcmp ((mbc1).ptr, (mbc2).ptr, (mbc1).bytes) > 0 ? 1 : -1) \ + : (memcmp ((mbc1).ptr, (mbc2).ptr, (mbc2).bytes) >= 0 ? 1 : -1))) +#define mb_equal(mbc1, mbc2) \ + ((mbc1).wc_valid && (mbc2).wc_valid \ + ? (mbc1).wc == (mbc2).wc \ + : (mbc1).bytes == (mbc2).bytes \ + && memcmp ((mbc1).ptr, (mbc2).ptr, (mbc1).bytes) == 0) +#define mb_caseequal(mbc1, mbc2) \ + ((mbc1).wc_valid && (mbc2).wc_valid \ + ? towlower ((mbc1).wc) == towlower ((mbc2).wc) \ + : (mbc1).bytes == (mbc2).bytes \ + && memcmp ((mbc1).ptr, (mbc2).ptr, (mbc1).bytes) == 0) + +/* , classification. */ +#define mb_isascii(mbc) \ + ((mbc).wc_valid && (mbc).wc >= 0 && (mbc).wc <= 127) +#define mb_isalnum(mbc) ((mbc).wc_valid && iswalnum ((mbc).wc)) +#define mb_isalpha(mbc) ((mbc).wc_valid && iswalpha ((mbc).wc)) +#define mb_isblank(mbc) ((mbc).wc_valid && iswblank ((mbc).wc)) +#define mb_iscntrl(mbc) ((mbc).wc_valid && iswcntrl ((mbc).wc)) +#define mb_isdigit(mbc) ((mbc).wc_valid && iswdigit ((mbc).wc)) +#define mb_isgraph(mbc) ((mbc).wc_valid && iswgraph ((mbc).wc)) +#define mb_islower(mbc) ((mbc).wc_valid && iswlower ((mbc).wc)) +#define mb_isprint(mbc) ((mbc).wc_valid && iswprint ((mbc).wc)) +#define mb_ispunct(mbc) ((mbc).wc_valid && iswpunct ((mbc).wc)) +#define mb_isspace(mbc) ((mbc).wc_valid && iswspace ((mbc).wc)) +#define mb_isupper(mbc) ((mbc).wc_valid && iswupper ((mbc).wc)) +#define mb_isxdigit(mbc) ((mbc).wc_valid && iswxdigit ((mbc).wc)) + +/* Extra function. */ + +/* Unprintable characters appear as a small box of width 1. */ +#define MB_UNPRINTABLE_WIDTH 1 + +MBCHAR_INLINE int +mb_width_aux (wint_t wc) +{ + int w = wcwidth (wc); + /* For unprintable characters, arbitrarily return 0 for control characters + and MB_UNPRINTABLE_WIDTH otherwise. */ + return (w >= 0 ? w : iswcntrl (wc) ? 0 : MB_UNPRINTABLE_WIDTH); +} + +#define mb_width(mbc) \ + ((mbc).wc_valid ? mb_width_aux ((mbc).wc) : MB_UNPRINTABLE_WIDTH) + +/* Output. */ +#define mb_putc(mbc, stream) fwrite ((mbc).ptr, 1, (mbc).bytes, (stream)) + +/* Assignment. */ +#define mb_setascii(mbc, sc) \ + ((mbc)->ptr = (mbc)->buf, (mbc)->bytes = 1, (mbc)->wc_valid = 1, \ + (mbc)->wc = (mbc)->buf[0] = (sc)) + +/* Copying a character. */ +MBCHAR_INLINE void +mb_copy (mbchar_t *new_mbc, const mbchar_t *old_mbc) +{ + if (old_mbc->ptr == &old_mbc->buf[0]) + { + memcpy (&new_mbc->buf[0], &old_mbc->buf[0], old_mbc->bytes); + new_mbc->ptr = &new_mbc->buf[0]; + } + else + new_mbc->ptr = old_mbc->ptr; + new_mbc->bytes = old_mbc->bytes; + if ((new_mbc->wc_valid = old_mbc->wc_valid)) + new_mbc->wc = old_mbc->wc; +} + + +/* is_basic(c) tests whether the single-byte character c is in the + ISO C "basic character set". + This is a convenience function, and is in this file only to share code + between mbiter_multi.h and mbfile_multi.h. */ +#if (' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ + && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \ + && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \ + && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \ + && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \ + && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \ + && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \ + && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \ + && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \ + && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \ + && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \ + && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \ + && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \ + && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \ + && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \ + && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \ + && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \ + && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \ + && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \ + && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \ + && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \ + && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \ + && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126) +/* The character set is ISO-646, not EBCDIC. */ +# define IS_BASIC_ASCII 1 + +extern const unsigned int is_basic_table[]; + +MBCHAR_INLINE bool +is_basic (char c) +{ + return (is_basic_table [(unsigned char) c >> 5] >> ((unsigned char) c & 31)) + & 1; +} + +#else + +MBCHAR_INLINE bool +is_basic (char c) +{ + switch (c) + { + case '\t': case '\v': case '\f': + case ' ': case '!': case '"': case '#': case '%': + case '&': case '\'': case '(': case ')': case '*': + case '+': case ',': case '-': case '.': case '/': + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + case ':': case ';': case '<': case '=': case '>': + case '?': + case 'A': case 'B': case 'C': case 'D': case 'E': + case 'F': case 'G': case 'H': case 'I': case 'J': + case 'K': case 'L': case 'M': case 'N': case 'O': + case 'P': case 'Q': case 'R': case 'S': case 'T': + case 'U': case 'V': case 'W': case 'X': case 'Y': + case 'Z': + case '[': case '\\': case ']': case '^': case '_': + case 'a': case 'b': case 'c': case 'd': case 'e': + case 'f': case 'g': case 'h': case 'i': case 'j': + case 'k': case 'l': case 'm': case 'n': case 'o': + case 'p': case 'q': case 'r': case 's': case 't': + case 'u': case 'v': case 'w': case 'x': case 'y': + case 'z': case '{': case '|': case '}': case '~': + return 1; + default: + return 0; + } +} + +#endif + +_GL_INLINE_HEADER_END + +#endif /* _MBCHAR_H */ diff --git a/gettext-tools/gnulib-lib/mbiter.c b/gettext-tools/gnulib-lib/mbiter.c new file mode 100644 index 0000000..22a1ff8 --- /dev/null +++ b/gettext-tools/gnulib-lib/mbiter.c @@ -0,0 +1,3 @@ +#include +#define MBITER_INLINE _GL_EXTERN_INLINE +#include "mbiter.h" diff --git a/gettext-tools/gnulib-lib/mbiter.h b/gettext-tools/gnulib-lib/mbiter.h new file mode 100644 index 0000000..32fff8c --- /dev/null +++ b/gettext-tools/gnulib-lib/mbiter.h @@ -0,0 +1,225 @@ +/* Iterating through multibyte strings: macros for multi-byte encodings. + Copyright (C) 2001, 2005, 2007, 2009-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Written by Bruno Haible . */ + +/* The macros in this file implement forward iteration through a + multi-byte string. + + With these macros, an iteration loop that looks like + + char *iter; + for (iter = buf; iter < buf + buflen; iter++) + { + do_something (*iter); + } + + becomes + + mbi_iterator_t iter; + for (mbi_init (iter, buf, buflen); mbi_avail (iter); mbi_advance (iter)) + { + do_something (mbi_cur_ptr (iter), mb_len (mbi_cur (iter))); + } + + The benefit of these macros over plain use of mbrtowc is: + - Handling of invalid multibyte sequences is possible without + making the code more complicated, while still preserving the + invalid multibyte sequences. + + mbi_iterator_t + is a type usable for variable declarations. + + mbi_init (iter, startptr, length) + initializes the iterator, starting at startptr and crossing length bytes. + + mbi_avail (iter) + returns true if there are more multibyte characters available before + the end of string is reached. In this case, mbi_cur (iter) is + initialized to the next multibyte character. + + mbi_advance (iter) + advances the iterator by one multibyte character. + + mbi_cur (iter) + returns the current multibyte character, of type mbchar_t. All the + macros defined in mbchar.h can be used on it. + + mbi_cur_ptr (iter) + return a pointer to the beginning of the current multibyte character. + + mbi_reloc (iter, ptrdiff) + relocates iterator when the string is moved by ptrdiff bytes. + + mbi_copy (&destiter, &srciter) + copies srciter to destiter. + + Here are the function prototypes of the macros. + + extern void mbi_init (mbi_iterator_t iter, + const char *startptr, size_t length); + extern bool mbi_avail (mbi_iterator_t iter); + extern void mbi_advance (mbi_iterator_t iter); + extern mbchar_t mbi_cur (mbi_iterator_t iter); + extern const char * mbi_cur_ptr (mbi_iterator_t iter); + extern void mbi_reloc (mbi_iterator_t iter, ptrdiff_t ptrdiff); + extern void mbi_copy (mbi_iterator_t *new, const mbi_iterator_t *old); + */ + +#ifndef _MBITER_H +#define _MBITER_H 1 + +#include +#include +#include +#include + +/* Tru64 with Desktop Toolkit C has a bug: must be included before + . + BSD/OS 4.1 has a bug: and must be included before + . */ +#include +#include +#include + +#include "mbchar.h" + +#ifndef _GL_INLINE_HEADER_BEGIN + #error "Please include config.h first." +#endif +_GL_INLINE_HEADER_BEGIN +#ifndef MBITER_INLINE +# define MBITER_INLINE _GL_INLINE +#endif + +struct mbiter_multi +{ + const char *limit; /* pointer to end of string */ + bool in_shift; /* true if next byte may not be interpreted as ASCII */ + mbstate_t state; /* if in_shift: current shift state */ + bool next_done; /* true if mbi_avail has already filled the following */ + struct mbchar cur; /* the current character: + const char *cur.ptr pointer to current character + The following are only valid after mbi_avail. + size_t cur.bytes number of bytes of current character + bool cur.wc_valid true if wc is a valid wide character + wchar_t cur.wc if wc_valid: the current character + */ +}; + +MBITER_INLINE void +mbiter_multi_next (struct mbiter_multi *iter) +{ + if (iter->next_done) + return; + if (iter->in_shift) + goto with_shift; + /* Handle most ASCII characters quickly, without calling mbrtowc(). */ + if (is_basic (*iter->cur.ptr)) + { + /* These characters are part of the basic character set. ISO C 99 + guarantees that their wide character code is identical to their + char code. */ + iter->cur.bytes = 1; + iter->cur.wc = *iter->cur.ptr; + iter->cur.wc_valid = true; + } + else + { + assert (mbsinit (&iter->state)); + iter->in_shift = true; + with_shift: + iter->cur.bytes = mbrtowc (&iter->cur.wc, iter->cur.ptr, + iter->limit - iter->cur.ptr, &iter->state); + if (iter->cur.bytes == (size_t) -1) + { + /* An invalid multibyte sequence was encountered. */ + iter->cur.bytes = 1; + iter->cur.wc_valid = false; + /* Whether to set iter->in_shift = false and reset iter->state + or not is not very important; the string is bogus anyway. */ + } + else if (iter->cur.bytes == (size_t) -2) + { + /* An incomplete multibyte character at the end. */ + iter->cur.bytes = iter->limit - iter->cur.ptr; + iter->cur.wc_valid = false; + /* Whether to set iter->in_shift = false and reset iter->state + or not is not important; the string end is reached anyway. */ + } + else + { + if (iter->cur.bytes == 0) + { + /* A null wide character was encountered. */ + iter->cur.bytes = 1; + assert (*iter->cur.ptr == '\0'); + assert (iter->cur.wc == 0); + } + iter->cur.wc_valid = true; + + /* When in the initial state, we can go back treating ASCII + characters more quickly. */ + if (mbsinit (&iter->state)) + iter->in_shift = false; + } + } + iter->next_done = true; +} + +MBITER_INLINE void +mbiter_multi_reloc (struct mbiter_multi *iter, ptrdiff_t ptrdiff) +{ + iter->cur.ptr += ptrdiff; + iter->limit += ptrdiff; +} + +MBITER_INLINE void +mbiter_multi_copy (struct mbiter_multi *new_iter, const struct mbiter_multi *old_iter) +{ + new_iter->limit = old_iter->limit; + if ((new_iter->in_shift = old_iter->in_shift)) + memcpy (&new_iter->state, &old_iter->state, sizeof (mbstate_t)); + else + memset (&new_iter->state, 0, sizeof (mbstate_t)); + new_iter->next_done = old_iter->next_done; + mb_copy (&new_iter->cur, &old_iter->cur); +} + +/* Iteration macros. */ +typedef struct mbiter_multi mbi_iterator_t; +#define mbi_init(iter, startptr, length) \ + ((iter).cur.ptr = (startptr), (iter).limit = (iter).cur.ptr + (length), \ + (iter).in_shift = false, memset (&(iter).state, '\0', sizeof (mbstate_t)), \ + (iter).next_done = false) +#define mbi_avail(iter) \ + ((iter).cur.ptr < (iter).limit && (mbiter_multi_next (&(iter)), true)) +#define mbi_advance(iter) \ + ((iter).cur.ptr += (iter).cur.bytes, (iter).next_done = false) + +/* Access to the current character. */ +#define mbi_cur(iter) (iter).cur +#define mbi_cur_ptr(iter) (iter).cur.ptr + +/* Relocation. */ +#define mbi_reloc(iter, ptrdiff) mbiter_multi_reloc (&iter, ptrdiff) + +/* Copying an iterator. */ +#define mbi_copy mbiter_multi_copy + +_GL_INLINE_HEADER_END + +#endif /* _MBITER_H */ diff --git a/gettext-tools/gnulib-lib/mbrtowc.c b/gettext-tools/gnulib-lib/mbrtowc.c new file mode 100644 index 0000000..5743f43 --- /dev/null +++ b/gettext-tools/gnulib-lib/mbrtowc.c @@ -0,0 +1,407 @@ +/* Convert multibyte character to wide character. + Copyright (C) 1999-2002, 2005-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2008. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include + +#if GNULIB_defined_mbstate_t +/* Implement mbrtowc() on top of mbtowc(). */ + +# include +# include + +# include "localcharset.h" +# include "streq.h" +# include "verify.h" + + +verify (sizeof (mbstate_t) >= 4); + +static char internal_state[4]; + +size_t +mbrtowc (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps) +{ + char *pstate = (char *)ps; + + if (s == NULL) + { + pwc = NULL; + s = ""; + n = 1; + } + + if (n == 0) + return (size_t)(-2); + + /* Here n > 0. */ + + if (pstate == NULL) + pstate = internal_state; + + { + size_t nstate = pstate[0]; + char buf[4]; + const char *p; + size_t m; + + switch (nstate) + { + case 0: + p = s; + m = n; + break; + case 3: + buf[2] = pstate[3]; + /*FALLTHROUGH*/ + case 2: + buf[1] = pstate[2]; + /*FALLTHROUGH*/ + case 1: + buf[0] = pstate[1]; + p = buf; + m = nstate; + buf[m++] = s[0]; + if (n >= 2 && m < 4) + { + buf[m++] = s[1]; + if (n >= 3 && m < 4) + buf[m++] = s[2]; + } + break; + default: + errno = EINVAL; + return (size_t)(-1); + } + + /* Here m > 0. */ + +# if __GLIBC__ || defined __UCLIBC__ + /* Work around bug */ + mbtowc (NULL, NULL, 0); +# endif + { + int res = mbtowc (pwc, p, m); + + if (res >= 0) + { + if (pwc != NULL && ((*pwc == 0) != (res == 0))) + abort (); + if (nstate >= (res > 0 ? res : 1)) + abort (); + res -= nstate; + pstate[0] = 0; + return res; + } + + /* mbtowc does not distinguish between invalid and incomplete multibyte + sequences. But mbrtowc needs to make this distinction. + There are two possible approaches: + - Use iconv() and its return value. + - Use built-in knowledge about the possible encodings. + Given the low quality of implementation of iconv() on the systems that + lack mbrtowc(), we use the second approach. + The possible encodings are: + - 8-bit encodings, + - EUC-JP, EUC-KR, GB2312, EUC-TW, BIG5, GB18030, SJIS, + - UTF-8. + Use specialized code for each. */ + if (m >= 4 || m >= MB_CUR_MAX) + goto invalid; + /* Here MB_CUR_MAX > 1 and 0 < m < 4. */ + { + const char *encoding = locale_charset (); + + if (STREQ_OPT (encoding, "UTF-8", 'U', 'T', 'F', '-', '8', 0, 0, 0, 0)) + { + /* Cf. unistr/u8-mblen.c. */ + unsigned char c = (unsigned char) p[0]; + + if (c >= 0xc2) + { + if (c < 0xe0) + { + if (m == 1) + goto incomplete; + } + else if (c < 0xf0) + { + if (m == 1) + goto incomplete; + if (m == 2) + { + unsigned char c2 = (unsigned char) p[1]; + + if ((c2 ^ 0x80) < 0x40 + && (c >= 0xe1 || c2 >= 0xa0) + && (c != 0xed || c2 < 0xa0)) + goto incomplete; + } + } + else if (c <= 0xf4) + { + if (m == 1) + goto incomplete; + else /* m == 2 || m == 3 */ + { + unsigned char c2 = (unsigned char) p[1]; + + if ((c2 ^ 0x80) < 0x40 + && (c >= 0xf1 || c2 >= 0x90) + && (c < 0xf4 || (c == 0xf4 && c2 < 0x90))) + { + if (m == 2) + goto incomplete; + else /* m == 3 */ + { + unsigned char c3 = (unsigned char) p[2]; + + if ((c3 ^ 0x80) < 0x40) + goto incomplete; + } + } + } + } + } + goto invalid; + } + + /* As a reference for this code, you can use the GNU libiconv + implementation. Look for uses of the RET_TOOFEW macro. */ + + if (STREQ_OPT (encoding, + "EUC-JP", 'E', 'U', 'C', '-', 'J', 'P', 0, 0, 0)) + { + if (m == 1) + { + unsigned char c = (unsigned char) p[0]; + + if ((c >= 0xa1 && c < 0xff) || c == 0x8e || c == 0x8f) + goto incomplete; + } + if (m == 2) + { + unsigned char c = (unsigned char) p[0]; + + if (c == 0x8f) + { + unsigned char c2 = (unsigned char) p[1]; + + if (c2 >= 0xa1 && c2 < 0xff) + goto incomplete; + } + } + goto invalid; + } + if (STREQ_OPT (encoding, + "EUC-KR", 'E', 'U', 'C', '-', 'K', 'R', 0, 0, 0) + || STREQ_OPT (encoding, + "GB2312", 'G', 'B', '2', '3', '1', '2', 0, 0, 0) + || STREQ_OPT (encoding, + "BIG5", 'B', 'I', 'G', '5', 0, 0, 0, 0, 0)) + { + if (m == 1) + { + unsigned char c = (unsigned char) p[0]; + + if (c >= 0xa1 && c < 0xff) + goto incomplete; + } + goto invalid; + } + if (STREQ_OPT (encoding, + "EUC-TW", 'E', 'U', 'C', '-', 'T', 'W', 0, 0, 0)) + { + if (m == 1) + { + unsigned char c = (unsigned char) p[0]; + + if ((c >= 0xa1 && c < 0xff) || c == 0x8e) + goto incomplete; + } + else /* m == 2 || m == 3 */ + { + unsigned char c = (unsigned char) p[0]; + + if (c == 0x8e) + goto incomplete; + } + goto invalid; + } + if (STREQ_OPT (encoding, + "GB18030", 'G', 'B', '1', '8', '0', '3', '0', 0, 0)) + { + if (m == 1) + { + unsigned char c = (unsigned char) p[0]; + + if ((c >= 0x90 && c <= 0xe3) || (c >= 0xf8 && c <= 0xfe)) + goto incomplete; + } + else /* m == 2 || m == 3 */ + { + unsigned char c = (unsigned char) p[0]; + + if (c >= 0x90 && c <= 0xe3) + { + unsigned char c2 = (unsigned char) p[1]; + + if (c2 >= 0x30 && c2 <= 0x39) + { + if (m == 2) + goto incomplete; + else /* m == 3 */ + { + unsigned char c3 = (unsigned char) p[2]; + + if (c3 >= 0x81 && c3 <= 0xfe) + goto incomplete; + } + } + } + } + goto invalid; + } + if (STREQ_OPT (encoding, "SJIS", 'S', 'J', 'I', 'S', 0, 0, 0, 0, 0)) + { + if (m == 1) + { + unsigned char c = (unsigned char) p[0]; + + if ((c >= 0x81 && c <= 0x9f) || (c >= 0xe0 && c <= 0xea) + || (c >= 0xf0 && c <= 0xf9)) + goto incomplete; + } + goto invalid; + } + + /* An unknown multibyte encoding. */ + goto incomplete; + } + + incomplete: + { + size_t k = nstate; + /* Here 0 <= k < m < 4. */ + pstate[++k] = s[0]; + if (k < m) + { + pstate[++k] = s[1]; + if (k < m) + pstate[++k] = s[2]; + } + if (k != m) + abort (); + } + pstate[0] = m; + return (size_t)(-2); + + invalid: + errno = EILSEQ; + /* The conversion state is undefined, says POSIX. */ + return (size_t)(-1); + } + } +} + +#else +/* Override the system's mbrtowc() function. */ + +# undef mbrtowc + +size_t +rpl_mbrtowc (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps) +{ +# if MBRTOWC_NULL_ARG2_BUG || MBRTOWC_RETVAL_BUG || MBRTOWC_EMPTY_INPUT_BUG + if (s == NULL) + { + pwc = NULL; + s = ""; + n = 1; + } +# endif + +# if MBRTOWC_EMPTY_INPUT_BUG + if (n == 0) + return (size_t) -2; +# endif + +# if MBRTOWC_RETVAL_BUG + { + static mbstate_t internal_state; + + /* Override mbrtowc's internal state. We cannot call mbsinit() on the + hidden internal state, but we can call it on our variable. */ + if (ps == NULL) + ps = &internal_state; + + if (!mbsinit (ps)) + { + /* Parse the rest of the multibyte character byte for byte. */ + size_t count = 0; + for (; n > 0; s++, n--) + { + wchar_t wc; + size_t ret = mbrtowc (&wc, s, 1, ps); + + if (ret == (size_t)(-1)) + return (size_t)(-1); + count++; + if (ret != (size_t)(-2)) + { + /* The multibyte character has been completed. */ + if (pwc != NULL) + *pwc = wc; + return (wc == 0 ? 0 : count); + } + } + return (size_t)(-2); + } + } +# endif + +# if MBRTOWC_NUL_RETVAL_BUG + { + wchar_t wc; + size_t ret = mbrtowc (&wc, s, n, ps); + + if (ret != (size_t)(-1) && ret != (size_t)(-2)) + { + if (pwc != NULL) + *pwc = wc; + if (wc == 0) + ret = 0; + } + return ret; + } +# else + { +# if MBRTOWC_NULL_ARG1_BUG + wchar_t dummy; + + if (pwc == NULL) + pwc = &dummy; +# endif + + return mbrtowc (pwc, s, n, ps); + } +# endif +} + +#endif diff --git a/gettext-tools/gnulib-lib/mbsinit.c b/gettext-tools/gnulib-lib/mbsinit.c new file mode 100644 index 0000000..df4bcd1 --- /dev/null +++ b/gettext-tools/gnulib-lib/mbsinit.c @@ -0,0 +1,61 @@ +/* Test for initial conversion state. + Copyright (C) 2008-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2008. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include + +#include "verify.h" + +#if (defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__ + +/* On native Windows, 'mbstate_t' is defined as 'int'. */ + +int +mbsinit (const mbstate_t *ps) +{ + return ps == NULL || *ps == 0; +} + +#else + +/* Platforms that lack mbsinit() also lack mbrlen(), mbrtowc(), mbsrtowcs() + and wcrtomb(), wcsrtombs(). + We assume that + - sizeof (mbstate_t) >= 4, + - only stateless encodings are supported (such as UTF-8 and EUC-JP, but + not ISO-2022 variants), + - for each encoding, the number of bytes for a wide character is <= 4. + (This maximum is attained for UTF-8, GB18030, EUC-TW.) + We define the meaning of mbstate_t as follows: + - In mb -> wc direction, mbstate_t's first byte contains the number of + buffered bytes (in the range 0..3), followed by up to 3 buffered bytes. + - In wc -> mb direction, mbstate_t contains no information. In other + words, it is always in the initial state. */ + +verify (sizeof (mbstate_t) >= 4); + +int +mbsinit (const mbstate_t *ps) +{ + const char *pstate = (const char *)ps; + + return pstate == NULL || pstate[0] == 0; +} + +#endif diff --git a/gettext-tools/gnulib-lib/mbslen.c b/gettext-tools/gnulib-lib/mbslen.c new file mode 100644 index 0000000..74c6ec1 --- /dev/null +++ b/gettext-tools/gnulib-lib/mbslen.c @@ -0,0 +1,44 @@ +/* Counting the multibyte characters in a string. + Copyright (C) 2007-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2007. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include + +#include + +#include "mbuiter.h" + +/* Return the number of multibyte characters in the character string STRING. */ +size_t +mbslen (const char *string) +{ + if (MB_CUR_MAX > 1) + { + size_t count; + mbui_iterator_t iter; + + count = 0; + for (mbui_init (iter, string); mbui_avail (iter); mbui_advance (iter)) + count++; + + return count; + } + else + return strlen (string); +} diff --git a/gettext-tools/gnulib-lib/mbsrtowcs-impl.h b/gettext-tools/gnulib-lib/mbsrtowcs-impl.h new file mode 100644 index 0000000..d42af01 --- /dev/null +++ b/gettext-tools/gnulib-lib/mbsrtowcs-impl.h @@ -0,0 +1,122 @@ +/* Convert string to wide string. + Copyright (C) 2008-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2008. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +size_t +mbsrtowcs (wchar_t *dest, const char **srcp, size_t len, mbstate_t *ps) +{ + if (ps == NULL) + ps = &_gl_mbsrtowcs_state; + { + const char *src = *srcp; + + if (dest != NULL) + { + wchar_t *destptr = dest; + + for (; len > 0; destptr++, len--) + { + size_t src_avail; + size_t ret; + + /* An optimized variant of + src_avail = strnlen1 (src, MB_LEN_MAX); */ + if (src[0] == '\0') + src_avail = 1; + else if (src[1] == '\0') + src_avail = 2; + else if (src[2] == '\0') + src_avail = 3; + else if (MB_LEN_MAX <= 4 || src[3] == '\0') + src_avail = 4; + else + src_avail = 4 + strnlen1 (src + 4, MB_LEN_MAX - 4); + + /* Parse the next multibyte character. */ + ret = mbrtowc (destptr, src, src_avail, ps); + + if (ret == (size_t)(-2)) + /* Encountered a multibyte character that extends past a '\0' byte + or that is longer than MB_LEN_MAX bytes. Cannot happen. */ + abort (); + + if (ret == (size_t)(-1)) + goto bad_input; + if (ret == 0) + { + src = NULL; + /* Here mbsinit (ps). */ + break; + } + src += ret; + } + + *srcp = src; + return destptr - dest; + } + else + { + /* Ignore dest and len, don't store *srcp at the end, and + don't clobber *ps. */ + mbstate_t state = *ps; + size_t totalcount = 0; + + for (;; totalcount++) + { + size_t src_avail; + size_t ret; + + /* An optimized variant of + src_avail = strnlen1 (src, MB_LEN_MAX); */ + if (src[0] == '\0') + src_avail = 1; + else if (src[1] == '\0') + src_avail = 2; + else if (src[2] == '\0') + src_avail = 3; + else if (MB_LEN_MAX <= 4 || src[3] == '\0') + src_avail = 4; + else + src_avail = 4 + strnlen1 (src + 4, MB_LEN_MAX - 4); + + /* Parse the next multibyte character. */ + ret = mbrtowc (NULL, src, src_avail, &state); + + if (ret == (size_t)(-2)) + /* Encountered a multibyte character that extends past a '\0' byte + or that is longer than MB_LEN_MAX bytes. Cannot happen. */ + abort (); + + if (ret == (size_t)(-1)) + goto bad_input2; + if (ret == 0) + { + /* Here mbsinit (&state). */ + break; + } + src += ret; + } + + return totalcount; + } + + bad_input: + *srcp = src; + bad_input2: + errno = EILSEQ; + return (size_t)(-1); + } +} diff --git a/gettext-tools/gnulib-lib/mbsrtowcs-state.c b/gettext-tools/gnulib-lib/mbsrtowcs-state.c new file mode 100644 index 0000000..2a7019a --- /dev/null +++ b/gettext-tools/gnulib-lib/mbsrtowcs-state.c @@ -0,0 +1,37 @@ +/* Convert string to wide string. + Copyright (C) 2008-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2008. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +#include + +/* Internal state used by the functions mbsrtowcs() and mbsnrtowcs(). */ +mbstate_t _gl_mbsrtowcs_state +/* The state must initially be in the "initial state"; so, zero-initialize it. + On most systems, putting it into BSS is sufficient. Not so on Mac OS X 10.3, + see . + When it needs an initializer, use 0 or {0} as initializer? 0 only works + when mbstate_t is a scalar type (such as when gnulib defines it, or on + AIX, IRIX, mingw). {0} works as an initializer in all cases: for a struct + or union type, but also for a scalar type (ISO C 99, 6.7.8.(11)). */ +#if defined __ELF__ + /* On ELF systems, variables in BSS behave well. */ +#else + /* Use braces, to be on the safe side. */ + = { 0 } +#endif + ; diff --git a/gettext-tools/gnulib-lib/mbsrtowcs.c b/gettext-tools/gnulib-lib/mbsrtowcs.c new file mode 100644 index 0000000..136ec34 --- /dev/null +++ b/gettext-tools/gnulib-lib/mbsrtowcs.c @@ -0,0 +1,32 @@ +/* Convert string to wide string. + Copyright (C) 2008-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2008. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include + +#include +#include +#include + +#include "strnlen1.h" + + +extern mbstate_t _gl_mbsrtowcs_state; + +#include "mbsrtowcs-impl.h" diff --git a/gettext-tools/gnulib-lib/mbsstr.c b/gettext-tools/gnulib-lib/mbsstr.c new file mode 100644 index 0000000..1ae9fe4 --- /dev/null +++ b/gettext-tools/gnulib-lib/mbsstr.c @@ -0,0 +1,384 @@ +/* Searching in a string. + Copyright (C) 2005-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2005. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include + +#include +#include /* for NULL, in case a nonstandard string.h lacks it */ + +#include "malloca.h" +#include "mbuiter.h" + +/* Knuth-Morris-Pratt algorithm. */ +#define UNIT unsigned char +#define CANON_ELEMENT(c) c +#include "str-kmp.h" + +/* Knuth-Morris-Pratt algorithm. + See http://en.wikipedia.org/wiki/Knuth-Morris-Pratt_algorithm + Return a boolean indicating success: + Return true and set *RESULTP if the search was completed. + Return false if it was aborted because not enough memory was available. */ +static bool +knuth_morris_pratt_multibyte (const char *haystack, const char *needle, + const char **resultp) +{ + size_t m = mbslen (needle); + mbchar_t *needle_mbchars; + size_t *table; + + /* Allocate room for needle_mbchars and the table. */ + void *memory = nmalloca (m, sizeof (mbchar_t) + sizeof (size_t)); + void *table_memory; + if (memory == NULL) + return false; + needle_mbchars = memory; + table_memory = needle_mbchars + m; + table = table_memory; + + /* Fill needle_mbchars. */ + { + mbui_iterator_t iter; + size_t j; + + j = 0; + for (mbui_init (iter, needle); mbui_avail (iter); mbui_advance (iter), j++) + mb_copy (&needle_mbchars[j], &mbui_cur (iter)); + } + + /* Fill the table. + For 0 < i < m: + 0 < table[i] <= i is defined such that + forall 0 < x < table[i]: needle[x..i-1] != needle[0..i-1-x], + and table[i] is as large as possible with this property. + This implies: + 1) For 0 < i < m: + If table[i] < i, + needle[table[i]..i-1] = needle[0..i-1-table[i]]. + 2) For 0 < i < m: + rhaystack[0..i-1] == needle[0..i-1] + and exists h, i <= h < m: rhaystack[h] != needle[h] + implies + forall 0 <= x < table[i]: rhaystack[x..x+m-1] != needle[0..m-1]. + table[0] remains uninitialized. */ + { + size_t i, j; + + /* i = 1: Nothing to verify for x = 0. */ + table[1] = 1; + j = 0; + + for (i = 2; i < m; i++) + { + /* Here: j = i-1 - table[i-1]. + The inequality needle[x..i-1] != needle[0..i-1-x] is known to hold + for x < table[i-1], by induction. + Furthermore, if j>0: needle[i-1-j..i-2] = needle[0..j-1]. */ + mbchar_t *b = &needle_mbchars[i - 1]; + + for (;;) + { + /* Invariants: The inequality needle[x..i-1] != needle[0..i-1-x] + is known to hold for x < i-1-j. + Furthermore, if j>0: needle[i-1-j..i-2] = needle[0..j-1]. */ + if (mb_equal (*b, needle_mbchars[j])) + { + /* Set table[i] := i-1-j. */ + table[i] = i - ++j; + break; + } + /* The inequality needle[x..i-1] != needle[0..i-1-x] also holds + for x = i-1-j, because + needle[i-1] != needle[j] = needle[i-1-x]. */ + if (j == 0) + { + /* The inequality holds for all possible x. */ + table[i] = i; + break; + } + /* The inequality needle[x..i-1] != needle[0..i-1-x] also holds + for i-1-j < x < i-1-j+table[j], because for these x: + needle[x..i-2] + = needle[x-(i-1-j)..j-1] + != needle[0..j-1-(x-(i-1-j))] (by definition of table[j]) + = needle[0..i-2-x], + hence needle[x..i-1] != needle[0..i-1-x]. + Furthermore + needle[i-1-j+table[j]..i-2] + = needle[table[j]..j-1] + = needle[0..j-1-table[j]] (by definition of table[j]). */ + j = j - table[j]; + } + /* Here: j = i - table[i]. */ + } + } + + /* Search, using the table to accelerate the processing. */ + { + size_t j; + mbui_iterator_t rhaystack; + mbui_iterator_t phaystack; + + *resultp = NULL; + j = 0; + mbui_init (rhaystack, haystack); + mbui_init (phaystack, haystack); + /* Invariant: phaystack = rhaystack + j. */ + while (mbui_avail (phaystack)) + if (mb_equal (needle_mbchars[j], mbui_cur (phaystack))) + { + j++; + mbui_advance (phaystack); + if (j == m) + { + /* The entire needle has been found. */ + *resultp = mbui_cur_ptr (rhaystack); + break; + } + } + else if (j > 0) + { + /* Found a match of needle[0..j-1], mismatch at needle[j]. */ + size_t count = table[j]; + j -= count; + for (; count > 0; count--) + { + if (!mbui_avail (rhaystack)) + abort (); + mbui_advance (rhaystack); + } + } + else + { + /* Found a mismatch at needle[0] already. */ + if (!mbui_avail (rhaystack)) + abort (); + mbui_advance (rhaystack); + mbui_advance (phaystack); + } + } + + freea (memory); + return true; +} + +/* Find the first occurrence of the character string NEEDLE in the character + string HAYSTACK. Return NULL if NEEDLE is not found in HAYSTACK. */ +char * +mbsstr (const char *haystack, const char *needle) +{ + /* Be careful not to look at the entire extent of haystack or needle + until needed. This is useful because of these two cases: + - haystack may be very long, and a match of needle found early, + - needle may be very long, and not even a short initial segment of + needle may be found in haystack. */ + if (MB_CUR_MAX > 1) + { + mbui_iterator_t iter_needle; + + mbui_init (iter_needle, needle); + if (mbui_avail (iter_needle)) + { + /* Minimizing the worst-case complexity: + Let n = mbslen(haystack), m = mbslen(needle). + The naïve algorithm is O(n*m) worst-case. + The Knuth-Morris-Pratt algorithm is O(n) worst-case but it needs a + memory allocation. + To achieve linear complexity and yet amortize the cost of the + memory allocation, we activate the Knuth-Morris-Pratt algorithm + only once the naïve algorithm has already run for some time; more + precisely, when + - the outer loop count is >= 10, + - the average number of comparisons per outer loop is >= 5, + - the total number of comparisons is >= m. + But we try it only once. If the memory allocation attempt failed, + we don't retry it. */ + bool try_kmp = true; + size_t outer_loop_count = 0; + size_t comparison_count = 0; + size_t last_ccount = 0; /* last comparison count */ + mbui_iterator_t iter_needle_last_ccount; /* = needle + last_ccount */ + + mbui_iterator_t iter_haystack; + + mbui_init (iter_needle_last_ccount, needle); + mbui_init (iter_haystack, haystack); + for (;; mbui_advance (iter_haystack)) + { + if (!mbui_avail (iter_haystack)) + /* No match. */ + return NULL; + + /* See whether it's advisable to use an asymptotically faster + algorithm. */ + if (try_kmp + && outer_loop_count >= 10 + && comparison_count >= 5 * outer_loop_count) + { + /* See if needle + comparison_count now reaches the end of + needle. */ + size_t count = comparison_count - last_ccount; + for (; + count > 0 && mbui_avail (iter_needle_last_ccount); + count--) + mbui_advance (iter_needle_last_ccount); + last_ccount = comparison_count; + if (!mbui_avail (iter_needle_last_ccount)) + { + /* Try the Knuth-Morris-Pratt algorithm. */ + const char *result; + bool success = + knuth_morris_pratt_multibyte (haystack, needle, + &result); + if (success) + return (char *) result; + try_kmp = false; + } + } + + outer_loop_count++; + comparison_count++; + if (mb_equal (mbui_cur (iter_haystack), mbui_cur (iter_needle))) + /* The first character matches. */ + { + mbui_iterator_t rhaystack; + mbui_iterator_t rneedle; + + memcpy (&rhaystack, &iter_haystack, sizeof (mbui_iterator_t)); + mbui_advance (rhaystack); + + mbui_init (rneedle, needle); + if (!mbui_avail (rneedle)) + abort (); + mbui_advance (rneedle); + + for (;; mbui_advance (rhaystack), mbui_advance (rneedle)) + { + if (!mbui_avail (rneedle)) + /* Found a match. */ + return (char *) mbui_cur_ptr (iter_haystack); + if (!mbui_avail (rhaystack)) + /* No match. */ + return NULL; + comparison_count++; + if (!mb_equal (mbui_cur (rhaystack), mbui_cur (rneedle))) + /* Nothing in this round. */ + break; + } + } + } + } + else + return (char *) haystack; + } + else + { + if (*needle != '\0') + { + /* Minimizing the worst-case complexity: + Let n = strlen(haystack), m = strlen(needle). + The naïve algorithm is O(n*m) worst-case. + The Knuth-Morris-Pratt algorithm is O(n) worst-case but it needs a + memory allocation. + To achieve linear complexity and yet amortize the cost of the + memory allocation, we activate the Knuth-Morris-Pratt algorithm + only once the naïve algorithm has already run for some time; more + precisely, when + - the outer loop count is >= 10, + - the average number of comparisons per outer loop is >= 5, + - the total number of comparisons is >= m. + But we try it only once. If the memory allocation attempt failed, + we don't retry it. */ + bool try_kmp = true; + size_t outer_loop_count = 0; + size_t comparison_count = 0; + size_t last_ccount = 0; /* last comparison count */ + const char *needle_last_ccount = needle; /* = needle + last_ccount */ + + /* Speed up the following searches of needle by caching its first + character. */ + char b = *needle++; + + for (;; haystack++) + { + if (*haystack == '\0') + /* No match. */ + return NULL; + + /* See whether it's advisable to use an asymptotically faster + algorithm. */ + if (try_kmp + && outer_loop_count >= 10 + && comparison_count >= 5 * outer_loop_count) + { + /* See if needle + comparison_count now reaches the end of + needle. */ + if (needle_last_ccount != NULL) + { + needle_last_ccount += + strnlen (needle_last_ccount, + comparison_count - last_ccount); + if (*needle_last_ccount == '\0') + needle_last_ccount = NULL; + last_ccount = comparison_count; + } + if (needle_last_ccount == NULL) + { + /* Try the Knuth-Morris-Pratt algorithm. */ + const unsigned char *result; + bool success = + knuth_morris_pratt ((const unsigned char *) haystack, + (const unsigned char *) (needle - 1), + strlen (needle - 1), + &result); + if (success) + return (char *) result; + try_kmp = false; + } + } + + outer_loop_count++; + comparison_count++; + if (*haystack == b) + /* The first character matches. */ + { + const char *rhaystack = haystack + 1; + const char *rneedle = needle; + + for (;; rhaystack++, rneedle++) + { + if (*rneedle == '\0') + /* Found a match. */ + return (char *) haystack; + if (*rhaystack == '\0') + /* No match. */ + return NULL; + comparison_count++; + if (*rhaystack != *rneedle) + /* Nothing in this round. */ + break; + } + } + } + } + else + return (char *) haystack; + } +} diff --git a/gettext-tools/gnulib-lib/mbswidth.c b/gettext-tools/gnulib-lib/mbswidth.c new file mode 100644 index 0000000..d39067a --- /dev/null +++ b/gettext-tools/gnulib-lib/mbswidth.c @@ -0,0 +1,193 @@ +/* Determine the number of screen columns needed for a string. + Copyright (C) 2000-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Written by Bruno Haible . */ + +#include + +/* Specification. */ +#include "mbswidth.h" + +/* Get MB_CUR_MAX. */ +#include + +#include + +/* Get isprint(). */ +#include + +/* Get mbstate_t, mbrtowc(), mbsinit(), wcwidth(). */ +#include + +/* Get iswcntrl(). */ +#include + +/* Get INT_MAX. */ +#include + +/* Returns the number of columns needed to represent the multibyte + character string pointed to by STRING. If a non-printable character + occurs, and MBSW_REJECT_UNPRINTABLE is specified, -1 is returned. + With flags = MBSW_REJECT_INVALID | MBSW_REJECT_UNPRINTABLE, this is + the multibyte analogue of the wcswidth function. */ +int +mbswidth (const char *string, int flags) +{ + return mbsnwidth (string, strlen (string), flags); +} + +/* Returns the number of columns needed to represent the multibyte + character string pointed to by STRING of length NBYTES. If a + non-printable character occurs, and MBSW_REJECT_UNPRINTABLE is + specified, -1 is returned. */ +int +mbsnwidth (const char *string, size_t nbytes, int flags) +{ + const char *p = string; + const char *plimit = p + nbytes; + int width; + + width = 0; + if (MB_CUR_MAX > 1) + { + while (p < plimit) + switch (*p) + { + case ' ': case '!': case '"': case '#': case '%': + case '&': case '\'': case '(': case ')': case '*': + case '+': case ',': case '-': case '.': case '/': + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + case ':': case ';': case '<': case '=': case '>': + case '?': + case 'A': case 'B': case 'C': case 'D': case 'E': + case 'F': case 'G': case 'H': case 'I': case 'J': + case 'K': case 'L': case 'M': case 'N': case 'O': + case 'P': case 'Q': case 'R': case 'S': case 'T': + case 'U': case 'V': case 'W': case 'X': case 'Y': + case 'Z': + case '[': case '\\': case ']': case '^': case '_': + case 'a': case 'b': case 'c': case 'd': case 'e': + case 'f': case 'g': case 'h': case 'i': case 'j': + case 'k': case 'l': case 'm': case 'n': case 'o': + case 'p': case 'q': case 'r': case 's': case 't': + case 'u': case 'v': case 'w': case 'x': case 'y': + case 'z': case '{': case '|': case '}': case '~': + /* These characters are printable ASCII characters. */ + p++; + width++; + break; + default: + /* If we have a multibyte sequence, scan it up to its end. */ + { + mbstate_t mbstate; + memset (&mbstate, 0, sizeof mbstate); + do + { + wchar_t wc; + size_t bytes; + int w; + + bytes = mbrtowc (&wc, p, plimit - p, &mbstate); + + if (bytes == (size_t) -1) + /* An invalid multibyte sequence was encountered. */ + { + if (!(flags & MBSW_REJECT_INVALID)) + { + p++; + width++; + break; + } + else + return -1; + } + + if (bytes == (size_t) -2) + /* An incomplete multibyte character at the end. */ + { + if (!(flags & MBSW_REJECT_INVALID)) + { + p = plimit; + width++; + break; + } + else + return -1; + } + + if (bytes == 0) + /* A null wide character was encountered. */ + bytes = 1; + + w = wcwidth (wc); + if (w >= 0) + /* A printable multibyte character. */ + { + if (w > INT_MAX - width) + goto overflow; + width += w; + } + else + /* An unprintable multibyte character. */ + if (!(flags & MBSW_REJECT_UNPRINTABLE)) + { + if (!iswcntrl (wc)) + { + if (width == INT_MAX) + goto overflow; + width++; + } + } + else + return -1; + + p += bytes; + } + while (! mbsinit (&mbstate)); + } + break; + } + return width; + } + + while (p < plimit) + { + unsigned char c = (unsigned char) *p++; + + if (isprint (c)) + { + if (width == INT_MAX) + goto overflow; + width++; + } + else if (!(flags & MBSW_REJECT_UNPRINTABLE)) + { + if (!iscntrl (c)) + { + if (width == INT_MAX) + goto overflow; + width++; + } + } + else + return -1; + } + return width; + + overflow: + return INT_MAX; +} diff --git a/gettext-tools/gnulib-lib/mbswidth.h b/gettext-tools/gnulib-lib/mbswidth.h new file mode 100644 index 0000000..ab7c150 --- /dev/null +++ b/gettext-tools/gnulib-lib/mbswidth.h @@ -0,0 +1,60 @@ +/* Determine the number of screen columns needed for a string. + Copyright (C) 2000-2004, 2007, 2009-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Avoid a clash of our mbswidth() with a function of the same name defined + in UnixWare 7.1.1 . We need this #include before the #define + below. + However, we don't want to #include on all platforms because + - Tru64 with Desktop Toolkit C has a bug: must be included before + . + - BSD/OS 4.1 has a bug: and must be included before + . */ +#if HAVE_DECL_MBSWIDTH_IN_WCHAR_H +# include +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Optional flags to influence mbswidth/mbsnwidth behavior. */ + +/* If this bit is set, return -1 upon finding an invalid or incomplete + character. Otherwise, assume invalid characters have width 1. */ +#define MBSW_REJECT_INVALID 1 + +/* If this bit is set, return -1 upon finding a non-printable character. + Otherwise, assume unprintable characters have width 0 if they are + control characters and 1 otherwise. */ +#define MBSW_REJECT_UNPRINTABLE 2 + + +/* Returns the number of screen columns needed for STRING. */ +#define mbswidth gnu_mbswidth /* avoid clash with UnixWare 7.1.1 function */ +extern int mbswidth (const char *string, int flags); + +/* Returns the number of screen columns needed for the NBYTES bytes + starting at BUF. */ +extern int mbsnwidth (const char *buf, size_t nbytes, int flags); + + +#ifdef __cplusplus +} +#endif diff --git a/gettext-tools/gnulib-lib/mbuiter.c b/gettext-tools/gnulib-lib/mbuiter.c new file mode 100644 index 0000000..9167580 --- /dev/null +++ b/gettext-tools/gnulib-lib/mbuiter.c @@ -0,0 +1,3 @@ +#include +#define MBUITER_INLINE _GL_EXTERN_INLINE +#include "mbuiter.h" diff --git a/gettext-tools/gnulib-lib/mbuiter.h b/gettext-tools/gnulib-lib/mbuiter.h new file mode 100644 index 0000000..1702f14 --- /dev/null +++ b/gettext-tools/gnulib-lib/mbuiter.h @@ -0,0 +1,232 @@ +/* Iterating through multibyte strings: macros for multi-byte encodings. + Copyright (C) 2001, 2005, 2007, 2009-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Written by Bruno Haible . */ + +/* The macros in this file implement forward iteration through a + multi-byte string, without knowing its length a-priori. + + With these macros, an iteration loop that looks like + + char *iter; + for (iter = buf; *iter != '\0'; iter++) + { + do_something (*iter); + } + + becomes + + mbui_iterator_t iter; + for (mbui_init (iter, buf); mbui_avail (iter); mbui_advance (iter)) + { + do_something (mbui_cur_ptr (iter), mb_len (mbui_cur (iter))); + } + + The benefit of these macros over plain use of mbrtowc is: + - Handling of invalid multibyte sequences is possible without + making the code more complicated, while still preserving the + invalid multibyte sequences. + + Compared to mbiter.h, the macros here don't need to know the string's + length a-priori. The downside is that at each step, the look-ahead + that guards against overrunning the terminating '\0' is more expensive. + The mbui_* macros are therefore suitable when there is a high probability + that only the first few multibyte characters need to be inspected. + Whereas the mbi_* macros are better if usually the iteration runs + through the entire string. + + mbui_iterator_t + is a type usable for variable declarations. + + mbui_init (iter, startptr) + initializes the iterator, starting at startptr. + + mbui_avail (iter) + returns true if there are more multibyte characters available before + the end of string is reached. In this case, mbui_cur (iter) is + initialized to the next multibyte character. + + mbui_advance (iter) + advances the iterator by one multibyte character. + + mbui_cur (iter) + returns the current multibyte character, of type mbchar_t. All the + macros defined in mbchar.h can be used on it. + + mbui_cur_ptr (iter) + return a pointer to the beginning of the current multibyte character. + + mbui_reloc (iter, ptrdiff) + relocates iterator when the string is moved by ptrdiff bytes. + + mbui_copy (&destiter, &srciter) + copies srciter to destiter. + + Here are the function prototypes of the macros. + + extern void mbui_init (mbui_iterator_t iter, const char *startptr); + extern bool mbui_avail (mbui_iterator_t iter); + extern void mbui_advance (mbui_iterator_t iter); + extern mbchar_t mbui_cur (mbui_iterator_t iter); + extern const char * mbui_cur_ptr (mbui_iterator_t iter); + extern void mbui_reloc (mbui_iterator_t iter, ptrdiff_t ptrdiff); + extern void mbui_copy (mbui_iterator_t *new, const mbui_iterator_t *old); + */ + +#ifndef _MBUITER_H +#define _MBUITER_H 1 + +#include +#include +#include +#include +#include + +/* Tru64 with Desktop Toolkit C has a bug: must be included before + . + BSD/OS 4.1 has a bug: and must be included before + . */ +#include +#include +#include + +#include "mbchar.h" +#include "strnlen1.h" + +#ifndef _GL_INLINE_HEADER_BEGIN + #error "Please include config.h first." +#endif +_GL_INLINE_HEADER_BEGIN +#ifndef MBUITER_INLINE +# define MBUITER_INLINE _GL_INLINE +#endif + +struct mbuiter_multi +{ + bool in_shift; /* true if next byte may not be interpreted as ASCII */ + mbstate_t state; /* if in_shift: current shift state */ + bool next_done; /* true if mbui_avail has already filled the following */ + struct mbchar cur; /* the current character: + const char *cur.ptr pointer to current character + The following are only valid after mbui_avail. + size_t cur.bytes number of bytes of current character + bool cur.wc_valid true if wc is a valid wide character + wchar_t cur.wc if wc_valid: the current character + */ +}; + +MBUITER_INLINE void +mbuiter_multi_next (struct mbuiter_multi *iter) +{ + if (iter->next_done) + return; + if (iter->in_shift) + goto with_shift; + /* Handle most ASCII characters quickly, without calling mbrtowc(). */ + if (is_basic (*iter->cur.ptr)) + { + /* These characters are part of the basic character set. ISO C 99 + guarantees that their wide character code is identical to their + char code. */ + iter->cur.bytes = 1; + iter->cur.wc = *iter->cur.ptr; + iter->cur.wc_valid = true; + } + else + { + assert (mbsinit (&iter->state)); + iter->in_shift = true; + with_shift: + iter->cur.bytes = mbrtowc (&iter->cur.wc, iter->cur.ptr, + strnlen1 (iter->cur.ptr, MB_CUR_MAX), + &iter->state); + if (iter->cur.bytes == (size_t) -1) + { + /* An invalid multibyte sequence was encountered. */ + iter->cur.bytes = 1; + iter->cur.wc_valid = false; + /* Whether to set iter->in_shift = false and reset iter->state + or not is not very important; the string is bogus anyway. */ + } + else if (iter->cur.bytes == (size_t) -2) + { + /* An incomplete multibyte character at the end. */ + iter->cur.bytes = strlen (iter->cur.ptr); + iter->cur.wc_valid = false; + /* Whether to set iter->in_shift = false and reset iter->state + or not is not important; the string end is reached anyway. */ + } + else + { + if (iter->cur.bytes == 0) + { + /* A null wide character was encountered. */ + iter->cur.bytes = 1; + assert (*iter->cur.ptr == '\0'); + assert (iter->cur.wc == 0); + } + iter->cur.wc_valid = true; + + /* When in the initial state, we can go back treating ASCII + characters more quickly. */ + if (mbsinit (&iter->state)) + iter->in_shift = false; + } + } + iter->next_done = true; +} + +MBUITER_INLINE void +mbuiter_multi_reloc (struct mbuiter_multi *iter, ptrdiff_t ptrdiff) +{ + iter->cur.ptr += ptrdiff; +} + +MBUITER_INLINE void +mbuiter_multi_copy (struct mbuiter_multi *new_iter, const struct mbuiter_multi *old_iter) +{ + if ((new_iter->in_shift = old_iter->in_shift)) + memcpy (&new_iter->state, &old_iter->state, sizeof (mbstate_t)); + else + memset (&new_iter->state, 0, sizeof (mbstate_t)); + new_iter->next_done = old_iter->next_done; + mb_copy (&new_iter->cur, &old_iter->cur); +} + +/* Iteration macros. */ +typedef struct mbuiter_multi mbui_iterator_t; +#define mbui_init(iter, startptr) \ + ((iter).cur.ptr = (startptr), \ + (iter).in_shift = false, memset (&(iter).state, '\0', sizeof (mbstate_t)), \ + (iter).next_done = false) +#define mbui_avail(iter) \ + (mbuiter_multi_next (&(iter)), !mb_isnul ((iter).cur)) +#define mbui_advance(iter) \ + ((iter).cur.ptr += (iter).cur.bytes, (iter).next_done = false) + +/* Access to the current character. */ +#define mbui_cur(iter) (iter).cur +#define mbui_cur_ptr(iter) (iter).cur.ptr + +/* Relocation. */ +#define mbui_reloc(iter, ptrdiff) mbuiter_multi_reloc (&iter, ptrdiff) + +/* Copying an iterator. */ +#define mbui_copy mbuiter_multi_copy + +_GL_INLINE_HEADER_END + +#endif /* _MBUITER_H */ diff --git a/gettext-tools/gnulib-lib/memchr.c b/gettext-tools/gnulib-lib/memchr.c new file mode 100644 index 0000000..6709f6e --- /dev/null +++ b/gettext-tools/gnulib-lib/memchr.c @@ -0,0 +1,172 @@ +/* Copyright (C) 1991, 1993, 1996-1997, 1999-2000, 2003-2004, 2006, 2008-2014 + Free Software Foundation, Inc. + + Based on strlen implementation by Torbjorn Granlund (tege@sics.se), + with help from Dan Sahlin (dan@sics.se) and + commentary by Jim Blandy (jimb@ai.mit.edu); + adaptation to memchr suggested by Dick Karpinski (dick@cca.ucsf.edu), + and implemented by Roland McGrath (roland@ai.mit.edu). + +NOTE: The canonical source of this file is maintained with the GNU C Library. +Bugs can be reported to bug-glibc@prep.ai.mit.edu. + +This program is free software: you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 3 of the License, or any +later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . */ + +#ifndef _LIBC +# include +#endif + +#include + +#include + +#if defined _LIBC +# include +#else +# define reg_char char +#endif + +#include + +#if HAVE_BP_SYM_H || defined _LIBC +# include +#else +# define BP_SYM(sym) sym +#endif + +#undef __memchr +#ifdef _LIBC +# undef memchr +#endif + +#ifndef weak_alias +# define __memchr memchr +#endif + +/* Search no more than N bytes of S for C. */ +void * +__memchr (void const *s, int c_in, size_t n) +{ + /* On 32-bit hardware, choosing longword to be a 32-bit unsigned + long instead of a 64-bit uintmax_t tends to give better + performance. On 64-bit hardware, unsigned long is generally 64 + bits already. Change this typedef to experiment with + performance. */ + typedef unsigned long int longword; + + const unsigned char *char_ptr; + const longword *longword_ptr; + longword repeated_one; + longword repeated_c; + unsigned reg_char c; + + c = (unsigned char) c_in; + + /* Handle the first few bytes by reading one byte at a time. + Do this until CHAR_PTR is aligned on a longword boundary. */ + for (char_ptr = (const unsigned char *) s; + n > 0 && (size_t) char_ptr % sizeof (longword) != 0; + --n, ++char_ptr) + if (*char_ptr == c) + return (void *) char_ptr; + + longword_ptr = (const longword *) char_ptr; + + /* All these elucidatory comments refer to 4-byte longwords, + but the theory applies equally well to any size longwords. */ + + /* Compute auxiliary longword values: + repeated_one is a value which has a 1 in every byte. + repeated_c has c in every byte. */ + repeated_one = 0x01010101; + repeated_c = c | (c << 8); + repeated_c |= repeated_c << 16; + if (0xffffffffU < (longword) -1) + { + repeated_one |= repeated_one << 31 << 1; + repeated_c |= repeated_c << 31 << 1; + if (8 < sizeof (longword)) + { + size_t i; + + for (i = 64; i < sizeof (longword) * 8; i *= 2) + { + repeated_one |= repeated_one << i; + repeated_c |= repeated_c << i; + } + } + } + + /* Instead of the traditional loop which tests each byte, we will test a + longword at a time. The tricky part is testing if *any of the four* + bytes in the longword in question are equal to c. We first use an xor + with repeated_c. This reduces the task to testing whether *any of the + four* bytes in longword1 is zero. + + We compute tmp = + ((longword1 - repeated_one) & ~longword1) & (repeated_one << 7). + That is, we perform the following operations: + 1. Subtract repeated_one. + 2. & ~longword1. + 3. & a mask consisting of 0x80 in every byte. + Consider what happens in each byte: + - If a byte of longword1 is zero, step 1 and 2 transform it into 0xff, + and step 3 transforms it into 0x80. A carry can also be propagated + to more significant bytes. + - If a byte of longword1 is nonzero, let its lowest 1 bit be at + position k (0 <= k <= 7); so the lowest k bits are 0. After step 1, + the byte ends in a single bit of value 0 and k bits of value 1. + After step 2, the result is just k bits of value 1: 2^k - 1. After + step 3, the result is 0. And no carry is produced. + So, if longword1 has only non-zero bytes, tmp is zero. + Whereas if longword1 has a zero byte, call j the position of the least + significant zero byte. Then the result has a zero at positions 0, ..., + j-1 and a 0x80 at position j. We cannot predict the result at the more + significant bytes (positions j+1..3), but it does not matter since we + already have a non-zero bit at position 8*j+7. + + So, the test whether any byte in longword1 is zero is equivalent to + testing whether tmp is nonzero. */ + + while (n >= sizeof (longword)) + { + longword longword1 = *longword_ptr ^ repeated_c; + + if ((((longword1 - repeated_one) & ~longword1) + & (repeated_one << 7)) != 0) + break; + longword_ptr++; + n -= sizeof (longword); + } + + char_ptr = (const unsigned char *) longword_ptr; + + /* At this point, we know that either n < sizeof (longword), or one of the + sizeof (longword) bytes starting at char_ptr is == c. On little-endian + machines, we could determine the first such byte without any further + memory accesses, just by looking at the tmp result from the last loop + iteration. But this does not work on big-endian machines. Choose code + that works in both cases. */ + + for (; n > 0; --n, ++char_ptr) + { + if (*char_ptr == c) + return (void *) char_ptr; + } + + return NULL; +} +#ifdef weak_alias +weak_alias (__memchr, BP_SYM (memchr)) +#endif diff --git a/gettext-tools/gnulib-lib/memchr.valgrind b/gettext-tools/gnulib-lib/memchr.valgrind new file mode 100644 index 0000000..60f247e --- /dev/null +++ b/gettext-tools/gnulib-lib/memchr.valgrind @@ -0,0 +1,14 @@ +# Suppress a valgrind message about use of uninitialized memory in memchr(). +# POSIX states that when the character is found, memchr must not read extra +# bytes in an overestimated length (for example, where memchr is used to +# implement strnlen). However, we use a safe word read to provide a speedup. +{ + memchr-value4 + Memcheck:Value4 + fun:rpl_memchr +} +{ + memchr-value8 + Memcheck:Value8 + fun:rpl_memchr +} diff --git a/gettext-tools/gnulib-lib/memmove.c b/gettext-tools/gnulib-lib/memmove.c new file mode 100644 index 0000000..0f04054 --- /dev/null +++ b/gettext-tools/gnulib-lib/memmove.c @@ -0,0 +1,26 @@ +/* memmove.c -- copy memory. + Copy LENGTH bytes from SOURCE to DEST. Does not null-terminate. + In the public domain. + By David MacKenzie . */ + +#include + +#include + +void * +memmove (void *dest0, void const *source0, size_t length) +{ + char *dest = dest0; + char const *source = source0; + if (source < dest) + /* Moving from low mem to hi mem; start at end. */ + for (source += length, dest += length; length; --length) + *--dest = *--source; + else if (source != dest) + { + /* Moving from hi mem to low mem; start at beginning. */ + for (; length; --length) + *dest++ = *source++; + } + return dest0; +} diff --git a/gettext-tools/gnulib-lib/memset.c b/gettext-tools/gnulib-lib/memset.c new file mode 100644 index 0000000..e995f37 --- /dev/null +++ b/gettext-tools/gnulib-lib/memset.c @@ -0,0 +1,29 @@ +/* memset.c -- set an area of memory to a given value + Copyright (C) 1991, 2003, 2009-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . */ + +#include + +#include + +void * +memset (void *str, int c, size_t len) +{ + register char *st = str; + + while (len-- > 0) + *st++ = c; + return str; +} diff --git a/gettext-tools/gnulib-lib/minmax.h b/gettext-tools/gnulib-lib/minmax.h new file mode 100644 index 0000000..af1fc9b --- /dev/null +++ b/gettext-tools/gnulib-lib/minmax.h @@ -0,0 +1,60 @@ +/* MIN, MAX macros. + Copyright (C) 1995, 1998, 2001, 2003, 2005, 2009-2014 Free Software + Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . */ + +#ifndef _MINMAX_H +#define _MINMAX_H + +/* Note: MIN, MAX are also defined in on some systems + (glibc, IRIX, HP-UX, OSF/1). Therefore you might get warnings about + MIN, MAX macro redefinitions on some systems; the workaround is to + #include this file as the last one among the #include list. */ + +/* Before we define the following symbols we get the file + since otherwise we get redefinitions on some systems if is + included after this file. Likewise for . + If more than one of these system headers define MIN and MAX, pick just + one of the headers (because the definitions most likely are the same). */ +#if HAVE_MINMAX_IN_LIMITS_H +# include +#elif HAVE_MINMAX_IN_SYS_PARAM_H +# include +#endif + +/* Note: MIN and MAX should be used with two arguments of the + same type. They might not return the minimum and maximum of their two + arguments, if the arguments have different types or have unusual + floating-point values. For example, on a typical host with 32-bit 'int', + 64-bit 'long long', and 64-bit IEEE 754 'double' types: + + MAX (-1, 2147483648) returns 4294967295. + MAX (9007199254740992.0, 9007199254740993) returns 9007199254740992.0. + MAX (NaN, 0.0) returns 0.0. + MAX (+0.0, -0.0) returns -0.0. + + and in each case the answer is in some sense bogus. */ + +/* MAX(a,b) returns the maximum of A and B. */ +#ifndef MAX +# define MAX(a,b) ((a) > (b) ? (a) : (b)) +#endif + +/* MIN(a,b) returns the minimum of A and B. */ +#ifndef MIN +# define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif + +#endif /* _MINMAX_H */ diff --git a/gettext-tools/gnulib-lib/mkdtemp.c b/gettext-tools/gnulib-lib/mkdtemp.c new file mode 100644 index 0000000..18237f2 --- /dev/null +++ b/gettext-tools/gnulib-lib/mkdtemp.c @@ -0,0 +1,39 @@ +/* Copyright (C) 1999, 2001-2003, 2006-2007, 2009-2014 Free Software + Foundation, Inc. + This file is part of the GNU C Library. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Extracted from misc/mkdtemp.c. */ + +#include + +/* Specification. */ +#include + +#include "tempname.h" + +/* Generate a unique temporary directory from XTEMPLATE. + The last six characters of XTEMPLATE must be "XXXXXX"; + they are replaced with a string that makes the filename unique. + The directory is created, mode 700, and its name is returned. + (This function comes from OpenBSD.) */ +char * +mkdtemp (char *xtemplate) +{ + if (gen_tempname (xtemplate, 0, 0, GT_DIR)) + return NULL; + else + return xtemplate; +} diff --git a/gettext-tools/gnulib-lib/moo.h b/gettext-tools/gnulib-lib/moo.h new file mode 100644 index 0000000..a1ea917 --- /dev/null +++ b/gettext-tools/gnulib-lib/moo.h @@ -0,0 +1,248 @@ +/* Minimal object-oriented facilities for C. + Copyright (C) 2006 Free Software Foundation, Inc. + Written by Bruno Haible , 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* This file defines minimal facilities for object-oriented programming + style in ANSI C. + + The facilities allow to define classes with single inheritance and + "virtual" methods. + + Strict type checking is provided in combination with a C++ compiler: + The code compiles in ANSI C with less strict type checking; when + compiled with a C++ compiler, strict type checking is done. + + In contrast to [OOC] and [OOPC], this implementation concentrates on the + bare essentials of an object-oriented programming style. It does not + provide features that are "sometimes useful", but not essential. + + Features: + - Combination of fields and methods into a single object. YES + - Description of objects of same shape and same behaviour + by a class. YES + - Single inheritance. YES + - Multiple inheritance. NO + - Operator overloading (compile-time polymorphism). NO + - Virtual methods (run-time polymorphism). YES + - Information hiding: private/protected/public. private fields + - Static fields and methods. NO + - Constructors, destructors. NO + - 'new', 'delete'. NO + - Exception handling. NO + - Garbage collection. NO + - Templates / Generic classes with parameters. NO + - Namespaces. NO + - Hidden 'this' pointer in methods. NO + - Declaring or implementing several classes in the same file. NO + + Rationale for NO: + - Multiple inheritance is not supported because programming languages + like Java and C# prove that they are not necessary. Modern design + patterns use delegation more often than composition; this reduces + the pressure to use multiple inheritance. + Multiple inheritance of "interfaces" (classes without fields) might + be considered, though. + - Operator overloading is not essential: The programmer can rename + methods so that they carry unambiguous method names. This also makes + the code more readable. + - Virtual methods are supported. Non-virtual methods are not: they + constitute an assumption about the possible subclasses which is more + often wrong than right. In other words, non-virtual methods are a + premature optimization - "the root of all evil", according to + Donald E. Knuth. + - Information hiding: 'protected' is not supported because it is always + inappropriate: it prohibits the use of the delegation design pattern. + 'private' is implemented on fields. There are no 'public' fields, + since the use of getters/setters allows for overriding in subclasses + and is more maintainable (ability to set breakpoints). On the other + hand, all methods are 'public'. 'private` methods are not supported + because methods with static linkage can be used instead. + - Static fields and methods are not supported because normal variables + and functions with static or extern linkage can be used instead. + - Constructors and destructors are not supported. The programmer can + define 'init' and 'do_free' methods himself. + - 'new', 'delete' are not supported because they only provide the + grouping of two lines of code into a single line of code. + - Exception handling is not supported because conventions with a return + code can be used instead. + - Garbage collection is not supported. Without it the programmer's life + is harder, but not impossible. The programmer has to think about + ownership of objects. + - Templates / Generic classes with parameters are not supported because + they are mostly used for container classes, and container classes can + be implemented in a simpler object-oriented way that requires only a + very limited form of class inheritance. + - Namespaces are not implemented, because they can be simulated by a + consistent naming convention. + - A hidden 'this' pointer in methods is not implemented. It reduces the + transparency of the code (because what looks like a variable access can + be an access through 'this') and is simply not needed. + - Declaring or implementing several classes in the same file is not + supported, because it is anyway good practice to define each class in + its own .oo.h / .oo.c file. + + Syntax: + + The syntax resembles C++, but deviates from C++ where the C++ syntax is + just too braindead. + + A root class is declared in a .oo.h file: + + struct rootfoo + { + methods: + int method1 (rootfoo_t x, ...); ... + }; + + and in the corresponding .oo.c file: + + struct rootfoo + { + fields: + int field1; ... + }; + + A subclass is declared in a .oo.h file as well: + + struct subclass : struct rootfoo + { + methods: + int method2 (subclass_t x, ...); ... + }; + + and in the corresponding .oo.c file: + + struct subclass : struct rootfoo + { + fields: + int field2; ... + }; + + This defines: + - An incomplete type 'struct any_rootfoo_representation' or + 'struct subclass_representation', respectively. It denotes the memory + occupied by an object of the respective class. The prefix 'any_' is + present only for a root class. + - A type 'rootfoo_t' or 'subclass_t' that is equivalent to a pointer + 'struct any_rootfoo_representation *' or + 'struct subclass_representation *', respectively. + - A type 'struct rootfoo_implementation' or + 'struct subclass_implementation', respectively. It contains a virtual + function table for the corresponding type. + - A type 'struct rootfoo_representation_header' or + 'struct subclass_representation_header', respectively, that defines + the part of the memory representation containing the virtual function + table pointer. + - Functions 'rootfoo_method1 (rootfoo_t x, ...);' ... + 'subclass_method1 (subclass_t x, ...);' ... + 'subclass_method2 (subclass_t x, ...);' ... + that invoke the corresponding methods. They are realized as inline + functions if possible. + - A declaration of 'rootfoo_typeinfo' or 'subclass_typeinfo', respectively, + each being a typeinfo_t instance. + - A declaration of 'ROOTFOO_SUPERCLASSES' or 'SUBCLASS_SUPERCLASSES', + respectively, each being an initializer for an array of typeinfo_t. + - A declaration of 'ROOTFOO_SUPERCLASSES_LENGTH' or + 'SUBCLASS_SUPERCLASSES_LENGTH', respectively, each denoting the length + of that initializer. + - A declaration of 'rootfoo_vtable' or 'subclass_vtable', respectively, + being an instance of 'struct rootfoo_implementation' or + 'struct subclass_implementation', respectively. + - A header file "rootfoo.priv.h" or "subclass.priv.h" that defines the + private fields of 'struct rootfoo_representation' or + 'struct subclass_representation', respectively. + + A class implementation looks like this, in a .oo.c file: + + struct subclass : struct rootfoo + { + fields: + int field2; ... + }; + + int subclass::method1 (subclass_t x, ...) { ... } [optional] + int subclass::method2 (subclass_t x, ...) { ... } + ... + + At the place of the second "struct subclass" definition, the type + 'struct subclass_representation' is expanded, and the macro 'super' is + defined, referring to the vtable of the superclass. For root classes, + 'super' is not defined. Also, 'subclass_typeinfo' is defined. + + Each method subclass::method_i defines the implementation of a method + for the particular class. Its C name is subclass__method_i (not to be + confused with subclass_method_i, which is the externally visible function + that invokes this method). + + Methods that are not defined implicitly inherited from the superclass. + + At the end of the file, 'subclass_vtable' is defined, as well as + 'subclass_method1 (subclass_t x, ...);' ... + 'subclass_method2 (subclass_t x, ...);' ... + if they were not already defined as inline functions in the header file. + + Object representation in memory: + - Objects have as their first field, called 'vtable', a pointer to a table + to data and function pointers that depend only on the class, not on the + object instance. + - One of the first fields of the vtable is a pointer to the + 'superclasses'; this is a NULL-terminated array of pointers to + typeinfo_t objects, starting with the class itself, then its + superclass etc. + + + [OOC] Axel-Tobias Schreiner: Object-oriented programming with ANSI-C. 1993. + + [OOPC] Laurent Deniau: Object Oriented Programming in C. 2001. + + */ + +#ifndef _MOO_H +#define _MOO_H + +/* Get size_t, abort(). */ +#include + +/* An object of this type is defined for each class. */ +typedef struct +{ + const char *classname; +} typeinfo_t; + +/* IS_INSTANCE (OBJ, ROOTCLASSNAME, CLASSNAME) + tests whether an object is instance of a given class, given as lower case + class name. */ +#define IS_INSTANCE(obj,rootclassname,classname) \ + (((const struct rootclassname##_representation_header *)(const struct any_##rootclassname##_representation *)(obj))->vtable->superclasses_length \ + >= classname##_SUPERCLASSES_LENGTH \ + && ((const struct rootclassname##_representation_header *)(const struct any_##rootclassname##_representation *)(obj))->vtable->superclasses \ + [((const struct rootclassname##_representation_header *)(const struct any_##rootclassname##_representation *)(obj))->vtable->superclasses_length \ + - classname##_SUPERCLASSES_LENGTH] \ + == & classname##_typeinfo) +/* This instance test consists of two comparisons. One could even optimize + this to a single comparison, by limiting the inheritance depth to a fixed + limit, for example, say, depth <= 10. The superclasses list would then + need to be stored in reverse order, from the root down to the class itself, + and be filled up with NULLs so that the array has length 10. The instance + test would look like this: + #define IS_INSTANCE(obj,rootclassname,classname) \ + (((const struct rootclassname##_representation_header *)(const struct any_##rootclassname##_representation *)(obj))->vtable->superclasses \ + [classname##_SUPERCLASSES_LENGTH - 1] \ + == & classname##_typeinfo) + but the classname##_superclasses_length would no longer be available as a + simple sizeof expression. */ + +#endif /* _MOO_H */ diff --git a/gettext-tools/gnulib-lib/msvc-inval.c b/gettext-tools/gnulib-lib/msvc-inval.c new file mode 100644 index 0000000..f83827f --- /dev/null +++ b/gettext-tools/gnulib-lib/msvc-inval.c @@ -0,0 +1,129 @@ +/* Invalid parameter handler for MSVC runtime libraries. + Copyright (C) 2011-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, see . */ + +#include + +/* Specification. */ +#include "msvc-inval.h" + +#if HAVE_MSVC_INVALID_PARAMETER_HANDLER \ + && !(MSVC_INVALID_PARAMETER_HANDLING == SANE_LIBRARY_HANDLING) + +/* Get _invalid_parameter_handler type and _set_invalid_parameter_handler + declaration. */ +# include + +# if MSVC_INVALID_PARAMETER_HANDLING == DEFAULT_HANDLING + +static void __cdecl +gl_msvc_invalid_parameter_handler (const wchar_t *expression, + const wchar_t *function, + const wchar_t *file, + unsigned int line, + uintptr_t dummy) +{ +} + +# else + +/* Get declarations of the native Windows API functions. */ +# define WIN32_LEAN_AND_MEAN +# include + +# if defined _MSC_VER + +static void __cdecl +gl_msvc_invalid_parameter_handler (const wchar_t *expression, + const wchar_t *function, + const wchar_t *file, + unsigned int line, + uintptr_t dummy) +{ + RaiseException (STATUS_GNULIB_INVALID_PARAMETER, 0, 0, NULL); +} + +# else + +/* An index to thread-local storage. */ +static DWORD tls_index; +static int tls_initialized /* = 0 */; + +/* Used as a fallback only. */ +static struct gl_msvc_inval_per_thread not_per_thread; + +struct gl_msvc_inval_per_thread * +gl_msvc_inval_current (void) +{ + if (!tls_initialized) + { + tls_index = TlsAlloc (); + tls_initialized = 1; + } + if (tls_index == TLS_OUT_OF_INDEXES) + /* TlsAlloc had failed. */ + return ¬_per_thread; + else + { + struct gl_msvc_inval_per_thread *pointer = + (struct gl_msvc_inval_per_thread *) TlsGetValue (tls_index); + if (pointer == NULL) + { + /* First call. Allocate a new 'struct gl_msvc_inval_per_thread'. */ + pointer = + (struct gl_msvc_inval_per_thread *) + malloc (sizeof (struct gl_msvc_inval_per_thread)); + if (pointer == NULL) + /* Could not allocate memory. Use the global storage. */ + pointer = ¬_per_thread; + TlsSetValue (tls_index, pointer); + } + return pointer; + } +} + +static void __cdecl +gl_msvc_invalid_parameter_handler (const wchar_t *expression, + const wchar_t *function, + const wchar_t *file, + unsigned int line, + uintptr_t dummy) +{ + struct gl_msvc_inval_per_thread *current = gl_msvc_inval_current (); + if (current->restart_valid) + longjmp (current->restart, 1); + else + /* An invalid parameter notification from outside the gnulib code. + Give the caller a chance to intervene. */ + RaiseException (STATUS_GNULIB_INVALID_PARAMETER, 0, 0, NULL); +} + +# endif + +# endif + +static int gl_msvc_inval_initialized /* = 0 */; + +void +gl_msvc_inval_ensure_handler (void) +{ + if (gl_msvc_inval_initialized == 0) + { + _set_invalid_parameter_handler (gl_msvc_invalid_parameter_handler); + gl_msvc_inval_initialized = 1; + } +} + +#endif diff --git a/gettext-tools/gnulib-lib/msvc-inval.h b/gettext-tools/gnulib-lib/msvc-inval.h new file mode 100644 index 0000000..a0ef540 --- /dev/null +++ b/gettext-tools/gnulib-lib/msvc-inval.h @@ -0,0 +1,222 @@ +/* Invalid parameter handler for MSVC runtime libraries. + Copyright (C) 2011-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, see . */ + +#ifndef _MSVC_INVAL_H +#define _MSVC_INVAL_H + +/* With MSVC runtime libraries with the "invalid parameter handler" concept, + functions like fprintf(), dup2(), or close() crash when the caller passes + an invalid argument. But POSIX wants error codes (such as EINVAL or EBADF) + instead. + This file defines macros that turn such an invalid parameter notification + into a non-local exit. An error code can then be produced at the target + of this exit. You can thus write code like + + TRY_MSVC_INVAL + { + + } + CATCH_MSVC_INVAL + { + + } + DONE_MSVC_INVAL; + + This entire block expands to a single statement. + + The handling of invalid parameters can be done in three ways: + + * The default way, which is reasonable for programs (not libraries): + AC_DEFINE([MSVC_INVALID_PARAMETER_HANDLING], [DEFAULT_HANDLING]) + + * The way for libraries that make "hairy" calls (like close(-1), or + fclose(fp) where fileno(fp) is closed, or simply getdtablesize()): + AC_DEFINE([MSVC_INVALID_PARAMETER_HANDLING], [HAIRY_LIBRARY_HANDLING]) + + * The way for libraries that make no "hairy" calls: + AC_DEFINE([MSVC_INVALID_PARAMETER_HANDLING], [SANE_LIBRARY_HANDLING]) + */ + +#define DEFAULT_HANDLING 0 +#define HAIRY_LIBRARY_HANDLING 1 +#define SANE_LIBRARY_HANDLING 2 + +#if HAVE_MSVC_INVALID_PARAMETER_HANDLER \ + && !(MSVC_INVALID_PARAMETER_HANDLING == SANE_LIBRARY_HANDLING) +/* A native Windows platform with the "invalid parameter handler" concept, + and either DEFAULT_HANDLING or HAIRY_LIBRARY_HANDLING. */ + +# if MSVC_INVALID_PARAMETER_HANDLING == DEFAULT_HANDLING +/* Default handling. */ + +# ifdef __cplusplus +extern "C" { +# endif + +/* Ensure that the invalid parameter handler in installed that just returns. + Because we assume no other part of the program installs a different + invalid parameter handler, this solution is multithread-safe. */ +extern void gl_msvc_inval_ensure_handler (void); + +# ifdef __cplusplus +} +# endif + +# define TRY_MSVC_INVAL \ + do \ + { \ + gl_msvc_inval_ensure_handler (); \ + if (1) +# define CATCH_MSVC_INVAL \ + else +# define DONE_MSVC_INVAL \ + } \ + while (0) + +# else +/* Handling for hairy libraries. */ + +# include + +/* Gnulib can define its own status codes, as described in the page + "Raising Software Exceptions" on microsoft.com + . + Our status codes are composed of + - 0xE0000000, mandatory for all user-defined status codes, + - 0x474E550, a API identifier ("GNU"), + - 0, 1, 2, ..., used to distinguish different status codes from the + same API. */ +# define STATUS_GNULIB_INVALID_PARAMETER (0xE0000000 + 0x474E550 + 0) + +# if defined _MSC_VER +/* A compiler that supports __try/__except, as described in the page + "try-except statement" on microsoft.com + . + With __try/__except, we can use the multithread-safe exception handling. */ + +# ifdef __cplusplus +extern "C" { +# endif + +/* Ensure that the invalid parameter handler in installed that raises a + software exception with code STATUS_GNULIB_INVALID_PARAMETER. + Because we assume no other part of the program installs a different + invalid parameter handler, this solution is multithread-safe. */ +extern void gl_msvc_inval_ensure_handler (void); + +# ifdef __cplusplus +} +# endif + +# define TRY_MSVC_INVAL \ + do \ + { \ + gl_msvc_inval_ensure_handler (); \ + __try +# define CATCH_MSVC_INVAL \ + __except (GetExceptionCode () == STATUS_GNULIB_INVALID_PARAMETER \ + ? EXCEPTION_EXECUTE_HANDLER \ + : EXCEPTION_CONTINUE_SEARCH) +# define DONE_MSVC_INVAL \ + } \ + while (0) + +# else +/* Any compiler. + We can only use setjmp/longjmp. */ + +# include + +# ifdef __cplusplus +extern "C" { +# endif + +struct gl_msvc_inval_per_thread +{ + /* The restart that will resume execution at the code between + CATCH_MSVC_INVAL and DONE_MSVC_INVAL. It is enabled only between + TRY_MSVC_INVAL and CATCH_MSVC_INVAL. */ + jmp_buf restart; + + /* Tells whether the contents of restart is valid. */ + int restart_valid; +}; + +/* Ensure that the invalid parameter handler in installed that passes + control to the gl_msvc_inval_restart if it is valid, or raises a + software exception with code STATUS_GNULIB_INVALID_PARAMETER otherwise. + Because we assume no other part of the program installs a different + invalid parameter handler, this solution is multithread-safe. */ +extern void gl_msvc_inval_ensure_handler (void); + +/* Return a pointer to the per-thread data for the current thread. */ +extern struct gl_msvc_inval_per_thread *gl_msvc_inval_current (void); + +# ifdef __cplusplus +} +# endif + +# define TRY_MSVC_INVAL \ + do \ + { \ + struct gl_msvc_inval_per_thread *msvc_inval_current; \ + gl_msvc_inval_ensure_handler (); \ + msvc_inval_current = gl_msvc_inval_current (); \ + /* First, initialize gl_msvc_inval_restart. */ \ + if (setjmp (msvc_inval_current->restart) == 0) \ + { \ + /* Then, mark it as valid. */ \ + msvc_inval_current->restart_valid = 1; +# define CATCH_MSVC_INVAL \ + /* Execution completed. \ + Mark gl_msvc_inval_restart as invalid. */ \ + msvc_inval_current->restart_valid = 0; \ + } \ + else \ + { \ + /* Execution triggered an invalid parameter notification. \ + Mark gl_msvc_inval_restart as invalid. */ \ + msvc_inval_current->restart_valid = 0; +# define DONE_MSVC_INVAL \ + } \ + } \ + while (0) + +# endif + +# endif + +#else +/* A platform that does not need to the invalid parameter handler, + or when SANE_LIBRARY_HANDLING is desired. */ + +/* The braces here avoid GCC warnings like + "warning: suggest explicit braces to avoid ambiguous 'else'". */ +# define TRY_MSVC_INVAL \ + do \ + { \ + if (1) +# define CATCH_MSVC_INVAL \ + else +# define DONE_MSVC_INVAL \ + } \ + while (0) + +#endif + +#endif /* _MSVC_INVAL_H */ diff --git a/gettext-tools/gnulib-lib/msvc-nothrow.c b/gettext-tools/gnulib-lib/msvc-nothrow.c new file mode 100644 index 0000000..b1e5f0c --- /dev/null +++ b/gettext-tools/gnulib-lib/msvc-nothrow.c @@ -0,0 +1,49 @@ +/* Wrappers that don't throw invalid parameter notifications + with MSVC runtime libraries. + Copyright (C) 2011-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, see . */ + +#include + +/* Specification. */ +#include "msvc-nothrow.h" + +/* Get declarations of the native Windows API functions. */ +#define WIN32_LEAN_AND_MEAN +#include + +#include "msvc-inval.h" + +#undef _get_osfhandle + +#if HAVE_MSVC_INVALID_PARAMETER_HANDLER +intptr_t +_gl_nothrow_get_osfhandle (int fd) +{ + intptr_t result; + + TRY_MSVC_INVAL + { + result = _get_osfhandle (fd); + } + CATCH_MSVC_INVAL + { + result = (intptr_t) INVALID_HANDLE_VALUE; + } + DONE_MSVC_INVAL; + + return result; +} +#endif diff --git a/gettext-tools/gnulib-lib/msvc-nothrow.h b/gettext-tools/gnulib-lib/msvc-nothrow.h new file mode 100644 index 0000000..0d4dea5 --- /dev/null +++ b/gettext-tools/gnulib-lib/msvc-nothrow.h @@ -0,0 +1,43 @@ +/* Wrappers that don't throw invalid parameter notifications + with MSVC runtime libraries. + Copyright (C) 2011-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, see . */ + +#ifndef _MSVC_NOTHROW_H +#define _MSVC_NOTHROW_H + +/* With MSVC runtime libraries with the "invalid parameter handler" concept, + functions like fprintf(), dup2(), or close() crash when the caller passes + an invalid argument. But POSIX wants error codes (such as EINVAL or EBADF) + instead. + This file defines wrappers that turn such an invalid parameter notification + into an error code. */ + +#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ + +/* Get original declaration of _get_osfhandle. */ +# include + +# if HAVE_MSVC_INVALID_PARAMETER_HANDLER + +/* Override _get_osfhandle. */ +extern intptr_t _gl_nothrow_get_osfhandle (int fd); +# define _get_osfhandle _gl_nothrow_get_osfhandle + +# endif + +#endif + +#endif /* _MSVC_NOTHROW_H */ diff --git a/gettext-tools/gnulib-lib/obstack.c b/gettext-tools/gnulib-lib/obstack.c new file mode 100644 index 0000000..fa3cc44 --- /dev/null +++ b/gettext-tools/gnulib-lib/obstack.c @@ -0,0 +1,353 @@ +/* obstack.c - subroutines used implicitly by object stack macros + Copyright (C) 1988-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public + License along with the GNU C Library; if not, see + . */ + + +#ifdef _LIBC +# include +#else +# include +# include "obstack.h" +#endif + +/* NOTE BEFORE MODIFYING THIS FILE: _OBSTACK_INTERFACE_VERSION in + obstack.h must be incremented whenever callers compiled using an old + obstack.h can no longer properly call the functions in this file. */ + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself, and the installed library + supports the same library interface we do. This code is part of the GNU + C Library, but also included in many other GNU distributions. Compiling + and linking in this code is a waste when using the GNU C library + (especially if it is a shared library). Rather than having every GNU + program understand 'configure --with-gnu-libc' and omit the object + files, it is simpler to just do this in the source for each such file. */ +#if !defined _LIBC && defined __GNU_LIBRARY__ && __GNU_LIBRARY__ > 1 +# include +# if (_GNU_OBSTACK_INTERFACE_VERSION == _OBSTACK_INTERFACE_VERSION \ + || (_GNU_OBSTACK_INTERFACE_VERSION == 1 \ + && _OBSTACK_INTERFACE_VERSION == 2 \ + && defined SIZEOF_INT && defined SIZEOF_SIZE_T \ + && SIZEOF_INT == SIZEOF_SIZE_T)) +# define _OBSTACK_ELIDE_CODE +# endif +#endif + +#ifndef _OBSTACK_ELIDE_CODE +/* If GCC, or if an oddball (testing?) host that #defines __alignof__, + use the already-supplied __alignof__. Otherwise, this must be Gnulib + (as glibc assumes GCC); defer to Gnulib's alignof_type. */ +# if !defined __GNUC__ && !defined __alignof__ +# include +# define __alignof__(type) alignof_type (type) +# endif +# include +# include + +# ifndef MAX +# define MAX(a,b) ((a) > (b) ? (a) : (b)) +# endif + +/* Determine default alignment. */ + +/* If malloc were really smart, it would round addresses to DEFAULT_ALIGNMENT. + But in fact it might be less smart and round addresses to as much as + DEFAULT_ROUNDING. So we prepare for it to do that. + + DEFAULT_ALIGNMENT cannot be an enum constant; see gnulib's alignof.h. */ +#define DEFAULT_ALIGNMENT MAX (__alignof__ (long double), \ + MAX (__alignof__ (uintmax_t), \ + __alignof__ (void *))) +#define DEFAULT_ROUNDING MAX (sizeof (long double), \ + MAX (sizeof (uintmax_t), \ + sizeof (void *))) + +/* Call functions with either the traditional malloc/free calling + interface, or the mmalloc/mfree interface (that adds an extra first + argument), based on the value of use_extra_arg. */ + +static void * +call_chunkfun (struct obstack *h, size_t size) +{ + if (h->use_extra_arg) + return h->chunkfun.extra (h->extra_arg, size); + else + return h->chunkfun.plain (size); +} + +static void +call_freefun (struct obstack *h, void *old_chunk) +{ + if (h->use_extra_arg) + h->freefun.extra (h->extra_arg, old_chunk); + else + h->freefun.plain (old_chunk); +} + + +/* Initialize an obstack H for use. Specify chunk size SIZE (0 means default). + Objects start on multiples of ALIGNMENT (0 means use default). + + Return nonzero if successful, calls obstack_alloc_failed_handler if + allocation fails. */ + +static int +_obstack_begin_worker (struct obstack *h, + _OBSTACK_SIZE_T size, _OBSTACK_SIZE_T alignment) +{ + struct _obstack_chunk *chunk; /* points to new chunk */ + + if (alignment == 0) + alignment = DEFAULT_ALIGNMENT; + if (size == 0) + /* Default size is what GNU malloc can fit in a 4096-byte block. */ + { + /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc. + Use the values for range checking, because if range checking is off, + the extra bytes won't be missed terribly, but if range checking is on + and we used a larger request, a whole extra 4096 bytes would be + allocated. + + These number are irrelevant to the new GNU malloc. I suspect it is + less sensitive to the size of the request. */ + int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1)) + + 4 + DEFAULT_ROUNDING - 1) + & ~(DEFAULT_ROUNDING - 1)); + size = 4096 - extra; + } + + h->chunk_size = size; + h->alignment_mask = alignment - 1; + + chunk = h->chunk = call_chunkfun (h, h->chunk_size); + if (!chunk) + (*obstack_alloc_failed_handler) (); + h->next_free = h->object_base = __PTR_ALIGN ((char *) chunk, chunk->contents, + alignment - 1); + h->chunk_limit = chunk->limit = (char *) chunk + h->chunk_size; + chunk->prev = 0; + /* The initial chunk now contains no empty object. */ + h->maybe_empty_object = 0; + h->alloc_failed = 0; + return 1; +} + +int +_obstack_begin (struct obstack *h, + _OBSTACK_SIZE_T size, _OBSTACK_SIZE_T alignment, + void *(*chunkfun) (size_t), + void (*freefun) (void *)) +{ + h->chunkfun.plain = chunkfun; + h->freefun.plain = freefun; + h->use_extra_arg = 0; + return _obstack_begin_worker (h, size, alignment); +} + +int +_obstack_begin_1 (struct obstack *h, + _OBSTACK_SIZE_T size, _OBSTACK_SIZE_T alignment, + void *(*chunkfun) (void *, size_t), + void (*freefun) (void *, void *), + void *arg) +{ + h->chunkfun.extra = chunkfun; + h->freefun.extra = freefun; + h->extra_arg = arg; + h->use_extra_arg = 1; + return _obstack_begin_worker (h, size, alignment); +} + +/* Allocate a new current chunk for the obstack *H + on the assumption that LENGTH bytes need to be added + to the current object, or a new object of length LENGTH allocated. + Copies any partial object from the end of the old chunk + to the beginning of the new one. */ + +void +_obstack_newchunk (struct obstack *h, _OBSTACK_SIZE_T length) +{ + struct _obstack_chunk *old_chunk = h->chunk; + struct _obstack_chunk *new_chunk = 0; + size_t obj_size = h->next_free - h->object_base; + char *object_base; + + /* Compute size for new chunk. */ + size_t sum1 = obj_size + length; + size_t sum2 = sum1 + h->alignment_mask; + size_t new_size = sum2 + (obj_size >> 3) + 100; + if (new_size < sum2) + new_size = sum2; + if (new_size < h->chunk_size) + new_size = h->chunk_size; + + /* Allocate and initialize the new chunk. */ + if (obj_size <= sum1 && sum1 <= sum2) + new_chunk = call_chunkfun (h, new_size); + if (!new_chunk) + (*obstack_alloc_failed_handler)(); + h->chunk = new_chunk; + new_chunk->prev = old_chunk; + new_chunk->limit = h->chunk_limit = (char *) new_chunk + new_size; + + /* Compute an aligned object_base in the new chunk */ + object_base = + __PTR_ALIGN ((char *) new_chunk, new_chunk->contents, h->alignment_mask); + + /* Move the existing object to the new chunk. */ + memcpy (object_base, h->object_base, obj_size); + + /* If the object just copied was the only data in OLD_CHUNK, + free that chunk and remove it from the chain. + But not if that chunk might contain an empty object. */ + if (!h->maybe_empty_object + && (h->object_base + == __PTR_ALIGN ((char *) old_chunk, old_chunk->contents, + h->alignment_mask))) + { + new_chunk->prev = old_chunk->prev; + call_freefun (h, old_chunk); + } + + h->object_base = object_base; + h->next_free = h->object_base + obj_size; + /* The new chunk certainly contains no empty object yet. */ + h->maybe_empty_object = 0; +} + +/* Return nonzero if object OBJ has been allocated from obstack H. + This is here for debugging. + If you use it in a program, you are probably losing. */ + +/* Suppress -Wmissing-prototypes warning. We don't want to declare this in + obstack.h because it is just for debugging. */ +int _obstack_allocated_p (struct obstack *h, void *obj) __attribute_pure__; + +int +_obstack_allocated_p (struct obstack *h, void *obj) +{ + struct _obstack_chunk *lp; /* below addr of any objects in this chunk */ + struct _obstack_chunk *plp; /* point to previous chunk if any */ + + lp = (h)->chunk; + /* We use >= rather than > since the object cannot be exactly at + the beginning of the chunk but might be an empty object exactly + at the end of an adjacent chunk. */ + while (lp != 0 && ((void *) lp >= obj || (void *) (lp)->limit < obj)) + { + plp = lp->prev; + lp = plp; + } + return lp != 0; +} + +/* Free objects in obstack H, including OBJ and everything allocate + more recently than OBJ. If OBJ is zero, free everything in H. */ + +void +_obstack_free (struct obstack *h, void *obj) +{ + struct _obstack_chunk *lp; /* below addr of any objects in this chunk */ + struct _obstack_chunk *plp; /* point to previous chunk if any */ + + lp = h->chunk; + /* We use >= because there cannot be an object at the beginning of a chunk. + But there can be an empty object at that address + at the end of another chunk. */ + while (lp != 0 && ((void *) lp >= obj || (void *) (lp)->limit < obj)) + { + plp = lp->prev; + call_freefun (h, lp); + lp = plp; + /* If we switch chunks, we can't tell whether the new current + chunk contains an empty object, so assume that it may. */ + h->maybe_empty_object = 1; + } + if (lp) + { + h->object_base = h->next_free = (char *) (obj); + h->chunk_limit = lp->limit; + h->chunk = lp; + } + else if (obj != 0) + /* obj is not in any of the chunks! */ + abort (); +} + +_OBSTACK_SIZE_T +_obstack_memory_used (struct obstack *h) +{ + struct _obstack_chunk *lp; + _OBSTACK_SIZE_T nbytes = 0; + + for (lp = h->chunk; lp != 0; lp = lp->prev) + { + nbytes += lp->limit - (char *) lp; + } + return nbytes; +} + +# ifndef _OBSTACK_NO_ERROR_HANDLER +/* Define the error handler. */ +# include + +/* Exit value used when 'print_and_abort' is used. */ +# ifdef _LIBC +int obstack_exit_failure = EXIT_FAILURE; +# else +# include "exitfail.h" +# define obstack_exit_failure exit_failure +# endif + +# ifdef _LIBC +# include +# else +# include "gettext.h" +# endif +# ifndef _ +# define _(msgid) gettext (msgid) +# endif + +# ifdef _LIBC +# include +# endif + +static _Noreturn void +print_and_abort (void) +{ + /* Don't change any of these strings. Yes, it would be possible to add + the newline to the string and use fputs or so. But this must not + happen because the "memory exhausted" message appears in other places + like this and the translation should be reused instead of creating + a very similar string which requires a separate translation. */ +# ifdef _LIBC + (void) __fxprintf (NULL, "%s\n", _("memory exhausted")); +# else + fprintf (stderr, "%s\n", _("memory exhausted")); +# endif + exit (obstack_exit_failure); +} + +/* The functions allocating more room by calling 'obstack_chunk_alloc' + jump to the handler pointed to by 'obstack_alloc_failed_handler'. + This can be set to a user defined function which should either + abort gracefully or use longjump - but shouldn't return. This + variable by default points to the internal function + 'print_and_abort'. */ +void (*obstack_alloc_failed_handler) (void) = print_and_abort; +# endif /* !_OBSTACK_NO_ERROR_HANDLER */ +#endif /* !_OBSTACK_ELIDE_CODE */ diff --git a/gettext-tools/gnulib-lib/obstack.h b/gettext-tools/gnulib-lib/obstack.h new file mode 100644 index 0000000..cc44c06 --- /dev/null +++ b/gettext-tools/gnulib-lib/obstack.h @@ -0,0 +1,531 @@ +/* obstack.h - object stack macros + Copyright (C) 1988-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public + License along with the GNU C Library; if not, see + . */ + +/* Summary: + + All the apparent functions defined here are macros. The idea + is that you would use these pre-tested macros to solve a + very specific set of problems, and they would run fast. + Caution: no side-effects in arguments please!! They may be + evaluated MANY times!! + + These macros operate a stack of objects. Each object starts life + small, and may grow to maturity. (Consider building a word syllable + by syllable.) An object can move while it is growing. Once it has + been "finished" it never changes address again. So the "top of the + stack" is typically an immature growing object, while the rest of the + stack is of mature, fixed size and fixed address objects. + + These routines grab large chunks of memory, using a function you + supply, called 'obstack_chunk_alloc'. On occasion, they free chunks, + by calling 'obstack_chunk_free'. You must define them and declare + them before using any obstack macros. + + Each independent stack is represented by a 'struct obstack'. + Each of the obstack macros expects a pointer to such a structure + as the first argument. + + One motivation for this package is the problem of growing char strings + in symbol tables. Unless you are "fascist pig with a read-only mind" + --Gosper's immortal quote from HAKMEM item 154, out of context--you + would not like to put any arbitrary upper limit on the length of your + symbols. + + In practice this often means you will build many short symbols and a + few long symbols. At the time you are reading a symbol you don't know + how long it is. One traditional method is to read a symbol into a + buffer, realloc()ating the buffer every time you try to read a symbol + that is longer than the buffer. This is beaut, but you still will + want to copy the symbol from the buffer to a more permanent + symbol-table entry say about half the time. + + With obstacks, you can work differently. Use one obstack for all symbol + names. As you read a symbol, grow the name in the obstack gradually. + When the name is complete, finalize it. Then, if the symbol exists already, + free the newly read name. + + The way we do this is to take a large chunk, allocating memory from + low addresses. When you want to build a symbol in the chunk you just + add chars above the current "high water mark" in the chunk. When you + have finished adding chars, because you got to the end of the symbol, + you know how long the chars are, and you can create a new object. + Mostly the chars will not burst over the highest address of the chunk, + because you would typically expect a chunk to be (say) 100 times as + long as an average object. + + In case that isn't clear, when we have enough chars to make up + the object, THEY ARE ALREADY CONTIGUOUS IN THE CHUNK (guaranteed) + so we just point to it where it lies. No moving of chars is + needed and this is the second win: potentially long strings need + never be explicitly shuffled. Once an object is formed, it does not + change its address during its lifetime. + + When the chars burst over a chunk boundary, we allocate a larger + chunk, and then copy the partly formed object from the end of the old + chunk to the beginning of the new larger chunk. We then carry on + accreting characters to the end of the object as we normally would. + + A special macro is provided to add a single char at a time to a + growing object. This allows the use of register variables, which + break the ordinary 'growth' macro. + + Summary: + We allocate large chunks. + We carve out one object at a time from the current chunk. + Once carved, an object never moves. + We are free to append data of any size to the currently + growing object. + Exactly one object is growing in an obstack at any one time. + You can run one obstack per control block. + You may have as many control blocks as you dare. + Because of the way we do it, you can "unwind" an obstack + back to a previous state. (You may remove objects much + as you would with a stack.) + */ + + +/* Don't do the contents of this file more than once. */ + +#ifndef _OBSTACK_H +#define _OBSTACK_H 1 + +#ifndef _OBSTACK_INTERFACE_VERSION +# define _OBSTACK_INTERFACE_VERSION 2 +#endif + +#include /* For size_t and ptrdiff_t. */ +#include /* For __GNU_LIBRARY__, and memcpy. */ + +#if _OBSTACK_INTERFACE_VERSION == 1 +/* For binary compatibility with obstack version 1, which used "int" + and "long" for these two types. */ +# define _OBSTACK_SIZE_T unsigned int +# define _CHUNK_SIZE_T unsigned long +# define _OBSTACK_CAST(type, expr) ((type) (expr)) +#else +/* Version 2 with sane types, especially for 64-bit hosts. */ +# define _OBSTACK_SIZE_T size_t +# define _CHUNK_SIZE_T size_t +# define _OBSTACK_CAST(type, expr) (expr) +#endif + +/* If B is the base of an object addressed by P, return the result of + aligning P to the next multiple of A + 1. B and P must be of type + char *. A + 1 must be a power of 2. */ + +#define __BPTR_ALIGN(B, P, A) ((B) + (((P) - (B) + (A)) & ~(A))) + +/* Similar to __BPTR_ALIGN (B, P, A), except optimize the common case + where pointers can be converted to integers, aligned as integers, + and converted back again. If ptrdiff_t is narrower than a + pointer (e.g., the AS/400), play it safe and compute the alignment + relative to B. Otherwise, use the faster strategy of computing the + alignment relative to 0. */ + +#define __PTR_ALIGN(B, P, A) \ + __BPTR_ALIGN (sizeof (ptrdiff_t) < sizeof (void *) ? (B) : (char *) 0, \ + P, A) + +#ifndef __attribute_pure__ +# define __attribute_pure__ _GL_ATTRIBUTE_PURE +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +struct _obstack_chunk /* Lives at front of each chunk. */ +{ + char *limit; /* 1 past end of this chunk */ + struct _obstack_chunk *prev; /* address of prior chunk or NULL */ + char contents[4]; /* objects begin here */ +}; + +struct obstack /* control current object in current chunk */ +{ + _CHUNK_SIZE_T chunk_size; /* preferred size to allocate chunks in */ + struct _obstack_chunk *chunk; /* address of current struct obstack_chunk */ + char *object_base; /* address of object we are building */ + char *next_free; /* where to add next char to current object */ + char *chunk_limit; /* address of char after current chunk */ + union + { + _OBSTACK_SIZE_T i; + void *p; + } temp; /* Temporary for some macros. */ + _OBSTACK_SIZE_T alignment_mask; /* Mask of alignment for each object. */ + + /* These prototypes vary based on 'use_extra_arg'. */ + union + { + void *(*plain) (size_t); + void *(*extra) (void *, size_t); + } chunkfun; + union + { + void (*plain) (void *); + void (*extra) (void *, void *); + } freefun; + + void *extra_arg; /* first arg for chunk alloc/dealloc funcs */ + unsigned use_extra_arg : 1; /* chunk alloc/dealloc funcs take extra arg */ + unsigned maybe_empty_object : 1; /* There is a possibility that the current + chunk contains a zero-length object. This + prevents freeing the chunk if we allocate + a bigger chunk to replace it. */ + unsigned alloc_failed : 1; /* No longer used, as we now call the failed + handler on error, but retained for binary + compatibility. */ +}; + +/* Declare the external functions we use; they are in obstack.c. */ + +extern void _obstack_newchunk (struct obstack *, _OBSTACK_SIZE_T); +extern void _obstack_free (struct obstack *, void *); +extern int _obstack_begin (struct obstack *, + _OBSTACK_SIZE_T, _OBSTACK_SIZE_T, + void *(*) (size_t), void (*) (void *)); +extern int _obstack_begin_1 (struct obstack *, + _OBSTACK_SIZE_T, _OBSTACK_SIZE_T, + void *(*) (void *, size_t), + void (*) (void *, void *), void *); +extern _OBSTACK_SIZE_T _obstack_memory_used (struct obstack *) + __attribute_pure__; + + +/* Error handler called when 'obstack_chunk_alloc' failed to allocate + more memory. This can be set to a user defined function which + should either abort gracefully or use longjump - but shouldn't + return. The default action is to print a message and abort. */ +extern DLL_VARIABLE void (*obstack_alloc_failed_handler) (void); + +/* Exit value used when 'print_and_abort' is used. */ +extern DLL_VARIABLE int obstack_exit_failure; + +/* Pointer to beginning of object being allocated or to be allocated next. + Note that this might not be the final address of the object + because a new chunk might be needed to hold the final size. */ + +#define obstack_base(h) ((void *) (h)->object_base) + +/* Size for allocating ordinary chunks. */ + +#define obstack_chunk_size(h) ((h)->chunk_size) + +/* Pointer to next byte not yet allocated in current chunk. */ + +#define obstack_next_free(h) ((void *) (h)->next_free) + +/* Mask specifying low bits that should be clear in address of an object. */ + +#define obstack_alignment_mask(h) ((h)->alignment_mask) + +/* To prevent prototype warnings provide complete argument list. */ +#define obstack_init(h) \ + _obstack_begin ((h), 0, 0, \ + _OBSTACK_CAST (void *(*) (size_t), obstack_chunk_alloc), \ + _OBSTACK_CAST (void (*) (void *), obstack_chunk_free)) + +#define obstack_begin(h, size) \ + _obstack_begin ((h), (size), 0, \ + _OBSTACK_CAST (void *(*) (size_t), obstack_chunk_alloc), \ + _OBSTACK_CAST (void (*) (void *), obstack_chunk_free)) + +#define obstack_specify_allocation(h, size, alignment, chunkfun, freefun) \ + _obstack_begin ((h), (size), (alignment), \ + _OBSTACK_CAST (void *(*) (size_t), chunkfun), \ + _OBSTACK_CAST (void (*) (void *), freefun)) + +#define obstack_specify_allocation_with_arg(h, size, alignment, chunkfun, freefun, arg) \ + _obstack_begin_1 ((h), (size), (alignment), \ + _OBSTACK_CAST (void *(*) (void *, size_t), chunkfun), \ + _OBSTACK_CAST (void (*) (void *, void *), freefun), arg) + +#define obstack_chunkfun(h, newchunkfun) \ + ((void) ((h)->chunkfun.extra = (void *(*) (void *, size_t)) (newchunkfun))) + +#define obstack_freefun(h, newfreefun) \ + ((void) ((h)->freefun.extra = (void *(*) (void *, void *)) (newfreefun))) + +#define obstack_1grow_fast(h, achar) ((void) (*((h)->next_free)++ = (achar))) + +#define obstack_blank_fast(h, n) ((void) ((h)->next_free += (n))) + +#define obstack_memory_used(h) _obstack_memory_used (h) + +#if defined __GNUC__ +# if !defined __GNUC_MINOR__ || __GNUC__ * 1000 + __GNUC_MINOR__ < 2008 +# define __extension__ +# endif + +/* For GNU C, if not -traditional, + we can define these macros to compute all args only once + without using a global variable. + Also, we can avoid using the 'temp' slot, to make faster code. */ + +# define obstack_object_size(OBSTACK) \ + __extension__ \ + ({ struct obstack const *__o = (OBSTACK); \ + (_OBSTACK_SIZE_T) (__o->next_free - __o->object_base); }) + +/* The local variable is named __o1 to avoid a shadowed variable + warning when invoked from other obstack macros. */ +# define obstack_room(OBSTACK) \ + __extension__ \ + ({ struct obstack const *__o1 = (OBSTACK); \ + (_OBSTACK_SIZE_T) (__o1->chunk_limit - __o1->next_free); }) + +# define obstack_make_room(OBSTACK, length) \ + __extension__ \ + ({ struct obstack *__o = (OBSTACK); \ + _OBSTACK_SIZE_T __len = (length); \ + if (obstack_room (__o) < __len) \ + _obstack_newchunk (__o, __len); \ + (void) 0; }) + +# define obstack_empty_p(OBSTACK) \ + __extension__ \ + ({ struct obstack const *__o = (OBSTACK); \ + (__o->chunk->prev == 0 \ + && __o->next_free == __PTR_ALIGN ((char *) __o->chunk, \ + __o->chunk->contents, \ + __o->alignment_mask)); }) + +# define obstack_grow(OBSTACK, where, length) \ + __extension__ \ + ({ struct obstack *__o = (OBSTACK); \ + _OBSTACK_SIZE_T __len = (length); \ + if (obstack_room (__o) < __len) \ + _obstack_newchunk (__o, __len); \ + memcpy (__o->next_free, where, __len); \ + __o->next_free += __len; \ + (void) 0; }) + +# define obstack_grow0(OBSTACK, where, length) \ + __extension__ \ + ({ struct obstack *__o = (OBSTACK); \ + _OBSTACK_SIZE_T __len = (length); \ + if (obstack_room (__o) < __len + 1) \ + _obstack_newchunk (__o, __len + 1); \ + memcpy (__o->next_free, where, __len); \ + __o->next_free += __len; \ + *(__o->next_free)++ = 0; \ + (void) 0; }) + +# define obstack_1grow(OBSTACK, datum) \ + __extension__ \ + ({ struct obstack *__o = (OBSTACK); \ + if (obstack_room (__o) < 1) \ + _obstack_newchunk (__o, 1); \ + obstack_1grow_fast (__o, datum); }) + +/* These assume that the obstack alignment is good enough for pointers + or ints, and that the data added so far to the current object + shares that much alignment. */ + +# define obstack_ptr_grow(OBSTACK, datum) \ + __extension__ \ + ({ struct obstack *__o = (OBSTACK); \ + if (obstack_room (__o) < sizeof (void *)) \ + _obstack_newchunk (__o, sizeof (void *)); \ + obstack_ptr_grow_fast (__o, datum); }) + +# define obstack_int_grow(OBSTACK, datum) \ + __extension__ \ + ({ struct obstack *__o = (OBSTACK); \ + if (obstack_room (__o) < sizeof (int)) \ + _obstack_newchunk (__o, sizeof (int)); \ + obstack_int_grow_fast (__o, datum); }) + +# define obstack_ptr_grow_fast(OBSTACK, aptr) \ + __extension__ \ + ({ struct obstack *__o1 = (OBSTACK); \ + void *__p1 = __o1->next_free; \ + *(const void **) __p1 = (aptr); \ + __o1->next_free += sizeof (const void *); \ + (void) 0; }) + +# define obstack_int_grow_fast(OBSTACK, aint) \ + __extension__ \ + ({ struct obstack *__o1 = (OBSTACK); \ + void *__p1 = __o1->next_free; \ + *(int *) __p1 = (aint); \ + __o1->next_free += sizeof (int); \ + (void) 0; }) + +# define obstack_blank(OBSTACK, length) \ + __extension__ \ + ({ struct obstack *__o = (OBSTACK); \ + _OBSTACK_SIZE_T __len = (length); \ + if (obstack_room (__o) < __len) \ + _obstack_newchunk (__o, __len); \ + obstack_blank_fast (__o, __len); }) + +# define obstack_alloc(OBSTACK, length) \ + __extension__ \ + ({ struct obstack *__h = (OBSTACK); \ + obstack_blank (__h, (length)); \ + obstack_finish (__h); }) + +# define obstack_copy(OBSTACK, where, length) \ + __extension__ \ + ({ struct obstack *__h = (OBSTACK); \ + obstack_grow (__h, (where), (length)); \ + obstack_finish (__h); }) + +# define obstack_copy0(OBSTACK, where, length) \ + __extension__ \ + ({ struct obstack *__h = (OBSTACK); \ + obstack_grow0 (__h, (where), (length)); \ + obstack_finish (__h); }) + +/* The local variable is named __o1 to avoid a shadowed variable + warning when invoked from other obstack macros, typically obstack_free. */ +# define obstack_finish(OBSTACK) \ + __extension__ \ + ({ struct obstack *__o1 = (OBSTACK); \ + void *__value = (void *) __o1->object_base; \ + if (__o1->next_free == __value) \ + __o1->maybe_empty_object = 1; \ + __o1->next_free \ + = __PTR_ALIGN (__o1->object_base, __o1->next_free, \ + __o1->alignment_mask); \ + if ((size_t) (__o1->next_free - (char *) __o1->chunk) \ + > (size_t) (__o1->chunk_limit - (char *) __o1->chunk)) \ + __o1->next_free = __o1->chunk_limit; \ + __o1->object_base = __o1->next_free; \ + __value; }) + +# define obstack_free(OBSTACK, OBJ) \ + __extension__ \ + ({ struct obstack *__o = (OBSTACK); \ + void *__obj = (void *) (OBJ); \ + if (__obj > (void *) __o->chunk && __obj < (void *) __o->chunk_limit) \ + __o->next_free = __o->object_base = (char *) __obj; \ + else \ + _obstack_free (__o, __obj); }) + +#else /* not __GNUC__ */ + +# define obstack_object_size(h) \ + ((_OBSTACK_SIZE_T) ((h)->next_free - (h)->object_base)) + +# define obstack_room(h) \ + ((_OBSTACK_SIZE_T) ((h)->chunk_limit - (h)->next_free)) + +# define obstack_empty_p(h) \ + ((h)->chunk->prev == 0 \ + && (h)->next_free == __PTR_ALIGN ((char *) (h)->chunk, \ + (h)->chunk->contents, \ + (h)->alignment_mask)) + +/* Note that the call to _obstack_newchunk is enclosed in (..., 0) + so that we can avoid having void expressions + in the arms of the conditional expression. + Casting the third operand to void was tried before, + but some compilers won't accept it. */ + +# define obstack_make_room(h, length) \ + ((h)->temp.i = (length), \ + ((obstack_room (h) < (h)->temp.i) \ + ? (_obstack_newchunk (h, (h)->temp.i), 0) : 0), \ + (void) 0) + +# define obstack_grow(h, where, length) \ + ((h)->temp.i = (length), \ + ((obstack_room (h) < (h)->temp.i) \ + ? (_obstack_newchunk ((h), (h)->temp.i), 0) : 0), \ + memcpy ((h)->next_free, where, (h)->temp.i), \ + (h)->next_free += (h)->temp.i, \ + (void) 0) + +# define obstack_grow0(h, where, length) \ + ((h)->temp.i = (length), \ + ((obstack_room (h) < (h)->temp.i + 1) \ + ? (_obstack_newchunk ((h), (h)->temp.i + 1), 0) : 0), \ + memcpy ((h)->next_free, where, (h)->temp.i), \ + (h)->next_free += (h)->temp.i, \ + *((h)->next_free)++ = 0, \ + (void) 0) + +# define obstack_1grow(h, datum) \ + (((obstack_room (h) < 1) \ + ? (_obstack_newchunk ((h), 1), 0) : 0), \ + obstack_1grow_fast (h, datum)) + +# define obstack_ptr_grow(h, datum) \ + (((obstack_room (h) < sizeof (char *)) \ + ? (_obstack_newchunk ((h), sizeof (char *)), 0) : 0), \ + obstack_ptr_grow_fast (h, datum)) + +# define obstack_int_grow(h, datum) \ + (((obstack_room (h) < sizeof (int)) \ + ? (_obstack_newchunk ((h), sizeof (int)), 0) : 0), \ + obstack_int_grow_fast (h, datum)) + +# define obstack_ptr_grow_fast(h, aptr) \ + (((const void **) ((h)->next_free += sizeof (void *)))[-1] = (aptr), \ + (void) 0) + +# define obstack_int_grow_fast(h, aint) \ + (((int *) ((h)->next_free += sizeof (int)))[-1] = (aint), \ + (void) 0) + +# define obstack_blank(h, length) \ + ((h)->temp.i = (length), \ + ((obstack_room (h) < (h)->temp.i) \ + ? (_obstack_newchunk ((h), (h)->temp.i), 0) : 0), \ + obstack_blank_fast (h, (h)->temp.i)) + +# define obstack_alloc(h, length) \ + (obstack_blank ((h), (length)), obstack_finish ((h))) + +# define obstack_copy(h, where, length) \ + (obstack_grow ((h), (where), (length)), obstack_finish ((h))) + +# define obstack_copy0(h, where, length) \ + (obstack_grow0 ((h), (where), (length)), obstack_finish ((h))) + +# define obstack_finish(h) \ + (((h)->next_free == (h)->object_base \ + ? (((h)->maybe_empty_object = 1), 0) \ + : 0), \ + (h)->temp.p = (h)->object_base, \ + (h)->next_free \ + = __PTR_ALIGN ((h)->object_base, (h)->next_free, \ + (h)->alignment_mask), \ + (((size_t) ((h)->next_free - (char *) (h)->chunk) \ + > (size_t) ((h)->chunk_limit - (char *) (h)->chunk)) \ + ? ((h)->next_free = (h)->chunk_limit) : 0), \ + (h)->object_base = (h)->next_free, \ + (h)->temp.p) + +# define obstack_free(h, obj) \ + ((h)->temp.p = (void *) (obj), \ + (((h)->temp.p > (void *) (h)->chunk \ + && (h)->temp.p < (void *) (h)->chunk_limit) \ + ? (void) ((h)->next_free = (h)->object_base = (char *) (h)->temp.p) \ + : _obstack_free ((h), (h)->temp.p))) + +#endif /* not __GNUC__ */ + +#ifdef __cplusplus +} /* C++ */ +#endif + +#endif /* _OBSTACK_H */ diff --git a/gettext-tools/gnulib-lib/open.c b/gettext-tools/gnulib-lib/open.c new file mode 100644 index 0000000..d6f8e0d --- /dev/null +++ b/gettext-tools/gnulib-lib/open.c @@ -0,0 +1,181 @@ +/* Open a descriptor to a file. + Copyright (C) 2007-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Written by Bruno Haible , 2007. */ + +/* If the user's config.h happens to include , let it include only + the system's here, so that orig_open doesn't recurse to + rpl_open. */ +#define __need_system_fcntl_h +#include + +/* Get the original definition of open. It might be defined as a macro. */ +#include +#include +#undef __need_system_fcntl_h + +static int +orig_open (const char *filename, int flags, mode_t mode) +{ + return open (filename, flags, mode); +} + +/* Specification. */ +/* Write "fcntl.h" here, not , otherwise OSF/1 5.1 DTK cc eliminates + this include because of the preliminary #include above. */ +#include "fcntl.h" + +#include +#include +#include +#include +#include +#include + +#ifndef REPLACE_OPEN_DIRECTORY +# define REPLACE_OPEN_DIRECTORY 0 +#endif + +int +open (const char *filename, int flags, ...) +{ + mode_t mode; + int fd; + + mode = 0; + if (flags & O_CREAT) + { + va_list arg; + va_start (arg, flags); + + /* We have to use PROMOTED_MODE_T instead of mode_t, otherwise GCC 4 + creates crashing code when 'mode_t' is smaller than 'int'. */ + mode = va_arg (arg, PROMOTED_MODE_T); + + va_end (arg); + } + +#if GNULIB_defined_O_NONBLOCK + /* The only known platform that lacks O_NONBLOCK is mingw, but it + also lacks named pipes and Unix sockets, which are the only two + file types that require non-blocking handling in open(). + Therefore, it is safe to ignore O_NONBLOCK here. It is handy + that mingw also lacks openat(), so that is also covered here. */ + flags &= ~O_NONBLOCK; +#endif + +#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ + if (strcmp (filename, "/dev/null") == 0) + filename = "NUL"; +#endif + +#if OPEN_TRAILING_SLASH_BUG + /* If the filename ends in a slash and one of O_CREAT, O_WRONLY, O_RDWR + is specified, then fail. + Rationale: POSIX + says that + "A pathname that contains at least one non-slash character and that + ends with one or more trailing slashes shall be resolved as if a + single dot character ( '.' ) were appended to the pathname." + and + "The special filename dot shall refer to the directory specified by + its predecessor." + If the named file already exists as a directory, then + - if O_CREAT is specified, open() must fail because of the semantics + of O_CREAT, + - if O_WRONLY or O_RDWR is specified, open() must fail because POSIX + says that it + fails with errno = EISDIR in this case. + If the named file does not exist or does not name a directory, then + - if O_CREAT is specified, open() must fail since open() cannot create + directories, + - if O_WRONLY or O_RDWR is specified, open() must fail because the + file does not contain a '.' directory. */ + if (flags & (O_CREAT | O_WRONLY | O_RDWR)) + { + size_t len = strlen (filename); + if (len > 0 && filename[len - 1] == '/') + { + errno = EISDIR; + return -1; + } + } +#endif + + fd = orig_open (filename, flags, mode); + +#if REPLACE_FCHDIR + /* Implementing fchdir and fdopendir requires the ability to open a + directory file descriptor. If open doesn't support that (as on + mingw), we use a dummy file that behaves the same as directories + on Linux (ie. always reports EOF on attempts to read()), and + override fstat() in fchdir.c to hide the fact that we have a + dummy. */ + if (REPLACE_OPEN_DIRECTORY && fd < 0 && errno == EACCES + && ((flags & O_ACCMODE) == O_RDONLY + || (O_SEARCH != O_RDONLY && (flags & O_ACCMODE) == O_SEARCH))) + { + struct stat statbuf; + if (stat (filename, &statbuf) == 0 && S_ISDIR (statbuf.st_mode)) + { + /* Maximum recursion depth of 1. */ + fd = open ("/dev/null", flags, mode); + if (0 <= fd) + fd = _gl_register_fd (fd, filename); + } + else + errno = EACCES; + } +#endif + +#if OPEN_TRAILING_SLASH_BUG + /* If the filename ends in a slash and fd does not refer to a directory, + then fail. + Rationale: POSIX + says that + "A pathname that contains at least one non-slash character and that + ends with one or more trailing slashes shall be resolved as if a + single dot character ( '.' ) were appended to the pathname." + and + "The special filename dot shall refer to the directory specified by + its predecessor." + If the named file without the slash is not a directory, open() must fail + with ENOTDIR. */ + if (fd >= 0) + { + /* We know len is positive, since open did not fail with ENOENT. */ + size_t len = strlen (filename); + if (filename[len - 1] == '/') + { + struct stat statbuf; + + if (fstat (fd, &statbuf) >= 0 && !S_ISDIR (statbuf.st_mode)) + { + close (fd); + errno = ENOTDIR; + return -1; + } + } + } +#endif + +#if REPLACE_FCHDIR + if (!REPLACE_OPEN_DIRECTORY && 0 <= fd) + fd = _gl_register_fd (fd, filename); +#endif + + return fd; +} diff --git a/gettext-tools/gnulib-lib/opendir.c b/gettext-tools/gnulib-lib/opendir.c new file mode 100644 index 0000000..c67f2e5 --- /dev/null +++ b/gettext-tools/gnulib-lib/opendir.c @@ -0,0 +1,148 @@ +/* Start reading the entries of a directory. + Copyright (C) 2006-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include + +#include +#include + +#if HAVE_OPENDIR + +/* Override opendir(), to keep track of the open file descriptors. + Needed because there is a function dirfd(). */ + +#else + +# include + +# include "dirent-private.h" +# include "filename.h" + +#endif + +#if REPLACE_FCHDIR +# include +#endif + +DIR * +opendir (const char *dir_name) +{ +#if HAVE_OPENDIR +# undef opendir + DIR *dirp; + + dirp = opendir (dir_name); + if (dirp == NULL) + return NULL; + +#else + + char dir_name_mask[MAX_PATH + 1 + 1 + 1]; + int status; + HANDLE current; + WIN32_FIND_DATA entry; + struct gl_directory *dirp; + + if (dir_name[0] == '\0') + { + errno = ENOENT; + return NULL; + } + + /* Make the dir_name absolute, so that we continue reading the same + directory if the current directory changed between this opendir() + call and a subsequent rewinddir() call. */ + if (!GetFullPathName (dir_name, MAX_PATH, dir_name_mask, NULL)) + { + errno = EINVAL; + return NULL; + } + + /* Append the mask. + "*" and "*.*" appear to be equivalent. */ + { + char *p; + + p = dir_name_mask + strlen (dir_name_mask); + if (p > dir_name_mask && !ISSLASH (p[-1])) + *p++ = '\\'; + *p++ = '*'; + *p = '\0'; + } + + /* Start searching the directory. */ + status = -1; + current = FindFirstFile (dir_name_mask, &entry); + if (current == INVALID_HANDLE_VALUE) + { + switch (GetLastError ()) + { + case ERROR_FILE_NOT_FOUND: + status = -2; + break; + case ERROR_PATH_NOT_FOUND: + errno = ENOENT; + return NULL; + case ERROR_DIRECTORY: + errno = ENOTDIR; + return NULL; + case ERROR_ACCESS_DENIED: + errno = EACCES; + return NULL; + default: + errno = EIO; + return NULL; + } + } + + /* Allocate the result. */ + dirp = + (struct gl_directory *) + malloc (offsetof (struct gl_directory, dir_name_mask[0]) + + strlen (dir_name_mask) + 1); + if (dirp == NULL) + { + if (current != INVALID_HANDLE_VALUE) + FindClose (current); + errno = ENOMEM; + return NULL; + } + dirp->status = status; + dirp->current = current; + if (status == -1) + memcpy (&dirp->entry, &entry, sizeof (WIN32_FIND_DATA)); + strcpy (dirp->dir_name_mask, dir_name_mask); + +#endif + +#if REPLACE_FCHDIR + { + int fd = dirfd (dirp); + if (0 <= fd && _gl_register_fd (fd, dir_name) != fd) + { + int saved_errno = errno; + closedir (dirp); + errno = saved_errno; + return NULL; + } + } +#endif + + return dirp; +} diff --git a/gettext-tools/gnulib-lib/ostream.c b/gettext-tools/gnulib-lib/ostream.c new file mode 100644 index 0000000..854d4a0 --- /dev/null +++ b/gettext-tools/gnulib-lib/ostream.c @@ -0,0 +1,122 @@ +/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ + +#line 1 "ostream.oo.c" +/* Abstract output stream data type. + Copyright (C) 2006 Free Software Foundation, Inc. + Written by Bruno Haible , 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include "ostream.h" + +#line 27 "ostream.c" +#if !IS_CPLUSPLUS +#define ostream_representation any_ostream_representation +#endif +#include "ostream.priv.h" + +const typeinfo_t ostream_typeinfo = { "ostream" }; + +static const typeinfo_t * const ostream_superclasses[] = + { ostream_SUPERCLASSES }; + +#line 27 "ostream.oo.c" + +#if !HAVE_INLINE + +void +ostream_write_str (ostream_t stream, const char *string) +{ + ostream_write_mem (stream, string, strlen (string)); +} + +#endif + +#line 50 "ostream.c" +void ostream__write_mem (ostream_t first_arg, const void *data, size_t len); +void +ostream__write_mem (ostream_t first_arg, const void *data, size_t len) +{ + /* Abstract (unimplemented) method called. */ + abort (); + #ifndef __GNUC__ + ostream__write_mem (first_arg,data,len); + #endif +} + +void ostream__flush (ostream_t first_arg); +void +ostream__flush (ostream_t first_arg) +{ + /* Abstract (unimplemented) method called. */ + abort (); + #ifndef __GNUC__ + ostream__flush (first_arg); + #endif +} + +void ostream__free (ostream_t first_arg); +void +ostream__free (ostream_t first_arg) +{ + /* Abstract (unimplemented) method called. */ + abort (); + #ifndef __GNUC__ + ostream__free (first_arg); + #endif +} + + +const struct ostream_implementation ostream_vtable = +{ + ostream_superclasses, + sizeof (ostream_superclasses) / sizeof (ostream_superclasses[0]), + sizeof (struct ostream_representation), + ostream__write_mem, + ostream__flush, + ostream__free, +}; + +#if !HAVE_INLINE + +/* Define the functions that invoke the methods. */ + +void +ostream_write_mem (ostream_t first_arg, const void *data, size_t len) +{ + const struct ostream_implementation *vtable = + ((struct ostream_representation_header *) (struct any_ostream_representation *) first_arg)->vtable; + vtable->write_mem (first_arg,data,len); +} + +void +ostream_flush (ostream_t first_arg) +{ + const struct ostream_implementation *vtable = + ((struct ostream_representation_header *) (struct any_ostream_representation *) first_arg)->vtable; + vtable->flush (first_arg); +} + +void +ostream_free (ostream_t first_arg) +{ + const struct ostream_implementation *vtable = + ((struct ostream_representation_header *) (struct any_ostream_representation *) first_arg)->vtable; + vtable->free (first_arg); +} + +#endif diff --git a/gettext-tools/gnulib-lib/ostream.h b/gettext-tools/gnulib-lib/ostream.h new file mode 100644 index 0000000..96cb623 --- /dev/null +++ b/gettext-tools/gnulib-lib/ostream.h @@ -0,0 +1,141 @@ +/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ + +#line 1 "ostream.oo.h" +/* Abstract output stream data type. + Copyright (C) 2006 Free Software Foundation, Inc. + Written by Bruno Haible , 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _OSTREAM_H +#define _OSTREAM_H + +#include +#include + +#include "moo.h" + +/* An output stream is an object to which one can feed a sequence of bytes. */ + +#line 32 "ostream.h" +struct any_ostream_representation; +/* ostream_t is defined as a pointer to struct any_ostream_representation. + In C++ mode, we use a smart pointer class. + In C mode, we have no other choice than a typedef to the root class type. */ +#if IS_CPLUSPLUS +struct ostream_t +{ +private: + struct any_ostream_representation *_pointer; +public: + ostream_t () : _pointer (NULL) {} + ostream_t (struct any_ostream_representation *pointer) : _pointer (pointer) {} + struct any_ostream_representation * operator -> () { return _pointer; } + operator struct any_ostream_representation * () { return _pointer; } + operator void * () { return _pointer; } + bool operator == (const void *p) { return _pointer == p; } + bool operator != (const void *p) { return _pointer != p; } +}; +#else +typedef struct any_ostream_representation * ostream_t; +#endif + +/* Functions that invoke the methods. */ +extern void ostream_write_mem (ostream_t first_arg, const void *data, size_t len); +extern void ostream_flush (ostream_t first_arg); +extern void ostream_free (ostream_t first_arg); + +/* Type representing an implementation of ostream_t. */ +struct ostream_implementation +{ + const typeinfo_t * const *superclasses; + size_t superclasses_length; + size_t instance_size; +#define THIS_ARG ostream_t first_arg +#include "ostream.vt.h" +#undef THIS_ARG +}; + +/* Public portion of the object pointed to by a ostream_t. */ +struct ostream_representation_header +{ + const struct ostream_implementation *vtable; +}; + +#if HAVE_INLINE + +/* Define the functions that invoke the methods as inline accesses to + the ostream_implementation. + Use #define to avoid a warning because of extern vs. static. */ + +# define ostream_write_mem ostream_write_mem_inline +static inline void +ostream_write_mem (ostream_t first_arg, const void *data, size_t len) +{ + const struct ostream_implementation *vtable = + ((struct ostream_representation_header *) (struct any_ostream_representation *) first_arg)->vtable; + vtable->write_mem (first_arg,data,len); +} + +# define ostream_flush ostream_flush_inline +static inline void +ostream_flush (ostream_t first_arg) +{ + const struct ostream_implementation *vtable = + ((struct ostream_representation_header *) (struct any_ostream_representation *) first_arg)->vtable; + vtable->flush (first_arg); +} + +# define ostream_free ostream_free_inline +static inline void +ostream_free (ostream_t first_arg) +{ + const struct ostream_implementation *vtable = + ((struct ostream_representation_header *) (struct any_ostream_representation *) first_arg)->vtable; + vtable->free (first_arg); +} + +#endif + +extern const typeinfo_t ostream_typeinfo; +#define ostream_SUPERCLASSES &ostream_typeinfo, NULL +#define ostream_SUPERCLASSES_LENGTH (1 + 1) + +extern const struct ostream_implementation ostream_vtable; + +#line 41 "ostream.oo.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Write a string's contents to a stream. */ +extern void ostream_write_str (ostream_t stream, const char *string); + +#if HAVE_INLINE + +#define ostream_write_str ostream_write_str_inline +static inline void +ostream_write_str (ostream_t stream, const char *string) +{ + ostream_write_mem (stream, string, strlen (string)); +} + +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _OSTREAM_H */ diff --git a/gettext-tools/gnulib-lib/ostream.oo.c b/gettext-tools/gnulib-lib/ostream.oo.c new file mode 100644 index 0000000..49ee16f --- /dev/null +++ b/gettext-tools/gnulib-lib/ostream.oo.c @@ -0,0 +1,36 @@ +/* Abstract output stream data type. + Copyright (C) 2006 Free Software Foundation, Inc. + Written by Bruno Haible , 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include "ostream.h" + +struct ostream +{ +fields: +}; + +#if !HAVE_INLINE + +void +ostream_write_str (ostream_t stream, const char *string) +{ + ostream_write_mem (stream, string, strlen (string)); +} + +#endif diff --git a/gettext-tools/gnulib-lib/ostream.oo.h b/gettext-tools/gnulib-lib/ostream.oo.h new file mode 100644 index 0000000..2a9a7f3 --- /dev/null +++ b/gettext-tools/gnulib-lib/ostream.oo.h @@ -0,0 +1,64 @@ +/* Abstract output stream data type. + Copyright (C) 2006 Free Software Foundation, Inc. + Written by Bruno Haible , 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _OSTREAM_H +#define _OSTREAM_H + +#include +#include + +#include "moo.h" + +/* An output stream is an object to which one can feed a sequence of bytes. */ + +struct ostream +{ +methods: + + /* Write a sequence of bytes to a stream. */ + void write_mem (ostream_t stream, const void *data, size_t len); + + /* Bring buffered data to its destination. */ + void flush (ostream_t stream); + + /* Close and free a stream. */ + void free (ostream_t stream); +}; + +#ifdef __cplusplus +extern "C" { +#endif + +/* Write a string's contents to a stream. */ +extern void ostream_write_str (ostream_t stream, const char *string); + +#if HAVE_INLINE + +#define ostream_write_str ostream_write_str_inline +static inline void +ostream_write_str (ostream_t stream, const char *string) +{ + ostream_write_mem (stream, string, strlen (string)); +} + +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _OSTREAM_H */ diff --git a/gettext-tools/gnulib-lib/ostream.priv.h b/gettext-tools/gnulib-lib/ostream.priv.h new file mode 100644 index 0000000..af0d117 --- /dev/null +++ b/gettext-tools/gnulib-lib/ostream.priv.h @@ -0,0 +1,7 @@ +/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ + +/* Field layout of ostream class. */ +struct ostream_representation +{ + const void *vtable; +}; diff --git a/gettext-tools/gnulib-lib/ostream.vt.h b/gettext-tools/gnulib-lib/ostream.vt.h new file mode 100644 index 0000000..9ac018d --- /dev/null +++ b/gettext-tools/gnulib-lib/ostream.vt.h @@ -0,0 +1,6 @@ +/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ + +/* Virtual function table layout of ostream class. */ + void (*write_mem) (THIS_ARG, const void *data, size_t len); + void (*flush) (THIS_ARG); + void (*free) (THIS_ARG); diff --git a/gettext-tools/gnulib-lib/pathmax.h b/gettext-tools/gnulib-lib/pathmax.h new file mode 100644 index 0000000..33fc355 --- /dev/null +++ b/gettext-tools/gnulib-lib/pathmax.h @@ -0,0 +1,83 @@ +/* Define PATH_MAX somehow. Requires sys/types.h. + Copyright (C) 1992, 1999, 2001, 2003, 2005, 2009-2014 Free Software + Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . */ + +#ifndef _PATHMAX_H +# define _PATHMAX_H + +/* POSIX:2008 defines PATH_MAX to be the maximum number of bytes in a filename, + including the terminating NUL byte. + + PATH_MAX is not defined on systems which have no limit on filename length, + such as GNU/Hurd. + + This file does *not* define PATH_MAX always. Programs that use this file + can handle the GNU/Hurd case in several ways: + - Either with a package-wide handling, or with a per-file handling, + - Either through a + #ifdef PATH_MAX + or through a fallback like + #ifndef PATH_MAX + # define PATH_MAX 8192 + #endif + or through a fallback like + #ifndef PATH_MAX + # define PATH_MAX pathconf ("/", _PC_PATH_MAX) + #endif + */ + +# include + +# include + +# ifndef _POSIX_PATH_MAX +# define _POSIX_PATH_MAX 256 +# endif + +/* Don't include sys/param.h if it already has been. */ +# if defined HAVE_SYS_PARAM_H && !defined PATH_MAX && !defined MAXPATHLEN +# include +# endif + +# if !defined PATH_MAX && defined MAXPATHLEN +# define PATH_MAX MAXPATHLEN +# endif + +# ifdef __hpux +/* On HP-UX, PATH_MAX designates the maximum number of bytes in a filename, + *not* including the terminating NUL byte, and is set to 1023. + Additionally, when _XOPEN_SOURCE is defined to 500 or more, PATH_MAX is + not defined at all any more. */ +# undef PATH_MAX +# define PATH_MAX 1024 +# endif + +# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ +/* The page "Naming Files, Paths, and Namespaces" on msdn.microsoft.com, + section "Maximum Path Length Limitation", + + explains that the maximum size of a filename, including the terminating + NUL byte, is 260 = 3 + 256 + 1. + This is the same value as + - FILENAME_MAX in , + - _MAX_PATH in , + - MAX_PATH in . + Undefine the original value, because mingw's gets it wrong. */ +# undef PATH_MAX +# define PATH_MAX 260 +# endif + +#endif /* _PATHMAX_H */ diff --git a/gettext-tools/gnulib-lib/pipe-filter-aux.c b/gettext-tools/gnulib-lib/pipe-filter-aux.c new file mode 100644 index 0000000..eb93d9a --- /dev/null +++ b/gettext-tools/gnulib-lib/pipe-filter-aux.c @@ -0,0 +1,43 @@ +/* Auxiliary code for filtering of data through a subprocess. + Copyright (C) 2012-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +#define PIPE_FILTER_AUX_INLINE _GL_EXTERN_INLINE + +#include "pipe-filter.h" + +#include +#include +#include +#include +#include +#include +#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ +# include +#else +# include +# include +#endif + +#include "error.h" +#include "spawn-pipe.h" +#include "wait-process.h" +#include "gettext.h" + +#define _(str) gettext (str) + +#include "pipe-filter-aux.h" diff --git a/gettext-tools/gnulib-lib/pipe-filter-aux.h b/gettext-tools/gnulib-lib/pipe-filter-aux.h new file mode 100644 index 0000000..8f2a707 --- /dev/null +++ b/gettext-tools/gnulib-lib/pipe-filter-aux.h @@ -0,0 +1,103 @@ +/* Auxiliary code for filtering of data through a subprocess. + Copyright (C) 2001-2003, 2008-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2009. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _GL_INLINE_HEADER_BEGIN + #error "Please include config.h first." +#endif +_GL_INLINE_HEADER_BEGIN +#ifndef PIPE_FILTER_AUX_INLINE +# define PIPE_FILTER_AUX_INLINE _GL_INLINE +#endif + +#ifndef SSIZE_MAX +# define SSIZE_MAX ((ssize_t) (SIZE_MAX / 2)) +#endif + +/* We use a child process, and communicate through a bidirectional pipe. + To avoid deadlocks, let the child process decide when it wants to read + or to write, and let the parent behave accordingly. The parent uses + select() to know whether it must write or read. On platforms without + select(), we use non-blocking I/O. (This means the parent is busy + looping while waiting for the child. Not good. But hardly any platform + lacks select() nowadays.) */ + +/* On BeOS select() works only on sockets, not on normal file descriptors. */ +#ifdef __BEOS__ +# undef HAVE_SELECT +#endif + +#ifdef EINTR + +/* EINTR handling for close(), read(), write(), select(). + These functions can return -1/EINTR even though we don't have any + signal handlers set up, namely when we get interrupted via SIGSTOP. */ + +PIPE_FILTER_AUX_INLINE int +nonintr_close (int fd) +{ + int retval; + + do + retval = close (fd); + while (retval < 0 && errno == EINTR); + + return retval; +} +#undef close /* avoid warning related to gnulib module unistd */ +#define close nonintr_close + +PIPE_FILTER_AUX_INLINE ssize_t +nonintr_read (int fd, void *buf, size_t count) +{ + ssize_t retval; + + do + retval = read (fd, buf, count); + while (retval < 0 && errno == EINTR); + + return retval; +} +#define read nonintr_read + +PIPE_FILTER_AUX_INLINE ssize_t +nonintr_write (int fd, const void *buf, size_t count) +{ + ssize_t retval; + + do + retval = write (fd, buf, count); + while (retval < 0 && errno == EINTR); + + return retval; +} +#undef write /* avoid warning on VMS */ +#define write nonintr_write + +#endif + +/* Non-blocking I/O. */ +#if HAVE_SELECT +# define IS_EAGAIN(errcode) 0 +#else +# ifdef EWOULDBLOCK +# define IS_EAGAIN(errcode) ((errcode) == EAGAIN || (errcode) == EWOULDBLOCK) +# else +# define IS_EAGAIN(errcode) ((errcode) == EAGAIN) +# endif +#endif + +_GL_INLINE_HEADER_END diff --git a/gettext-tools/gnulib-lib/pipe-filter-ii.c b/gettext-tools/gnulib-lib/pipe-filter-ii.c new file mode 100644 index 0000000..db398d2 --- /dev/null +++ b/gettext-tools/gnulib-lib/pipe-filter-ii.c @@ -0,0 +1,474 @@ +/* Filtering of data through a subprocess. + Copyright (C) 2001-2003, 2008-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2009. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +#include "pipe-filter.h" + +#include +#include +#include +#include +#include +#include +#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ +# include +#else +# include +# include +#endif + +#include "error.h" +#include "spawn-pipe.h" +#include "wait-process.h" +#include "gettext.h" + +#define _(str) gettext (str) + +#include "pipe-filter-aux.h" + +#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ + +struct locals +{ + /* Arguments passed to pipe_filter_ii_execute. */ + prepare_write_fn prepare_write; + done_write_fn done_write; + prepare_read_fn prepare_read; + done_read_fn done_read; + + /* Management of the subprocess. */ + void *private_data; + int fd[2]; + + /* Status of the writer part. */ + volatile bool writer_terminated; + volatile int writer_errno; + /* Status of the reader part. */ + volatile bool reader_terminated; + volatile int reader_errno; +}; + +static unsigned int WINAPI +writer_thread_func (void *thread_arg) +{ + struct locals *l = (struct locals *) thread_arg; + + for (;;) + { + size_t bufsize; + const void *buf = l->prepare_write (&bufsize, l->private_data); + if (buf != NULL) + { + ssize_t nwritten = + write (l->fd[1], buf, bufsize > SSIZE_MAX ? SSIZE_MAX : bufsize); + if (nwritten < 0) + { + /* Don't assume that the gnulib modules 'write' and 'sigpipe' are + used. */ + if (GetLastError () == ERROR_NO_DATA) + errno = EPIPE; + l->writer_errno = errno; + break; + } + else if (nwritten > 0) + l->done_write ((void *) buf, nwritten, l->private_data); + } + else + break; + } + + l->writer_terminated = true; + _endthreadex (0); /* calls ExitThread (0) */ + abort (); +} + +static unsigned int WINAPI +reader_thread_func (void *thread_arg) +{ + struct locals *l = (struct locals *) thread_arg; + + for (;;) + { + size_t bufsize; + void *buf = l->prepare_read (&bufsize, l->private_data); + if (!(buf != NULL && bufsize > 0)) + /* prepare_read returned wrong values. */ + abort (); + { + ssize_t nread = + read (l->fd[0], buf, bufsize > SSIZE_MAX ? SSIZE_MAX : bufsize); + if (nread < 0) + { + l->reader_errno = errno; + break; + } + else if (nread > 0) + l->done_read (buf, nread, l->private_data); + else /* nread == 0 */ + break; + } + } + + l->reader_terminated = true; + _endthreadex (0); /* calls ExitThread (0) */ + abort (); +} + +#endif + +int +pipe_filter_ii_execute (const char *progname, + const char *prog_path, const char **prog_argv, + bool null_stderr, bool exit_on_error, + prepare_write_fn prepare_write, + done_write_fn done_write, + prepare_read_fn prepare_read, + done_read_fn done_read, + void *private_data) +{ + pid_t child; + int fd[2]; +#if !((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__) + struct sigaction orig_sigpipe_action; +#endif + + /* Open a bidirectional pipe to a subprocess. */ + child = create_pipe_bidi (progname, prog_path, (char **) prog_argv, + null_stderr, true, exit_on_error, + fd); + if (child == -1) + return -1; + +#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ + /* Native Windows API. */ + /* Pipes have a non-blocking mode, see function SetNamedPipeHandleState and + the article "Named Pipe Type, Read, and Wait Modes", but Microsoft's + documentation discourages its use. So don't use it. + Asynchronous I/O is also not suitable because it notifies the caller only + about completion of the I/O request, not about intermediate progress. + So do the writing and the reading in separate threads. */ + { + struct locals l; + HANDLE handles[2]; + #define writer_thread_handle handles[0] + #define reader_thread_handle handles[1] + bool writer_cleaned_up; + bool reader_cleaned_up; + + l.prepare_write = prepare_write; + l.done_write = done_write; + l.prepare_read = prepare_read; + l.done_read = done_read; + l.private_data = private_data; + l.fd[0] = fd[0]; + l.fd[1] = fd[1]; + l.writer_terminated = false; + l.writer_errno = 0; + l.reader_terminated = false; + l.reader_errno = 0; + + writer_thread_handle = + (HANDLE) _beginthreadex (NULL, 100000, writer_thread_func, &l, 0, NULL); + reader_thread_handle = + (HANDLE) _beginthreadex (NULL, 100000, reader_thread_func, &l, 0, NULL); + if (writer_thread_handle == NULL || reader_thread_handle == NULL) + { + if (exit_on_error) + error (EXIT_FAILURE, 0, _("creation of threads failed")); + if (reader_thread_handle != NULL) + CloseHandle (reader_thread_handle); + if (writer_thread_handle != NULL) + CloseHandle (writer_thread_handle); + goto fail; + } + writer_cleaned_up = false; + reader_cleaned_up = false; + for (;;) + { + DWORD ret; + + /* Here !(writer_cleaned_up && reader_cleaned_up). */ + if (writer_cleaned_up) + ret = WaitForSingleObject (reader_thread_handle, INFINITE); + else if (reader_cleaned_up) + ret = WaitForSingleObject (writer_thread_handle, INFINITE); + else + ret = WaitForMultipleObjects (2, handles, FALSE, INFINITE); + if (!(ret == WAIT_OBJECT_0 + 0 || ret == WAIT_OBJECT_0 + 1)) + abort (); + + if (l.writer_terminated) + { + /* The writer thread has just terminated. */ + l.writer_terminated = false; + CloseHandle (writer_thread_handle); + if (l.writer_errno) + { + if (exit_on_error) + error (EXIT_FAILURE, l.writer_errno, + _("write to %s subprocess failed"), progname); + if (!reader_cleaned_up) + { + TerminateThread (reader_thread_handle, 1); + CloseHandle (reader_thread_handle); + } + goto fail; + } + /* Tell the child there is nothing more the parent will send. */ + close (fd[1]); + writer_cleaned_up = true; + } + if (l.reader_terminated) + { + /* The reader thread has just terminated. */ + l.reader_terminated = false; + CloseHandle (reader_thread_handle); + if (l.reader_errno) + { + if (exit_on_error) + error (EXIT_FAILURE, l.reader_errno, + _("read from %s subprocess failed"), progname); + if (!writer_cleaned_up) + { + TerminateThread (writer_thread_handle, 1); + CloseHandle (writer_thread_handle); + } + goto fail; + } + reader_cleaned_up = true; + } + if (writer_cleaned_up && reader_cleaned_up) + break; + } + } +#else + /* When we write to the child process and it has just terminated, + we don't want to die from a SIGPIPE signal. So set the SIGPIPE + handler to SIG_IGN, and handle EPIPE error codes in write(). */ + { + struct sigaction sigpipe_action; + + sigpipe_action.sa_handler = SIG_IGN; + sigpipe_action.sa_flags = 0; + sigemptyset (&sigpipe_action.sa_mask); + if (sigaction (SIGPIPE, &sigpipe_action, &orig_sigpipe_action) < 0) + abort (); + } + + { +# if HAVE_SELECT + fd_set readfds; /* All bits except fd[0] are always cleared. */ + fd_set writefds; /* All bits except fd[1] are always cleared. */ +# endif + bool done_writing; + + /* Enable non-blocking I/O. This permits the read() and write() calls + to return -1/EAGAIN without blocking; this is important for polling + if HAVE_SELECT is not defined. It also permits the read() and write() + calls to return after partial reads/writes; this is important if + HAVE_SELECT is defined, because select() only says that some data + can be read or written, not how many. Without non-blocking I/O, + Linux 2.2.17 and BSD systems prefer to block instead of returning + with partial results. */ + { + int fcntl_flags; + + if ((fcntl_flags = fcntl (fd[1], F_GETFL, 0)) < 0 + || fcntl (fd[1], F_SETFL, fcntl_flags | O_NONBLOCK) == -1 + || (fcntl_flags = fcntl (fd[0], F_GETFL, 0)) < 0 + || fcntl (fd[0], F_SETFL, fcntl_flags | O_NONBLOCK) == -1) + { + if (exit_on_error) + error (EXIT_FAILURE, errno, + _("cannot set up nonblocking I/O to %s subprocess"), + progname); + goto fail; + } + } + +# if HAVE_SELECT + FD_ZERO (&readfds); + FD_ZERO (&writefds); +# endif + done_writing = false; + for (;;) + { +# if HAVE_SELECT + int n, retval; + + FD_SET (fd[0], &readfds); + n = fd[0] + 1; + if (!done_writing) + { + FD_SET (fd[1], &writefds); + if (n <= fd[1]) + n = fd[1] + 1; + } + + /* Do EINTR handling here instead of in pipe-filter-aux.h, + because select() cannot be referred to from an inline + function on AIX 7.1. */ + do + retval = select (n, &readfds, (!done_writing ? &writefds : NULL), + NULL, NULL); + while (retval < 0 && errno == EINTR); + n = retval; + + if (n < 0) + { + if (exit_on_error) + error (EXIT_FAILURE, errno, + _("communication with %s subprocess failed"), progname); + goto fail; + } + if (!done_writing && FD_ISSET (fd[1], &writefds)) + goto try_write; + if (FD_ISSET (fd[0], &readfds)) + goto try_read; + /* How could select() return if none of the two descriptors is ready? */ + abort (); +# endif + + /* Attempt to write. */ +# if HAVE_SELECT + try_write: +# endif + if (!done_writing) + { + size_t bufsize; + const void *buf = prepare_write (&bufsize, private_data); + if (buf != NULL) + { + /* Writing to a pipe in non-blocking mode is tricky: The + write() call may fail with EAGAIN, simply because sufficient + space is not available in the pipe. See POSIX:2008 + . + This happens actually on AIX and IRIX, when bufsize >= 8192 + (even though PIPE_BUF and pathconf ("/", _PC_PIPE_BUF) are + both 32768). */ + size_t attempt_to_write = + (bufsize > SSIZE_MAX ? SSIZE_MAX : bufsize); + for (;;) + { + ssize_t nwritten = write (fd[1], buf, attempt_to_write); + if (nwritten < 0) + { + if (errno == EAGAIN) + { + attempt_to_write = attempt_to_write / 2; + if (attempt_to_write == 0) + break; + } + else if (!IS_EAGAIN (errno)) + { + if (exit_on_error) + error (EXIT_FAILURE, errno, + _("write to %s subprocess failed"), + progname); + goto fail; + } + } + else + { + if (nwritten > 0) + done_write ((void *) buf, nwritten, private_data); + break; + } + } + } + else + { + /* Tell the child there is nothing more the parent will send. */ + close (fd[1]); + done_writing = true; + } + } +# if HAVE_SELECT + continue; +# endif + + /* Attempt to read. */ +# if HAVE_SELECT + try_read: +# endif + { + size_t bufsize; + void *buf = prepare_read (&bufsize, private_data); + if (!(buf != NULL && bufsize > 0)) + /* prepare_read returned wrong values. */ + abort (); + { + ssize_t nread = + read (fd[0], buf, bufsize > SSIZE_MAX ? SSIZE_MAX : bufsize); + if (nread < 0) + { + if (!IS_EAGAIN (errno)) + { + if (exit_on_error) + error (EXIT_FAILURE, errno, + _("read from %s subprocess failed"), progname); + goto fail; + } + } + else if (nread > 0) + done_read (buf, nread, private_data); + else /* nread == 0 */ + { + if (done_writing) + break; + } + } + } +# if HAVE_SELECT + continue; +# endif + } + } + + /* Restore SIGPIPE signal handler. */ + if (sigaction (SIGPIPE, &orig_sigpipe_action, NULL) < 0) + abort (); +#endif + + close (fd[0]); + + /* Remove zombie process from process list. */ + { + int exitstatus = + wait_subprocess (child, progname, false, null_stderr, + true, exit_on_error, NULL); + if (exitstatus != 0 && exit_on_error) + error (EXIT_FAILURE, 0, _("%s subprocess terminated with exit code %d"), + progname, exitstatus); + return exitstatus; + } + + fail: + { + int saved_errno = errno; + close (fd[1]); +#if !((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__) + if (sigaction (SIGPIPE, &orig_sigpipe_action, NULL) < 0) + abort (); +#endif + close (fd[0]); + wait_subprocess (child, progname, true, true, true, false, NULL); + errno = saved_errno; + return -1; + } +} diff --git a/gettext-tools/gnulib-lib/pipe-filter.h b/gettext-tools/gnulib-lib/pipe-filter.h new file mode 100644 index 0000000..4c15677 --- /dev/null +++ b/gettext-tools/gnulib-lib/pipe-filter.h @@ -0,0 +1,237 @@ +/* Filtering of data through a subprocess. + Copyright (C) 2009-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2009, + and Paolo Bonzini , 2009. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _PIPE_FILTER_H +#define _PIPE_FILTER_H + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Piping data through a subprocess in the naïve way - write data to the + subprocess and read from the subprocess when you expect it to have + produced results - is subject to two kinds of deadlocks: + 1) If you write more than PIPE_MAX bytes or, more generally, if you write + more bytes than the subprocess can handle at once, the subprocess + may write its data and wait on you to read it, but you are currently + busy writing. + 2) When you don't know ahead of time how many bytes the subprocess + will produce, the usual technique of calling read (fd, buf, BUFSIZ) + with a fixed BUFSIZ will, on Linux 2.2.17 and on BSD systems, cause + the read() call to block until *all* of the buffer has been filled. + But the subprocess cannot produce more data until you gave it more + input. But you are currently busy reading from it. + + This header file declares four set of functions that pipes data through + the subprocess, without risking these deadlocks. + + The side that writes data to the subprocess can be seen as a "generator", + that is, as a subroutine that produces and writes a piece of data here and + there, see . + But often, it can be written in the form of an "iterator", that is, as a + function that, each time it is invoked, produces and writes one more piece + of data. + + Similarly, the side that reads data from the subprocess can be seen as + a "generator", that is, as a subroutine that consumes a piece of data here + and there. Often, it can be written in the form of an "iterator", that + is, as a function that, each time it is invoked, consumes one more piece + of data. + + This header file declares four set of functions: + + | writer | reader | + ----------------+------------+------------+ + pipe_filter_ii | iterator | iterator | + pipe_filter_ig | iterator | generator | + pipe_filter_gi | generator | iterator | + pipe_filter_gg | generator | generator | + ----------------+------------+------------+ + + The last one uses threads in order to implement two generators running at + the same time. (For the relation between generators, coroutines, and + threads, see + and .) It is therefore only + portable to platforms with kernel-based POSIX threads. */ + +/* These two functions together describe the side that writes data to the + subprocess when it has the form of an iterator. + - prepare_write (&num_bytes, p) must either return a pointer to data that + is ready to be written and set num_bytes to the number of bytes ready to + be written, or return NULL when no more bytes are to be written. + - done_write (data_written, num_bytes_written) is called after + num_bytes_written bytes were written. It is guaranteed that + num_bytes_written > 0. + Here p is always the private_data argument passed to the main function. */ +typedef const void * (*prepare_write_fn) (size_t *num_bytes_p, + void *private_data); +typedef void (*done_write_fn) (void *data_written, size_t num_bytes_written, + void *private_data); + +/* These two functions together describe the side that reads data from the + subprocess when it has the form of an iterator. + - prepare_read (&num_bytes, p) must return a pointer to a buffer for data + that can be read and set num_bytes to the size of that buffer + (must be > 0). + - done_read (data_read, num_bytes_read, p) is called after num_bytes_read + bytes were read into the buffer. + Here p is always the private_data argument passed to the main function. */ +typedef void * (*prepare_read_fn) (size_t *num_bytes_p, + void *private_data); +typedef void (*done_read_fn) (void *data_read, size_t num_bytes_read, + void *private_data); + + +/* ============================ pipe_filter_ii ============================ */ + +/* Create a subprocess and pipe some data through it. + Arguments: + - progname is the program name used in error messages. + - prog_path is the file name of the program to invoke. + - prog_argv is a NULL terminated argument list, starting with prog_path as + first element. + - If null_stderr is true, the subprocess' stderr will be redirected to + /dev/null, and the usual error message to stderr will be omitted. + This is suitable when the subprocess does not fulfill an important task. + - If exit_on_error is true, any error will cause the main process to exit + with an error status. + If the subprocess does not terminate correctly, exit if exit_on_error is + true, otherwise return 127. + Callback arguments are as described above. + + Data is alternately written to the subprocess, through the functions + prepare_write and done_write, and read from the subprocess, through the + functions prepare_read and done_read. + + Note that the prepare_write/done_write functions and the + prepare_read/done_read functions may be called in different threads than + the current thread (depending on the platform). But they will not be + called after the pipe_filter_ii_execute function has returned. + + Return 0 upon success, or (only if exit_on_error is false): + - -1 with errno set upon failure, + - the positive exit code of the subprocess if that failed. */ +extern int + pipe_filter_ii_execute (const char *progname, + const char *prog_path, const char **prog_argv, + bool null_stderr, bool exit_on_error, + prepare_write_fn prepare_write, + done_write_fn done_write, + prepare_read_fn prepare_read, + done_read_fn done_read, + void *private_data); + + +/* ============================ pipe_filter_ig ============================ */ + +struct pipe_filter_ig; + + +/* ============================ pipe_filter_gi ============================ */ + +struct pipe_filter_gi; + +/* Create a subprocess and pipe some data through it. + Arguments: + - progname is the program name used in error messages. + - prog_path is the file name of the program to invoke. + - prog_argv is a NULL terminated argument list, starting with + prog_path as first element. + - If null_stderr is true, the subprocess' stderr will be redirected + to /dev/null, and the usual error message to stderr will be + omitted. This is suitable when the subprocess does not fulfill an + important task. + - If exit_on_error is true, any error will cause the main process to + exit with an error status. + If the subprocess does not start correctly, exit if exit_on_error is + true, otherwise return NULL and set errno. + + The caller will write to the subprocess through pipe_filter_gi_write + and finally call pipe_filter_gi_close. During such calls, the + prepare_read and done_read function may be called to process any data + that the subprocess has written. + + Note that the prepare_read/done_read functions may be called in a + different thread than the current thread (depending on the platform). + But they will not be called after the pipe_filter_gi_close function has + returned. + + Return the freshly created 'struct pipe_filter_gi'. */ +extern struct pipe_filter_gi * + pipe_filter_gi_create (const char *progname, + const char *prog_path, const char **prog_argv, + bool null_stderr, bool exit_on_error, + prepare_read_fn prepare_read, + done_read_fn done_read, + void *private_data); + +/* Write size bytes starting at buf into the pipe and in the meanwhile + possibly call the prepare_read and done_read functions specified to + pipe_filter_gi_create. + + Note that the prepare_read/done_read functions may be called in a + different thread than the current thread (depending on the platform). + However, they will always be called before pipe_filter_gi_write has + returned, or otherwise not sooner than the next call to + pipe_filter_gi_write or pipe_filter_gi_close. + + Return only after all the entire buffer has been written to the pipe or + the subprocess has exited. + + Return 0 upon success, or (only if exit_on_error is false): + - -1 with errno set upon failure, + - the positive exit code of the subprocess if that failed. */ +extern int + pipe_filter_gi_write (struct pipe_filter_gi *filter, + const void *buf, size_t size); + +/* Finish reading the output via the prepare_read/done_read functions + specified to pipe_filter_gi_create. + + Note that the prepare_read/done_read functions may be called in a + different thread than the current thread (depending on the platform). + However, they will always be called before pipe_filter_gi_close has + returned. + + The write side of the pipe is closed as soon as pipe_filter_gi_close + starts, while the read side will be closed just before it finishes. + + Return 0 upon success, or (only if exit_on_error is false): + - -1 with errno set upon failure, + - the positive exit code of the subprocess if that failed. */ +extern int + pipe_filter_gi_close (struct pipe_filter_gi *filter); + + +/* ============================ pipe_filter_gg ============================ */ + + +/* ======================================================================== */ + + +#ifdef __cplusplus +} +#endif + + +#endif /* _PIPE_FILTER_H */ diff --git a/gettext-tools/gnulib-lib/pipe-safer.c b/gettext-tools/gnulib-lib/pipe-safer.c new file mode 100644 index 0000000..70fb40f --- /dev/null +++ b/gettext-tools/gnulib-lib/pipe-safer.c @@ -0,0 +1,56 @@ +/* Invoke pipe, but avoid some glitches. + Copyright (C) 2005-2006, 2009-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Written by Jim Meyering. */ + +#include + +#include "unistd-safer.h" + +#include +#include + +/* Like pipe, but ensure that neither of the file descriptors is + STDIN_FILENO, STDOUT_FILENO, or STDERR_FILENO. Fail with ENOSYS on + platforms that lack pipe. */ + +int +pipe_safer (int fd[2]) +{ +#if HAVE_PIPE + if (pipe (fd) == 0) + { + int i; + for (i = 0; i < 2; i++) + { + fd[i] = fd_safer (fd[i]); + if (fd[i] < 0) + { + int e = errno; + close (fd[1 - i]); + errno = e; + return -1; + } + } + + return 0; + } +#else + errno = ENOSYS; +#endif + + return -1; +} diff --git a/gettext-tools/gnulib-lib/pipe2-safer.c b/gettext-tools/gnulib-lib/pipe2-safer.c new file mode 100644 index 0000000..66dcb75 --- /dev/null +++ b/gettext-tools/gnulib-lib/pipe2-safer.c @@ -0,0 +1,52 @@ +/* Invoke pipe2, but avoid some glitches. + Copyright (C) 2005-2006, 2009-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Written by Eric Blake. */ + +#include + +/* Specification. */ +#include "unistd-safer.h" + +#include +#include + +/* Like pipe2, but ensure that neither of the file descriptors is + STDIN_FILENO, STDOUT_FILENO, or STDERR_FILENO. */ + +int +pipe2_safer (int fd[2], int flags) +{ + /* This is a generalization of the pipe_safer implementation. */ + if (pipe2 (fd, flags) == 0) + { + int i; + for (i = 0; i < 2; i++) + { + fd[i] = fd_safer_flag (fd[i], flags); + if (fd[i] < 0) + { + int e = errno; + close (fd[1 - i]); + errno = e; + return -1; + } + } + + return 0; + } + return -1; +} diff --git a/gettext-tools/gnulib-lib/pipe2.c b/gettext-tools/gnulib-lib/pipe2.c new file mode 100644 index 0000000..61c42a0 --- /dev/null +++ b/gettext-tools/gnulib-lib/pipe2.c @@ -0,0 +1,168 @@ +/* Create a pipe, with specific opening flags. + Copyright (C) 2009-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, see . */ + +#include + +/* Specification. */ +#include + +#include +#include + +#include "binary-io.h" +#include "verify.h" + +#if GNULIB_defined_O_NONBLOCK +# include "nonblocking.h" +#endif + +#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ +/* Native Windows API. */ + +# include + +#endif + +int +pipe2 (int fd[2], int flags) +{ + /* Mingw _pipe() corrupts fd on failure; also, if we succeed at + creating the pipe but later fail at changing fcntl, we want + to leave fd unchanged: http://austingroupbugs.net/view.php?id=467 */ + int tmp[2]; + tmp[0] = fd[0]; + tmp[1] = fd[1]; + +#if HAVE_PIPE2 +# undef pipe2 + /* Try the system call first, if it exists. (We may be running with a glibc + that has the function but with an older kernel that lacks it.) */ + { + /* Cache the information whether the system call really exists. */ + static int have_pipe2_really; /* 0 = unknown, 1 = yes, -1 = no */ + if (have_pipe2_really >= 0) + { + int result = pipe2 (fd, flags); + if (!(result < 0 && errno == ENOSYS)) + { + have_pipe2_really = 1; + return result; + } + have_pipe2_really = -1; + } + } +#endif + + /* Check the supported flags. */ + if ((flags & ~(O_CLOEXEC | O_NONBLOCK | O_BINARY | O_TEXT)) != 0) + { + errno = EINVAL; + return -1; + } + +#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ +/* Native Windows API. */ + + if (_pipe (fd, 4096, flags & ~O_NONBLOCK) < 0) + { + fd[0] = tmp[0]; + fd[1] = tmp[1]; + return -1; + } + + /* O_NONBLOCK handling. + On native Windows platforms, O_NONBLOCK is defined by gnulib. Use the + functions defined by the gnulib module 'nonblocking'. */ +# if GNULIB_defined_O_NONBLOCK + if (flags & O_NONBLOCK) + { + if (set_nonblocking_flag (fd[0], true) != 0 + || set_nonblocking_flag (fd[1], true) != 0) + goto fail; + } +# else + { + verify (O_NONBLOCK == 0); + } +# endif + + return 0; + +#else +/* Unix API. */ + + if (pipe (fd) < 0) + return -1; + + /* POSIX + says that initially, the O_NONBLOCK and FD_CLOEXEC flags are cleared on + both fd[0] and fd[1]. */ + + /* O_NONBLOCK handling. + On Unix platforms, O_NONBLOCK is defined by the system. Use fcntl(). */ + if (flags & O_NONBLOCK) + { + int fcntl_flags; + + if ((fcntl_flags = fcntl (fd[1], F_GETFL, 0)) < 0 + || fcntl (fd[1], F_SETFL, fcntl_flags | O_NONBLOCK) == -1 + || (fcntl_flags = fcntl (fd[0], F_GETFL, 0)) < 0 + || fcntl (fd[0], F_SETFL, fcntl_flags | O_NONBLOCK) == -1) + goto fail; + } + + if (flags & O_CLOEXEC) + { + int fcntl_flags; + + if ((fcntl_flags = fcntl (fd[1], F_GETFD, 0)) < 0 + || fcntl (fd[1], F_SETFD, fcntl_flags | FD_CLOEXEC) == -1 + || (fcntl_flags = fcntl (fd[0], F_GETFD, 0)) < 0 + || fcntl (fd[0], F_SETFD, fcntl_flags | FD_CLOEXEC) == -1) + goto fail; + } + +# if O_BINARY + if (flags & O_BINARY) + { + set_binary_mode (fd[1], O_BINARY); + set_binary_mode (fd[0], O_BINARY); + } + else if (flags & O_TEXT) + { + set_binary_mode (fd[1], O_TEXT); + set_binary_mode (fd[0], O_TEXT); + } +# endif + + return 0; + +#endif + +#if GNULIB_defined_O_NONBLOCK || \ + !((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__) + fail: + { + int saved_errno = errno; + close (fd[0]); + close (fd[1]); + fd[0] = tmp[0]; + fd[1] = tmp[1]; + errno = saved_errno; + return -1; + } +#endif +} diff --git a/gettext-tools/gnulib-lib/printf-args.c b/gettext-tools/gnulib-lib/printf-args.c new file mode 100644 index 0000000..39cd0a4 --- /dev/null +++ b/gettext-tools/gnulib-lib/printf-args.c @@ -0,0 +1,187 @@ +/* Decomposed printf argument list. + Copyright (C) 1999, 2002-2003, 2005-2007, 2009-2014 Free Software + Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, see . */ + +/* This file can be parametrized with the following macros: + ENABLE_UNISTDIO Set to 1 to enable the unistdio extensions. + PRINTF_FETCHARGS Name of the function to be defined. + STATIC Set to 'static' to declare the function static. */ + +#ifndef PRINTF_FETCHARGS +# include +#endif + +/* Specification. */ +#ifndef PRINTF_FETCHARGS +# include "printf-args.h" +#endif + +#ifdef STATIC +STATIC +#endif +int +PRINTF_FETCHARGS (va_list args, arguments *a) +{ + size_t i; + argument *ap; + + for (i = 0, ap = &a->arg[0]; i < a->count; i++, ap++) + switch (ap->type) + { + case TYPE_SCHAR: + ap->a.a_schar = va_arg (args, /*signed char*/ int); + break; + case TYPE_UCHAR: + ap->a.a_uchar = va_arg (args, /*unsigned char*/ int); + break; + case TYPE_SHORT: + ap->a.a_short = va_arg (args, /*short*/ int); + break; + case TYPE_USHORT: + ap->a.a_ushort = va_arg (args, /*unsigned short*/ int); + break; + case TYPE_INT: + ap->a.a_int = va_arg (args, int); + break; + case TYPE_UINT: + ap->a.a_uint = va_arg (args, unsigned int); + break; + case TYPE_LONGINT: + ap->a.a_longint = va_arg (args, long int); + break; + case TYPE_ULONGINT: + ap->a.a_ulongint = va_arg (args, unsigned long int); + break; +#if HAVE_LONG_LONG_INT + case TYPE_LONGLONGINT: + ap->a.a_longlongint = va_arg (args, long long int); + break; + case TYPE_ULONGLONGINT: + ap->a.a_ulonglongint = va_arg (args, unsigned long long int); + break; +#endif + case TYPE_DOUBLE: + ap->a.a_double = va_arg (args, double); + break; + case TYPE_LONGDOUBLE: + ap->a.a_longdouble = va_arg (args, long double); + break; + case TYPE_CHAR: + ap->a.a_char = va_arg (args, int); + break; +#if HAVE_WINT_T + case TYPE_WIDE_CHAR: + /* Although ISO C 99 7.24.1.(2) says that wint_t is "unchanged by + default argument promotions", this is not the case in mingw32, + where wint_t is 'unsigned short'. */ + ap->a.a_wide_char = + (sizeof (wint_t) < sizeof (int) + ? (wint_t) va_arg (args, int) + : va_arg (args, wint_t)); + break; +#endif + case TYPE_STRING: + ap->a.a_string = va_arg (args, const char *); + /* A null pointer is an invalid argument for "%s", but in practice + it occurs quite frequently in printf statements that produce + debug output. Use a fallback in this case. */ + if (ap->a.a_string == NULL) + ap->a.a_string = "(NULL)"; + break; +#if HAVE_WCHAR_T + case TYPE_WIDE_STRING: + ap->a.a_wide_string = va_arg (args, const wchar_t *); + /* A null pointer is an invalid argument for "%ls", but in practice + it occurs quite frequently in printf statements that produce + debug output. Use a fallback in this case. */ + if (ap->a.a_wide_string == NULL) + { + static const wchar_t wide_null_string[] = + { + (wchar_t)'(', + (wchar_t)'N', (wchar_t)'U', (wchar_t)'L', (wchar_t)'L', + (wchar_t)')', + (wchar_t)0 + }; + ap->a.a_wide_string = wide_null_string; + } + break; +#endif + case TYPE_POINTER: + ap->a.a_pointer = va_arg (args, void *); + break; + case TYPE_COUNT_SCHAR_POINTER: + ap->a.a_count_schar_pointer = va_arg (args, signed char *); + break; + case TYPE_COUNT_SHORT_POINTER: + ap->a.a_count_short_pointer = va_arg (args, short *); + break; + case TYPE_COUNT_INT_POINTER: + ap->a.a_count_int_pointer = va_arg (args, int *); + break; + case TYPE_COUNT_LONGINT_POINTER: + ap->a.a_count_longint_pointer = va_arg (args, long int *); + break; +#if HAVE_LONG_LONG_INT + case TYPE_COUNT_LONGLONGINT_POINTER: + ap->a.a_count_longlongint_pointer = va_arg (args, long long int *); + break; +#endif +#if ENABLE_UNISTDIO + /* The unistdio extensions. */ + case TYPE_U8_STRING: + ap->a.a_u8_string = va_arg (args, const uint8_t *); + /* A null pointer is an invalid argument for "%U", but in practice + it occurs quite frequently in printf statements that produce + debug output. Use a fallback in this case. */ + if (ap->a.a_u8_string == NULL) + { + static const uint8_t u8_null_string[] = + { '(', 'N', 'U', 'L', 'L', ')', 0 }; + ap->a.a_u8_string = u8_null_string; + } + break; + case TYPE_U16_STRING: + ap->a.a_u16_string = va_arg (args, const uint16_t *); + /* A null pointer is an invalid argument for "%lU", but in practice + it occurs quite frequently in printf statements that produce + debug output. Use a fallback in this case. */ + if (ap->a.a_u16_string == NULL) + { + static const uint16_t u16_null_string[] = + { '(', 'N', 'U', 'L', 'L', ')', 0 }; + ap->a.a_u16_string = u16_null_string; + } + break; + case TYPE_U32_STRING: + ap->a.a_u32_string = va_arg (args, const uint32_t *); + /* A null pointer is an invalid argument for "%llU", but in practice + it occurs quite frequently in printf statements that produce + debug output. Use a fallback in this case. */ + if (ap->a.a_u32_string == NULL) + { + static const uint32_t u32_null_string[] = + { '(', 'N', 'U', 'L', 'L', ')', 0 }; + ap->a.a_u32_string = u32_null_string; + } + break; +#endif + default: + /* Unknown type. */ + return -1; + } + return 0; +} diff --git a/gettext-tools/gnulib-lib/printf-args.h b/gettext-tools/gnulib-lib/printf-args.h new file mode 100644 index 0000000..9364eed --- /dev/null +++ b/gettext-tools/gnulib-lib/printf-args.h @@ -0,0 +1,158 @@ +/* Decomposed printf argument list. + Copyright (C) 1999, 2002-2003, 2006-2007, 2011-2014 Free Software + Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, see . */ + +#ifndef _PRINTF_ARGS_H +#define _PRINTF_ARGS_H + +/* This file can be parametrized with the following macros: + ENABLE_UNISTDIO Set to 1 to enable the unistdio extensions. + PRINTF_FETCHARGS Name of the function to be declared. + STATIC Set to 'static' to declare the function static. */ + +/* Default parameters. */ +#ifndef PRINTF_FETCHARGS +# define PRINTF_FETCHARGS printf_fetchargs +#endif + +/* Get size_t. */ +#include + +/* Get wchar_t. */ +#if HAVE_WCHAR_T +# include +#endif + +/* Get wint_t. */ +#if HAVE_WINT_T +# include +#endif + +/* Get va_list. */ +#include + + +/* Argument types */ +typedef enum +{ + TYPE_NONE, + TYPE_SCHAR, + TYPE_UCHAR, + TYPE_SHORT, + TYPE_USHORT, + TYPE_INT, + TYPE_UINT, + TYPE_LONGINT, + TYPE_ULONGINT, +#if HAVE_LONG_LONG_INT + TYPE_LONGLONGINT, + TYPE_ULONGLONGINT, +#endif + TYPE_DOUBLE, + TYPE_LONGDOUBLE, + TYPE_CHAR, +#if HAVE_WINT_T + TYPE_WIDE_CHAR, +#endif + TYPE_STRING, +#if HAVE_WCHAR_T + TYPE_WIDE_STRING, +#endif + TYPE_POINTER, + TYPE_COUNT_SCHAR_POINTER, + TYPE_COUNT_SHORT_POINTER, + TYPE_COUNT_INT_POINTER, + TYPE_COUNT_LONGINT_POINTER +#if HAVE_LONG_LONG_INT +, TYPE_COUNT_LONGLONGINT_POINTER +#endif +#if ENABLE_UNISTDIO + /* The unistdio extensions. */ +, TYPE_U8_STRING +, TYPE_U16_STRING +, TYPE_U32_STRING +#endif +} arg_type; + +/* Polymorphic argument */ +typedef struct +{ + arg_type type; + union + { + signed char a_schar; + unsigned char a_uchar; + short a_short; + unsigned short a_ushort; + int a_int; + unsigned int a_uint; + long int a_longint; + unsigned long int a_ulongint; +#if HAVE_LONG_LONG_INT + long long int a_longlongint; + unsigned long long int a_ulonglongint; +#endif + float a_float; + double a_double; + long double a_longdouble; + int a_char; +#if HAVE_WINT_T + wint_t a_wide_char; +#endif + const char* a_string; +#if HAVE_WCHAR_T + const wchar_t* a_wide_string; +#endif + void* a_pointer; + signed char * a_count_schar_pointer; + short * a_count_short_pointer; + int * a_count_int_pointer; + long int * a_count_longint_pointer; +#if HAVE_LONG_LONG_INT + long long int * a_count_longlongint_pointer; +#endif +#if ENABLE_UNISTDIO + /* The unistdio extensions. */ + const uint8_t * a_u8_string; + const uint16_t * a_u16_string; + const uint32_t * a_u32_string; +#endif + } + a; +} +argument; + +/* Number of directly allocated arguments (no malloc() needed). */ +#define N_DIRECT_ALLOC_ARGUMENTS 7 + +typedef struct +{ + size_t count; + argument *arg; + argument direct_alloc_arg[N_DIRECT_ALLOC_ARGUMENTS]; +} +arguments; + + +/* Fetch the arguments, putting them into a. */ +#ifdef STATIC +STATIC +#else +extern +#endif +int PRINTF_FETCHARGS (va_list args, arguments *a); + +#endif /* _PRINTF_ARGS_H */ diff --git a/gettext-tools/gnulib-lib/printf-parse.c b/gettext-tools/gnulib-lib/printf-parse.c new file mode 100644 index 0000000..131d0f0 --- /dev/null +++ b/gettext-tools/gnulib-lib/printf-parse.c @@ -0,0 +1,638 @@ +/* Formatted output to strings. + Copyright (C) 1999-2000, 2002-2003, 2006-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, see . */ + +/* This file can be parametrized with the following macros: + CHAR_T The element type of the format string. + CHAR_T_ONLY_ASCII Set to 1 to enable verification that all characters + in the format string are ASCII. + DIRECTIVE Structure denoting a format directive. + Depends on CHAR_T. + DIRECTIVES Structure denoting the set of format directives of a + format string. Depends on CHAR_T. + PRINTF_PARSE Function that parses a format string. + Depends on CHAR_T. + STATIC Set to 'static' to declare the function static. + ENABLE_UNISTDIO Set to 1 to enable the unistdio extensions. */ + +#ifndef PRINTF_PARSE +# include +#endif + +/* Specification. */ +#ifndef PRINTF_PARSE +# include "printf-parse.h" +#endif + +/* Default parameters. */ +#ifndef PRINTF_PARSE +# define PRINTF_PARSE printf_parse +# define CHAR_T char +# define DIRECTIVE char_directive +# define DIRECTIVES char_directives +#endif + +/* Get size_t, NULL. */ +#include + +/* Get intmax_t. */ +#if defined IN_LIBINTL || defined IN_LIBASPRINTF +# if HAVE_STDINT_H_WITH_UINTMAX +# include +# endif +# if HAVE_INTTYPES_H_WITH_UINTMAX +# include +# endif +#else +# include +#endif + +/* malloc(), realloc(), free(). */ +#include + +/* memcpy(). */ +#include + +/* errno. */ +#include + +/* Checked size_t computations. */ +#include "xsize.h" + +#if CHAR_T_ONLY_ASCII +/* c_isascii(). */ +# include "c-ctype.h" +#endif + +#ifdef STATIC +STATIC +#endif +int +PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a) +{ + const CHAR_T *cp = format; /* pointer into format */ + size_t arg_posn = 0; /* number of regular arguments consumed */ + size_t d_allocated; /* allocated elements of d->dir */ + size_t a_allocated; /* allocated elements of a->arg */ + size_t max_width_length = 0; + size_t max_precision_length = 0; + + d->count = 0; + d_allocated = N_DIRECT_ALLOC_DIRECTIVES; + d->dir = d->direct_alloc_dir; + + a->count = 0; + a_allocated = N_DIRECT_ALLOC_ARGUMENTS; + a->arg = a->direct_alloc_arg; + +#define REGISTER_ARG(_index_,_type_) \ + { \ + size_t n = (_index_); \ + if (n >= a_allocated) \ + { \ + size_t memory_size; \ + argument *memory; \ + \ + a_allocated = xtimes (a_allocated, 2); \ + if (a_allocated <= n) \ + a_allocated = xsum (n, 1); \ + memory_size = xtimes (a_allocated, sizeof (argument)); \ + if (size_overflow_p (memory_size)) \ + /* Overflow, would lead to out of memory. */ \ + goto out_of_memory; \ + memory = (argument *) (a->arg != a->direct_alloc_arg \ + ? realloc (a->arg, memory_size) \ + : malloc (memory_size)); \ + if (memory == NULL) \ + /* Out of memory. */ \ + goto out_of_memory; \ + if (a->arg == a->direct_alloc_arg) \ + memcpy (memory, a->arg, a->count * sizeof (argument)); \ + a->arg = memory; \ + } \ + while (a->count <= n) \ + a->arg[a->count++].type = TYPE_NONE; \ + if (a->arg[n].type == TYPE_NONE) \ + a->arg[n].type = (_type_); \ + else if (a->arg[n].type != (_type_)) \ + /* Ambiguous type for positional argument. */ \ + goto error; \ + } + + while (*cp != '\0') + { + CHAR_T c = *cp++; + if (c == '%') + { + size_t arg_index = ARG_NONE; + DIRECTIVE *dp = &d->dir[d->count]; /* pointer to next directive */ + + /* Initialize the next directive. */ + dp->dir_start = cp - 1; + dp->flags = 0; + dp->width_start = NULL; + dp->width_end = NULL; + dp->width_arg_index = ARG_NONE; + dp->precision_start = NULL; + dp->precision_end = NULL; + dp->precision_arg_index = ARG_NONE; + dp->arg_index = ARG_NONE; + + /* Test for positional argument. */ + if (*cp >= '0' && *cp <= '9') + { + const CHAR_T *np; + + for (np = cp; *np >= '0' && *np <= '9'; np++) + ; + if (*np == '$') + { + size_t n = 0; + + for (np = cp; *np >= '0' && *np <= '9'; np++) + n = xsum (xtimes (n, 10), *np - '0'); + if (n == 0) + /* Positional argument 0. */ + goto error; + if (size_overflow_p (n)) + /* n too large, would lead to out of memory later. */ + goto error; + arg_index = n - 1; + cp = np + 1; + } + } + + /* Read the flags. */ + for (;;) + { + if (*cp == '\'') + { + dp->flags |= FLAG_GROUP; + cp++; + } + else if (*cp == '-') + { + dp->flags |= FLAG_LEFT; + cp++; + } + else if (*cp == '+') + { + dp->flags |= FLAG_SHOWSIGN; + cp++; + } + else if (*cp == ' ') + { + dp->flags |= FLAG_SPACE; + cp++; + } + else if (*cp == '#') + { + dp->flags |= FLAG_ALT; + cp++; + } + else if (*cp == '0') + { + dp->flags |= FLAG_ZERO; + cp++; + } +#if __GLIBC__ >= 2 && !defined __UCLIBC__ + else if (*cp == 'I') + { + dp->flags |= FLAG_LOCALIZED; + cp++; + } +#endif + else + break; + } + + /* Parse the field width. */ + if (*cp == '*') + { + dp->width_start = cp; + cp++; + dp->width_end = cp; + if (max_width_length < 1) + max_width_length = 1; + + /* Test for positional argument. */ + if (*cp >= '0' && *cp <= '9') + { + const CHAR_T *np; + + for (np = cp; *np >= '0' && *np <= '9'; np++) + ; + if (*np == '$') + { + size_t n = 0; + + for (np = cp; *np >= '0' && *np <= '9'; np++) + n = xsum (xtimes (n, 10), *np - '0'); + if (n == 0) + /* Positional argument 0. */ + goto error; + if (size_overflow_p (n)) + /* n too large, would lead to out of memory later. */ + goto error; + dp->width_arg_index = n - 1; + cp = np + 1; + } + } + if (dp->width_arg_index == ARG_NONE) + { + dp->width_arg_index = arg_posn++; + if (dp->width_arg_index == ARG_NONE) + /* arg_posn wrapped around. */ + goto error; + } + REGISTER_ARG (dp->width_arg_index, TYPE_INT); + } + else if (*cp >= '0' && *cp <= '9') + { + size_t width_length; + + dp->width_start = cp; + for (; *cp >= '0' && *cp <= '9'; cp++) + ; + dp->width_end = cp; + width_length = dp->width_end - dp->width_start; + if (max_width_length < width_length) + max_width_length = width_length; + } + + /* Parse the precision. */ + if (*cp == '.') + { + cp++; + if (*cp == '*') + { + dp->precision_start = cp - 1; + cp++; + dp->precision_end = cp; + if (max_precision_length < 2) + max_precision_length = 2; + + /* Test for positional argument. */ + if (*cp >= '0' && *cp <= '9') + { + const CHAR_T *np; + + for (np = cp; *np >= '0' && *np <= '9'; np++) + ; + if (*np == '$') + { + size_t n = 0; + + for (np = cp; *np >= '0' && *np <= '9'; np++) + n = xsum (xtimes (n, 10), *np - '0'); + if (n == 0) + /* Positional argument 0. */ + goto error; + if (size_overflow_p (n)) + /* n too large, would lead to out of memory + later. */ + goto error; + dp->precision_arg_index = n - 1; + cp = np + 1; + } + } + if (dp->precision_arg_index == ARG_NONE) + { + dp->precision_arg_index = arg_posn++; + if (dp->precision_arg_index == ARG_NONE) + /* arg_posn wrapped around. */ + goto error; + } + REGISTER_ARG (dp->precision_arg_index, TYPE_INT); + } + else + { + size_t precision_length; + + dp->precision_start = cp - 1; + for (; *cp >= '0' && *cp <= '9'; cp++) + ; + dp->precision_end = cp; + precision_length = dp->precision_end - dp->precision_start; + if (max_precision_length < precision_length) + max_precision_length = precision_length; + } + } + + { + arg_type type; + + /* Parse argument type/size specifiers. */ + { + int flags = 0; + + for (;;) + { + if (*cp == 'h') + { + flags |= (1 << (flags & 1)); + cp++; + } + else if (*cp == 'L') + { + flags |= 4; + cp++; + } + else if (*cp == 'l') + { + flags += 8; + cp++; + } + else if (*cp == 'j') + { + if (sizeof (intmax_t) > sizeof (long)) + { + /* intmax_t = long long */ + flags += 16; + } + else if (sizeof (intmax_t) > sizeof (int)) + { + /* intmax_t = long */ + flags += 8; + } + cp++; + } + else if (*cp == 'z' || *cp == 'Z') + { + /* 'z' is standardized in ISO C 99, but glibc uses 'Z' + because the warning facility in gcc-2.95.2 understands + only 'Z' (see gcc-2.95.2/gcc/c-common.c:1784). */ + if (sizeof (size_t) > sizeof (long)) + { + /* size_t = long long */ + flags += 16; + } + else if (sizeof (size_t) > sizeof (int)) + { + /* size_t = long */ + flags += 8; + } + cp++; + } + else if (*cp == 't') + { + if (sizeof (ptrdiff_t) > sizeof (long)) + { + /* ptrdiff_t = long long */ + flags += 16; + } + else if (sizeof (ptrdiff_t) > sizeof (int)) + { + /* ptrdiff_t = long */ + flags += 8; + } + cp++; + } +#if defined __APPLE__ && defined __MACH__ + /* On Mac OS X 10.3, PRIdMAX is defined as "qd". + We cannot change it to "lld" because PRIdMAX must also + be understood by the system's printf routines. */ + else if (*cp == 'q') + { + if (64 / 8 > sizeof (long)) + { + /* int64_t = long long */ + flags += 16; + } + else + { + /* int64_t = long */ + flags += 8; + } + cp++; + } +#endif +#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ + /* On native Windows, PRIdMAX is defined as "I64d". + We cannot change it to "lld" because PRIdMAX must also + be understood by the system's printf routines. */ + else if (*cp == 'I' && cp[1] == '6' && cp[2] == '4') + { + if (64 / 8 > sizeof (long)) + { + /* __int64 = long long */ + flags += 16; + } + else + { + /* __int64 = long */ + flags += 8; + } + cp += 3; + } +#endif + else + break; + } + + /* Read the conversion character. */ + c = *cp++; + switch (c) + { + case 'd': case 'i': +#if HAVE_LONG_LONG_INT + /* If 'long long' exists and is larger than 'long': */ + if (flags >= 16 || (flags & 4)) + type = TYPE_LONGLONGINT; + else +#endif + /* If 'long long' exists and is the same as 'long', we parse + "lld" into TYPE_LONGINT. */ + if (flags >= 8) + type = TYPE_LONGINT; + else if (flags & 2) + type = TYPE_SCHAR; + else if (flags & 1) + type = TYPE_SHORT; + else + type = TYPE_INT; + break; + case 'o': case 'u': case 'x': case 'X': +#if HAVE_LONG_LONG_INT + /* If 'long long' exists and is larger than 'long': */ + if (flags >= 16 || (flags & 4)) + type = TYPE_ULONGLONGINT; + else +#endif + /* If 'unsigned long long' exists and is the same as + 'unsigned long', we parse "llu" into TYPE_ULONGINT. */ + if (flags >= 8) + type = TYPE_ULONGINT; + else if (flags & 2) + type = TYPE_UCHAR; + else if (flags & 1) + type = TYPE_USHORT; + else + type = TYPE_UINT; + break; + case 'f': case 'F': case 'e': case 'E': case 'g': case 'G': + case 'a': case 'A': + if (flags >= 16 || (flags & 4)) + type = TYPE_LONGDOUBLE; + else + type = TYPE_DOUBLE; + break; + case 'c': + if (flags >= 8) +#if HAVE_WINT_T + type = TYPE_WIDE_CHAR; +#else + goto error; +#endif + else + type = TYPE_CHAR; + break; +#if HAVE_WINT_T + case 'C': + type = TYPE_WIDE_CHAR; + c = 'c'; + break; +#endif + case 's': + if (flags >= 8) +#if HAVE_WCHAR_T + type = TYPE_WIDE_STRING; +#else + goto error; +#endif + else + type = TYPE_STRING; + break; +#if HAVE_WCHAR_T + case 'S': + type = TYPE_WIDE_STRING; + c = 's'; + break; +#endif + case 'p': + type = TYPE_POINTER; + break; + case 'n': +#if HAVE_LONG_LONG_INT + /* If 'long long' exists and is larger than 'long': */ + if (flags >= 16 || (flags & 4)) + type = TYPE_COUNT_LONGLONGINT_POINTER; + else +#endif + /* If 'long long' exists and is the same as 'long', we parse + "lln" into TYPE_COUNT_LONGINT_POINTER. */ + if (flags >= 8) + type = TYPE_COUNT_LONGINT_POINTER; + else if (flags & 2) + type = TYPE_COUNT_SCHAR_POINTER; + else if (flags & 1) + type = TYPE_COUNT_SHORT_POINTER; + else + type = TYPE_COUNT_INT_POINTER; + break; +#if ENABLE_UNISTDIO + /* The unistdio extensions. */ + case 'U': + if (flags >= 16) + type = TYPE_U32_STRING; + else if (flags >= 8) + type = TYPE_U16_STRING; + else + type = TYPE_U8_STRING; + break; +#endif + case '%': + type = TYPE_NONE; + break; + default: + /* Unknown conversion character. */ + goto error; + } + } + + if (type != TYPE_NONE) + { + dp->arg_index = arg_index; + if (dp->arg_index == ARG_NONE) + { + dp->arg_index = arg_posn++; + if (dp->arg_index == ARG_NONE) + /* arg_posn wrapped around. */ + goto error; + } + REGISTER_ARG (dp->arg_index, type); + } + dp->conversion = c; + dp->dir_end = cp; + } + + d->count++; + if (d->count >= d_allocated) + { + size_t memory_size; + DIRECTIVE *memory; + + d_allocated = xtimes (d_allocated, 2); + memory_size = xtimes (d_allocated, sizeof (DIRECTIVE)); + if (size_overflow_p (memory_size)) + /* Overflow, would lead to out of memory. */ + goto out_of_memory; + memory = (DIRECTIVE *) (d->dir != d->direct_alloc_dir + ? realloc (d->dir, memory_size) + : malloc (memory_size)); + if (memory == NULL) + /* Out of memory. */ + goto out_of_memory; + if (d->dir == d->direct_alloc_dir) + memcpy (memory, d->dir, d->count * sizeof (DIRECTIVE)); + d->dir = memory; + } + } +#if CHAR_T_ONLY_ASCII + else if (!c_isascii (c)) + { + /* Non-ASCII character. Not supported. */ + goto error; + } +#endif + } + d->dir[d->count].dir_start = cp; + + d->max_width_length = max_width_length; + d->max_precision_length = max_precision_length; + return 0; + +error: + if (a->arg != a->direct_alloc_arg) + free (a->arg); + if (d->dir != d->direct_alloc_dir) + free (d->dir); + errno = EINVAL; + return -1; + +out_of_memory: + if (a->arg != a->direct_alloc_arg) + free (a->arg); + if (d->dir != d->direct_alloc_dir) + free (d->dir); + errno = ENOMEM; + return -1; +} + +#undef PRINTF_PARSE +#undef DIRECTIVES +#undef DIRECTIVE +#undef CHAR_T_ONLY_ASCII +#undef CHAR_T diff --git a/gettext-tools/gnulib-lib/printf-parse.h b/gettext-tools/gnulib-lib/printf-parse.h new file mode 100644 index 0000000..2651195 --- /dev/null +++ b/gettext-tools/gnulib-lib/printf-parse.h @@ -0,0 +1,193 @@ +/* Parse printf format string. + Copyright (C) 1999, 2002-2003, 2005, 2007, 2010-2014 Free Software + Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, see . */ + +#ifndef _PRINTF_PARSE_H +#define _PRINTF_PARSE_H + +/* This file can be parametrized with the following macros: + ENABLE_UNISTDIO Set to 1 to enable the unistdio extensions. + STATIC Set to 'static' to declare the function static. */ + +#if HAVE_FEATURES_H +# include /* for __GLIBC__, __UCLIBC__ */ +#endif + +#include "printf-args.h" + + +/* Flags */ +#define FLAG_GROUP 1 /* ' flag */ +#define FLAG_LEFT 2 /* - flag */ +#define FLAG_SHOWSIGN 4 /* + flag */ +#define FLAG_SPACE 8 /* space flag */ +#define FLAG_ALT 16 /* # flag */ +#define FLAG_ZERO 32 +#if __GLIBC__ >= 2 && !defined __UCLIBC__ +# define FLAG_LOCALIZED 64 /* I flag, uses localized digits */ +#endif + +/* arg_index value indicating that no argument is consumed. */ +#define ARG_NONE (~(size_t)0) + +/* xxx_directive: A parsed directive. + xxx_directives: A parsed format string. */ + +/* Number of directly allocated directives (no malloc() needed). */ +#define N_DIRECT_ALLOC_DIRECTIVES 7 + +/* A parsed directive. */ +typedef struct +{ + const char* dir_start; + const char* dir_end; + int flags; + const char* width_start; + const char* width_end; + size_t width_arg_index; + const char* precision_start; + const char* precision_end; + size_t precision_arg_index; + char conversion; /* d i o u x X f F e E g G a A c s p n U % but not C S */ + size_t arg_index; +} +char_directive; + +/* A parsed format string. */ +typedef struct +{ + size_t count; + char_directive *dir; + size_t max_width_length; + size_t max_precision_length; + char_directive direct_alloc_dir[N_DIRECT_ALLOC_DIRECTIVES]; +} +char_directives; + +#if ENABLE_UNISTDIO + +/* A parsed directive. */ +typedef struct +{ + const uint8_t* dir_start; + const uint8_t* dir_end; + int flags; + const uint8_t* width_start; + const uint8_t* width_end; + size_t width_arg_index; + const uint8_t* precision_start; + const uint8_t* precision_end; + size_t precision_arg_index; + uint8_t conversion; /* d i o u x X f F e E g G a A c s p n U % but not C S */ + size_t arg_index; +} +u8_directive; + +/* A parsed format string. */ +typedef struct +{ + size_t count; + u8_directive *dir; + size_t max_width_length; + size_t max_precision_length; + u8_directive direct_alloc_dir[N_DIRECT_ALLOC_DIRECTIVES]; +} +u8_directives; + +/* A parsed directive. */ +typedef struct +{ + const uint16_t* dir_start; + const uint16_t* dir_end; + int flags; + const uint16_t* width_start; + const uint16_t* width_end; + size_t width_arg_index; + const uint16_t* precision_start; + const uint16_t* precision_end; + size_t precision_arg_index; + uint16_t conversion; /* d i o u x X f F e E g G a A c s p n U % but not C S */ + size_t arg_index; +} +u16_directive; + +/* A parsed format string. */ +typedef struct +{ + size_t count; + u16_directive *dir; + size_t max_width_length; + size_t max_precision_length; + u16_directive direct_alloc_dir[N_DIRECT_ALLOC_DIRECTIVES]; +} +u16_directives; + +/* A parsed directive. */ +typedef struct +{ + const uint32_t* dir_start; + const uint32_t* dir_end; + int flags; + const uint32_t* width_start; + const uint32_t* width_end; + size_t width_arg_index; + const uint32_t* precision_start; + const uint32_t* precision_end; + size_t precision_arg_index; + uint32_t conversion; /* d i o u x X f F e E g G a A c s p n U % but not C S */ + size_t arg_index; +} +u32_directive; + +/* A parsed format string. */ +typedef struct +{ + size_t count; + u32_directive *dir; + size_t max_width_length; + size_t max_precision_length; + u32_directive direct_alloc_dir[N_DIRECT_ALLOC_DIRECTIVES]; +} +u32_directives; + +#endif + + +/* Parses the format string. Fills in the number N of directives, and fills + in directives[0], ..., directives[N-1], and sets directives[N].dir_start + to the end of the format string. Also fills in the arg_type fields of the + arguments and the needed count of arguments. */ +#if ENABLE_UNISTDIO +extern int + ulc_printf_parse (const char *format, char_directives *d, arguments *a); +extern int + u8_printf_parse (const uint8_t *format, u8_directives *d, arguments *a); +extern int + u16_printf_parse (const uint16_t *format, u16_directives *d, + arguments *a); +extern int + u32_printf_parse (const uint32_t *format, u32_directives *d, + arguments *a); +#else +# ifdef STATIC +STATIC +# else +extern +# endif +int printf_parse (const char *format, char_directives *d, arguments *a); +#endif + +#endif /* _PRINTF_PARSE_H */ diff --git a/gettext-tools/gnulib-lib/progname.c b/gettext-tools/gnulib-lib/progname.c new file mode 100644 index 0000000..2919be9 --- /dev/null +++ b/gettext-tools/gnulib-lib/progname.c @@ -0,0 +1,92 @@ +/* Program name management. + Copyright (C) 2001-2003, 2005-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2001. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + + +#include + +/* Specification. */ +#undef ENABLE_RELOCATABLE /* avoid defining set_program_name as a macro */ +#include "progname.h" + +#include /* get program_invocation_name declaration */ +#include +#include +#include + + +/* String containing name the program is called with. + To be initialized by main(). */ +const char *program_name = NULL; + +/* Set program_name, based on argv[0]. + argv0 must be a string allocated with indefinite extent, and must not be + modified after this call. */ +void +set_program_name (const char *argv0) +{ + /* libtool creates a temporary executable whose name is sometimes prefixed + with "lt-" (depends on the platform). It also makes argv[0] absolute. + But the name of the temporary executable is a detail that should not be + visible to the end user and to the test suite. + Remove this "/.libs/" or "/.libs/lt-" prefix here. */ + const char *slash; + const char *base; + + /* Sanity check. POSIX requires the invoking process to pass a non-NULL + argv[0]. */ + if (argv0 == NULL) + { + /* It's a bug in the invoking program. Help diagnosing it. */ + fputs ("A NULL argv[0] was passed through an exec system call.\n", + stderr); + abort (); + } + + slash = strrchr (argv0, '/'); + base = (slash != NULL ? slash + 1 : argv0); + if (base - argv0 >= 7 && strncmp (base - 7, "/.libs/", 7) == 0) + { + argv0 = base; + if (strncmp (base, "lt-", 3) == 0) + { + argv0 = base + 3; + /* On glibc systems, remove the "lt-" prefix from the variable + program_invocation_short_name. */ +#if HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME + program_invocation_short_name = (char *) argv0; +#endif + } + } + + /* But don't strip off a leading / in general, because when the user + runs + /some/hidden/place/bin/cp foo foo + he should get the error message + /some/hidden/place/bin/cp: `foo' and `foo' are the same file + not + cp: `foo' and `foo' are the same file + */ + + program_name = argv0; + + /* On glibc systems, the error() function comes from libc and uses the + variable program_invocation_name, not program_name. So set this variable + as well. */ +#if HAVE_DECL_PROGRAM_INVOCATION_NAME + program_invocation_name = (char *) argv0; +#endif +} diff --git a/gettext-tools/gnulib-lib/progname.h b/gettext-tools/gnulib-lib/progname.h new file mode 100644 index 0000000..f620027 --- /dev/null +++ b/gettext-tools/gnulib-lib/progname.h @@ -0,0 +1,62 @@ +/* Program name management. + Copyright (C) 2001-2004, 2006, 2009-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2001. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _PROGNAME_H +#define _PROGNAME_H + +/* Programs using this file should do the following in main(): + set_program_name (argv[0]); + */ + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* String containing name the program is called with. */ +extern DLL_VARIABLE const char *program_name; + +/* Set program_name, based on argv[0]. + argv0 must be a string allocated with indefinite extent, and must not be + modified after this call. */ +extern void set_program_name (const char *argv0); + +#if ENABLE_RELOCATABLE + +/* Set program_name, based on argv[0], and original installation prefix and + directory, for relocatability. */ +extern void set_program_name_and_installdir (const char *argv0, + const char *orig_installprefix, + const char *orig_installdir); +#undef set_program_name +#define set_program_name(ARG0) \ + set_program_name_and_installdir (ARG0, INSTALLPREFIX, INSTALLDIR) + +/* Return the full pathname of the current executable, based on the earlier + call to set_program_name_and_installdir. Return NULL if unknown. */ +extern char *get_full_program_name (void); + +#endif + + +#ifdef __cplusplus +} +#endif + + +#endif /* _PROGNAME_H */ diff --git a/gettext-tools/gnulib-lib/progreloc.c b/gettext-tools/gnulib-lib/progreloc.c new file mode 100644 index 0000000..3d7b6a9 --- /dev/null +++ b/gettext-tools/gnulib-lib/progreloc.c @@ -0,0 +1,372 @@ +/* Provide relocatable programs. + Copyright (C) 2003-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2003. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + + +#define _GL_USE_STDLIB_ALLOC 1 +#include + +/* Specification. */ +#include "progname.h" + +#include +#include +#include +#include +#include +#include +#include + +/* Get declaration of _NSGetExecutablePath on Mac OS X 10.2 or newer. */ +#if HAVE_MACH_O_DYLD_H +# include +#endif + +#if (defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__ +# define WINDOWS_NATIVE +#endif + +#ifdef WINDOWS_NATIVE +# define WIN32_LEAN_AND_MEAN +# include +#endif + +#include "relocatable.h" + +#ifdef NO_XMALLOC +# include "areadlink.h" +# define xreadlink areadlink +#else +# include "xreadlink.h" +#endif + +#ifdef NO_XMALLOC +# define xmalloc malloc +# define xstrdup strdup +#else +# include "xalloc.h" +#endif + +#ifndef O_EXEC +# define O_EXEC O_RDONLY /* This is often close enough in older systems. */ +#endif + +/* Declare canonicalize_file_name. + The included above may be the system's one, not the gnulib + one. */ +extern char * canonicalize_file_name (const char *name); + +/* Pathname support. + ISSLASH(C) tests whether C is a directory separator character. + IS_PATH_WITH_DIR(P) tests whether P contains a directory specification. + */ +#if ((defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__) || defined __EMX__ || defined __DJGPP__ + /* Native Windows, OS/2, DOS */ +# define ISSLASH(C) ((C) == '/' || (C) == '\\') +# define HAS_DEVICE(P) \ + ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) \ + && (P)[1] == ':') +# define IS_PATH_WITH_DIR(P) \ + (strchr (P, '/') != NULL || strchr (P, '\\') != NULL || HAS_DEVICE (P)) +# define FILE_SYSTEM_PREFIX_LEN(P) (HAS_DEVICE (P) ? 2 : 0) +#else + /* Unix */ +# define ISSLASH(C) ((C) == '/') +# define IS_PATH_WITH_DIR(P) (strchr (P, '/') != NULL) +# define FILE_SYSTEM_PREFIX_LEN(P) 0 +#endif + +/* Use the system functions, not the gnulib overrides in this file. */ +#undef sprintf + +#undef set_program_name + + +#if ENABLE_RELOCATABLE + +#if defined __linux__ || defined __CYGWIN__ +/* File descriptor of the executable. + (Only used to verify that we find the correct executable.) */ +static int executable_fd = -1; +#endif + +/* Tests whether a given pathname may belong to the executable. */ +static bool +maybe_executable (const char *filename) +{ + /* The native Windows API lacks the access() function. */ +#if !defined WINDOWS_NATIVE + if (access (filename, X_OK) < 0) + return false; +#endif + +#if defined __linux__ || defined __CYGWIN__ + if (executable_fd >= 0) + { + /* If we already have an executable_fd, check that filename points to + the same inode. */ + struct stat statexe; + struct stat statfile; + + if (fstat (executable_fd, &statexe) >= 0) + { + if (stat (filename, &statfile) < 0) + return false; + if (!(statfile.st_dev + && statfile.st_dev == statexe.st_dev + && statfile.st_ino == statexe.st_ino)) + return false; + } + } +#endif + + return true; +} + +/* Determine the full pathname of the current executable, freshly allocated. + Return NULL if unknown. + Guaranteed to work on Linux and native Windows. Likely to work on the + other Unixes (maybe except BeOS), under most conditions. */ +static char * +find_executable (const char *argv0) +{ +#if defined WINDOWS_NATIVE + /* Native Windows only. + On Cygwin, it is better to use the Cygwin provided /proc interface, than + to use native Windows API and cygwin_conv_to_posix_path, because it + supports longer file names + (see ). */ + char location[MAX_PATH]; + int length = GetModuleFileName (NULL, location, sizeof (location)); + if (length < 0) + return NULL; + if (!IS_PATH_WITH_DIR (location)) + /* Shouldn't happen. */ + return NULL; + return xstrdup (location); +#else /* Unix */ +# ifdef __linux__ + /* The executable is accessible as /proc//exe. In newer Linux + versions, also as /proc/self/exe. Linux >= 2.1 provides a symlink + to the true pathname; older Linux versions give only device and ino, + enclosed in brackets, which we cannot use here. */ + { + char *link; + + link = xreadlink ("/proc/self/exe"); + if (link != NULL && link[0] != '[') + return link; + if (executable_fd < 0) + executable_fd = open ("/proc/self/exe", O_EXEC, 0); + + { + char buf[6+10+5]; + sprintf (buf, "/proc/%d/exe", getpid ()); + link = xreadlink (buf); + if (link != NULL && link[0] != '[') + return link; + if (executable_fd < 0) + executable_fd = open (buf, O_EXEC, 0); + } + } +# endif +# ifdef __CYGWIN__ + /* The executable is accessible as /proc//exe, at least in + Cygwin >= 1.5. */ + { + char *link; + + link = xreadlink ("/proc/self/exe"); + if (link != NULL) + return link; + if (executable_fd < 0) + executable_fd = open ("/proc/self/exe", O_EXEC, 0); + } +# endif +# if HAVE_MACH_O_DYLD_H && HAVE__NSGETEXECUTABLEPATH + /* On Mac OS X 10.2 or newer, the function + int _NSGetExecutablePath (char *buf, uint32_t *bufsize); + can be used to retrieve the executable's full path. */ + char location[4096]; + unsigned int length = sizeof (location); + if (_NSGetExecutablePath (location, &length) == 0 + && location[0] == '/') + return canonicalize_file_name (location); +# endif + /* Guess the executable's full path. We assume the executable has been + called via execlp() or execvp() with properly set up argv[0]. The + login(1) convention to add a '-' prefix to argv[0] is not supported. */ + { + bool has_slash = false; + { + const char *p; + for (p = argv0; *p; p++) + if (*p == '/') + { + has_slash = true; + break; + } + } + if (!has_slash) + { + /* exec searches paths without slashes in the directory list given + by $PATH. */ + const char *path = getenv ("PATH"); + + if (path != NULL) + { + const char *p; + const char *p_next; + + for (p = path; *p; p = p_next) + { + const char *q; + size_t p_len; + char *concat_name; + + for (q = p; *q; q++) + if (*q == ':') + break; + p_len = q - p; + p_next = (*q == '\0' ? q : q + 1); + + /* We have a path item at p, of length p_len. + Now concatenate the path item and argv0. */ + concat_name = (char *) xmalloc (p_len + strlen (argv0) + 2); +# ifdef NO_XMALLOC + if (concat_name == NULL) + return NULL; +# endif + if (p_len == 0) + /* An empty PATH element designates the current directory. */ + strcpy (concat_name, argv0); + else + { + memcpy (concat_name, p, p_len); + concat_name[p_len] = '/'; + strcpy (concat_name + p_len + 1, argv0); + } + if (maybe_executable (concat_name)) + return canonicalize_file_name (concat_name); + free (concat_name); + } + } + /* Not found in the PATH, assume the current directory. */ + } + /* exec treats paths containing slashes as relative to the current + directory. */ + if (maybe_executable (argv0)) + return canonicalize_file_name (argv0); + } + /* No way to find the executable. */ + return NULL; +#endif +} + +/* Full pathname of executable, or NULL. */ +static char *executable_fullname; + +static void +prepare_relocate (const char *orig_installprefix, const char *orig_installdir, + const char *argv0) +{ + char *curr_prefix; + + /* Determine the full pathname of the current executable. */ + executable_fullname = find_executable (argv0); + + /* Determine the current installation prefix from it. */ + curr_prefix = compute_curr_prefix (orig_installprefix, orig_installdir, + executable_fullname); + if (curr_prefix != NULL) + { + /* Now pass this prefix to all copies of the relocate.c source file. */ + set_relocation_prefix (orig_installprefix, curr_prefix); + + free (curr_prefix); + } +} + +/* Set program_name, based on argv[0], and original installation prefix and + directory, for relocatability. */ +void +set_program_name_and_installdir (const char *argv0, + const char *orig_installprefix, + const char *orig_installdir) +{ + const char *argv0_stripped = argv0; + + /* Relocatable programs are renamed to .bin by install-reloc. Or, more + generally, their suffix is changed from $exeext to .bin$exeext. + Remove the ".bin" here. */ + { + size_t argv0_len = strlen (argv0); + const size_t exeext_len = sizeof (EXEEXT) - sizeof (""); + if (argv0_len > 4 + exeext_len) + if (memcmp (argv0 + argv0_len - exeext_len - 4, ".bin", 4) == 0) + { + if (sizeof (EXEEXT) > sizeof ("")) + { + /* Compare using an inlined copy of c_strncasecmp(), because + the filenames may have undergone a case conversion since + they were packaged. In other words, EXEEXT may be ".exe" + on one system and ".EXE" on another. */ + static const char exeext[] = EXEEXT; + const char *s1 = argv0 + argv0_len - exeext_len; + const char *s2 = exeext; + for (; *s1 != '\0'; s1++, s2++) + { + unsigned char c1 = *s1; + unsigned char c2 = *s2; + if ((c1 >= 'A' && c1 <= 'Z' ? c1 - 'A' + 'a' : c1) + != (c2 >= 'A' && c2 <= 'Z' ? c2 - 'A' + 'a' : c2)) + goto done_stripping; + } + } + /* Remove ".bin" before EXEEXT or its equivalent. */ + { + char *shorter = (char *) xmalloc (argv0_len - 4 + 1); +#ifdef NO_XMALLOC + if (shorter != NULL) +#endif + { + memcpy (shorter, argv0, argv0_len - exeext_len - 4); + if (sizeof (EXEEXT) > sizeof ("")) + memcpy (shorter + argv0_len - exeext_len - 4, + argv0 + argv0_len - exeext_len - 4, + exeext_len); + shorter[argv0_len - 4] = '\0'; + argv0_stripped = shorter; + } + } + done_stripping: ; + } + } + + set_program_name (argv0_stripped); + + prepare_relocate (orig_installprefix, orig_installdir, argv0); +} + +/* Return the full pathname of the current executable, based on the earlier + call to set_program_name_and_installdir. Return NULL if unknown. */ +char * +get_full_program_name (void) +{ + return executable_fullname; +} + +#endif diff --git a/gettext-tools/gnulib-lib/propername.c b/gettext-tools/gnulib-lib/propername.c new file mode 100644 index 0000000..54a6ada --- /dev/null +++ b/gettext-tools/gnulib-lib/propername.c @@ -0,0 +1,318 @@ +/* Localization of proper names. + Copyright (C) 2006-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Without this pragma, gcc 4.7.0 20111124 mistakenly suggests that + the proper_name function might be candidate for attribute 'const' */ +#if (__GNUC__ == 4 && 6 <= __GNUC_MINOR__) || 4 < __GNUC__ +# pragma GCC diagnostic ignored "-Wsuggest-attribute=const" +#endif + +#include + +/* Specification. */ +#include "propername.h" + +#include +#include +#include +#include +#include +#if HAVE_ICONV +# include +#endif + +#include "trim.h" +#include "mbchar.h" +#include "mbuiter.h" +#include "localcharset.h" +#include "c-strcase.h" +#include "xstriconv.h" +#include "xalloc.h" +#include "gettext.h" + + +/* Tests whether STRING contains trim (SUB), starting and ending at word + boundaries. + Here, instead of implementing Unicode Standard Annex #29 for determining + word boundaries, we assume that trim (SUB) starts and ends with words and + only test whether the part before it ends with a non-word and the part + after it starts with a non-word. */ +static bool +mbsstr_trimmed_wordbounded (const char *string, const char *sub) +{ + char *tsub = trim (sub); + bool found = false; + + for (; *string != '\0';) + { + const char *tsub_in_string = mbsstr (string, tsub); + if (tsub_in_string == NULL) + break; + else + { + if (MB_CUR_MAX > 1) + { + mbui_iterator_t string_iter; + bool word_boundary_before; + bool word_boundary_after; + + mbui_init (string_iter, string); + word_boundary_before = true; + if (mbui_cur_ptr (string_iter) < tsub_in_string) + { + mbchar_t last_char_before_tsub; + do + { + if (!mbui_avail (string_iter)) + abort (); + last_char_before_tsub = mbui_cur (string_iter); + mbui_advance (string_iter); + } + while (mbui_cur_ptr (string_iter) < tsub_in_string); + if (mb_isalnum (last_char_before_tsub)) + word_boundary_before = false; + } + + mbui_init (string_iter, tsub_in_string); + { + mbui_iterator_t tsub_iter; + + for (mbui_init (tsub_iter, tsub); + mbui_avail (tsub_iter); + mbui_advance (tsub_iter)) + { + if (!mbui_avail (string_iter)) + abort (); + mbui_advance (string_iter); + } + } + word_boundary_after = true; + if (mbui_avail (string_iter)) + { + mbchar_t first_char_after_tsub = mbui_cur (string_iter); + if (mb_isalnum (first_char_after_tsub)) + word_boundary_after = false; + } + + if (word_boundary_before && word_boundary_after) + { + found = true; + break; + } + + mbui_init (string_iter, tsub_in_string); + if (!mbui_avail (string_iter)) + break; + string = tsub_in_string + mb_len (mbui_cur (string_iter)); + } + else + { + bool word_boundary_before; + const char *p; + bool word_boundary_after; + + word_boundary_before = true; + if (string < tsub_in_string) + if (isalnum ((unsigned char) tsub_in_string[-1])) + word_boundary_before = false; + + p = tsub_in_string + strlen (tsub); + word_boundary_after = true; + if (*p != '\0') + if (isalnum ((unsigned char) *p)) + word_boundary_after = false; + + if (word_boundary_before && word_boundary_after) + { + found = true; + break; + } + + if (*tsub_in_string == '\0') + break; + string = tsub_in_string + 1; + } + } + } + free (tsub); + return found; +} + +/* Return the localization of NAME. NAME is written in ASCII. */ + +const char * +proper_name (const char *name) +{ + /* See whether there is a translation. */ + const char *translation = gettext (name); + + if (translation != name) + { + /* See whether the translation contains the original name. */ + if (mbsstr_trimmed_wordbounded (translation, name)) + return translation; + else + { + /* Return "TRANSLATION (NAME)". */ + char *result = + XNMALLOC (strlen (translation) + 2 + strlen (name) + 1 + 1, char); + + sprintf (result, "%s (%s)", translation, name); + return result; + } + } + else + return name; +} + +/* Return the localization of a name whose original writing is not ASCII. + NAME_UTF8 is the real name, written in UTF-8 with octal or hexadecimal + escape sequences. NAME_ASCII is a fallback written only with ASCII + characters. */ + +const char * +proper_name_utf8 (const char *name_ascii, const char *name_utf8) +{ + /* See whether there is a translation. */ + const char *translation = gettext (name_ascii); + + /* Try to convert NAME_UTF8 to the locale encoding. */ + const char *locale_code = locale_charset (); + char *alloc_name_converted = NULL; + char *alloc_name_converted_translit = NULL; + const char *name_converted = NULL; + const char *name_converted_translit = NULL; + const char *name; + + if (c_strcasecmp (locale_code, "UTF-8") != 0) + { +#if HAVE_ICONV + name_converted = alloc_name_converted = + xstr_iconv (name_utf8, "UTF-8", locale_code); + +# if (((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2) \ + && !defined __UCLIBC__) \ + || _LIBICONV_VERSION >= 0x0105 + { + char *converted_translit; + + size_t len = strlen (locale_code); + char *locale_code_translit = XNMALLOC (len + 10 + 1, char); + memcpy (locale_code_translit, locale_code, len); + memcpy (locale_code_translit + len, "//TRANSLIT", 10 + 1); + + converted_translit = + xstr_iconv (name_utf8, "UTF-8", locale_code_translit); + + free (locale_code_translit); + + if (converted_translit != NULL) + { +# if !_LIBICONV_VERSION + /* Don't use the transliteration if it added question marks. + glibc's transliteration falls back to question marks; libiconv's + transliteration does not. + mbschr is equivalent to strchr in this case. */ + if (strchr (converted_translit, '?') != NULL) + free (converted_translit); + else +# endif + name_converted_translit = alloc_name_converted_translit = + converted_translit; + } + } +# endif +#endif + } + else + { + name_converted = name_utf8; + name_converted_translit = name_utf8; + } + + /* The name in locale encoding. */ + name = (name_converted != NULL ? name_converted : + name_converted_translit != NULL ? name_converted_translit : + name_ascii); + + /* See whether we have a translation. Some translators have not understood + that they should use the UTF-8 form of the name, if possible. So if the + translator provided a no-op translation, we ignore it. */ + if (strcmp (translation, name_ascii) != 0) + { + /* See whether the translation contains the original name. */ + if (mbsstr_trimmed_wordbounded (translation, name_ascii) + || (name_converted != NULL + && mbsstr_trimmed_wordbounded (translation, name_converted)) + || (name_converted_translit != NULL + && mbsstr_trimmed_wordbounded (translation, name_converted_translit))) + { + if (alloc_name_converted != NULL) + free (alloc_name_converted); + if (alloc_name_converted_translit != NULL) + free (alloc_name_converted_translit); + return translation; + } + else + { + /* Return "TRANSLATION (NAME)". */ + char *result = + XNMALLOC (strlen (translation) + 2 + strlen (name) + 1 + 1, char); + + sprintf (result, "%s (%s)", translation, name); + + if (alloc_name_converted != NULL) + free (alloc_name_converted); + if (alloc_name_converted_translit != NULL) + free (alloc_name_converted_translit); + return result; + } + } + else + { + if (alloc_name_converted != NULL && alloc_name_converted != name) + free (alloc_name_converted); + if (alloc_name_converted_translit != NULL + && alloc_name_converted_translit != name) + free (alloc_name_converted_translit); + return name; + } +} + +#ifdef TEST1 +# include +int +main (int argc, char *argv[]) +{ + setlocale (LC_ALL, ""); + if (mbsstr_trimmed_wordbounded (argv[1], argv[2])) + printf("found\n"); + return 0; +} +#endif + +#ifdef TEST2 +# include +# include +int +main (int argc, char *argv[]) +{ + setlocale (LC_ALL, ""); + printf ("%s\n", proper_name_utf8 ("Franc,ois Pinard", "Fran\303\247ois Pinard")); + return 0; +} +#endif diff --git a/gettext-tools/gnulib-lib/propername.h b/gettext-tools/gnulib-lib/propername.h new file mode 100644 index 0000000..7e3de0f --- /dev/null +++ b/gettext-tools/gnulib-lib/propername.h @@ -0,0 +1,106 @@ +/* Localization of proper names. + Copyright (C) 2006, 2008-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* INTRODUCTION + + What do + + Torbjörn Granlund (coreutils) + François Pinard (coreutils) + Danilo Å egan (gettext) + + have in common? + + A non-ASCII name. This causes trouble in the --version output. The simple + "solution", unfortunately mutilates the name. + + $ du --version| grep Granlund + Écrit par Torbjorn Granlund, David MacKenzie, Paul Eggert et Jim Meyering. + + $ ptx --version| grep Pinard + Écrit par F. Pinard. + + What is desirable, is to print the full name if the output character set + allows it, and the ASCIIfied name only as a fallback. + + $ recode-sr-latin --version + ... + Written by Danilo Å egan and Bruno Haible. + + $ LC_ALL=C recode-sr-latin --version + ... + Written by Danilo Segan and Bruno Haible. + + The 'propername' module does exactly this. Plus, for languages that use + a different writing system than the Latin alphabet, it allows a translator + to write the name using that different writing system. In that case the + output will look like this: + () + + To use the 'propername' module is done in three simple steps: + + 1) Add it to the list of gnulib modules to import, + + 2) Change the arguments of version_etc, from + + from "Paul Eggert" + to proper_name ("Paul Eggert") + + from "Torbjorn Granlund" + to proper_name_utf8 ("Torbjorn Granlund", "Torbj\303\266rn Granlund") + + from "F. Pinard" + to proper_name_utf8 ("Franc,ois Pinard", "Fran\303\247ois Pinard") + + (Optionally, here you can also add / * TRANSLATORS: ... * / comments + explaining how the name is written or pronounced.) + + 3) If you are using GNU gettext version 0.16.1 or older, in po/Makevars, + in the definition of the XGETTEXT_OPTIONS variable, add: + + --keyword='proper_name:1,"This is a proper name. See the gettext manual, section Names."' + --keyword='proper_name_utf8:1,"This is a proper name. See the gettext manual, section Names."' + + This specifies automatic comments for the translator. (Requires + xgettext >= 0.15. The double-quotes inside the quoted string are on + purpose: they are part of the --keyword argument syntax.) + */ + +#ifndef _PROPERNAME_H +#define _PROPERNAME_H + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Return the localization of NAME. NAME is written in ASCII. */ +extern const char * proper_name (const char *name) /* NOT attribute const */; + +/* Return the localization of a name whose original writing is not ASCII. + NAME_UTF8 is the real name, written in UTF-8 with octal or hexadecimal + escape sequences. NAME_ASCII is a fallback written only with ASCII + characters. */ +extern const char * proper_name_utf8 (const char *name_ascii, + const char *name_utf8); + +#ifdef __cplusplus +} +#endif + + +#endif /* _PROPERNAME_H */ diff --git a/gettext-tools/gnulib-lib/qcopy-acl.c b/gettext-tools/gnulib-lib/qcopy-acl.c new file mode 100644 index 0000000..4e53b63 --- /dev/null +++ b/gettext-tools/gnulib-lib/qcopy-acl.c @@ -0,0 +1,583 @@ +/* copy-acl.c - copy access control list from one file to another file + + Copyright (C) 2002-2003, 2005-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + Written by Paul Eggert, Andreas Grünbacher, and Bruno Haible. */ + +#include + +#include "acl.h" + +#include "acl-internal.h" + + +/* Copy access control lists from one file to another. If SOURCE_DESC is + a valid file descriptor, use file descriptor operations, else use + filename based operations on SRC_NAME. Likewise for DEST_DESC and + DST_NAME. + If access control lists are not available, fchmod the target file to + MODE. Also sets the non-permission bits of the destination file + (S_ISUID, S_ISGID, S_ISVTX) to those from MODE if any are set. + Return 0 if successful. + Return -2 and set errno for an error relating to the source file. + Return -1 and set errno for an error relating to the destination file. */ + +int +qcopy_acl (const char *src_name, int source_desc, const char *dst_name, + int dest_desc, mode_t mode) +{ +#if USE_ACL && HAVE_ACL_GET_FILE + /* POSIX 1003.1e (draft 17 -- abandoned) specific version. */ + /* Linux, FreeBSD, Mac OS X, IRIX, Tru64 */ +# if !HAVE_ACL_TYPE_EXTENDED + /* Linux, FreeBSD, IRIX, Tru64 */ + + acl_t acl; + int ret; + + if (HAVE_ACL_GET_FD && source_desc != -1) + acl = acl_get_fd (source_desc); + else + acl = acl_get_file (src_name, ACL_TYPE_ACCESS); + if (acl == NULL) + { + if (! acl_errno_valid (errno)) + return qset_acl (dst_name, dest_desc, mode); + else + return -2; + } + + if (HAVE_ACL_SET_FD && dest_desc != -1) + ret = acl_set_fd (dest_desc, acl); + else + ret = acl_set_file (dst_name, ACL_TYPE_ACCESS, acl); + if (ret != 0) + { + int saved_errno = errno; + + if (! acl_errno_valid (errno) && !acl_access_nontrivial (acl)) + { + acl_free (acl); + return chmod_or_fchmod (dst_name, dest_desc, mode); + } + else + { + acl_free (acl); + chmod_or_fchmod (dst_name, dest_desc, mode); + errno = saved_errno; + return -1; + } + } + else + acl_free (acl); + + if (!MODE_INSIDE_ACL || (mode & (S_ISUID | S_ISGID | S_ISVTX))) + { + /* We did not call chmod so far, and either the mode and the ACL are + separate or special bits are to be set which don't fit into ACLs. */ + + if (chmod_or_fchmod (dst_name, dest_desc, mode) != 0) + return -1; + } + + if (S_ISDIR (mode)) + { + acl = acl_get_file (src_name, ACL_TYPE_DEFAULT); + if (acl == NULL) + return -2; + + if (acl_set_file (dst_name, ACL_TYPE_DEFAULT, acl)) + { + int saved_errno = errno; + + acl_free (acl); + errno = saved_errno; + return -1; + } + else + acl_free (acl); + } + return 0; + +# else /* HAVE_ACL_TYPE_EXTENDED */ + /* Mac OS X */ + + /* On Mac OS X, acl_get_file (name, ACL_TYPE_ACCESS) + and acl_get_file (name, ACL_TYPE_DEFAULT) + always return NULL / EINVAL. You have to use + acl_get_file (name, ACL_TYPE_EXTENDED) + or acl_get_fd (open (name, ...)) + to retrieve an ACL. + On the other hand, + acl_set_file (name, ACL_TYPE_ACCESS, acl) + and acl_set_file (name, ACL_TYPE_DEFAULT, acl) + have the same effect as + acl_set_file (name, ACL_TYPE_EXTENDED, acl): + Each of these calls sets the file's ACL. */ + + acl_t acl; + int ret; + + if (HAVE_ACL_GET_FD && source_desc != -1) + acl = acl_get_fd (source_desc); + else + acl = acl_get_file (src_name, ACL_TYPE_EXTENDED); + if (acl == NULL) + { + if (!acl_errno_valid (errno)) + return qset_acl (dst_name, dest_desc, mode); + else + return -2; + } + + if (HAVE_ACL_SET_FD && dest_desc != -1) + ret = acl_set_fd (dest_desc, acl); + else + ret = acl_set_file (dst_name, ACL_TYPE_EXTENDED, acl); + if (ret != 0) + { + int saved_errno = errno; + + if (!acl_errno_valid (saved_errno) && !acl_extended_nontrivial (acl)) + { + acl_free (acl); + return chmod_or_fchmod (dst_name, dest_desc, mode); + } + else + { + acl_free (acl); + chmod_or_fchmod (dst_name, dest_desc, mode); + errno = saved_errno; + return -1; + } + } + else + acl_free (acl); + + /* Since !MODE_INSIDE_ACL, we have to call chmod explicitly. */ + return chmod_or_fchmod (dst_name, dest_desc, mode); + +# endif + +#elif USE_ACL && defined GETACL /* Solaris, Cygwin, not HP-UX */ + + /* Solaris 2.5 through Solaris 10, Cygwin, and contemporaneous versions + of Unixware. The acl() call returns the access and default ACL both + at once. */ +# ifdef ACE_GETACL + int ace_count; + ace_t *ace_entries; +# endif + int count; + aclent_t *entries; + int did_chmod; + int saved_errno; + int ret; + +# ifdef ACE_GETACL + /* Solaris also has a different variant of ACLs, used in ZFS and NFSv4 + file systems (whereas the other ones are used in UFS file systems). + There is an API + pathconf (name, _PC_ACL_ENABLED) + fpathconf (desc, _PC_ACL_ENABLED) + that allows to determine which of the two kinds of ACLs is supported + for the given file. But some file systems may implement this call + incorrectly, so better not use it. + When fetching the source ACL, we simply fetch both ACL types. + When setting the destination ACL, we try either ACL types, assuming + that the kernel will translate the ACL from one form to the other. + (See in + the description of ENOTSUP.) */ + for (;;) + { + ace_count = (source_desc != -1 + ? facl (source_desc, ACE_GETACLCNT, 0, NULL) + : acl (src_name, ACE_GETACLCNT, 0, NULL)); + + if (ace_count < 0) + { + if (errno == ENOSYS || errno == EINVAL) + { + ace_count = 0; + ace_entries = NULL; + break; + } + else + return -2; + } + + if (ace_count == 0) + { + ace_entries = NULL; + break; + } + + ace_entries = (ace_t *) malloc (ace_count * sizeof (ace_t)); + if (ace_entries == NULL) + { + errno = ENOMEM; + return -2; + } + + ret = (source_desc != -1 + ? facl (source_desc, ACE_GETACL, ace_count, ace_entries) + : acl (src_name, ACE_GETACL, ace_count, ace_entries)); + if (ret < 0) + { + free (ace_entries); + if (errno == ENOSYS || errno == EINVAL) + { + ace_count = 0; + ace_entries = NULL; + break; + } + else + return -2; + } + if (ret == ace_count) + break; + /* Huh? The number of ACL entries changed since the last call. + Repeat. */ + } +# endif + + for (;;) + { + count = (source_desc != -1 + ? facl (source_desc, GETACLCNT, 0, NULL) + : acl (src_name, GETACLCNT, 0, NULL)); + + if (count < 0) + { + if (errno == ENOSYS || errno == ENOTSUP || errno == EOPNOTSUPP) + { + count = 0; + entries = NULL; + break; + } + else + return -2; + } + + if (count == 0) + { + entries = NULL; + break; + } + + entries = (aclent_t *) malloc (count * sizeof (aclent_t)); + if (entries == NULL) + { + errno = ENOMEM; + return -2; + } + + if ((source_desc != -1 + ? facl (source_desc, GETACL, count, entries) + : acl (src_name, GETACL, count, entries)) + == count) + break; + /* Huh? The number of ACL entries changed since the last call. + Repeat. */ + } + + /* Is there an ACL of either kind? */ +# ifdef ACE_GETACL + if (ace_count == 0) +# endif + if (count == 0) + return qset_acl (dst_name, dest_desc, mode); + + did_chmod = 0; /* set to 1 once the mode bits in 0777 have been set */ + saved_errno = 0; /* the first non-ignorable error code */ + + if (!MODE_INSIDE_ACL) + { + /* On Cygwin, it is necessary to call chmod before acl, because + chmod can change the contents of the ACL (in ways that don't + change the allowed accesses, but still visible). */ + if (chmod_or_fchmod (dst_name, dest_desc, mode) != 0) + saved_errno = errno; + did_chmod = 1; + } + + /* If both ace_entries and entries are available, try SETACL before + ACE_SETACL, because SETACL cannot fail with ENOTSUP whereas ACE_SETACL + can. */ + + if (count > 0) + { + ret = (dest_desc != -1 + ? facl (dest_desc, SETACL, count, entries) + : acl (dst_name, SETACL, count, entries)); + if (ret < 0 && saved_errno == 0) + { + saved_errno = errno; + if ((errno == ENOSYS || errno == EOPNOTSUPP || errno == EINVAL) + && !acl_nontrivial (count, entries)) + saved_errno = 0; + } + else + did_chmod = 1; + } + free (entries); + +# ifdef ACE_GETACL + if (ace_count > 0) + { + ret = (dest_desc != -1 + ? facl (dest_desc, ACE_SETACL, ace_count, ace_entries) + : acl (dst_name, ACE_SETACL, ace_count, ace_entries)); + if (ret < 0 && saved_errno == 0) + { + saved_errno = errno; + if ((errno == ENOSYS || errno == EINVAL || errno == ENOTSUP) + && !acl_ace_nontrivial (ace_count, ace_entries)) + saved_errno = 0; + } + } + free (ace_entries); +# endif + + if (MODE_INSIDE_ACL + && did_chmod <= ((mode & (S_ISUID | S_ISGID | S_ISVTX)) ? 1 : 0)) + { + /* We did not call chmod so far, and either the mode and the ACL are + separate or special bits are to be set which don't fit into ACLs. */ + + if (chmod_or_fchmod (dst_name, dest_desc, mode) != 0) + { + if (saved_errno == 0) + saved_errno = errno; + } + } + + if (saved_errno) + { + errno = saved_errno; + return -1; + } + return 0; + +#elif USE_ACL && HAVE_GETACL /* HP-UX */ + + struct acl_entry entries[NACLENTRIES]; + int count; +# if HAVE_ACLV_H + struct acl aclv_entries[NACLVENTRIES]; + int aclv_count; +# endif + int did_chmod; + int saved_errno; + int ret; + + count = (source_desc != -1 + ? fgetacl (source_desc, NACLENTRIES, entries) + : getacl (src_name, NACLENTRIES, entries)); + + if (count < 0) + { + if (errno == ENOSYS || errno == EOPNOTSUPP || errno == ENOTSUP) + count = 0; + else + return -2; + } + else if (count > 0) + { + if (count > NACLENTRIES) + /* If NACLENTRIES cannot be trusted, use dynamic memory allocation. */ + abort (); + } + +# if HAVE_ACLV_H + aclv_count = acl ((char *) src_name, ACL_GET, NACLVENTRIES, aclv_entries); + + if (aclv_count < 0) + { + if (errno == ENOSYS || errno == EOPNOTSUPP || errno == EINVAL) + count = 0; + else + return -2; + } + else if (aclv_count > 0) + { + if (aclv_count > NACLVENTRIES) + /* If NACLVENTRIES cannot be trusted, use dynamic memory allocation. */ + abort (); + } +# endif + + if (count == 0) +# if HAVE_ACLV_H + if (aclv_count == 0) +# endif + return qset_acl (dst_name, dest_desc, mode); + + did_chmod = 0; /* set to 1 once the mode bits in 0777 have been set */ + saved_errno = 0; /* the first non-ignorable error code */ + + if (count > 0) + { + ret = (dest_desc != -1 + ? fsetacl (dest_desc, count, entries) + : setacl (dst_name, count, entries)); + if (ret < 0 && saved_errno == 0) + { + saved_errno = errno; + if (errno == ENOSYS || errno == EOPNOTSUPP || errno == ENOTSUP) + { + struct stat source_statbuf; + + if ((source_desc != -1 + ? fstat (source_desc, &source_statbuf) + : stat (src_name, &source_statbuf)) == 0) + { + if (!acl_nontrivial (count, entries, &source_statbuf)) + saved_errno = 0; + } + else + saved_errno = errno; + } + } + else + did_chmod = 1; + } + +# if HAVE_ACLV_H + if (aclv_count > 0) + { + ret = acl ((char *) dst_name, ACL_SET, aclv_count, aclv_entries); + if (ret < 0 && saved_errno == 0) + { + saved_errno = errno; + if (errno == ENOSYS || errno == EOPNOTSUPP || errno == EINVAL) + { + if (!aclv_nontrivial (aclv_count, aclv_entries)) + saved_errno = 0; + } + } + else + did_chmod = 1; + } +# endif + + if (did_chmod <= ((mode & (S_ISUID | S_ISGID | S_ISVTX)) ? 1 : 0)) + { + /* We did not call chmod so far, and special bits are to be set which + don't fit into ACLs. */ + + if (chmod_or_fchmod (dst_name, dest_desc, mode) != 0) + { + if (saved_errno == 0) + saved_errno = errno; + } + } + + if (saved_errno) + { + errno = saved_errno; + return -1; + } + return 0; + +#elif USE_ACL && HAVE_ACLX_GET && 0 /* AIX */ + + /* TODO */ + +#elif USE_ACL && HAVE_STATACL /* older AIX */ + + union { struct acl a; char room[4096]; } u; + int ret; + + if ((source_desc != -1 + ? fstatacl (source_desc, STX_NORMAL, &u.a, sizeof (u)) + : statacl (src_name, STX_NORMAL, &u.a, sizeof (u))) + < 0) + return -2; + + ret = (dest_desc != -1 + ? fchacl (dest_desc, &u.a, u.a.acl_len) + : chacl (dst_name, &u.a, u.a.acl_len)); + if (ret < 0) + { + int saved_errno = errno; + + chmod_or_fchmod (dst_name, dest_desc, mode); + errno = saved_errno; + return -1; + } + + /* No need to call chmod_or_fchmod at this point, since the mode bits + S_ISUID, S_ISGID, S_ISVTX are also stored in the ACL. */ + + return 0; + +#elif USE_ACL && HAVE_ACLSORT /* NonStop Kernel */ + + struct acl entries[NACLENTRIES]; + int count; + int ret; + + count = acl ((char *) src_name, ACL_GET, NACLENTRIES, entries); + + if (count < 0) + { + if (0) + count = 0; + else + return -2; + } + else if (count > 0) + { + if (count > NACLENTRIES) + /* If NACLENTRIES cannot be trusted, use dynamic memory allocation. */ + abort (); + } + + if (count == 0) + return qset_acl (dst_name, dest_desc, mode); + + ret = acl ((char *) dst_name, ACL_SET, count, entries); + if (ret < 0) + { + int saved_errno = errno; + + if (0) + { + if (!acl_nontrivial (count, entries)) + return chmod_or_fchmod (dst_name, dest_desc, mode); + } + + chmod_or_fchmod (dst_name, dest_desc, mode); + errno = saved_errno; + return -1; + } + + if (mode & (S_ISUID | S_ISGID | S_ISVTX)) + { + /* We did not call chmod so far, and either the mode and the ACL are + separate or special bits are to be set which don't fit into ACLs. */ + + return chmod_or_fchmod (dst_name, dest_desc, mode); + } + return 0; + +#else + + return qset_acl (dst_name, dest_desc, mode); + +#endif +} diff --git a/gettext-tools/gnulib-lib/qset-acl.c b/gettext-tools/gnulib-lib/qset-acl.c new file mode 100644 index 0000000..7d9af57 --- /dev/null +++ b/gettext-tools/gnulib-lib/qset-acl.c @@ -0,0 +1,676 @@ +/* qset-acl.c - set access control list equivalent to a mode + + Copyright (C) 2002-2003, 2005-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + Written by Paul Eggert and Andreas Gruenbacher, and Bruno Haible. */ + +#include + +#define ACL_INTERNAL_INLINE _GL_EXTERN_INLINE + +#include "acl.h" + +#include "acl-internal.h" + + +/* If DESC is a valid file descriptor use fchmod to change the + file's mode to MODE on systems that have fchmod. On systems + that don't have fchmod and if DESC is invalid, use chmod on + NAME instead. + Return 0 if successful. Return -1 and set errno upon failure. */ + +int +chmod_or_fchmod (const char *name, int desc, mode_t mode) +{ + if (HAVE_FCHMOD && desc != -1) + return fchmod (desc, mode); + else + return chmod (name, mode); +} + +/* Set the access control lists of a file. If DESC is a valid file + descriptor, use file descriptor operations where available, else use + filename based operations on NAME. If access control lists are not + available, fchmod the target file to MODE. Also sets the + non-permission bits of the destination file (S_ISUID, S_ISGID, S_ISVTX) + to those from MODE if any are set. + Return 0 if successful. Return -1 and set errno upon failure. */ + +int +qset_acl (char const *name, int desc, mode_t mode) +{ +#if USE_ACL +# if HAVE_ACL_GET_FILE + /* POSIX 1003.1e draft 17 (abandoned) specific version. */ + /* Linux, FreeBSD, Mac OS X, IRIX, Tru64 */ +# if !HAVE_ACL_TYPE_EXTENDED + /* Linux, FreeBSD, IRIX, Tru64 */ + + /* We must also have acl_from_text and acl_delete_def_file. + (acl_delete_def_file could be emulated with acl_init followed + by acl_set_file, but acl_set_file with an empty acl is + unspecified.) */ + +# ifndef HAVE_ACL_FROM_TEXT +# error Must have acl_from_text (see POSIX 1003.1e draft 17). +# endif +# ifndef HAVE_ACL_DELETE_DEF_FILE +# error Must have acl_delete_def_file (see POSIX 1003.1e draft 17). +# endif + + acl_t acl; + int ret; + + if (HAVE_ACL_FROM_MODE) /* Linux */ + { + acl = acl_from_mode (mode); + if (!acl) + return -1; + } + else /* FreeBSD, IRIX, Tru64 */ + { + /* If we were to create the ACL using the functions acl_init(), + acl_create_entry(), acl_set_tag_type(), acl_set_qualifier(), + acl_get_permset(), acl_clear_perm[s](), acl_add_perm(), we + would need to create a qualifier. I don't know how to do this. + So create it using acl_from_text(). */ + +# if HAVE_ACL_FREE_TEXT /* Tru64 */ + char acl_text[] = "u::---,g::---,o::---,"; +# else /* FreeBSD, IRIX */ + char acl_text[] = "u::---,g::---,o::---"; +# endif + + if (mode & S_IRUSR) acl_text[ 3] = 'r'; + if (mode & S_IWUSR) acl_text[ 4] = 'w'; + if (mode & S_IXUSR) acl_text[ 5] = 'x'; + if (mode & S_IRGRP) acl_text[10] = 'r'; + if (mode & S_IWGRP) acl_text[11] = 'w'; + if (mode & S_IXGRP) acl_text[12] = 'x'; + if (mode & S_IROTH) acl_text[17] = 'r'; + if (mode & S_IWOTH) acl_text[18] = 'w'; + if (mode & S_IXOTH) acl_text[19] = 'x'; + + acl = acl_from_text (acl_text); + if (!acl) + return -1; + } + if (HAVE_ACL_SET_FD && desc != -1) + ret = acl_set_fd (desc, acl); + else + ret = acl_set_file (name, ACL_TYPE_ACCESS, acl); + if (ret != 0) + { + int saved_errno = errno; + acl_free (acl); + if (! acl_errno_valid (errno)) + return chmod_or_fchmod (name, desc, mode); + errno = saved_errno; + return -1; + } + else + acl_free (acl); + + if (S_ISDIR (mode) && acl_delete_def_file (name)) + return -1; + + if (!MODE_INSIDE_ACL || (mode & (S_ISUID | S_ISGID | S_ISVTX))) + { + /* We did not call chmod so far, and either the mode and the ACL are + separate or special bits are to be set which don't fit into ACLs. */ + return chmod_or_fchmod (name, desc, mode); + } + return 0; + +# else /* HAVE_ACL_TYPE_EXTENDED */ + /* Mac OS X */ + + /* On Mac OS X, acl_get_file (name, ACL_TYPE_ACCESS) + and acl_get_file (name, ACL_TYPE_DEFAULT) + always return NULL / EINVAL. You have to use + acl_get_file (name, ACL_TYPE_EXTENDED) + or acl_get_fd (open (name, ...)) + to retrieve an ACL. + On the other hand, + acl_set_file (name, ACL_TYPE_ACCESS, acl) + and acl_set_file (name, ACL_TYPE_DEFAULT, acl) + have the same effect as + acl_set_file (name, ACL_TYPE_EXTENDED, acl): + Each of these calls sets the file's ACL. */ + + acl_t acl; + int ret; + + /* Remove the ACL if the file has ACLs. */ + if (HAVE_ACL_GET_FD && desc != -1) + acl = acl_get_fd (desc); + else + acl = acl_get_file (name, ACL_TYPE_EXTENDED); + if (acl) + { + acl_free (acl); + + acl = acl_init (0); + if (acl) + { + if (HAVE_ACL_SET_FD && desc != -1) + ret = acl_set_fd (desc, acl); + else + ret = acl_set_file (name, ACL_TYPE_EXTENDED, acl); + if (ret != 0) + { + int saved_errno = errno; + acl_free (acl); + if (! acl_errno_valid (saved_errno)) + return chmod_or_fchmod (name, desc, mode); + errno = saved_errno; + return -1; + } + acl_free (acl); + } + } + + /* Since !MODE_INSIDE_ACL, we have to call chmod explicitly. */ + return chmod_or_fchmod (name, desc, mode); +# endif + +# elif HAVE_FACL && defined GETACL /* Solaris, Cygwin, not HP-UX */ + + int done_setacl = 0; + +# ifdef ACE_GETACL + /* Solaris also has a different variant of ACLs, used in ZFS and NFSv4 + file systems (whereas the other ones are used in UFS file systems). */ + + /* The flags in the ace_t structure changed in a binary incompatible way + when ACL_NO_TRIVIAL etc. were introduced in version 1.15. + How to distinguish the two conventions at runtime? + We fetch the existing ACL. In the old convention, usually three ACEs have + a_flags = ACE_OWNER / ACE_GROUP / ACE_OTHER, in the range 0x0100..0x0400. + In the new convention, these values are not used. */ + int convention; + + { + /* Initially, try to read the entries into a stack-allocated buffer. + Use malloc if it does not fit. */ + enum + { + alloc_init = 4000 / sizeof (ace_t), /* >= 3 */ + alloc_max = MIN (INT_MAX, SIZE_MAX / sizeof (ace_t)) + }; + ace_t buf[alloc_init]; + size_t alloc = alloc_init; + ace_t *entries = buf; + ace_t *malloced = NULL; + int count; + + for (;;) + { + count = (desc != -1 + ? facl (desc, ACE_GETACL, alloc, entries) + : acl (name, ACE_GETACL, alloc, entries)); + if (count < 0 && errno == ENOSPC) + { + /* Increase the size of the buffer. */ + free (malloced); + if (alloc > alloc_max / 2) + { + errno = ENOMEM; + return -1; + } + alloc = 2 * alloc; /* <= alloc_max */ + entries = malloced = (ace_t *) malloc (alloc * sizeof (ace_t)); + if (entries == NULL) + { + errno = ENOMEM; + return -1; + } + continue; + } + break; + } + + if (count <= 0) + convention = -1; + else + { + int i; + + convention = 0; + for (i = 0; i < count; i++) + if (entries[i].a_flags & (OLD_ACE_OWNER | OLD_ACE_GROUP | OLD_ACE_OTHER)) + { + convention = 1; + break; + } + } + free (malloced); + } + + if (convention >= 0) + { + ace_t entries[6]; + int count; + int ret; + + if (convention) + { + /* Running on Solaris 10. */ + entries[0].a_type = OLD_ALLOW; + entries[0].a_flags = OLD_ACE_OWNER; + entries[0].a_who = 0; /* irrelevant */ + entries[0].a_access_mask = (mode >> 6) & 7; + entries[1].a_type = OLD_ALLOW; + entries[1].a_flags = OLD_ACE_GROUP; + entries[1].a_who = 0; /* irrelevant */ + entries[1].a_access_mask = (mode >> 3) & 7; + entries[2].a_type = OLD_ALLOW; + entries[2].a_flags = OLD_ACE_OTHER; + entries[2].a_who = 0; + entries[2].a_access_mask = mode & 7; + count = 3; + } + else + { + /* Running on Solaris 10 (newer version) or Solaris 11. + The details here were found through "/bin/ls -lvd somefiles". */ + entries[0].a_type = NEW_ACE_ACCESS_DENIED_ACE_TYPE; + entries[0].a_flags = NEW_ACE_OWNER; + entries[0].a_who = 0; /* irrelevant */ + entries[0].a_access_mask = 0; + entries[1].a_type = NEW_ACE_ACCESS_ALLOWED_ACE_TYPE; + entries[1].a_flags = NEW_ACE_OWNER; + entries[1].a_who = 0; /* irrelevant */ + entries[1].a_access_mask = NEW_ACE_WRITE_NAMED_ATTRS + | NEW_ACE_WRITE_ATTRIBUTES + | NEW_ACE_WRITE_ACL + | NEW_ACE_WRITE_OWNER; + if (mode & 0400) + entries[1].a_access_mask |= NEW_ACE_READ_DATA; + else + entries[0].a_access_mask |= NEW_ACE_READ_DATA; + if (mode & 0200) + entries[1].a_access_mask |= NEW_ACE_WRITE_DATA | NEW_ACE_APPEND_DATA; + else + entries[0].a_access_mask |= NEW_ACE_WRITE_DATA | NEW_ACE_APPEND_DATA; + if (mode & 0100) + entries[1].a_access_mask |= NEW_ACE_EXECUTE; + else + entries[0].a_access_mask |= NEW_ACE_EXECUTE; + entries[2].a_type = NEW_ACE_ACCESS_DENIED_ACE_TYPE; + entries[2].a_flags = NEW_ACE_GROUP | NEW_ACE_IDENTIFIER_GROUP; + entries[2].a_who = 0; /* irrelevant */ + entries[2].a_access_mask = 0; + entries[3].a_type = NEW_ACE_ACCESS_ALLOWED_ACE_TYPE; + entries[3].a_flags = NEW_ACE_GROUP | NEW_ACE_IDENTIFIER_GROUP; + entries[3].a_who = 0; /* irrelevant */ + entries[3].a_access_mask = 0; + if (mode & 0040) + entries[3].a_access_mask |= NEW_ACE_READ_DATA; + else + entries[2].a_access_mask |= NEW_ACE_READ_DATA; + if (mode & 0020) + entries[3].a_access_mask |= NEW_ACE_WRITE_DATA | NEW_ACE_APPEND_DATA; + else + entries[2].a_access_mask |= NEW_ACE_WRITE_DATA | NEW_ACE_APPEND_DATA; + if (mode & 0010) + entries[3].a_access_mask |= NEW_ACE_EXECUTE; + else + entries[2].a_access_mask |= NEW_ACE_EXECUTE; + entries[4].a_type = NEW_ACE_ACCESS_DENIED_ACE_TYPE; + entries[4].a_flags = NEW_ACE_EVERYONE; + entries[4].a_who = 0; + entries[4].a_access_mask = NEW_ACE_WRITE_NAMED_ATTRS + | NEW_ACE_WRITE_ATTRIBUTES + | NEW_ACE_WRITE_ACL + | NEW_ACE_WRITE_OWNER; + entries[5].a_type = NEW_ACE_ACCESS_ALLOWED_ACE_TYPE; + entries[5].a_flags = NEW_ACE_EVERYONE; + entries[5].a_who = 0; + entries[5].a_access_mask = NEW_ACE_READ_NAMED_ATTRS + | NEW_ACE_READ_ATTRIBUTES + | NEW_ACE_READ_ACL + | NEW_ACE_SYNCHRONIZE; + if (mode & 0004) + entries[5].a_access_mask |= NEW_ACE_READ_DATA; + else + entries[4].a_access_mask |= NEW_ACE_READ_DATA; + if (mode & 0002) + entries[5].a_access_mask |= NEW_ACE_WRITE_DATA | NEW_ACE_APPEND_DATA; + else + entries[4].a_access_mask |= NEW_ACE_WRITE_DATA | NEW_ACE_APPEND_DATA; + if (mode & 0001) + entries[5].a_access_mask |= NEW_ACE_EXECUTE; + else + entries[4].a_access_mask |= NEW_ACE_EXECUTE; + count = 6; + } + if (desc != -1) + ret = facl (desc, ACE_SETACL, count, entries); + else + ret = acl (name, ACE_SETACL, count, entries); + if (ret < 0 && errno != EINVAL && errno != ENOTSUP) + { + if (errno == ENOSYS) + return chmod_or_fchmod (name, desc, mode); + return -1; + } + if (ret == 0) + done_setacl = 1; + } +# endif + + if (!done_setacl) + { + aclent_t entries[3]; + int ret; + + entries[0].a_type = USER_OBJ; + entries[0].a_id = 0; /* irrelevant */ + entries[0].a_perm = (mode >> 6) & 7; + entries[1].a_type = GROUP_OBJ; + entries[1].a_id = 0; /* irrelevant */ + entries[1].a_perm = (mode >> 3) & 7; + entries[2].a_type = OTHER_OBJ; + entries[2].a_id = 0; + entries[2].a_perm = mode & 7; + + if (desc != -1) + ret = facl (desc, SETACL, + sizeof (entries) / sizeof (aclent_t), entries); + else + ret = acl (name, SETACL, + sizeof (entries) / sizeof (aclent_t), entries); + if (ret < 0) + { + if (errno == ENOSYS || errno == EOPNOTSUPP) + return chmod_or_fchmod (name, desc, mode); + return -1; + } + } + + if (!MODE_INSIDE_ACL || (mode & (S_ISUID | S_ISGID | S_ISVTX))) + { + /* We did not call chmod so far, so the special bits have not yet + been set. */ + return chmod_or_fchmod (name, desc, mode); + } + return 0; + +# elif HAVE_GETACL /* HP-UX */ + + struct stat statbuf; + int ret; + + if (desc != -1) + ret = fstat (desc, &statbuf); + else + ret = stat (name, &statbuf); + if (ret < 0) + return -1; + + { + struct acl_entry entries[3]; + + entries[0].uid = statbuf.st_uid; + entries[0].gid = ACL_NSGROUP; + entries[0].mode = (mode >> 6) & 7; + entries[1].uid = ACL_NSUSER; + entries[1].gid = statbuf.st_gid; + entries[1].mode = (mode >> 3) & 7; + entries[2].uid = ACL_NSUSER; + entries[2].gid = ACL_NSGROUP; + entries[2].mode = mode & 7; + + if (desc != -1) + ret = fsetacl (desc, sizeof (entries) / sizeof (struct acl_entry), entries); + else + ret = setacl (name, sizeof (entries) / sizeof (struct acl_entry), entries); + } + if (ret < 0) + { + if (!(errno == ENOSYS || errno == EOPNOTSUPP || errno == ENOTSUP)) + return -1; + +# if HAVE_ACLV_H /* HP-UX >= 11.11 */ + { + struct acl entries[4]; + + entries[0].a_type = USER_OBJ; + entries[0].a_id = 0; /* irrelevant */ + entries[0].a_perm = (mode >> 6) & 7; + entries[1].a_type = GROUP_OBJ; + entries[1].a_id = 0; /* irrelevant */ + entries[1].a_perm = (mode >> 3) & 7; + entries[2].a_type = CLASS_OBJ; + entries[2].a_id = 0; + entries[2].a_perm = (mode >> 3) & 7; + entries[3].a_type = OTHER_OBJ; + entries[3].a_id = 0; + entries[3].a_perm = mode & 7; + + ret = aclsort (sizeof (entries) / sizeof (struct acl), 1, entries); + if (ret > 0) + abort (); + if (ret < 0) + { + if (0) + return chmod_or_fchmod (name, desc, mode); + return -1; + } + + ret = acl ((char *) name, ACL_SET, + sizeof (entries) / sizeof (struct acl), entries); + if (ret < 0) + { + if (errno == ENOSYS || errno == EOPNOTSUPP || errno == EINVAL) + return chmod_or_fchmod (name, desc, mode); + return -1; + } + } +# else + return chmod_or_fchmod (name, desc, mode); +# endif + } + + if (mode & (S_ISUID | S_ISGID | S_ISVTX)) + { + /* We did not call chmod so far, so the special bits have not yet + been set. */ + return chmod_or_fchmod (name, desc, mode); + } + return 0; + +# elif HAVE_ACLX_GET && defined ACL_AIX_WIP /* AIX */ + + acl_type_list_t types; + size_t types_size = sizeof (types); + acl_type_t type; + + if (aclx_gettypes (name, &types, &types_size) < 0 + || types.num_entries == 0) + return chmod_or_fchmod (name, desc, mode); + + /* XXX Do we need to clear all types of ACLs for the given file, or is it + sufficient to clear the first one? */ + type = types.entries[0]; + if (type.u64 == ACL_AIXC) + { + union { struct acl a; char room[128]; } u; + int ret; + + u.a.acl_len = (char *) &u.a.acl_ext[0] - (char *) &u.a; /* no entries */ + u.a.acl_mode = mode & ~(S_IXACL | 0777); + u.a.u_access = (mode >> 6) & 7; + u.a.g_access = (mode >> 3) & 7; + u.a.o_access = mode & 7; + + if (desc != -1) + ret = aclx_fput (desc, SET_ACL | SET_MODE_S_BITS, + type, &u.a, u.a.acl_len, mode); + else + ret = aclx_put (name, SET_ACL | SET_MODE_S_BITS, + type, &u.a, u.a.acl_len, mode); + if (!(ret < 0 && errno == ENOSYS)) + return ret; + } + else if (type.u64 == ACL_NFS4) + { + union { nfs4_acl_int_t a; char room[128]; } u; + nfs4_ace_int_t *ace; + int ret; + + u.a.aclVersion = NFS4_ACL_INT_STRUCT_VERSION; + u.a.aclEntryN = 0; + ace = &u.a.aclEntry[0]; + { + ace->flags = ACE4_ID_SPECIAL; + ace->aceWho.special_whoid = ACE4_WHO_OWNER; + ace->aceType = ACE4_ACCESS_ALLOWED_ACE_TYPE; + ace->aceFlags = 0; + ace->aceMask = + (mode & 0400 ? ACE4_READ_DATA | ACE4_LIST_DIRECTORY : 0) + | (mode & 0200 + ? ACE4_WRITE_DATA | ACE4_ADD_FILE | ACE4_APPEND_DATA + | ACE4_ADD_SUBDIRECTORY + : 0) + | (mode & 0100 ? ACE4_EXECUTE : 0); + ace->aceWhoString[0] = '\0'; + ace->entryLen = (char *) &ace->aceWhoString[4] - (char *) ace; + ace = (nfs4_ace_int_t *) (char *) &ace->aceWhoString[4]; + u.a.aclEntryN++; + } + { + ace->flags = ACE4_ID_SPECIAL; + ace->aceWho.special_whoid = ACE4_WHO_GROUP; + ace->aceType = ACE4_ACCESS_ALLOWED_ACE_TYPE; + ace->aceFlags = 0; + ace->aceMask = + (mode & 0040 ? ACE4_READ_DATA | ACE4_LIST_DIRECTORY : 0) + | (mode & 0020 + ? ACE4_WRITE_DATA | ACE4_ADD_FILE | ACE4_APPEND_DATA + | ACE4_ADD_SUBDIRECTORY + : 0) + | (mode & 0010 ? ACE4_EXECUTE : 0); + ace->aceWhoString[0] = '\0'; + ace->entryLen = (char *) &ace->aceWhoString[4] - (char *) ace; + ace = (nfs4_ace_int_t *) (char *) &ace->aceWhoString[4]; + u.a.aclEntryN++; + } + { + ace->flags = ACE4_ID_SPECIAL; + ace->aceWho.special_whoid = ACE4_WHO_EVERYONE; + ace->aceType = ACE4_ACCESS_ALLOWED_ACE_TYPE; + ace->aceFlags = 0; + ace->aceMask = + (mode & 0004 ? ACE4_READ_DATA | ACE4_LIST_DIRECTORY : 0) + | (mode & 0002 + ? ACE4_WRITE_DATA | ACE4_ADD_FILE | ACE4_APPEND_DATA + | ACE4_ADD_SUBDIRECTORY + : 0) + | (mode & 0001 ? ACE4_EXECUTE : 0); + ace->aceWhoString[0] = '\0'; + ace->entryLen = (char *) &ace->aceWhoString[4] - (char *) ace; + ace = (nfs4_ace_int_t *) (char *) &ace->aceWhoString[4]; + u.a.aclEntryN++; + } + u.a.aclLength = (char *) ace - (char *) &u.a; + + if (desc != -1) + ret = aclx_fput (desc, SET_ACL | SET_MODE_S_BITS, + type, &u.a, u.a.aclLength, mode); + else + ret = aclx_put (name, SET_ACL | SET_MODE_S_BITS, + type, &u.a, u.a.aclLength, mode); + if (!(ret < 0 && errno == ENOSYS)) + return ret; + } + + return chmod_or_fchmod (name, desc, mode); + +# elif HAVE_STATACL /* older AIX */ + + union { struct acl a; char room[128]; } u; + int ret; + + u.a.acl_len = (char *) &u.a.acl_ext[0] - (char *) &u.a; /* no entries */ + u.a.acl_mode = mode & ~(S_IXACL | 0777); + u.a.u_access = (mode >> 6) & 7; + u.a.g_access = (mode >> 3) & 7; + u.a.o_access = mode & 7; + + if (desc != -1) + ret = fchacl (desc, &u.a, u.a.acl_len); + else + ret = chacl (name, &u.a, u.a.acl_len); + + if (ret < 0 && errno == ENOSYS) + return chmod_or_fchmod (name, desc, mode); + + return ret; + +# elif HAVE_ACLSORT /* NonStop Kernel */ + + struct acl entries[4]; + int ret; + + entries[0].a_type = USER_OBJ; + entries[0].a_id = 0; /* irrelevant */ + entries[0].a_perm = (mode >> 6) & 7; + entries[1].a_type = GROUP_OBJ; + entries[1].a_id = 0; /* irrelevant */ + entries[1].a_perm = (mode >> 3) & 7; + entries[2].a_type = CLASS_OBJ; + entries[2].a_id = 0; + entries[2].a_perm = (mode >> 3) & 7; + entries[3].a_type = OTHER_OBJ; + entries[3].a_id = 0; + entries[3].a_perm = mode & 7; + + ret = aclsort (sizeof (entries) / sizeof (struct acl), 1, entries); + if (ret > 0) + abort (); + if (ret < 0) + { + if (0) + return chmod_or_fchmod (name, desc, mode); + return -1; + } + + ret = acl ((char *) name, ACL_SET, + sizeof (entries) / sizeof (struct acl), entries); + if (ret < 0) + { + if (0) + return chmod_or_fchmod (name, desc, mode); + return -1; + } + + if (mode & (S_ISUID | S_ISGID | S_ISVTX)) + { + /* We did not call chmod so far, so the special bits have not yet + been set. */ + return chmod_or_fchmod (name, desc, mode); + } + return 0; + +# else /* Unknown flavor of ACLs */ + return chmod_or_fchmod (name, desc, mode); +# endif +#else /* !USE_ACL */ + return chmod_or_fchmod (name, desc, mode); +#endif +} diff --git a/gettext-tools/gnulib-lib/quote.h b/gettext-tools/gnulib-lib/quote.h new file mode 100644 index 0000000..fb338a7 --- /dev/null +++ b/gettext-tools/gnulib-lib/quote.h @@ -0,0 +1,46 @@ +/* quote.h - prototypes for quote.c + + Copyright (C) 1998-2001, 2003, 2009-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef QUOTE_H_ +# define QUOTE_H_ 1 + +# include + +/* The quoting options used by quote_n and quote. Its type is incomplete, + so it's useful only in expressions like '"e_quoting_options'. */ +extern struct quoting_options quote_quoting_options; + +/* Return an unambiguous printable representation of ARG (of size + ARGSIZE), allocated in slot N, suitable for diagnostics. If + ARGSIZE is SIZE_MAX, use the string length of the argument for + ARGSIZE. */ +char const *quote_n_mem (int n, char const *arg, size_t argsize); + +/* Return an unambiguous printable representation of ARG (of size + ARGSIZE), suitable for diagnostics. If ARGSIZE is SIZE_MAX, use + the string length of the argument for ARGSIZE. */ +char const *quote_mem (char const *arg, size_t argsize); + +/* Return an unambiguous printable representation of ARG, allocated in + slot N, suitable for diagnostics. */ +char const *quote_n (int n, char const *arg); + +/* Return an unambiguous printable representation of ARG, suitable for + diagnostics. */ +char const *quote (char const *arg); + +#endif /* !QUOTE_H_ */ diff --git a/gettext-tools/gnulib-lib/quotearg.c b/gettext-tools/gnulib-lib/quotearg.c new file mode 100644 index 0000000..bef7b98 --- /dev/null +++ b/gettext-tools/gnulib-lib/quotearg.c @@ -0,0 +1,968 @@ +/* quotearg.c - quote arguments for output + + Copyright (C) 1998-2002, 2004-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Written by Paul Eggert */ + +/* Without this pragma, gcc 4.7.0 20111124 mistakenly suggests that + the quoting_options_from_style function might be candidate for + attribute 'pure' */ +#if (__GNUC__ == 4 && 6 <= __GNUC_MINOR__) || 4 < __GNUC__ +# pragma GCC diagnostic ignored "-Wsuggest-attribute=pure" +#endif + +#include + +#include "quotearg.h" +#include "quote.h" + +#include "xalloc.h" +#include "c-strcaseeq.h" +#include "localcharset.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gettext.h" +#define _(msgid) gettext (msgid) +#define N_(msgid) msgid + +#ifndef SIZE_MAX +# define SIZE_MAX ((size_t) -1) +#endif + +#define INT_BITS (sizeof (int) * CHAR_BIT) + +struct quoting_options +{ + /* Basic quoting style. */ + enum quoting_style style; + + /* Additional flags. Bitwise combination of enum quoting_flags. */ + int flags; + + /* Quote the characters indicated by this bit vector even if the + quoting style would not normally require them to be quoted. */ + unsigned int quote_these_too[(UCHAR_MAX / INT_BITS) + 1]; + + /* The left quote for custom_quoting_style. */ + char const *left_quote; + + /* The right quote for custom_quoting_style. */ + char const *right_quote; +}; + +/* Names of quoting styles. */ +char const *const quoting_style_args[] = +{ + "literal", + "shell", + "shell-always", + "c", + "c-maybe", + "escape", + "locale", + "clocale", + 0 +}; + +/* Correspondences to quoting style names. */ +enum quoting_style const quoting_style_vals[] = +{ + literal_quoting_style, + shell_quoting_style, + shell_always_quoting_style, + c_quoting_style, + c_maybe_quoting_style, + escape_quoting_style, + locale_quoting_style, + clocale_quoting_style +}; + +/* The default quoting options. */ +static struct quoting_options default_quoting_options; + +/* Allocate a new set of quoting options, with contents initially identical + to O if O is not null, or to the default if O is null. + It is the caller's responsibility to free the result. */ +struct quoting_options * +clone_quoting_options (struct quoting_options *o) +{ + int e = errno; + struct quoting_options *p = xmemdup (o ? o : &default_quoting_options, + sizeof *o); + errno = e; + return p; +} + +/* Get the value of O's quoting style. If O is null, use the default. */ +enum quoting_style +get_quoting_style (struct quoting_options *o) +{ + return (o ? o : &default_quoting_options)->style; +} + +/* In O (or in the default if O is null), + set the value of the quoting style to S. */ +void +set_quoting_style (struct quoting_options *o, enum quoting_style s) +{ + (o ? o : &default_quoting_options)->style = s; +} + +/* In O (or in the default if O is null), + set the value of the quoting options for character C to I. + Return the old value. Currently, the only values defined for I are + 0 (the default) and 1 (which means to quote the character even if + it would not otherwise be quoted). */ +int +set_char_quoting (struct quoting_options *o, char c, int i) +{ + unsigned char uc = c; + unsigned int *p = + (o ? o : &default_quoting_options)->quote_these_too + uc / INT_BITS; + int shift = uc % INT_BITS; + int r = (*p >> shift) & 1; + *p ^= ((i & 1) ^ r) << shift; + return r; +} + +/* In O (or in the default if O is null), + set the value of the quoting options flag to I, which can be a + bitwise combination of enum quoting_flags, or 0 for default + behavior. Return the old value. */ +int +set_quoting_flags (struct quoting_options *o, int i) +{ + int r; + if (!o) + o = &default_quoting_options; + r = o->flags; + o->flags = i; + return r; +} + +void +set_custom_quoting (struct quoting_options *o, + char const *left_quote, char const *right_quote) +{ + if (!o) + o = &default_quoting_options; + o->style = custom_quoting_style; + if (!left_quote || !right_quote) + abort (); + o->left_quote = left_quote; + o->right_quote = right_quote; +} + +/* Return quoting options for STYLE, with no extra quoting. */ +static struct quoting_options /* NOT PURE!! */ +quoting_options_from_style (enum quoting_style style) +{ + struct quoting_options o = { literal_quoting_style, 0, { 0 }, NULL, NULL }; + if (style == custom_quoting_style) + abort (); + o.style = style; + return o; +} + +/* MSGID approximates a quotation mark. Return its translation if it + has one; otherwise, return either it or "\"", depending on S. + + S is either clocale_quoting_style or locale_quoting_style. */ +static char const * +gettext_quote (char const *msgid, enum quoting_style s) +{ + char const *translation = _(msgid); + char const *locale_code; + + if (translation != msgid) + return translation; + + /* For UTF-8 and GB-18030, use single quotes U+2018 and U+2019. + Here is a list of other locales that include U+2018 and U+2019: + + ISO-8859-7 0xA1 KOI8-T 0x91 + CP869 0x8B CP874 0x91 + CP932 0x81 0x65 CP936 0xA1 0xAE + CP949 0xA1 0xAE CP950 0xA1 0xA5 + CP1250 0x91 CP1251 0x91 + CP1252 0x91 CP1253 0x91 + CP1254 0x91 CP1255 0x91 + CP1256 0x91 CP1257 0x91 + EUC-JP 0xA1 0xC6 EUC-KR 0xA1 0xAE + EUC-TW 0xA1 0xE4 BIG5 0xA1 0xA5 + BIG5-HKSCS 0xA1 0xA5 EUC-CN 0xA1 0xAE + GBK 0xA1 0xAE Georgian-PS 0x91 + PT154 0x91 + + None of these is still in wide use; using iconv is overkill. */ + locale_code = locale_charset (); + if (STRCASEEQ (locale_code, "UTF-8", 'U','T','F','-','8',0,0,0,0)) + return msgid[0] == '`' ? "\xe2\x80\x98": "\xe2\x80\x99"; + if (STRCASEEQ (locale_code, "GB18030", 'G','B','1','8','0','3','0',0,0)) + return msgid[0] == '`' ? "\xa1\ae": "\xa1\xaf"; + + return (s == clocale_quoting_style ? "\"" : "'"); +} + +/* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of + argument ARG (of size ARGSIZE), using QUOTING_STYLE, FLAGS, and + QUOTE_THESE_TOO to control quoting. + Terminate the output with a null character, and return the written + size of the output, not counting the terminating null. + If BUFFERSIZE is too small to store the output string, return the + value that would have been returned had BUFFERSIZE been large enough. + If ARGSIZE is SIZE_MAX, use the string length of the argument for ARGSIZE. + + This function acts like quotearg_buffer (BUFFER, BUFFERSIZE, ARG, + ARGSIZE, O), except it breaks O into its component pieces and is + not careful about errno. */ + +static size_t +quotearg_buffer_restyled (char *buffer, size_t buffersize, + char const *arg, size_t argsize, + enum quoting_style quoting_style, int flags, + unsigned int const *quote_these_too, + char const *left_quote, + char const *right_quote) +{ + size_t i; + size_t len = 0; + char const *quote_string = 0; + size_t quote_string_len = 0; + bool backslash_escapes = false; + bool unibyte_locale = MB_CUR_MAX == 1; + bool elide_outer_quotes = (flags & QA_ELIDE_OUTER_QUOTES) != 0; + +#define STORE(c) \ + do \ + { \ + if (len < buffersize) \ + buffer[len] = (c); \ + len++; \ + } \ + while (0) + + switch (quoting_style) + { + case c_maybe_quoting_style: + quoting_style = c_quoting_style; + elide_outer_quotes = true; + /* Fall through. */ + case c_quoting_style: + if (!elide_outer_quotes) + STORE ('"'); + backslash_escapes = true; + quote_string = "\""; + quote_string_len = 1; + break; + + case escape_quoting_style: + backslash_escapes = true; + elide_outer_quotes = false; + break; + + case locale_quoting_style: + case clocale_quoting_style: + case custom_quoting_style: + { + if (quoting_style != custom_quoting_style) + { + /* TRANSLATORS: + Get translations for open and closing quotation marks. + The message catalog should translate "`" to a left + quotation mark suitable for the locale, and similarly for + "'". For example, a French Unicode local should translate + these to U+00AB (LEFT-POINTING DOUBLE ANGLE + QUOTATION MARK), and U+00BB (RIGHT-POINTING DOUBLE ANGLE + QUOTATION MARK), respectively. + + If the catalog has no translation, we will try to + use Unicode U+2018 (LEFT SINGLE QUOTATION MARK) and + Unicode U+2019 (RIGHT SINGLE QUOTATION MARK). If the + current locale is not Unicode, locale_quoting_style + will quote 'like this', and clocale_quoting_style will + quote "like this". You should always include translations + for "`" and "'" even if U+2018 and U+2019 are appropriate + for your locale. + + If you don't know what to put here, please see + + and use glyphs suitable for your language. */ + left_quote = gettext_quote (N_("`"), quoting_style); + right_quote = gettext_quote (N_("'"), quoting_style); + } + if (!elide_outer_quotes) + for (quote_string = left_quote; *quote_string; quote_string++) + STORE (*quote_string); + backslash_escapes = true; + quote_string = right_quote; + quote_string_len = strlen (quote_string); + } + break; + + case shell_quoting_style: + quoting_style = shell_always_quoting_style; + elide_outer_quotes = true; + /* Fall through. */ + case shell_always_quoting_style: + if (!elide_outer_quotes) + STORE ('\''); + quote_string = "'"; + quote_string_len = 1; + break; + + case literal_quoting_style: + elide_outer_quotes = false; + break; + + default: + abort (); + } + + for (i = 0; ! (argsize == SIZE_MAX ? arg[i] == '\0' : i == argsize); i++) + { + unsigned char c; + unsigned char esc; + bool is_right_quote = false; + + if (backslash_escapes + && quote_string_len + && (i + quote_string_len + <= (argsize == SIZE_MAX && 1 < quote_string_len + /* Use strlen only if we must: when argsize is SIZE_MAX, + and when the quote string is more than 1 byte long. + If we do call strlen, save the result. */ + ? (argsize = strlen (arg)) : argsize)) + && memcmp (arg + i, quote_string, quote_string_len) == 0) + { + if (elide_outer_quotes) + goto force_outer_quoting_style; + is_right_quote = true; + } + + c = arg[i]; + switch (c) + { + case '\0': + if (backslash_escapes) + { + if (elide_outer_quotes) + goto force_outer_quoting_style; + STORE ('\\'); + /* If quote_string were to begin with digits, we'd need to + test for the end of the arg as well. However, it's + hard to imagine any locale that would use digits in + quotes, and set_custom_quoting is documented not to + accept them. */ + if (i + 1 < argsize && '0' <= arg[i + 1] && arg[i + 1] <= '9') + { + STORE ('0'); + STORE ('0'); + } + c = '0'; + /* We don't have to worry that this last '0' will be + backslash-escaped because, again, quote_string should + not start with it and because quote_these_too is + documented as not accepting it. */ + } + else if (flags & QA_ELIDE_NULL_BYTES) + continue; + break; + + case '?': + switch (quoting_style) + { + case shell_always_quoting_style: + if (elide_outer_quotes) + goto force_outer_quoting_style; + break; + + case c_quoting_style: + if ((flags & QA_SPLIT_TRIGRAPHS) + && i + 2 < argsize && arg[i + 1] == '?') + switch (arg[i + 2]) + { + case '!': case '\'': + case '(': case ')': case '-': case '/': + case '<': case '=': case '>': + /* Escape the second '?' in what would otherwise be + a trigraph. */ + if (elide_outer_quotes) + goto force_outer_quoting_style; + c = arg[i + 2]; + i += 2; + STORE ('?'); + STORE ('"'); + STORE ('"'); + STORE ('?'); + break; + + default: + break; + } + break; + + default: + break; + } + break; + + case '\a': esc = 'a'; goto c_escape; + case '\b': esc = 'b'; goto c_escape; + case '\f': esc = 'f'; goto c_escape; + case '\n': esc = 'n'; goto c_and_shell_escape; + case '\r': esc = 'r'; goto c_and_shell_escape; + case '\t': esc = 't'; goto c_and_shell_escape; + case '\v': esc = 'v'; goto c_escape; + case '\\': esc = c; + /* No need to escape the escape if we are trying to elide + outer quotes and nothing else is problematic. */ + if (backslash_escapes && elide_outer_quotes && quote_string_len) + goto store_c; + + c_and_shell_escape: + if (quoting_style == shell_always_quoting_style + && elide_outer_quotes) + goto force_outer_quoting_style; + /* Fall through. */ + c_escape: + if (backslash_escapes) + { + c = esc; + goto store_escape; + } + break; + + case '{': case '}': /* sometimes special if isolated */ + if (! (argsize == SIZE_MAX ? arg[1] == '\0' : argsize == 1)) + break; + /* Fall through. */ + case '#': case '~': + if (i != 0) + break; + /* Fall through. */ + case ' ': + case '!': /* special in bash */ + case '"': case '$': case '&': + case '(': case ')': case '*': case ';': + case '<': + case '=': /* sometimes special in 0th or (with "set -k") later args */ + case '>': case '[': + case '^': /* special in old /bin/sh, e.g. SunOS 4.1.4 */ + case '`': case '|': + /* A shell special character. In theory, '$' and '`' could + be the first bytes of multibyte characters, which means + we should check them with mbrtowc, but in practice this + doesn't happen so it's not worth worrying about. */ + if (quoting_style == shell_always_quoting_style + && elide_outer_quotes) + goto force_outer_quoting_style; + break; + + case '\'': + if (quoting_style == shell_always_quoting_style) + { + if (elide_outer_quotes) + goto force_outer_quoting_style; + STORE ('\''); + STORE ('\\'); + STORE ('\''); + } + break; + + case '%': case '+': case ',': case '-': case '.': case '/': + case '0': case '1': case '2': case '3': case '4': case '5': + case '6': case '7': case '8': case '9': case ':': + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': + case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': + case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': + case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': + case 'Y': case 'Z': case ']': case '_': case 'a': case 'b': + case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': + case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': + case 'o': case 'p': case 'q': case 'r': case 's': case 't': + case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': + /* These characters don't cause problems, no matter what the + quoting style is. They cannot start multibyte sequences. + A digit or a special letter would cause trouble if it + appeared at the beginning of quote_string because we'd then + escape by prepending a backslash. However, it's hard to + imagine any locale that would use digits or letters as + quotes, and set_custom_quoting is documented not to accept + them. Also, a digit or a special letter would cause + trouble if it appeared in quote_these_too, but that's also + documented as not accepting them. */ + break; + + default: + /* If we have a multibyte sequence, copy it until we reach + its end, find an error, or come back to the initial shift + state. For C-like styles, if the sequence has + unprintable characters, escape the whole sequence, since + we can't easily escape single characters within it. */ + { + /* Length of multibyte sequence found so far. */ + size_t m; + + bool printable; + + if (unibyte_locale) + { + m = 1; + printable = isprint (c) != 0; + } + else + { + mbstate_t mbstate; + memset (&mbstate, 0, sizeof mbstate); + + m = 0; + printable = true; + if (argsize == SIZE_MAX) + argsize = strlen (arg); + + do + { + wchar_t w; + size_t bytes = mbrtowc (&w, &arg[i + m], + argsize - (i + m), &mbstate); + if (bytes == 0) + break; + else if (bytes == (size_t) -1) + { + printable = false; + break; + } + else if (bytes == (size_t) -2) + { + printable = false; + while (i + m < argsize && arg[i + m]) + m++; + break; + } + else + { + /* Work around a bug with older shells that "see" a '\' + that is really the 2nd byte of a multibyte character. + In practice the problem is limited to ASCII + chars >= '@' that are shell special chars. */ + if ('[' == 0x5b && elide_outer_quotes + && quoting_style == shell_always_quoting_style) + { + size_t j; + for (j = 1; j < bytes; j++) + switch (arg[i + m + j]) + { + case '[': case '\\': case '^': + case '`': case '|': + goto force_outer_quoting_style; + + default: + break; + } + } + + if (! iswprint (w)) + printable = false; + m += bytes; + } + } + while (! mbsinit (&mbstate)); + } + + if (1 < m || (backslash_escapes && ! printable)) + { + /* Output a multibyte sequence, or an escaped + unprintable unibyte character. */ + size_t ilim = i + m; + + for (;;) + { + if (backslash_escapes && ! printable) + { + if (elide_outer_quotes) + goto force_outer_quoting_style; + STORE ('\\'); + STORE ('0' + (c >> 6)); + STORE ('0' + ((c >> 3) & 7)); + c = '0' + (c & 7); + } + else if (is_right_quote) + { + STORE ('\\'); + is_right_quote = false; + } + if (ilim <= i + 1) + break; + STORE (c); + c = arg[++i]; + } + + goto store_c; + } + } + } + + if (! ((backslash_escapes || elide_outer_quotes) + && quote_these_too + && quote_these_too[c / INT_BITS] >> (c % INT_BITS) & 1) + && !is_right_quote) + goto store_c; + + store_escape: + if (elide_outer_quotes) + goto force_outer_quoting_style; + STORE ('\\'); + + store_c: + STORE (c); + } + + if (len == 0 && quoting_style == shell_always_quoting_style + && elide_outer_quotes) + goto force_outer_quoting_style; + + if (quote_string && !elide_outer_quotes) + for (; *quote_string; quote_string++) + STORE (*quote_string); + + if (len < buffersize) + buffer[len] = '\0'; + return len; + + force_outer_quoting_style: + /* Don't reuse quote_these_too, since the addition of outer quotes + sufficiently quotes the specified characters. */ + return quotearg_buffer_restyled (buffer, buffersize, arg, argsize, + quoting_style, + flags & ~QA_ELIDE_OUTER_QUOTES, NULL, + left_quote, right_quote); +} + +/* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of + argument ARG (of size ARGSIZE), using O to control quoting. + If O is null, use the default. + Terminate the output with a null character, and return the written + size of the output, not counting the terminating null. + If BUFFERSIZE is too small to store the output string, return the + value that would have been returned had BUFFERSIZE been large enough. + If ARGSIZE is SIZE_MAX, use the string length of the argument for + ARGSIZE. */ +size_t +quotearg_buffer (char *buffer, size_t buffersize, + char const *arg, size_t argsize, + struct quoting_options const *o) +{ + struct quoting_options const *p = o ? o : &default_quoting_options; + int e = errno; + size_t r = quotearg_buffer_restyled (buffer, buffersize, arg, argsize, + p->style, p->flags, p->quote_these_too, + p->left_quote, p->right_quote); + errno = e; + return r; +} + +/* Equivalent to quotearg_alloc (ARG, ARGSIZE, NULL, O). */ +char * +quotearg_alloc (char const *arg, size_t argsize, + struct quoting_options const *o) +{ + return quotearg_alloc_mem (arg, argsize, NULL, o); +} + +/* Like quotearg_buffer (..., ARG, ARGSIZE, O), except return newly + allocated storage containing the quoted string, and store the + resulting size into *SIZE, if non-NULL. The result can contain + embedded null bytes only if ARGSIZE is not SIZE_MAX, SIZE is not + NULL, and set_quoting_flags has not set the null byte elision + flag. */ +char * +quotearg_alloc_mem (char const *arg, size_t argsize, size_t *size, + struct quoting_options const *o) +{ + struct quoting_options const *p = o ? o : &default_quoting_options; + int e = errno; + /* Elide embedded null bytes if we can't return a size. */ + int flags = p->flags | (size ? 0 : QA_ELIDE_NULL_BYTES); + size_t bufsize = quotearg_buffer_restyled (0, 0, arg, argsize, p->style, + flags, p->quote_these_too, + p->left_quote, + p->right_quote) + 1; + char *buf = xcharalloc (bufsize); + quotearg_buffer_restyled (buf, bufsize, arg, argsize, p->style, flags, + p->quote_these_too, + p->left_quote, p->right_quote); + errno = e; + if (size) + *size = bufsize - 1; + return buf; +} + +/* A storage slot with size and pointer to a value. */ +struct slotvec +{ + size_t size; + char *val; +}; + +/* Preallocate a slot 0 buffer, so that the caller can always quote + one small component of a "memory exhausted" message in slot 0. */ +static char slot0[256]; +static unsigned int nslots = 1; +static struct slotvec slotvec0 = {sizeof slot0, slot0}; +static struct slotvec *slotvec = &slotvec0; + +void +quotearg_free (void) +{ + struct slotvec *sv = slotvec; + unsigned int i; + for (i = 1; i < nslots; i++) + free (sv[i].val); + if (sv[0].val != slot0) + { + free (sv[0].val); + slotvec0.size = sizeof slot0; + slotvec0.val = slot0; + } + if (sv != &slotvec0) + { + free (sv); + slotvec = &slotvec0; + } + nslots = 1; +} + +/* Use storage slot N to return a quoted version of argument ARG. + ARG is of size ARGSIZE, but if that is SIZE_MAX, ARG is a + null-terminated string. + OPTIONS specifies the quoting options. + The returned value points to static storage that can be + reused by the next call to this function with the same value of N. + N must be nonnegative. N is deliberately declared with type "int" + to allow for future extensions (using negative values). */ +static char * +quotearg_n_options (int n, char const *arg, size_t argsize, + struct quoting_options const *options) +{ + int e = errno; + + unsigned int n0 = n; + struct slotvec *sv = slotvec; + + if (n < 0) + abort (); + + if (nslots <= n0) + { + /* FIXME: technically, the type of n1 should be 'unsigned int', + but that evokes an unsuppressible warning from gcc-4.0.1 and + older. If gcc ever provides an option to suppress that warning, + revert to the original type, so that the test in xalloc_oversized + is once again performed only at compile time. */ + size_t n1 = n0 + 1; + bool preallocated = (sv == &slotvec0); + + if (xalloc_oversized (n1, sizeof *sv)) + xalloc_die (); + + slotvec = sv = xrealloc (preallocated ? NULL : sv, n1 * sizeof *sv); + if (preallocated) + *sv = slotvec0; + memset (sv + nslots, 0, (n1 - nslots) * sizeof *sv); + nslots = n1; + } + + { + size_t size = sv[n].size; + char *val = sv[n].val; + /* Elide embedded null bytes since we don't return a size. */ + int flags = options->flags | QA_ELIDE_NULL_BYTES; + size_t qsize = quotearg_buffer_restyled (val, size, arg, argsize, + options->style, flags, + options->quote_these_too, + options->left_quote, + options->right_quote); + + if (size <= qsize) + { + sv[n].size = size = qsize + 1; + if (val != slot0) + free (val); + sv[n].val = val = xcharalloc (size); + quotearg_buffer_restyled (val, size, arg, argsize, options->style, + flags, options->quote_these_too, + options->left_quote, + options->right_quote); + } + + errno = e; + return val; + } +} + +char * +quotearg_n (int n, char const *arg) +{ + return quotearg_n_options (n, arg, SIZE_MAX, &default_quoting_options); +} + +char * +quotearg_n_mem (int n, char const *arg, size_t argsize) +{ + return quotearg_n_options (n, arg, argsize, &default_quoting_options); +} + +char * +quotearg (char const *arg) +{ + return quotearg_n (0, arg); +} + +char * +quotearg_mem (char const *arg, size_t argsize) +{ + return quotearg_n_mem (0, arg, argsize); +} + +char * +quotearg_n_style (int n, enum quoting_style s, char const *arg) +{ + struct quoting_options const o = quoting_options_from_style (s); + return quotearg_n_options (n, arg, SIZE_MAX, &o); +} + +char * +quotearg_n_style_mem (int n, enum quoting_style s, + char const *arg, size_t argsize) +{ + struct quoting_options const o = quoting_options_from_style (s); + return quotearg_n_options (n, arg, argsize, &o); +} + +char * +quotearg_style (enum quoting_style s, char const *arg) +{ + return quotearg_n_style (0, s, arg); +} + +char * +quotearg_style_mem (enum quoting_style s, char const *arg, size_t argsize) +{ + return quotearg_n_style_mem (0, s, arg, argsize); +} + +char * +quotearg_char_mem (char const *arg, size_t argsize, char ch) +{ + struct quoting_options options; + options = default_quoting_options; + set_char_quoting (&options, ch, 1); + return quotearg_n_options (0, arg, argsize, &options); +} + +char * +quotearg_char (char const *arg, char ch) +{ + return quotearg_char_mem (arg, SIZE_MAX, ch); +} + +char * +quotearg_colon (char const *arg) +{ + return quotearg_char (arg, ':'); +} + +char * +quotearg_colon_mem (char const *arg, size_t argsize) +{ + return quotearg_char_mem (arg, argsize, ':'); +} + +char * +quotearg_n_custom (int n, char const *left_quote, + char const *right_quote, char const *arg) +{ + return quotearg_n_custom_mem (n, left_quote, right_quote, arg, + SIZE_MAX); +} + +char * +quotearg_n_custom_mem (int n, char const *left_quote, + char const *right_quote, + char const *arg, size_t argsize) +{ + struct quoting_options o = default_quoting_options; + set_custom_quoting (&o, left_quote, right_quote); + return quotearg_n_options (n, arg, argsize, &o); +} + +char * +quotearg_custom (char const *left_quote, char const *right_quote, + char const *arg) +{ + return quotearg_n_custom (0, left_quote, right_quote, arg); +} + +char * +quotearg_custom_mem (char const *left_quote, char const *right_quote, + char const *arg, size_t argsize) +{ + return quotearg_n_custom_mem (0, left_quote, right_quote, arg, + argsize); +} + + +/* The quoting option used by the functions of quote.h. */ +struct quoting_options quote_quoting_options = + { + locale_quoting_style, + 0, + { 0 }, + NULL, NULL + }; + +char const * +quote_n_mem (int n, char const *arg, size_t argsize) +{ + return quotearg_n_options (n, arg, argsize, "e_quoting_options); +} + +char const * +quote_mem (char const *arg, size_t argsize) +{ + return quote_n_mem (0, arg, argsize); +} + +char const * +quote_n (int n, char const *arg) +{ + return quote_n_mem (n, arg, SIZE_MAX); +} + +char const * +quote (char const *arg) +{ + return quote_n (0, arg); +} diff --git a/gettext-tools/gnulib-lib/quotearg.h b/gettext-tools/gnulib-lib/quotearg.h new file mode 100644 index 0000000..da29d7b --- /dev/null +++ b/gettext-tools/gnulib-lib/quotearg.h @@ -0,0 +1,391 @@ +/* quotearg.h - quote arguments for output + + Copyright (C) 1998-2002, 2004, 2006, 2008-2014 Free Software Foundation, + Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Written by Paul Eggert */ + +#ifndef QUOTEARG_H_ +# define QUOTEARG_H_ 1 + +# include + +/* Basic quoting styles. For each style, an example is given on the + input strings "simple", "\0 \t\n'\"\033?""?/\\", and "a:b", using + quotearg_buffer, quotearg_mem, and quotearg_colon_mem with that + style and the default flags and quoted characters. Note that the + examples are shown here as valid C strings rather than what + displays on a terminal (with "??/" as a trigraph for "\\"). */ +enum quoting_style + { + /* Output names as-is (ls --quoting-style=literal). Can result in + embedded null bytes if QA_ELIDE_NULL_BYTES is not in + effect. + + quotearg_buffer: + "simple", "\0 \t\n'\"\033??/\\", "a:b" + quotearg: + "simple", " \t\n'\"\033??/\\", "a:b" + quotearg_colon: + "simple", " \t\n'\"\033??/\\", "a:b" + */ + literal_quoting_style, + + /* Quote names for the shell if they contain shell metacharacters + or would cause ambiguous output (ls --quoting-style=shell). + Can result in embedded null bytes if QA_ELIDE_NULL_BYTES is not + in effect. + + quotearg_buffer: + "simple", "'\0 \t\n'\\''\"\033??/\\'", "a:b" + quotearg: + "simple", "' \t\n'\\''\"\033??/\\'", "a:b" + quotearg_colon: + "simple", "' \t\n'\\''\"\033??/\\'", "'a:b'" + */ + shell_quoting_style, + + /* Quote names for the shell, even if they would normally not + require quoting (ls --quoting-style=shell-always). Can result + in embedded null bytes if QA_ELIDE_NULL_BYTES is not in effect. + Behaves like shell_quoting_style if QA_ELIDE_OUTER_QUOTES is in + effect. + + quotearg_buffer: + "'simple'", "'\0 \t\n'\\''\"\033??/\\'", "'a:b'" + quotearg: + "'simple'", "' \t\n'\\''\"\033??/\\'", "'a:b'" + quotearg_colon: + "'simple'", "' \t\n'\\''\"\033??/\\'", "'a:b'" + */ + shell_always_quoting_style, + + /* Quote names as for a C language string (ls --quoting-style=c). + Behaves like c_maybe_quoting_style if QA_ELIDE_OUTER_QUOTES is + in effect. Split into consecutive strings if + QA_SPLIT_TRIGRAPHS. + + quotearg_buffer: + "\"simple\"", "\"\\0 \\t\\n'\\\"\\033??/\\\\\"", "\"a:b\"" + quotearg: + "\"simple\"", "\"\\0 \\t\\n'\\\"\\033??/\\\\\"", "\"a:b\"" + quotearg_colon: + "\"simple\"", "\"\\0 \\t\\n'\\\"\\033??/\\\\\"", "\"a\\:b\"" + */ + c_quoting_style, + + /* Like c_quoting_style except omit the surrounding double-quote + characters if no quoted characters are encountered. + + quotearg_buffer: + "simple", "\"\\0 \\t\\n'\\\"\\033??/\\\\\"", "a:b" + quotearg: + "simple", "\"\\0 \\t\\n'\\\"\\033??/\\\\\"", "a:b" + quotearg_colon: + "simple", "\"\\0 \\t\\n'\\\"\\033??/\\\\\"", "\"a:b\"" + */ + c_maybe_quoting_style, + + /* Like c_quoting_style except always omit the surrounding + double-quote characters and ignore QA_SPLIT_TRIGRAPHS + (ls --quoting-style=escape). + + quotearg_buffer: + "simple", "\\0 \\t\\n'\"\\033??/\\\\", "a:b" + quotearg: + "simple", "\\0 \\t\\n'\"\\033??/\\\\", "a:b" + quotearg_colon: + "simple", "\\0 \\t\\n'\"\\033??/\\\\", "a\\:b" + */ + escape_quoting_style, + + /* Like clocale_quoting_style, but use single quotes in the + default C locale or if the program does not use gettext + (ls --quoting-style=locale). For UTF-8 locales, quote + characters will use Unicode. + + LC_MESSAGES=C + quotearg_buffer: + "`simple'", "`\\0 \\t\\n\\'\"\\033??/\\\\'", "`a:b'" + quotearg: + "`simple'", "`\\0 \\t\\n\\'\"\\033??/\\\\'", "`a:b'" + quotearg_colon: + "`simple'", "`\\0 \\t\\n\\'\"\\033??/\\\\'", "`a\\:b'" + + LC_MESSAGES=pt_PT.utf8 + quotearg_buffer: + "\302\253simple\302\273", + "\302\253\\0 \\t\\n'\"\\033??/\\\\\302\253", "\302\253a:b\302\273" + quotearg: + "\302\253simple\302\273", + "\302\253\\0 \\t\\n'\"\\033??/\\\\\302\253", "\302\253a:b\302\273" + quotearg_colon: + "\302\253simple\302\273", + "\302\253\\0 \\t\\n'\"\\033??/\\\\\302\253", "\302\253a\\:b\302\273" + */ + locale_quoting_style, + + /* Like c_quoting_style except use quotation marks appropriate for + the locale and ignore QA_SPLIT_TRIGRAPHS + (ls --quoting-style=clocale). + + LC_MESSAGES=C + quotearg_buffer: + "\"simple\"", "\"\\0 \\t\\n'\\\"\\033??/\\\\\"", "\"a:b\"" + quotearg: + "\"simple\"", "\"\\0 \\t\\n'\\\"\\033??/\\\\\"", "\"a:b\"" + quotearg_colon: + "\"simple\"", "\"\\0 \\t\\n'\\\"\\033??/\\\\\"", "\"a\\:b\"" + + LC_MESSAGES=pt_PT.utf8 + quotearg_buffer: + "\302\253simple\302\273", + "\302\253\\0 \\t\\n'\"\\033??/\\\\\302\253", "\302\253a:b\302\273" + quotearg: + "\302\253simple\302\273", + "\302\253\\0 \\t\\n'\"\\033??/\\\\\302\253", "\302\253a:b\302\273" + quotearg_colon: + "\302\253simple\302\273", + "\302\253\\0 \\t\\n'\"\\033??/\\\\\302\253", "\302\253a\\:b\302\273" + */ + clocale_quoting_style, + + /* Like clocale_quoting_style except use the custom quotation marks + set by set_custom_quoting. If custom quotation marks are not + set, the behavior is undefined. + + left_quote = right_quote = "'" + quotearg_buffer: + "'simple'", "'\\0 \\t\\n\\'\"\\033??/\\\\'", "'a:b'" + quotearg: + "'simple'", "'\\0 \\t\\n\\'\"\\033??/\\\\'", "'a:b'" + quotearg_colon: + "'simple'", "'\\0 \\t\\n\\'\"\\033??/\\\\'", "'a\\:b'" + + left_quote = "(" and right_quote = ")" + quotearg_buffer: + "(simple)", "(\\0 \\t\\n'\"\\033??/\\\\)", "(a:b)" + quotearg: + "(simple)", "(\\0 \\t\\n'\"\\033??/\\\\)", "(a:b)" + quotearg_colon: + "(simple)", "(\\0 \\t\\n'\"\\033??/\\\\)", "(a\\:b)" + + left_quote = ":" and right_quote = " " + quotearg_buffer: + ":simple ", ":\\0\\ \\t\\n'\"\\033??/\\\\ ", ":a:b " + quotearg: + ":simple ", ":\\0\\ \\t\\n'\"\\033??/\\\\ ", ":a:b " + quotearg_colon: + ":simple ", ":\\0\\ \\t\\n'\"\\033??/\\\\ ", ":a\\:b " + + left_quote = "\"'" and right_quote = "'\"" + Notice that this is treated as a single level of quotes or two + levels where the outer quote need not be escaped within the inner + quotes. For two levels where the outer quote must be escaped + within the inner quotes, you must use separate quotearg + invocations. + quotearg_buffer: + "\"'simple'\"", "\"'\\0 \\t\\n\\'\"\\033??/\\\\'\"", "\"'a:b'\"" + quotearg: + "\"'simple'\"", "\"'\\0 \\t\\n\\'\"\\033??/\\\\'\"", "\"'a:b'\"" + quotearg_colon: + "\"'simple'\"", "\"'\\0 \\t\\n\\'\"\\033??/\\\\'\"", "\"'a\\:b'\"" + */ + custom_quoting_style + }; + +/* Flags for use in set_quoting_flags. */ +enum quoting_flags + { + /* Always elide null bytes from styles that do not quote them, + even when the length of the result is available to the + caller. */ + QA_ELIDE_NULL_BYTES = 0x01, + + /* Omit the surrounding quote characters if no escaped characters + are encountered. Note that if no other character needs + escaping, then neither does the escape character. */ + QA_ELIDE_OUTER_QUOTES = 0x02, + + /* In the c_quoting_style and c_maybe_quoting_style, split ANSI + trigraph sequences into concatenated strings (for example, + "?""?/" rather than "??/", which could be confused with + "\\"). */ + QA_SPLIT_TRIGRAPHS = 0x04 + }; + +/* For now, --quoting-style=literal is the default, but this may change. */ +# ifndef DEFAULT_QUOTING_STYLE +# define DEFAULT_QUOTING_STYLE literal_quoting_style +# endif + +/* Names of quoting styles and their corresponding values. */ +extern char const *const quoting_style_args[]; +extern enum quoting_style const quoting_style_vals[]; + +struct quoting_options; + +/* The functions listed below set and use a hidden variable + that contains the default quoting style options. */ + +/* Allocate a new set of quoting options, with contents initially identical + to O if O is not null, or to the default if O is null. + It is the caller's responsibility to free the result. */ +struct quoting_options *clone_quoting_options (struct quoting_options *o); + +/* Get the value of O's quoting style. If O is null, use the default. */ +enum quoting_style get_quoting_style (struct quoting_options *o); + +/* In O (or in the default if O is null), + set the value of the quoting style to S. */ +void set_quoting_style (struct quoting_options *o, enum quoting_style s); + +/* In O (or in the default if O is null), + set the value of the quoting options for character C to I. + Return the old value. Currently, the only values defined for I are + 0 (the default) and 1 (which means to quote the character even if + it would not otherwise be quoted). C must never be a digit or a + letter that has special meaning after a backslash (for example, "\t" + for tab). */ +int set_char_quoting (struct quoting_options *o, char c, int i); + +/* In O (or in the default if O is null), + set the value of the quoting options flag to I, which can be a + bitwise combination of enum quoting_flags, or 0 for default + behavior. Return the old value. */ +int set_quoting_flags (struct quoting_options *o, int i); + +/* In O (or in the default if O is null), + set the value of the quoting style to custom_quoting_style, + set the left quote to LEFT_QUOTE, and set the right quote to + RIGHT_QUOTE. Each of LEFT_QUOTE and RIGHT_QUOTE must be + null-terminated and can be the empty string. Because backslashes are + used for escaping, it does not make sense for RIGHT_QUOTE to contain + a backslash. RIGHT_QUOTE must not begin with a digit or a letter + that has special meaning after a backslash (for example, "\t" for + tab). */ +void set_custom_quoting (struct quoting_options *o, + char const *left_quote, + char const *right_quote); + +/* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of + argument ARG (of size ARGSIZE), using O to control quoting. + If O is null, use the default. + Terminate the output with a null character, and return the written + size of the output, not counting the terminating null. + If BUFFERSIZE is too small to store the output string, return the + value that would have been returned had BUFFERSIZE been large enough. + If ARGSIZE is -1, use the string length of the argument for ARGSIZE. + On output, BUFFER might contain embedded null bytes if ARGSIZE was + not -1, the style of O does not use backslash escapes, and the + flags of O do not request elision of null bytes.*/ +size_t quotearg_buffer (char *buffer, size_t buffersize, + char const *arg, size_t argsize, + struct quoting_options const *o); + +/* Like quotearg_buffer, except return the result in a newly allocated + buffer. It is the caller's responsibility to free the result. The + result will not contain embedded null bytes. */ +char *quotearg_alloc (char const *arg, size_t argsize, + struct quoting_options const *o); + +/* Like quotearg_alloc, except that the length of the result, + excluding the terminating null byte, is stored into SIZE if it is + non-NULL. The result might contain embedded null bytes if ARGSIZE + was not -1, SIZE was not NULL, the style of O does not use + backslash escapes, and the flags of O do not request elision of + null bytes.*/ +char *quotearg_alloc_mem (char const *arg, size_t argsize, + size_t *size, struct quoting_options const *o); + +/* Use storage slot N to return a quoted version of the string ARG. + Use the default quoting options. + The returned value points to static storage that can be + reused by the next call to this function with the same value of N. + N must be nonnegative. The output of all functions in the + quotearg_n family are guaranteed to not contain embedded null + bytes.*/ +char *quotearg_n (int n, char const *arg); + +/* Equivalent to quotearg_n (0, ARG). */ +char *quotearg (char const *arg); + +/* Use storage slot N to return a quoted version of the argument ARG + of size ARGSIZE. This is like quotearg_n (N, ARG), except it can + quote null bytes. */ +char *quotearg_n_mem (int n, char const *arg, size_t argsize); + +/* Equivalent to quotearg_n_mem (0, ARG, ARGSIZE). */ +char *quotearg_mem (char const *arg, size_t argsize); + +/* Use style S and storage slot N to return a quoted version of the string ARG. + This is like quotearg_n (N, ARG), except that it uses S with no other + options to specify the quoting method. */ +char *quotearg_n_style (int n, enum quoting_style s, char const *arg); + +/* Use style S and storage slot N to return a quoted version of the + argument ARG of size ARGSIZE. This is like quotearg_n_style + (N, S, ARG), except it can quote null bytes. */ +char *quotearg_n_style_mem (int n, enum quoting_style s, + char const *arg, size_t argsize); + +/* Equivalent to quotearg_n_style (0, S, ARG). */ +char *quotearg_style (enum quoting_style s, char const *arg); + +/* Equivalent to quotearg_n_style_mem (0, S, ARG, ARGSIZE). */ +char *quotearg_style_mem (enum quoting_style s, + char const *arg, size_t argsize); + +/* Like quotearg (ARG), except also quote any instances of CH. + See set_char_quoting for a description of acceptable CH values. */ +char *quotearg_char (char const *arg, char ch); + +/* Like quotearg_char (ARG, CH), except it can quote null bytes. */ +char *quotearg_char_mem (char const *arg, size_t argsize, char ch); + +/* Equivalent to quotearg_char (ARG, ':'). */ +char *quotearg_colon (char const *arg); + +/* Like quotearg_colon (ARG), except it can quote null bytes. */ +char *quotearg_colon_mem (char const *arg, size_t argsize); + +/* Like quotearg_n_style (N, S, ARG) but with S as custom_quoting_style + with left quote as LEFT_QUOTE and right quote as RIGHT_QUOTE. See + set_custom_quoting for a description of acceptable LEFT_QUOTE and + RIGHT_QUOTE values. */ +char *quotearg_n_custom (int n, char const *left_quote, + char const *right_quote, char const *arg); + +/* Like quotearg_n_custom (N, LEFT_QUOTE, RIGHT_QUOTE, ARG) except it + can quote null bytes. */ +char *quotearg_n_custom_mem (int n, char const *left_quote, + char const *right_quote, + char const *arg, size_t argsize); + +/* Equivalent to quotearg_n_custom (0, LEFT_QUOTE, RIGHT_QUOTE, ARG). */ +char *quotearg_custom (char const *left_quote, char const *right_quote, + char const *arg); + +/* Equivalent to quotearg_n_custom_mem (0, LEFT_QUOTE, RIGHT_QUOTE, ARG, + ARGSIZE). */ +char *quotearg_custom_mem (char const *left_quote, + char const *right_quote, + char const *arg, size_t argsize); + +/* Free any dynamically allocated memory. */ +void quotearg_free (void); + +#endif /* !QUOTEARG_H_ */ diff --git a/gettext-tools/gnulib-lib/raise.c b/gettext-tools/gnulib-lib/raise.c new file mode 100644 index 0000000..cf58a7e --- /dev/null +++ b/gettext-tools/gnulib-lib/raise.c @@ -0,0 +1,79 @@ +/* Provide a non-threads replacement for the POSIX raise function. + + Copyright (C) 2002-2003, 2005-2006, 2009-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* written by Jim Meyering and Bruno Haible */ + +#include + +/* Specification. */ +#include + +#if HAVE_RAISE +/* Native Windows platform. */ + +# include + +# include "msvc-inval.h" + +# undef raise + +# if HAVE_MSVC_INVALID_PARAMETER_HANDLER +static int +raise_nothrow (int sig) +{ + int result; + + TRY_MSVC_INVAL + { + result = raise (sig); + } + CATCH_MSVC_INVAL + { + result = -1; + errno = EINVAL; + } + DONE_MSVC_INVAL; + + return result; +} +# else +# define raise_nothrow raise +# endif + +#else +/* An old Unix platform. */ + +# include + +# define rpl_raise raise + +#endif + +int +rpl_raise (int sig) +{ +#if GNULIB_defined_signal_blocking && GNULIB_defined_SIGPIPE + if (sig == SIGPIPE) + return _gl_raise_SIGPIPE (); +#endif + +#if HAVE_RAISE + return raise_nothrow (sig); +#else + return kill (getpid (), sig); +#endif +} diff --git a/gettext-tools/gnulib-lib/rawmemchr.c b/gettext-tools/gnulib-lib/rawmemchr.c new file mode 100644 index 0000000..63bdb5c --- /dev/null +++ b/gettext-tools/gnulib-lib/rawmemchr.c @@ -0,0 +1,136 @@ +/* Searching in a string. + Copyright (C) 2008-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include + +/* Find the first occurrence of C in S. */ +void * +rawmemchr (const void *s, int c_in) +{ + /* On 32-bit hardware, choosing longword to be a 32-bit unsigned + long instead of a 64-bit uintmax_t tends to give better + performance. On 64-bit hardware, unsigned long is generally 64 + bits already. Change this typedef to experiment with + performance. */ + typedef unsigned long int longword; + + const unsigned char *char_ptr; + const longword *longword_ptr; + longword repeated_one; + longword repeated_c; + unsigned char c; + + c = (unsigned char) c_in; + + /* Handle the first few bytes by reading one byte at a time. + Do this until CHAR_PTR is aligned on a longword boundary. */ + for (char_ptr = (const unsigned char *) s; + (size_t) char_ptr % sizeof (longword) != 0; + ++char_ptr) + if (*char_ptr == c) + return (void *) char_ptr; + + longword_ptr = (const longword *) char_ptr; + + /* All these elucidatory comments refer to 4-byte longwords, + but the theory applies equally well to any size longwords. */ + + /* Compute auxiliary longword values: + repeated_one is a value which has a 1 in every byte. + repeated_c has c in every byte. */ + repeated_one = 0x01010101; + repeated_c = c | (c << 8); + repeated_c |= repeated_c << 16; + if (0xffffffffU < (longword) -1) + { + repeated_one |= repeated_one << 31 << 1; + repeated_c |= repeated_c << 31 << 1; + if (8 < sizeof (longword)) + { + size_t i; + + for (i = 64; i < sizeof (longword) * 8; i *= 2) + { + repeated_one |= repeated_one << i; + repeated_c |= repeated_c << i; + } + } + } + + /* Instead of the traditional loop which tests each byte, we will + test a longword at a time. The tricky part is testing if *any of + the four* bytes in the longword in question are equal to NUL or + c. We first use an xor with repeated_c. This reduces the task + to testing whether *any of the four* bytes in longword1 is zero. + + We compute tmp = + ((longword1 - repeated_one) & ~longword1) & (repeated_one << 7). + That is, we perform the following operations: + 1. Subtract repeated_one. + 2. & ~longword1. + 3. & a mask consisting of 0x80 in every byte. + Consider what happens in each byte: + - If a byte of longword1 is zero, step 1 and 2 transform it into 0xff, + and step 3 transforms it into 0x80. A carry can also be propagated + to more significant bytes. + - If a byte of longword1 is nonzero, let its lowest 1 bit be at + position k (0 <= k <= 7); so the lowest k bits are 0. After step 1, + the byte ends in a single bit of value 0 and k bits of value 1. + After step 2, the result is just k bits of value 1: 2^k - 1. After + step 3, the result is 0. And no carry is produced. + So, if longword1 has only non-zero bytes, tmp is zero. + Whereas if longword1 has a zero byte, call j the position of the least + significant zero byte. Then the result has a zero at positions 0, ..., + j-1 and a 0x80 at position j. We cannot predict the result at the more + significant bytes (positions j+1..3), but it does not matter since we + already have a non-zero bit at position 8*j+7. + + The test whether any byte in longword1 is zero is equivalent + to testing whether tmp is nonzero. + + This test can read beyond the end of a string, depending on where + C_IN is encountered. However, this is considered safe since the + initialization phase ensured that the read will be aligned, + therefore, the read will not cross page boundaries and will not + cause a fault. */ + + while (1) + { + longword longword1 = *longword_ptr ^ repeated_c; + + if ((((longword1 - repeated_one) & ~longword1) + & (repeated_one << 7)) != 0) + break; + longword_ptr++; + } + + char_ptr = (const unsigned char *) longword_ptr; + + /* At this point, we know that one of the sizeof (longword) bytes + starting at char_ptr is == c. On little-endian machines, we + could determine the first such byte without any further memory + accesses, just by looking at the tmp result from the last loop + iteration. But this does not work on big-endian machines. + Choose code that works in both cases. */ + + char_ptr = (unsigned char *) longword_ptr; + while (*char_ptr != c) + char_ptr++; + return (void *) char_ptr; +} diff --git a/gettext-tools/gnulib-lib/rawmemchr.valgrind b/gettext-tools/gnulib-lib/rawmemchr.valgrind new file mode 100644 index 0000000..6363923 --- /dev/null +++ b/gettext-tools/gnulib-lib/rawmemchr.valgrind @@ -0,0 +1,12 @@ +# Suppress a valgrind message about use of uninitialized memory in rawmemchr(). +# This use is OK because it provides only a speedup. +{ + rawmemchr-value4 + Memcheck:Value4 + fun:rawmemchr +} +{ + rawmemchr-value8 + Memcheck:Value8 + fun:rawmemchr +} diff --git a/gettext-tools/gnulib-lib/read.c b/gettext-tools/gnulib-lib/read.c new file mode 100644 index 0000000..d125b51 --- /dev/null +++ b/gettext-tools/gnulib-lib/read.c @@ -0,0 +1,85 @@ +/* POSIX compatible read() function. + Copyright (C) 2008-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2011. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include + +#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ + +# include +# include + +# define WIN32_LEAN_AND_MEAN /* avoid including junk */ +# include + +# include "msvc-inval.h" +# include "msvc-nothrow.h" + +# undef read + +# if HAVE_MSVC_INVALID_PARAMETER_HANDLER +static ssize_t +read_nothrow (int fd, void *buf, size_t count) +{ + ssize_t result; + + TRY_MSVC_INVAL + { + result = read (fd, buf, count); + } + CATCH_MSVC_INVAL + { + result = -1; + errno = EBADF; + } + DONE_MSVC_INVAL; + + return result; +} +# else +# define read_nothrow read +# endif + +ssize_t +rpl_read (int fd, void *buf, size_t count) +{ + ssize_t ret = read_nothrow (fd, buf, count); + +# if GNULIB_NONBLOCKING + if (ret < 0 + && GetLastError () == ERROR_NO_DATA) + { + HANDLE h = (HANDLE) _get_osfhandle (fd); + if (GetFileType (h) == FILE_TYPE_PIPE) + { + /* h is a pipe or socket. */ + DWORD state; + if (GetNamedPipeHandleState (h, &state, NULL, NULL, NULL, NULL, 0) + && (state & PIPE_NOWAIT) != 0) + /* h is a pipe in non-blocking mode. + Change errno from EINVAL to EAGAIN. */ + errno = EAGAIN; + } + } +# endif + + return ret; +} + +#endif diff --git a/gettext-tools/gnulib-lib/readdir.c b/gettext-tools/gnulib-lib/readdir.c new file mode 100644 index 0000000..b74aebe --- /dev/null +++ b/gettext-tools/gnulib-lib/readdir.c @@ -0,0 +1,98 @@ +/* Read the next entry of a directory. + Copyright (C) 2011-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include + +#include +#include + +#include "dirent-private.h" + +struct dirent * +readdir (DIR *dirp) +{ + char type; + struct dirent *result; + + /* There is no need to add code to produce entries for "." and "..". + According to the POSIX:2008 section "4.12 Pathname Resolution" + + "." and ".." are syntactic entities. + POSIX also says: + "If entries for dot or dot-dot exist, one entry shall be returned + for dot and one entry shall be returned for dot-dot; otherwise, + they shall not be returned." */ + + switch (dirp->status) + { + case -2: + /* End of directory already reached. */ + return NULL; + case -1: + break; + case 0: + if (!FindNextFile (dirp->current, &dirp->entry)) + { + switch (GetLastError ()) + { + case ERROR_NO_MORE_FILES: + dirp->status = -2; + return NULL; + default: + errno = EIO; + return NULL; + } + } + break; + default: + errno = dirp->status; + return NULL; + } + + dirp->status = 0; + + if (dirp->entry.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + type = DT_DIR; + else if (dirp->entry.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) + type = DT_LNK; + else if ((dirp->entry.dwFileAttributes + & ~(FILE_ATTRIBUTE_READONLY + | FILE_ATTRIBUTE_HIDDEN + | FILE_ATTRIBUTE_SYSTEM + | FILE_ATTRIBUTE_ARCHIVE + | FILE_ATTRIBUTE_NORMAL + | FILE_ATTRIBUTE_TEMPORARY + | FILE_ATTRIBUTE_SPARSE_FILE + | FILE_ATTRIBUTE_COMPRESSED + | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED + | FILE_ATTRIBUTE_ENCRYPTED)) == 0) + /* Devices like COM1, LPT1, NUL would also have the attributes 0x20 but + they cannot occur here. */ + type = DT_REG; + else + type = DT_UNKNOWN; + + /* Reuse the memory of dirp->entry for the result. */ + result = + (struct dirent *) + ((char *) dirp->entry.cFileName - offsetof (struct dirent, d_name[0])); + result->d_type = type; + + return result; +} diff --git a/gettext-tools/gnulib-lib/readlink.c b/gettext-tools/gnulib-lib/readlink.c new file mode 100644 index 0000000..4c49639 --- /dev/null +++ b/gettext-tools/gnulib-lib/readlink.c @@ -0,0 +1,74 @@ +/* Stub for readlink(). + Copyright (C) 2003-2007, 2009-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include + +#include +#include +#include + +#if !HAVE_READLINK + +/* readlink() substitute for systems that don't have a readlink() function, + such as DJGPP 2.03 and mingw32. */ + +ssize_t +readlink (const char *name, char *buf _GL_UNUSED, + size_t bufsize _GL_UNUSED) +{ + struct stat statbuf; + + /* In general we should use lstat() here, not stat(). But on platforms + without symbolic links, lstat() - if it exists - would be equivalent to + stat(), therefore we can use stat(). This saves us a configure check. */ + if (stat (name, &statbuf) >= 0) + errno = EINVAL; + return -1; +} + +#else /* HAVE_READLINK */ + +# undef readlink + +/* readlink() wrapper that uses correct types, for systems like cygwin + 1.5.x where readlink returns int, and which rejects trailing slash, + for Solaris 9. */ + +ssize_t +rpl_readlink (const char *name, char *buf, size_t bufsize) +{ +# if READLINK_TRAILING_SLASH_BUG + size_t len = strlen (name); + if (len && name[len - 1] == '/') + { + /* Even if name without the slash is a symlink to a directory, + both lstat() and stat() must resolve the trailing slash to + the directory rather than the symlink. We can therefore + safely use stat() to distinguish between EINVAL and + ENOTDIR/ENOENT, avoiding extra overhead of rpl_lstat(). */ + struct stat st; + if (stat (name, &st) == 0) + errno = EINVAL; + return -1; + } +# endif /* READLINK_TRAILING_SLASH_BUG */ + return readlink (name, buf, bufsize); +} + +#endif /* HAVE_READLINK */ diff --git a/gettext-tools/gnulib-lib/realloc.c b/gettext-tools/gnulib-lib/realloc.c new file mode 100644 index 0000000..8dfcfbe --- /dev/null +++ b/gettext-tools/gnulib-lib/realloc.c @@ -0,0 +1,79 @@ +/* realloc() function that is glibc compatible. + + Copyright (C) 1997, 2003-2004, 2006-2007, 2009-2014 Free Software + Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* written by Jim Meyering and Bruno Haible */ + +#define _GL_USE_STDLIB_ALLOC 1 +#include + +/* Only the AC_FUNC_REALLOC macro defines 'realloc' already in config.h. */ +#ifdef realloc +# define NEED_REALLOC_GNU 1 +/* Whereas the gnulib module 'realloc-gnu' defines HAVE_REALLOC_GNU. */ +#elif GNULIB_REALLOC_GNU && !HAVE_REALLOC_GNU +# define NEED_REALLOC_GNU 1 +#endif + +/* Infer the properties of the system's malloc function. + The gnulib module 'malloc-gnu' defines HAVE_MALLOC_GNU. */ +#if GNULIB_MALLOC_GNU && HAVE_MALLOC_GNU +# define SYSTEM_MALLOC_GLIBC_COMPATIBLE 1 +#endif + +#include + +#include + +/* Change the size of an allocated block of memory P to N bytes, + with error checking. If N is zero, change it to 1. If P is NULL, + use malloc. */ + +void * +rpl_realloc (void *p, size_t n) +{ + void *result; + +#if NEED_REALLOC_GNU + if (n == 0) + { + n = 1; + + /* In theory realloc might fail, so don't rely on it to free. */ + free (p); + p = NULL; + } +#endif + + if (p == NULL) + { +#if GNULIB_REALLOC_GNU && !NEED_REALLOC_GNU && !SYSTEM_MALLOC_GLIBC_COMPATIBLE + if (n == 0) + n = 1; +#endif + result = malloc (n); + } + else + result = realloc (p, n); + +#if !HAVE_REALLOC_POSIX + if (result == NULL) + errno = ENOMEM; +#endif + + return result; +} diff --git a/gettext-tools/gnulib-lib/ref-add.sin b/gettext-tools/gnulib-lib/ref-add.sin new file mode 100644 index 0000000..0e14022 --- /dev/null +++ b/gettext-tools/gnulib-lib/ref-add.sin @@ -0,0 +1,29 @@ +# Add this package to a list of references stored in a text file. +# +# Copyright (C) 2000, 2009-2014 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, see . +# +# Written by Bruno Haible . +# +/^# Packages using this file: / { + s/# Packages using this file:// + ta + :a + s/ @PACKAGE@ / @PACKAGE@ / + tb + s/ $/ @PACKAGE@ / + :b + s/^/# Packages using this file:/ +} diff --git a/gettext-tools/gnulib-lib/ref-del.sin b/gettext-tools/gnulib-lib/ref-del.sin new file mode 100644 index 0000000..2dbcf7b --- /dev/null +++ b/gettext-tools/gnulib-lib/ref-del.sin @@ -0,0 +1,24 @@ +# Remove this package from a list of references stored in a text file. +# +# Copyright (C) 2000, 2009-2014 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, see . +# +# Written by Bruno Haible . +# +/^# Packages using this file: / { + s/# Packages using this file:// + s/ @PACKAGE@ / / + s/^/# Packages using this file:/ +} diff --git a/gettext-tools/gnulib-lib/relocatable.c b/gettext-tools/gnulib-lib/relocatable.c new file mode 100644 index 0000000..0e20897 --- /dev/null +++ b/gettext-tools/gnulib-lib/relocatable.c @@ -0,0 +1,496 @@ +/* Provide relocatable packages. + Copyright (C) 2003-2006, 2008-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2003. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + + +/* Tell glibc's to provide a prototype for getline(). + This must come before because may include + , and once has been included, it's too late. */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +#endif + +#define _GL_USE_STDLIB_ALLOC 1 +#include + +/* Specification. */ +#include "relocatable.h" + +#if ENABLE_RELOCATABLE + +#include +#include +#include +#include + +#ifdef NO_XMALLOC +# define xmalloc malloc +#else +# include "xalloc.h" +#endif + +#if (defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__ +# define WIN32_LEAN_AND_MEAN +# include +#endif + +#if DEPENDS_ON_LIBCHARSET +# include +#endif +#if DEPENDS_ON_LIBICONV && HAVE_ICONV +# include +#endif +#if DEPENDS_ON_LIBINTL && ENABLE_NLS +# include +#endif + +/* Faked cheap 'bool'. */ +#undef bool +#undef false +#undef true +#define bool int +#define false 0 +#define true 1 + +/* Pathname support. + ISSLASH(C) tests whether C is a directory separator character. + IS_PATH_WITH_DIR(P) tests whether P contains a directory specification. + */ +#if ((defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__) || defined __EMX__ || defined __DJGPP__ + /* Native Windows, OS/2, DOS */ +# define ISSLASH(C) ((C) == '/' || (C) == '\\') +# define HAS_DEVICE(P) \ + ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) \ + && (P)[1] == ':') +# define IS_PATH_WITH_DIR(P) \ + (strchr (P, '/') != NULL || strchr (P, '\\') != NULL || HAS_DEVICE (P)) +# define FILE_SYSTEM_PREFIX_LEN(P) (HAS_DEVICE (P) ? 2 : 0) +#else + /* Unix */ +# define ISSLASH(C) ((C) == '/') +# define IS_PATH_WITH_DIR(P) (strchr (P, '/') != NULL) +# define FILE_SYSTEM_PREFIX_LEN(P) 0 +#endif + +/* Whether to enable the more costly support for relocatable libraries. + It allows libraries to be have been installed with a different original + prefix than the program. But it is quite costly, especially on Cygwin + platforms, see below. Therefore we enable it by default only on native + Windows platforms. */ +#ifndef ENABLE_COSTLY_RELOCATABLE +# if (defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__ +# define ENABLE_COSTLY_RELOCATABLE 1 +# else +# define ENABLE_COSTLY_RELOCATABLE 0 +# endif +#endif + +/* Original installation prefix. */ +static char *orig_prefix; +static size_t orig_prefix_len; +/* Current installation prefix. */ +static char *curr_prefix; +static size_t curr_prefix_len; +/* These prefixes do not end in a slash. Anything that will be concatenated + to them must start with a slash. */ + +/* Sets the original and the current installation prefix of this module. + Relocation simply replaces a pathname starting with the original prefix + by the corresponding pathname with the current prefix instead. Both + prefixes should be directory names without trailing slash (i.e. use "" + instead of "/"). */ +static void +set_this_relocation_prefix (const char *orig_prefix_arg, + const char *curr_prefix_arg) +{ + if (orig_prefix_arg != NULL && curr_prefix_arg != NULL + /* Optimization: if orig_prefix and curr_prefix are equal, the + relocation is a nop. */ + && strcmp (orig_prefix_arg, curr_prefix_arg) != 0) + { + /* Duplicate the argument strings. */ + char *memory; + + orig_prefix_len = strlen (orig_prefix_arg); + curr_prefix_len = strlen (curr_prefix_arg); + memory = (char *) xmalloc (orig_prefix_len + 1 + curr_prefix_len + 1); +#ifdef NO_XMALLOC + if (memory != NULL) +#endif + { + memcpy (memory, orig_prefix_arg, orig_prefix_len + 1); + orig_prefix = memory; + memory += orig_prefix_len + 1; + memcpy (memory, curr_prefix_arg, curr_prefix_len + 1); + curr_prefix = memory; + return; + } + } + orig_prefix = NULL; + curr_prefix = NULL; + /* Don't worry about wasted memory here - this function is usually only + called once. */ +} + +/* Sets the original and the current installation prefix of the package. + Relocation simply replaces a pathname starting with the original prefix + by the corresponding pathname with the current prefix instead. Both + prefixes should be directory names without trailing slash (i.e. use "" + instead of "/"). */ +void +set_relocation_prefix (const char *orig_prefix_arg, const char *curr_prefix_arg) +{ + set_this_relocation_prefix (orig_prefix_arg, curr_prefix_arg); + + /* Now notify all dependent libraries. */ +#if DEPENDS_ON_LIBCHARSET + libcharset_set_relocation_prefix (orig_prefix_arg, curr_prefix_arg); +#endif +#if DEPENDS_ON_LIBICONV && HAVE_ICONV && _LIBICONV_VERSION >= 0x0109 + libiconv_set_relocation_prefix (orig_prefix_arg, curr_prefix_arg); +#endif +#if DEPENDS_ON_LIBINTL && ENABLE_NLS && defined libintl_set_relocation_prefix + libintl_set_relocation_prefix (orig_prefix_arg, curr_prefix_arg); +#endif +} + +#if !defined IN_LIBRARY || (defined PIC && defined INSTALLDIR && ENABLE_COSTLY_RELOCATABLE) + +/* Convenience function: + Computes the current installation prefix, based on the original + installation prefix, the original installation directory of a particular + file, and the current pathname of this file. + Returns it, freshly allocated. Returns NULL upon failure. */ +#ifdef IN_LIBRARY +#define compute_curr_prefix local_compute_curr_prefix +static +#endif +char * +compute_curr_prefix (const char *orig_installprefix, + const char *orig_installdir, + const char *curr_pathname) +{ + char *curr_installdir; + const char *rel_installdir; + + if (curr_pathname == NULL) + return NULL; + + /* Determine the relative installation directory, relative to the prefix. + This is simply the difference between orig_installprefix and + orig_installdir. */ + if (strncmp (orig_installprefix, orig_installdir, strlen (orig_installprefix)) + != 0) + /* Shouldn't happen - nothing should be installed outside $(prefix). */ + return NULL; + rel_installdir = orig_installdir + strlen (orig_installprefix); + + /* Determine the current installation directory. */ + { + const char *p_base = curr_pathname + FILE_SYSTEM_PREFIX_LEN (curr_pathname); + const char *p = curr_pathname + strlen (curr_pathname); + char *q; + + while (p > p_base) + { + p--; + if (ISSLASH (*p)) + break; + } + + q = (char *) xmalloc (p - curr_pathname + 1); +#ifdef NO_XMALLOC + if (q == NULL) + return NULL; +#endif + memcpy (q, curr_pathname, p - curr_pathname); + q[p - curr_pathname] = '\0'; + curr_installdir = q; + } + + /* Compute the current installation prefix by removing the trailing + rel_installdir from it. */ + { + const char *rp = rel_installdir + strlen (rel_installdir); + const char *cp = curr_installdir + strlen (curr_installdir); + const char *cp_base = + curr_installdir + FILE_SYSTEM_PREFIX_LEN (curr_installdir); + + while (rp > rel_installdir && cp > cp_base) + { + bool same = false; + const char *rpi = rp; + const char *cpi = cp; + + while (rpi > rel_installdir && cpi > cp_base) + { + rpi--; + cpi--; + if (ISSLASH (*rpi) || ISSLASH (*cpi)) + { + if (ISSLASH (*rpi) && ISSLASH (*cpi)) + same = true; + break; + } + /* Do case-insensitive comparison if the file system is always or + often case-insensitive. It's better to accept the comparison + if the difference is only in case, rather than to fail. */ +#if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__ + /* Native Windows, Cygwin, OS/2, DOS - case insignificant file system */ + if ((*rpi >= 'a' && *rpi <= 'z' ? *rpi - 'a' + 'A' : *rpi) + != (*cpi >= 'a' && *cpi <= 'z' ? *cpi - 'a' + 'A' : *cpi)) + break; +#else + if (*rpi != *cpi) + break; +#endif + } + if (!same) + break; + /* The last pathname component was the same. opi and cpi now point + to the slash before it. */ + rp = rpi; + cp = cpi; + } + + if (rp > rel_installdir) + { + /* Unexpected: The curr_installdir does not end with rel_installdir. */ + free (curr_installdir); + return NULL; + } + + { + size_t curr_prefix_len = cp - curr_installdir; + char *curr_prefix; + + curr_prefix = (char *) xmalloc (curr_prefix_len + 1); +#ifdef NO_XMALLOC + if (curr_prefix == NULL) + { + free (curr_installdir); + return NULL; + } +#endif + memcpy (curr_prefix, curr_installdir, curr_prefix_len); + curr_prefix[curr_prefix_len] = '\0'; + + free (curr_installdir); + + return curr_prefix; + } + } +} + +#endif /* !IN_LIBRARY || PIC */ + +#if defined PIC && defined INSTALLDIR && ENABLE_COSTLY_RELOCATABLE + +/* Full pathname of shared library, or NULL. */ +static char *shared_library_fullname; + +#if (defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__ +/* Native Windows only. + On Cygwin, it is better to use the Cygwin provided /proc interface, than + to use native Windows API and cygwin_conv_to_posix_path, because it + supports longer file names + (see ). */ + +/* Determine the full pathname of the shared library when it is loaded. */ + +BOOL WINAPI +DllMain (HINSTANCE module_handle, DWORD event, LPVOID reserved) +{ + (void) reserved; + + if (event == DLL_PROCESS_ATTACH) + { + /* The DLL is being loaded into an application's address range. */ + static char location[MAX_PATH]; + + if (!GetModuleFileName (module_handle, location, sizeof (location))) + /* Shouldn't happen. */ + return FALSE; + + if (!IS_PATH_WITH_DIR (location)) + /* Shouldn't happen. */ + return FALSE; + + shared_library_fullname = strdup (location); + } + + return TRUE; +} + +#else /* Unix */ + +static void +find_shared_library_fullname () +{ +#if (defined __linux__ && (__GLIBC__ >= 2 || defined __UCLIBC__)) || defined __CYGWIN__ + /* Linux has /proc/self/maps. glibc 2 and uClibc have the getline() + function. + Cygwin >= 1.5 has /proc/self/maps and the getline() function too. + But it is costly: ca. 0.3 ms on Linux, 3 ms on Cygwin 1.5, and 5 ms on + Cygwin 1.7. */ + FILE *fp; + + /* Open the current process' maps file. It describes one VMA per line. */ + fp = fopen ("/proc/self/maps", "r"); + if (fp) + { + unsigned long address = (unsigned long) &find_shared_library_fullname; + for (;;) + { + unsigned long start, end; + int c; + + if (fscanf (fp, "%lx-%lx", &start, &end) != 2) + break; + if (address >= start && address <= end - 1) + { + /* Found it. Now see if this line contains a filename. */ + while (c = getc (fp), c != EOF && c != '\n' && c != '/') + continue; + if (c == '/') + { + size_t size; + int len; + + ungetc (c, fp); + shared_library_fullname = NULL; size = 0; + len = getline (&shared_library_fullname, &size, fp); + if (len >= 0) + { + /* Success: filled shared_library_fullname. */ + if (len > 0 && shared_library_fullname[len - 1] == '\n') + shared_library_fullname[len - 1] = '\0'; + } + } + break; + } + while (c = getc (fp), c != EOF && c != '\n') + continue; + } + fclose (fp); + } +#endif +} + +#endif /* Native Windows / Unix */ + +/* Return the full pathname of the current shared library. + Return NULL if unknown. + Guaranteed to work only on Linux, Cygwin, and native Windows. */ +static char * +get_shared_library_fullname () +{ +#if !((defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__) + static bool tried_find_shared_library_fullname; + if (!tried_find_shared_library_fullname) + { + find_shared_library_fullname (); + tried_find_shared_library_fullname = true; + } +#endif + return shared_library_fullname; +} + +#endif /* PIC */ + +/* Returns the pathname, relocated according to the current installation + directory. + The returned string is either PATHNAME unmodified or a freshly allocated + string that you can free with free() after casting it to 'char *'. */ +const char * +relocate (const char *pathname) +{ +#if defined PIC && defined INSTALLDIR && ENABLE_COSTLY_RELOCATABLE + static int initialized; + + /* Initialization code for a shared library. */ + if (!initialized) + { + /* At this point, orig_prefix and curr_prefix likely have already been + set through the main program's set_program_name_and_installdir + function. This is sufficient in the case that the library has + initially been installed in the same orig_prefix. But we can do + better, to also cover the cases that 1. it has been installed + in a different prefix before being moved to orig_prefix and (later) + to curr_prefix, 2. unlike the program, it has not moved away from + orig_prefix. */ + const char *orig_installprefix = INSTALLPREFIX; + const char *orig_installdir = INSTALLDIR; + char *curr_prefix_better; + + curr_prefix_better = + compute_curr_prefix (orig_installprefix, orig_installdir, + get_shared_library_fullname ()); + + set_relocation_prefix (orig_installprefix, + curr_prefix_better != NULL + ? curr_prefix_better + : curr_prefix); + + if (curr_prefix_better != NULL) + free (curr_prefix_better); + + initialized = 1; + } +#endif + + /* Note: It is not necessary to perform case insensitive comparison here, + even for DOS-like file systems, because the pathname argument was + typically created from the same Makefile variable as orig_prefix came + from. */ + if (orig_prefix != NULL && curr_prefix != NULL + && strncmp (pathname, orig_prefix, orig_prefix_len) == 0) + { + if (pathname[orig_prefix_len] == '\0') + { + /* pathname equals orig_prefix. */ + char *result = (char *) xmalloc (strlen (curr_prefix) + 1); + +#ifdef NO_XMALLOC + if (result != NULL) +#endif + { + strcpy (result, curr_prefix); + return result; + } + } + else if (ISSLASH (pathname[orig_prefix_len])) + { + /* pathname starts with orig_prefix. */ + const char *pathname_tail = &pathname[orig_prefix_len]; + char *result = + (char *) xmalloc (curr_prefix_len + strlen (pathname_tail) + 1); + +#ifdef NO_XMALLOC + if (result != NULL) +#endif + { + memcpy (result, curr_prefix, curr_prefix_len); + strcpy (result + curr_prefix_len, pathname_tail); + return result; + } + } + } + /* Nothing to relocate. */ + return pathname; +} + +#endif diff --git a/gettext-tools/gnulib-lib/relocatable.h b/gettext-tools/gnulib-lib/relocatable.h new file mode 100644 index 0000000..2b0fab7 --- /dev/null +++ b/gettext-tools/gnulib-lib/relocatable.h @@ -0,0 +1,81 @@ +/* Provide relocatable packages. + Copyright (C) 2003, 2005, 2008-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2003. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _RELOCATABLE_H +#define _RELOCATABLE_H + +#ifdef __cplusplus +extern "C" { +#endif + + +/* This can be enabled through the configure --enable-relocatable option. */ +#if ENABLE_RELOCATABLE + +/* When building a DLL, we must export some functions. Note that because + this is a private .h file, we don't need to use __declspec(dllimport) + in any case. */ +#if HAVE_VISIBILITY && BUILDING_DLL +# define RELOCATABLE_DLL_EXPORTED __attribute__((__visibility__("default"))) +#elif defined _MSC_VER && BUILDING_DLL +# define RELOCATABLE_DLL_EXPORTED __declspec(dllexport) +#else +# define RELOCATABLE_DLL_EXPORTED +#endif + +/* Sets the original and the current installation prefix of the package. + Relocation simply replaces a pathname starting with the original prefix + by the corresponding pathname with the current prefix instead. Both + prefixes should be directory names without trailing slash (i.e. use "" + instead of "/"). */ +extern RELOCATABLE_DLL_EXPORTED void + set_relocation_prefix (const char *orig_prefix, + const char *curr_prefix); + +/* Returns the pathname, relocated according to the current installation + directory. + The returned string is either PATHNAME unmodified or a freshly allocated + string that you can free with free() after casting it to 'char *'. */ +extern const char * relocate (const char *pathname); + +/* Memory management: relocate() potentially allocates memory, because it has + to construct a fresh pathname. If this is a problem because your program + calls relocate() frequently, think about caching the result. Or free the + return value if it was different from the argument pathname. */ + +/* Convenience function: + Computes the current installation prefix, based on the original + installation prefix, the original installation directory of a particular + file, and the current pathname of this file. + Returns it, freshly allocated. Returns NULL upon failure. */ +extern char * compute_curr_prefix (const char *orig_installprefix, + const char *orig_installdir, + const char *curr_pathname); + +#else + +/* By default, we use the hardwired pathnames. */ +#define relocate(pathname) (pathname) + +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* _RELOCATABLE_H */ diff --git a/gettext-tools/gnulib-lib/relocwrapper.c b/gettext-tools/gnulib-lib/relocwrapper.c new file mode 100644 index 0000000..4f330de --- /dev/null +++ b/gettext-tools/gnulib-lib/relocwrapper.c @@ -0,0 +1,198 @@ +/* Relocating wrapper program. + Copyright (C) 2003, 2005-2007, 2009-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2003. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Dependencies: + relocwrapper + -> progname + -> progreloc + -> areadlink + -> careadlinkat + -> allocator + -> readlink + -> canonicalize-lgpl + -> malloca + -> readlink + -> relocatable + -> setenv + -> malloca + -> c-ctype + + Macros that need to be set while compiling this file: + - ENABLE_RELOCATABLE 1 + - INSTALLPREFIX the base installation directory + - INSTALLDIR the directory into which this program is installed + - LIBPATHVAR the platform dependent runtime library path variable + - LIBDIRS a comma-terminated list of strings representing the list of + directories that contain the libraries at installation time + + We don't want to internationalize this wrapper because then it would + depend on libintl and therefore need relocation itself. So use only + libc functions, no gettext(), no error(), no xmalloc(), no xsetenv(). + */ + +#define _GL_USE_STDLIB_ALLOC 1 +#include + +#include +#include +#include +#include +#include + +#include "progname.h" +#include "relocatable.h" +#include "c-ctype.h" +#include "verify.h" + +/* Use the system functions, not the gnulib overrides in this file. */ +#undef fprintf + +/* Return a copy of the filename, with an extra ".bin" at the end. + More generally, it replaces "${EXEEXT}" at the end with ".bin${EXEEXT}". */ +static char * +add_dotbin (const char *filename) +{ + size_t filename_len = strlen (filename); + char *result = (char *) malloc (filename_len + 4 + 1); + + if (result != NULL) + { + if (sizeof (EXEEXT) > sizeof ("")) + { + /* EXEEXT handling. */ + const size_t exeext_len = sizeof (EXEEXT) - sizeof (""); + static const char exeext[] = EXEEXT; + if (filename_len > exeext_len) + { + /* Compare using an inlined copy of c_strncasecmp(), because + the filenames may have undergone a case conversion since + they were packaged. In other words, EXEEXT may be ".exe" + on one system and ".EXE" on another. */ + const char *s1 = filename + filename_len - exeext_len; + const char *s2 = exeext; + for (; *s1 != '\0'; s1++, s2++) + { + unsigned char c1 = *s1; + unsigned char c2 = *s2; + if (c_tolower (c1) != c_tolower (c2)) + goto simple_append; + } + /* Insert ".bin" before EXEEXT or its equivalent. */ + memcpy (result, filename, filename_len - exeext_len); + memcpy (result + filename_len - exeext_len, ".bin", 4); + memcpy (result + filename_len - exeext_len + 4, + filename + filename_len - exeext_len, + exeext_len + 1); + return result; + } + } + simple_append: + /* Simply append ".bin". */ + memcpy (result, filename, filename_len); + memcpy (result + filename_len, ".bin", 4 + 1); + return result; + } + else + { + fprintf (stderr, "%s: %s\n", program_name, "memory exhausted"); + exit (1); + } +} + +/* List of directories that contain the libraries. */ +static const char *libdirs[] = { LIBDIRS NULL }; +/* Verify that at least one directory is given. */ +verify (sizeof (libdirs) / sizeof (libdirs[0]) > 1); + +/* Relocate the list of directories that contain the libraries. */ +static void +relocate_libdirs () +{ + size_t i; + + for (i = 0; i < sizeof (libdirs) / sizeof (libdirs[0]) - 1; i++) + libdirs[i] = relocate (libdirs[i]); +} + +/* Activate the list of directories in the LIBPATHVAR. */ +static void +activate_libdirs () +{ + const char *old_value; + size_t total; + size_t i; + char *value; + char *p; + + old_value = getenv (LIBPATHVAR); + if (old_value == NULL) + old_value = ""; + + total = 0; + for (i = 0; i < sizeof (libdirs) / sizeof (libdirs[0]) - 1; i++) + total += strlen (libdirs[i]) + 1; + total += strlen (old_value) + 1; + + value = (char *) malloc (total); + if (value == NULL) + { + fprintf (stderr, "%s: %s\n", program_name, "memory exhausted"); + exit (1); + } + p = value; + for (i = 0; i < sizeof (libdirs) / sizeof (libdirs[0]) - 1; i++) + { + size_t len = strlen (libdirs[i]); + memcpy (p, libdirs[i], len); + p += len; + *p++ = ':'; + } + if (old_value[0] != '\0') + strcpy (p, old_value); + else + p[-1] = '\0'; + + if (setenv (LIBPATHVAR, value, 1) < 0) + { + fprintf (stderr, "%s: %s\n", program_name, "memory exhausted"); + exit (1); + } +} + +int +main (int argc, char *argv[]) +{ + char *full_program_name; + + /* Set the program name and perform preparations for + get_full_program_name() and relocate(). */ + set_program_name_and_installdir (argv[0], INSTALLPREFIX, INSTALLDIR); + + /* Get the full program path. (Important if accessed through a symlink.) */ + full_program_name = get_full_program_name (); + if (full_program_name == NULL) + full_program_name = argv[0]; + + /* Invoke the real program, with suffix ".bin". */ + argv[0] = add_dotbin (full_program_name); + relocate_libdirs (); + activate_libdirs (); + execv (argv[0], argv); + fprintf (stderr, "%s: could not execute %s: %s\n", + program_name, argv[0], strerror (errno)); + exit (127); +} diff --git a/gettext-tools/gnulib-lib/rmdir.c b/gettext-tools/gnulib-lib/rmdir.c new file mode 100644 index 0000000..ec7a586 --- /dev/null +++ b/gettext-tools/gnulib-lib/rmdir.c @@ -0,0 +1,53 @@ +/* Work around rmdir bugs. + + Copyright (C) 1988, 1990, 1999, 2003-2006, 2009-2014 Free Software + Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +#include + +#include +#include + +#include "dosname.h" + +#undef rmdir + +/* Remove directory DIR. + Return 0 if successful, -1 if not. */ + +int +rpl_rmdir (char const *dir) +{ + /* Work around cygwin 1.5.x bug where rmdir("dir/./") succeeds. */ + size_t len = strlen (dir); + int result; + while (len && ISSLASH (dir[len - 1])) + len--; + if (len && dir[len - 1] == '.' && (1 == len || ISSLASH (dir[len - 2]))) + { + errno = EINVAL; + return -1; + } + result = rmdir (dir); + /* Work around mingw bug, where rmdir("file/") fails with EINVAL + instead of ENOTDIR. We've already filtered out trailing ., the + only reason allowed by POSIX for EINVAL. */ + if (result == -1 && errno == EINVAL) + errno = ENOTDIR; + return result; +} diff --git a/gettext-tools/gnulib-lib/safe-read.c b/gettext-tools/gnulib-lib/safe-read.c new file mode 100644 index 0000000..c9b8828 --- /dev/null +++ b/gettext-tools/gnulib-lib/safe-read.c @@ -0,0 +1,77 @@ +/* An interface to read and write that retries after interrupts. + + Copyright (C) 1993-1994, 1998, 2002-2006, 2009-2014 Free Software + Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#ifdef SAFE_WRITE +# include "safe-write.h" +#else +# include "safe-read.h" +#endif + +/* Get ssize_t. */ +#include +#include + +#include + +#ifdef EINTR +# define IS_EINTR(x) ((x) == EINTR) +#else +# define IS_EINTR(x) 0 +#endif + +#include + +#ifdef SAFE_WRITE +# define safe_rw safe_write +# define rw write +#else +# define safe_rw safe_read +# define rw read +# undef const +# define const /* empty */ +#endif + +/* Read(write) up to COUNT bytes at BUF from(to) descriptor FD, retrying if + interrupted. Return the actual number of bytes read(written), zero for EOF, + or SAFE_READ_ERROR(SAFE_WRITE_ERROR) upon error. */ +size_t +safe_rw (int fd, void const *buf, size_t count) +{ + /* Work around a bug in Tru64 5.1. Attempting to read more than + INT_MAX bytes fails with errno == EINVAL. See + . + When decreasing COUNT, keep it block-aligned. */ + enum { BUGGY_READ_MAXIMUM = INT_MAX & ~8191 }; + + for (;;) + { + ssize_t result = rw (fd, buf, count); + + if (0 <= result) + return result; + else if (IS_EINTR (errno)) + continue; + else if (errno == EINVAL && BUGGY_READ_MAXIMUM < count) + count = BUGGY_READ_MAXIMUM; + else + return result; + } +} diff --git a/gettext-tools/gnulib-lib/safe-read.h b/gettext-tools/gnulib-lib/safe-read.h new file mode 100644 index 0000000..aba8bdb --- /dev/null +++ b/gettext-tools/gnulib-lib/safe-read.h @@ -0,0 +1,47 @@ +/* An interface to read() that retries after interrupts. + Copyright (C) 2002, 2006, 2009-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Some system calls may be interrupted and fail with errno = EINTR in the + following situations: + - The process is stopped and restarted (signal SIGSTOP and SIGCONT, user + types Ctrl-Z) on some platforms: Mac OS X. + - The process receives a signal for which a signal handler was installed + with sigaction() with an sa_flags field that does not contain + SA_RESTART. + - The process receives a signal for which a signal handler was installed + with signal() and for which no call to siginterrupt(sig,0) was done, + on some platforms: AIX, HP-UX, IRIX, OSF/1, Solaris. + + This module provides a wrapper around read() that handles EINTR. */ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +#define SAFE_READ_ERROR ((size_t) -1) + +/* Read up to COUNT bytes at BUF from descriptor FD, retrying if interrupted. + Return the actual number of bytes read, zero for EOF, or SAFE_READ_ERROR + upon error. */ +extern size_t safe_read (int fd, void *buf, size_t count); + + +#ifdef __cplusplus +} +#endif diff --git a/gettext-tools/gnulib-lib/safe-write.c b/gettext-tools/gnulib-lib/safe-write.c new file mode 100644 index 0000000..bf72dd4 --- /dev/null +++ b/gettext-tools/gnulib-lib/safe-write.c @@ -0,0 +1,18 @@ +/* An interface to write that retries after interrupts. + Copyright (C) 2002, 2009-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#define SAFE_WRITE +#include "safe-read.c" diff --git a/gettext-tools/gnulib-lib/safe-write.h b/gettext-tools/gnulib-lib/safe-write.h new file mode 100644 index 0000000..ae18657 --- /dev/null +++ b/gettext-tools/gnulib-lib/safe-write.h @@ -0,0 +1,37 @@ +/* An interface to write() that retries after interrupts. + Copyright (C) 2002, 2009-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Some system calls may be interrupted and fail with errno = EINTR in the + following situations: + - The process is stopped and restarted (signal SIGSTOP and SIGCONT, user + types Ctrl-Z) on some platforms: Mac OS X. + - The process receives a signal for which a signal handler was installed + with sigaction() with an sa_flags field that does not contain + SA_RESTART. + - The process receives a signal for which a signal handler was installed + with signal() and for which no call to siginterrupt(sig,0) was done, + on some platforms: AIX, HP-UX, IRIX, OSF/1, Solaris. + + This module provides a wrapper around write() that handles EINTR. */ + +#include + +#define SAFE_WRITE_ERROR ((size_t) -1) + +/* Write up to COUNT bytes at BUF to descriptor FD, retrying if interrupted. + Return the actual number of bytes written, zero for EOF, or SAFE_WRITE_ERROR + upon error. */ +extern size_t safe_write (int fd, const void *buf, size_t count); diff --git a/gettext-tools/gnulib-lib/sched.in.h b/gettext-tools/gnulib-lib/sched.in.h new file mode 100644 index 0000000..edebf81 --- /dev/null +++ b/gettext-tools/gnulib-lib/sched.in.h @@ -0,0 +1,57 @@ +/* Replacement for platforms that lack it. + Copyright (C) 2008-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _@GUARD_PREFIX@_SCHED_H + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +/* The include_next requires a split double-inclusion guard. */ +#if @HAVE_SCHED_H@ +# @INCLUDE_NEXT@ @NEXT_SCHED_H@ +#endif + +#ifndef _@GUARD_PREFIX@_SCHED_H +#define _@GUARD_PREFIX@_SCHED_H + +/* Get pid_t. + This is needed on glibc 2.11 (see + glibc bug ) + and Mac OS X 10.5. */ +#include + +#if !@HAVE_STRUCT_SCHED_PARAM@ + +# if !GNULIB_defined_struct_sched_param +struct sched_param +{ + int sched_priority; +}; +# define GNULIB_defined_struct_sched_param 1 +# endif + +#endif + +#if !(defined SCHED_FIFO && defined SCHED_RR && defined SCHED_OTHER) +# define SCHED_FIFO 1 +# define SCHED_RR 2 +# define SCHED_OTHER 0 +#endif + +#endif /* _@GUARD_PREFIX@_SCHED_H */ +#endif /* _@GUARD_PREFIX@_SCHED_H */ diff --git a/gettext-tools/gnulib-lib/secure_getenv.c b/gettext-tools/gnulib-lib/secure_getenv.c new file mode 100644 index 0000000..32819e6 --- /dev/null +++ b/gettext-tools/gnulib-lib/secure_getenv.c @@ -0,0 +1,41 @@ +/* Look up an environment variable more securely. + + Copyright 2013-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +#include + +#if !HAVE___SECURE_GETENV +# if HAVE_ISSETUGID +# include +# else +# undef issetugid +# define issetugid() 1 +# endif +#endif + +char * +secure_getenv (char const *name) +{ +#if HAVE___SECURE_GETENV + return __secure_getenv (name); +#else + if (issetugid ()) + return 0; + return getenv (name); +#endif +} diff --git a/gettext-tools/gnulib-lib/set-acl.c b/gettext-tools/gnulib-lib/set-acl.c new file mode 100644 index 0000000..9807f10 --- /dev/null +++ b/gettext-tools/gnulib-lib/set-acl.c @@ -0,0 +1,48 @@ +/* set-acl.c - set access control list equivalent to a mode + + Copyright (C) 2002-2003, 2005-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + Written by Paul Eggert and Andreas Gruenbacher, and Bruno Haible. */ + +#include + +#include "acl.h" + +#include + +#include "quote.h" +#include "error.h" +#include "gettext.h" +#define _(msgid) gettext (msgid) + + +/* Set the access control lists of a file. If DESC is a valid file + descriptor, use file descriptor operations where available, else use + filename based operations on NAME. If access control lists are not + available, fchmod the target file to MODE. Also sets the + non-permission bits of the destination file (S_ISUID, S_ISGID, S_ISVTX) + to those from MODE if any are set. + Return 0 if successful. On failure, output a diagnostic, set errno and + return -1. */ + +int +set_acl (char const *name, int desc, mode_t mode) +{ + int ret = qset_acl (name, desc, mode); + if (ret != 0) + error (0, errno, _("setting permissions for %s"), quote (name)); + return ret; +} diff --git a/gettext-tools/gnulib-lib/setenv.c b/gettext-tools/gnulib-lib/setenv.c new file mode 100644 index 0000000..06791a9 --- /dev/null +++ b/gettext-tools/gnulib-lib/setenv.c @@ -0,0 +1,390 @@ +/* Copyright (C) 1992, 1995-2003, 2005-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#if !_LIBC +/* Don't use __attribute__ __nonnull__ in this compilation unit. Otherwise gcc + optimizes away the name == NULL test below. */ +# define _GL_ARG_NONNULL(params) + +# define _GL_USE_STDLIB_ALLOC 1 +# include +#endif + +#include + +/* Specification. */ +#include + +#include +#ifndef __set_errno +# define __set_errno(ev) ((errno) = (ev)) +#endif + +#include +#if _LIBC || HAVE_UNISTD_H +# include +#endif + +#if !_LIBC +# include "malloca.h" +#endif + +#if _LIBC || !HAVE_SETENV + +#if !_LIBC +# define __environ environ +#endif + +#if _LIBC +/* This lock protects against simultaneous modifications of 'environ'. */ +# include +__libc_lock_define_initialized (static, envlock) +# define LOCK __libc_lock_lock (envlock) +# define UNLOCK __libc_lock_unlock (envlock) +#else +# define LOCK +# define UNLOCK +#endif + +/* In the GNU C library we must keep the namespace clean. */ +#ifdef _LIBC +# define setenv __setenv +# define clearenv __clearenv +# define tfind __tfind +# define tsearch __tsearch +#endif + +/* In the GNU C library implementation we try to be more clever and + allow arbitrarily many changes of the environment given that the used + values are from a small set. Outside glibc this will eat up all + memory after a while. */ +#if defined _LIBC || (defined HAVE_SEARCH_H && defined HAVE_TSEARCH \ + && defined __GNUC__) +# define USE_TSEARCH 1 +# include +typedef int (*compar_fn_t) (const void *, const void *); + +/* This is a pointer to the root of the search tree with the known + values. */ +static void *known_values; + +# define KNOWN_VALUE(Str) \ + ({ \ + void *value = tfind (Str, &known_values, (compar_fn_t) strcmp); \ + value != NULL ? *(char **) value : NULL; \ + }) +# define STORE_VALUE(Str) \ + tsearch (Str, &known_values, (compar_fn_t) strcmp) + +#else +# undef USE_TSEARCH + +# define KNOWN_VALUE(Str) NULL +# define STORE_VALUE(Str) do { } while (0) + +#endif + + +/* If this variable is not a null pointer we allocated the current + environment. */ +static char **last_environ; + + +/* This function is used by 'setenv' and 'putenv'. The difference between + the two functions is that for the former must create a new string which + is then placed in the environment, while the argument of 'putenv' + must be used directly. This is all complicated by the fact that we try + to reuse values once generated for a 'setenv' call since we can never + free the strings. */ +int +__add_to_environ (const char *name, const char *value, const char *combined, + int replace) +{ + char **ep; + size_t size; + const size_t namelen = strlen (name); + const size_t vallen = value != NULL ? strlen (value) + 1 : 0; + + LOCK; + + /* We have to get the pointer now that we have the lock and not earlier + since another thread might have created a new environment. */ + ep = __environ; + + size = 0; + if (ep != NULL) + { + for (; *ep != NULL; ++ep) + if (!strncmp (*ep, name, namelen) && (*ep)[namelen] == '=') + break; + else + ++size; + } + + if (ep == NULL || *ep == NULL) + { + char **new_environ; +#ifdef USE_TSEARCH + char *new_value; +#endif + + /* We allocated this space; we can extend it. */ + new_environ = + (char **) (last_environ == NULL + ? malloc ((size + 2) * sizeof (char *)) + : realloc (last_environ, (size + 2) * sizeof (char *))); + if (new_environ == NULL) + { + /* It's easier to set errno to ENOMEM than to rely on the + 'malloc-posix' and 'realloc-posix' gnulib modules. */ + __set_errno (ENOMEM); + UNLOCK; + return -1; + } + + /* If the whole entry is given add it. */ + if (combined != NULL) + /* We must not add the string to the search tree since it belongs + to the user. */ + new_environ[size] = (char *) combined; + else + { + /* See whether the value is already known. */ +#ifdef USE_TSEARCH +# ifdef _LIBC + new_value = (char *) alloca (namelen + 1 + vallen); + __mempcpy (__mempcpy (__mempcpy (new_value, name, namelen), "=", 1), + value, vallen); +# else + new_value = (char *) malloca (namelen + 1 + vallen); + if (new_value == NULL) + { + __set_errno (ENOMEM); + UNLOCK; + return -1; + } + memcpy (new_value, name, namelen); + new_value[namelen] = '='; + memcpy (&new_value[namelen + 1], value, vallen); +# endif + + new_environ[size] = KNOWN_VALUE (new_value); + if (new_environ[size] == NULL) +#endif + { + new_environ[size] = (char *) malloc (namelen + 1 + vallen); + if (new_environ[size] == NULL) + { +#if defined USE_TSEARCH && !defined _LIBC + freea (new_value); +#endif + __set_errno (ENOMEM); + UNLOCK; + return -1; + } + +#ifdef USE_TSEARCH + memcpy (new_environ[size], new_value, namelen + 1 + vallen); +#else + memcpy (new_environ[size], name, namelen); + new_environ[size][namelen] = '='; + memcpy (&new_environ[size][namelen + 1], value, vallen); +#endif + /* And save the value now. We cannot do this when we remove + the string since then we cannot decide whether it is a + user string or not. */ + STORE_VALUE (new_environ[size]); + } +#if defined USE_TSEARCH && !defined _LIBC + freea (new_value); +#endif + } + + if (__environ != last_environ) + memcpy ((char *) new_environ, (char *) __environ, + size * sizeof (char *)); + + new_environ[size + 1] = NULL; + + last_environ = __environ = new_environ; + } + else if (replace) + { + char *np; + + /* Use the user string if given. */ + if (combined != NULL) + np = (char *) combined; + else + { +#ifdef USE_TSEARCH + char *new_value; +# ifdef _LIBC + new_value = alloca (namelen + 1 + vallen); + __mempcpy (__mempcpy (__mempcpy (new_value, name, namelen), "=", 1), + value, vallen); +# else + new_value = malloca (namelen + 1 + vallen); + if (new_value == NULL) + { + __set_errno (ENOMEM); + UNLOCK; + return -1; + } + memcpy (new_value, name, namelen); + new_value[namelen] = '='; + memcpy (&new_value[namelen + 1], value, vallen); +# endif + + np = KNOWN_VALUE (new_value); + if (np == NULL) +#endif + { + np = (char *) malloc (namelen + 1 + vallen); + if (np == NULL) + { +#if defined USE_TSEARCH && !defined _LIBC + freea (new_value); +#endif + __set_errno (ENOMEM); + UNLOCK; + return -1; + } + +#ifdef USE_TSEARCH + memcpy (np, new_value, namelen + 1 + vallen); +#else + memcpy (np, name, namelen); + np[namelen] = '='; + memcpy (&np[namelen + 1], value, vallen); +#endif + /* And remember the value. */ + STORE_VALUE (np); + } +#if defined USE_TSEARCH && !defined _LIBC + freea (new_value); +#endif + } + + *ep = np; + } + + UNLOCK; + + return 0; +} + +int +setenv (const char *name, const char *value, int replace) +{ + if (name == NULL || *name == '\0' || strchr (name, '=') != NULL) + { + __set_errno (EINVAL); + return -1; + } + + return __add_to_environ (name, value, NULL, replace); +} + +/* The 'clearenv' was planned to be added to POSIX.1 but probably + never made it. Nevertheless the POSIX.9 standard (POSIX bindings + for Fortran 77) requires this function. */ +int +clearenv (void) +{ + LOCK; + + if (__environ == last_environ && __environ != NULL) + { + /* We allocated this environment so we can free it. */ + free (__environ); + last_environ = NULL; + } + + /* Clear the environment pointer removes the whole environment. */ + __environ = NULL; + + UNLOCK; + + return 0; +} + +#ifdef _LIBC +static void +free_mem (void) +{ + /* Remove all traces. */ + clearenv (); + + /* Now remove the search tree. */ + __tdestroy (known_values, free); + known_values = NULL; +} +text_set_element (__libc_subfreeres, free_mem); + + +# undef setenv +# undef clearenv +weak_alias (__setenv, setenv) +weak_alias (__clearenv, clearenv) +#endif + +#endif /* _LIBC || !HAVE_SETENV */ + +/* The rest of this file is called into use when replacing an existing + but buggy setenv. Known bugs include failure to diagnose invalid + name, and consuming a leading '=' from value. */ +#if HAVE_SETENV + +# undef setenv +# if !HAVE_DECL_SETENV +extern int setenv (const char *, const char *, int); +# endif +# define STREQ(a, b) (strcmp (a, b) == 0) + +int +rpl_setenv (const char *name, const char *value, int replace) +{ + int result; + if (!name || !*name || strchr (name, '=')) + { + errno = EINVAL; + return -1; + } + /* Call the real setenv even if replace is 0, in case implementation + has underlying data to update, such as when environ changes. */ + result = setenv (name, value, replace); + if (result == 0 && replace && *value == '=') + { + char *tmp = getenv (name); + if (!STREQ (tmp, value)) + { + int saved_errno; + size_t len = strlen (value); + tmp = malloca (len + 2); + /* Since leading '=' is eaten, double it up. */ + *tmp = '='; + memcpy (tmp + 1, value, len + 1); + result = setenv (name, tmp, replace); + saved_errno = errno; + freea (tmp); + errno = saved_errno; + } + } + return result; +} + +#endif /* HAVE_SETENV */ diff --git a/gettext-tools/gnulib-lib/setlocale.c b/gettext-tools/gnulib-lib/setlocale.c new file mode 100644 index 0000000..3009d2c --- /dev/null +++ b/gettext-tools/gnulib-lib/setlocale.c @@ -0,0 +1,938 @@ +/* Set the current locale. + Copyright (C) 2009, 2011-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Written by Bruno Haible , 2009. */ + +#include + +/* Override setlocale() so that when the default locale is requested + (locale = ""), the environment variables LC_ALL, LC_*, and LANG are + considered. + Also include all the functionality from libintl's setlocale() override. */ + +/* Please keep this file in sync with + gettext/gettext-runtime/intl/setlocale.c ! */ + +/* Specification. */ +#include + +#include +#include + +#include "localename.h" + +#if 1 + +# undef setlocale + +/* Return string representation of locale category CATEGORY. */ +static const char * +category_to_name (int category) +{ + const char *retval; + + switch (category) + { + case LC_COLLATE: + retval = "LC_COLLATE"; + break; + case LC_CTYPE: + retval = "LC_CTYPE"; + break; + case LC_MONETARY: + retval = "LC_MONETARY"; + break; + case LC_NUMERIC: + retval = "LC_NUMERIC"; + break; + case LC_TIME: + retval = "LC_TIME"; + break; + case LC_MESSAGES: + retval = "LC_MESSAGES"; + break; + default: + /* If you have a better idea for a default value let me know. */ + retval = "LC_XXX"; + } + + return retval; +} + +# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ + +/* The native Windows setlocale() function expects locale names of the form + "German" or "German_Germany" or "DEU", but not "de" or "de_DE". We need + to convert the names from the form with ISO 639 language code and ISO 3166 + country code to the form with English names or with three-letter identifier. + The three-letter identifiers known by a Windows XP SP2 or SP3 are: + AFK Afrikaans_South Africa.1252 + ARA Arabic_Saudi Arabia.1256 + ARB Arabic_Lebanon.1256 + ARE Arabic_Egypt.1256 + ARG Arabic_Algeria.1256 + ARH Arabic_Bahrain.1256 + ARI Arabic_Iraq.1256 + ARJ Arabic_Jordan.1256 + ARK Arabic_Kuwait.1256 + ARL Arabic_Libya.1256 + ARM Arabic_Morocco.1256 + ARO Arabic_Oman.1256 + ARQ Arabic_Qatar.1256 + ARS Arabic_Syria.1256 + ART Arabic_Tunisia.1256 + ARU Arabic_U.A.E..1256 + ARY Arabic_Yemen.1256 + AZE Azeri (Latin)_Azerbaijan.1254 + BEL Belarusian_Belarus.1251 + BGR Bulgarian_Bulgaria.1251 + BSB Bosnian_Bosnia and Herzegovina.1250 + BSC Bosnian (Cyrillic)_Bosnia and Herzegovina.1250 (wrong encoding!) + CAT Catalan_Spain.1252 + CHH Chinese_Hong Kong S.A.R..950 + CHI Chinese_Singapore.936 + CHS Chinese_People's Republic of China.936 + CHT Chinese_Taiwan.950 + CSY Czech_Czech Republic.1250 + CYM Welsh_United Kingdom.1252 + DAN Danish_Denmark.1252 + DEA German_Austria.1252 + DEC German_Liechtenstein.1252 + DEL German_Luxembourg.1252 + DES German_Switzerland.1252 + DEU German_Germany.1252 + ELL Greek_Greece.1253 + ENA English_Australia.1252 + ENB English_Caribbean.1252 + ENC English_Canada.1252 + ENG English_United Kingdom.1252 + ENI English_Ireland.1252 + ENJ English_Jamaica.1252 + ENL English_Belize.1252 + ENP English_Republic of the Philippines.1252 + ENS English_South Africa.1252 + ENT English_Trinidad and Tobago.1252 + ENU English_United States.1252 + ENW English_Zimbabwe.1252 + ENZ English_New Zealand.1252 + ESA Spanish_Panama.1252 + ESB Spanish_Bolivia.1252 + ESC Spanish_Costa Rica.1252 + ESD Spanish_Dominican Republic.1252 + ESE Spanish_El Salvador.1252 + ESF Spanish_Ecuador.1252 + ESG Spanish_Guatemala.1252 + ESH Spanish_Honduras.1252 + ESI Spanish_Nicaragua.1252 + ESL Spanish_Chile.1252 + ESM Spanish_Mexico.1252 + ESN Spanish_Spain.1252 + ESO Spanish_Colombia.1252 + ESP Spanish_Spain.1252 + ESR Spanish_Peru.1252 + ESS Spanish_Argentina.1252 + ESU Spanish_Puerto Rico.1252 + ESV Spanish_Venezuela.1252 + ESY Spanish_Uruguay.1252 + ESZ Spanish_Paraguay.1252 + ETI Estonian_Estonia.1257 + EUQ Basque_Spain.1252 + FAR Farsi_Iran.1256 + FIN Finnish_Finland.1252 + FOS Faroese_Faroe Islands.1252 + FPO Filipino_Philippines.1252 + FRA French_France.1252 + FRB French_Belgium.1252 + FRC French_Canada.1252 + FRL French_Luxembourg.1252 + FRM French_Principality of Monaco.1252 + FRS French_Switzerland.1252 + FYN Frisian_Netherlands.1252 + GLC Galician_Spain.1252 + HEB Hebrew_Israel.1255 + HRB Croatian_Bosnia and Herzegovina.1250 + HRV Croatian_Croatia.1250 + HUN Hungarian_Hungary.1250 + IND Indonesian_Indonesia.1252 + IRE Irish_Ireland.1252 + ISL Icelandic_Iceland.1252 + ITA Italian_Italy.1252 + ITS Italian_Switzerland.1252 + IUK Inuktitut (Latin)_Canada.1252 + JPN Japanese_Japan.932 + KKZ Kazakh_Kazakhstan.1251 + KOR Korean_Korea.949 + KYR Kyrgyz_Kyrgyzstan.1251 + LBX Luxembourgish_Luxembourg.1252 + LTH Lithuanian_Lithuania.1257 + LVI Latvian_Latvia.1257 + MKI FYRO Macedonian_Former Yugoslav Republic of Macedonia.1251 + MON Mongolian_Mongolia.1251 + MPD Mapudungun_Chile.1252 + MSB Malay_Brunei Darussalam.1252 + MSL Malay_Malaysia.1252 + MWK Mohawk_Canada.1252 + NLB Dutch_Belgium.1252 + NLD Dutch_Netherlands.1252 + NON Norwegian-Nynorsk_Norway.1252 + NOR Norwegian (BokmÃ¥l)_Norway.1252 + NSO Northern Sotho_South Africa.1252 + PLK Polish_Poland.1250 + PTB Portuguese_Brazil.1252 + PTG Portuguese_Portugal.1252 + QUB Quechua_Bolivia.1252 + QUE Quechua_Ecuador.1252 + QUP Quechua_Peru.1252 + RMC Romansh_Switzerland.1252 + ROM Romanian_Romania.1250 + RUS Russian_Russia.1251 + SKY Slovak_Slovakia.1250 + SLV Slovenian_Slovenia.1250 + SMA Sami (Southern)_Norway.1252 + SMB Sami (Southern)_Sweden.1252 + SME Sami (Northern)_Norway.1252 + SMF Sami (Northern)_Sweden.1252 + SMG Sami (Northern)_Finland.1252 + SMJ Sami (Lule)_Norway.1252 + SMK Sami (Lule)_Sweden.1252 + SMN Sami (Inari)_Finland.1252 + SMS Sami (Skolt)_Finland.1252 + SQI Albanian_Albania.1250 + SRB Serbian (Cyrillic)_Serbia and Montenegro.1251 + SRL Serbian (Latin)_Serbia and Montenegro.1250 + SRN Serbian (Cyrillic)_Bosnia and Herzegovina.1251 + SRS Serbian (Latin)_Bosnia and Herzegovina.1250 + SVE Swedish_Sweden.1252 + SVF Swedish_Finland.1252 + SWK Swahili_Kenya.1252 + THA Thai_Thailand.874 + TRK Turkish_Turkey.1254 + TSN Tswana_South Africa.1252 + TTT Tatar_Russia.1251 + UKR Ukrainian_Ukraine.1251 + URD Urdu_Islamic Republic of Pakistan.1256 + USA English_United States.1252 + UZB Uzbek (Latin)_Uzbekistan.1254 + VIT Vietnamese_Viet Nam.1258 + XHO Xhosa_South Africa.1252 + ZHH Chinese_Hong Kong S.A.R..950 + ZHI Chinese_Singapore.936 + ZHM Chinese_Macau S.A.R..950 + ZUL Zulu_South Africa.1252 + */ + +/* Table from ISO 639 language code, optionally with country or script suffix, + to English name. + Keep in sync with the gl_locale_name_from_win32_LANGID function in + localename.c! */ +struct table_entry +{ + const char *code; + const char *english; +}; +static const struct table_entry language_table[] = + { + { "af", "Afrikaans" }, + { "am", "Amharic" }, + { "ar", "Arabic" }, + { "arn", "Mapudungun" }, + { "as", "Assamese" }, + { "az@cyrillic", "Azeri (Cyrillic)" }, + { "az@latin", "Azeri (Latin)" }, + { "ba", "Bashkir" }, + { "be", "Belarusian" }, + { "ber", "Tamazight" }, + { "ber@arabic", "Tamazight (Arabic)" }, + { "ber@latin", "Tamazight (Latin)" }, + { "bg", "Bulgarian" }, + { "bin", "Edo" }, + { "bn", "Bengali" }, + { "bn_BD", "Bengali (Bangladesh)" }, + { "bn_IN", "Bengali (India)" }, + { "bnt", "Sutu" }, + { "bo", "Tibetan" }, + { "br", "Breton" }, + { "bs", "BSB" }, /* "Bosnian (Latin)" */ + { "bs@cyrillic", "BSC" }, /* Bosnian (Cyrillic) */ + { "ca", "Catalan" }, + { "chr", "Cherokee" }, + { "co", "Corsican" }, + { "cpe", "Hawaiian" }, + { "cs", "Czech" }, + { "cy", "Welsh" }, + { "da", "Danish" }, + { "de", "German" }, + { "dsb", "Lower Sorbian" }, + { "dv", "Divehi" }, + { "el", "Greek" }, + { "en", "English" }, + { "es", "Spanish" }, + { "et", "Estonian" }, + { "eu", "Basque" }, + { "fa", "Farsi" }, + { "ff", "Fulfulde" }, + { "fi", "Finnish" }, + { "fo", "Faroese" }, /* "Faeroese" does not work */ + { "fr", "French" }, + { "fy", "Frisian" }, + { "ga", "IRE" }, /* Gaelic (Ireland) */ + { "gd", "Gaelic (Scotland)" }, + { "gd", "Scottish Gaelic" }, + { "gl", "Galician" }, + { "gn", "Guarani" }, + { "gsw", "Alsatian" }, + { "gu", "Gujarati" }, + { "ha", "Hausa" }, + { "he", "Hebrew" }, + { "hi", "Hindi" }, + { "hr", "Croatian" }, + { "hsb", "Upper Sorbian" }, + { "hu", "Hungarian" }, + { "hy", "Armenian" }, + { "id", "Indonesian" }, + { "ig", "Igbo" }, + { "ii", "Yi" }, + { "is", "Icelandic" }, + { "it", "Italian" }, + { "iu", "IUK" }, /* Inuktitut */ + { "ja", "Japanese" }, + { "ka", "Georgian" }, + { "kk", "Kazakh" }, + { "kl", "Greenlandic" }, + { "km", "Cambodian" }, + { "km", "Khmer" }, + { "kn", "Kannada" }, + { "ko", "Korean" }, + { "kok", "Konkani" }, + { "kr", "Kanuri" }, + { "ks", "Kashmiri" }, + { "ks_IN", "Kashmiri_India" }, + { "ks_PK", "Kashmiri (Arabic)_Pakistan" }, + { "ky", "Kyrgyz" }, + { "la", "Latin" }, + { "lb", "Luxembourgish" }, + { "lo", "Lao" }, + { "lt", "Lithuanian" }, + { "lv", "Latvian" }, + { "mi", "Maori" }, + { "mk", "FYRO Macedonian" }, + { "mk", "Macedonian" }, + { "ml", "Malayalam" }, + { "mn", "Mongolian" }, + { "mni", "Manipuri" }, + { "moh", "Mohawk" }, + { "mr", "Marathi" }, + { "ms", "Malay" }, + { "mt", "Maltese" }, + { "my", "Burmese" }, + { "nb", "NOR" }, /* Norwegian BokmÃ¥l */ + { "ne", "Nepali" }, + { "nic", "Ibibio" }, + { "nl", "Dutch" }, + { "nn", "NON" }, /* Norwegian Nynorsk */ + { "no", "Norwegian" }, + { "nso", "Northern Sotho" }, + { "nso", "Sepedi" }, + { "oc", "Occitan" }, + { "om", "Oromo" }, + { "or", "Oriya" }, + { "pa", "Punjabi" }, + { "pap", "Papiamentu" }, + { "pl", "Polish" }, + { "prs", "Dari" }, + { "ps", "Pashto" }, + { "pt", "Portuguese" }, + { "qu", "Quechua" }, + { "qut", "K'iche'" }, + { "rm", "Romansh" }, + { "ro", "Romanian" }, + { "ru", "Russian" }, + { "rw", "Kinyarwanda" }, + { "sa", "Sanskrit" }, + { "sah", "Yakut" }, + { "sd", "Sindhi" }, + { "se", "Sami (Northern)" }, + { "se", "Northern Sami" }, + { "si", "Sinhalese" }, + { "sk", "Slovak" }, + { "sl", "Slovenian" }, + { "sma", "Sami (Southern)" }, + { "sma", "Southern Sami" }, + { "smj", "Sami (Lule)" }, + { "smj", "Lule Sami" }, + { "smn", "Sami (Inari)" }, + { "smn", "Inari Sami" }, + { "sms", "Sami (Skolt)" }, + { "sms", "Skolt Sami" }, + { "so", "Somali" }, + { "sq", "Albanian" }, + { "sr", "Serbian (Latin)" }, + { "sr@cyrillic", "SRB" }, /* Serbian (Cyrillic) */ + { "sw", "Swahili" }, + { "syr", "Syriac" }, + { "ta", "Tamil" }, + { "te", "Telugu" }, + { "tg", "Tajik" }, + { "th", "Thai" }, + { "ti", "Tigrinya" }, + { "tk", "Turkmen" }, + { "tl", "Filipino" }, + { "tn", "Tswana" }, + { "tr", "Turkish" }, + { "ts", "Tsonga" }, + { "tt", "Tatar" }, + { "ug", "Uighur" }, + { "uk", "Ukrainian" }, + { "ur", "Urdu" }, + { "uz", "Uzbek" }, + { "uz", "Uzbek (Latin)" }, + { "uz@cyrillic", "Uzbek (Cyrillic)" }, + { "ve", "Venda" }, + { "vi", "Vietnamese" }, + { "wen", "Sorbian" }, + { "wo", "Wolof" }, + { "xh", "Xhosa" }, + { "yi", "Yiddish" }, + { "yo", "Yoruba" }, + { "zh", "Chinese" }, + { "zu", "Zulu" } + }; + +/* Table from ISO 3166 country code to English name. + Keep in sync with the gl_locale_name_from_win32_LANGID function in + localename.c! */ +static const struct table_entry country_table[] = + { + { "AE", "U.A.E." }, + { "AF", "Afghanistan" }, + { "AL", "Albania" }, + { "AM", "Armenia" }, + { "AN", "Netherlands Antilles" }, + { "AR", "Argentina" }, + { "AT", "Austria" }, + { "AU", "Australia" }, + { "AZ", "Azerbaijan" }, + { "BA", "Bosnia and Herzegovina" }, + { "BD", "Bangladesh" }, + { "BE", "Belgium" }, + { "BG", "Bulgaria" }, + { "BH", "Bahrain" }, + { "BN", "Brunei Darussalam" }, + { "BO", "Bolivia" }, + { "BR", "Brazil" }, + { "BT", "Bhutan" }, + { "BY", "Belarus" }, + { "BZ", "Belize" }, + { "CA", "Canada" }, + { "CG", "Congo" }, + { "CH", "Switzerland" }, + { "CI", "Cote d'Ivoire" }, + { "CL", "Chile" }, + { "CM", "Cameroon" }, + { "CN", "People's Republic of China" }, + { "CO", "Colombia" }, + { "CR", "Costa Rica" }, + { "CS", "Serbia and Montenegro" }, + { "CZ", "Czech Republic" }, + { "DE", "Germany" }, + { "DK", "Denmark" }, + { "DO", "Dominican Republic" }, + { "DZ", "Algeria" }, + { "EC", "Ecuador" }, + { "EE", "Estonia" }, + { "EG", "Egypt" }, + { "ER", "Eritrea" }, + { "ES", "Spain" }, + { "ET", "Ethiopia" }, + { "FI", "Finland" }, + { "FO", "Faroe Islands" }, + { "FR", "France" }, + { "GB", "United Kingdom" }, + { "GD", "Caribbean" }, + { "GE", "Georgia" }, + { "GL", "Greenland" }, + { "GR", "Greece" }, + { "GT", "Guatemala" }, + { "HK", "Hong Kong" }, + { "HK", "Hong Kong S.A.R." }, + { "HN", "Honduras" }, + { "HR", "Croatia" }, + { "HT", "Haiti" }, + { "HU", "Hungary" }, + { "ID", "Indonesia" }, + { "IE", "Ireland" }, + { "IL", "Israel" }, + { "IN", "India" }, + { "IQ", "Iraq" }, + { "IR", "Iran" }, + { "IS", "Iceland" }, + { "IT", "Italy" }, + { "JM", "Jamaica" }, + { "JO", "Jordan" }, + { "JP", "Japan" }, + { "KE", "Kenya" }, + { "KG", "Kyrgyzstan" }, + { "KH", "Cambodia" }, + { "KR", "South Korea" }, + { "KW", "Kuwait" }, + { "KZ", "Kazakhstan" }, + { "LA", "Laos" }, + { "LB", "Lebanon" }, + { "LI", "Liechtenstein" }, + { "LK", "Sri Lanka" }, + { "LT", "Lithuania" }, + { "LU", "Luxembourg" }, + { "LV", "Latvia" }, + { "LY", "Libya" }, + { "MA", "Morocco" }, + { "MC", "Principality of Monaco" }, + { "MD", "Moldava" }, + { "MD", "Moldova" }, + { "ME", "Montenegro" }, + { "MK", "Former Yugoslav Republic of Macedonia" }, + { "ML", "Mali" }, + { "MM", "Myanmar" }, + { "MN", "Mongolia" }, + { "MO", "Macau S.A.R." }, + { "MT", "Malta" }, + { "MV", "Maldives" }, + { "MX", "Mexico" }, + { "MY", "Malaysia" }, + { "NG", "Nigeria" }, + { "NI", "Nicaragua" }, + { "NL", "Netherlands" }, + { "NO", "Norway" }, + { "NP", "Nepal" }, + { "NZ", "New Zealand" }, + { "OM", "Oman" }, + { "PA", "Panama" }, + { "PE", "Peru" }, + { "PH", "Philippines" }, + { "PK", "Islamic Republic of Pakistan" }, + { "PL", "Poland" }, + { "PR", "Puerto Rico" }, + { "PT", "Portugal" }, + { "PY", "Paraguay" }, + { "QA", "Qatar" }, + { "RE", "Reunion" }, + { "RO", "Romania" }, + { "RS", "Serbia" }, + { "RU", "Russia" }, + { "RW", "Rwanda" }, + { "SA", "Saudi Arabia" }, + { "SE", "Sweden" }, + { "SG", "Singapore" }, + { "SI", "Slovenia" }, + { "SK", "Slovak" }, + { "SN", "Senegal" }, + { "SO", "Somalia" }, + { "SR", "Suriname" }, + { "SV", "El Salvador" }, + { "SY", "Syria" }, + { "TH", "Thailand" }, + { "TJ", "Tajikistan" }, + { "TM", "Turkmenistan" }, + { "TN", "Tunisia" }, + { "TR", "Turkey" }, + { "TT", "Trinidad and Tobago" }, + { "TW", "Taiwan" }, + { "TZ", "Tanzania" }, + { "UA", "Ukraine" }, + { "US", "United States" }, + { "UY", "Uruguay" }, + { "VA", "Vatican" }, + { "VE", "Venezuela" }, + { "VN", "Viet Nam" }, + { "YE", "Yemen" }, + { "ZA", "South Africa" }, + { "ZW", "Zimbabwe" } + }; + +/* Given a string STRING, find the set of indices i such that TABLE[i].code is + the given STRING. It is a range [lo,hi-1]. */ +typedef struct { size_t lo; size_t hi; } range_t; +static void +search (const struct table_entry *table, size_t table_size, const char *string, + range_t *result) +{ + /* The table is sorted. Perform a binary search. */ + size_t hi = table_size; + size_t lo = 0; + while (lo < hi) + { + /* Invariant: + for i < lo, strcmp (table[i].code, string) < 0, + for i >= hi, strcmp (table[i].code, string) > 0. */ + size_t mid = (hi + lo) >> 1; /* >= lo, < hi */ + int cmp = strcmp (table[mid].code, string); + if (cmp < 0) + lo = mid + 1; + else if (cmp > 0) + hi = mid; + else + { + /* Found an i with + strcmp (language_table[i].code, string) == 0. + Find the entire interval of such i. */ + { + size_t i; + + for (i = mid; i > lo; ) + { + i--; + if (strcmp (table[i].code, string) < 0) + { + lo = i + 1; + break; + } + } + } + { + size_t i; + + for (i = mid; i < hi; i++) + { + if (strcmp (table[i].code, string) > 0) + { + hi = i; + break; + } + } + } + /* The set of i with + strcmp (language_table[i].code, string) == 0 + is the interval [lo, hi-1]. */ + break; + } + } + result->lo = lo; + result->hi = hi; +} + +/* Like setlocale, but accept also locale names in the form ll or ll_CC, + where ll is an ISO 639 language code and CC is an ISO 3166 country code. */ +static char * +setlocale_unixlike (int category, const char *locale) +{ + char *result; + char llCC_buf[64]; + char ll_buf[64]; + char CC_buf[64]; + + /* First, try setlocale with the original argument unchanged. */ + result = setlocale (category, locale); + if (result != NULL) + return result; + + /* Otherwise, assume the argument is in the form + language[_territory][.codeset][@modifier] + and try to map it using the tables. */ + if (strlen (locale) < sizeof (llCC_buf)) + { + /* Second try: Remove the codeset part. */ + { + const char *p = locale; + char *q = llCC_buf; + + /* Copy the part before the dot. */ + for (; *p != '\0' && *p != '.'; p++, q++) + *q = *p; + if (*p == '.') + /* Skip the part up to the '@', if any. */ + for (; *p != '\0' && *p != '@'; p++) + ; + /* Copy the part starting with '@', if any. */ + for (; *p != '\0'; p++, q++) + *q = *p; + *q = '\0'; + } + /* llCC_buf now contains + language[_territory][@modifier] + */ + if (strcmp (llCC_buf, locale) != 0) + { + result = setlocale (category, llCC_buf); + if (result != NULL) + return result; + } + /* Look it up in language_table. */ + { + range_t range; + size_t i; + + search (language_table, + sizeof (language_table) / sizeof (language_table[0]), + llCC_buf, + &range); + + for (i = range.lo; i < range.hi; i++) + { + /* Try the replacement in language_table[i]. */ + result = setlocale (category, language_table[i].english); + if (result != NULL) + return result; + } + } + /* Split language[_territory][@modifier] + into ll_buf = language[@modifier] + and CC_buf = territory + */ + { + const char *underscore = strchr (llCC_buf, '_'); + if (underscore != NULL) + { + const char *territory_start = underscore + 1; + const char *territory_end = strchr (territory_start, '@'); + if (territory_end == NULL) + territory_end = territory_start + strlen (territory_start); + + memcpy (ll_buf, llCC_buf, underscore - llCC_buf); + strcpy (ll_buf + (underscore - llCC_buf), territory_end); + + memcpy (CC_buf, territory_start, territory_end - territory_start); + CC_buf[territory_end - territory_start] = '\0'; + + { + /* Look up ll_buf in language_table + and CC_buf in country_table. */ + range_t language_range; + + search (language_table, + sizeof (language_table) / sizeof (language_table[0]), + ll_buf, + &language_range); + if (language_range.lo < language_range.hi) + { + range_t country_range; + + search (country_table, + sizeof (country_table) / sizeof (country_table[0]), + CC_buf, + &country_range); + if (country_range.lo < country_range.hi) + { + size_t i; + size_t j; + + for (i = language_range.lo; i < language_range.hi; i++) + for (j = country_range.lo; j < country_range.hi; j++) + { + /* Concatenate the replacements. */ + const char *part1 = language_table[i].english; + size_t part1_len = strlen (part1); + const char *part2 = country_table[j].english; + size_t part2_len = strlen (part2) + 1; + char buf[64+64]; + + if (!(part1_len + 1 + part2_len <= sizeof (buf))) + abort (); + memcpy (buf, part1, part1_len); + buf[part1_len] = '_'; + memcpy (buf + part1_len + 1, part2, part2_len); + + /* Try the concatenated replacements. */ + result = setlocale (category, buf); + if (result != NULL) + return result; + } + } + + /* Try omitting the country entirely. This may set a locale + corresponding to the wrong country, but is better than + failing entirely. */ + { + size_t i; + + for (i = language_range.lo; i < language_range.hi; i++) + { + /* Try only the language replacement. */ + result = + setlocale (category, language_table[i].english); + if (result != NULL) + return result; + } + } + } + } + } + } + } + + /* Failed. */ + return NULL; +} + +# else +# define setlocale_unixlike setlocale +# endif + +# if LC_MESSAGES == 1729 + +/* The system does not store an LC_MESSAGES locale category. Do it here. */ +static char lc_messages_name[64] = "C"; + +/* Like setlocale, but support also LC_MESSAGES. */ +static char * +setlocale_single (int category, const char *locale) +{ + if (category == LC_MESSAGES) + { + if (locale != NULL) + { + lc_messages_name[sizeof (lc_messages_name) - 1] = '\0'; + strncpy (lc_messages_name, locale, sizeof (lc_messages_name) - 1); + } + return lc_messages_name; + } + else + return setlocale_unixlike (category, locale); +} + +# else +# define setlocale_single setlocale_unixlike +# endif + +char * +rpl_setlocale (int category, const char *locale) +{ + if (locale != NULL && locale[0] == '\0') + { + /* A request to the set the current locale to the default locale. */ + if (category == LC_ALL) + { + /* Set LC_CTYPE first. Then the other categories. */ + static int const categories[] = + { + LC_NUMERIC, + LC_TIME, + LC_COLLATE, + LC_MONETARY, + LC_MESSAGES + }; + char *saved_locale; + const char *base_name; + unsigned int i; + + /* Back up the old locale, in case one of the steps fails. */ + saved_locale = setlocale (LC_ALL, NULL); + if (saved_locale == NULL) + return NULL; + saved_locale = strdup (saved_locale); + if (saved_locale == NULL) + return NULL; + + /* Set LC_CTYPE category. Set all other categories (except possibly + LC_MESSAGES) to the same value in the same call; this is likely to + save calls. */ + base_name = + gl_locale_name_environ (LC_CTYPE, category_to_name (LC_CTYPE)); + if (base_name == NULL) + base_name = gl_locale_name_default (); + + if (setlocale_unixlike (LC_ALL, base_name) == NULL) + goto fail; +# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ + /* On native Windows, setlocale(LC_ALL,...) may succeed but set the + LC_CTYPE category to an invalid value ("C") when it does not + support the specified encoding. Report a failure instead. */ + if (strchr (base_name, '.') != NULL + && strcmp (setlocale (LC_CTYPE, NULL), "C") == 0) + goto fail; +# endif + + for (i = 0; i < sizeof (categories) / sizeof (categories[0]); i++) + { + int cat = categories[i]; + const char *name; + + name = gl_locale_name_environ (cat, category_to_name (cat)); + if (name == NULL) + name = gl_locale_name_default (); + + /* If name is the same as base_name, it has already been set + through the setlocale call before the loop. */ + if (strcmp (name, base_name) != 0 +# if LC_MESSAGES == 1729 + || cat == LC_MESSAGES +# endif + ) + if (setlocale_single (cat, name) == NULL) + goto fail; + } + + /* All steps were successful. */ + free (saved_locale); + return setlocale (LC_ALL, NULL); + + fail: + if (saved_locale[0] != '\0') /* don't risk an endless recursion */ + setlocale (LC_ALL, saved_locale); + free (saved_locale); + return NULL; + } + else + { + const char *name = + gl_locale_name_environ (category, category_to_name (category)); + if (name == NULL) + name = gl_locale_name_default (); + + return setlocale_single (category, name); + } + } + else + { +# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ + if (category == LC_ALL && locale != NULL && strchr (locale, '.') != NULL) + { + char *saved_locale; + + /* Back up the old locale. */ + saved_locale = setlocale (LC_ALL, NULL); + if (saved_locale == NULL) + return NULL; + saved_locale = strdup (saved_locale); + if (saved_locale == NULL) + return NULL; + + if (setlocale_unixlike (LC_ALL, locale) == NULL) + { + free (saved_locale); + return NULL; + } + + /* On native Windows, setlocale(LC_ALL,...) may succeed but set the + LC_CTYPE category to an invalid value ("C") when it does not + support the specified encoding. Report a failure instead. */ + if (strcmp (setlocale (LC_CTYPE, NULL), "C") == 0) + { + if (saved_locale[0] != '\0') /* don't risk an endless recursion */ + setlocale (LC_ALL, saved_locale); + free (saved_locale); + return NULL; + } + + /* It was really successful. */ + free (saved_locale); + return setlocale (LC_ALL, NULL); + } + else +# endif + return setlocale_single (category, locale); + } +} + +#endif diff --git a/gettext-tools/gnulib-lib/sh-quote.c b/gettext-tools/gnulib-lib/sh-quote.c new file mode 100644 index 0000000..a97be57 --- /dev/null +++ b/gettext-tools/gnulib-lib/sh-quote.c @@ -0,0 +1,107 @@ +/* Shell quoting. + Copyright (C) 2001-2004, 2006, 2009-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2001. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include "sh-quote.h" + +#include + +#include "quotearg.h" +#include "xalloc.h" + +/* Describes quoting for sh compatible shells. */ +static struct quoting_options *sh_quoting_options; + +/* Initializes the sh_quoting_options variable. */ +static void +init_sh_quoting_options () +{ + sh_quoting_options = clone_quoting_options (NULL); + set_quoting_style (sh_quoting_options, shell_quoting_style); +} + +/* Returns the number of bytes needed for the quoted string. */ +size_t +shell_quote_length (const char *string) +{ + if (sh_quoting_options == NULL) + init_sh_quoting_options (); + return quotearg_buffer (NULL, 0, string, strlen (string), + sh_quoting_options); +} + +/* Copies the quoted string to p and returns the incremented p. + There must be room for shell_quote_length (string) + 1 bytes at p. */ +char * +shell_quote_copy (char *p, const char *string) +{ + if (sh_quoting_options == NULL) + init_sh_quoting_options (); + return p + quotearg_buffer (p, (size_t)(-1), string, strlen (string), + sh_quoting_options); +} + +/* Returns the freshly allocated quoted string. */ +char * +shell_quote (const char *string) +{ + if (sh_quoting_options == NULL) + init_sh_quoting_options (); + return quotearg_alloc (string, strlen (string), sh_quoting_options); +} + +/* Returns a freshly allocated string containing all argument strings, quoted, + separated through spaces. */ +char * +shell_quote_argv (char * const *argv) +{ + if (*argv != NULL) + { + char * const *argp; + size_t length; + char *command; + char *p; + + length = 0; + for (argp = argv; ; ) + { + length += shell_quote_length (*argp) + 1; + argp++; + if (*argp == NULL) + break; + } + + command = XNMALLOC (length, char); + + p = command; + for (argp = argv; ; ) + { + p = shell_quote_copy (p, *argp); + argp++; + if (*argp == NULL) + break; + *p++ = ' '; + } + *p = '\0'; + + return command; + } + else + return xstrdup (""); +} diff --git a/gettext-tools/gnulib-lib/sh-quote.h b/gettext-tools/gnulib-lib/sh-quote.h new file mode 100644 index 0000000..8615275 --- /dev/null +++ b/gettext-tools/gnulib-lib/sh-quote.h @@ -0,0 +1,49 @@ +/* Shell quoting. + Copyright (C) 2001-2002, 2004, 2009-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2001. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _SH_QUOTE_H +#define _SH_QUOTE_H + +/* When passing a command to a shell, we must quote the program name and + arguments, since Unix shells interpret characters like " ", "'", "<", ">", + "$", '*', '?' etc. in a special way. */ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Returns the number of bytes needed for the quoted string. */ +extern size_t shell_quote_length (const char *string); + +/* Copies the quoted string to p and returns the incremented p. + There must be room for shell_quote_length (string) + 1 bytes at p. */ +extern char * shell_quote_copy (char *p, const char *string); + +/* Returns the freshly allocated quoted string. */ +extern char * shell_quote (const char *string); + +/* Returns a freshly allocated string containing all argument strings, quoted, + separated through spaces. */ +extern char * shell_quote_argv (char * const *argv); + +#ifdef __cplusplus +} +#endif + +#endif /* _SH_QUOTE_H */ diff --git a/gettext-tools/gnulib-lib/sig-handler.c b/gettext-tools/gnulib-lib/sig-handler.c new file mode 100644 index 0000000..52c3621 --- /dev/null +++ b/gettext-tools/gnulib-lib/sig-handler.c @@ -0,0 +1,3 @@ +#include +#define SIG_HANDLER_INLINE _GL_EXTERN_INLINE +#include "sig-handler.h" diff --git a/gettext-tools/gnulib-lib/sig-handler.h b/gettext-tools/gnulib-lib/sig-handler.h new file mode 100644 index 0000000..f4fe7ec --- /dev/null +++ b/gettext-tools/gnulib-lib/sig-handler.h @@ -0,0 +1,54 @@ +/* Convenience declarations when working with . + + Copyright (C) 2008-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _GL_SIG_HANDLER_H +#define _GL_SIG_HANDLER_H + +#include + +#ifndef _GL_INLINE_HEADER_BEGIN + #error "Please include config.h first." +#endif +_GL_INLINE_HEADER_BEGIN +#ifndef SIG_HANDLER_INLINE +# define SIG_HANDLER_INLINE _GL_INLINE +#endif + +/* Convenience type when working with signal handlers. */ +typedef void (*sa_handler_t) (int); + +/* Return the handler of a signal, as a sa_handler_t value regardless + of its true type. The resulting function can be compared to + special values like SIG_IGN but it is not portable to call it. */ +SIG_HANDLER_INLINE sa_handler_t +get_handler (struct sigaction const *a) +{ +#ifdef SA_SIGINFO + /* POSIX says that special values like SIG_IGN can only occur when + action.sa_flags does not contain SA_SIGINFO. But in Linux 2.4, + for example, sa_sigaction and sa_handler are aliases and a signal + is ignored if sa_sigaction (after casting) equals SIG_IGN. So + use (and cast) sa_sigaction in that case. */ + if (a->sa_flags & SA_SIGINFO) + return (sa_handler_t) a->sa_sigaction; +#endif + return a->sa_handler; +} + +_GL_INLINE_HEADER_END + +#endif /* _GL_SIG_HANDLER_H */ diff --git a/gettext-tools/gnulib-lib/sigaction.c b/gettext-tools/gnulib-lib/sigaction.c new file mode 100644 index 0000000..c56ca46 --- /dev/null +++ b/gettext-tools/gnulib-lib/sigaction.c @@ -0,0 +1,204 @@ +/* POSIX compatible signal blocking. + Copyright (C) 2008-2014 Free Software Foundation, Inc. + Written by Eric Blake , 2008. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include + +#include +#include +#include + +/* This implementation of sigaction is tailored to native Windows behavior: + signal() has SysV semantics (ie. the handler is uninstalled before + it is invoked). This is an inherent data race if an asynchronous + signal is sent twice in a row before we can reinstall our handler, + but there's nothing we can do about it. Meanwhile, sigprocmask() + is not present, and while we can use the gnulib replacement to + provide critical sections, it too suffers from potential data races + in the face of an ill-timed asynchronous signal. And we compound + the situation by reading static storage in a signal handler, which + POSIX warns is not generically async-signal-safe. Oh well. + + Additionally: + - We don't implement SA_NOCLDSTOP or SA_NOCLDWAIT, because SIGCHLD + is not defined. + - We don't implement SA_ONSTACK, because sigaltstack() is not present. + - We ignore SA_RESTART, because blocking native Windows API calls are + not interrupted anyway when an asynchronous signal occurs, and the + MSVCRT runtime never sets errno to EINTR. + - We don't implement SA_SIGINFO because it is impossible to do so + portably. + + POSIX states that an application should not mix signal() and + sigaction(). We support the use of signal() within the gnulib + sigprocmask() substitute, but all other application code linked + with this module should stick with only sigaction(). */ + +/* Check some of our assumptions. */ +#if defined SIGCHLD || defined HAVE_SIGALTSTACK || defined HAVE_SIGINTERRUPT +# error "Revisit the assumptions made in the sigaction module" +#endif + +/* Out-of-range substitutes make a good fallback for uncatchable + signals. */ +#ifndef SIGKILL +# define SIGKILL (-1) +#endif +#ifndef SIGSTOP +# define SIGSTOP (-1) +#endif + +/* On native Windows, as of 2008, the signal SIGABRT_COMPAT is an alias + for the signal SIGABRT. Only one signal handler is stored for both + SIGABRT and SIGABRT_COMPAT. SIGABRT_COMPAT is not a signal of its own. */ +#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ +# undef SIGABRT_COMPAT +# define SIGABRT_COMPAT 6 +#endif + +/* A signal handler. */ +typedef void (*handler_t) (int signal); + +/* Set of current actions. If sa_handler for an entry is NULL, then + that signal is not currently handled by the sigaction handler. */ +static struct sigaction volatile action_array[NSIG] /* = 0 */; + +/* Signal handler that is installed for signals. */ +static void +sigaction_handler (int sig) +{ + handler_t handler; + sigset_t mask; + sigset_t oldmask; + int saved_errno = errno; + if (sig < 0 || NSIG <= sig || !action_array[sig].sa_handler) + { + /* Unexpected situation; be careful to avoid recursive abort. */ + if (sig == SIGABRT) + signal (SIGABRT, SIG_DFL); + abort (); + } + + /* Reinstall the signal handler when required; otherwise update the + bookkeeping so that the user's handler may call sigaction and get + accurate results. We know the signal isn't currently blocked, or + we wouldn't be in its handler, therefore we know that we are not + interrupting a sigaction() call. There is a race where any + asynchronous instance of the same signal occurring before we + reinstall the handler will trigger the default handler; oh + well. */ + handler = action_array[sig].sa_handler; + if ((action_array[sig].sa_flags & SA_RESETHAND) == 0) + signal (sig, sigaction_handler); + else + action_array[sig].sa_handler = NULL; + + /* Block appropriate signals. */ + mask = action_array[sig].sa_mask; + if ((action_array[sig].sa_flags & SA_NODEFER) == 0) + sigaddset (&mask, sig); + sigprocmask (SIG_BLOCK, &mask, &oldmask); + + /* Invoke the user's handler, then restore prior mask. */ + errno = saved_errno; + handler (sig); + saved_errno = errno; + sigprocmask (SIG_SETMASK, &oldmask, NULL); + errno = saved_errno; +} + +/* Change and/or query the action that will be taken on delivery of + signal SIG. If not NULL, ACT describes the new behavior. If not + NULL, OACT is set to the prior behavior. Return 0 on success, or + set errno and return -1 on failure. */ +int +sigaction (int sig, const struct sigaction *restrict act, + struct sigaction *restrict oact) +{ + sigset_t mask; + sigset_t oldmask; + int saved_errno; + + if (sig < 0 || NSIG <= sig || sig == SIGKILL || sig == SIGSTOP + || (act && act->sa_handler == SIG_ERR)) + { + errno = EINVAL; + return -1; + } + +#ifdef SIGABRT_COMPAT + if (sig == SIGABRT_COMPAT) + sig = SIGABRT; +#endif + + /* POSIX requires sigaction() to be async-signal-safe. In other + words, if an asynchronous signal can occur while we are anywhere + inside this function, the user's handler could then call + sigaction() recursively and expect consistent results. We meet + this rule by using sigprocmask to block all signals before + modifying any data structure that could be read from a signal + handler; this works since we know that the gnulib sigprocmask + replacement does not try to use sigaction() from its handler. */ + if (!act && !oact) + return 0; + sigfillset (&mask); + sigprocmask (SIG_BLOCK, &mask, &oldmask); + if (oact) + { + if (action_array[sig].sa_handler) + *oact = action_array[sig]; + else + { + /* Safe to change the handler at will here, since all + signals are currently blocked. */ + oact->sa_handler = signal (sig, SIG_DFL); + if (oact->sa_handler == SIG_ERR) + goto failure; + signal (sig, oact->sa_handler); + oact->sa_flags = SA_RESETHAND | SA_NODEFER; + sigemptyset (&oact->sa_mask); + } + } + + if (act) + { + /* Safe to install the handler before updating action_array, + since all signals are currently blocked. */ + if (act->sa_handler == SIG_DFL || act->sa_handler == SIG_IGN) + { + if (signal (sig, act->sa_handler) == SIG_ERR) + goto failure; + action_array[sig].sa_handler = NULL; + } + else + { + if (signal (sig, sigaction_handler) == SIG_ERR) + goto failure; + action_array[sig] = *act; + } + } + sigprocmask (SIG_SETMASK, &oldmask, NULL); + return 0; + + failure: + saved_errno = errno; + sigprocmask (SIG_SETMASK, &oldmask, NULL); + errno = saved_errno; + return -1; +} diff --git a/gettext-tools/gnulib-lib/signal.in.h b/gettext-tools/gnulib-lib/signal.in.h new file mode 100644 index 0000000..925e16f --- /dev/null +++ b/gettext-tools/gnulib-lib/signal.in.h @@ -0,0 +1,461 @@ +/* A GNU-like . + + Copyright (C) 2006-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +#if defined __need_sig_atomic_t || defined __need_sigset_t || defined _GL_ALREADY_INCLUDING_SIGNAL_H || (defined _SIGNAL_H && !defined __SIZEOF_PTHREAD_MUTEX_T) +/* Special invocation convention: + - Inside glibc header files. + - On glibc systems we have a sequence of nested includes + -> -> . + In this situation, the functions are not yet declared, therefore we cannot + provide the C++ aliases. + - On glibc systems with GCC 4.3 we have a sequence of nested includes + -> -> -> . + In this situation, some of the functions are not yet declared, therefore + we cannot provide the C++ aliases. */ + +# @INCLUDE_NEXT@ @NEXT_SIGNAL_H@ + +#else +/* Normal invocation convention. */ + +#ifndef _@GUARD_PREFIX@_SIGNAL_H + +#define _GL_ALREADY_INCLUDING_SIGNAL_H + +/* Define pid_t, uid_t. + Also, mingw defines sigset_t not in , but in . + On Solaris 10, includes , which eventually includes + us; so include now, before the second inclusion guard. */ +#include + +/* The include_next requires a split double-inclusion guard. */ +#@INCLUDE_NEXT@ @NEXT_SIGNAL_H@ + +#undef _GL_ALREADY_INCLUDING_SIGNAL_H + +#ifndef _@GUARD_PREFIX@_SIGNAL_H +#define _@GUARD_PREFIX@_SIGNAL_H + +/* Mac OS X 10.3, FreeBSD 6.4, OpenBSD 3.8, OSF/1 4.0, Solaris 2.6 declare + pthread_sigmask in , not in . + But avoid namespace pollution on glibc systems.*/ +#if (@GNULIB_PTHREAD_SIGMASK@ || defined GNULIB_POSIXCHECK) \ + && ((defined __APPLE__ && defined __MACH__) || defined __FreeBSD__ || defined __OpenBSD__ || defined __osf__ || defined __sun) \ + && ! defined __GLIBC__ +# include +#endif + +/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ + +/* The definition of _GL_ARG_NONNULL is copied here. */ + +/* The definition of _GL_WARN_ON_USE is copied here. */ + +/* On AIX, sig_atomic_t already includes volatile. C99 requires that + 'volatile sig_atomic_t' ignore the extra modifier, but C89 did not. + Hence, redefine this to a non-volatile type as needed. */ +#if ! @HAVE_TYPE_VOLATILE_SIG_ATOMIC_T@ +# if !GNULIB_defined_sig_atomic_t +typedef int rpl_sig_atomic_t; +# undef sig_atomic_t +# define sig_atomic_t rpl_sig_atomic_t +# define GNULIB_defined_sig_atomic_t 1 +# endif +#endif + +/* A set or mask of signals. */ +#if !@HAVE_SIGSET_T@ +# if !GNULIB_defined_sigset_t +typedef unsigned int sigset_t; +# define GNULIB_defined_sigset_t 1 +# endif +#endif + +/* Define sighandler_t, the type of signal handlers. A GNU extension. */ +#if !@HAVE_SIGHANDLER_T@ +# ifdef __cplusplus +extern "C" { +# endif +# if !GNULIB_defined_sighandler_t +typedef void (*sighandler_t) (int); +# define GNULIB_defined_sighandler_t 1 +# endif +# ifdef __cplusplus +} +# endif +#endif + + +#if @GNULIB_SIGNAL_H_SIGPIPE@ +# ifndef SIGPIPE +/* Define SIGPIPE to a value that does not overlap with other signals. */ +# define SIGPIPE 13 +# define GNULIB_defined_SIGPIPE 1 +/* To actually use SIGPIPE, you also need the gnulib modules 'sigprocmask', + 'write', 'stdio'. */ +# endif +#endif + + +/* Maximum signal number + 1. */ +#ifndef NSIG +# if defined __TANDEM +# define NSIG 32 +# endif +#endif + + +#if @GNULIB_PTHREAD_SIGMASK@ +# if @REPLACE_PTHREAD_SIGMASK@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef pthread_sigmask +# define pthread_sigmask rpl_pthread_sigmask +# endif +_GL_FUNCDECL_RPL (pthread_sigmask, int, + (int how, const sigset_t *new_mask, sigset_t *old_mask)); +_GL_CXXALIAS_RPL (pthread_sigmask, int, + (int how, const sigset_t *new_mask, sigset_t *old_mask)); +# else +# if !@HAVE_PTHREAD_SIGMASK@ +_GL_FUNCDECL_SYS (pthread_sigmask, int, + (int how, const sigset_t *new_mask, sigset_t *old_mask)); +# endif +_GL_CXXALIAS_SYS (pthread_sigmask, int, + (int how, const sigset_t *new_mask, sigset_t *old_mask)); +# endif +_GL_CXXALIASWARN (pthread_sigmask); +#elif defined GNULIB_POSIXCHECK +# undef pthread_sigmask +# if HAVE_RAW_DECL_PTHREAD_SIGMASK +_GL_WARN_ON_USE (pthread_sigmask, "pthread_sigmask is not portable - " + "use gnulib module pthread_sigmask for portability"); +# endif +#endif + + +#if @GNULIB_RAISE@ +# if @REPLACE_RAISE@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef raise +# define raise rpl_raise +# endif +_GL_FUNCDECL_RPL (raise, int, (int sig)); +_GL_CXXALIAS_RPL (raise, int, (int sig)); +# else +# if !@HAVE_RAISE@ +_GL_FUNCDECL_SYS (raise, int, (int sig)); +# endif +_GL_CXXALIAS_SYS (raise, int, (int sig)); +# endif +_GL_CXXALIASWARN (raise); +#elif defined GNULIB_POSIXCHECK +# undef raise +/* Assume raise is always declared. */ +_GL_WARN_ON_USE (raise, "raise can crash on native Windows - " + "use gnulib module raise for portability"); +#endif + + +#if @GNULIB_SIGPROCMASK@ +# if !@HAVE_POSIX_SIGNALBLOCKING@ + +# ifndef GNULIB_defined_signal_blocking +# define GNULIB_defined_signal_blocking 1 +# endif + +/* Maximum signal number + 1. */ +# ifndef NSIG +# define NSIG 32 +# endif + +/* This code supports only 32 signals. */ +# if !GNULIB_defined_verify_NSIG_constraint +typedef int verify_NSIG_constraint[NSIG <= 32 ? 1 : -1]; +# define GNULIB_defined_verify_NSIG_constraint 1 +# endif + +# endif + +/* When also using extern inline, suppress the use of static inline in + standard headers of problematic Apple configurations, as Libc at + least through Libc-825.26 (2013-04-09) mishandles it; see, e.g., + . + Perhaps Apple will fix this some day. */ +#if (defined _GL_EXTERN_INLINE_IN_USE && defined __APPLE__ \ + && (defined __i386__ || defined __x86_64__)) +# undef sigaddset +# undef sigdelset +# undef sigemptyset +# undef sigfillset +# undef sigismember +#endif + +/* Test whether a given signal is contained in a signal set. */ +# if @HAVE_POSIX_SIGNALBLOCKING@ +/* This function is defined as a macro on Mac OS X. */ +# if defined __cplusplus && defined GNULIB_NAMESPACE +# undef sigismember +# endif +# else +_GL_FUNCDECL_SYS (sigismember, int, (const sigset_t *set, int sig) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (sigismember, int, (const sigset_t *set, int sig)); +_GL_CXXALIASWARN (sigismember); + +/* Initialize a signal set to the empty set. */ +# if @HAVE_POSIX_SIGNALBLOCKING@ +/* This function is defined as a macro on Mac OS X. */ +# if defined __cplusplus && defined GNULIB_NAMESPACE +# undef sigemptyset +# endif +# else +_GL_FUNCDECL_SYS (sigemptyset, int, (sigset_t *set) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (sigemptyset, int, (sigset_t *set)); +_GL_CXXALIASWARN (sigemptyset); + +/* Add a signal to a signal set. */ +# if @HAVE_POSIX_SIGNALBLOCKING@ +/* This function is defined as a macro on Mac OS X. */ +# if defined __cplusplus && defined GNULIB_NAMESPACE +# undef sigaddset +# endif +# else +_GL_FUNCDECL_SYS (sigaddset, int, (sigset_t *set, int sig) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (sigaddset, int, (sigset_t *set, int sig)); +_GL_CXXALIASWARN (sigaddset); + +/* Remove a signal from a signal set. */ +# if @HAVE_POSIX_SIGNALBLOCKING@ +/* This function is defined as a macro on Mac OS X. */ +# if defined __cplusplus && defined GNULIB_NAMESPACE +# undef sigdelset +# endif +# else +_GL_FUNCDECL_SYS (sigdelset, int, (sigset_t *set, int sig) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (sigdelset, int, (sigset_t *set, int sig)); +_GL_CXXALIASWARN (sigdelset); + +/* Fill a signal set with all possible signals. */ +# if @HAVE_POSIX_SIGNALBLOCKING@ +/* This function is defined as a macro on Mac OS X. */ +# if defined __cplusplus && defined GNULIB_NAMESPACE +# undef sigfillset +# endif +# else +_GL_FUNCDECL_SYS (sigfillset, int, (sigset_t *set) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (sigfillset, int, (sigset_t *set)); +_GL_CXXALIASWARN (sigfillset); + +/* Return the set of those blocked signals that are pending. */ +# if !@HAVE_POSIX_SIGNALBLOCKING@ +_GL_FUNCDECL_SYS (sigpending, int, (sigset_t *set) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (sigpending, int, (sigset_t *set)); +_GL_CXXALIASWARN (sigpending); + +/* If OLD_SET is not NULL, put the current set of blocked signals in *OLD_SET. + Then, if SET is not NULL, affect the current set of blocked signals by + combining it with *SET as indicated in OPERATION. + In this implementation, you are not allowed to change a signal handler + while the signal is blocked. */ +# if !@HAVE_POSIX_SIGNALBLOCKING@ +# define SIG_BLOCK 0 /* blocked_set = blocked_set | *set; */ +# define SIG_SETMASK 1 /* blocked_set = *set; */ +# define SIG_UNBLOCK 2 /* blocked_set = blocked_set & ~*set; */ +_GL_FUNCDECL_SYS (sigprocmask, int, + (int operation, const sigset_t *set, sigset_t *old_set)); +# endif +_GL_CXXALIAS_SYS (sigprocmask, int, + (int operation, const sigset_t *set, sigset_t *old_set)); +_GL_CXXALIASWARN (sigprocmask); + +/* Install the handler FUNC for signal SIG, and return the previous + handler. */ +# ifdef __cplusplus +extern "C" { +# endif +# if !GNULIB_defined_function_taking_int_returning_void_t +typedef void (*_gl_function_taking_int_returning_void_t) (int); +# define GNULIB_defined_function_taking_int_returning_void_t 1 +# endif +# ifdef __cplusplus +} +# endif +# if !@HAVE_POSIX_SIGNALBLOCKING@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define signal rpl_signal +# endif +_GL_FUNCDECL_RPL (signal, _gl_function_taking_int_returning_void_t, + (int sig, _gl_function_taking_int_returning_void_t func)); +_GL_CXXALIAS_RPL (signal, _gl_function_taking_int_returning_void_t, + (int sig, _gl_function_taking_int_returning_void_t func)); +# else +_GL_CXXALIAS_SYS (signal, _gl_function_taking_int_returning_void_t, + (int sig, _gl_function_taking_int_returning_void_t func)); +# endif +_GL_CXXALIASWARN (signal); + +# if !@HAVE_POSIX_SIGNALBLOCKING@ && GNULIB_defined_SIGPIPE +/* Raise signal SIGPIPE. */ +_GL_EXTERN_C int _gl_raise_SIGPIPE (void); +# endif + +#elif defined GNULIB_POSIXCHECK +# undef sigaddset +# if HAVE_RAW_DECL_SIGADDSET +_GL_WARN_ON_USE (sigaddset, "sigaddset is unportable - " + "use the gnulib module sigprocmask for portability"); +# endif +# undef sigdelset +# if HAVE_RAW_DECL_SIGDELSET +_GL_WARN_ON_USE (sigdelset, "sigdelset is unportable - " + "use the gnulib module sigprocmask for portability"); +# endif +# undef sigemptyset +# if HAVE_RAW_DECL_SIGEMPTYSET +_GL_WARN_ON_USE (sigemptyset, "sigemptyset is unportable - " + "use the gnulib module sigprocmask for portability"); +# endif +# undef sigfillset +# if HAVE_RAW_DECL_SIGFILLSET +_GL_WARN_ON_USE (sigfillset, "sigfillset is unportable - " + "use the gnulib module sigprocmask for portability"); +# endif +# undef sigismember +# if HAVE_RAW_DECL_SIGISMEMBER +_GL_WARN_ON_USE (sigismember, "sigismember is unportable - " + "use the gnulib module sigprocmask for portability"); +# endif +# undef sigpending +# if HAVE_RAW_DECL_SIGPENDING +_GL_WARN_ON_USE (sigpending, "sigpending is unportable - " + "use the gnulib module sigprocmask for portability"); +# endif +# undef sigprocmask +# if HAVE_RAW_DECL_SIGPROCMASK +_GL_WARN_ON_USE (sigprocmask, "sigprocmask is unportable - " + "use the gnulib module sigprocmask for portability"); +# endif +#endif /* @GNULIB_SIGPROCMASK@ */ + + +#if @GNULIB_SIGACTION@ +# if !@HAVE_SIGACTION@ + +# if !@HAVE_SIGINFO_T@ + +# if !GNULIB_defined_siginfo_types + +/* Present to allow compilation, but unsupported by gnulib. */ +union sigval +{ + int sival_int; + void *sival_ptr; +}; + +/* Present to allow compilation, but unsupported by gnulib. */ +struct siginfo_t +{ + int si_signo; + int si_code; + int si_errno; + pid_t si_pid; + uid_t si_uid; + void *si_addr; + int si_status; + long si_band; + union sigval si_value; +}; +typedef struct siginfo_t siginfo_t; + +# define GNULIB_defined_siginfo_types 1 +# endif + +# endif /* !@HAVE_SIGINFO_T@ */ + +/* We assume that platforms which lack the sigaction() function also lack + the 'struct sigaction' type, and vice versa. */ + +# if !GNULIB_defined_struct_sigaction + +struct sigaction +{ + union + { + void (*_sa_handler) (int); + /* Present to allow compilation, but unsupported by gnulib. POSIX + says that implementations may, but not must, make sa_sigaction + overlap with sa_handler, but we know of no implementation where + they do not overlap. */ + void (*_sa_sigaction) (int, siginfo_t *, void *); + } _sa_func; + sigset_t sa_mask; + /* Not all POSIX flags are supported. */ + int sa_flags; +}; +# define sa_handler _sa_func._sa_handler +# define sa_sigaction _sa_func._sa_sigaction +/* Unsupported flags are not present. */ +# define SA_RESETHAND 1 +# define SA_NODEFER 2 +# define SA_RESTART 4 + +# define GNULIB_defined_struct_sigaction 1 +# endif + +_GL_FUNCDECL_SYS (sigaction, int, (int, const struct sigaction *restrict, + struct sigaction *restrict)); + +# elif !@HAVE_STRUCT_SIGACTION_SA_SIGACTION@ + +# define sa_sigaction sa_handler + +# endif /* !@HAVE_SIGACTION@, !@HAVE_STRUCT_SIGACTION_SA_SIGACTION@ */ + +_GL_CXXALIAS_SYS (sigaction, int, (int, const struct sigaction *restrict, + struct sigaction *restrict)); +_GL_CXXALIASWARN (sigaction); + +#elif defined GNULIB_POSIXCHECK +# undef sigaction +# if HAVE_RAW_DECL_SIGACTION +_GL_WARN_ON_USE (sigaction, "sigaction is unportable - " + "use the gnulib module sigaction for portability"); +# endif +#endif + +/* Some systems don't have SA_NODEFER. */ +#ifndef SA_NODEFER +# define SA_NODEFER 0 +#endif + + +#endif /* _@GUARD_PREFIX@_SIGNAL_H */ +#endif /* _@GUARD_PREFIX@_SIGNAL_H */ +#endif diff --git a/gettext-tools/gnulib-lib/sigprocmask.c b/gettext-tools/gnulib-lib/sigprocmask.c new file mode 100644 index 0000000..506a51f --- /dev/null +++ b/gettext-tools/gnulib-lib/sigprocmask.c @@ -0,0 +1,349 @@ +/* POSIX compatible signal blocking. + Copyright (C) 2006-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include + +#include +#include +#include + +#if HAVE_MSVC_INVALID_PARAMETER_HANDLER +# include "msvc-inval.h" +#endif + +/* We assume that a platform without POSIX signal blocking functions + also does not have the POSIX sigaction() function, only the + signal() function. We also assume signal() has SysV semantics, + where any handler is uninstalled prior to being invoked. This is + true for native Windows platforms. */ + +/* We use raw signal(), but also provide a wrapper rpl_signal() so + that applications can query or change a blocked signal. */ +#undef signal + +/* Provide invalid signal numbers as fallbacks if the uncatchable + signals are not defined. */ +#ifndef SIGKILL +# define SIGKILL (-1) +#endif +#ifndef SIGSTOP +# define SIGSTOP (-1) +#endif + +/* On native Windows, as of 2008, the signal SIGABRT_COMPAT is an alias + for the signal SIGABRT. Only one signal handler is stored for both + SIGABRT and SIGABRT_COMPAT. SIGABRT_COMPAT is not a signal of its own. */ +#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ +# undef SIGABRT_COMPAT +# define SIGABRT_COMPAT 6 +#endif +#ifdef SIGABRT_COMPAT +# define SIGABRT_COMPAT_MASK (1U << SIGABRT_COMPAT) +#else +# define SIGABRT_COMPAT_MASK 0 +#endif + +typedef void (*handler_t) (int); + +#if HAVE_MSVC_INVALID_PARAMETER_HANDLER +static handler_t +signal_nothrow (int sig, handler_t handler) +{ + handler_t result; + + TRY_MSVC_INVAL + { + result = signal (sig, handler); + } + CATCH_MSVC_INVAL + { + result = SIG_ERR; + errno = EINVAL; + } + DONE_MSVC_INVAL; + + return result; +} +# define signal signal_nothrow +#endif + +/* Handling of gnulib defined signals. */ + +#if GNULIB_defined_SIGPIPE +static handler_t SIGPIPE_handler = SIG_DFL; +#endif + +#if GNULIB_defined_SIGPIPE +static handler_t +ext_signal (int sig, handler_t handler) +{ + switch (sig) + { + case SIGPIPE: + { + handler_t old_handler = SIGPIPE_handler; + SIGPIPE_handler = handler; + return old_handler; + } + default: /* System defined signal */ + return signal (sig, handler); + } +} +# undef signal +# define signal ext_signal +#endif + +int +sigismember (const sigset_t *set, int sig) +{ + if (sig >= 0 && sig < NSIG) + { + #ifdef SIGABRT_COMPAT + if (sig == SIGABRT_COMPAT) + sig = SIGABRT; + #endif + + return (*set >> sig) & 1; + } + else + return 0; +} + +int +sigemptyset (sigset_t *set) +{ + *set = 0; + return 0; +} + +int +sigaddset (sigset_t *set, int sig) +{ + if (sig >= 0 && sig < NSIG) + { + #ifdef SIGABRT_COMPAT + if (sig == SIGABRT_COMPAT) + sig = SIGABRT; + #endif + + *set |= 1U << sig; + return 0; + } + else + { + errno = EINVAL; + return -1; + } +} + +int +sigdelset (sigset_t *set, int sig) +{ + if (sig >= 0 && sig < NSIG) + { + #ifdef SIGABRT_COMPAT + if (sig == SIGABRT_COMPAT) + sig = SIGABRT; + #endif + + *set &= ~(1U << sig); + return 0; + } + else + { + errno = EINVAL; + return -1; + } +} + + +int +sigfillset (sigset_t *set) +{ + *set = ((2U << (NSIG - 1)) - 1) & ~ SIGABRT_COMPAT_MASK; + return 0; +} + +/* Set of currently blocked signals. */ +static volatile sigset_t blocked_set /* = 0 */; + +/* Set of currently blocked and pending signals. */ +static volatile sig_atomic_t pending_array[NSIG] /* = { 0 } */; + +/* Signal handler that is installed for blocked signals. */ +static void +blocked_handler (int sig) +{ + /* Reinstall the handler, in case the signal occurs multiple times + while blocked. There is an inherent race where an asynchronous + signal in between when the kernel uninstalled the handler and + when we reinstall it will trigger the default handler; oh + well. */ + signal (sig, blocked_handler); + if (sig >= 0 && sig < NSIG) + pending_array[sig] = 1; +} + +int +sigpending (sigset_t *set) +{ + sigset_t pending = 0; + int sig; + + for (sig = 0; sig < NSIG; sig++) + if (pending_array[sig]) + pending |= 1U << sig; + *set = pending; + return 0; +} + +/* The previous signal handlers. + Only the array elements corresponding to blocked signals are relevant. */ +static volatile handler_t old_handlers[NSIG]; + +int +sigprocmask (int operation, const sigset_t *set, sigset_t *old_set) +{ + if (old_set != NULL) + *old_set = blocked_set; + + if (set != NULL) + { + sigset_t new_blocked_set; + sigset_t to_unblock; + sigset_t to_block; + + switch (operation) + { + case SIG_BLOCK: + new_blocked_set = blocked_set | *set; + break; + case SIG_SETMASK: + new_blocked_set = *set; + break; + case SIG_UNBLOCK: + new_blocked_set = blocked_set & ~*set; + break; + default: + errno = EINVAL; + return -1; + } + to_unblock = blocked_set & ~new_blocked_set; + to_block = new_blocked_set & ~blocked_set; + + if (to_block != 0) + { + int sig; + + for (sig = 0; sig < NSIG; sig++) + if ((to_block >> sig) & 1) + { + pending_array[sig] = 0; + if ((old_handlers[sig] = signal (sig, blocked_handler)) != SIG_ERR) + blocked_set |= 1U << sig; + } + } + + if (to_unblock != 0) + { + sig_atomic_t received[NSIG]; + int sig; + + for (sig = 0; sig < NSIG; sig++) + if ((to_unblock >> sig) & 1) + { + if (signal (sig, old_handlers[sig]) != blocked_handler) + /* The application changed a signal handler while the signal + was blocked, bypassing our rpl_signal replacement. + We don't support this. */ + abort (); + received[sig] = pending_array[sig]; + blocked_set &= ~(1U << sig); + pending_array[sig] = 0; + } + else + received[sig] = 0; + + for (sig = 0; sig < NSIG; sig++) + if (received[sig]) + raise (sig); + } + } + return 0; +} + +/* Install the handler FUNC for signal SIG, and return the previous + handler. */ +handler_t +rpl_signal (int sig, handler_t handler) +{ + /* We must provide a wrapper, so that a user can query what handler + they installed even if that signal is currently blocked. */ + if (sig >= 0 && sig < NSIG && sig != SIGKILL && sig != SIGSTOP + && handler != SIG_ERR) + { + #ifdef SIGABRT_COMPAT + if (sig == SIGABRT_COMPAT) + sig = SIGABRT; + #endif + + if (blocked_set & (1U << sig)) + { + /* POSIX states that sigprocmask and signal are both + async-signal-safe. This is not true of our + implementation - there is a slight data race where an + asynchronous interrupt on signal A can occur after we + install blocked_handler but before we have updated + old_handlers for signal B, such that handler A can see + stale information if it calls signal(B). Oh well - + signal handlers really shouldn't try to manipulate the + installed handlers of unrelated signals. */ + handler_t result = old_handlers[sig]; + old_handlers[sig] = handler; + return result; + } + else + return signal (sig, handler); + } + else + { + errno = EINVAL; + return SIG_ERR; + } +} + +#if GNULIB_defined_SIGPIPE +/* Raise the signal SIGPIPE. */ +int +_gl_raise_SIGPIPE (void) +{ + if (blocked_set & (1U << SIGPIPE)) + pending_array[SIGPIPE] = 1; + else + { + handler_t handler = SIGPIPE_handler; + if (handler == SIG_DFL) + exit (128 + SIGPIPE); + else if (handler != SIG_IGN) + (*handler) (SIGPIPE); + } + return 0; +} +#endif diff --git a/gettext-tools/gnulib-lib/size_max.h b/gettext-tools/gnulib-lib/size_max.h new file mode 100644 index 0000000..461ff1c --- /dev/null +++ b/gettext-tools/gnulib-lib/size_max.h @@ -0,0 +1,30 @@ +/* size_max.h -- declare SIZE_MAX through system headers + Copyright (C) 2005-2006, 2009-2014 Free Software Foundation, Inc. + Written by Simon Josefsson. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . */ + +#ifndef GNULIB_SIZE_MAX_H +#define GNULIB_SIZE_MAX_H + +/* Get SIZE_MAX declaration on systems like Solaris 7/8/9. */ +# include +/* Get SIZE_MAX declaration on systems like glibc 2. */ +# if HAVE_STDINT_H +# include +# endif +/* On systems where these include files don't define it, SIZE_MAX is defined + in config.h. */ + +#endif /* GNULIB_SIZE_MAX_H */ diff --git a/gettext-tools/gnulib-lib/snprintf.c b/gettext-tools/gnulib-lib/snprintf.c new file mode 100644 index 0000000..ea1321c --- /dev/null +++ b/gettext-tools/gnulib-lib/snprintf.c @@ -0,0 +1,71 @@ +/* Formatted output to strings. + Copyright (C) 2004, 2006-2014 Free Software Foundation, Inc. + Written by Simon Josefsson and Paul Eggert. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, see . */ + +#include + +/* Specification. */ +#include + +#include +#include +#include +#include +#include + +#include "vasnprintf.h" + +/* Print formatted output to string STR. Similar to sprintf, but + additional length SIZE limit how much is written into STR. Returns + string length of formatted string (which may be larger than SIZE). + STR may be NULL, in which case nothing will be written. On error, + return a negative value. */ +int +snprintf (char *str, size_t size, const char *format, ...) +{ + char *output; + size_t len; + size_t lenbuf = size; + va_list args; + + va_start (args, format); + output = vasnprintf (str, &lenbuf, format, args); + len = lenbuf; + va_end (args); + + if (!output) + return -1; + + if (output != str) + { + if (size) + { + size_t pruned_len = (len < size ? len : size - 1); + memcpy (str, output, pruned_len); + str[pruned_len] = '\0'; + } + + free (output); + } + + if (INT_MAX < len) + { + errno = EOVERFLOW; + return -1; + } + + return len; +} diff --git a/gettext-tools/gnulib-lib/spawn-pipe.c b/gettext-tools/gnulib-lib/spawn-pipe.c new file mode 100644 index 0000000..b7fa95b --- /dev/null +++ b/gettext-tools/gnulib-lib/spawn-pipe.c @@ -0,0 +1,454 @@ +/* Creation of subprocesses, communicating via pipes. + Copyright (C) 2001-2004, 2006-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2001. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + + +#include + +/* Specification. */ +#include "spawn-pipe.h" + +#include +#include +#include +#include +#include + +#include "error.h" +#include "fatal-signal.h" +#include "unistd-safer.h" +#include "wait-process.h" +#include "gettext.h" + +#define _(str) gettext (str) + +#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ + +/* Native Windows API. */ +# include +# include "w32spawn.h" + +#else + +/* Unix API. */ +# include + +#endif + +/* environ is the exported symbol referencing the internal + __cygwin_environ variable on cygwin64: + . */ +#if defined __CYGWIN__ && defined __x86_64__ +extern DLL_VARIABLE char **environ; +#endif + + +#ifdef EINTR + +/* EINTR handling for close(). + These functions can return -1/EINTR even though we don't have any + signal handlers set up, namely when we get interrupted via SIGSTOP. */ + +static int +nonintr_close (int fd) +{ + int retval; + + do + retval = close (fd); + while (retval < 0 && errno == EINTR); + + return retval; +} +#define close nonintr_close + +#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ +static int +nonintr_open (const char *pathname, int oflag, mode_t mode) +{ + int retval; + + do + retval = open (pathname, oflag, mode); + while (retval < 0 && errno == EINTR); + + return retval; +} +# undef open /* avoid warning on VMS */ +# define open nonintr_open +#endif + +#endif + + +/* Open a pipe connected to a child process. + * + * write system read + * parent -> fd[1] -> STDIN_FILENO -> child if pipe_stdin + * parent <- fd[0] <- STDOUT_FILENO <- child if pipe_stdout + * read system write + * + * At least one of pipe_stdin, pipe_stdout must be true. + * pipe_stdin and prog_stdin together determine the child's standard input. + * pipe_stdout and prog_stdout together determine the child's standard output. + * If pipe_stdin is true, prog_stdin is ignored. + * If pipe_stdout is true, prog_stdout is ignored. + */ +static pid_t +create_pipe (const char *progname, + const char *prog_path, char **prog_argv, + bool pipe_stdin, bool pipe_stdout, + const char *prog_stdin, const char *prog_stdout, + bool null_stderr, + bool slave_process, bool exit_on_error, + int fd[2]) +{ +#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ + + /* Native Windows API. + This uses _pipe(), dup2(), and spawnv(). It could also be implemented + using the low-level functions CreatePipe(), DuplicateHandle(), + CreateProcess() and _open_osfhandle(); see the GNU make and GNU clisp + and cvs source code. */ + int ifd[2]; + int ofd[2]; + int orig_stdin; + int orig_stdout; + int orig_stderr; + int child; + int nulloutfd; + int stdinfd; + int stdoutfd; + int saved_errno; + + /* FIXME: Need to free memory allocated by prepare_spawn. */ + prog_argv = prepare_spawn (prog_argv); + + if (pipe_stdout) + if (pipe2_safer (ifd, O_BINARY | O_CLOEXEC) < 0) + error (EXIT_FAILURE, errno, _("cannot create pipe")); + if (pipe_stdin) + if (pipe2_safer (ofd, O_BINARY | O_CLOEXEC) < 0) + error (EXIT_FAILURE, errno, _("cannot create pipe")); +/* Data flow diagram: + * + * write system read + * parent -> ofd[1] -> ofd[0] -> child if pipe_stdin + * parent <- ifd[0] <- ifd[1] <- child if pipe_stdout + * read system write + * + */ + + /* Save standard file handles of parent process. */ + if (pipe_stdin || prog_stdin != NULL) + orig_stdin = dup_safer_noinherit (STDIN_FILENO); + if (pipe_stdout || prog_stdout != NULL) + orig_stdout = dup_safer_noinherit (STDOUT_FILENO); + if (null_stderr) + orig_stderr = dup_safer_noinherit (STDERR_FILENO); + child = -1; + + /* Create standard file handles of child process. */ + nulloutfd = -1; + stdinfd = -1; + stdoutfd = -1; + if ((!pipe_stdin || dup2 (ofd[0], STDIN_FILENO) >= 0) + && (!pipe_stdout || dup2 (ifd[1], STDOUT_FILENO) >= 0) + && (!null_stderr + || ((nulloutfd = open ("NUL", O_RDWR, 0)) >= 0 + && (nulloutfd == STDERR_FILENO + || (dup2 (nulloutfd, STDERR_FILENO) >= 0 + && close (nulloutfd) >= 0)))) + && (pipe_stdin + || prog_stdin == NULL + || ((stdinfd = open (prog_stdin, O_RDONLY, 0)) >= 0 + && (stdinfd == STDIN_FILENO + || (dup2 (stdinfd, STDIN_FILENO) >= 0 + && close (stdinfd) >= 0)))) + && (pipe_stdout + || prog_stdout == NULL + || ((stdoutfd = open (prog_stdout, O_WRONLY, 0)) >= 0 + && (stdoutfd == STDOUT_FILENO + || (dup2 (stdoutfd, STDOUT_FILENO) >= 0 + && close (stdoutfd) >= 0))))) + /* The child process doesn't inherit ifd[0], ifd[1], ofd[0], ofd[1], + but it inherits all open()ed or dup2()ed file handles (which is what + we want in the case of STD*_FILENO). */ + /* Use spawnvpe and pass the environment explicitly. This is needed if + the program has modified the environment using putenv() or [un]setenv(). + On Windows, programs have two environments, one in the "environment + block" of the process and managed through SetEnvironmentVariable(), and + one inside the process, in the location retrieved by the 'environ' + macro. When using spawnvp() without 'e', the child process inherits a + copy of the environment block - ignoring the effects of putenv() and + [un]setenv(). */ + { + child = spawnvpe (P_NOWAIT, prog_path, (const char **) prog_argv, + (const char **) environ); + if (child < 0 && errno == ENOEXEC) + { + /* prog is not a native executable. Try to execute it as a + shell script. Note that prepare_spawn() has already prepended + a hidden element "sh.exe" to prog_argv. */ + --prog_argv; + child = spawnvpe (P_NOWAIT, prog_argv[0], (const char **) prog_argv, + (const char **) environ); + } + } + if (child == -1) + saved_errno = errno; + if (stdinfd >= 0) + close (stdinfd); + if (stdoutfd >= 0) + close (stdoutfd); + if (nulloutfd >= 0) + close (nulloutfd); + + /* Restore standard file handles of parent process. */ + if (null_stderr) + undup_safer_noinherit (orig_stderr, STDERR_FILENO); + if (pipe_stdout || prog_stdout != NULL) + undup_safer_noinherit (orig_stdout, STDOUT_FILENO); + if (pipe_stdin || prog_stdin != NULL) + undup_safer_noinherit (orig_stdin, STDIN_FILENO); + + if (pipe_stdin) + close (ofd[0]); + if (pipe_stdout) + close (ifd[1]); + if (child == -1) + { + if (exit_on_error || !null_stderr) + error (exit_on_error ? EXIT_FAILURE : 0, saved_errno, + _("%s subprocess failed"), progname); + if (pipe_stdout) + close (ifd[0]); + if (pipe_stdin) + close (ofd[1]); + errno = saved_errno; + return -1; + } + + if (pipe_stdout) + fd[0] = ifd[0]; + if (pipe_stdin) + fd[1] = ofd[1]; + return child; + +#else + + /* Unix API. */ + int ifd[2]; + int ofd[2]; + sigset_t blocked_signals; + posix_spawn_file_actions_t actions; + bool actions_allocated; + posix_spawnattr_t attrs; + bool attrs_allocated; + int err; + pid_t child; + + if (pipe_stdout) + if (pipe_safer (ifd) < 0) + error (EXIT_FAILURE, errno, _("cannot create pipe")); + if (pipe_stdin) + if (pipe_safer (ofd) < 0) + error (EXIT_FAILURE, errno, _("cannot create pipe")); +/* Data flow diagram: + * + * write system read + * parent -> ofd[1] -> ofd[0] -> child if pipe_stdin + * parent <- ifd[0] <- ifd[1] <- child if pipe_stdout + * read system write + * + */ + + if (slave_process) + { + sigprocmask (SIG_SETMASK, NULL, &blocked_signals); + block_fatal_signals (); + } + actions_allocated = false; + attrs_allocated = false; + if ((err = posix_spawn_file_actions_init (&actions)) != 0 + || (actions_allocated = true, + (pipe_stdin + && (err = posix_spawn_file_actions_adddup2 (&actions, + ofd[0], STDIN_FILENO)) + != 0) + || (pipe_stdout + && (err = posix_spawn_file_actions_adddup2 (&actions, + ifd[1], STDOUT_FILENO)) + != 0) + || (pipe_stdin + && (err = posix_spawn_file_actions_addclose (&actions, ofd[0])) + != 0) + || (pipe_stdout + && (err = posix_spawn_file_actions_addclose (&actions, ifd[1])) + != 0) + || (pipe_stdin + && (err = posix_spawn_file_actions_addclose (&actions, ofd[1])) + != 0) + || (pipe_stdout + && (err = posix_spawn_file_actions_addclose (&actions, ifd[0])) + != 0) + || (null_stderr + && (err = posix_spawn_file_actions_addopen (&actions, + STDERR_FILENO, + "/dev/null", O_RDWR, + 0)) + != 0) + || (!pipe_stdin + && prog_stdin != NULL + && (err = posix_spawn_file_actions_addopen (&actions, + STDIN_FILENO, + prog_stdin, O_RDONLY, + 0)) + != 0) + || (!pipe_stdout + && prog_stdout != NULL + && (err = posix_spawn_file_actions_addopen (&actions, + STDOUT_FILENO, + prog_stdout, O_WRONLY, + 0)) + != 0) + || (slave_process + && ((err = posix_spawnattr_init (&attrs)) != 0 + || (attrs_allocated = true, + (err = posix_spawnattr_setsigmask (&attrs, + &blocked_signals)) + != 0 + || (err = posix_spawnattr_setflags (&attrs, + POSIX_SPAWN_SETSIGMASK)) + != 0))) + || (err = posix_spawnp (&child, prog_path, &actions, + attrs_allocated ? &attrs : NULL, prog_argv, + environ)) + != 0)) + { + if (actions_allocated) + posix_spawn_file_actions_destroy (&actions); + if (attrs_allocated) + posix_spawnattr_destroy (&attrs); + if (slave_process) + unblock_fatal_signals (); + if (exit_on_error || !null_stderr) + error (exit_on_error ? EXIT_FAILURE : 0, err, + _("%s subprocess failed"), progname); + if (pipe_stdout) + { + close (ifd[0]); + close (ifd[1]); + } + if (pipe_stdin) + { + close (ofd[0]); + close (ofd[1]); + } + errno = err; + return -1; + } + posix_spawn_file_actions_destroy (&actions); + if (attrs_allocated) + posix_spawnattr_destroy (&attrs); + if (slave_process) + { + register_slave_subprocess (child); + unblock_fatal_signals (); + } + if (pipe_stdin) + close (ofd[0]); + if (pipe_stdout) + close (ifd[1]); + + if (pipe_stdout) + fd[0] = ifd[0]; + if (pipe_stdin) + fd[1] = ofd[1]; + return child; + +#endif +} + +/* Open a bidirectional pipe. + * + * write system read + * parent -> fd[1] -> STDIN_FILENO -> child + * parent <- fd[0] <- STDOUT_FILENO <- child + * read system write + * + */ +pid_t +create_pipe_bidi (const char *progname, + const char *prog_path, char **prog_argv, + bool null_stderr, + bool slave_process, bool exit_on_error, + int fd[2]) +{ + pid_t result = create_pipe (progname, prog_path, prog_argv, + true, true, NULL, NULL, + null_stderr, slave_process, exit_on_error, + fd); + return result; +} + +/* Open a pipe for input from a child process. + * The child's stdin comes from a file. + * + * read system write + * parent <- fd[0] <- STDOUT_FILENO <- child + * + */ +pid_t +create_pipe_in (const char *progname, + const char *prog_path, char **prog_argv, + const char *prog_stdin, bool null_stderr, + bool slave_process, bool exit_on_error, + int fd[1]) +{ + int iofd[2]; + pid_t result = create_pipe (progname, prog_path, prog_argv, + false, true, prog_stdin, NULL, + null_stderr, slave_process, exit_on_error, + iofd); + if (result != -1) + fd[0] = iofd[0]; + return result; +} + +/* Open a pipe for output to a child process. + * The child's stdout goes to a file. + * + * write system read + * parent -> fd[0] -> STDIN_FILENO -> child + * + */ +pid_t +create_pipe_out (const char *progname, + const char *prog_path, char **prog_argv, + const char *prog_stdout, bool null_stderr, + bool slave_process, bool exit_on_error, + int fd[1]) +{ + int iofd[2]; + pid_t result = create_pipe (progname, prog_path, prog_argv, + true, false, NULL, prog_stdout, + null_stderr, slave_process, exit_on_error, + iofd); + if (result != -1) + fd[0] = iofd[1]; + return result; +} diff --git a/gettext-tools/gnulib-lib/spawn-pipe.h b/gettext-tools/gnulib-lib/spawn-pipe.h new file mode 100644 index 0000000..4e25752 --- /dev/null +++ b/gettext-tools/gnulib-lib/spawn-pipe.h @@ -0,0 +1,147 @@ +/* Creation of subprocesses, communicating via pipes. + Copyright (C) 2001-2003, 2006, 2008-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2001. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _SPAWN_PIPE_H +#define _SPAWN_PIPE_H + +/* Get pid_t. */ +#include +#include +#include + +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* All these functions create a subprocess and don't wait for its termination. + They return the process id of the subprocess. They also return in fd[] + one or two file descriptors for communication with the subprocess. + If the subprocess creation fails: if exit_on_error is true, the main + process exits with an error message; otherwise, an error message is given + if null_stderr is false, then -1 is returned, with errno set, and fd[] + remain uninitialized. + + After finishing communication, the caller should call wait_subprocess() + to get rid of the subprocess in the process table. + + If slave_process is true, the child process will be terminated when its + creator receives a catchable fatal signal or exits normally. If + slave_process is false, the child process will continue running in this + case, until it is lucky enough to attempt to communicate with its creator + and thus get a SIGPIPE signal. + + If exit_on_error is false, a child process id of -1 should be treated the + same way as a subprocess which accepts no input, produces no output and + terminates with exit code 127. Why? Some errors during posix_spawnp() + cause the function posix_spawnp() to return an error code; some other + errors cause the subprocess to exit with return code 127. It is + implementation dependent which error is reported which way. The caller + must treat both cases as equivalent. + + It is recommended that no signal is blocked or ignored (i.e. have a + signal handler with value SIG_IGN) while any of these functions is called. + The reason is that child processes inherit the mask of blocked signals + from their parent (both through posix_spawn() and fork()/exec()); + likewise, signals ignored in the parent are also ignored in the child + (except possibly for SIGCHLD). And POSIX:2001 says [in the description + of exec()]: + "it should be noted that many existing applications wrongly + assume that they start with certain signals set to the default + action and/or unblocked. In particular, applications written + with a simpler signal model that does not include blocking of + signals, such as the one in the ISO C standard, may not behave + properly if invoked with some signals blocked. Therefore, it is + best not to block or ignore signals across execs without explicit + reason to do so, and especially not to block signals across execs + of arbitrary (not closely co-operating) programs." */ + +/* Open a pipe for output to a child process. + * The child's stdout goes to a file. + * + * write system read + * parent -> fd[0] -> STDIN_FILENO -> child + * + * Note: When writing to a child process, it is useful to ignore the SIGPIPE + * signal and the EPIPE error code. + */ +extern pid_t create_pipe_out (const char *progname, + const char *prog_path, char **prog_argv, + const char *prog_stdout, bool null_stderr, + bool slave_process, bool exit_on_error, + int fd[1]); + +/* Open a pipe for input from a child process. + * The child's stdin comes from a file. + * + * read system write + * parent <- fd[0] <- STDOUT_FILENO <- child + * + */ +extern pid_t create_pipe_in (const char *progname, + const char *prog_path, char **prog_argv, + const char *prog_stdin, bool null_stderr, + bool slave_process, bool exit_on_error, + int fd[1]); + +/* Open a bidirectional pipe. + * + * write system read + * parent -> fd[1] -> STDIN_FILENO -> child + * parent <- fd[0] <- STDOUT_FILENO <- child + * read system write + * + * Note: When writing to a child process, it is useful to ignore the SIGPIPE + * signal and the EPIPE error code. + * + * Note: The parent process must be careful to avoid deadlock. + * 1) If you write more than PIPE_MAX bytes or, more generally, if you write + * more bytes than the subprocess can handle at once, the subprocess + * may write its data and wait on you to read it, but you are currently + * busy writing. + * 2) When you don't know ahead of time how many bytes the subprocess + * will produce, the usual technique of calling read (fd, buf, BUFSIZ) + * with a fixed BUFSIZ will, on Linux 2.2.17 and on BSD systems, cause + * the read() call to block until *all* of the buffer has been filled. + * But the subprocess cannot produce more data until you gave it more + * input. But you are currently busy reading from it. + */ +extern pid_t create_pipe_bidi (const char *progname, + const char *prog_path, char **prog_argv, + bool null_stderr, + bool slave_process, bool exit_on_error, + int fd[2]); + +/* The name of the "always silent" device. */ +#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ +/* Native Windows API. */ +# define DEV_NULL "NUL" +#else +/* Unix API. */ +# define DEV_NULL "/dev/null" +#endif + + +#ifdef __cplusplus +} +#endif + + +#endif /* _SPAWN_PIPE_H */ diff --git a/gettext-tools/gnulib-lib/spawn.in.h b/gettext-tools/gnulib-lib/spawn.in.h new file mode 100644 index 0000000..eb76bb0 --- /dev/null +++ b/gettext-tools/gnulib-lib/spawn.in.h @@ -0,0 +1,881 @@ +/* Definitions for POSIX spawn interface. + Copyright (C) 2000, 2003-2004, 2008-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _@GUARD_PREFIX@_SPAWN_H + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +/* The include_next requires a split double-inclusion guard. */ +#if @HAVE_SPAWN_H@ +# @INCLUDE_NEXT@ @NEXT_SPAWN_H@ +#endif + +#ifndef _@GUARD_PREFIX@_SPAWN_H +#define _@GUARD_PREFIX@_SPAWN_H + +/* Get definitions of 'struct sched_param' and 'sigset_t'. + But avoid namespace pollution on glibc systems. */ +#if !(defined __GLIBC__ && !defined __UCLIBC__) +# include +# include +#endif + +#include + +#ifndef __THROW +# define __THROW +#endif + +/* GCC 2.95 and later have "__restrict"; C99 compilers have + "restrict", and "configure" may have defined "restrict". + Other compilers use __restrict, __restrict__, and _Restrict, and + 'configure' might #define 'restrict' to those words, so pick a + different name. */ +#ifndef _Restrict_ +# if 199901L <= __STDC_VERSION__ +# define _Restrict_ restrict +# elif 2 < __GNUC__ || (2 == __GNUC__ && 95 <= __GNUC_MINOR__) +# define _Restrict_ __restrict +# else +# define _Restrict_ +# endif +#endif +/* gcc 3.1 and up support the [restrict] syntax. Don't trust + sys/cdefs.h's definition of __restrict_arr, though, as it + mishandles gcc -ansi -pedantic. */ +#ifndef _Restrict_arr_ +# if ((199901L <= __STDC_VERSION__ \ + || ((3 < __GNUC__ || (3 == __GNUC__ && 1 <= __GNUC_MINOR__)) \ + && !defined __STRICT_ANSI__)) \ + && !defined __GNUG__) +# define _Restrict_arr_ _Restrict_ +# else +# define _Restrict_arr_ +# endif +#endif + +/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ + +/* The definition of _GL_ARG_NONNULL is copied here. */ + +/* The definition of _GL_WARN_ON_USE is copied here. */ + + +/* Data structure to contain attributes for thread creation. */ +#if @REPLACE_POSIX_SPAWN@ +# define posix_spawnattr_t rpl_posix_spawnattr_t +#endif +#if @REPLACE_POSIX_SPAWN@ || !@HAVE_POSIX_SPAWNATTR_T@ +# if !GNULIB_defined_posix_spawnattr_t +typedef struct +{ + short int _flags; + pid_t _pgrp; + sigset_t _sd; + sigset_t _ss; + struct sched_param _sp; + int _policy; + int __pad[16]; +} posix_spawnattr_t; +# define GNULIB_defined_posix_spawnattr_t 1 +# endif +#endif + + +/* Data structure to contain information about the actions to be + performed in the new process with respect to file descriptors. */ +#if @REPLACE_POSIX_SPAWN@ +# define posix_spawn_file_actions_t rpl_posix_spawn_file_actions_t +#endif +#if @REPLACE_POSIX_SPAWN@ || !@HAVE_POSIX_SPAWN_FILE_ACTIONS_T@ +# if !GNULIB_defined_posix_spawn_file_actions_t +typedef struct +{ + int _allocated; + int _used; + struct __spawn_action *_actions; + int __pad[16]; +} posix_spawn_file_actions_t; +# define GNULIB_defined_posix_spawn_file_actions_t 1 +# endif +#endif + + +/* Flags to be set in the 'posix_spawnattr_t'. */ +#if @HAVE_POSIX_SPAWN@ +/* Use the values from the system, but provide the missing ones. */ +# ifndef POSIX_SPAWN_SETSCHEDPARAM +# define POSIX_SPAWN_SETSCHEDPARAM 0 +# endif +# ifndef POSIX_SPAWN_SETSCHEDULER +# define POSIX_SPAWN_SETSCHEDULER 0 +# endif +#else +# if @REPLACE_POSIX_SPAWN@ +/* Use the values from the system, for better compatibility. */ +/* But this implementation does not support AIX extensions. */ +# undef POSIX_SPAWN_FORK_HANDLERS +# else +# define POSIX_SPAWN_RESETIDS 0x01 +# define POSIX_SPAWN_SETPGROUP 0x02 +# define POSIX_SPAWN_SETSIGDEF 0x04 +# define POSIX_SPAWN_SETSIGMASK 0x08 +# define POSIX_SPAWN_SETSCHEDPARAM 0x10 +# define POSIX_SPAWN_SETSCHEDULER 0x20 +# endif +#endif +/* A GNU extension. Use the next free bit position. */ +#define POSIX_SPAWN_USEVFORK \ + ((POSIX_SPAWN_RESETIDS | (POSIX_SPAWN_RESETIDS - 1) \ + | POSIX_SPAWN_SETPGROUP | (POSIX_SPAWN_SETPGROUP - 1) \ + | POSIX_SPAWN_SETSIGDEF | (POSIX_SPAWN_SETSIGDEF - 1) \ + | POSIX_SPAWN_SETSIGMASK | (POSIX_SPAWN_SETSIGMASK - 1) \ + | POSIX_SPAWN_SETSCHEDPARAM \ + | (POSIX_SPAWN_SETSCHEDPARAM > 0 ? POSIX_SPAWN_SETSCHEDPARAM - 1 : 0) \ + | POSIX_SPAWN_SETSCHEDULER \ + | (POSIX_SPAWN_SETSCHEDULER > 0 ? POSIX_SPAWN_SETSCHEDULER - 1 : 0)) \ + + 1) +#if !GNULIB_defined_verify_POSIX_SPAWN_USEVFORK_no_overlap +typedef int verify_POSIX_SPAWN_USEVFORK_no_overlap + [(((POSIX_SPAWN_RESETIDS | POSIX_SPAWN_SETPGROUP + | POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK + | POSIX_SPAWN_SETSCHEDPARAM | POSIX_SPAWN_SETSCHEDULER) + & POSIX_SPAWN_USEVFORK) + == 0) + ? 1 : -1]; +# define GNULIB_defined_verify_POSIX_SPAWN_USEVFORK_no_overlap 1 +#endif + + +#if @GNULIB_POSIX_SPAWN@ +/* Spawn a new process executing PATH with the attributes describes in *ATTRP. + Before running the process perform the actions described in FILE-ACTIONS. + + This function is a possible cancellation points and therefore not + marked with __THROW. */ +# if @REPLACE_POSIX_SPAWN@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define posix_spawn rpl_posix_spawn +# endif +_GL_FUNCDECL_RPL (posix_spawn, int, + (pid_t *_Restrict_ __pid, + const char *_Restrict_ __path, + const posix_spawn_file_actions_t *_Restrict_ __file_actions, + const posix_spawnattr_t *_Restrict_ __attrp, + char *const argv[_Restrict_arr_], + char *const envp[_Restrict_arr_]) + _GL_ARG_NONNULL ((2, 5, 6))); +_GL_CXXALIAS_RPL (posix_spawn, int, + (pid_t *_Restrict_ __pid, + const char *_Restrict_ __path, + const posix_spawn_file_actions_t *_Restrict_ __file_actions, + const posix_spawnattr_t *_Restrict_ __attrp, + char *const argv[_Restrict_arr_], + char *const envp[_Restrict_arr_])); +# else +# if !@HAVE_POSIX_SPAWN@ +_GL_FUNCDECL_SYS (posix_spawn, int, + (pid_t *_Restrict_ __pid, + const char *_Restrict_ __path, + const posix_spawn_file_actions_t *_Restrict_ __file_actions, + const posix_spawnattr_t *_Restrict_ __attrp, + char *const argv[_Restrict_arr_], + char *const envp[_Restrict_arr_]) + _GL_ARG_NONNULL ((2, 5, 6))); +# endif +_GL_CXXALIAS_SYS (posix_spawn, int, + (pid_t *_Restrict_ __pid, + const char *_Restrict_ __path, + const posix_spawn_file_actions_t *_Restrict_ __file_actions, + const posix_spawnattr_t *_Restrict_ __attrp, + char *const argv[_Restrict_arr_], + char *const envp[_Restrict_arr_])); +# endif +_GL_CXXALIASWARN (posix_spawn); +#elif defined GNULIB_POSIXCHECK +# undef posix_spawn +# if HAVE_RAW_DECL_POSIX_SPAWN +_GL_WARN_ON_USE (posix_spawn, "posix_spawn is unportable - " + "use gnulib module posix_spawn for portability"); +# endif +#endif + +#if @GNULIB_POSIX_SPAWNP@ +/* Similar to 'posix_spawn' but search for FILE in the PATH. + + This function is a possible cancellation points and therefore not + marked with __THROW. */ +# if @REPLACE_POSIX_SPAWN@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define posix_spawnp rpl_posix_spawnp +# endif +_GL_FUNCDECL_RPL (posix_spawnp, int, + (pid_t *__pid, const char *__file, + const posix_spawn_file_actions_t *__file_actions, + const posix_spawnattr_t *__attrp, + char *const argv[], char *const envp[]) + _GL_ARG_NONNULL ((2, 5, 6))); +_GL_CXXALIAS_RPL (posix_spawnp, int, + (pid_t *__pid, const char *__file, + const posix_spawn_file_actions_t *__file_actions, + const posix_spawnattr_t *__attrp, + char *const argv[], char *const envp[])); +# else +# if !@HAVE_POSIX_SPAWN@ +_GL_FUNCDECL_SYS (posix_spawnp, int, + (pid_t *__pid, const char *__file, + const posix_spawn_file_actions_t *__file_actions, + const posix_spawnattr_t *__attrp, + char *const argv[], char *const envp[]) + _GL_ARG_NONNULL ((2, 5, 6))); +# endif +_GL_CXXALIAS_SYS (posix_spawnp, int, + (pid_t *__pid, const char *__file, + const posix_spawn_file_actions_t *__file_actions, + const posix_spawnattr_t *__attrp, + char *const argv[], char *const envp[])); +# endif +_GL_CXXALIASWARN (posix_spawnp); +#elif defined GNULIB_POSIXCHECK +# undef posix_spawnp +# if HAVE_RAW_DECL_POSIX_SPAWNP +_GL_WARN_ON_USE (posix_spawnp, "posix_spawnp is unportable - " + "use gnulib module posix_spawnp for portability"); +# endif +#endif + + +#if @GNULIB_POSIX_SPAWNATTR_INIT@ +/* Initialize data structure with attributes for 'spawn' to default values. */ +# if @REPLACE_POSIX_SPAWN@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define posix_spawnattr_init rpl_posix_spawnattr_init +# endif +_GL_FUNCDECL_RPL (posix_spawnattr_init, int, (posix_spawnattr_t *__attr) + __THROW _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (posix_spawnattr_init, int, (posix_spawnattr_t *__attr)); +# else +# if !@HAVE_POSIX_SPAWN@ +_GL_FUNCDECL_SYS (posix_spawnattr_init, int, (posix_spawnattr_t *__attr) + __THROW _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (posix_spawnattr_init, int, (posix_spawnattr_t *__attr)); +# endif +_GL_CXXALIASWARN (posix_spawnattr_init); +#elif defined GNULIB_POSIXCHECK +# undef posix_spawnattr_init +# if HAVE_RAW_DECL_POSIX_SPAWNATTR_INIT +_GL_WARN_ON_USE (posix_spawnattr_init, "posix_spawnattr_init is unportable - " + "use gnulib module posix_spawnattr_init for portability"); +# endif +#endif + +#if @GNULIB_POSIX_SPAWNATTR_DESTROY@ +/* Free resources associated with ATTR. */ +# if @REPLACE_POSIX_SPAWN@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define posix_spawnattr_destroy rpl_posix_spawnattr_destroy +# endif +_GL_FUNCDECL_RPL (posix_spawnattr_destroy, int, (posix_spawnattr_t *__attr) + __THROW _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (posix_spawnattr_destroy, int, (posix_spawnattr_t *__attr)); +# else +# if !@HAVE_POSIX_SPAWN@ +_GL_FUNCDECL_SYS (posix_spawnattr_destroy, int, (posix_spawnattr_t *__attr) + __THROW _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (posix_spawnattr_destroy, int, (posix_spawnattr_t *__attr)); +# endif +_GL_CXXALIASWARN (posix_spawnattr_destroy); +#elif defined GNULIB_POSIXCHECK +# undef posix_spawnattr_destroy +# if HAVE_RAW_DECL_POSIX_SPAWNATTR_DESTROY +_GL_WARN_ON_USE (posix_spawnattr_destroy, + "posix_spawnattr_destroy is unportable - " + "use gnulib module posix_spawnattr_destroy for portability"); +# endif +#endif + +#if @GNULIB_POSIX_SPAWNATTR_GETSIGDEFAULT@ +/* Store signal mask for signals with default handling from ATTR in + SIGDEFAULT. */ +# if @REPLACE_POSIX_SPAWN@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define posix_spawnattr_getsigdefault rpl_posix_spawnattr_getsigdefault +# endif +_GL_FUNCDECL_RPL (posix_spawnattr_getsigdefault, int, + (const posix_spawnattr_t *_Restrict_ __attr, + sigset_t *_Restrict_ __sigdefault) + __THROW _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (posix_spawnattr_getsigdefault, int, + (const posix_spawnattr_t *_Restrict_ __attr, + sigset_t *_Restrict_ __sigdefault)); +# else +# if !@HAVE_POSIX_SPAWN@ +_GL_FUNCDECL_SYS (posix_spawnattr_getsigdefault, int, + (const posix_spawnattr_t *_Restrict_ __attr, + sigset_t *_Restrict_ __sigdefault) + __THROW _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (posix_spawnattr_getsigdefault, int, + (const posix_spawnattr_t *_Restrict_ __attr, + sigset_t *_Restrict_ __sigdefault)); +# endif +_GL_CXXALIASWARN (posix_spawnattr_getsigdefault); +#elif defined GNULIB_POSIXCHECK +# undef posix_spawnattr_getsigdefault +# if HAVE_RAW_DECL_POSIX_SPAWNATTR_GETSIGDEFAULT +_GL_WARN_ON_USE (posix_spawnattr_getsigdefault, + "posix_spawnattr_getsigdefault is unportable - " + "use gnulib module posix_spawnattr_getsigdefault for portability"); +# endif +#endif + +#if @GNULIB_POSIX_SPAWNATTR_SETSIGDEFAULT@ +/* Set signal mask for signals with default handling in ATTR to SIGDEFAULT. */ +# if @REPLACE_POSIX_SPAWN@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define posix_spawnattr_setsigdefault rpl_posix_spawnattr_setsigdefault +# endif +_GL_FUNCDECL_RPL (posix_spawnattr_setsigdefault, int, + (posix_spawnattr_t *_Restrict_ __attr, + const sigset_t *_Restrict_ __sigdefault) + __THROW _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (posix_spawnattr_setsigdefault, int, + (posix_spawnattr_t *_Restrict_ __attr, + const sigset_t *_Restrict_ __sigdefault)); +# else +# if !@HAVE_POSIX_SPAWN@ +_GL_FUNCDECL_SYS (posix_spawnattr_setsigdefault, int, + (posix_spawnattr_t *_Restrict_ __attr, + const sigset_t *_Restrict_ __sigdefault) + __THROW _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (posix_spawnattr_setsigdefault, int, + (posix_spawnattr_t *_Restrict_ __attr, + const sigset_t *_Restrict_ __sigdefault)); +# endif +_GL_CXXALIASWARN (posix_spawnattr_setsigdefault); +#elif defined GNULIB_POSIXCHECK +# undef posix_spawnattr_setsigdefault +# if HAVE_RAW_DECL_POSIX_SPAWNATTR_SETSIGDEFAULT +_GL_WARN_ON_USE (posix_spawnattr_setsigdefault, + "posix_spawnattr_setsigdefault is unportable - " + "use gnulib module posix_spawnattr_setsigdefault for portability"); +# endif +#endif + +#if @GNULIB_POSIX_SPAWNATTR_GETSIGMASK@ +/* Store signal mask for the new process from ATTR in SIGMASK. */ +# if @REPLACE_POSIX_SPAWN@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define posix_spawnattr_getsigmask rpl_posix_spawnattr_getsigmask +# endif +_GL_FUNCDECL_RPL (posix_spawnattr_getsigmask, int, + (const posix_spawnattr_t *_Restrict_ __attr, + sigset_t *_Restrict_ __sigmask) + __THROW _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (posix_spawnattr_getsigmask, int, + (const posix_spawnattr_t *_Restrict_ __attr, + sigset_t *_Restrict_ __sigmask)); +# else +# if !@HAVE_POSIX_SPAWN@ +_GL_FUNCDECL_SYS (posix_spawnattr_getsigmask, int, + (const posix_spawnattr_t *_Restrict_ __attr, + sigset_t *_Restrict_ __sigmask) + __THROW _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (posix_spawnattr_getsigmask, int, + (const posix_spawnattr_t *_Restrict_ __attr, + sigset_t *_Restrict_ __sigmask)); +# endif +_GL_CXXALIASWARN (posix_spawnattr_getsigmask); +#elif defined GNULIB_POSIXCHECK +# undef posix_spawnattr_getsigmask +# if HAVE_RAW_DECL_POSIX_SPAWNATTR_GETSIGMASK +_GL_WARN_ON_USE (posix_spawnattr_getsigmask, + "posix_spawnattr_getsigmask is unportable - " + "use gnulib module posix_spawnattr_getsigmask for portability"); +# endif +#endif + +#if @GNULIB_POSIX_SPAWNATTR_SETSIGMASK@ +/* Set signal mask for the new process in ATTR to SIGMASK. */ +# if @REPLACE_POSIX_SPAWN@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define posix_spawnattr_setsigmask rpl_posix_spawnattr_setsigmask +# endif +_GL_FUNCDECL_RPL (posix_spawnattr_setsigmask, int, + (posix_spawnattr_t *_Restrict_ __attr, + const sigset_t *_Restrict_ __sigmask) + __THROW _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (posix_spawnattr_setsigmask, int, + (posix_spawnattr_t *_Restrict_ __attr, + const sigset_t *_Restrict_ __sigmask)); +# else +# if !@HAVE_POSIX_SPAWN@ +_GL_FUNCDECL_SYS (posix_spawnattr_setsigmask, int, + (posix_spawnattr_t *_Restrict_ __attr, + const sigset_t *_Restrict_ __sigmask) + __THROW _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (posix_spawnattr_setsigmask, int, + (posix_spawnattr_t *_Restrict_ __attr, + const sigset_t *_Restrict_ __sigmask)); +# endif +_GL_CXXALIASWARN (posix_spawnattr_setsigmask); +#elif defined GNULIB_POSIXCHECK +# undef posix_spawnattr_setsigmask +# if HAVE_RAW_DECL_POSIX_SPAWNATTR_SETSIGMASK +_GL_WARN_ON_USE (posix_spawnattr_setsigmask, + "posix_spawnattr_setsigmask is unportable - " + "use gnulib module posix_spawnattr_setsigmask for portability"); +# endif +#endif + +#if @GNULIB_POSIX_SPAWNATTR_GETFLAGS@ +/* Get flag word from the attribute structure. */ +# if @REPLACE_POSIX_SPAWN@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define posix_spawnattr_getflags rpl_posix_spawnattr_getflags +# endif +_GL_FUNCDECL_RPL (posix_spawnattr_getflags, int, + (const posix_spawnattr_t *_Restrict_ __attr, + short int *_Restrict_ __flags) + __THROW _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (posix_spawnattr_getflags, int, + (const posix_spawnattr_t *_Restrict_ __attr, + short int *_Restrict_ __flags)); +# else +# if !@HAVE_POSIX_SPAWN@ +_GL_FUNCDECL_SYS (posix_spawnattr_getflags, int, + (const posix_spawnattr_t *_Restrict_ __attr, + short int *_Restrict_ __flags) + __THROW _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (posix_spawnattr_getflags, int, + (const posix_spawnattr_t *_Restrict_ __attr, + short int *_Restrict_ __flags)); +# endif +_GL_CXXALIASWARN (posix_spawnattr_getflags); +#elif defined GNULIB_POSIXCHECK +# undef posix_spawnattr_getflags +# if HAVE_RAW_DECL_POSIX_SPAWNATTR_GETFLAGS +_GL_WARN_ON_USE (posix_spawnattr_getflags, + "posix_spawnattr_getflags is unportable - " + "use gnulib module posix_spawnattr_getflags for portability"); +# endif +#endif + +#if @GNULIB_POSIX_SPAWNATTR_SETFLAGS@ +/* Store flags in the attribute structure. */ +# if @REPLACE_POSIX_SPAWN@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define posix_spawnattr_setflags rpl_posix_spawnattr_setflags +# endif +_GL_FUNCDECL_RPL (posix_spawnattr_setflags, int, + (posix_spawnattr_t *__attr, short int __flags) + __THROW _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (posix_spawnattr_setflags, int, + (posix_spawnattr_t *__attr, short int __flags)); +# else +# if !@HAVE_POSIX_SPAWN@ +_GL_FUNCDECL_SYS (posix_spawnattr_setflags, int, + (posix_spawnattr_t *__attr, short int __flags) + __THROW _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (posix_spawnattr_setflags, int, + (posix_spawnattr_t *__attr, short int __flags)); +# endif +_GL_CXXALIASWARN (posix_spawnattr_setflags); +#elif defined GNULIB_POSIXCHECK +# undef posix_spawnattr_setflags +# if HAVE_RAW_DECL_POSIX_SPAWNATTR_SETFLAGS +_GL_WARN_ON_USE (posix_spawnattr_setflags, + "posix_spawnattr_setflags is unportable - " + "use gnulib module posix_spawnattr_setflags for portability"); +# endif +#endif + +#if @GNULIB_POSIX_SPAWNATTR_GETPGROUP@ +/* Get process group ID from the attribute structure. */ +# if @REPLACE_POSIX_SPAWN@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define posix_spawnattr_getpgroup rpl_posix_spawnattr_getpgroup +# endif +_GL_FUNCDECL_RPL (posix_spawnattr_getpgroup, int, + (const posix_spawnattr_t *_Restrict_ __attr, + pid_t *_Restrict_ __pgroup) + __THROW _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (posix_spawnattr_getpgroup, int, + (const posix_spawnattr_t *_Restrict_ __attr, + pid_t *_Restrict_ __pgroup)); +# else +# if !@HAVE_POSIX_SPAWN@ +_GL_FUNCDECL_SYS (posix_spawnattr_getpgroup, int, + (const posix_spawnattr_t *_Restrict_ __attr, + pid_t *_Restrict_ __pgroup) + __THROW _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (posix_spawnattr_getpgroup, int, + (const posix_spawnattr_t *_Restrict_ __attr, + pid_t *_Restrict_ __pgroup)); +# endif +_GL_CXXALIASWARN (posix_spawnattr_getpgroup); +#elif defined GNULIB_POSIXCHECK +# undef posix_spawnattr_getpgroup +# if HAVE_RAW_DECL_POSIX_SPAWNATTR_GETPGROUP +_GL_WARN_ON_USE (posix_spawnattr_getpgroup, + "posix_spawnattr_getpgroup is unportable - " + "use gnulib module posix_spawnattr_getpgroup for portability"); +# endif +#endif + +#if @GNULIB_POSIX_SPAWNATTR_SETPGROUP@ +/* Store process group ID in the attribute structure. */ +# if @REPLACE_POSIX_SPAWN@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define posix_spawnattr_setpgroup rpl_posix_spawnattr_setpgroup +# endif +_GL_FUNCDECL_RPL (posix_spawnattr_setpgroup, int, + (posix_spawnattr_t *__attr, pid_t __pgroup) + __THROW _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (posix_spawnattr_setpgroup, int, + (posix_spawnattr_t *__attr, pid_t __pgroup)); +# else +# if !@HAVE_POSIX_SPAWN@ +_GL_FUNCDECL_SYS (posix_spawnattr_setpgroup, int, + (posix_spawnattr_t *__attr, pid_t __pgroup) + __THROW _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (posix_spawnattr_setpgroup, int, + (posix_spawnattr_t *__attr, pid_t __pgroup)); +# endif +_GL_CXXALIASWARN (posix_spawnattr_setpgroup); +#elif defined GNULIB_POSIXCHECK +# undef posix_spawnattr_setpgroup +# if HAVE_RAW_DECL_POSIX_SPAWNATTR_SETPGROUP +_GL_WARN_ON_USE (posix_spawnattr_setpgroup, + "posix_spawnattr_setpgroup is unportable - " + "use gnulib module posix_spawnattr_setpgroup for portability"); +# endif +#endif + +#if @GNULIB_POSIX_SPAWNATTR_GETSCHEDPOLICY@ +/* Get scheduling policy from the attribute structure. */ +# if @REPLACE_POSIX_SPAWN@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define posix_spawnattr_getschedpolicy rpl_posix_spawnattr_getschedpolicy +# endif +_GL_FUNCDECL_RPL (posix_spawnattr_getschedpolicy, int, + (const posix_spawnattr_t *_Restrict_ __attr, + int *_Restrict_ __schedpolicy) + __THROW _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (posix_spawnattr_getschedpolicy, int, + (const posix_spawnattr_t *_Restrict_ __attr, + int *_Restrict_ __schedpolicy)); +# else +# if !@HAVE_POSIX_SPAWN@ || POSIX_SPAWN_SETSCHEDULER == 0 +_GL_FUNCDECL_SYS (posix_spawnattr_getschedpolicy, int, + (const posix_spawnattr_t *_Restrict_ __attr, + int *_Restrict_ __schedpolicy) + __THROW _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (posix_spawnattr_getschedpolicy, int, + (const posix_spawnattr_t *_Restrict_ __attr, + int *_Restrict_ __schedpolicy)); +# endif +_GL_CXXALIASWARN (posix_spawnattr_getschedpolicy); +#elif defined GNULIB_POSIXCHECK +# undef posix_spawnattr_getschedpolicy +# if HAVE_RAW_DECL_POSIX_SPAWNATTR_GETSCHEDPOLICY +_GL_WARN_ON_USE (posix_spawnattr_getschedpolicy, + "posix_spawnattr_getschedpolicy is unportable - " + "use gnulib module posix_spawnattr_getschedpolicy for portability"); +# endif +#endif + +#if @GNULIB_POSIX_SPAWNATTR_SETSCHEDPOLICY@ +/* Store scheduling policy in the attribute structure. */ +# if @REPLACE_POSIX_SPAWN@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define posix_spawnattr_setschedpolicy rpl_posix_spawnattr_setschedpolicy +# endif +_GL_FUNCDECL_RPL (posix_spawnattr_setschedpolicy, int, + (posix_spawnattr_t *__attr, int __schedpolicy) + __THROW _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (posix_spawnattr_setschedpolicy, int, + (posix_spawnattr_t *__attr, int __schedpolicy)); +# else +# if !@HAVE_POSIX_SPAWN@ || POSIX_SPAWN_SETSCHEDULER == 0 +_GL_FUNCDECL_SYS (posix_spawnattr_setschedpolicy, int, + (posix_spawnattr_t *__attr, int __schedpolicy) + __THROW _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (posix_spawnattr_setschedpolicy, int, + (posix_spawnattr_t *__attr, int __schedpolicy)); +# endif +_GL_CXXALIASWARN (posix_spawnattr_setschedpolicy); +#elif defined GNULIB_POSIXCHECK +# undef posix_spawnattr_setschedpolicy +# if HAVE_RAW_DECL_POSIX_SPAWNATTR_SETSCHEDPOLICY +_GL_WARN_ON_USE (posix_spawnattr_setschedpolicy, + "posix_spawnattr_setschedpolicy is unportable - " + "use gnulib module posix_spawnattr_setschedpolicy for portability"); +# endif +#endif + +#if @GNULIB_POSIX_SPAWNATTR_GETSCHEDPARAM@ +/* Get scheduling parameters from the attribute structure. */ +# if @REPLACE_POSIX_SPAWN@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define posix_spawnattr_getschedparam rpl_posix_spawnattr_getschedparam +# endif +_GL_FUNCDECL_RPL (posix_spawnattr_getschedparam, int, + (const posix_spawnattr_t *_Restrict_ __attr, + struct sched_param *_Restrict_ __schedparam) + __THROW _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (posix_spawnattr_getschedparam, int, + (const posix_spawnattr_t *_Restrict_ __attr, + struct sched_param *_Restrict_ __schedparam)); +# else +# if !@HAVE_POSIX_SPAWN@ || POSIX_SPAWN_SETSCHEDPARAM == 0 +_GL_FUNCDECL_SYS (posix_spawnattr_getschedparam, int, + (const posix_spawnattr_t *_Restrict_ __attr, + struct sched_param *_Restrict_ __schedparam) + __THROW _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (posix_spawnattr_getschedparam, int, + (const posix_spawnattr_t *_Restrict_ __attr, + struct sched_param *_Restrict_ __schedparam)); +# endif +_GL_CXXALIASWARN (posix_spawnattr_getschedparam); +#elif defined GNULIB_POSIXCHECK +# undef posix_spawnattr_getschedparam +# if HAVE_RAW_DECL_POSIX_SPAWNATTR_GETSCHEDPARAM +_GL_WARN_ON_USE (posix_spawnattr_getschedparam, + "posix_spawnattr_getschedparam is unportable - " + "use gnulib module posix_spawnattr_getschedparam for portability"); +# endif +#endif + +#if @GNULIB_POSIX_SPAWNATTR_SETSCHEDPARAM@ +/* Store scheduling parameters in the attribute structure. */ +# if @REPLACE_POSIX_SPAWN@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define posix_spawnattr_setschedparam rpl_posix_spawnattr_setschedparam +# endif +_GL_FUNCDECL_RPL (posix_spawnattr_setschedparam, int, + (posix_spawnattr_t *_Restrict_ __attr, + const struct sched_param *_Restrict_ __schedparam) + __THROW _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (posix_spawnattr_setschedparam, int, + (posix_spawnattr_t *_Restrict_ __attr, + const struct sched_param *_Restrict_ __schedparam)); +# else +# if !@HAVE_POSIX_SPAWN@ || POSIX_SPAWN_SETSCHEDPARAM == 0 +_GL_FUNCDECL_SYS (posix_spawnattr_setschedparam, int, + (posix_spawnattr_t *_Restrict_ __attr, + const struct sched_param *_Restrict_ __schedparam) + __THROW _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (posix_spawnattr_setschedparam, int, + (posix_spawnattr_t *_Restrict_ __attr, + const struct sched_param *_Restrict_ __schedparam)); +# endif +_GL_CXXALIASWARN (posix_spawnattr_setschedparam); +#elif defined GNULIB_POSIXCHECK +# undef posix_spawnattr_setschedparam +# if HAVE_RAW_DECL_POSIX_SPAWNATTR_SETSCHEDPARAM +_GL_WARN_ON_USE (posix_spawnattr_setschedparam, + "posix_spawnattr_setschedparam is unportable - " + "use gnulib module posix_spawnattr_setschedparam for portability"); +# endif +#endif + + +#if @GNULIB_POSIX_SPAWN_FILE_ACTIONS_INIT@ +/* Initialize data structure for file attribute for 'spawn' call. */ +# if @REPLACE_POSIX_SPAWN@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define posix_spawn_file_actions_init rpl_posix_spawn_file_actions_init +# endif +_GL_FUNCDECL_RPL (posix_spawn_file_actions_init, int, + (posix_spawn_file_actions_t *__file_actions) + __THROW _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (posix_spawn_file_actions_init, int, + (posix_spawn_file_actions_t *__file_actions)); +# else +# if !@HAVE_POSIX_SPAWN@ +_GL_FUNCDECL_SYS (posix_spawn_file_actions_init, int, + (posix_spawn_file_actions_t *__file_actions) + __THROW _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (posix_spawn_file_actions_init, int, + (posix_spawn_file_actions_t *__file_actions)); +# endif +_GL_CXXALIASWARN (posix_spawn_file_actions_init); +#elif defined GNULIB_POSIXCHECK +# undef posix_spawn_file_actions_init +# if HAVE_RAW_DECL_POSIX_SPAWN_FILE_ACTIONS_INIT +_GL_WARN_ON_USE (posix_spawn_file_actions_init, + "posix_spawn_file_actions_init is unportable - " + "use gnulib module posix_spawn_file_actions_init for portability"); +# endif +#endif + +#if @GNULIB_POSIX_SPAWN_FILE_ACTIONS_DESTROY@ +/* Free resources associated with FILE-ACTIONS. */ +# if @REPLACE_POSIX_SPAWN@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define posix_spawn_file_actions_destroy rpl_posix_spawn_file_actions_destroy +# endif +_GL_FUNCDECL_RPL (posix_spawn_file_actions_destroy, int, + (posix_spawn_file_actions_t *__file_actions) + __THROW _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (posix_spawn_file_actions_destroy, int, + (posix_spawn_file_actions_t *__file_actions)); +# else +# if !@HAVE_POSIX_SPAWN@ +_GL_FUNCDECL_SYS (posix_spawn_file_actions_destroy, int, + (posix_spawn_file_actions_t *__file_actions) + __THROW _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (posix_spawn_file_actions_destroy, int, + (posix_spawn_file_actions_t *__file_actions)); +# endif +_GL_CXXALIASWARN (posix_spawn_file_actions_destroy); +#elif defined GNULIB_POSIXCHECK +# undef posix_spawn_file_actions_destroy +# if HAVE_RAW_DECL_POSIX_SPAWN_FILE_ACTIONS_DESTROY +_GL_WARN_ON_USE (posix_spawn_file_actions_destroy, + "posix_spawn_file_actions_destroy is unportable - " + "use gnulib module posix_spawn_file_actions_destroy for portability"); +# endif +#endif + +#if @GNULIB_POSIX_SPAWN_FILE_ACTIONS_ADDOPEN@ +/* Add an action to FILE-ACTIONS which tells the implementation to call + 'open' for the given file during the 'spawn' call. */ +# if @REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDOPEN@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define posix_spawn_file_actions_addopen rpl_posix_spawn_file_actions_addopen +# endif +_GL_FUNCDECL_RPL (posix_spawn_file_actions_addopen, int, + (posix_spawn_file_actions_t *_Restrict_ __file_actions, + int __fd, + const char *_Restrict_ __path, int __oflag, mode_t __mode) + __THROW _GL_ARG_NONNULL ((1, 3))); +_GL_CXXALIAS_RPL (posix_spawn_file_actions_addopen, int, + (posix_spawn_file_actions_t *_Restrict_ __file_actions, + int __fd, + const char *_Restrict_ __path, int __oflag, mode_t __mode)); +# else +# if !@HAVE_POSIX_SPAWN@ +_GL_FUNCDECL_SYS (posix_spawn_file_actions_addopen, int, + (posix_spawn_file_actions_t *_Restrict_ __file_actions, + int __fd, + const char *_Restrict_ __path, int __oflag, mode_t __mode) + __THROW _GL_ARG_NONNULL ((1, 3))); +# endif +_GL_CXXALIAS_SYS (posix_spawn_file_actions_addopen, int, + (posix_spawn_file_actions_t *_Restrict_ __file_actions, + int __fd, + const char *_Restrict_ __path, int __oflag, mode_t __mode)); +# endif +_GL_CXXALIASWARN (posix_spawn_file_actions_addopen); +#elif defined GNULIB_POSIXCHECK +# undef posix_spawn_file_actions_addopen +# if HAVE_RAW_DECL_POSIX_SPAWN_FILE_ACTIONS_ADDOPEN +_GL_WARN_ON_USE (posix_spawn_file_actions_addopen, + "posix_spawn_file_actions_addopen is unportable - " + "use gnulib module posix_spawn_file_actions_addopen for portability"); +# endif +#endif + +#if @GNULIB_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSE@ +/* Add an action to FILE-ACTIONS which tells the implementation to call + 'close' for the given file descriptor during the 'spawn' call. */ +# if @REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSE@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define posix_spawn_file_actions_addclose rpl_posix_spawn_file_actions_addclose +# endif +_GL_FUNCDECL_RPL (posix_spawn_file_actions_addclose, int, + (posix_spawn_file_actions_t *__file_actions, int __fd) + __THROW _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (posix_spawn_file_actions_addclose, int, + (posix_spawn_file_actions_t *__file_actions, int __fd)); +# else +# if !@HAVE_POSIX_SPAWN@ +_GL_FUNCDECL_SYS (posix_spawn_file_actions_addclose, int, + (posix_spawn_file_actions_t *__file_actions, int __fd) + __THROW _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (posix_spawn_file_actions_addclose, int, + (posix_spawn_file_actions_t *__file_actions, int __fd)); +# endif +_GL_CXXALIASWARN (posix_spawn_file_actions_addclose); +#elif defined GNULIB_POSIXCHECK +# undef posix_spawn_file_actions_addclose +# if HAVE_RAW_DECL_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSE +_GL_WARN_ON_USE (posix_spawn_file_actions_addclose, + "posix_spawn_file_actions_addclose is unportable - " + "use gnulib module posix_spawn_file_actions_addclose for portability"); +# endif +#endif + +#if @GNULIB_POSIX_SPAWN_FILE_ACTIONS_ADDDUP2@ +/* Add an action to FILE-ACTIONS which tells the implementation to call + 'dup2' for the given file descriptors during the 'spawn' call. */ +# if @REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDDUP2@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define posix_spawn_file_actions_adddup2 rpl_posix_spawn_file_actions_adddup2 +# endif +_GL_FUNCDECL_RPL (posix_spawn_file_actions_adddup2, int, + (posix_spawn_file_actions_t *__file_actions, + int __fd, int __newfd) + __THROW _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (posix_spawn_file_actions_adddup2, int, + (posix_spawn_file_actions_t *__file_actions, + int __fd, int __newfd)); +# else +# if !@HAVE_POSIX_SPAWN@ +_GL_FUNCDECL_SYS (posix_spawn_file_actions_adddup2, int, + (posix_spawn_file_actions_t *__file_actions, + int __fd, int __newfd) + __THROW _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (posix_spawn_file_actions_adddup2, int, + (posix_spawn_file_actions_t *__file_actions, + int __fd, int __newfd)); +# endif +_GL_CXXALIASWARN (posix_spawn_file_actions_adddup2); +#elif defined GNULIB_POSIXCHECK +# undef posix_spawn_file_actions_adddup2 +# if HAVE_RAW_DECL_POSIX_SPAWN_FILE_ACTIONS_ADDDUP2 +_GL_WARN_ON_USE (posix_spawn_file_actions_adddup2, + "posix_spawn_file_actions_adddup2 is unportable - " + "use gnulib module posix_spawn_file_actions_adddup2 for portability"); +# endif +#endif + + +#endif /* _@GUARD_PREFIX@_SPAWN_H */ +#endif /* _@GUARD_PREFIX@_SPAWN_H */ diff --git a/gettext-tools/gnulib-lib/spawn_faction_addclose.c b/gettext-tools/gnulib-lib/spawn_faction_addclose.c new file mode 100644 index 0000000..d681fe7 --- /dev/null +++ b/gettext-tools/gnulib-lib/spawn_faction_addclose.c @@ -0,0 +1,69 @@ +/* Copyright (C) 2000, 2009-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include + +#include +#include + +#if !_LIBC +# define __sysconf(open_max) getdtablesize () +#endif + +#if !HAVE_WORKING_POSIX_SPAWN +# include "spawn_int.h" +#endif + +/* Add an action to FILE-ACTIONS which tells the implementation to call + 'close' for the given file descriptor during the 'spawn' call. */ +int +posix_spawn_file_actions_addclose (posix_spawn_file_actions_t *file_actions, + int fd) +#undef posix_spawn_file_actions_addclose +{ + int maxfd = __sysconf (_SC_OPEN_MAX); + + /* Test for the validity of the file descriptor. */ + if (fd < 0 || fd >= maxfd) + return EBADF; + +#if HAVE_WORKING_POSIX_SPAWN + return posix_spawn_file_actions_addclose (file_actions, fd); +#else + /* Allocate more memory if needed. */ + if (file_actions->_used == file_actions->_allocated + && __posix_spawn_file_actions_realloc (file_actions) != 0) + /* This can only mean we ran out of memory. */ + return ENOMEM; + + { + struct __spawn_action *rec; + + /* Add the new value. */ + rec = &file_actions->_actions[file_actions->_used]; + rec->tag = spawn_do_close; + rec->action.open_action.fd = fd; + + /* Account for the new entry. */ + ++file_actions->_used; + + return 0; + } +#endif +} diff --git a/gettext-tools/gnulib-lib/spawn_faction_adddup2.c b/gettext-tools/gnulib-lib/spawn_faction_adddup2.c new file mode 100644 index 0000000..9292488 --- /dev/null +++ b/gettext-tools/gnulib-lib/spawn_faction_adddup2.c @@ -0,0 +1,70 @@ +/* Copyright (C) 2000, 2009-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include + +#include +#include + +#if !_LIBC +# define __sysconf(open_max) getdtablesize () +#endif + +#if !HAVE_WORKING_POSIX_SPAWN +# include "spawn_int.h" +#endif + +/* Add an action to FILE-ACTIONS which tells the implementation to call + 'dup2' for the given file descriptors during the 'spawn' call. */ +int +posix_spawn_file_actions_adddup2 (posix_spawn_file_actions_t *file_actions, + int fd, int newfd) +#undef posix_spawn_file_actions_adddup2 +{ + int maxfd = __sysconf (_SC_OPEN_MAX); + + /* Test for the validity of the file descriptor. */ + if (fd < 0 || newfd < 0 || fd >= maxfd || newfd >= maxfd) + return EBADF; + +#if HAVE_WORKING_POSIX_SPAWN + return posix_spawn_file_actions_adddup2 (file_actions, fd, newfd); +#else + /* Allocate more memory if needed. */ + if (file_actions->_used == file_actions->_allocated + && __posix_spawn_file_actions_realloc (file_actions) != 0) + /* This can only mean we ran out of memory. */ + return ENOMEM; + + { + struct __spawn_action *rec; + + /* Add the new value. */ + rec = &file_actions->_actions[file_actions->_used]; + rec->tag = spawn_do_dup2; + rec->action.dup2_action.fd = fd; + rec->action.dup2_action.newfd = newfd; + + /* Account for the new entry. */ + ++file_actions->_used; + + return 0; + } +#endif +} diff --git a/gettext-tools/gnulib-lib/spawn_faction_addopen.c b/gettext-tools/gnulib-lib/spawn_faction_addopen.c new file mode 100644 index 0000000..3ca9501 --- /dev/null +++ b/gettext-tools/gnulib-lib/spawn_faction_addopen.c @@ -0,0 +1,73 @@ +/* Copyright (C) 2000, 2009-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include + +#include +#include + +#if !_LIBC +# define __sysconf(open_max) getdtablesize () +#endif + +#if !HAVE_WORKING_POSIX_SPAWN +# include "spawn_int.h" +#endif + +/* Add an action to FILE-ACTIONS which tells the implementation to call + 'open' for the given file during the 'spawn' call. */ +int +posix_spawn_file_actions_addopen (posix_spawn_file_actions_t *file_actions, + int fd, const char *path, int oflag, + mode_t mode) +#undef posix_spawn_file_actions_addopen +{ + int maxfd = __sysconf (_SC_OPEN_MAX); + + /* Test for the validity of the file descriptor. */ + if (fd < 0 || fd >= maxfd) + return EBADF; + +#if HAVE_WORKING_POSIX_SPAWN + return posix_spawn_file_actions_addopen (file_actions, fd, path, oflag, mode); +#else + /* Allocate more memory if needed. */ + if (file_actions->_used == file_actions->_allocated + && __posix_spawn_file_actions_realloc (file_actions) != 0) + /* This can only mean we ran out of memory. */ + return ENOMEM; + + { + struct __spawn_action *rec; + + /* Add the new value. */ + rec = &file_actions->_actions[file_actions->_used]; + rec->tag = spawn_do_open; + rec->action.open_action.fd = fd; + rec->action.open_action.path = path; + rec->action.open_action.oflag = oflag; + rec->action.open_action.mode = mode; + + /* Account for the new entry. */ + ++file_actions->_used; + + return 0; + } +#endif +} diff --git a/gettext-tools/gnulib-lib/spawn_faction_destroy.c b/gettext-tools/gnulib-lib/spawn_faction_destroy.c new file mode 100644 index 0000000..bca46cc --- /dev/null +++ b/gettext-tools/gnulib-lib/spawn_faction_destroy.c @@ -0,0 +1,31 @@ +/* Copyright (C) 2000, 2009-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include + +#include + +/* Initialize data structure for file attribute for 'spawn' call. */ +int +posix_spawn_file_actions_destroy (posix_spawn_file_actions_t *file_actions) +{ + /* Free the memory allocated. */ + free (file_actions->_actions); + return 0; +} diff --git a/gettext-tools/gnulib-lib/spawn_faction_init.c b/gettext-tools/gnulib-lib/spawn_faction_init.c new file mode 100644 index 0000000..c8b8094 --- /dev/null +++ b/gettext-tools/gnulib-lib/spawn_faction_init.c @@ -0,0 +1,56 @@ +/* Copyright (C) 2000, 2009-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include + +#include +#include +#include + +#include "spawn_int.h" + + +/* Function used to increase the size of the allocated array. This + function is called from the 'add'-functions. */ +int +__posix_spawn_file_actions_realloc (posix_spawn_file_actions_t *file_actions) +{ + int newalloc = file_actions->_allocated + 8; + void *newmem = realloc (file_actions->_actions, + newalloc * sizeof (struct __spawn_action)); + + if (newmem == NULL) + /* Not enough memory. */ + return ENOMEM; + + file_actions->_actions = (struct __spawn_action *) newmem; + file_actions->_allocated = newalloc; + + return 0; +} + + +/* Initialize data structure for file attribute for 'spawn' call. */ +int +posix_spawn_file_actions_init (posix_spawn_file_actions_t *file_actions) +{ + /* Simply clear all the elements. */ + memset (file_actions, '\0', sizeof (*file_actions)); + return 0; +} diff --git a/gettext-tools/gnulib-lib/spawn_int.h b/gettext-tools/gnulib-lib/spawn_int.h new file mode 100644 index 0000000..04351a7 --- /dev/null +++ b/gettext-tools/gnulib-lib/spawn_int.h @@ -0,0 +1,62 @@ +/* Copyright (C) 2000, 2008-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Data structure to contain the action information. */ +struct __spawn_action +{ + enum + { + spawn_do_close, + spawn_do_dup2, + spawn_do_open + } tag; + + union + { + struct + { + int fd; + } close_action; + struct + { + int fd; + int newfd; + } dup2_action; + struct + { + int fd; + const char *path; + int oflag; + mode_t mode; + } open_action; + } action; +}; + +#if !_LIBC +# define __posix_spawn_file_actions_realloc gl_posix_spawn_file_actions_realloc +#endif +extern int __posix_spawn_file_actions_realloc (posix_spawn_file_actions_t * + file_actions); + +#if !_LIBC +# define __spawni gl_posix_spawn_internal +#endif +extern int __spawni (pid_t *pid, const char *path, + const posix_spawn_file_actions_t *file_actions, + const posix_spawnattr_t *attrp, char *const argv[], + char *const envp[], int use_path); diff --git a/gettext-tools/gnulib-lib/spawnattr_destroy.c b/gettext-tools/gnulib-lib/spawnattr_destroy.c new file mode 100644 index 0000000..7ebe141 --- /dev/null +++ b/gettext-tools/gnulib-lib/spawnattr_destroy.c @@ -0,0 +1,28 @@ +/* Copyright (C) 2000, 2009-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include + +/* Initialize data structure for file attribute for 'spawn' call. */ +int +posix_spawnattr_destroy (posix_spawnattr_t *attr) +{ + /* Nothing to do in the moment. */ + return 0; +} diff --git a/gettext-tools/gnulib-lib/spawnattr_init.c b/gettext-tools/gnulib-lib/spawnattr_init.c new file mode 100644 index 0000000..dec23be --- /dev/null +++ b/gettext-tools/gnulib-lib/spawnattr_init.c @@ -0,0 +1,33 @@ +/* Copyright (C) 2000, 2009-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include + +#include + +/* Initialize data structure for file attribute for 'spawn' call. */ +int +posix_spawnattr_init (posix_spawnattr_t *attr) +{ + /* All elements have to be initialized to the default values which + is generally zero. */ + memset (attr, '\0', sizeof (*attr)); + + return 0; +} diff --git a/gettext-tools/gnulib-lib/spawnattr_setflags.c b/gettext-tools/gnulib-lib/spawnattr_setflags.c new file mode 100644 index 0000000..f7cf0a2 --- /dev/null +++ b/gettext-tools/gnulib-lib/spawnattr_setflags.c @@ -0,0 +1,45 @@ +/* Copyright (C) 2000, 2004, 2009-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include + +#include +#include + +#define ALL_FLAGS (POSIX_SPAWN_RESETIDS \ + | POSIX_SPAWN_SETPGROUP \ + | POSIX_SPAWN_SETSIGDEF \ + | POSIX_SPAWN_SETSIGMASK \ + | POSIX_SPAWN_SETSCHEDPARAM \ + | POSIX_SPAWN_SETSCHEDULER \ + | POSIX_SPAWN_USEVFORK) + +/* Store flags in the attribute structure. */ +int +posix_spawnattr_setflags (posix_spawnattr_t *attr, short int flags) +{ + /* Check no invalid bits are set. */ + if (flags & ~ALL_FLAGS) + return EINVAL; + + /* Store the flag word. */ + attr->_flags = flags; + + return 0; +} diff --git a/gettext-tools/gnulib-lib/spawnattr_setsigmask.c b/gettext-tools/gnulib-lib/spawnattr_setsigmask.c new file mode 100644 index 0000000..b70b6bf --- /dev/null +++ b/gettext-tools/gnulib-lib/spawnattr_setsigmask.c @@ -0,0 +1,33 @@ +/* Copyright (C) 2000, 2009-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include + +#include + +/* Set signal mask for the new process in ATTR to SIGMASK. */ +int +posix_spawnattr_setsigmask (posix_spawnattr_t *attr, + const sigset_t *sigmask) +{ + /* Copy the sigset_t data to the user buffer. */ + memcpy (&attr->_ss, sigmask, sizeof (sigset_t)); + + return 0; +} diff --git a/gettext-tools/gnulib-lib/spawni.c b/gettext-tools/gnulib-lib/spawni.c new file mode 100644 index 0000000..ae5ee0c --- /dev/null +++ b/gettext-tools/gnulib-lib/spawni.c @@ -0,0 +1,374 @@ +/* Guts of POSIX spawn interface. Generic POSIX.1 version. + Copyright (C) 2000-2006, 2008-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include +#include "spawn_int.h" + +#include +#include + +#include +#ifndef O_LARGEFILE +# define O_LARGEFILE 0 +#endif + +#if _LIBC || HAVE_PATHS_H +# include +#else +# define _PATH_BSHELL "/bin/sh" +#endif + +#include +#include +#include +#include + +#if _LIBC +# include +#else +# define close_not_cancel close +# define open_not_cancel open +#endif + +#if _LIBC +# include +#else +# if !HAVE_SETEUID +# define seteuid(id) setresuid (-1, id, -1) +# endif +# if !HAVE_SETEGID +# define setegid(id) setresgid (-1, id, -1) +# endif +# define local_seteuid(id) seteuid (id) +# define local_setegid(id) setegid (id) +#endif + +#if _LIBC +# define alloca __alloca +# define execve __execve +# define dup2 __dup2 +# define fork __fork +# define getgid __getgid +# define getuid __getuid +# define sched_setparam __sched_setparam +# define sched_setscheduler __sched_setscheduler +# define setpgid __setpgid +# define sigaction __sigaction +# define sigismember __sigismember +# define sigprocmask __sigprocmask +# define strchrnul __strchrnul +# define vfork __vfork +#else +# undef internal_function +# define internal_function /* empty */ +#endif + + +/* The Unix standard contains a long explanation of the way to signal + an error after the fork() was successful. Since no new wait status + was wanted there is no way to signal an error using one of the + available methods. The committee chose to signal an error by a + normal program exit with the exit code 127. */ +#define SPAWN_ERROR 127 + + +#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ + +/* Native Windows API. */ +int +__spawni (pid_t *pid, const char *file, + const posix_spawn_file_actions_t *file_actions, + const posix_spawnattr_t *attrp, char *const argv[], + char *const envp[], int use_path) +{ + /* Not yet implemented. */ + return ENOSYS; +} + +#else + + +/* The file is accessible but it is not an executable file. Invoke + the shell to interpret it as a script. */ +static void +internal_function +script_execute (const char *file, char *const argv[], char *const envp[]) +{ + /* Count the arguments. */ + int argc = 0; + while (argv[argc++]) + ; + + /* Construct an argument list for the shell. */ + { + char **new_argv = (char **) alloca ((argc + 1) * sizeof (char *)); + new_argv[0] = (char *) _PATH_BSHELL; + new_argv[1] = (char *) file; + while (argc > 1) + { + new_argv[argc] = argv[argc - 1]; + --argc; + } + + /* Execute the shell. */ + execve (new_argv[0], new_argv, envp); + } +} + + +/* Spawn a new process executing PATH with the attributes describes in *ATTRP. + Before running the process perform the actions described in FILE-ACTIONS. */ +int +__spawni (pid_t *pid, const char *file, + const posix_spawn_file_actions_t *file_actions, + const posix_spawnattr_t *attrp, char *const argv[], + char *const envp[], int use_path) +{ + pid_t new_pid; + char *path, *p, *name; + size_t len; + size_t pathlen; + + /* Do this once. */ + short int flags = attrp == NULL ? 0 : attrp->_flags; + + /* Avoid gcc warning + "variable 'flags' might be clobbered by 'longjmp' or 'vfork'" */ + (void) &flags; + + /* Generate the new process. */ +#if HAVE_VFORK + if ((flags & POSIX_SPAWN_USEVFORK) != 0 + /* If no major work is done, allow using vfork. Note that we + might perform the path searching. But this would be done by + a call to execvp(), too, and such a call must be OK according + to POSIX. */ + || ((flags & (POSIX_SPAWN_SETSIGMASK | POSIX_SPAWN_SETSIGDEF + | POSIX_SPAWN_SETSCHEDPARAM | POSIX_SPAWN_SETSCHEDULER + | POSIX_SPAWN_SETPGROUP | POSIX_SPAWN_RESETIDS)) == 0 + && file_actions == NULL)) + new_pid = vfork (); + else +#endif + new_pid = fork (); + + if (new_pid != 0) + { + if (new_pid < 0) + return errno; + + /* The call was successful. Store the PID if necessary. */ + if (pid != NULL) + *pid = new_pid; + + return 0; + } + + /* Set signal mask. */ + if ((flags & POSIX_SPAWN_SETSIGMASK) != 0 + && sigprocmask (SIG_SETMASK, &attrp->_ss, NULL) != 0) + _exit (SPAWN_ERROR); + + /* Set signal default action. */ + if ((flags & POSIX_SPAWN_SETSIGDEF) != 0) + { + /* We have to iterate over all signals. This could possibly be + done better but it requires system specific solutions since + the sigset_t data type can be very different on different + architectures. */ + int sig; + struct sigaction sa; + + memset (&sa, '\0', sizeof (sa)); + sa.sa_handler = SIG_DFL; + + for (sig = 1; sig <= NSIG; ++sig) + if (sigismember (&attrp->_sd, sig) != 0 + && sigaction (sig, &sa, NULL) != 0) + _exit (SPAWN_ERROR); + + } + +#if (_LIBC ? defined _POSIX_PRIORITY_SCHEDULING : HAVE_SCHED_SETPARAM && HAVE_SCHED_SETSCHEDULER) + /* Set the scheduling algorithm and parameters. */ + if ((flags & (POSIX_SPAWN_SETSCHEDPARAM | POSIX_SPAWN_SETSCHEDULER)) + == POSIX_SPAWN_SETSCHEDPARAM) + { + if (sched_setparam (0, &attrp->_sp) == -1) + _exit (SPAWN_ERROR); + } + else if ((flags & POSIX_SPAWN_SETSCHEDULER) != 0) + { + if (sched_setscheduler (0, attrp->_policy, + (flags & POSIX_SPAWN_SETSCHEDPARAM) != 0 + ? &attrp->_sp : NULL) == -1) + _exit (SPAWN_ERROR); + } +#endif + + /* Set the process group ID. */ + if ((flags & POSIX_SPAWN_SETPGROUP) != 0 + && setpgid (0, attrp->_pgrp) != 0) + _exit (SPAWN_ERROR); + + /* Set the effective user and group IDs. */ + if ((flags & POSIX_SPAWN_RESETIDS) != 0 + && (local_seteuid (getuid ()) != 0 + || local_setegid (getgid ()) != 0)) + _exit (SPAWN_ERROR); + + /* Execute the file actions. */ + if (file_actions != NULL) + { + int cnt; + + for (cnt = 0; cnt < file_actions->_used; ++cnt) + { + struct __spawn_action *action = &file_actions->_actions[cnt]; + + switch (action->tag) + { + case spawn_do_close: + if (close_not_cancel (action->action.close_action.fd) != 0) + /* Signal the error. */ + _exit (SPAWN_ERROR); + break; + + case spawn_do_open: + { + int new_fd = open_not_cancel (action->action.open_action.path, + action->action.open_action.oflag + | O_LARGEFILE, + action->action.open_action.mode); + + if (new_fd == -1) + /* The 'open' call failed. */ + _exit (SPAWN_ERROR); + + /* Make sure the desired file descriptor is used. */ + if (new_fd != action->action.open_action.fd) + { + if (dup2 (new_fd, action->action.open_action.fd) + != action->action.open_action.fd) + /* The 'dup2' call failed. */ + _exit (SPAWN_ERROR); + + if (close_not_cancel (new_fd) != 0) + /* The 'close' call failed. */ + _exit (SPAWN_ERROR); + } + } + break; + + case spawn_do_dup2: + if (dup2 (action->action.dup2_action.fd, + action->action.dup2_action.newfd) + != action->action.dup2_action.newfd) + /* The 'dup2' call failed. */ + _exit (SPAWN_ERROR); + break; + } + } + } + + if (! use_path || strchr (file, '/') != NULL) + { + /* The FILE parameter is actually a path. */ + execve (file, argv, envp); + + if (errno == ENOEXEC) + script_execute (file, argv, envp); + + /* Oh, oh. 'execve' returns. This is bad. */ + _exit (SPAWN_ERROR); + } + + /* We have to search for FILE on the path. */ + path = getenv ("PATH"); + if (path == NULL) + { +#if HAVE_CONFSTR + /* There is no 'PATH' in the environment. + The default search path is the current directory + followed by the path 'confstr' returns for '_CS_PATH'. */ + len = confstr (_CS_PATH, (char *) NULL, 0); + path = (char *) alloca (1 + len); + path[0] = ':'; + (void) confstr (_CS_PATH, path + 1, len); +#else + /* Pretend that the PATH contains only the current directory. */ + path = ""; +#endif + } + + len = strlen (file) + 1; + pathlen = strlen (path); + name = alloca (pathlen + len + 1); + /* Copy the file name at the top. */ + name = (char *) memcpy (name + pathlen + 1, file, len); + /* And add the slash. */ + *--name = '/'; + + p = path; + do + { + char *startp; + + path = p; + p = strchrnul (path, ':'); + + if (p == path) + /* Two adjacent colons, or a colon at the beginning or the end + of 'PATH' means to search the current directory. */ + startp = name + 1; + else + startp = (char *) memcpy (name - (p - path), path, p - path); + + /* Try to execute this name. If it works, execv will not return. */ + execve (startp, argv, envp); + + if (errno == ENOEXEC) + script_execute (startp, argv, envp); + + switch (errno) + { + case EACCES: + case ENOENT: + case ESTALE: + case ENOTDIR: + /* Those errors indicate the file is missing or not executable + by us, in which case we want to just try the next path + directory. */ + break; + + default: + /* Some other error means we found an executable file, but + something went wrong executing it; return the error to our + caller. */ + _exit (SPAWN_ERROR); + } + } + while (*p++ != '\0'); + + /* Return with an error. */ + _exit (SPAWN_ERROR); +} + +#endif diff --git a/gettext-tools/gnulib-lib/spawnp.c b/gettext-tools/gnulib-lib/spawnp.c new file mode 100644 index 0000000..f856bbb --- /dev/null +++ b/gettext-tools/gnulib-lib/spawnp.c @@ -0,0 +1,33 @@ +/* Copyright (C) 2000, 2009-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include + +#include "spawn_int.h" + +/* Spawn a new process executing FILE with the attributes describes in *ATTRP. + Before running the process perform the actions described in FILE-ACTIONS. */ +int +posix_spawnp (pid_t *pid, const char *file, + const posix_spawn_file_actions_t *file_actions, + const posix_spawnattr_t *attrp, char *const argv[], + char *const envp[]) +{ + return __spawni (pid, file, file_actions, attrp, argv, envp, 1); +} diff --git a/gettext-tools/gnulib-lib/stat.c b/gettext-tools/gnulib-lib/stat.c new file mode 100644 index 0000000..35f4b0b --- /dev/null +++ b/gettext-tools/gnulib-lib/stat.c @@ -0,0 +1,138 @@ +/* Work around platform bugs in stat. + Copyright (C) 2009-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* written by Eric Blake */ + +/* If the user's config.h happens to include , let it include only + the system's here, so that orig_stat doesn't recurse to + rpl_stat. */ +#define __need_system_sys_stat_h +#include + +/* Get the original definition of stat. It might be defined as a macro. */ +#include +#include +#undef __need_system_sys_stat_h + +#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ +# if _GL_WINDOWS_64_BIT_ST_SIZE +# undef stat /* avoid warning on mingw64 with _FILE_OFFSET_BITS=64 */ +# define stat _stati64 +# define REPLACE_FUNC_STAT_DIR 1 +# undef REPLACE_FUNC_STAT_FILE +# elif REPLACE_FUNC_STAT_FILE +/* mingw64 has a broken stat() function, based on _stat(), in libmingwex.a. + Bypass it. */ +# define stat _stat +# define REPLACE_FUNC_STAT_DIR 1 +# undef REPLACE_FUNC_STAT_FILE +# endif +#endif + +static int +orig_stat (const char *filename, struct stat *buf) +{ + return stat (filename, buf); +} + +/* Specification. */ +/* Write "sys/stat.h" here, not , otherwise OSF/1 5.1 DTK cc + eliminates this include because of the preliminary #include + above. */ +#include "sys/stat.h" + +#include +#include +#include +#include +#include "dosname.h" +#include "verify.h" + +#if REPLACE_FUNC_STAT_DIR +# include "pathmax.h" + /* The only known systems where REPLACE_FUNC_STAT_DIR is needed also + have a constant PATH_MAX. */ +# ifndef PATH_MAX +# error "Please port this replacement to your platform" +# endif +#endif + +/* Store information about NAME into ST. Work around bugs with + trailing slashes. Mingw has other bugs (such as st_ino always + being 0 on success) which this wrapper does not work around. But + at least this implementation provides the ability to emulate fchdir + correctly. */ + +int +rpl_stat (char const *name, struct stat *st) +{ + int result = orig_stat (name, st); +#if REPLACE_FUNC_STAT_FILE + /* Solaris 9 mistakenly succeeds when given a non-directory with a + trailing slash. */ + if (result == 0 && !S_ISDIR (st->st_mode)) + { + size_t len = strlen (name); + if (ISSLASH (name[len - 1])) + { + errno = ENOTDIR; + return -1; + } + } +#endif /* REPLACE_FUNC_STAT_FILE */ +#if REPLACE_FUNC_STAT_DIR + + if (result == -1 && errno == ENOENT) + { + /* Due to mingw's oddities, there are some directories (like + c:\) where stat() only succeeds with a trailing slash, and + other directories (like c:\windows) where stat() only + succeeds without a trailing slash. But we want the two to be + synonymous, since chdir() manages either style. Likewise, Mingw also + reports ENOENT for names longer than PATH_MAX, when we want + ENAMETOOLONG, and for stat("file/"), when we want ENOTDIR. + Fortunately, mingw PATH_MAX is small enough for stack + allocation. */ + char fixed_name[PATH_MAX + 1] = {0}; + size_t len = strlen (name); + bool check_dir = false; + verify (PATH_MAX <= 4096); + if (PATH_MAX <= len) + errno = ENAMETOOLONG; + else if (len) + { + strcpy (fixed_name, name); + if (ISSLASH (fixed_name[len - 1])) + { + check_dir = true; + while (len && ISSLASH (fixed_name[len - 1])) + fixed_name[--len] = '\0'; + if (!len) + fixed_name[0] = '/'; + } + else + fixed_name[len++] = '/'; + result = orig_stat (fixed_name, st); + if (result == 0 && check_dir && !S_ISDIR (st->st_mode)) + { + result = -1; + errno = ENOTDIR; + } + } + } +#endif /* REPLACE_FUNC_STAT_DIR */ + return result; +} diff --git a/gettext-tools/gnulib-lib/stdarg.in.h b/gettext-tools/gnulib-lib/stdarg.in.h new file mode 100644 index 0000000..5b37dd3 --- /dev/null +++ b/gettext-tools/gnulib-lib/stdarg.in.h @@ -0,0 +1,35 @@ +/* Substitute for and wrapper around . + Copyright (C) 2008-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . */ + +#ifndef _@GUARD_PREFIX@_STDARG_H + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +/* The include_next requires a split double-inclusion guard. */ +#@INCLUDE_NEXT@ @NEXT_STDARG_H@ + +#ifndef _@GUARD_PREFIX@_STDARG_H +#define _@GUARD_PREFIX@_STDARG_H + +#ifndef va_copy +# define va_copy(a,b) ((a) = (b)) +#endif + +#endif /* _@GUARD_PREFIX@_STDARG_H */ +#endif /* _@GUARD_PREFIX@_STDARG_H */ diff --git a/gettext-tools/gnulib-lib/stdbool.in.h b/gettext-tools/gnulib-lib/stdbool.in.h new file mode 100644 index 0000000..651e8df --- /dev/null +++ b/gettext-tools/gnulib-lib/stdbool.in.h @@ -0,0 +1,132 @@ +/* Copyright (C) 2001-2003, 2006-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2001. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . */ + +#ifndef _GL_STDBOOL_H +#define _GL_STDBOOL_H + +/* ISO C 99 for platforms that lack it. */ + +/* Usage suggestions: + + Programs that use should be aware of some limitations + and standards compliance issues. + + Standards compliance: + + - must be #included before 'bool', 'false', 'true' + can be used. + + - You cannot assume that sizeof (bool) == 1. + + - Programs should not undefine the macros bool, true, and false, + as C99 lists that as an "obsolescent feature". + + Limitations of this substitute, when used in a C89 environment: + + - must be #included before the '_Bool' type can be used. + + - You cannot assume that _Bool is a typedef; it might be a macro. + + - Bit-fields of type 'bool' are not supported. Portable code + should use 'unsigned int foo : 1;' rather than 'bool foo : 1;'. + + - In C99, casts and automatic conversions to '_Bool' or 'bool' are + performed in such a way that every nonzero value gets converted + to 'true', and zero gets converted to 'false'. This doesn't work + with this substitute. With this substitute, only the values 0 and 1 + give the expected result when converted to _Bool' or 'bool'. + + - C99 allows the use of (_Bool)0.0 in constant expressions, but + this substitute cannot always provide this property. + + Also, it is suggested that programs use 'bool' rather than '_Bool'; + this isn't required, but 'bool' is more common. */ + + +/* 7.16. Boolean type and values */ + +/* BeOS already #defines false 0, true 1. We use the same + definitions below, but temporarily we have to #undef them. */ +#if defined __BEOS__ && !defined __HAIKU__ +# include /* defines bool but not _Bool */ +# undef false +# undef true +#endif + +#ifdef __cplusplus +# define _Bool bool +# define bool bool +#else +# if defined __BEOS__ && !defined __HAIKU__ + /* A compiler known to have 'bool'. */ + /* If the compiler already has both 'bool' and '_Bool', we can assume they + are the same types. */ +# if !@HAVE__BOOL@ +typedef bool _Bool; +# endif +# else +# if !defined __GNUC__ + /* If @HAVE__BOOL@: + Some HP-UX cc and AIX IBM C compiler versions have compiler bugs when + the built-in _Bool type is used. See + http://gcc.gnu.org/ml/gcc-patches/2003-12/msg02303.html + http://lists.gnu.org/archive/html/bug-coreutils/2005-11/msg00161.html + http://lists.gnu.org/archive/html/bug-coreutils/2005-10/msg00086.html + Similar bugs are likely with other compilers as well; this file + wouldn't be used if was working. + So we override the _Bool type. + If !@HAVE__BOOL@: + Need to define _Bool ourselves. As 'signed char' or as an enum type? + Use of a typedef, with SunPRO C, leads to a stupid + "warning: _Bool is a keyword in ISO C99". + Use of an enum type, with IRIX cc, leads to a stupid + "warning(1185): enumerated type mixed with another type". + Even the existence of an enum type, without a typedef, + "Invalid enumerator. (badenum)" with HP-UX cc on Tru64. + The only benefit of the enum, debuggability, is not important + with these compilers. So use 'signed char' and no enum. */ +# define _Bool signed char +# else + /* With this compiler, trust the _Bool type if the compiler has it. */ +# if !@HAVE__BOOL@ + /* For the sake of symbolic names in gdb, define true and false as + enum constants, not only as macros. + It is tempting to write + typedef enum { false = 0, true = 1 } _Bool; + so that gdb prints values of type 'bool' symbolically. But then + values of type '_Bool' might promote to 'int' or 'unsigned int' + (see ISO C 99 6.7.2.2.(4)); however, '_Bool' must promote to 'int' + (see ISO C 99 6.3.1.1.(2)). So add a negative value to the + enum; this ensures that '_Bool' promotes to 'int'. */ +typedef enum { _Bool_must_promote_to_int = -1, false = 0, true = 1 } _Bool; +# endif +# endif +# endif +# define bool _Bool +#endif + +/* The other macros must be usable in preprocessor directives. */ +#ifdef __cplusplus +# define false false +# define true true +#else +# define false 0 +# define true 1 +#endif + +#define __bool_true_false_are_defined 1 + +#endif /* _GL_STDBOOL_H */ diff --git a/gettext-tools/gnulib-lib/stddef.in.h b/gettext-tools/gnulib-lib/stddef.in.h new file mode 100644 index 0000000..f5c0e05 --- /dev/null +++ b/gettext-tools/gnulib-lib/stddef.in.h @@ -0,0 +1,86 @@ +/* A substitute for POSIX 2008 , for platforms that have issues. + + Copyright (C) 2009-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . */ + +/* Written by Eric Blake. */ + +/* + * POSIX 2008 for platforms that have issues. + * + */ + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +#if defined __need_wchar_t || defined __need_size_t \ + || defined __need_ptrdiff_t || defined __need_NULL \ + || defined __need_wint_t +/* Special invocation convention inside gcc header files. In + particular, gcc provides a version of that blindly + redefines NULL even when __need_wint_t was defined, even though + wint_t is not normally provided by . Hence, we must + remember if special invocation has ever been used to obtain wint_t, + in which case we need to clean up NULL yet again. */ + +# if !(defined _@GUARD_PREFIX@_STDDEF_H && defined _GL_STDDEF_WINT_T) +# ifdef __need_wint_t +# undef _@GUARD_PREFIX@_STDDEF_H +# define _GL_STDDEF_WINT_T +# endif +# @INCLUDE_NEXT@ @NEXT_STDDEF_H@ +# endif + +#else +/* Normal invocation convention. */ + +# ifndef _@GUARD_PREFIX@_STDDEF_H + +/* The include_next requires a split double-inclusion guard. */ + +# @INCLUDE_NEXT@ @NEXT_STDDEF_H@ + +# ifndef _@GUARD_PREFIX@_STDDEF_H +# define _@GUARD_PREFIX@_STDDEF_H + +/* On NetBSD 5.0, the definition of NULL lacks proper parentheses. */ +#if @REPLACE_NULL@ +# undef NULL +# ifdef __cplusplus + /* ISO C++ says that the macro NULL must expand to an integer constant + expression, hence '((void *) 0)' is not allowed in C++. */ +# if __GNUG__ >= 3 + /* GNU C++ has a __null macro that behaves like an integer ('int' or + 'long') but has the same size as a pointer. Use that, to avoid + warnings. */ +# define NULL __null +# else +# define NULL 0L +# endif +# else +# define NULL ((void *) 0) +# endif +#endif + +/* Some platforms lack wchar_t. */ +#if !@HAVE_WCHAR_T@ +# define wchar_t int +#endif + +# endif /* _@GUARD_PREFIX@_STDDEF_H */ +# endif /* _@GUARD_PREFIX@_STDDEF_H */ +#endif /* __need_XXX */ diff --git a/gettext-tools/gnulib-lib/stdint.in.h b/gettext-tools/gnulib-lib/stdint.in.h new file mode 100644 index 0000000..247f0d8 --- /dev/null +++ b/gettext-tools/gnulib-lib/stdint.in.h @@ -0,0 +1,635 @@ +/* Copyright (C) 2001-2002, 2004-2014 Free Software Foundation, Inc. + Written by Paul Eggert, Bruno Haible, Sam Steingold, Peter Burwood. + This file is part of gnulib. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . */ + +/* + * ISO C 99 for platforms that lack it. + * + */ + +#ifndef _@GUARD_PREFIX@_STDINT_H + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +/* When including a system file that in turn includes , + use the system , not our substitute. This avoids + problems with (for example) VMS, whose includes + . */ +#define _GL_JUST_INCLUDE_SYSTEM_INTTYPES_H + +/* On Android (Bionic libc), includes this file before + having defined 'time_t'. Therefore in this case avoid including + other system header files; just include the system's . + Ideally we should test __BIONIC__ here, but it is only defined after + has been included; hence test __ANDROID__ instead. */ +#if defined __ANDROID__ && defined _GL_INCLUDING_SYS_TYPES_H +# @INCLUDE_NEXT@ @NEXT_STDINT_H@ +#else + +/* Get those types that are already defined in other system include + files, so that we can "#define int8_t signed char" below without + worrying about a later system include file containing a "typedef + signed char int8_t;" that will get messed up by our macro. Our + macros should all be consistent with the system versions, except + for the "fast" types and macros, which we recommend against using + in public interfaces due to compiler differences. */ + +#if @HAVE_STDINT_H@ +# if defined __sgi && ! defined __c99 + /* Bypass IRIX's if in C89 mode, since it merely annoys users + with "This header file is to be used only for c99 mode compilations" + diagnostics. */ +# define __STDINT_H__ +# endif + + /* Some pre-C++11 implementations need this. */ +# ifdef __cplusplus +# ifndef __STDC_CONSTANT_MACROS +# define __STDC_CONSTANT_MACROS 1 +# endif +# ifndef __STDC_LIMIT_MACROS +# define __STDC_LIMIT_MACROS 1 +# endif +# endif + + /* Other systems may have an incomplete or buggy . + Include it before , since any "#include " + in would reinclude us, skipping our contents because + _@GUARD_PREFIX@_STDINT_H is defined. + The include_next requires a split double-inclusion guard. */ +# @INCLUDE_NEXT@ @NEXT_STDINT_H@ +#endif + +#if ! defined _@GUARD_PREFIX@_STDINT_H && ! defined _GL_JUST_INCLUDE_SYSTEM_STDINT_H +#define _@GUARD_PREFIX@_STDINT_H + +/* defines some of the stdint.h types as well, on glibc, + IRIX 6.5, and OpenBSD 3.8 (via ). + AIX 5.2 isn't needed and causes troubles. + Mac OS X 10.4.6 includes (which is us), but + relies on the system definitions, so include + after @NEXT_STDINT_H@. */ +#if @HAVE_SYS_TYPES_H@ && ! defined _AIX +# include +#endif + +/* Get SCHAR_MIN, SCHAR_MAX, UCHAR_MAX, INT_MIN, INT_MAX, + LONG_MIN, LONG_MAX, ULONG_MAX. */ +#include + +#if @HAVE_INTTYPES_H@ + /* In OpenBSD 3.8, includes , which defines + int{8,16,32,64}_t, uint{8,16,32,64}_t and __BIT_TYPES_DEFINED__. + also defines intptr_t and uintptr_t. */ +# include +#elif @HAVE_SYS_INTTYPES_H@ + /* Solaris 7 has the types except the *_fast*_t types, and + the macros except for *_FAST*_*, INTPTR_MIN, PTRDIFF_MIN, PTRDIFF_MAX. */ +# include +#endif + +#if @HAVE_SYS_BITYPES_H@ && ! defined __BIT_TYPES_DEFINED__ + /* Linux libc4 >= 4.6.7 and libc5 have a that defines + int{8,16,32,64}_t and __BIT_TYPES_DEFINED__. In libc5 >= 5.2.2 it is + included by . */ +# include +#endif + +#undef _GL_JUST_INCLUDE_SYSTEM_INTTYPES_H + +/* Minimum and maximum values for an integer type under the usual assumption. + Return an unspecified value if BITS == 0, adding a check to pacify + picky compilers. */ + +#define _STDINT_MIN(signed, bits, zero) \ + ((signed) ? (- ((zero) + 1) << ((bits) ? (bits) - 1 : 0)) : (zero)) + +#define _STDINT_MAX(signed, bits, zero) \ + ((signed) \ + ? ~ _STDINT_MIN (signed, bits, zero) \ + : /* The expression for the unsigned case. The subtraction of (signed) \ + is a nop in the unsigned case and avoids "signed integer overflow" \ + warnings in the signed case. */ \ + ((((zero) + 1) << ((bits) ? (bits) - 1 - (signed) : 0)) - 1) * 2 + 1) + +#if !GNULIB_defined_stdint_types + +/* 7.18.1.1. Exact-width integer types */ + +/* Here we assume a standard architecture where the hardware integer + types have 8, 16, 32, optionally 64 bits. */ + +#undef int8_t +#undef uint8_t +typedef signed char gl_int8_t; +typedef unsigned char gl_uint8_t; +#define int8_t gl_int8_t +#define uint8_t gl_uint8_t + +#undef int16_t +#undef uint16_t +typedef short int gl_int16_t; +typedef unsigned short int gl_uint16_t; +#define int16_t gl_int16_t +#define uint16_t gl_uint16_t + +#undef int32_t +#undef uint32_t +typedef int gl_int32_t; +typedef unsigned int gl_uint32_t; +#define int32_t gl_int32_t +#define uint32_t gl_uint32_t + +/* If the system defines INT64_MAX, assume int64_t works. That way, + if the underlying platform defines int64_t to be a 64-bit long long + int, the code below won't mistakenly define it to be a 64-bit long + int, which would mess up C++ name mangling. We must use #ifdef + rather than #if, to avoid an error with HP-UX 10.20 cc. */ + +#ifdef INT64_MAX +# define GL_INT64_T +#else +/* Do not undefine int64_t if gnulib is not being used with 64-bit + types, since otherwise it breaks platforms like Tandem/NSK. */ +# if LONG_MAX >> 31 >> 31 == 1 +# undef int64_t +typedef long int gl_int64_t; +# define int64_t gl_int64_t +# define GL_INT64_T +# elif defined _MSC_VER +# undef int64_t +typedef __int64 gl_int64_t; +# define int64_t gl_int64_t +# define GL_INT64_T +# elif @HAVE_LONG_LONG_INT@ +# undef int64_t +typedef long long int gl_int64_t; +# define int64_t gl_int64_t +# define GL_INT64_T +# endif +#endif + +#ifdef UINT64_MAX +# define GL_UINT64_T +#else +# if ULONG_MAX >> 31 >> 31 >> 1 == 1 +# undef uint64_t +typedef unsigned long int gl_uint64_t; +# define uint64_t gl_uint64_t +# define GL_UINT64_T +# elif defined _MSC_VER +# undef uint64_t +typedef unsigned __int64 gl_uint64_t; +# define uint64_t gl_uint64_t +# define GL_UINT64_T +# elif @HAVE_UNSIGNED_LONG_LONG_INT@ +# undef uint64_t +typedef unsigned long long int gl_uint64_t; +# define uint64_t gl_uint64_t +# define GL_UINT64_T +# endif +#endif + +/* Avoid collision with Solaris 2.5.1 etc. */ +#define _UINT8_T +#define _UINT32_T +#define _UINT64_T + + +/* 7.18.1.2. Minimum-width integer types */ + +/* Here we assume a standard architecture where the hardware integer + types have 8, 16, 32, optionally 64 bits. Therefore the leastN_t types + are the same as the corresponding N_t types. */ + +#undef int_least8_t +#undef uint_least8_t +#undef int_least16_t +#undef uint_least16_t +#undef int_least32_t +#undef uint_least32_t +#undef int_least64_t +#undef uint_least64_t +#define int_least8_t int8_t +#define uint_least8_t uint8_t +#define int_least16_t int16_t +#define uint_least16_t uint16_t +#define int_least32_t int32_t +#define uint_least32_t uint32_t +#ifdef GL_INT64_T +# define int_least64_t int64_t +#endif +#ifdef GL_UINT64_T +# define uint_least64_t uint64_t +#endif + +/* 7.18.1.3. Fastest minimum-width integer types */ + +/* Note: Other substitutes may define these types differently. + It is not recommended to use these types in public header files. */ + +/* Here we assume a standard architecture where the hardware integer + types have 8, 16, 32, optionally 64 bits. Therefore the fastN_t types + are taken from the same list of types. The following code normally + uses types consistent with glibc, as that lessens the chance of + incompatibility with older GNU hosts. */ + +#undef int_fast8_t +#undef uint_fast8_t +#undef int_fast16_t +#undef uint_fast16_t +#undef int_fast32_t +#undef uint_fast32_t +#undef int_fast64_t +#undef uint_fast64_t +typedef signed char gl_int_fast8_t; +typedef unsigned char gl_uint_fast8_t; + +#ifdef __sun +/* Define types compatible with SunOS 5.10, so that code compiled under + earlier SunOS versions works with code compiled under SunOS 5.10. */ +typedef int gl_int_fast32_t; +typedef unsigned int gl_uint_fast32_t; +#else +typedef long int gl_int_fast32_t; +typedef unsigned long int gl_uint_fast32_t; +#endif +typedef gl_int_fast32_t gl_int_fast16_t; +typedef gl_uint_fast32_t gl_uint_fast16_t; + +#define int_fast8_t gl_int_fast8_t +#define uint_fast8_t gl_uint_fast8_t +#define int_fast16_t gl_int_fast16_t +#define uint_fast16_t gl_uint_fast16_t +#define int_fast32_t gl_int_fast32_t +#define uint_fast32_t gl_uint_fast32_t +#ifdef GL_INT64_T +# define int_fast64_t int64_t +#endif +#ifdef GL_UINT64_T +# define uint_fast64_t uint64_t +#endif + +/* 7.18.1.4. Integer types capable of holding object pointers */ + +#undef intptr_t +#undef uintptr_t +typedef long int gl_intptr_t; +typedef unsigned long int gl_uintptr_t; +#define intptr_t gl_intptr_t +#define uintptr_t gl_uintptr_t + +/* 7.18.1.5. Greatest-width integer types */ + +/* Note: These types are compiler dependent. It may be unwise to use them in + public header files. */ + +/* If the system defines INTMAX_MAX, assume that intmax_t works, and + similarly for UINTMAX_MAX and uintmax_t. This avoids problems with + assuming one type where another is used by the system. */ + +#ifndef INTMAX_MAX +# undef INTMAX_C +# undef intmax_t +# if @HAVE_LONG_LONG_INT@ && LONG_MAX >> 30 == 1 +typedef long long int gl_intmax_t; +# define intmax_t gl_intmax_t +# elif defined GL_INT64_T +# define intmax_t int64_t +# else +typedef long int gl_intmax_t; +# define intmax_t gl_intmax_t +# endif +#endif + +#ifndef UINTMAX_MAX +# undef UINTMAX_C +# undef uintmax_t +# if @HAVE_UNSIGNED_LONG_LONG_INT@ && ULONG_MAX >> 31 == 1 +typedef unsigned long long int gl_uintmax_t; +# define uintmax_t gl_uintmax_t +# elif defined GL_UINT64_T +# define uintmax_t uint64_t +# else +typedef unsigned long int gl_uintmax_t; +# define uintmax_t gl_uintmax_t +# endif +#endif + +/* Verify that intmax_t and uintmax_t have the same size. Too much code + breaks if this is not the case. If this check fails, the reason is likely + to be found in the autoconf macros. */ +typedef int _verify_intmax_size[sizeof (intmax_t) == sizeof (uintmax_t) + ? 1 : -1]; + +#define GNULIB_defined_stdint_types 1 +#endif /* !GNULIB_defined_stdint_types */ + +/* 7.18.2. Limits of specified-width integer types */ + +/* 7.18.2.1. Limits of exact-width integer types */ + +/* Here we assume a standard architecture where the hardware integer + types have 8, 16, 32, optionally 64 bits. */ + +#undef INT8_MIN +#undef INT8_MAX +#undef UINT8_MAX +#define INT8_MIN (~ INT8_MAX) +#define INT8_MAX 127 +#define UINT8_MAX 255 + +#undef INT16_MIN +#undef INT16_MAX +#undef UINT16_MAX +#define INT16_MIN (~ INT16_MAX) +#define INT16_MAX 32767 +#define UINT16_MAX 65535 + +#undef INT32_MIN +#undef INT32_MAX +#undef UINT32_MAX +#define INT32_MIN (~ INT32_MAX) +#define INT32_MAX 2147483647 +#define UINT32_MAX 4294967295U + +#if defined GL_INT64_T && ! defined INT64_MAX +/* Prefer (- INTMAX_C (1) << 63) over (~ INT64_MAX) because SunPRO C 5.0 + evaluates the latter incorrectly in preprocessor expressions. */ +# define INT64_MIN (- INTMAX_C (1) << 63) +# define INT64_MAX INTMAX_C (9223372036854775807) +#endif + +#if defined GL_UINT64_T && ! defined UINT64_MAX +# define UINT64_MAX UINTMAX_C (18446744073709551615) +#endif + +/* 7.18.2.2. Limits of minimum-width integer types */ + +/* Here we assume a standard architecture where the hardware integer + types have 8, 16, 32, optionally 64 bits. Therefore the leastN_t types + are the same as the corresponding N_t types. */ + +#undef INT_LEAST8_MIN +#undef INT_LEAST8_MAX +#undef UINT_LEAST8_MAX +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST8_MAX INT8_MAX +#define UINT_LEAST8_MAX UINT8_MAX + +#undef INT_LEAST16_MIN +#undef INT_LEAST16_MAX +#undef UINT_LEAST16_MAX +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST16_MAX INT16_MAX +#define UINT_LEAST16_MAX UINT16_MAX + +#undef INT_LEAST32_MIN +#undef INT_LEAST32_MAX +#undef UINT_LEAST32_MAX +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST32_MAX INT32_MAX +#define UINT_LEAST32_MAX UINT32_MAX + +#undef INT_LEAST64_MIN +#undef INT_LEAST64_MAX +#ifdef GL_INT64_T +# define INT_LEAST64_MIN INT64_MIN +# define INT_LEAST64_MAX INT64_MAX +#endif + +#undef UINT_LEAST64_MAX +#ifdef GL_UINT64_T +# define UINT_LEAST64_MAX UINT64_MAX +#endif + +/* 7.18.2.3. Limits of fastest minimum-width integer types */ + +/* Here we assume a standard architecture where the hardware integer + types have 8, 16, 32, optionally 64 bits. Therefore the fastN_t types + are taken from the same list of types. */ + +#undef INT_FAST8_MIN +#undef INT_FAST8_MAX +#undef UINT_FAST8_MAX +#define INT_FAST8_MIN SCHAR_MIN +#define INT_FAST8_MAX SCHAR_MAX +#define UINT_FAST8_MAX UCHAR_MAX + +#undef INT_FAST16_MIN +#undef INT_FAST16_MAX +#undef UINT_FAST16_MAX +#define INT_FAST16_MIN INT_FAST32_MIN +#define INT_FAST16_MAX INT_FAST32_MAX +#define UINT_FAST16_MAX UINT_FAST32_MAX + +#undef INT_FAST32_MIN +#undef INT_FAST32_MAX +#undef UINT_FAST32_MAX +#ifdef __sun +# define INT_FAST32_MIN INT_MIN +# define INT_FAST32_MAX INT_MAX +# define UINT_FAST32_MAX UINT_MAX +#else +# define INT_FAST32_MIN LONG_MIN +# define INT_FAST32_MAX LONG_MAX +# define UINT_FAST32_MAX ULONG_MAX +#endif + +#undef INT_FAST64_MIN +#undef INT_FAST64_MAX +#ifdef GL_INT64_T +# define INT_FAST64_MIN INT64_MIN +# define INT_FAST64_MAX INT64_MAX +#endif + +#undef UINT_FAST64_MAX +#ifdef GL_UINT64_T +# define UINT_FAST64_MAX UINT64_MAX +#endif + +/* 7.18.2.4. Limits of integer types capable of holding object pointers */ + +#undef INTPTR_MIN +#undef INTPTR_MAX +#undef UINTPTR_MAX +#define INTPTR_MIN LONG_MIN +#define INTPTR_MAX LONG_MAX +#define UINTPTR_MAX ULONG_MAX + +/* 7.18.2.5. Limits of greatest-width integer types */ + +#ifndef INTMAX_MAX +# undef INTMAX_MIN +# ifdef INT64_MAX +# define INTMAX_MIN INT64_MIN +# define INTMAX_MAX INT64_MAX +# else +# define INTMAX_MIN INT32_MIN +# define INTMAX_MAX INT32_MAX +# endif +#endif + +#ifndef UINTMAX_MAX +# ifdef UINT64_MAX +# define UINTMAX_MAX UINT64_MAX +# else +# define UINTMAX_MAX UINT32_MAX +# endif +#endif + +/* 7.18.3. Limits of other integer types */ + +/* ptrdiff_t limits */ +#undef PTRDIFF_MIN +#undef PTRDIFF_MAX +#if @APPLE_UNIVERSAL_BUILD@ +# ifdef _LP64 +# define PTRDIFF_MIN _STDINT_MIN (1, 64, 0l) +# define PTRDIFF_MAX _STDINT_MAX (1, 64, 0l) +# else +# define PTRDIFF_MIN _STDINT_MIN (1, 32, 0) +# define PTRDIFF_MAX _STDINT_MAX (1, 32, 0) +# endif +#else +# define PTRDIFF_MIN \ + _STDINT_MIN (1, @BITSIZEOF_PTRDIFF_T@, 0@PTRDIFF_T_SUFFIX@) +# define PTRDIFF_MAX \ + _STDINT_MAX (1, @BITSIZEOF_PTRDIFF_T@, 0@PTRDIFF_T_SUFFIX@) +#endif + +/* sig_atomic_t limits */ +#undef SIG_ATOMIC_MIN +#undef SIG_ATOMIC_MAX +#define SIG_ATOMIC_MIN \ + _STDINT_MIN (@HAVE_SIGNED_SIG_ATOMIC_T@, @BITSIZEOF_SIG_ATOMIC_T@, \ + 0@SIG_ATOMIC_T_SUFFIX@) +#define SIG_ATOMIC_MAX \ + _STDINT_MAX (@HAVE_SIGNED_SIG_ATOMIC_T@, @BITSIZEOF_SIG_ATOMIC_T@, \ + 0@SIG_ATOMIC_T_SUFFIX@) + + +/* size_t limit */ +#undef SIZE_MAX +#if @APPLE_UNIVERSAL_BUILD@ +# ifdef _LP64 +# define SIZE_MAX _STDINT_MAX (0, 64, 0ul) +# else +# define SIZE_MAX _STDINT_MAX (0, 32, 0ul) +# endif +#else +# define SIZE_MAX _STDINT_MAX (0, @BITSIZEOF_SIZE_T@, 0@SIZE_T_SUFFIX@) +#endif + +/* wchar_t limits */ +/* Get WCHAR_MIN, WCHAR_MAX. + This include is not on the top, above, because on OSF/1 4.0 we have a + sequence of nested includes + -> -> -> , and the latter includes + and assumes its types are already defined. */ +#if @HAVE_WCHAR_H@ && ! (defined WCHAR_MIN && defined WCHAR_MAX) + /* BSD/OS 4.0.1 has a bug: , and must be + included before . */ +# include +# include +# include +# define _GL_JUST_INCLUDE_SYSTEM_WCHAR_H +# include +# undef _GL_JUST_INCLUDE_SYSTEM_WCHAR_H +#endif +#undef WCHAR_MIN +#undef WCHAR_MAX +#define WCHAR_MIN \ + _STDINT_MIN (@HAVE_SIGNED_WCHAR_T@, @BITSIZEOF_WCHAR_T@, 0@WCHAR_T_SUFFIX@) +#define WCHAR_MAX \ + _STDINT_MAX (@HAVE_SIGNED_WCHAR_T@, @BITSIZEOF_WCHAR_T@, 0@WCHAR_T_SUFFIX@) + +/* wint_t limits */ +#undef WINT_MIN +#undef WINT_MAX +#define WINT_MIN \ + _STDINT_MIN (@HAVE_SIGNED_WINT_T@, @BITSIZEOF_WINT_T@, 0@WINT_T_SUFFIX@) +#define WINT_MAX \ + _STDINT_MAX (@HAVE_SIGNED_WINT_T@, @BITSIZEOF_WINT_T@, 0@WINT_T_SUFFIX@) + +/* 7.18.4. Macros for integer constants */ + +/* 7.18.4.1. Macros for minimum-width integer constants */ +/* According to ISO C 99 Technical Corrigendum 1 */ + +/* Here we assume a standard architecture where the hardware integer + types have 8, 16, 32, optionally 64 bits, and int is 32 bits. */ + +#undef INT8_C +#undef UINT8_C +#define INT8_C(x) x +#define UINT8_C(x) x + +#undef INT16_C +#undef UINT16_C +#define INT16_C(x) x +#define UINT16_C(x) x + +#undef INT32_C +#undef UINT32_C +#define INT32_C(x) x +#define UINT32_C(x) x ## U + +#undef INT64_C +#undef UINT64_C +#if LONG_MAX >> 31 >> 31 == 1 +# define INT64_C(x) x##L +#elif defined _MSC_VER +# define INT64_C(x) x##i64 +#elif @HAVE_LONG_LONG_INT@ +# define INT64_C(x) x##LL +#endif +#if ULONG_MAX >> 31 >> 31 >> 1 == 1 +# define UINT64_C(x) x##UL +#elif defined _MSC_VER +# define UINT64_C(x) x##ui64 +#elif @HAVE_UNSIGNED_LONG_LONG_INT@ +# define UINT64_C(x) x##ULL +#endif + +/* 7.18.4.2. Macros for greatest-width integer constants */ + +#ifndef INTMAX_C +# if @HAVE_LONG_LONG_INT@ && LONG_MAX >> 30 == 1 +# define INTMAX_C(x) x##LL +# elif defined GL_INT64_T +# define INTMAX_C(x) INT64_C(x) +# else +# define INTMAX_C(x) x##L +# endif +#endif + +#ifndef UINTMAX_C +# if @HAVE_UNSIGNED_LONG_LONG_INT@ && ULONG_MAX >> 31 == 1 +# define UINTMAX_C(x) x##ULL +# elif defined GL_UINT64_T +# define UINTMAX_C(x) UINT64_C(x) +# else +# define UINTMAX_C(x) x##UL +# endif +#endif + +#endif /* _@GUARD_PREFIX@_STDINT_H */ +#endif /* !(defined __ANDROID__ && ...) */ +#endif /* !defined _@GUARD_PREFIX@_STDINT_H && !defined _GL_JUST_INCLUDE_SYSTEM_STDINT_H */ diff --git a/gettext-tools/gnulib-lib/stdio-write.c b/gettext-tools/gnulib-lib/stdio-write.c new file mode 100644 index 0000000..cf9174c --- /dev/null +++ b/gettext-tools/gnulib-lib/stdio-write.c @@ -0,0 +1,198 @@ +/* POSIX compatible FILE stream write function. + Copyright (C) 2008-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2008. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include + +/* Replace these functions only if module 'nonblocking' or module 'sigpipe' is + requested. */ +#if GNULIB_NONBLOCKING || GNULIB_SIGPIPE + +/* On native Windows platforms, SIGPIPE does not exist. When write() is + called on a pipe with no readers, WriteFile() fails with error + GetLastError() = ERROR_NO_DATA, and write() in consequence fails with + error EINVAL. This write() function is at the basis of the function + which flushes the buffer of a FILE stream. */ + +# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ + +# include +# include +# include + +# define WIN32_LEAN_AND_MEAN /* avoid including junk */ +# include + +# include "msvc-nothrow.h" + +# if GNULIB_NONBLOCKING +# define CLEAR_ERRNO \ + errno = 0; +# define HANDLE_ENOSPC \ + if (errno == ENOSPC && ferror (stream)) \ + { \ + int fd = fileno (stream); \ + if (fd >= 0) \ + { \ + HANDLE h = (HANDLE) _get_osfhandle (fd); \ + if (GetFileType (h) == FILE_TYPE_PIPE) \ + { \ + /* h is a pipe or socket. */ \ + DWORD state; \ + if (GetNamedPipeHandleState (h, &state, NULL, NULL, \ + NULL, NULL, 0) \ + && (state & PIPE_NOWAIT) != 0) \ + /* h is a pipe in non-blocking mode. \ + Change errno from ENOSPC to EAGAIN. */ \ + errno = EAGAIN; \ + } \ + } \ + } \ + else +# else +# define CLEAR_ERRNO +# define HANDLE_ENOSPC +# endif + +# if GNULIB_SIGPIPE +# define CLEAR_LastError \ + SetLastError (0); +# define HANDLE_ERROR_NO_DATA \ + if (GetLastError () == ERROR_NO_DATA && ferror (stream)) \ + { \ + int fd = fileno (stream); \ + if (fd >= 0 \ + && GetFileType ((HANDLE) _get_osfhandle (fd)) \ + == FILE_TYPE_PIPE) \ + { \ + /* Try to raise signal SIGPIPE. */ \ + raise (SIGPIPE); \ + /* If it is currently blocked or ignored, change errno from \ + EINVAL to EPIPE. */ \ + errno = EPIPE; \ + } \ + } \ + else +# else +# define CLEAR_LastError +# define HANDLE_ERROR_NO_DATA +# endif + +# define CALL_WITH_SIGPIPE_EMULATION(RETTYPE, EXPRESSION, FAILED) \ + if (ferror (stream)) \ + return (EXPRESSION); \ + else \ + { \ + RETTYPE ret; \ + CLEAR_ERRNO \ + CLEAR_LastError \ + ret = (EXPRESSION); \ + if (FAILED) \ + { \ + HANDLE_ENOSPC \ + HANDLE_ERROR_NO_DATA \ + ; \ + } \ + return ret; \ + } + +# if !REPLACE_PRINTF_POSIX /* avoid collision with printf.c */ +int +printf (const char *format, ...) +{ + int retval; + va_list args; + + va_start (args, format); + retval = vfprintf (stdout, format, args); + va_end (args); + + return retval; +} +# endif + +# if !REPLACE_FPRINTF_POSIX /* avoid collision with fprintf.c */ +int +fprintf (FILE *stream, const char *format, ...) +{ + int retval; + va_list args; + + va_start (args, format); + retval = vfprintf (stream, format, args); + va_end (args); + + return retval; +} +# endif + +# if !REPLACE_VPRINTF_POSIX /* avoid collision with vprintf.c */ +int +vprintf (const char *format, va_list args) +{ + return vfprintf (stdout, format, args); +} +# endif + +# if !REPLACE_VFPRINTF_POSIX /* avoid collision with vfprintf.c */ +int +vfprintf (FILE *stream, const char *format, va_list args) +#undef vfprintf +{ + CALL_WITH_SIGPIPE_EMULATION (int, vfprintf (stream, format, args), ret == EOF) +} +# endif + +int +putchar (int c) +{ + return fputc (c, stdout); +} + +int +fputc (int c, FILE *stream) +#undef fputc +{ + CALL_WITH_SIGPIPE_EMULATION (int, fputc (c, stream), ret == EOF) +} + +int +fputs (const char *string, FILE *stream) +#undef fputs +{ + CALL_WITH_SIGPIPE_EMULATION (int, fputs (string, stream), ret == EOF) +} + +int +puts (const char *string) +#undef puts +{ + FILE *stream = stdout; + CALL_WITH_SIGPIPE_EMULATION (int, puts (string), ret == EOF) +} + +size_t +fwrite (const void *ptr, size_t s, size_t n, FILE *stream) +#undef fwrite +{ + CALL_WITH_SIGPIPE_EMULATION (size_t, fwrite (ptr, s, n, stream), ret < n) +} + +# endif +#endif diff --git a/gettext-tools/gnulib-lib/stdio.in.h b/gettext-tools/gnulib-lib/stdio.in.h new file mode 100644 index 0000000..1e1fe84 --- /dev/null +++ b/gettext-tools/gnulib-lib/stdio.in.h @@ -0,0 +1,1353 @@ +/* A GNU-like . + + Copyright (C) 2004, 2007-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . */ + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +#if defined __need_FILE || defined __need___FILE || defined _GL_ALREADY_INCLUDING_STDIO_H +/* Special invocation convention: + - Inside glibc header files. + - On OSF/1 5.1 we have a sequence of nested includes + -> -> -> -> + -> -> -> . + In this situation, the functions are not yet declared, therefore we cannot + provide the C++ aliases. */ + +#@INCLUDE_NEXT@ @NEXT_STDIO_H@ + +#else +/* Normal invocation convention. */ + +#ifndef _@GUARD_PREFIX@_STDIO_H + +#define _GL_ALREADY_INCLUDING_STDIO_H + +/* The include_next requires a split double-inclusion guard. */ +#@INCLUDE_NEXT@ @NEXT_STDIO_H@ + +#undef _GL_ALREADY_INCLUDING_STDIO_H + +#ifndef _@GUARD_PREFIX@_STDIO_H +#define _@GUARD_PREFIX@_STDIO_H + +/* Get va_list. Needed on many systems, including glibc 2.8. */ +#include + +#include + +/* Get off_t and ssize_t. Needed on many systems, including glibc 2.8 + and eglibc 2.11.2. + May also define off_t to a 64-bit type on native Windows. */ +#include + +/* The __attribute__ feature is available in gcc versions 2.5 and later. + The __-protected variants of the attributes 'format' and 'printf' are + accepted by gcc versions 2.6.4 (effectively 2.7) and later. + We enable _GL_ATTRIBUTE_FORMAT only if these are supported too, because + gnulib and libintl do '#define printf __printf__' when they override + the 'printf' function. */ +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7) +# define _GL_ATTRIBUTE_FORMAT(spec) __attribute__ ((__format__ spec)) +#else +# define _GL_ATTRIBUTE_FORMAT(spec) /* empty */ +#endif + +/* _GL_ATTRIBUTE_FORMAT_PRINTF + indicates to GCC that the function takes a format string and arguments, + where the format string directives are the ones standardized by ISO C99 + and POSIX. */ +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) +# define _GL_ATTRIBUTE_FORMAT_PRINTF(formatstring_parameter, first_argument) \ + _GL_ATTRIBUTE_FORMAT ((__gnu_printf__, formatstring_parameter, first_argument)) +#else +# define _GL_ATTRIBUTE_FORMAT_PRINTF(formatstring_parameter, first_argument) \ + _GL_ATTRIBUTE_FORMAT ((__printf__, formatstring_parameter, first_argument)) +#endif + +/* _GL_ATTRIBUTE_FORMAT_PRINTF_SYSTEM is like _GL_ATTRIBUTE_FORMAT_PRINTF, + except that it indicates to GCC that the supported format string directives + are the ones of the system printf(), rather than the ones standardized by + ISO C99 and POSIX. */ +#define _GL_ATTRIBUTE_FORMAT_PRINTF_SYSTEM(formatstring_parameter, first_argument) \ + _GL_ATTRIBUTE_FORMAT ((__printf__, formatstring_parameter, first_argument)) + +/* _GL_ATTRIBUTE_FORMAT_SCANF + indicates to GCC that the function takes a format string and arguments, + where the format string directives are the ones standardized by ISO C99 + and POSIX. */ +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) +# define _GL_ATTRIBUTE_FORMAT_SCANF(formatstring_parameter, first_argument) \ + _GL_ATTRIBUTE_FORMAT ((__gnu_scanf__, formatstring_parameter, first_argument)) +#else +# define _GL_ATTRIBUTE_FORMAT_SCANF(formatstring_parameter, first_argument) \ + _GL_ATTRIBUTE_FORMAT ((__scanf__, formatstring_parameter, first_argument)) +#endif + +/* _GL_ATTRIBUTE_FORMAT_SCANF_SYSTEM is like _GL_ATTRIBUTE_FORMAT_SCANF, + except that it indicates to GCC that the supported format string directives + are the ones of the system scanf(), rather than the ones standardized by + ISO C99 and POSIX. */ +#define _GL_ATTRIBUTE_FORMAT_SCANF_SYSTEM(formatstring_parameter, first_argument) \ + _GL_ATTRIBUTE_FORMAT ((__scanf__, formatstring_parameter, first_argument)) + +/* Solaris 10 declares renameat in , not in . */ +/* But in any case avoid namespace pollution on glibc systems. */ +#if (@GNULIB_RENAMEAT@ || defined GNULIB_POSIXCHECK) && defined __sun \ + && ! defined __GLIBC__ +# include +#endif + + +/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ + +/* The definition of _GL_ARG_NONNULL is copied here. */ + +/* The definition of _GL_WARN_ON_USE is copied here. */ + +/* Macros for stringification. */ +#define _GL_STDIO_STRINGIZE(token) #token +#define _GL_STDIO_MACROEXPAND_AND_STRINGIZE(token) _GL_STDIO_STRINGIZE(token) + +/* When also using extern inline, suppress the use of static inline in + standard headers of problematic Apple configurations, as Libc at + least through Libc-825.26 (2013-04-09) mishandles it; see, e.g., + . + Perhaps Apple will fix this some day. */ +#if (defined _GL_EXTERN_INLINE_IN_USE && defined __APPLE__ \ + && defined __GNUC__ && defined __STDC__) +# undef putc_unlocked +#endif + +#if @GNULIB_DPRINTF@ +# if @REPLACE_DPRINTF@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define dprintf rpl_dprintf +# endif +_GL_FUNCDECL_RPL (dprintf, int, (int fd, const char *format, ...) + _GL_ATTRIBUTE_FORMAT_PRINTF (2, 3) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (dprintf, int, (int fd, const char *format, ...)); +# else +# if !@HAVE_DPRINTF@ +_GL_FUNCDECL_SYS (dprintf, int, (int fd, const char *format, ...) + _GL_ATTRIBUTE_FORMAT_PRINTF (2, 3) + _GL_ARG_NONNULL ((2))); +# endif +_GL_CXXALIAS_SYS (dprintf, int, (int fd, const char *format, ...)); +# endif +_GL_CXXALIASWARN (dprintf); +#elif defined GNULIB_POSIXCHECK +# undef dprintf +# if HAVE_RAW_DECL_DPRINTF +_GL_WARN_ON_USE (dprintf, "dprintf is unportable - " + "use gnulib module dprintf for portability"); +# endif +#endif + +#if @GNULIB_FCLOSE@ +/* Close STREAM and its underlying file descriptor. */ +# if @REPLACE_FCLOSE@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define fclose rpl_fclose +# endif +_GL_FUNCDECL_RPL (fclose, int, (FILE *stream) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (fclose, int, (FILE *stream)); +# else +_GL_CXXALIAS_SYS (fclose, int, (FILE *stream)); +# endif +_GL_CXXALIASWARN (fclose); +#elif defined GNULIB_POSIXCHECK +# undef fclose +/* Assume fclose is always declared. */ +_GL_WARN_ON_USE (fclose, "fclose is not always POSIX compliant - " + "use gnulib module fclose for portable POSIX compliance"); +#endif + +#if @GNULIB_FDOPEN@ +# if @REPLACE_FDOPEN@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef fdopen +# define fdopen rpl_fdopen +# endif +_GL_FUNCDECL_RPL (fdopen, FILE *, (int fd, const char *mode) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (fdopen, FILE *, (int fd, const char *mode)); +# else +_GL_CXXALIAS_SYS (fdopen, FILE *, (int fd, const char *mode)); +# endif +_GL_CXXALIASWARN (fdopen); +#elif defined GNULIB_POSIXCHECK +# undef fdopen +/* Assume fdopen is always declared. */ +_GL_WARN_ON_USE (fdopen, "fdopen on native Windows platforms is not POSIX compliant - " + "use gnulib module fdopen for portability"); +#endif + +#if @GNULIB_FFLUSH@ +/* Flush all pending data on STREAM according to POSIX rules. Both + output and seekable input streams are supported. + Note! LOSS OF DATA can occur if fflush is applied on an input stream + that is _not_seekable_ or on an update stream that is _not_seekable_ + and in which the most recent operation was input. Seekability can + be tested with lseek(fileno(fp),0,SEEK_CUR). */ +# if @REPLACE_FFLUSH@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define fflush rpl_fflush +# endif +_GL_FUNCDECL_RPL (fflush, int, (FILE *gl_stream)); +_GL_CXXALIAS_RPL (fflush, int, (FILE *gl_stream)); +# else +_GL_CXXALIAS_SYS (fflush, int, (FILE *gl_stream)); +# endif +_GL_CXXALIASWARN (fflush); +#elif defined GNULIB_POSIXCHECK +# undef fflush +/* Assume fflush is always declared. */ +_GL_WARN_ON_USE (fflush, "fflush is not always POSIX compliant - " + "use gnulib module fflush for portable POSIX compliance"); +#endif + +#if @GNULIB_FGETC@ +# if @REPLACE_STDIO_READ_FUNCS@ && @GNULIB_STDIO_H_NONBLOCKING@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef fgetc +# define fgetc rpl_fgetc +# endif +_GL_FUNCDECL_RPL (fgetc, int, (FILE *stream) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (fgetc, int, (FILE *stream)); +# else +_GL_CXXALIAS_SYS (fgetc, int, (FILE *stream)); +# endif +_GL_CXXALIASWARN (fgetc); +#endif + +#if @GNULIB_FGETS@ +# if @REPLACE_STDIO_READ_FUNCS@ && @GNULIB_STDIO_H_NONBLOCKING@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef fgets +# define fgets rpl_fgets +# endif +_GL_FUNCDECL_RPL (fgets, char *, (char *s, int n, FILE *stream) + _GL_ARG_NONNULL ((1, 3))); +_GL_CXXALIAS_RPL (fgets, char *, (char *s, int n, FILE *stream)); +# else +_GL_CXXALIAS_SYS (fgets, char *, (char *s, int n, FILE *stream)); +# endif +_GL_CXXALIASWARN (fgets); +#endif + +#if @GNULIB_FOPEN@ +# if @REPLACE_FOPEN@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef fopen +# define fopen rpl_fopen +# endif +_GL_FUNCDECL_RPL (fopen, FILE *, (const char *filename, const char *mode) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (fopen, FILE *, (const char *filename, const char *mode)); +# else +_GL_CXXALIAS_SYS (fopen, FILE *, (const char *filename, const char *mode)); +# endif +_GL_CXXALIASWARN (fopen); +#elif defined GNULIB_POSIXCHECK +# undef fopen +/* Assume fopen is always declared. */ +_GL_WARN_ON_USE (fopen, "fopen on native Windows platforms is not POSIX compliant - " + "use gnulib module fopen for portability"); +#endif + +#if @GNULIB_FPRINTF_POSIX@ || @GNULIB_FPRINTF@ +# if (@GNULIB_FPRINTF_POSIX@ && @REPLACE_FPRINTF@) \ + || (@GNULIB_FPRINTF@ && @REPLACE_STDIO_WRITE_FUNCS@ && (@GNULIB_STDIO_H_NONBLOCKING@ || @GNULIB_STDIO_H_SIGPIPE@)) +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define fprintf rpl_fprintf +# endif +# define GNULIB_overrides_fprintf 1 +# if @GNULIB_FPRINTF_POSIX@ || @GNULIB_VFPRINTF_POSIX@ +_GL_FUNCDECL_RPL (fprintf, int, (FILE *fp, const char *format, ...) + _GL_ATTRIBUTE_FORMAT_PRINTF (2, 3) + _GL_ARG_NONNULL ((1, 2))); +# else +_GL_FUNCDECL_RPL (fprintf, int, (FILE *fp, const char *format, ...) + _GL_ATTRIBUTE_FORMAT_PRINTF_SYSTEM (2, 3) + _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_RPL (fprintf, int, (FILE *fp, const char *format, ...)); +# else +_GL_CXXALIAS_SYS (fprintf, int, (FILE *fp, const char *format, ...)); +# endif +_GL_CXXALIASWARN (fprintf); +#endif +#if !@GNULIB_FPRINTF_POSIX@ && defined GNULIB_POSIXCHECK +# if !GNULIB_overrides_fprintf +# undef fprintf +# endif +/* Assume fprintf is always declared. */ +_GL_WARN_ON_USE (fprintf, "fprintf is not always POSIX compliant - " + "use gnulib module fprintf-posix for portable " + "POSIX compliance"); +#endif + +#if @GNULIB_FPURGE@ +/* Discard all pending buffered I/O data on STREAM. + STREAM must not be wide-character oriented. + When discarding pending output, the file position is set back to where it + was before the write calls. When discarding pending input, the file + position is advanced to match the end of the previously read input. + Return 0 if successful. Upon error, return -1 and set errno. */ +# if @REPLACE_FPURGE@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define fpurge rpl_fpurge +# endif +_GL_FUNCDECL_RPL (fpurge, int, (FILE *gl_stream) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (fpurge, int, (FILE *gl_stream)); +# else +# if !@HAVE_DECL_FPURGE@ +_GL_FUNCDECL_SYS (fpurge, int, (FILE *gl_stream) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (fpurge, int, (FILE *gl_stream)); +# endif +_GL_CXXALIASWARN (fpurge); +#elif defined GNULIB_POSIXCHECK +# undef fpurge +# if HAVE_RAW_DECL_FPURGE +_GL_WARN_ON_USE (fpurge, "fpurge is not always present - " + "use gnulib module fpurge for portability"); +# endif +#endif + +#if @GNULIB_FPUTC@ +# if @REPLACE_STDIO_WRITE_FUNCS@ && (@GNULIB_STDIO_H_NONBLOCKING@ || @GNULIB_STDIO_H_SIGPIPE@) +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef fputc +# define fputc rpl_fputc +# endif +_GL_FUNCDECL_RPL (fputc, int, (int c, FILE *stream) _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (fputc, int, (int c, FILE *stream)); +# else +_GL_CXXALIAS_SYS (fputc, int, (int c, FILE *stream)); +# endif +_GL_CXXALIASWARN (fputc); +#endif + +#if @GNULIB_FPUTS@ +# if @REPLACE_STDIO_WRITE_FUNCS@ && (@GNULIB_STDIO_H_NONBLOCKING@ || @GNULIB_STDIO_H_SIGPIPE@) +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef fputs +# define fputs rpl_fputs +# endif +_GL_FUNCDECL_RPL (fputs, int, (const char *string, FILE *stream) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (fputs, int, (const char *string, FILE *stream)); +# else +_GL_CXXALIAS_SYS (fputs, int, (const char *string, FILE *stream)); +# endif +_GL_CXXALIASWARN (fputs); +#endif + +#if @GNULIB_FREAD@ +# if @REPLACE_STDIO_READ_FUNCS@ && @GNULIB_STDIO_H_NONBLOCKING@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef fread +# define fread rpl_fread +# endif +_GL_FUNCDECL_RPL (fread, size_t, (void *ptr, size_t s, size_t n, FILE *stream) + _GL_ARG_NONNULL ((4))); +_GL_CXXALIAS_RPL (fread, size_t, (void *ptr, size_t s, size_t n, FILE *stream)); +# else +_GL_CXXALIAS_SYS (fread, size_t, (void *ptr, size_t s, size_t n, FILE *stream)); +# endif +_GL_CXXALIASWARN (fread); +#endif + +#if @GNULIB_FREOPEN@ +# if @REPLACE_FREOPEN@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef freopen +# define freopen rpl_freopen +# endif +_GL_FUNCDECL_RPL (freopen, FILE *, + (const char *filename, const char *mode, FILE *stream) + _GL_ARG_NONNULL ((2, 3))); +_GL_CXXALIAS_RPL (freopen, FILE *, + (const char *filename, const char *mode, FILE *stream)); +# else +_GL_CXXALIAS_SYS (freopen, FILE *, + (const char *filename, const char *mode, FILE *stream)); +# endif +_GL_CXXALIASWARN (freopen); +#elif defined GNULIB_POSIXCHECK +# undef freopen +/* Assume freopen is always declared. */ +_GL_WARN_ON_USE (freopen, + "freopen on native Windows platforms is not POSIX compliant - " + "use gnulib module freopen for portability"); +#endif + +#if @GNULIB_FSCANF@ +# if @REPLACE_STDIO_READ_FUNCS@ && @GNULIB_STDIO_H_NONBLOCKING@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef fscanf +# define fscanf rpl_fscanf +# endif +_GL_FUNCDECL_RPL (fscanf, int, (FILE *stream, const char *format, ...) + _GL_ATTRIBUTE_FORMAT_SCANF_SYSTEM (2, 3) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (fscanf, int, (FILE *stream, const char *format, ...)); +# else +_GL_CXXALIAS_SYS (fscanf, int, (FILE *stream, const char *format, ...)); +# endif +_GL_CXXALIASWARN (fscanf); +#endif + + +/* Set up the following warnings, based on which modules are in use. + GNU Coding Standards discourage the use of fseek, since it imposes + an arbitrary limitation on some 32-bit hosts. Remember that the + fseek module depends on the fseeko module, so we only have three + cases to consider: + + 1. The developer is not using either module. Issue a warning under + GNULIB_POSIXCHECK for both functions, to remind them that both + functions have bugs on some systems. _GL_NO_LARGE_FILES has no + impact on this warning. + + 2. The developer is using both modules. They may be unaware of the + arbitrary limitations of fseek, so issue a warning under + GNULIB_POSIXCHECK. On the other hand, they may be using both + modules intentionally, so the developer can define + _GL_NO_LARGE_FILES in the compilation units where the use of fseek + is safe, to silence the warning. + + 3. The developer is using the fseeko module, but not fseek. Gnulib + guarantees that fseek will still work around platform bugs in that + case, but we presume that the developer is aware of the pitfalls of + fseek and was trying to avoid it, so issue a warning even when + GNULIB_POSIXCHECK is undefined. Again, _GL_NO_LARGE_FILES can be + defined to silence the warning in particular compilation units. + In C++ compilations with GNULIB_NAMESPACE, in order to avoid that + fseek gets defined as a macro, it is recommended that the developer + uses the fseek module, even if he is not calling the fseek function. + + Most gnulib clients that perform stream operations should fall into + category 3. */ + +#if @GNULIB_FSEEK@ +# if defined GNULIB_POSIXCHECK && !defined _GL_NO_LARGE_FILES +# define _GL_FSEEK_WARN /* Category 2, above. */ +# undef fseek +# endif +# if @REPLACE_FSEEK@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef fseek +# define fseek rpl_fseek +# endif +_GL_FUNCDECL_RPL (fseek, int, (FILE *fp, long offset, int whence) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (fseek, int, (FILE *fp, long offset, int whence)); +# else +_GL_CXXALIAS_SYS (fseek, int, (FILE *fp, long offset, int whence)); +# endif +_GL_CXXALIASWARN (fseek); +#endif + +#if @GNULIB_FSEEKO@ +# if !@GNULIB_FSEEK@ && !defined _GL_NO_LARGE_FILES +# define _GL_FSEEK_WARN /* Category 3, above. */ +# undef fseek +# endif +# if @REPLACE_FSEEKO@ +/* Provide an fseeko function that is aware of a preceding fflush(), and which + detects pipes. */ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef fseeko +# define fseeko rpl_fseeko +# endif +_GL_FUNCDECL_RPL (fseeko, int, (FILE *fp, off_t offset, int whence) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (fseeko, int, (FILE *fp, off_t offset, int whence)); +# else +# if ! @HAVE_DECL_FSEEKO@ +_GL_FUNCDECL_SYS (fseeko, int, (FILE *fp, off_t offset, int whence) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (fseeko, int, (FILE *fp, off_t offset, int whence)); +# endif +_GL_CXXALIASWARN (fseeko); +#elif defined GNULIB_POSIXCHECK +# define _GL_FSEEK_WARN /* Category 1, above. */ +# undef fseek +# undef fseeko +# if HAVE_RAW_DECL_FSEEKO +_GL_WARN_ON_USE (fseeko, "fseeko is unportable - " + "use gnulib module fseeko for portability"); +# endif +#endif + +#ifdef _GL_FSEEK_WARN +# undef _GL_FSEEK_WARN +/* Here, either fseek is undefined (but C89 guarantees that it is + declared), or it is defined as rpl_fseek (declared above). */ +_GL_WARN_ON_USE (fseek, "fseek cannot handle files larger than 4 GB " + "on 32-bit platforms - " + "use fseeko function for handling of large files"); +#endif + + +/* ftell, ftello. See the comments on fseek/fseeko. */ + +#if @GNULIB_FTELL@ +# if defined GNULIB_POSIXCHECK && !defined _GL_NO_LARGE_FILES +# define _GL_FTELL_WARN /* Category 2, above. */ +# undef ftell +# endif +# if @REPLACE_FTELL@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef ftell +# define ftell rpl_ftell +# endif +_GL_FUNCDECL_RPL (ftell, long, (FILE *fp) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (ftell, long, (FILE *fp)); +# else +_GL_CXXALIAS_SYS (ftell, long, (FILE *fp)); +# endif +_GL_CXXALIASWARN (ftell); +#endif + +#if @GNULIB_FTELLO@ +# if !@GNULIB_FTELL@ && !defined _GL_NO_LARGE_FILES +# define _GL_FTELL_WARN /* Category 3, above. */ +# undef ftell +# endif +# if @REPLACE_FTELLO@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef ftello +# define ftello rpl_ftello +# endif +_GL_FUNCDECL_RPL (ftello, off_t, (FILE *fp) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (ftello, off_t, (FILE *fp)); +# else +# if ! @HAVE_DECL_FTELLO@ +_GL_FUNCDECL_SYS (ftello, off_t, (FILE *fp) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (ftello, off_t, (FILE *fp)); +# endif +_GL_CXXALIASWARN (ftello); +#elif defined GNULIB_POSIXCHECK +# define _GL_FTELL_WARN /* Category 1, above. */ +# undef ftell +# undef ftello +# if HAVE_RAW_DECL_FTELLO +_GL_WARN_ON_USE (ftello, "ftello is unportable - " + "use gnulib module ftello for portability"); +# endif +#endif + +#ifdef _GL_FTELL_WARN +# undef _GL_FTELL_WARN +/* Here, either ftell is undefined (but C89 guarantees that it is + declared), or it is defined as rpl_ftell (declared above). */ +_GL_WARN_ON_USE (ftell, "ftell cannot handle files larger than 4 GB " + "on 32-bit platforms - " + "use ftello function for handling of large files"); +#endif + + +#if @GNULIB_FWRITE@ +# if @REPLACE_STDIO_WRITE_FUNCS@ && (@GNULIB_STDIO_H_NONBLOCKING@ || @GNULIB_STDIO_H_SIGPIPE@) +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef fwrite +# define fwrite rpl_fwrite +# endif +_GL_FUNCDECL_RPL (fwrite, size_t, + (const void *ptr, size_t s, size_t n, FILE *stream) + _GL_ARG_NONNULL ((1, 4))); +_GL_CXXALIAS_RPL (fwrite, size_t, + (const void *ptr, size_t s, size_t n, FILE *stream)); +# else +_GL_CXXALIAS_SYS (fwrite, size_t, + (const void *ptr, size_t s, size_t n, FILE *stream)); + +/* Work around bug 11959 when fortifying glibc 2.4 through 2.15 + , + which sometimes causes an unwanted diagnostic for fwrite calls. + This affects only function declaration attributes under certain + versions of gcc and clang, and is not needed for C++. */ +# if (0 < __USE_FORTIFY_LEVEL \ + && __GLIBC__ == 2 && 4 <= __GLIBC_MINOR__ && __GLIBC_MINOR__ <= 15 \ + && 3 < __GNUC__ + (4 <= __GNUC_MINOR__) \ + && !defined __cplusplus) +# undef fwrite +# undef fwrite_unlocked +extern size_t __REDIRECT (rpl_fwrite, + (const void *__restrict, size_t, size_t, + FILE *__restrict), + fwrite); +extern size_t __REDIRECT (rpl_fwrite_unlocked, + (const void *__restrict, size_t, size_t, + FILE *__restrict), + fwrite_unlocked); +# define fwrite rpl_fwrite +# define fwrite_unlocked rpl_fwrite_unlocked +# endif +# endif +_GL_CXXALIASWARN (fwrite); +#endif + +#if @GNULIB_GETC@ +# if @REPLACE_STDIO_READ_FUNCS@ && @GNULIB_STDIO_H_NONBLOCKING@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef getc +# define getc rpl_fgetc +# endif +_GL_FUNCDECL_RPL (fgetc, int, (FILE *stream) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL_1 (getc, rpl_fgetc, int, (FILE *stream)); +# else +_GL_CXXALIAS_SYS (getc, int, (FILE *stream)); +# endif +_GL_CXXALIASWARN (getc); +#endif + +#if @GNULIB_GETCHAR@ +# if @REPLACE_STDIO_READ_FUNCS@ && @GNULIB_STDIO_H_NONBLOCKING@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef getchar +# define getchar rpl_getchar +# endif +_GL_FUNCDECL_RPL (getchar, int, (void)); +_GL_CXXALIAS_RPL (getchar, int, (void)); +# else +_GL_CXXALIAS_SYS (getchar, int, (void)); +# endif +_GL_CXXALIASWARN (getchar); +#endif + +#if @GNULIB_GETDELIM@ +/* Read input, up to (and including) the next occurrence of DELIMITER, from + STREAM, store it in *LINEPTR (and NUL-terminate it). + *LINEPTR is a pointer returned from malloc (or NULL), pointing to *LINESIZE + bytes of space. It is realloc'd as necessary. + Return the number of bytes read and stored at *LINEPTR (not including the + NUL terminator), or -1 on error or EOF. */ +# if @REPLACE_GETDELIM@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef getdelim +# define getdelim rpl_getdelim +# endif +_GL_FUNCDECL_RPL (getdelim, ssize_t, + (char **lineptr, size_t *linesize, int delimiter, + FILE *stream) + _GL_ARG_NONNULL ((1, 2, 4))); +_GL_CXXALIAS_RPL (getdelim, ssize_t, + (char **lineptr, size_t *linesize, int delimiter, + FILE *stream)); +# else +# if !@HAVE_DECL_GETDELIM@ +_GL_FUNCDECL_SYS (getdelim, ssize_t, + (char **lineptr, size_t *linesize, int delimiter, + FILE *stream) + _GL_ARG_NONNULL ((1, 2, 4))); +# endif +_GL_CXXALIAS_SYS (getdelim, ssize_t, + (char **lineptr, size_t *linesize, int delimiter, + FILE *stream)); +# endif +_GL_CXXALIASWARN (getdelim); +#elif defined GNULIB_POSIXCHECK +# undef getdelim +# if HAVE_RAW_DECL_GETDELIM +_GL_WARN_ON_USE (getdelim, "getdelim is unportable - " + "use gnulib module getdelim for portability"); +# endif +#endif + +#if @GNULIB_GETLINE@ +/* Read a line, up to (and including) the next newline, from STREAM, store it + in *LINEPTR (and NUL-terminate it). + *LINEPTR is a pointer returned from malloc (or NULL), pointing to *LINESIZE + bytes of space. It is realloc'd as necessary. + Return the number of bytes read and stored at *LINEPTR (not including the + NUL terminator), or -1 on error or EOF. */ +# if @REPLACE_GETLINE@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef getline +# define getline rpl_getline +# endif +_GL_FUNCDECL_RPL (getline, ssize_t, + (char **lineptr, size_t *linesize, FILE *stream) + _GL_ARG_NONNULL ((1, 2, 3))); +_GL_CXXALIAS_RPL (getline, ssize_t, + (char **lineptr, size_t *linesize, FILE *stream)); +# else +# if !@HAVE_DECL_GETLINE@ +_GL_FUNCDECL_SYS (getline, ssize_t, + (char **lineptr, size_t *linesize, FILE *stream) + _GL_ARG_NONNULL ((1, 2, 3))); +# endif +_GL_CXXALIAS_SYS (getline, ssize_t, + (char **lineptr, size_t *linesize, FILE *stream)); +# endif +# if @HAVE_DECL_GETLINE@ +_GL_CXXALIASWARN (getline); +# endif +#elif defined GNULIB_POSIXCHECK +# undef getline +# if HAVE_RAW_DECL_GETLINE +_GL_WARN_ON_USE (getline, "getline is unportable - " + "use gnulib module getline for portability"); +# endif +#endif + +/* It is very rare that the developer ever has full control of stdin, + so any use of gets warrants an unconditional warning; besides, C11 + removed it. */ +#undef gets +#if HAVE_RAW_DECL_GETS +_GL_WARN_ON_USE (gets, "gets is a security hole - use fgets instead"); +#endif + + +#if @GNULIB_OBSTACK_PRINTF@ || @GNULIB_OBSTACK_PRINTF_POSIX@ +struct obstack; +/* Grow an obstack with formatted output. Return the number of + bytes added to OBS. No trailing nul byte is added, and the + object should be closed with obstack_finish before use. Upon + memory allocation error, call obstack_alloc_failed_handler. Upon + other error, return -1. */ +# if @REPLACE_OBSTACK_PRINTF@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define obstack_printf rpl_obstack_printf +# endif +_GL_FUNCDECL_RPL (obstack_printf, int, + (struct obstack *obs, const char *format, ...) + _GL_ATTRIBUTE_FORMAT_PRINTF (2, 3) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (obstack_printf, int, + (struct obstack *obs, const char *format, ...)); +# else +# if !@HAVE_DECL_OBSTACK_PRINTF@ +_GL_FUNCDECL_SYS (obstack_printf, int, + (struct obstack *obs, const char *format, ...) + _GL_ATTRIBUTE_FORMAT_PRINTF (2, 3) + _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (obstack_printf, int, + (struct obstack *obs, const char *format, ...)); +# endif +_GL_CXXALIASWARN (obstack_printf); +# if @REPLACE_OBSTACK_PRINTF@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define obstack_vprintf rpl_obstack_vprintf +# endif +_GL_FUNCDECL_RPL (obstack_vprintf, int, + (struct obstack *obs, const char *format, va_list args) + _GL_ATTRIBUTE_FORMAT_PRINTF (2, 0) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (obstack_vprintf, int, + (struct obstack *obs, const char *format, va_list args)); +# else +# if !@HAVE_DECL_OBSTACK_PRINTF@ +_GL_FUNCDECL_SYS (obstack_vprintf, int, + (struct obstack *obs, const char *format, va_list args) + _GL_ATTRIBUTE_FORMAT_PRINTF (2, 0) + _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (obstack_vprintf, int, + (struct obstack *obs, const char *format, va_list args)); +# endif +_GL_CXXALIASWARN (obstack_vprintf); +#endif + +#if @GNULIB_PCLOSE@ +# if !@HAVE_PCLOSE@ +_GL_FUNCDECL_SYS (pclose, int, (FILE *stream) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (pclose, int, (FILE *stream)); +_GL_CXXALIASWARN (pclose); +#elif defined GNULIB_POSIXCHECK +# undef pclose +# if HAVE_RAW_DECL_PCLOSE +_GL_WARN_ON_USE (pclose, "pclose is unportable - " + "use gnulib module pclose for more portability"); +# endif +#endif + +#if @GNULIB_PERROR@ +/* Print a message to standard error, describing the value of ERRNO, + (if STRING is not NULL and not empty) prefixed with STRING and ": ", + and terminated with a newline. */ +# if @REPLACE_PERROR@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define perror rpl_perror +# endif +_GL_FUNCDECL_RPL (perror, void, (const char *string)); +_GL_CXXALIAS_RPL (perror, void, (const char *string)); +# else +_GL_CXXALIAS_SYS (perror, void, (const char *string)); +# endif +_GL_CXXALIASWARN (perror); +#elif defined GNULIB_POSIXCHECK +# undef perror +/* Assume perror is always declared. */ +_GL_WARN_ON_USE (perror, "perror is not always POSIX compliant - " + "use gnulib module perror for portability"); +#endif + +#if @GNULIB_POPEN@ +# if @REPLACE_POPEN@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef popen +# define popen rpl_popen +# endif +_GL_FUNCDECL_RPL (popen, FILE *, (const char *cmd, const char *mode) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (popen, FILE *, (const char *cmd, const char *mode)); +# else +# if !@HAVE_POPEN@ +_GL_FUNCDECL_SYS (popen, FILE *, (const char *cmd, const char *mode) + _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (popen, FILE *, (const char *cmd, const char *mode)); +# endif +_GL_CXXALIASWARN (popen); +#elif defined GNULIB_POSIXCHECK +# undef popen +# if HAVE_RAW_DECL_POPEN +_GL_WARN_ON_USE (popen, "popen is buggy on some platforms - " + "use gnulib module popen or pipe for more portability"); +# endif +#endif + +#if @GNULIB_PRINTF_POSIX@ || @GNULIB_PRINTF@ +# if (@GNULIB_PRINTF_POSIX@ && @REPLACE_PRINTF@) \ + || (@GNULIB_PRINTF@ && @REPLACE_STDIO_WRITE_FUNCS@ && (@GNULIB_STDIO_H_NONBLOCKING@ || @GNULIB_STDIO_H_SIGPIPE@)) +# if defined __GNUC__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +/* Don't break __attribute__((format(printf,M,N))). */ +# define printf __printf__ +# endif +# if @GNULIB_PRINTF_POSIX@ || @GNULIB_VFPRINTF_POSIX@ +_GL_FUNCDECL_RPL_1 (__printf__, int, + (const char *format, ...) + __asm__ (@ASM_SYMBOL_PREFIX@ + _GL_STDIO_MACROEXPAND_AND_STRINGIZE(rpl_printf)) + _GL_ATTRIBUTE_FORMAT_PRINTF (1, 2) + _GL_ARG_NONNULL ((1))); +# else +_GL_FUNCDECL_RPL_1 (__printf__, int, + (const char *format, ...) + __asm__ (@ASM_SYMBOL_PREFIX@ + _GL_STDIO_MACROEXPAND_AND_STRINGIZE(rpl_printf)) + _GL_ATTRIBUTE_FORMAT_PRINTF_SYSTEM (1, 2) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_RPL_1 (printf, __printf__, int, (const char *format, ...)); +# else +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define printf rpl_printf +# endif +_GL_FUNCDECL_RPL (printf, int, + (const char *format, ...) + _GL_ATTRIBUTE_FORMAT_PRINTF (1, 2) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (printf, int, (const char *format, ...)); +# endif +# define GNULIB_overrides_printf 1 +# else +_GL_CXXALIAS_SYS (printf, int, (const char *format, ...)); +# endif +_GL_CXXALIASWARN (printf); +#endif +#if !@GNULIB_PRINTF_POSIX@ && defined GNULIB_POSIXCHECK +# if !GNULIB_overrides_printf +# undef printf +# endif +/* Assume printf is always declared. */ +_GL_WARN_ON_USE (printf, "printf is not always POSIX compliant - " + "use gnulib module printf-posix for portable " + "POSIX compliance"); +#endif + +#if @GNULIB_PUTC@ +# if @REPLACE_STDIO_WRITE_FUNCS@ && (@GNULIB_STDIO_H_NONBLOCKING@ || @GNULIB_STDIO_H_SIGPIPE@) +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef putc +# define putc rpl_fputc +# endif +_GL_FUNCDECL_RPL (fputc, int, (int c, FILE *stream) _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL_1 (putc, rpl_fputc, int, (int c, FILE *stream)); +# else +_GL_CXXALIAS_SYS (putc, int, (int c, FILE *stream)); +# endif +_GL_CXXALIASWARN (putc); +#endif + +#if @GNULIB_PUTCHAR@ +# if @REPLACE_STDIO_WRITE_FUNCS@ && (@GNULIB_STDIO_H_NONBLOCKING@ || @GNULIB_STDIO_H_SIGPIPE@) +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef putchar +# define putchar rpl_putchar +# endif +_GL_FUNCDECL_RPL (putchar, int, (int c)); +_GL_CXXALIAS_RPL (putchar, int, (int c)); +# else +_GL_CXXALIAS_SYS (putchar, int, (int c)); +# endif +_GL_CXXALIASWARN (putchar); +#endif + +#if @GNULIB_PUTS@ +# if @REPLACE_STDIO_WRITE_FUNCS@ && (@GNULIB_STDIO_H_NONBLOCKING@ || @GNULIB_STDIO_H_SIGPIPE@) +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef puts +# define puts rpl_puts +# endif +_GL_FUNCDECL_RPL (puts, int, (const char *string) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (puts, int, (const char *string)); +# else +_GL_CXXALIAS_SYS (puts, int, (const char *string)); +# endif +_GL_CXXALIASWARN (puts); +#endif + +#if @GNULIB_REMOVE@ +# if @REPLACE_REMOVE@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef remove +# define remove rpl_remove +# endif +_GL_FUNCDECL_RPL (remove, int, (const char *name) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (remove, int, (const char *name)); +# else +_GL_CXXALIAS_SYS (remove, int, (const char *name)); +# endif +_GL_CXXALIASWARN (remove); +#elif defined GNULIB_POSIXCHECK +# undef remove +/* Assume remove is always declared. */ +_GL_WARN_ON_USE (remove, "remove cannot handle directories on some platforms - " + "use gnulib module remove for more portability"); +#endif + +#if @GNULIB_RENAME@ +# if @REPLACE_RENAME@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef rename +# define rename rpl_rename +# endif +_GL_FUNCDECL_RPL (rename, int, + (const char *old_filename, const char *new_filename) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (rename, int, + (const char *old_filename, const char *new_filename)); +# else +_GL_CXXALIAS_SYS (rename, int, + (const char *old_filename, const char *new_filename)); +# endif +_GL_CXXALIASWARN (rename); +#elif defined GNULIB_POSIXCHECK +# undef rename +/* Assume rename is always declared. */ +_GL_WARN_ON_USE (rename, "rename is buggy on some platforms - " + "use gnulib module rename for more portability"); +#endif + +#if @GNULIB_RENAMEAT@ +# if @REPLACE_RENAMEAT@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef renameat +# define renameat rpl_renameat +# endif +_GL_FUNCDECL_RPL (renameat, int, + (int fd1, char const *file1, int fd2, char const *file2) + _GL_ARG_NONNULL ((2, 4))); +_GL_CXXALIAS_RPL (renameat, int, + (int fd1, char const *file1, int fd2, char const *file2)); +# else +# if !@HAVE_RENAMEAT@ +_GL_FUNCDECL_SYS (renameat, int, + (int fd1, char const *file1, int fd2, char const *file2) + _GL_ARG_NONNULL ((2, 4))); +# endif +_GL_CXXALIAS_SYS (renameat, int, + (int fd1, char const *file1, int fd2, char const *file2)); +# endif +_GL_CXXALIASWARN (renameat); +#elif defined GNULIB_POSIXCHECK +# undef renameat +# if HAVE_RAW_DECL_RENAMEAT +_GL_WARN_ON_USE (renameat, "renameat is not portable - " + "use gnulib module renameat for portability"); +# endif +#endif + +#if @GNULIB_SCANF@ +# if @REPLACE_STDIO_READ_FUNCS@ && @GNULIB_STDIO_H_NONBLOCKING@ +# if defined __GNUC__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef scanf +/* Don't break __attribute__((format(scanf,M,N))). */ +# define scanf __scanf__ +# endif +_GL_FUNCDECL_RPL_1 (__scanf__, int, + (const char *format, ...) + __asm__ (@ASM_SYMBOL_PREFIX@ + _GL_STDIO_MACROEXPAND_AND_STRINGIZE(rpl_scanf)) + _GL_ATTRIBUTE_FORMAT_SCANF_SYSTEM (1, 2) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL_1 (scanf, __scanf__, int, (const char *format, ...)); +# else +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef scanf +# define scanf rpl_scanf +# endif +_GL_FUNCDECL_RPL (scanf, int, (const char *format, ...) + _GL_ATTRIBUTE_FORMAT_SCANF_SYSTEM (1, 2) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (scanf, int, (const char *format, ...)); +# endif +# else +_GL_CXXALIAS_SYS (scanf, int, (const char *format, ...)); +# endif +_GL_CXXALIASWARN (scanf); +#endif + +#if @GNULIB_SNPRINTF@ +# if @REPLACE_SNPRINTF@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define snprintf rpl_snprintf +# endif +_GL_FUNCDECL_RPL (snprintf, int, + (char *str, size_t size, const char *format, ...) + _GL_ATTRIBUTE_FORMAT_PRINTF (3, 4) + _GL_ARG_NONNULL ((3))); +_GL_CXXALIAS_RPL (snprintf, int, + (char *str, size_t size, const char *format, ...)); +# else +# if !@HAVE_DECL_SNPRINTF@ +_GL_FUNCDECL_SYS (snprintf, int, + (char *str, size_t size, const char *format, ...) + _GL_ATTRIBUTE_FORMAT_PRINTF (3, 4) + _GL_ARG_NONNULL ((3))); +# endif +_GL_CXXALIAS_SYS (snprintf, int, + (char *str, size_t size, const char *format, ...)); +# endif +_GL_CXXALIASWARN (snprintf); +#elif defined GNULIB_POSIXCHECK +# undef snprintf +# if HAVE_RAW_DECL_SNPRINTF +_GL_WARN_ON_USE (snprintf, "snprintf is unportable - " + "use gnulib module snprintf for portability"); +# endif +#endif + +/* Some people would argue that all sprintf uses should be warned about + (for example, OpenBSD issues a link warning for it), + since it can cause security holes due to buffer overruns. + However, we believe that sprintf can be used safely, and is more + efficient than snprintf in those safe cases; and as proof of our + belief, we use sprintf in several gnulib modules. So this header + intentionally avoids adding a warning to sprintf except when + GNULIB_POSIXCHECK is defined. */ + +#if @GNULIB_SPRINTF_POSIX@ +# if @REPLACE_SPRINTF@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define sprintf rpl_sprintf +# endif +_GL_FUNCDECL_RPL (sprintf, int, (char *str, const char *format, ...) + _GL_ATTRIBUTE_FORMAT_PRINTF (2, 3) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (sprintf, int, (char *str, const char *format, ...)); +# else +_GL_CXXALIAS_SYS (sprintf, int, (char *str, const char *format, ...)); +# endif +_GL_CXXALIASWARN (sprintf); +#elif defined GNULIB_POSIXCHECK +# undef sprintf +/* Assume sprintf is always declared. */ +_GL_WARN_ON_USE (sprintf, "sprintf is not always POSIX compliant - " + "use gnulib module sprintf-posix for portable " + "POSIX compliance"); +#endif + +#if @GNULIB_TMPFILE@ +# if @REPLACE_TMPFILE@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define tmpfile rpl_tmpfile +# endif +_GL_FUNCDECL_RPL (tmpfile, FILE *, (void)); +_GL_CXXALIAS_RPL (tmpfile, FILE *, (void)); +# else +_GL_CXXALIAS_SYS (tmpfile, FILE *, (void)); +# endif +_GL_CXXALIASWARN (tmpfile); +#elif defined GNULIB_POSIXCHECK +# undef tmpfile +# if HAVE_RAW_DECL_TMPFILE +_GL_WARN_ON_USE (tmpfile, "tmpfile is not usable on mingw - " + "use gnulib module tmpfile for portability"); +# endif +#endif + +#if @GNULIB_VASPRINTF@ +/* Write formatted output to a string dynamically allocated with malloc(). + If the memory allocation succeeds, store the address of the string in + *RESULT and return the number of resulting bytes, excluding the trailing + NUL. Upon memory allocation error, or some other error, return -1. */ +# if @REPLACE_VASPRINTF@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define asprintf rpl_asprintf +# endif +_GL_FUNCDECL_RPL (asprintf, int, + (char **result, const char *format, ...) + _GL_ATTRIBUTE_FORMAT_PRINTF (2, 3) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (asprintf, int, + (char **result, const char *format, ...)); +# else +# if !@HAVE_VASPRINTF@ +_GL_FUNCDECL_SYS (asprintf, int, + (char **result, const char *format, ...) + _GL_ATTRIBUTE_FORMAT_PRINTF (2, 3) + _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (asprintf, int, + (char **result, const char *format, ...)); +# endif +_GL_CXXALIASWARN (asprintf); +# if @REPLACE_VASPRINTF@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define vasprintf rpl_vasprintf +# endif +_GL_FUNCDECL_RPL (vasprintf, int, + (char **result, const char *format, va_list args) + _GL_ATTRIBUTE_FORMAT_PRINTF (2, 0) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (vasprintf, int, + (char **result, const char *format, va_list args)); +# else +# if !@HAVE_VASPRINTF@ +_GL_FUNCDECL_SYS (vasprintf, int, + (char **result, const char *format, va_list args) + _GL_ATTRIBUTE_FORMAT_PRINTF (2, 0) + _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (vasprintf, int, + (char **result, const char *format, va_list args)); +# endif +_GL_CXXALIASWARN (vasprintf); +#endif + +#if @GNULIB_VDPRINTF@ +# if @REPLACE_VDPRINTF@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define vdprintf rpl_vdprintf +# endif +_GL_FUNCDECL_RPL (vdprintf, int, (int fd, const char *format, va_list args) + _GL_ATTRIBUTE_FORMAT_PRINTF (2, 0) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (vdprintf, int, (int fd, const char *format, va_list args)); +# else +# if !@HAVE_VDPRINTF@ +_GL_FUNCDECL_SYS (vdprintf, int, (int fd, const char *format, va_list args) + _GL_ATTRIBUTE_FORMAT_PRINTF (2, 0) + _GL_ARG_NONNULL ((2))); +# endif +/* Need to cast, because on Solaris, the third parameter will likely be + __va_list args. */ +_GL_CXXALIAS_SYS_CAST (vdprintf, int, + (int fd, const char *format, va_list args)); +# endif +_GL_CXXALIASWARN (vdprintf); +#elif defined GNULIB_POSIXCHECK +# undef vdprintf +# if HAVE_RAW_DECL_VDPRINTF +_GL_WARN_ON_USE (vdprintf, "vdprintf is unportable - " + "use gnulib module vdprintf for portability"); +# endif +#endif + +#if @GNULIB_VFPRINTF_POSIX@ || @GNULIB_VFPRINTF@ +# if (@GNULIB_VFPRINTF_POSIX@ && @REPLACE_VFPRINTF@) \ + || (@GNULIB_VFPRINTF@ && @REPLACE_STDIO_WRITE_FUNCS@ && (@GNULIB_STDIO_H_NONBLOCKING@ || @GNULIB_STDIO_H_SIGPIPE@)) +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define vfprintf rpl_vfprintf +# endif +# define GNULIB_overrides_vfprintf 1 +# if @GNULIB_VFPRINTF_POSIX@ +_GL_FUNCDECL_RPL (vfprintf, int, (FILE *fp, const char *format, va_list args) + _GL_ATTRIBUTE_FORMAT_PRINTF (2, 0) + _GL_ARG_NONNULL ((1, 2))); +# else +_GL_FUNCDECL_RPL (vfprintf, int, (FILE *fp, const char *format, va_list args) + _GL_ATTRIBUTE_FORMAT_PRINTF_SYSTEM (2, 0) + _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_RPL (vfprintf, int, (FILE *fp, const char *format, va_list args)); +# else +/* Need to cast, because on Solaris, the third parameter is + __va_list args + and GCC's fixincludes did not change this to __gnuc_va_list. */ +_GL_CXXALIAS_SYS_CAST (vfprintf, int, + (FILE *fp, const char *format, va_list args)); +# endif +_GL_CXXALIASWARN (vfprintf); +#endif +#if !@GNULIB_VFPRINTF_POSIX@ && defined GNULIB_POSIXCHECK +# if !GNULIB_overrides_vfprintf +# undef vfprintf +# endif +/* Assume vfprintf is always declared. */ +_GL_WARN_ON_USE (vfprintf, "vfprintf is not always POSIX compliant - " + "use gnulib module vfprintf-posix for portable " + "POSIX compliance"); +#endif + +#if @GNULIB_VFSCANF@ +# if @REPLACE_STDIO_READ_FUNCS@ && @GNULIB_STDIO_H_NONBLOCKING@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef vfscanf +# define vfscanf rpl_vfscanf +# endif +_GL_FUNCDECL_RPL (vfscanf, int, + (FILE *stream, const char *format, va_list args) + _GL_ATTRIBUTE_FORMAT_SCANF_SYSTEM (2, 0) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (vfscanf, int, + (FILE *stream, const char *format, va_list args)); +# else +_GL_CXXALIAS_SYS (vfscanf, int, + (FILE *stream, const char *format, va_list args)); +# endif +_GL_CXXALIASWARN (vfscanf); +#endif + +#if @GNULIB_VPRINTF_POSIX@ || @GNULIB_VPRINTF@ +# if (@GNULIB_VPRINTF_POSIX@ && @REPLACE_VPRINTF@) \ + || (@GNULIB_VPRINTF@ && @REPLACE_STDIO_WRITE_FUNCS@ && (@GNULIB_STDIO_H_NONBLOCKING@ || @GNULIB_STDIO_H_SIGPIPE@)) +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define vprintf rpl_vprintf +# endif +# define GNULIB_overrides_vprintf 1 +# if @GNULIB_VPRINTF_POSIX@ || @GNULIB_VFPRINTF_POSIX@ +_GL_FUNCDECL_RPL (vprintf, int, (const char *format, va_list args) + _GL_ATTRIBUTE_FORMAT_PRINTF (1, 0) + _GL_ARG_NONNULL ((1))); +# else +_GL_FUNCDECL_RPL (vprintf, int, (const char *format, va_list args) + _GL_ATTRIBUTE_FORMAT_PRINTF_SYSTEM (1, 0) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_RPL (vprintf, int, (const char *format, va_list args)); +# else +/* Need to cast, because on Solaris, the second parameter is + __va_list args + and GCC's fixincludes did not change this to __gnuc_va_list. */ +_GL_CXXALIAS_SYS_CAST (vprintf, int, (const char *format, va_list args)); +# endif +_GL_CXXALIASWARN (vprintf); +#endif +#if !@GNULIB_VPRINTF_POSIX@ && defined GNULIB_POSIXCHECK +# if !GNULIB_overrides_vprintf +# undef vprintf +# endif +/* Assume vprintf is always declared. */ +_GL_WARN_ON_USE (vprintf, "vprintf is not always POSIX compliant - " + "use gnulib module vprintf-posix for portable " + "POSIX compliance"); +#endif + +#if @GNULIB_VSCANF@ +# if @REPLACE_STDIO_READ_FUNCS@ && @GNULIB_STDIO_H_NONBLOCKING@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef vscanf +# define vscanf rpl_vscanf +# endif +_GL_FUNCDECL_RPL (vscanf, int, (const char *format, va_list args) + _GL_ATTRIBUTE_FORMAT_SCANF_SYSTEM (1, 0) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (vscanf, int, (const char *format, va_list args)); +# else +_GL_CXXALIAS_SYS (vscanf, int, (const char *format, va_list args)); +# endif +_GL_CXXALIASWARN (vscanf); +#endif + +#if @GNULIB_VSNPRINTF@ +# if @REPLACE_VSNPRINTF@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define vsnprintf rpl_vsnprintf +# endif +_GL_FUNCDECL_RPL (vsnprintf, int, + (char *str, size_t size, const char *format, va_list args) + _GL_ATTRIBUTE_FORMAT_PRINTF (3, 0) + _GL_ARG_NONNULL ((3))); +_GL_CXXALIAS_RPL (vsnprintf, int, + (char *str, size_t size, const char *format, va_list args)); +# else +# if !@HAVE_DECL_VSNPRINTF@ +_GL_FUNCDECL_SYS (vsnprintf, int, + (char *str, size_t size, const char *format, va_list args) + _GL_ATTRIBUTE_FORMAT_PRINTF (3, 0) + _GL_ARG_NONNULL ((3))); +# endif +_GL_CXXALIAS_SYS (vsnprintf, int, + (char *str, size_t size, const char *format, va_list args)); +# endif +_GL_CXXALIASWARN (vsnprintf); +#elif defined GNULIB_POSIXCHECK +# undef vsnprintf +# if HAVE_RAW_DECL_VSNPRINTF +_GL_WARN_ON_USE (vsnprintf, "vsnprintf is unportable - " + "use gnulib module vsnprintf for portability"); +# endif +#endif + +#if @GNULIB_VSPRINTF_POSIX@ +# if @REPLACE_VSPRINTF@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define vsprintf rpl_vsprintf +# endif +_GL_FUNCDECL_RPL (vsprintf, int, + (char *str, const char *format, va_list args) + _GL_ATTRIBUTE_FORMAT_PRINTF (2, 0) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (vsprintf, int, + (char *str, const char *format, va_list args)); +# else +/* Need to cast, because on Solaris, the third parameter is + __va_list args + and GCC's fixincludes did not change this to __gnuc_va_list. */ +_GL_CXXALIAS_SYS_CAST (vsprintf, int, + (char *str, const char *format, va_list args)); +# endif +_GL_CXXALIASWARN (vsprintf); +#elif defined GNULIB_POSIXCHECK +# undef vsprintf +/* Assume vsprintf is always declared. */ +_GL_WARN_ON_USE (vsprintf, "vsprintf is not always POSIX compliant - " + "use gnulib module vsprintf-posix for portable " + "POSIX compliance"); +#endif + +#endif /* _@GUARD_PREFIX@_STDIO_H */ +#endif /* _@GUARD_PREFIX@_STDIO_H */ +#endif diff --git a/gettext-tools/gnulib-lib/stdlib.in.h b/gettext-tools/gnulib-lib/stdlib.in.h new file mode 100644 index 0000000..ee64324 --- /dev/null +++ b/gettext-tools/gnulib-lib/stdlib.in.h @@ -0,0 +1,977 @@ +/* A GNU-like . + + Copyright (C) 1995, 2001-2004, 2006-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +#if defined __need_system_stdlib_h || defined __need_malloc_and_calloc +/* Special invocation conventions inside some gnulib header files, + and inside some glibc header files, respectively. */ + +#@INCLUDE_NEXT@ @NEXT_STDLIB_H@ + +#else +/* Normal invocation convention. */ + +#ifndef _@GUARD_PREFIX@_STDLIB_H + +/* The include_next requires a split double-inclusion guard. */ +#@INCLUDE_NEXT@ @NEXT_STDLIB_H@ + +#ifndef _@GUARD_PREFIX@_STDLIB_H +#define _@GUARD_PREFIX@_STDLIB_H + +/* NetBSD 5.0 mis-defines NULL. */ +#include + +/* MirBSD 10 defines WEXITSTATUS in , not in . */ +#if @GNULIB_SYSTEM_POSIX@ && !defined WEXITSTATUS +# include +#endif + +/* Solaris declares getloadavg() in . */ +#if (@GNULIB_GETLOADAVG@ || defined GNULIB_POSIXCHECK) && @HAVE_SYS_LOADAVG_H@ +# include +#endif + +/* Native Windows platforms declare mktemp() in . */ +#if 0 && ((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__) +# include +#endif + +#if @GNULIB_RANDOM_R@ + +/* OSF/1 5.1 declares 'struct random_data' in , which is included + from if _REENTRANT is defined. Include it whenever we need + 'struct random_data'. */ +# if @HAVE_RANDOM_H@ +# include +# endif + +# if !@HAVE_STRUCT_RANDOM_DATA@ || @REPLACE_RANDOM_R@ || !@HAVE_RANDOM_R@ +# include +# endif + +# if !@HAVE_STRUCT_RANDOM_DATA@ +/* Define 'struct random_data'. + But allow multiple gnulib generated replacements to coexist. */ +# if !GNULIB_defined_struct_random_data +struct random_data +{ + int32_t *fptr; /* Front pointer. */ + int32_t *rptr; /* Rear pointer. */ + int32_t *state; /* Array of state values. */ + int rand_type; /* Type of random number generator. */ + int rand_deg; /* Degree of random number generator. */ + int rand_sep; /* Distance between front and rear. */ + int32_t *end_ptr; /* Pointer behind state table. */ +}; +# define GNULIB_defined_struct_random_data 1 +# endif +# endif +#endif + +#if (@GNULIB_MKSTEMP@ || @GNULIB_MKSTEMPS@ || @GNULIB_GETSUBOPT@ || defined GNULIB_POSIXCHECK) && ! defined __GLIBC__ && !((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__) +/* On Mac OS X 10.3, only declares mkstemp. */ +/* On Mac OS X 10.5, only declares mkstemps. */ +/* On Cygwin 1.7.1, only declares getsubopt. */ +/* But avoid namespace pollution on glibc systems and native Windows. */ +# include +#endif + +/* The __attribute__ feature is available in gcc versions 2.5 and later. + The attribute __pure__ was added in gcc 2.96. */ +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96) +# define _GL_ATTRIBUTE_PURE __attribute__ ((__pure__)) +#else +# define _GL_ATTRIBUTE_PURE /* empty */ +#endif + +/* The definition of _Noreturn is copied here. */ + +/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ + +/* The definition of _GL_ARG_NONNULL is copied here. */ + +/* The definition of _GL_WARN_ON_USE is copied here. */ + + +/* Some systems do not define EXIT_*, despite otherwise supporting C89. */ +#ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 +#endif +/* Tandem/NSK and other platforms that define EXIT_FAILURE as -1 interfere + with proper operation of xargs. */ +#ifndef EXIT_FAILURE +# define EXIT_FAILURE 1 +#elif EXIT_FAILURE != 1 +# undef EXIT_FAILURE +# define EXIT_FAILURE 1 +#endif + + +#if @GNULIB__EXIT@ +/* Terminate the current process with the given return code, without running + the 'atexit' handlers. */ +# if !@HAVE__EXIT@ +_GL_FUNCDECL_SYS (_Exit, _Noreturn void, (int status)); +# endif +_GL_CXXALIAS_SYS (_Exit, void, (int status)); +_GL_CXXALIASWARN (_Exit); +#elif defined GNULIB_POSIXCHECK +# undef _Exit +# if HAVE_RAW_DECL__EXIT +_GL_WARN_ON_USE (_Exit, "_Exit is unportable - " + "use gnulib module _Exit for portability"); +# endif +#endif + + +#if @GNULIB_ATOLL@ +/* Parse a signed decimal integer. + Returns the value of the integer. Errors are not detected. */ +# if !@HAVE_ATOLL@ +_GL_FUNCDECL_SYS (atoll, long long, (const char *string) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (atoll, long long, (const char *string)); +_GL_CXXALIASWARN (atoll); +#elif defined GNULIB_POSIXCHECK +# undef atoll +# if HAVE_RAW_DECL_ATOLL +_GL_WARN_ON_USE (atoll, "atoll is unportable - " + "use gnulib module atoll for portability"); +# endif +#endif + +#if @GNULIB_CALLOC_POSIX@ +# if @REPLACE_CALLOC@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef calloc +# define calloc rpl_calloc +# endif +_GL_FUNCDECL_RPL (calloc, void *, (size_t nmemb, size_t size)); +_GL_CXXALIAS_RPL (calloc, void *, (size_t nmemb, size_t size)); +# else +_GL_CXXALIAS_SYS (calloc, void *, (size_t nmemb, size_t size)); +# endif +_GL_CXXALIASWARN (calloc); +#elif defined GNULIB_POSIXCHECK +# undef calloc +/* Assume calloc is always declared. */ +_GL_WARN_ON_USE (calloc, "calloc is not POSIX compliant everywhere - " + "use gnulib module calloc-posix for portability"); +#endif + +#if @GNULIB_CANONICALIZE_FILE_NAME@ +# if @REPLACE_CANONICALIZE_FILE_NAME@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define canonicalize_file_name rpl_canonicalize_file_name +# endif +_GL_FUNCDECL_RPL (canonicalize_file_name, char *, (const char *name) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (canonicalize_file_name, char *, (const char *name)); +# else +# if !@HAVE_CANONICALIZE_FILE_NAME@ +_GL_FUNCDECL_SYS (canonicalize_file_name, char *, (const char *name) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (canonicalize_file_name, char *, (const char *name)); +# endif +_GL_CXXALIASWARN (canonicalize_file_name); +#elif defined GNULIB_POSIXCHECK +# undef canonicalize_file_name +# if HAVE_RAW_DECL_CANONICALIZE_FILE_NAME +_GL_WARN_ON_USE (canonicalize_file_name, + "canonicalize_file_name is unportable - " + "use gnulib module canonicalize-lgpl for portability"); +# endif +#endif + +#if @GNULIB_GETLOADAVG@ +/* Store max(NELEM,3) load average numbers in LOADAVG[]. + The three numbers are the load average of the last 1 minute, the last 5 + minutes, and the last 15 minutes, respectively. + LOADAVG is an array of NELEM numbers. */ +# if !@HAVE_DECL_GETLOADAVG@ +_GL_FUNCDECL_SYS (getloadavg, int, (double loadavg[], int nelem) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (getloadavg, int, (double loadavg[], int nelem)); +_GL_CXXALIASWARN (getloadavg); +#elif defined GNULIB_POSIXCHECK +# undef getloadavg +# if HAVE_RAW_DECL_GETLOADAVG +_GL_WARN_ON_USE (getloadavg, "getloadavg is not portable - " + "use gnulib module getloadavg for portability"); +# endif +#endif + +#if @GNULIB_GETSUBOPT@ +/* Assuming *OPTIONP is a comma separated list of elements of the form + "token" or "token=value", getsubopt parses the first of these elements. + If the first element refers to a "token" that is member of the given + NULL-terminated array of tokens: + - It replaces the comma with a NUL byte, updates *OPTIONP to point past + the first option and the comma, sets *VALUEP to the value of the + element (or NULL if it doesn't contain an "=" sign), + - It returns the index of the "token" in the given array of tokens. + Otherwise it returns -1, and *OPTIONP and *VALUEP are undefined. + For more details see the POSIX:2001 specification. + http://www.opengroup.org/susv3xsh/getsubopt.html */ +# if !@HAVE_GETSUBOPT@ +_GL_FUNCDECL_SYS (getsubopt, int, + (char **optionp, char *const *tokens, char **valuep) + _GL_ARG_NONNULL ((1, 2, 3))); +# endif +_GL_CXXALIAS_SYS (getsubopt, int, + (char **optionp, char *const *tokens, char **valuep)); +_GL_CXXALIASWARN (getsubopt); +#elif defined GNULIB_POSIXCHECK +# undef getsubopt +# if HAVE_RAW_DECL_GETSUBOPT +_GL_WARN_ON_USE (getsubopt, "getsubopt is unportable - " + "use gnulib module getsubopt for portability"); +# endif +#endif + +#if @GNULIB_GRANTPT@ +/* Change the ownership and access permission of the slave side of the + pseudo-terminal whose master side is specified by FD. */ +# if !@HAVE_GRANTPT@ +_GL_FUNCDECL_SYS (grantpt, int, (int fd)); +# endif +_GL_CXXALIAS_SYS (grantpt, int, (int fd)); +_GL_CXXALIASWARN (grantpt); +#elif defined GNULIB_POSIXCHECK +# undef grantpt +# if HAVE_RAW_DECL_GRANTPT +_GL_WARN_ON_USE (grantpt, "grantpt is not portable - " + "use gnulib module grantpt for portability"); +# endif +#endif + +/* If _GL_USE_STDLIB_ALLOC is nonzero, the including module does not + rely on GNU or POSIX semantics for malloc and realloc (for example, + by never specifying a zero size), so it does not need malloc or + realloc to be redefined. */ +#if @GNULIB_MALLOC_POSIX@ +# if @REPLACE_MALLOC@ +# if !((defined __cplusplus && defined GNULIB_NAMESPACE) \ + || _GL_USE_STDLIB_ALLOC) +# undef malloc +# define malloc rpl_malloc +# endif +_GL_FUNCDECL_RPL (malloc, void *, (size_t size)); +_GL_CXXALIAS_RPL (malloc, void *, (size_t size)); +# else +_GL_CXXALIAS_SYS (malloc, void *, (size_t size)); +# endif +_GL_CXXALIASWARN (malloc); +#elif defined GNULIB_POSIXCHECK && !_GL_USE_STDLIB_ALLOC +# undef malloc +/* Assume malloc is always declared. */ +_GL_WARN_ON_USE (malloc, "malloc is not POSIX compliant everywhere - " + "use gnulib module malloc-posix for portability"); +#endif + +/* Convert a multibyte character to a wide character. */ +#if @GNULIB_MBTOWC@ +# if @REPLACE_MBTOWC@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef mbtowc +# define mbtowc rpl_mbtowc +# endif +_GL_FUNCDECL_RPL (mbtowc, int, (wchar_t *pwc, const char *s, size_t n)); +_GL_CXXALIAS_RPL (mbtowc, int, (wchar_t *pwc, const char *s, size_t n)); +# else +_GL_CXXALIAS_SYS (mbtowc, int, (wchar_t *pwc, const char *s, size_t n)); +# endif +_GL_CXXALIASWARN (mbtowc); +#endif + +#if @GNULIB_MKDTEMP@ +/* Create a unique temporary directory from TEMPLATE. + The last six characters of TEMPLATE must be "XXXXXX"; + they are replaced with a string that makes the directory name unique. + Returns TEMPLATE, or a null pointer if it cannot get a unique name. + The directory is created mode 700. */ +# if !@HAVE_MKDTEMP@ +_GL_FUNCDECL_SYS (mkdtemp, char *, (char * /*template*/) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (mkdtemp, char *, (char * /*template*/)); +_GL_CXXALIASWARN (mkdtemp); +#elif defined GNULIB_POSIXCHECK +# undef mkdtemp +# if HAVE_RAW_DECL_MKDTEMP +_GL_WARN_ON_USE (mkdtemp, "mkdtemp is unportable - " + "use gnulib module mkdtemp for portability"); +# endif +#endif + +#if @GNULIB_MKOSTEMP@ +/* Create a unique temporary file from TEMPLATE. + The last six characters of TEMPLATE must be "XXXXXX"; + they are replaced with a string that makes the file name unique. + The flags are a bitmask, possibly including O_CLOEXEC (defined in ) + and O_TEXT, O_BINARY (defined in "binary-io.h"). + The file is then created, with the specified flags, ensuring it didn't exist + before. + The file is created read-write (mask at least 0600 & ~umask), but it may be + world-readable and world-writable (mask 0666 & ~umask), depending on the + implementation. + Returns the open file descriptor if successful, otherwise -1 and errno + set. */ +# if !@HAVE_MKOSTEMP@ +_GL_FUNCDECL_SYS (mkostemp, int, (char * /*template*/, int /*flags*/) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (mkostemp, int, (char * /*template*/, int /*flags*/)); +_GL_CXXALIASWARN (mkostemp); +#elif defined GNULIB_POSIXCHECK +# undef mkostemp +# if HAVE_RAW_DECL_MKOSTEMP +_GL_WARN_ON_USE (mkostemp, "mkostemp is unportable - " + "use gnulib module mkostemp for portability"); +# endif +#endif + +#if @GNULIB_MKOSTEMPS@ +/* Create a unique temporary file from TEMPLATE. + The last six characters of TEMPLATE before a suffix of length + SUFFIXLEN must be "XXXXXX"; + they are replaced with a string that makes the file name unique. + The flags are a bitmask, possibly including O_CLOEXEC (defined in ) + and O_TEXT, O_BINARY (defined in "binary-io.h"). + The file is then created, with the specified flags, ensuring it didn't exist + before. + The file is created read-write (mask at least 0600 & ~umask), but it may be + world-readable and world-writable (mask 0666 & ~umask), depending on the + implementation. + Returns the open file descriptor if successful, otherwise -1 and errno + set. */ +# if !@HAVE_MKOSTEMPS@ +_GL_FUNCDECL_SYS (mkostemps, int, + (char * /*template*/, int /*suffixlen*/, int /*flags*/) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (mkostemps, int, + (char * /*template*/, int /*suffixlen*/, int /*flags*/)); +_GL_CXXALIASWARN (mkostemps); +#elif defined GNULIB_POSIXCHECK +# undef mkostemps +# if HAVE_RAW_DECL_MKOSTEMPS +_GL_WARN_ON_USE (mkostemps, "mkostemps is unportable - " + "use gnulib module mkostemps for portability"); +# endif +#endif + +#if @GNULIB_MKSTEMP@ +/* Create a unique temporary file from TEMPLATE. + The last six characters of TEMPLATE must be "XXXXXX"; + they are replaced with a string that makes the file name unique. + The file is then created, ensuring it didn't exist before. + The file is created read-write (mask at least 0600 & ~umask), but it may be + world-readable and world-writable (mask 0666 & ~umask), depending on the + implementation. + Returns the open file descriptor if successful, otherwise -1 and errno + set. */ +# if @REPLACE_MKSTEMP@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define mkstemp rpl_mkstemp +# endif +_GL_FUNCDECL_RPL (mkstemp, int, (char * /*template*/) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (mkstemp, int, (char * /*template*/)); +# else +# if ! @HAVE_MKSTEMP@ +_GL_FUNCDECL_SYS (mkstemp, int, (char * /*template*/) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (mkstemp, int, (char * /*template*/)); +# endif +_GL_CXXALIASWARN (mkstemp); +#elif defined GNULIB_POSIXCHECK +# undef mkstemp +# if HAVE_RAW_DECL_MKSTEMP +_GL_WARN_ON_USE (mkstemp, "mkstemp is unportable - " + "use gnulib module mkstemp for portability"); +# endif +#endif + +#if @GNULIB_MKSTEMPS@ +/* Create a unique temporary file from TEMPLATE. + The last six characters of TEMPLATE prior to a suffix of length + SUFFIXLEN must be "XXXXXX"; + they are replaced with a string that makes the file name unique. + The file is then created, ensuring it didn't exist before. + The file is created read-write (mask at least 0600 & ~umask), but it may be + world-readable and world-writable (mask 0666 & ~umask), depending on the + implementation. + Returns the open file descriptor if successful, otherwise -1 and errno + set. */ +# if !@HAVE_MKSTEMPS@ +_GL_FUNCDECL_SYS (mkstemps, int, (char * /*template*/, int /*suffixlen*/) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (mkstemps, int, (char * /*template*/, int /*suffixlen*/)); +_GL_CXXALIASWARN (mkstemps); +#elif defined GNULIB_POSIXCHECK +# undef mkstemps +# if HAVE_RAW_DECL_MKSTEMPS +_GL_WARN_ON_USE (mkstemps, "mkstemps is unportable - " + "use gnulib module mkstemps for portability"); +# endif +#endif + +#if @GNULIB_POSIX_OPENPT@ +/* Return an FD open to the master side of a pseudo-terminal. Flags should + include O_RDWR, and may also include O_NOCTTY. */ +# if !@HAVE_POSIX_OPENPT@ +_GL_FUNCDECL_SYS (posix_openpt, int, (int flags)); +# endif +_GL_CXXALIAS_SYS (posix_openpt, int, (int flags)); +_GL_CXXALIASWARN (posix_openpt); +#elif defined GNULIB_POSIXCHECK +# undef posix_openpt +# if HAVE_RAW_DECL_POSIX_OPENPT +_GL_WARN_ON_USE (posix_openpt, "posix_openpt is not portable - " + "use gnulib module posix_openpt for portability"); +# endif +#endif + +#if @GNULIB_PTSNAME@ +/* Return the pathname of the pseudo-terminal slave associated with + the master FD is open on, or NULL on errors. */ +# if @REPLACE_PTSNAME@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef ptsname +# define ptsname rpl_ptsname +# endif +_GL_FUNCDECL_RPL (ptsname, char *, (int fd)); +_GL_CXXALIAS_RPL (ptsname, char *, (int fd)); +# else +# if !@HAVE_PTSNAME@ +_GL_FUNCDECL_SYS (ptsname, char *, (int fd)); +# endif +_GL_CXXALIAS_SYS (ptsname, char *, (int fd)); +# endif +_GL_CXXALIASWARN (ptsname); +#elif defined GNULIB_POSIXCHECK +# undef ptsname +# if HAVE_RAW_DECL_PTSNAME +_GL_WARN_ON_USE (ptsname, "ptsname is not portable - " + "use gnulib module ptsname for portability"); +# endif +#endif + +#if @GNULIB_PTSNAME_R@ +/* Set the pathname of the pseudo-terminal slave associated with + the master FD is open on and return 0, or set errno and return + non-zero on errors. */ +# if @REPLACE_PTSNAME_R@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef ptsname_r +# define ptsname_r rpl_ptsname_r +# endif +_GL_FUNCDECL_RPL (ptsname_r, int, (int fd, char *buf, size_t len)); +_GL_CXXALIAS_RPL (ptsname_r, int, (int fd, char *buf, size_t len)); +# else +# if !@HAVE_PTSNAME_R@ +_GL_FUNCDECL_SYS (ptsname_r, int, (int fd, char *buf, size_t len)); +# endif +_GL_CXXALIAS_SYS (ptsname_r, int, (int fd, char *buf, size_t len)); +# endif +_GL_CXXALIASWARN (ptsname_r); +#elif defined GNULIB_POSIXCHECK +# undef ptsname_r +# if HAVE_RAW_DECL_PTSNAME_R +_GL_WARN_ON_USE (ptsname_r, "ptsname_r is not portable - " + "use gnulib module ptsname_r for portability"); +# endif +#endif + +#if @GNULIB_PUTENV@ +# if @REPLACE_PUTENV@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef putenv +# define putenv rpl_putenv +# endif +_GL_FUNCDECL_RPL (putenv, int, (char *string) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (putenv, int, (char *string)); +# else +_GL_CXXALIAS_SYS (putenv, int, (char *string)); +# endif +_GL_CXXALIASWARN (putenv); +#endif + +#if @GNULIB_QSORT_R@ +# if @REPLACE_QSORT_R@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef qsort_r +# define qsort_r rpl_qsort_r +# endif +_GL_FUNCDECL_RPL (qsort_r, void, (void *base, size_t nmemb, size_t size, + int (*compare) (void const *, void const *, + void *), + void *arg) _GL_ARG_NONNULL ((1, 4))); +_GL_CXXALIAS_RPL (qsort_r, void, (void *base, size_t nmemb, size_t size, + int (*compare) (void const *, void const *, + void *), + void *arg)); +# else +_GL_CXXALIAS_SYS (qsort_r, void, (void *base, size_t nmemb, size_t size, + int (*compare) (void const *, void const *, + void *), + void *arg)); +# endif +_GL_CXXALIASWARN (qsort_r); +#endif + + +#if @GNULIB_RANDOM_R@ +# if !@HAVE_RANDOM_R@ +# ifndef RAND_MAX +# define RAND_MAX 2147483647 +# endif +# endif +#endif + + +#if @GNULIB_RANDOM@ +# if !@HAVE_RANDOM@ +_GL_FUNCDECL_SYS (random, long, (void)); +# endif +_GL_CXXALIAS_SYS (random, long, (void)); +_GL_CXXALIASWARN (random); +#elif defined GNULIB_POSIXCHECK +# undef random +# if HAVE_RAW_DECL_RANDOM +_GL_WARN_ON_USE (random, "random is unportable - " + "use gnulib module random for portability"); +# endif +#endif + +#if @GNULIB_RANDOM@ +# if !@HAVE_RANDOM@ +_GL_FUNCDECL_SYS (srandom, void, (unsigned int seed)); +# endif +_GL_CXXALIAS_SYS (srandom, void, (unsigned int seed)); +_GL_CXXALIASWARN (srandom); +#elif defined GNULIB_POSIXCHECK +# undef srandom +# if HAVE_RAW_DECL_SRANDOM +_GL_WARN_ON_USE (srandom, "srandom is unportable - " + "use gnulib module random for portability"); +# endif +#endif + +#if @GNULIB_RANDOM@ +# if !@HAVE_RANDOM@ +_GL_FUNCDECL_SYS (initstate, char *, + (unsigned int seed, char *buf, size_t buf_size) + _GL_ARG_NONNULL ((2))); +# endif +_GL_CXXALIAS_SYS (initstate, char *, + (unsigned int seed, char *buf, size_t buf_size)); +_GL_CXXALIASWARN (initstate); +#elif defined GNULIB_POSIXCHECK +# undef initstate +# if HAVE_RAW_DECL_INITSTATE_R +_GL_WARN_ON_USE (initstate, "initstate is unportable - " + "use gnulib module random for portability"); +# endif +#endif + +#if @GNULIB_RANDOM@ +# if !@HAVE_RANDOM@ +_GL_FUNCDECL_SYS (setstate, char *, (char *arg_state) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (setstate, char *, (char *arg_state)); +_GL_CXXALIASWARN (setstate); +#elif defined GNULIB_POSIXCHECK +# undef setstate +# if HAVE_RAW_DECL_SETSTATE_R +_GL_WARN_ON_USE (setstate, "setstate is unportable - " + "use gnulib module random for portability"); +# endif +#endif + + +#if @GNULIB_RANDOM_R@ +# if @REPLACE_RANDOM_R@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef random_r +# define random_r rpl_random_r +# endif +_GL_FUNCDECL_RPL (random_r, int, (struct random_data *buf, int32_t *result) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (random_r, int, (struct random_data *buf, int32_t *result)); +# else +# if !@HAVE_RANDOM_R@ +_GL_FUNCDECL_SYS (random_r, int, (struct random_data *buf, int32_t *result) + _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (random_r, int, (struct random_data *buf, int32_t *result)); +# endif +_GL_CXXALIASWARN (random_r); +#elif defined GNULIB_POSIXCHECK +# undef random_r +# if HAVE_RAW_DECL_RANDOM_R +_GL_WARN_ON_USE (random_r, "random_r is unportable - " + "use gnulib module random_r for portability"); +# endif +#endif + +#if @GNULIB_RANDOM_R@ +# if @REPLACE_RANDOM_R@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef srandom_r +# define srandom_r rpl_srandom_r +# endif +_GL_FUNCDECL_RPL (srandom_r, int, + (unsigned int seed, struct random_data *rand_state) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (srandom_r, int, + (unsigned int seed, struct random_data *rand_state)); +# else +# if !@HAVE_RANDOM_R@ +_GL_FUNCDECL_SYS (srandom_r, int, + (unsigned int seed, struct random_data *rand_state) + _GL_ARG_NONNULL ((2))); +# endif +_GL_CXXALIAS_SYS (srandom_r, int, + (unsigned int seed, struct random_data *rand_state)); +# endif +_GL_CXXALIASWARN (srandom_r); +#elif defined GNULIB_POSIXCHECK +# undef srandom_r +# if HAVE_RAW_DECL_SRANDOM_R +_GL_WARN_ON_USE (srandom_r, "srandom_r is unportable - " + "use gnulib module random_r for portability"); +# endif +#endif + +#if @GNULIB_RANDOM_R@ +# if @REPLACE_RANDOM_R@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef initstate_r +# define initstate_r rpl_initstate_r +# endif +_GL_FUNCDECL_RPL (initstate_r, int, + (unsigned int seed, char *buf, size_t buf_size, + struct random_data *rand_state) + _GL_ARG_NONNULL ((2, 4))); +_GL_CXXALIAS_RPL (initstate_r, int, + (unsigned int seed, char *buf, size_t buf_size, + struct random_data *rand_state)); +# else +# if !@HAVE_RANDOM_R@ +_GL_FUNCDECL_SYS (initstate_r, int, + (unsigned int seed, char *buf, size_t buf_size, + struct random_data *rand_state) + _GL_ARG_NONNULL ((2, 4))); +# endif +_GL_CXXALIAS_SYS (initstate_r, int, + (unsigned int seed, char *buf, size_t buf_size, + struct random_data *rand_state)); +# endif +_GL_CXXALIASWARN (initstate_r); +#elif defined GNULIB_POSIXCHECK +# undef initstate_r +# if HAVE_RAW_DECL_INITSTATE_R +_GL_WARN_ON_USE (initstate_r, "initstate_r is unportable - " + "use gnulib module random_r for portability"); +# endif +#endif + +#if @GNULIB_RANDOM_R@ +# if @REPLACE_RANDOM_R@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef setstate_r +# define setstate_r rpl_setstate_r +# endif +_GL_FUNCDECL_RPL (setstate_r, int, + (char *arg_state, struct random_data *rand_state) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (setstate_r, int, + (char *arg_state, struct random_data *rand_state)); +# else +# if !@HAVE_RANDOM_R@ +_GL_FUNCDECL_SYS (setstate_r, int, + (char *arg_state, struct random_data *rand_state) + _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (setstate_r, int, + (char *arg_state, struct random_data *rand_state)); +# endif +_GL_CXXALIASWARN (setstate_r); +#elif defined GNULIB_POSIXCHECK +# undef setstate_r +# if HAVE_RAW_DECL_SETSTATE_R +_GL_WARN_ON_USE (setstate_r, "setstate_r is unportable - " + "use gnulib module random_r for portability"); +# endif +#endif + + +#if @GNULIB_REALLOC_POSIX@ +# if @REPLACE_REALLOC@ +# if !((defined __cplusplus && defined GNULIB_NAMESPACE) \ + || _GL_USE_STDLIB_ALLOC) +# undef realloc +# define realloc rpl_realloc +# endif +_GL_FUNCDECL_RPL (realloc, void *, (void *ptr, size_t size)); +_GL_CXXALIAS_RPL (realloc, void *, (void *ptr, size_t size)); +# else +_GL_CXXALIAS_SYS (realloc, void *, (void *ptr, size_t size)); +# endif +_GL_CXXALIASWARN (realloc); +#elif defined GNULIB_POSIXCHECK && !_GL_USE_STDLIB_ALLOC +# undef realloc +/* Assume realloc is always declared. */ +_GL_WARN_ON_USE (realloc, "realloc is not POSIX compliant everywhere - " + "use gnulib module realloc-posix for portability"); +#endif + +#if @GNULIB_REALPATH@ +# if @REPLACE_REALPATH@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define realpath rpl_realpath +# endif +_GL_FUNCDECL_RPL (realpath, char *, (const char *name, char *resolved) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (realpath, char *, (const char *name, char *resolved)); +# else +# if !@HAVE_REALPATH@ +_GL_FUNCDECL_SYS (realpath, char *, (const char *name, char *resolved) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (realpath, char *, (const char *name, char *resolved)); +# endif +_GL_CXXALIASWARN (realpath); +#elif defined GNULIB_POSIXCHECK +# undef realpath +# if HAVE_RAW_DECL_REALPATH +_GL_WARN_ON_USE (realpath, "realpath is unportable - use gnulib module " + "canonicalize or canonicalize-lgpl for portability"); +# endif +#endif + +#if @GNULIB_RPMATCH@ +/* Test a user response to a question. + Return 1 if it is affirmative, 0 if it is negative, or -1 if not clear. */ +# if !@HAVE_RPMATCH@ +_GL_FUNCDECL_SYS (rpmatch, int, (const char *response) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (rpmatch, int, (const char *response)); +_GL_CXXALIASWARN (rpmatch); +#elif defined GNULIB_POSIXCHECK +# undef rpmatch +# if HAVE_RAW_DECL_RPMATCH +_GL_WARN_ON_USE (rpmatch, "rpmatch is unportable - " + "use gnulib module rpmatch for portability"); +# endif +#endif + +#if @GNULIB_SECURE_GETENV@ +/* Look up NAME in the environment, returning 0 in insecure situations. */ +# if !@HAVE_SECURE_GETENV@ +_GL_FUNCDECL_SYS (secure_getenv, char *, + (char const *name) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (secure_getenv, char *, (char const *name)); +_GL_CXXALIASWARN (secure_getenv); +#elif defined GNULIB_POSIXCHECK +# undef secure_getenv +# if HAVE_RAW_DECL_SECURE_GETENV +_GL_WARN_ON_USE (secure_getenv, "secure_getenv is unportable - " + "use gnulib module secure_getenv for portability"); +# endif +#endif + +#if @GNULIB_SETENV@ +/* Set NAME to VALUE in the environment. + If REPLACE is nonzero, overwrite an existing value. */ +# if @REPLACE_SETENV@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef setenv +# define setenv rpl_setenv +# endif +_GL_FUNCDECL_RPL (setenv, int, + (const char *name, const char *value, int replace) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (setenv, int, + (const char *name, const char *value, int replace)); +# else +# if !@HAVE_DECL_SETENV@ +_GL_FUNCDECL_SYS (setenv, int, + (const char *name, const char *value, int replace) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (setenv, int, + (const char *name, const char *value, int replace)); +# endif +# if !(@REPLACE_SETENV@ && !@HAVE_DECL_SETENV@) +_GL_CXXALIASWARN (setenv); +# endif +#elif defined GNULIB_POSIXCHECK +# undef setenv +# if HAVE_RAW_DECL_SETENV +_GL_WARN_ON_USE (setenv, "setenv is unportable - " + "use gnulib module setenv for portability"); +# endif +#endif + +#if @GNULIB_STRTOD@ + /* Parse a double from STRING, updating ENDP if appropriate. */ +# if @REPLACE_STRTOD@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define strtod rpl_strtod +# endif +_GL_FUNCDECL_RPL (strtod, double, (const char *str, char **endp) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (strtod, double, (const char *str, char **endp)); +# else +# if !@HAVE_STRTOD@ +_GL_FUNCDECL_SYS (strtod, double, (const char *str, char **endp) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (strtod, double, (const char *str, char **endp)); +# endif +_GL_CXXALIASWARN (strtod); +#elif defined GNULIB_POSIXCHECK +# undef strtod +# if HAVE_RAW_DECL_STRTOD +_GL_WARN_ON_USE (strtod, "strtod is unportable - " + "use gnulib module strtod for portability"); +# endif +#endif + +#if @GNULIB_STRTOLL@ +/* Parse a signed integer whose textual representation starts at STRING. + The integer is expected to be in base BASE (2 <= BASE <= 36); if BASE == 0, + it may be decimal or octal (with prefix "0") or hexadecimal (with prefix + "0x"). + If ENDPTR is not NULL, the address of the first byte after the integer is + stored in *ENDPTR. + Upon overflow, the return value is LLONG_MAX or LLONG_MIN, and errno is set + to ERANGE. */ +# if !@HAVE_STRTOLL@ +_GL_FUNCDECL_SYS (strtoll, long long, + (const char *string, char **endptr, int base) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (strtoll, long long, + (const char *string, char **endptr, int base)); +_GL_CXXALIASWARN (strtoll); +#elif defined GNULIB_POSIXCHECK +# undef strtoll +# if HAVE_RAW_DECL_STRTOLL +_GL_WARN_ON_USE (strtoll, "strtoll is unportable - " + "use gnulib module strtoll for portability"); +# endif +#endif + +#if @GNULIB_STRTOULL@ +/* Parse an unsigned integer whose textual representation starts at STRING. + The integer is expected to be in base BASE (2 <= BASE <= 36); if BASE == 0, + it may be decimal or octal (with prefix "0") or hexadecimal (with prefix + "0x"). + If ENDPTR is not NULL, the address of the first byte after the integer is + stored in *ENDPTR. + Upon overflow, the return value is ULLONG_MAX, and errno is set to + ERANGE. */ +# if !@HAVE_STRTOULL@ +_GL_FUNCDECL_SYS (strtoull, unsigned long long, + (const char *string, char **endptr, int base) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (strtoull, unsigned long long, + (const char *string, char **endptr, int base)); +_GL_CXXALIASWARN (strtoull); +#elif defined GNULIB_POSIXCHECK +# undef strtoull +# if HAVE_RAW_DECL_STRTOULL +_GL_WARN_ON_USE (strtoull, "strtoull is unportable - " + "use gnulib module strtoull for portability"); +# endif +#endif + +#if @GNULIB_UNLOCKPT@ +/* Unlock the slave side of the pseudo-terminal whose master side is specified + by FD, so that it can be opened. */ +# if !@HAVE_UNLOCKPT@ +_GL_FUNCDECL_SYS (unlockpt, int, (int fd)); +# endif +_GL_CXXALIAS_SYS (unlockpt, int, (int fd)); +_GL_CXXALIASWARN (unlockpt); +#elif defined GNULIB_POSIXCHECK +# undef unlockpt +# if HAVE_RAW_DECL_UNLOCKPT +_GL_WARN_ON_USE (unlockpt, "unlockpt is not portable - " + "use gnulib module unlockpt for portability"); +# endif +#endif + +#if @GNULIB_UNSETENV@ +/* Remove the variable NAME from the environment. */ +# if @REPLACE_UNSETENV@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef unsetenv +# define unsetenv rpl_unsetenv +# endif +_GL_FUNCDECL_RPL (unsetenv, int, (const char *name) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (unsetenv, int, (const char *name)); +# else +# if !@HAVE_DECL_UNSETENV@ +_GL_FUNCDECL_SYS (unsetenv, int, (const char *name) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (unsetenv, int, (const char *name)); +# endif +# if !(@REPLACE_UNSETENV@ && !@HAVE_DECL_UNSETENV@) +_GL_CXXALIASWARN (unsetenv); +# endif +#elif defined GNULIB_POSIXCHECK +# undef unsetenv +# if HAVE_RAW_DECL_UNSETENV +_GL_WARN_ON_USE (unsetenv, "unsetenv is unportable - " + "use gnulib module unsetenv for portability"); +# endif +#endif + +/* Convert a wide character to a multibyte character. */ +#if @GNULIB_WCTOMB@ +# if @REPLACE_WCTOMB@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef wctomb +# define wctomb rpl_wctomb +# endif +_GL_FUNCDECL_RPL (wctomb, int, (char *s, wchar_t wc)); +_GL_CXXALIAS_RPL (wctomb, int, (char *s, wchar_t wc)); +# else +_GL_CXXALIAS_SYS (wctomb, int, (char *s, wchar_t wc)); +# endif +_GL_CXXALIASWARN (wctomb); +#endif + + +#endif /* _@GUARD_PREFIX@_STDLIB_H */ +#endif /* _@GUARD_PREFIX@_STDLIB_H */ +#endif diff --git a/gettext-tools/gnulib-lib/stpcpy.c b/gettext-tools/gnulib-lib/stpcpy.c new file mode 100644 index 0000000..880a706 --- /dev/null +++ b/gettext-tools/gnulib-lib/stpcpy.c @@ -0,0 +1,49 @@ +/* stpcpy.c -- copy a string and return pointer to end of new string + Copyright (C) 1992, 1995, 1997-1998, 2006, 2009-2014 Free Software + Foundation, Inc. + + NOTE: The canonical source of this file is maintained with the GNU C Library. + Bugs can be reported to bug-glibc@prep.ai.mit.edu. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 3 of the License, or any + later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +#include + +#undef __stpcpy +#ifdef _LIBC +# undef stpcpy +#endif + +#ifndef weak_alias +# define __stpcpy stpcpy +#endif + +/* Copy SRC to DEST, returning the address of the terminating '\0' in DEST. */ +char * +__stpcpy (char *dest, const char *src) +{ + register char *d = dest; + register const char *s = src; + + do + *d++ = *s; + while (*s++ != '\0'); + + return d - 1; +} +#ifdef weak_alias +weak_alias (__stpcpy, stpcpy) +#endif diff --git a/gettext-tools/gnulib-lib/stpncpy.c b/gettext-tools/gnulib-lib/stpncpy.c new file mode 100644 index 0000000..37018e8 --- /dev/null +++ b/gettext-tools/gnulib-lib/stpncpy.c @@ -0,0 +1,92 @@ +/* Copyright (C) 1993, 1995-1997, 2002-2003, 2005-2007, 2009-2014 Free Software + * Foundation, Inc. + + NOTE: The canonical source of this file is maintained with the GNU C Library. + Bugs can be reported to bug-glibc@gnu.org. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 3 of the License, or any + later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* This is almost copied from strncpy.c, written by Torbjorn Granlund. */ + +#include + +/* Specification. */ +#include + +#ifndef weak_alias +# define __stpncpy stpncpy +#endif + +/* Copy no more than N bytes of SRC to DST, returning a pointer past the + last non-NUL byte written into DST. */ +char * +(__stpncpy) (char *dest, const char *src, size_t n) +{ + char c; + char *s = dest; + + if (n >= 4) + { + size_t n4 = n >> 2; + + for (;;) + { + c = *src++; + *dest++ = c; + if (c == '\0') + break; + c = *src++; + *dest++ = c; + if (c == '\0') + break; + c = *src++; + *dest++ = c; + if (c == '\0') + break; + c = *src++; + *dest++ = c; + if (c == '\0') + break; + if (--n4 == 0) + goto last_chars; + } + n -= dest - s; + goto zero_fill; + } + + last_chars: + n &= 3; + if (n == 0) + return dest; + + for (;;) + { + c = *src++; + --n; + *dest++ = c; + if (c == '\0') + break; + if (n == 0) + return dest; + } + + zero_fill: + while (n-- > 0) + dest[n] = '\0'; + + return dest - 1; +} +#ifdef weak_alias +weak_alias (__stpncpy, stpncpy) +#endif diff --git a/gettext-tools/gnulib-lib/str-kmp.h b/gettext-tools/gnulib-lib/str-kmp.h new file mode 100644 index 0000000..b25d07f --- /dev/null +++ b/gettext-tools/gnulib-lib/str-kmp.h @@ -0,0 +1,153 @@ +/* Substring search in a NUL terminated string of UNIT elements, + using the Knuth-Morris-Pratt algorithm. + Copyright (C) 2005-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2005. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . */ + +/* Before including this file, you need to define: + UNIT The element type of the needle and haystack. + CANON_ELEMENT(c) A macro that canonicalizes an element right after + it has been fetched from needle or haystack. + The argument is of type UNIT; the result must be + of type UNIT as well. */ + +/* Knuth-Morris-Pratt algorithm. + See http://en.wikipedia.org/wiki/Knuth-Morris-Pratt_algorithm + HAYSTACK is the NUL terminated string in which to search for. + NEEDLE is the string to search for in HAYSTACK, consisting of NEEDLE_LEN + units. + Return a boolean indicating success: + Return true and set *RESULTP if the search was completed. + Return false if it was aborted because not enough memory was available. */ +static bool +knuth_morris_pratt (const UNIT *haystack, + const UNIT *needle, size_t needle_len, + const UNIT **resultp) +{ + size_t m = needle_len; + + /* Allocate the table. */ + size_t *table = (size_t *) nmalloca (m, sizeof (size_t)); + if (table == NULL) + return false; + /* Fill the table. + For 0 < i < m: + 0 < table[i] <= i is defined such that + forall 0 < x < table[i]: needle[x..i-1] != needle[0..i-1-x], + and table[i] is as large as possible with this property. + This implies: + 1) For 0 < i < m: + If table[i] < i, + needle[table[i]..i-1] = needle[0..i-1-table[i]]. + 2) For 0 < i < m: + rhaystack[0..i-1] == needle[0..i-1] + and exists h, i <= h < m: rhaystack[h] != needle[h] + implies + forall 0 <= x < table[i]: rhaystack[x..x+m-1] != needle[0..m-1]. + table[0] remains uninitialized. */ + { + size_t i, j; + + /* i = 1: Nothing to verify for x = 0. */ + table[1] = 1; + j = 0; + + for (i = 2; i < m; i++) + { + /* Here: j = i-1 - table[i-1]. + The inequality needle[x..i-1] != needle[0..i-1-x] is known to hold + for x < table[i-1], by induction. + Furthermore, if j>0: needle[i-1-j..i-2] = needle[0..j-1]. */ + UNIT b = CANON_ELEMENT (needle[i - 1]); + + for (;;) + { + /* Invariants: The inequality needle[x..i-1] != needle[0..i-1-x] + is known to hold for x < i-1-j. + Furthermore, if j>0: needle[i-1-j..i-2] = needle[0..j-1]. */ + if (b == CANON_ELEMENT (needle[j])) + { + /* Set table[i] := i-1-j. */ + table[i] = i - ++j; + break; + } + /* The inequality needle[x..i-1] != needle[0..i-1-x] also holds + for x = i-1-j, because + needle[i-1] != needle[j] = needle[i-1-x]. */ + if (j == 0) + { + /* The inequality holds for all possible x. */ + table[i] = i; + break; + } + /* The inequality needle[x..i-1] != needle[0..i-1-x] also holds + for i-1-j < x < i-1-j+table[j], because for these x: + needle[x..i-2] + = needle[x-(i-1-j)..j-1] + != needle[0..j-1-(x-(i-1-j))] (by definition of table[j]) + = needle[0..i-2-x], + hence needle[x..i-1] != needle[0..i-1-x]. + Furthermore + needle[i-1-j+table[j]..i-2] + = needle[table[j]..j-1] + = needle[0..j-1-table[j]] (by definition of table[j]). */ + j = j - table[j]; + } + /* Here: j = i - table[i]. */ + } + } + + /* Search, using the table to accelerate the processing. */ + { + size_t j; + const UNIT *rhaystack; + const UNIT *phaystack; + + *resultp = NULL; + j = 0; + rhaystack = haystack; + phaystack = haystack; + /* Invariant: phaystack = rhaystack + j. */ + while (*phaystack != 0) + if (CANON_ELEMENT (needle[j]) == CANON_ELEMENT (*phaystack)) + { + j++; + phaystack++; + if (j == m) + { + /* The entire needle has been found. */ + *resultp = rhaystack; + break; + } + } + else if (j > 0) + { + /* Found a match of needle[0..j-1], mismatch at needle[j]. */ + rhaystack += table[j]; + j -= table[j]; + } + else + { + /* Found a mismatch at needle[0] already. */ + rhaystack++; + phaystack++; + } + } + + freea (table); + return true; +} + +#undef CANON_ELEMENT diff --git a/gettext-tools/gnulib-lib/str-two-way.h b/gettext-tools/gnulib-lib/str-two-way.h new file mode 100644 index 0000000..49ee746 --- /dev/null +++ b/gettext-tools/gnulib-lib/str-two-way.h @@ -0,0 +1,452 @@ +/* Byte-wise substring search, using the Two-Way algorithm. + Copyright (C) 2008-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Eric Blake , 2008. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, see . */ + +/* Before including this file, you need to include and + , and define: + RESULT_TYPE A macro that expands to the return type. + AVAILABLE(h, h_l, j, n_l) + A macro that returns nonzero if there are + at least N_L bytes left starting at H[J]. + H is 'unsigned char *', H_L, J, and N_L + are 'size_t'; H_L is an lvalue. For + NUL-terminated searches, H_L can be + modified each iteration to avoid having + to compute the end of H up front. + + For case-insensitivity, you may optionally define: + CMP_FUNC(p1, p2, l) A macro that returns 0 iff the first L + characters of P1 and P2 are equal. + CANON_ELEMENT(c) A macro that canonicalizes an element right after + it has been fetched from one of the two strings. + The argument is an 'unsigned char'; the result + must be an 'unsigned char' as well. + + This file undefines the macros documented above, and defines + LONG_NEEDLE_THRESHOLD. +*/ + +#include +#include + +/* We use the Two-Way string matching algorithm (also known as + Chrochemore-Perrin), which guarantees linear complexity with + constant space. Additionally, for long needles, we also use a bad + character shift table similar to the Boyer-Moore algorithm to + achieve improved (potentially sub-linear) performance. + + See http://www-igm.univ-mlv.fr/~lecroq/string/node26.html#SECTION00260, + http://en.wikipedia.org/wiki/Boyer-Moore_string_search_algorithm, + http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.34.6641&rep=rep1&type=pdf +*/ + +/* Point at which computing a bad-byte shift table is likely to be + worthwhile. Small needles should not compute a table, since it + adds (1 << CHAR_BIT) + NEEDLE_LEN computations of preparation for a + speedup no greater than a factor of NEEDLE_LEN. The larger the + needle, the better the potential performance gain. On the other + hand, on non-POSIX systems with CHAR_BIT larger than eight, the + memory required for the table is prohibitive. */ +#if CHAR_BIT < 10 +# define LONG_NEEDLE_THRESHOLD 32U +#else +# define LONG_NEEDLE_THRESHOLD SIZE_MAX +#endif + +#ifndef MAX +# define MAX(a, b) ((a < b) ? (b) : (a)) +#endif + +#ifndef CANON_ELEMENT +# define CANON_ELEMENT(c) c +#endif +#ifndef CMP_FUNC +# define CMP_FUNC memcmp +#endif + +/* Perform a critical factorization of NEEDLE, of length NEEDLE_LEN. + Return the index of the first byte in the right half, and set + *PERIOD to the global period of the right half. + + The global period of a string is the smallest index (possibly its + length) at which all remaining bytes in the string are repetitions + of the prefix (the last repetition may be a subset of the prefix). + + When NEEDLE is factored into two halves, a local period is the + length of the smallest word that shares a suffix with the left half + and shares a prefix with the right half. All factorizations of a + non-empty NEEDLE have a local period of at least 1 and no greater + than NEEDLE_LEN. + + A critical factorization has the property that the local period + equals the global period. All strings have at least one critical + factorization with the left half smaller than the global period. + And while some strings have more than one critical factorization, + it is provable that with an ordered alphabet, at least one of the + critical factorizations corresponds to a maximal suffix. + + Given an ordered alphabet, a critical factorization can be computed + in linear time, with 2 * NEEDLE_LEN comparisons, by computing the + shorter of two ordered maximal suffixes. The ordered maximal + suffixes are determined by lexicographic comparison while tracking + periodicity. */ +static size_t +critical_factorization (const unsigned char *needle, size_t needle_len, + size_t *period) +{ + /* Index of last byte of left half, or SIZE_MAX. */ + size_t max_suffix, max_suffix_rev; + size_t j; /* Index into NEEDLE for current candidate suffix. */ + size_t k; /* Offset into current period. */ + size_t p; /* Intermediate period. */ + unsigned char a, b; /* Current comparison bytes. */ + + /* Special case NEEDLE_LEN of 1 or 2 (all callers already filtered + out 0-length needles. */ + if (needle_len < 3) + { + *period = 1; + return needle_len - 1; + } + + /* Invariants: + 0 <= j < NEEDLE_LEN - 1 + -1 <= max_suffix{,_rev} < j (treating SIZE_MAX as if it were signed) + min(max_suffix, max_suffix_rev) < global period of NEEDLE + 1 <= p <= global period of NEEDLE + p == global period of the substring NEEDLE[max_suffix{,_rev}+1...j] + 1 <= k <= p + */ + + /* Perform lexicographic search. */ + max_suffix = SIZE_MAX; + j = 0; + k = p = 1; + while (j + k < needle_len) + { + a = CANON_ELEMENT (needle[j + k]); + b = CANON_ELEMENT (needle[max_suffix + k]); + if (a < b) + { + /* Suffix is smaller, period is entire prefix so far. */ + j += k; + k = 1; + p = j - max_suffix; + } + else if (a == b) + { + /* Advance through repetition of the current period. */ + if (k != p) + ++k; + else + { + j += p; + k = 1; + } + } + else /* b < a */ + { + /* Suffix is larger, start over from current location. */ + max_suffix = j++; + k = p = 1; + } + } + *period = p; + + /* Perform reverse lexicographic search. */ + max_suffix_rev = SIZE_MAX; + j = 0; + k = p = 1; + while (j + k < needle_len) + { + a = CANON_ELEMENT (needle[j + k]); + b = CANON_ELEMENT (needle[max_suffix_rev + k]); + if (b < a) + { + /* Suffix is smaller, period is entire prefix so far. */ + j += k; + k = 1; + p = j - max_suffix_rev; + } + else if (a == b) + { + /* Advance through repetition of the current period. */ + if (k != p) + ++k; + else + { + j += p; + k = 1; + } + } + else /* a < b */ + { + /* Suffix is larger, start over from current location. */ + max_suffix_rev = j++; + k = p = 1; + } + } + + /* Choose the shorter suffix. Return the index of the first byte of + the right half, rather than the last byte of the left half. + + For some examples, 'banana' has two critical factorizations, both + exposed by the two lexicographic extreme suffixes of 'anana' and + 'nana', where both suffixes have a period of 2. On the other + hand, with 'aab' and 'bba', both strings have a single critical + factorization of the last byte, with the suffix having a period + of 1. While the maximal lexicographic suffix of 'aab' is 'b', + the maximal lexicographic suffix of 'bba' is 'ba', which is not a + critical factorization. Conversely, the maximal reverse + lexicographic suffix of 'a' works for 'bba', but not 'ab' for + 'aab'. The shorter suffix of the two will always be a critical + factorization. */ + if (max_suffix_rev + 1 < max_suffix + 1) + return max_suffix + 1; + *period = p; + return max_suffix_rev + 1; +} + +/* Return the first location of non-empty NEEDLE within HAYSTACK, or + NULL. HAYSTACK_LEN is the minimum known length of HAYSTACK. This + method is optimized for NEEDLE_LEN < LONG_NEEDLE_THRESHOLD. + Performance is guaranteed to be linear, with an initialization cost + of 2 * NEEDLE_LEN comparisons. + + If AVAILABLE does not modify HAYSTACK_LEN (as in memmem), then at + most 2 * HAYSTACK_LEN - NEEDLE_LEN comparisons occur in searching. + If AVAILABLE modifies HAYSTACK_LEN (as in strstr), then at most 3 * + HAYSTACK_LEN - NEEDLE_LEN comparisons occur in searching. */ +static RETURN_TYPE +two_way_short_needle (const unsigned char *haystack, size_t haystack_len, + const unsigned char *needle, size_t needle_len) +{ + size_t i; /* Index into current byte of NEEDLE. */ + size_t j; /* Index into current window of HAYSTACK. */ + size_t period; /* The period of the right half of needle. */ + size_t suffix; /* The index of the right half of needle. */ + + /* Factor the needle into two halves, such that the left half is + smaller than the global period, and the right half is + periodic (with a period as large as NEEDLE_LEN - suffix). */ + suffix = critical_factorization (needle, needle_len, &period); + + /* Perform the search. Each iteration compares the right half + first. */ + if (CMP_FUNC (needle, needle + period, suffix) == 0) + { + /* Entire needle is periodic; a mismatch in the left half can + only advance by the period, so use memory to avoid rescanning + known occurrences of the period in the right half. */ + size_t memory = 0; + j = 0; + while (AVAILABLE (haystack, haystack_len, j, needle_len)) + { + /* Scan for matches in right half. */ + i = MAX (suffix, memory); + while (i < needle_len && (CANON_ELEMENT (needle[i]) + == CANON_ELEMENT (haystack[i + j]))) + ++i; + if (needle_len <= i) + { + /* Scan for matches in left half. */ + i = suffix - 1; + while (memory < i + 1 && (CANON_ELEMENT (needle[i]) + == CANON_ELEMENT (haystack[i + j]))) + --i; + if (i + 1 < memory + 1) + return (RETURN_TYPE) (haystack + j); + /* No match, so remember how many repetitions of period + on the right half were scanned. */ + j += period; + memory = needle_len - period; + } + else + { + j += i - suffix + 1; + memory = 0; + } + } + } + else + { + /* The two halves of needle are distinct; no extra memory is + required, and any mismatch results in a maximal shift. */ + period = MAX (suffix, needle_len - suffix) + 1; + j = 0; + while (AVAILABLE (haystack, haystack_len, j, needle_len)) + { + /* Scan for matches in right half. */ + i = suffix; + while (i < needle_len && (CANON_ELEMENT (needle[i]) + == CANON_ELEMENT (haystack[i + j]))) + ++i; + if (needle_len <= i) + { + /* Scan for matches in left half. */ + i = suffix - 1; + while (i != SIZE_MAX && (CANON_ELEMENT (needle[i]) + == CANON_ELEMENT (haystack[i + j]))) + --i; + if (i == SIZE_MAX) + return (RETURN_TYPE) (haystack + j); + j += period; + } + else + j += i - suffix + 1; + } + } + return NULL; +} + +/* Return the first location of non-empty NEEDLE within HAYSTACK, or + NULL. HAYSTACK_LEN is the minimum known length of HAYSTACK. This + method is optimized for LONG_NEEDLE_THRESHOLD <= NEEDLE_LEN. + Performance is guaranteed to be linear, with an initialization cost + of 3 * NEEDLE_LEN + (1 << CHAR_BIT) operations. + + If AVAILABLE does not modify HAYSTACK_LEN (as in memmem), then at + most 2 * HAYSTACK_LEN - NEEDLE_LEN comparisons occur in searching, + and sublinear performance O(HAYSTACK_LEN / NEEDLE_LEN) is possible. + If AVAILABLE modifies HAYSTACK_LEN (as in strstr), then at most 3 * + HAYSTACK_LEN - NEEDLE_LEN comparisons occur in searching, and + sublinear performance is not possible. */ +static RETURN_TYPE +two_way_long_needle (const unsigned char *haystack, size_t haystack_len, + const unsigned char *needle, size_t needle_len) +{ + size_t i; /* Index into current byte of NEEDLE. */ + size_t j; /* Index into current window of HAYSTACK. */ + size_t period; /* The period of the right half of needle. */ + size_t suffix; /* The index of the right half of needle. */ + size_t shift_table[1U << CHAR_BIT]; /* See below. */ + + /* Factor the needle into two halves, such that the left half is + smaller than the global period, and the right half is + periodic (with a period as large as NEEDLE_LEN - suffix). */ + suffix = critical_factorization (needle, needle_len, &period); + + /* Populate shift_table. For each possible byte value c, + shift_table[c] is the distance from the last occurrence of c to + the end of NEEDLE, or NEEDLE_LEN if c is absent from the NEEDLE. + shift_table[NEEDLE[NEEDLE_LEN - 1]] contains the only 0. */ + for (i = 0; i < 1U << CHAR_BIT; i++) + shift_table[i] = needle_len; + for (i = 0; i < needle_len; i++) + shift_table[CANON_ELEMENT (needle[i])] = needle_len - i - 1; + + /* Perform the search. Each iteration compares the right half + first. */ + if (CMP_FUNC (needle, needle + period, suffix) == 0) + { + /* Entire needle is periodic; a mismatch in the left half can + only advance by the period, so use memory to avoid rescanning + known occurrences of the period in the right half. */ + size_t memory = 0; + size_t shift; + j = 0; + while (AVAILABLE (haystack, haystack_len, j, needle_len)) + { + /* Check the last byte first; if it does not match, then + shift to the next possible match location. */ + shift = shift_table[CANON_ELEMENT (haystack[j + needle_len - 1])]; + if (0 < shift) + { + if (memory && shift < period) + { + /* Since needle is periodic, but the last period has + a byte out of place, there can be no match until + after the mismatch. */ + shift = needle_len - period; + } + memory = 0; + j += shift; + continue; + } + /* Scan for matches in right half. The last byte has + already been matched, by virtue of the shift table. */ + i = MAX (suffix, memory); + while (i < needle_len - 1 && (CANON_ELEMENT (needle[i]) + == CANON_ELEMENT (haystack[i + j]))) + ++i; + if (needle_len - 1 <= i) + { + /* Scan for matches in left half. */ + i = suffix - 1; + while (memory < i + 1 && (CANON_ELEMENT (needle[i]) + == CANON_ELEMENT (haystack[i + j]))) + --i; + if (i + 1 < memory + 1) + return (RETURN_TYPE) (haystack + j); + /* No match, so remember how many repetitions of period + on the right half were scanned. */ + j += period; + memory = needle_len - period; + } + else + { + j += i - suffix + 1; + memory = 0; + } + } + } + else + { + /* The two halves of needle are distinct; no extra memory is + required, and any mismatch results in a maximal shift. */ + size_t shift; + period = MAX (suffix, needle_len - suffix) + 1; + j = 0; + while (AVAILABLE (haystack, haystack_len, j, needle_len)) + { + /* Check the last byte first; if it does not match, then + shift to the next possible match location. */ + shift = shift_table[CANON_ELEMENT (haystack[j + needle_len - 1])]; + if (0 < shift) + { + j += shift; + continue; + } + /* Scan for matches in right half. The last byte has + already been matched, by virtue of the shift table. */ + i = suffix; + while (i < needle_len - 1 && (CANON_ELEMENT (needle[i]) + == CANON_ELEMENT (haystack[i + j]))) + ++i; + if (needle_len - 1 <= i) + { + /* Scan for matches in left half. */ + i = suffix - 1; + while (i != SIZE_MAX && (CANON_ELEMENT (needle[i]) + == CANON_ELEMENT (haystack[i + j]))) + --i; + if (i == SIZE_MAX) + return (RETURN_TYPE) (haystack + j); + j += period; + } + else + j += i - suffix + 1; + } + } + return NULL; +} + +#undef AVAILABLE +#undef CANON_ELEMENT +#undef CMP_FUNC +#undef MAX +#undef RETURN_TYPE diff --git a/gettext-tools/gnulib-lib/strchrnul.c b/gettext-tools/gnulib-lib/strchrnul.c new file mode 100644 index 0000000..452b554 --- /dev/null +++ b/gettext-tools/gnulib-lib/strchrnul.c @@ -0,0 +1,142 @@ +/* Searching in a string. + Copyright (C) 2003, 2007-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include + +/* Find the first occurrence of C in S or the final NUL byte. */ +char * +strchrnul (const char *s, int c_in) +{ + /* On 32-bit hardware, choosing longword to be a 32-bit unsigned + long instead of a 64-bit uintmax_t tends to give better + performance. On 64-bit hardware, unsigned long is generally 64 + bits already. Change this typedef to experiment with + performance. */ + typedef unsigned long int longword; + + const unsigned char *char_ptr; + const longword *longword_ptr; + longword repeated_one; + longword repeated_c; + unsigned char c; + + c = (unsigned char) c_in; + if (!c) + return rawmemchr (s, 0); + + /* Handle the first few bytes by reading one byte at a time. + Do this until CHAR_PTR is aligned on a longword boundary. */ + for (char_ptr = (const unsigned char *) s; + (size_t) char_ptr % sizeof (longword) != 0; + ++char_ptr) + if (!*char_ptr || *char_ptr == c) + return (char *) char_ptr; + + longword_ptr = (const longword *) char_ptr; + + /* All these elucidatory comments refer to 4-byte longwords, + but the theory applies equally well to any size longwords. */ + + /* Compute auxiliary longword values: + repeated_one is a value which has a 1 in every byte. + repeated_c has c in every byte. */ + repeated_one = 0x01010101; + repeated_c = c | (c << 8); + repeated_c |= repeated_c << 16; + if (0xffffffffU < (longword) -1) + { + repeated_one |= repeated_one << 31 << 1; + repeated_c |= repeated_c << 31 << 1; + if (8 < sizeof (longword)) + { + size_t i; + + for (i = 64; i < sizeof (longword) * 8; i *= 2) + { + repeated_one |= repeated_one << i; + repeated_c |= repeated_c << i; + } + } + } + + /* Instead of the traditional loop which tests each byte, we will + test a longword at a time. The tricky part is testing if *any of + the four* bytes in the longword in question are equal to NUL or + c. We first use an xor with repeated_c. This reduces the task + to testing whether *any of the four* bytes in longword1 or + longword2 is zero. + + Let's consider longword1. We compute tmp = + ((longword1 - repeated_one) & ~longword1) & (repeated_one << 7). + That is, we perform the following operations: + 1. Subtract repeated_one. + 2. & ~longword1. + 3. & a mask consisting of 0x80 in every byte. + Consider what happens in each byte: + - If a byte of longword1 is zero, step 1 and 2 transform it into 0xff, + and step 3 transforms it into 0x80. A carry can also be propagated + to more significant bytes. + - If a byte of longword1 is nonzero, let its lowest 1 bit be at + position k (0 <= k <= 7); so the lowest k bits are 0. After step 1, + the byte ends in a single bit of value 0 and k bits of value 1. + After step 2, the result is just k bits of value 1: 2^k - 1. After + step 3, the result is 0. And no carry is produced. + So, if longword1 has only non-zero bytes, tmp is zero. + Whereas if longword1 has a zero byte, call j the position of the least + significant zero byte. Then the result has a zero at positions 0, ..., + j-1 and a 0x80 at position j. We cannot predict the result at the more + significant bytes (positions j+1..3), but it does not matter since we + already have a non-zero bit at position 8*j+7. + + The test whether any byte in longword1 or longword2 is zero is equivalent + to testing whether tmp1 is nonzero or tmp2 is nonzero. We can combine + this into a single test, whether (tmp1 | tmp2) is nonzero. + + This test can read more than one byte beyond the end of a string, + depending on where the terminating NUL is encountered. However, + this is considered safe since the initialization phase ensured + that the read will be aligned, therefore, the read will not cross + page boundaries and will not cause a fault. */ + + while (1) + { + longword longword1 = *longword_ptr ^ repeated_c; + longword longword2 = *longword_ptr; + + if (((((longword1 - repeated_one) & ~longword1) + | ((longword2 - repeated_one) & ~longword2)) + & (repeated_one << 7)) != 0) + break; + longword_ptr++; + } + + char_ptr = (const unsigned char *) longword_ptr; + + /* At this point, we know that one of the sizeof (longword) bytes + starting at char_ptr is == 0 or == c. On little-endian machines, + we could determine the first such byte without any further memory + accesses, just by looking at the tmp result from the last loop + iteration. But this does not work on big-endian machines. + Choose code that works in both cases. */ + + char_ptr = (unsigned char *) longword_ptr; + while (*char_ptr && (*char_ptr != c)) + char_ptr++; + return (char *) char_ptr; +} diff --git a/gettext-tools/gnulib-lib/strchrnul.valgrind b/gettext-tools/gnulib-lib/strchrnul.valgrind new file mode 100644 index 0000000..b14fa13 --- /dev/null +++ b/gettext-tools/gnulib-lib/strchrnul.valgrind @@ -0,0 +1,12 @@ +# Suppress a valgrind message about use of uninitialized memory in strchrnul(). +# This use is OK because it provides only a speedup. +{ + strchrnul-value4 + Memcheck:Value4 + fun:strchrnul +} +{ + strchrnul-value8 + Memcheck:Value8 + fun:strchrnul +} diff --git a/gettext-tools/gnulib-lib/strcspn.c b/gettext-tools/gnulib-lib/strcspn.c new file mode 100644 index 0000000..02ffd56 --- /dev/null +++ b/gettext-tools/gnulib-lib/strcspn.c @@ -0,0 +1,41 @@ +/* Copyright (C) 1991, 1994, 1996-1997, 2002-2003, 2005-2006, 2009-2014 Free + * Software Foundation, Inc. + + NOTE: The canonical source of this file is maintained with the GNU C Library. + Bugs can be reported to bug-glibc@gnu.org. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 3 of the License, or any + later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +#include +#include + +#undef strcspn + +/* Return the length of the maximum initial segment of S + which contains no characters from REJECT. */ +size_t +strcspn (const char *s, const char *reject) +{ + size_t count = 0; + + while (*s != '\0') + if (strchr (reject, *s++) == NULL) + ++count; + else + return count; + + return count; +} diff --git a/gettext-tools/gnulib-lib/streq.h b/gettext-tools/gnulib-lib/streq.h new file mode 100644 index 0000000..0e62fb9 --- /dev/null +++ b/gettext-tools/gnulib-lib/streq.h @@ -0,0 +1,176 @@ +/* Optimized string comparison. + Copyright (C) 2001-2002, 2007, 2009-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Written by Bruno Haible . */ + +#ifndef _GL_STREQ_H +#define _GL_STREQ_H + +#include + +/* STREQ_OPT allows to optimize string comparison with a small literal string. + STREQ_OPT (s, "EUC-KR", 'E', 'U', 'C', '-', 'K', 'R', 0, 0, 0) + is semantically equivalent to + strcmp (s, "EUC-KR") == 0 + just faster. */ + +/* Help GCC to generate good code for string comparisons with + immediate strings. */ +#if defined (__GNUC__) && defined (__OPTIMIZE__) + +static inline int +streq9 (const char *s1, const char *s2) +{ + return strcmp (s1 + 9, s2 + 9) == 0; +} + +static inline int +streq8 (const char *s1, const char *s2, char s28) +{ + if (s1[8] == s28) + { + if (s28 == 0) + return 1; + else + return streq9 (s1, s2); + } + else + return 0; +} + +static inline int +streq7 (const char *s1, const char *s2, char s27, char s28) +{ + if (s1[7] == s27) + { + if (s27 == 0) + return 1; + else + return streq8 (s1, s2, s28); + } + else + return 0; +} + +static inline int +streq6 (const char *s1, const char *s2, char s26, char s27, char s28) +{ + if (s1[6] == s26) + { + if (s26 == 0) + return 1; + else + return streq7 (s1, s2, s27, s28); + } + else + return 0; +} + +static inline int +streq5 (const char *s1, const char *s2, char s25, char s26, char s27, char s28) +{ + if (s1[5] == s25) + { + if (s25 == 0) + return 1; + else + return streq6 (s1, s2, s26, s27, s28); + } + else + return 0; +} + +static inline int +streq4 (const char *s1, const char *s2, char s24, char s25, char s26, char s27, char s28) +{ + if (s1[4] == s24) + { + if (s24 == 0) + return 1; + else + return streq5 (s1, s2, s25, s26, s27, s28); + } + else + return 0; +} + +static inline int +streq3 (const char *s1, const char *s2, char s23, char s24, char s25, char s26, char s27, char s28) +{ + if (s1[3] == s23) + { + if (s23 == 0) + return 1; + else + return streq4 (s1, s2, s24, s25, s26, s27, s28); + } + else + return 0; +} + +static inline int +streq2 (const char *s1, const char *s2, char s22, char s23, char s24, char s25, char s26, char s27, char s28) +{ + if (s1[2] == s22) + { + if (s22 == 0) + return 1; + else + return streq3 (s1, s2, s23, s24, s25, s26, s27, s28); + } + else + return 0; +} + +static inline int +streq1 (const char *s1, const char *s2, char s21, char s22, char s23, char s24, char s25, char s26, char s27, char s28) +{ + if (s1[1] == s21) + { + if (s21 == 0) + return 1; + else + return streq2 (s1, s2, s22, s23, s24, s25, s26, s27, s28); + } + else + return 0; +} + +static inline int +streq0 (const char *s1, const char *s2, char s20, char s21, char s22, char s23, char s24, char s25, char s26, char s27, char s28) +{ + if (s1[0] == s20) + { + if (s20 == 0) + return 1; + else + return streq1 (s1, s2, s21, s22, s23, s24, s25, s26, s27, s28); + } + else + return 0; +} + +#define STREQ_OPT(s1,s2,s20,s21,s22,s23,s24,s25,s26,s27,s28) \ + streq0 (s1, s2, s20, s21, s22, s23, s24, s25, s26, s27, s28) + +#else + +#define STREQ_OPT(s1,s2,s20,s21,s22,s23,s24,s25,s26,s27,s28) \ + (strcmp (s1, s2) == 0) + +#endif + +#endif /* _GL_STREQ_H */ diff --git a/gettext-tools/gnulib-lib/strerror-override.c b/gettext-tools/gnulib-lib/strerror-override.c new file mode 100644 index 0000000..255d933 --- /dev/null +++ b/gettext-tools/gnulib-lib/strerror-override.c @@ -0,0 +1,302 @@ +/* strerror-override.c --- POSIX compatible system error routine + + Copyright (C) 2010-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Written by Bruno Haible , 2010. */ + +#include + +#include "strerror-override.h" + +#include + +#if GNULIB_defined_EWINSOCK /* native Windows platforms */ +# if HAVE_WINSOCK2_H +# include +# endif +#endif + +/* If ERRNUM maps to an errno value defined by gnulib, return a string + describing the error. Otherwise return NULL. */ +const char * +strerror_override (int errnum) +{ + /* These error messages are taken from glibc/sysdeps/gnu/errlist.c. */ + switch (errnum) + { +#if REPLACE_STRERROR_0 + case 0: + return "Success"; +#endif + +#if GNULIB_defined_ESOCK /* native Windows platforms with older */ + case EINPROGRESS: + return "Operation now in progress"; + case EALREADY: + return "Operation already in progress"; + case ENOTSOCK: + return "Socket operation on non-socket"; + case EDESTADDRREQ: + return "Destination address required"; + case EMSGSIZE: + return "Message too long"; + case EPROTOTYPE: + return "Protocol wrong type for socket"; + case ENOPROTOOPT: + return "Protocol not available"; + case EPROTONOSUPPORT: + return "Protocol not supported"; + case EOPNOTSUPP: + return "Operation not supported"; + case EAFNOSUPPORT: + return "Address family not supported by protocol"; + case EADDRINUSE: + return "Address already in use"; + case EADDRNOTAVAIL: + return "Cannot assign requested address"; + case ENETDOWN: + return "Network is down"; + case ENETUNREACH: + return "Network is unreachable"; + case ECONNRESET: + return "Connection reset by peer"; + case ENOBUFS: + return "No buffer space available"; + case EISCONN: + return "Transport endpoint is already connected"; + case ENOTCONN: + return "Transport endpoint is not connected"; + case ETIMEDOUT: + return "Connection timed out"; + case ECONNREFUSED: + return "Connection refused"; + case ELOOP: + return "Too many levels of symbolic links"; + case EHOSTUNREACH: + return "No route to host"; + case EWOULDBLOCK: + return "Operation would block"; +#endif +#if GNULIB_defined_ESTREAMS /* native Windows platforms with older */ + case ETXTBSY: + return "Text file busy"; + case ENODATA: + return "No data available"; + case ENOSR: + return "Out of streams resources"; + case ENOSTR: + return "Device not a stream"; + case ETIME: + return "Timer expired"; + case EOTHER: + return "Other error"; +#endif +#if GNULIB_defined_EWINSOCK /* native Windows platforms */ + case ESOCKTNOSUPPORT: + return "Socket type not supported"; + case EPFNOSUPPORT: + return "Protocol family not supported"; + case ESHUTDOWN: + return "Cannot send after transport endpoint shutdown"; + case ETOOMANYREFS: + return "Too many references: cannot splice"; + case EHOSTDOWN: + return "Host is down"; + case EPROCLIM: + return "Too many processes"; + case EUSERS: + return "Too many users"; + case EDQUOT: + return "Disk quota exceeded"; + case ESTALE: + return "Stale NFS file handle"; + case EREMOTE: + return "Object is remote"; +# if HAVE_WINSOCK2_H + /* WSA_INVALID_HANDLE maps to EBADF */ + /* WSA_NOT_ENOUGH_MEMORY maps to ENOMEM */ + /* WSA_INVALID_PARAMETER maps to EINVAL */ + case WSA_OPERATION_ABORTED: + return "Overlapped operation aborted"; + case WSA_IO_INCOMPLETE: + return "Overlapped I/O event object not in signaled state"; + case WSA_IO_PENDING: + return "Overlapped operations will complete later"; + /* WSAEINTR maps to EINTR */ + /* WSAEBADF maps to EBADF */ + /* WSAEACCES maps to EACCES */ + /* WSAEFAULT maps to EFAULT */ + /* WSAEINVAL maps to EINVAL */ + /* WSAEMFILE maps to EMFILE */ + /* WSAEWOULDBLOCK maps to EWOULDBLOCK */ + /* WSAEINPROGRESS maps to EINPROGRESS */ + /* WSAEALREADY maps to EALREADY */ + /* WSAENOTSOCK maps to ENOTSOCK */ + /* WSAEDESTADDRREQ maps to EDESTADDRREQ */ + /* WSAEMSGSIZE maps to EMSGSIZE */ + /* WSAEPROTOTYPE maps to EPROTOTYPE */ + /* WSAENOPROTOOPT maps to ENOPROTOOPT */ + /* WSAEPROTONOSUPPORT maps to EPROTONOSUPPORT */ + /* WSAESOCKTNOSUPPORT is ESOCKTNOSUPPORT */ + /* WSAEOPNOTSUPP maps to EOPNOTSUPP */ + /* WSAEPFNOSUPPORT is EPFNOSUPPORT */ + /* WSAEAFNOSUPPORT maps to EAFNOSUPPORT */ + /* WSAEADDRINUSE maps to EADDRINUSE */ + /* WSAEADDRNOTAVAIL maps to EADDRNOTAVAIL */ + /* WSAENETDOWN maps to ENETDOWN */ + /* WSAENETUNREACH maps to ENETUNREACH */ + /* WSAENETRESET maps to ENETRESET */ + /* WSAECONNABORTED maps to ECONNABORTED */ + /* WSAECONNRESET maps to ECONNRESET */ + /* WSAENOBUFS maps to ENOBUFS */ + /* WSAEISCONN maps to EISCONN */ + /* WSAENOTCONN maps to ENOTCONN */ + /* WSAESHUTDOWN is ESHUTDOWN */ + /* WSAETOOMANYREFS is ETOOMANYREFS */ + /* WSAETIMEDOUT maps to ETIMEDOUT */ + /* WSAECONNREFUSED maps to ECONNREFUSED */ + /* WSAELOOP maps to ELOOP */ + /* WSAENAMETOOLONG maps to ENAMETOOLONG */ + /* WSAEHOSTDOWN is EHOSTDOWN */ + /* WSAEHOSTUNREACH maps to EHOSTUNREACH */ + /* WSAENOTEMPTY maps to ENOTEMPTY */ + /* WSAEPROCLIM is EPROCLIM */ + /* WSAEUSERS is EUSERS */ + /* WSAEDQUOT is EDQUOT */ + /* WSAESTALE is ESTALE */ + /* WSAEREMOTE is EREMOTE */ + case WSASYSNOTREADY: + return "Network subsystem is unavailable"; + case WSAVERNOTSUPPORTED: + return "Winsock.dll version out of range"; + case WSANOTINITIALISED: + return "Successful WSAStartup not yet performed"; + case WSAEDISCON: + return "Graceful shutdown in progress"; + case WSAENOMORE: case WSA_E_NO_MORE: + return "No more results"; + case WSAECANCELLED: case WSA_E_CANCELLED: + return "Call was canceled"; + case WSAEINVALIDPROCTABLE: + return "Procedure call table is invalid"; + case WSAEINVALIDPROVIDER: + return "Service provider is invalid"; + case WSAEPROVIDERFAILEDINIT: + return "Service provider failed to initialize"; + case WSASYSCALLFAILURE: + return "System call failure"; + case WSASERVICE_NOT_FOUND: + return "Service not found"; + case WSATYPE_NOT_FOUND: + return "Class type not found"; + case WSAEREFUSED: + return "Database query was refused"; + case WSAHOST_NOT_FOUND: + return "Host not found"; + case WSATRY_AGAIN: + return "Nonauthoritative host not found"; + case WSANO_RECOVERY: + return "Nonrecoverable error"; + case WSANO_DATA: + return "Valid name, no data record of requested type"; + /* WSA_QOS_* omitted */ +# endif +#endif + +#if GNULIB_defined_ENOMSG + case ENOMSG: + return "No message of desired type"; +#endif + +#if GNULIB_defined_EIDRM + case EIDRM: + return "Identifier removed"; +#endif + +#if GNULIB_defined_ENOLINK + case ENOLINK: + return "Link has been severed"; +#endif + +#if GNULIB_defined_EPROTO + case EPROTO: + return "Protocol error"; +#endif + +#if GNULIB_defined_EMULTIHOP + case EMULTIHOP: + return "Multihop attempted"; +#endif + +#if GNULIB_defined_EBADMSG + case EBADMSG: + return "Bad message"; +#endif + +#if GNULIB_defined_EOVERFLOW + case EOVERFLOW: + return "Value too large for defined data type"; +#endif + +#if GNULIB_defined_ENOTSUP + case ENOTSUP: + return "Not supported"; +#endif + +#if GNULIB_defined_ENETRESET + case ENETRESET: + return "Network dropped connection on reset"; +#endif + +#if GNULIB_defined_ECONNABORTED + case ECONNABORTED: + return "Software caused connection abort"; +#endif + +#if GNULIB_defined_ESTALE + case ESTALE: + return "Stale NFS file handle"; +#endif + +#if GNULIB_defined_EDQUOT + case EDQUOT: + return "Disk quota exceeded"; +#endif + +#if GNULIB_defined_ECANCELED + case ECANCELED: + return "Operation canceled"; +#endif + +#if GNULIB_defined_EOWNERDEAD + case EOWNERDEAD: + return "Owner died"; +#endif + +#if GNULIB_defined_ENOTRECOVERABLE + case ENOTRECOVERABLE: + return "State not recoverable"; +#endif + +#if GNULIB_defined_EILSEQ + case EILSEQ: + return "Invalid or incomplete multibyte or wide character"; +#endif + + default: + return NULL; + } +} diff --git a/gettext-tools/gnulib-lib/strerror-override.h b/gettext-tools/gnulib-lib/strerror-override.h new file mode 100644 index 0000000..e98c1c1 --- /dev/null +++ b/gettext-tools/gnulib-lib/strerror-override.h @@ -0,0 +1,56 @@ +/* strerror-override.h --- POSIX compatible system error routine + + Copyright (C) 2010-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _GL_STRERROR_OVERRIDE_H +# define _GL_STRERROR_OVERRIDE_H + +# include +# include + +/* Reasonable buffer size that should never trigger ERANGE; if this + proves too small, we intentionally abort(), to remind us to fix + this value. */ +# define STACKBUF_LEN 256 + +/* If ERRNUM maps to an errno value defined by gnulib, return a string + describing the error. Otherwise return NULL. */ +# if REPLACE_STRERROR_0 \ + || GNULIB_defined_ESOCK \ + || GNULIB_defined_ESTREAMS \ + || GNULIB_defined_EWINSOCK \ + || GNULIB_defined_ENOMSG \ + || GNULIB_defined_EIDRM \ + || GNULIB_defined_ENOLINK \ + || GNULIB_defined_EPROTO \ + || GNULIB_defined_EMULTIHOP \ + || GNULIB_defined_EBADMSG \ + || GNULIB_defined_EOVERFLOW \ + || GNULIB_defined_ENOTSUP \ + || GNULIB_defined_ENETRESET \ + || GNULIB_defined_ECONNABORTED \ + || GNULIB_defined_ESTALE \ + || GNULIB_defined_EDQUOT \ + || GNULIB_defined_ECANCELED \ + || GNULIB_defined_EOWNERDEAD \ + || GNULIB_defined_ENOTRECOVERABLE \ + || GNULIB_defined_EILSEQ +extern const char *strerror_override (int errnum) _GL_ATTRIBUTE_CONST; +# else +# define strerror_override(ignored) NULL +# endif + +#endif /* _GL_STRERROR_OVERRIDE_H */ diff --git a/gettext-tools/gnulib-lib/strerror.c b/gettext-tools/gnulib-lib/strerror.c new file mode 100644 index 0000000..e54f0cc --- /dev/null +++ b/gettext-tools/gnulib-lib/strerror.c @@ -0,0 +1,70 @@ +/* strerror.c --- POSIX compatible system error routine + + Copyright (C) 2007-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include + +#include +#include +#include +#include + +#include "intprops.h" +#include "strerror-override.h" +#include "verify.h" + +/* Use the system functions, not the gnulib overrides in this file. */ +#undef sprintf + +char * +strerror (int n) +#undef strerror +{ + static char buf[STACKBUF_LEN]; + size_t len; + + /* Cast away const, due to the historical signature of strerror; + callers should not be modifying the string. */ + const char *msg = strerror_override (n); + if (msg) + return (char *) msg; + + msg = strerror (n); + + /* Our strerror_r implementation might use the system's strerror + buffer, so all other clients of strerror have to see the error + copied into a buffer that we manage. This is not thread-safe, + even if the system strerror is, but portable programs shouldn't + be using strerror if they care about thread-safety. */ + if (!msg || !*msg) + { + static char const fmt[] = "Unknown error %d"; + verify (sizeof buf >= sizeof (fmt) + INT_STRLEN_BOUND (n)); + sprintf (buf, fmt, n); + errno = EINVAL; + return buf; + } + + /* Fix STACKBUF_LEN if this ever aborts. */ + len = strlen (msg); + if (sizeof buf <= len) + abort (); + + return memcpy (buf, msg, len + 1); +} diff --git a/gettext-tools/gnulib-lib/striconv.c b/gettext-tools/gnulib-lib/striconv.c new file mode 100644 index 0000000..2495d81 --- /dev/null +++ b/gettext-tools/gnulib-lib/striconv.c @@ -0,0 +1,463 @@ +/* Charset conversion. + Copyright (C) 2001-2007, 2010-2014 Free Software Foundation, Inc. + Written by Bruno Haible and Simon Josefsson. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . */ + +#include + +/* Specification. */ +#include "striconv.h" + +#include +#include +#include + +#if HAVE_ICONV +# include +/* Get MB_LEN_MAX, CHAR_BIT. */ +# include +#endif + +#include "c-strcase.h" + +#ifndef SIZE_MAX +# define SIZE_MAX ((size_t) -1) +#endif + + +#if HAVE_ICONV + +int +mem_cd_iconv (const char *src, size_t srclen, iconv_t cd, + char **resultp, size_t *lengthp) +{ +# define tmpbufsize 4096 + size_t length; + char *result; + + /* Avoid glibc-2.1 bug and Solaris 2.7-2.9 bug. */ +# if defined _LIBICONV_VERSION \ + || !(((__GLIBC__ == 2 && __GLIBC_MINOR__ <= 1) && !defined __UCLIBC__) \ + || defined __sun) + /* Set to the initial state. */ + iconv (cd, NULL, NULL, NULL, NULL); +# endif + + /* Determine the length we need. */ + { + size_t count = 0; + /* The alignment is needed when converting e.g. to glibc's WCHAR_T or + libiconv's UCS-4-INTERNAL encoding. */ + union { unsigned int align; char buf[tmpbufsize]; } tmp; +# define tmpbuf tmp.buf + const char *inptr = src; + size_t insize = srclen; + + while (insize > 0) + { + char *outptr = tmpbuf; + size_t outsize = tmpbufsize; + size_t res = iconv (cd, + (ICONV_CONST char **) &inptr, &insize, + &outptr, &outsize); + + if (res == (size_t)(-1)) + { + if (errno == E2BIG) + ; + else if (errno == EINVAL) + break; + else + return -1; + } +# if !defined _LIBICONV_VERSION && !(defined __GLIBC__ && !defined __UCLIBC__) + /* Irix iconv() inserts a NUL byte if it cannot convert. + NetBSD iconv() inserts a question mark if it cannot convert. + Only GNU libiconv and GNU libc are known to prefer to fail rather + than doing a lossy conversion. */ + else if (res > 0) + { + errno = EILSEQ; + return -1; + } +# endif + count += outptr - tmpbuf; + } + /* Avoid glibc-2.1 bug and Solaris 2.7 bug. */ +# if defined _LIBICONV_VERSION \ + || !(((__GLIBC__ == 2 && __GLIBC_MINOR__ <= 1) && !defined __UCLIBC__) \ + || defined __sun) + { + char *outptr = tmpbuf; + size_t outsize = tmpbufsize; + size_t res = iconv (cd, NULL, NULL, &outptr, &outsize); + + if (res == (size_t)(-1)) + return -1; + count += outptr - tmpbuf; + } +# endif + length = count; +# undef tmpbuf + } + + if (length == 0) + { + *lengthp = 0; + return 0; + } + if (*resultp != NULL && *lengthp >= length) + result = *resultp; + else + { + result = (char *) malloc (length); + if (result == NULL) + { + errno = ENOMEM; + return -1; + } + } + + /* Avoid glibc-2.1 bug and Solaris 2.7-2.9 bug. */ +# if defined _LIBICONV_VERSION \ + || !(((__GLIBC__ == 2 && __GLIBC_MINOR__ <= 1) && !defined __UCLIBC__) \ + || defined __sun) + /* Return to the initial state. */ + iconv (cd, NULL, NULL, NULL, NULL); +# endif + + /* Do the conversion for real. */ + { + const char *inptr = src; + size_t insize = srclen; + char *outptr = result; + size_t outsize = length; + + while (insize > 0) + { + size_t res = iconv (cd, + (ICONV_CONST char **) &inptr, &insize, + &outptr, &outsize); + + if (res == (size_t)(-1)) + { + if (errno == EINVAL) + break; + else + goto fail; + } +# if !defined _LIBICONV_VERSION && !(defined __GLIBC__ && !defined __UCLIBC__) + /* Irix iconv() inserts a NUL byte if it cannot convert. + NetBSD iconv() inserts a question mark if it cannot convert. + Only GNU libiconv and GNU libc are known to prefer to fail rather + than doing a lossy conversion. */ + else if (res > 0) + { + errno = EILSEQ; + goto fail; + } +# endif + } + /* Avoid glibc-2.1 bug and Solaris 2.7 bug. */ +# if defined _LIBICONV_VERSION \ + || !(((__GLIBC__ == 2 && __GLIBC_MINOR__ <= 1) && !defined __UCLIBC__) \ + || defined __sun) + { + size_t res = iconv (cd, NULL, NULL, &outptr, &outsize); + + if (res == (size_t)(-1)) + goto fail; + } +# endif + if (outsize != 0) + abort (); + } + + *resultp = result; + *lengthp = length; + + return 0; + + fail: + { + if (result != *resultp) + { + int saved_errno = errno; + free (result); + errno = saved_errno; + } + return -1; + } +# undef tmpbufsize +} + +char * +str_cd_iconv (const char *src, iconv_t cd) +{ + /* For most encodings, a trailing NUL byte in the input will be converted + to a trailing NUL byte in the output. But not for UTF-7. So that this + function is usable for UTF-7, we have to exclude the NUL byte from the + conversion and add it by hand afterwards. */ +# if !defined _LIBICONV_VERSION && !(defined __GLIBC__ && !defined __UCLIBC__) + /* Irix iconv() inserts a NUL byte if it cannot convert. + NetBSD iconv() inserts a question mark if it cannot convert. + Only GNU libiconv and GNU libc are known to prefer to fail rather + than doing a lossy conversion. For other iconv() implementations, + we have to look at the number of irreversible conversions returned; + but this information is lost when iconv() returns for an E2BIG reason. + Therefore we cannot use the second, faster algorithm. */ + + char *result = NULL; + size_t length = 0; + int retval = mem_cd_iconv (src, strlen (src), cd, &result, &length); + char *final_result; + + if (retval < 0) + { + if (result != NULL) + abort (); + return NULL; + } + + /* Add the terminating NUL byte. */ + final_result = + (result != NULL ? realloc (result, length + 1) : malloc (length + 1)); + if (final_result == NULL) + { + free (result); + errno = ENOMEM; + return NULL; + } + final_result[length] = '\0'; + + return final_result; + +# else + /* This algorithm is likely faster than the one above. But it may produce + iconv() returns for an E2BIG reason, when the output size guess is too + small. Therefore it can only be used when we don't need the number of + irreversible conversions performed. */ + char *result; + size_t result_size; + size_t length; + const char *inptr = src; + size_t inbytes_remaining = strlen (src); + + /* Make a guess for the worst-case output size, in order to avoid a + realloc. It's OK if the guess is wrong as long as it is not zero and + doesn't lead to an integer overflow. */ + result_size = inbytes_remaining; + { + size_t approx_sqrt_SIZE_MAX = SIZE_MAX >> (sizeof (size_t) * CHAR_BIT / 2); + if (result_size <= approx_sqrt_SIZE_MAX / MB_LEN_MAX) + result_size *= MB_LEN_MAX; + } + result_size += 1; /* for the terminating NUL */ + + result = (char *) malloc (result_size); + if (result == NULL) + { + errno = ENOMEM; + return NULL; + } + + /* Avoid glibc-2.1 bug and Solaris 2.7-2.9 bug. */ +# if defined _LIBICONV_VERSION \ + || !(((__GLIBC__ == 2 && __GLIBC_MINOR__ <= 1) && !defined __UCLIBC__) \ + || defined __sun) + /* Set to the initial state. */ + iconv (cd, NULL, NULL, NULL, NULL); +# endif + + /* Do the conversion. */ + { + char *outptr = result; + size_t outbytes_remaining = result_size - 1; + + for (;;) + { + /* Here inptr + inbytes_remaining = src + strlen (src), + outptr + outbytes_remaining = result + result_size - 1. */ + size_t res = iconv (cd, + (ICONV_CONST char **) &inptr, &inbytes_remaining, + &outptr, &outbytes_remaining); + + if (res == (size_t)(-1)) + { + if (errno == EINVAL) + break; + else if (errno == E2BIG) + { + size_t used = outptr - result; + size_t newsize = result_size * 2; + char *newresult; + + if (!(newsize > result_size)) + { + errno = ENOMEM; + goto failed; + } + newresult = (char *) realloc (result, newsize); + if (newresult == NULL) + { + errno = ENOMEM; + goto failed; + } + result = newresult; + result_size = newsize; + outptr = result + used; + outbytes_remaining = result_size - 1 - used; + } + else + goto failed; + } + else + break; + } + /* Avoid glibc-2.1 bug and Solaris 2.7 bug. */ +# if defined _LIBICONV_VERSION \ + || !(((__GLIBC__ == 2 && __GLIBC_MINOR__ <= 1) && !defined __UCLIBC__) \ + || defined __sun) + for (;;) + { + /* Here outptr + outbytes_remaining = result + result_size - 1. */ + size_t res = iconv (cd, NULL, NULL, &outptr, &outbytes_remaining); + + if (res == (size_t)(-1)) + { + if (errno == E2BIG) + { + size_t used = outptr - result; + size_t newsize = result_size * 2; + char *newresult; + + if (!(newsize > result_size)) + { + errno = ENOMEM; + goto failed; + } + newresult = (char *) realloc (result, newsize); + if (newresult == NULL) + { + errno = ENOMEM; + goto failed; + } + result = newresult; + result_size = newsize; + outptr = result + used; + outbytes_remaining = result_size - 1 - used; + } + else + goto failed; + } + else + break; + } +# endif + + /* Add the terminating NUL byte. */ + *outptr++ = '\0'; + + length = outptr - result; + } + + /* Give away unused memory. */ + if (length < result_size) + { + char *smaller_result = (char *) realloc (result, length); + + if (smaller_result != NULL) + result = smaller_result; + } + + return result; + + failed: + { + int saved_errno = errno; + free (result); + errno = saved_errno; + return NULL; + } + +# endif +} + +#endif + +char * +str_iconv (const char *src, const char *from_codeset, const char *to_codeset) +{ + if (*src == '\0' || c_strcasecmp (from_codeset, to_codeset) == 0) + { + char *result = strdup (src); + + if (result == NULL) + errno = ENOMEM; + return result; + } + else + { +#if HAVE_ICONV + iconv_t cd; + char *result; + + /* Avoid glibc-2.1 bug with EUC-KR. */ +# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ <= 1) && !defined __UCLIBC__) \ + && !defined _LIBICONV_VERSION + if (c_strcasecmp (from_codeset, "EUC-KR") == 0 + || c_strcasecmp (to_codeset, "EUC-KR") == 0) + { + errno = EINVAL; + return NULL; + } +# endif + cd = iconv_open (to_codeset, from_codeset); + if (cd == (iconv_t) -1) + return NULL; + + result = str_cd_iconv (src, cd); + + if (result == NULL) + { + /* Close cd, but preserve the errno from str_cd_iconv. */ + int saved_errno = errno; + iconv_close (cd); + errno = saved_errno; + } + else + { + if (iconv_close (cd) < 0) + { + /* Return NULL, but free the allocated memory, and while doing + that, preserve the errno from iconv_close. */ + int saved_errno = errno; + free (result); + errno = saved_errno; + return NULL; + } + } + return result; +#else + /* This is a different error code than if iconv_open existed but didn't + support from_codeset and to_codeset, so that the caller can emit + an error message such as + "iconv() is not supported. Installing GNU libiconv and + then reinstalling this package would fix this." */ + errno = ENOSYS; + return NULL; +#endif + } +} diff --git a/gettext-tools/gnulib-lib/striconv.h b/gettext-tools/gnulib-lib/striconv.h new file mode 100644 index 0000000..5747731 --- /dev/null +++ b/gettext-tools/gnulib-lib/striconv.h @@ -0,0 +1,75 @@ +/* Charset conversion. + Copyright (C) 2001-2004, 2006-2007, 2009-2014 Free Software Foundation, Inc. + Written by Bruno Haible and Simon Josefsson. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . */ + +#ifndef _STRICONV_H +#define _STRICONV_H + +#include +#if HAVE_ICONV +#include +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + + +#if HAVE_ICONV + +/* Convert an entire string from one encoding to another, using iconv. + The original string is at [SRC,...,SRC+SRCLEN-1]. + The conversion descriptor is passed as CD. + *RESULTP and *LENGTH should initially be a scratch buffer and its size, + or *RESULTP can initially be NULL. + May erase the contents of the memory at *RESULTP. + Return value: 0 if successful, otherwise -1 and errno set. + If successful: The resulting string is stored in *RESULTP and its length + in *LENGTHP. *RESULTP is set to a freshly allocated memory block, or is + unchanged if no dynamic memory allocation was necessary. */ +extern int mem_cd_iconv (const char *src, size_t srclen, iconv_t cd, + char **resultp, size_t *lengthp); + +/* Convert an entire string from one encoding to another, using iconv. + The original string is the NUL-terminated string starting at SRC. + The conversion descriptor is passed as CD. Both the "from" and the "to" + encoding must use a single NUL byte at the end of the string (i.e. not + UCS-2, UCS-4, UTF-16, UTF-32). + Allocate a malloced memory block for the result. + Return value: the freshly allocated resulting NUL-terminated string if + successful, otherwise NULL and errno set. */ +extern char * str_cd_iconv (const char *src, iconv_t cd); + +#endif + +/* Convert an entire string from one encoding to another, using iconv. + The original string is the NUL-terminated string starting at SRC. + Both the "from" and the "to" encoding must use a single NUL byte at the + end of the string (i.e. not UCS-2, UCS-4, UTF-16, UTF-32). + Allocate a malloced memory block for the result. + Return value: the freshly allocated resulting NUL-terminated string if + successful, otherwise NULL and errno set. */ +extern char * str_iconv (const char *src, + const char *from_codeset, const char *to_codeset); + + +#ifdef __cplusplus +} +#endif + + +#endif /* _STRICONV_H */ diff --git a/gettext-tools/gnulib-lib/striconveh.c b/gettext-tools/gnulib-lib/striconveh.c new file mode 100644 index 0000000..82222bc --- /dev/null +++ b/gettext-tools/gnulib-lib/striconveh.c @@ -0,0 +1,1199 @@ +/* Character set conversion with error handling. + Copyright (C) 2001-2014 Free Software Foundation, Inc. + Written by Bruno Haible and Simon Josefsson. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include "striconveh.h" + +#include +#include +#include +#include + +#if HAVE_ICONV +# include +# include "unistr.h" +#endif + +#include "c-strcase.h" +#include "c-strcaseeq.h" + +#ifndef SIZE_MAX +# define SIZE_MAX ((size_t) -1) +#endif + + +#if HAVE_ICONV + +/* The caller must provide an iconveh_t, not just an iconv_t, because when a + conversion error occurs, we may have to determine the Unicode representation + of the inconvertible character. */ + +int +iconveh_open (const char *to_codeset, const char *from_codeset, iconveh_t *cdp) +{ + iconv_t cd; + iconv_t cd1; + iconv_t cd2; + + /* Avoid glibc-2.1 bug with EUC-KR. */ +# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ <= 1) && !defined __UCLIBC__) \ + && !defined _LIBICONV_VERSION + if (c_strcasecmp (from_codeset, "EUC-KR") == 0 + || c_strcasecmp (to_codeset, "EUC-KR") == 0) + { + errno = EINVAL; + return -1; + } +# endif + + cd = iconv_open (to_codeset, from_codeset); + + if (STRCASEEQ (from_codeset, "UTF-8", 'U','T','F','-','8',0,0,0,0)) + cd1 = (iconv_t)(-1); + else + { + cd1 = iconv_open ("UTF-8", from_codeset); + if (cd1 == (iconv_t)(-1)) + { + int saved_errno = errno; + if (cd != (iconv_t)(-1)) + iconv_close (cdp->cd); + errno = saved_errno; + return -1; + } + } + + if (STRCASEEQ (to_codeset, "UTF-8", 'U','T','F','-','8',0,0,0,0) +# if (((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2) \ + && !defined __UCLIBC__) \ + || _LIBICONV_VERSION >= 0x0105 + || c_strcasecmp (to_codeset, "UTF-8//TRANSLIT") == 0 +# endif + ) + cd2 = (iconv_t)(-1); + else + { + cd2 = iconv_open (to_codeset, "UTF-8"); + if (cd2 == (iconv_t)(-1)) + { + int saved_errno = errno; + if (cd1 != (iconv_t)(-1)) + iconv_close (cd1); + if (cd != (iconv_t)(-1)) + iconv_close (cd); + errno = saved_errno; + return -1; + } + } + + cdp->cd = cd; + cdp->cd1 = cd1; + cdp->cd2 = cd2; + return 0; +} + +int +iconveh_close (const iconveh_t *cd) +{ + if (cd->cd2 != (iconv_t)(-1) && iconv_close (cd->cd2) < 0) + { + /* Return -1, but preserve the errno from iconv_close. */ + int saved_errno = errno; + if (cd->cd1 != (iconv_t)(-1)) + iconv_close (cd->cd1); + if (cd->cd != (iconv_t)(-1)) + iconv_close (cd->cd); + errno = saved_errno; + return -1; + } + if (cd->cd1 != (iconv_t)(-1) && iconv_close (cd->cd1) < 0) + { + /* Return -1, but preserve the errno from iconv_close. */ + int saved_errno = errno; + if (cd->cd != (iconv_t)(-1)) + iconv_close (cd->cd); + errno = saved_errno; + return -1; + } + if (cd->cd != (iconv_t)(-1) && iconv_close (cd->cd) < 0) + return -1; + return 0; +} + +/* iconv_carefully is like iconv, except that it stops as soon as it encounters + a conversion error, and it returns in *INCREMENTED a boolean telling whether + it has incremented the input pointers past the error location. */ +# if !defined _LIBICONV_VERSION && !(defined __GLIBC__ && !defined __UCLIBC__) +/* Irix iconv() inserts a NUL byte if it cannot convert. + NetBSD iconv() inserts a question mark if it cannot convert. + Only GNU libiconv and GNU libc are known to prefer to fail rather + than doing a lossy conversion. */ +static size_t +iconv_carefully (iconv_t cd, + const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft, + bool *incremented) +{ + const char *inptr = *inbuf; + const char *inptr_end = inptr + *inbytesleft; + char *outptr = *outbuf; + size_t outsize = *outbytesleft; + const char *inptr_before; + size_t res; + + do + { + size_t insize; + + inptr_before = inptr; + res = (size_t)(-1); + + for (insize = 1; inptr + insize <= inptr_end; insize++) + { + res = iconv (cd, + (ICONV_CONST char **) &inptr, &insize, + &outptr, &outsize); + if (!(res == (size_t)(-1) && errno == EINVAL)) + break; + /* iconv can eat up a shift sequence but give EINVAL while attempting + to convert the first character. E.g. libiconv does this. */ + if (inptr > inptr_before) + { + res = 0; + break; + } + } + + if (res == 0) + { + *outbuf = outptr; + *outbytesleft = outsize; + } + } + while (res == 0 && inptr < inptr_end); + + *inbuf = inptr; + *inbytesleft = inptr_end - inptr; + if (res != (size_t)(-1) && res > 0) + { + /* iconv() has already incremented INPTR. We cannot go back to a + previous INPTR, otherwise the state inside CD would become invalid, + if FROM_CODESET is a stateful encoding. So, tell the caller that + *INBUF has already been incremented. */ + *incremented = (inptr > inptr_before); + errno = EILSEQ; + return (size_t)(-1); + } + else + { + *incremented = false; + return res; + } +} +# else +# define iconv_carefully(cd, inbuf, inbytesleft, outbuf, outbytesleft, incremented) \ + (*(incremented) = false, \ + iconv (cd, (ICONV_CONST char **) (inbuf), inbytesleft, outbuf, outbytesleft)) +# endif + +/* iconv_carefully_1 is like iconv_carefully, except that it stops after + converting one character or one shift sequence. */ +static size_t +iconv_carefully_1 (iconv_t cd, + const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft, + bool *incremented) +{ + const char *inptr_before = *inbuf; + const char *inptr = inptr_before; + const char *inptr_end = inptr_before + *inbytesleft; + char *outptr = *outbuf; + size_t outsize = *outbytesleft; + size_t res = (size_t)(-1); + size_t insize; + + for (insize = 1; inptr_before + insize <= inptr_end; insize++) + { + inptr = inptr_before; + res = iconv (cd, + (ICONV_CONST char **) &inptr, &insize, + &outptr, &outsize); + if (!(res == (size_t)(-1) && errno == EINVAL)) + break; + /* iconv can eat up a shift sequence but give EINVAL while attempting + to convert the first character. E.g. libiconv does this. */ + if (inptr > inptr_before) + { + res = 0; + break; + } + } + + *inbuf = inptr; + *inbytesleft = inptr_end - inptr; +# if !defined _LIBICONV_VERSION && !(defined __GLIBC__ && !defined __UCLIBC__) + /* Irix iconv() inserts a NUL byte if it cannot convert. + NetBSD iconv() inserts a question mark if it cannot convert. + Only GNU libiconv and GNU libc are known to prefer to fail rather + than doing a lossy conversion. */ + if (res != (size_t)(-1) && res > 0) + { + /* iconv() has already incremented INPTR. We cannot go back to a + previous INPTR, otherwise the state inside CD would become invalid, + if FROM_CODESET is a stateful encoding. So, tell the caller that + *INBUF has already been incremented. */ + *incremented = (inptr > inptr_before); + errno = EILSEQ; + return (size_t)(-1); + } +# endif + + if (res != (size_t)(-1)) + { + *outbuf = outptr; + *outbytesleft = outsize; + } + *incremented = false; + return res; +} + +/* utf8conv_carefully is like iconv, except that + - it converts from UTF-8 to UTF-8, + - it stops as soon as it encounters a conversion error, and it returns + in *INCREMENTED a boolean telling whether it has incremented the input + pointers past the error location, + - if one_character_only is true, it stops after converting one + character. */ +static size_t +utf8conv_carefully (bool one_character_only, + const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft, + bool *incremented) +{ + const char *inptr = *inbuf; + size_t insize = *inbytesleft; + char *outptr = *outbuf; + size_t outsize = *outbytesleft; + size_t res; + + res = 0; + do + { + ucs4_t uc; + int n; + int m; + + n = u8_mbtoucr (&uc, (const uint8_t *) inptr, insize); + if (n < 0) + { + errno = (n == -2 ? EINVAL : EILSEQ); + n = u8_mbtouc (&uc, (const uint8_t *) inptr, insize); + inptr += n; + insize -= n; + res = (size_t)(-1); + *incremented = true; + break; + } + if (outsize == 0) + { + errno = E2BIG; + res = (size_t)(-1); + *incremented = false; + break; + } + m = u8_uctomb ((uint8_t *) outptr, uc, outsize); + if (m == -2) + { + errno = E2BIG; + res = (size_t)(-1); + *incremented = false; + break; + } + inptr += n; + insize -= n; + if (m == -1) + { + errno = EILSEQ; + res = (size_t)(-1); + *incremented = true; + break; + } + outptr += m; + outsize -= m; + } + while (!one_character_only && insize > 0); + + *inbuf = inptr; + *inbytesleft = insize; + *outbuf = outptr; + *outbytesleft = outsize; + return res; +} + +static int +mem_cd_iconveh_internal (const char *src, size_t srclen, + iconv_t cd, iconv_t cd1, iconv_t cd2, + enum iconv_ilseq_handler handler, + size_t extra_alloc, + size_t *offsets, + char **resultp, size_t *lengthp) +{ + /* When a conversion error occurs, we cannot start using CD1 and CD2 at + this point: FROM_CODESET may be a stateful encoding like ISO-2022-KR. + Instead, we have to start afresh from the beginning of SRC. */ + /* Use a temporary buffer, so that for small strings, a single malloc() + call will be sufficient. */ +# define tmpbufsize 4096 + /* The alignment is needed when converting e.g. to glibc's WCHAR_T or + libiconv's UCS-4-INTERNAL encoding. */ + union { unsigned int align; char buf[tmpbufsize]; } tmp; +# define tmpbuf tmp.buf + + char *initial_result; + char *result; + size_t allocated; + size_t length; + size_t last_length = (size_t)(-1); /* only needed if offsets != NULL */ + + if (*resultp != NULL && *lengthp >= sizeof (tmpbuf)) + { + initial_result = *resultp; + allocated = *lengthp; + } + else + { + initial_result = tmpbuf; + allocated = sizeof (tmpbuf); + } + result = initial_result; + + /* Test whether a direct conversion is possible at all. */ + if (cd == (iconv_t)(-1)) + goto indirectly; + + if (offsets != NULL) + { + size_t i; + + for (i = 0; i < srclen; i++) + offsets[i] = (size_t)(-1); + + last_length = (size_t)(-1); + } + length = 0; + + /* First, try a direct conversion, and see whether a conversion error + occurs at all. */ + { + const char *inptr = src; + size_t insize = srclen; + + /* Avoid glibc-2.1 bug and Solaris 2.7-2.9 bug. */ +# if defined _LIBICONV_VERSION \ + || !(((__GLIBC__ == 2 && __GLIBC_MINOR__ <= 1) && !defined __UCLIBC__) \ + || defined __sun) + /* Set to the initial state. */ + iconv (cd, NULL, NULL, NULL, NULL); +# endif + + while (insize > 0) + { + char *outptr = result + length; + size_t outsize = allocated - extra_alloc - length; + bool incremented; + size_t res; + bool grow; + + if (offsets != NULL) + { + if (length != last_length) /* ensure that offset[] be increasing */ + { + offsets[inptr - src] = length; + last_length = length; + } + res = iconv_carefully_1 (cd, + &inptr, &insize, + &outptr, &outsize, + &incremented); + } + else + /* Use iconv_carefully instead of iconv here, because: + - If TO_CODESET is UTF-8, we can do the error handling in this + loop, no need for a second loop, + - With iconv() implementations other than GNU libiconv and GNU + libc, if we use iconv() in a big swoop, checking for an E2BIG + return, we lose the number of irreversible conversions. */ + res = iconv_carefully (cd, + &inptr, &insize, + &outptr, &outsize, + &incremented); + + length = outptr - result; + grow = (length + extra_alloc > allocated / 2); + if (res == (size_t)(-1)) + { + if (errno == E2BIG) + grow = true; + else if (errno == EINVAL) + break; + else if (errno == EILSEQ && handler != iconveh_error) + { + if (cd2 == (iconv_t)(-1)) + { + /* TO_CODESET is UTF-8. */ + /* Error handling can produce up to 1 byte of output. */ + if (length + 1 + extra_alloc > allocated) + { + char *memory; + + allocated = 2 * allocated; + if (length + 1 + extra_alloc > allocated) + abort (); + if (result == initial_result) + memory = (char *) malloc (allocated); + else + memory = (char *) realloc (result, allocated); + if (memory == NULL) + { + if (result != initial_result) + free (result); + errno = ENOMEM; + return -1; + } + if (result == initial_result) + memcpy (memory, initial_result, length); + result = memory; + grow = false; + } + /* The input is invalid in FROM_CODESET. Eat up one byte + and emit a question mark. */ + if (!incremented) + { + if (insize == 0) + abort (); + inptr++; + insize--; + } + result[length] = '?'; + length++; + } + else + goto indirectly; + } + else + { + if (result != initial_result) + { + int saved_errno = errno; + free (result); + errno = saved_errno; + } + return -1; + } + } + if (insize == 0) + break; + if (grow) + { + char *memory; + + allocated = 2 * allocated; + if (result == initial_result) + memory = (char *) malloc (allocated); + else + memory = (char *) realloc (result, allocated); + if (memory == NULL) + { + if (result != initial_result) + free (result); + errno = ENOMEM; + return -1; + } + if (result == initial_result) + memcpy (memory, initial_result, length); + result = memory; + } + } + } + + /* Now get the conversion state back to the initial state. + But avoid glibc-2.1 bug and Solaris 2.7 bug. */ +#if defined _LIBICONV_VERSION \ + || !(((__GLIBC__ == 2 && __GLIBC_MINOR__ <= 1) && !defined __UCLIBC__) \ + || defined __sun) + for (;;) + { + char *outptr = result + length; + size_t outsize = allocated - extra_alloc - length; + size_t res; + + res = iconv (cd, NULL, NULL, &outptr, &outsize); + length = outptr - result; + if (res == (size_t)(-1)) + { + if (errno == E2BIG) + { + char *memory; + + allocated = 2 * allocated; + if (result == initial_result) + memory = (char *) malloc (allocated); + else + memory = (char *) realloc (result, allocated); + if (memory == NULL) + { + if (result != initial_result) + free (result); + errno = ENOMEM; + return -1; + } + if (result == initial_result) + memcpy (memory, initial_result, length); + result = memory; + } + else + { + if (result != initial_result) + { + int saved_errno = errno; + free (result); + errno = saved_errno; + } + return -1; + } + } + else + break; + } +#endif + + /* The direct conversion succeeded. */ + goto done; + + indirectly: + /* The direct conversion failed. + Use a conversion through UTF-8. */ + if (offsets != NULL) + { + size_t i; + + for (i = 0; i < srclen; i++) + offsets[i] = (size_t)(-1); + + last_length = (size_t)(-1); + } + length = 0; + { + const bool slowly = (offsets != NULL || handler == iconveh_error); +# define utf8bufsize 4096 /* may also be smaller or larger than tmpbufsize */ + char utf8buf[utf8bufsize + 1]; + size_t utf8len = 0; + const char *in1ptr = src; + size_t in1size = srclen; + bool do_final_flush1 = true; + bool do_final_flush2 = true; + + /* Avoid glibc-2.1 bug and Solaris 2.7-2.9 bug. */ +# if defined _LIBICONV_VERSION \ + || !(((__GLIBC__ == 2 && __GLIBC_MINOR__ <= 1) && !defined __UCLIBC__) \ + || defined __sun) + /* Set to the initial state. */ + if (cd1 != (iconv_t)(-1)) + iconv (cd1, NULL, NULL, NULL, NULL); + if (cd2 != (iconv_t)(-1)) + iconv (cd2, NULL, NULL, NULL, NULL); +# endif + + while (in1size > 0 || do_final_flush1 || utf8len > 0 || do_final_flush2) + { + char *out1ptr = utf8buf + utf8len; + size_t out1size = utf8bufsize - utf8len; + bool incremented1; + size_t res1; + int errno1; + + /* Conversion step 1: from FROM_CODESET to UTF-8. */ + if (in1size > 0) + { + if (offsets != NULL + && length != last_length) /* ensure that offset[] be increasing */ + { + offsets[in1ptr - src] = length; + last_length = length; + } + if (cd1 != (iconv_t)(-1)) + { + if (slowly) + res1 = iconv_carefully_1 (cd1, + &in1ptr, &in1size, + &out1ptr, &out1size, + &incremented1); + else + res1 = iconv_carefully (cd1, + &in1ptr, &in1size, + &out1ptr, &out1size, + &incremented1); + } + else + { + /* FROM_CODESET is UTF-8. */ + res1 = utf8conv_carefully (slowly, + &in1ptr, &in1size, + &out1ptr, &out1size, + &incremented1); + } + } + else if (do_final_flush1) + { + /* Now get the conversion state of CD1 back to the initial state. + But avoid glibc-2.1 bug and Solaris 2.7 bug. */ +# if defined _LIBICONV_VERSION \ + || !(((__GLIBC__ == 2 && __GLIBC_MINOR__ <= 1) && !defined __UCLIBC__) \ + || defined __sun) + if (cd1 != (iconv_t)(-1)) + res1 = iconv (cd1, NULL, NULL, &out1ptr, &out1size); + else +# endif + res1 = 0; + do_final_flush1 = false; + incremented1 = true; + } + else + { + res1 = 0; + incremented1 = true; + } + if (res1 == (size_t)(-1) + && !(errno == E2BIG || errno == EINVAL || errno == EILSEQ)) + { + if (result != initial_result) + { + int saved_errno = errno; + free (result); + errno = saved_errno; + } + return -1; + } + if (res1 == (size_t)(-1) + && errno == EILSEQ && handler != iconveh_error) + { + /* The input is invalid in FROM_CODESET. Eat up one byte and + emit a question mark. Room for the question mark was allocated + at the end of utf8buf. */ + if (!incremented1) + { + if (in1size == 0) + abort (); + in1ptr++; + in1size--; + } + *out1ptr++ = '?'; + res1 = 0; + } + errno1 = errno; + utf8len = out1ptr - utf8buf; + + if (offsets != NULL + || in1size == 0 + || utf8len > utf8bufsize / 2 + || (res1 == (size_t)(-1) && errno1 == E2BIG)) + { + /* Conversion step 2: from UTF-8 to TO_CODESET. */ + const char *in2ptr = utf8buf; + size_t in2size = utf8len; + + while (in2size > 0 + || (in1size == 0 && !do_final_flush1 && do_final_flush2)) + { + char *out2ptr = result + length; + size_t out2size = allocated - extra_alloc - length; + bool incremented2; + size_t res2; + bool grow; + + if (in2size > 0) + { + if (cd2 != (iconv_t)(-1)) + res2 = iconv_carefully (cd2, + &in2ptr, &in2size, + &out2ptr, &out2size, + &incremented2); + else + /* TO_CODESET is UTF-8. */ + res2 = utf8conv_carefully (false, + &in2ptr, &in2size, + &out2ptr, &out2size, + &incremented2); + } + else /* in1size == 0 && !do_final_flush1 + && in2size == 0 && do_final_flush2 */ + { + /* Now get the conversion state of CD1 back to the initial + state. But avoid glibc-2.1 bug and Solaris 2.7 bug. */ +# if defined _LIBICONV_VERSION \ + || !(((__GLIBC__ == 2 && __GLIBC_MINOR__ <= 1) && !defined __UCLIBC__) \ + || defined __sun) + if (cd2 != (iconv_t)(-1)) + res2 = iconv (cd2, NULL, NULL, &out2ptr, &out2size); + else +# endif + res2 = 0; + do_final_flush2 = false; + incremented2 = true; + } + + length = out2ptr - result; + grow = (length + extra_alloc > allocated / 2); + if (res2 == (size_t)(-1)) + { + if (errno == E2BIG) + grow = true; + else if (errno == EINVAL) + break; + else if (errno == EILSEQ && handler != iconveh_error) + { + /* Error handling can produce up to 10 bytes of ASCII + output. But TO_CODESET may be UCS-2, UTF-16 or + UCS-4, so use CD2 here as well. */ + char scratchbuf[10]; + size_t scratchlen; + ucs4_t uc; + const char *inptr; + size_t insize; + size_t res; + + if (incremented2) + { + if (u8_prev (&uc, (const uint8_t *) in2ptr, + (const uint8_t *) utf8buf) + == NULL) + abort (); + } + else + { + int n; + if (in2size == 0) + abort (); + n = u8_mbtouc_unsafe (&uc, (const uint8_t *) in2ptr, + in2size); + in2ptr += n; + in2size -= n; + } + + if (handler == iconveh_escape_sequence) + { + static char hex[16] = "0123456789ABCDEF"; + scratchlen = 0; + scratchbuf[scratchlen++] = '\\'; + if (uc < 0x10000) + scratchbuf[scratchlen++] = 'u'; + else + { + scratchbuf[scratchlen++] = 'U'; + scratchbuf[scratchlen++] = hex[(uc>>28) & 15]; + scratchbuf[scratchlen++] = hex[(uc>>24) & 15]; + scratchbuf[scratchlen++] = hex[(uc>>20) & 15]; + scratchbuf[scratchlen++] = hex[(uc>>16) & 15]; + } + scratchbuf[scratchlen++] = hex[(uc>>12) & 15]; + scratchbuf[scratchlen++] = hex[(uc>>8) & 15]; + scratchbuf[scratchlen++] = hex[(uc>>4) & 15]; + scratchbuf[scratchlen++] = hex[uc & 15]; + } + else + { + scratchbuf[0] = '?'; + scratchlen = 1; + } + + inptr = scratchbuf; + insize = scratchlen; + if (cd2 != (iconv_t)(-1)) + res = iconv (cd2, + (ICONV_CONST char **) &inptr, &insize, + &out2ptr, &out2size); + else + { + /* TO_CODESET is UTF-8. */ + if (out2size >= insize) + { + memcpy (out2ptr, inptr, insize); + out2ptr += insize; + out2size -= insize; + inptr += insize; + insize = 0; + res = 0; + } + else + { + errno = E2BIG; + res = (size_t)(-1); + } + } + length = out2ptr - result; + if (res == (size_t)(-1) && errno == E2BIG) + { + char *memory; + + allocated = 2 * allocated; + if (length + 1 + extra_alloc > allocated) + abort (); + if (result == initial_result) + memory = (char *) malloc (allocated); + else + memory = (char *) realloc (result, allocated); + if (memory == NULL) + { + if (result != initial_result) + free (result); + errno = ENOMEM; + return -1; + } + if (result == initial_result) + memcpy (memory, initial_result, length); + result = memory; + grow = false; + + out2ptr = result + length; + out2size = allocated - extra_alloc - length; + if (cd2 != (iconv_t)(-1)) + res = iconv (cd2, + (ICONV_CONST char **) &inptr, + &insize, + &out2ptr, &out2size); + else + { + /* TO_CODESET is UTF-8. */ + if (!(out2size >= insize)) + abort (); + memcpy (out2ptr, inptr, insize); + out2ptr += insize; + out2size -= insize; + inptr += insize; + insize = 0; + res = 0; + } + length = out2ptr - result; + } +# if !defined _LIBICONV_VERSION && !(defined __GLIBC__ && !defined __UCLIBC__) + /* Irix iconv() inserts a NUL byte if it cannot convert. + NetBSD iconv() inserts a question mark if it cannot + convert. + Only GNU libiconv and GNU libc are known to prefer + to fail rather than doing a lossy conversion. */ + if (res != (size_t)(-1) && res > 0) + { + errno = EILSEQ; + res = (size_t)(-1); + } +# endif + if (res == (size_t)(-1)) + { + /* Failure converting the ASCII replacement. */ + if (result != initial_result) + { + int saved_errno = errno; + free (result); + errno = saved_errno; + } + return -1; + } + } + else + { + if (result != initial_result) + { + int saved_errno = errno; + free (result); + errno = saved_errno; + } + return -1; + } + } + if (!(in2size > 0 + || (in1size == 0 && !do_final_flush1 && do_final_flush2))) + break; + if (grow) + { + char *memory; + + allocated = 2 * allocated; + if (result == initial_result) + memory = (char *) malloc (allocated); + else + memory = (char *) realloc (result, allocated); + if (memory == NULL) + { + if (result != initial_result) + free (result); + errno = ENOMEM; + return -1; + } + if (result == initial_result) + memcpy (memory, initial_result, length); + result = memory; + } + } + + /* Move the remaining bytes to the beginning of utf8buf. */ + if (in2size > 0) + memmove (utf8buf, in2ptr, in2size); + utf8len = in2size; + } + + if (res1 == (size_t)(-1)) + { + if (errno1 == EINVAL) + in1size = 0; + else if (errno1 == EILSEQ) + { + if (result != initial_result) + free (result); + errno = errno1; + return -1; + } + } + } +# undef utf8bufsize + } + + done: + /* Now the final memory allocation. */ + if (result == tmpbuf) + { + size_t memsize = length + extra_alloc; + + if (*resultp != NULL && *lengthp >= memsize) + result = *resultp; + else + { + char *memory; + + memory = (char *) malloc (memsize > 0 ? memsize : 1); + if (memory != NULL) + result = memory; + else + { + errno = ENOMEM; + return -1; + } + } + memcpy (result, tmpbuf, length); + } + else if (result != *resultp && length + extra_alloc < allocated) + { + /* Shrink the allocated memory if possible. */ + size_t memsize = length + extra_alloc; + char *memory; + + memory = (char *) realloc (result, memsize > 0 ? memsize : 1); + if (memory != NULL) + result = memory; + } + *resultp = result; + *lengthp = length; + return 0; +# undef tmpbuf +# undef tmpbufsize +} + +int +mem_cd_iconveh (const char *src, size_t srclen, + const iconveh_t *cd, + enum iconv_ilseq_handler handler, + size_t *offsets, + char **resultp, size_t *lengthp) +{ + return mem_cd_iconveh_internal (src, srclen, cd->cd, cd->cd1, cd->cd2, + handler, 0, offsets, resultp, lengthp); +} + +char * +str_cd_iconveh (const char *src, + const iconveh_t *cd, + enum iconv_ilseq_handler handler) +{ + /* For most encodings, a trailing NUL byte in the input will be converted + to a trailing NUL byte in the output. But not for UTF-7. So that this + function is usable for UTF-7, we have to exclude the NUL byte from the + conversion and add it by hand afterwards. */ + char *result = NULL; + size_t length = 0; + int retval = mem_cd_iconveh_internal (src, strlen (src), + cd->cd, cd->cd1, cd->cd2, handler, 1, + NULL, &result, &length); + + if (retval < 0) + { + if (result != NULL) + { + int saved_errno = errno; + free (result); + errno = saved_errno; + } + return NULL; + } + + /* Add the terminating NUL byte. */ + result[length] = '\0'; + + return result; +} + +#endif + +int +mem_iconveh (const char *src, size_t srclen, + const char *from_codeset, const char *to_codeset, + enum iconv_ilseq_handler handler, + size_t *offsets, + char **resultp, size_t *lengthp) +{ + if (srclen == 0) + { + /* Nothing to convert. */ + *lengthp = 0; + return 0; + } + else if (offsets == NULL && c_strcasecmp (from_codeset, to_codeset) == 0) + { + char *result; + + if (*resultp != NULL && *lengthp >= srclen) + result = *resultp; + else + { + result = (char *) malloc (srclen); + if (result == NULL) + { + errno = ENOMEM; + return -1; + } + } + memcpy (result, src, srclen); + *resultp = result; + *lengthp = srclen; + return 0; + } + else + { +#if HAVE_ICONV + iconveh_t cd; + char *result; + size_t length; + int retval; + + if (iconveh_open (to_codeset, from_codeset, &cd) < 0) + return -1; + + result = *resultp; + length = *lengthp; + retval = mem_cd_iconveh (src, srclen, &cd, handler, offsets, + &result, &length); + + if (retval < 0) + { + /* Close cd, but preserve the errno from str_cd_iconv. */ + int saved_errno = errno; + iconveh_close (&cd); + errno = saved_errno; + } + else + { + if (iconveh_close (&cd) < 0) + { + /* Return -1, but free the allocated memory, and while doing + that, preserve the errno from iconveh_close. */ + int saved_errno = errno; + if (result != *resultp && result != NULL) + free (result); + errno = saved_errno; + return -1; + } + *resultp = result; + *lengthp = length; + } + return retval; +#else + /* This is a different error code than if iconv_open existed but didn't + support from_codeset and to_codeset, so that the caller can emit + an error message such as + "iconv() is not supported. Installing GNU libiconv and + then reinstalling this package would fix this." */ + errno = ENOSYS; + return -1; +#endif + } +} + +char * +str_iconveh (const char *src, + const char *from_codeset, const char *to_codeset, + enum iconv_ilseq_handler handler) +{ + if (*src == '\0' || c_strcasecmp (from_codeset, to_codeset) == 0) + { + char *result = strdup (src); + + if (result == NULL) + errno = ENOMEM; + return result; + } + else + { +#if HAVE_ICONV + iconveh_t cd; + char *result; + + if (iconveh_open (to_codeset, from_codeset, &cd) < 0) + return NULL; + + result = str_cd_iconveh (src, &cd, handler); + + if (result == NULL) + { + /* Close cd, but preserve the errno from str_cd_iconv. */ + int saved_errno = errno; + iconveh_close (&cd); + errno = saved_errno; + } + else + { + if (iconveh_close (&cd) < 0) + { + /* Return NULL, but free the allocated memory, and while doing + that, preserve the errno from iconveh_close. */ + int saved_errno = errno; + free (result); + errno = saved_errno; + return NULL; + } + } + return result; +#else + /* This is a different error code than if iconv_open existed but didn't + support from_codeset and to_codeset, so that the caller can emit + an error message such as + "iconv() is not supported. Installing GNU libiconv and + then reinstalling this package would fix this." */ + errno = ENOSYS; + return NULL; +#endif + } +} diff --git a/gettext-tools/gnulib-lib/striconveh.h b/gettext-tools/gnulib-lib/striconveh.h new file mode 100644 index 0000000..4f2416e --- /dev/null +++ b/gettext-tools/gnulib-lib/striconveh.h @@ -0,0 +1,140 @@ +/* Character set conversion with error handling. + Copyright (C) 2001-2007, 2009-2014 Free Software Foundation, Inc. + Written by Bruno Haible and Simon Josefsson. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _STRICONVEH_H +#define _STRICONVEH_H + +#include +#if HAVE_ICONV +#include +#endif + +#include "iconveh.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +#if HAVE_ICONV + +/* A conversion descriptor for use by the iconveh functions. */ +typedef struct + { + /* Conversion descriptor from FROM_CODESET to TO_CODESET, or (iconv_t)(-1) + if the system does not support a direct conversion from FROM_CODESET to + TO_CODESET. */ + iconv_t cd; + /* Conversion descriptor from FROM_CODESET to UTF-8 (or (iconv_t)(-1) if + FROM_CODESET is UTF-8). */ + iconv_t cd1; + /* Conversion descriptor from UTF-8 to TO_CODESET (or (iconv_t)(-1) if + TO_CODESET is UTF-8). */ + iconv_t cd2; + } + iconveh_t; + +/* Open a conversion descriptor for use by the iconveh functions. + If successful, fills *CDP and returns 0. Upon failure, return -1 with errno + set. */ +extern int + iconveh_open (const char *to_codeset, const char *from_codeset, + iconveh_t *cdp); + +/* Close a conversion descriptor created by iconveh_open(). + Return value: 0 if successful, otherwise -1 and errno set. */ +extern int + iconveh_close (const iconveh_t *cd); + +/* Convert an entire string from one encoding to another, using iconv. + The original string is at [SRC,...,SRC+SRCLEN-1]. + CD points to the conversion descriptor from FROMCODE to TOCODE, created by + the function iconveh_open(). + If OFFSETS is not NULL, it should point to an array of SRCLEN integers; this + array is filled with offsets into the result, i.e. the character starting + at SRC[i] corresponds to the character starting at (*RESULTP)[OFFSETS[i]], + and other offsets are set to (size_t)(-1). + *RESULTP and *LENGTH should initially be a scratch buffer and its size, + or *RESULTP can initially be NULL. + May erase the contents of the memory at *RESULTP. + Return value: 0 if successful, otherwise -1 and errno set. + If successful: The resulting string is stored in *RESULTP and its length + in *LENGTHP. *RESULTP is set to a freshly allocated memory block, or is + unchanged if no dynamic memory allocation was necessary. */ +extern int + mem_cd_iconveh (const char *src, size_t srclen, + const iconveh_t *cd, + enum iconv_ilseq_handler handler, + size_t *offsets, + char **resultp, size_t *lengthp); + +/* Convert an entire string from one encoding to another, using iconv. + The original string is the NUL-terminated string starting at SRC. + CD points to the conversion descriptor from FROMCODE to TOCODE, created by + the function iconveh_open(). + Both the "from" and the "to" encoding must use a single NUL byte at the end + of the string (i.e. not UCS-2, UCS-4, UTF-16, UTF-32). + Allocate a malloced memory block for the result. + Return value: the freshly allocated resulting NUL-terminated string if + successful, otherwise NULL and errno set. */ +extern char * + str_cd_iconveh (const char *src, + const iconveh_t *cd, + enum iconv_ilseq_handler handler); + +#endif + +/* Convert an entire string from one encoding to another, using iconv. + The original string is at [SRC,...,SRC+SRCLEN-1]. + If OFFSETS is not NULL, it should point to an array of SRCLEN integers; this + array is filled with offsets into the result, i.e. the character starting + at SRC[i] corresponds to the character starting at (*RESULTP)[OFFSETS[i]], + and other offsets are set to (size_t)(-1). + *RESULTP and *LENGTH should initially be a scratch buffer and its size, + or *RESULTP can initially be NULL. + May erase the contents of the memory at *RESULTP. + Return value: 0 if successful, otherwise -1 and errno set. + If successful: The resulting string is stored in *RESULTP and its length + in *LENGTHP. *RESULTP is set to a freshly allocated memory block, or is + unchanged if no dynamic memory allocation was necessary. */ +extern int + mem_iconveh (const char *src, size_t srclen, + const char *from_codeset, const char *to_codeset, + enum iconv_ilseq_handler handler, + size_t *offsets, + char **resultp, size_t *lengthp); + +/* Convert an entire string from one encoding to another, using iconv. + The original string is the NUL-terminated string starting at SRC. + Both the "from" and the "to" encoding must use a single NUL byte at the + end of the string (i.e. not UCS-2, UCS-4, UTF-16, UTF-32). + Allocate a malloced memory block for the result. + Return value: the freshly allocated resulting NUL-terminated string if + successful, otherwise NULL and errno set. */ +extern char * + str_iconveh (const char *src, + const char *from_codeset, const char *to_codeset, + enum iconv_ilseq_handler handler); + + +#ifdef __cplusplus +} +#endif + + +#endif /* _STRICONVEH_H */ diff --git a/gettext-tools/gnulib-lib/striconveha.c b/gettext-tools/gnulib-lib/striconveha.c new file mode 100644 index 0000000..f27d84e --- /dev/null +++ b/gettext-tools/gnulib-lib/striconveha.c @@ -0,0 +1,352 @@ +/* Character set conversion with error handling and autodetection. + Copyright (C) 2002, 2005, 2007, 2009-2014 Free Software Foundation, Inc. + Written by Bruno Haible. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include "striconveha.h" + +#include +#include +#include + +#include "malloca.h" +#include "c-strcase.h" +#include "striconveh.h" + +#define SIZEOF(a) (sizeof(a)/sizeof(a[0])) + + +/* Autodetection list. */ + +struct autodetect_alias +{ + struct autodetect_alias *next; + const char *name; + const char * const *encodings_to_try; +}; + +static const char * const autodetect_utf8_try[] = +{ + /* Try UTF-8 first. There are very few ISO-8859-1 inputs that would + be valid UTF-8, but many UTF-8 inputs are valid ISO-8859-1. */ + "UTF-8", "ISO-8859-1", + NULL +}; +static const char * const autodetect_jp_try[] = +{ + /* Try 7-bit encoding first. If the input contains bytes >= 0x80, + it will fail. + Try EUC-JP next. Short SHIFT_JIS inputs may come out wrong. This + is unavoidable. People will condemn SHIFT_JIS. + If we tried SHIFT_JIS first, then some short EUC-JP inputs would + come out wrong, and people would condemn EUC-JP and Unix, which + would not be good. + Finally try SHIFT_JIS. */ + "ISO-2022-JP-2", "EUC-JP", "SHIFT_JIS", + NULL +}; +static const char * const autodetect_kr_try[] = +{ + /* Try 7-bit encoding first. If the input contains bytes >= 0x80, + it will fail. + Finally try EUC-KR. */ + "ISO-2022-KR", "EUC-KR", + NULL +}; + +static struct autodetect_alias autodetect_predefined[] = +{ + { &autodetect_predefined[1], "autodetect_utf8", autodetect_utf8_try }, + { &autodetect_predefined[2], "autodetect_jp", autodetect_jp_try }, + { NULL, "autodetect_kr", autodetect_kr_try } +}; + +static struct autodetect_alias *autodetect_list = &autodetect_predefined[0]; +static struct autodetect_alias **autodetect_list_end = + &autodetect_predefined[SIZEOF(autodetect_predefined)-1].next; + +int +uniconv_register_autodetect (const char *name, + const char * const *try_in_order) +{ + size_t namelen; + size_t listlen; + size_t memneed; + size_t i; + char *memory; + struct autodetect_alias *new_alias; + char *new_name; + const char **new_try_in_order; + + /* The TRY_IN_ORDER list must not be empty. */ + if (try_in_order[0] == NULL) + { + errno = EINVAL; + return -1; + } + + /* We must deep-copy NAME and TRY_IN_ORDER, because they may be allocated + with dynamic extent. */ + namelen = strlen (name) + 1; + memneed = sizeof (struct autodetect_alias) + namelen + sizeof (char *); + for (i = 0; try_in_order[i] != NULL; i++) + memneed += sizeof (char *) + strlen (try_in_order[i]) + 1; + listlen = i; + + memory = (char *) malloc (memneed); + if (memory != NULL) + { + new_alias = (struct autodetect_alias *) memory; + memory += sizeof (struct autodetect_alias); + + new_try_in_order = (const char **) memory; + memory += (listlen + 1) * sizeof (char *); + + new_name = (char *) memory; + memcpy (new_name, name, namelen); + memory += namelen; + + for (i = 0; i < listlen; i++) + { + size_t len = strlen (try_in_order[i]) + 1; + memcpy (memory, try_in_order[i], len); + new_try_in_order[i] = (const char *) memory; + memory += len; + } + new_try_in_order[i] = NULL; + + /* Now insert the new alias. */ + new_alias->name = new_name; + new_alias->encodings_to_try = new_try_in_order; + new_alias->next = NULL; + /* FIXME: Not multithread-safe. */ + *autodetect_list_end = new_alias; + autodetect_list_end = &new_alias->next; + return 0; + } + else + { + errno = ENOMEM; + return -1; + } +} + +/* Like mem_iconveha, except no handling of transliteration. */ +static int +mem_iconveha_notranslit (const char *src, size_t srclen, + const char *from_codeset, const char *to_codeset, + enum iconv_ilseq_handler handler, + size_t *offsets, + char **resultp, size_t *lengthp) +{ + int retval = mem_iconveh (src, srclen, from_codeset, to_codeset, handler, + offsets, resultp, lengthp); + if (retval >= 0 || errno != EINVAL) + return retval; + else + { + struct autodetect_alias *alias; + + /* Unsupported from_codeset or to_codeset. Check whether the caller + requested autodetection. */ + for (alias = autodetect_list; alias != NULL; alias = alias->next) + if (strcmp (from_codeset, alias->name) == 0) + { + const char * const *encodings; + + if (handler != iconveh_error) + { + /* First try all encodings without any forgiving. */ + encodings = alias->encodings_to_try; + do + { + retval = mem_iconveha_notranslit (src, srclen, + *encodings, to_codeset, + iconveh_error, offsets, + resultp, lengthp); + if (!(retval < 0 && errno == EILSEQ)) + return retval; + encodings++; + } + while (*encodings != NULL); + } + + encodings = alias->encodings_to_try; + do + { + retval = mem_iconveha_notranslit (src, srclen, + *encodings, to_codeset, + handler, offsets, + resultp, lengthp); + if (!(retval < 0 && errno == EILSEQ)) + return retval; + encodings++; + } + while (*encodings != NULL); + + /* Return the last call's result. */ + return -1; + } + + /* It wasn't an autodetection name. */ + errno = EINVAL; + return -1; + } +} + +int +mem_iconveha (const char *src, size_t srclen, + const char *from_codeset, const char *to_codeset, + bool transliterate, + enum iconv_ilseq_handler handler, + size_t *offsets, + char **resultp, size_t *lengthp) +{ + if (srclen == 0) + { + /* Nothing to convert. */ + *lengthp = 0; + return 0; + } + + /* When using GNU libc >= 2.2 or GNU libiconv >= 1.5, + we want to use transliteration. */ +#if (((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2) \ + && !defined __UCLIBC__) \ + || _LIBICONV_VERSION >= 0x0105 + if (transliterate) + { + int retval; + size_t len = strlen (to_codeset); + char *to_codeset_suffixed = (char *) malloca (len + 10 + 1); + memcpy (to_codeset_suffixed, to_codeset, len); + memcpy (to_codeset_suffixed + len, "//TRANSLIT", 10 + 1); + + retval = mem_iconveha_notranslit (src, srclen, + from_codeset, to_codeset_suffixed, + handler, offsets, resultp, lengthp); + + freea (to_codeset_suffixed); + + return retval; + } + else +#endif + return mem_iconveha_notranslit (src, srclen, + from_codeset, to_codeset, + handler, offsets, resultp, lengthp); +} + +/* Like str_iconveha, except no handling of transliteration. */ +static char * +str_iconveha_notranslit (const char *src, + const char *from_codeset, const char *to_codeset, + enum iconv_ilseq_handler handler) +{ + char *result = str_iconveh (src, from_codeset, to_codeset, handler); + + if (result != NULL || errno != EINVAL) + return result; + else + { + struct autodetect_alias *alias; + + /* Unsupported from_codeset or to_codeset. Check whether the caller + requested autodetection. */ + for (alias = autodetect_list; alias != NULL; alias = alias->next) + if (strcmp (from_codeset, alias->name) == 0) + { + const char * const *encodings; + + if (handler != iconveh_error) + { + /* First try all encodings without any forgiving. */ + encodings = alias->encodings_to_try; + do + { + result = str_iconveha_notranslit (src, + *encodings, to_codeset, + iconveh_error); + if (!(result == NULL && errno == EILSEQ)) + return result; + encodings++; + } + while (*encodings != NULL); + } + + encodings = alias->encodings_to_try; + do + { + result = str_iconveha_notranslit (src, + *encodings, to_codeset, + handler); + if (!(result == NULL && errno == EILSEQ)) + return result; + encodings++; + } + while (*encodings != NULL); + + /* Return the last call's result. */ + return NULL; + } + + /* It wasn't an autodetection name. */ + errno = EINVAL; + return NULL; + } +} + +char * +str_iconveha (const char *src, + const char *from_codeset, const char *to_codeset, + bool transliterate, + enum iconv_ilseq_handler handler) +{ + if (*src == '\0' || c_strcasecmp (from_codeset, to_codeset) == 0) + { + char *result = strdup (src); + + if (result == NULL) + errno = ENOMEM; + return result; + } + + /* When using GNU libc >= 2.2 or GNU libiconv >= 1.5, + we want to use transliteration. */ +#if (((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2) \ + && !defined __UCLIBC__) \ + || _LIBICONV_VERSION >= 0x0105 + if (transliterate) + { + char *result; + size_t len = strlen (to_codeset); + char *to_codeset_suffixed = (char *) malloca (len + 10 + 1); + memcpy (to_codeset_suffixed, to_codeset, len); + memcpy (to_codeset_suffixed + len, "//TRANSLIT", 10 + 1); + + result = str_iconveha_notranslit (src, from_codeset, to_codeset_suffixed, + handler); + + freea (to_codeset_suffixed); + + return result; + } + else +#endif + return str_iconveha_notranslit (src, from_codeset, to_codeset, handler); +} diff --git a/gettext-tools/gnulib-lib/striconveha.h b/gettext-tools/gnulib-lib/striconveha.h new file mode 100644 index 0000000..e739585 --- /dev/null +++ b/gettext-tools/gnulib-lib/striconveha.h @@ -0,0 +1,95 @@ +/* Character set conversion with error handling and autodetection. + Copyright (C) 2002, 2005, 2007-2014 Free Software Foundation, Inc. + Written by Bruno Haible. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _STRICONVEHA_H +#define _STRICONVEHA_H + +#include +#include + +#include "iconveh.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Convert an entire string from one encoding to another, using iconv. + The original string is at [SRC,...,SRC+SRCLEN-1]. + The "from" encoding can also be a name defined for autodetection. + If TRANSLITERATE is true, transliteration will attempted to avoid conversion + errors, for iconv implementations that support this. Usually you'll choose + TRANSLITERATE = true if HANDLER != iconveh_error. + If OFFSETS is not NULL, it should point to an array of SRCLEN integers; this + array is filled with offsets into the result, i.e. the character starting + at SRC[i] corresponds to the character starting at (*RESULTP)[OFFSETS[i]], + and other offsets are set to (size_t)(-1). + *RESULTP and *LENGTH should initially be a scratch buffer and its size, + or *RESULTP can initially be NULL. + May erase the contents of the memory at *RESULTP. + Return value: 0 if successful, otherwise -1 and errno set. + If successful: The resulting string is stored in *RESULTP and its length + in *LENGTHP. *RESULTP is set to a freshly allocated memory block, or is + unchanged if no dynamic memory allocation was necessary. */ +extern int + mem_iconveha (const char *src, size_t srclen, + const char *from_codeset, const char *to_codeset, + bool transliterate, + enum iconv_ilseq_handler handler, + size_t *offsets, + char **resultp, size_t *lengthp); + +/* Convert an entire string from one encoding to another, using iconv. + The original string is the NUL-terminated string starting at SRC. + Both the "from" and the "to" encoding must use a single NUL byte at the + end of the string (i.e. not UCS-2, UCS-4, UTF-16, UTF-32). + The "from" encoding can also be a name defined for autodetection. + If TRANSLITERATE is true, transliteration will attempted to avoid conversion + errors, for iconv implementations that support this. Usually you'll choose + TRANSLITERATE = true if HANDLER != iconveh_error. + Allocate a malloced memory block for the result. + Return value: the freshly allocated resulting NUL-terminated string if + successful, otherwise NULL and errno set. */ +extern char * + str_iconveha (const char *src, + const char *from_codeset, const char *to_codeset, + bool transliterate, + enum iconv_ilseq_handler handler); + + +/* In the above, FROM_CODESET can also be one of the following values: + "autodetect_utf8" supports ISO-8859-1 and UTF-8 + "autodetect_jp" supports EUC-JP, ISO-2022-JP-2 and SHIFT_JIS + "autodetect_kr" supports EUC-KR and ISO-2022-KR + More names can be defined for autodetection. */ + +/* Registers an encoding name for autodetection. + TRY_IN_ORDER is a NULL terminated list of encodings to be tried. + Returns 0 upon success, or -1 (with errno set) in case of error. + Particular errno values: ENOMEM. */ +extern int + uniconv_register_autodetect (const char *name, + const char * const *try_in_order); + + +#ifdef __cplusplus +} +#endif + + +#endif /* _STRICONVEHA_H */ diff --git a/gettext-tools/gnulib-lib/string.in.h b/gettext-tools/gnulib-lib/string.in.h new file mode 100644 index 0000000..9062142 --- /dev/null +++ b/gettext-tools/gnulib-lib/string.in.h @@ -0,0 +1,1029 @@ +/* A GNU-like . + + Copyright (C) 1995-1996, 2001-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . */ + +#ifndef _@GUARD_PREFIX@_STRING_H + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +/* The include_next requires a split double-inclusion guard. */ +#@INCLUDE_NEXT@ @NEXT_STRING_H@ + +#ifndef _@GUARD_PREFIX@_STRING_H +#define _@GUARD_PREFIX@_STRING_H + +/* NetBSD 5.0 mis-defines NULL. */ +#include + +/* MirBSD defines mbslen as a macro. */ +#if @GNULIB_MBSLEN@ && defined __MirBSD__ +# include +#endif + +/* The __attribute__ feature is available in gcc versions 2.5 and later. + The attribute __pure__ was added in gcc 2.96. */ +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96) +# define _GL_ATTRIBUTE_PURE __attribute__ ((__pure__)) +#else +# define _GL_ATTRIBUTE_PURE /* empty */ +#endif + +/* NetBSD 5.0 declares strsignal in , not in . */ +/* But in any case avoid namespace pollution on glibc systems. */ +#if (@GNULIB_STRSIGNAL@ || defined GNULIB_POSIXCHECK) && defined __NetBSD__ \ + && ! defined __GLIBC__ +# include +#endif + +/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ + +/* The definition of _GL_ARG_NONNULL is copied here. */ + +/* The definition of _GL_WARN_ON_USE is copied here. */ + + +/* Find the index of the least-significant set bit. */ +#if @GNULIB_FFSL@ +# if !@HAVE_FFSL@ +_GL_FUNCDECL_SYS (ffsl, int, (long int i)); +# endif +_GL_CXXALIAS_SYS (ffsl, int, (long int i)); +_GL_CXXALIASWARN (ffsl); +#elif defined GNULIB_POSIXCHECK +# undef ffsl +# if HAVE_RAW_DECL_FFSL +_GL_WARN_ON_USE (ffsl, "ffsl is not portable - use the ffsl module"); +# endif +#endif + + +/* Find the index of the least-significant set bit. */ +#if @GNULIB_FFSLL@ +# if !@HAVE_FFSLL@ +_GL_FUNCDECL_SYS (ffsll, int, (long long int i)); +# endif +_GL_CXXALIAS_SYS (ffsll, int, (long long int i)); +_GL_CXXALIASWARN (ffsll); +#elif defined GNULIB_POSIXCHECK +# undef ffsll +# if HAVE_RAW_DECL_FFSLL +_GL_WARN_ON_USE (ffsll, "ffsll is not portable - use the ffsll module"); +# endif +#endif + + +/* Return the first instance of C within N bytes of S, or NULL. */ +#if @GNULIB_MEMCHR@ +# if @REPLACE_MEMCHR@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define memchr rpl_memchr +# endif +_GL_FUNCDECL_RPL (memchr, void *, (void const *__s, int __c, size_t __n) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (memchr, void *, (void const *__s, int __c, size_t __n)); +# else +# if ! @HAVE_MEMCHR@ +_GL_FUNCDECL_SYS (memchr, void *, (void const *__s, int __c, size_t __n) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1))); +# endif + /* On some systems, this function is defined as an overloaded function: + extern "C" { const void * std::memchr (const void *, int, size_t); } + extern "C++" { void * std::memchr (void *, int, size_t); } */ +_GL_CXXALIAS_SYS_CAST2 (memchr, + void *, (void const *__s, int __c, size_t __n), + void const *, (void const *__s, int __c, size_t __n)); +# endif +# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \ + && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) +_GL_CXXALIASWARN1 (memchr, void *, (void *__s, int __c, size_t __n)); +_GL_CXXALIASWARN1 (memchr, void const *, + (void const *__s, int __c, size_t __n)); +# else +_GL_CXXALIASWARN (memchr); +# endif +#elif defined GNULIB_POSIXCHECK +# undef memchr +/* Assume memchr is always declared. */ +_GL_WARN_ON_USE (memchr, "memchr has platform-specific bugs - " + "use gnulib module memchr for portability" ); +#endif + +/* Return the first occurrence of NEEDLE in HAYSTACK. */ +#if @GNULIB_MEMMEM@ +# if @REPLACE_MEMMEM@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define memmem rpl_memmem +# endif +_GL_FUNCDECL_RPL (memmem, void *, + (void const *__haystack, size_t __haystack_len, + void const *__needle, size_t __needle_len) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1, 3))); +_GL_CXXALIAS_RPL (memmem, void *, + (void const *__haystack, size_t __haystack_len, + void const *__needle, size_t __needle_len)); +# else +# if ! @HAVE_DECL_MEMMEM@ +_GL_FUNCDECL_SYS (memmem, void *, + (void const *__haystack, size_t __haystack_len, + void const *__needle, size_t __needle_len) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1, 3))); +# endif +_GL_CXXALIAS_SYS (memmem, void *, + (void const *__haystack, size_t __haystack_len, + void const *__needle, size_t __needle_len)); +# endif +_GL_CXXALIASWARN (memmem); +#elif defined GNULIB_POSIXCHECK +# undef memmem +# if HAVE_RAW_DECL_MEMMEM +_GL_WARN_ON_USE (memmem, "memmem is unportable and often quadratic - " + "use gnulib module memmem-simple for portability, " + "and module memmem for speed" ); +# endif +#endif + +/* Copy N bytes of SRC to DEST, return pointer to bytes after the + last written byte. */ +#if @GNULIB_MEMPCPY@ +# if ! @HAVE_MEMPCPY@ +_GL_FUNCDECL_SYS (mempcpy, void *, + (void *restrict __dest, void const *restrict __src, + size_t __n) + _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (mempcpy, void *, + (void *restrict __dest, void const *restrict __src, + size_t __n)); +_GL_CXXALIASWARN (mempcpy); +#elif defined GNULIB_POSIXCHECK +# undef mempcpy +# if HAVE_RAW_DECL_MEMPCPY +_GL_WARN_ON_USE (mempcpy, "mempcpy is unportable - " + "use gnulib module mempcpy for portability"); +# endif +#endif + +/* Search backwards through a block for a byte (specified as an int). */ +#if @GNULIB_MEMRCHR@ +# if ! @HAVE_DECL_MEMRCHR@ +_GL_FUNCDECL_SYS (memrchr, void *, (void const *, int, size_t) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1))); +# endif + /* On some systems, this function is defined as an overloaded function: + extern "C++" { const void * std::memrchr (const void *, int, size_t); } + extern "C++" { void * std::memrchr (void *, int, size_t); } */ +_GL_CXXALIAS_SYS_CAST2 (memrchr, + void *, (void const *, int, size_t), + void const *, (void const *, int, size_t)); +# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \ + && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) +_GL_CXXALIASWARN1 (memrchr, void *, (void *, int, size_t)); +_GL_CXXALIASWARN1 (memrchr, void const *, (void const *, int, size_t)); +# else +_GL_CXXALIASWARN (memrchr); +# endif +#elif defined GNULIB_POSIXCHECK +# undef memrchr +# if HAVE_RAW_DECL_MEMRCHR +_GL_WARN_ON_USE (memrchr, "memrchr is unportable - " + "use gnulib module memrchr for portability"); +# endif +#endif + +/* Find the first occurrence of C in S. More efficient than + memchr(S,C,N), at the expense of undefined behavior if C does not + occur within N bytes. */ +#if @GNULIB_RAWMEMCHR@ +# if ! @HAVE_RAWMEMCHR@ +_GL_FUNCDECL_SYS (rawmemchr, void *, (void const *__s, int __c_in) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1))); +# endif + /* On some systems, this function is defined as an overloaded function: + extern "C++" { const void * std::rawmemchr (const void *, int); } + extern "C++" { void * std::rawmemchr (void *, int); } */ +_GL_CXXALIAS_SYS_CAST2 (rawmemchr, + void *, (void const *__s, int __c_in), + void const *, (void const *__s, int __c_in)); +# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \ + && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) +_GL_CXXALIASWARN1 (rawmemchr, void *, (void *__s, int __c_in)); +_GL_CXXALIASWARN1 (rawmemchr, void const *, (void const *__s, int __c_in)); +# else +_GL_CXXALIASWARN (rawmemchr); +# endif +#elif defined GNULIB_POSIXCHECK +# undef rawmemchr +# if HAVE_RAW_DECL_RAWMEMCHR +_GL_WARN_ON_USE (rawmemchr, "rawmemchr is unportable - " + "use gnulib module rawmemchr for portability"); +# endif +#endif + +/* Copy SRC to DST, returning the address of the terminating '\0' in DST. */ +#if @GNULIB_STPCPY@ +# if ! @HAVE_STPCPY@ +_GL_FUNCDECL_SYS (stpcpy, char *, + (char *restrict __dst, char const *restrict __src) + _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (stpcpy, char *, + (char *restrict __dst, char const *restrict __src)); +_GL_CXXALIASWARN (stpcpy); +#elif defined GNULIB_POSIXCHECK +# undef stpcpy +# if HAVE_RAW_DECL_STPCPY +_GL_WARN_ON_USE (stpcpy, "stpcpy is unportable - " + "use gnulib module stpcpy for portability"); +# endif +#endif + +/* Copy no more than N bytes of SRC to DST, returning a pointer past the + last non-NUL byte written into DST. */ +#if @GNULIB_STPNCPY@ +# if @REPLACE_STPNCPY@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef stpncpy +# define stpncpy rpl_stpncpy +# endif +_GL_FUNCDECL_RPL (stpncpy, char *, + (char *restrict __dst, char const *restrict __src, + size_t __n) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (stpncpy, char *, + (char *restrict __dst, char const *restrict __src, + size_t __n)); +# else +# if ! @HAVE_STPNCPY@ +_GL_FUNCDECL_SYS (stpncpy, char *, + (char *restrict __dst, char const *restrict __src, + size_t __n) + _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (stpncpy, char *, + (char *restrict __dst, char const *restrict __src, + size_t __n)); +# endif +_GL_CXXALIASWARN (stpncpy); +#elif defined GNULIB_POSIXCHECK +# undef stpncpy +# if HAVE_RAW_DECL_STPNCPY +_GL_WARN_ON_USE (stpncpy, "stpncpy is unportable - " + "use gnulib module stpncpy for portability"); +# endif +#endif + +#if defined GNULIB_POSIXCHECK +/* strchr() does not work with multibyte strings if the locale encoding is + GB18030 and the character to be searched is a digit. */ +# undef strchr +/* Assume strchr is always declared. */ +_GL_WARN_ON_USE (strchr, "strchr cannot work correctly on character strings " + "in some multibyte locales - " + "use mbschr if you care about internationalization"); +#endif + +/* Find the first occurrence of C in S or the final NUL byte. */ +#if @GNULIB_STRCHRNUL@ +# if @REPLACE_STRCHRNUL@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define strchrnul rpl_strchrnul +# endif +_GL_FUNCDECL_RPL (strchrnul, char *, (const char *__s, int __c_in) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (strchrnul, char *, + (const char *str, int ch)); +# else +# if ! @HAVE_STRCHRNUL@ +_GL_FUNCDECL_SYS (strchrnul, char *, (char const *__s, int __c_in) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1))); +# endif + /* On some systems, this function is defined as an overloaded function: + extern "C++" { const char * std::strchrnul (const char *, int); } + extern "C++" { char * std::strchrnul (char *, int); } */ +_GL_CXXALIAS_SYS_CAST2 (strchrnul, + char *, (char const *__s, int __c_in), + char const *, (char const *__s, int __c_in)); +# endif +# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \ + && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) +_GL_CXXALIASWARN1 (strchrnul, char *, (char *__s, int __c_in)); +_GL_CXXALIASWARN1 (strchrnul, char const *, (char const *__s, int __c_in)); +# else +_GL_CXXALIASWARN (strchrnul); +# endif +#elif defined GNULIB_POSIXCHECK +# undef strchrnul +# if HAVE_RAW_DECL_STRCHRNUL +_GL_WARN_ON_USE (strchrnul, "strchrnul is unportable - " + "use gnulib module strchrnul for portability"); +# endif +#endif + +/* Duplicate S, returning an identical malloc'd string. */ +#if @GNULIB_STRDUP@ +# if @REPLACE_STRDUP@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef strdup +# define strdup rpl_strdup +# endif +_GL_FUNCDECL_RPL (strdup, char *, (char const *__s) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (strdup, char *, (char const *__s)); +# else +# if defined __cplusplus && defined GNULIB_NAMESPACE && defined strdup + /* strdup exists as a function and as a macro. Get rid of the macro. */ +# undef strdup +# endif +# if !(@HAVE_DECL_STRDUP@ || defined strdup) +_GL_FUNCDECL_SYS (strdup, char *, (char const *__s) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (strdup, char *, (char const *__s)); +# endif +_GL_CXXALIASWARN (strdup); +#elif defined GNULIB_POSIXCHECK +# undef strdup +# if HAVE_RAW_DECL_STRDUP +_GL_WARN_ON_USE (strdup, "strdup is unportable - " + "use gnulib module strdup for portability"); +# endif +#endif + +/* Append no more than N characters from SRC onto DEST. */ +#if @GNULIB_STRNCAT@ +# if @REPLACE_STRNCAT@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef strncat +# define strncat rpl_strncat +# endif +_GL_FUNCDECL_RPL (strncat, char *, (char *dest, const char *src, size_t n) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (strncat, char *, (char *dest, const char *src, size_t n)); +# else +_GL_CXXALIAS_SYS (strncat, char *, (char *dest, const char *src, size_t n)); +# endif +_GL_CXXALIASWARN (strncat); +#elif defined GNULIB_POSIXCHECK +# undef strncat +# if HAVE_RAW_DECL_STRNCAT +_GL_WARN_ON_USE (strncat, "strncat is unportable - " + "use gnulib module strncat for portability"); +# endif +#endif + +/* Return a newly allocated copy of at most N bytes of STRING. */ +#if @GNULIB_STRNDUP@ +# if @REPLACE_STRNDUP@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef strndup +# define strndup rpl_strndup +# endif +_GL_FUNCDECL_RPL (strndup, char *, (char const *__string, size_t __n) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (strndup, char *, (char const *__string, size_t __n)); +# else +# if ! @HAVE_DECL_STRNDUP@ +_GL_FUNCDECL_SYS (strndup, char *, (char const *__string, size_t __n) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (strndup, char *, (char const *__string, size_t __n)); +# endif +_GL_CXXALIASWARN (strndup); +#elif defined GNULIB_POSIXCHECK +# undef strndup +# if HAVE_RAW_DECL_STRNDUP +_GL_WARN_ON_USE (strndup, "strndup is unportable - " + "use gnulib module strndup for portability"); +# endif +#endif + +/* Find the length (number of bytes) of STRING, but scan at most + MAXLEN bytes. If no '\0' terminator is found in that many bytes, + return MAXLEN. */ +#if @GNULIB_STRNLEN@ +# if @REPLACE_STRNLEN@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef strnlen +# define strnlen rpl_strnlen +# endif +_GL_FUNCDECL_RPL (strnlen, size_t, (char const *__string, size_t __maxlen) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (strnlen, size_t, (char const *__string, size_t __maxlen)); +# else +# if ! @HAVE_DECL_STRNLEN@ +_GL_FUNCDECL_SYS (strnlen, size_t, (char const *__string, size_t __maxlen) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (strnlen, size_t, (char const *__string, size_t __maxlen)); +# endif +_GL_CXXALIASWARN (strnlen); +#elif defined GNULIB_POSIXCHECK +# undef strnlen +# if HAVE_RAW_DECL_STRNLEN +_GL_WARN_ON_USE (strnlen, "strnlen is unportable - " + "use gnulib module strnlen for portability"); +# endif +#endif + +#if defined GNULIB_POSIXCHECK +/* strcspn() assumes the second argument is a list of single-byte characters. + Even in this simple case, it does not work with multibyte strings if the + locale encoding is GB18030 and one of the characters to be searched is a + digit. */ +# undef strcspn +/* Assume strcspn is always declared. */ +_GL_WARN_ON_USE (strcspn, "strcspn cannot work correctly on character strings " + "in multibyte locales - " + "use mbscspn if you care about internationalization"); +#endif + +/* Find the first occurrence in S of any character in ACCEPT. */ +#if @GNULIB_STRPBRK@ +# if ! @HAVE_STRPBRK@ +_GL_FUNCDECL_SYS (strpbrk, char *, (char const *__s, char const *__accept) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1, 2))); +# endif + /* On some systems, this function is defined as an overloaded function: + extern "C" { const char * strpbrk (const char *, const char *); } + extern "C++" { char * strpbrk (char *, const char *); } */ +_GL_CXXALIAS_SYS_CAST2 (strpbrk, + char *, (char const *__s, char const *__accept), + const char *, (char const *__s, char const *__accept)); +# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \ + && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) +_GL_CXXALIASWARN1 (strpbrk, char *, (char *__s, char const *__accept)); +_GL_CXXALIASWARN1 (strpbrk, char const *, + (char const *__s, char const *__accept)); +# else +_GL_CXXALIASWARN (strpbrk); +# endif +# if defined GNULIB_POSIXCHECK +/* strpbrk() assumes the second argument is a list of single-byte characters. + Even in this simple case, it does not work with multibyte strings if the + locale encoding is GB18030 and one of the characters to be searched is a + digit. */ +# undef strpbrk +_GL_WARN_ON_USE (strpbrk, "strpbrk cannot work correctly on character strings " + "in multibyte locales - " + "use mbspbrk if you care about internationalization"); +# endif +#elif defined GNULIB_POSIXCHECK +# undef strpbrk +# if HAVE_RAW_DECL_STRPBRK +_GL_WARN_ON_USE (strpbrk, "strpbrk is unportable - " + "use gnulib module strpbrk for portability"); +# endif +#endif + +#if defined GNULIB_POSIXCHECK +/* strspn() assumes the second argument is a list of single-byte characters. + Even in this simple case, it cannot work with multibyte strings. */ +# undef strspn +/* Assume strspn is always declared. */ +_GL_WARN_ON_USE (strspn, "strspn cannot work correctly on character strings " + "in multibyte locales - " + "use mbsspn if you care about internationalization"); +#endif + +#if defined GNULIB_POSIXCHECK +/* strrchr() does not work with multibyte strings if the locale encoding is + GB18030 and the character to be searched is a digit. */ +# undef strrchr +/* Assume strrchr is always declared. */ +_GL_WARN_ON_USE (strrchr, "strrchr cannot work correctly on character strings " + "in some multibyte locales - " + "use mbsrchr if you care about internationalization"); +#endif + +/* Search the next delimiter (char listed in DELIM) starting at *STRINGP. + If one is found, overwrite it with a NUL, and advance *STRINGP + to point to the next char after it. Otherwise, set *STRINGP to NULL. + If *STRINGP was already NULL, nothing happens. + Return the old value of *STRINGP. + + This is a variant of strtok() that is multithread-safe and supports + empty fields. + + Caveat: It modifies the original string. + Caveat: These functions cannot be used on constant strings. + Caveat: The identity of the delimiting character is lost. + Caveat: It doesn't work with multibyte strings unless all of the delimiter + characters are ASCII characters < 0x30. + + See also strtok_r(). */ +#if @GNULIB_STRSEP@ +# if ! @HAVE_STRSEP@ +_GL_FUNCDECL_SYS (strsep, char *, + (char **restrict __stringp, char const *restrict __delim) + _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (strsep, char *, + (char **restrict __stringp, char const *restrict __delim)); +_GL_CXXALIASWARN (strsep); +# if defined GNULIB_POSIXCHECK +# undef strsep +_GL_WARN_ON_USE (strsep, "strsep cannot work correctly on character strings " + "in multibyte locales - " + "use mbssep if you care about internationalization"); +# endif +#elif defined GNULIB_POSIXCHECK +# undef strsep +# if HAVE_RAW_DECL_STRSEP +_GL_WARN_ON_USE (strsep, "strsep is unportable - " + "use gnulib module strsep for portability"); +# endif +#endif + +#if @GNULIB_STRSTR@ +# if @REPLACE_STRSTR@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define strstr rpl_strstr +# endif +_GL_FUNCDECL_RPL (strstr, char *, (const char *haystack, const char *needle) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (strstr, char *, (const char *haystack, const char *needle)); +# else + /* On some systems, this function is defined as an overloaded function: + extern "C++" { const char * strstr (const char *, const char *); } + extern "C++" { char * strstr (char *, const char *); } */ +_GL_CXXALIAS_SYS_CAST2 (strstr, + char *, (const char *haystack, const char *needle), + const char *, (const char *haystack, const char *needle)); +# endif +# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \ + && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) +_GL_CXXALIASWARN1 (strstr, char *, (char *haystack, const char *needle)); +_GL_CXXALIASWARN1 (strstr, const char *, + (const char *haystack, const char *needle)); +# else +_GL_CXXALIASWARN (strstr); +# endif +#elif defined GNULIB_POSIXCHECK +/* strstr() does not work with multibyte strings if the locale encoding is + different from UTF-8: + POSIX says that it operates on "strings", and "string" in POSIX is defined + as a sequence of bytes, not of characters. */ +# undef strstr +/* Assume strstr is always declared. */ +_GL_WARN_ON_USE (strstr, "strstr is quadratic on many systems, and cannot " + "work correctly on character strings in most " + "multibyte locales - " + "use mbsstr if you care about internationalization, " + "or use strstr if you care about speed"); +#endif + +/* Find the first occurrence of NEEDLE in HAYSTACK, using case-insensitive + comparison. */ +#if @GNULIB_STRCASESTR@ +# if @REPLACE_STRCASESTR@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define strcasestr rpl_strcasestr +# endif +_GL_FUNCDECL_RPL (strcasestr, char *, + (const char *haystack, const char *needle) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (strcasestr, char *, + (const char *haystack, const char *needle)); +# else +# if ! @HAVE_STRCASESTR@ +_GL_FUNCDECL_SYS (strcasestr, char *, + (const char *haystack, const char *needle) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1, 2))); +# endif + /* On some systems, this function is defined as an overloaded function: + extern "C++" { const char * strcasestr (const char *, const char *); } + extern "C++" { char * strcasestr (char *, const char *); } */ +_GL_CXXALIAS_SYS_CAST2 (strcasestr, + char *, (const char *haystack, const char *needle), + const char *, (const char *haystack, const char *needle)); +# endif +# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \ + && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) +_GL_CXXALIASWARN1 (strcasestr, char *, (char *haystack, const char *needle)); +_GL_CXXALIASWARN1 (strcasestr, const char *, + (const char *haystack, const char *needle)); +# else +_GL_CXXALIASWARN (strcasestr); +# endif +#elif defined GNULIB_POSIXCHECK +/* strcasestr() does not work with multibyte strings: + It is a glibc extension, and glibc implements it only for unibyte + locales. */ +# undef strcasestr +# if HAVE_RAW_DECL_STRCASESTR +_GL_WARN_ON_USE (strcasestr, "strcasestr does work correctly on character " + "strings in multibyte locales - " + "use mbscasestr if you care about " + "internationalization, or use c-strcasestr if you want " + "a locale independent function"); +# endif +#endif + +/* Parse S into tokens separated by characters in DELIM. + If S is NULL, the saved pointer in SAVE_PTR is used as + the next starting point. For example: + char s[] = "-abc-=-def"; + char *sp; + x = strtok_r(s, "-", &sp); // x = "abc", sp = "=-def" + x = strtok_r(NULL, "-=", &sp); // x = "def", sp = NULL + x = strtok_r(NULL, "=", &sp); // x = NULL + // s = "abc\0-def\0" + + This is a variant of strtok() that is multithread-safe. + + For the POSIX documentation for this function, see: + http://www.opengroup.org/susv3xsh/strtok.html + + Caveat: It modifies the original string. + Caveat: These functions cannot be used on constant strings. + Caveat: The identity of the delimiting character is lost. + Caveat: It doesn't work with multibyte strings unless all of the delimiter + characters are ASCII characters < 0x30. + + See also strsep(). */ +#if @GNULIB_STRTOK_R@ +# if @REPLACE_STRTOK_R@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef strtok_r +# define strtok_r rpl_strtok_r +# endif +_GL_FUNCDECL_RPL (strtok_r, char *, + (char *restrict s, char const *restrict delim, + char **restrict save_ptr) + _GL_ARG_NONNULL ((2, 3))); +_GL_CXXALIAS_RPL (strtok_r, char *, + (char *restrict s, char const *restrict delim, + char **restrict save_ptr)); +# else +# if @UNDEFINE_STRTOK_R@ || defined GNULIB_POSIXCHECK +# undef strtok_r +# endif +# if ! @HAVE_DECL_STRTOK_R@ +_GL_FUNCDECL_SYS (strtok_r, char *, + (char *restrict s, char const *restrict delim, + char **restrict save_ptr) + _GL_ARG_NONNULL ((2, 3))); +# endif +_GL_CXXALIAS_SYS (strtok_r, char *, + (char *restrict s, char const *restrict delim, + char **restrict save_ptr)); +# endif +_GL_CXXALIASWARN (strtok_r); +# if defined GNULIB_POSIXCHECK +_GL_WARN_ON_USE (strtok_r, "strtok_r cannot work correctly on character " + "strings in multibyte locales - " + "use mbstok_r if you care about internationalization"); +# endif +#elif defined GNULIB_POSIXCHECK +# undef strtok_r +# if HAVE_RAW_DECL_STRTOK_R +_GL_WARN_ON_USE (strtok_r, "strtok_r is unportable - " + "use gnulib module strtok_r for portability"); +# endif +#endif + + +/* The following functions are not specified by POSIX. They are gnulib + extensions. */ + +#if @GNULIB_MBSLEN@ +/* Return the number of multibyte characters in the character string STRING. + This considers multibyte characters, unlike strlen, which counts bytes. */ +# ifdef __MirBSD__ /* MirBSD defines mbslen as a macro. Override it. */ +# undef mbslen +# endif +# if @HAVE_MBSLEN@ /* AIX, OSF/1, MirBSD define mbslen already in libc. */ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define mbslen rpl_mbslen +# endif +_GL_FUNCDECL_RPL (mbslen, size_t, (const char *string) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (mbslen, size_t, (const char *string)); +# else +_GL_FUNCDECL_SYS (mbslen, size_t, (const char *string) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_SYS (mbslen, size_t, (const char *string)); +# endif +_GL_CXXALIASWARN (mbslen); +#endif + +#if @GNULIB_MBSNLEN@ +/* Return the number of multibyte characters in the character string starting + at STRING and ending at STRING + LEN. */ +_GL_EXTERN_C size_t mbsnlen (const char *string, size_t len) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1)); +#endif + +#if @GNULIB_MBSCHR@ +/* Locate the first single-byte character C in the character string STRING, + and return a pointer to it. Return NULL if C is not found in STRING. + Unlike strchr(), this function works correctly in multibyte locales with + encodings such as GB18030. */ +# if defined __hpux +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define mbschr rpl_mbschr /* avoid collision with HP-UX function */ +# endif +_GL_FUNCDECL_RPL (mbschr, char *, (const char *string, int c) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (mbschr, char *, (const char *string, int c)); +# else +_GL_FUNCDECL_SYS (mbschr, char *, (const char *string, int c) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_SYS (mbschr, char *, (const char *string, int c)); +# endif +_GL_CXXALIASWARN (mbschr); +#endif + +#if @GNULIB_MBSRCHR@ +/* Locate the last single-byte character C in the character string STRING, + and return a pointer to it. Return NULL if C is not found in STRING. + Unlike strrchr(), this function works correctly in multibyte locales with + encodings such as GB18030. */ +# if defined __hpux || defined __INTERIX +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define mbsrchr rpl_mbsrchr /* avoid collision with system function */ +# endif +_GL_FUNCDECL_RPL (mbsrchr, char *, (const char *string, int c) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (mbsrchr, char *, (const char *string, int c)); +# else +_GL_FUNCDECL_SYS (mbsrchr, char *, (const char *string, int c) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_SYS (mbsrchr, char *, (const char *string, int c)); +# endif +_GL_CXXALIASWARN (mbsrchr); +#endif + +#if @GNULIB_MBSSTR@ +/* Find the first occurrence of the character string NEEDLE in the character + string HAYSTACK. Return NULL if NEEDLE is not found in HAYSTACK. + Unlike strstr(), this function works correctly in multibyte locales with + encodings different from UTF-8. */ +_GL_EXTERN_C char * mbsstr (const char *haystack, const char *needle) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1, 2)); +#endif + +#if @GNULIB_MBSCASECMP@ +/* Compare the character strings S1 and S2, ignoring case, returning less than, + equal to or greater than zero if S1 is lexicographically less than, equal to + or greater than S2. + Note: This function may, in multibyte locales, return 0 for strings of + different lengths! + Unlike strcasecmp(), this function works correctly in multibyte locales. */ +_GL_EXTERN_C int mbscasecmp (const char *s1, const char *s2) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1, 2)); +#endif + +#if @GNULIB_MBSNCASECMP@ +/* Compare the initial segment of the character string S1 consisting of at most + N characters with the initial segment of the character string S2 consisting + of at most N characters, ignoring case, returning less than, equal to or + greater than zero if the initial segment of S1 is lexicographically less + than, equal to or greater than the initial segment of S2. + Note: This function may, in multibyte locales, return 0 for initial segments + of different lengths! + Unlike strncasecmp(), this function works correctly in multibyte locales. + But beware that N is not a byte count but a character count! */ +_GL_EXTERN_C int mbsncasecmp (const char *s1, const char *s2, size_t n) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1, 2)); +#endif + +#if @GNULIB_MBSPCASECMP@ +/* Compare the initial segment of the character string STRING consisting of + at most mbslen (PREFIX) characters with the character string PREFIX, + ignoring case. If the two match, return a pointer to the first byte + after this prefix in STRING. Otherwise, return NULL. + Note: This function may, in multibyte locales, return non-NULL if STRING + is of smaller length than PREFIX! + Unlike strncasecmp(), this function works correctly in multibyte + locales. */ +_GL_EXTERN_C char * mbspcasecmp (const char *string, const char *prefix) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1, 2)); +#endif + +#if @GNULIB_MBSCASESTR@ +/* Find the first occurrence of the character string NEEDLE in the character + string HAYSTACK, using case-insensitive comparison. + Note: This function may, in multibyte locales, return success even if + strlen (haystack) < strlen (needle) ! + Unlike strcasestr(), this function works correctly in multibyte locales. */ +_GL_EXTERN_C char * mbscasestr (const char *haystack, const char *needle) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1, 2)); +#endif + +#if @GNULIB_MBSCSPN@ +/* Find the first occurrence in the character string STRING of any character + in the character string ACCEPT. Return the number of bytes from the + beginning of the string to this occurrence, or to the end of the string + if none exists. + Unlike strcspn(), this function works correctly in multibyte locales. */ +_GL_EXTERN_C size_t mbscspn (const char *string, const char *accept) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1, 2)); +#endif + +#if @GNULIB_MBSPBRK@ +/* Find the first occurrence in the character string STRING of any character + in the character string ACCEPT. Return the pointer to it, or NULL if none + exists. + Unlike strpbrk(), this function works correctly in multibyte locales. */ +# if defined __hpux +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define mbspbrk rpl_mbspbrk /* avoid collision with HP-UX function */ +# endif +_GL_FUNCDECL_RPL (mbspbrk, char *, (const char *string, const char *accept) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (mbspbrk, char *, (const char *string, const char *accept)); +# else +_GL_FUNCDECL_SYS (mbspbrk, char *, (const char *string, const char *accept) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_SYS (mbspbrk, char *, (const char *string, const char *accept)); +# endif +_GL_CXXALIASWARN (mbspbrk); +#endif + +#if @GNULIB_MBSSPN@ +/* Find the first occurrence in the character string STRING of any character + not in the character string REJECT. Return the number of bytes from the + beginning of the string to this occurrence, or to the end of the string + if none exists. + Unlike strspn(), this function works correctly in multibyte locales. */ +_GL_EXTERN_C size_t mbsspn (const char *string, const char *reject) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1, 2)); +#endif + +#if @GNULIB_MBSSEP@ +/* Search the next delimiter (multibyte character listed in the character + string DELIM) starting at the character string *STRINGP. + If one is found, overwrite it with a NUL, and advance *STRINGP to point + to the next multibyte character after it. Otherwise, set *STRINGP to NULL. + If *STRINGP was already NULL, nothing happens. + Return the old value of *STRINGP. + + This is a variant of mbstok_r() that supports empty fields. + + Caveat: It modifies the original string. + Caveat: These functions cannot be used on constant strings. + Caveat: The identity of the delimiting character is lost. + + See also mbstok_r(). */ +_GL_EXTERN_C char * mbssep (char **stringp, const char *delim) + _GL_ARG_NONNULL ((1, 2)); +#endif + +#if @GNULIB_MBSTOK_R@ +/* Parse the character string STRING into tokens separated by characters in + the character string DELIM. + If STRING is NULL, the saved pointer in SAVE_PTR is used as + the next starting point. For example: + char s[] = "-abc-=-def"; + char *sp; + x = mbstok_r(s, "-", &sp); // x = "abc", sp = "=-def" + x = mbstok_r(NULL, "-=", &sp); // x = "def", sp = NULL + x = mbstok_r(NULL, "=", &sp); // x = NULL + // s = "abc\0-def\0" + + Caveat: It modifies the original string. + Caveat: These functions cannot be used on constant strings. + Caveat: The identity of the delimiting character is lost. + + See also mbssep(). */ +_GL_EXTERN_C char * mbstok_r (char *string, const char *delim, char **save_ptr) + _GL_ARG_NONNULL ((2, 3)); +#endif + +/* Map any int, typically from errno, into an error message. */ +#if @GNULIB_STRERROR@ +# if @REPLACE_STRERROR@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef strerror +# define strerror rpl_strerror +# endif +_GL_FUNCDECL_RPL (strerror, char *, (int)); +_GL_CXXALIAS_RPL (strerror, char *, (int)); +# else +_GL_CXXALIAS_SYS (strerror, char *, (int)); +# endif +_GL_CXXALIASWARN (strerror); +#elif defined GNULIB_POSIXCHECK +# undef strerror +/* Assume strerror is always declared. */ +_GL_WARN_ON_USE (strerror, "strerror is unportable - " + "use gnulib module strerror to guarantee non-NULL result"); +#endif + +/* Map any int, typically from errno, into an error message. Multithread-safe. + Uses the POSIX declaration, not the glibc declaration. */ +#if @GNULIB_STRERROR_R@ +# if @REPLACE_STRERROR_R@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef strerror_r +# define strerror_r rpl_strerror_r +# endif +_GL_FUNCDECL_RPL (strerror_r, int, (int errnum, char *buf, size_t buflen) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (strerror_r, int, (int errnum, char *buf, size_t buflen)); +# else +# if !@HAVE_DECL_STRERROR_R@ +_GL_FUNCDECL_SYS (strerror_r, int, (int errnum, char *buf, size_t buflen) + _GL_ARG_NONNULL ((2))); +# endif +_GL_CXXALIAS_SYS (strerror_r, int, (int errnum, char *buf, size_t buflen)); +# endif +# if @HAVE_DECL_STRERROR_R@ +_GL_CXXALIASWARN (strerror_r); +# endif +#elif defined GNULIB_POSIXCHECK +# undef strerror_r +# if HAVE_RAW_DECL_STRERROR_R +_GL_WARN_ON_USE (strerror_r, "strerror_r is unportable - " + "use gnulib module strerror_r-posix for portability"); +# endif +#endif + +#if @GNULIB_STRSIGNAL@ +# if @REPLACE_STRSIGNAL@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define strsignal rpl_strsignal +# endif +_GL_FUNCDECL_RPL (strsignal, char *, (int __sig)); +_GL_CXXALIAS_RPL (strsignal, char *, (int __sig)); +# else +# if ! @HAVE_DECL_STRSIGNAL@ +_GL_FUNCDECL_SYS (strsignal, char *, (int __sig)); +# endif +/* Need to cast, because on Cygwin 1.5.x systems, the return type is + 'const char *'. */ +_GL_CXXALIAS_SYS_CAST (strsignal, char *, (int __sig)); +# endif +_GL_CXXALIASWARN (strsignal); +#elif defined GNULIB_POSIXCHECK +# undef strsignal +# if HAVE_RAW_DECL_STRSIGNAL +_GL_WARN_ON_USE (strsignal, "strsignal is unportable - " + "use gnulib module strsignal for portability"); +# endif +#endif + +#if @GNULIB_STRVERSCMP@ +# if !@HAVE_STRVERSCMP@ +_GL_FUNCDECL_SYS (strverscmp, int, (const char *, const char *) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (strverscmp, int, (const char *, const char *)); +_GL_CXXALIASWARN (strverscmp); +#elif defined GNULIB_POSIXCHECK +# undef strverscmp +# if HAVE_RAW_DECL_STRVERSCMP +_GL_WARN_ON_USE (strverscmp, "strverscmp is unportable - " + "use gnulib module strverscmp for portability"); +# endif +#endif + + +#endif /* _@GUARD_PREFIX@_STRING_H */ +#endif /* _@GUARD_PREFIX@_STRING_H */ diff --git a/gettext-tools/gnulib-lib/strnlen.c b/gettext-tools/gnulib-lib/strnlen.c new file mode 100644 index 0000000..ddccebc --- /dev/null +++ b/gettext-tools/gnulib-lib/strnlen.c @@ -0,0 +1,30 @@ +/* Find the length of STRING, but scan at most MAXLEN characters. + Copyright (C) 2005-2007, 2009-2014 Free Software Foundation, Inc. + Written by Simon Josefsson. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . */ + +#include + +#include + +/* Find the length of STRING, but scan at most MAXLEN characters. + If no '\0' terminator is found in that many characters, return MAXLEN. */ + +size_t +strnlen (const char *string, size_t maxlen) +{ + const char *end = memchr (string, '\0', maxlen); + return end ? (size_t) (end - string) : maxlen; +} diff --git a/gettext-tools/gnulib-lib/strnlen1.c b/gettext-tools/gnulib-lib/strnlen1.c new file mode 100644 index 0000000..363776a --- /dev/null +++ b/gettext-tools/gnulib-lib/strnlen1.c @@ -0,0 +1,35 @@ +/* Find the length of STRING + 1, but scan at most MAXLEN bytes. + Copyright (C) 2005-2006, 2009-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include "strnlen1.h" + +#include + +/* Find the length of STRING + 1, but scan at most MAXLEN bytes. + If no '\0' terminator is found in that many characters, return MAXLEN. */ +/* This is the same as strnlen (string, maxlen - 1) + 1. */ +size_t +strnlen1 (const char *string, size_t maxlen) +{ + const char *end = (const char *) memchr (string, '\0', maxlen); + if (end != NULL) + return end - string + 1; + else + return maxlen; +} diff --git a/gettext-tools/gnulib-lib/strnlen1.h b/gettext-tools/gnulib-lib/strnlen1.h new file mode 100644 index 0000000..b2f956f --- /dev/null +++ b/gettext-tools/gnulib-lib/strnlen1.h @@ -0,0 +1,40 @@ +/* Find the length of STRING + 1, but scan at most MAXLEN bytes. + Copyright (C) 2005, 2009-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _STRNLEN1_H +#define _STRNLEN1_H + +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Find the length of STRING + 1, but scan at most MAXLEN bytes. + If no '\0' terminator is found in that many characters, return MAXLEN. */ +/* This is the same as strnlen (string, maxlen - 1) + 1. */ +extern size_t strnlen1 (const char *string, size_t maxlen) + _GL_ATTRIBUTE_PURE; + + +#ifdef __cplusplus +} +#endif + + +#endif /* _STRNLEN1_H */ diff --git a/gettext-tools/gnulib-lib/strpbrk.c b/gettext-tools/gnulib-lib/strpbrk.c new file mode 100644 index 0000000..46e58d3 --- /dev/null +++ b/gettext-tools/gnulib-lib/strpbrk.c @@ -0,0 +1,41 @@ +/* Copyright (C) 1991, 1994, 2000, 2002-2003, 2006, 2009-2014 Free Software + Foundation, Inc. + + NOTE: The canonical source of this file is maintained with the GNU C Library. + Bugs can be reported to bug-glibc@prep.ai.mit.edu. + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 3, or (at your option) any + later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . */ + +#include + +#include +#include + +#undef strpbrk + +/* Find the first occurrence in S of any character in ACCEPT. */ +char * +strpbrk (const char *s, const char *accept) +{ + while (*s != '\0') + { + const char *a = accept; + while (*a != '\0') + if (*a++ == *s) + return (char *) s; + ++s; + } + + return NULL; +} diff --git a/gettext-tools/gnulib-lib/strstr.c b/gettext-tools/gnulib-lib/strstr.c new file mode 100644 index 0000000..d5b9d78 --- /dev/null +++ b/gettext-tools/gnulib-lib/strstr.c @@ -0,0 +1,82 @@ +/* Copyright (C) 1991-1994, 1996-1998, 2000, 2004, 2007-2014 Free Software + Foundation, Inc. + This file is part of the GNU C Library. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, see . */ + +/* This particular implementation was written by Eric Blake, 2008. */ + +#ifndef _LIBC +# include +#endif + +/* Specification of strstr. */ +#include + +#include + +#ifndef _LIBC +# define __builtin_expect(expr, val) (expr) +#endif + +#define RETURN_TYPE char * +#define AVAILABLE(h, h_l, j, n_l) \ + (!memchr ((h) + (h_l), '\0', (j) + (n_l) - (h_l)) \ + && ((h_l) = (j) + (n_l))) +#include "str-two-way.h" + +/* Return the first occurrence of NEEDLE in HAYSTACK. Return HAYSTACK + if NEEDLE is empty, otherwise NULL if NEEDLE is not found in + HAYSTACK. */ +char * +strstr (const char *haystack_start, const char *needle_start) +{ + const char *haystack = haystack_start; + const char *needle = needle_start; + size_t needle_len; /* Length of NEEDLE. */ + size_t haystack_len; /* Known minimum length of HAYSTACK. */ + bool ok = true; /* True if NEEDLE is prefix of HAYSTACK. */ + + /* Determine length of NEEDLE, and in the process, make sure + HAYSTACK is at least as long (no point processing all of a long + NEEDLE if HAYSTACK is too short). */ + while (*haystack && *needle) + ok &= *haystack++ == *needle++; + if (*needle) + return NULL; + if (ok) + return (char *) haystack_start; + + /* Reduce the size of haystack using strchr, since it has a smaller + linear coefficient than the Two-Way algorithm. */ + needle_len = needle - needle_start; + haystack = strchr (haystack_start + 1, *needle_start); + if (!haystack || __builtin_expect (needle_len == 1, 0)) + return (char *) haystack; + needle -= needle_len; + haystack_len = (haystack > haystack_start + needle_len ? 1 + : needle_len + haystack_start - haystack); + + /* Perform the search. Abstract memory is considered to be an array + of 'unsigned char' values, not an array of 'char' values. See + ISO C 99 section 6.2.6.1. */ + if (needle_len < LONG_NEEDLE_THRESHOLD) + return two_way_short_needle ((const unsigned char *) haystack, + haystack_len, + (const unsigned char *) needle, needle_len); + return two_way_long_needle ((const unsigned char *) haystack, haystack_len, + (const unsigned char *) needle, needle_len); +} + +#undef LONG_NEEDLE_THRESHOLD diff --git a/gettext-tools/gnulib-lib/strtol.c b/gettext-tools/gnulib-lib/strtol.c new file mode 100644 index 0000000..2e015dc --- /dev/null +++ b/gettext-tools/gnulib-lib/strtol.c @@ -0,0 +1,433 @@ +/* Convert string representation of a number into an integer value. + + Copyright (C) 1991-1992, 1994-1999, 2003, 2005-2007, 2009-2014 Free Software + Foundation, Inc. + + NOTE: The canonical source of this file is maintained with the GNU C + Library. Bugs can be reported to bug-glibc@gnu.org. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 3 of the License, or any + later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifdef _LIBC +# define USE_NUMBER_GROUPING +#else +# include +#endif + +#include +#include +#ifndef __set_errno +# define __set_errno(Val) errno = (Val) +#endif + +#include +#include +#include +#include + +#ifdef USE_NUMBER_GROUPING +# include "../locale/localeinfo.h" +#endif + +/* Nonzero if we are defining 'strtoul' or 'strtoull', operating on + unsigned integers. */ +#ifndef UNSIGNED +# define UNSIGNED 0 +# define INT LONG int +#else +# define INT unsigned LONG int +#endif + +/* Determine the name. */ +#ifdef USE_IN_EXTENDED_LOCALE_MODEL +# if UNSIGNED +# ifdef USE_WIDE_CHAR +# ifdef QUAD +# define strtol __wcstoull_l +# else +# define strtol __wcstoul_l +# endif +# else +# ifdef QUAD +# define strtol __strtoull_l +# else +# define strtol __strtoul_l +# endif +# endif +# else +# ifdef USE_WIDE_CHAR +# ifdef QUAD +# define strtol __wcstoll_l +# else +# define strtol __wcstol_l +# endif +# else +# ifdef QUAD +# define strtol __strtoll_l +# else +# define strtol __strtol_l +# endif +# endif +# endif +#else +# if UNSIGNED +# ifdef USE_WIDE_CHAR +# ifdef QUAD +# define strtol wcstoull +# else +# define strtol wcstoul +# endif +# else +# ifdef QUAD +# define strtol strtoull +# else +# define strtol strtoul +# endif +# endif +# else +# ifdef USE_WIDE_CHAR +# ifdef QUAD +# define strtol wcstoll +# else +# define strtol wcstol +# endif +# else +# ifdef QUAD +# define strtol strtoll +# endif +# endif +# endif +#endif + +/* If QUAD is defined, we are defining 'strtoll' or 'strtoull', + operating on 'long long int's. */ +#ifdef QUAD +# define LONG long long +# define STRTOL_LONG_MIN LLONG_MIN +# define STRTOL_LONG_MAX LLONG_MAX +# define STRTOL_ULONG_MAX ULLONG_MAX + +/* The extra casts in the following macros work around compiler bugs, + e.g., in Cray C 5.0.3.0. */ + +/* True if negative values of the signed integer type T use two's + complement, ones' complement, or signed magnitude representation, + respectively. Much GNU code assumes two's complement, but some + people like to be portable to all possible C hosts. */ +# define TYPE_TWOS_COMPLEMENT(t) ((t) ~ (t) 0 == (t) -1) +# define TYPE_ONES_COMPLEMENT(t) ((t) ~ (t) 0 == 0) +# define TYPE_SIGNED_MAGNITUDE(t) ((t) ~ (t) 0 < (t) -1) + +/* True if the arithmetic type T is signed. */ +# define TYPE_SIGNED(t) (! ((t) 0 < (t) -1)) + +/* The maximum and minimum values for the integer type T. These + macros have undefined behavior if T is signed and has padding bits. + If this is a problem for you, please let us know how to fix it for + your host. */ +# define TYPE_MINIMUM(t) \ + ((t) (! TYPE_SIGNED (t) \ + ? (t) 0 \ + : TYPE_SIGNED_MAGNITUDE (t) \ + ? ~ (t) 0 \ + : ~ TYPE_MAXIMUM (t))) +# define TYPE_MAXIMUM(t) \ + ((t) (! TYPE_SIGNED (t) \ + ? (t) -1 \ + : ((((t) 1 << (sizeof (t) * CHAR_BIT - 2)) - 1) * 2 + 1))) + +# ifndef ULLONG_MAX +# define ULLONG_MAX TYPE_MAXIMUM (unsigned long long) +# endif +# ifndef LLONG_MAX +# define LLONG_MAX TYPE_MAXIMUM (long long int) +# endif +# ifndef LLONG_MIN +# define LLONG_MIN TYPE_MINIMUM (long long int) +# endif + +# if __GNUC__ == 2 && __GNUC_MINOR__ < 7 + /* Work around gcc bug with using this constant. */ + static const unsigned long long int maxquad = ULLONG_MAX; +# undef STRTOL_ULONG_MAX +# define STRTOL_ULONG_MAX maxquad +# endif +#else +# define LONG long +# define STRTOL_LONG_MIN LONG_MIN +# define STRTOL_LONG_MAX LONG_MAX +# define STRTOL_ULONG_MAX ULONG_MAX +#endif + + +/* We use this code also for the extended locale handling where the + function gets as an additional argument the locale which has to be + used. To access the values we have to redefine the _NL_CURRENT + macro. */ +#ifdef USE_IN_EXTENDED_LOCALE_MODEL +# undef _NL_CURRENT +# define _NL_CURRENT(category, item) \ + (current->values[_NL_ITEM_INDEX (item)].string) +# define LOCALE_PARAM , loc +# define LOCALE_PARAM_PROTO , __locale_t loc +#else +# define LOCALE_PARAM +# define LOCALE_PARAM_PROTO +#endif + +#ifdef USE_WIDE_CHAR +# include +# include +# define L_(Ch) L##Ch +# define UCHAR_TYPE wint_t +# define STRING_TYPE wchar_t +# ifdef USE_IN_EXTENDED_LOCALE_MODEL +# define ISSPACE(Ch) __iswspace_l ((Ch), loc) +# define ISALPHA(Ch) __iswalpha_l ((Ch), loc) +# define TOUPPER(Ch) __towupper_l ((Ch), loc) +# else +# define ISSPACE(Ch) iswspace (Ch) +# define ISALPHA(Ch) iswalpha (Ch) +# define TOUPPER(Ch) towupper (Ch) +# endif +#else +# define L_(Ch) Ch +# define UCHAR_TYPE unsigned char +# define STRING_TYPE char +# ifdef USE_IN_EXTENDED_LOCALE_MODEL +# define ISSPACE(Ch) __isspace_l ((Ch), loc) +# define ISALPHA(Ch) __isalpha_l ((Ch), loc) +# define TOUPPER(Ch) __toupper_l ((Ch), loc) +# else +# define ISSPACE(Ch) isspace (Ch) +# define ISALPHA(Ch) isalpha (Ch) +# define TOUPPER(Ch) toupper (Ch) +# endif +#endif + +#define INTERNAL(X) INTERNAL1(X) +#define INTERNAL1(X) __##X##_internal +#define WEAKNAME(X) WEAKNAME1(X) + +#ifdef USE_NUMBER_GROUPING +/* This file defines a function to check for correct grouping. */ +# include "grouping.h" +#endif + + + +/* Convert NPTR to an 'unsigned long int' or 'long int' in base BASE. + If BASE is 0 the base is determined by the presence of a leading + zero, indicating octal or a leading "0x" or "0X", indicating hexadecimal. + If BASE is < 2 or > 36, it is reset to 10. + If ENDPTR is not NULL, a pointer to the character after the last + one converted is stored in *ENDPTR. */ + +INT +INTERNAL (strtol) (const STRING_TYPE *nptr, STRING_TYPE **endptr, + int base, int group LOCALE_PARAM_PROTO) +{ + int negative; + register unsigned LONG int cutoff; + register unsigned int cutlim; + register unsigned LONG int i; + register const STRING_TYPE *s; + register UCHAR_TYPE c; + const STRING_TYPE *save, *end; + int overflow; + +#ifdef USE_NUMBER_GROUPING +# ifdef USE_IN_EXTENDED_LOCALE_MODEL + struct locale_data *current = loc->__locales[LC_NUMERIC]; +# endif + /* The thousands character of the current locale. */ + wchar_t thousands = L'\0'; + /* The numeric grouping specification of the current locale, + in the format described in . */ + const char *grouping; + + if (group) + { + grouping = _NL_CURRENT (LC_NUMERIC, GROUPING); + if (*grouping <= 0 || *grouping == CHAR_MAX) + grouping = NULL; + else + { + /* Figure out the thousands separator character. */ +# if defined _LIBC || defined _HAVE_BTOWC + thousands = __btowc (*_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP)); + if (thousands == WEOF) + thousands = L'\0'; +# endif + if (thousands == L'\0') + grouping = NULL; + } + } + else + grouping = NULL; +#endif + + if (base < 0 || base == 1 || base > 36) + { + __set_errno (EINVAL); + return 0; + } + + save = s = nptr; + + /* Skip white space. */ + while (ISSPACE (*s)) + ++s; + if (*s == L_('\0')) + goto noconv; + + /* Check for a sign. */ + if (*s == L_('-')) + { + negative = 1; + ++s; + } + else if (*s == L_('+')) + { + negative = 0; + ++s; + } + else + negative = 0; + + /* Recognize number prefix and if BASE is zero, figure it out ourselves. */ + if (*s == L_('0')) + { + if ((base == 0 || base == 16) && TOUPPER (s[1]) == L_('X')) + { + s += 2; + base = 16; + } + else if (base == 0) + base = 8; + } + else if (base == 0) + base = 10; + + /* Save the pointer so we can check later if anything happened. */ + save = s; + +#ifdef USE_NUMBER_GROUPING + if (group) + { + /* Find the end of the digit string and check its grouping. */ + end = s; + for (c = *end; c != L_('\0'); c = *++end) + if ((wchar_t) c != thousands + && ((wchar_t) c < L_('0') || (wchar_t) c > L_('9')) + && (!ISALPHA (c) || (int) (TOUPPER (c) - L_('A') + 10) >= base)) + break; + if (*s == thousands) + end = s; + else + end = correctly_grouped_prefix (s, end, thousands, grouping); + } + else +#endif + end = NULL; + + cutoff = STRTOL_ULONG_MAX / (unsigned LONG int) base; + cutlim = STRTOL_ULONG_MAX % (unsigned LONG int) base; + + overflow = 0; + i = 0; + for (c = *s; c != L_('\0'); c = *++s) + { + if (s == end) + break; + if (c >= L_('0') && c <= L_('9')) + c -= L_('0'); + else if (ISALPHA (c)) + c = TOUPPER (c) - L_('A') + 10; + else + break; + if ((int) c >= base) + break; + /* Check for overflow. */ + if (i > cutoff || (i == cutoff && c > cutlim)) + overflow = 1; + else + { + i *= (unsigned LONG int) base; + i += c; + } + } + + /* Check if anything actually happened. */ + if (s == save) + goto noconv; + + /* Store in ENDPTR the address of one character + past the last character we converted. */ + if (endptr != NULL) + *endptr = (STRING_TYPE *) s; + +#if !UNSIGNED + /* Check for a value that is within the range of + 'unsigned LONG int', but outside the range of 'LONG int'. */ + if (overflow == 0 + && i > (negative + ? -((unsigned LONG int) (STRTOL_LONG_MIN + 1)) + 1 + : (unsigned LONG int) STRTOL_LONG_MAX)) + overflow = 1; +#endif + + if (overflow) + { + __set_errno (ERANGE); +#if UNSIGNED + return STRTOL_ULONG_MAX; +#else + return negative ? STRTOL_LONG_MIN : STRTOL_LONG_MAX; +#endif + } + + /* Return the result of the appropriate sign. */ + return negative ? -i : i; + +noconv: + /* We must handle a special case here: the base is 0 or 16 and the + first two characters are '0' and 'x', but the rest are no + hexadecimal digits. This is no error case. We return 0 and + ENDPTR points to the 'x'. */ + if (endptr != NULL) + { + if (save - nptr >= 2 && TOUPPER (save[-1]) == L_('X') + && save[-2] == L_('0')) + *endptr = (STRING_TYPE *) &save[-1]; + else + /* There was no number to convert. */ + *endptr = (STRING_TYPE *) nptr; + } + + return 0L; +} + +/* External user entry point. */ + + +INT +#ifdef weak_function +weak_function +#endif +strtol (const STRING_TYPE *nptr, STRING_TYPE **endptr, + int base LOCALE_PARAM_PROTO) +{ + return INTERNAL (strtol) (nptr, endptr, base, 0 LOCALE_PARAM); +} diff --git a/gettext-tools/gnulib-lib/strtoul.c b/gettext-tools/gnulib-lib/strtoul.c new file mode 100644 index 0000000..4c5ceaf --- /dev/null +++ b/gettext-tools/gnulib-lib/strtoul.c @@ -0,0 +1,19 @@ +/* Copyright (C) 1991, 1997, 2009-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#define UNSIGNED 1 + +#include "strtol.c" diff --git a/gettext-tools/gnulib-lib/styled-ostream.c b/gettext-tools/gnulib-lib/styled-ostream.c new file mode 100644 index 0000000..3f584e4 --- /dev/null +++ b/gettext-tools/gnulib-lib/styled-ostream.c @@ -0,0 +1,143 @@ +/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ + +#line 1 "styled-ostream.oo.c" +/* Abstract output stream for CSS styled text. + Copyright (C) 2006 Free Software Foundation, Inc. + Written by Bruno Haible , 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include "styled-ostream.h" + + +#line 28 "styled-ostream.c" +#if !IS_CPLUSPLUS +#define styled_ostream_representation any_ostream_representation +#endif +#include "styled_ostream.priv.h" + +const typeinfo_t styled_ostream_typeinfo = { "styled_ostream" }; + +static const typeinfo_t * const styled_ostream_superclasses[] = + { styled_ostream_SUPERCLASSES }; + +#define super ostream_vtable + +#line 28 "styled-ostream.oo.c" + +#line 43 "styled-ostream.c" +void styled_ostream__write_mem (styled_ostream_t first_arg, const void *data, size_t len); +void +styled_ostream__write_mem (styled_ostream_t first_arg, const void *data, size_t len) +{ + super.write_mem (first_arg,data,len); +} + +void styled_ostream__flush (styled_ostream_t first_arg); +void +styled_ostream__flush (styled_ostream_t first_arg) +{ + super.flush (first_arg); +} + +void styled_ostream__free (styled_ostream_t first_arg); +void +styled_ostream__free (styled_ostream_t first_arg) +{ + super.free (first_arg); +} + +void styled_ostream__begin_use_class (styled_ostream_t first_arg, const char *classname); +void +styled_ostream__begin_use_class (styled_ostream_t first_arg, const char *classname) +{ + /* Abstract (unimplemented) method called. */ + abort (); + #ifndef __GNUC__ + styled_ostream__begin_use_class (first_arg,classname); + #endif +} + +void styled_ostream__end_use_class (styled_ostream_t first_arg, const char *classname); +void +styled_ostream__end_use_class (styled_ostream_t first_arg, const char *classname) +{ + /* Abstract (unimplemented) method called. */ + abort (); + #ifndef __GNUC__ + styled_ostream__end_use_class (first_arg,classname); + #endif +} + + +const struct styled_ostream_implementation styled_ostream_vtable = +{ + styled_ostream_superclasses, + sizeof (styled_ostream_superclasses) / sizeof (styled_ostream_superclasses[0]), + sizeof (struct styled_ostream_representation), + styled_ostream__write_mem, + styled_ostream__flush, + styled_ostream__free, + styled_ostream__begin_use_class, + styled_ostream__end_use_class, +}; + +#if !HAVE_INLINE + +/* Define the functions that invoke the methods. */ + +void +styled_ostream_write_mem (styled_ostream_t first_arg, const void *data, size_t len) +{ + const struct styled_ostream_implementation *vtable = + ((struct styled_ostream_representation_header *) (struct styled_ostream_representation *) first_arg)->vtable; + vtable->write_mem (first_arg,data,len); +} + +void +styled_ostream_flush (styled_ostream_t first_arg) +{ + const struct styled_ostream_implementation *vtable = + ((struct styled_ostream_representation_header *) (struct styled_ostream_representation *) first_arg)->vtable; + vtable->flush (first_arg); +} + +void +styled_ostream_free (styled_ostream_t first_arg) +{ + const struct styled_ostream_implementation *vtable = + ((struct styled_ostream_representation_header *) (struct styled_ostream_representation *) first_arg)->vtable; + vtable->free (first_arg); +} + +void +styled_ostream_begin_use_class (styled_ostream_t first_arg, const char *classname) +{ + const struct styled_ostream_implementation *vtable = + ((struct styled_ostream_representation_header *) (struct styled_ostream_representation *) first_arg)->vtable; + vtable->begin_use_class (first_arg,classname); +} + +void +styled_ostream_end_use_class (styled_ostream_t first_arg, const char *classname) +{ + const struct styled_ostream_implementation *vtable = + ((struct styled_ostream_representation_header *) (struct styled_ostream_representation *) first_arg)->vtable; + vtable->end_use_class (first_arg,classname); +} + +#endif diff --git a/gettext-tools/gnulib-lib/styled-ostream.h b/gettext-tools/gnulib-lib/styled-ostream.h new file mode 100644 index 0000000..9079bf8 --- /dev/null +++ b/gettext-tools/gnulib-lib/styled-ostream.h @@ -0,0 +1,144 @@ +/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ + +#line 1 "styled-ostream.oo.h" +/* Abstract output stream for CSS styled text. + Copyright (C) 2006 Free Software Foundation, Inc. + Written by Bruno Haible , 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _STYLED_OSTREAM_H +#define _STYLED_OSTREAM_H + +#include "ostream.h" + + +/* A styled output stream is an object to which one can feed a sequence of + bytes, marking some runs of text as belonging to specific CSS classes, + where the rendering of the CSS classes is defined through a CSS (cascading + style sheet). */ + +#line 33 "styled-ostream.h" +struct styled_ostream_representation; +/* styled_ostream_t is defined as a pointer to struct styled_ostream_representation. + In C++ mode, we use a smart pointer class. + In C mode, we have no other choice than a typedef to the root class type. */ +#if IS_CPLUSPLUS +struct styled_ostream_t +{ +private: + struct styled_ostream_representation *_pointer; +public: + styled_ostream_t () : _pointer (NULL) {} + styled_ostream_t (struct styled_ostream_representation *pointer) : _pointer (pointer) {} + struct styled_ostream_representation * operator -> () { return _pointer; } + operator struct styled_ostream_representation * () { return _pointer; } + operator struct any_ostream_representation * () { return (struct any_ostream_representation *) _pointer; } + operator void * () { return _pointer; } + bool operator == (const void *p) { return _pointer == p; } + bool operator != (const void *p) { return _pointer != p; } + operator ostream_t () { return (ostream_t) (struct any_ostream_representation *) _pointer; } + explicit styled_ostream_t (ostream_t x) : _pointer ((struct styled_ostream_representation *) (void *) x) {} +}; +#else +typedef ostream_t styled_ostream_t; +#endif + +/* Functions that invoke the methods. */ +extern void styled_ostream_write_mem (styled_ostream_t first_arg, const void *data, size_t len); +extern void styled_ostream_flush (styled_ostream_t first_arg); +extern void styled_ostream_free (styled_ostream_t first_arg); +extern void styled_ostream_begin_use_class (styled_ostream_t first_arg, const char *classname); +extern void styled_ostream_end_use_class (styled_ostream_t first_arg, const char *classname); + +/* Type representing an implementation of styled_ostream_t. */ +struct styled_ostream_implementation +{ + const typeinfo_t * const *superclasses; + size_t superclasses_length; + size_t instance_size; +#define THIS_ARG styled_ostream_t first_arg +#include "styled_ostream.vt.h" +#undef THIS_ARG +}; + +/* Public portion of the object pointed to by a styled_ostream_t. */ +struct styled_ostream_representation_header +{ + const struct styled_ostream_implementation *vtable; +}; + +#if HAVE_INLINE + +/* Define the functions that invoke the methods as inline accesses to + the styled_ostream_implementation. + Use #define to avoid a warning because of extern vs. static. */ + +# define styled_ostream_write_mem styled_ostream_write_mem_inline +static inline void +styled_ostream_write_mem (styled_ostream_t first_arg, const void *data, size_t len) +{ + const struct styled_ostream_implementation *vtable = + ((struct styled_ostream_representation_header *) (struct styled_ostream_representation *) first_arg)->vtable; + vtable->write_mem (first_arg,data,len); +} + +# define styled_ostream_flush styled_ostream_flush_inline +static inline void +styled_ostream_flush (styled_ostream_t first_arg) +{ + const struct styled_ostream_implementation *vtable = + ((struct styled_ostream_representation_header *) (struct styled_ostream_representation *) first_arg)->vtable; + vtable->flush (first_arg); +} + +# define styled_ostream_free styled_ostream_free_inline +static inline void +styled_ostream_free (styled_ostream_t first_arg) +{ + const struct styled_ostream_implementation *vtable = + ((struct styled_ostream_representation_header *) (struct styled_ostream_representation *) first_arg)->vtable; + vtable->free (first_arg); +} + +# define styled_ostream_begin_use_class styled_ostream_begin_use_class_inline +static inline void +styled_ostream_begin_use_class (styled_ostream_t first_arg, const char *classname) +{ + const struct styled_ostream_implementation *vtable = + ((struct styled_ostream_representation_header *) (struct styled_ostream_representation *) first_arg)->vtable; + vtable->begin_use_class (first_arg,classname); +} + +# define styled_ostream_end_use_class styled_ostream_end_use_class_inline +static inline void +styled_ostream_end_use_class (styled_ostream_t first_arg, const char *classname) +{ + const struct styled_ostream_implementation *vtable = + ((struct styled_ostream_representation_header *) (struct styled_ostream_representation *) first_arg)->vtable; + vtable->end_use_class (first_arg,classname); +} + +#endif + +extern DLL_VARIABLE const typeinfo_t styled_ostream_typeinfo; +#define styled_ostream_SUPERCLASSES &styled_ostream_typeinfo, ostream_SUPERCLASSES +#define styled_ostream_SUPERCLASSES_LENGTH (1 + ostream_SUPERCLASSES_LENGTH) + +extern DLL_VARIABLE const struct styled_ostream_implementation styled_ostream_vtable; + +#line 42 "styled-ostream.oo.h" + + +#endif /* _STYLED_OSTREAM_H */ diff --git a/gettext-tools/gnulib-lib/styled-ostream.oo.c b/gettext-tools/gnulib-lib/styled-ostream.oo.c new file mode 100644 index 0000000..9ec3525 --- /dev/null +++ b/gettext-tools/gnulib-lib/styled-ostream.oo.c @@ -0,0 +1,27 @@ +/* Abstract output stream for CSS styled text. + Copyright (C) 2006 Free Software Foundation, Inc. + Written by Bruno Haible , 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include "styled-ostream.h" + + +struct styled_ostream : struct ostream +{ +fields: +}; diff --git a/gettext-tools/gnulib-lib/styled-ostream.oo.h b/gettext-tools/gnulib-lib/styled-ostream.oo.h new file mode 100644 index 0000000..944c191 --- /dev/null +++ b/gettext-tools/gnulib-lib/styled-ostream.oo.h @@ -0,0 +1,44 @@ +/* Abstract output stream for CSS styled text. + Copyright (C) 2006 Free Software Foundation, Inc. + Written by Bruno Haible , 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _STYLED_OSTREAM_H +#define _STYLED_OSTREAM_H + +#include "ostream.h" + + +/* A styled output stream is an object to which one can feed a sequence of + bytes, marking some runs of text as belonging to specific CSS classes, + where the rendering of the CSS classes is defined through a CSS (cascading + style sheet). */ + +struct styled_ostream : struct ostream +{ +methods: + + /* Start a run of text belonging to CLASSNAME. The CLASSNAME is the name + of a CSS class. It can be chosen arbitrarily and customized through + an inline or external CSS. */ + void begin_use_class (styled_ostream_t stream, const char *classname); + + /* End a run of text belonging to CLASSNAME. + The begin_use_class / end_use_class calls must match properly. */ + void end_use_class (styled_ostream_t stream, const char *classname); +}; + + +#endif /* _STYLED_OSTREAM_H */ diff --git a/gettext-tools/gnulib-lib/styled_ostream.priv.h b/gettext-tools/gnulib-lib/styled_ostream.priv.h new file mode 100644 index 0000000..7436bff --- /dev/null +++ b/gettext-tools/gnulib-lib/styled_ostream.priv.h @@ -0,0 +1,10 @@ +/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ + +/* Field layout of superclass. */ +#include "ostream.priv.h" + +/* Field layout of styled_ostream class. */ +struct styled_ostream_representation +{ + struct ostream_representation base; +}; diff --git a/gettext-tools/gnulib-lib/styled_ostream.vt.h b/gettext-tools/gnulib-lib/styled_ostream.vt.h new file mode 100644 index 0000000..0a9dddf --- /dev/null +++ b/gettext-tools/gnulib-lib/styled_ostream.vt.h @@ -0,0 +1,8 @@ +/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ + +/* Virtual function table layout of superclass. */ +#include "ostream.vt.h" + +/* Virtual function table layout of styled_ostream class. */ + void (*begin_use_class) (THIS_ARG, const char *classname); + void (*end_use_class) (THIS_ARG, const char *classname); diff --git a/gettext-tools/gnulib-lib/sys_select.in.h b/gettext-tools/gnulib-lib/sys_select.in.h new file mode 100644 index 0000000..58508b0 --- /dev/null +++ b/gettext-tools/gnulib-lib/sys_select.in.h @@ -0,0 +1,314 @@ +/* Substitute for . + Copyright (C) 2007-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . */ + +# if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +# endif +@PRAGMA_COLUMNS@ + +/* On OSF/1 and Solaris 2.6, and + both include . + On Cygwin, includes . + Simply delegate to the system's header in this case. */ +#if (@HAVE_SYS_SELECT_H@ \ + && !defined _GL_SYS_SELECT_H_REDIRECT_FROM_SYS_TYPES_H \ + && ((defined __osf__ && defined _SYS_TYPES_H_ \ + && defined _OSF_SOURCE) \ + || (defined __sun && defined _SYS_TYPES_H \ + && (! (defined _XOPEN_SOURCE || defined _POSIX_C_SOURCE) \ + || defined __EXTENSIONS__)))) + +# define _GL_SYS_SELECT_H_REDIRECT_FROM_SYS_TYPES_H +# @INCLUDE_NEXT@ @NEXT_SYS_SELECT_H@ + +#elif (@HAVE_SYS_SELECT_H@ \ + && (defined _CYGWIN_SYS_TIME_H \ + || (!defined _GL_SYS_SELECT_H_REDIRECT_FROM_SYS_TIME_H \ + && ((defined __osf__ && defined _SYS_TIME_H_ \ + && defined _OSF_SOURCE) \ + || (defined __sun && defined _SYS_TIME_H \ + && (! (defined _XOPEN_SOURCE \ + || defined _POSIX_C_SOURCE) \ + || defined __EXTENSIONS__)))))) + +# define _GL_SYS_SELECT_H_REDIRECT_FROM_SYS_TIME_H +# @INCLUDE_NEXT@ @NEXT_SYS_SELECT_H@ + +/* On IRIX 6.5, includes , which includes + , which includes . At this point we cannot + include , because that includes , which + gives a syntax error because has not been completely + processed. Simply delegate to the system's header in this case. */ +#elif @HAVE_SYS_SELECT_H@ && defined __sgi && (defined _SYS_BSD_TYPES_H && !defined _GL_SYS_SELECT_H_REDIRECT_FROM_SYS_BSD_TYPES_H) + +# define _GL_SYS_SELECT_H_REDIRECT_FROM_SYS_BSD_TYPES_H +# @INCLUDE_NEXT@ @NEXT_SYS_SELECT_H@ + +/* On OpenBSD 5.0, includes , which includes + . At this point we cannot include , because that + includes gnulib's pthread.h override, which gives a syntax error because + /usr/include/pthread.h has not been completely processed. Simply delegate + to the system's header in this case. */ +#elif @HAVE_SYS_SELECT_H@ && defined __OpenBSD__ && (defined _PTHREAD_H_ && !defined PTHREAD_MUTEX_INITIALIZER) + +# @INCLUDE_NEXT@ @NEXT_SYS_SELECT_H@ + +#else + +#ifndef _@GUARD_PREFIX@_SYS_SELECT_H + +/* On many platforms, assumes prior inclusion of + . Also, mingw defines sigset_t there, instead of + in where it belongs. */ +#include + +#if @HAVE_SYS_SELECT_H@ + +/* On OSF/1 4.0, provides only a forward declaration + of 'struct timeval', and no definition of this type. + Also, Mac OS X, AIX, HP-UX, IRIX, Solaris, Interix declare select() + in . + But avoid namespace pollution on glibc systems. */ +# ifndef __GLIBC__ +# include +# endif + +/* On AIX 7 and Solaris 10, provides an FD_ZERO implementation + that relies on memset(), but without including . + But in any case avoid namespace pollution on glibc systems. */ +# if (defined __OpenBSD__ || defined _AIX || defined __sun || defined __osf__ || defined __BEOS__) \ + && ! defined __GLIBC__ +# include +# endif + +/* The include_next requires a split double-inclusion guard. */ +# @INCLUDE_NEXT@ @NEXT_SYS_SELECT_H@ + +#endif + +/* Get definition of 'sigset_t'. + But avoid namespace pollution on glibc systems. + Do this after the include_next (for the sake of OpenBSD 5.0) but before + the split double-inclusion guard (for the sake of Solaris). */ +#if !(defined __GLIBC__ && !defined __UCLIBC__) +# include +#endif + +#ifndef _@GUARD_PREFIX@_SYS_SELECT_H +#define _@GUARD_PREFIX@_SYS_SELECT_H + +#if !@HAVE_SYS_SELECT_H@ +/* A platform that lacks . */ +/* Get the 'struct timeval' and 'fd_set' types and the FD_* macros + on most platforms. */ +# include +/* On HP-UX 11, provides an FD_ZERO implementation + that relies on memset(), but without including . */ +# if defined __hpux +# include +# endif +/* On native Windows platforms: + Get the 'fd_set' type. + Get the close() declaration before we override it. */ +# if @HAVE_WINSOCK2_H@ +# if !defined _GL_INCLUDING_WINSOCK2_H +# define _GL_INCLUDING_WINSOCK2_H +# include +# undef _GL_INCLUDING_WINSOCK2_H +# endif +# include +# endif +#endif + +/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ + +/* The definition of _GL_WARN_ON_USE is copied here. */ + + +/* Fix some definitions from . */ + +#if @HAVE_WINSOCK2_H@ + +# if !GNULIB_defined_rpl_fd_isset + +/* Re-define FD_ISSET to avoid a WSA call while we are not using + network sockets. */ +static int +rpl_fd_isset (SOCKET fd, fd_set * set) +{ + u_int i; + if (set == NULL) + return 0; + + for (i = 0; i < set->fd_count; i++) + if (set->fd_array[i] == fd) + return 1; + + return 0; +} + +# define GNULIB_defined_rpl_fd_isset 1 +# endif + +# undef FD_ISSET +# define FD_ISSET(fd, set) rpl_fd_isset(fd, set) + +#endif + +/* Hide some function declarations from . */ + +#if @HAVE_WINSOCK2_H@ +# if !defined _@GUARD_PREFIX@_UNISTD_H +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef close +# define close close_used_without_including_unistd_h +# else + _GL_WARN_ON_USE (close, + "close() used without including "); +# endif +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef gethostname +# define gethostname gethostname_used_without_including_unistd_h +# else + _GL_WARN_ON_USE (gethostname, + "gethostname() used without including "); +# endif +# endif +# if !defined _@GUARD_PREFIX@_SYS_SOCKET_H +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef socket +# define socket socket_used_without_including_sys_socket_h +# undef connect +# define connect connect_used_without_including_sys_socket_h +# undef accept +# define accept accept_used_without_including_sys_socket_h +# undef bind +# define bind bind_used_without_including_sys_socket_h +# undef getpeername +# define getpeername getpeername_used_without_including_sys_socket_h +# undef getsockname +# define getsockname getsockname_used_without_including_sys_socket_h +# undef getsockopt +# define getsockopt getsockopt_used_without_including_sys_socket_h +# undef listen +# define listen listen_used_without_including_sys_socket_h +# undef recv +# define recv recv_used_without_including_sys_socket_h +# undef send +# define send send_used_without_including_sys_socket_h +# undef recvfrom +# define recvfrom recvfrom_used_without_including_sys_socket_h +# undef sendto +# define sendto sendto_used_without_including_sys_socket_h +# undef setsockopt +# define setsockopt setsockopt_used_without_including_sys_socket_h +# undef shutdown +# define shutdown shutdown_used_without_including_sys_socket_h +# else + _GL_WARN_ON_USE (socket, + "socket() used without including "); + _GL_WARN_ON_USE (connect, + "connect() used without including "); + _GL_WARN_ON_USE (accept, + "accept() used without including "); + _GL_WARN_ON_USE (bind, + "bind() used without including "); + _GL_WARN_ON_USE (getpeername, + "getpeername() used without including "); + _GL_WARN_ON_USE (getsockname, + "getsockname() used without including "); + _GL_WARN_ON_USE (getsockopt, + "getsockopt() used without including "); + _GL_WARN_ON_USE (listen, + "listen() used without including "); + _GL_WARN_ON_USE (recv, + "recv() used without including "); + _GL_WARN_ON_USE (send, + "send() used without including "); + _GL_WARN_ON_USE (recvfrom, + "recvfrom() used without including "); + _GL_WARN_ON_USE (sendto, + "sendto() used without including "); + _GL_WARN_ON_USE (setsockopt, + "setsockopt() used without including "); + _GL_WARN_ON_USE (shutdown, + "shutdown() used without including "); +# endif +# endif +#endif + + +#if @GNULIB_PSELECT@ +# if @REPLACE_PSELECT@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef pselect +# define pselect rpl_pselect +# endif +_GL_FUNCDECL_RPL (pselect, int, + (int, fd_set *restrict, fd_set *restrict, fd_set *restrict, + struct timespec const *restrict, const sigset_t *restrict)); +_GL_CXXALIAS_RPL (pselect, int, + (int, fd_set *restrict, fd_set *restrict, fd_set *restrict, + struct timespec const *restrict, const sigset_t *restrict)); +# else +# if !@HAVE_PSELECT@ +_GL_FUNCDECL_SYS (pselect, int, + (int, fd_set *restrict, fd_set *restrict, fd_set *restrict, + struct timespec const *restrict, const sigset_t *restrict)); +# endif +_GL_CXXALIAS_SYS (pselect, int, + (int, fd_set *restrict, fd_set *restrict, fd_set *restrict, + struct timespec const *restrict, const sigset_t *restrict)); +# endif +_GL_CXXALIASWARN (pselect); +#elif defined GNULIB_POSIXCHECK +# undef pselect +# if HAVE_RAW_DECL_PSELECT +_GL_WARN_ON_USE (pselect, "pselect is not portable - " + "use gnulib module pselect for portability"); +# endif +#endif + +#if @GNULIB_SELECT@ +# if @REPLACE_SELECT@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef select +# define select rpl_select +# endif +_GL_FUNCDECL_RPL (select, int, + (int, fd_set *, fd_set *, fd_set *, struct timeval *)); +_GL_CXXALIAS_RPL (select, int, + (int, fd_set *, fd_set *, fd_set *, struct timeval *)); +# else +_GL_CXXALIAS_SYS (select, int, + (int, fd_set *, fd_set *, fd_set *, struct timeval *)); +# endif +_GL_CXXALIASWARN (select); +#elif @HAVE_WINSOCK2_H@ +# undef select +# define select select_used_without_requesting_gnulib_module_select +#elif defined GNULIB_POSIXCHECK +# undef select +# if HAVE_RAW_DECL_SELECT +_GL_WARN_ON_USE (select, "select is not always POSIX compliant - " + "use gnulib module select for portability"); +# endif +#endif + + +#endif /* _@GUARD_PREFIX@_SYS_SELECT_H */ +#endif /* _@GUARD_PREFIX@_SYS_SELECT_H */ +#endif /* OSF/1 */ diff --git a/gettext-tools/gnulib-lib/sys_stat.in.h b/gettext-tools/gnulib-lib/sys_stat.in.h new file mode 100644 index 0000000..b47a7ff --- /dev/null +++ b/gettext-tools/gnulib-lib/sys_stat.in.h @@ -0,0 +1,732 @@ +/* Provide a more complete sys/stat header file. + Copyright (C) 2005-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . */ + +/* Written by Eric Blake, Paul Eggert, and Jim Meyering. */ + +/* This file is supposed to be used on platforms where is + incomplete. It is intended to provide definitions and prototypes + needed by an application. Start with what the system provides. */ + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +#if defined __need_system_sys_stat_h +/* Special invocation convention. */ + +#@INCLUDE_NEXT@ @NEXT_SYS_STAT_H@ + +#else +/* Normal invocation convention. */ + +#ifndef _@GUARD_PREFIX@_SYS_STAT_H + +/* Get nlink_t. + May also define off_t to a 64-bit type on native Windows. */ +#include + +/* Get struct timespec. */ +#include + +/* The include_next requires a split double-inclusion guard. */ +#@INCLUDE_NEXT@ @NEXT_SYS_STAT_H@ + +#ifndef _@GUARD_PREFIX@_SYS_STAT_H +#define _@GUARD_PREFIX@_SYS_STAT_H + +/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ + +/* The definition of _GL_ARG_NONNULL is copied here. */ + +/* The definition of _GL_WARN_ON_USE is copied here. */ + +/* Before doing "#define mkdir rpl_mkdir" below, we need to include all + headers that may declare mkdir(). Native Windows platforms declare mkdir + in and/or , not in . */ +#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ +# include /* mingw32, mingw64 */ +# include /* mingw64, MSVC 9 */ +#endif + +/* Native Windows platforms declare umask() in . */ +#if 0 && ((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__) +# include +#endif + +/* Large File Support on native Windows. */ +#if @WINDOWS_64_BIT_ST_SIZE@ +# define stat _stati64 +#endif + +#ifndef S_IFIFO +# ifdef _S_IFIFO +# define S_IFIFO _S_IFIFO +# endif +#endif + +#ifndef S_IFMT +# define S_IFMT 0170000 +#endif + +#if STAT_MACROS_BROKEN +# undef S_ISBLK +# undef S_ISCHR +# undef S_ISDIR +# undef S_ISFIFO +# undef S_ISLNK +# undef S_ISNAM +# undef S_ISMPB +# undef S_ISMPC +# undef S_ISNWK +# undef S_ISREG +# undef S_ISSOCK +#endif + +#ifndef S_ISBLK +# ifdef S_IFBLK +# define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) +# else +# define S_ISBLK(m) 0 +# endif +#endif + +#ifndef S_ISCHR +# ifdef S_IFCHR +# define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) +# else +# define S_ISCHR(m) 0 +# endif +#endif + +#ifndef S_ISDIR +# ifdef S_IFDIR +# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) +# else +# define S_ISDIR(m) 0 +# endif +#endif + +#ifndef S_ISDOOR /* Solaris 2.5 and up */ +# define S_ISDOOR(m) 0 +#endif + +#ifndef S_ISFIFO +# ifdef S_IFIFO +# define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) +# else +# define S_ISFIFO(m) 0 +# endif +#endif + +#ifndef S_ISLNK +# ifdef S_IFLNK +# define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) +# else +# define S_ISLNK(m) 0 +# endif +#endif + +#ifndef S_ISMPB /* V7 */ +# ifdef S_IFMPB +# define S_ISMPB(m) (((m) & S_IFMT) == S_IFMPB) +# define S_ISMPC(m) (((m) & S_IFMT) == S_IFMPC) +# else +# define S_ISMPB(m) 0 +# define S_ISMPC(m) 0 +# endif +#endif + +#ifndef S_ISMPX /* AIX */ +# define S_ISMPX(m) 0 +#endif + +#ifndef S_ISNAM /* Xenix */ +# ifdef S_IFNAM +# define S_ISNAM(m) (((m) & S_IFMT) == S_IFNAM) +# else +# define S_ISNAM(m) 0 +# endif +#endif + +#ifndef S_ISNWK /* HP/UX */ +# ifdef S_IFNWK +# define S_ISNWK(m) (((m) & S_IFMT) == S_IFNWK) +# else +# define S_ISNWK(m) 0 +# endif +#endif + +#ifndef S_ISPORT /* Solaris 10 and up */ +# define S_ISPORT(m) 0 +#endif + +#ifndef S_ISREG +# ifdef S_IFREG +# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) +# else +# define S_ISREG(m) 0 +# endif +#endif + +#ifndef S_ISSOCK +# ifdef S_IFSOCK +# define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) +# else +# define S_ISSOCK(m) 0 +# endif +#endif + + +#ifndef S_TYPEISMQ +# define S_TYPEISMQ(p) 0 +#endif + +#ifndef S_TYPEISTMO +# define S_TYPEISTMO(p) 0 +#endif + + +#ifndef S_TYPEISSEM +# ifdef S_INSEM +# define S_TYPEISSEM(p) (S_ISNAM ((p)->st_mode) && (p)->st_rdev == S_INSEM) +# else +# define S_TYPEISSEM(p) 0 +# endif +#endif + +#ifndef S_TYPEISSHM +# ifdef S_INSHD +# define S_TYPEISSHM(p) (S_ISNAM ((p)->st_mode) && (p)->st_rdev == S_INSHD) +# else +# define S_TYPEISSHM(p) 0 +# endif +#endif + +/* high performance ("contiguous data") */ +#ifndef S_ISCTG +# define S_ISCTG(p) 0 +#endif + +/* Cray DMF (data migration facility): off line, with data */ +#ifndef S_ISOFD +# define S_ISOFD(p) 0 +#endif + +/* Cray DMF (data migration facility): off line, with no data */ +#ifndef S_ISOFL +# define S_ISOFL(p) 0 +#endif + +/* 4.4BSD whiteout */ +#ifndef S_ISWHT +# define S_ISWHT(m) 0 +#endif + +/* If any of the following are undefined, + define them to their de facto standard values. */ +#if !S_ISUID +# define S_ISUID 04000 +#endif +#if !S_ISGID +# define S_ISGID 02000 +#endif + +/* S_ISVTX is a common extension to POSIX. */ +#ifndef S_ISVTX +# define S_ISVTX 01000 +#endif + +#if !S_IRUSR && S_IREAD +# define S_IRUSR S_IREAD +#endif +#if !S_IRUSR +# define S_IRUSR 00400 +#endif +#if !S_IRGRP +# define S_IRGRP (S_IRUSR >> 3) +#endif +#if !S_IROTH +# define S_IROTH (S_IRUSR >> 6) +#endif + +#if !S_IWUSR && S_IWRITE +# define S_IWUSR S_IWRITE +#endif +#if !S_IWUSR +# define S_IWUSR 00200 +#endif +#if !S_IWGRP +# define S_IWGRP (S_IWUSR >> 3) +#endif +#if !S_IWOTH +# define S_IWOTH (S_IWUSR >> 6) +#endif + +#if !S_IXUSR && S_IEXEC +# define S_IXUSR S_IEXEC +#endif +#if !S_IXUSR +# define S_IXUSR 00100 +#endif +#if !S_IXGRP +# define S_IXGRP (S_IXUSR >> 3) +#endif +#if !S_IXOTH +# define S_IXOTH (S_IXUSR >> 6) +#endif + +#if !S_IRWXU +# define S_IRWXU (S_IRUSR | S_IWUSR | S_IXUSR) +#endif +#if !S_IRWXG +# define S_IRWXG (S_IRGRP | S_IWGRP | S_IXGRP) +#endif +#if !S_IRWXO +# define S_IRWXO (S_IROTH | S_IWOTH | S_IXOTH) +#endif + +/* S_IXUGO is a common extension to POSIX. */ +#if !S_IXUGO +# define S_IXUGO (S_IXUSR | S_IXGRP | S_IXOTH) +#endif + +#ifndef S_IRWXUGO +# define S_IRWXUGO (S_IRWXU | S_IRWXG | S_IRWXO) +#endif + +/* Macros for futimens and utimensat. */ +#ifndef UTIME_NOW +# define UTIME_NOW (-1) +# define UTIME_OMIT (-2) +#endif + + +#if @GNULIB_FCHMODAT@ +# if !@HAVE_FCHMODAT@ +_GL_FUNCDECL_SYS (fchmodat, int, + (int fd, char const *file, mode_t mode, int flag) + _GL_ARG_NONNULL ((2))); +# endif +_GL_CXXALIAS_SYS (fchmodat, int, + (int fd, char const *file, mode_t mode, int flag)); +_GL_CXXALIASWARN (fchmodat); +#elif defined GNULIB_POSIXCHECK +# undef fchmodat +# if HAVE_RAW_DECL_FCHMODAT +_GL_WARN_ON_USE (fchmodat, "fchmodat is not portable - " + "use gnulib module openat for portability"); +# endif +#endif + + +#if @GNULIB_FSTAT@ +# if @REPLACE_FSTAT@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef fstat +# define fstat rpl_fstat +# endif +_GL_FUNCDECL_RPL (fstat, int, (int fd, struct stat *buf) _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (fstat, int, (int fd, struct stat *buf)); +# else +_GL_CXXALIAS_SYS (fstat, int, (int fd, struct stat *buf)); +# endif +_GL_CXXALIASWARN (fstat); +#elif @WINDOWS_64_BIT_ST_SIZE@ +/* Above, we define stat to _stati64. */ +# define fstat _fstati64 +#elif defined GNULIB_POSIXCHECK +# undef fstat +# if HAVE_RAW_DECL_FSTAT +_GL_WARN_ON_USE (fstat, "fstat has portability problems - " + "use gnulib module fstat for portability"); +# endif +#endif + + +#if @GNULIB_FSTATAT@ +# if @REPLACE_FSTATAT@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef fstatat +# define fstatat rpl_fstatat +# endif +_GL_FUNCDECL_RPL (fstatat, int, + (int fd, char const *name, struct stat *st, int flags) + _GL_ARG_NONNULL ((2, 3))); +_GL_CXXALIAS_RPL (fstatat, int, + (int fd, char const *name, struct stat *st, int flags)); +# else +# if !@HAVE_FSTATAT@ +_GL_FUNCDECL_SYS (fstatat, int, + (int fd, char const *name, struct stat *st, int flags) + _GL_ARG_NONNULL ((2, 3))); +# endif +_GL_CXXALIAS_SYS (fstatat, int, + (int fd, char const *name, struct stat *st, int flags)); +# endif +_GL_CXXALIASWARN (fstatat); +#elif defined GNULIB_POSIXCHECK +# undef fstatat +# if HAVE_RAW_DECL_FSTATAT +_GL_WARN_ON_USE (fstatat, "fstatat is not portable - " + "use gnulib module openat for portability"); +# endif +#endif + + +#if @GNULIB_FUTIMENS@ +/* Use the rpl_ prefix also on Solaris <= 9, because on Solaris 9 our futimens + implementation relies on futimesat, which on Solaris 10 makes an invocation + to futimens that is meant to invoke the libc's futimens(), not gnulib's + futimens(). */ +# if @REPLACE_FUTIMENS@ || (!@HAVE_FUTIMENS@ && defined __sun) +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef futimens +# define futimens rpl_futimens +# endif +_GL_FUNCDECL_RPL (futimens, int, (int fd, struct timespec const times[2])); +_GL_CXXALIAS_RPL (futimens, int, (int fd, struct timespec const times[2])); +# else +# if !@HAVE_FUTIMENS@ +_GL_FUNCDECL_SYS (futimens, int, (int fd, struct timespec const times[2])); +# endif +_GL_CXXALIAS_SYS (futimens, int, (int fd, struct timespec const times[2])); +# endif +# if @HAVE_FUTIMENS@ +_GL_CXXALIASWARN (futimens); +# endif +#elif defined GNULIB_POSIXCHECK +# undef futimens +# if HAVE_RAW_DECL_FUTIMENS +_GL_WARN_ON_USE (futimens, "futimens is not portable - " + "use gnulib module futimens for portability"); +# endif +#endif + + +#if @GNULIB_LCHMOD@ +/* Change the mode of FILENAME to MODE, without dereferencing it if FILENAME + denotes a symbolic link. */ +# if !@HAVE_LCHMOD@ +/* The lchmod replacement follows symbolic links. Callers should take + this into account; lchmod should be applied only to arguments that + are known to not be symbolic links. On hosts that lack lchmod, + this can lead to race conditions between the check and the + invocation of lchmod, but we know of no workarounds that are + reliable in general. You might try requesting support for lchmod + from your operating system supplier. */ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define lchmod chmod +# endif +/* Need to cast, because on mingw, the second parameter of chmod is + int mode. */ +_GL_CXXALIAS_RPL_CAST_1 (lchmod, chmod, int, + (const char *filename, mode_t mode)); +# else +# if 0 /* assume already declared */ +_GL_FUNCDECL_SYS (lchmod, int, (const char *filename, mode_t mode) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (lchmod, int, (const char *filename, mode_t mode)); +# endif +# if @HAVE_LCHMOD@ +_GL_CXXALIASWARN (lchmod); +# endif +#elif defined GNULIB_POSIXCHECK +# undef lchmod +# if HAVE_RAW_DECL_LCHMOD +_GL_WARN_ON_USE (lchmod, "lchmod is unportable - " + "use gnulib module lchmod for portability"); +# endif +#endif + + +#if @GNULIB_LSTAT@ +# if ! @HAVE_LSTAT@ +/* mingw does not support symlinks, therefore it does not have lstat. But + without links, stat does just fine. */ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define lstat stat +# endif +_GL_CXXALIAS_RPL_1 (lstat, stat, int, (const char *name, struct stat *buf)); +# elif @REPLACE_LSTAT@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef lstat +# define lstat rpl_lstat +# endif +_GL_FUNCDECL_RPL (lstat, int, (const char *name, struct stat *buf) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (lstat, int, (const char *name, struct stat *buf)); +# else +_GL_CXXALIAS_SYS (lstat, int, (const char *name, struct stat *buf)); +# endif +# if @HAVE_LSTAT@ +_GL_CXXALIASWARN (lstat); +# endif +#elif defined GNULIB_POSIXCHECK +# undef lstat +# if HAVE_RAW_DECL_LSTAT +_GL_WARN_ON_USE (lstat, "lstat is unportable - " + "use gnulib module lstat for portability"); +# endif +#endif + + +#if @REPLACE_MKDIR@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef mkdir +# define mkdir rpl_mkdir +# endif +_GL_FUNCDECL_RPL (mkdir, int, (char const *name, mode_t mode) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (mkdir, int, (char const *name, mode_t mode)); +#else +/* mingw's _mkdir() function has 1 argument, but we pass 2 arguments. + Additionally, it declares _mkdir (and depending on compile flags, an + alias mkdir), only in the nonstandard includes and , + which are included above. */ +# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ + +# if !GNULIB_defined_rpl_mkdir +static int +rpl_mkdir (char const *name, mode_t mode) +{ + return _mkdir (name); +} +# define GNULIB_defined_rpl_mkdir 1 +# endif + +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define mkdir rpl_mkdir +# endif +_GL_CXXALIAS_RPL (mkdir, int, (char const *name, mode_t mode)); +# else +_GL_CXXALIAS_SYS (mkdir, int, (char const *name, mode_t mode)); +# endif +#endif +_GL_CXXALIASWARN (mkdir); + + +#if @GNULIB_MKDIRAT@ +# if !@HAVE_MKDIRAT@ +_GL_FUNCDECL_SYS (mkdirat, int, (int fd, char const *file, mode_t mode) + _GL_ARG_NONNULL ((2))); +# endif +_GL_CXXALIAS_SYS (mkdirat, int, (int fd, char const *file, mode_t mode)); +_GL_CXXALIASWARN (mkdirat); +#elif defined GNULIB_POSIXCHECK +# undef mkdirat +# if HAVE_RAW_DECL_MKDIRAT +_GL_WARN_ON_USE (mkdirat, "mkdirat is not portable - " + "use gnulib module openat for portability"); +# endif +#endif + + +#if @GNULIB_MKFIFO@ +# if @REPLACE_MKFIFO@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef mkfifo +# define mkfifo rpl_mkfifo +# endif +_GL_FUNCDECL_RPL (mkfifo, int, (char const *file, mode_t mode) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (mkfifo, int, (char const *file, mode_t mode)); +# else +# if !@HAVE_MKFIFO@ +_GL_FUNCDECL_SYS (mkfifo, int, (char const *file, mode_t mode) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (mkfifo, int, (char const *file, mode_t mode)); +# endif +_GL_CXXALIASWARN (mkfifo); +#elif defined GNULIB_POSIXCHECK +# undef mkfifo +# if HAVE_RAW_DECL_MKFIFO +_GL_WARN_ON_USE (mkfifo, "mkfifo is not portable - " + "use gnulib module mkfifo for portability"); +# endif +#endif + + +#if @GNULIB_MKFIFOAT@ +# if !@HAVE_MKFIFOAT@ +_GL_FUNCDECL_SYS (mkfifoat, int, (int fd, char const *file, mode_t mode) + _GL_ARG_NONNULL ((2))); +# endif +_GL_CXXALIAS_SYS (mkfifoat, int, (int fd, char const *file, mode_t mode)); +_GL_CXXALIASWARN (mkfifoat); +#elif defined GNULIB_POSIXCHECK +# undef mkfifoat +# if HAVE_RAW_DECL_MKFIFOAT +_GL_WARN_ON_USE (mkfifoat, "mkfifoat is not portable - " + "use gnulib module mkfifoat for portability"); +# endif +#endif + + +#if @GNULIB_MKNOD@ +# if @REPLACE_MKNOD@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef mknod +# define mknod rpl_mknod +# endif +_GL_FUNCDECL_RPL (mknod, int, (char const *file, mode_t mode, dev_t dev) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (mknod, int, (char const *file, mode_t mode, dev_t dev)); +# else +# if !@HAVE_MKNOD@ +_GL_FUNCDECL_SYS (mknod, int, (char const *file, mode_t mode, dev_t dev) + _GL_ARG_NONNULL ((1))); +# endif +/* Need to cast, because on OSF/1 5.1, the third parameter is '...'. */ +_GL_CXXALIAS_SYS_CAST (mknod, int, (char const *file, mode_t mode, dev_t dev)); +# endif +_GL_CXXALIASWARN (mknod); +#elif defined GNULIB_POSIXCHECK +# undef mknod +# if HAVE_RAW_DECL_MKNOD +_GL_WARN_ON_USE (mknod, "mknod is not portable - " + "use gnulib module mknod for portability"); +# endif +#endif + + +#if @GNULIB_MKNODAT@ +# if !@HAVE_MKNODAT@ +_GL_FUNCDECL_SYS (mknodat, int, + (int fd, char const *file, mode_t mode, dev_t dev) + _GL_ARG_NONNULL ((2))); +# endif +_GL_CXXALIAS_SYS (mknodat, int, + (int fd, char const *file, mode_t mode, dev_t dev)); +_GL_CXXALIASWARN (mknodat); +#elif defined GNULIB_POSIXCHECK +# undef mknodat +# if HAVE_RAW_DECL_MKNODAT +_GL_WARN_ON_USE (mknodat, "mknodat is not portable - " + "use gnulib module mkfifoat for portability"); +# endif +#endif + + +#if @GNULIB_STAT@ +# if @REPLACE_STAT@ +/* We can't use the object-like #define stat rpl_stat, because of + struct stat. This means that rpl_stat will not be used if the user + does (stat)(a,b). Oh well. */ +# if defined _AIX && defined stat && defined _LARGE_FILES + /* With _LARGE_FILES defined, AIX (only) defines stat to stat64, + so we have to replace stat64() instead of stat(). */ +# undef stat64 +# define stat64(name, st) rpl_stat (name, st) +# elif @WINDOWS_64_BIT_ST_SIZE@ + /* Above, we define stat to _stati64. */ +# if defined __MINGW32__ && defined _stati64 +# ifndef _USE_32BIT_TIME_T + /* The system headers define _stati64 to _stat64. */ +# undef _stat64 +# define _stat64(name, st) rpl_stat (name, st) +# endif +# elif defined _MSC_VER && defined _stati64 +# ifdef _USE_32BIT_TIME_T + /* The system headers define _stati64 to _stat32i64. */ +# undef _stat32i64 +# define _stat32i64(name, st) rpl_stat (name, st) +# else + /* The system headers define _stati64 to _stat64. */ +# undef _stat64 +# define _stat64(name, st) rpl_stat (name, st) +# endif +# else +# undef _stati64 +# define _stati64(name, st) rpl_stat (name, st) +# endif +# elif defined __MINGW32__ && defined stat +# ifdef _USE_32BIT_TIME_T + /* The system headers define stat to _stat32i64. */ +# undef _stat32i64 +# define _stat32i64(name, st) rpl_stat (name, st) +# else + /* The system headers define stat to _stat64. */ +# undef _stat64 +# define _stat64(name, st) rpl_stat (name, st) +# endif +# elif defined _MSC_VER && defined stat +# ifdef _USE_32BIT_TIME_T + /* The system headers define stat to _stat32. */ +# undef _stat32 +# define _stat32(name, st) rpl_stat (name, st) +# else + /* The system headers define stat to _stat64i32. */ +# undef _stat64i32 +# define _stat64i32(name, st) rpl_stat (name, st) +# endif +# else /* !(_AIX ||__MINGW32__ || _MSC_VER) */ +# undef stat +# define stat(name, st) rpl_stat (name, st) +# endif /* !_LARGE_FILES */ +_GL_EXTERN_C int stat (const char *name, struct stat *buf) + _GL_ARG_NONNULL ((1, 2)); +# endif +#elif defined GNULIB_POSIXCHECK +# undef stat +# if HAVE_RAW_DECL_STAT +_GL_WARN_ON_USE (stat, "stat is unportable - " + "use gnulib module stat for portability"); +# endif +#endif + + +#if @GNULIB_UTIMENSAT@ +/* Use the rpl_ prefix also on Solaris <= 9, because on Solaris 9 our utimensat + implementation relies on futimesat, which on Solaris 10 makes an invocation + to utimensat that is meant to invoke the libc's utimensat(), not gnulib's + utimensat(). */ +# if @REPLACE_UTIMENSAT@ || (!@HAVE_UTIMENSAT@ && defined __sun) +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef utimensat +# define utimensat rpl_utimensat +# endif +_GL_FUNCDECL_RPL (utimensat, int, (int fd, char const *name, + struct timespec const times[2], int flag) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (utimensat, int, (int fd, char const *name, + struct timespec const times[2], int flag)); +# else +# if !@HAVE_UTIMENSAT@ +_GL_FUNCDECL_SYS (utimensat, int, (int fd, char const *name, + struct timespec const times[2], int flag) + _GL_ARG_NONNULL ((2))); +# endif +_GL_CXXALIAS_SYS (utimensat, int, (int fd, char const *name, + struct timespec const times[2], int flag)); +# endif +# if @HAVE_UTIMENSAT@ +_GL_CXXALIASWARN (utimensat); +# endif +#elif defined GNULIB_POSIXCHECK +# undef utimensat +# if HAVE_RAW_DECL_UTIMENSAT +_GL_WARN_ON_USE (utimensat, "utimensat is not portable - " + "use gnulib module utimensat for portability"); +# endif +#endif + + +#endif /* _@GUARD_PREFIX@_SYS_STAT_H */ +#endif /* _@GUARD_PREFIX@_SYS_STAT_H */ +#endif diff --git a/gettext-tools/gnulib-lib/sys_time.in.h b/gettext-tools/gnulib-lib/sys_time.in.h new file mode 100644 index 0000000..30057ad --- /dev/null +++ b/gettext-tools/gnulib-lib/sys_time.in.h @@ -0,0 +1,213 @@ +/* Provide a more complete sys/time.h. + + Copyright (C) 2007-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . */ + +/* Written by Paul Eggert. */ + +#ifndef _@GUARD_PREFIX@_SYS_TIME_H + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +/* On Cygwin and on many BSDish systems, includes itself + recursively via . + Simply delegate to the system's header in this case; it is a no-op. + Without this extra ifdef, the C++ gettimeofday declaration below + would be a forward declaration in gnulib's nested . */ +#if defined _CYGWIN_SYS_TIME_H || defined _SYS_TIME_H || defined _SYS_TIME_H_ +# @INCLUDE_NEXT@ @NEXT_SYS_TIME_H@ +#else + +/* The include_next requires a split double-inclusion guard. */ +#if @HAVE_SYS_TIME_H@ +# @INCLUDE_NEXT@ @NEXT_SYS_TIME_H@ +#endif + +#ifndef _@GUARD_PREFIX@_SYS_TIME_H +#define _@GUARD_PREFIX@_SYS_TIME_H + +#if ! @HAVE_SYS_TIME_H@ +# include +#endif + +/* On native Windows with MSVC, get the 'struct timeval' type. + Also, on native Windows with a 64-bit time_t, where we are overriding the + 'struct timeval' type, get all declarations of system functions whose + signature contains 'struct timeval'. */ +#if (defined _MSC_VER || @REPLACE_STRUCT_TIMEVAL@) && @HAVE_WINSOCK2_H@ && !defined _GL_INCLUDING_WINSOCK2_H +# define _GL_INCLUDING_WINSOCK2_H +# include +# undef _GL_INCLUDING_WINSOCK2_H +#endif + +/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ + +/* The definition of _GL_ARG_NONNULL is copied here. */ + +/* The definition of _GL_WARN_ON_USE is copied here. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !@HAVE_STRUCT_TIMEVAL@ || @REPLACE_STRUCT_TIMEVAL@ + +# if @REPLACE_STRUCT_TIMEVAL@ +# define timeval rpl_timeval +# endif + +# if !GNULIB_defined_struct_timeval +struct timeval +{ + time_t tv_sec; + long int tv_usec; +}; +# define GNULIB_defined_struct_timeval 1 +# endif + +#endif + +#ifdef __cplusplus +} +#endif + +#if @GNULIB_GETTIMEOFDAY@ +# if @REPLACE_GETTIMEOFDAY@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef gettimeofday +# define gettimeofday rpl_gettimeofday +# endif +_GL_FUNCDECL_RPL (gettimeofday, int, + (struct timeval *restrict, void *restrict) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (gettimeofday, int, + (struct timeval *restrict, void *restrict)); +# else +# if !@HAVE_GETTIMEOFDAY@ +_GL_FUNCDECL_SYS (gettimeofday, int, + (struct timeval *restrict, void *restrict) + _GL_ARG_NONNULL ((1))); +# endif +/* Need to cast, because on glibc systems, by default, the second argument is + struct timezone *. */ +_GL_CXXALIAS_SYS_CAST (gettimeofday, int, + (struct timeval *restrict, void *restrict)); +# endif +_GL_CXXALIASWARN (gettimeofday); +#elif defined GNULIB_POSIXCHECK +# undef gettimeofday +# if HAVE_RAW_DECL_GETTIMEOFDAY +_GL_WARN_ON_USE (gettimeofday, "gettimeofday is unportable - " + "use gnulib module gettimeofday for portability"); +# endif +#endif + +/* Hide some function declarations from . */ + +#if defined _MSC_VER && @HAVE_WINSOCK2_H@ +# if !defined _@GUARD_PREFIX@_UNISTD_H +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef close +# define close close_used_without_including_unistd_h +# else + _GL_WARN_ON_USE (close, + "close() used without including "); +# endif +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef gethostname +# define gethostname gethostname_used_without_including_unistd_h +# else + _GL_WARN_ON_USE (gethostname, + "gethostname() used without including "); +# endif +# endif +# if !defined _@GUARD_PREFIX@_SYS_SOCKET_H +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef socket +# define socket socket_used_without_including_sys_socket_h +# undef connect +# define connect connect_used_without_including_sys_socket_h +# undef accept +# define accept accept_used_without_including_sys_socket_h +# undef bind +# define bind bind_used_without_including_sys_socket_h +# undef getpeername +# define getpeername getpeername_used_without_including_sys_socket_h +# undef getsockname +# define getsockname getsockname_used_without_including_sys_socket_h +# undef getsockopt +# define getsockopt getsockopt_used_without_including_sys_socket_h +# undef listen +# define listen listen_used_without_including_sys_socket_h +# undef recv +# define recv recv_used_without_including_sys_socket_h +# undef send +# define send send_used_without_including_sys_socket_h +# undef recvfrom +# define recvfrom recvfrom_used_without_including_sys_socket_h +# undef sendto +# define sendto sendto_used_without_including_sys_socket_h +# undef setsockopt +# define setsockopt setsockopt_used_without_including_sys_socket_h +# undef shutdown +# define shutdown shutdown_used_without_including_sys_socket_h +# else + _GL_WARN_ON_USE (socket, + "socket() used without including "); + _GL_WARN_ON_USE (connect, + "connect() used without including "); + _GL_WARN_ON_USE (accept, + "accept() used without including "); + _GL_WARN_ON_USE (bind, + "bind() used without including "); + _GL_WARN_ON_USE (getpeername, + "getpeername() used without including "); + _GL_WARN_ON_USE (getsockname, + "getsockname() used without including "); + _GL_WARN_ON_USE (getsockopt, + "getsockopt() used without including "); + _GL_WARN_ON_USE (listen, + "listen() used without including "); + _GL_WARN_ON_USE (recv, + "recv() used without including "); + _GL_WARN_ON_USE (send, + "send() used without including "); + _GL_WARN_ON_USE (recvfrom, + "recvfrom() used without including "); + _GL_WARN_ON_USE (sendto, + "sendto() used without including "); + _GL_WARN_ON_USE (setsockopt, + "setsockopt() used without including "); + _GL_WARN_ON_USE (shutdown, + "shutdown() used without including "); +# endif +# endif +# if !defined _@GUARD_PREFIX@_SYS_SELECT_H +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef select +# define select select_used_without_including_sys_select_h +# else + _GL_WARN_ON_USE (select, + "select() used without including "); +# endif +# endif +#endif + +#endif /* _@GUARD_PREFIX@_SYS_TIME_H */ +#endif /* _CYGWIN_SYS_TIME_H */ +#endif /* _@GUARD_PREFIX@_SYS_TIME_H */ diff --git a/gettext-tools/gnulib-lib/sys_types.in.h b/gettext-tools/gnulib-lib/sys_types.in.h new file mode 100644 index 0000000..deb5d67 --- /dev/null +++ b/gettext-tools/gnulib-lib/sys_types.in.h @@ -0,0 +1,53 @@ +/* Provide a more complete sys/types.h. + + Copyright (C) 2011-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . */ + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +#ifndef _@GUARD_PREFIX@_SYS_TYPES_H + +/* The include_next requires a split double-inclusion guard. */ +# define _GL_INCLUDING_SYS_TYPES_H +#@INCLUDE_NEXT@ @NEXT_SYS_TYPES_H@ +# undef _GL_INCLUDING_SYS_TYPES_H + +#ifndef _@GUARD_PREFIX@_SYS_TYPES_H +#define _@GUARD_PREFIX@_SYS_TYPES_H + +/* Override off_t if Large File Support is requested on native Windows. */ +#if @WINDOWS_64_BIT_OFF_T@ +/* Same as int64_t in . */ +# if defined _MSC_VER +# define off_t __int64 +# else +# define off_t long long int +# endif +/* Indicator, for gnulib internal purposes. */ +# define _GL_WINDOWS_64_BIT_OFF_T 1 +#endif + +/* MSVC 9 defines size_t in , not in . */ +/* But avoid namespace pollution on glibc systems. */ +#if ((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__) \ + && ! defined __GLIBC__ +# include +#endif + +#endif /* _@GUARD_PREFIX@_SYS_TYPES_H */ +#endif /* _@GUARD_PREFIX@_SYS_TYPES_H */ diff --git a/gettext-tools/gnulib-lib/sys_wait.in.h b/gettext-tools/gnulib-lib/sys_wait.in.h new file mode 100644 index 0000000..6412af4 --- /dev/null +++ b/gettext-tools/gnulib-lib/sys_wait.in.h @@ -0,0 +1,129 @@ +/* A POSIX-like . + Copyright (C) 2001-2003, 2005-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . */ + + +#ifndef _@GUARD_PREFIX@_SYS_WAIT_H + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +/* The include_next requires a split double-inclusion guard. */ +#if !((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__) +# @INCLUDE_NEXT@ @NEXT_SYS_WAIT_H@ +#endif + +#ifndef _@GUARD_PREFIX@_SYS_WAIT_H +#define _@GUARD_PREFIX@_SYS_WAIT_H + +/* Get pid_t. */ +#include + + +/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ + +/* The definition of _GL_WARN_ON_USE is copied here. */ + + +#if !((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__) +/* Unix API. */ + +/* The following macros apply to an argument x, that is a status of a process, + as returned by waitpid(). + On nearly all systems, including Linux/x86, WEXITSTATUS are bits 15..8 and + WTERMSIG are bits 7..0, while BeOS uses the opposite. Therefore programs + have to use the abstract macros. */ + +/* For valid x, exactly one of WIFSIGNALED(x), WIFEXITED(x), WIFSTOPPED(x) + is true. */ +# ifndef WIFSIGNALED +# define WIFSIGNALED(x) (WTERMSIG (x) != 0 && WTERMSIG(x) != 0x7f) +# endif +# ifndef WIFEXITED +# define WIFEXITED(x) (WTERMSIG (x) == 0) +# endif +# ifndef WIFSTOPPED +# define WIFSTOPPED(x) (WTERMSIG (x) == 0x7f) +# endif + +/* The termination signal. Only to be accessed if WIFSIGNALED(x) is true. */ +# ifndef WTERMSIG +# define WTERMSIG(x) ((x) & 0x7f) +# endif + +/* The exit status. Only to be accessed if WIFEXITED(x) is true. */ +# ifndef WEXITSTATUS +# define WEXITSTATUS(x) (((x) >> 8) & 0xff) +# endif + +/* The stopping signal. Only to be accessed if WIFSTOPPED(x) is true. */ +# ifndef WSTOPSIG +# define WSTOPSIG(x) (((x) >> 8) & 0x7f) +# endif + +/* True if the process dumped core. Not standardized by POSIX. */ +# ifndef WCOREDUMP +# define WCOREDUMP(x) ((x) & 0x80) +# endif + +#else +/* Native Windows API. */ + +# include /* for SIGTERM */ + +/* The following macros apply to an argument x, that is a status of a process, + as returned by waitpid() or, equivalently, _cwait() or GetExitCodeProcess(). + This value is simply an 'int', not composed of bit fields. */ + +/* When an unhandled fatal signal terminates a process, the exit code is 3. */ +# define WIFSIGNALED(x) ((x) == 3) +# define WIFEXITED(x) ((x) != 3) +# define WIFSTOPPED(x) 0 + +/* The signal that terminated a process is not known posthum. */ +# define WTERMSIG(x) SIGTERM + +# define WEXITSTATUS(x) (x) + +/* There are no stopping signals. */ +# define WSTOPSIG(x) 0 + +/* There are no core dumps. */ +# define WCOREDUMP(x) 0 + +#endif + + +/* Declarations of functions. */ + +#if @GNULIB_WAITPID@ +# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ +_GL_FUNCDECL_SYS (waitpid, pid_t, (pid_t pid, int *statusp, int options)); +# endif +_GL_CXXALIAS_SYS (waitpid, pid_t, (pid_t pid, int *statusp, int options)); +_GL_CXXALIASWARN (waitpid); +#elif defined GNULIB_POSIXCHECK +# undef waitpid +# if HAVE_RAW_DECL_WAITPID +_GL_WARN_ON_USE (waitpid, "waitpid is unportable - " + "use gnulib module sys_wait for portability"); +# endif +#endif + + +#endif /* _@GUARD_PREFIX@_SYS_WAIT_H */ +#endif /* _@GUARD_PREFIX@_SYS_WAIT_H */ diff --git a/gettext-tools/gnulib-lib/tempname.c b/gettext-tools/gnulib-lib/tempname.c new file mode 100644 index 0000000..9b713cb --- /dev/null +++ b/gettext-tools/gnulib-lib/tempname.c @@ -0,0 +1,306 @@ +/* tempname.c - generate the name of a temporary file. + + Copyright (C) 1991-2003, 2005-2007, 2009-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Extracted from glibc sysdeps/posix/tempname.c. See also tmpdir.c. */ + +#if !_LIBC +# include +# include "tempname.h" +#endif + +#include +#include + +#include +#ifndef __set_errno +# define __set_errno(Val) errno = (Val) +#endif + +#include +#ifndef P_tmpdir +# define P_tmpdir "/tmp" +#endif +#ifndef TMP_MAX +# define TMP_MAX 238328 +#endif +#ifndef __GT_FILE +# define __GT_FILE 0 +# define __GT_DIR 1 +# define __GT_NOCREATE 2 +#endif +#if !_LIBC && (GT_FILE != __GT_FILE || GT_DIR != __GT_DIR \ + || GT_NOCREATE != __GT_NOCREATE) +# error report this to bug-gnulib@gnu.org +#endif + +#include +#include +#include + +#include +#include +#include +#include + +#include + +#if _LIBC +# define struct_stat64 struct stat64 +#else +# define struct_stat64 struct stat +# define __gen_tempname gen_tempname +# define __getpid getpid +# define __gettimeofday gettimeofday +# define __mkdir mkdir +# define __open open +# define __lxstat64(version, file, buf) lstat (file, buf) +# define __secure_getenv secure_getenv +#endif + +#ifdef _LIBC +# include +# if HP_TIMING_AVAIL +# define RANDOM_BITS(Var) \ + if (__builtin_expect (value == UINT64_C (0), 0)) \ + { \ + /* If this is the first time this function is used initialize \ + the variable we accumulate the value in to some somewhat \ + random value. If we'd not do this programs at startup time \ + might have a reduced set of possible names, at least on slow \ + machines. */ \ + struct timeval tv; \ + __gettimeofday (&tv, NULL); \ + value = ((uint64_t) tv.tv_usec << 16) ^ tv.tv_sec; \ + } \ + HP_TIMING_NOW (Var) +# endif +#endif + +/* Use the widest available unsigned type if uint64_t is not + available. The algorithm below extracts a number less than 62**6 + (approximately 2**35.725) from uint64_t, so ancient hosts where + uintmax_t is only 32 bits lose about 3.725 bits of randomness, + which is better than not having mkstemp at all. */ +#if !defined UINT64_MAX && !defined uint64_t +# define uint64_t uintmax_t +#endif + +#if _LIBC +/* Return nonzero if DIR is an existent directory. */ +static int +direxists (const char *dir) +{ + struct_stat64 buf; + return __xstat64 (_STAT_VER, dir, &buf) == 0 && S_ISDIR (buf.st_mode); +} + +/* Path search algorithm, for tmpnam, tmpfile, etc. If DIR is + non-null and exists, uses it; otherwise uses the first of $TMPDIR, + P_tmpdir, /tmp that exists. Copies into TMPL a template suitable + for use with mk[s]temp. Will fail (-1) if DIR is non-null and + doesn't exist, none of the searched dirs exists, or there's not + enough space in TMPL. */ +int +__path_search (char *tmpl, size_t tmpl_len, const char *dir, const char *pfx, + int try_tmpdir) +{ + const char *d; + size_t dlen, plen; + + if (!pfx || !pfx[0]) + { + pfx = "file"; + plen = 4; + } + else + { + plen = strlen (pfx); + if (plen > 5) + plen = 5; + } + + if (try_tmpdir) + { + d = __secure_getenv ("TMPDIR"); + if (d != NULL && direxists (d)) + dir = d; + else if (dir != NULL && direxists (dir)) + /* nothing */ ; + else + dir = NULL; + } + if (dir == NULL) + { + if (direxists (P_tmpdir)) + dir = P_tmpdir; + else if (strcmp (P_tmpdir, "/tmp") != 0 && direxists ("/tmp")) + dir = "/tmp"; + else + { + __set_errno (ENOENT); + return -1; + } + } + + dlen = strlen (dir); + while (dlen > 1 && dir[dlen - 1] == '/') + dlen--; /* remove trailing slashes */ + + /* check we have room for "${dir}/${pfx}XXXXXX\0" */ + if (tmpl_len < dlen + 1 + plen + 6 + 1) + { + __set_errno (EINVAL); + return -1; + } + + sprintf (tmpl, "%.*s/%.*sXXXXXX", (int) dlen, dir, (int) plen, pfx); + return 0; +} +#endif /* _LIBC */ + +/* These are the characters used in temporary file names. */ +static const char letters[] = +"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + +/* Generate a temporary file name based on TMPL. TMPL must match the + rules for mk[s]temp (i.e. end in "XXXXXX", possibly with a suffix). + The name constructed does not exist at the time of the call to + __gen_tempname. TMPL is overwritten with the result. + + KIND may be one of: + __GT_NOCREATE: simply verify that the name does not exist + at the time of the call. + __GT_FILE: create the file using open(O_CREAT|O_EXCL) + and return a read-write fd. The file is mode 0600. + __GT_DIR: create a directory, which will be mode 0700. + + We use a clever algorithm to get hard-to-predict names. */ +int +__gen_tempname (char *tmpl, int suffixlen, int flags, int kind) +{ + int len; + char *XXXXXX; + static uint64_t value; + uint64_t random_time_bits; + unsigned int count; + int fd = -1; + int save_errno = errno; + struct_stat64 st; + + /* A lower bound on the number of temporary files to attempt to + generate. The maximum total number of temporary file names that + can exist for a given template is 62**6. It should never be + necessary to try all of these combinations. Instead if a reasonable + number of names is tried (we define reasonable as 62**3) fail to + give the system administrator the chance to remove the problems. */ +#define ATTEMPTS_MIN (62 * 62 * 62) + + /* The number of times to attempt to generate a temporary file. To + conform to POSIX, this must be no smaller than TMP_MAX. */ +#if ATTEMPTS_MIN < TMP_MAX + unsigned int attempts = TMP_MAX; +#else + unsigned int attempts = ATTEMPTS_MIN; +#endif + + len = strlen (tmpl); + if (len < 6 + suffixlen || memcmp (&tmpl[len - 6 - suffixlen], "XXXXXX", 6)) + { + __set_errno (EINVAL); + return -1; + } + + /* This is where the Xs start. */ + XXXXXX = &tmpl[len - 6 - suffixlen]; + + /* Get some more or less random data. */ +#ifdef RANDOM_BITS + RANDOM_BITS (random_time_bits); +#else + { + struct timeval tv; + __gettimeofday (&tv, NULL); + random_time_bits = ((uint64_t) tv.tv_usec << 16) ^ tv.tv_sec; + } +#endif + value += random_time_bits ^ __getpid (); + + for (count = 0; count < attempts; value += 7777, ++count) + { + uint64_t v = value; + + /* Fill in the random bits. */ + XXXXXX[0] = letters[v % 62]; + v /= 62; + XXXXXX[1] = letters[v % 62]; + v /= 62; + XXXXXX[2] = letters[v % 62]; + v /= 62; + XXXXXX[3] = letters[v % 62]; + v /= 62; + XXXXXX[4] = letters[v % 62]; + v /= 62; + XXXXXX[5] = letters[v % 62]; + + switch (kind) + { + case __GT_FILE: + fd = __open (tmpl, + (flags & ~O_ACCMODE) + | O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); + break; + + case __GT_DIR: + fd = __mkdir (tmpl, S_IRUSR | S_IWUSR | S_IXUSR); + break; + + case __GT_NOCREATE: + /* This case is backward from the other three. __gen_tempname + succeeds if __xstat fails because the name does not exist. + Note the continue to bypass the common logic at the bottom + of the loop. */ + if (__lxstat64 (_STAT_VER, tmpl, &st) < 0) + { + if (errno == ENOENT) + { + __set_errno (save_errno); + return 0; + } + else + /* Give up now. */ + return -1; + } + continue; + + default: + assert (! "invalid KIND in __gen_tempname"); + abort (); + } + + if (fd >= 0) + { + __set_errno (save_errno); + return fd; + } + else if (errno != EEXIST) + return -1; + } + + /* We got out of the loop because we ran out of combinations to try. */ + __set_errno (EEXIST); + return -1; +} diff --git a/gettext-tools/gnulib-lib/tempname.h b/gettext-tools/gnulib-lib/tempname.h new file mode 100644 index 0000000..44d5f04 --- /dev/null +++ b/gettext-tools/gnulib-lib/tempname.h @@ -0,0 +1,50 @@ +/* Create a temporary file or directory. + + Copyright (C) 2006, 2009-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* header written by Eric Blake */ + +#ifndef GL_TEMPNAME_H +# define GL_TEMPNAME_H + +# include + +# ifdef __GT_FILE +# define GT_FILE __GT_FILE +# define GT_DIR __GT_DIR +# define GT_NOCREATE __GT_NOCREATE +# else +# define GT_FILE 0 +# define GT_DIR 1 +# define GT_NOCREATE 2 +# endif + +/* Generate a temporary file name based on TMPL. TMPL must match the + rules for mk[s]temp (i.e. end in "XXXXXX", possibly with a suffix). + The name constructed does not exist at the time of the call to + gen_tempname. TMPL is overwritten with the result. + + KIND may be one of: + GT_NOCREATE: simply verify that the name does not exist + at the time of the call. + GT_FILE: create a large file using open(O_CREAT|O_EXCL) + and return a read-write fd. The file is mode 0600. + GT_DIR: create a directory, which will be mode 0700. + + We use a clever algorithm to get hard-to-predict names. */ +extern int gen_tempname (char *tmpl, int suffixlen, int flags, int kind); + +#endif /* GL_TEMPNAME_H */ diff --git a/gettext-tools/gnulib-lib/term-ostream.c b/gettext-tools/gnulib-lib/term-ostream.c new file mode 100644 index 0000000..fbec783 --- /dev/null +++ b/gettext-tools/gnulib-lib/term-ostream.c @@ -0,0 +1,2043 @@ +/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ + +#line 1 "term-ostream.oo.c" +/* Output stream for attributed text, producing ANSI escape sequences. + Copyright (C) 2006-2008 Free Software Foundation, Inc. + Written by Bruno Haible , 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include "term-ostream.h" + +#include +#include +#include +#include +#include +#include + +#include "error.h" +#include "fatal-signal.h" +#include "full-write.h" +#include "terminfo.h" +#include "xalloc.h" +#include "xsize.h" +#include "gettext.h" + +#define _(str) gettext (str) + +#if HAVE_TPARAM +/* GNU termcap's tparam() function requires a buffer argument. Make it so + large that there is no risk that tparam() needs to call malloc(). */ +static char tparambuf[100]; +/* Define tparm in terms of tparam. In the scope of this file, it is called + with at most one argument after the string. */ +# define tparm(str, arg1) \ + tparam (str, tparambuf, sizeof (tparambuf), arg1) +#endif + +#define SIZEOF(a) (sizeof(a) / sizeof(a[0])) + + +/* =========================== Color primitives =========================== */ + +/* A color in RGB format. */ +typedef struct +{ + unsigned int red : 8; /* range 0..255 */ + unsigned int green : 8; /* range 0..255 */ + unsigned int blue : 8; /* range 0..255 */ +} rgb_t; + +/* A color in HSV (a.k.a. HSB) format. */ +typedef struct +{ + float hue; /* normalized to interval [0,6) */ + float saturation; /* normalized to interval [0,1] */ + float brightness; /* a.k.a. value, normalized to interval [0,1] */ +} hsv_t; + +/* Conversion of a color in RGB to HSV format. */ +static void +rgb_to_hsv (rgb_t c, hsv_t *result) +{ + unsigned int r = c.red; + unsigned int g = c.green; + unsigned int b = c.blue; + + if (r > g) + { + if (b > r) + { + /* b > r > g, so max = b, min = g */ + result->hue = 4.0f + (float) (r - g) / (float) (b - g); + result->saturation = 1.0f - (float) g / (float) b; + result->brightness = (float) b / 255.0f; + } + else if (b <= g) + { + /* r > g >= b, so max = r, min = b */ + result->hue = 0.0f + (float) (g - b) / (float) (r - b); + result->saturation = 1.0f - (float) b / (float) r; + result->brightness = (float) r / 255.0f; + } + else + { + /* r >= b > g, so max = r, min = g */ + result->hue = 6.0f - (float) (b - g) / (float) (r - g); + result->saturation = 1.0f - (float) g / (float) r; + result->brightness = (float) r / 255.0f; + } + } + else + { + if (b > g) + { + /* b > g >= r, so max = b, min = r */ + result->hue = 4.0f - (float) (g - r) / (float) (b - r); + result->saturation = 1.0f - (float) r / (float) b; + result->brightness = (float) b / 255.0f; + } + else if (b < r) + { + /* g >= r > b, so max = g, min = b */ + result->hue = 2.0f - (float) (r - b) / (float) (g - b); + result->saturation = 1.0f - (float) b / (float) g; + result->brightness = (float) g / 255.0f; + } + else if (g > r) + { + /* g >= b >= r, g > r, so max = g, min = r */ + result->hue = 2.0f + (float) (b - r) / (float) (g - r); + result->saturation = 1.0f - (float) r / (float) g; + result->brightness = (float) g / 255.0f; + } + else + { + /* r = g = b. A grey color. */ + result->hue = 0; /* arbitrary */ + result->saturation = 0; + result->brightness = (float) r / 255.0f; + } + } +} + +/* Square of distance of two colors. */ +static float +color_distance (const hsv_t *color1, const hsv_t *color2) +{ +#if 0 + /* Formula taken from "John Smith: Color Similarity", + http://www.ctr.columbia.edu/~jrsmith/html/pubs/acmmm96/node8.html. */ + float angle1 = color1->hue * 1.04719755f; /* normalize to [0,2Ï€] */ + float angle2 = color2->hue * 1.04719755f; /* normalize to [0,2Ï€] */ + float delta_x = color1->saturation * cosf (angle1) + - color2->saturation * cosf (angle2); + float delta_y = color1->saturation * sinf (angle1) + - color2->saturation * sinf (angle2); + float delta_v = color1->brightness + - color2->brightness; + + return delta_x * delta_x + delta_y * delta_y + delta_v * delta_v; +#else + /* Formula that considers hue differences with more weight than saturation + or brightness differences, like the human eye does. */ + float delta_hue = + (color1->hue >= color2->hue + ? (color1->hue - color2->hue >= 3.0f + ? 6.0f + color2->hue - color1->hue + : color1->hue - color2->hue) + : (color2->hue - color1->hue >= 3.0f + ? 6.0f + color1->hue - color2->hue + : color2->hue - color1->hue)); + float min_saturation = + (color1->saturation < color2->saturation + ? color1->saturation + : color2->saturation); + float delta_saturation = color1->saturation - color2->saturation; + float delta_brightness = color1->brightness - color2->brightness; + + return delta_hue * delta_hue * min_saturation + + delta_saturation * delta_saturation * 0.2f + + delta_brightness * delta_brightness * 0.8f; +#endif +} + +/* Return the index of the color in a color table that is nearest to a given + color. */ +static unsigned int +nearest_color (rgb_t given, const rgb_t *table, unsigned int table_size) +{ + hsv_t given_hsv; + unsigned int best_index; + float best_distance; + unsigned int i; + + assert (table_size > 0); + + rgb_to_hsv (given, &given_hsv); + + best_index = 0; + best_distance = 1000000.0f; + for (i = 0; i < table_size; i++) + { + hsv_t i_hsv; + + rgb_to_hsv (table[i], &i_hsv); + + /* Avoid converting a color to grey, or fading out a color too much. */ + if (i_hsv.saturation > given_hsv.saturation * 0.5f) + { + float distance = color_distance (&given_hsv, &i_hsv); + if (distance < best_distance) + { + best_index = i; + best_distance = distance; + } + } + } + +#if 0 /* Debugging code */ + hsv_t best_hsv; + rgb_to_hsv (table[best_index], &best_hsv); + fprintf (stderr, "nearest: (%d,%d,%d) = (%f,%f,%f)\n -> (%f,%f,%f) = (%d,%d,%d)\n", + given.red, given.green, given.blue, + (double)given_hsv.hue, (double)given_hsv.saturation, (double)given_hsv.brightness, + (double)best_hsv.hue, (double)best_hsv.saturation, (double)best_hsv.brightness, + table[best_index].red, table[best_index].green, table[best_index].blue); +#endif + + return best_index; +} + +/* The luminance of a color. This is the brightness of the color, as it + appears to the human eye. This must be used in color to grey conversion. */ +static float +color_luminance (int r, int g, int b) +{ + /* Use the luminance model used by NTSC and JPEG. + Taken from http://www.fho-emden.de/~hoffmann/gray10012001.pdf . + No need to care about rounding errors leading to luminance > 1; + this cannot happen. */ + return (0.299f * r + 0.587f * g + 0.114f * b) / 255.0f; +} + + +/* ============================= Color models ============================= */ + +/* The color model used by the terminal. */ +typedef enum +{ + cm_monochrome, /* No colors. */ + cm_common8, /* Usual terminal with at least 8 colors. */ + cm_xterm8, /* TERM=xterm, with 8 colors. */ + cm_xterm16, /* TERM=xterm-16color, with 16 colors. */ + cm_xterm88, /* TERM=xterm-88color, with 88 colors. */ + cm_xterm256 /* TERM=xterm-256color, with 256 colors. */ +} colormodel_t; + +/* ----------------------- cm_monochrome color model ----------------------- */ + +/* A non-default color index doesn't exist in this color model. */ +static inline term_color_t +rgb_to_color_monochrome () +{ + return COLOR_DEFAULT; +} + +/* ------------------------ cm_common8 color model ------------------------ */ + +/* A non-default color index is in the range 0..7. + RGB components + COLOR_BLACK 000 + COLOR_BLUE 001 + COLOR_GREEN 010 + COLOR_CYAN 011 + COLOR_RED 100 + COLOR_MAGENTA 101 + COLOR_YELLOW 110 + COLOR_WHITE 111 */ +static const rgb_t colors_of_common8[8] = +{ + /* R G B grey index */ + { 0, 0, 0 }, /* 0.000 0 */ + { 0, 0, 255 }, + { 0, 255, 0 }, + { 0, 255, 255 }, + { 255, 0, 0 }, + { 255, 0, 255 }, + { 255, 255, 0 }, + { 255, 255, 255 } /* 1.000 7 */ +}; + +static inline term_color_t +rgb_to_color_common8 (int r, int g, int b) +{ + rgb_t color; + hsv_t hsv; + + color.red = r; color.green = g; color.blue = b; + rgb_to_hsv (color, &hsv); + + if (hsv.saturation < 0.065f) + { + /* Greyscale approximation. */ + float luminance = color_luminance (r, g, b); + if (luminance < 0.500f) + return 0; + else + return 7; + } + else + /* Color approximation. */ + return nearest_color (color, colors_of_common8, 8); +} + +/* Convert a cm_common8 color in RGB encoding to BGR encoding. + See the ncurses terminfo(5) manual page, section "Color Handling", for an + explanation why this is needed. */ +static inline int +color_bgr (term_color_t color) +{ + return ((color & 4) >> 2) | (color & 2) | ((color & 1) << 2); +} + +/* ------------------------- cm_xterm8 color model ------------------------- */ + +/* A non-default color index is in the range 0..7. + BGR components + COLOR_BLACK 000 + COLOR_RED 001 + COLOR_GREEN 010 + COLOR_YELLOW 011 + COLOR_BLUE 100 + COLOR_MAGENTA 101 + COLOR_CYAN 110 + COLOR_WHITE 111 */ +static const rgb_t colors_of_xterm8[8] = +{ + /* The real xterm's colors are dimmed; assume full-brightness instead. */ + /* R G B grey index */ + { 0, 0, 0 }, /* 0.000 0 */ + { 255, 0, 0 }, + { 0, 255, 0 }, + { 255, 255, 0 }, + { 0, 0, 255 }, + { 255, 0, 255 }, + { 0, 255, 255 }, + { 255, 255, 255 } /* 1.000 7 */ +}; + +static inline term_color_t +rgb_to_color_xterm8 (int r, int g, int b) +{ + rgb_t color; + hsv_t hsv; + + color.red = r; color.green = g; color.blue = b; + rgb_to_hsv (color, &hsv); + + if (hsv.saturation < 0.065f) + { + /* Greyscale approximation. */ + float luminance = color_luminance (r, g, b); + if (luminance < 0.500f) + return 0; + else + return 7; + } + else + /* Color approximation. */ + return nearest_color (color, colors_of_xterm8, 8); +} + +/* ------------------------ cm_xterm16 color model ------------------------ */ + +/* A non-default color index is in the range 0..15. + The RGB values come from xterm's XTerm-col.ad. */ +static const rgb_t colors_of_xterm16[16] = +{ + /* R G B grey index */ + { 0, 0, 0 }, /* 0.000 0 */ + { 205, 0, 0 }, + { 0, 205, 0 }, + { 205, 205, 0 }, + { 0, 0, 205 }, + { 205, 0, 205 }, + { 0, 205, 205 }, + { 229, 229, 229 }, /* 0.898 7 */ + { 77, 77, 77 }, /* 0.302 8 */ + { 255, 0, 0 }, + { 0, 255, 0 }, + { 255, 255, 0 }, + { 0, 0, 255 }, + { 255, 0, 255 }, + { 0, 255, 255 }, + { 255, 255, 255 } /* 1.000 15 */ +}; + +static inline term_color_t +rgb_to_color_xterm16 (int r, int g, int b) +{ + rgb_t color; + hsv_t hsv; + + color.red = r; color.green = g; color.blue = b; + rgb_to_hsv (color, &hsv); + + if (hsv.saturation < 0.065f) + { + /* Greyscale approximation. */ + float luminance = color_luminance (r, g, b); + if (luminance < 0.151f) + return 0; + else if (luminance < 0.600f) + return 8; + else if (luminance < 0.949f) + return 7; + else + return 15; + } + else + /* Color approximation. */ + return nearest_color (color, colors_of_xterm16, 16); +} + +/* ------------------------ cm_xterm88 color model ------------------------ */ + +/* A non-default color index is in the range 0..87. + Colors 0..15 are the same as in the cm_xterm16 color model. + Colors 16..87 are defined in xterm's 88colres.h. */ + +static const rgb_t colors_of_xterm88[88] = +{ + /* R G B grey index */ + { 0, 0, 0 }, /* 0.000 0 */ + { 205, 0, 0 }, + { 0, 205, 0 }, + { 205, 205, 0 }, + { 0, 0, 205 }, + { 205, 0, 205 }, + { 0, 205, 205 }, + { 229, 229, 229 }, /* 0.898 7 */ + { 77, 77, 77 }, /* 0.302 8 */ + { 255, 0, 0 }, + { 0, 255, 0 }, + { 255, 255, 0 }, + { 0, 0, 255 }, + { 255, 0, 255 }, + { 0, 255, 255 }, + { 255, 255, 255 }, /* 1.000 15 */ + { 0, 0, 0 }, /* 0.000 16 */ + { 0, 0, 139 }, + { 0, 0, 205 }, + { 0, 0, 255 }, + { 0, 139, 0 }, + { 0, 139, 139 }, + { 0, 139, 205 }, + { 0, 139, 255 }, + { 0, 205, 0 }, + { 0, 205, 139 }, + { 0, 205, 205 }, + { 0, 205, 255 }, + { 0, 255, 0 }, + { 0, 255, 139 }, + { 0, 255, 205 }, + { 0, 255, 255 }, + { 139, 0, 0 }, + { 139, 0, 139 }, + { 139, 0, 205 }, + { 139, 0, 255 }, + { 139, 139, 0 }, + { 139, 139, 139 }, /* 0.545 37 */ + { 139, 139, 205 }, + { 139, 139, 255 }, + { 139, 205, 0 }, + { 139, 205, 139 }, + { 139, 205, 205 }, + { 139, 205, 255 }, + { 139, 255, 0 }, + { 139, 255, 139 }, + { 139, 255, 205 }, + { 139, 255, 255 }, + { 205, 0, 0 }, + { 205, 0, 139 }, + { 205, 0, 205 }, + { 205, 0, 255 }, + { 205, 139, 0 }, + { 205, 139, 139 }, + { 205, 139, 205 }, + { 205, 139, 255 }, + { 205, 205, 0 }, + { 205, 205, 139 }, + { 205, 205, 205 }, /* 0.804 58 */ + { 205, 205, 255 }, + { 205, 255, 0 }, + { 205, 255, 139 }, + { 205, 255, 205 }, + { 205, 255, 255 }, + { 255, 0, 0 }, + { 255, 0, 139 }, + { 255, 0, 205 }, + { 255, 0, 255 }, + { 255, 139, 0 }, + { 255, 139, 139 }, + { 255, 139, 205 }, + { 255, 139, 255 }, + { 255, 205, 0 }, + { 255, 205, 139 }, + { 255, 205, 205 }, + { 255, 205, 255 }, + { 255, 255, 0 }, + { 255, 255, 139 }, + { 255, 255, 205 }, + { 255, 255, 255 }, /* 1.000 79 */ + { 46, 46, 46 }, /* 0.180 80 */ + { 92, 92, 92 }, /* 0.361 81 */ + { 115, 115, 115 }, /* 0.451 82 */ + { 139, 139, 139 }, /* 0.545 83 */ + { 162, 162, 162 }, /* 0.635 84 */ + { 185, 185, 185 }, /* 0.725 85 */ + { 208, 208, 208 }, /* 0.816 86 */ + { 231, 231, 231 } /* 0.906 87 */ +}; + +static inline term_color_t +rgb_to_color_xterm88 (int r, int g, int b) +{ + rgb_t color; + hsv_t hsv; + + color.red = r; color.green = g; color.blue = b; + rgb_to_hsv (color, &hsv); + + if (hsv.saturation < 0.065f) + { + /* Greyscale approximation. */ + float luminance = color_luminance (r, g, b); + if (luminance < 0.090f) + return 0; + else if (luminance < 0.241f) + return 80; + else if (luminance < 0.331f) + return 8; + else if (luminance < 0.406f) + return 81; + else if (luminance < 0.498f) + return 82; + else if (luminance < 0.585f) + return 37; + else if (luminance < 0.680f) + return 84; + else if (luminance < 0.764f) + return 85; + else if (luminance < 0.810f) + return 58; + else if (luminance < 0.857f) + return 86; + else if (luminance < 0.902f) + return 7; + else if (luminance < 0.953f) + return 87; + else + return 15; + } + else + /* Color approximation. */ + return nearest_color (color, colors_of_xterm88, 88); +} + +/* ------------------------ cm_xterm256 color model ------------------------ */ + +/* A non-default color index is in the range 0..255. + Colors 0..15 are the same as in the cm_xterm16 color model. + Colors 16..255 are defined in xterm's 256colres.h. */ + +static const rgb_t colors_of_xterm256[256] = +{ + /* R G B grey index */ + { 0, 0, 0 }, /* 0.000 0 */ + { 205, 0, 0 }, + { 0, 205, 0 }, + { 205, 205, 0 }, + { 0, 0, 205 }, + { 205, 0, 205 }, + { 0, 205, 205 }, + { 229, 229, 229 }, /* 0.898 7 */ + { 77, 77, 77 }, /* 0.302 8 */ + { 255, 0, 0 }, + { 0, 255, 0 }, + { 255, 255, 0 }, + { 0, 0, 255 }, + { 255, 0, 255 }, + { 0, 255, 255 }, + { 255, 255, 255 }, /* 1.000 15 */ + { 0, 0, 0 }, /* 0.000 16 */ + { 0, 0, 42 }, + { 0, 0, 85 }, + { 0, 0, 127 }, + { 0, 0, 170 }, + { 0, 0, 212 }, + { 0, 42, 0 }, + { 0, 42, 42 }, + { 0, 42, 85 }, + { 0, 42, 127 }, + { 0, 42, 170 }, + { 0, 42, 212 }, + { 0, 85, 0 }, + { 0, 85, 42 }, + { 0, 85, 85 }, + { 0, 85, 127 }, + { 0, 85, 170 }, + { 0, 85, 212 }, + { 0, 127, 0 }, + { 0, 127, 42 }, + { 0, 127, 85 }, + { 0, 127, 127 }, + { 0, 127, 170 }, + { 0, 127, 212 }, + { 0, 170, 0 }, + { 0, 170, 42 }, + { 0, 170, 85 }, + { 0, 170, 127 }, + { 0, 170, 170 }, + { 0, 170, 212 }, + { 0, 212, 0 }, + { 0, 212, 42 }, + { 0, 212, 85 }, + { 0, 212, 127 }, + { 0, 212, 170 }, + { 0, 212, 212 }, + { 42, 0, 0 }, + { 42, 0, 42 }, + { 42, 0, 85 }, + { 42, 0, 127 }, + { 42, 0, 170 }, + { 42, 0, 212 }, + { 42, 42, 0 }, + { 42, 42, 42 }, /* 0.165 59 */ + { 42, 42, 85 }, + { 42, 42, 127 }, + { 42, 42, 170 }, + { 42, 42, 212 }, + { 42, 85, 0 }, + { 42, 85, 42 }, + { 42, 85, 85 }, + { 42, 85, 127 }, + { 42, 85, 170 }, + { 42, 85, 212 }, + { 42, 127, 0 }, + { 42, 127, 42 }, + { 42, 127, 85 }, + { 42, 127, 127 }, + { 42, 127, 170 }, + { 42, 127, 212 }, + { 42, 170, 0 }, + { 42, 170, 42 }, + { 42, 170, 85 }, + { 42, 170, 127 }, + { 42, 170, 170 }, + { 42, 170, 212 }, + { 42, 212, 0 }, + { 42, 212, 42 }, + { 42, 212, 85 }, + { 42, 212, 127 }, + { 42, 212, 170 }, + { 42, 212, 212 }, + { 85, 0, 0 }, + { 85, 0, 42 }, + { 85, 0, 85 }, + { 85, 0, 127 }, + { 85, 0, 170 }, + { 85, 0, 212 }, + { 85, 42, 0 }, + { 85, 42, 42 }, + { 85, 42, 85 }, + { 85, 42, 127 }, + { 85, 42, 170 }, + { 85, 42, 212 }, + { 85, 85, 0 }, + { 85, 85, 42 }, + { 85, 85, 85 }, /* 0.333 102 */ + { 85, 85, 127 }, + { 85, 85, 170 }, + { 85, 85, 212 }, + { 85, 127, 0 }, + { 85, 127, 42 }, + { 85, 127, 85 }, + { 85, 127, 127 }, + { 85, 127, 170 }, + { 85, 127, 212 }, + { 85, 170, 0 }, + { 85, 170, 42 }, + { 85, 170, 85 }, + { 85, 170, 127 }, + { 85, 170, 170 }, + { 85, 170, 212 }, + { 85, 212, 0 }, + { 85, 212, 42 }, + { 85, 212, 85 }, + { 85, 212, 127 }, + { 85, 212, 170 }, + { 85, 212, 212 }, + { 127, 0, 0 }, + { 127, 0, 42 }, + { 127, 0, 85 }, + { 127, 0, 127 }, + { 127, 0, 170 }, + { 127, 0, 212 }, + { 127, 42, 0 }, + { 127, 42, 42 }, + { 127, 42, 85 }, + { 127, 42, 127 }, + { 127, 42, 170 }, + { 127, 42, 212 }, + { 127, 85, 0 }, + { 127, 85, 42 }, + { 127, 85, 85 }, + { 127, 85, 127 }, + { 127, 85, 170 }, + { 127, 85, 212 }, + { 127, 127, 0 }, + { 127, 127, 42 }, + { 127, 127, 85 }, + { 127, 127, 127 }, /* 0.498 145 */ + { 127, 127, 170 }, + { 127, 127, 212 }, + { 127, 170, 0 }, + { 127, 170, 42 }, + { 127, 170, 85 }, + { 127, 170, 127 }, + { 127, 170, 170 }, + { 127, 170, 212 }, + { 127, 212, 0 }, + { 127, 212, 42 }, + { 127, 212, 85 }, + { 127, 212, 127 }, + { 127, 212, 170 }, + { 127, 212, 212 }, + { 170, 0, 0 }, + { 170, 0, 42 }, + { 170, 0, 85 }, + { 170, 0, 127 }, + { 170, 0, 170 }, + { 170, 0, 212 }, + { 170, 42, 0 }, + { 170, 42, 42 }, + { 170, 42, 85 }, + { 170, 42, 127 }, + { 170, 42, 170 }, + { 170, 42, 212 }, + { 170, 85, 0 }, + { 170, 85, 42 }, + { 170, 85, 85 }, + { 170, 85, 127 }, + { 170, 85, 170 }, + { 170, 85, 212 }, + { 170, 127, 0 }, + { 170, 127, 42 }, + { 170, 127, 85 }, + { 170, 127, 127 }, + { 170, 127, 170 }, + { 170, 127, 212 }, + { 170, 170, 0 }, + { 170, 170, 42 }, + { 170, 170, 85 }, + { 170, 170, 127 }, + { 170, 170, 170 }, /* 0.667 188 */ + { 170, 170, 212 }, + { 170, 212, 0 }, + { 170, 212, 42 }, + { 170, 212, 85 }, + { 170, 212, 127 }, + { 170, 212, 170 }, + { 170, 212, 212 }, + { 212, 0, 0 }, + { 212, 0, 42 }, + { 212, 0, 85 }, + { 212, 0, 127 }, + { 212, 0, 170 }, + { 212, 0, 212 }, + { 212, 42, 0 }, + { 212, 42, 42 }, + { 212, 42, 85 }, + { 212, 42, 127 }, + { 212, 42, 170 }, + { 212, 42, 212 }, + { 212, 85, 0 }, + { 212, 85, 42 }, + { 212, 85, 85 }, + { 212, 85, 127 }, + { 212, 85, 170 }, + { 212, 85, 212 }, + { 212, 127, 0 }, + { 212, 127, 42 }, + { 212, 127, 85 }, + { 212, 127, 127 }, + { 212, 127, 170 }, + { 212, 127, 212 }, + { 212, 170, 0 }, + { 212, 170, 42 }, + { 212, 170, 85 }, + { 212, 170, 127 }, + { 212, 170, 170 }, + { 212, 170, 212 }, + { 212, 212, 0 }, + { 212, 212, 42 }, + { 212, 212, 85 }, + { 212, 212, 127 }, + { 212, 212, 170 }, + { 212, 212, 212 }, /* 0.831 231 */ + { 8, 8, 8 }, /* 0.031 232 */ + { 18, 18, 18 }, /* 0.071 233 */ + { 28, 28, 28 }, /* 0.110 234 */ + { 38, 38, 38 }, /* 0.149 235 */ + { 48, 48, 48 }, /* 0.188 236 */ + { 58, 58, 58 }, /* 0.227 237 */ + { 68, 68, 68 }, /* 0.267 238 */ + { 78, 78, 78 }, /* 0.306 239 */ + { 88, 88, 88 }, /* 0.345 240 */ + { 98, 98, 98 }, /* 0.384 241 */ + { 108, 108, 108 }, /* 0.424 242 */ + { 118, 118, 118 }, /* 0.463 243 */ + { 128, 128, 128 }, /* 0.502 244 */ + { 138, 138, 138 }, /* 0.541 245 */ + { 148, 148, 148 }, /* 0.580 246 */ + { 158, 158, 158 }, /* 0.620 247 */ + { 168, 168, 168 }, /* 0.659 248 */ + { 178, 178, 178 }, /* 0.698 249 */ + { 188, 188, 188 }, /* 0.737 250 */ + { 198, 198, 198 }, /* 0.776 251 */ + { 208, 208, 208 }, /* 0.816 252 */ + { 218, 218, 218 }, /* 0.855 253 */ + { 228, 228, 228 }, /* 0.894 254 */ + { 238, 238, 238 } /* 0.933 255 */ +}; + +static inline term_color_t +rgb_to_color_xterm256 (int r, int g, int b) +{ + rgb_t color; + hsv_t hsv; + + color.red = r; color.green = g; color.blue = b; + rgb_to_hsv (color, &hsv); + + if (hsv.saturation < 0.065f) + { + /* Greyscale approximation. */ + float luminance = color_luminance (r, g, b); + if (luminance < 0.015f) + return 0; + else if (luminance < 0.051f) + return 232; + else if (luminance < 0.090f) + return 233; + else if (luminance < 0.129f) + return 234; + else if (luminance < 0.157f) + return 235; + else if (luminance < 0.177f) + return 59; + else if (luminance < 0.207f) + return 236; + else if (luminance < 0.247f) + return 237; + else if (luminance < 0.284f) + return 238; + else if (luminance < 0.304f) + return 8; + else if (luminance < 0.319f) + return 239; + else if (luminance < 0.339f) + return 102; + else if (luminance < 0.364f) + return 240; + else if (luminance < 0.404f) + return 241; + else if (luminance < 0.443f) + return 242; + else if (luminance < 0.480f) + return 243; + else if (luminance < 0.500f) + return 145; + else if (luminance < 0.521f) + return 244; + else if (luminance < 0.560f) + return 245; + else if (luminance < 0.600f) + return 246; + else if (luminance < 0.639f) + return 247; + else if (luminance < 0.663f) + return 248; + else if (luminance < 0.682f) + return 188; + else if (luminance < 0.717f) + return 249; + else if (luminance < 0.756f) + return 250; + else if (luminance < 0.796f) + return 251; + else if (luminance < 0.823f) + return 252; + else if (luminance < 0.843f) + return 231; + else if (luminance < 0.874f) + return 253; + else if (luminance < 0.896f) + return 254; + else if (luminance < 0.915f) + return 7; + else if (luminance < 0.966f) + return 255; + else + return 15; + } + else + /* Color approximation. */ + return nearest_color (color, colors_of_xterm256, 256); +} + + +/* ============================= attributes_t ============================= */ + +/* ANSI C and ISO C99 6.7.2.1.(4) forbid use of bit fields for types other + than 'int' or 'unsigned int'. + On the other hand, C++ forbids conversion between enum types and integer + types without an explicit cast. */ +#ifdef __cplusplus +# define BITFIELD_TYPE(orig_type,integer_type) orig_type +#else +# define BITFIELD_TYPE(orig_type,integer_type) integer_type +#endif + +/* Attributes that can be set on a character. */ +typedef struct +{ + BITFIELD_TYPE(term_color_t, signed int) color : 9; + BITFIELD_TYPE(term_color_t, signed int) bgcolor : 9; + BITFIELD_TYPE(term_weight_t, unsigned int) weight : 1; + BITFIELD_TYPE(term_posture_t, unsigned int) posture : 1; + BITFIELD_TYPE(term_underline_t, unsigned int) underline : 1; +} attributes_t; + + +/* ============================ term_ostream_t ============================ */ + +#line 943 "term-ostream.c" +#if !IS_CPLUSPLUS +#define term_ostream_representation any_ostream_representation +#endif +#include "term_ostream.priv.h" + +const typeinfo_t term_ostream_typeinfo = { "term_ostream" }; + +static const typeinfo_t * const term_ostream_superclasses[] = + { term_ostream_SUPERCLASSES }; + +#define super ostream_vtable + +#line 979 "term-ostream.oo.c" + +/* Simplify attributes, according to the terminal's capabilities. */ +static attributes_t +simplify_attributes (term_ostream_t stream, attributes_t attr) +{ + if ((attr.color != COLOR_DEFAULT || attr.bgcolor != COLOR_DEFAULT) + && stream->no_color_video > 0) + { + /* When colors and attributes can not be represented simultaneously, + we give preference to the color. */ + if (stream->no_color_video & 2) + /* Colors conflict with underlining. */ + attr.underline = UNDERLINE_OFF; + if (stream->no_color_video & 32) + /* Colors conflict with bold weight. */ + attr.weight = WEIGHT_NORMAL; + } + if (!stream->supports_foreground) + attr.color = COLOR_DEFAULT; + if (!stream->supports_background) + attr.bgcolor = COLOR_DEFAULT; + if (!stream->supports_weight) + attr.weight = WEIGHT_DEFAULT; + if (!stream->supports_posture) + attr.posture = POSTURE_DEFAULT; + if (!stream->supports_underline) + attr.underline = UNDERLINE_DEFAULT; + return attr; +} + +/* While a line is being output, we need to be careful to restore the + terminal's settings in case of a fatal signal or an exit() call. */ + +/* File descriptor to which out_char shall output escape sequences. */ +static int out_fd = -1; + +/* Filename of out_fd. */ +static const char *out_filename; + +/* Output a single char to out_fd. Ignore errors. */ +static int +out_char_unchecked (int c) +{ + char bytes[1]; + + bytes[0] = (char)c; + full_write (out_fd, bytes, 1); + return 0; +} + +/* State that informs the exit handler what to do. */ +static const char *restore_colors; +static const char *restore_weight; +static const char *restore_posture; +static const char *restore_underline; + +/* The exit handler. */ +static void +restore (void) +{ + /* Only do something while some output was interrupted. */ + if (out_fd >= 0) + { + if (restore_colors != NULL) + tputs (restore_colors, 1, out_char_unchecked); + if (restore_weight != NULL) + tputs (restore_weight, 1, out_char_unchecked); + if (restore_posture != NULL) + tputs (restore_posture, 1, out_char_unchecked); + if (restore_underline != NULL) + tputs (restore_underline, 1, out_char_unchecked); + } +} + +/* The list of signals whose default behaviour is to stop the program. */ +static int stopping_signals[] = + { +#ifdef SIGTSTP + SIGTSTP, +#endif +#ifdef SIGTTIN + SIGTTIN, +#endif +#ifdef SIGTTOU + SIGTTOU, +#endif + 0 + }; + +#define num_stopping_signals (SIZEOF (stopping_signals) - 1) + +static sigset_t stopping_signal_set; + +static void +init_stopping_signal_set () +{ + static bool stopping_signal_set_initialized = false; + if (!stopping_signal_set_initialized) + { + size_t i; + + sigemptyset (&stopping_signal_set); + for (i = 0; i < num_stopping_signals; i++) + sigaddset (&stopping_signal_set, stopping_signals[i]); + + stopping_signal_set_initialized = true; + } +} + +/* Temporarily delay the stopping signals. */ +static inline void +block_stopping_signals () +{ + init_stopping_signal_set (); + sigprocmask (SIG_BLOCK, &stopping_signal_set, NULL); +} + +/* Stop delaying the stopping signals. */ +static inline void +unblock_stopping_signals () +{ + init_stopping_signal_set (); + sigprocmask (SIG_UNBLOCK, &stopping_signal_set, NULL); +} + +/* Compare two sets of attributes for equality. */ +static inline bool +equal_attributes (attributes_t attr1, attributes_t attr2) +{ + return (attr1.color == attr2.color + && attr1.bgcolor == attr2.bgcolor + && attr1.weight == attr2.weight + && attr1.posture == attr2.posture + && attr1.underline == attr2.underline); +} + +/* Signal error after full_write failed. */ +static void +out_error () +{ + error (EXIT_FAILURE, errno, _("error writing to %s"), out_filename); +} + +/* Output a single char to out_fd. */ +static int +out_char (int c) +{ + char bytes[1]; + + bytes[0] = (char)c; + /* We have to write directly to the file descriptor, not to a buffer with + the same destination, because of the padding and sleeping that tputs() + does. */ + if (full_write (out_fd, bytes, 1) < 1) + out_error (); + return 0; +} + +/* Output escape sequences to switch from OLD_ATTR to NEW_ATTR. */ +static void +out_attr_change (term_ostream_t stream, + attributes_t old_attr, attributes_t new_attr) +{ + bool cleared_attributes; + + /* We don't know the default colors of the terminal. The only way to switch + back to a default color is to use stream->orig_pair. */ + if ((new_attr.color == COLOR_DEFAULT && old_attr.color != COLOR_DEFAULT) + || (new_attr.bgcolor == COLOR_DEFAULT && old_attr.bgcolor != COLOR_DEFAULT)) + { + assert (stream->supports_foreground || stream->supports_background); + tputs (stream->orig_pair, 1, out_char); + old_attr.color = COLOR_DEFAULT; + old_attr.bgcolor = COLOR_DEFAULT; + } + + /* To turn off WEIGHT_BOLD, the only way is to output the exit_attribute_mode + sequence. (With xterm, you can also do it with "Esc [ 0 m", but this + escape sequence is not contained in the terminfo description.) It may + also clear the colors; this is the case e.g. when TERM="xterm" or + TERM="ansi". + To turn off UNDERLINE_ON, we can use the exit_underline_mode or the + exit_attribute_mode sequence. In the latter case, it will not only + turn off UNDERLINE_ON, but also the other attributes, and possibly also + the colors. + To turn off POSTURE_ITALIC, we can use the exit_italics_mode or the + exit_attribute_mode sequence. Again, in the latter case, it will not + only turn off POSTURE_ITALIC, but also the other attributes, and possibly + also the colors. + There is no point in setting an attribute just before emitting an + escape sequence that may again turn off the attribute. Therefore we + proceed in two steps: First, clear the attributes that need to be + cleared; then - taking into account that this may have cleared all + attributes and all colors - set the colors and the attributes. + The variable 'cleared_attributes' tells whether an escape sequence + has been output that may have cleared all attributes and all color + settings. */ + cleared_attributes = false; + if (old_attr.posture != POSTURE_NORMAL + && new_attr.posture == POSTURE_NORMAL + && stream->exit_italics_mode != NULL) + { + tputs (stream->exit_italics_mode, 1, out_char); + old_attr.posture = POSTURE_NORMAL; + cleared_attributes = true; + } + if (old_attr.underline != UNDERLINE_OFF + && new_attr.underline == UNDERLINE_OFF + && stream->exit_underline_mode != NULL) + { + tputs (stream->exit_underline_mode, 1, out_char); + old_attr.underline = UNDERLINE_OFF; + cleared_attributes = true; + } + if ((old_attr.weight != WEIGHT_NORMAL + && new_attr.weight == WEIGHT_NORMAL) + || (old_attr.posture != POSTURE_NORMAL + && new_attr.posture == POSTURE_NORMAL + /* implies stream->exit_italics_mode == NULL */) + || (old_attr.underline != UNDERLINE_OFF + && new_attr.underline == UNDERLINE_OFF + /* implies stream->exit_underline_mode == NULL */)) + { + tputs (stream->exit_attribute_mode, 1, out_char); + /* We don't know exactly what effects exit_attribute_mode has, but + this is the minimum effect: */ + old_attr.weight = WEIGHT_NORMAL; + if (stream->exit_italics_mode == NULL) + old_attr.posture = POSTURE_NORMAL; + if (stream->exit_underline_mode == NULL) + old_attr.underline = UNDERLINE_OFF; + cleared_attributes = true; + } + + /* Turn on the colors. */ + if (new_attr.color != old_attr.color + || (cleared_attributes && new_attr.color != COLOR_DEFAULT)) + { + assert (stream->supports_foreground); + assert (new_attr.color != COLOR_DEFAULT); + switch (stream->colormodel) + { + case cm_common8: + assert (new_attr.color >= 0 && new_attr.color < 8); + if (stream->set_a_foreground != NULL) + tputs (tparm (stream->set_a_foreground, + color_bgr (new_attr.color)), + 1, out_char); + else + tputs (tparm (stream->set_foreground, new_attr.color), + 1, out_char); + break; + /* When we are dealing with an xterm, there is no need to go through + tputs() because we know there is no padding and sleeping. */ + case cm_xterm8: + assert (new_attr.color >= 0 && new_attr.color < 8); + { + char bytes[5]; + bytes[0] = 0x1B; bytes[1] = '['; + bytes[2] = '3'; bytes[3] = '0' + new_attr.color; + bytes[4] = 'm'; + if (full_write (out_fd, bytes, 5) < 5) + out_error (); + } + break; + case cm_xterm16: + assert (new_attr.color >= 0 && new_attr.color < 16); + { + char bytes[5]; + bytes[0] = 0x1B; bytes[1] = '['; + if (new_attr.color < 8) + { + bytes[2] = '3'; bytes[3] = '0' + new_attr.color; + } + else + { + bytes[2] = '9'; bytes[3] = '0' + (new_attr.color - 8); + } + bytes[4] = 'm'; + if (full_write (out_fd, bytes, 5) < 5) + out_error (); + } + break; + case cm_xterm88: + assert (new_attr.color >= 0 && new_attr.color < 88); + { + char bytes[10]; + char *p; + bytes[0] = 0x1B; bytes[1] = '['; + bytes[2] = '3'; bytes[3] = '8'; bytes[4] = ';'; + bytes[5] = '5'; bytes[6] = ';'; + p = bytes + 7; + if (new_attr.color >= 10) + *p++ = '0' + (new_attr.color / 10); + *p++ = '0' + (new_attr.color % 10); + *p++ = 'm'; + if (full_write (out_fd, bytes, p - bytes) < p - bytes) + out_error (); + } + break; + case cm_xterm256: + assert (new_attr.color >= 0 && new_attr.color < 256); + { + char bytes[11]; + char *p; + bytes[0] = 0x1B; bytes[1] = '['; + bytes[2] = '3'; bytes[3] = '8'; bytes[4] = ';'; + bytes[5] = '5'; bytes[6] = ';'; + p = bytes + 7; + if (new_attr.color >= 100) + *p++ = '0' + (new_attr.color / 100); + if (new_attr.color >= 10) + *p++ = '0' + ((new_attr.color % 100) / 10); + *p++ = '0' + (new_attr.color % 10); + *p++ = 'm'; + if (full_write (out_fd, bytes, p - bytes) < p - bytes) + out_error (); + } + break; + default: + abort (); + } + } + if (new_attr.bgcolor != old_attr.bgcolor + || (cleared_attributes && new_attr.bgcolor != COLOR_DEFAULT)) + { + assert (stream->supports_background); + assert (new_attr.bgcolor != COLOR_DEFAULT); + switch (stream->colormodel) + { + case cm_common8: + assert (new_attr.bgcolor >= 0 && new_attr.bgcolor < 8); + if (stream->set_a_background != NULL) + tputs (tparm (stream->set_a_background, + color_bgr (new_attr.bgcolor)), + 1, out_char); + else + tputs (tparm (stream->set_background, new_attr.bgcolor), + 1, out_char); + break; + /* When we are dealing with an xterm, there is no need to go through + tputs() because we know there is no padding and sleeping. */ + case cm_xterm8: + assert (new_attr.bgcolor >= 0 && new_attr.bgcolor < 8); + { + char bytes[5]; + bytes[0] = 0x1B; bytes[1] = '['; + bytes[2] = '4'; bytes[3] = '0' + new_attr.bgcolor; + bytes[4] = 'm'; + if (full_write (out_fd, bytes, 5) < 5) + out_error (); + } + break; + case cm_xterm16: + assert (new_attr.bgcolor >= 0 && new_attr.bgcolor < 16); + { + char bytes[6]; + bytes[0] = 0x1B; bytes[1] = '['; + if (new_attr.bgcolor < 8) + { + bytes[2] = '4'; bytes[3] = '0' + new_attr.bgcolor; + bytes[4] = 'm'; + if (full_write (out_fd, bytes, 5) < 5) + out_error (); + } + else + { + bytes[2] = '1'; bytes[3] = '0'; + bytes[4] = '0' + (new_attr.bgcolor - 8); bytes[5] = 'm'; + if (full_write (out_fd, bytes, 6) < 6) + out_error (); + } + } + break; + case cm_xterm88: + assert (new_attr.bgcolor >= 0 && new_attr.bgcolor < 88); + { + char bytes[10]; + char *p; + bytes[0] = 0x1B; bytes[1] = '['; + bytes[2] = '4'; bytes[3] = '8'; bytes[4] = ';'; + bytes[5] = '5'; bytes[6] = ';'; + p = bytes + 7; + if (new_attr.bgcolor >= 10) + *p++ = '0' + (new_attr.bgcolor / 10); + *p++ = '0' + (new_attr.bgcolor % 10); + *p++ = 'm'; + if (full_write (out_fd, bytes, p - bytes) < p - bytes) + out_error (); + } + break; + case cm_xterm256: + assert (new_attr.bgcolor >= 0 && new_attr.bgcolor < 256); + { + char bytes[11]; + char *p; + bytes[0] = 0x1B; bytes[1] = '['; + bytes[2] = '4'; bytes[3] = '8'; bytes[4] = ';'; + bytes[5] = '5'; bytes[6] = ';'; + p = bytes + 7; + if (new_attr.bgcolor >= 100) + *p++ = '0' + (new_attr.bgcolor / 100); + if (new_attr.bgcolor >= 10) + *p++ = '0' + ((new_attr.bgcolor % 100) / 10); + *p++ = '0' + (new_attr.bgcolor % 10); + *p++ = 'm'; + if (full_write (out_fd, bytes, p - bytes) < p - bytes) + out_error (); + } + break; + default: + abort (); + } + } + + if (new_attr.weight != old_attr.weight + || (cleared_attributes && new_attr.weight != WEIGHT_DEFAULT)) + { + assert (stream->supports_weight); + assert (new_attr.weight != WEIGHT_DEFAULT); + /* This implies: */ + assert (new_attr.weight == WEIGHT_BOLD); + tputs (stream->enter_bold_mode, 1, out_char); + } + if (new_attr.posture != old_attr.posture + || (cleared_attributes && new_attr.posture != POSTURE_DEFAULT)) + { + assert (stream->supports_posture); + assert (new_attr.posture != POSTURE_DEFAULT); + /* This implies: */ + assert (new_attr.posture == POSTURE_ITALIC); + tputs (stream->enter_italics_mode, 1, out_char); + } + if (new_attr.underline != old_attr.underline + || (cleared_attributes && new_attr.underline != UNDERLINE_DEFAULT)) + { + assert (stream->supports_underline); + assert (new_attr.underline != UNDERLINE_DEFAULT); + /* This implies: */ + assert (new_attr.underline == UNDERLINE_ON); + tputs (stream->enter_underline_mode, 1, out_char); + } +} + +/* Output the buffered line atomically. + The terminal is assumed to have the default state (regarding colors and + attributes) before this call. It is left in default state after this + call (regardless of stream->curr_attr). */ +static void +output_buffer (term_ostream_t stream) +{ + attributes_t default_attr; + attributes_t attr; + const char *cp; + const attributes_t *ap; + size_t len; + size_t n; + + default_attr.color = COLOR_DEFAULT; + default_attr.bgcolor = COLOR_DEFAULT; + default_attr.weight = WEIGHT_DEFAULT; + default_attr.posture = POSTURE_DEFAULT; + default_attr.underline = UNDERLINE_DEFAULT; + + attr = default_attr; + + cp = stream->buffer; + ap = stream->attrbuffer; + len = stream->buflen; + + /* See how much we can output without blocking signals. */ + for (n = 0; n < len && equal_attributes (ap[n], attr); n++) + ; + if (n > 0) + { + if (full_write (stream->fd, cp, n) < n) + error (EXIT_FAILURE, errno, _("error writing to %s"), stream->filename); + cp += n; + ap += n; + len -= n; + } + if (len > 0) + { + /* Block fatal signals, so that a SIGINT or similar doesn't interrupt + us without the possibility of restoring the terminal's state. */ + block_fatal_signals (); + /* Likewise for SIGTSTP etc. */ + block_stopping_signals (); + + /* Enable the exit handler for restoring the terminal's state. */ + restore_colors = + (stream->supports_foreground || stream->supports_background + ? stream->orig_pair + : NULL); + restore_weight = + (stream->supports_weight ? stream->exit_attribute_mode : NULL); + restore_posture = + (stream->supports_posture + ? (stream->exit_italics_mode != NULL + ? stream->exit_italics_mode + : stream->exit_attribute_mode) + : NULL); + restore_underline = + (stream->supports_underline + ? (stream->exit_underline_mode != NULL + ? stream->exit_underline_mode + : stream->exit_attribute_mode) + : NULL); + out_fd = stream->fd; + out_filename = stream->filename; + + while (len > 0) + { + /* Activate the attributes in *ap. */ + out_attr_change (stream, attr, *ap); + attr = *ap; + /* See how many characters we can output without further attribute + changes. */ + for (n = 1; n < len && equal_attributes (ap[n], attr); n++) + ; + if (full_write (stream->fd, cp, n) < n) + error (EXIT_FAILURE, errno, _("error writing to %s"), + stream->filename); + cp += n; + ap += n; + len -= n; + } + + /* Switch back to the default attributes. */ + out_attr_change (stream, attr, default_attr); + + /* Disable the exit handler. */ + out_fd = -1; + out_filename = NULL; + + /* Unblock fatal and stopping signals. */ + unblock_stopping_signals (); + unblock_fatal_signals (); + } + stream->buflen = 0; +} + +/* Implementation of ostream_t methods. */ + +static term_color_t +term_ostream__rgb_to_color (term_ostream_t stream, int red, int green, int blue) +{ + switch (stream->colormodel) + { + case cm_monochrome: + return rgb_to_color_monochrome (); + case cm_common8: + return rgb_to_color_common8 (red, green, blue); + case cm_xterm8: + return rgb_to_color_xterm8 (red, green, blue); + case cm_xterm16: + return rgb_to_color_xterm16 (red, green, blue); + case cm_xterm88: + return rgb_to_color_xterm88 (red, green, blue); + case cm_xterm256: + return rgb_to_color_xterm256 (red, green, blue); + default: + abort (); + } +} + +static void +term_ostream__write_mem (term_ostream_t stream, const void *data, size_t len) +{ + const char *cp = (const char *) data; + while (len > 0) + { + /* Look for the next newline. */ + const char *newline = (const char *) memchr (cp, '\n', len); + size_t n = (newline != NULL ? newline - cp : len); + + /* Copy n bytes into the buffer. */ + if (n > stream->allocated - stream->buflen) + { + size_t new_allocated = + xmax (xsum (stream->buflen, n), + xsum (stream->allocated, stream->allocated)); + if (size_overflow_p (new_allocated)) + error (EXIT_FAILURE, 0, + _("%s: too much output, buffer size overflow"), + "term_ostream"); + stream->buffer = (char *) xrealloc (stream->buffer, new_allocated); + stream->attrbuffer = + (attributes_t *) + xrealloc (stream->attrbuffer, + new_allocated * sizeof (attributes_t)); + stream->allocated = new_allocated; + } + memcpy (stream->buffer + stream->buflen, cp, n); + { + attributes_t attr = stream->simp_attr; + attributes_t *ap = stream->attrbuffer + stream->buflen; + attributes_t *ap_end = ap + n; + for (; ap < ap_end; ap++) + *ap = attr; + } + stream->buflen += n; + + if (newline != NULL) + { + output_buffer (stream); + if (full_write (stream->fd, "\n", 1) < 1) + error (EXIT_FAILURE, errno, _("error writing to %s"), + stream->filename); + cp += n + 1; /* cp = newline + 1; */ + len -= n + 1; + } + else + break; + } +} + +static void +term_ostream__flush (term_ostream_t stream) +{ + output_buffer (stream); +} + +static void +term_ostream__free (term_ostream_t stream) +{ + term_ostream_flush (stream); + free (stream->filename); + if (stream->set_a_foreground != NULL) + free (stream->set_a_foreground); + if (stream->set_foreground != NULL) + free (stream->set_foreground); + if (stream->set_a_background != NULL) + free (stream->set_a_background); + if (stream->set_background != NULL) + free (stream->set_background); + if (stream->orig_pair != NULL) + free (stream->orig_pair); + if (stream->enter_bold_mode != NULL) + free (stream->enter_bold_mode); + if (stream->enter_italics_mode != NULL) + free (stream->enter_italics_mode); + if (stream->exit_italics_mode != NULL) + free (stream->exit_italics_mode); + if (stream->enter_underline_mode != NULL) + free (stream->enter_underline_mode); + if (stream->exit_underline_mode != NULL) + free (stream->exit_underline_mode); + if (stream->exit_attribute_mode != NULL) + free (stream->exit_attribute_mode); + free (stream->buffer); + free (stream); +} + +/* Implementation of term_ostream_t methods. */ + +static term_color_t +term_ostream__get_color (term_ostream_t stream) +{ + return stream->curr_attr.color; +} + +static void +term_ostream__set_color (term_ostream_t stream, term_color_t color) +{ + stream->curr_attr.color = color; + stream->simp_attr = simplify_attributes (stream, stream->curr_attr); +} + +static term_color_t +term_ostream__get_bgcolor (term_ostream_t stream) +{ + return stream->curr_attr.bgcolor; +} + +static void +term_ostream__set_bgcolor (term_ostream_t stream, term_color_t color) +{ + stream->curr_attr.bgcolor = color; + stream->simp_attr = simplify_attributes (stream, stream->curr_attr); +} + +static term_weight_t +term_ostream__get_weight (term_ostream_t stream) +{ + return stream->curr_attr.weight; +} + +static void +term_ostream__set_weight (term_ostream_t stream, term_weight_t weight) +{ + stream->curr_attr.weight = weight; + stream->simp_attr = simplify_attributes (stream, stream->curr_attr); +} + +static term_posture_t +term_ostream__get_posture (term_ostream_t stream) +{ + return stream->curr_attr.posture; +} + +static void +term_ostream__set_posture (term_ostream_t stream, term_posture_t posture) +{ + stream->curr_attr.posture = posture; + stream->simp_attr = simplify_attributes (stream, stream->curr_attr); +} + +static term_underline_t +term_ostream__get_underline (term_ostream_t stream) +{ + return stream->curr_attr.underline; +} + +static void +term_ostream__set_underline (term_ostream_t stream, term_underline_t underline) +{ + stream->curr_attr.underline = underline; + stream->simp_attr = simplify_attributes (stream, stream->curr_attr); +} + +/* Constructor. */ + +static inline char * +xstrdup0 (const char *str) +{ + if (str == NULL) + return NULL; +#if HAVE_TERMINFO + if (str == (const char *)(-1)) + return NULL; +#endif + return xstrdup (str); +} + +term_ostream_t +term_ostream_create (int fd, const char *filename) +{ + term_ostream_t stream = XMALLOC (struct term_ostream_representation); + const char *term; + + stream->base.vtable = &term_ostream_vtable; + stream->fd = fd; + stream->filename = xstrdup (filename); + + /* Defaults. */ + stream->max_colors = -1; + stream->no_color_video = -1; + stream->set_a_foreground = NULL; + stream->set_foreground = NULL; + stream->set_a_background = NULL; + stream->set_background = NULL; + stream->orig_pair = NULL; + stream->enter_bold_mode = NULL; + stream->enter_italics_mode = NULL; + stream->exit_italics_mode = NULL; + stream->enter_underline_mode = NULL; + stream->exit_underline_mode = NULL; + stream->exit_attribute_mode = NULL; + + /* Retrieve the terminal type. */ + term = getenv ("TERM"); + if (term != NULL && term[0] != '\0') + { + /* When the terminfo function are available, we prefer them over the + termcap functions because + 1. they don't risk a buffer overflow, + 2. on OSF/1, for TERM=xterm, the tiget* functions provide access + to the number of colors and the color escape sequences, whereas + the tget* functions don't provide them. */ +#if HAVE_TERMINFO + int err = 1; + + if (setupterm (term, fd, &err) || err == 1) + { + /* Retrieve particular values depending on the terminal type. */ + stream->max_colors = tigetnum ("colors"); + stream->no_color_video = tigetnum ("ncv"); + stream->set_a_foreground = xstrdup0 (tigetstr ("setaf")); + stream->set_foreground = xstrdup0 (tigetstr ("setf")); + stream->set_a_background = xstrdup0 (tigetstr ("setab")); + stream->set_background = xstrdup0 (tigetstr ("setb")); + stream->orig_pair = xstrdup0 (tigetstr ("op")); + stream->enter_bold_mode = xstrdup0 (tigetstr ("bold")); + stream->enter_italics_mode = xstrdup0 (tigetstr ("sitm")); + stream->exit_italics_mode = xstrdup0 (tigetstr ("ritm")); + stream->enter_underline_mode = xstrdup0 (tigetstr ("smul")); + stream->exit_underline_mode = xstrdup0 (tigetstr ("rmul")); + stream->exit_attribute_mode = xstrdup0 (tigetstr ("sgr0")); + } +#elif HAVE_TERMCAP + struct { char buf[1024]; char canary[4]; } termcapbuf; + int retval; + + /* Call tgetent, being defensive against buffer overflow. */ + memcpy (termcapbuf.canary, "CnRy", 4); + retval = tgetent (termcapbuf.buf, term); + if (memcmp (termcapbuf.canary, "CnRy", 4) != 0) + /* Buffer overflow! */ + abort (); + + if (retval > 0) + { + struct { char buf[1024]; char canary[4]; } termentrybuf; + char *termentryptr; + + /* Prepare for calling tgetstr, being defensive against buffer + overflow. ncurses' tgetstr() supports a second argument NULL, + but NetBSD's tgetstr() doesn't. */ + memcpy (termentrybuf.canary, "CnRz", 4); + #define TEBP ((termentryptr = termentrybuf.buf), &termentryptr) + + /* Retrieve particular values depending on the terminal type. */ + stream->max_colors = tgetnum ("Co"); + stream->no_color_video = tgetnum ("NC"); + stream->set_a_foreground = xstrdup0 (tgetstr ("AF", TEBP)); + stream->set_foreground = xstrdup0 (tgetstr ("Sf", TEBP)); + stream->set_a_background = xstrdup0 (tgetstr ("AB", TEBP)); + stream->set_background = xstrdup0 (tgetstr ("Sb", TEBP)); + stream->orig_pair = xstrdup0 (tgetstr ("op", TEBP)); + stream->enter_bold_mode = xstrdup0 (tgetstr ("md", TEBP)); + stream->enter_italics_mode = xstrdup0 (tgetstr ("ZH", TEBP)); + stream->exit_italics_mode = xstrdup0 (tgetstr ("ZR", TEBP)); + stream->enter_underline_mode = xstrdup0 (tgetstr ("us", TEBP)); + stream->exit_underline_mode = xstrdup0 (tgetstr ("ue", TEBP)); + stream->exit_attribute_mode = xstrdup0 (tgetstr ("me", TEBP)); + +# ifdef __BEOS__ + /* The BeOS termcap entry for "beterm" is broken: For "AF" and "AB" + it contains balues in terminfo syntax but the system's tparam() + function understands only the termcap syntax. */ + if (stream->set_a_foreground != NULL + && strcmp (stream->set_a_foreground, "\033[3%p1%dm") == 0) + { + free (stream->set_a_foreground); + stream->set_a_foreground = xstrdup ("\033[3%dm"); + } + if (stream->set_a_background != NULL + && strcmp (stream->set_a_background, "\033[4%p1%dm") == 0) + { + free (stream->set_a_background); + stream->set_a_background = xstrdup ("\033[4%dm"); + } +# endif + + /* The termcap entry for cygwin is broken: It has no "ncv" value, + but bold and underline are actually rendered through colors. */ + if (strcmp (term, "cygwin") == 0) + stream->no_color_video |= 2 | 32; + + /* Done with tgetstr. Detect possible buffer overflow. */ + #undef TEBP + if (memcmp (termentrybuf.canary, "CnRz", 4) != 0) + /* Buffer overflow! */ + abort (); + } +#else + /* Fallback code for platforms with neither the terminfo nor the termcap + functions, such as mingw. + Assume the ANSI escape sequences. Extracted through + "TERM=ansi infocmp", replacing \E with \033. */ + stream->max_colors = 8; + stream->no_color_video = 3; + stream->set_a_foreground = xstrdup ("\033[3%p1%dm"); + stream->set_a_background = xstrdup ("\033[4%p1%dm"); + stream->orig_pair = xstrdup ("\033[39;49m"); + stream->enter_bold_mode = xstrdup ("\033[1m"); + stream->enter_underline_mode = xstrdup ("\033[4m"); + stream->exit_underline_mode = xstrdup ("\033[m"); + stream->exit_attribute_mode = xstrdup ("\033[0;10m"); +#endif + + /* AIX 4.3.2, IRIX 6.5, HP-UX 11, Solaris 7..10 all lack the + description of color capabilities of "xterm" and "xterms" + in their terminfo database. But it is important to have + color in xterm. So we provide the color capabilities here. */ + if (stream->max_colors <= 1 + && (strcmp (term, "xterm") == 0 || strcmp (term, "xterms") == 0)) + { + stream->max_colors = 8; + stream->set_a_foreground = xstrdup ("\033[3%p1%dm"); + stream->set_a_background = xstrdup ("\033[4%p1%dm"); + stream->orig_pair = xstrdup ("\033[39;49m"); + } + } + + /* Infer the capabilities. */ + stream->supports_foreground = + (stream->max_colors >= 8 + && (stream->set_a_foreground != NULL || stream->set_foreground != NULL) + && stream->orig_pair != NULL); + stream->supports_background = + (stream->max_colors >= 8 + && (stream->set_a_background != NULL || stream->set_background != NULL) + && stream->orig_pair != NULL); + stream->colormodel = + (stream->supports_foreground || stream->supports_background + ? (term != NULL + && (/* Recognize xterm-16color, xterm-88color, xterm-256color. */ + (strlen (term) >= 5 && memcmp (term, "xterm", 5) == 0) + || /* Recognize rxvt-16color. */ + (strlen (term) >= 4 && memcmp (term, "rxvt", 7) == 0) + || /* Recognize konsole-16color. */ + (strlen (term) >= 7 && memcmp (term, "konsole", 7) == 0)) + ? (stream->max_colors == 256 ? cm_xterm256 : + stream->max_colors == 88 ? cm_xterm88 : + stream->max_colors == 16 ? cm_xterm16 : + cm_xterm8) + : cm_common8) + : cm_monochrome); + stream->supports_weight = + (stream->enter_bold_mode != NULL && stream->exit_attribute_mode != NULL); + stream->supports_posture = + (stream->enter_italics_mode != NULL + && (stream->exit_italics_mode != NULL + || stream->exit_attribute_mode != NULL)); + stream->supports_underline = + (stream->enter_underline_mode != NULL + && (stream->exit_underline_mode != NULL + || stream->exit_attribute_mode != NULL)); + + /* Initialize the buffer. */ + stream->allocated = 120; + stream->buffer = XNMALLOC (stream->allocated, char); + stream->attrbuffer = XNMALLOC (stream->allocated, attributes_t); + stream->buflen = 0; + + /* Initialize the current attributes. */ + stream->curr_attr.color = COLOR_DEFAULT; + stream->curr_attr.bgcolor = COLOR_DEFAULT; + stream->curr_attr.weight = WEIGHT_DEFAULT; + stream->curr_attr.posture = POSTURE_DEFAULT; + stream->curr_attr.underline = UNDERLINE_DEFAULT; + stream->simp_attr = simplify_attributes (stream, stream->curr_attr); + + /* Register an exit handler. */ + { + static bool registered = false; + if (!registered) + { + atexit (restore); + registered = true; + } + } + + return stream; +} + +#line 1905 "term-ostream.c" + +const struct term_ostream_implementation term_ostream_vtable = +{ + term_ostream_superclasses, + sizeof (term_ostream_superclasses) / sizeof (term_ostream_superclasses[0]), + sizeof (struct term_ostream_representation), + term_ostream__write_mem, + term_ostream__flush, + term_ostream__free, + term_ostream__rgb_to_color, + term_ostream__get_color, + term_ostream__set_color, + term_ostream__get_bgcolor, + term_ostream__set_bgcolor, + term_ostream__get_weight, + term_ostream__set_weight, + term_ostream__get_posture, + term_ostream__set_posture, + term_ostream__get_underline, + term_ostream__set_underline, +}; + +#if !HAVE_INLINE + +/* Define the functions that invoke the methods. */ + +void +term_ostream_write_mem (term_ostream_t first_arg, const void *data, size_t len) +{ + const struct term_ostream_implementation *vtable = + ((struct term_ostream_representation_header *) (struct term_ostream_representation *) first_arg)->vtable; + vtable->write_mem (first_arg,data,len); +} + +void +term_ostream_flush (term_ostream_t first_arg) +{ + const struct term_ostream_implementation *vtable = + ((struct term_ostream_representation_header *) (struct term_ostream_representation *) first_arg)->vtable; + vtable->flush (first_arg); +} + +void +term_ostream_free (term_ostream_t first_arg) +{ + const struct term_ostream_implementation *vtable = + ((struct term_ostream_representation_header *) (struct term_ostream_representation *) first_arg)->vtable; + vtable->free (first_arg); +} + +term_color_t +term_ostream_rgb_to_color (term_ostream_t first_arg, int red, int green, int blue) +{ + const struct term_ostream_implementation *vtable = + ((struct term_ostream_representation_header *) (struct term_ostream_representation *) first_arg)->vtable; + return vtable->rgb_to_color (first_arg,red,green,blue); +} + +term_color_t +term_ostream_get_color (term_ostream_t first_arg) +{ + const struct term_ostream_implementation *vtable = + ((struct term_ostream_representation_header *) (struct term_ostream_representation *) first_arg)->vtable; + return vtable->get_color (first_arg); +} + +void +term_ostream_set_color (term_ostream_t first_arg, term_color_t color) +{ + const struct term_ostream_implementation *vtable = + ((struct term_ostream_representation_header *) (struct term_ostream_representation *) first_arg)->vtable; + vtable->set_color (first_arg,color); +} + +term_color_t +term_ostream_get_bgcolor (term_ostream_t first_arg) +{ + const struct term_ostream_implementation *vtable = + ((struct term_ostream_representation_header *) (struct term_ostream_representation *) first_arg)->vtable; + return vtable->get_bgcolor (first_arg); +} + +void +term_ostream_set_bgcolor (term_ostream_t first_arg, term_color_t color) +{ + const struct term_ostream_implementation *vtable = + ((struct term_ostream_representation_header *) (struct term_ostream_representation *) first_arg)->vtable; + vtable->set_bgcolor (first_arg,color); +} + +term_weight_t +term_ostream_get_weight (term_ostream_t first_arg) +{ + const struct term_ostream_implementation *vtable = + ((struct term_ostream_representation_header *) (struct term_ostream_representation *) first_arg)->vtable; + return vtable->get_weight (first_arg); +} + +void +term_ostream_set_weight (term_ostream_t first_arg, term_weight_t weight) +{ + const struct term_ostream_implementation *vtable = + ((struct term_ostream_representation_header *) (struct term_ostream_representation *) first_arg)->vtable; + vtable->set_weight (first_arg,weight); +} + +term_posture_t +term_ostream_get_posture (term_ostream_t first_arg) +{ + const struct term_ostream_implementation *vtable = + ((struct term_ostream_representation_header *) (struct term_ostream_representation *) first_arg)->vtable; + return vtable->get_posture (first_arg); +} + +void +term_ostream_set_posture (term_ostream_t first_arg, term_posture_t posture) +{ + const struct term_ostream_implementation *vtable = + ((struct term_ostream_representation_header *) (struct term_ostream_representation *) first_arg)->vtable; + vtable->set_posture (first_arg,posture); +} + +term_underline_t +term_ostream_get_underline (term_ostream_t first_arg) +{ + const struct term_ostream_implementation *vtable = + ((struct term_ostream_representation_header *) (struct term_ostream_representation *) first_arg)->vtable; + return vtable->get_underline (first_arg); +} + +void +term_ostream_set_underline (term_ostream_t first_arg, term_underline_t underline) +{ + const struct term_ostream_implementation *vtable = + ((struct term_ostream_representation_header *) (struct term_ostream_representation *) first_arg)->vtable; + vtable->set_underline (first_arg,underline); +} + +#endif diff --git a/gettext-tools/gnulib-lib/term-ostream.h b/gettext-tools/gnulib-lib/term-ostream.h new file mode 100644 index 0000000..8ede7e3 --- /dev/null +++ b/gettext-tools/gnulib-lib/term-ostream.h @@ -0,0 +1,282 @@ +/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ + +#line 1 "term-ostream.oo.h" +/* Output stream for attributed text, producing ANSI escape sequences. + Copyright (C) 2006 Free Software Foundation, Inc. + Written by Bruno Haible , 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _TERM_OSTREAM_H +#define _TERM_OSTREAM_H + +#include "ostream.h" + + +/* Querying and setting of text attributes. + The stream has a notion of the current text attributes; they apply + implicitly to all following output. The attributes are automatically + reset when the stream is closed. + Note: Not all terminal types can actually render all attributes adequately. + For example, xterm cannot render POSTURE_ITALIC nor the combination of + WEIGHT_BOLD and UNDERLINE_ON. */ + +/* Colors are represented by indices >= 0 in a stream dependent format. */ +typedef int term_color_t; +/* The value -1 denotes the default (foreground or background) color. */ +enum +{ + COLOR_DEFAULT = -1 /* unknown */ +}; + +typedef enum +{ + WEIGHT_NORMAL = 0, + WEIGHT_BOLD, + WEIGHT_DEFAULT = WEIGHT_NORMAL +} term_weight_t; + +typedef enum +{ + POSTURE_NORMAL = 0, + POSTURE_ITALIC, /* same as oblique */ + POSTURE_DEFAULT = POSTURE_NORMAL +} term_posture_t; + +typedef enum +{ + UNDERLINE_OFF = 0, + UNDERLINE_ON, + UNDERLINE_DEFAULT = UNDERLINE_OFF +} term_underline_t; + +#line 65 "term-ostream.h" +struct term_ostream_representation; +/* term_ostream_t is defined as a pointer to struct term_ostream_representation. + In C++ mode, we use a smart pointer class. + In C mode, we have no other choice than a typedef to the root class type. */ +#if IS_CPLUSPLUS +struct term_ostream_t +{ +private: + struct term_ostream_representation *_pointer; +public: + term_ostream_t () : _pointer (NULL) {} + term_ostream_t (struct term_ostream_representation *pointer) : _pointer (pointer) {} + struct term_ostream_representation * operator -> () { return _pointer; } + operator struct term_ostream_representation * () { return _pointer; } + operator struct any_ostream_representation * () { return (struct any_ostream_representation *) _pointer; } + operator void * () { return _pointer; } + bool operator == (const void *p) { return _pointer == p; } + bool operator != (const void *p) { return _pointer != p; } + operator ostream_t () { return (ostream_t) (struct any_ostream_representation *) _pointer; } + explicit term_ostream_t (ostream_t x) : _pointer ((struct term_ostream_representation *) (void *) x) {} +}; +#else +typedef ostream_t term_ostream_t; +#endif + +/* Functions that invoke the methods. */ +extern void term_ostream_write_mem (term_ostream_t first_arg, const void *data, size_t len); +extern void term_ostream_flush (term_ostream_t first_arg); +extern void term_ostream_free (term_ostream_t first_arg); +extern term_color_t term_ostream_rgb_to_color (term_ostream_t first_arg, int red, int green, int blue); +extern term_color_t term_ostream_get_color (term_ostream_t first_arg); +extern void term_ostream_set_color (term_ostream_t first_arg, term_color_t color); +extern term_color_t term_ostream_get_bgcolor (term_ostream_t first_arg); +extern void term_ostream_set_bgcolor (term_ostream_t first_arg, term_color_t color); +extern term_weight_t term_ostream_get_weight (term_ostream_t first_arg); +extern void term_ostream_set_weight (term_ostream_t first_arg, term_weight_t weight); +extern term_posture_t term_ostream_get_posture (term_ostream_t first_arg); +extern void term_ostream_set_posture (term_ostream_t first_arg, term_posture_t posture); +extern term_underline_t term_ostream_get_underline (term_ostream_t first_arg); +extern void term_ostream_set_underline (term_ostream_t first_arg, term_underline_t underline); + +/* Type representing an implementation of term_ostream_t. */ +struct term_ostream_implementation +{ + const typeinfo_t * const *superclasses; + size_t superclasses_length; + size_t instance_size; +#define THIS_ARG term_ostream_t first_arg +#include "term_ostream.vt.h" +#undef THIS_ARG +}; + +/* Public portion of the object pointed to by a term_ostream_t. */ +struct term_ostream_representation_header +{ + const struct term_ostream_implementation *vtable; +}; + +#if HAVE_INLINE + +/* Define the functions that invoke the methods as inline accesses to + the term_ostream_implementation. + Use #define to avoid a warning because of extern vs. static. */ + +# define term_ostream_write_mem term_ostream_write_mem_inline +static inline void +term_ostream_write_mem (term_ostream_t first_arg, const void *data, size_t len) +{ + const struct term_ostream_implementation *vtable = + ((struct term_ostream_representation_header *) (struct term_ostream_representation *) first_arg)->vtable; + vtable->write_mem (first_arg,data,len); +} + +# define term_ostream_flush term_ostream_flush_inline +static inline void +term_ostream_flush (term_ostream_t first_arg) +{ + const struct term_ostream_implementation *vtable = + ((struct term_ostream_representation_header *) (struct term_ostream_representation *) first_arg)->vtable; + vtable->flush (first_arg); +} + +# define term_ostream_free term_ostream_free_inline +static inline void +term_ostream_free (term_ostream_t first_arg) +{ + const struct term_ostream_implementation *vtable = + ((struct term_ostream_representation_header *) (struct term_ostream_representation *) first_arg)->vtable; + vtable->free (first_arg); +} + +# define term_ostream_rgb_to_color term_ostream_rgb_to_color_inline +static inline term_color_t +term_ostream_rgb_to_color (term_ostream_t first_arg, int red, int green, int blue) +{ + const struct term_ostream_implementation *vtable = + ((struct term_ostream_representation_header *) (struct term_ostream_representation *) first_arg)->vtable; + return vtable->rgb_to_color (first_arg,red,green,blue); +} + +# define term_ostream_get_color term_ostream_get_color_inline +static inline term_color_t +term_ostream_get_color (term_ostream_t first_arg) +{ + const struct term_ostream_implementation *vtable = + ((struct term_ostream_representation_header *) (struct term_ostream_representation *) first_arg)->vtable; + return vtable->get_color (first_arg); +} + +# define term_ostream_set_color term_ostream_set_color_inline +static inline void +term_ostream_set_color (term_ostream_t first_arg, term_color_t color) +{ + const struct term_ostream_implementation *vtable = + ((struct term_ostream_representation_header *) (struct term_ostream_representation *) first_arg)->vtable; + vtable->set_color (first_arg,color); +} + +# define term_ostream_get_bgcolor term_ostream_get_bgcolor_inline +static inline term_color_t +term_ostream_get_bgcolor (term_ostream_t first_arg) +{ + const struct term_ostream_implementation *vtable = + ((struct term_ostream_representation_header *) (struct term_ostream_representation *) first_arg)->vtable; + return vtable->get_bgcolor (first_arg); +} + +# define term_ostream_set_bgcolor term_ostream_set_bgcolor_inline +static inline void +term_ostream_set_bgcolor (term_ostream_t first_arg, term_color_t color) +{ + const struct term_ostream_implementation *vtable = + ((struct term_ostream_representation_header *) (struct term_ostream_representation *) first_arg)->vtable; + vtable->set_bgcolor (first_arg,color); +} + +# define term_ostream_get_weight term_ostream_get_weight_inline +static inline term_weight_t +term_ostream_get_weight (term_ostream_t first_arg) +{ + const struct term_ostream_implementation *vtable = + ((struct term_ostream_representation_header *) (struct term_ostream_representation *) first_arg)->vtable; + return vtable->get_weight (first_arg); +} + +# define term_ostream_set_weight term_ostream_set_weight_inline +static inline void +term_ostream_set_weight (term_ostream_t first_arg, term_weight_t weight) +{ + const struct term_ostream_implementation *vtable = + ((struct term_ostream_representation_header *) (struct term_ostream_representation *) first_arg)->vtable; + vtable->set_weight (first_arg,weight); +} + +# define term_ostream_get_posture term_ostream_get_posture_inline +static inline term_posture_t +term_ostream_get_posture (term_ostream_t first_arg) +{ + const struct term_ostream_implementation *vtable = + ((struct term_ostream_representation_header *) (struct term_ostream_representation *) first_arg)->vtable; + return vtable->get_posture (first_arg); +} + +# define term_ostream_set_posture term_ostream_set_posture_inline +static inline void +term_ostream_set_posture (term_ostream_t first_arg, term_posture_t posture) +{ + const struct term_ostream_implementation *vtable = + ((struct term_ostream_representation_header *) (struct term_ostream_representation *) first_arg)->vtable; + vtable->set_posture (first_arg,posture); +} + +# define term_ostream_get_underline term_ostream_get_underline_inline +static inline term_underline_t +term_ostream_get_underline (term_ostream_t first_arg) +{ + const struct term_ostream_implementation *vtable = + ((struct term_ostream_representation_header *) (struct term_ostream_representation *) first_arg)->vtable; + return vtable->get_underline (first_arg); +} + +# define term_ostream_set_underline term_ostream_set_underline_inline +static inline void +term_ostream_set_underline (term_ostream_t first_arg, term_underline_t underline) +{ + const struct term_ostream_implementation *vtable = + ((struct term_ostream_representation_header *) (struct term_ostream_representation *) first_arg)->vtable; + vtable->set_underline (first_arg,underline); +} + +#endif + +extern const typeinfo_t term_ostream_typeinfo; +#define term_ostream_SUPERCLASSES &term_ostream_typeinfo, ostream_SUPERCLASSES +#define term_ostream_SUPERCLASSES_LENGTH (1 + ostream_SUPERCLASSES_LENGTH) + +extern const struct term_ostream_implementation term_ostream_vtable; + +#line 91 "term-ostream.oo.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Create an output stream referring to the file descriptor FD. + FILENAME is used only for error messages. + The resulting stream will be line-buffered. + Note that the resulting stream must be closed before FD can be closed. */ +extern term_ostream_t term_ostream_create (int fd, const char *filename); + + +#ifdef __cplusplus +} +#endif + +#endif /* _TERM_OSTREAM_H */ diff --git a/gettext-tools/gnulib-lib/term-ostream.oo.c b/gettext-tools/gnulib-lib/term-ostream.oo.c new file mode 100644 index 0000000..6556e15 --- /dev/null +++ b/gettext-tools/gnulib-lib/term-ostream.oo.c @@ -0,0 +1,1925 @@ +/* Output stream for attributed text, producing ANSI escape sequences. + Copyright (C) 2006-2008 Free Software Foundation, Inc. + Written by Bruno Haible , 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include "term-ostream.h" + +#include +#include +#include +#include +#include +#include + +#include "error.h" +#include "fatal-signal.h" +#include "full-write.h" +#include "terminfo.h" +#include "xalloc.h" +#include "xsize.h" +#include "gettext.h" + +#define _(str) gettext (str) + +#if HAVE_TPARAM +/* GNU termcap's tparam() function requires a buffer argument. Make it so + large that there is no risk that tparam() needs to call malloc(). */ +static char tparambuf[100]; +/* Define tparm in terms of tparam. In the scope of this file, it is called + with at most one argument after the string. */ +# define tparm(str, arg1) \ + tparam (str, tparambuf, sizeof (tparambuf), arg1) +#endif + +#define SIZEOF(a) (sizeof(a) / sizeof(a[0])) + + +/* =========================== Color primitives =========================== */ + +/* A color in RGB format. */ +typedef struct +{ + unsigned int red : 8; /* range 0..255 */ + unsigned int green : 8; /* range 0..255 */ + unsigned int blue : 8; /* range 0..255 */ +} rgb_t; + +/* A color in HSV (a.k.a. HSB) format. */ +typedef struct +{ + float hue; /* normalized to interval [0,6) */ + float saturation; /* normalized to interval [0,1] */ + float brightness; /* a.k.a. value, normalized to interval [0,1] */ +} hsv_t; + +/* Conversion of a color in RGB to HSV format. */ +static void +rgb_to_hsv (rgb_t c, hsv_t *result) +{ + unsigned int r = c.red; + unsigned int g = c.green; + unsigned int b = c.blue; + + if (r > g) + { + if (b > r) + { + /* b > r > g, so max = b, min = g */ + result->hue = 4.0f + (float) (r - g) / (float) (b - g); + result->saturation = 1.0f - (float) g / (float) b; + result->brightness = (float) b / 255.0f; + } + else if (b <= g) + { + /* r > g >= b, so max = r, min = b */ + result->hue = 0.0f + (float) (g - b) / (float) (r - b); + result->saturation = 1.0f - (float) b / (float) r; + result->brightness = (float) r / 255.0f; + } + else + { + /* r >= b > g, so max = r, min = g */ + result->hue = 6.0f - (float) (b - g) / (float) (r - g); + result->saturation = 1.0f - (float) g / (float) r; + result->brightness = (float) r / 255.0f; + } + } + else + { + if (b > g) + { + /* b > g >= r, so max = b, min = r */ + result->hue = 4.0f - (float) (g - r) / (float) (b - r); + result->saturation = 1.0f - (float) r / (float) b; + result->brightness = (float) b / 255.0f; + } + else if (b < r) + { + /* g >= r > b, so max = g, min = b */ + result->hue = 2.0f - (float) (r - b) / (float) (g - b); + result->saturation = 1.0f - (float) b / (float) g; + result->brightness = (float) g / 255.0f; + } + else if (g > r) + { + /* g >= b >= r, g > r, so max = g, min = r */ + result->hue = 2.0f + (float) (b - r) / (float) (g - r); + result->saturation = 1.0f - (float) r / (float) g; + result->brightness = (float) g / 255.0f; + } + else + { + /* r = g = b. A grey color. */ + result->hue = 0; /* arbitrary */ + result->saturation = 0; + result->brightness = (float) r / 255.0f; + } + } +} + +/* Square of distance of two colors. */ +static float +color_distance (const hsv_t *color1, const hsv_t *color2) +{ +#if 0 + /* Formula taken from "John Smith: Color Similarity", + http://www.ctr.columbia.edu/~jrsmith/html/pubs/acmmm96/node8.html. */ + float angle1 = color1->hue * 1.04719755f; /* normalize to [0,2Ï€] */ + float angle2 = color2->hue * 1.04719755f; /* normalize to [0,2Ï€] */ + float delta_x = color1->saturation * cosf (angle1) + - color2->saturation * cosf (angle2); + float delta_y = color1->saturation * sinf (angle1) + - color2->saturation * sinf (angle2); + float delta_v = color1->brightness + - color2->brightness; + + return delta_x * delta_x + delta_y * delta_y + delta_v * delta_v; +#else + /* Formula that considers hue differences with more weight than saturation + or brightness differences, like the human eye does. */ + float delta_hue = + (color1->hue >= color2->hue + ? (color1->hue - color2->hue >= 3.0f + ? 6.0f + color2->hue - color1->hue + : color1->hue - color2->hue) + : (color2->hue - color1->hue >= 3.0f + ? 6.0f + color1->hue - color2->hue + : color2->hue - color1->hue)); + float min_saturation = + (color1->saturation < color2->saturation + ? color1->saturation + : color2->saturation); + float delta_saturation = color1->saturation - color2->saturation; + float delta_brightness = color1->brightness - color2->brightness; + + return delta_hue * delta_hue * min_saturation + + delta_saturation * delta_saturation * 0.2f + + delta_brightness * delta_brightness * 0.8f; +#endif +} + +/* Return the index of the color in a color table that is nearest to a given + color. */ +static unsigned int +nearest_color (rgb_t given, const rgb_t *table, unsigned int table_size) +{ + hsv_t given_hsv; + unsigned int best_index; + float best_distance; + unsigned int i; + + assert (table_size > 0); + + rgb_to_hsv (given, &given_hsv); + + best_index = 0; + best_distance = 1000000.0f; + for (i = 0; i < table_size; i++) + { + hsv_t i_hsv; + + rgb_to_hsv (table[i], &i_hsv); + + /* Avoid converting a color to grey, or fading out a color too much. */ + if (i_hsv.saturation > given_hsv.saturation * 0.5f) + { + float distance = color_distance (&given_hsv, &i_hsv); + if (distance < best_distance) + { + best_index = i; + best_distance = distance; + } + } + } + +#if 0 /* Debugging code */ + hsv_t best_hsv; + rgb_to_hsv (table[best_index], &best_hsv); + fprintf (stderr, "nearest: (%d,%d,%d) = (%f,%f,%f)\n -> (%f,%f,%f) = (%d,%d,%d)\n", + given.red, given.green, given.blue, + (double)given_hsv.hue, (double)given_hsv.saturation, (double)given_hsv.brightness, + (double)best_hsv.hue, (double)best_hsv.saturation, (double)best_hsv.brightness, + table[best_index].red, table[best_index].green, table[best_index].blue); +#endif + + return best_index; +} + +/* The luminance of a color. This is the brightness of the color, as it + appears to the human eye. This must be used in color to grey conversion. */ +static float +color_luminance (int r, int g, int b) +{ + /* Use the luminance model used by NTSC and JPEG. + Taken from http://www.fho-emden.de/~hoffmann/gray10012001.pdf . + No need to care about rounding errors leading to luminance > 1; + this cannot happen. */ + return (0.299f * r + 0.587f * g + 0.114f * b) / 255.0f; +} + + +/* ============================= Color models ============================= */ + +/* The color model used by the terminal. */ +typedef enum +{ + cm_monochrome, /* No colors. */ + cm_common8, /* Usual terminal with at least 8 colors. */ + cm_xterm8, /* TERM=xterm, with 8 colors. */ + cm_xterm16, /* TERM=xterm-16color, with 16 colors. */ + cm_xterm88, /* TERM=xterm-88color, with 88 colors. */ + cm_xterm256 /* TERM=xterm-256color, with 256 colors. */ +} colormodel_t; + +/* ----------------------- cm_monochrome color model ----------------------- */ + +/* A non-default color index doesn't exist in this color model. */ +static inline term_color_t +rgb_to_color_monochrome () +{ + return COLOR_DEFAULT; +} + +/* ------------------------ cm_common8 color model ------------------------ */ + +/* A non-default color index is in the range 0..7. + RGB components + COLOR_BLACK 000 + COLOR_BLUE 001 + COLOR_GREEN 010 + COLOR_CYAN 011 + COLOR_RED 100 + COLOR_MAGENTA 101 + COLOR_YELLOW 110 + COLOR_WHITE 111 */ +static const rgb_t colors_of_common8[8] = +{ + /* R G B grey index */ + { 0, 0, 0 }, /* 0.000 0 */ + { 0, 0, 255 }, + { 0, 255, 0 }, + { 0, 255, 255 }, + { 255, 0, 0 }, + { 255, 0, 255 }, + { 255, 255, 0 }, + { 255, 255, 255 } /* 1.000 7 */ +}; + +static inline term_color_t +rgb_to_color_common8 (int r, int g, int b) +{ + rgb_t color; + hsv_t hsv; + + color.red = r; color.green = g; color.blue = b; + rgb_to_hsv (color, &hsv); + + if (hsv.saturation < 0.065f) + { + /* Greyscale approximation. */ + float luminance = color_luminance (r, g, b); + if (luminance < 0.500f) + return 0; + else + return 7; + } + else + /* Color approximation. */ + return nearest_color (color, colors_of_common8, 8); +} + +/* Convert a cm_common8 color in RGB encoding to BGR encoding. + See the ncurses terminfo(5) manual page, section "Color Handling", for an + explanation why this is needed. */ +static inline int +color_bgr (term_color_t color) +{ + return ((color & 4) >> 2) | (color & 2) | ((color & 1) << 2); +} + +/* ------------------------- cm_xterm8 color model ------------------------- */ + +/* A non-default color index is in the range 0..7. + BGR components + COLOR_BLACK 000 + COLOR_RED 001 + COLOR_GREEN 010 + COLOR_YELLOW 011 + COLOR_BLUE 100 + COLOR_MAGENTA 101 + COLOR_CYAN 110 + COLOR_WHITE 111 */ +static const rgb_t colors_of_xterm8[8] = +{ + /* The real xterm's colors are dimmed; assume full-brightness instead. */ + /* R G B grey index */ + { 0, 0, 0 }, /* 0.000 0 */ + { 255, 0, 0 }, + { 0, 255, 0 }, + { 255, 255, 0 }, + { 0, 0, 255 }, + { 255, 0, 255 }, + { 0, 255, 255 }, + { 255, 255, 255 } /* 1.000 7 */ +}; + +static inline term_color_t +rgb_to_color_xterm8 (int r, int g, int b) +{ + rgb_t color; + hsv_t hsv; + + color.red = r; color.green = g; color.blue = b; + rgb_to_hsv (color, &hsv); + + if (hsv.saturation < 0.065f) + { + /* Greyscale approximation. */ + float luminance = color_luminance (r, g, b); + if (luminance < 0.500f) + return 0; + else + return 7; + } + else + /* Color approximation. */ + return nearest_color (color, colors_of_xterm8, 8); +} + +/* ------------------------ cm_xterm16 color model ------------------------ */ + +/* A non-default color index is in the range 0..15. + The RGB values come from xterm's XTerm-col.ad. */ +static const rgb_t colors_of_xterm16[16] = +{ + /* R G B grey index */ + { 0, 0, 0 }, /* 0.000 0 */ + { 205, 0, 0 }, + { 0, 205, 0 }, + { 205, 205, 0 }, + { 0, 0, 205 }, + { 205, 0, 205 }, + { 0, 205, 205 }, + { 229, 229, 229 }, /* 0.898 7 */ + { 77, 77, 77 }, /* 0.302 8 */ + { 255, 0, 0 }, + { 0, 255, 0 }, + { 255, 255, 0 }, + { 0, 0, 255 }, + { 255, 0, 255 }, + { 0, 255, 255 }, + { 255, 255, 255 } /* 1.000 15 */ +}; + +static inline term_color_t +rgb_to_color_xterm16 (int r, int g, int b) +{ + rgb_t color; + hsv_t hsv; + + color.red = r; color.green = g; color.blue = b; + rgb_to_hsv (color, &hsv); + + if (hsv.saturation < 0.065f) + { + /* Greyscale approximation. */ + float luminance = color_luminance (r, g, b); + if (luminance < 0.151f) + return 0; + else if (luminance < 0.600f) + return 8; + else if (luminance < 0.949f) + return 7; + else + return 15; + } + else + /* Color approximation. */ + return nearest_color (color, colors_of_xterm16, 16); +} + +/* ------------------------ cm_xterm88 color model ------------------------ */ + +/* A non-default color index is in the range 0..87. + Colors 0..15 are the same as in the cm_xterm16 color model. + Colors 16..87 are defined in xterm's 88colres.h. */ + +static const rgb_t colors_of_xterm88[88] = +{ + /* R G B grey index */ + { 0, 0, 0 }, /* 0.000 0 */ + { 205, 0, 0 }, + { 0, 205, 0 }, + { 205, 205, 0 }, + { 0, 0, 205 }, + { 205, 0, 205 }, + { 0, 205, 205 }, + { 229, 229, 229 }, /* 0.898 7 */ + { 77, 77, 77 }, /* 0.302 8 */ + { 255, 0, 0 }, + { 0, 255, 0 }, + { 255, 255, 0 }, + { 0, 0, 255 }, + { 255, 0, 255 }, + { 0, 255, 255 }, + { 255, 255, 255 }, /* 1.000 15 */ + { 0, 0, 0 }, /* 0.000 16 */ + { 0, 0, 139 }, + { 0, 0, 205 }, + { 0, 0, 255 }, + { 0, 139, 0 }, + { 0, 139, 139 }, + { 0, 139, 205 }, + { 0, 139, 255 }, + { 0, 205, 0 }, + { 0, 205, 139 }, + { 0, 205, 205 }, + { 0, 205, 255 }, + { 0, 255, 0 }, + { 0, 255, 139 }, + { 0, 255, 205 }, + { 0, 255, 255 }, + { 139, 0, 0 }, + { 139, 0, 139 }, + { 139, 0, 205 }, + { 139, 0, 255 }, + { 139, 139, 0 }, + { 139, 139, 139 }, /* 0.545 37 */ + { 139, 139, 205 }, + { 139, 139, 255 }, + { 139, 205, 0 }, + { 139, 205, 139 }, + { 139, 205, 205 }, + { 139, 205, 255 }, + { 139, 255, 0 }, + { 139, 255, 139 }, + { 139, 255, 205 }, + { 139, 255, 255 }, + { 205, 0, 0 }, + { 205, 0, 139 }, + { 205, 0, 205 }, + { 205, 0, 255 }, + { 205, 139, 0 }, + { 205, 139, 139 }, + { 205, 139, 205 }, + { 205, 139, 255 }, + { 205, 205, 0 }, + { 205, 205, 139 }, + { 205, 205, 205 }, /* 0.804 58 */ + { 205, 205, 255 }, + { 205, 255, 0 }, + { 205, 255, 139 }, + { 205, 255, 205 }, + { 205, 255, 255 }, + { 255, 0, 0 }, + { 255, 0, 139 }, + { 255, 0, 205 }, + { 255, 0, 255 }, + { 255, 139, 0 }, + { 255, 139, 139 }, + { 255, 139, 205 }, + { 255, 139, 255 }, + { 255, 205, 0 }, + { 255, 205, 139 }, + { 255, 205, 205 }, + { 255, 205, 255 }, + { 255, 255, 0 }, + { 255, 255, 139 }, + { 255, 255, 205 }, + { 255, 255, 255 }, /* 1.000 79 */ + { 46, 46, 46 }, /* 0.180 80 */ + { 92, 92, 92 }, /* 0.361 81 */ + { 115, 115, 115 }, /* 0.451 82 */ + { 139, 139, 139 }, /* 0.545 83 */ + { 162, 162, 162 }, /* 0.635 84 */ + { 185, 185, 185 }, /* 0.725 85 */ + { 208, 208, 208 }, /* 0.816 86 */ + { 231, 231, 231 } /* 0.906 87 */ +}; + +static inline term_color_t +rgb_to_color_xterm88 (int r, int g, int b) +{ + rgb_t color; + hsv_t hsv; + + color.red = r; color.green = g; color.blue = b; + rgb_to_hsv (color, &hsv); + + if (hsv.saturation < 0.065f) + { + /* Greyscale approximation. */ + float luminance = color_luminance (r, g, b); + if (luminance < 0.090f) + return 0; + else if (luminance < 0.241f) + return 80; + else if (luminance < 0.331f) + return 8; + else if (luminance < 0.406f) + return 81; + else if (luminance < 0.498f) + return 82; + else if (luminance < 0.585f) + return 37; + else if (luminance < 0.680f) + return 84; + else if (luminance < 0.764f) + return 85; + else if (luminance < 0.810f) + return 58; + else if (luminance < 0.857f) + return 86; + else if (luminance < 0.902f) + return 7; + else if (luminance < 0.953f) + return 87; + else + return 15; + } + else + /* Color approximation. */ + return nearest_color (color, colors_of_xterm88, 88); +} + +/* ------------------------ cm_xterm256 color model ------------------------ */ + +/* A non-default color index is in the range 0..255. + Colors 0..15 are the same as in the cm_xterm16 color model. + Colors 16..255 are defined in xterm's 256colres.h. */ + +static const rgb_t colors_of_xterm256[256] = +{ + /* R G B grey index */ + { 0, 0, 0 }, /* 0.000 0 */ + { 205, 0, 0 }, + { 0, 205, 0 }, + { 205, 205, 0 }, + { 0, 0, 205 }, + { 205, 0, 205 }, + { 0, 205, 205 }, + { 229, 229, 229 }, /* 0.898 7 */ + { 77, 77, 77 }, /* 0.302 8 */ + { 255, 0, 0 }, + { 0, 255, 0 }, + { 255, 255, 0 }, + { 0, 0, 255 }, + { 255, 0, 255 }, + { 0, 255, 255 }, + { 255, 255, 255 }, /* 1.000 15 */ + { 0, 0, 0 }, /* 0.000 16 */ + { 0, 0, 42 }, + { 0, 0, 85 }, + { 0, 0, 127 }, + { 0, 0, 170 }, + { 0, 0, 212 }, + { 0, 42, 0 }, + { 0, 42, 42 }, + { 0, 42, 85 }, + { 0, 42, 127 }, + { 0, 42, 170 }, + { 0, 42, 212 }, + { 0, 85, 0 }, + { 0, 85, 42 }, + { 0, 85, 85 }, + { 0, 85, 127 }, + { 0, 85, 170 }, + { 0, 85, 212 }, + { 0, 127, 0 }, + { 0, 127, 42 }, + { 0, 127, 85 }, + { 0, 127, 127 }, + { 0, 127, 170 }, + { 0, 127, 212 }, + { 0, 170, 0 }, + { 0, 170, 42 }, + { 0, 170, 85 }, + { 0, 170, 127 }, + { 0, 170, 170 }, + { 0, 170, 212 }, + { 0, 212, 0 }, + { 0, 212, 42 }, + { 0, 212, 85 }, + { 0, 212, 127 }, + { 0, 212, 170 }, + { 0, 212, 212 }, + { 42, 0, 0 }, + { 42, 0, 42 }, + { 42, 0, 85 }, + { 42, 0, 127 }, + { 42, 0, 170 }, + { 42, 0, 212 }, + { 42, 42, 0 }, + { 42, 42, 42 }, /* 0.165 59 */ + { 42, 42, 85 }, + { 42, 42, 127 }, + { 42, 42, 170 }, + { 42, 42, 212 }, + { 42, 85, 0 }, + { 42, 85, 42 }, + { 42, 85, 85 }, + { 42, 85, 127 }, + { 42, 85, 170 }, + { 42, 85, 212 }, + { 42, 127, 0 }, + { 42, 127, 42 }, + { 42, 127, 85 }, + { 42, 127, 127 }, + { 42, 127, 170 }, + { 42, 127, 212 }, + { 42, 170, 0 }, + { 42, 170, 42 }, + { 42, 170, 85 }, + { 42, 170, 127 }, + { 42, 170, 170 }, + { 42, 170, 212 }, + { 42, 212, 0 }, + { 42, 212, 42 }, + { 42, 212, 85 }, + { 42, 212, 127 }, + { 42, 212, 170 }, + { 42, 212, 212 }, + { 85, 0, 0 }, + { 85, 0, 42 }, + { 85, 0, 85 }, + { 85, 0, 127 }, + { 85, 0, 170 }, + { 85, 0, 212 }, + { 85, 42, 0 }, + { 85, 42, 42 }, + { 85, 42, 85 }, + { 85, 42, 127 }, + { 85, 42, 170 }, + { 85, 42, 212 }, + { 85, 85, 0 }, + { 85, 85, 42 }, + { 85, 85, 85 }, /* 0.333 102 */ + { 85, 85, 127 }, + { 85, 85, 170 }, + { 85, 85, 212 }, + { 85, 127, 0 }, + { 85, 127, 42 }, + { 85, 127, 85 }, + { 85, 127, 127 }, + { 85, 127, 170 }, + { 85, 127, 212 }, + { 85, 170, 0 }, + { 85, 170, 42 }, + { 85, 170, 85 }, + { 85, 170, 127 }, + { 85, 170, 170 }, + { 85, 170, 212 }, + { 85, 212, 0 }, + { 85, 212, 42 }, + { 85, 212, 85 }, + { 85, 212, 127 }, + { 85, 212, 170 }, + { 85, 212, 212 }, + { 127, 0, 0 }, + { 127, 0, 42 }, + { 127, 0, 85 }, + { 127, 0, 127 }, + { 127, 0, 170 }, + { 127, 0, 212 }, + { 127, 42, 0 }, + { 127, 42, 42 }, + { 127, 42, 85 }, + { 127, 42, 127 }, + { 127, 42, 170 }, + { 127, 42, 212 }, + { 127, 85, 0 }, + { 127, 85, 42 }, + { 127, 85, 85 }, + { 127, 85, 127 }, + { 127, 85, 170 }, + { 127, 85, 212 }, + { 127, 127, 0 }, + { 127, 127, 42 }, + { 127, 127, 85 }, + { 127, 127, 127 }, /* 0.498 145 */ + { 127, 127, 170 }, + { 127, 127, 212 }, + { 127, 170, 0 }, + { 127, 170, 42 }, + { 127, 170, 85 }, + { 127, 170, 127 }, + { 127, 170, 170 }, + { 127, 170, 212 }, + { 127, 212, 0 }, + { 127, 212, 42 }, + { 127, 212, 85 }, + { 127, 212, 127 }, + { 127, 212, 170 }, + { 127, 212, 212 }, + { 170, 0, 0 }, + { 170, 0, 42 }, + { 170, 0, 85 }, + { 170, 0, 127 }, + { 170, 0, 170 }, + { 170, 0, 212 }, + { 170, 42, 0 }, + { 170, 42, 42 }, + { 170, 42, 85 }, + { 170, 42, 127 }, + { 170, 42, 170 }, + { 170, 42, 212 }, + { 170, 85, 0 }, + { 170, 85, 42 }, + { 170, 85, 85 }, + { 170, 85, 127 }, + { 170, 85, 170 }, + { 170, 85, 212 }, + { 170, 127, 0 }, + { 170, 127, 42 }, + { 170, 127, 85 }, + { 170, 127, 127 }, + { 170, 127, 170 }, + { 170, 127, 212 }, + { 170, 170, 0 }, + { 170, 170, 42 }, + { 170, 170, 85 }, + { 170, 170, 127 }, + { 170, 170, 170 }, /* 0.667 188 */ + { 170, 170, 212 }, + { 170, 212, 0 }, + { 170, 212, 42 }, + { 170, 212, 85 }, + { 170, 212, 127 }, + { 170, 212, 170 }, + { 170, 212, 212 }, + { 212, 0, 0 }, + { 212, 0, 42 }, + { 212, 0, 85 }, + { 212, 0, 127 }, + { 212, 0, 170 }, + { 212, 0, 212 }, + { 212, 42, 0 }, + { 212, 42, 42 }, + { 212, 42, 85 }, + { 212, 42, 127 }, + { 212, 42, 170 }, + { 212, 42, 212 }, + { 212, 85, 0 }, + { 212, 85, 42 }, + { 212, 85, 85 }, + { 212, 85, 127 }, + { 212, 85, 170 }, + { 212, 85, 212 }, + { 212, 127, 0 }, + { 212, 127, 42 }, + { 212, 127, 85 }, + { 212, 127, 127 }, + { 212, 127, 170 }, + { 212, 127, 212 }, + { 212, 170, 0 }, + { 212, 170, 42 }, + { 212, 170, 85 }, + { 212, 170, 127 }, + { 212, 170, 170 }, + { 212, 170, 212 }, + { 212, 212, 0 }, + { 212, 212, 42 }, + { 212, 212, 85 }, + { 212, 212, 127 }, + { 212, 212, 170 }, + { 212, 212, 212 }, /* 0.831 231 */ + { 8, 8, 8 }, /* 0.031 232 */ + { 18, 18, 18 }, /* 0.071 233 */ + { 28, 28, 28 }, /* 0.110 234 */ + { 38, 38, 38 }, /* 0.149 235 */ + { 48, 48, 48 }, /* 0.188 236 */ + { 58, 58, 58 }, /* 0.227 237 */ + { 68, 68, 68 }, /* 0.267 238 */ + { 78, 78, 78 }, /* 0.306 239 */ + { 88, 88, 88 }, /* 0.345 240 */ + { 98, 98, 98 }, /* 0.384 241 */ + { 108, 108, 108 }, /* 0.424 242 */ + { 118, 118, 118 }, /* 0.463 243 */ + { 128, 128, 128 }, /* 0.502 244 */ + { 138, 138, 138 }, /* 0.541 245 */ + { 148, 148, 148 }, /* 0.580 246 */ + { 158, 158, 158 }, /* 0.620 247 */ + { 168, 168, 168 }, /* 0.659 248 */ + { 178, 178, 178 }, /* 0.698 249 */ + { 188, 188, 188 }, /* 0.737 250 */ + { 198, 198, 198 }, /* 0.776 251 */ + { 208, 208, 208 }, /* 0.816 252 */ + { 218, 218, 218 }, /* 0.855 253 */ + { 228, 228, 228 }, /* 0.894 254 */ + { 238, 238, 238 } /* 0.933 255 */ +}; + +static inline term_color_t +rgb_to_color_xterm256 (int r, int g, int b) +{ + rgb_t color; + hsv_t hsv; + + color.red = r; color.green = g; color.blue = b; + rgb_to_hsv (color, &hsv); + + if (hsv.saturation < 0.065f) + { + /* Greyscale approximation. */ + float luminance = color_luminance (r, g, b); + if (luminance < 0.015f) + return 0; + else if (luminance < 0.051f) + return 232; + else if (luminance < 0.090f) + return 233; + else if (luminance < 0.129f) + return 234; + else if (luminance < 0.157f) + return 235; + else if (luminance < 0.177f) + return 59; + else if (luminance < 0.207f) + return 236; + else if (luminance < 0.247f) + return 237; + else if (luminance < 0.284f) + return 238; + else if (luminance < 0.304f) + return 8; + else if (luminance < 0.319f) + return 239; + else if (luminance < 0.339f) + return 102; + else if (luminance < 0.364f) + return 240; + else if (luminance < 0.404f) + return 241; + else if (luminance < 0.443f) + return 242; + else if (luminance < 0.480f) + return 243; + else if (luminance < 0.500f) + return 145; + else if (luminance < 0.521f) + return 244; + else if (luminance < 0.560f) + return 245; + else if (luminance < 0.600f) + return 246; + else if (luminance < 0.639f) + return 247; + else if (luminance < 0.663f) + return 248; + else if (luminance < 0.682f) + return 188; + else if (luminance < 0.717f) + return 249; + else if (luminance < 0.756f) + return 250; + else if (luminance < 0.796f) + return 251; + else if (luminance < 0.823f) + return 252; + else if (luminance < 0.843f) + return 231; + else if (luminance < 0.874f) + return 253; + else if (luminance < 0.896f) + return 254; + else if (luminance < 0.915f) + return 7; + else if (luminance < 0.966f) + return 255; + else + return 15; + } + else + /* Color approximation. */ + return nearest_color (color, colors_of_xterm256, 256); +} + + +/* ============================= attributes_t ============================= */ + +/* ANSI C and ISO C99 6.7.2.1.(4) forbid use of bit fields for types other + than 'int' or 'unsigned int'. + On the other hand, C++ forbids conversion between enum types and integer + types without an explicit cast. */ +#ifdef __cplusplus +# define BITFIELD_TYPE(orig_type,integer_type) orig_type +#else +# define BITFIELD_TYPE(orig_type,integer_type) integer_type +#endif + +/* Attributes that can be set on a character. */ +typedef struct +{ + BITFIELD_TYPE(term_color_t, signed int) color : 9; + BITFIELD_TYPE(term_color_t, signed int) bgcolor : 9; + BITFIELD_TYPE(term_weight_t, unsigned int) weight : 1; + BITFIELD_TYPE(term_posture_t, unsigned int) posture : 1; + BITFIELD_TYPE(term_underline_t, unsigned int) underline : 1; +} attributes_t; + + +/* ============================ term_ostream_t ============================ */ + +struct term_ostream : struct ostream +{ +fields: + /* The file descriptor used for output. Note that ncurses termcap emulation + uses the baud rate information from file descriptor 1 (stdout) if it is + a tty, or from file descriptor 2 (stderr) otherwise. */ + int fd; + char *filename; + /* Values from the terminal type's terminfo/termcap description. + See terminfo(5) for details. */ + /* terminfo termcap */ + int max_colors; /* colors Co */ + int no_color_video; /* ncv NC */ + char *set_a_foreground; /* setaf AF */ + char *set_foreground; /* setf Sf */ + char *set_a_background; /* setab AB */ + char *set_background; /* setb Sb */ + char *orig_pair; /* op op */ + char *enter_bold_mode; /* bold md */ + char *enter_italics_mode; /* sitm ZH */ + char *exit_italics_mode; /* ritm ZR */ + char *enter_underline_mode; /* smul us */ + char *exit_underline_mode; /* rmul ue */ + char *exit_attribute_mode; /* sgr0 me */ + /* Inferred values. */ + bool supports_foreground; + bool supports_background; + colormodel_t colormodel; + bool supports_weight; + bool supports_posture; + bool supports_underline; + /* Variable state. */ + char *buffer; /* Buffer for the current line. */ + attributes_t *attrbuffer; /* Buffer for the simplified attributes; same + length as buffer. */ + size_t buflen; /* Number of bytes stored so far. */ + size_t allocated; /* Allocated size of the buffer. */ + attributes_t curr_attr; /* Current attributes. */ + attributes_t simp_attr; /* Simplified current attributes. */ +}; + +/* Simplify attributes, according to the terminal's capabilities. */ +static attributes_t +simplify_attributes (term_ostream_t stream, attributes_t attr) +{ + if ((attr.color != COLOR_DEFAULT || attr.bgcolor != COLOR_DEFAULT) + && stream->no_color_video > 0) + { + /* When colors and attributes can not be represented simultaneously, + we give preference to the color. */ + if (stream->no_color_video & 2) + /* Colors conflict with underlining. */ + attr.underline = UNDERLINE_OFF; + if (stream->no_color_video & 32) + /* Colors conflict with bold weight. */ + attr.weight = WEIGHT_NORMAL; + } + if (!stream->supports_foreground) + attr.color = COLOR_DEFAULT; + if (!stream->supports_background) + attr.bgcolor = COLOR_DEFAULT; + if (!stream->supports_weight) + attr.weight = WEIGHT_DEFAULT; + if (!stream->supports_posture) + attr.posture = POSTURE_DEFAULT; + if (!stream->supports_underline) + attr.underline = UNDERLINE_DEFAULT; + return attr; +} + +/* While a line is being output, we need to be careful to restore the + terminal's settings in case of a fatal signal or an exit() call. */ + +/* File descriptor to which out_char shall output escape sequences. */ +static int out_fd = -1; + +/* Filename of out_fd. */ +static const char *out_filename; + +/* Output a single char to out_fd. Ignore errors. */ +static int +out_char_unchecked (int c) +{ + char bytes[1]; + + bytes[0] = (char)c; + full_write (out_fd, bytes, 1); + return 0; +} + +/* State that informs the exit handler what to do. */ +static const char *restore_colors; +static const char *restore_weight; +static const char *restore_posture; +static const char *restore_underline; + +/* The exit handler. */ +static void +restore (void) +{ + /* Only do something while some output was interrupted. */ + if (out_fd >= 0) + { + if (restore_colors != NULL) + tputs (restore_colors, 1, out_char_unchecked); + if (restore_weight != NULL) + tputs (restore_weight, 1, out_char_unchecked); + if (restore_posture != NULL) + tputs (restore_posture, 1, out_char_unchecked); + if (restore_underline != NULL) + tputs (restore_underline, 1, out_char_unchecked); + } +} + +/* The list of signals whose default behaviour is to stop the program. */ +static int stopping_signals[] = + { +#ifdef SIGTSTP + SIGTSTP, +#endif +#ifdef SIGTTIN + SIGTTIN, +#endif +#ifdef SIGTTOU + SIGTTOU, +#endif + 0 + }; + +#define num_stopping_signals (SIZEOF (stopping_signals) - 1) + +static sigset_t stopping_signal_set; + +static void +init_stopping_signal_set () +{ + static bool stopping_signal_set_initialized = false; + if (!stopping_signal_set_initialized) + { + size_t i; + + sigemptyset (&stopping_signal_set); + for (i = 0; i < num_stopping_signals; i++) + sigaddset (&stopping_signal_set, stopping_signals[i]); + + stopping_signal_set_initialized = true; + } +} + +/* Temporarily delay the stopping signals. */ +static inline void +block_stopping_signals () +{ + init_stopping_signal_set (); + sigprocmask (SIG_BLOCK, &stopping_signal_set, NULL); +} + +/* Stop delaying the stopping signals. */ +static inline void +unblock_stopping_signals () +{ + init_stopping_signal_set (); + sigprocmask (SIG_UNBLOCK, &stopping_signal_set, NULL); +} + +/* Compare two sets of attributes for equality. */ +static inline bool +equal_attributes (attributes_t attr1, attributes_t attr2) +{ + return (attr1.color == attr2.color + && attr1.bgcolor == attr2.bgcolor + && attr1.weight == attr2.weight + && attr1.posture == attr2.posture + && attr1.underline == attr2.underline); +} + +/* Signal error after full_write failed. */ +static void +out_error () +{ + error (EXIT_FAILURE, errno, _("error writing to %s"), out_filename); +} + +/* Output a single char to out_fd. */ +static int +out_char (int c) +{ + char bytes[1]; + + bytes[0] = (char)c; + /* We have to write directly to the file descriptor, not to a buffer with + the same destination, because of the padding and sleeping that tputs() + does. */ + if (full_write (out_fd, bytes, 1) < 1) + out_error (); + return 0; +} + +/* Output escape sequences to switch from OLD_ATTR to NEW_ATTR. */ +static void +out_attr_change (term_ostream_t stream, + attributes_t old_attr, attributes_t new_attr) +{ + bool cleared_attributes; + + /* We don't know the default colors of the terminal. The only way to switch + back to a default color is to use stream->orig_pair. */ + if ((new_attr.color == COLOR_DEFAULT && old_attr.color != COLOR_DEFAULT) + || (new_attr.bgcolor == COLOR_DEFAULT && old_attr.bgcolor != COLOR_DEFAULT)) + { + assert (stream->supports_foreground || stream->supports_background); + tputs (stream->orig_pair, 1, out_char); + old_attr.color = COLOR_DEFAULT; + old_attr.bgcolor = COLOR_DEFAULT; + } + + /* To turn off WEIGHT_BOLD, the only way is to output the exit_attribute_mode + sequence. (With xterm, you can also do it with "Esc [ 0 m", but this + escape sequence is not contained in the terminfo description.) It may + also clear the colors; this is the case e.g. when TERM="xterm" or + TERM="ansi". + To turn off UNDERLINE_ON, we can use the exit_underline_mode or the + exit_attribute_mode sequence. In the latter case, it will not only + turn off UNDERLINE_ON, but also the other attributes, and possibly also + the colors. + To turn off POSTURE_ITALIC, we can use the exit_italics_mode or the + exit_attribute_mode sequence. Again, in the latter case, it will not + only turn off POSTURE_ITALIC, but also the other attributes, and possibly + also the colors. + There is no point in setting an attribute just before emitting an + escape sequence that may again turn off the attribute. Therefore we + proceed in two steps: First, clear the attributes that need to be + cleared; then - taking into account that this may have cleared all + attributes and all colors - set the colors and the attributes. + The variable 'cleared_attributes' tells whether an escape sequence + has been output that may have cleared all attributes and all color + settings. */ + cleared_attributes = false; + if (old_attr.posture != POSTURE_NORMAL + && new_attr.posture == POSTURE_NORMAL + && stream->exit_italics_mode != NULL) + { + tputs (stream->exit_italics_mode, 1, out_char); + old_attr.posture = POSTURE_NORMAL; + cleared_attributes = true; + } + if (old_attr.underline != UNDERLINE_OFF + && new_attr.underline == UNDERLINE_OFF + && stream->exit_underline_mode != NULL) + { + tputs (stream->exit_underline_mode, 1, out_char); + old_attr.underline = UNDERLINE_OFF; + cleared_attributes = true; + } + if ((old_attr.weight != WEIGHT_NORMAL + && new_attr.weight == WEIGHT_NORMAL) + || (old_attr.posture != POSTURE_NORMAL + && new_attr.posture == POSTURE_NORMAL + /* implies stream->exit_italics_mode == NULL */) + || (old_attr.underline != UNDERLINE_OFF + && new_attr.underline == UNDERLINE_OFF + /* implies stream->exit_underline_mode == NULL */)) + { + tputs (stream->exit_attribute_mode, 1, out_char); + /* We don't know exactly what effects exit_attribute_mode has, but + this is the minimum effect: */ + old_attr.weight = WEIGHT_NORMAL; + if (stream->exit_italics_mode == NULL) + old_attr.posture = POSTURE_NORMAL; + if (stream->exit_underline_mode == NULL) + old_attr.underline = UNDERLINE_OFF; + cleared_attributes = true; + } + + /* Turn on the colors. */ + if (new_attr.color != old_attr.color + || (cleared_attributes && new_attr.color != COLOR_DEFAULT)) + { + assert (stream->supports_foreground); + assert (new_attr.color != COLOR_DEFAULT); + switch (stream->colormodel) + { + case cm_common8: + assert (new_attr.color >= 0 && new_attr.color < 8); + if (stream->set_a_foreground != NULL) + tputs (tparm (stream->set_a_foreground, + color_bgr (new_attr.color)), + 1, out_char); + else + tputs (tparm (stream->set_foreground, new_attr.color), + 1, out_char); + break; + /* When we are dealing with an xterm, there is no need to go through + tputs() because we know there is no padding and sleeping. */ + case cm_xterm8: + assert (new_attr.color >= 0 && new_attr.color < 8); + { + char bytes[5]; + bytes[0] = 0x1B; bytes[1] = '['; + bytes[2] = '3'; bytes[3] = '0' + new_attr.color; + bytes[4] = 'm'; + if (full_write (out_fd, bytes, 5) < 5) + out_error (); + } + break; + case cm_xterm16: + assert (new_attr.color >= 0 && new_attr.color < 16); + { + char bytes[5]; + bytes[0] = 0x1B; bytes[1] = '['; + if (new_attr.color < 8) + { + bytes[2] = '3'; bytes[3] = '0' + new_attr.color; + } + else + { + bytes[2] = '9'; bytes[3] = '0' + (new_attr.color - 8); + } + bytes[4] = 'm'; + if (full_write (out_fd, bytes, 5) < 5) + out_error (); + } + break; + case cm_xterm88: + assert (new_attr.color >= 0 && new_attr.color < 88); + { + char bytes[10]; + char *p; + bytes[0] = 0x1B; bytes[1] = '['; + bytes[2] = '3'; bytes[3] = '8'; bytes[4] = ';'; + bytes[5] = '5'; bytes[6] = ';'; + p = bytes + 7; + if (new_attr.color >= 10) + *p++ = '0' + (new_attr.color / 10); + *p++ = '0' + (new_attr.color % 10); + *p++ = 'm'; + if (full_write (out_fd, bytes, p - bytes) < p - bytes) + out_error (); + } + break; + case cm_xterm256: + assert (new_attr.color >= 0 && new_attr.color < 256); + { + char bytes[11]; + char *p; + bytes[0] = 0x1B; bytes[1] = '['; + bytes[2] = '3'; bytes[3] = '8'; bytes[4] = ';'; + bytes[5] = '5'; bytes[6] = ';'; + p = bytes + 7; + if (new_attr.color >= 100) + *p++ = '0' + (new_attr.color / 100); + if (new_attr.color >= 10) + *p++ = '0' + ((new_attr.color % 100) / 10); + *p++ = '0' + (new_attr.color % 10); + *p++ = 'm'; + if (full_write (out_fd, bytes, p - bytes) < p - bytes) + out_error (); + } + break; + default: + abort (); + } + } + if (new_attr.bgcolor != old_attr.bgcolor + || (cleared_attributes && new_attr.bgcolor != COLOR_DEFAULT)) + { + assert (stream->supports_background); + assert (new_attr.bgcolor != COLOR_DEFAULT); + switch (stream->colormodel) + { + case cm_common8: + assert (new_attr.bgcolor >= 0 && new_attr.bgcolor < 8); + if (stream->set_a_background != NULL) + tputs (tparm (stream->set_a_background, + color_bgr (new_attr.bgcolor)), + 1, out_char); + else + tputs (tparm (stream->set_background, new_attr.bgcolor), + 1, out_char); + break; + /* When we are dealing with an xterm, there is no need to go through + tputs() because we know there is no padding and sleeping. */ + case cm_xterm8: + assert (new_attr.bgcolor >= 0 && new_attr.bgcolor < 8); + { + char bytes[5]; + bytes[0] = 0x1B; bytes[1] = '['; + bytes[2] = '4'; bytes[3] = '0' + new_attr.bgcolor; + bytes[4] = 'm'; + if (full_write (out_fd, bytes, 5) < 5) + out_error (); + } + break; + case cm_xterm16: + assert (new_attr.bgcolor >= 0 && new_attr.bgcolor < 16); + { + char bytes[6]; + bytes[0] = 0x1B; bytes[1] = '['; + if (new_attr.bgcolor < 8) + { + bytes[2] = '4'; bytes[3] = '0' + new_attr.bgcolor; + bytes[4] = 'm'; + if (full_write (out_fd, bytes, 5) < 5) + out_error (); + } + else + { + bytes[2] = '1'; bytes[3] = '0'; + bytes[4] = '0' + (new_attr.bgcolor - 8); bytes[5] = 'm'; + if (full_write (out_fd, bytes, 6) < 6) + out_error (); + } + } + break; + case cm_xterm88: + assert (new_attr.bgcolor >= 0 && new_attr.bgcolor < 88); + { + char bytes[10]; + char *p; + bytes[0] = 0x1B; bytes[1] = '['; + bytes[2] = '4'; bytes[3] = '8'; bytes[4] = ';'; + bytes[5] = '5'; bytes[6] = ';'; + p = bytes + 7; + if (new_attr.bgcolor >= 10) + *p++ = '0' + (new_attr.bgcolor / 10); + *p++ = '0' + (new_attr.bgcolor % 10); + *p++ = 'm'; + if (full_write (out_fd, bytes, p - bytes) < p - bytes) + out_error (); + } + break; + case cm_xterm256: + assert (new_attr.bgcolor >= 0 && new_attr.bgcolor < 256); + { + char bytes[11]; + char *p; + bytes[0] = 0x1B; bytes[1] = '['; + bytes[2] = '4'; bytes[3] = '8'; bytes[4] = ';'; + bytes[5] = '5'; bytes[6] = ';'; + p = bytes + 7; + if (new_attr.bgcolor >= 100) + *p++ = '0' + (new_attr.bgcolor / 100); + if (new_attr.bgcolor >= 10) + *p++ = '0' + ((new_attr.bgcolor % 100) / 10); + *p++ = '0' + (new_attr.bgcolor % 10); + *p++ = 'm'; + if (full_write (out_fd, bytes, p - bytes) < p - bytes) + out_error (); + } + break; + default: + abort (); + } + } + + if (new_attr.weight != old_attr.weight + || (cleared_attributes && new_attr.weight != WEIGHT_DEFAULT)) + { + assert (stream->supports_weight); + assert (new_attr.weight != WEIGHT_DEFAULT); + /* This implies: */ + assert (new_attr.weight == WEIGHT_BOLD); + tputs (stream->enter_bold_mode, 1, out_char); + } + if (new_attr.posture != old_attr.posture + || (cleared_attributes && new_attr.posture != POSTURE_DEFAULT)) + { + assert (stream->supports_posture); + assert (new_attr.posture != POSTURE_DEFAULT); + /* This implies: */ + assert (new_attr.posture == POSTURE_ITALIC); + tputs (stream->enter_italics_mode, 1, out_char); + } + if (new_attr.underline != old_attr.underline + || (cleared_attributes && new_attr.underline != UNDERLINE_DEFAULT)) + { + assert (stream->supports_underline); + assert (new_attr.underline != UNDERLINE_DEFAULT); + /* This implies: */ + assert (new_attr.underline == UNDERLINE_ON); + tputs (stream->enter_underline_mode, 1, out_char); + } +} + +/* Output the buffered line atomically. + The terminal is assumed to have the default state (regarding colors and + attributes) before this call. It is left in default state after this + call (regardless of stream->curr_attr). */ +static void +output_buffer (term_ostream_t stream) +{ + attributes_t default_attr; + attributes_t attr; + const char *cp; + const attributes_t *ap; + size_t len; + size_t n; + + default_attr.color = COLOR_DEFAULT; + default_attr.bgcolor = COLOR_DEFAULT; + default_attr.weight = WEIGHT_DEFAULT; + default_attr.posture = POSTURE_DEFAULT; + default_attr.underline = UNDERLINE_DEFAULT; + + attr = default_attr; + + cp = stream->buffer; + ap = stream->attrbuffer; + len = stream->buflen; + + /* See how much we can output without blocking signals. */ + for (n = 0; n < len && equal_attributes (ap[n], attr); n++) + ; + if (n > 0) + { + if (full_write (stream->fd, cp, n) < n) + error (EXIT_FAILURE, errno, _("error writing to %s"), stream->filename); + cp += n; + ap += n; + len -= n; + } + if (len > 0) + { + /* Block fatal signals, so that a SIGINT or similar doesn't interrupt + us without the possibility of restoring the terminal's state. */ + block_fatal_signals (); + /* Likewise for SIGTSTP etc. */ + block_stopping_signals (); + + /* Enable the exit handler for restoring the terminal's state. */ + restore_colors = + (stream->supports_foreground || stream->supports_background + ? stream->orig_pair + : NULL); + restore_weight = + (stream->supports_weight ? stream->exit_attribute_mode : NULL); + restore_posture = + (stream->supports_posture + ? (stream->exit_italics_mode != NULL + ? stream->exit_italics_mode + : stream->exit_attribute_mode) + : NULL); + restore_underline = + (stream->supports_underline + ? (stream->exit_underline_mode != NULL + ? stream->exit_underline_mode + : stream->exit_attribute_mode) + : NULL); + out_fd = stream->fd; + out_filename = stream->filename; + + while (len > 0) + { + /* Activate the attributes in *ap. */ + out_attr_change (stream, attr, *ap); + attr = *ap; + /* See how many characters we can output without further attribute + changes. */ + for (n = 1; n < len && equal_attributes (ap[n], attr); n++) + ; + if (full_write (stream->fd, cp, n) < n) + error (EXIT_FAILURE, errno, _("error writing to %s"), + stream->filename); + cp += n; + ap += n; + len -= n; + } + + /* Switch back to the default attributes. */ + out_attr_change (stream, attr, default_attr); + + /* Disable the exit handler. */ + out_fd = -1; + out_filename = NULL; + + /* Unblock fatal and stopping signals. */ + unblock_stopping_signals (); + unblock_fatal_signals (); + } + stream->buflen = 0; +} + +/* Implementation of ostream_t methods. */ + +static term_color_t +term_ostream::rgb_to_color (term_ostream_t stream, int red, int green, int blue) +{ + switch (stream->colormodel) + { + case cm_monochrome: + return rgb_to_color_monochrome (); + case cm_common8: + return rgb_to_color_common8 (red, green, blue); + case cm_xterm8: + return rgb_to_color_xterm8 (red, green, blue); + case cm_xterm16: + return rgb_to_color_xterm16 (red, green, blue); + case cm_xterm88: + return rgb_to_color_xterm88 (red, green, blue); + case cm_xterm256: + return rgb_to_color_xterm256 (red, green, blue); + default: + abort (); + } +} + +static void +term_ostream::write_mem (term_ostream_t stream, const void *data, size_t len) +{ + const char *cp = (const char *) data; + while (len > 0) + { + /* Look for the next newline. */ + const char *newline = (const char *) memchr (cp, '\n', len); + size_t n = (newline != NULL ? newline - cp : len); + + /* Copy n bytes into the buffer. */ + if (n > stream->allocated - stream->buflen) + { + size_t new_allocated = + xmax (xsum (stream->buflen, n), + xsum (stream->allocated, stream->allocated)); + if (size_overflow_p (new_allocated)) + error (EXIT_FAILURE, 0, + _("%s: too much output, buffer size overflow"), + "term_ostream"); + stream->buffer = (char *) xrealloc (stream->buffer, new_allocated); + stream->attrbuffer = + (attributes_t *) + xrealloc (stream->attrbuffer, + new_allocated * sizeof (attributes_t)); + stream->allocated = new_allocated; + } + memcpy (stream->buffer + stream->buflen, cp, n); + { + attributes_t attr = stream->simp_attr; + attributes_t *ap = stream->attrbuffer + stream->buflen; + attributes_t *ap_end = ap + n; + for (; ap < ap_end; ap++) + *ap = attr; + } + stream->buflen += n; + + if (newline != NULL) + { + output_buffer (stream); + if (full_write (stream->fd, "\n", 1) < 1) + error (EXIT_FAILURE, errno, _("error writing to %s"), + stream->filename); + cp += n + 1; /* cp = newline + 1; */ + len -= n + 1; + } + else + break; + } +} + +static void +term_ostream::flush (term_ostream_t stream) +{ + output_buffer (stream); +} + +static void +term_ostream::free (term_ostream_t stream) +{ + term_ostream_flush (stream); + free (stream->filename); + if (stream->set_a_foreground != NULL) + free (stream->set_a_foreground); + if (stream->set_foreground != NULL) + free (stream->set_foreground); + if (stream->set_a_background != NULL) + free (stream->set_a_background); + if (stream->set_background != NULL) + free (stream->set_background); + if (stream->orig_pair != NULL) + free (stream->orig_pair); + if (stream->enter_bold_mode != NULL) + free (stream->enter_bold_mode); + if (stream->enter_italics_mode != NULL) + free (stream->enter_italics_mode); + if (stream->exit_italics_mode != NULL) + free (stream->exit_italics_mode); + if (stream->enter_underline_mode != NULL) + free (stream->enter_underline_mode); + if (stream->exit_underline_mode != NULL) + free (stream->exit_underline_mode); + if (stream->exit_attribute_mode != NULL) + free (stream->exit_attribute_mode); + free (stream->buffer); + free (stream); +} + +/* Implementation of term_ostream_t methods. */ + +static term_color_t +term_ostream::get_color (term_ostream_t stream) +{ + return stream->curr_attr.color; +} + +static void +term_ostream::set_color (term_ostream_t stream, term_color_t color) +{ + stream->curr_attr.color = color; + stream->simp_attr = simplify_attributes (stream, stream->curr_attr); +} + +static term_color_t +term_ostream::get_bgcolor (term_ostream_t stream) +{ + return stream->curr_attr.bgcolor; +} + +static void +term_ostream::set_bgcolor (term_ostream_t stream, term_color_t color) +{ + stream->curr_attr.bgcolor = color; + stream->simp_attr = simplify_attributes (stream, stream->curr_attr); +} + +static term_weight_t +term_ostream::get_weight (term_ostream_t stream) +{ + return stream->curr_attr.weight; +} + +static void +term_ostream::set_weight (term_ostream_t stream, term_weight_t weight) +{ + stream->curr_attr.weight = weight; + stream->simp_attr = simplify_attributes (stream, stream->curr_attr); +} + +static term_posture_t +term_ostream::get_posture (term_ostream_t stream) +{ + return stream->curr_attr.posture; +} + +static void +term_ostream::set_posture (term_ostream_t stream, term_posture_t posture) +{ + stream->curr_attr.posture = posture; + stream->simp_attr = simplify_attributes (stream, stream->curr_attr); +} + +static term_underline_t +term_ostream::get_underline (term_ostream_t stream) +{ + return stream->curr_attr.underline; +} + +static void +term_ostream::set_underline (term_ostream_t stream, term_underline_t underline) +{ + stream->curr_attr.underline = underline; + stream->simp_attr = simplify_attributes (stream, stream->curr_attr); +} + +/* Constructor. */ + +static inline char * +xstrdup0 (const char *str) +{ + if (str == NULL) + return NULL; +#if HAVE_TERMINFO + if (str == (const char *)(-1)) + return NULL; +#endif + return xstrdup (str); +} + +term_ostream_t +term_ostream_create (int fd, const char *filename) +{ + term_ostream_t stream = XMALLOC (struct term_ostream_representation); + const char *term; + + stream->base.vtable = &term_ostream_vtable; + stream->fd = fd; + stream->filename = xstrdup (filename); + + /* Defaults. */ + stream->max_colors = -1; + stream->no_color_video = -1; + stream->set_a_foreground = NULL; + stream->set_foreground = NULL; + stream->set_a_background = NULL; + stream->set_background = NULL; + stream->orig_pair = NULL; + stream->enter_bold_mode = NULL; + stream->enter_italics_mode = NULL; + stream->exit_italics_mode = NULL; + stream->enter_underline_mode = NULL; + stream->exit_underline_mode = NULL; + stream->exit_attribute_mode = NULL; + + /* Retrieve the terminal type. */ + term = getenv ("TERM"); + if (term != NULL && term[0] != '\0') + { + /* When the terminfo function are available, we prefer them over the + termcap functions because + 1. they don't risk a buffer overflow, + 2. on OSF/1, for TERM=xterm, the tiget* functions provide access + to the number of colors and the color escape sequences, whereas + the tget* functions don't provide them. */ +#if HAVE_TERMINFO + int err = 1; + + if (setupterm (term, fd, &err) || err == 1) + { + /* Retrieve particular values depending on the terminal type. */ + stream->max_colors = tigetnum ("colors"); + stream->no_color_video = tigetnum ("ncv"); + stream->set_a_foreground = xstrdup0 (tigetstr ("setaf")); + stream->set_foreground = xstrdup0 (tigetstr ("setf")); + stream->set_a_background = xstrdup0 (tigetstr ("setab")); + stream->set_background = xstrdup0 (tigetstr ("setb")); + stream->orig_pair = xstrdup0 (tigetstr ("op")); + stream->enter_bold_mode = xstrdup0 (tigetstr ("bold")); + stream->enter_italics_mode = xstrdup0 (tigetstr ("sitm")); + stream->exit_italics_mode = xstrdup0 (tigetstr ("ritm")); + stream->enter_underline_mode = xstrdup0 (tigetstr ("smul")); + stream->exit_underline_mode = xstrdup0 (tigetstr ("rmul")); + stream->exit_attribute_mode = xstrdup0 (tigetstr ("sgr0")); + } +#elif HAVE_TERMCAP + struct { char buf[1024]; char canary[4]; } termcapbuf; + int retval; + + /* Call tgetent, being defensive against buffer overflow. */ + memcpy (termcapbuf.canary, "CnRy", 4); + retval = tgetent (termcapbuf.buf, term); + if (memcmp (termcapbuf.canary, "CnRy", 4) != 0) + /* Buffer overflow! */ + abort (); + + if (retval > 0) + { + struct { char buf[1024]; char canary[4]; } termentrybuf; + char *termentryptr; + + /* Prepare for calling tgetstr, being defensive against buffer + overflow. ncurses' tgetstr() supports a second argument NULL, + but NetBSD's tgetstr() doesn't. */ + memcpy (termentrybuf.canary, "CnRz", 4); + #define TEBP ((termentryptr = termentrybuf.buf), &termentryptr) + + /* Retrieve particular values depending on the terminal type. */ + stream->max_colors = tgetnum ("Co"); + stream->no_color_video = tgetnum ("NC"); + stream->set_a_foreground = xstrdup0 (tgetstr ("AF", TEBP)); + stream->set_foreground = xstrdup0 (tgetstr ("Sf", TEBP)); + stream->set_a_background = xstrdup0 (tgetstr ("AB", TEBP)); + stream->set_background = xstrdup0 (tgetstr ("Sb", TEBP)); + stream->orig_pair = xstrdup0 (tgetstr ("op", TEBP)); + stream->enter_bold_mode = xstrdup0 (tgetstr ("md", TEBP)); + stream->enter_italics_mode = xstrdup0 (tgetstr ("ZH", TEBP)); + stream->exit_italics_mode = xstrdup0 (tgetstr ("ZR", TEBP)); + stream->enter_underline_mode = xstrdup0 (tgetstr ("us", TEBP)); + stream->exit_underline_mode = xstrdup0 (tgetstr ("ue", TEBP)); + stream->exit_attribute_mode = xstrdup0 (tgetstr ("me", TEBP)); + +# ifdef __BEOS__ + /* The BeOS termcap entry for "beterm" is broken: For "AF" and "AB" + it contains balues in terminfo syntax but the system's tparam() + function understands only the termcap syntax. */ + if (stream->set_a_foreground != NULL + && strcmp (stream->set_a_foreground, "\033[3%p1%dm") == 0) + { + free (stream->set_a_foreground); + stream->set_a_foreground = xstrdup ("\033[3%dm"); + } + if (stream->set_a_background != NULL + && strcmp (stream->set_a_background, "\033[4%p1%dm") == 0) + { + free (stream->set_a_background); + stream->set_a_background = xstrdup ("\033[4%dm"); + } +# endif + + /* The termcap entry for cygwin is broken: It has no "ncv" value, + but bold and underline are actually rendered through colors. */ + if (strcmp (term, "cygwin") == 0) + stream->no_color_video |= 2 | 32; + + /* Done with tgetstr. Detect possible buffer overflow. */ + #undef TEBP + if (memcmp (termentrybuf.canary, "CnRz", 4) != 0) + /* Buffer overflow! */ + abort (); + } +#else + /* Fallback code for platforms with neither the terminfo nor the termcap + functions, such as mingw. + Assume the ANSI escape sequences. Extracted through + "TERM=ansi infocmp", replacing \E with \033. */ + stream->max_colors = 8; + stream->no_color_video = 3; + stream->set_a_foreground = xstrdup ("\033[3%p1%dm"); + stream->set_a_background = xstrdup ("\033[4%p1%dm"); + stream->orig_pair = xstrdup ("\033[39;49m"); + stream->enter_bold_mode = xstrdup ("\033[1m"); + stream->enter_underline_mode = xstrdup ("\033[4m"); + stream->exit_underline_mode = xstrdup ("\033[m"); + stream->exit_attribute_mode = xstrdup ("\033[0;10m"); +#endif + + /* AIX 4.3.2, IRIX 6.5, HP-UX 11, Solaris 7..10 all lack the + description of color capabilities of "xterm" and "xterms" + in their terminfo database. But it is important to have + color in xterm. So we provide the color capabilities here. */ + if (stream->max_colors <= 1 + && (strcmp (term, "xterm") == 0 || strcmp (term, "xterms") == 0)) + { + stream->max_colors = 8; + stream->set_a_foreground = xstrdup ("\033[3%p1%dm"); + stream->set_a_background = xstrdup ("\033[4%p1%dm"); + stream->orig_pair = xstrdup ("\033[39;49m"); + } + } + + /* Infer the capabilities. */ + stream->supports_foreground = + (stream->max_colors >= 8 + && (stream->set_a_foreground != NULL || stream->set_foreground != NULL) + && stream->orig_pair != NULL); + stream->supports_background = + (stream->max_colors >= 8 + && (stream->set_a_background != NULL || stream->set_background != NULL) + && stream->orig_pair != NULL); + stream->colormodel = + (stream->supports_foreground || stream->supports_background + ? (term != NULL + && (/* Recognize xterm-16color, xterm-88color, xterm-256color. */ + (strlen (term) >= 5 && memcmp (term, "xterm", 5) == 0) + || /* Recognize rxvt-16color. */ + (strlen (term) >= 4 && memcmp (term, "rxvt", 7) == 0) + || /* Recognize konsole-16color. */ + (strlen (term) >= 7 && memcmp (term, "konsole", 7) == 0)) + ? (stream->max_colors == 256 ? cm_xterm256 : + stream->max_colors == 88 ? cm_xterm88 : + stream->max_colors == 16 ? cm_xterm16 : + cm_xterm8) + : cm_common8) + : cm_monochrome); + stream->supports_weight = + (stream->enter_bold_mode != NULL && stream->exit_attribute_mode != NULL); + stream->supports_posture = + (stream->enter_italics_mode != NULL + && (stream->exit_italics_mode != NULL + || stream->exit_attribute_mode != NULL)); + stream->supports_underline = + (stream->enter_underline_mode != NULL + && (stream->exit_underline_mode != NULL + || stream->exit_attribute_mode != NULL)); + + /* Initialize the buffer. */ + stream->allocated = 120; + stream->buffer = XNMALLOC (stream->allocated, char); + stream->attrbuffer = XNMALLOC (stream->allocated, attributes_t); + stream->buflen = 0; + + /* Initialize the current attributes. */ + stream->curr_attr.color = COLOR_DEFAULT; + stream->curr_attr.bgcolor = COLOR_DEFAULT; + stream->curr_attr.weight = WEIGHT_DEFAULT; + stream->curr_attr.posture = POSTURE_DEFAULT; + stream->curr_attr.underline = UNDERLINE_DEFAULT; + stream->simp_attr = simplify_attributes (stream, stream->curr_attr); + + /* Register an exit handler. */ + { + static bool registered = false; + if (!registered) + { + atexit (restore); + registered = true; + } + } + + return stream; +} diff --git a/gettext-tools/gnulib-lib/term-ostream.oo.h b/gettext-tools/gnulib-lib/term-ostream.oo.h new file mode 100644 index 0000000..1ace97b --- /dev/null +++ b/gettext-tools/gnulib-lib/term-ostream.oo.h @@ -0,0 +1,109 @@ +/* Output stream for attributed text, producing ANSI escape sequences. + Copyright (C) 2006 Free Software Foundation, Inc. + Written by Bruno Haible , 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _TERM_OSTREAM_H +#define _TERM_OSTREAM_H + +#include "ostream.h" + + +/* Querying and setting of text attributes. + The stream has a notion of the current text attributes; they apply + implicitly to all following output. The attributes are automatically + reset when the stream is closed. + Note: Not all terminal types can actually render all attributes adequately. + For example, xterm cannot render POSTURE_ITALIC nor the combination of + WEIGHT_BOLD and UNDERLINE_ON. */ + +/* Colors are represented by indices >= 0 in a stream dependent format. */ +typedef int term_color_t; +/* The value -1 denotes the default (foreground or background) color. */ +enum +{ + COLOR_DEFAULT = -1 /* unknown */ +}; + +typedef enum +{ + WEIGHT_NORMAL = 0, + WEIGHT_BOLD, + WEIGHT_DEFAULT = WEIGHT_NORMAL +} term_weight_t; + +typedef enum +{ + POSTURE_NORMAL = 0, + POSTURE_ITALIC, /* same as oblique */ + POSTURE_DEFAULT = POSTURE_NORMAL +} term_posture_t; + +typedef enum +{ + UNDERLINE_OFF = 0, + UNDERLINE_ON, + UNDERLINE_DEFAULT = UNDERLINE_OFF +} term_underline_t; + +struct term_ostream : struct ostream +{ +methods: + + /* Convert an RGB value (red, green, blue in [0..255]) to a color, valid + for this stream only. */ + term_color_t rgb_to_color (term_ostream_t stream, + int red, int green, int blue); + + /* Get/set the text color. */ + term_color_t get_color (term_ostream_t stream); + void set_color (term_ostream_t stream, term_color_t color); + + /* Get/set the background color. */ + term_color_t get_bgcolor (term_ostream_t stream); + void set_bgcolor (term_ostream_t stream, term_color_t color); + + /* Get/set the font weight. */ + term_weight_t get_weight (term_ostream_t stream); + void set_weight (term_ostream_t stream, term_weight_t weight); + + /* Get/set the font posture. */ + term_posture_t get_posture (term_ostream_t stream); + void set_posture (term_ostream_t stream, term_posture_t posture); + + /* Get/set the text underline decoration. */ + term_underline_t get_underline (term_ostream_t stream); + void set_underline (term_ostream_t stream, + term_underline_t underline); +}; + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Create an output stream referring to the file descriptor FD. + FILENAME is used only for error messages. + The resulting stream will be line-buffered. + Note that the resulting stream must be closed before FD can be closed. */ +extern term_ostream_t term_ostream_create (int fd, const char *filename); + + +#ifdef __cplusplus +} +#endif + +#endif /* _TERM_OSTREAM_H */ diff --git a/gettext-tools/gnulib-lib/term-styled-ostream.c b/gettext-tools/gnulib-lib/term-styled-ostream.c new file mode 100644 index 0000000..38a0084 --- /dev/null +++ b/gettext-tools/gnulib-lib/term-styled-ostream.c @@ -0,0 +1,688 @@ +/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ + +#line 1 "term-styled-ostream.oo.c" +/* Output stream for CSS styled text, producing ANSI escape sequences. + Copyright (C) 2006-2007 Free Software Foundation, Inc. + Written by Bruno Haible , 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include "term-styled-ostream.h" + +#include + +#include +#include +#include +#include +/* has a broken double-inclusion guard in libcroco-0.6.1. */ +#ifndef __CR_FONTS_H__ +# include +#endif +#include + +#include "term-ostream.h" +#include "hash.h" +#include "xalloc.h" + + +/* CSS matching works as follows: + Suppose we have an element inside class "header" inside class "table". + We pretend to have an XML tree that looks like this: + + (root) + +----table + +----header + + For each of these XML nodes, the CSS matching engine can report the + matching CSS declarations. We extract the CSS property values that + matter for terminal styling and cache them. */ + +/* Attributes that can be set on a character. */ +typedef struct +{ + term_color_t color; + term_color_t bgcolor; + term_weight_t weight; + term_posture_t posture; + term_underline_t underline; +} attributes_t; + +#line 66 "term-styled-ostream.c" +#if !IS_CPLUSPLUS +#define term_styled_ostream_representation any_ostream_representation +#endif +#include "term_styled_ostream.priv.h" + +const typeinfo_t term_styled_ostream_typeinfo = { "term_styled_ostream" }; + +static const typeinfo_t * const term_styled_ostream_superclasses[] = + { term_styled_ostream_SUPERCLASSES }; + +#define super styled_ostream_vtable + +#line 82 "term-styled-ostream.oo.c" + +/* Implementation of ostream_t methods. */ + +static void +term_styled_ostream__write_mem (term_styled_ostream_t stream, + const void *data, size_t len) +{ + term_ostream_set_color (stream->destination, stream->curr_attr->color); + term_ostream_set_bgcolor (stream->destination, stream->curr_attr->bgcolor); + term_ostream_set_weight (stream->destination, stream->curr_attr->weight); + term_ostream_set_posture (stream->destination, stream->curr_attr->posture); + term_ostream_set_underline (stream->destination, stream->curr_attr->underline); + + term_ostream_write_mem (stream->destination, data, len); +} + +static void +term_styled_ostream__flush (term_styled_ostream_t stream) +{ + term_ostream_flush (stream->destination); +} + +static void +term_styled_ostream__free (term_styled_ostream_t stream) +{ + term_ostream_free (stream->destination); + cr_cascade_destroy (stream->css_document); + cr_sel_eng_destroy (stream->css_engine); + free (stream->curr_classes); + { + void *ptr = NULL; + const void *key; + size_t keylen; + void *data; + + while (hash_iterate (&stream->cache, &ptr, &key, &keylen, &data) == 0) + { + free (data); + } + } + hash_destroy (&stream->cache); + free (stream); +} + +/* Implementation of styled_ostream_t methods. */ + +/* CRStyle doesn't contain a value for the 'text-decoration' property. + So we have to extend it. */ + +enum CRXTextDecorationType +{ + TEXT_DECORATION_NONE, + TEXT_DECORATION_UNDERLINE, + TEXT_DECORATION_OVERLINE, + TEXT_DECORATION_LINE_THROUGH, + TEXT_DECORATION_BLINK, + TEXT_DECORATION_INHERIT +}; + +typedef struct _CRXStyle +{ + struct _CRXStyle *parent_style; + CRStyle *base; + enum CRXTextDecorationType text_decoration; +} CRXStyle; + +/* An extended version of cr_style_new. */ +static CRXStyle * +crx_style_new (gboolean a_set_props_to_initial_values) +{ + CRStyle *base; + CRXStyle *result; + + base = cr_style_new (a_set_props_to_initial_values); + if (base == NULL) + return NULL; + + result = XMALLOC (CRXStyle); + result->base = base; + if (a_set_props_to_initial_values) + result->text_decoration = TEXT_DECORATION_NONE; + else + result->text_decoration = TEXT_DECORATION_INHERIT; + + return result; +} + +/* An extended version of cr_style_destroy. */ +static void +crx_style_destroy (CRXStyle *a_style) +{ + cr_style_destroy (a_style->base); + free (a_style); +} + +/* An extended version of cr_sel_eng_get_matched_style. */ +static enum CRStatus +crx_sel_eng_get_matched_style (CRSelEng * a_this, CRCascade * a_cascade, + xmlNode * a_node, + CRXStyle * a_parent_style, CRXStyle ** a_style, + gboolean a_set_props_to_initial_values) +{ + enum CRStatus status; + CRPropList *props = NULL; + + if (!(a_this && a_cascade && a_node && a_style)) + return CR_BAD_PARAM_ERROR; + + status = cr_sel_eng_get_matched_properties_from_cascade (a_this, a_cascade, + a_node, &props); + if (!(status == CR_OK)) + return status; + + if (props) + { + CRXStyle *style; + + if (!*a_style) + { + *a_style = crx_style_new (a_set_props_to_initial_values); + if (!*a_style) + return CR_ERROR; + } + else + { + if (a_set_props_to_initial_values) + { + cr_style_set_props_to_initial_values ((*a_style)->base); + (*a_style)->text_decoration = TEXT_DECORATION_NONE; + } + else + { + cr_style_set_props_to_default_values ((*a_style)->base); + (*a_style)->text_decoration = TEXT_DECORATION_INHERIT; + } + } + style = *a_style; + style->parent_style = a_parent_style; + style->base->parent_style = + (a_parent_style != NULL ? a_parent_style->base : NULL); + + { + CRPropList *cur; + + for (cur = props; cur != NULL; cur = cr_prop_list_get_next (cur)) + { + CRDeclaration *decl = NULL; + + cr_prop_list_get_decl (cur, &decl); + cr_style_set_style_from_decl (style->base, decl); + if (decl != NULL + && decl->property != NULL + && decl->property->stryng != NULL + && decl->property->stryng->str != NULL) + { + if (strcmp (decl->property->stryng->str, "text-decoration") == 0 + && decl->value != NULL + && decl->value->type == TERM_IDENT + && decl->value->content.str != NULL) + { + const char *value = + cr_string_peek_raw_str (decl->value->content.str); + + if (value != NULL) + { + if (strcmp (value, "none") == 0) + style->text_decoration = TEXT_DECORATION_NONE; + else if (strcmp (value, "underline") == 0) + style->text_decoration = TEXT_DECORATION_UNDERLINE; + else if (strcmp (value, "overline") == 0) + style->text_decoration = TEXT_DECORATION_OVERLINE; + else if (strcmp (value, "line-through") == 0) + style->text_decoration = TEXT_DECORATION_LINE_THROUGH; + else if (strcmp (value, "blink") == 0) + style->text_decoration = TEXT_DECORATION_BLINK; + else if (strcmp (value, "inherit") == 0) + style->text_decoration = TEXT_DECORATION_INHERIT; + } + } + } + } + } + + cr_prop_list_destroy (props); + } + + return CR_OK; +} + +/* According to the CSS2 spec, sections 6.1 and 6.2, we need to do a + propagation: specified values -> computed values -> actual values. + The computed values are necessary. libcroco does not compute them for us. + The function cr_style_resolve_inherited_properties is also not sufficient: + it handles only the case of inheritance, not the case of non-inheritance. + So we write style accessors that fetch the computed value, doing the + inheritance on the fly. + We then compute the actual values from the computed values; for colors, + this is done through the rgb_to_color method. */ + +static term_color_t +style_compute_color_value (CRStyle *style, enum CRRgbProp which, + term_ostream_t stream) +{ + for (;;) + { + if (style == NULL) + return COLOR_DEFAULT; + if (cr_rgb_is_set_to_inherit (&style->rgb_props[which].sv)) + style = style->parent_style; + else if (cr_rgb_is_set_to_transparent (&style->rgb_props[which].sv)) + /* A transparent color occurs as default background color, set by + cr_style_set_props_to_default_values. */ + return COLOR_DEFAULT; + else + { + CRRgb rgb; + int r; + int g; + int b; + + cr_rgb_copy (&rgb, &style->rgb_props[which].sv); + if (cr_rgb_compute_from_percentage (&rgb) != CR_OK) + abort (); + r = rgb.red & 0xff; + g = rgb.green & 0xff; + b = rgb.blue & 0xff; + return term_ostream_rgb_to_color (stream, r, g, b); + } + } +} + +static term_weight_t +style_compute_font_weight_value (const CRStyle *style) +{ + int value = 0; + for (;;) + { + if (style == NULL) + value += 4; + else + switch (style->font_weight) + { + case FONT_WEIGHT_INHERIT: + style = style->parent_style; + continue; + case FONT_WEIGHT_BOLDER: + value += 1; + style = style->parent_style; + continue; + case FONT_WEIGHT_LIGHTER: + value -= 1; + style = style->parent_style; + continue; + case FONT_WEIGHT_100: + value += 1; + break; + case FONT_WEIGHT_200: + value += 2; + break; + case FONT_WEIGHT_300: + value += 3; + break; + case FONT_WEIGHT_400: case FONT_WEIGHT_NORMAL: + value += 4; + break; + case FONT_WEIGHT_500: + value += 5; + break; + case FONT_WEIGHT_600: + value += 6; + break; + case FONT_WEIGHT_700: case FONT_WEIGHT_BOLD: + value += 7; + break; + case FONT_WEIGHT_800: + value += 8; + break; + case FONT_WEIGHT_900: + value += 9; + break; + default: + abort (); + } + /* Value >= 600 -> WEIGHT_BOLD. Value <= 500 -> WEIGHT_NORMAL. */ + return (value >= 6 ? WEIGHT_BOLD : WEIGHT_NORMAL); + } +} + +static term_posture_t +style_compute_font_posture_value (const CRStyle *style) +{ + for (;;) + { + if (style == NULL) + return POSTURE_DEFAULT; + switch (style->font_style) + { + case FONT_STYLE_INHERIT: + style = style->parent_style; + break; + case FONT_STYLE_NORMAL: + return POSTURE_NORMAL; + case FONT_STYLE_ITALIC: + case FONT_STYLE_OBLIQUE: + return POSTURE_ITALIC; + default: + abort (); + } + } +} + +static term_underline_t +style_compute_text_underline_value (const CRXStyle *style) +{ + for (;;) + { + if (style == NULL) + return UNDERLINE_DEFAULT; + switch (style->text_decoration) + { + case TEXT_DECORATION_INHERIT: + style = style->parent_style; + break; + case TEXT_DECORATION_NONE: + case TEXT_DECORATION_OVERLINE: + case TEXT_DECORATION_LINE_THROUGH: + case TEXT_DECORATION_BLINK: + return UNDERLINE_OFF; + case TEXT_DECORATION_UNDERLINE: + return UNDERLINE_ON; + default: + abort (); + } + } +} + +/* Match the current list of CSS classes to the CSS and return the result. */ +static attributes_t * +match (term_styled_ostream_t stream) +{ + xmlNodePtr root; + xmlNodePtr curr; + char *p_end; + char *p_start; + CRXStyle *curr_style; + CRStyle *curr_style_base; + attributes_t *attr; + + /* Create a hierarchy of XML nodes. */ + root = xmlNewNode (NULL, (const xmlChar *) "__root__"); + root->type = XML_ELEMENT_NODE; + curr = root; + p_end = &stream->curr_classes[stream->curr_classes_length]; + p_start = stream->curr_classes; + while (p_start < p_end) + { + char *p; + xmlNodePtr child; + + if (!(*p_start == ' ')) + abort (); + p_start++; + for (p = p_start; p < p_end && *p != ' '; p++) + ; + + /* Temporarily replace the ' ' by '\0'. */ + *p = '\0'; + child = xmlNewNode (NULL, (const xmlChar *) p_start); + child->type = XML_ELEMENT_NODE; + xmlSetProp (child, (const xmlChar *) "class", (const xmlChar *) p_start); + *p = ' '; + + if (xmlAddChild (curr, child) == NULL) + /* Error! Shouldn't happen. */ + abort (); + + curr = child; + p_start = p; + } + + /* Retrieve the matching CSS declarations. */ + /* Not curr_style = crx_style_new (TRUE); because that assumes that the + default foreground color is black and that the default background color + is white, which is not necessarily true in a terminal context. */ + curr_style = NULL; + for (curr = root; curr != NULL; curr = curr->children) + { + CRXStyle *parent_style = curr_style; + curr_style = NULL; + + if (crx_sel_eng_get_matched_style (stream->css_engine, + stream->css_document, + curr, + parent_style, &curr_style, + FALSE) != CR_OK) + abort (); + if (curr_style == NULL) + /* No declarations matched this node. Inherit all values. */ + curr_style = parent_style; + else + /* curr_style is a new style, inheriting from parent_style. */ + ; + } + curr_style_base = (curr_style != NULL ? curr_style->base : NULL); + + /* Extract the CSS declarations that we can use. */ + attr = XMALLOC (attributes_t); + attr->color = + style_compute_color_value (curr_style_base, RGB_PROP_COLOR, + stream->destination); + attr->bgcolor = + style_compute_color_value (curr_style_base, RGB_PROP_BACKGROUND_COLOR, + stream->destination); + attr->weight = style_compute_font_weight_value (curr_style_base); + attr->posture = style_compute_font_posture_value (curr_style_base); + attr->underline = style_compute_text_underline_value (curr_style); + + /* Free the style chain. */ + while (curr_style != NULL) + { + CRXStyle *parent_style = curr_style->parent_style; + + crx_style_destroy (curr_style); + curr_style = parent_style; + } + + /* Free the XML nodes. */ + xmlFreeNodeList (root); + + return attr; +} + +/* Match the current list of CSS classes to the CSS and store the result in + stream->curr_attr and in the cache. */ +static void +match_and_cache (term_styled_ostream_t stream) +{ + attributes_t *attr = match (stream); + if (hash_insert_entry (&stream->cache, + stream->curr_classes, stream->curr_classes_length, + attr) == NULL) + abort (); + stream->curr_attr = attr; +} + +static void +term_styled_ostream__begin_use_class (term_styled_ostream_t stream, + const char *classname) +{ + size_t classname_len; + char *p; + void *found; + + if (classname[0] == '\0' || strchr (classname, ' ') != NULL) + /* Invalid classname argument. */ + abort (); + + /* Push the classname onto the classname list. */ + classname_len = strlen (classname); + if (stream->curr_classes_length + 1 + classname_len + 1 + > stream->curr_classes_allocated) + { + size_t new_allocated = stream->curr_classes_length + 1 + classname_len + 1; + if (new_allocated < 2 * stream->curr_classes_allocated) + new_allocated = 2 * stream->curr_classes_allocated; + + stream->curr_classes = xrealloc (stream->curr_classes, new_allocated); + stream->curr_classes_allocated = new_allocated; + } + p = &stream->curr_classes[stream->curr_classes_length]; + *p++ = ' '; + memcpy (p, classname, classname_len); + stream->curr_classes_length += 1 + classname_len; + + /* Uodate stream->curr_attr. */ + if (hash_find_entry (&stream->cache, + stream->curr_classes, stream->curr_classes_length, + &found) < 0) + match_and_cache (stream); + else + stream->curr_attr = (attributes_t *) found; +} + +static void +term_styled_ostream__end_use_class (term_styled_ostream_t stream, + const char *classname) +{ + char *p_end; + char *p_start; + char *p; + void *found; + + if (stream->curr_classes_length == 0) + /* No matching call to begin_use_class. */ + abort (); + + /* Remove the trailing classname. */ + p_end = &stream->curr_classes[stream->curr_classes_length]; + p = p_end; + while (*--p != ' ') + ; + p_start = p + 1; + if (!(p_end - p_start == strlen (classname) + && memcmp (p_start, classname, p_end - p_start) == 0)) + /* The match ing call to begin_use_class used a different classname. */ + abort (); + stream->curr_classes_length = p - stream->curr_classes; + + /* Update stream->curr_attr. */ + if (hash_find_entry (&stream->cache, + stream->curr_classes, stream->curr_classes_length, + &found) < 0) + abort (); + stream->curr_attr = (attributes_t *) found; +} + +/* Constructor. */ + +term_styled_ostream_t +term_styled_ostream_create (int fd, const char *filename, + const char *css_filename) +{ + term_styled_ostream_t stream = + XMALLOC (struct term_styled_ostream_representation); + CRStyleSheet *css_file_contents; + + stream->base.base.vtable = &term_styled_ostream_vtable; + stream->destination = term_ostream_create (fd, filename); + + if (cr_om_parser_simply_parse_file ((const guchar *) css_filename, + CR_UTF_8, /* CR_AUTO is not supported */ + &css_file_contents) != CR_OK) + { + term_ostream_free (stream->destination); + free (stream); + return NULL; + } + stream->css_document = cr_cascade_new (NULL, css_file_contents, NULL); + stream->css_engine = cr_sel_eng_new (); + + stream->curr_classes_allocated = 60; + stream->curr_classes = XNMALLOC (stream->curr_classes_allocated, char); + stream->curr_classes_length = 0; + + hash_init (&stream->cache, 10); + + match_and_cache (stream); + + return stream; +} + +#line 631 "term-styled-ostream.c" + +const struct term_styled_ostream_implementation term_styled_ostream_vtable = +{ + term_styled_ostream_superclasses, + sizeof (term_styled_ostream_superclasses) / sizeof (term_styled_ostream_superclasses[0]), + sizeof (struct term_styled_ostream_representation), + term_styled_ostream__write_mem, + term_styled_ostream__flush, + term_styled_ostream__free, + term_styled_ostream__begin_use_class, + term_styled_ostream__end_use_class, +}; + +#if !HAVE_INLINE + +/* Define the functions that invoke the methods. */ + +void +term_styled_ostream_write_mem (term_styled_ostream_t first_arg, const void *data, size_t len) +{ + const struct term_styled_ostream_implementation *vtable = + ((struct term_styled_ostream_representation_header *) (struct term_styled_ostream_representation *) first_arg)->vtable; + vtable->write_mem (first_arg,data,len); +} + +void +term_styled_ostream_flush (term_styled_ostream_t first_arg) +{ + const struct term_styled_ostream_implementation *vtable = + ((struct term_styled_ostream_representation_header *) (struct term_styled_ostream_representation *) first_arg)->vtable; + vtable->flush (first_arg); +} + +void +term_styled_ostream_free (term_styled_ostream_t first_arg) +{ + const struct term_styled_ostream_implementation *vtable = + ((struct term_styled_ostream_representation_header *) (struct term_styled_ostream_representation *) first_arg)->vtable; + vtable->free (first_arg); +} + +void +term_styled_ostream_begin_use_class (term_styled_ostream_t first_arg, const char *classname) +{ + const struct term_styled_ostream_implementation *vtable = + ((struct term_styled_ostream_representation_header *) (struct term_styled_ostream_representation *) first_arg)->vtable; + vtable->begin_use_class (first_arg,classname); +} + +void +term_styled_ostream_end_use_class (term_styled_ostream_t first_arg, const char *classname) +{ + const struct term_styled_ostream_implementation *vtable = + ((struct term_styled_ostream_representation_header *) (struct term_styled_ostream_representation *) first_arg)->vtable; + vtable->end_use_class (first_arg,classname); +} + +#endif diff --git a/gettext-tools/gnulib-lib/term-styled-ostream.h b/gettext-tools/gnulib-lib/term-styled-ostream.h new file mode 100644 index 0000000..51b79ee --- /dev/null +++ b/gettext-tools/gnulib-lib/term-styled-ostream.h @@ -0,0 +1,161 @@ +/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ + +#line 1 "term-styled-ostream.oo.h" +/* Output stream for CSS styled text, producing ANSI escape sequences. + Copyright (C) 2006 Free Software Foundation, Inc. + Written by Bruno Haible , 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _TERM_STYLED_OSTREAM_H +#define _TERM_STYLED_OSTREAM_H + +#include "styled-ostream.h" + + +#line 28 "term-styled-ostream.h" +struct term_styled_ostream_representation; +/* term_styled_ostream_t is defined as a pointer to struct term_styled_ostream_representation. + In C++ mode, we use a smart pointer class. + In C mode, we have no other choice than a typedef to the root class type. */ +#if IS_CPLUSPLUS +struct term_styled_ostream_t +{ +private: + struct term_styled_ostream_representation *_pointer; +public: + term_styled_ostream_t () : _pointer (NULL) {} + term_styled_ostream_t (struct term_styled_ostream_representation *pointer) : _pointer (pointer) {} + struct term_styled_ostream_representation * operator -> () { return _pointer; } + operator struct term_styled_ostream_representation * () { return _pointer; } + operator struct any_ostream_representation * () { return (struct any_ostream_representation *) _pointer; } + operator struct styled_ostream_representation * () { return (struct styled_ostream_representation *) _pointer; } + operator void * () { return _pointer; } + bool operator == (const void *p) { return _pointer == p; } + bool operator != (const void *p) { return _pointer != p; } + operator ostream_t () { return (ostream_t) (struct any_ostream_representation *) _pointer; } + explicit term_styled_ostream_t (ostream_t x) : _pointer ((struct term_styled_ostream_representation *) (void *) x) {} + operator styled_ostream_t () { return (styled_ostream_t) (struct styled_ostream_representation *) _pointer; } + explicit term_styled_ostream_t (styled_ostream_t x) : _pointer ((struct term_styled_ostream_representation *) (void *) x) {} +}; +#else +typedef styled_ostream_t term_styled_ostream_t; +#endif + +/* Functions that invoke the methods. */ +extern void term_styled_ostream_write_mem (term_styled_ostream_t first_arg, const void *data, size_t len); +extern void term_styled_ostream_flush (term_styled_ostream_t first_arg); +extern void term_styled_ostream_free (term_styled_ostream_t first_arg); +extern void term_styled_ostream_begin_use_class (term_styled_ostream_t first_arg, const char *classname); +extern void term_styled_ostream_end_use_class (term_styled_ostream_t first_arg, const char *classname); + +/* Type representing an implementation of term_styled_ostream_t. */ +struct term_styled_ostream_implementation +{ + const typeinfo_t * const *superclasses; + size_t superclasses_length; + size_t instance_size; +#define THIS_ARG term_styled_ostream_t first_arg +#include "term_styled_ostream.vt.h" +#undef THIS_ARG +}; + +/* Public portion of the object pointed to by a term_styled_ostream_t. */ +struct term_styled_ostream_representation_header +{ + const struct term_styled_ostream_implementation *vtable; +}; + +#if HAVE_INLINE + +/* Define the functions that invoke the methods as inline accesses to + the term_styled_ostream_implementation. + Use #define to avoid a warning because of extern vs. static. */ + +# define term_styled_ostream_write_mem term_styled_ostream_write_mem_inline +static inline void +term_styled_ostream_write_mem (term_styled_ostream_t first_arg, const void *data, size_t len) +{ + const struct term_styled_ostream_implementation *vtable = + ((struct term_styled_ostream_representation_header *) (struct term_styled_ostream_representation *) first_arg)->vtable; + vtable->write_mem (first_arg,data,len); +} + +# define term_styled_ostream_flush term_styled_ostream_flush_inline +static inline void +term_styled_ostream_flush (term_styled_ostream_t first_arg) +{ + const struct term_styled_ostream_implementation *vtable = + ((struct term_styled_ostream_representation_header *) (struct term_styled_ostream_representation *) first_arg)->vtable; + vtable->flush (first_arg); +} + +# define term_styled_ostream_free term_styled_ostream_free_inline +static inline void +term_styled_ostream_free (term_styled_ostream_t first_arg) +{ + const struct term_styled_ostream_implementation *vtable = + ((struct term_styled_ostream_representation_header *) (struct term_styled_ostream_representation *) first_arg)->vtable; + vtable->free (first_arg); +} + +# define term_styled_ostream_begin_use_class term_styled_ostream_begin_use_class_inline +static inline void +term_styled_ostream_begin_use_class (term_styled_ostream_t first_arg, const char *classname) +{ + const struct term_styled_ostream_implementation *vtable = + ((struct term_styled_ostream_representation_header *) (struct term_styled_ostream_representation *) first_arg)->vtable; + vtable->begin_use_class (first_arg,classname); +} + +# define term_styled_ostream_end_use_class term_styled_ostream_end_use_class_inline +static inline void +term_styled_ostream_end_use_class (term_styled_ostream_t first_arg, const char *classname) +{ + const struct term_styled_ostream_implementation *vtable = + ((struct term_styled_ostream_representation_header *) (struct term_styled_ostream_representation *) first_arg)->vtable; + vtable->end_use_class (first_arg,classname); +} + +#endif + +extern const typeinfo_t term_styled_ostream_typeinfo; +#define term_styled_ostream_SUPERCLASSES &term_styled_ostream_typeinfo, styled_ostream_SUPERCLASSES +#define term_styled_ostream_SUPERCLASSES_LENGTH (1 + styled_ostream_SUPERCLASSES_LENGTH) + +extern const struct term_styled_ostream_implementation term_styled_ostream_vtable; + +#line 28 "term-styled-ostream.oo.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Create an output stream referring to the file descriptor FD, styled with + the file CSS_FILENAME. + FILENAME is used only for error messages. + Note that the resulting stream must be closed before FD can be closed. + Return NULL upon failure. */ +extern term_styled_ostream_t + term_styled_ostream_create (int fd, const char *filename, + const char *css_filename); + + +#ifdef __cplusplus +} +#endif + +#endif /* _TERM_STYLED_OSTREAM_H */ diff --git a/gettext-tools/gnulib-lib/term-styled-ostream.oo.c b/gettext-tools/gnulib-lib/term-styled-ostream.oo.c new file mode 100644 index 0000000..a08bf65 --- /dev/null +++ b/gettext-tools/gnulib-lib/term-styled-ostream.oo.c @@ -0,0 +1,631 @@ +/* Output stream for CSS styled text, producing ANSI escape sequences. + Copyright (C) 2006-2007 Free Software Foundation, Inc. + Written by Bruno Haible , 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include "term-styled-ostream.h" + +#include + +#include +#include +#include +#include +/* has a broken double-inclusion guard in libcroco-0.6.1. */ +#ifndef __CR_FONTS_H__ +# include +#endif +#include + +#include "term-ostream.h" +#include "hash.h" +#include "xalloc.h" + + +/* CSS matching works as follows: + Suppose we have an element inside class "header" inside class "table". + We pretend to have an XML tree that looks like this: + + (root) + +----table + +----header + + For each of these XML nodes, the CSS matching engine can report the + matching CSS declarations. We extract the CSS property values that + matter for terminal styling and cache them. */ + +/* Attributes that can be set on a character. */ +typedef struct +{ + term_color_t color; + term_color_t bgcolor; + term_weight_t weight; + term_posture_t posture; + term_underline_t underline; +} attributes_t; + +struct term_styled_ostream : struct styled_ostream +{ +fields: + /* The destination stream. */ + term_ostream_t destination; + /* The CSS document. */ + CRCascade *css_document; + /* The CSS matching engine. */ + CRSelEng *css_engine; + /* The list of active XML elements, with a space before each. + For example, in above example, it is " table header". */ + char *curr_classes; + size_t curr_classes_length; + size_t curr_classes_allocated; + /* A hash table mapping a list of classes (as a string) to an + 'attributes_t *'. */ + hash_table cache; + /* The current attributes. */ + attributes_t *curr_attr; +}; + +/* Implementation of ostream_t methods. */ + +static void +term_styled_ostream::write_mem (term_styled_ostream_t stream, + const void *data, size_t len) +{ + term_ostream_set_color (stream->destination, stream->curr_attr->color); + term_ostream_set_bgcolor (stream->destination, stream->curr_attr->bgcolor); + term_ostream_set_weight (stream->destination, stream->curr_attr->weight); + term_ostream_set_posture (stream->destination, stream->curr_attr->posture); + term_ostream_set_underline (stream->destination, stream->curr_attr->underline); + + term_ostream_write_mem (stream->destination, data, len); +} + +static void +term_styled_ostream::flush (term_styled_ostream_t stream) +{ + term_ostream_flush (stream->destination); +} + +static void +term_styled_ostream::free (term_styled_ostream_t stream) +{ + term_ostream_free (stream->destination); + cr_cascade_destroy (stream->css_document); + cr_sel_eng_destroy (stream->css_engine); + free (stream->curr_classes); + { + void *ptr = NULL; + const void *key; + size_t keylen; + void *data; + + while (hash_iterate (&stream->cache, &ptr, &key, &keylen, &data) == 0) + { + free (data); + } + } + hash_destroy (&stream->cache); + free (stream); +} + +/* Implementation of styled_ostream_t methods. */ + +/* CRStyle doesn't contain a value for the 'text-decoration' property. + So we have to extend it. */ + +enum CRXTextDecorationType +{ + TEXT_DECORATION_NONE, + TEXT_DECORATION_UNDERLINE, + TEXT_DECORATION_OVERLINE, + TEXT_DECORATION_LINE_THROUGH, + TEXT_DECORATION_BLINK, + TEXT_DECORATION_INHERIT +}; + +typedef struct _CRXStyle +{ + struct _CRXStyle *parent_style; + CRStyle *base; + enum CRXTextDecorationType text_decoration; +} CRXStyle; + +/* An extended version of cr_style_new. */ +static CRXStyle * +crx_style_new (gboolean a_set_props_to_initial_values) +{ + CRStyle *base; + CRXStyle *result; + + base = cr_style_new (a_set_props_to_initial_values); + if (base == NULL) + return NULL; + + result = XMALLOC (CRXStyle); + result->base = base; + if (a_set_props_to_initial_values) + result->text_decoration = TEXT_DECORATION_NONE; + else + result->text_decoration = TEXT_DECORATION_INHERIT; + + return result; +} + +/* An extended version of cr_style_destroy. */ +static void +crx_style_destroy (CRXStyle *a_style) +{ + cr_style_destroy (a_style->base); + free (a_style); +} + +/* An extended version of cr_sel_eng_get_matched_style. */ +static enum CRStatus +crx_sel_eng_get_matched_style (CRSelEng * a_this, CRCascade * a_cascade, + xmlNode * a_node, + CRXStyle * a_parent_style, CRXStyle ** a_style, + gboolean a_set_props_to_initial_values) +{ + enum CRStatus status; + CRPropList *props = NULL; + + if (!(a_this && a_cascade && a_node && a_style)) + return CR_BAD_PARAM_ERROR; + + status = cr_sel_eng_get_matched_properties_from_cascade (a_this, a_cascade, + a_node, &props); + if (!(status == CR_OK)) + return status; + + if (props) + { + CRXStyle *style; + + if (!*a_style) + { + *a_style = crx_style_new (a_set_props_to_initial_values); + if (!*a_style) + return CR_ERROR; + } + else + { + if (a_set_props_to_initial_values) + { + cr_style_set_props_to_initial_values ((*a_style)->base); + (*a_style)->text_decoration = TEXT_DECORATION_NONE; + } + else + { + cr_style_set_props_to_default_values ((*a_style)->base); + (*a_style)->text_decoration = TEXT_DECORATION_INHERIT; + } + } + style = *a_style; + style->parent_style = a_parent_style; + style->base->parent_style = + (a_parent_style != NULL ? a_parent_style->base : NULL); + + { + CRPropList *cur; + + for (cur = props; cur != NULL; cur = cr_prop_list_get_next (cur)) + { + CRDeclaration *decl = NULL; + + cr_prop_list_get_decl (cur, &decl); + cr_style_set_style_from_decl (style->base, decl); + if (decl != NULL + && decl->property != NULL + && decl->property->stryng != NULL + && decl->property->stryng->str != NULL) + { + if (strcmp (decl->property->stryng->str, "text-decoration") == 0 + && decl->value != NULL + && decl->value->type == TERM_IDENT + && decl->value->content.str != NULL) + { + const char *value = + cr_string_peek_raw_str (decl->value->content.str); + + if (value != NULL) + { + if (strcmp (value, "none") == 0) + style->text_decoration = TEXT_DECORATION_NONE; + else if (strcmp (value, "underline") == 0) + style->text_decoration = TEXT_DECORATION_UNDERLINE; + else if (strcmp (value, "overline") == 0) + style->text_decoration = TEXT_DECORATION_OVERLINE; + else if (strcmp (value, "line-through") == 0) + style->text_decoration = TEXT_DECORATION_LINE_THROUGH; + else if (strcmp (value, "blink") == 0) + style->text_decoration = TEXT_DECORATION_BLINK; + else if (strcmp (value, "inherit") == 0) + style->text_decoration = TEXT_DECORATION_INHERIT; + } + } + } + } + } + + cr_prop_list_destroy (props); + } + + return CR_OK; +} + +/* According to the CSS2 spec, sections 6.1 and 6.2, we need to do a + propagation: specified values -> computed values -> actual values. + The computed values are necessary. libcroco does not compute them for us. + The function cr_style_resolve_inherited_properties is also not sufficient: + it handles only the case of inheritance, not the case of non-inheritance. + So we write style accessors that fetch the computed value, doing the + inheritance on the fly. + We then compute the actual values from the computed values; for colors, + this is done through the rgb_to_color method. */ + +static term_color_t +style_compute_color_value (CRStyle *style, enum CRRgbProp which, + term_ostream_t stream) +{ + for (;;) + { + if (style == NULL) + return COLOR_DEFAULT; + if (cr_rgb_is_set_to_inherit (&style->rgb_props[which].sv)) + style = style->parent_style; + else if (cr_rgb_is_set_to_transparent (&style->rgb_props[which].sv)) + /* A transparent color occurs as default background color, set by + cr_style_set_props_to_default_values. */ + return COLOR_DEFAULT; + else + { + CRRgb rgb; + int r; + int g; + int b; + + cr_rgb_copy (&rgb, &style->rgb_props[which].sv); + if (cr_rgb_compute_from_percentage (&rgb) != CR_OK) + abort (); + r = rgb.red & 0xff; + g = rgb.green & 0xff; + b = rgb.blue & 0xff; + return term_ostream_rgb_to_color (stream, r, g, b); + } + } +} + +static term_weight_t +style_compute_font_weight_value (const CRStyle *style) +{ + int value = 0; + for (;;) + { + if (style == NULL) + value += 4; + else + switch (style->font_weight) + { + case FONT_WEIGHT_INHERIT: + style = style->parent_style; + continue; + case FONT_WEIGHT_BOLDER: + value += 1; + style = style->parent_style; + continue; + case FONT_WEIGHT_LIGHTER: + value -= 1; + style = style->parent_style; + continue; + case FONT_WEIGHT_100: + value += 1; + break; + case FONT_WEIGHT_200: + value += 2; + break; + case FONT_WEIGHT_300: + value += 3; + break; + case FONT_WEIGHT_400: case FONT_WEIGHT_NORMAL: + value += 4; + break; + case FONT_WEIGHT_500: + value += 5; + break; + case FONT_WEIGHT_600: + value += 6; + break; + case FONT_WEIGHT_700: case FONT_WEIGHT_BOLD: + value += 7; + break; + case FONT_WEIGHT_800: + value += 8; + break; + case FONT_WEIGHT_900: + value += 9; + break; + default: + abort (); + } + /* Value >= 600 -> WEIGHT_BOLD. Value <= 500 -> WEIGHT_NORMAL. */ + return (value >= 6 ? WEIGHT_BOLD : WEIGHT_NORMAL); + } +} + +static term_posture_t +style_compute_font_posture_value (const CRStyle *style) +{ + for (;;) + { + if (style == NULL) + return POSTURE_DEFAULT; + switch (style->font_style) + { + case FONT_STYLE_INHERIT: + style = style->parent_style; + break; + case FONT_STYLE_NORMAL: + return POSTURE_NORMAL; + case FONT_STYLE_ITALIC: + case FONT_STYLE_OBLIQUE: + return POSTURE_ITALIC; + default: + abort (); + } + } +} + +static term_underline_t +style_compute_text_underline_value (const CRXStyle *style) +{ + for (;;) + { + if (style == NULL) + return UNDERLINE_DEFAULT; + switch (style->text_decoration) + { + case TEXT_DECORATION_INHERIT: + style = style->parent_style; + break; + case TEXT_DECORATION_NONE: + case TEXT_DECORATION_OVERLINE: + case TEXT_DECORATION_LINE_THROUGH: + case TEXT_DECORATION_BLINK: + return UNDERLINE_OFF; + case TEXT_DECORATION_UNDERLINE: + return UNDERLINE_ON; + default: + abort (); + } + } +} + +/* Match the current list of CSS classes to the CSS and return the result. */ +static attributes_t * +match (term_styled_ostream_t stream) +{ + xmlNodePtr root; + xmlNodePtr curr; + char *p_end; + char *p_start; + CRXStyle *curr_style; + CRStyle *curr_style_base; + attributes_t *attr; + + /* Create a hierarchy of XML nodes. */ + root = xmlNewNode (NULL, (const xmlChar *) "__root__"); + root->type = XML_ELEMENT_NODE; + curr = root; + p_end = &stream->curr_classes[stream->curr_classes_length]; + p_start = stream->curr_classes; + while (p_start < p_end) + { + char *p; + xmlNodePtr child; + + if (!(*p_start == ' ')) + abort (); + p_start++; + for (p = p_start; p < p_end && *p != ' '; p++) + ; + + /* Temporarily replace the ' ' by '\0'. */ + *p = '\0'; + child = xmlNewNode (NULL, (const xmlChar *) p_start); + child->type = XML_ELEMENT_NODE; + xmlSetProp (child, (const xmlChar *) "class", (const xmlChar *) p_start); + *p = ' '; + + if (xmlAddChild (curr, child) == NULL) + /* Error! Shouldn't happen. */ + abort (); + + curr = child; + p_start = p; + } + + /* Retrieve the matching CSS declarations. */ + /* Not curr_style = crx_style_new (TRUE); because that assumes that the + default foreground color is black and that the default background color + is white, which is not necessarily true in a terminal context. */ + curr_style = NULL; + for (curr = root; curr != NULL; curr = curr->children) + { + CRXStyle *parent_style = curr_style; + curr_style = NULL; + + if (crx_sel_eng_get_matched_style (stream->css_engine, + stream->css_document, + curr, + parent_style, &curr_style, + FALSE) != CR_OK) + abort (); + if (curr_style == NULL) + /* No declarations matched this node. Inherit all values. */ + curr_style = parent_style; + else + /* curr_style is a new style, inheriting from parent_style. */ + ; + } + curr_style_base = (curr_style != NULL ? curr_style->base : NULL); + + /* Extract the CSS declarations that we can use. */ + attr = XMALLOC (attributes_t); + attr->color = + style_compute_color_value (curr_style_base, RGB_PROP_COLOR, + stream->destination); + attr->bgcolor = + style_compute_color_value (curr_style_base, RGB_PROP_BACKGROUND_COLOR, + stream->destination); + attr->weight = style_compute_font_weight_value (curr_style_base); + attr->posture = style_compute_font_posture_value (curr_style_base); + attr->underline = style_compute_text_underline_value (curr_style); + + /* Free the style chain. */ + while (curr_style != NULL) + { + CRXStyle *parent_style = curr_style->parent_style; + + crx_style_destroy (curr_style); + curr_style = parent_style; + } + + /* Free the XML nodes. */ + xmlFreeNodeList (root); + + return attr; +} + +/* Match the current list of CSS classes to the CSS and store the result in + stream->curr_attr and in the cache. */ +static void +match_and_cache (term_styled_ostream_t stream) +{ + attributes_t *attr = match (stream); + if (hash_insert_entry (&stream->cache, + stream->curr_classes, stream->curr_classes_length, + attr) == NULL) + abort (); + stream->curr_attr = attr; +} + +static void +term_styled_ostream::begin_use_class (term_styled_ostream_t stream, + const char *classname) +{ + size_t classname_len; + char *p; + void *found; + + if (classname[0] == '\0' || strchr (classname, ' ') != NULL) + /* Invalid classname argument. */ + abort (); + + /* Push the classname onto the classname list. */ + classname_len = strlen (classname); + if (stream->curr_classes_length + 1 + classname_len + 1 + > stream->curr_classes_allocated) + { + size_t new_allocated = stream->curr_classes_length + 1 + classname_len + 1; + if (new_allocated < 2 * stream->curr_classes_allocated) + new_allocated = 2 * stream->curr_classes_allocated; + + stream->curr_classes = xrealloc (stream->curr_classes, new_allocated); + stream->curr_classes_allocated = new_allocated; + } + p = &stream->curr_classes[stream->curr_classes_length]; + *p++ = ' '; + memcpy (p, classname, classname_len); + stream->curr_classes_length += 1 + classname_len; + + /* Uodate stream->curr_attr. */ + if (hash_find_entry (&stream->cache, + stream->curr_classes, stream->curr_classes_length, + &found) < 0) + match_and_cache (stream); + else + stream->curr_attr = (attributes_t *) found; +} + +static void +term_styled_ostream::end_use_class (term_styled_ostream_t stream, + const char *classname) +{ + char *p_end; + char *p_start; + char *p; + void *found; + + if (stream->curr_classes_length == 0) + /* No matching call to begin_use_class. */ + abort (); + + /* Remove the trailing classname. */ + p_end = &stream->curr_classes[stream->curr_classes_length]; + p = p_end; + while (*--p != ' ') + ; + p_start = p + 1; + if (!(p_end - p_start == strlen (classname) + && memcmp (p_start, classname, p_end - p_start) == 0)) + /* The match ing call to begin_use_class used a different classname. */ + abort (); + stream->curr_classes_length = p - stream->curr_classes; + + /* Update stream->curr_attr. */ + if (hash_find_entry (&stream->cache, + stream->curr_classes, stream->curr_classes_length, + &found) < 0) + abort (); + stream->curr_attr = (attributes_t *) found; +} + +/* Constructor. */ + +term_styled_ostream_t +term_styled_ostream_create (int fd, const char *filename, + const char *css_filename) +{ + term_styled_ostream_t stream = + XMALLOC (struct term_styled_ostream_representation); + CRStyleSheet *css_file_contents; + + stream->base.base.vtable = &term_styled_ostream_vtable; + stream->destination = term_ostream_create (fd, filename); + + if (cr_om_parser_simply_parse_file ((const guchar *) css_filename, + CR_UTF_8, /* CR_AUTO is not supported */ + &css_file_contents) != CR_OK) + { + term_ostream_free (stream->destination); + free (stream); + return NULL; + } + stream->css_document = cr_cascade_new (NULL, css_file_contents, NULL); + stream->css_engine = cr_sel_eng_new (); + + stream->curr_classes_allocated = 60; + stream->curr_classes = XNMALLOC (stream->curr_classes_allocated, char); + stream->curr_classes_length = 0; + + hash_init (&stream->cache, 10); + + match_and_cache (stream); + + return stream; +} diff --git a/gettext-tools/gnulib-lib/term-styled-ostream.oo.h b/gettext-tools/gnulib-lib/term-styled-ostream.oo.h new file mode 100644 index 0000000..b890e3d --- /dev/null +++ b/gettext-tools/gnulib-lib/term-styled-ostream.oo.h @@ -0,0 +1,49 @@ +/* Output stream for CSS styled text, producing ANSI escape sequences. + Copyright (C) 2006 Free Software Foundation, Inc. + Written by Bruno Haible , 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _TERM_STYLED_OSTREAM_H +#define _TERM_STYLED_OSTREAM_H + +#include "styled-ostream.h" + + +struct term_styled_ostream : struct styled_ostream +{ +methods: +}; + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Create an output stream referring to the file descriptor FD, styled with + the file CSS_FILENAME. + FILENAME is used only for error messages. + Note that the resulting stream must be closed before FD can be closed. + Return NULL upon failure. */ +extern term_styled_ostream_t + term_styled_ostream_create (int fd, const char *filename, + const char *css_filename); + + +#ifdef __cplusplus +} +#endif + +#endif /* _TERM_STYLED_OSTREAM_H */ diff --git a/gettext-tools/gnulib-lib/term_ostream.priv.h b/gettext-tools/gnulib-lib/term_ostream.priv.h new file mode 100644 index 0000000..21a70e1 --- /dev/null +++ b/gettext-tools/gnulib-lib/term_ostream.priv.h @@ -0,0 +1,42 @@ +/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ + +/* Field layout of superclass. */ +#include "ostream.priv.h" + +/* Field layout of term_ostream class. */ +struct term_ostream_representation +{ + struct ostream_representation base; + + int fd; + char *filename; + + + int max_colors; + int no_color_video; + char *set_a_foreground; + char *set_foreground; + char *set_a_background; + char *set_background; + char *orig_pair; + char *enter_bold_mode; + char *enter_italics_mode; + char *exit_italics_mode; + char *enter_underline_mode; + char *exit_underline_mode; + char *exit_attribute_mode; + + bool supports_foreground; + bool supports_background; + colormodel_t colormodel; + bool supports_weight; + bool supports_posture; + bool supports_underline; + + char *buffer; + attributes_t *attrbuffer; + size_t buflen; + size_t allocated; + attributes_t curr_attr; + attributes_t simp_attr; +}; diff --git a/gettext-tools/gnulib-lib/term_ostream.vt.h b/gettext-tools/gnulib-lib/term_ostream.vt.h new file mode 100644 index 0000000..ba84486 --- /dev/null +++ b/gettext-tools/gnulib-lib/term_ostream.vt.h @@ -0,0 +1,17 @@ +/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ + +/* Virtual function table layout of superclass. */ +#include "ostream.vt.h" + +/* Virtual function table layout of term_ostream class. */ + term_color_t (*rgb_to_color) (THIS_ARG, int red, int green, int blue); + term_color_t (*get_color) (THIS_ARG); + void (*set_color) (THIS_ARG, term_color_t color); + term_color_t (*get_bgcolor) (THIS_ARG); + void (*set_bgcolor) (THIS_ARG, term_color_t color); + term_weight_t (*get_weight) (THIS_ARG); + void (*set_weight) (THIS_ARG, term_weight_t weight); + term_posture_t (*get_posture) (THIS_ARG); + void (*set_posture) (THIS_ARG, term_posture_t posture); + term_underline_t (*get_underline) (THIS_ARG); + void (*set_underline) (THIS_ARG, term_underline_t underline); diff --git a/gettext-tools/gnulib-lib/term_styled_ostream.priv.h b/gettext-tools/gnulib-lib/term_styled_ostream.priv.h new file mode 100644 index 0000000..9a954e5 --- /dev/null +++ b/gettext-tools/gnulib-lib/term_styled_ostream.priv.h @@ -0,0 +1,24 @@ +/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ + +/* Field layout of superclass. */ +#include "styled_ostream.priv.h" + +/* Field layout of term_styled_ostream class. */ +struct term_styled_ostream_representation +{ + struct styled_ostream_representation base; + + term_ostream_t destination; + + CRCascade *css_document; + + CRSelEng *css_engine; + + char *curr_classes; + size_t curr_classes_length; + size_t curr_classes_allocated; + + hash_table cache; + + attributes_t *curr_attr; +}; diff --git a/gettext-tools/gnulib-lib/term_styled_ostream.vt.h b/gettext-tools/gnulib-lib/term_styled_ostream.vt.h new file mode 100644 index 0000000..517193a --- /dev/null +++ b/gettext-tools/gnulib-lib/term_styled_ostream.vt.h @@ -0,0 +1,6 @@ +/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ + +/* Virtual function table layout of superclass. */ +#include "styled_ostream.vt.h" + +/* Virtual function table layout of term_styled_ostream class. */ diff --git a/gettext-tools/gnulib-lib/terminfo.h b/gettext-tools/gnulib-lib/terminfo.h new file mode 100644 index 0000000..320aede --- /dev/null +++ b/gettext-tools/gnulib-lib/terminfo.h @@ -0,0 +1,114 @@ +/* Information about terminal capabilities. + Copyright (C) 2006 Free Software Foundation, Inc. + Written by Bruno Haible , 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _TERMINFO_H +#define _TERMINFO_H + +/* Including or is dangerous, because it also declares + a lot of junk, such as variables PC, UP, and other. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if HAVE_TERMINFO + +/* Gets the capability information for terminal type TYPE and prepares FD. + Returns 0 if successful, -1 upon error. If ERRP is non-NULL, also returns + an error indicator in *ERRP; otherwise an error is signalled. */ +extern int setupterm (const char *type, int fd, int *errp); + +/* Retrieves the value of a numerical capability. + Returns -1 if it is not available, -2 if ID is invalid. */ +extern int tigetnum (const char *id); + +/* Retrieves the value of a boolean capability. + Returns 1 if it available, 0 if not available, -1 if ID is invalid. */ +extern int tigetflag (const char *id); + +/* Retrieves the value of a string capability. + Returns NULL if it is not available, (char *)(-1) if ID is invalid. */ +extern const char * tigetstr (const char *id); + +#elif HAVE_TERMCAP + +/* Gets the capability information for terminal type TYPE. + Returns 1 if successful, 0 if TYPE is unknown, -1 on other error. */ +extern int tgetent (char *bp, const char *type); + +/* Retrieves the value of a numerical capability. + Returns -1 if it is not available. */ +extern int tgetnum (const char *id); + +/* Retrieves the value of a boolean capability. + Returns 1 if it available, 0 otherwise. */ +extern int tgetflag (const char *id); + +/* Retrieves the value of a string capability. + Returns NULL if it is not available. + Also, if AREA != NULL, stores it at *AREA and advances *AREA. */ +extern const char * tgetstr (const char *id, char **area); + +#endif + +#if HAVE_TPARAM + +/* API provided by GNU termcap in . */ + +/* Instantiates a string capability with format strings. + BUF must be a buffer having room for BUFSIZE bytes. + The return value is either equal to BUF or freshly malloc()ed. */ +extern char * tparam (const char *str, void *buf, int bufsize, ...); + +#else + +/* API provided by + - GNU ncurses in , , , + - OSF/1 curses in , , + - Solaris, AIX, HP-UX, IRIX curses in , + - gnulib's replacement. */ + +/* Instantiates a string capability with format strings. + The return value is statically allocated and must not be freed. */ +extern char * tparm (const char *str, ...); + +#endif + +#if HAVE_TERMINFO || HAVE_TERMCAP + +/* Retrieves a string that causes cursor positioning to (column, row). + This function is necessary because the string returned by tgetstr ("cm") + is in a special format. */ +extern const char * tgoto (const char *cm, int column, int row); + +#endif + +/* Retrieves the value of a string capability. + OUTCHARFUN is called in turn for each 'char' of the result. + This function is necessary because string capabilities can contain + padding commands. */ +extern void tputs (const char *cp, int affcnt, int (*outcharfun) (int)); + +/* The ncurses functions for color handling (see ncurses/base/lib_color.c) + are overkill: Most terminal emulators support only a fixed, small number + of colors. */ + +#ifdef __cplusplus +} +#endif + +#endif /* _TERMINFO_H */ diff --git a/gettext-tools/gnulib-lib/time.in.h b/gettext-tools/gnulib-lib/time.in.h new file mode 100644 index 0000000..81abdf4 --- /dev/null +++ b/gettext-tools/gnulib-lib/time.in.h @@ -0,0 +1,274 @@ +/* A more-standard . + + Copyright (C) 2007-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . */ + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +/* Don't get in the way of glibc when it includes time.h merely to + declare a few standard symbols, rather than to declare all the + symbols. Also, Solaris 8 eventually includes itself + recursively; if that is happening, just include the system + without adding our own declarations. */ +#if (defined __need_time_t || defined __need_clock_t \ + || defined __need_timespec \ + || defined _@GUARD_PREFIX@_TIME_H) + +# @INCLUDE_NEXT@ @NEXT_TIME_H@ + +#else + +# define _@GUARD_PREFIX@_TIME_H + +# @INCLUDE_NEXT@ @NEXT_TIME_H@ + +/* NetBSD 5.0 mis-defines NULL. */ +# include + +/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ + +/* The definition of _GL_ARG_NONNULL is copied here. */ + +/* The definition of _GL_WARN_ON_USE is copied here. */ + +/* Some systems don't define struct timespec (e.g., AIX 4.1, Ultrix 4.3). + Or they define it with the wrong member names or define it in + (e.g., FreeBSD circa 1997). Stock Mingw prior to 3.0 does not define it, + but the pthreads-win32 library defines it in . */ +# if ! @TIME_H_DEFINES_STRUCT_TIMESPEC@ +# if @SYS_TIME_H_DEFINES_STRUCT_TIMESPEC@ +# include +# elif @PTHREAD_H_DEFINES_STRUCT_TIMESPEC@ +# include +# else + +# ifdef __cplusplus +extern "C" { +# endif + +# if !GNULIB_defined_struct_timespec +# undef timespec +# define timespec rpl_timespec +struct timespec +{ + time_t tv_sec; + long int tv_nsec; +}; +# define GNULIB_defined_struct_timespec 1 +# endif + +# ifdef __cplusplus +} +# endif + +# endif +# endif + +# if !GNULIB_defined_struct_time_t_must_be_integral +/* Per http://austingroupbugs.net/view.php?id=327, POSIX requires + time_t to be an integer type, even though C99 permits floating + point. We don't know of any implementation that uses floating + point, and it is much easier to write code that doesn't have to + worry about that corner case, so we force the issue. */ +struct __time_t_must_be_integral { + unsigned int __floating_time_t_unsupported : (time_t) 1; +}; +# define GNULIB_defined_struct_time_t_must_be_integral 1 +# endif + +/* Sleep for at least RQTP seconds unless interrupted, If interrupted, + return -1 and store the remaining time into RMTP. See + . */ +# if @GNULIB_NANOSLEEP@ +# if @REPLACE_NANOSLEEP@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define nanosleep rpl_nanosleep +# endif +_GL_FUNCDECL_RPL (nanosleep, int, + (struct timespec const *__rqtp, struct timespec *__rmtp) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (nanosleep, int, + (struct timespec const *__rqtp, struct timespec *__rmtp)); +# else +# if ! @HAVE_NANOSLEEP@ +_GL_FUNCDECL_SYS (nanosleep, int, + (struct timespec const *__rqtp, struct timespec *__rmtp) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (nanosleep, int, + (struct timespec const *__rqtp, struct timespec *__rmtp)); +# endif +_GL_CXXALIASWARN (nanosleep); +# endif + +/* Return the 'time_t' representation of TP and normalize TP. */ +# if @GNULIB_MKTIME@ +# if @REPLACE_MKTIME@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define mktime rpl_mktime +# endif +_GL_FUNCDECL_RPL (mktime, time_t, (struct tm *__tp) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (mktime, time_t, (struct tm *__tp)); +# else +_GL_CXXALIAS_SYS (mktime, time_t, (struct tm *__tp)); +# endif +_GL_CXXALIASWARN (mktime); +# endif + +/* Convert TIMER to RESULT, assuming local time and UTC respectively. See + and + . */ +# if @GNULIB_TIME_R@ +# if @REPLACE_LOCALTIME_R@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef localtime_r +# define localtime_r rpl_localtime_r +# endif +_GL_FUNCDECL_RPL (localtime_r, struct tm *, (time_t const *restrict __timer, + struct tm *restrict __result) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (localtime_r, struct tm *, (time_t const *restrict __timer, + struct tm *restrict __result)); +# else +# if ! @HAVE_DECL_LOCALTIME_R@ +_GL_FUNCDECL_SYS (localtime_r, struct tm *, (time_t const *restrict __timer, + struct tm *restrict __result) + _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (localtime_r, struct tm *, (time_t const *restrict __timer, + struct tm *restrict __result)); +# endif +# if @HAVE_DECL_LOCALTIME_R@ +_GL_CXXALIASWARN (localtime_r); +# endif +# if @REPLACE_LOCALTIME_R@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef gmtime_r +# define gmtime_r rpl_gmtime_r +# endif +_GL_FUNCDECL_RPL (gmtime_r, struct tm *, (time_t const *restrict __timer, + struct tm *restrict __result) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (gmtime_r, struct tm *, (time_t const *restrict __timer, + struct tm *restrict __result)); +# else +# if ! @HAVE_DECL_LOCALTIME_R@ +_GL_FUNCDECL_SYS (gmtime_r, struct tm *, (time_t const *restrict __timer, + struct tm *restrict __result) + _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (gmtime_r, struct tm *, (time_t const *restrict __timer, + struct tm *restrict __result)); +# endif +# if @HAVE_DECL_LOCALTIME_R@ +_GL_CXXALIASWARN (gmtime_r); +# endif +# endif + +/* Convert TIMER to RESULT, assuming local time and UTC respectively. See + and + . */ +# if @GNULIB_GETTIMEOFDAY@ +# if @REPLACE_LOCALTIME@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef localtime +# define localtime rpl_localtime +# endif +_GL_FUNCDECL_RPL (localtime, struct tm *, (time_t const *__timer) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (localtime, struct tm *, (time_t const *__timer)); +# else +_GL_CXXALIAS_SYS (localtime, struct tm *, (time_t const *__timer)); +# endif +_GL_CXXALIASWARN (localtime); +# endif + +# if @GNULIB_GETTIMEOFDAY@ +# if @REPLACE_GMTIME@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef gmtime +# define gmtime rpl_gmtime +# endif +_GL_FUNCDECL_RPL (gmtime, struct tm *, (time_t const *__timer) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (gmtime, struct tm *, (time_t const *__timer)); +# else +_GL_CXXALIAS_SYS (gmtime, struct tm *, (time_t const *__timer)); +# endif +_GL_CXXALIASWARN (gmtime); +# endif + +/* Parse BUF as a time stamp, assuming FORMAT specifies its layout, and store + the resulting broken-down time into TM. See + . */ +# if @GNULIB_STRPTIME@ +# if ! @HAVE_STRPTIME@ +_GL_FUNCDECL_SYS (strptime, char *, (char const *restrict __buf, + char const *restrict __format, + struct tm *restrict __tm) + _GL_ARG_NONNULL ((1, 2, 3))); +# endif +_GL_CXXALIAS_SYS (strptime, char *, (char const *restrict __buf, + char const *restrict __format, + struct tm *restrict __tm)); +_GL_CXXALIASWARN (strptime); +# endif + +/* Convert TM to a time_t value, assuming UTC. */ +# if @GNULIB_TIMEGM@ +# if @REPLACE_TIMEGM@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef timegm +# define timegm rpl_timegm +# endif +_GL_FUNCDECL_RPL (timegm, time_t, (struct tm *__tm) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (timegm, time_t, (struct tm *__tm)); +# else +# if ! @HAVE_TIMEGM@ +_GL_FUNCDECL_SYS (timegm, time_t, (struct tm *__tm) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (timegm, time_t, (struct tm *__tm)); +# endif +_GL_CXXALIASWARN (timegm); +# endif + +/* Encourage applications to avoid unsafe functions that can overrun + buffers when given outlandish struct tm values. Portable + applications should use strftime (or even sprintf) instead. */ +# if defined GNULIB_POSIXCHECK +# undef asctime +_GL_WARN_ON_USE (asctime, "asctime can overrun buffers in some cases - " + "better use strftime (or even sprintf) instead"); +# endif +# if defined GNULIB_POSIXCHECK +# undef asctime_r +_GL_WARN_ON_USE (asctime, "asctime_r can overrun buffers in some cases - " + "better use strftime (or even sprintf) instead"); +# endif +# if defined GNULIB_POSIXCHECK +# undef ctime +_GL_WARN_ON_USE (asctime, "ctime can overrun buffers in some cases - " + "better use strftime (or even sprintf) instead"); +# endif +# if defined GNULIB_POSIXCHECK +# undef ctime_r +_GL_WARN_ON_USE (asctime, "ctime_r can overrun buffers in some cases - " + "better use strftime (or even sprintf) instead"); +# endif + +#endif diff --git a/gettext-tools/gnulib-lib/tmpdir.c b/gettext-tools/gnulib-lib/tmpdir.c new file mode 100644 index 0000000..e68dcef --- /dev/null +++ b/gettext-tools/gnulib-lib/tmpdir.c @@ -0,0 +1,159 @@ +/* Copyright (C) 1999, 2001-2002, 2006, 2009-2014 Free Software Foundation, + Inc. + This file is part of the GNU C Library. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Extracted from sysdeps/posix/tempname.c. */ + +#include + +/* Specification. */ +#include "tmpdir.h" + +#include +#include +#include + +#include +#ifndef __set_errno +# define __set_errno(Val) errno = (Val) +#endif + +#include +#ifndef P_tmpdir +# ifdef _P_tmpdir /* native Windows */ +# define P_tmpdir _P_tmpdir +# else +# define P_tmpdir "/tmp" +# endif +#endif + +#include + +#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ +# define WIN32_LEAN_AND_MEAN /* avoid including junk */ +# include +#endif + +#include "pathmax.h" + +#if _LIBC +# define struct_stat64 struct stat64 +#else +# define struct_stat64 struct stat +# define __libc_secure_getenv secure_getenv +# define __xstat64(version, path, buf) stat (path, buf) +#endif + +/* Pathname support. + ISSLASH(C) tests whether C is a directory separator character. + */ +#if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__ + /* Native Windows, Cygwin, OS/2, DOS */ +# define ISSLASH(C) ((C) == '/' || (C) == '\\') +#else + /* Unix */ +# define ISSLASH(C) ((C) == '/') +#endif + + +/* Return nonzero if DIR is an existent directory. */ +static bool +direxists (const char *dir) +{ + struct_stat64 buf; + return __xstat64 (_STAT_VER, dir, &buf) == 0 && S_ISDIR (buf.st_mode); +} + +/* Path search algorithm, for tmpnam, tmpfile, etc. If DIR is + non-null and exists, uses it; otherwise uses the first of $TMPDIR, + P_tmpdir, /tmp that exists. Copies into TMPL a template suitable + for use with mk[s]temp. Will fail (-1) if DIR is non-null and + doesn't exist, none of the searched dirs exists, or there's not + enough space in TMPL. */ +int +path_search (char *tmpl, size_t tmpl_len, const char *dir, const char *pfx, + bool try_tmpdir) +{ + const char *d; + size_t dlen, plen; + bool add_slash; + + if (!pfx || !pfx[0]) + { + pfx = "file"; + plen = 4; + } + else + { + plen = strlen (pfx); + if (plen > 5) + plen = 5; + } + + if (try_tmpdir) + { + d = __libc_secure_getenv ("TMPDIR"); + if (d != NULL && direxists (d)) + dir = d; + else if (dir != NULL && direxists (dir)) + /* nothing */ ; + else + dir = NULL; + } + if (dir == NULL) + { +#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ + char dirbuf[PATH_MAX]; + DWORD retval; + + /* Find Windows temporary file directory. + We try this before P_tmpdir because Windows defines P_tmpdir to "\\" + and will therefore try to put all temporary files in the root + directory (unless $TMPDIR is set). */ + retval = GetTempPath (PATH_MAX, dirbuf); + if (retval > 0 && retval < PATH_MAX && direxists (dirbuf)) + dir = dirbuf; + else +#endif + if (direxists (P_tmpdir)) + dir = P_tmpdir; + else if (strcmp (P_tmpdir, "/tmp") != 0 && direxists ("/tmp")) + dir = "/tmp"; + else + { + __set_errno (ENOENT); + return -1; + } + } + + dlen = strlen (dir); +#ifdef __VMS + add_slash = 0; +#else + add_slash = dlen != 0 && !ISSLASH (dir[dlen - 1]); +#endif + + /* check we have room for "${dir}/${pfx}XXXXXX\0" */ + if (tmpl_len < dlen + add_slash + plen + 6 + 1) + { + __set_errno (EINVAL); + return -1; + } + + memcpy (tmpl, dir, dlen); + sprintf (tmpl + dlen, &"/%.*sXXXXXX"[!add_slash], (int) plen, pfx); + return 0; +} diff --git a/gettext-tools/gnulib-lib/tmpdir.h b/gettext-tools/gnulib-lib/tmpdir.h new file mode 100644 index 0000000..b7a644a --- /dev/null +++ b/gettext-tools/gnulib-lib/tmpdir.h @@ -0,0 +1,26 @@ +/* Determine a temporary directory. + Copyright (C) 2001-2002, 2009-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include +#include + +/* Path search algorithm, for tmpnam, tmpfile, etc. If DIR is + non-null and exists, uses it; otherwise uses the first of $TMPDIR, + P_tmpdir, /tmp that exists. Copies into TMPL a template suitable + for use with mk[s]temp. Will fail (-1) if DIR is non-null and + doesn't exist, none of the searched dirs exists, or there's not + enough space in TMPL. */ +extern int path_search (char *tmpl, size_t tmpl_len, const char *dir, const char *pfx, bool try_tmpdir); diff --git a/gettext-tools/gnulib-lib/tparm.c b/gettext-tools/gnulib-lib/tparm.c new file mode 100644 index 0000000..878ea8d --- /dev/null +++ b/gettext-tools/gnulib-lib/tparm.c @@ -0,0 +1,896 @@ +/* Substitution of parameters in strings from terminal descriptions. + Copyright (C) 2006, 2012 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Originally by Ross Ridge, Public Domain, 92/02/01 07:30:36 */ + +#include + +#include +#include +#include + +#include "c-ctype.h" + +#ifdef USE_SCCS_IDS +static const char SCCSid[] = "@(#) mytinfo tparm.c 3.2 92/02/01 public domain, By Ross Ridge"; +#endif + +#ifndef MAX_PUSHED +#define MAX_PUSHED 32 +#endif + +#define ARG 1 +#define NUM 2 + +#define INTEGER 1 +#define STRING 2 + +#define MAX_LINE 640 + +typedef struct stack_str +{ + int type; + int argnum; + int value; +} stack; + +static stack S[MAX_PUSHED]; +static stack vars['z'-'a'+1]; +static int pos = 0; + +static +struct arg_str +{ + int type; + int integer; + char *string; +} arg_list[10]; + +static int argcnt; + +static va_list tparm_args; + +static int +pusharg (int arg) +{ + if (pos == MAX_PUSHED) + return 1; + S[pos].type = ARG; + S[pos++].argnum = arg; + return 0; +} + +static int +pushnum (int num) +{ + if (pos == MAX_PUSHED) + return 1; + S[pos].type = NUM; + S[pos++].value = num; + return 0; +} + +static int +getarg (int argnum, int type, void *p) +{ + while (argcnt < argnum) + { + arg_list[argcnt].type = INTEGER; + arg_list[argcnt++].integer = (int) va_arg (tparm_args, int); + } + if (argcnt > argnum) + { + if (arg_list[argnum].type != type) + return 1; + else if (type == STRING) + *(char **)p = arg_list[argnum].string; + else + *(int *)p = arg_list[argnum].integer; + } + else + { + arg_list[argcnt].type = type; + if (type == STRING) + *(char **)p = arg_list[argcnt++].string = (char *) va_arg (tparm_args, char *); + else + *(int *)p = arg_list[argcnt++].integer = (int) va_arg (tparm_args, int); + } + return 0; +} + +static int +popstring (char **str) +{ + if (pos-- == 0) + return 1; + if (S[pos].type != ARG) + return 1; + return getarg (S[pos].argnum, STRING, str); +} + +static int +popnum (int *num) +{ + if (pos-- == 0) + return 1; + switch (S[pos].type) + { + case ARG: + return getarg (S[pos].argnum, INTEGER, num); + case NUM: + *num = S[pos].value; + return 0; + } + return 1; +} + +static int +cvtchar (const char *sp, char *c) +{ + switch (*sp) + { + case '\\': + switch (*++sp) + { + case '\'': + case '$': + case '\\': + case '%': + *c = *sp; + return 2; + case '\0': + *c = '\\'; + return 1; + case '0': + if (sp[1] == '0' && sp[2] == '0') + { + *c = '\0'; + return 4; + } + *c = '\200'; /* '\0' ???? */ + return 2; + default: + *c = *sp; + return 2; + } + default: + *c = *sp; + return 1; + } +} + +/* sigh... this has got to be the ugliest code I've ever written. + Trying to handle everything has its cost, I guess. + + It actually isn't to hard to figure out if a given % code is supposed + to be interpeted with its termcap or terminfo meaning since almost + all terminfo codes are invalid unless something has been pushed on + the stack and termcap strings will never push things on the stack + (%p isn't used by termcap). So where we have a choice we make the + decision by wether or not somthing has been pushed on the stack. + The static variable termcap keeps track of this; it starts out set + to 1 and is incremented as each argument processed by a termcap % code, + however if something is pushed on the stack it's set to 0 and the + rest of the % codes are interpeted as terminfo % codes. Another way + of putting it is that if termcap equals one we haven't decided either + way yet, if it equals zero we're looking for terminfo codes, and if + its greater than 1 we're looking for termcap codes. + + Terminfo % codes: + + %% output a '%' + %[[:][-+# ][width][.precision]][doxXs] + output pop according to the printf format + %c output pop as a char + %'c' push character constant c. + %{n} push decimal constant n. + %p[1-9] push paramter [1-9] + %g[a-z] push variable [a-z] + %P[a-z] put pop in variable [a-z] + %l push the length of pop (a string) + %+ add pop to pop and push the result + %- subtract pop from pop and push the result + %* multiply pop and pop and push the result + %& bitwise and pop and pop and push the result + %| bitwise or pop and pop and push the result + %^ bitwise xor pop and pop and push the result + %~ push the bitwise not of pop + %= compare if pop and pop are equal and push the result + %> compare if pop is less than pop and push the result + %< compare if pop is greater than pop and push the result + %A logical and pop and pop and push the result + %O logical or pop and pop and push the result + %! push the logical not of pop + %? condition %t if_true [%e if_false] %; + if condtion evaulates as true then evaluate if_true, + else evaluate if_false. elseif's can be done: + %? cond %t true [%e cond2 %t true2] ... [%e condN %t trueN] [%e false] %; + %i add one to parameters 1 and 2. (ANSI) + + Termcap Codes: + + %% output a % + %. output parameter as a character + %d output parameter as a decimal number + %2 output parameter in printf format %02d + %3 output parameter in printf format %03d + %+x add the character x to parameter and output it as a character +(UW) %-x subtract parameter FROM the character x and output it as a char +(UW) %ax add the character x to parameter +(GNU) %a[+*-/=][cp]x + GNU arithmetic. +(UW) %sx subtract parameter FROM the character x + %>xy if parameter > character x then add character y to parameter + %B convert to BCD (parameter = (parameter/10)*16 + parameter%16) + %D Delta Data encode (parameter = parameter - 2*(paramter%16)) + %i increment the first two parameters by one + %n xor the first two parameters by 0140 +(GNU) %m xor the first two parameters by 0177 + %r swap the first two parameters +(GNU) %b backup to previous parameter +(GNU) %f skip this parameter + + Note the two definitions of %a, the GNU definition is used if the characters + after the 'a' are valid, otherwise the UW definition is used. + + (GNU) used by GNU Emacs termcap libraries + (UW) used by the University of Waterloo (MFCF) termcap libraries + +*/ + +char * +tparm (const char *str, ...) +{ + static int termcap; + static char OOPS[] = "OOPS"; + static char buf[MAX_LINE]; + const char *sp; + char *dp; + char *fmt; + char scan_for; + int scan_depth; + int if_depth; + char fmt_buf[MAX_LINE]; + char sbuf[MAX_LINE]; + + va_start (tparm_args, str); + + sp = str; + dp = buf; + scan_for = 0; + scan_depth = 0; + if_depth = 0; + argcnt = 0; + pos = 0; + termcap = 1; + while (*sp != '\0') + { + switch (*sp) + { + case '\\': + if (scan_for) + { + if (*++sp != '\0') + sp++; + break; + } + *dp++ = *sp++; + if (*sp != '\0') + *dp++ = *sp++; + break; + case '%': + sp++; + if (scan_for) + { + if (*sp == scan_for && if_depth == scan_depth) + { + if (scan_for == ';') + if_depth--; + scan_for = 0; + } + else if (*sp == '?') + if_depth++; + else if (*sp == ';') + { + if (if_depth == 0) + return OOPS; + else + if_depth--; + } + sp++; + break; + } + fmt = NULL; + switch (*sp) + { + case '%': + *dp++ = *sp++; + break; + case '+': + if (!termcap) + { + int i, j; + if (popnum (&j) || popnum (&i)) + return OOPS; + i += j; + if (pushnum (i)) + return OOPS; + sp++; + break; + } + /* FALLTHROUGH */ + case 'C': + if (*sp == 'C') + { + int i; + if (getarg (termcap - 1, INTEGER, &i)) + return OOPS; + if (i >= 96) + { + i /= 96; + if (i == '$') + *dp++ = '\\'; + *dp++ = i; + } + } + fmt = "%c"; + /* FALLTHROUGH */ + case 'a': + if (!termcap) + return OOPS; + { + int i; + if (getarg (termcap - 1, INTEGER, &i)) + return OOPS; + if (*++sp == '\0') + return OOPS; + if ((sp[1] == 'p' || sp[1] == 'c') + && sp[2] != '\0' && fmt == NULL) + { + /* GNU arithmetic parameter, what they really need is + terminfo. */ + int val; + int lc; + if (sp[1] == 'p' + && getarg (termcap - 1 + sp[2] - '@', INTEGER, &val)) + return OOPS; + if (sp[1] == 'c') + { + char c; + lc = cvtchar (sp + 2, &c) + 2; + /* Mask out 8th bit so \200 can be used for \0 as per + GNU docs. */ + val = c & 0177; + } + else + lc = 2; + switch (sp[0]) + { + case '=': + break; + case '+': + val = i + val; + break; + case '-': + val = i - val; + break; + case '*': + val = i * val; + break; + case '/': + val = i / val; + break; + default: + /* Not really GNU's %a after all... */ + { + char c; + lc = cvtchar (sp, &c); + val = c + i; + } + break; + } + arg_list[termcap - 1].integer = val; + sp += lc; + break; + } + { + char c; + sp += cvtchar (sp, &c); + arg_list[termcap - 1].integer = c + i; + } + } + if (fmt == NULL) + break; + sp--; + /* FALLTHROUGH */ + case '-': + if (!termcap) + { + int i, j; + if (popnum (&j) || popnum (&i)) + return OOPS; + i -= j; + if (pushnum (i)) + return OOPS; + sp++; + break; + } + fmt = "%c"; + /* FALLTHROUGH */ + case 's': + if (termcap && (fmt == NULL || *sp == '-')) + { + int i; + if (getarg (termcap - 1, INTEGER, &i)) + return OOPS; + if (*++sp == '\0') + return OOPS; + { + char c; + sp += cvtchar (sp, &c); + arg_list[termcap - 1].integer = c - i; + } + if (fmt == NULL) + break; + sp--; + } + if (!termcap) + return OOPS; + /* FALLTHROUGH */ + case '.': + if (termcap && fmt == NULL) + fmt = "%c"; + /* FALLTHROUGH */ + case 'd': + if (termcap && fmt == NULL) + fmt = "%d"; + /* FALLTHROUGH */ + case '2': + if (termcap && fmt == NULL) + fmt = "%02d"; + /* FALLTHROUGH */ + case '3': + if (termcap && fmt == NULL) + fmt = "%03d"; + /* FALLTHROUGH */ + case ':': case ' ': case '#': case 'u': + case 'x': case 'X': case 'o': case 'c': + case '0': case '1': case '4': case '5': + case '6': case '7': case '8': case '9': + if (fmt == NULL) + { + if (termcap) + return OOPS; + if (*sp == ':') + sp++; + fmt = fmt_buf; + *fmt++ = '%'; + while (*sp != 's' && *sp != 'x' && *sp != 'X' && *sp != 'd' + && *sp != 'o' && *sp != 'c' && *sp != 'u') + { + if (*sp == '\0') + return OOPS; + *fmt++ = *sp++; + } + *fmt++ = *sp; + *fmt = '\0'; + fmt = fmt_buf; + } + { + char conv_char = fmt[strlen (fmt) - 1]; + if (conv_char == 's') + { + char *s; + if (popstring (&s)) + return OOPS; + sprintf (sbuf, fmt, s); + } + else + { + int i; + if (termcap) + { + if (getarg (termcap++ - 1, INTEGER, &i)) + return OOPS; + } + else + if (popnum (&i)) + return OOPS; + if (i == 0 && conv_char == 'c') + strcpy (sbuf, "\000"); + else + sprintf (sbuf, fmt, i); + } + } + sp++; + fmt = sbuf; + while (*fmt != '\0') + { + if (*fmt == '$') + *dp++ = '\\'; + *dp++ = *fmt++; + } + break; + case 'r': + { + int i; + if (!termcap || getarg (1, INTEGER, &i)) + return OOPS; + arg_list[1].integer = arg_list[0].integer; + arg_list[0].integer = i; + } + sp++; + break; + case 'i': + { + int i; + if (getarg (1, INTEGER, &i) || arg_list[0].type != INTEGER) + return OOPS; + } + arg_list[1].integer++; + arg_list[0].integer++; + sp++; + break; + case 'n': + { + int i; + if (!termcap || getarg (1, INTEGER, &i)) + return OOPS; + } + arg_list[0].integer ^= 0140; + arg_list[1].integer ^= 0140; + sp++; + break; + case '>': + if (!termcap) + { + int i, j; + if (popnum (&j) || popnum (&i)) + return OOPS; + i = (i > j); + if (pushnum (i)) + return OOPS; + sp++; + break; + } + { + int i; + if (getarg (termcap-1, INTEGER, &i)) + return OOPS; + { + char c; + sp += cvtchar (sp, &c); + if (i > c) + { + sp += cvtchar (sp, &c); + arg_list[termcap-1].integer += c; + } + else + sp += cvtchar (sp, &c); + } + } + sp++; + break; + case 'B': + { + int i; + if (!termcap || getarg (termcap-1, INTEGER, &i)) + return OOPS; + arg_list[termcap-1].integer = 16 * (i / 10) + i % 10; + } + sp++; + break; + case 'D': + { + int i; + if (!termcap || getarg (termcap-1, INTEGER, &i)) + return OOPS; + arg_list[termcap-1].integer = i - 2 * (i % 16); + } + sp++; + break; + case 'p': + if (termcap > 1) + return OOPS; + if (*++sp == '\0') + return OOPS; + { + int i = (*sp == '0' ? 9 : *sp - '1'); + if (i < 0 || i > 9) + return OOPS; + if (pusharg (i)) + return OOPS; + } + termcap = 0; + sp++; + break; + case 'P': + if (termcap || *++sp == '\0') + return OOPS; + { + int i = *sp++ - 'a'; + if (i < 0 || i > 25) + return OOPS; + if (pos-- == 0) + return OOPS; + switch (vars[i].type = S[pos].type) + { + case ARG: + vars[i].argnum = S[pos].argnum; + break; + case NUM: + vars[i].value = S[pos].value; + break; + } + } + break; + case 'g': + if (termcap || *++sp == '\0') + return OOPS; + { + int i = *sp++ - 'a'; + if (i < 0 || i > 25) + return OOPS; + switch (vars[i].type) + { + case ARG: + if (pusharg (vars[i].argnum)) + return OOPS; + break; + case NUM: + if (pushnum (vars[i].value)) + return OOPS; + break; + } + } + break; + case '\'': + if (termcap > 1) + return OOPS; + if (*++sp == '\0') + return OOPS; + { + char c; + sp += cvtchar (sp, &c); + if (pushnum (c) || *sp++ != '\'') + return OOPS; + } + termcap = 0; + break; + case '{': + if (termcap > 1) + return OOPS; + { + int i; + i = 0; + sp++; + while (c_isdigit (*sp)) + i = 10 * i + *sp++ - '0'; + if (*sp++ != '}' || pushnum (i)) + return OOPS; + } + termcap = 0; + break; + case 'l': + { + int i; + char *s; + if (termcap || popstring (&s)) + return OOPS; + i = strlen (s); + if (pushnum (i)) + return OOPS; + } + sp++; + break; + case '*': + { + int i, j; + if (termcap || popnum (&j) || popnum (&i)) + return OOPS; + i *= j; + if (pushnum (i)) + return OOPS; + } + sp++; + break; + case '/': + { + int i, j; + if (termcap || popnum (&j) || popnum (&i)) + return OOPS; + i /= j; + if (pushnum (i)) + return OOPS; + } + sp++; + break; + case 'm': + if (termcap) + { + int i; + if (getarg (1, INTEGER, &i)) + return OOPS; + arg_list[0].integer ^= 0177; + arg_list[1].integer ^= 0177; + sp++; + break; + } + { + int i, j; + if (popnum (&j) || popnum (&i)) + return OOPS; + i %= j; + if (pushnum (i)) + return OOPS; + } + sp++; + break; + case '&': + { + int i, j; + if (popnum (&j) || popnum (&i)) + return OOPS; + i &= j; + if (pushnum (i)) + return OOPS; + } + sp++; + break; + case '|': + { + int i, j; + if (popnum (&j) || popnum (&i)) + return OOPS; + i |= j; + if (pushnum (i)) + return OOPS; + } + sp++; + break; + case '^': + { + int i, j; + if (popnum (&j) || popnum (&i)) + return OOPS; + i ^= j; + if (pushnum (i)) + return OOPS; + } + sp++; + break; + case '=': + { + int i, j; + if (popnum (&j) || popnum (&i)) + return OOPS; + i = (i == j); + if (pushnum (i)) + return OOPS; + } + sp++; + break; + case '<': + { + int i, j; + if (popnum (&j) || popnum (&i)) + return OOPS; + i = (i < j); + if (pushnum (i)) + return OOPS; + } + sp++; + break; + case 'A': + { + int i, j; + if (popnum (&j) || popnum (&i)) + return OOPS; + i = (i && j); + if (pushnum (i)) + return OOPS; + } + sp++; + break; + case 'O': + { + int i, j; + if (popnum (&j) || popnum (&i)) + return OOPS; + i = (i || j); + if (pushnum (i)) + return OOPS; + } + sp++; + break; + case '!': + { + int i; + if (popnum (&i)) + return OOPS; + i = !i; + if (pushnum (i)) + return OOPS; + } + sp++; + break; + case '~': + { + int i; + if (popnum (&i)) + return OOPS; + i = ~i; + if (pushnum (i)) + return OOPS; + } + sp++; + break; + case '?': + if (termcap > 1) + return OOPS; + termcap = 0; + if_depth++; + sp++; + break; + case 't': + { + int i; + if (popnum (&i) || if_depth == 0) + return OOPS; + if (!i) + { + scan_for = 'e'; + scan_depth = if_depth; + } + } + sp++; + break; + case 'e': + if (if_depth == 0) + return OOPS; + scan_for = ';'; + scan_depth = if_depth; + sp++; + break; + case ';': + if (if_depth-- == 0) + return OOPS; + sp++; + break; + case 'b': + if (--termcap < 1) + return OOPS; + sp++; + break; + case 'f': + if (!termcap++) + return OOPS; + sp++; + break; + } + break; + default: + if (scan_for) + sp++; + else + *dp++ = *sp++; + break; + } + } + va_end (tparm_args); + *dp = '\0'; + return buf; +} diff --git a/gettext-tools/gnulib-lib/tputs.c b/gettext-tools/gnulib-lib/tputs.c new file mode 100644 index 0000000..858b020 --- /dev/null +++ b/gettext-tools/gnulib-lib/tputs.c @@ -0,0 +1,41 @@ +/* Output of string from terminal descriptions. + Copyright (C) 2006 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification in termcap.h or terminfo.h. */ +extern +#ifdef __cplusplus +"C" +#endif +void tputs (const char *cp, int affcnt, int (*outcharfun) (int)); + +#include "c-ctype.h" + +void +tputs (const char *cp, int affcnt, int (*outcharfun) (int)) +{ + while (c_isdigit (*cp)) + cp++; + if (*cp == '.') + { + cp++; + while (c_isdigit (*cp)) + cp++; + } + for (; *cp != '\0'; cp++) + outcharfun (*cp); +} diff --git a/gettext-tools/gnulib-lib/trim.c b/gettext-tools/gnulib-lib/trim.c new file mode 100644 index 0000000..742de9b --- /dev/null +++ b/gettext-tools/gnulib-lib/trim.c @@ -0,0 +1,129 @@ +/* Removes leading and/or trailing whitespaces + Copyright (C) 2006-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Written by Davide Angelocola */ + +#include + +/* Specification. */ +#include "trim.h" + +#include +#include +#include +#include + +#include "mbchar.h" +#include "mbiter.h" +#include "xalloc.h" + +/* Use this to suppress gcc's "...may be used before initialized" warnings. */ +#ifdef lint +# define IF_LINT(Code) Code +#else +# define IF_LINT(Code) /* empty */ +#endif + +char * +trim2 (const char *s, int how) +{ + char *d; + + d = strdup (s); + + if (!d) + xalloc_die (); + + if (MB_CUR_MAX > 1) + { + mbi_iterator_t i; + + /* Trim leading whitespaces. */ + if (how != TRIM_TRAILING) + { + mbi_init (i, d, strlen (d)); + + for (; mbi_avail (i) && mb_isspace (mbi_cur (i)); mbi_advance (i)) + ; + + memmove (d, mbi_cur_ptr (i), strlen (mbi_cur_ptr (i)) + 1); + } + + /* Trim trailing whitespaces. */ + if (how != TRIM_LEADING) + { + unsigned int state = 0; + char *r IF_LINT (= NULL); /* used only while state = 2 */ + + mbi_init (i, d, strlen (d)); + + for (; mbi_avail (i); mbi_advance (i)) + { + if (state == 0 && mb_isspace (mbi_cur (i))) + continue; + + if (state == 0 && !mb_isspace (mbi_cur (i))) + { + state = 1; + continue; + } + + if (state == 1 && !mb_isspace (mbi_cur (i))) + continue; + + if (state == 1 && mb_isspace (mbi_cur (i))) + { + state = 2; + r = (char *) mbi_cur_ptr (i); + } + else if (state == 2 && mb_isspace (mbi_cur (i))) + { + /* empty */ + } + else + { + state = 1; + } + } + + if (state == 2) + *r = '\0'; + } + } + else + { + char *p; + + /* Trim leading whitespaces. */ + if (how != TRIM_TRAILING) + { + for (p = d; *p && isspace ((unsigned char) *p); p++) + ; + + memmove (d, p, strlen (p) + 1); + } + + /* Trim trailing whitespaces. */ + if (how != TRIM_LEADING) + { + for (p = d + strlen (d) - 1; + p >= d && isspace ((unsigned char) *p); p--) + *p = '\0'; + } + } + + return d; +} diff --git a/gettext-tools/gnulib-lib/trim.h b/gettext-tools/gnulib-lib/trim.h new file mode 100644 index 0000000..e4dc938 --- /dev/null +++ b/gettext-tools/gnulib-lib/trim.h @@ -0,0 +1,33 @@ +/* Removes leading and/or trailing whitespaces + Copyright (C) 2006, 2009-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Written by Davide Angelocola */ + +/* Trim mode. */ +#define TRIM_TRAILING 0 +#define TRIM_LEADING 1 +#define TRIM_BOTH 2 + +/* Removes trailing and leading whitespaces. */ +#define trim(s) trim2(s, TRIM_BOTH) + +/* Removes trailing whitespaces. */ +#define trim_trailing(s) trim2(s, TRIM_TRAILING) + +/* Removes leading whitespaces. */ +#define trim_leading(s) trim2(s, TRIM_LEADING) + +char *trim2 (const char *, int); diff --git a/gettext-tools/gnulib-lib/uniconv.in.h b/gettext-tools/gnulib-lib/uniconv.in.h new file mode 100644 index 0000000..4f44fc0 --- /dev/null +++ b/gettext-tools/gnulib-lib/uniconv.in.h @@ -0,0 +1,172 @@ +/* Conversions between Unicode and legacy encodings. + Copyright (C) 2002, 2005, 2007, 2009-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _UNICONV_H +#define _UNICONV_H + +/* Get size_t. */ +#include + +#include "unitypes.h" + +/* Get enum iconv_ilseq_handler. */ +#include "iconveh.h" + +/* Get uniconv_register_autodetect() declaration. */ +#include "striconveha.h" + +/* Get locale_charset() declaration. */ +#include "localcharset.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Converts an entire string, possibly including NUL bytes, from one encoding + to a Unicode encoding. + Converts a memory region given in encoding FROMCODE. FROMCODE is as for + iconv_open(3). + The input is in the memory region between SRC (inclusive) and SRC + SRCLEN + (exclusive). + If OFFSETS is not NULL, it should point to an array of SRCLEN integers; this + array is filled with offsets into the result, i.e. the character starting + at SRC[i] corresponds to the character starting at (*RESULTP)[OFFSETS[i]], + and other offsets are set to (size_t)(-1). + RESULTBUF and *LENGTHP should initially be a scratch buffer and its size, + or *RESULTBUF can be NULL. + May erase the contents of the memory at RESULTBUF. + If successful: The resulting Unicode string (non-NULL) is returned and its + length stored in *LENGTHP. The resulting string is RESULTBUF if no dynamic + memory allocation was necessary, or a freshly allocated memory block + otherwise. + In case of error: NULL is returned and errno is set. Particular errno + values: EINVAL, EILSEQ, ENOMEM. */ +extern uint8_t * + u8_conv_from_encoding (const char *fromcode, + enum iconv_ilseq_handler handler, + const char *src, size_t srclen, + size_t *offsets, + uint8_t *resultbuf, size_t *lengthp); +extern uint16_t * + u16_conv_from_encoding (const char *fromcode, + enum iconv_ilseq_handler handler, + const char *src, size_t srclen, + size_t *offsets, + uint16_t *resultbuf, size_t *lengthp); +extern uint32_t * + u32_conv_from_encoding (const char *fromcode, + enum iconv_ilseq_handler handler, + const char *src, size_t srclen, + size_t *offsets, + uint32_t *resultbuf, size_t *lengthp); + +/* Converts an entire Unicode string, possibly including NUL units, from a + Unicode encoding to a given encoding. + Converts a memory region to encoding TOCODE. TOCODE is as for + iconv_open(3). + The input is in the memory region between SRC (inclusive) and SRC + SRCLEN + (exclusive). + If OFFSETS is not NULL, it should point to an array of SRCLEN integers; this + array is filled with offsets into the result, i.e. the character starting + at SRC[i] corresponds to the character starting at (*RESULTP)[OFFSETS[i]], + and other offsets are set to (size_t)(-1). + RESULTBUF and *LENGTHP should initially be a scratch buffer and its size, + or RESULTBUF can be NULL. + May erase the contents of the memory at RESULTBUF. + If successful: The resulting string (non-NULL) is returned and its length + stored in *LENGTHP. The resulting string is RESULTBUF if no dynamic memory + allocation was necessary, or a freshly allocated memory block otherwise. + In case of error: NULL is returned and errno is set. Particular errno + values: EINVAL, EILSEQ, ENOMEM. */ +extern char * + u8_conv_to_encoding (const char *tocode, + enum iconv_ilseq_handler handler, + const uint8_t *src, size_t srclen, + size_t *offsets, + char *resultbuf, size_t *lengthp); +extern char * + u16_conv_to_encoding (const char *tocode, + enum iconv_ilseq_handler handler, + const uint16_t *src, size_t srclen, + size_t *offsets, + char *resultbuf, size_t *lengthp); +extern char * + u32_conv_to_encoding (const char *tocode, + enum iconv_ilseq_handler handler, + const uint32_t *src, size_t srclen, + size_t *offsets, + char *resultbuf, size_t *lengthp); + +/* Converts a NUL terminated string from a given encoding. + The result is malloc allocated, or NULL (with errno set) in case of error. + Particular errno values: EILSEQ, ENOMEM. */ +extern uint8_t * + u8_strconv_from_encoding (const char *string, + const char *fromcode, + enum iconv_ilseq_handler handler); +extern uint16_t * + u16_strconv_from_encoding (const char *string, + const char *fromcode, + enum iconv_ilseq_handler handler); +extern uint32_t * + u32_strconv_from_encoding (const char *string, + const char *fromcode, + enum iconv_ilseq_handler handler); + +/* Converts a NUL terminated string to a given encoding. + The result is malloc allocated, or NULL (with errno set) in case of error. + Particular errno values: EILSEQ, ENOMEM. */ +extern char * + u8_strconv_to_encoding (const uint8_t *string, + const char *tocode, + enum iconv_ilseq_handler handler); +extern char * + u16_strconv_to_encoding (const uint16_t *string, + const char *tocode, + enum iconv_ilseq_handler handler); +extern char * + u32_strconv_to_encoding (const uint32_t *string, + const char *tocode, + enum iconv_ilseq_handler handler); + +/* Converts a NUL terminated string from the locale encoding. + The result is malloc allocated, or NULL (with errno set) in case of error. + Particular errno values: ENOMEM. */ +extern uint8_t * + u8_strconv_from_locale (const char *string); +extern uint16_t * + u16_strconv_from_locale (const char *string); +extern uint32_t * + u32_strconv_from_locale (const char *string); + +/* Converts a NUL terminated string to the locale encoding. + The result is malloc allocated, or NULL (with errno set) in case of error. + Particular errno values: ENOMEM. */ +extern char * + u8_strconv_to_locale (const uint8_t *string); +extern char * + u16_strconv_to_locale (const uint16_t *string); +extern char * + u32_strconv_to_locale (const uint32_t *string); + + +#ifdef __cplusplus +} +#endif + +#endif /* _UNICONV_H */ diff --git a/gettext-tools/gnulib-lib/uniconv/u8-conv-from-enc.c b/gettext-tools/gnulib-lib/uniconv/u8-conv-from-enc.c new file mode 100644 index 0000000..2d28cde --- /dev/null +++ b/gettext-tools/gnulib-lib/uniconv/u8-conv-from-enc.c @@ -0,0 +1,105 @@ +/* Conversion to UTF-8 from legacy encodings. + Copyright (C) 2002, 2006-2007, 2009-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Written by Bruno Haible . */ + +#include + +/* Specification. */ +#include "uniconv.h" + +#include +#include +#include + +#include "c-strcaseeq.h" +#include "striconveha.h" +#include "unistr.h" + +uint8_t * +u8_conv_from_encoding (const char *fromcode, + enum iconv_ilseq_handler handler, + const char *src, size_t srclen, + size_t *offsets, + uint8_t *resultbuf, size_t *lengthp) +{ + if (STRCASEEQ (fromcode, "UTF-8", 'U','T','F','-','8',0,0,0,0)) + { + /* Conversion from UTF-8 to UTF-8. No need to go through iconv(). */ + uint8_t *result; + + if (u8_check ((const uint8_t *) src, srclen)) + { + errno = EILSEQ; + return NULL; + } + + if (offsets != NULL) + { + size_t i; + + for (i = 0; i < srclen; ) + { + int count = u8_mblen ((const uint8_t *) src + i, srclen - i); + /* We can rely on count > 0 because of the previous u8_check. */ + if (count <= 0) + abort (); + offsets[i] = i; + i++; + while (--count > 0) + offsets[i++] = (size_t)(-1); + } + } + + /* Memory allocation. */ + if (resultbuf != NULL && *lengthp >= srclen) + result = resultbuf; + else + { + result = (uint8_t *) malloc (srclen > 0 ? srclen : 1); + if (result == NULL) + { + errno = ENOMEM; + return NULL; + } + } + + memcpy ((char *) result, src, srclen); + *lengthp = srclen; + return result; + } + else + { + char *result = (char *) resultbuf; + size_t length = *lengthp; + + if (mem_iconveha (src, srclen, fromcode, "UTF-8", true, handler, + offsets, &result, &length) < 0) + return NULL; + + if (result == NULL) /* when (resultbuf == NULL && length == 0) */ + { + result = (char *) malloc (1); + if (result == NULL) + { + errno = ENOMEM; + return NULL; + } + } + *lengthp = length; + return (uint8_t *) result; + } +} diff --git a/gettext-tools/gnulib-lib/unilbrk.in.h b/gettext-tools/gnulib-lib/unilbrk.in.h new file mode 100644 index 0000000..de0f453 --- /dev/null +++ b/gettext-tools/gnulib-lib/unilbrk.in.h @@ -0,0 +1,110 @@ +/* Line breaking of Unicode strings. + Copyright (C) 2001-2003, 2005-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2001. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _UNILBRK_H +#define _UNILBRK_H + +/* Get size_t. */ +#include + +#include "unitypes.h" + +/* Get locale_charset() declaration. */ +#include "localcharset.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* These functions are locale dependent. The encoding argument identifies + the encoding (e.g. "ISO-8859-2" for Polish). */ + + +/* Line breaking. */ + +enum +{ + UC_BREAK_UNDEFINED, + UC_BREAK_PROHIBITED, + UC_BREAK_POSSIBLE, + UC_BREAK_MANDATORY, + UC_BREAK_HYPHENATION +}; + +/* Determine the line break points in S, and store the result at p[0..n-1]. + p[i] = UC_BREAK_MANDATORY means that s[i] is a line break character. + p[i] = UC_BREAK_POSSIBLE means that a line break may be inserted between + s[i-1] and s[i]. + p[i] = UC_BREAK_HYPHENATION means that a hyphen and a line break may be + inserted between s[i-1] and s[i]. But beware of language dependent + hyphenation rules. + p[i] = UC_BREAK_PROHIBITED means that s[i-1] and s[i] must not be separated. + */ +extern void + u8_possible_linebreaks (const uint8_t *s, size_t n, + const char *encoding, char *p); +extern void + u16_possible_linebreaks (const uint16_t *s, size_t n, + const char *encoding, char *p); +extern void + u32_possible_linebreaks (const uint32_t *s, size_t n, + const char *encoding, char *p); +extern void + ulc_possible_linebreaks (const char *s, size_t n, + const char *encoding, char *p); + +/* Choose the best line breaks, assuming the uc_width function. + The string is s[0..n-1]. The maximum number of columns per line is given + as WIDTH. The starting column of the string is given as START_COLUMN. + If the algorithm shall keep room after the last piece, they can be given + as AT_END_COLUMNS. + o is an optional override; if o[i] != UC_BREAK_UNDEFINED, o[i] takes + precedence over p[i] as returned by the *_possible_linebreaks function. + The given ENCODING is used for disambiguating widths in uc_width. + Return the column after the end of the string, and store the result at + p[0..n-1]. + */ +extern int + u8_width_linebreaks (const uint8_t *s, size_t n, int width, + int start_column, int at_end_columns, + const char *o, const char *encoding, + char *p); +extern int + u16_width_linebreaks (const uint16_t *s, size_t n, int width, + int start_column, int at_end_columns, + const char *o, const char *encoding, + char *p); +extern int + u32_width_linebreaks (const uint32_t *s, size_t n, int width, + int start_column, int at_end_columns, + const char *o, const char *encoding, + char *p); +extern int + ulc_width_linebreaks (const char *s, size_t n, int width, + int start_column, int at_end_columns, + const char *o, const char *encoding, + char *p); + + +#ifdef __cplusplus +} +#endif + + +#endif /* _UNILBRK_H */ diff --git a/gettext-tools/gnulib-lib/unilbrk/lbrkprop1.h b/gettext-tools/gnulib-lib/unilbrk/lbrkprop1.h new file mode 100644 index 0000000..aacd2d7 --- /dev/null +++ b/gettext-tools/gnulib-lib/unilbrk/lbrkprop1.h @@ -0,0 +1,33 @@ +/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ +/* Line breaking properties of Unicode characters. */ +/* Generated automatically by gen-lbrk for Unicode 6.0.0. */ + +/* Copyright (C) 2000-2002, 2004, 2008 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#define lbrkprop_header_0 16 +#define lbrkprop_header_1 15 +#define lbrkprop_header_2 7 +#define lbrkprop_header_3 511 +#define lbrkprop_header_4 127 + +typedef struct + { + int level1[15]; + int level2[4 << 9]; + unsigned char level3[166 << 7]; + } +lbrkprop_t; +extern const lbrkprop_t unilbrkprop; diff --git a/gettext-tools/gnulib-lib/unilbrk/lbrkprop2.h b/gettext-tools/gnulib-lib/unilbrk/lbrkprop2.h new file mode 100644 index 0000000..6c1baff --- /dev/null +++ b/gettext-tools/gnulib-lib/unilbrk/lbrkprop2.h @@ -0,0 +1,2942 @@ +/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ +/* Line breaking properties of Unicode characters. */ +/* Generated automatically by gen-lbrk for Unicode 6.0.0. */ + +/* Copyright (C) 2000-2002, 2004, 2008 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +const lbrkprop_t unilbrkprop = +{ + { + 0, 512, 1024, 1024, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 1536 + }, + { + 0, 128, 256, 256, 256, 384, 512, 640, + 256, 768, 896, 1024, 1152, 1280, 1408, 1536, + 1664, -1, 1792, 1920, 2048, 2176, 2304, 2432, + 2560, 2688, 2816, 2944, 3072, 3200, 3328, 3456, + 3584, 3712, 3840, 3968, 4096, 4224, 4352, 4480, + 4608, 256, 256, 256, 256, 4736, 4864, 4992, + 5120, 5248, 5376, 5504, 5632, 5760, 5888, 6016, + 6144, 6272, 256, 6400, 256, 256, 6528, 6656, + 6784, 6912, 7040, 7168, 7296, 7424, 7552, 7680, + 7808, 7936, 8064, 8192, 8320, 8448, 8576, 8704, + 256, 256, 256, 8832, 256, 256, 8960, -1, + 9088, 9216, 9344, 9472, 9600, 9728, 9856, 9984, + 10112, 10240, 10368, 10496, 10624, 10752, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 10880, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 11008, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 11136, 256, 256, 11264, 11392, 256, 11520, + 11648, 11776, 11904, 12032, 12160, 12288, 12416, 12544, + 12672, 12800, 12928, 13056, 13184, 13312, 13440, 12672, + 12800, 12928, 13056, 13184, 13312, 13440, 12672, 12800, + 12928, 13056, 13184, 13312, 13440, 12672, 12800, 12928, + 13056, 13184, 13312, 13440, 12672, 12800, 12928, 13056, + 13184, 13312, 13440, 12672, 12800, 12928, 13056, 13184, + 13312, 13440, 12672, 12800, 12928, 13056, 13184, 13312, + 13440, 12672, 12800, 12928, 13056, 13184, 13312, 13440, + 12672, 12800, 12928, 13056, 13184, 13312, 13440, 12672, + 12800, 12928, 13056, 13184, 13312, 13440, 12672, 12800, + 12928, 13056, 13184, 13312, 13440, 12672, 12800, 12928, + 13056, 13184, 13312, 13440, 12672, 12800, 12928, 13568, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 9856, 9856, 9856, 9856, 13696, 13824, + 256, 256, 13952, 14080, 14208, 14336, 14464, 14592, + 14720, 14848, 14976, 15104, -1, 15232, 15360, 15488, + 256, 15616, -1, -1, -1, -1, -1, -1, + 15744, -1, 15872, -1, 16000, -1, 16128, -1, + 16256, -1, -1, -1, 16384, -1, -1, -1, + 16512, 16640, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 256, 256, 256, 256, 256, 256, 16768, -1, + 16896, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 256, 256, 256, 256, 17024, 17152, 17280, 256, + 17408, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 256, 256, 256, 256, 17536, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 17664, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 256, 17792, 17920, 18048, 18176, -1, 18304, -1, + 18432, 18560, 18688, 256, 256, 18816, 256, 18944, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 19072, 19200, 19328, 19456, 19584, -1, 19712, 19840, + 19968, 20096, 20224, 20352, 20480, 20608, 7680, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 9856, + 9856, 9856, 9856, 9856, 9856, 9856, 9856, 20736, + 20864, -1, 20992, 21120, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1 + }, + { + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_BA, LBP_BK, LBP_BK, LBP_BK, LBP_BK, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_SP, LBP_EX, LBP_QU, LBP_AL, LBP_PR, LBP_PO, LBP_AL, LBP_QU, + LBP_OP, LBP_CP, LBP_AL, LBP_PR, LBP_IS, LBP_HY, LBP_IS, LBP_SY, + LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, + LBP_NU, LBP_NU, LBP_IS, LBP_IS, LBP_AL, LBP_AL, LBP_AL, LBP_EX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_OP, LBP_PR, LBP_CP, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_OP, LBP_BA, LBP_CL, LBP_AL, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_BK, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_GL, LBP_OP, LBP_PO, LBP_PR, LBP_PR, LBP_PR, LBP_AL, LBP_AI, + LBP_AI, LBP_AL, LBP_AI, LBP_QU, LBP_AL, LBP_BA, LBP_AL, LBP_AL, + LBP_PO, LBP_PR, LBP_AI, LBP_AI, LBP_BB, LBP_AL, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AI, LBP_QU, LBP_AI, LBP_AI, LBP_AI, LBP_OP, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AI, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AI, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AI, + LBP_BB, LBP_AI, LBP_AI, LBP_AI, LBP_BB, LBP_AI, LBP_AL, LBP_AL, + LBP_AI, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AL, LBP_AI, LBP_AL, LBP_BB, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_GL, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_GL, LBP_GL, LBP_GL, LBP_GL, + LBP_GL, LBP_GL, LBP_GL, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_XX, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_IS, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_XX, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, + LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_XX, LBP_IS, LBP_BA, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_BA, LBP_CM, + LBP_AL, LBP_CM, LBP_CM, LBP_AL, LBP_CM, LBP_CM, LBP_EX, LBP_CM, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_AL, LBP_AL, + LBP_AL, LBP_PO, LBP_PO, LBP_PO, LBP_IS, LBP_IS, LBP_AL, LBP_AL, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_EX, LBP_XX, LBP_XX, LBP_EX, LBP_EX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, + LBP_NU, LBP_NU, LBP_PO, LBP_NU, LBP_NU, LBP_AL, LBP_AL, LBP_AL, + LBP_CM, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_EX, LBP_AL, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_AL, LBP_AL, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_AL, LBP_AL, LBP_CM, + LBP_CM, LBP_AL, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_AL, LBP_AL, + LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, + LBP_NU, LBP_NU, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_AL, + LBP_AL, LBP_CM, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_XX, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, + LBP_NU, LBP_NU, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_IS, LBP_EX, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_AL, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_AL, LBP_CM, LBP_CM, LBP_CM, + LBP_AL, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_XX, LBP_AL, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_CM, LBP_CM, LBP_CM, LBP_AL, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_AL, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_CM, LBP_CM, LBP_BA, LBP_BA, LBP_NU, LBP_NU, + LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_XX, LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_AL, + LBP_AL, LBP_XX, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_XX, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_CM, LBP_AL, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_XX, LBP_CM, + LBP_CM, LBP_XX, LBP_XX, LBP_CM, LBP_CM, LBP_CM, LBP_AL, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_CM, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_AL, LBP_AL, LBP_XX, LBP_AL, + LBP_AL, LBP_AL, LBP_CM, LBP_CM, LBP_XX, LBP_XX, LBP_NU, LBP_NU, + LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, + LBP_AL, LBP_AL, LBP_PO, LBP_PO, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_PO, LBP_AL, LBP_PR, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_AL, + LBP_AL, LBP_XX, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_XX, + LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_CM, LBP_XX, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_CM, + LBP_CM, LBP_XX, LBP_XX, LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_XX, + LBP_XX, LBP_CM, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_NU, LBP_NU, + LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, + LBP_CM, LBP_CM, LBP_AL, LBP_AL, LBP_AL, LBP_CM, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_AL, + LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_CM, LBP_AL, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_CM, + LBP_CM, LBP_CM, LBP_XX, LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_XX, + LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_CM, LBP_CM, LBP_XX, LBP_XX, LBP_NU, LBP_NU, + LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, + LBP_XX, LBP_PR, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_AL, + LBP_AL, LBP_XX, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_CM, LBP_AL, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_XX, LBP_CM, + LBP_CM, LBP_XX, LBP_XX, LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_CM, LBP_CM, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_AL, LBP_AL, LBP_XX, LBP_AL, + LBP_AL, LBP_AL, LBP_CM, LBP_CM, LBP_XX, LBP_XX, LBP_NU, LBP_NU, + LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_CM, LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_AL, LBP_AL, + LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, + LBP_XX, LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_XX, LBP_AL, LBP_AL, + LBP_XX, LBP_XX, LBP_XX, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_XX, LBP_XX, LBP_CM, LBP_CM, + LBP_CM, LBP_XX, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_XX, + LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_CM, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_NU, LBP_NU, + LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_PR, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_AL, + LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_AL, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_CM, LBP_CM, + LBP_CM, LBP_XX, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_CM, LBP_CM, LBP_XX, + LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_CM, LBP_CM, LBP_XX, LBP_XX, LBP_NU, LBP_NU, + LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_XX, LBP_XX, LBP_CM, LBP_CM, LBP_XX, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_AL, + LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_CM, LBP_AL, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_CM, LBP_CM, + LBP_CM, LBP_XX, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_CM, LBP_CM, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_AL, LBP_XX, + LBP_AL, LBP_AL, LBP_CM, LBP_CM, LBP_XX, LBP_XX, LBP_NU, LBP_NU, + LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, + LBP_XX, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_CM, LBP_CM, LBP_XX, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_AL, + LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_AL, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_CM, LBP_CM, + LBP_CM, LBP_XX, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_AL, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_CM, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_CM, LBP_CM, LBP_XX, LBP_XX, LBP_NU, LBP_NU, + LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, + LBP_XX, LBP_PO, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_XX, LBP_XX, LBP_CM, LBP_CM, LBP_XX, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, + LBP_XX, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, + LBP_XX, LBP_XX, LBP_CM, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_CM, LBP_XX, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_CM, LBP_CM, LBP_AL, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_PR, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_AL, + LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, + LBP_NU, LBP_NU, LBP_BA, LBP_BA, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_SA, LBP_SA, LBP_XX, LBP_SA, LBP_XX, LBP_XX, LBP_SA, + LBP_SA, LBP_XX, LBP_SA, LBP_XX, LBP_XX, LBP_SA, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_XX, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_XX, LBP_SA, LBP_SA, LBP_SA, LBP_XX, LBP_SA, LBP_XX, LBP_SA, + LBP_XX, LBP_XX, LBP_SA, LBP_SA, LBP_XX, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_XX, LBP_SA, LBP_SA, LBP_SA, LBP_XX, LBP_XX, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_XX, LBP_SA, LBP_XX, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_XX, LBP_XX, + LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, + LBP_NU, LBP_NU, LBP_XX, LBP_XX, LBP_SA, LBP_SA, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_BB, LBP_BB, LBP_BB, LBP_BB, LBP_AL, LBP_BB, LBP_BB, + LBP_GL, LBP_BB, LBP_BB, LBP_BA, LBP_GL, LBP_EX, LBP_EX, LBP_EX, + LBP_EX, LBP_EX, LBP_GL, LBP_AL, LBP_EX, LBP_AL, LBP_AL, LBP_AL, + LBP_CM, LBP_CM, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, + LBP_NU, LBP_NU, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_BA, LBP_CM, LBP_AL, LBP_CM, + LBP_AL, LBP_CM, LBP_OP, LBP_CL, LBP_OP, LBP_CL, LBP_CM, LBP_CM, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_BA, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_BA, LBP_CM, LBP_CM, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_XX, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_BA, LBP_BA, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_CM, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_AL, + LBP_BB, LBP_BB, LBP_BA, LBP_BB, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_GL, LBP_GL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, + LBP_NU, LBP_NU, LBP_BA, LBP_BA, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, + LBP_NU, LBP_NU, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, + LBP_JL, LBP_JL, LBP_JL, LBP_JL, LBP_JL, LBP_JL, LBP_JL, LBP_JL, + LBP_JL, LBP_JL, LBP_JL, LBP_JL, LBP_JL, LBP_JL, LBP_JL, LBP_JL, + LBP_JL, LBP_JL, LBP_JL, LBP_JL, LBP_JL, LBP_JL, LBP_JL, LBP_JL, + LBP_JL, LBP_JL, LBP_JL, LBP_JL, LBP_JL, LBP_JL, LBP_JL, LBP_JL, + LBP_JL, LBP_JL, LBP_JL, LBP_JL, LBP_JL, LBP_JL, LBP_JL, LBP_JL, + LBP_JL, LBP_JL, LBP_JL, LBP_JL, LBP_JL, LBP_JL, LBP_JL, LBP_JL, + LBP_JL, LBP_JL, LBP_JL, LBP_JL, LBP_JL, LBP_JL, LBP_JL, LBP_JL, + LBP_JL, LBP_JL, LBP_JL, LBP_JL, LBP_JL, LBP_JL, LBP_JL, LBP_JL, + LBP_JL, LBP_JL, LBP_JL, LBP_JL, LBP_JL, LBP_JL, LBP_JL, LBP_JL, + LBP_JL, LBP_JL, LBP_JL, LBP_JL, LBP_JL, LBP_JL, LBP_JL, LBP_JL, + LBP_JL, LBP_JL, LBP_JL, LBP_JL, LBP_JL, LBP_JL, LBP_JL, LBP_JL, + LBP_JL, LBP_JL, LBP_JL, LBP_JL, LBP_JL, LBP_JL, LBP_JL, LBP_JL, + LBP_JV, LBP_JV, LBP_JV, LBP_JV, LBP_JV, LBP_JV, LBP_JV, LBP_JV, + LBP_JV, LBP_JV, LBP_JV, LBP_JV, LBP_JV, LBP_JV, LBP_JV, LBP_JV, + LBP_JV, LBP_JV, LBP_JV, LBP_JV, LBP_JV, LBP_JV, LBP_JV, LBP_JV, + LBP_JV, LBP_JV, LBP_JV, LBP_JV, LBP_JV, LBP_JV, LBP_JV, LBP_JV, + LBP_JV, LBP_JV, LBP_JV, LBP_JV, LBP_JV, LBP_JV, LBP_JV, LBP_JV, + LBP_JV, LBP_JV, LBP_JV, LBP_JV, LBP_JV, LBP_JV, LBP_JV, LBP_JV, + LBP_JV, LBP_JV, LBP_JV, LBP_JV, LBP_JV, LBP_JV, LBP_JV, LBP_JV, + LBP_JV, LBP_JV, LBP_JV, LBP_JV, LBP_JV, LBP_JV, LBP_JV, LBP_JV, + LBP_JV, LBP_JV, LBP_JV, LBP_JV, LBP_JV, LBP_JV, LBP_JV, LBP_JV, + LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, + LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, + LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, + LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, + LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, + LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, + LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, + LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, + LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, + LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, + LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, + LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, + LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_CM, LBP_CM, LBP_CM, + LBP_AL, LBP_BA, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_BA, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_BA, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_OP, LBP_CL, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_BA, LBP_BA, LBP_BA, LBP_AL, LBP_AL, + LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_CM, LBP_CM, LBP_CM, LBP_BA, LBP_BA, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_CM, LBP_CM, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_AL, + LBP_AL, LBP_XX, LBP_CM, LBP_CM, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_BA, LBP_BA, LBP_NS, LBP_SA, + LBP_BA, LBP_AL, LBP_BA, LBP_PR, LBP_SA, LBP_SA, LBP_XX, LBP_XX, + LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, + LBP_NU, LBP_NU, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_EX, LBP_EX, LBP_BA, LBP_BA, LBP_BB, LBP_AL, + LBP_EX, LBP_EX, LBP_AL, LBP_CM, LBP_CM, LBP_CM, LBP_GL, LBP_XX, + LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, + LBP_NU, LBP_NU, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_CM, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_EX, LBP_EX, LBP_NU, LBP_NU, + LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_XX, LBP_XX, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, + LBP_NU, LBP_NU, LBP_SA, LBP_XX, LBP_XX, LBP_XX, LBP_SA, LBP_SA, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_XX, LBP_AL, LBP_AL, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_XX, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_XX, LBP_XX, LBP_CM, + LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, + LBP_NU, LBP_NU, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, + LBP_NU, LBP_NU, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, + LBP_NU, LBP_NU, LBP_BA, LBP_BA, LBP_AL, LBP_BA, LBP_BA, LBP_BA, + LBP_BA, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, + LBP_CM, LBP_CM, LBP_CM, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_XX, LBP_XX, LBP_AL, LBP_AL, + LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, + LBP_NU, LBP_NU, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_XX, LBP_XX, LBP_XX, LBP_BA, LBP_BA, LBP_BA, LBP_BA, LBP_BA, + LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, + LBP_NU, LBP_NU, LBP_XX, LBP_XX, LBP_XX, LBP_AL, LBP_AL, LBP_AL, + LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, + LBP_NU, LBP_NU, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_BA, LBP_BA, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_CM, LBP_CM, LBP_CM, LBP_AL, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_CM, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_CM, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_XX, LBP_AL, LBP_XX, LBP_AL, LBP_XX, LBP_AL, LBP_XX, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_XX, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_BB, LBP_AL, LBP_XX, + LBP_BA, LBP_BA, LBP_BA, LBP_BA, LBP_BA, LBP_BA, LBP_BA, LBP_GL, + LBP_BA, LBP_BA, LBP_BA, LBP_ZW, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_BA, LBP_GL, LBP_BA, LBP_BA, LBP_B2, LBP_AI, LBP_AI, LBP_AL, + LBP_QU, LBP_QU, LBP_OP, LBP_QU, LBP_QU, LBP_QU, LBP_OP, LBP_QU, + LBP_AI, LBP_AI, LBP_AL, LBP_AL, LBP_IN, LBP_IN, LBP_IN, LBP_BA, + LBP_BK, LBP_BK, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_GL, + LBP_PO, LBP_PO, LBP_PO, LBP_PO, LBP_PO, LBP_PO, LBP_PO, LBP_PO, + LBP_AL, LBP_QU, LBP_QU, LBP_AI, LBP_NS, LBP_NS, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_IS, LBP_OP, LBP_CL, LBP_NS, + LBP_NS, LBP_NS, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_BA, LBP_AL, + LBP_BA, LBP_BA, LBP_BA, LBP_BA, LBP_AL, LBP_BA, LBP_BA, LBP_BA, + LBP_WJ, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_AI, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_OP, LBP_CL, LBP_AI, + LBP_AL, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_OP, LBP_CL, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, + LBP_PR, LBP_PR, LBP_PR, LBP_PR, LBP_PR, LBP_PR, LBP_PR, LBP_PO, + LBP_PR, LBP_PR, LBP_PR, LBP_PR, LBP_PR, LBP_PR, LBP_PR, LBP_PR, + LBP_PR, LBP_PR, LBP_PR, LBP_PR, LBP_PR, LBP_PR, LBP_PO, LBP_PR, + LBP_PR, LBP_PR, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_PO, LBP_AL, LBP_AI, LBP_AL, LBP_AL, + LBP_AL, LBP_PO, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AI, LBP_AL, LBP_AL, LBP_PR, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AI, LBP_AI, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AI, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AI, LBP_AI, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AI, LBP_AL, LBP_AL, LBP_AI, LBP_AL, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AI, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AI, LBP_AL, LBP_AI, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AI, LBP_AL, LBP_AI, LBP_AI, LBP_AL, LBP_AL, LBP_AL, LBP_AI, + LBP_AI, LBP_AL, LBP_AL, LBP_AI, LBP_AL, LBP_AL, LBP_AL, LBP_AI, + LBP_AL, LBP_AI, LBP_PR, LBP_PR, LBP_AL, LBP_AI, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AI, LBP_AL, LBP_AL, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AL, LBP_AL, LBP_AI, LBP_AL, LBP_AI, LBP_AL, LBP_AI, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AL, LBP_AI, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AI, LBP_AI, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AI, LBP_AL, LBP_AL, LBP_AL, LBP_AI, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AI, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AI, LBP_AI, LBP_AL, LBP_AL, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AL, LBP_AL, LBP_AI, LBP_AI, LBP_AL, LBP_AL, LBP_AI, LBP_AI, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AI, LBP_AI, LBP_AL, LBP_AL, LBP_AI, LBP_AI, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AI, LBP_AL, LBP_AL, + LBP_AL, LBP_AI, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AI, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AI, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AI, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_OP, LBP_CL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AL, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AL, LBP_AL, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AI, LBP_AI, LBP_AL, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AI, LBP_AI, LBP_AL, LBP_AL, LBP_AI, LBP_AI, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AI, LBP_AI, LBP_AL, LBP_AL, + LBP_AI, LBP_AI, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AI, LBP_AI, + LBP_AI, LBP_AL, LBP_AL, LBP_AI, LBP_AL, LBP_AL, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AI, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AI, LBP_AI, LBP_AL, + LBP_AL, LBP_AI, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AI, LBP_AI, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AI, LBP_AL, LBP_AI, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AI, LBP_AL, LBP_AI, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AI, LBP_AI, LBP_AL, LBP_AI, LBP_AI, LBP_AI, LBP_AL, LBP_AI, + LBP_AI, LBP_AI, LBP_AI, LBP_AL, LBP_AI, LBP_AI, LBP_AL, LBP_AI, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AI, LBP_AI, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AI, LBP_AI, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AL, LBP_AI, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AL, LBP_AI, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AI, + LBP_AL, LBP_AL, LBP_AL, LBP_QU, LBP_QU, LBP_QU, LBP_QU, LBP_AL, + LBP_AL, LBP_AL, LBP_EX, LBP_EX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_OP, LBP_CL, LBP_OP, LBP_CL, LBP_OP, LBP_CL, LBP_OP, LBP_CL, + LBP_OP, LBP_CL, LBP_OP, LBP_CL, LBP_OP, LBP_CL, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_OP, LBP_CL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_XX, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_OP, LBP_CL, + LBP_OP, LBP_CL, LBP_OP, LBP_CL, LBP_OP, LBP_CL, LBP_OP, LBP_CL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_OP, LBP_CL, LBP_OP, LBP_CL, LBP_OP, + LBP_CL, LBP_OP, LBP_CL, LBP_OP, LBP_CL, LBP_OP, LBP_CL, LBP_OP, + LBP_CL, LBP_OP, LBP_CL, LBP_OP, LBP_CL, LBP_OP, LBP_CL, LBP_OP, + LBP_CL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_OP, LBP_CL, LBP_OP, LBP_CL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_OP, LBP_CL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_CM, + LBP_CM, LBP_CM, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_EX, LBP_BA, LBP_BA, LBP_BA, LBP_AL, LBP_EX, LBP_BA, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_AL, + LBP_BA, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_CM, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_QU, LBP_QU, LBP_QU, LBP_QU, LBP_QU, LBP_QU, LBP_QU, LBP_QU, + LBP_QU, LBP_QU, LBP_QU, LBP_QU, LBP_QU, LBP_QU, LBP_BA, LBP_BA, + LBP_BA, LBP_BA, LBP_BA, LBP_BA, LBP_BA, LBP_BA, LBP_AL, LBP_BA, + LBP_OP, LBP_BA, LBP_AL, LBP_AL, LBP_QU, LBP_QU, LBP_AL, LBP_AL, + LBP_QU, LBP_QU, LBP_OP, LBP_CL, LBP_OP, LBP_CL, LBP_OP, LBP_CL, + LBP_OP, LBP_CL, LBP_BA, LBP_BA, LBP_BA, LBP_BA, LBP_EX, LBP_AL, + LBP_BA, LBP_BA, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_XX, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_ID, LBP_CL, LBP_CL, LBP_ID, LBP_ID, LBP_NS, LBP_ID, LBP_ID, + LBP_OP, LBP_CL, LBP_OP, LBP_CL, LBP_OP, LBP_CL, LBP_OP, LBP_CL, + LBP_OP, LBP_CL, LBP_ID, LBP_ID, LBP_OP, LBP_CL, LBP_OP, LBP_CL, + LBP_OP, LBP_CL, LBP_OP, LBP_CL, LBP_NS, LBP_OP, LBP_CL, LBP_CL, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_NS, LBP_NS, LBP_ID, LBP_ID, LBP_ID, + LBP_XX, LBP_NS, LBP_ID, LBP_NS, LBP_ID, LBP_NS, LBP_ID, LBP_NS, + LBP_ID, LBP_NS, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_NS, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_NS, LBP_ID, LBP_NS, LBP_ID, LBP_NS, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_NS, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_NS, LBP_NS, LBP_XX, + LBP_XX, LBP_CM, LBP_CM, LBP_NS, LBP_NS, LBP_NS, LBP_NS, LBP_ID, + LBP_NS, LBP_NS, LBP_ID, LBP_NS, LBP_ID, LBP_NS, LBP_ID, LBP_NS, + LBP_ID, LBP_NS, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_NS, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_NS, LBP_ID, LBP_NS, LBP_ID, LBP_NS, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_NS, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_NS, LBP_NS, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_NS, LBP_NS, LBP_NS, LBP_NS, LBP_ID, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_XX, LBP_XX, + LBP_XX, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_XX, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_NS, LBP_NS, LBP_NS, LBP_NS, LBP_NS, LBP_NS, LBP_NS, LBP_NS, + LBP_NS, LBP_NS, LBP_NS, LBP_NS, LBP_NS, LBP_NS, LBP_NS, LBP_NS, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_XX, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_XX, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_NS, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_XX, LBP_XX, LBP_XX, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_BA, LBP_BA, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_BA, LBP_EX, LBP_BA, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, + LBP_NU, LBP_NU, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_CM, LBP_CM, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_CM, LBP_CM, LBP_AL, LBP_BA, LBP_BA, LBP_BA, LBP_BA, LBP_BA, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, + LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_CM, LBP_AL, LBP_AL, LBP_AL, LBP_CM, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_CM, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_PO, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_BB, LBP_BB, LBP_EX, LBP_EX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_CM, LBP_CM, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_BA, LBP_BA, + LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, + LBP_NU, LBP_NU, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, + LBP_NU, LBP_NU, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_BA, LBP_BA, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_AL, + LBP_JL, LBP_JL, LBP_JL, LBP_JL, LBP_JL, LBP_JL, LBP_JL, LBP_JL, + LBP_JL, LBP_JL, LBP_JL, LBP_JL, LBP_JL, LBP_JL, LBP_JL, LBP_JL, + LBP_JL, LBP_JL, LBP_JL, LBP_JL, LBP_JL, LBP_JL, LBP_JL, LBP_JL, + LBP_JL, LBP_JL, LBP_JL, LBP_JL, LBP_JL, LBP_XX, LBP_XX, LBP_XX, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_BA, + LBP_BA, LBP_BA, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_AL, + LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, + LBP_NU, LBP_NU, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_AL, LBP_AL, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_CM, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_CM, LBP_CM, LBP_XX, LBP_XX, + LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, + LBP_NU, LBP_NU, LBP_XX, LBP_XX, LBP_AL, LBP_BA, LBP_BA, LBP_BA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_SA, LBP_SA, LBP_SA, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, + LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, + LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_BA, LBP_CM, LBP_CM, LBP_XX, LBP_XX, + LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, + LBP_NU, LBP_NU, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_H2, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H2, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H2, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H2, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H2, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H2, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H2, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H2, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H2, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H2, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H2, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H2, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H2, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H2, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H2, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H2, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H2, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H2, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H2, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H2, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H2, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H2, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H2, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H2, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H2, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H2, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H2, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H2, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H2, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H2, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H2, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H2, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H2, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_H3, + LBP_H3, LBP_H3, LBP_H3, LBP_H3, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_JV, LBP_JV, LBP_JV, LBP_JV, LBP_JV, LBP_JV, LBP_JV, LBP_JV, + LBP_JV, LBP_JV, LBP_JV, LBP_JV, LBP_JV, LBP_JV, LBP_JV, LBP_JV, + LBP_JV, LBP_JV, LBP_JV, LBP_JV, LBP_JV, LBP_JV, LBP_JV, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, + LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, + LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, + LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, + LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, + LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_JT, + LBP_JT, LBP_JT, LBP_JT, LBP_JT, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_AL, LBP_CM, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_XX, + LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_OP, LBP_CL, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_XX, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_PO, LBP_AL, LBP_XX, LBP_XX, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_IS, LBP_CL, LBP_CL, LBP_IS, LBP_IS, LBP_EX, LBP_EX, LBP_OP, + LBP_CL, LBP_IN, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_OP, LBP_CL, LBP_OP, + LBP_CL, LBP_OP, LBP_CL, LBP_OP, LBP_CL, LBP_OP, LBP_CL, LBP_OP, + LBP_CL, LBP_OP, LBP_CL, LBP_OP, LBP_CL, LBP_ID, LBP_ID, LBP_OP, + LBP_CL, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_CL, LBP_ID, LBP_CL, LBP_XX, LBP_NS, LBP_NS, LBP_EX, LBP_EX, + LBP_ID, LBP_OP, LBP_CL, LBP_OP, LBP_CL, LBP_OP, LBP_CL, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_XX, + LBP_ID, LBP_PR, LBP_PO, LBP_ID, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_WJ, + LBP_XX, LBP_EX, LBP_ID, LBP_ID, LBP_PR, LBP_PO, LBP_ID, LBP_ID, + LBP_OP, LBP_CL, LBP_ID, LBP_ID, LBP_CL, LBP_ID, LBP_CL, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_NS, LBP_NS, LBP_ID, LBP_ID, LBP_ID, LBP_EX, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_OP, LBP_ID, LBP_CL, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_OP, LBP_ID, LBP_CL, LBP_ID, LBP_OP, + LBP_CL, LBP_CL, LBP_OP, LBP_CL, LBP_CL, LBP_NS, LBP_AL, LBP_NS, + LBP_NS, LBP_NS, LBP_NS, LBP_NS, LBP_NS, LBP_NS, LBP_NS, LBP_NS, + LBP_NS, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_NS, LBP_NS, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, + LBP_XX, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_XX, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_XX, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_XX, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, + LBP_PO, LBP_PR, LBP_ID, LBP_ID, LBP_ID, LBP_PR, LBP_PR, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_CM, LBP_CM, LBP_CM, LBP_CB, LBP_AI, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_XX, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_BA, LBP_BA, LBP_BA, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_CM, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_BA, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_BA, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, + LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, + LBP_NU, LBP_NU, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, + LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_AL, + LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_AL, LBP_XX, LBP_XX, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_BA, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_BA, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_AL, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_CM, LBP_CM, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_AL, + LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_CM, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_BA, LBP_BA, LBP_BA, LBP_BA, LBP_BA, LBP_BA, LBP_BA, LBP_BA, + LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, + LBP_XX, LBP_BA, LBP_BA, LBP_BA, LBP_BA, LBP_BA, LBP_BA, LBP_BA, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, + LBP_CM, LBP_CM, LBP_CM, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_BA, + LBP_BA, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_NU, LBP_NU, + LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_CM, LBP_CM, LBP_CM, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_AL, LBP_AL, LBP_AL, LBP_BA, LBP_BA, + LBP_BA, LBP_BA, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_BA, LBP_BA, LBP_BA, LBP_BA, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_OP, LBP_OP, LBP_OP, LBP_CL, LBP_CL, LBP_CL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_CL, LBP_AL, LBP_AL, LBP_AL, LBP_OP, LBP_CL, + LBP_OP, LBP_CL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_OP, LBP_CL, LBP_CL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_ID, LBP_ID, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, + LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_AL, LBP_AL, LBP_AL, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_AL, LBP_AL, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_CM, LBP_CM, LBP_CM, LBP_AL, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_AL, + LBP_XX, LBP_XX, LBP_AL, LBP_XX, LBP_XX, LBP_AL, LBP_AL, LBP_XX, + LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_XX, + LBP_XX, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_NU, LBP_NU, + LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, + LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, + LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, + LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, + LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, + LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, + LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, + LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AI, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AL, LBP_XX, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, + LBP_AI, LBP_AI, LBP_AI, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_ID, LBP_ID, LBP_ID, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_ID, LBP_ID, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, + LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_XX, + LBP_AL, LBP_XX, LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, + LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, + LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_XX, LBP_XX, + LBP_XX, LBP_CM, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, + LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX + } +}; diff --git a/gettext-tools/gnulib-lib/unilbrk/lbrktables.c b/gettext-tools/gnulib-lib/unilbrk/lbrktables.c new file mode 100644 index 0000000..3a511f6 --- /dev/null +++ b/gettext-tools/gnulib-lib/unilbrk/lbrktables.c @@ -0,0 +1,64 @@ +/* Line breaking auxiliary tables. + Copyright (C) 2001-2003, 2006-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2001. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include "unilbrk/lbrktables.h" + +/* Define unilbrkprop, table of line breaking properties. */ +#include "unilbrk/lbrkprop2.h" + +const unsigned char unilbrk_table[25][25] = +{ + /* after */ + /* WJ GL B2 BA BB HY CL CP EX IN NS OP QU IS NU PO PR SY AL H2 H3 ID JL JV JT */ +/* WJ */ { P, I, I, I, I, I, P, P, P, I, I, I, I, P, I, I, I, P, I, I, I, I, I, I, I, }, +/* GL */ { P, I, I, I, I, I, P, P, P, I, I, I, I, P, I, I, I, P, I, I, I, I, I, I, I, }, +/* B2 */ { P, I, P, I, D, I, P, P, P, D, I, D, I, P, D, D, D, P, D, D, D, D, D, D, D, }, +/* BA */ { P, D, D, I, D, I, P, P, P, D, I, D, I, P, D, D, D, P, D, D, D, D, D, D, D, }, +/* BB */ { P, I, I, I, I, I, P, P, P, I, I, I, I, P, I, I, I, P, I, I, I, I, I, I, I, }, +/* HY */ { P, D, D, I, D, I, P, P, P, D, I, D, I, P, I, D, D, P, D, D, D, D, D, D, D, }, +/* CL */ { P, I, D, I, D, I, P, P, P, D, P, D, I, P, D, I, I, P, D, D, D, D, D, D, D, }, +/* CP */ { P, I, D, I, D, I, P, P, P, D, P, D, I, P, I, I, I, P, I, D, D, D, D, D, D, }, +/* EX */ { P, I, D, I, D, I, P, P, P, D, I, D, I, P, D, D, D, P, D, D, D, D, D, D, D, }, +/* IN */ { P, I, D, I, D, I, P, P, P, I, I, D, I, P, D, D, D, P, D, D, D, D, D, D, D, }, +/* NS */ { P, I, D, I, D, I, P, P, P, D, I, D, I, P, D, D, D, P, D, D, D, D, D, D, D, }, +/* OP */ { P, P, P, P, P, P, P, P, P, P, P, P, P, P, P, P, P, P, P, P, P, P, P, P, P, }, +/* QU */ { P, I, I, I, I, I, P, P, P, I, I, P, I, P, I, I, I, P, I, I, I, I, I, I, I, }, +/* IS */ { P, I, D, I, D, I, P, P, P, D, I, D, I, P, I, D, D, P, D, D, D, D, D, D, D, }, +/* NU */ { P, I, D, I, D, I, P, P, P, I, I, I, I, P, I, I, I, P, I, D, D, D, D, D, D, }, +/* PO */ { P, I, D, I, D, I, P, P, P, D, I, I, I, P, I, D, D, P, I, D, D, D, D, D, D, }, +/* PR */ { P, I, D, I, D, I, P, P, P, D, I, I, I, P, I, D, D, P, I, I, I, I, I, I, I, }, +/* SY */ { P, I, D, I, D, I, P, P, P, D, I, D, I, P, I, D, D, P, D, D, D, D, D, D, D, }, +/* AL */ { P, I, D, I, D, I, P, P, P, I, I, I, I, P, I, D, D, P, I, D, D, D, D, D, D, }, +/* H2 */ { P, I, D, I, D, I, P, P, P, I, I, D, I, P, D, I, D, P, D, D, D, D, D, I, I, }, +/* H3 */ { P, I, D, I, D, I, P, P, P, I, I, D, I, P, D, I, D, P, D, D, D, D, D, D, I, }, +/* ID */ { P, I, D, I, D, I, P, P, P, I, I, D, I, P, D, I, D, P, D, D, D, D, D, D, D, }, +/* JL */ { P, I, D, I, D, I, P, P, P, I, I, D, I, P, D, I, D, P, D, I, I, D, I, I, D, }, +/* JV */ { P, I, D, I, D, I, P, P, P, I, I, D, I, P, D, I, D, P, D, D, D, D, D, I, I, }, +/* JT */ { P, I, D, I, D, I, P, P, P, I, I, D, I, P, D, I, D, P, D, D, D, D, D, D, I, }, +/* "" */ +/* before */ +}; +/* Note: The (IS,AL) entry has been changed from I to D. In other words, the + rule "Do not break between numeric punctuation and alphabetics" is not + implemented here. We want to break before the HTML tag in strings like + "

Some sentence.

" */ +/* Note: The (B2,B2) entry should probably be D instead of P. */ +/* Note: The (PR,ID) entry should probably be D instead of I. */ +/* Note: The (WJ,*) and (GL,*) entries should probably be P instead of I. */ diff --git a/gettext-tools/gnulib-lib/unilbrk/lbrktables.h b/gettext-tools/gnulib-lib/unilbrk/lbrktables.h new file mode 100644 index 0000000..33a6f56 --- /dev/null +++ b/gettext-tools/gnulib-lib/unilbrk/lbrktables.h @@ -0,0 +1,95 @@ +/* Line breaking auxiliary tables. + Copyright (C) 2001-2003, 2006-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2001. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include "unitypes.h" + +/* Line breaking classification. */ + +enum +{ + /* Values >= 25 are resolved at run time. */ + LBP_BK = 25, /* mandatory break */ +/*LBP_CR, carriage return - not used here because it's a DOSism */ +/*LBP_LF, line feed - not used here because it's a DOSism */ + LBP_CM = 26, /* attached characters and combining marks */ +/*LBP_NL, next line - not used here because it's equivalent to LBP_BK */ +/*LBP_SG, surrogates - not used here because they are not characters */ + LBP_WJ = 0, /* word joiner */ + LBP_ZW = 27, /* zero width space */ + LBP_GL = 1, /* non-breaking (glue) */ + LBP_SP = 28, /* space */ + LBP_B2 = 2, /* break opportunity before and after */ + LBP_BA = 3, /* break opportunity after */ + LBP_BB = 4, /* break opportunity before */ + LBP_HY = 5, /* hyphen */ + LBP_CB = 29, /* contingent break opportunity */ + LBP_CL = 6, /* closing punctuation */ + LBP_CP = 7, /* closing parenthesis */ + LBP_EX = 8, /* exclamation/interrogation */ + LBP_IN = 9, /* inseparable */ + LBP_NS = 10, /* non starter */ + LBP_OP = 11, /* opening punctuation */ + LBP_QU = 12, /* ambiguous quotation */ + LBP_IS = 13, /* infix separator (numeric) */ + LBP_NU = 14, /* numeric */ + LBP_PO = 15, /* postfix (numeric) */ + LBP_PR = 16, /* prefix (numeric) */ + LBP_SY = 17, /* symbols allowing breaks */ + LBP_AI = 30, /* ambiguous (alphabetic or ideograph) */ + LBP_AL = 18, /* ordinary alphabetic and symbol characters */ + LBP_H2 = 19, /* Hangul LV syllable */ + LBP_H3 = 20, /* Hangul LVT syllable */ + LBP_ID = 21, /* ideographic */ + LBP_JL = 22, /* Hangul L Jamo */ + LBP_JV = 23, /* Hangul V Jamo */ + LBP_JT = 24, /* Hangul T Jamo */ + LBP_SA = 31, /* complex context (South East Asian) */ + LBP_XX = 32 /* unknown */ +}; + +#include "lbrkprop1.h" + +static inline unsigned char +unilbrkprop_lookup (ucs4_t uc) +{ + unsigned int index1 = uc >> lbrkprop_header_0; + if (index1 < lbrkprop_header_1) + { + int lookup1 = unilbrkprop.level1[index1]; + if (lookup1 >= 0) + { + unsigned int index2 = (uc >> lbrkprop_header_2) & lbrkprop_header_3; + int lookup2 = unilbrkprop.level2[lookup1 + index2]; + if (lookup2 >= 0) + { + unsigned int index3 = uc & lbrkprop_header_4; + return unilbrkprop.level3[lookup2 + index3]; + } + } + } + return LBP_XX; +} + +/* Table indexed by two line breaking classifications. */ +#define D 1 /* direct break opportunity, empty in table 7.3 of UTR #14 */ +#define I 2 /* indirect break opportunity, '%' in table 7.3 of UTR #14 */ +#define P 3 /* prohibited break, '^' in table 7.3 of UTR #14 */ + +extern const unsigned char unilbrk_table[25][25]; + +/* We don't support line breaking of complex-context dependent characters + (Thai, Lao, Myanmar, Khmer) yet, because it requires dictionary lookup. */ diff --git a/gettext-tools/gnulib-lib/unilbrk/u8-possible-linebreaks.c b/gettext-tools/gnulib-lib/unilbrk/u8-possible-linebreaks.c new file mode 100644 index 0000000..ba5e892 --- /dev/null +++ b/gettext-tools/gnulib-lib/unilbrk/u8-possible-linebreaks.c @@ -0,0 +1,261 @@ +/* Line breaking of UTF-8 strings. + Copyright (C) 2001-2003, 2006-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2001. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include "unilbrk.h" + +#include +#include + +#include "unilbrk/lbrktables.h" +#include "uniwidth/cjk.h" +#include "unistr.h" + +void +u8_possible_linebreaks (const uint8_t *s, size_t n, const char *encoding, char *p) +{ + int LBP_AI_REPLACEMENT = (is_cjk_encoding (encoding) ? LBP_ID : LBP_AL); + const uint8_t *s_end = s + n; + int last_prop = LBP_BK; /* line break property of last non-space character */ + char *seen_space = NULL; /* Was a space seen after the last non-space character? */ + char *seen_space2 = NULL; /* At least two spaces after the last non-space? */ + + /* Don't break inside multibyte characters. */ + memset (p, UC_BREAK_PROHIBITED, n); + + while (s < s_end) + { + ucs4_t uc; + int count = u8_mbtouc_unsafe (&uc, s, s_end - s); + int prop = unilbrkprop_lookup (uc); + + if (prop == LBP_BK) + { + /* Mandatory break. */ + *p = UC_BREAK_MANDATORY; + last_prop = LBP_BK; + seen_space = NULL; + seen_space2 = NULL; + } + else + { + char *q; + + /* Resolve property values whose behaviour is not fixed. */ + switch (prop) + { + case LBP_AI: + /* Resolve ambiguous. */ + prop = LBP_AI_REPLACEMENT; + break; + case LBP_CB: + /* This is arbitrary. */ + prop = LBP_ID; + break; + case LBP_SA: + /* We don't handle complex scripts yet. + Treat LBP_SA like LBP_XX. */ + case LBP_XX: + /* This is arbitrary. */ + prop = LBP_AL; + break; + } + + /* Deal with spaces and combining characters. */ + q = p; + if (prop == LBP_SP) + { + /* Don't break just before a space. */ + *p = UC_BREAK_PROHIBITED; + seen_space2 = seen_space; + seen_space = p; + } + else if (prop == LBP_ZW) + { + /* Don't break just before a zero-width space. */ + *p = UC_BREAK_PROHIBITED; + last_prop = LBP_ZW; + seen_space = NULL; + seen_space2 = NULL; + } + else if (prop == LBP_CM) + { + /* Don't break just before a combining character, except immediately after a + zero-width space. */ + if (last_prop == LBP_ZW) + { + /* Break after zero-width space. */ + *p = UC_BREAK_POSSIBLE; + /* A combining character turns a preceding space into LBP_ID. */ + last_prop = LBP_ID; + } + else + { + *p = UC_BREAK_PROHIBITED; + /* A combining character turns a preceding space into LBP_ID. */ + if (seen_space != NULL) + { + q = seen_space; + seen_space = seen_space2; + prop = LBP_ID; + goto lookup_via_table; + } + } + } + else + { + lookup_via_table: + /* prop must be usable as an index for table 7.3 of UTR #14. */ + if (!(prop >= 0 && prop < sizeof (unilbrk_table) / sizeof (unilbrk_table[0]))) + abort (); + + if (last_prop == LBP_BK) + { + /* Don't break at the beginning of a line. */ + *q = UC_BREAK_PROHIBITED; + } + else if (last_prop == LBP_ZW) + { + /* Break after zero-width space. */ + *q = UC_BREAK_POSSIBLE; + } + else + { + switch (unilbrk_table [last_prop] [prop]) + { + case D: + *q = UC_BREAK_POSSIBLE; + break; + case I: + *q = (seen_space != NULL ? UC_BREAK_POSSIBLE : UC_BREAK_PROHIBITED); + break; + case P: + *q = UC_BREAK_PROHIBITED; + break; + default: + abort (); + } + } + last_prop = prop; + seen_space = NULL; + seen_space2 = NULL; + } + } + + s += count; + p += count; + } +} + + +#ifdef TEST + +#include +#include + +/* Read the contents of an input stream, and return it, terminated with a NUL + byte. */ +char * +read_file (FILE *stream) +{ +#define BUFSIZE 4096 + char *buf = NULL; + int alloc = 0; + int size = 0; + int count; + + while (! feof (stream)) + { + if (size + BUFSIZE > alloc) + { + alloc = alloc + alloc / 2; + if (alloc < size + BUFSIZE) + alloc = size + BUFSIZE; + buf = realloc (buf, alloc); + if (buf == NULL) + { + fprintf (stderr, "out of memory\n"); + exit (1); + } + } + count = fread (buf + size, 1, BUFSIZE, stream); + if (count == 0) + { + if (ferror (stream)) + { + perror ("fread"); + exit (1); + } + } + else + size += count; + } + buf = realloc (buf, size + 1); + if (buf == NULL) + { + fprintf (stderr, "out of memory\n"); + exit (1); + } + buf[size] = '\0'; + return buf; +#undef BUFSIZE +} + +int +main (int argc, char * argv[]) +{ + if (argc == 1) + { + /* Display all the break opportunities in the input string. */ + char *input = read_file (stdin); + int length = strlen (input); + char *breaks = malloc (length); + int i; + + u8_possible_linebreaks ((uint8_t *) input, length, "UTF-8", breaks); + + for (i = 0; i < length; i++) + { + switch (breaks[i]) + { + case UC_BREAK_POSSIBLE: + /* U+2027 in UTF-8 encoding */ + putc (0xe2, stdout); putc (0x80, stdout); putc (0xa7, stdout); + break; + case UC_BREAK_MANDATORY: + /* U+21B2 (or U+21B5) in UTF-8 encoding */ + putc (0xe2, stdout); putc (0x86, stdout); putc (0xb2, stdout); + break; + case UC_BREAK_PROHIBITED: + break; + default: + abort (); + } + putc (input[i], stdout); + } + + free (breaks); + + return 0; + } + else + return 1; +} + +#endif /* TEST */ diff --git a/gettext-tools/gnulib-lib/unilbrk/u8-width-linebreaks.c b/gettext-tools/gnulib-lib/unilbrk/u8-width-linebreaks.c new file mode 100644 index 0000000..9099983 --- /dev/null +++ b/gettext-tools/gnulib-lib/unilbrk/u8-width-linebreaks.c @@ -0,0 +1,204 @@ +/* Line breaking of UTF-8 strings. + Copyright (C) 2001-2003, 2006-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2001. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include "unilbrk.h" + +#include "unistr.h" +#include "uniwidth.h" + +int +u8_width_linebreaks (const uint8_t *s, size_t n, + int width, int start_column, int at_end_columns, + const char *o, const char *encoding, + char *p) +{ + const uint8_t *s_end; + char *last_p; + int last_column; + int piece_width; + + u8_possible_linebreaks (s, n, encoding, p); + + s_end = s + n; + last_p = NULL; + last_column = start_column; + piece_width = 0; + while (s < s_end) + { + ucs4_t uc; + int count = u8_mbtouc_unsafe (&uc, s, s_end - s); + + /* Respect the override. */ + if (o != NULL && *o != UC_BREAK_UNDEFINED) + *p = *o; + + if (*p == UC_BREAK_POSSIBLE || *p == UC_BREAK_MANDATORY) + { + /* An atomic piece of text ends here. */ + if (last_p != NULL && last_column + piece_width > width) + { + /* Insert a line break. */ + *last_p = UC_BREAK_POSSIBLE; + last_column = 0; + } + } + + if (*p == UC_BREAK_MANDATORY) + { + /* uc is a line break character. */ + /* Start a new piece at column 0. */ + last_p = NULL; + last_column = 0; + piece_width = 0; + } + else + { + /* uc is not a line break character. */ + int w; + + if (*p == UC_BREAK_POSSIBLE) + { + /* Start a new piece. */ + last_p = p; + last_column += piece_width; + piece_width = 0; + /* No line break for the moment, may be turned into + UC_BREAK_POSSIBLE later, via last_p. */ + } + + *p = UC_BREAK_PROHIBITED; + + w = uc_width (uc, encoding); + if (w >= 0) /* ignore control characters in the string */ + piece_width += w; + } + + s += count; + p += count; + if (o != NULL) + o += count; + } + + /* The last atomic piece of text ends here. */ + if (last_p != NULL && last_column + piece_width + at_end_columns > width) + { + /* Insert a line break. */ + *last_p = UC_BREAK_POSSIBLE; + last_column = 0; + } + + return last_column + piece_width; +} + + +#ifdef TEST + +#include +#include +#include + +/* Read the contents of an input stream, and return it, terminated with a NUL + byte. */ +char * +read_file (FILE *stream) +{ +#define BUFSIZE 4096 + char *buf = NULL; + int alloc = 0; + int size = 0; + int count; + + while (! feof (stream)) + { + if (size + BUFSIZE > alloc) + { + alloc = alloc + alloc / 2; + if (alloc < size + BUFSIZE) + alloc = size + BUFSIZE; + buf = realloc (buf, alloc); + if (buf == NULL) + { + fprintf (stderr, "out of memory\n"); + exit (1); + } + } + count = fread (buf + size, 1, BUFSIZE, stream); + if (count == 0) + { + if (ferror (stream)) + { + perror ("fread"); + exit (1); + } + } + else + size += count; + } + buf = realloc (buf, size + 1); + if (buf == NULL) + { + fprintf (stderr, "out of memory\n"); + exit (1); + } + buf[size] = '\0'; + return buf; +#undef BUFSIZE +} + +int +main (int argc, char * argv[]) +{ + if (argc == 2) + { + /* Insert line breaks for a given width. */ + int width = atoi (argv[1]); + char *input = read_file (stdin); + int length = strlen (input); + char *breaks = malloc (length); + int i; + + u8_width_linebreaks ((uint8_t *) input, length, width, 0, 0, NULL, "UTF-8", breaks); + + for (i = 0; i < length; i++) + { + switch (breaks[i]) + { + case UC_BREAK_POSSIBLE: + putc ('\n', stdout); + break; + case UC_BREAK_MANDATORY: + break; + case UC_BREAK_PROHIBITED: + break; + default: + abort (); + } + putc (input[i], stdout); + } + + free (breaks); + + return 0; + } + else + return 1; +} + +#endif /* TEST */ diff --git a/gettext-tools/gnulib-lib/unilbrk/ulc-common.c b/gettext-tools/gnulib-lib/unilbrk/ulc-common.c new file mode 100644 index 0000000..b18dfb9 --- /dev/null +++ b/gettext-tools/gnulib-lib/unilbrk/ulc-common.c @@ -0,0 +1,51 @@ +/* Line breaking auxiliary functions. + Copyright (C) 2001-2003, 2006-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2001. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include "unilbrk/ulc-common.h" + +#include "c-ctype.h" +#include "c-strcaseeq.h" + +int +is_utf8_encoding (const char *encoding) +{ + if (STRCASEEQ (encoding, "UTF-8", 'U', 'T', 'F', '-', '8', 0, 0, 0, 0)) + return 1; + return 0; +} + +#if C_CTYPE_ASCII + +/* Tests whether a string is entirely ASCII. Returns 1 if yes. + Returns 0 if the string is in an 8-bit encoding or an ISO-2022 encoding. */ +int +is_all_ascii (const char *s, size_t n) +{ + for (; n > 0; s++, n--) + { + unsigned char c = (unsigned char) *s; + + if (!(c_isprint (c) || c_isspace (c))) + return 0; + } + return 1; +} + +#endif /* C_CTYPE_ASCII */ diff --git a/gettext-tools/gnulib-lib/unilbrk/ulc-common.h b/gettext-tools/gnulib-lib/unilbrk/ulc-common.h new file mode 100644 index 0000000..8e422ea --- /dev/null +++ b/gettext-tools/gnulib-lib/unilbrk/ulc-common.h @@ -0,0 +1,31 @@ +/* Line breaking auxiliary functions. + Copyright (C) 2001-2003, 2006-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2001. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Get size_t. */ +#include + +#include "c-ctype.h" + +#define is_utf8_encoding unilbrk_is_utf8_encoding +extern int is_utf8_encoding (const char *encoding); + +#if C_CTYPE_ASCII + +# define is_all_ascii unilbrk_is_all_ascii +extern int is_all_ascii (const char *s, size_t n); + +#endif /* C_CTYPE_ASCII */ diff --git a/gettext-tools/gnulib-lib/unilbrk/ulc-width-linebreaks.c b/gettext-tools/gnulib-lib/unilbrk/ulc-width-linebreaks.c new file mode 100644 index 0000000..58da133 --- /dev/null +++ b/gettext-tools/gnulib-lib/unilbrk/ulc-width-linebreaks.c @@ -0,0 +1,231 @@ +/* Line breaking of strings. + Copyright (C) 2001-2003, 2006-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2001. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include "unilbrk.h" + +#include +#include + +#include "c-ctype.h" +#include "uniconv.h" +#include "unilbrk/ulc-common.h" + +/* Line breaking of a string in an arbitrary encoding. + + We convert the input string to Unicode. + + The standardized Unicode encodings are UTF-8, UCS-2, UCS-4, UTF-16, + UTF-16BE, UTF-16LE, UTF-7. UCS-2 supports only characters up to + \U0000FFFF. UTF-16 and variants support only characters up to + \U0010FFFF. UTF-7 is way too complex and not supported by glibc-2.1. + UCS-4 specification leaves doubts about endianness and byte order mark. + glibc currently interprets it as big endian without byte order mark, + but this is not backed by an RFC. So we use UTF-8. It supports + characters up to \U7FFFFFFF and is unambiguously defined. */ + +int +ulc_width_linebreaks (const char *s, size_t n, + int width, int start_column, int at_end_columns, + const char *o, const char *encoding, + char *p) +{ + if (n > 0) + { + if (is_utf8_encoding (encoding)) + return u8_width_linebreaks ((const uint8_t *) s, n, width, start_column, at_end_columns, o, encoding, p); + else + { + /* Convert the string to UTF-8 and build a translation table + from offsets into s to offsets into the translated string. */ + size_t *offsets = (size_t *) malloc (n * sizeof (size_t)); + + if (offsets != NULL) + { + uint8_t *t; + size_t m; + + t = u8_conv_from_encoding (encoding, iconveh_question_mark, + s, n, offsets, NULL, &m); + if (t != NULL) + { + char *memory = + (char *) (m > 0 ? malloc (m + (o != NULL ? m : 0)) : NULL); + + if (m == 0 || memory != NULL) + { + char *q = (char *) memory; + char *o8 = (o != NULL ? (char *) (q + m) : NULL); + int res_column; + size_t i; + + /* Translate the overrides to the UTF-8 string. */ + if (o != NULL) + { + memset (o8, UC_BREAK_UNDEFINED, m); + for (i = 0; i < n; i++) + if (offsets[i] != (size_t)(-1)) + o8[offsets[i]] = o[i]; + } + + /* Determine the line breaks of the UTF-8 string. */ + res_column = + u8_width_linebreaks (t, m, width, start_column, at_end_columns, o8, encoding, q); + + /* Translate the result back to the original string. */ + memset (p, UC_BREAK_PROHIBITED, n); + for (i = 0; i < n; i++) + if (offsets[i] != (size_t)(-1)) + p[i] = q[offsets[i]]; + + free (memory); + free (t); + free (offsets); + return res_column; + } + free (t); + } + free (offsets); + } + /* Impossible to convert. */ +#if C_CTYPE_ASCII + if (is_all_ascii (s, n)) + { + /* ASCII is a subset of UTF-8. */ + return u8_width_linebreaks ((const uint8_t *) s, n, width, start_column, at_end_columns, o, encoding, p); + } +#endif + /* We have a non-ASCII string and cannot convert it. + Don't produce line breaks except those already present in the + input string. All we assume here is that the encoding is + minimally ASCII compatible. */ + { + const char *s_end = s + n; + while (s < s_end) + { + *p = ((o != NULL && *o == UC_BREAK_MANDATORY) || *s == '\n' + ? UC_BREAK_MANDATORY + : UC_BREAK_PROHIBITED); + s++; + p++; + if (o != NULL) + o++; + } + /* We cannot compute widths in this case. */ + } + } + } + return start_column; +} + + +#ifdef TEST + +#include +#include + +/* Read the contents of an input stream, and return it, terminated with a NUL + byte. */ +char * +read_file (FILE *stream) +{ +#define BUFSIZE 4096 + char *buf = NULL; + int alloc = 0; + int size = 0; + int count; + + while (! feof (stream)) + { + if (size + BUFSIZE > alloc) + { + alloc = alloc + alloc / 2; + if (alloc < size + BUFSIZE) + alloc = size + BUFSIZE; + buf = realloc (buf, alloc); + if (buf == NULL) + { + fprintf (stderr, "out of memory\n"); + exit (1); + } + } + count = fread (buf + size, 1, BUFSIZE, stream); + if (count == 0) + { + if (ferror (stream)) + { + perror ("fread"); + exit (1); + } + } + else + size += count; + } + buf = realloc (buf, size + 1); + if (buf == NULL) + { + fprintf (stderr, "out of memory\n"); + exit (1); + } + buf[size] = '\0'; + return buf; +#undef BUFSIZE +} + +int +main (int argc, char * argv[]) +{ + setlocale (LC_CTYPE, ""); + if (argc == 2) + { + /* Insert line breaks for a given width. */ + int width = atoi (argv[1]); + char *input = read_file (stdin); + int length = strlen (input); + char *breaks = malloc (length); + int i; + + ulc_width_linebreaks (input, length, width, 0, 0, NULL, locale_charset (), breaks); + + for (i = 0; i < length; i++) + { + switch (breaks[i]) + { + case UC_BREAK_POSSIBLE: + putc ('\n', stdout); + break; + case UC_BREAK_MANDATORY: + break; + case UC_BREAK_PROHIBITED: + break; + default: + abort (); + } + putc (input[i], stdout); + } + + free (breaks); + + return 0; + } + else + return 1; +} + +#endif /* TEST */ diff --git a/gettext-tools/gnulib-lib/uniname.in.h b/gettext-tools/gnulib-lib/uniname.in.h new file mode 100644 index 0000000..d13466a --- /dev/null +++ b/gettext-tools/gnulib-lib/uniname.in.h @@ -0,0 +1,46 @@ +/* Association between Unicode characters and their names. + Copyright (C) 2000-2002, 2005, 2007, 2009-2014 Free Software Foundation, + Inc. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _UNINAME_H +#define _UNINAME_H + +#include "unitypes.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Required size of buffer for a Unicode character name. */ +#define UNINAME_MAX 256 + +/* Looks up the name of a Unicode character, in uppercase ASCII. + Returns the filled buf, or NULL if the character does not have a name. */ +extern char * + unicode_character_name (ucs4_t uc, char *buf); + +/* Looks up the Unicode character with a given name, in upper- or lowercase + ASCII. Returns the character if found, or UNINAME_INVALID if not found. */ +extern ucs4_t + unicode_name_character (const char *name) + _UC_ATTRIBUTE_PURE; +#define UNINAME_INVALID ((ucs4_t) 0xFFFF) + +#ifdef __cplusplus +} +#endif + +#endif /* _UNINAME_H */ diff --git a/gettext-tools/gnulib-lib/uniname/gen-uninames.lisp b/gettext-tools/gnulib-lib/uniname/gen-uninames.lisp new file mode 100755 index 0000000..d08e93f --- /dev/null +++ b/gettext-tools/gnulib-lib/uniname/gen-uninames.lisp @@ -0,0 +1,301 @@ +#!/usr/local/bin/clisp -C + +;;; Creation of gnulib's uninames.h from the UnicodeData.txt table. +;;; Bruno Haible 2000-12-28 + +(defparameter add-comments nil) + +(defstruct unicode-char + (code nil :type integer) + (name nil :type string) + word-indices + word-indices-index +) + +(defstruct word-list + (hashed nil :type hash-table) + (sorted nil :type list) + size ; number of characters total + length ; number of words +) + +(defun main (inputfile outputfile) + (declare (type string inputfile outputfile)) + #+UNICODE (setq *default-file-encoding* charset:utf-8) + (let ((all-chars '())) + ;; Read all characters and names from the input file. + (with-open-file (istream inputfile :direction :input) + (loop + (let ((line (read-line istream nil nil))) + (unless line (return)) + (let* ((i1 (position #\; line)) + (i2 (position #\; line :start (1+ i1))) + (code-string (subseq line 0 i1)) + (code (parse-integer code-string :radix 16)) + (name-string (subseq line (1+ i1) i2))) + ; Ignore characters whose name starts with "<". + (unless (eql (char name-string 0) #\<) + ; Also ignore Hangul syllables; they are treated specially. + (unless (<= #xAC00 code #xD7A3) + ; Also ignore CJK compatibility ideographs; they are treated + ; specially as well. + (unless (or (<= #xF900 code #xFA2D) (<= #xFA30 code #xFA6A) + (<= #xFA70 code #xFAD9) (<= #x2F800 code #x2FA1D)) + ; Transform the code so that it fits in 16 bits. In + ; Unicode 5.1 the following ranges are used. + ; 0x00000..0x04DFF >>12= 0x00..0x04 -> 0x0..0x4 + ; 0x0A000..0x0AAFF >>12= 0x0A -> 0x5 + ; 0x0F900..0x0FFFF >>12= 0x0F -> 0x6 + ; 0x10000..0x10A58 >>12= 0x10 -> 0x7 + ; 0x12000..0x12473 >>12= 0x12 -> 0x8 + ; 0x1D000..0x1D7FF >>12= 0x1D -> 0x9 + ; 0x1F000..0x1F093 >>12= 0x1F -> 0xA + ; 0x2F800..0x2FAFF >>12= 0x2F -> 0xB + ; 0xE0000..0xE00FF >>12= 0xE0 -> 0xC + (flet ((transform (x) + (dpb + (case (ash x -12) + ((#x00 #x01 #x02 #x03 #x04) (ash x -12)) + (#x0A 5) + (#x0F 6) + (#x10 7) + (#x12 8) + (#x1D 9) + (#x1F #xA) + (#x2F #xB) + (#xE0 #xC) + (t (error "Update the transform function for 0x~5,'0X" x)) + ) + (byte 8 12) + x + )) ) + (push (make-unicode-char :code (transform code) + :name name-string) + all-chars + ) ) ) ) ) + ) ) ) ) + (setq all-chars (nreverse all-chars)) + ;; Split into words. + (let ((words-by-length (make-array 0 :adjustable t))) + (dolist (name (list* "HANGUL SYLLABLE" "CJK COMPATIBILITY" (mapcar #'unicode-char-name all-chars))) + (let ((i1 0)) + (loop + (when (>= i1 (length name)) (return)) + (let ((i2 (or (position #\Space name :start i1) (length name)))) + (let* ((word (subseq name i1 i2)) + (len (length word))) + (when (>= len (length words-by-length)) + (adjust-array words-by-length (1+ len)) + ) + (unless (aref words-by-length len) + (setf (aref words-by-length len) + (make-word-list + :hashed (make-hash-table :test #'equal) + :sorted '() + ) ) ) + (let ((word-list (aref words-by-length len))) + (unless (gethash word (word-list-hashed word-list)) + (setf (gethash word (word-list-hashed word-list)) t) + (push word (word-list-sorted word-list)) + ) ) + ) + (setq i1 (1+ i2)) + ) ) ) ) + ;; Sort the word lists. + (dotimes (len (length words-by-length)) + (unless (aref words-by-length len) + (setf (aref words-by-length len) + (make-word-list + :hashed (make-hash-table :test #'equal) + :sorted '() + ) ) ) + (let ((word-list (aref words-by-length len))) + (setf (word-list-sorted word-list) + (sort (word-list-sorted word-list) #'string<) + ) + (setf (word-list-size word-list) + (reduce #'+ (mapcar #'length (word-list-sorted word-list))) + ) + (setf (word-list-length word-list) + (length (word-list-sorted word-list)) + ) ) ) + ;; Output the tables. + (with-open-file (ostream outputfile :direction :output + #+UNICODE :external-format #+UNICODE charset:ascii) + (format ostream "/* DO NOT EDIT! GENERATED AUTOMATICALLY! */~%") + (format ostream "/*~%") + (format ostream " * ~A~%" (file-namestring outputfile)) + (format ostream " *~%") + (format ostream " * Unicode character name table.~%") + (format ostream " * Generated automatically by the gen-uninames utility.~%") + (format ostream " */~%") + (format ostream "~%") + (format ostream "static const char unicode_name_words[~D] = {~%" + (let ((sum 0)) + (dotimes (len (length words-by-length)) + (let ((word-list (aref words-by-length len))) + (incf sum (word-list-size word-list)) + ) ) + sum + ) ) + (dotimes (len (length words-by-length)) + (let ((word-list (aref words-by-length len))) + (dolist (word (word-list-sorted word-list)) + (format ostream " ~{ '~C',~}~%" (coerce word 'list)) + ) ) ) + (format ostream "};~%") + (format ostream "#define UNICODE_CHARNAME_NUM_WORDS ~D~%" + (let ((sum 0)) + (dotimes (len (length words-by-length)) + (let ((word-list (aref words-by-length len))) + (incf sum (word-list-length word-list)) + ) ) + sum + ) ) + #| ; Redundant data + (format ostream "static const uint16_t unicode_name_word_offsets[~D] = {~%" + (let ((sum 0)) + (dotimes (len (length words-by-length)) + (let ((word-list (aref words-by-length len))) + (incf sum (word-list-length word-list)) + ) ) + sum + ) ) + (dotimes (len (length words-by-length)) + (let ((word-list (aref words-by-length len))) + (when (word-list-sorted word-list) + (format ostream " ") + (do ((l (word-list-sorted word-list) (cdr l)) + (offset 0 (+ offset (length (car l))))) + ((endp l)) + (format ostream "~<~% ~0,79:; ~D,~>" offset) + ) + (format ostream "~%") + ) ) ) + (format ostream "};~%") + |# + (format ostream "static const struct { uint16_t extra_offset; uint16_t ind_offset; } unicode_name_by_length[~D] = {~%" + (1+ (length words-by-length)) + ) + (let ((extra-offset 0) + (ind-offset 0)) + (dotimes (len (length words-by-length)) + (let ((word-list (aref words-by-length len))) + (format ostream " { ~D, ~D },~%" extra-offset ind-offset) + (incf extra-offset (word-list-size word-list)) + (incf ind-offset (word-list-length word-list)) + ) ) + (format ostream " { ~D, ~D }~%" extra-offset ind-offset) + ) + (format ostream "};~%") + (let ((ind-offset 0)) + (dotimes (len (length words-by-length)) + (let ((word-list (aref words-by-length len))) + (dolist (word (word-list-sorted word-list)) + (setf (gethash word (word-list-hashed word-list)) ind-offset) + (incf ind-offset) + ) ) ) ) + (dolist (word '("HANGUL" "SYLLABLE" "CJK" "COMPATIBILITY")) + (format ostream "#define UNICODE_CHARNAME_WORD_~A ~D~%" word + (gethash word (word-list-hashed (aref words-by-length (length word)))) + ) ) + ;; Compute the word-indices for every unicode-char. + (dolist (uc all-chars) + (let ((name (unicode-char-name uc)) + (indices '())) + (let ((i1 0)) + (loop + (when (>= i1 (length name)) (return)) + (let ((i2 (or (position #\Space name :start i1) (length name)))) + (let* ((word (subseq name i1 i2)) + (len (length word))) + (push (gethash word (word-list-hashed (aref words-by-length len))) + indices + ) + ) + (setq i1 (1+ i2)) + ) ) ) + (setf (unicode-char-word-indices uc) + (coerce (nreverse indices) 'vector) + ) + ) ) + ;; Sort the list of unicode-chars by word-indices. + (setq all-chars + (sort all-chars + (lambda (vec1 vec2) + (let ((len1 (length vec1)) + (len2 (length vec2))) + (do ((i 0 (1+ i))) + (nil) + (if (< i len2) + (if (< i len1) + (cond ((< (aref vec1 i) (aref vec2 i)) (return t)) + ((> (aref vec1 i) (aref vec2 i)) (return nil)) + ) + (return t) + ) + (return nil) + ) ) ) ) + :key #'unicode-char-word-indices + ) ) + ;; Output the word-indices. + (format ostream "static const uint16_t unicode_names[~D] = {~%" + (reduce #'+ (mapcar (lambda (uc) (length (unicode-char-word-indices uc))) all-chars)) + ) + (let ((i 0)) + (dolist (uc all-chars) + (format ostream " ~{ ~D,~}" + (maplist (lambda (r) (+ (* 2 (car r)) (if (cdr r) 1 0))) + (coerce (unicode-char-word-indices uc) 'list) + ) + ) + (when add-comments + (format ostream "~40T/* ~A */" (unicode-char-name uc)) + ) + (format ostream "~%") + (setf (unicode-char-word-indices-index uc) i) + (incf i (length (unicode-char-word-indices uc))) + ) ) + (format ostream "};~%") + (format ostream "static const struct { uint16_t code; uint32_t name:24; }~%") + (format ostream "#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7)~%__attribute__((__packed__))~%#endif~%") + (format ostream "unicode_name_to_code[~D] = {~%" + (length all-chars) + ) + (dolist (uc all-chars) + (format ostream " { 0x~4,'0X, ~D }," + (unicode-char-code uc) + (unicode-char-word-indices-index uc) + ) + (when add-comments + (format ostream "~21T/* ~A */" (unicode-char-name uc)) + ) + (format ostream "~%") + ) + (format ostream "};~%") + (format ostream "static const struct { uint16_t code; uint32_t name:24; }~%") + (format ostream "#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7)~%__attribute__((__packed__))~%#endif~%") + (format ostream "unicode_code_to_name[~D] = {~%" + (length all-chars) + ) + (dolist (uc (sort (copy-list all-chars) #'< :key #'unicode-char-code)) + (format ostream " { 0x~4,'0X, ~D }," + (unicode-char-code uc) + (unicode-char-word-indices-index uc) + ) + (when add-comments + (format ostream "~21T/* ~A */" (unicode-char-name uc)) + ) + (format ostream "~%") + ) + (format ostream "};~%") + (format ostream "#define UNICODE_CHARNAME_MAX_LENGTH ~D~%" + (reduce #'max (mapcar (lambda (uc) (length (unicode-char-name uc))) all-chars)) + ) + (format ostream "#define UNICODE_CHARNAME_MAX_WORDS ~D~%" + (reduce #'max (mapcar (lambda (uc) (length (unicode-char-word-indices uc))) all-chars)) + ) + ) +) ) ) + +(main (first *args*) (second *args*)) diff --git a/gettext-tools/gnulib-lib/uniname/uniname.c b/gettext-tools/gnulib-lib/uniname/uniname.c new file mode 100644 index 0000000..cf7a939 --- /dev/null +++ b/gettext-tools/gnulib-lib/uniname/uniname.c @@ -0,0 +1,516 @@ +/* Association between Unicode characters and their names. + Copyright (C) 2000-2002, 2005-2007, 2009-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include "uniname.h" + +#include +#include +#include +#include +#include + +#define SIZEOF(a) (sizeof(a) / sizeof(a[0])) + + +/* Table of Unicode character names, derived from UnicodeData.txt. + This table is generated in a way to minimize the memory footprint: + 1. its compiled size is small (less than 350 KB), + 2. it resides entirely in the text or read-only data segment of the + executable or shared library: the table contains only immediate + integers, no pointers, and the functions don't do heap allocation. + */ +#include "uninames.h" +/* It contains: + static const char unicode_name_words[36303] = ...; + #define UNICODE_CHARNAME_NUM_WORDS 6260 + static const struct { uint16_t extra_offset; uint16_t ind_offset; } unicode_name_by_length[26] = ...; + #define UNICODE_CHARNAME_WORD_HANGUL 3902 + #define UNICODE_CHARNAME_WORD_SYLLABLE 4978 + #define UNICODE_CHARNAME_WORD_CJK 417 + #define UNICODE_CHARNAME_WORD_COMPATIBILITY 6107 + static const uint16_t unicode_names[68940] = ...; + static const struct { uint16_t code; uint32_t name:24; } unicode_name_to_code[16626] = ...; + static const struct { uint16_t code; uint32_t name:24; } unicode_code_to_name[16626] = ...; + #define UNICODE_CHARNAME_MAX_LENGTH 83 + #define UNICODE_CHARNAME_MAX_WORDS 13 +*/ + +/* Returns the word with a given index. */ +static const char * +unicode_name_word (unsigned int index, unsigned int *lengthp) +{ + unsigned int i1; + unsigned int i2; + unsigned int i; + + assert (index < UNICODE_CHARNAME_NUM_WORDS); + + /* Binary search for i with + unicode_name_by_length[i].ind_offset <= index + and + index < unicode_name_by_length[i+1].ind_offset + */ + + i1 = 0; + i2 = SIZEOF (unicode_name_by_length) - 1; + while (i2 - i1 > 1) + { + unsigned int i = (i1 + i2) >> 1; + if (unicode_name_by_length[i].ind_offset <= index) + i1 = i; + else + i2 = i; + } + i = i1; + assert (unicode_name_by_length[i].ind_offset <= index + && index < unicode_name_by_length[i+1].ind_offset); + *lengthp = i; + return &unicode_name_words[unicode_name_by_length[i].extra_offset + + (index-unicode_name_by_length[i].ind_offset)*i]; +} + +/* Looks up the index of a word. */ +static int +unicode_name_word_lookup (const char *word, unsigned int length) +{ + if (length > 0 && length < SIZEOF (unicode_name_by_length) - 1) + { + /* Binary search among the words of given length. */ + unsigned int extra_offset = unicode_name_by_length[length].extra_offset; + unsigned int i0 = unicode_name_by_length[length].ind_offset; + unsigned int i1 = i0; + unsigned int i2 = unicode_name_by_length[length+1].ind_offset; + while (i2 - i1 > 0) + { + unsigned int i = (i1 + i2) >> 1; + const char *p = &unicode_name_words[extra_offset + (i-i0)*length]; + const char *w = word; + unsigned int n = length; + for (;;) + { + if (*p < *w) + { + if (i1 == i) + return -1; + /* Note here: i1 < i < i2. */ + i1 = i; + break; + } + if (*p > *w) + { + /* Note here: i1 <= i < i2. */ + i2 = i; + break; + } + p++; w++; n--; + if (n == 0) + return i; + } + } + } + return -1; +} + +/* Auxiliary tables for Hangul syllable names, see the Unicode 3.0 book, + sections 3.11 and 4.4. */ +static const char jamo_initial_short_name[19][3] = +{ + "G", "GG", "N", "D", "DD", "R", "M", "B", "BB", "S", "SS", "", "J", "JJ", + "C", "K", "T", "P", "H" +}; +static const char jamo_medial_short_name[21][4] = +{ + "A", "AE", "YA", "YAE", "EO", "E", "YEO", "YE", "O", "WA", "WAE", "OE", "YO", + "U", "WEO", "WE", "WI", "YU", "EU", "YI", "I" +}; +static const char jamo_final_short_name[28][3] = +{ + "", "G", "GG", "GS", "N", "NI", "NH", "D", "L", "LG", "LM", "LB", "LS", "LT", + "LP", "LH", "M", "B", "BS", "S", "SS", "NG", "J", "C", "K", "T", "P", "H" +}; + +/* Looks up the name of a Unicode character, in uppercase ASCII. + Returns the filled buf, or NULL if the character does not have a name. */ +char * +unicode_character_name (ucs4_t c, char *buf) +{ + if (c >= 0xAC00 && c <= 0xD7A3) + { + /* Special case for Hangul syllables. Keeps the tables small. */ + char *ptr; + unsigned int tmp; + unsigned int index1; + unsigned int index2; + unsigned int index3; + const char *q; + + /* buf needs to have at least 16 + 7 bytes here. */ + memcpy (buf, "HANGUL SYLLABLE ", 16); + ptr = buf + 16; + + tmp = c - 0xAC00; + index3 = tmp % 28; tmp = tmp / 28; + index2 = tmp % 21; tmp = tmp / 21; + index1 = tmp; + + q = jamo_initial_short_name[index1]; + while (*q != '\0') + *ptr++ = *q++; + q = jamo_medial_short_name[index2]; + while (*q != '\0') + *ptr++ = *q++; + q = jamo_final_short_name[index3]; + while (*q != '\0') + *ptr++ = *q++; + *ptr = '\0'; + return buf; + } + else if ((c >= 0xF900 && c <= 0xFA2D) || (c >= 0xFA30 && c <= 0xFA6A) + || (c >= 0xFA70 && c <= 0xFAD9) || (c >= 0x2F800 && c <= 0x2FA1D)) + { + /* Special case for CJK compatibility ideographs. Keeps the tables + small. */ + char *ptr; + int i; + + /* buf needs to have at least 28 + 5 bytes here. */ + memcpy (buf, "CJK COMPATIBILITY IDEOGRAPH-", 28); + ptr = buf + 28; + + for (i = (c < 0x10000 ? 12 : 16); i >= 0; i -= 4) + { + unsigned int x = (c >> i) & 0xf; + *ptr++ = (x < 10 ? '0' : 'A' - 10) + x; + } + *ptr = '\0'; + return buf; + } + else + { + const uint16_t *words; + + /* Transform the code so that it fits in 16 bits. */ + switch (c >> 12) + { + case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: + break; + case 0x0A: + c -= 0x05000; + break; + case 0x0F: + c -= 0x09000; + break; + case 0x10: + c -= 0x09000; + break; + case 0x12: + c -= 0x0A000; + break; + case 0x1D: + c -= 0x14000; + break; + case 0x1F: + c -= 0x15000; + break; + case 0x2F: + c -= 0x24000; + break; + case 0xE0: + c -= 0xD4000; + break; + default: + return NULL; + } + + { + /* Binary search in unicode_code_to_name. */ + unsigned int i1 = 0; + unsigned int i2 = SIZEOF (unicode_code_to_name); + for (;;) + { + unsigned int i = (i1 + i2) >> 1; + if (unicode_code_to_name[i].code == c) + { + words = &unicode_names[unicode_code_to_name[i].name]; + break; + } + else if (unicode_code_to_name[i].code < c) + { + if (i1 == i) + { + words = NULL; + break; + } + /* Note here: i1 < i < i2. */ + i1 = i; + } + else if (unicode_code_to_name[i].code > c) + { + if (i2 == i) + { + words = NULL; + break; + } + /* Note here: i1 <= i < i2. */ + i2 = i; + } + } + } + if (words != NULL) + { + /* Found it in unicode_code_to_name. Now concatenate the words. */ + /* buf needs to have at least UNICODE_CHARNAME_MAX_LENGTH bytes. */ + char *ptr = buf; + for (;;) + { + unsigned int wordlen; + const char *word = unicode_name_word (*words>>1, &wordlen); + do + *ptr++ = *word++; + while (--wordlen > 0); + if ((*words & 1) == 0) + break; + *ptr++ = ' '; + words++; + } + *ptr = '\0'; + return buf; + } + return NULL; + } +} + +/* Looks up the Unicode character with a given name, in upper- or lowercase + ASCII. Returns the character if found, or UNINAME_INVALID if not found. */ +ucs4_t +unicode_name_character (const char *name) +{ + unsigned int len = strlen (name); + if (len > 1 && len <= UNICODE_CHARNAME_MAX_LENGTH) + { + /* Test for "word1 word2 ..." syntax. */ + char buf[UNICODE_CHARNAME_MAX_LENGTH]; + char *ptr = buf; + for (;;) + { + char c = *name++; + if (!(c >= ' ' && c <= '~')) + break; + *ptr++ = (c >= 'a' && c <= 'z' ? c - 'a' + 'A' : c); + if (--len == 0) + goto filled_buf; + } + if (false) + filled_buf: + { + /* Convert the constituents to uint16_t words. */ + uint16_t words[UNICODE_CHARNAME_MAX_WORDS]; + uint16_t *wordptr = words; + { + const char *p1 = buf; + for (;;) + { + { + int word; + const char *p2 = p1; + while (p2 < ptr && *p2 != ' ') + p2++; + word = unicode_name_word_lookup (p1, p2 - p1); + if (word < 0) + break; + if (wordptr == &words[UNICODE_CHARNAME_MAX_WORDS]) + break; + *wordptr++ = word; + if (p2 == ptr) + goto filled_words; + p1 = p2 + 1; + } + /* Special case for Hangul syllables. Keeps the tables small. */ + if (wordptr == &words[2] + && words[0] == UNICODE_CHARNAME_WORD_HANGUL + && words[1] == UNICODE_CHARNAME_WORD_SYLLABLE) + { + /* Split the last word [p1..ptr) into three parts: + 1) [BCDGHJKMNPRST] + 2) [AEIOUWY] + 3) [BCDGHIJKLMNPST] + */ + const char *p2; + const char *p3; + const char *p4; + + p2 = p1; + while (p2 < ptr + && (*p2 == 'B' || *p2 == 'C' || *p2 == 'D' + || *p2 == 'G' || *p2 == 'H' || *p2 == 'J' + || *p2 == 'K' || *p2 == 'M' || *p2 == 'N' + || *p2 == 'P' || *p2 == 'R' || *p2 == 'S' + || *p2 == 'T')) + p2++; + p3 = p2; + while (p3 < ptr + && (*p3 == 'A' || *p3 == 'E' || *p3 == 'I' + || *p3 == 'O' || *p3 == 'U' || *p3 == 'W' + || *p3 == 'Y')) + p3++; + p4 = p3; + while (p4 < ptr + && (*p4 == 'B' || *p4 == 'C' || *p4 == 'D' + || *p4 == 'G' || *p4 == 'H' || *p4 == 'I' + || *p4 == 'J' || *p4 == 'K' || *p4 == 'L' + || *p4 == 'M' || *p4 == 'N' || *p4 == 'P' + || *p4 == 'S' || *p4 == 'T')) + p4++; + if (p4 == ptr) + { + unsigned int n1 = p2 - p1; + unsigned int n2 = p3 - p2; + unsigned int n3 = p4 - p3; + + if (n1 <= 2 && (n2 >= 1 && n2 <= 3) && n3 <= 2) + { + unsigned int index1; + + for (index1 = 0; index1 < 19; index1++) + if (memcmp (jamo_initial_short_name[index1], p1, n1) == 0 + && jamo_initial_short_name[index1][n1] == '\0') + { + unsigned int index2; + + for (index2 = 0; index2 < 21; index2++) + if (memcmp (jamo_medial_short_name[index2], p2, n2) == 0 + && jamo_medial_short_name[index2][n2] == '\0') + { + unsigned int index3; + + for (index3 = 0; index3 < 28; index3++) + if (memcmp (jamo_final_short_name[index3], p3, n3) == 0 + && jamo_final_short_name[index3][n3] == '\0') + { + return 0xAC00 + (index1 * 21 + index2) * 28 + index3; + } + break; + } + break; + } + } + } + } + /* Special case for CJK compatibility ideographs. Keeps the + tables small. */ + if (wordptr == &words[2] + && words[0] == UNICODE_CHARNAME_WORD_CJK + && words[1] == UNICODE_CHARNAME_WORD_COMPATIBILITY + && p1 + 14 <= ptr + && p1 + 15 >= ptr + && memcmp (p1, "IDEOGRAPH-", 10) == 0) + { + const char *p2 = p1 + 10; + + if (*p2 != '0') + { + unsigned int c = 0; + + for (;;) + { + if (*p2 >= '0' && *p2 <= '9') + c += (*p2 - '0'); + else if (*p2 >= 'A' && *p2 <= 'F') + c += (*p2 - 'A' + 10); + else + break; + p2++; + if (p2 == ptr) + { + if ((c >= 0xF900 && c <= 0xFA2D) + || (c >= 0xFA30 && c <= 0xFA6A) + || (c >= 0xFA70 && c <= 0xFAD9) + || (c >= 0x2F800 && c <= 0x2FA1D)) + return c; + else + break; + } + c = c << 4; + } + } + } + } + } + if (false) + filled_words: + { + /* Multiply by 2, to simplify later comparisons. */ + unsigned int words_length = wordptr - words; + { + int i = words_length - 1; + words[i] = 2 * words[i]; + for (; --i >= 0; ) + words[i] = 2 * words[i] + 1; + } + /* Binary search in unicode_name_to_code. */ + { + unsigned int i1 = 0; + unsigned int i2 = SIZEOF (unicode_name_to_code); + for (;;) + { + unsigned int i = (i1 + i2) >> 1; + const uint16_t *w = words; + const uint16_t *p = &unicode_names[unicode_name_to_code[i].name]; + unsigned int n = words_length; + for (;;) + { + if (*p < *w) + { + if (i1 == i) + goto name_not_found; + /* Note here: i1 < i < i2. */ + i1 = i; + break; + } + else if (*p > *w) + { + if (i2 == i) + goto name_not_found; + /* Note here: i1 <= i < i2. */ + i2 = i; + break; + } + p++; w++; n--; + if (n == 0) + { + unsigned int c = unicode_name_to_code[i].code; + + /* Undo the transformation to 16-bit space. */ + static const unsigned int offset[13] = + { + 0x00000, 0x00000, 0x00000, 0x00000, 0x00000, + 0x05000, 0x09000, 0x09000, 0x0A000, 0x14000, + 0x15000, 0x24000, 0xD4000 + }; + return c + offset[c >> 12]; + } + } + } + } + name_not_found: ; + } + } + } + return UNINAME_INVALID; +} diff --git a/gettext-tools/gnulib-lib/uniname/uninames.h b/gettext-tools/gnulib-lib/uniname/uninames.h new file mode 100644 index 0000000..7b6db1f --- /dev/null +++ b/gettext-tools/gnulib-lib/uniname/uninames.h @@ -0,0 +1,61495 @@ +/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ +/* + * uninames.h + * + * Unicode character name table. + * Generated automatically by the gen-uninames utility. + */ + +static const char unicode_name_words[39544] = { + 'A', + 'B', + 'C', + 'D', + 'E', + 'F', + 'G', + 'H', + 'I', + 'J', + 'K', + 'L', + 'M', + 'N', + 'O', + 'P', + 'Q', + 'R', + 'S', + 'T', + 'U', + 'V', + 'W', + 'X', + 'Y', + 'Z', + '-', 'A', + 'A', '2', + 'A', '3', + 'A', 'A', + 'A', 'B', + 'A', 'C', + 'A', 'D', + 'A', 'E', + 'A', 'G', + 'A', 'H', + 'A', 'I', + 'A', 'K', + 'A', 'L', + 'A', 'M', + 'A', 'N', + 'A', 'O', + 'A', 'P', + 'A', 'Q', + 'A', 'S', + 'A', 'T', + 'A', 'U', + 'A', 'V', + 'A', 'X', + 'A', 'Y', + 'B', 'A', + 'B', 'E', + 'B', 'H', + 'B', 'I', + 'B', 'O', + 'B', 'Q', + 'B', 'U', + 'B', 'Y', + 'C', 'A', + 'C', 'C', + 'C', 'D', + 'C', 'E', + 'C', 'H', + 'C', 'I', + 'C', 'M', + 'C', 'O', + 'C', 'U', + 'C', 'Y', + 'D', '2', + 'D', 'A', + 'D', 'B', + 'D', 'E', + 'D', 'I', + 'D', 'L', + 'D', 'M', + 'D', 'O', + 'D', 'U', + 'D', 'V', + 'D', 'Z', + 'E', '2', + 'E', 'A', + 'E', 'E', + 'E', 'F', + 'E', 'H', + 'E', 'I', + 'E', 'K', + 'E', 'L', + 'E', 'M', + 'E', 'N', + 'E', 'O', + 'E', 'P', + 'E', 'R', + 'E', 'S', + 'E', 'T', + 'E', 'U', + 'E', 'V', + 'E', 'W', + 'E', 'X', + 'F', 'A', + 'F', 'E', + 'F', 'F', + 'F', 'I', + 'F', 'L', + 'F', 'M', + 'F', 'O', + 'F', 'U', + 'F', 'Y', + 'G', '2', + 'G', 'A', + 'G', 'B', + 'G', 'E', + 'G', 'G', + 'G', 'I', + 'G', 'N', + 'G', 'O', + 'G', 'U', + 'G', 'V', + 'G', 'Y', + 'H', 'A', + 'H', 'E', + 'H', 'G', + 'H', 'I', + 'H', 'K', + 'H', 'O', + 'H', 'P', + 'H', 'U', + 'H', 'V', + 'H', 'Z', + 'I', 'B', + 'I', 'E', + 'I', 'F', + 'I', 'G', + 'I', 'H', + 'I', 'I', + 'I', 'J', + 'I', 'L', + 'I', 'M', + 'I', 'N', + 'I', 'O', + 'I', 'P', + 'I', 'R', + 'I', 'S', + 'I', 'T', + 'I', 'U', + 'I', 'X', + 'I', 'Y', + 'J', 'A', + 'J', 'E', + 'J', 'I', + 'J', 'O', + 'J', 'U', + 'J', 'Y', + 'K', '2', + 'K', 'A', + 'K', 'B', + 'K', 'E', + 'K', 'G', + 'K', 'I', + 'K', 'K', + 'K', 'L', + 'K', 'M', + 'K', 'O', + 'K', 'T', + 'K', 'U', + 'K', 'V', + 'K', 'W', + 'L', 'A', + 'L', 'D', + 'L', 'E', + 'L', 'H', + 'L', 'I', + 'L', 'J', + 'L', 'L', + 'L', 'M', + 'L', 'N', + 'L', 'O', + 'L', 'S', + 'L', 'U', + 'L', 'V', + 'L', 'X', + 'L', 'Y', + 'L', 'Z', + 'M', 'A', + 'M', 'B', + 'M', 'E', + 'M', 'G', + 'M', 'H', + 'M', 'I', + 'M', 'L', + 'M', 'M', + 'M', 'O', + 'M', 'S', + 'M', 'U', + 'M', 'V', + 'M', 'W', + 'M', 'Y', + 'N', 'A', + 'N', 'D', + 'N', 'E', + 'N', 'F', + 'N', 'G', + 'N', 'H', + 'N', 'I', + 'N', 'J', + 'N', 'M', + 'N', 'N', + 'N', 'O', + 'N', 'S', + 'N', 'U', + 'N', 'V', + 'N', 'W', + 'O', 'A', + 'O', 'B', + 'O', 'E', + 'O', 'F', + 'O', 'H', + 'O', 'I', + 'O', 'L', + 'O', 'M', + 'O', 'N', + 'O', 'O', + 'O', 'P', + 'O', 'R', + 'O', 'S', + 'O', 'T', + 'O', 'U', + 'O', 'V', + 'O', 'W', + 'O', 'X', + 'O', 'Y', + 'P', '2', + 'P', 'A', + 'P', 'C', + 'P', 'D', + 'P', 'E', + 'P', 'F', + 'P', 'G', + 'P', 'H', + 'P', 'I', + 'P', 'M', + 'P', 'O', + 'P', 'R', + 'P', 'S', + 'P', 'U', + 'P', 'V', + 'P', 'W', + 'P', 'Y', + 'P', 'Z', + 'Q', 'A', + 'Q', 'E', + 'Q', 'I', + 'Q', 'O', + 'Q', 'P', + 'Q', 'U', + 'Q', 'Y', + 'R', 'A', + 'R', 'E', + 'R', 'I', + 'R', 'O', + 'R', 'R', + 'R', 'U', + 'R', 'Y', + 'S', 'A', + 'S', 'E', + 'S', 'G', + 'S', 'H', + 'S', 'I', + 'S', 'K', + 'S', 'O', + 'S', 'P', + 'S', 'R', + 'S', 'S', + 'S', 'T', + 'S', 'U', + 'S', 'V', + 'S', 'W', + 'S', 'Y', + 'S', 'Z', + 'T', 'A', + 'T', 'C', + 'T', 'E', + 'T', 'H', + 'T', 'I', + 'T', 'N', + 'T', 'O', + 'T', 'R', + 'T', 'S', + 'T', 'T', + 'T', 'U', + 'T', 'Z', + 'U', '2', + 'U', 'A', + 'U', 'B', + 'U', 'C', + 'U', 'D', + 'U', 'E', + 'U', 'K', + 'U', 'M', + 'U', 'N', + 'U', 'O', + 'U', 'P', + 'U', 'R', + 'U', 'S', + 'U', 'U', + 'U', 'Y', + 'V', 'A', + 'V', 'E', + 'V', 'I', + 'V', 'O', + 'V', 'U', + 'V', 'Y', + 'W', 'A', + 'W', 'B', + 'W', 'E', + 'W', 'G', + 'W', 'I', + 'W', 'O', + 'W', 'U', + 'W', 'V', + 'X', 'A', + 'X', 'E', + 'X', 'G', + 'X', 'I', + 'X', 'O', + 'X', 'U', + 'X', 'Y', + 'Y', 'A', + 'Y', 'E', + 'Y', 'I', + 'Y', 'N', + 'Y', 'O', + 'Y', 'R', + 'Y', 'U', + 'Y', 'V', + 'Y', 'Y', + 'Z', 'A', + 'Z', 'E', + 'Z', 'H', + 'Z', 'I', + 'Z', 'O', + 'Z', 'U', + 'Z', 'Y', + '-', 'U', 'M', + 'A', '-', 'O', + 'A', '-', 'U', + 'A', 'A', 'I', + 'A', 'A', 'J', + 'A', 'A', 'K', + 'A', 'A', 'M', + 'A', 'A', 'W', + 'A', 'A', 'Y', + 'A', 'B', '2', + 'A', 'D', 'I', + 'A', 'D', 'O', + 'A', 'G', 'E', + 'A', 'I', 'N', + 'A', 'I', 'R', + 'A', 'L', 'F', + 'A', 'L', 'I', + 'A', 'L', 'L', + 'A', 'N', 'D', + 'A', 'N', 'G', + 'A', 'N', 'N', + 'A', 'N', 'O', + 'A', 'P', 'L', + 'A', 'R', 'C', + 'A', 'R', 'E', + 'A', 'R', 'M', + 'A', 'S', 'H', + 'A', 'U', 'E', + 'A', 'W', 'E', + 'A', 'X', 'E', + 'A', 'Y', 'B', + 'A', 'Z', 'U', + 'B', 'A', 'A', + 'B', 'A', 'D', + 'B', 'A', 'G', + 'B', 'A', 'L', + 'B', 'A', 'N', + 'B', 'A', 'P', + 'B', 'A', 'R', + 'B', 'A', 'T', + 'B', 'A', 'X', + 'B', 'B', 'A', + 'B', 'B', 'E', + 'B', 'B', 'I', + 'B', 'B', 'O', + 'B', 'B', 'U', + 'B', 'B', 'Y', + 'B', 'E', 'E', + 'B', 'E', 'H', + 'B', 'E', 'I', + 'B', 'E', 'N', + 'B', 'E', 'P', + 'B', 'E', 'T', + 'B', 'E', 'X', + 'B', 'H', 'A', + 'B', 'H', 'E', + 'B', 'H', 'I', + 'B', 'H', 'O', + 'B', 'H', 'U', + 'B', 'I', 'B', + 'B', 'I', 'E', + 'B', 'I', 'G', + 'B', 'I', 'P', + 'B', 'I', 'T', + 'B', 'I', 'X', + 'B', 'L', 'A', + 'B', 'O', 'A', + 'B', 'O', 'O', + 'B', 'O', 'P', + 'B', 'O', 'T', + 'B', 'O', 'W', + 'B', 'O', 'X', + 'B', 'U', 'O', + 'B', 'U', 'P', + 'B', 'U', 'R', + 'B', 'U', 'T', + 'B', 'U', 'X', + 'B', 'W', 'A', + 'B', 'W', 'E', + 'B', 'W', 'I', + 'B', 'X', 'G', + 'B', 'Y', 'P', + 'B', 'Y', 'R', + 'B', 'Y', 'T', + 'B', 'Y', 'X', + 'C', 'A', 'A', + 'C', 'A', 'L', + 'C', 'A', 'N', + 'C', 'A', 'P', + 'C', 'A', 'T', + 'C', 'A', 'X', + 'C', 'C', 'A', + 'C', 'C', 'E', + 'C', 'C', 'I', + 'C', 'C', 'O', + 'C', 'C', 'U', + 'C', 'E', 'E', + 'C', 'E', 'N', + 'C', 'E', 'P', + 'C', 'E', 'X', + 'C', 'H', 'A', + 'C', 'H', 'E', + 'C', 'H', 'I', + 'C', 'H', 'O', + 'C', 'H', 'U', + 'C', 'H', 'Y', + 'C', 'I', 'E', + 'C', 'I', 'I', + 'C', 'I', 'L', + 'C', 'I', 'P', + 'C', 'I', 'T', + 'C', 'I', 'X', + 'C', 'J', 'K', + 'C', 'O', 'A', + 'C', 'O', 'N', + 'C', 'O', 'O', + 'C', 'O', 'P', + 'C', 'O', 'T', + 'C', 'O', 'W', + 'C', 'O', 'X', + 'C', 'U', 'M', + 'C', 'U', 'O', + 'C', 'U', 'P', + 'C', 'U', 'R', + 'C', 'U', 'T', + 'C', 'U', 'X', + 'C', 'W', 'A', + 'C', 'W', 'E', + 'C', 'W', 'I', + 'C', 'W', 'O', + 'C', 'Y', 'A', + 'C', 'Y', 'P', + 'C', 'Y', 'R', + 'C', 'Y', 'T', + 'C', 'Y', 'X', + 'D', 'A', 'A', + 'D', 'A', 'D', + 'D', 'A', 'G', + 'D', 'A', 'L', + 'D', 'A', 'M', + 'D', 'A', 'P', + 'D', 'A', 'R', + 'D', 'A', 'T', + 'D', 'A', 'X', + 'D', 'A', 'Y', + 'D', 'D', 'A', + 'D', 'D', 'E', + 'D', 'D', 'I', + 'D', 'D', 'O', + 'D', 'D', 'U', + 'D', 'E', 'E', + 'D', 'E', 'I', + 'D', 'E', 'K', + 'D', 'E', 'L', + 'D', 'E', 'P', + 'D', 'E', 'X', + 'D', 'H', 'A', + 'D', 'H', 'E', + 'D', 'H', 'I', + 'D', 'H', 'O', + 'D', 'H', 'U', + 'D', 'I', 'B', + 'D', 'I', 'E', + 'D', 'I', 'M', + 'D', 'I', 'N', + 'D', 'I', 'P', + 'D', 'I', 'T', + 'D', 'I', 'X', + 'D', 'J', 'A', + 'D', 'J', 'E', + 'D', 'L', 'A', + 'D', 'L', 'E', + 'D', 'L', 'I', + 'D', 'L', 'O', + 'D', 'L', 'U', + 'D', 'O', 'A', + 'D', 'O', 'G', + 'D', 'O', 'N', + 'D', 'O', 'O', + 'D', 'O', 'P', + 'D', 'O', 'T', + 'D', 'O', 'X', + 'D', 'R', 'Y', + 'D', 'U', 'B', + 'D', 'U', 'G', + 'D', 'U', 'H', + 'D', 'U', 'L', + 'D', 'U', 'M', + 'D', 'U', 'N', + 'D', 'U', 'O', + 'D', 'U', 'P', + 'D', 'U', 'R', + 'D', 'U', 'T', + 'D', 'U', 'X', + 'D', 'W', 'A', + 'D', 'W', 'E', + 'D', 'W', 'O', + 'D', 'Y', 'O', + 'D', 'Z', 'A', + 'D', 'Z', 'E', + 'D', 'Z', 'I', + 'D', 'Z', 'O', + 'D', 'Z', 'U', + 'E', 'A', 'R', + 'E', 'A', 'T', + 'E', 'C', 'H', + 'E', 'D', 'D', + 'E', 'E', 'N', + 'E', 'G', 'G', + 'E', 'I', 'E', + 'E', 'I', 'S', + 'E', 'K', 'S', + 'E', 'N', 'D', + 'E', 'N', 'G', + 'E', 'N', 'N', + 'E', 'O', 'H', + 'E', 'R', 'A', + 'E', 'R', 'G', + 'E', 'R', 'R', + 'E', 'R', 'S', + 'E', 'S', 'H', + 'E', 'S', 'O', + 'E', 'T', 'A', + 'E', 'T', 'H', + 'E', 'W', 'E', + 'E', 'X', 'O', + 'E', 'Y', 'E', + 'E', 'Z', 'H', + 'F', 'A', 'A', + 'F', 'A', 'N', + 'F', 'A', 'P', + 'F', 'A', 'T', + 'F', 'A', 'X', + 'F', 'E', 'E', + 'F', 'E', 'H', + 'F', 'E', 'I', + 'F', 'F', 'I', + 'F', 'F', 'L', + 'F', 'I', 'I', + 'F', 'I', 'P', + 'F', 'I', 'T', + 'F', 'I', 'X', + 'F', 'L', 'A', + 'F', 'L', 'Y', + 'F', 'O', 'O', + 'F', 'O', 'P', + 'F', 'O', 'R', + 'F', 'O', 'X', + 'F', 'U', 'P', + 'F', 'U', 'R', + 'F', 'U', 'T', + 'F', 'U', 'X', + 'F', 'W', 'A', + 'F', 'W', 'E', + 'F', 'W', 'I', + 'F', 'Y', 'A', + 'F', 'Y', 'P', + 'F', 'Y', 'T', + 'F', 'Y', 'X', + 'G', 'A', '2', + 'G', 'A', 'A', + 'G', 'A', 'D', + 'G', 'A', 'F', + 'G', 'A', 'G', + 'G', 'A', 'L', + 'G', 'A', 'M', + 'G', 'A', 'N', + 'G', 'A', 'P', + 'G', 'A', 'R', + 'G', 'A', 'T', + 'G', 'A', 'X', + 'G', 'A', 'Y', + 'G', 'B', 'A', + 'G', 'B', 'E', + 'G', 'B', 'I', + 'G', 'B', 'O', + 'G', 'B', 'U', + 'G', 'E', 'E', + 'G', 'E', 'N', + 'G', 'E', 'P', + 'G', 'E', 'R', + 'G', 'E', 'T', + 'G', 'E', 'X', + 'G', 'G', 'A', + 'G', 'G', 'E', + 'G', 'G', 'I', + 'G', 'G', 'O', + 'G', 'G', 'U', + 'G', 'H', 'A', + 'G', 'H', 'E', + 'G', 'H', 'I', + 'G', 'H', 'O', + 'G', 'H', 'U', + 'G', 'H', 'Z', + 'G', 'I', '4', + 'G', 'I', 'E', + 'G', 'I', 'M', + 'G', 'I', 'P', + 'G', 'I', 'T', + 'G', 'I', 'X', + 'G', 'J', 'E', + 'G', 'L', 'A', + 'G', 'O', 'A', + 'G', 'O', 'O', + 'G', 'O', 'P', + 'G', 'O', 'T', + 'G', 'O', 'X', + 'G', 'P', 'A', + 'G', 'R', 'U', + 'G', 'U', '2', + 'G', 'U', 'D', + 'G', 'U', 'G', + 'G', 'U', 'L', + 'G', 'U', 'M', + 'G', 'U', 'O', + 'G', 'U', 'P', + 'G', 'U', 'R', + 'G', 'U', 'T', + 'G', 'U', 'X', + 'G', 'W', 'A', + 'G', 'W', 'E', + 'G', 'W', 'I', + 'G', 'Y', 'A', + 'G', 'Y', 'E', + 'G', 'Y', 'I', + 'G', 'Y', 'O', + 'G', 'Y', 'U', + 'H', 'A', 'A', + 'H', 'A', 'E', + 'H', 'A', 'H', + 'H', 'A', 'L', + 'H', 'A', 'N', + 'H', 'A', 'P', + 'H', 'A', 'R', + 'H', 'A', 'T', + 'H', 'A', 'X', + 'H', 'E', 'E', + 'H', 'E', 'H', + 'H', 'E', 'I', + 'H', 'E', 'N', + 'H', 'E', 'P', + 'H', 'E', 'T', + 'H', 'E', 'X', + 'H', 'H', 'A', + 'H', 'H', 'E', + 'H', 'H', 'I', + 'H', 'H', 'O', + 'H', 'H', 'U', + 'H', 'I', 'E', + 'H', 'I', 'I', + 'H', 'I', 'N', + 'H', 'I', 'P', + 'H', 'I', 'T', + 'H', 'L', 'A', + 'H', 'L', 'E', + 'H', 'L', 'I', + 'H', 'L', 'O', + 'H', 'L', 'U', + 'H', 'L', 'Y', + 'H', 'M', 'A', + 'H', 'M', 'I', + 'H', 'M', 'O', + 'H', 'M', 'U', + 'H', 'M', 'Y', + 'H', 'N', 'A', + 'H', 'N', 'E', + 'H', 'N', 'I', + 'H', 'O', 'A', + 'H', 'O', 'E', + 'H', 'O', 'N', + 'H', 'O', 'O', + 'H', 'O', 'P', + 'H', 'O', 'T', + 'H', 'O', 'X', + 'H', 'P', 'A', + 'H', 'T', 'A', + 'H', 'U', 'N', + 'H', 'U', 'O', + 'H', 'W', 'A', + 'H', 'W', 'E', + 'H', 'W', 'I', + 'H', 'W', 'O', + 'H', 'W', 'U', + 'H', 'X', 'A', + 'H', 'X', 'E', + 'H', 'X', 'I', + 'H', 'X', 'O', + 'H', 'Z', 'G', + 'H', 'Z', 'T', + 'H', 'Z', 'W', + 'H', 'Z', 'Z', + 'I', '-', 'A', + 'I', '-', 'O', + 'I', '-', 'U', + 'I', 'A', 'N', + 'I', 'C', 'E', + 'I', 'E', 'P', + 'I', 'E', 'T', + 'I', 'E', 'X', + 'I', 'G', 'I', + 'I', 'L', '2', + 'I', 'N', 'G', + 'I', 'N', 'I', + 'I', 'N', 'N', + 'I', 'N', 'Y', + 'I', 'O', 'R', + 'I', 'R', 'I', + 'I', 'S', 'H', + 'I', 'S', 'S', + 'J', 'A', 'A', + 'J', 'A', 'R', + 'J', 'E', 'E', + 'J', 'E', 'H', + 'J', 'E', 'R', + 'J', 'H', 'A', + 'J', 'H', 'O', + 'J', 'I', 'A', + 'J', 'I', 'E', + 'J', 'I', 'L', + 'J', 'I', 'P', + 'J', 'I', 'T', + 'J', 'I', 'X', + 'J', 'J', 'A', + 'J', 'J', 'E', + 'J', 'J', 'I', + 'J', 'J', 'O', + 'J', 'J', 'U', + 'J', 'J', 'Y', + 'J', 'O', 'A', + 'J', 'O', 'O', + 'J', 'O', 'P', + 'J', 'O', 'T', + 'J', 'O', 'X', + 'J', 'O', 'Y', + 'J', 'U', 'O', + 'J', 'U', 'P', + 'J', 'U', 'R', + 'J', 'U', 'T', + 'J', 'U', 'X', + 'J', 'W', 'A', + 'J', 'Y', 'P', + 'J', 'Y', 'R', + 'J', 'Y', 'T', + 'J', 'Y', 'X', + 'K', 'A', '2', + 'K', 'A', 'A', + 'K', 'A', 'B', + 'K', 'A', 'F', + 'K', 'A', 'H', + 'K', 'A', 'I', + 'K', 'A', 'K', + 'K', 'A', 'L', + 'K', 'A', 'N', + 'K', 'A', 'P', + 'K', 'A', 'T', + 'K', 'A', 'X', + 'K', 'A', 'Y', + 'K', 'E', 'E', + 'K', 'E', 'H', + 'K', 'E', 'N', + 'K', 'E', 'P', + 'K', 'E', 'T', + 'K', 'E', 'X', + 'K', 'E', 'Y', + 'K', 'H', 'A', + 'K', 'H', 'E', + 'K', 'H', 'I', + 'K', 'H', 'O', + 'K', 'H', 'U', + 'K', 'H', 'Z', + 'K', 'I', 'D', + 'K', 'I', 'E', + 'K', 'I', 'H', + 'K', 'I', 'I', + 'K', 'I', 'N', + 'K', 'I', 'P', + 'K', 'I', 'T', + 'K', 'I', 'X', + 'K', 'J', 'E', + 'K', 'K', 'A', + 'K', 'K', 'E', + 'K', 'K', 'I', + 'K', 'K', 'O', + 'K', 'K', 'U', + 'K', 'L', 'A', + 'K', 'O', 'A', + 'K', 'O', 'H', + 'K', 'O', 'N', + 'K', 'O', 'O', + 'K', 'O', 'P', + 'K', 'O', 'T', + 'K', 'O', 'X', + 'K', 'P', 'A', + 'K', 'P', 'E', + 'K', 'P', 'I', + 'K', 'P', 'O', + 'K', 'P', 'U', + 'K', 'R', 'A', + 'K', 'S', 'I', + 'K', 'U', '3', + 'K', 'U', '4', + 'K', 'U', '7', + 'K', 'U', 'L', + 'K', 'U', 'N', + 'K', 'U', 'O', + 'K', 'U', 'P', + 'K', 'U', 'R', + 'K', 'U', 'T', + 'K', 'U', 'X', + 'K', 'V', 'A', + 'K', 'W', 'A', + 'K', 'W', 'E', + 'K', 'W', 'I', + 'K', 'W', 'O', + 'K', 'X', 'A', + 'K', 'X', 'E', + 'K', 'X', 'I', + 'K', 'X', 'O', + 'K', 'X', 'U', + 'K', 'Y', 'A', + 'K', 'Y', 'E', + 'K', 'Y', 'I', + 'K', 'Y', 'O', + 'K', 'Y', 'U', + 'L', 'A', 'A', + 'L', 'A', 'E', + 'L', 'A', 'L', + 'L', 'A', 'M', + 'L', 'A', 'O', + 'L', 'A', 'P', + 'L', 'A', 'S', + 'L', 'A', 'T', + 'L', 'A', 'W', + 'L', 'A', 'X', + 'L', 'C', 'E', + 'L', 'C', 'I', + 'L', 'D', '2', + 'L', 'E', 'E', + 'L', 'E', 'G', + 'L', 'E', 'K', + 'L', 'E', 'O', + 'L', 'E', 'P', + 'L', 'E', 'X', + 'L', 'H', 'A', + 'L', 'H', 'E', + 'L', 'H', 'I', + 'L', 'H', 'O', + 'L', 'H', 'U', + 'L', 'I', 'D', + 'L', 'I', 'E', + 'L', 'I', 'I', + 'L', 'I', 'L', + 'L', 'I', 'P', + 'L', 'I', 'T', + 'L', 'I', 'X', + 'L', 'J', 'E', + 'L', 'L', 'A', + 'L', 'O', 'A', + 'L', 'O', 'G', + 'L', 'O', 'O', + 'L', 'O', 'P', + 'L', 'O', 'T', + 'L', 'O', 'W', + 'L', 'O', 'X', + 'L', 'U', '2', + 'L', 'U', '3', + 'L', 'U', 'E', + 'L', 'U', 'H', + 'L', 'U', 'L', + 'L', 'U', 'M', + 'L', 'U', 'O', + 'L', 'U', 'P', + 'L', 'U', 'R', + 'L', 'U', 'T', + 'L', 'U', 'X', + 'L', 'W', 'A', + 'L', 'W', 'E', + 'L', 'W', 'I', + 'L', 'W', 'O', + 'L', 'Y', 'P', + 'L', 'Y', 'R', + 'L', 'Y', 'T', + 'L', 'Y', 'X', + 'L', 'Y', 'Y', + 'M', 'A', '2', + 'M', 'A', 'A', + 'M', 'A', 'H', + 'M', 'A', 'I', + 'M', 'A', 'N', + 'M', 'A', 'P', + 'M', 'A', 'R', + 'M', 'A', 'T', + 'M', 'A', 'X', + 'M', 'A', 'Y', + 'M', 'B', '2', + 'M', 'B', '3', + 'M', 'B', '4', + 'M', 'B', 'A', + 'M', 'B', 'E', + 'M', 'B', 'I', + 'M', 'B', 'O', + 'M', 'B', 'U', + 'M', 'E', 'D', + 'M', 'E', 'E', + 'M', 'E', 'M', + 'M', 'E', 'N', + 'M', 'E', 'S', + 'M', 'E', 'X', + 'M', 'G', 'A', + 'M', 'G', 'E', + 'M', 'G', 'O', + 'M', 'G', 'U', + 'M', 'H', 'Z', + 'M', 'I', 'D', + 'M', 'I', 'E', + 'M', 'I', 'G', + 'M', 'I', 'I', + 'M', 'I', 'L', + 'M', 'I', 'M', + 'M', 'I', 'N', + 'M', 'I', 'P', + 'M', 'I', 'T', + 'M', 'I', 'X', + 'M', 'L', 'A', + 'M', 'O', 'A', + 'M', 'O', 'L', + 'M', 'O', 'N', + 'M', 'O', 'O', + 'M', 'O', 'P', + 'M', 'O', 'T', + 'M', 'O', 'X', + 'M', 'P', 'A', + 'M', 'U', 'E', + 'M', 'U', 'G', + 'M', 'U', 'M', + 'M', 'U', 'O', + 'M', 'U', 'P', + 'M', 'U', 'R', + 'M', 'U', 'T', + 'M', 'U', 'X', + 'M', 'W', 'A', + 'M', 'W', 'E', + 'M', 'W', 'I', + 'M', 'W', 'O', + 'M', 'Y', 'A', + 'M', 'Y', 'P', + 'M', 'Y', 'T', + 'M', 'Y', 'X', + 'N', 'A', '2', + 'N', 'A', 'A', + 'N', 'A', 'G', + 'N', 'A', 'H', + 'N', 'A', 'M', + 'N', 'A', 'P', + 'N', 'A', 'R', + 'N', 'A', 'X', + 'N', 'B', 'A', + 'N', 'B', 'I', + 'N', 'B', 'O', + 'N', 'B', 'U', + 'N', 'B', 'Y', + 'N', 'D', 'A', + 'N', 'D', 'E', + 'N', 'D', 'I', + 'N', 'D', 'O', + 'N', 'D', 'U', + 'N', 'E', 'E', + 'N', 'E', 'N', + 'N', 'E', 'O', + 'N', 'E', 'P', + 'N', 'E', 'T', + 'N', 'E', 'W', + 'N', 'E', 'X', + 'N', 'G', 'A', + 'N', 'G', 'E', + 'N', 'G', 'G', + 'N', 'G', 'I', + 'N', 'G', 'O', + 'N', 'G', 'U', + 'N', 'H', 'A', + 'N', 'I', '2', + 'N', 'I', 'A', + 'N', 'I', 'B', + 'N', 'I', 'E', + 'N', 'I', 'I', + 'N', 'I', 'M', + 'N', 'I', 'P', + 'N', 'I', 'T', + 'N', 'I', 'X', + 'N', 'J', 'A', + 'N', 'J', 'E', + 'N', 'J', 'I', + 'N', 'J', 'O', + 'N', 'J', 'U', + 'N', 'J', 'Y', + 'N', 'K', 'O', + 'N', 'N', 'A', + 'N', 'N', 'G', + 'N', 'N', 'O', + 'N', 'O', 'A', + 'N', 'O', 'O', + 'N', 'O', 'P', + 'N', 'O', 'R', + 'N', 'O', 'T', + 'N', 'O', 'W', + 'N', 'O', 'X', + 'N', 'R', 'A', + 'N', 'R', 'E', + 'N', 'R', 'O', + 'N', 'R', 'U', + 'N', 'R', 'Y', + 'N', 'U', 'E', + 'N', 'U', 'M', + 'N', 'U', 'N', + 'N', 'U', 'O', + 'N', 'U', 'P', + 'N', 'U', 'R', + 'N', 'U', 'T', + 'N', 'U', 'X', + 'N', 'W', 'A', + 'N', 'W', 'E', + 'N', 'Y', 'A', + 'N', 'Y', 'D', + 'N', 'Y', 'E', + 'N', 'Y', 'I', + 'N', 'Y', 'O', + 'N', 'Y', 'U', + 'N', 'Z', 'A', + 'N', 'Z', 'E', + 'N', 'Z', 'I', + 'N', 'Z', 'U', + 'N', 'Z', 'Y', + 'O', '-', 'E', + 'O', '-', 'O', + 'O', '-', 'U', + 'O', 'A', 'K', + 'O', 'A', 'Y', + 'O', 'C', 'R', + 'O', 'D', 'D', + 'O', 'H', 'M', + 'O', 'I', 'L', + 'O', 'L', 'D', + 'O', 'L', 'E', + 'O', 'N', 'E', + 'O', 'N', 'G', + 'O', 'N', 'N', + 'O', 'N', 'U', + 'O', 'O', 'N', + 'O', 'O', 'U', + 'O', 'T', 'T', + 'O', 'T', 'U', + 'O', 'U', 'T', + 'P', 'A', 'A', + 'P', 'A', 'D', + 'P', 'A', 'N', + 'P', 'A', 'P', + 'P', 'A', 'R', + 'P', 'A', 'T', + 'P', 'A', 'W', + 'P', 'A', 'X', + 'P', 'E', 'E', + 'P', 'E', 'H', + 'P', 'E', 'R', + 'P', 'E', 'S', + 'P', 'H', 'A', + 'P', 'H', 'E', + 'P', 'H', 'I', + 'P', 'H', 'O', + 'P', 'H', 'U', + 'P', 'I', 'E', + 'P', 'I', 'G', + 'P', 'I', 'I', + 'P', 'I', 'P', + 'P', 'I', 'T', + 'P', 'I', 'X', + 'P', 'L', 'A', + 'P', 'O', 'A', + 'P', 'O', 'O', + 'P', 'O', 'P', + 'P', 'O', 'T', + 'P', 'O', 'X', + 'P', 'P', 'A', + 'P', 'P', 'M', + 'P', 'S', 'I', + 'P', 'T', 'E', + 'P', 'U', '2', + 'P', 'U', 'O', + 'P', 'U', 'P', + 'P', 'U', 'R', + 'P', 'U', 'T', + 'P', 'U', 'X', + 'P', 'W', 'A', + 'P', 'W', 'E', + 'P', 'W', 'I', + 'P', 'W', 'O', + 'P', 'Y', 'P', + 'P', 'Y', 'R', + 'P', 'Y', 'T', + 'P', 'Y', 'X', + 'Q', 'A', 'A', + 'Q', 'A', 'F', + 'Q', 'A', 'I', + 'Q', 'A', 'Q', + 'Q', 'A', 'R', + 'Q', 'A', 'U', + 'Q', 'E', 'E', + 'Q', 'H', 'A', + 'Q', 'H', 'E', + 'Q', 'H', 'I', + 'Q', 'H', 'O', + 'Q', 'H', 'U', + 'Q', 'I', 'E', + 'Q', 'I', 'I', + 'Q', 'I', 'P', + 'Q', 'I', 'T', + 'Q', 'I', 'X', + 'Q', 'O', 'A', + 'Q', 'O', 'F', + 'Q', 'O', 'O', + 'Q', 'O', 'P', + 'Q', 'O', 'T', + 'Q', 'O', 'X', + 'Q', 'U', 'A', + 'Q', 'U', 'E', + 'Q', 'U', 'I', + 'Q', 'U', 'K', + 'Q', 'U', 'O', + 'Q', 'U', 'P', + 'Q', 'U', 'R', + 'Q', 'U', 'T', + 'Q', 'U', 'U', + 'Q', 'U', 'V', + 'Q', 'U', 'X', + 'Q', 'W', 'A', + 'Q', 'W', 'E', + 'Q', 'W', 'I', + 'Q', 'Y', 'A', + 'Q', 'Y', 'E', + 'Q', 'Y', 'I', + 'Q', 'Y', 'O', + 'Q', 'Y', 'P', + 'Q', 'Y', 'R', + 'Q', 'Y', 'T', + 'Q', 'Y', 'U', + 'Q', 'Y', 'X', + 'R', 'A', '2', + 'R', 'A', '3', + 'R', 'A', 'A', + 'R', 'A', 'B', + 'R', 'A', 'D', + 'R', 'A', 'E', + 'R', 'A', 'M', + 'R', 'A', 'N', + 'R', 'A', 'P', + 'R', 'A', 'T', + 'R', 'A', 'X', + 'R', 'A', 'Y', + 'R', 'D', 'O', + 'R', 'E', 'D', + 'R', 'E', 'E', + 'R', 'E', 'H', + 'R', 'E', 'P', + 'R', 'E', 'X', + 'R', 'H', 'A', + 'R', 'H', 'O', + 'R', 'I', 'I', + 'R', 'I', 'N', + 'R', 'I', 'P', + 'R', 'J', 'E', + 'R', 'O', '2', + 'R', 'O', 'A', + 'R', 'O', 'C', + 'R', 'O', 'D', + 'R', 'O', 'O', + 'R', 'O', 'P', + 'R', 'O', 'T', + 'R', 'O', 'X', + 'R', 'R', 'A', + 'R', 'R', 'E', + 'R', 'R', 'O', + 'R', 'R', 'U', + 'R', 'R', 'Y', + 'R', 'U', 'A', + 'R', 'U', 'B', + 'R', 'U', 'M', + 'R', 'U', 'N', + 'R', 'U', 'O', + 'R', 'U', 'P', + 'R', 'U', 'R', + 'R', 'U', 'T', + 'R', 'U', 'X', + 'R', 'W', 'A', + 'R', 'Y', 'A', + 'R', 'Y', 'P', + 'R', 'Y', 'R', + 'R', 'Y', 'T', + 'R', 'Y', 'X', + 'R', 'Y', 'Y', + 'S', '-', 'W', + 'S', 'A', 'A', + 'S', 'A', 'D', + 'S', 'A', 'G', + 'S', 'A', 'L', + 'S', 'A', 'N', + 'S', 'A', 'P', + 'S', 'A', 'R', + 'S', 'A', 'T', + 'S', 'A', 'W', + 'S', 'A', 'X', + 'S', 'A', 'Y', + 'S', 'E', 'E', + 'S', 'E', 'H', + 'S', 'E', 'P', + 'S', 'E', 'T', + 'S', 'E', 'X', + 'S', 'H', '2', + 'S', 'H', 'A', + 'S', 'H', 'E', + 'S', 'H', 'I', + 'S', 'H', 'O', + 'S', 'H', 'U', + 'S', 'H', 'Y', + 'S', 'I', 'E', + 'S', 'I', 'G', + 'S', 'I', 'I', + 'S', 'I', 'N', + 'S', 'I', 'P', + 'S', 'I', 'T', + 'S', 'I', 'X', + 'S', 'J', 'E', + 'S', 'K', 'W', + 'S', 'N', 'A', + 'S', 'O', 'A', + 'S', 'O', 'F', + 'S', 'O', 'N', + 'S', 'O', 'O', + 'S', 'O', 'P', + 'S', 'O', 'T', + 'S', 'O', 'U', + 'S', 'O', 'W', + 'S', 'O', 'X', + 'S', 'S', 'A', + 'S', 'S', 'E', + 'S', 'S', 'I', + 'S', 'S', 'O', + 'S', 'S', 'U', + 'S', 'S', 'Y', + 'S', 'T', '2', + 'S', 'U', 'A', + 'S', 'U', 'D', + 'S', 'U', 'M', + 'S', 'U', 'N', + 'S', 'U', 'O', + 'S', 'U', 'P', + 'S', 'U', 'R', + 'S', 'U', 'T', + 'S', 'U', 'X', + 'S', 'W', 'A', + 'S', 'W', 'E', + 'S', 'W', 'G', + 'S', 'W', 'I', + 'S', 'W', 'O', + 'S', 'W', 'Z', + 'S', 'Y', 'A', + 'S', 'Y', 'P', + 'S', 'Y', 'R', + 'S', 'Y', 'T', + 'S', 'Y', 'X', + 'S', 'Z', 'A', + 'S', 'Z', 'E', + 'S', 'Z', 'I', + 'S', 'Z', 'O', + 'S', 'Z', 'U', + 'S', 'Z', 'Z', + 'T', 'A', '2', + 'T', 'A', 'A', + 'T', 'A', 'B', + 'T', 'A', 'G', + 'T', 'A', 'H', + 'T', 'A', 'I', + 'T', 'A', 'K', + 'T', 'A', 'M', + 'T', 'A', 'N', + 'T', 'A', 'O', + 'T', 'A', 'P', + 'T', 'A', 'R', + 'T', 'A', 'T', + 'T', 'A', 'U', + 'T', 'A', 'V', + 'T', 'A', 'W', + 'T', 'A', 'X', + 'T', 'E', 'E', + 'T', 'E', 'H', + 'T', 'E', 'N', + 'T', 'E', 'P', + 'T', 'E', 'T', + 'T', 'E', 'X', + 'T', 'H', 'A', + 'T', 'H', 'E', + 'T', 'H', 'I', + 'T', 'H', 'O', + 'T', 'H', 'U', + 'T', 'H', 'Z', + 'T', 'I', 'E', + 'T', 'I', 'I', + 'T', 'I', 'L', + 'T', 'I', 'P', + 'T', 'I', 'R', + 'T', 'I', 'T', + 'T', 'I', 'X', + 'T', 'J', 'E', + 'T', 'L', 'A', + 'T', 'L', 'E', + 'T', 'L', 'I', + 'T', 'L', 'O', + 'T', 'L', 'U', + 'T', 'L', 'V', + 'T', 'O', 'A', + 'T', 'O', 'N', + 'T', 'O', 'O', + 'T', 'O', 'P', + 'T', 'O', 'T', + 'T', 'O', 'X', + 'T', 'R', 'I', + 'T', 'S', 'A', + 'T', 'S', 'E', + 'T', 'S', 'I', + 'T', 'S', 'O', + 'T', 'S', 'U', + 'T', 'S', 'V', + 'T', 'T', '2', + 'T', 'T', 'A', + 'T', 'T', 'E', + 'T', 'T', 'H', + 'T', 'T', 'I', + 'T', 'T', 'O', + 'T', 'T', 'U', + 'T', 'U', 'K', + 'T', 'U', 'M', + 'T', 'U', 'O', + 'T', 'U', 'P', + 'T', 'U', 'R', + 'T', 'U', 'T', + 'T', 'U', 'X', + 'T', 'W', 'A', + 'T', 'W', 'E', + 'T', 'W', 'I', + 'T', 'W', 'O', + 'T', 'Y', 'A', + 'T', 'Y', 'E', + 'T', 'Y', 'I', + 'T', 'Y', 'O', + 'T', 'Y', 'R', + 'T', 'Z', 'A', + 'T', 'Z', 'E', + 'T', 'Z', 'I', + 'T', 'Z', 'O', + 'T', 'Z', 'U', + 'U', '-', 'A', + 'U', '-', 'U', + 'U', 'E', 'E', + 'U', 'E', 'Y', + 'U', 'K', 'U', + 'U', 'L', 'U', + 'U', 'N', 'A', + 'U', 'N', 'N', + 'U', 'O', 'N', + 'U', 'O', 'P', + 'U', 'O', 'X', + 'U', 'R', '2', + 'U', 'R', '4', + 'U', 'R', 'A', + 'U', 'R', 'I', + 'U', 'R', 'N', + 'U', 'R', 'U', + 'U', 'S', 'E', + 'U', 'S', 'H', + 'U', 'U', 'U', + 'U', 'Z', '3', + 'U', 'Z', 'U', + 'V', 'A', 'A', + 'V', 'A', 'I', + 'V', 'A', 'P', + 'V', 'A', 'T', + 'V', 'A', 'V', + 'V', 'A', 'X', + 'V', 'E', 'E', + 'V', 'E', 'H', + 'V', 'E', 'P', + 'V', 'E', 'W', + 'V', 'E', 'X', + 'V', 'I', 'E', + 'V', 'I', 'N', + 'V', 'I', 'P', + 'V', 'I', 'T', + 'V', 'I', 'X', + 'V', 'O', 'O', + 'V', 'O', 'P', + 'V', 'O', 'T', + 'V', 'O', 'U', + 'V', 'O', 'W', + 'V', 'O', 'X', + 'V', 'U', 'P', + 'V', 'U', 'R', + 'V', 'U', 'T', + 'V', 'U', 'X', + 'V', 'W', 'A', + 'V', 'Y', 'P', + 'V', 'Y', 'R', + 'V', 'Y', 'T', + 'V', 'Y', 'X', + 'W', 'A', 'A', + 'W', 'A', 'E', + 'W', 'A', 'N', + 'W', 'A', 'P', + 'W', 'A', 'T', + 'W', 'A', 'U', + 'W', 'A', 'W', + 'W', 'A', 'X', + 'W', 'E', 'E', + 'W', 'E', 'N', + 'W', 'E', 'O', + 'W', 'E', 'P', + 'W', 'E', 'X', + 'W', 'I', 'I', + 'W', 'I', 'N', + 'W', 'O', 'A', + 'W', 'O', 'E', + 'W', 'O', 'N', + 'W', 'O', 'O', + 'W', 'O', 'P', + 'W', 'O', 'X', + 'W', 'U', 'N', + 'W', 'U', 'O', + 'X', 'A', 'A', + 'X', 'A', 'N', + 'X', 'E', 'E', + 'X', 'E', 'H', + 'X', 'I', 'E', + 'X', 'I', 'P', + 'X', 'I', 'T', + 'X', 'I', 'X', + 'X', 'O', 'A', + 'X', 'O', 'P', + 'X', 'O', 'R', + 'X', 'O', 'T', + 'X', 'O', 'X', + 'X', 'U', 'O', + 'X', 'V', 'A', + 'X', 'W', 'A', + 'X', 'W', 'E', + 'X', 'W', 'I', + 'X', 'Y', 'A', + 'X', 'Y', 'E', + 'X', 'Y', 'I', + 'X', 'Y', 'O', + 'X', 'Y', 'P', + 'X', 'Y', 'R', + 'X', 'Y', 'T', + 'X', 'Y', 'U', + 'X', 'Y', 'X', + 'Y', 'A', 'A', + 'Y', 'A', 'B', + 'Y', 'A', 'D', + 'Y', 'A', 'E', + 'Y', 'A', 'F', + 'Y', 'A', 'G', + 'Y', 'A', 'H', + 'Y', 'A', 'J', + 'Y', 'A', 'K', + 'Y', 'A', 'L', + 'Y', 'A', 'M', + 'Y', 'A', 'N', + 'Y', 'A', 'P', + 'Y', 'A', 'Q', + 'Y', 'A', 'R', + 'Y', 'A', 'S', + 'Y', 'A', 'T', + 'Y', 'A', 'V', + 'Y', 'A', 'W', + 'Y', 'A', 'Y', + 'Y', 'A', 'Z', + 'Y', 'E', 'A', + 'Y', 'E', 'E', + 'Y', 'E', 'H', + 'Y', 'E', 'N', + 'Y', 'E', 'O', + 'Y', 'E', 'R', + 'Y', 'E', 'W', + 'Y', 'E', 'Y', + 'Y', 'I', 'E', + 'Y', 'I', 'G', + 'Y', 'I', 'I', + 'Y', 'I', 'N', + 'Y', 'I', 'P', + 'Y', 'I', 'T', + 'Y', 'I', 'X', + 'Y', 'O', 'A', + 'Y', 'O', 'D', + 'Y', 'O', 'O', + 'Y', 'O', 'P', + 'Y', 'O', 'T', + 'Y', 'O', 'X', + 'Y', 'U', 'O', + 'Y', 'U', 'P', + 'Y', 'U', 'R', + 'Y', 'U', 'S', + 'Y', 'U', 'T', + 'Y', 'U', 'X', + 'Y', 'W', 'A', + 'Y', 'W', 'E', + 'Y', 'W', 'I', + 'Y', 'W', 'O', + 'Y', 'Y', 'A', + 'Y', 'Y', 'P', + 'Y', 'Y', 'R', + 'Y', 'Y', 'T', + 'Y', 'Y', 'X', + 'Z', 'A', 'A', + 'Z', 'A', 'G', + 'Z', 'A', 'H', + 'Z', 'A', 'I', + 'Z', 'A', 'L', + 'Z', 'A', 'P', + 'Z', 'A', 'T', + 'Z', 'A', 'X', + 'Z', 'E', '2', + 'Z', 'E', 'E', + 'Z', 'E', 'N', + 'Z', 'E', 'P', + 'Z', 'E', 'X', + 'Z', 'H', 'A', + 'Z', 'H', 'E', + 'Z', 'H', 'I', + 'Z', 'H', 'O', + 'Z', 'H', 'U', + 'Z', 'H', 'Y', + 'Z', 'I', '3', + 'Z', 'I', 'B', + 'Z', 'I', 'E', + 'Z', 'I', 'G', + 'Z', 'I', 'P', + 'Z', 'I', 'T', + 'Z', 'I', 'X', + 'Z', 'J', 'E', + 'Z', 'L', 'A', + 'Z', 'O', 'A', + 'Z', 'O', 'O', + 'Z', 'O', 'P', + 'Z', 'O', 'T', + 'Z', 'O', 'X', + 'Z', 'R', 'A', + 'Z', 'U', '5', + 'Z', 'U', 'M', + 'Z', 'U', 'O', + 'Z', 'U', 'P', + 'Z', 'U', 'R', + 'Z', 'U', 'T', + 'Z', 'U', 'X', + 'Z', 'W', 'A', + 'Z', 'Y', 'P', + 'Z', 'Y', 'R', + 'Z', 'Y', 'T', + 'Z', 'Y', 'X', + 'Z', 'Z', 'A', + 'Z', 'Z', 'E', + 'Z', 'Z', 'I', + 'Z', 'Z', 'O', + 'Z', 'Z', 'U', + 'Z', 'Z', 'Y', + 'A', 'A', 'R', 'U', + 'A', 'D', 'A', 'K', + 'A', 'D', 'E', 'G', + 'A', 'E', 'S', 'C', + 'A', 'H', 'A', 'D', + 'A', 'H', 'S', 'A', + 'A', 'I', 'L', 'M', + 'A', 'I', 'N', 'N', + 'A', 'I', 'N', 'U', + 'A', 'L', 'A', 'N', + 'A', 'L', 'E', 'F', + 'A', 'L', 'F', 'A', + 'A', 'L', 'L', 'I', + 'A', 'L', 'L', 'O', + 'A', 'L', 'P', 'A', + 'A', 'L', 'T', 'A', + 'A', 'M', 'A', 'R', + 'A', 'M', 'B', 'A', + 'A', 'M', 'P', 'S', + 'A', 'N', 'H', 'U', + 'A', 'N', 'K', 'H', + 'A', 'P', 'I', 'N', + 'A', 'P', 'L', 'I', + 'A', 'R', 'A', 'D', + 'A', 'R', 'C', 'H', + 'A', 'R', 'G', 'I', + 'A', 'R', 'M', 'Y', + 'A', 'S', 'A', 'T', + 'A', 'S', 'H', '2', + 'A', 'S', 'H', '9', + 'A', 'T', 'O', 'M', + 'A', 'U', 'N', 'N', + 'A', 'Y', 'A', 'H', + 'A', 'Y', 'E', 'R', + 'A', 'Y', 'I', 'N', + 'B', '0', '0', '1', + 'B', '0', '0', '2', + 'B', '0', '0', '3', + 'B', '0', '0', '4', + 'B', '0', '0', '5', + 'B', '0', '0', '6', + 'B', '0', '0', '7', + 'B', '0', '0', '8', + 'B', '0', '0', '9', + 'B', '0', '1', '0', + 'B', '0', '1', '1', + 'B', '0', '1', '2', + 'B', '0', '1', '3', + 'B', '0', '1', '4', + 'B', '0', '1', '5', + 'B', '0', '1', '6', + 'B', '0', '1', '7', + 'B', '0', '1', '8', + 'B', '0', '1', '9', + 'B', '0', '2', '0', + 'B', '0', '2', '1', + 'B', '0', '2', '2', + 'B', '0', '2', '3', + 'B', '0', '2', '4', + 'B', '0', '2', '5', + 'B', '0', '2', '6', + 'B', '0', '2', '7', + 'B', '0', '2', '8', + 'B', '0', '2', '9', + 'B', '0', '3', '0', + 'B', '0', '3', '1', + 'B', '0', '3', '2', + 'B', '0', '3', '3', + 'B', '0', '3', '4', + 'B', '0', '3', '6', + 'B', '0', '3', '7', + 'B', '0', '3', '8', + 'B', '0', '3', '9', + 'B', '0', '4', '0', + 'B', '0', '4', '1', + 'B', '0', '4', '2', + 'B', '0', '4', '3', + 'B', '0', '4', '4', + 'B', '0', '4', '5', + 'B', '0', '4', '6', + 'B', '0', '4', '7', + 'B', '0', '4', '8', + 'B', '0', '4', '9', + 'B', '0', '5', '0', + 'B', '0', '5', '1', + 'B', '0', '5', '2', + 'B', '0', '5', '3', + 'B', '0', '5', '4', + 'B', '0', '5', '5', + 'B', '0', '5', '6', + 'B', '0', '5', '7', + 'B', '0', '5', '8', + 'B', '0', '5', '9', + 'B', '0', '6', '0', + 'B', '0', '6', '1', + 'B', '0', '6', '2', + 'B', '0', '6', '3', + 'B', '0', '6', '4', + 'B', '0', '6', '5', + 'B', '0', '6', '6', + 'B', '0', '6', '7', + 'B', '0', '6', '8', + 'B', '0', '6', '9', + 'B', '0', '7', '0', + 'B', '0', '7', '1', + 'B', '0', '7', '2', + 'B', '0', '7', '3', + 'B', '0', '7', '4', + 'B', '0', '7', '5', + 'B', '0', '7', '6', + 'B', '0', '7', '7', + 'B', '0', '7', '8', + 'B', '0', '7', '9', + 'B', '0', '8', '0', + 'B', '0', '8', '1', + 'B', '0', '8', '2', + 'B', '0', '8', '3', + 'B', '0', '8', '5', + 'B', '0', '8', '6', + 'B', '0', '8', '7', + 'B', '0', '8', '9', + 'B', '0', '9', '0', + 'B', '0', '9', '1', + 'B', '1', '0', '0', + 'B', '1', '0', '2', + 'B', '1', '0', '4', + 'B', '1', '0', '5', + 'B', '1', '2', '0', + 'B', '1', '2', '1', + 'B', '1', '2', '2', + 'B', '1', '2', '3', + 'B', '1', '2', '5', + 'B', '1', '2', '7', + 'B', '1', '2', '8', + 'B', '1', '3', '0', + 'B', '1', '3', '1', + 'B', '1', '3', '2', + 'B', '1', '3', '3', + 'B', '1', '3', '5', + 'B', '1', '4', '0', + 'B', '1', '4', '1', + 'B', '1', '4', '2', + 'B', '1', '4', '5', + 'B', '1', '4', '6', + 'B', '1', '5', '0', + 'B', '1', '5', '1', + 'B', '1', '5', '2', + 'B', '1', '5', '3', + 'B', '1', '5', '4', + 'B', '1', '5', '5', + 'B', '1', '5', '6', + 'B', '1', '5', '7', + 'B', '1', '5', '8', + 'B', '1', '5', '9', + 'B', '1', '6', '0', + 'B', '1', '6', '1', + 'B', '1', '6', '2', + 'B', '1', '6', '3', + 'B', '1', '6', '4', + 'B', '1', '6', '5', + 'B', '1', '6', '6', + 'B', '1', '6', '7', + 'B', '1', '6', '8', + 'B', '1', '6', '9', + 'B', '1', '7', '0', + 'B', '1', '7', '1', + 'B', '1', '7', '2', + 'B', '1', '7', '3', + 'B', '1', '7', '4', + 'B', '1', '7', '6', + 'B', '1', '7', '7', + 'B', '1', '7', '8', + 'B', '1', '7', '9', + 'B', '1', '8', '0', + 'B', '1', '8', '1', + 'B', '1', '8', '2', + 'B', '1', '8', '3', + 'B', '1', '8', '4', + 'B', '1', '8', '5', + 'B', '1', '8', '9', + 'B', '1', '9', '0', + 'B', '1', '9', '1', + 'B', '2', '0', '0', + 'B', '2', '0', '1', + 'B', '2', '0', '2', + 'B', '2', '0', '3', + 'B', '2', '0', '4', + 'B', '2', '0', '5', + 'B', '2', '0', '6', + 'B', '2', '0', '7', + 'B', '2', '0', '8', + 'B', '2', '0', '9', + 'B', '2', '1', '0', + 'B', '2', '1', '1', + 'B', '2', '1', '2', + 'B', '2', '1', '3', + 'B', '2', '1', '4', + 'B', '2', '1', '5', + 'B', '2', '1', '6', + 'B', '2', '1', '7', + 'B', '2', '1', '8', + 'B', '2', '1', '9', + 'B', '2', '2', '0', + 'B', '2', '2', '1', + 'B', '2', '2', '2', + 'B', '2', '2', '5', + 'B', '2', '2', '6', + 'B', '2', '2', '7', + 'B', '2', '2', '8', + 'B', '2', '2', '9', + 'B', '2', '3', '0', + 'B', '2', '3', '1', + 'B', '2', '3', '2', + 'B', '2', '3', '3', + 'B', '2', '3', '4', + 'B', '2', '3', '6', + 'B', '2', '4', '0', + 'B', '2', '4', '1', + 'B', '2', '4', '2', + 'B', '2', '4', '3', + 'B', '2', '4', '5', + 'B', '2', '4', '6', + 'B', '2', '4', '7', + 'B', '2', '4', '8', + 'B', '2', '4', '9', + 'B', '2', '5', '0', + 'B', '2', '5', '1', + 'B', '2', '5', '2', + 'B', '2', '5', '3', + 'B', '2', '5', '4', + 'B', '2', '5', '5', + 'B', '2', '5', '6', + 'B', '2', '5', '7', + 'B', '2', '5', '8', + 'B', '2', '5', '9', + 'B', '3', '0', '5', + 'B', 'A', 'C', 'K', + 'B', 'A', 'G', '3', + 'B', 'A', 'G', 'A', + 'B', 'A', 'H', 'T', + 'B', 'A', 'N', '2', + 'B', 'A', 'N', 'D', + 'B', 'A', 'N', 'G', + 'B', 'A', 'N', 'K', + 'B', 'A', 'R', 'B', + 'B', 'A', 'R', 'S', + 'B', 'A', 'S', 'E', + 'B', 'B', 'A', 'P', + 'B', 'B', 'A', 'T', + 'B', 'B', 'A', 'X', + 'B', 'B', 'E', 'P', + 'B', 'B', 'E', 'X', + 'B', 'B', 'I', 'E', + 'B', 'B', 'I', 'P', + 'B', 'B', 'I', 'T', + 'B', 'B', 'I', 'X', + 'B', 'B', 'O', 'P', + 'B', 'B', 'O', 'T', + 'B', 'B', 'O', 'X', + 'B', 'B', 'U', 'O', + 'B', 'B', 'U', 'P', + 'B', 'B', 'U', 'R', + 'B', 'B', 'U', 'T', + 'B', 'B', 'U', 'X', + 'B', 'B', 'Y', 'P', + 'B', 'B', 'Y', 'T', + 'B', 'B', 'Y', 'X', + 'B', 'C', 'A', 'D', + 'B', 'E', 'A', 'M', + 'B', 'E', 'A', 'N', + 'B', 'E', 'A', 'T', + 'B', 'E', 'E', 'H', + 'B', 'E', 'L', 'L', + 'B', 'E', 'L', 'T', + 'B', 'E', 'N', 'D', + 'B', 'E', 'T', 'A', + 'B', 'E', 'T', 'H', + 'B', 'H', 'E', 'E', + 'B', 'H', 'O', 'O', + 'B', 'I', 'E', 'P', + 'B', 'I', 'E', 'T', + 'B', 'I', 'E', 'X', + 'B', 'I', 'R', 'D', + 'B', 'I', 'R', 'U', + 'B', 'K', 'A', '-', + 'B', 'L', 'U', 'E', + 'B', 'O', 'A', 'R', + 'B', 'O', 'A', 'T', + 'B', 'O', 'D', 'Y', + 'B', 'O', 'L', 'D', + 'B', 'O', 'L', 'T', + 'B', 'O', 'N', 'E', + 'B', 'R', 'D', 'A', + 'B', 'U', 'K', 'Y', + 'B', 'U', 'L', 'L', + 'B', 'U', 'O', 'N', + 'B', 'U', 'O', 'P', + 'B', 'U', 'O', 'X', + 'B', 'U', 'R', '2', + 'B', 'U', 'R', 'U', + 'B', 'U', 'R', 'X', + 'B', 'W', 'E', 'E', + 'B', 'Y', 'R', 'X', + 'B', 'Z', 'H', 'I', + 'C', '-', '1', '8', + 'C', '-', '3', '9', + 'C', 'A', 'A', 'I', + 'C', 'A', 'D', 'A', + 'C', 'A', 'L', 'C', + 'C', 'A', 'L', 'L', + 'C', 'A', 'N', 'G', + 'C', 'A', 'P', 'O', + 'C', 'A', 'R', 'E', + 'C', 'A', 'R', 'T', + 'C', 'A', 'V', 'E', + 'C', 'A', 'Y', 'N', + 'C', 'C', 'A', 'A', + 'C', 'C', 'E', 'E', + 'C', 'C', 'H', 'A', + 'C', 'C', 'H', 'E', + 'C', 'C', 'H', 'I', + 'C', 'C', 'H', 'O', + 'C', 'C', 'H', 'U', + 'C', 'E', 'D', 'I', + 'C', 'E', 'N', 'T', + 'C', 'H', 'A', 'A', + 'C', 'H', 'A', 'D', + 'C', 'H', 'A', 'M', + 'C', 'H', 'A', 'N', + 'C', 'H', 'A', 'P', + 'C', 'H', 'A', 'R', + 'C', 'H', 'A', 'T', + 'C', 'H', 'A', 'X', + 'C', 'H', 'E', 'E', + 'C', 'H', 'E', 'H', + 'C', 'H', 'E', 'N', + 'C', 'H', 'E', 'P', + 'C', 'H', 'E', 'T', + 'C', 'H', 'E', 'X', + 'C', 'H', 'H', 'A', + 'C', 'H', 'I', 'N', + 'C', 'H', 'O', 'A', + 'C', 'H', 'O', 'E', + 'C', 'H', 'O', 'P', + 'C', 'H', 'O', 'T', + 'C', 'H', 'O', 'X', + 'C', 'H', 'U', 'O', + 'C', 'H', 'U', 'P', + 'C', 'H', 'U', 'R', + 'C', 'H', 'U', 'X', + 'C', 'H', 'W', 'A', + 'C', 'H', 'Y', 'P', + 'C', 'H', 'Y', 'R', + 'C', 'H', 'Y', 'T', + 'C', 'H', 'Y', 'X', + 'C', 'I', 'E', 'P', + 'C', 'I', 'E', 'T', + 'C', 'I', 'E', 'X', + 'C', 'I', 'T', 'Y', + 'C', 'L', 'A', 'N', + 'C', 'L', 'A', 'W', + 'C', 'L', 'E', 'F', + 'C', 'L', 'U', 'B', + 'C', 'O', 'D', 'A', + 'C', 'O', 'L', 'L', + 'C', 'O', 'M', 'B', + 'C', 'O', 'P', 'Y', + 'C', 'R', 'O', 'P', + 'C', 'U', 'B', 'E', + 'C', 'U', 'O', 'P', + 'C', 'U', 'O', 'X', + 'C', 'U', 'R', 'L', + 'C', 'U', 'R', 'X', + 'C', 'W', 'A', 'A', + 'C', 'W', 'I', 'I', + 'C', 'W', 'O', 'O', + 'C', 'Y', 'R', 'X', + 'D', 'A', 'E', 'G', + 'D', 'A', 'G', 'S', + 'D', 'A', 'I', 'R', + 'D', 'A', 'M', 'P', + 'D', 'A', 'N', 'G', + 'D', 'A', 'R', 'K', + 'D', 'A', 'R', 'T', + 'D', 'A', 'S', 'H', + 'D', 'A', 'T', 'A', + 'D', 'A', 'T', 'E', + 'D', 'D', 'A', 'A', + 'D', 'D', 'A', 'L', + 'D', 'D', 'A', 'P', + 'D', 'D', 'A', 'T', + 'D', 'D', 'A', 'X', + 'D', 'D', 'D', 'A', + 'D', 'D', 'E', 'E', + 'D', 'D', 'E', 'P', + 'D', 'D', 'E', 'X', + 'D', 'D', 'H', 'A', + 'D', 'D', 'H', 'O', + 'D', 'D', 'I', 'E', + 'D', 'D', 'I', 'P', + 'D', 'D', 'I', 'T', + 'D', 'D', 'I', 'X', + 'D', 'D', 'O', 'A', + 'D', 'D', 'O', 'P', + 'D', 'D', 'O', 'T', + 'D', 'D', 'O', 'X', + 'D', 'D', 'U', 'O', + 'D', 'D', 'U', 'P', + 'D', 'D', 'U', 'R', + 'D', 'D', 'U', 'T', + 'D', 'D', 'U', 'X', + 'D', 'D', 'W', 'A', + 'D', 'E', 'A', 'D', + 'D', 'E', 'E', 'L', + 'D', 'E', 'E', 'R', + 'D', 'E', 'H', 'I', + 'D', 'E', 'K', 'A', + 'D', 'E', 'L', 'T', + 'D', 'E', 'N', 'G', + 'D', 'E', 'S', 'I', + 'D', 'E', 'Z', 'H', + 'D', 'H', 'A', 'L', + 'D', 'H', 'E', 'E', + 'D', 'H', 'H', 'A', + 'D', 'H', 'H', 'E', + 'D', 'H', 'H', 'I', + 'D', 'H', 'H', 'O', + 'D', 'H', 'H', 'U', + 'D', 'H', 'O', 'O', + 'D', 'I', 'E', 'P', + 'D', 'I', 'E', 'X', + 'D', 'I', 'G', 'A', + 'D', 'I', 'M', '2', + 'D', 'I', 'N', 'G', + 'D', 'I', 'S', 'C', + 'D', 'I', 'S', 'H', + 'D', 'K', 'A', 'R', + 'D', 'L', 'E', 'E', + 'D', 'O', '-', 'O', + 'D', 'O', 'E', 'S', + 'D', 'O', 'I', 'T', + 'D', 'O', 'N', 'G', + 'D', 'O', 'O', 'R', + 'D', 'O', 'R', 'U', + 'D', 'O', 'T', 'S', + 'D', 'O', 'V', 'E', + 'D', 'O', 'W', 'N', + 'D', 'R', 'I', 'L', + 'D', 'R', 'U', 'M', + 'D', 'U', 'B', '2', + 'D', 'U', 'N', '3', + 'D', 'U', 'N', '4', + 'D', 'U', 'N', 'G', + 'D', 'U', 'O', 'X', + 'D', 'U', 'R', '2', + 'D', 'U', 'R', 'X', + 'D', 'Y', 'E', 'H', + 'D', 'Z', 'E', 'E', + 'D', 'Z', 'H', 'A', + 'D', 'Z', 'H', 'E', + 'D', 'Z', 'J', 'E', + 'D', 'Z', 'W', 'E', + 'D', 'Z', 'Z', 'E', + 'E', 'A', 'S', 'E', + 'E', 'A', 'S', 'T', + 'E', 'D', 'I', 'N', + 'E', 'G', 'I', 'R', + 'E', 'N', 'O', 'S', + 'E', 'O', '-', 'O', + 'E', 'O', '-', 'U', + 'E', 'R', 'E', 'N', + 'E', 'S', 'H', '2', + 'E', 'U', '-', 'U', + 'E', 'U', 'R', 'O', + 'E', 'V', 'E', 'N', + 'E', 'Z', 'E', 'N', + 'F', 'A', 'A', 'I', + 'F', 'A', 'C', 'E', + 'F', 'A', 'N', 'G', + 'F', 'E', 'E', 'D', + 'F', 'E', 'H', 'U', + 'F', 'E', 'N', 'G', + 'F', 'E', 'O', 'H', + 'F', 'I', 'L', 'E', + 'F', 'I', 'L', 'L', + 'F', 'I', 'R', 'E', + 'F', 'I', 'S', 'H', + 'F', 'I', 'T', 'A', + 'F', 'I', 'V', 'E', + 'F', 'L', 'A', 'G', + 'F', 'L', 'A', 'T', + 'F', 'L', 'I', 'P', + 'F', 'O', 'O', 'T', + 'F', 'O', 'R', 'K', + 'F', 'O', 'R', 'M', + 'F', 'O', 'U', 'R', + 'F', 'R', 'E', 'E', + 'F', 'R', 'O', 'G', + 'F', 'R', 'O', 'M', + 'F', 'U', 'L', 'L', + 'F', 'U', 'R', 'X', + 'F', 'U', 'S', 'A', + 'F', 'U', 'S', 'E', + 'F', 'W', 'A', 'A', + 'F', 'W', 'E', 'E', + 'G', 'A', 'B', 'A', + 'G', 'A', 'L', 'I', + 'G', 'A', 'M', 'L', + 'G', 'A', 'N', '2', + 'G', 'A', 'R', '3', + 'G', 'A', 'T', 'E', + 'G', 'B', 'E', 'E', + 'G', 'B', 'E', 'N', + 'G', 'B', 'O', 'N', + 'G', 'B', 'O', 'O', + 'G', 'C', 'A', 'N', + 'G', 'C', 'I', 'G', + 'G', 'D', 'A', 'N', + 'G', 'E', 'A', 'R', + 'G', 'E', 'B', 'A', + 'G', 'E', 'B', 'O', + 'G', 'E', 'D', 'E', + 'G', 'E', 'T', 'A', + 'G', 'G', 'A', 'A', + 'G', 'G', 'A', 'P', + 'G', 'G', 'A', 'T', + 'G', 'G', 'A', 'X', + 'G', 'G', 'E', 'E', + 'G', 'G', 'E', 'P', + 'G', 'G', 'E', 'T', + 'G', 'G', 'E', 'X', + 'G', 'G', 'I', 'E', + 'G', 'G', 'I', 'T', + 'G', 'G', 'I', 'X', + 'G', 'G', 'O', 'P', + 'G', 'G', 'O', 'T', + 'G', 'G', 'O', 'X', + 'G', 'G', 'U', 'O', + 'G', 'G', 'U', 'P', + 'G', 'G', 'U', 'R', + 'G', 'G', 'U', 'T', + 'G', 'G', 'U', 'X', + 'G', 'G', 'W', 'A', + 'G', 'G', 'W', 'E', + 'G', 'G', 'W', 'I', + 'G', 'H', 'A', 'D', + 'G', 'H', 'A', 'N', + 'G', 'H', 'E', 'E', + 'G', 'H', 'H', 'A', + 'G', 'H', 'W', 'A', + 'G', 'I', 'B', 'A', + 'G', 'I', 'E', 'P', + 'G', 'I', 'E', 'T', + 'G', 'I', 'E', 'X', + 'G', 'I', 'G', 'A', + 'G', 'I', 'R', '2', + 'G', 'I', 'R', '3', + 'G', 'I', 'S', 'H', + 'G', 'O', 'A', 'L', + 'G', 'O', 'L', 'D', + 'G', 'O', 'N', 'G', + 'G', 'O', 'R', 'A', + 'G', 'O', 'R', 'T', + 'G', 'R', 'A', 'M', + 'G', 'S', 'U', 'M', + 'G', 'T', 'E', 'R', + 'G', 'U', 'E', 'H', + 'G', 'U', 'N', 'U', + 'G', 'U', 'O', 'P', + 'G', 'U', 'O', 'T', + 'G', 'U', 'O', 'X', + 'G', 'U', 'R', '7', + 'G', 'U', 'R', 'X', + 'G', 'W', 'A', 'A', + 'G', 'W', 'E', 'E', + 'G', 'Y', 'A', 'A', + 'G', 'Y', 'A', 'S', + 'G', 'Y', 'E', 'E', + 'G', 'Y', 'F', 'U', + 'G', 'Y', 'O', 'N', + 'H', 'A', 'G', 'L', + 'H', 'A', 'I', 'R', + 'H', 'A', 'L', 'F', + 'H', 'A', 'N', 'D', + 'H', 'A', 'R', 'D', + 'H', 'A', 'T', 'E', + 'H', 'A', 'V', 'E', + 'H', 'E', 'A', 'D', + 'H', 'E', 'L', 'M', + 'H', 'E', 'M', 'P', + 'H', 'E', 'N', 'G', + 'H', 'E', 'R', 'U', + 'H', 'E', 'T', 'A', + 'H', 'E', 'T', 'H', + 'H', 'H', 'A', 'A', + 'H', 'H', 'E', 'E', + 'H', 'H', 'W', 'A', + 'H', 'I', 'D', 'E', + 'H', 'I', 'E', 'X', + 'H', 'I', 'G', 'H', + 'H', 'I', 'Z', 'B', + 'H', 'L', 'A', 'P', + 'H', 'L', 'A', 'T', + 'H', 'L', 'A', 'X', + 'H', 'L', 'E', 'P', + 'H', 'L', 'E', 'X', + 'H', 'L', 'I', 'E', + 'H', 'L', 'I', 'P', + 'H', 'L', 'I', 'T', + 'H', 'L', 'I', 'X', + 'H', 'L', 'O', 'P', + 'H', 'L', 'O', 'X', + 'H', 'L', 'U', 'O', + 'H', 'L', 'U', 'P', + 'H', 'L', 'U', 'R', + 'H', 'L', 'U', 'T', + 'H', 'L', 'U', 'X', + 'H', 'L', 'Y', 'P', + 'H', 'L', 'Y', 'R', + 'H', 'L', 'Y', 'T', + 'H', 'L', 'Y', 'X', + 'H', 'M', 'A', 'P', + 'H', 'M', 'A', 'T', + 'H', 'M', 'A', 'X', + 'H', 'M', 'I', 'E', + 'H', 'M', 'I', 'P', + 'H', 'M', 'I', 'T', + 'H', 'M', 'I', 'X', + 'H', 'M', 'O', 'P', + 'H', 'M', 'O', 'T', + 'H', 'M', 'O', 'X', + 'H', 'M', 'U', 'O', + 'H', 'M', 'U', 'P', + 'H', 'M', 'U', 'R', + 'H', 'M', 'U', 'T', + 'H', 'M', 'U', 'X', + 'H', 'M', 'Y', 'P', + 'H', 'M', 'Y', 'R', + 'H', 'M', 'Y', 'X', + 'H', 'N', 'A', 'P', + 'H', 'N', 'A', 'T', + 'H', 'N', 'A', 'X', + 'H', 'N', 'E', 'P', + 'H', 'N', 'E', 'X', + 'H', 'N', 'I', 'E', + 'H', 'N', 'I', 'P', + 'H', 'N', 'I', 'T', + 'H', 'N', 'I', 'X', + 'H', 'N', 'O', 'P', + 'H', 'N', 'O', 'T', + 'H', 'N', 'O', 'X', + 'H', 'N', 'U', 'O', + 'H', 'N', 'U', 'T', + 'H', 'O', 'O', 'K', + 'H', 'O', 'O', 'N', + 'H', 'O', 'R', 'I', + 'H', 'O', 'R', 'N', + 'H', 'O', 'T', 'A', + 'H', 'O', 'U', 'R', + 'H', 'P', 'W', 'G', + 'H', 'U', 'B', '2', + 'H', 'U', 'L', '2', + 'H', 'U', 'N', 'G', + 'H', 'U', 'O', 'P', + 'H', 'U', 'O', 'T', + 'H', 'U', 'O', 'X', + 'H', 'W', 'E', 'E', + 'H', 'X', 'A', 'P', + 'H', 'X', 'A', 'T', + 'H', 'X', 'A', 'X', + 'H', 'X', 'E', 'P', + 'H', 'X', 'E', 'X', + 'H', 'X', 'I', 'E', + 'H', 'X', 'I', 'P', + 'H', 'X', 'I', 'T', + 'H', 'X', 'I', 'X', + 'H', 'X', 'O', 'P', + 'H', 'X', 'O', 'T', + 'H', 'X', 'O', 'X', + 'H', 'X', 'U', 'O', + 'H', 'X', 'W', 'G', + 'H', 'Z', 'W', 'G', + 'H', 'Z', 'Z', 'P', + 'H', 'Z', 'Z', 'Z', + 'I', '-', 'E', 'U', + 'I', '-', 'Y', 'A', + 'I', 'D', 'I', 'M', + 'I', 'D', 'L', 'E', + 'I', 'F', 'I', 'N', + 'I', 'L', 'U', 'T', + 'I', 'L', 'U', 'Y', + 'I', 'M', 'I', 'N', + 'I', 'N', 'C', 'H', + 'I', 'N', 'N', 'N', + 'I', 'N', 'T', 'I', + 'I', 'O', 'T', 'A', + 'I', 'S', 'A', 'Z', + 'I', 'S', 'O', 'N', + 'I', 'T', 'E', 'M', + 'I', 'U', 'J', 'A', + 'I', 'W', 'A', 'Z', + 'I', 'Z', 'H', 'E', + 'J', 'A', 'D', 'E', + 'J', 'E', 'E', 'M', + 'J', 'E', 'R', 'A', + 'J', 'H', 'A', 'N', + 'J', 'H', 'E', 'H', + 'J', 'I', 'E', 'P', + 'J', 'I', 'E', 'T', + 'J', 'I', 'E', 'X', + 'J', 'J', 'E', 'E', + 'J', 'J', 'I', 'E', + 'J', 'J', 'I', 'P', + 'J', 'J', 'I', 'T', + 'J', 'J', 'I', 'X', + 'J', 'J', 'O', 'P', + 'J', 'J', 'O', 'T', + 'J', 'J', 'O', 'X', + 'J', 'J', 'U', 'O', + 'J', 'J', 'U', 'P', + 'J', 'J', 'U', 'R', + 'J', 'J', 'U', 'T', + 'J', 'J', 'U', 'X', + 'J', 'J', 'Y', 'P', + 'J', 'J', 'Y', 'T', + 'J', 'J', 'Y', 'X', + 'J', 'O', 'I', 'N', + 'J', 'O', 'N', 'A', + 'J', 'O', 'N', 'G', + 'J', 'U', 'L', 'Y', + 'J', 'U', 'N', 'E', + 'J', 'U', 'N', 'O', + 'J', 'U', 'O', 'P', + 'J', 'U', 'O', 'T', + 'J', 'U', 'O', 'X', + 'J', 'U', 'R', 'X', + 'J', 'Y', 'R', 'X', + 'K', 'A', 'A', 'F', + 'K', 'A', 'A', 'I', + 'K', 'A', 'B', 'A', + 'K', 'A', 'D', '2', + 'K', 'A', 'D', '3', + 'K', 'A', 'D', '4', + 'K', 'A', 'D', '5', + 'K', 'A', 'K', 'O', + 'K', 'A', 'M', '2', + 'K', 'A', 'M', '4', + 'K', 'A', 'N', 'A', + 'K', 'A', 'N', 'G', + 'K', 'A', 'P', 'A', + 'K', 'A', 'P', 'H', + 'K', 'A', 'P', 'O', + 'K', 'A', 'T', 'O', + 'K', 'A', 'U', 'N', + 'K', 'C', 'A', 'L', + 'K', 'H', 'A', 'A', + 'K', 'H', 'A', 'H', + 'K', 'H', 'A', 'I', + 'K', 'H', 'A', 'N', + 'K', 'H', 'A', 'R', + 'K', 'H', 'E', 'E', + 'K', 'H', 'E', 'I', + 'K', 'H', 'H', 'A', + 'K', 'H', 'O', 'N', + 'K', 'H', 'O', 'T', + 'K', 'I', 'C', 'K', + 'K', 'I', 'E', 'P', + 'K', 'I', 'E', 'X', + 'K', 'I', 'N', 'G', + 'K', 'I', 'R', 'O', + 'K', 'I', 'S', 'H', + 'K', 'K', 'E', 'E', + 'K', 'O', 'E', 'T', + 'K', 'O', 'M', 'I', + 'K', 'O', 'T', 'O', + 'K', 'P', 'A', 'N', + 'K', 'P', 'E', 'E', + 'K', 'P', 'E', 'N', + 'K', 'P', 'O', 'O', + 'K', 'S', 'S', 'A', + 'K', 'U', 'N', 'G', + 'K', 'U', 'O', 'P', + 'K', 'U', 'O', 'X', + 'K', 'U', 'R', 'T', + 'K', 'U', 'R', 'X', + 'K', 'U', 'U', 'H', + 'K', 'W', 'A', 'A', + 'K', 'W', 'E', 'E', + 'K', 'W', 'I', 'I', + 'K', 'W', 'O', 'O', + 'K', 'X', 'A', 'A', + 'K', 'X', 'E', 'E', + 'K', 'X', 'W', 'A', + 'K', 'X', 'W', 'E', + 'K', 'X', 'W', 'I', + 'K', 'Y', 'A', 'A', + 'K', 'Y', 'E', 'E', + 'L', 'A', 'A', 'I', + 'L', 'A', 'A', 'N', + 'L', 'A', 'C', 'A', + 'L', 'A', 'C', 'K', + 'L', 'A', 'E', 'V', + 'L', 'A', 'G', 'U', + 'L', 'A', 'K', 'E', + 'L', 'A', 'M', 'D', + 'L', 'A', 'M', 'E', + 'L', 'A', 'S', 'T', + 'L', 'A', 'T', 'E', + 'L', 'A', 'Z', 'Y', + 'L', 'D', 'A', 'N', + 'L', 'E', 'A', 'F', + 'L', 'E', 'E', 'K', + 'L', 'E', 'F', 'T', + 'L', 'E', 'G', 'S', + 'L', 'E', 'S', 'S', + 'L', 'E', 'Z', 'H', + 'L', 'H', 'A', 'A', + 'L', 'H', 'A', 'G', + 'L', 'H', 'E', 'E', + 'L', 'H', 'I', 'I', + 'L', 'H', 'O', 'O', + 'L', 'I', 'E', 'P', + 'L', 'I', 'E', 'T', + 'L', 'I', 'E', 'X', + 'L', 'I', 'F', 'E', + 'L', 'I', 'L', 'Y', + 'L', 'I', 'N', 'E', + 'L', 'I', 'N', 'G', + 'L', 'I', 'N', 'K', + 'L', 'I', 'R', 'A', + 'L', 'I', 'S', 'H', + 'L', 'I', 'W', 'N', + 'L', 'L', 'L', 'A', + 'L', 'O', 'G', 'R', + 'L', 'O', 'L', 'L', + 'L', 'O', 'N', 'G', + 'L', 'O', 'O', 'P', + 'L', 'O', 'O', 'T', + 'L', 'U', 'I', 'S', + 'L', 'U', 'O', 'P', + 'L', 'U', 'O', 'T', + 'L', 'U', 'O', 'X', + 'L', 'U', 'R', 'X', + 'L', 'W', 'A', 'A', + 'L', 'W', 'I', 'I', + 'L', 'W', 'O', 'O', + 'L', 'Y', 'R', 'X', + 'M', 'A', 'A', 'I', + 'M', 'A', 'D', 'U', + 'M', 'A', 'L', 'E', + 'M', 'A', 'R', 'E', + 'M', 'A', 'R', 'K', + 'M', 'A', 'S', 'H', + 'M', 'A', 'S', 'U', + 'M', 'B', 'E', 'E', + 'M', 'B', 'O', 'O', + 'M', 'C', 'H', 'U', + 'M', 'D', 'U', 'N', + 'M', 'E', 'A', 'T', + 'M', 'E', 'E', 'M', + 'M', 'E', 'E', 'T', + 'M', 'E', 'G', 'A', + 'M', 'E', 'R', 'I', + 'M', 'E', 'S', 'H', + 'M', 'E', 'S', 'I', + 'M', 'E', 'S', 'O', + 'M', 'E', 'T', 'A', + 'M', 'G', 'A', 'P', + 'M', 'G', 'A', 'T', + 'M', 'G', 'A', 'X', + 'M', 'G', 'B', 'A', + 'M', 'G', 'B', 'E', + 'M', 'G', 'B', 'I', + 'M', 'G', 'B', 'O', + 'M', 'G', 'B', 'U', + 'M', 'G', 'E', 'P', + 'M', 'G', 'E', 'X', + 'M', 'G', 'I', 'E', + 'M', 'G', 'O', 'P', + 'M', 'G', 'O', 'T', + 'M', 'G', 'O', 'X', + 'M', 'G', 'U', 'O', + 'M', 'G', 'U', 'P', + 'M', 'G', 'U', 'R', + 'M', 'G', 'U', 'T', + 'M', 'G', 'U', 'X', + 'M', 'I', 'E', 'P', + 'M', 'I', 'E', 'X', + 'M', 'I', 'I', 'N', + 'M', 'I', 'L', 'L', + 'M', 'I', 'M', 'E', + 'M', 'I', 'N', 'Y', + 'M', 'I', 'R', 'I', + 'M', 'N', 'A', 'S', + 'M', 'O', 'O', 'N', + 'M', 'U', 'A', 'N', + 'M', 'U', 'C', 'H', + 'M', 'U', 'I', 'N', + 'M', 'U', 'O', 'P', + 'M', 'U', 'O', 'T', + 'M', 'U', 'O', 'X', + 'M', 'U', 'O', 'Y', + 'M', 'U', 'R', 'X', + 'M', 'U', 'S', 'H', + 'M', 'W', 'A', 'A', + 'M', 'W', 'E', 'E', + 'M', 'W', 'I', 'I', + 'M', 'W', 'O', 'O', + 'N', 'A', 'A', 'I', + 'N', 'A', 'G', 'A', + 'N', 'A', 'M', '2', + 'N', 'A', 'M', 'E', + 'N', 'A', 'N', 'A', + 'N', 'A', 'N', 'D', + 'N', 'A', 'N', 'O', + 'N', 'A', 'O', 'S', + 'N', 'A', 'U', 'D', + 'N', 'B', 'A', 'P', + 'N', 'B', 'A', 'T', + 'N', 'B', 'A', 'X', + 'N', 'B', 'I', 'E', + 'N', 'B', 'I', 'P', + 'N', 'B', 'I', 'T', + 'N', 'B', 'I', 'X', + 'N', 'B', 'O', 'P', + 'N', 'B', 'O', 'T', + 'N', 'B', 'O', 'X', + 'N', 'B', 'U', 'P', + 'N', 'B', 'U', 'R', + 'N', 'B', 'U', 'T', + 'N', 'B', 'U', 'X', + 'N', 'B', 'Y', 'P', + 'N', 'B', 'Y', 'R', + 'N', 'B', 'Y', 'T', + 'N', 'B', 'Y', 'X', + 'N', 'D', 'A', 'P', + 'N', 'D', 'A', 'T', + 'N', 'D', 'A', 'X', + 'N', 'D', 'E', 'E', + 'N', 'D', 'E', 'P', + 'N', 'D', 'E', 'X', + 'N', 'D', 'I', 'E', + 'N', 'D', 'I', 'P', + 'N', 'D', 'I', 'T', + 'N', 'D', 'I', 'X', + 'N', 'D', 'O', 'O', + 'N', 'D', 'O', 'P', + 'N', 'D', 'O', 'T', + 'N', 'D', 'O', 'X', + 'N', 'D', 'U', 'P', + 'N', 'D', 'U', 'R', + 'N', 'D', 'U', 'T', + 'N', 'D', 'U', 'X', + 'N', 'E', 'X', 'T', + 'N', 'G', 'A', 'A', + 'N', 'G', 'A', 'I', + 'N', 'G', 'A', 'N', + 'N', 'G', 'A', 'P', + 'N', 'G', 'A', 'S', + 'N', 'G', 'A', 'T', + 'N', 'G', 'A', 'X', + 'N', 'G', 'E', 'N', + 'N', 'G', 'E', 'P', + 'N', 'G', 'E', 'X', + 'N', 'G', 'G', 'A', + 'N', 'G', 'G', 'E', + 'N', 'G', 'G', 'I', + 'N', 'G', 'G', 'O', + 'N', 'G', 'G', 'U', + 'N', 'G', 'I', 'E', + 'N', 'G', 'I', 'I', + 'N', 'G', 'K', 'A', + 'N', 'G', 'O', 'N', + 'N', 'G', 'O', 'O', + 'N', 'G', 'O', 'P', + 'N', 'G', 'O', 'T', + 'N', 'G', 'O', 'X', + 'N', 'G', 'U', 'E', + 'N', 'G', 'U', 'O', + 'N', 'H', 'J', 'A', + 'N', 'H', 'U', 'E', + 'N', 'I', 'E', 'P', + 'N', 'I', 'E', 'X', + 'N', 'I', 'N', 'E', + 'N', 'I', 'O', 'N', + 'N', 'J', 'E', 'E', + 'N', 'J', 'I', 'E', + 'N', 'J', 'I', 'P', + 'N', 'J', 'I', 'T', + 'N', 'J', 'I', 'X', + 'N', 'J', 'O', 'O', + 'N', 'J', 'O', 'P', + 'N', 'J', 'O', 'T', + 'N', 'J', 'O', 'X', + 'N', 'J', 'U', 'O', + 'N', 'J', 'U', 'P', + 'N', 'J', 'U', 'R', + 'N', 'J', 'U', 'X', + 'N', 'J', 'Y', 'P', + 'N', 'J', 'Y', 'R', + 'N', 'J', 'Y', 'T', + 'N', 'J', 'Y', 'X', + 'N', 'N', 'G', 'A', + 'N', 'N', 'G', 'I', + 'N', 'N', 'G', 'O', + 'N', 'N', 'N', 'A', + 'N', 'N', 'Y', 'A', + 'N', 'O', 'D', 'E', + 'N', 'O', 'O', 'N', + 'N', 'O', 'S', 'E', + 'N', 'O', 'T', 'E', + 'N', 'R', 'A', 'P', + 'N', 'R', 'A', 'T', + 'N', 'R', 'A', 'X', + 'N', 'R', 'E', 'P', + 'N', 'R', 'E', 'T', + 'N', 'R', 'E', 'X', + 'N', 'R', 'O', 'P', + 'N', 'R', 'O', 'X', + 'N', 'R', 'U', 'P', + 'N', 'R', 'U', 'R', + 'N', 'R', 'U', 'T', + 'N', 'R', 'U', 'X', + 'N', 'R', 'Y', 'P', + 'N', 'R', 'Y', 'R', + 'N', 'R', 'Y', 'T', + 'N', 'R', 'Y', 'X', + 'N', 'U', '1', '1', + 'N', 'U', 'L', 'L', + 'N', 'U', 'O', 'P', + 'N', 'U', 'O', 'X', + 'N', 'U', 'R', 'X', + 'N', 'U', 'U', 'N', + 'N', 'W', 'A', 'A', + 'N', 'Y', 'A', 'A', + 'N', 'Y', 'C', 'A', + 'N', 'Y', 'E', 'E', + 'N', 'Y', 'E', 'H', + 'N', 'Y', 'E', 'T', + 'N', 'Y', 'I', 'E', + 'N', 'Y', 'I', 'P', + 'N', 'Y', 'I', 'S', + 'N', 'Y', 'I', 'T', + 'N', 'Y', 'I', 'X', + 'N', 'Y', 'J', 'A', + 'N', 'Y', 'O', 'A', + 'N', 'Y', 'O', 'O', + 'N', 'Y', 'O', 'P', + 'N', 'Y', 'O', 'T', + 'N', 'Y', 'O', 'X', + 'N', 'Y', 'U', 'O', + 'N', 'Y', 'U', 'P', + 'N', 'Y', 'U', 'T', + 'N', 'Y', 'U', 'X', + 'N', 'Y', 'W', 'A', + 'N', 'Z', 'A', 'P', + 'N', 'Z', 'A', 'T', + 'N', 'Z', 'A', 'X', + 'N', 'Z', 'E', 'X', + 'N', 'Z', 'I', 'E', + 'N', 'Z', 'I', 'P', + 'N', 'Z', 'I', 'T', + 'N', 'Z', 'I', 'X', + 'N', 'Z', 'O', 'P', + 'N', 'Z', 'O', 'X', + 'N', 'Z', 'U', 'O', + 'N', 'Z', 'U', 'P', + 'N', 'Z', 'U', 'R', + 'N', 'Z', 'U', 'X', + 'N', 'Z', 'Y', 'P', + 'N', 'Z', 'Y', 'R', + 'N', 'Z', 'Y', 'T', + 'N', 'Z', 'Y', 'X', + 'O', '-', 'E', 'O', + 'O', '-', 'Y', 'E', + 'O', 'B', 'O', 'L', + 'O', 'K', 'T', 'O', + 'O', 'N', 'S', 'U', + 'O', 'O', 'M', 'U', + 'O', 'O', 'Z', 'E', + 'O', 'P', 'E', 'N', + 'O', 'V', 'E', 'R', + 'O', 'X', 'I', 'A', + 'P', 'A', 'A', 'I', + 'P', 'A', 'G', 'E', + 'P', 'A', 'L', 'M', + 'P', 'A', 'N', 'G', + 'P', 'A', 'R', 'A', + 'P', 'A', 'R', 'T', + 'P', 'A', 'T', 'H', + 'P', 'A', 'W', 'N', + 'P', 'E', 'E', 'P', + 'P', 'E', 'S', 'O', + 'P', 'H', 'A', 'A', + 'P', 'H', 'A', 'N', + 'P', 'H', 'A', 'R', + 'P', 'H', 'E', 'E', + 'P', 'H', 'O', 'A', + 'P', 'H', 'U', 'R', + 'P', 'H', 'W', 'A', + 'P', 'I', 'C', 'K', + 'P', 'I', 'E', 'P', + 'P', 'I', 'E', 'X', + 'P', 'I', 'K', 'O', + 'P', 'I', 'N', 'G', + 'P', 'I', 'W', 'R', + 'P', 'L', 'A', 'K', + 'P', 'L', 'O', 'W', + 'P', 'L', 'U', 'K', + 'P', 'L', 'U', 'M', + 'P', 'L', 'U', 'S', + 'P', 'O', 'L', 'E', + 'P', 'O', 'L', 'I', + 'P', 'R', 'A', 'M', + 'P', 'U', 'N', 'G', + 'P', 'U', 'O', 'P', + 'P', 'U', 'O', 'X', + 'P', 'U', 'R', 'X', + 'P', 'W', 'A', 'A', + 'P', 'W', 'E', 'E', + 'P', 'W', 'I', 'I', + 'P', 'W', 'O', 'O', + 'P', 'Y', 'R', 'X', + 'Q', 'A', 'A', 'F', + 'Q', 'A', 'A', 'I', + 'Q', 'A', 'L', 'A', + 'Q', 'A', 'P', 'H', + 'Q', 'H', 'A', 'A', + 'Q', 'H', 'E', 'E', + 'Q', 'H', 'W', 'A', + 'Q', 'H', 'W', 'E', + 'Q', 'H', 'W', 'I', + 'Q', 'I', 'E', 'P', + 'Q', 'I', 'E', 'T', + 'Q', 'I', 'E', 'X', + 'Q', 'O', 'P', 'A', + 'Q', 'U', 'A', 'D', + 'Q', 'U', 'O', 'P', + 'Q', 'U', 'O', 'T', + 'Q', 'U', 'O', 'X', + 'Q', 'U', 'R', 'X', + 'Q', 'U', 'U', 'V', + 'Q', 'W', 'A', 'A', + 'Q', 'W', 'E', 'E', + 'Q', 'Y', 'A', 'A', + 'Q', 'Y', 'E', 'E', + 'Q', 'Y', 'R', 'X', + 'R', 'A', 'A', 'I', + 'R', 'A', 'D', 'I', + 'R', 'A', 'F', 'E', + 'R', 'A', 'I', 'N', + 'R', 'A', 'M', 'S', + 'R', 'A', 'Y', 'S', + 'R', 'D', 'E', 'L', + 'R', 'E', 'I', 'D', + 'R', 'E', 'M', 'U', + 'R', 'E', 'P', 'A', + 'R', 'E', 'S', 'H', + 'R', 'E', 'S', 'T', + 'R', 'G', 'Y', 'A', + 'R', 'I', 'A', 'L', + 'R', 'I', 'C', 'E', + 'R', 'I', 'E', 'L', + 'R', 'I', 'N', 'G', + 'R', 'I', 'R', 'A', + 'R', 'I', 'S', 'H', + 'R', 'J', 'E', 'S', + 'R', 'N', 'A', 'M', + 'R', 'O', 'A', 'R', + 'R', 'O', 'O', 'F', + 'R', 'O', 'O', 'K', + 'R', 'O', 'O', 'T', + 'R', 'O', 'S', 'H', + 'R', 'R', 'A', 'X', + 'R', 'R', 'E', 'H', + 'R', 'R', 'E', 'P', + 'R', 'R', 'E', 'T', + 'R', 'R', 'E', 'X', + 'R', 'R', 'O', 'P', + 'R', 'R', 'O', 'T', + 'R', 'R', 'O', 'X', + 'R', 'R', 'U', 'O', + 'R', 'R', 'U', 'P', + 'R', 'R', 'U', 'R', + 'R', 'R', 'U', 'T', + 'R', 'R', 'U', 'X', + 'R', 'R', 'Y', 'P', + 'R', 'R', 'Y', 'R', + 'R', 'R', 'Y', 'T', + 'R', 'R', 'Y', 'X', + 'R', 'U', 'I', 'S', + 'R', 'U', 'L', 'E', + 'R', 'U', 'O', 'P', + 'R', 'U', 'O', 'X', + 'R', 'U', 'R', 'X', + 'R', 'U', 'S', 'I', + 'R', 'W', 'A', 'A', + 'R', 'Y', 'R', 'X', + 'S', 'A', '-', 'I', + 'S', 'A', 'A', 'I', + 'S', 'A', 'D', 'E', + 'S', 'A', 'G', 'A', + 'S', 'A', 'I', 'L', + 'S', 'A', 'L', 'A', + 'S', 'A', 'L', 'T', + 'S', 'A', 'P', 'A', + 'S', 'A', 'R', 'A', + 'S', 'A', 'R', 'I', + 'S', 'B', 'U', 'B', + 'S', 'C', 'A', 'N', + 'S', 'C', 'W', 'A', + 'S', 'E', 'A', 'L', + 'S', 'E', 'E', 'N', + 'S', 'E', 'L', 'F', + 'S', 'E', 'M', 'K', + 'S', 'G', 'A', 'B', + 'S', 'G', 'A', 'W', + 'S', 'G', 'O', 'R', + 'S', 'G', 'R', 'A', + 'S', 'H', 'A', '3', + 'S', 'H', 'A', '6', + 'S', 'H', 'A', 'A', + 'S', 'H', 'A', 'D', + 'S', 'H', 'A', 'N', + 'S', 'H', 'A', 'P', + 'S', 'H', 'A', 'T', + 'S', 'H', 'A', 'X', + 'S', 'H', 'E', 'E', + 'S', 'H', 'E', 'I', + 'S', 'H', 'E', 'N', + 'S', 'H', 'E', 'P', + 'S', 'H', 'E', 'T', + 'S', 'H', 'E', 'X', + 'S', 'H', 'H', 'A', + 'S', 'H', 'I', 'D', + 'S', 'H', 'I', 'I', + 'S', 'H', 'I', 'M', + 'S', 'H', 'I', 'N', + 'S', 'H', 'I', 'P', + 'S', 'H', 'I', 'R', + 'S', 'H', 'O', 'A', + 'S', 'H', 'O', 'E', + 'S', 'H', 'O', 'G', + 'S', 'H', 'O', 'O', + 'S', 'H', 'O', 'P', + 'S', 'H', 'O', 'T', + 'S', 'H', 'O', 'X', + 'S', 'H', 'T', 'A', + 'S', 'H', 'U', '2', + 'S', 'H', 'U', 'O', + 'S', 'H', 'U', 'P', + 'S', 'H', 'U', 'R', + 'S', 'H', 'U', 'T', + 'S', 'H', 'U', 'X', + 'S', 'H', 'W', 'A', + 'S', 'H', 'W', 'E', + 'S', 'H', 'W', 'I', + 'S', 'H', 'W', 'O', + 'S', 'H', 'Y', 'A', + 'S', 'H', 'Y', 'P', + 'S', 'H', 'Y', 'R', + 'S', 'H', 'Y', 'T', + 'S', 'H', 'Y', 'X', + 'S', 'I', 'B', 'E', + 'S', 'I', 'E', 'P', + 'S', 'I', 'E', 'X', + 'S', 'I', 'G', '4', + 'S', 'I', 'G', 'N', + 'S', 'I', 'K', '2', + 'S', 'I', 'K', 'I', + 'S', 'I', 'L', 'K', + 'S', 'I', 'M', 'A', + 'S', 'I', 'N', 'E', + 'S', 'I', 'O', 'S', + 'S', 'K', 'I', 'N', + 'S', 'K', 'W', 'A', + 'S', 'L', 'U', 'R', + 'S', 'N', 'A', 'P', + 'S', 'O', 'F', 'T', + 'S', 'P', 'O', 'T', + 'S', 'P', 'W', 'A', + 'S', 'S', 'A', 'A', + 'S', 'S', 'A', 'P', + 'S', 'S', 'A', 'T', + 'S', 'S', 'A', 'X', + 'S', 'S', 'E', 'E', + 'S', 'S', 'E', 'P', + 'S', 'S', 'E', 'X', + 'S', 'S', 'I', 'E', + 'S', 'S', 'I', 'P', + 'S', 'S', 'I', 'T', + 'S', 'S', 'I', 'X', + 'S', 'S', 'O', 'P', + 'S', 'S', 'O', 'T', + 'S', 'S', 'O', 'X', + 'S', 'S', 'U', 'P', + 'S', 'S', 'U', 'T', + 'S', 'S', 'U', 'X', + 'S', 'S', 'Y', 'P', + 'S', 'S', 'Y', 'R', + 'S', 'S', 'Y', 'T', + 'S', 'S', 'Y', 'X', + 'S', 'T', 'A', 'N', + 'S', 'T', 'A', 'R', + 'S', 'T', 'E', 'M', + 'S', 'T', 'E', 'P', + 'S', 'T', 'O', 'P', + 'S', 'T', 'W', 'A', + 'S', 'U', 'D', '2', + 'S', 'U', 'I', 'T', + 'S', 'U', 'K', 'U', + 'S', 'U', 'N', 'G', + 'S', 'U', 'O', 'P', + 'S', 'U', 'O', 'X', + 'S', 'U', 'R', '9', + 'S', 'U', 'R', 'E', + 'S', 'U', 'R', 'X', + 'S', 'W', 'A', 'A', + 'S', 'W', 'I', 'I', + 'S', 'W', 'O', 'O', + 'S', 'Y', 'R', 'X', + 'S', 'Z', 'A', 'A', + 'S', 'Z', 'E', 'E', + 'S', 'Z', 'W', 'A', + 'S', 'Z', 'W', 'G', + 'T', 'A', 'A', 'I', + 'T', 'A', 'C', 'K', + 'T', 'A', 'I', 'L', + 'T', 'A', 'K', '4', + 'T', 'A', 'K', 'E', + 'T', 'A', 'L', 'L', + 'T', 'A', 'P', 'E', + 'T', 'A', 'W', 'A', + 'T', 'C', 'H', 'E', + 'T', 'E', '-', 'U', + 'T', 'E', 'N', 'S', + 'T', 'E', 'N', 'T', + 'T', 'E', 'N', 'U', + 'T', 'E', 'S', 'H', + 'T', 'E', 'T', 'H', + 'T', 'E', 'X', 'T', + 'T', 'H', 'A', 'A', + 'T', 'H', 'A', 'I', + 'T', 'H', 'A', 'L', + 'T', 'H', 'A', 'N', + 'T', 'H', 'E', 'E', + 'T', 'H', 'E', 'H', + 'T', 'H', 'E', 'N', + 'T', 'H', 'E', 'S', + 'T', 'H', 'E', 'Y', + 'T', 'H', 'I', 'I', + 'T', 'H', 'I', 'N', + 'T', 'H', 'O', 'A', + 'T', 'H', 'O', 'O', + 'T', 'H', 'W', 'A', + 'T', 'I', 'C', 'K', + 'T', 'I', 'E', 'P', + 'T', 'I', 'E', 'X', + 'T', 'I', 'L', 'E', + 'T', 'I', 'M', 'E', + 'T', 'I', 'N', 'G', + 'T', 'I', 'N', 'Y', + 'T', 'I', 'W', 'N', + 'T', 'L', 'E', 'E', + 'T', 'L', 'H', 'A', + 'T', 'L', 'H', 'E', + 'T', 'L', 'H', 'I', + 'T', 'L', 'H', 'O', + 'T', 'L', 'H', 'U', + 'T', 'O', 'D', 'O', + 'T', 'O', 'N', 'E', + 'T', 'O', 'N', 'G', + 'T', 'R', 'E', 'E', + 'T', 'R', 'I', 'A', + 'T', 'R', 'U', 'E', + 'T', 'S', 'A', 'A', + 'T', 'S', 'E', 'E', + 'T', 'S', 'H', 'A', + 'T', 'S', 'H', 'E', + 'T', 'S', 'S', 'E', + 'T', 'S', 'W', 'A', + 'T', 'S', 'W', 'E', + 'T', 'T', 'A', 'A', + 'T', 'T', 'E', 'E', + 'T', 'T', 'E', 'H', + 'T', 'T', 'H', 'A', + 'T', 'T', 'H', 'E', + 'T', 'T', 'H', 'I', + 'T', 'T', 'H', 'O', + 'T', 'T', 'S', 'A', + 'T', 'T', 'S', 'E', + 'T', 'T', 'S', 'I', + 'T', 'T', 'S', 'O', + 'T', 'T', 'S', 'U', + 'T', 'U', 'G', '2', + 'T', 'U', 'O', 'P', + 'T', 'U', 'O', 'T', + 'T', 'U', 'O', 'X', + 'T', 'U', 'R', 'N', + 'T', 'U', 'R', 'X', + 'T', 'W', 'A', 'A', + 'T', 'W', 'I', 'I', + 'T', 'W', 'O', 'O', + 'T', 'Y', 'P', 'E', + 'T', 'Z', 'A', 'A', + 'T', 'Z', 'E', 'E', + 'T', 'Z', 'I', 'R', + 'T', 'Z', 'O', 'A', + 'U', '-', 'A', 'E', + 'U', '-', 'Y', 'E', + 'U', 'A', 'T', 'H', + 'U', 'D', 'U', 'G', + 'U', 'M', 'U', 'M', + 'U', 'N', 'D', 'O', + 'U', 'N', 'I', 'T', + 'U', 'R', 'I', '3', + 'U', 'R', 'U', 'S', + 'U', 'R', 'U', 'Z', + 'U', 'S', 'E', 'D', + 'U', 'S', 'H', '2', + 'U', 'S', 'H', 'X', + 'U', 'S', 'S', 'U', + 'U', 'U', 'U', '2', + 'U', 'U', 'U', '3', + 'U', 'U', 'U', 'U', + 'V', 'A', 'N', 'E', + 'V', 'E', 'D', 'E', + 'V', 'E', 'N', 'D', + 'V', 'E', 'R', 'Y', + 'V', 'I', 'D', 'A', + 'V', 'I', 'E', 'P', + 'V', 'I', 'E', 'T', + 'V', 'I', 'E', 'X', + 'V', 'I', 'N', 'E', + 'V', 'O', 'I', 'D', + 'V', 'U', 'R', 'X', + 'V', 'Y', 'R', 'X', + 'W', 'A', 'E', 'N', + 'W', 'A', 'L', 'K', + 'W', 'A', 'L', 'L', + 'W', 'A', 'V', 'E', + 'W', 'A', 'V', 'Y', + 'W', 'E', 'E', 'N', + 'W', 'E', 'L', 'L', + 'W', 'E', 'S', 'T', + 'W', 'I', 'D', 'E', + 'W', 'I', 'N', 'D', + 'W', 'I', 'N', 'E', + 'W', 'I', 'T', 'H', + 'W', 'O', 'O', 'D', + 'W', 'O', 'O', 'L', + 'W', 'O', 'O', 'N', + 'W', 'O', 'R', 'D', + 'W', 'O', 'R', 'K', + 'W', 'R', 'A', 'P', + 'W', 'U', 'O', 'P', + 'W', 'U', 'O', 'X', + 'W', 'Y', 'N', 'N', + 'X', 'I', 'E', 'P', + 'X', 'I', 'E', 'T', + 'X', 'I', 'E', 'X', + 'X', 'U', 'O', 'X', + 'X', 'W', 'A', 'A', + 'X', 'W', 'E', 'E', + 'X', 'Y', 'A', 'A', + 'X', 'Y', 'E', 'E', + 'X', 'Y', 'R', 'X', + 'Y', 'A', '-', 'O', + 'Y', 'A', 'A', 'I', + 'Y', 'A', 'B', 'H', + 'Y', 'A', 'C', 'H', + 'Y', 'A', 'D', 'D', + 'Y', 'A', 'D', 'H', + 'Y', 'A', 'G', 'H', + 'Y', 'A', 'G', 'N', + 'Y', 'A', 'H', 'H', + 'Y', 'A', 'K', 'H', + 'Y', 'A', 'N', 'G', + 'Y', 'A', 'R', 'R', + 'Y', 'A', 'S', 'H', + 'Y', 'A', 'S', 'S', + 'Y', 'A', 'T', 'H', + 'Y', 'A', 'T', 'I', + 'Y', 'A', 'T', 'T', + 'Y', 'A', 'Z', 'H', + 'Y', 'A', 'Z', 'Z', + 'Y', 'E', 'A', 'R', + 'Y', 'E', 'R', 'I', + 'Y', 'E', 'R', 'U', + 'Y', 'F', 'E', 'N', + 'Y', 'I', '-', 'U', + 'Y', 'I', 'E', 'P', + 'Y', 'I', 'E', 'T', + 'Y', 'I', 'E', 'X', + 'Y', 'I', 'N', 'G', + 'Y', 'I', 'W', 'N', + 'Y', 'O', '-', 'I', + 'Y', 'O', '-', 'O', + 'Y', 'O', 'G', 'H', + 'Y', 'O', 'M', 'O', + 'Y', 'O', 'R', 'I', + 'Y', 'U', '-', 'A', + 'Y', 'U', '-', 'E', + 'Y', 'U', '-', 'I', + 'Y', 'U', '-', 'U', + 'Y', 'U', 'A', 'N', + 'Y', 'U', 'D', 'H', + 'Y', 'U', 'O', 'P', + 'Y', 'U', 'O', 'T', + 'Y', 'U', 'O', 'X', + 'Y', 'U', 'R', 'X', + 'Y', 'W', 'A', 'A', + 'Y', 'W', 'I', 'I', + 'Y', 'W', 'O', 'O', + 'Y', 'Y', 'R', 'X', + 'Z', 'A', 'I', 'N', + 'Z', 'A', 'M', 'X', + 'Z', 'A', 'T', 'A', + 'Z', 'E', 'R', 'O', + 'Z', 'E', 'T', 'A', + 'Z', 'H', 'A', 'A', + 'Z', 'H', 'A', 'P', + 'Z', 'H', 'A', 'R', + 'Z', 'H', 'A', 'T', + 'Z', 'H', 'A', 'X', + 'Z', 'H', 'E', 'E', + 'Z', 'H', 'E', 'P', + 'Z', 'H', 'E', 'T', + 'Z', 'H', 'E', 'X', + 'Z', 'H', 'O', 'O', + 'Z', 'H', 'O', 'P', + 'Z', 'H', 'O', 'T', + 'Z', 'H', 'O', 'X', + 'Z', 'H', 'U', 'O', + 'Z', 'H', 'U', 'P', + 'Z', 'H', 'U', 'R', + 'Z', 'H', 'U', 'T', + 'Z', 'H', 'U', 'X', + 'Z', 'H', 'W', 'A', + 'Z', 'H', 'W', 'E', + 'Z', 'H', 'Y', 'P', + 'Z', 'H', 'Y', 'R', + 'Z', 'H', 'Y', 'T', + 'Z', 'H', 'Y', 'X', + 'Z', 'I', 'D', 'A', + 'Z', 'I', 'E', 'P', + 'Z', 'I', 'E', 'X', + 'Z', 'I', 'Z', '2', + 'Z', 'U', 'O', 'P', + 'Z', 'U', 'O', 'X', + 'Z', 'U', 'R', 'X', + 'Z', 'Y', 'R', 'X', + 'Z', 'Z', 'A', 'A', + 'Z', 'Z', 'A', 'P', + 'Z', 'Z', 'A', 'T', + 'Z', 'Z', 'A', 'X', + 'Z', 'Z', 'E', 'E', + 'Z', 'Z', 'E', 'P', + 'Z', 'Z', 'E', 'X', + 'Z', 'Z', 'I', 'E', + 'Z', 'Z', 'I', 'P', + 'Z', 'Z', 'I', 'T', + 'Z', 'Z', 'I', 'X', + 'Z', 'Z', 'O', 'P', + 'Z', 'Z', 'O', 'X', + 'Z', 'Z', 'U', 'P', + 'Z', 'Z', 'U', 'R', + 'Z', 'Z', 'U', 'X', + 'Z', 'Z', 'Y', 'P', + 'Z', 'Z', 'Y', 'R', + 'Z', 'Z', 'Y', 'T', + 'Z', 'Z', 'Y', 'X', + '-', 'C', 'H', 'A', 'L', + '-', 'C', 'H', 'A', 'R', + '-', 'D', 'Z', 'U', 'D', + '-', 'P', 'H', 'R', 'U', + 'A', 'B', 'O', 'V', 'E', + 'A', 'C', 'U', 'T', 'E', + 'A', 'D', 'D', 'A', 'K', + 'A', 'F', 'T', 'E', 'R', + 'A', 'G', 'A', 'I', 'N', + 'A', 'G', 'O', 'G', 'I', + 'A', 'H', 'S', 'D', 'A', + 'A', 'K', 'A', 'R', 'A', + 'A', 'K', 'B', 'A', 'R', + 'A', 'L', 'A', 'P', 'H', + 'A', 'L', 'E', 'P', 'H', + 'A', 'L', 'E', 'U', 'T', + 'A', 'L', 'G', 'I', 'Z', + 'A', 'L', 'I', 'F', 'U', + 'A', 'L', 'L', 'A', 'H', + 'A', 'L', 'P', 'H', 'A', + 'A', 'N', 'G', 'L', 'E', + 'A', 'N', 'P', 'E', 'A', + 'A', 'N', 'S', 'H', 'E', + 'A', 'N', 'S', 'U', 'Z', + 'A', 'P', 'A', 'R', 'T', + 'A', 'P', 'E', 'S', 'O', + 'A', 'P', 'R', 'I', 'L', + 'A', 'R', 'A', 'E', 'A', + 'A', 'R', 'E', 'P', 'A', + 'A', 'R', 'G', 'O', 'N', + 'A', 'R', 'I', 'E', 'S', + 'A', 'R', 'K', 'A', 'B', + 'A', 'R', 'R', 'A', 'Y', + 'A', 'R', 'R', 'O', 'W', + 'A', 'S', 'A', 'L', '2', + 'A', 'T', 'N', 'A', 'H', + 'A', 'T', 'T', 'A', 'K', + 'A', 'T', 'T', 'I', 'C', + 'B', '1', '0', '5', 'F', + 'B', '1', '0', '5', 'M', + 'B', '1', '0', '6', 'F', + 'B', '1', '0', '6', 'M', + 'B', '1', '0', '7', 'F', + 'B', '1', '0', '7', 'M', + 'B', '1', '0', '8', 'F', + 'B', '1', '0', '8', 'M', + 'B', '1', '0', '9', 'F', + 'B', '1', '0', '9', 'M', + 'B', 'A', 'L', 'A', 'G', + 'B', 'A', 'R', 'A', '2', + 'B', 'A', 'S', 'S', 'A', + 'B', 'B', 'I', 'E', 'P', + 'B', 'B', 'I', 'E', 'T', + 'B', 'B', 'I', 'E', 'X', + 'B', 'B', 'U', 'O', 'P', + 'B', 'B', 'U', 'O', 'X', + 'B', 'B', 'U', 'R', 'X', + 'B', 'E', 'E', 'T', 'A', + 'B', 'E', 'G', 'I', 'N', + 'B', 'E', 'H', 'E', 'H', + 'B', 'E', 'I', 'T', 'H', + 'B', 'E', 'L', 'O', 'W', + 'B', 'E', 'N', 'D', 'E', + 'B', 'E', 'O', 'R', 'C', + 'B', 'H', 'E', 'T', 'H', + 'B', 'I', 'N', 'D', 'I', + 'B', 'I', 'R', 'G', 'A', + 'B', 'I', 'S', 'A', 'H', + 'B', 'L', 'A', 'C', 'K', + 'B', 'L', 'A', 'D', 'E', + 'B', 'L', 'A', 'N', 'K', + 'B', 'L', 'O', 'C', 'K', + 'B', 'L', 'O', 'O', 'D', + 'B', 'R', 'A', 'C', 'E', + 'B', 'R', 'E', 'V', 'E', + 'B', 'R', 'O', 'A', 'D', + 'B', 'R', 'U', 'S', 'H', + 'B', 'S', 'D', 'U', 'S', + 'B', 'S', 'K', 'A', '-', + 'B', 'S', 'K', 'U', 'R', + 'B', 'S', 'T', 'A', 'R', + 'B', 'U', 'H', 'I', 'D', + 'B', 'U', 'L', 'L', 'S', + 'B', 'U', 'L', 'U', 'G', + 'B', 'U', 'M', 'P', 'Y', + 'B', 'Z', 'U', 'N', 'G', + 'C', 'A', 'L', 'Y', 'A', + 'C', 'A', 'R', 'E', 'T', + 'C', 'A', 'R', 'I', 'K', + 'C', 'A', 'R', 'O', 'N', + 'C', 'A', 'U', 'D', 'A', + 'C', 'C', 'H', 'A', 'A', + 'C', 'C', 'H', 'E', 'E', + 'C', 'E', 'A', 'L', 'C', + 'C', 'E', 'C', 'E', 'K', + 'C', 'E', 'I', 'R', 'T', + 'C', 'E', 'R', 'E', 'S', + 'C', 'H', 'A', 'D', 'A', + 'C', 'H', 'A', 'I', 'R', + 'C', 'H', 'A', 'N', 'G', + 'C', 'H', 'E', 'C', 'K', + 'C', 'H', 'E', 'S', 'S', + 'C', 'H', 'I', 'K', 'I', + 'C', 'H', 'I', 'L', 'D', + 'C', 'H', 'I', 'N', 'G', + 'C', 'H', 'O', 'K', 'E', + 'C', 'H', 'R', 'O', 'A', + 'C', 'H', 'U', 'L', 'A', + 'C', 'H', 'U', 'O', 'P', + 'C', 'H', 'U', 'O', 'T', + 'C', 'H', 'U', 'O', 'X', + 'C', 'H', 'U', 'R', 'X', + 'C', 'H', 'Y', 'R', 'X', + 'C', 'I', 'E', 'U', 'C', + 'C', 'L', 'E', 'A', 'R', + 'C', 'L', 'I', 'C', 'K', + 'C', 'L', 'I', 'F', 'F', + 'C', 'L', 'O', 'S', 'E', + 'C', 'L', 'O', 'T', 'H', + 'C', 'L', 'O', 'U', 'D', + 'C', 'O', 'E', 'N', 'G', + 'C', 'O', 'L', 'O', 'N', + 'C', 'O', 'L', 'O', 'R', + 'C', 'O', 'M', 'E', 'T', + 'C', 'O', 'M', 'M', 'A', + 'C', 'O', 'V', 'E', 'R', + 'C', 'R', 'O', 'I', 'X', + 'C', 'R', 'O', 'S', 'S', + 'C', 'U', 'B', 'E', 'D', + 'C', 'U', 'R', 'L', 'Y', + 'C', 'U', 'R', 'V', 'E', + 'D', 'A', 'A', 'S', 'U', + 'D', 'A', 'E', 'N', 'G', + 'D', 'A', 'G', 'A', 'Z', + 'D', 'A', 'H', 'A', 'L', + 'D', 'A', 'I', 'N', 'G', + 'D', 'A', 'L', 'D', 'A', + 'D', 'A', 'L', 'E', 'T', + 'D', 'A', 'M', 'M', 'A', + 'D', 'A', 'N', 'D', 'A', + 'D', 'A', 'R', 'A', '3', + 'D', 'A', 'R', 'A', '4', + 'D', 'A', 'R', 'G', 'A', + 'D', 'A', 'S', 'I', 'A', + 'D', 'A', 'V', 'I', 'D', + 'D', 'D', 'D', 'H', 'A', + 'D', 'D', 'I', 'E', 'P', + 'D', 'D', 'I', 'E', 'X', + 'D', 'D', 'U', 'O', 'P', + 'D', 'D', 'U', 'O', 'X', + 'D', 'D', 'U', 'R', 'X', + 'D', 'E', 'A', 'T', 'H', + 'D', 'E', 'B', 'I', 'T', + 'D', 'E', 'L', 'T', 'A', + 'D', 'E', 'R', 'E', 'T', + 'D', 'E', 'U', 'N', 'G', + 'D', 'E', 'X', 'I', 'A', + 'D', 'H', 'H', 'E', 'E', + 'D', 'H', 'H', 'O', 'O', + 'D', 'I', 'F', 'A', 'T', + 'D', 'I', 'G', 'I', 'T', + 'D', 'I', 'P', 'L', 'I', + 'D', 'I', 'P', 'T', 'E', + 'D', 'I', 'T', 'T', 'O', + 'D', 'J', 'E', 'R', 'V', + 'D', 'O', 'B', 'R', 'O', + 'D', 'O', 'O', 'N', 'G', + 'D', 'O', 'U', 'B', 'T', + 'D', 'R', 'I', 'V', 'E', + 'D', 'R', 'O', 'P', 'S', + 'D', 'U', 'G', 'U', 'D', + 'D', 'Z', 'E', 'L', 'O', + 'E', 'A', 'G', 'L', 'E', + 'E', 'A', 'R', 'L', 'Y', + 'E', 'A', 'R', 'T', 'H', + 'E', 'E', 'K', 'A', 'A', + 'E', 'H', 'W', 'A', 'Z', + 'E', 'I', 'G', 'H', 'T', + 'E', 'J', 'E', 'C', 'T', + 'E', 'K', 'A', 'R', 'A', + 'E', 'L', 'I', 'F', 'I', + 'E', 'M', 'P', 'T', 'Y', + 'E', 'N', 'D', 'E', 'P', + 'E', 'N', 'T', 'E', 'R', + 'E', 'O', '-', 'E', 'U', + 'E', 'O', 'L', 'H', 'X', + 'E', 'Q', 'U', 'A', 'L', + 'E', 'Q', 'U', 'I', 'D', + 'E', 'R', 'A', 'S', 'E', + 'E', 'R', 'I', 'N', '2', + 'E', 'S', '-', 'T', 'E', + 'E', 'S', 'A', 'S', 'A', + 'E', 'S', 'H', '1', '6', + 'E', 'S', 'H', '2', '1', + 'E', 'S', 'H', 'E', '3', + 'E', 'T', 'H', 'E', 'L', + 'E', 'U', '-', 'E', 'U', + 'E', 'U', 'L', 'E', 'R', + 'E', 'X', 'I', 'S', 'T', + 'F', 'A', 'A', 'F', 'U', + 'F', 'A', 'I', 'H', 'U', + 'F', 'A', 'R', 'S', 'I', + 'F', 'A', 'T', 'H', 'A', + 'F', 'E', 'A', 'R', 'N', + 'F', 'E', 'E', 'N', 'G', + 'F', 'E', 'N', 'C', 'E', + 'F', 'I', 'E', 'L', 'D', + 'F', 'I', 'F', 'T', 'H', + 'F', 'I', 'F', 'T', 'Y', + 'F', 'I', 'G', 'H', 'T', + 'F', 'I', 'N', 'A', 'L', + 'F', 'I', 'R', 'S', 'T', + 'F', 'L', 'O', 'O', 'R', + 'F', 'L', 'U', 'T', 'E', + 'F', 'O', 'L', 'L', 'Y', + 'F', 'O', 'R', 'C', 'E', + 'F', 'O', 'R', 'M', 'S', + 'F', 'O', 'R', 'T', 'E', + 'F', 'O', 'R', 'T', 'Y', + 'F', 'R', 'A', 'M', 'E', + 'F', 'R', 'A', 'N', 'C', + 'F', 'R', 'I', 'T', 'U', + 'F', 'R', 'O', 'W', 'N', + 'G', 'A', 'A', 'F', 'U', + 'G', 'A', 'D', 'O', 'L', + 'G', 'A', 'L', 'A', 'M', + 'G', 'A', 'M', 'A', 'L', + 'G', 'A', 'M', 'L', 'A', + 'G', 'A', 'M', 'M', 'A', + 'G', 'A', 'N', 'M', 'A', + 'G', 'A', 'R', 'O', 'N', + 'G', 'E', 'S', 'H', '2', + 'G', 'E', 'S', 'H', 'U', + 'G', 'G', 'I', 'E', 'P', + 'G', 'G', 'I', 'E', 'X', + 'G', 'G', 'U', 'O', 'P', + 'G', 'G', 'U', 'O', 'T', + 'G', 'G', 'U', 'O', 'X', + 'G', 'G', 'U', 'R', 'X', + 'G', 'G', 'W', 'A', 'A', + 'G', 'G', 'W', 'E', 'E', + 'G', 'H', 'A', 'I', 'N', + 'G', 'H', 'O', 'S', 'T', + 'G', 'I', 'D', 'I', 'M', + 'G', 'I', 'M', 'E', 'L', + 'G', 'I', 'N', 'I', 'I', + 'G', 'I', 'S', 'A', 'L', + 'G', 'N', 'Y', 'I', 'S', + 'G', 'O', 'I', 'N', 'G', + 'G', 'O', 'R', 'G', 'I', + 'G', 'R', 'A', 'C', 'E', + 'G', 'R', 'A', 'I', 'N', + 'G', 'R', 'A', 'S', 'S', + 'G', 'R', 'A', 'V', 'E', + 'G', 'R', 'E', 'A', 'T', + 'G', 'R', 'E', 'E', 'K', + 'G', 'R', 'E', 'E', 'N', + 'G', 'R', 'O', 'U', 'P', + 'G', 'U', 'R', 'U', 'N', + 'H', 'A', '-', 'H', 'A', + 'H', 'A', 'A', 'R', 'U', + 'H', 'A', 'E', 'G', 'L', + 'H', 'A', 'I', 'T', 'U', + 'H', 'A', 'M', 'Z', 'A', + 'H', 'A', 'N', 'D', 'S', + 'H', 'A', 'S', 'E', 'R', + 'H', 'A', 'T', 'A', 'F', + 'H', 'A', 'T', 'H', 'I', + 'H', 'B', 'A', 'S', 'A', + 'H', 'E', 'A', 'R', 'T', + 'H', 'E', 'A', 'V', 'Y', + 'H', 'I', 'D', 'E', 'T', + 'H', 'I', 'E', 'U', 'H', + 'H', 'I', 'R', 'I', 'Q', + 'H', 'L', 'I', 'E', 'P', + 'H', 'L', 'I', 'E', 'X', + 'H', 'L', 'U', 'O', 'P', + 'H', 'L', 'U', 'O', 'X', + 'H', 'L', 'U', 'R', 'X', + 'H', 'L', 'Y', 'R', 'X', + 'H', 'M', 'I', 'E', 'P', + 'H', 'M', 'I', 'E', 'X', + 'H', 'M', 'U', 'O', 'P', + 'H', 'M', 'U', 'O', 'X', + 'H', 'M', 'U', 'R', 'X', + 'H', 'M', 'Y', 'R', 'X', + 'H', 'N', 'I', 'E', 'P', + 'H', 'N', 'I', 'E', 'T', + 'H', 'N', 'I', 'E', 'X', + 'H', 'N', 'U', 'O', 'X', + 'H', 'O', 'L', 'A', 'M', + 'H', 'O', 'O', 'R', 'U', + 'H', 'O', 'R', 'S', 'E', + 'H', 'O', 'U', 'S', 'E', + 'H', 'U', 'M', 'A', 'N', + 'H', 'U', 'R', 'A', 'N', + 'H', 'W', 'A', 'I', 'R', + 'H', 'X', 'I', 'E', 'P', + 'H', 'X', 'I', 'E', 'T', + 'H', 'X', 'I', 'E', 'X', + 'H', 'X', 'U', 'O', 'P', + 'H', 'X', 'U', 'O', 'T', + 'H', 'X', 'U', 'O', 'X', + 'H', 'Z', 'Z', 'Z', 'G', + 'I', 'A', 'U', 'D', 'A', + 'I', 'C', 'H', 'O', 'S', + 'I', 'C', 'H', 'O', 'U', + 'I', 'E', 'U', 'N', 'G', + 'I', 'G', 'G', 'W', 'S', + 'I', 'K', 'A', 'R', 'A', + 'I', 'M', 'A', 'G', 'E', + 'I', 'M', 'I', 'N', '3', + 'I', 'N', 'D', 'E', 'X', + 'I', 'N', 'N', 'E', 'R', + 'J', 'E', 'R', 'A', 'N', + 'J', 'J', 'I', 'E', 'P', + 'J', 'J', 'I', 'E', 'T', + 'J', 'J', 'I', 'E', 'X', + 'J', 'J', 'U', 'O', 'P', + 'J', 'J', 'U', 'O', 'X', + 'J', 'J', 'U', 'R', 'X', + 'J', 'O', 'K', 'E', 'R', + 'J', 'U', 'D', 'G', 'E', + 'J', 'U', 'E', 'U', 'I', + 'K', 'A', 'A', 'F', 'U', + 'K', 'A', 'I', 'R', 'I', + 'K', 'A', 'P', 'A', 'L', + 'K', 'A', 'P', 'P', 'A', + 'K', 'A', 'R', 'E', 'N', + 'K', 'A', 'S', 'R', 'A', + 'K', 'A', 'U', 'N', 'A', + 'K', 'A', 'Y', 'A', 'H', + 'K', 'E', 'E', 'N', 'G', + 'K', 'E', 'E', 'S', 'U', + 'K', 'E', 'H', 'E', 'H', + 'K', 'E', 'N', 'A', 'T', + 'K', 'E', 'S', 'H', '2', + 'K', 'E', 'T', 'T', 'I', + 'K', 'H', 'A', 'N', 'G', + 'K', 'H', 'A', 'P', 'H', + 'K', 'H', 'M', 'E', 'R', + 'K', 'H', 'U', 'A', 'T', + 'K', 'H', 'W', 'A', 'I', + 'K', 'I', 'S', 'A', 'L', + 'K', 'N', 'I', 'F', 'E', + 'K', 'O', 'M', 'B', 'U', + 'K', 'O', 'O', 'P', 'O', + 'K', 'O', 'P', 'P', 'A', + 'K', 'U', 'S', 'M', 'A', + 'K', 'X', 'W', 'A', 'A', + 'K', 'X', 'W', 'E', 'E', + 'L', 'A', 'A', 'M', 'U', + 'L', 'A', 'B', 'O', 'R', + 'L', 'A', 'G', 'A', 'B', + 'L', 'A', 'G', 'A', 'R', + 'L', 'A', 'G', 'U', 'S', + 'L', 'A', 'M', 'D', 'A', + 'L', 'A', 'M', 'E', 'D', + 'L', 'A', 'R', 'G', 'E', + 'L', 'A', 'T', 'I', 'K', + 'L', 'A', 'T', 'I', 'N', + 'L', 'A', 'U', 'L', 'A', + 'L', 'E', 'M', 'O', 'I', + 'L', 'E', 'N', 'G', 'A', + 'L', 'E', 'V', 'E', 'L', + 'L', 'I', 'B', 'R', 'A', + 'L', 'I', 'G', 'H', 'T', + 'L', 'I', 'M', 'B', 'U', + 'L', 'I', 'M', 'I', 'T', + 'L', 'I', 'M', 'M', 'U', + 'L', 'I', 'N', 'E', 'S', + 'L', 'I', 'T', 'R', 'A', + 'L', 'O', 'N', 'G', 'A', + 'L', 'O', 'T', 'U', 'S', + 'L', 'O', 'U', 'R', 'E', + 'L', 'O', 'W', '-', '9', + 'L', 'O', 'W', 'E', 'R', + 'L', 'U', 'G', 'A', 'L', + 'M', 'A', 'D', 'D', 'A', + 'M', 'A', 'H', 'H', 'A', + 'M', 'A', 'I', 'R', 'U', + 'M', 'A', 'N', 'N', 'A', + 'M', 'A', 'P', 'I', 'Q', + 'M', 'A', 'Q', 'A', 'F', + 'M', 'A', 'R', 'C', 'H', + 'M', 'A', 'S', 'H', '2', + 'M', 'E', 'E', 'M', 'U', + 'M', 'E', 'I', 'Z', 'I', + 'M', 'E', 'L', 'O', 'N', + 'M', 'E', 'T', 'A', 'L', + 'M', 'E', 'T', 'E', 'G', + 'M', 'E', 'Z', 'Z', 'O', + 'M', 'G', 'B', 'E', 'E', + 'M', 'G', 'B', 'O', 'O', + 'M', 'G', 'I', 'E', 'X', + 'M', 'G', 'U', 'O', 'P', + 'M', 'G', 'U', 'O', 'X', + 'M', 'G', 'U', 'R', 'X', + 'M', 'I', 'C', 'R', 'O', + 'M', 'I', 'E', 'U', 'M', + 'M', 'I', 'K', 'R', 'I', + 'M', 'I', 'L', 'L', 'E', + 'M', 'I', 'N', 'U', 'S', + 'M', 'I', 'R', 'E', 'D', + 'M', 'I', 'S', 'R', 'A', + 'M', 'N', 'Y', 'A', 'M', + 'M', 'O', 'D', 'E', 'L', + 'M', 'O', 'N', 'T', 'H', + 'M', 'O', 'U', 'N', 'D', + 'M', 'O', 'U', 'T', 'H', + 'M', 'O', 'V', 'E', 'D', + 'M', 'U', 'L', 'T', 'I', + 'M', 'U', 'N', 'A', 'H', + 'M', 'U', 'R', 'D', 'A', + 'M', 'U', 'S', 'H', '3', + 'M', 'U', 'S', 'I', 'C', + 'N', '-', 'A', 'R', 'Y', + 'N', 'A', 'B', 'L', 'A', + 'N', 'A', 'G', 'A', 'R', + 'N', 'A', 'G', 'R', 'I', + 'N', 'A', 'I', 'R', 'A', + 'N', 'A', 'S', 'H', 'I', + 'N', 'B', 'I', 'E', 'P', + 'N', 'B', 'I', 'E', 'X', + 'N', 'B', 'U', 'R', 'X', + 'N', 'B', 'Y', 'R', 'X', + 'N', 'D', 'I', 'E', 'X', + 'N', 'D', 'O', 'L', 'E', + 'N', 'D', 'U', 'R', 'X', + 'N', 'G', 'A', 'A', 'I', + 'N', 'G', 'G', 'E', 'E', + 'N', 'G', 'G', 'E', 'N', + 'N', 'G', 'G', 'O', 'O', + 'N', 'G', 'I', 'E', 'P', + 'N', 'G', 'I', 'E', 'X', + 'N', 'G', 'O', 'E', 'H', + 'N', 'G', 'U', 'O', 'T', + 'N', 'G', 'U', 'O', 'X', + 'N', 'I', 'E', 'U', 'N', + 'N', 'I', 'G', 'H', 'T', + 'N', 'I', 'S', 'A', 'G', + 'N', 'J', 'I', 'E', 'P', + 'N', 'J', 'I', 'E', 'T', + 'N', 'J', 'I', 'E', 'X', + 'N', 'J', 'U', 'O', 'X', + 'N', 'J', 'U', 'R', 'X', + 'N', 'J', 'Y', 'R', 'X', + 'N', 'N', 'G', 'A', 'A', + 'N', 'N', 'G', 'I', 'I', + 'N', 'N', 'G', 'O', 'O', + 'N', 'O', 'O', 'N', 'U', + 'N', 'O', 'R', 'T', 'H', + 'N', 'O', 'T', 'C', 'H', + 'N', 'O', 'T', 'E', 'S', + 'N', 'O', 'T', 'T', 'O', + 'N', 'R', 'U', 'R', 'X', + 'N', 'R', 'Y', 'R', 'X', + 'N', 'U', 'K', 'T', 'A', + 'N', 'U', 'N', 'U', 'Z', + 'N', 'Y', 'I', 'E', 'P', + 'N', 'Y', 'I', 'E', 'T', + 'N', 'Y', 'I', 'E', 'X', + 'N', 'Y', 'U', 'O', 'P', + 'N', 'Y', 'U', 'O', 'X', + 'N', 'Z', 'I', 'E', 'P', + 'N', 'Z', 'I', 'E', 'X', + 'N', 'Z', 'U', 'O', 'X', + 'N', 'Z', 'U', 'R', 'X', + 'N', 'Z', 'Y', 'R', 'X', + 'O', 'B', 'O', 'L', 'S', + 'O', 'G', 'H', 'A', 'M', + 'O', 'J', 'E', 'O', 'N', + 'O', 'K', 'A', 'R', 'A', + 'O', 'L', 'I', 'V', 'E', + 'O', 'M', 'E', 'G', 'A', + 'O', 'N', 'K', 'A', 'R', + 'O', 'R', 'I', 'Y', 'A', + 'O', 'T', 'H', 'A', 'L', + 'O', 'U', 'N', 'C', 'E', + 'O', 'U', 'T', 'E', 'R', + 'O', 'X', 'E', 'I', 'A', + 'P', 'A', 'A', 'T', 'U', + 'P', 'A', 'D', 'M', 'A', + 'P', 'A', 'N', 'T', 'I', + 'P', 'A', 'P', 'E', 'R', + 'P', 'A', 'S', 'E', 'Q', + 'P', 'A', 'S', 'U', 'Q', + 'P', 'A', 'T', 'A', 'H', + 'P', 'A', 'T', 'A', 'K', + 'P', 'A', 'Z', 'E', 'R', + 'P', 'E', 'A', 'C', 'E', + 'P', 'E', 'D', 'A', 'L', + 'P', 'E', 'E', 'Z', 'I', + 'P', 'E', 'H', 'E', 'H', + 'P', 'E', 'I', 'T', 'H', + 'P', 'E', 'N', 'N', 'Y', + 'P', 'E', 'N', 'S', 'U', + 'P', 'E', 'P', 'E', 'T', + 'P', 'E', 'S', 'H', '2', + 'P', 'H', 'U', 'N', 'G', + 'P', 'I', 'A', 'N', 'O', + 'P', 'I', 'E', 'C', 'E', + 'P', 'I', 'E', 'U', 'P', + 'P', 'I', 'R', 'I', 'G', + 'P', 'L', 'A', 'C', 'E', + 'P', 'L', 'A', 'N', 'E', + 'P', 'L', 'U', 'T', 'O', + 'P', 'O', 'I', 'N', 'T', + 'P', 'O', 'N', 'D', 'O', + 'P', 'O', 'U', 'N', 'D', + 'P', 'O', 'W', 'E', 'R', + 'P', 'R', 'I', 'M', 'E', + 'P', 'R', 'I', 'N', 'T', + 'P', 'R', 'O', 'O', 'F', + 'P', 'R', 'O', 'V', 'E', + 'P', 'S', 'I', 'L', 'I', + 'Q', 'A', 'A', 'F', 'U', + 'Q', 'A', 'D', 'M', 'A', + 'Q', 'A', 'T', 'A', 'N', + 'Q', 'H', 'W', 'A', 'A', + 'Q', 'H', 'W', 'E', 'E', + 'Q', 'U', 'E', 'E', 'N', + 'Q', 'U', 'I', 'L', 'L', + 'Q', 'U', 'O', 'T', 'E', + 'R', 'A', 'I', 'D', 'A', + 'R', 'A', 'I', 'D', 'O', + 'R', 'A', 'N', 'G', 'E', + 'R', 'A', 'S', 'H', 'A', + 'R', 'A', 'T', 'I', 'O', + 'R', 'B', 'A', 'S', 'A', + 'R', 'E', 'A', 'C', 'H', + 'R', 'E', 'L', 'A', 'A', + 'R', 'E', 'V', 'I', 'A', + 'R', 'E', 'V', 'M', 'A', + 'R', 'G', 'Y', 'A', 'N', + 'R', 'I', 'C', 'E', 'M', + 'R', 'I', 'E', 'U', 'L', + 'R', 'I', 'G', 'H', 'T', + 'R', 'I', 'T', 'S', 'I', + 'R', 'I', 'V', 'E', 'R', + 'R', 'N', 'O', 'O', 'N', + 'R', 'O', 'B', 'A', 'T', + 'R', 'O', 'M', 'A', 'N', + 'R', 'O', 'U', 'N', 'D', + 'R', 'R', 'U', 'O', 'X', + 'R', 'R', 'U', 'R', 'X', + 'R', 'R', 'Y', 'R', 'X', + 'R', 'T', 'A', 'G', 'S', + 'R', 'U', 'M', 'A', 'I', + 'R', 'U', 'N', 'I', 'C', + 'R', 'U', 'P', 'E', 'E', + 'R', 'U', 'P', 'I', 'I', + 'R', 'W', 'A', 'H', 'A', + 'S', 'A', 'D', 'H', 'E', + 'S', 'A', 'F', 'H', 'A', + 'S', 'A', 'L', 'A', 'M', + 'S', 'A', 'L', 'L', 'A', + 'S', 'A', 'M', 'K', 'A', + 'S', 'A', 'M', 'P', 'I', + 'S', 'A', 'N', 'A', 'H', + 'S', 'A', 'S', 'A', 'K', + 'S', 'A', 'U', 'I', 'L', + 'S', 'B', 'R', 'U', 'L', + 'S', 'C', 'H', 'W', 'A', + 'S', 'D', 'O', 'N', 'G', + 'S', 'E', 'E', 'N', 'U', + 'S', 'E', 'G', 'N', 'O', + 'S', 'E', 'G', 'O', 'L', + 'S', 'E', 'N', 'T', 'I', + 'S', 'E', 'N', 'T', 'O', + 'S', 'E', 'V', 'E', 'N', + 'S', 'H', 'A', 'B', '6', + 'S', 'H', 'A', 'D', 'E', + 'S', 'H', 'A', 'N', 'G', + 'S', 'H', 'A', 'R', '2', + 'S', 'H', 'A', 'R', 'P', + 'S', 'H', 'A', 'R', 'U', + 'S', 'H', 'C', 'H', 'A', + 'S', 'H', 'E', 'E', 'N', + 'S', 'H', 'E', 'E', 'P', + 'S', 'H', 'E', 'G', '9', + 'S', 'H', 'E', 'L', 'F', + 'S', 'H', 'E', 'L', 'L', + 'S', 'H', 'E', 'S', 'H', + 'S', 'H', 'E', 'V', 'A', + 'S', 'H', 'I', 'F', 'T', + 'S', 'H', 'I', 'I', 'N', + 'S', 'H', 'I', 'M', 'A', + 'S', 'H', 'I', 'T', 'A', + 'S', 'H', 'O', 'G', 'I', + 'S', 'H', 'O', 'O', 'T', + 'S', 'H', 'O', 'R', 'T', + 'S', 'H', 'U', 'O', 'P', + 'S', 'H', 'U', 'O', 'X', + 'S', 'H', 'U', 'R', 'X', + 'S', 'H', 'W', 'A', 'A', + 'S', 'H', 'W', 'I', 'I', + 'S', 'H', 'W', 'O', 'O', + 'S', 'H', 'Y', 'R', 'X', + 'S', 'I', 'G', 'E', 'L', + 'S', 'I', 'G', 'M', 'A', + 'S', 'I', 'G', 'N', 'S', + 'S', 'I', 'L', 'A', '3', + 'S', 'I', 'X', 'T', 'H', + 'S', 'I', 'X', 'T', 'Y', + 'S', 'K', 'U', 'L', 'L', + 'S', 'L', 'A', 'S', 'H', + 'S', 'L', 'A', 'V', 'E', + 'S', 'L', 'I', 'C', 'E', + 'S', 'L', 'I', 'N', 'G', + 'S', 'L', 'O', 'P', 'E', + 'S', 'L', 'O', 'V', 'O', + 'S', 'M', 'A', 'L', 'L', + 'S', 'M', 'A', 'S', 'H', + 'S', 'M', 'E', 'A', 'R', + 'S', 'M', 'I', 'L', 'E', + 'S', 'N', 'A', 'K', 'E', + 'S', 'N', 'O', 'U', 'T', + 'S', 'O', 'U', 'N', 'D', + 'S', 'O', 'U', 'T', 'H', + 'S', 'P', 'A', 'C', 'E', + 'S', 'P', 'A', 'D', 'E', + 'S', 'P', 'E', 'A', 'R', + 'S', 'P', 'I', 'C', 'E', + 'S', 'P', 'O', 'O', 'N', + 'S', 'Q', 'U', 'A', 'T', + 'S', 'S', 'I', 'E', 'P', + 'S', 'S', 'I', 'E', 'X', + 'S', 'S', 'Y', 'R', 'X', + 'S', 'T', 'A', 'F', 'F', + 'S', 'T', 'A', 'N', 'D', + 'S', 'T', 'A', 'R', 'K', + 'S', 'T', 'A', 'R', 'T', + 'S', 'T', 'E', 'A', 'M', + 'S', 'T', 'I', 'L', 'E', + 'S', 'T', 'I', 'L', 'L', + 'S', 'T', 'O', 'C', 'K', + 'S', 'T', 'O', 'N', 'E', + 'S', 'T', 'O', 'V', 'E', + 'S', 'T', 'U', 'D', 'Y', + 'S', 'U', 'H', 'U', 'R', + 'S', 'U', 'K', 'U', 'N', + 'S', 'W', 'A', 'S', 'H', + 'S', 'W', 'E', 'E', 'T', + 'S', 'W', 'O', 'R', 'D', + 'S', 'W', 'U', 'N', 'G', + 'S', 'Y', 'R', 'M', 'A', + 'T', 'A', 'B', 'L', 'E', + 'T', 'A', 'M', 'I', 'L', + 'T', 'A', 'P', 'E', 'R', + 'T', 'C', 'H', 'E', 'H', + 'T', 'E', 'G', 'E', 'H', + 'T', 'E', 'H', 'E', 'H', + 'T', 'E', 'I', 'W', 'S', + 'T', 'E', 'V', 'I', 'R', + 'T', 'H', 'E', 'M', 'A', + 'T', 'H', 'E', 'R', 'E', + 'T', 'H', 'E', 'T', 'A', + 'T', 'H', 'I', 'G', 'H', + 'T', 'H', 'I', 'R', 'D', + 'T', 'H', 'I', 'T', 'A', + 'T', 'H', 'O', 'N', 'G', + 'T', 'H', 'O', 'R', 'N', + 'T', 'H', 'R', 'E', 'E', + 'T', 'H', 'U', 'N', 'G', + 'T', 'H', 'U', 'R', 'S', + 'T', 'H', 'W', 'A', 'A', + 'T', 'I', 'A', 'R', 'A', + 'T', 'I', 'G', 'E', 'R', + 'T', 'I', 'G', 'H', 'T', + 'T', 'I', 'L', 'D', 'E', + 'T', 'I', 'M', 'E', 'S', + 'T', 'I', 'N', 'N', 'E', + 'T', 'I', 'P', 'P', 'I', + 'T', 'I', 'T', 'L', 'O', + 'T', 'I', 'W', 'A', 'Z', + 'T', 'L', 'H', 'E', 'E', + 'T', 'O', 'N', 'A', 'L', + 'T', 'O', 'N', 'O', 'S', + 'T', 'O', 'O', 'T', 'H', + 'T', 'O', 'T', 'A', 'L', + 'T', 'R', 'A', 'C', 'K', + 'T', 'R', 'A', 'D', 'E', + 'T', 'R', 'I', 'O', 'N', + 'T', 'R', 'U', 'N', 'K', + 'T', 'R', 'U', 'T', 'H', + 'T', 'S', 'A', 'D', 'I', + 'T', 'S', 'E', 'R', 'E', + 'T', 'S', 'H', 'E', 'G', + 'T', 'S', 'H', 'E', 'S', + 'T', 'T', 'S', 'E', 'E', + 'T', 'T', 'T', 'H', 'A', + 'T', 'U', 'N', 'N', 'Y', + 'T', 'U', 'R', 'O', '2', + 'T', 'U', 'U', 'M', 'U', + 'U', 'D', 'A', 'A', 'T', + 'U', 'K', 'A', 'R', 'A', + 'U', 'M', 'B', 'I', 'N', + 'U', 'N', 'C', 'I', 'A', + 'U', 'N', 'D', 'E', 'R', + 'U', 'N', 'I', 'O', 'N', + 'U', 'N', 'I', 'T', 'Y', + 'U', 'P', 'P', 'E', 'R', + 'U', 'R', 'U', 'D', 'A', + 'U', 'S', 'S', 'U', '3', + 'U', 'T', 'U', 'K', 'I', + 'V', 'A', 'A', 'V', 'U', + 'V', 'A', 'R', 'I', 'A', + 'V', 'A', 'R', 'Y', 'S', + 'V', 'A', 'S', 'I', 'S', + 'V', 'A', 'T', 'H', 'Y', + 'V', 'E', 'R', 'G', 'E', + 'V', 'E', 'R', 'S', 'E', + 'V', 'E', 'S', 'T', 'A', + 'V', 'I', 'R', 'G', 'A', + 'V', 'I', 'R', 'G', 'O', + 'V', 'O', 'C', 'A', 'L', + 'V', 'O', 'W', 'E', 'L', + 'V', 'Z', 'M', 'E', 'T', + 'W', 'A', 'A', 'V', 'U', + 'W', 'A', 'S', 'L', 'A', + 'W', 'A', 'T', 'C', 'H', + 'W', 'A', 'T', 'E', 'R', + 'W', 'A', 'T', 'T', 'O', + 'W', 'H', 'E', 'A', 'T', + 'W', 'H', 'E', 'E', 'L', + 'W', 'H', 'I', 'T', 'E', + 'W', 'H', 'O', 'L', 'E', + 'W', 'I', 'D', 'T', 'H', + 'W', 'I', 'N', 'D', 'U', + 'W', 'I', 'N', 'J', 'A', + 'W', 'O', 'M', 'A', 'N', + 'W', 'R', 'O', 'N', 'G', + 'W', 'U', 'N', 'J', 'O', + 'X', 'I', 'R', 'O', 'N', + 'Y', 'A', '-', 'Y', 'O', + 'Y', 'A', 'A', 'D', 'O', + 'Y', 'A', 'A', 'R', 'U', + 'Y', 'A', 'D', 'D', 'H', + 'Y', 'A', 'G', 'H', 'H', + 'Y', 'A', 'K', 'H', 'H', + 'Y', 'E', 'O', '-', 'O', + 'Y', 'E', 'O', '-', 'U', + 'Y', 'E', 'R', 'A', 'H', + 'Y', 'E', 'S', 'T', 'U', + 'Y', 'E', 'T', 'I', 'V', + 'Y', 'I', 'Z', 'E', 'T', + 'Y', 'O', '-', 'Y', 'A', + 'Y', 'U', '-', 'E', 'O', + 'Y', 'U', '-', 'Y', 'E', + 'Z', 'A', 'Q', 'E', 'F', + 'Z', 'A', 'R', 'Q', 'A', + 'Z', 'A', 'Y', 'I', 'N', + 'Z', 'H', 'A', 'I', 'N', + 'Z', 'H', 'U', 'O', 'P', + 'Z', 'H', 'U', 'O', 'X', + 'Z', 'H', 'U', 'R', 'X', + 'Z', 'H', 'Y', 'R', 'X', + 'Z', 'I', 'L', 'D', 'E', + 'Z', 'I', 'N', 'O', 'R', + 'Z', 'L', 'A', 'M', 'A', + 'Z', 'U', 'B', 'U', 'R', + 'Z', 'Y', 'G', 'O', 'S', + 'Z', 'Z', 'I', 'E', 'P', + 'Z', 'Z', 'I', 'E', 'T', + 'Z', 'Z', 'I', 'E', 'X', + 'Z', 'Z', 'U', 'R', 'X', + 'Z', 'Z', 'Y', 'R', 'X', + '-', 'K', 'H', 'Y', 'I', 'L', + '-', 'K', 'H', 'Y', 'U', 'D', + 'A', 'C', 'C', 'E', 'N', 'T', + 'A', 'E', 'G', 'E', 'A', 'N', + 'A', 'I', 'H', 'V', 'U', 'S', + 'A', 'I', 'K', 'A', 'R', 'A', + 'A', 'L', 'A', 'Y', 'H', 'E', + 'A', 'L', 'M', 'O', 'S', 'T', + 'A', 'M', 'O', 'U', 'N', 'T', + 'A', 'N', 'C', 'H', 'O', 'R', + 'A', 'N', 'C', 'O', 'R', 'A', + 'A', 'P', 'A', 'A', 'T', 'O', + 'A', 'P', 'L', 'O', 'U', 'N', + 'A', 'R', 'A', 'B', 'I', 'C', + 'A', 'R', 'A', 'E', 'A', 'E', + 'A', 'R', 'L', 'A', 'U', 'G', + 'A', 'R', 'M', 'O', 'U', 'R', + 'A', 'R', 'O', 'U', 'N', 'D', + 'A', 'R', 'O', 'U', 'R', 'A', + 'A', 'R', 'R', 'I', 'V', 'E', + 'A', 'R', 'R', 'O', 'W', 'S', + 'A', 'R', 'S', 'E', 'O', 'S', + 'A', 'R', 'T', 'A', 'B', 'E', + 'A', 'R', 'U', 'H', 'U', 'A', + 'A', 'S', 'C', 'E', 'N', 'T', + 'A', 'S', 'H', 'G', 'A', 'B', + 'A', 'S', 'Y', 'U', 'R', 'A', + 'A', 'U', 'G', 'U', 'S', 'T', + 'A', 'U', 'T', 'U', 'M', 'N', + 'A', 'Y', 'A', 'N', 'N', 'A', + 'B', 'A', 'D', 'G', 'E', 'R', + 'B', 'A', 'H', 'A', 'R', '2', + 'B', 'A', 'I', 'M', 'A', 'I', + 'B', 'A', 'L', 'L', 'O', 'T', + 'B', 'A', 'L', 'U', 'D', 'A', + 'B', 'A', 'M', 'B', 'O', 'O', + 'B', 'A', 'N', 'T', 'O', 'C', + 'B', 'A', 'R', 'L', 'E', 'Y', + 'B', 'A', 'R', 'R', 'E', 'D', + 'B', 'A', 'R', 'R', 'E', 'E', + 'B', 'E', 'A', 'M', 'E', 'D', + 'B', 'E', 'F', 'O', 'R', 'E', + 'B', 'E', 'R', 'B', 'E', 'R', + 'B', 'E', 'S', 'I', 'D', 'E', + 'B', 'E', 'Y', 'Y', 'A', 'L', + 'B', 'I', 'N', 'A', 'R', 'Y', + 'B', 'I', 'S', 'H', 'O', 'P', + 'B', 'I', 'T', 'I', 'N', 'G', + 'B', 'I', 'T', 'T', 'E', 'R', + 'B', 'O', 'R', 'U', 'T', 'O', + 'B', 'O', 'T', 'T', 'O', 'M', + 'B', 'O', 'W', 'T', 'I', 'E', + 'B', 'R', 'A', 'N', 'C', 'H', + 'B', 'R', 'E', 'A', 'T', 'H', + 'B', 'R', 'E', 'V', 'I', 'S', + 'B', 'R', 'I', 'D', 'G', 'E', + 'B', 'R', 'O', 'K', 'E', 'N', + 'B', 'R', 'O', 'N', 'Z', 'E', + 'B', 'U', 'C', 'K', 'L', 'E', + 'B', 'U', 'L', 'L', 'E', 'T', + 'C', 'A', 'M', 'N', 'U', 'C', + 'C', 'A', 'N', 'C', 'E', 'L', + 'C', 'A', 'N', 'C', 'E', 'R', + 'C', 'A', 'N', 'D', 'R', 'A', + 'C', 'A', 'R', 'I', 'A', 'N', + 'C', 'A', 'T', 'A', 'W', 'A', + 'C', 'E', 'N', 'T', 'R', 'E', + 'C', 'E', 'R', '-', 'W', 'A', + 'C', 'H', 'A', 'M', 'K', 'O', + 'C', 'H', 'A', 'N', 'G', 'E', + 'C', 'H', 'I', 'L', 'L', 'U', + 'C', 'H', 'I', 'R', 'E', 'T', + 'C', 'H', 'I', 'R', 'O', 'N', + 'C', 'H', 'R', 'I', 'V', 'I', + 'C', 'H', 'R', 'O', 'M', 'A', + 'C', 'H', 'U', 'R', 'C', 'H', + 'C', 'I', 'R', 'C', 'L', 'E', + 'C', 'L', 'E', 'F', '-', '1', + 'C', 'L', 'E', 'F', '-', '2', + 'C', 'L', 'I', 'V', 'I', 'S', + 'C', 'L', 'O', 'S', 'E', 'D', + 'C', 'O', 'F', 'F', 'I', 'N', + 'C', 'O', 'L', 'U', 'M', 'N', + 'C', 'O', 'M', 'I', 'N', 'G', + 'C', 'O', 'M', 'M', 'O', 'N', + 'C', 'O', 'P', 'T', 'I', 'C', + 'C', 'O', 'R', 'N', 'E', 'R', + 'C', 'O', 'R', 'P', 'S', 'E', + 'C', 'R', 'E', 'D', 'I', 'T', + 'C', 'U', 'R', 'V', 'E', 'D', + 'D', 'A', 'A', 'D', 'H', 'U', + 'D', 'A', 'G', 'E', 'S', 'H', + 'D', 'A', 'G', 'G', 'E', 'R', + 'D', 'A', 'L', 'A', 'T', 'H', + 'D', 'A', 'M', 'A', 'R', 'U', + 'D', 'A', 'S', 'E', 'I', 'A', + 'D', 'A', 'S', 'H', 'E', 'D', + 'D', 'D', 'A', 'H', 'A', 'L', + 'D', 'E', 'G', 'R', 'E', 'E', + 'D', 'E', 'L', 'E', 'T', 'E', + 'D', 'E', 'N', 'N', 'E', 'N', + 'D', 'E', 'N', 'T', 'A', 'L', + 'D', 'E', 'V', 'I', 'C', 'E', + 'D', 'H', 'A', 'A', 'L', 'U', + 'D', 'H', 'A', 'R', 'M', 'A', + 'D', 'I', 'E', 'S', 'I', 'S', + 'D', 'I', 'G', 'R', 'A', 'M', + 'D', 'I', 'P', 'P', 'E', 'R', + 'D', 'I', 'R', 'E', 'C', 'T', + 'D', 'I', 'V', 'I', 'D', 'E', + 'D', 'J', 'E', 'R', 'V', 'I', + 'D', 'O', 'L', 'I', 'U', 'M', + 'D', 'O', 'L', 'L', 'A', 'R', + 'D', 'O', 'M', 'A', 'I', 'N', + 'D', 'O', 'M', 'I', 'N', 'O', + 'D', 'O', 'T', 'S', '-', '1', + 'D', 'O', 'T', 'S', '-', '2', + 'D', 'O', 'T', 'S', '-', '3', + 'D', 'O', 'T', 'S', '-', '4', + 'D', 'O', 'T', 'S', '-', '5', + 'D', 'O', 'T', 'S', '-', '6', + 'D', 'O', 'T', 'S', '-', '7', + 'D', 'O', 'T', 'S', '-', '8', + 'D', 'O', 'T', 'T', 'E', 'D', + 'D', 'O', 'U', 'B', 'L', 'E', + 'D', 'R', 'A', 'G', 'O', 'N', + 'D', 'U', 'T', 'I', 'E', 'S', + 'E', 'I', 'G', 'H', 'T', 'H', + 'E', 'I', 'G', 'H', 'T', 'Y', + 'E', 'L', 'E', 'V', 'E', 'N', + 'E', 'N', 'D', 'I', 'N', 'G', + 'E', 'Q', 'U', 'A', 'L', 'S', + 'E', 'S', 'C', 'A', 'P', 'E', + 'E', 'T', 'E', 'R', 'O', 'N', + 'E', 'X', 'C', 'E', 'S', 'S', + 'E', 'X', 'I', 'S', 'T', 'S', + 'E', 'Y', 'A', 'N', 'N', 'A', + 'F', 'A', 'C', 'E', '-', '1', + 'F', 'A', 'C', 'E', '-', '2', + 'F', 'A', 'C', 'E', '-', '3', + 'F', 'A', 'C', 'E', '-', '4', + 'F', 'A', 'C', 'E', '-', '5', + 'F', 'A', 'C', 'E', '-', '6', + 'F', 'A', 'C', 'T', 'O', 'R', + 'F', 'A', 'M', 'I', 'L', 'Y', + 'F', 'A', 'T', 'H', 'E', 'R', + 'F', 'E', 'M', 'A', 'L', 'E', + 'F', 'H', 'T', 'O', 'R', 'A', + 'F', 'I', 'F', 'T', 'H', 'S', + 'F', 'I', 'G', 'U', 'R', 'E', + 'F', 'I', 'L', 'L', 'E', 'D', + 'F', 'I', 'L', 'L', 'E', 'R', + 'F', 'I', 'N', 'I', 'T', 'E', + 'F', 'L', 'A', 'G', '-', '1', + 'F', 'L', 'A', 'G', '-', '2', + 'F', 'L', 'A', 'G', '-', '3', + 'F', 'L', 'A', 'G', '-', '4', + 'F', 'L', 'A', 'G', '-', '5', + 'F', 'L', 'E', 'X', 'U', 'S', + 'F', 'L', 'I', 'G', 'H', 'T', + 'F', 'L', 'O', 'R', 'A', 'L', + 'F', 'L', 'O', 'W', 'E', 'R', + 'F', 'O', 'R', 'C', 'E', 'S', + 'F', 'O', 'R', 'K', 'E', 'D', + 'F', 'O', 'U', 'R', 'T', 'H', + 'F', 'R', 'E', 'N', 'C', 'H', + 'F', 'T', 'H', 'O', 'R', 'A', + 'G', 'A', 'N', 'G', 'I', 'A', + 'G', 'A', 'P', 'P', 'E', 'D', + 'G', 'A', 'S', 'H', 'A', 'N', + 'G', 'E', 'D', 'O', 'L', 'A', + 'G', 'E', 'M', 'I', 'N', 'I', + 'G', 'E', 'N', 'I', 'K', 'I', + 'G', 'E', 'N', 'T', 'L', 'E', + 'G', 'E', 'R', 'E', 'S', 'H', + 'G', 'E', 'R', 'M', 'A', 'N', + 'G', 'H', 'A', 'I', 'N', 'U', + 'G', 'H', 'A', 'M', 'A', 'L', + 'G', 'H', 'U', 'N', 'N', 'A', + 'G', 'L', 'E', 'I', 'C', 'H', + 'G', 'O', 'R', 'G', 'O', 'N', + 'G', 'O', 'T', 'H', 'I', 'C', + 'G', 'R', 'A', 'M', 'M', 'A', + 'G', 'R', 'A', 'T', 'E', 'R', + 'G', 'R', 'O', 'U', 'N', 'D', + 'G', 'U', 'R', 'A', 'M', 'U', + 'G', 'U', 'R', 'U', 'S', 'H', + 'H', '-', 'T', 'Y', 'P', 'E', + 'H', 'A', 'F', 'U', 'K', 'H', + 'H', 'A', 'G', 'L', 'A', 'Z', + 'H', 'A', 'M', 'M', 'E', 'R', + 'H', 'A', 'N', 'G', 'U', 'L', + 'H', 'E', 'A', 'D', 'E', 'D', + 'H', 'E', 'A', 'V', 'E', 'N', + 'H', 'E', 'B', 'R', 'E', 'W', + 'H', 'E', 'I', 'S', 'E', 'I', + 'H', 'E', 'L', 'M', 'E', 'T', + 'H', 'E', 'R', 'M', 'E', 'S', + 'H', 'E', 'R', 'U', 'T', 'U', + 'H', 'I', 'D', 'I', 'N', 'G', + 'H', 'U', 'I', 'I', 'T', 'O', + 'H', 'Y', 'P', 'H', 'E', 'N', + 'I', '-', 'B', 'E', 'A', 'M', + 'I', 'L', 'I', 'M', 'M', 'U', + 'I', 'N', 'G', 'W', 'A', 'Z', + 'I', 'N', 'I', 'N', 'G', 'U', + 'I', 'N', 'S', 'E', 'C', 'T', + 'I', 'N', 'S', 'I', 'D', 'E', + 'I', 'S', 'A', 'K', 'I', 'A', + 'I', 'S', 'S', 'H', 'A', 'R', + 'I', 'T', 'A', 'L', 'I', 'C', + 'I', 'Y', 'A', 'N', 'N', 'A', + 'J', 'O', 'I', 'N', 'E', 'D', + 'J', 'O', 'I', 'N', 'E', 'R', + 'J', 'O', 'Y', 'O', 'U', 'S', + 'K', 'A', 'N', 'A', 'K', 'O', + 'K', 'A', 'N', 'G', 'X', 'I', + 'K', 'A', 'S', 'K', 'A', 'L', + 'K', 'A', 'T', 'A', 'V', 'A', + 'K', 'A', 'V', 'Y', 'K', 'A', + 'K', 'A', 'Z', 'A', 'K', 'H', + 'K', 'E', 'F', 'U', 'L', 'A', + 'K', 'E', 'L', 'V', 'I', 'N', + 'K', 'E', 'M', 'P', 'L', 'I', + 'K', 'E', 'M', 'P', 'U', 'L', + 'K', 'E', 'Y', 'C', 'A', 'P', + 'K', 'H', 'A', 'N', 'D', 'A', + 'K', 'H', 'O', 'M', 'U', 'T', + 'K', 'I', 'S', 'I', 'M', '5', + 'K', 'I', 'Y', 'E', 'O', 'K', + 'K', 'L', 'A', 'S', 'M', 'A', + 'K', 'L', 'I', 'T', 'O', 'N', + 'K', 'N', 'I', 'G', 'H', 'T', + 'K', 'O', 'R', 'E', 'A', 'N', + 'K', 'O', 'R', 'U', 'N', 'A', + 'K', 'U', 'S', 'H', 'U', '2', + 'K', 'W', 'U', '3', '1', '8', + 'K', 'Y', 'U', 'R', 'I', 'I', + 'L', '-', 'T', 'Y', 'P', 'E', + 'L', 'A', 'H', 'S', 'H', 'U', + 'L', 'A', 'M', 'A', 'D', 'H', + 'L', 'A', 'M', 'B', 'D', 'A', + 'L', 'A', 'R', 'G', 'E', 'R', + 'L', 'A', 'U', 'K', 'A', 'Z', + 'L', 'E', 'A', 'D', 'E', 'R', + 'L', 'E', 'G', 'I', 'O', 'N', + 'L', 'E', 'I', 'M', 'M', 'A', + 'L', 'E', 'N', 'G', 'T', 'H', + 'L', 'E', 'P', 'C', 'H', 'A', + 'L', 'E', 'S', 'S', 'E', 'R', + 'L', 'E', 'T', 'T', 'E', 'R', + 'L', 'I', 'L', 'I', 'T', 'H', + 'L', 'I', 'M', 'M', 'U', '2', + 'L', 'I', 'M', 'M', 'U', '4', + 'L', 'I', 'N', 'E', '-', '1', + 'L', 'I', 'N', 'E', '-', '3', + 'L', 'I', 'N', 'E', '-', '7', + 'L', 'I', 'N', 'E', '-', '9', + 'L', 'I', 'N', 'E', 'A', 'R', + 'L', 'I', 'Q', 'U', 'I', 'D', + 'L', 'I', 'T', 'T', 'L', 'E', + 'L', 'U', 'N', 'A', 'T', 'E', + 'L', 'Y', 'C', 'I', 'A', 'N', + 'L', 'Y', 'D', 'I', 'A', 'N', + 'M', 'A', 'C', 'R', 'O', 'N', + 'M', 'A', 'D', 'D', 'A', 'H', + 'M', 'A', 'I', 'D', 'E', 'N', + 'M', 'A', 'N', 'C', 'H', 'U', + 'M', 'A', 'N', 'N', 'A', 'Z', + 'M', 'A', 'R', 'K', '-', '1', + 'M', 'A', 'R', 'K', '-', '2', + 'M', 'A', 'R', 'K', '-', '3', + 'M', 'A', 'R', 'K', '-', '4', + 'M', 'A', 'R', 'K', 'E', 'R', + 'M', 'A', 'R', 'U', 'K', 'U', + 'M', 'A', 'S', 'O', 'R', 'A', + 'M', 'A', 'T', 'R', 'I', 'X', + 'M', 'A', 'X', 'I', 'M', 'A', + 'M', 'E', 'D', 'I', 'A', 'L', + 'M', 'E', 'D', 'I', 'U', 'M', + 'M', 'E', 'G', 'A', 'L', 'I', + 'M', 'E', 'M', 'B', 'E', 'R', + 'M', 'E', 'R', 'K', 'H', 'A', + 'M', 'E', 'T', 'R', 'I', 'A', + 'M', 'I', 'D', 'D', 'L', 'E', + 'M', 'I', 'K', 'R', 'O', 'N', + 'M', 'I', 'L', 'L', 'E', 'T', + 'M', 'I', 'N', 'I', 'M', 'A', + 'M', 'O', 'D', 'E', 'L', 'S', + 'M', 'O', 'D', 'U', 'L', 'O', + 'M', 'O', 'R', 'T', 'A', 'R', + 'M', 'O', 'T', 'H', 'E', 'R', + 'M', 'U', 'C', 'A', 'A', 'D', + 'M', 'U', 'N', 'S', 'U', 'B', + 'M', 'U', 'Q', 'D', 'A', 'M', + 'M', 'U', 'R', 'G', 'U', '2', + 'N', '-', 'C', 'R', 'E', 'E', + 'N', 'A', 'R', 'R', 'O', 'W', + 'N', 'A', 'U', 'D', 'I', 'Z', + 'N', 'A', 'U', 'T', 'H', 'S', + 'N', 'A', 'X', 'I', 'A', 'N', + 'N', 'E', 'N', 'A', 'N', 'O', + 'N', 'E', 'S', 'T', 'E', 'D', + 'N', 'E', 'U', 'T', 'E', 'R', + 'N', 'I', 'N', 'D', 'A', '2', + 'N', 'I', 'N', 'E', 'T', 'Y', + 'N', 'I', 'R', 'U', 'G', 'U', + 'N', 'O', 'K', 'H', 'U', 'K', + 'N', 'O', 'R', 'M', 'A', 'L', + 'N', 'U', 'B', 'I', 'A', 'N', + 'N', 'U', 'M', 'B', 'E', 'R', + 'N', 'U', 'M', 'E', 'R', 'O', + 'O', 'B', 'E', 'L', 'O', 'S', + 'O', 'B', 'E', 'L', 'U', 'S', + 'O', 'B', 'J', 'E', 'C', 'T', + 'O', 'G', 'O', 'N', 'E', 'K', + 'O', 'L', 'I', 'G', 'O', 'N', + 'O', 'M', 'A', 'L', 'O', 'N', + 'O', 'P', 'E', 'N', '-', 'P', + 'O', 'P', 'P', 'O', 'S', 'E', + 'O', 'P', 'T', 'I', 'O', 'N', + 'O', 'R', 'C', 'H', 'I', 'D', + 'O', 'R', 'I', 'G', 'I', 'N', + 'O', 'R', 'N', 'A', 'T', 'E', + 'O', 'T', 'T', 'A', 'V', 'A', + 'O', 'U', 'N', 'K', 'I', 'A', + 'O', 'X', 'E', 'I', 'A', 'I', + 'O', 'Y', 'A', 'N', 'N', 'A', + 'P', 'A', 'I', 'R', 'E', 'D', + 'P', 'A', 'L', 'L', 'A', 'S', + 'P', 'A', 'L', 'U', 'T', 'A', + 'P', 'A', 'M', 'A', 'D', 'A', + 'P', 'A', 'S', 'H', 'T', 'A', + 'P', 'E', 'N', 'C', 'I', 'L', + 'P', 'E', 'N', 'I', 'H', 'I', + 'P', 'E', 'O', 'R', 'T', 'H', + 'P', 'E', 'R', 'S', 'O', 'N', + 'P', 'E', 'R', 'T', 'H', 'O', + 'P', 'E', 'S', 'E', 'T', 'A', + 'P', 'H', 'N', 'A', 'E', 'K', + 'P', 'H', 'R', 'A', 'S', 'E', + 'P', 'I', 'A', 'S', 'M', 'A', + 'P', 'I', 'K', 'U', 'R', 'U', + 'P', 'I', 'P', 'I', 'N', 'G', + 'P', 'I', 'S', 'C', 'E', 'S', + 'P', 'L', 'A', 'N', 'C', 'K', + 'P', 'L', 'O', 'P', 'H', 'U', + 'P', 'L', 'U', 'M', 'E', 'D', + 'P', 'O', 'E', 'T', 'I', 'C', + 'P', 'O', 'E', 'T', 'R', 'Y', + 'P', 'O', 'I', 'N', 'T', 'O', + 'P', 'O', 'K', 'O', 'J', 'I', + 'P', 'O', 'S', 'T', 'A', 'L', + 'P', 'O', 'W', 'E', 'R', 'S', + 'P', 'R', 'O', 'T', 'O', 'S', + 'P', 'S', 'I', 'L', 'O', 'N', + 'P', 'T', 'H', 'A', 'H', 'A', + 'P', 'U', 'R', 'I', 'T', 'Y', + 'Q', 'A', 'M', 'A', 'T', 'S', + 'Q', 'A', 'R', 'N', 'E', 'Y', + 'Q', 'E', 'T', 'A', 'N', 'A', + 'Q', 'U', 'B', 'U', 'T', 'S', + 'R', '-', 'C', 'R', 'E', 'E', + 'R', 'A', 'I', 'S', 'E', 'D', + 'R', 'A', 'M', 'B', 'A', 'T', + 'R', 'A', 'S', 'O', 'U', 'L', + 'R', 'E', 'C', 'O', 'R', 'D', + 'R', 'E', 'J', 'A', 'N', 'G', + 'R', 'E', 'P', 'E', 'A', 'T', + 'R', 'E', 'T', 'U', 'R', 'N', + 'R', 'H', 'O', 'T', 'I', 'C', + 'R', 'I', 'K', 'R', 'I', 'K', + 'R', 'I', 'S', 'I', 'N', 'G', + 'R', 'I', 'T', 'U', 'A', 'L', + 'R', 'N', 'Y', 'I', 'N', 'G', + 'R', 'U', 'N', 'O', 'U', 'T', + 'S', 'A', 'A', 'D', 'H', 'U', + 'S', 'A', 'J', 'D', 'A', 'H', + 'S', 'A', 'M', 'E', 'K', 'H', + 'S', 'A', 'M', 'Y', 'O', 'K', + 'S', 'A', 'N', 'G', 'A', '2', + 'S', 'A', 'N', 'N', 'Y', 'A', + 'S', 'A', 'T', 'U', 'R', 'N', + 'S', 'A', 'Y', 'I', 'S', 'I', + 'S', 'C', 'A', 'L', 'E', 'S', + 'S', 'C', 'H', 'E', 'M', 'A', + 'S', 'C', 'R', 'E', 'E', 'N', + 'S', 'C', 'R', 'I', 'P', 'T', + 'S', 'E', 'C', 'O', 'N', 'D', + 'S', 'E', 'C', 'R', 'E', 'T', + 'S', 'E', 'C', 'T', 'O', 'R', + 'S', 'E', 'I', 'S', 'M', 'A', + 'S', 'E', 'R', 'I', 'F', 'S', + 'S', 'E', 'S', 'A', 'M', 'E', + 'S', 'H', 'A', 'D', 'D', 'A', + 'S', 'H', 'A', 'K', 'T', 'I', + 'S', 'H', 'A', 'P', 'E', 'S', + 'S', 'H', 'E', 'E', 'N', 'U', + 'S', 'H', 'E', 'Q', 'E', 'L', + 'S', 'H', 'E', 'S', 'H', '2', + 'S', 'H', 'I', 'E', 'L', 'D', + 'S', 'H', 'I', 'N', 'I', 'G', + 'S', 'H', 'O', 'R', 'T', 'S', + 'S', 'H', 'U', 'B', 'U', 'R', + 'S', 'I', 'C', 'K', 'L', 'E', + 'S', 'I', 'N', 'D', 'H', 'I', + 'S', 'I', 'N', 'G', 'L', 'E', + 'S', 'I', 'X', 'T', 'H', 'S', + 'S', 'K', 'E', 'W', 'E', 'D', + 'S', 'L', 'O', 'W', 'L', 'Y', + 'S', 'O', 'U', 'R', 'C', 'E', + 'S', 'O', 'W', 'I', 'L', 'O', + 'S', 'P', 'A', 'T', 'H', 'I', + 'S', 'P', 'E', 'E', 'C', 'H', + 'S', 'P', 'I', 'R', 'A', 'L', + 'S', 'P', 'I', 'R', 'I', 'T', + 'S', 'P', 'O', 'K', 'E', 'D', + 'S', 'P', 'R', 'I', 'N', 'G', + 'S', 'P', 'R', 'O', 'U', 'T', + 'S', 'P', 'U', 'N', 'G', 'S', + 'S', 'Q', 'U', 'A', 'R', 'E', + 'S', 'Q', 'U', 'I', 'S', 'H', + 'S', 'T', 'I', 'G', 'M', 'A', + 'S', 'T', 'I', 'M', 'M', 'E', + 'S', 'T', 'R', 'A', 'I', 'F', + 'S', 'T', 'R', 'E', 'S', 'S', + 'S', 'T', 'R', 'I', 'D', 'E', + 'S', 'T', 'R', 'O', 'K', 'E', + 'S', 'U', 'B', 'I', 'T', 'O', + 'S', 'U', 'B', 'S', 'E', 'T', + 'S', 'U', 'M', 'A', 'S', 'H', + 'S', 'U', 'M', 'M', 'E', 'R', + 'S', 'U', 'R', 'A', 'N', 'G', + 'S', 'W', 'O', 'R', 'D', 'S', + 'S', 'Y', 'L', 'O', 'T', 'I', + 'S', 'Y', 'M', 'B', 'O', 'L', + 'S', 'Y', 'N', 'A', 'F', 'I', + 'S', 'Y', 'O', 'U', 'W', 'A', + 'S', 'Y', 'R', 'I', 'A', 'C', + 'T', 'A', '-', 'R', 'O', 'L', + 'T', 'A', 'I', 'L', 'E', 'D', + 'T', 'A', 'L', 'E', 'N', 'T', + 'T', 'A', 'L', 'I', 'N', 'G', + 'T', 'A', 'M', 'I', 'N', 'G', + 'T', 'A', 'N', 'N', 'E', 'D', + 'T', 'A', 'U', 'R', 'U', 'S', + 'T', 'E', 'D', 'U', 'N', 'G', + 'T', 'E', 'L', 'E', 'I', 'A', + 'T', 'E', 'L', 'O', 'U', 'S', + 'T', 'E', 'L', 'U', 'G', 'U', + 'T', 'E', 'M', 'P', 'U', 'S', + 'T', 'E', 'N', 'U', 'T', 'O', + 'T', 'H', 'A', 'A', 'L', 'U', + 'T', 'H', 'A', 'A', 'N', 'A', + 'T', 'H', 'A', 'H', 'A', 'N', + 'T', 'H', 'A', 'N', 'N', 'A', + 'T', 'H', 'E', 'T', 'H', 'E', + 'T', 'H', 'I', 'R', 'D', 'S', + 'T', 'H', 'I', 'R', 'T', 'Y', + 'T', 'H', 'I', 'U', 'T', 'H', + 'T', 'H', 'R', 'E', 'A', 'D', + 'T', 'H', 'Y', 'O', 'O', 'M', + 'T', 'I', 'K', 'E', 'U', 'T', + 'T', 'I', 'P', 'E', 'H', 'A', + 'T', 'O', 'N', 'E', '-', '1', + 'T', 'O', 'N', 'E', '-', '2', + 'T', 'O', 'N', 'E', '-', '3', + 'T', 'O', 'N', 'E', '-', '4', + 'T', 'O', 'N', 'E', '-', '5', + 'T', 'O', 'N', 'E', '-', '6', + 'T', 'O', 'N', 'G', 'U', 'E', + 'T', 'O', 'P', 'B', 'A', 'R', + 'T', 'R', 'I', 'P', 'L', 'E', + 'T', 'R', 'I', 'P', 'L', 'I', + 'T', 'R', 'I', 'P', 'O', 'D', + 'T', 'R', 'I', 'T', 'O', 'S', + 'T', 'S', 'H', 'O', 'O', 'K', + 'T', 'S', 'H', 'U', 'G', 'S', + 'T', 'T', 'E', 'H', 'E', 'H', + 'T', 'U', 'A', 'R', 'E', 'G', + 'T', 'U', 'G', 'R', 'I', 'K', + 'T', 'U', 'R', 'B', 'A', 'N', + 'T', 'U', 'R', 'N', 'E', 'D', + 'T', 'U', 'R', 'T', 'L', 'E', + 'T', 'V', 'R', 'I', 'D', 'O', + 'T', 'W', 'E', 'L', 'V', 'E', + 'T', 'W', 'E', 'N', 'T', 'Y', + 'T', 'Y', 'P', 'E', '-', '1', + 'T', 'Y', 'P', 'E', '-', '2', + 'T', 'Y', 'P', 'E', '-', '3', + 'T', 'Y', 'P', 'E', '-', '4', + 'T', 'Y', 'P', 'E', '-', '5', + 'T', 'Y', 'P', 'E', '-', '6', + 'T', 'Y', 'P', 'E', '-', '7', + 'U', 'D', 'A', 'T', 'T', 'A', + 'U', 'I', 'G', 'H', 'U', 'R', + 'U', 'P', 'T', 'U', 'R', 'N', + 'U', 'P', 'W', 'A', 'R', 'D', + 'U', 'R', 'A', 'N', 'U', 'S', + 'U', 'S', 'H', 'U', 'M', 'X', + 'U', 'Y', 'A', 'N', 'N', 'A', + 'V', 'A', 'L', 'L', 'E', 'Y', + 'V', 'A', 'R', 'E', 'I', 'A', + 'V', 'A', 'R', 'I', 'K', 'A', + 'V', 'E', 'C', 'T', 'O', 'R', + 'V', 'E', 'S', 'S', 'E', 'L', + 'V', 'I', 'R', 'A', 'M', 'A', + 'V', 'I', 'R', 'I', 'A', 'M', + 'V', 'O', 'I', 'C', 'E', 'D', + 'V', 'O', 'L', 'U', 'M', 'E', + 'V', 'R', 'A', 'C', 'H', 'Y', + 'V', 'U', 'L', 'G', 'A', 'R', + 'W', 'E', 'A', 'P', 'O', 'N', + 'W', 'E', 'I', 'G', 'H', 'T', + 'W', 'I', 'G', 'G', 'L', 'Y', + 'W', 'I', 'N', 'T', 'E', 'R', + 'W', 'O', 'L', 'O', 'S', 'O', + 'W', 'R', 'E', 'A', 'T', 'H', + 'X', 'E', 'S', 'T', 'E', 'S', + 'Y', '-', 'C', 'R', 'E', 'E', + 'Y', 'A', 'K', 'A', 'S', 'H', + 'Y', 'E', 'L', 'L', 'O', 'W', + 'Y', 'F', 'E', 'S', 'I', 'S', + 'Y', 'O', '-', 'Y', 'A', 'E', + 'Y', 'O', '-', 'Y', 'E', 'O', + 'Y', 'P', 'S', 'I', 'L', 'I', + 'Y', 'U', '-', 'Y', 'E', 'O', + 'Z', 'E', 'M', 'L', 'J', 'A', + 'Z', 'E', 'M', 'L', 'Y', 'A', + 'Z', 'I', 'G', 'Z', 'A', 'G', + 'Z', 'Q', 'A', 'P', 'H', 'A', + 'A', 'A', 'Y', 'A', 'N', 'N', 'A', + 'A', 'B', 'A', 'F', 'I', 'L', 'I', + 'A', 'B', 'Y', 'S', 'M', 'A', 'L', + 'A', 'C', 'A', 'D', 'E', 'M', 'Y', + 'A', 'C', 'C', 'O', 'U', 'N', 'T', + 'A', 'D', 'V', 'A', 'N', 'C', 'E', + 'A', 'E', 'Y', 'A', 'N', 'N', 'A', + 'A', 'F', 'G', 'H', 'A', 'N', 'I', + 'A', 'F', 'R', 'I', 'C', 'A', 'N', + 'A', 'H', 'A', 'G', 'G', 'A', 'R', + 'A', 'I', 'V', 'I', 'L', 'I', 'K', + 'A', 'I', 'Y', 'A', 'N', 'N', 'A', + 'A', 'L', 'E', 'M', 'B', 'I', 'C', + 'A', 'L', 'I', 'G', 'N', 'E', 'D', + 'A', 'L', 'L', 'A', 'H', 'O', 'U', + 'A', 'N', 'G', 'U', 'L', 'A', 'R', + 'A', 'N', 'N', 'U', 'I', 'T', 'Y', + 'A', 'P', 'O', 'T', 'H', 'E', 'S', + 'A', 'R', 'A', 'E', 'A', '-', 'I', + 'A', 'R', 'A', 'E', 'A', '-', 'U', + 'A', 'R', 'C', 'H', 'A', 'I', 'C', + 'A', 'R', 'K', 'T', 'I', 'K', 'O', + 'A', 'U', 'S', 'T', 'R', 'A', 'L', + 'A', 'U', 'Y', 'A', 'N', 'N', 'A', + 'A', 'V', 'E', 'R', 'A', 'G', 'E', + 'B', 'A', 'A', 'R', 'E', 'R', 'U', + 'B', 'A', 'I', 'R', 'K', 'A', 'N', + 'B', 'A', 'M', 'B', 'O', 'O', 'S', + 'B', 'A', 'R', 'L', 'I', 'N', 'E', + 'B', 'A', 'R', 'R', 'E', 'K', 'H', + 'B', 'A', 'R', 'R', 'I', 'E', 'R', + 'B', 'A', 'S', 'H', 'K', 'I', 'R', + 'B', 'A', 'T', 'H', 'T', 'U', 'B', + 'B', 'A', 'Y', 'A', 'N', 'N', 'A', + 'B', 'E', 'C', 'A', 'U', 'S', 'E', + 'B', 'E', 'E', 'H', 'I', 'V', 'E', + 'B', 'E', 'N', 'G', 'A', 'L', 'I', + 'B', 'E', 'N', 'Z', 'E', 'N', 'E', + 'B', 'E', 'T', 'W', 'E', 'E', 'N', + 'B', 'I', 'N', 'D', 'I', 'N', 'G', + 'B', 'J', 'A', 'R', 'K', 'A', 'N', + 'B', 'L', 'E', 'N', 'D', 'E', 'D', + 'B', 'R', 'A', 'C', 'K', 'E', 'T', + 'B', 'R', 'A', 'I', 'L', 'L', 'E', + 'B', 'R', 'A', 'K', 'C', 'E', 'T', + 'B', 'R', 'I', 'S', 'T', 'L', 'E', + 'B', 'U', 'U', 'M', 'I', 'S', 'H', + 'C', 'A', 'E', 'S', 'U', 'R', 'A', + 'C', 'A', 'P', 'I', 'T', 'A', 'L', + 'C', 'A', 'P', 'T', 'I', 'V', 'E', + 'C', 'A', 'R', 'R', 'I', 'E', 'R', + 'C', 'A', 'U', 'T', 'I', 'O', 'N', + 'C', 'A', 'Y', 'A', 'N', 'N', 'A', + 'C', 'E', 'D', 'I', 'L', 'L', 'A', + 'C', 'E', 'I', 'L', 'I', 'N', 'G', + 'C', 'E', 'L', 'S', 'I', 'U', 'S', + 'C', 'E', 'N', 'T', 'R', 'E', 'D', + 'C', 'H', 'A', 'M', 'I', 'L', 'I', + 'C', 'H', 'A', 'R', 'I', 'O', 'T', + 'C', 'H', 'E', 'V', 'R', 'O', 'N', + 'C', 'H', 'I', 'E', 'U', 'C', 'H', + 'C', 'H', 'I', 'N', 'E', 'S', 'E', + 'C', 'H', 'R', 'O', 'N', 'O', 'N', + 'C', 'H', 'R', 'O', 'N', 'O', 'U', + 'C', 'I', 'R', 'C', 'L', 'E', 'D', + 'C', 'I', 'R', 'C', 'L', 'E', 'S', + 'C', 'L', 'O', 'S', 'I', 'N', 'G', + 'C', 'L', 'O', 'S', 'U', 'R', 'E', + 'C', 'L', 'O', 'T', 'H', 'E', 'S', + 'C', 'L', 'U', 'S', 'T', 'E', 'R', + 'C', 'O', 'M', 'P', 'A', 'R', 'E', + 'C', 'O', 'N', 'I', 'C', 'A', 'L', + 'C', 'O', 'N', 'T', 'A', 'C', 'T', + 'C', 'O', 'N', 'T', 'A', 'I', 'N', + 'C', 'O', 'N', 'T', 'O', 'U', 'R', + 'C', 'O', 'N', 'T', 'R', 'O', 'L', + 'C', 'O', 'R', 'N', 'E', 'R', 'S', + 'C', 'O', 'R', 'O', 'N', 'I', 'S', + 'C', 'O', 'R', 'R', 'E', 'C', 'T', + 'C', 'O', 'U', 'N', 'C', 'I', 'L', + 'C', 'R', 'O', 'S', 'S', 'E', 'D', + 'C', 'U', 'R', 'R', 'E', 'N', 'T', + 'C', 'U', 'R', 'V', 'I', 'N', 'G', + 'C', 'W', 'E', 'O', 'R', 'T', 'H', + 'C', 'Y', 'P', 'E', 'R', 'U', 'S', + 'C', 'Y', 'P', 'R', 'I', 'O', 'T', + 'D', 'A', 'G', 'A', 'L', 'G', 'A', + 'D', 'A', 'N', 'T', 'A', 'J', 'A', + 'D', 'A', 'P', '-', 'B', 'E', 'I', + 'D', 'A', 'P', '-', 'P', 'I', 'I', + 'D', 'A', 'Y', 'A', 'N', 'N', 'A', + 'D', 'E', 'C', 'A', 'Y', 'E', 'D', + 'D', 'E', 'C', 'I', 'M', 'A', 'L', + 'D', 'E', 'L', 'P', 'H', 'I', 'C', + 'D', 'E', 'S', 'E', 'R', 'E', 'T', + 'D', 'H', 'A', 'L', 'A', 'T', 'H', + 'D', 'I', 'A', 'M', 'O', 'N', 'D', + 'D', 'I', 'A', 'R', 'G', 'O', 'N', + 'D', 'I', 'G', 'A', 'M', 'M', 'A', + 'D', 'I', 'G', 'R', 'A', 'P', 'H', + 'D', 'I', 'M', 'I', 'D', 'I', 'A', + 'D', 'I', 'M', 'M', 'I', 'N', 'G', + 'D', 'I', 'N', 'G', 'B', 'A', 'T', + 'D', 'I', 'P', 'L', 'O', 'U', 'N', + 'D', 'I', 'S', 'I', 'M', 'O', 'U', + 'D', 'I', 'V', 'I', 'D', 'E', 'D', + 'D', 'I', 'V', 'I', 'D', 'E', 'R', + 'D', 'I', 'V', 'I', 'D', 'E', 'S', + 'D', 'I', 'V', 'O', 'R', 'C', 'E', + 'D', 'O', 'T', 'L', 'E', 'S', 'S', + 'D', 'O', 'T', 'S', '-', '1', '2', + 'D', 'O', 'T', 'S', '-', '1', '3', + 'D', 'O', 'T', 'S', '-', '1', '4', + 'D', 'O', 'T', 'S', '-', '1', '5', + 'D', 'O', 'T', 'S', '-', '1', '6', + 'D', 'O', 'T', 'S', '-', '1', '7', + 'D', 'O', 'T', 'S', '-', '1', '8', + 'D', 'O', 'T', 'S', '-', '2', '3', + 'D', 'O', 'T', 'S', '-', '2', '4', + 'D', 'O', 'T', 'S', '-', '2', '5', + 'D', 'O', 'T', 'S', '-', '2', '6', + 'D', 'O', 'T', 'S', '-', '2', '7', + 'D', 'O', 'T', 'S', '-', '2', '8', + 'D', 'O', 'T', 'S', '-', '3', '4', + 'D', 'O', 'T', 'S', '-', '3', '5', + 'D', 'O', 'T', 'S', '-', '3', '6', + 'D', 'O', 'T', 'S', '-', '3', '7', + 'D', 'O', 'T', 'S', '-', '3', '8', + 'D', 'O', 'T', 'S', '-', '4', '5', + 'D', 'O', 'T', 'S', '-', '4', '6', + 'D', 'O', 'T', 'S', '-', '4', '7', + 'D', 'O', 'T', 'S', '-', '4', '8', + 'D', 'O', 'T', 'S', '-', '5', '6', + 'D', 'O', 'T', 'S', '-', '5', '7', + 'D', 'O', 'T', 'S', '-', '5', '8', + 'D', 'O', 'T', 'S', '-', '6', '7', + 'D', 'O', 'T', 'S', '-', '6', '8', + 'D', 'O', 'T', 'S', '-', '7', '8', + 'D', 'O', 'U', 'B', 'L', 'E', 'D', + 'D', 'R', 'A', 'C', 'H', 'M', 'A', + 'E', 'A', 'B', 'H', 'A', 'D', 'H', + 'E', 'A', 'D', 'H', 'A', 'D', 'H', + 'E', 'A', 'R', 'T', 'H', 'L', 'Y', + 'E', 'A', 'S', 'T', 'E', 'R', 'N', + 'E', 'B', 'E', 'F', 'I', 'L', 'I', + 'E', 'E', 'Y', 'A', 'N', 'N', 'A', + 'E', 'I', 'G', 'H', 'T', 'H', 'S', + 'E', 'L', 'A', 'F', 'R', 'O', 'N', + 'E', 'L', 'E', 'M', 'E', 'N', 'T', + 'E', 'L', 'L', 'I', 'P', 'S', 'E', + 'E', 'N', 'A', 'R', 'X', 'I', 'S', + 'E', 'N', 'Q', 'U', 'I', 'R', 'Y', + 'E', 'P', 'S', 'I', 'L', 'O', 'N', + 'E', 'T', 'N', 'A', 'H', 'T', 'A', + 'E', 'V', 'E', 'N', 'I', 'N', 'G', + 'F', 'A', 'I', 'L', 'U', 'R', 'E', + 'F', 'A', 'L', 'L', 'I', 'N', 'G', + 'F', 'A', 'Y', 'A', 'N', 'N', 'A', + 'F', 'E', 'A', 'T', 'H', 'E', 'R', + 'F', 'E', 'R', 'M', 'A', 'T', 'A', + 'F', 'I', 'F', 'T', 'E', 'E', 'N', + 'F', 'I', 'S', 'H', 'E', 'Y', 'E', + 'F', 'O', 'N', 'G', 'M', 'A', 'N', + 'F', 'O', 'R', 'K', 'I', 'N', 'G', + 'F', 'R', 'A', 'K', 'T', 'U', 'R', + 'F', 'U', 'N', 'E', 'R', 'A', 'L', + 'G', 'A', 'A', 'H', 'L', 'A', 'A', + 'G', 'A', 'R', 'M', 'E', 'N', 'T', + 'G', 'A', 'Y', 'A', 'N', 'N', 'A', + 'G', 'E', 'N', 'E', 'R', 'I', 'C', + 'G', 'E', 'S', 'H', 'T', 'I', 'N', + 'G', 'I', 'R', 'U', 'D', 'A', 'A', + 'G', 'L', 'A', 'G', 'O', 'L', 'I', + 'G', 'L', 'O', 'T', 'T', 'A', 'L', + 'G', 'R', 'E', 'A', 'T', 'E', 'R', + 'G', 'U', 'A', 'R', 'A', 'N', 'I', + 'H', 'A', 'F', 'U', 'K', 'H', 'A', + 'H', 'A', 'L', 'A', 'N', 'T', 'A', + 'H', 'A', 'L', 'B', 'E', 'R', 'D', + 'H', 'A', 'N', 'U', 'N', 'O', 'O', + 'H', 'A', 'R', 'P', 'O', 'O', 'N', + 'H', 'A', 'S', 'A', 'N', 'T', 'A', + 'H', 'A', 'Y', 'A', 'N', 'N', 'A', + 'H', 'E', '-', 'G', 'O', 'A', 'T', + 'H', 'E', 'A', 'D', 'I', 'N', 'G', + 'H', 'E', 'R', 'A', 'E', 'U', 'M', + 'H', 'E', 'X', 'A', 'G', 'O', 'N', + 'H', 'O', 'L', 'D', 'I', 'N', 'G', + 'H', 'R', 'Y', 'V', 'N', 'I', 'A', + 'H', 'U', 'N', 'D', 'R', 'E', 'D', + 'I', '-', 'A', 'R', 'A', 'E', 'A', + 'I', 'B', 'I', 'F', 'I', 'L', 'I', + 'I', 'C', 'H', 'A', 'D', 'I', 'N', + 'I', 'I', 'Y', 'A', 'N', 'N', 'A', + 'I', 'L', 'I', 'M', 'M', 'U', '3', + 'I', 'L', 'I', 'M', 'M', 'U', '4', + 'I', 'M', 'I', 'S', 'E', 'O', 'S', + 'I', 'N', 'H', 'I', 'B', 'I', 'T', + 'I', 'N', 'I', 'T', 'I', 'A', 'L', + 'I', 'N', 'S', 'U', 'L', 'A', 'R', + 'I', 'N', 'V', 'E', 'R', 'S', 'E', + 'I', 'O', 'D', 'H', 'A', 'D', 'H', + 'I', 'O', 'T', 'A', 'T', 'E', 'D', + 'I', 'Z', 'H', 'I', 'T', 'S', 'A', + 'J', 'A', 'N', 'U', 'A', 'R', 'Y', + 'J', 'A', 'Y', 'A', 'N', 'N', 'A', + 'J', 'E', 'G', 'O', 'G', 'A', 'N', + 'J', 'U', 'P', 'I', 'T', 'E', 'R', + 'K', 'A', 'K', 'A', 'B', 'A', 'T', + 'K', 'A', 'N', 'N', 'A', 'D', 'A', + 'K', 'A', 'N', 'T', 'A', 'J', 'A', + 'K', 'A', 'R', 'A', 'T', 'T', 'O', + 'K', 'A', 'R', 'O', 'R', 'I', 'I', + 'K', 'A', 'Y', 'A', 'N', 'N', 'A', + 'K', 'E', 'E', 'P', 'I', 'N', 'G', + 'K', 'E', 'M', 'B', 'A', 'N', 'G', + 'K', 'E', 'N', 'T', 'I', 'M', 'A', + 'K', 'H', 'I', 'E', 'U', 'K', 'H', + 'K', 'I', 'N', 'S', 'H', 'I', 'P', + 'K', 'I', 'R', 'G', 'H', 'I', 'Z', + 'K', 'O', 'M', 'B', 'U', 'V', 'A', + 'K', 'O', 'O', 'M', 'U', 'U', 'T', + 'K', 'O', 'R', 'A', 'N', 'I', 'C', + 'K', 'O', 'R', 'O', 'N', 'I', 'S', + 'K', 'R', 'A', 'T', 'I', 'M', 'A', + 'K', 'U', 'R', 'O', 'O', 'N', 'E', + 'K', 'Y', 'A', 'T', 'H', 'O', 'S', + 'K', 'Y', 'L', 'I', 'S', 'M', 'A', + 'L', 'A', 'T', 'E', 'R', 'A', 'L', + 'L', 'A', 'Y', 'A', 'N', 'N', 'A', + 'L', 'E', 'A', 'T', 'H', 'E', 'R', + 'L', 'E', 'G', 'E', 'T', 'O', 'S', + 'L', 'I', 'M', 'I', 'T', 'E', 'D', + 'L', 'I', 'N', 'K', 'I', 'N', 'G', + 'L', 'J', 'U', 'D', 'I', 'J', 'E', + 'L', 'O', 'G', 'I', 'C', 'A', 'L', + 'L', 'O', 'Z', 'E', 'N', 'G', 'E', + 'L', 'Y', 'G', 'I', 'S', 'M', 'A', + 'M', 'A', 'H', 'J', 'O', 'N', 'G', + 'M', 'A', 'I', 'K', 'U', 'R', 'O', + 'M', 'A', 'I', 'M', 'U', 'A', 'N', + 'M', 'A', 'K', 'S', 'U', 'R', 'A', + 'M', 'A', 'L', 'A', 'K', 'O', 'N', + 'M', 'A', 'L', 'T', 'E', 'S', 'E', + 'M', 'A', 'N', 'S', 'Y', 'O', 'N', + 'M', 'A', 'R', 'B', 'U', 'T', 'A', + 'M', 'A', 'R', 'C', 'A', 'T', 'O', + 'M', 'A', 'S', 'S', 'I', 'N', 'G', + 'M', 'A', 'T', 'T', 'O', 'C', 'K', + 'M', 'A', 'Y', 'A', 'N', 'N', 'A', + 'M', 'E', 'A', 'S', 'U', 'R', 'E', + 'M', 'E', 'E', 'T', 'O', 'R', 'U', + 'M', 'E', 'G', 'A', 'T', 'O', 'N', + 'M', 'E', 'R', 'C', 'U', 'R', 'Y', + 'M', 'I', 'D', 'L', 'I', 'N', 'E', + 'M', 'I', 'K', 'U', 'R', 'O', 'N', + 'M', 'O', 'D', 'E', 'S', 'T', 'Y', + 'M', 'O', 'R', 'N', 'I', 'N', 'G', + 'M', 'U', 'S', 'I', 'C', 'A', 'L', + 'M', 'Y', 'A', 'N', 'M', 'A', 'R', + 'M', 'Y', 'S', 'L', 'I', 'T', 'E', + 'N', 'A', 'S', 'K', 'A', 'P', 'I', + 'N', 'A', 'T', 'U', 'R', 'A', 'L', + 'N', 'A', 'Y', 'A', 'N', 'N', 'A', + 'N', 'E', 'G', 'A', 'T', 'E', 'D', + 'N', 'E', 'I', 'T', 'H', 'E', 'R', + 'N', 'E', 'P', 'T', 'U', 'N', 'E', + 'N', 'E', 'U', 'T', 'R', 'A', 'L', + 'N', 'E', 'W', 'L', 'I', 'N', 'E', + 'N', 'G', 'E', 'A', 'D', 'A', 'L', + 'N', 'I', 'K', 'A', 'H', 'I', 'T', + 'N', 'O', 'M', 'I', 'N', 'A', 'L', + 'N', 'O', 'T', 'C', 'H', 'E', 'D', + 'N', 'U', 'M', 'E', 'R', 'A', 'L', + 'N', 'U', 'M', 'E', 'R', 'I', 'C', + 'N', 'U', 'N', 'A', 'V', 'I', 'K', + 'N', 'U', 'N', 'A', 'V', 'U', 'T', + 'N', 'U', 'T', 'I', 'L', 'L', 'U', + 'N', 'Y', 'I', 'N', '-', 'D', 'O', + 'O', 'B', 'L', 'I', 'Q', 'U', 'E', + 'O', 'B', 'O', 'F', 'I', 'L', 'I', + 'O', 'C', 'T', 'O', 'B', 'E', 'R', + 'O', 'M', 'I', 'C', 'R', 'O', 'N', + 'O', 'N', 'E', 'S', 'E', 'L', 'F', + 'O', 'O', 'Y', 'A', 'N', 'N', 'A', + 'O', 'P', 'E', 'N', 'I', 'N', 'G', + 'O', 'R', 'D', 'I', 'N', 'A', 'L', + 'O', 'S', 'M', 'A', 'N', 'Y', 'A', + 'O', 'T', 'H', 'A', 'L', 'A', 'N', + 'O', 'U', 'T', 'L', 'I', 'N', 'E', + 'O', 'V', 'E', 'R', 'B', 'A', 'R', + 'O', 'V', 'E', 'R', 'L', 'A', 'Y', + 'P', 'A', 'C', 'K', 'I', 'N', 'G', + 'P', 'A', 'L', 'A', 'T', 'A', 'L', + 'P', 'A', 'L', 'A', 'U', 'N', 'G', + 'P', 'A', 'L', 'L', 'A', 'W', 'A', + 'P', 'A', 'M', 'A', 'A', 'E', 'H', + 'P', 'A', 'M', 'E', 'P', 'E', 'T', + 'P', 'A', 'N', 'S', 'I', 'O', 'S', + 'P', 'A', 'N', 'Y', 'I', 'K', 'U', + 'P', 'A', 'N', 'Y', 'U', 'K', 'U', + 'P', 'A', 'P', 'Y', 'R', 'U', 'S', + 'P', 'A', 'R', 'E', 'R', 'E', 'N', + 'P', 'A', 'R', 'T', 'I', 'A', 'L', + 'P', 'A', 'T', 'T', 'E', 'R', 'N', + 'P', 'A', 'Y', 'A', 'N', 'N', 'A', + 'P', 'A', 'Y', 'E', 'R', 'O', 'K', + 'P', 'E', 'R', 'C', 'E', 'N', 'T', + 'P', 'E', 'R', 'S', 'I', 'A', 'N', + 'P', 'E', 'T', 'A', 'S', 'M', 'A', + 'P', 'E', 'T', 'A', 'S', 'T', 'I', + 'P', 'H', 'I', 'E', 'U', 'P', 'H', + 'P', 'H', 'I', 'N', 'T', 'H', 'U', + 'P', 'H', 'U', 'T', 'H', 'A', 'O', + 'P', 'I', 'L', 'C', 'R', 'O', 'W', + 'P', 'L', 'A', 'G', 'I', 'O', 'S', + 'P', 'O', 'D', 'A', 'T', 'U', 'S', + 'P', 'O', 'I', 'N', 'T', 'E', 'D', + 'P', 'O', 'I', 'N', 'T', 'E', 'R', + 'P', 'R', 'E', 'C', 'E', 'D', 'E', + 'P', 'R', 'E', 'F', 'A', 'C', 'E', + 'P', 'R', 'I', 'V', 'A', 'T', 'E', + 'P', 'R', 'O', 'D', 'U', 'C', 'T', + 'P', 'U', 'S', 'H', 'I', 'N', 'G', + 'Q', 'U', 'A', 'R', 'T', 'E', 'R', + 'R', 'A', 'D', 'I', 'C', 'A', 'L', + 'R', 'A', 'K', 'H', 'A', 'N', 'G', + 'R', 'A', 'P', 'I', 'S', 'M', 'A', + 'R', 'A', 'Y', 'A', 'N', 'N', 'A', + 'R', 'E', 'A', 'H', 'M', 'U', 'K', + 'R', 'E', 'L', 'E', 'A', 'S', 'E', + 'R', 'E', 'R', 'E', 'K', 'A', 'N', + 'R', 'E', 'T', 'R', 'E', 'A', 'T', + 'R', 'E', 'V', 'E', 'R', 'S', 'E', + 'R', 'G', 'Y', 'I', 'N', 'G', 'S', + 'R', 'I', 'T', 'T', 'O', 'R', 'U', + 'R', 'O', 'S', 'E', 'T', 'T', 'E', + 'R', 'O', 'T', 'A', 'T', 'E', 'D', + 'R', 'O', 'T', 'U', 'N', 'D', 'A', + 'R', 'O', 'U', 'N', 'D', 'E', 'D', + 'R', 'U', 'U', 'B', 'U', 'R', 'U', + 'S', 'A', 'I', 'K', 'U', 'R', 'U', + 'S', 'A', 'L', 'T', 'I', 'R', 'E', + 'S', 'A', 'M', 'P', 'H', 'A', 'O', + 'S', 'A', 'N', 'Y', 'A', 'K', 'A', + 'S', 'A', 'Y', 'A', 'N', 'N', 'A', + 'S', 'C', 'H', 'O', 'L', 'A', 'R', + 'S', 'C', 'R', 'U', 'P', 'L', 'E', + 'S', 'E', 'A', 'G', 'U', 'L', 'L', + 'S', 'E', 'C', 'T', 'I', 'O', 'N', + 'S', 'E', 'G', 'M', 'E', 'N', 'T', + 'S', 'E', 'M', 'K', 'A', 'T', 'H', + 'S', 'E', 'R', 'V', 'I', 'C', 'E', + 'S', 'E', 'V', 'E', 'N', 'T', 'Y', + 'S', 'E', 'X', 'T', 'A', 'N', 'S', + 'S', 'E', 'X', 'T', 'I', 'L', 'E', + 'S', 'E', 'X', 'T', 'U', 'L', 'A', + 'S', 'H', 'A', 'P', 'I', 'N', 'G', + 'S', 'H', 'A', 'V', 'I', 'A', 'N', + 'S', 'H', 'E', 'S', 'H', 'I', 'G', + 'S', 'H', 'T', 'A', 'P', 'I', 'C', + 'S', 'H', 'U', 'F', 'F', 'L', 'E', + 'S', 'I', 'L', 'I', 'Q', 'U', 'A', + 'S', 'I', 'M', 'I', 'L', 'A', 'R', + 'S', 'I', 'N', 'H', 'A', 'L', 'A', + 'S', 'I', 'N', 'K', 'I', 'N', 'G', + 'S', 'I', 'R', 'I', 'N', 'G', 'U', + 'S', 'I', 'X', 'T', 'E', 'E', 'N', + 'S', 'K', 'L', 'I', 'R', 'O', 'N', + 'S', 'L', 'A', 'N', 'T', 'E', 'D', + 'S', 'L', 'O', 'P', 'I', 'N', 'G', + 'S', 'M', 'A', 'L', 'L', 'E', 'R', + 'S', 'M', 'I', 'L', 'I', 'N', 'G', + 'S', 'N', 'O', 'W', 'M', 'A', 'N', + 'S', 'O', 'C', 'I', 'E', 'T', 'Y', + 'S', 'O', 'G', 'D', 'I', 'A', 'N', + 'S', 'O', 'L', 'I', 'D', 'U', 'S', + 'S', 'P', 'A', 'C', 'I', 'N', 'G', + 'S', 'P', 'A', 'R', 'K', 'L', 'E', + 'S', 'P', 'E', 'C', 'I', 'A', 'L', + 'S', 'P', 'I', 'D', 'E', 'R', 'Y', + 'S', 'P', 'I', 'R', 'A', 'N', 'T', + 'S', 'P', 'R', 'I', 'N', 'G', 'S', + 'S', 'Q', 'U', 'A', 'R', 'E', 'D', + 'S', 'Q', 'U', 'A', 'R', 'E', 'S', + 'S', 'T', 'A', 'T', 'E', 'R', 'S', + 'S', 'T', 'A', 'U', 'R', 'O', 'S', + 'S', 'T', 'A', 'V', 'R', 'O', 'S', + 'S', 'T', 'A', 'V', 'R', 'O', 'U', + 'S', 'T', 'R', 'O', 'K', 'E', 'S', + 'S', 'U', 'B', 'J', 'E', 'C', 'T', + 'S', 'U', 'B', 'U', 'N', 'I', 'T', + 'S', 'U', 'C', 'C', 'E', 'E', 'D', + 'S', 'U', 'R', 'F', 'A', 'C', 'E', + 'S', 'Y', 'N', 'A', 'G', 'M', 'A', + 'S', 'Y', 'N', 'E', 'V', 'M', 'A', + 'T', 'A', 'A', 'L', 'U', 'J', 'A', + 'T', 'A', 'G', 'A', 'L', 'O', 'G', + 'T', 'A', 'I', 'S', 'Y', 'O', 'U', + 'T', 'A', 'L', 'E', 'N', 'T', 'S', + 'T', 'A', 'T', 'W', 'E', 'E', 'L', + 'T', 'A', 'Y', 'A', 'N', 'N', 'A', + 'T', 'C', 'H', 'E', 'H', 'E', 'H', + 'T', 'E', 'L', 'I', 'S', 'H', 'A', + 'T', 'E', 'S', 'S', 'E', 'R', 'A', + 'T', 'H', '-', 'C', 'R', 'E', 'E', + 'T', 'H', 'E', 'S', 'E', 'O', 'S', + 'T', 'H', 'I', 'E', 'U', 'T', 'H', + 'T', 'H', 'R', 'E', 'E', '-', 'D', + 'T', 'H', 'R', 'O', 'U', 'G', 'H', + 'T', 'H', 'U', 'N', 'D', 'E', 'R', + 'T', 'I', 'B', 'E', 'T', 'A', 'N', + 'T', 'I', 'N', 'A', 'G', 'M', 'A', + 'T', 'R', 'I', 'G', 'R', 'A', 'M', + 'T', 'R', 'I', 'I', 'S', 'A', 'P', + 'T', 'R', 'I', 'S', 'E', 'M', 'E', + 'T', 'T', 'U', 'D', 'D', 'A', 'G', + 'U', '-', 'E', 'O', '-', 'E', 'U', + 'U', 'B', 'A', 'D', 'A', 'M', 'A', + 'U', 'B', 'U', 'F', 'I', 'L', 'I', + 'U', 'P', 'R', 'I', 'G', 'H', 'T', + 'U', 'P', 'S', 'I', 'L', 'O', 'N', + 'U', 'P', 'W', 'A', 'R', 'D', 'S', + 'U', 'U', 'Y', 'A', 'N', 'N', 'A', + 'V', 'A', 'R', 'E', 'I', 'A', 'I', + 'V', 'A', 'R', 'I', 'A', 'N', 'T', + 'V', 'A', 'Y', 'A', 'N', 'N', 'A', + 'V', 'I', 'C', 'T', 'O', 'R', 'Y', + 'V', 'I', 'L', 'L', 'A', 'G', 'E', + 'V', 'I', 'S', 'A', 'R', 'G', 'A', + 'V', 'O', 'C', 'A', 'L', 'I', 'C', + 'V', 'O', 'I', 'C', 'I', 'N', 'G', + 'V', 'O', 'L', 'T', 'A', 'G', 'E', + 'W', 'A', 'I', 'T', 'I', 'N', 'G', + 'W', 'A', 'R', 'N', 'I', 'N', 'G', + 'W', 'A', 'S', 'T', 'I', 'N', 'G', + 'W', 'E', 'S', 'T', 'E', 'R', 'N', + 'W', 'H', 'E', 'E', 'L', 'E', 'D', + 'W', 'R', 'I', 'T', 'I', 'N', 'G', + 'Y', 'A', 'Y', 'A', 'N', 'N', 'A', + 'Y', 'I', 'D', 'D', 'I', 'S', 'H', + 'Y', 'P', 'O', 'R', 'R', 'O', 'I', + 'Z', 'H', 'I', 'V', 'E', 'T', 'E', + 'A', 'C', 'T', 'I', 'V', 'A', 'T', 'E', + 'A', 'C', 'T', 'U', 'A', 'L', 'L', 'Y', + 'A', 'E', 'E', 'Y', 'A', 'N', 'N', 'A', + 'A', 'I', 'R', 'P', 'L', 'A', 'N', 'E', + 'A', 'K', 'H', 'M', 'I', 'M', 'I', 'C', + 'A', 'L', 'L', 'I', 'A', 'N', 'C', 'E', + 'A', 'L', 'V', 'E', 'O', 'L', 'A', 'R', + 'A', 'N', 'G', 'S', 'T', 'R', 'O', 'M', + 'A', 'N', 'U', 'D', 'A', 'T', 'T', 'A', + 'A', 'N', 'U', 'S', 'V', 'A', 'R', 'A', + 'A', 'P', 'O', 'D', 'E', 'R', 'M', 'A', + 'A', 'P', 'O', 'D', 'E', 'X', 'I', 'A', + 'A', 'P', 'O', 'T', 'H', 'E', 'M', 'A', + 'A', 'P', 'P', 'R', 'O', 'A', 'C', 'H', + 'A', 'Q', 'U', 'A', 'R', 'I', 'U', 'S', + 'A', 'R', 'A', 'E', 'A', '-', 'E', 'O', + 'A', 'R', 'C', 'H', 'A', 'I', 'O', 'N', + 'A', 'R', 'G', 'O', 'T', 'E', 'R', 'I', + 'A', 'R', 'I', 'S', 'T', 'E', 'R', 'A', + 'A', 'R', 'M', 'E', 'N', 'I', 'A', 'N', + 'A', 'R', 'O', 'U', 'S', 'I', 'N', 'G', + 'A', 'S', 'S', 'A', 'L', 'L', 'A', 'M', + 'A', 'S', 'S', 'Y', 'R', 'I', 'A', 'N', + 'A', 'S', 'T', 'E', 'R', 'I', 'S', 'K', + 'A', 'S', 'T', 'E', 'R', 'I', 'S', 'M', + 'A', 'T', 'T', 'H', 'A', 'C', 'A', 'N', + 'A', 'V', 'A', 'G', 'R', 'A', 'H', 'A', + 'B', 'A', 'L', 'I', 'N', 'E', 'S', 'E', + 'B', 'E', 'L', 'G', 'T', 'H', 'O', 'R', + 'B', 'E', 'R', 'K', 'A', 'N', 'A', 'N', + 'B', 'E', 'V', 'E', 'R', 'A', 'G', 'E', + 'B', 'I', 'D', 'E', 'N', 'T', 'A', 'L', + 'B', 'I', 'L', 'A', 'B', 'I', 'A', 'L', + 'B', 'O', 'P', 'O', 'M', 'O', 'F', 'O', + 'B', 'O', 'U', 'N', 'D', 'A', 'R', 'Y', + 'B', 'U', 'G', 'I', 'N', 'E', 'S', 'E', + 'B', 'U', 'L', 'L', 'S', 'E', 'Y', 'E', + 'B', 'U', 'S', 'S', 'Y', 'E', 'R', 'U', + 'C', 'A', 'D', 'U', 'C', 'E', 'U', 'S', + 'C', 'A', 'N', 'A', 'D', 'I', 'A', 'N', + 'C', 'A', 'R', 'R', 'I', 'A', 'G', 'E', + 'C', 'A', 'U', 'L', 'D', 'R', 'O', 'N', + 'C', 'H', 'A', 'M', 'I', 'L', 'O', 'N', + 'C', 'H', 'A', 'T', 'T', 'A', 'W', 'A', + 'C', 'H', 'E', 'R', 'O', 'K', 'E', 'E', + 'C', 'H', 'O', 'R', 'E', 'V', 'M', 'A', + 'C', 'H', 'O', 'S', 'E', 'O', 'N', 'G', + 'C', 'I', 'R', 'C', 'U', 'L', 'A', 'R', + 'C', 'I', 'V', 'I', 'L', 'I', 'A', 'N', + 'C', 'L', 'I', 'M', 'A', 'C', 'U', 'S', + 'C', 'L', 'I', 'N', 'G', 'I', 'N', 'G', + 'C', 'O', 'N', 'F', 'L', 'I', 'C', 'T', + 'C', 'O', 'N', 'S', 'T', 'A', 'N', 'T', + 'C', 'O', 'N', 'T', 'A', 'I', 'N', 'S', + 'C', 'O', 'U', 'N', 'T', 'I', 'N', 'G', + 'C', 'R', 'E', 'A', 'T', 'I', 'V', 'E', + 'C', 'R', 'E', 'S', 'C', 'E', 'N', 'T', + 'C', 'R', 'O', 'S', 'S', 'I', 'N', 'G', + 'C', 'R', 'U', 'Z', 'E', 'I', 'R', 'O', + 'C', 'U', 'R', 'R', 'E', 'N', 'C', 'Y', + 'C', 'U', 'S', 'T', 'O', 'M', 'E', 'R', + 'C', 'Y', 'R', 'E', 'N', 'A', 'I', 'C', + 'C', 'Y', 'R', 'I', 'L', 'L', 'I', 'C', + 'D', 'A', 'M', 'M', 'A', 'T', 'A', 'N', + 'D', 'A', 'P', '-', 'B', 'U', 'O', 'N', + 'D', 'A', 'P', '-', 'M', 'U', 'O', 'Y', + 'D', 'A', 'P', '-', 'P', 'R', 'A', 'M', + 'D', 'A', 'V', 'I', 'Y', 'A', 'N', 'I', + 'D', 'D', 'A', 'Y', 'A', 'N', 'N', 'A', + 'D', 'E', 'C', 'E', 'M', 'B', 'E', 'R', + 'D', 'E', 'C', 'R', 'E', 'A', 'S', 'E', + 'D', 'E', 'N', 'A', 'R', 'I', 'U', 'S', + 'D', 'E', 'Y', 'T', 'E', 'R', 'O', 'S', + 'D', 'E', 'Y', 'T', 'E', 'R', 'O', 'U', + 'D', 'I', 'A', 'G', 'O', 'N', 'A', 'L', + 'D', 'I', 'A', 'M', 'E', 'T', 'E', 'R', + 'D', 'I', 'A', 'S', 'T', 'O', 'L', 'I', + 'D', 'I', 'A', 'T', 'O', 'N', 'O', 'N', + 'D', 'I', 'F', 'O', 'N', 'I', 'A', 'S', + 'D', 'I', 'G', 'O', 'R', 'G', 'O', 'N', + 'D', 'I', 'G', 'R', 'A', 'M', 'M', 'A', + 'D', 'I', 'R', 'E', 'C', 'T', 'L', 'Y', + 'D', 'I', 'V', 'I', 'S', 'I', 'O', 'N', + 'D', 'O', 'D', 'E', 'K', 'A', 'T', 'A', + 'D', 'O', 'T', 'S', '-', '1', '2', '3', + 'D', 'O', 'T', 'S', '-', '1', '2', '4', + 'D', 'O', 'T', 'S', '-', '1', '2', '5', + 'D', 'O', 'T', 'S', '-', '1', '2', '6', + 'D', 'O', 'T', 'S', '-', '1', '2', '7', + 'D', 'O', 'T', 'S', '-', '1', '2', '8', + 'D', 'O', 'T', 'S', '-', '1', '3', '4', + 'D', 'O', 'T', 'S', '-', '1', '3', '5', + 'D', 'O', 'T', 'S', '-', '1', '3', '6', + 'D', 'O', 'T', 'S', '-', '1', '3', '7', + 'D', 'O', 'T', 'S', '-', '1', '3', '8', + 'D', 'O', 'T', 'S', '-', '1', '4', '5', + 'D', 'O', 'T', 'S', '-', '1', '4', '6', + 'D', 'O', 'T', 'S', '-', '1', '4', '7', + 'D', 'O', 'T', 'S', '-', '1', '4', '8', + 'D', 'O', 'T', 'S', '-', '1', '5', '6', + 'D', 'O', 'T', 'S', '-', '1', '5', '7', + 'D', 'O', 'T', 'S', '-', '1', '5', '8', + 'D', 'O', 'T', 'S', '-', '1', '6', '7', + 'D', 'O', 'T', 'S', '-', '1', '6', '8', + 'D', 'O', 'T', 'S', '-', '1', '7', '8', + 'D', 'O', 'T', 'S', '-', '2', '3', '4', + 'D', 'O', 'T', 'S', '-', '2', '3', '5', + 'D', 'O', 'T', 'S', '-', '2', '3', '6', + 'D', 'O', 'T', 'S', '-', '2', '3', '7', + 'D', 'O', 'T', 'S', '-', '2', '3', '8', + 'D', 'O', 'T', 'S', '-', '2', '4', '5', + 'D', 'O', 'T', 'S', '-', '2', '4', '6', + 'D', 'O', 'T', 'S', '-', '2', '4', '7', + 'D', 'O', 'T', 'S', '-', '2', '4', '8', + 'D', 'O', 'T', 'S', '-', '2', '5', '6', + 'D', 'O', 'T', 'S', '-', '2', '5', '7', + 'D', 'O', 'T', 'S', '-', '2', '5', '8', + 'D', 'O', 'T', 'S', '-', '2', '6', '7', + 'D', 'O', 'T', 'S', '-', '2', '6', '8', + 'D', 'O', 'T', 'S', '-', '2', '7', '8', + 'D', 'O', 'T', 'S', '-', '3', '4', '5', + 'D', 'O', 'T', 'S', '-', '3', '4', '6', + 'D', 'O', 'T', 'S', '-', '3', '4', '7', + 'D', 'O', 'T', 'S', '-', '3', '4', '8', + 'D', 'O', 'T', 'S', '-', '3', '5', '6', + 'D', 'O', 'T', 'S', '-', '3', '5', '7', + 'D', 'O', 'T', 'S', '-', '3', '5', '8', + 'D', 'O', 'T', 'S', '-', '3', '6', '7', + 'D', 'O', 'T', 'S', '-', '3', '6', '8', + 'D', 'O', 'T', 'S', '-', '3', '7', '8', + 'D', 'O', 'T', 'S', '-', '4', '5', '6', + 'D', 'O', 'T', 'S', '-', '4', '5', '7', + 'D', 'O', 'T', 'S', '-', '4', '5', '8', + 'D', 'O', 'T', 'S', '-', '4', '6', '7', + 'D', 'O', 'T', 'S', '-', '4', '6', '8', + 'D', 'O', 'T', 'S', '-', '4', '7', '8', + 'D', 'O', 'T', 'S', '-', '5', '6', '7', + 'D', 'O', 'T', 'S', '-', '5', '6', '8', + 'D', 'O', 'T', 'S', '-', '5', '7', '8', + 'D', 'O', 'T', 'S', '-', '6', '7', '8', + 'D', 'O', 'T', 'T', 'E', 'D', '-', 'L', + 'D', 'O', 'T', 'T', 'E', 'D', '-', 'N', + 'D', 'O', 'T', 'T', 'E', 'D', '-', 'P', + 'D', 'R', 'A', 'C', 'H', 'M', 'A', 'S', + 'D', 'R', 'A', 'F', 'T', 'I', 'N', 'G', + 'D', 'R', 'A', 'U', 'G', 'H', 'T', 'S', + 'D', 'R', 'A', 'W', 'I', 'N', 'G', 'S', + 'D', 'U', 'R', 'A', 'T', 'I', 'O', 'N', + 'D', 'V', 'I', 'S', 'V', 'A', 'R', 'A', + 'E', 'I', 'G', 'H', 'T', 'E', 'E', 'N', + 'E', 'L', 'E', 'C', 'T', 'R', 'I', 'C', + 'E', 'L', 'L', 'I', 'P', 'S', 'I', 'S', + 'E', 'M', 'P', 'H', 'A', 'S', 'I', 'S', + 'E', 'M', 'P', 'H', 'A', 'T', 'I', 'C', + 'E', 'N', 'T', 'E', 'R', 'I', 'N', 'G', + 'E', 'N', 'V', 'E', 'L', 'O', 'P', 'E', + 'E', 'P', 'E', 'G', 'E', 'R', 'M', 'A', + 'E', 'S', 'U', 'K', 'U', 'U', 'D', 'O', + 'E', 'T', 'E', 'R', 'N', 'I', 'T', 'Y', + 'E', 'T', 'H', 'I', 'O', 'P', 'I', 'C', + 'E', 'X', 'T', 'E', 'N', 'D', 'E', 'D', + 'F', 'A', 'T', 'H', 'A', 'T', 'A', 'N', + 'F', 'E', 'B', 'R', 'U', 'A', 'R', 'Y', + 'F', 'E', 'M', 'I', 'N', 'I', 'N', 'E', + 'F', 'E', 'S', 'T', 'I', 'V', 'A', 'L', + 'F', 'I', 'G', 'U', 'R', 'E', '-', '1', + 'F', 'I', 'G', 'U', 'R', 'E', '-', '2', + 'F', 'I', 'G', 'U', 'R', 'E', '-', '3', + 'F', 'I', 'N', 'G', 'E', 'R', 'E', 'D', + 'F', 'I', 'S', 'H', 'H', 'O', 'O', 'K', + 'F', 'L', 'A', 'T', 'N', 'E', 'S', 'S', + 'F', 'L', 'O', 'R', 'E', 'T', 'T', 'E', + 'F', 'L', 'O', 'U', 'R', 'I', 'S', 'H', + 'F', 'O', 'O', 'T', 'N', 'O', 'T', 'E', + 'F', 'O', 'U', 'R', 'T', 'E', 'E', 'N', + 'F', 'R', 'A', 'C', 'T', 'I', 'O', 'N', + 'F', 'R', 'A', 'G', 'M', 'E', 'N', 'T', + 'F', 'R', 'A', 'G', 'R', 'A', 'N', 'T', + 'F', 'R', 'O', 'W', 'N', 'I', 'N', 'G', + 'F', 'U', 'L', 'L', 'N', 'E', 'S', 'S', + 'F', 'U', 'N', 'C', 'T', 'I', 'O', 'N', + 'G', 'A', 'R', 'S', 'H', 'U', 'N', 'I', + 'G', 'A', 'U', 'N', 'T', 'L', 'E', 'T', + 'G', 'E', 'N', 'I', 'T', 'I', 'V', 'E', + 'G', 'E', 'O', 'R', 'G', 'I', 'A', 'N', + 'G', 'R', 'A', 'P', 'H', 'E', 'M', 'E', + 'G', 'U', 'J', 'A', 'R', 'A', 'T', 'I', + 'G', 'U', 'R', 'M', 'U', 'K', 'H', 'I', + 'H', 'A', 'N', '-', 'A', 'K', 'A', 'T', + 'H', 'A', 'N', 'G', 'Z', 'H', 'O', 'U', + 'H', 'A', 'R', 'D', 'N', 'E', 'S', 'S', + 'H', 'A', 'R', 'K', 'L', 'E', 'A', 'N', + 'H', 'A', 'R', 'M', 'O', 'N', 'I', 'C', + 'H', 'E', 'A', 'V', 'E', 'N', 'L', 'Y', + 'H', 'E', 'X', 'A', 'G', 'R', 'A', 'M', + 'H', 'I', 'R', 'A', 'G', 'A', 'N', 'A', + 'H', 'U', 'A', 'R', 'A', 'D', 'D', 'O', + 'I', 'D', 'E', 'O', 'G', 'R', 'A', 'M', + 'I', 'L', 'U', 'Y', 'A', 'N', 'N', 'A', + 'I', 'M', 'I', 'F', 'O', 'N', 'O', 'N', + 'I', 'N', 'C', 'R', 'E', 'A', 'S', 'E', + 'I', 'N', 'D', 'I', 'R', 'E', 'C', 'T', + 'I', 'N', 'F', 'I', 'N', 'I', 'T', 'Y', + 'I', 'N', 'H', 'E', 'R', 'E', 'N', 'T', + 'I', 'N', 'T', 'E', 'G', 'R', 'A', 'L', + 'I', 'N', 'T', 'E', 'R', 'E', 'S', 'T', + 'I', 'N', 'T', 'E', 'R', 'I', 'O', 'R', + 'I', 'N', 'V', 'E', 'R', 'T', 'E', 'D', + 'I', 'O', 'T', 'I', 'F', 'I', 'E', 'D', + 'I', 'R', 'U', 'Y', 'A', 'N', 'N', 'A', + 'I', 'S', '-', 'P', 'I', 'L', 'L', 'A', + 'I', 'S', 'O', 'L', 'A', 'T', 'E', 'D', + 'J', 'A', 'P', 'A', 'N', 'E', 'S', 'E', + 'J', 'A', 'V', 'I', 'Y', 'A', 'N', 'I', + 'K', 'A', 'S', 'R', 'A', 'T', 'A', 'N', + 'K', 'A', 'T', 'A', 'K', 'A', 'N', 'A', + 'K', 'A', 'T', 'H', 'I', 'S', 'T', 'I', + 'K', 'E', 'Y', 'B', 'O', 'A', 'R', 'D', + 'K', 'O', 'N', 'T', 'E', 'V', 'M', 'A', + 'K', 'O', 'U', 'F', 'I', 'S', 'M', 'A', + 'K', 'R', 'E', 'M', 'A', 'S', 'T', 'I', + 'L', '-', 'S', 'H', 'A', 'P', 'E', 'D', + 'L', 'A', 'N', 'G', 'U', 'A', 'G', 'E', + 'L', 'A', 'T', 'I', 'N', 'A', 'T', 'E', + 'L', 'I', 'G', 'A', 'T', 'U', 'R', 'E', + 'L', 'O', 'C', 'A', 'T', 'I', 'O', 'N', + 'L', 'O', 'C', 'A', 'T', 'I', 'V', 'E', + 'L', 'O', 'G', 'O', 'T', 'Y', 'P', 'E', + 'L', 'O', 'R', 'R', 'A', 'I', 'N', 'E', + 'M', 'A', 'H', 'A', 'P', 'A', 'K', 'H', + 'M', 'A', 'I', 'M', 'A', 'L', 'A', 'I', + 'M', 'A', 'I', 'Y', 'A', 'M', 'O', 'K', + 'M', 'A', 'N', 'A', 'C', 'L', 'E', 'S', + 'M', 'A', 'N', 'G', 'A', 'L', 'A', 'M', + 'M', 'A', 'R', 'R', 'I', 'A', 'G', 'E', + 'M', 'A', 'R', 'R', 'Y', 'I', 'N', 'G', + 'M', 'A', 'R', 'T', 'Y', 'R', 'I', 'A', + 'M', 'E', 'A', 'S', 'U', 'R', 'E', 'D', + 'M', 'E', 'D', 'I', 'C', 'I', 'N', 'E', + 'M', 'E', 'T', 'R', 'E', 'T', 'E', 'S', + 'M', 'E', 'T', 'R', 'I', 'C', 'A', 'L', + 'M', 'I', 'L', 'L', 'I', 'O', 'N', 'S', + 'M', 'I', 'N', 'I', 'S', 'T', 'E', 'R', + 'M', 'O', 'D', 'I', 'F', 'I', 'E', 'R', + 'M', 'O', 'H', 'A', 'M', 'M', 'A', 'D', + 'M', 'O', 'N', 'O', 'G', 'R', 'A', 'M', + 'M', 'O', 'U', 'N', 'T', 'A', 'I', 'N', + 'M', 'U', 'L', 'T', 'I', 'M', 'A', 'P', + 'M', 'U', 'L', 'T', 'I', 'P', 'L', 'E', + 'M', 'U', 'L', 'T', 'I', 'S', 'E', 'T', + 'N', 'A', 'T', 'I', 'O', 'N', 'A', 'L', + 'N', 'E', 'G', 'A', 'T', 'I', 'O', 'N', + 'N', 'E', 'G', 'A', 'T', 'I', 'V', 'E', + 'N', 'I', 'K', 'H', 'A', 'H', 'I', 'T', + 'N', 'I', 'N', 'E', 'T', 'E', 'E', 'N', + 'N', 'O', '-', 'B', 'R', 'E', 'A', 'K', + 'N', 'O', 'T', 'A', 'T', 'I', 'O', 'N', + 'N', 'O', 'T', 'E', 'H', 'E', 'A', 'D', + 'N', 'O', 'V', 'E', 'M', 'B', 'E', 'R', + 'O', 'M', 'I', 'S', 'S', 'I', 'O', 'N', + 'O', 'N', 'E', '-', 'L', 'I', 'N', 'E', + 'O', 'P', 'E', 'R', 'A', 'T', 'O', 'R', + 'O', 'P', 'P', 'O', 'S', 'I', 'N', 'G', + 'O', 'R', 'I', 'G', 'I', 'N', 'A', 'L', + 'O', 'R', 'N', 'A', 'M', 'E', 'N', 'T', + 'O', 'R', 'T', 'H', 'O', 'D', 'O', 'X', + 'O', 'U', 'T', 'L', 'I', 'N', 'E', 'D', + 'O', 'V', 'E', 'R', 'L', 'A', 'I', 'D', + 'O', 'V', 'E', 'R', 'L', 'I', 'N', 'E', + 'O', 'V', 'E', 'R', 'R', 'I', 'D', 'E', + 'P', 'A', 'A', 'S', 'E', 'N', 'T', 'O', + 'P', 'A', 'I', 'R', 'T', 'H', 'R', 'A', + 'P', 'A', 'L', 'O', 'C', 'H', 'K', 'A', + 'P', 'A', 'M', 'E', 'N', 'E', 'N', 'G', + 'P', 'A', 'M', 'U', 'D', 'P', 'O', 'D', + 'P', 'A', 'N', 'G', 'H', 'U', 'L', 'U', + 'P', 'A', 'N', 'O', 'L', 'O', 'N', 'G', + 'P', 'A', 'N', 'Y', 'A', 'K', 'R', 'A', + 'P', 'A', 'N', 'Y', 'E', 'C', 'E', 'K', + 'P', 'A', 'R', 'A', 'L', 'L', 'E', 'L', + 'P', 'A', 'R', 'I', 'C', 'H', 'O', 'N', + 'P', 'A', 'V', 'I', 'Y', 'A', 'N', 'I', + 'P', 'E', 'D', 'E', 'S', 'T', 'A', 'L', + 'P', 'E', 'L', 'A', 'S', 'T', 'O', 'N', + 'P', 'E', 'N', 'T', 'A', 'G', 'O', 'N', + 'P', 'E', 'R', 'F', 'E', 'C', 'T', 'A', + 'P', 'E', 'T', 'A', 'L', 'L', 'E', 'D', + 'P', 'H', 'A', 'A', 'R', 'K', 'A', 'A', + 'P', 'H', 'A', 'G', 'S', '-', 'P', 'A', + 'P', 'H', 'A', 'I', 'S', 'T', 'O', 'S', + 'P', 'I', 'N', 'W', 'H', 'E', 'E', 'L', + 'P', 'L', 'A', 'S', 'T', 'I', 'C', 'S', + 'P', 'L', 'E', 'T', 'H', 'R', 'O', 'N', + 'P', 'N', 'E', 'U', 'M', 'A', 'T', 'A', + 'P', 'O', 'I', 'N', 'T', 'I', 'N', 'G', + 'P', 'O', 'K', 'R', 'Y', 'T', 'I', 'E', + 'P', 'O', 'S', 'I', 'T', 'I', 'O', 'N', + 'P', 'R', 'A', 'M', '-', 'B', 'E', 'I', + 'P', 'R', 'A', 'M', '-', 'P', 'I', 'I', + 'P', 'R', 'E', 'C', 'E', 'D', 'E', 'D', + 'P', 'R', 'E', 'C', 'E', 'D', 'E', 'S', + 'P', 'R', 'E', 'V', 'I', 'O', 'U', 'S', + 'P', 'R', 'O', 'F', 'O', 'U', 'N', 'D', + 'P', 'R', 'O', 'G', 'R', 'E', 'S', 'S', + 'P', 'R', 'O', 'P', 'E', 'R', 'T', 'Y', + 'Q', 'A', 'I', 'R', 'T', 'H', 'R', 'A', + 'Q', 'U', 'A', 'D', 'R', 'A', 'N', 'T', + 'Q', 'U', 'A', 'R', 'T', 'E', 'R', 'S', + 'Q', 'U', 'E', 'S', 'T', 'I', 'O', 'N', + 'Q', 'U', 'I', 'N', 'C', 'U', 'N', 'X', + 'R', 'E', 'C', 'O', 'R', 'D', 'E', 'R', + 'R', 'E', 'C', 'Y', 'C', 'L', 'E', 'D', + 'R', 'E', 'L', 'A', 'T', 'I', 'O', 'N', + 'R', 'E', 'L', 'I', 'G', 'I', 'O', 'N', + 'R', 'E', 'N', 'T', 'O', 'G', 'E', 'N', + 'R', 'E', 'P', 'E', 'A', 'T', 'E', 'D', + 'R', 'E', 'S', 'O', 'U', 'R', 'C', 'E', + 'R', 'E', 'S', 'P', 'O', 'N', 'S', 'E', + 'R', 'E', 'V', 'E', 'R', 'S', 'E', 'D', + 'R', 'U', 'K', 'K', 'A', 'K', 'H', 'A', + 'S', '-', 'S', 'H', 'A', 'P', 'E', 'D', + 'S', 'A', 'L', 'T', 'I', 'L', 'L', 'O', + 'S', 'A', 'N', 'T', 'I', 'I', 'M', 'U', + 'S', 'A', 'N', 'Y', 'O', 'O', 'G', 'A', + 'S', 'A', 'X', 'I', 'M', 'A', 'T', 'A', + 'S', 'C', 'I', 'S', 'S', 'O', 'R', 'S', + 'S', 'C', 'O', 'R', 'P', 'I', 'U', 'S', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', + 'S', 'E', 'M', 'I', 'S', 'O', 'F', 'T', + 'S', 'E', 'M', 'U', 'N', 'C', 'I', 'A', + 'S', 'H', 'A', 'D', 'O', 'W', 'E', 'D', + 'S', 'H', 'A', 'M', 'R', 'O', 'C', 'K', + 'S', 'H', 'E', '-', 'G', 'O', 'A', 'T', + 'S', 'H', 'E', 'S', 'H', 'L', 'A', 'M', + 'S', 'I', 'C', 'K', 'N', 'E', 'S', 'S', + 'S', 'I', 'D', 'E', 'W', 'A', 'Y', 'S', + 'S', 'I', 'M', 'A', 'N', 'S', 'I', 'S', + 'S', 'I', 'X', '-', 'L', 'I', 'N', 'E', + 'S', 'L', 'A', 'V', 'O', 'N', 'I', 'C', + 'S', 'Q', 'U', 'I', 'G', 'G', 'L', 'E', + 'S', 'Q', 'U', 'I', 'R', 'R', 'E', 'L', + 'S', 'T', 'A', 'C', 'C', 'A', 'T', 'O', + 'S', 'T', 'A', 'L', 'L', 'I', 'O', 'N', + 'S', 'T', 'A', 'N', 'D', 'A', 'R', 'D', + 'S', 'T', 'O', 'P', 'P', 'A', 'G', 'E', + 'S', 'T', 'O', 'P', 'P', 'I', 'N', 'G', + 'S', 'T', 'R', 'A', 'I', 'G', 'H', 'T', + 'S', 'T', 'R', 'A', 'I', 'N', 'E', 'R', + 'S', 'T', 'R', 'A', 'T', 'I', 'A', 'N', + 'S', 'T', 'R', 'E', 'N', 'G', 'T', 'H', + 'S', 'T', 'R', 'I', 'C', 'T', 'L', 'Y', + 'S', 'T', 'R', 'O', 'K', 'E', '-', '1', + 'S', 'T', 'R', 'O', 'K', 'E', '-', '2', + 'S', 'T', 'R', 'O', 'K', 'E', '-', '3', + 'S', 'T', 'R', 'O', 'K', 'E', '-', '4', + 'S', 'T', 'R', 'O', 'K', 'E', '-', '5', + 'S', 'T', 'R', 'O', 'K', 'E', '-', '6', + 'S', 'T', 'R', 'O', 'K', 'E', '-', '7', + 'S', 'T', 'R', 'O', 'K', 'E', '-', '8', + 'S', 'T', 'R', 'O', 'K', 'E', '-', '9', + 'S', 'U', 'B', 'G', 'R', 'O', 'U', 'P', + 'S', 'U', 'C', 'C', 'E', 'E', 'D', 'S', + 'S', 'U', 'I', 'T', 'A', 'B', 'L', 'E', + 'S', 'U', 'P', 'E', 'R', 'S', 'E', 'T', + 'S', 'U', 'R', 'R', 'O', 'U', 'N', 'D', + 'S', 'W', 'A', 'P', 'P', 'I', 'N', 'G', + 'S', 'Y', 'L', 'L', 'A', 'B', 'L', 'E', + 'S', 'Y', 'M', 'B', 'O', 'L', '-', '1', + 'S', 'Y', 'M', 'B', 'O', 'L', '-', '2', + 'S', 'Y', 'M', 'B', 'O', 'L', '-', '3', + 'S', 'Y', 'M', 'B', 'O', 'L', '-', '4', + 'S', 'Y', 'M', 'B', 'O', 'L', '-', '5', + 'S', 'Y', 'M', 'B', 'O', 'L', '-', '6', + 'S', 'Y', 'M', 'B', 'O', 'L', '-', '7', + 'S', 'Y', 'M', 'B', 'O', 'L', '-', '8', + 'S', 'Y', 'M', 'B', 'O', 'L', '-', '9', + 'S', 'Y', 'M', 'M', 'E', 'T', 'R', 'Y', + 'T', 'A', 'G', 'B', 'A', 'N', 'W', 'A', + 'T', 'A', 'I', 'L', 'L', 'E', 'S', 'S', + 'T', 'A', 'T', 'T', 'O', 'O', 'E', 'D', + 'T', 'A', 'V', 'I', 'Y', 'A', 'N', 'I', + 'T', 'E', 'S', 'S', 'A', 'R', 'O', 'N', + 'T', 'E', 'T', 'A', 'R', 'T', 'O', 'S', + 'T', 'E', 'T', 'R', 'A', 'P', 'L', 'I', + 'T', 'H', 'E', 'S', 'P', 'I', 'A', 'N', + 'T', 'H', 'I', 'R', 'T', 'E', 'E', 'N', + 'T', 'H', 'O', 'U', 'S', 'A', 'N', 'D', + 'T', 'H', 'U', 'R', 'I', 'S', 'A', 'Z', + 'T', 'I', 'F', 'I', 'N', 'A', 'G', 'H', + 'T', 'I', 'R', 'O', 'N', 'I', 'A', 'N', + 'T', 'O', 'G', 'E', 'T', 'H', 'E', 'R', + 'T', 'O', 'R', 'C', 'U', 'L', 'U', 'S', + 'T', 'O', 'R', 'T', 'O', 'I', 'S', 'E', + 'T', 'R', 'E', 'A', 'D', 'I', 'N', 'G', + 'T', 'R', 'E', 'S', 'I', 'L', 'L', 'O', + 'T', 'R', 'I', 'A', 'N', 'G', 'L', 'E', + 'T', 'R', 'I', 'C', 'O', 'L', 'O', 'N', + 'T', 'R', 'I', 'S', 'I', 'M', 'O', 'U', + 'T', 'R', 'O', 'M', 'I', 'K', 'O', 'N', + 'T', 'R', 'Y', 'B', 'L', 'I', 'O', 'N', + 'T', 'T', 'A', 'Y', 'A', 'N', 'N', 'A', + 'T', 'T', 'U', 'D', 'D', 'A', 'A', 'G', + 'T', 'V', 'I', 'M', 'A', 'D', 'U', 'R', + 'T', 'W', 'O', '-', 'L', 'I', 'N', 'E', + 'U', 'G', 'A', 'R', 'I', 'T', 'I', 'C', + 'U', 'I', 'L', 'L', 'E', 'A', 'N', 'N', + 'U', 'M', 'B', 'R', 'E', 'L', 'L', 'A', + 'U', 'N', 'D', 'E', 'R', 'B', 'A', 'R', + 'U', 'N', 'D', 'E', 'R', 'D', 'O', 'T', + 'U', 'N', 'D', 'E', 'R', 'T', 'I', 'E', + 'V', 'A', 'S', 'T', 'N', 'E', 'S', 'S', + 'V', 'E', 'R', 'S', 'I', 'C', 'L', 'E', + 'V', 'E', 'R', 'T', 'I', 'C', 'A', 'L', + 'V', 'I', 'E', 'W', 'D', 'A', 'T', 'A', + 'W', 'A', 'N', 'D', 'E', 'R', 'E', 'R', + 'W', 'A', 'S', 'A', 'L', 'L', 'A', 'M', + 'Y', 'A', 'M', 'A', 'K', 'K', 'A', 'N', + 'Y', 'E', 'S', 'I', 'E', 'U', 'N', 'G', + 'Y', 'O', 'U', 'T', 'H', 'F', 'U', 'L', + 'Z', 'A', 'V', 'I', 'Y', 'A', 'N', 'I', + 'Z', 'W', 'A', 'R', 'A', 'K', 'A', 'Y', + 'A', 'A', 'B', 'A', 'A', 'F', 'I', 'L', 'I', + 'A', 'B', 'K', 'H', 'A', 'S', 'I', 'A', 'N', + 'A', 'B', 'U', 'N', 'D', 'A', 'N', 'C', 'E', + 'A', 'D', 'D', 'R', 'E', 'S', 'S', 'E', 'D', + 'A', 'L', '-', 'L', 'A', 'K', 'U', 'N', 'A', + 'A', 'L', 'P', 'A', 'P', 'R', 'A', 'N', 'A', + 'A', 'L', 'T', 'E', 'R', 'N', 'A', 'T', 'E', + 'A', 'M', 'P', 'E', 'R', 'S', 'A', 'N', 'D', + 'A', 'N', 'T', 'I', 'F', 'O', 'N', 'I', 'A', + 'A', 'R', '-', 'R', 'A', 'H', 'E', 'E', 'M', + 'A', 'R', '-', 'R', 'A', 'H', 'M', 'A', 'N', + 'A', 'R', 'R', 'O', 'W', 'H', 'E', 'A', 'D', + 'A', 'S', 'C', 'E', 'N', 'D', 'I', 'N', 'G', + 'A', 'S', 'P', 'I', 'R', 'A', 'T', 'E', 'D', + 'A', 'S', 'S', 'E', 'R', 'T', 'I', 'O', 'N', + 'A', 'S', 'T', 'E', 'R', 'I', 'S', 'K', 'S', + 'A', 'T', 'T', 'E', 'N', 'T', 'I', 'O', 'N', + 'B', 'A', 'C', 'K', 'S', 'L', 'A', 'S', 'H', + 'B', 'A', 'C', 'K', 'S', 'P', 'A', 'C', 'E', + 'B', 'E', 'G', 'I', 'N', 'N', 'I', 'N', 'G', + 'B', 'I', 'N', 'O', 'C', 'U', 'L', 'A', 'R', + 'B', 'I', 'O', 'H', 'A', 'Z', 'A', 'R', 'D', + 'B', 'I', 'S', 'E', 'C', 'T', 'I', 'N', 'G', + 'B', 'I', 'S', 'M', 'I', 'L', 'L', 'A', 'H', + 'B', 'L', 'A', 'C', 'K', 'F', 'O', 'O', 'T', + 'B', 'O', 'O', 'M', 'E', 'R', 'A', 'N', 'G', + 'B', 'R', 'A', 'N', 'C', 'H', 'I', 'N', 'G', + 'B', 'Y', 'Z', 'A', 'N', 'T', 'I', 'N', 'E', + 'C', 'A', 'P', 'R', 'I', 'C', 'O', 'R', 'N', + 'C', 'A', 'R', 'P', 'E', 'N', 'T', 'R', 'Y', + 'C', 'A', 'R', 'Y', 'S', 'T', 'I', 'A', 'N', + 'C', 'E', 'N', 'T', 'U', 'R', 'I', 'A', 'L', + 'C', 'H', 'A', 'R', 'A', 'C', 'T', 'E', 'R', + 'C', 'H', 'A', 'V', 'I', 'Y', 'A', 'N', 'I', + 'C', 'L', 'O', 'C', 'K', 'W', 'I', 'S', 'E', + 'C', 'L', 'O', 'S', 'E', 'N', 'E', 'S', 'S', + 'C', 'O', 'M', 'B', 'I', 'N', 'I', 'N', 'G', + 'C', 'O', 'M', 'P', 'L', 'E', 'T', 'E', 'D', + 'C', 'O', 'N', 'G', 'R', 'U', 'E', 'N', 'T', + 'C', 'O', 'N', 'J', 'U', 'G', 'A', 'T', 'E', + 'C', 'O', 'N', 'S', 'O', 'N', 'A', 'N', 'T', + 'C', 'O', 'N', 'S', 'T', 'A', 'N', 'C', 'Y', + 'C', 'O', 'N', 'T', 'O', 'U', 'R', 'E', 'D', + 'C', 'O', 'P', 'R', 'O', 'D', 'U', 'C', 'T', + 'C', 'O', 'P', 'Y', 'R', 'I', 'G', 'H', 'T', + 'C', 'R', 'E', 'S', 'C', 'E', 'N', 'D', 'O', + 'C', 'U', 'A', 'T', 'R', 'I', 'L', 'L', 'O', + 'C', 'U', 'N', 'E', 'I', 'F', 'O', 'R', 'M', + 'D', 'A', 'H', 'Y', 'A', 'A', 'U', 'S', 'H', + 'D', 'A', 'R', 'K', 'E', 'N', 'I', 'N', 'G', + 'D', 'E', 'L', 'I', 'M', 'I', 'T', 'E', 'R', + 'D', 'E', 'N', 'T', 'I', 'S', 'T', 'R', 'Y', + 'D', 'E', 'P', 'A', 'R', 'T', 'I', 'N', 'G', + 'D', 'E', 'P', 'A', 'R', 'T', 'U', 'R', 'E', + 'D', 'E', 'S', 'C', 'E', 'N', 'D', 'E', 'R', + 'D', 'I', 'A', 'E', 'R', 'E', 'S', 'I', 'S', + 'D', 'I', 'A', 'L', 'E', 'C', 'T', '-', 'P', + 'D', 'I', 'A', 'L', 'Y', 'T', 'I', 'K', 'A', + 'D', 'I', 'A', 'T', 'O', 'N', 'I', 'K', 'I', + 'D', 'I', 'F', 'T', 'O', 'G', 'G', 'O', 'S', + 'D', 'I', 'G', 'R', 'A', 'M', 'M', 'O', 'S', + 'D', 'I', 'M', 'E', 'N', 'S', 'I', 'O', 'N', + 'D', 'O', 'T', 'S', '-', '1', '2', '3', '4', + 'D', 'O', 'T', 'S', '-', '1', '2', '3', '5', + 'D', 'O', 'T', 'S', '-', '1', '2', '3', '6', + 'D', 'O', 'T', 'S', '-', '1', '2', '3', '7', + 'D', 'O', 'T', 'S', '-', '1', '2', '3', '8', + 'D', 'O', 'T', 'S', '-', '1', '2', '4', '5', + 'D', 'O', 'T', 'S', '-', '1', '2', '4', '6', + 'D', 'O', 'T', 'S', '-', '1', '2', '4', '7', + 'D', 'O', 'T', 'S', '-', '1', '2', '4', '8', + 'D', 'O', 'T', 'S', '-', '1', '2', '5', '6', + 'D', 'O', 'T', 'S', '-', '1', '2', '5', '7', + 'D', 'O', 'T', 'S', '-', '1', '2', '5', '8', + 'D', 'O', 'T', 'S', '-', '1', '2', '6', '7', + 'D', 'O', 'T', 'S', '-', '1', '2', '6', '8', + 'D', 'O', 'T', 'S', '-', '1', '2', '7', '8', + 'D', 'O', 'T', 'S', '-', '1', '3', '4', '5', + 'D', 'O', 'T', 'S', '-', '1', '3', '4', '6', + 'D', 'O', 'T', 'S', '-', '1', '3', '4', '7', + 'D', 'O', 'T', 'S', '-', '1', '3', '4', '8', + 'D', 'O', 'T', 'S', '-', '1', '3', '5', '6', + 'D', 'O', 'T', 'S', '-', '1', '3', '5', '7', + 'D', 'O', 'T', 'S', '-', '1', '3', '5', '8', + 'D', 'O', 'T', 'S', '-', '1', '3', '6', '7', + 'D', 'O', 'T', 'S', '-', '1', '3', '6', '8', + 'D', 'O', 'T', 'S', '-', '1', '3', '7', '8', + 'D', 'O', 'T', 'S', '-', '1', '4', '5', '6', + 'D', 'O', 'T', 'S', '-', '1', '4', '5', '7', + 'D', 'O', 'T', 'S', '-', '1', '4', '5', '8', + 'D', 'O', 'T', 'S', '-', '1', '4', '6', '7', + 'D', 'O', 'T', 'S', '-', '1', '4', '6', '8', + 'D', 'O', 'T', 'S', '-', '1', '4', '7', '8', + 'D', 'O', 'T', 'S', '-', '1', '5', '6', '7', + 'D', 'O', 'T', 'S', '-', '1', '5', '6', '8', + 'D', 'O', 'T', 'S', '-', '1', '5', '7', '8', + 'D', 'O', 'T', 'S', '-', '1', '6', '7', '8', + 'D', 'O', 'T', 'S', '-', '2', '3', '4', '5', + 'D', 'O', 'T', 'S', '-', '2', '3', '4', '6', + 'D', 'O', 'T', 'S', '-', '2', '3', '4', '7', + 'D', 'O', 'T', 'S', '-', '2', '3', '4', '8', + 'D', 'O', 'T', 'S', '-', '2', '3', '5', '6', + 'D', 'O', 'T', 'S', '-', '2', '3', '5', '7', + 'D', 'O', 'T', 'S', '-', '2', '3', '5', '8', + 'D', 'O', 'T', 'S', '-', '2', '3', '6', '7', + 'D', 'O', 'T', 'S', '-', '2', '3', '6', '8', + 'D', 'O', 'T', 'S', '-', '2', '3', '7', '8', + 'D', 'O', 'T', 'S', '-', '2', '4', '5', '6', + 'D', 'O', 'T', 'S', '-', '2', '4', '5', '7', + 'D', 'O', 'T', 'S', '-', '2', '4', '5', '8', + 'D', 'O', 'T', 'S', '-', '2', '4', '6', '7', + 'D', 'O', 'T', 'S', '-', '2', '4', '6', '8', + 'D', 'O', 'T', 'S', '-', '2', '4', '7', '8', + 'D', 'O', 'T', 'S', '-', '2', '5', '6', '7', + 'D', 'O', 'T', 'S', '-', '2', '5', '6', '8', + 'D', 'O', 'T', 'S', '-', '2', '5', '7', '8', + 'D', 'O', 'T', 'S', '-', '2', '6', '7', '8', + 'D', 'O', 'T', 'S', '-', '3', '4', '5', '6', + 'D', 'O', 'T', 'S', '-', '3', '4', '5', '7', + 'D', 'O', 'T', 'S', '-', '3', '4', '5', '8', + 'D', 'O', 'T', 'S', '-', '3', '4', '6', '7', + 'D', 'O', 'T', 'S', '-', '3', '4', '6', '8', + 'D', 'O', 'T', 'S', '-', '3', '4', '7', '8', + 'D', 'O', 'T', 'S', '-', '3', '5', '6', '7', + 'D', 'O', 'T', 'S', '-', '3', '5', '6', '8', + 'D', 'O', 'T', 'S', '-', '3', '5', '7', '8', + 'D', 'O', 'T', 'S', '-', '3', '6', '7', '8', + 'D', 'O', 'T', 'S', '-', '4', '5', '6', '7', + 'D', 'O', 'T', 'S', '-', '4', '5', '6', '8', + 'D', 'O', 'T', 'S', '-', '4', '5', '7', '8', + 'D', 'O', 'T', 'S', '-', '4', '6', '7', '8', + 'D', 'O', 'T', 'S', '-', '5', '6', '7', '8', + 'D', 'O', 'W', 'N', 'W', 'A', 'R', 'D', 'S', + 'D', 'U', 'P', 'O', 'N', 'D', 'I', 'U', 'S', + 'E', 'D', 'I', 'T', 'O', 'R', 'I', 'A', 'L', + 'E', 'E', 'B', 'E', 'E', 'F', 'I', 'L', 'I', + 'E', 'M', 'B', 'E', 'D', 'D', 'I', 'N', 'G', + 'E', 'N', 'C', 'L', 'O', 'S', 'I', 'N', 'G', + 'E', 'N', 'C', 'L', 'O', 'S', 'U', 'R', 'E', + 'E', 'N', 'D', 'E', 'A', 'V', 'O', 'U', 'R', + 'E', 'N', 'D', 'O', 'F', 'O', 'N', 'O', 'N', + 'E', 'S', 'T', 'I', 'M', 'A', 'T', 'E', 'D', + 'E', 'S', 'T', 'I', 'M', 'A', 'T', 'E', 'S', + 'E', 'X', 'C', 'E', 'L', 'L', 'E', 'N', 'T', + 'E', 'X', 'T', 'E', 'N', 'S', 'I', 'O', 'N', + 'E', 'X', 'T', 'R', 'A', '-', 'L', 'O', 'W', + 'E', 'Y', 'B', 'E', 'Y', 'F', 'I', 'L', 'I', + 'F', 'A', 'C', 'S', 'I', 'M', 'I', 'L', 'E', + 'F', 'A', 'N', 'E', 'R', 'O', 'S', 'I', 'S', + 'F', 'I', 'N', 'A', 'N', 'C', 'I', 'A', 'L', + 'F', 'I', 'V', 'E', '-', 'L', 'I', 'N', 'E', + 'F', 'L', 'A', 'T', 'T', 'E', 'N', 'E', 'D', + 'F', 'O', 'L', 'L', 'O', 'W', 'I', 'N', 'G', + 'F', 'O', 'O', 'T', 'S', 'T', 'O', 'O', 'L', + 'F', 'O', 'S', 'T', 'E', 'R', 'I', 'N', 'G', + 'F', 'O', 'U', 'R', '-', 'L', 'I', 'N', 'E', + 'F', 'R', 'E', 'T', 'B', 'O', 'A', 'R', 'D', + 'F', 'R', 'I', 'C', 'A', 'T', 'I', 'V', 'E', + 'F', 'U', 'L', 'L', 'W', 'I', 'D', 'T', 'H', + 'G', 'A', 'T', 'H', 'E', 'R', 'I', 'N', 'G', + 'G', 'E', 'O', 'M', 'E', 'T', 'R', 'I', 'C', + 'G', 'E', 'R', 'S', 'H', 'A', 'Y', 'I', 'M', + 'G', 'L', 'I', 'S', 'S', 'A', 'N', 'D', 'O', + 'G', 'N', 'A', 'V', 'I', 'Y', 'A', 'N', 'I', + 'G', 'O', 'R', 'G', 'O', 'T', 'E', 'R', 'I', + 'G', 'R', 'E', 'A', 'T', 'N', 'E', 'S', 'S', + 'G', 'R', 'E', 'G', 'O', 'R', 'I', 'A', 'N', + 'G', 'U', 'R', 'A', 'M', 'U', 'T', 'O', 'N', + 'H', 'A', 'L', 'F', 'W', 'I', 'D', 'T', 'H', + 'H', 'E', 'K', 'U', 'T', 'A', 'A', 'R', 'U', + 'H', 'E', 'R', 'M', 'I', 'T', 'I', 'A', 'N', + 'H', 'O', 'U', 'R', 'G', 'L', 'A', 'S', 'S', + 'I', 'C', 'H', 'I', 'M', 'A', 'T', 'O', 'S', + 'I', 'D', 'E', 'N', 'T', 'I', 'C', 'A', 'L', + 'I', 'D', 'E', 'O', 'G', 'R', 'A', 'P', 'H', + 'I', 'L', 'U', 'U', 'Y', 'A', 'N', 'N', 'A', + 'I', 'M', 'I', 'F', 'T', 'H', 'O', 'R', 'A', + 'I', 'N', 'C', 'L', 'U', 'D', 'I', 'N', 'G', + 'I', 'N', 'C', 'R', 'E', 'A', 'S', 'E', 'S', + 'I', 'N', 'C', 'R', 'E', 'M', 'E', 'N', 'T', + 'I', 'N', 'D', 'I', 'C', 'A', 'T', 'O', 'R', + 'I', 'N', 'F', 'L', 'U', 'E', 'N', 'C', 'E', + 'I', 'N', 'N', 'O', 'C', 'E', 'N', 'C', 'E', + 'I', 'N', 'S', 'E', 'R', 'T', 'I', 'O', 'N', + 'I', 'N', 'V', 'I', 'S', 'I', 'B', 'L', 'E', + 'I', 'R', 'U', 'U', 'Y', 'A', 'N', 'N', 'A', + 'I', 'T', 'E', 'R', 'A', 'T', 'I', 'O', 'N', + 'J', 'E', 'R', 'U', 'S', 'A', 'L', 'E', 'M', + 'J', 'O', 'N', 'G', 'S', 'E', 'O', 'N', 'G', + 'J', 'U', 'N', 'G', 'S', 'E', 'O', 'N', 'G', + 'K', 'A', 'T', 'A', 'V', 'A', 'S', 'M', 'A', + 'K', 'E', 'M', 'P', 'H', 'R', 'E', 'N', 'G', + 'K', 'E', 'N', 'T', 'I', 'M', 'A', 'T', 'A', + 'K', 'I', 'R', 'O', 'W', 'A', 'T', 'T', 'O', + 'K', 'R', 'A', 'T', 'I', 'M', 'A', 'T', 'A', + 'K', 'U', 'R', 'U', 'Z', 'E', 'I', 'R', 'O', + 'L', 'A', 'B', 'O', 'U', 'R', 'I', 'N', 'G', + 'L', 'A', 'R', 'Y', 'N', 'G', 'E', 'A', 'L', + 'L', 'E', 'F', 'T', '-', 'H', 'A', 'N', 'D', + 'L', 'E', 'F', 'T', '-', 'S', 'I', 'D', 'E', + 'L', 'E', 'F', 'T', '-', 'S', 'T', 'E', 'M', + 'L', 'E', 'F', 'T', 'W', 'A', 'R', 'D', 'S', + 'L', 'E', 'S', 'S', '-', 'T', 'H', 'A', 'N', + 'L', 'H', 'A', 'V', 'I', 'Y', 'A', 'N', 'I', + 'L', 'I', 'A', 'B', 'I', 'L', 'I', 'T', 'Y', + 'L', 'I', 'G', 'H', 'T', 'N', 'I', 'N', 'G', + 'M', 'A', 'H', 'A', 'P', 'R', 'A', 'N', 'A', + 'M', 'A', 'I', 'T', 'A', 'I', 'K', 'H', 'U', + 'M', 'A', 'L', 'A', 'Y', 'A', 'L', 'A', 'M', + 'M', 'A', 'S', 'C', 'U', 'L', 'I', 'N', 'E', + 'M', 'A', 'T', 'E', 'R', 'I', 'A', 'L', 'S', + 'M', 'E', 'S', 'S', 'E', 'N', 'I', 'A', 'N', + 'M', 'E', 'T', 'O', 'B', 'E', 'L', 'U', 'S', + 'M', 'I', 'R', 'I', 'B', 'A', 'A', 'R', 'U', + 'M', 'O', 'N', 'G', 'O', 'L', 'I', 'A', 'N', + 'M', 'O', 'N', 'O', 'C', 'U', 'L', 'A', 'R', + 'M', 'O', 'N', 'O', 'G', 'R', 'A', 'P', 'H', + 'M', 'O', 'N', 'O', 'S', 'P', 'A', 'C', 'E', + 'M', 'U', 'K', 'P', 'H', 'R', 'E', 'N', 'G', + 'M', 'U', 'U', 'R', 'D', 'H', 'A', 'J', 'A', + 'N', 'I', 'G', 'G', 'A', 'H', 'I', 'T', 'A', + 'N', 'I', 'G', 'I', 'D', 'A', 'E', 'S', 'H', + 'N', 'I', 'G', 'I', 'D', 'A', 'M', 'I', 'N', + 'N', 'O', 'R', 'T', 'H', 'W', 'E', 'S', 'T', + 'N', 'U', 'M', 'E', 'R', 'A', 'T', 'O', 'R', + 'O', 'A', 'B', 'O', 'A', 'F', 'I', 'L', 'I', + 'O', 'O', 'B', 'O', 'O', 'F', 'I', 'L', 'I', + 'O', 'Y', 'R', 'A', 'N', 'I', 'S', 'M', 'A', + 'P', 'A', 'A', '-', 'P', 'I', 'L', 'L', 'A', + 'P', 'A', 'I', 'Y', 'A', 'N', 'N', 'O', 'I', + 'P', 'A', 'M', 'I', 'N', 'G', 'K', 'A', 'L', + 'P', 'A', 'M', 'U', 'N', 'G', 'K', 'A', 'H', + 'P', 'A', 'N', 'G', 'L', 'A', 'Y', 'A', 'R', + 'P', 'A', 'N', 'G', 'W', 'I', 'S', 'A', 'D', + 'P', 'A', 'R', 'A', 'G', 'R', 'A', 'P', 'H', + 'P', 'E', 'N', 'T', 'A', 'S', 'E', 'M', 'E', + 'P', 'E', 'R', 'F', 'E', 'C', 'T', 'U', 'M', + 'P', 'E', 'R', 'M', 'A', 'N', 'E', 'N', 'T', + 'P', 'I', 'A', 'S', 'U', 'T', 'O', 'R', 'U', + 'P', 'I', 'T', 'C', 'H', 'F', 'O', 'R', 'K', + 'P', 'I', 'Z', 'Z', 'I', 'C', 'A', 'T', 'O', + 'P', 'O', 'R', 'R', 'E', 'C', 'T', 'U', 'S', + 'P', 'R', 'A', 'M', '-', 'B', 'U', 'O', 'N', + 'P', 'R', 'A', 'M', '-', 'M', 'U', 'O', 'Y', + 'P', 'R', 'E', 'C', 'E', 'D', 'I', 'N', 'G', + 'P', 'R', 'O', 'L', 'O', 'N', 'G', 'E', 'D', + 'P', 'R', 'O', 'P', 'E', 'L', 'L', 'E', 'R', + 'P', 'S', 'I', 'F', 'I', 'S', 'T', 'O', 'N', + 'Q', 'U', 'A', 'D', 'R', 'U', 'P', 'L', 'E', + 'Q', 'U', 'I', 'N', 'A', 'R', 'I', 'U', 'S', + 'Q', 'U', 'O', 'T', 'A', 'T', 'I', 'O', 'N', + 'Q', 'U', 'S', 'H', 'S', 'H', 'A', 'Y', 'A', + 'R', 'E', 'C', 'E', 'P', 'T', 'I', 'V', 'E', + 'R', 'E', 'C', 'O', 'R', 'D', 'I', 'N', 'G', + 'R', 'E', 'C', 'T', 'A', 'N', 'G', 'L', 'E', + 'R', 'E', 'C', 'Y', 'C', 'L', 'I', 'N', 'G', + 'R', 'E', 'F', 'E', 'R', 'E', 'N', 'C', 'E', + 'R', 'E', 'P', 'R', 'E', 'S', 'E', 'N', 'T', + 'R', 'E', 'S', 'I', 'D', 'E', 'N', 'C', 'E', + 'R', 'E', 'S', 'U', 'P', 'I', 'N', 'U', 'S', + 'R', 'E', 'T', 'R', 'O', 'F', 'L', 'E', 'X', + 'R', 'I', 'G', 'H', 'T', 'H', 'A', 'N', 'D', + 'S', 'A', 'M', 'A', 'R', 'I', 'T', 'A', 'N', + 'S', 'C', 'A', 'N', 'D', 'I', 'C', 'U', 'S', + 'S', 'E', 'B', 'A', 'T', 'B', 'E', 'I', 'T', + 'S', 'E', 'M', 'I', 'C', 'O', 'L', 'O', 'N', + 'S', 'E', 'M', 'I', 'V', 'O', 'W', 'E', 'L', + 'S', 'E', 'P', 'A', 'R', 'A', 'T', 'O', 'R', + 'S', 'E', 'P', 'T', 'E', 'M', 'B', 'E', 'R', + 'S', 'E', 'V', 'E', 'N', 'T', 'E', 'E', 'N', + 'S', 'E', 'V', 'E', 'R', 'A', 'N', 'C', 'E', + 'S', 'H', 'A', 'V', 'I', 'Y', 'A', 'N', 'I', + 'S', 'H', 'O', 'R', 'T', 'E', 'N', 'E', 'R', + 'S', 'I', 'X', 'T', 'E', 'E', 'N', 'T', 'H', + 'S', 'N', 'O', 'W', 'F', 'L', 'A', 'K', 'E', + 'S', 'P', 'H', 'E', 'R', 'I', 'C', 'A', 'L', + 'S', 'P', 'L', 'I', 'T', 'T', 'I', 'N', 'G', + 'S', 'S', 'A', 'N', 'G', 'S', 'I', 'O', 'S', + 'S', 'T', 'R', 'E', 'T', 'C', 'H', 'E', 'D', + 'S', 'T', 'R', 'O', 'K', 'E', '-', '1', '0', + 'S', 'T', 'R', 'O', 'K', 'E', '-', '1', '1', + 'S', 'U', 'B', 'J', 'O', 'I', 'N', 'E', 'D', + 'S', 'U', 'B', 'L', 'I', 'N', 'E', 'A', 'R', + 'S', 'U', 'B', 'S', 'C', 'R', 'I', 'P', 'T', + 'S', 'U', 'M', 'M', 'A', 'T', 'I', 'O', 'N', + 'S', 'U', 'N', 'D', 'A', 'N', 'E', 'S', 'E', + 'S', 'U', 'P', 'E', 'R', 'V', 'I', 'S', 'E', + 'S', 'Y', 'L', 'L', 'A', 'B', 'I', 'C', 'S', + 'S', 'Y', 'M', 'B', 'O', 'L', '-', '1', '0', + 'S', 'Y', 'M', 'B', 'O', 'L', '-', '1', '1', + 'S', 'Y', 'M', 'B', 'O', 'L', '-', '1', '2', + 'S', 'Y', 'M', 'B', 'O', 'L', '-', '1', '3', + 'S', 'Y', 'M', 'B', 'O', 'L', '-', '1', '4', + 'S', 'Y', 'M', 'B', 'O', 'L', '-', '1', '5', + 'S', 'Y', 'M', 'B', 'O', 'L', '-', '1', '6', + 'S', 'Y', 'M', 'B', 'O', 'L', '-', '1', '7', + 'S', 'Y', 'M', 'B', 'O', 'L', '-', '1', '8', + 'S', 'Y', 'M', 'B', 'O', 'L', '-', '1', '9', + 'S', 'Y', 'M', 'B', 'O', 'L', '-', '2', '0', + 'S', 'Y', 'M', 'B', 'O', 'L', '-', '2', '1', + 'S', 'Y', 'M', 'B', 'O', 'L', '-', '2', '2', + 'S', 'Y', 'M', 'B', 'O', 'L', '-', '2', '3', + 'S', 'Y', 'M', 'B', 'O', 'L', '-', '2', '4', + 'S', 'Y', 'M', 'B', 'O', 'L', '-', '2', '5', + 'S', 'Y', 'M', 'B', 'O', 'L', '-', '2', '6', + 'S', 'Y', 'M', 'B', 'O', 'L', '-', '2', '7', + 'S', 'Y', 'M', 'B', 'O', 'L', '-', '2', '9', + 'S', 'Y', 'M', 'B', 'O', 'L', '-', '3', '0', + 'S', 'Y', 'M', 'B', 'O', 'L', '-', '3', '2', + 'S', 'Y', 'M', 'B', 'O', 'L', '-', '3', '6', + 'S', 'Y', 'M', 'B', 'O', 'L', '-', '3', '7', + 'S', 'Y', 'M', 'B', 'O', 'L', '-', '3', '8', + 'S', 'Y', 'M', 'B', 'O', 'L', '-', '3', '9', + 'S', 'Y', 'M', 'B', 'O', 'L', '-', '4', '0', + 'S', 'Y', 'M', 'B', 'O', 'L', '-', '4', '2', + 'S', 'Y', 'M', 'B', 'O', 'L', '-', '4', '3', + 'S', 'Y', 'M', 'B', 'O', 'L', '-', '4', '5', + 'S', 'Y', 'M', 'B', 'O', 'L', '-', '4', '7', + 'S', 'Y', 'M', 'B', 'O', 'L', '-', '4', '8', + 'S', 'Y', 'M', 'B', 'O', 'L', '-', '4', '9', + 'S', 'Y', 'M', 'B', 'O', 'L', '-', '5', '0', + 'S', 'Y', 'M', 'B', 'O', 'L', '-', '5', '1', + 'S', 'Y', 'M', 'B', 'O', 'L', '-', '5', '2', + 'S', 'Y', 'M', 'B', 'O', 'L', '-', '5', '3', + 'S', 'Y', 'M', 'B', 'O', 'L', '-', '5', '4', + 'S', 'Y', 'M', 'M', 'E', 'T', 'R', 'I', 'C', + 'S', 'Y', 'N', 'D', 'E', 'S', 'M', 'O', 'S', + 'S', 'Y', 'R', 'M', 'A', 'T', 'I', 'K', 'I', + 'T', 'A', 'K', 'H', 'A', 'L', 'L', 'U', 'S', + 'T', 'E', 'L', 'E', 'G', 'R', 'A', 'P', 'H', + 'T', 'E', 'L', 'E', 'P', 'H', 'O', 'N', 'E', + 'T', 'E', 'T', 'R', 'A', 'G', 'R', 'A', 'M', + 'T', 'E', 'T', 'R', 'A', 'S', 'E', 'M', 'E', + 'T', 'H', 'E', 'R', 'E', 'F', 'O', 'R', 'E', + 'T', 'H', 'O', 'U', 'S', 'A', 'N', 'D', 'S', + 'T', 'R', 'A', 'P', 'E', 'Z', 'I', 'U', 'M', + 'T', 'R', 'E', 'M', 'O', 'L', 'O', '-', '1', + 'T', 'R', 'E', 'M', 'O', 'L', 'O', '-', '2', + 'T', 'R', 'E', 'M', 'O', 'L', 'O', '-', '3', + 'T', 'R', 'I', 'F', 'O', 'N', 'I', 'A', 'S', + 'T', 'R', 'I', 'G', 'O', 'R', 'G', 'O', 'N', + 'T', 'R', 'U', 'N', 'C', 'A', 'T', 'E', 'D', + 'T', 'U', 'R', 'N', 'S', 'T', 'I', 'L', 'E', + 'T', 'U', 'T', 'E', 'Y', 'A', 'S', 'A', 'T', + 'U', 'K', 'R', 'A', 'I', 'N', 'I', 'A', 'N', + 'U', 'N', 'D', 'E', 'R', 'L', 'I', 'N', 'E', + 'U', 'N', 'I', 'V', 'E', 'R', 'S', 'A', 'L', + 'U', 'N', 'M', 'A', 'R', 'R', 'I', 'E', 'D', + 'V', 'A', 'R', 'I', 'A', 'T', 'I', 'O', 'N', + 'V', 'I', 'S', 'A', 'R', 'G', 'A', 'Y', 'A', + 'V', 'O', 'I', 'C', 'E', 'L', 'E', 'S', 'S', + 'W', 'A', 'S', 'S', 'A', 'L', 'L', 'A', 'M', + 'W', 'E', 'S', 'T', '-', 'C', 'R', 'E', 'E', + 'W', 'O', 'R', 'D', 'S', 'P', 'A', 'C', 'E', + 'Y', 'P', 'O', 'K', 'R', 'I', 'S', 'I', 'S', + 'A', 'C', 'R', 'O', 'P', 'H', 'O', 'N', 'I', 'C', + 'A', 'E', 'D', 'A', '-', 'P', 'I', 'L', 'L', 'A', + 'A', 'E', 'L', 'A', '-', 'P', 'I', 'L', 'L', 'A', + 'A', 'L', 'P', 'A', 'P', 'R', 'A', 'A', 'N', 'A', + 'A', 'N', 'G', 'K', 'H', 'A', 'N', 'K', 'H', 'U', + 'A', 'N', 'N', 'O', 'T', 'A', 'T', 'I', 'O', 'N', + 'A', 'N', 'T', 'I', 'K', 'E', 'N', 'O', 'M', 'A', + 'A', 'N', 'U', 'S', 'V', 'A', 'R', 'A', 'Y', 'A', + 'A', 'P', 'O', 'S', 'T', 'R', 'O', 'F', 'O', 'I', + 'A', 'P', 'O', 'S', 'T', 'R', 'O', 'F', 'O', 'S', + 'A', 'P', 'O', 'S', 'T', 'R', 'O', 'P', 'H', 'E', + 'A', 'P', 'P', 'R', 'O', 'A', 'C', 'H', 'E', 'S', + 'A', 'R', 'P', 'E', 'G', 'G', 'I', 'A', 'T', 'O', + 'A', 'R', 'R', 'O', 'W', '-', 'T', 'A', 'I', 'L', + 'A', 'S', 'T', 'E', 'R', 'I', 'S', 'C', 'U', 'S', + 'A', 'T', 'H', 'A', 'P', 'A', 'S', 'C', 'A', 'N', + 'A', 'U', 'R', 'A', 'M', 'A', 'Z', 'D', 'A', 'A', + 'B', 'A', 'R', 'I', 'Y', 'O', 'O', 'S', 'A', 'N', + 'B', 'A', 'T', 'H', 'A', 'M', 'A', 'S', 'A', 'T', + 'B', 'I', 'B', 'L', 'E', '-', 'C', 'R', 'E', 'E', + 'C', 'E', 'N', 'T', 'R', 'E', 'L', 'I', 'N', 'E', + 'C', 'H', 'A', 'R', 'A', 'C', 'T', 'E', 'R', 'S', + 'C', 'I', 'R', 'C', 'U', 'M', 'F', 'L', 'E', 'X', + 'C', 'O', 'M', 'M', 'E', 'R', 'C', 'I', 'A', 'L', + 'C', 'O', 'M', 'P', 'L', 'E', 'M', 'E', 'N', 'T', + 'C', 'O', 'M', 'P', 'L', 'E', 'T', 'I', 'O', 'N', + 'C', 'O', 'M', 'P', 'L', 'I', 'A', 'N', 'C', 'E', + 'C', 'O', 'N', 'J', 'O', 'I', 'N', 'I', 'N', 'G', + 'C', 'O', 'N', 'T', 'A', 'I', 'N', 'I', 'N', 'G', + 'C', 'O', 'N', 'T', 'E', 'N', 'T', 'I', 'O', 'N', + 'C', 'O', 'N', 'T', 'I', 'N', 'U', 'O', 'U', 'S', + 'C', 'R', 'O', 'S', 'S', 'B', 'O', 'N', 'E', 'S', + 'C', 'R', 'O', 'S', 'S', 'H', 'A', 'T', 'C', 'H', + 'D', 'A', 'G', 'B', 'A', 'S', 'I', 'N', 'N', 'A', + 'D', 'E', 'F', 'I', 'N', 'I', 'T', 'I', 'O', 'N', + 'D', 'E', 'S', 'C', 'E', 'N', 'D', 'I', 'N', 'G', + 'D', 'E', 'V', 'A', 'N', 'A', 'G', 'A', 'R', 'I', + 'D', 'I', 'F', 'F', 'E', 'R', 'E', 'N', 'C', 'E', + 'D', 'I', 'F', 'F', 'I', 'C', 'U', 'L', 'T', 'Y', + 'D', 'I', 'S', 'P', 'E', 'R', 'S', 'I', 'O', 'N', + 'D', 'I', 'S', 'T', 'O', 'R', 'T', 'I', 'O', 'N', + 'D', 'I', 'V', 'E', 'R', 'G', 'E', 'N', 'C', 'E', + 'D', 'I', 'V', 'I', 'N', 'A', 'T', 'I', 'O', 'N', + 'D', 'O', 'T', 'S', '-', '1', '2', '3', '4', '5', + 'D', 'O', 'T', 'S', '-', '1', '2', '3', '4', '6', + 'D', 'O', 'T', 'S', '-', '1', '2', '3', '4', '7', + 'D', 'O', 'T', 'S', '-', '1', '2', '3', '4', '8', + 'D', 'O', 'T', 'S', '-', '1', '2', '3', '5', '6', + 'D', 'O', 'T', 'S', '-', '1', '2', '3', '5', '7', + 'D', 'O', 'T', 'S', '-', '1', '2', '3', '5', '8', + 'D', 'O', 'T', 'S', '-', '1', '2', '3', '6', '7', + 'D', 'O', 'T', 'S', '-', '1', '2', '3', '6', '8', + 'D', 'O', 'T', 'S', '-', '1', '2', '3', '7', '8', + 'D', 'O', 'T', 'S', '-', '1', '2', '4', '5', '6', + 'D', 'O', 'T', 'S', '-', '1', '2', '4', '5', '7', + 'D', 'O', 'T', 'S', '-', '1', '2', '4', '5', '8', + 'D', 'O', 'T', 'S', '-', '1', '2', '4', '6', '7', + 'D', 'O', 'T', 'S', '-', '1', '2', '4', '6', '8', + 'D', 'O', 'T', 'S', '-', '1', '2', '4', '7', '8', + 'D', 'O', 'T', 'S', '-', '1', '2', '5', '6', '7', + 'D', 'O', 'T', 'S', '-', '1', '2', '5', '6', '8', + 'D', 'O', 'T', 'S', '-', '1', '2', '5', '7', '8', + 'D', 'O', 'T', 'S', '-', '1', '2', '6', '7', '8', + 'D', 'O', 'T', 'S', '-', '1', '3', '4', '5', '6', + 'D', 'O', 'T', 'S', '-', '1', '3', '4', '5', '7', + 'D', 'O', 'T', 'S', '-', '1', '3', '4', '5', '8', + 'D', 'O', 'T', 'S', '-', '1', '3', '4', '6', '7', + 'D', 'O', 'T', 'S', '-', '1', '3', '4', '6', '8', + 'D', 'O', 'T', 'S', '-', '1', '3', '4', '7', '8', + 'D', 'O', 'T', 'S', '-', '1', '3', '5', '6', '7', + 'D', 'O', 'T', 'S', '-', '1', '3', '5', '6', '8', + 'D', 'O', 'T', 'S', '-', '1', '3', '5', '7', '8', + 'D', 'O', 'T', 'S', '-', '1', '3', '6', '7', '8', + 'D', 'O', 'T', 'S', '-', '1', '4', '5', '6', '7', + 'D', 'O', 'T', 'S', '-', '1', '4', '5', '6', '8', + 'D', 'O', 'T', 'S', '-', '1', '4', '5', '7', '8', + 'D', 'O', 'T', 'S', '-', '1', '4', '6', '7', '8', + 'D', 'O', 'T', 'S', '-', '1', '5', '6', '7', '8', + 'D', 'O', 'T', 'S', '-', '2', '3', '4', '5', '6', + 'D', 'O', 'T', 'S', '-', '2', '3', '4', '5', '7', + 'D', 'O', 'T', 'S', '-', '2', '3', '4', '5', '8', + 'D', 'O', 'T', 'S', '-', '2', '3', '4', '6', '7', + 'D', 'O', 'T', 'S', '-', '2', '3', '4', '6', '8', + 'D', 'O', 'T', 'S', '-', '2', '3', '4', '7', '8', + 'D', 'O', 'T', 'S', '-', '2', '3', '5', '6', '7', + 'D', 'O', 'T', 'S', '-', '2', '3', '5', '6', '8', + 'D', 'O', 'T', 'S', '-', '2', '3', '5', '7', '8', + 'D', 'O', 'T', 'S', '-', '2', '3', '6', '7', '8', + 'D', 'O', 'T', 'S', '-', '2', '4', '5', '6', '7', + 'D', 'O', 'T', 'S', '-', '2', '4', '5', '6', '8', + 'D', 'O', 'T', 'S', '-', '2', '4', '5', '7', '8', + 'D', 'O', 'T', 'S', '-', '2', '4', '6', '7', '8', + 'D', 'O', 'T', 'S', '-', '2', '5', '6', '7', '8', + 'D', 'O', 'T', 'S', '-', '3', '4', '5', '6', '7', + 'D', 'O', 'T', 'S', '-', '3', '4', '5', '6', '8', + 'D', 'O', 'T', 'S', '-', '3', '4', '5', '7', '8', + 'D', 'O', 'T', 'S', '-', '3', '4', '6', '7', '8', + 'D', 'O', 'T', 'S', '-', '3', '5', '6', '7', '8', + 'D', 'O', 'T', 'S', '-', '4', '5', '6', '7', '8', + 'E', 'K', 'S', 'T', 'R', 'E', 'P', 'T', 'O', 'N', + 'E', 'L', 'E', 'C', 'T', 'R', 'I', 'C', 'A', 'L', + 'E', 'M', 'B', 'R', 'O', 'I', 'D', 'E', 'R', 'Y', + 'E', 'N', 'A', 'R', 'M', 'O', 'N', 'I', 'O', 'S', + 'E', 'N', 'C', 'O', 'U', 'N', 'T', 'E', 'R', 'S', + 'E', 'N', 'T', 'E', 'R', 'P', 'R', 'I', 'S', 'E', + 'E', 'N', 'T', 'H', 'U', 'S', 'I', 'A', 'S', 'M', + 'E', 'P', 'I', 'D', 'A', 'U', 'R', 'E', 'A', 'N', + 'E', 'P', 'I', 'G', 'R', 'A', 'P', 'H', 'I', 'C', + 'E', 'Q', 'U', 'I', 'V', 'A', 'L', 'E', 'N', 'T', + 'E', 'X', 'H', 'A', 'U', 'S', 'T', 'I', 'O', 'N', + 'E', 'X', 'T', 'R', 'A', '-', 'H', 'I', 'G', 'H', + 'F', 'A', 'H', 'R', 'E', 'N', 'H', 'E', 'I', 'T', + 'F', 'E', 'L', 'L', 'O', 'W', 'S', 'H', 'I', 'P', + 'F', 'I', 'X', 'E', 'D', '-', 'F', 'O', 'R', 'M', + 'F', 'O', 'R', 'M', 'A', 'T', 'T', 'I', 'N', 'G', + 'F', 'U', 'N', 'C', 'T', 'I', 'O', 'N', 'A', 'L', + 'G', 'B', 'A', 'K', 'U', 'R', 'U', 'N', 'E', 'N', + 'G', 'E', 'M', 'I', 'N', 'A', 'T', 'I', 'O', 'N', + 'G', 'L', 'A', 'G', 'O', 'L', 'I', 'T', 'I', 'C', + 'G', 'O', 'R', 'T', 'H', 'M', 'I', 'K', 'O', 'N', + 'H', 'E', 'R', 'M', 'I', 'O', 'N', 'I', 'A', 'N', + 'H', 'O', 'M', 'O', 'T', 'H', 'E', 'T', 'I', 'C', + 'H', 'O', 'R', 'I', 'Z', 'O', 'N', 'T', 'A', 'L', + 'H', 'Y', 'S', 'T', 'E', 'R', 'E', 'S', 'I', 'S', + 'I', 'E', 'U', 'N', 'G', '-', 'S', 'I', 'O', 'S', + 'I', 'M', 'I', 'D', 'I', 'A', 'R', 'G', 'O', 'N', + 'I', 'M', 'I', 'F', 'T', 'H', 'O', 'R', 'O', 'N', + 'I', 'M', 'P', 'E', 'R', 'F', 'E', 'C', 'T', 'A', + 'I', 'N', 'C', 'O', 'M', 'P', 'L', 'E', 'T', 'E', + 'I', 'N', 'D', 'U', 'S', 'T', 'R', 'I', 'A', 'L', + 'K', 'H', 'A', 'K', 'A', 'S', 'S', 'I', 'A', 'N', + 'K', 'H', 'A', 'R', 'O', 'S', 'H', 'T', 'H', 'I', + 'K', 'I', 'R', 'O', 'G', 'U', 'R', 'A', 'M', 'U', + 'K', 'U', 'N', 'D', 'D', 'A', 'L', 'I', 'Y', 'A', + 'L', 'A', 'J', 'A', 'N', 'Y', 'A', 'L', 'A', 'N', + 'L', 'E', 'N', 'G', 'T', 'H', 'E', 'N', 'E', 'R', + 'L', 'E', 'N', 'T', 'I', 'C', 'U', 'L', 'A', 'R', + 'L', 'I', 'M', 'I', 'T', 'A', 'T', 'I', 'O', 'N', + 'M', 'E', 'M', 'B', 'E', 'R', 'S', 'H', 'I', 'P', + 'M', 'I', 'E', 'U', 'M', '-', 'S', 'I', 'O', 'S', + 'M', 'O', 'N', 'O', 'F', 'O', 'N', 'I', 'A', 'S', + 'M', 'O', 'N', 'O', 'S', 'T', 'A', 'B', 'L', 'E', + 'M', 'O', 'O', 'S', 'E', '-', 'C', 'R', 'E', 'E', + 'M', 'U', '-', 'G', 'A', 'A', 'H', 'L', 'A', 'A', + 'N', 'A', 'A', 'S', 'I', 'K', 'Y', 'A', 'Y', 'A', + 'N', 'A', 'N', 'G', 'M', 'O', 'N', 'T', 'H', 'O', + 'N', 'I', 'E', 'U', 'N', '-', 'S', 'I', 'O', 'S', + 'N', 'O', 'N', '-', 'J', 'O', 'I', 'N', 'E', 'R', + 'N', 'O', 'N', 'F', 'O', 'R', 'K', 'I', 'N', 'G', + 'O', 'P', 'P', 'O', 'S', 'I', 'T', 'I', 'O', 'N', + 'O', 'P', 'P', 'R', 'E', 'S', 'S', 'I', 'O', 'N', + 'O', 'R', 'T', 'H', 'O', 'G', 'O', 'N', 'A', 'L', + 'P', 'A', 'M', 'P', 'H', 'Y', 'L', 'I', 'A', 'N', + 'P', 'A', 'N', 'A', 'E', 'L', 'A', 'E', 'N', 'G', + 'P', 'A', 'N', 'E', 'U', 'L', 'E', 'U', 'N', 'G', + 'P', 'A', 'R', 'A', 'P', 'H', 'R', 'A', 'S', 'E', + 'P', 'A', 'T', 'H', 'A', 'M', 'A', 'S', 'A', 'T', + 'P', 'E', 'D', 'E', 'S', 'T', 'R', 'I', 'A', 'N', + 'P', 'E', 'R', 'C', 'U', 'S', 'S', 'I', 'V', 'E', + 'P', 'H', 'A', 'R', 'Y', 'N', 'G', 'E', 'A', 'L', + 'P', 'H', 'I', 'L', 'I', 'P', 'P', 'I', 'N', 'E', + 'P', 'H', 'O', 'E', 'N', 'I', 'C', 'I', 'A', 'N', + 'P', 'I', 'E', 'U', 'P', '-', 'S', 'I', 'O', 'S', + 'P', 'L', 'U', 'S', '-', 'M', 'I', 'N', 'U', 'S', + 'P', 'O', 'S', 'S', 'E', 'S', 'S', 'I', 'O', 'N', + 'P', 'R', 'O', 'J', 'E', 'C', 'T', 'I', 'O', 'N', + 'P', 'R', 'O', 'J', 'E', 'C', 'T', 'I', 'V', 'E', + 'P', 'R', 'O', 'L', 'A', 'T', 'I', 'O', 'N', 'E', + 'P', 'R', 'O', 'P', 'O', 'R', 'T', 'I', 'O', 'N', + 'P', 'R', 'O', 'T', 'O', 'V', 'A', 'R', 'Y', 'S', + 'Q', 'U', 'A', 'T', 'E', 'R', 'N', 'I', 'O', 'N', + 'Q', 'U', 'E', 'S', 'T', 'I', 'O', 'N', 'E', 'D', + 'R', 'E', 'G', 'I', 'S', 'T', 'E', 'R', 'E', 'D', + 'R', 'E', 'L', 'A', 'T', 'I', 'O', 'N', 'A', 'L', + 'R', 'E', 'S', 'I', 'S', 'T', 'A', 'N', 'C', 'E', + 'R', 'E', 'S', 'O', 'L', 'U', 'T', 'I', 'O', 'N', + 'R', 'E', 'V', 'O', 'L', 'U', 'T', 'I', 'O', 'N', + 'R', 'I', 'E', 'U', 'L', '-', 'S', 'I', 'O', 'S', + 'R', 'I', 'G', 'H', 'T', '-', 'H', 'A', 'N', 'D', + 'R', 'I', 'G', 'H', 'T', '-', 'S', 'I', 'D', 'E', + 'R', 'I', 'G', 'H', 'T', 'W', 'A', 'R', 'D', 'S', + 'S', 'A', 'N', 'S', '-', 'S', 'E', 'R', 'I', 'F', + 'S', 'A', 'U', 'R', 'A', 'S', 'H', 'T', 'R', 'A', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '3', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '4', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '5', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '6', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '7', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '8', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '9', + 'S', 'E', 'M', 'I', 'B', 'R', 'E', 'V', 'I', 'S', + 'S', 'E', 'M', 'I', 'C', 'I', 'R', 'C', 'L', 'E', + 'S', 'E', 'M', 'I', 'D', 'I', 'R', 'E', 'C', 'T', + 'S', 'E', 'M', 'I', 'M', 'I', 'N', 'I', 'M', 'A', + 'S', 'E', 'S', 'T', 'E', 'R', 'T', 'I', 'U', 'S', + 'S', 'H', 'A', 'L', 'S', 'H', 'E', 'L', 'E', 'T', + 'S', 'H', 'O', 'U', 'L', 'D', 'E', 'R', 'E', 'D', + 'S', 'I', 'M', 'P', 'L', 'I', 'F', 'I', 'E', 'D', + 'S', 'I', 'O', 'S', '-', 'C', 'I', 'E', 'U', 'C', + 'S', 'I', 'O', 'S', '-', 'H', 'I', 'E', 'U', 'H', + 'S', 'I', 'O', 'S', '-', 'I', 'E', 'U', 'N', 'G', + 'S', 'I', 'O', 'S', '-', 'M', 'I', 'E', 'U', 'M', + 'S', 'I', 'O', 'S', '-', 'N', 'I', 'E', 'U', 'N', + 'S', 'I', 'O', 'S', '-', 'P', 'I', 'E', 'U', 'P', + 'S', 'I', 'O', 'S', '-', 'R', 'I', 'E', 'U', 'L', + 'S', 'I', 'X', '-', 'P', 'E', 'R', '-', 'E', 'M', + 'S', 'I', 'X', '-', 'S', 'T', 'R', 'I', 'N', 'G', + 'S', 'S', 'A', 'N', 'G', 'A', 'R', 'A', 'E', 'A', + 'S', 'S', 'A', 'N', 'G', 'C', 'I', 'E', 'U', 'C', + 'S', 'S', 'A', 'N', 'G', 'H', 'I', 'E', 'U', 'H', + 'S', 'S', 'A', 'N', 'G', 'I', 'E', 'U', 'N', 'G', + 'S', 'S', 'A', 'N', 'G', 'N', 'I', 'E', 'U', 'N', + 'S', 'S', 'A', 'N', 'G', 'P', 'I', 'E', 'U', 'P', + 'S', 'S', 'A', 'N', 'G', 'R', 'I', 'E', 'U', 'L', + 'S', 'T', 'A', 'N', 'D', 'S', 'T', 'I', 'L', 'L', + 'S', 'U', 'B', 'P', 'U', 'N', 'C', 'T', 'I', 'S', + 'S', 'U', 'B', 'S', 'T', 'I', 'T', 'U', 'T', 'E', + 'S', 'U', 'P', 'E', 'R', 'F', 'I', 'X', 'E', 'D', + 'S', 'U', 'S', 'P', 'E', 'N', 'S', 'I', 'O', 'N', + 'T', 'A', 'B', 'U', 'L', 'A', 'T', 'I', 'O', 'N', + 'T', 'A', 'W', 'E', 'L', 'L', 'E', 'M', 'E', 'T', + 'T', 'E', 'R', 'M', 'I', 'N', 'A', 'T', 'O', 'R', + 'T', 'E', 'T', 'R', 'A', 'S', 'I', 'M', 'O', 'U', + 'T', 'H', 'I', 'R', 'T', 'Y', '-', 'O', 'N', 'E', + 'T', 'H', 'R', 'E', 'E', '-', 'L', 'I', 'N', 'E', + 'T', 'R', 'I', 'A', 'N', 'G', 'U', 'L', 'A', 'R', + 'T', 'R', 'I', 'F', 'O', 'L', 'I', 'A', 'T', 'E', + 'T', 'R', 'I', 'G', 'R', 'A', 'M', 'M', 'O', 'S', + 'T', 'R', 'O', 'E', 'Z', 'E', 'N', 'I', 'A', 'N', + 'T', 'R', 'O', 'K', 'U', 'T', 'A', 'S', 'T', 'I', + 'T', 'W', 'E', 'N', 'T', 'Y', '-', 'O', 'N', 'E', + 'T', 'W', 'E', 'N', 'T', 'Y', '-', 'S', 'I', 'X', + 'T', 'W', 'E', 'N', 'T', 'Y', '-', 'T', 'W', 'O', + 'T', 'W', 'O', '-', 'H', 'E', 'A', 'D', 'E', 'D', + 'V', 'E', 'R', 'T', 'I', 'C', 'A', 'L', 'L', 'Y', + 'V', 'I', 'S', 'I', 'G', 'O', 'T', 'H', 'I', 'C', + 'W', 'H', 'E', 'E', 'L', 'C', 'H', 'A', 'I', 'R', + 'W', 'O', 'O', 'D', 'S', '-', 'C', 'R', 'E', 'E', + 'A', 'C', 'K', 'N', 'O', 'W', 'L', 'E', 'D', 'G', 'E', + 'A', 'E', 'S', 'C', 'U', 'L', 'A', 'P', 'I', 'U', 'S', + 'A', 'G', 'G', 'R', 'A', 'V', 'A', 'T', 'I', 'O', 'N', + 'A', 'L', 'T', 'E', 'R', 'N', 'A', 'T', 'I', 'O', 'N', + 'A', 'L', 'T', 'E', 'R', 'N', 'A', 'T', 'I', 'V', 'E', + 'A', 'P', 'P', 'L', 'I', 'C', 'A', 'T', 'I', 'O', 'N', + 'A', 'P', 'P', 'R', 'O', 'X', 'I', 'M', 'A', 'T', 'E', + 'B', 'A', 'C', 'K', '-', 'T', 'I', 'L', 'T', 'E', 'D', + 'C', 'A', 'N', 'D', 'R', 'A', 'B', 'I', 'N', 'D', 'U', + 'C', 'I', 'E', 'U', 'C', '-', 'I', 'E', 'U', 'N', 'G', + 'C', 'I', 'R', 'C', 'U', 'L', 'A', 'T', 'I', 'O', 'N', + 'C', 'L', 'U', 'B', '-', 'S', 'P', 'O', 'K', 'E', 'D', + 'C', 'O', 'M', 'P', 'O', 'S', 'I', 'T', 'I', 'O', 'N', + 'C', 'O', 'N', 'J', 'U', 'N', 'C', 'T', 'I', 'O', 'N', + 'C', 'O', 'N', 'S', 'E', 'C', 'U', 'T', 'I', 'V', 'E', + 'C', 'O', 'N', 'T', 'R', 'A', 'C', 'T', 'I', 'O', 'N', + 'C', 'O', 'N', 'T', 'R', 'A', 'R', 'I', 'E', 'T', 'Y', + 'C', 'O', 'R', 'P', 'O', 'R', 'A', 'T', 'I', 'O', 'N', + 'C', 'O', 'R', 'R', 'E', 'S', 'P', 'O', 'N', 'D', 'S', + 'C', 'O', 'U', 'N', 'T', 'E', 'R', 'B', 'O', 'R', 'E', + 'C', 'O', 'U', 'N', 'T', 'E', 'R', 'S', 'I', 'N', 'K', + 'D', 'A', 'H', 'Y', 'A', 'A', 'U', 'S', 'H', '-', '2', + 'D', 'E', 'C', 'R', 'E', 'S', 'C', 'E', 'N', 'D', 'O', + 'D', 'E', 'L', 'I', 'V', 'E', 'R', 'A', 'N', 'C', 'E', + 'D', 'E', 'N', 'O', 'M', 'I', 'N', 'A', 'T', 'O', 'R', + 'D', 'E', 'R', 'E', 'T', '-', 'H', 'I', 'D', 'E', 'T', + 'D', 'E', 'S', 'C', 'R', 'I', 'P', 'T', 'I', 'O', 'N', + 'D', 'E', 'V', 'E', 'L', 'O', 'P', 'M', 'E', 'N', 'T', + 'D', 'I', 'A', 'E', 'R', 'E', 'S', 'I', 'Z', 'E', 'D', + 'D', 'I', 'M', 'E', 'N', 'S', 'I', 'O', 'N', 'A', 'L', + 'D', 'I', 'R', 'E', 'C', 'T', 'I', 'O', 'N', 'A', 'L', + 'D', 'I', 'S', 'T', 'I', 'N', 'G', 'U', 'I', 'S', 'H', + 'D', 'O', 'A', 'C', 'H', 'A', 'S', 'H', 'M', 'E', 'E', + 'D', 'O', 'T', 'S', '-', '1', '2', '3', '4', '5', '6', + 'D', 'O', 'T', 'S', '-', '1', '2', '3', '4', '5', '7', + 'D', 'O', 'T', 'S', '-', '1', '2', '3', '4', '5', '8', + 'D', 'O', 'T', 'S', '-', '1', '2', '3', '4', '6', '7', + 'D', 'O', 'T', 'S', '-', '1', '2', '3', '4', '6', '8', + 'D', 'O', 'T', 'S', '-', '1', '2', '3', '4', '7', '8', + 'D', 'O', 'T', 'S', '-', '1', '2', '3', '5', '6', '7', + 'D', 'O', 'T', 'S', '-', '1', '2', '3', '5', '6', '8', + 'D', 'O', 'T', 'S', '-', '1', '2', '3', '5', '7', '8', + 'D', 'O', 'T', 'S', '-', '1', '2', '3', '6', '7', '8', + 'D', 'O', 'T', 'S', '-', '1', '2', '4', '5', '6', '7', + 'D', 'O', 'T', 'S', '-', '1', '2', '4', '5', '6', '8', + 'D', 'O', 'T', 'S', '-', '1', '2', '4', '5', '7', '8', + 'D', 'O', 'T', 'S', '-', '1', '2', '4', '6', '7', '8', + 'D', 'O', 'T', 'S', '-', '1', '2', '5', '6', '7', '8', + 'D', 'O', 'T', 'S', '-', '1', '3', '4', '5', '6', '7', + 'D', 'O', 'T', 'S', '-', '1', '3', '4', '5', '6', '8', + 'D', 'O', 'T', 'S', '-', '1', '3', '4', '5', '7', '8', + 'D', 'O', 'T', 'S', '-', '1', '3', '4', '6', '7', '8', + 'D', 'O', 'T', 'S', '-', '1', '3', '5', '6', '7', '8', + 'D', 'O', 'T', 'S', '-', '1', '4', '5', '6', '7', '8', + 'D', 'O', 'T', 'S', '-', '2', '3', '4', '5', '6', '7', + 'D', 'O', 'T', 'S', '-', '2', '3', '4', '5', '6', '8', + 'D', 'O', 'T', 'S', '-', '2', '3', '4', '5', '7', '8', + 'D', 'O', 'T', 'S', '-', '2', '3', '4', '6', '7', '8', + 'D', 'O', 'T', 'S', '-', '2', '3', '5', '6', '7', '8', + 'D', 'O', 'T', 'S', '-', '2', '4', '5', '6', '7', '8', + 'D', 'O', 'T', 'S', '-', '3', '4', '5', '6', '7', '8', + 'D', 'O', 'U', 'B', 'L', 'E', '-', 'L', 'I', 'N', 'E', + 'E', 'A', 'M', 'H', 'A', 'N', 'C', 'H', 'O', 'L', 'L', + 'E', 'K', 'F', 'O', 'N', 'I', 'T', 'I', 'K', 'O', 'N', + 'E', 'N', 'L', 'A', 'R', 'G', 'E', 'M', 'E', 'N', 'T', + 'E', 'Q', 'U', 'I', 'A', 'N', 'G', 'U', 'L', 'A', 'R', + 'E', 'X', 'C', 'L', 'A', 'M', 'A', 'T', 'I', 'O', 'N', + 'F', 'I', 'N', 'G', 'E', 'R', 'N', 'A', 'I', 'L', 'S', + 'F', 'O', 'U', 'R', '-', 'P', 'E', 'R', '-', 'E', 'M', + 'F', 'O', 'U', 'R', '-', 'S', 'T', 'R', 'I', 'N', 'G', + 'G', 'A', 'Y', 'A', 'N', 'U', 'K', 'I', 'T', 'T', 'A', + 'G', 'U', 'A', 'R', 'D', 'E', 'D', 'N', 'E', 'S', 'S', + 'H', 'A', 'U', 'P', 'T', 'S', 'T', 'I', 'M', 'M', 'E', + 'H', 'B', 'A', 'S', 'A', '-', 'E', 'S', 'A', 'S', 'A', + 'H', 'I', 'E', 'U', 'H', '-', 'M', 'I', 'E', 'U', 'M', + 'H', 'I', 'E', 'U', 'H', '-', 'N', 'I', 'E', 'U', 'N', + 'H', 'I', 'E', 'U', 'H', '-', 'P', 'I', 'E', 'U', 'P', + 'H', 'I', 'E', 'U', 'H', '-', 'R', 'I', 'E', 'U', 'L', + 'H', 'Y', 'P', 'H', 'E', 'N', 'A', 'T', 'I', 'O', 'N', + 'I', 'D', 'E', 'O', 'G', 'R', 'A', 'P', 'H', 'I', 'C', + 'I', 'E', 'U', 'N', 'G', '-', 'C', 'I', 'E', 'U', 'C', + 'I', 'E', 'U', 'N', 'G', '-', 'M', 'I', 'E', 'U', 'M', + 'I', 'E', 'U', 'N', 'G', '-', 'P', 'I', 'E', 'U', 'P', + 'I', 'M', 'P', 'E', 'R', 'F', 'E', 'C', 'T', 'U', 'M', + 'I', 'N', 'D', 'E', 'P', 'E', 'N', 'D', 'E', 'N', 'T', + 'I', 'N', 'F', 'O', 'R', 'M', 'A', 'T', 'I', 'O', 'N', + 'I', 'N', 'T', 'E', 'G', 'R', 'A', 'T', 'I', 'O', 'N', + 'I', 'N', 'T', 'E', 'R', 'C', 'A', 'L', 'A', 'T', 'E', + 'I', 'N', 'T', 'E', 'R', 'L', 'I', 'N', 'E', 'A', 'R', + 'I', 'N', 'T', 'E', 'R', 'L', 'O', 'C', 'K', 'E', 'D', + 'I', 'N', 'T', 'E', 'R', 'R', 'O', 'B', 'A', 'N', 'G', + 'J', 'I', 'H', 'V', 'A', 'M', 'U', 'L', 'I', 'Y', 'A', + 'K', 'I', 'R', 'O', 'M', 'E', 'E', 'T', 'O', 'R', 'U', + 'K', 'I', 'Y', 'E', 'O', 'K', '-', 'S', 'I', 'O', 'S', + 'L', 'A', 'K', 'K', 'H', 'A', 'N', 'G', 'Y', 'A', 'O', + 'L', 'E', 'F', 'T', '-', 'S', 'H', 'A', 'D', 'E', 'D', + 'M', 'A', 'H', 'A', 'A', 'P', 'R', 'A', 'A', 'N', 'A', + 'M', 'I', 'E', 'U', 'M', '-', 'H', 'I', 'E', 'U', 'H', + 'M', 'I', 'E', 'U', 'M', '-', 'P', 'I', 'E', 'U', 'P', + 'M', 'I', 'E', 'U', 'M', '-', 'R', 'I', 'E', 'U', 'L', + 'M', 'O', 'N', 'O', 'G', 'R', 'A', 'M', 'M', 'O', 'S', + 'M', 'U', 'L', 'T', 'I', 'O', 'C', 'U', 'L', 'A', 'R', + 'M', 'U', 'U', 'S', 'I', 'K', 'A', 'T', 'O', 'A', 'N', + 'N', 'A', 'A', 'K', 'S', 'I', 'K', 'Y', 'A', 'Y', 'A', + 'N', 'E', 'B', 'E', 'N', 'S', 'T', 'I', 'M', 'M', 'E', + 'N', 'I', 'E', 'U', 'N', '-', 'C', 'I', 'E', 'U', 'C', + 'N', 'I', 'E', 'U', 'N', '-', 'H', 'I', 'E', 'U', 'H', + 'N', 'I', 'E', 'U', 'N', '-', 'P', 'I', 'E', 'U', 'P', + 'O', 'B', 'S', 'T', 'R', 'U', 'C', 'T', 'I', 'O', 'N', + 'O', 'P', 'E', 'N', '-', 'H', 'E', 'A', 'D', 'E', 'D', + 'O', 'V', 'E', 'R', 'L', 'A', 'P', 'P', 'I', 'N', 'G', + 'P', 'A', 'L', 'A', 'T', 'A', 'L', 'I', 'Z', 'E', 'D', + 'P', 'A', 'R', 'A', 'G', 'R', 'A', 'P', 'H', 'O', 'S', + 'P', 'A', 'R', 'A', 'K', 'A', 'L', 'E', 'S', 'M', 'A', + 'P', 'A', 'R', 'A', 'K', 'L', 'I', 'T', 'I', 'K', 'I', + 'P', 'A', 'R', 'E', 'N', 'T', 'H', 'E', 'S', 'I', 'S', + 'P', 'A', 'R', 'T', 'N', 'E', 'R', 'S', 'H', 'I', 'P', + 'P', 'E', 'N', 'E', 'T', 'R', 'A', 'T', 'I', 'O', 'N', + 'P', 'E', 'R', 'I', 'S', 'P', 'O', 'M', 'E', 'N', 'I', + 'P', 'E', 'R', 'S', 'P', 'E', 'C', 'T', 'I', 'V', 'E', + 'P', 'I', 'E', 'U', 'P', '-', 'C', 'I', 'E', 'U', 'C', + 'P', 'I', 'E', 'U', 'P', '-', 'H', 'I', 'E', 'U', 'H', + 'P', 'I', 'E', 'U', 'P', '-', 'N', 'I', 'E', 'U', 'N', + 'P', 'I', 'E', 'U', 'P', '-', 'R', 'I', 'E', 'U', 'L', + 'P', 'U', 'N', 'C', 'T', 'U', 'A', 'T', 'I', 'O', 'N', + 'R', 'A', 'D', 'I', 'O', 'A', 'C', 'T', 'I', 'V', 'E', + 'R', 'A', 'H', 'M', 'A', 'T', 'U', 'L', 'L', 'A', 'H', + 'R', 'E', 'C', 'T', 'A', 'N', 'G', 'U', 'L', 'A', 'R', + 'R', 'E', 'C', 'T', 'I', 'L', 'I', 'N', 'E', 'A', 'R', + 'R', 'E', 'P', 'L', 'A', 'C', 'E', 'M', 'E', 'N', 'T', + 'R', 'I', 'E', 'U', 'L', '-', 'H', 'I', 'E', 'U', 'H', + 'R', 'I', 'E', 'U', 'L', '-', 'M', 'I', 'E', 'U', 'M', + 'R', 'I', 'E', 'U', 'L', '-', 'N', 'I', 'E', 'U', 'N', + 'R', 'I', 'E', 'U', 'L', '-', 'P', 'I', 'E', 'U', 'P', + 'R', 'I', 'N', 'F', 'O', 'R', 'Z', 'A', 'N', 'D', 'O', + 'S', 'A', 'C', 'R', 'I', 'F', 'I', 'C', 'I', 'A', 'L', + 'S', 'A', 'G', 'I', 'T', 'T', 'A', 'R', 'I', 'U', 'S', + 'S', 'A', 'L', 'L', 'A', 'L', 'L', 'A', 'H', 'O', 'U', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '0', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '1', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '2', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '3', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '4', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '5', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '6', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '7', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '8', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '9', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '0', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '1', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '2', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '3', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '4', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '5', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '6', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '7', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '8', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '9', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '3', '0', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '3', '1', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '3', '2', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '3', '3', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '3', '4', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '3', '5', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '3', '6', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '3', '7', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '3', '8', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '3', '9', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '4', '0', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '4', '1', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '4', '2', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '4', '3', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '4', '4', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '4', '5', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '4', '6', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '4', '7', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '4', '8', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '4', '9', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '5', '0', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '5', '1', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '5', '2', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '5', '3', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '5', '4', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '5', '5', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '5', '6', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '5', '7', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '5', '8', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '5', '9', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '6', '0', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '6', '1', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '6', '2', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '6', '3', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '6', '4', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '6', '5', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '6', '6', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '6', '7', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '6', '8', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '6', '9', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '7', '0', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '7', '1', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '7', '2', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '7', '3', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '7', '4', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '7', '5', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '7', '6', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '7', '7', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '7', '8', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '7', '9', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '8', '0', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '8', '1', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '8', '2', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '8', '3', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '8', '4', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '8', '5', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '8', '6', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '8', '7', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '8', '8', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '8', '9', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '9', '0', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '9', '1', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '9', '2', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '9', '3', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '9', '4', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '9', '5', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '9', '6', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '9', '7', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '9', '8', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '9', '9', + 'S', 'E', 'M', 'I', '-', 'V', 'O', 'I', 'C', 'E', 'D', + 'S', 'E', 'M', 'I', 'S', 'E', 'X', 'T', 'I', 'L', 'E', + 'S', 'I', 'N', 'G', 'L', 'E', '-', 'L', 'I', 'N', 'E', + 'S', 'I', 'O', 'S', '-', 'K', 'I', 'Y', 'E', 'O', 'K', + 'S', 'I', 'O', 'S', '-', 'T', 'I', 'K', 'E', 'U', 'T', + 'S', 'S', 'A', 'N', 'G', 'K', 'I', 'Y', 'E', 'O', 'K', + 'S', 'S', 'A', 'N', 'G', 'T', 'I', 'K', 'E', 'U', 'T', + 'S', 'U', 'P', 'E', 'R', 'S', 'C', 'R', 'I', 'P', 'T', + 'S', 'U', 'P', 'R', 'A', 'L', 'I', 'N', 'E', 'A', 'R', + 'S', 'Y', 'N', 'C', 'H', 'R', 'O', 'N', 'O', 'U', 'S', + 'T', 'E', 'T', 'R', 'A', 'F', 'O', 'N', 'I', 'A', 'S', + 'T', 'H', 'A', 'N', 'T', 'H', 'A', 'K', 'H', 'A', 'T', + 'T', 'H', 'E', 'M', 'A', 'T', 'I', 'S', 'M', 'O', 'S', + 'T', 'O', 'A', 'N', 'D', 'A', 'K', 'H', 'I', 'A', 'T', + 'T', 'O', 'P', '-', 'L', 'I', 'G', 'H', 'T', 'E', 'D', + 'T', 'R', 'A', 'N', 'S', 'V', 'E', 'R', 'S', 'A', 'L', + 'T', 'R', 'I', 'T', 'I', 'M', 'O', 'R', 'I', 'O', 'N', + 'T', 'W', 'E', 'N', 'T', 'Y', '-', 'F', 'I', 'V', 'E', + 'T', 'W', 'E', 'N', 'T', 'Y', '-', 'F', 'O', 'U', 'R', + 'T', 'W', 'E', 'N', 'T', 'Y', '-', 'N', 'I', 'N', 'E', + 'U', 'N', 'A', 'S', 'P', 'I', 'R', 'A', 'T', 'E', 'D', + 'U', 'P', '-', 'P', 'O', 'I', 'N', 'T', 'I', 'N', 'G', + 'U', 'P', 'A', 'D', 'H', 'M', 'A', 'N', 'I', 'Y', 'A', + 'W', 'I', 'D', 'E', '-', 'H', 'E', 'A', 'D', 'E', 'D', + 'Y', 'E', 'O', 'R', 'I', 'N', 'H', 'I', 'E', 'U', 'H', + 'A', 'B', 'B', 'R', 'E', 'V', 'I', 'A', 'T', 'I', 'O', 'N', + 'A', 'C', 'C', 'U', 'M', 'U', 'L', 'A', 'T', 'I', 'O', 'N', + 'A', 'C', 'U', 'T', 'E', '-', 'M', 'A', 'C', 'R', 'O', 'N', + 'A', 'K', 'T', 'I', 'E', 'S', 'E', 'L', 'S', 'K', 'A', 'B', + 'A', 'M', 'A', 'L', 'G', 'A', 'M', 'A', 'T', 'I', 'O', 'N', + 'A', 'N', 'A', 'T', 'R', 'I', 'C', 'H', 'I', 'S', 'M', 'A', + 'A', 'R', 'A', 'B', 'I', 'C', '-', 'I', 'N', 'D', 'I', 'C', + 'A', 'S', 'T', 'R', 'O', 'L', 'O', 'G', 'I', 'C', 'A', 'L', + 'A', 'U', 'G', 'M', 'E', 'N', 'T', 'A', 'T', 'I', 'O', 'N', + 'A', 'U', 'R', 'A', 'M', 'A', 'Z', 'D', 'A', 'A', '-', '2', + 'A', 'U', 'R', 'A', 'M', 'A', 'Z', 'D', 'A', 'A', 'H', 'A', + 'B', 'L', 'A', 'C', 'K', '-', 'L', 'E', 'T', 'T', 'E', 'R', + 'B', 'R', 'E', 'A', 'K', 'T', 'H', 'R', 'O', 'U', 'G', 'H', + 'B', 'R', 'E', 'V', 'E', '-', 'M', 'A', 'C', 'R', 'O', 'N', + 'C', '-', 'S', 'I', 'M', 'P', 'L', 'I', 'F', 'I', 'E', 'D', + 'C', 'A', 'N', 'C', 'E', 'L', 'L', 'A', 'T', 'I', 'O', 'N', + 'C', 'A', 'N', 'T', 'I', 'L', 'L', 'A', 'T', 'I', 'O', 'N', + 'C', 'H', 'I', 'T', 'U', 'E', 'U', 'M', 'S', 'I', 'O', 'S', + 'C', 'R', 'O', 'S', 'S', 'E', 'D', '-', 'T', 'A', 'I', 'L', + 'C', 'Y', 'L', 'I', 'N', 'D', 'R', 'I', 'C', 'I', 'T', 'Y', + 'D', 'E', 'C', 'I', 'S', 'I', 'V', 'E', 'N', 'E', 'S', 'S', + 'D', 'I', 'F', 'F', 'E', 'R', 'E', 'N', 'T', 'I', 'A', 'L', + 'D', 'I', 'F', 'F', 'I', 'C', 'U', 'L', 'T', 'I', 'E', 'S', + 'D', 'I', 'M', 'I', 'N', 'I', 'S', 'H', 'M', 'E', 'N', 'T', + 'D', 'I', 'M', 'I', 'N', 'U', 'T', 'I', 'O', 'N', '-', '1', + 'D', 'I', 'M', 'I', 'N', 'U', 'T', 'I', 'O', 'N', '-', '2', + 'D', 'I', 'M', 'I', 'N', 'U', 'T', 'I', 'O', 'N', '-', '3', + 'D', 'O', 'T', 'S', '-', '1', '2', '3', '4', '5', '6', '7', + 'D', 'O', 'T', 'S', '-', '1', '2', '3', '4', '5', '6', '8', + 'D', 'O', 'T', 'S', '-', '1', '2', '3', '4', '5', '7', '8', + 'D', 'O', 'T', 'S', '-', '1', '2', '3', '4', '6', '7', '8', + 'D', 'O', 'T', 'S', '-', '1', '2', '3', '5', '6', '7', '8', + 'D', 'O', 'T', 'S', '-', '1', '2', '4', '5', '6', '7', '8', + 'D', 'O', 'T', 'S', '-', '1', '3', '4', '5', '6', '7', '8', + 'D', 'O', 'T', 'S', '-', '2', '3', '4', '5', '6', '7', '8', + 'D', 'O', 'U', 'B', 'L', 'E', '-', 'E', 'N', 'D', 'E', 'D', + 'E', 'R', 'R', 'O', 'R', '-', 'B', 'A', 'R', 'R', 'E', 'D', + 'F', 'L', 'E', 'U', 'R', '-', 'D', 'E', '-', 'L', 'I', 'S', + 'F', 'R', 'O', 'N', 'T', '-', 'T', 'I', 'L', 'T', 'E', 'D', + 'G', 'A', 'E', 'T', 'T', 'A', '-', 'P', 'I', 'L', 'L', 'A', + 'G', 'R', 'A', 'V', 'E', '-', 'M', 'A', 'C', 'R', 'O', 'N', + 'G', 'R', 'E', 'A', 'T', 'E', 'R', '-', 'T', 'H', 'A', 'N', + 'G', 'R', 'O', 'N', 'T', 'H', 'I', 'S', 'M', 'A', 'T', 'A', + 'H', 'O', 'R', 'I', 'Z', 'O', 'N', 'T', 'A', 'L', 'L', 'Y', + 'H', 'Y', 'P', 'H', 'E', 'N', '-', 'M', 'I', 'N', 'U', 'S', + 'H', 'Y', 'P', 'O', 'D', 'I', 'A', 'S', 'T', 'O', 'L', 'E', + 'I', 'C', 'E', 'L', 'A', 'N', 'D', 'I', 'C', '-', 'Y', 'R', + 'I', 'E', 'U', 'N', 'G', '-', 'K', 'I', 'Y', 'E', 'O', 'K', + 'I', 'E', 'U', 'N', 'G', '-', 'T', 'I', 'K', 'E', 'U', 'T', + 'I', 'N', 'S', 'T', 'R', 'U', 'M', 'E', 'N', 'T', 'A', 'L', + 'I', 'N', 'T', 'E', 'R', 'S', 'E', 'C', 'T', 'I', 'N', 'G', + 'I', 'N', 'T', 'E', 'R', 'S', 'E', 'C', 'T', 'I', 'O', 'N', + 'J', '-', 'S', 'I', 'M', 'P', 'L', 'I', 'F', 'I', 'E', 'D', + 'K', 'I', 'Y', 'E', 'O', 'K', '-', 'R', 'I', 'E', 'U', 'L', + 'M', 'A', 'C', 'R', 'O', 'N', '-', 'A', 'C', 'U', 'T', 'E', + 'M', 'A', 'C', 'R', 'O', 'N', '-', 'B', 'R', 'E', 'V', 'E', + 'M', 'A', 'C', 'R', 'O', 'N', '-', 'G', 'R', 'A', 'V', 'E', + 'M', 'A', 'T', 'H', 'E', 'M', 'A', 'T', 'I', 'C', 'A', 'L', + 'M', 'I', 'D', 'D', 'L', 'E', '-', 'W', 'E', 'L', 'S', 'H', + 'M', 'I', 'E', 'U', 'M', '-', 'K', 'I', 'Y', 'E', 'O', 'K', + 'N', 'A', 'S', 'A', 'L', 'I', 'Z', 'A', 'T', 'I', 'O', 'N', + 'N', 'I', 'E', 'U', 'N', '-', 'K', 'I', 'Y', 'E', 'O', 'K', + 'N', 'I', 'E', 'U', 'N', '-', 'T', 'I', 'K', 'E', 'U', 'T', + 'N', 'O', 'N', '-', 'B', 'R', 'E', 'A', 'K', 'I', 'N', 'G', + 'P', 'I', 'E', 'U', 'P', '-', 'K', 'I', 'Y', 'E', 'O', 'K', + 'P', 'I', 'E', 'U', 'P', '-', 'T', 'I', 'K', 'E', 'U', 'T', + 'P', 'O', 'S', 'T', 'P', 'O', 'S', 'I', 'T', 'I', 'O', 'N', + 'P', 'R', 'E', 'S', 'C', 'R', 'I', 'P', 'T', 'I', 'O', 'N', + 'P', 'R', 'E', 'S', 'E', 'N', 'T', 'A', 'T', 'I', 'O', 'N', + 'P', 'R', 'O', 'P', 'O', 'R', 'T', 'I', 'O', 'N', 'A', 'L', + 'Q', 'U', 'I', 'N', 'D', 'I', 'C', 'E', 'S', 'I', 'M', 'A', + 'R', 'I', 'E', 'U', 'L', '-', 'K', 'I', 'Y', 'E', 'O', 'K', + 'R', 'I', 'E', 'U', 'L', '-', 'T', 'I', 'K', 'E', 'U', 'T', + 'R', 'I', 'G', 'H', 'T', '-', 'S', 'H', 'A', 'D', 'E', 'D', + 'R', 'O', 'U', 'N', 'D', '-', 'T', 'I', 'P', 'P', 'E', 'D', + 'R', 'U', 'L', 'E', '-', 'D', 'E', 'L', 'A', 'Y', 'E', 'D', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '0', '0', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '0', '1', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '0', '2', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '0', '3', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '0', '4', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '0', '5', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '0', '6', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '0', '7', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '0', '8', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '0', '9', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '1', '0', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '1', '1', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '1', '2', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '1', '3', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '1', '4', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '1', '5', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '1', '6', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '1', '7', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '1', '8', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '1', '9', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '2', '0', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '2', '1', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '2', '2', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '2', '3', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '2', '4', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '2', '5', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '2', '6', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '2', '7', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '2', '8', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '2', '9', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '3', '0', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '3', '1', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '3', '2', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '3', '3', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '3', '4', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '3', '5', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '3', '6', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '3', '7', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '3', '8', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '3', '9', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '4', '0', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '4', '1', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '4', '2', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '4', '3', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '4', '4', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '4', '5', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '4', '6', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '4', '7', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '4', '8', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '4', '9', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '5', '0', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '5', '1', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '5', '2', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '5', '3', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '5', '4', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '5', '5', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '5', '6', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '5', '7', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '5', '8', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '5', '9', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '6', '0', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '6', '1', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '6', '2', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '6', '3', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '6', '4', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '6', '5', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '6', '6', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '6', '7', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '6', '8', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '6', '9', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '7', '0', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '7', '1', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '7', '2', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '7', '3', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '7', '4', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '7', '5', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '7', '6', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '7', '7', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '7', '8', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '7', '9', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '8', '0', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '8', '1', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '8', '2', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '8', '3', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '8', '4', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '8', '5', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '8', '6', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '8', '7', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '8', '8', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '8', '9', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '9', '0', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '9', '1', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '9', '2', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '9', '3', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '9', '4', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '9', '5', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '9', '6', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '9', '7', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '9', '8', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '1', '9', '9', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '0', '0', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '0', '1', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '0', '2', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '0', '3', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '0', '4', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '0', '5', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '0', '6', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '0', '7', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '0', '8', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '0', '9', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '1', '0', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '1', '1', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '1', '2', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '1', '3', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '1', '4', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '1', '5', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '1', '6', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '1', '7', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '1', '8', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '1', '9', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '2', '0', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '2', '1', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '2', '2', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '2', '3', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '2', '4', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '2', '5', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '2', '6', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '2', '7', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '2', '8', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '2', '9', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '3', '0', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '3', '1', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '3', '2', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '3', '3', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '3', '4', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '3', '5', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '3', '6', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '3', '7', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '3', '8', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '3', '9', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '4', '0', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '4', '1', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '4', '2', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '4', '3', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '4', '4', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '4', '5', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '4', '6', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '4', '7', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '4', '8', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '4', '9', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '5', '0', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '5', '1', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '5', '2', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '5', '3', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '5', '4', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '5', '5', + 'S', 'E', 'L', 'E', 'C', 'T', 'O', 'R', '-', '2', '5', '6', + 'S', 'E', 'M', 'I', 'C', 'I', 'R', 'C', 'U', 'L', 'A', 'R', + 'S', 'I', 'O', 'S', '-', 'C', 'H', 'I', 'E', 'U', 'C', 'H', + 'S', 'I', 'O', 'S', '-', 'K', 'H', 'I', 'E', 'U', 'K', 'H', + 'S', 'I', 'O', 'S', '-', 'P', 'H', 'I', 'E', 'U', 'P', 'H', + 'S', 'I', 'O', 'S', '-', 'T', 'H', 'I', 'E', 'U', 'T', 'H', + 'S', 'I', 'X', 'T', 'Y', '-', 'F', 'O', 'U', 'R', 'T', 'H', + 'S', 'O', 'U', 'T', 'H', '-', 'S', 'L', 'A', 'V', 'E', 'Y', + 'S', 'P', 'R', 'E', 'C', 'H', 'G', 'E', 'S', 'A', 'N', 'G', + 'S', 'T', 'R', 'A', 'G', 'G', 'I', 'S', 'M', 'A', 'T', 'A', + 'S', 'T', 'R', 'A', 'I', 'G', 'H', 'T', 'N', 'E', 'S', 'S', + 'S', 'U', 'B', 'S', 'T', 'I', 'T', 'U', 'T', 'I', 'O', 'N', + 'S', 'U', 'P', 'E', 'R', 'I', 'M', 'P', 'O', 'S', 'E', 'D', + 'T', 'H', 'R', 'E', 'E', '-', 'P', 'E', 'R', '-', 'E', 'M', + 'T', 'H', 'U', 'N', 'D', 'E', 'R', 'S', 'T', 'O', 'R', 'M', + 'T', 'I', 'K', 'E', 'U', 'T', '-', 'R', 'I', 'E', 'U', 'L', + 'T', 'R', 'A', 'N', 'S', 'M', 'I', 'S', 'S', 'I', 'O', 'N', + 'T', 'W', 'E', 'N', 'T', 'Y', '-', 'E', 'I', 'G', 'H', 'T', + 'T', 'W', 'E', 'N', 'T', 'Y', '-', 'S', 'E', 'V', 'E', 'N', + 'T', 'W', 'E', 'N', 'T', 'Y', '-', 'T', 'H', 'R', 'E', 'E', + 'W', 'E', 'D', 'G', 'E', '-', 'T', 'A', 'I', 'L', 'E', 'D', + 'X', 'S', 'H', 'A', 'A', 'Y', 'A', 'T', 'H', 'I', 'Y', 'A', + 'Y', 'O', 'U', 'T', 'H', 'F', 'U', 'L', 'N', 'E', 'S', 'S', + 'A', 'N', 'T', 'I', 'C', 'L', 'O', 'C', 'K', 'W', 'I', 'S', 'E', + 'A', 'P', 'P', 'R', 'O', 'X', 'I', 'M', 'A', 'T', 'E', 'L', 'Y', + 'A', 'R', 'G', 'O', 'S', 'Y', 'N', 'T', 'H', 'E', 'T', 'O', 'N', + 'A', 'V', 'A', 'K', 'R', 'A', 'H', 'A', 'S', 'A', 'N', 'Y', 'A', + 'C', 'H', 'I', 'E', 'U', 'C', 'H', '-', 'H', 'I', 'E', 'U', 'H', + 'C', 'H', 'I', 'T', 'U', 'E', 'U', 'M', 'C', 'I', 'E', 'U', 'C', + 'C', 'H', 'R', 'Y', 'S', 'A', 'N', 'T', 'H', 'E', 'M', 'U', 'M', + 'C', 'O', 'M', 'P', 'A', 'T', 'I', 'B', 'I', 'L', 'I', 'T', 'Y', + 'C', 'O', 'N', 'C', 'A', 'V', 'E', '-', 'S', 'I', 'D', 'E', 'D', + 'C', 'O', 'N', 'T', 'E', 'M', 'P', 'L', 'A', 'T', 'I', 'O', 'N', + 'C', 'R', 'Y', 'P', 'T', 'O', 'G', 'R', 'A', 'M', 'M', 'I', 'C', + 'D', 'E', 'F', 'E', 'C', 'T', 'I', 'V', 'E', 'N', 'E', 'S', 'S', + 'D', 'I', 'S', 'C', 'O', 'N', 'T', 'I', 'N', 'U', 'O', 'U', 'S', + 'D', 'O', 'T', 'S', '-', '1', '2', '3', '4', '5', '6', '7', '8', + 'D', 'O', 'U', 'B', 'L', 'E', '-', 'S', 'T', 'R', 'U', 'C', 'K', + 'D', 'O', 'W', 'N', '-', 'P', 'O', 'I', 'N', 'T', 'I', 'N', 'G', + 'D', 'R', 'O', 'P', '-', 'S', 'H', 'A', 'D', 'O', 'W', 'E', 'D', + 'E', 'G', 'Y', 'P', 'T', 'O', 'L', 'O', 'G', 'I', 'C', 'A', 'L', + 'E', 'M', 'B', 'E', 'L', 'L', 'I', 'S', 'H', 'M', 'E', 'N', 'T', + 'E', 'U', 'R', 'O', '-', 'C', 'U', 'R', 'R', 'E', 'N', 'C', 'Y', + 'G', 'E', 'O', 'M', 'E', 'T', 'R', 'I', 'C', 'A', 'L', 'L', 'Y', + 'I', 'E', 'U', 'N', 'G', '-', 'C', 'H', 'I', 'E', 'U', 'C', 'H', + 'I', 'E', 'U', 'N', 'G', '-', 'K', 'H', 'I', 'E', 'U', 'K', 'H', + 'I', 'E', 'U', 'N', 'G', '-', 'P', 'A', 'N', 'S', 'I', 'O', 'S', + 'I', 'E', 'U', 'N', 'G', '-', 'P', 'H', 'I', 'E', 'U', 'P', 'H', + 'I', 'E', 'U', 'N', 'G', '-', 'T', 'H', 'I', 'E', 'U', 'T', 'H', + 'I', 'N', 'T', 'E', 'R', 'P', 'O', 'L', 'A', 'T', 'I', 'O', 'N', + 'I', 'N', 'T', 'E', 'R', 'S', 'Y', 'L', 'L', 'A', 'B', 'I', 'C', + 'J', 'U', 'D', 'E', 'O', '-', 'S', 'P', 'A', 'N', 'I', 'S', 'H', + 'K', 'A', 'P', 'Y', 'E', 'O', 'U', 'N', 'M', 'I', 'E', 'U', 'M', + 'K', 'A', 'P', 'Y', 'E', 'O', 'U', 'N', 'P', 'I', 'E', 'U', 'P', + 'K', 'A', 'P', 'Y', 'E', 'O', 'U', 'N', 'R', 'I', 'E', 'U', 'L', + 'L', 'A', 'B', 'I', 'A', 'L', 'I', 'Z', 'A', 'T', 'I', 'O', 'N', + 'L', 'E', 'F', 'T', '-', 'P', 'O', 'I', 'N', 'T', 'I', 'N', 'G', + 'L', 'E', 'F', 'T', '-', 'T', 'O', '-', 'R', 'I', 'G', 'H', 'T', + 'M', 'I', 'E', 'U', 'M', '-', 'C', 'H', 'I', 'E', 'U', 'C', 'H', + 'M', 'I', 'E', 'U', 'M', '-', 'P', 'A', 'N', 'S', 'I', 'O', 'S', + 'M', 'I', 'N', 'U', 'S', '-', 'O', 'R', '-', 'P', 'L', 'U', 'S', + 'M', 'O', 'R', 'P', 'H', 'O', 'L', 'O', 'G', 'I', 'C', 'A', 'L', + 'N', 'I', 'E', 'U', 'N', '-', 'P', 'A', 'N', 'S', 'I', 'O', 'S', + 'N', 'I', 'E', 'U', 'N', '-', 'T', 'H', 'I', 'E', 'U', 'T', 'H', + 'O', 'P', 'E', 'N', '-', 'O', 'U', 'T', 'L', 'I', 'N', 'E', 'D', + 'P', 'A', 'R', 'A', 'L', 'L', 'E', 'L', 'O', 'G', 'R', 'A', 'M', + 'P', 'A', 'R', 'E', 'N', 'T', 'H', 'E', 'S', 'I', 'Z', 'E', 'D', + 'P', 'A', 'R', 'E', 'S', 'T', 'I', 'G', 'M', 'E', 'N', 'O', 'N', + 'P', 'E', 'R', 'P', 'E', 'N', 'D', 'I', 'C', 'U', 'L', 'A', 'R', + 'P', 'H', 'I', 'E', 'U', 'P', 'H', '-', 'P', 'I', 'E', 'U', 'P', + 'P', 'I', 'E', 'U', 'P', '-', 'C', 'H', 'I', 'E', 'U', 'C', 'H', + 'P', 'I', 'E', 'U', 'P', '-', 'P', 'H', 'I', 'E', 'U', 'P', 'H', + 'P', 'I', 'E', 'U', 'P', '-', 'T', 'H', 'I', 'E', 'U', 'T', 'H', + 'P', 'R', 'E', 'P', 'O', 'N', 'D', 'E', 'R', 'A', 'N', 'C', 'E', + 'R', 'I', 'E', 'U', 'L', '-', 'K', 'H', 'I', 'E', 'U', 'K', 'H', + 'R', 'I', 'E', 'U', 'L', '-', 'P', 'A', 'N', 'S', 'I', 'O', 'S', + 'R', 'I', 'E', 'U', 'L', '-', 'P', 'H', 'I', 'E', 'U', 'P', 'H', + 'R', 'I', 'E', 'U', 'L', '-', 'T', 'H', 'I', 'E', 'U', 'T', 'H', + 'R', 'I', 'G', 'H', 'T', '-', 'T', 'O', '-', 'L', 'E', 'F', 'T', + 'S', 'H', 'O', 'R', 'T', '-', 'T', 'W', 'I', 'G', '-', 'A', 'R', + 'S', 'H', 'O', 'R', 'T', '-', 'T', 'W', 'I', 'G', '-', 'Y', 'R', + 'S', 'T', 'A', 'C', 'C', 'A', 'T', 'I', 'S', 'S', 'I', 'M', 'O', + 'S', 'T', 'R', 'I', 'K', 'E', 'T', 'H', 'R', 'O', 'U', 'G', 'H', + 'T', 'E', 'T', 'A', 'R', 'T', 'I', 'M', 'O', 'R', 'I', 'O', 'N', + 'T', 'H', 'E', 'R', 'M', 'O', 'D', 'Y', 'N', 'A', 'M', 'I', 'C', + 'T', 'H', 'I', 'R', 'T', 'Y', '-', 'S', 'E', 'C', 'O', 'N', 'D', + 'T', 'I', 'K', 'E', 'U', 'T', '-', 'K', 'I', 'Y', 'E', 'O', 'K', + 'T', 'R', 'A', 'N', 'S', 'P', 'O', 'S', 'I', 'T', 'I', 'O', 'N', + 'T', 'W', 'E', 'N', 'T', 'Y', '-', 'E', 'I', 'G', 'H', 'T', 'H', + 'V', 'O', 'W', 'E', 'L', '-', 'C', 'A', 'R', 'R', 'I', 'E', 'R', + 'Y', 'E', 'S', 'I', 'E', 'U', 'N', 'G', '-', 'S', 'I', 'O', 'S', + 'Y', 'P', 'O', 'G', 'E', 'G', 'R', 'A', 'M', 'M', 'E', 'N', 'I', + 'Y', 'U', 'U', 'K', 'A', 'L', 'E', 'A', 'P', 'I', 'N', 'T', 'U', + 'A', 'F', 'O', 'R', 'E', 'M', 'E', 'N', 'T', 'I', 'O', 'N', 'E', 'D', + 'A', 'R', 'O', 'U', 'N', 'D', '-', 'P', 'R', 'O', 'F', 'I', 'L', 'E', + 'A', 'S', 'Y', 'M', 'P', 'T', 'O', 'T', 'I', 'C', 'A', 'L', 'L', 'Y', + 'B', 'A', 'L', 'L', 'O', 'O', 'N', '-', 'S', 'P', 'O', 'K', 'E', 'D', + 'B', 'O', 'T', 'T', 'O', 'M', '-', 'L', 'I', 'G', 'H', 'T', 'E', 'D', + 'C', 'O', 'N', 'G', 'R', 'A', 'T', 'U', 'L', 'A', 'T', 'I', 'O', 'N', + 'G', 'O', 'R', 'G', 'O', 'S', 'Y', 'N', 'T', 'H', 'E', 'T', 'O', 'N', + 'I', 'D', 'E', 'N', 'T', 'I', 'F', 'I', 'C', 'A', 'T', 'I', 'O', 'N', + 'L', 'O', 'N', 'G', '-', 'B', 'R', 'A', 'N', 'C', 'H', '-', 'A', 'R', + 'L', 'O', 'N', 'G', '-', 'B', 'R', 'A', 'N', 'C', 'H', '-', 'Y', 'R', + 'M', 'U', 'L', 'T', 'I', 'P', 'L', 'I', 'C', 'A', 'T', 'I', 'O', 'N', + 'P', 'A', 'L', 'A', 'T', 'A', 'L', 'I', 'Z', 'A', 'T', 'I', 'O', 'N', + 'P', 'R', 'O', 'S', 'G', 'E', 'G', 'R', 'A', 'M', 'M', 'E', 'N', 'I', + 'R', 'I', 'G', 'H', 'T', '-', 'P', 'O', 'I', 'N', 'T', 'I', 'N', 'G', + 'R', 'I', 'G', 'H', 'T', '-', 'S', 'H', 'A', 'D', 'O', 'W', 'E', 'D', + 'S', 'E', 'S', 'Q', 'U', 'I', 'Q', 'U', 'A', 'D', 'R', 'A', 'T', 'E', + 'S', 'H', 'O', 'R', 'T', '-', 'T', 'W', 'I', 'G', '-', 'O', 'S', 'S', + 'S', 'H', 'O', 'R', 'T', '-', 'T', 'W', 'I', 'G', '-', 'S', 'O', 'L', + 'S', 'H', 'O', 'R', 'T', '-', 'T', 'W', 'I', 'G', '-', 'T', 'Y', 'R', + 'S', 'I', 'O', 'S', '-', 'S', 'S', 'A', 'N', 'G', 'S', 'I', 'O', 'S', + 'T', 'R', 'I', 'A', 'N', 'G', 'L', 'E', '-', 'R', 'O', 'U', 'N', 'D', + 'T', 'R', 'O', 'M', 'I', 'K', 'O', 'L', 'Y', 'G', 'I', 'S', 'M', 'A', + 'T', 'R', 'O', 'M', 'I', 'K', 'O', 'S', 'Y', 'N', 'A', 'G', 'M', 'A', + 'V', 'E', 'R', 'T', 'I', 'C', 'A', 'L', '-', '0', '0', '-', '0', '0', + 'V', 'E', 'R', 'T', 'I', 'C', 'A', 'L', '-', '0', '0', '-', '0', '1', + 'V', 'E', 'R', 'T', 'I', 'C', 'A', 'L', '-', '0', '0', '-', '0', '2', + 'V', 'E', 'R', 'T', 'I', 'C', 'A', 'L', '-', '0', '0', '-', '0', '3', + 'V', 'E', 'R', 'T', 'I', 'C', 'A', 'L', '-', '0', '0', '-', '0', '4', + 'V', 'E', 'R', 'T', 'I', 'C', 'A', 'L', '-', '0', '0', '-', '0', '5', + 'V', 'E', 'R', 'T', 'I', 'C', 'A', 'L', '-', '0', '0', '-', '0', '6', + 'V', 'E', 'R', 'T', 'I', 'C', 'A', 'L', '-', '0', '1', '-', '0', '0', + 'V', 'E', 'R', 'T', 'I', 'C', 'A', 'L', '-', '0', '1', '-', '0', '1', + 'V', 'E', 'R', 'T', 'I', 'C', 'A', 'L', '-', '0', '1', '-', '0', '2', + 'V', 'E', 'R', 'T', 'I', 'C', 'A', 'L', '-', '0', '1', '-', '0', '3', + 'V', 'E', 'R', 'T', 'I', 'C', 'A', 'L', '-', '0', '1', '-', '0', '4', + 'V', 'E', 'R', 'T', 'I', 'C', 'A', 'L', '-', '0', '1', '-', '0', '5', + 'V', 'E', 'R', 'T', 'I', 'C', 'A', 'L', '-', '0', '1', '-', '0', '6', + 'V', 'E', 'R', 'T', 'I', 'C', 'A', 'L', '-', '0', '2', '-', '0', '0', + 'V', 'E', 'R', 'T', 'I', 'C', 'A', 'L', '-', '0', '2', '-', '0', '1', + 'V', 'E', 'R', 'T', 'I', 'C', 'A', 'L', '-', '0', '2', '-', '0', '2', + 'V', 'E', 'R', 'T', 'I', 'C', 'A', 'L', '-', '0', '2', '-', '0', '3', + 'V', 'E', 'R', 'T', 'I', 'C', 'A', 'L', '-', '0', '2', '-', '0', '4', + 'V', 'E', 'R', 'T', 'I', 'C', 'A', 'L', '-', '0', '2', '-', '0', '5', + 'V', 'E', 'R', 'T', 'I', 'C', 'A', 'L', '-', '0', '2', '-', '0', '6', + 'V', 'E', 'R', 'T', 'I', 'C', 'A', 'L', '-', '0', '3', '-', '0', '0', + 'V', 'E', 'R', 'T', 'I', 'C', 'A', 'L', '-', '0', '3', '-', '0', '1', + 'V', 'E', 'R', 'T', 'I', 'C', 'A', 'L', '-', '0', '3', '-', '0', '2', + 'V', 'E', 'R', 'T', 'I', 'C', 'A', 'L', '-', '0', '3', '-', '0', '3', + 'V', 'E', 'R', 'T', 'I', 'C', 'A', 'L', '-', '0', '3', '-', '0', '4', + 'V', 'E', 'R', 'T', 'I', 'C', 'A', 'L', '-', '0', '3', '-', '0', '5', + 'V', 'E', 'R', 'T', 'I', 'C', 'A', 'L', '-', '0', '3', '-', '0', '6', + 'V', 'E', 'R', 'T', 'I', 'C', 'A', 'L', '-', '0', '4', '-', '0', '0', + 'V', 'E', 'R', 'T', 'I', 'C', 'A', 'L', '-', '0', '4', '-', '0', '1', + 'V', 'E', 'R', 'T', 'I', 'C', 'A', 'L', '-', '0', '4', '-', '0', '2', + 'V', 'E', 'R', 'T', 'I', 'C', 'A', 'L', '-', '0', '4', '-', '0', '3', + 'V', 'E', 'R', 'T', 'I', 'C', 'A', 'L', '-', '0', '4', '-', '0', '4', + 'V', 'E', 'R', 'T', 'I', 'C', 'A', 'L', '-', '0', '4', '-', '0', '5', + 'V', 'E', 'R', 'T', 'I', 'C', 'A', 'L', '-', '0', '4', '-', '0', '6', + 'V', 'E', 'R', 'T', 'I', 'C', 'A', 'L', '-', '0', '5', '-', '0', '0', + 'V', 'E', 'R', 'T', 'I', 'C', 'A', 'L', '-', '0', '5', '-', '0', '1', + 'V', 'E', 'R', 'T', 'I', 'C', 'A', 'L', '-', '0', '5', '-', '0', '2', + 'V', 'E', 'R', 'T', 'I', 'C', 'A', 'L', '-', '0', '5', '-', '0', '3', + 'V', 'E', 'R', 'T', 'I', 'C', 'A', 'L', '-', '0', '5', '-', '0', '4', + 'V', 'E', 'R', 'T', 'I', 'C', 'A', 'L', '-', '0', '5', '-', '0', '5', + 'V', 'E', 'R', 'T', 'I', 'C', 'A', 'L', '-', '0', '5', '-', '0', '6', + 'V', 'E', 'R', 'T', 'I', 'C', 'A', 'L', '-', '0', '6', '-', '0', '0', + 'V', 'E', 'R', 'T', 'I', 'C', 'A', 'L', '-', '0', '6', '-', '0', '1', + 'V', 'E', 'R', 'T', 'I', 'C', 'A', 'L', '-', '0', '6', '-', '0', '2', + 'V', 'E', 'R', 'T', 'I', 'C', 'A', 'L', '-', '0', '6', '-', '0', '3', + 'V', 'E', 'R', 'T', 'I', 'C', 'A', 'L', '-', '0', '6', '-', '0', '4', + 'V', 'E', 'R', 'T', 'I', 'C', 'A', 'L', '-', '0', '6', '-', '0', '5', + 'V', 'E', 'R', 'T', 'I', 'C', 'A', 'L', '-', '0', '6', '-', '0', '6', + 'A', 'C', 'C', 'E', 'N', 'T', '-', 'S', 'T', 'A', 'C', 'C', 'A', 'T', 'O', + 'A', 'N', 'T', 'I', 'K', 'E', 'N', 'O', 'K', 'Y', 'L', 'I', 'S', 'M', 'A', + 'A', 'N', 'T', 'I', 'R', 'E', 'S', 'T', 'R', 'I', 'C', 'T', 'I', 'O', 'N', + 'B', 'L', 'A', 'C', 'K', '-', 'F', 'E', 'A', 'T', 'H', 'E', 'R', 'E', 'D', + 'C', 'E', 'O', 'N', 'G', 'C', 'H', 'I', 'E', 'U', 'M', 'S', 'I', 'O', 'S', + 'C', 'H', 'I', 'E', 'U', 'C', 'H', '-', 'K', 'H', 'I', 'E', 'U', 'K', 'H', + 'C', 'H', 'I', 'T', 'U', 'E', 'U', 'M', 'C', 'H', 'I', 'E', 'U', 'C', 'H', + 'C', 'O', 'N', 'C', 'A', 'V', 'E', '-', 'P', 'O', 'I', 'N', 'T', 'E', 'D', + 'H', 'I', 'G', 'H', '-', 'R', 'E', 'V', 'E', 'R', 'S', 'E', 'D', '-', '9', + 'J', 'A', 'L', 'L', 'A', 'J', 'A', 'L', 'A', 'L', 'O', 'U', 'H', 'O', 'U', + 'K', 'A', 'P', 'Y', 'E', 'O', 'U', 'N', 'P', 'H', 'I', 'E', 'U', 'P', 'H', + 'K', 'R', 'A', 'T', 'I', 'M', 'O', 'K', 'O', 'U', 'F', 'I', 'S', 'M', 'A', + 'K', 'R', 'A', 'T', 'I', 'M', 'O', 'Y', 'P', 'O', 'R', 'R', 'O', 'O', 'N', + 'L', 'O', 'N', 'G', '-', 'B', 'R', 'A', 'N', 'C', 'H', '-', 'O', 'S', 'S', + 'L', 'O', 'N', 'G', '-', 'B', 'R', 'A', 'N', 'C', 'H', '-', 'S', 'O', 'L', + 'M', 'I', 'E', 'U', 'M', '-', 'S', 'S', 'A', 'N', 'G', 'S', 'I', 'O', 'S', + 'P', 'E', 'T', 'A', 'S', 'T', 'O', 'K', 'O', 'U', 'F', 'I', 'S', 'M', 'A', + 'P', 'I', 'E', 'U', 'P', '-', 'S', 'S', 'A', 'N', 'G', 'S', 'I', 'O', 'S', + 'P', 'S', 'I', 'F', 'I', 'S', 'T', 'O', 'L', 'Y', 'G', 'I', 'S', 'M', 'A', + 'P', 'S', 'I', 'F', 'I', 'S', 'T', 'O', 'S', 'Y', 'N', 'A', 'G', 'M', 'A', + 'R', 'I', 'E', 'U', 'L', '-', 'S', 'S', 'A', 'N', 'G', 'S', 'I', 'O', 'S', + 'S', 'H', 'O', 'R', 'T', '-', 'T', 'W', 'I', 'G', '-', 'M', 'A', 'D', 'R', + 'S', 'H', 'O', 'R', 'T', '-', 'T', 'W', 'I', 'G', '-', 'N', 'A', 'U', 'D', + 'T', 'E', 'A', 'R', 'D', 'R', 'O', 'P', '-', 'B', 'A', 'R', 'B', 'E', 'D', + 'T', 'E', 'A', 'R', 'D', 'R', 'O', 'P', '-', 'S', 'P', 'O', 'K', 'E', 'D', + 'T', 'R', 'I', 'A', 'N', 'G', 'L', 'E', '-', 'H', 'E', 'A', 'D', 'E', 'D', + 'W', 'H', 'I', 'T', 'E', '-', 'F', 'E', 'A', 'T', 'H', 'E', 'R', 'E', 'D', + 'C', 'E', 'O', 'N', 'G', 'C', 'H', 'I', 'E', 'U', 'M', 'C', 'I', 'E', 'U', 'C', + 'H', 'O', 'R', 'I', 'Z', 'O', 'N', 'T', 'A', 'L', '-', '0', '0', '-', '0', '0', + 'H', 'O', 'R', 'I', 'Z', 'O', 'N', 'T', 'A', 'L', '-', '0', '0', '-', '0', '1', + 'H', 'O', 'R', 'I', 'Z', 'O', 'N', 'T', 'A', 'L', '-', '0', '0', '-', '0', '2', + 'H', 'O', 'R', 'I', 'Z', 'O', 'N', 'T', 'A', 'L', '-', '0', '0', '-', '0', '3', + 'H', 'O', 'R', 'I', 'Z', 'O', 'N', 'T', 'A', 'L', '-', '0', '0', '-', '0', '4', + 'H', 'O', 'R', 'I', 'Z', 'O', 'N', 'T', 'A', 'L', '-', '0', '0', '-', '0', '5', + 'H', 'O', 'R', 'I', 'Z', 'O', 'N', 'T', 'A', 'L', '-', '0', '0', '-', '0', '6', + 'H', 'O', 'R', 'I', 'Z', 'O', 'N', 'T', 'A', 'L', '-', '0', '1', '-', '0', '0', + 'H', 'O', 'R', 'I', 'Z', 'O', 'N', 'T', 'A', 'L', '-', '0', '1', '-', '0', '1', + 'H', 'O', 'R', 'I', 'Z', 'O', 'N', 'T', 'A', 'L', '-', '0', '1', '-', '0', '2', + 'H', 'O', 'R', 'I', 'Z', 'O', 'N', 'T', 'A', 'L', '-', '0', '1', '-', '0', '3', + 'H', 'O', 'R', 'I', 'Z', 'O', 'N', 'T', 'A', 'L', '-', '0', '1', '-', '0', '4', + 'H', 'O', 'R', 'I', 'Z', 'O', 'N', 'T', 'A', 'L', '-', '0', '1', '-', '0', '5', + 'H', 'O', 'R', 'I', 'Z', 'O', 'N', 'T', 'A', 'L', '-', '0', '1', '-', '0', '6', + 'H', 'O', 'R', 'I', 'Z', 'O', 'N', 'T', 'A', 'L', '-', '0', '2', '-', '0', '0', + 'H', 'O', 'R', 'I', 'Z', 'O', 'N', 'T', 'A', 'L', '-', '0', '2', '-', '0', '1', + 'H', 'O', 'R', 'I', 'Z', 'O', 'N', 'T', 'A', 'L', '-', '0', '2', '-', '0', '2', + 'H', 'O', 'R', 'I', 'Z', 'O', 'N', 'T', 'A', 'L', '-', '0', '2', '-', '0', '3', + 'H', 'O', 'R', 'I', 'Z', 'O', 'N', 'T', 'A', 'L', '-', '0', '2', '-', '0', '4', + 'H', 'O', 'R', 'I', 'Z', 'O', 'N', 'T', 'A', 'L', '-', '0', '2', '-', '0', '5', + 'H', 'O', 'R', 'I', 'Z', 'O', 'N', 'T', 'A', 'L', '-', '0', '2', '-', '0', '6', + 'H', 'O', 'R', 'I', 'Z', 'O', 'N', 'T', 'A', 'L', '-', '0', '3', '-', '0', '0', + 'H', 'O', 'R', 'I', 'Z', 'O', 'N', 'T', 'A', 'L', '-', '0', '3', '-', '0', '1', + 'H', 'O', 'R', 'I', 'Z', 'O', 'N', 'T', 'A', 'L', '-', '0', '3', '-', '0', '2', + 'H', 'O', 'R', 'I', 'Z', 'O', 'N', 'T', 'A', 'L', '-', '0', '3', '-', '0', '3', + 'H', 'O', 'R', 'I', 'Z', 'O', 'N', 'T', 'A', 'L', '-', '0', '3', '-', '0', '4', + 'H', 'O', 'R', 'I', 'Z', 'O', 'N', 'T', 'A', 'L', '-', '0', '3', '-', '0', '5', + 'H', 'O', 'R', 'I', 'Z', 'O', 'N', 'T', 'A', 'L', '-', '0', '3', '-', '0', '6', + 'H', 'O', 'R', 'I', 'Z', 'O', 'N', 'T', 'A', 'L', '-', '0', '4', '-', '0', '0', + 'H', 'O', 'R', 'I', 'Z', 'O', 'N', 'T', 'A', 'L', '-', '0', '4', '-', '0', '1', + 'H', 'O', 'R', 'I', 'Z', 'O', 'N', 'T', 'A', 'L', '-', '0', '4', '-', '0', '2', + 'H', 'O', 'R', 'I', 'Z', 'O', 'N', 'T', 'A', 'L', '-', '0', '4', '-', '0', '3', + 'H', 'O', 'R', 'I', 'Z', 'O', 'N', 'T', 'A', 'L', '-', '0', '4', '-', '0', '4', + 'H', 'O', 'R', 'I', 'Z', 'O', 'N', 'T', 'A', 'L', '-', '0', '4', '-', '0', '5', + 'H', 'O', 'R', 'I', 'Z', 'O', 'N', 'T', 'A', 'L', '-', '0', '4', '-', '0', '6', + 'H', 'O', 'R', 'I', 'Z', 'O', 'N', 'T', 'A', 'L', '-', '0', '5', '-', '0', '0', + 'H', 'O', 'R', 'I', 'Z', 'O', 'N', 'T', 'A', 'L', '-', '0', '5', '-', '0', '1', + 'H', 'O', 'R', 'I', 'Z', 'O', 'N', 'T', 'A', 'L', '-', '0', '5', '-', '0', '2', + 'H', 'O', 'R', 'I', 'Z', 'O', 'N', 'T', 'A', 'L', '-', '0', '5', '-', '0', '3', + 'H', 'O', 'R', 'I', 'Z', 'O', 'N', 'T', 'A', 'L', '-', '0', '5', '-', '0', '4', + 'H', 'O', 'R', 'I', 'Z', 'O', 'N', 'T', 'A', 'L', '-', '0', '5', '-', '0', '5', + 'H', 'O', 'R', 'I', 'Z', 'O', 'N', 'T', 'A', 'L', '-', '0', '5', '-', '0', '6', + 'H', 'O', 'R', 'I', 'Z', 'O', 'N', 'T', 'A', 'L', '-', '0', '6', '-', '0', '0', + 'H', 'O', 'R', 'I', 'Z', 'O', 'N', 'T', 'A', 'L', '-', '0', '6', '-', '0', '1', + 'H', 'O', 'R', 'I', 'Z', 'O', 'N', 'T', 'A', 'L', '-', '0', '6', '-', '0', '2', + 'H', 'O', 'R', 'I', 'Z', 'O', 'N', 'T', 'A', 'L', '-', '0', '6', '-', '0', '3', + 'H', 'O', 'R', 'I', 'Z', 'O', 'N', 'T', 'A', 'L', '-', '0', '6', '-', '0', '4', + 'H', 'O', 'R', 'I', 'Z', 'O', 'N', 'T', 'A', 'L', '-', '0', '6', '-', '0', '5', + 'H', 'O', 'R', 'I', 'Z', 'O', 'N', 'T', 'A', 'L', '-', '0', '6', '-', '0', '6', + 'L', 'O', 'N', 'G', '-', 'B', 'R', 'A', 'N', 'C', 'H', '-', 'M', 'A', 'D', 'R', + 'M', 'A', 'R', 'C', 'A', 'T', 'O', '-', 'S', 'T', 'A', 'C', 'C', 'A', 'T', 'O', + 'P', 'I', 'E', 'U', 'P', '-', 'S', 'I', 'O', 'S', '-', 'C', 'I', 'E', 'U', 'C', + 'P', 'I', 'E', 'U', 'P', '-', 'S', 'I', 'O', 'S', '-', 'P', 'I', 'E', 'U', 'P', + 'R', 'I', 'E', 'U', 'L', '-', 'M', 'I', 'E', 'U', 'M', '-', 'S', 'I', 'O', 'S', + 'R', 'I', 'E', 'U', 'L', '-', 'P', 'I', 'E', 'U', 'P', '-', 'S', 'I', 'O', 'S', + 'T', 'E', 'A', 'R', 'D', 'R', 'O', 'P', '-', 'S', 'H', 'A', 'N', 'K', 'E', 'D', + 'T', 'R', 'O', 'M', 'I', 'K', 'O', 'P', 'S', 'I', 'F', 'I', 'S', 'T', 'O', 'N', + 'Y', 'E', 'S', 'I', 'E', 'U', 'N', 'G', '-', 'P', 'A', 'N', 'S', 'I', 'O', 'S', + 'A', 'C', 'U', 'T', 'E', '-', 'G', 'R', 'A', 'V', 'E', '-', 'A', 'C', 'U', 'T', 'E', + 'C', 'H', 'I', 'T', 'U', 'E', 'U', 'M', 'S', 'S', 'A', 'N', 'G', 'S', 'I', 'O', 'S', + 'G', 'R', 'A', 'V', 'E', '-', 'A', 'C', 'U', 'T', 'E', '-', 'G', 'R', 'A', 'V', 'E', + 'I', 'E', 'U', 'N', 'G', '-', 'S', 'S', 'A', 'N', 'G', 'K', 'I', 'Y', 'E', 'O', 'K', + 'K', 'A', 'T', 'A', 'K', 'A', 'N', 'A', '-', 'H', 'I', 'R', 'A', 'G', 'A', 'N', 'A', + 'P', 'I', 'E', 'U', 'P', '-', 'S', 'I', 'O', 'S', '-', 'K', 'I', 'Y', 'E', 'O', 'K', + 'P', 'I', 'E', 'U', 'P', '-', 'S', 'I', 'O', 'S', '-', 'T', 'I', 'K', 'E', 'U', 'T', + 'R', 'I', 'E', 'U', 'L', '-', 'K', 'I', 'Y', 'E', 'O', 'K', '-', 'S', 'I', 'O', 'S', + 'R', 'I', 'E', 'U', 'L', '-', 'P', 'I', 'E', 'U', 'P', '-', 'H', 'I', 'E', 'U', 'H', + 'R', 'I', 'E', 'U', 'L', '-', 'Y', 'E', 'O', 'R', 'I', 'N', 'H', 'I', 'E', 'U', 'H', + 'S', 'H', 'O', 'R', 'T', '-', 'T', 'W', 'I', 'G', '-', 'H', 'A', 'G', 'A', 'L', 'L', + 'S', 'I', 'O', 'S', '-', 'P', 'I', 'E', 'U', 'P', '-', 'K', 'I', 'Y', 'E', 'O', 'K', + 'S', 'O', 'F', 'T', 'W', 'A', 'R', 'E', '-', 'F', 'U', 'N', 'C', 'T', 'I', 'O', 'N', + 'C', 'E', 'O', 'N', 'G', 'C', 'H', 'I', 'E', 'U', 'M', 'C', 'H', 'I', 'E', 'U', 'C', 'H', + 'C', 'H', 'I', 'T', 'U', 'E', 'U', 'M', 'S', 'S', 'A', 'N', 'G', 'C', 'I', 'E', 'U', 'C', + 'K', 'A', 'P', 'Y', 'E', 'O', 'U', 'N', 'S', 'S', 'A', 'N', 'G', 'P', 'I', 'E', 'U', 'P', + 'K', 'I', 'Y', 'E', 'O', 'K', '-', 'S', 'I', 'O', 'S', '-', 'K', 'I', 'Y', 'E', 'O', 'K', + 'L', 'O', 'N', 'G', '-', 'B', 'R', 'A', 'N', 'C', 'H', '-', 'H', 'A', 'G', 'A', 'L', 'L', + 'P', 'A', 'R', 'T', 'I', 'A', 'L', 'L', 'Y', '-', 'R', 'E', 'C', 'Y', 'C', 'L', 'E', 'D', + 'R', 'I', 'E', 'U', 'L', '-', 'M', 'I', 'E', 'U', 'M', '-', 'K', 'I', 'Y', 'E', 'O', 'K', + 'R', 'I', 'E', 'U', 'L', '-', 'T', 'I', 'K', 'E', 'U', 'T', '-', 'H', 'I', 'E', 'U', 'H', + 'S', 'H', 'O', 'R', 'T', '-', 'T', 'W', 'I', 'G', '-', 'B', 'J', 'A', 'R', 'K', 'A', 'N', + 'T', 'R', 'O', 'M', 'I', 'K', 'O', 'P', 'A', 'R', 'A', 'K', 'A', 'L', 'E', 'S', 'M', 'A', + 'O', 'P', 'E', 'N', '-', 'C', 'I', 'R', 'C', 'U', 'I', 'T', '-', 'O', 'U', 'T', 'P', 'U', 'T', + 'P', 'S', 'I', 'F', 'I', 'S', 'T', 'O', 'P', 'A', 'R', 'A', 'K', 'A', 'L', 'E', 'S', 'M', 'A', + 'R', 'I', 'E', 'U', 'L', '-', 'K', 'A', 'P', 'Y', 'E', 'O', 'U', 'N', 'P', 'I', 'E', 'U', 'P', + 'C', 'E', 'O', 'N', 'G', 'C', 'H', 'I', 'E', 'U', 'M', 'S', 'S', 'A', 'N', 'G', 'S', 'I', 'O', 'S', + 'A', 'N', 'T', 'I', 'C', 'L', 'O', 'C', 'K', 'W', 'I', 'S', 'E', '-', 'R', 'O', 'T', 'A', 'T', 'E', 'D', + 'C', 'E', 'O', 'N', 'G', 'C', 'H', 'I', 'E', 'U', 'M', 'S', 'S', 'A', 'N', 'G', 'C', 'I', 'E', 'U', 'C', + 'B', 'Y', 'E', 'L', 'O', 'R', 'U', 'S', 'S', 'I', 'A', 'N', '-', 'U', 'K', 'R', 'A', 'I', 'N', 'I', 'A', 'N', + 'P', 'A', 'S', 'S', 'I', 'V', 'E', '-', 'P', 'U', 'L', 'L', '-', 'U', 'P', '-', 'O', 'U', 'T', 'P', 'U', 'T', + 'P', 'A', 'S', 'S', 'I', 'V', 'E', '-', 'P', 'U', 'L', 'L', '-', 'D', 'O', 'W', 'N', '-', 'O', 'U', 'T', 'P', 'U', 'T', +}; +#define UNICODE_CHARNAME_NUM_WORDS 6710 +static const struct { uint16_t extra_offset; uint16_t ind_offset; } unicode_name_by_length[26] = { + { 0, 0 }, + { 0, 0 }, + { 26, 26 }, + { 658, 342 }, + { 4468, 1612 }, + { 10756, 3184 }, + { 14596, 3952 }, + { 17782, 4483 }, + { 20883, 4926 }, + { 24251, 5347 }, + { 27446, 5702 }, + { 29846, 5942 }, + { 32629, 6195 }, + { 35689, 6450 }, + { 36599, 6520 }, + { 37607, 6592 }, + { 38012, 6619 }, + { 38956, 6678 }, + { 39177, 6691 }, + { 39357, 6701 }, + { 39414, 6704 }, + { 39434, 6705 }, + { 39476, 6707 }, + { 39520, 6709 }, + { 39520, 6709 }, + { 39544, 6710 } +}; +#define UNICODE_CHARNAME_WORD_HANGUL 4143 +#define UNICODE_CHARNAME_WORD_SYLLABLE 5292 +#define UNICODE_CHARNAME_WORD_CJK 454 +#define UNICODE_CHARNAME_WORD_COMPATIBILITY 6457 +static const uint16_t unicode_names[75152] = { + 23, 3, 761, 8774, + 37, 275, 10642, + 47, 275, 1, 11203, 826, + 51, 10365, 753, 11680, + 51, 10365, 4849, 6989, 9050, + 51, 10365, 4849, 9045, 9050, + 51, 10365, 5782, + 51, 10365, 6031, 6610, + 51, 10365, 7421, 13188, + 51, 10365, 7443, 6989, 9050, + 51, 10365, 7443, 9045, 9050, + 51, 10365, 8131, 13188, + 51, 10365, 8675, 8590, + 51, 10365, 8675, 11734, + 51, 10365, 8675, 11908, + 51, 10365, 11751, 11908, + 63, 9128, + 175, 3992, + 175, 5496, + 175, 7608, + 177, 3992, + 177, 5496, + 177, 7608, + 435, 6573, 385, 9798, + 435, 6573, 3232, + 435, 6573, 6689, 2170, + 435, 6573, 6689, 2540, + 435, 6573, 6689, 2778, + 435, 6573, 6689, 4200, + 435, 6573, 6689, 4214, + 435, 6573, 6689, 5190, + 435, 6573, 6689, 6260, + 435, 6573, 6689, 6722, + 435, 6573, 6689, 7508, + 435, 6573, 6689, 7694, + 435, 6573, 7430, + 435, 6573, 8405, 68, + 435, 6573, 8405, 76, + 435, 6573, 8405, 90, + 435, 6573, 8405, 176, + 435, 6573, 8405, 180, + 435, 6573, 8405, 264, + 435, 6573, 8405, 280, + 435, 6573, 8405, 282, + 435, 6573, 8405, 332, + 435, 6573, 8405, 336, + 435, 6573, 8405, 340, + 435, 6573, 8405, 350, + 435, 6573, 8405, 354, + 435, 6573, 8405, 424, + 435, 6573, 8405, 430, + 435, 6573, 8405, 452, + 435, 6573, 8405, 586, + 435, 6573, 8405, 588, + 435, 6573, 8405, 608, + 435, 6573, 8405, 692, + 435, 6573, 8405, 694, + 435, 6573, 8405, 696, + 435, 6573, 8405, 698, + 435, 6573, 8405, 722, + 435, 6573, 8405, 1096, + 435, 6573, 8405, 1120, + 435, 6573, 8405, 1492, + 435, 6573, 8405, 1732, + 435, 6573, 8405, 2182, + 435, 6573, 8405, 2814, + 435, 6573, 9299, 10654, + 435, 6573, 10426, + 435, 6573, 11691, 10654, + 435, 6573, 12133, 8153, 8488, + 435, 6573, 12133, 8488, + 445, 6121, 1045, 8318, + 601, 3713, 4849, 4117, 3713, 4849, 9326, + 601, 3713, 4849, 4117, 3713, 7443, 9326, + 601, 3713, 7443, 4117, 3713, 4849, 9326, + 601, 3713, 7443, 4117, 3713, 7443, 9326, + 601, 4117, 6434, + 601, 4117, 6435, 6121, 3716, + 601, 4117, 6505, 6434, + 601, 4117, 7821, 6434, + 601, 4117, 8153, 6434, + 601, 4197, 5878, + 601, 5876, + 601, 5877, 6121, 8057, 6376, + 601, 6435, 9785, 8056, + 601, 7443, 10001, 10154, + 601, 10716, + 601, 10717, 9043, 2779, 11649, 3714, + 657, 9617, 134, + 657, 9617, 152, + 657, 9617, 216, + 657, 9617, 298, + 657, 9617, 310, + 657, 9617, 340, + 657, 9617, 374, + 657, 9617, 442, + 657, 9617, 576, + 657, 9617, 632, + 657, 9617, 660, + 657, 9617, 670, + 657, 9617, 832, + 657, 9617, 886, + 657, 9617, 902, + 657, 9617, 946, + 657, 9617, 950, + 657, 9617, 1242, + 657, 9617, 1294, + 657, 9617, 1406, + 657, 9617, 1538, + 657, 9617, 1636, + 657, 9617, 1782, + 657, 9617, 1844, + 657, 9617, 1940, + 657, 9617, 2262, + 657, 9617, 2278, + 657, 9617, 2324, + 657, 9617, 2526, + 657, 9617, 2570, + 657, 9617, 2656, + 657, 9617, 2860, + 657, 9617, 2890, + 657, 9617, 3074, + 657, 9617, 3182, + 657, 9617, 3194, + 657, 9617, 3196, + 657, 9617, 3748, + 657, 9617, 3962, + 657, 9617, 4040, + 657, 9617, 4292, + 657, 9617, 4298, + 657, 9617, 4572, + 657, 9617, 4576, + 657, 9617, 4582, + 657, 9617, 4646, + 657, 9617, 4666, + 657, 9617, 5064, + 657, 9617, 5304, + 657, 9617, 5318, + 657, 9617, 5356, + 657, 9617, 5674, + 657, 9617, 5712, + 657, 9617, 5726, + 657, 9617, 7896, + 657, 10585, 0, + 657, 10585, 8, + 657, 10585, 16, + 657, 10585, 28, + 657, 10585, 84, + 657, 10585, 90, + 657, 10585, 96, + 657, 10585, 100, + 657, 10585, 102, + 657, 10585, 106, + 657, 10585, 108, + 657, 10585, 112, + 657, 10585, 114, + 657, 10585, 116, + 657, 10585, 122, + 657, 10585, 126, + 657, 10585, 130, + 657, 10585, 132, + 657, 10585, 134, + 657, 10585, 138, + 657, 10585, 142, + 657, 10585, 144, + 657, 10585, 150, + 657, 10585, 152, + 657, 10585, 194, + 657, 10585, 196, + 657, 10585, 202, + 657, 10585, 208, + 657, 10585, 210, + 657, 10585, 212, + 657, 10585, 216, + 657, 10585, 220, + 657, 10585, 224, + 657, 10585, 228, + 657, 10585, 230, + 657, 10585, 236, + 657, 10585, 238, + 657, 10585, 246, + 657, 10585, 258, + 657, 10585, 278, + 657, 10585, 284, + 657, 10585, 288, + 657, 10585, 296, + 657, 10585, 298, + 657, 10585, 300, + 657, 10585, 302, + 657, 10585, 306, + 657, 10585, 310, + 657, 10585, 314, + 657, 10585, 322, + 657, 10585, 326, + 657, 10585, 332, + 657, 10585, 336, + 657, 10585, 340, + 657, 10585, 350, + 657, 10585, 354, + 657, 10585, 360, + 657, 10585, 364, + 657, 10585, 368, + 657, 10585, 374, + 657, 10585, 380, + 657, 10585, 384, + 657, 10585, 390, + 657, 10585, 392, + 657, 10585, 396, + 657, 10585, 404, + 657, 10585, 412, + 657, 10585, 416, + 657, 10585, 442, + 657, 10585, 448, + 657, 10585, 456, + 657, 10585, 462, + 657, 10585, 476, + 657, 10585, 480, + 657, 10585, 486, + 657, 10585, 492, + 657, 10585, 500, + 657, 10585, 502, + 657, 10585, 506, + 657, 10585, 508, + 657, 10585, 510, + 657, 10585, 512, + 657, 10585, 516, + 657, 10585, 520, + 657, 10585, 522, + 657, 10585, 524, + 657, 10585, 526, + 657, 10585, 532, + 657, 10585, 536, + 657, 10585, 546, + 657, 10585, 552, + 657, 10585, 556, + 657, 10585, 560, + 657, 10585, 564, + 657, 10585, 568, + 657, 10585, 576, + 657, 10585, 598, + 657, 10585, 610, + 657, 10585, 614, + 657, 10585, 616, + 657, 10585, 618, + 657, 10585, 620, + 657, 10585, 622, + 657, 10585, 626, + 657, 10585, 632, + 657, 10585, 634, + 657, 10585, 644, + 657, 10585, 646, + 657, 10585, 650, + 657, 10585, 656, + 657, 10585, 660, + 657, 10585, 664, + 657, 10585, 668, + 657, 10585, 670, + 657, 10585, 672, + 657, 10585, 676, + 657, 10585, 678, + 657, 10585, 680, + 657, 10585, 682, + 657, 10585, 758, + 657, 10585, 762, + 657, 10585, 764, + 657, 10585, 766, + 657, 10585, 768, + 657, 10585, 770, + 657, 10585, 772, + 657, 10585, 774, + 657, 10585, 776, + 657, 10585, 786, + 657, 10585, 790, + 657, 10585, 804, + 657, 10585, 808, + 657, 10585, 810, + 657, 10585, 812, + 657, 10585, 820, + 657, 10585, 822, + 657, 10585, 826, + 657, 10585, 828, + 657, 10585, 830, + 657, 10585, 832, + 657, 10585, 834, + 657, 10585, 836, + 657, 10585, 846, + 657, 10585, 848, + 657, 10585, 850, + 657, 10585, 852, + 657, 10585, 860, + 657, 10585, 862, + 657, 10585, 864, + 657, 10585, 880, + 657, 10585, 882, + 657, 10585, 884, + 657, 10585, 886, + 657, 10585, 890, + 657, 10585, 892, + 657, 10585, 894, + 657, 10585, 896, + 657, 10585, 902, + 657, 10585, 904, + 657, 10585, 906, + 657, 10585, 916, + 657, 10585, 918, + 657, 10585, 922, + 657, 10585, 926, + 657, 10585, 928, + 657, 10585, 930, + 657, 10585, 932, + 657, 10585, 934, + 657, 10585, 946, + 657, 10585, 948, + 657, 10585, 950, + 657, 10585, 952, + 657, 10585, 964, + 657, 10585, 968, + 657, 10585, 970, + 657, 10585, 974, + 657, 10585, 976, + 657, 10585, 978, + 657, 10585, 980, + 657, 10585, 982, + 657, 10585, 992, + 657, 10585, 994, + 657, 10585, 1008, + 657, 10585, 1014, + 657, 10585, 1016, + 657, 10585, 1018, + 657, 10585, 1042, + 657, 10585, 1044, + 657, 10585, 1046, + 657, 10585, 1062, + 657, 10585, 1064, + 657, 10585, 1066, + 657, 10585, 1068, + 657, 10585, 1070, + 657, 10585, 1144, + 657, 10585, 1146, + 657, 10585, 1148, + 657, 10585, 1162, + 657, 10585, 1164, + 657, 10585, 1166, + 657, 10585, 1174, + 657, 10585, 1178, + 657, 10585, 1180, + 657, 10585, 1182, + 657, 10585, 1184, + 657, 10585, 1186, + 657, 10585, 1196, + 657, 10585, 1198, + 657, 10585, 1200, + 657, 10585, 1218, + 657, 10585, 1222, + 657, 10585, 1224, + 657, 10585, 1242, + 657, 10585, 1246, + 657, 10585, 1248, + 657, 10585, 1250, + 657, 10585, 1252, + 657, 10585, 1254, + 657, 10585, 1256, + 657, 10585, 1258, + 657, 10585, 1274, + 657, 10585, 1278, + 657, 10585, 1280, + 657, 10585, 1282, + 657, 10585, 1292, + 657, 10585, 1294, + 657, 10585, 1296, + 657, 10585, 1312, + 657, 10585, 1314, + 657, 10585, 1316, + 657, 10585, 1318, + 657, 10585, 1320, + 657, 10585, 1348, + 657, 10585, 1352, + 657, 10585, 1354, + 657, 10585, 1364, + 657, 10585, 1368, + 657, 10585, 1380, + 657, 10585, 1388, + 657, 10585, 1390, + 657, 10585, 1392, + 657, 10585, 1394, + 657, 10585, 1396, + 657, 10585, 1398, + 657, 10585, 1400, + 657, 10585, 1402, + 657, 10585, 1404, + 657, 10585, 1406, + 657, 10585, 1408, + 657, 10585, 1410, + 657, 10585, 1412, + 657, 10585, 1414, + 657, 10585, 1416, + 657, 10585, 1426, + 657, 10585, 1428, + 657, 10585, 1430, + 657, 10585, 1438, + 657, 10585, 1450, + 657, 10585, 1452, + 657, 10585, 1454, + 657, 10585, 1456, + 657, 10585, 1476, + 657, 10585, 1478, + 657, 10585, 1480, + 657, 10585, 1518, + 657, 10585, 1522, + 657, 10585, 1524, + 657, 10585, 1526, + 657, 10585, 1532, + 657, 10585, 1534, + 657, 10585, 1536, + 657, 10585, 1538, + 657, 10585, 1544, + 657, 10585, 1546, + 657, 10585, 1548, + 657, 10585, 1552, + 657, 10585, 1554, + 657, 10585, 1556, + 657, 10585, 1558, + 657, 10585, 1560, + 657, 10585, 1564, + 657, 10585, 1566, + 657, 10585, 1568, + 657, 10585, 1570, + 657, 10585, 1590, + 657, 10585, 1592, + 657, 10585, 1594, + 657, 10585, 1604, + 657, 10585, 1606, + 657, 10585, 1608, + 657, 10585, 1626, + 657, 10585, 1634, + 657, 10585, 1636, + 657, 10585, 1638, + 657, 10585, 1662, + 657, 10585, 1664, + 657, 10585, 1666, + 657, 10585, 1692, + 657, 10585, 1694, + 657, 10585, 1696, + 657, 10585, 1698, + 657, 10585, 1700, + 657, 10585, 1742, + 657, 10585, 1746, + 657, 10585, 1750, + 657, 10585, 1766, + 657, 10585, 1768, + 657, 10585, 1782, + 657, 10585, 1788, + 657, 10585, 1790, + 657, 10585, 1792, + 657, 10585, 1804, + 657, 10585, 1806, + 657, 10585, 1810, + 657, 10585, 1824, + 657, 10585, 1826, + 657, 10585, 1828, + 657, 10585, 1830, + 657, 10585, 1832, + 657, 10585, 1842, + 657, 10585, 1844, + 657, 10585, 1846, + 657, 10585, 1848, + 657, 10585, 1862, + 657, 10585, 1866, + 657, 10585, 1868, + 657, 10585, 1898, + 657, 10585, 1900, + 657, 10585, 1902, + 657, 10585, 1904, + 657, 10585, 1906, + 657, 10585, 1912, + 657, 10585, 1924, + 657, 10585, 1926, + 657, 10585, 1928, + 657, 10585, 1940, + 657, 10585, 1942, + 657, 10585, 1944, + 657, 10585, 1954, + 657, 10585, 1956, + 657, 10585, 1958, + 657, 10585, 1960, + 657, 10585, 1962, + 657, 10585, 1974, + 657, 10585, 1976, + 657, 10585, 1978, + 657, 10585, 1990, + 657, 10585, 1994, + 657, 10585, 1996, + 657, 10585, 1998, + 657, 10585, 2000, + 657, 10585, 2002, + 657, 10585, 2004, + 657, 10585, 2006, + 657, 10585, 2008, + 657, 10585, 2010, + 657, 10585, 2012, + 657, 10585, 2014, + 657, 10585, 2022, + 657, 10585, 2028, + 657, 10585, 2030, + 657, 10585, 2032, + 657, 10585, 2038, + 657, 10585, 2050, + 657, 10585, 2056, + 657, 10585, 2058, + 657, 10585, 2060, + 657, 10585, 2066, + 657, 10585, 2068, + 657, 10585, 2070, + 657, 10585, 2072, + 657, 10585, 2086, + 657, 10585, 2090, + 657, 10585, 2094, + 657, 10585, 2096, + 657, 10585, 2098, + 657, 10585, 2100, + 657, 10585, 2102, + 657, 10585, 2104, + 657, 10585, 2112, + 657, 10585, 2114, + 657, 10585, 2116, + 657, 10585, 2118, + 657, 10585, 2120, + 657, 10585, 2132, + 657, 10585, 2134, + 657, 10585, 2136, + 657, 10585, 2138, + 657, 10585, 2140, + 657, 10585, 2142, + 657, 10585, 2144, + 657, 10585, 2146, + 657, 10585, 2194, + 657, 10585, 2198, + 657, 10585, 2202, + 657, 10585, 2222, + 657, 10585, 2228, + 657, 10585, 2230, + 657, 10585, 2232, + 657, 10585, 2240, + 657, 10585, 2242, + 657, 10585, 2244, + 657, 10585, 2256, + 657, 10585, 2258, + 657, 10585, 2260, + 657, 10585, 2262, + 657, 10585, 2264, + 657, 10585, 2274, + 657, 10585, 2276, + 657, 10585, 2278, + 657, 10585, 2280, + 657, 10585, 2306, + 657, 10585, 2310, + 657, 10585, 2312, + 657, 10585, 2314, + 657, 10585, 2322, + 657, 10585, 2324, + 657, 10585, 2326, + 657, 10585, 2336, + 657, 10585, 2338, + 657, 10585, 2340, + 657, 10585, 2342, + 657, 10585, 2348, + 657, 10585, 2364, + 657, 10585, 2366, + 657, 10585, 2368, + 657, 10585, 2372, + 657, 10585, 2390, + 657, 10585, 2392, + 657, 10585, 2394, + 657, 10585, 2406, + 657, 10585, 2408, + 657, 10585, 2432, + 657, 10585, 2434, + 657, 10585, 2436, + 657, 10585, 2438, + 657, 10585, 2440, + 657, 10585, 2442, + 657, 10585, 2444, + 657, 10585, 2446, + 657, 10585, 2456, + 657, 10585, 2458, + 657, 10585, 2460, + 657, 10585, 2462, + 657, 10585, 2464, + 657, 10585, 2470, + 657, 10585, 2472, + 657, 10585, 2474, + 657, 10585, 2476, + 657, 10585, 2492, + 657, 10585, 2496, + 657, 10585, 2500, + 657, 10585, 2508, + 657, 10585, 2512, + 657, 10585, 2516, + 657, 10585, 2518, + 657, 10585, 2522, + 657, 10585, 2524, + 657, 10585, 2526, + 657, 10585, 2528, + 657, 10585, 2536, + 657, 10585, 2538, + 657, 10585, 2540, + 657, 10585, 2556, + 657, 10585, 2558, + 657, 10585, 2564, + 657, 10585, 2566, + 657, 10585, 2568, + 657, 10585, 2570, + 657, 10585, 2572, + 657, 10585, 2574, + 657, 10585, 2576, + 657, 10585, 2588, + 657, 10585, 2590, + 657, 10585, 2592, + 657, 10585, 2594, + 657, 10585, 2596, + 657, 10585, 2612, + 657, 10585, 2614, + 657, 10585, 2616, + 657, 10585, 2618, + 657, 10585, 2652, + 657, 10585, 2656, + 657, 10585, 2664, + 657, 10585, 2672, + 657, 10585, 2676, + 657, 10585, 2690, + 657, 10585, 2696, + 657, 10585, 2700, + 657, 10585, 2702, + 657, 10585, 2724, + 657, 10585, 2726, + 657, 10585, 2728, + 657, 10585, 2762, + 657, 10585, 2764, + 657, 10585, 2766, + 657, 10585, 2768, + 657, 10585, 2770, + 657, 10585, 2818, + 657, 10585, 2820, + 657, 10585, 2848, + 657, 10585, 2850, + 657, 10585, 2854, + 657, 10585, 2860, + 657, 10585, 2864, + 657, 10585, 2866, + 657, 10585, 2870, + 657, 10585, 2872, + 657, 10585, 2874, + 657, 10585, 2878, + 657, 10585, 2880, + 657, 10585, 2886, + 657, 10585, 2888, + 657, 10585, 2890, + 657, 10585, 2892, + 657, 10585, 2894, + 657, 10585, 2898, + 657, 10585, 2900, + 657, 10585, 2902, + 657, 10585, 2904, + 657, 10585, 2912, + 657, 10585, 2914, + 657, 10585, 2920, + 657, 10585, 2928, + 657, 10585, 2930, + 657, 10585, 2944, + 657, 10585, 2946, + 657, 10585, 2950, + 657, 10585, 2960, + 657, 10585, 2962, + 657, 10585, 2964, + 657, 10585, 2966, + 657, 10585, 2970, + 657, 10585, 2974, + 657, 10585, 2976, + 657, 10585, 2978, + 657, 10585, 2996, + 657, 10585, 2998, + 657, 10585, 3000, + 657, 10585, 3004, + 657, 10585, 3064, + 657, 10585, 3072, + 657, 10585, 3074, + 657, 10585, 3076, + 657, 10585, 3084, + 657, 10585, 3086, + 657, 10585, 3088, + 657, 10585, 3090, + 657, 10585, 3092, + 657, 10585, 3094, + 657, 10585, 3098, + 657, 10585, 3100, + 657, 10585, 3112, + 657, 10585, 3114, + 657, 10585, 3116, + 657, 10585, 3118, + 657, 10585, 3130, + 657, 10585, 3132, + 657, 10585, 3134, + 657, 10585, 3142, + 657, 10585, 3144, + 657, 10585, 3146, + 657, 10585, 3148, + 657, 10585, 3152, + 657, 10585, 3154, + 657, 10585, 3156, + 657, 10585, 3162, + 657, 10585, 3166, + 657, 10585, 3168, + 657, 10585, 3170, + 657, 10585, 3180, + 657, 10585, 3182, + 657, 10585, 3184, + 657, 10585, 3192, + 657, 10585, 3194, + 657, 10585, 3196, + 657, 10585, 3198, + 657, 10585, 3200, + 657, 10585, 3204, + 657, 10585, 3206, + 657, 10585, 3208, + 657, 10585, 3210, + 657, 10585, 3212, + 657, 10585, 3214, + 657, 10585, 3216, + 657, 10585, 3218, + 657, 10585, 3220, + 657, 10585, 3222, + 657, 10585, 3718, + 657, 10585, 3720, + 657, 10585, 3722, + 657, 10585, 3724, + 657, 10585, 3726, + 657, 10585, 3728, + 657, 10585, 3730, + 657, 10585, 3732, + 657, 10585, 3734, + 657, 10585, 3736, + 657, 10585, 3738, + 657, 10585, 3740, + 657, 10585, 3742, + 657, 10585, 3744, + 657, 10585, 3746, + 657, 10585, 3748, + 657, 10585, 3750, + 657, 10585, 3752, + 657, 10585, 3754, + 657, 10585, 3756, + 657, 10585, 3782, + 657, 10585, 3784, + 657, 10585, 3786, + 657, 10585, 3816, + 657, 10585, 3818, + 657, 10585, 3824, + 657, 10585, 3828, + 657, 10585, 3882, + 657, 10585, 3886, + 657, 10585, 3888, + 657, 10585, 3896, + 657, 10585, 3898, + 657, 10585, 3900, + 657, 10585, 3910, + 657, 10585, 3912, + 657, 10585, 3914, + 657, 10585, 3916, + 657, 10585, 3918, + 657, 10585, 3920, + 657, 10585, 3922, + 657, 10585, 3926, + 657, 10585, 3928, + 657, 10585, 3930, + 657, 10585, 3932, + 657, 10585, 3934, + 657, 10585, 3936, + 657, 10585, 3938, + 657, 10585, 3962, + 657, 10585, 3964, + 657, 10585, 3968, + 657, 10585, 3976, + 657, 10585, 4002, + 657, 10585, 4004, + 657, 10585, 4006, + 657, 10585, 4012, + 657, 10585, 4014, + 657, 10585, 4020, + 657, 10585, 4022, + 657, 10585, 4024, + 657, 10585, 4026, + 657, 10585, 4030, + 657, 10585, 4032, + 657, 10585, 4034, + 657, 10585, 4036, + 657, 10585, 4038, + 657, 10585, 4040, + 657, 10585, 4042, + 657, 10585, 4044, + 657, 10585, 4082, + 657, 10585, 4084, + 657, 10585, 4130, + 657, 10585, 4134, + 657, 10585, 4224, + 657, 10585, 4272, + 657, 10585, 4274, + 657, 10585, 4276, + 657, 10585, 4280, + 657, 10585, 4282, + 657, 10585, 4284, + 657, 10585, 4286, + 657, 10585, 4288, + 657, 10585, 4290, + 657, 10585, 4292, + 657, 10585, 4294, + 657, 10585, 4296, + 657, 10585, 4298, + 657, 10585, 4300, + 657, 10585, 4302, + 657, 10585, 4304, + 657, 10585, 4306, + 657, 10585, 4326, + 657, 10585, 4328, + 657, 10585, 4330, + 657, 10585, 4360, + 657, 10585, 4362, + 657, 10585, 4364, + 657, 10585, 4368, + 657, 10585, 4420, + 657, 10585, 4426, + 657, 10585, 4428, + 657, 10585, 4430, + 657, 10585, 4432, + 657, 10585, 4434, + 657, 10585, 4436, + 657, 10585, 4438, + 657, 10585, 4440, + 657, 10585, 4442, + 657, 10585, 4444, + 657, 10585, 4446, + 657, 10585, 4448, + 657, 10585, 4450, + 657, 10585, 4452, + 657, 10585, 4454, + 657, 10585, 4456, + 657, 10585, 4458, + 657, 10585, 4460, + 657, 10585, 4462, + 657, 10585, 4464, + 657, 10585, 4466, + 657, 10585, 4468, + 657, 10585, 4470, + 657, 10585, 4472, + 657, 10585, 4474, + 657, 10585, 4476, + 657, 10585, 4478, + 657, 10585, 4480, + 657, 10585, 4482, + 657, 10585, 4484, + 657, 10585, 4486, + 657, 10585, 4488, + 657, 10585, 4490, + 657, 10585, 4492, + 657, 10585, 4494, + 657, 10585, 4496, + 657, 10585, 4498, + 657, 10585, 4500, + 657, 10585, 4502, + 657, 10585, 4504, + 657, 10585, 4506, + 657, 10585, 4508, + 657, 10585, 4510, + 657, 10585, 4512, + 657, 10585, 4514, + 657, 10585, 4516, + 657, 10585, 4518, + 657, 10585, 4520, + 657, 10585, 4522, + 657, 10585, 4524, + 657, 10585, 4526, + 657, 10585, 4528, + 657, 10585, 4550, + 657, 10585, 4552, + 657, 10585, 4554, + 657, 10585, 4558, + 657, 10585, 4560, + 657, 10585, 4562, + 657, 10585, 4564, + 657, 10585, 4566, + 657, 10585, 4568, + 657, 10585, 4570, + 657, 10585, 4572, + 657, 10585, 4574, + 657, 10585, 4576, + 657, 10585, 4578, + 657, 10585, 4580, + 657, 10585, 4582, + 657, 10585, 4638, + 657, 10585, 4640, + 657, 10585, 4642, + 657, 10585, 4646, + 657, 10585, 4648, + 657, 10585, 4650, + 657, 10585, 4652, + 657, 10585, 4654, + 657, 10585, 4656, + 657, 10585, 4658, + 657, 10585, 4660, + 657, 10585, 4662, + 657, 10585, 4664, + 657, 10585, 4666, + 657, 10585, 4668, + 657, 10585, 4670, + 657, 10585, 4672, + 657, 10585, 4674, + 657, 10585, 4688, + 657, 10585, 4690, + 657, 10585, 4692, + 657, 10585, 4694, + 657, 10585, 4696, + 657, 10585, 4756, + 657, 10585, 4758, + 657, 10585, 4786, + 657, 10585, 4788, + 657, 10585, 4792, + 657, 10585, 4866, + 657, 10585, 4868, + 657, 10585, 4870, + 657, 10585, 4902, + 657, 10585, 4904, + 657, 10585, 4906, + 657, 10585, 4908, + 657, 10585, 4916, + 657, 10585, 4958, + 657, 10585, 4960, + 657, 10585, 4962, + 657, 10585, 4974, + 657, 10585, 4976, + 657, 10585, 4978, + 657, 10585, 4980, + 657, 10585, 4982, + 657, 10585, 4984, + 657, 10585, 4986, + 657, 10585, 4988, + 657, 10585, 4990, + 657, 10585, 4992, + 657, 10585, 4994, + 657, 10585, 4996, + 657, 10585, 4998, + 657, 10585, 5020, + 657, 10585, 5022, + 657, 10585, 5024, + 657, 10585, 5028, + 657, 10585, 5058, + 657, 10585, 5060, + 657, 10585, 5062, + 657, 10585, 5064, + 657, 10585, 5066, + 657, 10585, 5068, + 657, 10585, 5070, + 657, 10585, 5072, + 657, 10585, 5074, + 657, 10585, 5076, + 657, 10585, 5078, + 657, 10585, 5080, + 657, 10585, 5082, + 657, 10585, 5084, + 657, 10585, 5086, + 657, 10585, 5088, + 657, 10585, 5090, + 657, 10585, 5092, + 657, 10585, 5094, + 657, 10585, 5096, + 657, 10585, 5098, + 657, 10585, 5102, + 657, 10585, 5104, + 657, 10585, 5106, + 657, 10585, 5108, + 657, 10585, 5110, + 657, 10585, 5112, + 657, 10585, 5116, + 657, 10585, 5118, + 657, 10585, 5120, + 657, 10585, 5122, + 657, 10585, 5124, + 657, 10585, 5126, + 657, 10585, 5128, + 657, 10585, 5138, + 657, 10585, 5142, + 657, 10585, 5144, + 657, 10585, 5148, + 657, 10585, 5150, + 657, 10585, 5162, + 657, 10585, 5172, + 657, 10585, 5174, + 657, 10585, 5176, + 657, 10585, 5180, + 657, 10585, 5186, + 657, 10585, 5188, + 657, 10585, 5196, + 657, 10585, 5198, + 657, 10585, 5200, + 657, 10585, 5202, + 657, 10585, 5206, + 657, 10585, 5208, + 657, 10585, 5210, + 657, 10585, 5212, + 657, 10585, 5214, + 657, 10585, 5216, + 657, 10585, 5218, + 657, 10585, 5220, + 657, 10585, 5222, + 657, 10585, 5224, + 657, 10585, 5226, + 657, 10585, 5246, + 657, 10585, 5248, + 657, 10585, 5250, + 657, 10585, 5252, + 657, 10585, 5254, + 657, 10585, 5256, + 657, 10585, 5258, + 657, 10585, 5260, + 657, 10585, 5262, + 657, 10585, 5264, + 657, 10585, 5266, + 657, 10585, 5268, + 657, 10585, 5270, + 657, 10585, 5272, + 657, 10585, 5274, + 657, 10585, 5276, + 657, 10585, 5282, + 657, 10585, 5284, + 657, 10585, 5286, + 657, 10585, 5302, + 657, 10585, 5304, + 657, 10585, 5308, + 657, 10585, 5310, + 657, 10585, 5318, + 657, 10585, 5320, + 657, 10585, 5322, + 657, 10585, 5324, + 657, 10585, 5326, + 657, 10585, 5328, + 657, 10585, 5330, + 657, 10585, 5334, + 657, 10585, 5336, + 657, 10585, 5338, + 657, 10585, 5340, + 657, 10585, 5342, + 657, 10585, 5344, + 657, 10585, 5346, + 657, 10585, 5348, + 657, 10585, 5350, + 657, 10585, 5352, + 657, 10585, 5354, + 657, 10585, 5356, + 657, 10585, 5358, + 657, 10585, 5360, + 657, 10585, 5362, + 657, 10585, 5364, + 657, 10585, 5366, + 657, 10585, 5368, + 657, 10585, 5426, + 657, 10585, 5428, + 657, 10585, 5454, + 657, 10585, 5456, + 657, 10585, 5458, + 657, 10585, 5468, + 657, 10585, 5488, + 657, 10585, 5490, + 657, 10585, 5492, + 657, 10585, 5498, + 657, 10585, 5500, + 657, 10585, 5502, + 657, 10585, 5504, + 657, 10585, 5516, + 657, 10585, 5570, + 657, 10585, 5574, + 657, 10585, 5576, + 657, 10585, 5578, + 657, 10585, 5580, + 657, 10585, 5582, + 657, 10585, 5584, + 657, 10585, 5586, + 657, 10585, 5588, + 657, 10585, 5590, + 657, 10585, 5592, + 657, 10585, 5594, + 657, 10585, 5596, + 657, 10585, 5598, + 657, 10585, 5600, + 657, 10585, 5602, + 657, 10585, 5608, + 657, 10585, 5610, + 657, 10585, 5612, + 657, 10585, 5618, + 657, 10585, 5672, + 657, 10585, 5674, + 657, 10585, 5676, + 657, 10585, 5684, + 657, 10585, 5686, + 657, 10585, 5688, + 657, 10585, 5712, + 657, 10585, 5714, + 657, 10585, 5716, + 657, 10585, 5722, + 657, 10585, 5724, + 657, 10585, 5726, + 657, 10585, 5728, + 657, 10585, 5730, + 657, 10585, 5742, + 657, 10585, 5744, + 657, 10585, 5746, + 657, 10585, 5748, + 657, 10585, 5752, + 657, 10585, 5754, + 657, 10585, 5788, + 657, 10585, 5790, + 657, 10585, 5792, + 657, 10585, 5796, + 657, 10585, 5798, + 657, 10585, 5800, + 657, 10585, 5802, + 657, 10585, 5804, + 657, 10585, 5806, + 657, 10585, 5808, + 657, 10585, 5810, + 657, 10585, 5812, + 657, 10585, 5814, + 657, 10585, 5816, + 657, 10585, 5818, + 657, 10585, 5820, + 657, 10585, 5822, + 657, 10585, 5824, + 657, 10585, 5826, + 657, 10585, 5848, + 657, 10585, 5850, + 657, 10585, 5856, + 657, 10585, 5864, + 657, 10585, 5936, + 657, 10585, 5938, + 657, 10585, 6014, + 657, 10585, 6016, + 657, 10585, 6018, + 657, 10585, 6022, + 657, 10585, 6084, + 657, 10585, 6086, + 657, 10585, 6088, + 657, 10585, 6094, + 657, 10585, 6096, + 657, 10585, 6134, + 657, 10585, 6136, + 657, 10585, 6140, + 657, 10585, 6142, + 657, 10585, 6144, + 657, 10585, 6146, + 657, 10585, 6156, + 657, 10585, 6206, + 657, 10585, 6208, + 657, 10585, 6210, + 657, 10585, 6238, + 657, 10585, 6240, + 657, 10585, 6242, + 657, 10585, 6244, + 657, 10585, 6252, + 657, 10585, 6266, + 657, 10585, 6270, + 657, 10585, 6272, + 657, 10585, 6276, + 657, 10585, 6278, + 657, 10585, 6280, + 657, 10585, 6284, + 657, 10585, 6286, + 657, 10585, 6288, + 657, 10585, 6290, + 657, 10585, 6292, + 657, 10585, 6294, + 657, 10585, 6296, + 657, 10585, 6298, + 657, 10585, 6304, + 657, 10585, 6306, + 657, 10585, 6308, + 657, 10585, 6310, + 657, 10585, 6314, + 657, 10585, 6316, + 657, 10585, 6320, + 657, 10585, 6322, + 657, 10585, 6324, + 657, 10585, 6326, + 657, 10585, 6330, + 657, 10585, 6332, + 657, 10585, 6334, + 657, 10585, 6338, + 657, 10585, 6340, + 657, 10585, 6342, + 657, 10585, 6344, + 657, 10585, 6346, + 657, 10585, 6348, + 657, 10585, 6350, + 657, 10585, 6352, + 657, 10585, 6354, + 657, 10585, 6356, + 657, 10585, 6358, + 657, 10585, 6360, + 657, 10585, 6362, + 657, 10585, 6364, + 657, 10585, 6366, + 657, 10585, 6470, + 657, 10585, 6472, + 657, 10585, 6474, + 657, 10585, 6476, + 657, 10585, 6478, + 657, 10585, 6480, + 657, 10585, 6584, + 657, 10585, 6586, + 657, 10585, 6588, + 657, 10585, 6590, + 657, 10585, 6592, + 657, 10585, 6660, + 657, 10585, 6662, + 657, 10585, 6664, + 657, 10585, 6666, + 657, 10585, 6668, + 657, 10585, 6834, + 657, 10585, 6836, + 657, 10585, 6838, + 657, 10585, 6840, + 657, 10585, 6842, + 657, 10585, 6844, + 657, 10585, 6916, + 657, 10585, 6918, + 657, 10585, 6920, + 657, 10585, 6922, + 657, 10585, 6924, + 657, 10585, 6926, + 657, 10585, 6928, + 657, 10585, 6930, + 657, 10585, 6932, + 657, 10585, 6934, + 657, 10585, 6936, + 657, 10585, 6938, + 657, 10585, 6940, + 657, 10585, 6942, + 657, 10585, 6944, + 657, 10585, 6946, + 657, 10585, 6962, + 657, 10585, 6964, + 657, 10585, 6966, + 657, 10585, 6968, + 657, 10585, 6970, + 657, 10585, 6972, + 657, 10585, 6998, + 657, 10585, 7000, + 657, 10585, 7002, + 657, 10585, 7004, + 657, 10585, 7006, + 657, 10585, 7008, + 657, 10585, 7156, + 657, 10585, 7158, + 657, 10585, 7160, + 657, 10585, 7162, + 657, 10585, 7212, + 657, 10585, 7214, + 657, 10585, 7216, + 657, 10585, 7218, + 657, 10585, 7220, + 657, 10585, 7224, + 657, 10585, 7234, + 657, 10585, 7236, + 657, 10585, 7240, + 657, 10585, 7242, + 657, 10585, 7250, + 657, 10585, 7252, + 657, 10585, 7254, + 657, 10585, 7256, + 657, 10585, 7258, + 657, 10585, 7260, + 657, 10585, 7278, + 657, 10585, 7280, + 657, 10585, 7286, + 657, 10585, 7288, + 657, 10585, 7290, + 657, 10585, 7292, + 657, 10585, 7294, + 657, 10585, 7296, + 657, 10585, 7298, + 657, 10585, 7300, + 657, 10585, 7302, + 657, 10585, 7304, + 657, 10585, 7456, + 657, 10585, 7458, + 657, 10585, 7460, + 657, 10585, 7552, + 657, 10585, 7554, + 657, 10585, 7556, + 657, 10585, 7564, + 657, 10585, 7620, + 657, 10585, 7622, + 657, 10585, 7624, + 657, 10585, 7876, + 657, 10585, 7878, + 657, 10585, 7880, + 657, 10585, 7882, + 657, 10585, 7894, + 657, 10585, 7896, + 657, 10585, 7898, + 657, 10585, 7900, + 657, 10585, 7902, + 705, 8694, + 719, 6741, 568, + 719, 13042, + 721, 6121, 1044, + 729, 11635, 8775, 601, 5707, 1546, + 729, 11635, 8775, 601, 5877, 1546, + 729, 11635, 8775, 601, 5877, 9546, + 729, 11635, 8775, 601, 5877, 10804, + 729, 11635, 8775, 601, 6543, 7708, + 729, 11635, 8775, 991, 7636, + 729, 11635, 8775, 991, 7708, + 729, 11635, 8775, 991, 10804, + 729, 11635, 8775, 1547, 10666, + 729, 11635, 8775, 1547, 10804, + 729, 11635, 8775, 2412, + 729, 11635, 8775, 4117, 5707, 7636, + 729, 11635, 8775, 4117, 5877, 1546, + 729, 11635, 8775, 4117, 5877, 10666, + 729, 11635, 8775, 4117, 6543, 7708, + 729, 11635, 8775, 4614, + 729, 11635, 8775, 4615, 10666, + 729, 11635, 8775, 4849, 5707, 7636, + 729, 11635, 8775, 5496, + 729, 11635, 8775, 5497, 601, 6542, + 729, 11635, 8775, 5497, 990, + 729, 11635, 8775, 5497, 1546, + 729, 11635, 8775, 5497, 2091, 6740, + 729, 11635, 8775, 5497, 4117, 6542, + 729, 11635, 8775, 5497, 6610, + 729, 11635, 8775, 5497, 6674, + 729, 11635, 8775, 5497, 6740, + 729, 11635, 8775, 5497, 7580, + 729, 11635, 8775, 5497, 8056, + 729, 11635, 8775, 5497, 8122, + 729, 11635, 8775, 5497, 9158, + 729, 11635, 8775, 5497, 9811, 6434, + 729, 11635, 8775, 5497, 10468, + 729, 11635, 8775, 5497, 10728, + 729, 11635, 8775, 5497, 10959, 6434, + 729, 11635, 8775, 5497, 11097, 6434, + 729, 11635, 8775, 5497, 11098, + 729, 11635, 8775, 5497, 11765, 6434, + 729, 11635, 8775, 5497, 12472, + 729, 11635, 8775, 5831, 10804, + 729, 11635, 8775, 6406, + 729, 11635, 8775, 6407, 10666, + 729, 11635, 8775, 6617, 760, + 729, 11635, 8775, 6675, 7636, + 729, 11635, 8775, 6675, 10666, + 729, 11635, 8775, 7316, + 729, 11635, 8775, 7317, 10666, + 729, 11635, 8775, 7415, 5496, + 729, 11635, 8775, 7415, 10666, + 729, 11635, 8775, 7581, 760, + 729, 11635, 8775, 7637, 7708, + 729, 11635, 8775, 7709, 10804, + 729, 11635, 8775, 7884, + 729, 11635, 8775, 8057, 1546, + 729, 11635, 8775, 8057, 5830, + 729, 11635, 8775, 8057, 7636, + 729, 11635, 8775, 8057, 10666, + 729, 11635, 8775, 8057, 10728, + 729, 11635, 8775, 8057, 10804, + 729, 11635, 8775, 8308, + 729, 11635, 8775, 8747, 5496, + 729, 11635, 8775, 9159, 10666, + 729, 11635, 8775, 9271, 10666, + 729, 11635, 8775, 9811, 6074, + 729, 11635, 8775, 10729, 760, + 729, 11635, 8775, 10959, 6074, + 729, 11635, 8775, 11097, 6074, + 729, 11635, 8775, 11225, 10666, + 729, 11635, 8775, 11765, 6074, + 729, 11635, 8775, 12473, 10804, + 730, + 789, 8774, + 807, 9633, 9718, + 807, 9718, + 827, 10145, 601, 6909, 721, 4117, 11649, 7100, + 827, 10145, 601, 6909, 721, 4849, 4117, 7100, + 827, 10145, 601, 6909, 721, 4849, 7100, + 827, 10145, 601, 6909, 721, 7443, 4117, 7100, + 827, 10145, 601, 6909, 721, 7443, 7100, + 827, 10145, 601, 6909, 721, 11649, 7100, + 827, 10145, 601, 7101, 721, 4117, 11649, 6908, + 827, 10145, 601, 7101, 721, 4849, 4117, 6908, + 827, 10145, 601, 7101, 721, 4849, 6908, + 827, 10145, 601, 7101, 721, 7443, 4117, 6908, + 827, 10145, 601, 7101, 721, 7443, 6908, + 827, 10145, 601, 7101, 721, 11649, 6908, + 827, 10145, 601, 8153, 721, 4849, 8716, + 827, 10145, 601, 8153, 721, 7443, 8716, + 827, 10145, 601, 8153, 721, 11649, 8716, + 827, 10145, 601, 8717, 721, 4849, 8152, + 827, 10145, 601, 8717, 721, 7443, 8152, + 827, 10145, 601, 8717, 721, 11649, 8152, + 827, 10145, 4117, 6909, 721, 601, 11649, 7100, + 827, 10145, 4117, 6909, 721, 4849, 601, 7100, + 827, 10145, 4117, 6909, 721, 4849, 7100, + 827, 10145, 4117, 6909, 721, 7443, 601, 7100, + 827, 10145, 4117, 6909, 721, 7443, 7100, + 827, 10145, 4117, 6909, 721, 11649, 7100, + 827, 10145, 4117, 7101, 721, 601, 11649, 6908, + 827, 10145, 4117, 7101, 721, 4849, 601, 6908, + 827, 10145, 4117, 7101, 721, 4849, 6908, + 827, 10145, 4117, 7101, 721, 7443, 601, 6908, + 827, 10145, 4117, 7101, 721, 7443, 6908, + 827, 10145, 4117, 7101, 721, 11649, 6908, + 827, 10145, 4117, 8153, 721, 4849, 8716, + 827, 10145, 4117, 8153, 721, 7443, 8716, + 827, 10145, 4117, 8153, 721, 11649, 8716, + 827, 10145, 4117, 8717, 721, 4849, 8152, + 827, 10145, 4117, 8717, 721, 7443, 8152, + 827, 10145, 4117, 8717, 721, 11649, 8152, + 827, 10145, 4849, 601, 6909, 721, 7443, 4117, 7100, + 827, 10145, 4849, 4117, 6909, 721, 7443, 601, 7100, + 827, 10145, 4849, 6909, 721, 7443, 601, 7100, + 827, 10145, 4849, 6909, 721, 7443, 4117, 7100, + 827, 10145, 4849, 6909, 721, 7443, 10677, 7100, + 827, 10145, 4849, 7101, 721, 7443, 601, 6908, + 827, 10145, 4849, 7101, 721, 7443, 4117, 6908, + 827, 10145, 4849, 7101, 721, 7443, 10677, 6908, + 827, 10145, 6909, 600, + 827, 10145, 6909, 601, 721, 4848, + 827, 10145, 6909, 601, 721, 7101, 4116, + 827, 10145, 6909, 601, 721, 7442, + 827, 10145, 6909, 601, 721, 11648, + 827, 10145, 6909, 4116, + 827, 10145, 6909, 4117, 721, 4848, + 827, 10145, 6909, 4117, 721, 7442, + 827, 10145, 6909, 4117, 721, 11648, + 827, 10145, 6909, 4848, + 827, 10145, 6909, 4849, 721, 7101, 7442, + 827, 10145, 6909, 7442, + 827, 10145, 6909, 8153, 3993, 10676, + 827, 10145, 6909, 8153, 3993, 11648, + 827, 10145, 6909, 8849, 3993, 10676, + 827, 10145, 6909, 8849, 3993, 11648, + 827, 10145, 6909, 10676, + 827, 10145, 6909, 10677, 721, 4848, + 827, 10145, 6909, 10677, 721, 7442, + 827, 10145, 6909, 10677, 721, 11648, + 827, 10145, 6909, 11191, 3993, 10676, + 827, 10145, 6909, 11191, 3993, 11648, + 827, 10145, 6909, 11648, + 827, 10145, 7101, 600, + 827, 10145, 7101, 601, 721, 4848, + 827, 10145, 7101, 601, 721, 6909, 4116, + 827, 10145, 7101, 601, 721, 7442, + 827, 10145, 7101, 601, 721, 11648, + 827, 10145, 7101, 731, 601, 721, 4848, + 827, 10145, 7101, 731, 601, 721, 7442, + 827, 10145, 7101, 731, 4117, 721, 4848, + 827, 10145, 7101, 731, 4117, 721, 7442, + 827, 10145, 7101, 4116, + 827, 10145, 7101, 4117, 721, 4848, + 827, 10145, 7101, 4117, 721, 7442, + 827, 10145, 7101, 4117, 721, 11648, + 827, 10145, 7101, 4848, + 827, 10145, 7101, 4849, 721, 6909, 7442, + 827, 10145, 7101, 7442, + 827, 10145, 7101, 8153, 3993, 10676, + 827, 10145, 7101, 8153, 3993, 11648, + 827, 10145, 7101, 8849, 3993, 10676, + 827, 10145, 7101, 8849, 3993, 11648, + 827, 10145, 7101, 10001, 6622, + 827, 10145, 7101, 10001, 7773, 4849, 569, 7121, 7442, + 827, 10145, 7101, 10001, 7773, 7443, 569, 7121, 4848, + 827, 10145, 7101, 10676, + 827, 10145, 7101, 10677, 721, 4848, + 827, 10145, 7101, 10677, 721, 7442, + 827, 10145, 7101, 10677, 721, 11648, + 827, 10145, 7101, 11191, 3993, 10676, + 827, 10145, 7101, 11191, 3993, 11648, + 827, 10145, 7101, 11648, + 827, 10145, 7443, 601, 6909, 721, 4849, 4117, 7100, + 827, 10145, 7443, 4117, 6909, 721, 4849, 601, 7100, + 827, 10145, 7443, 6909, 721, 4849, 601, 7100, + 827, 10145, 7443, 6909, 721, 4849, 4117, 7100, + 827, 10145, 7443, 6909, 721, 4849, 10677, 7100, + 827, 10145, 7443, 7101, 721, 4849, 601, 6908, + 827, 10145, 7443, 7101, 721, 4849, 4117, 6908, + 827, 10145, 7443, 7101, 721, 4849, 10677, 6908, + 827, 10145, 8153, 601, 721, 4848, + 827, 10145, 8153, 601, 721, 7442, + 827, 10145, 8153, 601, 721, 11648, + 827, 10145, 8153, 4117, 721, 4848, + 827, 10145, 8153, 4117, 721, 7442, + 827, 10145, 8153, 4117, 721, 11648, + 827, 10145, 8153, 10676, + 827, 10145, 8153, 10677, 721, 4848, + 827, 10145, 8153, 10677, 721, 7442, + 827, 10145, 8153, 10677, 721, 11648, + 827, 10145, 8153, 11648, + 827, 10145, 10677, 6909, 721, 4849, 7100, + 827, 10145, 10677, 6909, 721, 7443, 7100, + 827, 10145, 10677, 6909, 721, 11649, 7100, + 827, 10145, 10677, 7101, 721, 4849, 6908, + 827, 10145, 10677, 7101, 721, 7443, 6908, + 827, 10145, 10677, 7101, 721, 11649, 6908, + 827, 10145, 10677, 8153, 721, 4849, 8716, + 827, 10145, 10677, 8153, 721, 7443, 8716, + 827, 10145, 10677, 8153, 721, 11649, 8716, + 827, 10145, 10677, 8717, 721, 4849, 8152, + 827, 10145, 10677, 8717, 721, 7443, 8152, + 827, 10145, 10677, 8717, 721, 11649, 8152, + 889, 2412, + 909, 8759, 6, + 909, 8759, 14, + 909, 8759, 26, + 909, 8759, 30, + 909, 8759, 32, + 909, 8759, 36, + 909, 8759, 38, + 909, 8759, 240, + 909, 8759, 248, + 909, 8759, 254, + 909, 8759, 466, + 909, 8759, 472, + 909, 8759, 494, + 909, 8759, 528, + 909, 8759, 538, + 909, 8759, 544, + 909, 8759, 550, + 909, 8759, 554, + 909, 8759, 566, + 909, 8759, 628, + 909, 8759, 642, + 909, 8759, 844, + 909, 8759, 1458, + 909, 8759, 1460, + 909, 8759, 1462, + 909, 8759, 1464, + 909, 8759, 2602, + 909, 8759, 2608, + 909, 8759, 2630, + 909, 8759, 4542, + 909, 8759, 4584, + 909, 8759, 4586, + 909, 8759, 4588, + 909, 8759, 4590, + 909, 8759, 5872, + 909, 8759, 6974, + 909, 9617, 826, + 909, 9617, 920, + 909, 9617, 1036, + 909, 9617, 1093, 2170, + 909, 9617, 1093, 2778, + 909, 9617, 1093, 7694, + 909, 9617, 1132, + 909, 9617, 1136, + 909, 9617, 2025, 2170, + 909, 9617, 2025, 2778, + 909, 9617, 2025, 4214, + 909, 9617, 2025, 7694, + 909, 9617, 2166, + 909, 9617, 2201, 2170, + 909, 9617, 2201, 2778, + 909, 9617, 2386, + 909, 9617, 2390, + 909, 9617, 2586, + 909, 9617, 3794, + 909, 9617, 3805, 429, 6604, + 909, 9617, 3806, + 909, 9617, 3940, + 909, 9617, 4194, + 909, 9617, 4208, + 909, 9617, 4390, + 909, 9617, 4398, + 909, 9617, 4536, + 909, 9617, 4628, + 909, 9617, 4835, 2170, + 909, 9617, 4835, 2778, + 909, 9617, 4835, 4214, + 909, 9617, 4835, 7694, + 909, 9617, 4895, 2170, + 909, 9617, 4895, 2778, + 909, 9617, 4940, + 909, 9617, 4950, + 909, 9617, 5012, + 909, 9617, 5524, + 909, 9617, 5646, + 909, 9617, 5764, + 909, 9617, 6101, 2170, + 909, 9617, 6101, 2778, + 909, 9617, 6113, 2170, + 909, 9617, 6113, 2778, + 909, 9617, 6521, 2170, + 909, 9617, 6521, 2778, + 909, 9617, 6578, + 909, 9617, 6600, + 909, 9617, 6670, + 909, 9617, 6852, + 909, 9617, 6873, 2170, + 909, 9617, 6873, 2778, + 909, 9617, 6873, 7694, + 909, 9617, 6907, 2170, + 909, 9617, 6907, 2778, + 909, 9617, 7057, 2170, + 909, 9617, 7057, 2778, + 909, 9617, 7185, 2170, + 909, 9617, 7185, 2778, + 909, 9617, 7526, + 909, 9617, 7593, 2170, + 909, 9617, 7593, 2778, + 909, 9617, 7600, + 909, 9617, 7603, 2170, + 909, 9617, 7603, 2778, + 909, 9617, 7662, + 909, 9617, 7704, + 909, 9617, 7813, 2170, + 909, 9617, 7813, 2778, + 909, 9617, 7974, + 909, 9617, 8484, + 909, 9617, 8486, + 909, 9617, 8576, + 909, 9617, 8640, + 909, 9617, 8681, 2170, + 909, 9617, 8681, 2778, + 909, 9617, 8681, 7694, + 909, 9617, 8735, 2170, + 909, 9617, 8735, 2778, + 909, 9617, 8824, + 909, 9617, 8870, + 909, 9617, 9102, + 909, 9617, 9948, + 909, 9617, 11488, + 909, 9617, 11803, 4389, 5969, 7736, + 909, 9617, 11803, 4536, + 909, 9617, 11803, 6100, + 909, 9617, 11803, 7816, + 909, 9617, 11803, 8946, + 909, 9617, 12419, 1092, + 909, 9617, 12419, 1170, + 909, 9617, 12419, 2504, + 909, 9617, 12419, 3788, + 909, 9617, 12419, 3850, + 909, 9617, 12419, 4172, + 909, 9617, 12419, 4196, + 909, 9617, 12419, 4218, + 909, 9617, 12419, 4244, + 909, 9617, 12419, 4342, + 909, 9617, 12419, 4844, + 909, 9617, 12419, 4894, + 909, 9617, 12419, 5632, + 909, 9617, 12419, 5764, + 909, 9617, 12419, 6116, + 909, 9617, 12419, 6952, + 909, 9617, 12419, 7532, + 909, 9617, 12419, 7726, + 909, 9617, 12419, 8154, + 909, 9617, 12419, 8730, + 909, 9617, 12419, 8793, 9426, + 909, 9617, 12419, 8870, + 909, 9617, 12495, 4172, + 909, 9617, 12495, 7726, + 909, 9617, 12495, 8154, + 909, 9617, 12495, 8870, + 1009, 8178, + 1009, 8180, + 1009, 8182, + 1009, 8184, + 1009, 8186, + 1009, 8188, + 1045, 5444, + 1045, 6376, + 1045, 7172, + 1045, 10374, + 1109, 429, 7394, + 1177, 718, + 1429, 9730, + 1429, 9912, + 1635, 5758, + 1741, 247, 380, + 1741, 247, 412, + 1741, 323, 332, + 1741, 5965, 1859, 170, + 1741, 5965, 1859, 564, + 1741, 5965, 1859, 2684, + 1741, 5965, 1859, 8034, + 1741, 6689, 2170, + 1741, 6689, 2540, + 1741, 6689, 2778, + 1741, 6689, 4200, + 1741, 6689, 4214, + 1741, 6689, 5190, + 1741, 6689, 6260, + 1741, 6689, 6722, + 1741, 6689, 7508, + 1741, 6689, 7694, + 1741, 7803, 5759, 0, + 1741, 7803, 5759, 8, + 1741, 7803, 5759, 16, + 1741, 7803, 5759, 28, + 1741, 7803, 5759, 40, + 1741, 7803, 5759, 48, + 1741, 7803, 5759, 58, + 1741, 7803, 5759, 72, + 1741, 7803, 5759, 78, + 1741, 7803, 5759, 98, + 1741, 7803, 5759, 168, + 1741, 7803, 5759, 266, + 1741, 7803, 5759, 606, + 1741, 7803, 5759, 668, + 1741, 7803, 5759, 1859, 1588, + 1741, 7803, 5759, 1859, 1658, + 1741, 8405, 28, + 1741, 8405, 108, + 1741, 8405, 130, + 1741, 8405, 150, + 1741, 8405, 209, 2646, + 1741, 8405, 209, 5846, + 1741, 8405, 247, 2646, + 1741, 8405, 247, 5846, + 1741, 8405, 322, + 1741, 8405, 351, 4878, + 1741, 8405, 351, 4898, + 1741, 8405, 380, + 1741, 8405, 412, + 1741, 8405, 480, + 1741, 8405, 537, 2646, + 1741, 8405, 537, 5846, + 1741, 8405, 568, + 1741, 8405, 632, + 1741, 8405, 660, + 1741, 8405, 1619, 2646, + 1741, 8405, 1619, 5846, + 1741, 8405, 2038, + 1741, 8405, 2134, + 1741, 8405, 2219, 2646, + 1741, 8405, 2219, 5846, + 1741, 8405, 2685, 2646, + 1741, 8405, 2685, 5846, + 1741, 10154, + 1741, 11134, + 1741, 11227, 5759, 350, + 1741, 11227, 5759, 2134, + 1741, 12421, 4926, + 1764, + 1809, 4876, + 1809, 8153, 7391, 11195, 4926, + 1809, 9898, + 2027, 2643, 1817, 5759, 1734, + 2027, 2643, 1817, 5759, 4826, + 2027, 2643, 1817, 5965, 8442, + 2027, 2643, 1817, 5965, 8444, + 2027, 2643, 1817, 6689, 2170, + 2027, 2643, 1817, 6689, 2540, + 2027, 2643, 1817, 6689, 2778, + 2027, 2643, 1817, 6689, 4200, + 2027, 2643, 1817, 6689, 4214, + 2027, 2643, 1817, 6689, 5190, + 2027, 2643, 1817, 6689, 6260, + 2027, 2643, 1817, 6689, 6722, + 2027, 2643, 1817, 6689, 7508, + 2027, 2643, 1817, 6689, 7694, + 2027, 2643, 1817, 7803, 5759, 8, + 2027, 2643, 1817, 7803, 5759, 28, + 2027, 2643, 1817, 7803, 5759, 40, + 2027, 2643, 1817, 7803, 5759, 58, + 2027, 2643, 1817, 7803, 5759, 66, + 2027, 2643, 1817, 7803, 5759, 98, + 2027, 2643, 1817, 7803, 5759, 266, + 2027, 2643, 1817, 7803, 5759, 290, + 2027, 2643, 1817, 7803, 5759, 422, + 2027, 2643, 1817, 7803, 5759, 458, + 2027, 2643, 1817, 7803, 5759, 590, + 2027, 2643, 1817, 7803, 5759, 606, + 2027, 2643, 1817, 7803, 5759, 608, + 2027, 2643, 1817, 7803, 5759, 700, + 2027, 2643, 1817, 7803, 5759, 2156, + 2027, 2643, 1817, 7803, 5759, 2806, + 2027, 2643, 1817, 7803, 5759, 7803, 11238, + 2027, 2643, 1817, 8405, 1809, 100, + 2027, 2643, 1817, 8405, 1809, 138, + 2027, 2643, 1817, 8405, 1809, 196, + 2027, 2643, 1817, 8405, 1809, 236, + 2027, 2643, 1817, 8405, 1809, 306, + 2027, 2643, 1817, 8405, 1809, 332, + 2027, 2643, 1817, 8405, 1809, 364, + 2027, 2643, 1817, 8405, 1809, 392, + 2027, 2643, 1817, 8405, 1809, 462, + 2027, 2643, 1817, 8405, 1809, 496, + 2027, 2643, 1817, 8405, 1809, 524, + 2027, 2643, 1817, 8405, 1809, 556, + 2027, 2643, 1817, 8405, 1809, 610, + 2027, 2643, 1817, 8405, 1809, 638, + 2027, 2643, 1817, 8405, 1809, 652, + 2027, 2643, 1817, 8405, 1809, 1702, + 2027, 2643, 1817, 8405, 1809, 2030, + 2027, 2643, 1817, 8405, 1809, 2212, + 2027, 2643, 1817, 8405, 1809, 2678, + 2027, 2643, 1817, 8405, 1809, 2732, + 2027, 2643, 1817, 8405, 1809, 2980, + 2027, 2643, 1817, 8405, 4423, 100, + 2027, 2643, 1817, 8405, 4423, 138, + 2027, 2643, 1817, 8405, 4423, 196, + 2027, 2643, 1817, 8405, 4423, 236, + 2027, 2643, 1817, 8405, 4423, 306, + 2027, 2643, 1817, 8405, 4423, 332, + 2027, 2643, 1817, 8405, 4423, 364, + 2027, 2643, 1817, 8405, 4423, 392, + 2027, 2643, 1817, 8405, 4423, 462, + 2027, 2643, 1817, 8405, 4423, 496, + 2027, 2643, 1817, 8405, 4423, 524, + 2027, 2643, 1817, 8405, 4423, 556, + 2027, 2643, 1817, 8405, 4423, 610, + 2027, 2643, 1817, 8405, 4423, 638, + 2027, 2643, 1817, 8405, 4423, 652, + 2027, 2643, 1817, 8405, 4423, 1702, + 2027, 2643, 1817, 8405, 4423, 2030, + 2027, 2643, 1817, 8405, 4423, 2212, + 2027, 2643, 1817, 8405, 4423, 2678, + 2027, 2643, 1817, 8405, 4423, 2732, + 2027, 2643, 1817, 8405, 4423, 2980, + 2027, 2643, 1817, 8405, 6789, 2, + 2027, 2643, 1817, 8405, 6789, 6, + 2027, 2643, 1817, 8405, 6789, 20, + 2027, 2643, 1817, 8405, 6789, 24, + 2027, 2643, 1817, 8405, 6789, 26, + 2027, 2643, 1817, 8405, 6789, 42, + 2027, 2643, 1817, 8405, 6789, 400, + 2027, 8701, 5758, + 2075, 1809, 5965, 11424, + 2075, 4423, 5965, 11424, + 2075, 6616, + 2075, 6689, 2170, + 2075, 6689, 2540, + 2075, 6689, 2778, + 2075, 6689, 4200, + 2075, 6689, 4214, + 2075, 6689, 5190, + 2075, 6689, 6260, + 2075, 6689, 6722, + 2075, 6689, 7508, + 2075, 6689, 7694, + 2075, 8405, 0, + 2075, 8405, 8, + 2075, 8405, 16, + 2075, 8405, 26, + 2075, 8405, 28, + 2075, 8405, 40, + 2075, 8405, 100, + 2075, 8405, 138, + 2075, 8405, 162, + 2075, 8405, 196, + 2075, 8405, 236, + 2075, 8405, 292, + 2075, 8405, 306, + 2075, 8405, 332, + 2075, 8405, 364, + 2075, 8405, 392, + 2075, 8405, 393, 8936, + 2075, 8405, 440, + 2075, 8405, 462, + 2075, 8405, 510, + 2075, 8405, 524, + 2075, 8405, 556, + 2075, 8405, 622, + 2075, 8405, 652, + 2075, 8405, 884, + 2075, 8405, 1228, + 2075, 8405, 2126, + 2075, 8405, 2127, 8936, + 2075, 8405, 2438, + 2075, 8405, 4679, 292, + 2075, 8405, 4679, 510, + 2075, 8405, 4679, 884, + 2075, 8405, 11470, + 2075, 8775, 441, 8104, + 2075, 8775, 11636, + 2075, 10767, 4895, 1809, 5964, + 2075, 10767, 4895, 4423, 5964, + 2075, 10767, 4895, 8649, 5964, + 2075, 10767, 4895, 11475, 5964, + 2075, 10767, 7551, 1809, 5964, + 2075, 10767, 7551, 4423, 5964, + 2075, 10767, 7551, 8649, 5964, + 2075, 10767, 8153, 1045, 6376, + 2075, 10767, 12511, 4926, + 2075, 11672, + 2075, 12017, 4926, + 2088, + 2091, 1, 8763, 428, + 2091, 1, 10579, 428, + 2091, 81, 9263, 428, + 2091, 5758, + 2091, 5972, + 2091, 6569, 4926, + 2091, 6741, 568, + 2091, 7708, + 2091, 7919, 6741, 568, + 2091, 8521, 10573, 428, + 2091, 8521, 10573, 429, 445, 6741, 568, + 2091, 8745, 6989, 429, 445, 6741, 568, + 2091, 8745, 10379, 429, 445, 6741, 568, + 2091, 10411, 568, + 2091, 11041, 568, + 2091, 11098, + 2091, 11621, 568, + 2091, 12472, + 2091, 13045, 6741, 568, + 2159, 825, 2690, + 2159, 3771, 8020, + 2159, 3992, + 2159, 4210, + 2159, 4530, + 2159, 6564, + 2159, 7921, 429, 6568, + 2159, 8009, 3711, 13054, + 2159, 8153, 10728, + 2159, 9973, 8975, 8524, + 2159, 10267, 4210, + 2163, 5758, + 2167, 8325, 8405, 0, + 2167, 8325, 8405, 8, + 2167, 8325, 8405, 16, + 2167, 8325, 8405, 28, + 2167, 8325, 8405, 40, + 2167, 8325, 8405, 102, + 2167, 8325, 8405, 142, + 2167, 8325, 8405, 164, + 2167, 8325, 8405, 172, + 2167, 8325, 8405, 174, + 2167, 8325, 8405, 176, + 2167, 8325, 8405, 182, + 2167, 8325, 8405, 184, + 2167, 8325, 8405, 238, + 2167, 8325, 8405, 266, + 2167, 8325, 8405, 306, + 2167, 8325, 8405, 310, + 2167, 8325, 8405, 326, + 2167, 8325, 8405, 468, + 2167, 8325, 8405, 560, + 2167, 8325, 8405, 606, + 2167, 8325, 8405, 612, + 2167, 8325, 8405, 672, + 2167, 8325, 8405, 886, + 2167, 8325, 8405, 1106, + 2167, 8325, 8405, 1122, + 2167, 8325, 8405, 1124, + 2167, 8325, 8405, 1614, + 2167, 8325, 8405, 2214, + 2167, 8325, 8405, 2518, + 2167, 8325, 8405, 2680, + 2167, 8325, 9513, 2170, + 2167, 8325, 9513, 2670, + 2167, 8325, 9513, 4200, + 2167, 8325, 9513, 6784, + 2167, 9583, 5759, 0, + 2167, 9583, 5759, 16, + 2167, 9583, 5759, 40, + 2167, 9583, 5759, 100, + 2167, 9583, 5759, 116, + 2167, 9583, 5759, 138, + 2167, 9583, 5759, 144, + 2167, 9583, 5759, 152, + 2167, 9583, 5759, 196, + 2167, 9583, 5759, 216, + 2167, 9583, 5759, 230, + 2167, 9583, 5759, 236, + 2167, 9583, 5759, 292, + 2167, 9583, 5759, 296, + 2167, 9583, 5759, 306, + 2167, 9583, 5759, 326, + 2167, 9583, 5759, 332, + 2167, 9583, 5759, 364, + 2167, 9583, 5759, 374, + 2167, 9583, 5759, 384, + 2167, 9583, 5759, 392, + 2167, 9583, 5759, 416, + 2167, 9583, 5759, 462, + 2167, 9583, 5759, 510, + 2167, 9583, 5759, 520, + 2167, 9583, 5759, 524, + 2167, 9583, 5759, 556, + 2167, 9583, 5759, 576, + 2167, 9583, 5759, 610, + 2167, 9583, 5759, 614, + 2167, 9583, 5759, 638, + 2167, 9583, 5759, 652, + 2167, 9583, 5759, 670, + 2167, 9583, 5759, 2516, + 2167, 9583, 5759, 2566, + 2167, 9583, 5759, 2678, + 2167, 9583, 5759, 3700, + 2167, 9583, 5759, 9058, + 2167, 9583, 5759, 10790, + 2167, 9583, 5759, 11436, + 2167, 9583, 5759, 11926, + 2167, 9583, 5759, 12408, + 2167, 9583, 5759, 12410, + 2167, 9583, 5759, 12896, + 2167, 9583, 6129, 9178, + 2167, 9583, 8525, 2170, + 2167, 9583, 8525, 2670, + 2167, 9583, 8525, 2778, + 2167, 9583, 8525, 8876, + 2167, 9583, 8525, 9344, + 2171, 1045, 5387, 2779, 4113, 12132, + 2171, 1045, 8392, + 2209, 2671, 10625, 5758, + 2209, 5758, + 2209, 7171, 5758, + 2241, 11945, 11632, + 2511, 7172, + 2541, 9601, 6505, 5830, + 2541, 10425, 6505, 721, 7821, 10194, + 2586, + 2639, 1809, 4876, + 2639, 4223, 5836, + 2639, 4849, 6627, 9050, + 2639, 4849, 8745, 9050, + 2639, 4849, 12114, + 2639, 5445, 5758, + 2639, 6610, + 2639, 6616, + 2639, 6689, 2170, + 2639, 6689, 2540, + 2639, 6689, 2778, + 2639, 6689, 4200, + 2639, 6689, 4214, + 2639, 6689, 5190, + 2639, 6689, 6260, + 2639, 6689, 6722, + 2639, 6689, 7508, + 2639, 6689, 7694, + 2639, 6875, 7908, + 2639, 7089, 7593, 8405, 0, + 2639, 7089, 7593, 8405, 2, + 2639, 7089, 7593, 8405, 4, + 2639, 7089, 7593, 8405, 6, + 2639, 7089, 7593, 8405, 8, + 2639, 7089, 7593, 8405, 10, + 2639, 7089, 7593, 8405, 12, + 2639, 7089, 7593, 8405, 14, + 2639, 7089, 7593, 8405, 16, + 2639, 7089, 7593, 8405, 18, + 2639, 7089, 7593, 8405, 20, + 2639, 7089, 7593, 8405, 22, + 2639, 7089, 7593, 8405, 24, + 2639, 7089, 7593, 8405, 26, + 2639, 7089, 7593, 8405, 28, + 2639, 7089, 7593, 8405, 30, + 2639, 7089, 7593, 8405, 32, + 2639, 7089, 7593, 8405, 34, + 2639, 7089, 7593, 8405, 36, + 2639, 7089, 7593, 8405, 38, + 2639, 7089, 7593, 8405, 40, + 2639, 7089, 7593, 8405, 42, + 2639, 7089, 7593, 8405, 44, + 2639, 7089, 7593, 8405, 46, + 2639, 7089, 7593, 8405, 48, + 2639, 7089, 7593, 8405, 50, + 2639, 7089, 9063, 8405, 0, + 2639, 7089, 9063, 8405, 2, + 2639, 7089, 9063, 8405, 4, + 2639, 7089, 9063, 8405, 6, + 2639, 7089, 9063, 8405, 8, + 2639, 7089, 9063, 8405, 10, + 2639, 7089, 9063, 8405, 12, + 2639, 7089, 9063, 8405, 14, + 2639, 7089, 9063, 8405, 16, + 2639, 7089, 9063, 8405, 18, + 2639, 7089, 9063, 8405, 20, + 2639, 7089, 9063, 8405, 22, + 2639, 7089, 9063, 8405, 24, + 2639, 7089, 9063, 8405, 26, + 2639, 7089, 9063, 8405, 28, + 2639, 7089, 9063, 8405, 30, + 2639, 7089, 9063, 8405, 32, + 2639, 7089, 9063, 8405, 34, + 2639, 7089, 9063, 8405, 36, + 2639, 7089, 9063, 8405, 38, + 2639, 7089, 9063, 8405, 40, + 2639, 7089, 9063, 8405, 42, + 2639, 7089, 9063, 8405, 44, + 2639, 7089, 9063, 8405, 46, + 2639, 7089, 9063, 8405, 48, + 2639, 7089, 9063, 8405, 50, + 2639, 7443, 6627, 9050, + 2639, 7443, 8745, 9050, + 2639, 7443, 12114, + 2639, 7608, + 2639, 7708, + 2639, 8129, 5758, + 2639, 8167, 5758, + 2639, 8525, 5758, + 2639, 9581, 5758, + 2639, 9633, 9718, + 2639, 9718, + 2639, 9898, + 2639, 10469, 4926, + 2639, 10677, 4876, + 2639, 10708, + 2639, 11099, 5758, + 2639, 11195, 4926, + 2639, 11224, + 2639, 11424, + 2639, 11449, 7908, + 2639, 11451, 90, + 2639, 12017, 4926, + 2639, 12473, 5758, + 2639, 12478, + 2643, 337, 8405, 0, + 2643, 337, 8405, 8, + 2643, 337, 8405, 16, + 2643, 337, 8405, 28, + 2643, 337, 8405, 40, + 2643, 337, 8405, 72, + 2643, 337, 8405, 162, + 2643, 337, 8405, 166, + 2643, 337, 8405, 196, + 2643, 337, 8405, 236, + 2643, 337, 8405, 306, + 2643, 337, 8405, 332, + 2643, 337, 8405, 364, + 2643, 337, 8405, 392, + 2643, 337, 8405, 440, + 2643, 337, 8405, 462, + 2643, 337, 8405, 496, + 2643, 337, 8405, 524, + 2643, 337, 8405, 556, + 2643, 337, 8405, 590, + 2643, 337, 8405, 610, + 2643, 337, 8405, 638, + 2643, 337, 8405, 652, + 2643, 337, 8405, 738, + 2643, 337, 8405, 1612, + 2643, 337, 8405, 2030, + 2643, 337, 8405, 2212, + 2643, 337, 8405, 2678, + 2643, 337, 8405, 2732, + 2643, 337, 8405, 5978, + 2643, 337, 8405, 8834, + 2643, 337, 8405, 8836, + 2643, 337, 8405, 8838, + 2643, 337, 8405, 8840, + 2643, 337, 8405, 8842, + 2691, 5387, 10256, + 2725, 731, 10763, 6435, 6121, 7172, + 2725, 731, 12901, 6434, + 2725, 731, 12901, 6435, 6121, 5444, + 2725, 4389, 10260, + 2725, 4849, 3958, + 2725, 4849, 4389, 9050, + 2725, 4849, 8076, + 2725, 6627, 9050, + 2725, 7443, 3958, + 2725, 7443, 4389, 9050, + 2725, 7443, 8076, + 2725, 8745, 9050, + 2725, 10637, 7533, 9050, + 2725, 12114, + 2779, 1045, 8392, + 2779, 1045, 12132, + 2779, 4113, 5387, 2171, 1045, 12132, + 2779, 8329, 9734, + 2779, 9437, 445, 10374, + 2779, 9437, 721, 10374, + 2779, 10725, 8993, 11876, + 2779, 11913, 8167, 7570, + 2779, 12491, 9437, 444, + 2779, 12491, 9437, 720, + 2847, 4223, 5836, + 2847, 6616, + 2847, 6689, 2170, + 2847, 6689, 2540, + 2847, 6689, 2778, + 2847, 6689, 4200, + 2847, 6689, 4214, + 2847, 6689, 5190, + 2847, 6689, 6260, + 2847, 6689, 6722, + 2847, 6689, 7508, + 2847, 6689, 7694, + 2847, 8775, 1140, + 2847, 8775, 2052, + 2847, 8775, 2634, + 2847, 8775, 3708, + 2847, 8775, 3986, + 2847, 8775, 4100, + 2847, 8775, 4680, + 2847, 8775, 4784, + 2847, 8775, 5944, + 2847, 8775, 5966, + 2847, 8775, 6700, + 2847, 8775, 6776, + 2847, 8775, 7032, + 2847, 10469, 4926, + 2847, 10585, 0, + 2847, 10585, 8, + 2847, 10585, 16, + 2847, 10585, 28, + 2847, 10585, 40, + 2847, 10585, 80, + 2847, 10585, 100, + 2847, 10585, 102, + 2847, 10585, 106, + 2847, 10585, 108, + 2847, 10585, 112, + 2847, 10585, 116, + 2847, 10585, 122, + 2847, 10585, 126, + 2847, 10585, 130, + 2847, 10585, 132, + 2847, 10585, 138, + 2847, 10585, 142, + 2847, 10585, 144, + 2847, 10585, 150, + 2847, 10585, 152, + 2847, 10585, 162, + 2847, 10585, 176, + 2847, 10585, 196, + 2847, 10585, 198, + 2847, 10585, 202, + 2847, 10585, 208, + 2847, 10585, 210, + 2847, 10585, 216, + 2847, 10585, 220, + 2847, 10585, 224, + 2847, 10585, 228, + 2847, 10585, 230, + 2847, 10585, 236, + 2847, 10585, 238, + 2847, 10585, 242, + 2847, 10585, 246, + 2847, 10585, 250, + 2847, 10585, 274, + 2847, 10585, 292, + 2847, 10585, 294, + 2847, 10585, 296, + 2847, 10585, 298, + 2847, 10585, 300, + 2847, 10585, 306, + 2847, 10585, 310, + 2847, 10585, 314, + 2847, 10585, 322, + 2847, 10585, 326, + 2847, 10585, 332, + 2847, 10585, 336, + 2847, 10585, 340, + 2847, 10585, 350, + 2847, 10585, 354, + 2847, 10585, 364, + 2847, 10585, 368, + 2847, 10585, 374, + 2847, 10585, 380, + 2847, 10585, 384, + 2847, 10585, 392, + 2847, 10585, 396, + 2847, 10585, 400, + 2847, 10585, 404, + 2847, 10585, 412, + 2847, 10585, 416, + 2847, 10585, 438, + 2847, 10585, 440, + 2847, 10585, 462, + 2847, 10585, 468, + 2847, 10585, 476, + 2847, 10585, 480, + 2847, 10585, 486, + 2847, 10585, 510, + 2847, 10585, 512, + 2847, 10585, 514, + 2847, 10585, 516, + 2847, 10585, 520, + 2847, 10585, 524, + 2847, 10585, 526, + 2847, 10585, 532, + 2847, 10585, 536, + 2847, 10585, 546, + 2847, 10585, 556, + 2847, 10585, 560, + 2847, 10585, 564, + 2847, 10585, 568, + 2847, 10585, 576, + 2847, 10585, 596, + 2847, 10585, 610, + 2847, 10585, 612, + 2847, 10585, 614, + 2847, 10585, 616, + 2847, 10585, 618, + 2847, 10585, 622, + 2847, 10585, 626, + 2847, 10585, 630, + 2847, 10585, 632, + 2847, 10585, 634, + 2847, 10585, 652, + 2847, 10585, 654, + 2847, 10585, 656, + 2847, 10585, 660, + 2847, 10585, 664, + 2847, 10585, 670, + 2847, 10585, 672, + 2847, 10585, 676, + 2847, 10585, 678, + 2847, 10585, 680, + 2847, 10585, 778, + 2847, 10585, 792, + 2847, 10585, 794, + 2847, 10585, 796, + 2847, 10585, 798, + 2847, 10585, 800, + 2847, 10585, 818, + 2847, 10585, 876, + 2847, 10585, 914, + 2847, 10585, 984, + 2847, 10585, 996, + 2847, 10585, 998, + 2847, 10585, 1000, + 2847, 10585, 1002, + 2847, 10585, 1004, + 2847, 10585, 1040, + 2847, 10585, 1098, + 2847, 10585, 1150, + 2847, 10585, 1172, + 2847, 10585, 1228, + 2847, 10585, 1230, + 2847, 10585, 1232, + 2847, 10585, 1234, + 2847, 10585, 1236, + 2847, 10585, 1238, + 2847, 10585, 1240, + 2847, 10585, 1290, + 2847, 10585, 1346, + 2847, 10585, 1356, + 2847, 10585, 1362, + 2847, 10585, 1384, + 2847, 10585, 1422, + 2847, 10585, 1424, + 2847, 10585, 1436, + 2847, 10585, 1506, + 2847, 10585, 1542, + 2847, 10585, 1588, + 2847, 10585, 1598, + 2847, 10585, 1660, + 2847, 10585, 1668, + 2847, 10585, 1670, + 2847, 10585, 1672, + 2847, 10585, 1674, + 2847, 10585, 1676, + 2847, 10585, 1758, + 2847, 10585, 1802, + 2847, 10585, 1878, + 2847, 10585, 1880, + 2847, 10585, 1882, + 2847, 10585, 1884, + 2847, 10585, 1886, + 2847, 10585, 1890, + 2847, 10585, 1938, + 2847, 10585, 2006, + 2847, 10585, 2008, + 2847, 10585, 2010, + 2847, 10585, 2012, + 2847, 10585, 2014, + 2847, 10585, 2016, + 2847, 10585, 2062, + 2847, 10585, 2064, + 2847, 10585, 2066, + 2847, 10585, 2068, + 2847, 10585, 2070, + 2847, 10585, 2084, + 2847, 10585, 2126, + 2847, 10585, 2130, + 2847, 10585, 2132, + 2847, 10585, 2134, + 2847, 10585, 2136, + 2847, 10585, 2178, + 2847, 10585, 2204, + 2847, 10585, 2238, + 2847, 10585, 2402, + 2847, 10585, 2430, + 2847, 10585, 2504, + 2847, 10585, 2516, + 2847, 10585, 2518, + 2847, 10585, 2520, + 2847, 10585, 2522, + 2847, 10585, 2524, + 2847, 10585, 2554, + 2847, 10585, 2666, + 2847, 10585, 2678, + 2847, 10585, 2680, + 2847, 10585, 2682, + 2847, 10585, 2684, + 2847, 10585, 2686, + 2847, 10585, 2722, + 2847, 10585, 2856, + 2847, 10585, 2876, + 2847, 10585, 2910, + 2847, 10585, 2922, + 2847, 10585, 2924, + 2847, 10585, 2934, + 2847, 10585, 2940, + 2847, 10585, 2942, + 2847, 10585, 2948, + 2847, 10585, 3050, + 2847, 10585, 3082, + 2847, 10585, 3138, + 2847, 10585, 3146, + 2847, 10585, 3148, + 2847, 10585, 3150, + 2847, 10585, 3152, + 2847, 10585, 3154, + 2847, 10585, 3178, + 2847, 10585, 3778, + 2847, 10585, 3780, + 2847, 10585, 4068, + 2847, 10585, 4070, + 2847, 10585, 4072, + 2847, 10585, 4074, + 2847, 10585, 4076, + 2847, 10585, 4078, + 2847, 10585, 4080, + 2847, 10585, 4246, + 2847, 10585, 4248, + 2847, 10585, 4250, + 2847, 10585, 4252, + 2847, 10585, 4774, + 2847, 10585, 4776, + 2847, 10585, 4778, + 2847, 10585, 4780, + 2847, 10585, 4932, + 2847, 10585, 4934, + 2847, 10585, 4964, + 2847, 10585, 4966, + 2847, 10585, 4968, + 2847, 10585, 4970, + 2847, 10585, 4972, + 2847, 10585, 5100, + 2847, 10585, 5114, + 2847, 10585, 5136, + 2847, 10585, 5146, + 2847, 10585, 5152, + 2847, 10585, 5154, + 2847, 10585, 5156, + 2847, 10585, 5158, + 2847, 10585, 5160, + 2847, 10585, 5168, + 2847, 10585, 5194, + 2847, 10585, 5204, + 2847, 10585, 5296, + 2847, 10585, 5316, + 2847, 10585, 5678, + 2847, 10585, 5710, + 2847, 10585, 5914, + 2847, 10585, 5930, + 2847, 10585, 6108, + 2847, 10585, 6126, + 2847, 10585, 6274, + 2847, 10585, 6282, + 2847, 10585, 6682, + 2847, 10585, 6684, + 2847, 10585, 7152, + 2847, 10585, 7154, + 2847, 10585, 7223, 150, + 2847, 10585, 7223, 196, + 2847, 10585, 7223, 306, + 2847, 10585, 7223, 364, + 2847, 10585, 7223, 2554, + 2847, 10585, 7228, + 2847, 10585, 7230, + 2847, 10585, 7232, + 2847, 10585, 11674, + 2941, 5758, + 2972, + 3055, 5758, + 3071, 6178, + 3245, 8774, + 3264, + 3285, 8774, + 3769, 8774, + 3839, 2812, + 3849, 428, + 3871, 5758, + 3873, 5758, + 3879, 6689, 2170, + 3879, 6689, 2540, + 3879, 6689, 2778, + 3879, 6689, 4200, + 3879, 6689, 4214, + 3879, 6689, 5190, + 3879, 6689, 6260, + 3879, 6689, 6722, + 3879, 6689, 7508, + 3879, 6689, 7694, + 3879, 7803, 5759, 16, + 3879, 7803, 5759, 28, + 3879, 7803, 5759, 40, + 3879, 7803, 5759, 58, + 3879, 7803, 5759, 72, + 3879, 7803, 5759, 92, + 3879, 7803, 5759, 168, + 3879, 7803, 5759, 266, + 3879, 7803, 5759, 426, + 3879, 7803, 5759, 590, + 3879, 8405, 0, + 3879, 8405, 8, + 3879, 8405, 16, + 3879, 8405, 28, + 3879, 8405, 40, + 3879, 8405, 72, + 3879, 8405, 100, + 3879, 8405, 138, + 3879, 8405, 216, + 3879, 8405, 236, + 3879, 8405, 292, + 3879, 8405, 306, + 3879, 8405, 332, + 3879, 8405, 364, + 3879, 8405, 392, + 3879, 8405, 462, + 3879, 8405, 510, + 3879, 8405, 524, + 3879, 8405, 556, + 3879, 8405, 610, + 3879, 8405, 652, + 3879, 8405, 766, + 3879, 8405, 792, + 3879, 8405, 884, + 3879, 8405, 974, + 3879, 8405, 996, + 3879, 8405, 1260, + 3879, 8405, 1512, + 3879, 8405, 1612, + 3879, 8405, 1948, + 3879, 8405, 2030, + 3879, 8405, 2042, + 3879, 8405, 2106, + 3879, 8405, 2212, + 3879, 8405, 2246, + 3879, 8405, 2566, + 3879, 8405, 2678, + 3879, 8405, 3902, + 3879, 8405, 5178, + 3879, 8405, 5182, + 3879, 8405, 5184, + 3879, 8405, 6789, 12, + 3879, 8405, 6789, 20, + 3879, 8405, 6789, 22, + 3879, 8405, 6789, 26, + 3879, 8405, 6789, 30, + 3879, 8405, 6789, 34, + 3879, 8405, 6789, 38, + 3879, 8405, 6789, 48, + 3879, 8405, 6789, 124, + 3879, 8405, 6789, 400, + 3879, 8405, 6789, 542, + 3879, 10775, 5759, 332, + 3879, 10775, 5759, 510, + 3879, 10775, 5759, 622, + 3879, 10775, 5759, 652, + 3879, 10775, 5759, 6789, 14, + 3879, 10775, 5759, 6789, 24, + 3879, 10775, 5759, 6789, 400, + 3879, 12133, 6646, + 3879, 12133, 8153, 6646, + 3879, 12133, 8732, + 3879, 12133, 8849, 6646, + 3961, 5566, + 3989, 7512, + 4103, 2091, 6798, + 4103, 2091, 7396, + 4103, 2091, 8122, + 4103, 2091, 8123, 6121, 10489, 10355, 7580, + 4103, 2091, 9113, 89, 8466, + 4103, 2091, 9113, 89, 8521, 10572, + 4103, 2091, 9113, 89, 8521, 10573, 445, 6740, + 4103, 2091, 9604, + 4103, 2091, 9605, 445, 6740, + 4103, 2091, 9750, + 4103, 2091, 9751, 445, 6740, + 4107, 5758, + 4117, 4197, 5878, + 4117, 5876, + 4117, 5877, 6121, 8057, 6490, + 4117, 7443, 10001, 10154, + 4117, 10716, + 4153, 8781, 6622, + 4171, 5758, + 4201, 1045, 4926, + 4201, 1045, 12132, + 4215, 1045, 4926, + 4215, 1045, 12132, + 4215, 11907, 9898, + 4215, 13047, 9898, + 4215, 13233, 9898, + 4223, 5836, + 4223, 6510, + 4223, 7327, 4676, + 4228, + 4260, + 4269, 4926, + 4387, 7608, + 4401, 8774, + 4423, 9831, 5758, + 4676, + 4686, + 4837, 9615, 5012, + 4849, 721, 7443, 5876, + 4849, 721, 7443, 8153, 11378, + 4849, 731, 11099, 9050, + 4849, 1809, 11715, 9050, + 4849, 2171, 8159, 6510, + 4849, 2171, 9615, 6510, + 4849, 3713, 601, 7443, 3713, 601, 9326, + 4849, 3713, 601, 7443, 3713, 4117, 9326, + 4849, 3713, 4117, 7443, 3713, 601, 9326, + 4849, 3713, 4117, 7443, 3713, 4117, 9326, + 4849, 4197, 5878, + 4849, 4201, 9259, 6510, + 4849, 4389, 6505, 8056, + 4849, 4389, 6510, + 4849, 5876, + 4849, 6409, 9050, + 4849, 6409, 9051, 6121, 1044, + 4849, 6435, 6121, 7593, 8056, + 4849, 6435, 6121, 9095, 5444, + 4849, 6505, 10637, 7533, 9050, + 4849, 6505, 11677, 9050, + 4849, 6627, 9050, + 4849, 6627, 9051, 7121, 4530, + 4849, 6627, 9051, 7773, 4530, + 4849, 6627, 9051, 8473, 7370, + 4849, 6792, + 4849, 7327, 4676, + 4849, 7443, 6105, 6434, + 4849, 7443, 6434, + 4849, 7443, 6435, 6121, 8153, 10677, 8758, + 4849, 7443, 6435, 6121, 8758, + 4849, 7443, 6435, 6121, 10677, 8758, + 4849, 7443, 6435, 9785, 7593, 8056, + 4849, 7443, 6505, 6434, + 4849, 7443, 7821, 6434, + 4849, 7443, 8153, 6434, + 4849, 7443, 8153, 6435, 6121, 8758, + 4849, 7443, 8153, 6435, 6121, 10677, 8758, + 4849, 7443, 12103, 6434, + 4849, 7509, 9259, 6510, + 4849, 7695, 9259, 6510, + 4849, 7695, 10467, 6510, + 4849, 7821, 6627, 9050, + 4849, 7821, 8077, 9050, + 4849, 7821, 8745, 9050, + 4849, 7821, 10637, 7533, 9050, + 4849, 7821, 11677, 9050, + 4849, 7821, 12114, + 4849, 8077, 9050, + 4849, 8151, 12877, 9050, + 4849, 8153, 6409, 9050, + 4849, 8153, 8933, 6778, + 4849, 8153, 11195, 4926, + 4849, 8153, 12114, + 4849, 8521, 8191, 11793, 9610, + 4849, 8631, 10371, 9050, + 4849, 8717, 11195, 4926, + 4849, 8745, 9050, + 4849, 8745, 9051, 6121, 5935, 275, 2725, 8076, + 4849, 8745, 9051, 6121, 5935, 275, 8005, 8076, + 4849, 8745, 9051, 6121, 7412, + 4849, 8745, 9051, 6121, 10666, + 4849, 8745, 9051, 7121, 8076, + 4849, 8745, 9051, 7773, 8076, + 4849, 8745, 9051, 10982, + 4849, 8933, 6778, + 4849, 9074, + 4849, 10346, + 4849, 10493, 753, 10794, + 4849, 10523, 41, 9050, + 4849, 10637, 7533, 9050, + 4849, 10643, 7991, 10677, 760, + 4849, 10677, 761, 6121, 7412, + 4849, 10677, 827, 4876, + 4849, 11793, 9610, + 4849, 12114, + 4849, 12115, 7121, 4530, + 4849, 12115, 7773, 4530, + 4849, 12115, 10982, + 4849, 12877, 9050, + 4849, 13029, 9050, + 4877, 11228, + 4877, 12057, 2091, 11049, 2681, 5446, + 4877, 12057, 6121, 12139, 5403, 7939, 5446, + 4877, 12057, 6121, 12857, 5403, 7939, 5446, + 4883, 5758, + 4895, 3993, 4221, 4849, 8467, 429, 8153, 10676, + 4895, 4849, 5876, + 4895, 4849, 7443, 6434, + 4895, 4849, 7443, 8153, 6434, + 4895, 7443, 5876, + 4895, 10016, + 4895, 11097, 6434, + 4895, 11097, 6435, 4221, 760, + 4895, 11097, 8153, 6434, + 4895, 11097, 8153, 6435, 4221, 760, + 4895, 11097, 10531, 6434, + 4895, 11765, 6434, + 4895, 11765, 6435, 4221, 760, + 4895, 11765, 8153, 6434, + 4895, 11765, 8153, 6435, 4221, 760, + 4895, 11765, 10531, 6434, + 4923, 721, 8197, 5758, + 4923, 5758, + 4923, 6121, 8759, 721, 4923, 721, 8197, 5758, + 4923, 6121, 8759, 5758, + 4931, 4926, + 5003, 5758, + 5006, + 5017, 11098, + 5017, 12472, + 5050, + 5131, 5392, + 5385, 826, + 5385, 8037, 6505, 5830, + 5385, 8037, 6622, + 5385, 8037, 9898, + 5385, 8037, 13233, 9898, + 5385, 8762, + 5385, 10578, + 5395, 8008, + 5401, 11891, 4926, + 5409, 5758, + 5445, 5758, + 5445, 5759, 275, 4849, 4389, 8056, + 5445, 5759, 275, 7443, 4389, 8056, + 5445, 5759, 275, 10642, + 5445, 5759, 6121, 1045, 6490, + 5445, 5759, 6121, 6505, 10642, + 5445, 5759, 6121, 7593, 8057, 6376, + 5445, 5759, 6121, 7709, 6376, + 5445, 5759, 6121, 7709, 6490, + 5445, 5759, 6121, 11261, 2778, + 5445, 5759, 6121, 11449, 7909, 6376, + 5445, 5759, 6377, 8167, 5758, + 5545, 5758, + 5551, 275, 6741, 568, + 5551, 6376, + 5551, 6741, 568, + 5551, 7382, + 5551, 10374, + 5769, 6104, + 5781, 8306, + 5831, 429, 6656, + 5831, 721, 9964, + 5831, 8166, + 5831, 10374, + 5887, 6704, + 5909, 6689, 2170, + 5909, 6689, 2540, + 5909, 6689, 2778, + 5909, 6689, 4200, + 5909, 6689, 4214, + 5909, 6689, 5190, + 5909, 6689, 6260, + 5909, 6689, 6722, + 5909, 6689, 7508, + 5909, 6689, 7694, + 5909, 9971, 8775, 3702, + 5909, 10759, 29, 722, + 5909, 10759, 109, 7968, + 5909, 10759, 151, 988, + 5909, 10759, 151, 6562, + 5909, 10759, 209, 196, + 5909, 10759, 209, 1142, + 5909, 10759, 247, 1386, + 5909, 10759, 247, 8518, + 5909, 10759, 323, 1582, + 5909, 10759, 351, 4878, + 5909, 10759, 351, 6582, + 5909, 10759, 354, + 5909, 10759, 381, 364, + 5909, 10759, 413, 416, + 5909, 10759, 413, 2018, + 5909, 10759, 481, 2234, + 5909, 10759, 517, 2448, + 5909, 10759, 520, + 5909, 10759, 537, 536, + 5909, 10759, 537, 2580, + 5909, 10759, 537, 5614, + 5909, 10759, 537, 5630, + 5909, 10759, 569, 2650, + 5909, 10759, 569, 7344, + 5909, 10759, 633, 6098, + 5909, 10759, 661, 3022, + 5909, 10759, 661, 6212, + 5909, 10759, 891, 3880, + 5909, 10759, 891, 3908, + 5909, 10759, 891, 6566, + 5909, 10759, 891, 6576, + 5909, 10759, 1619, 4738, + 5909, 10759, 1619, 4750, + 5909, 10759, 1619, 7050, + 5909, 10759, 1619, 7052, + 5909, 10759, 1619, 9618, + 5909, 10759, 1859, 170, + 5909, 10759, 1859, 2684, + 5909, 10759, 1859, 2730, + 5909, 10759, 1859, 9938, + 5909, 10759, 1859, 10228, + 5909, 10759, 2039, 2040, + 5909, 10759, 2219, 5412, + 5909, 10759, 2219, 7366, + 5909, 10759, 2219, 9652, + 5909, 10759, 2685, 5912, + 5909, 10759, 2685, 7690, + 5909, 10759, 2685, 7696, + 5909, 10759, 2685, 8812, + 5909, 10759, 2685, 9592, + 5909, 10759, 2685, 11694, + 5909, 10759, 5637, 0, + 5909, 10759, 5637, 8, + 5909, 10759, 5637, 16, + 5909, 10759, 5637, 28, + 5909, 10759, 5637, 40, + 5909, 10759, 5637, 58, + 5909, 10759, 5637, 66, + 5909, 10759, 5637, 73, 9446, + 5909, 10759, 5637, 73, 10312, + 5909, 10759, 5637, 78, + 5909, 10759, 5637, 266, + 5909, 10759, 5637, 590, + 5909, 10759, 5637, 606, + 5909, 10759, 5637, 2804, + 5909, 10759, 8358, + 5909, 10759, 9290, + 5909, 10759, 9590, + 5909, 10759, 10314, + 5909, 10759, 10358, + 5909, 10759, 10684, + 5909, 10759, 11108, + 5909, 10759, 11152, + 5909, 10759, 11412, + 5909, 10759, 12072, + 5909, 10759, 12362, + 5927, 7608, + 5946, + 5972, + 6051, 8774, + 6081, 5017, 11098, + 6081, 5017, 12472, + 6105, 3992, + 6105, 6435, 10441, 10015, 4848, + 6105, 6435, 10441, 10015, 7442, + 6107, 1809, 4876, + 6107, 3992, + 6107, 4876, + 6107, 10388, + 6113, 8781, 6622, + 6129, 8330, + 6261, 7825, 7608, + 6261, 7825, 8330, + 6261, 7825, 10363, 7608, + 6261, 7825, 11698, + 6379, 6408, + 6379, 7908, + 6408, + 6409, 6121, 37, 8318, + 6409, 6121, 10666, + 6428, + 6435, 10441, 10959, 5919, 9131, 11096, + 6435, 10441, 10959, 5919, 9131, 11764, + 6435, 10441, 11765, 5919, 9131, 9810, + 6435, 10441, 11765, 5919, 9131, 10958, + 6505, 2048, + 6505, 2587, 6121, 5528, + 6505, 3949, 5842, + 6505, 4202, + 6505, 4215, 9601, 5830, + 6505, 4849, 10441, 6992, + 6505, 5013, 8406, + 6505, 5830, + 6505, 6081, 7593, 8744, + 6505, 6571, 4760, + 6505, 6571, 5404, + 6505, 6571, 5564, + 6505, 6571, 7410, + 6505, 6571, 7996, + 6505, 6571, 8368, + 6505, 6907, 5842, + 6505, 7085, 8056, + 6505, 7085, 8744, + 6505, 7121, 4849, 10642, + 6505, 7121, 7443, 10642, + 6505, 7443, 10441, 6992, + 6505, 7547, 7370, + 6505, 7593, 5830, + 6505, 7593, 8744, + 6505, 7593, 9158, + 6505, 7593, 9438, + 6505, 7611, 5842, + 6505, 7773, 4849, 10642, + 6505, 7773, 7443, 10642, + 6505, 8006, + 6505, 8037, 7821, 5830, + 6505, 8056, + 6505, 8057, 6121, 2779, 7821, 4112, + 6505, 8057, 6121, 4117, 6434, + 6505, 8057, 6121, 7821, 1045, 7442, + 6505, 8463, 7593, 8744, + 6505, 8463, 8744, + 6505, 8463, 9158, + 6505, 8463, 9438, + 6505, 8744, + 6505, 9158, + 6505, 9159, 5842, + 6505, 9159, 6121, 4117, 6434, + 6505, 9159, 7173, 7821, 46, + 6505, 9338, + 6505, 9438, + 6505, 9711, 4178, + 6505, 10143, 1860, + 6505, 10143, 4760, + 6505, 10194, + 6505, 10420, + 6505, 10502, + 6505, 10677, 9264, + 6505, 10677, 11202, + 6505, 11036, + 6505, 11097, 8022, + 6505, 11202, + 6505, 11354, + 6505, 11387, 11205, 8774, + 6505, 11649, 9264, + 6505, 11765, 6434, + 6505, 11765, 8022, + 6505, 11765, 10716, + 6505, 12383, 7593, 10642, + 6505, 12383, 10642, + 6505, 12931, 7593, 10642, + 6505, 12931, 10642, + 6505, 12967, 7593, 10642, + 6505, 12967, 9602, + 6505, 12967, 10642, + 6505, 12984, + 6505, 13067, 7593, 10642, + 6505, 13067, 9602, + 6505, 13067, 10420, + 6505, 13067, 10642, + 6509, 8774, + 6516, + 6531, 7803, 5759, 16, + 6531, 7803, 5759, 40, + 6531, 8405, 0, + 6531, 8405, 16, + 6531, 8405, 40, + 6531, 8405, 100, + 6531, 8405, 138, + 6531, 8405, 216, + 6531, 8405, 236, + 6531, 8405, 306, + 6531, 8405, 332, + 6531, 8405, 364, + 6531, 8405, 392, + 6531, 8405, 462, + 6531, 8405, 510, + 6531, 8405, 524, + 6531, 8405, 556, + 6531, 8405, 622, + 6531, 8405, 652, + 6531, 8405, 2030, + 6542, + 6543, 11061, 7382, + 6546, + 6560, + 6569, 4926, + 6597, 8677, 8774, + 6603, 600, + 6606, + 6610, + 6611, 5758, + 6611, 8166, + 6614, + 6616, + 6623, 429, 10308, + 6623, 429, 11068, + 6627, 9051, 10982, + 6627, 9437, 444, + 6627, 9437, 720, + 6643, 8774, + 6675, 6741, 568, + 6689, 2170, + 6689, 2171, 4223, 5836, + 6689, 2540, + 6689, 2541, 4223, 5836, + 6689, 2778, + 6689, 2779, 4223, 5836, + 6689, 4200, + 6689, 4201, 4223, 5836, + 6689, 4214, + 6689, 4215, 4223, 5836, + 6689, 5190, + 6689, 5191, 4223, 5836, + 6689, 6260, + 6689, 6722, + 6689, 6723, 4223, 5836, + 6689, 7508, + 6689, 7509, 4223, 5836, + 6689, 7694, + 6689, 7695, 4223, 5836, + 6695, 4926, + 6716, + 6717, 8272, + 6723, 8737, 9898, + 6723, 9601, 6505, 5830, + 6723, 9601, 10433, 5830, + 6723, 9601, 12141, 6505, 5830, + 6723, 10425, 10385, 6505, 10194, + 6723, 13233, 11187, 9898, + 6725, 8774, + 6731, 2510, + 6731, 2511, 6121, 4849, 6435, 6376, + 6731, 2511, 6121, 7443, 6435, 6376, + 6731, 2511, 6121, 7593, 8057, 6376, + 6731, 2511, 6121, 9546, + 6735, 8774, + 6741, 569, 115, 11472, + 6741, 569, 445, 10452, + 6741, 569, 445, 10574, + 6741, 569, 445, 11098, + 6741, 569, 445, 12472, + 6741, 721, 10411, 568, + 6745, 569, 2681, 4848, + 6745, 569, 2681, 7442, + 6763, 9956, + 6771, 8774, + 6791, 9615, 5012, + 6812, + 6857, 8774, + 6875, 7908, + 6879, 477, 8774, + 6879, 727, 8798, + 6879, 1583, 8774, + 6879, 2171, 4389, 5758, + 6879, 2171, 4389, 5759, 10707, 4212, + 6879, 2217, 8774, + 6879, 2413, 6121, 8759, 8774, + 6879, 2413, 8774, + 6879, 2779, 7307, 5758, + 6879, 2779, 8819, 5758, + 6879, 3775, 8774, + 6879, 4201, 7307, 5758, + 6879, 4215, 7307, 5758, + 6879, 5375, 5758, + 6879, 5388, + 6879, 6197, 5758, + 6879, 6261, 5758, + 6879, 6654, + 6879, 6655, 721, 5388, + 6879, 6655, 721, 7782, + 6879, 6655, 721, 12120, + 6879, 7023, 8774, + 6879, 7111, 5758, + 6879, 7121, 9513, 5758, + 6879, 7398, + 6879, 7399, 721, 5388, + 6879, 7399, 721, 7782, + 6879, 7399, 721, 12120, + 6879, 7593, 8151, 8427, 7569, 8774, + 6879, 7593, 8405, 384, + 6879, 7593, 8405, 416, + 6879, 7593, 8405, 476, + 6879, 7593, 8405, 644, + 6879, 7593, 8405, 888, + 6879, 7593, 8405, 1128, + 6879, 7593, 8405, 1129, 6121, 5388, + 6879, 7593, 8405, 1129, 6121, 5389, 721, 13036, + 6879, 7593, 8405, 1129, 6121, 6654, + 6879, 7593, 8405, 1129, 6121, 6655, 721, 5388, + 6879, 7593, 8405, 1129, 6121, 6655, 721, 5389, 721, 13036, + 6879, 7593, 8405, 1129, 6121, 6655, 721, 7782, + 6879, 7593, 8405, 1129, 6121, 6655, 721, 7783, 721, 13036, + 6879, 7593, 8405, 1129, 6121, 6655, 721, 12120, + 6879, 7593, 8405, 1129, 6121, 6655, 721, 12121, 721, 13036, + 6879, 7593, 8405, 1129, 6121, 6655, 721, 13036, + 6879, 7593, 8405, 1129, 6121, 7398, + 6879, 7593, 8405, 1129, 6121, 7399, 721, 5388, + 6879, 7593, 8405, 1129, 6121, 7399, 721, 5389, 721, 13036, + 6879, 7593, 8405, 1129, 6121, 7399, 721, 7782, + 6879, 7593, 8405, 1129, 6121, 7399, 721, 7783, 721, 13036, + 6879, 7593, 8405, 1129, 6121, 7399, 721, 12120, + 6879, 7593, 8405, 1129, 6121, 7399, 721, 12121, 721, 13036, + 6879, 7593, 8405, 1129, 6121, 7399, 721, 13036, + 6879, 7593, 8405, 1129, 6121, 7724, + 6879, 7593, 8405, 1129, 6121, 7782, + 6879, 7593, 8405, 1129, 6121, 7783, 721, 13036, + 6879, 7593, 8405, 1129, 6121, 12120, + 6879, 7593, 8405, 1129, 6121, 12121, 721, 13036, + 6879, 7593, 8405, 1129, 6121, 13036, + 6879, 7593, 8405, 2216, + 6879, 7593, 8405, 2250, + 6879, 7593, 8405, 2412, + 6879, 7593, 8405, 2413, 6121, 6654, + 6879, 7593, 8405, 2413, 6121, 7398, + 6879, 7593, 8405, 2490, + 6879, 7593, 8405, 2522, + 6879, 7593, 8405, 2658, + 6879, 7593, 8405, 3774, + 6879, 7593, 8405, 4408, + 6879, 7593, 8405, 4614, + 6879, 7593, 8405, 4615, 6121, 5388, + 6879, 7593, 8405, 4615, 6121, 6654, + 6879, 7593, 8405, 4615, 6121, 6655, 721, 5388, + 6879, 7593, 8405, 4615, 6121, 6655, 721, 7782, + 6879, 7593, 8405, 4615, 6121, 6655, 721, 12120, + 6879, 7593, 8405, 4615, 6121, 7398, + 6879, 7593, 8405, 4615, 6121, 7399, 721, 5388, + 6879, 7593, 8405, 4615, 6121, 7399, 721, 7782, + 6879, 7593, 8405, 4615, 6121, 7399, 721, 12120, + 6879, 7593, 8405, 4615, 6121, 7724, + 6879, 7593, 8405, 4615, 6121, 7782, + 6879, 7593, 8405, 4615, 6121, 8432, + 6879, 7593, 8405, 4615, 6121, 8924, + 6879, 7593, 8405, 4615, 6121, 10808, + 6879, 7593, 8405, 4615, 6121, 10809, 721, 5388, + 6879, 7593, 8405, 4615, 6121, 10809, 721, 7724, + 6879, 7593, 8405, 4615, 6121, 10809, 721, 7782, + 6879, 7593, 8405, 4615, 6121, 10809, 721, 12120, + 6879, 7593, 8405, 4615, 6121, 12120, + 6879, 7593, 8405, 6262, + 6879, 7593, 8405, 6406, + 6879, 7593, 8405, 6407, 6121, 5388, + 6879, 7593, 8405, 6407, 6121, 5389, 721, 13036, + 6879, 7593, 8405, 6407, 6121, 6654, + 6879, 7593, 8405, 6407, 6121, 6655, 721, 5388, + 6879, 7593, 8405, 6407, 6121, 6655, 721, 5389, 721, 13036, + 6879, 7593, 8405, 6407, 6121, 6655, 721, 7782, + 6879, 7593, 8405, 6407, 6121, 6655, 721, 7783, 721, 13036, + 6879, 7593, 8405, 6407, 6121, 6655, 721, 12120, + 6879, 7593, 8405, 6407, 6121, 6655, 721, 12121, 721, 13036, + 6879, 7593, 8405, 6407, 6121, 6655, 721, 13036, + 6879, 7593, 8405, 6407, 6121, 7398, + 6879, 7593, 8405, 6407, 6121, 7399, 721, 5388, + 6879, 7593, 8405, 6407, 6121, 7399, 721, 5389, 721, 13036, + 6879, 7593, 8405, 6407, 6121, 7399, 721, 7782, + 6879, 7593, 8405, 6407, 6121, 7399, 721, 7783, 721, 13036, + 6879, 7593, 8405, 6407, 6121, 7399, 721, 12120, + 6879, 7593, 8405, 6407, 6121, 7399, 721, 12121, 721, 13036, + 6879, 7593, 8405, 6407, 6121, 7399, 721, 13036, + 6879, 7593, 8405, 6407, 6121, 7724, + 6879, 7593, 8405, 6407, 6121, 7782, + 6879, 7593, 8405, 6407, 6121, 7783, 721, 13036, + 6879, 7593, 8405, 6407, 6121, 8432, + 6879, 7593, 8405, 6407, 6121, 8924, + 6879, 7593, 8405, 6407, 6121, 12120, + 6879, 7593, 8405, 6407, 6121, 12121, 721, 13036, + 6879, 7593, 8405, 6407, 6121, 13036, + 6879, 7593, 8405, 6674, + 6879, 7593, 8405, 6789, 7568, + 6879, 7593, 8405, 6824, + 6879, 7593, 8405, 7022, + 6879, 7593, 8405, 7062, + 6879, 7593, 8405, 7080, + 6879, 7593, 8405, 7316, + 6879, 7593, 8405, 7317, 6121, 5388, + 6879, 7593, 8405, 7317, 6121, 5389, 721, 13036, + 6879, 7593, 8405, 7317, 6121, 6654, + 6879, 7593, 8405, 7317, 6121, 6655, 721, 5388, + 6879, 7593, 8405, 7317, 6121, 6655, 721, 5389, 721, 13036, + 6879, 7593, 8405, 7317, 6121, 6655, 721, 7782, + 6879, 7593, 8405, 7317, 6121, 6655, 721, 7783, 721, 13036, + 6879, 7593, 8405, 7317, 6121, 6655, 721, 12120, + 6879, 7593, 8405, 7317, 6121, 6655, 721, 12121, 721, 13036, + 6879, 7593, 8405, 7317, 6121, 6655, 721, 13036, + 6879, 7593, 8405, 7317, 6121, 7398, + 6879, 7593, 8405, 7317, 6121, 7399, 721, 5388, + 6879, 7593, 8405, 7317, 6121, 7399, 721, 5389, 721, 13036, + 6879, 7593, 8405, 7317, 6121, 7399, 721, 7782, + 6879, 7593, 8405, 7317, 6121, 7399, 721, 7783, 721, 13036, + 6879, 7593, 8405, 7317, 6121, 7399, 721, 12120, + 6879, 7593, 8405, 7317, 6121, 7399, 721, 12121, 721, 13036, + 6879, 7593, 8405, 7317, 6121, 7399, 721, 13036, + 6879, 7593, 8405, 7317, 6121, 7724, + 6879, 7593, 8405, 7317, 6121, 7782, + 6879, 7593, 8405, 7317, 6121, 7783, 721, 13036, + 6879, 7593, 8405, 7317, 6121, 12120, + 6879, 7593, 8405, 7317, 6121, 12121, 721, 13036, + 6879, 7593, 8405, 7317, 6121, 13036, + 6879, 7593, 8405, 7484, + 6879, 7593, 8405, 7568, + 6879, 7593, 8405, 7682, + 6879, 7593, 8405, 8748, + 6879, 7593, 8405, 9007, 7062, + 6879, 7593, 8405, 9007, 7484, + 6879, 7593, 8405, 9162, + 6879, 7593, 8405, 9270, + 6879, 7593, 8405, 9271, 6121, 5388, + 6879, 7593, 8405, 9271, 6121, 6654, + 6879, 7593, 8405, 9271, 6121, 6655, 721, 5388, + 6879, 7593, 8405, 9271, 6121, 6655, 721, 7782, + 6879, 7593, 8405, 9271, 6121, 7398, + 6879, 7593, 8405, 9271, 6121, 7399, 721, 5388, + 6879, 7593, 8405, 9271, 6121, 7399, 721, 7782, + 6879, 7593, 8405, 9271, 6121, 7724, + 6879, 7593, 8405, 9271, 6121, 7782, + 6879, 7593, 8405, 9530, + 6879, 7593, 8405, 9531, 6121, 5388, + 6879, 7593, 8405, 9531, 6121, 6654, + 6879, 7593, 8405, 9531, 6121, 6655, 721, 5388, + 6879, 7593, 8405, 9531, 6121, 6655, 721, 7782, + 6879, 7593, 8405, 9531, 6121, 7398, + 6879, 7593, 8405, 9531, 6121, 7399, 721, 5388, + 6879, 7593, 8405, 9531, 6121, 7399, 721, 7782, + 6879, 7593, 8405, 9531, 6121, 7724, + 6879, 7593, 8405, 9531, 6121, 7782, + 6879, 7593, 8405, 9808, + 6879, 7593, 8405, 9809, 6121, 5388, + 6879, 7593, 8405, 9809, 6121, 6654, + 6879, 7593, 8405, 9809, 6121, 6655, 721, 5388, + 6879, 7593, 8405, 9809, 6121, 6655, 721, 7782, + 6879, 7593, 8405, 9809, 6121, 6655, 721, 12120, + 6879, 7593, 8405, 9809, 6121, 7398, + 6879, 7593, 8405, 9809, 6121, 7399, 721, 5388, + 6879, 7593, 8405, 9809, 6121, 7399, 721, 7782, + 6879, 7593, 8405, 9809, 6121, 7399, 721, 12120, + 6879, 7593, 8405, 9809, 6121, 7724, + 6879, 7593, 8405, 9809, 6121, 7782, + 6879, 7593, 8405, 9809, 6121, 8432, + 6879, 7593, 8405, 9809, 6121, 8924, + 6879, 7593, 8405, 9809, 6121, 10808, + 6879, 7593, 8405, 9809, 6121, 10809, 721, 5388, + 6879, 7593, 8405, 9809, 6121, 10809, 721, 7724, + 6879, 7593, 8405, 9809, 6121, 10809, 721, 7782, + 6879, 7593, 8405, 9809, 6121, 10809, 721, 12120, + 6879, 7593, 8405, 9809, 6121, 12120, + 6879, 7593, 8405, 11709, 9162, + 6879, 7593, 10489, 8151, 8427, 7569, 8774, + 6879, 7593, 10489, 8427, 7569, 8774, + 6879, 7683, 8774, + 6879, 7695, 7307, 5758, + 6879, 7695, 10467, 5758, + 6879, 7724, + 6879, 7782, + 6879, 7801, 10365, 10586, + 6879, 7801, 10365, 10588, + 6879, 7801, 10365, 10590, + 6879, 7801, 10365, 10592, + 6879, 7801, 10365, 10594, + 6879, 7801, 10365, 10596, + 6879, 7801, 10365, 10598, + 6879, 7801, 10365, 10600, + 6879, 7801, 10365, 10602, + 6879, 7801, 10365, 11270, + 6879, 7801, 10365, 11272, + 6879, 7801, 10365, 11274, + 6879, 7801, 10365, 11276, + 6879, 7801, 10365, 11278, + 6879, 7801, 10365, 11280, + 6879, 7801, 10365, 11282, + 6879, 7801, 10365, 11284, + 6879, 7801, 10365, 11286, + 6879, 7801, 10365, 11288, + 6879, 7801, 10365, 11290, + 6879, 7801, 10365, 11292, + 6879, 7801, 10365, 11294, + 6879, 7801, 10365, 11296, + 6879, 7801, 10365, 11298, + 6879, 7801, 10365, 11334, + 6879, 7801, 10365, 11336, + 6879, 7801, 10365, 11338, + 6879, 7801, 10365, 11340, + 6879, 7801, 10365, 11342, + 6879, 7941, 5758, + 6879, 7949, 5758, + 6879, 8269, 5758, + 6879, 8405, 3086, + 6879, 8405, 7062, + 6879, 8405, 7484, + 6879, 8405, 7593, 9063, 476, + 6879, 8405, 7593, 9063, 2250, + 6879, 8405, 7593, 9063, 2412, + 6879, 8405, 7593, 9063, 6824, + 6879, 8405, 7593, 9063, 7080, + 6879, 8405, 8748, + 6879, 8405, 9007, 7062, + 6879, 8405, 9162, + 6879, 8427, 7569, 8774, + 6879, 8427, 9271, 8774, + 6879, 8555, 5758, + 6879, 8787, 5758, + 6879, 8941, 5758, + 6879, 9063, 1583, 8774, + 6879, 9063, 7683, 8774, + 6879, 9063, 8151, 8427, 7569, 8774, + 6879, 9063, 8405, 384, + 6879, 9063, 8405, 416, + 6879, 9063, 8405, 476, + 6879, 9063, 8405, 644, + 6879, 9063, 8405, 888, + 6879, 9063, 8405, 1128, + 6879, 9063, 8405, 1129, 6121, 5388, + 6879, 9063, 8405, 1129, 6121, 6654, + 6879, 9063, 8405, 1129, 6121, 6655, 721, 5388, + 6879, 9063, 8405, 1129, 6121, 6655, 721, 5389, 721, 13064, + 6879, 9063, 8405, 1129, 6121, 6655, 721, 7782, + 6879, 9063, 8405, 1129, 6121, 6655, 721, 7783, 721, 13064, + 6879, 9063, 8405, 1129, 6121, 6655, 721, 12120, + 6879, 9063, 8405, 1129, 6121, 6655, 721, 12121, 721, 13064, + 6879, 9063, 8405, 1129, 6121, 6655, 721, 13064, + 6879, 9063, 8405, 1129, 6121, 7398, + 6879, 9063, 8405, 1129, 6121, 7399, 721, 5388, + 6879, 9063, 8405, 1129, 6121, 7399, 721, 5389, 721, 13064, + 6879, 9063, 8405, 1129, 6121, 7399, 721, 7782, + 6879, 9063, 8405, 1129, 6121, 7399, 721, 7783, 721, 13064, + 6879, 9063, 8405, 1129, 6121, 7399, 721, 12120, + 6879, 9063, 8405, 1129, 6121, 7399, 721, 12121, 721, 13064, + 6879, 9063, 8405, 1129, 6121, 7399, 721, 13064, + 6879, 9063, 8405, 1129, 6121, 7724, + 6879, 9063, 8405, 1129, 6121, 7782, + 6879, 9063, 8405, 1129, 6121, 13064, + 6879, 9063, 8405, 2216, + 6879, 9063, 8405, 2250, + 6879, 9063, 8405, 2412, + 6879, 9063, 8405, 2413, 6121, 6654, + 6879, 9063, 8405, 2490, + 6879, 9063, 8405, 2522, + 6879, 9063, 8405, 2658, + 6879, 9063, 8405, 3774, + 6879, 9063, 8405, 4408, + 6879, 9063, 8405, 4614, + 6879, 9063, 8405, 4615, 6121, 5388, + 6879, 9063, 8405, 4615, 6121, 6654, + 6879, 9063, 8405, 4615, 6121, 6655, 721, 5388, + 6879, 9063, 8405, 4615, 6121, 6655, 721, 7782, + 6879, 9063, 8405, 4615, 6121, 6655, 721, 12120, + 6879, 9063, 8405, 4615, 6121, 7398, + 6879, 9063, 8405, 4615, 6121, 7399, 721, 5388, + 6879, 9063, 8405, 4615, 6121, 7399, 721, 7782, + 6879, 9063, 8405, 4615, 6121, 7399, 721, 12120, + 6879, 9063, 8405, 4615, 6121, 7724, + 6879, 9063, 8405, 4615, 6121, 7782, + 6879, 9063, 8405, 4615, 6121, 8432, + 6879, 9063, 8405, 4615, 6121, 8924, + 6879, 9063, 8405, 4615, 6121, 10808, + 6879, 9063, 8405, 6262, + 6879, 9063, 8405, 6406, + 6879, 9063, 8405, 6407, 6121, 5388, + 6879, 9063, 8405, 6407, 6121, 6654, + 6879, 9063, 8405, 6407, 6121, 6655, 721, 5388, + 6879, 9063, 8405, 6407, 6121, 6655, 721, 5389, 721, 13064, + 6879, 9063, 8405, 6407, 6121, 6655, 721, 7782, + 6879, 9063, 8405, 6407, 6121, 6655, 721, 7783, 721, 13064, + 6879, 9063, 8405, 6407, 6121, 6655, 721, 12120, + 6879, 9063, 8405, 6407, 6121, 6655, 721, 12121, 721, 13064, + 6879, 9063, 8405, 6407, 6121, 6655, 721, 13064, + 6879, 9063, 8405, 6407, 6121, 7398, + 6879, 9063, 8405, 6407, 6121, 7399, 721, 5388, + 6879, 9063, 8405, 6407, 6121, 7399, 721, 5389, 721, 13064, + 6879, 9063, 8405, 6407, 6121, 7399, 721, 7782, + 6879, 9063, 8405, 6407, 6121, 7399, 721, 7783, 721, 13064, + 6879, 9063, 8405, 6407, 6121, 7399, 721, 12120, + 6879, 9063, 8405, 6407, 6121, 7399, 721, 12121, 721, 13064, + 6879, 9063, 8405, 6407, 6121, 7399, 721, 13064, + 6879, 9063, 8405, 6407, 6121, 7724, + 6879, 9063, 8405, 6407, 6121, 7782, + 6879, 9063, 8405, 6407, 6121, 8432, + 6879, 9063, 8405, 6407, 6121, 8924, + 6879, 9063, 8405, 6407, 6121, 13064, + 6879, 9063, 8405, 6674, + 6879, 9063, 8405, 6824, + 6879, 9063, 8405, 7022, + 6879, 9063, 8405, 7080, + 6879, 9063, 8405, 7316, + 6879, 9063, 8405, 7317, 6121, 5388, + 6879, 9063, 8405, 7317, 6121, 6654, + 6879, 9063, 8405, 7317, 6121, 6655, 721, 5388, + 6879, 9063, 8405, 7317, 6121, 6655, 721, 5389, 721, 13064, + 6879, 9063, 8405, 7317, 6121, 6655, 721, 7782, + 6879, 9063, 8405, 7317, 6121, 6655, 721, 7783, 721, 13064, + 6879, 9063, 8405, 7317, 6121, 6655, 721, 12120, + 6879, 9063, 8405, 7317, 6121, 6655, 721, 12121, 721, 13064, + 6879, 9063, 8405, 7317, 6121, 6655, 721, 13064, + 6879, 9063, 8405, 7317, 6121, 7398, + 6879, 9063, 8405, 7317, 6121, 7399, 721, 5388, + 6879, 9063, 8405, 7317, 6121, 7399, 721, 5389, 721, 13064, + 6879, 9063, 8405, 7317, 6121, 7399, 721, 7782, + 6879, 9063, 8405, 7317, 6121, 7399, 721, 7783, 721, 13064, + 6879, 9063, 8405, 7317, 6121, 7399, 721, 12120, + 6879, 9063, 8405, 7317, 6121, 7399, 721, 12121, 721, 13064, + 6879, 9063, 8405, 7317, 6121, 7399, 721, 13064, + 6879, 9063, 8405, 7317, 6121, 7724, + 6879, 9063, 8405, 7317, 6121, 7782, + 6879, 9063, 8405, 7317, 6121, 13064, + 6879, 9063, 8405, 7568, + 6879, 9063, 8405, 7682, + 6879, 9063, 8405, 9007, 7484, + 6879, 9063, 8405, 9270, + 6879, 9063, 8405, 9271, 6121, 5388, + 6879, 9063, 8405, 9271, 6121, 6654, + 6879, 9063, 8405, 9271, 6121, 6655, 721, 5388, + 6879, 9063, 8405, 9271, 6121, 6655, 721, 7782, + 6879, 9063, 8405, 9271, 6121, 7398, + 6879, 9063, 8405, 9271, 6121, 7399, 721, 5388, + 6879, 9063, 8405, 9271, 6121, 7399, 721, 7782, + 6879, 9063, 8405, 9271, 6121, 7724, + 6879, 9063, 8405, 9271, 6121, 7782, + 6879, 9063, 8405, 9530, + 6879, 9063, 8405, 9531, 6121, 5388, + 6879, 9063, 8405, 9531, 6121, 6654, + 6879, 9063, 8405, 9531, 6121, 6655, 721, 5388, + 6879, 9063, 8405, 9531, 6121, 6655, 721, 7782, + 6879, 9063, 8405, 9531, 6121, 7398, + 6879, 9063, 8405, 9531, 6121, 7399, 721, 5388, + 6879, 9063, 8405, 9531, 6121, 7399, 721, 7782, + 6879, 9063, 8405, 9531, 6121, 7724, + 6879, 9063, 8405, 9531, 6121, 7782, + 6879, 9063, 8405, 9808, + 6879, 9063, 8405, 9809, 6121, 5388, + 6879, 9063, 8405, 9809, 6121, 6654, + 6879, 9063, 8405, 9809, 6121, 6655, 721, 5388, + 6879, 9063, 8405, 9809, 6121, 6655, 721, 7782, + 6879, 9063, 8405, 9809, 6121, 6655, 721, 12120, + 6879, 9063, 8405, 9809, 6121, 7724, + 6879, 9063, 8405, 9809, 6121, 7782, + 6879, 9063, 8405, 9809, 6121, 8432, + 6879, 9063, 8405, 9809, 6121, 8924, + 6879, 9063, 8405, 9809, 6121, 10808, + 6879, 9063, 8405, 11709, 9162, + 6879, 9063, 8427, 7569, 8774, + 6879, 9063, 10489, 8151, 8427, 7569, 8774, + 6879, 9063, 10489, 8427, 7569, 8774, + 6879, 9245, 5758, + 6879, 9412, + 6879, 9419, 3717, 5758, + 6879, 9483, 8396, + 6879, 9513, 5758, + 6879, 9809, 6121, 4531, 8774, + 6879, 9809, 6121, 6379, 721, 4531, 8774, + 6879, 9809, 6121, 10805, 721, 4531, 8774, + 6879, 10331, 5758, + 6879, 10469, 4926, + 6879, 10489, 8427, 9271, 8774, + 6879, 10651, 3717, 5758, + 6879, 10809, 721, 5388, + 6879, 10809, 721, 7782, + 6879, 10809, 721, 12120, + 6879, 10809, 7724, + 6879, 11261, 7593, 8405, 888, + 6879, 11261, 7593, 8405, 2216, + 6879, 11261, 7593, 8405, 2412, + 6879, 11261, 7593, 8405, 3774, + 6879, 11261, 7593, 8405, 6824, + 6879, 11405, 6443, 2171, 4388, + 6879, 11405, 6443, 2171, 9244, + 6879, 11405, 6443, 2171, 9345, 9736, + 6879, 11405, 6443, 2171, 9345, 9764, + 6879, 11405, 6443, 2171, 9614, + 6879, 11405, 6443, 2171, 10625, 9736, + 6879, 11405, 6443, 2171, 10625, 9764, + 6879, 11405, 6443, 2671, 5010, + 6879, 11405, 6443, 2671, 9736, + 6879, 11405, 6443, 2671, 9764, + 6879, 11405, 6443, 2671, 10625, 9736, + 6879, 11405, 6443, 4200, + 6879, 11405, 6443, 4201, 9344, + 6879, 11405, 6443, 4201, 9345, 9736, + 6879, 11405, 6443, 4201, 9345, 9764, + 6879, 11405, 6443, 4201, 9736, + 6879, 11405, 6443, 4201, 9764, + 6879, 11405, 6443, 4201, 10624, + 6879, 11405, 6443, 4201, 10625, 9764, + 6879, 11405, 6443, 6784, + 6879, 11405, 6443, 6785, 9736, + 6879, 11405, 6443, 6785, 9764, + 6879, 11405, 6443, 6785, 10624, + 6879, 11405, 6443, 6785, 10625, 9736, + 6879, 11405, 8505, 4201, 9344, + 6879, 11405, 9153, 4201, 5010, + 6879, 11405, 9337, 2171, 10436, + 6879, 11405, 9975, 2779, 10138, + 6879, 11405, 10549, 6785, 5010, + 6879, 11405, 10621, 2170, + 6879, 11405, 10621, 2171, 9344, + 6879, 11405, 10621, 2171, 10624, + 6879, 11405, 10621, 2670, + 6879, 11405, 10621, 2778, + 6879, 11405, 10621, 4201, 9344, + 6879, 11405, 10621, 4201, 10624, + 6879, 11405, 10621, 6784, + 6879, 11405, 10621, 7695, 9344, + 6879, 11405, 10621, 8820, + 6879, 11405, 10755, 4201, 9344, + 6879, 11405, 11117, 2670, + 6879, 11405, 11617, 2778, + 6879, 11405, 11617, 2779, 10138, + 6879, 11405, 11617, 4201, 9344, + 6879, 11405, 11645, 2170, + 6879, 11405, 11645, 2670, + 6879, 11405, 11645, 6784, + 6879, 11405, 11865, 2670, + 6879, 11405, 11865, 2671, 10707, 4212, + 6879, 11405, 11865, 4200, + 6879, 11405, 11865, 4201, 9344, + 6879, 11405, 11865, 6784, + 6879, 11405, 11865, 6785, 10707, 4212, + 6879, 12120, + 6879, 12489, 10365, 10586, + 6879, 12489, 10365, 10588, + 6879, 12489, 10365, 10592, + 6879, 12489, 10365, 10594, + 6879, 12489, 10365, 10598, + 6879, 12489, 10365, 10600, + 6879, 12489, 10365, 11272, + 6879, 12489, 10365, 11274, + 6879, 12489, 10365, 11276, + 6879, 12489, 10365, 11278, + 6879, 12489, 10365, 11284, + 6879, 12489, 10365, 11286, + 6879, 12489, 10365, 11288, + 6879, 12489, 10365, 11296, + 6879, 12489, 10365, 11298, + 6879, 12489, 10365, 11300, + 6879, 12489, 10365, 11302, + 6879, 12489, 10365, 11304, + 6879, 12489, 10365, 11306, + 6879, 12489, 10365, 11308, + 6879, 12489, 10365, 11310, + 6879, 12489, 10365, 11312, + 6879, 12489, 10365, 11314, + 6879, 12489, 10365, 11316, + 6879, 12489, 10365, 11318, + 6879, 12489, 10365, 11320, + 6879, 12489, 10365, 11322, + 6879, 12489, 10365, 11324, + 6879, 12489, 10365, 11326, + 6879, 12489, 10365, 11328, + 6879, 12489, 10365, 11330, + 6879, 12489, 10365, 11332, + 6879, 12489, 10365, 11334, + 6879, 12489, 10365, 11336, + 6879, 12489, 10365, 11338, + 6879, 12489, 10365, 11340, + 6879, 12489, 10365, 11342, + 6879, 13036, + 6879, 13064, + 6909, 4215, 13047, 9898, + 6909, 5385, 8037, 6622, + 6909, 6505, 6906, + 6909, 6505, 8083, 9811, 721, 11765, 6434, + 6909, 6505, 8083, 10959, 721, 11765, 6434, + 6909, 6569, 4926, + 6909, 6723, 9601, 12141, 6505, 5830, + 6909, 6723, 13233, 11187, 9898, + 6909, 6879, 6622, + 6909, 6907, 12017, 4927, 10380, + 6909, 7121, 13069, 7821, 11765, 6434, + 6909, 7271, 4153, 6434, + 6909, 7607, 4153, 6434, + 6909, 7773, 13069, 7821, 11765, 6434, + 6909, 7971, 46, + 6909, 8097, 13235, 11765, 6434, + 6909, 8153, 6617, 11195, 4927, 10380, + 6909, 8153, 8869, 6617, 11195, 4927, 10380, + 6909, 8717, 6617, 11195, 4927, 10380, + 6909, 8717, 8869, 6617, 11195, 4927, 10380, + 6909, 9085, 11242, + 6909, 9722, + 6909, 9898, + 6909, 10385, 6505, 5830, + 6909, 10677, 760, + 6909, 11765, 6434, + 6909, 12017, 4927, 10380, + 6909, 12387, 11765, 6434, + 6909, 12539, 11765, 6434, + 6909, 12895, 11765, 6434, + 6909, 12967, 6409, 9051, 10380, + 6909, 12967, 6409, 11195, 4927, 10380, + 6909, 13061, 46, + 6909, 13067, 6409, 9051, 10380, + 6909, 13067, 6409, 11195, 4927, 10380, + 6909, 13191, 7271, 4153, 6434, + 6909, 13191, 7607, 4153, 6434, + 6909, 13191, 11765, 6434, + 6909, 13199, 6505, 11765, 6434, + 6909, 13233, 9898, + 6909, 13233, 10433, 9898, + 6909, 13235, 11765, 6434, + 6909, 13351, 11765, 6434, + 6954, + 6989, 428, + 6989, 429, 445, 12903, 6741, 568, + 7031, 341, 5759, 940, + 7031, 341, 5759, 5740, + 7031, 341, 5965, 6540, + 7031, 341, 5965, 6541, 8596, + 7031, 341, 5965, 8596, + 7031, 341, 6689, 2170, + 7031, 341, 6689, 2540, + 7031, 341, 6689, 2778, + 7031, 341, 6689, 4200, + 7031, 341, 6689, 4214, + 7031, 341, 6689, 5190, + 7031, 341, 6689, 6260, + 7031, 341, 6689, 6722, + 7031, 341, 6689, 7508, + 7031, 341, 6689, 7694, + 7031, 341, 7803, 8, + 7031, 341, 7803, 28, + 7031, 341, 7803, 40, + 7031, 341, 7803, 162, + 7031, 341, 7803, 590, + 7031, 341, 8405, 0, + 7031, 341, 8405, 16, + 7031, 341, 8405, 100, + 7031, 341, 8405, 116, + 7031, 341, 8405, 138, + 7031, 341, 8405, 216, + 7031, 341, 8405, 236, + 7031, 341, 8405, 306, + 7031, 341, 8405, 332, + 7031, 341, 8405, 364, + 7031, 341, 8405, 392, + 7031, 341, 8405, 426, + 7031, 341, 8405, 440, + 7031, 341, 8405, 462, + 7031, 341, 8405, 510, + 7031, 341, 8405, 524, + 7031, 341, 8405, 556, + 7031, 341, 8405, 610, + 7031, 341, 8405, 622, + 7031, 341, 8405, 652, + 7031, 341, 8405, 670, + 7031, 341, 8405, 1434, + 7031, 341, 8405, 1612, + 7031, 341, 8405, 2030, + 7031, 341, 8405, 2126, + 7031, 341, 8405, 2212, + 7031, 341, 8405, 2516, + 7031, 341, 8405, 2678, + 7049, 5759, 1763, 2722, + 7049, 5759, 4740, + 7049, 5759, 6388, + 7049, 5759, 6608, + 7049, 5759, 7450, + 7049, 5759, 7976, + 7049, 5759, 7992, + 7049, 5759, 8025, 2227, 4794, + 7049, 5759, 8583, 5014, + 7049, 5759, 8663, 8666, + 7049, 5759, 8918, + 7049, 5759, 9382, + 7049, 5759, 9408, + 7049, 5759, 9506, + 7049, 5759, 9624, + 7049, 5759, 9794, + 7049, 5759, 9902, + 7049, 5759, 11438, + 7049, 5759, 11440, + 7049, 5759, 12088, + 7049, 5759, 12366, + 7049, 5759, 12906, + 7049, 5759, 13038, + 7049, 6689, 2170, + 7049, 6689, 2540, + 7049, 6689, 2778, + 7049, 6689, 4200, + 7049, 6689, 4214, + 7049, 6689, 5190, + 7049, 6689, 6260, + 7049, 6689, 6722, + 7049, 6689, 7508, + 7049, 6689, 7694, + 7049, 7803, 5759, 8, + 7049, 7803, 5759, 16, + 7049, 7803, 5759, 40, + 7049, 7803, 5759, 48, + 7049, 7803, 5759, 58, + 7049, 7803, 5759, 66, + 7049, 7803, 5759, 72, + 7049, 7803, 5759, 92, + 7049, 7803, 5759, 258, + 7049, 7803, 5759, 266, + 7049, 7803, 5759, 426, + 7049, 7803, 5759, 440, + 7049, 7803, 5759, 582, + 7049, 7803, 5759, 606, + 7049, 7803, 5759, 652, + 7049, 7803, 5759, 668, + 7049, 7803, 10259, 58, + 7049, 7803, 10259, 86, + 7049, 8405, 100, + 7049, 8405, 116, + 7049, 8405, 130, + 7049, 8405, 138, + 7049, 8405, 150, + 7049, 8405, 236, + 7049, 8405, 306, + 7049, 8405, 322, + 7049, 8405, 332, + 7049, 8405, 350, + 7049, 8405, 380, + 7049, 8405, 412, + 7049, 8405, 480, + 7049, 8405, 496, + 7049, 8405, 516, + 7049, 8405, 524, + 7049, 8405, 556, + 7049, 8405, 568, + 7049, 8405, 616, + 7049, 8405, 660, + 7049, 8405, 884, + 7049, 8405, 890, + 7049, 8405, 1612, + 7049, 8405, 1618, + 7049, 8405, 2038, + 7049, 8405, 2080, + 7049, 8405, 2134, + 7049, 8405, 2212, + 7049, 8405, 2218, + 7049, 8405, 2516, + 7049, 8405, 2572, + 7049, 8405, 2678, + 7049, 8405, 2684, + 7049, 8405, 5994, + 7049, 8405, 6000, + 7049, 8775, 783, 2426, + 7049, 8775, 783, 4768, + 7049, 8775, 965, 2426, + 7049, 8775, 965, 4768, + 7049, 8775, 1763, 6441, 782, + 7049, 8775, 1763, 6441, 2226, + 7049, 8775, 1763, 6441, 2552, + 7049, 8775, 1763, 6441, 3814, + 7049, 8775, 1763, 6441, 5026, + 7049, 8775, 1763, 6441, 5450, + 7049, 8775, 1763, 6441, 10446, + 7049, 8775, 1763, 6441, 10448, + 7049, 8775, 1763, 6441, 11178, + 7049, 8775, 1763, 6441, 11180, + 7049, 8775, 2227, 2426, + 7049, 8775, 2227, 4768, + 7049, 8775, 3815, 2426, + 7049, 8775, 3815, 4768, + 7049, 8775, 5027, 2426, + 7049, 8775, 5027, 4768, + 7049, 8775, 5451, 2426, + 7049, 8775, 5451, 4768, + 7049, 8775, 9143, 2426, + 7049, 8775, 9143, 4768, + 7049, 8775, 9145, 2426, + 7049, 8775, 9145, 4768, + 7049, 8775, 9981, 2426, + 7049, 8775, 9981, 4768, + 7049, 8775, 9983, 2426, + 7049, 8775, 9983, 4768, + 7049, 8775, 9985, 2426, + 7049, 8775, 9985, 4768, + 7049, 8775, 10447, 2426, + 7049, 8775, 10447, 4768, + 7049, 8775, 10449, 2426, + 7049, 8775, 10449, 4768, + 7049, 8775, 11179, 2426, + 7049, 8775, 11179, 4768, + 7049, 8775, 11181, 2426, + 7049, 8775, 11181, 4768, + 7049, 8775, 11380, + 7049, 8775, 11716, + 7049, 9971, 8775, 5548, + 7049, 12053, 7803, 360, + 7049, 12053, 7803, 498, + 7049, 12053, 7803, 500, + 7049, 12053, 7803, 506, + 7049, 12053, 7803, 522, + 7049, 12053, 7803, 1850, + 7049, 12053, 7803, 2282, + 7049, 12053, 7803, 2286, + 7049, 12053, 7803, 2288, + 7049, 12053, 7803, 2292, + 7049, 12053, 7803, 2308, + 7049, 12053, 7803, 2321, 6031, 2170, + 7049, 12053, 7803, 2321, 6031, 2778, + 7049, 12053, 7803, 2334, + 7049, 12053, 7803, 2344, + 7049, 12053, 7803, 2478, + 7049, 12053, 7803, 5506, + 7085, 601, 5876, + 7085, 4117, 5876, + 7085, 4849, 10643, 10374, + 7085, 8056, + 7085, 8849, 10677, 761, 10374, + 7089, 6622, + 7089, 7593, 8405, 0, + 7089, 7593, 8405, 1, 6121, 1045, 6376, + 7089, 7593, 8405, 1, 6121, 1045, 6377, 721, 8432, + 7089, 7593, 8405, 1, 6121, 1045, 6490, + 7089, 7593, 8405, 1, 6121, 4531, 6376, + 7089, 7593, 8405, 1, 6121, 5551, 6376, + 7089, 7593, 8405, 1, 6121, 5551, 6377, 721, 6378, + 7089, 7593, 8405, 1, 6121, 5551, 6490, + 7089, 7593, 8405, 1, 6121, 6378, + 7089, 7593, 8405, 1, 6121, 6516, + 7089, 7593, 8405, 1, 6121, 6517, 721, 1045, 6490, + 7089, 7593, 8405, 1, 6121, 6517, 721, 4531, 6376, + 7089, 7593, 8405, 1, 6121, 6517, 721, 6378, + 7089, 7593, 8405, 1, 6121, 6517, 721, 6874, + 7089, 7593, 8405, 1, 6121, 6517, 721, 7708, + 7089, 7593, 8405, 1, 6121, 6546, + 7089, 7593, 8405, 1, 6121, 6874, + 7089, 7593, 8405, 1, 6121, 7443, 4389, 5550, + 7089, 7593, 8405, 1, 6121, 7708, + 7089, 7593, 8405, 1, 6121, 8153, 6874, + 7089, 7593, 8405, 1, 6121, 8432, + 7089, 7593, 8405, 1, 6121, 8534, + 7089, 7593, 8405, 1, 6121, 8758, + 7089, 7593, 8405, 1, 6121, 10267, 6516, + 7089, 7593, 8405, 1, 6121, 10804, + 7089, 7593, 8405, 1, 6121, 10805, 721, 8432, + 7089, 7593, 8405, 1, 6121, 11215, 4530, + 7089, 7593, 8405, 1, 6121, 11448, + 7089, 7593, 8405, 1, 6121, 11449, 721, 1045, 6490, + 7089, 7593, 8405, 1, 6121, 11449, 721, 4531, 6376, + 7089, 7593, 8405, 1, 6121, 11449, 721, 6378, + 7089, 7593, 8405, 1, 6121, 11449, 721, 6874, + 7089, 7593, 8405, 1, 6121, 11449, 721, 7708, + 7089, 7593, 8405, 2, + 7089, 7593, 8405, 3, 6121, 1045, 6376, + 7089, 7593, 8405, 3, 6121, 1045, 6490, + 7089, 7593, 8405, 3, 6121, 4530, + 7089, 7593, 8405, 3, 6121, 4877, 6490, + 7089, 7593, 8405, 3, 6121, 8473, 7708, + 7089, 7593, 8405, 3, 6121, 8758, + 7089, 7593, 8405, 3, 6121, 8846, + 7089, 7593, 8405, 3, 6121, 9553, 4530, + 7089, 7593, 8405, 4, + 7089, 7593, 8405, 5, 6121, 1045, 6376, + 7089, 7593, 8405, 5, 6121, 3966, + 7089, 7593, 8405, 5, 6121, 4530, + 7089, 7593, 8405, 5, 6121, 6378, + 7089, 7593, 8405, 5, 6121, 6546, + 7089, 7593, 8405, 5, 6121, 8758, + 7089, 7593, 8405, 5, 6121, 9072, + 7089, 7593, 8405, 5, 6121, 9073, 721, 6378, + 7089, 7593, 8405, 5, 6121, 11448, + 7089, 7593, 8405, 6, + 7089, 7593, 8405, 7, 6121, 1045, 6376, + 7089, 7593, 8405, 7, 6121, 1045, 6490, + 7089, 7593, 8405, 7, 6121, 3966, + 7089, 7593, 8405, 7, 6121, 4530, + 7089, 7593, 8405, 7, 6121, 4531, 721, 5878, + 7089, 7593, 8405, 7, 6121, 4877, 6490, + 7089, 7593, 8405, 7, 6121, 5878, + 7089, 7593, 8405, 7, 6121, 6546, + 7089, 7593, 8405, 7, 6121, 8473, 7708, + 7089, 7593, 8405, 7, 6121, 8758, + 7089, 7593, 8405, 7, 6121, 8846, + 7089, 7593, 8405, 7, 6121, 9072, + 7089, 7593, 8405, 7, 6121, 9553, 4530, + 7089, 7593, 8405, 7, 6121, 11449, 6490, + 7089, 7593, 8405, 8, + 7089, 7593, 8405, 9, 6121, 1045, 6376, + 7089, 7593, 8405, 9, 6121, 1045, 6490, + 7089, 7593, 8405, 9, 6121, 4531, 6376, + 7089, 7593, 8405, 9, 6121, 6378, + 7089, 7593, 8405, 9, 6121, 6516, + 7089, 7593, 8405, 9, 6121, 6546, + 7089, 7593, 8405, 9, 6121, 6874, + 7089, 7593, 8405, 9, 6121, 7272, + 7089, 7593, 8405, 9, 6121, 7708, + 7089, 7593, 8405, 9, 6121, 7709, 6490, + 7089, 7593, 8405, 9, 6121, 8153, 6874, + 7089, 7593, 8405, 9, 6121, 8432, + 7089, 7593, 8405, 9, 6121, 8433, 721, 6378, + 7089, 7593, 8405, 9, 6121, 8433, 721, 6874, + 7089, 7593, 8405, 9, 6121, 8534, + 7089, 7593, 8405, 9, 6121, 8758, + 7089, 7593, 8405, 9, 6121, 9072, + 7089, 7593, 8405, 9, 6121, 9073, 721, 6516, + 7089, 7593, 8405, 9, 6121, 10267, 6516, + 7089, 7593, 8405, 9, 6121, 10804, + 7089, 7593, 8405, 9, 6121, 11215, 4530, + 7089, 7593, 8405, 9, 6121, 11448, + 7089, 7593, 8405, 9, 6121, 11449, 721, 1045, 6490, + 7089, 7593, 8405, 9, 6121, 11449, 721, 4531, 6376, + 7089, 7593, 8405, 9, 6121, 11449, 721, 6378, + 7089, 7593, 8405, 9, 6121, 11449, 721, 6874, + 7089, 7593, 8405, 9, 6121, 11449, 721, 7708, + 7089, 7593, 8405, 9, 6121, 11449, 6490, + 7089, 7593, 8405, 10, + 7089, 7593, 8405, 11, 6121, 1045, 6376, + 7089, 7593, 8405, 11, 6121, 4530, + 7089, 7593, 8405, 11, 6121, 8473, 7708, + 7089, 7593, 8405, 11, 6121, 9553, 4530, + 7089, 7593, 8405, 12, + 7089, 7593, 8405, 13, 6121, 1045, 6376, + 7089, 7593, 8405, 13, 6121, 4530, + 7089, 7593, 8405, 13, 6121, 6378, + 7089, 7593, 8405, 13, 6121, 6516, + 7089, 7593, 8405, 13, 6121, 6546, + 7089, 7593, 8405, 13, 6121, 8432, + 7089, 7593, 8405, 13, 6121, 8758, + 7089, 7593, 8405, 13, 6121, 9072, + 7089, 7593, 8405, 13, 6121, 9553, 4530, + 7089, 7593, 8405, 13, 6121, 11448, + 7089, 7593, 8405, 14, + 7089, 7593, 8405, 15, 6121, 1045, 6376, + 7089, 7593, 8405, 15, 6121, 1045, 6490, + 7089, 7593, 8405, 15, 6121, 4530, + 7089, 7593, 8405, 15, 6121, 4877, 6490, + 7089, 7593, 8405, 15, 6121, 6517, 6490, + 7089, 7593, 8405, 15, 6121, 6546, + 7089, 7593, 8405, 15, 6121, 8758, + 7089, 7593, 8405, 15, 6121, 9072, + 7089, 7593, 8405, 15, 6121, 10802, + 7089, 7593, 8405, 15, 6121, 10804, + 7089, 7593, 8405, 15, 6121, 11448, + 7089, 7593, 8405, 16, + 7089, 7593, 8405, 17, 6121, 1045, 6490, + 7089, 7593, 8405, 17, 6121, 4531, 6376, + 7089, 7593, 8405, 17, 6121, 6378, + 7089, 7593, 8405, 17, 6121, 6516, + 7089, 7593, 8405, 17, 6121, 6546, + 7089, 7593, 8405, 17, 6121, 6874, + 7089, 7593, 8405, 17, 6121, 7708, + 7089, 7593, 8405, 17, 6121, 7709, 6490, + 7089, 7593, 8405, 17, 6121, 8153, 6874, + 7089, 7593, 8405, 17, 6121, 8432, + 7089, 7593, 8405, 17, 6121, 8534, + 7089, 7593, 8405, 17, 6121, 8758, + 7089, 7593, 8405, 17, 6121, 10267, 6516, + 7089, 7593, 8405, 17, 6121, 10804, + 7089, 7593, 8405, 17, 6121, 10805, 721, 6378, + 7089, 7593, 8405, 17, 6121, 11215, 4530, + 7089, 7593, 8405, 17, 6121, 11448, + 7089, 7593, 8405, 18, + 7089, 7593, 8405, 19, 6121, 6546, + 7089, 7593, 8405, 19, 6121, 8758, + 7089, 7593, 8405, 19, 6121, 11448, + 7089, 7593, 8405, 19, 6121, 12426, + 7089, 7593, 8405, 20, + 7089, 7593, 8405, 21, 6121, 1045, 6490, + 7089, 7593, 8405, 21, 6121, 4530, + 7089, 7593, 8405, 21, 6121, 4877, 6490, + 7089, 7593, 8405, 21, 6121, 6378, + 7089, 7593, 8405, 21, 6121, 6546, + 7089, 7593, 8405, 21, 6121, 8758, + 7089, 7593, 8405, 21, 6121, 8759, 721, 10001, 8758, + 7089, 7593, 8405, 21, 6121, 9072, + 7089, 7593, 8405, 21, 6121, 9553, 4530, + 7089, 7593, 8405, 21, 6121, 10001, 8758, + 7089, 7593, 8405, 21, 6121, 10802, + 7089, 7593, 8405, 22, + 7089, 7593, 8405, 23, 6121, 760, + 7089, 7593, 8405, 23, 6121, 1045, 6490, + 7089, 7593, 8405, 23, 6121, 1045, 6491, 721, 8432, + 7089, 7593, 8405, 23, 6121, 3770, + 7089, 7593, 8405, 23, 6121, 3966, + 7089, 7593, 8405, 23, 6121, 4423, 8758, + 7089, 7593, 8405, 23, 6121, 4877, 6490, + 7089, 7593, 8405, 23, 6121, 6378, + 7089, 7593, 8405, 23, 6121, 6546, + 7089, 7593, 8405, 23, 6121, 8153, 760, + 7089, 7593, 8405, 23, 6121, 8473, 1044, + 7089, 7593, 8405, 23, 6121, 8473, 7708, + 7089, 7593, 8405, 23, 6121, 8758, + 7089, 7593, 8405, 23, 6121, 9072, + 7089, 7593, 8405, 23, 6121, 9553, 4530, + 7089, 7593, 8405, 23, 6121, 11215, 4530, + 7089, 7593, 8405, 23, 6121, 11449, 6490, + 7089, 7593, 8405, 24, + 7089, 7593, 8405, 25, 6121, 1045, 6376, + 7089, 7593, 8405, 25, 6121, 1045, 6490, + 7089, 7593, 8405, 25, 6121, 4530, + 7089, 7593, 8405, 25, 6121, 6378, + 7089, 7593, 8405, 25, 6121, 8473, 7708, + 7089, 7593, 8405, 25, 6121, 9553, 4530, + 7089, 7593, 8405, 26, + 7089, 7593, 8405, 27, 6121, 1045, 6376, + 7089, 7593, 8405, 27, 6121, 1045, 6490, + 7089, 7593, 8405, 27, 6121, 3966, + 7089, 7593, 8405, 27, 6121, 4849, 4530, + 7089, 7593, 8405, 27, 6121, 4877, 6490, + 7089, 7593, 8405, 27, 6121, 4895, 7443, 1760, + 7089, 7593, 8405, 27, 6121, 6378, + 7089, 7593, 8405, 27, 6121, 6546, + 7089, 7593, 8405, 27, 6121, 6874, + 7089, 7593, 8405, 27, 6121, 7708, + 7089, 7593, 8405, 27, 6121, 8473, 7708, + 7089, 7593, 8405, 27, 6121, 9072, + 7089, 7593, 8405, 27, 6121, 9553, 4530, + 7089, 7593, 8405, 27, 6121, 11215, 4530, + 7089, 7593, 8405, 27, 6121, 11449, 6490, + 7089, 7593, 8405, 27, 10451, 115, 11424, + 7089, 7593, 8405, 28, + 7089, 7593, 8405, 29, 6121, 1045, 6376, + 7089, 7593, 8405, 29, 6121, 1045, 6377, 721, 8432, + 7089, 7593, 8405, 29, 6121, 1045, 6490, + 7089, 7593, 8405, 29, 6121, 1809, 5551, 8318, + 7089, 7593, 8405, 29, 6121, 4531, 6376, + 7089, 7593, 8405, 29, 6121, 4536, + 7089, 7593, 8405, 29, 6121, 4537, 721, 1045, 6490, + 7089, 7593, 8405, 29, 6121, 4537, 721, 4531, 6376, + 7089, 7593, 8405, 29, 6121, 4537, 721, 6378, + 7089, 7593, 8405, 29, 6121, 4537, 721, 6874, + 7089, 7593, 8405, 29, 6121, 4537, 721, 7708, + 7089, 7593, 8405, 29, 6121, 4895, 8759, 9548, + 7089, 7593, 8405, 29, 6121, 4896, + 7089, 7593, 8405, 29, 6121, 6378, + 7089, 7593, 8405, 29, 6121, 6516, + 7089, 7593, 8405, 29, 6121, 6546, + 7089, 7593, 8405, 29, 6121, 6874, + 7089, 7593, 8405, 29, 6121, 7708, + 7089, 7593, 8405, 29, 6121, 7709, 721, 6378, + 7089, 7593, 8405, 29, 6121, 7709, 721, 8432, + 7089, 7593, 8405, 29, 6121, 7709, 721, 10804, + 7089, 7593, 8405, 29, 6121, 8153, 6378, + 7089, 7593, 8405, 29, 6121, 8153, 6874, + 7089, 7593, 8405, 29, 6121, 8432, + 7089, 7593, 8405, 29, 6121, 8433, 721, 6378, + 7089, 7593, 8405, 29, 6121, 8433, 721, 6874, + 7089, 7593, 8405, 29, 6121, 8534, + 7089, 7593, 8405, 29, 6121, 8535, 721, 8432, + 7089, 7593, 8405, 29, 6121, 8758, + 7089, 7593, 8405, 29, 6121, 8759, 721, 6378, + 7089, 7593, 8405, 29, 6121, 10267, 6516, + 7089, 7593, 8405, 29, 6121, 10804, + 7089, 7593, 8405, 29, 6121, 10805, 721, 8432, + 7089, 7593, 8405, 29, 6121, 11448, + 7089, 7593, 8405, 29, 6121, 11449, 721, 1045, 6490, + 7089, 7593, 8405, 29, 6121, 11449, 721, 4531, 6376, + 7089, 7593, 8405, 29, 6121, 11449, 721, 6378, + 7089, 7593, 8405, 29, 6121, 11449, 721, 6874, + 7089, 7593, 8405, 29, 6121, 11449, 721, 7708, + 7089, 7593, 8405, 30, + 7089, 7593, 8405, 31, 6121, 1045, 6376, + 7089, 7593, 8405, 31, 6121, 4530, + 7089, 7593, 8405, 31, 6121, 6378, + 7089, 7593, 8405, 31, 6121, 8473, 7708, + 7089, 7593, 8405, 31, 6121, 8758, + 7089, 7593, 8405, 31, 6121, 8759, 9785, 10802, + 7089, 7593, 8405, 31, 6121, 9553, 4530, + 7089, 7593, 8405, 31, 6121, 10196, + 7089, 7593, 8405, 31, 6121, 10533, 5878, + 7089, 7593, 8405, 32, + 7089, 7593, 8405, 33, 6121, 4530, + 7089, 7593, 8405, 33, 6121, 4531, 5878, + 7089, 7593, 8405, 33, 6121, 8759, 9785, 10802, + 7089, 7593, 8405, 33, 6121, 10001, 8758, + 7089, 7593, 8405, 34, + 7089, 7593, 8405, 35, 6121, 1045, 6376, + 7089, 7593, 8405, 35, 6121, 1045, 6490, + 7089, 7593, 8405, 35, 6121, 1045, 6491, 721, 8432, + 7089, 7593, 8405, 35, 6121, 4877, 6490, + 7089, 7593, 8405, 35, 6121, 4895, 1760, + 7089, 7593, 8405, 35, 6121, 5878, + 7089, 7593, 8405, 35, 6121, 6378, + 7089, 7593, 8405, 35, 6121, 6546, + 7089, 7593, 8405, 35, 6121, 8153, 6874, + 7089, 7593, 8405, 35, 6121, 8473, 7708, + 7089, 7593, 8405, 35, 6121, 8758, + 7089, 7593, 8405, 35, 6121, 9072, + 7089, 7593, 8405, 35, 6121, 9553, 4530, + 7089, 7593, 8405, 35, 6121, 10190, + 7089, 7593, 8405, 35, 6121, 10191, 721, 8473, 7708, + 7089, 7593, 8405, 35, 6121, 10267, 6516, + 7089, 7593, 8405, 35, 9642, + 7089, 7593, 8405, 36, + 7089, 7593, 8405, 37, 6121, 1045, 6376, + 7089, 7593, 8405, 37, 6121, 1045, 6490, + 7089, 7593, 8405, 37, 6121, 1045, 6491, 721, 1045, 6376, + 7089, 7593, 8405, 37, 6121, 4530, + 7089, 7593, 8405, 37, 6121, 6378, + 7089, 7593, 8405, 37, 6121, 6379, 721, 1045, 6376, + 7089, 7593, 8405, 37, 6121, 6546, + 7089, 7593, 8405, 37, 6121, 6547, 721, 1045, 6376, + 7089, 7593, 8405, 37, 6121, 6617, 6490, + 7089, 7593, 8405, 37, 6121, 7653, 5878, + 7089, 7593, 8405, 37, 6121, 8473, 7708, + 7089, 7593, 8405, 37, 6121, 9072, + 7089, 7593, 8405, 37, 6121, 9553, 4530, + 7089, 7593, 8405, 37, 6121, 11448, + 7089, 7593, 8405, 38, + 7089, 7593, 8405, 39, 6121, 1045, 6376, + 7089, 7593, 8405, 39, 6121, 1045, 6490, + 7089, 7593, 8405, 39, 6121, 3966, + 7089, 7593, 8405, 39, 6121, 4530, + 7089, 7593, 8405, 39, 6121, 4877, 6490, + 7089, 7593, 8405, 39, 6121, 6546, + 7089, 7593, 8405, 39, 6121, 6617, 6490, + 7089, 7593, 8405, 39, 6121, 8473, 7708, + 7089, 7593, 8405, 39, 6121, 8758, + 7089, 7593, 8405, 39, 6121, 9072, + 7089, 7593, 8405, 39, 6121, 9553, 4530, + 7089, 7593, 8405, 39, 6121, 10001, 8758, + 7089, 7593, 8405, 39, 6121, 10804, + 7089, 7593, 8405, 39, 6121, 11215, 4530, + 7089, 7593, 8405, 39, 6121, 11449, 6490, + 7089, 7593, 8405, 40, + 7089, 7593, 8405, 41, 760, + 7089, 7593, 8405, 41, 6121, 1045, 6490, + 7089, 7593, 8405, 41, 6121, 4531, 6376, + 7089, 7593, 8405, 41, 6121, 4536, + 7089, 7593, 8405, 41, 6121, 4537, 721, 1045, 6490, + 7089, 7593, 8405, 41, 6121, 4537, 721, 4531, 6376, + 7089, 7593, 8405, 41, 6121, 4537, 721, 6378, + 7089, 7593, 8405, 41, 6121, 4537, 721, 6874, + 7089, 7593, 8405, 41, 6121, 4537, 721, 7708, + 7089, 7593, 8405, 41, 6121, 5551, 6376, + 7089, 7593, 8405, 41, 6121, 6378, + 7089, 7593, 8405, 41, 6121, 6516, + 7089, 7593, 8405, 41, 6121, 6546, + 7089, 7593, 8405, 41, 6121, 6874, + 7089, 7593, 8405, 41, 6121, 7708, + 7089, 7593, 8405, 41, 6121, 7709, 721, 6378, + 7089, 7593, 8405, 41, 6121, 7709, 6490, + 7089, 7593, 8405, 41, 6121, 8153, 6378, + 7089, 7593, 8405, 41, 6121, 8153, 6874, + 7089, 7593, 8405, 41, 6121, 8432, + 7089, 7593, 8405, 41, 6121, 8433, 721, 10804, + 7089, 7593, 8405, 41, 6121, 8534, + 7089, 7593, 8405, 41, 6121, 10267, 6516, + 7089, 7593, 8405, 41, 6121, 10804, + 7089, 7593, 8405, 41, 6121, 10805, 721, 6378, + 7089, 7593, 8405, 41, 6121, 10805, 721, 6546, + 7089, 7593, 8405, 41, 6121, 10805, 721, 6874, + 7089, 7593, 8405, 41, 6121, 10805, 721, 8432, + 7089, 7593, 8405, 41, 6121, 10805, 6490, + 7089, 7593, 8405, 41, 6121, 11215, 4530, + 7089, 7593, 8405, 41, 6121, 11448, + 7089, 7593, 8405, 41, 6121, 11449, 6490, + 7089, 7593, 8405, 42, + 7089, 7593, 8405, 43, 6121, 1045, 6490, + 7089, 7593, 8405, 43, 6121, 3966, + 7089, 7593, 8405, 43, 6121, 4530, + 7089, 7593, 8405, 43, 6121, 7443, 4530, + 7089, 7593, 8405, 43, 6121, 7708, + 7089, 7593, 8405, 43, 6121, 9553, 4530, + 7089, 7593, 8405, 43, 6121, 10001, 8758, + 7089, 7593, 8405, 44, + 7089, 7593, 8405, 45, 6121, 1045, 6376, + 7089, 7593, 8405, 45, 6121, 1045, 6490, + 7089, 7593, 8405, 45, 6121, 4530, + 7089, 7593, 8405, 45, 6121, 5551, 6376, + 7089, 7593, 8405, 45, 6121, 6378, + 7089, 7593, 8405, 45, 6121, 6874, + 7089, 7593, 8405, 45, 6121, 10804, + 7089, 7593, 8405, 45, 6121, 11448, + 7089, 7593, 8405, 46, + 7089, 7593, 8405, 47, 6121, 1045, 6376, + 7089, 7593, 8405, 47, 6121, 9553, 4530, + 7089, 7593, 8405, 47, 6121, 10804, + 7089, 7593, 8405, 48, + 7089, 7593, 8405, 49, 6121, 1045, 6376, + 7089, 7593, 8405, 49, 6121, 1045, 6490, + 7089, 7593, 8405, 49, 6121, 4530, + 7089, 7593, 8405, 49, 6121, 4531, 6376, + 7089, 7593, 8405, 49, 6121, 4896, + 7089, 7593, 8405, 49, 6121, 5551, 6376, + 7089, 7593, 8405, 49, 6121, 6378, + 7089, 7593, 8405, 49, 6121, 6874, + 7089, 7593, 8405, 49, 6121, 7708, + 7089, 7593, 8405, 49, 6121, 8432, + 7089, 7593, 8405, 49, 6121, 8758, + 7089, 7593, 8405, 49, 6121, 10804, + 7089, 7593, 8405, 49, 6121, 11448, + 7089, 7593, 8405, 50, + 7089, 7593, 8405, 51, 6121, 1045, 6376, + 7089, 7593, 8405, 51, 6121, 1045, 6490, + 7089, 7593, 8405, 51, 6121, 3966, + 7089, 7593, 8405, 51, 6121, 4530, + 7089, 7593, 8405, 51, 6121, 4877, 6490, + 7089, 7593, 8405, 51, 6121, 6378, + 7089, 7593, 8405, 51, 6121, 6546, + 7089, 7593, 8405, 51, 6121, 7653, 5878, + 7089, 7593, 8405, 51, 6121, 8473, 7708, + 7089, 7593, 8405, 51, 6121, 8758, + 7089, 7593, 8405, 51, 6121, 9553, 4530, + 7089, 7593, 8405, 51, 6121, 10802, + 7089, 7593, 8405, 51, 6121, 11215, 4530, + 7089, 7593, 8405, 51, 6121, 11448, + 7089, 7593, 8405, 58, + 7089, 7593, 8405, 66, + 7089, 7593, 8405, 67, 6121, 6378, + 7089, 7593, 8405, 67, 6121, 8432, + 7089, 7593, 8405, 82, + 7089, 7593, 8405, 92, + 7089, 7593, 8405, 94, + 7089, 7593, 8405, 95, 6121, 11649, 760, + 7089, 7593, 8405, 98, + 7089, 7593, 8405, 141, 9164, + 7089, 7593, 8405, 156, + 7089, 7593, 8405, 157, 6121, 6546, + 7089, 7593, 8405, 157, 9164, + 7089, 7593, 8405, 157, 9165, 6121, 3966, + 7089, 7593, 8405, 186, + 7089, 7593, 8405, 252, + 7089, 7593, 8405, 282, + 7089, 7593, 8405, 342, + 7089, 7593, 8405, 353, 9164, + 7089, 7593, 8405, 363, 9164, + 7089, 7593, 8405, 406, + 7089, 7593, 8405, 432, + 7089, 7593, 8405, 440, + 7089, 7593, 8405, 450, + 7089, 7593, 8405, 505, 9164, + 7089, 7593, 8405, 559, 9165, 6121, 3966, + 7089, 7593, 8405, 563, 6121, 13018, + 7089, 7593, 8405, 573, 9164, + 7089, 7593, 8405, 578, + 7089, 7593, 8405, 590, + 7089, 7593, 8405, 594, + 7089, 7593, 8405, 620, + 7089, 7593, 8405, 912, + 7089, 7593, 8405, 1058, + 7089, 7593, 8405, 1110, + 7089, 7593, 8405, 1124, + 7089, 7593, 8405, 1125, 6121, 3966, + 7089, 7593, 8405, 1125, 6121, 9553, 4530, + 7089, 7593, 8405, 1125, 6121, 11215, 4530, + 7089, 7593, 8405, 1130, + 7089, 7593, 8405, 1138, + 7089, 7593, 8405, 1139, 6121, 3966, + 7089, 7593, 8405, 1139, 6121, 5878, + 7089, 7593, 8405, 1139, 6121, 6546, + 7089, 7593, 8405, 1139, 6121, 11215, 4530, + 7089, 7593, 8405, 1139, 10488, + 7089, 7593, 8405, 1678, + 7089, 7593, 8405, 1822, + 7089, 7593, 8405, 1952, + 7089, 7593, 8405, 2108, + 7089, 7593, 8405, 2216, + 7089, 7593, 8405, 2452, + 7089, 7593, 8405, 2453, 9642, + 7089, 7593, 8405, 2725, 4389, 28, + 7089, 7593, 8405, 2760, + 7089, 7593, 8405, 4065, 9164, + 7089, 7593, 8405, 4187, 9164, + 7089, 7593, 8405, 4389, 14, + 7089, 7593, 8405, 4404, + 7089, 7593, 8405, 4405, 6121, 4530, + 7089, 7593, 8405, 4614, + 7089, 7593, 8405, 4615, 6121, 8758, + 7089, 7593, 8405, 4854, + 7089, 7593, 8405, 4895, 36, + 7089, 7593, 8405, 4895, 37, 6121, 1045, 6376, + 7089, 7593, 8405, 4895, 37, 6121, 4423, 8758, + 7089, 7593, 8405, 4895, 37, 6121, 10001, 8758, + 7089, 7593, 8405, 5385, 8, + 7089, 7593, 8405, 5385, 9, 6121, 11215, 4530, + 7089, 7593, 8405, 5385, 28, + 7089, 7593, 8405, 5385, 29, 6121, 11215, 4530, + 7089, 7593, 8405, 5527, 4536, + 7089, 7593, 8405, 5901, 9164, + 7089, 7593, 8405, 5965, 2540, + 7089, 7593, 8405, 5965, 2778, + 7089, 7593, 8405, 5965, 4200, + 7089, 7593, 8405, 6078, + 7089, 7593, 8405, 6220, + 7089, 7593, 8405, 6406, + 7089, 7593, 8405, 6407, 6121, 11215, 4530, + 7089, 7593, 8405, 6674, + 7089, 7593, 8405, 6824, + 7089, 7593, 8405, 7494, + 7089, 7593, 8405, 7495, 6121, 4530, + 7089, 7593, 8405, 7495, 6121, 11215, 4530, + 7089, 7593, 8405, 7519, 36, + 7089, 7593, 8405, 7619, 10489, 1124, + 7089, 7593, 8405, 7692, + 7089, 7593, 8405, 7693, 6121, 8758, + 7089, 7593, 8405, 7693, 6121, 8759, 9785, 10802, + 7089, 7593, 8405, 7981, 28, + 7089, 7593, 8405, 8005, 4389, 28, + 7089, 7593, 8405, 8017, 22, + 7089, 7593, 8405, 8065, 5385, 8, + 7089, 7593, 8405, 8065, 7316, + 7089, 7593, 8405, 8065, 10489, 5385, 8, + 7089, 7593, 8405, 8387, 6121, 8758, + 7089, 7593, 8405, 8679, 12, + 7089, 7593, 8405, 8869, 0, + 7089, 7593, 8405, 8869, 8, + 7089, 7593, 8405, 8869, 12, + 7089, 7593, 8405, 8869, 14, + 7089, 7593, 8405, 8869, 15, 6121, 10190, + 7089, 7593, 8405, 8869, 15, 6121, 10191, 721, 5878, + 7089, 7593, 8405, 8869, 16, + 7089, 7593, 8405, 8869, 20, + 7089, 7593, 8405, 8869, 22, + 7089, 7593, 8405, 8869, 24, + 7089, 7593, 8405, 8869, 25, 6121, 4895, 1760, + 7089, 7593, 8405, 8869, 34, + 7089, 7593, 8405, 8869, 35, 6121, 4530, + 7089, 7593, 8405, 8869, 35, 6121, 4895, 1760, + 7089, 7593, 8405, 8869, 35, 6121, 5878, + 7089, 7593, 8405, 8869, 38, + 7089, 7593, 8405, 8869, 42, + 7089, 7593, 8405, 8869, 44, + 7089, 7593, 8405, 8869, 48, + 7089, 7593, 8405, 8869, 66, + 7089, 7593, 8405, 8869, 426, + 7089, 7593, 8405, 8869, 5385, 8, + 7089, 7593, 8405, 8869, 6406, + 7089, 7593, 8405, 8869, 6674, + 7089, 7593, 8405, 8869, 9365, 12, + 7089, 7593, 8405, 9185, 16, + 7089, 7593, 8405, 9185, 18, + 7089, 7593, 8405, 9185, 19, 6121, 8758, + 7089, 7593, 8405, 9185, 19, 6121, 8759, 721, 4530, + 7089, 7593, 8405, 9313, 5836, + 7089, 7593, 8405, 9365, 6, + 7089, 7593, 8405, 9365, 10, + 7089, 7593, 8405, 9365, 12, + 7089, 7593, 8405, 9365, 34, + 7089, 7593, 8405, 9365, 36, + 7089, 7593, 8405, 9365, 38, + 7089, 7593, 8405, 9808, + 7089, 7593, 8405, 9809, 6121, 8758, + 7089, 7593, 8405, 10489, 4, + 7089, 7593, 8405, 10489, 5, 6121, 1044, + 7089, 7593, 8405, 10489, 8, + 7089, 7593, 8405, 10489, 35, 6121, 10190, + 7089, 7593, 8405, 10489, 5385, 8, + 7089, 7593, 8405, 10489, 5385, 9, 6121, 4530, + 7089, 7593, 8405, 10489, 5385, 9, 6121, 11215, 4530, + 7089, 7593, 8405, 10494, + 7089, 7593, 8405, 10523, 28, + 7089, 7593, 8405, 10523, 29, 6121, 8758, + 7089, 7593, 8405, 10523, 40, + 7089, 7593, 8405, 10523, 5385, 28, + 7089, 7593, 8405, 10523, 8869, 24, + 7089, 7593, 8405, 10523, 11941, 40, + 7089, 7593, 8405, 10609, 2216, + 7089, 7593, 8405, 10640, + 7089, 7593, 8405, 10786, + 7089, 7593, 8405, 10787, 6121, 6616, + 7089, 7593, 8405, 11879, 50, + 7089, 7593, 8405, 12507, 42, + 7089, 7593, 8405, 12507, 344, + 7089, 7593, 8405, 12935, 710, + 7089, 7593, 8405, 12935, 3244, + 7089, 7593, 9063, 8405, 17, 6121, 8758, + 7089, 7593, 9063, 8405, 41, 6121, 8758, + 7089, 7593, 10301, 200, + 7089, 7593, 10301, 202, + 7089, 7593, 10301, 204, + 7089, 7593, 10301, 268, + 7089, 7593, 10301, 426, + 7089, 7593, 10301, 544, + 7089, 7593, 10301, 1156, + 7089, 7593, 10301, 1158, + 7089, 7593, 10301, 4895, 37, 38, + 7089, 8405, 662, + 7089, 8405, 710, + 7089, 8405, 2779, 6121, 8758, + 7089, 8405, 6138, + 7089, 8405, 7593, 9063, 0, + 7089, 8405, 7593, 9063, 2, + 7089, 8405, 7593, 9063, 4, + 7089, 8405, 7593, 9063, 6, + 7089, 8405, 7593, 9063, 8, + 7089, 8405, 7593, 9063, 10, + 7089, 8405, 7593, 9063, 12, + 7089, 8405, 7593, 9063, 13, 6121, 4530, + 7089, 8405, 7593, 9063, 14, + 7089, 8405, 7593, 9063, 16, + 7089, 8405, 7593, 9063, 18, + 7089, 8405, 7593, 9063, 20, + 7089, 8405, 7593, 9063, 22, + 7089, 8405, 7593, 9063, 23, 6121, 8758, + 7089, 8405, 7593, 9063, 24, + 7089, 8405, 7593, 9063, 26, + 7089, 8405, 7593, 9063, 28, + 7089, 8405, 7593, 9063, 30, + 7089, 8405, 7593, 9063, 34, + 7089, 8405, 7593, 9063, 36, + 7089, 8405, 7593, 9063, 38, + 7089, 8405, 7593, 9063, 40, + 7089, 8405, 7593, 9063, 42, + 7089, 8405, 7593, 9063, 44, + 7089, 8405, 7593, 9063, 48, + 7089, 8405, 7593, 9063, 50, + 7089, 8405, 7593, 9063, 66, + 7089, 8405, 7593, 9063, 426, + 7089, 8405, 7593, 9063, 450, + 7089, 8405, 7593, 9063, 1130, + 7089, 8405, 7593, 9063, 1138, + 7089, 8405, 7593, 9063, 2452, + 7089, 8405, 7593, 9063, 5385, 28, + 7089, 8405, 7593, 9063, 7981, 2, + 7089, 8405, 7593, 9063, 8869, 8, + 7089, 8405, 7593, 9063, 8869, 34, + 7089, 8405, 7593, 9063, 10267, 34, + 7089, 8405, 7593, 9063, 10489, 26, + 7089, 8405, 7593, 9063, 10489, 34, + 7089, 8405, 8107, 6598, + 7089, 8405, 8921, 11089, 9728, + 7089, 8405, 9313, 5836, + 7089, 8405, 9313, 5837, 6121, 8758, + 7089, 8405, 9423, 6598, + 7089, 8405, 9865, 6598, + 7089, 8405, 9915, 11720, + 7089, 8405, 9917, 6598, + 7089, 8405, 9917, 11720, + 7089, 8405, 10267, 9313, 5836, + 7089, 8405, 10267, 9313, 5837, 6121, 8758, + 7089, 8405, 10489, 1125, 4896, + 7089, 8405, 10489, 9313, 5837, 6121, 8758, + 7089, 8405, 11215, 6598, + 7089, 8405, 11251, 4, + 7089, 8405, 11723, 8921, 11008, + 7089, 9063, 8405, 0, + 7089, 9063, 8405, 1, 6121, 1045, 6376, + 7089, 9063, 8405, 1, 6121, 1045, 6377, 721, 8432, + 7089, 9063, 8405, 1, 6121, 1045, 6490, + 7089, 9063, 8405, 1, 6121, 4531, 6376, + 7089, 9063, 8405, 1, 6121, 5551, 6376, + 7089, 9063, 8405, 1, 6121, 5551, 6377, 721, 6378, + 7089, 9063, 8405, 1, 6121, 5551, 6490, + 7089, 9063, 8405, 1, 6121, 6378, + 7089, 9063, 8405, 1, 6121, 6516, + 7089, 9063, 8405, 1, 6121, 6517, 721, 1045, 6490, + 7089, 9063, 8405, 1, 6121, 6517, 721, 4531, 6376, + 7089, 9063, 8405, 1, 6121, 6517, 721, 6378, + 7089, 9063, 8405, 1, 6121, 6517, 721, 6874, + 7089, 9063, 8405, 1, 6121, 6517, 721, 7708, + 7089, 9063, 8405, 1, 6121, 6546, + 7089, 9063, 8405, 1, 6121, 6874, + 7089, 9063, 8405, 1, 6121, 7708, + 7089, 9063, 8405, 1, 6121, 8153, 6874, + 7089, 9063, 8405, 1, 6121, 8432, + 7089, 9063, 8405, 1, 6121, 8534, + 7089, 9063, 8405, 1, 6121, 8758, + 7089, 9063, 8405, 1, 6121, 10267, 6516, + 7089, 9063, 8405, 1, 6121, 10804, + 7089, 9063, 8405, 1, 6121, 10805, 721, 8432, + 7089, 9063, 8405, 1, 6121, 11448, + 7089, 9063, 8405, 1, 6121, 11449, 721, 1045, 6490, + 7089, 9063, 8405, 1, 6121, 11449, 721, 4531, 6376, + 7089, 9063, 8405, 1, 6121, 11449, 721, 6378, + 7089, 9063, 8405, 1, 6121, 11449, 721, 6874, + 7089, 9063, 8405, 1, 6121, 11449, 721, 7708, + 7089, 9063, 8405, 2, + 7089, 9063, 8405, 3, 6121, 1045, 6376, + 7089, 9063, 8405, 3, 6121, 1045, 6490, + 7089, 9063, 8405, 3, 6121, 4530, + 7089, 9063, 8405, 3, 6121, 4877, 6490, + 7089, 9063, 8405, 3, 6121, 8758, + 7089, 9063, 8405, 3, 6121, 8846, + 7089, 9063, 8405, 4, + 7089, 9063, 8405, 5, 6121, 1045, 6376, + 7089, 9063, 8405, 5, 6121, 4530, + 7089, 9063, 8405, 5, 6121, 6378, + 7089, 9063, 8405, 5, 6121, 6546, + 7089, 9063, 8405, 5, 6121, 8758, + 7089, 9063, 8405, 5, 6121, 9072, + 7089, 9063, 8405, 5, 6121, 9073, 721, 6378, + 7089, 9063, 8405, 5, 6121, 11448, + 7089, 9063, 8405, 6, + 7089, 9063, 8405, 7, 6121, 1045, 6376, + 7089, 9063, 8405, 7, 6121, 1045, 6490, + 7089, 9063, 8405, 7, 6121, 4530, + 7089, 9063, 8405, 7, 6121, 4877, 6490, + 7089, 9063, 8405, 7, 6121, 6546, + 7089, 9063, 8405, 7, 6121, 7593, 8405, 50, + 7089, 9063, 8405, 7, 6121, 7593, 8405, 51, 6121, 6546, + 7089, 9063, 8405, 7, 6121, 8758, + 7089, 9063, 8405, 7, 6121, 8846, + 7089, 9063, 8405, 7, 6121, 9072, + 7089, 9063, 8405, 7, 6121, 11449, 6490, + 7089, 9063, 8405, 8, + 7089, 9063, 8405, 9, 6121, 1045, 6376, + 7089, 9063, 8405, 9, 6121, 1045, 6490, + 7089, 9063, 8405, 9, 6121, 4531, 6376, + 7089, 9063, 8405, 9, 6121, 6378, + 7089, 9063, 8405, 9, 6121, 6516, + 7089, 9063, 8405, 9, 6121, 6546, + 7089, 9063, 8405, 9, 6121, 6874, + 7089, 9063, 8405, 9, 6121, 7708, + 7089, 9063, 8405, 9, 6121, 7709, 6490, + 7089, 9063, 8405, 9, 6121, 8153, 6874, + 7089, 9063, 8405, 9, 6121, 8432, + 7089, 9063, 8405, 9, 6121, 8433, 721, 6378, + 7089, 9063, 8405, 9, 6121, 8433, 721, 6874, + 7089, 9063, 8405, 9, 6121, 8534, + 7089, 9063, 8405, 9, 6121, 8758, + 7089, 9063, 8405, 9, 6121, 9072, + 7089, 9063, 8405, 9, 6121, 9073, 721, 6516, + 7089, 9063, 8405, 9, 6121, 10267, 6516, + 7089, 9063, 8405, 9, 6121, 10804, + 7089, 9063, 8405, 9, 6121, 11448, + 7089, 9063, 8405, 9, 6121, 11449, 721, 1045, 6490, + 7089, 9063, 8405, 9, 6121, 11449, 721, 4531, 6376, + 7089, 9063, 8405, 9, 6121, 11449, 721, 6378, + 7089, 9063, 8405, 9, 6121, 11449, 721, 6874, + 7089, 9063, 8405, 9, 6121, 11449, 721, 7708, + 7089, 9063, 8405, 9, 6121, 11449, 6490, + 7089, 9063, 8405, 10, + 7089, 9063, 8405, 11, 6121, 1045, 6376, + 7089, 9063, 8405, 11, 6121, 4530, + 7089, 9063, 8405, 12, + 7089, 9063, 8405, 13, 6121, 1045, 6376, + 7089, 9063, 8405, 13, 6121, 4530, + 7089, 9063, 8405, 13, 6121, 6378, + 7089, 9063, 8405, 13, 6121, 6516, + 7089, 9063, 8405, 13, 6121, 6546, + 7089, 9063, 8405, 13, 6121, 8432, + 7089, 9063, 8405, 13, 6121, 8758, + 7089, 9063, 8405, 13, 6121, 9072, + 7089, 9063, 8405, 13, 6121, 11448, + 7089, 9063, 8405, 14, + 7089, 9063, 8405, 15, 6121, 1045, 6376, + 7089, 9063, 8405, 15, 6121, 1045, 6490, + 7089, 9063, 8405, 15, 6121, 6517, 6490, + 7089, 9063, 8405, 15, 6121, 6546, + 7089, 9063, 8405, 15, 6121, 8758, + 7089, 9063, 8405, 15, 6121, 9072, + 7089, 9063, 8405, 15, 6121, 10802, + 7089, 9063, 8405, 15, 6121, 10804, + 7089, 9063, 8405, 15, 6121, 11448, + 7089, 9063, 8405, 16, + 7089, 9063, 8405, 17, 6121, 1045, 6376, + 7089, 9063, 8405, 17, 6121, 1045, 6490, + 7089, 9063, 8405, 17, 6121, 4531, 6376, + 7089, 9063, 8405, 17, 6121, 6378, + 7089, 9063, 8405, 17, 6121, 6516, + 7089, 9063, 8405, 17, 6121, 6546, + 7089, 9063, 8405, 17, 6121, 6874, + 7089, 9063, 8405, 17, 6121, 7708, + 7089, 9063, 8405, 17, 6121, 7709, 6490, + 7089, 9063, 8405, 17, 6121, 8153, 6874, + 7089, 9063, 8405, 17, 6121, 8432, + 7089, 9063, 8405, 17, 6121, 8534, + 7089, 9063, 8405, 17, 6121, 8758, + 7089, 9063, 8405, 17, 6121, 10267, 6516, + 7089, 9063, 8405, 17, 6121, 10804, + 7089, 9063, 8405, 17, 6121, 10805, 721, 6378, + 7089, 9063, 8405, 17, 6121, 11448, + 7089, 9063, 8405, 18, + 7089, 9063, 8405, 19, 6121, 8758, + 7089, 9063, 8405, 19, 6121, 11448, + 7089, 9063, 8405, 20, + 7089, 9063, 8405, 21, 6121, 1045, 6490, + 7089, 9063, 8405, 21, 6121, 4530, + 7089, 9063, 8405, 21, 6121, 4877, 6490, + 7089, 9063, 8405, 21, 6121, 6378, + 7089, 9063, 8405, 21, 6121, 6546, + 7089, 9063, 8405, 21, 6121, 8758, + 7089, 9063, 8405, 21, 6121, 8759, 721, 10001, 8758, + 7089, 9063, 8405, 21, 6121, 9072, + 7089, 9063, 8405, 21, 6121, 10001, 8758, + 7089, 9063, 8405, 21, 6121, 10802, + 7089, 9063, 8405, 22, + 7089, 9063, 8405, 23, 6121, 760, + 7089, 9063, 8405, 23, 6121, 1045, 6490, + 7089, 9063, 8405, 23, 6121, 1045, 6491, 721, 8432, + 7089, 9063, 8405, 23, 6121, 4423, 8758, + 7089, 9063, 8405, 23, 6121, 4877, 6490, + 7089, 9063, 8405, 23, 6121, 6378, + 7089, 9063, 8405, 23, 6121, 6546, + 7089, 9063, 8405, 23, 6121, 7593, 8405, 18, + 7089, 9063, 8405, 23, 6121, 8153, 760, + 7089, 9063, 8405, 23, 6121, 8473, 1044, + 7089, 9063, 8405, 23, 6121, 8473, 7708, + 7089, 9063, 8405, 23, 6121, 8758, + 7089, 9063, 8405, 23, 6121, 9072, + 7089, 9063, 8405, 23, 6121, 11449, 6490, + 7089, 9063, 8405, 24, + 7089, 9063, 8405, 25, 6121, 1045, 6376, + 7089, 9063, 8405, 25, 6121, 1045, 6490, + 7089, 9063, 8405, 25, 6121, 4530, + 7089, 9063, 8405, 25, 6121, 6378, + 7089, 9063, 8405, 26, + 7089, 9063, 8405, 27, 6121, 1045, 6376, + 7089, 9063, 8405, 27, 6121, 1045, 6490, + 7089, 9063, 8405, 27, 6121, 4849, 4530, + 7089, 9063, 8405, 27, 6121, 4877, 6490, + 7089, 9063, 8405, 27, 6121, 4895, 7443, 1760, + 7089, 9063, 8405, 27, 6121, 6378, + 7089, 9063, 8405, 27, 6121, 6546, + 7089, 9063, 8405, 27, 6121, 6874, + 7089, 9063, 8405, 27, 6121, 7593, 8405, 18, + 7089, 9063, 8405, 27, 6121, 7708, + 7089, 9063, 8405, 27, 6121, 9072, + 7089, 9063, 8405, 27, 6121, 11449, 6490, + 7089, 9063, 8405, 28, + 7089, 9063, 8405, 29, 6121, 1045, 6376, + 7089, 9063, 8405, 29, 6121, 1045, 6377, 721, 8432, + 7089, 9063, 8405, 29, 6121, 1045, 6490, + 7089, 9063, 8405, 29, 6121, 4531, 6376, + 7089, 9063, 8405, 29, 6121, 4536, + 7089, 9063, 8405, 29, 6121, 4537, 721, 1045, 6490, + 7089, 9063, 8405, 29, 6121, 4537, 721, 4531, 6376, + 7089, 9063, 8405, 29, 6121, 4537, 721, 6378, + 7089, 9063, 8405, 29, 6121, 4537, 721, 6874, + 7089, 9063, 8405, 29, 6121, 4537, 721, 7708, + 7089, 9063, 8405, 29, 6121, 4895, 8759, 9548, + 7089, 9063, 8405, 29, 6121, 4896, + 7089, 9063, 8405, 29, 6121, 6378, + 7089, 9063, 8405, 29, 6121, 6516, + 7089, 9063, 8405, 29, 6121, 6546, + 7089, 9063, 8405, 29, 6121, 6874, + 7089, 9063, 8405, 29, 6121, 7708, + 7089, 9063, 8405, 29, 6121, 7709, 721, 6378, + 7089, 9063, 8405, 29, 6121, 7709, 721, 8432, + 7089, 9063, 8405, 29, 6121, 7709, 721, 10804, + 7089, 9063, 8405, 29, 6121, 8153, 6378, + 7089, 9063, 8405, 29, 6121, 8153, 6874, + 7089, 9063, 8405, 29, 6121, 8432, + 7089, 9063, 8405, 29, 6121, 8433, 721, 6378, + 7089, 9063, 8405, 29, 6121, 8433, 721, 6874, + 7089, 9063, 8405, 29, 6121, 8473, 7708, + 7089, 9063, 8405, 29, 6121, 8534, + 7089, 9063, 8405, 29, 6121, 8535, 721, 8432, + 7089, 9063, 8405, 29, 6121, 8758, + 7089, 9063, 8405, 29, 6121, 8759, 721, 6378, + 7089, 9063, 8405, 29, 6121, 10267, 6516, + 7089, 9063, 8405, 29, 6121, 10804, + 7089, 9063, 8405, 29, 6121, 10805, 721, 8432, + 7089, 9063, 8405, 29, 6121, 11448, + 7089, 9063, 8405, 29, 6121, 11449, 721, 1045, 6490, + 7089, 9063, 8405, 29, 6121, 11449, 721, 4531, 6376, + 7089, 9063, 8405, 29, 6121, 11449, 721, 6378, + 7089, 9063, 8405, 29, 6121, 11449, 721, 6874, + 7089, 9063, 8405, 29, 6121, 11449, 721, 7708, + 7089, 9063, 8405, 30, + 7089, 9063, 8405, 31, 6121, 1045, 6376, + 7089, 9063, 8405, 31, 6121, 4530, + 7089, 9063, 8405, 31, 6121, 6378, + 7089, 9063, 8405, 31, 6121, 8758, + 7089, 9063, 8405, 31, 6121, 8759, 9785, 10802, + 7089, 9063, 8405, 31, 6121, 10196, + 7089, 9063, 8405, 31, 6121, 10533, 5878, + 7089, 9063, 8405, 32, + 7089, 9063, 8405, 33, 6121, 8759, 9785, 10802, + 7089, 9063, 8405, 33, 6121, 10001, 8758, + 7089, 9063, 8405, 34, + 7089, 9063, 8405, 35, 6121, 1045, 6376, + 7089, 9063, 8405, 35, 6121, 1045, 6490, + 7089, 9063, 8405, 35, 6121, 1045, 6491, 721, 8432, + 7089, 9063, 8405, 35, 6121, 4877, 6490, + 7089, 9063, 8405, 35, 6121, 5878, + 7089, 9063, 8405, 35, 6121, 6378, + 7089, 9063, 8405, 35, 6121, 6546, + 7089, 9063, 8405, 35, 6121, 8153, 6874, + 7089, 9063, 8405, 35, 6121, 8758, + 7089, 9063, 8405, 35, 6121, 9072, + 7089, 9063, 8405, 35, 6121, 10267, 6516, + 7089, 9063, 8405, 35, 9642, + 7089, 9063, 8405, 36, + 7089, 9063, 8405, 37, 6121, 1045, 6376, + 7089, 9063, 8405, 37, 6121, 1045, 6490, + 7089, 9063, 8405, 37, 6121, 1045, 6491, 721, 1045, 6376, + 7089, 9063, 8405, 37, 6121, 6378, + 7089, 9063, 8405, 37, 6121, 6379, 721, 1045, 6376, + 7089, 9063, 8405, 37, 6121, 6546, + 7089, 9063, 8405, 37, 6121, 6547, 721, 1045, 6376, + 7089, 9063, 8405, 37, 6121, 6617, 6490, + 7089, 9063, 8405, 37, 6121, 9072, + 7089, 9063, 8405, 37, 6121, 11448, + 7089, 9063, 8405, 38, + 7089, 9063, 8405, 39, 6121, 1045, 6376, + 7089, 9063, 8405, 39, 6121, 1045, 6490, + 7089, 9063, 8405, 39, 6121, 4530, + 7089, 9063, 8405, 39, 6121, 4877, 6490, + 7089, 9063, 8405, 39, 6121, 6546, + 7089, 9063, 8405, 39, 6121, 6617, 6490, + 7089, 9063, 8405, 39, 6121, 8758, + 7089, 9063, 8405, 39, 6121, 9072, + 7089, 9063, 8405, 39, 6121, 10001, 8758, + 7089, 9063, 8405, 39, 6121, 11215, 4530, + 7089, 9063, 8405, 39, 6121, 11449, 6490, + 7089, 9063, 8405, 40, + 7089, 9063, 8405, 41, 760, + 7089, 9063, 8405, 41, 6121, 1045, 6490, + 7089, 9063, 8405, 41, 6121, 4531, 6376, + 7089, 9063, 8405, 41, 6121, 4536, + 7089, 9063, 8405, 41, 6121, 4537, 721, 1045, 6490, + 7089, 9063, 8405, 41, 6121, 4537, 721, 4531, 6376, + 7089, 9063, 8405, 41, 6121, 4537, 721, 6378, + 7089, 9063, 8405, 41, 6121, 4537, 721, 6874, + 7089, 9063, 8405, 41, 6121, 4537, 721, 7708, + 7089, 9063, 8405, 41, 6121, 5551, 6376, + 7089, 9063, 8405, 41, 6121, 6378, + 7089, 9063, 8405, 41, 6121, 6516, + 7089, 9063, 8405, 41, 6121, 6546, + 7089, 9063, 8405, 41, 6121, 6874, + 7089, 9063, 8405, 41, 6121, 7708, + 7089, 9063, 8405, 41, 6121, 7709, 721, 6378, + 7089, 9063, 8405, 41, 6121, 7709, 6490, + 7089, 9063, 8405, 41, 6121, 8153, 6378, + 7089, 9063, 8405, 41, 6121, 8153, 6874, + 7089, 9063, 8405, 41, 6121, 8432, + 7089, 9063, 8405, 41, 6121, 8433, 721, 10804, + 7089, 9063, 8405, 41, 6121, 8534, + 7089, 9063, 8405, 41, 6121, 10267, 6516, + 7089, 9063, 8405, 41, 6121, 10804, + 7089, 9063, 8405, 41, 6121, 10805, 721, 6378, + 7089, 9063, 8405, 41, 6121, 10805, 721, 6546, + 7089, 9063, 8405, 41, 6121, 10805, 721, 6874, + 7089, 9063, 8405, 41, 6121, 10805, 721, 8432, + 7089, 9063, 8405, 41, 6121, 10805, 6490, + 7089, 9063, 8405, 41, 6121, 11448, + 7089, 9063, 8405, 41, 6121, 11449, 6490, + 7089, 9063, 8405, 42, + 7089, 9063, 8405, 43, 6121, 1045, 6490, + 7089, 9063, 8405, 43, 6121, 4530, + 7089, 9063, 8405, 43, 6121, 7708, + 7089, 9063, 8405, 43, 6121, 10001, 8758, + 7089, 9063, 8405, 44, + 7089, 9063, 8405, 45, 6121, 1045, 6376, + 7089, 9063, 8405, 45, 6121, 1045, 6490, + 7089, 9063, 8405, 45, 6121, 4530, + 7089, 9063, 8405, 45, 6121, 6378, + 7089, 9063, 8405, 45, 6121, 6874, + 7089, 9063, 8405, 45, 6121, 10804, + 7089, 9063, 8405, 45, 6121, 11448, + 7089, 9063, 8405, 46, + 7089, 9063, 8405, 47, 6121, 1045, 6376, + 7089, 9063, 8405, 47, 6121, 10804, + 7089, 9063, 8405, 48, + 7089, 9063, 8405, 49, 6121, 1045, 6376, + 7089, 9063, 8405, 49, 6121, 1045, 6490, + 7089, 9063, 8405, 49, 6121, 4530, + 7089, 9063, 8405, 49, 6121, 4531, 6376, + 7089, 9063, 8405, 49, 6121, 4896, + 7089, 9063, 8405, 49, 6121, 6378, + 7089, 9063, 8405, 49, 6121, 6874, + 7089, 9063, 8405, 49, 6121, 7708, + 7089, 9063, 8405, 49, 6121, 8432, + 7089, 9063, 8405, 49, 6121, 8758, + 7089, 9063, 8405, 49, 6121, 10804, + 7089, 9063, 8405, 49, 6121, 11448, + 7089, 9063, 8405, 50, + 7089, 9063, 8405, 51, 6121, 1045, 6376, + 7089, 9063, 8405, 51, 6121, 1045, 6490, + 7089, 9063, 8405, 51, 6121, 4530, + 7089, 9063, 8405, 51, 6121, 4877, 6490, + 7089, 9063, 8405, 51, 6121, 6378, + 7089, 9063, 8405, 51, 6121, 6546, + 7089, 9063, 8405, 51, 6121, 8758, + 7089, 9063, 8405, 51, 6121, 10802, + 7089, 9063, 8405, 51, 6121, 11448, + 7089, 9063, 8405, 58, + 7089, 9063, 8405, 66, + 7089, 9063, 8405, 67, 6121, 6378, + 7089, 9063, 8405, 67, 6121, 8432, + 7089, 9063, 8405, 82, + 7089, 9063, 8405, 92, + 7089, 9063, 8405, 94, + 7089, 9063, 8405, 95, 6121, 11649, 760, + 7089, 9063, 8405, 98, + 7089, 9063, 8405, 156, + 7089, 9063, 8405, 157, 6121, 6546, + 7089, 9063, 8405, 186, + 7089, 9063, 8405, 282, + 7089, 9063, 8405, 342, + 7089, 9063, 8405, 406, + 7089, 9063, 8405, 432, + 7089, 9063, 8405, 440, + 7089, 9063, 8405, 450, + 7089, 9063, 8405, 578, + 7089, 9063, 8405, 620, + 7089, 9063, 8405, 912, + 7089, 9063, 8405, 1110, + 7089, 9063, 8405, 1124, + 7089, 9063, 8405, 1130, + 7089, 9063, 8405, 1138, + 7089, 9063, 8405, 1139, 6121, 6546, + 7089, 9063, 8405, 1139, 10488, + 7089, 9063, 8405, 2453, 9642, + 7089, 9063, 8405, 4389, 14, + 7089, 9063, 8405, 4404, + 7089, 9063, 8405, 4614, + 7089, 9063, 8405, 5385, 8, + 7089, 9063, 8405, 5385, 28, + 7089, 9063, 8405, 5965, 2540, + 7089, 9063, 8405, 5965, 2778, + 7089, 9063, 8405, 5965, 4200, + 7089, 9063, 8405, 6078, + 7089, 9063, 8405, 6138, + 7089, 9063, 8405, 6220, + 7089, 9063, 8405, 6406, + 7089, 9063, 8405, 6824, + 7089, 9063, 8405, 6960, + 7089, 9063, 8405, 7494, + 7089, 9063, 8405, 7519, 36, + 7089, 9063, 8405, 7593, 33, 6121, 4531, 5878, + 7089, 9063, 8405, 7692, + 7089, 9063, 8405, 7693, 6121, 8758, + 7089, 9063, 8405, 7693, 6121, 8759, 9785, 10802, + 7089, 9063, 8405, 8017, 22, + 7089, 9063, 8405, 8869, 0, + 7089, 9063, 8405, 8869, 22, + 7089, 9063, 8405, 8869, 24, + 7089, 9063, 8405, 8869, 42, + 7089, 9063, 8405, 8869, 9365, 12, + 7089, 9063, 8405, 8983, 6, + 7089, 9063, 8405, 9313, 5836, + 7089, 9063, 8405, 9365, 6, + 7089, 9063, 8405, 9365, 10, + 7089, 9063, 8405, 9365, 12, + 7089, 9063, 8405, 9365, 34, + 7089, 9063, 8405, 9365, 36, + 7089, 9063, 8405, 9365, 38, + 7089, 9063, 8405, 9808, + 7089, 9063, 8405, 10489, 5, 6121, 1044, + 7089, 9063, 8405, 10489, 8, + 7089, 9063, 8405, 10494, + 7089, 9063, 8405, 10640, + 7089, 9063, 8405, 10786, + 7089, 9063, 8405, 10787, 6121, 6616, + 7089, 9063, 8405, 11879, 50, + 7089, 9063, 8405, 12507, 42, + 7089, 9063, 8405, 12507, 344, + 7089, 9063, 8405, 12935, 710, + 7089, 9063, 8405, 12935, 3244, + 7089, 9063, 10301, 268, + 7089, 9063, 10301, 426, + 7089, 11261, 7593, 8405, 0, + 7089, 11261, 7593, 8405, 8, + 7089, 11261, 7593, 8405, 16, + 7089, 11261, 7593, 8405, 18, + 7089, 11261, 7593, 8405, 28, + 7089, 11261, 7593, 8405, 34, + 7089, 11261, 7593, 8405, 40, + 7089, 11261, 7593, 8405, 42, + 7089, 11261, 7593, 8405, 46, + 7089, 11261, 7593, 8405, 7494, + 7089, 11619, 8405, 17, 7112, + 7089, 11619, 8405, 9007, 24, + 7089, 11619, 8405, 10267, 24, + 7089, 11619, 8405, 10489, 10, + 7089, 11619, 8405, 10489, 30, + 7098, + 7101, 4849, 10637, 7533, 9051, 10380, + 7101, 7443, 10637, 7533, 9051, 10380, + 7101, 7512, + 7101, 10677, 760, + 7103, 5759, 1802, + 7103, 5759, 5620, + 7103, 5759, 11076, + 7103, 5759, 11130, + 7103, 6689, 2170, + 7103, 6689, 2540, + 7103, 6689, 2778, + 7103, 6689, 4200, + 7103, 6689, 4214, + 7103, 6689, 5190, + 7103, 6689, 6260, + 7103, 6689, 6722, + 7103, 6689, 7508, + 7103, 6689, 7694, + 7103, 7593, 8405, 306, + 7103, 7593, 8405, 332, + 7103, 7593, 8405, 364, + 7103, 7593, 8405, 392, + 7103, 7593, 8405, 462, + 7103, 7593, 8405, 510, + 7103, 7593, 8405, 556, + 7103, 7593, 8405, 2030, + 7103, 7593, 8405, 9870, + 7103, 7803, 5759, 0, + 7103, 7803, 5759, 8, + 7103, 7803, 5759, 16, + 7103, 7803, 5759, 28, + 7103, 7803, 5759, 40, + 7103, 7803, 5759, 72, + 7103, 7803, 5759, 92, + 7103, 7803, 5759, 162, + 7103, 7803, 5759, 440, + 7103, 8405, 100, + 7103, 8405, 116, + 7103, 8405, 138, + 7103, 8405, 216, + 7103, 8405, 236, + 7103, 8405, 292, + 7103, 8405, 306, + 7103, 8405, 332, + 7103, 8405, 364, + 7103, 8405, 392, + 7103, 8405, 462, + 7103, 8405, 510, + 7103, 8405, 524, + 7103, 8405, 556, + 7103, 8405, 622, + 7103, 8405, 652, + 7103, 8405, 792, + 7103, 8405, 884, + 7103, 8405, 996, + 7103, 8405, 1260, + 7103, 8405, 1512, + 7103, 8405, 1612, + 7103, 8405, 2030, + 7103, 8405, 2212, + 7103, 8405, 2516, + 7103, 8405, 2566, + 7103, 8405, 2678, + 7103, 8405, 3028, + 7103, 10469, 4926, + 7103, 11257, 8405, 510, + 7103, 11257, 8405, 622, + 7103, 11257, 8405, 652, + 7103, 12017, 4926, + 7103, 13033, 8404, + 7121, 2171, 8159, 6510, + 7121, 2171, 9615, 6510, + 7121, 4201, 9259, 6510, + 7121, 4389, 6510, + 7121, 4389, 8056, + 7121, 4389, 9367, 7821, 8056, + 7121, 4849, 10465, 9947, 730, + 7121, 4849, 10642, + 7121, 4849, 12857, 12901, 6434, + 7121, 6507, 10502, + 7121, 7443, 8077, 6121, 1044, + 7121, 7443, 8570, + 7121, 7443, 10465, 9947, 730, + 7121, 7443, 10513, 7821, 8744, + 7121, 7443, 10642, + 7121, 7443, 12857, 10763, 6434, + 7121, 7443, 12933, 7821, 8744, + 7121, 7509, 9259, 6510, + 7121, 7695, 9259, 6510, + 7121, 7695, 10467, 6510, + 7165, 5758, + 7173, 5758, + 7173, 5759, 275, 10642, + 7173, 5759, 6121, 1045, 6490, + 7173, 5759, 6121, 6617, 6376, + 7173, 5759, 6121, 8649, 4112, + 7173, 5759, 6121, 9279, 4112, + 7173, 7708, + 7199, 4205, 5758, + 7199, 7519, 5758, + 7199, 9491, 5758, + 7201, 7711, 10374, + 7201, 7768, + 7201, 7769, 10375, 6121, 1044, + 7201, 7769, 10375, 6121, 5444, + 7201, 7821, 10677, 760, + 7201, 8745, 7769, 10374, + 7201, 8745, 12493, 10374, + 7201, 9095, 1045, 10374, + 7201, 9095, 5445, 10374, + 7201, 9095, 7711, 10374, + 7201, 9437, 444, + 7201, 9437, 720, + 7201, 9610, + 7201, 10780, + 7201, 11262, + 7201, 12492, + 7202, + 7209, 5758, + 7271, 4153, 721, 7607, 6113, 6434, + 7271, 4153, 6434, + 7271, 4153, 6435, 721, 7607, 4153, 6434, + 7271, 4153, 6435, 6121, 4530, + 7271, 4153, 6435, 9967, 7271, 6113, 6434, + 7271, 4153, 6435, 9967, 7607, 4153, 6434, + 7271, 4153, 6505, 6434, + 7271, 4153, 7821, 6434, + 7271, 4153, 8153, 6434, + 7271, 6113, 721, 7607, 4153, 6434, + 7271, 6113, 6434, + 7271, 6113, 6435, 569, 4895, 760, + 7271, 6113, 6435, 569, 8076, + 7271, 6113, 6435, 721, 7271, 4153, 6434, + 7271, 6113, 6435, 6121, 4530, + 7271, 6113, 6435, 9967, 7271, 4153, 6434, + 7271, 6113, 6505, 6434, + 7271, 6113, 7821, 6434, + 7271, 6113, 8153, 6434, + 7309, 7609, 4926, + 7309, 8405, 444, + 7309, 8405, 602, + 7309, 8405, 2174, + 7309, 8405, 3236, + 7309, 8405, 3952, + 7309, 8405, 3982, + 7309, 8405, 4348, + 7309, 8405, 4600, + 7309, 8405, 4900, + 7309, 8405, 5018, + 7309, 8405, 5192, + 7309, 8405, 5604, + 7309, 8405, 5628, + 7309, 8405, 6044, + 7309, 8405, 6488, + 7309, 8405, 6558, + 7309, 8405, 6774, + 7309, 8405, 7356, + 7309, 8405, 7712, + 7309, 8405, 8752, + 7309, 8405, 9246, + 7309, 8405, 9248, + 7309, 8405, 9368, + 7309, 8405, 9504, + 7309, 8405, 10662, + 7309, 8405, 12008, + 7309, 9283, 4926, + 7309, 10489, 9283, 4926, + 7321, 73, 8399, 4926, + 7321, 93, 8399, 4926, + 7321, 5759, 7282, + 7321, 5759, 8916, + 7321, 5759, 9824, + 7321, 5759, 9870, + 7321, 5759, 9904, + 7321, 5759, 11900, + 7321, 6689, 2170, + 7321, 6689, 2540, + 7321, 6689, 2778, + 7321, 6689, 4200, + 7321, 6689, 4214, + 7321, 6689, 5190, + 7321, 6689, 6260, + 7321, 6689, 6722, + 7321, 6689, 7508, + 7321, 6689, 7694, + 7321, 7803, 5759, 8, + 7321, 7803, 5759, 16, + 7321, 7803, 5759, 28, + 7321, 7803, 5759, 40, + 7321, 7803, 5759, 58, + 7321, 7803, 5759, 72, + 7321, 7803, 5759, 92, + 7321, 7803, 5759, 266, + 7321, 7803, 5759, 606, + 7321, 7803, 5759, 9827, 22, + 7321, 7803, 5759, 9827, 34, + 7321, 7803, 5759, 9827, 344, + 7321, 7803, 5759, 9827, 518, + 7321, 8322, + 7321, 8405, 0, + 7321, 8405, 8, + 7321, 8405, 16, + 7321, 8405, 28, + 7321, 8405, 40, + 7321, 8405, 58, + 7321, 8405, 72, + 7321, 8405, 92, + 7321, 8405, 100, + 7321, 8405, 116, + 7321, 8405, 138, + 7321, 8405, 216, + 7321, 8405, 236, + 7321, 8405, 266, + 7321, 8405, 292, + 7321, 8405, 306, + 7321, 8405, 332, + 7321, 8405, 364, + 7321, 8405, 392, + 7321, 8405, 462, + 7321, 8405, 510, + 7321, 8405, 524, + 7321, 8405, 556, + 7321, 8405, 606, + 7321, 8405, 610, + 7321, 8405, 622, + 7321, 8405, 652, + 7321, 8405, 792, + 7321, 8405, 884, + 7321, 8405, 974, + 7321, 8405, 996, + 7321, 8405, 1260, + 7321, 8405, 1512, + 7321, 8405, 1612, + 7321, 8405, 1796, + 7321, 8405, 2030, + 7321, 8405, 2076, + 7321, 8405, 2126, + 7321, 8405, 2212, + 7321, 8405, 2410, + 7321, 8405, 2438, + 7321, 8405, 2516, + 7321, 8405, 2566, + 7321, 8405, 2678, + 7321, 8405, 2746, + 7321, 8405, 3110, + 7321, 8405, 4016, + 7321, 8405, 5994, + 7321, 8405, 9827, 22, + 7321, 8405, 9827, 34, + 7321, 8405, 9827, 344, + 7321, 8405, 9827, 518, + 7325, 5758, + 7349, 8774, + 7377, 429, 10263, 5758, + 7380, + 7387, 5758, + 7390, + 7393, 8677, 8774, + 7424, + 7443, 731, 12473, 9050, + 7443, 1809, 11715, 9050, + 7443, 2171, 8159, 6510, + 7443, 4197, 5878, + 7443, 4389, 6505, 8056, + 7443, 4389, 6510, + 7443, 5876, + 7443, 6408, + 7443, 6409, 6121, 730, + 7443, 6409, 6121, 10959, 8963, 6434, + 7443, 6409, 8151, 12877, 8450, + 7443, 6409, 9050, + 7443, 6409, 9051, 6121, 1044, + 7443, 6409, 9817, 6121, 8744, + 7443, 6409, 12877, 8450, + 7443, 6435, 6121, 7593, 8056, + 7443, 6435, 6121, 9095, 5444, + 7443, 6505, 10637, 7533, 9050, + 7443, 6505, 11677, 9050, + 7443, 6627, 9050, + 7443, 6627, 9051, 7121, 4530, + 7443, 6627, 9051, 7773, 4530, + 7443, 6627, 9051, 8473, 7370, + 7443, 6792, + 7443, 7327, 4676, + 7443, 7821, 6627, 9050, + 7443, 7821, 8077, 9050, + 7443, 7821, 8745, 9050, + 7443, 7821, 10637, 7533, 9050, + 7443, 7821, 11677, 9050, + 7443, 7821, 12114, + 7443, 8077, 9050, + 7443, 8151, 12877, 9050, + 7443, 8153, 6409, 9050, + 7443, 8153, 6435, 6121, 9645, 4398, + 7443, 8153, 8933, 6778, + 7443, 8153, 11195, 4926, + 7443, 8153, 12114, + 7443, 8521, 8191, 11793, 9610, + 7443, 8631, 10371, 9050, + 7443, 8717, 11195, 4926, + 7443, 8745, 9050, + 7443, 8745, 9051, 6121, 5935, 275, 2725, 8076, + 7443, 8745, 9051, 6121, 5935, 275, 8005, 8076, + 7443, 8745, 9051, 6121, 7412, + 7443, 8745, 9051, 6121, 10666, + 7443, 8745, 9051, 7121, 8076, + 7443, 8745, 9051, 7773, 8076, + 7443, 8745, 9051, 10982, + 7443, 8933, 6778, + 7443, 9074, + 7443, 10493, 753, 10794, + 7443, 10523, 41, 9050, + 7443, 10637, 7533, 9050, + 7443, 10642, + 7443, 10643, 6377, 4849, 10642, + 7443, 10677, 761, 6121, 7412, + 7443, 10677, 827, 4876, + 7443, 11793, 9610, + 7443, 12114, + 7443, 12115, 7121, 4530, + 7443, 12115, 7773, 4530, + 7443, 12115, 10982, + 7443, 12877, 9050, + 7443, 13029, 9050, + 7453, 89, 5758, + 7453, 7765, 5758, + 7453, 9167, 9679, 5758, + 7453, 9513, 2170, + 7453, 9513, 2171, 9344, + 7453, 9513, 2171, 9345, 10624, + 7453, 9513, 2171, 10624, + 7453, 9513, 2171, 10625, 5, 6, + 7453, 9513, 2540, + 7453, 9513, 2541, 4839, 4212, + 7453, 9513, 2670, + 7453, 9513, 2671, 10624, + 7453, 9513, 2778, + 7453, 9513, 4200, + 7453, 9513, 4201, 9344, + 7453, 9513, 4201, 10624, + 7453, 9513, 4214, + 7453, 9513, 5190, + 7453, 9513, 6722, + 7453, 9513, 6784, + 7453, 9513, 6785, 6715, 4212, + 7453, 9513, 6785, 10624, + 7453, 9513, 7508, + 7453, 9513, 7694, + 7453, 9513, 8162, + 7453, 9513, 8874, + 7453, 9513, 10489, 2171, 9344, + 7453, 9675, 5758, + 7453, 9679, 5758, + 7453, 9691, 5758, + 7453, 9995, 5758, + 7453, 10511, 5758, + 7453, 10757, 5758, + 7453, 10961, 5758, + 7453, 11193, 5758, + 7453, 11797, 5758, + 7467, 6623, 12132, + 7467, 7935, 8774, + 7467, 8405, 4, + 7467, 8405, 6, + 7467, 8405, 8, + 7467, 8405, 12, + 7467, 8405, 28, + 7467, 8405, 32, + 7467, 8405, 42, + 7467, 8405, 44, + 7467, 8405, 46, + 7467, 8405, 48, + 7467, 8405, 50, + 7467, 8405, 63, 0, + 7467, 8405, 426, + 7467, 8405, 438, + 7467, 8405, 447, 28, + 7467, 8405, 662, + 7467, 8405, 878, + 7467, 8405, 1090, + 7467, 8405, 1110, + 7467, 8405, 1130, + 7467, 8405, 1220, + 7467, 8405, 1244, + 7467, 8405, 1486, + 7467, 8405, 1494, + 7467, 8405, 3230, + 7467, 8405, 3840, + 7467, 8405, 4185, 4189, 199, 10, + 7467, 8405, 4265, 4381, 12, + 7467, 8405, 4617, 283, 1501, 16, + 7467, 8405, 4625, 1114, + 7467, 8405, 4731, 20, + 7467, 8405, 5828, + 7467, 8405, 6059, 603, 40, + 7467, 8405, 6401, 6738, + 7467, 8405, 6415, 0, + 7467, 8405, 6554, + 7467, 8405, 6635, 3979, 6, + 7467, 8405, 6721, 167, 8, + 7467, 8405, 6891, 14, + 7467, 8405, 6997, 18, + 7467, 8405, 7028, + 7467, 8405, 7419, 2383, 5533, 34, + 7467, 8405, 7567, 13213, 36, + 7467, 8405, 7719, 2699, 2789, 38, + 7467, 8405, 7835, 6139, 44, + 7467, 8405, 8283, 14, + 7467, 8405, 8312, + 7467, 8405, 8391, 4829, 4891, 22, + 7467, 8405, 8441, 1861, 24, + 7467, 8405, 8501, 2129, 5057, 26, + 7467, 8405, 8540, + 7467, 8405, 8579, 8575, 30, + 7467, 8405, 8727, 36, + 7467, 8405, 9132, + 7467, 8405, 9543, 6759, 28, + 7467, 8405, 9911, 6495, 9047, 2, + 7467, 8405, 10132, + 7467, 8405, 10134, + 7467, 8405, 10136, + 7467, 8405, 10627, 7699, 7692, + 7467, 8405, 12482, + 7467, 8405, 13013, 0, + 7467, 8405, 13014, + 7467, 8405, 13057, 66, + 7467, 8405, 13058, + 7467, 8405, 13073, 28, + 7467, 8405, 13075, 36, + 7467, 8405, 13077, 38, + 7467, 8405, 13211, 28, + 7467, 8405, 13227, 24, + 7467, 8405, 13229, 26, + 7467, 8405, 13339, 24, + 7467, 8405, 13377, 14, + 7467, 8405, 13391, 14, + 7467, 8405, 13399, 2, + 7467, 8717, 12132, + 7467, 9909, 8774, + 7467, 10349, 12132, + 7467, 10657, 8774, + 7469, 5758, + 7551, 601, 5876, + 7551, 601, 5877, 6121, 10666, + 7551, 601, 5877, 6377, 7551, 4117, 5876, + 7551, 4117, 5876, + 7551, 4117, 5877, 6121, 9546, + 7551, 4849, 5876, + 7551, 11765, 6435, 6377, 11097, 6434, + 7579, 721, 11466, + 7588, + 7593, 175, 3992, + 7593, 2857, 6121, 10666, + 7593, 4223, 5836, + 7593, 4849, 6627, 9050, + 7593, 4849, 10637, 7533, 9050, + 7593, 4849, 12114, + 7593, 5445, 5758, + 7593, 6610, + 7593, 6616, + 7593, 7443, 6627, 9050, + 7593, 7443, 10637, 7533, 9050, + 7593, 7443, 12114, + 7593, 7453, 9513, 2170, + 7593, 7453, 9513, 2171, 9344, + 7593, 7453, 9513, 2171, 10624, + 7593, 7453, 9513, 2540, + 7593, 7453, 9513, 2670, + 7593, 7453, 9513, 2778, + 7593, 7453, 9513, 4200, + 7593, 7453, 9513, 4201, 9344, + 7593, 7453, 9513, 4214, + 7593, 7453, 9513, 5190, + 7593, 7453, 9513, 6722, + 7593, 7453, 9513, 6784, + 7593, 7453, 9513, 7508, + 7593, 7453, 9513, 7694, + 7593, 7453, 9513, 8162, + 7593, 7453, 9513, 8874, + 7593, 7708, + 7593, 8129, 5758, + 7593, 8167, 5758, + 7593, 8525, 5758, + 7593, 9263, 428, + 7593, 9263, 429, 6121, 9546, + 7593, 9263, 429, 6121, 10677, 761, 91, 1109, 429, 11649, 8758, + 7593, 9581, 5758, + 7593, 9633, 9718, + 7593, 9898, + 7593, 9959, 89, 8466, + 7593, 9959, 6121, 9546, + 7593, 9959, 6121, 10677, 761, 91, 1109, 429, 11649, 8758, + 7593, 10469, 4926, + 7593, 10708, + 7593, 11099, 5758, + 7593, 11224, + 7593, 11451, 90, + 7593, 12017, 4926, + 7593, 12043, 6616, + 7593, 12473, 5758, + 7593, 12478, + 7595, 9610, + 7598, + 7605, 11201, 10782, + 7607, 4153, 6434, + 7607, 4153, 6435, 569, 8076, + 7607, 4153, 6435, 721, 7607, 6113, 6434, + 7607, 4153, 6435, 6121, 4530, + 7607, 4153, 6435, 9967, 7271, 4153, 6434, + 7607, 4153, 6505, 6434, + 7607, 4153, 7821, 6434, + 7607, 4153, 8153, 6434, + 7607, 6113, 6434, + 7607, 6113, 6435, 721, 7271, 6113, 6434, + 7607, 6113, 6435, 6121, 4530, + 7607, 6113, 6505, 6434, + 7607, 6113, 7821, 6434, + 7607, 6113, 8153, 6434, + 7608, + 7619, 6505, 11765, 6434, + 7627, 429, 8298, + 7627, 429, 11886, + 7659, 3992, + 7665, 89, 6377, 5758, + 7665, 93, 8399, 4926, + 7665, 436, + 7665, 973, 5758, + 7665, 5759, 8916, + 7665, 5759, 9824, + 7665, 5759, 9870, + 7665, 6197, 5758, + 7665, 6673, 5758, + 7665, 6689, 2170, + 7665, 6689, 2540, + 7665, 6689, 2778, + 7665, 6689, 4200, + 7665, 6689, 4214, + 7665, 6689, 5190, + 7665, 6689, 6260, + 7665, 6689, 6722, + 7665, 6689, 7508, + 7665, 6689, 7694, + 7665, 7183, 5758, + 7665, 7469, 5758, + 7665, 7803, 5759, 8, + 7665, 7803, 5759, 16, + 7665, 7803, 5759, 28, + 7665, 7803, 5759, 40, + 7665, 7803, 5759, 58, + 7665, 7803, 5759, 72, + 7665, 7803, 5759, 92, + 7665, 7803, 5759, 162, + 7665, 7803, 5759, 266, + 7665, 7803, 5759, 440, + 7665, 7803, 5759, 606, + 7665, 8081, 5758, + 7665, 8405, 0, + 7665, 8405, 8, + 7665, 8405, 16, + 7665, 8405, 28, + 7665, 8405, 40, + 7665, 8405, 58, + 7665, 8405, 72, + 7665, 8405, 92, + 7665, 8405, 116, + 7665, 8405, 162, + 7665, 8405, 236, + 7665, 8405, 266, + 7665, 8405, 292, + 7665, 8405, 306, + 7665, 8405, 332, + 7665, 8405, 364, + 7665, 8405, 392, + 7665, 8405, 440, + 7665, 8405, 462, + 7665, 8405, 510, + 7665, 8405, 524, + 7665, 8405, 556, + 7665, 8405, 606, + 7665, 8405, 610, + 7665, 8405, 652, + 7665, 8405, 1796, + 7665, 8405, 2030, + 7665, 8405, 2076, + 7665, 8405, 2126, + 7665, 8405, 2438, + 7665, 8405, 2516, + 7665, 8405, 2566, + 7665, 8405, 2746, + 7665, 8405, 4888, + 7665, 8405, 5234, + 7665, 8525, 2171, 9344, + 7665, 8525, 2171, 10624, + 7665, 8525, 2670, + 7665, 8525, 5758, + 7681, 4103, 2091, 6764, + 7681, 8174, + 7695, 1045, 12132, + 7695, 11097, 7944, + 7695, 11765, 7944, + 7695, 11913, 8167, 7570, + 7695, 11943, 6408, + 7707, 11861, 11242, + 7708, + 7709, 6121, 1045, 6376, + 7709, 6121, 1045, 6490, + 7709, 6121, 5551, 6376, + 7709, 10374, + 7709, 10375, 6121, 1045, 6376, + 7709, 10375, 6121, 8649, 4112, + 7709, 10375, 6377, 11097, 6434, + 7709, 10375, 6377, 11765, 6434, + 7711, 6121, 4849, 4389, 6504, + 7711, 6121, 7443, 4389, 6504, + 7729, 8654, + 7733, 4927, 5758, + 7768, + 7769, 6121, 7173, 5758, + 7769, 6121, 9437, 444, + 7769, 6121, 9546, + 7769, 6377, 761, 6377, 12492, + 7769, 6377, 12492, + 7769, 7991, 721, 8329, 6121, 7768, + 7773, 2171, 8159, 6510, + 7773, 4389, 6510, + 7773, 4389, 8056, + 7773, 4389, 9367, 7821, 8056, + 7773, 4849, 445, 7121, 7443, 6627, 9051, 9664, + 7773, 4849, 8077, 6121, 1044, + 7773, 4849, 10465, 9947, 730, + 7773, 4849, 10642, + 7773, 6507, 10502, + 7773, 7443, 445, 7121, 4849, 6627, 9051, 9664, + 7773, 7443, 8570, + 7773, 7443, 10465, 9947, 730, + 7773, 7443, 10513, 7821, 8744, + 7773, 7443, 10642, + 7773, 7443, 12933, 7821, 8744, + 7794, + 7798, + 7810, + 7819, 429, 8112, + 7821, 601, 10441, 6992, + 7821, 2048, + 7821, 2587, 6121, 5528, + 7821, 3949, 5842, + 7821, 4117, 10441, 6992, + 7821, 4202, + 7821, 4215, 9601, 5830, + 7821, 4849, 10441, 6992, + 7821, 5830, + 7821, 6081, 7593, 8744, + 7821, 6571, 4760, + 7821, 6571, 5404, + 7821, 6571, 5564, + 7821, 6571, 7410, + 7821, 6571, 7996, + 7821, 6571, 8368, + 7821, 6907, 5842, + 7821, 7085, 8744, + 7821, 7443, 10441, 6992, + 7821, 7547, 7370, + 7821, 7593, 5830, + 7821, 7593, 8744, + 7821, 7593, 9438, + 7821, 7611, 5842, + 7821, 8022, + 7821, 8056, + 7821, 8057, 6121, 1045, 7442, + 7821, 8057, 6121, 2779, 4112, + 7821, 8057, 6121, 4117, 6434, + 7821, 8057, 6121, 7121, 4849, 10464, + 7821, 8057, 6121, 7121, 7443, 10464, + 7821, 8057, 6121, 7773, 4849, 10464, + 7821, 8057, 6121, 7773, 7443, 10464, + 7821, 8463, 5830, + 7821, 8463, 7593, 8744, + 7821, 8463, 8744, + 7821, 8463, 9158, + 7821, 8463, 9438, + 7821, 8691, 1044, + 7821, 8744, + 7821, 8745, 6121, 7121, 4849, 10464, + 7821, 8745, 6121, 7121, 7443, 10464, + 7821, 8745, 6121, 7773, 4849, 10464, + 7821, 8745, 6121, 7773, 7443, 10464, + 7821, 8745, 6121, 8037, 10677, 4876, + 7821, 8745, 6121, 9645, 9118, + 7821, 8745, 6121, 10677, 10739, 4876, + 7821, 8745, 6121, 11097, 5934, + 7821, 8745, 6121, 11765, 5934, + 7821, 8745, 11461, 6505, 7593, 8744, + 7821, 9158, + 7821, 9159, 5842, + 7821, 9159, 6121, 9079, 1044, + 7821, 9159, 11461, 6505, 7593, 9158, + 7821, 9338, + 7821, 9711, 4178, + 7821, 10143, 1860, + 7821, 10143, 4760, + 7821, 10194, + 7821, 10209, 4178, + 7821, 10420, + 7821, 10502, + 7821, 10643, 11461, 7593, 7821, 10642, + 7821, 10677, 760, + 7821, 10677, 9264, + 7821, 10677, 11202, + 7821, 11036, + 7821, 11202, + 7821, 11354, + 7821, 11364, + 7821, 11649, 9264, + 7821, 12383, 7593, 10642, + 7821, 12383, 10642, + 7821, 12383, 10643, 6121, 1044, + 7821, 12917, 9158, + 7821, 12917, 9159, 6121, 11097, 5934, + 7821, 12917, 9159, 6121, 11765, 5934, + 7821, 12931, 7593, 10642, + 7821, 12931, 10642, + 7821, 12967, 7593, 10642, + 7821, 12967, 9602, + 7821, 12967, 10642, + 7821, 12984, + 7821, 13067, 7593, 10642, + 7821, 13067, 9602, + 7821, 13067, 10420, + 7821, 13067, 10642, + 7911, 1049, 9467, 6791, 9748, + 7911, 6129, 11229, 1044, + 7911, 6129, 11229, 4876, + 7911, 6569, 4926, + 7911, 8423, 9467, 6791, 9748, + 7911, 8525, 2170, + 7911, 8525, 2171, 9344, + 7911, 8525, 2171, 10624, + 7911, 8525, 2540, + 7911, 8525, 2541, 9344, + 7911, 8525, 2541, 10624, + 7911, 8525, 2670, + 7911, 8525, 2671, 10624, + 7911, 8525, 2778, + 7911, 8525, 2779, 9344, + 7911, 8525, 2779, 10624, + 7911, 8525, 4200, + 7911, 8525, 4201, 9344, + 7911, 8525, 4201, 10624, + 7911, 8525, 4214, + 7911, 8525, 4215, 9344, + 7911, 8525, 4215, 10624, + 7911, 8525, 5190, + 7911, 8525, 5191, 9344, + 7911, 8525, 5191, 10624, + 7911, 8525, 6722, + 7911, 8525, 6723, 9344, + 7911, 8525, 6723, 10624, + 7911, 8525, 6784, + 7911, 8525, 6785, 10624, + 7911, 8525, 6804, + 7911, 8525, 6805, 10624, + 7911, 8525, 7508, + 7911, 8525, 7509, 9344, + 7911, 8525, 7509, 10624, + 7911, 8525, 7576, + 7911, 8525, 7577, 10624, + 7911, 8525, 7694, + 7911, 8525, 7695, 9344, + 7911, 8525, 7695, 10624, + 7911, 8525, 8160, + 7911, 8525, 8161, 10624, + 7911, 8525, 8514, + 7911, 8525, 8515, 10624, + 7911, 8525, 8820, + 7911, 8525, 8821, 10624, + 7911, 8525, 8876, + 7911, 8525, 8877, 10624, + 7911, 8525, 9672, + 7911, 8525, 9673, 10624, + 7911, 8931, 3717, 6052, + 7911, 8931, 6791, 9748, + 7911, 8931, 7687, 9748, + 7911, 8931, 8233, 9748, + 7911, 8931, 8681, 9748, + 7911, 9467, 7687, 9748, + 7911, 9467, 8681, 9748, + 7919, 6741, 445, 6741, 568, + 7919, 6741, 568, + 7919, 6741, 569, 6121, 11449, 7908, + 7922, + 7931, 1109, 429, 3288, + 7931, 2396, + 7931, 3997, 11228, + 7931, 4201, 9601, 5830, + 7931, 4223, 5836, + 7931, 4927, 5241, 8260, + 7931, 5759, 5521, 8995, 3262, + 7931, 5759, 7176, + 7931, 5759, 7476, + 7931, 5759, 7486, + 7931, 5759, 7917, 9894, + 7931, 5759, 8715, 10708, + 7931, 5759, 8715, 12523, 1894, + 7931, 5759, 11350, + 7931, 5759, 12137, 7916, + 7931, 5759, 12159, 7917, 11396, + 7931, 5879, 10204, + 7931, 6616, + 7931, 6644, + 7931, 6645, 8461, 4212, + 7931, 6645, 10275, 4212, + 7931, 6731, 8037, 1809, 5836, + 7931, 6731, 8037, 4423, 5836, + 7931, 6772, + 7931, 6773, 6121, 2779, 4112, + 7931, 6773, 8461, 4212, + 7931, 6773, 10275, 4212, + 7931, 6895, 6376, + 7931, 6895, 6490, + 7931, 7026, + 7931, 7027, 8461, 4212, + 7931, 7027, 10275, 4212, + 7931, 7377, 429, 8658, + 7931, 7593, 1809, 4942, + 7931, 7593, 1809, 5648, + 7931, 7593, 2918, + 7931, 7593, 3052, + 7931, 7593, 4423, 1739, 3244, + 7931, 7593, 4423, 2640, + 7931, 7593, 4423, 3052, + 7931, 7593, 4423, 4630, + 7931, 7593, 4423, 4943, 9363, 4212, + 7931, 7593, 4423, 4943, 10275, 4212, + 7931, 7593, 4423, 5240, + 7931, 7593, 4423, 5648, + 7931, 7593, 4423, 6254, + 7931, 7593, 4423, 7124, + 7931, 7593, 4423, 7695, 4112, + 7931, 7593, 4423, 9185, 4399, 429, 4736, + 7931, 7593, 4423, 9645, 6260, + 7931, 7593, 4423, 9807, 12139, 6260, + 7931, 7593, 4423, 10301, 2285, 6121, 1739, 6121, 3245, 9448, + 7931, 7593, 4423, 10301, 2485, 6121, 1739, 6121, 3245, 9448, + 7931, 7593, 4423, 10301, 3245, 6121, 1739, 6121, 3052, + 7931, 7593, 6644, + 7931, 7593, 6772, + 7931, 7593, 7026, + 7931, 7633, 429, 2451, 173, 4424, + 7931, 7650, + 7931, 7651, 8461, 4212, + 7931, 7651, 10275, 4212, + 7931, 7803, 5759, 1045, 6490, + 7931, 7803, 5759, 7593, 43, 6376, + 7931, 7803, 5759, 10267, 7593, 43, 6376, + 7931, 8405, 8, + 7931, 8405, 9, 6789, 4212, + 7931, 8405, 9, 8461, 4212, + 7931, 8405, 9, 9363, 4212, + 7931, 8405, 9, 10275, 4212, + 7931, 8405, 40, + 7931, 8405, 41, 6121, 6895, 6376, + 7931, 8405, 41, 6121, 6895, 6377, 10275, 4212, + 7931, 8405, 41, 6789, 4212, + 7931, 8405, 41, 10275, 4212, + 7931, 8405, 66, + 7931, 8405, 400, + 7931, 8405, 401, 6789, 4212, + 7931, 8405, 401, 8461, 4212, + 7931, 8405, 401, 9363, 4212, + 7931, 8405, 401, 10275, 4212, + 7931, 8405, 426, + 7931, 8405, 427, 6789, 4212, + 7931, 8405, 427, 10275, 4212, + 7931, 8405, 612, + 7931, 8405, 613, 6789, 4212, + 7931, 8405, 613, 10275, 4212, + 7931, 8405, 664, + 7931, 8405, 665, 6789, 4212, + 7931, 8405, 665, 10275, 4212, + 7931, 8405, 710, + 7931, 8405, 711, 6121, 2779, 4113, 6376, + 7931, 8405, 711, 6121, 2779, 4113, 11877, 6376, + 7931, 8405, 711, 6121, 7695, 4113, 6376, + 7931, 8405, 711, 6121, 7695, 4113, 10441, 10959, 6376, + 7931, 8405, 711, 6789, 4212, + 7931, 8405, 711, 8461, 4212, + 7931, 8405, 711, 9363, 4212, + 7931, 8405, 711, 10275, 4212, + 7931, 8405, 780, + 7931, 8405, 781, 6121, 1045, 6491, 721, 7695, 4113, 6376, + 7931, 8405, 781, 6121, 2779, 4113, 6491, 721, 1045, 6376, + 7931, 8405, 781, 6121, 7593, 42, + 7931, 8405, 781, 6121, 7695, 4113, 10441, 9811, 6490, + 7931, 8405, 781, 6121, 7695, 4113, 10441, 9811, 6491, 721, 2779, 4113, 6376, + 7931, 8405, 781, 6121, 7695, 4113, 12477, 6490, + 7931, 8405, 781, 6121, 10267, 7593, 43, 6490, + 7931, 8405, 781, 6789, 4212, + 7931, 8405, 781, 8461, 4212, + 7931, 8405, 781, 9363, 4212, + 7931, 8405, 781, 10275, 4212, + 7931, 8405, 956, + 7931, 8405, 957, 6121, 1045, 6490, + 7931, 8405, 957, 6789, 4212, + 7931, 8405, 957, 8461, 4212, + 7931, 8405, 957, 9363, 4212, + 7931, 8405, 957, 10275, 4212, + 7931, 8405, 960, + 7931, 8405, 961, 6121, 1045, 6490, + 7931, 8405, 961, 6121, 1045, 6491, 721, 7593, 2640, + 7931, 8405, 961, 6121, 2779, 4113, 11877, 6491, 721, 7593, 2640, + 7931, 8405, 961, 6121, 4215, 4113, 6376, + 7931, 8405, 961, 6121, 5550, + 7931, 8405, 961, 6121, 7695, 4113, 6377, 10958, + 7931, 8405, 961, 6121, 10267, 42, + 7931, 8405, 961, 6121, 10267, 7593, 43, 6490, + 7931, 8405, 961, 6789, 4212, + 7931, 8405, 961, 10275, 4212, + 7931, 8405, 1056, + 7931, 8405, 1057, 6789, 4212, + 7931, 8405, 1057, 10275, 4212, + 7931, 8405, 1152, + 7931, 8405, 1153, 6121, 1045, 6490, + 7931, 8405, 1153, 6121, 1045, 7189, 6490, + 7931, 8405, 1153, 6121, 2779, 4113, 6490, + 7931, 8405, 1153, 6121, 7695, 4113, 6490, + 7931, 8405, 1153, 6121, 7695, 4113, 10441, 9811, 6490, + 7931, 8405, 1153, 6789, 4212, + 7931, 8405, 1153, 8461, 4212, + 7931, 8405, 1153, 9363, 4212, + 7931, 8405, 1153, 10275, 4212, + 7931, 8405, 1208, + 7931, 8405, 1209, 6121, 2779, 4113, 6490, + 7931, 8405, 1209, 6121, 5550, + 7931, 8405, 1209, 6121, 7695, 4113, 6376, + 7931, 8405, 1209, 6789, 4212, + 7931, 8405, 1209, 8461, 4212, + 7931, 8405, 1209, 9363, 4212, + 7931, 8405, 1209, 10275, 4212, + 7931, 8405, 1342, + 7931, 8405, 1343, 6121, 2779, 4113, 6376, + 7931, 8405, 1343, 6121, 2779, 4113, 10677, 6376, + 7931, 8405, 1343, 6121, 6895, 6376, + 7931, 8405, 1343, 6121, 7593, 7931, 8405, 2641, 721, 2779, 4112, + 7931, 8405, 1343, 6121, 7593, 7931, 8405, 2641, 6376, + 7931, 8405, 1343, 6121, 7593, 7931, 8405, 2641, 6490, + 7931, 8405, 1343, 6121, 7695, 4113, 6376, + 7931, 8405, 1343, 6121, 7695, 4113, 10441, 9811, 6490, + 7931, 8405, 1343, 6121, 10173, 12403, 6689, 4215, 6490, + 7931, 8405, 1343, 6789, 4212, + 7931, 8405, 1343, 8461, 4212, + 7931, 8405, 1343, 9363, 4212, + 7931, 8405, 1343, 10275, 4212, + 7931, 8405, 1358, + 7931, 8405, 1359, 4340, + 7931, 8405, 1359, 4341, 6121, 6895, 6376, + 7931, 8405, 1359, 4341, 6789, 4212, + 7931, 8405, 1359, 4341, 8461, 4212, + 7931, 8405, 1359, 4341, 9363, 4212, + 7931, 8405, 1359, 4341, 10275, 4212, + 7931, 8405, 1359, 6121, 3053, 6376, + 7931, 8405, 1359, 6121, 3053, 6377, 6789, 4212, + 7931, 8405, 1359, 6121, 3053, 6377, 10275, 4212, + 7931, 8405, 1359, 6121, 10267, 42, + 7931, 8405, 1359, 6789, 4212, + 7931, 8405, 1359, 8461, 4212, + 7931, 8405, 1359, 9363, 4212, + 7931, 8405, 1359, 10275, 4212, + 7931, 8405, 1359, 11948, + 7931, 8405, 1359, 11949, 6789, 4212, + 7931, 8405, 1359, 11949, 8461, 4212, + 7931, 8405, 1359, 11949, 9363, 4212, + 7931, 8405, 1359, 11949, 10275, 4212, + 7931, 8405, 1508, + 7931, 8405, 1509, 6789, 4212, + 7931, 8405, 1509, 10275, 4212, + 7931, 8405, 1578, + 7931, 8405, 1579, 6121, 1045, 6376, + 7931, 8405, 1579, 6121, 2779, 4113, 6376, + 7931, 8405, 1579, 6121, 5550, + 7931, 8405, 1579, 6121, 7695, 4113, 6490, + 7931, 8405, 1579, 6789, 4212, + 7931, 8405, 1579, 8461, 4212, + 7931, 8405, 1579, 9363, 4212, + 7931, 8405, 1579, 10275, 4212, + 7931, 8405, 1738, + 7931, 8405, 1739, 6121, 760, + 7931, 8405, 1739, 6121, 1045, 6376, + 7931, 8405, 1739, 6121, 7593, 42, + 7931, 8405, 1739, 6121, 7695, 4113, 6376, + 7931, 8405, 1739, 6121, 7695, 4113, 6490, + 7931, 8405, 1739, 6789, 4212, + 7931, 8405, 1739, 8461, 4212, + 7931, 8405, 1739, 9363, 4212, + 7931, 8405, 1739, 10275, 4212, + 7931, 8405, 2206, + 7931, 8405, 2207, 6789, 4212, + 7931, 8405, 2207, 8461, 4212, + 7931, 8405, 2207, 9363, 4212, + 7931, 8405, 2207, 10275, 4212, + 7931, 8405, 2284, + 7931, 8405, 2285, 6121, 1045, 6376, + 7931, 8405, 2285, 6121, 7695, 4113, 6376, + 7931, 8405, 2285, 6789, 4212, + 7931, 8405, 2285, 8461, 4212, + 7931, 8405, 2285, 9363, 4212, + 7931, 8405, 2285, 10275, 4212, + 7931, 8405, 2404, + 7931, 8405, 2405, 6121, 1045, 6490, + 7931, 8405, 2405, 6121, 1045, 6491, 721, 1045, 6376, + 7931, 8405, 2405, 6121, 2779, 4113, 6376, + 7931, 8405, 2405, 6121, 2779, 4113, 11877, 6376, + 7931, 8405, 2405, 6121, 4215, 4113, 6376, + 7931, 8405, 2405, 6121, 5550, + 7931, 8405, 2405, 6121, 6895, 6376, + 7931, 8405, 2405, 6121, 7593, 42, + 7931, 8405, 2405, 6121, 7593, 43, 6490, + 7931, 8405, 2405, 6121, 7593, 7931, 8405, 2641, 721, 2779, 4112, + 7931, 8405, 2405, 6121, 8758, + 7931, 8405, 2405, 6121, 10267, 42, + 7931, 8405, 2405, 6789, 4212, + 7931, 8405, 2405, 10275, 4212, + 7931, 8405, 2484, + 7931, 8405, 2485, 6121, 2779, 4113, 6490, + 7931, 8405, 2485, 6121, 7695, 4113, 6376, + 7931, 8405, 2485, 6789, 4212, + 7931, 8405, 2485, 8461, 4212, + 7931, 8405, 2485, 9363, 4212, + 7931, 8405, 2485, 10275, 4212, + 7931, 8405, 2640, + 7931, 8405, 2641, 6121, 7695, 4113, 6376, + 7931, 8405, 2641, 6789, 4212, + 7931, 8405, 2641, 8461, 4212, + 7931, 8405, 2641, 9363, 4212, + 7931, 8405, 2641, 10275, 4212, + 7931, 8405, 2668, + 7931, 8405, 2669, 6121, 5550, + 7931, 8405, 2669, 6121, 7695, 4113, 6377, 10958, + 7931, 8405, 2669, 6789, 4212, + 7931, 8405, 2669, 8461, 4212, + 7931, 8405, 2669, 9363, 4212, + 7931, 8405, 2669, 9456, + 7931, 8405, 2669, 9457, 4340, + 7931, 8405, 2669, 9457, 6789, 4212, + 7931, 8405, 2669, 9457, 10275, 4212, + 7931, 8405, 2669, 10275, 4212, + 7931, 8405, 2858, + 7931, 8405, 2859, 6789, 4212, + 7931, 8405, 2859, 8461, 4212, + 7931, 8405, 2859, 9363, 4212, + 7931, 8405, 2859, 10275, 4212, + 7931, 8405, 2918, + 7931, 8405, 2919, 6121, 1045, 6376, + 7931, 8405, 2919, 6121, 2779, 4113, 6376, + 7931, 8405, 2919, 6121, 5550, + 7931, 8405, 2919, 6121, 6895, 6376, + 7931, 8405, 2919, 6121, 6895, 6377, 6789, 4212, + 7931, 8405, 2919, 6121, 6895, 6377, 10275, 4212, + 7931, 8405, 2919, 6121, 10173, 12403, 6689, 2779, 6376, + 7931, 8405, 2919, 6121, 10173, 12403, 6689, 7695, 6376, + 7931, 8405, 2919, 6789, 4212, + 7931, 8405, 2919, 10275, 4212, + 7931, 8405, 3052, + 7931, 8405, 3053, 6121, 5878, + 7931, 8405, 3053, 6121, 6895, 6376, + 7931, 8405, 3053, 6121, 6895, 6377, 6789, 4212, + 7931, 8405, 3053, 6121, 6895, 6377, 8461, 4212, + 7931, 8405, 3053, 6121, 6895, 6377, 9363, 4212, + 7931, 8405, 3053, 6121, 6895, 6377, 10275, 4212, + 7931, 8405, 3053, 6121, 7593, 42, + 7931, 8405, 3053, 6121, 7695, 4113, 6490, + 7931, 8405, 3053, 6789, 4212, + 7931, 8405, 3053, 7982, + 7931, 8405, 3053, 7983, 6121, 6895, 6376, + 7931, 8405, 3053, 7983, 6121, 6895, 6377, 6789, 4212, + 7931, 8405, 3053, 7983, 6121, 6895, 6377, 10275, 4212, + 7931, 8405, 3053, 7983, 6121, 10173, 12403, 6689, 2779, 6376, + 7931, 8405, 3053, 7983, 6121, 10173, 12403, 6689, 7695, 6376, + 7931, 8405, 3053, 7983, 6789, 4212, + 7931, 8405, 3053, 7983, 10275, 4212, + 7931, 8405, 3053, 8461, 4212, + 7931, 8405, 3053, 9363, 4212, + 7931, 8405, 3053, 10275, 4212, + 7931, 8405, 3124, + 7931, 8405, 3125, 6789, 4212, + 7931, 8405, 3125, 8461, 4212, + 7931, 8405, 3125, 9363, 4212, + 7931, 8405, 3125, 10275, 4212, + 7931, 8405, 3244, + 7931, 8405, 3245, 6121, 6107, 6895, 6376, + 7931, 8405, 3245, 6121, 6107, 6895, 6490, + 7931, 8405, 3245, 6121, 6895, 6376, + 7931, 8405, 3245, 6121, 6895, 6377, 6789, 4212, + 7931, 8405, 3245, 6121, 6895, 6377, 10275, 4212, + 7931, 8405, 3245, 6121, 6895, 6490, + 7931, 8405, 3245, 6121, 6895, 6491, 6789, 4212, + 7931, 8405, 3245, 6121, 6895, 6491, 10275, 4212, + 7931, 8405, 3245, 6121, 7125, 6376, + 7931, 8405, 3245, 6121, 7125, 6377, 6789, 4212, + 7931, 8405, 3245, 6121, 7125, 6377, 10275, 4212, + 7931, 8405, 3245, 6121, 10173, 12403, 6689, 2779, 6376, + 7931, 8405, 3245, 6121, 10173, 12403, 6689, 7695, 6376, + 7931, 8405, 3245, 6789, 4212, + 7931, 8405, 3245, 7808, + 7931, 8405, 3245, 7809, 6789, 4212, + 7931, 8405, 3245, 7809, 10275, 4212, + 7931, 8405, 3245, 9448, + 7931, 8405, 3245, 9449, 6789, 4212, + 7931, 8405, 3245, 9449, 10275, 4212, + 7931, 8405, 3245, 10275, 4212, + 7931, 8405, 3766, + 7931, 8405, 3767, 6789, 4212, + 7931, 8405, 3767, 8461, 4212, + 7931, 8405, 3767, 9363, 4212, + 7931, 8405, 3767, 10275, 4212, + 7931, 8405, 4000, + 7931, 8405, 4001, 6789, 4212, + 7931, 8405, 4001, 10275, 4212, + 7931, 8405, 4136, + 7931, 8405, 4137, 6789, 4212, + 7931, 8405, 4137, 8461, 4212, + 7931, 8405, 4137, 9363, 4212, + 7931, 8405, 4137, 10275, 4212, + 7931, 8405, 4356, + 7931, 8405, 4357, 6789, 4212, + 7931, 8405, 4357, 8461, 4212, + 7931, 8405, 4357, 9363, 4212, + 7931, 8405, 4357, 10275, 4212, + 7931, 8405, 4423, 6894, + 7931, 8405, 4423, 6895, 2918, + 7931, 8405, 4423, 6895, 3052, + 7931, 8405, 4423, 6895, 3244, + 7931, 8405, 4630, + 7931, 8405, 4631, 6789, 4212, + 7931, 8405, 4631, 8461, 4212, + 7931, 8405, 4631, 9363, 4212, + 7931, 8405, 4631, 10275, 4212, + 7931, 8405, 4736, + 7931, 8405, 4737, 6789, 4212, + 7931, 8405, 4737, 8461, 4212, + 7931, 8405, 4737, 9363, 4212, + 7931, 8405, 4737, 10275, 4212, + 7931, 8405, 4942, + 7931, 8405, 4943, 6121, 1045, 6376, + 7931, 8405, 4943, 6121, 1045, 6490, + 7931, 8405, 4943, 6789, 4212, + 7931, 8405, 4943, 8461, 4212, + 7931, 8405, 4943, 9363, 4212, + 7931, 8405, 4943, 10275, 4212, + 7931, 8405, 5240, + 7931, 8405, 5241, 6121, 1045, 6490, + 7931, 8405, 5241, 6121, 2779, 4113, 6490, + 7931, 8405, 5241, 6121, 5550, + 7931, 8405, 5241, 6121, 7593, 42, + 7931, 8405, 5241, 6121, 7593, 2640, + 7931, 8405, 5241, 6121, 7695, 4113, 6376, + 7931, 8405, 5241, 6789, 4212, + 7931, 8405, 5241, 8260, + 7931, 8405, 5241, 8261, 6789, 4212, + 7931, 8405, 5241, 8261, 10275, 4212, + 7931, 8405, 5241, 8461, 4212, + 7931, 8405, 5241, 9363, 4212, + 7931, 8405, 5241, 10275, 4212, + 7931, 8405, 5298, + 7931, 8405, 5299, 6789, 4212, + 7931, 8405, 5299, 8461, 4212, + 7931, 8405, 5299, 9363, 4212, + 7931, 8405, 5299, 10275, 4212, + 7931, 8405, 5572, + 7931, 8405, 5573, 6789, 4212, + 7931, 8405, 5573, 10275, 4212, + 7931, 8405, 5648, + 7931, 8405, 5649, 6121, 1045, 6491, 721, 1045, 6376, + 7931, 8405, 5649, 6121, 2779, 4113, 11877, 6376, + 7931, 8405, 5649, 6121, 4215, 4113, 6376, + 7931, 8405, 5649, 6121, 7593, 7931, 8405, 2641, 721, 2779, 4112, + 7931, 8405, 5649, 6121, 7695, 4113, 6490, + 7931, 8405, 5649, 6121, 7695, 4113, 6491, 721, 7695, 4113, 6376, + 7931, 8405, 5649, 6121, 10173, 12403, 6689, 4215, 6376, + 7931, 8405, 5649, 6121, 10267, 42, + 7931, 8405, 5649, 6789, 4212, + 7931, 8405, 5649, 8461, 4212, + 7931, 8405, 5649, 9363, 4212, + 7931, 8405, 5649, 10275, 4212, + 7931, 8405, 5910, + 7931, 8405, 5911, 6789, 4212, + 7931, 8405, 5911, 10275, 4212, + 7931, 8405, 5916, + 7931, 8405, 5917, 6789, 4212, + 7931, 8405, 5917, 8461, 4212, + 7931, 8405, 5917, 9363, 4212, + 7931, 8405, 5917, 10275, 4212, + 7931, 8405, 5992, + 7931, 8405, 5993, 6789, 4212, + 7931, 8405, 5993, 8461, 4212, + 7931, 8405, 5993, 9363, 4212, + 7931, 8405, 5993, 10275, 4212, + 7931, 8405, 6254, + 7931, 8405, 6255, 6789, 4212, + 7931, 8405, 6255, 10275, 4212, + 7931, 8405, 6486, + 7931, 8405, 6487, 6789, 4212, + 7931, 8405, 6487, 8461, 4212, + 7931, 8405, 6487, 9363, 4212, + 7931, 8405, 6487, 10275, 4212, + 7931, 8405, 6636, + 7931, 8405, 6637, 6789, 4212, + 7931, 8405, 6637, 10275, 4212, + 7931, 8405, 6771, 3052, + 7931, 8405, 6771, 3053, 6121, 2779, 4113, 6376, + 7931, 8405, 6771, 3053, 6121, 7695, 4113, 6376, + 7931, 8405, 6771, 3053, 6121, 10173, 12403, 6689, 2779, 6376, + 7931, 8405, 6771, 3053, 6121, 10173, 12403, 6689, 4215, 6490, + 7931, 8405, 6771, 3053, 6121, 10173, 12403, 6689, 7695, 6376, + 7931, 8405, 6771, 3053, 6121, 10267, 42, + 7931, 8405, 6771, 3053, 6789, 4212, + 7931, 8405, 6771, 3053, 8461, 4212, + 7931, 8405, 6771, 3053, 9363, 4212, + 7931, 8405, 6771, 3053, 10275, 4212, + 7931, 8405, 6850, + 7931, 8405, 6851, 6121, 1045, 6490, + 7931, 8405, 6851, 6789, 4212, + 7931, 8405, 6851, 8461, 4212, + 7931, 8405, 6851, 9363, 4212, + 7931, 8405, 6851, 10275, 4212, + 7931, 8405, 6894, + 7931, 8405, 6895, 10275, 4212, + 7931, 8405, 7036, + 7931, 8405, 7037, 6121, 1045, 6376, + 7931, 8405, 7037, 6121, 2779, 4113, 6376, + 7931, 8405, 7037, 6121, 7695, 4113, 6376, + 7931, 8405, 7037, 6121, 7695, 4113, 6490, + 7931, 8405, 7037, 6121, 7695, 4113, 10441, 9811, 6490, + 7931, 8405, 7037, 6789, 4212, + 7931, 8405, 7037, 8461, 4212, + 7931, 8405, 7037, 9363, 4212, + 7931, 8405, 7037, 10275, 4212, + 7931, 8405, 7238, + 7931, 8405, 7239, 6789, 4212, + 7931, 8405, 7239, 8461, 4212, + 7931, 8405, 7239, 9363, 4212, + 7931, 8405, 7239, 10275, 4212, + 7931, 8405, 7354, + 7931, 8405, 7355, 6789, 4212, + 7931, 8405, 7355, 8461, 4212, + 7931, 8405, 7355, 9363, 4212, + 7931, 8405, 7355, 10275, 4212, + 7931, 8405, 7448, + 7931, 8405, 7449, 6789, 4212, + 7931, 8405, 7449, 8461, 4212, + 7931, 8405, 7449, 9363, 4212, + 7931, 8405, 7449, 10275, 4212, + 7931, 8405, 7524, + 7931, 8405, 7525, 6121, 1045, 6490, + 7931, 8405, 7525, 6789, 4212, + 7931, 8405, 7525, 8461, 4212, + 7931, 8405, 7525, 9363, 4212, + 7931, 8405, 7525, 10275, 4212, + 7931, 8405, 7653, 1578, + 7931, 8405, 7668, + 7931, 8405, 7669, 6121, 1045, 6376, + 7931, 8405, 7669, 6789, 4212, + 7931, 8405, 7669, 8461, 4212, + 7931, 8405, 7669, 9363, 4212, + 7931, 8405, 7669, 10275, 4212, + 7931, 8405, 7672, + 7931, 8405, 7673, 6789, 4212, + 7931, 8405, 7673, 8461, 4212, + 7931, 8405, 7673, 9363, 4212, + 7931, 8405, 7673, 10275, 4212, + 7931, 8405, 8098, + 7931, 8405, 8099, 6789, 4212, + 7931, 8405, 8099, 10275, 4212, + 7931, 8405, 8860, + 7931, 8405, 8861, 6789, 4212, + 7931, 8405, 8861, 8461, 4212, + 7931, 8405, 8861, 9363, 4212, + 7931, 8405, 8861, 10275, 4212, + 7931, 8405, 8895, 8345, 9405, 3245, 9449, 8461, 4212, + 7931, 8405, 8895, 8345, 9405, 3245, 9449, 9363, 4212, + 7931, 8405, 9185, 780, + 7931, 8405, 9185, 1152, + 7931, 8405, 9185, 2284, + 7931, 8405, 9405, 426, + 7931, 8405, 9405, 427, 6789, 4212, + 7931, 8405, 9405, 427, 10275, 4212, + 7931, 8405, 9405, 664, + 7931, 8405, 9405, 665, 6789, 4212, + 7931, 8405, 9405, 665, 10275, 4212, + 7931, 8405, 9770, + 7931, 8405, 9771, 6789, 4212, + 7931, 8405, 9771, 8461, 4212, + 7931, 8405, 9771, 9363, 4212, + 7931, 8405, 9771, 10275, 4212, + 7931, 8405, 12355, 3244, + 7931, 8435, 6376, + 7931, 8525, 5758, + 7931, 8601, 7793, 5758, + 7931, 8692, + 7931, 8693, 8461, 4212, + 7931, 8693, 10275, 4212, + 7931, 8849, 1045, 12133, 4926, + 7931, 9151, 11228, + 7931, 9581, 5758, + 7931, 9645, 4423, 5837, 6121, 8205, 8036, + 7931, 9766, + 7931, 9767, 6121, 10175, 6376, + 7931, 9978, + 7931, 9979, 10275, 4212, + 7931, 10174, + 7931, 10175, 10275, 4212, + 7931, 10199, 8450, + 7931, 10267, 6644, + 7931, 10280, + 7931, 10281, 10275, 4212, + 7931, 10301, 711, 6121, 3053, 6789, 4212, + 7931, 10301, 711, 6121, 3053, 10275, 4212, + 7931, 10301, 711, 6121, 3245, 9449, 6789, 4212, + 7931, 10301, 711, 6121, 3245, 9449, 10275, 4212, + 7931, 10301, 711, 6121, 4631, 6121, 4943, 6789, 4212, + 7931, 10301, 711, 6121, 4631, 6121, 4943, 9363, 4212, + 7931, 10301, 711, 6121, 4631, 9363, 4212, + 7931, 10301, 711, 6121, 4631, 10275, 4212, + 7931, 10301, 711, 6121, 4943, 6121, 3053, 6789, 4212, + 7931, 10301, 711, 6121, 4943, 6121, 3245, 9449, 6789, 4212, + 7931, 10301, 711, 6121, 4943, 6121, 4943, 6789, 4212, + 7931, 10301, 711, 6121, 4943, 6121, 4943, 9363, 4212, + 7931, 10301, 711, 6121, 4943, 9363, 4212, + 7931, 10301, 711, 6121, 4943, 10275, 4212, + 7931, 10301, 781, 6121, 1343, 6121, 3053, 6789, 4212, + 7931, 10301, 781, 6121, 1343, 9363, 4212, + 7931, 10301, 781, 6121, 1343, 10275, 4212, + 7931, 10301, 781, 6121, 1359, 8461, 4212, + 7931, 10301, 781, 6121, 1359, 9363, 4212, + 7931, 10301, 781, 6121, 2405, 6789, 4212, + 7931, 10301, 781, 6121, 3053, 6789, 4212, + 7931, 10301, 781, 6121, 3053, 10275, 4212, + 7931, 10301, 781, 6121, 3245, 9449, 6789, 4212, + 7931, 10301, 781, 6121, 3245, 9449, 10275, 4212, + 7931, 10301, 781, 6121, 4631, 9363, 4212, + 7931, 10301, 781, 6121, 4631, 10275, 4212, + 7931, 10301, 781, 6121, 4737, 6121, 3053, 6789, 4212, + 7931, 10301, 781, 6121, 4737, 9363, 4212, + 7931, 10301, 781, 6121, 4737, 10275, 4212, + 7931, 10301, 781, 6121, 4943, 6789, 4212, + 7931, 10301, 781, 6121, 4943, 8461, 4212, + 7931, 10301, 781, 6121, 4943, 9363, 4212, + 7931, 10301, 781, 6121, 4943, 10275, 4212, + 7931, 10301, 781, 6121, 5241, 6789, 4212, + 7931, 10301, 781, 6121, 6255, 6789, 4212, + 7931, 10301, 957, 6121, 1343, 6121, 3053, 6789, 4212, + 7931, 10301, 957, 6121, 1343, 6121, 3245, 9449, 6789, 4212, + 7931, 10301, 957, 6121, 1343, 9363, 4212, + 7931, 10301, 957, 6121, 1343, 10275, 4212, + 7931, 10301, 957, 6121, 2405, 6789, 4212, + 7931, 10301, 957, 6121, 2405, 10275, 4212, + 7931, 10301, 957, 6121, 3053, 6789, 4212, + 7931, 10301, 957, 6121, 3053, 10275, 4212, + 7931, 10301, 957, 6121, 3245, 9449, 6789, 4212, + 7931, 10301, 957, 6121, 3245, 9449, 10275, 4212, + 7931, 10301, 957, 6121, 4631, 9363, 4212, + 7931, 10301, 957, 6121, 4631, 10275, 4212, + 7931, 10301, 957, 6121, 4737, 6121, 4943, 6789, 4212, + 7931, 10301, 957, 6121, 4737, 6121, 4943, 9363, 4212, + 7931, 10301, 957, 6121, 4737, 9363, 4212, + 7931, 10301, 957, 6121, 4737, 10275, 4212, + 7931, 10301, 957, 6121, 4943, 9363, 4212, + 7931, 10301, 957, 6121, 4943, 10275, 4212, + 7931, 10301, 1153, 6121, 1343, 9363, 4212, + 7931, 10301, 1153, 6121, 1343, 10275, 4212, + 7931, 10301, 1153, 6121, 3053, 6789, 4212, + 7931, 10301, 1153, 6121, 3053, 10275, 4212, + 7931, 10301, 1153, 6121, 3245, 9449, 6789, 4212, + 7931, 10301, 1153, 6121, 3245, 9449, 10275, 4212, + 7931, 10301, 1153, 6121, 4631, 9363, 4212, + 7931, 10301, 1153, 6121, 4631, 10275, 4212, + 7931, 10301, 1153, 6121, 4737, 6121, 4943, 6789, 4212, + 7931, 10301, 1153, 6121, 4737, 6121, 4943, 9363, 4212, + 7931, 10301, 1153, 6121, 4737, 9363, 4212, + 7931, 10301, 1153, 6121, 4737, 10275, 4212, + 7931, 10301, 1153, 6121, 4943, 6121, 3053, 6789, 4212, + 7931, 10301, 1153, 6121, 4943, 9363, 4212, + 7931, 10301, 1153, 6121, 4943, 10275, 4212, + 7931, 10301, 1343, 6121, 3053, 6789, 4212, + 7931, 10301, 1343, 6121, 3053, 10275, 4212, + 7931, 10301, 1343, 6121, 3245, 9449, 6789, 4212, + 7931, 10301, 1343, 6121, 3245, 9449, 10275, 4212, + 7931, 10301, 1343, 6121, 4631, 6121, 3053, 6789, 4212, + 7931, 10301, 1343, 6121, 4631, 9363, 4212, + 7931, 10301, 1343, 6121, 4631, 10275, 4212, + 7931, 10301, 1343, 6121, 4943, 6121, 3053, 6789, 4212, + 7931, 10301, 1343, 6121, 4943, 6121, 3245, 9449, 6789, 4212, + 7931, 10301, 1343, 6121, 4943, 9363, 4212, + 7931, 10301, 1343, 6121, 4943, 10275, 4212, + 7931, 10301, 1359, 6121, 3053, 10275, 4212, + 7931, 10301, 1359, 6121, 3245, 9449, 10275, 4212, + 7931, 10301, 1359, 6121, 4631, 9363, 4212, + 7931, 10301, 1359, 6121, 4631, 10275, 4212, + 7931, 10301, 1359, 6121, 4943, 6121, 4631, 9363, 4212, + 7931, 10301, 1359, 6121, 4943, 6121, 4943, 9363, 4212, + 7931, 10301, 1359, 6121, 4943, 9363, 4212, + 7931, 10301, 1359, 6121, 4943, 10275, 4212, + 7931, 10301, 1359, 6121, 12355, 3245, 9363, 4212, + 7931, 10301, 1579, 6121, 1343, 9363, 4212, + 7931, 10301, 1579, 6121, 1343, 10275, 4212, + 7931, 10301, 1579, 6121, 1739, 6789, 4212, + 7931, 10301, 1579, 6121, 1739, 8461, 4212, + 7931, 10301, 1579, 6121, 1739, 9363, 4212, + 7931, 10301, 1579, 6121, 1739, 10275, 4212, + 7931, 10301, 1579, 6121, 3053, 6789, 4212, + 7931, 10301, 1579, 6121, 3053, 10275, 4212, + 7931, 10301, 1579, 6121, 3245, 6789, 4212, + 7931, 10301, 1579, 6121, 3245, 9449, 6789, 4212, + 7931, 10301, 1579, 6121, 3245, 9449, 10275, 4212, + 7931, 10301, 1579, 6121, 3245, 10275, 4212, + 7931, 10301, 1579, 6121, 4631, 9363, 4212, + 7931, 10301, 1579, 6121, 4631, 10275, 4212, + 7931, 10301, 1579, 6121, 4737, 9363, 4212, + 7931, 10301, 1579, 6121, 4737, 10275, 4212, + 7931, 10301, 1579, 6121, 4943, 6121, 3053, 6789, 4212, + 7931, 10301, 1579, 6121, 4943, 6121, 4943, 6789, 4212, + 7931, 10301, 1579, 6121, 4943, 6121, 4943, 9363, 4212, + 7931, 10301, 1579, 6121, 4943, 6789, 4212, + 7931, 10301, 1579, 6121, 4943, 8461, 4212, + 7931, 10301, 1579, 6121, 4943, 9363, 4212, + 7931, 10301, 1579, 6121, 4943, 10275, 4212, + 7931, 10301, 1739, 6121, 1343, 6121, 3053, 6789, 4212, + 7931, 10301, 1739, 6121, 1343, 6121, 3245, 9449, 6789, 4212, + 7931, 10301, 1739, 6121, 1343, 6121, 4943, 6789, 4212, + 7931, 10301, 1739, 6121, 1343, 6121, 4943, 9363, 4212, + 7931, 10301, 1739, 6121, 1343, 9363, 4212, + 7931, 10301, 1739, 6121, 1343, 10275, 4212, + 7931, 10301, 1739, 6121, 1359, 9363, 4212, + 7931, 10301, 1739, 6121, 3053, 6789, 4212, + 7931, 10301, 1739, 6121, 3053, 10275, 4212, + 7931, 10301, 1739, 6121, 3245, 6121, 6895, 6377, 6789, 4212, + 7931, 10301, 1739, 6121, 3245, 6121, 6895, 6377, 10275, 4212, + 7931, 10301, 1739, 6121, 3245, 6121, 6895, 6491, 6789, 4212, + 7931, 10301, 1739, 6121, 3245, 6121, 6895, 6491, 10275, 4212, + 7931, 10301, 1739, 6121, 3245, 6121, 7125, 6377, 6789, 4212, + 7931, 10301, 1739, 6121, 3245, 6121, 7125, 6377, 10275, 4212, + 7931, 10301, 1739, 6121, 3245, 6789, 4212, + 7931, 10301, 1739, 6121, 3245, 9449, 6789, 4212, + 7931, 10301, 1739, 6121, 3245, 9449, 10275, 4212, + 7931, 10301, 1739, 6121, 3245, 10275, 4212, + 7931, 10301, 1739, 6121, 4631, 6121, 3053, 6789, 4212, + 7931, 10301, 1739, 6121, 4631, 6121, 4631, 6789, 4212, + 7931, 10301, 1739, 6121, 4631, 6121, 4631, 9363, 4212, + 7931, 10301, 1739, 6121, 4631, 6121, 4943, 6789, 4212, + 7931, 10301, 1739, 6121, 4631, 6121, 4943, 9363, 4212, + 7931, 10301, 1739, 6121, 4631, 9363, 4212, + 7931, 10301, 1739, 6121, 4631, 10275, 4212, + 7931, 10301, 1739, 6121, 4737, 6121, 4943, 6789, 4212, + 7931, 10301, 1739, 6121, 4737, 6121, 4943, 9363, 4212, + 7931, 10301, 1739, 6121, 4737, 9363, 4212, + 7931, 10301, 1739, 6121, 4737, 10275, 4212, + 7931, 10301, 1739, 6121, 4943, 6121, 1343, 6789, 4212, + 7931, 10301, 1739, 6121, 4943, 6121, 1343, 9363, 4212, + 7931, 10301, 1739, 6121, 4943, 6121, 3053, 6789, 4212, + 7931, 10301, 1739, 6121, 4943, 6789, 4212, + 7931, 10301, 1739, 6121, 4943, 8461, 4212, + 7931, 10301, 1739, 6121, 4943, 9363, 4212, + 7931, 10301, 1739, 6121, 4943, 10275, 4212, + 7931, 10301, 2285, 6121, 1343, 9363, 4212, + 7931, 10301, 2285, 6121, 1343, 10275, 4212, + 7931, 10301, 2285, 6121, 3053, 6789, 4212, + 7931, 10301, 2285, 6121, 3053, 10275, 4212, + 7931, 10301, 2285, 6121, 3245, 9449, 6789, 4212, + 7931, 10301, 2285, 6121, 3245, 9449, 10275, 4212, + 7931, 10301, 2285, 6121, 4943, 6121, 1343, 6789, 4212, + 7931, 10301, 2285, 6121, 4943, 6121, 1343, 9363, 4212, + 7931, 10301, 2285, 6121, 4943, 6121, 3053, 6789, 4212, + 7931, 10301, 2285, 6121, 4943, 6121, 4943, 6789, 4212, + 7931, 10301, 2285, 6121, 4943, 9363, 4212, + 7931, 10301, 2285, 6121, 4943, 10275, 4212, + 7931, 10301, 2405, 6121, 12355, 3245, 10275, 4212, + 7931, 10301, 2485, 6121, 1343, 6121, 1343, 6789, 4212, + 7931, 10301, 2485, 6121, 1343, 6121, 1343, 9363, 4212, + 7931, 10301, 2485, 6121, 1343, 6121, 3053, 6789, 4212, + 7931, 10301, 2485, 6121, 1343, 9363, 4212, + 7931, 10301, 2485, 6121, 1343, 10275, 4212, + 7931, 10301, 2485, 6121, 2405, 6789, 4212, + 7931, 10301, 2485, 6121, 2405, 10275, 4212, + 7931, 10301, 2485, 6121, 3053, 6789, 4212, + 7931, 10301, 2485, 6121, 3053, 10275, 4212, + 7931, 10301, 2485, 6121, 3245, 9449, 6789, 4212, + 7931, 10301, 2485, 6121, 3245, 9449, 10275, 4212, + 7931, 10301, 2485, 6121, 4737, 9363, 4212, + 7931, 10301, 2485, 6121, 4943, 6121, 4943, 6789, 4212, + 7931, 10301, 2485, 6121, 4943, 6121, 4943, 9363, 4212, + 7931, 10301, 2485, 6121, 4943, 9363, 4212, + 7931, 10301, 2485, 6121, 4943, 10275, 4212, + 7931, 10301, 2641, 6121, 1343, 9363, 4212, + 7931, 10301, 2641, 6121, 1343, 10275, 4212, + 7931, 10301, 2641, 6121, 3053, 6789, 4212, + 7931, 10301, 2641, 6121, 3053, 10275, 4212, + 7931, 10301, 2641, 6121, 3245, 9449, 6789, 4212, + 7931, 10301, 2641, 6121, 3245, 9449, 10275, 4212, + 7931, 10301, 2641, 6121, 4943, 6121, 1343, 6789, 4212, + 7931, 10301, 2641, 6121, 4943, 6121, 1343, 9363, 4212, + 7931, 10301, 2641, 6121, 4943, 6121, 3053, 6789, 4212, + 7931, 10301, 2641, 6121, 4943, 6121, 4943, 9363, 4212, + 7931, 10301, 2641, 6121, 4943, 8461, 4212, + 7931, 10301, 2641, 6121, 4943, 9363, 4212, + 7931, 10301, 2641, 6121, 4943, 10275, 4212, + 7931, 10301, 2669, 6121, 1343, 6121, 4631, 6789, 4212, + 7931, 10301, 2669, 6121, 1343, 6121, 4631, 9363, 4212, + 7931, 10301, 2669, 6121, 1343, 6121, 4943, 9363, 4212, + 7931, 10301, 2669, 6121, 1343, 9363, 4212, + 7931, 10301, 2669, 6121, 1343, 10275, 4212, + 7931, 10301, 2669, 6121, 1359, 8461, 4212, + 7931, 10301, 2669, 6121, 1359, 9363, 4212, + 7931, 10301, 2669, 6121, 2405, 6789, 4212, + 7931, 10301, 2669, 6121, 3053, 6789, 4212, + 7931, 10301, 2669, 6121, 3053, 10275, 4212, + 7931, 10301, 2669, 6121, 3245, 9449, 6789, 4212, + 7931, 10301, 2669, 6121, 3245, 9449, 10275, 4212, + 7931, 10301, 2669, 6121, 4631, 6121, 3053, 6789, 4212, + 7931, 10301, 2669, 6121, 4631, 6121, 3245, 9449, 6789, 4212, + 7931, 10301, 2669, 6121, 4631, 6121, 4943, 9363, 4212, + 7931, 10301, 2669, 6121, 4631, 9363, 4212, + 7931, 10301, 2669, 6121, 4631, 10275, 4212, + 7931, 10301, 2669, 6121, 4737, 6121, 3053, 6789, 4212, + 7931, 10301, 2669, 6121, 4737, 6121, 3245, 9449, 6789, 4212, + 7931, 10301, 2669, 6121, 4737, 6121, 4943, 9363, 4212, + 7931, 10301, 2669, 6121, 4737, 9363, 4212, + 7931, 10301, 2669, 6121, 4737, 10275, 4212, + 7931, 10301, 2669, 6121, 4943, 6121, 1343, 9363, 4212, + 7931, 10301, 2669, 6121, 4943, 6121, 3053, 6789, 4212, + 7931, 10301, 2669, 6121, 4943, 6121, 3245, 9449, 6789, 4212, + 7931, 10301, 2669, 6121, 4943, 6121, 4631, 9363, 4212, + 7931, 10301, 2669, 6121, 4943, 6121, 4737, 9363, 4212, + 7931, 10301, 2669, 6121, 4943, 6789, 4212, + 7931, 10301, 2669, 6121, 4943, 8461, 4212, + 7931, 10301, 2669, 6121, 4943, 9363, 4212, + 7931, 10301, 2669, 6121, 4943, 10275, 4212, + 7931, 10301, 2669, 6121, 5241, 6789, 4212, + 7931, 10301, 2669, 6121, 6255, 6789, 4212, + 7931, 10301, 3053, 6121, 1343, 6121, 3053, 6789, 4212, + 7931, 10301, 3053, 6121, 1343, 9363, 4212, + 7931, 10301, 3053, 6121, 1343, 10275, 4212, + 7931, 10301, 3053, 6121, 1359, 8461, 4212, + 7931, 10301, 3053, 6121, 1359, 9363, 4212, + 7931, 10301, 3053, 6121, 2405, 6789, 4212, + 7931, 10301, 3053, 6121, 3053, 6789, 4212, + 7931, 10301, 3053, 6121, 3053, 10275, 4212, + 7931, 10301, 3053, 6121, 3245, 9449, 6789, 4212, + 7931, 10301, 3053, 6121, 3245, 9449, 10275, 4212, + 7931, 10301, 3053, 6121, 4631, 6121, 3053, 6789, 4212, + 7931, 10301, 3053, 6121, 4631, 9363, 4212, + 7931, 10301, 3053, 6121, 4631, 10275, 4212, + 7931, 10301, 3053, 6121, 4737, 9363, 4212, + 7931, 10301, 3053, 6121, 4737, 10275, 4212, + 7931, 10301, 3053, 6121, 4943, 6121, 3053, 6789, 4212, + 7931, 10301, 3053, 6121, 4943, 6121, 4943, 6789, 4212, + 7931, 10301, 3053, 6121, 4943, 6121, 4943, 9363, 4212, + 7931, 10301, 3053, 6121, 4943, 6789, 4212, + 7931, 10301, 3053, 6121, 4943, 8461, 4212, + 7931, 10301, 3053, 6121, 4943, 9363, 4212, + 7931, 10301, 3053, 6121, 4943, 10275, 4212, + 7931, 10301, 3053, 6121, 5241, 6789, 4212, + 7931, 10301, 3053, 6121, 6255, 6789, 4212, + 7931, 10301, 3053, 6121, 6895, 6377, 6121, 9, 6789, 4212, + 7931, 10301, 3053, 6121, 6895, 6377, 6121, 9, 9363, 4212, + 7931, 10301, 3053, 6121, 6895, 6377, 6121, 9, 10275, 4212, + 7931, 10301, 3053, 6121, 6895, 6377, 6121, 41, 6789, 4212, + 7931, 10301, 3053, 6121, 6895, 6377, 6121, 41, 10275, 4212, + 7931, 10301, 3053, 6121, 6895, 6377, 6121, 67, 6789, 4212, + 7931, 10301, 3053, 6121, 6895, 6377, 6121, 67, 10275, 4212, + 7931, 10301, 3053, 6121, 6895, 6377, 6121, 427, 6789, 4212, + 7931, 10301, 3053, 6121, 6895, 6377, 6121, 427, 10275, 4212, + 7931, 10301, 3053, 6121, 6895, 6377, 6121, 665, 6789, 4212, + 7931, 10301, 3053, 6121, 6895, 6377, 6121, 665, 10275, 4212, + 7931, 10301, 3053, 6121, 6895, 6377, 6121, 1343, 9363, 4212, + 7931, 10301, 3053, 6121, 6895, 6377, 6121, 1343, 10275, 4212, + 7931, 10301, 3053, 6121, 6895, 6377, 6121, 1359, 8461, 4212, + 7931, 10301, 3053, 6121, 6895, 6377, 6121, 1359, 9363, 4212, + 7931, 10301, 3053, 6121, 6895, 6377, 6121, 2405, 6789, 4212, + 7931, 10301, 3053, 6121, 6895, 6377, 6121, 2919, 6789, 4212, + 7931, 10301, 3053, 6121, 6895, 6377, 6121, 2919, 10275, 4212, + 7931, 10301, 3053, 6121, 6895, 6377, 6121, 3053, 6789, 4212, + 7931, 10301, 3053, 6121, 6895, 6377, 6121, 3053, 10275, 4212, + 7931, 10301, 3053, 6121, 6895, 6377, 6121, 3245, 6789, 4212, + 7931, 10301, 3053, 6121, 6895, 6377, 6121, 3245, 9449, 6789, 4212, + 7931, 10301, 3053, 6121, 6895, 6377, 6121, 3245, 9449, 10275, 4212, + 7931, 10301, 3053, 6121, 6895, 6377, 6121, 3245, 10275, 4212, + 7931, 10301, 3053, 6121, 6895, 6377, 6121, 4631, 9363, 4212, + 7931, 10301, 3053, 6121, 6895, 6377, 6121, 4631, 10275, 4212, + 7931, 10301, 3053, 6121, 6895, 6377, 6121, 4737, 9363, 4212, + 7931, 10301, 3053, 6121, 6895, 6377, 6121, 4943, 6789, 4212, + 7931, 10301, 3053, 6121, 6895, 6377, 6121, 4943, 8461, 4212, + 7931, 10301, 3053, 6121, 6895, 6377, 6121, 4943, 9363, 4212, + 7931, 10301, 3053, 6121, 6895, 6377, 6121, 4943, 10275, 4212, + 7931, 10301, 3053, 6121, 6895, 6377, 6121, 5241, 6789, 4212, + 7931, 10301, 3053, 6121, 6895, 6377, 6121, 6255, 6789, 4212, + 7931, 10301, 3125, 6121, 4943, 8461, 4212, + 7931, 10301, 3125, 6121, 4943, 9363, 4212, + 7931, 10301, 3125, 6121, 4943, 10275, 4212, + 7931, 10301, 3245, 6121, 10175, 6789, 4212, + 7931, 10301, 3245, 6121, 10175, 10275, 4212, + 7931, 10301, 3245, 9449, 6121, 12355, 3245, 6789, 4212, + 7931, 10301, 3245, 9449, 6121, 12355, 3245, 10275, 4212, + 7931, 10301, 4631, 6121, 1343, 6121, 3053, 6789, 4212, + 7931, 10301, 4631, 6121, 1343, 6121, 3245, 9449, 6789, 4212, + 7931, 10301, 4631, 6121, 1343, 9363, 4212, + 7931, 10301, 4631, 6121, 1343, 10275, 4212, + 7931, 10301, 4631, 6121, 3053, 6789, 4212, + 7931, 10301, 4631, 6121, 3053, 10275, 4212, + 7931, 10301, 4631, 6121, 3245, 9449, 6789, 4212, + 7931, 10301, 4631, 6121, 3245, 9449, 10275, 4212, + 7931, 10301, 4631, 6121, 4943, 6121, 1343, 6789, 4212, + 7931, 10301, 4631, 6121, 4943, 6121, 1343, 9363, 4212, + 7931, 10301, 4631, 6121, 4943, 6121, 3053, 6789, 4212, + 7931, 10301, 4631, 6121, 4943, 6121, 3245, 9449, 6789, 4212, + 7931, 10301, 4631, 6121, 4943, 9363, 4212, + 7931, 10301, 4631, 6121, 4943, 10275, 4212, + 7931, 10301, 4737, 6121, 1343, 10275, 4212, + 7931, 10301, 4737, 6121, 3053, 6789, 4212, + 7931, 10301, 4737, 6121, 3053, 10275, 4212, + 7931, 10301, 4737, 6121, 3245, 9449, 6789, 4212, + 7931, 10301, 4737, 6121, 3245, 9449, 10275, 4212, + 7931, 10301, 4737, 6121, 4631, 9363, 4212, + 7931, 10301, 4737, 6121, 4631, 10275, 4212, + 7931, 10301, 4737, 6121, 4943, 9363, 4212, + 7931, 10301, 4737, 6121, 4943, 10275, 4212, + 7931, 10301, 4943, 6121, 1343, 6121, 3053, 6789, 4212, + 7931, 10301, 4943, 6121, 1343, 6121, 4631, 9363, 4212, + 7931, 10301, 4943, 6121, 1343, 6121, 4943, 9363, 4212, + 7931, 10301, 4943, 6121, 1343, 9363, 4212, + 7931, 10301, 4943, 6121, 1343, 10275, 4212, + 7931, 10301, 4943, 6121, 3053, 10275, 4212, + 7931, 10301, 4943, 6121, 3245, 6789, 4212, + 7931, 10301, 4943, 6121, 3245, 9449, 10275, 4212, + 7931, 10301, 4943, 6121, 4631, 6121, 1343, 9363, 4212, + 7931, 10301, 4943, 6121, 4631, 6121, 3053, 6789, 4212, + 7931, 10301, 4943, 6121, 4631, 6121, 4737, 9363, 4212, + 7931, 10301, 4943, 6121, 4631, 6121, 4943, 9363, 4212, + 7931, 10301, 4943, 6121, 4631, 9363, 4212, + 7931, 10301, 4943, 6121, 4631, 10275, 4212, + 7931, 10301, 4943, 6121, 4737, 6121, 3053, 6789, 4212, + 7931, 10301, 4943, 6121, 4737, 6121, 4631, 9363, 4212, + 7931, 10301, 4943, 6121, 4737, 6121, 4943, 9363, 4212, + 7931, 10301, 4943, 6121, 4737, 9363, 4212, + 7931, 10301, 4943, 6121, 4737, 10275, 4212, + 7931, 10301, 4943, 6121, 4943, 6121, 3053, 6789, 4212, + 7931, 10301, 4943, 6121, 4943, 6789, 4212, + 7931, 10301, 4943, 6121, 4943, 9363, 4212, + 7931, 10301, 4943, 6121, 4943, 10275, 4212, + 7931, 10301, 5241, 6121, 1343, 6121, 3053, 6789, 4212, + 7931, 10301, 5241, 6121, 1343, 6121, 3245, 9449, 6789, 4212, + 7931, 10301, 5241, 6121, 1343, 6121, 4943, 9363, 4212, + 7931, 10301, 5241, 6121, 1343, 9363, 4212, + 7931, 10301, 5241, 6121, 1343, 10275, 4212, + 7931, 10301, 5241, 6121, 1359, 8461, 4212, + 7931, 10301, 5241, 6121, 1359, 9363, 4212, + 7931, 10301, 5241, 6121, 2405, 6789, 4212, + 7931, 10301, 5241, 6121, 3053, 6789, 4212, + 7931, 10301, 5241, 6121, 3053, 10275, 4212, + 7931, 10301, 5241, 6121, 3245, 9449, 6789, 4212, + 7931, 10301, 5241, 6121, 3245, 9449, 10275, 4212, + 7931, 10301, 5241, 6121, 4631, 6121, 1343, 6789, 4212, + 7931, 10301, 5241, 6121, 4631, 6121, 1343, 9363, 4212, + 7931, 10301, 5241, 6121, 4631, 6121, 3053, 6789, 4212, + 7931, 10301, 5241, 6121, 4631, 6121, 3245, 9449, 6789, 4212, + 7931, 10301, 5241, 6121, 4631, 6121, 4943, 6789, 4212, + 7931, 10301, 5241, 6121, 4631, 6121, 4943, 9363, 4212, + 7931, 10301, 5241, 6121, 4631, 9363, 4212, + 7931, 10301, 5241, 6121, 4631, 10275, 4212, + 7931, 10301, 5241, 6121, 4737, 9363, 4212, + 7931, 10301, 5241, 6121, 4737, 10275, 4212, + 7931, 10301, 5241, 6121, 4943, 6121, 3053, 6789, 4212, + 7931, 10301, 5241, 6121, 4943, 6121, 3245, 9449, 6789, 4212, + 7931, 10301, 5241, 6121, 4943, 6789, 4212, + 7931, 10301, 5241, 6121, 4943, 8461, 4212, + 7931, 10301, 5241, 6121, 4943, 9363, 4212, + 7931, 10301, 5241, 6121, 4943, 10275, 4212, + 7931, 10301, 5241, 6121, 5241, 6789, 4212, + 7931, 10301, 5241, 6121, 6255, 6789, 4212, + 7931, 10301, 5475, 6061, 89, 9411, 5837, 5759, 10275, 4212, + 7931, 10301, 5649, 6121, 1343, 6121, 4631, 9363, 4212, + 7931, 10301, 5649, 6121, 1343, 8461, 4212, + 7931, 10301, 5649, 6121, 1343, 9363, 4212, + 7931, 10301, 5649, 6121, 1343, 10275, 4212, + 7931, 10301, 5649, 6121, 1359, 8461, 4212, + 7931, 10301, 5649, 6121, 1359, 9363, 4212, + 7931, 10301, 5649, 6121, 2405, 6789, 4212, + 7931, 10301, 5649, 6121, 2405, 10275, 4212, + 7931, 10301, 5649, 6121, 3053, 6789, 4212, + 7931, 10301, 5649, 6121, 3053, 10275, 4212, + 7931, 10301, 5649, 6121, 3245, 9449, 6789, 4212, + 7931, 10301, 5649, 6121, 3245, 9449, 10275, 4212, + 7931, 10301, 5649, 6121, 4631, 6121, 1343, 9363, 4212, + 7931, 10301, 5649, 6121, 4631, 6121, 3245, 9449, 6789, 4212, + 7931, 10301, 5649, 6121, 4631, 8461, 4212, + 7931, 10301, 5649, 6121, 4631, 9363, 4212, + 7931, 10301, 5649, 6121, 4631, 10275, 4212, + 7931, 10301, 5649, 6121, 4737, 6121, 3053, 6789, 4212, + 7931, 10301, 5649, 6121, 4737, 6121, 3245, 9449, 6789, 4212, + 7931, 10301, 5649, 6121, 4737, 8461, 4212, + 7931, 10301, 5649, 6121, 4737, 9363, 4212, + 7931, 10301, 5649, 6121, 4737, 10275, 4212, + 7931, 10301, 5649, 6121, 4943, 6121, 1343, 6789, 4212, + 7931, 10301, 5649, 6121, 4943, 6121, 1343, 9363, 4212, + 7931, 10301, 5649, 6121, 4943, 6121, 4631, 9363, 4212, + 7931, 10301, 5649, 6121, 4943, 6121, 4943, 6789, 4212, + 7931, 10301, 5649, 6121, 4943, 6121, 4943, 9363, 4212, + 7931, 10301, 5649, 6121, 4943, 8461, 4212, + 7931, 10301, 5649, 6121, 4943, 9363, 4212, + 7931, 10301, 5649, 6121, 4943, 10275, 4212, + 7931, 10301, 5911, 6121, 12355, 3245, 10275, 4212, + 7931, 10301, 5917, 6121, 1359, 8461, 4212, + 7931, 10301, 5917, 6121, 2405, 6789, 4212, + 7931, 10301, 5917, 6121, 3053, 6789, 4212, + 7931, 10301, 5917, 6121, 3053, 10275, 4212, + 7931, 10301, 5917, 6121, 3245, 9449, 6789, 4212, + 7931, 10301, 5917, 6121, 3245, 9449, 10275, 4212, + 7931, 10301, 5917, 6121, 4631, 10275, 4212, + 7931, 10301, 5917, 6121, 4943, 6789, 4212, + 7931, 10301, 5917, 6121, 4943, 8461, 4212, + 7931, 10301, 5917, 6121, 4943, 9363, 4212, + 7931, 10301, 5917, 6121, 4943, 10275, 4212, + 7931, 10301, 5917, 6121, 5241, 6789, 4212, + 7931, 10301, 5917, 6121, 6255, 6789, 4212, + 7931, 10301, 6393, 10275, 4212, + 7931, 10301, 6405, 10275, 4212, + 7931, 10301, 6851, 6121, 3053, 6789, 4212, + 7931, 10301, 6851, 6121, 3053, 10275, 4212, + 7931, 10301, 6851, 6121, 3245, 9449, 6789, 4212, + 7931, 10301, 6851, 6121, 3245, 9449, 10275, 4212, + 7931, 10301, 6851, 6121, 4631, 9363, 4212, + 7931, 10301, 6851, 6121, 4631, 10275, 4212, + 7931, 10301, 6851, 6121, 4943, 6121, 3053, 6789, 4212, + 7931, 10301, 6851, 6121, 4943, 6121, 3245, 9449, 6789, 4212, + 7931, 10301, 6851, 6121, 4943, 6121, 4943, 6789, 4212, + 7931, 10301, 6851, 6121, 4943, 9363, 4212, + 7931, 10301, 6851, 6121, 4943, 10275, 4212, + 7931, 10301, 7479, 10275, 4212, + 7931, 10301, 7481, 6061, 89, 9411, 5837, 5759, 10275, 4212, + 7931, 10301, 7481, 10275, 4212, + 7931, 10301, 7525, 6121, 1343, 6121, 3053, 6789, 4212, + 7931, 10301, 7525, 6121, 1343, 6121, 4943, 6789, 4212, + 7931, 10301, 7525, 6121, 1343, 6121, 4943, 9363, 4212, + 7931, 10301, 7525, 6121, 1343, 6789, 4212, + 7931, 10301, 7525, 6121, 1343, 8461, 4212, + 7931, 10301, 7525, 6121, 1343, 9363, 4212, + 7931, 10301, 7525, 6121, 1343, 10275, 4212, + 7931, 10301, 7525, 6121, 1359, 8461, 4212, + 7931, 10301, 7525, 6121, 1359, 9363, 4212, + 7931, 10301, 7525, 6121, 2405, 6789, 4212, + 7931, 10301, 7525, 6121, 2405, 10275, 4212, + 7931, 10301, 7525, 6121, 3053, 6789, 4212, + 7931, 10301, 7525, 6121, 3053, 10275, 4212, + 7931, 10301, 7525, 6121, 3245, 9449, 6789, 4212, + 7931, 10301, 7525, 6121, 3245, 9449, 10275, 4212, + 7931, 10301, 7525, 6121, 4631, 6121, 3053, 6789, 4212, + 7931, 10301, 7525, 6121, 4631, 6789, 4212, + 7931, 10301, 7525, 6121, 4631, 8461, 4212, + 7931, 10301, 7525, 6121, 4631, 9363, 4212, + 7931, 10301, 7525, 6121, 4631, 10275, 4212, + 7931, 10301, 7525, 6121, 4737, 6789, 4212, + 7931, 10301, 7525, 6121, 4737, 8461, 4212, + 7931, 10301, 7525, 6121, 4737, 9363, 4212, + 7931, 10301, 7525, 6121, 4737, 10275, 4212, + 7931, 10301, 7525, 6121, 4943, 6121, 4737, 6789, 4212, + 7931, 10301, 7525, 6121, 4943, 6121, 4737, 9363, 4212, + 7931, 10301, 7525, 6121, 4943, 6121, 4943, 6789, 4212, + 7931, 10301, 7525, 6121, 4943, 6121, 4943, 9363, 4212, + 7931, 10301, 7525, 6121, 4943, 6789, 4212, + 7931, 10301, 7525, 6121, 4943, 8461, 4212, + 7931, 10301, 7525, 6121, 4943, 9363, 4212, + 7931, 10301, 7525, 6121, 4943, 10275, 4212, + 7931, 10301, 7917, 10275, 4212, + 7931, 10301, 8635, 10275, 4212, + 7931, 10301, 8693, 6121, 6645, 8461, 4212, + 7931, 10301, 8693, 6121, 6645, 10275, 4212, + 7931, 10301, 8693, 6121, 6773, 8461, 4212, + 7931, 10301, 8693, 6121, 6773, 10275, 4212, + 7931, 10301, 8693, 6121, 7027, 8461, 4212, + 7931, 10301, 8693, 6121, 7027, 10275, 4212, + 7931, 10301, 8693, 6121, 9979, 10275, 4212, + 7931, 10301, 8693, 6121, 10281, 10275, 4212, + 7931, 10301, 8693, 6121, 12355, 3245, 10275, 4212, + 7931, 10301, 8895, 9405, 3053, 6121, 6895, 6377, 6121, 3245, 9449, 6789, 4212, + 7931, 10301, 8895, 9405, 3053, 6121, 6895, 6377, 6121, 3245, 9449, 9363, 4212, + 7931, 10301, 8895, 9405, 3053, 6121, 6895, 6377, 6121, 3245, 9449, 10275, 4212, + 7931, 10301, 10341, 10275, 4212, + 7931, 10301, 10683, 10275, 4212, + 7931, 10301, 10741, 10715, 10712, + 7931, 10301, 12159, 7917, 10682, + 7931, 10301, 13202, + 7931, 10469, 4926, + 7931, 10489, 6644, + 7931, 10692, + 7931, 11224, + 7931, 11261, 3244, + 7931, 11363, 11228, + 7971, 46, + 7971, 826, + 7971, 827, 6121, 46, + 7971, 827, 6121, 6568, + 7985, 8159, 7274, + 7985, 11241, 7274, + 8005, 731, 12901, 6434, + 8005, 4389, 10260, + 8005, 4849, 3958, + 8005, 4849, 4389, 9050, + 8005, 4849, 8076, + 8005, 6627, 9050, + 8005, 7443, 3958, + 8005, 7443, 4389, 9050, + 8005, 7443, 8076, + 8005, 8745, 9050, + 8005, 8745, 9051, 5387, 2725, 8745, 9050, + 8005, 10637, 7533, 9050, + 8005, 12114, + 8006, + 8007, 6121, 4849, 4389, 6504, + 8007, 6121, 7443, 4389, 6504, + 8017, 760, + 8017, 8057, 6121, 11141, 6434, + 8022, + 8023, 10374, + 8027, 2638, + 8028, + 8033, 8405, 0, + 8033, 8405, 2, + 8033, 8405, 6, + 8033, 8405, 8, + 8033, 8405, 12, + 8033, 8405, 16, + 8033, 8405, 20, + 8033, 8405, 22, + 8033, 8405, 24, + 8033, 8405, 26, + 8033, 8405, 28, + 8033, 8405, 30, + 8033, 8405, 32, + 8033, 8405, 34, + 8033, 8405, 36, + 8033, 8405, 38, + 8033, 8405, 40, + 8033, 8405, 46, + 8033, 8405, 54, + 8033, 8405, 136, + 8033, 8405, 158, + 8033, 8405, 214, + 8033, 8405, 266, + 8033, 8405, 304, + 8033, 8405, 334, + 8033, 8405, 366, + 8033, 8405, 394, + 8033, 8405, 400, + 8033, 8405, 410, + 8033, 8405, 460, + 8033, 8405, 518, + 8033, 8405, 530, + 8033, 8405, 542, + 8033, 8405, 544, + 8033, 8405, 574, + 8033, 8405, 606, + 8033, 8405, 1756, + 8033, 8405, 1872, + 8033, 8405, 1874, + 8033, 8405, 1876, + 8033, 8405, 2514, + 8033, 8405, 2578, + 8033, 8405, 2744, + 8033, 8405, 2838, + 8033, 8405, 3832, + 8033, 8405, 3834, + 8033, 8405, 6068, + 8033, 8405, 6070, + 8033, 8405, 6072, + 8037, 4877, 8774, + 8048, + 8057, 6121, 719, 835, 7773, 4849, 10465, 6504, + 8057, 6121, 2779, 11649, 9745, 569, 2681, 7442, + 8057, 6121, 4849, 4389, 6504, + 8057, 6121, 7121, 4389, 6504, + 8057, 6121, 7443, 4389, 6504, + 8057, 6121, 7593, 8057, 569, 2681, 7442, + 8057, 6121, 7773, 4389, 6504, + 8057, 6121, 7773, 7443, 10465, 6504, + 8057, 6121, 10677, 4192, + 8057, 6121, 11649, 760, + 8057, 6121, 12879, 46, + 8057, 9177, 115, 11649, 761, 721, 2725, 4389, 9177, 115, 10677, 760, + 8065, 7769, 6121, 8688, + 8065, 7769, 6121, 8689, 721, 7595, 9610, + 8065, 8762, + 8065, 8763, 445, 6741, 568, + 8065, 10578, + 8065, 10579, 445, 6741, 568, + 8065, 12493, 6121, 8688, + 8066, + 8075, 2167, 8523, 4223, 5836, + 8075, 2167, 8523, 7793, 9178, + 8075, 2167, 8523, 8121, 10469, 4926, + 8075, 2167, 8523, 10255, 10469, 4926, + 8075, 4223, 5836, + 8075, 7593, 8405, 28, + 8075, 7593, 8405, 202, + 8075, 7593, 8405, 374, + 8075, 7593, 8405, 404, + 8075, 7593, 8405, 476, + 8075, 7593, 8405, 516, + 8075, 7593, 8405, 582, + 8075, 7593, 8405, 986, + 8075, 7593, 8405, 1102, + 8075, 7593, 8405, 1154, + 8075, 7593, 8405, 1616, + 8075, 7593, 8405, 1680, + 8075, 7593, 8405, 2167, 8075, 236, + 8075, 7593, 8405, 2167, 8075, 710, + 8075, 7593, 8405, 2167, 8075, 1020, + 8075, 7593, 8405, 2167, 8075, 1124, + 8075, 7593, 8405, 2167, 8075, 1352, + 8075, 7593, 8405, 2167, 8075, 1360, + 8075, 7593, 8405, 2167, 8075, 2180, + 8075, 7593, 8405, 2167, 8075, 4534, + 8075, 7593, 8405, 2167, 8075, 5680, + 8075, 7593, 8405, 2167, 8075, 7542, + 8075, 7593, 8405, 2167, 8075, 8238, + 8075, 7593, 8405, 2167, 8523, 2036, + 8075, 7593, 8405, 2167, 8523, 2132, + 8075, 7593, 8405, 2167, 8523, 2916, + 8075, 7593, 8405, 2167, 8523, 7542, + 8075, 7593, 8405, 2180, + 8075, 7593, 8405, 2250, + 8075, 7593, 8405, 2560, + 8075, 7593, 8405, 2658, + 8075, 7593, 8405, 3246, + 8075, 7593, 8405, 4394, + 8075, 7593, 8405, 4534, + 8075, 7593, 8405, 4722, + 8075, 7593, 8405, 4746, + 8075, 7593, 8405, 5680, + 8075, 7593, 8405, 5766, + 8075, 7593, 8405, 6082, + 8075, 7593, 8405, 6258, + 8075, 7593, 8405, 6640, + 8075, 7593, 8405, 6824, + 8075, 7593, 8405, 6976, + 8075, 7593, 8405, 7090, + 8075, 7593, 8405, 7484, + 8075, 7593, 8405, 7542, + 8075, 7593, 8405, 8238, + 8075, 7593, 8405, 8816, + 8075, 7593, 8405, 9127, 5680, + 8075, 7593, 8405, 9861, 4746, + 8075, 7593, 8405, 10295, 236, + 8075, 7593, 8405, 10807, 404, + 8075, 7593, 8405, 10807, 3244, + 8075, 7593, 8405, 10807, 4534, + 8075, 7593, 8405, 10807, 4722, + 8075, 7593, 8405, 12921, 404, + 8075, 7593, 8405, 12921, 1102, + 8075, 8775, 375, 516, + 8075, 8775, 477, 516, + 8075, 8775, 1582, + 8075, 8775, 1617, 516, + 8075, 8775, 2659, 516, + 8075, 8775, 7543, 5766, + 8075, 8775, 9738, + 8075, 9063, 8405, 28, + 8075, 9063, 8405, 202, + 8075, 9063, 8405, 374, + 8075, 9063, 8405, 404, + 8075, 9063, 8405, 476, + 8075, 9063, 8405, 516, + 8075, 9063, 8405, 582, + 8075, 9063, 8405, 986, + 8075, 9063, 8405, 1102, + 8075, 9063, 8405, 1154, + 8075, 9063, 8405, 1616, + 8075, 9063, 8405, 1680, + 8075, 9063, 8405, 2167, 8075, 236, + 8075, 9063, 8405, 2167, 8075, 710, + 8075, 9063, 8405, 2167, 8075, 1020, + 8075, 9063, 8405, 2167, 8075, 1124, + 8075, 9063, 8405, 2167, 8075, 1352, + 8075, 9063, 8405, 2167, 8075, 1360, + 8075, 9063, 8405, 2167, 8075, 2180, + 8075, 9063, 8405, 2167, 8075, 4534, + 8075, 9063, 8405, 2167, 8075, 5680, + 8075, 9063, 8405, 2167, 8075, 7542, + 8075, 9063, 8405, 2167, 8075, 8238, + 8075, 9063, 8405, 2167, 8523, 2036, + 8075, 9063, 8405, 2167, 8523, 2132, + 8075, 9063, 8405, 2167, 8523, 2916, + 8075, 9063, 8405, 2167, 8523, 7542, + 8075, 9063, 8405, 2180, + 8075, 9063, 8405, 2250, + 8075, 9063, 8405, 2560, + 8075, 9063, 8405, 2658, + 8075, 9063, 8405, 3246, + 8075, 9063, 8405, 4394, + 8075, 9063, 8405, 4534, + 8075, 9063, 8405, 4722, + 8075, 9063, 8405, 4746, + 8075, 9063, 8405, 5680, + 8075, 9063, 8405, 5766, + 8075, 9063, 8405, 6082, + 8075, 9063, 8405, 6258, + 8075, 9063, 8405, 6640, + 8075, 9063, 8405, 6824, + 8075, 9063, 8405, 6976, + 8075, 9063, 8405, 7090, + 8075, 9063, 8405, 7484, + 8075, 9063, 8405, 7542, + 8075, 9063, 8405, 8238, + 8075, 9063, 8405, 8816, + 8075, 9063, 8405, 9127, 5680, + 8075, 9063, 8405, 9861, 4746, + 8075, 9063, 8405, 10295, 236, + 8075, 9063, 8405, 10807, 404, + 8075, 9063, 8405, 10807, 3244, + 8075, 9063, 8405, 10807, 4534, + 8075, 9063, 8405, 10807, 4722, + 8075, 9063, 8405, 12921, 404, + 8075, 9063, 8405, 12921, 1102, + 8075, 10203, 2171, 4388, + 8075, 12977, 9178, + 8083, 5833, 11163, 5759, 10380, + 8088, + 8097, 1809, 4876, + 8097, 10388, + 8097, 13235, 11765, 6434, + 8101, 5758, + 8101, 9076, + 8101, 11626, + 8117, 1177, 6716, + 8117, 1177, 6957, 6716, + 8117, 1177, 8403, 3070, + 8117, 1177, 8403, 6178, + 8117, 1177, 9251, 6956, + 8117, 1177, 9251, 8290, + 8117, 1177, 9315, 3070, + 8117, 1177, 9315, 6178, + 8117, 1177, 10239, 6716, + 8121, 9129, 8775, 4213, 2778, + 8129, 5758, + 8133, 5941, 10677, 3696, + 8133, 5941, 11649, 3696, + 8133, 5941, 13086, + 8133, 5941, 13088, + 8133, 5941, 13090, + 8133, 5941, 13092, + 8133, 5941, 13094, + 8133, 5941, 13096, + 8133, 5941, 13098, + 8133, 5941, 13100, + 8133, 5941, 13102, + 8133, 5941, 13104, + 8133, 5941, 13106, + 8133, 5941, 13108, + 8133, 5941, 13110, + 8133, 5941, 13112, + 8133, 5941, 13114, + 8133, 5941, 13116, + 8133, 5941, 13118, + 8133, 5941, 13120, + 8133, 5941, 13122, + 8133, 5941, 13124, + 8133, 5941, 13126, + 8133, 5941, 13128, + 8133, 5941, 13130, + 8133, 5941, 13132, + 8133, 5941, 13134, + 8133, 5941, 13136, + 8133, 5941, 13138, + 8133, 5941, 13140, + 8133, 5941, 13142, + 8133, 5941, 13144, + 8133, 5941, 13146, + 8133, 5941, 13148, + 8133, 5941, 13150, + 8133, 5941, 13152, + 8133, 5941, 13154, + 8133, 5941, 13156, + 8133, 5941, 13158, + 8133, 5941, 13160, + 8133, 5941, 13162, + 8133, 5941, 13164, + 8133, 5941, 13166, + 8133, 5941, 13168, + 8133, 5941, 13170, + 8133, 5941, 13172, + 8133, 5941, 13174, + 8133, 5941, 13176, + 8133, 5941, 13178, + 8133, 5941, 13180, + 8133, 5941, 13182, + 8133, 5941, 13240, + 8133, 5941, 13242, + 8133, 5941, 13244, + 8133, 5941, 13246, + 8133, 5941, 13248, + 8133, 5941, 13250, + 8133, 5941, 13252, + 8133, 5941, 13254, + 8133, 5941, 13256, + 8133, 5941, 13258, + 8133, 5941, 13260, + 8133, 5941, 13262, + 8133, 5941, 13264, + 8133, 5941, 13266, + 8133, 5941, 13268, + 8133, 5941, 13270, + 8133, 5941, 13272, + 8133, 5941, 13274, + 8133, 5941, 13276, + 8133, 5941, 13278, + 8133, 5941, 13280, + 8133, 5941, 13282, + 8133, 5941, 13284, + 8133, 5941, 13286, + 8133, 5941, 13288, + 8133, 5941, 13290, + 8133, 5941, 13292, + 8133, 5941, 13294, + 8133, 5941, 13296, + 8133, 5941, 13298, + 8133, 5941, 13300, + 8133, 5941, 13302, + 8133, 5941, 13304, + 8133, 5941, 13306, + 8133, 5941, 13308, + 8133, 5941, 13310, + 8133, 5941, 13312, + 8133, 5941, 13314, + 8133, 5941, 13316, + 8133, 5941, 13318, + 8133, 5941, 13320, + 8133, 5941, 13322, + 8133, 5941, 13324, + 8133, 5941, 13326, + 8133, 5941, 13328, + 8133, 5941, 13330, + 8133, 5941, 13332, + 8133, 5941, 13334, + 8133, 5941, 13336, + 8151, 6622, + 8151, 6778, + 8151, 8056, + 8151, 8528, + 8151, 8744, + 8151, 13029, 8450, + 8151, 13067, 6408, + 8153, 601, 5876, + 8153, 1809, 4876, + 8153, 4117, 5876, + 8153, 4849, 731, 12473, 9050, + 8153, 5444, + 8153, 6107, 10388, + 8153, 6379, 7908, + 8153, 6611, 6740, + 8153, 7119, 11195, 4926, + 8153, 7390, + 8153, 7391, 11195, 4926, + 8153, 7443, 731, 11099, 9050, + 8153, 7768, + 8153, 8088, + 8153, 8509, 11098, + 8153, 8509, 11099, 6121, 10666, + 8153, 8509, 12472, + 8153, 8745, 7768, + 8153, 8745, 12492, + 8153, 8759, 2091, 5758, + 8153, 8762, + 8153, 9095, 6689, 2170, + 8153, 9095, 6689, 2540, + 8153, 9095, 6689, 2778, + 8153, 9095, 6689, 4200, + 8153, 9095, 6689, 4214, + 8153, 9095, 6689, 5190, + 8153, 9095, 6689, 6722, + 8153, 9095, 6689, 7508, + 8153, 9095, 6689, 7694, + 8153, 9095, 8525, 2670, + 8153, 9437, 444, + 8153, 9437, 720, + 8153, 9525, 8306, + 8153, 9719, 10374, + 8153, 10260, + 8153, 10452, + 8153, 10469, 4926, + 8153, 10574, + 8153, 10578, + 8153, 10677, 761, 4849, 11378, + 8153, 10677, 761, 8153, 4849, 11378, + 8153, 10677, 761, 8153, 7443, 11378, + 8153, 10677, 4876, + 8153, 12017, 4926, + 8153, 12492, + 8153, 13201, 11195, 4926, + 8159, 5244, + 8167, 5758, + 8167, 5759, 721, 9705, 10410, + 8167, 5759, 721, 9705, 10411, 6121, 7709, 6376, + 8167, 5759, 6121, 1045, 6490, + 8167, 5759, 6121, 2779, 4113, 6377, 721, 2779, 4113, 6490, + 8167, 5759, 6121, 6537, 6376, + 8167, 5759, 6377, 5445, 5758, + 8167, 5759, 6377, 7709, 10374, + 8167, 5759, 6377, 11097, 6434, + 8167, 5759, 6377, 11765, 6434, + 8167, 6121, 9898, + 8167, 6610, + 8172, + 8197, 5758, + 8203, 3992, + 8203, 7608, + 8209, 5401, 10260, + 8225, 6906, + 8226, + 8227, 12133, 4926, + 8228, + 8231, 12108, + 8233, 5566, + 8235, 6809, 5758, + 8246, + 8255, 7359, 5758, + 8263, 7630, + 8267, 8405, 1104, + 8267, 8405, 1510, + 8267, 8405, 3234, + 8267, 8405, 3980, + 8267, 8405, 4324, + 8267, 8405, 4384, + 8267, 8405, 4622, + 8267, 8405, 5191, 9344, + 8267, 8405, 6056, + 8267, 8405, 6768, + 8267, 8405, 6960, + 8267, 8405, 6984, + 8267, 8405, 7064, + 8267, 8405, 7078, + 8267, 8405, 7130, + 8267, 8405, 7322, + 8267, 8405, 7416, + 8267, 8405, 7490, + 8267, 8405, 7674, + 8267, 8405, 7828, + 8267, 8405, 7912, + 8267, 8405, 8502, + 8267, 8405, 8514, + 8267, 8405, 8822, + 8267, 8405, 9018, + 8267, 8405, 10394, + 8267, 8405, 10462, + 8285, 721, 5424, + 8285, 721, 8712, + 8287, 8153, 1045, 5965, 4926, + 8287, 8206, + 8287, 8405, 0, + 8287, 8405, 8, + 8287, 8405, 16, + 8287, 8405, 28, + 8287, 8405, 40, + 8287, 8405, 66, + 8287, 8405, 178, + 8287, 8405, 188, + 8287, 8405, 426, + 8287, 8405, 622, + 8287, 8405, 626, + 8287, 8405, 630, + 8287, 8405, 652, + 8287, 8405, 654, + 8287, 8405, 656, + 8287, 8405, 660, + 8287, 8405, 664, + 8287, 8405, 2908, + 8287, 8405, 2926, + 8287, 8405, 3012, + 8287, 8405, 3056, + 8287, 8405, 5770, + 8287, 8405, 6216, + 8287, 8405, 6230, + 8287, 8405, 6422, + 8287, 8405, 6594, + 8287, 8405, 6912, + 8287, 8405, 6982, + 8287, 8405, 7166, + 8287, 8405, 7244, + 8287, 8405, 7372, + 8287, 8405, 7440, + 8287, 8405, 7862, + 8287, 8405, 7866, + 8287, 8405, 7932, + 8287, 8405, 8362, + 8287, 8405, 8828, + 8287, 8405, 8950, + 8287, 8405, 8956, + 8287, 8405, 9086, + 8287, 8405, 9400, + 8287, 8405, 9562, + 8287, 8405, 9588, + 8287, 8405, 9780, + 8287, 8405, 10686, + 8287, 8405, 11248, + 8287, 8405, 11682, + 8287, 8405, 11696, + 8287, 8405, 11728, + 8287, 8405, 11758, + 8287, 8405, 11804, + 8287, 8405, 11812, + 8287, 8405, 11814, + 8287, 8405, 11824, + 8287, 8405, 11826, + 8287, 8405, 11828, + 8287, 8405, 11830, + 8287, 8405, 11832, + 8287, 8405, 12070, + 8287, 8405, 12080, + 8287, 8405, 12094, + 8287, 8405, 12096, + 8287, 8405, 12124, + 8287, 8405, 12144, + 8287, 8405, 12146, + 8287, 8405, 12150, + 8287, 8405, 12346, + 8287, 8405, 12348, + 8287, 8405, 12350, + 8287, 8405, 12352, + 8287, 8405, 12388, + 8287, 8405, 12514, + 8287, 8405, 12518, + 8287, 8405, 12520, + 8287, 8405, 12532, + 8287, 8405, 12534, + 8287, 8405, 12958, + 8287, 8405, 12960, + 8287, 8405, 12972, + 8287, 8405, 12978, + 8287, 8405, 12998, + 8287, 8405, 13004, + 8287, 8405, 13006, + 8287, 8405, 13008, + 8287, 8405, 13034, + 8287, 8405, 13204, + 8287, 8405, 13348, + 8287, 8405, 13354, + 8287, 8405, 13366, + 8287, 8405, 13368, + 8287, 8405, 13370, + 8287, 8405, 13374, + 8287, 8405, 13386, + 8287, 8717, 1045, 5965, 4926, + 8287, 9945, 5770, + 8287, 9945, 6594, + 8287, 9945, 6912, + 8287, 9945, 6982, + 8287, 9945, 7166, + 8287, 9945, 7244, + 8287, 9945, 7372, + 8287, 9945, 7440, + 8287, 9945, 8206, + 8287, 9945, 8362, + 8287, 9945, 8828, + 8287, 9945, 9086, + 8287, 9945, 9400, + 8287, 9945, 9562, + 8287, 9945, 9588, + 8287, 9945, 9780, + 8287, 9945, 10686, + 8287, 9945, 11248, + 8287, 9945, 11652, + 8287, 9945, 11728, + 8287, 9945, 11804, + 8287, 9945, 11806, + 8287, 9945, 11808, + 8287, 9945, 11810, + 8287, 9945, 11812, + 8287, 9945, 11814, + 8287, 9945, 11816, + 8287, 9945, 11824, + 8287, 9945, 11826, + 8287, 9945, 11828, + 8287, 9945, 11830, + 8287, 9945, 11832, + 8287, 9945, 11834, + 8287, 9945, 11902, + 8287, 9945, 12044, + 8287, 9945, 12046, + 8287, 9945, 12048, + 8287, 9945, 12080, + 8287, 9945, 12098, + 8287, 9945, 12124, + 8287, 9945, 12128, + 8287, 9945, 12144, + 8287, 9945, 12148, + 8287, 9945, 12346, + 8287, 9945, 12348, + 8287, 9945, 12350, + 8287, 9945, 12352, + 8287, 9945, 12388, + 8287, 9945, 12424, + 8287, 9945, 12484, + 8287, 9945, 12486, + 8287, 9945, 12512, + 8287, 9945, 12514, + 8287, 9945, 12518, + 8287, 9945, 12520, + 8287, 9945, 12858, + 8287, 9945, 12860, + 8287, 9945, 12862, + 8287, 9945, 12864, + 8287, 9945, 12908, + 8287, 9945, 12910, + 8287, 9945, 12942, + 8287, 9945, 12946, + 8287, 9945, 12948, + 8287, 9945, 12950, + 8287, 9945, 12958, + 8287, 9945, 12960, + 8287, 9945, 12962, + 8287, 9945, 12992, + 8287, 9945, 12994, + 8287, 9945, 12996, + 8287, 9945, 12998, + 8287, 9945, 13026, + 8287, 9945, 13078, + 8287, 9945, 13192, + 8287, 9945, 13194, + 8287, 9945, 13196, + 8287, 9945, 13204, + 8287, 9945, 13218, + 8287, 9945, 13238, + 8287, 9945, 13342, + 8287, 9945, 13344, + 8287, 9945, 13358, + 8287, 9945, 13366, + 8287, 9945, 13368, + 8287, 9945, 13378, + 8287, 9945, 13382, + 8287, 9945, 13384, + 8287, 9945, 13386, + 8287, 9945, 13408, + 8287, 9945, 13412, + 8287, 11071, 5770, + 8287, 11071, 6594, + 8287, 11071, 6912, + 8287, 11071, 6982, + 8287, 11071, 7166, + 8287, 11071, 7244, + 8287, 11071, 7372, + 8287, 11071, 7440, + 8287, 11071, 8362, + 8287, 11071, 8828, + 8287, 11071, 9086, + 8287, 11071, 9400, + 8287, 11071, 9562, + 8287, 11071, 9588, + 8287, 11071, 9780, + 8287, 11071, 10686, + 8287, 11071, 11248, + 8287, 11071, 11682, + 8287, 11071, 11696, + 8287, 11071, 11728, + 8287, 11071, 11758, + 8287, 11071, 11814, + 8287, 11071, 11816, + 8287, 11071, 11828, + 8287, 11071, 11834, + 8287, 11071, 12032, + 8287, 11071, 12034, + 8287, 11071, 12036, + 8287, 11071, 12038, + 8287, 11071, 12070, + 8287, 11071, 12078, + 8287, 11071, 12080, + 8287, 11071, 12082, + 8287, 11071, 12094, + 8287, 11071, 12096, + 8287, 11071, 12126, + 8287, 11071, 12130, + 8287, 11071, 12144, + 8287, 11071, 12146, + 8287, 11071, 12148, + 8287, 11071, 12150, + 8287, 11071, 12346, + 8287, 11071, 12348, + 8287, 11071, 12350, + 8287, 11071, 12388, + 8287, 11071, 12484, + 8287, 11071, 12496, + 8287, 11071, 12508, + 8287, 11071, 12512, + 8287, 11071, 12514, + 8287, 11071, 12532, + 8287, 11071, 12534, + 8287, 11071, 12884, + 8287, 11071, 12944, + 8287, 11071, 12958, + 8287, 11071, 12960, + 8287, 11071, 12970, + 8287, 11071, 12972, + 8287, 11071, 12978, + 8287, 11071, 12980, + 8287, 11071, 12992, + 8287, 11071, 12996, + 8287, 11071, 13002, + 8287, 11071, 13004, + 8287, 11071, 13006, + 8287, 11071, 13008, + 8287, 11071, 13026, + 8287, 11071, 13034, + 8287, 11071, 13204, + 8287, 11071, 13214, + 8287, 11071, 13224, + 8287, 11071, 13346, + 8287, 11071, 13348, + 8287, 11071, 13354, + 8287, 11071, 13362, + 8287, 11071, 13370, + 8287, 11071, 13372, + 8287, 11071, 13374, + 8287, 11071, 13388, + 8287, 11071, 13394, + 8287, 11071, 13396, + 8287, 11071, 13406, + 8287, 11073, 0, + 8287, 11073, 8, + 8287, 11073, 16, + 8287, 11073, 28, + 8287, 11073, 40, + 8287, 11073, 66, + 8287, 11073, 178, + 8287, 11073, 188, + 8287, 11073, 426, + 8287, 11073, 622, + 8287, 11073, 626, + 8287, 11073, 630, + 8287, 11073, 652, + 8287, 11073, 654, + 8287, 11073, 656, + 8287, 11073, 660, + 8287, 11073, 664, + 8287, 11073, 686, + 8287, 11073, 688, + 8287, 11073, 1466, + 8287, 11073, 1468, + 8287, 11073, 1470, + 8287, 11073, 2148, + 8287, 11073, 2150, + 8287, 11073, 2152, + 8287, 11073, 2800, + 8287, 11073, 2802, + 8287, 11073, 2908, + 8287, 11073, 2926, + 8287, 11073, 3012, + 8287, 11073, 3056, + 8287, 11073, 4160, + 8287, 11073, 4162, + 8287, 11073, 4168, + 8287, 11073, 4592, + 8287, 11073, 4594, + 8287, 11073, 5370, + 8287, 11073, 5372, + 8287, 11073, 6040, + 8287, 11073, 6042, + 8287, 11073, 6158, + 8287, 11073, 6204, + 8287, 11073, 6216, + 8287, 11073, 6218, + 8287, 11073, 6226, + 8287, 11073, 6228, + 8287, 11073, 6230, + 8287, 11073, 6232, + 8287, 11073, 6422, + 8287, 11073, 6736, + 8287, 11073, 6760, + 8287, 11073, 7838, + 8287, 11073, 7850, + 8287, 11073, 7852, + 8287, 11073, 7862, + 8287, 11073, 7864, + 8287, 11073, 7866, + 8287, 11073, 8206, + 8287, 11073, 8950, + 8287, 11073, 8952, + 8287, 11073, 8956, + 8287, 11073, 9002, + 8287, 11073, 9004, + 8287, 11073, 9346, + 8287, 11073, 9800, + 8287, 11073, 9882, + 8287, 11073, 11822, + 8293, 4927, 7121, 1044, + 8293, 4927, 7773, 1044, + 8293, 4927, 8455, 8056, + 8293, 7383, 2535, 1044, + 8293, 7383, 5522, + 8293, 7383, 5699, 1044, + 8293, 7383, 6901, 7342, + 8293, 7383, 6901, 7502, + 8293, 7383, 6901, 8620, + 8293, 7383, 6914, + 8293, 7383, 6948, + 8293, 7383, 6949, 6899, 1177, 2852, + 8293, 7383, 7148, + 8293, 7383, 7342, + 8293, 7383, 7502, + 8293, 7383, 7536, + 8293, 7383, 7742, + 8293, 7383, 8087, 445, 7132, + 8293, 7383, 8620, + 8293, 7383, 8621, 7404, + 8293, 7383, 8626, + 8293, 7383, 12957, 8910, + 8293, 7909, 2168, + 8293, 7909, 4054, + 8293, 7909, 4604, + 8293, 7909, 6439, 8280, + 8293, 7909, 6652, + 8293, 7909, 7192, + 8293, 7909, 7346, + 8293, 7909, 7402, + 8293, 7909, 7432, + 8293, 7909, 7502, + 8293, 7909, 7676, + 8293, 7909, 7855, 785, 6222, + 8293, 7909, 7858, + 8293, 7909, 7869, 6816, + 8293, 7909, 7869, 7404, + 8293, 7909, 7870, + 8293, 7909, 7886, + 8293, 7909, 8252, + 8293, 7909, 8253, 8492, + 8293, 7909, 8468, + 8293, 7909, 8469, 8346, + 8293, 7909, 8568, + 8293, 7909, 8623, 5398, + 8293, 7909, 8830, + 8293, 7909, 9272, + 8293, 7909, 9773, 8244, + 8293, 7909, 9773, 8624, + 8293, 7909, 10310, + 8293, 7909, 11016, + 8293, 7909, 11798, + 8293, 8405, 238, + 8293, 8405, 239, 6121, 7132, + 8293, 8405, 468, + 8293, 8405, 469, 6121, 5522, + 8293, 8405, 469, 6121, 8086, + 8293, 8405, 788, + 8293, 8405, 789, 6121, 5522, + 8293, 8405, 789, 6121, 8086, + 8293, 8405, 1366, + 8293, 8405, 1578, + 8293, 8405, 1579, 6121, 5522, + 8293, 8405, 1579, 6121, 8086, + 8293, 8405, 1892, + 8293, 8405, 1893, 6121, 8086, + 8293, 8405, 2110, + 8293, 8405, 2111, 6121, 8086, + 8293, 8405, 2318, + 8293, 8405, 2319, 6121, 8086, + 8293, 8405, 2660, + 8293, 8405, 2661, 6121, 8086, + 8293, 8405, 2674, + 8293, 8405, 2675, 6121, 8086, + 8293, 8405, 2852, + 8293, 8405, 2853, 6121, 6948, + 8293, 8405, 2853, 6121, 8086, + 8293, 8405, 3080, + 8293, 8405, 3081, 6121, 6914, + 8293, 8405, 3081, 6121, 8086, + 8293, 8405, 3244, + 8293, 8405, 3245, 6121, 7132, + 8293, 8405, 3245, 6121, 7342, + 8293, 8405, 3245, 6121, 8620, + 8293, 8405, 3292, + 8293, 8405, 5538, + 8293, 8405, 5539, 6121, 8086, + 8293, 8405, 5698, + 8293, 8405, 5699, 6121, 2535, 1044, + 8293, 8405, 5699, 6121, 5699, 1044, + 8293, 8405, 5699, 6121, 8086, + 8293, 8405, 5699, 6121, 8087, 721, 2535, 1044, + 8293, 8405, 5699, 6121, 8087, 721, 5699, 1044, + 8293, 8405, 6115, 238, + 8293, 8405, 6115, 1578, + 8293, 8405, 6115, 2660, + 8293, 8405, 6115, 3244, + 8293, 8405, 6115, 5538, + 8293, 8405, 6115, 6642, + 8293, 8405, 6115, 6789, 1892, + 8293, 8405, 6115, 7082, + 8293, 8405, 6642, + 8293, 8405, 6643, 6121, 8086, + 8293, 8405, 6789, 468, + 8293, 8405, 6789, 469, 6121, 8086, + 8293, 8405, 6789, 1578, + 8293, 8405, 6789, 1579, 6121, 8086, + 8293, 8405, 6789, 1892, + 8293, 8405, 6789, 2110, + 8293, 8405, 6789, 7740, + 8293, 8405, 6856, + 8293, 8405, 6857, 6121, 8086, + 8293, 8405, 7082, + 8293, 8405, 7083, 6121, 8086, + 8293, 8405, 7740, + 8293, 8405, 7741, 6121, 8086, + 8293, 8405, 7872, + 8293, 8405, 7873, 6121, 8086, + 8293, 8405, 8660, + 8293, 8405, 8661, 6121, 8086, + 8293, 8405, 11893, 3292, + 8293, 8405, 11893, 5445, 5758, + 8293, 10301, 3245, 7082, + 8293, 10301, 9847, 2853, 3080, + 8293, 10301, 9847, 3081, 3081, 7342, + 8293, 10301, 9847, 8153, 2852, + 8293, 10301, 9847, 8153, 3080, + 8293, 12133, 2111, 9318, + 8293, 12133, 2551, 7340, + 8293, 12133, 7134, + 8293, 12133, 7338, + 8293, 12133, 8252, + 8293, 12133, 11016, + 8306, + 8307, 6121, 10804, + 8307, 8022, + 8337, 9617, 151, 2090, + 8337, 9617, 228, + 8337, 9617, 229, 8722, + 8337, 9617, 720, + 8337, 9617, 742, + 8337, 9617, 806, + 8337, 9617, 824, + 8337, 9617, 920, + 8337, 9617, 1036, + 8337, 9617, 1044, + 8337, 9617, 1048, + 8337, 9617, 1090, + 8337, 9617, 1092, + 8337, 9617, 1136, + 8337, 9617, 1170, + 8337, 9617, 1182, + 8337, 9617, 1474, + 8337, 9617, 1504, + 8337, 9617, 1780, + 8337, 9617, 1860, + 8337, 9617, 2024, + 8337, 9617, 2090, + 8337, 9617, 2166, + 8337, 9617, 2170, + 8337, 9617, 2224, + 8337, 9617, 2390, + 8337, 9617, 2392, + 8337, 9617, 2400, + 8337, 9617, 2454, + 8337, 9617, 2502, + 8337, 9617, 2504, + 8337, 9617, 2586, + 8337, 9617, 2670, + 8337, 9617, 2778, + 8337, 9617, 2779, 6896, + 8337, 9617, 2834, + 8337, 9617, 3762, + 8337, 9617, 3788, + 8337, 9617, 3794, + 8337, 9617, 3798, + 8337, 9617, 3800, + 8337, 9617, 3805, 429, 6604, + 8337, 9617, 3806, + 8337, 9617, 3850, + 8337, 9617, 3852, + 8337, 9617, 3940, + 8337, 9617, 3942, + 8337, 9617, 3944, + 8337, 9617, 4052, + 8337, 9617, 4094, + 8337, 9617, 4108, + 8337, 9617, 4117, 826, + 8337, 9617, 4120, + 8337, 9617, 4172, + 8337, 9617, 4178, + 8337, 9617, 4180, + 8337, 9617, 4194, + 8337, 9617, 4196, + 8337, 9617, 4208, + 8337, 9617, 4218, + 8337, 9617, 4244, + 8337, 9617, 4342, + 8337, 9617, 4386, + 8337, 9617, 4389, 5969, 7736, + 8337, 9617, 4390, + 8337, 9617, 4398, + 8337, 9617, 4402, + 8337, 9617, 4530, + 8337, 9617, 4536, + 8337, 9617, 4608, + 8337, 9617, 4628, + 8337, 9617, 4824, + 8337, 9617, 4834, + 8337, 9617, 4844, + 8337, 9617, 4846, + 8337, 9617, 4850, + 8337, 9617, 4872, + 8337, 9617, 4876, + 8337, 9617, 4894, + 8337, 9617, 4895, 8756, + 8337, 9617, 4940, + 8337, 9617, 5012, + 8337, 9617, 5242, + 8337, 9617, 5385, 826, + 8337, 9617, 5438, + 8337, 9617, 5524, + 8337, 9617, 5546, + 8337, 9617, 5562, + 8337, 9617, 5632, + 8337, 9617, 5646, + 8337, 9617, 5650, + 8337, 9617, 5764, + 8337, 9617, 5772, + 8337, 9617, 5834, + 8337, 9617, 5836, + 8337, 9617, 5884, + 8337, 9617, 5940, + 8337, 9617, 5968, + 8337, 9617, 6100, + 8337, 9617, 6101, 10970, + 8337, 9617, 6112, + 8337, 9617, 6116, + 8337, 9617, 6118, + 8337, 9617, 6130, + 8337, 9617, 6132, + 8337, 9617, 6384, + 8337, 9617, 6434, + 8337, 9617, 6504, + 8337, 9617, 6512, + 8337, 9617, 6520, + 8337, 9617, 6574, + 8337, 9617, 6600, + 8337, 9617, 6612, + 8337, 9617, 6618, + 8337, 9617, 6670, + 8337, 9617, 6716, + 8337, 9617, 6722, + 8337, 9617, 6734, + 8337, 9617, 6780, + 8337, 9617, 6786, + 8337, 9617, 6794, + 8337, 9617, 6852, + 8337, 9617, 6870, + 8337, 9617, 6872, + 8337, 9617, 6906, + 8337, 9617, 6952, + 8337, 9617, 7056, + 8337, 9617, 7144, + 8337, 9617, 7184, + 8337, 9617, 7186, + 8337, 9617, 7388, + 8337, 9617, 7443, 5385, 826, + 8337, 9617, 7446, + 8337, 9617, 7526, + 8337, 9617, 7532, + 8337, 9617, 7548, + 8337, 9617, 7551, 8785, 3788, + 8337, 9617, 7551, 8824, + 8337, 9617, 7580, + 8337, 9617, 7582, + 8337, 9617, 7584, + 8337, 9617, 7592, + 8337, 9617, 7602, + 8337, 9617, 7604, + 8337, 9617, 7612, + 8337, 9617, 7616, + 8337, 9617, 7628, + 8337, 9617, 7634, + 8337, 9617, 7642, + 8337, 9617, 7654, + 8337, 9617, 7662, + 8337, 9617, 7704, + 8337, 9617, 7726, + 8337, 9617, 7730, + 8337, 9617, 7812, + 8337, 9617, 7816, + 8337, 9617, 7820, + 8337, 9617, 7830, + 8337, 9617, 7832, + 8337, 9617, 7942, + 8337, 9617, 7964, + 8337, 9617, 7974, + 8337, 9617, 8000, + 8337, 9617, 8008, + 8337, 9617, 8078, + 8337, 9617, 8118, + 8337, 9617, 8151, 5896, + 8337, 9617, 8151, 6600, + 8337, 9617, 8153, 46, + 8337, 9617, 8154, + 8337, 9617, 8194, + 8337, 9617, 8303, 10970, + 8337, 9617, 8316, + 8337, 9617, 8476, + 8337, 9617, 8484, + 8337, 9617, 8542, + 8337, 9617, 8678, + 8337, 9617, 8680, + 8337, 9617, 8730, + 8337, 9617, 8734, + 8337, 9617, 8740, + 8337, 9617, 8744, + 8337, 9617, 8793, 9426, + 8337, 9617, 8844, + 8337, 9617, 8852, + 8337, 9617, 8866, + 8337, 9617, 8870, + 8337, 9617, 8906, + 8337, 9617, 8928, + 8337, 9617, 8946, + 8337, 9617, 9056, + 8337, 9617, 9102, + 8337, 9617, 9106, + 8337, 9617, 9274, + 8337, 9617, 9282, + 8337, 9617, 9322, + 8337, 9617, 9426, + 8337, 9617, 9480, + 8337, 9617, 9532, + 8337, 9617, 9608, + 8337, 9617, 9658, + 8337, 9617, 9822, + 8337, 9617, 9934, + 8337, 9617, 10206, + 8337, 9617, 10336, + 8337, 9617, 10344, + 8337, 9617, 10456, + 8337, 9617, 10520, + 8337, 9617, 10542, + 8337, 9617, 10970, + 8337, 9617, 11488, + 8337, 9617, 11606, + 8337, 9617, 11946, + 8337, 9617, 12155, 6118, + 8349, 5758, + 8371, 10539, 8774, + 8389, 5912, + 8389, 5913, 445, 6741, 568, + 8401, 5759, 2388, + 8401, 5759, 7282, + 8401, 6689, 2170, + 8401, 6689, 2540, + 8401, 6689, 2778, + 8401, 6689, 4200, + 8401, 6689, 4214, + 8401, 6689, 5190, + 8401, 6689, 6260, + 8401, 6689, 6722, + 8401, 6689, 7508, + 8401, 6689, 7694, + 8401, 7803, 5759, 8, + 8401, 7803, 5759, 16, + 8401, 7803, 5759, 28, + 8401, 7803, 5759, 40, + 8401, 7803, 5759, 58, + 8401, 7803, 5759, 440, + 8401, 7803, 5759, 606, + 8401, 8405, 0, + 8401, 8405, 100, + 8401, 8405, 116, + 8401, 8405, 138, + 8401, 8405, 196, + 8401, 8405, 216, + 8401, 8405, 236, + 8401, 8405, 292, + 8401, 8405, 306, + 8401, 8405, 332, + 8401, 8405, 364, + 8401, 8405, 392, + 8401, 8405, 462, + 8401, 8405, 510, + 8401, 8405, 524, + 8401, 8405, 556, + 8401, 8405, 610, + 8401, 8405, 622, + 8401, 8405, 652, + 8401, 8405, 814, + 8401, 8405, 884, + 8401, 8405, 974, + 8401, 8405, 1080, + 8401, 8405, 1168, + 8401, 8405, 1286, + 8401, 8405, 1390, + 8401, 8405, 1612, + 8401, 8405, 1652, + 8401, 8405, 1930, + 8401, 8405, 2030, + 8401, 8405, 2126, + 8401, 8405, 2212, + 8401, 8405, 2234, + 8401, 8405, 2516, + 8401, 8405, 2678, + 8401, 8405, 2732, + 8401, 8405, 2746, + 8401, 8405, 5978, + 8401, 8405, 5994, + 8401, 10775, 5759, 20, + 8401, 10775, 5759, 22, + 8401, 10775, 5759, 24, + 8401, 10775, 5759, 26, + 8401, 10775, 5759, 30, + 8401, 10775, 5759, 34, + 8401, 10775, 5759, 38, + 8401, 10775, 5759, 4720, + 8401, 10775, 5759, 9522, + 8401, 11257, 8405, 510, + 8401, 11257, 8405, 652, + 8401, 12133, 5301, 8827, 8782, + 8401, 12133, 8038, + 8401, 12133, 8782, + 8401, 12133, 8856, + 8401, 12133, 8857, 8038, + 8421, 3, 8775, 3328, + 8421, 3, 8775, 3330, + 8421, 3, 8775, 3336, + 8421, 3, 8775, 3360, + 8421, 3, 8775, 3384, + 8421, 3, 8775, 3388, + 8421, 3, 8775, 3402, + 8421, 3, 8775, 3416, + 8421, 3, 8775, 3418, + 8421, 3, 8775, 3448, + 8421, 3, 8775, 3454, + 8421, 3, 8775, 3456, + 8421, 3, 8775, 3460, + 8421, 3, 8775, 3464, + 8421, 3, 10247, 3471, 1860, + 8421, 3, 10247, 3473, 7830, + 8421, 3, 10247, 3475, 4052, + 8421, 3, 10247, 3477, 6742, + 8421, 3, 10247, 3479, 7816, + 8421, 3, 10247, 3481, 7978, + 8421, 3, 10247, 3483, 7314, + 8421, 3, 10247, 3485, 7614, + 8421, 3, 10247, 3487, 9134, + 8421, 3, 10247, 3493, 2164, + 8421, 3, 10247, 3495, 6118, + 8421, 3, 10247, 3496, + 8421, 3, 10247, 3503, 8018, + 8421, 3, 10247, 3505, 4342, + 8421, 3, 10247, 3506, + 8421, 3, 10247, 3509, 6124, + 8421, 3, 10247, 3510, + 8421, 3, 10247, 3512, + 8421, 3, 10247, 3515, 4536, + 8421, 3, 10247, 3516, + 8421, 3, 10247, 3518, + 8421, 3, 10247, 3520, + 8421, 3, 10247, 3526, + 8421, 3, 10247, 3528, + 8421, 3, 10247, 3531, 6604, + 8421, 3, 10247, 3532, + 8421, 3, 10247, 3534, + 8421, 3, 10247, 3537, 9300, + 8421, 3, 10247, 3539, 7936, + 8421, 3, 10247, 3540, + 8421, 3, 10247, 3542, + 8421, 3, 10247, 3544, + 8421, 3, 10247, 3546, + 8421, 3, 10247, 3548, + 8421, 3, 10247, 3550, + 8421, 3, 10247, 3552, + 8421, 3, 10247, 3554, + 8421, 3, 10247, 3556, + 8421, 3, 10247, 3559, 7182, + 8421, 3, 10247, 3560, + 8421, 3, 10247, 3563, 5968, + 8421, 3, 10247, 3564, + 8421, 3, 10247, 3566, + 8421, 3, 10247, 3568, + 8421, 3, 10247, 3570, + 8421, 3, 10247, 3572, + 8421, 3, 10247, 3574, + 8421, 3, 10247, 3576, + 8421, 3, 10247, 3578, + 8421, 3, 10247, 3580, + 8421, 3, 10247, 3582, + 8421, 3, 10247, 3584, + 8421, 3, 10247, 3587, 8296, + 8421, 3, 10247, 3629, 11000, + 8421, 3, 10247, 3635, 9030, + 8421, 3, 10247, 3645, 7612, + 8421, 3, 10247, 3647, 6434, + 8421, 3, 10247, 3648, + 8421, 3, 10247, 3651, 7656, + 8421, 3, 10247, 3652, + 8421, 3, 10247, 3654, + 8421, 3, 10247, 3657, 9841, 9082, + 8421, 3, 10247, 3659, 9082, + 8421, 3, 10247, 3661, 9083, 6806, + 8421, 3, 10247, 3663, 7818, + 8421, 3, 10247, 3664, + 8421, 3, 10247, 3666, + 8421, 3, 10247, 3670, + 8421, 3, 10247, 3672, + 8421, 3, 10247, 3676, + 8421, 3, 10247, 3678, + 8421, 3, 10247, 3680, + 8421, 3, 10247, 3683, 3990, + 8421, 3, 10247, 3684, + 8421, 3, 10247, 3686, + 8421, 3, 10247, 3688, + 8421, 3, 10247, 3690, + 8421, 3, 10247, 3692, + 8421, 3, 10247, 6445, 4924, + 8421, 3, 10247, 6447, 10536, + 8421, 3, 10247, 6449, 1132, + 8421, 3, 10247, 6451, 2386, + 8421, 3, 10247, 6453, 10516, + 8421, 3, 10247, 6455, 9332, + 8421, 3, 10247, 6457, 2562, + 8421, 3, 10247, 6459, 3796, + 8421, 3, 10247, 6461, 920, + 8421, 3, 10247, 6463, 3812, + 8421, 3, 10247, 8915, 3522, + 8421, 3, 10247, 8915, 3588, + 8421, 3, 10247, 8915, 3590, + 8421, 3, 10247, 8915, 3592, + 8421, 3, 10247, 8915, 3594, + 8421, 3, 10247, 8915, 3596, + 8421, 3, 10247, 8915, 3598, + 8421, 3, 10247, 8915, 3600, + 8421, 3, 10247, 8915, 3602, + 8421, 3, 10247, 8915, 3604, + 8421, 3, 10247, 8915, 3606, + 8421, 3, 10247, 8915, 3608, + 8421, 3, 10247, 8915, 3610, + 8421, 3, 10247, 8915, 3612, + 8421, 3, 10247, 8915, 3614, + 8421, 3, 10247, 8915, 3616, + 8421, 3, 10247, 8915, 3618, + 8421, 3, 10247, 8915, 3620, + 8421, 3, 10247, 8915, 3622, + 8421, 3, 10247, 8915, 3624, + 8421, 3, 10247, 8915, 3626, + 8421, 3, 10247, 8915, 3630, + 8421, 3, 10247, 8915, 3632, + 8421, 3, 10247, 8915, 3636, + 8421, 3, 10247, 8915, 3638, + 8421, 3, 10247, 8915, 3640, + 8421, 3, 10247, 8915, 3642, + 8421, 3, 10247, 8915, 3674, + 8421, 3, 10247, 8915, 3694, + 8421, 3, 10343, 3489, 4726, + 8421, 3, 10343, 3491, 8334, + 8421, 3, 10343, 3499, 6424, + 8421, 3, 10343, 3501, 4948, + 8421, 3, 10343, 3525, 7754, + 8421, 3, 10343, 3669, 6692, + 8421, 3, 10585, 3295, 138, + 8421, 3, 10585, 3297, 516, + 8421, 3, 10585, 3299, 462, + 8421, 3, 10585, 3301, 560, + 8421, 3, 10585, 3303, 568, + 8421, 3, 10585, 3305, 392, + 8421, 3, 10585, 3307, 144, + 8421, 3, 10585, 3309, 0, + 8421, 3, 10585, 3311, 526, + 8421, 3, 10585, 3313, 40, + 8421, 3, 10585, 3315, 480, + 8421, 3, 10585, 3317, 536, + 8421, 3, 10585, 3319, 368, + 8421, 3, 10585, 3321, 150, + 8421, 3, 10585, 3323, 380, + 8421, 3, 10585, 3325, 496, + 8421, 3, 10585, 3327, 670, + 8421, 3, 10585, 3333, 678, + 8421, 3, 10585, 3335, 500, + 8421, 3, 10585, 3339, 384, + 8421, 3, 10585, 3341, 396, + 8421, 3, 10585, 3343, 54, + 8421, 3, 10585, 3345, 520, + 8421, 3, 10585, 3347, 512, + 8421, 3, 10585, 3349, 16, + 8421, 3, 10585, 3351, 2254, + 8421, 3, 10585, 3353, 404, + 8421, 3, 10585, 3355, 524, + 8421, 3, 10585, 3357, 502, + 8421, 3, 10585, 3359, 2376, + 8421, 3, 10585, 3363, 298, + 8421, 3, 10585, 3365, 564, + 8421, 3, 10585, 3367, 8, + 8421, 3, 10585, 3369, 476, + 8421, 3, 10585, 3371, 630, + 8421, 3, 10585, 3373, 532, + 8421, 3, 10585, 3375, 632, + 8421, 3, 10585, 3377, 56, + 8421, 3, 10585, 3379, 310, + 8421, 3, 10585, 3381, 142, + 8421, 3, 10585, 3383, 294, + 8421, 3, 10585, 3387, 2122, + 8421, 3, 10585, 3391, 486, + 8421, 3, 10585, 3393, 152, + 8421, 3, 10585, 3395, 412, + 8421, 3, 10585, 3397, 514, + 8421, 3, 10585, 3399, 622, + 8421, 3, 10585, 3401, 416, + 8421, 3, 10585, 3405, 292, + 8421, 3, 10585, 3407, 546, + 8421, 3, 10585, 3409, 556, + 8421, 3, 10585, 3411, 510, + 8421, 3, 10585, 3413, 28, + 8421, 3, 10585, 3415, 2252, + 8421, 3, 10585, 3421, 300, + 8421, 3, 10585, 3423, 2632, + 8421, 3, 10585, 3425, 314, + 8421, 3, 10585, 3427, 2422, + 8421, 3, 10585, 3429, 576, + 8421, 3, 10585, 3431, 322, + 8421, 3, 10585, 3433, 1074, + 8421, 3, 10585, 3435, 468, + 8421, 3, 10585, 3437, 374, + 8421, 3, 10585, 3439, 672, + 8421, 3, 10585, 3441, 626, + 8421, 3, 10585, 3443, 2374, + 8421, 3, 10585, 3445, 306, + 8421, 3, 10585, 3447, 498, + 8421, 3, 10585, 3451, 364, + 8421, 3, 10585, 3453, 326, + 8421, 3, 10585, 3459, 92, + 8421, 3, 10585, 3463, 2774, + 8421, 3, 10585, 3467, 1076, + 8421, 3, 10585, 3469, 2778, + 8429, 8405, 0, + 8429, 8405, 2, + 8429, 8405, 6, + 8429, 8405, 8, + 8429, 8405, 12, + 8429, 8405, 14, + 8429, 8405, 16, + 8429, 8405, 18, + 8429, 8405, 20, + 8429, 8405, 22, + 8429, 8405, 24, + 8429, 8405, 26, + 8429, 8405, 30, + 8429, 8405, 32, + 8429, 8405, 34, + 8429, 8405, 36, + 8429, 8405, 38, + 8429, 8405, 40, + 8429, 8405, 44, + 8429, 8405, 46, + 8429, 8405, 50, + 8429, 8405, 80, + 8429, 8405, 104, + 8429, 8405, 176, + 8429, 8405, 316, + 8429, 8405, 378, + 8429, 8405, 410, + 8429, 8405, 562, + 8429, 8405, 574, + 8431, 8405, 0, + 8431, 8405, 2, + 8431, 8405, 4, + 8431, 8405, 6, + 8431, 8405, 8, + 8431, 8405, 10, + 8431, 8405, 12, + 8431, 8405, 16, + 8431, 8405, 20, + 8431, 8405, 22, + 8431, 8405, 24, + 8431, 8405, 26, + 8431, 8405, 28, + 8431, 8405, 32, + 8431, 8405, 34, + 8431, 8405, 36, + 8431, 8405, 38, + 8431, 8405, 40, + 8431, 8405, 42, + 8431, 8405, 48, + 8431, 8405, 80, + 8431, 8405, 176, + 8431, 8405, 360, + 8431, 8405, 410, + 8431, 8405, 542, + 8431, 8405, 574, + 8431, 11859, 4926, + 8432, + 8463, 4849, 6627, 9051, 10380, + 8463, 4849, 12115, 10380, + 8463, 6505, 8056, + 8463, 7443, 6627, 9051, 10380, + 8463, 7443, 12115, 10380, + 8463, 7512, + 8463, 7593, 7821, 8056, + 8463, 7821, 8056, + 8463, 10677, 760, + 8463, 10997, 4849, 12115, 10380, + 8463, 10997, 7443, 12115, 10380, + 8463, 12505, 7608, + 8463, 12967, 6409, 9051, 10380, + 8463, 13067, 6409, 9051, 10380, + 8473, 1044, + 8480, + 8483, 2779, 2584, + 8499, 10363, 7608, + 8510, + 8521, 10573, 428, + 8521, 10573, 429, 445, 6741, 568, + 8525, 2671, 4223, 5836, + 8525, 5758, + 8525, 8163, 4223, 5836, + 8525, 8875, 4223, 5836, + 8525, 8877, 4223, 5836, + 8525, 9287, 4223, 5836, + 8525, 9701, 4223, 5836, + 8525, 10151, 4223, 5836, + 8525, 10201, 4223, 5836, + 8525, 10361, 4223, 5836, + 8525, 10623, 4223, 5836, + 8525, 11233, 4223, 5836, + 8527, 5758, + 8533, 12143, 10758, + 8534, + 8545, 1610, + 8551, 4849, 12114, + 8551, 7443, 12114, + 8562, + 8570, + 8581, 5758, + 8592, + 8595, 9956, + 8595, 9957, 5387, 2779, 476, + 8609, 4926, + 8609, 4927, 4178, + 8631, 8151, 12953, 8450, + 8631, 8744, + 8631, 12953, 8450, + 8639, 7803, 5759, 8, + 8639, 7803, 5759, 16, + 8639, 7803, 5759, 28, + 8639, 7803, 5759, 40, + 8639, 7803, 5759, 72, + 8639, 7803, 5759, 92, + 8639, 7803, 5759, 160, + 8639, 7803, 5759, 188, + 8639, 8405, 0, + 8639, 8405, 100, + 8639, 8405, 116, + 8639, 8405, 138, + 8639, 8405, 216, + 8639, 8405, 236, + 8639, 8405, 292, + 8639, 8405, 306, + 8639, 8405, 332, + 8639, 8405, 364, + 8639, 8405, 392, + 8639, 8405, 462, + 8639, 8405, 510, + 8639, 8405, 524, + 8639, 8405, 556, + 8639, 8405, 622, + 8639, 8405, 652, + 8639, 8405, 1878, + 8639, 8405, 2006, + 8639, 8405, 2030, + 8639, 8405, 2126, + 8639, 8405, 5152, + 8639, 8405, 5312, + 8639, 8916, + 8639, 9665, 4926, + 8639, 10775, 5759, 14, + 8639, 10775, 5759, 26, + 8639, 10775, 5759, 34, + 8639, 10775, 5759, 400, + 8643, 8774, + 8649, 10001, 9967, 7607, 4153, 6434, + 8649, 10001, 9967, 9279, 10000, + 8668, + 8672, + 8679, 7593, 8, + 8679, 7593, 12, + 8679, 7593, 22, + 8679, 7593, 28, + 8679, 9063, 2, + 8679, 9063, 8, + 8679, 9063, 10, + 8679, 9063, 14, + 8679, 9063, 16, + 8679, 9063, 22, + 8679, 9063, 24, + 8679, 9063, 30, + 8679, 9063, 34, + 8684, + 8691, 1044, + 8717, 7119, 11195, 4926, + 8717, 12967, 6409, 11195, 4926, + 8717, 13067, 6409, 11195, 4926, + 8717, 13201, 11195, 4926, + 8745, 1, 5387, 24, + 8745, 5, 5387, 312, + 8745, 21, 2162, + 8745, 25, 2162, + 8745, 25, 5387, 36, + 8745, 25, 5387, 37, 9732, + 8745, 25, 6624, + 8745, 25, 9732, + 8745, 43, 5387, 24, + 8745, 78, + 8745, 92, + 8745, 110, + 8745, 118, + 8745, 120, + 8745, 128, + 8745, 129, 6624, + 8745, 129, 9732, + 8745, 130, + 8745, 138, + 8745, 140, + 8745, 146, + 8745, 148, + 8745, 149, 6624, + 8745, 149, 9732, + 8745, 190, + 8745, 206, + 8745, 218, + 8745, 234, + 8745, 236, + 8745, 240, + 8745, 248, + 8745, 254, + 8745, 274, + 8745, 286, + 8745, 306, + 8745, 308, + 8745, 312, + 8745, 316, + 8745, 318, + 8745, 320, + 8745, 321, 6624, + 8745, 321, 9062, + 8745, 321, 9732, + 8745, 324, + 8745, 328, + 8745, 330, + 8745, 346, + 8745, 348, + 8745, 358, + 8745, 364, + 8745, 366, + 8745, 367, 7592, + 8745, 370, + 8745, 376, + 8745, 378, + 8745, 379, 6624, + 8745, 379, 9732, + 8745, 382, + 8745, 385, 0, + 8745, 385, 10, + 8745, 385, 12, + 8745, 385, 22, + 8745, 385, 24, + 8745, 385, 36, + 8745, 385, 42, + 8745, 385, 44, + 8745, 386, + 8745, 387, 4946, + 8745, 388, + 8745, 389, 4946, + 8745, 392, + 8745, 398, + 8745, 408, + 8745, 414, + 8745, 418, + 8745, 420, + 8745, 452, + 8745, 462, + 8745, 463, 3260, + 8745, 464, + 8745, 470, + 8745, 474, + 8745, 478, + 8745, 482, + 8745, 484, + 8745, 488, + 8745, 490, + 8745, 540, + 8745, 548, + 8745, 624, + 8745, 760, + 8745, 856, + 8745, 860, + 8745, 928, + 8745, 1117, 5047, 7142, + 8745, 1117, 5047, 8294, + 8745, 1117, 5047, 8778, + 8745, 1117, 5047, 9762, + 8745, 1118, + 8745, 1212, + 8745, 1270, + 8745, 1298, + 8745, 1422, + 8745, 1432, + 8745, 1622, + 8745, 1668, + 8745, 1800, + 8745, 1908, + 8745, 1918, + 8745, 1934, + 8745, 1946, + 8745, 2248, + 8745, 2382, + 8745, 2383, 5387, 36, + 8745, 2383, 5387, 37, 9732, + 8745, 2688, + 8745, 2720, + 8745, 2816, + 8745, 3224, + 8745, 3790, + 8745, 4062, + 8745, 4110, + 8745, 4208, + 8745, 4332, + 8745, 4532, + 8745, 4612, + 8745, 4732, + 8745, 4762, + 8745, 4849, 5385, 827, 10374, + 8745, 4946, + 8745, 5008, + 8745, 5052, + 8745, 5378, + 8745, 5380, + 8745, 5408, + 8745, 5430, + 8745, 5534, + 8745, 5552, + 8745, 5566, + 8745, 6121, 2725, 4389, 6504, + 8745, 6121, 4849, 4389, 6504, + 8745, 6121, 7121, 4849, 10001, 4389, 6504, + 8745, 6121, 7121, 7443, 10001, 4389, 6504, + 8745, 6121, 7443, 4389, 6504, + 8745, 6121, 7773, 4849, 569, 7121, 7443, 4192, + 8745, 6121, 7773, 4849, 10001, 4389, 6504, + 8745, 6121, 7773, 7443, 569, 7121, 4849, 4192, + 8745, 6121, 7773, 7443, 10001, 4389, 6504, + 8745, 6121, 8005, 4389, 6504, + 8745, 6121, 10001, 11469, 4192, + 8745, 6121, 10677, 4192, + 8745, 6121, 10779, 9544, + 8745, 6121, 11649, 4192, + 8745, 6121, 11707, 11469, 4192, + 8745, 6234, + 8745, 6410, + 8745, 6482, + 8745, 6630, + 8745, 6718, + 8745, 6826, + 8745, 6828, + 8745, 6858, + 8745, 6892, + 8745, 6950, + 8745, 6958, + 8745, 6989, 428, + 8745, 6989, 429, 445, 2091, 6741, 568, + 8745, 6989, 429, 445, 6741, 568, + 8745, 7018, + 8745, 7034, + 8745, 7060, + 8745, 7126, + 8745, 7128, + 8745, 7276, + 8745, 7330, + 8745, 7352, + 8745, 7360, + 8745, 7384, + 8745, 7443, 5385, 827, 10374, + 8745, 7470, + 8745, 7504, + 8745, 7506, + 8745, 7814, + 8745, 7840, + 8745, 7842, + 8745, 7926, + 8745, 7950, + 8745, 8002, + 8745, 8274, + 8745, 8300, + 8745, 8304, + 8745, 8314, + 8745, 8372, + 8745, 8378, + 8745, 8452, + 8745, 8572, + 8745, 8588, + 8745, 8604, + 8745, 9016, + 8745, 9308, + 8745, 9388, + 8745, 9390, + 8745, 9416, + 8745, 9438, + 8745, 9444, + 8745, 9454, + 8745, 9468, + 8745, 9470, + 8745, 9476, + 8745, 9636, + 8745, 9646, + 8745, 9648, + 8745, 9698, + 8745, 9926, + 8745, 10166, + 8745, 10244, + 8745, 10379, 428, + 8745, 10379, 429, 445, 2091, 6741, 568, + 8745, 10379, 429, 445, 6741, 568, + 8745, 10392, + 8745, 10480, + 8745, 10496, + 8745, 11028, + 8745, 11032, + 8745, 11080, + 8745, 11084, + 8745, 11120, + 8745, 11170, + 8745, 11668, + 8745, 11918, + 8745, 12068, + 8755, 10385, 7821, 5830, + 8763, 428, + 8763, 429, 445, 6741, 568, + 8763, 429, 445, 6741, 569, 6121, 1045, 6376, + 8763, 429, 6121, 2091, 6741, 568, + 8763, 429, 6377, 2091, 6741, 568, + 8763, 429, 6377, 7709, 10374, + 8763, 429, 6377, 7919, 6741, 568, + 8763, 429, 6377, 8167, 5758, + 8763, 6121, 1044, + 8763, 6121, 5445, 5759, 6490, + 8763, 6121, 13061, 5759, 6490, + 8763, 6377, 8762, + 8763, 6377, 10578, + 8763, 6377, 11765, 6434, + 8773, 7207, 5759, 9328, + 8773, 7207, 5759, 9870, + 8773, 7207, 5759, 10148, + 8773, 7207, 7803, 5759, 0, + 8773, 7207, 7803, 5759, 8, + 8773, 7207, 7803, 5759, 16, + 8773, 7207, 7803, 5759, 40, + 8773, 7207, 7803, 5759, 440, + 8773, 7207, 8405, 0, + 8773, 7207, 8405, 8, + 8773, 7207, 8405, 16, + 8773, 7207, 8405, 28, + 8773, 7207, 8405, 40, + 8773, 7207, 8405, 108, + 8773, 7207, 8405, 130, + 8773, 7207, 8405, 150, + 8773, 7207, 8405, 228, + 8773, 7207, 8405, 246, + 8773, 7207, 8405, 298, + 8773, 7207, 8405, 322, + 8773, 7207, 8405, 350, + 8773, 7207, 8405, 380, + 8773, 7207, 8405, 412, + 8773, 7207, 8405, 480, + 8773, 7207, 8405, 516, + 8773, 7207, 8405, 536, + 8773, 7207, 8405, 568, + 8773, 7207, 8405, 798, + 8773, 7207, 8405, 890, + 8773, 7207, 8405, 980, + 8773, 7207, 8405, 1002, + 8773, 7207, 8405, 1266, + 8773, 7207, 8405, 1514, + 8773, 7207, 8405, 1618, + 8773, 7207, 8405, 2218, + 8773, 7207, 8405, 2442, + 8773, 7207, 8405, 2684, + 8773, 7207, 8405, 2754, + 8773, 7207, 8405, 4018, + 8773, 7207, 8405, 6000, + 8773, 7207, 8603, 8442, + 8773, 7207, 8603, 8444, + 8773, 7207, 8603, 8446, + 8773, 7207, 8603, 8448, + 8775, 1177, 1109, 429, 5904, + 8775, 1177, 1109, 429, 8462, + 8775, 1177, 1109, 429, 12886, + 8775, 1177, 1109, 429, 12887, 6510, + 8775, 1177, 3768, + 8775, 1177, 3995, 4881, 8168, + 8775, 1177, 4191, 11228, + 8775, 1177, 4213, 4182, + 8775, 1177, 4877, 4182, + 8775, 1177, 5280, + 8775, 1177, 6053, 11228, + 8775, 1177, 6883, 11228, + 8775, 1177, 7539, 274, + 8775, 1177, 7539, 2186, + 8775, 1177, 7608, + 8775, 1177, 7633, 429, 5904, + 8775, 1177, 7633, 429, 9334, + 8775, 1177, 8026, + 8775, 1177, 8102, + 8775, 1177, 8103, 4213, 2778, + 8775, 1177, 8109, 9117, 2170, + 8775, 1177, 8109, 9117, 2778, + 8775, 1177, 8109, 9117, 4214, + 8775, 1177, 8109, 9117, 7694, + 8775, 1177, 8168, + 8775, 1177, 8637, 11228, + 8775, 1177, 9268, + 8775, 1177, 9502, + 8775, 1177, 9933, 8642, + 8775, 1177, 10357, 11884, + 8775, 1177, 10677, 11846, + 8775, 1177, 10730, + 8775, 1177, 11219, 8724, + 8775, 1177, 11649, 11846, + 8775, 1177, 11840, + 8775, 1177, 11841, 4213, 2778, + 8775, 1177, 11884, + 8775, 1177, 12359, 4598, + 8781, 1109, 429, 11162, + 8781, 2779, 10677, 4113, 6376, + 8781, 2779, 10677, 4113, 6490, + 8781, 6611, 8721, 4848, + 8781, 6611, 8721, 7442, + 8781, 6751, 6376, + 8781, 6751, 6490, + 8781, 6905, 6376, + 8781, 6905, 6490, + 8781, 7198, + 8781, 7427, 6376, + 8781, 7427, 6490, + 8781, 7472, + 8781, 7695, 4113, 6376, + 8781, 7695, 4113, 6490, + 8781, 8151, 7889, 8996, + 8781, 8151, 7889, 11648, + 8781, 8405, 8, + 8781, 8405, 238, + 8781, 8405, 468, + 8781, 8405, 1920, + 8781, 8405, 2110, + 8781, 8405, 2662, + 8781, 8405, 2918, + 8781, 8405, 3776, + 8781, 8405, 4410, + 8781, 8405, 4724, + 8781, 8405, 5476, + 8781, 8405, 5554, + 8781, 8405, 5698, + 8781, 8405, 5902, + 8781, 8405, 5903, 10214, + 8781, 8405, 6236, + 8781, 8405, 6237, 238, + 8781, 8405, 6254, + 8781, 8405, 6394, + 8781, 8405, 6789, 9668, + 8781, 8405, 6820, + 8781, 8405, 6821, 10214, + 8781, 8405, 7474, + 8781, 8405, 8090, + 8781, 8405, 8384, + 8781, 8405, 9185, 8091, 5554, + 8781, 8405, 9583, 6496, + 8781, 8405, 9583, 8258, + 8781, 8405, 9583, 9156, + 8781, 8405, 9668, + 8781, 8405, 9717, 198, + 8781, 8405, 9717, 7046, + 8781, 8405, 9717, 7874, + 8781, 8405, 10489, 468, + 8781, 8405, 12355, 6394, + 8781, 8617, 6376, + 8781, 8617, 6490, + 8781, 8617, 8150, + 8781, 8965, 6376, + 8781, 8965, 6490, + 8781, 8965, 8150, + 8781, 9024, + 8781, 9525, 4877, 6376, + 8781, 9525, 4877, 6490, + 8781, 10179, 1044, + 8781, 10235, 8530, + 8781, 10235, 11118, + 8781, 10235, 11432, + 8781, 10490, + 8781, 11196, + 8781, 11259, 4223, 5836, + 8781, 11259, 6610, + 8781, 11259, 6611, 8721, 7442, + 8781, 11649, 6610, + 8781, 11914, + 8781, 12031, 8150, + 8781, 12357, 4223, 5836, + 8781, 12357, 6610, + 8781, 12357, 6611, 8721, 4848, + 8781, 12391, 4926, + 8794, + 8803, 73, 8399, 4926, + 8803, 5759, 7756, + 8803, 5759, 8916, + 8803, 5759, 9824, + 8803, 5759, 9870, + 8803, 5759, 9904, + 8803, 5759, 11900, + 8803, 6689, 2170, + 8803, 6689, 2540, + 8803, 6689, 2778, + 8803, 6689, 4200, + 8803, 6689, 4214, + 8803, 6689, 5190, + 8803, 6689, 6260, + 8803, 6689, 6722, + 8803, 6689, 7508, + 8803, 6689, 7694, + 8803, 7803, 5759, 8, + 8803, 7803, 5759, 16, + 8803, 7803, 5759, 28, + 8803, 7803, 5759, 40, + 8803, 7803, 5759, 58, + 8803, 7803, 5759, 72, + 8803, 7803, 5759, 92, + 8803, 7803, 5759, 162, + 8803, 7803, 5759, 266, + 8803, 7803, 5759, 440, + 8803, 7803, 5759, 606, + 8803, 7803, 5759, 9827, 22, + 8803, 7803, 5759, 9827, 34, + 8803, 7803, 5759, 9827, 344, + 8803, 7803, 5759, 9827, 518, + 8803, 8399, 4926, + 8803, 8405, 0, + 8803, 8405, 8, + 8803, 8405, 16, + 8803, 8405, 28, + 8803, 8405, 40, + 8803, 8405, 58, + 8803, 8405, 72, + 8803, 8405, 92, + 8803, 8405, 100, + 8803, 8405, 116, + 8803, 8405, 138, + 8803, 8405, 162, + 8803, 8405, 216, + 8803, 8405, 236, + 8803, 8405, 266, + 8803, 8405, 292, + 8803, 8405, 306, + 8803, 8405, 332, + 8803, 8405, 364, + 8803, 8405, 392, + 8803, 8405, 440, + 8803, 8405, 462, + 8803, 8405, 510, + 8803, 8405, 524, + 8803, 8405, 556, + 8803, 8405, 606, + 8803, 8405, 610, + 8803, 8405, 652, + 8803, 8405, 792, + 8803, 8405, 884, + 8803, 8405, 974, + 8803, 8405, 996, + 8803, 8405, 1080, + 8803, 8405, 1260, + 8803, 8405, 1512, + 8803, 8405, 1612, + 8803, 8405, 1796, + 8803, 8405, 2030, + 8803, 8405, 2076, + 8803, 8405, 2126, + 8803, 8405, 2212, + 8803, 8405, 2438, + 8803, 8405, 2516, + 8803, 8405, 2566, + 8803, 8405, 2678, + 8803, 8405, 2732, + 8803, 8405, 2746, + 8803, 8405, 4016, + 8803, 8405, 5994, + 8803, 8405, 9827, 22, + 8803, 8405, 9827, 34, + 8803, 8405, 9827, 344, + 8803, 8405, 9827, 518, + 8803, 10203, 6689, 2171, 1177, 2161, 8611, 429, 4214, + 8803, 10203, 6689, 2171, 1177, 4173, 8611, 429, 4214, + 8803, 10203, 6689, 2779, 1177, 2161, 8611, 429, 4214, + 8803, 10203, 6689, 2779, 1177, 4173, 8611, 429, 4214, + 8803, 10203, 6689, 6261, 1177, 2161, 8611, 429, 4214, + 8803, 10203, 6689, 7695, 1177, 2161, 8611, 429, 4214, + 8803, 10203, 6689, 7695, 1177, 4173, 8611, 429, 4214, + 8811, 7650, + 8811, 8405, 568, + 8811, 8405, 678, + 8811, 8405, 748, + 8811, 8405, 1338, + 8811, 8405, 1982, + 8811, 8405, 2378, + 8811, 8405, 3006, + 8811, 8405, 3120, + 8811, 8405, 3240, + 8811, 8405, 4412, + 8811, 8405, 4734, + 8811, 8405, 5906, + 8811, 8405, 5988, + 8811, 8405, 6402, + 8811, 8405, 6766, + 8811, 8405, 6814, + 8811, 8405, 7016, + 8811, 8405, 7070, + 8811, 8405, 7140, + 8811, 8405, 7268, + 8811, 8405, 7400, + 8811, 8405, 7498, + 8811, 8405, 7780, + 8811, 8405, 7806, + 8811, 8405, 8084, + 8811, 8405, 8110, + 8811, 8405, 8256, + 8811, 8405, 8656, + 8811, 8405, 8698, + 8811, 8405, 8808, + 8811, 8405, 9986, + 8811, 8405, 10278, + 8811, 8405, 10414, + 8811, 8405, 10612, + 8811, 8405, 10690, + 8811, 8405, 10760, + 8811, 8405, 11020, + 8811, 8405, 11100, + 8811, 8405, 11236, + 8811, 8968, + 8811, 9254, + 8811, 9348, + 8811, 9526, + 8811, 9804, + 8811, 10694, + 8811, 10964, + 8811, 10986, + 8811, 11144, + 8811, 11146, + 8849, 5444, + 8849, 6611, 10374, + 8849, 7390, + 8849, 7708, + 8849, 8509, 11098, + 8849, 8509, 12472, + 8849, 9719, 7995, 10476, + 8849, 10260, + 8849, 10677, 761, 6121, 11649, 8758, + 8849, 10677, 761, 7443, 11378, + 8849, 10677, 761, 7995, 10476, + 8849, 10677, 761, 10794, + 8849, 11649, 761, 6121, 8153, 10677, 8758, + 8849, 11649, 761, 6121, 8849, 10677, 8758, + 8865, 5758, + 8869, 2091, 5758, + 8869, 6408, + 8869, 6879, 7593, 8405, 4614, + 8869, 7593, 10, + 8869, 9063, 10, + 8869, 10708, + 8869, 11767, 9063, 12, + 8869, 11767, 9063, 22, + 8869, 11767, 9063, 48, + 8875, 9601, 6505, 5830, + 8900, + 8913, 445, 6623, 9610, + 8923, 10260, + 8927, 10203, 2171, 4388, + 8927, 10203, 2171, 6782, + 8927, 10203, 2171, 7574, + 8927, 10203, 2171, 7686, + 8927, 10203, 2171, 8158, + 8927, 10203, 2171, 9614, + 8927, 10203, 2779, 8200, + 8927, 10203, 2779, 8818, + 8927, 10203, 4201, 8718, + 8927, 10203, 4201, 9258, + 8927, 10203, 4215, 8200, + 8927, 10203, 7509, 9258, + 8927, 10203, 7695, 8200, + 8927, 10203, 7695, 9258, + 8927, 10203, 7695, 10466, + 8939, 9610, + 8975, 428, + 8981, 5758, + 8990, + 9011, 5758, + 9034, + 9039, 93, 8399, 4926, + 9039, 5759, 7282, + 9039, 5759, 8916, + 9039, 5759, 9824, + 9039, 5759, 9870, + 9039, 5759, 9904, + 9039, 5759, 11900, + 9039, 6689, 2170, + 9039, 6689, 2540, + 9039, 6689, 2778, + 9039, 6689, 4200, + 9039, 6689, 4214, + 9039, 6689, 5190, + 9039, 6689, 6260, + 9039, 6689, 6722, + 9039, 6689, 7508, + 9039, 6689, 7694, + 9039, 7469, 4926, + 9039, 7469, 5758, + 9039, 7803, 5759, 8, + 9039, 7803, 5759, 16, + 9039, 7803, 5759, 28, + 9039, 7803, 5759, 40, + 9039, 7803, 5759, 58, + 9039, 7803, 5759, 72, + 9039, 7803, 5759, 92, + 9039, 7803, 5759, 266, + 9039, 7803, 5759, 606, + 9039, 7803, 5759, 9827, 22, + 9039, 7803, 5759, 9827, 34, + 9039, 7803, 5759, 9827, 344, + 9039, 7803, 5759, 9827, 518, + 9039, 8322, + 9039, 8405, 0, + 9039, 8405, 8, + 9039, 8405, 16, + 9039, 8405, 28, + 9039, 8405, 40, + 9039, 8405, 58, + 9039, 8405, 72, + 9039, 8405, 92, + 9039, 8405, 100, + 9039, 8405, 116, + 9039, 8405, 138, + 9039, 8405, 216, + 9039, 8405, 236, + 9039, 8405, 266, + 9039, 8405, 292, + 9039, 8405, 306, + 9039, 8405, 332, + 9039, 8405, 364, + 9039, 8405, 392, + 9039, 8405, 462, + 9039, 8405, 510, + 9039, 8405, 511, 6121, 7121, 10000, + 9039, 8405, 511, 6121, 8473, 10000, + 9039, 8405, 524, + 9039, 8405, 556, + 9039, 8405, 606, + 9039, 8405, 652, + 9039, 8405, 792, + 9039, 8405, 884, + 9039, 8405, 974, + 9039, 8405, 996, + 9039, 8405, 1260, + 9039, 8405, 1512, + 9039, 8405, 1612, + 9039, 8405, 2030, + 9039, 8405, 2076, + 9039, 8405, 2126, + 9039, 8405, 2212, + 9039, 8405, 2410, + 9039, 8405, 2438, + 9039, 8405, 2516, + 9039, 8405, 2566, + 9039, 8405, 2678, + 9039, 8405, 2746, + 9039, 8405, 3110, + 9039, 8405, 4016, + 9039, 8405, 5994, + 9039, 8405, 8357, 556, + 9039, 8405, 9827, 22, + 9039, 8405, 9827, 34, + 9039, 8405, 9827, 344, + 9039, 8405, 9827, 518, + 9039, 9971, 11143, 2170, + 9039, 9971, 11143, 2171, 4853, 5913, 2681, 11932, + 9039, 9971, 11143, 2778, + 9039, 9971, 11143, 4214, + 9039, 9971, 11143, 7694, + 9039, 9971, 11933, 9700, + 9041, 5550, + 9041, 5551, 6121, 8056, + 9042, + 9053, 9575, 6508, + 9053, 9575, 8134, + 9053, 9575, 8136, + 9053, 9575, 8138, + 9053, 9575, 8140, + 9053, 9575, 8142, + 9053, 9575, 8144, + 9053, 9575, 8146, + 9053, 9575, 8148, + 9053, 9575, 9186, + 9053, 9575, 9188, + 9053, 9575, 9190, + 9053, 9575, 9192, + 9053, 9575, 9194, + 9053, 9575, 9196, + 9053, 9575, 9198, + 9053, 9575, 9200, + 9053, 9575, 9202, + 9053, 9575, 9204, + 9053, 9575, 9206, + 9053, 9575, 9208, + 9053, 9575, 9210, + 9053, 9575, 9212, + 9053, 9575, 9214, + 9053, 9575, 9216, + 9053, 9575, 9218, + 9053, 9575, 9220, + 9053, 9575, 9222, + 9053, 9575, 9224, + 9053, 9575, 9226, + 9053, 9575, 9228, + 9053, 9575, 9230, + 9053, 9575, 9232, + 9053, 9575, 9234, + 9053, 9575, 9236, + 9053, 9575, 9238, + 9053, 9575, 9240, + 9053, 9575, 10020, + 9053, 9575, 10022, + 9053, 9575, 10024, + 9053, 9575, 10026, + 9053, 9575, 10028, + 9053, 9575, 10030, + 9053, 9575, 10032, + 9053, 9575, 10034, + 9053, 9575, 10036, + 9053, 9575, 10038, + 9053, 9575, 10040, + 9053, 9575, 10042, + 9053, 9575, 10044, + 9053, 9575, 10046, + 9053, 9575, 10048, + 9053, 9575, 10050, + 9053, 9575, 10052, + 9053, 9575, 10054, + 9053, 9575, 10056, + 9053, 9575, 10058, + 9053, 9575, 10060, + 9053, 9575, 10062, + 9053, 9575, 10064, + 9053, 9575, 10066, + 9053, 9575, 10068, + 9053, 9575, 10070, + 9053, 9575, 10072, + 9053, 9575, 10074, + 9053, 9575, 10076, + 9053, 9575, 10078, + 9053, 9575, 10080, + 9053, 9575, 10082, + 9053, 9575, 10084, + 9053, 9575, 10086, + 9053, 9575, 10088, + 9053, 9575, 10090, + 9053, 9575, 10092, + 9053, 9575, 10094, + 9053, 9575, 10096, + 9053, 9575, 10098, + 9053, 9575, 10100, + 9053, 9575, 10102, + 9053, 9575, 10104, + 9053, 9575, 10106, + 9053, 9575, 10108, + 9053, 9575, 10110, + 9053, 9575, 10112, + 9053, 9575, 10114, + 9053, 9575, 10116, + 9053, 9575, 10118, + 9053, 9575, 10120, + 9053, 9575, 10122, + 9053, 9575, 10124, + 9053, 9575, 10126, + 9053, 9575, 10128, + 9053, 9575, 10130, + 9053, 9575, 10818, + 9053, 9575, 10820, + 9053, 9575, 10822, + 9053, 9575, 10824, + 9053, 9575, 10826, + 9053, 9575, 10828, + 9053, 9575, 10830, + 9053, 9575, 10832, + 9053, 9575, 10834, + 9053, 9575, 10836, + 9053, 9575, 10838, + 9053, 9575, 10840, + 9053, 9575, 10842, + 9053, 9575, 10844, + 9053, 9575, 10846, + 9053, 9575, 10848, + 9053, 9575, 10850, + 9053, 9575, 10852, + 9053, 9575, 10854, + 9053, 9575, 10856, + 9053, 9575, 10858, + 9053, 9575, 10860, + 9053, 9575, 10862, + 9053, 9575, 10864, + 9053, 9575, 10866, + 9053, 9575, 10868, + 9053, 9575, 10870, + 9053, 9575, 10872, + 9053, 9575, 10874, + 9053, 9575, 10876, + 9053, 9575, 10878, + 9053, 9575, 10880, + 9053, 9575, 10882, + 9053, 9575, 10884, + 9053, 9575, 10886, + 9053, 9575, 10888, + 9053, 9575, 10890, + 9053, 9575, 10892, + 9053, 9575, 10894, + 9053, 9575, 10896, + 9053, 9575, 10898, + 9053, 9575, 10900, + 9053, 9575, 10902, + 9053, 9575, 10904, + 9053, 9575, 10906, + 9053, 9575, 10908, + 9053, 9575, 10910, + 9053, 9575, 10912, + 9053, 9575, 10914, + 9053, 9575, 10916, + 9053, 9575, 10918, + 9053, 9575, 10920, + 9053, 9575, 10922, + 9053, 9575, 10924, + 9053, 9575, 10926, + 9053, 9575, 10928, + 9053, 9575, 10930, + 9053, 9575, 10932, + 9053, 9575, 10934, + 9053, 9575, 10936, + 9053, 9575, 10938, + 9053, 9575, 10940, + 9053, 9575, 10942, + 9053, 9575, 10944, + 9053, 9575, 10946, + 9053, 9575, 10948, + 9053, 9575, 10950, + 9053, 9575, 10952, + 9053, 9575, 10954, + 9053, 9575, 10956, + 9053, 9575, 11490, + 9053, 9575, 11492, + 9053, 9575, 11494, + 9053, 9575, 11496, + 9053, 9575, 11498, + 9053, 9575, 11500, + 9053, 9575, 11502, + 9053, 9575, 11504, + 9053, 9575, 11506, + 9053, 9575, 11508, + 9053, 9575, 11510, + 9053, 9575, 11512, + 9053, 9575, 11514, + 9053, 9575, 11516, + 9053, 9575, 11518, + 9053, 9575, 11520, + 9053, 9575, 11522, + 9053, 9575, 11524, + 9053, 9575, 11526, + 9053, 9575, 11528, + 9053, 9575, 11530, + 9053, 9575, 11532, + 9053, 9575, 11534, + 9053, 9575, 11536, + 9053, 9575, 11538, + 9053, 9575, 11540, + 9053, 9575, 11542, + 9053, 9575, 11544, + 9053, 9575, 11546, + 9053, 9575, 11548, + 9053, 9575, 11550, + 9053, 9575, 11552, + 9053, 9575, 11554, + 9053, 9575, 11556, + 9053, 9575, 11558, + 9053, 9575, 11560, + 9053, 9575, 11562, + 9053, 9575, 11564, + 9053, 9575, 11566, + 9053, 9575, 11568, + 9053, 9575, 11570, + 9053, 9575, 11572, + 9053, 9575, 11574, + 9053, 9575, 11576, + 9053, 9575, 11578, + 9053, 9575, 11580, + 9053, 9575, 11582, + 9053, 9575, 11584, + 9053, 9575, 11586, + 9053, 9575, 11588, + 9053, 9575, 11590, + 9053, 9575, 11592, + 9053, 9575, 11594, + 9053, 9575, 11596, + 9053, 9575, 11598, + 9053, 9575, 11600, + 9053, 9575, 11950, + 9053, 9575, 11952, + 9053, 9575, 11954, + 9053, 9575, 11956, + 9053, 9575, 11958, + 9053, 9575, 11960, + 9053, 9575, 11962, + 9053, 9575, 11964, + 9053, 9575, 11966, + 9053, 9575, 11968, + 9053, 9575, 11970, + 9053, 9575, 11972, + 9053, 9575, 11974, + 9053, 9575, 11976, + 9053, 9575, 11978, + 9053, 9575, 11980, + 9053, 9575, 11982, + 9053, 9575, 11984, + 9053, 9575, 11986, + 9053, 9575, 11988, + 9053, 9575, 11990, + 9053, 9575, 11992, + 9053, 9575, 11994, + 9053, 9575, 11996, + 9053, 9575, 11998, + 9053, 9575, 12000, + 9053, 9575, 12002, + 9053, 9575, 12004, + 9053, 9575, 12444, + 9053, 9575, 12446, + 9053, 9575, 12448, + 9053, 9575, 12450, + 9053, 9575, 12452, + 9053, 9575, 12454, + 9053, 9575, 12456, + 9053, 9575, 12458, + 9053, 9575, 12926, + 9069, 5758, + 9072, + 9095, 1045, 10374, + 9095, 3992, + 9095, 5385, 8037, 6723, 9601, 5830, + 9095, 5444, + 9095, 5551, 10374, + 9095, 6689, 2170, + 9095, 6689, 2540, + 9095, 6689, 2778, + 9095, 6689, 4200, + 9095, 6689, 4214, + 9095, 6689, 5190, + 9095, 6689, 6260, + 9095, 6689, 6722, + 9095, 6689, 7508, + 9095, 6689, 7694, + 9095, 6909, 7821, 11765, 6434, + 9095, 7089, 7593, 8405, 0, + 9095, 7089, 7593, 8405, 2, + 9095, 7089, 7593, 8405, 4, + 9095, 7089, 7593, 8405, 6, + 9095, 7089, 7593, 8405, 8, + 9095, 7089, 7593, 8405, 10, + 9095, 7089, 7593, 8405, 12, + 9095, 7089, 7593, 8405, 14, + 9095, 7089, 7593, 8405, 16, + 9095, 7089, 7593, 8405, 18, + 9095, 7089, 7593, 8405, 20, + 9095, 7089, 7593, 8405, 22, + 9095, 7089, 7593, 8405, 24, + 9095, 7089, 7593, 8405, 26, + 9095, 7089, 7593, 8405, 28, + 9095, 7089, 7593, 8405, 30, + 9095, 7089, 7593, 8405, 32, + 9095, 7089, 7593, 8405, 34, + 9095, 7089, 7593, 8405, 36, + 9095, 7089, 7593, 8405, 38, + 9095, 7089, 7593, 8405, 40, + 9095, 7089, 7593, 8405, 42, + 9095, 7089, 7593, 8405, 44, + 9095, 7089, 7593, 8405, 46, + 9095, 7089, 7593, 8405, 48, + 9095, 7089, 7593, 8405, 50, + 9095, 7089, 9063, 8405, 0, + 9095, 7089, 9063, 8405, 2, + 9095, 7089, 9063, 8405, 4, + 9095, 7089, 9063, 8405, 6, + 9095, 7089, 9063, 8405, 8, + 9095, 7089, 9063, 8405, 10, + 9095, 7089, 9063, 8405, 12, + 9095, 7089, 9063, 8405, 14, + 9095, 7089, 9063, 8405, 16, + 9095, 7089, 9063, 8405, 18, + 9095, 7089, 9063, 8405, 20, + 9095, 7089, 9063, 8405, 22, + 9095, 7089, 9063, 8405, 24, + 9095, 7089, 9063, 8405, 26, + 9095, 7089, 9063, 8405, 28, + 9095, 7089, 9063, 8405, 30, + 9095, 7089, 9063, 8405, 32, + 9095, 7089, 9063, 8405, 34, + 9095, 7089, 9063, 8405, 36, + 9095, 7089, 9063, 8405, 38, + 9095, 7089, 9063, 8405, 40, + 9095, 7089, 9063, 8405, 42, + 9095, 7089, 9063, 8405, 44, + 9095, 7089, 9063, 8405, 46, + 9095, 7089, 9063, 8405, 48, + 9095, 7089, 9063, 8405, 50, + 9095, 7172, + 9095, 7710, + 9095, 7821, 5830, + 9095, 7821, 8022, + 9095, 8022, + 9095, 8166, + 9095, 8287, 5770, + 9095, 8287, 5771, 0, + 9095, 8287, 6594, + 9095, 8287, 6595, 0, + 9095, 8287, 6912, + 9095, 8287, 6913, 0, + 9095, 8287, 6982, + 9095, 8287, 6983, 0, + 9095, 8287, 6983, 40, + 9095, 8287, 7166, + 9095, 8287, 7167, 0, + 9095, 8287, 7244, + 9095, 8287, 7245, 0, + 9095, 8287, 7372, + 9095, 8287, 7373, 0, + 9095, 8287, 7440, + 9095, 8287, 7441, 0, + 9095, 8287, 8362, + 9095, 8287, 8363, 0, + 9095, 8287, 8828, + 9095, 8287, 8829, 0, + 9095, 8287, 9086, + 9095, 8287, 9087, 0, + 9095, 8287, 9400, + 9095, 8287, 9401, 0, + 9095, 8287, 9588, + 9095, 8287, 9589, 0, + 9095, 8287, 9780, + 9095, 8287, 9781, 0, + 9095, 8371, 10759, 7014, + 9095, 8371, 10759, 8040, + 9095, 8525, 2670, + 9095, 8525, 6784, + 9095, 8525, 6804, + 9095, 8525, 6805, 2170, + 9095, 8525, 6805, 2540, + 9095, 8525, 6805, 2778, + 9095, 8525, 6805, 4200, + 9095, 8525, 6805, 4214, + 9095, 8525, 6805, 5190, + 9095, 8525, 6805, 6722, + 9095, 8525, 6805, 7508, + 9095, 8525, 6805, 7694, + 9095, 8525, 8162, + 9095, 8525, 8820, + 9095, 8525, 8821, 2170, + 9095, 8525, 8821, 2540, + 9095, 8525, 8821, 2778, + 9095, 8525, 8821, 4200, + 9095, 8525, 8821, 4214, + 9095, 8525, 8821, 5190, + 9095, 8525, 8821, 6722, + 9095, 8525, 8821, 7508, + 9095, 8525, 8821, 7694, + 9095, 8525, 8874, + 9095, 8525, 8876, + 9095, 8525, 8877, 2170, + 9095, 8525, 8877, 2540, + 9095, 8525, 8877, 2778, + 9095, 8525, 8877, 4200, + 9095, 8525, 8877, 4214, + 9095, 8525, 8877, 5190, + 9095, 8525, 8877, 6722, + 9095, 8525, 8877, 7508, + 9095, 8525, 8877, 7694, + 9095, 8525, 9286, + 9095, 8525, 9700, + 9095, 8525, 10150, + 9095, 8525, 10200, + 9095, 8525, 10360, + 9095, 8525, 10622, + 9095, 8525, 11232, + 9095, 8609, 4926, + 9095, 9633, 9718, + 9095, 9899, 10374, + 9095, 10017, 5758, + 9095, 10017, 7580, + 9095, 10283, 0, + 9095, 10283, 8, + 9095, 10283, 16, + 9095, 10283, 28, + 9095, 10283, 40, + 9095, 10283, 236, + 9095, 10283, 238, + 9095, 10283, 242, + 9095, 10283, 246, + 9095, 10283, 250, + 9095, 10283, 306, + 9095, 10283, 310, + 9095, 10283, 314, + 9095, 10283, 322, + 9095, 10283, 326, + 9095, 10283, 364, + 9095, 10283, 368, + 9095, 10283, 374, + 9095, 10283, 380, + 9095, 10283, 384, + 9095, 10283, 392, + 9095, 10283, 396, + 9095, 10283, 404, + 9095, 10283, 412, + 9095, 10283, 416, + 9095, 10283, 510, + 9095, 10283, 512, + 9095, 10283, 514, + 9095, 10283, 516, + 9095, 10283, 520, + 9095, 10283, 524, + 9095, 10283, 526, + 9095, 10283, 532, + 9095, 10283, 536, + 9095, 10283, 546, + 9095, 10283, 556, + 9095, 10283, 560, + 9095, 10283, 564, + 9095, 10283, 568, + 9095, 10283, 576, + 9095, 10283, 622, + 9095, 10283, 626, + 9095, 10283, 630, + 9095, 10283, 632, + 9095, 10283, 652, + 9095, 10283, 660, + 9095, 10283, 664, + 9095, 10410, + 9095, 10643, 4116, + 9095, 10677, 760, + 9095, 11043, 1808, + 9095, 11043, 2170, + 9095, 11043, 2540, + 9095, 11043, 2586, + 9095, 11043, 2670, + 9095, 11043, 2778, + 9095, 11043, 3956, + 9095, 11043, 4194, + 9095, 11043, 4200, + 9095, 11043, 4214, + 9095, 11043, 4396, + 9095, 11043, 4422, + 9095, 11043, 4620, + 9095, 11043, 4848, + 9095, 11043, 4922, + 9095, 11043, 5012, + 9095, 11043, 5046, + 9095, 11043, 5190, + 9095, 11043, 5540, + 9095, 11043, 6122, + 9095, 11043, 6716, + 9095, 11043, 6722, + 9095, 11043, 7072, + 9095, 11043, 7146, + 9095, 11043, 7246, + 9095, 11043, 7392, + 9095, 11043, 7442, + 9095, 11043, 7508, + 9095, 11043, 7640, + 9095, 11043, 7646, + 9095, 11043, 7694, + 9095, 11043, 7812, + 9095, 11043, 8036, + 9095, 11043, 8196, + 9095, 11043, 8682, + 9095, 11043, 9122, + 9095, 11043, 9714, + 9095, 11043, 9724, + 9095, 11043, 9862, + 9095, 11043, 10328, + 9095, 11043, 10478, + 9095, 11043, 10484, + 9095, 11043, 10576, + 9095, 11043, 10726, + 9095, 11043, 10980, + 9095, 11043, 10992, + 9095, 11043, 11266, + 9095, 11043, 11612, + 9095, 11043, 13050, + 9095, 11098, + 9095, 11649, 761, 6121, 7272, + 9095, 12472, + 9095, 12990, + 9095, 13061, 5759, 6121, 11449, 7908, + 9095, 13411, 10017, 5758, + 9109, 7666, + 9115, 10260, + 9127, 8770, + 9137, 10585, 0, + 9137, 10585, 8, + 9137, 10585, 16, + 9137, 10585, 28, + 9137, 10585, 40, + 9137, 10585, 292, + 9137, 10585, 298, + 9137, 10585, 306, + 9137, 10585, 310, + 9137, 10585, 314, + 9137, 10585, 322, + 9137, 10585, 326, + 9137, 10585, 332, + 9137, 10585, 336, + 9137, 10585, 340, + 9137, 10585, 350, + 9137, 10585, 354, + 9137, 10585, 364, + 9137, 10585, 368, + 9137, 10585, 374, + 9137, 10585, 380, + 9137, 10585, 384, + 9137, 10585, 392, + 9137, 10585, 396, + 9137, 10585, 404, + 9137, 10585, 412, + 9137, 10585, 416, + 9137, 10585, 462, + 9137, 10585, 468, + 9137, 10585, 476, + 9137, 10585, 480, + 9137, 10585, 486, + 9137, 10585, 510, + 9137, 10585, 512, + 9137, 10585, 514, + 9137, 10585, 516, + 9137, 10585, 520, + 9137, 10585, 524, + 9137, 10585, 526, + 9137, 10585, 532, + 9137, 10585, 536, + 9137, 10585, 546, + 9137, 10585, 556, + 9137, 10585, 560, + 9137, 10585, 564, + 9137, 10585, 568, + 9137, 10585, 576, + 9137, 10585, 622, + 9137, 10585, 626, + 9137, 10585, 630, + 9137, 10585, 632, + 9137, 10585, 638, + 9137, 10585, 640, + 9137, 10585, 670, + 9137, 10585, 678, + 9151, 11229, 1611, 8774, + 9155, 7593, 8405, 14, + 9155, 7593, 8405, 98, + 9155, 7593, 8405, 164, + 9155, 7593, 8405, 172, + 9155, 7593, 8405, 174, + 9155, 7593, 8405, 176, + 9155, 7593, 8405, 182, + 9155, 7593, 8405, 184, + 9155, 7593, 8405, 192, + 9155, 7593, 8405, 432, + 9155, 7593, 8405, 454, + 9155, 7593, 8405, 634, + 9155, 7593, 8405, 778, + 9155, 7593, 8405, 984, + 9155, 7593, 8405, 1110, + 9155, 7593, 8405, 1124, + 9155, 7593, 8405, 1130, + 9155, 7593, 8405, 1226, + 9155, 7593, 8405, 1506, + 9155, 7593, 8405, 1596, + 9155, 7593, 8405, 2204, + 9155, 7593, 8405, 2666, + 9155, 7593, 8405, 2856, + 9155, 7593, 8405, 3050, + 9155, 7593, 8405, 3138, + 9155, 7593, 8405, 3890, + 9155, 7593, 8405, 4895, 0, + 9155, 7593, 8405, 4895, 8, + 9155, 7593, 8405, 4895, 16, + 9155, 7593, 8405, 4895, 28, + 9155, 7593, 8405, 4895, 70, + 9155, 7593, 8405, 4895, 440, + 9155, 7593, 8405, 5914, + 9155, 7593, 8405, 6274, + 9155, 7593, 8405, 7551, 0, + 9155, 7593, 8405, 7551, 8, + 9155, 7593, 8405, 7551, 16, + 9155, 7593, 8405, 7551, 28, + 9155, 7593, 8405, 7551, 70, + 9155, 7593, 8405, 7551, 440, + 9155, 9063, 8405, 14, + 9155, 9063, 8405, 98, + 9155, 9063, 8405, 164, + 9155, 9063, 8405, 172, + 9155, 9063, 8405, 174, + 9155, 9063, 8405, 176, + 9155, 9063, 8405, 182, + 9155, 9063, 8405, 184, + 9155, 9063, 8405, 192, + 9155, 9063, 8405, 432, + 9155, 9063, 8405, 454, + 9155, 9063, 8405, 634, + 9155, 9063, 8405, 778, + 9155, 9063, 8405, 984, + 9155, 9063, 8405, 1110, + 9155, 9063, 8405, 1124, + 9155, 9063, 8405, 1130, + 9155, 9063, 8405, 1226, + 9155, 9063, 8405, 1506, + 9155, 9063, 8405, 1596, + 9155, 9063, 8405, 2204, + 9155, 9063, 8405, 2666, + 9155, 9063, 8405, 2856, + 9155, 9063, 8405, 3050, + 9155, 9063, 8405, 3138, + 9155, 9063, 8405, 3890, + 9155, 9063, 8405, 4895, 0, + 9155, 9063, 8405, 4895, 8, + 9155, 9063, 8405, 4895, 16, + 9155, 9063, 8405, 4895, 28, + 9155, 9063, 8405, 4895, 70, + 9155, 9063, 8405, 4895, 440, + 9155, 9063, 8405, 5914, + 9155, 9063, 8405, 6274, + 9155, 9063, 8405, 7551, 0, + 9155, 9063, 8405, 7551, 8, + 9155, 9063, 8405, 7551, 16, + 9155, 9063, 8405, 7551, 28, + 9155, 9063, 8405, 7551, 70, + 9155, 9063, 8405, 7551, 440, + 9159, 6121, 2725, 4389, 6504, + 9159, 6121, 4849, 4389, 6504, + 9159, 6121, 7443, 4389, 6504, + 9159, 6121, 8005, 4389, 6504, + 9159, 10374, + 9171, 9095, 11767, 6689, 2170, + 9171, 9095, 11767, 6689, 2540, + 9171, 9095, 11767, 6689, 2778, + 9171, 9095, 11767, 6689, 4200, + 9171, 9095, 11767, 6689, 4214, + 9171, 9095, 11767, 6689, 5190, + 9171, 9095, 11767, 6689, 6722, + 9171, 9095, 11767, 6689, 7508, + 9171, 9095, 11767, 6689, 7694, + 9171, 9095, 11767, 8525, 2670, + 9171, 10357, 9095, 6689, 2170, + 9171, 10357, 9095, 6689, 2540, + 9171, 10357, 9095, 6689, 2778, + 9171, 10357, 9095, 6689, 4200, + 9171, 10357, 9095, 6689, 4214, + 9171, 10357, 9095, 6689, 5190, + 9171, 10357, 9095, 6689, 6722, + 9171, 10357, 9095, 6689, 7508, + 9171, 10357, 9095, 6689, 7694, + 9171, 10357, 9095, 8525, 2670, + 9171, 10357, 9095, 11767, 6689, 2170, + 9171, 10357, 9095, 11767, 6689, 2540, + 9171, 10357, 9095, 11767, 6689, 2778, + 9171, 10357, 9095, 11767, 6689, 4200, + 9171, 10357, 9095, 11767, 6689, 4214, + 9171, 10357, 9095, 11767, 6689, 5190, + 9171, 10357, 9095, 11767, 6689, 6722, + 9171, 10357, 9095, 11767, 6689, 7508, + 9171, 10357, 9095, 11767, 6689, 7694, + 9171, 10357, 9095, 11767, 8525, 2670, + 9180, + 9183, 8774, + 9243, 4923, 5758, + 9243, 8197, 5758, + 9245, 5758, + 9263, 428, + 9263, 429, 6121, 1045, 6376, + 9263, 429, 6121, 2779, 11649, 9744, + 9263, 429, 6121, 4895, 11649, 8758, + 9263, 429, 6121, 9546, + 9263, 429, 6121, 10666, + 9263, 429, 6121, 10677, 761, 91, 1109, 429, 11649, 8758, + 9263, 429, 9537, 9810, + 9263, 429, 9537, 10958, + 9279, 10001, 9967, 7271, 4153, 6434, + 9279, 10001, 9967, 8649, 10000, + 9288, + 9292, + 9297, 2830, + 9317, 5758, + 9325, 5759, 10400, + 9325, 7803, 5759, 16, + 9325, 7803, 5759, 40, + 9325, 8405, 0, + 9325, 8405, 16, + 9325, 8405, 40, + 9325, 8405, 100, + 9325, 8405, 138, + 9325, 8405, 216, + 9325, 8405, 236, + 9325, 8405, 306, + 9325, 8405, 332, + 9325, 8405, 364, + 9325, 8405, 392, + 9325, 8405, 462, + 9325, 8405, 510, + 9325, 8405, 524, + 9325, 8405, 556, + 9325, 8405, 622, + 9325, 8405, 652, + 9325, 8405, 2030, + 9343, 5758, + 9361, 7931, 4213, 9680, + 9361, 11345, 10582, + 9367, 7821, 8056, + 9367, 8022, + 9380, + 9385, 73, 8399, 4926, + 9385, 5759, 7282, + 9385, 5759, 8916, + 9385, 5759, 9824, + 9385, 5759, 9870, + 9385, 5759, 9904, + 9385, 5759, 12066, + 9385, 5759, 12384, + 9385, 6689, 2170, + 9385, 6689, 2540, + 9385, 6689, 2778, + 9385, 6689, 4200, + 9385, 6689, 4214, + 9385, 6689, 5190, + 9385, 6689, 6260, + 9385, 6689, 6722, + 9385, 6689, 7508, + 9385, 6689, 7694, + 9385, 7803, 5759, 8, + 9385, 7803, 5759, 16, + 9385, 7803, 5759, 28, + 9385, 7803, 5759, 40, + 9385, 7803, 5759, 58, + 9385, 7803, 5759, 72, + 9385, 7803, 5759, 92, + 9385, 7803, 5759, 162, + 9385, 7803, 5759, 266, + 9385, 7803, 5759, 440, + 9385, 7803, 5759, 606, + 9385, 7803, 5759, 9827, 22, + 9385, 7803, 5759, 9827, 34, + 9385, 7803, 5759, 9827, 344, + 9385, 7803, 5759, 9827, 518, + 9385, 8399, 4926, + 9385, 8405, 0, + 9385, 8405, 8, + 9385, 8405, 16, + 9385, 8405, 28, + 9385, 8405, 40, + 9385, 8405, 58, + 9385, 8405, 72, + 9385, 8405, 92, + 9385, 8405, 100, + 9385, 8405, 116, + 9385, 8405, 138, + 9385, 8405, 162, + 9385, 8405, 196, + 9385, 8405, 216, + 9385, 8405, 236, + 9385, 8405, 266, + 9385, 8405, 292, + 9385, 8405, 306, + 9385, 8405, 332, + 9385, 8405, 364, + 9385, 8405, 392, + 9385, 8405, 440, + 9385, 8405, 462, + 9385, 8405, 510, + 9385, 8405, 524, + 9385, 8405, 556, + 9385, 8405, 606, + 9385, 8405, 610, + 9385, 8405, 652, + 9385, 8405, 792, + 9385, 8405, 884, + 9385, 8405, 974, + 9385, 8405, 996, + 9385, 8405, 1260, + 9385, 8405, 1512, + 9385, 8405, 1612, + 9385, 8405, 1796, + 9385, 8405, 2030, + 9385, 8405, 2076, + 9385, 8405, 2126, + 9385, 8405, 2212, + 9385, 8405, 2438, + 9385, 8405, 2516, + 9385, 8405, 2566, + 9385, 8405, 2678, + 9385, 8405, 2746, + 9385, 8405, 4016, + 9385, 8405, 5994, + 9385, 8405, 9827, 22, + 9385, 8405, 9827, 34, + 9385, 8405, 9827, 344, + 9385, 8405, 9827, 518, + 9431, 11103, 5758, + 9437, 444, + 9437, 445, 6121, 1045, 6376, + 9437, 445, 6121, 8153, 9546, + 9437, 445, 6121, 8153, 10666, + 9437, 445, 6121, 8473, 5832, + 9437, 445, 6121, 11649, 3992, + 9437, 445, 12105, 9437, 720, + 9437, 720, + 9437, 721, 6121, 1045, 6376, + 9437, 721, 6121, 8153, 9546, + 9437, 721, 6121, 8153, 10666, + 9437, 721, 6121, 8473, 5832, + 9437, 721, 6121, 10666, + 9437, 721, 6121, 11649, 3992, + 9438, + 9439, 9177, 115, 11649, 5606, + 9443, 5941, 2171, 429, 9020, + 9443, 5941, 2171, 429, 9096, + 9443, 5941, 2171, 429, 11446, + 9443, 5941, 2401, 8154, + 9443, 5941, 2541, 429, 9020, + 9443, 5941, 2541, 429, 9096, + 9443, 5941, 2541, 429, 11446, + 9443, 5941, 2779, 429, 9020, + 9443, 5941, 2779, 429, 9096, + 9443, 5941, 2779, 429, 11446, + 9443, 5941, 3696, + 9443, 5941, 4153, 6116, + 9443, 5941, 4201, 429, 9020, + 9443, 5941, 4201, 429, 9096, + 9443, 5941, 4201, 429, 11446, + 9443, 5941, 4215, 429, 9020, + 9443, 5941, 4215, 429, 9096, + 9443, 5941, 4215, 429, 11446, + 9443, 5941, 5191, 429, 9020, + 9443, 5941, 5191, 429, 9096, + 9443, 5941, 5191, 429, 11446, + 9443, 5941, 5442, + 9443, 5941, 6113, 6116, + 9443, 5941, 6723, 429, 9020, + 9443, 5941, 6723, 429, 9096, + 9443, 5941, 6723, 429, 11446, + 9443, 5941, 6881, 8154, + 9443, 5941, 7010, + 9443, 5941, 7271, 6116, + 9443, 5941, 7509, 429, 9020, + 9443, 5941, 7509, 429, 9096, + 9443, 5941, 7509, 429, 11446, + 9443, 5941, 7607, 6116, + 9443, 5941, 7695, 429, 9020, + 9443, 5941, 7695, 429, 9096, + 9443, 5941, 7695, 429, 11446, + 9443, 5941, 7821, 8154, + 9443, 5941, 7960, + 9443, 5941, 7974, + 9443, 5941, 8546, + 9443, 5941, 8738, + 9443, 5941, 8766, + 9443, 5941, 8934, + 9443, 5941, 12912, + 9453, 6622, + 9472, + 9475, 11649, 10154, + 9483, 8775, 5, 3946, + 9483, 8775, 11, 3946, + 9483, 8775, 11, 3947, 8553, 3254, + 9483, 8775, 11, 3947, 8553, 6468, + 9483, 8775, 13, 3946, + 9483, 8775, 13, 3947, 8553, 3254, + 9483, 8775, 13, 3947, 8553, 6468, + 9483, 8775, 47, 10366, + 9483, 8775, 50, + 9483, 8775, 139, 3846, + 9483, 8775, 570, + 9483, 8775, 933, 5942, + 9483, 8775, 961, 7500, + 9483, 8775, 1109, 429, 8750, + 9483, 8775, 1109, 2690, + 9483, 8775, 1109, 3760, + 9483, 8775, 1109, 5776, + 9483, 8775, 1109, 8584, + 9483, 8775, 2171, 9345, 13031, 5244, + 9483, 8775, 2171, 9345, 13031, 5540, + 9483, 8775, 2211, 11838, + 9483, 8775, 3950, + 9483, 8775, 3984, + 9483, 8775, 3985, 718, + 9483, 8775, 4121, 8058, + 9483, 8775, 4121, 8060, + 9483, 8775, 4205, 600, + 9483, 8775, 4205, 4116, + 9483, 8775, 4227, 6504, + 9483, 8775, 4227, 7820, + 9483, 8775, 4389, 5244, + 9483, 8775, 4389, 5540, + 9483, 8775, 4389, 7351, 4926, + 9483, 8775, 4849, 8641, 5758, + 9483, 8775, 5013, 10367, 6504, + 9483, 8775, 5013, 10367, 7820, + 9483, 8775, 5281, 10366, + 9483, 8775, 5445, 10366, + 9483, 8775, 6020, + 9483, 8775, 6021, 600, + 9483, 8775, 6021, 7580, + 9483, 8775, 6093, 10366, + 9483, 8775, 6121, 12018, + 9483, 8775, 6485, 2690, + 9483, 8775, 6485, 3760, + 9483, 8775, 6485, 5776, + 9483, 8775, 6485, 8584, + 9483, 8775, 6514, + 9483, 8775, 6516, + 9483, 8775, 6620, + 9483, 8775, 6789, 9022, + 9483, 8775, 6802, + 9483, 8775, 6869, 5245, 413, 7580, + 9483, 8775, 6869, 5245, 7580, + 9483, 8775, 7112, + 9483, 8775, 7113, 10423, 5540, + 9483, 8775, 7113, 11659, 5540, + 9483, 8775, 7150, + 9483, 8775, 7191, 5540, + 9483, 8775, 7351, 601, 4926, + 9483, 8775, 7351, 4926, + 9483, 8775, 7368, + 9483, 8775, 7443, 8641, 5758, + 9483, 8775, 7500, + 9483, 8775, 7519, 600, + 9483, 8775, 7519, 4116, + 9483, 8775, 7551, 9022, + 9483, 8775, 7796, + 9483, 8775, 7823, 5244, + 9483, 8775, 7823, 5540, + 9483, 8775, 8011, 4926, + 9483, 8775, 8012, + 9483, 8775, 8013, 5540, + 9483, 8775, 8057, 47, 10366, + 9483, 8775, 8062, + 9483, 8775, 8073, 5942, + 9483, 8775, 8097, 9022, + 9483, 8775, 8101, 7580, + 9483, 8775, 8153, 4204, + 9483, 8775, 8153, 7518, + 9483, 8775, 8153, 9022, + 9483, 8775, 8159, 5244, + 9483, 8775, 8159, 5540, + 9483, 8775, 8458, + 9483, 8775, 8478, + 9483, 8775, 8479, 5540, + 9483, 8775, 8479, 6504, + 9483, 8775, 8553, 3254, + 9483, 8775, 8553, 6468, + 9483, 8775, 8641, 4112, + 9483, 8775, 8717, 9022, + 9483, 8775, 8745, 2, + 9483, 8775, 8745, 10367, 6504, + 9483, 8775, 8745, 10367, 7820, + 9483, 8775, 8760, + 9483, 8775, 8805, 11167, 925, 11739, 10422, + 9483, 8775, 8805, 11167, 925, 11739, 10423, 12438, + 9483, 8775, 8805, 11167, 925, 11739, 11658, + 9483, 8775, 8805, 12051, 925, 11739, 10422, + 9483, 8775, 8805, 12051, 925, 11739, 11658, + 9483, 8775, 8805, 12051, 925, 11739, 11659, 12438, + 9483, 8775, 8805, 12051, 925, 11739, 11659, 12440, + 9483, 8775, 8805, 12051, 925, 11739, 11659, 12442, + 9483, 8775, 9050, + 9483, 8775, 9060, + 9483, 8775, 9105, 10367, 6504, + 9483, 8775, 9105, 10367, 7820, + 9483, 8775, 9284, + 9483, 8775, 9285, 6490, + 9483, 8775, 9491, 600, + 9483, 8775, 9491, 4116, + 9483, 8775, 9598, + 9483, 8775, 9615, 5244, + 9483, 8775, 9615, 5540, + 9483, 8775, 9615, 5965, 4204, + 9483, 8775, 9615, 5965, 7518, + 9483, 8775, 9633, 6789, 9022, + 9483, 8775, 9950, + 9483, 8775, 10189, 11366, + 9483, 8775, 10189, 11368, + 9483, 8775, 10189, 11370, + 9483, 8775, 10267, 6020, + 9483, 8775, 10349, 9467, 5540, + 9483, 8775, 10367, 6504, + 9483, 8775, 10373, 7626, + 9483, 8775, 10381, 10554, + 9483, 8775, 10381, 10556, + 9483, 8775, 10381, 10558, + 9483, 8775, 10381, 10560, + 9483, 8775, 10381, 10562, + 9483, 8775, 10381, 10564, + 9483, 8775, 10381, 10566, + 9483, 8775, 10381, 10568, + 9483, 8775, 10381, 10570, + 9483, 8775, 10381, 11252, + 9483, 8775, 10381, 11254, + 9483, 8775, 10483, 10182, + 9483, 8775, 10483, 10184, + 9483, 8775, 10483, 10186, + 9483, 8775, 10527, 7626, + 9483, 8775, 10634, + 9483, 8775, 10635, 11212, + 9483, 8775, 10643, 10367, 601, 6504, + 9483, 8775, 10643, 10367, 601, 7443, 6504, + 9483, 8775, 10643, 10367, 601, 7443, 7820, + 9483, 8775, 10643, 10367, 601, 7820, + 9483, 8775, 10643, 10367, 4117, 6504, + 9483, 8775, 10643, 10367, 4117, 7820, + 9483, 8775, 10643, 10367, 4849, 6504, + 9483, 8775, 10643, 10367, 4849, 7820, + 9483, 8775, 10643, 10367, 7443, 6504, + 9483, 8775, 10643, 10367, 7443, 7820, + 9483, 8775, 10659, 7626, + 9483, 8775, 10767, 601, 824, + 9483, 8775, 10767, 2418, + 9483, 8775, 10767, 3772, + 9483, 8775, 10767, 4104, + 9483, 8775, 10767, 4117, 824, + 9483, 8775, 10767, 4206, + 9483, 8775, 10767, 5779, 11174, + 9483, 8775, 10767, 5832, + 9483, 8775, 10767, 7116, + 9483, 8775, 10767, 7596, + 9483, 8775, 10767, 7908, + 9483, 8775, 10767, 8153, 8844, + 9483, 8775, 10767, 8210, + 9483, 8775, 10767, 8212, + 9483, 8775, 10767, 8214, + 9483, 8775, 10767, 8216, + 9483, 8775, 10767, 8218, + 9483, 8775, 10767, 8806, + 9483, 8775, 10767, 8849, 8844, + 9483, 8775, 10767, 9458, + 9483, 8775, 10767, 10236, + 9483, 8775, 10767, 10534, + 9483, 8775, 10767, 11366, + 9483, 8775, 10767, 11368, + 9483, 8775, 10767, 11370, + 9483, 8775, 10767, 12407, 1044, + 9483, 8775, 10767, 12871, 5832, + 9483, 8775, 10767, 13016, + 9483, 8775, 10767, 13184, + 9483, 8775, 10767, 13340, + 9483, 8775, 10784, + 9483, 8775, 10995, 7626, + 9483, 8775, 11005, 7626, + 9483, 8775, 11019, 600, + 9483, 8775, 11019, 4116, + 9483, 8775, 11027, 5, 3946, + 9483, 8775, 11027, 11, 3946, + 9483, 8775, 11176, + 9483, 8775, 11177, 8220, + 9483, 8775, 11220, + 9483, 8775, 11221, 8220, + 9483, 8775, 11241, 5244, + 9483, 8775, 11241, 5540, + 9483, 8775, 11429, 600, + 9483, 8775, 11429, 4116, + 9483, 8775, 11789, 5540, + 9483, 8775, 11789, 6504, + 9483, 8775, 11789, 7820, + 9483, 8775, 11795, 5540, + 9483, 8775, 11795, 6504, + 9483, 8775, 11795, 7820, + 9483, 8775, 11821, 11006, + 9483, 8775, 11857, 7626, + 9483, 8775, 11928, + 9483, 8775, 12023, 11006, + 9483, 8775, 12028, + 9483, 8775, 12092, + 9483, 8775, 12115, 10366, + 9483, 8775, 12152, + 9483, 8775, 12531, 3254, + 9483, 8775, 12531, 6468, + 9483, 8775, 12867, 5244, + 9483, 8775, 12867, 5540, + 9483, 8775, 13025, 5244, + 9483, 8775, 13025, 5540, + 9483, 8775, 13081, 10367, 4117, 6504, + 9483, 8775, 13081, 10367, 4117, 7820, + 9485, 5671, 6689, 2170, + 9485, 5671, 6689, 2540, + 9485, 5671, 6689, 2778, + 9485, 5671, 6689, 4200, + 9485, 5671, 6689, 4214, + 9485, 5671, 6689, 5190, + 9485, 5671, 6689, 6260, + 9485, 5671, 6689, 6722, + 9485, 5671, 6689, 7508, + 9485, 5671, 6689, 7694, + 9485, 5759, 1045, 6490, + 9485, 5759, 3278, + 9485, 5759, 5671, 8834, + 9485, 5759, 5671, 8836, + 9485, 5759, 5671, 8840, + 9485, 5759, 5671, 8842, + 9485, 5759, 5671, 9125, 8834, + 9485, 5759, 5671, 9125, 8836, + 9485, 5759, 5671, 9125, 10159, 5964, + 9485, 5759, 7465, 9555, 8840, + 9485, 5759, 8425, 9664, + 9485, 5759, 8916, + 9485, 5759, 9664, + 9485, 5759, 9824, + 9485, 5759, 9839, 2273, 7025, 8832, + 9485, 5759, 9839, 2273, 7025, 8834, + 9485, 5759, 9839, 2273, 7025, 8836, + 9485, 5759, 9839, 2273, 7025, 8838, + 9485, 5759, 9839, 2273, 7025, 8840, + 9485, 5759, 9870, + 9485, 5965, 4927, 5657, 7025, 311, 2218, + 9485, 5965, 4927, 5657, 7025, 6902, + 9485, 6689, 2170, + 9485, 6689, 2540, + 9485, 6689, 2778, + 9485, 6689, 4200, + 9485, 6689, 4214, + 9485, 6689, 5190, + 9485, 6689, 6260, + 9485, 6689, 6722, + 9485, 6689, 7508, + 9485, 6689, 7694, + 9485, 7803, 5759, 8, + 9485, 7803, 5759, 9, 6376, + 9485, 7803, 5759, 16, + 9485, 7803, 5759, 40, + 9485, 7803, 5759, 58, + 9485, 7803, 5759, 72, + 9485, 7803, 5759, 266, + 9485, 7803, 5759, 606, + 9485, 7803, 5759, 1937, 28, + 9485, 7803, 5759, 1937, 266, + 9485, 7803, 5759, 4263, 7025, 16, + 9485, 7803, 5759, 5657, 7025, 188, + 9485, 7803, 5759, 5671, 8, + 9485, 7803, 5759, 5671, 9, 6376, + 9485, 7803, 5759, 5671, 58, + 9485, 7803, 5759, 5671, 6789, 48, + 9485, 7803, 5759, 5885, 58, + 9485, 7803, 5759, 7031, 40, + 9485, 7803, 5759, 7031, 162, + 9485, 7803, 5759, 7031, 426, + 9485, 7803, 5759, 9827, 22, + 9485, 7803, 5759, 9827, 34, + 9485, 7803, 5759, 9827, 344, + 9485, 7803, 5759, 9827, 518, + 9485, 7803, 5759, 9839, 2273, 7025, 188, + 9485, 7803, 5759, 9839, 2273, 7025, 590, + 9485, 8405, 0, + 9485, 8405, 8, + 9485, 8405, 16, + 9485, 8405, 28, + 9485, 8405, 40, + 9485, 8405, 92, + 9485, 8405, 100, + 9485, 8405, 116, + 9485, 8405, 138, + 9485, 8405, 216, + 9485, 8405, 236, + 9485, 8405, 266, + 9485, 8405, 292, + 9485, 8405, 306, + 9485, 8405, 332, + 9485, 8405, 364, + 9485, 8405, 392, + 9485, 8405, 462, + 9485, 8405, 510, + 9485, 8405, 524, + 9485, 8405, 556, + 9485, 8405, 606, + 9485, 8405, 622, + 9485, 8405, 652, + 9485, 8405, 792, + 9485, 8405, 884, + 9485, 8405, 974, + 9485, 8405, 996, + 9485, 8405, 1260, + 9485, 8405, 1512, + 9485, 8405, 1612, + 9485, 8405, 1796, + 9485, 8405, 1937, 8, + 9485, 8405, 1937, 766, + 9485, 8405, 1937, 768, + 9485, 8405, 1937, 1512, + 9485, 8405, 1937, 2030, + 9485, 8405, 2030, + 9485, 8405, 2076, + 9485, 8405, 2126, + 9485, 8405, 2212, + 9485, 8405, 2516, + 9485, 8405, 2566, + 9485, 8405, 2678, + 9485, 8405, 2746, + 9485, 8405, 4016, + 9485, 8405, 5236, + 9485, 8405, 5657, 7025, 2516, + 9485, 8405, 5671, 0, + 9485, 8405, 5671, 100, + 9485, 8405, 5671, 116, + 9485, 8405, 5671, 138, + 9485, 8405, 5671, 196, + 9485, 8405, 5671, 216, + 9485, 8405, 5671, 236, + 9485, 8405, 5671, 306, + 9485, 8405, 5671, 392, + 9485, 8405, 5671, 670, + 9485, 8405, 5671, 1612, + 9485, 8405, 5671, 2126, + 9485, 8405, 5671, 2212, + 9485, 8405, 5671, 2678, + 9485, 8405, 5994, + 9485, 8405, 6877, 524, + 9485, 8405, 7465, 9555, 196, + 9485, 8405, 9253, 2273, 7025, 2076, + 9485, 8405, 9253, 2273, 7025, 3102, + 9485, 8405, 9253, 2273, 7025, 4322, + 9485, 8405, 9827, 22, + 9485, 8405, 9827, 34, + 9485, 8405, 9827, 344, + 9485, 8405, 9827, 518, + 9485, 8405, 9839, 2273, 7025, 2266, + 9485, 8405, 9839, 2273, 7025, 2678, + 9485, 8775, 5671, 2170, + 9485, 8775, 5671, 12016, + 9485, 8775, 10218, + 9485, 8775, 10304, + 9485, 8775, 10768, + 9485, 8775, 13040, + 9485, 10775, 5759, 1937, 8461, 332, + 9485, 10775, 5759, 1937, 8461, 364, + 9485, 10775, 5759, 1937, 8461, 392, + 9485, 10775, 5759, 5671, 8461, 622, + 9485, 10775, 5759, 8461, 236, + 9485, 10775, 5759, 8461, 510, + 9485, 10775, 5759, 8461, 622, + 9485, 10775, 5759, 8461, 652, + 9495, 8153, 10677, 761, 8153, 7443, 11378, + 9497, 1, 8763, 429, 2089, 6741, 568, + 9497, 1, 10579, 429, 2089, 6741, 568, + 9497, 11099, 2089, 6741, 568, + 9497, 11099, 2089, 11621, 568, + 9497, 11099, 2089, 12472, + 9497, 12473, 2089, 6741, 568, + 9497, 12473, 2089, 11098, + 9497, 12473, 2089, 11621, 568, + 9497, 12903, 2089, 9855, 6741, 568, + 9498, + 9509, 6689, 8696, + 9511, 7121, 13069, 7821, 11765, 6434, + 9511, 7773, 13069, 7821, 11765, 6434, + 9525, 6409, 9537, 600, + 9525, 6409, 9537, 4116, + 9541, 6689, 2170, + 9541, 6689, 2540, + 9541, 6689, 2778, + 9541, 6689, 4200, + 9541, 6689, 4214, + 9541, 6689, 5190, + 9541, 6689, 6260, + 9541, 6689, 6722, + 9541, 6689, 7508, + 9541, 6689, 7694, + 9541, 8405, 0, + 9541, 8405, 8, + 9541, 8405, 16, + 9541, 8405, 28, + 9541, 8405, 40, + 9541, 8405, 58, + 9541, 8405, 100, + 9541, 8405, 162, + 9541, 8405, 196, + 9541, 8405, 216, + 9541, 8405, 236, + 9541, 8405, 292, + 9541, 8405, 440, + 9541, 8405, 510, + 9541, 8405, 524, + 9541, 8405, 556, + 9541, 8405, 638, + 9541, 8405, 652, + 9541, 8405, 996, + 9541, 8405, 1612, + 9541, 8405, 2918, + 9541, 8405, 3244, + 9541, 8405, 3854, + 9541, 8405, 4050, + 9541, 8405, 4698, + 9541, 8405, 4820, + 9541, 8405, 5000, + 9541, 8405, 5288, + 9541, 8405, 5470, + 9541, 8405, 7540, + 9573, 12432, + 9581, 5758, + 9595, 5758, + 9615, 5244, + 9617, 8775, 8004, + 9633, 7709, 10375, 6377, 11097, 6434, + 9633, 7709, 10375, 6377, 11765, 6434, + 9633, 9718, + 9633, 9719, 6121, 11649, 8758, + 9633, 9719, 10374, + 9633, 9719, 11183, 8762, + 9641, 6909, 6505, 6907, 8022, + 9641, 8225, 6907, 8022, + 9641, 9063, 32, + 9650, + 9660, + 9665, 5758, + 9666, + 9671, 4926, + 9676, + 9683, 8405, 70, + 9683, 8405, 260, + 9683, 8405, 438, + 9683, 8405, 444, + 9683, 8405, 536, + 9683, 8405, 600, + 9683, 8405, 706, + 9683, 8405, 708, + 9683, 8405, 712, + 9683, 8405, 732, + 9683, 8405, 736, + 9683, 8405, 740, + 9683, 8405, 802, + 9683, 8405, 1090, + 9683, 8405, 1092, + 9683, 8405, 1100, + 9683, 8405, 1120, + 9683, 8405, 1150, + 9683, 8405, 1210, + 9683, 8405, 1472, + 9683, 8405, 1474, + 9683, 8405, 2110, + 9683, 8405, 2154, + 9683, 8405, 2164, + 9683, 8405, 2186, + 9683, 8405, 2726, + 9683, 8405, 2884, + 9683, 8405, 2938, + 9683, 8405, 3048, + 9683, 8405, 3060, + 9683, 8405, 3178, + 9683, 8405, 4048, + 9683, 8405, 4548, + 9683, 8405, 4754, + 9683, 8405, 4892, + 9683, 8405, 5004, + 9683, 8405, 5382, + 9683, 8405, 5406, + 9683, 8405, 5560, + 9683, 8405, 5854, + 9683, 8405, 5922, + 9683, 8405, 6124, + 9683, 8405, 6432, + 9683, 8405, 6886, + 9683, 8405, 7012, + 9683, 8405, 7684, + 9683, 8405, 8054, + 9683, 8405, 9466, + 9689, 9610, + 9693, 445, 11098, + 9693, 445, 12472, + 9693, 6377, 11099, 6377, 8167, 5758, + 9693, 6377, 12473, 6377, 8167, 5758, + 9693, 7173, 9692, + 9695, 5759, 10702, + 9695, 5759, 11392, + 9695, 5759, 11418, + 9695, 7803, 5759, 4087, 9406, + 9695, 7803, 5759, 4087, 10272, + 9695, 7803, 5759, 4087, 11150, + 9695, 7803, 5759, 4087, 11406, + 9695, 7803, 5759, 4087, 12024, + 9695, 7803, 5759, 4087, 12468, + 9695, 7803, 5759, 7043, 10272, + 9695, 7803, 5759, 7043, 11150, + 9695, 7803, 5759, 7043, 11406, + 9695, 7803, 5759, 7059, 4056, + 9695, 7803, 5759, 9406, + 9695, 7803, 5759, 9407, 1339, 4087, 11408, + 9695, 7803, 5759, 9407, 1339, 11408, + 9695, 7803, 5759, 9407, 1339, 12024, + 9695, 7803, 5759, 11408, + 9695, 7803, 5759, 12024, + 9695, 7803, 5759, 12468, + 9695, 8405, 3259, 9032, + 9695, 8405, 7962, + 9695, 8405, 8176, + 9695, 8405, 8326, + 9695, 8405, 8558, + 9695, 8405, 8904, + 9695, 8405, 8966, + 9695, 8405, 8978, + 9695, 8405, 8988, + 9695, 8405, 9012, + 9695, 8405, 9141, 9424, + 9695, 8405, 9141, 9492, + 9695, 8405, 9141, 9656, + 9695, 8405, 9256, + 9695, 8405, 9280, + 9695, 8405, 9330, + 9695, 8405, 9352, + 9695, 8405, 9387, 11692, + 9695, 8405, 9464, + 9695, 8405, 9534, + 9695, 8405, 9622, + 9695, 8405, 9655, 9146, + 9695, 8405, 9655, 9302, + 9695, 8405, 9655, 9376, + 9695, 8405, 9655, 9988, + 9695, 8405, 9759, 9656, + 9695, 8405, 9759, 10499, 12090, + 9695, 8405, 9759, 11692, + 9695, 8405, 9812, + 9695, 8405, 9818, + 9695, 8405, 9844, + 9695, 8405, 9856, + 9695, 8405, 10248, + 9695, 8405, 10270, + 9695, 8405, 11044, + 9695, 8405, 11064, + 9695, 8405, 11133, 9424, + 9695, 8405, 11133, 9492, + 9695, 8405, 11133, 9656, + 9695, 8405, 11411, 9032, + 9695, 8405, 11411, 9070, + 9695, 8405, 11411, 9146, + 9695, 8405, 11411, 9302, + 9695, 8405, 11411, 9376, + 9695, 8405, 11411, 9392, + 9695, 8405, 11411, 9576, + 9695, 8405, 11411, 9768, + 9695, 8405, 11411, 9988, + 9695, 8405, 11411, 10652, + 9695, 8405, 12077, 9032, + 9695, 8405, 12077, 9070, + 9695, 8405, 12077, 9146, + 9695, 8405, 12077, 9302, + 9695, 8405, 12077, 9376, + 9695, 8405, 12077, 9392, + 9695, 8405, 12077, 9576, + 9695, 8405, 12077, 9768, + 9695, 8405, 12077, 9988, + 9695, 8405, 12077, 10652, + 9695, 12133, 11670, + 9701, 9601, 9898, + 9705, 6741, 569, 445, 11098, + 9705, 6741, 569, 445, 11099, 6121, 1045, 8318, + 9705, 6741, 569, 445, 12472, + 9705, 6741, 569, 445, 12473, 6121, 1045, 8318, + 9707, 7085, 444, + 9707, 7085, 720, + 9709, 5912, + 9709, 5913, 445, 6741, 568, + 9712, + 9718, + 9719, 6121, 9546, + 9722, + 9733, 1045, 10374, + 9733, 4215, 1045, 12132, + 9733, 5444, + 9733, 7172, + 9733, 7593, 8056, + 9733, 7710, + 9733, 8649, 10001, 7580, + 9733, 8744, + 9733, 9279, 10001, 7580, + 9733, 9898, + 9753, 10260, + 9761, 5759, 8916, + 9761, 7803, 5759, 16, + 9761, 7803, 5759, 40, + 9761, 8405, 0, + 9761, 8405, 16, + 9761, 8405, 40, + 9761, 8405, 100, + 9761, 8405, 138, + 9761, 8405, 216, + 9761, 8405, 236, + 9761, 8405, 306, + 9761, 8405, 332, + 9761, 8405, 364, + 9761, 8405, 392, + 9761, 8405, 462, + 9761, 8405, 524, + 9761, 8405, 556, + 9761, 8405, 622, + 9761, 8405, 652, + 9761, 8405, 2030, + 9783, 12369, 11765, 10716, + 9783, 13049, 11765, 10716, + 9789, 327, 521, 1612, + 9789, 327, 521, 1613, 3831, 1915, 858, + 9789, 4927, 723, 7045, 4376, + 9789, 4927, 723, 7045, 4382, + 9789, 4927, 887, 1904, + 9789, 4927, 1307, 7463, 4376, + 9789, 4927, 1307, 7463, 4382, + 9789, 4927, 2417, 3895, 8743, 5668, + 9789, 4927, 2733, 6374, + 9789, 4927, 3067, 1905, 7745, 5669, 364, + 9789, 4927, 3793, 5709, 3067, 1904, + 9789, 4927, 4355, 3067, 1905, 685, 4355, 7745, 364, + 9789, 4927, 4355, 3067, 1905, 685, 5559, 3759, 364, + 9789, 4927, 4355, 3067, 1905, 11377, 0, + 9789, 4927, 4355, 7744, + 9789, 4927, 5141, 6539, 2133, 3174, + 9789, 4927, 5141, 6539, 5659, 7462, + 9789, 4927, 5307, 5668, + 9789, 4927, 5307, 7744, + 9789, 4927, 5307, 7745, 5668, + 9789, 4927, 5543, 4351, 5668, + 9789, 4927, 5668, + 9789, 4927, 6523, 7462, + 9789, 4927, 6525, 5709, 225, 1905, 7436, + 9789, 4927, 6527, 3067, 1904, + 9789, 4927, 6543, 3067, 1905, 5421, 5669, 364, + 9789, 4927, 6543, 6373, 7463, 369, 4895, 858, + 9789, 4927, 6543, 6373, 7463, 3831, 1915, 858, + 9789, 4927, 7179, 3067, 225, 1905, 7436, + 9789, 4927, 7493, 5668, + 9789, 4927, 7745, 5668, + 9789, 4927, 8564, + 9789, 4927, 9099, 3067, 1905, 5655, 364, + 9789, 4927, 9099, 3809, 8653, 3067, 1905, 5655, 364, + 9789, 4927, 9320, + 9789, 4927, 9363, 3067, 1905, 4939, 364, + 9789, 4927, 9363, 3809, 8653, 3067, 1905, 4939, 364, + 9789, 4927, 10795, 7745, 6528, + 9789, 4927, 12955, 7744, + 9789, 5759, 1301, 859, 9634, + 9789, 5759, 1301, 1889, 9634, + 9789, 5759, 1753, 2733, 858, + 9789, 5759, 1755, 7462, + 9789, 5759, 1865, 7746, + 9789, 5759, 2133, 3175, 1983, 138, + 9789, 5759, 2547, 4842, + 9789, 5759, 3035, 7746, + 9789, 5759, 4937, 858, + 9789, 5759, 5531, 1985, 4256, + 9789, 5759, 5531, 1985, 4352, + 9789, 5759, 5531, 1985, 5531, 4096, + 9789, 5759, 5531, 1985, 6862, + 9789, 5759, 5531, 4097, 4256, + 9789, 5759, 5531, 4097, 4352, + 9789, 5759, 5531, 4097, 5531, 1984, + 9789, 5759, 5531, 4097, 6862, + 9789, 5759, 5557, 547, 2031, 516, + 9789, 5759, 5559, 3758, + 9789, 5759, 6179, 7462, + 9789, 6689, 2170, + 9789, 6689, 2540, + 9789, 6689, 2778, + 9789, 6689, 4200, + 9789, 6689, 4214, + 9789, 6689, 4389, 2170, + 9789, 6689, 4389, 2540, + 9789, 6689, 4389, 2778, + 9789, 6689, 4389, 4200, + 9789, 6689, 4389, 4214, + 9789, 6689, 4389, 5190, + 9789, 6689, 4389, 6260, + 9789, 6689, 4389, 6722, + 9789, 6689, 4389, 7508, + 9789, 6689, 4389, 7694, + 9789, 6689, 5190, + 9789, 6689, 6260, + 9789, 6689, 6722, + 9789, 6689, 7508, + 9789, 6689, 7694, + 9789, 7803, 5759, 8, + 9789, 7803, 5759, 16, + 9789, 7803, 5759, 28, + 9789, 7803, 5759, 40, + 9789, 7803, 5759, 58, + 9789, 7803, 5759, 162, + 9789, 7803, 5759, 266, + 9789, 7803, 5759, 440, + 9789, 7803, 5759, 606, + 9789, 7803, 5759, 9827, 22, + 9789, 7803, 5759, 9827, 34, + 9789, 7803, 5759, 9827, 344, + 9789, 7803, 5759, 9827, 518, + 9789, 7803, 5759, 10489, 16, + 9789, 7803, 5759, 10489, 266, + 9789, 8405, 0, + 9789, 8405, 52, + 9789, 8405, 100, + 9789, 8405, 116, + 9789, 8405, 138, + 9789, 8405, 216, + 9789, 8405, 236, + 9789, 8405, 292, + 9789, 8405, 306, + 9789, 8405, 332, + 9789, 8405, 364, + 9789, 8405, 392, + 9789, 8405, 462, + 9789, 8405, 510, + 9789, 8405, 524, + 9789, 8405, 556, + 9789, 8405, 622, + 9789, 8405, 652, + 9789, 8405, 670, + 9789, 8405, 792, + 9789, 8405, 884, + 9789, 8405, 974, + 9789, 8405, 996, + 9789, 8405, 1080, + 9789, 8405, 1260, + 9789, 8405, 1612, + 9789, 8405, 1642, + 9789, 8405, 2030, + 9789, 8405, 2076, + 9789, 8405, 2126, + 9789, 8405, 2212, + 9789, 8405, 2438, + 9789, 8405, 2516, + 9789, 8405, 2566, + 9789, 8405, 2678, + 9789, 8405, 2732, + 9789, 8405, 2746, + 9789, 8405, 3146, + 9789, 8405, 4016, + 9789, 8405, 4140, + 9789, 8405, 4782, + 9789, 8405, 5978, + 9789, 8405, 5994, + 9789, 8405, 11631, 510, + 9789, 8775, 2089, 112, + 9789, 8775, 2089, 113, 3831, 7904, + 9789, 8775, 2089, 113, 4353, 7904, + 9789, 8775, 2089, 113, 5307, 7904, + 9789, 8775, 2399, 2420, + 9789, 8775, 2399, 2421, 5543, 4350, + 9789, 8775, 4119, 112, + 9789, 8775, 5421, 462, + 9789, 8775, 7333, 4258, + 9789, 10307, 5759, 3877, 7462, + 9789, 10307, 5759, 4859, 7462, + 9789, 10585, 436, + 9789, 11257, 8405, 0, + 9789, 11257, 8405, 52, + 9789, 11257, 8405, 100, + 9789, 11257, 8405, 116, + 9789, 11257, 8405, 138, + 9789, 11257, 8405, 216, + 9789, 11257, 8405, 236, + 9789, 11257, 8405, 292, + 9789, 11257, 8405, 306, + 9789, 11257, 8405, 332, + 9789, 11257, 8405, 364, + 9789, 11257, 8405, 392, + 9789, 11257, 8405, 462, + 9789, 11257, 8405, 510, + 9789, 11257, 8405, 524, + 9789, 11257, 8405, 556, + 9789, 11257, 8405, 622, + 9789, 11257, 8405, 652, + 9789, 11257, 8405, 670, + 9789, 11257, 8405, 792, + 9789, 11257, 8405, 884, + 9789, 11257, 8405, 974, + 9789, 11257, 8405, 996, + 9789, 11257, 8405, 1080, + 9789, 11257, 8405, 1260, + 9789, 11257, 8405, 1612, + 9789, 11257, 8405, 2030, + 9789, 11257, 8405, 2076, + 9789, 11257, 8405, 2126, + 9789, 11257, 8405, 2212, + 9789, 11257, 8405, 2516, + 9789, 11257, 8405, 2566, + 9789, 11257, 8405, 2678, + 9789, 11257, 8405, 2732, + 9789, 11257, 8405, 2746, + 9789, 11257, 8405, 3146, + 9789, 11257, 8405, 4016, + 9789, 11257, 8405, 4140, + 9789, 11257, 8405, 4782, + 9789, 11257, 8405, 5978, + 9789, 11257, 8405, 5994, + 9789, 11257, 8405, 11631, 510, + 9789, 11257, 8405, 11631, 622, + 9789, 11257, 8405, 11631, 652, + 9789, 12405, 5759, 5661, 4255, 6371, 7462, + 9789, 12405, 5759, 7497, 8858, + 9789, 12405, 5759, 7907, 462, + 9789, 12423, 5759, 3845, 5892, + 9789, 12423, 5759, 5641, 6368, + 9789, 12423, 5759, 6909, 3764, + 9789, 12423, 5759, 7101, 3764, + 9793, 1177, 4194, + 9793, 1177, 4830, + 9793, 1177, 6116, + 9793, 1177, 6716, + 9793, 1177, 7812, + 9793, 1177, 8290, + 9793, 1177, 9786, + 9793, 1177, 10344, + 9811, 2779, 8289, 6434, + 9811, 6434, + 9811, 6435, 569, 760, + 9811, 6435, 4221, 760, + 9811, 6435, 6121, 2697, 11096, + 9811, 6435, 6121, 2697, 11764, + 9811, 6435, 6121, 8153, 8758, + 9811, 6435, 6121, 11649, 8758, + 9811, 6435, 11097, 429, 10959, 6434, + 9811, 6505, 6434, + 9811, 7821, 6434, + 9811, 7821, 6435, 439, 10416, + 9811, 7821, 6435, 439, 10417, 6121, 10677, 760, + 9811, 7821, 6435, 439, 10417, 6121, 11649, 760, + 9811, 7821, 6435, 4221, 760, + 9811, 7821, 8153, 6434, + 9811, 7821, 8153, 6435, 439, 10416, + 9811, 7924, + 9811, 8097, 6434, + 9811, 8153, 6434, + 9811, 8561, 7944, + 9811, 8849, 6434, + 9811, 9327, 6121, 3713, 4849, 569, 760, + 9811, 9327, 6121, 3713, 4849, 4221, 760, + 9811, 9327, 6121, 3713, 4849, 7991, 9811, 9327, 6121, 3713, 7442, + 9811, 9327, 6121, 3713, 4849, 7991, 10959, 9327, 6121, 3713, 7442, + 9811, 9327, 6121, 3713, 7443, 569, 760, + 9811, 9327, 6121, 3713, 7443, 4221, 760, + 9811, 9327, 6121, 3713, 11096, + 9811, 9327, 6121, 3713, 11764, + 9811, 11191, 6434, + 9811, 11875, 6435, 4221, 7593, 8056, + 9821, 4390, + 9835, 5758, + 9843, 4390, + 9853, 7931, 4213, 9680, + 9853, 11345, 10582, + 9858, + 9867, 5758, + 9880, + 9891, 4223, 5836, + 9891, 6616, + 9891, 7593, 8405, 116, + 9891, 7593, 8405, 130, + 9891, 7593, 8405, 138, + 9891, 7593, 8405, 166, + 9891, 7593, 8405, 186, + 9891, 7593, 8405, 246, + 9891, 7593, 8405, 292, + 9891, 7593, 8405, 430, + 9891, 7593, 8405, 510, + 9891, 7593, 8405, 568, + 9891, 7593, 8405, 616, + 9891, 7593, 8405, 656, + 9891, 7593, 8405, 670, + 9891, 7593, 8405, 744, + 9891, 7593, 8405, 784, + 9891, 7593, 8405, 884, + 9891, 7593, 8405, 1094, + 9891, 7593, 8405, 1152, + 9891, 7593, 8405, 1276, + 9891, 7593, 8405, 1488, + 9891, 7593, 8405, 1600, + 9891, 7593, 8405, 1602, + 9891, 7593, 8405, 1894, + 9891, 7593, 8405, 2092, + 9891, 7593, 8405, 2206, + 9891, 7593, 8405, 2404, + 9891, 7593, 8405, 2506, + 9891, 7593, 8405, 2516, + 9891, 7593, 8405, 2862, + 9891, 7593, 8405, 2958, + 9891, 7593, 8405, 3148, + 9891, 7593, 8405, 3892, + 9891, 7593, 8405, 4314, + 9891, 7593, 8405, 4636, + 9891, 7593, 8405, 4886, + 9891, 7593, 8405, 5434, + 9891, 7593, 8405, 5948, + 9891, 7593, 8405, 6214, + 9891, 7593, 10301, 1095, 6214, + 9891, 7593, 10301, 1895, 1094, + 9891, 7593, 10301, 1895, 1488, + 9891, 7593, 10301, 1895, 2092, + 9891, 7593, 10301, 1895, 2958, + 9891, 7593, 10301, 2863, 2092, + 9891, 8306, + 9891, 9063, 8405, 116, + 9891, 9063, 8405, 130, + 9891, 9063, 8405, 138, + 9891, 9063, 8405, 166, + 9891, 9063, 8405, 186, + 9891, 9063, 8405, 246, + 9891, 9063, 8405, 292, + 9891, 9063, 8405, 430, + 9891, 9063, 8405, 510, + 9891, 9063, 8405, 568, + 9891, 9063, 8405, 616, + 9891, 9063, 8405, 656, + 9891, 9063, 8405, 670, + 9891, 9063, 8405, 744, + 9891, 9063, 8405, 784, + 9891, 9063, 8405, 884, + 9891, 9063, 8405, 1094, + 9891, 9063, 8405, 1152, + 9891, 9063, 8405, 1276, + 9891, 9063, 8405, 1488, + 9891, 9063, 8405, 1600, + 9891, 9063, 8405, 1602, + 9891, 9063, 8405, 1894, + 9891, 9063, 8405, 2092, + 9891, 9063, 8405, 2206, + 9891, 9063, 8405, 2404, + 9891, 9063, 8405, 2506, + 9891, 9063, 8405, 2516, + 9891, 9063, 8405, 2862, + 9891, 9063, 8405, 2958, + 9891, 9063, 8405, 3148, + 9891, 9063, 8405, 3892, + 9891, 9063, 8405, 4314, + 9891, 9063, 8405, 4636, + 9891, 9063, 8405, 4886, + 9891, 9063, 8405, 5434, + 9891, 9063, 8405, 5948, + 9891, 9063, 8405, 6214, + 9891, 10157, 4926, + 9891, 10339, 8405, 4849, 4389, 5550, + 9891, 10469, 4926, + 9891, 11424, + 9891, 12017, 4926, + 9891, 12391, 4926, + 9898, + 9899, 10374, + 9900, + 9907, 3229, 3228, + 9907, 5759, 2811, 7438, + 9907, 5759, 2811, 8030, + 9907, 5759, 6502, + 9907, 5759, 6556, + 9907, 5759, 8768, + 9907, 5759, 9628, + 9907, 6545, 5762, + 9907, 6545, 9570, + 9907, 6545, 11156, + 9907, 6689, 2170, + 9907, 6689, 2540, + 9907, 6689, 2778, + 9907, 6689, 4200, + 9907, 6689, 4214, + 9907, 6689, 5190, + 9907, 6689, 6260, + 9907, 6689, 6722, + 9907, 6689, 7508, + 9907, 6689, 7694, + 9907, 7334, + 9907, 7803, 5759, 333, 7094, + 9907, 7803, 5759, 333, 7095, 8796, + 9907, 7803, 5759, 511, 5536, + 9907, 7803, 5759, 511, 5537, 8796, + 9907, 7803, 5759, 2810, + 9907, 7803, 5759, 2811, 5638, + 9907, 7803, 5759, 5844, + 9907, 7803, 5759, 5845, 4602, + 9907, 7803, 5759, 7362, + 9907, 7803, 5759, 7363, 8796, + 9907, 7803, 5759, 8788, + 9907, 7803, 5759, 8789, 5536, + 9907, 7803, 5759, 8789, 5537, 8796, + 9907, 7803, 5759, 8789, 8796, + 9907, 7803, 5759, 8796, + 9907, 7826, + 9907, 8405, 100, + 9907, 8405, 101, 9396, + 9907, 8405, 116, + 9907, 8405, 117, 4822, + 9907, 8405, 138, + 9907, 8405, 139, 4920, + 9907, 8405, 139, 7195, 10704, + 9907, 8405, 139, 7195, 11106, + 9907, 8405, 165, 7488, + 9907, 8405, 216, + 9907, 8405, 217, 4346, + 9907, 8405, 236, + 9907, 8405, 292, + 9907, 8405, 293, 4632, + 9907, 8405, 306, + 9907, 8405, 307, 11106, + 9907, 8405, 332, + 9907, 8405, 333, 7094, + 9907, 8405, 333, 7095, 8796, + 9907, 8405, 364, + 9907, 8405, 392, + 9907, 8405, 393, 8632, + 9907, 8405, 462, + 9907, 8405, 463, 7020, + 9907, 8405, 510, + 9907, 8405, 511, 5536, + 9907, 8405, 511, 5537, 8796, + 9907, 8405, 524, + 9907, 8405, 525, 5626, + 9907, 8405, 525, 5634, + 9907, 8405, 556, + 9907, 8405, 557, 5888, + 9907, 8405, 557, 7086, + 9907, 8405, 557, 7195, 11106, + 9907, 8405, 613, 7488, + 9907, 8405, 622, + 9907, 8405, 652, + 9907, 8405, 1579, 7488, + 9907, 8405, 2030, + 9907, 8405, 2126, + 9907, 8405, 3129, 7488, + 9907, 8405, 4753, 7488, + 9907, 8405, 6037, 7488, + 9907, 8405, 6390, + 9907, 8405, 6391, 8796, + 9907, 8405, 6726, + 9907, 8405, 6986, + 9907, 8405, 6987, 8796, + 9907, 8405, 7312, + 9907, 8405, 7313, 8796, + 9907, 8405, 7760, + 9907, 8405, 7761, 8796, + 9907, 8405, 7914, + 9907, 8405, 7957, 7488, + 9907, 8566, + 9907, 9483, 8775, 3986, + 9907, 9483, 8775, 3987, 4266, + 9907, 9483, 8775, 3987, 8768, + 9907, 9483, 8775, 4060, + 9907, 9483, 8775, 4090, + 9907, 9483, 8775, 4106, + 9907, 9483, 8775, 4128, + 9907, 9483, 8775, 6632, + 9907, 9483, 8775, 6638, + 9907, 9483, 8775, 6678, + 9907, 9483, 8775, 10767, 4344, + 9907, 9483, 8775, 10767, 6492, + 9907, 9483, 8775, 10767, 6732, + 9907, 9483, 8775, 10767, 7670, + 9907, 9483, 8775, 10767, 8350, + 9907, 9483, 8775, 10767, 8351, 6121, 9378, + 9907, 9483, 8775, 10767, 8352, + 9907, 9483, 8775, 10767, 8353, 6121, 9378, + 9907, 9483, 8775, 10767, 9378, + 9907, 9483, 8775, 11091, 5385, 5396, + 9907, 9483, 8775, 11091, 5385, 5432, + 9907, 9483, 8775, 11091, 5385, 5452, + 9907, 9483, 8775, 11091, 8065, 5436, + 9907, 9483, 8775, 11091, 8065, 5440, + 9907, 9483, 8775, 11761, 5385, 958, + 9907, 9483, 8775, 11761, 5385, 1052, + 9907, 9483, 8775, 11761, 8065, 2644, + 9907, 9483, 8775, 11761, 8065, 2758, + 9907, 10398, + 9919, 6789, 8405, 14, + 9919, 6789, 8405, 20, + 9919, 6789, 8405, 30, + 9919, 6789, 8405, 38, + 9919, 8405, 0, + 9919, 8405, 2, + 9919, 8405, 4, + 9919, 8405, 6, + 9919, 8405, 8, + 9919, 8405, 10, + 9919, 8405, 12, + 9919, 8405, 14, + 9919, 8405, 16, + 9919, 8405, 18, + 9919, 8405, 20, + 9919, 8405, 22, + 9919, 8405, 24, + 9919, 8405, 26, + 9919, 8405, 28, + 9919, 8405, 30, + 9919, 8405, 32, + 9919, 8405, 34, + 9919, 8405, 36, + 9919, 8405, 38, + 9919, 8405, 40, + 9919, 8405, 42, + 9919, 8405, 46, + 9919, 8405, 50, + 9919, 8405, 72, + 9919, 8405, 78, + 9919, 8405, 80, + 9919, 8405, 92, + 9919, 8405, 112, + 9919, 8405, 124, + 9919, 8405, 162, + 9919, 8405, 166, + 9919, 8405, 168, + 9919, 8405, 176, + 9919, 8405, 182, + 9919, 8405, 226, + 9919, 8405, 230, + 9919, 8405, 264, + 9919, 8405, 272, + 9919, 8405, 280, + 9919, 8405, 286, + 9919, 8405, 296, + 9919, 8405, 400, + 9919, 8405, 436, + 9919, 8405, 440, + 9919, 8405, 450, + 9919, 8405, 530, + 9919, 8405, 674, + 9919, 8405, 676, + 9919, 8405, 722, + 9919, 8405, 724, + 9919, 8405, 1110, + 9919, 8405, 1112, + 9919, 8405, 1490, + 9919, 8405, 2034, + 9919, 8405, 2172, + 9919, 8405, 2174, + 9919, 8405, 2814, + 9919, 8405, 3238, + 9919, 8405, 3286, + 9919, 8405, 4610, + 9923, 1109, 429, 9664, + 9923, 7803, 5759, 8, + 9923, 7803, 5759, 16, + 9923, 7803, 5759, 28, + 9923, 7803, 5759, 40, + 9923, 7803, 5759, 66, + 9923, 8405, 0, + 9923, 8405, 100, + 9923, 8405, 116, + 9923, 8405, 138, + 9923, 8405, 216, + 9923, 8405, 236, + 9923, 8405, 292, + 9923, 8405, 306, + 9923, 8405, 332, + 9923, 8405, 364, + 9923, 8405, 392, + 9923, 8405, 462, + 9923, 8405, 510, + 9923, 8405, 524, + 9923, 8405, 556, + 9923, 8405, 610, + 9923, 8405, 652, + 9923, 8405, 1946, + 9923, 8405, 2030, + 9923, 8405, 2096, + 9923, 8405, 2126, + 9923, 8405, 5166, + 9923, 8405, 5294, + 9923, 9556, + 9924, + 9928, + 9931, 11269, 0, + 9931, 11269, 4, + 9931, 11269, 8, + 9931, 11269, 10, + 9931, 11269, 16, + 9931, 11269, 20, + 9931, 11269, 22, + 9931, 11269, 24, + 9931, 11269, 26, + 9931, 11269, 28, + 9931, 11269, 30, + 9931, 11269, 32, + 9931, 11269, 34, + 9931, 11269, 36, + 9931, 11269, 38, + 9931, 11269, 48, + 9931, 11269, 58, + 9931, 11269, 72, + 9931, 11269, 80, + 9931, 11269, 116, + 9931, 11269, 122, + 9931, 11269, 126, + 9931, 11269, 130, + 9931, 11269, 176, + 9931, 11269, 196, + 9931, 11269, 198, + 9931, 11269, 202, + 9931, 11269, 208, + 9931, 11269, 244, + 9931, 11269, 266, + 9931, 11269, 274, + 9931, 11269, 306, + 9931, 11269, 310, + 9931, 11269, 314, + 9931, 11269, 322, + 9931, 11269, 330, + 9931, 11269, 332, + 9931, 11269, 336, + 9931, 11269, 338, + 9931, 11269, 340, + 9931, 11269, 350, + 9931, 11269, 364, + 9931, 11269, 368, + 9931, 11269, 372, + 9931, 11269, 374, + 9931, 11269, 380, + 9931, 11269, 392, + 9931, 11269, 396, + 9931, 11269, 400, + 9931, 11269, 402, + 9931, 11269, 404, + 9931, 11269, 412, + 9931, 11269, 438, + 9931, 11269, 440, + 9931, 11269, 462, + 9931, 11269, 468, + 9931, 11269, 476, + 9931, 11269, 480, + 9931, 11269, 496, + 9931, 11269, 500, + 9931, 11269, 502, + 9931, 11269, 510, + 9931, 11269, 512, + 9931, 11269, 514, + 9931, 11269, 516, + 9931, 11269, 524, + 9931, 11269, 526, + 9931, 11269, 530, + 9931, 11269, 532, + 9931, 11269, 536, + 9931, 11269, 550, + 9931, 11269, 556, + 9931, 11269, 560, + 9931, 11269, 562, + 9931, 11269, 564, + 9931, 11269, 568, + 9931, 11269, 622, + 9931, 11269, 626, + 9931, 11269, 630, + 9931, 11269, 632, + 9931, 11269, 652, + 9931, 11269, 654, + 9931, 11269, 656, + 9931, 11269, 660, + 9931, 11269, 690, + 9931, 11269, 854, + 9931, 11269, 889, 5758, + 9931, 11269, 898, + 9931, 11269, 914, + 9931, 11269, 936, + 9931, 11269, 938, + 9931, 11269, 940, + 9931, 11269, 942, + 9931, 11269, 1140, + 9931, 11269, 1160, + 9931, 11269, 1172, + 9931, 11269, 1574, + 9931, 11269, 1630, + 9931, 11269, 1660, + 9931, 11269, 1704, + 9931, 11269, 1706, + 9931, 11269, 1708, + 9931, 11269, 1710, + 9931, 11269, 1732, + 9931, 11269, 1770, + 9931, 11269, 1774, + 9931, 11269, 1776, + 9931, 11269, 1784, + 9931, 11269, 1802, + 9931, 11269, 1834, + 9931, 11269, 1836, + 9931, 11269, 1838, + 9931, 11269, 1840, + 9931, 11269, 1854, + 9931, 11269, 1916, + 9931, 11269, 1938, + 9931, 11269, 1964, + 9931, 11269, 1966, + 9931, 11269, 1968, + 9931, 11269, 1970, + 9931, 11269, 1982, + 9931, 11269, 2030, + 9931, 11269, 2036, + 9931, 11269, 2038, + 9931, 11269, 2052, + 9931, 11269, 2078, + 9931, 11269, 2084, + 9931, 11269, 2122, + 9931, 11269, 2124, + 9931, 11269, 2188, + 9931, 11269, 2226, + 9931, 11269, 2238, + 9931, 11269, 2266, + 9931, 11269, 2268, + 9931, 11269, 2270, + 9931, 11269, 2272, + 9931, 11269, 2282, + 9931, 11269, 2286, + 9931, 11269, 2308, + 9931, 11269, 2320, + 9931, 11269, 2378, + 9931, 11269, 2414, + 9931, 11269, 2430, + 9931, 11269, 2482, + 9931, 11269, 2516, + 9931, 11269, 2518, + 9931, 11269, 2520, + 9931, 11269, 2522, + 9931, 11269, 2532, + 9931, 11269, 2554, + 9931, 11269, 2598, + 9931, 11269, 2600, + 9931, 11269, 2604, + 9931, 11269, 2606, + 9931, 11269, 2634, + 9931, 11269, 2678, + 9931, 11269, 2680, + 9931, 11269, 2682, + 9931, 11269, 2684, + 9931, 11269, 2692, + 9931, 11269, 2722, + 9931, 11269, 2746, + 9931, 11269, 2748, + 9931, 11269, 2750, + 9931, 11269, 2752, + 9931, 11269, 2754, + 9931, 11269, 2772, + 9931, 11269, 2774, + 9931, 11269, 2776, + 9931, 11269, 2778, + 9931, 11269, 2780, + 9931, 11269, 2782, + 9931, 11269, 2784, + 9931, 11269, 2786, + 9931, 11269, 2906, + 9931, 11269, 2932, + 9931, 11269, 2942, + 9931, 11269, 3006, + 9931, 11269, 3068, + 9931, 11269, 3082, + 9931, 11269, 3102, + 9931, 11269, 3104, + 9931, 11269, 3106, + 9931, 11269, 3108, + 9931, 11269, 3836, + 9931, 11269, 3970, + 9931, 11269, 3972, + 9931, 11269, 3974, + 9931, 11269, 4176, + 9931, 11269, 4223, 5836, + 9931, 11269, 4230, + 9931, 11269, 4700, + 9931, 11269, 4796, + 9931, 11269, 4800, + 9931, 11269, 4802, + 9931, 11269, 4818, + 9931, 11269, 4856, + 9931, 11269, 4862, + 9931, 11269, 4864, + 9931, 11269, 4910, + 9931, 11269, 4912, + 9931, 11269, 4914, + 9931, 11269, 4918, + 9931, 11269, 5032, + 9931, 11269, 5036, + 9931, 11269, 5038, + 9931, 11269, 5040, + 9931, 11269, 5132, + 9931, 11269, 5134, + 9931, 11269, 5164, + 9931, 11269, 5170, + 9931, 11269, 5228, + 9931, 11269, 5230, + 9931, 11269, 5232, + 9931, 11269, 5290, + 9931, 11269, 5390, + 9931, 11269, 5460, + 9931, 11269, 5464, + 9931, 11269, 5466, + 9931, 11269, 5472, + 9931, 11269, 5518, + 9931, 11269, 5616, + 9931, 11269, 5622, + 9931, 11269, 5666, + 9931, 11269, 5694, + 9931, 11269, 5710, + 9931, 11269, 5732, + 9931, 11269, 5734, + 9931, 11269, 5736, + 9931, 11269, 5738, + 9931, 11269, 5858, + 9931, 11269, 5860, + 9931, 11269, 5862, + 9931, 11269, 5874, + 9931, 11269, 5906, + 9931, 11269, 5924, + 9931, 11269, 5930, + 9931, 11269, 5952, + 9931, 11269, 5954, + 9931, 11269, 5956, + 9931, 11269, 5958, + 9931, 11269, 5994, + 9931, 11269, 5996, + 9931, 11269, 5998, + 9931, 11269, 6000, + 9931, 11269, 6024, + 9931, 11269, 6026, + 9931, 11269, 6028, + 9931, 11269, 6160, + 9931, 11269, 6246, + 9931, 11269, 6248, + 9931, 11269, 6250, + 9931, 11269, 6789, 2725, 4389, 5550, + 9931, 11269, 6789, 4117, 5876, + 9931, 11269, 6789, 5444, + 9931, 11269, 6789, 5550, + 9931, 11269, 6789, 6378, + 9931, 11269, 6789, 6874, + 9931, 11269, 6789, 7443, 4389, 5550, + 9931, 11269, 6789, 7551, 11649, 8758, + 9931, 11269, 6789, 8005, 4389, 5550, + 9931, 11269, 6789, 8153, 6378, + 9931, 11269, 6789, 8153, 7551, 10677, 9744, + 9931, 11269, 6789, 8473, 1044, + 9931, 11269, 7226, + 9931, 11269, 7262, + 9931, 11269, 7264, + 9931, 11269, 7266, + 9931, 11269, 7558, + 9931, 11269, 7560, + 9931, 11269, 7562, + 9931, 11269, 7700, + 9931, 11269, 8461, 22, + 9931, 11269, 8461, 34, + 9931, 11269, 8497, 2680, + 9931, 11269, 8497, 2682, + 9931, 11269, 8497, 5924, + 9931, 11269, 8629, 512, + 9931, 11269, 8671, 24, + 9931, 11269, 8671, 236, + 9931, 11269, 8671, 238, + 9931, 11269, 8671, 242, + 9931, 11269, 8671, 246, + 9931, 11269, 8671, 296, + 9931, 11269, 8671, 300, + 9931, 11269, 8671, 562, + 9931, 11269, 8671, 656, + 9931, 11269, 8671, 2516, + 9931, 11269, 8671, 2518, + 9931, 11269, 8671, 2520, + 9931, 11269, 8671, 2522, + 9931, 11269, 8943, 44, + 9931, 11269, 8943, 440, + 9931, 11269, 8943, 914, + 9931, 11269, 8943, 1660, + 9931, 11269, 8943, 1802, + 9931, 11269, 8943, 1938, + 9931, 11269, 8943, 2084, + 9931, 11269, 8943, 2238, + 9931, 11269, 8943, 2554, + 9931, 11269, 8943, 2722, + 9931, 11269, 8943, 3082, + 9931, 11269, 8943, 5460, + 9931, 11269, 8987, 2, + 9931, 11269, 9067, 14, + 9931, 11269, 9067, 16, + 9931, 11269, 9067, 30, + 9931, 11269, 9067, 50, + 9931, 11269, 9067, 144, + 9931, 11269, 9067, 162, + 9931, 11269, 9067, 216, + 9931, 11269, 9067, 220, + 9931, 11269, 9067, 224, + 9931, 11269, 9067, 228, + 9931, 11269, 9067, 230, + 9931, 11269, 9067, 242, + 9931, 11269, 9067, 292, + 9931, 11269, 9067, 294, + 9931, 11269, 9067, 296, + 9931, 11269, 9067, 298, + 9931, 11269, 9067, 300, + 9931, 11269, 9067, 316, + 9931, 11269, 9067, 332, + 9931, 11269, 9067, 336, + 9931, 11269, 9067, 340, + 9931, 11269, 9067, 350, + 9931, 11269, 9067, 354, + 9931, 11269, 9067, 364, + 9931, 11269, 9067, 368, + 9931, 11269, 9067, 374, + 9931, 11269, 9067, 380, + 9931, 11269, 9067, 384, + 9931, 11269, 9067, 392, + 9931, 11269, 9067, 396, + 9931, 11269, 9067, 400, + 9931, 11269, 9067, 404, + 9931, 11269, 9067, 412, + 9931, 11269, 9067, 416, + 9931, 11269, 9067, 462, + 9931, 11269, 9067, 468, + 9931, 11269, 9067, 476, + 9931, 11269, 9067, 480, + 9931, 11269, 9067, 486, + 9931, 11269, 9067, 510, + 9931, 11269, 9067, 512, + 9931, 11269, 9067, 514, + 9931, 11269, 9067, 516, + 9931, 11269, 9067, 520, + 9931, 11269, 9067, 524, + 9931, 11269, 9067, 526, + 9931, 11269, 9067, 530, + 9931, 11269, 9067, 532, + 9931, 11269, 9067, 536, + 9931, 11269, 9067, 546, + 9931, 11269, 9067, 622, + 9931, 11269, 9067, 626, + 9931, 11269, 9067, 630, + 9931, 11269, 9067, 632, + 9931, 11269, 9067, 634, + 9931, 11269, 9067, 652, + 9931, 11269, 9067, 654, + 9931, 11269, 9067, 656, + 9931, 11269, 9067, 660, + 9931, 11269, 9067, 664, + 9931, 11269, 9067, 670, + 9931, 11269, 9067, 672, + 9931, 11269, 9067, 676, + 9931, 11269, 9067, 678, + 9931, 11269, 9067, 680, + 9931, 11269, 9067, 884, + 9931, 11269, 9067, 886, + 9931, 11269, 9067, 888, + 9931, 11269, 9067, 890, + 9931, 11269, 9067, 892, + 9931, 11269, 9067, 984, + 9931, 11269, 9067, 1024, + 9931, 11269, 9067, 1026, + 9931, 11269, 9067, 1028, + 9931, 11269, 9067, 1030, + 9931, 11269, 9067, 1032, + 9931, 11269, 9067, 1080, + 9931, 11269, 9067, 1082, + 9931, 11269, 9067, 1084, + 9931, 11269, 9067, 1086, + 9931, 11269, 9067, 1088, + 9931, 11269, 9067, 1238, + 9931, 11269, 9067, 1260, + 9931, 11269, 9067, 1262, + 9931, 11269, 9067, 1264, + 9931, 11269, 9067, 1266, + 9931, 11269, 9067, 1268, + 9931, 11269, 9067, 1356, + 9931, 11269, 9067, 1440, + 9931, 11269, 9067, 1442, + 9931, 11269, 9067, 1444, + 9931, 11269, 9067, 1446, + 9931, 11269, 9067, 1448, + 9931, 11269, 9067, 1506, + 9931, 11269, 9067, 1528, + 9931, 11269, 9067, 1530, + 9931, 11269, 9067, 1532, + 9931, 11269, 9067, 1534, + 9931, 11269, 9067, 1536, + 9931, 11269, 9067, 1612, + 9931, 11269, 9067, 1614, + 9931, 11269, 9067, 1616, + 9931, 11269, 9067, 1618, + 9931, 11269, 9067, 1620, + 9931, 11269, 9067, 1642, + 9931, 11269, 9067, 1644, + 9931, 11269, 9067, 1646, + 9931, 11269, 9067, 1648, + 9931, 11269, 9067, 1650, + 9931, 11269, 9067, 1758, + 9931, 11269, 9067, 1770, + 9931, 11269, 9067, 1772, + 9931, 11269, 9067, 1774, + 9931, 11269, 9067, 1776, + 9931, 11269, 9067, 1778, + 9931, 11269, 9067, 1890, + 9931, 11269, 9067, 2016, + 9931, 11269, 9067, 2204, + 9931, 11269, 9067, 2402, + 9931, 11269, 9067, 2504, + 9931, 11269, 9067, 2516, + 9931, 11269, 9067, 2518, + 9931, 11269, 9067, 2520, + 9931, 11269, 9067, 2522, + 9931, 11269, 9067, 2524, + 9931, 11269, 9067, 2678, + 9931, 11269, 9067, 2680, + 9931, 11269, 9067, 2682, + 9931, 11269, 9067, 2684, + 9931, 11269, 9067, 2686, + 9931, 11269, 9067, 2706, + 9931, 11269, 9067, 2708, + 9931, 11269, 9067, 2710, + 9931, 11269, 9067, 2712, + 9931, 11269, 9067, 2714, + 9931, 11269, 9067, 2732, + 9931, 11269, 9067, 2734, + 9931, 11269, 9067, 2736, + 9931, 11269, 9067, 2738, + 9931, 11269, 9067, 2740, + 9931, 11269, 9067, 2746, + 9931, 11269, 9067, 2748, + 9931, 11269, 9067, 2752, + 9931, 11269, 9067, 2754, + 9931, 11269, 9067, 2756, + 9931, 11269, 9067, 2922, + 9931, 11269, 9067, 3050, + 9931, 11269, 9067, 3138, + 9931, 11269, 9067, 3890, + 9931, 11269, 9067, 4098, + 9931, 11269, 9067, 4138, + 9931, 11269, 9067, 4318, + 9931, 11269, 9067, 4556, + 9931, 11269, 9067, 4644, + 9931, 11269, 9067, 4744, + 9931, 11269, 9067, 4766, + 9931, 11269, 9067, 4860, + 9931, 11269, 9067, 5678, + 9931, 11269, 9067, 5914, + 9931, 11269, 9067, 5950, + 9931, 11269, 9067, 5952, + 9931, 11269, 9067, 5954, + 9931, 11269, 9067, 5956, + 9931, 11269, 9067, 5958, + 9931, 11269, 9067, 5960, + 9931, 11269, 9067, 5976, + 9931, 11269, 9067, 5990, + 9931, 11269, 9067, 6002, + 9931, 11269, 9067, 6004, + 9931, 11269, 9067, 6006, + 9931, 11269, 9067, 6008, + 9931, 11269, 9067, 6010, + 9931, 11269, 9067, 7720, + 9931, 11269, 9067, 7748, + 9931, 11269, 9067, 9363, 50, + 9931, 11269, 9313, 5836, + 9931, 11269, 9489, 2480, + 9931, 11269, 9489, 2544, + 9931, 11269, 9489, 2906, + 9931, 11269, 9489, 2942, + 9931, 11269, 9489, 3970, + 9931, 11269, 9489, 4796, + 9931, 11269, 9489, 5032, + 9931, 11269, 9489, 5290, + 9931, 11269, 9489, 5644, + 9931, 11269, 9489, 5774, + 9931, 11269, 9489, 5784, + 9931, 11269, 9489, 5838, + 9931, 11269, 9489, 5858, + 9931, 11269, 9489, 6024, + 9931, 11269, 9489, 6246, + 9931, 11269, 9517, 14, + 9931, 11269, 9517, 236, + 9931, 11269, 9517, 238, + 9931, 11269, 9517, 242, + 9931, 11269, 9517, 246, + 9931, 11269, 9517, 1338, + 9931, 11269, 9517, 1382, + 9931, 11269, 9517, 1424, + 9931, 11269, 9519, 14, + 9931, 11269, 9777, 562, + 9931, 11269, 9777, 2678, + 9931, 11269, 9777, 2680, + 9931, 11269, 9777, 2682, + 9931, 11269, 9777, 2684, + 9931, 11269, 9777, 5906, + 9931, 11269, 9777, 5924, + 9931, 11269, 9777, 5930, + 9931, 11269, 10743, 0, + 9931, 11269, 10743, 8, + 9931, 11269, 10743, 16, + 9931, 11269, 10743, 28, + 9931, 11269, 10743, 36, + 9931, 11269, 10743, 306, + 9931, 11269, 10743, 310, + 9931, 11269, 10743, 314, + 9931, 11269, 10743, 322, + 9931, 11269, 10743, 392, + 9931, 11269, 10743, 396, + 9931, 11269, 10743, 404, + 9931, 11269, 10743, 412, + 9931, 11269, 10743, 622, + 9931, 11269, 10743, 626, + 9931, 11269, 10743, 630, + 9931, 11269, 10743, 632, + 9931, 11269, 11399, 22, + 9931, 11269, 11399, 24, + 9931, 11269, 11399, 30, + 9931, 11269, 11399, 34, + 9931, 11269, 11399, 48, + 9931, 11269, 11399, 332, + 9931, 11269, 11399, 336, + 9931, 11269, 11399, 350, + 9931, 11269, 11399, 510, + 9931, 11269, 11399, 512, + 9931, 11269, 11399, 514, + 9931, 11269, 11399, 516, + 9931, 11269, 11399, 622, + 9931, 11269, 11399, 626, + 9931, 11269, 11399, 630, + 9931, 11269, 11399, 632, + 9931, 11269, 11399, 936, + 9931, 11269, 11399, 938, + 9931, 11269, 11399, 940, + 9931, 11269, 11399, 942, + 9931, 11269, 11399, 1704, + 9931, 11269, 11399, 1706, + 9931, 11269, 11399, 1708, + 9931, 11269, 11399, 1710, + 9931, 11269, 11399, 1834, + 9931, 11269, 11399, 1836, + 9931, 11269, 11399, 1838, + 9931, 11269, 11399, 1840, + 9931, 11269, 11399, 1964, + 9931, 11269, 11399, 1966, + 9931, 11269, 11399, 1968, + 9931, 11269, 11399, 1970, + 9931, 11269, 11399, 2122, + 9931, 11269, 11399, 2124, + 9931, 11269, 11399, 2266, + 9931, 11269, 11399, 2268, + 9931, 11269, 11399, 2270, + 9931, 11269, 11399, 2272, + 9931, 11269, 11399, 2598, + 9931, 11269, 11399, 2600, + 9931, 11269, 11399, 2604, + 9931, 11269, 11399, 2606, + 9931, 11269, 11399, 2772, + 9931, 11269, 11399, 2774, + 9931, 11269, 11399, 2776, + 9931, 11269, 11399, 2778, + 9931, 11269, 11399, 2906, + 9931, 11269, 11399, 2932, + 9931, 11269, 11399, 2942, + 9931, 11269, 11399, 3102, + 9931, 11269, 11399, 3104, + 9931, 11269, 11399, 3106, + 9931, 11269, 11399, 3108, + 9931, 11269, 11399, 3970, + 9931, 11269, 11399, 3972, + 9931, 11269, 11399, 3974, + 9931, 11269, 11399, 4230, + 9931, 11269, 11399, 4796, + 9931, 11269, 11399, 4800, + 9931, 11269, 11399, 4802, + 9931, 11269, 11399, 4910, + 9931, 11269, 11399, 4912, + 9931, 11269, 11399, 4914, + 9931, 11269, 11399, 5032, + 9931, 11269, 11399, 5036, + 9931, 11269, 11399, 5038, + 9931, 11269, 11399, 5290, + 9931, 11269, 11399, 5460, + 9931, 11269, 11399, 5464, + 9931, 11269, 11399, 5466, + 9931, 11269, 11399, 5616, + 9931, 11269, 11399, 5732, + 9931, 11269, 11399, 5734, + 9931, 11269, 11399, 5736, + 9931, 11269, 11399, 5738, + 9931, 11269, 11399, 5858, + 9931, 11269, 11399, 5860, + 9931, 11269, 11399, 5862, + 9931, 11269, 11399, 6024, + 9931, 11269, 11399, 6026, + 9931, 11269, 11399, 6028, + 9931, 11269, 11399, 6246, + 9931, 11269, 11399, 6248, + 9931, 11269, 11399, 6250, + 9931, 11269, 11399, 7558, + 9931, 11269, 11399, 7560, + 9931, 11269, 11399, 7562, + 9931, 11269, 11399, 7700, + 9931, 11269, 11435, 24, + 9931, 11269, 11435, 36, + 9931, 11269, 11443, 48, + 9931, 11269, 11689, 534, + 9931, 11269, 11883, 562, + 9931, 11269, 11883, 2678, + 9931, 11269, 11883, 2680, + 9931, 11269, 11883, 2682, + 9931, 11269, 11883, 2684, + 9931, 11269, 12869, 1580, + 9931, 11269, 12869, 1600, + 9931, 11269, 12869, 1628, + 9931, 11269, 12869, 1656, + 9941, 8405, 0, + 9941, 8405, 8, + 9941, 8405, 16, + 9941, 8405, 28, + 9941, 8405, 36, + 9941, 8405, 40, + 9941, 8405, 42, + 9941, 8405, 138, + 9941, 8405, 142, + 9941, 8405, 144, + 9941, 8405, 150, + 9941, 8405, 152, + 9941, 8405, 154, + 9941, 8405, 216, + 9941, 8405, 220, + 9941, 8405, 224, + 9941, 8405, 228, + 9941, 8405, 230, + 9941, 8405, 232, + 9941, 8405, 236, + 9941, 8405, 238, + 9941, 8405, 242, + 9941, 8405, 246, + 9941, 8405, 250, + 9941, 8405, 252, + 9941, 8405, 306, + 9941, 8405, 332, + 9941, 8405, 336, + 9941, 8405, 340, + 9941, 8405, 350, + 9941, 8405, 354, + 9941, 8405, 356, + 9941, 8405, 364, + 9941, 8405, 368, + 9941, 8405, 374, + 9941, 8405, 380, + 9941, 8405, 384, + 9941, 8405, 392, + 9941, 8405, 396, + 9941, 8405, 404, + 9941, 8405, 412, + 9941, 8405, 416, + 9941, 8405, 418, + 9941, 8405, 524, + 9941, 8405, 526, + 9941, 8405, 532, + 9941, 8405, 536, + 9941, 8405, 546, + 9941, 8405, 548, + 9941, 8405, 556, + 9941, 8405, 560, + 9941, 8405, 564, + 9941, 8405, 622, + 9941, 8405, 626, + 9941, 8405, 630, + 9941, 8405, 632, + 9941, 8405, 634, + 9941, 8405, 636, + 9941, 8405, 652, + 9941, 8405, 654, + 9941, 8405, 656, + 9941, 8405, 660, + 9941, 8405, 664, + 9941, 8405, 666, + 9941, 8405, 1024, + 9941, 8405, 1412, + 9941, 8405, 1986, + 9941, 8405, 2328, + 9941, 8405, 2330, + 9941, 8405, 2332, + 9941, 8405, 2336, + 9941, 8405, 2344, + 9941, 8405, 2346, + 9941, 8405, 2706, + 9941, 8405, 2708, + 9941, 8405, 2710, + 9941, 8405, 2712, + 9941, 8405, 2714, + 9941, 8405, 2716, + 9941, 8405, 2732, + 9941, 8405, 2734, + 9941, 8405, 2736, + 9941, 8405, 2738, + 9941, 8405, 2740, + 9941, 8405, 2742, + 9959, 89, 8466, + 9959, 89, 8521, 10572, + 9959, 89, 8521, 10573, 445, 6741, 568, + 9959, 6121, 4895, 11649, 8758, + 9959, 6121, 9546, + 9959, 6121, 10677, 761, 91, 1109, 429, 11649, 8758, + 9961, 2429, 5895, 6689, 2170, + 9961, 2429, 5895, 6689, 2540, + 9961, 2429, 5895, 6689, 2778, + 9961, 2429, 5895, 6689, 4200, + 9961, 2429, 5895, 6689, 4214, + 9961, 2429, 5895, 6689, 5190, + 9961, 2429, 5895, 6689, 6722, + 9961, 2429, 5895, 6689, 7508, + 9961, 2429, 5895, 6689, 7694, + 9961, 2429, 6053, 6689, 2170, + 9961, 2429, 6053, 6689, 2540, + 9961, 2429, 6053, 6689, 2778, + 9961, 2429, 6053, 6689, 4200, + 9961, 2429, 6053, 6689, 4214, + 9961, 2429, 6053, 6689, 5190, + 9961, 2429, 6053, 6689, 6722, + 9961, 2429, 6053, 6689, 7508, + 9961, 2429, 6053, 6689, 7694, + 9969, 5758, + 9971, 5758, + 9977, 7593, 8405, 0, + 9977, 7593, 8405, 1, 6121, 6516, + 9977, 7593, 8405, 1, 6121, 10804, + 9977, 7593, 8405, 8, + 9977, 7593, 8405, 9, 6121, 10804, + 9977, 7593, 8405, 16, + 9977, 7593, 8405, 17, 6121, 6874, + 9977, 7593, 8405, 17, 6121, 8432, + 9977, 7593, 8405, 17, 6121, 10804, + 9977, 7593, 8405, 28, + 9977, 7593, 8405, 29, 6121, 10804, + 9977, 7593, 8405, 40, + 9977, 7593, 8405, 41, 6121, 8153, 6378, + 9977, 7593, 8405, 41, 6121, 8432, + 9977, 7593, 8405, 41, 6121, 10804, + 9977, 7593, 8405, 102, + 9977, 7593, 8405, 142, + 9977, 7593, 8405, 164, + 9977, 7593, 8405, 172, + 9977, 7593, 8405, 173, 6121, 4530, + 9977, 7593, 8405, 173, 6121, 5878, + 9977, 7593, 8405, 173, 6121, 8473, 4530, + 9977, 7593, 8405, 174, + 9977, 7593, 8405, 175, 6121, 5878, + 9977, 7593, 8405, 176, + 9977, 7593, 8405, 177, 6121, 4530, + 9977, 7593, 8405, 177, 6121, 5878, + 9977, 7593, 8405, 177, 6121, 8473, 4530, + 9977, 7593, 8405, 177, 6121, 10802, + 9977, 7593, 8405, 182, + 9977, 7593, 8405, 183, 6121, 5934, + 9977, 7593, 8405, 184, + 9977, 7593, 8405, 185, 6121, 10802, + 9977, 7593, 8405, 236, + 9977, 7593, 8405, 237, 6121, 4530, + 9977, 7593, 8405, 237, 6121, 8758, + 9977, 7593, 8405, 237, 6121, 10802, + 9977, 7593, 8405, 258, + 9977, 7593, 8405, 259, 6121, 6516, + 9977, 7593, 8405, 259, 6121, 6874, + 9977, 7593, 8405, 276, + 9977, 7593, 8405, 294, + 9977, 7593, 8405, 306, + 9977, 7593, 8405, 307, 6121, 4530, + 9977, 7593, 8405, 307, 6121, 8758, + 9977, 7593, 8405, 307, 6121, 10677, 8758, + 9977, 7593, 8405, 307, 6121, 10802, + 9977, 7593, 8405, 448, + 9977, 7593, 8405, 468, + 9977, 7593, 8405, 469, 6121, 8473, 4530, + 9977, 7593, 8405, 496, + 9977, 7593, 8405, 560, + 9977, 7593, 8405, 561, 6121, 8473, 4530, + 9977, 7593, 8405, 561, 6121, 10802, + 9977, 7593, 8405, 592, + 9977, 7593, 8405, 612, + 9977, 7593, 8405, 626, + 9977, 7593, 8405, 652, + 9977, 7593, 8405, 656, + 9977, 7593, 8405, 658, + 9977, 7593, 8405, 664, + 9977, 7593, 8405, 672, + 9977, 7593, 8405, 673, 6121, 10802, + 9977, 7593, 8405, 673, 6121, 10804, + 9977, 7593, 8405, 807, 3096, + 9977, 7593, 8405, 886, + 9977, 7593, 8405, 887, 6121, 10677, 8758, + 9977, 7593, 8405, 887, 6121, 10802, + 9977, 7593, 8405, 887, 6121, 10804, + 9977, 7593, 8405, 1022, + 9977, 7593, 8405, 1074, + 9977, 7593, 8405, 1082, + 9977, 7593, 8405, 1262, + 9977, 7593, 8405, 1263, 6121, 8473, 4530, + 9977, 7593, 8405, 1263, 6121, 8758, + 9977, 7593, 8405, 1263, 6121, 8759, 721, 4530, + 9977, 7593, 8405, 1263, 6121, 8896, + 9977, 7593, 8405, 1263, 6121, 10802, + 9977, 7593, 8405, 1284, + 9977, 7593, 8405, 1442, + 9977, 7593, 8405, 1640, + 9977, 7593, 8405, 1680, + 9977, 7593, 8405, 1770, + 9977, 7593, 8405, 1794, + 9977, 7593, 8405, 2064, + 9977, 7593, 8405, 2250, + 9977, 7593, 8405, 2410, + 9977, 7593, 8405, 2516, + 9977, 7593, 8405, 2734, + 9977, 7593, 8405, 2774, + 9977, 7593, 8405, 3012, + 9977, 7593, 8405, 3038, + 9977, 7593, 8405, 3148, + 9977, 7593, 8405, 3149, 6121, 6516, + 9977, 7593, 8405, 3149, 6121, 10802, + 9977, 7593, 8405, 3149, 6121, 10804, + 9977, 7593, 8405, 3862, + 9977, 7593, 8405, 4142, + 9977, 7593, 8405, 4146, + 9977, 7593, 8405, 4148, + 9977, 7593, 8405, 4198, + 9977, 7593, 8405, 4393, 5758, + 9977, 7593, 8405, 4614, + 9977, 7593, 8405, 4771, 142, + 9977, 7593, 8405, 4771, 1022, + 9977, 7593, 8405, 4771, 1794, + 9977, 7593, 8405, 4771, 2064, + 9977, 7593, 8405, 4771, 2542, + 9977, 7593, 8405, 4771, 2704, + 9977, 7593, 8405, 4771, 3172, + 9977, 7593, 8405, 4771, 4144, + 9977, 7593, 8405, 5690, + 9977, 7593, 8405, 5734, + 9977, 7593, 8405, 5781, 142, + 9977, 7593, 8405, 5781, 172, + 9977, 7593, 8405, 5781, 174, + 9977, 7593, 8405, 5781, 5758, + 9977, 7593, 8405, 5890, + 9977, 7593, 8405, 5980, + 9977, 7593, 8405, 5982, + 9977, 7593, 8405, 5986, + 9977, 7593, 8405, 6200, + 9977, 7593, 8405, 6201, 6121, 3697, 3058, + 9977, 7593, 8405, 6201, 6121, 10804, + 9977, 7593, 8405, 6302, + 9977, 7593, 8405, 6399, 306, + 9977, 7593, 8405, 6519, 7316, + 9977, 7593, 8405, 6696, + 9977, 7593, 8405, 6710, + 9977, 7593, 8405, 7062, + 9977, 7593, 8405, 7316, + 9977, 7593, 8405, 7317, 6121, 7716, + 9977, 7593, 8405, 7455, 7316, + 9977, 7593, 8405, 7494, + 9977, 7593, 8405, 7495, 6121, 10804, + 9977, 7593, 8405, 7522, + 9977, 7593, 8405, 7551, 16, + 9977, 7593, 8405, 7551, 17, 6121, 5878, + 9977, 7593, 8405, 7551, 40, + 9977, 7593, 8405, 7981, 28, + 9977, 7593, 8405, 7981, 29, 6121, 10804, + 9977, 7593, 8405, 8065, 8425, 3096, + 9977, 7593, 8405, 8153, 11125, 28, + 9977, 7593, 8405, 8425, 3096, + 9977, 7593, 8405, 8960, + 9977, 7593, 8405, 9029, 306, + 9977, 7593, 8405, 9049, 3096, + 9977, 7593, 8405, 9372, + 9977, 7593, 8405, 9373, 6121, 8153, 6875, 7908, + 9977, 7593, 8405, 9501, 3058, + 9977, 7593, 8405, 10269, 0, + 9977, 7593, 8405, 10269, 8, + 9977, 7593, 8405, 10269, 807, 3096, + 9977, 7593, 8405, 10269, 3038, + 9977, 7593, 8405, 10269, 8065, 8425, 3096, + 9977, 7593, 8405, 10269, 8425, 3096, + 9977, 7593, 8405, 10396, + 9977, 7593, 8405, 10489, 664, + 9977, 7593, 8405, 10489, 672, + 9977, 7593, 8405, 10489, 1082, + 9977, 7593, 8405, 10509, 5758, + 9977, 7593, 8405, 10545, 40, + 9977, 7593, 8405, 10545, 41, 6121, 8758, + 9977, 7593, 8405, 10697, 236, + 9977, 7593, 8405, 10697, 886, + 9977, 7593, 8405, 10697, 887, 6121, 10802, + 9977, 7593, 8405, 10697, 1082, + 9977, 7593, 8405, 10735, 28, + 9977, 7593, 8405, 11125, 28, + 9977, 7593, 8405, 11127, 592, + 9977, 7593, 8405, 11383, 258, + 9977, 7593, 8405, 11665, 886, + 9977, 7593, 8405, 13415, 16, + 9977, 7593, 10301, 1, 258, + 9977, 7593, 10301, 177, 1262, + 9977, 7593, 10301, 561, 2734, + 9977, 8342, + 9977, 8405, 7593, 9063, 172, + 9977, 8405, 10396, + 9977, 8405, 12087, 28, + 9977, 9063, 8405, 0, + 9977, 9063, 8405, 1, 6121, 6516, + 9977, 9063, 8405, 1, 6121, 10804, + 9977, 9063, 8405, 8, + 9977, 9063, 8405, 9, 6121, 10804, + 9977, 9063, 8405, 16, + 9977, 9063, 8405, 17, 6121, 6874, + 9977, 9063, 8405, 17, 6121, 8432, + 9977, 9063, 8405, 17, 6121, 10804, + 9977, 9063, 8405, 28, + 9977, 9063, 8405, 29, 6121, 10804, + 9977, 9063, 8405, 40, + 9977, 9063, 8405, 41, 6121, 8153, 6378, + 9977, 9063, 8405, 41, 6121, 8432, + 9977, 9063, 8405, 41, 6121, 10804, + 9977, 9063, 8405, 102, + 9977, 9063, 8405, 142, + 9977, 9063, 8405, 164, + 9977, 9063, 8405, 172, + 9977, 9063, 8405, 173, 6121, 4530, + 9977, 9063, 8405, 173, 6121, 5878, + 9977, 9063, 8405, 173, 6121, 8473, 4530, + 9977, 9063, 8405, 174, + 9977, 9063, 8405, 175, 6121, 5878, + 9977, 9063, 8405, 176, + 9977, 9063, 8405, 177, 6121, 4530, + 9977, 9063, 8405, 177, 6121, 5878, + 9977, 9063, 8405, 177, 6121, 8473, 4530, + 9977, 9063, 8405, 177, 6121, 10802, + 9977, 9063, 8405, 182, + 9977, 9063, 8405, 183, 6121, 5934, + 9977, 9063, 8405, 184, + 9977, 9063, 8405, 185, 6121, 10802, + 9977, 9063, 8405, 236, + 9977, 9063, 8405, 237, 6121, 4530, + 9977, 9063, 8405, 237, 6121, 8758, + 9977, 9063, 8405, 237, 6121, 10802, + 9977, 9063, 8405, 258, + 9977, 9063, 8405, 259, 6121, 6516, + 9977, 9063, 8405, 259, 6121, 6874, + 9977, 9063, 8405, 276, + 9977, 9063, 8405, 294, + 9977, 9063, 8405, 306, + 9977, 9063, 8405, 307, 6121, 4530, + 9977, 9063, 8405, 307, 6121, 8758, + 9977, 9063, 8405, 307, 6121, 10677, 8758, + 9977, 9063, 8405, 307, 6121, 10802, + 9977, 9063, 8405, 448, + 9977, 9063, 8405, 468, + 9977, 9063, 8405, 469, 6121, 8473, 4530, + 9977, 9063, 8405, 496, + 9977, 9063, 8405, 560, + 9977, 9063, 8405, 561, 6121, 8473, 4530, + 9977, 9063, 8405, 561, 6121, 10802, + 9977, 9063, 8405, 592, + 9977, 9063, 8405, 612, + 9977, 9063, 8405, 626, + 9977, 9063, 8405, 652, + 9977, 9063, 8405, 656, + 9977, 9063, 8405, 658, + 9977, 9063, 8405, 664, + 9977, 9063, 8405, 672, + 9977, 9063, 8405, 673, 6121, 10802, + 9977, 9063, 8405, 673, 6121, 10804, + 9977, 9063, 8405, 807, 3096, + 9977, 9063, 8405, 886, + 9977, 9063, 8405, 887, 6121, 10677, 8758, + 9977, 9063, 8405, 887, 6121, 10802, + 9977, 9063, 8405, 887, 6121, 10804, + 9977, 9063, 8405, 1022, + 9977, 9063, 8405, 1074, + 9977, 9063, 8405, 1082, + 9977, 9063, 8405, 1262, + 9977, 9063, 8405, 1263, 6121, 8473, 4530, + 9977, 9063, 8405, 1263, 6121, 8758, + 9977, 9063, 8405, 1263, 6121, 8759, 721, 4530, + 9977, 9063, 8405, 1263, 6121, 8896, + 9977, 9063, 8405, 1263, 6121, 10802, + 9977, 9063, 8405, 1284, + 9977, 9063, 8405, 1442, + 9977, 9063, 8405, 1640, + 9977, 9063, 8405, 1680, + 9977, 9063, 8405, 1770, + 9977, 9063, 8405, 1794, + 9977, 9063, 8405, 2064, + 9977, 9063, 8405, 2250, + 9977, 9063, 8405, 2410, + 9977, 9063, 8405, 2516, + 9977, 9063, 8405, 2734, + 9977, 9063, 8405, 2774, + 9977, 9063, 8405, 3012, + 9977, 9063, 8405, 3038, + 9977, 9063, 8405, 3148, + 9977, 9063, 8405, 3149, 6121, 6516, + 9977, 9063, 8405, 3149, 6121, 10802, + 9977, 9063, 8405, 3149, 6121, 10804, + 9977, 9063, 8405, 3862, + 9977, 9063, 8405, 4142, + 9977, 9063, 8405, 4146, + 9977, 9063, 8405, 4148, + 9977, 9063, 8405, 4198, + 9977, 9063, 8405, 4393, 5758, + 9977, 9063, 8405, 4614, + 9977, 9063, 8405, 4771, 142, + 9977, 9063, 8405, 4771, 1022, + 9977, 9063, 8405, 4771, 1794, + 9977, 9063, 8405, 4771, 2064, + 9977, 9063, 8405, 4771, 2542, + 9977, 9063, 8405, 4771, 2704, + 9977, 9063, 8405, 4771, 3172, + 9977, 9063, 8405, 4771, 4144, + 9977, 9063, 8405, 5690, + 9977, 9063, 8405, 5734, + 9977, 9063, 8405, 5781, 142, + 9977, 9063, 8405, 5781, 172, + 9977, 9063, 8405, 5781, 174, + 9977, 9063, 8405, 5781, 5758, + 9977, 9063, 8405, 5890, + 9977, 9063, 8405, 5980, + 9977, 9063, 8405, 5982, + 9977, 9063, 8405, 5986, + 9977, 9063, 8405, 6200, + 9977, 9063, 8405, 6201, 6121, 3697, 3058, + 9977, 9063, 8405, 6201, 6121, 10804, + 9977, 9063, 8405, 6302, + 9977, 9063, 8405, 6399, 306, + 9977, 9063, 8405, 6519, 7316, + 9977, 9063, 8405, 6696, + 9977, 9063, 8405, 6710, + 9977, 9063, 8405, 7062, + 9977, 9063, 8405, 7316, + 9977, 9063, 8405, 7317, 6121, 7716, + 9977, 9063, 8405, 7455, 7316, + 9977, 9063, 8405, 7494, + 9977, 9063, 8405, 7495, 6121, 10804, + 9977, 9063, 8405, 7522, + 9977, 9063, 8405, 7551, 16, + 9977, 9063, 8405, 7551, 17, 6121, 5878, + 9977, 9063, 8405, 7551, 40, + 9977, 9063, 8405, 7981, 28, + 9977, 9063, 8405, 7981, 29, 6121, 10804, + 9977, 9063, 8405, 8065, 8425, 3096, + 9977, 9063, 8405, 8153, 11125, 28, + 9977, 9063, 8405, 8425, 3096, + 9977, 9063, 8405, 8960, + 9977, 9063, 8405, 9029, 306, + 9977, 9063, 8405, 9049, 3096, + 9977, 9063, 8405, 9372, + 9977, 9063, 8405, 9373, 6121, 8153, 6875, 7908, + 9977, 9063, 8405, 9501, 3058, + 9977, 9063, 8405, 10269, 0, + 9977, 9063, 8405, 10269, 8, + 9977, 9063, 8405, 10269, 807, 3096, + 9977, 9063, 8405, 10269, 3038, + 9977, 9063, 8405, 10269, 8065, 8425, 3096, + 9977, 9063, 8405, 10269, 8425, 3096, + 9977, 9063, 8405, 10489, 664, + 9977, 9063, 8405, 10489, 672, + 9977, 9063, 8405, 10489, 1082, + 9977, 9063, 8405, 10509, 5758, + 9977, 9063, 8405, 10545, 40, + 9977, 9063, 8405, 10545, 41, 6121, 8758, + 9977, 9063, 8405, 10697, 236, + 9977, 9063, 8405, 10697, 886, + 9977, 9063, 8405, 10697, 887, 6121, 10802, + 9977, 9063, 8405, 10697, 1082, + 9977, 9063, 8405, 10735, 28, + 9977, 9063, 8405, 11125, 28, + 9977, 9063, 8405, 11127, 592, + 9977, 9063, 8405, 11383, 258, + 9977, 9063, 8405, 11665, 886, + 9977, 9063, 8405, 13415, 16, + 9977, 9063, 10301, 1, 258, + 9977, 9063, 10301, 177, 1262, + 9977, 9063, 10301, 561, 2734, + 9977, 9578, + 9977, 11363, 5758, + 10003, 5758, + 10017, 5758, + 10017, 7580, + 10017, 7710, + 10141, 7383, 11765, 6434, + 10153, 6434, + 10157, 8774, + 10162, + 10171, 4223, 5836, + 10171, 6610, + 10171, 6616, + 10171, 6689, 2170, + 10171, 6689, 2540, + 10171, 6689, 2778, + 10171, 6689, 4200, + 10171, 6689, 4214, + 10171, 6689, 5190, + 10171, 6689, 6722, + 10171, 6689, 7508, + 10171, 6689, 7694, + 10171, 7723, 4927, 4790, + 10171, 7723, 4927, 6676, + 10171, 7723, 4927, 6686, + 10171, 7723, 4927, 6910, + 10171, 7723, 4927, 7038, + 10171, 7723, 4927, 7551, 8646, + 10171, 7723, 4927, 7860, + 10171, 7723, 4927, 8046, + 10171, 7723, 4927, 8646, + 10171, 7723, 4927, 11934, + 10171, 8525, 2670, + 10171, 8525, 2671, 10624, + 10171, 8525, 6784, + 10171, 8525, 6804, + 10171, 8525, 7576, + 10171, 8525, 8160, + 10171, 8525, 8514, + 10171, 8525, 8820, + 10171, 8525, 8876, + 10171, 8525, 9344, + 10171, 8525, 9672, + 10171, 9607, 6610, + 10171, 9665, 4926, + 10171, 10469, 4926, + 10171, 10585, 100, + 10171, 10585, 102, + 10171, 10585, 106, + 10171, 10585, 108, + 10171, 10585, 112, + 10171, 10585, 116, + 10171, 10585, 122, + 10171, 10585, 126, + 10171, 10585, 130, + 10171, 10585, 132, + 10171, 10585, 138, + 10171, 10585, 142, + 10171, 10585, 144, + 10171, 10585, 150, + 10171, 10585, 152, + 10171, 10585, 196, + 10171, 10585, 198, + 10171, 10585, 202, + 10171, 10585, 208, + 10171, 10585, 210, + 10171, 10585, 216, + 10171, 10585, 220, + 10171, 10585, 224, + 10171, 10585, 228, + 10171, 10585, 230, + 10171, 10585, 236, + 10171, 10585, 238, + 10171, 10585, 242, + 10171, 10585, 246, + 10171, 10585, 250, + 10171, 10585, 292, + 10171, 10585, 294, + 10171, 10585, 296, + 10171, 10585, 298, + 10171, 10585, 300, + 10171, 10585, 306, + 10171, 10585, 310, + 10171, 10585, 314, + 10171, 10585, 322, + 10171, 10585, 326, + 10171, 10585, 332, + 10171, 10585, 336, + 10171, 10585, 340, + 10171, 10585, 350, + 10171, 10585, 354, + 10171, 10585, 364, + 10171, 10585, 368, + 10171, 10585, 374, + 10171, 10585, 380, + 10171, 10585, 384, + 10171, 10585, 392, + 10171, 10585, 396, + 10171, 10585, 404, + 10171, 10585, 412, + 10171, 10585, 416, + 10171, 10585, 462, + 10171, 10585, 468, + 10171, 10585, 476, + 10171, 10585, 480, + 10171, 10585, 486, + 10171, 10585, 496, + 10171, 10585, 498, + 10171, 10585, 500, + 10171, 10585, 502, + 10171, 10585, 506, + 10171, 10585, 510, + 10171, 10585, 512, + 10171, 10585, 514, + 10171, 10585, 516, + 10171, 10585, 520, + 10171, 10585, 524, + 10171, 10585, 526, + 10171, 10585, 532, + 10171, 10585, 536, + 10171, 10585, 546, + 10171, 10585, 556, + 10171, 10585, 560, + 10171, 10585, 564, + 10171, 10585, 568, + 10171, 10585, 576, + 10171, 10585, 610, + 10171, 10585, 612, + 10171, 10585, 614, + 10171, 10585, 616, + 10171, 10585, 618, + 10171, 10585, 622, + 10171, 10585, 626, + 10171, 10585, 630, + 10171, 10585, 632, + 10171, 10585, 634, + 10171, 10585, 638, + 10171, 10585, 640, + 10171, 10585, 644, + 10171, 10585, 646, + 10171, 10585, 648, + 10171, 10585, 652, + 10171, 10585, 654, + 10171, 10585, 656, + 10171, 10585, 660, + 10171, 10585, 664, + 10171, 10585, 670, + 10171, 10585, 672, + 10171, 10585, 676, + 10171, 10585, 678, + 10171, 10585, 680, + 10171, 10585, 748, + 10171, 10585, 778, + 10171, 10585, 816, + 10171, 10585, 838, + 10171, 10585, 840, + 10171, 10585, 842, + 10171, 10585, 854, + 10171, 10585, 866, + 10171, 10585, 868, + 10171, 10585, 870, + 10171, 10585, 872, + 10171, 10585, 874, + 10171, 10585, 876, + 10171, 10585, 884, + 10171, 10585, 886, + 10171, 10585, 888, + 10171, 10585, 890, + 10171, 10585, 892, + 10171, 10585, 910, + 10171, 10585, 936, + 10171, 10585, 954, + 10171, 10585, 974, + 10171, 10585, 976, + 10171, 10585, 978, + 10171, 10585, 980, + 10171, 10585, 982, + 10171, 10585, 984, + 10171, 10585, 1034, + 10171, 10585, 1072, + 10171, 10585, 1140, + 10171, 10585, 1150, + 10171, 10585, 1188, + 10171, 10585, 1190, + 10171, 10585, 1192, + 10171, 10585, 1194, + 10171, 10585, 1204, + 10171, 10585, 1238, + 10171, 10585, 1250, + 10171, 10585, 1252, + 10171, 10585, 1254, + 10171, 10585, 1256, + 10171, 10585, 1258, + 10171, 10585, 1288, + 10171, 10585, 1322, + 10171, 10585, 1324, + 10171, 10585, 1326, + 10171, 10585, 1328, + 10171, 10585, 1330, + 10171, 10585, 1332, + 10171, 10585, 1334, + 10171, 10585, 1336, + 10171, 10585, 1338, + 10171, 10585, 1356, + 10171, 10585, 1370, + 10171, 10585, 1372, + 10171, 10585, 1374, + 10171, 10585, 1376, + 10171, 10585, 1378, + 10171, 10585, 1418, + 10171, 10585, 1502, + 10171, 10585, 1506, + 10171, 10585, 1540, + 10171, 10585, 1562, + 10171, 10585, 1574, + 10171, 10585, 1598, + 10171, 10585, 1654, + 10171, 10585, 1704, + 10171, 10585, 1706, + 10171, 10585, 1708, + 10171, 10585, 1712, + 10171, 10585, 1714, + 10171, 10585, 1716, + 10171, 10585, 1718, + 10171, 10585, 1720, + 10171, 10585, 1722, + 10171, 10585, 1724, + 10171, 10585, 1726, + 10171, 10585, 1728, + 10171, 10585, 1730, + 10171, 10585, 1732, + 10171, 10585, 1758, + 10171, 10585, 1798, + 10171, 10585, 1834, + 10171, 10585, 1854, + 10171, 10585, 1890, + 10171, 10585, 1932, + 10171, 10585, 1964, + 10171, 10585, 1966, + 10171, 10585, 1968, + 10171, 10585, 1972, + 10171, 10585, 1982, + 10171, 10585, 2016, + 10171, 10585, 2082, + 10171, 10585, 2122, + 10171, 10585, 2126, + 10171, 10585, 2130, + 10171, 10585, 2132, + 10171, 10585, 2134, + 10171, 10585, 2136, + 10171, 10585, 2188, + 10171, 10585, 2204, + 10171, 10585, 2212, + 10171, 10585, 2214, + 10171, 10585, 2216, + 10171, 10585, 2218, + 10171, 10585, 2220, + 10171, 10585, 2236, + 10171, 10585, 2266, + 10171, 10585, 2268, + 10171, 10585, 2270, + 10171, 10585, 2282, + 10171, 10585, 2294, + 10171, 10585, 2296, + 10171, 10585, 2298, + 10171, 10585, 2300, + 10171, 10585, 2302, + 10171, 10585, 2304, + 10171, 10585, 2316, + 10171, 10585, 2350, + 10171, 10585, 2352, + 10171, 10585, 2354, + 10171, 10585, 2356, + 10171, 10585, 2358, + 10171, 10585, 2360, + 10171, 10585, 2362, + 10171, 10585, 2370, + 10171, 10585, 2378, + 10171, 10585, 2402, + 10171, 10585, 2424, + 10171, 10585, 2466, + 10171, 10585, 2468, + 10171, 10585, 2482, + 10171, 10585, 2504, + 10171, 10585, 2516, + 10171, 10585, 2518, + 10171, 10585, 2520, + 10171, 10585, 2522, + 10171, 10585, 2524, + 10171, 10585, 2548, + 10171, 10585, 2566, + 10171, 10585, 2568, + 10171, 10585, 2570, + 10171, 10585, 2572, + 10171, 10585, 2574, + 10171, 10585, 2598, + 10171, 10585, 2620, + 10171, 10585, 2622, + 10171, 10585, 2624, + 10171, 10585, 2626, + 10171, 10585, 2628, + 10171, 10585, 2634, + 10171, 10585, 2666, + 10171, 10585, 2678, + 10171, 10585, 2680, + 10171, 10585, 2682, + 10171, 10585, 2684, + 10171, 10585, 2686, + 10171, 10585, 2718, + 10171, 10585, 2732, + 10171, 10585, 2734, + 10171, 10585, 2736, + 10171, 10585, 2738, + 10171, 10585, 2740, + 10171, 10585, 2772, + 10171, 10585, 2790, + 10171, 10585, 2792, + 10171, 10585, 2794, + 10171, 10585, 2796, + 10171, 10585, 2798, + 10171, 10585, 2844, + 10171, 10585, 2856, + 10171, 10585, 2896, + 10171, 10585, 2906, + 10171, 10585, 2922, + 10171, 10585, 2936, + 10171, 10585, 2952, + 10171, 10585, 2956, + 10171, 10585, 2968, + 10171, 10585, 2982, + 10171, 10585, 2984, + 10171, 10585, 2986, + 10171, 10585, 2988, + 10171, 10585, 2990, + 10171, 10585, 2992, + 10171, 10585, 2994, + 10171, 10585, 3002, + 10171, 10585, 3006, + 10171, 10585, 3050, + 10171, 10585, 3078, + 10171, 10585, 3120, + 10171, 10585, 3138, + 10171, 10585, 3146, + 10171, 10585, 3148, + 10171, 10585, 3150, + 10171, 10585, 3152, + 10171, 10585, 3154, + 10171, 10585, 3176, + 10171, 10585, 3202, + 10171, 10585, 3212, + 10171, 10585, 3214, + 10171, 10585, 3216, + 10171, 10585, 3218, + 10171, 10585, 3220, + 10171, 10585, 3826, + 10171, 10585, 3856, + 10171, 10585, 3858, + 10171, 10585, 3860, + 10171, 10585, 3862, + 10171, 10585, 3864, + 10171, 10585, 3866, + 10171, 10585, 3868, + 10171, 10585, 3874, + 10171, 10585, 3890, + 10171, 10585, 3906, + 10171, 10585, 3924, + 10171, 10585, 3998, + 10171, 10585, 4010, + 10171, 10585, 4028, + 10171, 10585, 4046, + 10171, 10585, 4232, + 10171, 10585, 4270, + 10171, 10585, 4278, + 10171, 10585, 4308, + 10171, 10585, 4310, + 10171, 10585, 4312, + 10171, 10585, 4370, + 10171, 10585, 4372, + 10171, 10585, 4374, + 10171, 10585, 4378, + 10171, 10585, 4412, + 10171, 10585, 4414, + 10171, 10585, 4416, + 10171, 10585, 4796, + 10171, 10585, 4798, + 10171, 10585, 4804, + 10171, 10585, 4806, + 10171, 10585, 4808, + 10171, 10585, 4810, + 10171, 10585, 4812, + 10171, 10585, 4814, + 10171, 10585, 4816, + 10171, 10585, 5034, + 10171, 10585, 5292, + 10171, 10585, 5296, + 10171, 10585, 5314, + 10171, 10585, 5332, + 10171, 10585, 5410, + 10171, 10585, 5416, + 10171, 10585, 5418, + 10171, 10585, 5422, + 10171, 10585, 5462, + 10171, 10585, 5478, + 10171, 10585, 5480, + 10171, 10585, 5482, + 10171, 10585, 5484, + 10171, 10585, 5486, + 10171, 10585, 5508, + 10171, 10585, 5510, + 10171, 10585, 5512, + 10171, 10585, 5514, + 10171, 10585, 5666, + 10171, 10585, 5678, + 10171, 10585, 5704, + 10171, 10585, 5732, + 10171, 10585, 5786, + 10171, 10585, 5794, + 10171, 10585, 5866, + 10171, 10585, 5868, + 10171, 10585, 5870, + 10171, 10585, 5906, + 10171, 10585, 5914, + 10171, 10585, 5928, + 10171, 10585, 5932, + 10171, 10585, 5974, + 10171, 10585, 5976, + 10171, 10585, 5984, + 10171, 10585, 6032, + 10171, 10585, 6034, + 10171, 10585, 6038, + 10171, 10585, 6148, + 10171, 10585, 6150, + 10171, 10585, 6152, + 10171, 10585, 6154, + 10171, 10585, 6264, + 10171, 10585, 6274, + 10171, 10585, 6300, + 10171, 10585, 6328, + 10171, 10585, 6336, + 10171, 10585, 6550, + 10171, 10585, 6552, + 10171, 10585, 6846, + 10171, 10585, 6848, + 10171, 10585, 7066, + 10171, 10585, 7068, + 10171, 10585, 7406, + 10171, 10585, 7408, + 10171, 10585, 9313, 0, + 10171, 10585, 9313, 8, + 10171, 10585, 9313, 16, + 10171, 10585, 9313, 28, + 10171, 10585, 9313, 40, + 10171, 10585, 9313, 58, + 10171, 10585, 9313, 162, + 10171, 10585, 9313, 422, + 10171, 10585, 9313, 622, + 10171, 10585, 11223, 838, + 10171, 10585, 11223, 1188, + 10171, 10585, 11223, 1964, + 10171, 10585, 11223, 2266, + 10171, 10585, 11723, 0, + 10171, 10585, 11723, 8, + 10171, 10585, 11723, 16, + 10171, 10585, 11723, 28, + 10171, 10585, 11723, 40, + 10171, 10585, 11723, 58, + 10171, 10585, 11723, 162, + 10171, 10767, 11639, 4926, + 10171, 11163, 11228, + 10171, 11224, + 10171, 11400, + 10173, 12403, 6689, 2170, + 10173, 12403, 6689, 2540, + 10173, 12403, 6689, 2778, + 10173, 12403, 6689, 4200, + 10173, 12403, 6689, 4214, + 10173, 12403, 6689, 5190, + 10173, 12403, 6689, 6260, + 10173, 12403, 6689, 6722, + 10173, 12403, 6689, 7508, + 10173, 12403, 6689, 7694, + 10179, 9539, 11054, + 10192, + 10203, 7580, + 10203, 11143, 2170, + 10213, 11894, + 10221, 7593, 8405, 80, + 10221, 7593, 8405, 176, + 10221, 7593, 8405, 238, + 10221, 7593, 8405, 274, + 10221, 7593, 8405, 438, + 10221, 7593, 8405, 596, + 10221, 7593, 8405, 626, + 10221, 7593, 8405, 756, + 10221, 7593, 8405, 858, + 10221, 7593, 8405, 900, + 10221, 7593, 8405, 1038, + 10221, 7593, 8405, 1216, + 10221, 7593, 8405, 1340, + 10221, 7593, 8405, 1350, + 10221, 7593, 8405, 1380, + 10221, 7593, 8405, 1420, + 10221, 7593, 8405, 1520, + 10221, 7593, 8405, 1588, + 10221, 7593, 8405, 1744, + 10221, 7593, 8405, 1860, + 10221, 7593, 8405, 1992, + 10221, 7593, 8405, 2196, + 10221, 7593, 8405, 2290, + 10221, 7593, 8405, 2384, + 10221, 7593, 8405, 2490, + 10221, 7593, 8405, 2648, + 10221, 7593, 8405, 2654, + 10221, 7593, 8405, 2868, + 10221, 7593, 8405, 2954, + 10221, 7593, 8405, 3140, + 10221, 7593, 8405, 3884, + 10221, 7593, 8405, 3904, + 10221, 7593, 8405, 4316, + 10221, 7593, 8405, 4634, + 10221, 7593, 8405, 4742, + 10221, 7593, 8405, 5414, + 10221, 7593, 8405, 5698, + 10221, 7593, 8405, 6268, + 10221, 8405, 80, + 10221, 8405, 176, + 10221, 8405, 202, + 10221, 8405, 238, + 10221, 8405, 274, + 10221, 8405, 438, + 10221, 8405, 596, + 10221, 8405, 626, + 10221, 8405, 658, + 10221, 8405, 710, + 10221, 8405, 756, + 10221, 8405, 858, + 10221, 8405, 900, + 10221, 8405, 1038, + 10221, 8405, 1216, + 10221, 8405, 1340, + 10221, 8405, 1350, + 10221, 8405, 1380, + 10221, 8405, 1420, + 10221, 8405, 1520, + 10221, 8405, 1588, + 10221, 8405, 1744, + 10221, 8405, 1860, + 10221, 8405, 1992, + 10221, 8405, 2196, + 10221, 8405, 2290, + 10221, 8405, 2384, + 10221, 8405, 2490, + 10221, 8405, 2648, + 10221, 8405, 2654, + 10221, 8405, 2868, + 10221, 8405, 2954, + 10221, 8405, 3140, + 10221, 8405, 3884, + 10221, 8405, 3904, + 10221, 8405, 4316, + 10221, 8405, 4634, + 10221, 8405, 4742, + 10221, 8405, 5414, + 10221, 8405, 5698, + 10221, 8405, 6268, + 10221, 8405, 6728, + 10221, 8405, 8869, 1216, + 10221, 9063, 8405, 80, + 10221, 9063, 8405, 176, + 10221, 9063, 8405, 238, + 10221, 9063, 8405, 274, + 10221, 9063, 8405, 438, + 10221, 9063, 8405, 596, + 10221, 9063, 8405, 626, + 10221, 9063, 8405, 756, + 10221, 9063, 8405, 858, + 10221, 9063, 8405, 900, + 10221, 9063, 8405, 1038, + 10221, 9063, 8405, 1216, + 10221, 9063, 8405, 1340, + 10221, 9063, 8405, 1350, + 10221, 9063, 8405, 1380, + 10221, 9063, 8405, 1420, + 10221, 9063, 8405, 1520, + 10221, 9063, 8405, 1588, + 10221, 9063, 8405, 1744, + 10221, 9063, 8405, 1860, + 10221, 9063, 8405, 1992, + 10221, 9063, 8405, 2196, + 10221, 9063, 8405, 2290, + 10221, 9063, 8405, 2384, + 10221, 9063, 8405, 2490, + 10221, 9063, 8405, 2648, + 10221, 9063, 8405, 2654, + 10221, 9063, 8405, 2868, + 10221, 9063, 8405, 2954, + 10221, 9063, 8405, 3140, + 10221, 9063, 8405, 3884, + 10221, 9063, 8405, 3904, + 10221, 9063, 8405, 4316, + 10221, 9063, 8405, 4634, + 10221, 9063, 8405, 4742, + 10221, 9063, 8405, 5414, + 10221, 9063, 8405, 5698, + 10221, 9063, 8405, 6268, + 10221, 11163, 11228, + 10225, 436, + 10225, 5759, 7282, + 10225, 5759, 8916, + 10225, 5759, 9824, + 10225, 5759, 9870, + 10225, 5759, 9904, + 10225, 5759, 11900, + 10225, 6689, 2170, + 10225, 6689, 2540, + 10225, 6689, 2778, + 10225, 6689, 4200, + 10225, 6689, 4214, + 10225, 6689, 5190, + 10225, 6689, 6260, + 10225, 6689, 6722, + 10225, 6689, 7508, + 10225, 6689, 7694, + 10225, 7469, 5758, + 10225, 7803, 5759, 8, + 10225, 7803, 5759, 16, + 10225, 7803, 5759, 28, + 10225, 7803, 5759, 40, + 10225, 7803, 5759, 58, + 10225, 7803, 5759, 72, + 10225, 7803, 5759, 92, + 10225, 7803, 5759, 266, + 10225, 7803, 5759, 606, + 10225, 7803, 5759, 8031, 8, + 10225, 7803, 5759, 8031, 28, + 10225, 7803, 5759, 9827, 22, + 10225, 7803, 5759, 9827, 34, + 10225, 7803, 5759, 9827, 344, + 10225, 7803, 5759, 9827, 518, + 10225, 7803, 8031, 8, + 10225, 7803, 8031, 28, + 10225, 8405, 0, + 10225, 8405, 8, + 10225, 8405, 16, + 10225, 8405, 28, + 10225, 8405, 40, + 10225, 8405, 58, + 10225, 8405, 72, + 10225, 8405, 92, + 10225, 8405, 100, + 10225, 8405, 116, + 10225, 8405, 138, + 10225, 8405, 216, + 10225, 8405, 236, + 10225, 8405, 266, + 10225, 8405, 292, + 10225, 8405, 306, + 10225, 8405, 332, + 10225, 8405, 364, + 10225, 8405, 392, + 10225, 8405, 462, + 10225, 8405, 510, + 10225, 8405, 524, + 10225, 8405, 556, + 10225, 8405, 606, + 10225, 8405, 610, + 10225, 8405, 652, + 10225, 8405, 792, + 10225, 8405, 884, + 10225, 8405, 974, + 10225, 8405, 996, + 10225, 8405, 1260, + 10225, 8405, 1512, + 10225, 8405, 1612, + 10225, 8405, 1796, + 10225, 8405, 2030, + 10225, 8405, 2076, + 10225, 8405, 2126, + 10225, 8405, 2212, + 10225, 8405, 2516, + 10225, 8405, 2566, + 10225, 8405, 2678, + 10225, 8405, 2746, + 10225, 8405, 4016, + 10225, 8405, 5994, + 10225, 8405, 9827, 22, + 10225, 8405, 9827, 34, + 10225, 8405, 9827, 344, + 10225, 8405, 9827, 518, + 10227, 171, 7318, + 10227, 1496, + 10227, 2826, + 10227, 5759, 3227, 6498, + 10227, 5759, 6498, + 10227, 5759, 7282, + 10227, 5759, 7758, + 10227, 5759, 8916, + 10227, 5759, 8944, + 10227, 5759, 9824, + 10227, 6380, + 10227, 6689, 2170, + 10227, 6689, 2540, + 10227, 6689, 2778, + 10227, 6689, 4200, + 10227, 6689, 4214, + 10227, 6689, 5190, + 10227, 6689, 6260, + 10227, 6689, 6722, + 10227, 6689, 7508, + 10227, 6689, 7694, + 10227, 7714, + 10227, 7803, 5759, 16, + 10227, 7803, 5759, 40, + 10227, 7803, 5759, 58, + 10227, 7803, 5759, 72, + 10227, 7803, 5759, 92, + 10227, 7803, 5759, 162, + 10227, 7803, 5759, 266, + 10227, 7803, 5759, 440, + 10227, 7803, 5759, 606, + 10227, 8405, 0, + 10227, 8405, 16, + 10227, 8405, 40, + 10227, 8405, 58, + 10227, 8405, 72, + 10227, 8405, 92, + 10227, 8405, 100, + 10227, 8405, 116, + 10227, 8405, 138, + 10227, 8405, 162, + 10227, 8405, 196, + 10227, 8405, 216, + 10227, 8405, 236, + 10227, 8405, 266, + 10227, 8405, 292, + 10227, 8405, 306, + 10227, 8405, 332, + 10227, 8405, 364, + 10227, 8405, 392, + 10227, 8405, 440, + 10227, 8405, 462, + 10227, 8405, 510, + 10227, 8405, 524, + 10227, 8405, 556, + 10227, 8405, 606, + 10227, 8405, 610, + 10227, 8405, 652, + 10227, 8405, 670, + 10227, 8405, 792, + 10227, 8405, 884, + 10227, 8405, 974, + 10227, 8405, 996, + 10227, 8405, 1260, + 10227, 8405, 1512, + 10227, 8405, 1612, + 10227, 8405, 1796, + 10227, 8405, 2030, + 10227, 8405, 2076, + 10227, 8405, 2126, + 10227, 8405, 2212, + 10227, 8405, 2438, + 10227, 8405, 2516, + 10227, 8405, 2678, + 10227, 8405, 2746, + 10227, 8405, 4016, + 10227, 8405, 4320, + 10227, 8405, 4748, + 10227, 8405, 5994, + 10231, 9513, 2170, + 10231, 9513, 2540, + 10231, 9513, 2670, + 10231, 9513, 2778, + 10231, 9513, 4200, + 10231, 9513, 4214, + 10231, 9513, 5190, + 10231, 9513, 6722, + 10231, 9513, 7508, + 10231, 9513, 7694, + 10231, 9513, 8820, + 10231, 9513, 8876, + 10241, 1177, 2681, 3276, + 10241, 1177, 2681, 6110, + 10241, 1177, 2681, 8192, + 10241, 1177, 2681, 8251, 6116, + 10241, 1177, 2681, 8333, 4830, + 10241, 1177, 2681, 8971, 7812, + 10241, 1177, 2681, 9395, 7639, 10344, + 10241, 1177, 2681, 9893, 9786, + 10241, 1177, 2681, 9934, + 10241, 1177, 2681, 9953, 4194, + 10241, 1177, 2681, 9963, 8290, + 10241, 1177, 2681, 10323, 8436, + 10241, 1177, 2681, 10680, + 10241, 1177, 2681, 11199, 6716, + 10241, 1177, 6131, 439, 2681, 9148, + 10241, 1177, 6383, 11454, + 10241, 1177, 6868, + 10241, 1177, 6877, 7388, + 10241, 1177, 6877, 8790, + 10241, 1177, 6877, 11732, + 10241, 1177, 6877, 13000, + 10241, 1177, 6995, 7738, + 10241, 1177, 7187, 9118, + 10241, 1177, 7348, + 10241, 1177, 7593, 8790, + 10241, 1177, 7593, 13000, + 10241, 1177, 7987, 11454, + 10241, 1177, 7999, 9784, + 10241, 1177, 8071, 569, 4944, + 10241, 1177, 8642, + 10241, 1177, 9341, 10632, + 10241, 1177, 9478, + 10241, 1177, 9613, 8898, + 10241, 1177, 9630, + 10241, 1177, 9832, + 10241, 1177, 9878, + 10241, 1177, 9954, + 10241, 1177, 9992, + 10241, 1177, 10146, + 10241, 1177, 10252, + 10241, 1177, 10458, + 10241, 1177, 10638, + 10241, 1177, 10689, 6796, + 10241, 1177, 10698, + 10241, 1177, 10793, 429, 2681, 7100, + 10241, 1177, 10998, + 10241, 1177, 11013, 10632, + 10241, 1177, 11056, + 10241, 1177, 11058, + 10241, 1177, 11247, 6416, + 10241, 1177, 11481, 91, 2681, 10732, + 10241, 1177, 11482, + 10241, 1177, 11614, + 10241, 1177, 11628, + 10241, 1177, 11678, + 10241, 1177, 11702, + 10241, 1177, 11704, + 10241, 1177, 11756, + 10241, 1177, 11836, + 10241, 1177, 11930, + 10241, 1177, 11938, + 10241, 1177, 12100, + 10241, 1177, 12414, + 10241, 1177, 12918, + 10243, 8405, 0, + 10243, 8405, 8, + 10243, 8405, 16, + 10243, 8405, 26, + 10243, 8405, 28, + 10243, 8405, 40, + 10243, 8405, 100, + 10243, 8405, 102, + 10243, 8405, 106, + 10243, 8405, 108, + 10243, 8405, 112, + 10243, 8405, 138, + 10243, 8405, 142, + 10243, 8405, 144, + 10243, 8405, 150, + 10243, 8405, 152, + 10243, 8405, 216, + 10243, 8405, 220, + 10243, 8405, 224, + 10243, 8405, 228, + 10243, 8405, 230, + 10243, 8405, 236, + 10243, 8405, 238, + 10243, 8405, 242, + 10243, 8405, 246, + 10243, 8405, 250, + 10243, 8405, 306, + 10243, 8405, 310, + 10243, 8405, 314, + 10243, 8405, 322, + 10243, 8405, 326, + 10243, 8405, 364, + 10243, 8405, 368, + 10243, 8405, 374, + 10243, 8405, 380, + 10243, 8405, 384, + 10243, 8405, 392, + 10243, 8405, 396, + 10243, 8405, 404, + 10243, 8405, 412, + 10243, 8405, 416, + 10243, 8405, 462, + 10243, 8405, 468, + 10243, 8405, 476, + 10243, 8405, 480, + 10243, 8405, 486, + 10243, 8405, 510, + 10243, 8405, 512, + 10243, 8405, 514, + 10243, 8405, 516, + 10243, 8405, 520, + 10243, 8405, 524, + 10243, 8405, 526, + 10243, 8405, 532, + 10243, 8405, 536, + 10243, 8405, 546, + 10243, 8405, 556, + 10243, 8405, 560, + 10243, 8405, 564, + 10243, 8405, 568, + 10243, 8405, 576, + 10243, 8405, 618, + 10243, 8405, 622, + 10243, 8405, 626, + 10243, 8405, 630, + 10243, 8405, 632, + 10243, 8405, 652, + 10243, 8405, 660, + 10243, 8405, 664, + 10243, 8405, 670, + 10243, 8405, 672, + 10243, 8405, 676, + 10243, 8405, 678, + 10243, 8405, 680, + 10243, 8405, 7593, 0, + 10243, 8405, 7593, 8, + 10243, 8405, 7593, 16, + 10243, 8405, 7593, 28, + 10243, 8405, 7593, 40, + 10243, 8405, 7593, 306, + 10243, 8405, 7593, 310, + 10243, 8405, 7593, 576, + 10243, 8405, 7593, 622, + 10243, 8405, 7593, 652, + 10243, 8405, 7593, 660, + 10243, 8405, 7593, 664, + 10243, 8921, 11067, 4926, + 10243, 9165, 6224, + 10243, 11067, 4926, + 10256, + 10257, 9495, 6121, 10677, 760, + 10260, + 10261, 6121, 7711, 5758, + 10261, 6121, 7768, + 10261, 6121, 8153, 8758, + 10261, 6121, 9546, + 10261, 6121, 10666, + 10261, 6121, 11097, 6435, 6121, 4530, + 10261, 6121, 12492, + 10261, 7939, 1, 7383, 10374, + 10261, 9015, 6121, 7580, + 10261, 10982, + 10265, 9610, + 10267, 2163, 5758, + 10267, 4841, 36, + 10267, 10469, 4926, + 10267, 10670, + 10267, 12017, 4926, + 10267, 12064, + 10277, 11663, 10539, 8774, + 10283, 8405, 0, + 10283, 8405, 8, + 10283, 8405, 16, + 10283, 8405, 26, + 10283, 8405, 28, + 10283, 8405, 40, + 10283, 8405, 100, + 10283, 8405, 102, + 10283, 8405, 106, + 10283, 8405, 108, + 10283, 8405, 112, + 10283, 8405, 138, + 10283, 8405, 142, + 10283, 8405, 144, + 10283, 8405, 150, + 10283, 8405, 152, + 10283, 8405, 216, + 10283, 8405, 220, + 10283, 8405, 224, + 10283, 8405, 228, + 10283, 8405, 230, + 10283, 8405, 236, + 10283, 8405, 238, + 10283, 8405, 242, + 10283, 8405, 246, + 10283, 8405, 250, + 10283, 8405, 306, + 10283, 8405, 310, + 10283, 8405, 314, + 10283, 8405, 322, + 10283, 8405, 326, + 10283, 8405, 364, + 10283, 8405, 368, + 10283, 8405, 374, + 10283, 8405, 380, + 10283, 8405, 384, + 10283, 8405, 392, + 10283, 8405, 396, + 10283, 8405, 404, + 10283, 8405, 412, + 10283, 8405, 416, + 10283, 8405, 462, + 10283, 8405, 468, + 10283, 8405, 476, + 10283, 8405, 480, + 10283, 8405, 486, + 10283, 8405, 510, + 10283, 8405, 512, + 10283, 8405, 514, + 10283, 8405, 516, + 10283, 8405, 520, + 10283, 8405, 524, + 10283, 8405, 526, + 10283, 8405, 532, + 10283, 8405, 536, + 10283, 8405, 546, + 10283, 8405, 556, + 10283, 8405, 560, + 10283, 8405, 564, + 10283, 8405, 568, + 10283, 8405, 576, + 10283, 8405, 610, + 10283, 8405, 612, + 10283, 8405, 614, + 10283, 8405, 616, + 10283, 8405, 618, + 10283, 8405, 622, + 10283, 8405, 626, + 10283, 8405, 630, + 10283, 8405, 632, + 10283, 8405, 652, + 10283, 8405, 660, + 10283, 8405, 664, + 10283, 8405, 670, + 10283, 8405, 672, + 10283, 8405, 676, + 10283, 8405, 678, + 10283, 8405, 680, + 10283, 8405, 7593, 0, + 10283, 8405, 7593, 8, + 10283, 8405, 7593, 16, + 10283, 8405, 7593, 28, + 10283, 8405, 7593, 40, + 10283, 8405, 7593, 236, + 10283, 8405, 7593, 238, + 10283, 8405, 7593, 242, + 10283, 8405, 7593, 246, + 10283, 8405, 7593, 250, + 10283, 8405, 7593, 306, + 10283, 8405, 7593, 310, + 10283, 8405, 7593, 326, + 10283, 8405, 7593, 384, + 10283, 8405, 7593, 416, + 10283, 8405, 7593, 510, + 10283, 8405, 7593, 512, + 10283, 8405, 7593, 514, + 10283, 8405, 7593, 516, + 10283, 8405, 7593, 520, + 10283, 8405, 7593, 532, + 10283, 8405, 7593, 546, + 10283, 8405, 7593, 568, + 10283, 8405, 7593, 576, + 10283, 8405, 7593, 622, + 10283, 8405, 7593, 652, + 10283, 8405, 7593, 660, + 10283, 8405, 7593, 664, + 10283, 8473, 1044, + 10283, 8921, 11067, 4926, + 10283, 9165, 4772, + 10283, 11067, 4926, + 10286, + 10297, 2638, + 10321, 8774, + 10327, 114, + 10327, 6408, + 10327, 6409, 6121, 5385, 735, 8165, 275, 6435, 10441, 601, 721, 4848, + 10327, 6409, 6121, 5385, 735, 8165, 275, 6435, 10441, 601, 721, 7442, + 10327, 6409, 6121, 5385, 735, 8165, 275, 6435, 10441, 4117, 721, 4848, + 10327, 6409, 6121, 5385, 735, 8165, 275, 6435, 10441, 4117, 721, 7442, + 10327, 6409, 6121, 5385, 735, 8165, 275, 6435, 10441, 4849, 721, 600, + 10327, 6409, 6121, 5385, 735, 8165, 275, 6435, 10441, 4849, 721, 4116, + 10327, 6409, 6121, 5385, 735, 8165, 275, 6435, 10441, 7443, 721, 600, + 10327, 6409, 6121, 5385, 735, 8165, 275, 6435, 10441, 7443, 721, 4116, + 10327, 6409, 9537, 4848, + 10327, 7443, 6409, 6121, 1044, + 10333, 2779, 8709, 5387, 4894, + 10333, 2779, 8709, 8328, + 10333, 4895, 5387, 2779, 8708, + 10333, 4895, 5387, 7550, + 10333, 6516, + 10333, 7551, 5387, 4894, + 10333, 9796, + 10333, 11164, + 10333, 11358, + 10339, 8405, 601, 5876, + 10339, 8405, 601, 10716, + 10339, 8405, 604, + 10339, 8405, 1045, 7580, + 10339, 8405, 1045, 10677, 760, + 10339, 8405, 1045, 11649, 760, + 10339, 8405, 1109, 1809, 5964, + 10339, 8405, 1109, 4423, 5964, + 10339, 8405, 1809, 601, 10716, + 10339, 8405, 1809, 4117, 10716, + 10339, 8405, 1809, 4849, 6434, + 10339, 8405, 1809, 4849, 10716, + 10339, 8405, 1809, 5550, + 10339, 8405, 1809, 5965, 760, + 10339, 8405, 1809, 6379, 7908, + 10339, 8405, 1809, 6875, 7908, + 10339, 8405, 1809, 7443, 10716, + 10339, 8405, 1809, 7708, + 10339, 8405, 1809, 8151, 5965, 760, + 10339, 8405, 1809, 8151, 11095, 5965, 760, + 10339, 8405, 1809, 8432, + 10339, 8405, 1809, 10267, 12017, 4926, + 10339, 8405, 1809, 10677, 4876, + 10339, 8405, 1809, 11095, 5965, 760, + 10339, 8405, 1809, 11449, 7908, + 10339, 8405, 1911, 5965, 760, + 10339, 8405, 1911, 8151, 5965, 760, + 10339, 8405, 1911, 8151, 11095, 5965, 760, + 10339, 8405, 1911, 11095, 5965, 760, + 10339, 8405, 3071, 10799, 5965, 4926, + 10339, 8405, 4117, 5876, + 10339, 8405, 4117, 10716, + 10339, 8405, 4389, 11859, 6610, + 10339, 8405, 4423, 5965, 760, + 10339, 8405, 4423, 8151, 5965, 760, + 10339, 8405, 4423, 8151, 11095, 5965, 760, + 10339, 8405, 4423, 11095, 5965, 760, + 10339, 8405, 4849, 4389, 5550, + 10339, 8405, 4849, 10716, + 10339, 8405, 5385, 7530, + 10339, 8405, 5445, 5758, + 10339, 8405, 6179, 10799, 5965, 4926, + 10339, 8405, 6379, 7908, + 10339, 8405, 6485, 1809, 5964, + 10339, 8405, 6485, 4423, 5964, + 10339, 8405, 6610, + 10339, 8405, 6623, 7908, + 10339, 8405, 6875, 7908, + 10339, 8405, 7121, 7443, 8077, 6408, + 10339, 8405, 7173, 5758, + 10339, 8405, 7390, + 10339, 8405, 7443, 4389, 5550, + 10339, 8405, 7443, 10716, + 10339, 8405, 7530, + 10339, 8405, 7551, 8167, 5758, + 10339, 8405, 7593, 0, + 10339, 8405, 7593, 2, + 10339, 8405, 7593, 4, + 10339, 8405, 7593, 5, 6121, 3966, + 10339, 8405, 7593, 6, + 10339, 8405, 7593, 8, + 10339, 8405, 7593, 10, + 10339, 8405, 7593, 12, + 10339, 8405, 7593, 14, + 10339, 8405, 7593, 15, 6121, 4530, + 10339, 8405, 7593, 17, 6121, 8758, + 10339, 8405, 7593, 18, + 10339, 8405, 7593, 19, 6121, 12426, + 10339, 8405, 7593, 20, + 10339, 8405, 7593, 22, + 10339, 8405, 7593, 23, 6121, 9553, 4530, + 10339, 8405, 7593, 23, 6121, 11215, 4530, + 10339, 8405, 7593, 24, + 10339, 8405, 7593, 25, 6121, 4530, + 10339, 8405, 7593, 27, 6121, 4849, 4530, + 10339, 8405, 7593, 27, 6121, 11215, 4530, + 10339, 8405, 7593, 28, + 10339, 8405, 7593, 30, + 10339, 8405, 7593, 34, + 10339, 8405, 7593, 36, + 10339, 8405, 7593, 37, 6121, 4530, + 10339, 8405, 7593, 38, + 10339, 8405, 7593, 39, 6121, 9553, 4530, + 10339, 8405, 7593, 40, + 10339, 8405, 7593, 41, 760, + 10339, 8405, 7593, 42, + 10339, 8405, 7593, 43, 6121, 4530, + 10339, 8405, 7593, 44, + 10339, 8405, 7593, 46, + 10339, 8405, 7593, 48, + 10339, 8405, 7593, 50, + 10339, 8405, 7593, 51, 6121, 3966, + 10339, 8405, 7593, 51, 6121, 11215, 4530, + 10339, 8405, 7593, 710, + 10339, 8405, 7593, 888, + 10339, 8405, 7593, 1110, + 10339, 8405, 7593, 1124, + 10339, 8405, 7593, 1130, + 10339, 8405, 7593, 1138, + 10339, 8405, 7593, 2216, + 10339, 8405, 7593, 2725, 4389, 28, + 10339, 8405, 7593, 3774, + 10339, 8405, 7593, 4614, + 10339, 8405, 7593, 5385, 8, + 10339, 8405, 7593, 5385, 28, + 10339, 8405, 7593, 6406, + 10339, 8405, 7593, 6674, + 10339, 8405, 7593, 6824, + 10339, 8405, 7593, 6879, 2216, + 10339, 8405, 7593, 6879, 6824, + 10339, 8405, 7593, 7494, + 10339, 8405, 7593, 7682, + 10339, 8405, 7593, 7981, 28, + 10339, 8405, 7593, 8005, 4389, 28, + 10339, 8405, 7593, 8679, 12, + 10339, 8405, 7593, 8869, 0, + 10339, 8405, 7593, 8869, 14, + 10339, 8405, 7593, 8869, 16, + 10339, 8405, 7593, 8869, 24, + 10339, 8405, 7593, 8869, 25, 6121, 4895, 1760, + 10339, 8405, 7593, 8869, 34, + 10339, 8405, 7593, 8869, 35, 6121, 4530, + 10339, 8405, 7593, 8869, 42, + 10339, 8405, 7593, 8869, 66, + 10339, 8405, 7593, 8869, 5385, 8, + 10339, 8405, 7593, 8869, 6406, + 10339, 8405, 7593, 9063, 16, + 10339, 8405, 7593, 9063, 17, 6121, 8758, + 10339, 8405, 7593, 9063, 22, + 10339, 8405, 7593, 9063, 26, + 10339, 8405, 7593, 9063, 40, + 10339, 8405, 7593, 9063, 10267, 34, + 10339, 8405, 7593, 9185, 19, 6121, 8758, + 10339, 8405, 7593, 9808, + 10339, 8405, 7593, 10489, 5385, 8, + 10339, 8405, 7593, 10489, 9313, 5836, + 10339, 8405, 7593, 10523, 40, + 10339, 8405, 8153, 7390, + 10339, 8405, 8153, 11424, + 10339, 8405, 8432, + 10339, 8405, 8473, 6875, 7908, + 10339, 8405, 8473, 8153, 6379, 7908, + 10339, 8405, 8473, 8153, 6875, 7908, + 10339, 8405, 8631, 601, 6434, + 10339, 8405, 8631, 4117, 6434, + 10339, 8405, 8631, 6610, + 10339, 8405, 8631, 10267, 12017, 4926, + 10339, 8405, 8631, 12017, 4926, + 10339, 8405, 8645, 4530, + 10339, 8405, 8755, 721, 1809, 5964, + 10339, 8405, 8755, 721, 4423, 5964, + 10339, 8405, 8869, 6616, + 10339, 8405, 9063, 0, + 10339, 8405, 9063, 2, + 10339, 8405, 9063, 6, + 10339, 8405, 9063, 8, + 10339, 8405, 9063, 12, + 10339, 8405, 9063, 14, + 10339, 8405, 9063, 16, + 10339, 8405, 9063, 18, + 10339, 8405, 9063, 20, + 10339, 8405, 9063, 22, + 10339, 8405, 9063, 24, + 10339, 8405, 9063, 26, + 10339, 8405, 9063, 28, + 10339, 8405, 9063, 30, + 10339, 8405, 9063, 34, + 10339, 8405, 9063, 38, + 10339, 8405, 9063, 40, + 10339, 8405, 9063, 42, + 10339, 8405, 9063, 44, + 10339, 8405, 9063, 66, + 10339, 8405, 9063, 450, + 10339, 8405, 9063, 7981, 2, + 10339, 8405, 9063, 10489, 8, + 10339, 8405, 9063, 10489, 26, + 10339, 8405, 9079, 4849, 4389, 5550, + 10339, 8405, 9079, 7443, 4389, 5550, + 10339, 8405, 9089, 5965, 3071, 506, + 10339, 8405, 9089, 5965, 3071, 520, + 10339, 8405, 9089, 5965, 3071, 5432, + 10339, 8405, 9089, 5965, 3071, 7514, + 10339, 8405, 9089, 5965, 6179, 506, + 10339, 8405, 9089, 5965, 6179, 520, + 10339, 8405, 9089, 5965, 6179, 5432, + 10339, 8405, 9089, 5965, 6179, 7514, + 10339, 8405, 9313, 5836, + 10339, 8405, 9828, + 10339, 8405, 9977, 176, + 10339, 8405, 10221, 1992, + 10339, 8405, 10489, 6616, + 10339, 8405, 10489, 9313, 5836, + 10339, 8405, 10677, 4876, + 10339, 8405, 10985, 5965, 760, + 10339, 8405, 10985, 8151, 5965, 760, + 10339, 8405, 10985, 8151, 11095, 5965, 760, + 10339, 8405, 10985, 11095, 5965, 760, + 10339, 8405, 11424, + 10339, 8405, 11449, 7908, + 10339, 8405, 11625, 5965, 760, + 10339, 8405, 11625, 8151, 5965, 760, + 10339, 8405, 11625, 8151, 11095, 5965, 760, + 10339, 8405, 11625, 11095, 5965, 760, + 10339, 8405, 11859, 6610, + 10339, 8405, 12380, + 10343, 1177, 3070, + 10343, 1177, 6178, + 10343, 1177, 6716, + 10346, + 10350, + 10351, 7768, + 10351, 13060, + 10353, 6689, 8696, + 10357, 9095, 6689, 6260, + 10357, 9095, 8525, 8162, + 10357, 9095, 8525, 8874, + 10357, 9095, 8525, 8876, + 10357, 9095, 8525, 9286, + 10357, 9095, 8525, 9700, + 10357, 9095, 8525, 10150, + 10357, 9095, 8525, 10200, + 10357, 9095, 8525, 10360, + 10357, 9095, 8525, 10622, + 10357, 9095, 8525, 11232, + 10363, 7608, + 10379, 428, + 10383, 6622, + 10385, 6505, 5830, + 10385, 6879, 6622, + 10385, 7089, 6622, + 10385, 7821, 5830, + 10388, + 10411, 568, + 10411, 6121, 7709, 10374, + 10411, 6121, 11649, 8758, + 10429, 4927, 5668, + 10429, 4927, 8153, 5668, + 10429, 8153, 4399, 4926, + 10429, 8405, 0, + 10429, 8405, 8, + 10429, 8405, 16, + 10429, 8405, 28, + 10429, 8405, 40, + 10429, 8405, 100, + 10429, 8405, 116, + 10429, 8405, 138, + 10429, 8405, 162, + 10429, 8405, 196, + 10429, 8405, 216, + 10429, 8405, 236, + 10429, 8405, 292, + 10429, 8405, 306, + 10429, 8405, 332, + 10429, 8405, 364, + 10429, 8405, 392, + 10429, 8405, 462, + 10429, 8405, 496, + 10429, 8405, 510, + 10429, 8405, 524, + 10429, 8405, 556, + 10429, 8405, 622, + 10429, 8405, 638, + 10429, 8405, 652, + 10429, 8405, 670, + 10429, 8405, 884, + 10429, 8405, 974, + 10429, 8405, 1080, + 10429, 8405, 1250, + 10429, 8405, 1612, + 10429, 8405, 2030, + 10429, 8405, 2076, + 10429, 8405, 2126, + 10429, 8405, 2212, + 10429, 8405, 2516, + 10429, 8405, 2678, + 10429, 8405, 2732, + 10429, 8405, 2746, + 10429, 8405, 3146, + 10429, 8405, 5978, + 10429, 8405, 5994, + 10429, 8405, 7593, 0, + 10429, 8405, 8921, 236, + 10429, 8405, 10707, 652, + 10429, 8405, 10721, 196, + 10429, 8405, 11395, 2516, + 10429, 8405, 11900, + 10429, 8717, 4399, 4926, + 10429, 11257, 8405, 510, + 10429, 11257, 8405, 622, + 10429, 11257, 8405, 652, + 10429, 11843, 8405, 510, + 10431, 4093, 5759, 457, 3696, + 10431, 4093, 5759, 778, + 10431, 4093, 5759, 824, + 10431, 4093, 5759, 862, + 10431, 4093, 5759, 1780, + 10431, 4093, 5759, 2386, + 10431, 4093, 5759, 2498, + 10431, 4093, 5759, 3948, + 10431, 4093, 5759, 3954, + 10431, 4093, 5759, 4114, + 10431, 4093, 5759, 4418, + 10431, 4093, 5759, 4536, + 10431, 4093, 5759, 4874, + 10431, 4093, 5759, 5700, + 10431, 4093, 5759, 6090, + 10431, 4093, 5759, 6107, 3706, + 10431, 4093, 5759, 6434, + 10431, 4093, 5759, 6533, 1760, + 10431, 4093, 5759, 6574, + 10431, 4093, 5759, 6712, + 10431, 4093, 5759, 6794, + 10431, 4093, 5759, 7379, 5968, + 10431, 4093, 5759, 7586, + 10431, 4093, 5759, 7593, 742, + 10431, 4093, 5759, 7702, + 10431, 4093, 5759, 7752, + 10431, 4093, 5759, 7830, + 10431, 4093, 5759, 8068, + 10431, 4093, 5759, 8126, + 10431, 4093, 5759, 8270, + 10431, 4093, 5759, 8296, + 10431, 4093, 5759, 8599, 4398, + 10431, 4093, 5759, 8704, + 10431, 4093, 5759, 9036, + 10431, 4093, 5759, 9064, + 10431, 4093, 5759, 9462, + 10431, 4093, 5759, 9568, + 10431, 4093, 5759, 9638, + 10431, 4093, 5759, 10216, + 10431, 4093, 5759, 10316, + 10431, 4093, 5759, 10546, + 10431, 4093, 5759, 10611, 4398, + 10431, 4093, 5759, 10744, + 10431, 4093, 5759, 10753, 7378, + 10431, 4093, 5759, 10767, 9525, 8758, + 10431, 4093, 5759, 11718, + 10433, 5830, + 10445, 11054, + 10452, + 10453, 445, 6741, 568, + 10453, 445, 11621, 568, + 10453, 835, 2091, 11621, 568, + 10453, 6377, 2091, 6741, 568, + 10453, 6377, 2091, 7919, 6741, 568, + 10453, 6377, 7919, 6741, 568, + 10453, 6377, 8167, 5758, + 10453, 6377, 12345, 2091, 6741, 568, + 10453, 6377, 12345, 8167, 5758, + 10453, 7767, 10476, + 10455, 5392, + 10461, 4876, + 10465, 7121, 4848, + 10465, 7121, 7442, + 10465, 7773, 4848, + 10465, 7773, 4849, 721, 7121, 4849, 721, 7121, 7442, + 10465, 7773, 4849, 721, 7121, 7442, + 10465, 7773, 4849, 721, 7773, 7443, 721, 7121, 4848, + 10465, 7773, 4849, 721, 7773, 7443, 721, 7121, 7442, + 10465, 7773, 7442, + 10465, 7773, 7443, 721, 7121, 4848, + 10465, 7773, 7443, 721, 7121, 4849, 721, 7121, 7442, + 10469, 4926, + 10469, 12017, 4926, + 10470, + 10475, 7337, 8774, + 10486, + 10489, 2091, 5758, + 10489, 6408, + 10489, 6409, 6121, 10666, + 10489, 6731, 2510, + 10489, 7390, + 10489, 7708, + 10489, 7709, 8166, + 10489, 8153, 7390, + 10489, 8153, 7391, 11195, 4926, + 10489, 8153, 8759, 2091, 5758, + 10489, 8231, 12108, + 10489, 8849, 7390, + 10489, 9595, 5758, + 10489, 9641, 8225, 6907, 8022, + 10489, 10469, 4926, + 10489, 11224, + 10489, 11767, 9063, 22, + 10504, + 10513, 7821, 5830, + 10513, 7821, 7089, 6622, + 10513, 7821, 8056, + 10514, + 10529, 9898, + 10553, 11621, 568, + 10574, + 10575, 445, 6741, 568, + 10575, 445, 11621, 568, + 10575, 835, 2091, 11621, 568, + 10575, 6377, 2091, 6741, 568, + 10575, 6377, 2091, 7919, 6741, 568, + 10575, 6377, 7919, 6741, 568, + 10575, 6377, 8167, 5758, + 10575, 6377, 12345, 2091, 6741, 568, + 10575, 6377, 12345, 8167, 5758, + 10575, 7767, 10476, + 10579, 428, + 10579, 429, 445, 6741, 568, + 10579, 429, 445, 6741, 569, 6121, 1045, 6376, + 10579, 429, 6121, 2091, 6741, 568, + 10579, 429, 6377, 2091, 6741, 568, + 10579, 429, 6377, 7709, 10374, + 10579, 429, 6377, 7919, 6741, 568, + 10579, 429, 6377, 8167, 5758, + 10579, 6121, 1044, + 10579, 6121, 5445, 5759, 6490, + 10579, 6121, 13061, 5759, 6490, + 10579, 6377, 8762, + 10579, 6377, 10578, + 10579, 6377, 11097, 6434, + 10579, 7991, 721, 8329, 115, 3993, 6121, 8762, + 10579, 7991, 8762, + 10579, 11183, 9718, + 10604, + 10607, 7803, 5759, 16, + 10607, 7803, 5759, 40, + 10607, 8405, 0, + 10607, 8405, 16, + 10607, 8405, 40, + 10607, 8405, 100, + 10607, 8405, 138, + 10607, 8405, 216, + 10607, 8405, 306, + 10607, 8405, 332, + 10607, 8405, 364, + 10607, 8405, 392, + 10607, 8405, 462, + 10607, 8405, 524, + 10607, 8405, 556, + 10607, 8405, 622, + 10607, 8405, 652, + 10607, 8405, 2030, + 10629, 8405, 652, + 10629, 8405, 656, + 10629, 8405, 664, + 10629, 8405, 3006, + 10629, 8405, 3008, + 10629, 8405, 3010, + 10629, 8405, 3014, + 10629, 8405, 3016, + 10629, 8405, 3018, + 10629, 8405, 3020, + 10629, 8405, 3022, + 10629, 8405, 3024, + 10629, 8405, 3026, + 10629, 8405, 3028, + 10629, 8405, 3030, + 10629, 8405, 3032, + 10629, 8405, 3034, + 10629, 8405, 3036, + 10629, 8405, 3038, + 10629, 8405, 3040, + 10629, 8405, 3042, + 10629, 8405, 3044, + 10629, 8405, 3046, + 10629, 8405, 3062, + 10629, 8405, 3291, 6170, + 10629, 8405, 6162, + 10629, 8405, 6164, + 10629, 8405, 6166, + 10629, 8405, 6168, + 10629, 8405, 6170, + 10629, 8405, 6174, + 10629, 8405, 6176, + 10629, 8405, 6180, + 10629, 8405, 6182, + 10629, 8405, 6184, + 10629, 8405, 6186, + 10629, 8405, 6190, + 10629, 8405, 6192, + 10629, 8405, 6194, + 10629, 8405, 7844, + 10629, 8405, 7846, + 10629, 8405, 7848, + 10629, 8405, 7989, 8973, 3018, + 10629, 8405, 7989, 8973, 3020, + 10629, 8405, 8863, 3018, + 10629, 8405, 8863, 3022, + 10629, 8405, 8863, 3032, + 10629, 8405, 8863, 6170, + 10629, 8405, 8863, 6172, + 10629, 8405, 8863, 6176, + 10629, 8405, 8863, 6178, + 10629, 8405, 8863, 6192, + 10629, 8405, 8985, 6192, + 10629, 8405, 11849, 3046, + 10629, 10339, 8405, 12965, 4926, + 10631, 5759, 186, + 10643, 6121, 1045, 6376, + 10643, 6121, 8689, 91, 8004, + 10643, 6121, 10666, + 10644, + 10661, 6129, 9178, + 10661, 8405, 16, + 10661, 8405, 40, + 10661, 8405, 246, + 10661, 8405, 486, + 10661, 8405, 568, + 10661, 8405, 632, + 10661, 8405, 680, + 10661, 8405, 710, + 10661, 8405, 1578, + 10661, 8405, 1612, + 10661, 8405, 1892, + 10661, 8405, 2110, + 10661, 8405, 2574, + 10661, 8405, 2674, + 10661, 8405, 3080, + 10661, 8405, 3252, + 10661, 8405, 3774, + 10661, 8405, 4066, + 10661, 8405, 4538, + 10661, 8405, 5494, + 10661, 8405, 5624, + 10661, 8405, 5698, + 10661, 8405, 6262, + 10661, 8405, 6674, + 10661, 8405, 6822, + 10661, 8405, 6850, + 10661, 8405, 7080, + 10661, 8405, 7422, + 10661, 8405, 7482, + 10661, 8405, 8814, + 10664, + 10665, 6121, 5525, 6706, + 10670, + 10674, + 10677, 761, 6121, 11649, 8758, + 10677, 761, 7991, 7443, 10642, + 10677, 761, 8153, 4849, 11378, + 10677, 761, 8849, 7443, 11378, + 10677, 4215, 4112, + 10677, 4719, 8641, 4926, + 10677, 4719, 8641, 4927, 7121, 4388, + 10677, 4719, 8641, 4927, 7773, 4388, + 10677, 4719, 8641, 6121, 8921, 7605, 4926, + 10677, 4719, 8641, 6121, 8921, 7605, 4927, 7773, 4388, + 10677, 4876, + 10677, 4877, 6121, 8057, 6376, + 10677, 4877, 6121, 8057, 6490, + 10677, 4877, 6121, 8473, 1044, + 10677, 4877, 10982, + 10677, 4923, 6121, 8759, 5758, + 10677, 7708, + 10677, 8963, 4876, + 10677, 10154, + 10677, 12043, 11067, 4926, + 10679, 8744, + 10701, 569, 2681, 9746, + 10708, + 10719, 5238, + 10722, + 10737, 5758, + 10749, 9483, 8775, 1078, + 10749, 9483, 8775, 1135, 12010, + 10749, 9483, 8775, 3268, + 10749, 9483, 8775, 4619, 2020, + 10749, 9483, 8775, 4619, 9884, + 10749, 9483, 8775, 5048, + 10749, 9483, 8775, 5921, 1583, 9000, + 10749, 9483, 8775, 5970, + 10749, 9483, 8775, 6203, 726, + 10749, 9483, 8775, 6203, 4728, + 10749, 9483, 8775, 6387, 3274, + 10749, 9483, 8775, 6387, 4952, + 10749, 9483, 8775, 6387, 5449, 3274, + 10749, 9483, 8775, 6387, 5449, 6866, + 10749, 9483, 8775, 6387, 6866, + 10749, 9483, 8775, 6387, 8470, + 10749, 9483, 8775, 6387, 9886, + 10749, 9483, 8775, 6387, 11022, + 10749, 9483, 8775, 6419, 1135, 2020, + 10749, 9483, 8775, 6419, 12010, + 10749, 9483, 8775, 6426, + 10749, 9483, 8775, 6581, 7892, + 10749, 9483, 8775, 6581, 8366, + 10749, 9483, 8775, 6581, 8728, + 10749, 9483, 8775, 6690, + 10749, 9483, 8775, 6691, 9884, + 10749, 9483, 8775, 7092, + 10749, 9483, 8775, 7329, 2020, + 10749, 9483, 8775, 7329, 6690, + 10749, 9483, 8775, 7329, 12010, + 10749, 9483, 8775, 7398, + 10749, 9483, 8775, 7434, + 10749, 9483, 8775, 7660, + 10749, 9483, 8775, 7678, + 10749, 9483, 8775, 7679, 7928, + 10749, 9483, 8775, 7688, + 10749, 9483, 8775, 7788, + 10749, 9483, 8775, 7837, 8364, + 10749, 9483, 8775, 8094, + 10749, 9483, 8775, 8115, 3269, 1079, 10018, + 10749, 9483, 8775, 8115, 10815, 195, 10018, + 10749, 9483, 8775, 8115, 11863, 5377, 10018, + 10749, 9483, 8775, 8115, 12085, 9775, 10018, + 10749, 9483, 8775, 8115, 12372, + 10749, 9483, 8775, 8115, 13020, + 10749, 9483, 8775, 8171, 12110, + 10749, 9483, 8775, 8171, 12904, + 10749, 9483, 8775, 8199, 9703, 8053, 7786, + 10749, 9483, 8775, 8237, 17, 8949, 13020, + 10749, 9483, 8775, 8237, 5055, 6978, + 10749, 9483, 8775, 8237, 8506, + 10749, 9483, 8775, 8237, 9451, 8053, 10008, + 10749, 9483, 8775, 8237, 9451, 8053, 11684, + 10749, 9483, 8775, 8237, 9703, 8053, 8776, + 10749, 9483, 8775, 8237, 9703, 10007, 144, + 10749, 9483, 8775, 8237, 9884, + 10749, 9483, 8775, 8237, 9885, 9999, 6980, + 10749, 9483, 8775, 8237, 10811, 144, + 10749, 9483, 8775, 8237, 10811, 310, + 10749, 9483, 8775, 8237, 10811, 405, 726, + 10749, 9483, 8775, 8237, 10811, 405, 4728, + 10749, 9483, 8775, 8237, 10811, 462, + 10749, 9483, 8775, 8237, 10811, 678, + 10749, 9483, 8775, 8237, 10811, 5048, + 10749, 9483, 8775, 8237, 11609, 10710, + 10749, 9483, 8775, 8249, 8114, + 10749, 9483, 8775, 8249, 8948, + 10749, 9483, 8775, 8265, 2021, 726, + 10749, 9483, 8775, 8265, 2021, 4728, + 10749, 9483, 8775, 8265, 9884, + 10749, 9483, 8775, 8265, 12989, 6680, + 10749, 9483, 8775, 8265, 12989, 9888, + 10749, 9483, 8775, 8321, 8801, 11038, + 10749, 9483, 8775, 8341, 10648, + 10749, 9483, 8775, 8364, + 10749, 9483, 8775, 8365, 726, + 10749, 9483, 8775, 8365, 4728, + 10749, 9483, 8775, 8397, 1079, 9090, + 10749, 9483, 8775, 8397, 4159, 9092, + 10749, 9483, 8775, 8397, 7735, 9090, + 10749, 9483, 8775, 8397, 9359, 9092, + 10749, 9483, 8775, 8397, 10615, 9090, + 10749, 9483, 8775, 8475, 4618, + 10749, 9483, 8775, 8537, 2020, + 10749, 9483, 8775, 8537, 9884, + 10749, 9483, 8775, 8538, + 10749, 9483, 8775, 8557, 9884, + 10749, 9483, 8775, 8587, 2020, + 10749, 9483, 8775, 8587, 9884, + 10749, 9483, 8775, 8614, + 10749, 9483, 8775, 8686, + 10749, 9483, 8775, 8687, 2020, + 10749, 9483, 8775, 8748, + 10749, 9483, 8775, 8798, + 10749, 9483, 8775, 8850, + 10749, 9483, 8775, 8909, 2020, + 10749, 9483, 8775, 8909, 6690, + 10749, 9483, 8775, 8909, 12010, + 10749, 9483, 8775, 8949, 3269, 1079, 10018, + 10749, 9483, 8775, 8949, 10815, 195, 10018, + 10749, 9483, 8775, 8949, 11863, 5377, 10018, + 10749, 9483, 8775, 8949, 12085, 9775, 10018, + 10749, 9483, 8775, 8949, 12372, + 10749, 9483, 8775, 8954, + 10749, 9483, 8775, 9009, 144, + 10749, 9483, 8775, 9009, 216, + 10749, 9483, 8775, 9009, 310, + 10749, 9483, 8775, 9009, 404, + 10749, 9483, 8775, 9009, 462, + 10749, 9483, 8775, 9009, 678, + 10749, 9483, 8775, 9009, 2882, + 10749, 9483, 8775, 9080, + 10749, 9483, 8775, 9160, + 10749, 9483, 8775, 9260, + 10749, 9483, 8775, 9267, 1583, 8237, 2882, + 10749, 9483, 8775, 9350, + 10749, 9483, 8775, 9399, 2021, 726, + 10749, 9483, 8775, 9399, 2021, 4728, + 10749, 9483, 8775, 9399, 2021, 4954, + 10749, 9483, 8775, 9399, 9884, + 10749, 9483, 8775, 9412, + 10749, 9483, 8775, 9415, 2020, + 10749, 9483, 8775, 9415, 3250, + 10749, 9483, 8775, 9415, 9884, + 10749, 9483, 8775, 9420, + 10749, 9483, 8775, 9440, + 10749, 9483, 8775, 9584, + 10749, 9483, 8775, 9586, + 10749, 9483, 8775, 9620, + 10749, 9483, 8775, 9740, + 10749, 9483, 8775, 9741, 9874, + 10749, 9483, 8775, 9755, 2020, + 10749, 9483, 8775, 9755, 4957, 9742, + 10749, 9483, 8775, 9755, 9884, + 10749, 9483, 8775, 9756, + 10749, 9483, 8775, 9774, + 10749, 9483, 8775, 9790, + 10749, 9483, 8775, 9815, 9884, + 10749, 9483, 8775, 9848, + 10749, 9483, 8775, 9873, 2020, + 10749, 9483, 8775, 9873, 9884, + 10749, 9483, 8775, 9876, + 10749, 9483, 8775, 9936, + 10749, 9483, 8775, 9943, 2020, + 10749, 9483, 8775, 9943, 9884, + 10749, 9483, 8775, 10005, 3269, 7168, + 10749, 9483, 8775, 10005, 3269, 8464, + 10749, 9483, 8775, 10005, 6690, + 10749, 9483, 8775, 10005, 9778, + 10749, 9483, 8775, 10010, + 10749, 9483, 8775, 10011, 12989, 6680, + 10749, 9483, 8775, 10011, 12989, 9889, 726, + 10749, 9483, 8775, 10011, 12989, 9889, 4728, + 10749, 9483, 8775, 10013, 222, + 10749, 9483, 8775, 10164, + 10749, 9483, 8775, 10250, + 10749, 9483, 8775, 10284, + 10749, 9483, 8775, 10288, + 10749, 9483, 8775, 10289, 3250, + 10749, 9483, 8775, 10290, + 10749, 9483, 8775, 10292, + 10749, 9483, 8775, 10325, 3249, 8613, 6978, + 10749, 9483, 8775, 10325, 3249, 9997, 6978, + 10749, 9483, 8775, 10325, 7785, 6978, + 10749, 9483, 8775, 10325, 8613, 6978, + 10749, 9483, 8775, 10325, 8855, 6978, + 10749, 9483, 8775, 10325, 9429, 6978, + 10749, 9483, 8775, 10325, 9597, 6978, + 10749, 9483, 8775, 10325, 9597, 10617, 6978, + 10749, 9483, 8775, 10325, 9997, 6978, + 10749, 9483, 8775, 10325, 10617, 6978, + 10749, 9483, 8775, 10325, 10617, 9429, 6978, + 10749, 9483, 8775, 10325, 11372, + 10749, 9483, 8775, 10325, 11743, 6978, + 10749, 9483, 8775, 10412, + 10749, 9483, 8775, 10418, + 10749, 9483, 8775, 10419, 2020, + 10749, 9483, 8775, 10500, + 10749, 9483, 8775, 10525, 7946, + 10749, 9483, 8775, 10525, 7947, 9174, + 10749, 9483, 8775, 10525, 7947, 10646, + 10749, 9483, 8775, 10525, 7947, 11852, + 10749, 9483, 8775, 10525, 9778, + 10749, 9483, 8775, 10525, 9779, 9174, + 10749, 9483, 8775, 10525, 9779, 10646, + 10749, 9483, 8775, 10525, 9779, 11852, + 10749, 9483, 8775, 10618, + 10749, 9483, 8775, 10649, 2020, + 10749, 9483, 8775, 10649, 3250, + 10749, 9483, 8775, 10649, 9884, + 10749, 9483, 8775, 10813, 450, + 10749, 9483, 8775, 10974, + 10749, 9483, 8775, 10991, 10008, + 10749, 9483, 8775, 10991, 11684, + 10749, 9483, 8775, 10991, 12360, + 10749, 9483, 8775, 11046, + 10749, 9483, 8775, 11074, + 10749, 9483, 8775, 11078, + 10749, 9483, 8775, 11079, 2021, 726, + 10749, 9483, 8775, 11079, 2021, 4728, + 10749, 9483, 8775, 11079, 2021, 4954, + 10749, 9483, 8775, 11079, 9884, + 10749, 9483, 8775, 11082, + 10749, 9483, 8775, 11149, 2020, + 10749, 9483, 8775, 11149, 9884, + 10749, 9483, 8775, 11188, + 10749, 9483, 8775, 11189, 2020, + 10749, 9483, 8775, 11348, + 10749, 9483, 8775, 11374, + 10749, 9483, 8775, 11402, + 10749, 9483, 8775, 11403, 6690, + 10749, 9483, 8775, 11416, + 10749, 9483, 8775, 11421, 8801, 11038, + 10749, 9483, 8775, 11421, 11347, 2020, + 10749, 9483, 8775, 11422, + 10749, 9483, 8775, 11423, 2020, + 10749, 9483, 8775, 11423, 6690, + 10749, 9483, 8775, 11602, + 10749, 9483, 8775, 11643, 27, 7928, + 10749, 9483, 8775, 11643, 27, 9172, + 10749, 9483, 8775, 11654, + 10749, 9483, 8775, 11656, + 10749, 9483, 8775, 12111, 2020, + 10749, 9483, 8775, 12111, 9884, + 10749, 9483, 8775, 12112, + 10749, 9483, 8775, 12113, 2020, + 10749, 9483, 8775, 12113, 9884, + 10749, 9483, 8775, 12120, + 10749, 9483, 8775, 12365, 1126, + 10749, 9483, 8775, 12365, 1134, + 10749, 9483, 8775, 12400, + 10749, 9483, 8775, 12474, + 10749, 9483, 8775, 12872, + 10749, 9483, 8775, 12904, + 10749, 9483, 8775, 13052, + 10749, 9483, 8775, 13082, + 10749, 9483, 8775, 13084, + 10749, 9483, 8775, 13186, + 10749, 9483, 8775, 13206, + 10749, 9483, 8775, 13208, + 10749, 9483, 8775, 13216, + 10749, 9483, 8775, 13220, + 10749, 9483, 8775, 13222, + 10749, 9483, 8775, 13352, + 10749, 9483, 8775, 13400, + 10749, 9483, 8775, 13404, + 10750, + 10759, 2690, + 10763, 2725, 11791, 6434, + 10763, 5385, 8057, 6434, + 10763, 8065, 8057, 6434, + 10763, 8241, 8057, 6434, + 10763, 9115, 10260, + 10763, 10260, + 10767, 47, 6376, + 10767, 47, 6490, + 10767, 283, 6490, + 10767, 601, 5877, 6490, + 10767, 603, 6376, + 10767, 605, 6376, + 10767, 1045, 6376, + 10767, 1045, 6377, 7442, + 10767, 1045, 6490, + 10767, 1809, 4876, + 10767, 2091, 7709, 6376, + 10767, 4117, 5877, 6490, + 10767, 4215, 4113, 6376, + 10767, 4531, 6376, + 10767, 4536, + 10767, 4849, 4389, 5551, 6376, + 10767, 4849, 4389, 5551, 6490, + 10767, 4849, 5877, 6490, + 10767, 4849, 6409, 6376, + 10767, 4849, 6409, 6490, + 10767, 4849, 6435, 6376, + 10767, 4849, 6435, 6490, + 10767, 4849, 7443, 6435, 6376, + 10767, 4849, 7443, 6435, 6490, + 10767, 4849, 9327, 6376, + 10767, 4849, 10717, 6376, + 10767, 4849, 10717, 6490, + 10767, 4895, 8153, 9719, 9548, + 10767, 4895, 8759, 9548, + 10767, 4895, 9719, 9548, + 10767, 4895, 10677, 4877, 9548, + 10767, 5445, 5759, 6490, + 10767, 5551, 6376, + 10767, 5551, 6490, + 10767, 5551, 9548, + 10767, 6115, 8015, 6376, + 10767, 6379, 5965, 4926, + 10767, 6379, 7908, + 10767, 6379, 7909, 6490, + 10767, 6516, + 10767, 6517, 6490, + 10767, 6546, + 10767, 6547, 6490, + 10767, 6617, 6376, + 10767, 6617, 6377, 7442, + 10767, 6617, 6490, + 10767, 6875, 5965, 4926, + 10767, 6875, 7908, + 10767, 6875, 7909, 6490, + 10767, 6879, 9412, + 10767, 6879, 9483, 9796, + 10767, 6879, 9483, 11164, + 10767, 6879, 9483, 11358, + 10767, 6879, 10809, 7724, + 10767, 6879, 12120, + 10767, 6879, 13036, + 10767, 7089, 7593, 8405, 0, + 10767, 7089, 7593, 8405, 4, + 10767, 7089, 7593, 8405, 5, 9072, + 10767, 7089, 7593, 8405, 6, + 10767, 7089, 7593, 8405, 8, + 10767, 7089, 7593, 8405, 12, + 10767, 7089, 7593, 8405, 14, + 10767, 7089, 7593, 8405, 16, + 10767, 7089, 7593, 8405, 20, + 10767, 7089, 7593, 8405, 22, + 10767, 7089, 7593, 8405, 24, + 10767, 7089, 7593, 8405, 26, + 10767, 7089, 7593, 8405, 28, + 10767, 7089, 7593, 8405, 34, + 10767, 7089, 7593, 8405, 35, 6490, + 10767, 7089, 7593, 8405, 35, 9642, + 10767, 7089, 7593, 8405, 36, + 10767, 7089, 7593, 8405, 38, + 10767, 7089, 7593, 8405, 40, + 10767, 7089, 7593, 8405, 42, + 10767, 7089, 7593, 8405, 46, + 10767, 7089, 7593, 8405, 50, + 10767, 7089, 7593, 8405, 66, + 10767, 7089, 7593, 8405, 82, + 10767, 7089, 7593, 8405, 94, + 10767, 7089, 7593, 8405, 1130, + 10767, 7089, 7593, 8405, 4895, 36, + 10767, 7089, 7593, 8405, 9365, 6, + 10767, 7089, 7593, 8405, 10997, 5385, 1, 6376, + 10767, 7089, 8405, 7593, 9063, 12, + 10767, 7089, 8405, 7593, 9063, 22, + 10767, 7089, 8405, 7593, 9063, 24, + 10767, 7089, 8405, 7593, 9063, 26, + 10767, 7089, 8405, 7593, 9063, 34, + 10767, 7173, 5759, 6490, + 10767, 7443, 4389, 5551, 6376, + 10767, 7443, 4389, 5551, 6490, + 10767, 7443, 5877, 6490, + 10767, 7443, 6435, 6376, + 10767, 7443, 6435, 6490, + 10767, 7443, 9327, 6376, + 10767, 7443, 10717, 721, 601, 10717, 6490, + 10767, 7443, 10717, 721, 4117, 10717, 6490, + 10767, 7443, 10717, 6376, + 10767, 7443, 10717, 6490, + 10767, 7551, 8759, 9548, + 10767, 7551, 9719, 9548, + 10767, 7551, 10677, 4877, 9548, + 10767, 7601, 6490, + 10767, 7695, 4113, 6376, + 10767, 7708, + 10767, 7709, 6490, + 10767, 7709, 9548, + 10767, 7919, 6741, 569, 6376, + 10767, 8015, 6376, + 10767, 8015, 6490, + 10767, 8151, 6379, 7908, + 10767, 8151, 6875, 7908, + 10767, 8153, 1809, 4876, + 10767, 8153, 5551, 6490, + 10767, 8153, 6379, 7908, + 10767, 8153, 6516, + 10767, 8153, 6517, 6490, + 10767, 8153, 6875, 7908, + 10767, 8153, 7708, + 10767, 8153, 7709, 4849, 4388, + 10767, 8153, 7709, 7443, 4388, + 10767, 8153, 8432, + 10767, 8153, 8433, 6490, + 10767, 8153, 10267, 6516, + 10767, 8153, 10388, + 10767, 8153, 10677, 4877, 6376, + 10767, 8153, 10677, 4877, 6490, + 10767, 8153, 10677, 8759, 9548, + 10767, 8153, 11449, 6376, + 10767, 8153, 11765, 6435, 6490, + 10767, 8167, 5759, 6490, + 10767, 8432, + 10767, 8433, 4849, 4388, + 10767, 8433, 6490, + 10767, 8433, 7443, 4388, + 10767, 8534, + 10767, 8535, 6376, + 10767, 8745, 6490, + 10767, 8849, 10668, + 10767, 8869, 6617, 6376, + 10767, 8963, 6376, + 10767, 8963, 6490, + 10767, 8999, 8774, + 10767, 9072, + 10767, 9284, + 10767, 9633, 9719, 9548, + 10767, 9663, 6490, + 10767, 9811, 6435, 6490, + 10767, 9899, 6376, + 10767, 9899, 6490, + 10767, 9977, 2671, 10335, 5758, + 10767, 9977, 6655, 10438, + 10767, 9977, 7399, 10438, + 10767, 9977, 7716, + 10767, 9977, 7804, + 10767, 9977, 8342, + 10767, 9977, 8405, 0, + 10767, 9977, 8405, 28, + 10767, 9977, 8405, 102, + 10767, 9977, 8405, 142, + 10767, 9977, 8405, 172, + 10767, 9977, 8405, 174, + 10767, 9977, 8405, 176, + 10767, 9977, 8405, 182, + 10767, 9977, 8405, 184, + 10767, 9977, 8405, 236, + 10767, 9977, 8405, 258, + 10767, 9977, 8405, 306, + 10767, 9977, 8405, 468, + 10767, 9977, 8405, 560, + 10767, 9977, 8405, 612, + 10767, 9977, 8405, 664, + 10767, 9977, 8405, 672, + 10767, 9977, 8405, 807, 3096, + 10767, 9977, 8405, 886, + 10767, 9977, 8405, 1262, + 10767, 9977, 8405, 2516, + 10767, 9977, 8405, 2734, + 10767, 9977, 8405, 3038, + 10767, 9977, 8405, 3148, + 10767, 9977, 8405, 4198, + 10767, 9977, 8405, 6696, + 10767, 9977, 8405, 6748, + 10767, 9977, 8405, 7522, + 10767, 9977, 8405, 8425, 3096, + 10767, 9977, 8405, 10269, 0, + 10767, 9977, 8405, 10269, 807, 3096, + 10767, 9977, 8405, 11127, 592, + 10767, 9977, 9345, 10335, 5758, + 10767, 9977, 9345, 11363, 5758, + 10767, 9977, 9578, + 10767, 9977, 10335, 5758, + 10767, 9977, 10442, + 10767, 9977, 10625, 10335, 5758, + 10767, 9977, 13062, + 10767, 10223, 8330, + 10767, 10267, 6516, + 10767, 10267, 6517, 6490, + 10767, 10267, 8015, 6490, + 10767, 10267, 8153, 3273, 6490, + 10767, 10301, 4849, 4388, + 10767, 10301, 7443, 4388, + 10767, 10388, + 10767, 10489, 6617, 6376, + 10767, 10677, 4877, 6376, + 10767, 10677, 4877, 6490, + 10767, 10677, 7708, + 10767, 10763, 5551, 9548, + 10767, 10763, 6435, 6376, + 10767, 10804, + 10767, 10805, 6490, + 10767, 10969, 8056, + 10767, 10969, 8057, 10728, + 10767, 10969, 8354, + 10767, 10969, 8676, + 10767, 10969, 8744, + 10767, 10969, 8899, 10441, 10642, + 10767, 10969, 9158, + 10767, 11097, 6435, 9548, + 10767, 11097, 9327, 6121, 3713, 10958, + 10767, 11215, 4531, 6490, + 10767, 11449, 7908, + 10767, 11449, 7909, 6490, + 10767, 11459, 8432, + 10767, 11647, 6376, + 10767, 11765, 9327, 6121, 3713, 10958, + 10767, 11845, 4926, + 10767, 11900, + 10767, 12107, 4531, 6490, + 10767, 12394, + 10767, 12416, + 10767, 12470, + 10767, 12498, + 10767, 12500, + 10767, 12502, + 10767, 12901, 5551, 9548, + 10767, 12901, 6435, 6376, + 10767, 13356, + 10767, 13360, + 10767, 13365, 8921, 7605, 4926, + 10767, 13365, 12341, 7605, 4926, + 10771, 6121, 1045, 6376, + 10783, 5758, + 10789, 5759, 0, + 10789, 5759, 1, 7711, 0, + 10789, 5759, 1, 7711, 236, + 10789, 5759, 1, 7711, 750, + 10789, 5759, 1, 7711, 1482, + 10789, 5759, 1, 7711, 2486, + 10789, 5759, 1, 7711, 4241, 5898, + 10789, 5759, 1, 7711, 5030, + 10789, 5759, 1, 7711, 7077, 4358, + 10789, 5759, 8, + 10789, 5759, 9, 5387, 9, 2111, 5387, 2110, + 10789, 5759, 9, 7711, 2194, + 10789, 5759, 16, + 10789, 5759, 17, 0, + 10789, 5759, 40, + 10789, 5759, 41, 41, 40, + 10789, 5759, 41, 1304, + 10789, 5759, 41, 5387, 41, 41, 10489, 5387, 41, 10488, + 10789, 5759, 41, 5387, 41, 463, 5387, 463, 1221, 5387, 1220, + 10789, 5759, 41, 5387, 41, 2593, 5387, 2592, + 10789, 5759, 54, + 10789, 5759, 60, + 10789, 5759, 61, 4358, + 10789, 5759, 61, 7711, 41, 5445, 41, 5445, 40, + 10789, 5759, 61, 7711, 236, + 10789, 5759, 61, 7711, 1212, + 10789, 5759, 61, 7711, 1483, 4358, + 10789, 5759, 61, 7711, 3280, + 10789, 5759, 61, 7711, 4125, 4358, + 10789, 5759, 61, 7711, 4241, 5898, + 10789, 5759, 61, 7711, 4606, + 10789, 5759, 61, 7711, 7074, + 10789, 5759, 61, 7711, 7534, + 10789, 5759, 64, + 10789, 5759, 74, + 10789, 5759, 75, 7711, 6746, + 10789, 5759, 75, 7711, 7545, 5445, 4338, + 10789, 5759, 76, + 10789, 5759, 77, 7711, 76, + 10789, 5759, 77, 7711, 236, + 10789, 5759, 77, 7711, 314, + 10789, 5759, 77, 7711, 2518, + 10789, 5759, 77, 7711, 2836, + 10789, 5759, 77, 7711, 4088, + 10789, 5759, 77, 7711, 4338, + 10789, 5759, 77, 7711, 4706, + 10789, 5759, 80, + 10789, 5759, 81, 5387, 80, + 10789, 5759, 81, 5445, 5043, 9732, + 10789, 5759, 81, 5445, 5043, 10377, 81, 5445, 5042, + 10789, 5759, 81, 7695, 7710, + 10789, 5759, 100, + 10789, 5759, 106, + 10789, 5759, 107, 7711, 0, + 10789, 5759, 107, 7711, 1220, + 10789, 5759, 107, 7711, 1483, 4358, + 10789, 5759, 112, + 10789, 5759, 113, 5387, 113, 60, + 10789, 5759, 113, 5387, 113, 596, + 10789, 5759, 113, 9967, 112, + 10789, 5759, 138, + 10789, 5759, 144, + 10789, 5759, 152, + 10789, 5759, 153, 4358, + 10789, 5759, 153, 5387, 152, + 10789, 5759, 153, 9684, + 10789, 5759, 158, + 10789, 5759, 159, 7711, 1, 5445, 237, 5445, 138, + 10789, 5759, 159, 7711, 40, + 10789, 5759, 159, 7711, 374, + 10789, 5759, 159, 7711, 1220, + 10789, 5759, 159, 7711, 2488, + 10789, 5759, 159, 7711, 2518, + 10789, 5759, 172, + 10789, 5759, 176, + 10789, 5759, 177, 7711, 368, + 10789, 5759, 177, 7711, 4240, + 10789, 5759, 177, 7711, 4241, 5898, + 10789, 5759, 177, 9732, + 10789, 5759, 177, 9967, 176, + 10789, 5759, 177, 10377, 176, + 10789, 5759, 216, + 10789, 5759, 217, 4358, + 10789, 5759, 224, + 10789, 5759, 225, 7711, 8, + 10789, 5759, 225, 7711, 40, + 10789, 5759, 225, 9967, 224, + 10789, 5759, 230, + 10789, 5759, 231, 9967, 230, + 10789, 5759, 236, + 10789, 5759, 237, 4358, + 10789, 5759, 237, 5898, + 10789, 5759, 242, + 10789, 5759, 243, 7711, 40, + 10789, 5759, 243, 7711, 736, + 10789, 5759, 243, 7711, 750, + 10789, 5759, 243, 7711, 1206, + 10789, 5759, 243, 7711, 1632, + 10789, 5759, 243, 7711, 2110, + 10789, 5759, 243, 7711, 2518, + 10789, 5759, 243, 7711, 3280, + 10789, 5759, 243, 7711, 4094, + 10789, 5759, 250, + 10789, 5759, 256, + 10789, 5759, 262, + 10789, 5759, 270, + 10789, 5759, 271, 7711, 4241, 5898, + 10789, 5759, 272, + 10789, 5759, 273, 7711, 5880, + 10789, 5759, 273, 9732, + 10789, 5759, 273, 9967, 272, + 10789, 5759, 273, 10377, 272, + 10789, 5759, 274, + 10789, 5759, 280, + 10789, 5759, 306, + 10789, 5759, 307, 7711, 0, + 10789, 5759, 307, 7711, 40, + 10789, 5759, 307, 7711, 64, + 10789, 5759, 307, 7711, 65, 5445, 1682, + 10789, 5759, 307, 7711, 106, + 10789, 5759, 307, 7711, 216, + 10789, 5759, 307, 7711, 224, + 10789, 5759, 307, 7711, 230, + 10789, 5759, 307, 7711, 272, + 10789, 5759, 307, 7711, 314, + 10789, 5759, 307, 7711, 340, + 10789, 5759, 307, 7711, 354, + 10789, 5759, 307, 7711, 368, + 10789, 5759, 307, 7711, 369, 5445, 152, + 10789, 5759, 307, 7711, 369, 5445, 224, + 10789, 5759, 307, 7711, 369, 5445, 560, + 10789, 5759, 307, 7711, 374, + 10789, 5759, 307, 7711, 375, 5445, 7284, + 10789, 5759, 307, 7711, 396, + 10789, 5759, 307, 7711, 476, + 10789, 5759, 307, 7711, 520, + 10789, 5759, 307, 7711, 524, + 10789, 5759, 307, 7711, 580, + 10789, 5759, 307, 7711, 588, + 10789, 5759, 307, 7711, 676, + 10789, 5759, 307, 7711, 750, + 10789, 5759, 307, 7711, 760, + 10789, 5759, 307, 7711, 1212, + 10789, 5759, 307, 7711, 1220, + 10789, 5759, 307, 7711, 1221, 5445, 5663, 5445, 0, + 10789, 5759, 307, 7711, 1482, + 10789, 5759, 307, 7711, 1584, + 10789, 5759, 307, 7711, 1624, + 10789, 5759, 307, 7711, 2110, + 10789, 5759, 307, 7711, 2494, + 10789, 5759, 307, 7711, 2516, + 10789, 5759, 307, 7711, 2518, + 10789, 5759, 307, 7711, 2524, + 10789, 5759, 307, 7711, 2530, + 10789, 5759, 307, 7711, 2654, + 10789, 5759, 307, 7711, 2836, + 10789, 5759, 307, 7711, 3280, + 10789, 5759, 307, 7711, 4166, + 10789, 5759, 307, 7711, 4241, 5898, + 10789, 5759, 307, 7711, 4334, + 10789, 5759, 307, 7711, 4339, 5445, 2494, + 10789, 5759, 307, 7711, 4339, 9967, 4338, + 10789, 5759, 307, 7711, 4366, + 10789, 5759, 307, 7711, 5692, + 10789, 5759, 307, 7711, 6049, 7711, 462, + 10789, 5759, 307, 7711, 6464, + 10789, 5759, 307, 7711, 6746, + 10789, 5759, 307, 7711, 7648, + 10789, 5759, 314, + 10789, 5759, 315, 7711, 40, + 10789, 5759, 315, 7711, 588, + 10789, 5759, 315, 7711, 750, + 10789, 5759, 326, + 10789, 5759, 327, 5387, 243, 7711, 3281, 327, 5387, 243, 7711, 3280, + 10789, 5759, 332, + 10789, 5759, 340, + 10789, 5759, 354, + 10789, 5759, 355, 7711, 750, + 10789, 5759, 364, + 10789, 5759, 365, 4358, + 10789, 5759, 365, 7711, 5880, + 10789, 5759, 368, + 10789, 5759, 374, + 10789, 5759, 384, + 10789, 5759, 385, 5387, 384, + 10789, 5759, 392, + 10789, 5759, 396, + 10789, 5759, 397, 7711, 0, + 10789, 5759, 397, 7711, 588, + 10789, 5759, 397, 9684, + 10789, 5759, 404, + 10789, 5759, 405, 7711, 8, + 10789, 5759, 416, + 10789, 5759, 462, + 10789, 5759, 476, + 10789, 5759, 477, 7711, 0, + 10789, 5759, 477, 7711, 8, + 10789, 5759, 477, 7711, 16, + 10789, 5759, 477, 7711, 40, + 10789, 5759, 477, 7711, 60, + 10789, 5759, 477, 7711, 106, + 10789, 5759, 477, 7711, 112, + 10789, 5759, 477, 7711, 256, + 10789, 5759, 477, 7711, 580, + 10789, 5759, 477, 9967, 476, + 10789, 5759, 510, + 10789, 5759, 514, + 10789, 5759, 520, + 10789, 5759, 524, + 10789, 5759, 532, + 10789, 5759, 533, 4358, + 10789, 5759, 546, + 10789, 5759, 547, 5387, 546, + 10789, 5759, 556, + 10789, 5759, 557, 4358, + 10789, 5759, 557, 7711, 242, + 10789, 5759, 557, 7711, 374, + 10789, 5759, 557, 9898, + 10789, 5759, 560, + 10789, 5759, 561, 4358, + 10789, 5759, 564, + 10789, 5759, 565, 5898, + 10789, 5759, 576, + 10789, 5759, 580, + 10789, 5759, 584, + 10789, 5759, 588, + 10789, 5759, 589, 4358, + 10789, 5759, 589, 7711, 41, 5445, 41, 5445, 40, + 10789, 5759, 589, 7711, 41, 5445, 41, 5445, 41, 4358, + 10789, 5759, 589, 7711, 374, + 10789, 5759, 589, 7711, 750, + 10789, 5759, 589, 8374, + 10789, 5759, 589, 9684, + 10789, 5759, 589, 9685, 7711, 750, + 10789, 5759, 594, + 10789, 5759, 595, 7711, 40, + 10789, 5759, 595, 7711, 369, 5445, 138, + 10789, 5759, 595, 7711, 5662, + 10789, 5759, 595, 7711, 7074, + 10789, 5759, 596, + 10789, 5759, 597, 4358, + 10789, 5759, 602, + 10789, 5759, 603, 9684, + 10789, 5759, 603, 9967, 602, + 10789, 5759, 670, + 10789, 5759, 671, 5898, + 10789, 5759, 671, 9733, 7711, 1696, + 10789, 5759, 676, + 10789, 5759, 677, 5387, 676, + 10789, 5759, 680, + 10789, 5759, 702, + 10789, 5759, 703, 7711, 369, 5445, 176, + 10789, 5759, 703, 7711, 4241, 5898, + 10789, 5759, 703, 7711, 5662, + 10789, 5759, 703, 7711, 5880, + 10789, 5759, 703, 7711, 6464, + 10789, 5759, 736, + 10789, 5759, 737, 4703, 5898, + 10789, 5759, 737, 5387, 737, 5387, 736, + 10789, 5759, 737, 5387, 737, 5387, 737, 9967, 737, 5387, 737, 5387, 736, + 10789, 5759, 737, 5387, 737, 6013, 5387, 6013, 6013, 5387, 6013, 2194, + 10789, 5759, 737, 6313, 5898, + 10789, 5759, 750, + 10789, 5759, 754, + 10789, 5759, 755, 5387, 754, + 10789, 5759, 760, + 10789, 5759, 832, + 10789, 5759, 958, + 10789, 5759, 959, 8361, 7711, 1, 5445, 4928, + 10789, 5759, 959, 8361, 7711, 106, + 10789, 5759, 959, 8361, 7711, 216, + 10789, 5759, 959, 8361, 7711, 217, 5445, 4928, + 10789, 5759, 959, 8361, 7711, 224, + 10789, 5759, 959, 8361, 7711, 236, + 10789, 5759, 959, 8361, 7711, 280, + 10789, 5759, 959, 8361, 7711, 281, 5445, 354, + 10789, 5759, 959, 8361, 7711, 332, + 10789, 5759, 959, 8361, 7711, 354, + 10789, 5759, 959, 8361, 7711, 355, 5445, 7138, + 10789, 5759, 959, 8361, 7711, 396, + 10789, 5759, 959, 8361, 7711, 532, + 10789, 5759, 959, 8361, 7711, 581, 5445, 4334, + 10789, 5759, 959, 8361, 7711, 1304, + 10789, 5759, 959, 8361, 7711, 1584, + 10789, 5759, 959, 8361, 7711, 1822, + 10789, 5759, 959, 8361, 7711, 2195, 5445, 2194, + 10789, 5759, 959, 8361, 7711, 2836, + 10789, 5759, 959, 8361, 7711, 3256, + 10789, 5759, 959, 8361, 7711, 4334, + 10789, 5759, 959, 8361, 7711, 5880, + 10789, 5759, 959, 8361, 7711, 6464, + 10789, 5759, 962, + 10789, 5759, 966, + 10789, 5759, 1006, + 10789, 5759, 1010, + 10789, 5759, 1011, 7711, 2518, + 10789, 5759, 1012, + 10789, 5759, 1013, 8339, 41, 4359, 4094, + 10789, 5759, 1050, + 10789, 5759, 1051, 7711, 4166, + 10789, 5759, 1052, + 10789, 5759, 1054, + 10789, 5759, 1060, + 10789, 5759, 1202, + 10789, 5759, 1203, 5387, 1202, + 10789, 5759, 1203, 7711, 1, 5445, 139, 5445, 236, + 10789, 5759, 1203, 7711, 1, 5445, 236, + 10789, 5759, 1203, 7711, 1, 5445, 1482, + 10789, 5759, 1203, 7711, 40, + 10789, 5759, 1203, 7711, 80, + 10789, 5759, 1203, 7711, 138, + 10789, 5759, 1203, 7711, 144, + 10789, 5759, 1203, 7711, 172, + 10789, 5759, 1203, 7711, 173, 5445, 332, + 10789, 5759, 1203, 7711, 176, + 10789, 5759, 1203, 7711, 177, 7711, 4241, 5898, + 10789, 5759, 1203, 7711, 224, + 10789, 5759, 1203, 7711, 237, 5445, 355, 5445, 4166, + 10789, 5759, 1203, 7711, 243, 5445, 340, + 10789, 5759, 1203, 7711, 332, + 10789, 5759, 1203, 7711, 369, 5445, 176, + 10789, 5759, 1203, 7711, 374, + 10789, 5759, 1203, 7711, 462, + 10789, 5759, 1203, 7711, 588, + 10789, 5759, 1203, 7711, 589, 5445, 152, + 10789, 5759, 1203, 7711, 703, 5899, 5445, 2636, + 10789, 5759, 1203, 7711, 736, + 10789, 5759, 1203, 7711, 750, + 10789, 5759, 1203, 7711, 761, 5445, 510, + 10789, 5759, 1203, 7711, 832, + 10789, 5759, 1203, 7711, 833, 5445, 510, + 10789, 5759, 1203, 7711, 1011, 7711, 2518, + 10789, 5759, 1203, 7711, 1050, + 10789, 5759, 1203, 7711, 1220, + 10789, 5759, 1203, 7711, 1272, + 10789, 5759, 1203, 7711, 1273, 5445, 0, + 10789, 5759, 1203, 7711, 1344, + 10789, 5759, 1203, 7711, 1345, 5445, 332, + 10789, 5759, 1203, 7711, 1483, 4358, + 10789, 5759, 1203, 7711, 1499, 5445, 251, 5445, 736, + 10789, 5759, 1203, 7711, 1584, + 10789, 5759, 1203, 7711, 1624, + 10789, 5759, 1203, 7711, 1625, 5445, 1736, + 10789, 5759, 1203, 7711, 1683, 5445, 80, + 10789, 5759, 1203, 7711, 2110, + 10789, 5759, 1203, 7711, 2111, 5387, 2110, + 10789, 5759, 1203, 7711, 2488, + 10789, 5759, 1203, 7711, 2494, + 10789, 5759, 1203, 7711, 2518, + 10789, 5759, 1203, 7711, 2519, 5445, 2766, + 10789, 5759, 1203, 7711, 2584, + 10789, 5759, 1203, 7711, 3281, 5445, 1212, + 10789, 5759, 1203, 7711, 4241, 5898, + 10789, 5759, 1203, 7711, 4335, 5445, 546, + 10789, 5759, 1203, 7711, 4544, + 10789, 5759, 1203, 7711, 5692, + 10789, 5759, 1203, 7711, 5880, + 10789, 5759, 1203, 7711, 8338, + 10789, 5759, 1206, + 10789, 5759, 1207, 5387, 1207, 1221, 5387, 1220, + 10789, 5759, 1212, + 10789, 5759, 1213, 1207, 5387, 1207, 1221, 5387, 1220, + 10789, 5759, 1214, + 10789, 5759, 1216, + 10789, 5759, 1220, + 10789, 5759, 1272, + 10789, 5759, 1273, 5387, 1272, + 10789, 5759, 1273, 9967, 1272, + 10789, 5759, 1302, + 10789, 5759, 1303, 4358, + 10789, 5759, 1303, 7711, 1584, + 10789, 5759, 1303, 7711, 1585, 7711, 1483, 4358, + 10789, 5759, 1303, 7711, 2110, + 10789, 5759, 1303, 7711, 2489, 5445, 6012, + 10789, 5759, 1304, + 10789, 5759, 1305, 5387, 1305, 7122, + 10789, 5759, 1305, 7711, 1, 5445, 1696, + 10789, 5759, 1305, 7711, 1696, + 10789, 5759, 1308, + 10789, 5759, 1310, + 10789, 5759, 1311, 7711, 2518, + 10789, 5759, 1316, + 10789, 5759, 1344, + 10789, 5759, 1482, + 10789, 5759, 1483, 514, + 10789, 5759, 1483, 1006, + 10789, 5759, 1483, 4358, + 10789, 5759, 1483, 5387, 1483, 5703, 5387, 5703, 589, 5387, 588, + 10789, 5759, 1484, + 10789, 5759, 1498, + 10789, 5759, 1572, + 10789, 5759, 1573, 9967, 1572, + 10789, 5759, 1576, + 10789, 5759, 1584, + 10789, 5759, 1585, 7711, 1483, 4358, + 10789, 5759, 1586, + 10789, 5759, 1587, 7711, 750, + 10789, 5759, 1587, 9967, 1586, + 10789, 5759, 1624, + 10789, 5759, 1632, + 10789, 5759, 1682, + 10789, 5759, 1684, + 10789, 5759, 1685, 9817, 4212, + 10789, 5759, 1686, + 10789, 5759, 1688, + 10789, 5759, 1689, 4358, + 10789, 5759, 1690, + 10789, 5759, 1696, + 10789, 5759, 1697, 10377, 1696, + 10789, 5759, 1736, + 10789, 5759, 1737, 7711, 1736, + 10789, 5759, 1738, + 10789, 5759, 1739, 7711, 1696, + 10789, 5759, 1739, 7711, 1697, 5445, 520, + 10789, 5759, 1786, + 10789, 5759, 1812, + 10789, 5759, 1813, 5898, + 10789, 5759, 1813, 7711, 76, + 10789, 5759, 1813, 7711, 243, 7711, 750, + 10789, 5759, 1813, 7711, 272, + 10789, 5759, 1813, 7711, 314, + 10789, 5759, 1813, 7711, 333, 5445, 736, + 10789, 5759, 1813, 7711, 369, 5445, 176, + 10789, 5759, 1813, 7711, 396, + 10789, 5759, 1813, 7711, 416, + 10789, 5759, 1813, 7711, 533, 5445, 736, + 10789, 5759, 1813, 7711, 750, + 10789, 5759, 1813, 7711, 4166, + 10789, 5759, 1813, 7711, 4167, 5898, + 10789, 5759, 1813, 7711, 4241, 5898, + 10789, 5759, 1813, 7711, 4704, + 10789, 5759, 1813, 7711, 4706, + 10789, 5759, 1813, 7711, 4707, 5445, 736, + 10789, 5759, 1813, 7711, 5761, 5445, 112, + 10789, 5759, 1813, 7711, 6012, + 10789, 5759, 1813, 7711, 7074, + 10789, 5759, 1813, 9684, + 10789, 5759, 1813, 9732, + 10789, 5759, 1813, 9967, 1812, + 10789, 5759, 1813, 10377, 1812, + 10789, 5759, 1814, + 10789, 5759, 1818, + 10789, 5759, 1820, + 10789, 5759, 1822, + 10789, 5759, 1823, 5387, 1822, + 10789, 5759, 1823, 5387, 1823, 1221, 5387, 1220, + 10789, 5759, 1852, + 10789, 5759, 1856, + 10789, 5759, 1864, + 10789, 5759, 1896, + 10789, 5759, 1922, + 10789, 5759, 1950, + 10789, 5759, 1951, 4358, + 10789, 5759, 1980, + 10789, 5759, 1988, + 10789, 5759, 1989, 9520, + 10789, 5759, 2044, + 10789, 5759, 2054, + 10789, 5759, 2055, 7711, 1221, 5445, 4241, 5898, + 10789, 5759, 2055, 7711, 4241, 5898, + 10789, 5759, 2110, + 10789, 5759, 2111, 5387, 2110, + 10789, 5759, 2111, 5898, + 10789, 5759, 2111, 7077, 7711, 1220, + 10789, 5759, 2111, 7077, 7711, 2488, + 10789, 5759, 2111, 7077, 7711, 2489, 5387, 2111, 7077, 7711, 2488, + 10789, 5759, 2111, 7077, 7711, 2836, + 10789, 5759, 2111, 7077, 7711, 4928, + 10789, 5759, 2111, 9967, 2110, + 10789, 5759, 2111, 9967, 2111, 7077, 5387, 7076, + 10789, 5759, 2190, + 10789, 5759, 2192, + 10789, 5759, 2194, + 10789, 5759, 2380, + 10789, 5759, 2486, + 10789, 5759, 2487, 4358, + 10789, 5759, 2487, 5387, 2486, + 10789, 5759, 2487, 7711, 0, + 10789, 5759, 2487, 7711, 152, + 10789, 5759, 2487, 7711, 236, + 10789, 5759, 2487, 7711, 374, + 10789, 5759, 2487, 7711, 580, + 10789, 5759, 2487, 7711, 584, + 10789, 5759, 2487, 7711, 594, + 10789, 5759, 2487, 7711, 602, + 10789, 5759, 2487, 7711, 1050, + 10789, 5759, 2487, 7711, 1584, + 10789, 5759, 2487, 7711, 1696, + 10789, 5759, 2487, 7711, 1822, + 10789, 5759, 2487, 7711, 2110, + 10789, 5759, 2487, 7711, 2488, + 10789, 5759, 2487, 7711, 2636, + 10789, 5759, 2487, 7711, 2836, + 10789, 5759, 2487, 7711, 5692, + 10789, 5759, 2487, 9520, + 10789, 5759, 2488, + 10789, 5759, 2489, 7075, 7711, 3280, + 10789, 5759, 2494, + 10789, 5759, 2516, + 10789, 5759, 2518, + 10789, 5759, 2519, 250, + 10789, 5759, 2519, 5387, 2519, 1207, 5387, 1207, 1221, 5387, 1220, + 10789, 5759, 2519, 5387, 2519, 2637, 5387, 2637, 1221, 5387, 1220, + 10789, 5759, 2524, + 10789, 5759, 2525, 5387, 10267, 2524, + 10789, 5759, 2530, + 10789, 5759, 2582, + 10789, 5759, 2584, + 10789, 5759, 2592, + 10789, 5759, 2636, + 10789, 5759, 2637, 5387, 2637, 405, 5387, 405, 4095, 5387, 4094, + 10789, 5759, 2637, 9732, + 10789, 5759, 2638, + 10789, 5759, 2639, 7711, 106, + 10789, 5759, 2639, 7711, 588, + 10789, 5759, 2639, 7711, 1304, + 10789, 5759, 2639, 7711, 2518, + 10789, 5759, 2639, 7711, 2524, + 10789, 5759, 2639, 7711, 6012, + 10789, 5759, 2654, + 10789, 5759, 2694, + 10789, 5759, 2698, + 10789, 5759, 2699, 5387, 2698, + 10789, 5759, 2699, 5387, 2699, 1207, 5387, 1207, 1221, 5387, 1220, + 10789, 5759, 2699, 7711, 5880, + 10789, 5759, 2758, + 10789, 5759, 2760, + 10789, 5759, 2766, + 10789, 5759, 2767, 5387, 2767, 671, 5387, 670, + 10789, 5759, 2822, + 10789, 5759, 2823, 7711, 1, 5445, 236, + 10789, 5759, 2823, 7711, 1, 5445, 392, + 10789, 5759, 2823, 7711, 76, + 10789, 5759, 2823, 7711, 236, + 10789, 5759, 2823, 7711, 580, + 10789, 5759, 2823, 7711, 581, 5445, 106, + 10789, 5759, 2823, 7711, 581, 5445, 736, + 10789, 5759, 2823, 7711, 2110, + 10789, 5759, 2824, + 10789, 5759, 2828, + 10789, 5759, 2832, + 10789, 5759, 2833, 7711, 0, + 10789, 5759, 2833, 7711, 41, 5445, 1304, + 10789, 5759, 2833, 7711, 216, + 10789, 5759, 2833, 7711, 230, + 10789, 5759, 2833, 7711, 236, + 10789, 5759, 2833, 7711, 272, + 10789, 5759, 2833, 7711, 314, + 10789, 5759, 2833, 7711, 462, + 10789, 5759, 2833, 7711, 576, + 10789, 5759, 2833, 7711, 588, + 10789, 5759, 2833, 7711, 760, + 10789, 5759, 2833, 7711, 1060, + 10789, 5759, 2833, 7711, 1212, + 10789, 5759, 2833, 7711, 1220, + 10789, 5759, 2833, 7711, 1482, + 10789, 5759, 2833, 7711, 1498, + 10789, 5759, 2833, 7711, 1822, + 10789, 5759, 2833, 7711, 1922, + 10789, 5759, 2833, 7711, 2518, + 10789, 5759, 2833, 7711, 4241, 5898, + 10789, 5759, 2833, 7711, 5756, + 10789, 5759, 2833, 7711, 7774, + 10789, 5759, 2833, 7711, 7954, + 10789, 5759, 2836, + 10789, 5759, 2837, 7711, 0, + 10789, 5759, 2837, 7711, 326, + 10789, 5759, 2837, 7711, 1696, + 10789, 5759, 2837, 7711, 5880, + 10789, 5759, 2840, + 10789, 5759, 2841, 7711, 8338, + 10789, 5759, 2842, + 10789, 5759, 3122, + 10789, 5759, 3136, + 10789, 5759, 3158, + 10789, 5759, 3160, + 10789, 5759, 3161, 4703, 5898, + 10789, 5759, 3164, + 10789, 5759, 3188, + 10789, 5759, 3189, 7711, 0, + 10789, 5759, 3190, + 10789, 5759, 3242, + 10789, 5759, 3256, + 10789, 5759, 3257, 7711, 2518, + 10789, 5759, 3266, + 10789, 5759, 3270, + 10789, 5759, 3271, 7711, 1696, + 10789, 5759, 3280, + 10789, 5759, 3698, + 10789, 5759, 3820, + 10789, 5759, 4088, + 10789, 5759, 4094, + 10789, 5759, 4122, + 10789, 5759, 4124, + 10789, 5759, 4125, 4358, + 10789, 5759, 4125, 4359, 4358, + 10789, 5759, 4126, + 10789, 5759, 4132, + 10789, 5759, 4154, + 10789, 5759, 4156, + 10789, 5759, 4164, + 10789, 5759, 4166, + 10789, 5759, 4174, + 10789, 5759, 4175, 7711, 0, + 10789, 5759, 4175, 7711, 1, 5445, 1736, + 10789, 5759, 4175, 7711, 1, 5445, 1737, 7711, 1736, + 10789, 5759, 4175, 7711, 80, + 10789, 5759, 4175, 7711, 236, + 10789, 5759, 4175, 7711, 237, 4358, + 10789, 5759, 4175, 7711, 332, + 10789, 5759, 4175, 7711, 340, + 10789, 5759, 4175, 7711, 354, + 10789, 5759, 4175, 7711, 580, + 10789, 5759, 4175, 7711, 588, + 10789, 5759, 4175, 7711, 750, + 10789, 5759, 4175, 7711, 1483, 4358, + 10789, 5759, 4175, 7711, 1682, + 10789, 5759, 4175, 7711, 1737, 7711, 1736, + 10789, 5759, 4175, 7711, 4125, 4358, + 10789, 5759, 4175, 7711, 4125, 4359, 4358, + 10789, 5759, 4175, 7711, 8338, + 10789, 5759, 4175, 7711, 8339, 9732, + 10789, 5759, 4234, + 10789, 5759, 4235, 9967, 4234, + 10789, 5759, 4240, + 10789, 5759, 4241, 5387, 4240, + 10789, 5759, 4241, 5898, + 10789, 5759, 4241, 9967, 4240, + 10789, 5759, 4242, + 10789, 5759, 4334, + 10789, 5759, 4335, 4358, + 10789, 5759, 4336, + 10789, 5759, 4337, 7711, 1, 5445, 1482, + 10789, 5759, 4337, 7711, 355, 5445, 1482, + 10789, 5759, 4337, 7711, 462, + 10789, 5759, 4337, 7711, 1482, + 10789, 5759, 4337, 7711, 4241, 5898, + 10789, 5759, 4338, + 10789, 5759, 4339, 5898, + 10789, 5759, 4339, 7711, 750, + 10789, 5759, 4339, 7711, 5880, + 10789, 5759, 4339, 9967, 4338, + 10789, 5759, 4366, + 10789, 5759, 4544, + 10789, 5759, 4545, 7711, 80, + 10789, 5759, 4545, 7711, 588, + 10789, 5759, 4545, 7711, 1344, + 10789, 5759, 4545, 7711, 4884, + 10789, 5759, 4545, 7711, 8338, + 10789, 5759, 4546, + 10789, 5759, 4596, + 10789, 5759, 4597, 5387, 4597, 832, + 10789, 5759, 4597, 5387, 4597, 9732, + 10789, 5759, 4606, + 10789, 5759, 4704, + 10789, 5759, 4706, + 10789, 5759, 4708, + 10789, 5759, 4710, + 10789, 5759, 4711, 5387, 4710, + 10789, 5759, 4714, + 10789, 5759, 4716, + 10789, 5759, 4764, + 10789, 5759, 4884, + 10789, 5759, 4928, + 10789, 5759, 5030, + 10789, 5759, 5031, 5387, 5030, + 10789, 5759, 5031, 5387, 5031, 7711, 1, 5445, 392, + 10789, 5759, 5031, 7711, 0, + 10789, 5759, 5031, 7711, 670, + 10789, 5759, 5031, 7711, 1696, + 10789, 5759, 5031, 9967, 5030, + 10789, 5759, 5042, + 10789, 5759, 5043, 7711, 2525, 5898, + 10789, 5759, 5043, 10266, + 10789, 5759, 5043, 10377, 5042, + 10789, 5759, 5044, + 10789, 5759, 5278, + 10789, 5759, 5662, + 10789, 5759, 5663, 7711, 0, + 10789, 5759, 5663, 7711, 40, + 10789, 5759, 5663, 7711, 41, 5445, 0, + 10789, 5759, 5663, 7711, 396, + 10789, 5759, 5663, 7711, 750, + 10789, 5759, 5663, 7711, 2766, + 10789, 5759, 5663, 7711, 4338, + 10789, 5759, 5663, 7711, 5720, + 10789, 5759, 5664, + 10789, 5759, 5682, + 10789, 5759, 5692, + 10789, 5759, 5693, 7711, 0, + 10789, 5759, 5693, 7711, 272, + 10789, 5759, 5696, + 10789, 5759, 5697, 7711, 0, + 10789, 5759, 5697, 7711, 754, + 10789, 5759, 5697, 7711, 1012, + 10789, 5759, 5697, 7711, 1220, + 10789, 5759, 5697, 7711, 1482, + 10789, 5759, 5697, 7711, 1483, 4358, + 10789, 5759, 5697, 7711, 1820, + 10789, 5759, 5697, 7711, 1950, + 10789, 5759, 5697, 7711, 2488, + 10789, 5759, 5697, 7711, 6534, + 10789, 5759, 5697, 7711, 8374, + 10789, 5759, 5702, + 10789, 5759, 5703, 5387, 5703, 833, 5387, 832, + 10789, 5759, 5703, 5898, + 10789, 5759, 5720, + 10789, 5759, 5756, + 10789, 5759, 5757, 5387, 5757, 5720, + 10789, 5759, 5760, + 10789, 5759, 5840, + 10789, 5759, 5852, + 10789, 5759, 5880, + 10789, 5759, 6012, + 10789, 5759, 6046, + 10789, 5759, 6048, + 10789, 5759, 6049, 7711, 462, + 10789, 5759, 6049, 7711, 8338, + 10789, 5759, 6054, + 10789, 5759, 6062, + 10789, 5759, 6064, + 10789, 5759, 6256, + 10789, 5759, 6318, + 10789, 5759, 6396, + 10789, 5759, 6412, + 10789, 5759, 6430, + 10789, 5759, 6436, + 10789, 5759, 6464, + 10789, 5759, 6466, + 10789, 5759, 6534, + 10789, 5759, 6535, 5387, 6534, + 10789, 5759, 6648, + 10789, 5759, 6650, + 10789, 5759, 6708, + 10789, 5759, 6746, + 10789, 5759, 6818, + 10789, 5759, 6854, + 10789, 5759, 6860, + 10789, 5759, 6884, + 10789, 5759, 7040, + 10789, 5759, 7054, + 10789, 5759, 7074, + 10789, 5759, 7075, 7711, 0, + 10789, 5759, 7075, 7711, 1, 5445, 139, 5445, 236, + 10789, 5759, 7075, 7711, 1, 5445, 1220, + 10789, 5759, 7075, 7711, 1, 5445, 1736, + 10789, 5759, 7075, 7711, 40, + 10789, 5759, 7075, 7711, 41, 5445, 0, + 10789, 5759, 7075, 7711, 41, 5445, 41, 5445, 40, + 10789, 5759, 7075, 7711, 76, + 10789, 5759, 7075, 7711, 80, + 10789, 5759, 7075, 7711, 106, + 10789, 5759, 7075, 7711, 176, + 10789, 5759, 7075, 7711, 216, + 10789, 5759, 7075, 7711, 236, + 10789, 5759, 7075, 7711, 243, 7711, 2110, + 10789, 5759, 7075, 7711, 272, + 10789, 5759, 7075, 7711, 273, 5445, 236, + 10789, 5759, 7075, 7711, 273, 5445, 354, + 10789, 5759, 7075, 7711, 314, + 10789, 5759, 7075, 7711, 354, + 10789, 5759, 7075, 7711, 368, + 10789, 5759, 7075, 7711, 369, 5445, 176, + 10789, 5759, 7075, 7711, 396, + 10789, 5759, 7075, 7711, 561, 5445, 1, 5445, 547, 5445, 392, + 10789, 5759, 7075, 7711, 581, 5445, 736, + 10789, 5759, 7075, 7711, 588, + 10789, 5759, 7075, 7711, 737, 6313, 5898, + 10789, 5759, 7075, 7711, 750, + 10789, 5759, 7075, 7711, 966, + 10789, 5759, 7075, 7711, 1220, + 10789, 5759, 7075, 7711, 1304, + 10789, 5759, 7075, 7711, 1305, 5445, 1304, + 10789, 5759, 7075, 7711, 1344, + 10789, 5759, 7075, 7711, 1483, 4358, + 10789, 5759, 7075, 7711, 1632, + 10789, 5759, 7075, 7711, 1682, + 10789, 5759, 7075, 7711, 1688, + 10789, 5759, 7075, 7711, 1689, 5445, 243, 5445, 0, + 10789, 5759, 7075, 7711, 1820, + 10789, 5759, 7075, 7711, 2519, 5445, 2584, + 10789, 5759, 7075, 7711, 2584, + 10789, 5759, 7075, 7711, 2638, + 10789, 5759, 7075, 7711, 2836, + 10789, 5759, 7075, 7711, 4884, + 10789, 5759, 7075, 7711, 5030, + 10789, 5759, 7075, 7711, 5720, + 10789, 5759, 7075, 7711, 5721, 5445, 5720, + 10789, 5759, 7075, 7711, 5880, + 10789, 5759, 7075, 7711, 7074, + 10789, 5759, 7075, 7711, 7545, 5445, 4339, 5445, 6746, + 10789, 5759, 7075, 7711, 7545, 5445, 4339, 5898, + 10789, 5759, 7075, 9732, + 10789, 5759, 7076, + 10789, 5759, 7077, 4358, + 10789, 5759, 7077, 4359, 5387, 7077, 4359, 2518, + 10789, 5759, 7077, 7711, 2518, + 10789, 5759, 7077, 7711, 2519, 5445, 2584, + 10789, 5759, 7122, + 10789, 5759, 7123, 5387, 7122, + 10789, 5759, 7123, 9684, + 10789, 5759, 7123, 10377, 7122, + 10789, 5759, 7138, + 10789, 5759, 7196, + 10789, 5759, 7197, 4358, + 10789, 5759, 7197, 7711, 0, + 10789, 5759, 7197, 7711, 1, 5445, 144, + 10789, 5759, 7197, 7711, 144, + 10789, 5759, 7204, + 10789, 5759, 7248, + 10789, 5759, 7284, + 10789, 5759, 7285, 703, 7711, 106, + 10789, 5759, 7285, 703, 7711, 332, + 10789, 5759, 7285, 703, 7711, 396, + 10789, 5759, 7285, 703, 7711, 580, + 10789, 5759, 7285, 703, 7711, 1052, + 10789, 5759, 7285, 703, 7711, 1304, + 10789, 5759, 7285, 703, 7711, 1483, 4358, + 10789, 5759, 7285, 703, 7711, 4706, + 10789, 5759, 7285, 703, 7711, 7572, + 10789, 5759, 7285, 703, 7711, 7954, + 10789, 5759, 7285, 8361, 7711, 106, + 10789, 5759, 7285, 8361, 7711, 107, 40, + 10789, 5759, 7364, + 10789, 5759, 7374, + 10789, 5759, 7375, 7711, 588, + 10789, 5759, 7375, 7711, 670, + 10789, 5759, 7375, 7711, 1586, + 10789, 5759, 7375, 10377, 7374, + 10789, 5759, 7510, + 10789, 5759, 7516, + 10789, 5759, 7528, + 10789, 5759, 7534, + 10789, 5759, 7544, + 10789, 5759, 7572, + 10789, 5759, 7648, + 10789, 5759, 7762, + 10789, 5759, 7774, + 10789, 5759, 7775, 7711, 40, + 10789, 5759, 7778, + 10789, 5759, 7890, + 10789, 5759, 7954, + 10789, 5759, 7966, + 10789, 5759, 8242, + 10789, 5759, 8276, + 10789, 5759, 8338, + 10789, 5759, 8339, 5387, 8339, 7075, 7711, 41, 5387, 7075, 7711, 40, + 10789, 5759, 8339, 7075, 7711, 41, 5387, 7075, 7711, 40, + 10789, 5759, 8360, + 10789, 5759, 8361, 5387, 8360, + 10789, 5759, 8374, + 10789, 5759, 8376, + 10789, 5759, 8382, + 10789, 5759, 8408, + 10789, 5759, 8490, + 10789, 5759, 8494, + 10789, 5759, 8512, + 10789, 5759, 8513, 7711, 80, + 10789, 5759, 8513, 7711, 369, 5445, 4241, 5898, + 10789, 5759, 8513, 7711, 396, + 10789, 5759, 8513, 7711, 581, 5445, 736, + 10789, 5759, 8513, 7711, 736, + 10789, 5759, 8513, 7711, 737, 5445, 736, + 10789, 5759, 8513, 7711, 1304, + 10789, 5759, 8513, 7711, 2110, + 10789, 5759, 8513, 7711, 2518, + 10789, 5759, 8513, 7711, 2519, 5445, 1, 80, + 10789, 5759, 8513, 7711, 2519, 5445, 736, + 10789, 5759, 8513, 7711, 2519, 5445, 737, 5445, 736, + 10789, 5759, 8513, 7711, 2836, + 10789, 5759, 8664, + 10789, 5759, 8702, + 10789, 5759, 8706, + 10789, 5759, 8710, + 10789, 5759, 8764, + 10789, 5759, 8902, + 10789, 5759, 9306, + 10789, 5759, 9307, 7711, 1696, + 10789, 5759, 10518, + 10789, 9515, 5759, 2167, 9897, 2171, 7574, + 10789, 9515, 5759, 2167, 9897, 2171, 9614, + 10789, 9515, 5759, 2171, 3704, + 10789, 9515, 5759, 2171, 3822, + 10789, 9515, 5759, 2171, 6756, + 10789, 9515, 5759, 2171, 6830, + 10789, 9515, 5759, 2171, 6832, + 10789, 9515, 5759, 2171, 7520, + 10789, 9515, 5759, 2171, 7687, 4094, + 10789, 9515, 5759, 2171, 7687, 9817, 4213, 0, + 10789, 9515, 5759, 2171, 8159, 736, + 10789, 9515, 5759, 2171, 9615, 736, + 10789, 9515, 5759, 2541, 40, + 10789, 9515, 5759, 2541, 736, + 10789, 9515, 5759, 2541, 737, 5898, + 10789, 9515, 5759, 2541, 4094, + 10789, 9515, 5759, 2541, 6830, + 10789, 9515, 5759, 2541, 7516, + 10789, 9515, 5759, 2541, 9817, 4213, 3282, + 10789, 9515, 5759, 2779, 736, + 10789, 9515, 5759, 2779, 737, 5898, + 10789, 9515, 5759, 2779, 3704, + 10789, 9515, 5759, 2779, 3822, + 10789, 9515, 5759, 2779, 6756, + 10789, 9515, 5759, 2779, 6830, + 10789, 9515, 5759, 2779, 6832, + 10789, 9515, 5759, 2779, 7516, + 10789, 9515, 5759, 2779, 7520, + 10789, 9515, 5759, 2779, 8819, 4094, + 10789, 9515, 5759, 2779, 8819, 9817, 4213, 0, + 10789, 9515, 5759, 4201, 40, + 10789, 9515, 5759, 4201, 736, + 10789, 9515, 5759, 4201, 737, 5898, + 10789, 9515, 5759, 4201, 3704, + 10789, 9515, 5759, 4201, 3705, 9817, 4212, + 10789, 9515, 5759, 4201, 3822, + 10789, 9515, 5759, 4201, 4094, + 10789, 9515, 5759, 4201, 6830, + 10789, 9515, 5759, 4201, 6832, + 10789, 9515, 5759, 4201, 7516, + 10789, 9515, 5759, 4201, 7520, + 10789, 9515, 5759, 4201, 8719, 4094, + 10789, 9515, 5759, 4215, 40, + 10789, 9515, 5759, 4215, 736, + 10789, 9515, 5759, 4215, 737, 5898, + 10789, 9515, 5759, 4215, 3704, + 10789, 9515, 5759, 4215, 3705, 9817, 4212, + 10789, 9515, 5759, 4215, 3822, + 10789, 9515, 5759, 4215, 4094, + 10789, 9515, 5759, 4215, 6830, + 10789, 9515, 5759, 4215, 6832, + 10789, 9515, 5759, 4215, 7516, + 10789, 9515, 5759, 4215, 7520, + 10789, 9515, 5759, 4215, 9817, 4213, 7106, + 10789, 9515, 5759, 4215, 9817, 4213, 7107, 0, + 10789, 9515, 5759, 4215, 9817, 4213, 7107, 2, + 10789, 9515, 5759, 4215, 9817, 4213, 8410, + 10789, 9515, 5759, 5191, 40, + 10789, 9515, 5759, 5191, 736, + 10789, 9515, 5759, 5191, 4094, + 10789, 9515, 5759, 5191, 6830, + 10789, 9515, 5759, 5191, 7516, + 10789, 9515, 5759, 5191, 9817, 4213, 8310, + 10789, 9515, 5759, 5191, 9817, 4213, 8311, 0, + 10789, 9515, 5759, 5191, 9817, 4213, 9354, + 10789, 9515, 5759, 5191, 9817, 4213, 9356, + 10789, 9515, 5759, 6723, 40, + 10789, 9515, 5759, 6723, 736, + 10789, 9515, 5759, 6723, 4094, + 10789, 9515, 5759, 6723, 6830, + 10789, 9515, 5759, 6723, 7516, + 10789, 9515, 5759, 6723, 9817, 4213, 6066, + 10789, 9515, 5759, 6723, 9817, 4213, 7776, + 10789, 9515, 5759, 7509, 40, + 10789, 9515, 5759, 7509, 736, + 10789, 9515, 5759, 7509, 4094, + 10789, 9515, 5759, 7509, 6830, + 10789, 9515, 5759, 7509, 7516, + 10789, 9515, 5759, 7509, 9817, 4213, 4607, 0, + 10789, 9515, 5759, 7509, 9817, 4213, 4607, 2, + 10789, 9515, 5759, 7509, 9817, 4213, 6990, + 10789, 9515, 5759, 7517, 7711, 1213, 5445, 1922, + 10789, 9515, 5759, 7517, 7711, 1213, 5445, 4094, + 10789, 9515, 5759, 7695, 736, + 10789, 9515, 5759, 7695, 737, 5898, + 10789, 9515, 5759, 7695, 3704, + 10789, 9515, 5759, 7695, 3822, + 10789, 9515, 5759, 7695, 3823, 9817, 4212, + 10789, 9515, 5759, 7695, 4094, + 10789, 9515, 5759, 7695, 6830, + 10789, 9515, 5759, 7695, 6832, + 10789, 9515, 5759, 7695, 7516, + 10789, 9515, 5759, 7695, 7517, 9817, 4212, + 10789, 9515, 5759, 7695, 7520, + 10789, 9515, 5759, 7695, 7521, 9817, 4212, + 10789, 9515, 5759, 7695, 9817, 4213, 6752, + 10789, 9515, 5759, 7695, 9817, 4213, 6754, + 10789, 9515, 5759, 11136, + 10789, 9515, 5759, 11138, + 10789, 12133, 5759, 2167, 9897, 6129, 9178, + 10789, 12133, 5759, 10001, 6610, + 10789, 12133, 5759, 10001, 10644, + 10789, 12133, 5759, 10677, 6610, + 10797, 8775, 7101, 601, 721, 11648, + 10797, 8775, 7101, 601, 721, 11649, 6121, 6104, + 10797, 8775, 7101, 601, 721, 11649, 6121, 8056, + 10797, 8775, 7101, 601, 721, 11649, 6121, 10642, + 10797, 8775, 7101, 4117, 721, 11648, + 10797, 8775, 7101, 4117, 721, 11649, 6121, 6104, + 10797, 8775, 7101, 4117, 721, 11649, 6121, 8056, + 10797, 8775, 7101, 4117, 721, 11649, 6121, 10642, + 10797, 8775, 7101, 10677, 721, 2725, 4848, + 10797, 8775, 7101, 10677, 721, 2725, 7442, + 10797, 8775, 7101, 10677, 721, 6104, + 10797, 8775, 7101, 10677, 721, 8005, 4848, + 10797, 8775, 7101, 10677, 721, 8005, 7442, + 10797, 8775, 7101, 10677, 6121, 8056, + 10797, 8775, 7101, 10677, 6121, 10642, + 10804, + 10817, 8548, + 10959, 2779, 8289, 6434, + 10959, 6434, + 10959, 6435, 569, 760, + 10959, 6435, 4221, 760, + 10959, 6435, 6121, 2697, 11096, + 10959, 6435, 6121, 2697, 11764, + 10959, 6435, 6121, 8077, 11096, + 10959, 6435, 6121, 8153, 8758, + 10959, 6435, 6121, 11649, 8758, + 10959, 6435, 11097, 429, 9811, 6434, + 10959, 6505, 6434, + 10959, 7821, 6434, + 10959, 7924, + 10959, 8097, 6434, + 10959, 8153, 6434, + 10959, 8561, 7944, + 10959, 8849, 6434, + 10959, 8963, 6434, + 10959, 9327, 6121, 3713, 4849, 569, 760, + 10959, 9327, 6121, 3713, 4849, 4221, 760, + 10959, 9327, 6121, 3713, 4849, 7991, 9811, 9327, 6121, 3713, 7442, + 10959, 9327, 6121, 3713, 4849, 7991, 10959, 9327, 6121, 3713, 7442, + 10959, 9327, 6121, 3713, 7443, 569, 760, + 10959, 9327, 6121, 3713, 7443, 4221, 760, + 10959, 9327, 6121, 3713, 11096, + 10959, 9327, 6121, 3713, 11764, + 10959, 11191, 6434, + 10963, 9120, + 10977, 8774, + 10978, + 10989, 5758, + 11011, 1809, 4876, + 11011, 2091, 5758, + 11011, 2941, 5758, + 11011, 3055, 5758, + 11011, 3873, 5758, + 11011, 4223, 5836, + 11011, 4849, 6627, 9050, + 11011, 4849, 7821, 12114, + 11011, 4849, 8745, 9050, + 11011, 4849, 12114, + 11011, 5445, 5758, + 11011, 6610, + 11011, 6616, + 11011, 6689, 2170, + 11011, 6689, 2540, + 11011, 6689, 2778, + 11011, 6689, 4200, + 11011, 6689, 4214, + 11011, 6689, 5190, + 11011, 6689, 6260, + 11011, 6689, 6722, + 11011, 6689, 7508, + 11011, 6689, 7694, + 11011, 6875, 7908, + 11011, 7089, 7593, 8405, 0, + 11011, 7089, 7593, 8405, 2, + 11011, 7089, 7593, 8405, 4, + 11011, 7089, 7593, 8405, 6, + 11011, 7089, 7593, 8405, 8, + 11011, 7089, 7593, 8405, 10, + 11011, 7089, 7593, 8405, 12, + 11011, 7089, 7593, 8405, 14, + 11011, 7089, 7593, 8405, 16, + 11011, 7089, 7593, 8405, 18, + 11011, 7089, 7593, 8405, 20, + 11011, 7089, 7593, 8405, 22, + 11011, 7089, 7593, 8405, 24, + 11011, 7089, 7593, 8405, 26, + 11011, 7089, 7593, 8405, 28, + 11011, 7089, 7593, 8405, 30, + 11011, 7089, 7593, 8405, 32, + 11011, 7089, 7593, 8405, 34, + 11011, 7089, 7593, 8405, 36, + 11011, 7089, 7593, 8405, 38, + 11011, 7089, 7593, 8405, 40, + 11011, 7089, 7593, 8405, 42, + 11011, 7089, 7593, 8405, 44, + 11011, 7089, 7593, 8405, 46, + 11011, 7089, 7593, 8405, 48, + 11011, 7089, 7593, 8405, 50, + 11011, 7089, 9063, 8405, 0, + 11011, 7089, 9063, 8405, 2, + 11011, 7089, 9063, 8405, 4, + 11011, 7089, 9063, 8405, 6, + 11011, 7089, 9063, 8405, 8, + 11011, 7089, 9063, 8405, 10, + 11011, 7089, 9063, 8405, 12, + 11011, 7089, 9063, 8405, 14, + 11011, 7089, 9063, 8405, 16, + 11011, 7089, 9063, 8405, 18, + 11011, 7089, 9063, 8405, 20, + 11011, 7089, 9063, 8405, 22, + 11011, 7089, 9063, 8405, 24, + 11011, 7089, 9063, 8405, 26, + 11011, 7089, 9063, 8405, 28, + 11011, 7089, 9063, 8405, 30, + 11011, 7089, 9063, 8405, 32, + 11011, 7089, 9063, 8405, 34, + 11011, 7089, 9063, 8405, 36, + 11011, 7089, 9063, 8405, 38, + 11011, 7089, 9063, 8405, 40, + 11011, 7089, 9063, 8405, 42, + 11011, 7089, 9063, 8405, 44, + 11011, 7089, 9063, 8405, 46, + 11011, 7089, 9063, 8405, 48, + 11011, 7089, 9063, 8405, 50, + 11011, 7387, 5758, + 11011, 7443, 6627, 9050, + 11011, 7443, 7821, 12114, + 11011, 7443, 8745, 9050, + 11011, 7443, 12114, + 11011, 7708, + 11011, 8017, 760, + 11011, 8129, 5758, + 11011, 8167, 5758, + 11011, 8432, + 11011, 8525, 5758, + 11011, 9581, 5758, + 11011, 9633, 9718, + 11011, 9718, + 11011, 9898, + 11011, 10469, 4926, + 11011, 10677, 4876, + 11011, 10708, + 11011, 11099, 5758, + 11011, 11195, 4926, + 11011, 11224, + 11011, 11424, + 11011, 11449, 7908, + 11011, 11451, 90, + 11011, 12017, 4926, + 11011, 12473, 5758, + 11011, 12478, + 11015, 11740, + 11031, 4849, 8077, 9050, + 11031, 6505, 8744, + 11031, 6801, 7101, 10676, + 11031, 7443, 8077, 9050, + 11031, 7821, 8056, + 11031, 8287, 8206, + 11031, 8287, 8405, 0, + 11031, 8287, 8405, 8, + 11031, 8287, 8405, 16, + 11031, 8287, 8405, 28, + 11031, 8287, 8405, 40, + 11031, 8287, 8405, 66, + 11031, 8287, 8405, 178, + 11031, 8287, 8405, 188, + 11031, 8287, 8405, 426, + 11031, 8287, 8405, 622, + 11031, 8287, 8405, 626, + 11031, 8287, 8405, 630, + 11031, 8287, 8405, 652, + 11031, 8287, 8405, 654, + 11031, 8287, 8405, 656, + 11031, 8287, 8405, 660, + 11031, 8287, 8405, 664, + 11031, 8287, 8405, 2908, + 11031, 8287, 8405, 2926, + 11031, 8287, 8405, 3012, + 11031, 8287, 8405, 3056, + 11031, 8287, 8405, 5770, + 11031, 8287, 8405, 6594, + 11031, 8287, 8405, 6912, + 11031, 8287, 8405, 6982, + 11031, 8287, 8405, 7166, + 11031, 8287, 8405, 7244, + 11031, 8287, 8405, 7372, + 11031, 8287, 8405, 7440, + 11031, 8287, 8405, 8362, + 11031, 8287, 8405, 8828, + 11031, 8287, 8405, 9086, + 11031, 8287, 8405, 9400, + 11031, 8287, 8405, 9588, + 11031, 8287, 8405, 9780, + 11031, 8287, 8405, 11248, + 11031, 8287, 8405, 11728, + 11031, 8287, 8405, 11758, + 11031, 8287, 8405, 11824, + 11031, 8287, 8405, 11832, + 11031, 8287, 8405, 12070, + 11031, 8287, 8405, 12094, + 11031, 8287, 8405, 12096, + 11031, 8287, 8405, 12144, + 11031, 8287, 8405, 12146, + 11031, 8287, 8405, 12150, + 11031, 8287, 8405, 12350, + 11031, 8287, 8405, 12352, + 11031, 8287, 8405, 12532, + 11031, 8287, 8405, 13006, + 11031, 8287, 8405, 13008, + 11031, 9811, 6434, + 11031, 10283, 8405, 0, + 11031, 10283, 8405, 8, + 11031, 10283, 8405, 16, + 11031, 10283, 8405, 26, + 11031, 10283, 8405, 28, + 11031, 10283, 8405, 40, + 11031, 10283, 8405, 236, + 11031, 10283, 8405, 238, + 11031, 10283, 8405, 242, + 11031, 10283, 8405, 246, + 11031, 10283, 8405, 250, + 11031, 10283, 8405, 306, + 11031, 10283, 8405, 310, + 11031, 10283, 8405, 314, + 11031, 10283, 8405, 322, + 11031, 10283, 8405, 326, + 11031, 10283, 8405, 364, + 11031, 10283, 8405, 368, + 11031, 10283, 8405, 374, + 11031, 10283, 8405, 380, + 11031, 10283, 8405, 384, + 11031, 10283, 8405, 392, + 11031, 10283, 8405, 396, + 11031, 10283, 8405, 404, + 11031, 10283, 8405, 412, + 11031, 10283, 8405, 416, + 11031, 10283, 8405, 510, + 11031, 10283, 8405, 512, + 11031, 10283, 8405, 514, + 11031, 10283, 8405, 516, + 11031, 10283, 8405, 520, + 11031, 10283, 8405, 524, + 11031, 10283, 8405, 526, + 11031, 10283, 8405, 532, + 11031, 10283, 8405, 536, + 11031, 10283, 8405, 546, + 11031, 10283, 8405, 556, + 11031, 10283, 8405, 560, + 11031, 10283, 8405, 564, + 11031, 10283, 8405, 568, + 11031, 10283, 8405, 576, + 11031, 10283, 8405, 622, + 11031, 10283, 8405, 632, + 11031, 10283, 8405, 652, + 11031, 10283, 8405, 660, + 11031, 10283, 8405, 664, + 11031, 10283, 8405, 7593, 0, + 11031, 10283, 8405, 7593, 8, + 11031, 10283, 8405, 7593, 16, + 11031, 10283, 8405, 7593, 28, + 11031, 10283, 8405, 7593, 40, + 11031, 10283, 8405, 7593, 576, + 11031, 10283, 8405, 7593, 652, + 11031, 10283, 8405, 7593, 660, + 11031, 10283, 8405, 7593, 664, + 11031, 10283, 8473, 1044, + 11031, 10283, 8921, 7605, 4926, + 11031, 10283, 12341, 7605, 4926, + 11031, 10959, 6434, + 11031, 11097, 6434, + 11031, 11765, 6434, + 11031, 12043, 4223, 5836, + 11031, 12043, 6616, + 11031, 13365, 11185, 7605, 4926, + 11035, 10773, 8456, + 11036, + 11041, 568, + 11041, 569, 721, 9705, 10410, + 11041, 6121, 1045, 6376, + 11051, 88, + 11052, + 11061, 8774, + 11063, 5444, + 11063, 7710, + 11063, 11228, + 11093, 731, 12901, 6434, + 11097, 2779, 8289, 6434, + 11097, 6105, 6434, + 11097, 6434, + 11097, 6435, 569, 760, + 11097, 6435, 569, 761, 5387, 11765, 6435, 569, 760, + 11097, 6435, 569, 6505, 9158, + 11097, 6435, 4221, 760, + 11097, 6435, 4221, 761, 569, 6505, 9158, + 11097, 6435, 5387, 11765, 6434, + 11097, 6435, 6121, 2697, 9810, + 11097, 6435, 6121, 2697, 10958, + 11097, 6435, 6121, 4530, + 11097, 6435, 6121, 4896, + 11097, 6435, 6121, 5445, 6490, + 11097, 6435, 6121, 5878, + 11097, 6435, 6121, 5879, 6121, 8153, 10677, 8758, + 11097, 6435, 6121, 5879, 6121, 10677, 8758, + 11097, 6435, 6121, 8151, 5832, + 11097, 6435, 6121, 8153, 10677, 8758, + 11097, 6435, 6121, 8758, + 11097, 6435, 6121, 10677, 8758, + 11097, 6435, 6377, 7551, 11765, 6434, + 11097, 6435, 6377, 7709, 10374, + 11097, 6435, 6377, 7919, 6741, 568, + 11097, 6435, 6377, 9633, 7709, 10374, + 11097, 6435, 6377, 9633, 7919, 6741, 568, + 11097, 6435, 9785, 46, + 11097, 6435, 9785, 8762, + 11097, 6435, 9785, 11098, + 11097, 6505, 6434, + 11097, 7821, 6434, + 11097, 8097, 6434, + 11097, 8153, 3993, 6434, + 11097, 8153, 6434, + 11097, 8153, 6435, 4221, 760, + 11097, 8153, 6435, 6121, 8758, + 11097, 8153, 6435, 6121, 10677, 8758, + 11097, 8153, 11430, + 11097, 8561, 7944, + 11097, 8849, 3993, 6434, + 11097, 8849, 6434, + 11097, 9327, 5387, 11765, 9326, + 11097, 9327, 6121, 3713, 601, 569, 760, + 11097, 9327, 6121, 3713, 601, 4221, 760, + 11097, 9327, 6121, 3713, 601, 6377, 4895, 3992, + 11097, 9327, 6121, 3713, 601, 6377, 11097, 9327, 6121, 3713, 4116, + 11097, 9327, 6121, 3713, 601, 6377, 11765, 9327, 6121, 3713, 600, + 11097, 9327, 6121, 3713, 4117, 569, 760, + 11097, 9327, 6121, 3713, 4117, 4221, 760, + 11097, 9327, 6121, 3713, 4117, 6377, 11765, 9327, 6121, 3713, 4116, + 11097, 9327, 6121, 3713, 4117, 6491, 4895, 3992, + 11097, 9327, 6121, 3713, 9810, + 11097, 9327, 6121, 3713, 10958, + 11097, 10531, 6434, + 11097, 11191, 6434, + 11097, 11430, + 11097, 11875, 6435, 4221, 760, + 11097, 11875, 6435, 6121, 5878, + 11097, 11875, 6435, 6121, 5879, 6121, 8153, 10677, 8758, + 11097, 11875, 6435, 6121, 5879, 6121, 10677, 8758, + 11097, 11875, 6435, 6121, 8153, 10677, 8758, + 11097, 11875, 6435, 6121, 10677, 8758, + 11097, 11875, 8849, 3993, 6434, + 11097, 12103, 6434, + 11099, 445, 6741, 568, + 11099, 445, 9705, 6741, 568, + 11099, 445, 9705, 6741, 569, 6121, 1045, 6376, + 11099, 445, 9705, 6741, 569, 6121, 1045, 6377, 7442, + 11099, 445, 9705, 6741, 569, 6121, 1045, 8318, + 11099, 445, 11621, 568, + 11099, 445, 11896, + 11099, 445, 12472, + 11099, 721, 2091, 11896, + 11099, 721, 12345, 2091, 6741, 568, + 11099, 835, 2091, 6741, 568, + 11099, 835, 2091, 11621, 568, + 11099, 5387, 6741, 568, + 11099, 5758, + 11099, 6121, 1044, + 11099, 6121, 8057, 8318, + 11099, 6121, 10469, 4927, 6376, + 11099, 6377, 9693, 445, 6740, + 11099, 6377, 9693, 6377, 12472, + 11099, 6377, 9705, 6741, 6377, 12473, 6377, 9705, 6740, + 11099, 6377, 11097, 6434, + 11099, 6377, 12007, 6741, 6377, 12472, + 11099, 6377, 12473, 6377, 12007, 6740, + 11099, 6741, 569, 445, 12472, + 11099, 8065, 115, 6628, + 11099, 8065, 115, 6629, 6377, 9705, 6740, + 11104, + 11111, 93, 8399, 4926, + 11111, 3997, 4926, + 11111, 5759, 8916, + 11111, 5759, 9824, + 11111, 5759, 9870, + 11111, 5759, 9904, + 11111, 6689, 2170, + 11111, 6689, 2540, + 11111, 6689, 2778, + 11111, 6689, 4200, + 11111, 6689, 4214, + 11111, 6689, 5190, + 11111, 6689, 6260, + 11111, 6689, 6722, + 11111, 6689, 7508, + 11111, 6689, 7694, + 11111, 7803, 5759, 8, + 11111, 7803, 5759, 16, + 11111, 7803, 5759, 28, + 11111, 7803, 5759, 40, + 11111, 7803, 5759, 58, + 11111, 7803, 5759, 72, + 11111, 7803, 5759, 92, + 11111, 7803, 5759, 162, + 11111, 7803, 5759, 266, + 11111, 7803, 5759, 440, + 11111, 7803, 5759, 606, + 11111, 7803, 5759, 9827, 22, + 11111, 7803, 5759, 9827, 34, + 11111, 7803, 5759, 9827, 344, + 11111, 7803, 5759, 9827, 518, + 11111, 8405, 0, + 11111, 8405, 8, + 11111, 8405, 16, + 11111, 8405, 28, + 11111, 8405, 40, + 11111, 8405, 58, + 11111, 8405, 72, + 11111, 8405, 92, + 11111, 8405, 100, + 11111, 8405, 116, + 11111, 8405, 138, + 11111, 8405, 162, + 11111, 8405, 216, + 11111, 8405, 236, + 11111, 8405, 266, + 11111, 8405, 292, + 11111, 8405, 306, + 11111, 8405, 332, + 11111, 8405, 364, + 11111, 8405, 392, + 11111, 8405, 440, + 11111, 8405, 462, + 11111, 8405, 510, + 11111, 8405, 524, + 11111, 8405, 556, + 11111, 8405, 606, + 11111, 8405, 610, + 11111, 8405, 652, + 11111, 8405, 792, + 11111, 8405, 884, + 11111, 8405, 974, + 11111, 8405, 996, + 11111, 8405, 1260, + 11111, 8405, 1512, + 11111, 8405, 1612, + 11111, 8405, 1796, + 11111, 8405, 2030, + 11111, 8405, 2076, + 11111, 8405, 2126, + 11111, 8405, 2212, + 11111, 8405, 2438, + 11111, 8405, 2516, + 11111, 8405, 2566, + 11111, 8405, 2678, + 11111, 8405, 2746, + 11111, 8405, 4016, + 11111, 8405, 4888, + 11111, 8405, 5994, + 11111, 8405, 8045, 20, + 11111, 8405, 8045, 22, + 11111, 8405, 8045, 26, + 11111, 8405, 8045, 344, + 11111, 8405, 8045, 410, + 11111, 8405, 8045, 518, + 11111, 8405, 9827, 22, + 11111, 8405, 9827, 34, + 11111, 8405, 9827, 344, + 11111, 8405, 9827, 518, + 11111, 8525, 2171, 9344, + 11111, 8525, 2171, 10624, + 11111, 8525, 2670, + 11111, 10203, 2171, 4388, + 11111, 10203, 2171, 9614, + 11111, 10203, 7695, 10466, + 11113, 9539, 11054, + 11123, 4215, 4112, + 11123, 4217, 11391, 10507, 2170, + 11123, 4217, 11391, 10507, 2778, + 11123, 4217, 11391, 10507, 7694, + 11123, 4223, 5836, + 11123, 5751, 10585, 9921, 8450, + 11123, 5963, 5781, 8306, + 11123, 6500, + 11123, 6610, + 11123, 6616, + 11123, 6689, 2170, + 11123, 6689, 2540, + 11123, 6689, 2778, + 11123, 6689, 4200, + 11123, 6689, 4214, + 11123, 6689, 5190, + 11123, 6689, 6260, + 11123, 6689, 6722, + 11123, 6689, 7508, + 11123, 6689, 7694, + 11123, 7803, 11228, + 11123, 8405, 0, + 11123, 8405, 8, + 11123, 8405, 16, + 11123, 8405, 28, + 11123, 8405, 40, + 11123, 8405, 100, + 11123, 8405, 138, + 11123, 8405, 162, + 11123, 8405, 196, + 11123, 8405, 216, + 11123, 8405, 292, + 11123, 8405, 306, + 11123, 8405, 332, + 11123, 8405, 364, + 11123, 8405, 392, + 11123, 8405, 426, + 11123, 8405, 462, + 11123, 8405, 496, + 11123, 8405, 510, + 11123, 8405, 524, + 11123, 8405, 556, + 11123, 8405, 590, + 11123, 8405, 622, + 11123, 8405, 652, + 11123, 8405, 670, + 11123, 8405, 717, 4237, 0, + 11123, 8405, 717, 4237, 16, + 11123, 8405, 717, 4237, 70, + 11123, 8405, 717, 4237, 116, + 11123, 8405, 717, 4237, 138, + 11123, 8405, 717, 4237, 306, + 11123, 8405, 717, 4237, 462, + 11123, 8405, 717, 4237, 556, + 11123, 8405, 717, 4237, 670, + 11123, 8405, 717, 4237, 974, + 11123, 8405, 717, 4237, 2030, + 11123, 8405, 717, 4237, 2076, + 11123, 8405, 717, 4237, 2212, + 11123, 8405, 717, 4237, 2566, + 11123, 8405, 717, 4237, 2746, + 11123, 8405, 717, 4237, 3146, + 11123, 8405, 717, 4237, 4389, 40, + 11123, 8405, 717, 4237, 4389, 652, + 11123, 8405, 717, 4237, 5994, + 11123, 8405, 717, 4237, 7695, 7972, + 11123, 8405, 717, 4237, 7972, + 11123, 8405, 717, 4237, 8092, + 11123, 8405, 717, 4237, 9138, + 11123, 8405, 717, 4237, 9802, + 11123, 8405, 717, 4237, 9825, 2170, + 11123, 8405, 717, 4237, 9871, 2170, + 11123, 8405, 717, 4237, 10267, 9802, + 11123, 8405, 722, + 11123, 8405, 884, + 11123, 8405, 888, + 11123, 8405, 1338, + 11123, 8405, 1612, + 11123, 8405, 1770, + 11123, 8405, 2516, + 11123, 8405, 2732, + 11123, 8405, 3150, + 11123, 8405, 3186, + 11123, 8405, 5751, 8, + 11123, 8405, 5751, 16, + 11123, 8405, 5751, 40, + 11123, 8405, 5751, 138, + 11123, 8405, 5751, 196, + 11123, 8405, 5751, 216, + 11123, 8405, 5751, 236, + 11123, 8405, 5751, 290, + 11123, 8405, 5751, 292, + 11123, 8405, 5751, 306, + 11123, 8405, 5751, 462, + 11123, 8405, 5751, 556, + 11123, 8405, 5751, 590, + 11123, 8405, 5751, 670, + 11123, 8405, 5751, 722, + 11123, 8405, 5751, 884, + 11123, 8405, 5751, 1204, + 11123, 8405, 5751, 1338, + 11123, 8405, 5751, 2378, + 11123, 8405, 5751, 2516, + 11123, 8405, 5751, 2732, + 11123, 8405, 5751, 3146, + 11123, 8405, 5963, 8, + 11123, 8405, 5963, 16, + 11123, 8405, 5963, 28, + 11123, 8405, 5963, 40, + 11123, 8405, 5963, 100, + 11123, 8405, 5963, 138, + 11123, 8405, 5963, 216, + 11123, 8405, 5963, 292, + 11123, 8405, 5963, 306, + 11123, 8405, 5963, 364, + 11123, 8405, 5963, 426, + 11123, 8405, 5963, 462, + 11123, 8405, 5963, 496, + 11123, 8405, 5963, 556, + 11123, 8405, 5963, 590, + 11123, 8405, 5963, 622, + 11123, 8405, 5963, 652, + 11123, 8405, 5963, 717, 4237, 556, + 11123, 8405, 5963, 717, 4237, 3146, + 11123, 8405, 5963, 722, + 11123, 8405, 5963, 884, + 11123, 8405, 5963, 1080, + 11123, 8405, 5963, 1204, + 11123, 8405, 5963, 1338, + 11123, 8405, 5963, 1516, + 11123, 8405, 5963, 2046, + 11123, 8405, 5963, 2732, + 11123, 8405, 5963, 4895, 7803, 5758, + 11123, 8405, 8439, 16, + 11123, 8405, 8439, 196, + 11123, 8405, 8439, 306, + 11123, 8405, 8439, 510, + 11123, 8405, 8439, 717, 4237, 116, + 11123, 8405, 8439, 717, 4237, 556, + 11123, 8405, 8439, 717, 4237, 670, + 11123, 8405, 8439, 717, 4237, 792, + 11123, 8405, 8439, 717, 4237, 944, + 11123, 8405, 8439, 717, 4237, 996, + 11123, 8405, 8439, 717, 4237, 1260, + 11123, 8405, 8439, 717, 4237, 1512, + 11123, 8405, 8439, 717, 4237, 1770, + 11123, 8405, 8439, 717, 4237, 2030, + 11123, 8405, 8439, 717, 4237, 2566, + 11123, 8405, 8439, 717, 4237, 2746, + 11123, 8405, 8439, 717, 4237, 3146, + 11123, 8405, 8439, 717, 4237, 4016, + 11123, 8405, 8439, 3146, + 11123, 8439, 4223, 5836, + 11123, 8439, 6616, + 11123, 8516, + 11123, 10154, + 11163, 11228, + 11169, 7337, 5758, + 11172, + 11173, 6121, 2667, 2724, + 11191, 7390, + 11191, 10261, 10374, + 11195, 4926, + 11205, 8775, 1177, 8879, 10434, + 11205, 8775, 1177, 8881, 10434, + 11205, 8775, 1177, 8883, 10434, + 11205, 8775, 1177, 8885, 10434, + 11205, 8775, 1177, 8887, 10434, + 11205, 8775, 1177, 8889, 10434, + 11205, 8775, 1177, 8891, 10434, + 11205, 8775, 1177, 9305, 11114, + 11207, 4926, + 11217, 10265, 9610, + 11224, + 11242, + 11245, 6408, + 11245, 6409, 9537, 600, + 11245, 6409, 9537, 4848, + 11261, 2170, + 11261, 2540, + 11261, 2778, + 11261, 4200, + 11261, 4214, + 11261, 4849, 12114, + 11261, 5190, + 11261, 5445, 5758, + 11261, 6260, + 11261, 6722, + 11261, 7172, + 11261, 7443, 12114, + 11261, 7508, + 11261, 7694, + 11261, 8167, 5758, + 11263, 2724, + 11263, 6121, 10260, + 11263, 8004, + 11265, 5759, 9558, + 11265, 5759, 10408, + 11265, 5759, 11158, + 11265, 5759, 11160, + 11265, 6689, 2170, + 11265, 6689, 2540, + 11265, 6689, 2778, + 11265, 6689, 4200, + 11265, 6689, 4214, + 11265, 6689, 5190, + 11265, 6689, 6260, + 11265, 6689, 6722, + 11265, 6689, 7508, + 11265, 6689, 7694, + 11265, 7803, 5759, 9560, + 11265, 7803, 5759, 9566, + 11265, 7803, 5759, 10402, + 11265, 7803, 5759, 10404, + 11265, 7803, 5759, 11710, + 11265, 7803, 5759, 11712, + 11265, 8405, 0, + 11265, 8405, 8, + 11265, 8405, 16, + 11265, 8405, 28, + 11265, 8405, 40, + 11265, 8405, 66, + 11265, 8405, 100, + 11265, 8405, 116, + 11265, 8405, 138, + 11265, 8405, 188, + 11265, 8405, 196, + 11265, 8405, 216, + 11265, 8405, 236, + 11265, 8405, 292, + 11265, 8405, 306, + 11265, 8405, 332, + 11265, 8405, 364, + 11265, 8405, 392, + 11265, 8405, 462, + 11265, 8405, 496, + 11265, 8405, 510, + 11265, 8405, 524, + 11265, 8405, 556, + 11265, 8405, 610, + 11265, 8405, 622, + 11265, 8405, 638, + 11265, 8405, 652, + 11265, 8405, 670, + 11265, 8405, 1612, + 11265, 8405, 2030, + 11265, 8405, 2126, + 11265, 8405, 2610, + 11265, 10775, 5759, 9564, + 11265, 10775, 5759, 10406, + 11265, 10775, 5759, 11154, + 11355, 5758, + 11355, 10303, 5758, + 11355, 10472, + 11357, 1177, 439, 2681, 7790, + 11357, 1177, 1550, + 11357, 1177, 1749, 445, 7180, + 11357, 1177, 3803, 11754, + 11357, 1177, 4150, + 11357, 1177, 4223, 8056, + 11357, 1177, 6702, + 11357, 1177, 6865, 569, 4944, + 11357, 1177, 6994, + 11357, 1177, 7174, + 11357, 1177, 7428, + 11357, 1177, 7644, + 11357, 1177, 7770, + 11357, 1177, 7810, + 11357, 1177, 7952, + 11357, 1177, 8036, + 11357, 1177, 8042, + 11357, 1177, 8065, 7186, + 11357, 1177, 8156, + 11357, 1177, 8222, + 11357, 1177, 8394, + 11357, 1177, 8618, + 11357, 1177, 8650, + 11357, 1177, 8976, + 11357, 1177, 9026, + 11357, 1177, 9100, + 11357, 1177, 9110, + 11357, 1177, 9168, + 11357, 1177, 9276, + 11357, 1177, 9341, 3696, + 11357, 1177, 9395, 7592, + 11357, 1177, 9402, + 11357, 1177, 9460, + 11357, 1177, 9466, + 11357, 1177, 9550, + 11357, 1177, 9574, + 11357, 1177, 9626, + 11357, 1177, 9696, + 11357, 1177, 9832, + 11357, 1177, 10168, + 11357, 1177, 10210, + 11357, 1177, 10232, + 11357, 1177, 10252, + 11357, 1177, 10486, + 11357, 1177, 10540, + 11357, 1177, 10550, + 11357, 1177, 10673, 445, 9836, + 11357, 1177, 10747, 2186, + 11357, 1177, 10764, + 11357, 1177, 10776, + 11357, 1177, 10792, + 11357, 1177, 10800, + 11357, 1177, 10972, + 11357, 1177, 10998, + 11357, 1177, 11002, + 11357, 1177, 11012, + 11357, 1177, 11013, 274, + 11357, 1177, 11024, + 11357, 1177, 11086, + 11357, 1177, 11210, + 11357, 1177, 11234, + 11357, 1177, 11454, + 11357, 1177, 11456, + 11357, 1177, 11462, + 11357, 1177, 11486, + 11357, 1177, 11610, + 11357, 1177, 11622, + 11357, 1177, 11702, + 11357, 1177, 11752, + 11357, 1177, 11888, + 11357, 1177, 11916, + 11357, 1177, 12012, + 11357, 1177, 12026, + 11357, 1177, 12118, + 11357, 1177, 12392, + 11357, 1177, 12430, + 11357, 1177, 12434, + 11357, 1177, 12436, + 11357, 1177, 12898, + 11357, 1177, 12923, 445, 11484, + 11357, 1177, 12936, + 11360, + 11387, 11205, 8774, + 11389, 12117, 8774, + 11391, 11770, + 11391, 11772, + 11391, 11774, + 11391, 11776, + 11391, 11778, + 11391, 11780, + 11391, 11782, + 11391, 11784, + 11391, 11786, + 11391, 12160, + 11391, 12162, + 11391, 12164, + 11391, 12166, + 11391, 12168, + 11391, 12170, + 11391, 12172, + 11391, 12174, + 11391, 12176, + 11391, 12178, + 11391, 12180, + 11391, 12182, + 11391, 12184, + 11391, 12186, + 11391, 12188, + 11391, 12190, + 11391, 12192, + 11391, 12194, + 11391, 12196, + 11391, 12198, + 11391, 12200, + 11391, 12202, + 11391, 12204, + 11391, 12206, + 11391, 12208, + 11391, 12210, + 11391, 12212, + 11391, 12214, + 11391, 12216, + 11391, 12218, + 11391, 12220, + 11391, 12222, + 11391, 12224, + 11391, 12226, + 11391, 12228, + 11391, 12230, + 11391, 12232, + 11391, 12234, + 11391, 12236, + 11391, 12238, + 11391, 12240, + 11391, 12242, + 11391, 12244, + 11391, 12246, + 11391, 12248, + 11391, 12250, + 11391, 12252, + 11391, 12254, + 11391, 12256, + 11391, 12258, + 11391, 12260, + 11391, 12262, + 11391, 12264, + 11391, 12266, + 11391, 12268, + 11391, 12270, + 11391, 12272, + 11391, 12274, + 11391, 12276, + 11391, 12278, + 11391, 12280, + 11391, 12282, + 11391, 12284, + 11391, 12286, + 11391, 12288, + 11391, 12290, + 11391, 12292, + 11391, 12294, + 11391, 12296, + 11391, 12298, + 11391, 12300, + 11391, 12302, + 11391, 12304, + 11391, 12306, + 11391, 12308, + 11391, 12310, + 11391, 12312, + 11391, 12314, + 11391, 12316, + 11391, 12318, + 11391, 12320, + 11391, 12322, + 11391, 12324, + 11391, 12326, + 11391, 12328, + 11391, 12330, + 11391, 12332, + 11391, 12334, + 11391, 12336, + 11391, 12338, + 11391, 12542, + 11391, 12544, + 11391, 12546, + 11391, 12548, + 11391, 12550, + 11391, 12552, + 11391, 12554, + 11391, 12556, + 11391, 12558, + 11391, 12560, + 11391, 12562, + 11391, 12564, + 11391, 12566, + 11391, 12568, + 11391, 12570, + 11391, 12572, + 11391, 12574, + 11391, 12576, + 11391, 12578, + 11391, 12580, + 11391, 12582, + 11391, 12584, + 11391, 12586, + 11391, 12588, + 11391, 12590, + 11391, 12592, + 11391, 12594, + 11391, 12596, + 11391, 12598, + 11391, 12600, + 11391, 12602, + 11391, 12604, + 11391, 12606, + 11391, 12608, + 11391, 12610, + 11391, 12612, + 11391, 12614, + 11391, 12616, + 11391, 12618, + 11391, 12620, + 11391, 12622, + 11391, 12624, + 11391, 12626, + 11391, 12628, + 11391, 12630, + 11391, 12632, + 11391, 12634, + 11391, 12636, + 11391, 12638, + 11391, 12640, + 11391, 12642, + 11391, 12644, + 11391, 12646, + 11391, 12648, + 11391, 12650, + 11391, 12652, + 11391, 12654, + 11391, 12656, + 11391, 12658, + 11391, 12660, + 11391, 12662, + 11391, 12664, + 11391, 12666, + 11391, 12668, + 11391, 12670, + 11391, 12672, + 11391, 12674, + 11391, 12676, + 11391, 12678, + 11391, 12680, + 11391, 12682, + 11391, 12684, + 11391, 12686, + 11391, 12688, + 11391, 12690, + 11391, 12692, + 11391, 12694, + 11391, 12696, + 11391, 12698, + 11391, 12700, + 11391, 12702, + 11391, 12704, + 11391, 12706, + 11391, 12708, + 11391, 12710, + 11391, 12712, + 11391, 12714, + 11391, 12716, + 11391, 12718, + 11391, 12720, + 11391, 12722, + 11391, 12724, + 11391, 12726, + 11391, 12728, + 11391, 12730, + 11391, 12732, + 11391, 12734, + 11391, 12736, + 11391, 12738, + 11391, 12740, + 11391, 12742, + 11391, 12744, + 11391, 12746, + 11391, 12748, + 11391, 12750, + 11391, 12752, + 11391, 12754, + 11391, 12756, + 11391, 12758, + 11391, 12760, + 11391, 12762, + 11391, 12764, + 11391, 12766, + 11391, 12768, + 11391, 12770, + 11391, 12772, + 11391, 12774, + 11391, 12776, + 11391, 12778, + 11391, 12780, + 11391, 12782, + 11391, 12784, + 11391, 12786, + 11391, 12788, + 11391, 12790, + 11391, 12792, + 11391, 12794, + 11391, 12796, + 11391, 12798, + 11391, 12800, + 11391, 12802, + 11391, 12804, + 11391, 12806, + 11391, 12808, + 11391, 12810, + 11391, 12812, + 11391, 12814, + 11391, 12816, + 11391, 12818, + 11391, 12820, + 11391, 12822, + 11391, 12824, + 11391, 12826, + 11391, 12828, + 11391, 12830, + 11391, 12832, + 11391, 12834, + 11391, 12836, + 11391, 12838, + 11391, 12840, + 11391, 12842, + 11391, 12844, + 11391, 12846, + 11391, 12848, + 11391, 12850, + 11391, 12852, + 11391, 12854, + 11424, + 11427, 2681, 7104, + 11445, 1809, 4876, + 11445, 10388, + 11449, 7908, + 11451, 90, + 11451, 7173, 5758, + 11452, + 11465, 11385, 8774, + 11475, 5238, + 11477, 436, + 11477, 5759, 4423, 9721, 1044, + 11477, 5759, 7282, + 11477, 5759, 8916, + 11477, 5759, 9824, + 11477, 5759, 9870, + 11477, 5759, 9904, + 11477, 5759, 11900, + 11477, 6379, 7908, + 11477, 6646, + 11477, 6689, 2170, + 11477, 6689, 2540, + 11477, 6689, 2778, + 11477, 6689, 4200, + 11477, 6689, 4214, + 11477, 6689, 5190, + 11477, 6689, 6260, + 11477, 6689, 6722, + 11477, 6689, 7508, + 11477, 6689, 7694, + 11477, 6875, 7908, + 11477, 7803, 5759, 8, + 11477, 7803, 5759, 16, + 11477, 7803, 5759, 28, + 11477, 7803, 5759, 40, + 11477, 7803, 5759, 58, + 11477, 7803, 5759, 72, + 11477, 7803, 5759, 92, + 11477, 7803, 5759, 266, + 11477, 7803, 5759, 606, + 11477, 7803, 5759, 7551, 8, + 11477, 7803, 5759, 7551, 28, + 11477, 7803, 5759, 8031, 8, + 11477, 7803, 5759, 8031, 28, + 11477, 7803, 5759, 9827, 22, + 11477, 7803, 5759, 9827, 34, + 11477, 7803, 5759, 9827, 344, + 11477, 7803, 5759, 9827, 518, + 11477, 8153, 6646, + 11477, 8405, 0, + 11477, 8405, 8, + 11477, 8405, 16, + 11477, 8405, 28, + 11477, 8405, 40, + 11477, 8405, 58, + 11477, 8405, 72, + 11477, 8405, 92, + 11477, 8405, 100, + 11477, 8405, 116, + 11477, 8405, 138, + 11477, 8405, 196, + 11477, 8405, 216, + 11477, 8405, 236, + 11477, 8405, 266, + 11477, 8405, 292, + 11477, 8405, 306, + 11477, 8405, 332, + 11477, 8405, 364, + 11477, 8405, 392, + 11477, 8405, 462, + 11477, 8405, 496, + 11477, 8405, 510, + 11477, 8405, 524, + 11477, 8405, 556, + 11477, 8405, 606, + 11477, 8405, 610, + 11477, 8405, 652, + 11477, 8405, 670, + 11477, 8405, 766, + 11477, 8405, 792, + 11477, 8405, 884, + 11477, 8405, 974, + 11477, 8405, 996, + 11477, 8405, 1250, + 11477, 8405, 1260, + 11477, 8405, 1512, + 11477, 8405, 1528, + 11477, 8405, 1612, + 11477, 8405, 1796, + 11477, 8405, 2030, + 11477, 8405, 2076, + 11477, 8405, 2126, + 11477, 8405, 2212, + 11477, 8405, 2410, + 11477, 8405, 2438, + 11477, 8405, 2516, + 11477, 8405, 2566, + 11477, 8405, 2678, + 11477, 8405, 2746, + 11477, 8405, 3110, + 11477, 8405, 4008, + 11477, 8405, 4016, + 11477, 8405, 4320, + 11477, 8405, 4748, + 11477, 8405, 4888, + 11477, 8405, 5234, + 11477, 8405, 5994, + 11477, 8405, 6658, + 11477, 8405, 7551, 0, + 11477, 8405, 7551, 8, + 11477, 8405, 7551, 28, + 11477, 8405, 8031, 0, + 11477, 8405, 8031, 8, + 11477, 8405, 8031, 28, + 11477, 8405, 9313, 5836, + 11477, 8405, 9827, 22, + 11477, 8405, 9827, 34, + 11477, 8405, 9827, 344, + 11477, 8405, 9827, 518, + 11477, 8755, 5759, 8892, + 11477, 8755, 5759, 9868, + 11477, 12391, 5758, + 11479, 9042, + 11605, 12492, + 11621, 568, + 11621, 6121, 4215, 4113, 6376, + 11641, 7593, 8405, 16, + 11641, 7593, 8405, 468, + 11641, 7593, 8405, 660, + 11641, 7593, 8405, 664, + 11641, 7593, 8405, 746, + 11641, 7593, 8405, 807, 3096, + 11641, 7593, 8405, 2176, + 11641, 7593, 8405, 2184, + 11641, 7593, 8405, 2516, + 11641, 7593, 8405, 2736, + 11641, 7593, 8405, 2808, + 11641, 7593, 8405, 3810, + 11641, 7593, 8405, 4198, + 11641, 7593, 8405, 4406, + 11641, 7593, 8405, 4626, + 11641, 7593, 8405, 4712, + 11641, 7593, 8405, 5718, + 11641, 7593, 8405, 6076, + 11641, 7593, 8405, 6188, + 11641, 7593, 8405, 6198, + 11641, 7593, 8405, 6200, + 11641, 7593, 8405, 6698, + 11641, 7593, 8405, 6710, + 11641, 7593, 8405, 6810, + 11641, 7593, 8405, 7210, + 11641, 7593, 8405, 7444, + 11641, 7593, 8405, 7590, + 11641, 7593, 8405, 7593, 3096, + 11641, 7593, 8405, 7593, 3097, 6121, 5878, + 11641, 7593, 8405, 7856, + 11641, 7593, 8405, 8050, + 11641, 7593, 8405, 8124, + 11641, 7593, 8405, 8606, + 11641, 7593, 8405, 8872, + 11641, 7593, 8405, 8958, + 11641, 7593, 8405, 9310, + 11641, 7593, 8405, 9363, 4626, + 11641, 7593, 8405, 9371, 807, 3096, + 11641, 7593, 8405, 9371, 7593, 3096, + 11641, 7593, 8405, 9372, + 11641, 7593, 8405, 9434, + 11641, 7593, 8405, 9486, + 11641, 7593, 8405, 9686, + 11641, 7593, 8405, 9727, 236, + 11641, 7593, 8405, 9850, + 11641, 7593, 8405, 10299, 9486, + 11641, 7593, 8405, 11867, 0, + 11641, 9063, 8405, 16, + 11641, 9063, 8405, 468, + 11641, 9063, 8405, 660, + 11641, 9063, 8405, 664, + 11641, 9063, 8405, 746, + 11641, 9063, 8405, 807, 3096, + 11641, 9063, 8405, 2176, + 11641, 9063, 8405, 2184, + 11641, 9063, 8405, 2516, + 11641, 9063, 8405, 2736, + 11641, 9063, 8405, 2808, + 11641, 9063, 8405, 3810, + 11641, 9063, 8405, 4198, + 11641, 9063, 8405, 4406, + 11641, 9063, 8405, 4626, + 11641, 9063, 8405, 4712, + 11641, 9063, 8405, 5718, + 11641, 9063, 8405, 6076, + 11641, 9063, 8405, 6188, + 11641, 9063, 8405, 6198, + 11641, 9063, 8405, 6200, + 11641, 9063, 8405, 6698, + 11641, 9063, 8405, 6710, + 11641, 9063, 8405, 6810, + 11641, 9063, 8405, 7210, + 11641, 9063, 8405, 7444, + 11641, 9063, 8405, 7590, + 11641, 9063, 8405, 7593, 3096, + 11641, 9063, 8405, 7593, 3097, 6121, 5878, + 11641, 9063, 8405, 7856, + 11641, 9063, 8405, 8050, + 11641, 9063, 8405, 8124, + 11641, 9063, 8405, 8606, + 11641, 9063, 8405, 8872, + 11641, 9063, 8405, 8958, + 11641, 9063, 8405, 9310, + 11641, 9063, 8405, 9363, 4626, + 11641, 9063, 8405, 9371, 807, 3096, + 11641, 9063, 8405, 9371, 7593, 3096, + 11641, 9063, 8405, 9372, + 11641, 9063, 8405, 9434, + 11641, 9063, 8405, 9486, + 11641, 9063, 8405, 9686, + 11641, 9063, 8405, 9727, 236, + 11641, 9063, 8405, 9850, + 11641, 9063, 8405, 10299, 9486, + 11641, 9063, 8405, 11867, 0, + 11646, + 11649, 760, + 11649, 4877, 10982, + 11649, 4923, 6121, 8759, 5758, + 11649, 5643, 8412, + 11649, 5643, 8414, + 11649, 5643, 8416, + 11649, 5643, 8418, + 11649, 6505, 9338, + 11649, 10154, + 11651, 8774, + 11661, 10256, + 11667, 5759, 761, 6376, + 11667, 5759, 1045, 6490, + 11667, 5759, 6548, + 11667, 5759, 8153, 5551, 6490, + 11667, 5759, 9824, + 11667, 5759, 9870, + 11667, 6689, 2170, + 11667, 6689, 2778, + 11667, 6689, 4214, + 11667, 6689, 7694, + 11667, 7803, 5759, 8, + 11667, 7803, 5759, 16, + 11667, 7803, 5759, 28, + 11667, 7803, 5759, 40, + 11667, 7803, 5759, 9827, 34, + 11667, 7803, 8399, 4926, + 11667, 8405, 0, + 11667, 8405, 100, + 11667, 8405, 116, + 11667, 8405, 138, + 11667, 8405, 216, + 11667, 8405, 236, + 11667, 8405, 292, + 11667, 8405, 306, + 11667, 8405, 332, + 11667, 8405, 364, + 11667, 8405, 392, + 11667, 8405, 462, + 11667, 8405, 510, + 11667, 8405, 524, + 11667, 8405, 556, + 11667, 8405, 610, + 11667, 8405, 652, + 11667, 8405, 670, + 11667, 8405, 792, + 11667, 8405, 884, + 11667, 8405, 974, + 11667, 8405, 996, + 11667, 8405, 1260, + 11667, 8405, 1612, + 11667, 8405, 1642, + 11667, 8405, 2076, + 11667, 8405, 2126, + 11667, 8405, 2212, + 11667, 8405, 2516, + 11667, 8405, 2566, + 11667, 8405, 2678, + 11667, 8405, 2746, + 11667, 8405, 4016, + 11667, 8405, 5994, + 11667, 8405, 7750, + 11667, 8525, 2171, 9344, + 11667, 8525, 2171, 10624, + 11667, 8525, 2670, + 11667, 8525, 8876, + 11667, 8916, + 11667, 12133, 1044, + 11667, 12133, 6646, + 11667, 12133, 7108, + 11667, 12133, 7114, + 11667, 12133, 7593, 8056, + 11667, 12133, 8056, + 11667, 12133, 8153, 6646, + 11667, 12133, 9965, 760, + 11667, 12133, 10318, + 11687, 8774, + 11700, + 11702, + 11725, 8153, 12132, + 11725, 8717, 12132, + 11727, 6129, 11228, + 11727, 8405, 238, + 11727, 8405, 468, + 11727, 8405, 710, + 11727, 8405, 714, + 11727, 8405, 788, + 11727, 8405, 1366, + 11727, 8405, 1578, + 11727, 8405, 1892, + 11727, 8405, 2110, + 11727, 8405, 2318, + 11727, 8405, 2658, + 11727, 8405, 2674, + 11727, 8405, 2916, + 11727, 8405, 3080, + 11727, 8405, 3126, + 11727, 8405, 4058, + 11727, 8405, 4238, + 11727, 8405, 4832, + 11727, 8405, 5568, + 11727, 8405, 5624, + 11727, 8405, 5652, + 11727, 8405, 5698, + 11727, 8525, 2170, + 11727, 8525, 2171, 9344, + 11727, 8525, 2670, + 11727, 8525, 8876, + 11731, 5758, + 11736, + 11740, + 11745, 10261, 10374, + 11747, 6741, 568, + 11749, 5758, + 11763, 731, 10763, 6434, + 11765, 2779, 8289, 6434, + 11765, 6105, 6434, + 11765, 6434, + 11765, 6435, 569, 760, + 11765, 6435, 569, 6505, 9158, + 11765, 6435, 4221, 760, + 11765, 6435, 4221, 761, 569, 6505, 9158, + 11765, 6435, 5387, 11097, 6434, + 11765, 6435, 6121, 2697, 9810, + 11765, 6435, 6121, 2697, 10958, + 11765, 6435, 6121, 4530, + 11765, 6435, 6121, 4896, + 11765, 6435, 6121, 5445, 6490, + 11765, 6435, 6121, 5878, + 11765, 6435, 6121, 5879, 6121, 8153, 10677, 8758, + 11765, 6435, 6121, 5879, 6121, 10677, 8758, + 11765, 6435, 6121, 8077, 10958, + 11765, 6435, 6121, 8151, 5832, + 11765, 6435, 6121, 8153, 10677, 8758, + 11765, 6435, 6121, 8758, + 11765, 6435, 6121, 10677, 8758, + 11765, 6435, 6377, 7551, 11097, 6434, + 11765, 6435, 6377, 7709, 10374, + 11765, 6435, 6377, 7919, 6741, 568, + 11765, 6435, 6377, 9633, 7709, 10374, + 11765, 6435, 6377, 9633, 7919, 6741, 568, + 11765, 6435, 9785, 46, + 11765, 6435, 9785, 10578, + 11765, 6435, 9785, 12472, + 11765, 7821, 6434, + 11765, 7821, 6435, 4221, 6102, + 11765, 8097, 6434, + 11765, 8153, 3993, 6434, + 11765, 8153, 6434, + 11765, 8153, 6435, 4221, 760, + 11765, 8153, 6435, 6121, 8758, + 11765, 8153, 6435, 6121, 10677, 8758, + 11765, 8153, 11430, + 11765, 8561, 7944, + 11765, 8849, 3993, 6434, + 11765, 8849, 6434, + 11765, 9327, 5387, 11097, 9326, + 11765, 9327, 6121, 3713, 601, 569, 760, + 11765, 9327, 6121, 3713, 601, 4221, 760, + 11765, 9327, 6121, 3713, 601, 6377, 4895, 3992, + 11765, 9327, 6121, 3713, 601, 6377, 11097, 9327, 6121, 3713, 600, + 11765, 9327, 6121, 3713, 601, 6377, 11765, 9327, 6121, 3713, 4116, + 11765, 9327, 6121, 3713, 4117, 569, 760, + 11765, 9327, 6121, 3713, 4117, 4221, 760, + 11765, 9327, 6121, 3713, 4117, 6377, 11097, 9327, 6121, 3713, 4116, + 11765, 9327, 6121, 3713, 4117, 6491, 4895, 3992, + 11765, 9327, 6121, 3713, 9810, + 11765, 9327, 6121, 3713, 10958, + 11765, 10531, 6434, + 11765, 11191, 6434, + 11765, 11430, + 11765, 11875, 6435, 4221, 760, + 11765, 11875, 6435, 6121, 5878, + 11765, 11875, 6435, 6121, 5879, 6121, 8153, 10677, 8758, + 11765, 11875, 6435, 6121, 5879, 6121, 10677, 8758, + 11765, 11875, 6435, 6121, 8153, 10677, 8758, + 11765, 11875, 6435, 6121, 10677, 8758, + 11765, 11875, 8849, 3993, 6434, + 11765, 12103, 6434, + 11769, 5759, 8916, + 11769, 5759, 9824, + 11769, 5759, 9870, + 11769, 6646, + 11769, 6689, 2170, + 11769, 6689, 2540, + 11769, 6689, 2778, + 11769, 6689, 4200, + 11769, 6689, 4214, + 11769, 6689, 5190, + 11769, 6689, 6260, + 11769, 6689, 6722, + 11769, 6689, 7508, + 11769, 6689, 7694, + 11769, 7803, 5759, 8, + 11769, 7803, 5759, 16, + 11769, 7803, 5759, 28, + 11769, 7803, 5759, 40, + 11769, 7803, 5759, 58, + 11769, 7803, 5759, 72, + 11769, 7803, 5759, 92, + 11769, 7803, 5759, 162, + 11769, 7803, 5759, 266, + 11769, 7803, 5759, 440, + 11769, 7803, 5759, 606, + 11769, 7803, 5759, 9827, 22, + 11769, 7803, 5759, 9827, 34, + 11769, 7803, 5759, 9827, 344, + 11769, 7803, 5759, 9827, 518, + 11769, 8153, 6646, + 11769, 8405, 0, + 11769, 8405, 8, + 11769, 8405, 16, + 11769, 8405, 28, + 11769, 8405, 40, + 11769, 8405, 58, + 11769, 8405, 72, + 11769, 8405, 92, + 11769, 8405, 100, + 11769, 8405, 116, + 11769, 8405, 138, + 11769, 8405, 162, + 11769, 8405, 216, + 11769, 8405, 236, + 11769, 8405, 266, + 11769, 8405, 292, + 11769, 8405, 306, + 11769, 8405, 332, + 11769, 8405, 364, + 11769, 8405, 392, + 11769, 8405, 440, + 11769, 8405, 462, + 11769, 8405, 510, + 11769, 8405, 524, + 11769, 8405, 556, + 11769, 8405, 606, + 11769, 8405, 610, + 11769, 8405, 652, + 11769, 8405, 792, + 11769, 8405, 884, + 11769, 8405, 974, + 11769, 8405, 996, + 11769, 8405, 1260, + 11769, 8405, 1512, + 11769, 8405, 1612, + 11769, 8405, 1796, + 11769, 8405, 2030, + 11769, 8405, 2076, + 11769, 8405, 2126, + 11769, 8405, 2212, + 11769, 8405, 2516, + 11769, 8405, 2566, + 11769, 8405, 2678, + 11769, 8405, 2746, + 11769, 8405, 4016, + 11769, 8405, 5994, + 11769, 8405, 9827, 22, + 11769, 8405, 9827, 34, + 11769, 8405, 9827, 344, + 11769, 8405, 9827, 518, + 11769, 10775, 5759, 6888, + 11793, 9611, 6121, 8005, 8064, + 11801, 5385, 826, + 11819, 7608, + 11859, 8022, + 11881, 8774, + 11893, 1611, 8774, + 11899, 10513, 7821, 11765, 6434, + 11905, 10212, + 11909, 8774, + 11910, + 11921, 568, + 11922, + 11924, + 12007, 6741, 569, 445, 11098, + 12007, 6741, 569, 445, 12472, + 12007, 9705, 6741, 569, 445, 11098, + 12007, 9705, 6741, 569, 445, 12472, + 12007, 9705, 11099, 445, 6741, 568, + 12007, 9705, 12473, 445, 6741, 568, + 12015, 568, + 12017, 4926, + 12017, 10469, 4926, + 12021, 7608, + 12041, 7382, + 12043, 4223, 5836, + 12043, 4389, 4193, 7608, + 12043, 6616, + 12043, 7097, 5965, 4926, + 12043, 7608, + 12043, 8525, 6260, + 12043, 8649, 5965, 4926, + 12043, 9099, 4926, + 12043, 10161, 5965, 4926, + 12043, 10799, 5965, 4926, + 12043, 11067, 4926, + 12043, 11353, 4877, 4183, 11229, 8774, + 12043, 11353, 8775, 1177, 973, 2170, + 12043, 11353, 8775, 1177, 973, 2540, + 12043, 11353, 8775, 1177, 973, 2670, + 12043, 11353, 8775, 1177, 973, 2778, + 12043, 11353, 8775, 1177, 973, 4200, + 12043, 11353, 8775, 1177, 973, 4214, + 12043, 11353, 8775, 1177, 973, 5190, + 12043, 11353, 8775, 1177, 973, 6722, + 12043, 11353, 8775, 1177, 973, 7508, + 12043, 11353, 8775, 1177, 973, 7694, + 12043, 11353, 8775, 1177, 973, 8162, + 12043, 11353, 8775, 1177, 973, 8820, + 12043, 11353, 8775, 1177, 973, 8874, + 12043, 11353, 8775, 1177, 973, 8876, + 12043, 11353, 8775, 1177, 973, 9286, + 12043, 11353, 8775, 1177, 973, 9700, + 12043, 11353, 8775, 1177, 973, 10150, + 12043, 11353, 8775, 1177, 973, 10200, + 12043, 11353, 8775, 1177, 973, 10360, + 12043, 11353, 8775, 1177, 973, 10622, + 12043, 11353, 8775, 1177, 973, 11232, + 12043, 11353, 8775, 1177, 973, 11854, + 12043, 11353, 8775, 1177, 973, 11868, + 12043, 11353, 8775, 1177, 973, 11870, + 12043, 11353, 8775, 1177, 973, 11872, + 12043, 11353, 8775, 1177, 973, 12374, + 12043, 11353, 8775, 1177, 973, 12376, + 12043, 11353, 8775, 1177, 973, 12378, + 12043, 11353, 8775, 1177, 973, 12888, + 12043, 11353, 8775, 1177, 973, 12890, + 12043, 11353, 8775, 1177, 973, 12892, + 12043, 11353, 8775, 1177, 1870, + 12043, 11353, 8775, 1177, 4541, 2170, + 12043, 11353, 8775, 1177, 4541, 2540, + 12043, 11353, 8775, 1177, 4541, 2670, + 12043, 11353, 8775, 1177, 4541, 2778, + 12043, 11353, 8775, 1177, 4541, 4200, + 12043, 11353, 8775, 1177, 4541, 4214, + 12043, 11353, 8775, 1177, 4541, 5190, + 12043, 11353, 8775, 1177, 4541, 6260, + 12043, 11353, 8775, 1177, 4541, 6722, + 12043, 11353, 8775, 1177, 4541, 7508, + 12043, 11353, 8775, 1177, 4541, 7694, + 12043, 11353, 8775, 1177, 4541, 8162, + 12043, 11353, 8775, 1177, 4541, 8874, + 12043, 11353, 8775, 1177, 4541, 8876, + 12043, 11353, 8775, 1177, 4541, 9286, + 12043, 11353, 8775, 1177, 4541, 9700, + 12043, 11353, 8775, 1177, 4541, 10150, + 12043, 11353, 8775, 1177, 4541, 10200, + 12043, 11353, 8775, 1177, 4541, 10360, + 12043, 11353, 8775, 1177, 4541, 10622, + 12043, 11353, 8775, 1177, 4541, 11232, + 12043, 11353, 8775, 1177, 4541, 11868, + 12043, 11353, 8775, 1177, 4541, 11872, + 12043, 11353, 8775, 1177, 4541, 12376, + 12043, 11353, 8775, 1177, 4541, 12892, + 12043, 11353, 8775, 1177, 4682, + 12043, 11353, 8775, 1177, 4684, + 12043, 11353, 8775, 1177, 6420, + 12043, 11353, 8775, 1177, 7136, + 12043, 11353, 8775, 1177, 7958, + 12043, 11353, 8775, 1177, 9374, + 12043, 11353, 8775, 1177, 9528, + 12043, 11353, 8775, 1177, 9990, + 12043, 11353, 8775, 1177, 10176, + 12043, 11353, 8775, 1177, 10368, + 12043, 11353, 8775, 1177, 11230, + 12043, 11391, 11054, + 12043, 11415, 1861, 4926, + 12043, 11415, 2171, 4926, + 12043, 11415, 2725, 4926, + 12043, 11415, 2779, 4926, + 12043, 11415, 4215, 4926, + 12043, 11415, 6717, 4926, + 12043, 11415, 6791, 4926, + 12043, 11415, 7687, 4926, + 12043, 11415, 7695, 4926, + 12043, 11415, 8005, 4926, + 12043, 11415, 8233, 4926, + 12043, 11415, 8291, 4926, + 12043, 11415, 8473, 4926, + 12043, 11415, 8681, 4926, + 12043, 11415, 9433, 4926, + 12043, 11415, 9633, 4926, + 12043, 11937, 10759, 4223, 10580, + 12043, 11937, 10759, 4849, 569, 7442, + 12043, 11937, 10759, 4849, 569, 8473, 721, 7442, + 12043, 11937, 10759, 6377, 569, 6490, + 12043, 11937, 10759, 6377, 569, 8473, 721, 6490, + 12043, 11937, 10759, 10386, + 12043, 11937, 10759, 10581, 4221, 4848, + 12043, 11937, 10759, 10581, 4221, 6376, + 12043, 11937, 10759, 10581, 4221, 6490, + 12043, 11937, 10759, 10581, 4221, 7121, 4848, + 12043, 11937, 10759, 10581, 4221, 7773, 4848, + 12043, 11937, 10759, 10581, 4221, 7773, 7442, + 12055, 8724, + 12058, + 12061, 11415, 7922, + 12061, 11415, 11228, + 12061, 11415, 11850, + 12063, 8197, 721, 4923, 5758, + 12064, + 12075, 7821, 11765, 6434, + 12108, + 12117, 5758, + 12122, + 12133, 7608, + 12135, 5758, + 12143, 10758, + 12156, + 12342, + 12355, 2170, + 12355, 2540, + 12355, 2778, + 12355, 4200, + 12355, 4214, + 12355, 4849, 12114, + 12355, 5190, + 12355, 5445, 5758, + 12355, 6260, + 12355, 6722, + 12355, 7089, 7593, 8405, 16, + 12355, 7089, 7593, 8405, 26, + 12355, 7172, + 12355, 7443, 12114, + 12355, 7508, + 12355, 7694, + 12355, 8167, 5758, + 12371, 12492, + 12383, 10643, 6121, 4849, 4389, 6504, + 12383, 10643, 6121, 7443, 4389, 6504, + 12396, + 12399, 445, 10780, + 12403, 2209, 2671, 10625, 5758, + 12403, 2209, 7171, 5758, + 12403, 3961, 5566, + 12403, 6689, 2170, + 12403, 6689, 2540, + 12403, 6689, 2778, + 12403, 6689, 4200, + 12403, 6689, 4214, + 12403, 6689, 5190, + 12403, 6689, 6260, + 12403, 6689, 6722, + 12403, 6689, 7508, + 12403, 6689, 7694, + 12403, 8233, 5566, + 12413, 9063, 4, + 12413, 9063, 14, + 12413, 9063, 16, + 12413, 9063, 34, + 12413, 9063, 50, + 12428, + 12461, 10346, + 12463, 6505, 8056, + 12463, 6505, 8744, + 12463, 6505, 9158, + 12463, 7821, 8056, + 12463, 7821, 8744, + 12463, 7821, 9158, + 12464, + 12467, 10513, 7821, 11765, 6434, + 12473, 445, 6741, 568, + 12473, 445, 9705, 6741, 568, + 12473, 445, 9705, 6741, 569, 6121, 1045, 6376, + 12473, 445, 9705, 6741, 569, 6121, 1045, 6377, 4848, + 12473, 445, 9705, 6741, 569, 6121, 1045, 8318, + 12473, 445, 11098, + 12473, 445, 11621, 568, + 12473, 445, 11896, + 12473, 721, 2091, 11896, + 12473, 721, 12345, 2091, 6741, 568, + 12473, 835, 2091, 6741, 568, + 12473, 835, 2091, 11621, 568, + 12473, 5387, 6741, 568, + 12473, 5758, + 12473, 6121, 1044, + 12473, 6121, 8057, 8318, + 12473, 6121, 10469, 4927, 6376, + 12473, 6377, 9693, 445, 6740, + 12473, 6377, 9693, 6377, 11098, + 12473, 6377, 9705, 6741, 6377, 11099, 6377, 9705, 6740, + 12473, 6377, 11099, 6377, 12007, 6740, + 12473, 6377, 11765, 6434, + 12473, 6377, 12007, 6741, 6377, 11098, + 12473, 6741, 569, 445, 11098, + 12473, 7991, 11098, + 12473, 8065, 115, 6628, + 12473, 8065, 115, 6629, 6377, 9705, 6740, + 12473, 12105, 11098, + 12478, + 12480, + 12492, + 12493, 6121, 1044, + 12493, 6121, 9437, 720, + 12493, 6121, 9546, + 12493, 6377, 761, 6377, 7768, + 12493, 6377, 7768, + 12493, 7991, 721, 8329, 6121, 12492, + 12505, 3803, 477, 8774, + 12505, 3803, 2217, 8774, + 12505, 3803, 2413, 8774, + 12505, 3803, 6689, 2170, + 12505, 3803, 6689, 2540, + 12505, 3803, 6689, 2778, + 12505, 3803, 6689, 4200, + 12505, 3803, 6689, 4214, + 12505, 3803, 6689, 5190, + 12505, 3803, 6689, 6260, + 12505, 3803, 6689, 6722, + 12505, 3803, 6689, 7508, + 12505, 3803, 6689, 7694, + 12505, 3803, 7023, 8774, + 12505, 3803, 7202, + 12505, 3803, 7593, 0, + 12505, 3803, 7593, 2, + 12505, 3803, 7593, 4, + 12505, 3803, 7593, 6, + 12505, 3803, 7593, 8, + 12505, 3803, 7593, 10, + 12505, 3803, 7593, 12, + 12505, 3803, 7593, 14, + 12505, 3803, 7593, 16, + 12505, 3803, 7593, 18, + 12505, 3803, 7593, 20, + 12505, 3803, 7593, 22, + 12505, 3803, 7593, 24, + 12505, 3803, 7593, 26, + 12505, 3803, 7593, 28, + 12505, 3803, 7593, 30, + 12505, 3803, 7593, 32, + 12505, 3803, 7593, 34, + 12505, 3803, 7593, 36, + 12505, 3803, 7593, 38, + 12505, 3803, 7593, 40, + 12505, 3803, 7593, 42, + 12505, 3803, 7593, 44, + 12505, 3803, 7593, 46, + 12505, 3803, 7593, 48, + 12505, 3803, 7593, 50, + 12505, 3803, 7593, 384, + 12505, 3803, 7593, 416, + 12505, 3803, 7593, 476, + 12505, 3803, 7593, 644, + 12505, 3803, 7593, 888, + 12505, 3803, 7593, 1128, + 12505, 3803, 7593, 2216, + 12505, 3803, 7593, 2250, + 12505, 3803, 7593, 2412, + 12505, 3803, 7593, 2658, + 12505, 3803, 7593, 3774, + 12505, 3803, 7593, 4614, + 12505, 3803, 7593, 6262, + 12505, 3803, 7593, 6406, + 12505, 3803, 7593, 6674, + 12505, 3803, 7593, 6789, 7568, + 12505, 3803, 7593, 6824, + 12505, 3803, 7593, 7022, + 12505, 3803, 7593, 7080, + 12505, 3803, 7593, 7316, + 12505, 3803, 7593, 7568, + 12505, 3803, 7593, 7682, + 12505, 3803, 7593, 9162, + 12505, 3803, 7593, 9270, + 12505, 3803, 7593, 9530, + 12505, 3803, 7593, 9808, + 12505, 3803, 7683, 8774, + 12505, 3803, 8325, 477, 8774, + 12505, 3803, 8325, 2217, 8774, + 12505, 3803, 8325, 2413, 8774, + 12505, 3803, 8325, 7023, 8774, + 12505, 3803, 8325, 7202, + 12505, 3803, 8325, 7593, 0, + 12505, 3803, 8325, 7593, 2, + 12505, 3803, 8325, 7593, 4, + 12505, 3803, 8325, 7593, 6, + 12505, 3803, 8325, 7593, 8, + 12505, 3803, 8325, 7593, 10, + 12505, 3803, 8325, 7593, 12, + 12505, 3803, 8325, 7593, 14, + 12505, 3803, 8325, 7593, 16, + 12505, 3803, 8325, 7593, 18, + 12505, 3803, 8325, 7593, 20, + 12505, 3803, 8325, 7593, 22, + 12505, 3803, 8325, 7593, 24, + 12505, 3803, 8325, 7593, 26, + 12505, 3803, 8325, 7593, 28, + 12505, 3803, 8325, 7593, 30, + 12505, 3803, 8325, 7593, 32, + 12505, 3803, 8325, 7593, 34, + 12505, 3803, 8325, 7593, 36, + 12505, 3803, 8325, 7593, 38, + 12505, 3803, 8325, 7593, 40, + 12505, 3803, 8325, 7593, 42, + 12505, 3803, 8325, 7593, 44, + 12505, 3803, 8325, 7593, 46, + 12505, 3803, 8325, 7593, 48, + 12505, 3803, 8325, 7593, 50, + 12505, 3803, 8325, 7593, 384, + 12505, 3803, 8325, 7593, 416, + 12505, 3803, 8325, 7593, 476, + 12505, 3803, 8325, 7593, 644, + 12505, 3803, 8325, 7593, 888, + 12505, 3803, 8325, 7593, 1128, + 12505, 3803, 8325, 7593, 2216, + 12505, 3803, 8325, 7593, 2250, + 12505, 3803, 8325, 7593, 2412, + 12505, 3803, 8325, 7593, 2658, + 12505, 3803, 8325, 7593, 3774, + 12505, 3803, 8325, 7593, 4614, + 12505, 3803, 8325, 7593, 6262, + 12505, 3803, 8325, 7593, 6406, + 12505, 3803, 8325, 7593, 6674, + 12505, 3803, 8325, 7593, 6789, 7568, + 12505, 3803, 8325, 7593, 6824, + 12505, 3803, 8325, 7593, 7022, + 12505, 3803, 8325, 7593, 7080, + 12505, 3803, 8325, 7593, 7316, + 12505, 3803, 8325, 7593, 7568, + 12505, 3803, 8325, 7593, 7682, + 12505, 3803, 8325, 7593, 9270, + 12505, 3803, 8325, 7593, 9530, + 12505, 3803, 8325, 7593, 9808, + 12505, 3803, 8325, 7683, 8774, + 12505, 3803, 8325, 9063, 0, + 12505, 3803, 8325, 9063, 2, + 12505, 3803, 8325, 9063, 4, + 12505, 3803, 8325, 9063, 6, + 12505, 3803, 8325, 9063, 8, + 12505, 3803, 8325, 9063, 10, + 12505, 3803, 8325, 9063, 12, + 12505, 3803, 8325, 9063, 14, + 12505, 3803, 8325, 9063, 16, + 12505, 3803, 8325, 9063, 18, + 12505, 3803, 8325, 9063, 20, + 12505, 3803, 8325, 9063, 22, + 12505, 3803, 8325, 9063, 24, + 12505, 3803, 8325, 9063, 26, + 12505, 3803, 8325, 9063, 28, + 12505, 3803, 8325, 9063, 30, + 12505, 3803, 8325, 9063, 32, + 12505, 3803, 8325, 9063, 34, + 12505, 3803, 8325, 9063, 36, + 12505, 3803, 8325, 9063, 38, + 12505, 3803, 8325, 9063, 40, + 12505, 3803, 8325, 9063, 42, + 12505, 3803, 8325, 9063, 44, + 12505, 3803, 8325, 9063, 46, + 12505, 3803, 8325, 9063, 48, + 12505, 3803, 8325, 9063, 50, + 12505, 3803, 8325, 9063, 384, + 12505, 3803, 8325, 9063, 416, + 12505, 3803, 8325, 9063, 476, + 12505, 3803, 8325, 9063, 644, + 12505, 3803, 8325, 9063, 888, + 12505, 3803, 8325, 9063, 1128, + 12505, 3803, 8325, 9063, 2216, + 12505, 3803, 8325, 9063, 2250, + 12505, 3803, 8325, 9063, 2412, + 12505, 3803, 8325, 9063, 2658, + 12505, 3803, 8325, 9063, 3774, + 12505, 3803, 8325, 9063, 4614, + 12505, 3803, 8325, 9063, 6262, + 12505, 3803, 8325, 9063, 6406, + 12505, 3803, 8325, 9063, 6674, + 12505, 3803, 8325, 9063, 6824, + 12505, 3803, 8325, 9063, 7022, + 12505, 3803, 8325, 9063, 7080, + 12505, 3803, 8325, 9063, 7316, + 12505, 3803, 8325, 9063, 7568, + 12505, 3803, 8325, 9063, 7682, + 12505, 3803, 8325, 9063, 7683, 8774, + 12505, 3803, 8325, 9063, 9270, + 12505, 3803, 8325, 9063, 9530, + 12505, 3803, 8325, 9063, 9808, + 12505, 3803, 8325, 9271, 8774, + 12505, 3803, 8325, 9573, 12432, + 12505, 3803, 8679, 7593, 0, + 12505, 3803, 8679, 7593, 2, + 12505, 3803, 8679, 7593, 4, + 12505, 3803, 8679, 7593, 6, + 12505, 3803, 8679, 7593, 8, + 12505, 3803, 8679, 7593, 10, + 12505, 3803, 8679, 7593, 12, + 12505, 3803, 8679, 7593, 14, + 12505, 3803, 8679, 7593, 16, + 12505, 3803, 8679, 7593, 18, + 12505, 3803, 8679, 7593, 20, + 12505, 3803, 8679, 7593, 22, + 12505, 3803, 8679, 7593, 24, + 12505, 3803, 8679, 7593, 26, + 12505, 3803, 8679, 7593, 28, + 12505, 3803, 8679, 7593, 30, + 12505, 3803, 8679, 7593, 32, + 12505, 3803, 8679, 7593, 34, + 12505, 3803, 8679, 7593, 36, + 12505, 3803, 8679, 7593, 38, + 12505, 3803, 8679, 7593, 40, + 12505, 3803, 8679, 7593, 42, + 12505, 3803, 8679, 7593, 44, + 12505, 3803, 8679, 7593, 46, + 12505, 3803, 8679, 7593, 48, + 12505, 3803, 8679, 7593, 50, + 12505, 3803, 8679, 9063, 0, + 12505, 3803, 8679, 9063, 2, + 12505, 3803, 8679, 9063, 4, + 12505, 3803, 8679, 9063, 6, + 12505, 3803, 8679, 9063, 8, + 12505, 3803, 8679, 9063, 10, + 12505, 3803, 8679, 9063, 12, + 12505, 3803, 8679, 9063, 14, + 12505, 3803, 8679, 9063, 16, + 12505, 3803, 8679, 9063, 18, + 12505, 3803, 8679, 9063, 20, + 12505, 3803, 8679, 9063, 22, + 12505, 3803, 8679, 9063, 24, + 12505, 3803, 8679, 9063, 26, + 12505, 3803, 8679, 9063, 28, + 12505, 3803, 8679, 9063, 30, + 12505, 3803, 8679, 9063, 32, + 12505, 3803, 8679, 9063, 34, + 12505, 3803, 8679, 9063, 36, + 12505, 3803, 8679, 9063, 38, + 12505, 3803, 8679, 9063, 40, + 12505, 3803, 8679, 9063, 42, + 12505, 3803, 8679, 9063, 44, + 12505, 3803, 8679, 9063, 46, + 12505, 3803, 8679, 9063, 48, + 12505, 3803, 8679, 9063, 50, + 12505, 3803, 9063, 0, + 12505, 3803, 9063, 2, + 12505, 3803, 9063, 4, + 12505, 3803, 9063, 6, + 12505, 3803, 9063, 8, + 12505, 3803, 9063, 10, + 12505, 3803, 9063, 12, + 12505, 3803, 9063, 14, + 12505, 3803, 9063, 16, + 12505, 3803, 9063, 18, + 12505, 3803, 9063, 20, + 12505, 3803, 9063, 22, + 12505, 3803, 9063, 24, + 12505, 3803, 9063, 26, + 12505, 3803, 9063, 28, + 12505, 3803, 9063, 30, + 12505, 3803, 9063, 32, + 12505, 3803, 9063, 34, + 12505, 3803, 9063, 36, + 12505, 3803, 9063, 38, + 12505, 3803, 9063, 40, + 12505, 3803, 9063, 42, + 12505, 3803, 9063, 44, + 12505, 3803, 9063, 46, + 12505, 3803, 9063, 48, + 12505, 3803, 9063, 50, + 12505, 3803, 9063, 384, + 12505, 3803, 9063, 416, + 12505, 3803, 9063, 476, + 12505, 3803, 9063, 644, + 12505, 3803, 9063, 888, + 12505, 3803, 9063, 1128, + 12505, 3803, 9063, 2216, + 12505, 3803, 9063, 2250, + 12505, 3803, 9063, 2412, + 12505, 3803, 9063, 2658, + 12505, 3803, 9063, 3774, + 12505, 3803, 9063, 4614, + 12505, 3803, 9063, 6262, + 12505, 3803, 9063, 6406, + 12505, 3803, 9063, 6674, + 12505, 3803, 9063, 6824, + 12505, 3803, 9063, 7022, + 12505, 3803, 9063, 7080, + 12505, 3803, 9063, 7316, + 12505, 3803, 9063, 7568, + 12505, 3803, 9063, 7682, + 12505, 3803, 9063, 7683, 8774, + 12505, 3803, 9063, 9162, + 12505, 3803, 9063, 9270, + 12505, 3803, 9063, 9530, + 12505, 3803, 9063, 9808, + 12505, 3803, 9271, 8774, + 12505, 3803, 9295, 7593, 0, + 12505, 3803, 9295, 7593, 2, + 12505, 3803, 9295, 7593, 4, + 12505, 3803, 9295, 7593, 6, + 12505, 3803, 9295, 7593, 8, + 12505, 3803, 9295, 7593, 10, + 12505, 3803, 9295, 7593, 12, + 12505, 3803, 9295, 7593, 14, + 12505, 3803, 9295, 7593, 16, + 12505, 3803, 9295, 7593, 18, + 12505, 3803, 9295, 7593, 20, + 12505, 3803, 9295, 7593, 22, + 12505, 3803, 9295, 7593, 24, + 12505, 3803, 9295, 7593, 26, + 12505, 3803, 9295, 7593, 28, + 12505, 3803, 9295, 7593, 30, + 12505, 3803, 9295, 7593, 32, + 12505, 3803, 9295, 7593, 34, + 12505, 3803, 9295, 7593, 36, + 12505, 3803, 9295, 7593, 38, + 12505, 3803, 9295, 7593, 40, + 12505, 3803, 9295, 7593, 42, + 12505, 3803, 9295, 7593, 44, + 12505, 3803, 9295, 7593, 46, + 12505, 3803, 9295, 7593, 48, + 12505, 3803, 9295, 7593, 50, + 12505, 3803, 9295, 9063, 0, + 12505, 3803, 9295, 9063, 2, + 12505, 3803, 9295, 9063, 4, + 12505, 3803, 9295, 9063, 6, + 12505, 3803, 9295, 9063, 8, + 12505, 3803, 9295, 9063, 10, + 12505, 3803, 9295, 9063, 12, + 12505, 3803, 9295, 9063, 14, + 12505, 3803, 9295, 9063, 16, + 12505, 3803, 9295, 9063, 18, + 12505, 3803, 9295, 9063, 20, + 12505, 3803, 9295, 9063, 22, + 12505, 3803, 9295, 9063, 24, + 12505, 3803, 9295, 9063, 26, + 12505, 3803, 9295, 9063, 28, + 12505, 3803, 9295, 9063, 30, + 12505, 3803, 9295, 9063, 32, + 12505, 3803, 9295, 9063, 34, + 12505, 3803, 9295, 9063, 36, + 12505, 3803, 9295, 9063, 38, + 12505, 3803, 9295, 9063, 40, + 12505, 3803, 9295, 9063, 42, + 12505, 3803, 9295, 9063, 44, + 12505, 3803, 9295, 9063, 46, + 12505, 3803, 9295, 9063, 48, + 12505, 3803, 9295, 9063, 50, + 12505, 3803, 9573, 12432, + 12505, 4849, 6409, 9050, + 12505, 4849, 7821, 8745, 9050, + 12505, 4849, 7821, 10637, 7533, 9050, + 12505, 4849, 8153, 6409, 9050, + 12505, 4849, 10997, 12114, + 12505, 7443, 6409, 9050, + 12505, 7443, 7821, 8745, 9050, + 12505, 7443, 7821, 10637, 7533, 9050, + 12505, 7443, 8153, 6409, 9050, + 12505, 7443, 10997, 12114, + 12505, 8325, 477, 8774, + 12505, 8325, 2217, 8774, + 12505, 8325, 2413, 8774, + 12505, 8325, 7023, 8774, + 12505, 8325, 7202, + 12505, 8325, 7593, 0, + 12505, 8325, 7593, 2, + 12505, 8325, 7593, 4, + 12505, 8325, 7593, 6, + 12505, 8325, 7593, 8, + 12505, 8325, 7593, 10, + 12505, 8325, 7593, 12, + 12505, 8325, 7593, 16, + 12505, 8325, 7593, 18, + 12505, 8325, 7593, 20, + 12505, 8325, 7593, 22, + 12505, 8325, 7593, 24, + 12505, 8325, 7593, 26, + 12505, 8325, 7593, 28, + 12505, 8325, 7593, 30, + 12505, 8325, 7593, 32, + 12505, 8325, 7593, 34, + 12505, 8325, 7593, 36, + 12505, 8325, 7593, 38, + 12505, 8325, 7593, 40, + 12505, 8325, 7593, 42, + 12505, 8325, 7593, 44, + 12505, 8325, 7593, 46, + 12505, 8325, 7593, 48, + 12505, 8325, 7593, 50, + 12505, 8325, 7593, 384, + 12505, 8325, 7593, 416, + 12505, 8325, 7593, 476, + 12505, 8325, 7593, 644, + 12505, 8325, 7593, 888, + 12505, 8325, 7593, 1128, + 12505, 8325, 7593, 2216, + 12505, 8325, 7593, 2250, + 12505, 8325, 7593, 2412, + 12505, 8325, 7593, 2658, + 12505, 8325, 7593, 3774, + 12505, 8325, 7593, 4614, + 12505, 8325, 7593, 6262, + 12505, 8325, 7593, 6406, + 12505, 8325, 7593, 6674, + 12505, 8325, 7593, 6789, 7568, + 12505, 8325, 7593, 6824, + 12505, 8325, 7593, 7022, + 12505, 8325, 7593, 7080, + 12505, 8325, 7593, 7316, + 12505, 8325, 7593, 7568, + 12505, 8325, 7593, 7682, + 12505, 8325, 7593, 9185, 16, + 12505, 8325, 7593, 9185, 18, + 12505, 8325, 7593, 9270, + 12505, 8325, 7593, 9530, + 12505, 8325, 7593, 9808, + 12505, 8325, 7683, 8774, + 12505, 8325, 9063, 0, + 12505, 8325, 9063, 2, + 12505, 8325, 9063, 4, + 12505, 8325, 9063, 6, + 12505, 8325, 9063, 8, + 12505, 8325, 9063, 10, + 12505, 8325, 9063, 12, + 12505, 8325, 9063, 14, + 12505, 8325, 9063, 16, + 12505, 8325, 9063, 18, + 12505, 8325, 9063, 20, + 12505, 8325, 9063, 22, + 12505, 8325, 9063, 24, + 12505, 8325, 9063, 26, + 12505, 8325, 9063, 28, + 12505, 8325, 9063, 30, + 12505, 8325, 9063, 32, + 12505, 8325, 9063, 34, + 12505, 8325, 9063, 36, + 12505, 8325, 9063, 38, + 12505, 8325, 9063, 40, + 12505, 8325, 9063, 42, + 12505, 8325, 9063, 44, + 12505, 8325, 9063, 46, + 12505, 8325, 9063, 48, + 12505, 8325, 9063, 50, + 12505, 8325, 9063, 384, + 12505, 8325, 9063, 416, + 12505, 8325, 9063, 476, + 12505, 8325, 9063, 644, + 12505, 8325, 9063, 888, + 12505, 8325, 9063, 1128, + 12505, 8325, 9063, 2216, + 12505, 8325, 9063, 2250, + 12505, 8325, 9063, 2412, + 12505, 8325, 9063, 2658, + 12505, 8325, 9063, 3774, + 12505, 8325, 9063, 4614, + 12505, 8325, 9063, 6262, + 12505, 8325, 9063, 6406, + 12505, 8325, 9063, 6674, + 12505, 8325, 9063, 6824, + 12505, 8325, 9063, 7022, + 12505, 8325, 9063, 7080, + 12505, 8325, 9063, 7316, + 12505, 8325, 9063, 7568, + 12505, 8325, 9063, 7682, + 12505, 8325, 9063, 7683, 8774, + 12505, 8325, 9063, 9270, + 12505, 8325, 9063, 9530, + 12505, 8325, 9063, 9808, + 12505, 8325, 9271, 8774, + 12505, 8325, 9573, 12432, + 12505, 8679, 7593, 0, + 12505, 8679, 7593, 2, + 12505, 8679, 7593, 4, + 12505, 8679, 7593, 6, + 12505, 8679, 7593, 10, + 12505, 8679, 7593, 14, + 12505, 8679, 7593, 16, + 12505, 8679, 7593, 18, + 12505, 8679, 7593, 20, + 12505, 8679, 7593, 22, + 12505, 8679, 7593, 24, + 12505, 8679, 7593, 26, + 12505, 8679, 7593, 30, + 12505, 8679, 7593, 32, + 12505, 8679, 7593, 34, + 12505, 8679, 7593, 36, + 12505, 8679, 7593, 38, + 12505, 8679, 7593, 40, + 12505, 8679, 7593, 42, + 12505, 8679, 7593, 44, + 12505, 8679, 7593, 46, + 12505, 8679, 7593, 48, + 12505, 8679, 7593, 50, + 12505, 8679, 9063, 0, + 12505, 8679, 9063, 4, + 12505, 8679, 9063, 6, + 12505, 8679, 9063, 12, + 12505, 8679, 9063, 18, + 12505, 8679, 9063, 20, + 12505, 8679, 9063, 26, + 12505, 8679, 9063, 28, + 12505, 8679, 9063, 30, + 12505, 8679, 9063, 32, + 12505, 8679, 9063, 36, + 12505, 8679, 9063, 38, + 12505, 8679, 9063, 40, + 12505, 8679, 9063, 42, + 12505, 8679, 9063, 44, + 12505, 8679, 9063, 46, + 12505, 8679, 9063, 48, + 12505, 8679, 9063, 50, + 12505, 9295, 7593, 0, + 12505, 9295, 7593, 2, + 12505, 9295, 7593, 4, + 12505, 9295, 7593, 6, + 12505, 9295, 7593, 8, + 12505, 9295, 7593, 10, + 12505, 9295, 7593, 12, + 12505, 9295, 7593, 14, + 12505, 9295, 7593, 16, + 12505, 9295, 7593, 18, + 12505, 9295, 7593, 20, + 12505, 9295, 7593, 22, + 12505, 9295, 7593, 24, + 12505, 9295, 7593, 26, + 12505, 9295, 7593, 28, + 12505, 9295, 7593, 30, + 12505, 9295, 7593, 32, + 12505, 9295, 7593, 34, + 12505, 9295, 7593, 36, + 12505, 9295, 7593, 38, + 12505, 9295, 7593, 40, + 12505, 9295, 7593, 42, + 12505, 9295, 7593, 44, + 12505, 9295, 7593, 46, + 12505, 9295, 7593, 48, + 12505, 9295, 7593, 50, + 12505, 9295, 9063, 0, + 12505, 9295, 9063, 2, + 12505, 9295, 9063, 6, + 12505, 9295, 9063, 8, + 12505, 9295, 9063, 10, + 12505, 9295, 9063, 12, + 12505, 9295, 9063, 18, + 12505, 9295, 9063, 20, + 12505, 9295, 9063, 22, + 12505, 9295, 9063, 24, + 12505, 9295, 9063, 26, + 12505, 9295, 9063, 28, + 12505, 9295, 9063, 30, + 12505, 9295, 9063, 32, + 12505, 9295, 9063, 36, + 12505, 9295, 9063, 38, + 12505, 9295, 9063, 40, + 12505, 9295, 9063, 42, + 12505, 9295, 9063, 44, + 12505, 9295, 9063, 46, + 12505, 9295, 9063, 48, + 12505, 11129, 6689, 2170, + 12505, 11129, 6689, 2540, + 12505, 11129, 6689, 2778, + 12505, 11129, 6689, 4200, + 12505, 11129, 6689, 4214, + 12505, 11129, 6689, 5190, + 12505, 11129, 6689, 6260, + 12505, 11129, 6689, 6722, + 12505, 11129, 6689, 7508, + 12505, 11129, 6689, 7694, + 12505, 11129, 7593, 0, + 12505, 11129, 7593, 2, + 12505, 11129, 7593, 4, + 12505, 11129, 7593, 6, + 12505, 11129, 7593, 8, + 12505, 11129, 7593, 10, + 12505, 11129, 7593, 12, + 12505, 11129, 7593, 14, + 12505, 11129, 7593, 16, + 12505, 11129, 7593, 18, + 12505, 11129, 7593, 20, + 12505, 11129, 7593, 22, + 12505, 11129, 7593, 24, + 12505, 11129, 7593, 26, + 12505, 11129, 7593, 28, + 12505, 11129, 7593, 30, + 12505, 11129, 7593, 32, + 12505, 11129, 7593, 34, + 12505, 11129, 7593, 36, + 12505, 11129, 7593, 38, + 12505, 11129, 7593, 40, + 12505, 11129, 7593, 42, + 12505, 11129, 7593, 44, + 12505, 11129, 7593, 46, + 12505, 11129, 7593, 48, + 12505, 11129, 7593, 50, + 12505, 11129, 9063, 0, + 12505, 11129, 9063, 2, + 12505, 11129, 9063, 4, + 12505, 11129, 9063, 6, + 12505, 11129, 9063, 8, + 12505, 11129, 9063, 10, + 12505, 11129, 9063, 12, + 12505, 11129, 9063, 14, + 12505, 11129, 9063, 16, + 12505, 11129, 9063, 18, + 12505, 11129, 9063, 20, + 12505, 11129, 9063, 22, + 12505, 11129, 9063, 24, + 12505, 11129, 9063, 26, + 12505, 11129, 9063, 28, + 12505, 11129, 9063, 30, + 12505, 11129, 9063, 32, + 12505, 11129, 9063, 34, + 12505, 11129, 9063, 36, + 12505, 11129, 9063, 38, + 12505, 11129, 9063, 40, + 12505, 11129, 9063, 42, + 12505, 11129, 9063, 44, + 12505, 11129, 9063, 46, + 12505, 11129, 9063, 48, + 12505, 11129, 9063, 50, + 12505, 11767, 3803, 477, 8774, + 12505, 11767, 3803, 2217, 8774, + 12505, 11767, 3803, 2413, 8774, + 12505, 11767, 3803, 6689, 2170, + 12505, 11767, 3803, 6689, 2540, + 12505, 11767, 3803, 6689, 2778, + 12505, 11767, 3803, 6689, 4200, + 12505, 11767, 3803, 6689, 4214, + 12505, 11767, 3803, 6689, 5190, + 12505, 11767, 3803, 6689, 6260, + 12505, 11767, 3803, 6689, 6722, + 12505, 11767, 3803, 6689, 7508, + 12505, 11767, 3803, 6689, 7694, + 12505, 11767, 3803, 7023, 8774, + 12505, 11767, 3803, 7202, + 12505, 11767, 3803, 7593, 0, + 12505, 11767, 3803, 7593, 2, + 12505, 11767, 3803, 7593, 4, + 12505, 11767, 3803, 7593, 6, + 12505, 11767, 3803, 7593, 8, + 12505, 11767, 3803, 7593, 10, + 12505, 11767, 3803, 7593, 12, + 12505, 11767, 3803, 7593, 14, + 12505, 11767, 3803, 7593, 16, + 12505, 11767, 3803, 7593, 18, + 12505, 11767, 3803, 7593, 20, + 12505, 11767, 3803, 7593, 22, + 12505, 11767, 3803, 7593, 24, + 12505, 11767, 3803, 7593, 26, + 12505, 11767, 3803, 7593, 28, + 12505, 11767, 3803, 7593, 30, + 12505, 11767, 3803, 7593, 32, + 12505, 11767, 3803, 7593, 34, + 12505, 11767, 3803, 7593, 36, + 12505, 11767, 3803, 7593, 38, + 12505, 11767, 3803, 7593, 40, + 12505, 11767, 3803, 7593, 42, + 12505, 11767, 3803, 7593, 44, + 12505, 11767, 3803, 7593, 46, + 12505, 11767, 3803, 7593, 48, + 12505, 11767, 3803, 7593, 50, + 12505, 11767, 3803, 7593, 384, + 12505, 11767, 3803, 7593, 416, + 12505, 11767, 3803, 7593, 476, + 12505, 11767, 3803, 7593, 644, + 12505, 11767, 3803, 7593, 888, + 12505, 11767, 3803, 7593, 1128, + 12505, 11767, 3803, 7593, 2216, + 12505, 11767, 3803, 7593, 2250, + 12505, 11767, 3803, 7593, 2412, + 12505, 11767, 3803, 7593, 2658, + 12505, 11767, 3803, 7593, 3774, + 12505, 11767, 3803, 7593, 4614, + 12505, 11767, 3803, 7593, 6262, + 12505, 11767, 3803, 7593, 6406, + 12505, 11767, 3803, 7593, 6674, + 12505, 11767, 3803, 7593, 6789, 7568, + 12505, 11767, 3803, 7593, 6824, + 12505, 11767, 3803, 7593, 7022, + 12505, 11767, 3803, 7593, 7080, + 12505, 11767, 3803, 7593, 7316, + 12505, 11767, 3803, 7593, 7568, + 12505, 11767, 3803, 7593, 7682, + 12505, 11767, 3803, 7593, 9270, + 12505, 11767, 3803, 7593, 9530, + 12505, 11767, 3803, 7593, 9808, + 12505, 11767, 3803, 7683, 8774, + 12505, 11767, 3803, 8325, 477, 8774, + 12505, 11767, 3803, 8325, 2217, 8774, + 12505, 11767, 3803, 8325, 2413, 8774, + 12505, 11767, 3803, 8325, 7023, 8774, + 12505, 11767, 3803, 8325, 7202, + 12505, 11767, 3803, 8325, 7593, 0, + 12505, 11767, 3803, 8325, 7593, 2, + 12505, 11767, 3803, 8325, 7593, 4, + 12505, 11767, 3803, 8325, 7593, 6, + 12505, 11767, 3803, 8325, 7593, 8, + 12505, 11767, 3803, 8325, 7593, 10, + 12505, 11767, 3803, 8325, 7593, 12, + 12505, 11767, 3803, 8325, 7593, 14, + 12505, 11767, 3803, 8325, 7593, 16, + 12505, 11767, 3803, 8325, 7593, 18, + 12505, 11767, 3803, 8325, 7593, 20, + 12505, 11767, 3803, 8325, 7593, 22, + 12505, 11767, 3803, 8325, 7593, 24, + 12505, 11767, 3803, 8325, 7593, 26, + 12505, 11767, 3803, 8325, 7593, 28, + 12505, 11767, 3803, 8325, 7593, 30, + 12505, 11767, 3803, 8325, 7593, 32, + 12505, 11767, 3803, 8325, 7593, 34, + 12505, 11767, 3803, 8325, 7593, 36, + 12505, 11767, 3803, 8325, 7593, 38, + 12505, 11767, 3803, 8325, 7593, 40, + 12505, 11767, 3803, 8325, 7593, 42, + 12505, 11767, 3803, 8325, 7593, 44, + 12505, 11767, 3803, 8325, 7593, 46, + 12505, 11767, 3803, 8325, 7593, 48, + 12505, 11767, 3803, 8325, 7593, 50, + 12505, 11767, 3803, 8325, 7593, 384, + 12505, 11767, 3803, 8325, 7593, 416, + 12505, 11767, 3803, 8325, 7593, 476, + 12505, 11767, 3803, 8325, 7593, 644, + 12505, 11767, 3803, 8325, 7593, 888, + 12505, 11767, 3803, 8325, 7593, 1128, + 12505, 11767, 3803, 8325, 7593, 2216, + 12505, 11767, 3803, 8325, 7593, 2250, + 12505, 11767, 3803, 8325, 7593, 2412, + 12505, 11767, 3803, 8325, 7593, 2658, + 12505, 11767, 3803, 8325, 7593, 3774, + 12505, 11767, 3803, 8325, 7593, 4614, + 12505, 11767, 3803, 8325, 7593, 6262, + 12505, 11767, 3803, 8325, 7593, 6406, + 12505, 11767, 3803, 8325, 7593, 6674, + 12505, 11767, 3803, 8325, 7593, 6789, 7568, + 12505, 11767, 3803, 8325, 7593, 6824, + 12505, 11767, 3803, 8325, 7593, 7022, + 12505, 11767, 3803, 8325, 7593, 7080, + 12505, 11767, 3803, 8325, 7593, 7316, + 12505, 11767, 3803, 8325, 7593, 7568, + 12505, 11767, 3803, 8325, 7593, 7682, + 12505, 11767, 3803, 8325, 7593, 9270, + 12505, 11767, 3803, 8325, 7593, 9530, + 12505, 11767, 3803, 8325, 7593, 9808, + 12505, 11767, 3803, 8325, 7683, 8774, + 12505, 11767, 3803, 8325, 9063, 0, + 12505, 11767, 3803, 8325, 9063, 2, + 12505, 11767, 3803, 8325, 9063, 4, + 12505, 11767, 3803, 8325, 9063, 6, + 12505, 11767, 3803, 8325, 9063, 8, + 12505, 11767, 3803, 8325, 9063, 10, + 12505, 11767, 3803, 8325, 9063, 12, + 12505, 11767, 3803, 8325, 9063, 14, + 12505, 11767, 3803, 8325, 9063, 16, + 12505, 11767, 3803, 8325, 9063, 18, + 12505, 11767, 3803, 8325, 9063, 20, + 12505, 11767, 3803, 8325, 9063, 22, + 12505, 11767, 3803, 8325, 9063, 24, + 12505, 11767, 3803, 8325, 9063, 26, + 12505, 11767, 3803, 8325, 9063, 28, + 12505, 11767, 3803, 8325, 9063, 30, + 12505, 11767, 3803, 8325, 9063, 32, + 12505, 11767, 3803, 8325, 9063, 34, + 12505, 11767, 3803, 8325, 9063, 36, + 12505, 11767, 3803, 8325, 9063, 38, + 12505, 11767, 3803, 8325, 9063, 40, + 12505, 11767, 3803, 8325, 9063, 42, + 12505, 11767, 3803, 8325, 9063, 44, + 12505, 11767, 3803, 8325, 9063, 46, + 12505, 11767, 3803, 8325, 9063, 48, + 12505, 11767, 3803, 8325, 9063, 50, + 12505, 11767, 3803, 8325, 9063, 384, + 12505, 11767, 3803, 8325, 9063, 416, + 12505, 11767, 3803, 8325, 9063, 476, + 12505, 11767, 3803, 8325, 9063, 644, + 12505, 11767, 3803, 8325, 9063, 888, + 12505, 11767, 3803, 8325, 9063, 1128, + 12505, 11767, 3803, 8325, 9063, 2216, + 12505, 11767, 3803, 8325, 9063, 2250, + 12505, 11767, 3803, 8325, 9063, 2412, + 12505, 11767, 3803, 8325, 9063, 2658, + 12505, 11767, 3803, 8325, 9063, 3774, + 12505, 11767, 3803, 8325, 9063, 4614, + 12505, 11767, 3803, 8325, 9063, 6262, + 12505, 11767, 3803, 8325, 9063, 6406, + 12505, 11767, 3803, 8325, 9063, 6674, + 12505, 11767, 3803, 8325, 9063, 6824, + 12505, 11767, 3803, 8325, 9063, 7022, + 12505, 11767, 3803, 8325, 9063, 7080, + 12505, 11767, 3803, 8325, 9063, 7316, + 12505, 11767, 3803, 8325, 9063, 7568, + 12505, 11767, 3803, 8325, 9063, 7682, + 12505, 11767, 3803, 8325, 9063, 7683, 8774, + 12505, 11767, 3803, 8325, 9063, 9270, + 12505, 11767, 3803, 8325, 9063, 9530, + 12505, 11767, 3803, 8325, 9063, 9808, + 12505, 11767, 3803, 8325, 9271, 8774, + 12505, 11767, 3803, 8325, 9573, 12432, + 12505, 11767, 3803, 9063, 0, + 12505, 11767, 3803, 9063, 2, + 12505, 11767, 3803, 9063, 4, + 12505, 11767, 3803, 9063, 6, + 12505, 11767, 3803, 9063, 8, + 12505, 11767, 3803, 9063, 10, + 12505, 11767, 3803, 9063, 12, + 12505, 11767, 3803, 9063, 14, + 12505, 11767, 3803, 9063, 16, + 12505, 11767, 3803, 9063, 18, + 12505, 11767, 3803, 9063, 20, + 12505, 11767, 3803, 9063, 22, + 12505, 11767, 3803, 9063, 24, + 12505, 11767, 3803, 9063, 26, + 12505, 11767, 3803, 9063, 28, + 12505, 11767, 3803, 9063, 30, + 12505, 11767, 3803, 9063, 32, + 12505, 11767, 3803, 9063, 34, + 12505, 11767, 3803, 9063, 36, + 12505, 11767, 3803, 9063, 38, + 12505, 11767, 3803, 9063, 40, + 12505, 11767, 3803, 9063, 42, + 12505, 11767, 3803, 9063, 44, + 12505, 11767, 3803, 9063, 46, + 12505, 11767, 3803, 9063, 48, + 12505, 11767, 3803, 9063, 50, + 12505, 11767, 3803, 9063, 384, + 12505, 11767, 3803, 9063, 416, + 12505, 11767, 3803, 9063, 476, + 12505, 11767, 3803, 9063, 644, + 12505, 11767, 3803, 9063, 888, + 12505, 11767, 3803, 9063, 1128, + 12505, 11767, 3803, 9063, 2216, + 12505, 11767, 3803, 9063, 2250, + 12505, 11767, 3803, 9063, 2412, + 12505, 11767, 3803, 9063, 2658, + 12505, 11767, 3803, 9063, 3774, + 12505, 11767, 3803, 9063, 4614, + 12505, 11767, 3803, 9063, 6262, + 12505, 11767, 3803, 9063, 6406, + 12505, 11767, 3803, 9063, 6674, + 12505, 11767, 3803, 9063, 6824, + 12505, 11767, 3803, 9063, 7022, + 12505, 11767, 3803, 9063, 7080, + 12505, 11767, 3803, 9063, 7316, + 12505, 11767, 3803, 9063, 7568, + 12505, 11767, 3803, 9063, 7682, + 12505, 11767, 3803, 9063, 7683, 8774, + 12505, 11767, 3803, 9063, 9270, + 12505, 11767, 3803, 9063, 9530, + 12505, 11767, 3803, 9063, 9808, + 12505, 11767, 3803, 9271, 8774, + 12505, 11767, 3803, 9573, 12432, + 12505, 11767, 6689, 2170, + 12505, 11767, 6689, 2540, + 12505, 11767, 6689, 2778, + 12505, 11767, 6689, 4200, + 12505, 11767, 6689, 4214, + 12505, 11767, 6689, 5190, + 12505, 11767, 6689, 6260, + 12505, 11767, 6689, 6722, + 12505, 11767, 6689, 7508, + 12505, 11767, 6689, 7694, + 12505, 11767, 7593, 0, + 12505, 11767, 7593, 2, + 12505, 11767, 7593, 4, + 12505, 11767, 7593, 6, + 12505, 11767, 7593, 8, + 12505, 11767, 7593, 10, + 12505, 11767, 7593, 12, + 12505, 11767, 7593, 14, + 12505, 11767, 7593, 16, + 12505, 11767, 7593, 18, + 12505, 11767, 7593, 20, + 12505, 11767, 7593, 22, + 12505, 11767, 7593, 24, + 12505, 11767, 7593, 26, + 12505, 11767, 7593, 28, + 12505, 11767, 7593, 30, + 12505, 11767, 7593, 32, + 12505, 11767, 7593, 34, + 12505, 11767, 7593, 36, + 12505, 11767, 7593, 38, + 12505, 11767, 7593, 40, + 12505, 11767, 7593, 42, + 12505, 11767, 7593, 44, + 12505, 11767, 7593, 46, + 12505, 11767, 7593, 48, + 12505, 11767, 7593, 50, + 12505, 11767, 8325, 7593, 0, + 12505, 11767, 8325, 7593, 2, + 12505, 11767, 8325, 7593, 4, + 12505, 11767, 8325, 7593, 6, + 12505, 11767, 8325, 7593, 8, + 12505, 11767, 8325, 7593, 10, + 12505, 11767, 8325, 7593, 12, + 12505, 11767, 8325, 7593, 14, + 12505, 11767, 8325, 7593, 16, + 12505, 11767, 8325, 7593, 18, + 12505, 11767, 8325, 7593, 20, + 12505, 11767, 8325, 7593, 22, + 12505, 11767, 8325, 7593, 24, + 12505, 11767, 8325, 7593, 26, + 12505, 11767, 8325, 7593, 28, + 12505, 11767, 8325, 7593, 30, + 12505, 11767, 8325, 7593, 32, + 12505, 11767, 8325, 7593, 34, + 12505, 11767, 8325, 7593, 36, + 12505, 11767, 8325, 7593, 38, + 12505, 11767, 8325, 7593, 40, + 12505, 11767, 8325, 7593, 42, + 12505, 11767, 8325, 7593, 44, + 12505, 11767, 8325, 7593, 46, + 12505, 11767, 8325, 7593, 48, + 12505, 11767, 8325, 7593, 50, + 12505, 11767, 8325, 9063, 0, + 12505, 11767, 8325, 9063, 2, + 12505, 11767, 8325, 9063, 4, + 12505, 11767, 8325, 9063, 6, + 12505, 11767, 8325, 9063, 8, + 12505, 11767, 8325, 9063, 10, + 12505, 11767, 8325, 9063, 12, + 12505, 11767, 8325, 9063, 14, + 12505, 11767, 8325, 9063, 16, + 12505, 11767, 8325, 9063, 18, + 12505, 11767, 8325, 9063, 20, + 12505, 11767, 8325, 9063, 22, + 12505, 11767, 8325, 9063, 24, + 12505, 11767, 8325, 9063, 26, + 12505, 11767, 8325, 9063, 28, + 12505, 11767, 8325, 9063, 30, + 12505, 11767, 8325, 9063, 32, + 12505, 11767, 8325, 9063, 34, + 12505, 11767, 8325, 9063, 36, + 12505, 11767, 8325, 9063, 38, + 12505, 11767, 8325, 9063, 40, + 12505, 11767, 8325, 9063, 42, + 12505, 11767, 8325, 9063, 44, + 12505, 11767, 8325, 9063, 46, + 12505, 11767, 8325, 9063, 48, + 12505, 11767, 8325, 9063, 50, + 12505, 11767, 9063, 0, + 12505, 11767, 9063, 2, + 12505, 11767, 9063, 4, + 12505, 11767, 9063, 6, + 12505, 11767, 9063, 8, + 12505, 11767, 9063, 10, + 12505, 11767, 9063, 12, + 12505, 11767, 9063, 14, + 12505, 11767, 9063, 16, + 12505, 11767, 9063, 18, + 12505, 11767, 9063, 20, + 12505, 11767, 9063, 22, + 12505, 11767, 9063, 24, + 12505, 11767, 9063, 26, + 12505, 11767, 9063, 28, + 12505, 11767, 9063, 30, + 12505, 11767, 9063, 32, + 12505, 11767, 9063, 34, + 12505, 11767, 9063, 36, + 12505, 11767, 9063, 38, + 12505, 11767, 9063, 40, + 12505, 11767, 9063, 42, + 12505, 11767, 9063, 44, + 12505, 11767, 9063, 46, + 12505, 11767, 9063, 48, + 12505, 11767, 9063, 50, + 12505, 12929, 6689, 2170, + 12505, 12929, 6689, 2540, + 12505, 12929, 6689, 2778, + 12505, 12929, 6689, 4200, + 12505, 12929, 6689, 4214, + 12505, 12929, 6689, 5190, + 12505, 12929, 6689, 6260, + 12505, 12929, 6689, 6722, + 12505, 12929, 6689, 7508, + 12505, 12929, 6689, 7694, + 12505, 12929, 7593, 0, + 12505, 12929, 7593, 2, + 12505, 12929, 7593, 4, + 12505, 12929, 7593, 6, + 12505, 12929, 7593, 8, + 12505, 12929, 7593, 10, + 12505, 12929, 7593, 12, + 12505, 12929, 7593, 14, + 12505, 12929, 7593, 16, + 12505, 12929, 7593, 18, + 12505, 12929, 7593, 20, + 12505, 12929, 7593, 22, + 12505, 12929, 7593, 24, + 12505, 12929, 7593, 26, + 12505, 12929, 7593, 28, + 12505, 12929, 7593, 30, + 12505, 12929, 7593, 32, + 12505, 12929, 7593, 34, + 12505, 12929, 7593, 36, + 12505, 12929, 7593, 38, + 12505, 12929, 7593, 40, + 12505, 12929, 7593, 42, + 12505, 12929, 7593, 44, + 12505, 12929, 7593, 46, + 12505, 12929, 7593, 48, + 12505, 12929, 7593, 50, + 12505, 12929, 9063, 0, + 12505, 12929, 9063, 2, + 12505, 12929, 9063, 6, + 12505, 12929, 9063, 8, + 12505, 12929, 9063, 10, + 12505, 12929, 9063, 12, + 12505, 12929, 9063, 16, + 12505, 12929, 9063, 18, + 12505, 12929, 9063, 20, + 12505, 12929, 9063, 22, + 12505, 12929, 9063, 24, + 12505, 12929, 9063, 28, + 12505, 12929, 9063, 36, + 12505, 12929, 9063, 38, + 12505, 12929, 9063, 40, + 12505, 12929, 9063, 42, + 12505, 12929, 9063, 44, + 12505, 12929, 9063, 46, + 12505, 12929, 9063, 48, + 12517, 8306, + 12525, 5882, + 12527, 4213, 1177, 10677, 175, 3992, + 12527, 4213, 1177, 10677, 177, 3992, + 12527, 4213, 1177, 10677, 1809, 4876, + 12527, 4213, 1177, 10677, 2779, 1045, 8392, + 12527, 4213, 1177, 10677, 4849, 6409, 9050, + 12527, 4213, 1177, 10677, 4849, 6505, 11677, 9050, + 12527, 4213, 1177, 10677, 4849, 6627, 9050, + 12527, 4213, 1177, 10677, 4849, 7821, 8077, 9050, + 12527, 4213, 1177, 10677, 4849, 7821, 11677, 9050, + 12527, 4213, 1177, 10677, 4849, 8077, 9050, + 12527, 4213, 1177, 10677, 4849, 8153, 6409, 9050, + 12527, 4213, 1177, 10677, 4849, 8745, 9050, + 12527, 4213, 1177, 10677, 4849, 10637, 7533, 9050, + 12527, 4213, 1177, 10677, 4849, 12114, + 12527, 4213, 1177, 10677, 6107, 1809, 4876, + 12527, 4213, 1177, 10677, 6610, + 12527, 4213, 1177, 10677, 6616, + 12527, 4213, 1177, 10677, 7443, 6409, 9050, + 12527, 4213, 1177, 10677, 7443, 6505, 11677, 9050, + 12527, 4213, 1177, 10677, 7443, 6627, 9050, + 12527, 4213, 1177, 10677, 7443, 7821, 8077, 9050, + 12527, 4213, 1177, 10677, 7443, 7821, 11677, 9054, + 12527, 4213, 1177, 10677, 7443, 8077, 9050, + 12527, 4213, 1177, 10677, 7443, 8153, 6409, 9050, + 12527, 4213, 1177, 10677, 7443, 8745, 9050, + 12527, 4213, 1177, 10677, 7443, 10637, 7533, 9050, + 12527, 4213, 1177, 10677, 7443, 12114, + 12527, 4213, 1177, 10677, 10469, 4926, + 12527, 4213, 1177, 10677, 11224, + 12527, 4213, 1177, 10677, 11649, 10154, + 12527, 4213, 1177, 10677, 12017, 4926, + 12527, 4213, 1177, 10677, 12043, 4223, 5836, + 12527, 4213, 1177, 10677, 12043, 6616, + 12529, 568, + 12537, 7821, 11765, 6434, + 12540, + 12874, + 12881, 7608, + 12882, + 12895, 11765, 6434, + 12901, 2725, 11791, 6434, + 12901, 5385, 8057, 6434, + 12901, 8065, 8057, 6434, + 12901, 8241, 8057, 6434, + 12901, 9115, 10260, + 12901, 12056, + 12903, 835, 2091, 9855, 6741, 568, + 12903, 6741, 445, 6741, 568, + 12903, 6741, 568, + 12903, 6741, 569, 445, 2681, 6989, 428, + 12925, 11385, 8774, + 12929, 7201, 11262, + 12929, 7593, 476, + 12929, 7593, 6824, + 12929, 8325, 7593, 6, + 12929, 8325, 7593, 8, + 12929, 8325, 7593, 16, + 12929, 8325, 7593, 18, + 12929, 8325, 9063, 6, + 12929, 9063, 4, + 12929, 9063, 14, + 12929, 9063, 26, + 12929, 9063, 30, + 12929, 9063, 32, + 12929, 9063, 34, + 12929, 9063, 50, + 12929, 9063, 476, + 12929, 9063, 6824, + 12931, 10643, 6121, 4849, 4389, 6504, + 12931, 10643, 6121, 7443, 4389, 6504, + 12939, 5758, + 12941, 6741, 568, + 12941, 11621, 568, + 12967, 6409, 9050, + 12967, 8083, 6409, 9050, + 12967, 8153, 6409, 11195, 4926, + 12969, 4926, + 12969, 10390, + 12969, 10966, + 12975, 5758, + 12983, 11765, 6434, + 12987, 6689, 2170, + 12987, 6689, 2540, + 12987, 6689, 2778, + 12987, 6689, 4200, + 12987, 6689, 4214, + 12987, 6689, 5190, + 12987, 6689, 6722, + 12987, 6689, 7508, + 12987, 6689, 7694, + 12987, 7089, 7593, 8405, 0, + 12987, 7089, 7593, 8405, 2, + 12987, 7089, 7593, 8405, 4, + 12987, 7089, 7593, 8405, 6, + 12987, 7089, 7593, 8405, 8, + 12987, 7089, 7593, 8405, 10, + 12987, 7089, 7593, 8405, 12, + 12987, 7089, 7593, 8405, 14, + 12987, 7089, 7593, 8405, 16, + 12987, 7089, 7593, 8405, 18, + 12987, 7089, 7593, 8405, 20, + 12987, 7089, 7593, 8405, 22, + 12987, 7089, 7593, 8405, 24, + 12987, 7089, 7593, 8405, 26, + 12987, 7089, 7593, 8405, 28, + 12987, 7089, 7593, 8405, 30, + 12987, 7089, 7593, 8405, 32, + 12987, 7089, 7593, 8405, 34, + 12987, 7089, 7593, 8405, 36, + 12987, 7089, 7593, 8405, 38, + 12987, 7089, 7593, 8405, 40, + 12987, 7089, 7593, 8405, 42, + 12987, 7089, 7593, 8405, 44, + 12987, 7089, 7593, 8405, 46, + 12987, 7089, 7593, 8405, 48, + 12987, 7089, 7593, 8405, 50, + 12987, 8287, 5770, + 12987, 8287, 5771, 0, + 12987, 8287, 6594, + 12987, 8287, 6595, 0, + 12987, 8287, 6595, 40, + 12987, 8287, 6912, + 12987, 8287, 6913, 0, + 12987, 8287, 6982, + 12987, 8287, 6983, 0, + 12987, 8287, 7166, + 12987, 8287, 7167, 0, + 12987, 8287, 7244, + 12987, 8287, 7245, 0, + 12987, 8287, 7372, + 12987, 8287, 7373, 0, + 12987, 8287, 7440, + 12987, 8287, 7441, 0, + 12987, 8287, 8362, + 12987, 8287, 8363, 0, + 12987, 8287, 8828, + 12987, 8287, 8829, 0, + 12987, 8287, 9086, + 12987, 8287, 9087, 0, + 12987, 8287, 9400, + 12987, 8287, 9401, 0, + 12987, 8287, 9588, + 12987, 8287, 9589, 0, + 12987, 8287, 9780, + 12987, 8287, 9781, 0, + 12987, 8371, 10759, 29, 250, + 12987, 8371, 10759, 7310, + 12987, 8525, 2670, + 12987, 8525, 8162, + 12987, 8525, 8874, + 12987, 8525, 8876, + 12987, 8525, 9286, + 12987, 8525, 9700, + 12987, 8525, 10150, + 12987, 8525, 10200, + 12987, 8525, 10360, + 12987, 8525, 10622, + 12987, 8525, 11232, + 12987, 11043, 2170, + 12987, 11043, 2540, + 12987, 11043, 2586, + 12987, 11043, 2670, + 12987, 11043, 2778, + 12987, 11043, 3842, + 12987, 11043, 4194, + 12987, 11043, 4200, + 12987, 11043, 4214, + 12987, 11043, 4396, + 12987, 11043, 5012, + 12987, 11043, 5046, + 12987, 11043, 5190, + 12987, 11043, 5540, + 12987, 11043, 5650, + 12987, 11043, 6122, + 12987, 11043, 6716, + 12987, 11043, 6722, + 12987, 11043, 7072, + 12987, 11043, 7146, + 12987, 11043, 7428, + 12987, 11043, 7508, + 12987, 11043, 7640, + 12987, 11043, 7646, + 12987, 11043, 7694, + 12987, 11043, 7812, + 12987, 11043, 9714, + 12987, 11043, 9724, + 12987, 11043, 9862, + 12987, 11043, 10180, + 12987, 11043, 10484, + 12987, 11043, 10992, + 12987, 11043, 11208, + 12987, 11043, 11266, + 12987, 11043, 11612, + 12987, 11043, 13050, + 12990, + 12991, 6121, 36, + 13011, 4926, + 13011, 10390, + 13011, 10966, + 13022, + 13045, 6741, 568, + 13047, 9898, + 13061, 46, + 13061, 5758, + 13061, 5759, 275, 4849, 4389, 8056, + 13061, 5759, 275, 7443, 4389, 8056, + 13061, 5759, 275, 8153, 8056, + 13061, 5759, 275, 10642, + 13061, 5759, 6121, 1045, 6376, + 13061, 5759, 6121, 10666, + 13067, 6409, 9050, + 13067, 8083, 6409, 9050, + 13067, 8153, 6409, 11195, 4926, + 13070, + 13191, 7271, 4153, 6434, + 13191, 7607, 4153, 6434, + 13191, 11765, 6434, + 13231, 11765, 6434, + 13233, 9898, + 13235, 11765, 6434, + 13237, 11765, 6434, + 13365, 8153, 8306, + 13365, 8921, 7605, 4926, + 13365, 11185, 7605, 4926, + 13365, 12341, 7605, 4926, + 13381, 8774, + 13393, 7337, 8774, + 13403, 8279, 8774, + 13403, 8381, 8774, + 13417, 8774, + 13419, 8774, +}; +static const struct { uint16_t code; uint32_t name:24; } +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7) +__attribute__((__packed__)) +#endif +unicode_name_to_code[18242] = { + { 0x2114, 0 }, + { 0x29CC, 4 }, + { 0x2327, 7 }, + { 0x22FF, 12 }, + { 0x2987, 16 }, + { 0x2989, 21 }, + { 0x2981, 26 }, + { 0x2982, 29 }, + { 0x2A65, 33 }, + { 0x2988, 37 }, + { 0x298A, 42 }, + { 0x2A64, 47 }, + { 0x2A20, 51 }, + { 0x2A21, 55 }, + { 0x2A1F, 59 }, + { 0x2A3E, 63 }, + { 0x23E6, 67 }, + { 0x2014, 69 }, + { 0x2001, 71 }, + { 0x2003, 73 }, + { 0x2013, 75 }, + { 0x2000, 77 }, + { 0x2002, 79 }, + { 0x1C78, 81 }, + { 0x1C7D, 85 }, + { 0x1C51, 88 }, + { 0x1C56, 92 }, + { 0x1C52, 96 }, + { 0x1C55, 100 }, + { 0x1C54, 104 }, + { 0x1C59, 108 }, + { 0x1C50, 112 }, + { 0x1C58, 116 }, + { 0x1C57, 120 }, + { 0x1C53, 124 }, + { 0x1C7B, 128 }, + { 0x1C5C, 131 }, + { 0x1C5E, 135 }, + { 0x1C5B, 139 }, + { 0x1C71, 143 }, + { 0x1C6F, 147 }, + { 0x1C66, 151 }, + { 0x1C68, 155 }, + { 0x1C65, 159 }, + { 0x1C5A, 163 }, + { 0x1C6E, 167 }, + { 0x1C64, 171 }, + { 0x1C73, 175 }, + { 0x1C69, 179 }, + { 0x1C75, 183 }, + { 0x1C77, 187 }, + { 0x1C76, 191 }, + { 0x1C6A, 195 }, + { 0x1C6B, 199 }, + { 0x1C6D, 203 }, + { 0x1C61, 207 }, + { 0x1C60, 211 }, + { 0x1C62, 215 }, + { 0x1C63, 219 }, + { 0x1C5D, 223 }, + { 0x1C70, 227 }, + { 0x1C72, 231 }, + { 0x1C67, 235 }, + { 0x1C5F, 239 }, + { 0x1C74, 243 }, + { 0x1C6C, 247 }, + { 0x1C79, 251 }, + { 0x1C7C, 255 }, + { 0x1C7A, 258 }, + { 0x1C7F, 262 }, + { 0x1C7E, 267 }, + { 0x27C7, 271 }, + { 0x2951, 275 }, + { 0x294D, 282 }, + { 0x294C, 289 }, + { 0x294F, 296 }, + { 0x2195, 303 }, + { 0x21A8, 306 }, + { 0x2B0D, 311 }, + { 0x21F3, 315 }, + { 0x21D5, 319 }, + { 0x297E, 323 }, + { 0x22A5, 326 }, + { 0x27DF, 328 }, + { 0x29BD, 333 }, + { 0x22F0, 337 }, + { 0x2303, 341 }, + { 0x2324, 343 }, + { 0x54BC, 349 }, + { 0x54B9, 352 }, + { 0x54A1, 355 }, + { 0x54B3, 358 }, + { 0x54C6, 361 }, + { 0x5491, 364 }, + { 0x5498, 367 }, + { 0x54A9, 370 }, + { 0x54A8, 373 }, + { 0x54B8, 376 }, + { 0x549D, 379 }, + { 0x54B2, 382 }, + { 0x54A5, 385 }, + { 0x54C3, 388 }, + { 0x54BE, 391 }, + { 0x5494, 394 }, + { 0x54A3, 397 }, + { 0x5497, 400 }, + { 0x54B6, 403 }, + { 0x54AD, 406 }, + { 0x54B5, 409 }, + { 0x5492, 412 }, + { 0x54BB, 415 }, + { 0x549A, 418 }, + { 0x549C, 421 }, + { 0x549E, 424 }, + { 0x54AC, 427 }, + { 0x5490, 430 }, + { 0x54B0, 433 }, + { 0x5495, 436 }, + { 0x54A0, 439 }, + { 0x54B1, 442 }, + { 0x54AF, 445 }, + { 0x54AE, 448 }, + { 0x54AB, 451 }, + { 0x54A2, 454 }, + { 0x54C1, 457 }, + { 0x549B, 460 }, + { 0x54BD, 463 }, + { 0x54A4, 466 }, + { 0x5496, 469 }, + { 0x54A6, 472 }, + { 0x5499, 475 }, + { 0x54BF, 478 }, + { 0x549F, 481 }, + { 0x54B7, 484 }, + { 0x54AA, 487 }, + { 0x54C5, 490 }, + { 0x5493, 493 }, + { 0x54A7, 496 }, + { 0x54B4, 499 }, + { 0x54C0, 502 }, + { 0x54C2, 505 }, + { 0x54BA, 508 }, + { 0x54C4, 511 }, + { 0x500A, 514 }, + { 0x5014, 517 }, + { 0x5002, 520 }, + { 0x5011, 523 }, + { 0x500B, 526 }, + { 0x5008, 529 }, + { 0x5009, 532 }, + { 0x5020, 535 }, + { 0x502A, 538 }, + { 0x5018, 541 }, + { 0x5027, 544 }, + { 0x502E, 547 }, + { 0x5034, 550 }, + { 0x52B8, 553 }, + { 0x52C2, 556 }, + { 0x52B0, 559 }, + { 0x52BF, 562 }, + { 0x52C6, 565 }, + { 0x52CC, 568 }, + { 0x5109, 571 }, + { 0x5112, 574 }, + { 0x5102, 577 }, + { 0x510F, 580 }, + { 0x5116, 583 }, + { 0x5013, 586 }, + { 0x50D3, 589 }, + { 0x50CF, 592 }, + { 0x50D6, 595 }, + { 0x50DA, 598 }, + { 0x50E0, 601 }, + { 0x51E4, 604 }, + { 0x51F0, 607 }, + { 0x51DC, 610 }, + { 0x51EC, 613 }, + { 0x51F4, 616 }, + { 0x5273, 619 }, + { 0x527E, 622 }, + { 0x527B, 625 }, + { 0x5006, 628 }, + { 0x5003, 631 }, + { 0x5000, 634 }, + { 0x5001, 637 }, + { 0x53E2, 640 }, + { 0x53EE, 643 }, + { 0x53F2, 646 }, + { 0x53F8, 649 }, + { 0x5201, 652 }, + { 0x520C, 655 }, + { 0x51FA, 658 }, + { 0x5208, 661 }, + { 0x5210, 664 }, + { 0x51C1, 667 }, + { 0x51CC, 670 }, + { 0x51B9, 673 }, + { 0x51C9, 676 }, + { 0x51D0, 679 }, + { 0x51D6, 682 }, + { 0x50B7, 685 }, + { 0x50C2, 688 }, + { 0x50B0, 691 }, + { 0x50BF, 694 }, + { 0x50C5, 697 }, + { 0x50CB, 700 }, + { 0x5185, 703 }, + { 0x518F, 706 }, + { 0x517F, 709 }, + { 0x518C, 712 }, + { 0x5193, 715 }, + { 0x5012, 718 }, + { 0x500F, 721 }, + { 0x5010, 724 }, + { 0x5041, 727 }, + { 0x503A, 730 }, + { 0x5048, 733 }, + { 0x504C, 736 }, + { 0x5052, 739 }, + { 0x53FE, 742 }, + { 0x540A, 745 }, + { 0x540E, 748 }, + { 0x5414, 751 }, + { 0x53C8, 754 }, + { 0x53D2, 757 }, + { 0x53CF, 760 }, + { 0x53D6, 763 }, + { 0x53DC, 766 }, + { 0x5312, 769 }, + { 0x531C, 772 }, + { 0x530B, 775 }, + { 0x5319, 778 }, + { 0x5320, 781 }, + { 0x5326, 784 }, + { 0x5123, 787 }, + { 0x512E, 790 }, + { 0x511C, 793 }, + { 0x512B, 796 }, + { 0x5132, 799 }, + { 0x500D, 802 }, + { 0x50EC, 805 }, + { 0x50E4, 808 }, + { 0x50F0, 811 }, + { 0x50F6, 814 }, + { 0x50FC, 817 }, + { 0x5282, 820 }, + { 0x528B, 823 }, + { 0x5288, 826 }, + { 0x5015, 829 }, + { 0x545F, 832 }, + { 0x5469, 835 }, + { 0x546D, 838 }, + { 0x5473, 841 }, + { 0x547F, 844 }, + { 0x5483, 847 }, + { 0x5489, 850 }, + { 0x5296, 853 }, + { 0x52A0, 856 }, + { 0x528F, 859 }, + { 0x529D, 862 }, + { 0x52A4, 865 }, + { 0x52AA, 868 }, + { 0x5021, 871 }, + { 0x501E, 874 }, + { 0x501F, 877 }, + { 0x5060, 880 }, + { 0x506A, 883 }, + { 0x5058, 886 }, + { 0x5067, 889 }, + { 0x506E, 892 }, + { 0x5074, 895 }, + { 0x502B, 898 }, + { 0x5029, 901 }, + { 0x501C, 904 }, + { 0x5019, 907 }, + { 0x5016, 910 }, + { 0x5017, 913 }, + { 0x5028, 916 }, + { 0x5025, 919 }, + { 0x5026, 922 }, + { 0x5023, 925 }, + { 0x502F, 928 }, + { 0x5031, 931 }, + { 0x502C, 934 }, + { 0x502D, 937 }, + { 0x5035, 940 }, + { 0x5037, 943 }, + { 0x5032, 946 }, + { 0x5033, 949 }, + { 0x52B9, 952 }, + { 0x52B6, 955 }, + { 0x52B7, 958 }, + { 0x52C3, 961 }, + { 0x52C1, 964 }, + { 0x5363, 967 }, + { 0x536F, 970 }, + { 0x536B, 973 }, + { 0x5372, 976 }, + { 0x5378, 979 }, + { 0x52B4, 982 }, + { 0x52B1, 985 }, + { 0x52AE, 988 }, + { 0x52AF, 991 }, + { 0x52C0, 994 }, + { 0x52BD, 997 }, + { 0x52BE, 1000 }, + { 0x52BB, 1003 }, + { 0x52C7, 1006 }, + { 0x52C9, 1009 }, + { 0x52C4, 1012 }, + { 0x52C5, 1015 }, + { 0x52CD, 1018 }, + { 0x52CF, 1021 }, + { 0x52CA, 1024 }, + { 0x52CB, 1027 }, + { 0x510A, 1030 }, + { 0x5107, 1033 }, + { 0x5108, 1036 }, + { 0x513F, 1039 }, + { 0x5149, 1042 }, + { 0x5138, 1045 }, + { 0x5146, 1048 }, + { 0x514D, 1051 }, + { 0x5113, 1054 }, + { 0x5111, 1057 }, + { 0x5105, 1060 }, + { 0x5103, 1063 }, + { 0x5100, 1066 }, + { 0x5101, 1069 }, + { 0x5110, 1072 }, + { 0x510D, 1075 }, + { 0x510E, 1078 }, + { 0x510C, 1081 }, + { 0x5117, 1084 }, + { 0x5119, 1087 }, + { 0x5114, 1090 }, + { 0x5115, 1093 }, + { 0x50D4, 1096 }, + { 0x50D1, 1099 }, + { 0x50D2, 1102 }, + { 0x50D0, 1105 }, + { 0x50CD, 1108 }, + { 0x50CE, 1111 }, + { 0x50D7, 1114 }, + { 0x50D5, 1117 }, + { 0x50DB, 1120 }, + { 0x50DD, 1123 }, + { 0x50D8, 1126 }, + { 0x50D9, 1129 }, + { 0x50E1, 1132 }, + { 0x50DE, 1135 }, + { 0x50DF, 1138 }, + { 0x51E5, 1141 }, + { 0x51E2, 1144 }, + { 0x51E3, 1147 }, + { 0x51F1, 1150 }, + { 0x51EE, 1153 }, + { 0x51EF, 1156 }, + { 0x521C, 1159 }, + { 0x5228, 1162 }, + { 0x5216, 1165 }, + { 0x5224, 1168 }, + { 0x522C, 1171 }, + { 0x51E0, 1174 }, + { 0x51DD, 1177 }, + { 0x51DA, 1180 }, + { 0x51DB, 1183 }, + { 0x51ED, 1186 }, + { 0x51EA, 1189 }, + { 0x51EB, 1192 }, + { 0x51E8, 1195 }, + { 0x51F5, 1198 }, + { 0x51F7, 1201 }, + { 0x51F2, 1204 }, + { 0x51F3, 1207 }, + { 0x5274, 1210 }, + { 0x5271, 1213 }, + { 0x5272, 1216 }, + { 0x527F, 1219 }, + { 0x527D, 1222 }, + { 0x5270, 1225 }, + { 0x526E, 1228 }, + { 0x51A0, 1231 }, + { 0x51A9, 1234 }, + { 0x5199, 1237 }, + { 0x51A6, 1240 }, + { 0x51AD, 1243 }, + { 0x51B3, 1246 }, + { 0x509A, 1249 }, + { 0x5093, 1252 }, + { 0x50A1, 1255 }, + { 0x50A5, 1258 }, + { 0x50AA, 1261 }, + { 0x5172, 1264 }, + { 0x517A, 1267 }, + { 0x516A, 1270 }, + { 0x527C, 1273 }, + { 0x5279, 1276 }, + { 0x527A, 1279 }, + { 0x5277, 1282 }, + { 0x5250, 1285 }, + { 0x525B, 1288 }, + { 0x5248, 1291 }, + { 0x5258, 1294 }, + { 0x5007, 1297 }, + { 0x5004, 1300 }, + { 0x5005, 1303 }, + { 0x53E6, 1306 }, + { 0x53E3, 1309 }, + { 0x53E0, 1312 }, + { 0x53E1, 1315 }, + { 0x541A, 1318 }, + { 0x5425, 1321 }, + { 0x5429, 1324 }, + { 0x542F, 1327 }, + { 0x53EF, 1330 }, + { 0x53EC, 1333 }, + { 0x53ED, 1336 }, + { 0x53EA, 1339 }, + { 0x53F3, 1342 }, + { 0x53F5, 1345 }, + { 0x53F0, 1348 }, + { 0x53F1, 1351 }, + { 0x53F9, 1354 }, + { 0x53FB, 1357 }, + { 0x53F6, 1360 }, + { 0x53F7, 1363 }, + { 0x5202, 1366 }, + { 0x51FF, 1369 }, + { 0x5200, 1372 }, + { 0x520D, 1375 }, + { 0x520A, 1378 }, + { 0x520B, 1381 }, + { 0x51FD, 1384 }, + { 0x51FB, 1387 }, + { 0x51F8, 1390 }, + { 0x51F9, 1393 }, + { 0x5209, 1396 }, + { 0x5206, 1399 }, + { 0x5207, 1402 }, + { 0x5204, 1405 }, + { 0x5211, 1408 }, + { 0x5213, 1411 }, + { 0x520E, 1414 }, + { 0x520F, 1417 }, + { 0x51C2, 1420 }, + { 0x51BF, 1423 }, + { 0x51C0, 1426 }, + { 0x51CD, 1429 }, + { 0x51CB, 1432 }, + { 0x51BD, 1435 }, + { 0x51BA, 1438 }, + { 0x51B7, 1441 }, + { 0x51B8, 1444 }, + { 0x51CA, 1447 }, + { 0x51C7, 1450 }, + { 0x51C8, 1453 }, + { 0x51C5, 1456 }, + { 0x51D1, 1459 }, + { 0x51D3, 1462 }, + { 0x51CE, 1465 }, + { 0x51CF, 1468 }, + { 0x51D7, 1471 }, + { 0x51D9, 1474 }, + { 0x51D4, 1477 }, + { 0x51D5, 1480 }, + { 0x50B8, 1483 }, + { 0x50B5, 1486 }, + { 0x50B6, 1489 }, + { 0x50C1, 1492 }, + { 0x5234, 1495 }, + { 0x523E, 1498 }, + { 0x523B, 1501 }, + { 0x5242, 1504 }, + { 0x50B3, 1507 }, + { 0x50B1, 1510 }, + { 0x50AE, 1513 }, + { 0x50AF, 1516 }, + { 0x50C0, 1519 }, + { 0x50BD, 1522 }, + { 0x50BE, 1525 }, + { 0x50BB, 1528 }, + { 0x50C6, 1531 }, + { 0x50C8, 1534 }, + { 0x50C3, 1537 }, + { 0x50C4, 1540 }, + { 0x50CC, 1543 }, + { 0x50C9, 1546 }, + { 0x50CA, 1549 }, + { 0x5186, 1552 }, + { 0x5184, 1555 }, + { 0x507F, 1558 }, + { 0x5078, 1561 }, + { 0x5083, 1564 }, + { 0x5087, 1567 }, + { 0x508D, 1570 }, + { 0x5159, 1573 }, + { 0x5160, 1576 }, + { 0x5153, 1579 }, + { 0x515D, 1582 }, + { 0x5164, 1585 }, + { 0x5190, 1588 }, + { 0x518E, 1591 }, + { 0x5262, 1594 }, + { 0x526C, 1597 }, + { 0x5269, 1600 }, + { 0x5182, 1603 }, + { 0x5180, 1606 }, + { 0x517D, 1609 }, + { 0x517E, 1612 }, + { 0x5433, 1615 }, + { 0x543D, 1618 }, + { 0x5440, 1621 }, + { 0x5446, 1624 }, + { 0x518D, 1627 }, + { 0x518A, 1630 }, + { 0x518B, 1633 }, + { 0x5396, 1636 }, + { 0x539D, 1639 }, + { 0x5399, 1642 }, + { 0x53A1, 1645 }, + { 0x53A7, 1648 }, + { 0x5188, 1651 }, + { 0x5194, 1654 }, + { 0x5196, 1657 }, + { 0x5191, 1660 }, + { 0x5192, 1663 }, + { 0x544C, 1666 }, + { 0x5457, 1669 }, + { 0x545B, 1672 }, + { 0x52F6, 1675 }, + { 0x52FD, 1678 }, + { 0x52EF, 1681 }, + { 0x52FF, 1684 }, + { 0x5305, 1687 }, + { 0x5042, 1690 }, + { 0x503F, 1693 }, + { 0x5040, 1696 }, + { 0x503D, 1699 }, + { 0x503B, 1702 }, + { 0x5038, 1705 }, + { 0x5039, 1708 }, + { 0x5049, 1711 }, + { 0x5046, 1714 }, + { 0x5047, 1717 }, + { 0x5044, 1720 }, + { 0x504D, 1723 }, + { 0x504F, 1726 }, + { 0x504A, 1729 }, + { 0x504B, 1732 }, + { 0x5053, 1735 }, + { 0x5055, 1738 }, + { 0x5050, 1741 }, + { 0x5051, 1744 }, + { 0x5402, 1747 }, + { 0x53FF, 1750 }, + { 0x53FC, 1753 }, + { 0x53FD, 1756 }, + { 0x540B, 1759 }, + { 0x5408, 1762 }, + { 0x5409, 1765 }, + { 0x5406, 1768 }, + { 0x540F, 1771 }, + { 0x5411, 1774 }, + { 0x540C, 1777 }, + { 0x540D, 1780 }, + { 0x5415, 1783 }, + { 0x5417, 1786 }, + { 0x5412, 1789 }, + { 0x5413, 1792 }, + { 0x53C9, 1795 }, + { 0x53C6, 1798 }, + { 0x53C7, 1801 }, + { 0x53D3, 1804 }, + { 0x53D1, 1807 }, + { 0x53D0, 1810 }, + { 0x53CD, 1813 }, + { 0x53CE, 1816 }, + { 0x537D, 1819 }, + { 0x5386, 1822 }, + { 0x5382, 1825 }, + { 0x538A, 1828 }, + { 0x5390, 1831 }, + { 0x53CB, 1834 }, + { 0x53D7, 1837 }, + { 0x53D9, 1840 }, + { 0x53D4, 1843 }, + { 0x53D5, 1846 }, + { 0x53DD, 1849 }, + { 0x53DF, 1852 }, + { 0x53DA, 1855 }, + { 0x53DB, 1858 }, + { 0x5313, 1861 }, + { 0x5310, 1864 }, + { 0x5311, 1867 }, + { 0x531D, 1870 }, + { 0x531B, 1873 }, + { 0x53AD, 1876 }, + { 0x53B8, 1879 }, + { 0x53B4, 1882 }, + { 0x53BC, 1885 }, + { 0x53C2, 1888 }, + { 0x530E, 1891 }, + { 0x530C, 1894 }, + { 0x5309, 1897 }, + { 0x530A, 1900 }, + { 0x531A, 1903 }, + { 0x5317, 1906 }, + { 0x5318, 1909 }, + { 0x5333, 1912 }, + { 0x533A, 1915 }, + { 0x532C, 1918 }, + { 0x5337, 1921 }, + { 0x533E, 1924 }, + { 0x5342, 1927 }, + { 0x5315, 1930 }, + { 0x5321, 1933 }, + { 0x5323, 1936 }, + { 0x531E, 1939 }, + { 0x531F, 1942 }, + { 0x5327, 1945 }, + { 0x5329, 1948 }, + { 0x5324, 1951 }, + { 0x5325, 1954 }, + { 0x5124, 1957 }, + { 0x5121, 1960 }, + { 0x5122, 1963 }, + { 0x512F, 1966 }, + { 0x512D, 1969 }, + { 0x511F, 1972 }, + { 0x511D, 1975 }, + { 0x511A, 1978 }, + { 0x511B, 1981 }, + { 0x512C, 1984 }, + { 0x5129, 1987 }, + { 0x512A, 1990 }, + { 0x5127, 1993 }, + { 0x5133, 1996 }, + { 0x5135, 1999 }, + { 0x5130, 2002 }, + { 0x5131, 2005 }, + { 0x500E, 2008 }, + { 0x500C, 2011 }, + { 0x50ED, 2014 }, + { 0x50EA, 2017 }, + { 0x50EB, 2020 }, + { 0x50F3, 2023 }, + { 0x50F2, 2026 }, + { 0x50E8, 2029 }, + { 0x50E5, 2032 }, + { 0x50E2, 2035 }, + { 0x50E3, 2038 }, + { 0x50F1, 2041 }, + { 0x50EE, 2044 }, + { 0x50EF, 2047 }, + { 0x50F7, 2050 }, + { 0x50F9, 2053 }, + { 0x50F4, 2056 }, + { 0x50F5, 2059 }, + { 0x50FD, 2062 }, + { 0x50FF, 2065 }, + { 0x50FA, 2068 }, + { 0x50FB, 2071 }, + { 0x5283, 2074 }, + { 0x5280, 2077 }, + { 0x5281, 2080 }, + { 0x528C, 2083 }, + { 0x528A, 2086 }, + { 0x5289, 2089 }, + { 0x5287, 2092 }, + { 0x5285, 2095 }, + { 0x5463, 2098 }, + { 0x5460, 2101 }, + { 0x545D, 2104 }, + { 0x545E, 2107 }, + { 0x546A, 2110 }, + { 0x5467, 2113 }, + { 0x5468, 2116 }, + { 0x5466, 2119 }, + { 0x546E, 2122 }, + { 0x5470, 2125 }, + { 0x546B, 2128 }, + { 0x546C, 2131 }, + { 0x5477, 2134 }, + { 0x5474, 2137 }, + { 0x5471, 2140 }, + { 0x5472, 2143 }, + { 0x5480, 2146 }, + { 0x547D, 2149 }, + { 0x547E, 2152 }, + { 0x547B, 2155 }, + { 0x5484, 2158 }, + { 0x5486, 2161 }, + { 0x5481, 2164 }, + { 0x5482, 2167 }, + { 0x548A, 2170 }, + { 0x548C, 2173 }, + { 0x5487, 2176 }, + { 0x5488, 2179 }, + { 0x5297, 2182 }, + { 0x5294, 2185 }, + { 0x5295, 2188 }, + { 0x52A1, 2191 }, + { 0x529F, 2194 }, + { 0x5348, 2197 }, + { 0x5353, 2200 }, + { 0x534F, 2203 }, + { 0x5357, 2206 }, + { 0x535D, 2209 }, + { 0x5292, 2212 }, + { 0x5290, 2215 }, + { 0x528D, 2218 }, + { 0x528E, 2221 }, + { 0x529E, 2224 }, + { 0x529B, 2227 }, + { 0x529C, 2230 }, + { 0x5299, 2233 }, + { 0x52A5, 2236 }, + { 0x52A7, 2239 }, + { 0x52A2, 2242 }, + { 0x52A3, 2245 }, + { 0x52AB, 2248 }, + { 0x52AD, 2251 }, + { 0x52A8, 2254 }, + { 0x52A9, 2257 }, + { 0x52DA, 2260 }, + { 0x52E0, 2263 }, + { 0x52D2, 2266 }, + { 0x52DD, 2269 }, + { 0x52E3, 2272 }, + { 0x52E9, 2275 }, + { 0x5061, 2278 }, + { 0x505E, 2281 }, + { 0x505F, 2284 }, + { 0x506B, 2287 }, + { 0x5069, 2290 }, + { 0x505C, 2293 }, + { 0x5059, 2296 }, + { 0x5056, 2299 }, + { 0x5057, 2302 }, + { 0x5068, 2305 }, + { 0x5065, 2308 }, + { 0x5066, 2311 }, + { 0x5063, 2314 }, + { 0x506F, 2317 }, + { 0x5071, 2320 }, + { 0x506C, 2323 }, + { 0x506D, 2326 }, + { 0x5075, 2329 }, + { 0x5072, 2332 }, + { 0x5073, 2335 }, + { 0x501D, 2338 }, + { 0x501A, 2341 }, + { 0x501B, 2344 }, + { 0x5024, 2347 }, + { 0x5022, 2350 }, + { 0x5030, 2353 }, + { 0x5036, 2356 }, + { 0x5364, 2359 }, + { 0x5361, 2362 }, + { 0x5362, 2365 }, + { 0x5370, 2368 }, + { 0x536D, 2371 }, + { 0x536E, 2374 }, + { 0x536C, 2377 }, + { 0x5369, 2380 }, + { 0x536A, 2383 }, + { 0x5367, 2386 }, + { 0x5373, 2389 }, + { 0x5375, 2392 }, + { 0x5371, 2395 }, + { 0x5379, 2398 }, + { 0x537B, 2401 }, + { 0x5376, 2404 }, + { 0x5377, 2407 }, + { 0x52B5, 2410 }, + { 0x52B2, 2413 }, + { 0x52B3, 2416 }, + { 0x52BC, 2419 }, + { 0x52BA, 2422 }, + { 0x52C8, 2425 }, + { 0x52CE, 2428 }, + { 0x5140, 2431 }, + { 0x513D, 2434 }, + { 0x513E, 2437 }, + { 0x514A, 2440 }, + { 0x5148, 2443 }, + { 0x513B, 2446 }, + { 0x5139, 2449 }, + { 0x5136, 2452 }, + { 0x5137, 2455 }, + { 0x5147, 2458 }, + { 0x5144, 2461 }, + { 0x5145, 2464 }, + { 0x5142, 2467 }, + { 0x514E, 2470 }, + { 0x5150, 2473 }, + { 0x514B, 2476 }, + { 0x514C, 2479 }, + { 0x5106, 2482 }, + { 0x5104, 2485 }, + { 0x510B, 2488 }, + { 0x5118, 2491 }, + { 0x50DC, 2494 }, + { 0x521D, 2497 }, + { 0x521A, 2500 }, + { 0x521B, 2503 }, + { 0x5229, 2506 }, + { 0x5226, 2509 }, + { 0x5227, 2512 }, + { 0x5218, 2515 }, + { 0x5214, 2518 }, + { 0x5215, 2521 }, + { 0x5225, 2524 }, + { 0x5222, 2527 }, + { 0x5223, 2530 }, + { 0x5220, 2533 }, + { 0x522D, 2536 }, + { 0x522F, 2539 }, + { 0x522A, 2542 }, + { 0x522B, 2545 }, + { 0x51E1, 2548 }, + { 0x51DE, 2551 }, + { 0x51DF, 2554 }, + { 0x51E9, 2557 }, + { 0x51E6, 2560 }, + { 0x51E7, 2563 }, + { 0x51F6, 2566 }, + { 0x526F, 2569 }, + { 0x51A1, 2572 }, + { 0x519E, 2575 }, + { 0x519F, 2578 }, + { 0x51AA, 2581 }, + { 0x51A8, 2584 }, + { 0x519C, 2587 }, + { 0x519A, 2590 }, + { 0x5197, 2593 }, + { 0x5198, 2596 }, + { 0x51A7, 2599 }, + { 0x51A5, 2602 }, + { 0x51A3, 2605 }, + { 0x51AE, 2608 }, + { 0x51B0, 2611 }, + { 0x51AB, 2614 }, + { 0x51AC, 2617 }, + { 0x51B4, 2620 }, + { 0x51B6, 2623 }, + { 0x51B1, 2626 }, + { 0x51B2, 2629 }, + { 0x509B, 2632 }, + { 0x5098, 2635 }, + { 0x5099, 2638 }, + { 0x5096, 2641 }, + { 0x5094, 2644 }, + { 0x5091, 2647 }, + { 0x5092, 2650 }, + { 0x50A2, 2653 }, + { 0x509F, 2656 }, + { 0x50A0, 2659 }, + { 0x509D, 2662 }, + { 0x50A6, 2665 }, + { 0x50A8, 2668 }, + { 0x50A3, 2671 }, + { 0x50A4, 2674 }, + { 0x50AB, 2677 }, + { 0x50AD, 2680 }, + { 0x50A9, 2683 }, + { 0x5173, 2686 }, + { 0x5170, 2689 }, + { 0x5171, 2692 }, + { 0x517B, 2695 }, + { 0x5179, 2698 }, + { 0x516E, 2701 }, + { 0x516B, 2704 }, + { 0x5168, 2707 }, + { 0x5169, 2710 }, + { 0x5178, 2713 }, + { 0x5176, 2716 }, + { 0x5177, 2719 }, + { 0x5175, 2722 }, + { 0x517C, 2725 }, + { 0x5278, 2728 }, + { 0x5275, 2731 }, + { 0x5276, 2734 }, + { 0x5251, 2737 }, + { 0x524E, 2740 }, + { 0x524F, 2743 }, + { 0x525C, 2746 }, + { 0x525A, 2749 }, + { 0x524C, 2752 }, + { 0x5249, 2755 }, + { 0x5246, 2758 }, + { 0x5247, 2761 }, + { 0x5259, 2764 }, + { 0x5256, 2767 }, + { 0x5257, 2770 }, + { 0x5254, 2773 }, + { 0x53E7, 2776 }, + { 0x53E4, 2779 }, + { 0x53E5, 2782 }, + { 0x541E, 2785 }, + { 0x541B, 2788 }, + { 0x5418, 2791 }, + { 0x5419, 2794 }, + { 0x5426, 2797 }, + { 0x5423, 2800 }, + { 0x5424, 2803 }, + { 0x5421, 2806 }, + { 0x542A, 2809 }, + { 0x542C, 2812 }, + { 0x5427, 2815 }, + { 0x5428, 2818 }, + { 0x5430, 2821 }, + { 0x542D, 2824 }, + { 0x542E, 2827 }, + { 0x53EB, 2830 }, + { 0x53E8, 2833 }, + { 0x53E9, 2836 }, + { 0x53F4, 2839 }, + { 0x53FA, 2842 }, + { 0x51FE, 2845 }, + { 0x51FC, 2848 }, + { 0x5205, 2851 }, + { 0x5203, 2854 }, + { 0x5212, 2857 }, + { 0x51BE, 2860 }, + { 0x51BB, 2863 }, + { 0x51BC, 2866 }, + { 0x51C6, 2869 }, + { 0x51C3, 2872 }, + { 0x51C4, 2875 }, + { 0x51D2, 2878 }, + { 0x51D8, 2881 }, + { 0x5235, 2884 }, + { 0x5232, 2887 }, + { 0x5233, 2890 }, + { 0x523F, 2893 }, + { 0x523D, 2896 }, + { 0x5231, 2899 }, + { 0x523C, 2902 }, + { 0x5239, 2905 }, + { 0x523A, 2908 }, + { 0x5237, 2911 }, + { 0x5243, 2914 }, + { 0x5245, 2917 }, + { 0x5240, 2920 }, + { 0x5241, 2923 }, + { 0x50B4, 2926 }, + { 0x50B2, 2929 }, + { 0x50BC, 2932 }, + { 0x50B9, 2935 }, + { 0x50BA, 2938 }, + { 0x50C7, 2941 }, + { 0x5080, 2944 }, + { 0x507D, 2947 }, + { 0x507E, 2950 }, + { 0x507B, 2953 }, + { 0x5079, 2956 }, + { 0x5076, 2959 }, + { 0x5077, 2962 }, + { 0x5084, 2965 }, + { 0x5081, 2968 }, + { 0x5082, 2971 }, + { 0x5088, 2974 }, + { 0x508A, 2977 }, + { 0x5085, 2980 }, + { 0x5086, 2983 }, + { 0x508E, 2986 }, + { 0x5090, 2989 }, + { 0x508B, 2992 }, + { 0x508C, 2995 }, + { 0x515A, 2998 }, + { 0x5157, 3001 }, + { 0x5158, 3004 }, + { 0x5161, 3007 }, + { 0x515F, 3010 }, + { 0x5156, 3013 }, + { 0x5154, 3016 }, + { 0x5151, 3019 }, + { 0x5152, 3022 }, + { 0x515E, 3025 }, + { 0x515B, 3028 }, + { 0x515C, 3031 }, + { 0x5165, 3034 }, + { 0x5167, 3037 }, + { 0x5162, 3040 }, + { 0x5163, 3043 }, + { 0x5263, 3046 }, + { 0x5260, 3049 }, + { 0x5261, 3052 }, + { 0x526D, 3055 }, + { 0x526B, 3058 }, + { 0x525E, 3061 }, + { 0x526A, 3064 }, + { 0x5267, 3067 }, + { 0x5268, 3070 }, + { 0x5266, 3073 }, + { 0x5183, 3076 }, + { 0x5181, 3079 }, + { 0x5437, 3082 }, + { 0x5434, 3085 }, + { 0x5431, 3088 }, + { 0x5432, 3091 }, + { 0x543E, 3094 }, + { 0x543B, 3097 }, + { 0x543C, 3100 }, + { 0x543A, 3103 }, + { 0x5441, 3106 }, + { 0x5443, 3109 }, + { 0x543F, 3112 }, + { 0x5447, 3115 }, + { 0x5449, 3118 }, + { 0x5444, 3121 }, + { 0x5445, 3124 }, + { 0x5397, 3127 }, + { 0x5394, 3130 }, + { 0x5395, 3133 }, + { 0x539E, 3136 }, + { 0x539B, 3139 }, + { 0x539C, 3142 }, + { 0x539A, 3145 }, + { 0x5398, 3148 }, + { 0x53A2, 3151 }, + { 0x53A4, 3154 }, + { 0x539F, 3157 }, + { 0x53A0, 3160 }, + { 0x53A8, 3163 }, + { 0x53AA, 3166 }, + { 0x53A5, 3169 }, + { 0x53A6, 3172 }, + { 0x5189, 3175 }, + { 0x5187, 3178 }, + { 0x5195, 3181 }, + { 0x5450, 3184 }, + { 0x544D, 3187 }, + { 0x544A, 3190 }, + { 0x544B, 3193 }, + { 0x5458, 3196 }, + { 0x5455, 3199 }, + { 0x5456, 3202 }, + { 0x5453, 3205 }, + { 0x545C, 3208 }, + { 0x5459, 3211 }, + { 0x545A, 3214 }, + { 0x52F7, 3217 }, + { 0x52F4, 3220 }, + { 0x52F5, 3223 }, + { 0x52FC, 3226 }, + { 0x52F2, 3229 }, + { 0x52F0, 3232 }, + { 0x52ED, 3235 }, + { 0x52EE, 3238 }, + { 0x52FB, 3241 }, + { 0x52FA, 3244 }, + { 0x52F9, 3247 }, + { 0x5300, 3250 }, + { 0x5302, 3253 }, + { 0x52FE, 3256 }, + { 0x5306, 3259 }, + { 0x5308, 3262 }, + { 0x5303, 3265 }, + { 0x5304, 3268 }, + { 0x503E, 3271 }, + { 0x503C, 3274 }, + { 0x5045, 3277 }, + { 0x5043, 3280 }, + { 0x504E, 3283 }, + { 0x5054, 3286 }, + { 0x5403, 3289 }, + { 0x5400, 3292 }, + { 0x5401, 3295 }, + { 0x5407, 3298 }, + { 0x5404, 3301 }, + { 0x5405, 3304 }, + { 0x5410, 3307 }, + { 0x5416, 3310 }, + { 0x537C, 3313 }, + { 0x5387, 3316 }, + { 0x5384, 3319 }, + { 0x5385, 3322 }, + { 0x5383, 3325 }, + { 0x5380, 3328 }, + { 0x5381, 3331 }, + { 0x537F, 3334 }, + { 0x538B, 3337 }, + { 0x538D, 3340 }, + { 0x5388, 3343 }, + { 0x5389, 3346 }, + { 0x5391, 3349 }, + { 0x5393, 3352 }, + { 0x538E, 3355 }, + { 0x538F, 3358 }, + { 0x53CC, 3361 }, + { 0x53CA, 3364 }, + { 0x53D8, 3367 }, + { 0x53DE, 3370 }, + { 0x53AE, 3373 }, + { 0x53AB, 3376 }, + { 0x53AC, 3379 }, + { 0x53B9, 3382 }, + { 0x53B6, 3385 }, + { 0x53B7, 3388 }, + { 0x53B5, 3391 }, + { 0x53B2, 3394 }, + { 0x53B3, 3397 }, + { 0x53B0, 3400 }, + { 0x53BD, 3403 }, + { 0x53BF, 3406 }, + { 0x53BA, 3409 }, + { 0x53BB, 3412 }, + { 0x53C3, 3415 }, + { 0x53C5, 3418 }, + { 0x53C0, 3421 }, + { 0x53C1, 3424 }, + { 0x530F, 3427 }, + { 0x530D, 3430 }, + { 0x5334, 3433 }, + { 0x5331, 3436 }, + { 0x5332, 3439 }, + { 0x533B, 3442 }, + { 0x5339, 3445 }, + { 0x532F, 3448 }, + { 0x532D, 3451 }, + { 0x532A, 3454 }, + { 0x532B, 3457 }, + { 0x5338, 3460 }, + { 0x5335, 3463 }, + { 0x5336, 3466 }, + { 0x533F, 3469 }, + { 0x533C, 3472 }, + { 0x533D, 3475 }, + { 0x5343, 3478 }, + { 0x5345, 3481 }, + { 0x5340, 3484 }, + { 0x5341, 3487 }, + { 0x5316, 3490 }, + { 0x5314, 3493 }, + { 0x5322, 3496 }, + { 0x5328, 3499 }, + { 0x5120, 3502 }, + { 0x511E, 3505 }, + { 0x5128, 3508 }, + { 0x5125, 3511 }, + { 0x5126, 3514 }, + { 0x5134, 3517 }, + { 0x50E9, 3520 }, + { 0x50E6, 3523 }, + { 0x50E7, 3526 }, + { 0x50F8, 3529 }, + { 0x50FE, 3532 }, + { 0x5286, 3535 }, + { 0x5284, 3538 }, + { 0x5464, 3541 }, + { 0x5461, 3544 }, + { 0x5462, 3547 }, + { 0x5465, 3550 }, + { 0x546F, 3553 }, + { 0x5478, 3556 }, + { 0x5475, 3559 }, + { 0x5476, 3562 }, + { 0x547C, 3565 }, + { 0x5479, 3568 }, + { 0x547A, 3571 }, + { 0x5485, 3574 }, + { 0x548B, 3577 }, + { 0x5349, 3580 }, + { 0x5346, 3583 }, + { 0x5347, 3586 }, + { 0x5354, 3589 }, + { 0x5351, 3592 }, + { 0x5352, 3595 }, + { 0x5350, 3598 }, + { 0x534D, 3601 }, + { 0x534E, 3604 }, + { 0x534B, 3607 }, + { 0x5358, 3610 }, + { 0x535A, 3613 }, + { 0x5355, 3616 }, + { 0x5356, 3619 }, + { 0x535E, 3622 }, + { 0x5360, 3625 }, + { 0x535B, 3628 }, + { 0x535C, 3631 }, + { 0x5293, 3634 }, + { 0x5291, 3637 }, + { 0x529A, 3640 }, + { 0x5298, 3643 }, + { 0x52A6, 3646 }, + { 0x52AC, 3649 }, + { 0x52DB, 3652 }, + { 0x52D8, 3655 }, + { 0x52D9, 3658 }, + { 0x52E1, 3661 }, + { 0x52DF, 3664 }, + { 0x52D6, 3667 }, + { 0x52D3, 3670 }, + { 0x52D0, 3673 }, + { 0x52D1, 3676 }, + { 0x52DE, 3679 }, + { 0x52DC, 3682 }, + { 0x52E4, 3685 }, + { 0x52E6, 3688 }, + { 0x52E2, 3691 }, + { 0x52EA, 3694 }, + { 0x52EC, 3697 }, + { 0x52E7, 3700 }, + { 0x52E8, 3703 }, + { 0x505D, 3706 }, + { 0x505A, 3709 }, + { 0x505B, 3712 }, + { 0x5064, 3715 }, + { 0x5062, 3718 }, + { 0x5070, 3721 }, + { 0x5368, 3724 }, + { 0x5365, 3727 }, + { 0x5366, 3730 }, + { 0x5374, 3733 }, + { 0x537A, 3736 }, + { 0x513C, 3739 }, + { 0x513A, 3742 }, + { 0x5143, 3745 }, + { 0x5141, 3748 }, + { 0x514F, 3751 }, + { 0x5219, 3754 }, + { 0x5217, 3757 }, + { 0x5221, 3760 }, + { 0x521E, 3763 }, + { 0x521F, 3766 }, + { 0x522E, 3769 }, + { 0x519D, 3772 }, + { 0x519B, 3775 }, + { 0x51A4, 3778 }, + { 0x51A2, 3781 }, + { 0x51AF, 3784 }, + { 0x51B5, 3787 }, + { 0x5097, 3790 }, + { 0x5095, 3793 }, + { 0x509E, 3796 }, + { 0x509C, 3799 }, + { 0x50A7, 3802 }, + { 0x50AC, 3805 }, + { 0x516F, 3808 }, + { 0x516C, 3811 }, + { 0x516D, 3814 }, + { 0x5174, 3817 }, + { 0x524D, 3820 }, + { 0x524A, 3823 }, + { 0x524B, 3826 }, + { 0x5255, 3829 }, + { 0x5252, 3832 }, + { 0x5253, 3835 }, + { 0x541F, 3838 }, + { 0x541C, 3841 }, + { 0x541D, 3844 }, + { 0x5422, 3847 }, + { 0x5420, 3850 }, + { 0x542B, 3853 }, + { 0x5230, 3856 }, + { 0x5238, 3859 }, + { 0x5236, 3862 }, + { 0x5244, 3865 }, + { 0x507C, 3868 }, + { 0x507A, 3871 }, + { 0x5089, 3874 }, + { 0x508F, 3877 }, + { 0x5155, 3880 }, + { 0x5166, 3883 }, + { 0x525F, 3886 }, + { 0x525D, 3889 }, + { 0x5264, 3892 }, + { 0x5265, 3895 }, + { 0x5438, 3898 }, + { 0x5435, 3901 }, + { 0x5436, 3904 }, + { 0x5439, 3907 }, + { 0x5442, 3910 }, + { 0x5448, 3913 }, + { 0x53A3, 3916 }, + { 0x53A9, 3919 }, + { 0x5451, 3922 }, + { 0x544E, 3925 }, + { 0x544F, 3928 }, + { 0x5454, 3931 }, + { 0x5452, 3934 }, + { 0x52F3, 3937 }, + { 0x52F1, 3940 }, + { 0x52F8, 3943 }, + { 0x5301, 3946 }, + { 0x5307, 3949 }, + { 0x537E, 3952 }, + { 0x538C, 3955 }, + { 0x5392, 3958 }, + { 0x53B1, 3961 }, + { 0x53AF, 3964 }, + { 0x53BE, 3967 }, + { 0x53C4, 3970 }, + { 0x5330, 3973 }, + { 0x532E, 3976 }, + { 0x5344, 3979 }, + { 0x534C, 3982 }, + { 0x534A, 3985 }, + { 0x5359, 3988 }, + { 0x535F, 3991 }, + { 0x52D7, 3994 }, + { 0x52D4, 3997 }, + { 0x52D5, 4000 }, + { 0x52E5, 4003 }, + { 0x52EB, 4006 }, + { 0x262C, 4009 }, + { 0x224C, 4011 }, + { 0x232E, 4014 }, + { 0x27D1, 4016 }, + { 0x235D, 4019 }, + { 0x2355, 4025 }, + { 0x2351, 4031 }, + { 0x2361, 4037 }, + { 0x2372, 4043 }, + { 0x2352, 4049 }, + { 0x236B, 4054 }, + { 0x2362, 4059 }, + { 0x235B, 4064 }, + { 0x2364, 4069 }, + { 0x2374, 4074 }, + { 0x2366, 4078 }, + { 0x234E, 4084 }, + { 0x234A, 4090 }, + { 0x2371, 4096 }, + { 0x2373, 4102 }, + { 0x2378, 4106 }, + { 0x2367, 4111 }, + { 0x2395, 4117 }, + { 0x2353, 4121 }, + { 0x2354, 4127 }, + { 0x233B, 4132 }, + { 0x236F, 4137 }, + { 0x234C, 4143 }, + { 0x2360, 4149 }, + { 0x234D, 4154 }, + { 0x2338, 4159 }, + { 0x2341, 4164 }, + { 0x233C, 4169 }, + { 0x2339, 4174 }, + { 0x233A, 4179 }, + { 0x2350, 4184 }, + { 0x2370, 4190 }, + { 0x2342, 4195 }, + { 0x2357, 4200 }, + { 0x2347, 4206 }, + { 0x2343, 4212 }, + { 0x2348, 4217 }, + { 0x2344, 4223 }, + { 0x2363, 4228 }, + { 0x237A, 4233 }, + { 0x2376, 4237 }, + { 0x236A, 4242 }, + { 0x234B, 4247 }, + { 0x2359, 4252 }, + { 0x2375, 4257 }, + { 0x2379, 4261 }, + { 0x235E, 4266 }, + { 0x2358, 4271 }, + { 0x233F, 4276 }, + { 0x236D, 4281 }, + { 0x2368, 4286 }, + { 0x236C, 4291 }, + { 0x233E, 4295 }, + { 0x235F, 4300 }, + { 0x233D, 4305 }, + { 0x235C, 4310 }, + { 0x2349, 4315 }, + { 0x2365, 4320 }, + { 0x2336, 4325 }, + { 0x2337, 4329 }, + { 0x235A, 4334 }, + { 0x2377, 4339 }, + { 0x234F, 4344 }, + { 0x2340, 4349 }, + { 0x2356, 4354 }, + { 0x2345, 4359 }, + { 0x236E, 4364 }, + { 0x2346, 4369 }, + { 0x2369, 4374 }, + { 0x2312, 4379 }, + { 0x2136, 4380 }, + { 0x29F9, 4382 }, + { 0x29F8, 4385 }, + { 0x2540, 4387 }, + { 0x2526, 4395 }, + { 0x251A, 4403 }, + { 0x251E, 4410 }, + { 0x2516, 4418 }, + { 0x2538, 4425 }, + { 0x2548, 4432 }, + { 0x252A, 4440 }, + { 0x2519, 4448 }, + { 0x2522, 4455 }, + { 0x2515, 4463 }, + { 0x2537, 4470 }, + { 0x255C, 4477 }, + { 0x2559, 4484 }, + { 0x2568, 4491 }, + { 0x255B, 4498 }, + { 0x2558, 4505 }, + { 0x2567, 4512 }, + { 0x2541, 4519 }, + { 0x2527, 4527 }, + { 0x2512, 4535 }, + { 0x251F, 4542 }, + { 0x250E, 4550 }, + { 0x2530, 4557 }, + { 0x2547, 4564 }, + { 0x2529, 4572 }, + { 0x2511, 4580 }, + { 0x2521, 4587 }, + { 0x250D, 4595 }, + { 0x252F, 4602 }, + { 0x2556, 4609 }, + { 0x2553, 4616 }, + { 0x2565, 4623 }, + { 0x2555, 4630 }, + { 0x2552, 4637 }, + { 0x2564, 4644 }, + { 0x2543, 4651 }, + { 0x2545, 4660 }, + { 0x2535, 4669 }, + { 0x252D, 4677 }, + { 0x253D, 4685 }, + { 0x253A, 4693 }, + { 0x2532, 4701 }, + { 0x254A, 4709 }, + { 0x2579, 4717 }, + { 0x251B, 4721 }, + { 0x257F, 4727 }, + { 0x2517, 4734 }, + { 0x253B, 4740 }, + { 0x257B, 4746 }, + { 0x2513, 4750 }, + { 0x250F, 4756 }, + { 0x2533, 4762 }, + { 0x2578, 4768 }, + { 0x257E, 4772 }, + { 0x257A, 4779 }, + { 0x254F, 4783 }, + { 0x254D, 4789 }, + { 0x2507, 4795 }, + { 0x2505, 4801 }, + { 0x2503, 4807 }, + { 0x252B, 4811 }, + { 0x2523, 4817 }, + { 0x254B, 4823 }, + { 0x250B, 4829 }, + { 0x2509, 4835 }, + { 0x2501, 4841 }, + { 0x2575, 4845 }, + { 0x2518, 4849 }, + { 0x257D, 4855 }, + { 0x2514, 4862 }, + { 0x2534, 4868 }, + { 0x256F, 4874 }, + { 0x2570, 4881 }, + { 0x256E, 4888 }, + { 0x256D, 4895 }, + { 0x2577, 4902 }, + { 0x2510, 4906 }, + { 0x250C, 4912 }, + { 0x252C, 4918 }, + { 0x2574, 4924 }, + { 0x257C, 4928 }, + { 0x2576, 4935 }, + { 0x254E, 4939 }, + { 0x254C, 4945 }, + { 0x2506, 4951 }, + { 0x2504, 4957 }, + { 0x2573, 4963 }, + { 0x2572, 4968 }, + { 0x2571, 4977 }, + { 0x2502, 4986 }, + { 0x2524, 4990 }, + { 0x251C, 4996 }, + { 0x253C, 5002 }, + { 0x250A, 5008 }, + { 0x2508, 5014 }, + { 0x2500, 5020 }, + { 0x2544, 5024 }, + { 0x2546, 5033 }, + { 0x2536, 5042 }, + { 0x252E, 5050 }, + { 0x253E, 5058 }, + { 0x2539, 5066 }, + { 0x2531, 5074 }, + { 0x2549, 5082 }, + { 0x255D, 5090 }, + { 0x255A, 5096 }, + { 0x2569, 5102 }, + { 0x2557, 5108 }, + { 0x2554, 5114 }, + { 0x2566, 5120 }, + { 0x2551, 5126 }, + { 0x2563, 5130 }, + { 0x2560, 5136 }, + { 0x256C, 5142 }, + { 0x2550, 5148 }, + { 0x2528, 5152 }, + { 0x2520, 5159 }, + { 0x2542, 5166 }, + { 0x2525, 5173 }, + { 0x251D, 5180 }, + { 0x253F, 5187 }, + { 0x2562, 5194 }, + { 0x255F, 5201 }, + { 0x256B, 5208 }, + { 0x2561, 5215 }, + { 0x255E, 5222 }, + { 0x256A, 5229 }, + { 0x2627, 5236 }, + { 0x31D4, 5238 }, + { 0x31D0, 5241 }, + { 0x31CF, 5244 }, + { 0x31D2, 5247 }, + { 0x31E3, 5250 }, + { 0x31D1, 5253 }, + { 0x31C0, 5256 }, + { 0x31D6, 5259 }, + { 0x31C7, 5262 }, + { 0x31D5, 5265 }, + { 0x31DB, 5268 }, + { 0x31E2, 5271 }, + { 0x31DC, 5274 }, + { 0x31DA, 5277 }, + { 0x31D3, 5280 }, + { 0x31D9, 5283 }, + { 0x31C4, 5286 }, + { 0x31D7, 5289 }, + { 0x31DD, 5292 }, + { 0x31C1, 5295 }, + { 0x31C2, 5298 }, + { 0x31C3, 5301 }, + { 0x31C6, 5304 }, + { 0x31CA, 5307 }, + { 0x31CD, 5310 }, + { 0x31C5, 5313 }, + { 0x31DF, 5316 }, + { 0x31D8, 5319 }, + { 0x31DE, 5322 }, + { 0x31CC, 5325 }, + { 0x31E0, 5328 }, + { 0x31C8, 5331 }, + { 0x31CB, 5334 }, + { 0x31CE, 5337 }, + { 0x31C9, 5340 }, + { 0x31E1, 5343 }, + { 0x2E86, 5346 }, + { 0x2EA7, 5349 }, + { 0x2EA8, 5352 }, + { 0x2EDD, 5355 }, + { 0x2EDE, 5359 }, + { 0x2EDF, 5363 }, + { 0x2EB8, 5367 }, + { 0x2EAB, 5370 }, + { 0x2EB1, 5373 }, + { 0x2EB2, 5377 }, + { 0x2EB4, 5381 }, + { 0x2EB3, 5385 }, + { 0x2EB9, 5389 }, + { 0x2EA4, 5392 }, + { 0x2EA5, 5396 }, + { 0x2EB7, 5400 }, + { 0x2E99, 5403 }, + { 0x2E9C, 5406 }, + { 0x2ED8, 5409 }, + { 0x2EAA, 5412 }, + { 0x2EE3, 5417 }, + { 0x2ECF, 5420 }, + { 0x2EA3, 5423 }, + { 0x2ECA, 5426 }, + { 0x2E98, 5429 }, + { 0x2EE1, 5432 }, + { 0x2EC7, 5435 }, + { 0x2EA9, 5438 }, + { 0x2E8E, 5441 }, + { 0x2E8F, 5445 }, + { 0x2E91, 5449 }, + { 0x2E90, 5453 }, + { 0x2ED1, 5457 }, + { 0x2ED2, 5461 }, + { 0x2EBC, 5465 }, + { 0x2EB5, 5468 }, + { 0x2E9D, 5471 }, + { 0x2ED7, 5474 }, + { 0x2E8B, 5477 }, + { 0x2EAF, 5480 }, + { 0x2ECD, 5483 }, + { 0x2ECE, 5487 }, + { 0x2EC3, 5491 }, + { 0x2EC4, 5495 }, + { 0x2EBA, 5499 }, + { 0x2EBB, 5503 }, + { 0x2E9B, 5507 }, + { 0x2E81, 5510 }, + { 0x2E9E, 5513 }, + { 0x2EE4, 5516 }, + { 0x2EBE, 5519 }, + { 0x2EBF, 5523 }, + { 0x2EC0, 5527 }, + { 0x2E96, 5531 }, + { 0x2E97, 5535 }, + { 0x2E88, 5539 }, + { 0x2E89, 5543 }, + { 0x2ED5, 5547 }, + { 0x2ED6, 5551 }, + { 0x2EB6, 5555 }, + { 0x2E8C, 5558 }, + { 0x2E8D, 5562 }, + { 0x2E92, 5566 }, + { 0x2E94, 5569 }, + { 0x2E95, 5573 }, + { 0x2E87, 5577 }, + { 0x2EC1, 5580 }, + { 0x2EA1, 5583 }, + { 0x2EA2, 5587 }, + { 0x2EAE, 5591 }, + { 0x2EBD, 5594 }, + { 0x2E9F, 5597 }, + { 0x2E85, 5600 }, + { 0x2E80, 5603 }, + { 0x2E82, 5606 }, + { 0x2E83, 5610 }, + { 0x2E84, 5614 }, + { 0x2EAC, 5618 }, + { 0x2EAD, 5622 }, + { 0x2E93, 5626 }, + { 0x2EF1, 5629 }, + { 0x2EC2, 5632 }, + { 0x2EA0, 5635 }, + { 0x2E8A, 5638 }, + { 0x2EA6, 5641 }, + { 0x2EC6, 5647 }, + { 0x2ECC, 5651 }, + { 0x2EE8, 5655 }, + { 0x2EE9, 5659 }, + { 0x2EE0, 5663 }, + { 0x2EDC, 5667 }, + { 0x2EC5, 5671 }, + { 0x2EE6, 5675 }, + { 0x2ECB, 5679 }, + { 0x2EEC, 5683 }, + { 0x2EE5, 5687 }, + { 0x2EEA, 5691 }, + { 0x2ED4, 5695 }, + { 0x2ED0, 5699 }, + { 0x2EDA, 5703 }, + { 0x2ED3, 5707 }, + { 0x2EE7, 5711 }, + { 0x2EB0, 5715 }, + { 0x2EDB, 5719 }, + { 0x2EE2, 5723 }, + { 0x2EC9, 5727 }, + { 0x2EEE, 5731 }, + { 0x2EF0, 5735 }, + { 0x2EC8, 5739 }, + { 0x2ED9, 5743 }, + { 0x2EF3, 5748 }, + { 0x2EEB, 5752 }, + { 0x2EED, 5756 }, + { 0x2EEF, 5760 }, + { 0x2EF2, 5764 }, + { 0x2680, 5768 }, + { 0x2681, 5770 }, + { 0x2682, 5772 }, + { 0x2683, 5774 }, + { 0x2684, 5776 }, + { 0x2685, 5778 }, + { 0x2214, 5780 }, + { 0x02D9, 5782 }, + { 0x2238, 5784 }, + { 0x22C5, 5786 }, + { 0x220E, 5788 }, + { 0x2200, 5791 }, + { 0x2668, 5793 }, + { 0x2615, 5795 }, + { 0x20AD, 5797 }, + { 0x0EDD, 5799 }, + { 0x0EDC, 5802 }, + { 0x0EC6, 5805 }, + { 0x0EC8, 5808 }, + { 0x0ECA, 5812 }, + { 0x0EC9, 5816 }, + { 0x0ECB, 5820 }, + { 0x0ED1, 5824 }, + { 0x0ED6, 5827 }, + { 0x0ED2, 5830 }, + { 0x0ED5, 5833 }, + { 0x0ED4, 5836 }, + { 0x0ED9, 5839 }, + { 0x0ED0, 5842 }, + { 0x0ED8, 5845 }, + { 0x0ED7, 5848 }, + { 0x0ED3, 5851 }, + { 0x0EB0, 5854 }, + { 0x0EC0, 5858 }, + { 0x0EB4, 5862 }, + { 0x0EC2, 5866 }, + { 0x0EB8, 5870 }, + { 0x0EB6, 5874 }, + { 0x0EB2, 5878 }, + { 0x0EC4, 5882 }, + { 0x0EB3, 5886 }, + { 0x0EC3, 5890 }, + { 0x0EC1, 5894 }, + { 0x0EB5, 5898 }, + { 0x0EB9, 5902 }, + { 0x0EB7, 5906 }, + { 0x0EB1, 5910 }, + { 0x0EBB, 5915 }, + { 0x0EAD, 5920 }, + { 0x0E9A, 5923 }, + { 0x0E88, 5926 }, + { 0x0E94, 5929 }, + { 0x0E9D, 5932 }, + { 0x0E9F, 5936 }, + { 0x0EAE, 5940 }, + { 0x0EAB, 5944 }, + { 0x0E81, 5948 }, + { 0x0EA3, 5951 }, + { 0x0EA5, 5955 }, + { 0x0EA1, 5959 }, + { 0x0E99, 5962 }, + { 0x0E9B, 5965 }, + { 0x0E8A, 5968 }, + { 0x0EAA, 5972 }, + { 0x0E95, 5976 }, + { 0x0EA7, 5979 }, + { 0x0EA2, 5982 }, + { 0x0E84, 5985 }, + { 0x0E82, 5989 }, + { 0x0E87, 5993 }, + { 0x0E8D, 5996 }, + { 0x0E9E, 5999 }, + { 0x0E9C, 6003 }, + { 0x0E97, 6007 }, + { 0x0E96, 6011 }, + { 0x0EAF, 6015 }, + { 0x0ECD, 6017 }, + { 0x0EBC, 6019 }, + { 0x0EBD, 6023 }, + { 0x0ECC, 6027 }, + { 0x264C, 6030 }, + { 0x005F, 6031 }, + { 0x301F, 6033 }, + { 0x204E, 6038 }, + { 0x19DE, 6040 }, + { 0x19DF, 6045 }, + { 0x19C8, 6050 }, + { 0x19C9, 6055 }, + { 0x19D1, 6060 }, + { 0x19D6, 6065 }, + { 0x19D2, 6070 }, + { 0x19D5, 6075 }, + { 0x19D4, 6080 }, + { 0x19D9, 6085 }, + { 0x19D0, 6090 }, + { 0x19D8, 6095 }, + { 0x19D7, 6100 }, + { 0x19D3, 6105 }, + { 0x19B5, 6110 }, + { 0x19B7, 6116 }, + { 0x19B3, 6122 }, + { 0x19B1, 6128 }, + { 0x19B6, 6134 }, + { 0x19BA, 6140 }, + { 0x19B2, 6146 }, + { 0x19C0, 6152 }, + { 0x19B8, 6158 }, + { 0x19BD, 6164 }, + { 0x19B9, 6170 }, + { 0x19B4, 6176 }, + { 0x19BC, 6182 }, + { 0x19BB, 6188 }, + { 0x19BE, 6194 }, + { 0x19BF, 6200 }, + { 0x19B0, 6206 }, + { 0x19A5, 6213 }, + { 0x19A4, 6219 }, + { 0x199D, 6225 }, + { 0x19A3, 6231 }, + { 0x1985, 6237 }, + { 0x199F, 6243 }, + { 0x1999, 6249 }, + { 0x1993, 6255 }, + { 0x1997, 6261 }, + { 0x1981, 6267 }, + { 0x198C, 6273 }, + { 0x1991, 6279 }, + { 0x199E, 6285 }, + { 0x1986, 6291 }, + { 0x198D, 6297 }, + { 0x19A8, 6303 }, + { 0x1987, 6309 }, + { 0x1998, 6315 }, + { 0x1992, 6321 }, + { 0x198B, 6327 }, + { 0x19A9, 6333 }, + { 0x19A2, 6339 }, + { 0x19A1, 6345 }, + { 0x199A, 6351 }, + { 0x19A0, 6357 }, + { 0x1982, 6363 }, + { 0x199C, 6369 }, + { 0x1996, 6375 }, + { 0x1990, 6381 }, + { 0x1994, 6387 }, + { 0x1980, 6393 }, + { 0x1989, 6399 }, + { 0x198E, 6405 }, + { 0x199B, 6411 }, + { 0x1983, 6417 }, + { 0x198A, 6423 }, + { 0x19A6, 6429 }, + { 0x1984, 6435 }, + { 0x1995, 6441 }, + { 0x198F, 6447 }, + { 0x1988, 6453 }, + { 0x19A7, 6459 }, + { 0x19C7, 6465 }, + { 0x19C6, 6471 }, + { 0x19C5, 6477 }, + { 0x19C4, 6483 }, + { 0x19C3, 6489 }, + { 0x19C1, 6495 }, + { 0x19C2, 6501 }, + { 0x20AA, 6507 }, + { 0x07F5, 6510 }, + { 0x07F4, 6514 }, + { 0x07F8, 6518 }, + { 0x07C1, 6520 }, + { 0x07C6, 6523 }, + { 0x07C2, 6526 }, + { 0x07C5, 6529 }, + { 0x07C4, 6532 }, + { 0x07C9, 6535 }, + { 0x07C0, 6538 }, + { 0x07C8, 6541 }, + { 0x07C7, 6544 }, + { 0x07C3, 6547 }, + { 0x07CA, 6550 }, + { 0x07CD, 6553 }, + { 0x07CC, 6556 }, + { 0x07D2, 6559 }, + { 0x07D0, 6562 }, + { 0x07CE, 6565 }, + { 0x07D3, 6568 }, + { 0x07D8, 6571 }, + { 0x07CB, 6574 }, + { 0x07DD, 6577 }, + { 0x07E4, 6580 }, + { 0x07D6, 6583 }, + { 0x07DE, 6586 }, + { 0x07DF, 6589 }, + { 0x07E1, 6592 }, + { 0x07E3, 6595 }, + { 0x07E0, 6598 }, + { 0x07CF, 6602 }, + { 0x07D4, 6605 }, + { 0x07D9, 6608 }, + { 0x07DB, 6611 }, + { 0x07D5, 6614 }, + { 0x07E5, 6617 }, + { 0x07E6, 6620 }, + { 0x07D7, 6623 }, + { 0x07DC, 6626 }, + { 0x07E2, 6629 }, + { 0x07E7, 6632 }, + { 0x07DA, 6636 }, + { 0x07E8, 6639 }, + { 0x07EA, 6643 }, + { 0x07E9, 6647 }, + { 0x07D1, 6651 }, + { 0x07F6, 6654 }, + { 0x07F7, 6658 }, + { 0x07F0, 6661 }, + { 0x07EF, 6666 }, + { 0x07F1, 6671 }, + { 0x07EE, 6676 }, + { 0x07EC, 6681 }, + { 0x07EB, 6686 }, + { 0x07ED, 6691 }, + { 0x07F3, 6696 }, + { 0x07F2, 6701 }, + { 0x07FA, 6705 }, + { 0x07F9, 6707 }, + { 0x22BD, 6710 }, + { 0x2284, 6711 }, + { 0x2285, 6715 }, + { 0x2209, 6719 }, + { 0x00AC, 6723 }, + { 0x22AD, 6725 }, + { 0x237B, 6727 }, + { 0x2260, 6730 }, + { 0x2241, 6733 }, + { 0x2249, 6735 }, + { 0x22EA, 6739 }, + { 0x22EC, 6743 }, + { 0x22E2, 6750 }, + { 0x22E3, 6757 }, + { 0x2226, 6764 }, + { 0x2262, 6767 }, + { 0x226E, 6770 }, + { 0x226D, 6772 }, + { 0x226F, 6775 }, + { 0x2244, 6777 }, + { 0x2445, 6781 }, + { 0x2444, 6784 }, + { 0x2448, 6787 }, + { 0x2442, 6789 }, + { 0x2440, 6791 }, + { 0x2441, 6793 }, + { 0x2447, 6795 }, + { 0x2446, 6799 }, + { 0x244A, 6803 }, + { 0x2449, 6806 }, + { 0x2443, 6810 }, + { 0x2126, 6813 }, + { 0x7300, 6815 }, + { 0x7304, 6819 }, + { 0x7309, 6823 }, + { 0x730F, 6827 }, + { 0x7316, 6831 }, + { 0x7301, 6835 }, + { 0x7303, 6839 }, + { 0x731A, 6843 }, + { 0x730B, 6847 }, + { 0x730C, 6851 }, + { 0x730D, 6855 }, + { 0x7313, 6859 }, + { 0x7314, 6863 }, + { 0x7307, 6867 }, + { 0x731D, 6871 }, + { 0x730A, 6875 }, + { 0x7302, 6879 }, + { 0x7312, 6883 }, + { 0x7310, 6887 }, + { 0x7315, 6891 }, + { 0x731E, 6895 }, + { 0x7305, 6899 }, + { 0x7306, 6903 }, + { 0x731C, 6907 }, + { 0x7317, 6911 }, + { 0x731B, 6915 }, + { 0x730E, 6919 }, + { 0x7319, 6923 }, + { 0x7318, 6927 }, + { 0x7311, 6931 }, + { 0x7308, 6935 }, + { 0x7320, 6939 }, + { 0x7322, 6943 }, + { 0x7321, 6947 }, + { 0x7323, 6951 }, + { 0x73A0, 6955 }, + { 0x73A1, 6959 }, + { 0x73A2, 6963 }, + { 0x73B2, 6967 }, + { 0x73A8, 6971 }, + { 0x73AD, 6975 }, + { 0x73AE, 6979 }, + { 0x73AF, 6983 }, + { 0x73B3, 6987 }, + { 0x73A5, 6991 }, + { 0x73A6, 6995 }, + { 0x73C3, 6999 }, + { 0x73A9, 7003 }, + { 0x73AA, 7007 }, + { 0x73A3, 7011 }, + { 0x73A4, 7015 }, + { 0x73BE, 7019 }, + { 0x73B6, 7023 }, + { 0x73B7, 7027 }, + { 0x73B8, 7031 }, + { 0x73B4, 7035 }, + { 0x73B5, 7039 }, + { 0x73B1, 7043 }, + { 0x73BC, 7047 }, + { 0x73BD, 7051 }, + { 0x73BF, 7055 }, + { 0x73AB, 7059 }, + { 0x73AC, 7063 }, + { 0x73BA, 7067 }, + { 0x73BB, 7071 }, + { 0x73A7, 7075 }, + { 0x73B9, 7079 }, + { 0x73C0, 7083 }, + { 0x73C1, 7087 }, + { 0x73C2, 7091 }, + { 0x73B0, 7095 }, + { 0x73CE, 7099 }, + { 0x73CF, 7103 }, + { 0x73CC, 7107 }, + { 0x73C8, 7111 }, + { 0x73CD, 7115 }, + { 0x73C9, 7119 }, + { 0x73CA, 7123 }, + { 0x73CB, 7127 }, + { 0x73D0, 7131 }, + { 0x73D1, 7135 }, + { 0x73D3, 7139 }, + { 0x73D2, 7143 }, + { 0x73D4, 7147 }, + { 0x73D5, 7151 }, + { 0x2E2B, 7155 }, + { 0x2024, 7161 }, + { 0x2031, 7164 }, + { 0x214C, 7168 }, + { 0x2030, 7170 }, + { 0x202C, 7173 }, + { 0x2216, 7176 }, + { 0x2736, 7178 }, + { 0x273E, 7182 }, + { 0x2609, 7188 }, + { 0xC05F, 7189 }, + { 0xC02E, 7192 }, + { 0xC07B, 7195 }, + { 0xC05B, 7199 }, + { 0xC028, 7203 }, + { 0xC02B, 7206 }, + { 0xC03A, 7209 }, + { 0xC02C, 7211 }, + { 0xC031, 7213 }, + { 0xC036, 7216 }, + { 0xC032, 7219 }, + { 0xC035, 7222 }, + { 0xC034, 7225 }, + { 0xC039, 7228 }, + { 0xC030, 7231 }, + { 0xC038, 7234 }, + { 0xC037, 7237 }, + { 0xC033, 7240 }, + { 0xC060, 7243 }, + { 0xC061, 7246 }, + { 0xC062, 7251 }, + { 0xC063, 7256 }, + { 0xC064, 7261 }, + { 0xC065, 7266 }, + { 0xC066, 7271 }, + { 0xC067, 7276 }, + { 0xC068, 7281 }, + { 0xC069, 7286 }, + { 0xC06A, 7291 }, + { 0xC06B, 7296 }, + { 0xC06C, 7301 }, + { 0xC06D, 7306 }, + { 0xC06E, 7311 }, + { 0xC06F, 7316 }, + { 0xC070, 7321 }, + { 0xC071, 7326 }, + { 0xC072, 7331 }, + { 0xC073, 7336 }, + { 0xC074, 7341 }, + { 0xC075, 7346 }, + { 0xC076, 7351 }, + { 0xC077, 7356 }, + { 0xC078, 7361 }, + { 0xC079, 7366 }, + { 0xC07A, 7371 }, + { 0xC041, 7376 }, + { 0xC042, 7381 }, + { 0xC043, 7386 }, + { 0xC044, 7391 }, + { 0xC045, 7396 }, + { 0xC046, 7401 }, + { 0xC047, 7406 }, + { 0xC048, 7411 }, + { 0xC049, 7416 }, + { 0xC04A, 7421 }, + { 0xC04B, 7426 }, + { 0xC04C, 7431 }, + { 0xC04D, 7436 }, + { 0xC04E, 7441 }, + { 0xC04F, 7446 }, + { 0xC050, 7451 }, + { 0xC051, 7456 }, + { 0xC052, 7461 }, + { 0xC053, 7466 }, + { 0xC054, 7471 }, + { 0xC055, 7476 }, + { 0xC056, 7481 }, + { 0xC057, 7486 }, + { 0xC058, 7491 }, + { 0xC059, 7496 }, + { 0xC05A, 7501 }, + { 0xC07D, 7506 }, + { 0xC05D, 7510 }, + { 0xC029, 7514 }, + { 0xC020, 7517 }, + { 0xC07E, 7519 }, + { 0xC024, 7521 }, + { 0xC03D, 7524 }, + { 0xC023, 7527 }, + { 0xC025, 7530 }, + { 0xC05C, 7533 }, + { 0xC02F, 7536 }, + { 0xC02A, 7538 }, + { 0xC03F, 7540 }, + { 0xC07C, 7543 }, + { 0xC026, 7546 }, + { 0xC03C, 7548 }, + { 0xC022, 7551 }, + { 0xC03B, 7554 }, + { 0xC027, 7556 }, + { 0xC05E, 7558 }, + { 0xC040, 7561 }, + { 0xC021, 7564 }, + { 0xC03E, 7567 }, + { 0xC02D, 7570 }, + { 0x1963, 7572 }, + { 0x196B, 7576 }, + { 0x1964, 7580 }, + { 0x1969, 7584 }, + { 0x1967, 7588 }, + { 0x196D, 7592 }, + { 0x1965, 7596 }, + { 0x1966, 7600 }, + { 0x195C, 7604 }, + { 0x195E, 7608 }, + { 0x1950, 7612 }, + { 0x1958, 7616 }, + { 0x195B, 7620 }, + { 0x1962, 7624 }, + { 0x1968, 7628 }, + { 0x1959, 7632 }, + { 0x195F, 7636 }, + { 0x1954, 7640 }, + { 0x1956, 7644 }, + { 0x196A, 7648 }, + { 0x195D, 7652 }, + { 0x1951, 7656 }, + { 0x1955, 7660 }, + { 0x196C, 7664 }, + { 0x1960, 7668 }, + { 0x1952, 7672 }, + { 0x195A, 7676 }, + { 0x1957, 7680 }, + { 0x1953, 7684 }, + { 0x1961, 7688 }, + { 0x1970, 7692 }, + { 0x1971, 7696 }, + { 0x1972, 7700 }, + { 0x1973, 7704 }, + { 0x1974, 7708 }, + { 0x29DD, 7712 }, + { 0x293C, 7715 }, + { 0x293A, 7721 }, + { 0x293D, 7725 }, + { 0x2320, 7731 }, + { 0x230F, 7734 }, + { 0x2E22, 7737 }, + { 0x231C, 7741 }, + { 0x23DE, 7744 }, + { 0x230E, 7747 }, + { 0x2E23, 7750 }, + { 0x231D, 7754 }, + { 0x23B4, 7757 }, + { 0x23E0, 7760 }, + { 0x23DC, 7764 }, + { 0x2025, 7766 }, + { 0x205A, 7769 }, + { 0x2E2A, 7772 }, + { 0x29C9, 7778 }, + { 0x2A08, 7781 }, + { 0x2A07, 7785 }, + { 0x2051, 7789 }, + { 0x2A75, 7793 }, + { 0x2A56, 7797 }, + { 0x2A55, 7801 }, + { 0x560E, 7805 }, + { 0x560D, 7808 }, + { 0x5621, 7810 }, + { 0x5626, 7813 }, + { 0x5622, 7816 }, + { 0x5625, 7819 }, + { 0x5624, 7822 }, + { 0x5629, 7825 }, + { 0x5620, 7828 }, + { 0x5628, 7831 }, + { 0x5627, 7834 }, + { 0x5623, 7837 }, + { 0x5618, 7840 }, + { 0x5616, 7843 }, + { 0x5619, 7846 }, + { 0x5617, 7849 }, + { 0x561A, 7852 }, + { 0x561E, 7855 }, + { 0x561F, 7858 }, + { 0x561C, 7861 }, + { 0x5615, 7864 }, + { 0x561D, 7867 }, + { 0x561B, 7870 }, + { 0x5613, 7873 }, + { 0x5614, 7876 }, + { 0x560F, 7879 }, + { 0x5549, 7882 }, + { 0x55E1, 7885 }, + { 0x5524, 7888 }, + { 0x55BA, 7891 }, + { 0x5595, 7894 }, + { 0x554A, 7897 }, + { 0x5552, 7900 }, + { 0x55EA, 7903 }, + { 0x552C, 7906 }, + { 0x55C3, 7909 }, + { 0x559D, 7912 }, + { 0x5566, 7915 }, + { 0x55FF, 7918 }, + { 0x553F, 7921 }, + { 0x55D7, 7924 }, + { 0x55B0, 7927 }, + { 0x5560, 7930 }, + { 0x55F9, 7933 }, + { 0x5539, 7936 }, + { 0x55D1, 7939 }, + { 0x55AA, 7942 }, + { 0x5500, 7945 }, + { 0x55E2, 7948 }, + { 0x5558, 7951 }, + { 0x55F1, 7954 }, + { 0x5531, 7957 }, + { 0x55C9, 7960 }, + { 0x55A2, 7963 }, + { 0x556D, 7966 }, + { 0x5606, 7969 }, + { 0x5545, 7972 }, + { 0x55DD, 7975 }, + { 0x55B6, 7978 }, + { 0x554C, 7981 }, + { 0x55E4, 7984 }, + { 0x5526, 7987 }, + { 0x55BD, 7990 }, + { 0x5597, 7993 }, + { 0x5525, 7996 }, + { 0x5567, 7999 }, + { 0x5600, 8002 }, + { 0x5540, 8005 }, + { 0x55D8, 8008 }, + { 0x55B1, 8011 }, + { 0x556A, 8014 }, + { 0x5603, 8017 }, + { 0x5543, 8020 }, + { 0x55DB, 8023 }, + { 0x55B4, 8026 }, + { 0x555E, 8029 }, + { 0x55F7, 8032 }, + { 0x5537, 8035 }, + { 0x55CF, 8038 }, + { 0x55A8, 8041 }, + { 0x556E, 8044 }, + { 0x5608, 8047 }, + { 0x5546, 8050 }, + { 0x55DE, 8053 }, + { 0x55B7, 8056 }, + { 0x556F, 8059 }, + { 0x5609, 8062 }, + { 0x560B, 8065 }, + { 0x5547, 8068 }, + { 0x55DF, 8071 }, + { 0x55B8, 8074 }, + { 0x55BB, 8077 }, + { 0x5571, 8080 }, + { 0x5550, 8083 }, + { 0x55E8, 8086 }, + { 0x552A, 8089 }, + { 0x55C1, 8092 }, + { 0x559B, 8095 }, + { 0x555F, 8098 }, + { 0x55F8, 8101 }, + { 0x5538, 8104 }, + { 0x55D0, 8107 }, + { 0x55A9, 8110 }, + { 0x5562, 8113 }, + { 0x55FB, 8116 }, + { 0x553B, 8119 }, + { 0x55D3, 8122 }, + { 0x55AC, 8125 }, + { 0x555A, 8128 }, + { 0x55F3, 8131 }, + { 0x5533, 8134 }, + { 0x55CB, 8137 }, + { 0x55A4, 8140 }, + { 0x5596, 8143 }, + { 0x5559, 8146 }, + { 0x55F2, 8149 }, + { 0x5532, 8152 }, + { 0x55CA, 8155 }, + { 0x55A3, 8158 }, + { 0x554E, 8161 }, + { 0x55E6, 8164 }, + { 0x5528, 8167 }, + { 0x55BF, 8170 }, + { 0x5599, 8173 }, + { 0x5569, 8176 }, + { 0x5602, 8179 }, + { 0x5542, 8182 }, + { 0x55DA, 8185 }, + { 0x55B3, 8188 }, + { 0x5564, 8191 }, + { 0x55FD, 8194 }, + { 0x553D, 8197 }, + { 0x55D5, 8200 }, + { 0x55AE, 8203 }, + { 0x5507, 8206 }, + { 0x5551, 8209 }, + { 0x55E9, 8212 }, + { 0x552B, 8215 }, + { 0x55C2, 8218 }, + { 0x559C, 8221 }, + { 0x5578, 8224 }, + { 0x551A, 8227 }, + { 0x558B, 8230 }, + { 0x5514, 8233 }, + { 0x555C, 8236 }, + { 0x55F5, 8239 }, + { 0x5535, 8242 }, + { 0x55CD, 8245 }, + { 0x55A6, 8248 }, + { 0x5585, 8251 }, + { 0x5501, 8254 }, + { 0x550C, 8257 }, + { 0x557D, 8260 }, + { 0x5557, 8263 }, + { 0x55EF, 8266 }, + { 0x5530, 8269 }, + { 0x55C7, 8272 }, + { 0x55A1, 8275 }, + { 0x5520, 8278 }, + { 0x5607, 8281 }, + { 0x5591, 8284 }, + { 0x554D, 8287 }, + { 0x5502, 8290 }, + { 0x55E5, 8293 }, + { 0x5527, 8296 }, + { 0x55BE, 8299 }, + { 0x5573, 8302 }, + { 0x5598, 8305 }, + { 0x551B, 8308 }, + { 0x558C, 8311 }, + { 0x556B, 8314 }, + { 0x551E, 8317 }, + { 0x558F, 8320 }, + { 0x5554, 8323 }, + { 0x55EC, 8326 }, + { 0x552E, 8329 }, + { 0x55C5, 8332 }, + { 0x559F, 8335 }, + { 0x5512, 8338 }, + { 0x5583, 8341 }, + { 0x5553, 8344 }, + { 0x55EB, 8347 }, + { 0x552D, 8350 }, + { 0x55C4, 8353 }, + { 0x559E, 8356 }, + { 0x5521, 8359 }, + { 0x5592, 8362 }, + { 0x5561, 8365 }, + { 0x55FA, 8368 }, + { 0x553A, 8371 }, + { 0x55D2, 8374 }, + { 0x55AB, 8377 }, + { 0x5522, 8380 }, + { 0x5568, 8383 }, + { 0x5601, 8386 }, + { 0x5541, 8389 }, + { 0x55D9, 8392 }, + { 0x55B2, 8395 }, + { 0x5593, 8398 }, + { 0x5570, 8401 }, + { 0x560A, 8404 }, + { 0x5548, 8407 }, + { 0x55E0, 8410 }, + { 0x55B9, 8413 }, + { 0x5572, 8416 }, + { 0x5505, 8419 }, + { 0x5576, 8422 }, + { 0x5513, 8425 }, + { 0x5584, 8428 }, + { 0x5516, 8431 }, + { 0x5563, 8434 }, + { 0x55FC, 8437 }, + { 0x553C, 8440 }, + { 0x55D4, 8443 }, + { 0x55AD, 8446 }, + { 0x5587, 8449 }, + { 0x550E, 8452 }, + { 0x555B, 8455 }, + { 0x55F4, 8458 }, + { 0x5534, 8461 }, + { 0x55CC, 8464 }, + { 0x55A5, 8467 }, + { 0x557F, 8470 }, + { 0x550D, 8473 }, + { 0x557E, 8476 }, + { 0x554F, 8479 }, + { 0x5503, 8482 }, + { 0x55E7, 8485 }, + { 0x5529, 8488 }, + { 0x55C0, 8491 }, + { 0x5574, 8494 }, + { 0x559A, 8497 }, + { 0x551D, 8500 }, + { 0x558E, 8503 }, + { 0x5518, 8506 }, + { 0x5565, 8509 }, + { 0x55FE, 8512 }, + { 0x553E, 8515 }, + { 0x55D6, 8518 }, + { 0x55AF, 8521 }, + { 0x5589, 8524 }, + { 0x5506, 8527 }, + { 0x5577, 8530 }, + { 0x5510, 8533 }, + { 0x555D, 8536 }, + { 0x55F6, 8539 }, + { 0x5536, 8542 }, + { 0x55CE, 8545 }, + { 0x55A7, 8548 }, + { 0x5581, 8551 }, + { 0x550B, 8554 }, + { 0x55F0, 8557 }, + { 0x55C8, 8560 }, + { 0x557C, 8563 }, + { 0x5555, 8566 }, + { 0x5509, 8569 }, + { 0x55ED, 8572 }, + { 0x557A, 8575 }, + { 0x5508, 8578 }, + { 0x5579, 8581 }, + { 0x5556, 8584 }, + { 0x55EE, 8587 }, + { 0x552F, 8590 }, + { 0x55C6, 8593 }, + { 0x55A0, 8596 }, + { 0x5515, 8599 }, + { 0x5586, 8602 }, + { 0x554B, 8605 }, + { 0x55E3, 8608 }, + { 0x556C, 8611 }, + { 0x5604, 8614 }, + { 0x5544, 8617 }, + { 0x55DC, 8620 }, + { 0x55B5, 8623 }, + { 0x55BC, 8626 }, + { 0x551C, 8629 }, + { 0x558D, 8632 }, + { 0x5523, 8635 }, + { 0x5594, 8638 }, + { 0x5517, 8641 }, + { 0x5588, 8644 }, + { 0x550F, 8647 }, + { 0x5580, 8650 }, + { 0x5504, 8653 }, + { 0x5575, 8656 }, + { 0x5519, 8659 }, + { 0x558A, 8662 }, + { 0x5511, 8665 }, + { 0x5582, 8668 }, + { 0x550A, 8671 }, + { 0x557B, 8674 }, + { 0x562B, 8677 }, + { 0x5610, 8681 }, + { 0x5611, 8685 }, + { 0x562A, 8689 }, + { 0x5612, 8693 }, + { 0x551F, 8697 }, + { 0x5605, 8700 }, + { 0x5590, 8703 }, + { 0x560C, 8706 }, + { 0x20A9, 8709 }, + { 0x22BB, 8711 }, + { 0x00A5, 8712 }, + { 0x262F, 8714 }, + { 0x2135, 8716 }, + { 0x2625, 8718 }, + { 0x269B, 8719 }, + { 0x237E, 8721 }, + { 0x2106, 8723 }, + { 0x2105, 8725 }, + { 0x20B5, 8727 }, + { 0x00A2, 8729 }, + { 0x5A51, 8731 }, + { 0x5A56, 8734 }, + { 0x5A52, 8737 }, + { 0x5A55, 8740 }, + { 0x5A54, 8743 }, + { 0x5A59, 8746 }, + { 0x5A50, 8749 }, + { 0x5A58, 8752 }, + { 0x5A57, 8755 }, + { 0x5A53, 8758 }, + { 0x5A2A, 8761 }, + { 0x5A2F, 8765 }, + { 0x5A2D, 8769 }, + { 0x5A29, 8773 }, + { 0x5A30, 8777 }, + { 0x5A31, 8781 }, + { 0x5A2C, 8785 }, + { 0x5A2B, 8789 }, + { 0x5A2E, 8793 }, + { 0x5A32, 8797 }, + { 0x5A00, 8801 }, + { 0x5A03, 8804 }, + { 0x5A01, 8807 }, + { 0x5A05, 8810 }, + { 0x5A02, 8813 }, + { 0x5A04, 8816 }, + { 0x5A1D, 8819 }, + { 0x5A15, 8822 }, + { 0x5A08, 8825 }, + { 0x5A28, 8828 }, + { 0x5A0E, 8831 }, + { 0x5A06, 8834 }, + { 0x5A24, 8837 }, + { 0x5A20, 8840 }, + { 0x5A18, 8843 }, + { 0x5A1A, 8846 }, + { 0x5A23, 8849 }, + { 0x5A27, 8852 }, + { 0x5A13, 8855 }, + { 0x5A25, 8858 }, + { 0x5A22, 8861 }, + { 0x5A21, 8864 }, + { 0x5A1E, 8867 }, + { 0x5A0C, 8870 }, + { 0x5A19, 8873 }, + { 0x5A16, 8876 }, + { 0x5A09, 8879 }, + { 0x5A0F, 8882 }, + { 0x5A07, 8885 }, + { 0x5A1F, 8888 }, + { 0x5A0B, 8891 }, + { 0x5A11, 8894 }, + { 0x5A17, 8897 }, + { 0x5A1C, 8900 }, + { 0x5A1B, 8903 }, + { 0x5A26, 8906 }, + { 0x5A14, 8909 }, + { 0x5A0D, 8912 }, + { 0x5A0A, 8915 }, + { 0x5A12, 8918 }, + { 0x5A10, 8921 }, + { 0x5A41, 8924 }, + { 0x5A40, 8928 }, + { 0x5A4A, 8932 }, + { 0x5A46, 8936 }, + { 0x5A47, 8940 }, + { 0x5A49, 8944 }, + { 0x5A45, 8948 }, + { 0x5A48, 8952 }, + { 0x5A44, 8956 }, + { 0x5A42, 8960 }, + { 0x5A4B, 8964 }, + { 0x5A35, 8968 }, + { 0x5A34, 8972 }, + { 0x5A36, 8976 }, + { 0x5A33, 8980 }, + { 0x5A4D, 8984 }, + { 0x5A4C, 8989 }, + { 0x5A43, 8994 }, + { 0x5A5D, 8999 }, + { 0x5A5E, 9002 }, + { 0x5A5C, 9006 }, + { 0x5A5F, 9009 }, + { 0x221B, 9013 }, + { 0x2593, 9015 }, + { 0x22AE, 9017 }, + { 0x22AC, 9020 }, + { 0x2224, 9023 }, + { 0x2AEE, 9026 }, + { 0x220C, 9033 }, + { 0x22EB, 9038 }, + { 0x22ED, 9044 }, + { 0x2280, 9052 }, + { 0x22E0, 9055 }, + { 0x2281, 9060 }, + { 0x22E1, 9063 }, + { 0x20AB, 9068 }, + { 0x297F, 9070 }, + { 0x22A4, 9073 }, + { 0x2AF1, 9075 }, + { 0x22F1, 9080 }, + { 0x2304, 9084 }, + { 0x2671, 9086 }, + { 0x20AC, 9089 }, + { 0x2E2D, 9091 }, + { 0x2059, 9094 }, + { 0x205B, 9097 }, + { 0x2058, 9100 }, + { 0x2725, 9103 }, + { 0x2723, 9106 }, + { 0x2722, 9109 }, + { 0x002E, 9112 }, + { 0x2588, 9114 }, + { 0x27D7, 9116 }, + { 0x23DB, 9119 }, + { 0x2699, 9120 }, + { 0x3013, 9121 }, + { 0x200A, 9123 }, + { 0x2388, 9125 }, + { 0x26A1, 9127 }, + { 0x2A1D, 9130 }, + { 0x26B5, 9131 }, + { 0x263E, 9132 }, + { 0x27DB, 9135 }, + { 0x27DA, 9139 }, + { 0x2993, 9144 }, + { 0x2E1C, 9148 }, + { 0x258F, 9152 }, + { 0x258E, 9156 }, + { 0x294E, 9160 }, + { 0x294A, 9167 }, + { 0x294B, 9174 }, + { 0x2950, 9181 }, + { 0x297C, 9188 }, + { 0x258B, 9191 }, + { 0x25D6, 9195 }, + { 0x258C, 9199 }, + { 0x22A3, 9202 }, + { 0x3008, 9204 }, + { 0x2991, 9207 }, + { 0x2B30, 9212 }, + { 0x2B32, 9217 }, + { 0x2997, 9222 }, + { 0x3010, 9227 }, + { 0x007B, 9231 }, + { 0x23A9, 9234 }, + { 0x23A7, 9239 }, + { 0x23A8, 9244 }, + { 0x230A, 9249 }, + { 0x27D5, 9251 }, + { 0x21AD, 9254 }, + { 0x2194, 9258 }, + { 0x21FC, 9261 }, + { 0x21AE, 9268 }, + { 0x21F9, 9273 }, + { 0x2948, 9279 }, + { 0x2B0C, 9285 }, + { 0x2B04, 9289 }, + { 0x21D4, 9293 }, + { 0x21CE, 9297 }, + { 0x2904, 9303 }, + { 0x21FF, 9310 }, + { 0x2589, 9314 }, + { 0x258D, 9318 }, + { 0x258A, 9322 }, + { 0x2983, 9326 }, + { 0x300E, 9330 }, + { 0x301A, 9334 }, + { 0x3018, 9338 }, + { 0x3016, 9343 }, + { 0x2985, 9347 }, + { 0x300C, 9350 }, + { 0x2E04, 9353 }, + { 0x300A, 9357 }, + { 0x29DA, 9361 }, + { 0x201C, 9365 }, + { 0x2E28, 9369 }, + { 0x22C9, 9372 }, + { 0x2E0C, 9377 }, + { 0x2018, 9381 }, + { 0x005B, 9385 }, + { 0x298D, 9388 }, + { 0x298F, 9396 }, + { 0x2045, 9404 }, + { 0x298B, 9409 }, + { 0x23A3, 9414 }, + { 0x23A1, 9419 }, + { 0x23A2, 9424 }, + { 0x29D8, 9428 }, + { 0x2308, 9431 }, + { 0x27DC, 9433 }, + { 0x27C5, 9435 }, + { 0x2E26, 9439 }, + { 0x3014, 9443 }, + { 0x29CF, 9447 }, + { 0x2E20, 9452 }, + { 0x23B8, 9457 }, + { 0x22CB, 9461 }, + { 0x0028, 9464 }, + { 0x239D, 9466 }, + { 0x239B, 9470 }, + { 0x239C, 9474 }, + { 0x2E02, 9477 }, + { 0x2E09, 9480 }, + { 0x2028, 9483 }, + { 0x2A14, 9485 }, + { 0x2A12, 9491 }, + { 0x2A13, 9498 }, + { 0x20A4, 9505 }, + { 0x2AE6, 9507 }, + { 0x27DE, 9515 }, + { 0x27F7, 9518 }, + { 0x27FA, 9522 }, + { 0x27DD, 9527 }, + { 0x27CC, 9530 }, + { 0x27F5, 9532 }, + { 0x27FB, 9535 }, + { 0x27F8, 9540 }, + { 0x27FD, 9544 }, + { 0x2B33, 9550 }, + { 0x27F6, 9554 }, + { 0x27FC, 9557 }, + { 0x27F9, 9562 }, + { 0x27FE, 9566 }, + { 0x27FF, 9572 }, + { 0x26A5, 9576 }, + { 0x2642, 9580 }, + { 0x26A7, 9582 }, + { 0x26A6, 9590 }, + { 0x303C, 9594 }, + { 0x20A5, 9596 }, + { 0x29FF, 9598 }, + { 0x226A, 9599 }, + { 0x226B, 9601 }, + { 0x22BC, 9603 }, + { 0x2398, 9604 }, + { 0x2423, 9606 }, + { 0x272B, 9608 }, + { 0x271B, 9612 }, + { 0x2732, 9615 }, + { 0x273C, 9618 }, + { 0x27C3, 9622 }, + { 0x27C4, 9624 }, + { 0x2E19, 9626 }, + { 0x303D, 9628 }, + { 0x20B1, 9631 }, + { 0x002B, 9633 }, + { 0x2A2D, 9635 }, + { 0x2A2E, 9641 }, + { 0x2A39, 9647 }, + { 0x2A25, 9651 }, + { 0x2A28, 9656 }, + { 0x2A22, 9661 }, + { 0x2A24, 9667 }, + { 0x2A26, 9672 }, + { 0x2A27, 9677 }, + { 0x2A23, 9682 }, + { 0x2A72, 9688 }, + { 0x6DFC, 9693 }, + { 0x2256, 9695 }, + { 0x02DA, 9699 }, + { 0x2257, 9701 }, + { 0x2E30, 9704 }, + { 0x2218, 9706 }, + { 0x223F, 9708 }, + { 0x00AD, 9710 }, + { 0x2721, 9712 }, + { 0x262A, 9715 }, + { 0x225B, 9718 }, + { 0x22C6, 9720 }, + { 0x2707, 9722 }, + { 0x0E51, 9724 }, + { 0x0E56, 9727 }, + { 0x0E52, 9730 }, + { 0x0E55, 9733 }, + { 0x0E54, 9736 }, + { 0x0E59, 9739 }, + { 0x0E50, 9742 }, + { 0x0E58, 9745 }, + { 0x0E57, 9748 }, + { 0x0E53, 9751 }, + { 0x0E3F, 9754 }, + { 0x0E2D, 9758 }, + { 0x0E1A, 9762 }, + { 0x0E14, 9766 }, + { 0x0E0E, 9770 }, + { 0x0E1D, 9774 }, + { 0x0E1F, 9778 }, + { 0x0E2B, 9782 }, + { 0x0E2E, 9786 }, + { 0x0E01, 9790 }, + { 0x0E25, 9794 }, + { 0x0E2C, 9798 }, + { 0x0E26, 9802 }, + { 0x0E21, 9805 }, + { 0x0E19, 9809 }, + { 0x0E13, 9813 }, + { 0x0E1B, 9817 }, + { 0x0E23, 9821 }, + { 0x0E24, 9825 }, + { 0x0E0B, 9828 }, + { 0x0E2A, 9832 }, + { 0x0E29, 9836 }, + { 0x0E28, 9840 }, + { 0x0E15, 9844 }, + { 0x0E0F, 9848 }, + { 0x0E27, 9852 }, + { 0x0E22, 9856 }, + { 0x0E0D, 9860 }, + { 0x0E08, 9864 }, + { 0x0E0C, 9868 }, + { 0x0E0A, 9872 }, + { 0x0E09, 9876 }, + { 0x0E02, 9880 }, + { 0x0E05, 9884 }, + { 0x0E03, 9888 }, + { 0x0E04, 9892 }, + { 0x0E06, 9896 }, + { 0x0E48, 9900 }, + { 0x0E49, 9904 }, + { 0x0E4A, 9908 }, + { 0x0E4B, 9912 }, + { 0x0E31, 9916 }, + { 0x0E07, 9920 }, + { 0x0E1E, 9924 }, + { 0x0E1C, 9928 }, + { 0x0E20, 9932 }, + { 0x0E10, 9936 }, + { 0x0E18, 9940 }, + { 0x0E16, 9944 }, + { 0x0E17, 9948 }, + { 0x0E12, 9952 }, + { 0x0E11, 9956 }, + { 0x0E30, 9960 }, + { 0x0E40, 9964 }, + { 0x0E34, 9968 }, + { 0x0E42, 9972 }, + { 0x0E38, 9976 }, + { 0x0E32, 9980 }, + { 0x0E41, 9984 }, + { 0x0E43, 9988 }, + { 0x0E44, 9993 }, + { 0x0E33, 9998 }, + { 0x0E35, 10002 }, + { 0x0E36, 10006 }, + { 0x0E39, 10010 }, + { 0x0E37, 10014 }, + { 0x0E5B, 10018 }, + { 0x0E4F, 10021 }, + { 0x0E3A, 10024 }, + { 0x0E46, 10027 }, + { 0x0E4D, 10030 }, + { 0x0E4E, 10033 }, + { 0x0E47, 10036 }, + { 0x0E2F, 10039 }, + { 0x0E5A, 10042 }, + { 0x0E45, 10045 }, + { 0x0E4C, 10048 }, + { 0x2009, 10051 }, + { 0x29FE, 10053 }, + { 0x22A8, 10054 }, + { 0x238C, 10055 }, + { 0x22D8, 10057 }, + { 0x22D9, 10060 }, + { 0x301C, 10063 }, + { 0x2B3F, 10065 }, + { 0x2933, 10070 }, + { 0x6E4F, 10075 }, + { 0x3030, 10078 }, + { 0x2307, 10080 }, + { 0x6E4B, 10082 }, + { 0x2670, 10084 }, + { 0x2060, 10087 }, + { 0x200B, 10089 }, + { 0x200D, 10092 }, + { 0x6EFF, 10095 }, + { 0x200C, 10099 }, + { 0x299F, 10102 }, + { 0x00B4, 10104 }, + { 0x2220, 10106 }, + { 0x299E, 10107 }, + { 0x29A4, 10111 }, + { 0x2648, 10114 }, + { 0x2936, 10115 }, + { 0x2937, 10121 }, + { 0x2934, 10127 }, + { 0x2935, 10133 }, + { 0x2712, 10139 }, + { 0x2600, 10141 }, + { 0x2663, 10145 }, + { 0x2691, 10148 }, + { 0x2726, 10150 }, + { 0x261A, 10154 }, + { 0x26B8, 10158 }, + { 0x2605, 10161 }, + { 0x2B1D, 10163 }, + { 0x265A, 10167 }, + { 0x265F, 10170 }, + { 0x265C, 10173 }, + { 0x265B, 10176 }, + { 0x265D, 10179 }, + { 0x265E, 10182 }, + { 0x2665, 10185 }, + { 0x2B24, 10188 }, + { 0x2B1B, 10191 }, + { 0x25E3, 10194 }, + { 0x25E2, 10198 }, + { 0x261B, 10202 }, + { 0x2617, 10206 }, + { 0x2B51, 10209 }, + { 0x25AA, 10212 }, + { 0x2B29, 10215 }, + { 0x2B2A, 10218 }, + { 0x2660, 10221 }, + { 0x25E4, 10224 }, + { 0x25E5, 10228 }, + { 0x29D3, 10232 }, + { 0x272C, 10234 }, + { 0x25CF, 10238 }, + { 0x2689, 10240 }, + { 0x29ED, 10246 }, + { 0x2688, 10251 }, + { 0x25FE, 10257 }, + { 0x25FC, 10261 }, + { 0x2B25, 10264 }, + { 0x2B27, 10267 }, + { 0x25A0, 10270 }, + { 0x25C6, 10272 }, + { 0x2666, 10274 }, + { 0x29EA, 10277 }, + { 0x2756, 10282 }, + { 0x2B22, 10287 }, + { 0x29EB, 10289 }, + { 0x263B, 10291 }, + { 0x26C2, 10294 }, + { 0x26C3, 10297 }, + { 0x273F, 10300 }, + { 0x2B1F, 10302 }, + { 0x2702, 10304 }, + { 0x2B2E, 10306 }, + { 0x25AE, 10309 }, + { 0x29D7, 10312 }, + { 0x204C, 10314 }, + { 0x25AC, 10317 }, + { 0x260E, 10319 }, + { 0x267B, 10321 }, + { 0x2B2C, 10325 }, + { 0x27A1, 10328 }, + { 0x204D, 10331 }, + { 0x27A4, 10334 }, + { 0x25B4, 10337 }, + { 0x25B2, 10341 }, + { 0x25BE, 10344 }, + { 0x25BC, 10348 }, + { 0x25C2, 10351 }, + { 0x25C4, 10355 }, + { 0x25C0, 10358 }, + { 0x25B0, 10361 }, + { 0x25B8, 10363 }, + { 0x25BA, 10367 }, + { 0x2B53, 10370 }, + { 0x25B6, 10373 }, + { 0x2422, 10376 }, + { 0x02D8, 10378 }, + { 0x1752, 10379 }, + { 0x1753, 10383 }, + { 0x1740, 10387 }, + { 0x1741, 10390 }, + { 0x1742, 10393 }, + { 0x174A, 10396 }, + { 0x1747, 10399 }, + { 0x1744, 10402 }, + { 0x1751, 10405 }, + { 0x1743, 10408 }, + { 0x174E, 10411 }, + { 0x174B, 10414 }, + { 0x1748, 10417 }, + { 0x1749, 10420 }, + { 0x174D, 10423 }, + { 0x1750, 10426 }, + { 0x1746, 10429 }, + { 0x174F, 10432 }, + { 0x174C, 10435 }, + { 0x1745, 10438 }, + { 0x2038, 10441 }, + { 0x2041, 10442 }, + { 0x02C7, 10445 }, + { 0x26B3, 10446 }, + { 0x2713, 10447 }, + { 0x239A, 10449 }, + { 0x2050, 10452 }, + { 0x2601, 10454 }, + { 0x003A, 10455 }, + { 0x20A1, 10456 }, + { 0x2254, 10458 }, + { 0x2604, 10460 }, + { 0x002C, 10461 }, + { 0x2628, 10462 }, + { 0x2629, 10465 }, + { 0x23AA, 10468 }, + { 0x22CE, 10471 }, + { 0x22CF, 10474 }, + { 0x2138, 10477 }, + { 0x225C, 10479 }, + { 0x0031, 10482 }, + { 0x2488, 10484 }, + { 0x0036, 10488 }, + { 0x248D, 10490 }, + { 0x0032, 10494 }, + { 0x2489, 10496 }, + { 0x0035, 10500 }, + { 0x248C, 10502 }, + { 0x0034, 10506 }, + { 0x248B, 10508 }, + { 0x0039, 10512 }, + { 0x2490, 10514 }, + { 0x0030, 10518 }, + { 0x0038, 10520 }, + { 0x248F, 10522 }, + { 0x0037, 10526 }, + { 0x248E, 10528 }, + { 0x0033, 10532 }, + { 0x248A, 10534 }, + { 0x3003, 10538 }, + { 0x2641, 10540 }, + { 0x23DA, 10541 }, + { 0x2733, 10543 }, + { 0x2734, 10546 }, + { 0x2735, 10550 }, + { 0x2737, 10554 }, + { 0x2741, 10559 }, + { 0x274A, 10564 }, + { 0x23CF, 10568 }, + { 0x2205, 10570 }, + { 0x29B4, 10572 }, + { 0x29B3, 10578 }, + { 0x29B2, 10584 }, + { 0x29B1, 10590 }, + { 0x2386, 10594 }, + { 0x225D, 10596 }, + { 0x22DE, 10600 }, + { 0x22DF, 10604 }, + { 0x22DC, 10608 }, + { 0x22DD, 10612 }, + { 0x22D5, 10616 }, + { 0x232B, 10620 }, + { 0x2326, 10624 }, + { 0x2107, 10628 }, + { 0x262B, 10630 }, + { 0x263D, 10632 }, + { 0x2322, 10635 }, + { 0x2137, 10636 }, + { 0x0060, 10638 }, + { 0x03D6, 10640 }, + { 0x0387, 10643 }, + { 0x03D7, 10646 }, + { 0x7175, 10649 }, + { 0x7176, 10653 }, + { 0x03D5, 10659 }, + { 0x03FC, 10662 }, + { 0x03F1, 10667 }, + { 0x717D, 10670 }, + { 0x7177, 10674 }, + { 0x03D0, 10678 }, + { 0x7180, 10681 }, + { 0x717F, 10685 }, + { 0x717C, 10689 }, + { 0x1FFD, 10692 }, + { 0x7179, 10694 }, + { 0x718A, 10697 }, + { 0x1FFE, 10700 }, + { 0x1FDE, 10702 }, + { 0x1FDD, 10706 }, + { 0x1FDF, 10710 }, + { 0x03F0, 10714 }, + { 0x7183, 10717 }, + { 0x0375, 10720 }, + { 0x1FBF, 10724 }, + { 0x1FCE, 10726 }, + { 0x1FCD, 10730 }, + { 0x1FCF, 10734 }, + { 0x037C, 10738 }, + { 0x03BC, 10744 }, + { 0x03BD, 10748 }, + { 0x03C0, 10752 }, + { 0x03BE, 10756 }, + { 0x03C7, 10760 }, + { 0x03B7, 10764 }, + { 0x1F75, 10768 }, + { 0x1FC4, 10774 }, + { 0x1F21, 10782 }, + { 0x1F25, 10788 }, + { 0x1F95, 10796 }, + { 0x1F23, 10806 }, + { 0x1F93, 10814 }, + { 0x1F27, 10824 }, + { 0x1F97, 10832 }, + { 0x1F91, 10842 }, + { 0x1F20, 10850 }, + { 0x1F24, 10856 }, + { 0x1F94, 10864 }, + { 0x1F22, 10874 }, + { 0x1F92, 10882 }, + { 0x1F26, 10892 }, + { 0x1F96, 10900 }, + { 0x1F90, 10910 }, + { 0x03AE, 10918 }, + { 0x1F74, 10924 }, + { 0x1FC2, 10930 }, + { 0x1FC6, 10938 }, + { 0x1FC7, 10944 }, + { 0x1FC3, 10952 }, + { 0x03C6, 10958 }, + { 0x03C8, 10962 }, + { 0x03C1, 10966 }, + { 0x1FE5, 10970 }, + { 0x1FE4, 10976 }, + { 0x03FB, 10982 }, + { 0x03F8, 10986 }, + { 0x03C4, 10990 }, + { 0x03B2, 10994 }, + { 0x0371, 10998 }, + { 0x03B9, 11002 }, + { 0x1F77, 11006 }, + { 0x1F31, 11012 }, + { 0x1F35, 11018 }, + { 0x1F33, 11026 }, + { 0x1F37, 11034 }, + { 0x1F30, 11042 }, + { 0x1F34, 11048 }, + { 0x1F32, 11056 }, + { 0x1F36, 11064 }, + { 0x03AF, 11072 }, + { 0x1F76, 11078 }, + { 0x1FD1, 11084 }, + { 0x1FD0, 11090 }, + { 0x03CA, 11096 }, + { 0x1FD3, 11102 }, + { 0x0390, 11110 }, + { 0x1FD2, 11118 }, + { 0x1FD7, 11126 }, + { 0x1FD6, 11134 }, + { 0x03B6, 11140 }, + { 0x03B1, 11144 }, + { 0x1F71, 11148 }, + { 0x1FB4, 11154 }, + { 0x1F01, 11162 }, + { 0x1F05, 11168 }, + { 0x1F85, 11176 }, + { 0x1F03, 11186 }, + { 0x1F83, 11194 }, + { 0x1F07, 11204 }, + { 0x1F87, 11212 }, + { 0x1F81, 11222 }, + { 0x1F00, 11230 }, + { 0x1F04, 11236 }, + { 0x1F84, 11244 }, + { 0x1F02, 11254 }, + { 0x1F82, 11262 }, + { 0x1F06, 11272 }, + { 0x1F86, 11280 }, + { 0x1F80, 11290 }, + { 0x03AC, 11298 }, + { 0x1F70, 11304 }, + { 0x1FB2, 11310 }, + { 0x1FB1, 11318 }, + { 0x1FB0, 11324 }, + { 0x1FB6, 11330 }, + { 0x1FB7, 11336 }, + { 0x1FB3, 11344 }, + { 0x03B4, 11350 }, + { 0x03C2, 11354 }, + { 0x03B3, 11359 }, + { 0x03BA, 11363 }, + { 0x03DF, 11367 }, + { 0x03BB, 11371 }, + { 0x03C9, 11375 }, + { 0x1F7D, 11379 }, + { 0x1FF4, 11385 }, + { 0x1F61, 11393 }, + { 0x1F65, 11399 }, + { 0x1FA5, 11407 }, + { 0x1F63, 11417 }, + { 0x1FA3, 11425 }, + { 0x1F67, 11435 }, + { 0x1FA7, 11443 }, + { 0x1FA1, 11453 }, + { 0x1F60, 11461 }, + { 0x1F64, 11467 }, + { 0x1FA4, 11475 }, + { 0x1F62, 11485 }, + { 0x1FA2, 11493 }, + { 0x1F66, 11503 }, + { 0x1FA6, 11511 }, + { 0x1FA0, 11521 }, + { 0x03CE, 11529 }, + { 0x1F7C, 11535 }, + { 0x1FF2, 11541 }, + { 0x1FF6, 11549 }, + { 0x1FF7, 11555 }, + { 0x1FF3, 11563 }, + { 0x03E1, 11569 }, + { 0x03C3, 11573 }, + { 0x03B8, 11577 }, + { 0x03DB, 11581 }, + { 0x03D9, 11585 }, + { 0x0373, 11590 }, + { 0x03DD, 11595 }, + { 0x03B5, 11599 }, + { 0x1F73, 11603 }, + { 0x1F11, 11609 }, + { 0x1F15, 11615 }, + { 0x1F13, 11623 }, + { 0x1F10, 11631 }, + { 0x1F14, 11637 }, + { 0x1F12, 11645 }, + { 0x03AD, 11653 }, + { 0x1F72, 11659 }, + { 0x03BF, 11665 }, + { 0x1F79, 11669 }, + { 0x1F41, 11675 }, + { 0x1F45, 11681 }, + { 0x1F43, 11689 }, + { 0x1F40, 11697 }, + { 0x1F44, 11703 }, + { 0x1F42, 11711 }, + { 0x03CC, 11719 }, + { 0x1F78, 11725 }, + { 0x03C5, 11731 }, + { 0x1F7B, 11735 }, + { 0x1F51, 11741 }, + { 0x1F55, 11747 }, + { 0x1F53, 11755 }, + { 0x1F57, 11763 }, + { 0x1F50, 11771 }, + { 0x1F54, 11777 }, + { 0x1F52, 11785 }, + { 0x1F56, 11793 }, + { 0x03CD, 11801 }, + { 0x1F7A, 11807 }, + { 0x1FE1, 11813 }, + { 0x1FE0, 11819 }, + { 0x03CB, 11825 }, + { 0x1FE3, 11831 }, + { 0x03B0, 11839 }, + { 0x1FE2, 11847 }, + { 0x1FE7, 11855 }, + { 0x1FE6, 11863 }, + { 0x0377, 11869 }, + { 0x037D, 11874 }, + { 0x037B, 11881 }, + { 0x03D1, 11887 }, + { 0x717E, 11890 }, + { 0x7178, 11894 }, + { 0x0384, 11898 }, + { 0x1FEF, 11900 }, + { 0x9200, 11902 }, + { 0x9201, 11906 }, + { 0x9202, 11910 }, + { 0x9203, 11914 }, + { 0x9204, 11918 }, + { 0x9205, 11922 }, + { 0x9206, 11926 }, + { 0x9207, 11930 }, + { 0x9208, 11934 }, + { 0x9209, 11938 }, + { 0x920A, 11942 }, + { 0x920B, 11946 }, + { 0x920C, 11950 }, + { 0x920D, 11954 }, + { 0x920E, 11958 }, + { 0x920F, 11962 }, + { 0x9210, 11966 }, + { 0x9211, 11970 }, + { 0x9212, 11974 }, + { 0x9213, 11978 }, + { 0x9214, 11982 }, + { 0x9215, 11986 }, + { 0x9216, 11990 }, + { 0x9217, 11994 }, + { 0x9218, 11998 }, + { 0x9219, 12002 }, + { 0x921A, 12006 }, + { 0x921B, 12010 }, + { 0x921C, 12014 }, + { 0x7187, 12018 }, + { 0x7186, 12021 }, + { 0x7188, 12024 }, + { 0x03F3, 12027 }, + { 0x03DE, 12030 }, + { 0x03E0, 12033 }, + { 0x1D28, 12036 }, + { 0x1D2A, 12041 }, + { 0x1D29, 12046 }, + { 0x1D26, 12051 }, + { 0x1D27, 12056 }, + { 0x03DA, 12061 }, + { 0x03D8, 12064 }, + { 0x03DC, 12068 }, + { 0x03F2, 12071 }, + { 0x03F5, 12075 }, + { 0x7184, 12079 }, + { 0x717A, 12082 }, + { 0x7185, 12085 }, + { 0x03CF, 12088 }, + { 0x03F4, 12092 }, + { 0x03FE, 12096 }, + { 0x039C, 12102 }, + { 0x039D, 12106 }, + { 0x03A0, 12110 }, + { 0x039E, 12114 }, + { 0x03A7, 12118 }, + { 0x0397, 12122 }, + { 0x1FCB, 12126 }, + { 0x1F29, 12132 }, + { 0x1F2D, 12138 }, + { 0x1F9D, 12146 }, + { 0x1F2B, 12156 }, + { 0x1F9B, 12164 }, + { 0x1F2F, 12174 }, + { 0x1F9F, 12182 }, + { 0x1F99, 12192 }, + { 0x1F28, 12200 }, + { 0x1F2C, 12206 }, + { 0x1F9C, 12214 }, + { 0x1F2A, 12224 }, + { 0x1F9A, 12232 }, + { 0x1F2E, 12242 }, + { 0x1F9E, 12250 }, + { 0x1F98, 12260 }, + { 0x0389, 12268 }, + { 0x1FCA, 12274 }, + { 0x1FCC, 12280 }, + { 0x03A6, 12286 }, + { 0x03A8, 12290 }, + { 0x03A1, 12294 }, + { 0x1FEC, 12298 }, + { 0x03FA, 12304 }, + { 0x03F7, 12308 }, + { 0x03A4, 12312 }, + { 0x0392, 12316 }, + { 0x0370, 12320 }, + { 0x0399, 12324 }, + { 0x1FDB, 12328 }, + { 0x1F39, 12334 }, + { 0x1F3D, 12340 }, + { 0x1F3B, 12348 }, + { 0x1F3F, 12356 }, + { 0x1F38, 12364 }, + { 0x1F3C, 12370 }, + { 0x1F3A, 12378 }, + { 0x1F3E, 12386 }, + { 0x038A, 12394 }, + { 0x1FDA, 12400 }, + { 0x1FD9, 12406 }, + { 0x1FD8, 12412 }, + { 0x03AA, 12418 }, + { 0x0396, 12424 }, + { 0x0391, 12428 }, + { 0x1FBB, 12432 }, + { 0x1F09, 12438 }, + { 0x1F0D, 12444 }, + { 0x1F8D, 12452 }, + { 0x1F0B, 12462 }, + { 0x1F8B, 12470 }, + { 0x1F0F, 12480 }, + { 0x1F8F, 12488 }, + { 0x1F89, 12498 }, + { 0x1F08, 12506 }, + { 0x1F0C, 12512 }, + { 0x1F8C, 12520 }, + { 0x1F0A, 12530 }, + { 0x1F8A, 12538 }, + { 0x1F0E, 12548 }, + { 0x1F8E, 12556 }, + { 0x1F88, 12566 }, + { 0x0386, 12574 }, + { 0x1FBA, 12580 }, + { 0x1FB9, 12586 }, + { 0x1FB8, 12592 }, + { 0x1FBC, 12598 }, + { 0x0394, 12604 }, + { 0x0393, 12608 }, + { 0x039A, 12612 }, + { 0x039B, 12616 }, + { 0x03A9, 12620 }, + { 0x1FFB, 12624 }, + { 0x1F69, 12630 }, + { 0x1F6D, 12636 }, + { 0x1FAD, 12644 }, + { 0x1F6B, 12654 }, + { 0x1FAB, 12662 }, + { 0x1F6F, 12672 }, + { 0x1FAF, 12680 }, + { 0x1FA9, 12690 }, + { 0x1F68, 12698 }, + { 0x1F6C, 12704 }, + { 0x1FAC, 12712 }, + { 0x1F6A, 12722 }, + { 0x1FAA, 12730 }, + { 0x1F6E, 12740 }, + { 0x1FAE, 12748 }, + { 0x1FA8, 12758 }, + { 0x038F, 12766 }, + { 0x1FFA, 12772 }, + { 0x1FFC, 12778 }, + { 0x03A3, 12784 }, + { 0x0398, 12788 }, + { 0x0372, 12792 }, + { 0x0395, 12797 }, + { 0x1FC9, 12801 }, + { 0x1F19, 12807 }, + { 0x1F1D, 12813 }, + { 0x1F1B, 12821 }, + { 0x1F18, 12829 }, + { 0x1F1C, 12835 }, + { 0x1F1A, 12843 }, + { 0x0388, 12851 }, + { 0x1FC8, 12857 }, + { 0x039F, 12863 }, + { 0x1FF9, 12867 }, + { 0x1F49, 12873 }, + { 0x1F4D, 12879 }, + { 0x1F4B, 12887 }, + { 0x1F48, 12895 }, + { 0x1F4C, 12901 }, + { 0x1F4A, 12909 }, + { 0x038C, 12917 }, + { 0x1FF8, 12923 }, + { 0x03A5, 12929 }, + { 0x1FEB, 12933 }, + { 0x1F59, 12939 }, + { 0x1F5D, 12945 }, + { 0x1F5B, 12953 }, + { 0x1F5F, 12961 }, + { 0x038E, 12969 }, + { 0x1FEA, 12975 }, + { 0x1FE9, 12981 }, + { 0x1FE8, 12987 }, + { 0x03AB, 12993 }, + { 0x0376, 12999 }, + { 0x03F9, 13004 }, + { 0x03FF, 13009 }, + { 0x03FD, 13016 }, + { 0x717B, 13022 }, + { 0x1FBD, 13025 }, + { 0x7182, 13027 }, + { 0x9245, 13031 }, + { 0x0374, 13034 }, + { 0x03D2, 13037 }, + { 0x03D3, 13042 }, + { 0x03D4, 13049 }, + { 0x7181, 13056 }, + { 0x037E, 13059 }, + { 0x03F6, 13062 }, + { 0x7189, 13067 }, + { 0x1FEE, 13071 }, + { 0x1FED, 13075 }, + { 0x1FC1, 13079 }, + { 0x0385, 13083 }, + { 0x1D6A, 13086 }, + { 0x1D69, 13091 }, + { 0x1D68, 13096 }, + { 0x1D66, 13101 }, + { 0x1D67, 13106 }, + { 0x7141, 13111 }, + { 0x7142, 13116 }, + { 0x7152, 13121 }, + { 0x714B, 13127 }, + { 0x7140, 13133 }, + { 0x7154, 13138 }, + { 0x714D, 13144 }, + { 0x7157, 13150 }, + { 0x7150, 13155 }, + { 0x7149, 13160 }, + { 0x7155, 13165 }, + { 0x7143, 13171 }, + { 0x7145, 13175 }, + { 0x7153, 13180 }, + { 0x714C, 13186 }, + { 0x714F, 13192 }, + { 0x7148, 13197 }, + { 0x7146, 13202 }, + { 0x714E, 13207 }, + { 0x7144, 13213 }, + { 0x7151, 13217 }, + { 0x714A, 13222 }, + { 0x7147, 13227 }, + { 0x7156, 13232 }, + { 0x7170, 13238 }, + { 0x7173, 13243 }, + { 0x7158, 13248 }, + { 0x715D, 13253 }, + { 0x7174, 13258 }, + { 0x7159, 13263 }, + { 0x716A, 13267 }, + { 0x7171, 13272 }, + { 0x7164, 13277 }, + { 0x715C, 13281 }, + { 0x716E, 13285 }, + { 0x7172, 13290 }, + { 0x7169, 13295 }, + { 0x716B, 13299 }, + { 0x7165, 13304 }, + { 0x716F, 13308 }, + { 0x7163, 13313 }, + { 0x715B, 13317 }, + { 0x715E, 13321 }, + { 0x716C, 13326 }, + { 0x715A, 13331 }, + { 0x7162, 13335 }, + { 0x7168, 13339 }, + { 0x7160, 13343 }, + { 0x7161, 13347 }, + { 0x715F, 13353 }, + { 0x716D, 13357 }, + { 0x7166, 13362 }, + { 0x7167, 13366 }, + { 0x1FC0, 13372 }, + { 0x921D, 13374 }, + { 0x921E, 13378 }, + { 0x921F, 13382 }, + { 0x9220, 13386 }, + { 0x9221, 13390 }, + { 0x9222, 13394 }, + { 0x9223, 13398 }, + { 0x9224, 13402 }, + { 0x9225, 13406 }, + { 0x9226, 13410 }, + { 0x9227, 13414 }, + { 0x9228, 13418 }, + { 0x9229, 13422 }, + { 0x922A, 13426 }, + { 0x922B, 13430 }, + { 0x922C, 13434 }, + { 0x922D, 13438 }, + { 0x922E, 13442 }, + { 0x922F, 13446 }, + { 0x9230, 13450 }, + { 0x9231, 13454 }, + { 0x9232, 13458 }, + { 0x9233, 13462 }, + { 0x9234, 13466 }, + { 0x9235, 13470 }, + { 0x9236, 13474 }, + { 0x9237, 13478 }, + { 0x9238, 13482 }, + { 0x9239, 13486 }, + { 0x923A, 13490 }, + { 0x923B, 13494 }, + { 0x923C, 13498 }, + { 0x923D, 13502 }, + { 0x923E, 13506 }, + { 0x923F, 13510 }, + { 0x9240, 13514 }, + { 0x9241, 13518 }, + { 0x037A, 13522 }, + { 0x1FBE, 13524 }, + { 0x2724, 13526 }, + { 0x271C, 13530 }, + { 0x2764, 13534 }, + { 0x27A6, 13537 }, + { 0x27A5, 13544 }, + { 0x2714, 13551 }, + { 0x2738, 13554 }, + { 0x274B, 13560 }, + { 0x271A, 13565 }, + { 0x2763, 13568 }, + { 0x27AD, 13573 }, + { 0x279A, 13579 }, + { 0x2798, 13583 }, + { 0x27AE, 13587 }, + { 0x2718, 13593 }, + { 0x27A0, 13596 }, + { 0x275E, 13601 }, + { 0x275D, 13607 }, + { 0x275C, 13614 }, + { 0x275B, 13620 }, + { 0x2746, 13627 }, + { 0x2748, 13630 }, + { 0x2731, 13632 }, + { 0x272E, 13634 }, + { 0x275A, 13638 }, + { 0x2799, 13641 }, + { 0x2762, 13644 }, + { 0x2794, 13648 }, + { 0x279C, 13652 }, + { 0x27BD, 13656 }, + { 0x2770, 13660 }, + { 0x276E, 13665 }, + { 0x2716, 13671 }, + { 0x2771, 13674 }, + { 0x276F, 13679 }, + { 0x27B9, 13685 }, + { 0x27B7, 13690 }, + { 0x27B8, 13695 }, + { 0x27A8, 13699 }, + { 0x273D, 13704 }, + { 0x2743, 13707 }, + { 0x279E, 13711 }, + { 0x27BB, 13715 }, + { 0x2302, 13719 }, + { 0x22B7, 13720 }, + { 0x2253, 13722 }, + { 0x592E, 13728 }, + { 0x592F, 13732 }, + { 0x592C, 13736 }, + { 0x592D, 13740 }, + { 0x592B, 13745 }, + { 0x5901, 13749 }, + { 0x5906, 13753 }, + { 0x5902, 13757 }, + { 0x5905, 13761 }, + { 0x5904, 13765 }, + { 0x5909, 13769 }, + { 0x5900, 13773 }, + { 0x5908, 13777 }, + { 0x5907, 13781 }, + { 0x5903, 13785 }, + { 0x5927, 13789 }, + { 0x592A, 13793 }, + { 0x5928, 13797 }, + { 0x5929, 13801 }, + { 0x5926, 13805 }, + { 0x5922, 13809 }, + { 0x5924, 13813 }, + { 0x5919, 13817 }, + { 0x5921, 13821 }, + { 0x5918, 13825 }, + { 0x590C, 13829 }, + { 0x591F, 13833 }, + { 0x590A, 13837 }, + { 0x591C, 13841 }, + { 0x5917, 13845 }, + { 0x5914, 13849 }, + { 0x5923, 13853 }, + { 0x5925, 13857 }, + { 0x5915, 13861 }, + { 0x591A, 13865 }, + { 0x590E, 13869 }, + { 0x5912, 13873 }, + { 0x5920, 13877 }, + { 0x591D, 13881 }, + { 0x591B, 13885 }, + { 0x5910, 13889 }, + { 0x5913, 13893 }, + { 0x590B, 13897 }, + { 0x590D, 13901 }, + { 0x5911, 13905 }, + { 0x5916, 13909 }, + { 0x590F, 13913 }, + { 0x591E, 13917 }, + { 0x17D7, 13921 }, + { 0x17D4, 13925 }, + { 0x17CF, 13928 }, + { 0x17D2, 13931 }, + { 0x17CC, 13934 }, + { 0x17CB, 13937 }, + { 0x17D8, 13940 }, + { 0x17D6, 13943 }, + { 0x17D9, 13948 }, + { 0x17D0, 13952 }, + { 0x17D1, 13956 }, + { 0x17CE, 13959 }, + { 0x17DA, 13962 }, + { 0x17C6, 13965 }, + { 0x17C7, 13968 }, + { 0x17CA, 13971 }, + { 0x17DD, 13974 }, + { 0x17D5, 13977 }, + { 0x17D3, 13980 }, + { 0x17C9, 13983 }, + { 0x17CD, 13986 }, + { 0x17DC, 13989 }, + { 0x17C8, 13992 }, + { 0x17E1, 13995 }, + { 0x17E6, 13998 }, + { 0x17E2, 14001 }, + { 0x17E5, 14004 }, + { 0x17E4, 14007 }, + { 0x17E9, 14010 }, + { 0x17E0, 14013 }, + { 0x17E8, 14016 }, + { 0x17E7, 14019 }, + { 0x17E3, 14022 }, + { 0x17C1, 14025 }, + { 0x17B7, 14029 }, + { 0x17BB, 14033 }, + { 0x17B9, 14037 }, + { 0x17B6, 14041 }, + { 0x17C2, 14045 }, + { 0x17C3, 14049 }, + { 0x17C5, 14053 }, + { 0x17C0, 14057 }, + { 0x17B8, 14061 }, + { 0x17BE, 14065 }, + { 0x17C4, 14069 }, + { 0x17BD, 14073 }, + { 0x17BC, 14077 }, + { 0x17BF, 14081 }, + { 0x17BA, 14085 }, + { 0x17B5, 14089 }, + { 0x17B4, 14093 }, + { 0x1794, 14097 }, + { 0x1785, 14100 }, + { 0x1787, 14103 }, + { 0x178A, 14106 }, + { 0x178C, 14109 }, + { 0x17A0, 14112 }, + { 0x1780, 14115 }, + { 0x1782, 14118 }, + { 0x17A1, 14121 }, + { 0x179B, 14124 }, + { 0x1798, 14127 }, + { 0x1793, 14130 }, + { 0x1796, 14133 }, + { 0x17A2, 14136 }, + { 0x179A, 14139 }, + { 0x179F, 14142 }, + { 0x178F, 14145 }, + { 0x1791, 14148 }, + { 0x179C, 14151 }, + { 0x1799, 14154 }, + { 0x1786, 14157 }, + { 0x1788, 14160 }, + { 0x1781, 14163 }, + { 0x1783, 14166 }, + { 0x1784, 14169 }, + { 0x178E, 14172 }, + { 0x1789, 14175 }, + { 0x1795, 14178 }, + { 0x1797, 14181 }, + { 0x179D, 14184 }, + { 0x179E, 14187 }, + { 0x1790, 14190 }, + { 0x1792, 14193 }, + { 0x178B, 14196 }, + { 0x178D, 14199 }, + { 0x19F3, 14202 }, + { 0x19E3, 14206 }, + { 0x19FA, 14210 }, + { 0x19EA, 14214 }, + { 0x17F3, 14218 }, + { 0x17F2, 14223 }, + { 0x17F0, 14228 }, + { 0x17F4, 14233 }, + { 0x17F1, 14238 }, + { 0x17F5, 14243 }, + { 0x17F8, 14248 }, + { 0x17F7, 14253 }, + { 0x17F9, 14258 }, + { 0x17F6, 14263 }, + { 0x19F2, 14268 }, + { 0x19E2, 14272 }, + { 0x19F4, 14276 }, + { 0x19E4, 14280 }, + { 0x19F1, 14284 }, + { 0x19E1, 14288 }, + { 0x19F5, 14292 }, + { 0x19E5, 14296 }, + { 0x19FD, 14300 }, + { 0x19ED, 14304 }, + { 0x19FC, 14308 }, + { 0x19EC, 14312 }, + { 0x19FE, 14316 }, + { 0x19EE, 14320 }, + { 0x19FB, 14324 }, + { 0x19EB, 14328 }, + { 0x19FF, 14332 }, + { 0x19EF, 14336 }, + { 0x19F8, 14340 }, + { 0x19E8, 14344 }, + { 0x19F7, 14348 }, + { 0x19E7, 14352 }, + { 0x19F9, 14356 }, + { 0x19E9, 14360 }, + { 0x19F6, 14364 }, + { 0x19E6, 14368 }, + { 0x19F0, 14372 }, + { 0x19E0, 14375 }, + { 0x17DB, 14378 }, + { 0x17AD, 14382 }, + { 0x17AF, 14386 }, + { 0x17A5, 14390 }, + { 0x17A7, 14394 }, + { 0x17AB, 14398 }, + { 0x17AE, 14402 }, + { 0x17A4, 14406 }, + { 0x17B0, 14410 }, + { 0x17A3, 14414 }, + { 0x17B3, 14418 }, + { 0x17A6, 14422 }, + { 0x17B1, 14426 }, + { 0x17B2, 14432 }, + { 0x17A8, 14438 }, + { 0x17A9, 14442 }, + { 0x17AC, 14446 }, + { 0x17AA, 14450 }, + { 0x27D8, 14454 }, + { 0x27D9, 14457 }, + { 0x2A1E, 14460 }, + { 0x25EF, 14464 }, + { 0x2AFC, 14466 }, + { 0x271D, 14471 }, + { 0x0061, 14473 }, + { 0x0227, 14477 }, + { 0x01E1, 14484 }, + { 0x1EA1, 14493 }, + { 0x1EA3, 14500 }, + { 0x00E5, 14507 }, + { 0x01FB, 14514 }, + { 0x1E01, 14523 }, + { 0x00E1, 14530 }, + { 0x0103, 14536 }, + { 0x1EB7, 14542 }, + { 0x1EB3, 14551 }, + { 0x1EAF, 14560 }, + { 0x1EB1, 14568 }, + { 0x1EB5, 14576 }, + { 0x01CE, 14584 }, + { 0x00E0, 14590 }, + { 0x1E9A, 14596 }, + { 0x00E3, 14604 }, + { 0x0201, 14610 }, + { 0x0101, 14617 }, + { 0x0105, 14623 }, + { 0x2C65, 14629 }, + { 0x0203, 14635 }, + { 0x00E4, 14642 }, + { 0x01DF, 14648 }, + { 0x1D8F, 14656 }, + { 0x00E2, 14663 }, + { 0x1EAD, 14669 }, + { 0x1EA9, 14678 }, + { 0x1EA5, 14687 }, + { 0x1EA7, 14695 }, + { 0x1EAB, 14703 }, + { 0x0062, 14711 }, + { 0x1E03, 14715 }, + { 0x1E05, 14722 }, + { 0x0253, 14729 }, + { 0x1E07, 14735 }, + { 0x1D6C, 14742 }, + { 0x0180, 14749 }, + { 0x0183, 14755 }, + { 0x1D80, 14761 }, + { 0x0063, 14768 }, + { 0x010B, 14772 }, + { 0x0255, 14779 }, + { 0x0188, 14785 }, + { 0x0107, 14791 }, + { 0x010D, 14797 }, + { 0x023C, 14803 }, + { 0x00E7, 14809 }, + { 0x1E09, 14815 }, + { 0x0109, 14823 }, + { 0x0064, 14829 }, + { 0x1E0B, 14833 }, + { 0x1E0D, 14840 }, + { 0x0221, 14847 }, + { 0x0257, 14853 }, + { 0x1D91, 14859 }, + { 0x1E0F, 14867 }, + { 0x0256, 14874 }, + { 0x010F, 14880 }, + { 0x1D6D, 14886 }, + { 0x0111, 14893 }, + { 0x018C, 14899 }, + { 0x1E11, 14905 }, + { 0x1D81, 14911 }, + { 0x1E13, 14918 }, + { 0x0065, 14925 }, + { 0x0117, 14929 }, + { 0x1EB9, 14936 }, + { 0x1EBB, 14943 }, + { 0x00E9, 14950 }, + { 0x0115, 14956 }, + { 0x011B, 14962 }, + { 0x00E8, 14968 }, + { 0x2C78, 14974 }, + { 0x1EBD, 14980 }, + { 0x1E1B, 14986 }, + { 0x0205, 14993 }, + { 0x0113, 15000 }, + { 0x1E17, 15006 }, + { 0x1E15, 15014 }, + { 0x0119, 15022 }, + { 0x0247, 15028 }, + { 0x0229, 15034 }, + { 0x1E1D, 15040 }, + { 0x0207, 15048 }, + { 0x00EB, 15055 }, + { 0x1D92, 15061 }, + { 0x00EA, 15068 }, + { 0x1EC7, 15074 }, + { 0x1EC3, 15083 }, + { 0x1EBF, 15092 }, + { 0x1EC1, 15100 }, + { 0x1EC5, 15108 }, + { 0x1E19, 15116 }, + { 0x0066, 15123 }, + { 0x1E1F, 15127 }, + { 0x0192, 15134 }, + { 0x1D6E, 15140 }, + { 0x1D82, 15147 }, + { 0x0067, 15154 }, + { 0x0121, 15158 }, + { 0x0260, 15165 }, + { 0x01F5, 15171 }, + { 0x011F, 15177 }, + { 0x01E7, 15183 }, + { 0x1E21, 15189 }, + { 0x01E5, 15195 }, + { 0x0123, 15201 }, + { 0x1D83, 15207 }, + { 0x011D, 15214 }, + { 0x0068, 15220 }, + { 0x1E23, 15224 }, + { 0x1E25, 15231 }, + { 0x0266, 15238 }, + { 0x1E96, 15244 }, + { 0x1E2B, 15251 }, + { 0x021F, 15258 }, + { 0x0127, 15264 }, + { 0x1E29, 15270 }, + { 0x2C68, 15276 }, + { 0x1E27, 15282 }, + { 0x0125, 15288 }, + { 0x0069, 15294 }, + { 0x1ECB, 15298 }, + { 0x1EC9, 15305 }, + { 0x00ED, 15312 }, + { 0x012D, 15318 }, + { 0x01D0, 15324 }, + { 0x00EC, 15330 }, + { 0x0129, 15336 }, + { 0x1E2D, 15342 }, + { 0x0209, 15349 }, + { 0x012B, 15356 }, + { 0x012F, 15362 }, + { 0x0268, 15368 }, + { 0x020B, 15374 }, + { 0x00EF, 15381 }, + { 0x1E2F, 15387 }, + { 0x1D96, 15395 }, + { 0x00EE, 15402 }, + { 0x006A, 15408 }, + { 0x01F0, 15412 }, + { 0x0249, 15418 }, + { 0x0135, 15424 }, + { 0x029D, 15430 }, + { 0x006B, 15436 }, + { 0x1E33, 15440 }, + { 0x0199, 15447 }, + { 0x1E35, 15453 }, + { 0x1E31, 15460 }, + { 0x01E9, 15466 }, + { 0x5741, 15472 }, + { 0x5745, 15478 }, + { 0x0137, 15487 }, + { 0x1D84, 15493 }, + { 0x5743, 15500 }, + { 0x2C6A, 15507 }, + { 0x006C, 15513 }, + { 0x019A, 15517 }, + { 0x1E37, 15523 }, + { 0x1E39, 15530 }, + { 0x026C, 15539 }, + { 0x0234, 15545 }, + { 0x5749, 15551 }, + { 0x1E3B, 15558 }, + { 0x013A, 15565 }, + { 0x013E, 15571 }, + { 0x2C61, 15577 }, + { 0x0140, 15584 }, + { 0x026B, 15591 }, + { 0x0142, 15598 }, + { 0x013C, 15604 }, + { 0x1D85, 15610 }, + { 0x026D, 15617 }, + { 0x1E3D, 15624 }, + { 0x006D, 15631 }, + { 0x1E41, 15635 }, + { 0x1E43, 15642 }, + { 0x0271, 15649 }, + { 0x1E3F, 15655 }, + { 0x1D6F, 15661 }, + { 0x1D86, 15668 }, + { 0x006E, 15675 }, + { 0x1E45, 15679 }, + { 0x1E47, 15686 }, + { 0x0235, 15693 }, + { 0x0272, 15699 }, + { 0x1E49, 15706 }, + { 0x019E, 15713 }, + { 0x0144, 15721 }, + { 0x0148, 15727 }, + { 0x01F9, 15733 }, + { 0x00F1, 15739 }, + { 0x1D70, 15745 }, + { 0x0146, 15752 }, + { 0x1D87, 15758 }, + { 0x0273, 15765 }, + { 0x1E4B, 15772 }, + { 0x0149, 15779 }, + { 0x006F, 15786 }, + { 0x022F, 15790 }, + { 0x0231, 15797 }, + { 0x1ECD, 15806 }, + { 0x2C7A, 15813 }, + { 0x1ECF, 15821 }, + { 0x01A1, 15828 }, + { 0x1EE3, 15834 }, + { 0x1EDF, 15843 }, + { 0x1EDB, 15852 }, + { 0x1EDD, 15860 }, + { 0x1EE1, 15868 }, + { 0x574B, 15876 }, + { 0x574D, 15884 }, + { 0x00F3, 15890 }, + { 0x014F, 15896 }, + { 0x01D2, 15902 }, + { 0x00F2, 15908 }, + { 0x00F5, 15914 }, + { 0x1E4D, 15920 }, + { 0x022D, 15928 }, + { 0x1E4F, 15936 }, + { 0x0151, 15944 }, + { 0x020D, 15951 }, + { 0x014D, 15958 }, + { 0x1E53, 15964 }, + { 0x1E51, 15972 }, + { 0x01EB, 15980 }, + { 0x01ED, 15986 }, + { 0x00F8, 15994 }, + { 0x01FF, 16000 }, + { 0x020F, 16008 }, + { 0x00F6, 16015 }, + { 0x022B, 16021 }, + { 0x00F4, 16029 }, + { 0x1ED9, 16035 }, + { 0x1ED5, 16044 }, + { 0x1ED1, 16053 }, + { 0x1ED3, 16061 }, + { 0x1ED7, 16069 }, + { 0x0070, 16077 }, + { 0x1E57, 16081 }, + { 0x01A5, 16088 }, + { 0x1E55, 16094 }, + { 0x1D71, 16100 }, + { 0x1D7D, 16107 }, + { 0x5751, 16113 }, + { 0x1D88, 16121 }, + { 0x5753, 16128 }, + { 0x5755, 16134 }, + { 0x0071, 16141 }, + { 0x02A0, 16145 }, + { 0x024B, 16151 }, + { 0x5757, 16158 }, + { 0x5759, 16166 }, + { 0x0072, 16173 }, + { 0x1E59, 16177 }, + { 0x1E5B, 16184 }, + { 0x1E5D, 16191 }, + { 0x1E5F, 16200 }, + { 0x027C, 16207 }, + { 0x027D, 16214 }, + { 0x0155, 16220 }, + { 0x0159, 16226 }, + { 0x0211, 16232 }, + { 0x1D72, 16239 }, + { 0x024D, 16246 }, + { 0x0157, 16252 }, + { 0x1D89, 16258 }, + { 0x027E, 16265 }, + { 0x1D73, 16271 }, + { 0x0213, 16280 }, + { 0x575B, 16287 }, + { 0x0073, 16292 }, + { 0x1E61, 16296 }, + { 0x1E63, 16303 }, + { 0x1E69, 16310 }, + { 0x0282, 16320 }, + { 0x015B, 16326 }, + { 0x1E65, 16332 }, + { 0x0161, 16341 }, + { 0x1E67, 16347 }, + { 0x0219, 16356 }, + { 0x023F, 16363 }, + { 0x1D74, 16370 }, + { 0x015F, 16377 }, + { 0x1D8A, 16383 }, + { 0x015D, 16390 }, + { 0x0074, 16396 }, + { 0x1E6B, 16400 }, + { 0x1E6D, 16407 }, + { 0x0236, 16414 }, + { 0x01AD, 16420 }, + { 0x1E6F, 16426 }, + { 0x0165, 16433 }, + { 0x021B, 16439 }, + { 0x1D75, 16446 }, + { 0x0167, 16453 }, + { 0x0163, 16459 }, + { 0x01AB, 16465 }, + { 0x2C66, 16472 }, + { 0x1E97, 16479 }, + { 0x0288, 16485 }, + { 0x1E71, 16492 }, + { 0x0075, 16499 }, + { 0x0289, 16503 }, + { 0x1EE5, 16508 }, + { 0x1EE7, 16515 }, + { 0x01B0, 16522 }, + { 0x1EF1, 16528 }, + { 0x1EED, 16537 }, + { 0x1EE9, 16546 }, + { 0x1EEB, 16554 }, + { 0x1EEF, 16562 }, + { 0x016F, 16570 }, + { 0x00FA, 16577 }, + { 0x016D, 16583 }, + { 0x01D4, 16589 }, + { 0x00F9, 16595 }, + { 0x0169, 16601 }, + { 0x1E79, 16607 }, + { 0x1E75, 16615 }, + { 0x0171, 16622 }, + { 0x0215, 16629 }, + { 0x016B, 16636 }, + { 0x1E7B, 16642 }, + { 0x0173, 16650 }, + { 0x0217, 16656 }, + { 0x00FC, 16663 }, + { 0x01D8, 16669 }, + { 0x01DA, 16677 }, + { 0x01DC, 16685 }, + { 0x01D6, 16693 }, + { 0x1E73, 16701 }, + { 0x1D99, 16708 }, + { 0x00FB, 16715 }, + { 0x1E77, 16721 }, + { 0x0076, 16728 }, + { 0x1E7F, 16732 }, + { 0x2C74, 16739 }, + { 0x028B, 16745 }, + { 0x2C71, 16751 }, + { 0x1E7D, 16758 }, + { 0x1D8C, 16764 }, + { 0x575F, 16771 }, + { 0x0077, 16778 }, + { 0x1E87, 16782 }, + { 0x1E89, 16789 }, + { 0x2C73, 16796 }, + { 0x1E98, 16802 }, + { 0x1E83, 16809 }, + { 0x1E81, 16815 }, + { 0x1E85, 16821 }, + { 0x0175, 16827 }, + { 0x0078, 16833 }, + { 0x1E8B, 16837 }, + { 0x1D8D, 16844 }, + { 0x1E8D, 16851 }, + { 0x0079, 16857 }, + { 0x1E8F, 16861 }, + { 0x1EF5, 16868 }, + { 0x01B4, 16875 }, + { 0x1EF7, 16881 }, + { 0x1EFF, 16888 }, + { 0x1E99, 16894 }, + { 0x00FD, 16901 }, + { 0x1EF3, 16907 }, + { 0x1EF9, 16913 }, + { 0x0233, 16919 }, + { 0x024F, 16925 }, + { 0x00FF, 16931 }, + { 0x0177, 16937 }, + { 0x007A, 16943 }, + { 0x017C, 16947 }, + { 0x1E93, 16954 }, + { 0x0291, 16961 }, + { 0x0225, 16967 }, + { 0x1E95, 16973 }, + { 0x017A, 16980 }, + { 0x017E, 16986 }, + { 0x0240, 16992 }, + { 0x1D76, 16999 }, + { 0x01B6, 17006 }, + { 0x1D8E, 17012 }, + { 0x2C6C, 17019 }, + { 0x0290, 17025 }, + { 0x1E91, 17032 }, + { 0x5733, 17038 }, + { 0x00E6, 17042 }, + { 0x01FD, 17046 }, + { 0x01E3, 17052 }, + { 0x5735, 17058 }, + { 0x5737, 17062 }, + { 0x5739, 17066 }, + { 0x573B, 17070 }, + { 0x573D, 17077 }, + { 0x0238, 17081 }, + { 0x01F3, 17086 }, + { 0x01C6, 17090 }, + { 0x02A3, 17096 }, + { 0x02A5, 17101 }, + { 0x576B, 17108 }, + { 0x0195, 17112 }, + { 0x576D, 17116 }, + { 0x01C9, 17120 }, + { 0x02AA, 17124 }, + { 0x02AB, 17129 }, + { 0x01CC, 17134 }, + { 0x01A3, 17138 }, + { 0x574F, 17142 }, + { 0x0223, 17146 }, + { 0x0239, 17150 }, + { 0x02A8, 17155 }, + { 0x1D7A, 17162 }, + { 0x02A6, 17168 }, + { 0x5729, 17173 }, + { 0x1D6B, 17177 }, + { 0x5778, 17181 }, + { 0x5761, 17185 }, + { 0x576F, 17189 }, + { 0x5771, 17193 }, + { 0x014B, 17197 }, + { 0x0283, 17201 }, + { 0x0286, 17205 }, + { 0x1D8B, 17211 }, + { 0x1D98, 17218 }, + { 0x00F0, 17225 }, + { 0x0292, 17229 }, + { 0x0293, 17233 }, + { 0x01BA, 17239 }, + { 0x01EF, 17245 }, + { 0x1D9A, 17251 }, + { 0x01B9, 17258 }, + { 0x0138, 17263 }, + { 0x5772, 17267 }, + { 0x5773, 17271 }, + { 0x5774, 17275 }, + { 0x0278, 17279 }, + { 0x5775, 17283 }, + { 0x575D, 17287 }, + { 0x1D16, 17292 }, + { 0x5777, 17298 }, + { 0x02A4, 17302 }, + { 0x02A9, 17307 }, + { 0x2C76, 17312 }, + { 0x5727, 17317 }, + { 0x0267, 17321 }, + { 0x0269, 17327 }, + { 0x1D7C, 17331 }, + { 0x026E, 17337 }, + { 0x017F, 17341 }, + { 0x1E9B, 17346 }, + { 0x1E9D, 17354 }, + { 0x1E9C, 17362 }, + { 0x025B, 17370 }, + { 0x1D93, 17375 }, + { 0x0254, 17383 }, + { 0x1D97, 17388 }, + { 0x0264, 17396 }, + { 0x02A7, 17401 }, + { 0x0185, 17406 }, + { 0x01A8, 17411 }, + { 0x01BD, 17416 }, + { 0x5769, 17421 }, + { 0x021D, 17425 }, + { 0x0251, 17429 }, + { 0x1D90, 17433 }, + { 0x1E9F, 17440 }, + { 0x0263, 17444 }, + { 0x0259, 17448 }, + { 0x025A, 17452 }, + { 0x1D95, 17458 }, + { 0x00DF, 17465 }, + { 0x0285, 17470 }, + { 0x00FE, 17476 }, + { 0x5765, 17480 }, + { 0x5767, 17486 }, + { 0x0275, 17494 }, + { 0x1D17, 17499 }, + { 0x5747, 17505 }, + { 0x029A, 17510 }, + { 0x0277, 17516 }, + { 0x025E, 17521 }, + { 0x019B, 17528 }, + { 0x0261, 17534 }, + { 0x0250, 17539 }, + { 0x01DD, 17544 }, + { 0x1D77, 17549 }, + { 0x0265, 17554 }, + { 0x02AE, 17559 }, + { 0x02AF, 17566 }, + { 0x1D09, 17575 }, + { 0x029E, 17580 }, + { 0x5781, 17585 }, + { 0x026F, 17590 }, + { 0x0270, 17595 }, + { 0x0279, 17603 }, + { 0x027B, 17608 }, + { 0x027A, 17615 }, + { 0x2C79, 17623 }, + { 0x0287, 17630 }, + { 0x028C, 17635 }, + { 0x028D, 17640 }, + { 0x028E, 17645 }, + { 0x1D02, 17650 }, + { 0x1D14, 17655 }, + { 0x1D08, 17660 }, + { 0x0252, 17666 }, + { 0x018D, 17671 }, + { 0x577F, 17676 }, + { 0x0131, 17682 }, + { 0x0237, 17687 }, + { 0x025F, 17692 }, + { 0x0284, 17699 }, + { 0x0242, 17708 }, + { 0x577A, 17713 }, + { 0x577C, 17718 }, + { 0x1D79, 17723 }, + { 0x5783, 17728 }, + { 0x5785, 17733 }, + { 0x5787, 17738 }, + { 0x028A, 17743 }, + { 0x1D7F, 17747 }, + { 0x2184, 17753 }, + { 0x573F, 17758 }, + { 0x0258, 17765 }, + { 0x027F, 17770 }, + { 0x025C, 17777 }, + { 0x025D, 17783 }, + { 0x1D94, 17791 }, + { 0x578C, 17800 }, + { 0x1D11, 17804 }, + { 0x1D13, 17809 }, + { 0x1D1D, 17816 }, + { 0x1D12, 17821 }, + { 0x1D1F, 17827 }, + { 0x1D1E, 17833 }, + { 0x2C77, 17839 }, + { 0x572B, 17844 }, + { 0x572D, 17848 }, + { 0x572F, 17852 }, + { 0x5763, 17858 }, + { 0x1EFD, 17863 }, + { 0x1EFB, 17868 }, + { 0x5725, 17873 }, + { 0x5723, 17878 }, + { 0x1D7B, 17883 }, + { 0x1D7E, 17890 }, + { 0x6B00, 17897 }, + { 0x6B01, 17901 }, + { 0x6B02, 17905 }, + { 0x0133, 17909 }, + { 0x0153, 17913 }, + { 0x6B06, 17917 }, + { 0x6B03, 17921 }, + { 0x6B04, 17925 }, + { 0x6B05, 17929 }, + { 0x01A6, 17935 }, + { 0x1D25, 17938 }, + { 0x01BB, 17941 }, + { 0x01BF, 17946 }, + { 0x1D00, 17949 }, + { 0x0299, 17954 }, + { 0x1D04, 17959 }, + { 0x1D05, 17964 }, + { 0x1D07, 17969 }, + { 0x5730, 17974 }, + { 0x0262, 17979 }, + { 0x029B, 17984 }, + { 0x029C, 17991 }, + { 0x026A, 17996 }, + { 0x1D0A, 18001 }, + { 0x1D0B, 18006 }, + { 0x029F, 18011 }, + { 0x1D0C, 18016 }, + { 0x1D0D, 18023 }, + { 0x0274, 18028 }, + { 0x1D0F, 18033 }, + { 0x1D18, 18038 }, + { 0x0280, 18043 }, + { 0x5731, 18048 }, + { 0x1D1B, 18053 }, + { 0x1D1C, 18058 }, + { 0x1D20, 18063 }, + { 0x1D21, 18068 }, + { 0x028F, 18073 }, + { 0x1D22, 18078 }, + { 0x1D01, 18083 }, + { 0x0276, 18088 }, + { 0x1D15, 18093 }, + { 0x1D06, 18098 }, + { 0x1D23, 18103 }, + { 0x5776, 18108 }, + { 0x1D10, 18113 }, + { 0x1D03, 18119 }, + { 0x2C7B, 18125 }, + { 0x1D1A, 18131 }, + { 0x0281, 18137 }, + { 0x1D0E, 18143 }, + { 0x1D19, 18149 }, + { 0x01C0, 18155 }, + { 0x1D24, 18159 }, + { 0x0294, 18164 }, + { 0x02A1, 18168 }, + { 0x01C1, 18174 }, + { 0x01C2, 18178 }, + { 0x02AD, 18182 }, + { 0x0298, 18186 }, + { 0x02AC, 18190 }, + { 0x0296, 18194 }, + { 0x01BE, 18199 }, + { 0x01AA, 18206 }, + { 0x02A2, 18211 }, + { 0x01C3, 18218 }, + { 0x0297, 18222 }, + { 0x0295, 18226 }, + { 0x0041, 18231 }, + { 0x0226, 18235 }, + { 0x01E0, 18242 }, + { 0x1EA0, 18251 }, + { 0x1EA2, 18258 }, + { 0x00C5, 18265 }, + { 0x01FA, 18272 }, + { 0x1E00, 18281 }, + { 0x00C1, 18288 }, + { 0x0102, 18294 }, + { 0x1EB6, 18300 }, + { 0x1EB2, 18309 }, + { 0x1EAE, 18318 }, + { 0x1EB0, 18326 }, + { 0x1EB4, 18334 }, + { 0x01CD, 18342 }, + { 0x00C0, 18348 }, + { 0x00C3, 18354 }, + { 0x0200, 18360 }, + { 0x0100, 18367 }, + { 0x0104, 18373 }, + { 0x023A, 18379 }, + { 0x0202, 18385 }, + { 0x00C4, 18392 }, + { 0x01DE, 18398 }, + { 0x00C2, 18406 }, + { 0x1EAC, 18412 }, + { 0x1EA8, 18421 }, + { 0x1EA4, 18430 }, + { 0x1EA6, 18438 }, + { 0x1EAA, 18446 }, + { 0x0042, 18454 }, + { 0x1E02, 18458 }, + { 0x1E04, 18465 }, + { 0x0181, 18472 }, + { 0x1E06, 18478 }, + { 0x0243, 18485 }, + { 0x0182, 18491 }, + { 0x0043, 18497 }, + { 0x010A, 18501 }, + { 0x0187, 18508 }, + { 0x0106, 18514 }, + { 0x010C, 18520 }, + { 0x023B, 18526 }, + { 0x00C7, 18532 }, + { 0x1E08, 18538 }, + { 0x0108, 18546 }, + { 0x0044, 18552 }, + { 0x1E0A, 18556 }, + { 0x1E0C, 18563 }, + { 0x018A, 18570 }, + { 0x1E0E, 18576 }, + { 0x010E, 18583 }, + { 0x01F2, 18589 }, + { 0x01C5, 18597 }, + { 0x0110, 18607 }, + { 0x018B, 18613 }, + { 0x1E10, 18619 }, + { 0x1E12, 18625 }, + { 0x0045, 18632 }, + { 0x0116, 18636 }, + { 0x1EB8, 18643 }, + { 0x1EBA, 18650 }, + { 0x00C9, 18657 }, + { 0x0114, 18663 }, + { 0x011A, 18669 }, + { 0x00C8, 18675 }, + { 0x1EBC, 18681 }, + { 0x1E1A, 18687 }, + { 0x0204, 18694 }, + { 0x0112, 18701 }, + { 0x1E16, 18707 }, + { 0x1E14, 18715 }, + { 0x0118, 18723 }, + { 0x0246, 18729 }, + { 0x0228, 18735 }, + { 0x1E1C, 18741 }, + { 0x0206, 18749 }, + { 0x00CB, 18756 }, + { 0x00CA, 18762 }, + { 0x1EC6, 18768 }, + { 0x1EC2, 18777 }, + { 0x1EBE, 18786 }, + { 0x1EC0, 18794 }, + { 0x1EC4, 18802 }, + { 0x1E18, 18810 }, + { 0x0046, 18817 }, + { 0x1E1E, 18821 }, + { 0x0191, 18828 }, + { 0x0047, 18834 }, + { 0x0120, 18838 }, + { 0x0193, 18845 }, + { 0x01F4, 18851 }, + { 0x011E, 18857 }, + { 0x01E6, 18863 }, + { 0x1E20, 18869 }, + { 0x01E4, 18875 }, + { 0x0122, 18881 }, + { 0x011C, 18887 }, + { 0x0048, 18893 }, + { 0x1E22, 18897 }, + { 0x1E24, 18904 }, + { 0x1E2A, 18911 }, + { 0x021E, 18918 }, + { 0x0126, 18924 }, + { 0x1E28, 18930 }, + { 0x2C67, 18936 }, + { 0x1E26, 18942 }, + { 0x0124, 18948 }, + { 0x0049, 18954 }, + { 0x0130, 18958 }, + { 0x1ECA, 18965 }, + { 0x1EC8, 18972 }, + { 0x00CD, 18979 }, + { 0x012C, 18985 }, + { 0x01CF, 18991 }, + { 0x00CC, 18997 }, + { 0x0128, 19003 }, + { 0x1E2C, 19009 }, + { 0x0208, 19016 }, + { 0x012A, 19023 }, + { 0x012E, 19029 }, + { 0x0197, 19035 }, + { 0x020A, 19041 }, + { 0x00CF, 19048 }, + { 0x1E2E, 19054 }, + { 0x00CE, 19062 }, + { 0x004A, 19068 }, + { 0x0248, 19072 }, + { 0x0134, 19078 }, + { 0x004B, 19084 }, + { 0x1E32, 19088 }, + { 0x0198, 19095 }, + { 0x1E34, 19101 }, + { 0x1E30, 19108 }, + { 0x01E8, 19114 }, + { 0x5740, 19120 }, + { 0x5744, 19126 }, + { 0x0136, 19135 }, + { 0x5742, 19141 }, + { 0x2C69, 19148 }, + { 0x004C, 19154 }, + { 0x023D, 19158 }, + { 0x1E36, 19164 }, + { 0x1E38, 19171 }, + { 0x5748, 19180 }, + { 0x1E3A, 19187 }, + { 0x0139, 19194 }, + { 0x013D, 19200 }, + { 0x01C8, 19206 }, + { 0x2C60, 19214 }, + { 0x013F, 19221 }, + { 0x2C62, 19228 }, + { 0x0141, 19235 }, + { 0x013B, 19241 }, + { 0x1E3C, 19247 }, + { 0x004D, 19254 }, + { 0x1E40, 19258 }, + { 0x1E42, 19265 }, + { 0x2C6E, 19272 }, + { 0x1E3E, 19278 }, + { 0x004E, 19284 }, + { 0x1E44, 19288 }, + { 0x1E46, 19295 }, + { 0x019D, 19302 }, + { 0x1E48, 19309 }, + { 0x0220, 19316 }, + { 0x0143, 19324 }, + { 0x0147, 19330 }, + { 0x01F8, 19336 }, + { 0x01CB, 19342 }, + { 0x00D1, 19350 }, + { 0x0145, 19356 }, + { 0x1E4A, 19362 }, + { 0x004F, 19369 }, + { 0x022E, 19373 }, + { 0x0230, 19380 }, + { 0x1ECC, 19389 }, + { 0x1ECE, 19396 }, + { 0x01A0, 19403 }, + { 0x1EE2, 19409 }, + { 0x1EDE, 19418 }, + { 0x1EDA, 19427 }, + { 0x1EDC, 19435 }, + { 0x1EE0, 19443 }, + { 0x574A, 19451 }, + { 0x574C, 19459 }, + { 0x00D3, 19465 }, + { 0x014E, 19471 }, + { 0x01D1, 19477 }, + { 0x00D2, 19483 }, + { 0x00D5, 19489 }, + { 0x1E4C, 19495 }, + { 0x022C, 19503 }, + { 0x1E4E, 19511 }, + { 0x0150, 19519 }, + { 0x020C, 19526 }, + { 0x014C, 19533 }, + { 0x1E52, 19539 }, + { 0x1E50, 19547 }, + { 0x019F, 19555 }, + { 0x01EA, 19562 }, + { 0x01EC, 19568 }, + { 0x00D8, 19576 }, + { 0x01FE, 19582 }, + { 0x020E, 19590 }, + { 0x00D6, 19597 }, + { 0x022A, 19603 }, + { 0x00D4, 19611 }, + { 0x1ED8, 19617 }, + { 0x1ED4, 19626 }, + { 0x1ED0, 19635 }, + { 0x1ED2, 19643 }, + { 0x1ED6, 19651 }, + { 0x0050, 19659 }, + { 0x1E56, 19663 }, + { 0x01A4, 19670 }, + { 0x1E54, 19676 }, + { 0x2C63, 19682 }, + { 0x5750, 19688 }, + { 0x5752, 19696 }, + { 0x5754, 19702 }, + { 0x0051, 19709 }, + { 0x5756, 19713 }, + { 0x5758, 19721 }, + { 0x0052, 19728 }, + { 0x1E58, 19732 }, + { 0x1E5A, 19739 }, + { 0x1E5C, 19746 }, + { 0x1E5E, 19755 }, + { 0x2C64, 19762 }, + { 0x0154, 19768 }, + { 0x0158, 19774 }, + { 0x0210, 19780 }, + { 0x024C, 19787 }, + { 0x0156, 19793 }, + { 0x0212, 19799 }, + { 0x575A, 19806 }, + { 0x0053, 19811 }, + { 0x1E60, 19815 }, + { 0x1E62, 19822 }, + { 0x1E68, 19829 }, + { 0x015A, 19839 }, + { 0x1E64, 19845 }, + { 0x0160, 19854 }, + { 0x1E66, 19860 }, + { 0x0218, 19869 }, + { 0x015E, 19876 }, + { 0x015C, 19882 }, + { 0x0054, 19888 }, + { 0x1E6A, 19892 }, + { 0x1E6C, 19899 }, + { 0x01AC, 19906 }, + { 0x1E6E, 19912 }, + { 0x0164, 19919 }, + { 0x021A, 19925 }, + { 0x0166, 19932 }, + { 0x0162, 19938 }, + { 0x023E, 19944 }, + { 0x01AE, 19951 }, + { 0x1E70, 19958 }, + { 0x0055, 19965 }, + { 0x0244, 19969 }, + { 0x1EE4, 19974 }, + { 0x1EE6, 19981 }, + { 0x01AF, 19988 }, + { 0x1EF0, 19994 }, + { 0x1EEC, 20003 }, + { 0x1EE8, 20012 }, + { 0x1EEA, 20020 }, + { 0x1EEE, 20028 }, + { 0x016E, 20036 }, + { 0x00DA, 20043 }, + { 0x016C, 20049 }, + { 0x01D3, 20055 }, + { 0x00D9, 20061 }, + { 0x0168, 20067 }, + { 0x1E78, 20073 }, + { 0x1E74, 20081 }, + { 0x0170, 20088 }, + { 0x0214, 20095 }, + { 0x016A, 20102 }, + { 0x1E7A, 20108 }, + { 0x0172, 20116 }, + { 0x0216, 20122 }, + { 0x00DC, 20129 }, + { 0x01D7, 20135 }, + { 0x01D9, 20143 }, + { 0x01DB, 20151 }, + { 0x01D5, 20159 }, + { 0x1E72, 20167 }, + { 0x00DB, 20174 }, + { 0x1E76, 20180 }, + { 0x0056, 20187 }, + { 0x1E7E, 20191 }, + { 0x01B2, 20198 }, + { 0x1E7C, 20204 }, + { 0x575E, 20210 }, + { 0x0057, 20217 }, + { 0x1E86, 20221 }, + { 0x1E88, 20228 }, + { 0x2C72, 20235 }, + { 0x1E82, 20241 }, + { 0x1E80, 20247 }, + { 0x1E84, 20253 }, + { 0x0174, 20259 }, + { 0x0058, 20265 }, + { 0x1E8A, 20269 }, + { 0x1E8C, 20276 }, + { 0x0059, 20282 }, + { 0x1E8E, 20286 }, + { 0x1EF4, 20293 }, + { 0x01B3, 20300 }, + { 0x1EF6, 20306 }, + { 0x1EFE, 20313 }, + { 0x00DD, 20319 }, + { 0x1EF2, 20325 }, + { 0x1EF8, 20331 }, + { 0x0232, 20337 }, + { 0x024E, 20343 }, + { 0x0178, 20349 }, + { 0x0176, 20355 }, + { 0x005A, 20361 }, + { 0x017B, 20365 }, + { 0x1E92, 20372 }, + { 0x0224, 20379 }, + { 0x1E94, 20385 }, + { 0x0179, 20392 }, + { 0x017D, 20398 }, + { 0x01B5, 20404 }, + { 0x2C6B, 20410 }, + { 0x1E90, 20416 }, + { 0x5732, 20422 }, + { 0x00C6, 20426 }, + { 0x01FC, 20430 }, + { 0x01E2, 20436 }, + { 0x5734, 20442 }, + { 0x5736, 20446 }, + { 0x5738, 20450 }, + { 0x573A, 20454 }, + { 0x573C, 20461 }, + { 0x01F1, 20465 }, + { 0x01C4, 20469 }, + { 0x576A, 20475 }, + { 0x576C, 20479 }, + { 0x01C7, 20483 }, + { 0x01CA, 20487 }, + { 0x01A2, 20491 }, + { 0x574E, 20495 }, + { 0x0222, 20499 }, + { 0x5728, 20503 }, + { 0x5760, 20507 }, + { 0x576E, 20511 }, + { 0x014A, 20515 }, + { 0x01A9, 20519 }, + { 0x00D0, 20523 }, + { 0x01B7, 20527 }, + { 0x01EE, 20531 }, + { 0x01B8, 20537 }, + { 0x575C, 20542 }, + { 0x2C75, 20547 }, + { 0x5726, 20552 }, + { 0x0196, 20556 }, + { 0x0190, 20560 }, + { 0x0186, 20565 }, + { 0x0184, 20570 }, + { 0x01A7, 20575 }, + { 0x01BC, 20580 }, + { 0x5768, 20585 }, + { 0x01F7, 20589 }, + { 0x021C, 20593 }, + { 0x2C6D, 20597 }, + { 0x0194, 20601 }, + { 0x01F6, 20605 }, + { 0x018F, 20609 }, + { 0x1E9E, 20613 }, + { 0x024A, 20618 }, + { 0x00DE, 20626 }, + { 0x5764, 20630 }, + { 0x5766, 20636 }, + { 0x5746, 20644 }, + { 0x2C6F, 20649 }, + { 0x5780, 20654 }, + { 0x019C, 20659 }, + { 0x0245, 20664 }, + { 0x577E, 20669 }, + { 0x0189, 20675 }, + { 0x0241, 20680 }, + { 0x5779, 20685 }, + { 0x577B, 20690 }, + { 0x577D, 20695 }, + { 0x5782, 20700 }, + { 0x5784, 20705 }, + { 0x5786, 20710 }, + { 0x01B1, 20715 }, + { 0x573E, 20719 }, + { 0x018E, 20726 }, + { 0x578B, 20731 }, + { 0x572A, 20735 }, + { 0x572C, 20739 }, + { 0x572E, 20743 }, + { 0x5762, 20749 }, + { 0x1EFC, 20754 }, + { 0x1EFA, 20759 }, + { 0x5724, 20764 }, + { 0x5722, 20769 }, + { 0x0132, 20774 }, + { 0x0152, 20778 }, + { 0x2090, 20782 }, + { 0x2091, 20787 }, + { 0x1D62, 20792 }, + { 0x2C7C, 20797 }, + { 0x2092, 20802 }, + { 0x1D63, 20807 }, + { 0x1D64, 20812 }, + { 0x1D65, 20817 }, + { 0x2093, 20822 }, + { 0x2094, 20827 }, + { 0x57FE, 20832 }, + { 0x57FF, 20837 }, + { 0x57FD, 20842 }, + { 0x57FB, 20847 }, + { 0x57FC, 20852 }, + { 0x264E, 20857 }, + { 0x2772, 20858 }, + { 0x2773, 20864 }, + { 0x2591, 20870 }, + { 0x2758, 20872 }, + { 0x1940, 20875 }, + { 0x193B, 20878 }, + { 0x193A, 20881 }, + { 0x1939, 20884 }, + { 0x1947, 20887 }, + { 0x194C, 20890 }, + { 0x1948, 20893 }, + { 0x194B, 20896 }, + { 0x194A, 20899 }, + { 0x194F, 20902 }, + { 0x1946, 20905 }, + { 0x194E, 20908 }, + { 0x194D, 20911 }, + { 0x1949, 20914 }, + { 0x1930, 20917 }, + { 0x1938, 20921 }, + { 0x1936, 20925 }, + { 0x1934, 20929 }, + { 0x1935, 20933 }, + { 0x1937, 20937 }, + { 0x1933, 20941 }, + { 0x1931, 20945 }, + { 0x1932, 20949 }, + { 0x1920, 20953 }, + { 0x1927, 20957 }, + { 0x1921, 20961 }, + { 0x1928, 20965 }, + { 0x1922, 20969 }, + { 0x1924, 20973 }, + { 0x1926, 20977 }, + { 0x1923, 20981 }, + { 0x1925, 20985 }, + { 0x1912, 20989 }, + { 0x1906, 20992 }, + { 0x190D, 20995 }, + { 0x1903, 20998 }, + { 0x191C, 21001 }, + { 0x1908, 21004 }, + { 0x1901, 21007 }, + { 0x1917, 21010 }, + { 0x1914, 21013 }, + { 0x190F, 21016 }, + { 0x1910, 21019 }, + { 0x1916, 21022 }, + { 0x191B, 21025 }, + { 0x190B, 21028 }, + { 0x1918, 21031 }, + { 0x1915, 21034 }, + { 0x1913, 21037 }, + { 0x1907, 21040 }, + { 0x190E, 21043 }, + { 0x1904, 21046 }, + { 0x1909, 21049 }, + { 0x1902, 21052 }, + { 0x1905, 21055 }, + { 0x1911, 21058 }, + { 0x1919, 21061 }, + { 0x191A, 21064 }, + { 0x190C, 21067 }, + { 0x190A, 21070 }, + { 0x1945, 21073 }, + { 0x192A, 21076 }, + { 0x192B, 21080 }, + { 0x1929, 21084 }, + { 0x1944, 21088 }, + { 0x1900, 21091 }, + { 0x2581, 21094 }, + { 0x2582, 21098 }, + { 0x2585, 21102 }, + { 0x2584, 21106 }, + { 0x25E1, 21109 }, + { 0x25DB, 21112 }, + { 0x25DF, 21117 }, + { 0x25FA, 21122 }, + { 0x293F, 21125 }, + { 0x2703, 21130 }, + { 0x27D3, 21133 }, + { 0x270E, 21138 }, + { 0x25DE, 21141 }, + { 0x2751, 21146 }, + { 0x25FF, 21151 }, + { 0x293E, 21154 }, + { 0x274F, 21159 }, + { 0x2587, 21164 }, + { 0x2583, 21168 }, + { 0x2586, 21172 }, + { 0x00B5, 21176 }, + { 0x2212, 21178 }, + { 0x2A3A, 21180 }, + { 0x2A2A, 21184 }, + { 0x2A29, 21189 }, + { 0x2A2C, 21194 }, + { 0x2A2B, 21199 }, + { 0x2242, 21204 }, + { 0x266D, 21206 }, + { 0x266F, 21209 }, + { 0x266E, 21212 }, + { 0x2A09, 21215 }, + { 0x22C3, 21218 }, + { 0x2A03, 21220 }, + { 0x2A04, 21225 }, + { 0x2AFF, 21230 }, + { 0x2A06, 21234 }, + { 0x2A05, 21238 }, + { 0x2A00, 21242 }, + { 0x2A01, 21246 }, + { 0x2A02, 21250 }, + { 0x22C1, 21254 }, + { 0x22C0, 21257 }, + { 0x220F, 21260 }, + { 0x2210, 21262 }, + { 0x2211, 21264 }, + { 0x22C2, 21266 }, + { 0x2207, 21268 }, + { 0x20A6, 21269 }, + { 0x2922, 21271 }, + { 0x2197, 21277 }, + { 0x2928, 21280 }, + { 0x2924, 21287 }, + { 0x2931, 21292 }, + { 0x292E, 21299 }, + { 0x2B08, 21306 }, + { 0x2B00, 21310 }, + { 0x21D7, 21314 }, + { 0x2921, 21318 }, + { 0x2196, 21324 }, + { 0x21B8, 21327 }, + { 0x21F1, 21333 }, + { 0x2927, 21338 }, + { 0x2923, 21345 }, + { 0x2932, 21350 }, + { 0x2B09, 21357 }, + { 0x2B01, 21361 }, + { 0x21D6, 21365 }, + { 0x1680, 21369 }, + { 0x1696, 21372 }, + { 0x1692, 21375 }, + { 0x1691, 21378 }, + { 0x1690, 21381 }, + { 0x1689, 21384 }, + { 0x1687, 21387 }, + { 0x168C, 21390 }, + { 0x1698, 21393 }, + { 0x1682, 21396 }, + { 0x168B, 21399 }, + { 0x1685, 21402 }, + { 0x168F, 21405 }, + { 0x1684, 21408 }, + { 0x1686, 21411 }, + { 0x1681, 21414 }, + { 0x168A, 21417 }, + { 0x1683, 21420 }, + { 0x169A, 21423 }, + { 0x1688, 21426 }, + { 0x168E, 21429 }, + { 0x1695, 21432 }, + { 0x1693, 21435 }, + { 0x1694, 21438 }, + { 0x168D, 21441 }, + { 0x1697, 21444 }, + { 0x1699, 21447 }, + { 0x169B, 21450 }, + { 0x169C, 21453 }, + { 0x0B56, 21457 }, + { 0x0B57, 21461 }, + { 0x0B3C, 21465 }, + { 0x0B4D, 21468 }, + { 0x0B03, 21471 }, + { 0x0B02, 21474 }, + { 0x0B3D, 21477 }, + { 0x0B01, 21480 }, + { 0x0B67, 21483 }, + { 0x0B6C, 21486 }, + { 0x0B68, 21489 }, + { 0x0B6B, 21492 }, + { 0x0B6A, 21495 }, + { 0x0B6F, 21498 }, + { 0x0B66, 21501 }, + { 0x0B6E, 21504 }, + { 0x0B6D, 21507 }, + { 0x0B69, 21510 }, + { 0x0B47, 21513 }, + { 0x0B3F, 21517 }, + { 0x0B4B, 21521 }, + { 0x0B41, 21525 }, + { 0x0B3E, 21529 }, + { 0x0B48, 21533 }, + { 0x0B4C, 21537 }, + { 0x0B40, 21541 }, + { 0x0B42, 21545 }, + { 0x0B62, 21549 }, + { 0x0B43, 21554 }, + { 0x0B63, 21559 }, + { 0x0B44, 21564 }, + { 0x0B70, 21569 }, + { 0x0B05, 21571 }, + { 0x0B0F, 21574 }, + { 0x0B07, 21577 }, + { 0x0B13, 21580 }, + { 0x0B09, 21583 }, + { 0x0B06, 21586 }, + { 0x0B10, 21589 }, + { 0x0B14, 21592 }, + { 0x0B2C, 21595 }, + { 0x0B1A, 21598 }, + { 0x0B26, 21601 }, + { 0x0B17, 21604 }, + { 0x0B39, 21607 }, + { 0x0B08, 21610 }, + { 0x0B1C, 21613 }, + { 0x0B15, 21616 }, + { 0x0B32, 21619 }, + { 0x0B2E, 21622 }, + { 0x0B28, 21625 }, + { 0x0B2A, 21628 }, + { 0x0B30, 21631 }, + { 0x0B38, 21634 }, + { 0x0B24, 21637 }, + { 0x0B0A, 21640 }, + { 0x0B35, 21643 }, + { 0x0B71, 21646 }, + { 0x0B2F, 21649 }, + { 0x0B2D, 21652 }, + { 0x0B1B, 21655 }, + { 0x0B21, 21658 }, + { 0x0B27, 21661 }, + { 0x0B18, 21664 }, + { 0x0B1D, 21667 }, + { 0x0B16, 21670 }, + { 0x0B33, 21673 }, + { 0x0B19, 21676 }, + { 0x0B23, 21679 }, + { 0x0B1E, 21682 }, + { 0x0B2B, 21685 }, + { 0x0B5D, 21688 }, + { 0x0B5C, 21691 }, + { 0x0B36, 21694 }, + { 0x0B37, 21697 }, + { 0x0B25, 21700 }, + { 0x0B1F, 21703 }, + { 0x0B5F, 21706 }, + { 0x0B22, 21709 }, + { 0x0B20, 21712 }, + { 0x0B0C, 21715 }, + { 0x0B0B, 21719 }, + { 0x0B61, 21723 }, + { 0x0B60, 21727 }, + { 0x2125, 21731 }, + { 0x262E, 21733 }, + { 0x2318, 21735 }, + { 0x2647, 21739 }, + { 0x00A3, 21740 }, + { 0x2032, 21742 }, + { 0x2399, 21743 }, + { 0x2236, 21746 }, + { 0x2994, 21747 }, + { 0x2E1D, 21751 }, + { 0x2595, 21755 }, + { 0x297D, 21759 }, + { 0x25D7, 21762 }, + { 0x2590, 21766 }, + { 0x22A2, 21769 }, + { 0x221F, 21771 }, + { 0x22BE, 21773 }, + { 0x237C, 21777 }, + { 0x2E01, 21783 }, + { 0x3009, 21788 }, + { 0x2992, 21791 }, + { 0x299C, 21796 }, + { 0x2E00, 21801 }, + { 0x21F4, 21805 }, + { 0x27F4, 21810 }, + { 0x2998, 21815 }, + { 0x3011, 21820 }, + { 0x007D, 21824 }, + { 0x23AD, 21827 }, + { 0x23AB, 21832 }, + { 0x23AC, 21837 }, + { 0x230B, 21842 }, + { 0x27D6, 21844 }, + { 0x2984, 21847 }, + { 0x300F, 21851 }, + { 0x301B, 21855 }, + { 0x3019, 21859 }, + { 0x3017, 21864 }, + { 0x2986, 21868 }, + { 0x300D, 21871 }, + { 0x2E05, 21874 }, + { 0x300B, 21878 }, + { 0x2970, 21882 }, + { 0x29DB, 21888 }, + { 0x201D, 21892 }, + { 0x2E29, 21896 }, + { 0x22CA, 21899 }, + { 0x2E0D, 21904 }, + { 0x2019, 21908 }, + { 0x005D, 21912 }, + { 0x2990, 21915 }, + { 0x298E, 21923 }, + { 0x2046, 21931 }, + { 0x298C, 21936 }, + { 0x23A6, 21941 }, + { 0x23A4, 21946 }, + { 0x23A5, 21951 }, + { 0x29D9, 21955 }, + { 0x2309, 21958 }, + { 0x27C6, 21960 }, + { 0x2E27, 21964 }, + { 0x3015, 21968 }, + { 0x22BF, 21972 }, + { 0x29CE, 21974 }, + { 0x2E21, 21979 }, + { 0x23B9, 21984 }, + { 0x22CC, 21988 }, + { 0x0029, 21991 }, + { 0x23A0, 21993 }, + { 0x239E, 21997 }, + { 0x239F, 22001 }, + { 0x2E03, 22004 }, + { 0x2E0A, 22007 }, + { 0x719A, 22010 }, + { 0x7191, 22013 }, + { 0x7194, 22016 }, + { 0x2160, 22020 }, + { 0x216D, 22023 }, + { 0x2188, 22027 }, + { 0x216F, 22032 }, + { 0x2180, 22036 }, + { 0x2165, 22042 }, + { 0x2185, 22045 }, + { 0x2169, 22050 }, + { 0x2182, 22053 }, + { 0x2161, 22057 }, + { 0x2164, 22060 }, + { 0x216E, 22063 }, + { 0x2181, 22067 }, + { 0x2163, 22071 }, + { 0x2168, 22074 }, + { 0x2167, 22077 }, + { 0x216C, 22080 }, + { 0x2186, 22083 }, + { 0x2187, 22088 }, + { 0x2166, 22092 }, + { 0x2162, 22095 }, + { 0x216A, 22098 }, + { 0x216B, 22101 }, + { 0x2183, 22104 }, + { 0x7190, 22109 }, + { 0x7193, 22112 }, + { 0x7195, 22115 }, + { 0x7196, 22118 }, + { 0x7192, 22121 }, + { 0x719B, 22124 }, + { 0x7199, 22127 }, + { 0x7197, 22130 }, + { 0x7198, 22133 }, + { 0x16ED, 22136 }, + { 0x16EE, 22139 }, + { 0x16CD, 22142 }, + { 0x16D1, 22145 }, + { 0x16C2, 22148 }, + { 0x16B5, 22151 }, + { 0x16AE, 22154 }, + { 0x16E9, 22157 }, + { 0x16A1, 22160 }, + { 0x16A5, 22163 }, + { 0x16EA, 22166 }, + { 0x16A4, 22169 }, + { 0x16CE, 22172 }, + { 0x16AA, 22175 }, + { 0x16AF, 22179 }, + { 0x16B0, 22182 }, + { 0x16A9, 22185 }, + { 0x16A3, 22189 }, + { 0x16B3, 22192 }, + { 0x16E0, 22195 }, + { 0x16B6, 22198 }, + { 0x16A7, 22201 }, + { 0x16B8, 22204 }, + { 0x16C4, 22207 }, + { 0x16DD, 22210 }, + { 0x16E1, 22213 }, + { 0x16AB, 22216 }, + { 0x16E3, 22219 }, + { 0x16A0, 22222 }, + { 0x16B7, 22228 }, + { 0x16C1, 22233 }, + { 0x16C7, 22239 }, + { 0x16B4, 22243 }, + { 0x16E5, 22247 }, + { 0x16A2, 22250 }, + { 0x16C9, 22255 }, + { 0x16A8, 22259 }, + { 0x16E4, 22263 }, + { 0x16DE, 22266 }, + { 0x16D6, 22271 }, + { 0x16BB, 22276 }, + { 0x16C3, 22280 }, + { 0x16B2, 22284 }, + { 0x16B1, 22287 }, + { 0x16CB, 22293 }, + { 0x16CF, 22298 }, + { 0x16B9, 22304 }, + { 0x16BA, 22309 }, + { 0x16DC, 22313 }, + { 0x16DA, 22316 }, + { 0x16D7, 22322 }, + { 0x16BE, 22327 }, + { 0x16D5, 22333 }, + { 0x16C8, 22336 }, + { 0x16CA, 22341 }, + { 0x16E2, 22345 }, + { 0x16DF, 22348 }, + { 0x16D2, 22353 }, + { 0x16DB, 22359 }, + { 0x16C0, 22362 }, + { 0x16D4, 22365 }, + { 0x16A6, 22368 }, + { 0x16E8, 22373 }, + { 0x16C6, 22376 }, + { 0x16E7, 22380 }, + { 0x16C5, 22383 }, + { 0x16E6, 22387 }, + { 0x16AD, 22390 }, + { 0x16CC, 22394 }, + { 0x16D0, 22398 }, + { 0x16AC, 22402 }, + { 0x16D9, 22406 }, + { 0x16BF, 22410 }, + { 0x16D8, 22414 }, + { 0x16BD, 22418 }, + { 0x16BC, 22422 }, + { 0x16D3, 22426 }, + { 0x16EB, 22430 }, + { 0x16F0, 22433 }, + { 0x16EC, 22436 }, + { 0x16EF, 22439 }, + { 0x20A8, 22442 }, + { 0x2AE0, 22444 }, + { 0x2AE8, 22447 }, + { 0x2AE9, 22452 }, + { 0x2ADF, 22459 }, + { 0x2AE7, 22462 }, + { 0x2ADE, 22467 }, + { 0x2944, 22470 }, + { 0x2620, 22476 }, + { 0x2333, 22479 }, + { 0x6E58, 22480 }, + { 0x2A61, 22483 }, + { 0x6E52, 22487 }, + { 0x6E5B, 22490 }, + { 0x6E5D, 22494 }, + { 0x6E59, 22499 }, + { 0x6E62, 22502 }, + { 0x6E55, 22505 }, + { 0x6E50, 22507 }, + { 0x6E5C, 22509 }, + { 0x6E5E, 22513 }, + { 0x6E5A, 22518 }, + { 0x2170, 22521 }, + { 0x217D, 22525 }, + { 0x217F, 22530 }, + { 0x2175, 22535 }, + { 0x2179, 22539 }, + { 0x2171, 22543 }, + { 0x2174, 22547 }, + { 0x217E, 22551 }, + { 0x2173, 22556 }, + { 0x2178, 22560 }, + { 0x2177, 22564 }, + { 0x217C, 22568 }, + { 0x2176, 22572 }, + { 0x2172, 22576 }, + { 0x217A, 22580 }, + { 0x217B, 22584 }, + { 0x02DC, 22588 }, + { 0x6E69, 22590 }, + { 0x6E66, 22593 }, + { 0x6E5F, 22596 }, + { 0x220A, 22599 }, + { 0x22F7, 22602 }, + { 0x22F4, 22607 }, + { 0x6E6A, 22618 }, + { 0x6E68, 22621 }, + { 0x6E61, 22624 }, + { 0x220D, 22626 }, + { 0x22FE, 22630 }, + { 0x22FC, 22634 }, + { 0x6E56, 22644 }, + { 0x6E60, 22647 }, + { 0x6E64, 22649 }, + { 0x6E54, 22652 }, + { 0x6E6B, 22654 }, + { 0x6E57, 22657 }, + { 0x6E51, 22660 }, + { 0x6E65, 22663 }, + { 0x6E63, 22666 }, + { 0x2A33, 22668 }, + { 0x2323, 22670 }, + { 0x2117, 22671 }, + { 0x2198, 22674 }, + { 0x21F2, 22677 }, + { 0x2929, 22682 }, + { 0x2925, 22689 }, + { 0x292D, 22694 }, + { 0x2B0A, 22701 }, + { 0x2B02, 22705 }, + { 0x21D8, 22709 }, + { 0x2199, 22713 }, + { 0x292A, 22716 }, + { 0x2926, 22723 }, + { 0x2B0B, 22728 }, + { 0x2B03, 22732 }, + { 0x21D9, 22736 }, + { 0x0020, 22740 }, + { 0x27A7, 22741 }, + { 0x269A, 22745 }, + { 0x2695, 22748 }, + { 0x2053, 22751 }, + { 0x0BF8, 22753 }, + { 0x0BD7, 22757 }, + { 0x0BD0, 22761 }, + { 0x0BF3, 22763 }, + { 0x0BCD, 22766 }, + { 0x0B83, 22769 }, + { 0x0B82, 22772 }, + { 0x0BF5, 22775 }, + { 0x0BF6, 22778 }, + { 0x0BE7, 22781 }, + { 0x0BEC, 22784 }, + { 0x0BE8, 22787 }, + { 0x0BEB, 22790 }, + { 0x0BEA, 22793 }, + { 0x0BEF, 22796 }, + { 0x0BE6, 22799 }, + { 0x0BEE, 22802 }, + { 0x0BED, 22805 }, + { 0x0BE9, 22808 }, + { 0x0BF4, 22811 }, + { 0x0BF9, 22814 }, + { 0x0BC6, 22817 }, + { 0x0BBF, 22821 }, + { 0x0BCA, 22825 }, + { 0x0BC1, 22829 }, + { 0x0BBE, 22833 }, + { 0x0BC8, 22837 }, + { 0x0BCC, 22841 }, + { 0x0BC7, 22845 }, + { 0x0BC0, 22849 }, + { 0x0BCB, 22853 }, + { 0x0BC2, 22857 }, + { 0x0BF7, 22861 }, + { 0x0B85, 22864 }, + { 0x0B8E, 22867 }, + { 0x0B87, 22870 }, + { 0x0B92, 22873 }, + { 0x0B89, 22876 }, + { 0x0B86, 22879 }, + { 0x0B90, 22882 }, + { 0x0B94, 22885 }, + { 0x0B9A, 22888 }, + { 0x0B8F, 22891 }, + { 0x0BB9, 22894 }, + { 0x0B88, 22897 }, + { 0x0B9C, 22900 }, + { 0x0B95, 22903 }, + { 0x0BB2, 22906 }, + { 0x0BAE, 22909 }, + { 0x0BA8, 22912 }, + { 0x0B93, 22915 }, + { 0x0BAA, 22918 }, + { 0x0BB0, 22921 }, + { 0x0BB8, 22924 }, + { 0x0BA4, 22927 }, + { 0x0B8A, 22930 }, + { 0x0BB5, 22933 }, + { 0x0BAF, 22936 }, + { 0x0BB3, 22939 }, + { 0x0B99, 22942 }, + { 0x0BA3, 22945 }, + { 0x0B9E, 22948 }, + { 0x0BB1, 22951 }, + { 0x0BB6, 22954 }, + { 0x0BB7, 22957 }, + { 0x0B9F, 22960 }, + { 0x0BB4, 22963 }, + { 0x0BA9, 22966 }, + { 0x0BF1, 22969 }, + { 0x0BF2, 22973 }, + { 0x0BF0, 22977 }, + { 0x0BFA, 22980 }, + { 0x2204, 22983 }, + { 0x2203, 22987 }, + { 0x2056, 22989 }, + { 0x2B31, 22992 }, + { 0x21F6, 22995 }, + { 0x2A76, 22998 }, + { 0x27C0, 23002 }, + { 0x2745, 23005 }, + { 0x007E, 23008 }, + { 0x2E1E, 23009 }, + { 0x2E1F, 23013 }, + { 0x2E1B, 23017 }, + { 0x223C, 23021 }, + { 0x2A6A, 23023 }, + { 0x2A6B, 23028 }, + { 0x2B49, 23033 }, + { 0x2972, 23038 }, + { 0x29D4, 23043 }, + { 0x29D5, 23048 }, + { 0x2330, 23053 }, + { 0x2122, 23055 }, + { 0x222A, 23058 }, + { 0x2A41, 23059 }, + { 0x2A45, 23063 }, + { 0x2A42, 23067 }, + { 0x2A48, 23070 }, + { 0x2A46, 23075 }, + { 0x2A4A, 23078 }, + { 0x2594, 23084 }, + { 0x2580, 23088 }, + { 0x25E0, 23091 }, + { 0x25DA, 23094 }, + { 0x23B0, 23099 }, + { 0x27D4, 23107 }, + { 0x25DC, 23112 }, + { 0x25F8, 23117 }, + { 0x2701, 23120 }, + { 0x23B1, 23123 }, + { 0x2710, 23131 }, + { 0x25DD, 23134 }, + { 0x2752, 23139 }, + { 0x25F9, 23144 }, + { 0x2750, 23147 }, + { 0x26B6, 23152 }, + { 0x264D, 23153 }, + { 0x231A, 23154 }, + { 0x2638, 23155 }, + { 0x261D, 23158 }, + { 0x2711, 23162 }, + { 0x263C, 23164 }, + { 0x2667, 23168 }, + { 0x261F, 23171 }, + { 0x2690, 23175 }, + { 0x2727, 23177 }, + { 0x261C, 23181 }, + { 0x2606, 23185 }, + { 0x2B1E, 23187 }, + { 0x2654, 23191 }, + { 0x2659, 23194 }, + { 0x2656, 23197 }, + { 0x2655, 23200 }, + { 0x2657, 23203 }, + { 0x2658, 23206 }, + { 0x2661, 23209 }, + { 0x2B1C, 23212 }, + { 0x261E, 23215 }, + { 0x2616, 23219 }, + { 0x2B52, 23222 }, + { 0x25AB, 23225 }, + { 0x2B2B, 23228 }, + { 0x2664, 23231 }, + { 0x25E6, 23234 }, + { 0x25CB, 23236 }, + { 0x2686, 23238 }, + { 0x2687, 23243 }, + { 0x29EC, 23248 }, + { 0x25F5, 23253 }, + { 0x25F6, 23259 }, + { 0x25F4, 23265 }, + { 0x25F7, 23271 }, + { 0x2B50, 23277 }, + { 0x25FD, 23280 }, + { 0x25FB, 23284 }, + { 0x2B26, 23287 }, + { 0x2B28, 23290 }, + { 0x6E46, 23293 }, + { 0x25A1, 23296 }, + { 0x25F1, 23298 }, + { 0x25F2, 23304 }, + { 0x25F0, 23310 }, + { 0x25F3, 23316 }, + { 0x2385, 23322 }, + { 0x25A2, 23328 }, + { 0x25EB, 23333 }, + { 0x27E4, 23339 }, + { 0x27E5, 23344 }, + { 0x25A3, 23349 }, + { 0x25C7, 23355 }, + { 0x2662, 23357 }, + { 0x27D0, 23360 }, + { 0x25C8, 23365 }, + { 0x2B21, 23371 }, + { 0x263A, 23373 }, + { 0x26C0, 23376 }, + { 0x26C1, 23379 }, + { 0x2740, 23382 }, + { 0x2639, 23384 }, + { 0x2B20, 23387 }, + { 0x2704, 23389 }, + { 0x27C1, 23391 }, + { 0x2AFE, 23397 }, + { 0x2B2F, 23400 }, + { 0x25AF, 23403 }, + { 0x29D6, 23406 }, + { 0x25AD, 23408 }, + { 0x260F, 23410 }, + { 0x23E2, 23412 }, + { 0x2B2D, 23414 }, + { 0x25B5, 23417 }, + { 0x25B3, 23421 }, + { 0x25EC, 23424 }, + { 0x27E1, 23429 }, + { 0x27E2, 23432 }, + { 0x27E3, 23438 }, + { 0x25BF, 23444 }, + { 0x25BD, 23448 }, + { 0x25C3, 23451 }, + { 0x25C5, 23455 }, + { 0x25C1, 23458 }, + { 0x25B1, 23461 }, + { 0x25B9, 23463 }, + { 0x25BB, 23467 }, + { 0x2B54, 23470 }, + { 0x25B7, 23473 }, + { 0x713C, 23476 }, + { 0x7101, 23481 }, + { 0x7100, 23485 }, + { 0x7102, 23489 }, + { 0x713D, 23492 }, + { 0x7107, 23497 }, + { 0x7119, 23500 }, + { 0x7122, 23504 }, + { 0x710C, 23508 }, + { 0x711E, 23511 }, + { 0x7127, 23515 }, + { 0x7110, 23519 }, + { 0x712B, 23522 }, + { 0x7108, 23526 }, + { 0x711A, 23529 }, + { 0x7123, 23533 }, + { 0x710B, 23537 }, + { 0x711D, 23540 }, + { 0x7126, 23544 }, + { 0x710A, 23548 }, + { 0x711C, 23551 }, + { 0x7125, 23555 }, + { 0x710F, 23559 }, + { 0x7121, 23562 }, + { 0x712A, 23566 }, + { 0x710E, 23570 }, + { 0x7120, 23573 }, + { 0x7129, 23577 }, + { 0x7114, 23581 }, + { 0x712F, 23584 }, + { 0x7113, 23588 }, + { 0x712E, 23591 }, + { 0x710D, 23595 }, + { 0x711F, 23598 }, + { 0x7128, 23602 }, + { 0x7115, 23606 }, + { 0x7130, 23609 }, + { 0x7109, 23613 }, + { 0x711B, 23616 }, + { 0x7124, 23620 }, + { 0x7117, 23624 }, + { 0x7132, 23627 }, + { 0x7118, 23631 }, + { 0x7133, 23634 }, + { 0x7112, 23638 }, + { 0x712D, 23641 }, + { 0x7111, 23645 }, + { 0x712C, 23648 }, + { 0x7116, 23652 }, + { 0x7131, 23655 }, + { 0x7137, 23659 }, + { 0x7138, 23663 }, + { 0x713A, 23667 }, + { 0x713B, 23671 }, + { 0x7139, 23675 }, + { 0x713F, 23679 }, + { 0x713E, 23683 }, + { 0x224A, 23687 }, + { 0x2248, 23692 }, + { 0x2A6F, 23695 }, + { 0x2693, 23701 }, + { 0x06DD, 23702 }, + { 0x0608, 23706 }, + { 0x060D, 23708 }, + { 0x066D, 23711 }, + { 0x06D4, 23715 }, + { 0x0658, 23718 }, + { 0x0613, 23722 }, + { 0x060F, 23727 }, + { 0x0603, 23730 }, + { 0x0601, 23733 }, + { 0x0611, 23736 }, + { 0x06FD, 23740 }, + { 0x06FE, 23744 }, + { 0x0614, 23749 }, + { 0x0612, 23752 }, + { 0x0610, 23756 }, + { 0x6E73, 23761 }, + { 0x060C, 23764 }, + { 0x064F, 23766 }, + { 0x6E79, 23768 }, + { 0x6E78, 23772 }, + { 0x06EA, 23776 }, + { 0x06EB, 23781 }, + { 0x064E, 23786 }, + { 0x065E, 23788 }, + { 0x6E77, 23793 }, + { 0x6E76, 23797 }, + { 0x0654, 23801 }, + { 0x0655, 23804 }, + { 0x0650, 23807 }, + { 0x6E7B, 23809 }, + { 0x6E7A, 23813 }, + { 0x06E9, 23817 }, + { 0x06ED, 23821 }, + { 0x06E3, 23825 }, + { 0x06E5, 23829 }, + { 0x06E6, 23832 }, + { 0x06D9, 23835 }, + { 0x0615, 23840 }, + { 0x06E7, 23844 }, + { 0x06DA, 23848 }, + { 0x06D8, 23852 }, + { 0x06E2, 23858 }, + { 0x06E8, 23864 }, + { 0x06DC, 23868 }, + { 0x0617, 23872 }, + { 0x06E4, 23876 }, + { 0x06DB, 23880 }, + { 0x06E1, 23885 }, + { 0x06DF, 23892 }, + { 0x06E0, 23897 }, + { 0x06D7, 23903 }, + { 0x06D6, 23913 }, + { 0x0616, 23923 }, + { 0x0619, 23932 }, + { 0x0618, 23935 }, + { 0x061A, 23938 }, + { 0x06DE, 23941 }, + { 0x0652, 23947 }, + { 0x6E7F, 23949 }, + { 0x6E7E, 23953 }, + { 0x065C, 23957 }, + { 0x065A, 23962 }, + { 0x065B, 23968 }, + { 0x06D0, 23975 }, + { 0x6BE5, 23978 }, + { 0x6BE7, 23983 }, + { 0x6BE6, 23988 }, + { 0x6BE4, 23993 }, + { 0x06C7, 23998 }, + { 0x0677, 24001 }, + { 0x6BDD, 24007 }, + { 0x6BD8, 24015 }, + { 0x6BD7, 24020 }, + { 0x06D5, 24025 }, + { 0x06AD, 24028 }, + { 0x6BD4, 24031 }, + { 0x6BD6, 24036 }, + { 0x6BD5, 24041 }, + { 0x6BD3, 24046 }, + { 0x06C6, 24051 }, + { 0x6BDA, 24054 }, + { 0x6BD9, 24059 }, + { 0x06CB, 24064 }, + { 0x6BDF, 24067 }, + { 0x6BDE, 24072 }, + { 0x06C8, 24077 }, + { 0x6BDC, 24080 }, + { 0x6BDB, 24085 }, + { 0x0639, 24090 }, + { 0x075D, 24093 }, + { 0x075F, 24100 }, + { 0x06A0, 24108 }, + { 0x075E, 24115 }, + { 0x6ECA, 24124 }, + { 0x6ECC, 24129 }, + { 0x6ECB, 24134 }, + { 0x6EC9, 24139 }, + { 0x0628, 24144 }, + { 0x0751, 24147 }, + { 0x0754, 24157 }, + { 0x0756, 24167 }, + { 0x0752, 24173 }, + { 0x0753, 24182 }, + { 0x0750, 24195 }, + { 0x0755, 24203 }, + { 0x6E90, 24211 }, + { 0x6E92, 24216 }, + { 0x6E91, 24221 }, + { 0x6E8F, 24226 }, + { 0x0636, 24231 }, + { 0x06FB, 24234 }, + { 0x6EBE, 24240 }, + { 0x6EC0, 24245 }, + { 0x6EBF, 24250 }, + { 0x6EBD, 24255 }, + { 0x062F, 24260 }, + { 0x068A, 24263 }, + { 0x068B, 24269 }, + { 0x0759, 24278 }, + { 0x0690, 24289 }, + { 0x0689, 24296 }, + { 0x068F, 24301 }, + { 0x06EE, 24309 }, + { 0x075A, 24315 }, + { 0x6EAA, 24323 }, + { 0x6EA9, 24328 }, + { 0x068E, 24333 }, + { 0x6B87, 24336 }, + { 0x6B86, 24341 }, + { 0x0641, 24346 }, + { 0x06A3, 24349 }, + { 0x06A2, 24355 }, + { 0x0760, 24362 }, + { 0x06A5, 24369 }, + { 0x0761, 24376 }, + { 0x6ED2, 24385 }, + { 0x6ED4, 24390 }, + { 0x6ED3, 24395 }, + { 0x6ED1, 24400 }, + { 0x06AF, 24405 }, + { 0x06B2, 24408 }, + { 0x06B0, 24415 }, + { 0x06B4, 24420 }, + { 0x6B93, 24427 }, + { 0x6B95, 24432 }, + { 0x6B94, 24437 }, + { 0x6B92, 24442 }, + { 0x062D, 24447 }, + { 0x0757, 24450 }, + { 0x0682, 24457 }, + { 0x0681, 24465 }, + { 0x076F, 24471 }, + { 0x0772, 24482 }, + { 0x076E, 24491 }, + { 0x0685, 24500 }, + { 0x0758, 24507 }, + { 0x077C, 24516 }, + { 0x6EA2, 24525 }, + { 0x6EA4, 24530 }, + { 0x6EA3, 24535 }, + { 0x6EA1, 24540 }, + { 0x0647, 24545 }, + { 0x06C1, 24548 }, + { 0x06C2, 24552 }, + { 0x6BA7, 24559 }, + { 0x6BA9, 24565 }, + { 0x6BA8, 24571 }, + { 0x6BA6, 24577 }, + { 0x06C0, 24583 }, + { 0x6BA5, 24589 }, + { 0x6BA4, 24597 }, + { 0x06FF, 24605 }, + { 0x6EEA, 24611 }, + { 0x6EEC, 24616 }, + { 0x6EEB, 24621 }, + { 0x6EE9, 24626 }, + { 0x06BE, 24631 }, + { 0x6BAB, 24635 }, + { 0x6BAD, 24641 }, + { 0x6BAC, 24647 }, + { 0x6BAA, 24653 }, + { 0x0698, 24659 }, + { 0x6B8B, 24662 }, + { 0x6B8A, 24667 }, + { 0x0643, 24672 }, + { 0x06AC, 24675 }, + { 0x077F, 24681 }, + { 0x06AB, 24688 }, + { 0x06AE, 24693 }, + { 0x6EDA, 24700 }, + { 0x6EDC, 24705 }, + { 0x6EDB, 24710 }, + { 0x6ED9, 24715 }, + { 0x0644, 24720 }, + { 0x076A, 24723 }, + { 0x06B6, 24728 }, + { 0x06B5, 24734 }, + { 0x06B7, 24740 }, + { 0x06B8, 24747 }, + { 0x6EDE, 24754 }, + { 0x6EE0, 24759 }, + { 0x6EDF, 24764 }, + { 0x6EDD, 24769 }, + { 0x067E, 24774 }, + { 0x6B57, 24777 }, + { 0x6B59, 24782 }, + { 0x6B58, 24787 }, + { 0x6B56, 24792 }, + { 0x0642, 24797 }, + { 0x06A7, 24800 }, + { 0x06A8, 24806 }, + { 0x6ED6, 24813 }, + { 0x6ED8, 24818 }, + { 0x6ED7, 24823 }, + { 0x6ED5, 24828 }, + { 0x0631, 24833 }, + { 0x0694, 24836 }, + { 0x0696, 24842 }, + { 0x0697, 24851 }, + { 0x076B, 24858 }, + { 0x0699, 24866 }, + { 0x0693, 24873 }, + { 0x076C, 24878 }, + { 0x0692, 24884 }, + { 0x0695, 24890 }, + { 0x0771, 24897 }, + { 0x075B, 24908 }, + { 0x06EF, 24913 }, + { 0x6EAE, 24919 }, + { 0x6EAD, 24924 }, + { 0x0635, 24929 }, + { 0x069D, 24932 }, + { 0x069E, 24939 }, + { 0x6EBA, 24946 }, + { 0x6EBC, 24951 }, + { 0x6EBB, 24956 }, + { 0x6EB9, 24961 }, + { 0x0637, 24966 }, + { 0x069F, 24969 }, + { 0x6EC2, 24976 }, + { 0x6EC4, 24981 }, + { 0x6EC3, 24986 }, + { 0x6EC1, 24991 }, + { 0x062A, 24996 }, + { 0x067C, 24999 }, + { 0x067D, 25004 }, + { 0x6E96, 25012 }, + { 0x6E98, 25017 }, + { 0x6E97, 25022 }, + { 0x0629, 25027 }, + { 0x06C3, 25031 }, + { 0x6E94, 25036 }, + { 0x6E93, 25042 }, + { 0x6E95, 25048 }, + { 0x06A4, 25053 }, + { 0x6B6B, 25056 }, + { 0x6B6D, 25061 }, + { 0x6B6C, 25066 }, + { 0x6B6A, 25071 }, + { 0x0648, 25076 }, + { 0x06CF, 25079 }, + { 0x06CA, 25085 }, + { 0x06C4, 25092 }, + { 0x0624, 25097 }, + { 0x6E86, 25103 }, + { 0x6E85, 25111 }, + { 0x0778, 25119 }, + { 0x0779, 25128 }, + { 0x6EEE, 25137 }, + { 0x6EED, 25142 }, + { 0x064A, 25147 }, + { 0x06CD, 25150 }, + { 0x0626, 25155 }, + { 0x6E8A, 25161 }, + { 0x6E8C, 25169 }, + { 0x6E8B, 25177 }, + { 0x6E89, 25185 }, + { 0x06CE, 25193 }, + { 0x06D1, 25199 }, + { 0x6EF2, 25206 }, + { 0x06D2, 25211 }, + { 0x06D3, 25215 }, + { 0x6BB1, 25222 }, + { 0x6BB0, 25231 }, + { 0x077A, 25240 }, + { 0x077B, 25250 }, + { 0x6BAF, 25260 }, + { 0x6BAE, 25266 }, + { 0x6EF4, 25272 }, + { 0x6EF3, 25277 }, + { 0x6EF1, 25282 }, + { 0x0638, 25287 }, + { 0x6EC6, 25290 }, + { 0x6EC8, 25295 }, + { 0x6EC7, 25300 }, + { 0x6EC5, 25305 }, + { 0x0627, 25310 }, + { 0x0672, 25313 }, + { 0x0673, 25320 }, + { 0x0623, 25327 }, + { 0x6E84, 25333 }, + { 0x6E83, 25341 }, + { 0x0625, 25349 }, + { 0x6E88, 25355 }, + { 0x6E87, 25363 }, + { 0x0622, 25371 }, + { 0x6E82, 25377 }, + { 0x6E81, 25385 }, + { 0x0773, 25393 }, + { 0x0774, 25402 }, + { 0x6E8E, 25411 }, + { 0x0671, 25416 }, + { 0x6B51, 25420 }, + { 0x6B50, 25426 }, + { 0x0649, 25432 }, + { 0x6EF0, 25436 }, + { 0x6EEF, 25442 }, + { 0x6E8D, 25448 }, + { 0x067B, 25453 }, + { 0x6B53, 25456 }, + { 0x6B55, 25461 }, + { 0x6B54, 25466 }, + { 0x6B52, 25471 }, + { 0x0688, 25476 }, + { 0x6B89, 25479 }, + { 0x6B88, 25484 }, + { 0x0684, 25489 }, + { 0x6B73, 25492 }, + { 0x6B75, 25497 }, + { 0x6B74, 25502 }, + { 0x6B72, 25507 }, + { 0x06B3, 25512 }, + { 0x6B97, 25515 }, + { 0x6B99, 25520 }, + { 0x6B98, 25525 }, + { 0x6B96, 25530 }, + { 0x0674, 25535 }, + { 0x0676, 25539 }, + { 0x0678, 25544 }, + { 0x0675, 25549 }, + { 0x062C, 25554 }, + { 0x6E9E, 25557 }, + { 0x6EA0, 25562 }, + { 0x6E9F, 25567 }, + { 0x6E9D, 25572 }, + { 0x062E, 25577 }, + { 0x6EA6, 25580 }, + { 0x6EA8, 25585 }, + { 0x6EA7, 25590 }, + { 0x6EA5, 25595 }, + { 0x0645, 25600 }, + { 0x0765, 25603 }, + { 0x0766, 25609 }, + { 0x6EE2, 25615 }, + { 0x6EE4, 25620 }, + { 0x6EE3, 25625 }, + { 0x6EE1, 25630 }, + { 0x0646, 25635 }, + { 0x06B9, 25638 }, + { 0x0767, 25644 }, + { 0x06BC, 25651 }, + { 0x0769, 25656 }, + { 0x0768, 25662 }, + { 0x06BD, 25668 }, + { 0x6EE6, 25675 }, + { 0x06BA, 25680 }, + { 0x6B9F, 25684 }, + { 0x6B9E, 25690 }, + { 0x6EE8, 25696 }, + { 0x6EE7, 25701 }, + { 0x6EE5, 25706 }, + { 0x0683, 25711 }, + { 0x6B77, 25714 }, + { 0x6B79, 25719 }, + { 0x6B78, 25724 }, + { 0x6B76, 25729 }, + { 0x0691, 25734 }, + { 0x6B8D, 25737 }, + { 0x6B8C, 25742 }, + { 0x0633, 25747 }, + { 0x069A, 25750 }, + { 0x076D, 25759 }, + { 0x075C, 25767 }, + { 0x0770, 25774 }, + { 0x069B, 25785 }, + { 0x069C, 25792 }, + { 0x077D, 25803 }, + { 0x077E, 25812 }, + { 0x6EB2, 25818 }, + { 0x6EB4, 25823 }, + { 0x6EB3, 25828 }, + { 0x6EB1, 25833 }, + { 0x0630, 25838 }, + { 0x6EAC, 25841 }, + { 0x6EAB, 25846 }, + { 0x062B, 25851 }, + { 0x6E9A, 25854 }, + { 0x6E9C, 25859 }, + { 0x6E9B, 25864 }, + { 0x6E99, 25869 }, + { 0x0679, 25874 }, + { 0x6B67, 25877 }, + { 0x6B69, 25882 }, + { 0x6B68, 25887 }, + { 0x6B66, 25892 }, + { 0x0632, 25897 }, + { 0x6EB0, 25900 }, + { 0x6EAF, 25905 }, + { 0x0680, 25910 }, + { 0x6B5B, 25913 }, + { 0x6B5D, 25918 }, + { 0x6B5C, 25923 }, + { 0x6B5A, 25928 }, + { 0x068C, 25933 }, + { 0x6B85, 25936 }, + { 0x6B84, 25941 }, + { 0x06CC, 25946 }, + { 0x063E, 25950 }, + { 0x063F, 25958 }, + { 0x0775, 25966 }, + { 0x0777, 25976 }, + { 0x0776, 25986 }, + { 0x063D, 25996 }, + { 0x6BFD, 26003 }, + { 0x6BFF, 26009 }, + { 0x6BFE, 26015 }, + { 0x6BFC, 26021 }, + { 0x063A, 26027 }, + { 0x06FC, 26030 }, + { 0x6ECE, 26036 }, + { 0x6ED0, 26041 }, + { 0x6ECF, 26046 }, + { 0x6ECD, 26051 }, + { 0x0621, 26056 }, + { 0x6E80, 26059 }, + { 0x06A9, 26064 }, + { 0x0762, 26067 }, + { 0x063B, 26073 }, + { 0x0763, 26080 }, + { 0x063C, 26087 }, + { 0x0764, 26094 }, + { 0x6B8F, 26103 }, + { 0x6B91, 26108 }, + { 0x6B90, 26113 }, + { 0x6B8E, 26118 }, + { 0x06B1, 26123 }, + { 0x6B9B, 26126 }, + { 0x6B9D, 26131 }, + { 0x6B9C, 26136 }, + { 0x6B9A, 26141 }, + { 0x06A6, 26146 }, + { 0x6B6F, 26149 }, + { 0x6B71, 26154 }, + { 0x6B70, 26159 }, + { 0x6B6E, 26164 }, + { 0x06BB, 26169 }, + { 0x6BA1, 26172 }, + { 0x6BA3, 26177 }, + { 0x6BA2, 26182 }, + { 0x6BA0, 26187 }, + { 0x0634, 26192 }, + { 0x06FA, 26195 }, + { 0x6EB6, 26201 }, + { 0x6EB8, 26206 }, + { 0x6EB7, 26211 }, + { 0x6EB5, 26216 }, + { 0x06AA, 26221 }, + { 0x0686, 26225 }, + { 0x06BF, 26228 }, + { 0x6B7B, 26234 }, + { 0x6B7D, 26239 }, + { 0x6B7C, 26244 }, + { 0x6B7A, 26249 }, + { 0x067F, 26254 }, + { 0x6B63, 26257 }, + { 0x6B65, 26262 }, + { 0x6B64, 26267 }, + { 0x6B62, 26272 }, + { 0x068D, 26277 }, + { 0x6B83, 26280 }, + { 0x6B82, 26285 }, + { 0x067A, 26290 }, + { 0x6B5F, 26293 }, + { 0x6B61, 26298 }, + { 0x6B60, 26303 }, + { 0x6B5E, 26308 }, + { 0x6BE9, 26313 }, + { 0x6BE8, 26322 }, + { 0x066E, 26331 }, + { 0x06A1, 26335 }, + { 0x066F, 26339 }, + { 0x06C5, 26343 }, + { 0x6BE1, 26347 }, + { 0x6BE0, 26353 }, + { 0x06C9, 26359 }, + { 0x6BE3, 26363 }, + { 0x6BE2, 26369 }, + { 0x0687, 26375 }, + { 0x6B7F, 26378 }, + { 0x6B81, 26383 }, + { 0x6B80, 26388 }, + { 0x6B7E, 26393 }, + { 0x0670, 26398 }, + { 0x0653, 26402 }, + { 0x0600, 26405 }, + { 0x060E, 26408 }, + { 0x0651, 26412 }, + { 0x6E7D, 26414 }, + { 0x6E7C, 26418 }, + { 0x061E, 26422 }, + { 0x066B, 26427 }, + { 0x066A, 26430 }, + { 0x06EC, 26433 }, + { 0x0640, 26440 }, + { 0x6E71, 26442 }, + { 0x064C, 26447 }, + { 0x6E72, 26449 }, + { 0x064B, 26453 }, + { 0x6E70, 26455 }, + { 0x0602, 26459 }, + { 0x0657, 26462 }, + { 0x064D, 26465 }, + { 0x6E74, 26467 }, + { 0x6D14, 26471 }, + { 0x6CF8, 26478 }, + { 0x6D13, 26485 }, + { 0x6CF7, 26493 }, + { 0x6D75, 26501 }, + { 0x6DC4, 26510 }, + { 0x6CBA, 26519 }, + { 0x6C29, 26526 }, + { 0x6DB6, 26533 }, + { 0x6D78, 26542 }, + { 0x6D76, 26552 }, + { 0x6D77, 26561 }, + { 0x6CBB, 26570 }, + { 0x6C2A, 26577 }, + { 0x6DC2, 26584 }, + { 0x6C9D, 26593 }, + { 0x6C06, 26600 }, + { 0x6CE2, 26607 }, + { 0x6CA0, 26614 }, + { 0x6C6A, 26621 }, + { 0x6C6F, 26628 }, + { 0x6C0A, 26635 }, + { 0x6C6E, 26642 }, + { 0x6C09, 26650 }, + { 0x6C9C, 26658 }, + { 0x6C05, 26665 }, + { 0x6D9E, 26672 }, + { 0x6C9E, 26681 }, + { 0x6C07, 26688 }, + { 0x6C6C, 26695 }, + { 0x6CE1, 26702 }, + { 0x6C9F, 26709 }, + { 0x6C08, 26716 }, + { 0x6C6D, 26723 }, + { 0x6C6B, 26730 }, + { 0x6DAB, 26737 }, + { 0x6D6E, 26746 }, + { 0x6CB5, 26756 }, + { 0x6C23, 26763 }, + { 0x6D2C, 26770 }, + { 0x6D10, 26777 }, + { 0x6D24, 26784 }, + { 0x6D08, 26791 }, + { 0x6D23, 26798 }, + { 0x6D07, 26806 }, + { 0x6CB4, 26814 }, + { 0x6C22, 26821 }, + { 0x6D6F, 26828 }, + { 0x6D70, 26837 }, + { 0x6CB6, 26846 }, + { 0x6C24, 26853 }, + { 0x6CB7, 26860 }, + { 0x6C25, 26867 }, + { 0x6CBF, 26874 }, + { 0x6C2E, 26881 }, + { 0x6C7D, 26888 }, + { 0x6C32, 26895 }, + { 0x6C7C, 26902 }, + { 0x6C31, 26910 }, + { 0x6CBE, 26918 }, + { 0x6C2D, 26925 }, + { 0x6D7C, 26932 }, + { 0x6D7D, 26941 }, + { 0x6CC0, 26950 }, + { 0x6C2F, 26957 }, + { 0x6DC1, 26964 }, + { 0x6CC1, 26973 }, + { 0x6C30, 26980 }, + { 0x6D1C, 26987 }, + { 0x6D00, 26994 }, + { 0x6D1B, 27001 }, + { 0x6CFF, 27009 }, + { 0x6DBF, 27017 }, + { 0x6CA9, 27026 }, + { 0x6C17, 27033 }, + { 0x6D5A, 27040 }, + { 0x6D5B, 27049 }, + { 0x6CAA, 27059 }, + { 0x6C18, 27066 }, + { 0x6C54, 27073 }, + { 0x6C53, 27080 }, + { 0x6CD7, 27088 }, + { 0x6C51, 27095 }, + { 0x6D93, 27102 }, + { 0x6D94, 27111 }, + { 0x6CD8, 27120 }, + { 0x6C52, 27127 }, + { 0x6CD9, 27134 }, + { 0x6CC5, 27142 }, + { 0x6C39, 27149 }, + { 0x6C81, 27156 }, + { 0x6CEB, 27163 }, + { 0x6CC7, 27170 }, + { 0x6C3B, 27177 }, + { 0x6C84, 27184 }, + { 0x6C3E, 27191 }, + { 0x6C80, 27198 }, + { 0x6C83, 27205 }, + { 0x6C3D, 27213 }, + { 0x6C37, 27221 }, + { 0x6CC4, 27228 }, + { 0x6C38, 27235 }, + { 0x6CC6, 27242 }, + { 0x6C3A, 27249 }, + { 0x6DB7, 27256 }, + { 0x6DBB, 27265 }, + { 0x6DC3, 27274 }, + { 0x6C82, 27283 }, + { 0x6CEC, 27290 }, + { 0x6CC8, 27297 }, + { 0x6C3C, 27304 }, + { 0x6D81, 27311 }, + { 0x6D82, 27320 }, + { 0x6D80, 27330 }, + { 0x6DB5, 27339 }, + { 0x6CCA, 27348 }, + { 0x6C40, 27355 }, + { 0x6CCD, 27362 }, + { 0x6C87, 27369 }, + { 0x6C44, 27376 }, + { 0x6EF8, 27383 }, + { 0x6EF7, 27393 }, + { 0x6EFA, 27403 }, + { 0x6EF9, 27413 }, + { 0x6EF6, 27423 }, + { 0x6EF5, 27433 }, + { 0x6EFC, 27443 }, + { 0x6C86, 27450 }, + { 0x6C43, 27458 }, + { 0x6EFB, 27466 }, + { 0x6DAC, 27473 }, + { 0x6D84, 27482 }, + { 0x6D83, 27491 }, + { 0x6DBC, 27500 }, + { 0x6DBA, 27509 }, + { 0x6CC9, 27518 }, + { 0x6C3F, 27525 }, + { 0x6D85, 27532 }, + { 0x6D86, 27541 }, + { 0x6CCB, 27550 }, + { 0x6C41, 27557 }, + { 0x6D87, 27564 }, + { 0x6D88, 27573 }, + { 0x6DAD, 27582 }, + { 0x6C85, 27591 }, + { 0x6CED, 27598 }, + { 0x6CCC, 27605 }, + { 0x6C42, 27612 }, + { 0x6CC2, 27619 }, + { 0x6C33, 27626 }, + { 0x6C7F, 27633 }, + { 0x6C36, 27640 }, + { 0x6C7E, 27647 }, + { 0x6C35, 27655 }, + { 0x6D7E, 27663 }, + { 0x6DB4, 27672 }, + { 0x6DB2, 27681 }, + { 0x6D7F, 27690 }, + { 0x6CC3, 27699 }, + { 0x6C34, 27706 }, + { 0x6C5C, 27713 }, + { 0x6D64, 27721 }, + { 0x6D65, 27730 }, + { 0x6DA9, 27739 }, + { 0x6CB1, 27748 }, + { 0x6C20, 27755 }, + { 0x6D2B, 27762 }, + { 0x6D0F, 27769 }, + { 0x6D22, 27776 }, + { 0x6D06, 27783 }, + { 0x6D21, 27790 }, + { 0x6D05, 27798 }, + { 0x6CB2, 27806 }, + { 0x6D66, 27813 }, + { 0x6DC5, 27822 }, + { 0x6CB3, 27831 }, + { 0x6C21, 27838 }, + { 0x6CB8, 27845 }, + { 0x6C26, 27852 }, + { 0x6D12, 27859 }, + { 0x6CF6, 27866 }, + { 0x6D11, 27873 }, + { 0x6CF5, 27881 }, + { 0x6D71, 27889 }, + { 0x6D72, 27898 }, + { 0x6D74, 27907 }, + { 0x6D73, 27916 }, + { 0x6D3A, 27925 }, + { 0x6D33, 27932 }, + { 0x6C27, 27939 }, + { 0x6D51, 27946 }, + { 0x6D52, 27955 }, + { 0x6D53, 27964 }, + { 0x6CA2, 27973 }, + { 0x6C0C, 27980 }, + { 0x6CE4, 27987 }, + { 0x6CA5, 27994 }, + { 0x6C70, 28001 }, + { 0x6C75, 28008 }, + { 0x6C10, 28015 }, + { 0x6C74, 28022 }, + { 0x6C0F, 28030 }, + { 0x6D9F, 28038 }, + { 0x6DA0, 28047 }, + { 0x6D50, 28057 }, + { 0x6CA1, 28066 }, + { 0x6C0B, 28073 }, + { 0x6DA1, 28080 }, + { 0x6DA2, 28089 }, + { 0x6D54, 28099 }, + { 0x6CA3, 28108 }, + { 0x6C0D, 28115 }, + { 0x6D56, 28122 }, + { 0x6DA3, 28131 }, + { 0x6DA4, 28140 }, + { 0x6D55, 28150 }, + { 0x6D57, 28159 }, + { 0x6C72, 28168 }, + { 0x6CE3, 28175 }, + { 0x6CA4, 28182 }, + { 0x6C0E, 28189 }, + { 0x6C73, 28196 }, + { 0x6C71, 28203 }, + { 0x6DAE, 28210 }, + { 0x6CDB, 28219 }, + { 0x6C56, 28226 }, + { 0x6CF1, 28233 }, + { 0x6CDE, 28240 }, + { 0x6C91, 28247 }, + { 0x6C96, 28254 }, + { 0x6C5A, 28261 }, + { 0x6C95, 28268 }, + { 0x6C59, 28276 }, + { 0x6DAF, 28284 }, + { 0x6CDA, 28293 }, + { 0x6C55, 28300 }, + { 0x6CDC, 28307 }, + { 0x6C57, 28314 }, + { 0x6DB0, 28321 }, + { 0x6D9C, 28330 }, + { 0x6D9D, 28339 }, + { 0x6C93, 28348 }, + { 0x6CF0, 28355 }, + { 0x6CDD, 28362 }, + { 0x6C58, 28369 }, + { 0x6C94, 28376 }, + { 0x6C92, 28383 }, + { 0x6BF7, 28390 }, + { 0x6BF8, 28400 }, + { 0x6BF6, 28410 }, + { 0x6BF1, 28420 }, + { 0x6BF0, 28430 }, + { 0x6BED, 28440 }, + { 0x6BEC, 28450 }, + { 0x6BF3, 28460 }, + { 0x6BF2, 28470 }, + { 0x6BF5, 28480 }, + { 0x6BF4, 28490 }, + { 0x6C98, 28500 }, + { 0x6C01, 28510 }, + { 0x6CE0, 28520 }, + { 0x6C9B, 28530 }, + { 0x6C64, 28540 }, + { 0x6BEF, 28550 }, + { 0x6BEE, 28560 }, + { 0x6C69, 28570 }, + { 0x6C04, 28580 }, + { 0x6BEB, 28590 }, + { 0x6C68, 28600 }, + { 0x6C03, 28611 }, + { 0x6BEA, 28622 }, + { 0x6C97, 28632 }, + { 0x6C00, 28642 }, + { 0x6C99, 28652 }, + { 0x6C66, 28662 }, + { 0x6CDF, 28672 }, + { 0x6C9A, 28682 }, + { 0x6C02, 28692 }, + { 0x6C67, 28702 }, + { 0x6C65, 28712 }, + { 0x6D3B, 28722 }, + { 0x6CB9, 28729 }, + { 0x6C28, 28736 }, + { 0x6D3C, 28743 }, + { 0x6D3D, 28750 }, + { 0x6C90, 28757 }, + { 0x6C5D, 28766 }, + { 0x6DBE, 28775 }, + { 0x6DA6, 28784 }, + { 0x6CA7, 28794 }, + { 0x6C15, 28801 }, + { 0x6D1E, 28808 }, + { 0x6D02, 28815 }, + { 0x6D1D, 28822 }, + { 0x6D01, 28830 }, + { 0x6D58, 28838 }, + { 0x6D59, 28847 }, + { 0x6DA5, 28856 }, + { 0x6DA7, 28865 }, + { 0x6CA8, 28875 }, + { 0x6C16, 28882 }, + { 0x6C1A, 28889 }, + { 0x6D20, 28896 }, + { 0x6D04, 28903 }, + { 0x6D1F, 28910 }, + { 0x6D03, 28918 }, + { 0x6CAB, 28926 }, + { 0x6C19, 28933 }, + { 0x6CAC, 28940 }, + { 0x6C1B, 28947 }, + { 0x6D8B, 28954 }, + { 0x6D89, 28963 }, + { 0x6D8A, 28972 }, + { 0x6CCF, 28981 }, + { 0x6C46, 28988 }, + { 0x6C4A, 28995 }, + { 0x6C88, 29002 }, + { 0x6C49, 29009 }, + { 0x6D8C, 29017 }, + { 0x6DC0, 29026 }, + { 0x6D92, 29035 }, + { 0x6D8D, 29044 }, + { 0x6CCE, 29053 }, + { 0x6C45, 29060 }, + { 0x6DB9, 29067 }, + { 0x6D8E, 29076 }, + { 0x6D8F, 29085 }, + { 0x6CD0, 29094 }, + { 0x6C47, 29101 }, + { 0x6DB1, 29108 }, + { 0x6C89, 29117 }, + { 0x6CD1, 29124 }, + { 0x6C48, 29131 }, + { 0x6DB3, 29138 }, + { 0x6D96, 29147 }, + { 0x6D95, 29157 }, + { 0x6CD3, 29166 }, + { 0x6C4C, 29173 }, + { 0x6CEF, 29180 }, + { 0x6CD6, 29187 }, + { 0x6C8A, 29194 }, + { 0x6C8F, 29201 }, + { 0x6C50, 29208 }, + { 0x6C8E, 29215 }, + { 0x6C4F, 29223 }, + { 0x6DBD, 29231 }, + { 0x6DB8, 29240 }, + { 0x6DC7, 29249 }, + { 0x6D99, 29258 }, + { 0x6D97, 29268 }, + { 0x6D98, 29277 }, + { 0x6CD2, 29286 }, + { 0x6C4B, 29293 }, + { 0x6CD4, 29300 }, + { 0x6C4D, 29307 }, + { 0x6D9A, 29314 }, + { 0x6D9B, 29323 }, + { 0x6C8C, 29333 }, + { 0x6CEE, 29340 }, + { 0x6CD5, 29347 }, + { 0x6C4E, 29354 }, + { 0x6C8D, 29361 }, + { 0x6C8B, 29368 }, + { 0x6DF1, 29375 }, + { 0x6D5C, 29385 }, + { 0x6D35, 29394 }, + { 0x6CAE, 29401 }, + { 0x6C1D, 29408 }, + { 0x6CE8, 29415 }, + { 0x6D31, 29422 }, + { 0x6D2A, 29429 }, + { 0x6D0E, 29436 }, + { 0x6D18, 29443 }, + { 0x6CFC, 29450 }, + { 0x6D17, 29457 }, + { 0x6CFB, 29465 }, + { 0x6D5D, 29473 }, + { 0x6D5E, 29482 }, + { 0x6D34, 29492 }, + { 0x6CAD, 29499 }, + { 0x6C1C, 29506 }, + { 0x6DC6, 29513 }, + { 0x6DA8, 29522 }, + { 0x6D36, 29532 }, + { 0x6CAF, 29539 }, + { 0x6C1E, 29546 }, + { 0x6D5F, 29553 }, + { 0x6D60, 29562 }, + { 0x6D61, 29571 }, + { 0x6D62, 29580 }, + { 0x6D63, 29589 }, + { 0x6CE7, 29598 }, + { 0x6CB0, 29605 }, + { 0x6C1F, 29612 }, + { 0x6C5B, 29619 }, + { 0x6CE6, 29627 }, + { 0x6C76, 29634 }, + { 0x6C7B, 29641 }, + { 0x6C14, 29648 }, + { 0x6C7A, 29655 }, + { 0x6C13, 29663 }, + { 0x6C11, 29671 }, + { 0x6C78, 29678 }, + { 0x6CE5, 29685 }, + { 0x6CA6, 29692 }, + { 0x6C12, 29699 }, + { 0x6C79, 29706 }, + { 0x6C77, 29713 }, + { 0x6DF3, 29720 }, + { 0x6DF2, 29725 }, + { 0x6D16, 29730 }, + { 0x6CFA, 29737 }, + { 0x6D15, 29744 }, + { 0x6CF9, 29752 }, + { 0x6CBC, 29760 }, + { 0x6C2B, 29767 }, + { 0x6D7A, 29774 }, + { 0x6D7B, 29783 }, + { 0x6D79, 29793 }, + { 0x6CBD, 29802 }, + { 0x6C2C, 29809 }, + { 0x6DF5, 29816 }, + { 0x6DF0, 29821 }, + { 0x6DF9, 29831 }, + { 0x6DAA, 29836 }, + { 0x6D67, 29845 }, + { 0x6D68, 29854 }, + { 0x6D26, 29863 }, + { 0x6D38, 29870 }, + { 0x6D2E, 29877 }, + { 0x6D0A, 29884 }, + { 0x6CEA, 29891 }, + { 0x6D32, 29898 }, + { 0x6D29, 29905 }, + { 0x6D0D, 29912 }, + { 0x6D1A, 29919 }, + { 0x6CFE, 29926 }, + { 0x6D19, 29933 }, + { 0x6CFD, 29941 }, + { 0x6D69, 29949 }, + { 0x6D25, 29958 }, + { 0x6D37, 29965 }, + { 0x6D2D, 29972 }, + { 0x6D09, 29979 }, + { 0x6D27, 29986 }, + { 0x6D39, 29993 }, + { 0x6D2F, 30000 }, + { 0x6D0B, 30007 }, + { 0x6D6A, 30014 }, + { 0x6D6B, 30023 }, + { 0x6D6C, 30032 }, + { 0x6D6D, 30041 }, + { 0x6D28, 30050 }, + { 0x6CE9, 30057 }, + { 0x6D30, 30064 }, + { 0x6D0C, 30071 }, + { 0x6DF7, 30078 }, + { 0x6DF6, 30083 }, + { 0x6CF3, 30088 }, + { 0x6C61, 30095 }, + { 0x6CF2, 30102 }, + { 0x6C60, 30109 }, + { 0x6CF4, 30116 }, + { 0x6C62, 30123 }, + { 0x6C5E, 30130 }, + { 0x6C5F, 30137 }, + { 0x6C63, 30144 }, + { 0x6BFA, 30152 }, + { 0x6BFB, 30165 }, + { 0x6BF9, 30178 }, + { 0x6DF4, 30191 }, + { 0x6DF8, 30196 }, + { 0x6DFD, 30201 }, + { 0x6DFA, 30206 }, + { 0x6DFB, 30211 }, + { 0x061F, 30214 }, + { 0x065D, 30217 }, + { 0x0659, 30220 }, + { 0x061B, 30222 }, + { 0x0656, 30224 }, + { 0x066C, 30227 }, + { 0x2717, 30230 }, + { 0x2610, 30232 }, + { 0x2612, 30234 }, + { 0x2611, 30238 }, + { 0x266B, 30242 }, + { 0x266C, 30245 }, + { 0x293B, 30248 }, + { 0x2321, 30252 }, + { 0x230D, 30255 }, + { 0x2E24, 30258 }, + { 0x231E, 30262 }, + { 0x23DF, 30265 }, + { 0x230C, 30268 }, + { 0x2E25, 30271 }, + { 0x231F, 30275 }, + { 0x23B5, 30278 }, + { 0x23B6, 30281 }, + { 0x23E1, 30288 }, + { 0x23DD, 30292 }, + { 0x22C8, 30294 }, + { 0x29D1, 30295 }, + { 0x29D2, 30300 }, + { 0x00A6, 30305 }, + { 0x238B, 30307 }, + { 0x2022, 30312 }, + { 0x2219, 30313 }, + { 0xC07F, 30315 }, + { 0x264B, 30317 }, + { 0x72A0, 30318 }, + { 0x72A9, 30321 }, + { 0x72A2, 30324 }, + { 0x72BA, 30327 }, + { 0x72C0, 30330 }, + { 0x72B9, 30333 }, + { 0x72BC, 30336 }, + { 0x72A3, 30339 }, + { 0x72AA, 30342 }, + { 0x72B5, 30345 }, + { 0x72AB, 30348 }, + { 0x72B7, 30351 }, + { 0x72A8, 30354 }, + { 0x72A5, 30357 }, + { 0x72B0, 30360 }, + { 0x72AD, 30363 }, + { 0x72B2, 30366 }, + { 0x72B4, 30369 }, + { 0x72A7, 30372 }, + { 0x72AC, 30375 }, + { 0x72CF, 30378 }, + { 0x72C1, 30381 }, + { 0x72C5, 30384 }, + { 0x72BD, 30387 }, + { 0x72A6, 30390 }, + { 0x72CA, 30393 }, + { 0x72BE, 30396 }, + { 0x72C4, 30399 }, + { 0x72B3, 30402 }, + { 0x72A1, 30405 }, + { 0x72C9, 30408 }, + { 0x72AE, 30411 }, + { 0x72B8, 30414 }, + { 0x72C2, 30417 }, + { 0x72C7, 30420 }, + { 0x72BF, 30423 }, + { 0x72CE, 30426 }, + { 0x72CB, 30429 }, + { 0x72CC, 30432 }, + { 0x72CD, 30435 }, + { 0x72AF, 30438 }, + { 0x72C3, 30441 }, + { 0x72B6, 30444 }, + { 0x72A4, 30447 }, + { 0x72B1, 30450 }, + { 0x72C6, 30453 }, + { 0x72C8, 30456 }, + { 0x72D0, 30459 }, + { 0x72BB, 30462 }, + { 0x2104, 30465 }, + { 0x26B7, 30468 }, + { 0x25D5, 30469 }, + { 0x29C3, 30477 }, + { 0x25D0, 30485 }, + { 0x25D2, 30490 }, + { 0x25D1, 30495 }, + { 0x29C2, 30500 }, + { 0x25D3, 30507 }, + { 0x25D4, 30512 }, + { 0x25CD, 30518 }, + { 0x29B5, 30522 }, + { 0x29BB, 30526 }, + { 0x29BA, 30530 }, + { 0x2A4C, 30542 }, + { 0x2A50, 30546 }, + { 0x2ACF, 30553 }, + { 0x2AD1, 30555 }, + { 0x2AD0, 30560 }, + { 0x2AD2, 30562 }, + { 0x2A4D, 30567 }, + { 0x26B0, 30571 }, + { 0x2CF9, 30572 }, + { 0x2CFC, 30577 }, + { 0x2CFA, 30582 }, + { 0x2CFB, 30588 }, + { 0x2CFE, 30594 }, + { 0x2C9F, 30597 }, + { 0x2CAB, 30601 }, + { 0x2C99, 30605 }, + { 0x2C9B, 30609 }, + { 0x2CA1, 30613 }, + { 0x2CA3, 30617 }, + { 0x2CA9, 30621 }, + { 0x03EF, 30625 }, + { 0x2C89, 30629 }, + { 0x03E5, 30633 }, + { 0x2CAD, 30637 }, + { 0x2C9D, 30641 }, + { 0x2CCF, 30645 }, + { 0x2CB5, 30651 }, + { 0x2CD9, 30657 }, + { 0x2CC7, 30663 }, + { 0x2CD5, 30669 }, + { 0x2CD3, 30675 }, + { 0x2CBF, 30681 }, + { 0x2CCD, 30687 }, + { 0x2CC5, 30693 }, + { 0x2CDB, 30699 }, + { 0x2CD7, 30705 }, + { 0x2CDF, 30711 }, + { 0x2CE1, 30717 }, + { 0x2CE3, 30723 }, + { 0x2CDD, 30729 }, + { 0x2CB1, 30735 }, + { 0x2CAF, 30739 }, + { 0x2C8B, 30743 }, + { 0x2CA7, 30747 }, + { 0x2C81, 30751 }, + { 0x2C8F, 30755 }, + { 0x03E9, 30759 }, + { 0x2C95, 30763 }, + { 0x03E7, 30767 }, + { 0x03E3, 30771 }, + { 0x2CA5, 30775 }, + { 0x2C83, 30779 }, + { 0x2C8D, 30783 }, + { 0x2C87, 30787 }, + { 0x2C85, 30791 }, + { 0x2C93, 30795 }, + { 0x2C97, 30799 }, + { 0x2CC1, 30803 }, + { 0x03ED, 30807 }, + { 0x03EB, 30811 }, + { 0x2C91, 30815 }, + { 0x2CC3, 30819 }, + { 0x2CC9, 30824 }, + { 0x2CD1, 30829 }, + { 0x2CBB, 30834 }, + { 0x2CB3, 30839 }, + { 0x2CCB, 30844 }, + { 0x2CB9, 30849 }, + { 0x2CBD, 30854 }, + { 0x2CB7, 30859 }, + { 0x2CE5, 30864 }, + { 0x2CE6, 30868 }, + { 0x2CE4, 30872 }, + { 0x2CE9, 30875 }, + { 0x2CE8, 30879 }, + { 0x2CEA, 30883 }, + { 0x2CE7, 30887 }, + { 0x2C9E, 30890 }, + { 0x2CAA, 30894 }, + { 0x2C98, 30898 }, + { 0x2C9A, 30902 }, + { 0x2CA0, 30906 }, + { 0x2CA2, 30910 }, + { 0x2CA8, 30914 }, + { 0x03EE, 30918 }, + { 0x2C88, 30922 }, + { 0x03E4, 30926 }, + { 0x2CAC, 30930 }, + { 0x2C9C, 30934 }, + { 0x2CCE, 30938 }, + { 0x2CB4, 30944 }, + { 0x2CD8, 30950 }, + { 0x2CC6, 30956 }, + { 0x2CD4, 30962 }, + { 0x2CD2, 30968 }, + { 0x2CBE, 30974 }, + { 0x2CCC, 30980 }, + { 0x2CC4, 30986 }, + { 0x2CDA, 30992 }, + { 0x2CD6, 30998 }, + { 0x2CDE, 31004 }, + { 0x2CE0, 31010 }, + { 0x2CE2, 31016 }, + { 0x2CDC, 31022 }, + { 0x2CB0, 31028 }, + { 0x2CAE, 31032 }, + { 0x2C8A, 31036 }, + { 0x2CA6, 31040 }, + { 0x2C80, 31044 }, + { 0x2C8E, 31048 }, + { 0x03E8, 31052 }, + { 0x2C94, 31056 }, + { 0x03E6, 31060 }, + { 0x03E2, 31064 }, + { 0x2CA4, 31068 }, + { 0x2C82, 31072 }, + { 0x2C8C, 31076 }, + { 0x2C86, 31080 }, + { 0x2C84, 31084 }, + { 0x2C92, 31088 }, + { 0x2C96, 31092 }, + { 0x2CC0, 31096 }, + { 0x03EC, 31100 }, + { 0x03EA, 31104 }, + { 0x2C90, 31108 }, + { 0x2CC2, 31112 }, + { 0x2CC8, 31117 }, + { 0x2CD0, 31122 }, + { 0x2CBA, 31127 }, + { 0x2CB2, 31132 }, + { 0x2CCA, 31137 }, + { 0x2CB8, 31142 }, + { 0x2CBC, 31147 }, + { 0x2CB6, 31152 }, + { 0x2CFD, 31157 }, + { 0x2CFF, 31161 }, + { 0x2761, 31164 }, + { 0x2020, 31169 }, + { 0x6E4D, 31170 }, + { 0x6E49, 31173 }, + { 0x279F, 31175 }, + { 0x00B0, 31179 }, + { 0x2103, 31181 }, + { 0x2109, 31183 }, + { 0x9305, 31185 }, + { 0x9302, 31188 }, + { 0x268D, 31192 }, + { 0x268E, 31196 }, + { 0x9304, 31200 }, + { 0x9303, 31204 }, + { 0x268F, 31208 }, + { 0x268C, 31212 }, + { 0x9301, 31216 }, + { 0x2393, 31220 }, + { 0x0024, 31225 }, + { 0xA062, 31227 }, + { 0xA030, 31231 }, + { 0xA063, 31235 }, + { 0xA064, 31238 }, + { 0xA065, 31241 }, + { 0xA066, 31244 }, + { 0xA067, 31247 }, + { 0xA068, 31250 }, + { 0xA069, 31253 }, + { 0xA06A, 31256 }, + { 0xA06B, 31259 }, + { 0xA06C, 31262 }, + { 0xA06D, 31265 }, + { 0xA06E, 31268 }, + { 0xA06F, 31271 }, + { 0xA070, 31274 }, + { 0xA071, 31277 }, + { 0xA072, 31280 }, + { 0xA073, 31283 }, + { 0xA074, 31286 }, + { 0xA075, 31289 }, + { 0xA076, 31292 }, + { 0xA077, 31295 }, + { 0xA078, 31298 }, + { 0xA079, 31301 }, + { 0xA07A, 31304 }, + { 0xA07B, 31307 }, + { 0xA07C, 31310 }, + { 0xA07D, 31313 }, + { 0xA07E, 31316 }, + { 0xA07F, 31319 }, + { 0xA080, 31322 }, + { 0xA081, 31325 }, + { 0xA082, 31328 }, + { 0xA083, 31331 }, + { 0xA084, 31334 }, + { 0xA085, 31337 }, + { 0xA086, 31340 }, + { 0xA087, 31343 }, + { 0xA088, 31346 }, + { 0xA089, 31349 }, + { 0xA08A, 31352 }, + { 0xA08B, 31355 }, + { 0xA08C, 31358 }, + { 0xA08D, 31361 }, + { 0xA08E, 31364 }, + { 0xA08F, 31367 }, + { 0xA090, 31370 }, + { 0xA091, 31373 }, + { 0xA092, 31376 }, + { 0xA093, 31379 }, + { 0xA031, 31382 }, + { 0xA032, 31385 }, + { 0xA033, 31388 }, + { 0xA034, 31391 }, + { 0xA035, 31394 }, + { 0xA036, 31397 }, + { 0xA037, 31400 }, + { 0xA038, 31403 }, + { 0xA039, 31406 }, + { 0xA03A, 31409 }, + { 0xA03B, 31412 }, + { 0xA03C, 31415 }, + { 0xA03D, 31418 }, + { 0xA03E, 31421 }, + { 0xA03F, 31424 }, + { 0xA040, 31427 }, + { 0xA041, 31430 }, + { 0xA042, 31433 }, + { 0xA043, 31436 }, + { 0xA044, 31439 }, + { 0xA045, 31442 }, + { 0xA046, 31445 }, + { 0xA047, 31448 }, + { 0xA048, 31451 }, + { 0xA049, 31454 }, + { 0xA04A, 31457 }, + { 0xA04B, 31460 }, + { 0xA04C, 31463 }, + { 0xA04D, 31466 }, + { 0xA04E, 31469 }, + { 0xA04F, 31472 }, + { 0xA050, 31475 }, + { 0xA051, 31478 }, + { 0xA052, 31481 }, + { 0xA053, 31484 }, + { 0xA054, 31487 }, + { 0xA055, 31490 }, + { 0xA056, 31493 }, + { 0xA057, 31496 }, + { 0xA058, 31499 }, + { 0xA059, 31502 }, + { 0xA05A, 31505 }, + { 0xA05B, 31508 }, + { 0xA05C, 31511 }, + { 0xA05D, 31514 }, + { 0xA05E, 31517 }, + { 0xA05F, 31520 }, + { 0xA060, 31523 }, + { 0xA061, 31526 }, + { 0x205C, 31529 }, + { 0x2999, 31531 }, + { 0x25CC, 31533 }, + { 0x2E13, 31535 }, + { 0x2B1A, 31537 }, + { 0x2E08, 31539 }, + { 0x2E16, 31542 }, + { 0x2AEB, 31545 }, + { 0x2017, 31548 }, + { 0x2AEA, 31551 }, + { 0x2995, 31554 }, + { 0x29FA, 31559 }, + { 0x6E4C, 31561 }, + { 0x02DD, 31564 }, + { 0x2A74, 31567 }, + { 0x201E, 31570 }, + { 0x2033, 31574 }, + { 0x301E, 31576 }, + { 0x2996, 31580 }, + { 0x22D3, 31585 }, + { 0x2021, 31587 }, + { 0x2AA1, 31589 }, + { 0x2AA3, 31592 }, + { 0x2AA2, 31597 }, + { 0x2A4F, 31600 }, + { 0x2A4E, 31603 }, + { 0x2AEC, 31606 }, + { 0x22D0, 31610 }, + { 0x24F5, 31612 }, + { 0x24FA, 31616 }, + { 0x24F6, 31620 }, + { 0x24F9, 31624 }, + { 0x24F8, 31628 }, + { 0x24FD, 31632 }, + { 0x24FC, 31636 }, + { 0x24FB, 31640 }, + { 0x24F7, 31644 }, + { 0x24FE, 31648 }, + { 0x2A54, 31652 }, + { 0x2A53, 31655 }, + { 0x2E17, 31658 }, + { 0x2AFD, 31661 }, + { 0x222C, 31664 }, + { 0x2ABB, 31666 }, + { 0x2047, 31668 }, + { 0x2ABC, 31671 }, + { 0x22D1, 31673 }, + { 0x2AE3, 31675 }, + { 0x2AE5, 31680 }, + { 0x22AB, 31686 }, + { 0x2016, 31692 }, + { 0x203C, 31695 }, + { 0x22D2, 31698 }, + { 0x201F, 31700 }, + { 0x266A, 31704 }, + { 0x003D, 31706 }, + { 0x29E3, 31708 }, + { 0x29E4, 31713 }, + { 0x2A66, 31721 }, + { 0x2A77, 31726 }, + { 0x2AAE, 31736 }, + { 0x2A71, 31741 }, + { 0x2A73, 31746 }, + { 0x2B40, 31751 }, + { 0x2971, 31756 }, + { 0x2A6E, 31761 }, + { 0x2255, 31764 }, + { 0x2239, 31766 }, + { 0x2640, 31767 }, + { 0x2012, 31769 }, + { 0x2007, 31771 }, + { 0x2A0D, 31773 }, + { 0x2766, 31776 }, + { 0x2698, 31778 }, + { 0x2055, 31779 }, + { 0x22A9, 31782 }, + { 0x2E10, 31783 }, + { 0x221C, 31785 }, + { 0x20A3, 31787 }, + { 0x264A, 31790 }, + { 0x20B0, 31791 }, + { 0x29E6, 31794 }, + { 0x7339, 31796 }, + { 0x733E, 31799 }, + { 0x7330, 31802 }, + { 0x7333, 31805 }, + { 0x7332, 31808 }, + { 0x7337, 31811 }, + { 0x7336, 31814 }, + { 0x734A, 31817 }, + { 0x733F, 31821 }, + { 0x7346, 31824 }, + { 0x7348, 31827 }, + { 0x7347, 31830 }, + { 0x733A, 31833 }, + { 0x733B, 31836 }, + { 0x733C, 31839 }, + { 0x7349, 31842 }, + { 0x7342, 31845 }, + { 0x7343, 31848 }, + { 0x7344, 31851 }, + { 0x7345, 31854 }, + { 0x7334, 31857 }, + { 0x733D, 31860 }, + { 0x7341, 31863 }, + { 0x7338, 31866 }, + { 0x7331, 31869 }, + { 0x7340, 31872 }, + { 0x7335, 31875 }, + { 0x2692, 31878 }, + { 0x262D, 31881 }, + { 0x302F, 31884 }, + { 0x3164, 31889 }, + { 0x314F, 31891 }, + { 0x3154, 31894 }, + { 0x3163, 31897 }, + { 0x3157, 31900 }, + { 0x315C, 31903 }, + { 0x3150, 31906 }, + { 0x3153, 31909 }, + { 0x3161, 31912 }, + { 0x315A, 31915 }, + { 0x3158, 31918 }, + { 0x315E, 31921 }, + { 0x315F, 31924 }, + { 0x3151, 31927 }, + { 0x3156, 31930 }, + { 0x3162, 31933 }, + { 0x315B, 31936 }, + { 0x3160, 31939 }, + { 0x3159, 31942 }, + { 0x315D, 31945 }, + { 0x3152, 31948 }, + { 0x3155, 31951 }, + { 0x3145, 31954 }, + { 0x3189, 31957 }, + { 0x318C, 31960 }, + { 0x318D, 31963 }, + { 0x3148, 31966 }, + { 0x314E, 31969 }, + { 0x3147, 31972 }, + { 0x3141, 31975 }, + { 0x3134, 31978 }, + { 0x3142, 31981 }, + { 0x3139, 31984 }, + { 0x3187, 31987 }, + { 0x318B, 31990 }, + { 0x318E, 31993 }, + { 0x3131, 31996 }, + { 0x3137, 31999 }, + { 0x3188, 32002 }, + { 0x318A, 32005 }, + { 0x314A, 32008 }, + { 0x314B, 32011 }, + { 0x317F, 32014 }, + { 0x314D, 32017 }, + { 0x314C, 32020 }, + { 0x3181, 32023 }, + { 0x3146, 32026 }, + { 0x316F, 32029 }, + { 0x3167, 32032 }, + { 0x3144, 32035 }, + { 0x313D, 32038 }, + { 0x317E, 32041 }, + { 0x317B, 32044 }, + { 0x317D, 32047 }, + { 0x3149, 32050 }, + { 0x3185, 32053 }, + { 0x3180, 32056 }, + { 0x3165, 32059 }, + { 0x3143, 32062 }, + { 0x3133, 32065 }, + { 0x316E, 32068 }, + { 0x3135, 32071 }, + { 0x3136, 32074 }, + { 0x3176, 32077 }, + { 0x3140, 32080 }, + { 0x313B, 32083 }, + { 0x313C, 32086 }, + { 0x317A, 32089 }, + { 0x317C, 32092 }, + { 0x3132, 32095 }, + { 0x3138, 32098 }, + { 0x3186, 32101 }, + { 0x3166, 32104 }, + { 0x3172, 32107 }, + { 0x3173, 32110 }, + { 0x313A, 32113 }, + { 0x316A, 32116 }, + { 0x3171, 32119 }, + { 0x3178, 32122 }, + { 0x3170, 32125 }, + { 0x3168, 32128 }, + { 0x3177, 32131 }, + { 0x316C, 32134 }, + { 0x313F, 32137 }, + { 0x313E, 32140 }, + { 0x3182, 32143 }, + { 0x3184, 32146 }, + { 0x316B, 32149 }, + { 0x3183, 32152 }, + { 0x3174, 32155 }, + { 0x3175, 32158 }, + { 0x3169, 32161 }, + { 0x316D, 32164 }, + { 0x3179, 32167 }, + { 0x302E, 32170 }, + { 0x1109, 32175 }, + { 0x110C, 32178 }, + { 0x1112, 32181 }, + { 0x110B, 32184 }, + { 0x1106, 32187 }, + { 0x1102, 32190 }, + { 0x1107, 32193 }, + { 0x1105, 32196 }, + { 0x115F, 32199 }, + { 0x1100, 32202 }, + { 0x1103, 32205 }, + { 0x110E, 32208 }, + { 0x110F, 32211 }, + { 0x1140, 32214 }, + { 0x1111, 32217 }, + { 0x1110, 32220 }, + { 0x114C, 32223 }, + { 0x110A, 32226 }, + { 0x1145, 32229 }, + { 0x1121, 32232 }, + { 0x1136, 32235 }, + { 0x113B, 32238 }, + { 0x1135, 32241 }, + { 0x1131, 32244 }, + { 0x112E, 32247 }, + { 0x1132, 32250 }, + { 0x1130, 32253 }, + { 0x110D, 32256 }, + { 0x1158, 32259 }, + { 0x1147, 32262 }, + { 0x1114, 32265 }, + { 0x1108, 32268 }, + { 0x1119, 32271 }, + { 0x114D, 32274 }, + { 0x1148, 32277 }, + { 0x1143, 32280 }, + { 0x1144, 32283 }, + { 0x111C, 32286 }, + { 0x1116, 32289 }, + { 0x1127, 32292 }, + { 0x111F, 32295 }, + { 0x111A, 32298 }, + { 0x1118, 32301 }, + { 0x112D, 32304 }, + { 0x112F, 32307 }, + { 0x1101, 32310 }, + { 0x1104, 32313 }, + { 0x1159, 32316 }, + { 0x113C, 32319 }, + { 0x1141, 32322 }, + { 0x1142, 32325 }, + { 0x1113, 32328 }, + { 0x1115, 32331 }, + { 0x111E, 32334 }, + { 0x1120, 32337 }, + { 0x1137, 32340 }, + { 0x1138, 32343 }, + { 0x113A, 32346 }, + { 0x1139, 32349 }, + { 0x1153, 32352 }, + { 0x114E, 32355 }, + { 0x1149, 32358 }, + { 0x1146, 32361 }, + { 0x114B, 32364 }, + { 0x114A, 32367 }, + { 0x111D, 32370 }, + { 0x112B, 32373 }, + { 0x111B, 32376 }, + { 0x1156, 32379 }, + { 0x1128, 32382 }, + { 0x112A, 32385 }, + { 0x1129, 32388 }, + { 0x1117, 32391 }, + { 0x1134, 32394 }, + { 0x113E, 32397 }, + { 0x1152, 32400 }, + { 0x1154, 32403 }, + { 0x1157, 32406 }, + { 0x1125, 32409 }, + { 0x1150, 32412 }, + { 0x1126, 32415 }, + { 0x1124, 32418 }, + { 0x113D, 32421 }, + { 0x1122, 32424 }, + { 0x1123, 32427 }, + { 0x1133, 32430 }, + { 0x1155, 32433 }, + { 0x114F, 32436 }, + { 0x112C, 32439 }, + { 0x113F, 32442 }, + { 0x1151, 32445 }, + { 0x11BA, 32448 }, + { 0x11BD, 32451 }, + { 0x11C2, 32454 }, + { 0x11BC, 32457 }, + { 0x11B7, 32460 }, + { 0x11AB, 32463 }, + { 0x11B8, 32466 }, + { 0x11AF, 32469 }, + { 0x11A8, 32472 }, + { 0x11AE, 32475 }, + { 0x11BE, 32478 }, + { 0x11BF, 32481 }, + { 0x11EB, 32484 }, + { 0x11C1, 32487 }, + { 0x11C0, 32490 }, + { 0x11F0, 32493 }, + { 0x11BB, 32496 }, + { 0x11DD, 32499 }, + { 0x11C7, 32502 }, + { 0x11B9, 32505 }, + { 0x11B3, 32508 }, + { 0x11EA, 32511 }, + { 0x11E9, 32514 }, + { 0x11EE, 32517 }, + { 0x11D0, 32520 }, + { 0x11F7, 32523 }, + { 0x11F5, 32526 }, + { 0x11F8, 32529 }, + { 0x11F6, 32532 }, + { 0x11AA, 32535 }, + { 0x11E1, 32538 }, + { 0x11DC, 32541 }, + { 0x11DB, 32544 }, + { 0x11AC, 32547 }, + { 0x11AD, 32550 }, + { 0x11E5, 32553 }, + { 0x11E3, 32556 }, + { 0x11B6, 32559 }, + { 0x11B1, 32562 }, + { 0x11CD, 32565 }, + { 0x11B2, 32568 }, + { 0x11E7, 32571 }, + { 0x11E8, 32574 }, + { 0x11A9, 32577 }, + { 0x11F9, 32580 }, + { 0x11EC, 32583 }, + { 0x11C3, 32586 }, + { 0x11DA, 32589 }, + { 0x11C5, 32592 }, + { 0x11C6, 32595 }, + { 0x11B0, 32598 }, + { 0x11CE, 32601 }, + { 0x11CB, 32604 }, + { 0x11EF, 32607 }, + { 0x11E2, 32610 }, + { 0x11E6, 32613 }, + { 0x11E0, 32616 }, + { 0x11DF, 32619 }, + { 0x11C8, 32622 }, + { 0x11C9, 32625 }, + { 0x11F3, 32628 }, + { 0x11E4, 32631 }, + { 0x11D8, 32634 }, + { 0x11D7, 32637 }, + { 0x11B5, 32640 }, + { 0x11B4, 32643 }, + { 0x11CA, 32646 }, + { 0x11F1, 32649 }, + { 0x11F4, 32652 }, + { 0x11DE, 32655 }, + { 0x11D6, 32658 }, + { 0x11D2, 32661 }, + { 0x11D3, 32664 }, + { 0x11F2, 32667 }, + { 0x11ED, 32670 }, + { 0x11CC, 32673 }, + { 0x11D4, 32676 }, + { 0x11D9, 32679 }, + { 0x11C4, 32682 }, + { 0x11D1, 32685 }, + { 0x11CF, 32688 }, + { 0x11D5, 32691 }, + { 0x1161, 32694 }, + { 0x1166, 32697 }, + { 0x1175, 32700 }, + { 0x1169, 32703 }, + { 0x116E, 32706 }, + { 0x1162, 32709 }, + { 0x1165, 32712 }, + { 0x1173, 32715 }, + { 0x116C, 32718 }, + { 0x116A, 32721 }, + { 0x1170, 32724 }, + { 0x1171, 32727 }, + { 0x1163, 32730 }, + { 0x1168, 32733 }, + { 0x1174, 32736 }, + { 0x116D, 32739 }, + { 0x1172, 32742 }, + { 0x1176, 32745 }, + { 0x1177, 32748 }, + { 0x1198, 32751 }, + { 0x119A, 32754 }, + { 0x119B, 32757 }, + { 0x1180, 32760 }, + { 0x1182, 32763 }, + { 0x1183, 32766 }, + { 0x1189, 32769 }, + { 0x118D, 32772 }, + { 0x116B, 32775 }, + { 0x116F, 32778 }, + { 0x1164, 32781 }, + { 0x1167, 32784 }, + { 0x117A, 32787 }, + { 0x117B, 32790 }, + { 0x1195, 32793 }, + { 0x119C, 32796 }, + { 0x1199, 32799 }, + { 0x117F, 32802 }, + { 0x1181, 32805 }, + { 0x118A, 32808 }, + { 0x118C, 32811 }, + { 0x1178, 32814 }, + { 0x1197, 32817 }, + { 0x1188, 32820 }, + { 0x1187, 32823 }, + { 0x118E, 32826 }, + { 0x1190, 32829 }, + { 0x1194, 32832 }, + { 0x1193, 32835 }, + { 0x119E, 32838 }, + { 0x117C, 32841 }, + { 0x1196, 32844 }, + { 0x1179, 32847 }, + { 0x117D, 32850 }, + { 0x117E, 32853 }, + { 0x1184, 32856 }, + { 0x118F, 32859 }, + { 0x1192, 32862 }, + { 0x1160, 32865 }, + { 0x1185, 32868 }, + { 0x1186, 32871 }, + { 0x1191, 32874 }, + { 0x11A1, 32877 }, + { 0x11A0, 32880 }, + { 0x119D, 32883 }, + { 0x118B, 32886 }, + { 0x119F, 32889 }, + { 0x11A2, 32892 }, + { 0x05C5, 32895 }, + { 0x05C4, 32899 }, + { 0x05AF, 32903 }, + { 0x05C2, 32907 }, + { 0x05BF, 32911 }, + { 0x05C1, 32914 }, + { 0x05B2, 32918 }, + { 0x05B1, 32922 }, + { 0x05B3, 32926 }, + { 0x05B4, 32930 }, + { 0x05B9, 32933 }, + { 0x05BA, 32936 }, + { 0x05BD, 32942 }, + { 0x05B7, 32945 }, + { 0x05B6, 32948 }, + { 0x05B0, 32951 }, + { 0x05B5, 32954 }, + { 0x05BC, 32957 }, + { 0x05B8, 32962 }, + { 0x05C7, 32965 }, + { 0x05BB, 32969 }, + { 0x6B1E, 32972 }, + { 0x05AB, 32976 }, + { 0x05AD, 32979 }, + { 0x05AC, 32982 }, + { 0x05A2, 32985 }, + { 0x05A7, 32989 }, + { 0x05A3, 32992 }, + { 0x05A1, 32995 }, + { 0x05A8, 32998 }, + { 0x0597, 33001 }, + { 0x0592, 33004 }, + { 0x059B, 33007 }, + { 0x05AA, 33010 }, + { 0x059A, 33015 }, + { 0x0595, 33018 }, + { 0x0594, 33022 }, + { 0x0598, 33026 }, + { 0x05AE, 33029 }, + { 0x059C, 33032 }, + { 0x059D, 33035 }, + { 0x05A5, 33039 }, + { 0x05A6, 33042 }, + { 0x0599, 33046 }, + { 0x059F, 33049 }, + { 0x0596, 33053 }, + { 0x0591, 33056 }, + { 0x05A0, 33059 }, + { 0x05A9, 33063 }, + { 0x05A4, 33067 }, + { 0x059E, 33070 }, + { 0x0593, 33073 }, + { 0x05D4, 33076 }, + { 0x6B34, 33079 }, + { 0x05E4, 33084 }, + { 0x6B4E, 33087 }, + { 0x6B44, 33092 }, + { 0x05D1, 33097 }, + { 0x6B4C, 33100 }, + { 0x6B31, 33105 }, + { 0x05D7, 33110 }, + { 0x05DB, 33113 }, + { 0x6B4D, 33116 }, + { 0x6B3B, 33121 }, + { 0x05DE, 33126 }, + { 0x6B3E, 33129 }, + { 0x05E0, 33134 }, + { 0x6B40, 33137 }, + { 0x05E7, 33142 }, + { 0x6B47, 33145 }, + { 0x05EA, 33150 }, + { 0x6B4A, 33153 }, + { 0x05D8, 33158 }, + { 0x6B38, 33161 }, + { 0x05D5, 33166 }, + { 0x6B4B, 33169 }, + { 0x6B35, 33174 }, + { 0x05D9, 33179 }, + { 0x6B1D, 33182 }, + { 0x6B39, 33187 }, + { 0x05D0, 33192 }, + { 0x6B30, 33195 }, + { 0x6B2E, 33200 }, + { 0x6B2F, 33205 }, + { 0x05E2, 33210 }, + { 0x05E8, 33213 }, + { 0x6B48, 33216 }, + { 0x05E9, 33221 }, + { 0x6B2B, 33224 }, + { 0x6B2A, 33230 }, + { 0x6B49, 33236 }, + { 0x6B2D, 33241 }, + { 0x6B2C, 33249 }, + { 0x6B23, 33257 }, + { 0x6B24, 33261 }, + { 0x6B28, 33265 }, + { 0x6B21, 33269 }, + { 0x6B27, 33273 }, + { 0x6B22, 33277 }, + { 0x6B26, 33281 }, + { 0x6B25, 33286 }, + { 0x05D3, 33290 }, + { 0x6B33, 33293 }, + { 0x05E3, 33298 }, + { 0x6B43, 33302 }, + { 0x05DA, 33308 }, + { 0x6B3A, 33312 }, + { 0x05DD, 33318 }, + { 0x05DF, 33322 }, + { 0x05E5, 33326 }, + { 0x05D2, 33330 }, + { 0x6B32, 33333 }, + { 0x05DC, 33338 }, + { 0x6B3C, 33341 }, + { 0x05E6, 33346 }, + { 0x6B46, 33349 }, + { 0x05D6, 33354 }, + { 0x6B36, 33357 }, + { 0x05E1, 33362 }, + { 0x6B41, 33365 }, + { 0x6B20, 33370 }, + { 0x6B29, 33374 }, + { 0x6B4F, 33379 }, + { 0x05F1, 33383 }, + { 0x6B1F, 33388 }, + { 0x05F0, 33394 }, + { 0x05F2, 33399 }, + { 0x05C6, 33404 }, + { 0x05C3, 33408 }, + { 0x05BE, 33412 }, + { 0x05C0, 33415 }, + { 0x05F3, 33418 }, + { 0x05F4, 33421 }, + { 0x2010, 33424 }, + { 0x2E1A, 33425 }, + { 0x2043, 33428 }, + { 0x2F4F, 33430 }, + { 0x2F21, 33434 }, + { 0x2F22, 33437 }, + { 0x2F7D, 33441 }, + { 0x2F44, 33444 }, + { 0x2F24, 33447 }, + { 0x2F38, 33450 }, + { 0x2F5C, 33453 }, + { 0x2F5D, 33456 }, + { 0x2F02, 33459 }, + { 0x2F32, 33462 }, + { 0x2F7F, 33465 }, + { 0x2FB7, 33468 }, + { 0x2F6C, 33471 }, + { 0x2FB6, 33474 }, + { 0x2F51, 33477 }, + { 0x2F0E, 33480 }, + { 0x2F78, 33483 }, + { 0x2F07, 33486 }, + { 0x2F08, 33489 }, + { 0x2F79, 33492 }, + { 0x2F46, 33495 }, + { 0x2F7C, 33498 }, + { 0x2F00, 33501 }, + { 0x2F97, 33504 }, + { 0x2F41, 33507 }, + { 0x2FCF, 33510 }, + { 0x2F9A, 33513 }, + { 0x2F9B, 33516 }, + { 0x2F48, 33519 }, + { 0x2F92, 33522 }, + { 0x2F47, 33525 }, + { 0x2F17, 33528 }, + { 0x2F06, 33531 }, + { 0x2F36, 33534 }, + { 0x2F64, 33538 }, + { 0x2F96, 33541 }, + { 0x2FC3, 33544 }, + { 0x2FAD, 33547 }, + { 0x2F88, 33550 }, + { 0x2F9D, 33553 }, + { 0x2F66, 33556 }, + { 0x2FBB, 33561 }, + { 0x2F9E, 33564 }, + { 0x2F73, 33567 }, + { 0x2FA2, 33570 }, + { 0x2F52, 33573 }, + { 0x2F56, 33576 }, + { 0x2FC5, 33579 }, + { 0x2F6B, 33582 }, + { 0x2F3E, 33585 }, + { 0x2F0C, 33588 }, + { 0x2FCE, 33592 }, + { 0x2FD1, 33595 }, + { 0x2FAF, 33598 }, + { 0x2F5B, 33601 }, + { 0x2F55, 33604 }, + { 0x2FC2, 33607 }, + { 0x2F9C, 33610 }, + { 0x2FCC, 33613 }, + { 0x2FA8, 33616 }, + { 0x2FA6, 33619 }, + { 0x2FBD, 33622 }, + { 0x2F59, 33625 }, + { 0x2F3F, 33630 }, + { 0x2FB8, 33633 }, + { 0x2FC7, 33636 }, + { 0x2F05, 33639 }, + { 0x2F93, 33642 }, + { 0x2F28, 33645 }, + { 0x2F5F, 33648 }, + { 0x2F4B, 33651 }, + { 0x2F2A, 33654 }, + { 0x2FB4, 33657 }, + { 0x2FB2, 33660 }, + { 0x2F09, 33663 }, + { 0x2F63, 33666 }, + { 0x2F01, 33669 }, + { 0x2FA7, 33672 }, + { 0x2F35, 33675 }, + { 0x2F81, 33679 }, + { 0x2F49, 33682 }, + { 0x2FD0, 33685 }, + { 0x2F10, 33688 }, + { 0x2F7E, 33692 }, + { 0x2FAC, 33695 }, + { 0x2F76, 33698 }, + { 0x2F27, 33701 }, + { 0x2FC4, 33704 }, + { 0x2F19, 33707 }, + { 0x2F83, 33710 }, + { 0x2F77, 33713 }, + { 0x2F6A, 33716 }, + { 0x2F3B, 33719 }, + { 0x2F4C, 33722 }, + { 0x2FBC, 33725 }, + { 0x2F61, 33728 }, + { 0x2F4A, 33731 }, + { 0x2FA1, 33734 }, + { 0x2F8F, 33737 }, + { 0x2F91, 33741 }, + { 0x2FB5, 33744 }, + { 0x2FA3, 33747 }, + { 0x2F2F, 33750 }, + { 0x2F13, 33753 }, + { 0x2F1C, 33756 }, + { 0x2F6E, 33759 }, + { 0x2FCA, 33762 }, + { 0x2F8E, 33765 }, + { 0x2F80, 33768 }, + { 0x2F26, 33771 }, + { 0x2F1A, 33774 }, + { 0x2F8A, 33777 }, + { 0x2F0D, 33780 }, + { 0x2F4D, 33783 }, + { 0x2F1F, 33786 }, + { 0x2F0B, 33789 }, + { 0x2F0A, 33792 }, + { 0x2F65, 33795 }, + { 0x2FBE, 33798 }, + { 0x2FD5, 33801 }, + { 0x2FC1, 33804 }, + { 0x2F72, 33807 }, + { 0x2F8B, 33810 }, + { 0x2F3C, 33813 }, + { 0x2FBA, 33816 }, + { 0x2F11, 33819 }, + { 0x2F60, 33822 }, + { 0x2FA9, 33825 }, + { 0x2F1D, 33828 }, + { 0x2F12, 33831 }, + { 0x2F15, 33834 }, + { 0x2F2E, 33839 }, + { 0x2F7A, 33842 }, + { 0x2F99, 33845 }, + { 0x2F37, 33848 }, + { 0x2FAB, 33851 }, + { 0x2F33, 33856 }, + { 0x2F03, 33860 }, + { 0x2FAA, 33863 }, + { 0x2F5A, 33866 }, + { 0x2F29, 33869 }, + { 0x2F39, 33872 }, + { 0x2FB3, 33875 }, + { 0x2F6D, 33878 }, + { 0x2F14, 33881 }, + { 0x2F74, 33884 }, + { 0x2F53, 33887 }, + { 0x2F6F, 33890 }, + { 0x2F62, 33893 }, + { 0x2F0F, 33896 }, + { 0x2F8C, 33899 }, + { 0x2FD2, 33902 }, + { 0x2F71, 33905 }, + { 0x2F54, 33908 }, + { 0x2FC6, 33911 }, + { 0x2F69, 33914 }, + { 0x2F25, 33917 }, + { 0x2FAE, 33920 }, + { 0x2F84, 33923 }, + { 0x2F98, 33926 }, + { 0x2F75, 33929 }, + { 0x2F9F, 33932 }, + { 0x2F40, 33935 }, + { 0x2F2B, 33938 }, + { 0x2F43, 33941 }, + { 0x2F68, 33944 }, + { 0x2F34, 33948 }, + { 0x2F58, 33952 }, + { 0x2FD3, 33956 }, + { 0x2F57, 33959 }, + { 0x2F16, 33962 }, + { 0x2F8D, 33966 }, + { 0x2FC9, 33969 }, + { 0x2F85, 33972 }, + { 0x2F87, 33975 }, + { 0x2F42, 33978 }, + { 0x2F04, 33981 }, + { 0x2F94, 33984 }, + { 0x2F70, 33987 }, + { 0x2F2C, 33990 }, + { 0x2F45, 33993 }, + { 0x2FB1, 33996 }, + { 0x2F86, 34000 }, + { 0x2FCD, 34003 }, + { 0x2F31, 34006 }, + { 0x2FD4, 34009 }, + { 0x2F95, 34012 }, + { 0x2F4E, 34015 }, + { 0x2FC8, 34018 }, + { 0x2F3A, 34021 }, + { 0x2F90, 34024 }, + { 0x2F50, 34027 }, + { 0x2F23, 34030 }, + { 0x2F7B, 34033 }, + { 0x2F3D, 34036 }, + { 0x2FB0, 34039 }, + { 0x2FA0, 34042 }, + { 0x2F30, 34045 }, + { 0x2F1B, 34048 }, + { 0x2F20, 34051 }, + { 0x2FA5, 34054 }, + { 0x2FC0, 34057 }, + { 0x2FB9, 34060 }, + { 0x2F82, 34063 }, + { 0x2F2D, 34066 }, + { 0x2F5E, 34069 }, + { 0x2F67, 34072 }, + { 0x2F89, 34075 }, + { 0x2F1E, 34078 }, + { 0x2F18, 34081 }, + { 0x2FCB, 34084 }, + { 0x2FA4, 34087 }, + { 0x2FBF, 34090 }, + { 0x212A, 34094 }, + { 0x327F, 34096 }, + { 0x2AAB, 34099 }, + { 0x2AAD, 34101 }, + { 0x1C36, 34106 }, + { 0x1C37, 34109 }, + { 0x1C41, 34112 }, + { 0x1C46, 34115 }, + { 0x1C42, 34118 }, + { 0x1C45, 34121 }, + { 0x1C44, 34124 }, + { 0x1C49, 34127 }, + { 0x1C40, 34130 }, + { 0x1C48, 34133 }, + { 0x1C47, 34136 }, + { 0x1C43, 34139 }, + { 0x1C2C, 34142 }, + { 0x1C27, 34146 }, + { 0x1C28, 34150 }, + { 0x1C2A, 34154 }, + { 0x1C26, 34158 }, + { 0x1C29, 34162 }, + { 0x1C2B, 34166 }, + { 0x1C23, 34170 }, + { 0x1C13, 34173 }, + { 0x1C06, 34176 }, + { 0x1C0C, 34179 }, + { 0x1C11, 34182 }, + { 0x1C03, 34185 }, + { 0x1C1D, 34188 }, + { 0x1C08, 34191 }, + { 0x1C00, 34194 }, + { 0x1C1C, 34197 }, + { 0x1C15, 34200 }, + { 0x1C0D, 34203 }, + { 0x1C0E, 34206 }, + { 0x1C1B, 34209 }, + { 0x1C20, 34212 }, + { 0x1C0A, 34215 }, + { 0x1C1F, 34218 }, + { 0x1C22, 34221 }, + { 0x1C1A, 34224 }, + { 0x1C14, 34227 }, + { 0x1C07, 34230 }, + { 0x1C4F, 34233 }, + { 0x1C19, 34236 }, + { 0x1C12, 34239 }, + { 0x1C04, 34242 }, + { 0x1C1E, 34245 }, + { 0x1C02, 34248 }, + { 0x1C01, 34251 }, + { 0x1C16, 34254 }, + { 0x1C05, 34257 }, + { 0x1C09, 34260 }, + { 0x1C10, 34263 }, + { 0x1C0F, 34266 }, + { 0x1C21, 34269 }, + { 0x1C0B, 34272 }, + { 0x1C17, 34275 }, + { 0x1C4D, 34278 }, + { 0x1C18, 34281 }, + { 0x1C4E, 34284 }, + { 0x1C2D, 34287 }, + { 0x1C2F, 34291 }, + { 0x1C2E, 34295 }, + { 0x1C30, 34299 }, + { 0x1C31, 34303 }, + { 0x1C32, 34307 }, + { 0x1C33, 34311 }, + { 0x1C35, 34315 }, + { 0x1C34, 34319 }, + { 0x1C25, 34323 }, + { 0x1C24, 34327 }, + { 0x1C3C, 34331 }, + { 0x1C3D, 34336 }, + { 0x1C3B, 34339 }, + { 0x1C3F, 34342 }, + { 0x1C3E, 34345 }, + { 0x7050, 34349 }, + { 0x7051, 34353 }, + { 0x7052, 34357 }, + { 0x7053, 34361 }, + { 0x7054, 34365 }, + { 0x7055, 34369 }, + { 0x7056, 34373 }, + { 0x7057, 34377 }, + { 0x7058, 34381 }, + { 0x7059, 34385 }, + { 0x705A, 34389 }, + { 0x705B, 34393 }, + { 0x705C, 34397 }, + { 0x705D, 34401 }, + { 0x7080, 34405 }, + { 0x7081, 34410 }, + { 0x7082, 34415 }, + { 0x7083, 34420 }, + { 0x708E, 34425 }, + { 0x708F, 34430 }, + { 0x7090, 34435 }, + { 0x7091, 34440 }, + { 0x7092, 34445 }, + { 0x7095, 34450 }, + { 0x7096, 34455 }, + { 0x7097, 34460 }, + { 0x709A, 34464 }, + { 0x709B, 34469 }, + { 0x709C, 34474 }, + { 0x709D, 34478 }, + { 0x709E, 34483 }, + { 0x709F, 34487 }, + { 0x70A0, 34491 }, + { 0x70A1, 34496 }, + { 0x70A2, 34500 }, + { 0x70A3, 34504 }, + { 0x70A5, 34508 }, + { 0x70A6, 34512 }, + { 0x70A7, 34516 }, + { 0x70A8, 34521 }, + { 0x70A9, 34525 }, + { 0x70AA, 34529 }, + { 0x70AB, 34534 }, + { 0x70AC, 34539 }, + { 0x70AD, 34543 }, + { 0x70AE, 34547 }, + { 0x70AF, 34551 }, + { 0x70B0, 34555 }, + { 0x70B1, 34559 }, + { 0x70B2, 34563 }, + { 0x70B3, 34567 }, + { 0x70B4, 34571 }, + { 0x70B5, 34575 }, + { 0x70B6, 34580 }, + { 0x70B7, 34584 }, + { 0x70B8, 34589 }, + { 0x70B9, 34593 }, + { 0x70BA, 34597 }, + { 0x70BB, 34601 }, + { 0x70BC, 34605 }, + { 0x70BD, 34609 }, + { 0x70BE, 34613 }, + { 0x70BF, 34617 }, + { 0x70C0, 34621 }, + { 0x70C1, 34625 }, + { 0x70C2, 34629 }, + { 0x70C3, 34633 }, + { 0x70C4, 34638 }, + { 0x70C5, 34643 }, + { 0x70C6, 34648 }, + { 0x70C7, 34653 }, + { 0x70C8, 34658 }, + { 0x70C9, 34662 }, + { 0x70CA, 34667 }, + { 0x70CB, 34671 }, + { 0x70CC, 34675 }, + { 0x70CD, 34681 }, + { 0x70CE, 34686 }, + { 0x70CF, 34692 }, + { 0x70D0, 34697 }, + { 0x70D1, 34701 }, + { 0x70D3, 34705 }, + { 0x70D4, 34709 }, + { 0x70D5, 34713 }, + { 0x70D6, 34717 }, + { 0x70D7, 34721 }, + { 0x70D8, 34725 }, + { 0x70D9, 34730 }, + { 0x70DA, 34734 }, + { 0x70DB, 34738 }, + { 0x70DC, 34742 }, + { 0x70DD, 34746 }, + { 0x7084, 34750 }, + { 0x7085, 34755 }, + { 0x7086, 34760 }, + { 0x7087, 34765 }, + { 0x7088, 34770 }, + { 0x7089, 34775 }, + { 0x708A, 34780 }, + { 0x708B, 34785 }, + { 0x708C, 34790 }, + { 0x708D, 34795 }, + { 0x70DE, 34800 }, + { 0x70DF, 34805 }, + { 0x70E0, 34810 }, + { 0x70E1, 34815 }, + { 0x70E2, 34820 }, + { 0x70E3, 34825 }, + { 0x70E4, 34830 }, + { 0x70E5, 34835 }, + { 0x70E6, 34840 }, + { 0x70E7, 34845 }, + { 0x70E8, 34850 }, + { 0x70E9, 34855 }, + { 0x70EA, 34860 }, + { 0x70EB, 34865 }, + { 0x70EC, 34870 }, + { 0x70ED, 34875 }, + { 0x70EE, 34880 }, + { 0x70EF, 34885 }, + { 0x70F0, 34890 }, + { 0x70F1, 34895 }, + { 0x70F2, 34900 }, + { 0x70F3, 34905 }, + { 0x70F4, 34910 }, + { 0x70F5, 34915 }, + { 0x70F6, 34920 }, + { 0x70F7, 34925 }, + { 0x70F8, 34930 }, + { 0x70F9, 34935 }, + { 0x70FA, 34940 }, + { 0x7093, 34945 }, + { 0x7094, 34950 }, + { 0x7098, 34955 }, + { 0x7099, 34960 }, + { 0x70A4, 34965 }, + { 0x70D2, 34970 }, + { 0x7005, 34975 }, + { 0x702B, 34980 }, + { 0x701E, 34985 }, + { 0x7033, 34990 }, + { 0x7035, 34995 }, + { 0x7019, 35000 }, + { 0x7007, 35005 }, + { 0x7000, 35010 }, + { 0x702E, 35015 }, + { 0x7004, 35020 }, + { 0x7021, 35025 }, + { 0x7030, 35030 }, + { 0x7015, 35035 }, + { 0x7008, 35040 }, + { 0x7017, 35045 }, + { 0x7023, 35050 }, + { 0x703C, 35055 }, + { 0x703F, 35060 }, + { 0x7025, 35065 }, + { 0x7018, 35070 }, + { 0x701A, 35075 }, + { 0x7040, 35080 }, + { 0x702C, 35085 }, + { 0x7029, 35090 }, + { 0x7002, 35095 }, + { 0x7046, 35100 }, + { 0x701B, 35105 }, + { 0x702D, 35110 }, + { 0x7026, 35115 }, + { 0x7049, 35120 }, + { 0x700D, 35125 }, + { 0x7034, 35130 }, + { 0x7001, 35135 }, + { 0x7020, 35140 }, + { 0x7039, 35145 }, + { 0x702F, 35150 }, + { 0x703A, 35155 }, + { 0x7041, 35160 }, + { 0x7010, 35165 }, + { 0x7006, 35170 }, + { 0x700B, 35175 }, + { 0x7045, 35180 }, + { 0x7022, 35185 }, + { 0x7009, 35190 }, + { 0x701C, 35195 }, + { 0x702A, 35200 }, + { 0x7037, 35205 }, + { 0x701D, 35210 }, + { 0x700A, 35215 }, + { 0x7031, 35220 }, + { 0x7032, 35225 }, + { 0x7028, 35230 }, + { 0x7003, 35235 }, + { 0x7047, 35240 }, + { 0x700E, 35245 }, + { 0x704B, 35250 }, + { 0x7011, 35255 }, + { 0x704A, 35260 }, + { 0x7036, 35265 }, + { 0x7012, 35270 }, + { 0x7043, 35275 }, + { 0x701F, 35280 }, + { 0x7016, 35285 }, + { 0x703D, 35290 }, + { 0x7038, 35295 }, + { 0x7048, 35300 }, + { 0x700F, 35305 }, + { 0x7024, 35310 }, + { 0x7014, 35315 }, + { 0x7013, 35320 }, + { 0x7042, 35325 }, + { 0x704C, 35330 }, + { 0x7044, 35335 }, + { 0x704D, 35340 }, + { 0x7280, 35345 }, + { 0x7282, 35348 }, + { 0x7285, 35351 }, + { 0x7281, 35354 }, + { 0x7284, 35357 }, + { 0x729B, 35360 }, + { 0x7286, 35363 }, + { 0x728A, 35366 }, + { 0x728B, 35369 }, + { 0x728D, 35372 }, + { 0x728E, 35375 }, + { 0x728F, 35378 }, + { 0x7293, 35381 }, + { 0x728C, 35384 }, + { 0x7295, 35387 }, + { 0x7296, 35390 }, + { 0x7297, 35393 }, + { 0x7292, 35396 }, + { 0x7287, 35399 }, + { 0x729C, 35402 }, + { 0x7288, 35405 }, + { 0x7299, 35408 }, + { 0x7283, 35411 }, + { 0x729A, 35414 }, + { 0x7294, 35417 }, + { 0x7290, 35420 }, + { 0x7291, 35423 }, + { 0x7289, 35426 }, + { 0x7298, 35429 }, + { 0x7920, 35432 }, + { 0x7921, 35435 }, + { 0x7939, 35438 }, + { 0x7923, 35441 }, + { 0x7924, 35444 }, + { 0x7931, 35447 }, + { 0x7922, 35450 }, + { 0x7926, 35453 }, + { 0x7928, 35456 }, + { 0x7929, 35459 }, + { 0x792A, 35462 }, + { 0x792B, 35465 }, + { 0x792C, 35468 }, + { 0x7932, 35471 }, + { 0x792D, 35474 }, + { 0x7933, 35477 }, + { 0x792F, 35480 }, + { 0x7930, 35483 }, + { 0x7925, 35486 }, + { 0x7927, 35489 }, + { 0x7935, 35492 }, + { 0x7936, 35495 }, + { 0x7937, 35498 }, + { 0x7938, 35501 }, + { 0x792E, 35504 }, + { 0x7934, 35507 }, + { 0x793F, 35510 }, + { 0x00AF, 35513 }, + { 0x2774, 35514 }, + { 0x2768, 35519 }, + { 0x26AB, 35523 }, + { 0x2775, 35526 }, + { 0x2769, 35531 }, + { 0x2592, 35535 }, + { 0x26AC, 35537 }, + { 0x26AA, 35541 }, + { 0x2759, 35544 }, + { 0x276A, 35547 }, + { 0x276B, 35552 }, + { 0x205F, 35557 }, + { 0x276C, 35560 }, + { 0x276D, 35565 }, + { 0x00B7, 35570 }, + { 0x22A7, 35572 }, + { 0x2A0A, 35573 }, + { 0x202F, 35576 }, + { 0x26B2, 35579 }, + { 0x22B2, 35580 }, + { 0x22B4, 35583 }, + { 0x2491, 35589 }, + { 0x0023, 35593 }, + { 0x2492, 35595 }, + { 0x2493, 35599 }, + { 0x249B, 35603 }, + { 0x2496, 35607 }, + { 0x2497, 35611 }, + { 0x2499, 35615 }, + { 0x2495, 35619 }, + { 0x249A, 35623 }, + { 0x2494, 35627 }, + { 0x2498, 35631 }, + { 0x2116, 35635 }, + { 0x6FFC, 35637 }, + { 0x02DB, 35640 }, + { 0x2325, 35641 }, + { 0x6D3E, 35643 }, + { 0x6D3F, 35646 }, + { 0x26B4, 35649 }, + { 0x270F, 35650 }, + { 0x20A7, 35651 }, + { 0x2653, 35653 }, + { 0x210E, 35654 }, + { 0x210F, 35656 }, + { 0x3012, 35661 }, + { 0x3020, 35663 }, + { 0x2E07, 35666 }, + { 0x2E0B, 35670 }, + { 0x2E06, 35672 }, + { 0x5949, 35675 }, + { 0x5947, 35679 }, + { 0x594B, 35683 }, + { 0x5948, 35687 }, + { 0x594A, 35691 }, + { 0x594C, 35695 }, + { 0x594E, 35699 }, + { 0x594D, 35703 }, + { 0x5946, 35707 }, + { 0x5937, 35710 }, + { 0x5939, 35713 }, + { 0x5934, 35716 }, + { 0x5931, 35719 }, + { 0x5941, 35722 }, + { 0x593A, 35725 }, + { 0x5930, 35728 }, + { 0x593E, 35731 }, + { 0x5938, 35734 }, + { 0x5935, 35737 }, + { 0x5936, 35740 }, + { 0x593D, 35743 }, + { 0x593C, 35746 }, + { 0x5933, 35749 }, + { 0x5940, 35752 }, + { 0x593F, 35755 }, + { 0x5942, 35758 }, + { 0x5944, 35761 }, + { 0x5932, 35764 }, + { 0x593B, 35767 }, + { 0x5943, 35770 }, + { 0x5945, 35773 }, + { 0x5953, 35776 }, + { 0x595F, 35778 }, + { 0x5952, 35781 }, + { 0x5950, 35785 }, + { 0x5951, 35789 }, + { 0x594F, 35793 }, + { 0x23CE, 35797 }, + { 0x2930, 35799 }, + { 0x292B, 35805 }, + { 0x2644, 35810 }, + { 0x2696, 35811 }, + { 0x212F, 35812 }, + { 0x210A, 35815 }, + { 0x2113, 35818 }, + { 0x2134, 35821 }, + { 0x212C, 35824 }, + { 0x2130, 35827 }, + { 0x2131, 35830 }, + { 0x210B, 35833 }, + { 0x2110, 35836 }, + { 0x2112, 35839 }, + { 0x2133, 35842 }, + { 0x2118, 35845 }, + { 0x211B, 35848 }, + { 0x2314, 35851 }, + { 0x6E45, 35852 }, + { 0x201A, 35854 }, + { 0x2039, 35858 }, + { 0x203A, 35863 }, + { 0x201B, 35868 }, + { 0x33DF, 35872 }, + { 0x33C6, 35876 }, + { 0x33C0, 35880 }, + { 0x33C1, 35883 }, + { 0x33A7, 35886 }, + { 0x33A8, 35890 }, + { 0x33A5, 35895 }, + { 0x33A1, 35898 }, + { 0x33DE, 35901 }, + { 0x33C2, 35905 }, + { 0x3373, 35907 }, + { 0x33C3, 35909 }, + { 0x33C4, 35911 }, + { 0x33C5, 35913 }, + { 0x339D, 35915 }, + { 0x33A4, 35917 }, + { 0x33A0, 35920 }, + { 0x33C7, 35923 }, + { 0x3372, 35925 }, + { 0x33C8, 35927 }, + { 0x3397, 35929 }, + { 0x3377, 35931 }, + { 0x3379, 35933 }, + { 0x3378, 35936 }, + { 0x32CE, 35939 }, + { 0x3399, 35941 }, + { 0x3387, 35943 }, + { 0x33C9, 35945 }, + { 0x33CA, 35947 }, + { 0x32CC, 35949 }, + { 0x33CB, 35951 }, + { 0x3390, 35953 }, + { 0x33CC, 35955 }, + { 0x337A, 35957 }, + { 0x3384, 35959 }, + { 0x3385, 35961 }, + { 0x338F, 35963 }, + { 0x33CD, 35965 }, + { 0x3398, 35967 }, + { 0x339E, 35969 }, + { 0x33A6, 35971 }, + { 0x33CE, 35974 }, + { 0x33A2, 35977 }, + { 0x33CF, 35980 }, + { 0x33B8, 35982 }, + { 0x33BE, 35984 }, + { 0x33D0, 35986 }, + { 0x33D1, 35988 }, + { 0x33D3, 35990 }, + { 0x3383, 35992 }, + { 0x3386, 35994 }, + { 0x33D4, 35996 }, + { 0x338E, 35999 }, + { 0x3396, 36001 }, + { 0x339C, 36003 }, + { 0x33A3, 36005 }, + { 0x339F, 36008 }, + { 0x33B3, 36011 }, + { 0x3382, 36013 }, + { 0x338C, 36016 }, + { 0x338D, 36019 }, + { 0x3395, 36022 }, + { 0x339B, 36025 }, + { 0x33B2, 36028 }, + { 0x33B6, 36031 }, + { 0x33BC, 36034 }, + { 0x33B7, 36037 }, + { 0x33B9, 36039 }, + { 0x33BD, 36042 }, + { 0x33BF, 36044 }, + { 0x3381, 36047 }, + { 0x338B, 36049 }, + { 0x339A, 36051 }, + { 0x33B1, 36053 }, + { 0x33B5, 36055 }, + { 0x33BB, 36057 }, + { 0x3375, 36059 }, + { 0x33A9, 36061 }, + { 0x3380, 36063 }, + { 0x3376, 36066 }, + { 0x338A, 36068 }, + { 0x33D7, 36070 }, + { 0x33D8, 36072 }, + { 0x33DA, 36074 }, + { 0x33B0, 36076 }, + { 0x33B4, 36078 }, + { 0x33BA, 36080 }, + { 0x33DB, 36082 }, + { 0x33DC, 36084 }, + { 0x33DD, 36086 }, + { 0x3374, 36088 }, + { 0x3388, 36090 }, + { 0x2293, 36092 }, + { 0x2294, 36094 }, + { 0x337E, 36096 }, + { 0x337B, 36100 }, + { 0x337C, 36104 }, + { 0x337D, 36108 }, + { 0x32CD, 36112 }, + { 0x33FF, 36114 }, + { 0x3393, 36116 }, + { 0x33AC, 36118 }, + { 0x333F, 36120 }, + { 0x3371, 36122 }, + { 0x3391, 36124 }, + { 0x33AA, 36126 }, + { 0x33D2, 36128 }, + { 0x3392, 36130 }, + { 0x33D5, 36132 }, + { 0x33D6, 36134 }, + { 0x33AB, 36136 }, + { 0x33D9, 36138 }, + { 0x33AD, 36140 }, + { 0x33AE, 36142 }, + { 0x33AF, 36146 }, + { 0x3394, 36151 }, + { 0x3327, 36153 }, + { 0x3306, 36155 }, + { 0x3303, 36157 }, + { 0x3331, 36159 }, + { 0x3325, 36161 }, + { 0x3326, 36163 }, + { 0x23CD, 36165 }, + { 0x3310, 36167 }, + { 0x3342, 36169 }, + { 0x3305, 36171 }, + { 0x3389, 36173 }, + { 0x3314, 36175 }, + { 0x2ACD, 36177 }, + { 0x334B, 36182 }, + { 0x3349, 36184 }, + { 0x3328, 36186 }, + { 0x3309, 36188 }, + { 0x330A, 36190 }, + { 0x3337, 36192 }, + { 0x3330, 36194 }, + { 0x3355, 36196 }, + { 0x3352, 36198 }, + { 0x221A, 36200 }, + { 0x2B12, 36202 }, + { 0x25E7, 36207 }, + { 0x2B15, 36212 }, + { 0x25EA, 36219 }, + { 0x25E8, 36226 }, + { 0x25A7, 36231 }, + { 0x25E9, 36239 }, + { 0x25A8, 36246 }, + { 0x2B14, 36254 }, + { 0x2B13, 36261 }, + { 0x25A9, 36266 }, + { 0x25A5, 36271 }, + { 0x29E0, 36275 }, + { 0x25A4, 36279 }, + { 0x25A6, 36283 }, + { 0x3350, 36288 }, + { 0x3302, 36290 }, + { 0x333C, 36292 }, + { 0x3324, 36294 }, + { 0x3308, 36296 }, + { 0x330F, 36298 }, + { 0x330E, 36300 }, + { 0x3311, 36302 }, + { 0x332A, 36304 }, + { 0x3341, 36306 }, + { 0x3335, 36308 }, + { 0x228F, 36310 }, + { 0x22E4, 36313 }, + { 0x2291, 36320 }, + { 0x330B, 36326 }, + { 0x331C, 36328 }, + { 0x331E, 36330 }, + { 0x3345, 36332 }, + { 0x3344, 36334 }, + { 0x3329, 36336 }, + { 0x332C, 36338 }, + { 0x333B, 36340 }, + { 0x333A, 36342 }, + { 0x3340, 36344 }, + { 0x2ACE, 36346 }, + { 0x3353, 36351 }, + { 0x3322, 36353 }, + { 0x3323, 36355 }, + { 0x3357, 36357 }, + { 0x334E, 36359 }, + { 0x334F, 36361 }, + { 0x3300, 36363 }, + { 0x3301, 36365 }, + { 0x333E, 36367 }, + { 0x3318, 36369 }, + { 0x3339, 36371 }, + { 0x3333, 36373 }, + { 0x3304, 36375 }, + { 0x331D, 36377 }, + { 0x3312, 36379 }, + { 0x3346, 36381 }, + { 0x3338, 36383 }, + { 0x332F, 36385 }, + { 0x333D, 36387 }, + { 0x332D, 36389 }, + { 0x3313, 36391 }, + { 0x330C, 36393 }, + { 0x330D, 36395 }, + { 0x331B, 36397 }, + { 0x2311, 36399 }, + { 0x3343, 36401 }, + { 0x3347, 36403 }, + { 0x334D, 36405 }, + { 0x334C, 36407 }, + { 0x3348, 36409 }, + { 0x3351, 36411 }, + { 0x3354, 36413 }, + { 0x331F, 36415 }, + { 0x3321, 36417 }, + { 0x3334, 36419 }, + { 0x3307, 36421 }, + { 0x3332, 36423 }, + { 0x2290, 36425 }, + { 0x22E5, 36428 }, + { 0x2292, 36435 }, + { 0x332B, 36441 }, + { 0x3356, 36443 }, + { 0x3320, 36445 }, + { 0x3319, 36447 }, + { 0x3336, 36449 }, + { 0x3317, 36451 }, + { 0x331A, 36453 }, + { 0x334A, 36455 }, + { 0x332E, 36457 }, + { 0x3315, 36459 }, + { 0x337F, 36461 }, + { 0x3316, 36463 }, + { 0x2729, 36465 }, + { 0x2282, 36469 }, + { 0x2286, 36471 }, + { 0x2AC3, 36476 }, + { 0x228A, 36484 }, + { 0x2ACB, 36490 }, + { 0x2AC7, 36496 }, + { 0x2AC9, 36501 }, + { 0x2AC5, 36507 }, + { 0x2ABD, 36512 }, + { 0x2ABF, 36515 }, + { 0x2AC1, 36520 }, + { 0x2AD5, 36525 }, + { 0x2AD3, 36528 }, + { 0x2979, 36531 }, + { 0x5806, 36535 }, + { 0x580B, 36539 }, + { 0x5802, 36543 }, + { 0x5823, 36547 }, + { 0x5826, 36552 }, + { 0x5824, 36557 }, + { 0x5825, 36562 }, + { 0x5827, 36567 }, + { 0x5800, 36572 }, + { 0x5804, 36576 }, + { 0x5801, 36580 }, + { 0x5805, 36584 }, + { 0x5803, 36588 }, + { 0x581B, 36592 }, + { 0x580C, 36596 }, + { 0x5816, 36600 }, + { 0x5809, 36604 }, + { 0x5822, 36608 }, + { 0x580E, 36612 }, + { 0x5807, 36616 }, + { 0x581F, 36620 }, + { 0x581D, 36624 }, + { 0x5818, 36628 }, + { 0x5819, 36632 }, + { 0x581E, 36636 }, + { 0x5821, 36640 }, + { 0x5814, 36644 }, + { 0x581C, 36648 }, + { 0x580D, 36652 }, + { 0x5812, 36656 }, + { 0x5817, 36660 }, + { 0x580A, 36664 }, + { 0x580F, 36668 }, + { 0x5808, 36672 }, + { 0x581A, 36676 }, + { 0x5820, 36680 }, + { 0x5815, 36684 }, + { 0x5810, 36688 }, + { 0x5813, 36692 }, + { 0x5811, 36696 }, + { 0x5828, 36700 }, + { 0x5829, 36704 }, + { 0x582A, 36708 }, + { 0x582B, 36712 }, + { 0x2403, 36716 }, + { 0x2419, 36721 }, + { 0x2404, 36726 }, + { 0x2417, 36731 }, + { 0x2407, 36737 }, + { 0x2410, 36740 }, + { 0x241C, 36745 }, + { 0x240C, 36749 }, + { 0x240A, 36753 }, + { 0x2400, 36757 }, + { 0x241F, 36760 }, + { 0x241D, 36764 }, + { 0x240F, 36768 }, + { 0x240E, 36772 }, + { 0x2420, 36776 }, + { 0x2402, 36779 }, + { 0x2401, 36784 }, + { 0x2418, 36789 }, + { 0x2421, 36792 }, + { 0x2425, 36795 }, + { 0x2411, 36800 }, + { 0x2412, 36805 }, + { 0x2414, 36810 }, + { 0x2413, 36815 }, + { 0x241B, 36820 }, + { 0x241E, 36823 }, + { 0x2405, 36827 }, + { 0x2424, 36830 }, + { 0x240D, 36833 }, + { 0x2415, 36837 }, + { 0x240B, 36841 }, + { 0x2408, 36845 }, + { 0x214F, 36848 }, + { 0x2409, 36852 }, + { 0x241A, 36856 }, + { 0x2426, 36859 }, + { 0x2406, 36864 }, + { 0x2416, 36867 }, + { 0x0700, 36871 }, + { 0x0743, 36875 }, + { 0x0744, 36880 }, + { 0x0706, 36885 }, + { 0x0707, 36889 }, + { 0x073D, 36893 }, + { 0x073E, 36896 }, + { 0x073A, 36899 }, + { 0x073B, 36902 }, + { 0x0749, 36905 }, + { 0x0736, 36907 }, + { 0x0737, 36910 }, + { 0x073F, 36913 }, + { 0x0745, 36915 }, + { 0x0746, 36919 }, + { 0x0739, 36923 }, + { 0x0738, 36927 }, + { 0x0725, 36931 }, + { 0x0717, 36934 }, + { 0x0726, 36937 }, + { 0x0721, 36940 }, + { 0x0722, 36943 }, + { 0x072C, 36946 }, + { 0x0718, 36949 }, + { 0x0712, 36952 }, + { 0x071A, 36955 }, + { 0x071F, 36958 }, + { 0x0729, 36961 }, + { 0x072A, 36964 }, + { 0x072B, 36967 }, + { 0x071B, 36970 }, + { 0x071C, 36973 }, + { 0x071D, 36977 }, + { 0x071E, 36980 }, + { 0x0719, 36984 }, + { 0x0710, 36987 }, + { 0x0724, 36990 }, + { 0x0713, 36994 }, + { 0x0714, 36997 }, + { 0x0728, 37001 }, + { 0x0715, 37004 }, + { 0x0720, 37007 }, + { 0x0716, 37010 }, + { 0x072D, 37015 }, + { 0x072E, 37019 }, + { 0x072F, 37023 }, + { 0x0723, 37027 }, + { 0x074F, 37030 }, + { 0x074E, 37034 }, + { 0x074D, 37038 }, + { 0x0727, 37042 }, + { 0x0711, 37046 }, + { 0x0730, 37050 }, + { 0x0731, 37053 }, + { 0x0732, 37056 }, + { 0x0733, 37059 }, + { 0x0734, 37062 }, + { 0x0735, 37065 }, + { 0x074A, 37068 }, + { 0x0747, 37070 }, + { 0x0748, 37074 }, + { 0x0740, 37078 }, + { 0x070B, 37081 }, + { 0x070C, 37084 }, + { 0x070D, 37087 }, + { 0x0742, 37090 }, + { 0x0741, 37092 }, + { 0x0702, 37094 }, + { 0x0704, 37098 }, + { 0x0709, 37101 }, + { 0x0705, 37106 }, + { 0x070A, 37109 }, + { 0x073C, 37111 }, + { 0x0701, 37114 }, + { 0x0703, 37118 }, + { 0x0708, 37121 }, + { 0x070F, 37126 }, + { 0x2649, 37129 }, + { 0x0C56, 37130 }, + { 0x0C7F, 37134 }, + { 0x0C4D, 37137 }, + { 0x0C03, 37140 }, + { 0x0C02, 37143 }, + { 0x0C3D, 37146 }, + { 0x0C01, 37149 }, + { 0x0C67, 37152 }, + { 0x0C6C, 37155 }, + { 0x0C68, 37158 }, + { 0x0C6B, 37161 }, + { 0x0C6A, 37164 }, + { 0x0C6F, 37167 }, + { 0x0C66, 37170 }, + { 0x0C6E, 37173 }, + { 0x0C6D, 37176 }, + { 0x0C69, 37179 }, + { 0x0C46, 37182 }, + { 0x0C3F, 37186 }, + { 0x0C4A, 37190 }, + { 0x0C41, 37194 }, + { 0x0C3E, 37198 }, + { 0x0C48, 37202 }, + { 0x0C4C, 37206 }, + { 0x0C47, 37210 }, + { 0x0C40, 37214 }, + { 0x0C4B, 37218 }, + { 0x0C42, 37222 }, + { 0x0C62, 37226 }, + { 0x0C43, 37231 }, + { 0x0C63, 37236 }, + { 0x0C44, 37241 }, + { 0x0C55, 37246 }, + { 0x0C05, 37249 }, + { 0x0C0E, 37252 }, + { 0x0C07, 37255 }, + { 0x0C12, 37258 }, + { 0x0C09, 37261 }, + { 0x0C06, 37264 }, + { 0x0C10, 37267 }, + { 0x0C14, 37270 }, + { 0x0C2C, 37273 }, + { 0x0C1A, 37276 }, + { 0x0C26, 37279 }, + { 0x0C0F, 37282 }, + { 0x0C17, 37285 }, + { 0x0C39, 37288 }, + { 0x0C08, 37291 }, + { 0x0C1C, 37294 }, + { 0x0C15, 37297 }, + { 0x0C32, 37300 }, + { 0x0C2E, 37303 }, + { 0x0C28, 37306 }, + { 0x0C13, 37309 }, + { 0x0C2A, 37312 }, + { 0x0C30, 37315 }, + { 0x0C38, 37318 }, + { 0x0C24, 37321 }, + { 0x0C0A, 37324 }, + { 0x0C35, 37327 }, + { 0x0C2F, 37330 }, + { 0x0C2D, 37333 }, + { 0x0C1B, 37336 }, + { 0x0C21, 37339 }, + { 0x0C27, 37342 }, + { 0x0C59, 37345 }, + { 0x0C18, 37348 }, + { 0x0C1D, 37351 }, + { 0x0C16, 37354 }, + { 0x0C33, 37357 }, + { 0x0C19, 37360 }, + { 0x0C23, 37363 }, + { 0x0C1E, 37366 }, + { 0x0C2B, 37369 }, + { 0x0C31, 37372 }, + { 0x0C36, 37375 }, + { 0x0C37, 37378 }, + { 0x0C25, 37381 }, + { 0x0C58, 37384 }, + { 0x0C1F, 37387 }, + { 0x0C22, 37390 }, + { 0x0C20, 37393 }, + { 0x0C0C, 37396 }, + { 0x0C0B, 37400 }, + { 0x0C61, 37404 }, + { 0x0C60, 37408 }, + { 0x0C79, 37412 }, + { 0x0C7C, 37421 }, + { 0x0C7A, 37430 }, + { 0x0C7D, 37439 }, + { 0x0C78, 37448 }, + { 0x0C7B, 37457 }, + { 0x0C7E, 37466 }, + { 0x07B0, 37475 }, + { 0x07A0, 37477 }, + { 0x07A1, 37480 }, + { 0x0784, 37483 }, + { 0x0780, 37486 }, + { 0x07B1, 37489 }, + { 0x0783, 37492 }, + { 0x0794, 37495 }, + { 0x079C, 37498 }, + { 0x07A2, 37501 }, + { 0x0799, 37504 }, + { 0x079A, 37507 }, + { 0x078C, 37510 }, + { 0x0798, 37513 }, + { 0x0787, 37516 }, + { 0x078A, 37519 }, + { 0x078E, 37522 }, + { 0x0786, 37525 }, + { 0x078D, 37528 }, + { 0x0789, 37531 }, + { 0x0782, 37534 }, + { 0x07A4, 37537 }, + { 0x0790, 37540 }, + { 0x0788, 37543 }, + { 0x07A5, 37546 }, + { 0x079F, 37549 }, + { 0x078B, 37552 }, + { 0x07A3, 37555 }, + { 0x079E, 37558 }, + { 0x079D, 37561 }, + { 0x079B, 37564 }, + { 0x0791, 37567 }, + { 0x0796, 37570 }, + { 0x0795, 37573 }, + { 0x0793, 37576 }, + { 0x0792, 37579 }, + { 0x0797, 37582 }, + { 0x078F, 37585 }, + { 0x0785, 37588 }, + { 0x0781, 37591 }, + { 0x07A6, 37594 }, + { 0x07AC, 37596 }, + { 0x07A8, 37598 }, + { 0x07AE, 37600 }, + { 0x07AA, 37602 }, + { 0x07A7, 37604 }, + { 0x07A9, 37606 }, + { 0x07AD, 37608 }, + { 0x07AF, 37610 }, + { 0x07AB, 37612 }, + { 0x29FB, 37614 }, + { 0x2AF6, 37616 }, + { 0x2034, 37619 }, + { 0x224B, 37621 }, + { 0x2AF7, 37623 }, + { 0x2AF8, 37626 }, + { 0x2AFB, 37629 }, + { 0x222D, 37633 }, + { 0x2AF5, 37635 }, + { 0x22AA, 37641 }, + { 0x2AF4, 37646 }, + { 0x2980, 37651 }, + { 0x2A68, 37655 }, + { 0x2A69, 37662 }, + { 0x20AE, 37669 }, + { 0x2319, 37671 }, + { 0x29A2, 37674 }, + { 0x2129, 37676 }, + { 0x214E, 37681 }, + { 0x2132, 37684 }, + { 0x214B, 37687 }, + { 0x2141, 37689 }, + { 0x2142, 37693 }, + { 0x2144, 37697 }, + { 0x2739, 37701 }, + { 0x2645, 37705 }, + { 0x2A2F, 37706 }, + { 0x2230, 37710 }, + { 0x00BD, 37712 }, + { 0x2155, 37716 }, + { 0x2159, 37720 }, + { 0x2153, 37724 }, + { 0x215B, 37728 }, + { 0x00BC, 37732 }, + { 0x2156, 37736 }, + { 0x2154, 37740 }, + { 0x215A, 37744 }, + { 0x215D, 37748 }, + { 0x2158, 37752 }, + { 0x215E, 37756 }, + { 0x2157, 37760 }, + { 0x215C, 37764 }, + { 0x00BE, 37768 }, + { 0x2240, 37772 }, + { 0x2100, 37774 }, + { 0x060B, 37776 }, + { 0x2697, 37778 }, + { 0x20B3, 37779 }, + { 0x2235, 37781 }, + { 0x09D7, 37782 }, + { 0x09BC, 37786 }, + { 0x09CD, 37789 }, + { 0x0983, 37792 }, + { 0x0982, 37795 }, + { 0x09BD, 37798 }, + { 0x0981, 37801 }, + { 0x09E7, 37804 }, + { 0x09EC, 37807 }, + { 0x09E8, 37810 }, + { 0x09EB, 37813 }, + { 0x09EA, 37816 }, + { 0x09EF, 37819 }, + { 0x09E6, 37822 }, + { 0x09EE, 37825 }, + { 0x09ED, 37828 }, + { 0x09E9, 37831 }, + { 0x09F2, 37834 }, + { 0x09F3, 37837 }, + { 0x09C7, 37840 }, + { 0x09BF, 37844 }, + { 0x09CB, 37848 }, + { 0x09C1, 37852 }, + { 0x09BE, 37856 }, + { 0x09C8, 37860 }, + { 0x09CC, 37864 }, + { 0x09C0, 37868 }, + { 0x09C2, 37872 }, + { 0x09E2, 37876 }, + { 0x09C3, 37881 }, + { 0x09E3, 37886 }, + { 0x09C4, 37891 }, + { 0x09FA, 37896 }, + { 0x0985, 37898 }, + { 0x098F, 37901 }, + { 0x0987, 37904 }, + { 0x0993, 37907 }, + { 0x0989, 37910 }, + { 0x0986, 37913 }, + { 0x0990, 37916 }, + { 0x0994, 37919 }, + { 0x09AC, 37922 }, + { 0x099A, 37925 }, + { 0x09A6, 37928 }, + { 0x0997, 37931 }, + { 0x09B9, 37934 }, + { 0x0988, 37937 }, + { 0x099C, 37940 }, + { 0x0995, 37943 }, + { 0x09B2, 37946 }, + { 0x09AE, 37949 }, + { 0x09A8, 37952 }, + { 0x09AA, 37955 }, + { 0x09B0, 37958 }, + { 0x09F1, 37961 }, + { 0x09F0, 37967 }, + { 0x09B8, 37973 }, + { 0x09A4, 37976 }, + { 0x098A, 37979 }, + { 0x09AF, 37982 }, + { 0x09AD, 37985 }, + { 0x099B, 37988 }, + { 0x09A1, 37991 }, + { 0x09A7, 37994 }, + { 0x0998, 37997 }, + { 0x099D, 38000 }, + { 0x0996, 38003 }, + { 0x0999, 38006 }, + { 0x09A3, 38009 }, + { 0x099E, 38012 }, + { 0x09AB, 38015 }, + { 0x09DD, 38018 }, + { 0x09DC, 38021 }, + { 0x09B6, 38024 }, + { 0x09B7, 38027 }, + { 0x09A5, 38030 }, + { 0x099F, 38033 }, + { 0x09DF, 38036 }, + { 0x09A2, 38039 }, + { 0x09A0, 38042 }, + { 0x09CE, 38045 }, + { 0x098C, 38049 }, + { 0x098B, 38053 }, + { 0x09E1, 38057 }, + { 0x09E0, 38061 }, + { 0x09F4, 38065 }, + { 0x09F8, 38069 }, + { 0x09F5, 38077 }, + { 0x09F7, 38081 }, + { 0x09F6, 38085 }, + { 0x09F9, 38089 }, + { 0x232C, 38093 }, + { 0x23E3, 38095 }, + { 0x226C, 38099 }, + { 0x2800, 38100 }, + { 0x2801, 38103 }, + { 0x2802, 38106 }, + { 0x2804, 38109 }, + { 0x2808, 38112 }, + { 0x2810, 38115 }, + { 0x2820, 38118 }, + { 0x2840, 38121 }, + { 0x2880, 38124 }, + { 0x2803, 38127 }, + { 0x2805, 38130 }, + { 0x2809, 38133 }, + { 0x2811, 38136 }, + { 0x2821, 38139 }, + { 0x2841, 38142 }, + { 0x2881, 38145 }, + { 0x2806, 38148 }, + { 0x280A, 38151 }, + { 0x2812, 38154 }, + { 0x2822, 38157 }, + { 0x2842, 38160 }, + { 0x2882, 38163 }, + { 0x280C, 38166 }, + { 0x2814, 38169 }, + { 0x2824, 38172 }, + { 0x2844, 38175 }, + { 0x2884, 38178 }, + { 0x2818, 38181 }, + { 0x2828, 38184 }, + { 0x2848, 38187 }, + { 0x2888, 38190 }, + { 0x2830, 38193 }, + { 0x2850, 38196 }, + { 0x2890, 38199 }, + { 0x2860, 38202 }, + { 0x28A0, 38205 }, + { 0x28C0, 38208 }, + { 0x2807, 38211 }, + { 0x280B, 38214 }, + { 0x2813, 38217 }, + { 0x2823, 38220 }, + { 0x2843, 38223 }, + { 0x2883, 38226 }, + { 0x280D, 38229 }, + { 0x2815, 38232 }, + { 0x2825, 38235 }, + { 0x2845, 38238 }, + { 0x2885, 38241 }, + { 0x2819, 38244 }, + { 0x2829, 38247 }, + { 0x2849, 38250 }, + { 0x2889, 38253 }, + { 0x2831, 38256 }, + { 0x2851, 38259 }, + { 0x2891, 38262 }, + { 0x2861, 38265 }, + { 0x28A1, 38268 }, + { 0x28C1, 38271 }, + { 0x280E, 38274 }, + { 0x2816, 38277 }, + { 0x2826, 38280 }, + { 0x2846, 38283 }, + { 0x2886, 38286 }, + { 0x281A, 38289 }, + { 0x282A, 38292 }, + { 0x284A, 38295 }, + { 0x288A, 38298 }, + { 0x2832, 38301 }, + { 0x2852, 38304 }, + { 0x2892, 38307 }, + { 0x2862, 38310 }, + { 0x28A2, 38313 }, + { 0x28C2, 38316 }, + { 0x281C, 38319 }, + { 0x282C, 38322 }, + { 0x284C, 38325 }, + { 0x288C, 38328 }, + { 0x2834, 38331 }, + { 0x2854, 38334 }, + { 0x2894, 38337 }, + { 0x2864, 38340 }, + { 0x28A4, 38343 }, + { 0x28C4, 38346 }, + { 0x2838, 38349 }, + { 0x2858, 38352 }, + { 0x2898, 38355 }, + { 0x2868, 38358 }, + { 0x28A8, 38361 }, + { 0x28C8, 38364 }, + { 0x2870, 38367 }, + { 0x28B0, 38370 }, + { 0x28D0, 38373 }, + { 0x28E0, 38376 }, + { 0x280F, 38379 }, + { 0x2817, 38382 }, + { 0x2827, 38385 }, + { 0x2847, 38388 }, + { 0x2887, 38391 }, + { 0x281B, 38394 }, + { 0x282B, 38397 }, + { 0x284B, 38400 }, + { 0x288B, 38403 }, + { 0x2833, 38406 }, + { 0x2853, 38409 }, + { 0x2893, 38412 }, + { 0x2863, 38415 }, + { 0x28A3, 38418 }, + { 0x28C3, 38421 }, + { 0x281D, 38424 }, + { 0x282D, 38427 }, + { 0x284D, 38430 }, + { 0x288D, 38433 }, + { 0x2835, 38436 }, + { 0x2855, 38439 }, + { 0x2895, 38442 }, + { 0x2865, 38445 }, + { 0x28A5, 38448 }, + { 0x28C5, 38451 }, + { 0x2839, 38454 }, + { 0x2859, 38457 }, + { 0x2899, 38460 }, + { 0x2869, 38463 }, + { 0x28A9, 38466 }, + { 0x28C9, 38469 }, + { 0x2871, 38472 }, + { 0x28B1, 38475 }, + { 0x28D1, 38478 }, + { 0x28E1, 38481 }, + { 0x281E, 38484 }, + { 0x282E, 38487 }, + { 0x284E, 38490 }, + { 0x288E, 38493 }, + { 0x2836, 38496 }, + { 0x2856, 38499 }, + { 0x2896, 38502 }, + { 0x2866, 38505 }, + { 0x28A6, 38508 }, + { 0x28C6, 38511 }, + { 0x283A, 38514 }, + { 0x285A, 38517 }, + { 0x289A, 38520 }, + { 0x286A, 38523 }, + { 0x28AA, 38526 }, + { 0x28CA, 38529 }, + { 0x2872, 38532 }, + { 0x28B2, 38535 }, + { 0x28D2, 38538 }, + { 0x28E2, 38541 }, + { 0x283C, 38544 }, + { 0x285C, 38547 }, + { 0x289C, 38550 }, + { 0x286C, 38553 }, + { 0x28AC, 38556 }, + { 0x28CC, 38559 }, + { 0x2874, 38562 }, + { 0x28B4, 38565 }, + { 0x28D4, 38568 }, + { 0x28E4, 38571 }, + { 0x2878, 38574 }, + { 0x28B8, 38577 }, + { 0x28D8, 38580 }, + { 0x28E8, 38583 }, + { 0x28F0, 38586 }, + { 0x281F, 38589 }, + { 0x282F, 38592 }, + { 0x284F, 38595 }, + { 0x288F, 38598 }, + { 0x2837, 38601 }, + { 0x2857, 38604 }, + { 0x2897, 38607 }, + { 0x2867, 38610 }, + { 0x28A7, 38613 }, + { 0x28C7, 38616 }, + { 0x283B, 38619 }, + { 0x285B, 38622 }, + { 0x289B, 38625 }, + { 0x286B, 38628 }, + { 0x28AB, 38631 }, + { 0x28CB, 38634 }, + { 0x2873, 38637 }, + { 0x28B3, 38640 }, + { 0x28D3, 38643 }, + { 0x28E3, 38646 }, + { 0x283D, 38649 }, + { 0x285D, 38652 }, + { 0x289D, 38655 }, + { 0x286D, 38658 }, + { 0x28AD, 38661 }, + { 0x28CD, 38664 }, + { 0x2875, 38667 }, + { 0x28B5, 38670 }, + { 0x28D5, 38673 }, + { 0x28E5, 38676 }, + { 0x2879, 38679 }, + { 0x28B9, 38682 }, + { 0x28D9, 38685 }, + { 0x28E9, 38688 }, + { 0x28F1, 38691 }, + { 0x283E, 38694 }, + { 0x285E, 38697 }, + { 0x289E, 38700 }, + { 0x286E, 38703 }, + { 0x28AE, 38706 }, + { 0x28CE, 38709 }, + { 0x2876, 38712 }, + { 0x28B6, 38715 }, + { 0x28D6, 38718 }, + { 0x28E6, 38721 }, + { 0x287A, 38724 }, + { 0x28BA, 38727 }, + { 0x28DA, 38730 }, + { 0x28EA, 38733 }, + { 0x28F2, 38736 }, + { 0x287C, 38739 }, + { 0x28BC, 38742 }, + { 0x28DC, 38745 }, + { 0x28EC, 38748 }, + { 0x28F4, 38751 }, + { 0x28F8, 38754 }, + { 0x283F, 38757 }, + { 0x285F, 38760 }, + { 0x289F, 38763 }, + { 0x286F, 38766 }, + { 0x28AF, 38769 }, + { 0x28CF, 38772 }, + { 0x2877, 38775 }, + { 0x28B7, 38778 }, + { 0x28D7, 38781 }, + { 0x28E7, 38784 }, + { 0x287B, 38787 }, + { 0x28BB, 38790 }, + { 0x28DB, 38793 }, + { 0x28EB, 38796 }, + { 0x28F3, 38799 }, + { 0x287D, 38802 }, + { 0x28BD, 38805 }, + { 0x28DD, 38808 }, + { 0x28ED, 38811 }, + { 0x28F5, 38814 }, + { 0x28F9, 38817 }, + { 0x287E, 38820 }, + { 0x28BE, 38823 }, + { 0x28DE, 38826 }, + { 0x28EE, 38829 }, + { 0x28F6, 38832 }, + { 0x28FA, 38835 }, + { 0x28FC, 38838 }, + { 0x287F, 38841 }, + { 0x28BF, 38844 }, + { 0x28DF, 38847 }, + { 0x28EF, 38850 }, + { 0x28F7, 38853 }, + { 0x28FB, 38856 }, + { 0x28FD, 38859 }, + { 0x28FE, 38862 }, + { 0x28FF, 38865 }, + { 0x2621, 38868 }, + { 0x00B8, 38870 }, + { 0x2299, 38871 }, + { 0x229D, 38874 }, + { 0x2742, 38876 }, + { 0x2295, 38882 }, + { 0x229A, 38884 }, + { 0x2460, 38887 }, + { 0x2465, 38890 }, + { 0x2461, 38893 }, + { 0x2464, 38896 }, + { 0x2463, 38899 }, + { 0x2468, 38902 }, + { 0x24EA, 38905 }, + { 0x2467, 38908 }, + { 0x2466, 38911 }, + { 0x2462, 38914 }, + { 0x27B2, 38917 }, + { 0x24D0, 38922 }, + { 0x24D1, 38927 }, + { 0x24D2, 38932 }, + { 0x24D3, 38937 }, + { 0x24D4, 38942 }, + { 0x24D5, 38947 }, + { 0x24D6, 38952 }, + { 0x24D7, 38957 }, + { 0x24D8, 38962 }, + { 0x24D9, 38967 }, + { 0x24DA, 38972 }, + { 0x24DB, 38977 }, + { 0x24DC, 38982 }, + { 0x24DD, 38987 }, + { 0x24DE, 38992 }, + { 0x24DF, 38997 }, + { 0x24E0, 39002 }, + { 0x24E1, 39007 }, + { 0x24E2, 39012 }, + { 0x24E3, 39017 }, + { 0x24E4, 39022 }, + { 0x24E5, 39027 }, + { 0x24E6, 39032 }, + { 0x24E7, 39037 }, + { 0x24E8, 39042 }, + { 0x24E9, 39047 }, + { 0x24B6, 39052 }, + { 0x24B7, 39057 }, + { 0x24B8, 39062 }, + { 0x24B9, 39067 }, + { 0x24BA, 39072 }, + { 0x24BB, 39077 }, + { 0x24BC, 39082 }, + { 0x24BD, 39087 }, + { 0x24BE, 39092 }, + { 0x24BF, 39097 }, + { 0x24C0, 39102 }, + { 0x24C1, 39107 }, + { 0x24C2, 39112 }, + { 0x24C3, 39117 }, + { 0x24C4, 39122 }, + { 0x24C5, 39127 }, + { 0x24C6, 39132 }, + { 0x24C7, 39137 }, + { 0x24C8, 39142 }, + { 0x24C9, 39147 }, + { 0x24CA, 39152 }, + { 0x24CB, 39157 }, + { 0x24CC, 39162 }, + { 0x24CD, 39167 }, + { 0x24CE, 39172 }, + { 0x24CF, 39177 }, + { 0x2296, 39182 }, + { 0x2297, 39184 }, + { 0x272A, 39186 }, + { 0x29BE, 39189 }, + { 0x29BF, 39192 }, + { 0x229C, 39194 }, + { 0x3266, 39196 }, + { 0x3274, 39199 }, + { 0x3268, 39203 }, + { 0x3276, 39206 }, + { 0x326D, 39210 }, + { 0x327B, 39213 }, + { 0x3267, 39217 }, + { 0x3275, 39220 }, + { 0x327E, 39224 }, + { 0x3264, 39228 }, + { 0x3272, 39231 }, + { 0x3261, 39235 }, + { 0x326F, 39238 }, + { 0x3265, 39242 }, + { 0x3273, 39245 }, + { 0x3263, 39249 }, + { 0x3271, 39252 }, + { 0x3260, 39256 }, + { 0x326E, 39259 }, + { 0x3262, 39263 }, + { 0x3270, 39266 }, + { 0x3269, 39270 }, + { 0x3277, 39273 }, + { 0x326A, 39277 }, + { 0x3278, 39280 }, + { 0x326C, 39284 }, + { 0x327A, 39287 }, + { 0x326B, 39291 }, + { 0x3279, 39294 }, + { 0x327D, 39298 }, + { 0x327C, 39302 }, + { 0x2469, 39306 }, + { 0x32BF, 39309 }, + { 0x32B5, 39312 }, + { 0x32B6, 39315 }, + { 0x32BB, 39319 }, + { 0x32B7, 39323 }, + { 0x32BA, 39327 }, + { 0x32B9, 39331 }, + { 0x32BE, 39335 }, + { 0x32BD, 39339 }, + { 0x32BC, 39343 }, + { 0x32B8, 39347 }, + { 0x246A, 39351 }, + { 0x325A, 39354 }, + { 0x325B, 39357 }, + { 0x32B1, 39361 }, + { 0x325C, 39365 }, + { 0x325F, 39369 }, + { 0x325E, 39373 }, + { 0x32B4, 39377 }, + { 0x32B3, 39381 }, + { 0x32B2, 39385 }, + { 0x325D, 39389 }, + { 0x246B, 39393 }, + { 0x2473, 39396 }, + { 0x3251, 39399 }, + { 0x3256, 39403 }, + { 0x3252, 39407 }, + { 0x3255, 39411 }, + { 0x3254, 39415 }, + { 0x3259, 39419 }, + { 0x3258, 39423 }, + { 0x3257, 39427 }, + { 0x3253, 39431 }, + { 0x246E, 39435 }, + { 0x246F, 39438 }, + { 0x2471, 39441 }, + { 0x246D, 39444 }, + { 0x2472, 39447 }, + { 0x246C, 39450 }, + { 0x2470, 39453 }, + { 0x3036, 39456 }, + { 0x29B8, 39459 }, + { 0x229B, 39462 }, + { 0x2A38, 39465 }, + { 0x2298, 39468 }, + { 0x32D0, 39471 }, + { 0x32D3, 39474 }, + { 0x32D1, 39477 }, + { 0x32D4, 39480 }, + { 0x32D2, 39483 }, + { 0x32E9, 39486 }, + { 0x32EC, 39489 }, + { 0x32EA, 39492 }, + { 0x32ED, 39495 }, + { 0x32EB, 39498 }, + { 0x32D5, 39501 }, + { 0x32D8, 39504 }, + { 0x32D6, 39507 }, + { 0x32D9, 39510 }, + { 0x32D7, 39513 }, + { 0x32EE, 39516 }, + { 0x32F1, 39519 }, + { 0x32EF, 39522 }, + { 0x32F2, 39525 }, + { 0x32F0, 39528 }, + { 0x32E4, 39531 }, + { 0x32E7, 39534 }, + { 0x32E5, 39537 }, + { 0x32E8, 39540 }, + { 0x32E6, 39543 }, + { 0x32F6, 39546 }, + { 0x32F9, 39549 }, + { 0x32F7, 39552 }, + { 0x32FA, 39555 }, + { 0x32F8, 39558 }, + { 0x32DA, 39561 }, + { 0x32DD, 39564 }, + { 0x32DB, 39567 }, + { 0x32DE, 39570 }, + { 0x32DC, 39573 }, + { 0x32DF, 39576 }, + { 0x32E2, 39579 }, + { 0x32E0, 39582 }, + { 0x32E3, 39585 }, + { 0x32E1, 39588 }, + { 0x32FB, 39591 }, + { 0x32FD, 39594 }, + { 0x32FC, 39597 }, + { 0x32FE, 39600 }, + { 0x32F3, 39603 }, + { 0x32F5, 39606 }, + { 0x32F4, 39609 }, + { 0x29B7, 39612 }, + { 0x238A, 39614 }, + { 0x29B6, 39617 }, + { 0x32A6, 39620 }, + { 0x3280, 39623 }, + { 0x3285, 39626 }, + { 0x3290, 39629 }, + { 0x3289, 39632 }, + { 0x3281, 39635 }, + { 0x32A2, 39638 }, + { 0x328B, 39641 }, + { 0x3284, 39644 }, + { 0x3283, 39647 }, + { 0x3292, 39650 }, + { 0x32A4, 39653 }, + { 0x32A0, 39656 }, + { 0x32A7, 39659 }, + { 0x329A, 39662 }, + { 0x328A, 39665 }, + { 0x3294, 39668 }, + { 0x3288, 39671 }, + { 0x32A1, 39674 }, + { 0x328D, 39677 }, + { 0x328F, 39680 }, + { 0x3287, 39683 }, + { 0x3298, 39686 }, + { 0x328E, 39689 }, + { 0x32B0, 39692 }, + { 0x329E, 39695 }, + { 0x32A8, 39698 }, + { 0x3286, 39701 }, + { 0x3291, 39704 }, + { 0x32AB, 39707 }, + { 0x3282, 39710 }, + { 0x328C, 39713 }, + { 0x32A5, 39716 }, + { 0x329B, 39719 }, + { 0x3299, 39722 }, + { 0x32A3, 39725 }, + { 0x3293, 39728 }, + { 0x3295, 39731 }, + { 0x32AF, 39734 }, + { 0x32A9, 39737 }, + { 0x32AA, 39740 }, + { 0x32AE, 39743 }, + { 0x329C, 39746 }, + { 0x329F, 39749 }, + { 0x329D, 39752 }, + { 0x3296, 39755 }, + { 0x32AC, 39758 }, + { 0x32AD, 39761 }, + { 0x3297, 39764 }, + { 0x29C0, 39767 }, + { 0x2389, 39769 }, + { 0x29C1, 39774 }, + { 0x29B9, 39776 }, + { 0x2A36, 39778 }, + { 0x29BC, 39784 }, + { 0x2332, 39788 }, + { 0x222E, 39790 }, + { 0x2694, 39792 }, + { 0x7800, 39794 }, + { 0x7801, 39797 }, + { 0x7802, 39800 }, + { 0x7803, 39803 }, + { 0x7804, 39806 }, + { 0x7805, 39809 }, + { 0x7808, 39812 }, + { 0x780A, 39815 }, + { 0x780B, 39818 }, + { 0x780C, 39821 }, + { 0x780D, 39824 }, + { 0x780E, 39827 }, + { 0x780F, 39830 }, + { 0x7810, 39833 }, + { 0x7811, 39836 }, + { 0x7812, 39839 }, + { 0x7813, 39842 }, + { 0x7814, 39845 }, + { 0x7815, 39848 }, + { 0x7816, 39851 }, + { 0x7817, 39854 }, + { 0x7818, 39857 }, + { 0x7819, 39860 }, + { 0x781A, 39863 }, + { 0x781B, 39866 }, + { 0x781C, 39869 }, + { 0x781D, 39872 }, + { 0x781E, 39875 }, + { 0x781F, 39878 }, + { 0x7820, 39881 }, + { 0x7821, 39884 }, + { 0x7822, 39887 }, + { 0x7823, 39890 }, + { 0x7824, 39893 }, + { 0x7825, 39896 }, + { 0x7826, 39899 }, + { 0x7827, 39902 }, + { 0x7828, 39905 }, + { 0x7829, 39908 }, + { 0x782A, 39911 }, + { 0x782B, 39914 }, + { 0x782C, 39917 }, + { 0x782D, 39920 }, + { 0x782E, 39923 }, + { 0x782F, 39926 }, + { 0x7830, 39929 }, + { 0x7831, 39932 }, + { 0x7832, 39935 }, + { 0x7833, 39938 }, + { 0x7834, 39941 }, + { 0x7835, 39944 }, + { 0x7837, 39947 }, + { 0x7838, 39950 }, + { 0x783C, 39953 }, + { 0x783F, 39956 }, + { 0x2396, 39959 }, + { 0x7438, 39963 }, + { 0x7434, 39967 }, + { 0x7441, 39971 }, + { 0x744A, 39975 }, + { 0x744B, 39979 }, + { 0x744C, 39983 }, + { 0x7449, 39987 }, + { 0x7445, 39991 }, + { 0x744F, 39995 }, + { 0x744E, 39999 }, + { 0x7435, 40003 }, + { 0x7436, 40007 }, + { 0x743A, 40011 }, + { 0x743C, 40015 }, + { 0x744D, 40019 }, + { 0x7447, 40023 }, + { 0x7443, 40027 }, + { 0x7440, 40031 }, + { 0x743E, 40035 }, + { 0x743F, 40039 }, + { 0x7439, 40043 }, + { 0x743B, 40047 }, + { 0x7442, 40051 }, + { 0x7437, 40055 }, + { 0x7446, 40059 }, + { 0x743D, 40063 }, + { 0x742A, 40067 }, + { 0x7429, 40072 }, + { 0x7428, 40077 }, + { 0x742C, 40082 }, + { 0x742B, 40087 }, + { 0x742D, 40092 }, + { 0x7444, 40097 }, + { 0x7448, 40101 }, + { 0x7430, 40105 }, + { 0x742F, 40110 }, + { 0x742E, 40115 }, + { 0x7432, 40120 }, + { 0x7431, 40125 }, + { 0x7433, 40130 }, + { 0x7410, 40135 }, + { 0x740C, 40139 }, + { 0x7419, 40143 }, + { 0x7422, 40147 }, + { 0x7423, 40151 }, + { 0x7424, 40155 }, + { 0x7421, 40159 }, + { 0x741D, 40163 }, + { 0x7427, 40167 }, + { 0x7426, 40171 }, + { 0x740D, 40175 }, + { 0x740E, 40179 }, + { 0x7412, 40183 }, + { 0x7414, 40187 }, + { 0x7425, 40191 }, + { 0x741F, 40195 }, + { 0x741B, 40199 }, + { 0x7418, 40203 }, + { 0x7416, 40207 }, + { 0x7417, 40211 }, + { 0x7411, 40215 }, + { 0x7413, 40219 }, + { 0x741A, 40223 }, + { 0x740F, 40227 }, + { 0x741E, 40231 }, + { 0x7415, 40235 }, + { 0x7402, 40239 }, + { 0x7401, 40244 }, + { 0x7400, 40249 }, + { 0x7404, 40254 }, + { 0x7403, 40259 }, + { 0x7405, 40264 }, + { 0x741C, 40269 }, + { 0x7420, 40273 }, + { 0x7408, 40277 }, + { 0x7407, 40282 }, + { 0x7406, 40287 }, + { 0x740A, 40292 }, + { 0x7409, 40297 }, + { 0x740B, 40302 }, + { 0x2B18, 40307 }, + { 0x2B16, 40312 }, + { 0x2B17, 40317 }, + { 0x2B19, 40322 }, + { 0x22C4, 40327 }, + { 0x2780, 40329 }, + { 0x2785, 40334 }, + { 0x2781, 40339 }, + { 0x2784, 40344 }, + { 0x2783, 40349 }, + { 0x2788, 40354 }, + { 0x2787, 40359 }, + { 0x2786, 40364 }, + { 0x2782, 40369 }, + { 0x2789, 40374 }, + { 0x2776, 40379 }, + { 0x277B, 40384 }, + { 0x2777, 40389 }, + { 0x277A, 40394 }, + { 0x2779, 40399 }, + { 0x277E, 40404 }, + { 0x277D, 40409 }, + { 0x277C, 40414 }, + { 0x2778, 40419 }, + { 0x277F, 40424 }, + { 0x278A, 40429 }, + { 0x278F, 40435 }, + { 0x278B, 40441 }, + { 0x278E, 40447 }, + { 0x278D, 40453 }, + { 0x2792, 40459 }, + { 0x2791, 40465 }, + { 0x2790, 40471 }, + { 0x278C, 40477 }, + { 0x2793, 40483 }, + { 0x2223, 40489 }, + { 0x26AE, 40490 }, + { 0x26A3, 40492 }, + { 0x26A2, 40495 }, + { 0x20AF, 40498 }, + { 0x2208, 40500 }, + { 0x22F5, 40502 }, + { 0x22F9, 40507 }, + { 0x22F2, 40513 }, + { 0x22F6, 40519 }, + { 0x22F8, 40523 }, + { 0x22F3, 40527 }, + { 0x27D2, 40537 }, + { 0x2AD9, 40541 }, + { 0x292F, 40545 }, + { 0x292C, 40551 }, + { 0x25C9, 40556 }, + { 0x2ADC, 40557 }, + { 0x26B1, 40558 }, + { 0x20B2, 40560 }, + { 0x1734, 40562 }, + { 0x1732, 40565 }, + { 0x1733, 40569 }, + { 0x1720, 40573 }, + { 0x1721, 40576 }, + { 0x1722, 40579 }, + { 0x172A, 40582 }, + { 0x1727, 40585 }, + { 0x1724, 40588 }, + { 0x1731, 40591 }, + { 0x1723, 40594 }, + { 0x172E, 40597 }, + { 0x172B, 40600 }, + { 0x1728, 40603 }, + { 0x1729, 40606 }, + { 0x172D, 40609 }, + { 0x1730, 40612 }, + { 0x1726, 40615 }, + { 0x172F, 40618 }, + { 0x172C, 40621 }, + { 0x1725, 40624 }, + { 0x20B4, 40627 }, + { 0x206C, 40629 }, + { 0x206A, 40633 }, + { 0x25D9, 40636 }, + { 0x25D8, 40639 }, + { 0x2643, 40641 }, + { 0x0CD6, 40642 }, + { 0x0CBC, 40646 }, + { 0x0CCD, 40649 }, + { 0x0C83, 40652 }, + { 0x0C82, 40655 }, + { 0x0CBD, 40658 }, + { 0x0CF1, 40661 }, + { 0x0CF2, 40664 }, + { 0x0CE7, 40667 }, + { 0x0CEC, 40670 }, + { 0x0CE8, 40673 }, + { 0x0CEB, 40676 }, + { 0x0CEA, 40679 }, + { 0x0CEF, 40682 }, + { 0x0CE6, 40685 }, + { 0x0CEE, 40688 }, + { 0x0CED, 40691 }, + { 0x0CE9, 40694 }, + { 0x0CC6, 40697 }, + { 0x0CBF, 40701 }, + { 0x0CCA, 40705 }, + { 0x0CC1, 40709 }, + { 0x0CBE, 40713 }, + { 0x0CC8, 40717 }, + { 0x0CCC, 40721 }, + { 0x0CC7, 40725 }, + { 0x0CC0, 40729 }, + { 0x0CCB, 40733 }, + { 0x0CC2, 40737 }, + { 0x0CE2, 40741 }, + { 0x0CC3, 40746 }, + { 0x0CE3, 40751 }, + { 0x0CC4, 40756 }, + { 0x0CD5, 40761 }, + { 0x0C85, 40764 }, + { 0x0C8E, 40767 }, + { 0x0C87, 40770 }, + { 0x0C92, 40773 }, + { 0x0C89, 40776 }, + { 0x0C86, 40779 }, + { 0x0C90, 40782 }, + { 0x0C94, 40785 }, + { 0x0CAC, 40788 }, + { 0x0C9A, 40791 }, + { 0x0CA6, 40794 }, + { 0x0C8F, 40797 }, + { 0x0CDE, 40800 }, + { 0x0C97, 40803 }, + { 0x0CB9, 40806 }, + { 0x0C88, 40809 }, + { 0x0C9C, 40812 }, + { 0x0C95, 40815 }, + { 0x0CB2, 40818 }, + { 0x0CAE, 40821 }, + { 0x0CA8, 40824 }, + { 0x0C93, 40827 }, + { 0x0CAA, 40830 }, + { 0x0CB0, 40833 }, + { 0x0CB8, 40836 }, + { 0x0CA4, 40839 }, + { 0x0C8A, 40842 }, + { 0x0CB5, 40845 }, + { 0x0CAF, 40848 }, + { 0x0CAD, 40851 }, + { 0x0C9B, 40854 }, + { 0x0CA1, 40857 }, + { 0x0CA7, 40860 }, + { 0x0C98, 40863 }, + { 0x0C9D, 40866 }, + { 0x0C96, 40869 }, + { 0x0CB3, 40872 }, + { 0x0C99, 40875 }, + { 0x0CA3, 40878 }, + { 0x0C9E, 40881 }, + { 0x0CAB, 40884 }, + { 0x0CB1, 40887 }, + { 0x0CB6, 40890 }, + { 0x0CB7, 40893 }, + { 0x0CA5, 40896 }, + { 0x0C9F, 40899 }, + { 0x0CA2, 40902 }, + { 0x0CA0, 40905 }, + { 0x0C8C, 40908 }, + { 0x0C8B, 40912 }, + { 0x0CE1, 40916 }, + { 0x0CE0, 40920 }, + { 0x32CF, 40924 }, + { 0x2228, 40927 }, + { 0x2A52, 40929 }, + { 0x2A62, 40934 }, + { 0x2A63, 40939 }, + { 0x2A5B, 40944 }, + { 0x2A5D, 40949 }, + { 0x2A59, 40954 }, + { 0x2227, 40959 }, + { 0x2A51, 40961 }, + { 0x2A5E, 40966 }, + { 0x2A60, 40971 }, + { 0x2A5A, 40976 }, + { 0x2A5F, 40981 }, + { 0x2A5C, 40985 }, + { 0x25CA, 40990 }, + { 0x27E0, 40991 }, + { 0xA010, 40996 }, + { 0xA019, 41001 }, + { 0xA007, 41006 }, + { 0xA004, 41011 }, + { 0xA015, 41015 }, + { 0xA01E, 41020 }, + { 0xA00C, 41025 }, + { 0xA011, 41030 }, + { 0xA01A, 41035 }, + { 0xA008, 41040 }, + { 0xA02B, 41045 }, + { 0xA000, 41048 }, + { 0xA014, 41052 }, + { 0xA01D, 41057 }, + { 0xA00B, 41062 }, + { 0xA013, 41067 }, + { 0xA01C, 41072 }, + { 0xA00A, 41077 }, + { 0xA018, 41082 }, + { 0xA021, 41087 }, + { 0xA00F, 41092 }, + { 0xA022, 41097 }, + { 0xA002, 41100 }, + { 0xA017, 41104 }, + { 0xA020, 41109 }, + { 0xA00E, 41114 }, + { 0xA005, 41119 }, + { 0xA02A, 41123 }, + { 0xA003, 41126 }, + { 0xA016, 41130 }, + { 0xA01F, 41135 }, + { 0xA00D, 41140 }, + { 0xA001, 41145 }, + { 0xA012, 41149 }, + { 0xA01B, 41154 }, + { 0xA009, 41159 }, + { 0xA006, 41164 }, + { 0xA028, 41168 }, + { 0xA024, 41171 }, + { 0xA023, 41174 }, + { 0xA026, 41177 }, + { 0xA027, 41180 }, + { 0xA029, 41183 }, + { 0xA025, 41186 }, + { 0x2720, 41189 }, + { 0x263F, 41191 }, + { 0x22EF, 41192 }, + { 0x9121, 41195 }, + { 0x9122, 41199 }, + { 0x9123, 41203 }, + { 0x9124, 41209 }, + { 0x911E, 41215 }, + { 0x911F, 41219 }, + { 0x9120, 41225 }, + { 0x9143, 41231 }, + { 0x918E, 41235 }, + { 0x910A, 41238 }, + { 0x9196, 41242 }, + { 0x9135, 41245 }, + { 0x9109, 41249 }, + { 0x91A8, 41253 }, + { 0x9176, 41258 }, + { 0x9174, 41262 }, + { 0x9178, 41266 }, + { 0x917A, 41270 }, + { 0x9164, 41274 }, + { 0x9142, 41280 }, + { 0x91DD, 41286 }, + { 0x910C, 41290 }, + { 0x91B4, 41293 }, + { 0x91B5, 41296 }, + { 0x9125, 41300 }, + { 0x9126, 41304 }, + { 0x912C, 41308 }, + { 0x912D, 41312 }, + { 0x91C0, 41316 }, + { 0x91BF, 41320 }, + { 0x915E, 41324 }, + { 0x913C, 41328 }, + { 0x91B0, 41332 }, + { 0x9106, 41337 }, + { 0x9153, 41342 }, + { 0x9152, 41347 }, + { 0x9159, 41352 }, + { 0x9144, 41356 }, + { 0x9197, 41360 }, + { 0x919A, 41363 }, + { 0x9199, 41367 }, + { 0x9157, 41371 }, + { 0x91B3, 41375 }, + { 0x9175, 41379 }, + { 0x9173, 41383 }, + { 0x9177, 41387 }, + { 0x9179, 41391 }, + { 0x9114, 41395 }, + { 0x915C, 41398 }, + { 0x91CF, 41401 }, + { 0x9102, 41404 }, + { 0x9191, 41408 }, + { 0x9195, 41411 }, + { 0x9194, 41417 }, + { 0x91B7, 41422 }, + { 0x91C1, 41425 }, + { 0x91C2, 41430 }, + { 0x9190, 41435 }, + { 0x913A, 41438 }, + { 0x91AF, 41442 }, + { 0x91AE, 41447 }, + { 0x918F, 41451 }, + { 0x9107, 41454 }, + { 0x910B, 41459 }, + { 0x9130, 41462 }, + { 0x9131, 41466 }, + { 0x9105, 41470 }, + { 0x91D3, 41474 }, + { 0x915D, 41477 }, + { 0x913B, 41481 }, + { 0x9112, 41485 }, + { 0x91B8, 41489 }, + { 0x91C3, 41492 }, + { 0x9145, 41496 }, + { 0x91D5, 41501 }, + { 0x9134, 41504 }, + { 0x9104, 41508 }, + { 0x91A9, 41512 }, + { 0x912B, 41516 }, + { 0x912A, 41520 }, + { 0x9101, 41524 }, + { 0x9160, 41528 }, + { 0x913E, 41532 }, + { 0x91B6, 41536 }, + { 0x91BB, 41539 }, + { 0x91C5, 41542 }, + { 0x91BC, 41546 }, + { 0x9136, 41550 }, + { 0x9137, 41554 }, + { 0x9108, 41558 }, + { 0x9100, 41562 }, + { 0x91D2, 41566 }, + { 0x9147, 41570 }, + { 0x9146, 41575 }, + { 0x918D, 41580 }, + { 0x91C7, 41583 }, + { 0x91C9, 41590 }, + { 0x91C8, 41598 }, + { 0x91CA, 41605 }, + { 0x91CB, 41612 }, + { 0x91CC, 41619 }, + { 0x91CD, 41627 }, + { 0x91CE, 41635 }, + { 0x9115, 41643 }, + { 0x9113, 41646 }, + { 0x915B, 41649 }, + { 0x915A, 41654 }, + { 0x9110, 41659 }, + { 0x9111, 41662 }, + { 0x912E, 41666 }, + { 0x912F, 41670 }, + { 0x91D4, 41674 }, + { 0x915F, 41677 }, + { 0x913D, 41681 }, + { 0x9133, 41685 }, + { 0x9132, 41690 }, + { 0x9103, 41695 }, + { 0x91D7, 41700 }, + { 0x916A, 41703 }, + { 0x916B, 41707 }, + { 0x916C, 41711 }, + { 0x9198, 41715 }, + { 0x9129, 41719 }, + { 0x9158, 41724 }, + { 0x9116, 41728 }, + { 0x919B, 41732 }, + { 0x919C, 41736 }, + { 0x919D, 41740 }, + { 0x919E, 41744 }, + { 0x919F, 41748 }, + { 0x91A0, 41752 }, + { 0x91A1, 41756 }, + { 0x91A2, 41760 }, + { 0x91A3, 41764 }, + { 0x91A4, 41768 }, + { 0x91A5, 41772 }, + { 0x910D, 41776 }, + { 0x910E, 41780 }, + { 0x910F, 41784 }, + { 0x911B, 41788 }, + { 0x91D8, 41792 }, + { 0x91DC, 41795 }, + { 0x9149, 41799 }, + { 0x9151, 41805 }, + { 0x9150, 41812 }, + { 0x9148, 41819 }, + { 0x914F, 41825 }, + { 0x914E, 41831 }, + { 0x914B, 41837 }, + { 0x914A, 41843 }, + { 0x914D, 41849 }, + { 0x914C, 41855 }, + { 0x9117, 41861 }, + { 0x91AB, 41865 }, + { 0x9186, 41870 }, + { 0x9189, 41874 }, + { 0x9185, 41878 }, + { 0x91AA, 41882 }, + { 0x9187, 41887 }, + { 0x91AD, 41891 }, + { 0x9165, 41896 }, + { 0x9182, 41900 }, + { 0x9188, 41904 }, + { 0x917B, 41908 }, + { 0x918A, 41912 }, + { 0x916E, 41917 }, + { 0x916F, 41921 }, + { 0x9170, 41925 }, + { 0x9171, 41929 }, + { 0x9172, 41933 }, + { 0x917D, 41937 }, + { 0x918B, 41941 }, + { 0x917F, 41946 }, + { 0x91AC, 41950 }, + { 0x917C, 41954 }, + { 0x9167, 41958 }, + { 0x9168, 41962 }, + { 0x9169, 41966 }, + { 0x916D, 41970 }, + { 0x9166, 41975 }, + { 0x917E, 41980 }, + { 0x9181, 41984 }, + { 0x9180, 41988 }, + { 0x9192, 41992 }, + { 0x911A, 41995 }, + { 0x9119, 41999 }, + { 0x91B1, 42003 }, + { 0x91B2, 42007 }, + { 0x91D0, 42011 }, + { 0x91D1, 42016 }, + { 0x91D9, 42021 }, + { 0x91DA, 42024 }, + { 0x91D6, 42028 }, + { 0x91DB, 42031 }, + { 0x9161, 42035 }, + { 0x913F, 42039 }, + { 0x9183, 42043 }, + { 0x9184, 42047 }, + { 0x91C4, 42051 }, + { 0x91BA, 42055 }, + { 0x91B9, 42059 }, + { 0x91C6, 42063 }, + { 0x91BE, 42067 }, + { 0x91BD, 42071 }, + { 0x911C, 42075 }, + { 0x9118, 42079 }, + { 0x9193, 42083 }, + { 0x911D, 42086 }, + { 0x91A6, 42090 }, + { 0x91A7, 42093 }, + { 0x9156, 42096 }, + { 0x918C, 42100 }, + { 0x9138, 42103 }, + { 0x9139, 42107 }, + { 0x9163, 42111 }, + { 0x9141, 42115 }, + { 0x9162, 42119 }, + { 0x9140, 42123 }, + { 0x9155, 42127 }, + { 0x9154, 42133 }, + { 0x1091, 42139 }, + { 0x1096, 42143 }, + { 0x1092, 42147 }, + { 0x1095, 42151 }, + { 0x1094, 42155 }, + { 0x1099, 42159 }, + { 0x1090, 42163 }, + { 0x1098, 42167 }, + { 0x1097, 42171 }, + { 0x1093, 42175 }, + { 0x1037, 42179 }, + { 0x103A, 42183 }, + { 0x1087, 42186 }, + { 0x1088, 42190 }, + { 0x1089, 42194 }, + { 0x108A, 42198 }, + { 0x108B, 42202 }, + { 0x108C, 42207 }, + { 0x108D, 42212 }, + { 0x108F, 42218 }, + { 0x104A, 42223 }, + { 0x1039, 42227 }, + { 0x104B, 42230 }, + { 0x1038, 42233 }, + { 0x1069, 42236 }, + { 0x106A, 42242 }, + { 0x106B, 42248 }, + { 0x106C, 42254 }, + { 0x106D, 42260 }, + { 0x1036, 42266 }, + { 0x1064, 42269 }, + { 0x1063, 42276 }, + { 0x1041, 42282 }, + { 0x1046, 42285 }, + { 0x1042, 42288 }, + { 0x1045, 42291 }, + { 0x1044, 42294 }, + { 0x1049, 42297 }, + { 0x1040, 42300 }, + { 0x1048, 42303 }, + { 0x1047, 42306 }, + { 0x1043, 42309 }, + { 0x1031, 42312 }, + { 0x1035, 42316 }, + { 0x102D, 42321 }, + { 0x102F, 42325 }, + { 0x102C, 42329 }, + { 0x1032, 42333 }, + { 0x102E, 42337 }, + { 0x1030, 42341 }, + { 0x1034, 42345 }, + { 0x1033, 42350 }, + { 0x1071, 42355 }, + { 0x1062, 42361 }, + { 0x1084, 42367 }, + { 0x1085, 42372 }, + { 0x1083, 42378 }, + { 0x1086, 42383 }, + { 0x102B, 42389 }, + { 0x1073, 42394 }, + { 0x1074, 42399 }, + { 0x1072, 42404 }, + { 0x1058, 42409 }, + { 0x1056, 42414 }, + { 0x1059, 42419 }, + { 0x1057, 42424 }, + { 0x1067, 42429 }, + { 0x1068, 42436 }, + { 0x1021, 42443 }, + { 0x1027, 42446 }, + { 0x1023, 42449 }, + { 0x1029, 42452 }, + { 0x1025, 42455 }, + { 0x102A, 42458 }, + { 0x1017, 42461 }, + { 0x1005, 42464 }, + { 0x1012, 42467 }, + { 0x1002, 42470 }, + { 0x101F, 42473 }, + { 0x1024, 42476 }, + { 0x1007, 42479 }, + { 0x1000, 42482 }, + { 0x101C, 42485 }, + { 0x1019, 42488 }, + { 0x1014, 42491 }, + { 0x1015, 42494 }, + { 0x101B, 42497 }, + { 0x101E, 42500 }, + { 0x1010, 42503 }, + { 0x1026, 42506 }, + { 0x101D, 42509 }, + { 0x101A, 42512 }, + { 0x1018, 42515 }, + { 0x1006, 42518 }, + { 0x100D, 42521 }, + { 0x1013, 42524 }, + { 0x1003, 42527 }, + { 0x1008, 42530 }, + { 0x1001, 42533 }, + { 0x1020, 42536 }, + { 0x1028, 42539 }, + { 0x105C, 42543 }, + { 0x105D, 42547 }, + { 0x105B, 42551 }, + { 0x105A, 42555 }, + { 0x1004, 42559 }, + { 0x100F, 42562 }, + { 0x1009, 42565 }, + { 0x1016, 42568 }, + { 0x1050, 42571 }, + { 0x1051, 42574 }, + { 0x1011, 42577 }, + { 0x100B, 42580 }, + { 0x100E, 42583 }, + { 0x100A, 42586 }, + { 0x1061, 42589 }, + { 0x1022, 42594 }, + { 0x107F, 42598 }, + { 0x1078, 42602 }, + { 0x107B, 42606 }, + { 0x107E, 42610 }, + { 0x1077, 42614 }, + { 0x1081, 42618 }, + { 0x1075, 42622 }, + { 0x107C, 42626 }, + { 0x1079, 42630 }, + { 0x1076, 42634 }, + { 0x107A, 42638 }, + { 0x107D, 42642 }, + { 0x1080, 42646 }, + { 0x100C, 42650 }, + { 0x103F, 42653 }, + { 0x108E, 42657 }, + { 0x106E, 42662 }, + { 0x106F, 42668 }, + { 0x1070, 42674 }, + { 0x1054, 42680 }, + { 0x1052, 42684 }, + { 0x1055, 42688 }, + { 0x1053, 42692 }, + { 0x1066, 42696 }, + { 0x1065, 42702 }, + { 0x109E, 42708 }, + { 0x109F, 42712 }, + { 0x104F, 42716 }, + { 0x104C, 42719 }, + { 0x104D, 42722 }, + { 0x104E, 42725 }, + { 0x1060, 42728 }, + { 0x105F, 42734 }, + { 0x105E, 42740 }, + { 0x1082, 42746 }, + { 0x103E, 42752 }, + { 0x103C, 42757 }, + { 0x103D, 42762 }, + { 0x103B, 42767 }, + { 0x22AF, 42772 }, + { 0x2288, 42779 }, + { 0x2289, 42786 }, + { 0x2270, 42793 }, + { 0x2274, 42798 }, + { 0x2278, 42803 }, + { 0x2271, 42807 }, + { 0x2279, 42812 }, + { 0x2275, 42816 }, + { 0x2247, 42821 }, + { 0x2646, 42827 }, + { 0x206F, 42828 }, + { 0x27AF, 42831 }, + { 0x27B1, 42837 }, + { 0x29A6, 42843 }, + { 0x29A7, 42847 }, + { 0x74A1, 42851 }, + { 0x74A6, 42854 }, + { 0x74A2, 42857 }, + { 0x74A5, 42860 }, + { 0x74A4, 42863 }, + { 0x74A9, 42866 }, + { 0x74A0, 42869 }, + { 0x74A8, 42872 }, + { 0x74A7, 42875 }, + { 0x74A3, 42878 }, + { 0x7496, 42881 }, + { 0x7497, 42884 }, + { 0x7498, 42887 }, + { 0x7499, 42890 }, + { 0x749A, 42893 }, + { 0x749B, 42896 }, + { 0x7481, 42899 }, + { 0x749C, 42902 }, + { 0x748D, 42905 }, + { 0x748C, 42908 }, + { 0x7494, 42911 }, + { 0x7483, 42914 }, + { 0x749D, 42917 }, + { 0x7487, 42920 }, + { 0x7488, 42923 }, + { 0x7482, 42926 }, + { 0x7484, 42929 }, + { 0x7495, 42932 }, + { 0x748A, 42935 }, + { 0x7485, 42938 }, + { 0x7493, 42941 }, + { 0x7480, 42944 }, + { 0x748B, 42947 }, + { 0x7486, 42950 }, + { 0x748F, 42953 }, + { 0x7490, 42956 }, + { 0x7491, 42959 }, + { 0x7492, 42962 }, + { 0x748E, 42965 }, + { 0x7489, 42968 }, + { 0x2202, 42971 }, + { 0x0025, 42973 }, + { 0x00B6, 42975 }, + { 0x2669, 42977 }, + { 0x23B7, 42979 }, + { 0x2B41, 42982 }, + { 0x2B47, 42988 }, + { 0x005C, 42994 }, + { 0x29F7, 42996 }, + { 0x29F5, 43001 }, + { 0x27C8, 43004 }, + { 0x2765, 43008 }, + { 0x2767, 43013 }, + { 0x213A, 43017 }, + { 0x2613, 43020 }, + { 0x2108, 43021 }, + { 0x00A7, 43022 }, + { 0x2313, 43024 }, + { 0x2120, 43025 }, + { 0x26B9, 43027 }, + { 0x746D, 43028 }, + { 0x7466, 43031 }, + { 0x746A, 43034 }, + { 0x7479, 43037 }, + { 0x7455, 43040 }, + { 0x7473, 43043 }, + { 0x7469, 43046 }, + { 0x7471, 43049 }, + { 0x747A, 43052 }, + { 0x7478, 43055 }, + { 0x7468, 43058 }, + { 0x7477, 43061 }, + { 0x745A, 43064 }, + { 0x747D, 43067 }, + { 0x7470, 43070 }, + { 0x7467, 43073 }, + { 0x747B, 43076 }, + { 0x7453, 43079 }, + { 0x745C, 43082 }, + { 0x747E, 43085 }, + { 0x7472, 43088 }, + { 0x746F, 43091 }, + { 0x7474, 43094 }, + { 0x7476, 43097 }, + { 0x746C, 43100 }, + { 0x7451, 43103 }, + { 0x745D, 43106 }, + { 0x7462, 43109 }, + { 0x7458, 43112 }, + { 0x747F, 43115 }, + { 0x745F, 43118 }, + { 0x745B, 43121 }, + { 0x7459, 43124 }, + { 0x7452, 43127 }, + { 0x7464, 43130 }, + { 0x7465, 43133 }, + { 0x7475, 43136 }, + { 0x7450, 43139 }, + { 0x746E, 43142 }, + { 0x7456, 43145 }, + { 0x745E, 43148 }, + { 0x746B, 43151 }, + { 0x747C, 43154 }, + { 0x7463, 43157 }, + { 0x7461, 43160 }, + { 0x7454, 43163 }, + { 0x7457, 43166 }, + { 0x7460, 43169 }, + { 0x29E2, 43172 }, + { 0x2A9D, 43174 }, + { 0x2A9E, 43177 }, + { 0x2A9F, 43180 }, + { 0x2AA0, 43186 }, + { 0x2A6C, 43192 }, + { 0x0DCA, 43195 }, + { 0x0D83, 43198 }, + { 0x0D82, 43201 }, + { 0x0DDA, 43204 }, + { 0x0DD3, 43209 }, + { 0x0DD6, 43214 }, + { 0x0DD1, 43219 }, + { 0x0DF3, 43224 }, + { 0x0DF2, 43229 }, + { 0x0DD2, 43234 }, + { 0x0DD4, 43239 }, + { 0x0DD0, 43244 }, + { 0x0DDB, 43249 }, + { 0x0DD9, 43254 }, + { 0x0DDD, 43258 }, + { 0x0DDC, 43265 }, + { 0x0DDE, 43271 }, + { 0x0DCF, 43277 }, + { 0x0DDF, 43281 }, + { 0x0DD8, 43285 }, + { 0x0DB9, 43289 }, + { 0x0D85, 43293 }, + { 0x0D91, 43296 }, + { 0x0D89, 43299 }, + { 0x0D94, 43302 }, + { 0x0D8B, 43305 }, + { 0x0D86, 43308 }, + { 0x0D87, 43311 }, + { 0x0D93, 43314 }, + { 0x0D96, 43317 }, + { 0x0DBD, 43320 }, + { 0x0DB1, 43324 }, + { 0x0DC3, 43328 }, + { 0x0D92, 43332 }, + { 0x0DC6, 43335 }, + { 0x0DC4, 43338 }, + { 0x0D8A, 43341 }, + { 0x0D9E, 43344 }, + { 0x0DB8, 43348 }, + { 0x0D95, 43351 }, + { 0x0DBB, 43354 }, + { 0x0DB3, 43357 }, + { 0x0D9F, 43361 }, + { 0x0DA6, 43365 }, + { 0x0DAC, 43369 }, + { 0x0DC1, 43373 }, + { 0x0DA5, 43377 }, + { 0x0DA4, 43382 }, + { 0x0D8C, 43386 }, + { 0x0DC0, 43389 }, + { 0x0DBA, 43392 }, + { 0x0D88, 43395 }, + { 0x0D8F, 43398 }, + { 0x0D8D, 43401 }, + { 0x0D90, 43404 }, + { 0x0D8E, 43407 }, + { 0x0DC5, 43410 }, + { 0x0DAB, 43414 }, + { 0x0DC2, 43418 }, + { 0x0DB6, 43422 }, + { 0x0DA0, 43426 }, + { 0x0DAF, 43430 }, + { 0x0D9C, 43434 }, + { 0x0DA2, 43438 }, + { 0x0D9A, 43442 }, + { 0x0DB4, 43446 }, + { 0x0DAD, 43450 }, + { 0x0DA9, 43454 }, + { 0x0DA7, 43458 }, + { 0x0DB7, 43462 }, + { 0x0DA1, 43466 }, + { 0x0DB0, 43470 }, + { 0x0D9D, 43474 }, + { 0x0DA3, 43478 }, + { 0x0D9B, 43482 }, + { 0x0DB5, 43486 }, + { 0x0DAE, 43490 }, + { 0x0DAA, 43494 }, + { 0x0DA8, 43498 }, + { 0x0DF4, 43502 }, + { 0x273A, 43505 }, + { 0x2A95, 43508 }, + { 0x2A97, 43513 }, + { 0x2A96, 43521 }, + { 0x2A98, 43526 }, + { 0x2A57, 43534 }, + { 0x2A58, 43537 }, + { 0x2AAA, 43540 }, + { 0x2AAC, 43542 }, + { 0x2603, 43547 }, + { 0x002F, 43548 }, + { 0x29F6, 43549 }, + { 0x2747, 43552 }, + { 0x22A1, 43553 }, + { 0x2E2C, 43556 }, + { 0x229E, 43560 }, + { 0x229F, 43562 }, + { 0x29C7, 43564 }, + { 0x22A0, 43567 }, + { 0x29C4, 43569 }, + { 0x29C8, 43573 }, + { 0x29C5, 43575 }, + { 0x29C6, 43579 }, + { 0x222F, 43581 }, + { 0x1714, 43583 }, + { 0x1712, 43586 }, + { 0x1713, 43590 }, + { 0x1700, 43594 }, + { 0x1701, 43597 }, + { 0x1702, 43600 }, + { 0x170A, 43603 }, + { 0x1707, 43606 }, + { 0x1704, 43609 }, + { 0x1711, 43612 }, + { 0x1703, 43615 }, + { 0x170E, 43618 }, + { 0x170B, 43621 }, + { 0x1708, 43624 }, + { 0x1709, 43627 }, + { 0x1710, 43630 }, + { 0x1706, 43633 }, + { 0x170F, 43636 }, + { 0x170C, 43639 }, + { 0x1705, 43642 }, + { 0x27A2, 43645 }, + { 0x27A3, 43649 }, + { 0x0FBE, 43653 }, + { 0x0FBF, 43657 }, + { 0x0F3D, 43664 }, + { 0x0F3C, 43669 }, + { 0x0F38, 43674 }, + { 0x0F3B, 43678 }, + { 0x0F3A, 43683 }, + { 0x0F11, 43688 }, + { 0x0F39, 43694 }, + { 0x0F07, 43698 }, + { 0x0F0A, 43705 }, + { 0x0F03, 43711 }, + { 0x0F02, 43720 }, + { 0x0F01, 43729 }, + { 0x0F14, 43736 }, + { 0x0F35, 43740 }, + { 0x0F37, 43746 }, + { 0x0F0E, 43752 }, + { 0x0FD2, 43756 }, + { 0x0F10, 43760 }, + { 0x0F12, 43765 }, + { 0x0F0D, 43770 }, + { 0x0F34, 43773 }, + { 0x0FD0, 43777 }, + { 0x0F09, 43784 }, + { 0x0F06, 43789 }, + { 0x0F13, 43797 }, + { 0x0F36, 43805 }, + { 0x0FD1, 43813 }, + { 0x0F08, 43820 }, + { 0x0F0F, 43824 }, + { 0x0F85, 43828 }, + { 0x0F05, 43831 }, + { 0x0FD4, 43838 }, + { 0x0F84, 43847 }, + { 0x0F04, 43850 }, + { 0x0FD3, 43857 }, + { 0x0F0C, 43866 }, + { 0x0F0B, 43871 }, + { 0x0F8A, 43875 }, + { 0x0F8B, 43880 }, + { 0x0F88, 43885 }, + { 0x0F86, 43890 }, + { 0x0F3F, 43894 }, + { 0x0F82, 43898 }, + { 0x0F83, 43904 }, + { 0x0F3E, 43908 }, + { 0x0F89, 43912 }, + { 0x0F1D, 43916 }, + { 0x0FCF, 43921 }, + { 0x0FCE, 43926 }, + { 0x0F1E, 43932 }, + { 0x0F1A, 43937 }, + { 0x0F1C, 43942 }, + { 0x0F1F, 43947 }, + { 0x0F1B, 43953 }, + { 0x0F7E, 43958 }, + { 0x0F7F, 43964 }, + { 0x0F87, 43968 }, + { 0x0F21, 43972 }, + { 0x0F26, 43975 }, + { 0x0F22, 43978 }, + { 0x0F25, 43981 }, + { 0x0F24, 43984 }, + { 0x0F2A, 43987 }, + { 0x0F2F, 43991 }, + { 0x0F2B, 43995 }, + { 0x0F2E, 43999 }, + { 0x0F2D, 44003 }, + { 0x0F32, 44007 }, + { 0x0F33, 44011 }, + { 0x0F31, 44015 }, + { 0x0F30, 44019 }, + { 0x0F2C, 44023 }, + { 0x0F29, 44027 }, + { 0x0F20, 44030 }, + { 0x0F28, 44033 }, + { 0x0F27, 44036 }, + { 0x0F23, 44039 }, + { 0x0F7A, 44042 }, + { 0x0F72, 44046 }, + { 0x0F7C, 44050 }, + { 0x0F74, 44054 }, + { 0x0F71, 44058 }, + { 0x0F7B, 44062 }, + { 0x0F73, 44066 }, + { 0x0F7D, 44070 }, + { 0x0F75, 44074 }, + { 0x0F78, 44078 }, + { 0x0F76, 44083 }, + { 0x0F79, 44088 }, + { 0x0F77, 44093 }, + { 0x0F80, 44098 }, + { 0x0F81, 44103 }, + { 0x0F68, 44108 }, + { 0x0F60, 44111 }, + { 0x0F56, 44114 }, + { 0x0F45, 44117 }, + { 0x0F51, 44120 }, + { 0x0F42, 44123 }, + { 0x0F67, 44126 }, + { 0x0F47, 44129 }, + { 0x0F40, 44132 }, + { 0x0F63, 44135 }, + { 0x0F58, 44138 }, + { 0x0F53, 44141 }, + { 0x0F54, 44144 }, + { 0x0F62, 44147 }, + { 0x0F66, 44150 }, + { 0x0F4F, 44153 }, + { 0x0F5D, 44156 }, + { 0x0F61, 44159 }, + { 0x0F5F, 44162 }, + { 0x0F57, 44165 }, + { 0x0F46, 44168 }, + { 0x0F4C, 44171 }, + { 0x0F52, 44174 }, + { 0x0F5B, 44177 }, + { 0x0F43, 44180 }, + { 0x0F41, 44183 }, + { 0x0F6B, 44186 }, + { 0x0F44, 44189 }, + { 0x0F4E, 44192 }, + { 0x0F49, 44195 }, + { 0x0F55, 44198 }, + { 0x0F6C, 44201 }, + { 0x0F64, 44204 }, + { 0x0F65, 44207 }, + { 0x0F50, 44210 }, + { 0x0F59, 44213 }, + { 0x0F4A, 44216 }, + { 0x0F5E, 44219 }, + { 0x0F4D, 44222 }, + { 0x0F5C, 44225 }, + { 0x0F69, 44228 }, + { 0x0F5A, 44231 }, + { 0x0F4B, 44234 }, + { 0x0F6A, 44237 }, + { 0x0FC9, 44241 }, + { 0x0FCC, 44245 }, + { 0x0FCB, 44251 }, + { 0x0FCA, 44257 }, + { 0x0FC5, 44263 }, + { 0x0FC7, 44267 }, + { 0x0FC4, 44273 }, + { 0x0FC8, 44277 }, + { 0x0FC6, 44281 }, + { 0x0F15, 44285 }, + { 0x0F16, 44290 }, + { 0x0F00, 44295 }, + { 0x0FB8, 44298 }, + { 0x0FB0, 44302 }, + { 0x0FA6, 44306 }, + { 0x0F95, 44310 }, + { 0x0FA1, 44314 }, + { 0x0F92, 44318 }, + { 0x0FB7, 44322 }, + { 0x0F97, 44326 }, + { 0x0F90, 44330 }, + { 0x0FB3, 44334 }, + { 0x0FA8, 44338 }, + { 0x0FA3, 44342 }, + { 0x0FA4, 44346 }, + { 0x0FB2, 44350 }, + { 0x0FB6, 44354 }, + { 0x0F9F, 44358 }, + { 0x0FAD, 44362 }, + { 0x0FB1, 44366 }, + { 0x0FAF, 44370 }, + { 0x0FA7, 44374 }, + { 0x0F96, 44378 }, + { 0x0F9C, 44382 }, + { 0x0FA2, 44386 }, + { 0x0FAB, 44390 }, + { 0x0F93, 44394 }, + { 0x0F91, 44398 }, + { 0x0F94, 44402 }, + { 0x0F9E, 44406 }, + { 0x0F99, 44410 }, + { 0x0FA5, 44414 }, + { 0x0FB4, 44418 }, + { 0x0FB5, 44422 }, + { 0x0FA0, 44426 }, + { 0x0FA9, 44430 }, + { 0x0F9A, 44434 }, + { 0x0FAE, 44438 }, + { 0x0F9D, 44442 }, + { 0x0FAC, 44446 }, + { 0x0FB9, 44450 }, + { 0x0FAA, 44454 }, + { 0x0F9B, 44458 }, + { 0x0FBC, 44462 }, + { 0x0FBA, 44467 }, + { 0x0FBB, 44472 }, + { 0x0F17, 44477 }, + { 0x0F19, 44484 }, + { 0x0F18, 44489 }, + { 0x0FC2, 44494 }, + { 0x0FC3, 44499 }, + { 0x0FC0, 44504 }, + { 0x0FC1, 44509 }, + { 0x2632, 44514 }, + { 0x2631, 44517 }, + { 0x2634, 44520 }, + { 0x2637, 44523 }, + { 0x2635, 44526 }, + { 0x2630, 44529 }, + { 0x2633, 44532 }, + { 0x2636, 44535 }, + { 0x219F, 44538 }, + { 0x2191, 44542 }, + { 0x2912, 44544 }, + { 0x21A5, 44548 }, + { 0x21B0, 44552 }, + { 0x21B1, 44557 }, + { 0x21DE, 44562 }, + { 0x2909, 44567 }, + { 0x21C5, 44572 }, + { 0x2B06, 44578 }, + { 0x21E7, 44581 }, + { 0x21EB, 44584 }, + { 0x21ED, 44589 }, + { 0x21EC, 44597 }, + { 0x21EA, 44605 }, + { 0x21EE, 44610 }, + { 0x21EF, 44614 }, + { 0x2E15, 44620 }, + { 0x21E1, 44622 }, + { 0x21D1, 44625 }, + { 0x21C8, 44628 }, + { 0x290A, 44631 }, + { 0x2958, 44634 }, + { 0x2960, 44641 }, + { 0x2963, 44648 }, + { 0x296E, 44659 }, + { 0x2954, 44670 }, + { 0x295C, 44677 }, + { 0x21BF, 44684 }, + { 0x21BE, 44689 }, + { 0x27F0, 44694 }, + { 0x2949, 44697 }, + { 0x270C, 44703 }, + { 0x26A0, 44705 }, + { 0x270D, 44707 }, + { 0x206D, 44709 }, + { 0x206B, 44713 }, + { 0x2708, 44716 }, + { 0x212B, 44717 }, + { 0x2652, 44719 }, + { 0x0589, 44720 }, + { 0x055D, 44723 }, + { 0x056E, 44725 }, + { 0x0581, 44729 }, + { 0x0564, 44733 }, + { 0x0567, 44737 }, + { 0x0568, 44741 }, + { 0x0570, 44745 }, + { 0x0571, 44749 }, + { 0x0585, 44753 }, + { 0x057C, 44757 }, + { 0x0569, 44761 }, + { 0x0578, 44765 }, + { 0x0575, 44769 }, + { 0x0566, 44773 }, + { 0x0561, 44777 }, + { 0x0562, 44781 }, + { 0x0579, 44785 }, + { 0x0565, 44789 }, + { 0x0586, 44793 }, + { 0x0563, 44797 }, + { 0x056B, 44801 }, + { 0x0584, 44805 }, + { 0x056F, 44809 }, + { 0x0574, 44813 }, + { 0x0576, 44817 }, + { 0x057A, 44821 }, + { 0x0580, 44825 }, + { 0x057D, 44829 }, + { 0x0577, 44833 }, + { 0x057E, 44837 }, + { 0x056D, 44841 }, + { 0x056A, 44845 }, + { 0x0573, 44849 }, + { 0x0572, 44853 }, + { 0x057B, 44857 }, + { 0x056C, 44861 }, + { 0x0583, 44865 }, + { 0x057F, 44869 }, + { 0x0582, 44873 }, + { 0x0587, 44877 }, + { 0x6B14, 44882 }, + { 0x6B15, 44887 }, + { 0x6B13, 44892 }, + { 0x6B17, 44897 }, + { 0x6B16, 44902 }, + { 0x058A, 44907 }, + { 0x053E, 44909 }, + { 0x0551, 44913 }, + { 0x0534, 44917 }, + { 0x0537, 44921 }, + { 0x0538, 44925 }, + { 0x0540, 44929 }, + { 0x0541, 44933 }, + { 0x0555, 44937 }, + { 0x054C, 44941 }, + { 0x0539, 44945 }, + { 0x0548, 44949 }, + { 0x0545, 44953 }, + { 0x0536, 44957 }, + { 0x0531, 44961 }, + { 0x0532, 44965 }, + { 0x0549, 44969 }, + { 0x0535, 44973 }, + { 0x0556, 44977 }, + { 0x0533, 44981 }, + { 0x053B, 44985 }, + { 0x0554, 44989 }, + { 0x053F, 44993 }, + { 0x0544, 44997 }, + { 0x0546, 45001 }, + { 0x054A, 45005 }, + { 0x0550, 45009 }, + { 0x054D, 45013 }, + { 0x0547, 45017 }, + { 0x054E, 45021 }, + { 0x053D, 45025 }, + { 0x053A, 45029 }, + { 0x0543, 45033 }, + { 0x0542, 45037 }, + { 0x054B, 45041 }, + { 0x053C, 45045 }, + { 0x0553, 45049 }, + { 0x054F, 45053 }, + { 0x0552, 45057 }, + { 0x055B, 45061 }, + { 0x0559, 45064 }, + { 0x055E, 45070 }, + { 0x055A, 45073 }, + { 0x055C, 45075 }, + { 0x055F, 45078 }, + { 0x002A, 45081 }, + { 0x2217, 45082 }, + { 0x2042, 45084 }, + { 0x1B44, 45085 }, + { 0x1B00, 45088 }, + { 0x1B01, 45092 }, + { 0x1B04, 45096 }, + { 0x1B02, 45099 }, + { 0x1B03, 45102 }, + { 0x1B34, 45105 }, + { 0x1B5E, 45108 }, + { 0x1B5F, 45111 }, + { 0x1B5D, 45114 }, + { 0x1B51, 45117 }, + { 0x1B56, 45120 }, + { 0x1B52, 45123 }, + { 0x1B55, 45126 }, + { 0x1B54, 45129 }, + { 0x1B59, 45132 }, + { 0x1B50, 45135 }, + { 0x1B58, 45138 }, + { 0x1B57, 45141 }, + { 0x1B53, 45144 }, + { 0x1B5A, 45147 }, + { 0x1B3C, 45149 }, + { 0x1B3D, 45154 }, + { 0x1B3A, 45160 }, + { 0x1B3B, 45165 }, + { 0x1B36, 45171 }, + { 0x1B37, 45175 }, + { 0x1B38, 45180 }, + { 0x1B39, 45184 }, + { 0x1B42, 45189 }, + { 0x1B43, 45193 }, + { 0x1B3E, 45198 }, + { 0x1B3F, 45202 }, + { 0x1B41, 45207 }, + { 0x1B40, 45213 }, + { 0x1B35, 45218 }, + { 0x1B5C, 45222 }, + { 0x1B29, 45224 }, + { 0x1B2A, 45227 }, + { 0x1B18, 45231 }, + { 0x1B19, 45234 }, + { 0x1B24, 45238 }, + { 0x1B25, 45241 }, + { 0x1B1F, 45245 }, + { 0x1B20, 45250 }, + { 0x1B48, 45255 }, + { 0x1B15, 45259 }, + { 0x1B16, 45262 }, + { 0x1B33, 45266 }, + { 0x1B1A, 45269 }, + { 0x1B1B, 45272 }, + { 0x1B13, 45276 }, + { 0x1B14, 45279 }, + { 0x1B2E, 45283 }, + { 0x1B0D, 45286 }, + { 0x1B0E, 45290 }, + { 0x1B2B, 45295 }, + { 0x1B26, 45298 }, + { 0x1B21, 45301 }, + { 0x1B27, 45305 }, + { 0x1B28, 45308 }, + { 0x1B2D, 45312 }, + { 0x1B0B, 45315 }, + { 0x1B0C, 45319 }, + { 0x1B32, 45324 }, + { 0x1B30, 45327 }, + { 0x1B31, 45331 }, + { 0x1B22, 45335 }, + { 0x1B23, 45338 }, + { 0x1B1D, 45342 }, + { 0x1B1E, 45346 }, + { 0x1B49, 45351 }, + { 0x1B2F, 45355 }, + { 0x1B2C, 45358 }, + { 0x1B45, 45361 }, + { 0x1B17, 45365 }, + { 0x1B1C, 45368 }, + { 0x1B4A, 45371 }, + { 0x1B46, 45375 }, + { 0x1B47, 45379 }, + { 0x1B05, 45383 }, + { 0x1B06, 45386 }, + { 0x1B0F, 45390 }, + { 0x1B07, 45393 }, + { 0x1B08, 45396 }, + { 0x1B11, 45400 }, + { 0x1B12, 45403 }, + { 0x1B09, 45407 }, + { 0x1B0A, 45410 }, + { 0x1B10, 45414 }, + { 0x1B4B, 45417 }, + { 0x1B5B, 45421 }, + { 0x1B64, 45423 }, + { 0x1B6A, 45427 }, + { 0x1B65, 45432 }, + { 0x1B62, 45437 }, + { 0x1B66, 45441 }, + { 0x1B61, 45445 }, + { 0x1B63, 45449 }, + { 0x1B67, 45453 }, + { 0x1B69, 45457 }, + { 0x1B68, 45461 }, + { 0x1B73, 45465 }, + { 0x1B72, 45470 }, + { 0x1B6C, 45475 }, + { 0x1B6B, 45480 }, + { 0x1B6E, 45485 }, + { 0x1B71, 45490 }, + { 0x1B6D, 45497 }, + { 0x1B70, 45502 }, + { 0x1B6F, 45509 }, + { 0x1B78, 45514 }, + { 0x1B7C, 45520 }, + { 0x1B79, 45526 }, + { 0x1B7A, 45532 }, + { 0x1B7B, 45538 }, + { 0x1B75, 45544 }, + { 0x1B74, 45550 }, + { 0x1B77, 45556 }, + { 0x1B76, 45562 }, + { 0x1B60, 45568 }, + { 0x31B7, 45570 }, + { 0x31B6, 45574 }, + { 0x31B4, 45578 }, + { 0x31B5, 45582 }, + { 0x311A, 45586 }, + { 0x3105, 45589 }, + { 0x3118, 45592 }, + { 0x3109, 45595 }, + { 0x311C, 45598 }, + { 0x3108, 45601 }, + { 0x310D, 45604 }, + { 0x310F, 45607 }, + { 0x3127, 45610 }, + { 0x3110, 45613 }, + { 0x310E, 45616 }, + { 0x310C, 45619 }, + { 0x3107, 45622 }, + { 0x310B, 45625 }, + { 0x311B, 45628 }, + { 0x3106, 45631 }, + { 0x3111, 45634 }, + { 0x3116, 45637 }, + { 0x3119, 45640 }, + { 0x310A, 45643 }, + { 0x3128, 45646 }, + { 0x312A, 45649 }, + { 0x3112, 45652 }, + { 0x3117, 45655 }, + { 0x311E, 45658 }, + { 0x31B0, 45661 }, + { 0x3122, 45664 }, + { 0x3120, 45667 }, + { 0x31A0, 45670 }, + { 0x3114, 45673 }, + { 0x31A4, 45676 }, + { 0x311D, 45679 }, + { 0x311F, 45682 }, + { 0x3123, 45685 }, + { 0x3126, 45688 }, + { 0x312C, 45691 }, + { 0x31A3, 45694 }, + { 0x312D, 45697 }, + { 0x31AC, 45700 }, + { 0x31A8, 45703 }, + { 0x3129, 45706 }, + { 0x31A2, 45709 }, + { 0x312B, 45712 }, + { 0x31B1, 45715 }, + { 0x31A6, 45718 }, + { 0x3121, 45721 }, + { 0x3115, 45724 }, + { 0x3113, 45727 }, + { 0x31A1, 45730 }, + { 0x3124, 45733 }, + { 0x31A9, 45736 }, + { 0x3125, 45739 }, + { 0x31A5, 45742 }, + { 0x31AA, 45745 }, + { 0x31AD, 45748 }, + { 0x31B2, 45751 }, + { 0x31A7, 45754 }, + { 0x31AB, 45757 }, + { 0x31AE, 45760 }, + { 0x31AF, 45763 }, + { 0x31B3, 45766 }, + { 0x1A1F, 45769 }, + { 0x1A19, 45773 }, + { 0x1A17, 45777 }, + { 0x1A1A, 45781 }, + { 0x1A18, 45785 }, + { 0x1A1B, 45789 }, + { 0x1A15, 45793 }, + { 0x1A05, 45796 }, + { 0x1A0C, 45799 }, + { 0x1A09, 45802 }, + { 0x1A01, 45805 }, + { 0x1A16, 45808 }, + { 0x1A0D, 45811 }, + { 0x1A00, 45814 }, + { 0x1A12, 45817 }, + { 0x1A06, 45820 }, + { 0x1A0A, 45823 }, + { 0x1A04, 45826 }, + { 0x1A11, 45829 }, + { 0x1A14, 45832 }, + { 0x1A08, 45835 }, + { 0x1A13, 45838 }, + { 0x1A10, 45841 }, + { 0x1A07, 45844 }, + { 0x1A02, 45847 }, + { 0x1A0B, 45850 }, + { 0x1A0E, 45853 }, + { 0x1A03, 45856 }, + { 0x1A0F, 45859 }, + { 0x1A1E, 45862 }, + { 0x25CE, 45864 }, + { 0x2624, 45865 }, + { 0x140A, 45866 }, + { 0x14A1, 45869 }, + { 0x1401, 45872 }, + { 0x155D, 45875 }, + { 0x1403, 45878 }, + { 0x1483, 45881 }, + { 0x14EA, 45884 }, + { 0x14BB, 45887 }, + { 0x14D0, 45890 }, + { 0x1405, 45893 }, + { 0x1449, 45896 }, + { 0x1585, 45899 }, + { 0x1550, 45902 }, + { 0x1505, 45905 }, + { 0x1466, 45908 }, + { 0x153E, 45911 }, + { 0x140B, 45914 }, + { 0x141C, 45917 }, + { 0x142E, 45920 }, + { 0x1490, 45923 }, + { 0x1489, 45926 }, + { 0x148B, 45929 }, + { 0x148D, 45932 }, + { 0x142B, 45935 }, + { 0x1559, 45938 }, + { 0x1553, 45941 }, + { 0x1555, 45944 }, + { 0x1557, 45947 }, + { 0x157D, 45950 }, + { 0x1404, 45953 }, + { 0x142C, 45956 }, + { 0x1472, 45959 }, + { 0x146B, 45962 }, + { 0x146D, 45965 }, + { 0x146F, 45968 }, + { 0x1484, 45971 }, + { 0x14DA, 45974 }, + { 0x14D3, 45977 }, + { 0x15A6, 45980 }, + { 0x14D5, 45983 }, + { 0x14D7, 45986 }, + { 0x14AA, 45989 }, + { 0x14A3, 45992 }, + { 0x14BD, 45995 }, + { 0x14A5, 45998 }, + { 0x14A7, 46001 }, + { 0x14C7, 46004 }, + { 0x14C0, 46007 }, + { 0x1595, 46010 }, + { 0x14D2, 46013 }, + { 0x14C2, 46016 }, + { 0x14C4, 46019 }, + { 0x142D, 46022 }, + { 0x1406, 46025 }, + { 0x1438, 46028 }, + { 0x142F, 46031 }, + { 0x1431, 46034 }, + { 0x1433, 46037 }, + { 0x1583, 46040 }, + { 0x157F, 46043 }, + { 0x1581, 46046 }, + { 0x154B, 46049 }, + { 0x1542, 46052 }, + { 0x1546, 46055 }, + { 0x1548, 46058 }, + { 0x14F4, 46061 }, + { 0x14ED, 46064 }, + { 0x1525, 46067 }, + { 0x14EF, 46070 }, + { 0x14F1, 46073 }, + { 0x1507, 46076 }, + { 0x1455, 46079 }, + { 0x144C, 46082 }, + { 0x156A, 46085 }, + { 0x144E, 46088 }, + { 0x1450, 46091 }, + { 0x1417, 46094 }, + { 0x140C, 46097 }, + { 0x140E, 46100 }, + { 0x1412, 46103 }, + { 0x152D, 46106 }, + { 0x1526, 46109 }, + { 0x1528, 46112 }, + { 0x152A, 46115 }, + { 0x1402, 46118 }, + { 0x1491, 46121 }, + { 0x166D, 46124 }, + { 0x148C, 46128 }, + { 0x148E, 46131 }, + { 0x149C, 46134 }, + { 0x1492, 46137 }, + { 0x1494, 46140 }, + { 0x1498, 46143 }, + { 0x155A, 46146 }, + { 0x1556, 46149 }, + { 0x1558, 46152 }, + { 0x1473, 46155 }, + { 0x146E, 46158 }, + { 0x1470, 46161 }, + { 0x147E, 46164 }, + { 0x1474, 46167 }, + { 0x1476, 46170 }, + { 0x147A, 46173 }, + { 0x14DB, 46176 }, + { 0x15A4, 46179 }, + { 0x15A0, 46182 }, + { 0x15A2, 46185 }, + { 0x14D6, 46188 }, + { 0x14D8, 46191 }, + { 0x14E6, 46194 }, + { 0x14DC, 46197 }, + { 0x14DE, 46200 }, + { 0x14E2, 46203 }, + { 0x14AB, 46206 }, + { 0x14A6, 46209 }, + { 0x14A8, 46212 }, + { 0x14B6, 46215 }, + { 0x14AC, 46218 }, + { 0x14AE, 46221 }, + { 0x14B2, 46224 }, + { 0x14C8, 46227 }, + { 0x1593, 46230 }, + { 0x158F, 46233 }, + { 0x1591, 46236 }, + { 0x14C3, 46239 }, + { 0x1596, 46242 }, + { 0x14C5, 46245 }, + { 0x14CB, 46248 }, + { 0x14C9, 46251 }, + { 0x1439, 46254 }, + { 0x1432, 46257 }, + { 0x1434, 46260 }, + { 0x1444, 46263 }, + { 0x143A, 46266 }, + { 0x143C, 46269 }, + { 0x1440, 46272 }, + { 0x1584, 46275 }, + { 0x166F, 46278 }, + { 0x1580, 46281 }, + { 0x1582, 46284 }, + { 0x154C, 46287 }, + { 0x1547, 46290 }, + { 0x1549, 46293 }, + { 0x14F5, 46296 }, + { 0x1515, 46299 }, + { 0x1510, 46302 }, + { 0x1511, 46305 }, + { 0x1513, 46308 }, + { 0x14F0, 46311 }, + { 0x14F2, 46314 }, + { 0x1500, 46317 }, + { 0x14F6, 46320 }, + { 0x14F8, 46323 }, + { 0x14FC, 46326 }, + { 0x1456, 46329 }, + { 0x1566, 46332 }, + { 0x155E, 46335 }, + { 0x1560, 46338 }, + { 0x1564, 46341 }, + { 0x144F, 46344 }, + { 0x1451, 46347 }, + { 0x146A, 46350 }, + { 0x1467, 46353 }, + { 0x156F, 46356 }, + { 0x1468, 46359 }, + { 0x1469, 46362 }, + { 0x1461, 46365 }, + { 0x1457, 46368 }, + { 0x1459, 46371 }, + { 0x145D, 46374 }, + { 0x1573, 46377 }, + { 0x1570, 46380 }, + { 0x1571, 46383 }, + { 0x1572, 46386 }, + { 0x1419, 46389 }, + { 0x1410, 46392 }, + { 0x1414, 46395 }, + { 0x152E, 46398 }, + { 0x1529, 46401 }, + { 0x152B, 46404 }, + { 0x1539, 46407 }, + { 0x152F, 46410 }, + { 0x1531, 46413 }, + { 0x1535, 46416 }, + { 0x148A, 46419 }, + { 0x149E, 46422 }, + { 0x1496, 46425 }, + { 0x149A, 46428 }, + { 0x1554, 46431 }, + { 0x166E, 46434 }, + { 0x155B, 46438 }, + { 0x146C, 46441 }, + { 0x1480, 46444 }, + { 0x1478, 46447 }, + { 0x147C, 46450 }, + { 0x14D4, 46453 }, + { 0x15A5, 46456 }, + { 0x15A1, 46459 }, + { 0x15A3, 46462 }, + { 0x14E8, 46465 }, + { 0x14E0, 46468 }, + { 0x14E4, 46471 }, + { 0x14A4, 46474 }, + { 0x14B8, 46477 }, + { 0x14B0, 46480 }, + { 0x14B4, 46483 }, + { 0x14C1, 46486 }, + { 0x1594, 46489 }, + { 0x1670, 46492 }, + { 0x1590, 46495 }, + { 0x1592, 46498 }, + { 0x1675, 46501 }, + { 0x1671, 46504 }, + { 0x1673, 46507 }, + { 0x14CD, 46510 }, + { 0x1430, 46513 }, + { 0x1446, 46516 }, + { 0x143E, 46519 }, + { 0x1442, 46522 }, + { 0x157E, 46525 }, + { 0x1545, 46528 }, + { 0x154E, 46531 }, + { 0x14EE, 46534 }, + { 0x1516, 46537 }, + { 0x1512, 46540 }, + { 0x1514, 46543 }, + { 0x1521, 46546 }, + { 0x1517, 46549 }, + { 0x1519, 46552 }, + { 0x151D, 46555 }, + { 0x1502, 46558 }, + { 0x14FA, 46561 }, + { 0x14FE, 46564 }, + { 0x144D, 46567 }, + { 0x1567, 46570 }, + { 0x1562, 46573 }, + { 0x1565, 46576 }, + { 0x1589, 46579 }, + { 0x1586, 46582 }, + { 0x1587, 46585 }, + { 0x1588, 46588 }, + { 0x156E, 46591 }, + { 0x156B, 46594 }, + { 0x156C, 46597 }, + { 0x156D, 46600 }, + { 0x1463, 46603 }, + { 0x145B, 46606 }, + { 0x145F, 46609 }, + { 0x1527, 46612 }, + { 0x153B, 46615 }, + { 0x1533, 46618 }, + { 0x1537, 46621 }, + { 0x1422, 46624 }, + { 0x142A, 46630 }, + { 0x1429, 46635 }, + { 0x1424, 46639 }, + { 0x141F, 46643 }, + { 0x1420, 46647 }, + { 0x1423, 46651 }, + { 0x1428, 46657 }, + { 0x1421, 46663 }, + { 0x1425, 46669 }, + { 0x1426, 46674 }, + { 0x1427, 46681 }, + { 0x158E, 46686 }, + { 0x1676, 46689 }, + { 0x1672, 46692 }, + { 0x1674, 46695 }, + { 0x1523, 46698 }, + { 0x151B, 46701 }, + { 0x151F, 46704 }, + { 0x1568, 46707 }, + { 0x14EC, 46710 }, + { 0x1552, 46714 }, + { 0x155F, 46718 }, + { 0x1561, 46722 }, + { 0x1563, 46726 }, + { 0x1543, 46730 }, + { 0x14BF, 46734 }, + { 0x15C3, 46738 }, + { 0x15C0, 46742 }, + { 0x15C1, 46746 }, + { 0x15C2, 46750 }, + { 0x161A, 46754 }, + { 0x1615, 46758 }, + { 0x14A2, 46762 }, + { 0x1541, 46766 }, + { 0x159A, 46770 }, + { 0x1597, 46774 }, + { 0x1598, 46778 }, + { 0x1599, 46782 }, + { 0x141D, 46786 }, + { 0x1407, 46790 }, + { 0x148F, 46794 }, + { 0x1471, 46798 }, + { 0x14D9, 46802 }, + { 0x14A9, 46806 }, + { 0x14C6, 46810 }, + { 0x1435, 46814 }, + { 0x14F3, 46818 }, + { 0x1452, 46822 }, + { 0x152C, 46826 }, + { 0x1448, 46830 }, + { 0x15AF, 46834 }, + { 0x144B, 46838 }, + { 0x1409, 46842 }, + { 0x15EE, 46846 }, + { 0x1646, 46850 }, + { 0x1454, 46854 }, + { 0x1408, 46858 }, + { 0x15F4, 46862 }, + { 0x15F1, 46866 }, + { 0x15F3, 46870 }, + { 0x15F0, 46874 }, + { 0x15EF, 46878 }, + { 0x1437, 46882 }, + { 0x161B, 46886 }, + { 0x1617, 46890 }, + { 0x1619, 46894 }, + { 0x1616, 46898 }, + { 0x1614, 46902 }, + { 0x1601, 46906 }, + { 0x1627, 46910 }, + { 0x1624, 46914 }, + { 0x1626, 46918 }, + { 0x1623, 46922 }, + { 0x1622, 46926 }, + { 0x160D, 46930 }, + { 0x160A, 46934 }, + { 0x160C, 46938 }, + { 0x1609, 46942 }, + { 0x1608, 46946 }, + { 0x1607, 46950 }, + { 0x1604, 46954 }, + { 0x14D1, 46958 }, + { 0x1606, 46962 }, + { 0x1603, 46966 }, + { 0x1602, 46970 }, + { 0x15ED, 46974 }, + { 0x15EA, 46978 }, + { 0x15EC, 46982 }, + { 0x15E9, 46986 }, + { 0x15E8, 46990 }, + { 0x15CF, 46994 }, + { 0x15CC, 46998 }, + { 0x15CE, 47002 }, + { 0x15CB, 47006 }, + { 0x15CA, 47010 }, + { 0x1653, 47014 }, + { 0x1650, 47018 }, + { 0x165A, 47022 }, + { 0x1652, 47026 }, + { 0x164F, 47030 }, + { 0x164E, 47034 }, + { 0x15D5, 47038 }, + { 0x15D2, 47042 }, + { 0x15D4, 47046 }, + { 0x15D1, 47050 }, + { 0x15D0, 47054 }, + { 0x1613, 47058 }, + { 0x1610, 47062 }, + { 0x1612, 47066 }, + { 0x160F, 47070 }, + { 0x160E, 47074 }, + { 0x1645, 47078 }, + { 0x1642, 47082 }, + { 0x1644, 47086 }, + { 0x1641, 47090 }, + { 0x1640, 47094 }, + { 0x1666, 47098 }, + { 0x1663, 47102 }, + { 0x1665, 47106 }, + { 0x1662, 47110 }, + { 0x1661, 47114 }, + { 0x1453, 47118 }, + { 0x162D, 47122 }, + { 0x162A, 47126 }, + { 0x162C, 47130 }, + { 0x1629, 47134 }, + { 0x1628, 47138 }, + { 0x164D, 47142 }, + { 0x164A, 47146 }, + { 0x164C, 47150 }, + { 0x1649, 47154 }, + { 0x1648, 47158 }, + { 0x15F2, 47162 }, + { 0x15C9, 47166 }, + { 0x15C6, 47170 }, + { 0x15C8, 47174 }, + { 0x15C5, 47178 }, + { 0x15C4, 47182 }, + { 0x1436, 47186 }, + { 0x15DB, 47190 }, + { 0x15D8, 47194 }, + { 0x15DA, 47198 }, + { 0x15D7, 47202 }, + { 0x15D6, 47206 }, + { 0x1618, 47210 }, + { 0x1621, 47214 }, + { 0x161E, 47218 }, + { 0x1620, 47222 }, + { 0x161D, 47226 }, + { 0x161C, 47230 }, + { 0x15FA, 47234 }, + { 0x15F7, 47238 }, + { 0x15F9, 47242 }, + { 0x15F6, 47246 }, + { 0x15F5, 47250 }, + { 0x1600, 47254 }, + { 0x15FD, 47258 }, + { 0x15FF, 47262 }, + { 0x15FC, 47266 }, + { 0x15FB, 47270 }, + { 0x1625, 47274 }, + { 0x1633, 47278 }, + { 0x1630, 47282 }, + { 0x1632, 47286 }, + { 0x162F, 47290 }, + { 0x162E, 47294 }, + { 0x160B, 47298 }, + { 0x1605, 47302 }, + { 0x15EB, 47306 }, + { 0x15CD, 47310 }, + { 0x1651, 47314 }, + { 0x1659, 47318 }, + { 0x1656, 47322 }, + { 0x1658, 47326 }, + { 0x1655, 47330 }, + { 0x1654, 47334 }, + { 0x15E1, 47338 }, + { 0x15DE, 47342 }, + { 0x15E0, 47346 }, + { 0x15DD, 47350 }, + { 0x15DC, 47354 }, + { 0x163F, 47358 }, + { 0x163C, 47362 }, + { 0x163E, 47366 }, + { 0x163B, 47370 }, + { 0x163A, 47374 }, + { 0x1660, 47378 }, + { 0x165D, 47382 }, + { 0x165F, 47386 }, + { 0x165C, 47390 }, + { 0x165B, 47394 }, + { 0x15E7, 47398 }, + { 0x15E4, 47402 }, + { 0x15E6, 47406 }, + { 0x15E3, 47410 }, + { 0x15E2, 47414 }, + { 0x15D3, 47418 }, + { 0x1611, 47422 }, + { 0x1643, 47426 }, + { 0x1664, 47430 }, + { 0x162B, 47434 }, + { 0x164B, 47438 }, + { 0x15C7, 47442 }, + { 0x15D9, 47446 }, + { 0x161F, 47450 }, + { 0x15F8, 47454 }, + { 0x15FE, 47458 }, + { 0x1631, 47462 }, + { 0x1657, 47466 }, + { 0x15DF, 47470 }, + { 0x163D, 47474 }, + { 0x1639, 47478 }, + { 0x1636, 47482 }, + { 0x1638, 47486 }, + { 0x1635, 47490 }, + { 0x1634, 47494 }, + { 0x165E, 47498 }, + { 0x15E5, 47502 }, + { 0x166C, 47506 }, + { 0x1669, 47510 }, + { 0x166B, 47514 }, + { 0x1668, 47518 }, + { 0x1667, 47522 }, + { 0x1637, 47526 }, + { 0x166A, 47530 }, + { 0x1647, 47534 }, + { 0x141E, 47539 }, + { 0x150B, 47543 }, + { 0x150A, 47547 }, + { 0x141B, 47551 }, + { 0x1416, 47555 }, + { 0x14A0, 47559 }, + { 0x1482, 47563 }, + { 0x14BA, 47567 }, + { 0x14CF, 47571 }, + { 0x150F, 47575 }, + { 0x150E, 47579 }, + { 0x150C, 47583 }, + { 0x150D, 47587 }, + { 0x1504, 47591 }, + { 0x1465, 47595 }, + { 0x153D, 47599 }, + { 0x157B, 47603 }, + { 0x1579, 47607 }, + { 0x1574, 47611 }, + { 0x1575, 47615 }, + { 0x1577, 47619 }, + { 0x157A, 47623 }, + { 0x1576, 47627 }, + { 0x1578, 47631 }, + { 0x157C, 47635 }, + { 0x15AE, 47639 }, + { 0x15AC, 47643 }, + { 0x15A7, 47647 }, + { 0x15A8, 47651 }, + { 0x15AA, 47655 }, + { 0x15AD, 47659 }, + { 0x15A9, 47663 }, + { 0x15AB, 47667 }, + { 0x15B3, 47671 }, + { 0x15B0, 47675 }, + { 0x15B1, 47679 }, + { 0x15B2, 47683 }, + { 0x1508, 47687 }, + { 0x15BF, 47691 }, + { 0x15BC, 47695 }, + { 0x15BD, 47699 }, + { 0x15BE, 47703 }, + { 0x15BB, 47707 }, + { 0x15B8, 47711 }, + { 0x15B9, 47715 }, + { 0x15BA, 47719 }, + { 0x15B7, 47723 }, + { 0x15B4, 47727 }, + { 0x15B5, 47731 }, + { 0x15B6, 47735 }, + { 0x14EB, 47739 }, + { 0x14BC, 47743 }, + { 0x144A, 47747 }, + { 0x1551, 47751 }, + { 0x1540, 47755 }, + { 0x154D, 47759 }, + { 0x1544, 47763 }, + { 0x154A, 47767 }, + { 0x158D, 47771 }, + { 0x158A, 47775 }, + { 0x158B, 47779 }, + { 0x158C, 47783 }, + { 0x1418, 47787 }, + { 0x140D, 47791 }, + { 0x140F, 47795 }, + { 0x1413, 47799 }, + { 0x149D, 47803 }, + { 0x1493, 47807 }, + { 0x1495, 47811 }, + { 0x1499, 47815 }, + { 0x147F, 47819 }, + { 0x1475, 47823 }, + { 0x1477, 47827 }, + { 0x147B, 47831 }, + { 0x14E7, 47835 }, + { 0x14DD, 47839 }, + { 0x14DF, 47843 }, + { 0x14E3, 47847 }, + { 0x14B7, 47851 }, + { 0x14AD, 47855 }, + { 0x14AF, 47859 }, + { 0x14B3, 47863 }, + { 0x14CC, 47867 }, + { 0x14CA, 47871 }, + { 0x1445, 47875 }, + { 0x143B, 47879 }, + { 0x143D, 47883 }, + { 0x1441, 47887 }, + { 0x1501, 47891 }, + { 0x14F7, 47895 }, + { 0x14F9, 47899 }, + { 0x14FD, 47903 }, + { 0x1462, 47907 }, + { 0x1458, 47911 }, + { 0x145A, 47915 }, + { 0x145E, 47919 }, + { 0x141A, 47923 }, + { 0x1411, 47927 }, + { 0x1415, 47931 }, + { 0x153A, 47935 }, + { 0x1530, 47939 }, + { 0x1532, 47943 }, + { 0x1536, 47947 }, + { 0x149F, 47951 }, + { 0x1497, 47955 }, + { 0x149B, 47959 }, + { 0x155C, 47963 }, + { 0x1481, 47967 }, + { 0x1479, 47971 }, + { 0x147D, 47975 }, + { 0x14E9, 47979 }, + { 0x14E1, 47983 }, + { 0x14E5, 47987 }, + { 0x14B9, 47991 }, + { 0x14B1, 47995 }, + { 0x14B5, 47999 }, + { 0x14CE, 48003 }, + { 0x1447, 48007 }, + { 0x143F, 48011 }, + { 0x1443, 48015 }, + { 0x154F, 48019 }, + { 0x1522, 48023 }, + { 0x1518, 48027 }, + { 0x151A, 48031 }, + { 0x151E, 48035 }, + { 0x1503, 48039 }, + { 0x14FB, 48043 }, + { 0x14FF, 48047 }, + { 0x1464, 48051 }, + { 0x145C, 48055 }, + { 0x1460, 48059 }, + { 0x153C, 48063 }, + { 0x1534, 48067 }, + { 0x1538, 48071 }, + { 0x1524, 48075 }, + { 0x151C, 48079 }, + { 0x1520, 48083 }, + { 0x1569, 48087 }, + { 0x14BE, 48091 }, + { 0x1506, 48095 }, + { 0x153F, 48099 }, + { 0x1509, 48103 }, + { 0x159F, 48107 }, + { 0x159E, 48111 }, + { 0x159B, 48115 }, + { 0x159C, 48119 }, + { 0x159D, 48123 }, + { 0x1488, 48127 }, + { 0x1485, 48131 }, + { 0x1486, 48135 }, + { 0x1487, 48139 }, + { 0x13A0, 48143 }, + { 0x13A1, 48146 }, + { 0x13A2, 48149 }, + { 0x13A3, 48152 }, + { 0x13CD, 48155 }, + { 0x13A4, 48158 }, + { 0x13A5, 48161 }, + { 0x13D3, 48164 }, + { 0x13D5, 48167 }, + { 0x13D7, 48170 }, + { 0x13D9, 48173 }, + { 0x13DA, 48176 }, + { 0x13DB, 48179 }, + { 0x13A6, 48182 }, + { 0x13A8, 48185 }, + { 0x13A9, 48188 }, + { 0x13AA, 48191 }, + { 0x13AB, 48194 }, + { 0x13AC, 48197 }, + { 0x13AD, 48200 }, + { 0x13AE, 48203 }, + { 0x13AF, 48206 }, + { 0x13B0, 48209 }, + { 0x13B1, 48212 }, + { 0x13B2, 48215 }, + { 0x13A7, 48218 }, + { 0x13B3, 48221 }, + { 0x13B4, 48224 }, + { 0x13B5, 48227 }, + { 0x13B6, 48230 }, + { 0x13B7, 48233 }, + { 0x13B8, 48236 }, + { 0x13B9, 48239 }, + { 0x13BA, 48242 }, + { 0x13BB, 48245 }, + { 0x13BC, 48248 }, + { 0x13BD, 48251 }, + { 0x13BE, 48254 }, + { 0x13C1, 48257 }, + { 0x13C2, 48260 }, + { 0x13C3, 48263 }, + { 0x13C4, 48266 }, + { 0x13C5, 48269 }, + { 0x13CC, 48272 }, + { 0x13CE, 48275 }, + { 0x13CF, 48278 }, + { 0x13D0, 48281 }, + { 0x13D1, 48284 }, + { 0x13D2, 48287 }, + { 0x13D4, 48290 }, + { 0x13D6, 48293 }, + { 0x13D8, 48296 }, + { 0x13E9, 48299 }, + { 0x13EA, 48302 }, + { 0x13EB, 48305 }, + { 0x13EC, 48308 }, + { 0x13ED, 48311 }, + { 0x13EE, 48314 }, + { 0x13EF, 48317 }, + { 0x13F0, 48320 }, + { 0x13F1, 48323 }, + { 0x13F2, 48326 }, + { 0x13F3, 48329 }, + { 0x13F4, 48332 }, + { 0x13DC, 48335 }, + { 0x13BF, 48338 }, + { 0x13C0, 48341 }, + { 0x13C6, 48344 }, + { 0x13C7, 48347 }, + { 0x13C8, 48350 }, + { 0x13C9, 48353 }, + { 0x13CA, 48356 }, + { 0x13CB, 48359 }, + { 0x13DD, 48362 }, + { 0x13DE, 48365 }, + { 0x13DF, 48368 }, + { 0x13E0, 48371 }, + { 0x13E1, 48374 }, + { 0x13E2, 48377 }, + { 0x13E3, 48380 }, + { 0x13E4, 48383 }, + { 0x13E5, 48386 }, + { 0x13E6, 48389 }, + { 0x13E7, 48392 }, + { 0x13E8, 48395 }, + { 0x220B, 48398 }, + { 0x22B3, 48401 }, + { 0x22B5, 48405 }, + { 0x22FA, 48412 }, + { 0x22FD, 48417 }, + { 0x22FB, 48420 }, + { 0x9369, 48429 }, + { 0x936E, 48434 }, + { 0x936A, 48439 }, + { 0x936D, 48444 }, + { 0x936C, 48449 }, + { 0x9371, 48454 }, + { 0x9370, 48459 }, + { 0x936F, 48464 }, + { 0x936B, 48469 }, + { 0x9360, 48474 }, + { 0x9365, 48479 }, + { 0x9361, 48484 }, + { 0x9364, 48489 }, + { 0x9363, 48494 }, + { 0x9368, 48499 }, + { 0x9367, 48504 }, + { 0x9366, 48509 }, + { 0x9362, 48514 }, + { 0x20A2, 48519 }, + { 0x00A4, 48521 }, + { 0x0430, 48523 }, + { 0x04D1, 48527 }, + { 0x04D3, 48533 }, + { 0x044D, 48539 }, + { 0x04ED, 48543 }, + { 0x0438, 48549 }, + { 0x045D, 48553 }, + { 0x04E3, 48559 }, + { 0x04E5, 48565 }, + { 0x043E, 48571 }, + { 0x04E7, 48575 }, + { 0x0443, 48581 }, + { 0x04F3, 48585 }, + { 0x04EF, 48592 }, + { 0x04F1, 48598 }, + { 0x0431, 48604 }, + { 0x0434, 48608 }, + { 0x0444, 48612 }, + { 0x043B, 48616 }, + { 0x0513, 48620 }, + { 0x04C6, 48626 }, + { 0x0521, 48632 }, + { 0x043C, 48639 }, + { 0x04CE, 48643 }, + { 0x043D, 48649 }, + { 0x04C8, 48653 }, + { 0x04CA, 48659 }, + { 0x0523, 48665 }, + { 0x04A3, 48672 }, + { 0x0440, 48678 }, + { 0x048F, 48682 }, + { 0x0441, 48688 }, + { 0x04AB, 48692 }, + { 0x0445, 48698 }, + { 0x04FD, 48702 }, + { 0x04FF, 48708 }, + { 0x04B3, 48714 }, + { 0x0435, 48720 }, + { 0x04D7, 48724 }, + { 0x0450, 48730 }, + { 0x0451, 48736 }, + { 0x0458, 48740 }, + { 0x043A, 48744 }, + { 0x04C4, 48748 }, + { 0x049F, 48754 }, + { 0x049D, 48760 }, + { 0x049B, 48767 }, + { 0x047F, 48773 }, + { 0x043F, 48777 }, + { 0x04A7, 48781 }, + { 0x051B, 48788 }, + { 0x0442, 48792 }, + { 0x568B, 48796 }, + { 0x04AD, 48803 }, + { 0x0479, 48809 }, + { 0x0432, 48813 }, + { 0x051D, 48817 }, + { 0x044F, 48821 }, + { 0x0457, 48825 }, + { 0x565F, 48829 }, + { 0x044E, 48833 }, + { 0x0437, 48837 }, + { 0x0499, 48841 }, + { 0x04DF, 48847 }, + { 0x046B, 48853 }, + { 0x0447, 48858 }, + { 0x04B9, 48862 }, + { 0x04B7, 48869 }, + { 0x04F5, 48875 }, + { 0x0452, 48881 }, + { 0x5681, 48885 }, + { 0x0455, 48889 }, + { 0x0433, 48893 }, + { 0x0495, 48897 }, + { 0x0493, 48904 }, + { 0x04FB, 48910 }, + { 0x0491, 48918 }, + { 0x04F7, 48924 }, + { 0x0453, 48930 }, + { 0x5695, 48934 }, + { 0x045C, 48938 }, + { 0x046F, 48942 }, + { 0x0515, 48946 }, + { 0x0459, 48950 }, + { 0x045A, 48954 }, + { 0x0471, 48958 }, + { 0x0517, 48962 }, + { 0x0448, 48966 }, + { 0x0446, 48970 }, + { 0x568D, 48974 }, + { 0x0519, 48978 }, + { 0x0463, 48982 }, + { 0x0436, 48986 }, + { 0x04C2, 48990 }, + { 0x0497, 48996 }, + { 0x04DD, 49002 }, + { 0x5687, 49008 }, + { 0x045F, 49012 }, + { 0x5683, 49016 }, + { 0x5689, 49020 }, + { 0x0473, 49024 }, + { 0x044A, 49028 }, + { 0x5647, 49033 }, + { 0x0501, 49037 }, + { 0x0503, 49042 }, + { 0x0509, 49047 }, + { 0x050B, 49052 }, + { 0x050D, 49057 }, + { 0x050F, 49062 }, + { 0x0505, 49067 }, + { 0x0507, 49072 }, + { 0x04BB, 49077 }, + { 0x5697, 49081 }, + { 0x5663, 49085 }, + { 0x5665, 49090 }, + { 0x5667, 49095 }, + { 0x044C, 49100 }, + { 0x5693, 49105 }, + { 0x045B, 49109 }, + { 0x5691, 49113 }, + { 0x568F, 49117 }, + { 0x044B, 49121 }, + { 0x5651, 49125 }, + { 0x04F9, 49132 }, + { 0x5685, 49138 }, + { 0x051F, 49142 }, + { 0x564D, 49147 }, + { 0x5649, 49152 }, + { 0x5643, 49156 }, + { 0x0481, 49160 }, + { 0x0461, 49164 }, + { 0x047D, 49168 }, + { 0x047B, 49174 }, + { 0x04D9, 49179 }, + { 0x04DB, 49183 }, + { 0x0449, 49189 }, + { 0x0439, 49193 }, + { 0x048B, 49198 }, + { 0x045E, 49205 }, + { 0x04E9, 49210 }, + { 0x04EB, 49215 }, + { 0x5659, 49222 }, + { 0x566D, 49228 }, + { 0x0467, 49234 }, + { 0x5641, 49239 }, + { 0x04A1, 49243 }, + { 0x565B, 49248 }, + { 0x0475, 49253 }, + { 0x0477, 49257 }, + { 0x564F, 49265 }, + { 0x5657, 49270 }, + { 0x0465, 49275 }, + { 0x046D, 49280 }, + { 0x5653, 49286 }, + { 0x565D, 49291 }, + { 0x0469, 49298 }, + { 0x04CF, 49304 }, + { 0x5655, 49308 }, + { 0x0511, 49313 }, + { 0x5645, 49318 }, + { 0x048D, 49323 }, + { 0x04AF, 49328 }, + { 0x04B1, 49333 }, + { 0x04A9, 49340 }, + { 0x04BD, 49345 }, + { 0x04BF, 49350 }, + { 0x04E1, 49357 }, + { 0x566B, 49362 }, + { 0x5669, 49367 }, + { 0x564B, 49372 }, + { 0x0454, 49377 }, + { 0x04CC, 49382 }, + { 0x0456, 49387 }, + { 0x04D5, 49392 }, + { 0x04A5, 49397 }, + { 0x04B5, 49402 }, + { 0x567E, 49407 }, + { 0x1D2B, 49409 }, + { 0x04C0, 49414 }, + { 0x566E, 49417 }, + { 0x0410, 49421 }, + { 0x04D0, 49425 }, + { 0x04D2, 49431 }, + { 0x042D, 49437 }, + { 0x04EC, 49441 }, + { 0x0418, 49447 }, + { 0x040D, 49451 }, + { 0x04E2, 49457 }, + { 0x04E4, 49463 }, + { 0x041E, 49469 }, + { 0x04E6, 49473 }, + { 0x0423, 49479 }, + { 0x04F2, 49483 }, + { 0x04EE, 49490 }, + { 0x04F0, 49496 }, + { 0x0411, 49502 }, + { 0x0414, 49506 }, + { 0x0424, 49510 }, + { 0x041B, 49514 }, + { 0x0512, 49518 }, + { 0x04C5, 49524 }, + { 0x0520, 49530 }, + { 0x041C, 49537 }, + { 0x04CD, 49541 }, + { 0x041D, 49547 }, + { 0x04C7, 49551 }, + { 0x04C9, 49557 }, + { 0x0522, 49563 }, + { 0x04A2, 49570 }, + { 0x0420, 49576 }, + { 0x048E, 49580 }, + { 0x0421, 49586 }, + { 0x04AA, 49590 }, + { 0x0425, 49596 }, + { 0x04FC, 49600 }, + { 0x04FE, 49606 }, + { 0x04B2, 49612 }, + { 0x0415, 49618 }, + { 0x04D6, 49622 }, + { 0x0400, 49628 }, + { 0x0401, 49634 }, + { 0x0408, 49638 }, + { 0x041A, 49642 }, + { 0x04C3, 49646 }, + { 0x049E, 49652 }, + { 0x049C, 49658 }, + { 0x049A, 49665 }, + { 0x047E, 49671 }, + { 0x041F, 49675 }, + { 0x04A6, 49679 }, + { 0x051A, 49686 }, + { 0x0422, 49690 }, + { 0x568A, 49694 }, + { 0x04AC, 49701 }, + { 0x0478, 49707 }, + { 0x0412, 49711 }, + { 0x051C, 49715 }, + { 0x042F, 49719 }, + { 0x0407, 49723 }, + { 0x565E, 49727 }, + { 0x042E, 49731 }, + { 0x0417, 49735 }, + { 0x0498, 49739 }, + { 0x04DE, 49745 }, + { 0x046A, 49751 }, + { 0x0427, 49756 }, + { 0x04B8, 49760 }, + { 0x04B6, 49767 }, + { 0x04F4, 49773 }, + { 0x0402, 49779 }, + { 0x5680, 49783 }, + { 0x0405, 49787 }, + { 0x0413, 49791 }, + { 0x0494, 49795 }, + { 0x0492, 49802 }, + { 0x04FA, 49808 }, + { 0x0490, 49816 }, + { 0x04F6, 49822 }, + { 0x0403, 49828 }, + { 0x5694, 49832 }, + { 0x040C, 49836 }, + { 0x046E, 49840 }, + { 0x0514, 49844 }, + { 0x0409, 49848 }, + { 0x040A, 49852 }, + { 0x0470, 49856 }, + { 0x0516, 49860 }, + { 0x0428, 49864 }, + { 0x0426, 49868 }, + { 0x568C, 49872 }, + { 0x0518, 49876 }, + { 0x0462, 49880 }, + { 0x0416, 49884 }, + { 0x04C1, 49888 }, + { 0x0496, 49894 }, + { 0x04DC, 49900 }, + { 0x5686, 49906 }, + { 0x040F, 49910 }, + { 0x5682, 49914 }, + { 0x5688, 49918 }, + { 0x0472, 49922 }, + { 0x042A, 49926 }, + { 0x5646, 49931 }, + { 0x0500, 49935 }, + { 0x0502, 49940 }, + { 0x0508, 49945 }, + { 0x050A, 49950 }, + { 0x050C, 49955 }, + { 0x050E, 49960 }, + { 0x0504, 49965 }, + { 0x0506, 49970 }, + { 0x04BA, 49975 }, + { 0x5696, 49979 }, + { 0x5662, 49983 }, + { 0x5664, 49988 }, + { 0x5666, 49993 }, + { 0x042C, 49998 }, + { 0x5692, 50003 }, + { 0x040B, 50007 }, + { 0x5690, 50011 }, + { 0x568E, 50015 }, + { 0x042B, 50019 }, + { 0x5650, 50023 }, + { 0x04F8, 50030 }, + { 0x5684, 50036 }, + { 0x051E, 50040 }, + { 0x564C, 50045 }, + { 0x5648, 50050 }, + { 0x5642, 50054 }, + { 0x0480, 50058 }, + { 0x0460, 50062 }, + { 0x047C, 50066 }, + { 0x047A, 50072 }, + { 0x04D8, 50077 }, + { 0x04DA, 50081 }, + { 0x0429, 50087 }, + { 0x0419, 50091 }, + { 0x048A, 50096 }, + { 0x040E, 50103 }, + { 0x04E8, 50108 }, + { 0x04EA, 50113 }, + { 0x5658, 50120 }, + { 0x566C, 50126 }, + { 0x0466, 50132 }, + { 0x5640, 50137 }, + { 0x04A0, 50141 }, + { 0x565A, 50146 }, + { 0x0474, 50151 }, + { 0x0476, 50155 }, + { 0x564E, 50163 }, + { 0x5656, 50168 }, + { 0x0464, 50173 }, + { 0x046C, 50178 }, + { 0x5652, 50184 }, + { 0x565C, 50189 }, + { 0x0468, 50196 }, + { 0x5654, 50202 }, + { 0x0510, 50207 }, + { 0x5644, 50212 }, + { 0x048C, 50217 }, + { 0x04AE, 50222 }, + { 0x04B0, 50227 }, + { 0x04A8, 50234 }, + { 0x04BC, 50239 }, + { 0x04BE, 50244 }, + { 0x04E0, 50251 }, + { 0x566A, 50256 }, + { 0x5668, 50261 }, + { 0x564A, 50266 }, + { 0x0404, 50271 }, + { 0x04CB, 50276 }, + { 0x0406, 50281 }, + { 0x04D4, 50286 }, + { 0x04A4, 50291 }, + { 0x04B4, 50296 }, + { 0x567F, 50301 }, + { 0x0482, 50303 }, + { 0x2300, 50306 }, + { 0x00F7, 50308 }, + { 0x2215, 50310 }, + { 0x22C7, 50312 }, + { 0x279B, 50314 }, + { 0x2301, 50318 }, + { 0x2383, 50320 }, + { 0x2709, 50322 }, + { 0x1362, 50323 }, + { 0x1365, 50326 }, + { 0x1363, 50328 }, + { 0x1369, 50330 }, + { 0x136E, 50333 }, + { 0x136A, 50336 }, + { 0x136D, 50339 }, + { 0x136C, 50342 }, + { 0x1371, 50345 }, + { 0x1370, 50348 }, + { 0x136F, 50351 }, + { 0x136B, 50354 }, + { 0x1399, 50357 }, + { 0x1391, 50361 }, + { 0x1394, 50365 }, + { 0x1397, 50369 }, + { 0x1395, 50373 }, + { 0x1393, 50377 }, + { 0x1390, 50382 }, + { 0x1396, 50386 }, + { 0x1392, 50390 }, + { 0x1398, 50394 }, + { 0x1372, 50398 }, + { 0x137C, 50401 }, + { 0x1376, 50405 }, + { 0x1375, 50408 }, + { 0x1377, 50411 }, + { 0x1379, 50414 }, + { 0x137A, 50417 }, + { 0x1374, 50420 }, + { 0x1373, 50423 }, + { 0x137B, 50426 }, + { 0x1378, 50429 }, + { 0x1366, 50432 }, + { 0x1360, 50435 }, + { 0x1367, 50438 }, + { 0x1260, 50441 }, + { 0x1265, 50444 }, + { 0x1262, 50447 }, + { 0x1266, 50450 }, + { 0x1261, 50453 }, + { 0x1278, 50456 }, + { 0x127D, 50459 }, + { 0x127A, 50462 }, + { 0x127E, 50465 }, + { 0x1279, 50468 }, + { 0x12F0, 50471 }, + { 0x12F5, 50474 }, + { 0x12F2, 50477 }, + { 0x12F6, 50480 }, + { 0x12F1, 50483 }, + { 0x1348, 50486 }, + { 0x134D, 50489 }, + { 0x134A, 50492 }, + { 0x134E, 50495 }, + { 0x1349, 50498 }, + { 0x1308, 50501 }, + { 0x130D, 50504 }, + { 0x130A, 50507 }, + { 0x130E, 50510 }, + { 0x1309, 50513 }, + { 0x1200, 50516 }, + { 0x1205, 50519 }, + { 0x1202, 50522 }, + { 0x1206, 50525 }, + { 0x1201, 50528 }, + { 0x1300, 50531 }, + { 0x1305, 50534 }, + { 0x1302, 50537 }, + { 0x1306, 50540 }, + { 0x1301, 50543 }, + { 0x12A8, 50546 }, + { 0x12AD, 50549 }, + { 0x12AA, 50552 }, + { 0x12AE, 50555 }, + { 0x12A9, 50558 }, + { 0x1208, 50561 }, + { 0x120D, 50564 }, + { 0x120A, 50567 }, + { 0x120E, 50570 }, + { 0x1209, 50573 }, + { 0x1218, 50576 }, + { 0x121D, 50579 }, + { 0x121A, 50582 }, + { 0x121E, 50585 }, + { 0x1219, 50588 }, + { 0x1290, 50591 }, + { 0x1295, 50594 }, + { 0x1292, 50597 }, + { 0x1296, 50600 }, + { 0x1291, 50603 }, + { 0x1350, 50606 }, + { 0x1355, 50609 }, + { 0x1352, 50612 }, + { 0x1356, 50615 }, + { 0x1351, 50618 }, + { 0x1240, 50621 }, + { 0x1245, 50624 }, + { 0x1242, 50627 }, + { 0x1246, 50630 }, + { 0x1241, 50633 }, + { 0x1228, 50636 }, + { 0x122D, 50639 }, + { 0x122A, 50642 }, + { 0x122E, 50645 }, + { 0x1229, 50648 }, + { 0x1230, 50651 }, + { 0x1235, 50654 }, + { 0x1232, 50657 }, + { 0x1236, 50660 }, + { 0x1231, 50663 }, + { 0x1270, 50666 }, + { 0x1275, 50669 }, + { 0x1272, 50672 }, + { 0x1276, 50675 }, + { 0x1271, 50678 }, + { 0x1268, 50681 }, + { 0x126D, 50684 }, + { 0x126A, 50687 }, + { 0x126E, 50690 }, + { 0x1269, 50693 }, + { 0x12C8, 50696 }, + { 0x12CD, 50699 }, + { 0x12CA, 50702 }, + { 0x12CE, 50705 }, + { 0x12C9, 50708 }, + { 0x1280, 50711 }, + { 0x1285, 50714 }, + { 0x1282, 50717 }, + { 0x1286, 50720 }, + { 0x1281, 50723 }, + { 0x12E8, 50726 }, + { 0x12ED, 50729 }, + { 0x12EA, 50732 }, + { 0x12EE, 50735 }, + { 0x12E9, 50738 }, + { 0x12D8, 50741 }, + { 0x12DD, 50744 }, + { 0x12DA, 50747 }, + { 0x12DE, 50750 }, + { 0x12D9, 50753 }, + { 0x1263, 50756 }, + { 0x1264, 50759 }, + { 0x2D85, 50762 }, + { 0x1267, 50765 }, + { 0x1387, 50768 }, + { 0x1385, 50771 }, + { 0x127B, 50774 }, + { 0x2DA8, 50777 }, + { 0x2DAD, 50780 }, + { 0x2DAA, 50783 }, + { 0x2DAE, 50786 }, + { 0x2DA9, 50789 }, + { 0x127C, 50792 }, + { 0x1328, 50795 }, + { 0x132D, 50798 }, + { 0x132A, 50801 }, + { 0x132E, 50804 }, + { 0x1329, 50807 }, + { 0x2D87, 50810 }, + { 0x127F, 50813 }, + { 0x12F3, 50816 }, + { 0x12F8, 50819 }, + { 0x12FD, 50822 }, + { 0x12FA, 50825 }, + { 0x12FE, 50828 }, + { 0x12F9, 50831 }, + { 0x12F4, 50834 }, + { 0x2D8C, 50837 }, + { 0x12F7, 50840 }, + { 0x134B, 50843 }, + { 0x134C, 50846 }, + { 0x134F, 50849 }, + { 0x138B, 50852 }, + { 0x1389, 50855 }, + { 0x135A, 50858 }, + { 0x130B, 50861 }, + { 0x130C, 50864 }, + { 0x1318, 50867 }, + { 0x131D, 50870 }, + { 0x131A, 50873 }, + { 0x131E, 50876 }, + { 0x1319, 50879 }, + { 0x130F, 50882 }, + { 0x1310, 50885 }, + { 0x1315, 50888 }, + { 0x1312, 50891 }, + { 0x2DD8, 50894 }, + { 0x2DDD, 50897 }, + { 0x2DDA, 50900 }, + { 0x2DDE, 50903 }, + { 0x2DD9, 50906 }, + { 0x1203, 50909 }, + { 0x1204, 50912 }, + { 0x1210, 50915 }, + { 0x1215, 50918 }, + { 0x1212, 50921 }, + { 0x1216, 50924 }, + { 0x1211, 50927 }, + { 0x1207, 50930 }, + { 0x1303, 50933 }, + { 0x1304, 50936 }, + { 0x2D8E, 50939 }, + { 0x1307, 50942 }, + { 0x12AB, 50945 }, + { 0x12AC, 50948 }, + { 0x12AF, 50951 }, + { 0x12B0, 50954 }, + { 0x12B5, 50957 }, + { 0x12B2, 50960 }, + { 0x12B8, 50963 }, + { 0x12BD, 50966 }, + { 0x12BA, 50969 }, + { 0x12BE, 50972 }, + { 0x12B9, 50975 }, + { 0x2DC8, 50978 }, + { 0x2DCD, 50981 }, + { 0x2DCA, 50984 }, + { 0x2DCE, 50987 }, + { 0x2DC9, 50990 }, + { 0x120B, 50993 }, + { 0x120C, 50996 }, + { 0x2D80, 50999 }, + { 0x120F, 51002 }, + { 0x121B, 51005 }, + { 0x121C, 51008 }, + { 0x2D81, 51011 }, + { 0x121F, 51014 }, + { 0x1383, 51017 }, + { 0x1381, 51020 }, + { 0x1359, 51023 }, + { 0x1293, 51026 }, + { 0x1294, 51029 }, + { 0x2D88, 51032 }, + { 0x1297, 51035 }, + { 0x1298, 51038 }, + { 0x129D, 51041 }, + { 0x129A, 51044 }, + { 0x129E, 51047 }, + { 0x1299, 51050 }, + { 0x1353, 51053 }, + { 0x1354, 51056 }, + { 0x1330, 51059 }, + { 0x1335, 51062 }, + { 0x1332, 51065 }, + { 0x1336, 51068 }, + { 0x1331, 51071 }, + { 0x2D92, 51074 }, + { 0x1357, 51077 }, + { 0x138F, 51080 }, + { 0x138D, 51083 }, + { 0x1243, 51086 }, + { 0x1244, 51089 }, + { 0x1250, 51092 }, + { 0x1255, 51095 }, + { 0x1252, 51098 }, + { 0x1256, 51101 }, + { 0x1251, 51104 }, + { 0x1247, 51107 }, + { 0x1248, 51110 }, + { 0x124D, 51113 }, + { 0x124A, 51116 }, + { 0x2DC0, 51119 }, + { 0x2DC5, 51122 }, + { 0x2DC2, 51125 }, + { 0x2DC6, 51128 }, + { 0x2DC1, 51131 }, + { 0x122B, 51134 }, + { 0x122C, 51137 }, + { 0x2D82, 51140 }, + { 0x122F, 51143 }, + { 0x1358, 51146 }, + { 0x1233, 51149 }, + { 0x1234, 51152 }, + { 0x1238, 51155 }, + { 0x123D, 51158 }, + { 0x123A, 51161 }, + { 0x123E, 51164 }, + { 0x1239, 51167 }, + { 0x2D83, 51170 }, + { 0x2DA0, 51173 }, + { 0x2DA5, 51176 }, + { 0x2DA2, 51179 }, + { 0x2DA6, 51182 }, + { 0x2DA1, 51185 }, + { 0x1237, 51188 }, + { 0x1220, 51191 }, + { 0x1225, 51194 }, + { 0x1222, 51197 }, + { 0x1226, 51200 }, + { 0x1221, 51203 }, + { 0x1273, 51206 }, + { 0x1274, 51209 }, + { 0x1320, 51212 }, + { 0x1325, 51215 }, + { 0x1322, 51218 }, + { 0x1326, 51221 }, + { 0x1321, 51224 }, + { 0x2D86, 51227 }, + { 0x1338, 51230 }, + { 0x133D, 51233 }, + { 0x133A, 51236 }, + { 0x133E, 51239 }, + { 0x1339, 51242 }, + { 0x1277, 51245 }, + { 0x1340, 51248 }, + { 0x1345, 51251 }, + { 0x1342, 51254 }, + { 0x1346, 51257 }, + { 0x1341, 51260 }, + { 0x126B, 51263 }, + { 0x126C, 51266 }, + { 0x126F, 51269 }, + { 0x12CB, 51272 }, + { 0x12CC, 51275 }, + { 0x12CF, 51278 }, + { 0x1283, 51281 }, + { 0x1284, 51284 }, + { 0x1287, 51287 }, + { 0x1288, 51290 }, + { 0x128D, 51293 }, + { 0x128A, 51296 }, + { 0x2DD0, 51299 }, + { 0x2DD5, 51302 }, + { 0x2DD2, 51305 }, + { 0x2DD6, 51308 }, + { 0x2DD1, 51311 }, + { 0x12EB, 51314 }, + { 0x12EC, 51317 }, + { 0x12EF, 51320 }, + { 0x12DB, 51323 }, + { 0x12DC, 51326 }, + { 0x12E0, 51329 }, + { 0x12E5, 51332 }, + { 0x12E2, 51335 }, + { 0x12E6, 51338 }, + { 0x12E1, 51341 }, + { 0x2D8B, 51344 }, + { 0x12DF, 51347 }, + { 0x2DB0, 51350 }, + { 0x2DB5, 51353 }, + { 0x2DB2, 51356 }, + { 0x2DB6, 51359 }, + { 0x2DB1, 51362 }, + { 0x1386, 51365 }, + { 0x2DAB, 51368 }, + { 0x2DAC, 51371 }, + { 0x2DB8, 51374 }, + { 0x2DBD, 51377 }, + { 0x2DBA, 51380 }, + { 0x2DBE, 51383 }, + { 0x2DB9, 51386 }, + { 0x132B, 51389 }, + { 0x132C, 51392 }, + { 0x2D90, 51395 }, + { 0x132F, 51398 }, + { 0x12FB, 51401 }, + { 0x12FC, 51404 }, + { 0x2D8D, 51407 }, + { 0x12FF, 51410 }, + { 0x138A, 51413 }, + { 0x131B, 51416 }, + { 0x131C, 51419 }, + { 0x2D93, 51422 }, + { 0x2D96, 51425 }, + { 0x2D94, 51428 }, + { 0x1313, 51431 }, + { 0x1314, 51434 }, + { 0x2DDB, 51437 }, + { 0x2DDC, 51440 }, + { 0x1213, 51443 }, + { 0x1214, 51446 }, + { 0x1217, 51449 }, + { 0x12B3, 51452 }, + { 0x12B4, 51455 }, + { 0x12BB, 51458 }, + { 0x12BC, 51461 }, + { 0x12C0, 51464 }, + { 0x12C5, 51467 }, + { 0x12C2, 51470 }, + { 0x2DCB, 51473 }, + { 0x2DCC, 51476 }, + { 0x1382, 51479 }, + { 0x129B, 51482 }, + { 0x129C, 51485 }, + { 0x2D89, 51488 }, + { 0x129F, 51491 }, + { 0x1333, 51494 }, + { 0x1334, 51497 }, + { 0x2D91, 51500 }, + { 0x1337, 51503 }, + { 0x138E, 51506 }, + { 0x1253, 51509 }, + { 0x1254, 51512 }, + { 0x1258, 51515 }, + { 0x125D, 51518 }, + { 0x125A, 51521 }, + { 0x124B, 51524 }, + { 0x124C, 51527 }, + { 0x2DC3, 51530 }, + { 0x2DC4, 51533 }, + { 0x123B, 51536 }, + { 0x123C, 51539 }, + { 0x2D84, 51542 }, + { 0x123F, 51545 }, + { 0x2DA3, 51548 }, + { 0x2DA4, 51551 }, + { 0x1223, 51554 }, + { 0x1224, 51557 }, + { 0x1227, 51560 }, + { 0x1323, 51563 }, + { 0x1324, 51566 }, + { 0x2D8F, 51569 }, + { 0x1327, 51572 }, + { 0x133B, 51575 }, + { 0x133C, 51578 }, + { 0x133F, 51581 }, + { 0x1343, 51584 }, + { 0x1344, 51587 }, + { 0x1347, 51590 }, + { 0x128B, 51593 }, + { 0x128C, 51596 }, + { 0x2DD3, 51599 }, + { 0x2DD4, 51602 }, + { 0x12E3, 51605 }, + { 0x12E4, 51608 }, + { 0x12E7, 51611 }, + { 0x2DB3, 51614 }, + { 0x2DB4, 51617 }, + { 0x2DBB, 51620 }, + { 0x2DBC, 51623 }, + { 0x131F, 51626 }, + { 0x2D95, 51629 }, + { 0x12C3, 51632 }, + { 0x12C4, 51635 }, + { 0x125B, 51638 }, + { 0x125C, 51641 }, + { 0x12A0, 51644 }, + { 0x12A5, 51648 }, + { 0x12A2, 51652 }, + { 0x12A6, 51656 }, + { 0x12A1, 51660 }, + { 0x12A3, 51664 }, + { 0x12A4, 51668 }, + { 0x2D8A, 51672 }, + { 0x12A7, 51676 }, + { 0x1384, 51680 }, + { 0x1388, 51684 }, + { 0x1380, 51688 }, + { 0x138C, 51692 }, + { 0x12D0, 51696 }, + { 0x12D5, 51700 }, + { 0x12D2, 51704 }, + { 0x12D6, 51708 }, + { 0x12D1, 51712 }, + { 0x12D3, 51716 }, + { 0x12D4, 51720 }, + { 0x135F, 51724 }, + { 0x1368, 51728 }, + { 0x1364, 51731 }, + { 0x1361, 51733 }, + { 0x06F1, 51735 }, + { 0x06F6, 51739 }, + { 0x06F2, 51743 }, + { 0x06F5, 51747 }, + { 0x06F4, 51751 }, + { 0x06F9, 51755 }, + { 0x06F0, 51759 }, + { 0x06F8, 51763 }, + { 0x06F7, 51767 }, + { 0x06F3, 51771 }, + { 0x00AA, 51775 }, + { 0x23E5, 51778 }, + { 0x2044, 51779 }, + { 0x215F, 51781 }, + { 0x2061, 51784 }, + { 0x2D00, 51786 }, + { 0x2D04, 51790 }, + { 0x2D21, 51794 }, + { 0x2D08, 51798 }, + { 0x2D0D, 51802 }, + { 0x2D13, 51806 }, + { 0x2D23, 51810 }, + { 0x2D01, 51814 }, + { 0x2D1A, 51818 }, + { 0x2D1C, 51822 }, + { 0x2D03, 51826 }, + { 0x2D02, 51830 }, + { 0x2D20, 51834 }, + { 0x2D24, 51838 }, + { 0x2D22, 51842 }, + { 0x2D25, 51846 }, + { 0x2D1B, 51850 }, + { 0x2D09, 51854 }, + { 0x2D0A, 51858 }, + { 0x2D0B, 51862 }, + { 0x2D0C, 51866 }, + { 0x2D0E, 51870 }, + { 0x2D17, 51874 }, + { 0x2D10, 51878 }, + { 0x2D11, 51882 }, + { 0x2D07, 51886 }, + { 0x2D12, 51890 }, + { 0x2D05, 51894 }, + { 0x2D1E, 51898 }, + { 0x2D06, 51902 }, + { 0x2D1D, 51906 }, + { 0x2D19, 51910 }, + { 0x2D16, 51914 }, + { 0x2D1F, 51918 }, + { 0x2D15, 51922 }, + { 0x2D14, 51926 }, + { 0x2D18, 51930 }, + { 0x2D0F, 51934 }, + { 0x10D0, 51938 }, + { 0x10D4, 51941 }, + { 0x10F6, 51944 }, + { 0x10F1, 51947 }, + { 0x10D8, 51950 }, + { 0x10DD, 51953 }, + { 0x10E3, 51956 }, + { 0x10F3, 51959 }, + { 0x10F7, 51962 }, + { 0x10FA, 51965 }, + { 0x10D1, 51968 }, + { 0x10EA, 51971 }, + { 0x10EC, 51974 }, + { 0x10D3, 51977 }, + { 0x10D2, 51980 }, + { 0x10F0, 51983 }, + { 0x10F4, 51986 }, + { 0x10F2, 51989 }, + { 0x10F5, 51992 }, + { 0x10EB, 51995 }, + { 0x10D9, 51998 }, + { 0x10DA, 52001 }, + { 0x10DB, 52004 }, + { 0x10DC, 52007 }, + { 0x10DE, 52010 }, + { 0x10E7, 52013 }, + { 0x10E0, 52016 }, + { 0x10E1, 52019 }, + { 0x10D7, 52022 }, + { 0x10E2, 52025 }, + { 0x10D5, 52028 }, + { 0x10EE, 52031 }, + { 0x10D6, 52034 }, + { 0x10ED, 52037 }, + { 0x10E9, 52040 }, + { 0x10E6, 52043 }, + { 0x10EF, 52046 }, + { 0x10E5, 52049 }, + { 0x10E4, 52052 }, + { 0x10E8, 52055 }, + { 0x10DF, 52058 }, + { 0x10F8, 52061 }, + { 0x10F9, 52064 }, + { 0x10A0, 52068 }, + { 0x10A4, 52072 }, + { 0x10C1, 52076 }, + { 0x10A8, 52080 }, + { 0x10AD, 52084 }, + { 0x10B3, 52088 }, + { 0x10C3, 52092 }, + { 0x10A1, 52096 }, + { 0x10BA, 52100 }, + { 0x10BC, 52104 }, + { 0x10A3, 52108 }, + { 0x10A2, 52112 }, + { 0x10C0, 52116 }, + { 0x10C4, 52120 }, + { 0x10C2, 52124 }, + { 0x10C5, 52128 }, + { 0x10BB, 52132 }, + { 0x10A9, 52136 }, + { 0x10AA, 52140 }, + { 0x10AB, 52144 }, + { 0x10AC, 52148 }, + { 0x10AE, 52152 }, + { 0x10B7, 52156 }, + { 0x10B0, 52160 }, + { 0x10B1, 52164 }, + { 0x10A7, 52168 }, + { 0x10B2, 52172 }, + { 0x10A5, 52176 }, + { 0x10BE, 52180 }, + { 0x10A6, 52184 }, + { 0x10BD, 52188 }, + { 0x10B9, 52192 }, + { 0x10B6, 52196 }, + { 0x10BF, 52200 }, + { 0x10B5, 52204 }, + { 0x10B4, 52208 }, + { 0x10B8, 52212 }, + { 0x10AF, 52216 }, + { 0x10FB, 52220 }, + { 0x0AD0, 52223 }, + { 0x0ABC, 52225 }, + { 0x0ACD, 52228 }, + { 0x0A83, 52231 }, + { 0x0A82, 52234 }, + { 0x0ABD, 52237 }, + { 0x0A81, 52240 }, + { 0x0AE7, 52243 }, + { 0x0AEC, 52246 }, + { 0x0AE8, 52249 }, + { 0x0AEB, 52252 }, + { 0x0AEA, 52255 }, + { 0x0AEF, 52258 }, + { 0x0AE6, 52261 }, + { 0x0AEE, 52264 }, + { 0x0AED, 52267 }, + { 0x0AE9, 52270 }, + { 0x0AF1, 52273 }, + { 0x0AC7, 52276 }, + { 0x0ABF, 52280 }, + { 0x0ACB, 52284 }, + { 0x0AC1, 52288 }, + { 0x0ABE, 52292 }, + { 0x0AC8, 52296 }, + { 0x0ACC, 52300 }, + { 0x0AC0, 52304 }, + { 0x0AC2, 52308 }, + { 0x0AC5, 52312 }, + { 0x0AC9, 52317 }, + { 0x0AE2, 52322 }, + { 0x0AC3, 52327 }, + { 0x0AE3, 52332 }, + { 0x0AC4, 52337 }, + { 0x0A8D, 52342 }, + { 0x0A91, 52346 }, + { 0x0A85, 52350 }, + { 0x0A8F, 52353 }, + { 0x0A87, 52356 }, + { 0x0A93, 52359 }, + { 0x0A89, 52362 }, + { 0x0A86, 52365 }, + { 0x0A90, 52368 }, + { 0x0A94, 52371 }, + { 0x0AAC, 52374 }, + { 0x0A9A, 52377 }, + { 0x0AA6, 52380 }, + { 0x0A97, 52383 }, + { 0x0AB9, 52386 }, + { 0x0A88, 52389 }, + { 0x0A9C, 52392 }, + { 0x0A95, 52395 }, + { 0x0AB2, 52398 }, + { 0x0AAE, 52401 }, + { 0x0AA8, 52404 }, + { 0x0AAA, 52407 }, + { 0x0AB0, 52410 }, + { 0x0AB8, 52413 }, + { 0x0AA4, 52416 }, + { 0x0A8A, 52419 }, + { 0x0AB5, 52422 }, + { 0x0AAF, 52425 }, + { 0x0AAD, 52428 }, + { 0x0A9B, 52431 }, + { 0x0AA1, 52434 }, + { 0x0AA7, 52437 }, + { 0x0A98, 52440 }, + { 0x0A9D, 52443 }, + { 0x0A96, 52446 }, + { 0x0AB3, 52449 }, + { 0x0A99, 52452 }, + { 0x0AA3, 52455 }, + { 0x0A9E, 52458 }, + { 0x0AAB, 52461 }, + { 0x0AB6, 52464 }, + { 0x0AB7, 52467 }, + { 0x0AA5, 52470 }, + { 0x0A9F, 52473 }, + { 0x0AA2, 52476 }, + { 0x0AA0, 52479 }, + { 0x0A8C, 52482 }, + { 0x0A8B, 52486 }, + { 0x0AE1, 52490 }, + { 0x0AE0, 52494 }, + { 0x0A74, 52498 }, + { 0x0A72, 52501 }, + { 0x0A73, 52503 }, + { 0x0A01, 52505 }, + { 0x0A02, 52509 }, + { 0x0A3C, 52512 }, + { 0x0A51, 52515 }, + { 0x0A4D, 52518 }, + { 0x0A75, 52521 }, + { 0x0A03, 52524 }, + { 0x0A71, 52527 }, + { 0x0A67, 52529 }, + { 0x0A6C, 52532 }, + { 0x0A68, 52535 }, + { 0x0A6B, 52538 }, + { 0x0A6A, 52541 }, + { 0x0A6F, 52544 }, + { 0x0A66, 52547 }, + { 0x0A6E, 52550 }, + { 0x0A6D, 52553 }, + { 0x0A69, 52556 }, + { 0x0A70, 52559 }, + { 0x0A3F, 52561 }, + { 0x0A41, 52565 }, + { 0x0A3E, 52569 }, + { 0x0A48, 52573 }, + { 0x0A4C, 52577 }, + { 0x0A47, 52581 }, + { 0x0A40, 52585 }, + { 0x0A4B, 52589 }, + { 0x0A42, 52593 }, + { 0x0A05, 52597 }, + { 0x0A07, 52600 }, + { 0x0A09, 52603 }, + { 0x0A06, 52606 }, + { 0x0A10, 52609 }, + { 0x0A14, 52612 }, + { 0x0A2C, 52615 }, + { 0x0A1A, 52618 }, + { 0x0A26, 52621 }, + { 0x0A0F, 52624 }, + { 0x0A5E, 52627 }, + { 0x0A17, 52630 }, + { 0x0A39, 52633 }, + { 0x0A08, 52636 }, + { 0x0A1C, 52639 }, + { 0x0A15, 52642 }, + { 0x0A32, 52645 }, + { 0x0A2E, 52648 }, + { 0x0A28, 52651 }, + { 0x0A13, 52654 }, + { 0x0A2A, 52657 }, + { 0x0A30, 52660 }, + { 0x0A38, 52663 }, + { 0x0A24, 52666 }, + { 0x0A0A, 52669 }, + { 0x0A35, 52672 }, + { 0x0A2F, 52675 }, + { 0x0A5B, 52678 }, + { 0x0A2D, 52681 }, + { 0x0A1B, 52684 }, + { 0x0A21, 52687 }, + { 0x0A27, 52690 }, + { 0x0A18, 52693 }, + { 0x0A1D, 52696 }, + { 0x0A16, 52699 }, + { 0x0A33, 52702 }, + { 0x0A19, 52705 }, + { 0x0A23, 52708 }, + { 0x0A1E, 52711 }, + { 0x0A2B, 52714 }, + { 0x0A5C, 52717 }, + { 0x0A36, 52720 }, + { 0x0A25, 52723 }, + { 0x0A1F, 52726 }, + { 0x0A22, 52729 }, + { 0x0A5A, 52732 }, + { 0x0A59, 52735 }, + { 0x0A20, 52738 }, + { 0x3021, 52741 }, + { 0x3026, 52744 }, + { 0x3038, 52747 }, + { 0x3022, 52750 }, + { 0x3025, 52753 }, + { 0x3024, 52756 }, + { 0x3029, 52759 }, + { 0x3028, 52762 }, + { 0x3027, 52765 }, + { 0x3023, 52768 }, + { 0x303A, 52771 }, + { 0x3039, 52774 }, + { 0x4DC6, 52777 }, + { 0x4DEF, 52781 }, + { 0x4DE4, 52785 }, + { 0x4DF8, 52789 }, + { 0x4DF9, 52794 }, + { 0x4DDC, 52799 }, + { 0x4DF3, 52804 }, + { 0x4DF2, 52810 }, + { 0x4DF1, 52815 }, + { 0x4DDD, 52819 }, + { 0x4DC0, 52824 }, + { 0x4DF5, 52829 }, + { 0x4DF7, 52834 }, + { 0x4DC1, 52838 }, + { 0x4DD1, 52843 }, + { 0x4DFE, 52849 }, + { 0x4DD5, 52853 }, + { 0x4DE1, 52856 }, + { 0x4DD9, 52860 }, + { 0x4DCD, 52864 }, + { 0x4DDB, 52868 }, + { 0x4DFC, 52872 }, + { 0x4DDA, 52876 }, + { 0x4DCA, 52880 }, + { 0x4DC8, 52883 }, + { 0x4DFD, 52887 }, + { 0x4DFF, 52891 }, + { 0x4DD4, 52895 }, + { 0x4DEB, 52899 }, + { 0x4DD7, 52904 }, + { 0x4DC7, 52907 }, + { 0x4DCE, 52911 }, + { 0x4DED, 52914 }, + { 0x4DE0, 52918 }, + { 0x4DC4, 52921 }, + { 0x4DD2, 52924 }, + { 0x4DC5, 52927 }, + { 0x4DE8, 52930 }, + { 0x4DDF, 52933 }, + { 0x4DE9, 52936 }, + { 0x4DE2, 52939 }, + { 0x4DC9, 52942 }, + { 0x4DC3, 52945 }, + { 0x4DF6, 52949 }, + { 0x4DE3, 52952 }, + { 0x4DD0, 52958 }, + { 0x4DEC, 52961 }, + { 0x4DDE, 52965 }, + { 0x4DD8, 52968 }, + { 0x4DD6, 52971 }, + { 0x4DC2, 52975 }, + { 0x4DFA, 52981 }, + { 0x4DCF, 52984 }, + { 0x4DCC, 52987 }, + { 0x4DFB, 52990 }, + { 0x4DE5, 52993 }, + { 0x4DEE, 52996 }, + { 0x4DF0, 52999 }, + { 0x4DCB, 53002 }, + { 0x4DE7, 53005 }, + { 0x4DF4, 53008 }, + { 0x4DE6, 53011 }, + { 0x4DEA, 53014 }, + { 0x4DD3, 53017 }, + { 0x3042, 53020 }, + { 0x3048, 53023 }, + { 0x3044, 53026 }, + { 0x3093, 53029 }, + { 0x304A, 53032 }, + { 0x3046, 53035 }, + { 0x3070, 53038 }, + { 0x3079, 53041 }, + { 0x3073, 53044 }, + { 0x307C, 53047 }, + { 0x3076, 53050 }, + { 0x3060, 53053 }, + { 0x3067, 53056 }, + { 0x3062, 53059 }, + { 0x3069, 53062 }, + { 0x3065, 53065 }, + { 0x304C, 53068 }, + { 0x3052, 53071 }, + { 0x304E, 53074 }, + { 0x3054, 53077 }, + { 0x3050, 53080 }, + { 0x306F, 53083 }, + { 0x3078, 53086 }, + { 0x3072, 53089 }, + { 0x307B, 53092 }, + { 0x3075, 53095 }, + { 0x304B, 53098 }, + { 0x3051, 53101 }, + { 0x304D, 53104 }, + { 0x3053, 53107 }, + { 0x304F, 53110 }, + { 0x307E, 53113 }, + { 0x3081, 53116 }, + { 0x307F, 53119 }, + { 0x3082, 53122 }, + { 0x3080, 53125 }, + { 0x306A, 53128 }, + { 0x306D, 53131 }, + { 0x306B, 53134 }, + { 0x306E, 53137 }, + { 0x306C, 53140 }, + { 0x3071, 53143 }, + { 0x307A, 53146 }, + { 0x3074, 53149 }, + { 0x307D, 53152 }, + { 0x3077, 53155 }, + { 0x3089, 53158 }, + { 0x308C, 53161 }, + { 0x308A, 53164 }, + { 0x308D, 53167 }, + { 0x308B, 53170 }, + { 0x3055, 53173 }, + { 0x305B, 53176 }, + { 0x3057, 53179 }, + { 0x305D, 53182 }, + { 0x3059, 53185 }, + { 0x305F, 53188 }, + { 0x3066, 53191 }, + { 0x3061, 53194 }, + { 0x3068, 53197 }, + { 0x3064, 53200 }, + { 0x3094, 53203 }, + { 0x308F, 53206 }, + { 0x3091, 53209 }, + { 0x3090, 53212 }, + { 0x3092, 53215 }, + { 0x3084, 53218 }, + { 0x3088, 53221 }, + { 0x3086, 53224 }, + { 0x3056, 53227 }, + { 0x305C, 53230 }, + { 0x3058, 53233 }, + { 0x305E, 53236 }, + { 0x305A, 53239 }, + { 0x3041, 53242 }, + { 0x3047, 53246 }, + { 0x3043, 53250 }, + { 0x3049, 53254 }, + { 0x3045, 53258 }, + { 0x3095, 53262 }, + { 0x3096, 53266 }, + { 0x3063, 53270 }, + { 0x308E, 53274 }, + { 0x3083, 53278 }, + { 0x3087, 53282 }, + { 0x3085, 53286 }, + { 0x309E, 53290 }, + { 0x309F, 53294 }, + { 0x309D, 53297 }, + { 0x221E, 53300 }, + { 0x29DE, 53301 }, + { 0x222B, 53306 }, + { 0x2A18, 53307 }, + { 0x2A1A, 53311 }, + { 0x2A0E, 53314 }, + { 0x2A1B, 53318 }, + { 0x2A1C, 53321 }, + { 0x2A17, 53324 }, + { 0x2A19, 53330 }, + { 0x2A15, 53333 }, + { 0x2A0F, 53338 }, + { 0x23AE, 53342 }, + { 0x2A3C, 53344 }, + { 0x2127, 53346 }, + { 0x223E, 53349 }, + { 0x00BF, 53352 }, + { 0x2054, 53355 }, + { 0x00A1, 53357 }, + { 0x2E18, 53360 }, + { 0x3004, 53362 }, + { 0x30A2, 53366 }, + { 0x30A8, 53369 }, + { 0x30A4, 53372 }, + { 0x30F3, 53375 }, + { 0x30AA, 53378 }, + { 0x30A6, 53381 }, + { 0x30D0, 53384 }, + { 0x30D9, 53387 }, + { 0x30D3, 53390 }, + { 0x30DC, 53393 }, + { 0x30D6, 53396 }, + { 0x30C0, 53399 }, + { 0x30C7, 53402 }, + { 0x30C2, 53405 }, + { 0x30C9, 53408 }, + { 0x30C5, 53411 }, + { 0x30AC, 53414 }, + { 0x30B2, 53417 }, + { 0x30AE, 53420 }, + { 0x30B4, 53423 }, + { 0x30B0, 53426 }, + { 0x30CF, 53429 }, + { 0x30D8, 53432 }, + { 0x30D2, 53435 }, + { 0x30DB, 53438 }, + { 0x30D5, 53441 }, + { 0x30AB, 53444 }, + { 0x30B1, 53447 }, + { 0x30AD, 53450 }, + { 0x30B3, 53453 }, + { 0x30AF, 53456 }, + { 0x30DE, 53459 }, + { 0x30E1, 53462 }, + { 0x30DF, 53465 }, + { 0x30E2, 53468 }, + { 0x30E0, 53471 }, + { 0x30CA, 53474 }, + { 0x30CD, 53477 }, + { 0x30CB, 53480 }, + { 0x30CE, 53483 }, + { 0x30CC, 53486 }, + { 0x30D1, 53489 }, + { 0x30DA, 53492 }, + { 0x30D4, 53495 }, + { 0x30DD, 53498 }, + { 0x30D7, 53501 }, + { 0x30E9, 53504 }, + { 0x30EC, 53507 }, + { 0x30EA, 53510 }, + { 0x30ED, 53513 }, + { 0x30EB, 53516 }, + { 0x30B5, 53519 }, + { 0x30BB, 53522 }, + { 0x30B7, 53525 }, + { 0x30BD, 53528 }, + { 0x30B9, 53531 }, + { 0x30BF, 53534 }, + { 0x30C6, 53537 }, + { 0x30C1, 53540 }, + { 0x30C8, 53543 }, + { 0x30C4, 53546 }, + { 0x30F7, 53549 }, + { 0x30F9, 53552 }, + { 0x30F8, 53555 }, + { 0x30FA, 53558 }, + { 0x30F4, 53561 }, + { 0x30EF, 53564 }, + { 0x30F1, 53567 }, + { 0x30F0, 53570 }, + { 0x30F2, 53573 }, + { 0x30E4, 53576 }, + { 0x30E8, 53579 }, + { 0x30E6, 53582 }, + { 0x30B6, 53585 }, + { 0x30BC, 53588 }, + { 0x30B8, 53591 }, + { 0x30BE, 53594 }, + { 0x30BA, 53597 }, + { 0x30A1, 53600 }, + { 0x30A7, 53604 }, + { 0x30A3, 53608 }, + { 0x30A9, 53612 }, + { 0x30A5, 53616 }, + { 0x31F5, 53620 }, + { 0x31F8, 53624 }, + { 0x31F6, 53628 }, + { 0x31F9, 53632 }, + { 0x31F7, 53636 }, + { 0x30F5, 53640 }, + { 0x30F6, 53644 }, + { 0x31F0, 53648 }, + { 0x31FA, 53652 }, + { 0x31F4, 53656 }, + { 0x31FB, 53660 }, + { 0x31FE, 53664 }, + { 0x31FC, 53668 }, + { 0x31FF, 53672 }, + { 0x31FD, 53676 }, + { 0x31F1, 53680 }, + { 0x31F2, 53684 }, + { 0x31F3, 53688 }, + { 0x30C3, 53692 }, + { 0x30EE, 53696 }, + { 0x30E3, 53700 }, + { 0x30E7, 53704 }, + { 0x30E5, 53708 }, + { 0x30FB, 53712 }, + { 0x30FE, 53715 }, + { 0x30FF, 53719 }, + { 0x30FD, 53722 }, + { 0x2328, 53725 }, + { 0xC001, 53726 }, + { 0x26AD, 53728 }, + { 0x225E, 53730 }, + { 0x2221, 53732 }, + { 0x29A9, 53734 }, + { 0x29A8, 53746 }, + { 0x29AB, 53758 }, + { 0x29AA, 53770 }, + { 0x29AD, 53782 }, + { 0x29AF, 53794 }, + { 0x29AC, 53806 }, + { 0x29AE, 53818 }, + { 0x299B, 53830 }, + { 0x299D, 53834 }, + { 0x23D5, 53839 }, + { 0x23D6, 53844 }, + { 0x23D4, 53848 }, + { 0x23D2, 53853 }, + { 0x23D1, 53857 }, + { 0x23D3, 53859 }, + { 0x23D7, 53863 }, + { 0x23D9, 53865 }, + { 0x23D8, 53867 }, + { 0x02D4, 53869 }, + { 0x02C4, 53873 }, + { 0x5770, 53877 }, + { 0x5718, 53880 }, + { 0x5717, 53884 }, + { 0x5719, 53889 }, + { 0x02FC, 53894 }, + { 0x02FA, 53899 }, + { 0x02F0, 53904 }, + { 0x02EF, 53909 }, + { 0x02FF, 53914 }, + { 0x02F1, 53919 }, + { 0x02F3, 53924 }, + { 0x02E8, 53928 }, + { 0x02CF, 53933 }, + { 0x02CE, 53938 }, + { 0x02F2, 53943 }, + { 0x02F7, 53948 }, + { 0x570B, 53952 }, + { 0x5710, 53958 }, + { 0x02CD, 53965 }, + { 0x571F, 53969 }, + { 0x02CC, 53975 }, + { 0x5715, 53980 }, + { 0x5788, 53986 }, + { 0x02E7, 53991 }, + { 0x570A, 53996 }, + { 0x570F, 54002 }, + { 0x5714, 54009 }, + { 0x02EA, 54015 }, + { 0x02D5, 54021 }, + { 0x02C5, 54025 }, + { 0x02D1, 54029 }, + { 0x02E6, 54034 }, + { 0x5709, 54039 }, + { 0x570E, 54045 }, + { 0x5713, 54052 }, + { 0x02BF, 54058 }, + { 0x02C2, 54063 }, + { 0x02FE, 54067 }, + { 0x02D6, 54071 }, + { 0x02EB, 54075 }, + { 0x02CA, 54081 }, + { 0x02FB, 54085 }, + { 0x02F9, 54090 }, + { 0x5789, 54095 }, + { 0x02DF, 54098 }, + { 0x02CB, 54102 }, + { 0x571A, 54106 }, + { 0x02D7, 54112 }, + { 0x02B9, 54116 }, + { 0x02BE, 54119 }, + { 0x02C3, 54124 }, + { 0x02FD, 54128 }, + { 0x578A, 54131 }, + { 0x1D43, 54136 }, + { 0x1D47, 54140 }, + { 0x1D9C, 54144 }, + { 0x1D9D, 54148 }, + { 0x1D48, 54154 }, + { 0x1D49, 54158 }, + { 0x1DA0, 54162 }, + { 0x1D4D, 54166 }, + { 0x02B0, 54170 }, + { 0x02B1, 54174 }, + { 0x1DA4, 54180 }, + { 0x02B2, 54186 }, + { 0x1DA8, 54190 }, + { 0x1D4F, 54196 }, + { 0x02E1, 54200 }, + { 0x1DAA, 54204 }, + { 0x1DA9, 54211 }, + { 0x1D50, 54218 }, + { 0x1DAC, 54222 }, + { 0x1DAE, 54228 }, + { 0x1DAF, 54235 }, + { 0x1D52, 54242 }, + { 0x1D56, 54246 }, + { 0x02B3, 54250 }, + { 0x02E2, 54254 }, + { 0x1DB3, 54258 }, + { 0x1D57, 54264 }, + { 0x1DB5, 54268 }, + { 0x1D58, 54275 }, + { 0x1DB6, 54279 }, + { 0x1D5B, 54284 }, + { 0x1DB9, 54288 }, + { 0x02B7, 54294 }, + { 0x02E3, 54298 }, + { 0x02B8, 54302 }, + { 0x1DBB, 54306 }, + { 0x1DBD, 54310 }, + { 0x1DBC, 54316 }, + { 0x1D5C, 54323 }, + { 0x1D61, 54327 }, + { 0x1D51, 54331 }, + { 0x1DB4, 54335 }, + { 0x1D9E, 54339 }, + { 0x1DBE, 54343 }, + { 0x1DB2, 54347 }, + { 0x1D54, 54351 }, + { 0x1D5D, 54357 }, + { 0x1DA5, 54361 }, + { 0x1D4B, 54365 }, + { 0x1D53, 54370 }, + { 0x1D45, 54375 }, + { 0x1D5F, 54379 }, + { 0x02E0, 54383 }, + { 0x1D60, 54387 }, + { 0x1D5E, 54392 }, + { 0x1D4A, 54397 }, + { 0x1DBF, 54401 }, + { 0x1DB1, 54405 }, + { 0x1D55, 54410 }, + { 0x1DA2, 54416 }, + { 0x1D44, 54421 }, + { 0x1DA3, 54426 }, + { 0x1D4E, 54431 }, + { 0x1D5A, 54436 }, + { 0x1DAD, 54441 }, + { 0x02B4, 54449 }, + { 0x02B5, 54454 }, + { 0x1DBA, 54461 }, + { 0x1D46, 54466 }, + { 0x1D4C, 54471 }, + { 0x1D9B, 54477 }, + { 0x1DA6, 54482 }, + { 0x1DA7, 54487 }, + { 0x1DAB, 54494 }, + { 0x1DB0, 54499 }, + { 0x1DB8, 54504 }, + { 0x02B6, 54509 }, + { 0x1DA1, 54515 }, + { 0x1DB7, 54522 }, + { 0x1D9F, 54526 }, + { 0x02E4, 54532 }, + { 0x1D59, 54538 }, + { 0x02BA, 54543 }, + { 0x02EE, 54547 }, + { 0x02C9, 54551 }, + { 0x02F4, 54554 }, + { 0x02F6, 54559 }, + { 0x02F5, 54565 }, + { 0x571B, 54571 }, + { 0x571C, 54576 }, + { 0x02F8, 54581 }, + { 0x571E, 54585 }, + { 0x571D, 54591 }, + { 0x02DE, 54596 }, + { 0x5721, 54600 }, + { 0x5720, 54606 }, + { 0x02BB, 54612 }, + { 0x1D2C, 54616 }, + { 0x1D2E, 54620 }, + { 0x1D30, 54624 }, + { 0x1D31, 54628 }, + { 0x1D33, 54632 }, + { 0x1D34, 54636 }, + { 0x1D35, 54640 }, + { 0x1D36, 54644 }, + { 0x1D37, 54648 }, + { 0x1D38, 54652 }, + { 0x1D39, 54656 }, + { 0x1D3A, 54660 }, + { 0x1D3C, 54664 }, + { 0x1D3E, 54668 }, + { 0x1D3F, 54672 }, + { 0x1D40, 54676 }, + { 0x1D41, 54680 }, + { 0x2C7D, 54684 }, + { 0x1D42, 54688 }, + { 0x1D2D, 54692 }, + { 0x1D3D, 54696 }, + { 0x1D2F, 54700 }, + { 0x1D32, 54705 }, + { 0x1D3B, 54710 }, + { 0x02D3, 54715 }, + { 0x02D2, 54721 }, + { 0x5704, 54727 }, + { 0x5706, 54733 }, + { 0x5700, 54739 }, + { 0x5702, 54745 }, + { 0x5705, 54751 }, + { 0x5707, 54757 }, + { 0x5701, 54763 }, + { 0x5703, 54769 }, + { 0x02C0, 54775 }, + { 0x02EC, 54779 }, + { 0x1D78, 54782 }, + { 0x10FC, 54786 }, + { 0x02BD, 54790 }, + { 0x02C1, 54794 }, + { 0x02C8, 54799 }, + { 0x02E9, 54803 }, + { 0x570C, 54808 }, + { 0x5711, 54814 }, + { 0x5716, 54821 }, + { 0x02BC, 54827 }, + { 0x02C6, 54830 }, + { 0x02E5, 54834 }, + { 0x5708, 54839 }, + { 0x570D, 54845 }, + { 0x5712, 54852 }, + { 0x02D0, 54858 }, + { 0x02ED, 54862 }, + { 0x268B, 54865 }, + { 0x268A, 54868 }, + { 0x9300, 54871 }, + { 0x22B8, 54874 }, + { 0x228C, 54875 }, + { 0x228E, 54876 }, + { 0x228D, 54878 }, + { 0x206E, 54880 }, + { 0x24FF, 54883 }, + { 0x24EB, 54887 }, + { 0x24EC, 54891 }, + { 0x24F4, 54895 }, + { 0x24EF, 54899 }, + { 0x24F0, 54903 }, + { 0x24F2, 54907 }, + { 0x24EE, 54911 }, + { 0x24F3, 54915 }, + { 0x24ED, 54919 }, + { 0x24F1, 54923 }, + { 0x00A0, 54927 }, + { 0x22B6, 54929 }, + { 0x2626, 54931 }, + { 0x272D, 54933 }, + { 0x2719, 54936 }, + { 0x271F, 54939 }, + { 0x269D, 54942 }, + { 0x203E, 54945 }, + { 0x2225, 54946 }, + { 0x2AF3, 54948 }, + { 0x2AF2, 54952 }, + { 0x5876, 54956 }, + { 0x5877, 54959 }, + { 0x5875, 54963 }, + { 0x585D, 54967 }, + { 0x5860, 54970 }, + { 0x585E, 54973 }, + { 0x5861, 54976 }, + { 0x585F, 54979 }, + { 0x584E, 54982 }, + { 0x5844, 54985 }, + { 0x584A, 54988 }, + { 0x5866, 54991 }, + { 0x5864, 54994 }, + { 0x5842, 54997 }, + { 0x585C, 55000 }, + { 0x5846, 55003 }, + { 0x5840, 55006 }, + { 0x5859, 55009 }, + { 0x584F, 55012 }, + { 0x584B, 55015 }, + { 0x584C, 55018 }, + { 0x5862, 55021 }, + { 0x5858, 55024 }, + { 0x585B, 55027 }, + { 0x5848, 55030 }, + { 0x5853, 55033 }, + { 0x5863, 55036 }, + { 0x5857, 55039 }, + { 0x5855, 55042 }, + { 0x5845, 55045 }, + { 0x586B, 55048 }, + { 0x5852, 55051 }, + { 0x5865, 55054 }, + { 0x5841, 55057 }, + { 0x5843, 55060 }, + { 0x586C, 55063 }, + { 0x5847, 55066 }, + { 0x584D, 55069 }, + { 0x585A, 55072 }, + { 0x5849, 55075 }, + { 0x5850, 55078 }, + { 0x5869, 55081 }, + { 0x5854, 55084 }, + { 0x5851, 55087 }, + { 0x586A, 55090 }, + { 0x5856, 55093 }, + { 0x586F, 55097 }, + { 0x586D, 55101 }, + { 0x5870, 55105 }, + { 0x586E, 55109 }, + { 0x5873, 55113 }, + { 0x5874, 55116 }, + { 0x5871, 55120 }, + { 0x5867, 55124 }, + { 0x5868, 55128 }, + { 0x5872, 55132 }, + { 0x71F7, 55136 }, + { 0x71F1, 55141 }, + { 0x71DA, 55145 }, + { 0x71EC, 55149 }, + { 0x71E0, 55153 }, + { 0x71ED, 55157 }, + { 0x71DF, 55161 }, + { 0x71DC, 55165 }, + { 0x71E4, 55169 }, + { 0x71EF, 55173 }, + { 0x71EA, 55177 }, + { 0x71E9, 55181 }, + { 0x71F6, 55185 }, + { 0x71E8, 55189 }, + { 0x71F3, 55193 }, + { 0x71FC, 55197 }, + { 0x71D9, 55202 }, + { 0x71EB, 55206 }, + { 0x71D4, 55211 }, + { 0x71EE, 55215 }, + { 0x71F8, 55219 }, + { 0x71F2, 55223 }, + { 0x71E5, 55228 }, + { 0x71FB, 55232 }, + { 0x71D8, 55237 }, + { 0x71F0, 55241 }, + { 0x71D5, 55245 }, + { 0x71E6, 55249 }, + { 0x71E3, 55253 }, + { 0x71F9, 55257 }, + { 0x71D6, 55261 }, + { 0x71D1, 55265 }, + { 0x71DB, 55270 }, + { 0x71E7, 55274 }, + { 0x71D3, 55278 }, + { 0x71DE, 55282 }, + { 0x71F4, 55286 }, + { 0x71F5, 55290 }, + { 0x71D7, 55294 }, + { 0x71DD, 55298 }, + { 0x71FA, 55302 }, + { 0x71D2, 55306 }, + { 0x71E1, 55311 }, + { 0x71E2, 55315 }, + { 0x71FD, 55320 }, + { 0x71D0, 55326 }, + { 0x272F, 55330 }, + { 0x2316, 55332 }, + { 0x227A, 55334 }, + { 0x227C, 55335 }, + { 0x227E, 55339 }, + { 0x22E8, 55343 }, + { 0x2AB5, 55348 }, + { 0x2AB9, 55353 }, + { 0x2AB7, 55359 }, + { 0x2AB3, 55364 }, + { 0x2AB1, 55368 }, + { 0x2AAF, 55374 }, + { 0x22B0, 55379 }, + { 0x2397, 55382 }, + { 0x214A, 55384 }, + { 0x2596, 55386 }, + { 0x2597, 55389 }, + { 0x2598, 55392 }, + { 0x2599, 55395 }, + { 0x259A, 55404 }, + { 0x259B, 55410 }, + { 0x259C, 55419 }, + { 0x259D, 55428 }, + { 0x259E, 55431 }, + { 0x259F, 55437 }, + { 0x003F, 55446 }, + { 0x2048, 55448 }, + { 0x26BB, 55451 }, + { 0x267C, 55452 }, + { 0x211F, 55455 }, + { 0x2310, 55456 }, + { 0x29A3, 55459 }, + { 0x29A5, 55461 }, + { 0x29B0, 55465 }, + { 0x2035, 55468 }, + { 0x223D, 55470 }, + { 0x22CD, 55472 }, + { 0x2036, 55475 }, + { 0x301D, 55478 }, + { 0x2AED, 55483 }, + { 0x2E11, 55488 }, + { 0x2037, 55491 }, + { 0x204B, 55494 }, + { 0x2619, 55497 }, + { 0x2E2E, 55502 }, + { 0x204F, 55505 }, + { 0x2143, 55507 }, + { 0x264F, 55511 }, + { 0x2730, 55512 }, + { 0x271E, 55515 }, + { 0x274D, 55519 }, + { 0x2618, 55522 }, + { 0x5673, 55523 }, + { 0x2263, 55525 }, + { 0x227B, 55528 }, + { 0x227D, 55529 }, + { 0x227F, 55533 }, + { 0x22E9, 55537 }, + { 0x2AB6, 55542 }, + { 0x2ABA, 55547 }, + { 0x2AB8, 55553 }, + { 0x2AB4, 55558 }, + { 0x2AB2, 55562 }, + { 0x2AB0, 55568 }, + { 0x22B1, 55573 }, + { 0x2283, 55576 }, + { 0x2287, 55578 }, + { 0x2AC4, 55583 }, + { 0x228B, 55591 }, + { 0x2ACC, 55597 }, + { 0x2AC8, 55603 }, + { 0x2ACA, 55608 }, + { 0x2AC6, 55614 }, + { 0x2ABE, 55619 }, + { 0x2AC0, 55622 }, + { 0x2AC2, 55627 }, + { 0x2AD4, 55632 }, + { 0x2AD6, 55635 }, + { 0x297B, 55638 }, + { 0x2AD8, 55642 }, + { 0x2AD7, 55650 }, + { 0x27C9, 55653 }, + { 0x232F, 55656 }, + { 0x1772, 55657 }, + { 0x1773, 55661 }, + { 0x1760, 55665 }, + { 0x1761, 55668 }, + { 0x1762, 55671 }, + { 0x176A, 55674 }, + { 0x1767, 55677 }, + { 0x1764, 55680 }, + { 0x1763, 55683 }, + { 0x176E, 55686 }, + { 0x176B, 55689 }, + { 0x1768, 55692 }, + { 0x1769, 55695 }, + { 0x1770, 55698 }, + { 0x1766, 55701 }, + { 0x176F, 55704 }, + { 0x176C, 55707 }, + { 0x1765, 55710 }, + { 0x2D30, 55713 }, + { 0x2D49, 55716 }, + { 0x2D53, 55719 }, + { 0x2D44, 55722 }, + { 0x2D31, 55725 }, + { 0x2D37, 55728 }, + { 0x2D3C, 55731 }, + { 0x2D33, 55734 }, + { 0x2D40, 55737 }, + { 0x2D36, 55740 }, + { 0x2D3D, 55743 }, + { 0x2D4D, 55746 }, + { 0x2D4E, 55749 }, + { 0x2D4F, 55752 }, + { 0x2D52, 55755 }, + { 0x2D47, 55758 }, + { 0x2D54, 55761 }, + { 0x2D59, 55764 }, + { 0x2D5C, 55767 }, + { 0x2D60, 55770 }, + { 0x2D61, 55773 }, + { 0x2D62, 55776 }, + { 0x2D63, 55779 }, + { 0x2D3B, 55782 }, + { 0x2D58, 55785 }, + { 0x2D32, 55789 }, + { 0x2D5E, 55792 }, + { 0x2D39, 55795 }, + { 0x2D38, 55798 }, + { 0x2D56, 55801 }, + { 0x2D43, 55804 }, + { 0x2D45, 55807 }, + { 0x2D55, 55810 }, + { 0x2D5B, 55813 }, + { 0x2D5A, 55816 }, + { 0x2D5D, 55819 }, + { 0x2D5F, 55822 }, + { 0x2D4A, 55825 }, + { 0x2D65, 55828 }, + { 0x2D3A, 55831 }, + { 0x2D34, 55834 }, + { 0x2D3F, 55837 }, + { 0x2D41, 55840 }, + { 0x2D35, 55845 }, + { 0x2D42, 55850 }, + { 0x2D3E, 55854 }, + { 0x2D48, 55858 }, + { 0x2D57, 55862 }, + { 0x2D50, 55866 }, + { 0x2D46, 55870 }, + { 0x2D51, 55874 }, + { 0x2D4C, 55878 }, + { 0x2D4B, 55882 }, + { 0x2D64, 55886 }, + { 0x2D6F, 55890 }, + { 0x204A, 55895 }, + { 0x29CA, 55898 }, + { 0x29CD, 55902 }, + { 0x29CB, 55907 }, + { 0x205D, 55910 }, + { 0x739F, 55911 }, + { 0x739B, 55914 }, + { 0x739C, 55917 }, + { 0x7385, 55920 }, + { 0x7394, 55923 }, + { 0x739A, 55926 }, + { 0x7386, 55929 }, + { 0x7391, 55932 }, + { 0x7393, 55935 }, + { 0x738B, 55938 }, + { 0x7383, 55941 }, + { 0x738E, 55944 }, + { 0x7390, 55947 }, + { 0x739D, 55950 }, + { 0x7389, 55953 }, + { 0x738A, 55956 }, + { 0x7380, 55959 }, + { 0x7381, 55962 }, + { 0x738F, 55965 }, + { 0x7388, 55968 }, + { 0x7396, 55971 }, + { 0x7395, 55974 }, + { 0x738C, 55977 }, + { 0x7387, 55980 }, + { 0x7384, 55983 }, + { 0x7382, 55986 }, + { 0x7399, 55989 }, + { 0x738D, 55992 }, + { 0x7397, 55995 }, + { 0x7392, 55998 }, + { 0x7398, 56001 }, + { 0x2602, 56004 }, + { 0x2614, 56005 }, + { 0x203F, 56009 }, + { 0x2123, 56010 }, + { 0x27CA, 56011 }, + { 0x29D0, 56016 }, + { 0x2AE4, 56021 }, + { 0x2AE2, 56026 }, + { 0x205E, 56031 }, + { 0x3031, 56034 }, + { 0x3035, 56038 }, + { 0x3033, 56044 }, + { 0x3032, 56050 }, + { 0x3034, 56057 }, + { 0x007C, 56066 }, + { 0x2AEF, 56068 }, + { 0x2AF0, 56073 }, + { 0x237F, 56078 }, + { 0x23D0, 56083 }, + { 0x26A8, 56086 }, + { 0x2E2F, 56091 }, + { 0x299A, 56093 }, + { 0x22EE, 56096 }, + { 0x303B, 56098 }, + { 0x2317, 56102 }, + { 0x2101, 56104 }, + { 0x0026, 56108 }, + { 0x260A, 56109 }, + { 0x22A6, 56111 }, + { 0x2623, 56112 }, + { 0x902F, 56114 }, + { 0x900E, 56118 }, + { 0x9085, 56123 }, + { 0x9046, 56127 }, + { 0x901A, 56132 }, + { 0x9040, 56137 }, + { 0x9079, 56141 }, + { 0x9030, 56147 }, + { 0x907D, 56151 }, + { 0x907C, 56156 }, + { 0x909C, 56161 }, + { 0x909E, 56166 }, + { 0x909A, 56171 }, + { 0x90A1, 56177 }, + { 0x909F, 56183 }, + { 0x909D, 56188 }, + { 0x909B, 56193 }, + { 0x90A0, 56198 }, + { 0x9033, 56203 }, + { 0x900D, 56209 }, + { 0x9097, 56214 }, + { 0x90C8, 56218 }, + { 0x90C9, 56223 }, + { 0x90CA, 56228 }, + { 0x9086, 56233 }, + { 0x9080, 56237 }, + { 0x902E, 56242 }, + { 0x9048, 56246 }, + { 0x9004, 56251 }, + { 0x9003, 56256 }, + { 0x9000, 56261 }, + { 0x9025, 56265 }, + { 0x9066, 56269 }, + { 0x902D, 56273 }, + { 0x9078, 56277 }, + { 0x9014, 56282 }, + { 0x9019, 56286 }, + { 0x906A, 56290 }, + { 0x9001, 56295 }, + { 0x90D0, 56299 }, + { 0x90D2, 56306 }, + { 0x90D3, 56313 }, + { 0x90D1, 56320 }, + { 0x90CE, 56327 }, + { 0x90CF, 56332 }, + { 0x9060, 56337 }, + { 0x9074, 56342 }, + { 0x90C5, 56347 }, + { 0x90CB, 56354 }, + { 0x90BC, 56361 }, + { 0x90C7, 56367 }, + { 0x90C3, 56372 }, + { 0x90C4, 56379 }, + { 0x90C6, 56386 }, + { 0x90BE, 56393 }, + { 0x9034, 56400 }, + { 0x90B9, 56405 }, + { 0x90BD, 56412 }, + { 0x90BF, 56418 }, + { 0x90C2, 56424 }, + { 0x90C1, 56431 }, + { 0x90BA, 56438 }, + { 0x90C0, 56444 }, + { 0x90BB, 56450 }, + { 0x90CC, 56456 }, + { 0x90D8, 56462 }, + { 0x90D9, 56467 }, + { 0x908F, 56472 }, + { 0x90F5, 56478 }, + { 0x9016, 56484 }, + { 0x9091, 56489 }, + { 0x9090, 56495 }, + { 0x90AC, 56501 }, + { 0x9037, 56507 }, + { 0x9024, 56512 }, + { 0x907F, 56516 }, + { 0x90F4, 56521 }, + { 0x908B, 56526 }, + { 0x908A, 56532 }, + { 0x908C, 56538 }, + { 0x908E, 56544 }, + { 0x908D, 56550 }, + { 0x9057, 56556 }, + { 0x9047, 56561 }, + { 0x9015, 56566 }, + { 0x905B, 56571 }, + { 0x9020, 56575 }, + { 0x9059, 56580 }, + { 0x9026, 56585 }, + { 0x9017, 56590 }, + { 0x9029, 56594 }, + { 0x9069, 56598 }, + { 0x90E8, 56603 }, + { 0x900F, 56607 }, + { 0x9087, 56611 }, + { 0x9058, 56615 }, + { 0x9006, 56620 }, + { 0x9005, 56625 }, + { 0x90D4, 56630 }, + { 0x90D6, 56637 }, + { 0x90D7, 56644 }, + { 0x90D5, 56651 }, + { 0x90CD, 56658 }, + { 0x9050, 56663 }, + { 0x90EC, 56667 }, + { 0x90EB, 56672 }, + { 0x90ED, 56677 }, + { 0x90EF, 56682 }, + { 0x90E9, 56687 }, + { 0x90EE, 56692 }, + { 0x90EA, 56697 }, + { 0x9056, 56702 }, + { 0x9099, 56706 }, + { 0x9055, 56710 }, + { 0x90B6, 56714 }, + { 0x903F, 56721 }, + { 0x904F, 56725 }, + { 0x90F3, 56731 }, + { 0x90F1, 56737 }, + { 0x901B, 56743 }, + { 0x9089, 56748 }, + { 0x9083, 56752 }, + { 0x9082, 56757 }, + { 0x9081, 56762 }, + { 0x9061, 56767 }, + { 0x905D, 56771 }, + { 0x9041, 56775 }, + { 0x9049, 56779 }, + { 0x903C, 56783 }, + { 0x907E, 56787 }, + { 0x901F, 56791 }, + { 0x9065, 56796 }, + { 0x902B, 56801 }, + { 0x902A, 56807 }, + { 0x9013, 56812 }, + { 0x9031, 56816 }, + { 0x9027, 56820 }, + { 0x9021, 56824 }, + { 0x9053, 56829 }, + { 0x9084, 56833 }, + { 0x9022, 56838 }, + { 0x9023, 56843 }, + { 0x9018, 56847 }, + { 0x9067, 56851 }, + { 0x903B, 56856 }, + { 0x90DA, 56861 }, + { 0x90DB, 56867 }, + { 0x90DC, 56873 }, + { 0x90DD, 56878 }, + { 0x9092, 56883 }, + { 0x9095, 56887 }, + { 0x9094, 56893 }, + { 0x9093, 56900 }, + { 0x90E6, 56907 }, + { 0x9068, 56912 }, + { 0x90B7, 56916 }, + { 0x9007, 56920 }, + { 0x903A, 56924 }, + { 0x9042, 56928 }, + { 0x904A, 56933 }, + { 0x900C, 56937 }, + { 0x90A3, 56941 }, + { 0x90A5, 56948 }, + { 0x90B1, 56955 }, + { 0x90A2, 56961 }, + { 0x90A6, 56967 }, + { 0x90AA, 56973 }, + { 0x90AB, 56979 }, + { 0x90B3, 56985 }, + { 0x90A4, 56992 }, + { 0x90A8, 56998 }, + { 0x90A9, 57004 }, + { 0x90A7, 57011 }, + { 0x90B2, 57016 }, + { 0x901E, 57022 }, + { 0x9038, 57026 }, + { 0x904D, 57030 }, + { 0x901D, 57035 }, + { 0x90E2, 57039 }, + { 0x90E3, 57044 }, + { 0x90E4, 57050 }, + { 0x90E5, 57056 }, + { 0x90DE, 57062 }, + { 0x90DF, 57067 }, + { 0x90E0, 57073 }, + { 0x90E1, 57079 }, + { 0x9088, 57085 }, + { 0x9063, 57089 }, + { 0x9043, 57094 }, + { 0x9036, 57099 }, + { 0x90E7, 57104 }, + { 0x907B, 57109 }, + { 0x90B0, 57113 }, + { 0x90AF, 57118 }, + { 0x90AE, 57123 }, + { 0x9035, 57128 }, + { 0x907A, 57132 }, + { 0x9010, 57136 }, + { 0x904E, 57140 }, + { 0x90F2, 57146 }, + { 0x90F0, 57152 }, + { 0x901C, 57158 }, + { 0x9032, 57163 }, + { 0x9075, 57167 }, + { 0x902C, 57172 }, + { 0x9039, 57177 }, + { 0x905A, 57181 }, + { 0x9008, 57186 }, + { 0x9096, 57190 }, + { 0x900A, 57194 }, + { 0x900B, 57198 }, + { 0x905C, 57203 }, + { 0x90AD, 57207 }, + { 0x9052, 57213 }, + { 0x9011, 57219 }, + { 0x9051, 57223 }, + { 0x9012, 57228 }, + { 0x9064, 57233 }, + { 0x90B4, 57237 }, + { 0x90B5, 57243 }, + { 0x9098, 57249 }, + { 0x90B8, 57253 }, + { 0x905F, 57257 }, + { 0x903D, 57262 }, + { 0x9009, 57267 }, + { 0x905E, 57271 }, + { 0x903E, 57276 }, + { 0x9002, 57281 }, + { 0x9076, 57285 }, + { 0x9077, 57290 }, + { 0x9028, 57295 }, + { 0x9045, 57299 }, + { 0x9044, 57303 }, + { 0x9073, 57307 }, + { 0x9072, 57311 }, + { 0x906D, 57315 }, + { 0x9070, 57319 }, + { 0x9062, 57323 }, + { 0x904C, 57327 }, + { 0x9054, 57331 }, + { 0x904B, 57335 }, + { 0x906C, 57339 }, + { 0x9071, 57343 }, + { 0x906B, 57347 }, + { 0x906E, 57351 }, + { 0x906F, 57355 }, + { 0x2651, 57359 }, + { 0x2040, 57360 }, + { 0x21B7, 57362 }, + { 0x21BB, 57366 }, + { 0x2941, 57370 }, + { 0x27F3, 57374 }, + { 0x2232, 57378 }, + { 0x2231, 57381 }, + { 0x033D, 57383 }, + { 0x0353, 57386 }, + { 0x1DD0, 57389 }, + { 0x031D, 57392 }, + { 0x1DD1, 57396 }, + { 0x1DD2, 57399 }, + { 0x0307, 57402 }, + { 0x0358, 57405 }, + { 0x0323, 57409 }, + { 0x0332, 57412 }, + { 0x034A, 57415 }, + { 0x031E, 57419 }, + { 0x20DC, 57423 }, + { 0x0309, 57427 }, + { 0x031B, 57430 }, + { 0x0351, 57432 }, + { 0x031C, 57437 }, + { 0x0318, 57442 }, + { 0x031A, 57446 }, + { 0x0349, 57450 }, + { 0x20D6, 57454 }, + { 0x20EE, 57458 }, + { 0x20E1, 57462 }, + { 0x034D, 57467 }, + { 0x20D0, 57472 }, + { 0x1DFE, 57476 }, + { 0x0354, 57480 }, + { 0x20EB, 57484 }, + { 0x0336, 57489 }, + { 0x0338, 57493 }, + { 0x20D2, 57497 }, + { 0x031F, 57502 }, + { 0x030A, 57506 }, + { 0x0325, 57509 }, + { 0x20D8, 57512 }, + { 0x20E9, 57515 }, + { 0x0341, 57519 }, + { 0x0301, 57523 }, + { 0x0317, 57526 }, + { 0x0306, 57530 }, + { 0x032E, 57532 }, + { 0x030C, 57535 }, + { 0x032C, 57537 }, + { 0x0313, 57540 }, + { 0x0315, 57543 }, + { 0x0326, 57547 }, + { 0x0340, 57550 }, + { 0x0300, 57554 }, + { 0x0316, 57557 }, + { 0x0343, 57561 }, + { 0x9242, 57564 }, + { 0x9244, 57568 }, + { 0x9243, 57572 }, + { 0x0344, 57576 }, + { 0x0342, 57580 }, + { 0x0345, 57583 }, + { 0x0363, 57586 }, + { 0x0368, 57591 }, + { 0x1DD7, 57596 }, + { 0x0369, 57602 }, + { 0x0364, 57607 }, + { 0x1DDA, 57612 }, + { 0x036A, 57617 }, + { 0x0365, 57622 }, + { 0x1DDC, 57627 }, + { 0x1DDD, 57632 }, + { 0x036B, 57637 }, + { 0x1DE0, 57642 }, + { 0x0366, 57647 }, + { 0x036C, 57652 }, + { 0x1DCA, 57657 }, + { 0x1DE3, 57663 }, + { 0x1DE4, 57669 }, + { 0x036D, 57674 }, + { 0x0367, 57679 }, + { 0x036E, 57684 }, + { 0x036F, 57689 }, + { 0x1DE6, 57694 }, + { 0x1DD4, 57699 }, + { 0x1DD5, 57704 }, + { 0x1DD6, 57709 }, + { 0x1DD9, 57714 }, + { 0x1DE5, 57719 }, + { 0x1DD8, 57725 }, + { 0x1DD3, 57731 }, + { 0x1DDB, 57739 }, + { 0x1DDE, 57745 }, + { 0x1DDF, 57751 }, + { 0x1DE1, 57757 }, + { 0x1DE2, 57763 }, + { 0x0320, 57769 }, + { 0x0357, 57773 }, + { 0x0339, 57778 }, + { 0x0319, 57783 }, + { 0x20D7, 57787 }, + { 0x20EF, 57791 }, + { 0x20D1, 57795 }, + { 0x0356, 57799 }, + { 0x1DFF, 57806 }, + { 0x0350, 57813 }, + { 0x0355, 57817 }, + { 0x0335, 57821 }, + { 0x0337, 57825 }, + { 0x20D3, 57829 }, + { 0x1DC2, 57834 }, + { 0x20DB, 57837 }, + { 0x0303, 57841 }, + { 0x0330, 57843 }, + { 0x0334, 57846 }, + { 0x034C, 57849 }, + { 0x0346, 57854 }, + { 0x032A, 57857 }, + { 0x1DC1, 57860 }, + { 0x1DC0, 57864 }, + { 0x0333, 57868 }, + { 0x035A, 57872 }, + { 0x030B, 57876 }, + { 0x035D, 57880 }, + { 0x035C, 57883 }, + { 0x030F, 57887 }, + { 0x0360, 57891 }, + { 0x6E22, 57894 }, + { 0x6E23, 57899 }, + { 0x035E, 57904 }, + { 0x035F, 57907 }, + { 0x0361, 57911 }, + { 0x033F, 57915 }, + { 0x030E, 57918 }, + { 0x0348, 57923 }, + { 0x20E6, 57928 }, + { 0x1DCD, 57933 }, + { 0x0362, 57937 }, + { 0x0347, 57942 }, + { 0x0304, 57946 }, + { 0x6E24, 57948 }, + { 0x0331, 57952 }, + { 0x6E25, 57955 }, + { 0x0328, 57959 }, + { 0x1DCE, 57961 }, + { 0x033B, 57964 }, + { 0x20E8, 57967 }, + { 0x0312, 57970 }, + { 0x035B, 57974 }, + { 0x1DCF, 57977 }, + { 0x20E7, 57980 }, + { 0x0327, 57983 }, + { 0x0352, 57985 }, + { 0x20E5, 57987 }, + { 0x033C, 57991 }, + { 0x034E, 57994 }, + { 0x20F0, 57998 }, + { 0x0359, 58001 }, + { 0x5670, 58004 }, + { 0x0485, 58009 }, + { 0x0486, 58013 }, + { 0x0483, 58017 }, + { 0x566F, 58020 }, + { 0x567C, 58023 }, + { 0x2DF6, 58026 }, + { 0x2DEA, 58030 }, + { 0x2DE0, 58034 }, + { 0x2DE3, 58038 }, + { 0x2DE7, 58042 }, + { 0x2DE8, 58046 }, + { 0x2DE9, 58050 }, + { 0x2DEC, 58054 }, + { 0x2DED, 58058 }, + { 0x2DEF, 58062 }, + { 0x2DF7, 58066 }, + { 0x2DE6, 58070 }, + { 0x2DEB, 58074 }, + { 0x2DEE, 58078 }, + { 0x2DE1, 58082 }, + { 0x2DFB, 58086 }, + { 0x2DE5, 58090 }, + { 0x2DFE, 58094 }, + { 0x2DF1, 58099 }, + { 0x2DE2, 58103 }, + { 0x2DF2, 58107 }, + { 0x2DF0, 58111 }, + { 0x2DFA, 58115 }, + { 0x2DE4, 58119 }, + { 0x2DF4, 58123 }, + { 0x2DF8, 58127 }, + { 0x2DF5, 58131 }, + { 0x2DF3, 58135 }, + { 0x2DFD, 58139 }, + { 0x2DFC, 58144 }, + { 0x2DFF, 58149 }, + { 0x2DF9, 58155 }, + { 0x5671, 58160 }, + { 0x0488, 58165 }, + { 0x567D, 58170 }, + { 0x0489, 58173 }, + { 0x0487, 58177 }, + { 0x5672, 58180 }, + { 0x0484, 58185 }, + { 0x034F, 58188 }, + { 0x0311, 58191 }, + { 0x032F, 58194 }, + { 0x033A, 58198 }, + { 0x032B, 58202 }, + { 0x6E20, 58207 }, + { 0x6E21, 58211 }, + { 0x0305, 58215 }, + { 0x0314, 58217 }, + { 0x030D, 58221 }, + { 0x0329, 58225 }, + { 0x033E, 58229 }, + { 0x20D9, 58232 }, + { 0x20D5, 58236 }, + { 0x0308, 58240 }, + { 0x0324, 58242 }, + { 0x20DD, 58245 }, + { 0x20E0, 58248 }, + { 0x20E3, 58252 }, + { 0x20E2, 58255 }, + { 0x20DE, 58258 }, + { 0x20E4, 58261 }, + { 0x20DF, 58266 }, + { 0x20EA, 58269 }, + { 0x20ED, 58273 }, + { 0x0322, 58279 }, + { 0x0302, 58283 }, + { 0x032D, 58286 }, + { 0x6E26, 58290 }, + { 0x034B, 58293 }, + { 0x20EC, 58296 }, + { 0x1DC3, 58302 }, + { 0x0310, 58305 }, + { 0x0321, 58307 }, + { 0x1DC7, 58311 }, + { 0x1DCB, 58313 }, + { 0x1DC5, 58315 }, + { 0x1DC4, 58317 }, + { 0x1DCC, 58319 }, + { 0x1DC6, 58321 }, + { 0x20DA, 58323 }, + { 0x20D4, 58327 }, + { 0x1DC9, 58331 }, + { 0x1DC8, 58333 }, + { 0x3099, 58335 }, + { 0x309A, 58340 }, + { 0x2A6D, 58345 }, + { 0x00A9, 58349 }, + { 0x8000, 58351 }, + { 0x8001, 58354 }, + { 0x8004, 58359 }, + { 0x8002, 58364 }, + { 0x8005, 58369 }, + { 0x8008, 58374 }, + { 0x8003, 58379 }, + { 0x8007, 58385 }, + { 0x8006, 58390 }, + { 0x808A, 58396 }, + { 0x808C, 58399 }, + { 0x808B, 58407 }, + { 0x813F, 58412 }, + { 0x8140, 58415 }, + { 0x830B, 58419 }, + { 0x830D, 58422 }, + { 0x830C, 58427 }, + { 0x8310, 58431 }, + { 0x830E, 58441 }, + { 0x830F, 58452 }, + { 0x8009, 58460 }, + { 0x800A, 58463 }, + { 0x8015, 58466 }, + { 0x8014, 58470 }, + { 0x800F, 58479 }, + { 0x800D, 58484 }, + { 0x8010, 58489 }, + { 0x800B, 58495 }, + { 0x800C, 58500 }, + { 0x800E, 58506 }, + { 0x8011, 58512 }, + { 0x8012, 58517 }, + { 0x8013, 58522 }, + { 0x801C, 58527 }, + { 0x801D, 58530 }, + { 0x801E, 58533 }, + { 0x801F, 58538 }, + { 0x8020, 58545 }, + { 0x8021, 58548 }, + { 0x8024, 58553 }, + { 0x8026, 58558 }, + { 0x8027, 58563 }, + { 0x8028, 58568 }, + { 0x8022, 58573 }, + { 0x8023, 58578 }, + { 0x8025, 58583 }, + { 0x802D, 58588 }, + { 0x802E, 58591 }, + { 0x8031, 58596 }, + { 0x8030, 58602 }, + { 0x802F, 58611 }, + { 0x8040, 58616 }, + { 0x8049, 58619 }, + { 0x804A, 58622 }, + { 0x804B, 58627 }, + { 0x804C, 58632 }, + { 0x804D, 58638 }, + { 0x804E, 58641 }, + { 0x804F, 58647 }, + { 0x8050, 58653 }, + { 0x8055, 58658 }, + { 0x8072, 58661 }, + { 0x807A, 58664 }, + { 0x807C, 58667 }, + { 0x807B, 58671 }, + { 0x807D, 58676 }, + { 0x808D, 58680 }, + { 0x808E, 58683 }, + { 0x8093, 58692 }, + { 0x8090, 58697 }, + { 0x808F, 58702 }, + { 0x8091, 58707 }, + { 0x8092, 58712 }, + { 0x8096, 58717 }, + { 0x8097, 58720 }, + { 0x809A, 58723 }, + { 0x8098, 58728 }, + { 0x8099, 58733 }, + { 0x809D, 58739 }, + { 0x809B, 58743 }, + { 0x809C, 58748 }, + { 0x80B5, 58753 }, + { 0x80B6, 58756 }, + { 0x8100, 58760 }, + { 0x8101, 58763 }, + { 0x8102, 58768 }, + { 0x8103, 58773 }, + { 0x8116, 58778 }, + { 0x8117, 58781 }, + { 0x8129, 58786 }, + { 0x812B, 58789 }, + { 0x812A, 58793 }, + { 0x812D, 58797 }, + { 0x8136, 58800 }, + { 0x812E, 58805 }, + { 0x8130, 58810 }, + { 0x8132, 58815 }, + { 0x8133, 58820 }, + { 0x8134, 58825 }, + { 0x8135, 58830 }, + { 0x812F, 58835 }, + { 0x8131, 58840 }, + { 0x8137, 58845 }, + { 0x8141, 58848 }, + { 0x8145, 58851 }, + { 0x814B, 58854 }, + { 0x814C, 58857 }, + { 0x814E, 58863 }, + { 0x814F, 58866 }, + { 0x8152, 58871 }, + { 0x8150, 58875 }, + { 0x8151, 58880 }, + { 0x8154, 58885 }, + { 0x8155, 58888 }, + { 0x8157, 58891 }, + { 0x8158, 58894 }, + { 0x8187, 58899 }, + { 0x8159, 58904 }, + { 0x815A, 58909 }, + { 0x815F, 58916 }, + { 0x8162, 58921 }, + { 0x8167, 58926 }, + { 0x816B, 58931 }, + { 0x816E, 58936 }, + { 0x8170, 58941 }, + { 0x8172, 58946 }, + { 0x8173, 58951 }, + { 0x8174, 58956 }, + { 0x8175, 58961 }, + { 0x8176, 58968 }, + { 0x8177, 58975 }, + { 0x8178, 58982 }, + { 0x8179, 58987 }, + { 0x817A, 58994 }, + { 0x817C, 58999 }, + { 0x817D, 59004 }, + { 0x817E, 59009 }, + { 0x8188, 59014 }, + { 0x8189, 59019 }, + { 0x818C, 59024 }, + { 0x815C, 59029 }, + { 0x815E, 59034 }, + { 0x8163, 59039 }, + { 0x8165, 59044 }, + { 0x8166, 59049 }, + { 0x816D, 59058 }, + { 0x816F, 59063 }, + { 0x8171, 59068 }, + { 0x817B, 59073 }, + { 0x817F, 59078 }, + { 0x8180, 59083 }, + { 0x8181, 59088 }, + { 0x8183, 59093 }, + { 0x8184, 59098 }, + { 0x8186, 59103 }, + { 0x818B, 59108 }, + { 0x815B, 59113 }, + { 0x8161, 59118 }, + { 0x8164, 59123 }, + { 0x8168, 59129 }, + { 0x8169, 59134 }, + { 0x816A, 59141 }, + { 0x816C, 59148 }, + { 0x8182, 59153 }, + { 0x818A, 59158 }, + { 0x815D, 59165 }, + { 0x8160, 59170 }, + { 0x8185, 59175 }, + { 0x81A0, 59180 }, + { 0x81A2, 59183 }, + { 0x81A3, 59188 }, + { 0x81A1, 59193 }, + { 0x81AA, 59198 }, + { 0x81AB, 59201 }, + { 0x81B7, 59213 }, + { 0x81F7, 59216 }, + { 0x81FB, 59219 }, + { 0x81FC, 59222 }, + { 0x8220, 59227 }, + { 0x8222, 59230 }, + { 0x8221, 59234 }, + { 0x8228, 59239 }, + { 0x822A, 59242 }, + { 0x822C, 59245 }, + { 0x822D, 59248 }, + { 0x823E, 59253 }, + { 0x8248, 59256 }, + { 0x8249, 59259 }, + { 0x824A, 59264 }, + { 0x824B, 59269 }, + { 0x824C, 59273 }, + { 0x824D, 59276 }, + { 0x8261, 59281 }, + { 0x827A, 59284 }, + { 0x827F, 59287 }, + { 0x8280, 59290 }, + { 0x8284, 59295 }, + { 0x8285, 59300 }, + { 0x8287, 59305 }, + { 0x8281, 59310 }, + { 0x8282, 59315 }, + { 0x8283, 59320 }, + { 0x8286, 59325 }, + { 0x8288, 59330 }, + { 0x8289, 59335 }, + { 0x828F, 59340 }, + { 0x8291, 59343 }, + { 0x8292, 59346 }, + { 0x8293, 59349 }, + { 0x82DB, 59352 }, + { 0x82DC, 59355 }, + { 0x82E2, 59359 }, + { 0x82E3, 59362 }, + { 0x82EB, 59367 }, + { 0x82EF, 59370 }, + { 0x82ED, 59374 }, + { 0x82EE, 59379 }, + { 0x82EC, 59384 }, + { 0x82FC, 59388 }, + { 0x82FD, 59391 }, + { 0x82FE, 59395 }, + { 0x82FF, 59398 }, + { 0x8305, 59402 }, + { 0x8311, 59405 }, + { 0x8312, 59408 }, + { 0x8313, 59411 }, + { 0x8319, 59414 }, + { 0x8317, 59418 }, + { 0x8318, 59427 }, + { 0x8316, 59437 }, + { 0x8315, 59442 }, + { 0x8314, 59447 }, + { 0x831A, 59451 }, + { 0x831B, 59455 }, + { 0x831D, 59461 }, + { 0x8321, 59464 }, + { 0x831F, 59469 }, + { 0x8320, 59476 }, + { 0x831E, 59481 }, + { 0x8326, 59486 }, + { 0x8327, 59489 }, + { 0x8328, 59493 }, + { 0x832A, 59496 }, + { 0x8329, 59500 }, + { 0x835D, 59505 }, + { 0x835E, 59508 }, + { 0x835F, 59512 }, + { 0x8363, 59518 }, + { 0x8364, 59521 }, + { 0x836A, 59526 }, + { 0x8016, 59529 }, + { 0x8019, 59532 }, + { 0x8018, 59539 }, + { 0x801A, 59545 }, + { 0x801B, 59550 }, + { 0x8017, 59555 }, + { 0x8038, 59560 }, + { 0x803A, 59563 }, + { 0x803C, 59568 }, + { 0x803D, 59575 }, + { 0x803B, 59588 }, + { 0x8039, 59600 }, + { 0x8041, 59605 }, + { 0x8044, 59608 }, + { 0x8045, 59611 }, + { 0x8047, 59616 }, + { 0x8053, 59619 }, + { 0x8056, 59622 }, + { 0x8057, 59625 }, + { 0x805A, 59633 }, + { 0x805B, 59639 }, + { 0x805C, 59645 }, + { 0x805D, 59653 }, + { 0x8060, 59659 }, + { 0x8061, 59665 }, + { 0x8062, 59671 }, + { 0x8064, 59679 }, + { 0x8065, 59685 }, + { 0x8066, 59691 }, + { 0x8068, 59699 }, + { 0x806A, 59705 }, + { 0x806C, 59711 }, + { 0x805F, 59719 }, + { 0x8063, 59725 }, + { 0x8067, 59731 }, + { 0x8069, 59737 }, + { 0x806D, 59745 }, + { 0x8058, 59751 }, + { 0x805E, 59757 }, + { 0x806B, 59763 }, + { 0x8059, 59769 }, + { 0x806E, 59775 }, + { 0x806F, 59778 }, + { 0x8073, 59781 }, + { 0x8074, 59784 }, + { 0x8075, 59787 }, + { 0x8077, 59792 }, + { 0x8078, 59795 }, + { 0x807E, 59802 }, + { 0x807F, 59805 }, + { 0x8081, 59810 }, + { 0x8083, 59813 }, + { 0x8084, 59816 }, + { 0x80B7, 59819 }, + { 0x80ED, 59822 }, + { 0x80B8, 59827 }, + { 0x80B9, 59836 }, + { 0x80BA, 59843 }, + { 0x80EA, 59850 }, + { 0x80BC, 59855 }, + { 0x80C3, 59860 }, + { 0x80C4, 59865 }, + { 0x80C7, 59870 }, + { 0x80C8, 59875 }, + { 0x80C9, 59882 }, + { 0x80CA, 59887 }, + { 0x80CD, 59895 }, + { 0x80D1, 59900 }, + { 0x80D4, 59909 }, + { 0x80DD, 59916 }, + { 0x80DE, 59921 }, + { 0x80DF, 59928 }, + { 0x80E2, 59933 }, + { 0x80EB, 59938 }, + { 0x80EC, 59943 }, + { 0x80BB, 59950 }, + { 0x80BD, 59958 }, + { 0x80BF, 59963 }, + { 0x80C0, 59968 }, + { 0x80C1, 59975 }, + { 0x80C2, 59980 }, + { 0x80C5, 59987 }, + { 0x80C6, 59994 }, + { 0x80CC, 59999 }, + { 0x80CE, 60004 }, + { 0x80CF, 60009 }, + { 0x80D2, 60016 }, + { 0x80D3, 60021 }, + { 0x80D6, 60028 }, + { 0x80D7, 60034 }, + { 0x80D8, 60043 }, + { 0x80DA, 60048 }, + { 0x80DB, 60053 }, + { 0x80DC, 60060 }, + { 0x80E0, 60067 }, + { 0x80E1, 60072 }, + { 0x80E3, 60079 }, + { 0x80E4, 60084 }, + { 0x80E5, 60089 }, + { 0x80E6, 60094 }, + { 0x80E8, 60101 }, + { 0x80BE, 60106 }, + { 0x80CB, 60113 }, + { 0x80D0, 60119 }, + { 0x80D5, 60126 }, + { 0x80E7, 60131 }, + { 0x80E9, 60136 }, + { 0x80D9, 60141 }, + { 0x80F0, 60146 }, + { 0x80F1, 60149 }, + { 0x80F2, 60157 }, + { 0x80F3, 60160 }, + { 0x80F5, 60169 }, + { 0x80F6, 60172 }, + { 0x80FB, 60175 }, + { 0x8104, 60178 }, + { 0x8105, 60181 }, + { 0x8106, 60186 }, + { 0x8118, 60191 }, + { 0x811D, 60194 }, + { 0x8119, 60198 }, + { 0x811A, 60203 }, + { 0x811B, 60211 }, + { 0x811C, 60216 }, + { 0x811E, 60223 }, + { 0x8121, 60226 }, + { 0x811F, 60232 }, + { 0x8120, 60239 }, + { 0x8122, 60244 }, + { 0x8123, 60247 }, + { 0x8124, 60250 }, + { 0x8125, 60255 }, + { 0x812C, 60258 }, + { 0x8146, 60261 }, + { 0x8148, 60264 }, + { 0x8147, 60268 }, + { 0x814A, 60272 }, + { 0x8149, 60276 }, + { 0x814D, 60287 }, + { 0x8156, 60290 }, + { 0x818D, 60293 }, + { 0x818E, 60296 }, + { 0x818F, 60301 }, + { 0x8195, 60304 }, + { 0x8196, 60307 }, + { 0x8197, 60313 }, + { 0x8198, 60316 }, + { 0x8199, 60321 }, + { 0x81A4, 60326 }, + { 0x81A5, 60329 }, + { 0x81AC, 60332 }, + { 0x81AD, 60335 }, + { 0x81AE, 60338 }, + { 0x81AF, 60343 }, + { 0x81B0, 60346 }, + { 0x81B1, 60349 }, + { 0x81B2, 60353 }, + { 0x81B3, 60356 }, + { 0x81B4, 60359 }, + { 0x81F2, 60364 }, + { 0x81F3, 60367 }, + { 0x81F4, 60372 }, + { 0x81F5, 60375 }, + { 0x81F6, 60380 }, + { 0x81F8, 60387 }, + { 0x81FD, 60390 }, + { 0x8211, 60393 }, + { 0x81FE, 60397 }, + { 0x8203, 60402 }, + { 0x8204, 60409 }, + { 0x8208, 60414 }, + { 0x8209, 60419 }, + { 0x820B, 60426 }, + { 0x820C, 60433 }, + { 0x820D, 60438 }, + { 0x820E, 60443 }, + { 0x81FF, 60450 }, + { 0x8200, 60455 }, + { 0x8201, 60460 }, + { 0x8202, 60466 }, + { 0x8205, 60472 }, + { 0x8206, 60477 }, + { 0x8207, 60482 }, + { 0x820F, 60489 }, + { 0x8210, 60496 }, + { 0x820A, 60501 }, + { 0x8215, 60506 }, + { 0x8214, 60510 }, + { 0x8212, 60514 }, + { 0x8213, 60519 }, + { 0x8216, 60524 }, + { 0x821B, 60527 }, + { 0x821C, 60530 }, + { 0x821D, 60533 }, + { 0x821E, 60536 }, + { 0x821F, 60541 }, + { 0x8223, 60549 }, + { 0x8224, 60552 }, + { 0x8225, 60555 }, + { 0x8229, 60558 }, + { 0x822B, 60561 }, + { 0x822E, 60564 }, + { 0x822F, 60567 }, + { 0x823F, 60571 }, + { 0x8246, 60574 }, + { 0x8245, 60577 }, + { 0x824E, 60581 }, + { 0x824F, 60584 }, + { 0x8251, 60587 }, + { 0x8250, 60595 }, + { 0x8263, 60601 }, + { 0x826A, 60604 }, + { 0x8269, 60609 }, + { 0x8264, 60613 }, + { 0x8266, 60619 }, + { 0x8267, 60625 }, + { 0x8268, 60636 }, + { 0x8265, 60642 }, + { 0x826B, 60648 }, + { 0x826C, 60653 }, + { 0x827B, 60661 }, + { 0x827C, 60664 }, + { 0x827D, 60667 }, + { 0x8290, 60670 }, + { 0x8295, 60673 }, + { 0x82A8, 60676 }, + { 0x82A7, 60680 }, + { 0x8296, 60685 }, + { 0x8297, 60690 }, + { 0x8299, 60695 }, + { 0x829D, 60700 }, + { 0x82A2, 60705 }, + { 0x82A3, 60710 }, + { 0x82A4, 60715 }, + { 0x82A5, 60720 }, + { 0x8298, 60725 }, + { 0x829A, 60730 }, + { 0x829B, 60735 }, + { 0x829C, 60740 }, + { 0x829E, 60745 }, + { 0x829F, 60750 }, + { 0x82A1, 60755 }, + { 0x82A6, 60760 }, + { 0x82A0, 60765 }, + { 0x8294, 60770 }, + { 0x82A9, 60774 }, + { 0x82AA, 60777 }, + { 0x82AC, 60783 }, + { 0x82AD, 60786 }, + { 0x82BA, 60789 }, + { 0x82BB, 60792 }, + { 0x82BC, 60796 }, + { 0x82BD, 60807 }, + { 0x82D7, 60818 }, + { 0x82D8, 60821 }, + { 0x82DD, 60827 }, + { 0x82E4, 60830 }, + { 0x82E7, 60833 }, + { 0x82E9, 60836 }, + { 0x82F0, 60839 }, + { 0x82F1, 60842 }, + { 0x82F2, 60853 }, + { 0x82F3, 60857 }, + { 0x82F4, 60860 }, + { 0x82F9, 60865 }, + { 0x82F5, 60870 }, + { 0x82F6, 60875 }, + { 0x82F7, 60880 }, + { 0x82F8, 60885 }, + { 0x82FB, 60890 }, + { 0x8300, 60893 }, + { 0x8301, 60896 }, + { 0x8303, 60899 }, + { 0x8304, 60904 }, + { 0x8302, 60915 }, + { 0x8307, 60920 }, + { 0x8308, 60923 }, + { 0x8309, 60926 }, + { 0x830A, 60929 }, + { 0x832B, 60937 }, + { 0x832C, 60940 }, + { 0x832D, 60947 }, + { 0x832E, 60954 }, + { 0x832F, 60959 }, + { 0x8331, 60964 }, + { 0x8333, 60969 }, + { 0x8332, 60976 }, + { 0x8330, 60983 }, + { 0x8334, 60988 }, + { 0x8335, 60991 }, + { 0x8337, 60994 }, + { 0x8338, 60997 }, + { 0x834C, 61002 }, + { 0x833C, 61009 }, + { 0x8340, 61014 }, + { 0x8341, 61019 }, + { 0x8343, 61024 }, + { 0x8345, 61029 }, + { 0x8348, 61034 }, + { 0x834B, 61039 }, + { 0x834D, 61044 }, + { 0x833A, 61049 }, + { 0x833B, 61054 }, + { 0x833D, 61059 }, + { 0x833F, 61064 }, + { 0x8342, 61069 }, + { 0x8344, 61074 }, + { 0x8346, 61079 }, + { 0x8347, 61084 }, + { 0x8349, 61089 }, + { 0x833E, 61094 }, + { 0x834A, 61100 }, + { 0x834E, 61105 }, + { 0x8339, 61110 }, + { 0x8351, 61115 }, + { 0x8352, 61118 }, + { 0x8353, 61123 }, + { 0x8354, 61128 }, + { 0x8355, 61133 }, + { 0x835A, 61138 }, + { 0x835B, 61141 }, + { 0x835C, 61146 }, + { 0x8360, 61149 }, + { 0x8362, 61152 }, + { 0x8365, 61155 }, + { 0x8366, 61158 }, + { 0x8367, 61161 }, + { 0x8368, 61166 }, + { 0x836B, 61169 }, + { 0x836C, 61172 }, + { 0x836E, 61177 }, + { 0x8029, 61180 }, + { 0x802B, 61183 }, + { 0x802C, 61186 }, + { 0x8033, 61191 }, + { 0x8034, 61194 }, + { 0x8035, 61197 }, + { 0x803E, 61202 }, + { 0x8042, 61205 }, + { 0x8054, 61208 }, + { 0x8076, 61211 }, + { 0x8079, 61214 }, + { 0x8080, 61217 }, + { 0x8085, 61220 }, + { 0x8086, 61223 }, + { 0x8087, 61227 }, + { 0x8088, 61232 }, + { 0x8089, 61235 }, + { 0x8094, 61238 }, + { 0x8095, 61241 }, + { 0x809E, 61244 }, + { 0x80A0, 61247 }, + { 0x80A1, 61250 }, + { 0x80A2, 61253 }, + { 0x80A3, 61258 }, + { 0x80A4, 61265 }, + { 0x80A5, 61274 }, + { 0x80A9, 61279 }, + { 0x80AA, 61284 }, + { 0x80AF, 61290 }, + { 0x80B1, 61295 }, + { 0x80B2, 61300 }, + { 0x80B3, 61305 }, + { 0x80B4, 61310 }, + { 0x80A6, 61315 }, + { 0x80AB, 61320 }, + { 0x80AE, 61326 }, + { 0x80B0, 61331 }, + { 0x80A7, 61338 }, + { 0x80A8, 61344 }, + { 0x80AC, 61351 }, + { 0x80AD, 61356 }, + { 0x80EE, 61362 }, + { 0x80EF, 61365 }, + { 0x80F7, 61370 }, + { 0x80F9, 61373 }, + { 0x80F8, 61378 }, + { 0x80FA, 61382 }, + { 0x80FC, 61387 }, + { 0x8108, 61390 }, + { 0x8109, 61393 }, + { 0x810A, 61397 }, + { 0x810B, 61400 }, + { 0x810E, 61407 }, + { 0x810F, 61414 }, + { 0x810D, 61419 }, + { 0x810C, 61424 }, + { 0x8111, 61430 }, + { 0x8115, 61433 }, + { 0x8113, 61437 }, + { 0x8114, 61442 }, + { 0x8112, 61447 }, + { 0x8126, 61452 }, + { 0x8138, 61455 }, + { 0x8139, 61458 }, + { 0x813D, 61463 }, + { 0x813A, 61468 }, + { 0x813C, 61473 }, + { 0x813B, 61478 }, + { 0x813E, 61483 }, + { 0x8142, 61486 }, + { 0x8143, 61489 }, + { 0x8144, 61495 }, + { 0x8153, 61501 }, + { 0x8190, 61504 }, + { 0x8191, 61507 }, + { 0x8192, 61510 }, + { 0x8193, 61513 }, + { 0x8194, 61516 }, + { 0x819A, 61521 }, + { 0x819B, 61524 }, + { 0x81A7, 61527 }, + { 0x81FA, 61530 }, + { 0x8226, 61533 }, + { 0x8232, 61536 }, + { 0x8236, 61539 }, + { 0x8237, 61544 }, + { 0x8233, 61553 }, + { 0x8235, 61558 }, + { 0x8234, 61563 }, + { 0x8238, 61568 }, + { 0x8240, 61573 }, + { 0x8242, 61576 }, + { 0x8241, 61582 }, + { 0x8243, 61586 }, + { 0x8247, 61591 }, + { 0x8262, 61594 }, + { 0x82AE, 61597 }, + { 0x82AF, 61600 }, + { 0x82B5, 61605 }, + { 0x82B6, 61610 }, + { 0x82B2, 61617 }, + { 0x82B0, 61622 }, + { 0x82B4, 61627 }, + { 0x82B1, 61632 }, + { 0x82B3, 61637 }, + { 0x82B7, 61642 }, + { 0x82BF, 61645 }, + { 0x82C3, 61648 }, + { 0x82C4, 61651 }, + { 0x82C5, 61656 }, + { 0x82C6, 61661 }, + { 0x82C7, 61664 }, + { 0x82C8, 61669 }, + { 0x82CA, 61674 }, + { 0x82CB, 61679 }, + { 0x82CC, 61684 }, + { 0x82CD, 61689 }, + { 0x82CF, 61695 }, + { 0x82D0, 61700 }, + { 0x82D1, 61705 }, + { 0x82C9, 61710 }, + { 0x82CE, 61715 }, + { 0x82D3, 61720 }, + { 0x82D5, 61723 }, + { 0x82D4, 61731 }, + { 0x82D9, 61735 }, + { 0x82DE, 61738 }, + { 0x82DF, 61741 }, + { 0x82E0, 61747 }, + { 0x82E5, 61750 }, + { 0x82EA, 61753 }, + { 0x82FA, 61756 }, + { 0x8306, 61759 }, + { 0x831C, 61762 }, + { 0x8323, 61765 }, + { 0x8325, 61768 }, + { 0x8324, 61773 }, + { 0x8336, 61778 }, + { 0x8357, 61781 }, + { 0x8356, 61784 }, + { 0x8361, 61787 }, + { 0x8369, 61790 }, + { 0x802A, 61793 }, + { 0x8032, 61796 }, + { 0x8036, 61799 }, + { 0x8037, 61802 }, + { 0x8046, 61805 }, + { 0x8048, 61808 }, + { 0x8051, 61811 }, + { 0x8052, 61814 }, + { 0x8070, 61819 }, + { 0x8071, 61822 }, + { 0x8082, 61825 }, + { 0x809F, 61828 }, + { 0x80F4, 61831 }, + { 0x8107, 61834 }, + { 0x8110, 61837 }, + { 0x8127, 61840 }, + { 0x819F, 61843 }, + { 0x81A6, 61846 }, + { 0x81B8, 61849 }, + { 0x81B9, 61852 }, + { 0x81BA, 61857 }, + { 0x81BB, 61866 }, + { 0x81BC, 61873 }, + { 0x81E5, 61880 }, + { 0x81E6, 61885 }, + { 0x81E7, 61892 }, + { 0x81BD, 61901 }, + { 0x81BE, 61906 }, + { 0x81C1, 61911 }, + { 0x81C3, 61916 }, + { 0x81C4, 61921 }, + { 0x81C8, 61926 }, + { 0x81CA, 61931 }, + { 0x81CC, 61938 }, + { 0x81CD, 61943 }, + { 0x81CE, 61950 }, + { 0x81CF, 61957 }, + { 0x81D6, 61962 }, + { 0x81D8, 61967 }, + { 0x81D9, 61972 }, + { 0x81DB, 61979 }, + { 0x81E4, 61984 }, + { 0x81E8, 61995 }, + { 0x81E9, 62002 }, + { 0x81BF, 62007 }, + { 0x81C0, 62014 }, + { 0x81C2, 62019 }, + { 0x81C5, 62024 }, + { 0x81C6, 62029 }, + { 0x81C7, 62034 }, + { 0x81C9, 62041 }, + { 0x81CB, 62046 }, + { 0x81D0, 62052 }, + { 0x81D1, 62057 }, + { 0x81D2, 62062 }, + { 0x81D3, 62067 }, + { 0x81D7, 62076 }, + { 0x81DC, 62081 }, + { 0x81E1, 62088 }, + { 0x81E2, 62093 }, + { 0x81EA, 62098 }, + { 0x81D5, 62103 }, + { 0x81DA, 62108 }, + { 0x81DF, 62113 }, + { 0x81E0, 62118 }, + { 0x81E3, 62125 }, + { 0x81D4, 62130 }, + { 0x81DD, 62135 }, + { 0x81DE, 62144 }, + { 0x81EB, 62152 }, + { 0x81EC, 62156 }, + { 0x81EF, 62159 }, + { 0x81F0, 62163 }, + { 0x81ED, 62171 }, + { 0x81EE, 62176 }, + { 0x8217, 62183 }, + { 0x8218, 62186 }, + { 0x821A, 62191 }, + { 0x8219, 62195 }, + { 0x8227, 62200 }, + { 0x8239, 62203 }, + { 0x823D, 62206 }, + { 0x823A, 62210 }, + { 0x823B, 62215 }, + { 0x823C, 62222 }, + { 0x8244, 62227 }, + { 0x8260, 62230 }, + { 0x826D, 62233 }, + { 0x826F, 62236 }, + { 0x8274, 62242 }, + { 0x8275, 62248 }, + { 0x8277, 62254 }, + { 0x8270, 62260 }, + { 0x8271, 62266 }, + { 0x8272, 62272 }, + { 0x8273, 62279 }, + { 0x8276, 62285 }, + { 0x826E, 62291 }, + { 0x8278, 62297 }, + { 0x8279, 62303 }, + { 0x827E, 62310 }, + { 0x828A, 62313 }, + { 0x828C, 62316 }, + { 0x828D, 62321 }, + { 0x828B, 62326 }, + { 0x828E, 62331 }, + { 0x82B8, 62336 }, + { 0x82B9, 62339 }, + { 0x82BE, 62342 }, + { 0x82C0, 62345 }, + { 0x82D6, 62348 }, + { 0x82E1, 62351 }, + { 0x82E6, 62354 }, + { 0x8322, 62357 }, + { 0x834F, 62360 }, + { 0x8350, 62363 }, + { 0x8359, 62368 }, + { 0x836D, 62371 }, + { 0x803F, 62374 }, + { 0x8043, 62377 }, + { 0x80FD, 62380 }, + { 0x8128, 62383 }, + { 0x819C, 62386 }, + { 0x819E, 62389 }, + { 0x819D, 62401 }, + { 0x81A8, 62411 }, + { 0x81A9, 62414 }, + { 0x81B5, 62419 }, + { 0x81B6, 62422 }, + { 0x81F1, 62425 }, + { 0x81F9, 62428 }, + { 0x8230, 62431 }, + { 0x8231, 62434 }, + { 0x8252, 62437 }, + { 0x8253, 62440 }, + { 0x8257, 62445 }, + { 0x8258, 62453 }, + { 0x825E, 62458 }, + { 0x8254, 62465 }, + { 0x8255, 62470 }, + { 0x8256, 62477 }, + { 0x8259, 62482 }, + { 0x825A, 62487 }, + { 0x825B, 62492 }, + { 0x825C, 62500 }, + { 0x825D, 62507 }, + { 0x825F, 62516 }, + { 0x82AB, 62521 }, + { 0x82C1, 62524 }, + { 0x82D2, 62527 }, + { 0x82DA, 62530 }, + { 0x82E8, 62533 }, + { 0x8358, 62536 }, + { 0x80FE, 62539 }, + { 0x80FF, 62542 }, + { 0x82C2, 62547 }, + { 0x8461, 62550 }, + { 0x8462, 62557 }, + { 0x844F, 62564 }, + { 0x8434, 62569 }, + { 0x8458, 62574 }, + { 0x8415, 62579 }, + { 0x841E, 62584 }, + { 0x842C, 62589 }, + { 0x845A, 62594 }, + { 0x845D, 62600 }, + { 0x845F, 62608 }, + { 0x8460, 62614 }, + { 0x8411, 62620 }, + { 0x8404, 62625 }, + { 0x844E, 62630 }, + { 0x840B, 62636 }, + { 0x841A, 62641 }, + { 0x8428, 62646 }, + { 0x8440, 62651 }, + { 0x8400, 62658 }, + { 0x844A, 62663 }, + { 0x8450, 62669 }, + { 0x8435, 62674 }, + { 0x8459, 62679 }, + { 0x8416, 62684 }, + { 0x841F, 62689 }, + { 0x8423, 62694 }, + { 0x842D, 62699 }, + { 0x845B, 62704 }, + { 0x845E, 62710 }, + { 0x8410, 62718 }, + { 0x8403, 62723 }, + { 0x844D, 62728 }, + { 0x8454, 62734 }, + { 0x8455, 62739 }, + { 0x8439, 62746 }, + { 0x840A, 62751 }, + { 0x8419, 62756 }, + { 0x8422, 62761 }, + { 0x8427, 62766 }, + { 0x8431, 62771 }, + { 0x845C, 62776 }, + { 0x840F, 62782 }, + { 0x8402, 62787 }, + { 0x844C, 62792 }, + { 0x8452, 62798 }, + { 0x8453, 62803 }, + { 0x8438, 62810 }, + { 0x8409, 62815 }, + { 0x8418, 62820 }, + { 0x8421, 62825 }, + { 0x8426, 62830 }, + { 0x8430, 62835 }, + { 0x843C, 62840 }, + { 0x843E, 62847 }, + { 0x843F, 62855 }, + { 0x843D, 62863 }, + { 0x8414, 62870 }, + { 0x8407, 62875 }, + { 0x840E, 62880 }, + { 0x841D, 62885 }, + { 0x842B, 62890 }, + { 0x8446, 62895 }, + { 0x8449, 62902 }, + { 0x8447, 62910 }, + { 0x8448, 62917 }, + { 0x8413, 62924 }, + { 0x8406, 62929 }, + { 0x840D, 62934 }, + { 0x841C, 62939 }, + { 0x842A, 62944 }, + { 0x8444, 62949 }, + { 0x8445, 62956 }, + { 0x8412, 62963 }, + { 0x8405, 62968 }, + { 0x840C, 62973 }, + { 0x841B, 62978 }, + { 0x8429, 62983 }, + { 0x8442, 62988 }, + { 0x8443, 62996 }, + { 0x8441, 63004 }, + { 0x8433, 63011 }, + { 0x8432, 63019 }, + { 0x8401, 63027 }, + { 0x844B, 63032 }, + { 0x8451, 63038 }, + { 0x8436, 63043 }, + { 0x8437, 63048 }, + { 0x8408, 63055 }, + { 0x8417, 63060 }, + { 0x8420, 63065 }, + { 0x8424, 63070 }, + { 0x8425, 63075 }, + { 0x842E, 63082 }, + { 0x842F, 63087 }, + { 0x843A, 63094 }, + { 0x843B, 63101 }, + { 0x8457, 63108 }, + { 0x8456, 63112 }, + { 0x8470, 63116 }, + { 0x8472, 63123 }, + { 0x8473, 63128 }, + { 0x8471, 63133 }, + { 0x23CA, 63138 }, + { 0x23C8, 63144 }, + { 0x23C2, 63152 }, + { 0x23C5, 63160 }, + { 0x23C9, 63168 }, + { 0x23C7, 63174 }, + { 0x23C1, 63182 }, + { 0x23C4, 63190 }, + { 0x23CB, 63198 }, + { 0x23BE, 63205 }, + { 0x23C6, 63212 }, + { 0x23CC, 63218 }, + { 0x23BF, 63225 }, + { 0x23C0, 63232 }, + { 0x23C3, 63238 }, + { 0x00A8, 63244 }, + { 0x2331, 63245 }, + { 0x21A1, 63247 }, + { 0x2193, 63251 }, + { 0x2913, 63253 }, + { 0x21A7, 63257 }, + { 0x21B2, 63261 }, + { 0x21B3, 63266 }, + { 0x21B5, 63271 }, + { 0x21DF, 63276 }, + { 0x2908, 63281 }, + { 0x21F5, 63286 }, + { 0x2B07, 63292 }, + { 0x21E9, 63295 }, + { 0x2E14, 63298 }, + { 0x21E3, 63300 }, + { 0x21D3, 63303 }, + { 0x21CA, 63306 }, + { 0x290B, 63309 }, + { 0x21AF, 63312 }, + { 0x2959, 63315 }, + { 0x2961, 63322 }, + { 0x296F, 63329 }, + { 0x2965, 63340 }, + { 0x2955, 63351 }, + { 0x295D, 63358 }, + { 0x21C3, 63365 }, + { 0x21C2, 63370 }, + { 0x27F1, 63375 }, + { 0x2E0E, 63378 }, + { 0x212E, 63380 }, + { 0x2259, 63382 }, + { 0x213B, 63383 }, + { 0x6F3F, 63385 }, + { 0x6FE2, 63388 }, + { 0x6FE6, 63391 }, + { 0x6FE5, 63394 }, + { 0x6FE0, 63397 }, + { 0x6F0E, 63400 }, + { 0x6F5B, 63403 }, + { 0x6F5F, 63407 }, + { 0x6F3B, 63411 }, + { 0x6F08, 63415 }, + { 0x6F0B, 63418 }, + { 0x6F1A, 63421 }, + { 0x6F0C, 63423 }, + { 0x6F11, 63425 }, + { 0x6F16, 63428 }, + { 0x6F12, 63431 }, + { 0x6F15, 63434 }, + { 0x6F14, 63437 }, + { 0x6F19, 63440 }, + { 0x6F10, 63443 }, + { 0x6F18, 63446 }, + { 0x6F17, 63449 }, + { 0x6F13, 63452 }, + { 0x6F40, 63455 }, + { 0x6F41, 63458 }, + { 0x6F42, 63463 }, + { 0x6F43, 63468 }, + { 0x6F44, 63473 }, + { 0x6F45, 63478 }, + { 0x6F46, 63483 }, + { 0x6F47, 63488 }, + { 0x6F48, 63493 }, + { 0x6F49, 63498 }, + { 0x6F4A, 63503 }, + { 0x6F4B, 63508 }, + { 0x6F4C, 63513 }, + { 0x6F4D, 63518 }, + { 0x6F4E, 63523 }, + { 0x6F4F, 63528 }, + { 0x6F50, 63533 }, + { 0x6F51, 63538 }, + { 0x6F52, 63543 }, + { 0x6F53, 63548 }, + { 0x6F54, 63553 }, + { 0x6F55, 63558 }, + { 0x6F56, 63563 }, + { 0x6F57, 63568 }, + { 0x6F58, 63573 }, + { 0x6F59, 63578 }, + { 0x6F5A, 63583 }, + { 0x6F21, 63588 }, + { 0x6F22, 63593 }, + { 0x6F23, 63598 }, + { 0x6F24, 63603 }, + { 0x6F25, 63608 }, + { 0x6F26, 63613 }, + { 0x6F27, 63618 }, + { 0x6F28, 63623 }, + { 0x6F29, 63628 }, + { 0x6F2A, 63633 }, + { 0x6F2B, 63638 }, + { 0x6F2C, 63643 }, + { 0x6F2D, 63648 }, + { 0x6F2E, 63653 }, + { 0x6F2F, 63658 }, + { 0x6F30, 63663 }, + { 0x6F31, 63668 }, + { 0x6F32, 63673 }, + { 0x6F33, 63678 }, + { 0x6F34, 63683 }, + { 0x6F35, 63688 }, + { 0x6F36, 63693 }, + { 0x6F37, 63698 }, + { 0x6F38, 63703 }, + { 0x6F39, 63708 }, + { 0x6F3A, 63713 }, + { 0x6FE1, 63718 }, + { 0x6F5D, 63721 }, + { 0x6F60, 63725 }, + { 0x6F3D, 63729 }, + { 0x6F09, 63733 }, + { 0x6F5E, 63736 }, + { 0x6FE4, 63738 }, + { 0x6F04, 63741 }, + { 0x6F1D, 63744 }, + { 0x6FE3, 63747 }, + { 0x6F03, 63749 }, + { 0x6F05, 63752 }, + { 0x6F3C, 63755 }, + { 0x6F0F, 63758 }, + { 0x6F0A, 63760 }, + { 0x6F1F, 63762 }, + { 0x6F5C, 63765 }, + { 0x6F06, 63768 }, + { 0x6F1C, 63770 }, + { 0x6F02, 63773 }, + { 0x6F1B, 63776 }, + { 0x6F07, 63778 }, + { 0x6F3E, 63780 }, + { 0x6F20, 63783 }, + { 0x6F01, 63786 }, + { 0x6F1E, 63789 }, + { 0x6F0D, 63792 }, + { 0x223A, 63794 }, + { 0x6F62, 63796 }, + { 0x6FED, 63800 }, + { 0x6FE8, 63803 }, + { 0x6F63, 63807 }, + { 0x6FEE, 63811 }, + { 0x6FA0, 63814 }, + { 0x6FC2, 63817 }, + { 0x6FC7, 63821 }, + { 0x6FDC, 63825 }, + { 0x6FCC, 63829 }, + { 0x6FD3, 63833 }, + { 0x6FC3, 63837 }, + { 0x6FC6, 63841 }, + { 0x6FDA, 63845 }, + { 0x6FCF, 63849 }, + { 0x6FCD, 63853 }, + { 0x6FD5, 63857 }, + { 0x6FD6, 63861 }, + { 0x6FC4, 63865 }, + { 0x6FCB, 63869 }, + { 0x6FDB, 63873 }, + { 0x6FD2, 63877 }, + { 0x6FD7, 63881 }, + { 0x6FCE, 63885 }, + { 0x6FD4, 63889 }, + { 0x6FC5, 63893 }, + { 0x6FCA, 63897 }, + { 0x6FB5, 63901 }, + { 0x6FB8, 63905 }, + { 0x6FBE, 63909 }, + { 0x6FB7, 63913 }, + { 0x6FB1, 63917 }, + { 0x6FA4, 63921 }, + { 0x6FB2, 63925 }, + { 0x6FA9, 63929 }, + { 0x6FA1, 63933 }, + { 0x6FA7, 63937 }, + { 0x6FBA, 63941 }, + { 0x6FBB, 63945 }, + { 0x6FBD, 63949 }, + { 0x6FBC, 63953 }, + { 0x6FB6, 63957 }, + { 0x6FB4, 63961 }, + { 0x6FAD, 63965 }, + { 0x6FB9, 63969 }, + { 0x6FB3, 63973 }, + { 0x6FA3, 63977 }, + { 0x6FA5, 63981 }, + { 0x6FA6, 63985 }, + { 0x6FB0, 63989 }, + { 0x6FAB, 63993 }, + { 0x6FAC, 63997 }, + { 0x6FA2, 64001 }, + { 0x6FA8, 64005 }, + { 0x6FAA, 64009 }, + { 0x6FAF, 64013 }, + { 0x6FAE, 64017 }, + { 0x6FEA, 64021 }, + { 0x6F71, 64024 }, + { 0x6F74, 64028 }, + { 0x6F72, 64032 }, + { 0x6F9D, 64036 }, + { 0x6F75, 64040 }, + { 0x6F73, 64044 }, + { 0x6F8A, 64048 }, + { 0x6F8D, 64052 }, + { 0x6F8B, 64056 }, + { 0x6F8E, 64060 }, + { 0x6F8C, 64064 }, + { 0x6F76, 64068 }, + { 0x6F79, 64072 }, + { 0x6F77, 64076 }, + { 0x6F7A, 64080 }, + { 0x6F78, 64084 }, + { 0x6F8F, 64088 }, + { 0x6F92, 64092 }, + { 0x6F90, 64096 }, + { 0x6F93, 64100 }, + { 0x6F91, 64104 }, + { 0x6F85, 64108 }, + { 0x6F88, 64112 }, + { 0x6F86, 64116 }, + { 0x6F89, 64120 }, + { 0x6F87, 64124 }, + { 0x6F97, 64128 }, + { 0x6F9A, 64132 }, + { 0x6F98, 64136 }, + { 0x6F9B, 64140 }, + { 0x6F99, 64144 }, + { 0x6F7B, 64148 }, + { 0x6F7E, 64152 }, + { 0x6F7C, 64156 }, + { 0x6F7F, 64160 }, + { 0x6F7D, 64164 }, + { 0x6F80, 64168 }, + { 0x6F83, 64172 }, + { 0x6F81, 64176 }, + { 0x6F84, 64180 }, + { 0x6F82, 64184 }, + { 0x6F9C, 64188 }, + { 0x6F66, 64192 }, + { 0x6F94, 64196 }, + { 0x6F96, 64200 }, + { 0x6F95, 64204 }, + { 0x6F67, 64208 }, + { 0x6F6A, 64213 }, + { 0x6F68, 64218 }, + { 0x6F6B, 64223 }, + { 0x6F69, 64228 }, + { 0x6F6F, 64233 }, + { 0x6F6C, 64238 }, + { 0x6F6E, 64243 }, + { 0x6F6D, 64248 }, + { 0x6F65, 64253 }, + { 0x6F9E, 64257 }, + { 0x6F9F, 64262 }, + { 0x6FEC, 64267 }, + { 0x6FE9, 64270 }, + { 0x6FEB, 64273 }, + { 0x6F61, 64276 }, + { 0x6F64, 64280 }, + { 0x6F70, 64283 }, + { 0x22B9, 64288 }, + { 0x231B, 64291 }, + { 0x2261, 64292 }, + { 0x29E5, 64294 }, + { 0x2A67, 64299 }, + { 0x29E1, 64303 }, + { 0x2206, 64305 }, + { 0x2380, 64306 }, + { 0x2064, 64308 }, + { 0x2062, 64310 }, + { 0x2063, 64312 }, + { 0x2939, 64314 }, + { 0x219E, 64318 }, + { 0x219C, 64322 }, + { 0x2190, 64325 }, + { 0x21E4, 64327 }, + { 0x21B9, 64331 }, + { 0x291D, 64340 }, + { 0x21A4, 64345 }, + { 0x291F, 64349 }, + { 0x21C6, 64356 }, + { 0x2B11, 64361 }, + { 0x2B10, 64366 }, + { 0x21A9, 64371 }, + { 0x21AB, 64375 }, + { 0x2946, 64379 }, + { 0x21A2, 64384 }, + { 0x2B3A, 64388 }, + { 0x2B39, 64396 }, + { 0x2B38, 64403 }, + { 0x21FA, 64408 }, + { 0x219A, 64414 }, + { 0x21F7, 64418 }, + { 0x2943, 64423 }, + { 0x2973, 64429 }, + { 0x2B4A, 64434 }, + { 0x2B4B, 64440 }, + { 0x2B42, 64446 }, + { 0x2B3E, 64453 }, + { 0x297A, 64457 }, + { 0x2977, 64461 }, + { 0x2B05, 64465 }, + { 0x21E6, 64468 }, + { 0x21E0, 64471 }, + { 0x290C, 64474 }, + { 0x21D0, 64478 }, + { 0x2906, 64481 }, + { 0x21CD, 64486 }, + { 0x2902, 64491 }, + { 0x291B, 64497 }, + { 0x21C7, 64500 }, + { 0x290E, 64503 }, + { 0x21DA, 64507 }, + { 0x21CB, 64510 }, + { 0x2952, 64515 }, + { 0x295A, 64522 }, + { 0x296A, 64529 }, + { 0x2962, 64537 }, + { 0x2966, 64548 }, + { 0x2956, 64559 }, + { 0x295E, 64566 }, + { 0x2967, 64573 }, + { 0x296B, 64584 }, + { 0x21BC, 64592 }, + { 0x21BD, 64597 }, + { 0x21DC, 64602 }, + { 0x2B45, 64605 }, + { 0x2919, 64608 }, + { 0x2B36, 64610 }, + { 0x2B3B, 64615 }, + { 0x2B3D, 64620 }, + { 0x2B3C, 64629 }, + { 0x2B35, 64637 }, + { 0x2B34, 64644 }, + { 0x2B37, 64650 }, + { 0x21FD, 64655 }, + { 0x2264, 64658 }, + { 0x2A7D, 64662 }, + { 0x2A81, 64667 }, + { 0x2A83, 64675 }, + { 0x2A7F, 64684 }, + { 0x2272, 64692 }, + { 0x2A85, 64696 }, + { 0x2276, 64699 }, + { 0x2A89, 64702 }, + { 0x2A87, 64706 }, + { 0x2268, 64712 }, + { 0x22E6, 64717 }, + { 0x2266, 64722 }, + { 0x003C, 64726 }, + { 0x22D6, 64728 }, + { 0x2A79, 64731 }, + { 0x2A7B, 64735 }, + { 0x2A8D, 64740 }, + { 0x2A8F, 64745 }, + { 0x2A93, 64750 }, + { 0x2976, 64759 }, + { 0x2A8B, 64763 }, + { 0x2A91, 64769 }, + { 0x22DA, 64775 }, + { 0x2AA6, 64780 }, + { 0x2AA8, 64784 }, + { 0x2607, 64791 }, + { 0x0D57, 64792 }, + { 0x0D79, 64796 }, + { 0x0D4D, 64799 }, + { 0x0D03, 64802 }, + { 0x0D02, 64805 }, + { 0x0D3D, 64808 }, + { 0x0D67, 64811 }, + { 0x0D6C, 64814 }, + { 0x0D68, 64817 }, + { 0x0D6B, 64820 }, + { 0x0D6A, 64823 }, + { 0x0D6F, 64826 }, + { 0x0D66, 64829 }, + { 0x0D6E, 64832 }, + { 0x0D6D, 64835 }, + { 0x0D69, 64838 }, + { 0x0D46, 64841 }, + { 0x0D3F, 64845 }, + { 0x0D4A, 64849 }, + { 0x0D41, 64853 }, + { 0x0D3E, 64857 }, + { 0x0D48, 64861 }, + { 0x0D4C, 64865 }, + { 0x0D47, 64869 }, + { 0x0D40, 64873 }, + { 0x0D4B, 64877 }, + { 0x0D42, 64881 }, + { 0x0D62, 64885 }, + { 0x0D43, 64890 }, + { 0x0D63, 64895 }, + { 0x0D44, 64900 }, + { 0x0D05, 64905 }, + { 0x0D0E, 64908 }, + { 0x0D07, 64911 }, + { 0x0D12, 64914 }, + { 0x0D09, 64917 }, + { 0x0D06, 64920 }, + { 0x0D10, 64923 }, + { 0x0D14, 64926 }, + { 0x0D2C, 64929 }, + { 0x0D1A, 64932 }, + { 0x0D26, 64935 }, + { 0x0D0F, 64938 }, + { 0x0D17, 64941 }, + { 0x0D39, 64944 }, + { 0x0D08, 64947 }, + { 0x0D1C, 64950 }, + { 0x0D15, 64953 }, + { 0x0D32, 64956 }, + { 0x0D2E, 64959 }, + { 0x0D28, 64962 }, + { 0x0D13, 64965 }, + { 0x0D2A, 64968 }, + { 0x0D30, 64971 }, + { 0x0D38, 64974 }, + { 0x0D24, 64977 }, + { 0x0D0A, 64980 }, + { 0x0D35, 64983 }, + { 0x0D2F, 64986 }, + { 0x0D2D, 64989 }, + { 0x0D1B, 64992 }, + { 0x0D21, 64995 }, + { 0x0D27, 64998 }, + { 0x0D18, 65001 }, + { 0x0D1D, 65004 }, + { 0x0D16, 65007 }, + { 0x0D33, 65010 }, + { 0x0D19, 65013 }, + { 0x0D23, 65016 }, + { 0x0D1E, 65019 }, + { 0x0D2B, 65022 }, + { 0x0D31, 65025 }, + { 0x0D36, 65028 }, + { 0x0D37, 65031 }, + { 0x0D25, 65034 }, + { 0x0D1F, 65037 }, + { 0x0D22, 65040 }, + { 0x0D34, 65043 }, + { 0x0D20, 65046 }, + { 0x0D7F, 65049 }, + { 0x0D7D, 65053 }, + { 0x0D7B, 65057 }, + { 0x0D7E, 65061 }, + { 0x0D7A, 65065 }, + { 0x0D7C, 65069 }, + { 0x0D0C, 65073 }, + { 0x0D0B, 65077 }, + { 0x0D61, 65081 }, + { 0x0D60, 65085 }, + { 0x0D71, 65089 }, + { 0x0D72, 65093 }, + { 0x0D70, 65097 }, + { 0x0D74, 65100 }, + { 0x0D73, 65104 }, + { 0x0D75, 65108 }, + { 0x00BA, 65112 }, + { 0x1805, 65115 }, + { 0x180B, 65118 }, + { 0x180C, 65123 }, + { 0x180D, 65128 }, + { 0x1803, 65133 }, + { 0x1807, 65136 }, + { 0x1806, 65141 }, + { 0x1800, 65145 }, + { 0x1804, 65147 }, + { 0x1802, 65149 }, + { 0x1811, 65151 }, + { 0x1816, 65154 }, + { 0x1812, 65157 }, + { 0x1815, 65160 }, + { 0x1814, 65163 }, + { 0x1819, 65166 }, + { 0x1810, 65169 }, + { 0x1818, 65172 }, + { 0x1817, 65175 }, + { 0x1813, 65178 }, + { 0x180E, 65181 }, + { 0x1820, 65184 }, + { 0x1821, 65187 }, + { 0x1822, 65190 }, + { 0x1823, 65193 }, + { 0x1824, 65196 }, + { 0x182A, 65199 }, + { 0x1833, 65202 }, + { 0x1827, 65205 }, + { 0x1839, 65208 }, + { 0x182D, 65211 }, + { 0x1835, 65214 }, + { 0x183A, 65217 }, + { 0x182F, 65220 }, + { 0x182E, 65223 }, + { 0x1828, 65226 }, + { 0x1825, 65229 }, + { 0x182B, 65232 }, + { 0x182C, 65235 }, + { 0x1837, 65238 }, + { 0x1830, 65241 }, + { 0x1832, 65244 }, + { 0x1826, 65247 }, + { 0x1838, 65250 }, + { 0x1836, 65253 }, + { 0x183D, 65256 }, + { 0x1887, 65259 }, + { 0x1888, 65264 }, + { 0x1897, 65269 }, + { 0x188B, 65274 }, + { 0x1891, 65279 }, + { 0x1889, 65284 }, + { 0x1892, 65289 }, + { 0x1890, 65294 }, + { 0x1896, 65299 }, + { 0x188E, 65304 }, + { 0x188A, 65309 }, + { 0x188F, 65314 }, + { 0x1893, 65319 }, + { 0x1894, 65324 }, + { 0x188C, 65329 }, + { 0x1895, 65334 }, + { 0x18A6, 65339 }, + { 0x18A7, 65345 }, + { 0x188D, 65351 }, + { 0x1886, 65356 }, + { 0x1885, 65362 }, + { 0x1882, 65367 }, + { 0x18A9, 65372 }, + { 0x1883, 65377 }, + { 0x1881, 65382 }, + { 0x1880, 65388 }, + { 0x1884, 65394 }, + { 0x1829, 65400 }, + { 0x1834, 65403 }, + { 0x1842, 65406 }, + { 0x183E, 65409 }, + { 0x183B, 65412 }, + { 0x1840, 65415 }, + { 0x1831, 65418 }, + { 0x183C, 65421 }, + { 0x1841, 65424 }, + { 0x183F, 65427 }, + { 0x185D, 65430 }, + { 0x185E, 65434 }, + { 0x1861, 65438 }, + { 0x1869, 65442 }, + { 0x186B, 65446 }, + { 0x1864, 65450 }, + { 0x1865, 65454 }, + { 0x185F, 65458 }, + { 0x186A, 65462 }, + { 0x1863, 65466 }, + { 0x1866, 65470 }, + { 0x1868, 65474 }, + { 0x1860, 65478 }, + { 0x186F, 65482 }, + { 0x1862, 65486 }, + { 0x1871, 65490 }, + { 0x186C, 65494 }, + { 0x186D, 65498 }, + { 0x1870, 65502 }, + { 0x1867, 65506 }, + { 0x186E, 65510 }, + { 0x1872, 65514 }, + { 0x1844, 65518 }, + { 0x1845, 65522 }, + { 0x1846, 65526 }, + { 0x1847, 65530 }, + { 0x184B, 65534 }, + { 0x1851, 65538 }, + { 0x184E, 65542 }, + { 0x1853, 65546 }, + { 0x1857, 65550 }, + { 0x184F, 65554 }, + { 0x1848, 65558 }, + { 0x184C, 65562 }, + { 0x184D, 65566 }, + { 0x1850, 65570 }, + { 0x1849, 65574 }, + { 0x1856, 65578 }, + { 0x1855, 65582 }, + { 0x1898, 65586 }, + { 0x1899, 65592 }, + { 0x184A, 65598 }, + { 0x1852, 65602 }, + { 0x185C, 65606 }, + { 0x1858, 65610 }, + { 0x1859, 65614 }, + { 0x185A, 65618 }, + { 0x185B, 65622 }, + { 0x1854, 65626 }, + { 0x1843, 65630 }, + { 0x1873, 65636 }, + { 0x1876, 65640 }, + { 0x1874, 65644 }, + { 0x1875, 65648 }, + { 0x189C, 65652 }, + { 0x18A0, 65658 }, + { 0x18A5, 65664 }, + { 0x18A8, 65670 }, + { 0x18A3, 65676 }, + { 0x18A1, 65682 }, + { 0x189A, 65688 }, + { 0x189D, 65694 }, + { 0x18AA, 65700 }, + { 0x189B, 65706 }, + { 0x18A2, 65712 }, + { 0x189E, 65718 }, + { 0x18A4, 65724 }, + { 0x189F, 65730 }, + { 0x1877, 65736 }, + { 0x1809, 65740 }, + { 0x1808, 65744 }, + { 0x180A, 65747 }, + { 0x1801, 65749 }, + { 0x2029, 65751 }, + { 0x267E, 65753 }, + { 0x22D4, 65756 }, + { 0x2ADA, 65757 }, + { 0x2057, 65761 }, + { 0x2A0C, 65763 }, + { 0x0022, 65766 }, + { 0x2673, 65768 }, + { 0x2674, 65773 }, + { 0x2675, 65778 }, + { 0x2676, 65783 }, + { 0x2677, 65788 }, + { 0x2678, 65793 }, + { 0x2679, 65798 }, + { 0x267A, 65803 }, + { 0x203B, 65808 }, + { 0x2A3D, 65810 }, + { 0x003B, 65813 }, + { 0x2744, 65814 }, + { 0x2222, 65815 }, + { 0x29A1, 65817 }, + { 0x29A0, 65821 }, + { 0x2081, 65825 }, + { 0x2086, 65827 }, + { 0x2082, 65829 }, + { 0x2085, 65831 }, + { 0x2084, 65833 }, + { 0x208D, 65835 }, + { 0x2089, 65838 }, + { 0x208A, 65840 }, + { 0x2080, 65843 }, + { 0x2088, 65845 }, + { 0x208B, 65847 }, + { 0x208E, 65849 }, + { 0x2087, 65852 }, + { 0x2083, 65854 }, + { 0x208C, 65856 }, + { 0x23B2, 65859 }, + { 0x2A0B, 65861 }, + { 0x23B3, 65864 }, + { 0x1BAA, 65866 }, + { 0x1B80, 65869 }, + { 0x1B81, 65872 }, + { 0x1B82, 65875 }, + { 0x1BB1, 65878 }, + { 0x1BB6, 65881 }, + { 0x1BB2, 65884 }, + { 0x1BB5, 65887 }, + { 0x1BB4, 65890 }, + { 0x1BB9, 65893 }, + { 0x1BB0, 65896 }, + { 0x1BB8, 65899 }, + { 0x1BB7, 65902 }, + { 0x1BB3, 65905 }, + { 0x1BA8, 65908 }, + { 0x1BA5, 65912 }, + { 0x1BA4, 65916 }, + { 0x1BA7, 65920 }, + { 0x1BA6, 65924 }, + { 0x1BA9, 65928 }, + { 0x1B83, 65932 }, + { 0x1B88, 65935 }, + { 0x1B84, 65938 }, + { 0x1B87, 65941 }, + { 0x1B85, 65944 }, + { 0x1B86, 65947 }, + { 0x1B98, 65950 }, + { 0x1B8E, 65953 }, + { 0x1B93, 65956 }, + { 0x1B89, 65959 }, + { 0x1B96, 65962 }, + { 0x1B8C, 65965 }, + { 0x1BA0, 65968 }, + { 0x1B8F, 65971 }, + { 0x1B8A, 65974 }, + { 0x1B9C, 65977 }, + { 0x1B99, 65980 }, + { 0x1B94, 65983 }, + { 0x1B95, 65986 }, + { 0x1B8B, 65989 }, + { 0x1B9B, 65992 }, + { 0x1B9E, 65995 }, + { 0x1B92, 65998 }, + { 0x1B97, 66001 }, + { 0x1B9D, 66004 }, + { 0x1B9F, 66007 }, + { 0x1B9A, 66010 }, + { 0x1B90, 66013 }, + { 0x1BAE, 66016 }, + { 0x1B8D, 66019 }, + { 0x1B91, 66022 }, + { 0x1BAF, 66025 }, + { 0x1BA3, 66028 }, + { 0x1BA2, 66032 }, + { 0x1BA1, 66036 }, + { 0x2121, 66040 }, + { 0x2706, 66042 }, + { 0x2315, 66045 }, + { 0x9353, 66047 }, + { 0x931D, 66052 }, + { 0x932D, 66055 }, + { 0x9323, 66060 }, + { 0x931C, 66064 }, + { 0x9307, 66067 }, + { 0x9343, 66071 }, + { 0x932F, 66074 }, + { 0x9346, 66079 }, + { 0x9308, 66082 }, + { 0x9314, 66085 }, + { 0x9331, 66088 }, + { 0x933B, 66091 }, + { 0x9344, 66094 }, + { 0x930C, 66097 }, + { 0x9306, 66100 }, + { 0x9321, 66103 }, + { 0x933D, 66106 }, + { 0x9320, 66110 }, + { 0x9336, 66113 }, + { 0x9325, 66116 }, + { 0x932A, 66119 }, + { 0x9335, 66122 }, + { 0x9319, 66125 }, + { 0x9309, 66128 }, + { 0x934F, 66131 }, + { 0x9315, 66134 }, + { 0x9349, 66137 }, + { 0x9350, 66140 }, + { 0x9316, 66143 }, + { 0x930A, 66147 }, + { 0x9327, 66151 }, + { 0x9340, 66154 }, + { 0x9339, 66157 }, + { 0x9324, 66160 }, + { 0x9334, 66163 }, + { 0x931A, 66166 }, + { 0x9345, 66169 }, + { 0x9317, 66172 }, + { 0x933A, 66175 }, + { 0x932B, 66178 }, + { 0x934D, 66181 }, + { 0x9312, 66184 }, + { 0x932E, 66187 }, + { 0x934C, 66190 }, + { 0x9329, 66193 }, + { 0x9337, 66196 }, + { 0x930E, 66201 }, + { 0x9326, 66205 }, + { 0x9338, 66208 }, + { 0x9348, 66211 }, + { 0x9347, 66214 }, + { 0x931F, 66217 }, + { 0x9318, 66220 }, + { 0x9356, 66223 }, + { 0x9328, 66226 }, + { 0x933F, 66229 }, + { 0x9332, 66233 }, + { 0x9355, 66236 }, + { 0x932C, 66239 }, + { 0x934B, 66242 }, + { 0x934E, 66245 }, + { 0x9352, 66248 }, + { 0x931E, 66251 }, + { 0x9310, 66254 }, + { 0x9330, 66257 }, + { 0x934A, 66260 }, + { 0x930D, 66263 }, + { 0x931B, 66266 }, + { 0x9351, 66269 }, + { 0x930B, 66272 }, + { 0x9333, 66275 }, + { 0x933E, 66278 }, + { 0x9313, 66281 }, + { 0x9341, 66284 }, + { 0x9322, 66287 }, + { 0x9354, 66290 }, + { 0x933C, 66293 }, + { 0x9311, 66296 }, + { 0x930F, 66299 }, + { 0x9342, 66304 }, + { 0x2234, 66307 }, + { 0x2672, 66308 }, + { 0x26AF, 66311 }, + { 0x6E00, 66314 }, + { 0x6E01, 66316 }, + { 0x6E02, 66318 }, + { 0x6E03, 66320 }, + { 0x6E04, 66322 }, + { 0x6E05, 66324 }, + { 0x6E06, 66326 }, + { 0x6E07, 66328 }, + { 0x6E08, 66330 }, + { 0x6E09, 66332 }, + { 0x6E0A, 66334 }, + { 0x6E0B, 66336 }, + { 0x6E0C, 66338 }, + { 0x6E0D, 66340 }, + { 0x6E0E, 66342 }, + { 0x6E0F, 66344 }, + { 0xC100, 66346 }, + { 0xC101, 66348 }, + { 0xC102, 66350 }, + { 0xC103, 66352 }, + { 0xC104, 66354 }, + { 0xC105, 66356 }, + { 0xC106, 66358 }, + { 0xC107, 66360 }, + { 0xC108, 66362 }, + { 0xC109, 66364 }, + { 0xC10A, 66366 }, + { 0xC10B, 66368 }, + { 0xC10C, 66370 }, + { 0xC10D, 66372 }, + { 0xC10E, 66374 }, + { 0xC10F, 66376 }, + { 0xC110, 66378 }, + { 0xC111, 66380 }, + { 0xC112, 66382 }, + { 0xC113, 66384 }, + { 0xC114, 66386 }, + { 0xC115, 66388 }, + { 0xC116, 66390 }, + { 0xC117, 66392 }, + { 0xC118, 66394 }, + { 0xC119, 66396 }, + { 0xC11A, 66398 }, + { 0xC11B, 66400 }, + { 0xC11C, 66402 }, + { 0xC11D, 66404 }, + { 0xC11E, 66406 }, + { 0xC11F, 66408 }, + { 0xC120, 66410 }, + { 0xC121, 66412 }, + { 0xC122, 66414 }, + { 0xC123, 66416 }, + { 0xC124, 66418 }, + { 0xC125, 66420 }, + { 0xC126, 66422 }, + { 0xC127, 66424 }, + { 0xC128, 66426 }, + { 0xC129, 66428 }, + { 0xC12A, 66430 }, + { 0xC12B, 66432 }, + { 0xC12C, 66434 }, + { 0xC12D, 66436 }, + { 0xC12E, 66438 }, + { 0xC12F, 66440 }, + { 0xC130, 66442 }, + { 0xC131, 66444 }, + { 0xC132, 66446 }, + { 0xC133, 66448 }, + { 0xC134, 66450 }, + { 0xC135, 66452 }, + { 0xC136, 66454 }, + { 0xC137, 66456 }, + { 0xC138, 66458 }, + { 0xC139, 66460 }, + { 0xC13A, 66462 }, + { 0xC13B, 66464 }, + { 0xC13C, 66466 }, + { 0xC13D, 66468 }, + { 0xC13E, 66470 }, + { 0xC13F, 66472 }, + { 0xC140, 66474 }, + { 0xC141, 66476 }, + { 0xC142, 66478 }, + { 0xC143, 66480 }, + { 0xC144, 66482 }, + { 0xC145, 66484 }, + { 0xC146, 66486 }, + { 0xC147, 66488 }, + { 0xC148, 66490 }, + { 0xC149, 66492 }, + { 0xC14A, 66494 }, + { 0xC14B, 66496 }, + { 0xC14C, 66498 }, + { 0xC14D, 66500 }, + { 0xC14E, 66502 }, + { 0xC14F, 66504 }, + { 0xC150, 66506 }, + { 0xC151, 66508 }, + { 0xC152, 66510 }, + { 0xC153, 66512 }, + { 0xC154, 66514 }, + { 0xC155, 66516 }, + { 0xC156, 66518 }, + { 0xC157, 66520 }, + { 0xC158, 66522 }, + { 0xC159, 66524 }, + { 0xC15A, 66526 }, + { 0xC15B, 66528 }, + { 0xC15C, 66530 }, + { 0xC15D, 66532 }, + { 0xC15E, 66534 }, + { 0xC15F, 66536 }, + { 0xC160, 66538 }, + { 0xC161, 66540 }, + { 0xC162, 66542 }, + { 0xC163, 66544 }, + { 0xC164, 66546 }, + { 0xC165, 66548 }, + { 0xC166, 66550 }, + { 0xC167, 66552 }, + { 0xC168, 66554 }, + { 0xC169, 66556 }, + { 0xC16A, 66558 }, + { 0xC16B, 66560 }, + { 0xC16C, 66562 }, + { 0xC16D, 66564 }, + { 0xC16E, 66566 }, + { 0xC16F, 66568 }, + { 0xC170, 66570 }, + { 0xC171, 66572 }, + { 0xC172, 66574 }, + { 0xC173, 66576 }, + { 0xC174, 66578 }, + { 0xC175, 66580 }, + { 0xC176, 66582 }, + { 0xC177, 66584 }, + { 0xC178, 66586 }, + { 0xC179, 66588 }, + { 0xC17A, 66590 }, + { 0xC17B, 66592 }, + { 0xC17C, 66594 }, + { 0xC17D, 66596 }, + { 0xC17E, 66598 }, + { 0xC17F, 66600 }, + { 0xC180, 66602 }, + { 0xC181, 66604 }, + { 0xC182, 66606 }, + { 0xC183, 66608 }, + { 0xC184, 66610 }, + { 0xC185, 66612 }, + { 0xC186, 66614 }, + { 0xC187, 66616 }, + { 0xC188, 66618 }, + { 0xC189, 66620 }, + { 0xC18A, 66622 }, + { 0xC18B, 66624 }, + { 0xC18C, 66626 }, + { 0xC18D, 66628 }, + { 0xC18E, 66630 }, + { 0xC18F, 66632 }, + { 0xC190, 66634 }, + { 0xC191, 66636 }, + { 0xC192, 66638 }, + { 0xC193, 66640 }, + { 0xC194, 66642 }, + { 0xC195, 66644 }, + { 0xC196, 66646 }, + { 0xC197, 66648 }, + { 0xC198, 66650 }, + { 0xC199, 66652 }, + { 0xC19A, 66654 }, + { 0xC19B, 66656 }, + { 0xC19C, 66658 }, + { 0xC19D, 66660 }, + { 0xC19E, 66662 }, + { 0xC19F, 66664 }, + { 0xC1A0, 66666 }, + { 0xC1A1, 66668 }, + { 0xC1A2, 66670 }, + { 0xC1A3, 66672 }, + { 0xC1A4, 66674 }, + { 0xC1A5, 66676 }, + { 0xC1A6, 66678 }, + { 0xC1A7, 66680 }, + { 0xC1A8, 66682 }, + { 0xC1A9, 66684 }, + { 0xC1AA, 66686 }, + { 0xC1AB, 66688 }, + { 0xC1AC, 66690 }, + { 0xC1AD, 66692 }, + { 0xC1AE, 66694 }, + { 0xC1AF, 66696 }, + { 0xC1B0, 66698 }, + { 0xC1B1, 66700 }, + { 0xC1B2, 66702 }, + { 0xC1B3, 66704 }, + { 0xC1B4, 66706 }, + { 0xC1B5, 66708 }, + { 0xC1B6, 66710 }, + { 0xC1B7, 66712 }, + { 0xC1B8, 66714 }, + { 0xC1B9, 66716 }, + { 0xC1BA, 66718 }, + { 0xC1BB, 66720 }, + { 0xC1BC, 66722 }, + { 0xC1BD, 66724 }, + { 0xC1BE, 66726 }, + { 0xC1BF, 66728 }, + { 0xC1C0, 66730 }, + { 0xC1C1, 66732 }, + { 0xC1C2, 66734 }, + { 0xC1C3, 66736 }, + { 0xC1C4, 66738 }, + { 0xC1C5, 66740 }, + { 0xC1C6, 66742 }, + { 0xC1C7, 66744 }, + { 0xC1C8, 66746 }, + { 0xC1C9, 66748 }, + { 0xC1CA, 66750 }, + { 0xC1CB, 66752 }, + { 0xC1CC, 66754 }, + { 0xC1CD, 66756 }, + { 0xC1CE, 66758 }, + { 0xC1CF, 66760 }, + { 0xC1D0, 66762 }, + { 0xC1D1, 66764 }, + { 0xC1D2, 66766 }, + { 0xC1D3, 66768 }, + { 0xC1D4, 66770 }, + { 0xC1D5, 66772 }, + { 0xC1D6, 66774 }, + { 0xC1D7, 66776 }, + { 0xC1D8, 66778 }, + { 0xC1D9, 66780 }, + { 0xC1DA, 66782 }, + { 0xC1DB, 66784 }, + { 0xC1DC, 66786 }, + { 0xC1DD, 66788 }, + { 0xC1DE, 66790 }, + { 0xC1DF, 66792 }, + { 0xC1E0, 66794 }, + { 0xC1E1, 66796 }, + { 0xC1E2, 66798 }, + { 0xC1E3, 66800 }, + { 0xC1E4, 66802 }, + { 0xC1E5, 66804 }, + { 0xC1E6, 66806 }, + { 0xC1E7, 66808 }, + { 0xC1E8, 66810 }, + { 0xC1E9, 66812 }, + { 0xC1EA, 66814 }, + { 0xC1EB, 66816 }, + { 0xC1EC, 66818 }, + { 0xC1ED, 66820 }, + { 0xC1EE, 66822 }, + { 0xC1EF, 66824 }, + { 0x0027, 66826 }, + { 0x2250, 66827 }, + { 0x6E4E, 66830 }, + { 0x6E4A, 66833 }, + { 0x005E, 66835 }, + { 0x0040, 66837 }, + { 0x2052, 66839 }, + { 0x2201, 66842 }, + { 0x2381, 66843 }, + { 0x260B, 66846 }, + { 0x0950, 66848 }, + { 0x0971, 66850 }, + { 0x093C, 66855 }, + { 0x094D, 66858 }, + { 0x0903, 66861 }, + { 0x0902, 66864 }, + { 0x093D, 66867 }, + { 0x0901, 66870 }, + { 0x0954, 66873 }, + { 0x0964, 66876 }, + { 0x0967, 66878 }, + { 0x096C, 66881 }, + { 0x0968, 66884 }, + { 0x096B, 66887 }, + { 0x096A, 66890 }, + { 0x096F, 66893 }, + { 0x0966, 66896 }, + { 0x096E, 66899 }, + { 0x096D, 66902 }, + { 0x0969, 66905 }, + { 0x0953, 66908 }, + { 0x0947, 66911 }, + { 0x093F, 66915 }, + { 0x094B, 66919 }, + { 0x0941, 66923 }, + { 0x093E, 66927 }, + { 0x0948, 66931 }, + { 0x094C, 66935 }, + { 0x0940, 66939 }, + { 0x0942, 66943 }, + { 0x0946, 66947 }, + { 0x094A, 66952 }, + { 0x0945, 66957 }, + { 0x0949, 66962 }, + { 0x0962, 66967 }, + { 0x0943, 66972 }, + { 0x0963, 66977 }, + { 0x0944, 66982 }, + { 0x0965, 66987 }, + { 0x0905, 66990 }, + { 0x090F, 66993 }, + { 0x0907, 66996 }, + { 0x0913, 66999 }, + { 0x0909, 67002 }, + { 0x0906, 67005 }, + { 0x0910, 67008 }, + { 0x0914, 67011 }, + { 0x092C, 67014 }, + { 0x091A, 67017 }, + { 0x0926, 67020 }, + { 0x095E, 67023 }, + { 0x0917, 67026 }, + { 0x0939, 67029 }, + { 0x0908, 67032 }, + { 0x091C, 67035 }, + { 0x0915, 67038 }, + { 0x0932, 67041 }, + { 0x092E, 67044 }, + { 0x0928, 67047 }, + { 0x092A, 67050 }, + { 0x0958, 67053 }, + { 0x0930, 67056 }, + { 0x0938, 67059 }, + { 0x0924, 67062 }, + { 0x090A, 67065 }, + { 0x0935, 67068 }, + { 0x092F, 67071 }, + { 0x095B, 67074 }, + { 0x097F, 67077 }, + { 0x092D, 67080 }, + { 0x091B, 67083 }, + { 0x0921, 67086 }, + { 0x0927, 67089 }, + { 0x097B, 67092 }, + { 0x0918, 67095 }, + { 0x091D, 67098 }, + { 0x097C, 67101 }, + { 0x0916, 67104 }, + { 0x0933, 67107 }, + { 0x0919, 67110 }, + { 0x0923, 67113 }, + { 0x091E, 67116 }, + { 0x092B, 67119 }, + { 0x095D, 67122 }, + { 0x0931, 67125 }, + { 0x0936, 67128 }, + { 0x0937, 67131 }, + { 0x0925, 67134 }, + { 0x091F, 67137 }, + { 0x095F, 67140 }, + { 0x097E, 67143 }, + { 0x0922, 67146 }, + { 0x095A, 67149 }, + { 0x0959, 67152 }, + { 0x0934, 67155 }, + { 0x0929, 67158 }, + { 0x0920, 67161 }, + { 0x095C, 67164 }, + { 0x0904, 67167 }, + { 0x090E, 67171 }, + { 0x0912, 67175 }, + { 0x0972, 67179 }, + { 0x090D, 67183 }, + { 0x0911, 67187 }, + { 0x097D, 67191 }, + { 0x090C, 67195 }, + { 0x090B, 67199 }, + { 0x0961, 67203 }, + { 0x0960, 67207 }, + { 0x0951, 67211 }, + { 0x0952, 67215 }, + { 0x0970, 67219 }, + { 0x224F, 67222 }, + { 0x23E7, 67224 }, + { 0x224D, 67226 }, + { 0x2A78, 67228 }, + { 0x2C3B, 67233 }, + { 0x2C4A, 67237 }, + { 0x2C56, 67241 }, + { 0x2C53, 67245 }, + { 0x2C30, 67249 }, + { 0x2C58, 67253 }, + { 0x2C41, 67258 }, + { 0x2C49, 67262 }, + { 0x2C4E, 67266 }, + { 0x2C4C, 67270 }, + { 0x2C46, 67274 }, + { 0x2C31, 67278 }, + { 0x2C5A, 67282 }, + { 0x2C48, 67286 }, + { 0x2C39, 67290 }, + { 0x2C3D, 67294 }, + { 0x2C4B, 67298 }, + { 0x2C32, 67302 }, + { 0x2C51, 67306 }, + { 0x2C50, 67310 }, + { 0x2C4F, 67314 }, + { 0x2C34, 67318 }, + { 0x2C37, 67322 }, + { 0x2C47, 67326 }, + { 0x2C40, 67330 }, + { 0x2C43, 67334 }, + { 0x2C44, 67338 }, + { 0x2C54, 67342 }, + { 0x2C55, 67347 }, + { 0x2C35, 67354 }, + { 0x2C4D, 67358 }, + { 0x2C3C, 67362 }, + { 0x2C42, 67366 }, + { 0x2C45, 67370 }, + { 0x2C38, 67374 }, + { 0x2C33, 67378 }, + { 0x2C3A, 67382 }, + { 0x2C59, 67387 }, + { 0x2C57, 67393 }, + { 0x2C5B, 67399 }, + { 0x2C3E, 67403 }, + { 0x2C3F, 67407 }, + { 0x2C5C, 67411 }, + { 0x2C52, 67415 }, + { 0x2C36, 67420 }, + { 0x2C5E, 67424 }, + { 0x2C5D, 67429 }, + { 0x2C0B, 67434 }, + { 0x2C1A, 67438 }, + { 0x2C26, 67442 }, + { 0x2C23, 67446 }, + { 0x2C00, 67450 }, + { 0x2C28, 67454 }, + { 0x2C11, 67459 }, + { 0x2C19, 67463 }, + { 0x2C1E, 67467 }, + { 0x2C1C, 67471 }, + { 0x2C16, 67475 }, + { 0x2C01, 67479 }, + { 0x2C2A, 67483 }, + { 0x2C18, 67487 }, + { 0x2C09, 67491 }, + { 0x2C0D, 67495 }, + { 0x2C1B, 67499 }, + { 0x2C02, 67503 }, + { 0x2C21, 67507 }, + { 0x2C20, 67511 }, + { 0x2C1F, 67515 }, + { 0x2C04, 67519 }, + { 0x2C07, 67523 }, + { 0x2C17, 67527 }, + { 0x2C10, 67531 }, + { 0x2C13, 67535 }, + { 0x2C14, 67539 }, + { 0x2C24, 67543 }, + { 0x2C25, 67548 }, + { 0x2C05, 67555 }, + { 0x2C1D, 67559 }, + { 0x2C0C, 67563 }, + { 0x2C12, 67567 }, + { 0x2C15, 67571 }, + { 0x2C08, 67575 }, + { 0x2C03, 67579 }, + { 0x2C0A, 67583 }, + { 0x2C29, 67588 }, + { 0x2C27, 67594 }, + { 0x2C2B, 67600 }, + { 0x2C0E, 67604 }, + { 0x2C0F, 67608 }, + { 0x2C2C, 67612 }, + { 0x2C22, 67616 }, + { 0x2C06, 67621 }, + { 0x2C2E, 67625 }, + { 0x2C2D, 67630 }, + { 0x223B, 67635 }, + { 0x2015, 67636 }, + { 0x23AF, 67638 }, + { 0x26A9, 67641 }, + { 0x23BA, 67646 }, + { 0x23BB, 67649 }, + { 0x23BC, 67652 }, + { 0x23BD, 67655 }, + { 0x2B23, 67658 }, + { 0x2026, 67661 }, + { 0x238E, 67663 }, + { 0x29DC, 67665 }, + { 0x7A38, 67667 }, + { 0x7A3A, 67671 }, + { 0x7A39, 67675 }, + { 0x7A0D, 67678 }, + { 0x7A0F, 67683 }, + { 0x7A0E, 67686 }, + { 0x7A40, 67689 }, + { 0x7A41, 67692 }, + { 0x7A43, 67695 }, + { 0x7A42, 67698 }, + { 0x7A05, 67701 }, + { 0x7A01, 67705 }, + { 0x7A06, 67709 }, + { 0x7A02, 67713 }, + { 0x7A03, 67717 }, + { 0x7A0C, 67722 }, + { 0x7A00, 67726 }, + { 0x7A26, 67729 }, + { 0x7A15, 67732 }, + { 0x7A21, 67735 }, + { 0x7A12, 67738 }, + { 0x7A31, 67741 }, + { 0x7A17, 67744 }, + { 0x7A10, 67747 }, + { 0x7A2B, 67750 }, + { 0x7A28, 67753 }, + { 0x7A23, 67756 }, + { 0x7A24, 67759 }, + { 0x7A2A, 67762 }, + { 0x7A2F, 67765 }, + { 0x7A1F, 67768 }, + { 0x7A2C, 67771 }, + { 0x7A29, 67774 }, + { 0x7A30, 67777 }, + { 0x7A27, 67780 }, + { 0x7A16, 67783 }, + { 0x7A1C, 67786 }, + { 0x7A22, 67789 }, + { 0x7A13, 67792 }, + { 0x7A11, 67795 }, + { 0x7A32, 67798 }, + { 0x7A1E, 67801 }, + { 0x7A19, 67804 }, + { 0x7A25, 67807 }, + { 0x7A2D, 67810 }, + { 0x7A2E, 67813 }, + { 0x7A20, 67816 }, + { 0x7A1A, 67819 }, + { 0x7A1D, 67822 }, + { 0x7A1B, 67825 }, + { 0x7A33, 67828 }, + { 0x7A46, 67831 }, + { 0x7A47, 67835 }, + { 0x7A44, 67839 }, + { 0x7A45, 67842 }, + { 0x7A3F, 67845 }, + { 0x7A50, 67847 }, + { 0x7A56, 67850 }, + { 0x7A58, 67853 }, + { 0x7A55, 67856 }, + { 0x7A51, 67859 }, + { 0x7A52, 67863 }, + { 0x7A57, 67866 }, + { 0x7A53, 67870 }, + { 0x7A54, 67874 }, + { 0x238D, 67877 }, + { 0x2ADD, 67879 }, + { 0x260D, 67880 }, + { 0x1736, 67881 }, + { 0x1735, 67884 }, + { 0x791F, 67887 }, + { 0x7904, 67890 }, + { 0x7910, 67893 }, + { 0x790F, 67896 }, + { 0x7900, 67899 }, + { 0x7901, 67902 }, + { 0x7907, 67905 }, + { 0x790A, 67908 }, + { 0x790C, 67911 }, + { 0x790D, 67914 }, + { 0x7912, 67917 }, + { 0x7915, 67920 }, + { 0x7908, 67923 }, + { 0x7905, 67926 }, + { 0x7909, 67929 }, + { 0x7906, 67932 }, + { 0x7903, 67935 }, + { 0x7902, 67938 }, + { 0x790B, 67941 }, + { 0x7913, 67944 }, + { 0x7911, 67947 }, + { 0x790E, 67950 }, + { 0x7914, 67953 }, + { 0x7916, 67956 }, + { 0x7919, 67959 }, + { 0x7917, 67963 }, + { 0x7918, 67966 }, + { 0x00B1, 67969 }, + { 0x2305, 67971 }, + { 0x2237, 67972 }, + { 0x2A16, 67973 }, + { 0x225F, 67976 }, + { 0x00AE, 67979 }, + { 0x2938, 67981 }, + { 0x21A0, 67985 }, + { 0x219D, 67989 }, + { 0x2192, 67992 }, + { 0x21E5, 67994 }, + { 0x291E, 67998 }, + { 0x21A6, 68003 }, + { 0x2920, 68007 }, + { 0x21C4, 68014 }, + { 0x2B0F, 68019 }, + { 0x2B0E, 68024 }, + { 0x21AA, 68029 }, + { 0x21AC, 68033 }, + { 0x2945, 68037 }, + { 0x21A3, 68042 }, + { 0x2915, 68046 }, + { 0x2914, 68054 }, + { 0x21B4, 68061 }, + { 0x2911, 68066 }, + { 0x21FB, 68071 }, + { 0x219B, 68077 }, + { 0x21F8, 68081 }, + { 0x2942, 68086 }, + { 0x2974, 68092 }, + { 0x2975, 68097 }, + { 0x2B4C, 68103 }, + { 0x2B48, 68109 }, + { 0x2947, 68116 }, + { 0x2B44, 68120 }, + { 0x2B43, 68124 }, + { 0x21E8, 68128 }, + { 0x21F0, 68131 }, + { 0x21E2, 68136 }, + { 0x290D, 68139 }, + { 0x21D2, 68143 }, + { 0x2907, 68146 }, + { 0x21CF, 68151 }, + { 0x2903, 68156 }, + { 0x291C, 68162 }, + { 0x21C9, 68165 }, + { 0x290F, 68168 }, + { 0x21DB, 68172 }, + { 0x21CC, 68175 }, + { 0x2953, 68180 }, + { 0x295B, 68187 }, + { 0x296C, 68194 }, + { 0x2968, 68202 }, + { 0x2964, 68213 }, + { 0x2957, 68224 }, + { 0x295F, 68231 }, + { 0x2969, 68238 }, + { 0x296D, 68249 }, + { 0x21C0, 68257 }, + { 0x21C1, 68262 }, + { 0x21DD, 68267 }, + { 0x2B46, 68270 }, + { 0x291A, 68273 }, + { 0x2905, 68275 }, + { 0x2916, 68280 }, + { 0x2918, 68285 }, + { 0x2917, 68294 }, + { 0x2901, 68302 }, + { 0x2900, 68309 }, + { 0x2910, 68315 }, + { 0x21FE, 68320 }, + { 0x58C4, 68323 }, + { 0x5881, 68326 }, + { 0x5880, 68329 }, + { 0x58CE, 68332 }, + { 0x58D1, 68334 }, + { 0x58D6, 68337 }, + { 0x58D2, 68340 }, + { 0x58D5, 68343 }, + { 0x58D4, 68346 }, + { 0x58D9, 68349 }, + { 0x58D0, 68352 }, + { 0x58D8, 68355 }, + { 0x58D7, 68358 }, + { 0x58D3, 68361 }, + { 0x58BE, 68364 }, + { 0x58B6, 68368 }, + { 0x58C1, 68372 }, + { 0x58B8, 68376 }, + { 0x58B5, 68380 }, + { 0x58C0, 68384 }, + { 0x58C3, 68388 }, + { 0x58BF, 68392 }, + { 0x58B7, 68396 }, + { 0x58C2, 68400 }, + { 0x58B9, 68404 }, + { 0x58BC, 68408 }, + { 0x58BA, 68413 }, + { 0x58BD, 68418 }, + { 0x58BB, 68423 }, + { 0x58CF, 68428 }, + { 0x5882, 68431 }, + { 0x588C, 68434 }, + { 0x5884, 68437 }, + { 0x588F, 68440 }, + { 0x5886, 68443 }, + { 0x5883, 68446 }, + { 0x588E, 68449 }, + { 0x5891, 68452 }, + { 0x58A8, 68455 }, + { 0x5897, 68458 }, + { 0x58A3, 68461 }, + { 0x588D, 68464 }, + { 0x5894, 68467 }, + { 0x58B2, 68470 }, + { 0x5885, 68473 }, + { 0x5899, 68476 }, + { 0x5892, 68479 }, + { 0x58AD, 68482 }, + { 0x58AA, 68485 }, + { 0x58A5, 68488 }, + { 0x5890, 68491 }, + { 0x58A6, 68494 }, + { 0x58AC, 68497 }, + { 0x58B1, 68500 }, + { 0x58A1, 68503 }, + { 0x5887, 68506 }, + { 0x58AE, 68509 }, + { 0x58AB, 68512 }, + { 0x58A9, 68515 }, + { 0x5898, 68518 }, + { 0x589E, 68521 }, + { 0x58A4, 68524 }, + { 0x5895, 68527 }, + { 0x589A, 68530 }, + { 0x5893, 68533 }, + { 0x58B3, 68536 }, + { 0x5896, 68539 }, + { 0x58A0, 68542 }, + { 0x589B, 68545 }, + { 0x58A7, 68548 }, + { 0x58AF, 68551 }, + { 0x58B0, 68554 }, + { 0x58A2, 68557 }, + { 0x589C, 68560 }, + { 0x589F, 68563 }, + { 0x589D, 68566 }, + { 0x588A, 68569 }, + { 0x5888, 68573 }, + { 0x588B, 68577 }, + { 0x5889, 68581 }, + { 0x58B4, 68585 }, + { 0x2A32, 68589 }, + { 0x237D, 68594 }, + { 0x2006, 68597 }, + { 0x2023, 68599 }, + { 0x267F, 68601 }, + { 0x2387, 68603 }, + { 0x27AB, 68606 }, + { 0x2A10, 68611 }, + { 0x2384, 68613 }, + { 0x260C, 68615 }, + { 0x2258, 68616 }, + { 0x2334, 68618 }, + { 0x2335, 68619 }, + { 0x2A99, 68620 }, + { 0x2A9A, 68625 }, + { 0x2A9B, 68630 }, + { 0x2A9C, 68636 }, + { 0x2AF9, 68642 }, + { 0x2AFA, 68648 }, + { 0x225A, 68654 }, + { 0x0021, 68656 }, + { 0x2049, 68658 }, + { 0x2005, 68661 }, + { 0x2027, 68663 }, + { 0x3002, 68665 }, + { 0x303F, 68668 }, + { 0x3001, 68672 }, + { 0x302A, 68674 }, + { 0x3000, 68678 }, + { 0x3007, 68680 }, + { 0x302B, 68683 }, + { 0x3006, 68687 }, + { 0x302D, 68690 }, + { 0x302C, 68694 }, + { 0x3005, 68698 }, + { 0x3037, 68701 }, + { 0x33E0, 68707 }, + { 0x33E5, 68713 }, + { 0x33E9, 68719 }, + { 0x33E1, 68725 }, + { 0x33E4, 68731 }, + { 0x33E3, 68737 }, + { 0x33E8, 68743 }, + { 0x33E7, 68749 }, + { 0x33E6, 68755 }, + { 0x33E2, 68761 }, + { 0x33EA, 68767 }, + { 0x33FD, 68773 }, + { 0x33EB, 68779 }, + { 0x33F3, 68785 }, + { 0x33EE, 68791 }, + { 0x33EF, 68797 }, + { 0x33F1, 68803 }, + { 0x33ED, 68809 }, + { 0x33F2, 68815 }, + { 0x33EC, 68821 }, + { 0x33F0, 68827 }, + { 0x33FE, 68833 }, + { 0x33F4, 68839 }, + { 0x33F9, 68845 }, + { 0x33F5, 68851 }, + { 0x33F8, 68857 }, + { 0x33F7, 68863 }, + { 0x33FC, 68869 }, + { 0x33FB, 68875 }, + { 0x33FA, 68881 }, + { 0x33F6, 68887 }, + { 0x32C4, 68893 }, + { 0x3359, 68898 }, + { 0x335E, 68904 }, + { 0x3362, 68910 }, + { 0x335A, 68916 }, + { 0x335D, 68922 }, + { 0x335C, 68928 }, + { 0x3361, 68934 }, + { 0x3358, 68940 }, + { 0x3360, 68946 }, + { 0x335F, 68952 }, + { 0x335B, 68958 }, + { 0x3363, 68964 }, + { 0x3364, 68970 }, + { 0x336C, 68976 }, + { 0x3367, 68982 }, + { 0x3368, 68988 }, + { 0x336A, 68994 }, + { 0x3366, 69000 }, + { 0x336B, 69006 }, + { 0x3365, 69012 }, + { 0x3369, 69018 }, + { 0x336D, 69024 }, + { 0x336E, 69030 }, + { 0x3370, 69036 }, + { 0x336F, 69042 }, + { 0x32C6, 69048 }, + { 0x32C5, 69053 }, + { 0x32C3, 69058 }, + { 0x32C2, 69063 }, + { 0x32C7, 69068 }, + { 0x32C0, 69073 }, + { 0x32C9, 69078 }, + { 0x32CB, 69083 }, + { 0x32C1, 69088 }, + { 0x32CA, 69093 }, + { 0x32C8, 69098 }, + { 0x303E, 69103 }, + { 0x319F, 69106 }, + { 0x3192, 69110 }, + { 0x3196, 69114 }, + { 0x3193, 69118 }, + { 0x3195, 69122 }, + { 0x319E, 69126 }, + { 0x3199, 69130 }, + { 0x319B, 69134 }, + { 0x3194, 69138 }, + { 0x3198, 69142 }, + { 0x319C, 69146 }, + { 0x319D, 69150 }, + { 0x3197, 69154 }, + { 0x319A, 69158 }, + { 0x3190, 69162 }, + { 0x3191, 69166 }, + { 0x2FF4, 69170 }, + { 0x2FF0, 69175 }, + { 0x2FF2, 69181 }, + { 0x2FF1, 69189 }, + { 0x2FF3, 69195 }, + { 0x2FFB, 69203 }, + { 0x2FF7, 69207 }, + { 0x2FF5, 69213 }, + { 0x2FF6, 69219 }, + { 0x2FFA, 69225 }, + { 0x2FF8, 69232 }, + { 0x2FF9, 69239 }, + { 0x2139, 69246 }, + { 0x22BA, 69248 }, + { 0x6FF9, 69249 }, + { 0x6FFA, 69252 }, + { 0x6FFB, 69255 }, + { 0x26A4, 69258 }, + { 0x203D, 69263 }, + { 0x27AA, 69264 }, + { 0x2E0F, 69268 }, + { 0x3250, 69269 }, + { 0x2306, 69271 }, + { 0x2008, 69272 }, + { 0x2622, 69274 }, + { 0x6FFD, 69276 }, + { 0x2650, 69278 }, + { 0x26BA, 69279 }, + { 0x00B9, 69280 }, + { 0x2076, 69282 }, + { 0x00B2, 69284 }, + { 0x2075, 69286 }, + { 0x2074, 69288 }, + { 0x207D, 69290 }, + { 0x2079, 69293 }, + { 0x207A, 69295 }, + { 0x2070, 69298 }, + { 0x2078, 69300 }, + { 0x2071, 69302 }, + { 0x207F, 69307 }, + { 0x207B, 69312 }, + { 0x207E, 69314 }, + { 0x2077, 69317 }, + { 0x00B3, 69319 }, + { 0x207C, 69321 }, + { 0x2ADB, 69324 }, + { 0x25ED, 69326 }, + { 0x25EE, 69332 }, + { 0x214D, 69338 }, + { 0x2A3F, 69339 }, + { 0x060A, 69342 }, + { 0x0609, 69347 }, + { 0x0606, 69351 }, + { 0x0661, 69354 }, + { 0x0666, 69357 }, + { 0x0662, 69360 }, + { 0x0665, 69363 }, + { 0x0664, 69366 }, + { 0x0669, 69369 }, + { 0x0660, 69372 }, + { 0x0668, 69375 }, + { 0x0667, 69378 }, + { 0x0663, 69381 }, + { 0x0607, 69384 }, + { 0x212D, 69387 }, + { 0x210C, 69390 }, + { 0x2111, 69393 }, + { 0x211C, 69396 }, + { 0x2128, 69399 }, + { 0x232D, 69402 }, + { 0x29DF, 69403 }, + { 0x29F3, 69405 }, + { 0x29EF, 69408 }, + { 0x29F1, 69411 }, + { 0x29F2, 69414 }, + { 0x29EE, 69417 }, + { 0x29F0, 69420 }, + { 0x269C, 69423 }, + { 0x27AC, 69424 }, + { 0x2265, 69429 }, + { 0x2A7E, 69433 }, + { 0x2A82, 69438 }, + { 0x2A84, 69446 }, + { 0x2A80, 69455 }, + { 0x2277, 69463 }, + { 0x2273, 69466 }, + { 0x2A86, 69470 }, + { 0x2A8A, 69473 }, + { 0x2A88, 69477 }, + { 0x2269, 69483 }, + { 0x22E7, 69488 }, + { 0x2267, 69493 }, + { 0x003E, 69497 }, + { 0x22D7, 69499 }, + { 0x2A7A, 69502 }, + { 0x2A7C, 69506 }, + { 0x2A8E, 69511 }, + { 0x2A90, 69516 }, + { 0x2A94, 69521 }, + { 0x2A92, 69530 }, + { 0x2978, 69536 }, + { 0x2A8C, 69540 }, + { 0x22DB, 69546 }, + { 0x2AA5, 69551 }, + { 0x2AA7, 69554 }, + { 0x2AA9, 69558 }, + { 0x2AA4, 69565 }, + { 0x002D, 69568 }, + { 0x2E12, 69569 }, + { 0x2229, 69570 }, + { 0x2A40, 69571 }, + { 0x2A44, 69574 }, + { 0x2A43, 69578 }, + { 0x2A49, 69581 }, + { 0x2A47, 69586 }, + { 0x2A4B, 69589 }, + { 0x96E1, 69595 }, + { 0x96DF, 69599 }, + { 0x96E0, 69603 }, + { 0x97CF, 69607 }, + { 0x97D4, 69611 }, + { 0x97D0, 69615 }, + { 0x97D3, 69619 }, + { 0x97D2, 69623 }, + { 0x97D7, 69627 }, + { 0x97CE, 69631 }, + { 0x97D6, 69635 }, + { 0x97D5, 69639 }, + { 0x97D1, 69643 }, + { 0x96DE, 69647 }, + { 0x96C1, 69651 }, + { 0x941A, 69654 }, + { 0x941B, 69658 }, + { 0x941C, 69662 }, + { 0x941D, 69666 }, + { 0x941E, 69670 }, + { 0x941F, 69674 }, + { 0x9420, 69678 }, + { 0x9421, 69682 }, + { 0x9422, 69686 }, + { 0x9423, 69690 }, + { 0x9424, 69694 }, + { 0x9425, 69698 }, + { 0x9426, 69702 }, + { 0x9427, 69706 }, + { 0x9428, 69710 }, + { 0x9429, 69714 }, + { 0x942A, 69718 }, + { 0x942B, 69722 }, + { 0x942C, 69726 }, + { 0x942D, 69730 }, + { 0x942E, 69734 }, + { 0x942F, 69738 }, + { 0x9430, 69742 }, + { 0x9431, 69746 }, + { 0x9432, 69750 }, + { 0x9433, 69754 }, + { 0x96CD, 69758 }, + { 0x96CE, 69762 }, + { 0x96D1, 69766 }, + { 0x96CF, 69770 }, + { 0x96D8, 69774 }, + { 0x96C8, 69778 }, + { 0x96D7, 69782 }, + { 0x96D9, 69786 }, + { 0x96D2, 69790 }, + { 0x96D5, 69794 }, + { 0x96C3, 69798 }, + { 0x96CA, 69802 }, + { 0x96C7, 69806 }, + { 0x96C2, 69810 }, + { 0x96C5, 69814 }, + { 0x96D3, 69818 }, + { 0x96C4, 69823 }, + { 0x96CB, 69827 }, + { 0x96CC, 69831 }, + { 0x96DA, 69835 }, + { 0x96D4, 69839 }, + { 0x96C9, 69843 }, + { 0x97CB, 69847 }, + { 0x96C6, 69851 }, + { 0x96D0, 69855 }, + { 0x96D6, 69859 }, + { 0x96DD, 69863 }, + { 0x9755, 69867 }, + { 0x9753, 69872 }, + { 0x9754, 69877 }, + { 0x9752, 69882 }, + { 0x9735, 69887 }, + { 0x9482, 69891 }, + { 0x9483, 69896 }, + { 0x9484, 69901 }, + { 0x9485, 69906 }, + { 0x9486, 69911 }, + { 0x9487, 69916 }, + { 0x9488, 69921 }, + { 0x9489, 69926 }, + { 0x948A, 69931 }, + { 0x948B, 69936 }, + { 0x948C, 69941 }, + { 0x948D, 69946 }, + { 0x948E, 69951 }, + { 0x948F, 69956 }, + { 0x9490, 69961 }, + { 0x9491, 69966 }, + { 0x9492, 69971 }, + { 0x9493, 69976 }, + { 0x9494, 69981 }, + { 0x9495, 69986 }, + { 0x9496, 69991 }, + { 0x9497, 69996 }, + { 0x9498, 70001 }, + { 0x9499, 70006 }, + { 0x949A, 70011 }, + { 0x949B, 70016 }, + { 0x9741, 70021 }, + { 0x9742, 70026 }, + { 0x9745, 70031 }, + { 0x9743, 70036 }, + { 0x974C, 70041 }, + { 0x973C, 70046 }, + { 0x974B, 70051 }, + { 0x974D, 70056 }, + { 0x9746, 70061 }, + { 0x9749, 70066 }, + { 0x9737, 70071 }, + { 0x973E, 70076 }, + { 0x973B, 70081 }, + { 0x9736, 70086 }, + { 0x9739, 70091 }, + { 0x9747, 70096 }, + { 0x9738, 70102 }, + { 0x973F, 70107 }, + { 0x9740, 70112 }, + { 0x974E, 70117 }, + { 0x9748, 70122 }, + { 0x973D, 70127 }, + { 0x973A, 70132 }, + { 0x9744, 70137 }, + { 0x974A, 70142 }, + { 0x9751, 70147 }, + { 0x9468, 70152 }, + { 0x9469, 70157 }, + { 0x946A, 70162 }, + { 0x946B, 70167 }, + { 0x946C, 70172 }, + { 0x946D, 70177 }, + { 0x946E, 70182 }, + { 0x946F, 70187 }, + { 0x9470, 70192 }, + { 0x9471, 70197 }, + { 0x9472, 70202 }, + { 0x9473, 70207 }, + { 0x9474, 70212 }, + { 0x9475, 70217 }, + { 0x9476, 70222 }, + { 0x9477, 70227 }, + { 0x9478, 70232 }, + { 0x9479, 70237 }, + { 0x947A, 70242 }, + { 0x947B, 70247 }, + { 0x947C, 70252 }, + { 0x947D, 70257 }, + { 0x947E, 70262 }, + { 0x947F, 70267 }, + { 0x9480, 70272 }, + { 0x9481, 70277 }, + { 0x9727, 70282 }, + { 0x9728, 70287 }, + { 0x972B, 70292 }, + { 0x9729, 70297 }, + { 0x9732, 70302 }, + { 0x9722, 70307 }, + { 0x9731, 70312 }, + { 0x9733, 70317 }, + { 0x972C, 70322 }, + { 0x972F, 70327 }, + { 0x971D, 70332 }, + { 0x9724, 70337 }, + { 0x9721, 70342 }, + { 0x971C, 70347 }, + { 0x971F, 70352 }, + { 0x971E, 70357 }, + { 0x9725, 70362 }, + { 0x9726, 70367 }, + { 0x9734, 70372 }, + { 0x972E, 70377 }, + { 0x9723, 70382 }, + { 0x972D, 70387 }, + { 0x9720, 70393 }, + { 0x972A, 70398 }, + { 0x9730, 70403 }, + { 0x9750, 70408 }, + { 0x974F, 70413 }, + { 0x94EA, 70418 }, + { 0x94EB, 70423 }, + { 0x94EC, 70428 }, + { 0x94ED, 70433 }, + { 0x94EE, 70438 }, + { 0x94EF, 70443 }, + { 0x94F0, 70448 }, + { 0x94F1, 70453 }, + { 0x94F2, 70458 }, + { 0x94F3, 70463 }, + { 0x94F4, 70468 }, + { 0x94F5, 70473 }, + { 0x94F6, 70478 }, + { 0x94F7, 70483 }, + { 0x94F8, 70488 }, + { 0x94F9, 70493 }, + { 0x94FA, 70498 }, + { 0x94FB, 70503 }, + { 0x94FC, 70508 }, + { 0x94FD, 70513 }, + { 0x94FE, 70518 }, + { 0x94FF, 70523 }, + { 0x9500, 70528 }, + { 0x9501, 70533 }, + { 0x9502, 70538 }, + { 0x9503, 70543 }, + { 0x94D0, 70548 }, + { 0x94D1, 70553 }, + { 0x94D2, 70558 }, + { 0x94D3, 70563 }, + { 0x94D4, 70568 }, + { 0x94D5, 70573 }, + { 0x94D6, 70578 }, + { 0x94D7, 70583 }, + { 0x94D8, 70588 }, + { 0x94D9, 70593 }, + { 0x94DA, 70598 }, + { 0x94DB, 70603 }, + { 0x94DC, 70608 }, + { 0x94DD, 70613 }, + { 0x94DE, 70618 }, + { 0x94DF, 70623 }, + { 0x94E0, 70628 }, + { 0x94E1, 70633 }, + { 0x94E2, 70638 }, + { 0x94E3, 70643 }, + { 0x94E4, 70648 }, + { 0x94E5, 70653 }, + { 0x94E6, 70658 }, + { 0x94E7, 70663 }, + { 0x94E8, 70668 }, + { 0x94E9, 70673 }, + { 0x9400, 70678 }, + { 0x9401, 70682 }, + { 0x9402, 70686 }, + { 0x9403, 70690 }, + { 0x9404, 70694 }, + { 0x9405, 70698 }, + { 0x9406, 70702 }, + { 0x9407, 70706 }, + { 0x9408, 70710 }, + { 0x9409, 70714 }, + { 0x940A, 70718 }, + { 0x940B, 70722 }, + { 0x940C, 70726 }, + { 0x940D, 70730 }, + { 0x940E, 70734 }, + { 0x940F, 70738 }, + { 0x9410, 70742 }, + { 0x9411, 70746 }, + { 0x9412, 70750 }, + { 0x9413, 70754 }, + { 0x9414, 70758 }, + { 0x9415, 70762 }, + { 0x9416, 70766 }, + { 0x9417, 70770 }, + { 0x9418, 70774 }, + { 0x9419, 70778 }, + { 0x96B3, 70782 }, + { 0x96B4, 70786 }, + { 0x96B7, 70790 }, + { 0x96B5, 70794 }, + { 0x96BE, 70798 }, + { 0x96AE, 70802 }, + { 0x96BD, 70806 }, + { 0x96BF, 70810 }, + { 0x96B8, 70814 }, + { 0x96BB, 70818 }, + { 0x96A9, 70822 }, + { 0x96B0, 70826 }, + { 0x96AD, 70830 }, + { 0x96A8, 70834 }, + { 0x96AB, 70838 }, + { 0x96AA, 70842 }, + { 0x96B1, 70846 }, + { 0x96B2, 70850 }, + { 0x96C0, 70854 }, + { 0x96BA, 70858 }, + { 0x96AF, 70862 }, + { 0x96B9, 70866 }, + { 0x97CA, 70871 }, + { 0x96AC, 70875 }, + { 0x96B6, 70879 }, + { 0x96BC, 70883 }, + { 0x96DC, 70887 }, + { 0x9586, 70891 }, + { 0x9587, 70896 }, + { 0x9588, 70901 }, + { 0x9589, 70906 }, + { 0x958A, 70911 }, + { 0x958B, 70916 }, + { 0x958C, 70921 }, + { 0x958D, 70926 }, + { 0x958E, 70931 }, + { 0x958F, 70936 }, + { 0x9590, 70941 }, + { 0x9591, 70946 }, + { 0x9592, 70951 }, + { 0x9593, 70956 }, + { 0x9594, 70961 }, + { 0x9595, 70966 }, + { 0x9596, 70971 }, + { 0x9597, 70976 }, + { 0x9598, 70981 }, + { 0x9599, 70986 }, + { 0x959A, 70991 }, + { 0x959B, 70996 }, + { 0x959C, 71001 }, + { 0x959D, 71006 }, + { 0x959E, 71011 }, + { 0x959F, 71016 }, + { 0x956C, 71021 }, + { 0x956D, 71026 }, + { 0x956E, 71031 }, + { 0x956F, 71036 }, + { 0x9570, 71041 }, + { 0x9571, 71046 }, + { 0x9572, 71051 }, + { 0x9573, 71056 }, + { 0x9574, 71061 }, + { 0x9575, 71066 }, + { 0x9576, 71071 }, + { 0x9577, 71076 }, + { 0x9578, 71081 }, + { 0x9579, 71086 }, + { 0x957A, 71091 }, + { 0x957B, 71096 }, + { 0x957C, 71101 }, + { 0x957D, 71106 }, + { 0x957E, 71111 }, + { 0x957F, 71116 }, + { 0x9580, 71121 }, + { 0x9581, 71126 }, + { 0x9582, 71131 }, + { 0x9583, 71136 }, + { 0x9584, 71141 }, + { 0x9585, 71146 }, + { 0x96DB, 71151 }, + { 0x27E8, 71155 }, + { 0x27E6, 71159 }, + { 0x27EC, 71164 }, + { 0x27EA, 71170 }, + { 0x27EE, 71175 }, + { 0x27E9, 71179 }, + { 0x27E7, 71183 }, + { 0x27ED, 71188 }, + { 0x27EB, 71194 }, + { 0x27EF, 71199 }, + { 0x971B, 71203 }, + { 0x9719, 71207 }, + { 0x971A, 71211 }, + { 0x9718, 71215 }, + { 0x96FB, 71219 }, + { 0x944E, 71222 }, + { 0x944F, 71226 }, + { 0x9450, 71230 }, + { 0x9451, 71234 }, + { 0x9452, 71238 }, + { 0x9453, 71242 }, + { 0x9454, 71246 }, + { 0x9456, 71250 }, + { 0x9457, 71254 }, + { 0x9458, 71258 }, + { 0x9459, 71262 }, + { 0x945A, 71266 }, + { 0x945B, 71270 }, + { 0x945C, 71274 }, + { 0x945D, 71278 }, + { 0x945E, 71282 }, + { 0x945F, 71286 }, + { 0x9460, 71290 }, + { 0x9461, 71294 }, + { 0x9462, 71298 }, + { 0x9463, 71302 }, + { 0x9464, 71306 }, + { 0x9465, 71310 }, + { 0x9466, 71314 }, + { 0x9467, 71318 }, + { 0x9707, 71322 }, + { 0x9708, 71326 }, + { 0x970B, 71330 }, + { 0x9709, 71334 }, + { 0x9712, 71338 }, + { 0x9702, 71342 }, + { 0x9711, 71346 }, + { 0x9713, 71350 }, + { 0x970C, 71354 }, + { 0x970F, 71358 }, + { 0x96FD, 71362 }, + { 0x9704, 71366 }, + { 0x9701, 71370 }, + { 0x96FC, 71374 }, + { 0x96FF, 71378 }, + { 0x970D, 71382 }, + { 0x96FE, 71387 }, + { 0x9705, 71391 }, + { 0x9706, 71395 }, + { 0x9714, 71399 }, + { 0x970E, 71403 }, + { 0x9703, 71407 }, + { 0x96A4, 71411 }, + { 0x96A5, 71416 }, + { 0x9700, 71421 }, + { 0x970A, 71425 }, + { 0x9710, 71429 }, + { 0x9717, 71433 }, + { 0x9434, 71437 }, + { 0x9435, 71441 }, + { 0x9436, 71445 }, + { 0x9437, 71449 }, + { 0x9438, 71453 }, + { 0x9439, 71457 }, + { 0x943A, 71461 }, + { 0x943B, 71465 }, + { 0x943C, 71469 }, + { 0x943D, 71473 }, + { 0x943E, 71477 }, + { 0x943F, 71481 }, + { 0x9440, 71485 }, + { 0x9441, 71489 }, + { 0x9442, 71493 }, + { 0x9443, 71497 }, + { 0x9444, 71501 }, + { 0x9445, 71505 }, + { 0x9446, 71509 }, + { 0x9447, 71513 }, + { 0x9448, 71517 }, + { 0x9449, 71521 }, + { 0x944A, 71525 }, + { 0x944B, 71529 }, + { 0x944C, 71533 }, + { 0x944D, 71537 }, + { 0x96ED, 71541 }, + { 0x96EE, 71545 }, + { 0x96F1, 71549 }, + { 0x96EF, 71553 }, + { 0x96F8, 71557 }, + { 0x96E8, 71561 }, + { 0x96F7, 71565 }, + { 0x96F9, 71569 }, + { 0x96F2, 71573 }, + { 0x96F5, 71577 }, + { 0x96E3, 71581 }, + { 0x96EA, 71585 }, + { 0x96E7, 71589 }, + { 0x96E2, 71593 }, + { 0x96E5, 71597 }, + { 0x96E4, 71601 }, + { 0x96EB, 71605 }, + { 0x96EC, 71609 }, + { 0x96FA, 71613 }, + { 0x96F4, 71617 }, + { 0x96E9, 71621 }, + { 0x96F3, 71625 }, + { 0x96E6, 71630 }, + { 0x96F0, 71634 }, + { 0x96F6, 71638 }, + { 0x9716, 71642 }, + { 0x9715, 71646 }, + { 0x94B6, 71650 }, + { 0x94B7, 71654 }, + { 0x94B8, 71658 }, + { 0x94B9, 71662 }, + { 0x94BB, 71666 }, + { 0x94BD, 71670 }, + { 0x94BE, 71674 }, + { 0x94BF, 71678 }, + { 0x94C0, 71682 }, + { 0x94C1, 71686 }, + { 0x94C2, 71690 }, + { 0x94C3, 71694 }, + { 0x94C5, 71698 }, + { 0x94C6, 71702 }, + { 0x94C7, 71706 }, + { 0x94C8, 71710 }, + { 0x94C9, 71714 }, + { 0x94CA, 71718 }, + { 0x94CB, 71722 }, + { 0x94CC, 71726 }, + { 0x94CD, 71730 }, + { 0x94CE, 71734 }, + { 0x94CF, 71738 }, + { 0x949C, 71742 }, + { 0x949E, 71746 }, + { 0x949F, 71750 }, + { 0x94A2, 71754 }, + { 0x94A5, 71758 }, + { 0x94A6, 71762 }, + { 0x94A9, 71766 }, + { 0x94AA, 71770 }, + { 0x94AB, 71774 }, + { 0x94AC, 71778 }, + { 0x94AE, 71782 }, + { 0x94AF, 71786 }, + { 0x94B0, 71790 }, + { 0x94B1, 71794 }, + { 0x94B2, 71798 }, + { 0x94B3, 71802 }, + { 0x94B4, 71806 }, + { 0x94B5, 71810 }, + { 0x951E, 71814 }, + { 0x951F, 71818 }, + { 0x9520, 71822 }, + { 0x9521, 71826 }, + { 0x9522, 71830 }, + { 0x9523, 71834 }, + { 0x9524, 71838 }, + { 0x9525, 71842 }, + { 0x9526, 71846 }, + { 0x9527, 71850 }, + { 0x9528, 71854 }, + { 0x9529, 71858 }, + { 0x952A, 71862 }, + { 0x952B, 71866 }, + { 0x952C, 71870 }, + { 0x952D, 71874 }, + { 0x952E, 71878 }, + { 0x952F, 71882 }, + { 0x9530, 71886 }, + { 0x9531, 71890 }, + { 0x9532, 71894 }, + { 0x9533, 71898 }, + { 0x9534, 71902 }, + { 0x9535, 71906 }, + { 0x9536, 71910 }, + { 0x9537, 71914 }, + { 0x9504, 71918 }, + { 0x9505, 71922 }, + { 0x9507, 71926 }, + { 0x9508, 71930 }, + { 0x9509, 71934 }, + { 0x950A, 71938 }, + { 0x950D, 71942 }, + { 0x950E, 71946 }, + { 0x950F, 71950 }, + { 0x9510, 71954 }, + { 0x9511, 71958 }, + { 0x9512, 71962 }, + { 0x9513, 71966 }, + { 0x9514, 71970 }, + { 0x9516, 71974 }, + { 0x9517, 71978 }, + { 0x9518, 71982 }, + { 0x9519, 71986 }, + { 0x951A, 71990 }, + { 0x951B, 71994 }, + { 0x951C, 71998 }, + { 0x97F7, 72002 }, + { 0x97FC, 72006 }, + { 0x97F8, 72010 }, + { 0x97FB, 72014 }, + { 0x97FA, 72018 }, + { 0x97FF, 72022 }, + { 0x97F6, 72026 }, + { 0x97FE, 72030 }, + { 0x97FD, 72034 }, + { 0x97F9, 72038 }, + { 0x968A, 72042 }, + { 0x968B, 72046 }, + { 0x968C, 72050 }, + { 0x968D, 72054 }, + { 0x968E, 72058 }, + { 0x968F, 72062 }, + { 0x9690, 72066 }, + { 0x9691, 72070 }, + { 0x9692, 72074 }, + { 0x9693, 72078 }, + { 0x9694, 72082 }, + { 0x9695, 72086 }, + { 0x9696, 72090 }, + { 0x9697, 72094 }, + { 0x9698, 72098 }, + { 0x9699, 72102 }, + { 0x969A, 72106 }, + { 0x969B, 72110 }, + { 0x969C, 72114 }, + { 0x969D, 72118 }, + { 0x969E, 72122 }, + { 0x969F, 72126 }, + { 0x96A0, 72130 }, + { 0x96A1, 72134 }, + { 0x96A2, 72138 }, + { 0x96A3, 72142 }, + { 0x9670, 72146 }, + { 0x9671, 72150 }, + { 0x9672, 72154 }, + { 0x9673, 72158 }, + { 0x9674, 72162 }, + { 0x9675, 72166 }, + { 0x9676, 72170 }, + { 0x9677, 72174 }, + { 0x9678, 72178 }, + { 0x9679, 72182 }, + { 0x967A, 72186 }, + { 0x967B, 72190 }, + { 0x967C, 72194 }, + { 0x967D, 72198 }, + { 0x967E, 72202 }, + { 0x967F, 72206 }, + { 0x9680, 72210 }, + { 0x9681, 72214 }, + { 0x9682, 72218 }, + { 0x9683, 72222 }, + { 0x9684, 72226 }, + { 0x9685, 72230 }, + { 0x9686, 72234 }, + { 0x9687, 72238 }, + { 0x9688, 72242 }, + { 0x9689, 72246 }, + { 0x978F, 72250 }, + { 0x978D, 72255 }, + { 0x978E, 72260 }, + { 0x97ED, 72265 }, + { 0x97F2, 72270 }, + { 0x97EE, 72275 }, + { 0x97F1, 72280 }, + { 0x97F0, 72285 }, + { 0x97F5, 72290 }, + { 0x97EC, 72295 }, + { 0x97F4, 72300 }, + { 0x97F3, 72305 }, + { 0x97EF, 72310 }, + { 0x978C, 72315 }, + { 0x976F, 72320 }, + { 0x95EE, 72324 }, + { 0x95EF, 72329 }, + { 0x95F0, 72334 }, + { 0x95F1, 72339 }, + { 0x95F2, 72344 }, + { 0x95F3, 72349 }, + { 0x95F4, 72354 }, + { 0x95F5, 72359 }, + { 0x95F6, 72364 }, + { 0x95F7, 72369 }, + { 0x95F8, 72374 }, + { 0x95F9, 72379 }, + { 0x95FA, 72384 }, + { 0x95FB, 72389 }, + { 0x95FC, 72394 }, + { 0x95FD, 72399 }, + { 0x95FE, 72404 }, + { 0x95FF, 72409 }, + { 0x9600, 72414 }, + { 0x9601, 72419 }, + { 0x9602, 72424 }, + { 0x9603, 72429 }, + { 0x9604, 72434 }, + { 0x9605, 72439 }, + { 0x9606, 72444 }, + { 0x9607, 72449 }, + { 0x977B, 72454 }, + { 0x977C, 72459 }, + { 0x977F, 72464 }, + { 0x977D, 72469 }, + { 0x9786, 72474 }, + { 0x9776, 72479 }, + { 0x9785, 72484 }, + { 0x9787, 72489 }, + { 0x9780, 72494 }, + { 0x9783, 72499 }, + { 0x9771, 72504 }, + { 0x9778, 72509 }, + { 0x9775, 72514 }, + { 0x9770, 72519 }, + { 0x9773, 72524 }, + { 0x9781, 72529 }, + { 0x9772, 72535 }, + { 0x9779, 72540 }, + { 0x977A, 72545 }, + { 0x9788, 72550 }, + { 0x9782, 72555 }, + { 0x9777, 72560 }, + { 0x9774, 72565 }, + { 0x977E, 72570 }, + { 0x9784, 72575 }, + { 0x978B, 72580 }, + { 0x97C9, 72585 }, + { 0x97C7, 72591 }, + { 0x97C8, 72597 }, + { 0x97C6, 72603 }, + { 0x97A9, 72609 }, + { 0x9656, 72614 }, + { 0x9657, 72620 }, + { 0x9658, 72626 }, + { 0x9659, 72632 }, + { 0x965A, 72638 }, + { 0x965B, 72644 }, + { 0x965C, 72650 }, + { 0x965D, 72656 }, + { 0x965E, 72662 }, + { 0x965F, 72668 }, + { 0x9660, 72674 }, + { 0x9661, 72680 }, + { 0x9662, 72686 }, + { 0x9663, 72692 }, + { 0x9664, 72698 }, + { 0x9665, 72704 }, + { 0x9666, 72710 }, + { 0x9667, 72716 }, + { 0x9668, 72722 }, + { 0x9669, 72728 }, + { 0x966A, 72734 }, + { 0x966B, 72740 }, + { 0x966C, 72746 }, + { 0x966D, 72752 }, + { 0x966E, 72758 }, + { 0x966F, 72764 }, + { 0x97B5, 72770 }, + { 0x97B6, 72776 }, + { 0x97B9, 72782 }, + { 0x97B7, 72788 }, + { 0x97C0, 72794 }, + { 0x97B0, 72800 }, + { 0x97BF, 72806 }, + { 0x97C1, 72812 }, + { 0x97BA, 72818 }, + { 0x97BD, 72824 }, + { 0x97AB, 72830 }, + { 0x97B2, 72836 }, + { 0x97AF, 72842 }, + { 0x97AA, 72848 }, + { 0x97AD, 72854 }, + { 0x97BB, 72860 }, + { 0x97AC, 72867 }, + { 0x97B3, 72873 }, + { 0x97B4, 72879 }, + { 0x97C2, 72885 }, + { 0x97BC, 72891 }, + { 0x97B1, 72897 }, + { 0x97AE, 72903 }, + { 0x97B8, 72909 }, + { 0x97BE, 72915 }, + { 0x97C5, 72921 }, + { 0x963C, 72927 }, + { 0x963D, 72933 }, + { 0x963E, 72939 }, + { 0x963F, 72945 }, + { 0x9640, 72951 }, + { 0x9641, 72957 }, + { 0x9642, 72963 }, + { 0x9643, 72969 }, + { 0x9644, 72975 }, + { 0x9645, 72981 }, + { 0x9646, 72987 }, + { 0x9647, 72993 }, + { 0x9648, 72999 }, + { 0x9649, 73005 }, + { 0x964A, 73011 }, + { 0x964B, 73017 }, + { 0x964C, 73023 }, + { 0x964D, 73029 }, + { 0x964E, 73035 }, + { 0x964F, 73041 }, + { 0x9650, 73047 }, + { 0x9651, 73053 }, + { 0x9652, 73059 }, + { 0x9653, 73065 }, + { 0x9654, 73071 }, + { 0x9655, 73077 }, + { 0x979B, 73083 }, + { 0x979C, 73089 }, + { 0x979F, 73095 }, + { 0x979D, 73101 }, + { 0x97A6, 73107 }, + { 0x9796, 73113 }, + { 0x97A5, 73119 }, + { 0x97A7, 73125 }, + { 0x97A0, 73131 }, + { 0x97A3, 73137 }, + { 0x9791, 73143 }, + { 0x9798, 73149 }, + { 0x9795, 73155 }, + { 0x9790, 73161 }, + { 0x9793, 73167 }, + { 0x9792, 73173 }, + { 0x9799, 73179 }, + { 0x979A, 73185 }, + { 0x97A8, 73191 }, + { 0x97A2, 73197 }, + { 0x9797, 73203 }, + { 0x97A1, 73209 }, + { 0x9794, 73216 }, + { 0x979E, 73222 }, + { 0x97A4, 73228 }, + { 0x97C4, 73234 }, + { 0x97C3, 73240 }, + { 0x95D4, 73246 }, + { 0x95D5, 73251 }, + { 0x95D6, 73256 }, + { 0x95D7, 73261 }, + { 0x95D8, 73266 }, + { 0x95D9, 73271 }, + { 0x95DA, 73276 }, + { 0x95DB, 73281 }, + { 0x95DC, 73286 }, + { 0x95DD, 73291 }, + { 0x95DE, 73296 }, + { 0x95DF, 73301 }, + { 0x95E0, 73306 }, + { 0x95E1, 73311 }, + { 0x95E2, 73316 }, + { 0x95E3, 73321 }, + { 0x95E4, 73326 }, + { 0x95E5, 73331 }, + { 0x95E6, 73336 }, + { 0x95E7, 73341 }, + { 0x95E8, 73346 }, + { 0x95E9, 73351 }, + { 0x95EA, 73356 }, + { 0x95EB, 73361 }, + { 0x95EC, 73366 }, + { 0x95ED, 73371 }, + { 0x9761, 73376 }, + { 0x9762, 73381 }, + { 0x9765, 73386 }, + { 0x9763, 73391 }, + { 0x976C, 73396 }, + { 0x975C, 73401 }, + { 0x976B, 73406 }, + { 0x976D, 73411 }, + { 0x9766, 73416 }, + { 0x9769, 73421 }, + { 0x9757, 73426 }, + { 0x975E, 73431 }, + { 0x975B, 73436 }, + { 0x9756, 73441 }, + { 0x9759, 73446 }, + { 0x9758, 73451 }, + { 0x975F, 73456 }, + { 0x9760, 73461 }, + { 0x976E, 73466 }, + { 0x9768, 73471 }, + { 0x975D, 73476 }, + { 0x9767, 73481 }, + { 0x975A, 73487 }, + { 0x9764, 73492 }, + { 0x976A, 73497 }, + { 0x978A, 73502 }, + { 0x9789, 73507 }, + { 0x97E3, 73512 }, + { 0x97E8, 73516 }, + { 0x97E4, 73520 }, + { 0x97E7, 73524 }, + { 0x97E6, 73528 }, + { 0x97EB, 73532 }, + { 0x97E2, 73536 }, + { 0x97EA, 73540 }, + { 0x97E9, 73544 }, + { 0x97E5, 73548 }, + { 0x95BA, 73552 }, + { 0x95BB, 73556 }, + { 0x95BC, 73560 }, + { 0x95BD, 73564 }, + { 0x95BE, 73568 }, + { 0x95BF, 73572 }, + { 0x95C0, 73576 }, + { 0x95C1, 73580 }, + { 0x95C2, 73584 }, + { 0x95C3, 73588 }, + { 0x95C4, 73592 }, + { 0x95C5, 73596 }, + { 0x95C6, 73600 }, + { 0x95C7, 73604 }, + { 0x95C8, 73608 }, + { 0x95C9, 73612 }, + { 0x95CA, 73616 }, + { 0x95CB, 73620 }, + { 0x95CC, 73624 }, + { 0x95CD, 73628 }, + { 0x95CE, 73632 }, + { 0x95CF, 73636 }, + { 0x95D0, 73640 }, + { 0x95D1, 73644 }, + { 0x95D2, 73648 }, + { 0x95D3, 73652 }, + { 0x9622, 73656 }, + { 0x9623, 73661 }, + { 0x9624, 73666 }, + { 0x9625, 73671 }, + { 0x9626, 73676 }, + { 0x9627, 73681 }, + { 0x9628, 73686 }, + { 0x9629, 73691 }, + { 0x962A, 73696 }, + { 0x962B, 73701 }, + { 0x962C, 73706 }, + { 0x962D, 73711 }, + { 0x962E, 73716 }, + { 0x962F, 73721 }, + { 0x9630, 73726 }, + { 0x9631, 73731 }, + { 0x9632, 73736 }, + { 0x9633, 73741 }, + { 0x9634, 73746 }, + { 0x9635, 73751 }, + { 0x9636, 73756 }, + { 0x9637, 73761 }, + { 0x9638, 73766 }, + { 0x9639, 73771 }, + { 0x963A, 73776 }, + { 0x963B, 73781 }, + { 0x9608, 73786 }, + { 0x9609, 73791 }, + { 0x960A, 73796 }, + { 0x960B, 73801 }, + { 0x960C, 73806 }, + { 0x960D, 73811 }, + { 0x960E, 73816 }, + { 0x960F, 73821 }, + { 0x9610, 73826 }, + { 0x9611, 73831 }, + { 0x9612, 73836 }, + { 0x9613, 73841 }, + { 0x9614, 73846 }, + { 0x9615, 73851 }, + { 0x9616, 73856 }, + { 0x9617, 73861 }, + { 0x9618, 73866 }, + { 0x9619, 73871 }, + { 0x961A, 73876 }, + { 0x961B, 73881 }, + { 0x961C, 73886 }, + { 0x961D, 73891 }, + { 0x961E, 73896 }, + { 0x961F, 73901 }, + { 0x9620, 73906 }, + { 0x9621, 73911 }, + { 0x95A0, 73916 }, + { 0x95A1, 73920 }, + { 0x95A2, 73924 }, + { 0x95A3, 73928 }, + { 0x95A4, 73932 }, + { 0x95A5, 73936 }, + { 0x95A6, 73940 }, + { 0x95A7, 73944 }, + { 0x95A8, 73948 }, + { 0x95A9, 73952 }, + { 0x95AA, 73956 }, + { 0x95AB, 73960 }, + { 0x95AC, 73964 }, + { 0x95AD, 73968 }, + { 0x95AE, 73972 }, + { 0x95AF, 73976 }, + { 0x95B0, 73980 }, + { 0x95B1, 73984 }, + { 0x95B2, 73988 }, + { 0x95B3, 73992 }, + { 0x95B4, 73996 }, + { 0x95B5, 74000 }, + { 0x95B6, 74004 }, + { 0x95B7, 74008 }, + { 0x95B8, 74012 }, + { 0x95B9, 74016 }, + { 0x97D9, 74020 }, + { 0x97DE, 74024 }, + { 0x97DA, 74028 }, + { 0x97DD, 74032 }, + { 0x97DC, 74036 }, + { 0x97E1, 74040 }, + { 0x97D8, 74044 }, + { 0x97E0, 74048 }, + { 0x97DF, 74052 }, + { 0x97DB, 74056 }, + { 0x9552, 74060 }, + { 0x9553, 74064 }, + { 0x9554, 74068 }, + { 0x9555, 74072 }, + { 0x9556, 74076 }, + { 0x9557, 74080 }, + { 0x9558, 74084 }, + { 0x9559, 74088 }, + { 0x955A, 74092 }, + { 0x955B, 74096 }, + { 0x955C, 74100 }, + { 0x955D, 74104 }, + { 0x955E, 74108 }, + { 0x955F, 74112 }, + { 0x9560, 74116 }, + { 0x9561, 74120 }, + { 0x9562, 74124 }, + { 0x9563, 74128 }, + { 0x9564, 74132 }, + { 0x9565, 74136 }, + { 0x9566, 74140 }, + { 0x9567, 74144 }, + { 0x9568, 74148 }, + { 0x9569, 74152 }, + { 0x956A, 74156 }, + { 0x956B, 74160 }, + { 0x9538, 74164 }, + { 0x9539, 74168 }, + { 0x953B, 74172 }, + { 0x953C, 74176 }, + { 0x953D, 74180 }, + { 0x953E, 74184 }, + { 0x9540, 74188 }, + { 0x9541, 74192 }, + { 0x9542, 74196 }, + { 0x9543, 74200 }, + { 0x9544, 74204 }, + { 0x9546, 74208 }, + { 0x954A, 74212 }, + { 0x954B, 74216 }, + { 0x954C, 74220 }, + { 0x954D, 74224 }, + { 0x954E, 74228 }, + { 0x954F, 74232 }, + { 0x9550, 74236 }, + { 0x2011, 74240 }, + { 0x211E, 74242 }, + { 0x6E31, 74244 }, + { 0x6E32, 74250 }, + { 0x6E33, 74256 }, + { 0x6E30, 74262 }, + { 0x6E3F, 74269 }, + { 0x6E3B, 74276 }, + { 0x6E37, 74284 }, + { 0x6E43, 74291 }, + { 0x6E17, 74299 }, + { 0x6E41, 74307 }, + { 0x6E3D, 74314 }, + { 0x6E47, 74322 }, + { 0x6E39, 74329 }, + { 0x6E35, 74337 }, + { 0x6E34, 74343 }, + { 0x6E13, 74350 }, + { 0x6E10, 74355 }, + { 0x6E40, 74360 }, + { 0x6E3C, 74367 }, + { 0x6E38, 74375 }, + { 0x6E44, 74382 }, + { 0x6E18, 74390 }, + { 0x6E42, 74398 }, + { 0x6E3E, 74405 }, + { 0x6E48, 74413 }, + { 0x6E3A, 74420 }, + { 0x6E36, 74428 }, + { 0x6E16, 74434 }, + { 0x6E14, 74440 }, + { 0x6E19, 74445 }, + { 0x6E15, 74451 }, + { 0x6E12, 74457 }, + { 0x6E11, 74464 }, + { 0x221D, 74470 }, + { 0x27A9, 74472 }, + { 0x29F4, 74476 }, + { 0x23E4, 74477 }, + { 0x2004, 74478 }, + { 0x2608, 74480 }, + { 0x27BC, 74481 }, + { 0x21B6, 74484 }, + { 0x21BA, 74488 }, + { 0x2940, 74492 }, + { 0x27F2, 74496 }, + { 0x2233, 74500 }, + { 0x2A11, 74503 }, + { 0x2246, 74505 }, + { 0x2A70, 74511 }, + { 0x2245, 74516 }, + { 0x2252, 74519 }, + { 0x2382, 74526 }, + { 0x2140, 74529 }, + { 0x213C, 74532 }, + { 0x213D, 74535 }, + { 0x2146, 74538 }, + { 0x2147, 74542 }, + { 0x2148, 74546 }, + { 0x2149, 74550 }, + { 0x2145, 74554 }, + { 0x2102, 74558 }, + { 0x210D, 74561 }, + { 0x2115, 74564 }, + { 0x2119, 74567 }, + { 0x211A, 74570 }, + { 0x211D, 74573 }, + { 0x2124, 74576 }, + { 0x213F, 74579 }, + { 0x213E, 74582 }, + { 0x29E8, 74585 }, + { 0x29E9, 74591 }, + { 0x20A0, 74597 }, + { 0x2251, 74599 }, + { 0x224E, 74602 }, + { 0x2329, 74605 }, + { 0x29FC, 74608 }, + { 0x00AB, 74612 }, + { 0x200E, 74617 }, + { 0x202D, 74619 }, + { 0x202A, 74621 }, + { 0x2213, 74623 }, + { 0x27BE, 74625 }, + { 0x2474, 74628 }, + { 0x2479, 74631 }, + { 0x2475, 74634 }, + { 0x2478, 74637 }, + { 0x2477, 74640 }, + { 0x247C, 74643 }, + { 0x247B, 74646 }, + { 0x247A, 74649 }, + { 0x2476, 74652 }, + { 0x249C, 74655 }, + { 0x249D, 74660 }, + { 0x249E, 74665 }, + { 0x249F, 74670 }, + { 0x24A0, 74675 }, + { 0x24A1, 74680 }, + { 0x24A2, 74685 }, + { 0x24A3, 74690 }, + { 0x24A4, 74695 }, + { 0x24A5, 74700 }, + { 0x24A6, 74705 }, + { 0x24A7, 74710 }, + { 0x24A8, 74715 }, + { 0x24A9, 74720 }, + { 0x24AA, 74725 }, + { 0x24AB, 74730 }, + { 0x24AC, 74735 }, + { 0x24AD, 74740 }, + { 0x24AE, 74745 }, + { 0x24AF, 74750 }, + { 0x24B0, 74755 }, + { 0x24B1, 74760 }, + { 0x24B2, 74765 }, + { 0x24B3, 74770 }, + { 0x24B4, 74775 }, + { 0x24B5, 74780 }, + { 0x3206, 74785 }, + { 0x3214, 74788 }, + { 0x3208, 74792 }, + { 0x3216, 74795 }, + { 0x321C, 74799 }, + { 0x320D, 74803 }, + { 0x321B, 74806 }, + { 0x3207, 74810 }, + { 0x3215, 74813 }, + { 0x3204, 74817 }, + { 0x3212, 74820 }, + { 0x3201, 74824 }, + { 0x320F, 74827 }, + { 0x3205, 74831 }, + { 0x3213, 74834 }, + { 0x3203, 74838 }, + { 0x3211, 74841 }, + { 0x3200, 74845 }, + { 0x320E, 74848 }, + { 0x3202, 74852 }, + { 0x3210, 74855 }, + { 0x3209, 74859 }, + { 0x3217, 74862 }, + { 0x320A, 74866 }, + { 0x3218, 74869 }, + { 0x320C, 74873 }, + { 0x321A, 74876 }, + { 0x320B, 74880 }, + { 0x3219, 74883 }, + { 0x321E, 74887 }, + { 0x321D, 74892 }, + { 0x247D, 74896 }, + { 0x247E, 74899 }, + { 0x247F, 74902 }, + { 0x2487, 74905 }, + { 0x2482, 74908 }, + { 0x2483, 74911 }, + { 0x2485, 74914 }, + { 0x2481, 74917 }, + { 0x2486, 74920 }, + { 0x2480, 74923 }, + { 0x2484, 74926 }, + { 0x3220, 74929 }, + { 0x3225, 74932 }, + { 0x3230, 74935 }, + { 0x3229, 74938 }, + { 0x3221, 74941 }, + { 0x323A, 74944 }, + { 0x322B, 74947 }, + { 0x3224, 74950 }, + { 0x3223, 74953 }, + { 0x3232, 74956 }, + { 0x322A, 74959 }, + { 0x3234, 74962 }, + { 0x3228, 74965 }, + { 0x3241, 74968 }, + { 0x3242, 74971 }, + { 0x322D, 74974 }, + { 0x322F, 74977 }, + { 0x3227, 74980 }, + { 0x3238, 74983 }, + { 0x322E, 74986 }, + { 0x3243, 74989 }, + { 0x3226, 74992 }, + { 0x3231, 74995 }, + { 0x323B, 74998 }, + { 0x3222, 75001 }, + { 0x322C, 75004 }, + { 0x3233, 75007 }, + { 0x3235, 75010 }, + { 0x323F, 75013 }, + { 0x3240, 75016 }, + { 0x323E, 75019 }, + { 0x3236, 75022 }, + { 0x3239, 75025 }, + { 0x323C, 75028 }, + { 0x323D, 75031 }, + { 0x3237, 75034 }, + { 0x27C2, 75037 }, + { 0x2AE1, 75038 }, + { 0x200F, 75041 }, + { 0x202E, 75043 }, + { 0x202B, 75045 }, + { 0x29E7, 75047 }, + { 0x2243, 75048 }, + { 0x2749, 75051 }, + { 0x2715, 75053 }, + { 0x00D7, 75055 }, + { 0x2A34, 75057 }, + { 0x2A35, 75063 }, + { 0x2A37, 75069 }, + { 0x2A3B, 75074 }, + { 0x2A30, 75078 }, + { 0x2A31, 75083 }, + { 0x232A, 75087 }, + { 0x29FD, 75090 }, + { 0x00BB, 75094 }, + { 0x26BC, 75099 }, + { 0x27B6, 75100 }, + { 0x27B4, 75104 }, + { 0x27B5, 75108 }, + { 0x27BA, 75111 }, + { 0x273B, 75114 }, + { 0x279D, 75116 }, + { 0x27B3, 75119 }, + { 0x30A0, 75122 }, + { 0x309B, 75125 }, + { 0x30FC, 75129 }, + { 0x309C, 75133 }, + { 0x2394, 75137 }, + { 0x267D, 75139 }, + { 0x238F, 75142 }, + { 0x2390, 75145 }, + { 0x2392, 75148 }, + { 0x2391, 75150 }, +}; +static const struct { uint16_t code; uint32_t name:24; } +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7) +__attribute__((__packed__)) +#endif +unicode_code_to_name[18242] = { + { 0x0020, 22740 }, + { 0x0021, 68656 }, + { 0x0022, 65766 }, + { 0x0023, 35593 }, + { 0x0024, 31225 }, + { 0x0025, 42973 }, + { 0x0026, 56108 }, + { 0x0027, 66826 }, + { 0x0028, 9464 }, + { 0x0029, 21991 }, + { 0x002A, 45081 }, + { 0x002B, 9633 }, + { 0x002C, 10461 }, + { 0x002D, 69568 }, + { 0x002E, 9112 }, + { 0x002F, 43548 }, + { 0x0030, 10518 }, + { 0x0031, 10482 }, + { 0x0032, 10494 }, + { 0x0033, 10532 }, + { 0x0034, 10506 }, + { 0x0035, 10500 }, + { 0x0036, 10488 }, + { 0x0037, 10526 }, + { 0x0038, 10520 }, + { 0x0039, 10512 }, + { 0x003A, 10455 }, + { 0x003B, 65813 }, + { 0x003C, 64726 }, + { 0x003D, 31706 }, + { 0x003E, 69497 }, + { 0x003F, 55446 }, + { 0x0040, 66837 }, + { 0x0041, 18231 }, + { 0x0042, 18454 }, + { 0x0043, 18497 }, + { 0x0044, 18552 }, + { 0x0045, 18632 }, + { 0x0046, 18817 }, + { 0x0047, 18834 }, + { 0x0048, 18893 }, + { 0x0049, 18954 }, + { 0x004A, 19068 }, + { 0x004B, 19084 }, + { 0x004C, 19154 }, + { 0x004D, 19254 }, + { 0x004E, 19284 }, + { 0x004F, 19369 }, + { 0x0050, 19659 }, + { 0x0051, 19709 }, + { 0x0052, 19728 }, + { 0x0053, 19811 }, + { 0x0054, 19888 }, + { 0x0055, 19965 }, + { 0x0056, 20187 }, + { 0x0057, 20217 }, + { 0x0058, 20265 }, + { 0x0059, 20282 }, + { 0x005A, 20361 }, + { 0x005B, 9385 }, + { 0x005C, 42994 }, + { 0x005D, 21912 }, + { 0x005E, 66835 }, + { 0x005F, 6031 }, + { 0x0060, 10638 }, + { 0x0061, 14473 }, + { 0x0062, 14711 }, + { 0x0063, 14768 }, + { 0x0064, 14829 }, + { 0x0065, 14925 }, + { 0x0066, 15123 }, + { 0x0067, 15154 }, + { 0x0068, 15220 }, + { 0x0069, 15294 }, + { 0x006A, 15408 }, + { 0x006B, 15436 }, + { 0x006C, 15513 }, + { 0x006D, 15631 }, + { 0x006E, 15675 }, + { 0x006F, 15786 }, + { 0x0070, 16077 }, + { 0x0071, 16141 }, + { 0x0072, 16173 }, + { 0x0073, 16292 }, + { 0x0074, 16396 }, + { 0x0075, 16499 }, + { 0x0076, 16728 }, + { 0x0077, 16778 }, + { 0x0078, 16833 }, + { 0x0079, 16857 }, + { 0x007A, 16943 }, + { 0x007B, 9231 }, + { 0x007C, 56066 }, + { 0x007D, 21824 }, + { 0x007E, 23008 }, + { 0x00A0, 54927 }, + { 0x00A1, 53357 }, + { 0x00A2, 8729 }, + { 0x00A3, 21740 }, + { 0x00A4, 48521 }, + { 0x00A5, 8712 }, + { 0x00A6, 30305 }, + { 0x00A7, 43022 }, + { 0x00A8, 63244 }, + { 0x00A9, 58349 }, + { 0x00AA, 51775 }, + { 0x00AB, 74612 }, + { 0x00AC, 6723 }, + { 0x00AD, 9710 }, + { 0x00AE, 67979 }, + { 0x00AF, 35513 }, + { 0x00B0, 31179 }, + { 0x00B1, 67969 }, + { 0x00B2, 69284 }, + { 0x00B3, 69319 }, + { 0x00B4, 10104 }, + { 0x00B5, 21176 }, + { 0x00B6, 42975 }, + { 0x00B7, 35570 }, + { 0x00B8, 38870 }, + { 0x00B9, 69280 }, + { 0x00BA, 65112 }, + { 0x00BB, 75094 }, + { 0x00BC, 37732 }, + { 0x00BD, 37712 }, + { 0x00BE, 37768 }, + { 0x00BF, 53352 }, + { 0x00C0, 18348 }, + { 0x00C1, 18288 }, + { 0x00C2, 18406 }, + { 0x00C3, 18354 }, + { 0x00C4, 18392 }, + { 0x00C5, 18265 }, + { 0x00C6, 20426 }, + { 0x00C7, 18532 }, + { 0x00C8, 18675 }, + { 0x00C9, 18657 }, + { 0x00CA, 18762 }, + { 0x00CB, 18756 }, + { 0x00CC, 18997 }, + { 0x00CD, 18979 }, + { 0x00CE, 19062 }, + { 0x00CF, 19048 }, + { 0x00D0, 20523 }, + { 0x00D1, 19350 }, + { 0x00D2, 19483 }, + { 0x00D3, 19465 }, + { 0x00D4, 19611 }, + { 0x00D5, 19489 }, + { 0x00D6, 19597 }, + { 0x00D7, 75055 }, + { 0x00D8, 19576 }, + { 0x00D9, 20061 }, + { 0x00DA, 20043 }, + { 0x00DB, 20174 }, + { 0x00DC, 20129 }, + { 0x00DD, 20319 }, + { 0x00DE, 20626 }, + { 0x00DF, 17465 }, + { 0x00E0, 14590 }, + { 0x00E1, 14530 }, + { 0x00E2, 14663 }, + { 0x00E3, 14604 }, + { 0x00E4, 14642 }, + { 0x00E5, 14507 }, + { 0x00E6, 17042 }, + { 0x00E7, 14809 }, + { 0x00E8, 14968 }, + { 0x00E9, 14950 }, + { 0x00EA, 15068 }, + { 0x00EB, 15055 }, + { 0x00EC, 15330 }, + { 0x00ED, 15312 }, + { 0x00EE, 15402 }, + { 0x00EF, 15381 }, + { 0x00F0, 17225 }, + { 0x00F1, 15739 }, + { 0x00F2, 15908 }, + { 0x00F3, 15890 }, + { 0x00F4, 16029 }, + { 0x00F5, 15914 }, + { 0x00F6, 16015 }, + { 0x00F7, 50308 }, + { 0x00F8, 15994 }, + { 0x00F9, 16595 }, + { 0x00FA, 16577 }, + { 0x00FB, 16715 }, + { 0x00FC, 16663 }, + { 0x00FD, 16901 }, + { 0x00FE, 17476 }, + { 0x00FF, 16931 }, + { 0x0100, 18367 }, + { 0x0101, 14617 }, + { 0x0102, 18294 }, + { 0x0103, 14536 }, + { 0x0104, 18373 }, + { 0x0105, 14623 }, + { 0x0106, 18514 }, + { 0x0107, 14791 }, + { 0x0108, 18546 }, + { 0x0109, 14823 }, + { 0x010A, 18501 }, + { 0x010B, 14772 }, + { 0x010C, 18520 }, + { 0x010D, 14797 }, + { 0x010E, 18583 }, + { 0x010F, 14880 }, + { 0x0110, 18607 }, + { 0x0111, 14893 }, + { 0x0112, 18701 }, + { 0x0113, 15000 }, + { 0x0114, 18663 }, + { 0x0115, 14956 }, + { 0x0116, 18636 }, + { 0x0117, 14929 }, + { 0x0118, 18723 }, + { 0x0119, 15022 }, + { 0x011A, 18669 }, + { 0x011B, 14962 }, + { 0x011C, 18887 }, + { 0x011D, 15214 }, + { 0x011E, 18857 }, + { 0x011F, 15177 }, + { 0x0120, 18838 }, + { 0x0121, 15158 }, + { 0x0122, 18881 }, + { 0x0123, 15201 }, + { 0x0124, 18948 }, + { 0x0125, 15288 }, + { 0x0126, 18924 }, + { 0x0127, 15264 }, + { 0x0128, 19003 }, + { 0x0129, 15336 }, + { 0x012A, 19023 }, + { 0x012B, 15356 }, + { 0x012C, 18985 }, + { 0x012D, 15318 }, + { 0x012E, 19029 }, + { 0x012F, 15362 }, + { 0x0130, 18958 }, + { 0x0131, 17682 }, + { 0x0132, 20774 }, + { 0x0133, 17909 }, + { 0x0134, 19078 }, + { 0x0135, 15424 }, + { 0x0136, 19135 }, + { 0x0137, 15487 }, + { 0x0138, 17263 }, + { 0x0139, 19194 }, + { 0x013A, 15565 }, + { 0x013B, 19241 }, + { 0x013C, 15604 }, + { 0x013D, 19200 }, + { 0x013E, 15571 }, + { 0x013F, 19221 }, + { 0x0140, 15584 }, + { 0x0141, 19235 }, + { 0x0142, 15598 }, + { 0x0143, 19324 }, + { 0x0144, 15721 }, + { 0x0145, 19356 }, + { 0x0146, 15752 }, + { 0x0147, 19330 }, + { 0x0148, 15727 }, + { 0x0149, 15779 }, + { 0x014A, 20515 }, + { 0x014B, 17197 }, + { 0x014C, 19533 }, + { 0x014D, 15958 }, + { 0x014E, 19471 }, + { 0x014F, 15896 }, + { 0x0150, 19519 }, + { 0x0151, 15944 }, + { 0x0152, 20778 }, + { 0x0153, 17913 }, + { 0x0154, 19768 }, + { 0x0155, 16220 }, + { 0x0156, 19793 }, + { 0x0157, 16252 }, + { 0x0158, 19774 }, + { 0x0159, 16226 }, + { 0x015A, 19839 }, + { 0x015B, 16326 }, + { 0x015C, 19882 }, + { 0x015D, 16390 }, + { 0x015E, 19876 }, + { 0x015F, 16377 }, + { 0x0160, 19854 }, + { 0x0161, 16341 }, + { 0x0162, 19938 }, + { 0x0163, 16459 }, + { 0x0164, 19919 }, + { 0x0165, 16433 }, + { 0x0166, 19932 }, + { 0x0167, 16453 }, + { 0x0168, 20067 }, + { 0x0169, 16601 }, + { 0x016A, 20102 }, + { 0x016B, 16636 }, + { 0x016C, 20049 }, + { 0x016D, 16583 }, + { 0x016E, 20036 }, + { 0x016F, 16570 }, + { 0x0170, 20088 }, + { 0x0171, 16622 }, + { 0x0172, 20116 }, + { 0x0173, 16650 }, + { 0x0174, 20259 }, + { 0x0175, 16827 }, + { 0x0176, 20355 }, + { 0x0177, 16937 }, + { 0x0178, 20349 }, + { 0x0179, 20392 }, + { 0x017A, 16980 }, + { 0x017B, 20365 }, + { 0x017C, 16947 }, + { 0x017D, 20398 }, + { 0x017E, 16986 }, + { 0x017F, 17341 }, + { 0x0180, 14749 }, + { 0x0181, 18472 }, + { 0x0182, 18491 }, + { 0x0183, 14755 }, + { 0x0184, 20570 }, + { 0x0185, 17406 }, + { 0x0186, 20565 }, + { 0x0187, 18508 }, + { 0x0188, 14785 }, + { 0x0189, 20675 }, + { 0x018A, 18570 }, + { 0x018B, 18613 }, + { 0x018C, 14899 }, + { 0x018D, 17671 }, + { 0x018E, 20726 }, + { 0x018F, 20609 }, + { 0x0190, 20560 }, + { 0x0191, 18828 }, + { 0x0192, 15134 }, + { 0x0193, 18845 }, + { 0x0194, 20601 }, + { 0x0195, 17112 }, + { 0x0196, 20556 }, + { 0x0197, 19035 }, + { 0x0198, 19095 }, + { 0x0199, 15447 }, + { 0x019A, 15517 }, + { 0x019B, 17528 }, + { 0x019C, 20659 }, + { 0x019D, 19302 }, + { 0x019E, 15713 }, + { 0x019F, 19555 }, + { 0x01A0, 19403 }, + { 0x01A1, 15828 }, + { 0x01A2, 20491 }, + { 0x01A3, 17138 }, + { 0x01A4, 19670 }, + { 0x01A5, 16088 }, + { 0x01A6, 17935 }, + { 0x01A7, 20575 }, + { 0x01A8, 17411 }, + { 0x01A9, 20519 }, + { 0x01AA, 18206 }, + { 0x01AB, 16465 }, + { 0x01AC, 19906 }, + { 0x01AD, 16420 }, + { 0x01AE, 19951 }, + { 0x01AF, 19988 }, + { 0x01B0, 16522 }, + { 0x01B1, 20715 }, + { 0x01B2, 20198 }, + { 0x01B3, 20300 }, + { 0x01B4, 16875 }, + { 0x01B5, 20404 }, + { 0x01B6, 17006 }, + { 0x01B7, 20527 }, + { 0x01B8, 20537 }, + { 0x01B9, 17258 }, + { 0x01BA, 17239 }, + { 0x01BB, 17941 }, + { 0x01BC, 20580 }, + { 0x01BD, 17416 }, + { 0x01BE, 18199 }, + { 0x01BF, 17946 }, + { 0x01C0, 18155 }, + { 0x01C1, 18174 }, + { 0x01C2, 18178 }, + { 0x01C3, 18218 }, + { 0x01C4, 20469 }, + { 0x01C5, 18597 }, + { 0x01C6, 17090 }, + { 0x01C7, 20483 }, + { 0x01C8, 19206 }, + { 0x01C9, 17120 }, + { 0x01CA, 20487 }, + { 0x01CB, 19342 }, + { 0x01CC, 17134 }, + { 0x01CD, 18342 }, + { 0x01CE, 14584 }, + { 0x01CF, 18991 }, + { 0x01D0, 15324 }, + { 0x01D1, 19477 }, + { 0x01D2, 15902 }, + { 0x01D3, 20055 }, + { 0x01D4, 16589 }, + { 0x01D5, 20159 }, + { 0x01D6, 16693 }, + { 0x01D7, 20135 }, + { 0x01D8, 16669 }, + { 0x01D9, 20143 }, + { 0x01DA, 16677 }, + { 0x01DB, 20151 }, + { 0x01DC, 16685 }, + { 0x01DD, 17544 }, + { 0x01DE, 18398 }, + { 0x01DF, 14648 }, + { 0x01E0, 18242 }, + { 0x01E1, 14484 }, + { 0x01E2, 20436 }, + { 0x01E3, 17052 }, + { 0x01E4, 18875 }, + { 0x01E5, 15195 }, + { 0x01E6, 18863 }, + { 0x01E7, 15183 }, + { 0x01E8, 19114 }, + { 0x01E9, 15466 }, + { 0x01EA, 19562 }, + { 0x01EB, 15980 }, + { 0x01EC, 19568 }, + { 0x01ED, 15986 }, + { 0x01EE, 20531 }, + { 0x01EF, 17245 }, + { 0x01F0, 15412 }, + { 0x01F1, 20465 }, + { 0x01F2, 18589 }, + { 0x01F3, 17086 }, + { 0x01F4, 18851 }, + { 0x01F5, 15171 }, + { 0x01F6, 20605 }, + { 0x01F7, 20589 }, + { 0x01F8, 19336 }, + { 0x01F9, 15733 }, + { 0x01FA, 18272 }, + { 0x01FB, 14514 }, + { 0x01FC, 20430 }, + { 0x01FD, 17046 }, + { 0x01FE, 19582 }, + { 0x01FF, 16000 }, + { 0x0200, 18360 }, + { 0x0201, 14610 }, + { 0x0202, 18385 }, + { 0x0203, 14635 }, + { 0x0204, 18694 }, + { 0x0205, 14993 }, + { 0x0206, 18749 }, + { 0x0207, 15048 }, + { 0x0208, 19016 }, + { 0x0209, 15349 }, + { 0x020A, 19041 }, + { 0x020B, 15374 }, + { 0x020C, 19526 }, + { 0x020D, 15951 }, + { 0x020E, 19590 }, + { 0x020F, 16008 }, + { 0x0210, 19780 }, + { 0x0211, 16232 }, + { 0x0212, 19799 }, + { 0x0213, 16280 }, + { 0x0214, 20095 }, + { 0x0215, 16629 }, + { 0x0216, 20122 }, + { 0x0217, 16656 }, + { 0x0218, 19869 }, + { 0x0219, 16356 }, + { 0x021A, 19925 }, + { 0x021B, 16439 }, + { 0x021C, 20593 }, + { 0x021D, 17425 }, + { 0x021E, 18918 }, + { 0x021F, 15258 }, + { 0x0220, 19316 }, + { 0x0221, 14847 }, + { 0x0222, 20499 }, + { 0x0223, 17146 }, + { 0x0224, 20379 }, + { 0x0225, 16967 }, + { 0x0226, 18235 }, + { 0x0227, 14477 }, + { 0x0228, 18735 }, + { 0x0229, 15034 }, + { 0x022A, 19603 }, + { 0x022B, 16021 }, + { 0x022C, 19503 }, + { 0x022D, 15928 }, + { 0x022E, 19373 }, + { 0x022F, 15790 }, + { 0x0230, 19380 }, + { 0x0231, 15797 }, + { 0x0232, 20337 }, + { 0x0233, 16919 }, + { 0x0234, 15545 }, + { 0x0235, 15693 }, + { 0x0236, 16414 }, + { 0x0237, 17687 }, + { 0x0238, 17081 }, + { 0x0239, 17150 }, + { 0x023A, 18379 }, + { 0x023B, 18526 }, + { 0x023C, 14803 }, + { 0x023D, 19158 }, + { 0x023E, 19944 }, + { 0x023F, 16363 }, + { 0x0240, 16992 }, + { 0x0241, 20680 }, + { 0x0242, 17708 }, + { 0x0243, 18485 }, + { 0x0244, 19969 }, + { 0x0245, 20664 }, + { 0x0246, 18729 }, + { 0x0247, 15028 }, + { 0x0248, 19072 }, + { 0x0249, 15418 }, + { 0x024A, 20618 }, + { 0x024B, 16151 }, + { 0x024C, 19787 }, + { 0x024D, 16246 }, + { 0x024E, 20343 }, + { 0x024F, 16925 }, + { 0x0250, 17539 }, + { 0x0251, 17429 }, + { 0x0252, 17666 }, + { 0x0253, 14729 }, + { 0x0254, 17383 }, + { 0x0255, 14779 }, + { 0x0256, 14874 }, + { 0x0257, 14853 }, + { 0x0258, 17765 }, + { 0x0259, 17448 }, + { 0x025A, 17452 }, + { 0x025B, 17370 }, + { 0x025C, 17777 }, + { 0x025D, 17783 }, + { 0x025E, 17521 }, + { 0x025F, 17692 }, + { 0x0260, 15165 }, + { 0x0261, 17534 }, + { 0x0262, 17979 }, + { 0x0263, 17444 }, + { 0x0264, 17396 }, + { 0x0265, 17554 }, + { 0x0266, 15238 }, + { 0x0267, 17321 }, + { 0x0268, 15368 }, + { 0x0269, 17327 }, + { 0x026A, 17996 }, + { 0x026B, 15591 }, + { 0x026C, 15539 }, + { 0x026D, 15617 }, + { 0x026E, 17337 }, + { 0x026F, 17590 }, + { 0x0270, 17595 }, + { 0x0271, 15649 }, + { 0x0272, 15699 }, + { 0x0273, 15765 }, + { 0x0274, 18028 }, + { 0x0275, 17494 }, + { 0x0276, 18088 }, + { 0x0277, 17516 }, + { 0x0278, 17279 }, + { 0x0279, 17603 }, + { 0x027A, 17615 }, + { 0x027B, 17608 }, + { 0x027C, 16207 }, + { 0x027D, 16214 }, + { 0x027E, 16265 }, + { 0x027F, 17770 }, + { 0x0280, 18043 }, + { 0x0281, 18137 }, + { 0x0282, 16320 }, + { 0x0283, 17201 }, + { 0x0284, 17699 }, + { 0x0285, 17470 }, + { 0x0286, 17205 }, + { 0x0287, 17630 }, + { 0x0288, 16485 }, + { 0x0289, 16503 }, + { 0x028A, 17743 }, + { 0x028B, 16745 }, + { 0x028C, 17635 }, + { 0x028D, 17640 }, + { 0x028E, 17645 }, + { 0x028F, 18073 }, + { 0x0290, 17025 }, + { 0x0291, 16961 }, + { 0x0292, 17229 }, + { 0x0293, 17233 }, + { 0x0294, 18164 }, + { 0x0295, 18226 }, + { 0x0296, 18194 }, + { 0x0297, 18222 }, + { 0x0298, 18186 }, + { 0x0299, 17954 }, + { 0x029A, 17510 }, + { 0x029B, 17984 }, + { 0x029C, 17991 }, + { 0x029D, 15430 }, + { 0x029E, 17580 }, + { 0x029F, 18011 }, + { 0x02A0, 16145 }, + { 0x02A1, 18168 }, + { 0x02A2, 18211 }, + { 0x02A3, 17096 }, + { 0x02A4, 17302 }, + { 0x02A5, 17101 }, + { 0x02A6, 17168 }, + { 0x02A7, 17401 }, + { 0x02A8, 17155 }, + { 0x02A9, 17307 }, + { 0x02AA, 17124 }, + { 0x02AB, 17129 }, + { 0x02AC, 18190 }, + { 0x02AD, 18182 }, + { 0x02AE, 17559 }, + { 0x02AF, 17566 }, + { 0x02B0, 54170 }, + { 0x02B1, 54174 }, + { 0x02B2, 54186 }, + { 0x02B3, 54250 }, + { 0x02B4, 54449 }, + { 0x02B5, 54454 }, + { 0x02B6, 54509 }, + { 0x02B7, 54294 }, + { 0x02B8, 54302 }, + { 0x02B9, 54116 }, + { 0x02BA, 54543 }, + { 0x02BB, 54612 }, + { 0x02BC, 54827 }, + { 0x02BD, 54790 }, + { 0x02BE, 54119 }, + { 0x02BF, 54058 }, + { 0x02C0, 54775 }, + { 0x02C1, 54794 }, + { 0x02C2, 54063 }, + { 0x02C3, 54124 }, + { 0x02C4, 53873 }, + { 0x02C5, 54025 }, + { 0x02C6, 54830 }, + { 0x02C7, 10445 }, + { 0x02C8, 54799 }, + { 0x02C9, 54551 }, + { 0x02CA, 54081 }, + { 0x02CB, 54102 }, + { 0x02CC, 53975 }, + { 0x02CD, 53965 }, + { 0x02CE, 53938 }, + { 0x02CF, 53933 }, + { 0x02D0, 54858 }, + { 0x02D1, 54029 }, + { 0x02D2, 54721 }, + { 0x02D3, 54715 }, + { 0x02D4, 53869 }, + { 0x02D5, 54021 }, + { 0x02D6, 54071 }, + { 0x02D7, 54112 }, + { 0x02D8, 10378 }, + { 0x02D9, 5782 }, + { 0x02DA, 9699 }, + { 0x02DB, 35640 }, + { 0x02DC, 22588 }, + { 0x02DD, 31564 }, + { 0x02DE, 54596 }, + { 0x02DF, 54098 }, + { 0x02E0, 54383 }, + { 0x02E1, 54200 }, + { 0x02E2, 54254 }, + { 0x02E3, 54298 }, + { 0x02E4, 54532 }, + { 0x02E5, 54834 }, + { 0x02E6, 54034 }, + { 0x02E7, 53991 }, + { 0x02E8, 53928 }, + { 0x02E9, 54803 }, + { 0x02EA, 54015 }, + { 0x02EB, 54075 }, + { 0x02EC, 54779 }, + { 0x02ED, 54862 }, + { 0x02EE, 54547 }, + { 0x02EF, 53909 }, + { 0x02F0, 53904 }, + { 0x02F1, 53919 }, + { 0x02F2, 53943 }, + { 0x02F3, 53924 }, + { 0x02F4, 54554 }, + { 0x02F5, 54565 }, + { 0x02F6, 54559 }, + { 0x02F7, 53948 }, + { 0x02F8, 54581 }, + { 0x02F9, 54090 }, + { 0x02FA, 53899 }, + { 0x02FB, 54085 }, + { 0x02FC, 53894 }, + { 0x02FD, 54128 }, + { 0x02FE, 54067 }, + { 0x02FF, 53914 }, + { 0x0300, 57554 }, + { 0x0301, 57523 }, + { 0x0302, 58283 }, + { 0x0303, 57841 }, + { 0x0304, 57946 }, + { 0x0305, 58215 }, + { 0x0306, 57530 }, + { 0x0307, 57402 }, + { 0x0308, 58240 }, + { 0x0309, 57427 }, + { 0x030A, 57506 }, + { 0x030B, 57876 }, + { 0x030C, 57535 }, + { 0x030D, 58221 }, + { 0x030E, 57918 }, + { 0x030F, 57887 }, + { 0x0310, 58305 }, + { 0x0311, 58191 }, + { 0x0312, 57970 }, + { 0x0313, 57540 }, + { 0x0314, 58217 }, + { 0x0315, 57543 }, + { 0x0316, 57557 }, + { 0x0317, 57526 }, + { 0x0318, 57442 }, + { 0x0319, 57783 }, + { 0x031A, 57446 }, + { 0x031B, 57430 }, + { 0x031C, 57437 }, + { 0x031D, 57392 }, + { 0x031E, 57419 }, + { 0x031F, 57502 }, + { 0x0320, 57769 }, + { 0x0321, 58307 }, + { 0x0322, 58279 }, + { 0x0323, 57409 }, + { 0x0324, 58242 }, + { 0x0325, 57509 }, + { 0x0326, 57547 }, + { 0x0327, 57983 }, + { 0x0328, 57959 }, + { 0x0329, 58225 }, + { 0x032A, 57857 }, + { 0x032B, 58202 }, + { 0x032C, 57537 }, + { 0x032D, 58286 }, + { 0x032E, 57532 }, + { 0x032F, 58194 }, + { 0x0330, 57843 }, + { 0x0331, 57952 }, + { 0x0332, 57412 }, + { 0x0333, 57868 }, + { 0x0334, 57846 }, + { 0x0335, 57821 }, + { 0x0336, 57489 }, + { 0x0337, 57825 }, + { 0x0338, 57493 }, + { 0x0339, 57778 }, + { 0x033A, 58198 }, + { 0x033B, 57964 }, + { 0x033C, 57991 }, + { 0x033D, 57383 }, + { 0x033E, 58229 }, + { 0x033F, 57915 }, + { 0x0340, 57550 }, + { 0x0341, 57519 }, + { 0x0342, 57580 }, + { 0x0343, 57561 }, + { 0x0344, 57576 }, + { 0x0345, 57583 }, + { 0x0346, 57854 }, + { 0x0347, 57942 }, + { 0x0348, 57923 }, + { 0x0349, 57450 }, + { 0x034A, 57415 }, + { 0x034B, 58293 }, + { 0x034C, 57849 }, + { 0x034D, 57467 }, + { 0x034E, 57994 }, + { 0x034F, 58188 }, + { 0x0350, 57813 }, + { 0x0351, 57432 }, + { 0x0352, 57985 }, + { 0x0353, 57386 }, + { 0x0354, 57480 }, + { 0x0355, 57817 }, + { 0x0356, 57799 }, + { 0x0357, 57773 }, + { 0x0358, 57405 }, + { 0x0359, 58001 }, + { 0x035A, 57872 }, + { 0x035B, 57974 }, + { 0x035C, 57883 }, + { 0x035D, 57880 }, + { 0x035E, 57904 }, + { 0x035F, 57907 }, + { 0x0360, 57891 }, + { 0x0361, 57911 }, + { 0x0362, 57937 }, + { 0x0363, 57586 }, + { 0x0364, 57607 }, + { 0x0365, 57622 }, + { 0x0366, 57647 }, + { 0x0367, 57679 }, + { 0x0368, 57591 }, + { 0x0369, 57602 }, + { 0x036A, 57617 }, + { 0x036B, 57637 }, + { 0x036C, 57652 }, + { 0x036D, 57674 }, + { 0x036E, 57684 }, + { 0x036F, 57689 }, + { 0x0370, 12320 }, + { 0x0371, 10998 }, + { 0x0372, 12792 }, + { 0x0373, 11590 }, + { 0x0374, 13034 }, + { 0x0375, 10720 }, + { 0x0376, 12999 }, + { 0x0377, 11869 }, + { 0x037A, 13522 }, + { 0x037B, 11881 }, + { 0x037C, 10738 }, + { 0x037D, 11874 }, + { 0x037E, 13059 }, + { 0x0384, 11898 }, + { 0x0385, 13083 }, + { 0x0386, 12574 }, + { 0x0387, 10643 }, + { 0x0388, 12851 }, + { 0x0389, 12268 }, + { 0x038A, 12394 }, + { 0x038C, 12917 }, + { 0x038E, 12969 }, + { 0x038F, 12766 }, + { 0x0390, 11110 }, + { 0x0391, 12428 }, + { 0x0392, 12316 }, + { 0x0393, 12608 }, + { 0x0394, 12604 }, + { 0x0395, 12797 }, + { 0x0396, 12424 }, + { 0x0397, 12122 }, + { 0x0398, 12788 }, + { 0x0399, 12324 }, + { 0x039A, 12612 }, + { 0x039B, 12616 }, + { 0x039C, 12102 }, + { 0x039D, 12106 }, + { 0x039E, 12114 }, + { 0x039F, 12863 }, + { 0x03A0, 12110 }, + { 0x03A1, 12294 }, + { 0x03A3, 12784 }, + { 0x03A4, 12312 }, + { 0x03A5, 12929 }, + { 0x03A6, 12286 }, + { 0x03A7, 12118 }, + { 0x03A8, 12290 }, + { 0x03A9, 12620 }, + { 0x03AA, 12418 }, + { 0x03AB, 12993 }, + { 0x03AC, 11298 }, + { 0x03AD, 11653 }, + { 0x03AE, 10918 }, + { 0x03AF, 11072 }, + { 0x03B0, 11839 }, + { 0x03B1, 11144 }, + { 0x03B2, 10994 }, + { 0x03B3, 11359 }, + { 0x03B4, 11350 }, + { 0x03B5, 11599 }, + { 0x03B6, 11140 }, + { 0x03B7, 10764 }, + { 0x03B8, 11577 }, + { 0x03B9, 11002 }, + { 0x03BA, 11363 }, + { 0x03BB, 11371 }, + { 0x03BC, 10744 }, + { 0x03BD, 10748 }, + { 0x03BE, 10756 }, + { 0x03BF, 11665 }, + { 0x03C0, 10752 }, + { 0x03C1, 10966 }, + { 0x03C2, 11354 }, + { 0x03C3, 11573 }, + { 0x03C4, 10990 }, + { 0x03C5, 11731 }, + { 0x03C6, 10958 }, + { 0x03C7, 10760 }, + { 0x03C8, 10962 }, + { 0x03C9, 11375 }, + { 0x03CA, 11096 }, + { 0x03CB, 11825 }, + { 0x03CC, 11719 }, + { 0x03CD, 11801 }, + { 0x03CE, 11529 }, + { 0x03CF, 12088 }, + { 0x03D0, 10678 }, + { 0x03D1, 11887 }, + { 0x03D2, 13037 }, + { 0x03D3, 13042 }, + { 0x03D4, 13049 }, + { 0x03D5, 10659 }, + { 0x03D6, 10640 }, + { 0x03D7, 10646 }, + { 0x03D8, 12064 }, + { 0x03D9, 11585 }, + { 0x03DA, 12061 }, + { 0x03DB, 11581 }, + { 0x03DC, 12068 }, + { 0x03DD, 11595 }, + { 0x03DE, 12030 }, + { 0x03DF, 11367 }, + { 0x03E0, 12033 }, + { 0x03E1, 11569 }, + { 0x03E2, 31064 }, + { 0x03E3, 30771 }, + { 0x03E4, 30926 }, + { 0x03E5, 30633 }, + { 0x03E6, 31060 }, + { 0x03E7, 30767 }, + { 0x03E8, 31052 }, + { 0x03E9, 30759 }, + { 0x03EA, 31104 }, + { 0x03EB, 30811 }, + { 0x03EC, 31100 }, + { 0x03ED, 30807 }, + { 0x03EE, 30918 }, + { 0x03EF, 30625 }, + { 0x03F0, 10714 }, + { 0x03F1, 10667 }, + { 0x03F2, 12071 }, + { 0x03F3, 12027 }, + { 0x03F4, 12092 }, + { 0x03F5, 12075 }, + { 0x03F6, 13062 }, + { 0x03F7, 12308 }, + { 0x03F8, 10986 }, + { 0x03F9, 13004 }, + { 0x03FA, 12304 }, + { 0x03FB, 10982 }, + { 0x03FC, 10662 }, + { 0x03FD, 13016 }, + { 0x03FE, 12096 }, + { 0x03FF, 13009 }, + { 0x0400, 49628 }, + { 0x0401, 49634 }, + { 0x0402, 49779 }, + { 0x0403, 49828 }, + { 0x0404, 50271 }, + { 0x0405, 49787 }, + { 0x0406, 50281 }, + { 0x0407, 49723 }, + { 0x0408, 49638 }, + { 0x0409, 49848 }, + { 0x040A, 49852 }, + { 0x040B, 50007 }, + { 0x040C, 49836 }, + { 0x040D, 49451 }, + { 0x040E, 50103 }, + { 0x040F, 49910 }, + { 0x0410, 49421 }, + { 0x0411, 49502 }, + { 0x0412, 49711 }, + { 0x0413, 49791 }, + { 0x0414, 49506 }, + { 0x0415, 49618 }, + { 0x0416, 49884 }, + { 0x0417, 49735 }, + { 0x0418, 49447 }, + { 0x0419, 50091 }, + { 0x041A, 49642 }, + { 0x041B, 49514 }, + { 0x041C, 49537 }, + { 0x041D, 49547 }, + { 0x041E, 49469 }, + { 0x041F, 49675 }, + { 0x0420, 49576 }, + { 0x0421, 49586 }, + { 0x0422, 49690 }, + { 0x0423, 49479 }, + { 0x0424, 49510 }, + { 0x0425, 49596 }, + { 0x0426, 49868 }, + { 0x0427, 49756 }, + { 0x0428, 49864 }, + { 0x0429, 50087 }, + { 0x042A, 49926 }, + { 0x042B, 50019 }, + { 0x042C, 49998 }, + { 0x042D, 49437 }, + { 0x042E, 49731 }, + { 0x042F, 49719 }, + { 0x0430, 48523 }, + { 0x0431, 48604 }, + { 0x0432, 48813 }, + { 0x0433, 48893 }, + { 0x0434, 48608 }, + { 0x0435, 48720 }, + { 0x0436, 48986 }, + { 0x0437, 48837 }, + { 0x0438, 48549 }, + { 0x0439, 49193 }, + { 0x043A, 48744 }, + { 0x043B, 48616 }, + { 0x043C, 48639 }, + { 0x043D, 48649 }, + { 0x043E, 48571 }, + { 0x043F, 48777 }, + { 0x0440, 48678 }, + { 0x0441, 48688 }, + { 0x0442, 48792 }, + { 0x0443, 48581 }, + { 0x0444, 48612 }, + { 0x0445, 48698 }, + { 0x0446, 48970 }, + { 0x0447, 48858 }, + { 0x0448, 48966 }, + { 0x0449, 49189 }, + { 0x044A, 49028 }, + { 0x044B, 49121 }, + { 0x044C, 49100 }, + { 0x044D, 48539 }, + { 0x044E, 48833 }, + { 0x044F, 48821 }, + { 0x0450, 48730 }, + { 0x0451, 48736 }, + { 0x0452, 48881 }, + { 0x0453, 48930 }, + { 0x0454, 49377 }, + { 0x0455, 48889 }, + { 0x0456, 49387 }, + { 0x0457, 48825 }, + { 0x0458, 48740 }, + { 0x0459, 48950 }, + { 0x045A, 48954 }, + { 0x045B, 49109 }, + { 0x045C, 48938 }, + { 0x045D, 48553 }, + { 0x045E, 49205 }, + { 0x045F, 49012 }, + { 0x0460, 50062 }, + { 0x0461, 49164 }, + { 0x0462, 49880 }, + { 0x0463, 48982 }, + { 0x0464, 50173 }, + { 0x0465, 49275 }, + { 0x0466, 50132 }, + { 0x0467, 49234 }, + { 0x0468, 50196 }, + { 0x0469, 49298 }, + { 0x046A, 49751 }, + { 0x046B, 48853 }, + { 0x046C, 50178 }, + { 0x046D, 49280 }, + { 0x046E, 49840 }, + { 0x046F, 48942 }, + { 0x0470, 49856 }, + { 0x0471, 48958 }, + { 0x0472, 49922 }, + { 0x0473, 49024 }, + { 0x0474, 50151 }, + { 0x0475, 49253 }, + { 0x0476, 50155 }, + { 0x0477, 49257 }, + { 0x0478, 49707 }, + { 0x0479, 48809 }, + { 0x047A, 50072 }, + { 0x047B, 49174 }, + { 0x047C, 50066 }, + { 0x047D, 49168 }, + { 0x047E, 49671 }, + { 0x047F, 48773 }, + { 0x0480, 50058 }, + { 0x0481, 49160 }, + { 0x0482, 50303 }, + { 0x0483, 58017 }, + { 0x0484, 58185 }, + { 0x0485, 58009 }, + { 0x0486, 58013 }, + { 0x0487, 58177 }, + { 0x0488, 58165 }, + { 0x0489, 58173 }, + { 0x048A, 50096 }, + { 0x048B, 49198 }, + { 0x048C, 50217 }, + { 0x048D, 49323 }, + { 0x048E, 49580 }, + { 0x048F, 48682 }, + { 0x0490, 49816 }, + { 0x0491, 48918 }, + { 0x0492, 49802 }, + { 0x0493, 48904 }, + { 0x0494, 49795 }, + { 0x0495, 48897 }, + { 0x0496, 49894 }, + { 0x0497, 48996 }, + { 0x0498, 49739 }, + { 0x0499, 48841 }, + { 0x049A, 49665 }, + { 0x049B, 48767 }, + { 0x049C, 49658 }, + { 0x049D, 48760 }, + { 0x049E, 49652 }, + { 0x049F, 48754 }, + { 0x04A0, 50141 }, + { 0x04A1, 49243 }, + { 0x04A2, 49570 }, + { 0x04A3, 48672 }, + { 0x04A4, 50291 }, + { 0x04A5, 49397 }, + { 0x04A6, 49679 }, + { 0x04A7, 48781 }, + { 0x04A8, 50234 }, + { 0x04A9, 49340 }, + { 0x04AA, 49590 }, + { 0x04AB, 48692 }, + { 0x04AC, 49701 }, + { 0x04AD, 48803 }, + { 0x04AE, 50222 }, + { 0x04AF, 49328 }, + { 0x04B0, 50227 }, + { 0x04B1, 49333 }, + { 0x04B2, 49612 }, + { 0x04B3, 48714 }, + { 0x04B4, 50296 }, + { 0x04B5, 49402 }, + { 0x04B6, 49767 }, + { 0x04B7, 48869 }, + { 0x04B8, 49760 }, + { 0x04B9, 48862 }, + { 0x04BA, 49975 }, + { 0x04BB, 49077 }, + { 0x04BC, 50239 }, + { 0x04BD, 49345 }, + { 0x04BE, 50244 }, + { 0x04BF, 49350 }, + { 0x04C0, 49414 }, + { 0x04C1, 49888 }, + { 0x04C2, 48990 }, + { 0x04C3, 49646 }, + { 0x04C4, 48748 }, + { 0x04C5, 49524 }, + { 0x04C6, 48626 }, + { 0x04C7, 49551 }, + { 0x04C8, 48653 }, + { 0x04C9, 49557 }, + { 0x04CA, 48659 }, + { 0x04CB, 50276 }, + { 0x04CC, 49382 }, + { 0x04CD, 49541 }, + { 0x04CE, 48643 }, + { 0x04CF, 49304 }, + { 0x04D0, 49425 }, + { 0x04D1, 48527 }, + { 0x04D2, 49431 }, + { 0x04D3, 48533 }, + { 0x04D4, 50286 }, + { 0x04D5, 49392 }, + { 0x04D6, 49622 }, + { 0x04D7, 48724 }, + { 0x04D8, 50077 }, + { 0x04D9, 49179 }, + { 0x04DA, 50081 }, + { 0x04DB, 49183 }, + { 0x04DC, 49900 }, + { 0x04DD, 49002 }, + { 0x04DE, 49745 }, + { 0x04DF, 48847 }, + { 0x04E0, 50251 }, + { 0x04E1, 49357 }, + { 0x04E2, 49457 }, + { 0x04E3, 48559 }, + { 0x04E4, 49463 }, + { 0x04E5, 48565 }, + { 0x04E6, 49473 }, + { 0x04E7, 48575 }, + { 0x04E8, 50108 }, + { 0x04E9, 49210 }, + { 0x04EA, 50113 }, + { 0x04EB, 49215 }, + { 0x04EC, 49441 }, + { 0x04ED, 48543 }, + { 0x04EE, 49490 }, + { 0x04EF, 48592 }, + { 0x04F0, 49496 }, + { 0x04F1, 48598 }, + { 0x04F2, 49483 }, + { 0x04F3, 48585 }, + { 0x04F4, 49773 }, + { 0x04F5, 48875 }, + { 0x04F6, 49822 }, + { 0x04F7, 48924 }, + { 0x04F8, 50030 }, + { 0x04F9, 49132 }, + { 0x04FA, 49808 }, + { 0x04FB, 48910 }, + { 0x04FC, 49600 }, + { 0x04FD, 48702 }, + { 0x04FE, 49606 }, + { 0x04FF, 48708 }, + { 0x0500, 49935 }, + { 0x0501, 49037 }, + { 0x0502, 49940 }, + { 0x0503, 49042 }, + { 0x0504, 49965 }, + { 0x0505, 49067 }, + { 0x0506, 49970 }, + { 0x0507, 49072 }, + { 0x0508, 49945 }, + { 0x0509, 49047 }, + { 0x050A, 49950 }, + { 0x050B, 49052 }, + { 0x050C, 49955 }, + { 0x050D, 49057 }, + { 0x050E, 49960 }, + { 0x050F, 49062 }, + { 0x0510, 50207 }, + { 0x0511, 49313 }, + { 0x0512, 49518 }, + { 0x0513, 48620 }, + { 0x0514, 49844 }, + { 0x0515, 48946 }, + { 0x0516, 49860 }, + { 0x0517, 48962 }, + { 0x0518, 49876 }, + { 0x0519, 48978 }, + { 0x051A, 49686 }, + { 0x051B, 48788 }, + { 0x051C, 49715 }, + { 0x051D, 48817 }, + { 0x051E, 50040 }, + { 0x051F, 49142 }, + { 0x0520, 49530 }, + { 0x0521, 48632 }, + { 0x0522, 49563 }, + { 0x0523, 48665 }, + { 0x0531, 44961 }, + { 0x0532, 44965 }, + { 0x0533, 44981 }, + { 0x0534, 44917 }, + { 0x0535, 44973 }, + { 0x0536, 44957 }, + { 0x0537, 44921 }, + { 0x0538, 44925 }, + { 0x0539, 44945 }, + { 0x053A, 45029 }, + { 0x053B, 44985 }, + { 0x053C, 45045 }, + { 0x053D, 45025 }, + { 0x053E, 44909 }, + { 0x053F, 44993 }, + { 0x0540, 44929 }, + { 0x0541, 44933 }, + { 0x0542, 45037 }, + { 0x0543, 45033 }, + { 0x0544, 44997 }, + { 0x0545, 44953 }, + { 0x0546, 45001 }, + { 0x0547, 45017 }, + { 0x0548, 44949 }, + { 0x0549, 44969 }, + { 0x054A, 45005 }, + { 0x054B, 45041 }, + { 0x054C, 44941 }, + { 0x054D, 45013 }, + { 0x054E, 45021 }, + { 0x054F, 45053 }, + { 0x0550, 45009 }, + { 0x0551, 44913 }, + { 0x0552, 45057 }, + { 0x0553, 45049 }, + { 0x0554, 44989 }, + { 0x0555, 44937 }, + { 0x0556, 44977 }, + { 0x0559, 45064 }, + { 0x055A, 45073 }, + { 0x055B, 45061 }, + { 0x055C, 45075 }, + { 0x055D, 44723 }, + { 0x055E, 45070 }, + { 0x055F, 45078 }, + { 0x0561, 44777 }, + { 0x0562, 44781 }, + { 0x0563, 44797 }, + { 0x0564, 44733 }, + { 0x0565, 44789 }, + { 0x0566, 44773 }, + { 0x0567, 44737 }, + { 0x0568, 44741 }, + { 0x0569, 44761 }, + { 0x056A, 44845 }, + { 0x056B, 44801 }, + { 0x056C, 44861 }, + { 0x056D, 44841 }, + { 0x056E, 44725 }, + { 0x056F, 44809 }, + { 0x0570, 44745 }, + { 0x0571, 44749 }, + { 0x0572, 44853 }, + { 0x0573, 44849 }, + { 0x0574, 44813 }, + { 0x0575, 44769 }, + { 0x0576, 44817 }, + { 0x0577, 44833 }, + { 0x0578, 44765 }, + { 0x0579, 44785 }, + { 0x057A, 44821 }, + { 0x057B, 44857 }, + { 0x057C, 44757 }, + { 0x057D, 44829 }, + { 0x057E, 44837 }, + { 0x057F, 44869 }, + { 0x0580, 44825 }, + { 0x0581, 44729 }, + { 0x0582, 44873 }, + { 0x0583, 44865 }, + { 0x0584, 44805 }, + { 0x0585, 44753 }, + { 0x0586, 44793 }, + { 0x0587, 44877 }, + { 0x0589, 44720 }, + { 0x058A, 44907 }, + { 0x0591, 33056 }, + { 0x0592, 33004 }, + { 0x0593, 33073 }, + { 0x0594, 33022 }, + { 0x0595, 33018 }, + { 0x0596, 33053 }, + { 0x0597, 33001 }, + { 0x0598, 33026 }, + { 0x0599, 33046 }, + { 0x059A, 33015 }, + { 0x059B, 33007 }, + { 0x059C, 33032 }, + { 0x059D, 33035 }, + { 0x059E, 33070 }, + { 0x059F, 33049 }, + { 0x05A0, 33059 }, + { 0x05A1, 32995 }, + { 0x05A2, 32985 }, + { 0x05A3, 32992 }, + { 0x05A4, 33067 }, + { 0x05A5, 33039 }, + { 0x05A6, 33042 }, + { 0x05A7, 32989 }, + { 0x05A8, 32998 }, + { 0x05A9, 33063 }, + { 0x05AA, 33010 }, + { 0x05AB, 32976 }, + { 0x05AC, 32982 }, + { 0x05AD, 32979 }, + { 0x05AE, 33029 }, + { 0x05AF, 32903 }, + { 0x05B0, 32951 }, + { 0x05B1, 32922 }, + { 0x05B2, 32918 }, + { 0x05B3, 32926 }, + { 0x05B4, 32930 }, + { 0x05B5, 32954 }, + { 0x05B6, 32948 }, + { 0x05B7, 32945 }, + { 0x05B8, 32962 }, + { 0x05B9, 32933 }, + { 0x05BA, 32936 }, + { 0x05BB, 32969 }, + { 0x05BC, 32957 }, + { 0x05BD, 32942 }, + { 0x05BE, 33412 }, + { 0x05BF, 32911 }, + { 0x05C0, 33415 }, + { 0x05C1, 32914 }, + { 0x05C2, 32907 }, + { 0x05C3, 33408 }, + { 0x05C4, 32899 }, + { 0x05C5, 32895 }, + { 0x05C6, 33404 }, + { 0x05C7, 32965 }, + { 0x05D0, 33192 }, + { 0x05D1, 33097 }, + { 0x05D2, 33330 }, + { 0x05D3, 33290 }, + { 0x05D4, 33076 }, + { 0x05D5, 33166 }, + { 0x05D6, 33354 }, + { 0x05D7, 33110 }, + { 0x05D8, 33158 }, + { 0x05D9, 33179 }, + { 0x05DA, 33308 }, + { 0x05DB, 33113 }, + { 0x05DC, 33338 }, + { 0x05DD, 33318 }, + { 0x05DE, 33126 }, + { 0x05DF, 33322 }, + { 0x05E0, 33134 }, + { 0x05E1, 33362 }, + { 0x05E2, 33210 }, + { 0x05E3, 33298 }, + { 0x05E4, 33084 }, + { 0x05E5, 33326 }, + { 0x05E6, 33346 }, + { 0x05E7, 33142 }, + { 0x05E8, 33213 }, + { 0x05E9, 33221 }, + { 0x05EA, 33150 }, + { 0x05F0, 33394 }, + { 0x05F1, 33383 }, + { 0x05F2, 33399 }, + { 0x05F3, 33418 }, + { 0x05F4, 33421 }, + { 0x0600, 26405 }, + { 0x0601, 23733 }, + { 0x0602, 26459 }, + { 0x0603, 23730 }, + { 0x0606, 69351 }, + { 0x0607, 69384 }, + { 0x0608, 23706 }, + { 0x0609, 69347 }, + { 0x060A, 69342 }, + { 0x060B, 37776 }, + { 0x060C, 23764 }, + { 0x060D, 23708 }, + { 0x060E, 26408 }, + { 0x060F, 23727 }, + { 0x0610, 23756 }, + { 0x0611, 23736 }, + { 0x0612, 23752 }, + { 0x0613, 23722 }, + { 0x0614, 23749 }, + { 0x0615, 23840 }, + { 0x0616, 23923 }, + { 0x0617, 23872 }, + { 0x0618, 23935 }, + { 0x0619, 23932 }, + { 0x061A, 23938 }, + { 0x061B, 30222 }, + { 0x061E, 26422 }, + { 0x061F, 30214 }, + { 0x0621, 26056 }, + { 0x0622, 25371 }, + { 0x0623, 25327 }, + { 0x0624, 25097 }, + { 0x0625, 25349 }, + { 0x0626, 25155 }, + { 0x0627, 25310 }, + { 0x0628, 24144 }, + { 0x0629, 25027 }, + { 0x062A, 24996 }, + { 0x062B, 25851 }, + { 0x062C, 25554 }, + { 0x062D, 24447 }, + { 0x062E, 25577 }, + { 0x062F, 24260 }, + { 0x0630, 25838 }, + { 0x0631, 24833 }, + { 0x0632, 25897 }, + { 0x0633, 25747 }, + { 0x0634, 26192 }, + { 0x0635, 24929 }, + { 0x0636, 24231 }, + { 0x0637, 24966 }, + { 0x0638, 25287 }, + { 0x0639, 24090 }, + { 0x063A, 26027 }, + { 0x063B, 26073 }, + { 0x063C, 26087 }, + { 0x063D, 25996 }, + { 0x063E, 25950 }, + { 0x063F, 25958 }, + { 0x0640, 26440 }, + { 0x0641, 24346 }, + { 0x0642, 24797 }, + { 0x0643, 24672 }, + { 0x0644, 24720 }, + { 0x0645, 25600 }, + { 0x0646, 25635 }, + { 0x0647, 24545 }, + { 0x0648, 25076 }, + { 0x0649, 25432 }, + { 0x064A, 25147 }, + { 0x064B, 26453 }, + { 0x064C, 26447 }, + { 0x064D, 26465 }, + { 0x064E, 23786 }, + { 0x064F, 23766 }, + { 0x0650, 23807 }, + { 0x0651, 26412 }, + { 0x0652, 23947 }, + { 0x0653, 26402 }, + { 0x0654, 23801 }, + { 0x0655, 23804 }, + { 0x0656, 30224 }, + { 0x0657, 26462 }, + { 0x0658, 23718 }, + { 0x0659, 30220 }, + { 0x065A, 23962 }, + { 0x065B, 23968 }, + { 0x065C, 23957 }, + { 0x065D, 30217 }, + { 0x065E, 23788 }, + { 0x0660, 69372 }, + { 0x0661, 69354 }, + { 0x0662, 69360 }, + { 0x0663, 69381 }, + { 0x0664, 69366 }, + { 0x0665, 69363 }, + { 0x0666, 69357 }, + { 0x0667, 69378 }, + { 0x0668, 69375 }, + { 0x0669, 69369 }, + { 0x066A, 26430 }, + { 0x066B, 26427 }, + { 0x066C, 30227 }, + { 0x066D, 23711 }, + { 0x066E, 26331 }, + { 0x066F, 26339 }, + { 0x0670, 26398 }, + { 0x0671, 25416 }, + { 0x0672, 25313 }, + { 0x0673, 25320 }, + { 0x0674, 25535 }, + { 0x0675, 25549 }, + { 0x0676, 25539 }, + { 0x0677, 24001 }, + { 0x0678, 25544 }, + { 0x0679, 25874 }, + { 0x067A, 26290 }, + { 0x067B, 25453 }, + { 0x067C, 24999 }, + { 0x067D, 25004 }, + { 0x067E, 24774 }, + { 0x067F, 26254 }, + { 0x0680, 25910 }, + { 0x0681, 24465 }, + { 0x0682, 24457 }, + { 0x0683, 25711 }, + { 0x0684, 25489 }, + { 0x0685, 24500 }, + { 0x0686, 26225 }, + { 0x0687, 26375 }, + { 0x0688, 25476 }, + { 0x0689, 24296 }, + { 0x068A, 24263 }, + { 0x068B, 24269 }, + { 0x068C, 25933 }, + { 0x068D, 26277 }, + { 0x068E, 24333 }, + { 0x068F, 24301 }, + { 0x0690, 24289 }, + { 0x0691, 25734 }, + { 0x0692, 24884 }, + { 0x0693, 24873 }, + { 0x0694, 24836 }, + { 0x0695, 24890 }, + { 0x0696, 24842 }, + { 0x0697, 24851 }, + { 0x0698, 24659 }, + { 0x0699, 24866 }, + { 0x069A, 25750 }, + { 0x069B, 25785 }, + { 0x069C, 25792 }, + { 0x069D, 24932 }, + { 0x069E, 24939 }, + { 0x069F, 24969 }, + { 0x06A0, 24108 }, + { 0x06A1, 26335 }, + { 0x06A2, 24355 }, + { 0x06A3, 24349 }, + { 0x06A4, 25053 }, + { 0x06A5, 24369 }, + { 0x06A6, 26146 }, + { 0x06A7, 24800 }, + { 0x06A8, 24806 }, + { 0x06A9, 26064 }, + { 0x06AA, 26221 }, + { 0x06AB, 24688 }, + { 0x06AC, 24675 }, + { 0x06AD, 24028 }, + { 0x06AE, 24693 }, + { 0x06AF, 24405 }, + { 0x06B0, 24415 }, + { 0x06B1, 26123 }, + { 0x06B2, 24408 }, + { 0x06B3, 25512 }, + { 0x06B4, 24420 }, + { 0x06B5, 24734 }, + { 0x06B6, 24728 }, + { 0x06B7, 24740 }, + { 0x06B8, 24747 }, + { 0x06B9, 25638 }, + { 0x06BA, 25680 }, + { 0x06BB, 26169 }, + { 0x06BC, 25651 }, + { 0x06BD, 25668 }, + { 0x06BE, 24631 }, + { 0x06BF, 26228 }, + { 0x06C0, 24583 }, + { 0x06C1, 24548 }, + { 0x06C2, 24552 }, + { 0x06C3, 25031 }, + { 0x06C4, 25092 }, + { 0x06C5, 26343 }, + { 0x06C6, 24051 }, + { 0x06C7, 23998 }, + { 0x06C8, 24077 }, + { 0x06C9, 26359 }, + { 0x06CA, 25085 }, + { 0x06CB, 24064 }, + { 0x06CC, 25946 }, + { 0x06CD, 25150 }, + { 0x06CE, 25193 }, + { 0x06CF, 25079 }, + { 0x06D0, 23975 }, + { 0x06D1, 25199 }, + { 0x06D2, 25211 }, + { 0x06D3, 25215 }, + { 0x06D4, 23715 }, + { 0x06D5, 24025 }, + { 0x06D6, 23913 }, + { 0x06D7, 23903 }, + { 0x06D8, 23852 }, + { 0x06D9, 23835 }, + { 0x06DA, 23848 }, + { 0x06DB, 23880 }, + { 0x06DC, 23868 }, + { 0x06DD, 23702 }, + { 0x06DE, 23941 }, + { 0x06DF, 23892 }, + { 0x06E0, 23897 }, + { 0x06E1, 23885 }, + { 0x06E2, 23858 }, + { 0x06E3, 23825 }, + { 0x06E4, 23876 }, + { 0x06E5, 23829 }, + { 0x06E6, 23832 }, + { 0x06E7, 23844 }, + { 0x06E8, 23864 }, + { 0x06E9, 23817 }, + { 0x06EA, 23776 }, + { 0x06EB, 23781 }, + { 0x06EC, 26433 }, + { 0x06ED, 23821 }, + { 0x06EE, 24309 }, + { 0x06EF, 24913 }, + { 0x06F0, 51759 }, + { 0x06F1, 51735 }, + { 0x06F2, 51743 }, + { 0x06F3, 51771 }, + { 0x06F4, 51751 }, + { 0x06F5, 51747 }, + { 0x06F6, 51739 }, + { 0x06F7, 51767 }, + { 0x06F8, 51763 }, + { 0x06F9, 51755 }, + { 0x06FA, 26195 }, + { 0x06FB, 24234 }, + { 0x06FC, 26030 }, + { 0x06FD, 23740 }, + { 0x06FE, 23744 }, + { 0x06FF, 24605 }, + { 0x0700, 36871 }, + { 0x0701, 37114 }, + { 0x0702, 37094 }, + { 0x0703, 37118 }, + { 0x0704, 37098 }, + { 0x0705, 37106 }, + { 0x0706, 36885 }, + { 0x0707, 36889 }, + { 0x0708, 37121 }, + { 0x0709, 37101 }, + { 0x070A, 37109 }, + { 0x070B, 37081 }, + { 0x070C, 37084 }, + { 0x070D, 37087 }, + { 0x070F, 37126 }, + { 0x0710, 36987 }, + { 0x0711, 37046 }, + { 0x0712, 36952 }, + { 0x0713, 36994 }, + { 0x0714, 36997 }, + { 0x0715, 37004 }, + { 0x0716, 37010 }, + { 0x0717, 36934 }, + { 0x0718, 36949 }, + { 0x0719, 36984 }, + { 0x071A, 36955 }, + { 0x071B, 36970 }, + { 0x071C, 36973 }, + { 0x071D, 36977 }, + { 0x071E, 36980 }, + { 0x071F, 36958 }, + { 0x0720, 37007 }, + { 0x0721, 36940 }, + { 0x0722, 36943 }, + { 0x0723, 37027 }, + { 0x0724, 36990 }, + { 0x0725, 36931 }, + { 0x0726, 36937 }, + { 0x0727, 37042 }, + { 0x0728, 37001 }, + { 0x0729, 36961 }, + { 0x072A, 36964 }, + { 0x072B, 36967 }, + { 0x072C, 36946 }, + { 0x072D, 37015 }, + { 0x072E, 37019 }, + { 0x072F, 37023 }, + { 0x0730, 37050 }, + { 0x0731, 37053 }, + { 0x0732, 37056 }, + { 0x0733, 37059 }, + { 0x0734, 37062 }, + { 0x0735, 37065 }, + { 0x0736, 36907 }, + { 0x0737, 36910 }, + { 0x0738, 36927 }, + { 0x0739, 36923 }, + { 0x073A, 36899 }, + { 0x073B, 36902 }, + { 0x073C, 37111 }, + { 0x073D, 36893 }, + { 0x073E, 36896 }, + { 0x073F, 36913 }, + { 0x0740, 37078 }, + { 0x0741, 37092 }, + { 0x0742, 37090 }, + { 0x0743, 36875 }, + { 0x0744, 36880 }, + { 0x0745, 36915 }, + { 0x0746, 36919 }, + { 0x0747, 37070 }, + { 0x0748, 37074 }, + { 0x0749, 36905 }, + { 0x074A, 37068 }, + { 0x074D, 37038 }, + { 0x074E, 37034 }, + { 0x074F, 37030 }, + { 0x0750, 24195 }, + { 0x0751, 24147 }, + { 0x0752, 24173 }, + { 0x0753, 24182 }, + { 0x0754, 24157 }, + { 0x0755, 24203 }, + { 0x0756, 24167 }, + { 0x0757, 24450 }, + { 0x0758, 24507 }, + { 0x0759, 24278 }, + { 0x075A, 24315 }, + { 0x075B, 24908 }, + { 0x075C, 25767 }, + { 0x075D, 24093 }, + { 0x075E, 24115 }, + { 0x075F, 24100 }, + { 0x0760, 24362 }, + { 0x0761, 24376 }, + { 0x0762, 26067 }, + { 0x0763, 26080 }, + { 0x0764, 26094 }, + { 0x0765, 25603 }, + { 0x0766, 25609 }, + { 0x0767, 25644 }, + { 0x0768, 25662 }, + { 0x0769, 25656 }, + { 0x076A, 24723 }, + { 0x076B, 24858 }, + { 0x076C, 24878 }, + { 0x076D, 25759 }, + { 0x076E, 24491 }, + { 0x076F, 24471 }, + { 0x0770, 25774 }, + { 0x0771, 24897 }, + { 0x0772, 24482 }, + { 0x0773, 25393 }, + { 0x0774, 25402 }, + { 0x0775, 25966 }, + { 0x0776, 25986 }, + { 0x0777, 25976 }, + { 0x0778, 25119 }, + { 0x0779, 25128 }, + { 0x077A, 25240 }, + { 0x077B, 25250 }, + { 0x077C, 24516 }, + { 0x077D, 25803 }, + { 0x077E, 25812 }, + { 0x077F, 24681 }, + { 0x0780, 37486 }, + { 0x0781, 37591 }, + { 0x0782, 37534 }, + { 0x0783, 37492 }, + { 0x0784, 37483 }, + { 0x0785, 37588 }, + { 0x0786, 37525 }, + { 0x0787, 37516 }, + { 0x0788, 37543 }, + { 0x0789, 37531 }, + { 0x078A, 37519 }, + { 0x078B, 37552 }, + { 0x078C, 37510 }, + { 0x078D, 37528 }, + { 0x078E, 37522 }, + { 0x078F, 37585 }, + { 0x0790, 37540 }, + { 0x0791, 37567 }, + { 0x0792, 37579 }, + { 0x0793, 37576 }, + { 0x0794, 37495 }, + { 0x0795, 37573 }, + { 0x0796, 37570 }, + { 0x0797, 37582 }, + { 0x0798, 37513 }, + { 0x0799, 37504 }, + { 0x079A, 37507 }, + { 0x079B, 37564 }, + { 0x079C, 37498 }, + { 0x079D, 37561 }, + { 0x079E, 37558 }, + { 0x079F, 37549 }, + { 0x07A0, 37477 }, + { 0x07A1, 37480 }, + { 0x07A2, 37501 }, + { 0x07A3, 37555 }, + { 0x07A4, 37537 }, + { 0x07A5, 37546 }, + { 0x07A6, 37594 }, + { 0x07A7, 37604 }, + { 0x07A8, 37598 }, + { 0x07A9, 37606 }, + { 0x07AA, 37602 }, + { 0x07AB, 37612 }, + { 0x07AC, 37596 }, + { 0x07AD, 37608 }, + { 0x07AE, 37600 }, + { 0x07AF, 37610 }, + { 0x07B0, 37475 }, + { 0x07B1, 37489 }, + { 0x07C0, 6538 }, + { 0x07C1, 6520 }, + { 0x07C2, 6526 }, + { 0x07C3, 6547 }, + { 0x07C4, 6532 }, + { 0x07C5, 6529 }, + { 0x07C6, 6523 }, + { 0x07C7, 6544 }, + { 0x07C8, 6541 }, + { 0x07C9, 6535 }, + { 0x07CA, 6550 }, + { 0x07CB, 6574 }, + { 0x07CC, 6556 }, + { 0x07CD, 6553 }, + { 0x07CE, 6565 }, + { 0x07CF, 6602 }, + { 0x07D0, 6562 }, + { 0x07D1, 6651 }, + { 0x07D2, 6559 }, + { 0x07D3, 6568 }, + { 0x07D4, 6605 }, + { 0x07D5, 6614 }, + { 0x07D6, 6583 }, + { 0x07D7, 6623 }, + { 0x07D8, 6571 }, + { 0x07D9, 6608 }, + { 0x07DA, 6636 }, + { 0x07DB, 6611 }, + { 0x07DC, 6626 }, + { 0x07DD, 6577 }, + { 0x07DE, 6586 }, + { 0x07DF, 6589 }, + { 0x07E0, 6598 }, + { 0x07E1, 6592 }, + { 0x07E2, 6629 }, + { 0x07E3, 6595 }, + { 0x07E4, 6580 }, + { 0x07E5, 6617 }, + { 0x07E6, 6620 }, + { 0x07E7, 6632 }, + { 0x07E8, 6639 }, + { 0x07E9, 6647 }, + { 0x07EA, 6643 }, + { 0x07EB, 6686 }, + { 0x07EC, 6681 }, + { 0x07ED, 6691 }, + { 0x07EE, 6676 }, + { 0x07EF, 6666 }, + { 0x07F0, 6661 }, + { 0x07F1, 6671 }, + { 0x07F2, 6701 }, + { 0x07F3, 6696 }, + { 0x07F4, 6514 }, + { 0x07F5, 6510 }, + { 0x07F6, 6654 }, + { 0x07F7, 6658 }, + { 0x07F8, 6518 }, + { 0x07F9, 6707 }, + { 0x07FA, 6705 }, + { 0x0901, 66870 }, + { 0x0902, 66864 }, + { 0x0903, 66861 }, + { 0x0904, 67167 }, + { 0x0905, 66990 }, + { 0x0906, 67005 }, + { 0x0907, 66996 }, + { 0x0908, 67032 }, + { 0x0909, 67002 }, + { 0x090A, 67065 }, + { 0x090B, 67199 }, + { 0x090C, 67195 }, + { 0x090D, 67183 }, + { 0x090E, 67171 }, + { 0x090F, 66993 }, + { 0x0910, 67008 }, + { 0x0911, 67187 }, + { 0x0912, 67175 }, + { 0x0913, 66999 }, + { 0x0914, 67011 }, + { 0x0915, 67038 }, + { 0x0916, 67104 }, + { 0x0917, 67026 }, + { 0x0918, 67095 }, + { 0x0919, 67110 }, + { 0x091A, 67017 }, + { 0x091B, 67083 }, + { 0x091C, 67035 }, + { 0x091D, 67098 }, + { 0x091E, 67116 }, + { 0x091F, 67137 }, + { 0x0920, 67161 }, + { 0x0921, 67086 }, + { 0x0922, 67146 }, + { 0x0923, 67113 }, + { 0x0924, 67062 }, + { 0x0925, 67134 }, + { 0x0926, 67020 }, + { 0x0927, 67089 }, + { 0x0928, 67047 }, + { 0x0929, 67158 }, + { 0x092A, 67050 }, + { 0x092B, 67119 }, + { 0x092C, 67014 }, + { 0x092D, 67080 }, + { 0x092E, 67044 }, + { 0x092F, 67071 }, + { 0x0930, 67056 }, + { 0x0931, 67125 }, + { 0x0932, 67041 }, + { 0x0933, 67107 }, + { 0x0934, 67155 }, + { 0x0935, 67068 }, + { 0x0936, 67128 }, + { 0x0937, 67131 }, + { 0x0938, 67059 }, + { 0x0939, 67029 }, + { 0x093C, 66855 }, + { 0x093D, 66867 }, + { 0x093E, 66927 }, + { 0x093F, 66915 }, + { 0x0940, 66939 }, + { 0x0941, 66923 }, + { 0x0942, 66943 }, + { 0x0943, 66972 }, + { 0x0944, 66982 }, + { 0x0945, 66957 }, + { 0x0946, 66947 }, + { 0x0947, 66911 }, + { 0x0948, 66931 }, + { 0x0949, 66962 }, + { 0x094A, 66952 }, + { 0x094B, 66919 }, + { 0x094C, 66935 }, + { 0x094D, 66858 }, + { 0x0950, 66848 }, + { 0x0951, 67211 }, + { 0x0952, 67215 }, + { 0x0953, 66908 }, + { 0x0954, 66873 }, + { 0x0958, 67053 }, + { 0x0959, 67152 }, + { 0x095A, 67149 }, + { 0x095B, 67074 }, + { 0x095C, 67164 }, + { 0x095D, 67122 }, + { 0x095E, 67023 }, + { 0x095F, 67140 }, + { 0x0960, 67207 }, + { 0x0961, 67203 }, + { 0x0962, 66967 }, + { 0x0963, 66977 }, + { 0x0964, 66876 }, + { 0x0965, 66987 }, + { 0x0966, 66896 }, + { 0x0967, 66878 }, + { 0x0968, 66884 }, + { 0x0969, 66905 }, + { 0x096A, 66890 }, + { 0x096B, 66887 }, + { 0x096C, 66881 }, + { 0x096D, 66902 }, + { 0x096E, 66899 }, + { 0x096F, 66893 }, + { 0x0970, 67219 }, + { 0x0971, 66850 }, + { 0x0972, 67179 }, + { 0x097B, 67092 }, + { 0x097C, 67101 }, + { 0x097D, 67191 }, + { 0x097E, 67143 }, + { 0x097F, 67077 }, + { 0x0981, 37801 }, + { 0x0982, 37795 }, + { 0x0983, 37792 }, + { 0x0985, 37898 }, + { 0x0986, 37913 }, + { 0x0987, 37904 }, + { 0x0988, 37937 }, + { 0x0989, 37910 }, + { 0x098A, 37979 }, + { 0x098B, 38053 }, + { 0x098C, 38049 }, + { 0x098F, 37901 }, + { 0x0990, 37916 }, + { 0x0993, 37907 }, + { 0x0994, 37919 }, + { 0x0995, 37943 }, + { 0x0996, 38003 }, + { 0x0997, 37931 }, + { 0x0998, 37997 }, + { 0x0999, 38006 }, + { 0x099A, 37925 }, + { 0x099B, 37988 }, + { 0x099C, 37940 }, + { 0x099D, 38000 }, + { 0x099E, 38012 }, + { 0x099F, 38033 }, + { 0x09A0, 38042 }, + { 0x09A1, 37991 }, + { 0x09A2, 38039 }, + { 0x09A3, 38009 }, + { 0x09A4, 37976 }, + { 0x09A5, 38030 }, + { 0x09A6, 37928 }, + { 0x09A7, 37994 }, + { 0x09A8, 37952 }, + { 0x09AA, 37955 }, + { 0x09AB, 38015 }, + { 0x09AC, 37922 }, + { 0x09AD, 37985 }, + { 0x09AE, 37949 }, + { 0x09AF, 37982 }, + { 0x09B0, 37958 }, + { 0x09B2, 37946 }, + { 0x09B6, 38024 }, + { 0x09B7, 38027 }, + { 0x09B8, 37973 }, + { 0x09B9, 37934 }, + { 0x09BC, 37786 }, + { 0x09BD, 37798 }, + { 0x09BE, 37856 }, + { 0x09BF, 37844 }, + { 0x09C0, 37868 }, + { 0x09C1, 37852 }, + { 0x09C2, 37872 }, + { 0x09C3, 37881 }, + { 0x09C4, 37891 }, + { 0x09C7, 37840 }, + { 0x09C8, 37860 }, + { 0x09CB, 37848 }, + { 0x09CC, 37864 }, + { 0x09CD, 37789 }, + { 0x09CE, 38045 }, + { 0x09D7, 37782 }, + { 0x09DC, 38021 }, + { 0x09DD, 38018 }, + { 0x09DF, 38036 }, + { 0x09E0, 38061 }, + { 0x09E1, 38057 }, + { 0x09E2, 37876 }, + { 0x09E3, 37886 }, + { 0x09E6, 37822 }, + { 0x09E7, 37804 }, + { 0x09E8, 37810 }, + { 0x09E9, 37831 }, + { 0x09EA, 37816 }, + { 0x09EB, 37813 }, + { 0x09EC, 37807 }, + { 0x09ED, 37828 }, + { 0x09EE, 37825 }, + { 0x09EF, 37819 }, + { 0x09F0, 37967 }, + { 0x09F1, 37961 }, + { 0x09F2, 37834 }, + { 0x09F3, 37837 }, + { 0x09F4, 38065 }, + { 0x09F5, 38077 }, + { 0x09F6, 38085 }, + { 0x09F7, 38081 }, + { 0x09F8, 38069 }, + { 0x09F9, 38089 }, + { 0x09FA, 37896 }, + { 0x0A01, 52505 }, + { 0x0A02, 52509 }, + { 0x0A03, 52524 }, + { 0x0A05, 52597 }, + { 0x0A06, 52606 }, + { 0x0A07, 52600 }, + { 0x0A08, 52636 }, + { 0x0A09, 52603 }, + { 0x0A0A, 52669 }, + { 0x0A0F, 52624 }, + { 0x0A10, 52609 }, + { 0x0A13, 52654 }, + { 0x0A14, 52612 }, + { 0x0A15, 52642 }, + { 0x0A16, 52699 }, + { 0x0A17, 52630 }, + { 0x0A18, 52693 }, + { 0x0A19, 52705 }, + { 0x0A1A, 52618 }, + { 0x0A1B, 52684 }, + { 0x0A1C, 52639 }, + { 0x0A1D, 52696 }, + { 0x0A1E, 52711 }, + { 0x0A1F, 52726 }, + { 0x0A20, 52738 }, + { 0x0A21, 52687 }, + { 0x0A22, 52729 }, + { 0x0A23, 52708 }, + { 0x0A24, 52666 }, + { 0x0A25, 52723 }, + { 0x0A26, 52621 }, + { 0x0A27, 52690 }, + { 0x0A28, 52651 }, + { 0x0A2A, 52657 }, + { 0x0A2B, 52714 }, + { 0x0A2C, 52615 }, + { 0x0A2D, 52681 }, + { 0x0A2E, 52648 }, + { 0x0A2F, 52675 }, + { 0x0A30, 52660 }, + { 0x0A32, 52645 }, + { 0x0A33, 52702 }, + { 0x0A35, 52672 }, + { 0x0A36, 52720 }, + { 0x0A38, 52663 }, + { 0x0A39, 52633 }, + { 0x0A3C, 52512 }, + { 0x0A3E, 52569 }, + { 0x0A3F, 52561 }, + { 0x0A40, 52585 }, + { 0x0A41, 52565 }, + { 0x0A42, 52593 }, + { 0x0A47, 52581 }, + { 0x0A48, 52573 }, + { 0x0A4B, 52589 }, + { 0x0A4C, 52577 }, + { 0x0A4D, 52518 }, + { 0x0A51, 52515 }, + { 0x0A59, 52735 }, + { 0x0A5A, 52732 }, + { 0x0A5B, 52678 }, + { 0x0A5C, 52717 }, + { 0x0A5E, 52627 }, + { 0x0A66, 52547 }, + { 0x0A67, 52529 }, + { 0x0A68, 52535 }, + { 0x0A69, 52556 }, + { 0x0A6A, 52541 }, + { 0x0A6B, 52538 }, + { 0x0A6C, 52532 }, + { 0x0A6D, 52553 }, + { 0x0A6E, 52550 }, + { 0x0A6F, 52544 }, + { 0x0A70, 52559 }, + { 0x0A71, 52527 }, + { 0x0A72, 52501 }, + { 0x0A73, 52503 }, + { 0x0A74, 52498 }, + { 0x0A75, 52521 }, + { 0x0A81, 52240 }, + { 0x0A82, 52234 }, + { 0x0A83, 52231 }, + { 0x0A85, 52350 }, + { 0x0A86, 52365 }, + { 0x0A87, 52356 }, + { 0x0A88, 52389 }, + { 0x0A89, 52362 }, + { 0x0A8A, 52419 }, + { 0x0A8B, 52486 }, + { 0x0A8C, 52482 }, + { 0x0A8D, 52342 }, + { 0x0A8F, 52353 }, + { 0x0A90, 52368 }, + { 0x0A91, 52346 }, + { 0x0A93, 52359 }, + { 0x0A94, 52371 }, + { 0x0A95, 52395 }, + { 0x0A96, 52446 }, + { 0x0A97, 52383 }, + { 0x0A98, 52440 }, + { 0x0A99, 52452 }, + { 0x0A9A, 52377 }, + { 0x0A9B, 52431 }, + { 0x0A9C, 52392 }, + { 0x0A9D, 52443 }, + { 0x0A9E, 52458 }, + { 0x0A9F, 52473 }, + { 0x0AA0, 52479 }, + { 0x0AA1, 52434 }, + { 0x0AA2, 52476 }, + { 0x0AA3, 52455 }, + { 0x0AA4, 52416 }, + { 0x0AA5, 52470 }, + { 0x0AA6, 52380 }, + { 0x0AA7, 52437 }, + { 0x0AA8, 52404 }, + { 0x0AAA, 52407 }, + { 0x0AAB, 52461 }, + { 0x0AAC, 52374 }, + { 0x0AAD, 52428 }, + { 0x0AAE, 52401 }, + { 0x0AAF, 52425 }, + { 0x0AB0, 52410 }, + { 0x0AB2, 52398 }, + { 0x0AB3, 52449 }, + { 0x0AB5, 52422 }, + { 0x0AB6, 52464 }, + { 0x0AB7, 52467 }, + { 0x0AB8, 52413 }, + { 0x0AB9, 52386 }, + { 0x0ABC, 52225 }, + { 0x0ABD, 52237 }, + { 0x0ABE, 52292 }, + { 0x0ABF, 52280 }, + { 0x0AC0, 52304 }, + { 0x0AC1, 52288 }, + { 0x0AC2, 52308 }, + { 0x0AC3, 52327 }, + { 0x0AC4, 52337 }, + { 0x0AC5, 52312 }, + { 0x0AC7, 52276 }, + { 0x0AC8, 52296 }, + { 0x0AC9, 52317 }, + { 0x0ACB, 52284 }, + { 0x0ACC, 52300 }, + { 0x0ACD, 52228 }, + { 0x0AD0, 52223 }, + { 0x0AE0, 52494 }, + { 0x0AE1, 52490 }, + { 0x0AE2, 52322 }, + { 0x0AE3, 52332 }, + { 0x0AE6, 52261 }, + { 0x0AE7, 52243 }, + { 0x0AE8, 52249 }, + { 0x0AE9, 52270 }, + { 0x0AEA, 52255 }, + { 0x0AEB, 52252 }, + { 0x0AEC, 52246 }, + { 0x0AED, 52267 }, + { 0x0AEE, 52264 }, + { 0x0AEF, 52258 }, + { 0x0AF1, 52273 }, + { 0x0B01, 21480 }, + { 0x0B02, 21474 }, + { 0x0B03, 21471 }, + { 0x0B05, 21571 }, + { 0x0B06, 21586 }, + { 0x0B07, 21577 }, + { 0x0B08, 21610 }, + { 0x0B09, 21583 }, + { 0x0B0A, 21640 }, + { 0x0B0B, 21719 }, + { 0x0B0C, 21715 }, + { 0x0B0F, 21574 }, + { 0x0B10, 21589 }, + { 0x0B13, 21580 }, + { 0x0B14, 21592 }, + { 0x0B15, 21616 }, + { 0x0B16, 21670 }, + { 0x0B17, 21604 }, + { 0x0B18, 21664 }, + { 0x0B19, 21676 }, + { 0x0B1A, 21598 }, + { 0x0B1B, 21655 }, + { 0x0B1C, 21613 }, + { 0x0B1D, 21667 }, + { 0x0B1E, 21682 }, + { 0x0B1F, 21703 }, + { 0x0B20, 21712 }, + { 0x0B21, 21658 }, + { 0x0B22, 21709 }, + { 0x0B23, 21679 }, + { 0x0B24, 21637 }, + { 0x0B25, 21700 }, + { 0x0B26, 21601 }, + { 0x0B27, 21661 }, + { 0x0B28, 21625 }, + { 0x0B2A, 21628 }, + { 0x0B2B, 21685 }, + { 0x0B2C, 21595 }, + { 0x0B2D, 21652 }, + { 0x0B2E, 21622 }, + { 0x0B2F, 21649 }, + { 0x0B30, 21631 }, + { 0x0B32, 21619 }, + { 0x0B33, 21673 }, + { 0x0B35, 21643 }, + { 0x0B36, 21694 }, + { 0x0B37, 21697 }, + { 0x0B38, 21634 }, + { 0x0B39, 21607 }, + { 0x0B3C, 21465 }, + { 0x0B3D, 21477 }, + { 0x0B3E, 21529 }, + { 0x0B3F, 21517 }, + { 0x0B40, 21541 }, + { 0x0B41, 21525 }, + { 0x0B42, 21545 }, + { 0x0B43, 21554 }, + { 0x0B44, 21564 }, + { 0x0B47, 21513 }, + { 0x0B48, 21533 }, + { 0x0B4B, 21521 }, + { 0x0B4C, 21537 }, + { 0x0B4D, 21468 }, + { 0x0B56, 21457 }, + { 0x0B57, 21461 }, + { 0x0B5C, 21691 }, + { 0x0B5D, 21688 }, + { 0x0B5F, 21706 }, + { 0x0B60, 21727 }, + { 0x0B61, 21723 }, + { 0x0B62, 21549 }, + { 0x0B63, 21559 }, + { 0x0B66, 21501 }, + { 0x0B67, 21483 }, + { 0x0B68, 21489 }, + { 0x0B69, 21510 }, + { 0x0B6A, 21495 }, + { 0x0B6B, 21492 }, + { 0x0B6C, 21486 }, + { 0x0B6D, 21507 }, + { 0x0B6E, 21504 }, + { 0x0B6F, 21498 }, + { 0x0B70, 21569 }, + { 0x0B71, 21646 }, + { 0x0B82, 22772 }, + { 0x0B83, 22769 }, + { 0x0B85, 22864 }, + { 0x0B86, 22879 }, + { 0x0B87, 22870 }, + { 0x0B88, 22897 }, + { 0x0B89, 22876 }, + { 0x0B8A, 22930 }, + { 0x0B8E, 22867 }, + { 0x0B8F, 22891 }, + { 0x0B90, 22882 }, + { 0x0B92, 22873 }, + { 0x0B93, 22915 }, + { 0x0B94, 22885 }, + { 0x0B95, 22903 }, + { 0x0B99, 22942 }, + { 0x0B9A, 22888 }, + { 0x0B9C, 22900 }, + { 0x0B9E, 22948 }, + { 0x0B9F, 22960 }, + { 0x0BA3, 22945 }, + { 0x0BA4, 22927 }, + { 0x0BA8, 22912 }, + { 0x0BA9, 22966 }, + { 0x0BAA, 22918 }, + { 0x0BAE, 22909 }, + { 0x0BAF, 22936 }, + { 0x0BB0, 22921 }, + { 0x0BB1, 22951 }, + { 0x0BB2, 22906 }, + { 0x0BB3, 22939 }, + { 0x0BB4, 22963 }, + { 0x0BB5, 22933 }, + { 0x0BB6, 22954 }, + { 0x0BB7, 22957 }, + { 0x0BB8, 22924 }, + { 0x0BB9, 22894 }, + { 0x0BBE, 22833 }, + { 0x0BBF, 22821 }, + { 0x0BC0, 22849 }, + { 0x0BC1, 22829 }, + { 0x0BC2, 22857 }, + { 0x0BC6, 22817 }, + { 0x0BC7, 22845 }, + { 0x0BC8, 22837 }, + { 0x0BCA, 22825 }, + { 0x0BCB, 22853 }, + { 0x0BCC, 22841 }, + { 0x0BCD, 22766 }, + { 0x0BD0, 22761 }, + { 0x0BD7, 22757 }, + { 0x0BE6, 22799 }, + { 0x0BE7, 22781 }, + { 0x0BE8, 22787 }, + { 0x0BE9, 22808 }, + { 0x0BEA, 22793 }, + { 0x0BEB, 22790 }, + { 0x0BEC, 22784 }, + { 0x0BED, 22805 }, + { 0x0BEE, 22802 }, + { 0x0BEF, 22796 }, + { 0x0BF0, 22977 }, + { 0x0BF1, 22969 }, + { 0x0BF2, 22973 }, + { 0x0BF3, 22763 }, + { 0x0BF4, 22811 }, + { 0x0BF5, 22775 }, + { 0x0BF6, 22778 }, + { 0x0BF7, 22861 }, + { 0x0BF8, 22753 }, + { 0x0BF9, 22814 }, + { 0x0BFA, 22980 }, + { 0x0C01, 37149 }, + { 0x0C02, 37143 }, + { 0x0C03, 37140 }, + { 0x0C05, 37249 }, + { 0x0C06, 37264 }, + { 0x0C07, 37255 }, + { 0x0C08, 37291 }, + { 0x0C09, 37261 }, + { 0x0C0A, 37324 }, + { 0x0C0B, 37400 }, + { 0x0C0C, 37396 }, + { 0x0C0E, 37252 }, + { 0x0C0F, 37282 }, + { 0x0C10, 37267 }, + { 0x0C12, 37258 }, + { 0x0C13, 37309 }, + { 0x0C14, 37270 }, + { 0x0C15, 37297 }, + { 0x0C16, 37354 }, + { 0x0C17, 37285 }, + { 0x0C18, 37348 }, + { 0x0C19, 37360 }, + { 0x0C1A, 37276 }, + { 0x0C1B, 37336 }, + { 0x0C1C, 37294 }, + { 0x0C1D, 37351 }, + { 0x0C1E, 37366 }, + { 0x0C1F, 37387 }, + { 0x0C20, 37393 }, + { 0x0C21, 37339 }, + { 0x0C22, 37390 }, + { 0x0C23, 37363 }, + { 0x0C24, 37321 }, + { 0x0C25, 37381 }, + { 0x0C26, 37279 }, + { 0x0C27, 37342 }, + { 0x0C28, 37306 }, + { 0x0C2A, 37312 }, + { 0x0C2B, 37369 }, + { 0x0C2C, 37273 }, + { 0x0C2D, 37333 }, + { 0x0C2E, 37303 }, + { 0x0C2F, 37330 }, + { 0x0C30, 37315 }, + { 0x0C31, 37372 }, + { 0x0C32, 37300 }, + { 0x0C33, 37357 }, + { 0x0C35, 37327 }, + { 0x0C36, 37375 }, + { 0x0C37, 37378 }, + { 0x0C38, 37318 }, + { 0x0C39, 37288 }, + { 0x0C3D, 37146 }, + { 0x0C3E, 37198 }, + { 0x0C3F, 37186 }, + { 0x0C40, 37214 }, + { 0x0C41, 37194 }, + { 0x0C42, 37222 }, + { 0x0C43, 37231 }, + { 0x0C44, 37241 }, + { 0x0C46, 37182 }, + { 0x0C47, 37210 }, + { 0x0C48, 37202 }, + { 0x0C4A, 37190 }, + { 0x0C4B, 37218 }, + { 0x0C4C, 37206 }, + { 0x0C4D, 37137 }, + { 0x0C55, 37246 }, + { 0x0C56, 37130 }, + { 0x0C58, 37384 }, + { 0x0C59, 37345 }, + { 0x0C60, 37408 }, + { 0x0C61, 37404 }, + { 0x0C62, 37226 }, + { 0x0C63, 37236 }, + { 0x0C66, 37170 }, + { 0x0C67, 37152 }, + { 0x0C68, 37158 }, + { 0x0C69, 37179 }, + { 0x0C6A, 37164 }, + { 0x0C6B, 37161 }, + { 0x0C6C, 37155 }, + { 0x0C6D, 37176 }, + { 0x0C6E, 37173 }, + { 0x0C6F, 37167 }, + { 0x0C78, 37448 }, + { 0x0C79, 37412 }, + { 0x0C7A, 37430 }, + { 0x0C7B, 37457 }, + { 0x0C7C, 37421 }, + { 0x0C7D, 37439 }, + { 0x0C7E, 37466 }, + { 0x0C7F, 37134 }, + { 0x0C82, 40655 }, + { 0x0C83, 40652 }, + { 0x0C85, 40764 }, + { 0x0C86, 40779 }, + { 0x0C87, 40770 }, + { 0x0C88, 40809 }, + { 0x0C89, 40776 }, + { 0x0C8A, 40842 }, + { 0x0C8B, 40912 }, + { 0x0C8C, 40908 }, + { 0x0C8E, 40767 }, + { 0x0C8F, 40797 }, + { 0x0C90, 40782 }, + { 0x0C92, 40773 }, + { 0x0C93, 40827 }, + { 0x0C94, 40785 }, + { 0x0C95, 40815 }, + { 0x0C96, 40869 }, + { 0x0C97, 40803 }, + { 0x0C98, 40863 }, + { 0x0C99, 40875 }, + { 0x0C9A, 40791 }, + { 0x0C9B, 40854 }, + { 0x0C9C, 40812 }, + { 0x0C9D, 40866 }, + { 0x0C9E, 40881 }, + { 0x0C9F, 40899 }, + { 0x0CA0, 40905 }, + { 0x0CA1, 40857 }, + { 0x0CA2, 40902 }, + { 0x0CA3, 40878 }, + { 0x0CA4, 40839 }, + { 0x0CA5, 40896 }, + { 0x0CA6, 40794 }, + { 0x0CA7, 40860 }, + { 0x0CA8, 40824 }, + { 0x0CAA, 40830 }, + { 0x0CAB, 40884 }, + { 0x0CAC, 40788 }, + { 0x0CAD, 40851 }, + { 0x0CAE, 40821 }, + { 0x0CAF, 40848 }, + { 0x0CB0, 40833 }, + { 0x0CB1, 40887 }, + { 0x0CB2, 40818 }, + { 0x0CB3, 40872 }, + { 0x0CB5, 40845 }, + { 0x0CB6, 40890 }, + { 0x0CB7, 40893 }, + { 0x0CB8, 40836 }, + { 0x0CB9, 40806 }, + { 0x0CBC, 40646 }, + { 0x0CBD, 40658 }, + { 0x0CBE, 40713 }, + { 0x0CBF, 40701 }, + { 0x0CC0, 40729 }, + { 0x0CC1, 40709 }, + { 0x0CC2, 40737 }, + { 0x0CC3, 40746 }, + { 0x0CC4, 40756 }, + { 0x0CC6, 40697 }, + { 0x0CC7, 40725 }, + { 0x0CC8, 40717 }, + { 0x0CCA, 40705 }, + { 0x0CCB, 40733 }, + { 0x0CCC, 40721 }, + { 0x0CCD, 40649 }, + { 0x0CD5, 40761 }, + { 0x0CD6, 40642 }, + { 0x0CDE, 40800 }, + { 0x0CE0, 40920 }, + { 0x0CE1, 40916 }, + { 0x0CE2, 40741 }, + { 0x0CE3, 40751 }, + { 0x0CE6, 40685 }, + { 0x0CE7, 40667 }, + { 0x0CE8, 40673 }, + { 0x0CE9, 40694 }, + { 0x0CEA, 40679 }, + { 0x0CEB, 40676 }, + { 0x0CEC, 40670 }, + { 0x0CED, 40691 }, + { 0x0CEE, 40688 }, + { 0x0CEF, 40682 }, + { 0x0CF1, 40661 }, + { 0x0CF2, 40664 }, + { 0x0D02, 64805 }, + { 0x0D03, 64802 }, + { 0x0D05, 64905 }, + { 0x0D06, 64920 }, + { 0x0D07, 64911 }, + { 0x0D08, 64947 }, + { 0x0D09, 64917 }, + { 0x0D0A, 64980 }, + { 0x0D0B, 65077 }, + { 0x0D0C, 65073 }, + { 0x0D0E, 64908 }, + { 0x0D0F, 64938 }, + { 0x0D10, 64923 }, + { 0x0D12, 64914 }, + { 0x0D13, 64965 }, + { 0x0D14, 64926 }, + { 0x0D15, 64953 }, + { 0x0D16, 65007 }, + { 0x0D17, 64941 }, + { 0x0D18, 65001 }, + { 0x0D19, 65013 }, + { 0x0D1A, 64932 }, + { 0x0D1B, 64992 }, + { 0x0D1C, 64950 }, + { 0x0D1D, 65004 }, + { 0x0D1E, 65019 }, + { 0x0D1F, 65037 }, + { 0x0D20, 65046 }, + { 0x0D21, 64995 }, + { 0x0D22, 65040 }, + { 0x0D23, 65016 }, + { 0x0D24, 64977 }, + { 0x0D25, 65034 }, + { 0x0D26, 64935 }, + { 0x0D27, 64998 }, + { 0x0D28, 64962 }, + { 0x0D2A, 64968 }, + { 0x0D2B, 65022 }, + { 0x0D2C, 64929 }, + { 0x0D2D, 64989 }, + { 0x0D2E, 64959 }, + { 0x0D2F, 64986 }, + { 0x0D30, 64971 }, + { 0x0D31, 65025 }, + { 0x0D32, 64956 }, + { 0x0D33, 65010 }, + { 0x0D34, 65043 }, + { 0x0D35, 64983 }, + { 0x0D36, 65028 }, + { 0x0D37, 65031 }, + { 0x0D38, 64974 }, + { 0x0D39, 64944 }, + { 0x0D3D, 64808 }, + { 0x0D3E, 64857 }, + { 0x0D3F, 64845 }, + { 0x0D40, 64873 }, + { 0x0D41, 64853 }, + { 0x0D42, 64881 }, + { 0x0D43, 64890 }, + { 0x0D44, 64900 }, + { 0x0D46, 64841 }, + { 0x0D47, 64869 }, + { 0x0D48, 64861 }, + { 0x0D4A, 64849 }, + { 0x0D4B, 64877 }, + { 0x0D4C, 64865 }, + { 0x0D4D, 64799 }, + { 0x0D57, 64792 }, + { 0x0D60, 65085 }, + { 0x0D61, 65081 }, + { 0x0D62, 64885 }, + { 0x0D63, 64895 }, + { 0x0D66, 64829 }, + { 0x0D67, 64811 }, + { 0x0D68, 64817 }, + { 0x0D69, 64838 }, + { 0x0D6A, 64823 }, + { 0x0D6B, 64820 }, + { 0x0D6C, 64814 }, + { 0x0D6D, 64835 }, + { 0x0D6E, 64832 }, + { 0x0D6F, 64826 }, + { 0x0D70, 65097 }, + { 0x0D71, 65089 }, + { 0x0D72, 65093 }, + { 0x0D73, 65104 }, + { 0x0D74, 65100 }, + { 0x0D75, 65108 }, + { 0x0D79, 64796 }, + { 0x0D7A, 65065 }, + { 0x0D7B, 65057 }, + { 0x0D7C, 65069 }, + { 0x0D7D, 65053 }, + { 0x0D7E, 65061 }, + { 0x0D7F, 65049 }, + { 0x0D82, 43201 }, + { 0x0D83, 43198 }, + { 0x0D85, 43293 }, + { 0x0D86, 43308 }, + { 0x0D87, 43311 }, + { 0x0D88, 43395 }, + { 0x0D89, 43299 }, + { 0x0D8A, 43341 }, + { 0x0D8B, 43305 }, + { 0x0D8C, 43386 }, + { 0x0D8D, 43401 }, + { 0x0D8E, 43407 }, + { 0x0D8F, 43398 }, + { 0x0D90, 43404 }, + { 0x0D91, 43296 }, + { 0x0D92, 43332 }, + { 0x0D93, 43314 }, + { 0x0D94, 43302 }, + { 0x0D95, 43351 }, + { 0x0D96, 43317 }, + { 0x0D9A, 43442 }, + { 0x0D9B, 43482 }, + { 0x0D9C, 43434 }, + { 0x0D9D, 43474 }, + { 0x0D9E, 43344 }, + { 0x0D9F, 43361 }, + { 0x0DA0, 43426 }, + { 0x0DA1, 43466 }, + { 0x0DA2, 43438 }, + { 0x0DA3, 43478 }, + { 0x0DA4, 43382 }, + { 0x0DA5, 43377 }, + { 0x0DA6, 43365 }, + { 0x0DA7, 43458 }, + { 0x0DA8, 43498 }, + { 0x0DA9, 43454 }, + { 0x0DAA, 43494 }, + { 0x0DAB, 43414 }, + { 0x0DAC, 43369 }, + { 0x0DAD, 43450 }, + { 0x0DAE, 43490 }, + { 0x0DAF, 43430 }, + { 0x0DB0, 43470 }, + { 0x0DB1, 43324 }, + { 0x0DB3, 43357 }, + { 0x0DB4, 43446 }, + { 0x0DB5, 43486 }, + { 0x0DB6, 43422 }, + { 0x0DB7, 43462 }, + { 0x0DB8, 43348 }, + { 0x0DB9, 43289 }, + { 0x0DBA, 43392 }, + { 0x0DBB, 43354 }, + { 0x0DBD, 43320 }, + { 0x0DC0, 43389 }, + { 0x0DC1, 43373 }, + { 0x0DC2, 43418 }, + { 0x0DC3, 43328 }, + { 0x0DC4, 43338 }, + { 0x0DC5, 43410 }, + { 0x0DC6, 43335 }, + { 0x0DCA, 43195 }, + { 0x0DCF, 43277 }, + { 0x0DD0, 43244 }, + { 0x0DD1, 43219 }, + { 0x0DD2, 43234 }, + { 0x0DD3, 43209 }, + { 0x0DD4, 43239 }, + { 0x0DD6, 43214 }, + { 0x0DD8, 43285 }, + { 0x0DD9, 43254 }, + { 0x0DDA, 43204 }, + { 0x0DDB, 43249 }, + { 0x0DDC, 43265 }, + { 0x0DDD, 43258 }, + { 0x0DDE, 43271 }, + { 0x0DDF, 43281 }, + { 0x0DF2, 43229 }, + { 0x0DF3, 43224 }, + { 0x0DF4, 43502 }, + { 0x0E01, 9790 }, + { 0x0E02, 9880 }, + { 0x0E03, 9888 }, + { 0x0E04, 9892 }, + { 0x0E05, 9884 }, + { 0x0E06, 9896 }, + { 0x0E07, 9920 }, + { 0x0E08, 9864 }, + { 0x0E09, 9876 }, + { 0x0E0A, 9872 }, + { 0x0E0B, 9828 }, + { 0x0E0C, 9868 }, + { 0x0E0D, 9860 }, + { 0x0E0E, 9770 }, + { 0x0E0F, 9848 }, + { 0x0E10, 9936 }, + { 0x0E11, 9956 }, + { 0x0E12, 9952 }, + { 0x0E13, 9813 }, + { 0x0E14, 9766 }, + { 0x0E15, 9844 }, + { 0x0E16, 9944 }, + { 0x0E17, 9948 }, + { 0x0E18, 9940 }, + { 0x0E19, 9809 }, + { 0x0E1A, 9762 }, + { 0x0E1B, 9817 }, + { 0x0E1C, 9928 }, + { 0x0E1D, 9774 }, + { 0x0E1E, 9924 }, + { 0x0E1F, 9778 }, + { 0x0E20, 9932 }, + { 0x0E21, 9805 }, + { 0x0E22, 9856 }, + { 0x0E23, 9821 }, + { 0x0E24, 9825 }, + { 0x0E25, 9794 }, + { 0x0E26, 9802 }, + { 0x0E27, 9852 }, + { 0x0E28, 9840 }, + { 0x0E29, 9836 }, + { 0x0E2A, 9832 }, + { 0x0E2B, 9782 }, + { 0x0E2C, 9798 }, + { 0x0E2D, 9758 }, + { 0x0E2E, 9786 }, + { 0x0E2F, 10039 }, + { 0x0E30, 9960 }, + { 0x0E31, 9916 }, + { 0x0E32, 9980 }, + { 0x0E33, 9998 }, + { 0x0E34, 9968 }, + { 0x0E35, 10002 }, + { 0x0E36, 10006 }, + { 0x0E37, 10014 }, + { 0x0E38, 9976 }, + { 0x0E39, 10010 }, + { 0x0E3A, 10024 }, + { 0x0E3F, 9754 }, + { 0x0E40, 9964 }, + { 0x0E41, 9984 }, + { 0x0E42, 9972 }, + { 0x0E43, 9988 }, + { 0x0E44, 9993 }, + { 0x0E45, 10045 }, + { 0x0E46, 10027 }, + { 0x0E47, 10036 }, + { 0x0E48, 9900 }, + { 0x0E49, 9904 }, + { 0x0E4A, 9908 }, + { 0x0E4B, 9912 }, + { 0x0E4C, 10048 }, + { 0x0E4D, 10030 }, + { 0x0E4E, 10033 }, + { 0x0E4F, 10021 }, + { 0x0E50, 9742 }, + { 0x0E51, 9724 }, + { 0x0E52, 9730 }, + { 0x0E53, 9751 }, + { 0x0E54, 9736 }, + { 0x0E55, 9733 }, + { 0x0E56, 9727 }, + { 0x0E57, 9748 }, + { 0x0E58, 9745 }, + { 0x0E59, 9739 }, + { 0x0E5A, 10042 }, + { 0x0E5B, 10018 }, + { 0x0E81, 5948 }, + { 0x0E82, 5989 }, + { 0x0E84, 5985 }, + { 0x0E87, 5993 }, + { 0x0E88, 5926 }, + { 0x0E8A, 5968 }, + { 0x0E8D, 5996 }, + { 0x0E94, 5929 }, + { 0x0E95, 5976 }, + { 0x0E96, 6011 }, + { 0x0E97, 6007 }, + { 0x0E99, 5962 }, + { 0x0E9A, 5923 }, + { 0x0E9B, 5965 }, + { 0x0E9C, 6003 }, + { 0x0E9D, 5932 }, + { 0x0E9E, 5999 }, + { 0x0E9F, 5936 }, + { 0x0EA1, 5959 }, + { 0x0EA2, 5982 }, + { 0x0EA3, 5951 }, + { 0x0EA5, 5955 }, + { 0x0EA7, 5979 }, + { 0x0EAA, 5972 }, + { 0x0EAB, 5944 }, + { 0x0EAD, 5920 }, + { 0x0EAE, 5940 }, + { 0x0EAF, 6015 }, + { 0x0EB0, 5854 }, + { 0x0EB1, 5910 }, + { 0x0EB2, 5878 }, + { 0x0EB3, 5886 }, + { 0x0EB4, 5862 }, + { 0x0EB5, 5898 }, + { 0x0EB6, 5874 }, + { 0x0EB7, 5906 }, + { 0x0EB8, 5870 }, + { 0x0EB9, 5902 }, + { 0x0EBB, 5915 }, + { 0x0EBC, 6019 }, + { 0x0EBD, 6023 }, + { 0x0EC0, 5858 }, + { 0x0EC1, 5894 }, + { 0x0EC2, 5866 }, + { 0x0EC3, 5890 }, + { 0x0EC4, 5882 }, + { 0x0EC6, 5805 }, + { 0x0EC8, 5808 }, + { 0x0EC9, 5816 }, + { 0x0ECA, 5812 }, + { 0x0ECB, 5820 }, + { 0x0ECC, 6027 }, + { 0x0ECD, 6017 }, + { 0x0ED0, 5842 }, + { 0x0ED1, 5824 }, + { 0x0ED2, 5830 }, + { 0x0ED3, 5851 }, + { 0x0ED4, 5836 }, + { 0x0ED5, 5833 }, + { 0x0ED6, 5827 }, + { 0x0ED7, 5848 }, + { 0x0ED8, 5845 }, + { 0x0ED9, 5839 }, + { 0x0EDC, 5802 }, + { 0x0EDD, 5799 }, + { 0x0F00, 44295 }, + { 0x0F01, 43729 }, + { 0x0F02, 43720 }, + { 0x0F03, 43711 }, + { 0x0F04, 43850 }, + { 0x0F05, 43831 }, + { 0x0F06, 43789 }, + { 0x0F07, 43698 }, + { 0x0F08, 43820 }, + { 0x0F09, 43784 }, + { 0x0F0A, 43705 }, + { 0x0F0B, 43871 }, + { 0x0F0C, 43866 }, + { 0x0F0D, 43770 }, + { 0x0F0E, 43752 }, + { 0x0F0F, 43824 }, + { 0x0F10, 43760 }, + { 0x0F11, 43688 }, + { 0x0F12, 43765 }, + { 0x0F13, 43797 }, + { 0x0F14, 43736 }, + { 0x0F15, 44285 }, + { 0x0F16, 44290 }, + { 0x0F17, 44477 }, + { 0x0F18, 44489 }, + { 0x0F19, 44484 }, + { 0x0F1A, 43937 }, + { 0x0F1B, 43953 }, + { 0x0F1C, 43942 }, + { 0x0F1D, 43916 }, + { 0x0F1E, 43932 }, + { 0x0F1F, 43947 }, + { 0x0F20, 44030 }, + { 0x0F21, 43972 }, + { 0x0F22, 43978 }, + { 0x0F23, 44039 }, + { 0x0F24, 43984 }, + { 0x0F25, 43981 }, + { 0x0F26, 43975 }, + { 0x0F27, 44036 }, + { 0x0F28, 44033 }, + { 0x0F29, 44027 }, + { 0x0F2A, 43987 }, + { 0x0F2B, 43995 }, + { 0x0F2C, 44023 }, + { 0x0F2D, 44003 }, + { 0x0F2E, 43999 }, + { 0x0F2F, 43991 }, + { 0x0F30, 44019 }, + { 0x0F31, 44015 }, + { 0x0F32, 44007 }, + { 0x0F33, 44011 }, + { 0x0F34, 43773 }, + { 0x0F35, 43740 }, + { 0x0F36, 43805 }, + { 0x0F37, 43746 }, + { 0x0F38, 43674 }, + { 0x0F39, 43694 }, + { 0x0F3A, 43683 }, + { 0x0F3B, 43678 }, + { 0x0F3C, 43669 }, + { 0x0F3D, 43664 }, + { 0x0F3E, 43908 }, + { 0x0F3F, 43894 }, + { 0x0F40, 44132 }, + { 0x0F41, 44183 }, + { 0x0F42, 44123 }, + { 0x0F43, 44180 }, + { 0x0F44, 44189 }, + { 0x0F45, 44117 }, + { 0x0F46, 44168 }, + { 0x0F47, 44129 }, + { 0x0F49, 44195 }, + { 0x0F4A, 44216 }, + { 0x0F4B, 44234 }, + { 0x0F4C, 44171 }, + { 0x0F4D, 44222 }, + { 0x0F4E, 44192 }, + { 0x0F4F, 44153 }, + { 0x0F50, 44210 }, + { 0x0F51, 44120 }, + { 0x0F52, 44174 }, + { 0x0F53, 44141 }, + { 0x0F54, 44144 }, + { 0x0F55, 44198 }, + { 0x0F56, 44114 }, + { 0x0F57, 44165 }, + { 0x0F58, 44138 }, + { 0x0F59, 44213 }, + { 0x0F5A, 44231 }, + { 0x0F5B, 44177 }, + { 0x0F5C, 44225 }, + { 0x0F5D, 44156 }, + { 0x0F5E, 44219 }, + { 0x0F5F, 44162 }, + { 0x0F60, 44111 }, + { 0x0F61, 44159 }, + { 0x0F62, 44147 }, + { 0x0F63, 44135 }, + { 0x0F64, 44204 }, + { 0x0F65, 44207 }, + { 0x0F66, 44150 }, + { 0x0F67, 44126 }, + { 0x0F68, 44108 }, + { 0x0F69, 44228 }, + { 0x0F6A, 44237 }, + { 0x0F6B, 44186 }, + { 0x0F6C, 44201 }, + { 0x0F71, 44058 }, + { 0x0F72, 44046 }, + { 0x0F73, 44066 }, + { 0x0F74, 44054 }, + { 0x0F75, 44074 }, + { 0x0F76, 44083 }, + { 0x0F77, 44093 }, + { 0x0F78, 44078 }, + { 0x0F79, 44088 }, + { 0x0F7A, 44042 }, + { 0x0F7B, 44062 }, + { 0x0F7C, 44050 }, + { 0x0F7D, 44070 }, + { 0x0F7E, 43958 }, + { 0x0F7F, 43964 }, + { 0x0F80, 44098 }, + { 0x0F81, 44103 }, + { 0x0F82, 43898 }, + { 0x0F83, 43904 }, + { 0x0F84, 43847 }, + { 0x0F85, 43828 }, + { 0x0F86, 43890 }, + { 0x0F87, 43968 }, + { 0x0F88, 43885 }, + { 0x0F89, 43912 }, + { 0x0F8A, 43875 }, + { 0x0F8B, 43880 }, + { 0x0F90, 44330 }, + { 0x0F91, 44398 }, + { 0x0F92, 44318 }, + { 0x0F93, 44394 }, + { 0x0F94, 44402 }, + { 0x0F95, 44310 }, + { 0x0F96, 44378 }, + { 0x0F97, 44326 }, + { 0x0F99, 44410 }, + { 0x0F9A, 44434 }, + { 0x0F9B, 44458 }, + { 0x0F9C, 44382 }, + { 0x0F9D, 44442 }, + { 0x0F9E, 44406 }, + { 0x0F9F, 44358 }, + { 0x0FA0, 44426 }, + { 0x0FA1, 44314 }, + { 0x0FA2, 44386 }, + { 0x0FA3, 44342 }, + { 0x0FA4, 44346 }, + { 0x0FA5, 44414 }, + { 0x0FA6, 44306 }, + { 0x0FA7, 44374 }, + { 0x0FA8, 44338 }, + { 0x0FA9, 44430 }, + { 0x0FAA, 44454 }, + { 0x0FAB, 44390 }, + { 0x0FAC, 44446 }, + { 0x0FAD, 44362 }, + { 0x0FAE, 44438 }, + { 0x0FAF, 44370 }, + { 0x0FB0, 44302 }, + { 0x0FB1, 44366 }, + { 0x0FB2, 44350 }, + { 0x0FB3, 44334 }, + { 0x0FB4, 44418 }, + { 0x0FB5, 44422 }, + { 0x0FB6, 44354 }, + { 0x0FB7, 44322 }, + { 0x0FB8, 44298 }, + { 0x0FB9, 44450 }, + { 0x0FBA, 44467 }, + { 0x0FBB, 44472 }, + { 0x0FBC, 44462 }, + { 0x0FBE, 43653 }, + { 0x0FBF, 43657 }, + { 0x0FC0, 44504 }, + { 0x0FC1, 44509 }, + { 0x0FC2, 44494 }, + { 0x0FC3, 44499 }, + { 0x0FC4, 44273 }, + { 0x0FC5, 44263 }, + { 0x0FC6, 44281 }, + { 0x0FC7, 44267 }, + { 0x0FC8, 44277 }, + { 0x0FC9, 44241 }, + { 0x0FCA, 44257 }, + { 0x0FCB, 44251 }, + { 0x0FCC, 44245 }, + { 0x0FCE, 43926 }, + { 0x0FCF, 43921 }, + { 0x0FD0, 43777 }, + { 0x0FD1, 43813 }, + { 0x0FD2, 43756 }, + { 0x0FD3, 43857 }, + { 0x0FD4, 43838 }, + { 0x1000, 42482 }, + { 0x1001, 42533 }, + { 0x1002, 42470 }, + { 0x1003, 42527 }, + { 0x1004, 42559 }, + { 0x1005, 42464 }, + { 0x1006, 42518 }, + { 0x1007, 42479 }, + { 0x1008, 42530 }, + { 0x1009, 42565 }, + { 0x100A, 42586 }, + { 0x100B, 42580 }, + { 0x100C, 42650 }, + { 0x100D, 42521 }, + { 0x100E, 42583 }, + { 0x100F, 42562 }, + { 0x1010, 42503 }, + { 0x1011, 42577 }, + { 0x1012, 42467 }, + { 0x1013, 42524 }, + { 0x1014, 42491 }, + { 0x1015, 42494 }, + { 0x1016, 42568 }, + { 0x1017, 42461 }, + { 0x1018, 42515 }, + { 0x1019, 42488 }, + { 0x101A, 42512 }, + { 0x101B, 42497 }, + { 0x101C, 42485 }, + { 0x101D, 42509 }, + { 0x101E, 42500 }, + { 0x101F, 42473 }, + { 0x1020, 42536 }, + { 0x1021, 42443 }, + { 0x1022, 42594 }, + { 0x1023, 42449 }, + { 0x1024, 42476 }, + { 0x1025, 42455 }, + { 0x1026, 42506 }, + { 0x1027, 42446 }, + { 0x1028, 42539 }, + { 0x1029, 42452 }, + { 0x102A, 42458 }, + { 0x102B, 42389 }, + { 0x102C, 42329 }, + { 0x102D, 42321 }, + { 0x102E, 42337 }, + { 0x102F, 42325 }, + { 0x1030, 42341 }, + { 0x1031, 42312 }, + { 0x1032, 42333 }, + { 0x1033, 42350 }, + { 0x1034, 42345 }, + { 0x1035, 42316 }, + { 0x1036, 42266 }, + { 0x1037, 42179 }, + { 0x1038, 42233 }, + { 0x1039, 42227 }, + { 0x103A, 42183 }, + { 0x103B, 42767 }, + { 0x103C, 42757 }, + { 0x103D, 42762 }, + { 0x103E, 42752 }, + { 0x103F, 42653 }, + { 0x1040, 42300 }, + { 0x1041, 42282 }, + { 0x1042, 42288 }, + { 0x1043, 42309 }, + { 0x1044, 42294 }, + { 0x1045, 42291 }, + { 0x1046, 42285 }, + { 0x1047, 42306 }, + { 0x1048, 42303 }, + { 0x1049, 42297 }, + { 0x104A, 42223 }, + { 0x104B, 42230 }, + { 0x104C, 42719 }, + { 0x104D, 42722 }, + { 0x104E, 42725 }, + { 0x104F, 42716 }, + { 0x1050, 42571 }, + { 0x1051, 42574 }, + { 0x1052, 42684 }, + { 0x1053, 42692 }, + { 0x1054, 42680 }, + { 0x1055, 42688 }, + { 0x1056, 42414 }, + { 0x1057, 42424 }, + { 0x1058, 42409 }, + { 0x1059, 42419 }, + { 0x105A, 42555 }, + { 0x105B, 42551 }, + { 0x105C, 42543 }, + { 0x105D, 42547 }, + { 0x105E, 42740 }, + { 0x105F, 42734 }, + { 0x1060, 42728 }, + { 0x1061, 42589 }, + { 0x1062, 42361 }, + { 0x1063, 42276 }, + { 0x1064, 42269 }, + { 0x1065, 42702 }, + { 0x1066, 42696 }, + { 0x1067, 42429 }, + { 0x1068, 42436 }, + { 0x1069, 42236 }, + { 0x106A, 42242 }, + { 0x106B, 42248 }, + { 0x106C, 42254 }, + { 0x106D, 42260 }, + { 0x106E, 42662 }, + { 0x106F, 42668 }, + { 0x1070, 42674 }, + { 0x1071, 42355 }, + { 0x1072, 42404 }, + { 0x1073, 42394 }, + { 0x1074, 42399 }, + { 0x1075, 42622 }, + { 0x1076, 42634 }, + { 0x1077, 42614 }, + { 0x1078, 42602 }, + { 0x1079, 42630 }, + { 0x107A, 42638 }, + { 0x107B, 42606 }, + { 0x107C, 42626 }, + { 0x107D, 42642 }, + { 0x107E, 42610 }, + { 0x107F, 42598 }, + { 0x1080, 42646 }, + { 0x1081, 42618 }, + { 0x1082, 42746 }, + { 0x1083, 42378 }, + { 0x1084, 42367 }, + { 0x1085, 42372 }, + { 0x1086, 42383 }, + { 0x1087, 42186 }, + { 0x1088, 42190 }, + { 0x1089, 42194 }, + { 0x108A, 42198 }, + { 0x108B, 42202 }, + { 0x108C, 42207 }, + { 0x108D, 42212 }, + { 0x108E, 42657 }, + { 0x108F, 42218 }, + { 0x1090, 42163 }, + { 0x1091, 42139 }, + { 0x1092, 42147 }, + { 0x1093, 42175 }, + { 0x1094, 42155 }, + { 0x1095, 42151 }, + { 0x1096, 42143 }, + { 0x1097, 42171 }, + { 0x1098, 42167 }, + { 0x1099, 42159 }, + { 0x109E, 42708 }, + { 0x109F, 42712 }, + { 0x10A0, 52068 }, + { 0x10A1, 52096 }, + { 0x10A2, 52112 }, + { 0x10A3, 52108 }, + { 0x10A4, 52072 }, + { 0x10A5, 52176 }, + { 0x10A6, 52184 }, + { 0x10A7, 52168 }, + { 0x10A8, 52080 }, + { 0x10A9, 52136 }, + { 0x10AA, 52140 }, + { 0x10AB, 52144 }, + { 0x10AC, 52148 }, + { 0x10AD, 52084 }, + { 0x10AE, 52152 }, + { 0x10AF, 52216 }, + { 0x10B0, 52160 }, + { 0x10B1, 52164 }, + { 0x10B2, 52172 }, + { 0x10B3, 52088 }, + { 0x10B4, 52208 }, + { 0x10B5, 52204 }, + { 0x10B6, 52196 }, + { 0x10B7, 52156 }, + { 0x10B8, 52212 }, + { 0x10B9, 52192 }, + { 0x10BA, 52100 }, + { 0x10BB, 52132 }, + { 0x10BC, 52104 }, + { 0x10BD, 52188 }, + { 0x10BE, 52180 }, + { 0x10BF, 52200 }, + { 0x10C0, 52116 }, + { 0x10C1, 52076 }, + { 0x10C2, 52124 }, + { 0x10C3, 52092 }, + { 0x10C4, 52120 }, + { 0x10C5, 52128 }, + { 0x10D0, 51938 }, + { 0x10D1, 51968 }, + { 0x10D2, 51980 }, + { 0x10D3, 51977 }, + { 0x10D4, 51941 }, + { 0x10D5, 52028 }, + { 0x10D6, 52034 }, + { 0x10D7, 52022 }, + { 0x10D8, 51950 }, + { 0x10D9, 51998 }, + { 0x10DA, 52001 }, + { 0x10DB, 52004 }, + { 0x10DC, 52007 }, + { 0x10DD, 51953 }, + { 0x10DE, 52010 }, + { 0x10DF, 52058 }, + { 0x10E0, 52016 }, + { 0x10E1, 52019 }, + { 0x10E2, 52025 }, + { 0x10E3, 51956 }, + { 0x10E4, 52052 }, + { 0x10E5, 52049 }, + { 0x10E6, 52043 }, + { 0x10E7, 52013 }, + { 0x10E8, 52055 }, + { 0x10E9, 52040 }, + { 0x10EA, 51971 }, + { 0x10EB, 51995 }, + { 0x10EC, 51974 }, + { 0x10ED, 52037 }, + { 0x10EE, 52031 }, + { 0x10EF, 52046 }, + { 0x10F0, 51983 }, + { 0x10F1, 51947 }, + { 0x10F2, 51989 }, + { 0x10F3, 51959 }, + { 0x10F4, 51986 }, + { 0x10F5, 51992 }, + { 0x10F6, 51944 }, + { 0x10F7, 51962 }, + { 0x10F8, 52061 }, + { 0x10F9, 52064 }, + { 0x10FA, 51965 }, + { 0x10FB, 52220 }, + { 0x10FC, 54786 }, + { 0x1100, 32202 }, + { 0x1101, 32310 }, + { 0x1102, 32190 }, + { 0x1103, 32205 }, + { 0x1104, 32313 }, + { 0x1105, 32196 }, + { 0x1106, 32187 }, + { 0x1107, 32193 }, + { 0x1108, 32268 }, + { 0x1109, 32175 }, + { 0x110A, 32226 }, + { 0x110B, 32184 }, + { 0x110C, 32178 }, + { 0x110D, 32256 }, + { 0x110E, 32208 }, + { 0x110F, 32211 }, + { 0x1110, 32220 }, + { 0x1111, 32217 }, + { 0x1112, 32181 }, + { 0x1113, 32328 }, + { 0x1114, 32265 }, + { 0x1115, 32331 }, + { 0x1116, 32289 }, + { 0x1117, 32391 }, + { 0x1118, 32301 }, + { 0x1119, 32271 }, + { 0x111A, 32298 }, + { 0x111B, 32376 }, + { 0x111C, 32286 }, + { 0x111D, 32370 }, + { 0x111E, 32334 }, + { 0x111F, 32295 }, + { 0x1120, 32337 }, + { 0x1121, 32232 }, + { 0x1122, 32424 }, + { 0x1123, 32427 }, + { 0x1124, 32418 }, + { 0x1125, 32409 }, + { 0x1126, 32415 }, + { 0x1127, 32292 }, + { 0x1128, 32382 }, + { 0x1129, 32388 }, + { 0x112A, 32385 }, + { 0x112B, 32373 }, + { 0x112C, 32439 }, + { 0x112D, 32304 }, + { 0x112E, 32247 }, + { 0x112F, 32307 }, + { 0x1130, 32253 }, + { 0x1131, 32244 }, + { 0x1132, 32250 }, + { 0x1133, 32430 }, + { 0x1134, 32394 }, + { 0x1135, 32241 }, + { 0x1136, 32235 }, + { 0x1137, 32340 }, + { 0x1138, 32343 }, + { 0x1139, 32349 }, + { 0x113A, 32346 }, + { 0x113B, 32238 }, + { 0x113C, 32319 }, + { 0x113D, 32421 }, + { 0x113E, 32397 }, + { 0x113F, 32442 }, + { 0x1140, 32214 }, + { 0x1141, 32322 }, + { 0x1142, 32325 }, + { 0x1143, 32280 }, + { 0x1144, 32283 }, + { 0x1145, 32229 }, + { 0x1146, 32361 }, + { 0x1147, 32262 }, + { 0x1148, 32277 }, + { 0x1149, 32358 }, + { 0x114A, 32367 }, + { 0x114B, 32364 }, + { 0x114C, 32223 }, + { 0x114D, 32274 }, + { 0x114E, 32355 }, + { 0x114F, 32436 }, + { 0x1150, 32412 }, + { 0x1151, 32445 }, + { 0x1152, 32400 }, + { 0x1153, 32352 }, + { 0x1154, 32403 }, + { 0x1155, 32433 }, + { 0x1156, 32379 }, + { 0x1157, 32406 }, + { 0x1158, 32259 }, + { 0x1159, 32316 }, + { 0x115F, 32199 }, + { 0x1160, 32865 }, + { 0x1161, 32694 }, + { 0x1162, 32709 }, + { 0x1163, 32730 }, + { 0x1164, 32781 }, + { 0x1165, 32712 }, + { 0x1166, 32697 }, + { 0x1167, 32784 }, + { 0x1168, 32733 }, + { 0x1169, 32703 }, + { 0x116A, 32721 }, + { 0x116B, 32775 }, + { 0x116C, 32718 }, + { 0x116D, 32739 }, + { 0x116E, 32706 }, + { 0x116F, 32778 }, + { 0x1170, 32724 }, + { 0x1171, 32727 }, + { 0x1172, 32742 }, + { 0x1173, 32715 }, + { 0x1174, 32736 }, + { 0x1175, 32700 }, + { 0x1176, 32745 }, + { 0x1177, 32748 }, + { 0x1178, 32814 }, + { 0x1179, 32847 }, + { 0x117A, 32787 }, + { 0x117B, 32790 }, + { 0x117C, 32841 }, + { 0x117D, 32850 }, + { 0x117E, 32853 }, + { 0x117F, 32802 }, + { 0x1180, 32760 }, + { 0x1181, 32805 }, + { 0x1182, 32763 }, + { 0x1183, 32766 }, + { 0x1184, 32856 }, + { 0x1185, 32868 }, + { 0x1186, 32871 }, + { 0x1187, 32823 }, + { 0x1188, 32820 }, + { 0x1189, 32769 }, + { 0x118A, 32808 }, + { 0x118B, 32886 }, + { 0x118C, 32811 }, + { 0x118D, 32772 }, + { 0x118E, 32826 }, + { 0x118F, 32859 }, + { 0x1190, 32829 }, + { 0x1191, 32874 }, + { 0x1192, 32862 }, + { 0x1193, 32835 }, + { 0x1194, 32832 }, + { 0x1195, 32793 }, + { 0x1196, 32844 }, + { 0x1197, 32817 }, + { 0x1198, 32751 }, + { 0x1199, 32799 }, + { 0x119A, 32754 }, + { 0x119B, 32757 }, + { 0x119C, 32796 }, + { 0x119D, 32883 }, + { 0x119E, 32838 }, + { 0x119F, 32889 }, + { 0x11A0, 32880 }, + { 0x11A1, 32877 }, + { 0x11A2, 32892 }, + { 0x11A8, 32472 }, + { 0x11A9, 32577 }, + { 0x11AA, 32535 }, + { 0x11AB, 32463 }, + { 0x11AC, 32547 }, + { 0x11AD, 32550 }, + { 0x11AE, 32475 }, + { 0x11AF, 32469 }, + { 0x11B0, 32598 }, + { 0x11B1, 32562 }, + { 0x11B2, 32568 }, + { 0x11B3, 32508 }, + { 0x11B4, 32643 }, + { 0x11B5, 32640 }, + { 0x11B6, 32559 }, + { 0x11B7, 32460 }, + { 0x11B8, 32466 }, + { 0x11B9, 32505 }, + { 0x11BA, 32448 }, + { 0x11BB, 32496 }, + { 0x11BC, 32457 }, + { 0x11BD, 32451 }, + { 0x11BE, 32478 }, + { 0x11BF, 32481 }, + { 0x11C0, 32490 }, + { 0x11C1, 32487 }, + { 0x11C2, 32454 }, + { 0x11C3, 32586 }, + { 0x11C4, 32682 }, + { 0x11C5, 32592 }, + { 0x11C6, 32595 }, + { 0x11C7, 32502 }, + { 0x11C8, 32622 }, + { 0x11C9, 32625 }, + { 0x11CA, 32646 }, + { 0x11CB, 32604 }, + { 0x11CC, 32673 }, + { 0x11CD, 32565 }, + { 0x11CE, 32601 }, + { 0x11CF, 32688 }, + { 0x11D0, 32520 }, + { 0x11D1, 32685 }, + { 0x11D2, 32661 }, + { 0x11D3, 32664 }, + { 0x11D4, 32676 }, + { 0x11D5, 32691 }, + { 0x11D6, 32658 }, + { 0x11D7, 32637 }, + { 0x11D8, 32634 }, + { 0x11D9, 32679 }, + { 0x11DA, 32589 }, + { 0x11DB, 32544 }, + { 0x11DC, 32541 }, + { 0x11DD, 32499 }, + { 0x11DE, 32655 }, + { 0x11DF, 32619 }, + { 0x11E0, 32616 }, + { 0x11E1, 32538 }, + { 0x11E2, 32610 }, + { 0x11E3, 32556 }, + { 0x11E4, 32631 }, + { 0x11E5, 32553 }, + { 0x11E6, 32613 }, + { 0x11E7, 32571 }, + { 0x11E8, 32574 }, + { 0x11E9, 32514 }, + { 0x11EA, 32511 }, + { 0x11EB, 32484 }, + { 0x11EC, 32583 }, + { 0x11ED, 32670 }, + { 0x11EE, 32517 }, + { 0x11EF, 32607 }, + { 0x11F0, 32493 }, + { 0x11F1, 32649 }, + { 0x11F2, 32667 }, + { 0x11F3, 32628 }, + { 0x11F4, 32652 }, + { 0x11F5, 32526 }, + { 0x11F6, 32532 }, + { 0x11F7, 32523 }, + { 0x11F8, 32529 }, + { 0x11F9, 32580 }, + { 0x1200, 50516 }, + { 0x1201, 50528 }, + { 0x1202, 50522 }, + { 0x1203, 50909 }, + { 0x1204, 50912 }, + { 0x1205, 50519 }, + { 0x1206, 50525 }, + { 0x1207, 50930 }, + { 0x1208, 50561 }, + { 0x1209, 50573 }, + { 0x120A, 50567 }, + { 0x120B, 50993 }, + { 0x120C, 50996 }, + { 0x120D, 50564 }, + { 0x120E, 50570 }, + { 0x120F, 51002 }, + { 0x1210, 50915 }, + { 0x1211, 50927 }, + { 0x1212, 50921 }, + { 0x1213, 51443 }, + { 0x1214, 51446 }, + { 0x1215, 50918 }, + { 0x1216, 50924 }, + { 0x1217, 51449 }, + { 0x1218, 50576 }, + { 0x1219, 50588 }, + { 0x121A, 50582 }, + { 0x121B, 51005 }, + { 0x121C, 51008 }, + { 0x121D, 50579 }, + { 0x121E, 50585 }, + { 0x121F, 51014 }, + { 0x1220, 51191 }, + { 0x1221, 51203 }, + { 0x1222, 51197 }, + { 0x1223, 51554 }, + { 0x1224, 51557 }, + { 0x1225, 51194 }, + { 0x1226, 51200 }, + { 0x1227, 51560 }, + { 0x1228, 50636 }, + { 0x1229, 50648 }, + { 0x122A, 50642 }, + { 0x122B, 51134 }, + { 0x122C, 51137 }, + { 0x122D, 50639 }, + { 0x122E, 50645 }, + { 0x122F, 51143 }, + { 0x1230, 50651 }, + { 0x1231, 50663 }, + { 0x1232, 50657 }, + { 0x1233, 51149 }, + { 0x1234, 51152 }, + { 0x1235, 50654 }, + { 0x1236, 50660 }, + { 0x1237, 51188 }, + { 0x1238, 51155 }, + { 0x1239, 51167 }, + { 0x123A, 51161 }, + { 0x123B, 51536 }, + { 0x123C, 51539 }, + { 0x123D, 51158 }, + { 0x123E, 51164 }, + { 0x123F, 51545 }, + { 0x1240, 50621 }, + { 0x1241, 50633 }, + { 0x1242, 50627 }, + { 0x1243, 51086 }, + { 0x1244, 51089 }, + { 0x1245, 50624 }, + { 0x1246, 50630 }, + { 0x1247, 51107 }, + { 0x1248, 51110 }, + { 0x124A, 51116 }, + { 0x124B, 51524 }, + { 0x124C, 51527 }, + { 0x124D, 51113 }, + { 0x1250, 51092 }, + { 0x1251, 51104 }, + { 0x1252, 51098 }, + { 0x1253, 51509 }, + { 0x1254, 51512 }, + { 0x1255, 51095 }, + { 0x1256, 51101 }, + { 0x1258, 51515 }, + { 0x125A, 51521 }, + { 0x125B, 51638 }, + { 0x125C, 51641 }, + { 0x125D, 51518 }, + { 0x1260, 50441 }, + { 0x1261, 50453 }, + { 0x1262, 50447 }, + { 0x1263, 50756 }, + { 0x1264, 50759 }, + { 0x1265, 50444 }, + { 0x1266, 50450 }, + { 0x1267, 50765 }, + { 0x1268, 50681 }, + { 0x1269, 50693 }, + { 0x126A, 50687 }, + { 0x126B, 51263 }, + { 0x126C, 51266 }, + { 0x126D, 50684 }, + { 0x126E, 50690 }, + { 0x126F, 51269 }, + { 0x1270, 50666 }, + { 0x1271, 50678 }, + { 0x1272, 50672 }, + { 0x1273, 51206 }, + { 0x1274, 51209 }, + { 0x1275, 50669 }, + { 0x1276, 50675 }, + { 0x1277, 51245 }, + { 0x1278, 50456 }, + { 0x1279, 50468 }, + { 0x127A, 50462 }, + { 0x127B, 50774 }, + { 0x127C, 50792 }, + { 0x127D, 50459 }, + { 0x127E, 50465 }, + { 0x127F, 50813 }, + { 0x1280, 50711 }, + { 0x1281, 50723 }, + { 0x1282, 50717 }, + { 0x1283, 51281 }, + { 0x1284, 51284 }, + { 0x1285, 50714 }, + { 0x1286, 50720 }, + { 0x1287, 51287 }, + { 0x1288, 51290 }, + { 0x128A, 51296 }, + { 0x128B, 51593 }, + { 0x128C, 51596 }, + { 0x128D, 51293 }, + { 0x1290, 50591 }, + { 0x1291, 50603 }, + { 0x1292, 50597 }, + { 0x1293, 51026 }, + { 0x1294, 51029 }, + { 0x1295, 50594 }, + { 0x1296, 50600 }, + { 0x1297, 51035 }, + { 0x1298, 51038 }, + { 0x1299, 51050 }, + { 0x129A, 51044 }, + { 0x129B, 51482 }, + { 0x129C, 51485 }, + { 0x129D, 51041 }, + { 0x129E, 51047 }, + { 0x129F, 51491 }, + { 0x12A0, 51644 }, + { 0x12A1, 51660 }, + { 0x12A2, 51652 }, + { 0x12A3, 51664 }, + { 0x12A4, 51668 }, + { 0x12A5, 51648 }, + { 0x12A6, 51656 }, + { 0x12A7, 51676 }, + { 0x12A8, 50546 }, + { 0x12A9, 50558 }, + { 0x12AA, 50552 }, + { 0x12AB, 50945 }, + { 0x12AC, 50948 }, + { 0x12AD, 50549 }, + { 0x12AE, 50555 }, + { 0x12AF, 50951 }, + { 0x12B0, 50954 }, + { 0x12B2, 50960 }, + { 0x12B3, 51452 }, + { 0x12B4, 51455 }, + { 0x12B5, 50957 }, + { 0x12B8, 50963 }, + { 0x12B9, 50975 }, + { 0x12BA, 50969 }, + { 0x12BB, 51458 }, + { 0x12BC, 51461 }, + { 0x12BD, 50966 }, + { 0x12BE, 50972 }, + { 0x12C0, 51464 }, + { 0x12C2, 51470 }, + { 0x12C3, 51632 }, + { 0x12C4, 51635 }, + { 0x12C5, 51467 }, + { 0x12C8, 50696 }, + { 0x12C9, 50708 }, + { 0x12CA, 50702 }, + { 0x12CB, 51272 }, + { 0x12CC, 51275 }, + { 0x12CD, 50699 }, + { 0x12CE, 50705 }, + { 0x12CF, 51278 }, + { 0x12D0, 51696 }, + { 0x12D1, 51712 }, + { 0x12D2, 51704 }, + { 0x12D3, 51716 }, + { 0x12D4, 51720 }, + { 0x12D5, 51700 }, + { 0x12D6, 51708 }, + { 0x12D8, 50741 }, + { 0x12D9, 50753 }, + { 0x12DA, 50747 }, + { 0x12DB, 51323 }, + { 0x12DC, 51326 }, + { 0x12DD, 50744 }, + { 0x12DE, 50750 }, + { 0x12DF, 51347 }, + { 0x12E0, 51329 }, + { 0x12E1, 51341 }, + { 0x12E2, 51335 }, + { 0x12E3, 51605 }, + { 0x12E4, 51608 }, + { 0x12E5, 51332 }, + { 0x12E6, 51338 }, + { 0x12E7, 51611 }, + { 0x12E8, 50726 }, + { 0x12E9, 50738 }, + { 0x12EA, 50732 }, + { 0x12EB, 51314 }, + { 0x12EC, 51317 }, + { 0x12ED, 50729 }, + { 0x12EE, 50735 }, + { 0x12EF, 51320 }, + { 0x12F0, 50471 }, + { 0x12F1, 50483 }, + { 0x12F2, 50477 }, + { 0x12F3, 50816 }, + { 0x12F4, 50834 }, + { 0x12F5, 50474 }, + { 0x12F6, 50480 }, + { 0x12F7, 50840 }, + { 0x12F8, 50819 }, + { 0x12F9, 50831 }, + { 0x12FA, 50825 }, + { 0x12FB, 51401 }, + { 0x12FC, 51404 }, + { 0x12FD, 50822 }, + { 0x12FE, 50828 }, + { 0x12FF, 51410 }, + { 0x1300, 50531 }, + { 0x1301, 50543 }, + { 0x1302, 50537 }, + { 0x1303, 50933 }, + { 0x1304, 50936 }, + { 0x1305, 50534 }, + { 0x1306, 50540 }, + { 0x1307, 50942 }, + { 0x1308, 50501 }, + { 0x1309, 50513 }, + { 0x130A, 50507 }, + { 0x130B, 50861 }, + { 0x130C, 50864 }, + { 0x130D, 50504 }, + { 0x130E, 50510 }, + { 0x130F, 50882 }, + { 0x1310, 50885 }, + { 0x1312, 50891 }, + { 0x1313, 51431 }, + { 0x1314, 51434 }, + { 0x1315, 50888 }, + { 0x1318, 50867 }, + { 0x1319, 50879 }, + { 0x131A, 50873 }, + { 0x131B, 51416 }, + { 0x131C, 51419 }, + { 0x131D, 50870 }, + { 0x131E, 50876 }, + { 0x131F, 51626 }, + { 0x1320, 51212 }, + { 0x1321, 51224 }, + { 0x1322, 51218 }, + { 0x1323, 51563 }, + { 0x1324, 51566 }, + { 0x1325, 51215 }, + { 0x1326, 51221 }, + { 0x1327, 51572 }, + { 0x1328, 50795 }, + { 0x1329, 50807 }, + { 0x132A, 50801 }, + { 0x132B, 51389 }, + { 0x132C, 51392 }, + { 0x132D, 50798 }, + { 0x132E, 50804 }, + { 0x132F, 51398 }, + { 0x1330, 51059 }, + { 0x1331, 51071 }, + { 0x1332, 51065 }, + { 0x1333, 51494 }, + { 0x1334, 51497 }, + { 0x1335, 51062 }, + { 0x1336, 51068 }, + { 0x1337, 51503 }, + { 0x1338, 51230 }, + { 0x1339, 51242 }, + { 0x133A, 51236 }, + { 0x133B, 51575 }, + { 0x133C, 51578 }, + { 0x133D, 51233 }, + { 0x133E, 51239 }, + { 0x133F, 51581 }, + { 0x1340, 51248 }, + { 0x1341, 51260 }, + { 0x1342, 51254 }, + { 0x1343, 51584 }, + { 0x1344, 51587 }, + { 0x1345, 51251 }, + { 0x1346, 51257 }, + { 0x1347, 51590 }, + { 0x1348, 50486 }, + { 0x1349, 50498 }, + { 0x134A, 50492 }, + { 0x134B, 50843 }, + { 0x134C, 50846 }, + { 0x134D, 50489 }, + { 0x134E, 50495 }, + { 0x134F, 50849 }, + { 0x1350, 50606 }, + { 0x1351, 50618 }, + { 0x1352, 50612 }, + { 0x1353, 51053 }, + { 0x1354, 51056 }, + { 0x1355, 50609 }, + { 0x1356, 50615 }, + { 0x1357, 51077 }, + { 0x1358, 51146 }, + { 0x1359, 51023 }, + { 0x135A, 50858 }, + { 0x135F, 51724 }, + { 0x1360, 50435 }, + { 0x1361, 51733 }, + { 0x1362, 50323 }, + { 0x1363, 50328 }, + { 0x1364, 51731 }, + { 0x1365, 50326 }, + { 0x1366, 50432 }, + { 0x1367, 50438 }, + { 0x1368, 51728 }, + { 0x1369, 50330 }, + { 0x136A, 50336 }, + { 0x136B, 50354 }, + { 0x136C, 50342 }, + { 0x136D, 50339 }, + { 0x136E, 50333 }, + { 0x136F, 50351 }, + { 0x1370, 50348 }, + { 0x1371, 50345 }, + { 0x1372, 50398 }, + { 0x1373, 50423 }, + { 0x1374, 50420 }, + { 0x1375, 50408 }, + { 0x1376, 50405 }, + { 0x1377, 50411 }, + { 0x1378, 50429 }, + { 0x1379, 50414 }, + { 0x137A, 50417 }, + { 0x137B, 50426 }, + { 0x137C, 50401 }, + { 0x1380, 51688 }, + { 0x1381, 51020 }, + { 0x1382, 51479 }, + { 0x1383, 51017 }, + { 0x1384, 51680 }, + { 0x1385, 50771 }, + { 0x1386, 51365 }, + { 0x1387, 50768 }, + { 0x1388, 51684 }, + { 0x1389, 50855 }, + { 0x138A, 51413 }, + { 0x138B, 50852 }, + { 0x138C, 51692 }, + { 0x138D, 51083 }, + { 0x138E, 51506 }, + { 0x138F, 51080 }, + { 0x1390, 50382 }, + { 0x1391, 50361 }, + { 0x1392, 50390 }, + { 0x1393, 50377 }, + { 0x1394, 50365 }, + { 0x1395, 50373 }, + { 0x1396, 50386 }, + { 0x1397, 50369 }, + { 0x1398, 50394 }, + { 0x1399, 50357 }, + { 0x13A0, 48143 }, + { 0x13A1, 48146 }, + { 0x13A2, 48149 }, + { 0x13A3, 48152 }, + { 0x13A4, 48158 }, + { 0x13A5, 48161 }, + { 0x13A6, 48182 }, + { 0x13A7, 48218 }, + { 0x13A8, 48185 }, + { 0x13A9, 48188 }, + { 0x13AA, 48191 }, + { 0x13AB, 48194 }, + { 0x13AC, 48197 }, + { 0x13AD, 48200 }, + { 0x13AE, 48203 }, + { 0x13AF, 48206 }, + { 0x13B0, 48209 }, + { 0x13B1, 48212 }, + { 0x13B2, 48215 }, + { 0x13B3, 48221 }, + { 0x13B4, 48224 }, + { 0x13B5, 48227 }, + { 0x13B6, 48230 }, + { 0x13B7, 48233 }, + { 0x13B8, 48236 }, + { 0x13B9, 48239 }, + { 0x13BA, 48242 }, + { 0x13BB, 48245 }, + { 0x13BC, 48248 }, + { 0x13BD, 48251 }, + { 0x13BE, 48254 }, + { 0x13BF, 48338 }, + { 0x13C0, 48341 }, + { 0x13C1, 48257 }, + { 0x13C2, 48260 }, + { 0x13C3, 48263 }, + { 0x13C4, 48266 }, + { 0x13C5, 48269 }, + { 0x13C6, 48344 }, + { 0x13C7, 48347 }, + { 0x13C8, 48350 }, + { 0x13C9, 48353 }, + { 0x13CA, 48356 }, + { 0x13CB, 48359 }, + { 0x13CC, 48272 }, + { 0x13CD, 48155 }, + { 0x13CE, 48275 }, + { 0x13CF, 48278 }, + { 0x13D0, 48281 }, + { 0x13D1, 48284 }, + { 0x13D2, 48287 }, + { 0x13D3, 48164 }, + { 0x13D4, 48290 }, + { 0x13D5, 48167 }, + { 0x13D6, 48293 }, + { 0x13D7, 48170 }, + { 0x13D8, 48296 }, + { 0x13D9, 48173 }, + { 0x13DA, 48176 }, + { 0x13DB, 48179 }, + { 0x13DC, 48335 }, + { 0x13DD, 48362 }, + { 0x13DE, 48365 }, + { 0x13DF, 48368 }, + { 0x13E0, 48371 }, + { 0x13E1, 48374 }, + { 0x13E2, 48377 }, + { 0x13E3, 48380 }, + { 0x13E4, 48383 }, + { 0x13E5, 48386 }, + { 0x13E6, 48389 }, + { 0x13E7, 48392 }, + { 0x13E8, 48395 }, + { 0x13E9, 48299 }, + { 0x13EA, 48302 }, + { 0x13EB, 48305 }, + { 0x13EC, 48308 }, + { 0x13ED, 48311 }, + { 0x13EE, 48314 }, + { 0x13EF, 48317 }, + { 0x13F0, 48320 }, + { 0x13F1, 48323 }, + { 0x13F2, 48326 }, + { 0x13F3, 48329 }, + { 0x13F4, 48332 }, + { 0x1401, 45872 }, + { 0x1402, 46118 }, + { 0x1403, 45878 }, + { 0x1404, 45953 }, + { 0x1405, 45893 }, + { 0x1406, 46025 }, + { 0x1407, 46790 }, + { 0x1408, 46858 }, + { 0x1409, 46842 }, + { 0x140A, 45866 }, + { 0x140B, 45914 }, + { 0x140C, 46097 }, + { 0x140D, 47791 }, + { 0x140E, 46100 }, + { 0x140F, 47795 }, + { 0x1410, 46392 }, + { 0x1411, 47927 }, + { 0x1412, 46103 }, + { 0x1413, 47799 }, + { 0x1414, 46395 }, + { 0x1415, 47931 }, + { 0x1416, 47555 }, + { 0x1417, 46094 }, + { 0x1418, 47787 }, + { 0x1419, 46389 }, + { 0x141A, 47923 }, + { 0x141B, 47551 }, + { 0x141C, 45917 }, + { 0x141D, 46786 }, + { 0x141E, 47539 }, + { 0x141F, 46643 }, + { 0x1420, 46647 }, + { 0x1421, 46663 }, + { 0x1422, 46624 }, + { 0x1423, 46651 }, + { 0x1424, 46639 }, + { 0x1425, 46669 }, + { 0x1426, 46674 }, + { 0x1427, 46681 }, + { 0x1428, 46657 }, + { 0x1429, 46635 }, + { 0x142A, 46630 }, + { 0x142B, 45935 }, + { 0x142C, 45956 }, + { 0x142D, 46022 }, + { 0x142E, 45920 }, + { 0x142F, 46031 }, + { 0x1430, 46513 }, + { 0x1431, 46034 }, + { 0x1432, 46257 }, + { 0x1433, 46037 }, + { 0x1434, 46260 }, + { 0x1435, 46814 }, + { 0x1436, 47186 }, + { 0x1437, 46882 }, + { 0x1438, 46028 }, + { 0x1439, 46254 }, + { 0x143A, 46266 }, + { 0x143B, 47879 }, + { 0x143C, 46269 }, + { 0x143D, 47883 }, + { 0x143E, 46519 }, + { 0x143F, 48011 }, + { 0x1440, 46272 }, + { 0x1441, 47887 }, + { 0x1442, 46522 }, + { 0x1443, 48015 }, + { 0x1444, 46263 }, + { 0x1445, 47875 }, + { 0x1446, 46516 }, + { 0x1447, 48007 }, + { 0x1448, 46830 }, + { 0x1449, 45896 }, + { 0x144A, 47747 }, + { 0x144B, 46838 }, + { 0x144C, 46082 }, + { 0x144D, 46567 }, + { 0x144E, 46088 }, + { 0x144F, 46344 }, + { 0x1450, 46091 }, + { 0x1451, 46347 }, + { 0x1452, 46822 }, + { 0x1453, 47118 }, + { 0x1454, 46854 }, + { 0x1455, 46079 }, + { 0x1456, 46329 }, + { 0x1457, 46368 }, + { 0x1458, 47911 }, + { 0x1459, 46371 }, + { 0x145A, 47915 }, + { 0x145B, 46606 }, + { 0x145C, 48055 }, + { 0x145D, 46374 }, + { 0x145E, 47919 }, + { 0x145F, 46609 }, + { 0x1460, 48059 }, + { 0x1461, 46365 }, + { 0x1462, 47907 }, + { 0x1463, 46603 }, + { 0x1464, 48051 }, + { 0x1465, 47595 }, + { 0x1466, 45908 }, + { 0x1467, 46353 }, + { 0x1468, 46359 }, + { 0x1469, 46362 }, + { 0x146A, 46350 }, + { 0x146B, 45962 }, + { 0x146C, 46441 }, + { 0x146D, 45965 }, + { 0x146E, 46158 }, + { 0x146F, 45968 }, + { 0x1470, 46161 }, + { 0x1471, 46798 }, + { 0x1472, 45959 }, + { 0x1473, 46155 }, + { 0x1474, 46167 }, + { 0x1475, 47823 }, + { 0x1476, 46170 }, + { 0x1477, 47827 }, + { 0x1478, 46447 }, + { 0x1479, 47971 }, + { 0x147A, 46173 }, + { 0x147B, 47831 }, + { 0x147C, 46450 }, + { 0x147D, 47975 }, + { 0x147E, 46164 }, + { 0x147F, 47819 }, + { 0x1480, 46444 }, + { 0x1481, 47967 }, + { 0x1482, 47563 }, + { 0x1483, 45881 }, + { 0x1484, 45971 }, + { 0x1485, 48131 }, + { 0x1486, 48135 }, + { 0x1487, 48139 }, + { 0x1488, 48127 }, + { 0x1489, 45926 }, + { 0x148A, 46419 }, + { 0x148B, 45929 }, + { 0x148C, 46128 }, + { 0x148D, 45932 }, + { 0x148E, 46131 }, + { 0x148F, 46794 }, + { 0x1490, 45923 }, + { 0x1491, 46121 }, + { 0x1492, 46137 }, + { 0x1493, 47807 }, + { 0x1494, 46140 }, + { 0x1495, 47811 }, + { 0x1496, 46425 }, + { 0x1497, 47955 }, + { 0x1498, 46143 }, + { 0x1499, 47815 }, + { 0x149A, 46428 }, + { 0x149B, 47959 }, + { 0x149C, 46134 }, + { 0x149D, 47803 }, + { 0x149E, 46422 }, + { 0x149F, 47951 }, + { 0x14A0, 47559 }, + { 0x14A1, 45869 }, + { 0x14A2, 46762 }, + { 0x14A3, 45992 }, + { 0x14A4, 46474 }, + { 0x14A5, 45998 }, + { 0x14A6, 46209 }, + { 0x14A7, 46001 }, + { 0x14A8, 46212 }, + { 0x14A9, 46806 }, + { 0x14AA, 45989 }, + { 0x14AB, 46206 }, + { 0x14AC, 46218 }, + { 0x14AD, 47855 }, + { 0x14AE, 46221 }, + { 0x14AF, 47859 }, + { 0x14B0, 46480 }, + { 0x14B1, 47995 }, + { 0x14B2, 46224 }, + { 0x14B3, 47863 }, + { 0x14B4, 46483 }, + { 0x14B5, 47999 }, + { 0x14B6, 46215 }, + { 0x14B7, 47851 }, + { 0x14B8, 46477 }, + { 0x14B9, 47991 }, + { 0x14BA, 47567 }, + { 0x14BB, 45887 }, + { 0x14BC, 47743 }, + { 0x14BD, 45995 }, + { 0x14BE, 48091 }, + { 0x14BF, 46734 }, + { 0x14C0, 46007 }, + { 0x14C1, 46486 }, + { 0x14C2, 46016 }, + { 0x14C3, 46239 }, + { 0x14C4, 46019 }, + { 0x14C5, 46245 }, + { 0x14C6, 46810 }, + { 0x14C7, 46004 }, + { 0x14C8, 46227 }, + { 0x14C9, 46251 }, + { 0x14CA, 47871 }, + { 0x14CB, 46248 }, + { 0x14CC, 47867 }, + { 0x14CD, 46510 }, + { 0x14CE, 48003 }, + { 0x14CF, 47571 }, + { 0x14D0, 45890 }, + { 0x14D1, 46958 }, + { 0x14D2, 46013 }, + { 0x14D3, 45977 }, + { 0x14D4, 46453 }, + { 0x14D5, 45983 }, + { 0x14D6, 46188 }, + { 0x14D7, 45986 }, + { 0x14D8, 46191 }, + { 0x14D9, 46802 }, + { 0x14DA, 45974 }, + { 0x14DB, 46176 }, + { 0x14DC, 46197 }, + { 0x14DD, 47839 }, + { 0x14DE, 46200 }, + { 0x14DF, 47843 }, + { 0x14E0, 46468 }, + { 0x14E1, 47983 }, + { 0x14E2, 46203 }, + { 0x14E3, 47847 }, + { 0x14E4, 46471 }, + { 0x14E5, 47987 }, + { 0x14E6, 46194 }, + { 0x14E7, 47835 }, + { 0x14E8, 46465 }, + { 0x14E9, 47979 }, + { 0x14EA, 45884 }, + { 0x14EB, 47739 }, + { 0x14EC, 46710 }, + { 0x14ED, 46064 }, + { 0x14EE, 46534 }, + { 0x14EF, 46070 }, + { 0x14F0, 46311 }, + { 0x14F1, 46073 }, + { 0x14F2, 46314 }, + { 0x14F3, 46818 }, + { 0x14F4, 46061 }, + { 0x14F5, 46296 }, + { 0x14F6, 46320 }, + { 0x14F7, 47895 }, + { 0x14F8, 46323 }, + { 0x14F9, 47899 }, + { 0x14FA, 46561 }, + { 0x14FB, 48043 }, + { 0x14FC, 46326 }, + { 0x14FD, 47903 }, + { 0x14FE, 46564 }, + { 0x14FF, 48047 }, + { 0x1500, 46317 }, + { 0x1501, 47891 }, + { 0x1502, 46558 }, + { 0x1503, 48039 }, + { 0x1504, 47591 }, + { 0x1505, 45905 }, + { 0x1506, 48095 }, + { 0x1507, 46076 }, + { 0x1508, 47687 }, + { 0x1509, 48103 }, + { 0x150A, 47547 }, + { 0x150B, 47543 }, + { 0x150C, 47583 }, + { 0x150D, 47587 }, + { 0x150E, 47579 }, + { 0x150F, 47575 }, + { 0x1510, 46302 }, + { 0x1511, 46305 }, + { 0x1512, 46540 }, + { 0x1513, 46308 }, + { 0x1514, 46543 }, + { 0x1515, 46299 }, + { 0x1516, 46537 }, + { 0x1517, 46549 }, + { 0x1518, 48027 }, + { 0x1519, 46552 }, + { 0x151A, 48031 }, + { 0x151B, 46701 }, + { 0x151C, 48079 }, + { 0x151D, 46555 }, + { 0x151E, 48035 }, + { 0x151F, 46704 }, + { 0x1520, 48083 }, + { 0x1521, 46546 }, + { 0x1522, 48023 }, + { 0x1523, 46698 }, + { 0x1524, 48075 }, + { 0x1525, 46067 }, + { 0x1526, 46109 }, + { 0x1527, 46612 }, + { 0x1528, 46112 }, + { 0x1529, 46401 }, + { 0x152A, 46115 }, + { 0x152B, 46404 }, + { 0x152C, 46826 }, + { 0x152D, 46106 }, + { 0x152E, 46398 }, + { 0x152F, 46410 }, + { 0x1530, 47939 }, + { 0x1531, 46413 }, + { 0x1532, 47943 }, + { 0x1533, 46618 }, + { 0x1534, 48067 }, + { 0x1535, 46416 }, + { 0x1536, 47947 }, + { 0x1537, 46621 }, + { 0x1538, 48071 }, + { 0x1539, 46407 }, + { 0x153A, 47935 }, + { 0x153B, 46615 }, + { 0x153C, 48063 }, + { 0x153D, 47599 }, + { 0x153E, 45911 }, + { 0x153F, 48099 }, + { 0x1540, 47755 }, + { 0x1541, 46766 }, + { 0x1542, 46052 }, + { 0x1543, 46730 }, + { 0x1544, 47763 }, + { 0x1545, 46528 }, + { 0x1546, 46055 }, + { 0x1547, 46290 }, + { 0x1548, 46058 }, + { 0x1549, 46293 }, + { 0x154A, 47767 }, + { 0x154B, 46049 }, + { 0x154C, 46287 }, + { 0x154D, 47759 }, + { 0x154E, 46531 }, + { 0x154F, 48019 }, + { 0x1550, 45902 }, + { 0x1551, 47751 }, + { 0x1552, 46714 }, + { 0x1553, 45941 }, + { 0x1554, 46431 }, + { 0x1555, 45944 }, + { 0x1556, 46149 }, + { 0x1557, 45947 }, + { 0x1558, 46152 }, + { 0x1559, 45938 }, + { 0x155A, 46146 }, + { 0x155B, 46438 }, + { 0x155C, 47963 }, + { 0x155D, 45875 }, + { 0x155E, 46335 }, + { 0x155F, 46718 }, + { 0x1560, 46338 }, + { 0x1561, 46722 }, + { 0x1562, 46573 }, + { 0x1563, 46726 }, + { 0x1564, 46341 }, + { 0x1565, 46576 }, + { 0x1566, 46332 }, + { 0x1567, 46570 }, + { 0x1568, 46707 }, + { 0x1569, 48087 }, + { 0x156A, 46085 }, + { 0x156B, 46594 }, + { 0x156C, 46597 }, + { 0x156D, 46600 }, + { 0x156E, 46591 }, + { 0x156F, 46356 }, + { 0x1570, 46380 }, + { 0x1571, 46383 }, + { 0x1572, 46386 }, + { 0x1573, 46377 }, + { 0x1574, 47611 }, + { 0x1575, 47615 }, + { 0x1576, 47627 }, + { 0x1577, 47619 }, + { 0x1578, 47631 }, + { 0x1579, 47607 }, + { 0x157A, 47623 }, + { 0x157B, 47603 }, + { 0x157C, 47635 }, + { 0x157D, 45950 }, + { 0x157E, 46525 }, + { 0x157F, 46043 }, + { 0x1580, 46281 }, + { 0x1581, 46046 }, + { 0x1582, 46284 }, + { 0x1583, 46040 }, + { 0x1584, 46275 }, + { 0x1585, 45899 }, + { 0x1586, 46582 }, + { 0x1587, 46585 }, + { 0x1588, 46588 }, + { 0x1589, 46579 }, + { 0x158A, 47775 }, + { 0x158B, 47779 }, + { 0x158C, 47783 }, + { 0x158D, 47771 }, + { 0x158E, 46686 }, + { 0x158F, 46233 }, + { 0x1590, 46495 }, + { 0x1591, 46236 }, + { 0x1592, 46498 }, + { 0x1593, 46230 }, + { 0x1594, 46489 }, + { 0x1595, 46010 }, + { 0x1596, 46242 }, + { 0x1597, 46774 }, + { 0x1598, 46778 }, + { 0x1599, 46782 }, + { 0x159A, 46770 }, + { 0x159B, 48115 }, + { 0x159C, 48119 }, + { 0x159D, 48123 }, + { 0x159E, 48111 }, + { 0x159F, 48107 }, + { 0x15A0, 46182 }, + { 0x15A1, 46459 }, + { 0x15A2, 46185 }, + { 0x15A3, 46462 }, + { 0x15A4, 46179 }, + { 0x15A5, 46456 }, + { 0x15A6, 45980 }, + { 0x15A7, 47647 }, + { 0x15A8, 47651 }, + { 0x15A9, 47663 }, + { 0x15AA, 47655 }, + { 0x15AB, 47667 }, + { 0x15AC, 47643 }, + { 0x15AD, 47659 }, + { 0x15AE, 47639 }, + { 0x15AF, 46834 }, + { 0x15B0, 47675 }, + { 0x15B1, 47679 }, + { 0x15B2, 47683 }, + { 0x15B3, 47671 }, + { 0x15B4, 47727 }, + { 0x15B5, 47731 }, + { 0x15B6, 47735 }, + { 0x15B7, 47723 }, + { 0x15B8, 47711 }, + { 0x15B9, 47715 }, + { 0x15BA, 47719 }, + { 0x15BB, 47707 }, + { 0x15BC, 47695 }, + { 0x15BD, 47699 }, + { 0x15BE, 47703 }, + { 0x15BF, 47691 }, + { 0x15C0, 46742 }, + { 0x15C1, 46746 }, + { 0x15C2, 46750 }, + { 0x15C3, 46738 }, + { 0x15C4, 47182 }, + { 0x15C5, 47178 }, + { 0x15C6, 47170 }, + { 0x15C7, 47442 }, + { 0x15C8, 47174 }, + { 0x15C9, 47166 }, + { 0x15CA, 47010 }, + { 0x15CB, 47006 }, + { 0x15CC, 46998 }, + { 0x15CD, 47310 }, + { 0x15CE, 47002 }, + { 0x15CF, 46994 }, + { 0x15D0, 47054 }, + { 0x15D1, 47050 }, + { 0x15D2, 47042 }, + { 0x15D3, 47418 }, + { 0x15D4, 47046 }, + { 0x15D5, 47038 }, + { 0x15D6, 47206 }, + { 0x15D7, 47202 }, + { 0x15D8, 47194 }, + { 0x15D9, 47446 }, + { 0x15DA, 47198 }, + { 0x15DB, 47190 }, + { 0x15DC, 47354 }, + { 0x15DD, 47350 }, + { 0x15DE, 47342 }, + { 0x15DF, 47470 }, + { 0x15E0, 47346 }, + { 0x15E1, 47338 }, + { 0x15E2, 47414 }, + { 0x15E3, 47410 }, + { 0x15E4, 47402 }, + { 0x15E5, 47502 }, + { 0x15E6, 47406 }, + { 0x15E7, 47398 }, + { 0x15E8, 46990 }, + { 0x15E9, 46986 }, + { 0x15EA, 46978 }, + { 0x15EB, 47306 }, + { 0x15EC, 46982 }, + { 0x15ED, 46974 }, + { 0x15EE, 46846 }, + { 0x15EF, 46878 }, + { 0x15F0, 46874 }, + { 0x15F1, 46866 }, + { 0x15F2, 47162 }, + { 0x15F3, 46870 }, + { 0x15F4, 46862 }, + { 0x15F5, 47250 }, + { 0x15F6, 47246 }, + { 0x15F7, 47238 }, + { 0x15F8, 47454 }, + { 0x15F9, 47242 }, + { 0x15FA, 47234 }, + { 0x15FB, 47270 }, + { 0x15FC, 47266 }, + { 0x15FD, 47258 }, + { 0x15FE, 47458 }, + { 0x15FF, 47262 }, + { 0x1600, 47254 }, + { 0x1601, 46906 }, + { 0x1602, 46970 }, + { 0x1603, 46966 }, + { 0x1604, 46954 }, + { 0x1605, 47302 }, + { 0x1606, 46962 }, + { 0x1607, 46950 }, + { 0x1608, 46946 }, + { 0x1609, 46942 }, + { 0x160A, 46934 }, + { 0x160B, 47298 }, + { 0x160C, 46938 }, + { 0x160D, 46930 }, + { 0x160E, 47074 }, + { 0x160F, 47070 }, + { 0x1610, 47062 }, + { 0x1611, 47422 }, + { 0x1612, 47066 }, + { 0x1613, 47058 }, + { 0x1614, 46902 }, + { 0x1615, 46758 }, + { 0x1616, 46898 }, + { 0x1617, 46890 }, + { 0x1618, 47210 }, + { 0x1619, 46894 }, + { 0x161A, 46754 }, + { 0x161B, 46886 }, + { 0x161C, 47230 }, + { 0x161D, 47226 }, + { 0x161E, 47218 }, + { 0x161F, 47450 }, + { 0x1620, 47222 }, + { 0x1621, 47214 }, + { 0x1622, 46926 }, + { 0x1623, 46922 }, + { 0x1624, 46914 }, + { 0x1625, 47274 }, + { 0x1626, 46918 }, + { 0x1627, 46910 }, + { 0x1628, 47138 }, + { 0x1629, 47134 }, + { 0x162A, 47126 }, + { 0x162B, 47434 }, + { 0x162C, 47130 }, + { 0x162D, 47122 }, + { 0x162E, 47294 }, + { 0x162F, 47290 }, + { 0x1630, 47282 }, + { 0x1631, 47462 }, + { 0x1632, 47286 }, + { 0x1633, 47278 }, + { 0x1634, 47494 }, + { 0x1635, 47490 }, + { 0x1636, 47482 }, + { 0x1637, 47526 }, + { 0x1638, 47486 }, + { 0x1639, 47478 }, + { 0x163A, 47374 }, + { 0x163B, 47370 }, + { 0x163C, 47362 }, + { 0x163D, 47474 }, + { 0x163E, 47366 }, + { 0x163F, 47358 }, + { 0x1640, 47094 }, + { 0x1641, 47090 }, + { 0x1642, 47082 }, + { 0x1643, 47426 }, + { 0x1644, 47086 }, + { 0x1645, 47078 }, + { 0x1646, 46850 }, + { 0x1647, 47534 }, + { 0x1648, 47158 }, + { 0x1649, 47154 }, + { 0x164A, 47146 }, + { 0x164B, 47438 }, + { 0x164C, 47150 }, + { 0x164D, 47142 }, + { 0x164E, 47034 }, + { 0x164F, 47030 }, + { 0x1650, 47018 }, + { 0x1651, 47314 }, + { 0x1652, 47026 }, + { 0x1653, 47014 }, + { 0x1654, 47334 }, + { 0x1655, 47330 }, + { 0x1656, 47322 }, + { 0x1657, 47466 }, + { 0x1658, 47326 }, + { 0x1659, 47318 }, + { 0x165A, 47022 }, + { 0x165B, 47394 }, + { 0x165C, 47390 }, + { 0x165D, 47382 }, + { 0x165E, 47498 }, + { 0x165F, 47386 }, + { 0x1660, 47378 }, + { 0x1661, 47114 }, + { 0x1662, 47110 }, + { 0x1663, 47102 }, + { 0x1664, 47430 }, + { 0x1665, 47106 }, + { 0x1666, 47098 }, + { 0x1667, 47522 }, + { 0x1668, 47518 }, + { 0x1669, 47510 }, + { 0x166A, 47530 }, + { 0x166B, 47514 }, + { 0x166C, 47506 }, + { 0x166D, 46124 }, + { 0x166E, 46434 }, + { 0x166F, 46278 }, + { 0x1670, 46492 }, + { 0x1671, 46504 }, + { 0x1672, 46692 }, + { 0x1673, 46507 }, + { 0x1674, 46695 }, + { 0x1675, 46501 }, + { 0x1676, 46689 }, + { 0x1680, 21369 }, + { 0x1681, 21414 }, + { 0x1682, 21396 }, + { 0x1683, 21420 }, + { 0x1684, 21408 }, + { 0x1685, 21402 }, + { 0x1686, 21411 }, + { 0x1687, 21387 }, + { 0x1688, 21426 }, + { 0x1689, 21384 }, + { 0x168A, 21417 }, + { 0x168B, 21399 }, + { 0x168C, 21390 }, + { 0x168D, 21441 }, + { 0x168E, 21429 }, + { 0x168F, 21405 }, + { 0x1690, 21381 }, + { 0x1691, 21378 }, + { 0x1692, 21375 }, + { 0x1693, 21435 }, + { 0x1694, 21438 }, + { 0x1695, 21432 }, + { 0x1696, 21372 }, + { 0x1697, 21444 }, + { 0x1698, 21393 }, + { 0x1699, 21447 }, + { 0x169A, 21423 }, + { 0x169B, 21450 }, + { 0x169C, 21453 }, + { 0x16A0, 22222 }, + { 0x16A1, 22160 }, + { 0x16A2, 22250 }, + { 0x16A3, 22189 }, + { 0x16A4, 22169 }, + { 0x16A5, 22163 }, + { 0x16A6, 22368 }, + { 0x16A7, 22201 }, + { 0x16A8, 22259 }, + { 0x16A9, 22185 }, + { 0x16AA, 22175 }, + { 0x16AB, 22216 }, + { 0x16AC, 22402 }, + { 0x16AD, 22390 }, + { 0x16AE, 22154 }, + { 0x16AF, 22179 }, + { 0x16B0, 22182 }, + { 0x16B1, 22287 }, + { 0x16B2, 22284 }, + { 0x16B3, 22192 }, + { 0x16B4, 22243 }, + { 0x16B5, 22151 }, + { 0x16B6, 22198 }, + { 0x16B7, 22228 }, + { 0x16B8, 22204 }, + { 0x16B9, 22304 }, + { 0x16BA, 22309 }, + { 0x16BB, 22276 }, + { 0x16BC, 22422 }, + { 0x16BD, 22418 }, + { 0x16BE, 22327 }, + { 0x16BF, 22410 }, + { 0x16C0, 22362 }, + { 0x16C1, 22233 }, + { 0x16C2, 22148 }, + { 0x16C3, 22280 }, + { 0x16C4, 22207 }, + { 0x16C5, 22383 }, + { 0x16C6, 22376 }, + { 0x16C7, 22239 }, + { 0x16C8, 22336 }, + { 0x16C9, 22255 }, + { 0x16CA, 22341 }, + { 0x16CB, 22293 }, + { 0x16CC, 22394 }, + { 0x16CD, 22142 }, + { 0x16CE, 22172 }, + { 0x16CF, 22298 }, + { 0x16D0, 22398 }, + { 0x16D1, 22145 }, + { 0x16D2, 22353 }, + { 0x16D3, 22426 }, + { 0x16D4, 22365 }, + { 0x16D5, 22333 }, + { 0x16D6, 22271 }, + { 0x16D7, 22322 }, + { 0x16D8, 22414 }, + { 0x16D9, 22406 }, + { 0x16DA, 22316 }, + { 0x16DB, 22359 }, + { 0x16DC, 22313 }, + { 0x16DD, 22210 }, + { 0x16DE, 22266 }, + { 0x16DF, 22348 }, + { 0x16E0, 22195 }, + { 0x16E1, 22213 }, + { 0x16E2, 22345 }, + { 0x16E3, 22219 }, + { 0x16E4, 22263 }, + { 0x16E5, 22247 }, + { 0x16E6, 22387 }, + { 0x16E7, 22380 }, + { 0x16E8, 22373 }, + { 0x16E9, 22157 }, + { 0x16EA, 22166 }, + { 0x16EB, 22430 }, + { 0x16EC, 22436 }, + { 0x16ED, 22136 }, + { 0x16EE, 22139 }, + { 0x16EF, 22439 }, + { 0x16F0, 22433 }, + { 0x1700, 43594 }, + { 0x1701, 43597 }, + { 0x1702, 43600 }, + { 0x1703, 43615 }, + { 0x1704, 43609 }, + { 0x1705, 43642 }, + { 0x1706, 43633 }, + { 0x1707, 43606 }, + { 0x1708, 43624 }, + { 0x1709, 43627 }, + { 0x170A, 43603 }, + { 0x170B, 43621 }, + { 0x170C, 43639 }, + { 0x170E, 43618 }, + { 0x170F, 43636 }, + { 0x1710, 43630 }, + { 0x1711, 43612 }, + { 0x1712, 43586 }, + { 0x1713, 43590 }, + { 0x1714, 43583 }, + { 0x1720, 40573 }, + { 0x1721, 40576 }, + { 0x1722, 40579 }, + { 0x1723, 40594 }, + { 0x1724, 40588 }, + { 0x1725, 40624 }, + { 0x1726, 40615 }, + { 0x1727, 40585 }, + { 0x1728, 40603 }, + { 0x1729, 40606 }, + { 0x172A, 40582 }, + { 0x172B, 40600 }, + { 0x172C, 40621 }, + { 0x172D, 40609 }, + { 0x172E, 40597 }, + { 0x172F, 40618 }, + { 0x1730, 40612 }, + { 0x1731, 40591 }, + { 0x1732, 40565 }, + { 0x1733, 40569 }, + { 0x1734, 40562 }, + { 0x1735, 67884 }, + { 0x1736, 67881 }, + { 0x1740, 10387 }, + { 0x1741, 10390 }, + { 0x1742, 10393 }, + { 0x1743, 10408 }, + { 0x1744, 10402 }, + { 0x1745, 10438 }, + { 0x1746, 10429 }, + { 0x1747, 10399 }, + { 0x1748, 10417 }, + { 0x1749, 10420 }, + { 0x174A, 10396 }, + { 0x174B, 10414 }, + { 0x174C, 10435 }, + { 0x174D, 10423 }, + { 0x174E, 10411 }, + { 0x174F, 10432 }, + { 0x1750, 10426 }, + { 0x1751, 10405 }, + { 0x1752, 10379 }, + { 0x1753, 10383 }, + { 0x1760, 55665 }, + { 0x1761, 55668 }, + { 0x1762, 55671 }, + { 0x1763, 55683 }, + { 0x1764, 55680 }, + { 0x1765, 55710 }, + { 0x1766, 55701 }, + { 0x1767, 55677 }, + { 0x1768, 55692 }, + { 0x1769, 55695 }, + { 0x176A, 55674 }, + { 0x176B, 55689 }, + { 0x176C, 55707 }, + { 0x176E, 55686 }, + { 0x176F, 55704 }, + { 0x1770, 55698 }, + { 0x1772, 55657 }, + { 0x1773, 55661 }, + { 0x1780, 14115 }, + { 0x1781, 14163 }, + { 0x1782, 14118 }, + { 0x1783, 14166 }, + { 0x1784, 14169 }, + { 0x1785, 14100 }, + { 0x1786, 14157 }, + { 0x1787, 14103 }, + { 0x1788, 14160 }, + { 0x1789, 14175 }, + { 0x178A, 14106 }, + { 0x178B, 14196 }, + { 0x178C, 14109 }, + { 0x178D, 14199 }, + { 0x178E, 14172 }, + { 0x178F, 14145 }, + { 0x1790, 14190 }, + { 0x1791, 14148 }, + { 0x1792, 14193 }, + { 0x1793, 14130 }, + { 0x1794, 14097 }, + { 0x1795, 14178 }, + { 0x1796, 14133 }, + { 0x1797, 14181 }, + { 0x1798, 14127 }, + { 0x1799, 14154 }, + { 0x179A, 14139 }, + { 0x179B, 14124 }, + { 0x179C, 14151 }, + { 0x179D, 14184 }, + { 0x179E, 14187 }, + { 0x179F, 14142 }, + { 0x17A0, 14112 }, + { 0x17A1, 14121 }, + { 0x17A2, 14136 }, + { 0x17A3, 14414 }, + { 0x17A4, 14406 }, + { 0x17A5, 14390 }, + { 0x17A6, 14422 }, + { 0x17A7, 14394 }, + { 0x17A8, 14438 }, + { 0x17A9, 14442 }, + { 0x17AA, 14450 }, + { 0x17AB, 14398 }, + { 0x17AC, 14446 }, + { 0x17AD, 14382 }, + { 0x17AE, 14402 }, + { 0x17AF, 14386 }, + { 0x17B0, 14410 }, + { 0x17B1, 14426 }, + { 0x17B2, 14432 }, + { 0x17B3, 14418 }, + { 0x17B4, 14093 }, + { 0x17B5, 14089 }, + { 0x17B6, 14041 }, + { 0x17B7, 14029 }, + { 0x17B8, 14061 }, + { 0x17B9, 14037 }, + { 0x17BA, 14085 }, + { 0x17BB, 14033 }, + { 0x17BC, 14077 }, + { 0x17BD, 14073 }, + { 0x17BE, 14065 }, + { 0x17BF, 14081 }, + { 0x17C0, 14057 }, + { 0x17C1, 14025 }, + { 0x17C2, 14045 }, + { 0x17C3, 14049 }, + { 0x17C4, 14069 }, + { 0x17C5, 14053 }, + { 0x17C6, 13965 }, + { 0x17C7, 13968 }, + { 0x17C8, 13992 }, + { 0x17C9, 13983 }, + { 0x17CA, 13971 }, + { 0x17CB, 13937 }, + { 0x17CC, 13934 }, + { 0x17CD, 13986 }, + { 0x17CE, 13959 }, + { 0x17CF, 13928 }, + { 0x17D0, 13952 }, + { 0x17D1, 13956 }, + { 0x17D2, 13931 }, + { 0x17D3, 13980 }, + { 0x17D4, 13925 }, + { 0x17D5, 13977 }, + { 0x17D6, 13943 }, + { 0x17D7, 13921 }, + { 0x17D8, 13940 }, + { 0x17D9, 13948 }, + { 0x17DA, 13962 }, + { 0x17DB, 14378 }, + { 0x17DC, 13989 }, + { 0x17DD, 13974 }, + { 0x17E0, 14013 }, + { 0x17E1, 13995 }, + { 0x17E2, 14001 }, + { 0x17E3, 14022 }, + { 0x17E4, 14007 }, + { 0x17E5, 14004 }, + { 0x17E6, 13998 }, + { 0x17E7, 14019 }, + { 0x17E8, 14016 }, + { 0x17E9, 14010 }, + { 0x17F0, 14228 }, + { 0x17F1, 14238 }, + { 0x17F2, 14223 }, + { 0x17F3, 14218 }, + { 0x17F4, 14233 }, + { 0x17F5, 14243 }, + { 0x17F6, 14263 }, + { 0x17F7, 14253 }, + { 0x17F8, 14248 }, + { 0x17F9, 14258 }, + { 0x1800, 65145 }, + { 0x1801, 65749 }, + { 0x1802, 65149 }, + { 0x1803, 65133 }, + { 0x1804, 65147 }, + { 0x1805, 65115 }, + { 0x1806, 65141 }, + { 0x1807, 65136 }, + { 0x1808, 65744 }, + { 0x1809, 65740 }, + { 0x180A, 65747 }, + { 0x180B, 65118 }, + { 0x180C, 65123 }, + { 0x180D, 65128 }, + { 0x180E, 65181 }, + { 0x1810, 65169 }, + { 0x1811, 65151 }, + { 0x1812, 65157 }, + { 0x1813, 65178 }, + { 0x1814, 65163 }, + { 0x1815, 65160 }, + { 0x1816, 65154 }, + { 0x1817, 65175 }, + { 0x1818, 65172 }, + { 0x1819, 65166 }, + { 0x1820, 65184 }, + { 0x1821, 65187 }, + { 0x1822, 65190 }, + { 0x1823, 65193 }, + { 0x1824, 65196 }, + { 0x1825, 65229 }, + { 0x1826, 65247 }, + { 0x1827, 65205 }, + { 0x1828, 65226 }, + { 0x1829, 65400 }, + { 0x182A, 65199 }, + { 0x182B, 65232 }, + { 0x182C, 65235 }, + { 0x182D, 65211 }, + { 0x182E, 65223 }, + { 0x182F, 65220 }, + { 0x1830, 65241 }, + { 0x1831, 65418 }, + { 0x1832, 65244 }, + { 0x1833, 65202 }, + { 0x1834, 65403 }, + { 0x1835, 65214 }, + { 0x1836, 65253 }, + { 0x1837, 65238 }, + { 0x1838, 65250 }, + { 0x1839, 65208 }, + { 0x183A, 65217 }, + { 0x183B, 65412 }, + { 0x183C, 65421 }, + { 0x183D, 65256 }, + { 0x183E, 65409 }, + { 0x183F, 65427 }, + { 0x1840, 65415 }, + { 0x1841, 65424 }, + { 0x1842, 65406 }, + { 0x1843, 65630 }, + { 0x1844, 65518 }, + { 0x1845, 65522 }, + { 0x1846, 65526 }, + { 0x1847, 65530 }, + { 0x1848, 65558 }, + { 0x1849, 65574 }, + { 0x184A, 65598 }, + { 0x184B, 65534 }, + { 0x184C, 65562 }, + { 0x184D, 65566 }, + { 0x184E, 65542 }, + { 0x184F, 65554 }, + { 0x1850, 65570 }, + { 0x1851, 65538 }, + { 0x1852, 65602 }, + { 0x1853, 65546 }, + { 0x1854, 65626 }, + { 0x1855, 65582 }, + { 0x1856, 65578 }, + { 0x1857, 65550 }, + { 0x1858, 65610 }, + { 0x1859, 65614 }, + { 0x185A, 65618 }, + { 0x185B, 65622 }, + { 0x185C, 65606 }, + { 0x185D, 65430 }, + { 0x185E, 65434 }, + { 0x185F, 65458 }, + { 0x1860, 65478 }, + { 0x1861, 65438 }, + { 0x1862, 65486 }, + { 0x1863, 65466 }, + { 0x1864, 65450 }, + { 0x1865, 65454 }, + { 0x1866, 65470 }, + { 0x1867, 65506 }, + { 0x1868, 65474 }, + { 0x1869, 65442 }, + { 0x186A, 65462 }, + { 0x186B, 65446 }, + { 0x186C, 65494 }, + { 0x186D, 65498 }, + { 0x186E, 65510 }, + { 0x186F, 65482 }, + { 0x1870, 65502 }, + { 0x1871, 65490 }, + { 0x1872, 65514 }, + { 0x1873, 65636 }, + { 0x1874, 65644 }, + { 0x1875, 65648 }, + { 0x1876, 65640 }, + { 0x1877, 65736 }, + { 0x1880, 65388 }, + { 0x1881, 65382 }, + { 0x1882, 65367 }, + { 0x1883, 65377 }, + { 0x1884, 65394 }, + { 0x1885, 65362 }, + { 0x1886, 65356 }, + { 0x1887, 65259 }, + { 0x1888, 65264 }, + { 0x1889, 65284 }, + { 0x188A, 65309 }, + { 0x188B, 65274 }, + { 0x188C, 65329 }, + { 0x188D, 65351 }, + { 0x188E, 65304 }, + { 0x188F, 65314 }, + { 0x1890, 65294 }, + { 0x1891, 65279 }, + { 0x1892, 65289 }, + { 0x1893, 65319 }, + { 0x1894, 65324 }, + { 0x1895, 65334 }, + { 0x1896, 65299 }, + { 0x1897, 65269 }, + { 0x1898, 65586 }, + { 0x1899, 65592 }, + { 0x189A, 65688 }, + { 0x189B, 65706 }, + { 0x189C, 65652 }, + { 0x189D, 65694 }, + { 0x189E, 65718 }, + { 0x189F, 65730 }, + { 0x18A0, 65658 }, + { 0x18A1, 65682 }, + { 0x18A2, 65712 }, + { 0x18A3, 65676 }, + { 0x18A4, 65724 }, + { 0x18A5, 65664 }, + { 0x18A6, 65339 }, + { 0x18A7, 65345 }, + { 0x18A8, 65670 }, + { 0x18A9, 65372 }, + { 0x18AA, 65700 }, + { 0x1900, 21091 }, + { 0x1901, 21007 }, + { 0x1902, 21052 }, + { 0x1903, 20998 }, + { 0x1904, 21046 }, + { 0x1905, 21055 }, + { 0x1906, 20992 }, + { 0x1907, 21040 }, + { 0x1908, 21004 }, + { 0x1909, 21049 }, + { 0x190A, 21070 }, + { 0x190B, 21028 }, + { 0x190C, 21067 }, + { 0x190D, 20995 }, + { 0x190E, 21043 }, + { 0x190F, 21016 }, + { 0x1910, 21019 }, + { 0x1911, 21058 }, + { 0x1912, 20989 }, + { 0x1913, 21037 }, + { 0x1914, 21013 }, + { 0x1915, 21034 }, + { 0x1916, 21022 }, + { 0x1917, 21010 }, + { 0x1918, 21031 }, + { 0x1919, 21061 }, + { 0x191A, 21064 }, + { 0x191B, 21025 }, + { 0x191C, 21001 }, + { 0x1920, 20953 }, + { 0x1921, 20961 }, + { 0x1922, 20969 }, + { 0x1923, 20981 }, + { 0x1924, 20973 }, + { 0x1925, 20985 }, + { 0x1926, 20977 }, + { 0x1927, 20957 }, + { 0x1928, 20965 }, + { 0x1929, 21084 }, + { 0x192A, 21076 }, + { 0x192B, 21080 }, + { 0x1930, 20917 }, + { 0x1931, 20945 }, + { 0x1932, 20949 }, + { 0x1933, 20941 }, + { 0x1934, 20929 }, + { 0x1935, 20933 }, + { 0x1936, 20925 }, + { 0x1937, 20937 }, + { 0x1938, 20921 }, + { 0x1939, 20884 }, + { 0x193A, 20881 }, + { 0x193B, 20878 }, + { 0x1940, 20875 }, + { 0x1944, 21088 }, + { 0x1945, 21073 }, + { 0x1946, 20905 }, + { 0x1947, 20887 }, + { 0x1948, 20893 }, + { 0x1949, 20914 }, + { 0x194A, 20899 }, + { 0x194B, 20896 }, + { 0x194C, 20890 }, + { 0x194D, 20911 }, + { 0x194E, 20908 }, + { 0x194F, 20902 }, + { 0x1950, 7612 }, + { 0x1951, 7656 }, + { 0x1952, 7672 }, + { 0x1953, 7684 }, + { 0x1954, 7640 }, + { 0x1955, 7660 }, + { 0x1956, 7644 }, + { 0x1957, 7680 }, + { 0x1958, 7616 }, + { 0x1959, 7632 }, + { 0x195A, 7676 }, + { 0x195B, 7620 }, + { 0x195C, 7604 }, + { 0x195D, 7652 }, + { 0x195E, 7608 }, + { 0x195F, 7636 }, + { 0x1960, 7668 }, + { 0x1961, 7688 }, + { 0x1962, 7624 }, + { 0x1963, 7572 }, + { 0x1964, 7580 }, + { 0x1965, 7596 }, + { 0x1966, 7600 }, + { 0x1967, 7588 }, + { 0x1968, 7628 }, + { 0x1969, 7584 }, + { 0x196A, 7648 }, + { 0x196B, 7576 }, + { 0x196C, 7664 }, + { 0x196D, 7592 }, + { 0x1970, 7692 }, + { 0x1971, 7696 }, + { 0x1972, 7700 }, + { 0x1973, 7704 }, + { 0x1974, 7708 }, + { 0x1980, 6393 }, + { 0x1981, 6267 }, + { 0x1982, 6363 }, + { 0x1983, 6417 }, + { 0x1984, 6435 }, + { 0x1985, 6237 }, + { 0x1986, 6291 }, + { 0x1987, 6309 }, + { 0x1988, 6453 }, + { 0x1989, 6399 }, + { 0x198A, 6423 }, + { 0x198B, 6327 }, + { 0x198C, 6273 }, + { 0x198D, 6297 }, + { 0x198E, 6405 }, + { 0x198F, 6447 }, + { 0x1990, 6381 }, + { 0x1991, 6279 }, + { 0x1992, 6321 }, + { 0x1993, 6255 }, + { 0x1994, 6387 }, + { 0x1995, 6441 }, + { 0x1996, 6375 }, + { 0x1997, 6261 }, + { 0x1998, 6315 }, + { 0x1999, 6249 }, + { 0x199A, 6351 }, + { 0x199B, 6411 }, + { 0x199C, 6369 }, + { 0x199D, 6225 }, + { 0x199E, 6285 }, + { 0x199F, 6243 }, + { 0x19A0, 6357 }, + { 0x19A1, 6345 }, + { 0x19A2, 6339 }, + { 0x19A3, 6231 }, + { 0x19A4, 6219 }, + { 0x19A5, 6213 }, + { 0x19A6, 6429 }, + { 0x19A7, 6459 }, + { 0x19A8, 6303 }, + { 0x19A9, 6333 }, + { 0x19B0, 6206 }, + { 0x19B1, 6128 }, + { 0x19B2, 6146 }, + { 0x19B3, 6122 }, + { 0x19B4, 6176 }, + { 0x19B5, 6110 }, + { 0x19B6, 6134 }, + { 0x19B7, 6116 }, + { 0x19B8, 6158 }, + { 0x19B9, 6170 }, + { 0x19BA, 6140 }, + { 0x19BB, 6188 }, + { 0x19BC, 6182 }, + { 0x19BD, 6164 }, + { 0x19BE, 6194 }, + { 0x19BF, 6200 }, + { 0x19C0, 6152 }, + { 0x19C1, 6495 }, + { 0x19C2, 6501 }, + { 0x19C3, 6489 }, + { 0x19C4, 6483 }, + { 0x19C5, 6477 }, + { 0x19C6, 6471 }, + { 0x19C7, 6465 }, + { 0x19C8, 6050 }, + { 0x19C9, 6055 }, + { 0x19D0, 6090 }, + { 0x19D1, 6060 }, + { 0x19D2, 6070 }, + { 0x19D3, 6105 }, + { 0x19D4, 6080 }, + { 0x19D5, 6075 }, + { 0x19D6, 6065 }, + { 0x19D7, 6100 }, + { 0x19D8, 6095 }, + { 0x19D9, 6085 }, + { 0x19DE, 6040 }, + { 0x19DF, 6045 }, + { 0x19E0, 14375 }, + { 0x19E1, 14288 }, + { 0x19E2, 14272 }, + { 0x19E3, 14206 }, + { 0x19E4, 14280 }, + { 0x19E5, 14296 }, + { 0x19E6, 14368 }, + { 0x19E7, 14352 }, + { 0x19E8, 14344 }, + { 0x19E9, 14360 }, + { 0x19EA, 14214 }, + { 0x19EB, 14328 }, + { 0x19EC, 14312 }, + { 0x19ED, 14304 }, + { 0x19EE, 14320 }, + { 0x19EF, 14336 }, + { 0x19F0, 14372 }, + { 0x19F1, 14284 }, + { 0x19F2, 14268 }, + { 0x19F3, 14202 }, + { 0x19F4, 14276 }, + { 0x19F5, 14292 }, + { 0x19F6, 14364 }, + { 0x19F7, 14348 }, + { 0x19F8, 14340 }, + { 0x19F9, 14356 }, + { 0x19FA, 14210 }, + { 0x19FB, 14324 }, + { 0x19FC, 14308 }, + { 0x19FD, 14300 }, + { 0x19FE, 14316 }, + { 0x19FF, 14332 }, + { 0x1A00, 45814 }, + { 0x1A01, 45805 }, + { 0x1A02, 45847 }, + { 0x1A03, 45856 }, + { 0x1A04, 45826 }, + { 0x1A05, 45796 }, + { 0x1A06, 45820 }, + { 0x1A07, 45844 }, + { 0x1A08, 45835 }, + { 0x1A09, 45802 }, + { 0x1A0A, 45823 }, + { 0x1A0B, 45850 }, + { 0x1A0C, 45799 }, + { 0x1A0D, 45811 }, + { 0x1A0E, 45853 }, + { 0x1A0F, 45859 }, + { 0x1A10, 45841 }, + { 0x1A11, 45829 }, + { 0x1A12, 45817 }, + { 0x1A13, 45838 }, + { 0x1A14, 45832 }, + { 0x1A15, 45793 }, + { 0x1A16, 45808 }, + { 0x1A17, 45777 }, + { 0x1A18, 45785 }, + { 0x1A19, 45773 }, + { 0x1A1A, 45781 }, + { 0x1A1B, 45789 }, + { 0x1A1E, 45862 }, + { 0x1A1F, 45769 }, + { 0x1B00, 45088 }, + { 0x1B01, 45092 }, + { 0x1B02, 45099 }, + { 0x1B03, 45102 }, + { 0x1B04, 45096 }, + { 0x1B05, 45383 }, + { 0x1B06, 45386 }, + { 0x1B07, 45393 }, + { 0x1B08, 45396 }, + { 0x1B09, 45407 }, + { 0x1B0A, 45410 }, + { 0x1B0B, 45315 }, + { 0x1B0C, 45319 }, + { 0x1B0D, 45286 }, + { 0x1B0E, 45290 }, + { 0x1B0F, 45390 }, + { 0x1B10, 45414 }, + { 0x1B11, 45400 }, + { 0x1B12, 45403 }, + { 0x1B13, 45276 }, + { 0x1B14, 45279 }, + { 0x1B15, 45259 }, + { 0x1B16, 45262 }, + { 0x1B17, 45365 }, + { 0x1B18, 45231 }, + { 0x1B19, 45234 }, + { 0x1B1A, 45269 }, + { 0x1B1B, 45272 }, + { 0x1B1C, 45368 }, + { 0x1B1D, 45342 }, + { 0x1B1E, 45346 }, + { 0x1B1F, 45245 }, + { 0x1B20, 45250 }, + { 0x1B21, 45301 }, + { 0x1B22, 45335 }, + { 0x1B23, 45338 }, + { 0x1B24, 45238 }, + { 0x1B25, 45241 }, + { 0x1B26, 45298 }, + { 0x1B27, 45305 }, + { 0x1B28, 45308 }, + { 0x1B29, 45224 }, + { 0x1B2A, 45227 }, + { 0x1B2B, 45295 }, + { 0x1B2C, 45358 }, + { 0x1B2D, 45312 }, + { 0x1B2E, 45283 }, + { 0x1B2F, 45355 }, + { 0x1B30, 45327 }, + { 0x1B31, 45331 }, + { 0x1B32, 45324 }, + { 0x1B33, 45266 }, + { 0x1B34, 45105 }, + { 0x1B35, 45218 }, + { 0x1B36, 45171 }, + { 0x1B37, 45175 }, + { 0x1B38, 45180 }, + { 0x1B39, 45184 }, + { 0x1B3A, 45160 }, + { 0x1B3B, 45165 }, + { 0x1B3C, 45149 }, + { 0x1B3D, 45154 }, + { 0x1B3E, 45198 }, + { 0x1B3F, 45202 }, + { 0x1B40, 45213 }, + { 0x1B41, 45207 }, + { 0x1B42, 45189 }, + { 0x1B43, 45193 }, + { 0x1B44, 45085 }, + { 0x1B45, 45361 }, + { 0x1B46, 45375 }, + { 0x1B47, 45379 }, + { 0x1B48, 45255 }, + { 0x1B49, 45351 }, + { 0x1B4A, 45371 }, + { 0x1B4B, 45417 }, + { 0x1B50, 45135 }, + { 0x1B51, 45117 }, + { 0x1B52, 45123 }, + { 0x1B53, 45144 }, + { 0x1B54, 45129 }, + { 0x1B55, 45126 }, + { 0x1B56, 45120 }, + { 0x1B57, 45141 }, + { 0x1B58, 45138 }, + { 0x1B59, 45132 }, + { 0x1B5A, 45147 }, + { 0x1B5B, 45421 }, + { 0x1B5C, 45222 }, + { 0x1B5D, 45114 }, + { 0x1B5E, 45108 }, + { 0x1B5F, 45111 }, + { 0x1B60, 45568 }, + { 0x1B61, 45445 }, + { 0x1B62, 45437 }, + { 0x1B63, 45449 }, + { 0x1B64, 45423 }, + { 0x1B65, 45432 }, + { 0x1B66, 45441 }, + { 0x1B67, 45453 }, + { 0x1B68, 45461 }, + { 0x1B69, 45457 }, + { 0x1B6A, 45427 }, + { 0x1B6B, 45480 }, + { 0x1B6C, 45475 }, + { 0x1B6D, 45497 }, + { 0x1B6E, 45485 }, + { 0x1B6F, 45509 }, + { 0x1B70, 45502 }, + { 0x1B71, 45490 }, + { 0x1B72, 45470 }, + { 0x1B73, 45465 }, + { 0x1B74, 45550 }, + { 0x1B75, 45544 }, + { 0x1B76, 45562 }, + { 0x1B77, 45556 }, + { 0x1B78, 45514 }, + { 0x1B79, 45526 }, + { 0x1B7A, 45532 }, + { 0x1B7B, 45538 }, + { 0x1B7C, 45520 }, + { 0x1B80, 65869 }, + { 0x1B81, 65872 }, + { 0x1B82, 65875 }, + { 0x1B83, 65932 }, + { 0x1B84, 65938 }, + { 0x1B85, 65944 }, + { 0x1B86, 65947 }, + { 0x1B87, 65941 }, + { 0x1B88, 65935 }, + { 0x1B89, 65959 }, + { 0x1B8A, 65974 }, + { 0x1B8B, 65989 }, + { 0x1B8C, 65965 }, + { 0x1B8D, 66019 }, + { 0x1B8E, 65953 }, + { 0x1B8F, 65971 }, + { 0x1B90, 66013 }, + { 0x1B91, 66022 }, + { 0x1B92, 65998 }, + { 0x1B93, 65956 }, + { 0x1B94, 65983 }, + { 0x1B95, 65986 }, + { 0x1B96, 65962 }, + { 0x1B97, 66001 }, + { 0x1B98, 65950 }, + { 0x1B99, 65980 }, + { 0x1B9A, 66010 }, + { 0x1B9B, 65992 }, + { 0x1B9C, 65977 }, + { 0x1B9D, 66004 }, + { 0x1B9E, 65995 }, + { 0x1B9F, 66007 }, + { 0x1BA0, 65968 }, + { 0x1BA1, 66036 }, + { 0x1BA2, 66032 }, + { 0x1BA3, 66028 }, + { 0x1BA4, 65916 }, + { 0x1BA5, 65912 }, + { 0x1BA6, 65924 }, + { 0x1BA7, 65920 }, + { 0x1BA8, 65908 }, + { 0x1BA9, 65928 }, + { 0x1BAA, 65866 }, + { 0x1BAE, 66016 }, + { 0x1BAF, 66025 }, + { 0x1BB0, 65896 }, + { 0x1BB1, 65878 }, + { 0x1BB2, 65884 }, + { 0x1BB3, 65905 }, + { 0x1BB4, 65890 }, + { 0x1BB5, 65887 }, + { 0x1BB6, 65881 }, + { 0x1BB7, 65902 }, + { 0x1BB8, 65899 }, + { 0x1BB9, 65893 }, + { 0x1C00, 34194 }, + { 0x1C01, 34251 }, + { 0x1C02, 34248 }, + { 0x1C03, 34185 }, + { 0x1C04, 34242 }, + { 0x1C05, 34257 }, + { 0x1C06, 34176 }, + { 0x1C07, 34230 }, + { 0x1C08, 34191 }, + { 0x1C09, 34260 }, + { 0x1C0A, 34215 }, + { 0x1C0B, 34272 }, + { 0x1C0C, 34179 }, + { 0x1C0D, 34203 }, + { 0x1C0E, 34206 }, + { 0x1C0F, 34266 }, + { 0x1C10, 34263 }, + { 0x1C11, 34182 }, + { 0x1C12, 34239 }, + { 0x1C13, 34173 }, + { 0x1C14, 34227 }, + { 0x1C15, 34200 }, + { 0x1C16, 34254 }, + { 0x1C17, 34275 }, + { 0x1C18, 34281 }, + { 0x1C19, 34236 }, + { 0x1C1A, 34224 }, + { 0x1C1B, 34209 }, + { 0x1C1C, 34197 }, + { 0x1C1D, 34188 }, + { 0x1C1E, 34245 }, + { 0x1C1F, 34218 }, + { 0x1C20, 34212 }, + { 0x1C21, 34269 }, + { 0x1C22, 34221 }, + { 0x1C23, 34170 }, + { 0x1C24, 34327 }, + { 0x1C25, 34323 }, + { 0x1C26, 34158 }, + { 0x1C27, 34146 }, + { 0x1C28, 34150 }, + { 0x1C29, 34162 }, + { 0x1C2A, 34154 }, + { 0x1C2B, 34166 }, + { 0x1C2C, 34142 }, + { 0x1C2D, 34287 }, + { 0x1C2E, 34295 }, + { 0x1C2F, 34291 }, + { 0x1C30, 34299 }, + { 0x1C31, 34303 }, + { 0x1C32, 34307 }, + { 0x1C33, 34311 }, + { 0x1C34, 34319 }, + { 0x1C35, 34315 }, + { 0x1C36, 34106 }, + { 0x1C37, 34109 }, + { 0x1C3B, 34339 }, + { 0x1C3C, 34331 }, + { 0x1C3D, 34336 }, + { 0x1C3E, 34345 }, + { 0x1C3F, 34342 }, + { 0x1C40, 34130 }, + { 0x1C41, 34112 }, + { 0x1C42, 34118 }, + { 0x1C43, 34139 }, + { 0x1C44, 34124 }, + { 0x1C45, 34121 }, + { 0x1C46, 34115 }, + { 0x1C47, 34136 }, + { 0x1C48, 34133 }, + { 0x1C49, 34127 }, + { 0x1C4D, 34278 }, + { 0x1C4E, 34284 }, + { 0x1C4F, 34233 }, + { 0x1C50, 112 }, + { 0x1C51, 88 }, + { 0x1C52, 96 }, + { 0x1C53, 124 }, + { 0x1C54, 104 }, + { 0x1C55, 100 }, + { 0x1C56, 92 }, + { 0x1C57, 120 }, + { 0x1C58, 116 }, + { 0x1C59, 108 }, + { 0x1C5A, 163 }, + { 0x1C5B, 139 }, + { 0x1C5C, 131 }, + { 0x1C5D, 223 }, + { 0x1C5E, 135 }, + { 0x1C5F, 239 }, + { 0x1C60, 211 }, + { 0x1C61, 207 }, + { 0x1C62, 215 }, + { 0x1C63, 219 }, + { 0x1C64, 171 }, + { 0x1C65, 159 }, + { 0x1C66, 151 }, + { 0x1C67, 235 }, + { 0x1C68, 155 }, + { 0x1C69, 179 }, + { 0x1C6A, 195 }, + { 0x1C6B, 199 }, + { 0x1C6C, 247 }, + { 0x1C6D, 203 }, + { 0x1C6E, 167 }, + { 0x1C6F, 147 }, + { 0x1C70, 227 }, + { 0x1C71, 143 }, + { 0x1C72, 231 }, + { 0x1C73, 175 }, + { 0x1C74, 243 }, + { 0x1C75, 183 }, + { 0x1C76, 191 }, + { 0x1C77, 187 }, + { 0x1C78, 81 }, + { 0x1C79, 251 }, + { 0x1C7A, 258 }, + { 0x1C7B, 128 }, + { 0x1C7C, 255 }, + { 0x1C7D, 85 }, + { 0x1C7E, 267 }, + { 0x1C7F, 262 }, + { 0x1D00, 17949 }, + { 0x1D01, 18083 }, + { 0x1D02, 17650 }, + { 0x1D03, 18119 }, + { 0x1D04, 17959 }, + { 0x1D05, 17964 }, + { 0x1D06, 18098 }, + { 0x1D07, 17969 }, + { 0x1D08, 17660 }, + { 0x1D09, 17575 }, + { 0x1D0A, 18001 }, + { 0x1D0B, 18006 }, + { 0x1D0C, 18016 }, + { 0x1D0D, 18023 }, + { 0x1D0E, 18143 }, + { 0x1D0F, 18033 }, + { 0x1D10, 18113 }, + { 0x1D11, 17804 }, + { 0x1D12, 17821 }, + { 0x1D13, 17809 }, + { 0x1D14, 17655 }, + { 0x1D15, 18093 }, + { 0x1D16, 17292 }, + { 0x1D17, 17499 }, + { 0x1D18, 18038 }, + { 0x1D19, 18149 }, + { 0x1D1A, 18131 }, + { 0x1D1B, 18053 }, + { 0x1D1C, 18058 }, + { 0x1D1D, 17816 }, + { 0x1D1E, 17833 }, + { 0x1D1F, 17827 }, + { 0x1D20, 18063 }, + { 0x1D21, 18068 }, + { 0x1D22, 18078 }, + { 0x1D23, 18103 }, + { 0x1D24, 18159 }, + { 0x1D25, 17938 }, + { 0x1D26, 12051 }, + { 0x1D27, 12056 }, + { 0x1D28, 12036 }, + { 0x1D29, 12046 }, + { 0x1D2A, 12041 }, + { 0x1D2B, 49409 }, + { 0x1D2C, 54616 }, + { 0x1D2D, 54692 }, + { 0x1D2E, 54620 }, + { 0x1D2F, 54700 }, + { 0x1D30, 54624 }, + { 0x1D31, 54628 }, + { 0x1D32, 54705 }, + { 0x1D33, 54632 }, + { 0x1D34, 54636 }, + { 0x1D35, 54640 }, + { 0x1D36, 54644 }, + { 0x1D37, 54648 }, + { 0x1D38, 54652 }, + { 0x1D39, 54656 }, + { 0x1D3A, 54660 }, + { 0x1D3B, 54710 }, + { 0x1D3C, 54664 }, + { 0x1D3D, 54696 }, + { 0x1D3E, 54668 }, + { 0x1D3F, 54672 }, + { 0x1D40, 54676 }, + { 0x1D41, 54680 }, + { 0x1D42, 54688 }, + { 0x1D43, 54136 }, + { 0x1D44, 54421 }, + { 0x1D45, 54375 }, + { 0x1D46, 54466 }, + { 0x1D47, 54140 }, + { 0x1D48, 54154 }, + { 0x1D49, 54158 }, + { 0x1D4A, 54397 }, + { 0x1D4B, 54365 }, + { 0x1D4C, 54471 }, + { 0x1D4D, 54166 }, + { 0x1D4E, 54431 }, + { 0x1D4F, 54196 }, + { 0x1D50, 54218 }, + { 0x1D51, 54331 }, + { 0x1D52, 54242 }, + { 0x1D53, 54370 }, + { 0x1D54, 54351 }, + { 0x1D55, 54410 }, + { 0x1D56, 54246 }, + { 0x1D57, 54264 }, + { 0x1D58, 54275 }, + { 0x1D59, 54538 }, + { 0x1D5A, 54436 }, + { 0x1D5B, 54284 }, + { 0x1D5C, 54323 }, + { 0x1D5D, 54357 }, + { 0x1D5E, 54392 }, + { 0x1D5F, 54379 }, + { 0x1D60, 54387 }, + { 0x1D61, 54327 }, + { 0x1D62, 20792 }, + { 0x1D63, 20807 }, + { 0x1D64, 20812 }, + { 0x1D65, 20817 }, + { 0x1D66, 13101 }, + { 0x1D67, 13106 }, + { 0x1D68, 13096 }, + { 0x1D69, 13091 }, + { 0x1D6A, 13086 }, + { 0x1D6B, 17177 }, + { 0x1D6C, 14742 }, + { 0x1D6D, 14886 }, + { 0x1D6E, 15140 }, + { 0x1D6F, 15661 }, + { 0x1D70, 15745 }, + { 0x1D71, 16100 }, + { 0x1D72, 16239 }, + { 0x1D73, 16271 }, + { 0x1D74, 16370 }, + { 0x1D75, 16446 }, + { 0x1D76, 16999 }, + { 0x1D77, 17549 }, + { 0x1D78, 54782 }, + { 0x1D79, 17723 }, + { 0x1D7A, 17162 }, + { 0x1D7B, 17883 }, + { 0x1D7C, 17331 }, + { 0x1D7D, 16107 }, + { 0x1D7E, 17890 }, + { 0x1D7F, 17747 }, + { 0x1D80, 14761 }, + { 0x1D81, 14911 }, + { 0x1D82, 15147 }, + { 0x1D83, 15207 }, + { 0x1D84, 15493 }, + { 0x1D85, 15610 }, + { 0x1D86, 15668 }, + { 0x1D87, 15758 }, + { 0x1D88, 16121 }, + { 0x1D89, 16258 }, + { 0x1D8A, 16383 }, + { 0x1D8B, 17211 }, + { 0x1D8C, 16764 }, + { 0x1D8D, 16844 }, + { 0x1D8E, 17012 }, + { 0x1D8F, 14656 }, + { 0x1D90, 17433 }, + { 0x1D91, 14859 }, + { 0x1D92, 15061 }, + { 0x1D93, 17375 }, + { 0x1D94, 17791 }, + { 0x1D95, 17458 }, + { 0x1D96, 15395 }, + { 0x1D97, 17388 }, + { 0x1D98, 17218 }, + { 0x1D99, 16708 }, + { 0x1D9A, 17251 }, + { 0x1D9B, 54477 }, + { 0x1D9C, 54144 }, + { 0x1D9D, 54148 }, + { 0x1D9E, 54339 }, + { 0x1D9F, 54526 }, + { 0x1DA0, 54162 }, + { 0x1DA1, 54515 }, + { 0x1DA2, 54416 }, + { 0x1DA3, 54426 }, + { 0x1DA4, 54180 }, + { 0x1DA5, 54361 }, + { 0x1DA6, 54482 }, + { 0x1DA7, 54487 }, + { 0x1DA8, 54190 }, + { 0x1DA9, 54211 }, + { 0x1DAA, 54204 }, + { 0x1DAB, 54494 }, + { 0x1DAC, 54222 }, + { 0x1DAD, 54441 }, + { 0x1DAE, 54228 }, + { 0x1DAF, 54235 }, + { 0x1DB0, 54499 }, + { 0x1DB1, 54405 }, + { 0x1DB2, 54347 }, + { 0x1DB3, 54258 }, + { 0x1DB4, 54335 }, + { 0x1DB5, 54268 }, + { 0x1DB6, 54279 }, + { 0x1DB7, 54522 }, + { 0x1DB8, 54504 }, + { 0x1DB9, 54288 }, + { 0x1DBA, 54461 }, + { 0x1DBB, 54306 }, + { 0x1DBC, 54316 }, + { 0x1DBD, 54310 }, + { 0x1DBE, 54343 }, + { 0x1DBF, 54401 }, + { 0x1DC0, 57864 }, + { 0x1DC1, 57860 }, + { 0x1DC2, 57834 }, + { 0x1DC3, 58302 }, + { 0x1DC4, 58317 }, + { 0x1DC5, 58315 }, + { 0x1DC6, 58321 }, + { 0x1DC7, 58311 }, + { 0x1DC8, 58333 }, + { 0x1DC9, 58331 }, + { 0x1DCA, 57657 }, + { 0x1DCB, 58313 }, + { 0x1DCC, 58319 }, + { 0x1DCD, 57933 }, + { 0x1DCE, 57961 }, + { 0x1DCF, 57977 }, + { 0x1DD0, 57389 }, + { 0x1DD1, 57396 }, + { 0x1DD2, 57399 }, + { 0x1DD3, 57731 }, + { 0x1DD4, 57699 }, + { 0x1DD5, 57704 }, + { 0x1DD6, 57709 }, + { 0x1DD7, 57596 }, + { 0x1DD8, 57725 }, + { 0x1DD9, 57714 }, + { 0x1DDA, 57612 }, + { 0x1DDB, 57739 }, + { 0x1DDC, 57627 }, + { 0x1DDD, 57632 }, + { 0x1DDE, 57745 }, + { 0x1DDF, 57751 }, + { 0x1DE0, 57642 }, + { 0x1DE1, 57757 }, + { 0x1DE2, 57763 }, + { 0x1DE3, 57663 }, + { 0x1DE4, 57669 }, + { 0x1DE5, 57719 }, + { 0x1DE6, 57694 }, + { 0x1DFE, 57476 }, + { 0x1DFF, 57806 }, + { 0x1E00, 18281 }, + { 0x1E01, 14523 }, + { 0x1E02, 18458 }, + { 0x1E03, 14715 }, + { 0x1E04, 18465 }, + { 0x1E05, 14722 }, + { 0x1E06, 18478 }, + { 0x1E07, 14735 }, + { 0x1E08, 18538 }, + { 0x1E09, 14815 }, + { 0x1E0A, 18556 }, + { 0x1E0B, 14833 }, + { 0x1E0C, 18563 }, + { 0x1E0D, 14840 }, + { 0x1E0E, 18576 }, + { 0x1E0F, 14867 }, + { 0x1E10, 18619 }, + { 0x1E11, 14905 }, + { 0x1E12, 18625 }, + { 0x1E13, 14918 }, + { 0x1E14, 18715 }, + { 0x1E15, 15014 }, + { 0x1E16, 18707 }, + { 0x1E17, 15006 }, + { 0x1E18, 18810 }, + { 0x1E19, 15116 }, + { 0x1E1A, 18687 }, + { 0x1E1B, 14986 }, + { 0x1E1C, 18741 }, + { 0x1E1D, 15040 }, + { 0x1E1E, 18821 }, + { 0x1E1F, 15127 }, + { 0x1E20, 18869 }, + { 0x1E21, 15189 }, + { 0x1E22, 18897 }, + { 0x1E23, 15224 }, + { 0x1E24, 18904 }, + { 0x1E25, 15231 }, + { 0x1E26, 18942 }, + { 0x1E27, 15282 }, + { 0x1E28, 18930 }, + { 0x1E29, 15270 }, + { 0x1E2A, 18911 }, + { 0x1E2B, 15251 }, + { 0x1E2C, 19009 }, + { 0x1E2D, 15342 }, + { 0x1E2E, 19054 }, + { 0x1E2F, 15387 }, + { 0x1E30, 19108 }, + { 0x1E31, 15460 }, + { 0x1E32, 19088 }, + { 0x1E33, 15440 }, + { 0x1E34, 19101 }, + { 0x1E35, 15453 }, + { 0x1E36, 19164 }, + { 0x1E37, 15523 }, + { 0x1E38, 19171 }, + { 0x1E39, 15530 }, + { 0x1E3A, 19187 }, + { 0x1E3B, 15558 }, + { 0x1E3C, 19247 }, + { 0x1E3D, 15624 }, + { 0x1E3E, 19278 }, + { 0x1E3F, 15655 }, + { 0x1E40, 19258 }, + { 0x1E41, 15635 }, + { 0x1E42, 19265 }, + { 0x1E43, 15642 }, + { 0x1E44, 19288 }, + { 0x1E45, 15679 }, + { 0x1E46, 19295 }, + { 0x1E47, 15686 }, + { 0x1E48, 19309 }, + { 0x1E49, 15706 }, + { 0x1E4A, 19362 }, + { 0x1E4B, 15772 }, + { 0x1E4C, 19495 }, + { 0x1E4D, 15920 }, + { 0x1E4E, 19511 }, + { 0x1E4F, 15936 }, + { 0x1E50, 19547 }, + { 0x1E51, 15972 }, + { 0x1E52, 19539 }, + { 0x1E53, 15964 }, + { 0x1E54, 19676 }, + { 0x1E55, 16094 }, + { 0x1E56, 19663 }, + { 0x1E57, 16081 }, + { 0x1E58, 19732 }, + { 0x1E59, 16177 }, + { 0x1E5A, 19739 }, + { 0x1E5B, 16184 }, + { 0x1E5C, 19746 }, + { 0x1E5D, 16191 }, + { 0x1E5E, 19755 }, + { 0x1E5F, 16200 }, + { 0x1E60, 19815 }, + { 0x1E61, 16296 }, + { 0x1E62, 19822 }, + { 0x1E63, 16303 }, + { 0x1E64, 19845 }, + { 0x1E65, 16332 }, + { 0x1E66, 19860 }, + { 0x1E67, 16347 }, + { 0x1E68, 19829 }, + { 0x1E69, 16310 }, + { 0x1E6A, 19892 }, + { 0x1E6B, 16400 }, + { 0x1E6C, 19899 }, + { 0x1E6D, 16407 }, + { 0x1E6E, 19912 }, + { 0x1E6F, 16426 }, + { 0x1E70, 19958 }, + { 0x1E71, 16492 }, + { 0x1E72, 20167 }, + { 0x1E73, 16701 }, + { 0x1E74, 20081 }, + { 0x1E75, 16615 }, + { 0x1E76, 20180 }, + { 0x1E77, 16721 }, + { 0x1E78, 20073 }, + { 0x1E79, 16607 }, + { 0x1E7A, 20108 }, + { 0x1E7B, 16642 }, + { 0x1E7C, 20204 }, + { 0x1E7D, 16758 }, + { 0x1E7E, 20191 }, + { 0x1E7F, 16732 }, + { 0x1E80, 20247 }, + { 0x1E81, 16815 }, + { 0x1E82, 20241 }, + { 0x1E83, 16809 }, + { 0x1E84, 20253 }, + { 0x1E85, 16821 }, + { 0x1E86, 20221 }, + { 0x1E87, 16782 }, + { 0x1E88, 20228 }, + { 0x1E89, 16789 }, + { 0x1E8A, 20269 }, + { 0x1E8B, 16837 }, + { 0x1E8C, 20276 }, + { 0x1E8D, 16851 }, + { 0x1E8E, 20286 }, + { 0x1E8F, 16861 }, + { 0x1E90, 20416 }, + { 0x1E91, 17032 }, + { 0x1E92, 20372 }, + { 0x1E93, 16954 }, + { 0x1E94, 20385 }, + { 0x1E95, 16973 }, + { 0x1E96, 15244 }, + { 0x1E97, 16479 }, + { 0x1E98, 16802 }, + { 0x1E99, 16894 }, + { 0x1E9A, 14596 }, + { 0x1E9B, 17346 }, + { 0x1E9C, 17362 }, + { 0x1E9D, 17354 }, + { 0x1E9E, 20613 }, + { 0x1E9F, 17440 }, + { 0x1EA0, 18251 }, + { 0x1EA1, 14493 }, + { 0x1EA2, 18258 }, + { 0x1EA3, 14500 }, + { 0x1EA4, 18430 }, + { 0x1EA5, 14687 }, + { 0x1EA6, 18438 }, + { 0x1EA7, 14695 }, + { 0x1EA8, 18421 }, + { 0x1EA9, 14678 }, + { 0x1EAA, 18446 }, + { 0x1EAB, 14703 }, + { 0x1EAC, 18412 }, + { 0x1EAD, 14669 }, + { 0x1EAE, 18318 }, + { 0x1EAF, 14560 }, + { 0x1EB0, 18326 }, + { 0x1EB1, 14568 }, + { 0x1EB2, 18309 }, + { 0x1EB3, 14551 }, + { 0x1EB4, 18334 }, + { 0x1EB5, 14576 }, + { 0x1EB6, 18300 }, + { 0x1EB7, 14542 }, + { 0x1EB8, 18643 }, + { 0x1EB9, 14936 }, + { 0x1EBA, 18650 }, + { 0x1EBB, 14943 }, + { 0x1EBC, 18681 }, + { 0x1EBD, 14980 }, + { 0x1EBE, 18786 }, + { 0x1EBF, 15092 }, + { 0x1EC0, 18794 }, + { 0x1EC1, 15100 }, + { 0x1EC2, 18777 }, + { 0x1EC3, 15083 }, + { 0x1EC4, 18802 }, + { 0x1EC5, 15108 }, + { 0x1EC6, 18768 }, + { 0x1EC7, 15074 }, + { 0x1EC8, 18972 }, + { 0x1EC9, 15305 }, + { 0x1ECA, 18965 }, + { 0x1ECB, 15298 }, + { 0x1ECC, 19389 }, + { 0x1ECD, 15806 }, + { 0x1ECE, 19396 }, + { 0x1ECF, 15821 }, + { 0x1ED0, 19635 }, + { 0x1ED1, 16053 }, + { 0x1ED2, 19643 }, + { 0x1ED3, 16061 }, + { 0x1ED4, 19626 }, + { 0x1ED5, 16044 }, + { 0x1ED6, 19651 }, + { 0x1ED7, 16069 }, + { 0x1ED8, 19617 }, + { 0x1ED9, 16035 }, + { 0x1EDA, 19427 }, + { 0x1EDB, 15852 }, + { 0x1EDC, 19435 }, + { 0x1EDD, 15860 }, + { 0x1EDE, 19418 }, + { 0x1EDF, 15843 }, + { 0x1EE0, 19443 }, + { 0x1EE1, 15868 }, + { 0x1EE2, 19409 }, + { 0x1EE3, 15834 }, + { 0x1EE4, 19974 }, + { 0x1EE5, 16508 }, + { 0x1EE6, 19981 }, + { 0x1EE7, 16515 }, + { 0x1EE8, 20012 }, + { 0x1EE9, 16546 }, + { 0x1EEA, 20020 }, + { 0x1EEB, 16554 }, + { 0x1EEC, 20003 }, + { 0x1EED, 16537 }, + { 0x1EEE, 20028 }, + { 0x1EEF, 16562 }, + { 0x1EF0, 19994 }, + { 0x1EF1, 16528 }, + { 0x1EF2, 20325 }, + { 0x1EF3, 16907 }, + { 0x1EF4, 20293 }, + { 0x1EF5, 16868 }, + { 0x1EF6, 20306 }, + { 0x1EF7, 16881 }, + { 0x1EF8, 20331 }, + { 0x1EF9, 16913 }, + { 0x1EFA, 20759 }, + { 0x1EFB, 17868 }, + { 0x1EFC, 20754 }, + { 0x1EFD, 17863 }, + { 0x1EFE, 20313 }, + { 0x1EFF, 16888 }, + { 0x1F00, 11230 }, + { 0x1F01, 11162 }, + { 0x1F02, 11254 }, + { 0x1F03, 11186 }, + { 0x1F04, 11236 }, + { 0x1F05, 11168 }, + { 0x1F06, 11272 }, + { 0x1F07, 11204 }, + { 0x1F08, 12506 }, + { 0x1F09, 12438 }, + { 0x1F0A, 12530 }, + { 0x1F0B, 12462 }, + { 0x1F0C, 12512 }, + { 0x1F0D, 12444 }, + { 0x1F0E, 12548 }, + { 0x1F0F, 12480 }, + { 0x1F10, 11631 }, + { 0x1F11, 11609 }, + { 0x1F12, 11645 }, + { 0x1F13, 11623 }, + { 0x1F14, 11637 }, + { 0x1F15, 11615 }, + { 0x1F18, 12829 }, + { 0x1F19, 12807 }, + { 0x1F1A, 12843 }, + { 0x1F1B, 12821 }, + { 0x1F1C, 12835 }, + { 0x1F1D, 12813 }, + { 0x1F20, 10850 }, + { 0x1F21, 10782 }, + { 0x1F22, 10874 }, + { 0x1F23, 10806 }, + { 0x1F24, 10856 }, + { 0x1F25, 10788 }, + { 0x1F26, 10892 }, + { 0x1F27, 10824 }, + { 0x1F28, 12200 }, + { 0x1F29, 12132 }, + { 0x1F2A, 12224 }, + { 0x1F2B, 12156 }, + { 0x1F2C, 12206 }, + { 0x1F2D, 12138 }, + { 0x1F2E, 12242 }, + { 0x1F2F, 12174 }, + { 0x1F30, 11042 }, + { 0x1F31, 11012 }, + { 0x1F32, 11056 }, + { 0x1F33, 11026 }, + { 0x1F34, 11048 }, + { 0x1F35, 11018 }, + { 0x1F36, 11064 }, + { 0x1F37, 11034 }, + { 0x1F38, 12364 }, + { 0x1F39, 12334 }, + { 0x1F3A, 12378 }, + { 0x1F3B, 12348 }, + { 0x1F3C, 12370 }, + { 0x1F3D, 12340 }, + { 0x1F3E, 12386 }, + { 0x1F3F, 12356 }, + { 0x1F40, 11697 }, + { 0x1F41, 11675 }, + { 0x1F42, 11711 }, + { 0x1F43, 11689 }, + { 0x1F44, 11703 }, + { 0x1F45, 11681 }, + { 0x1F48, 12895 }, + { 0x1F49, 12873 }, + { 0x1F4A, 12909 }, + { 0x1F4B, 12887 }, + { 0x1F4C, 12901 }, + { 0x1F4D, 12879 }, + { 0x1F50, 11771 }, + { 0x1F51, 11741 }, + { 0x1F52, 11785 }, + { 0x1F53, 11755 }, + { 0x1F54, 11777 }, + { 0x1F55, 11747 }, + { 0x1F56, 11793 }, + { 0x1F57, 11763 }, + { 0x1F59, 12939 }, + { 0x1F5B, 12953 }, + { 0x1F5D, 12945 }, + { 0x1F5F, 12961 }, + { 0x1F60, 11461 }, + { 0x1F61, 11393 }, + { 0x1F62, 11485 }, + { 0x1F63, 11417 }, + { 0x1F64, 11467 }, + { 0x1F65, 11399 }, + { 0x1F66, 11503 }, + { 0x1F67, 11435 }, + { 0x1F68, 12698 }, + { 0x1F69, 12630 }, + { 0x1F6A, 12722 }, + { 0x1F6B, 12654 }, + { 0x1F6C, 12704 }, + { 0x1F6D, 12636 }, + { 0x1F6E, 12740 }, + { 0x1F6F, 12672 }, + { 0x1F70, 11304 }, + { 0x1F71, 11148 }, + { 0x1F72, 11659 }, + { 0x1F73, 11603 }, + { 0x1F74, 10924 }, + { 0x1F75, 10768 }, + { 0x1F76, 11078 }, + { 0x1F77, 11006 }, + { 0x1F78, 11725 }, + { 0x1F79, 11669 }, + { 0x1F7A, 11807 }, + { 0x1F7B, 11735 }, + { 0x1F7C, 11535 }, + { 0x1F7D, 11379 }, + { 0x1F80, 11290 }, + { 0x1F81, 11222 }, + { 0x1F82, 11262 }, + { 0x1F83, 11194 }, + { 0x1F84, 11244 }, + { 0x1F85, 11176 }, + { 0x1F86, 11280 }, + { 0x1F87, 11212 }, + { 0x1F88, 12566 }, + { 0x1F89, 12498 }, + { 0x1F8A, 12538 }, + { 0x1F8B, 12470 }, + { 0x1F8C, 12520 }, + { 0x1F8D, 12452 }, + { 0x1F8E, 12556 }, + { 0x1F8F, 12488 }, + { 0x1F90, 10910 }, + { 0x1F91, 10842 }, + { 0x1F92, 10882 }, + { 0x1F93, 10814 }, + { 0x1F94, 10864 }, + { 0x1F95, 10796 }, + { 0x1F96, 10900 }, + { 0x1F97, 10832 }, + { 0x1F98, 12260 }, + { 0x1F99, 12192 }, + { 0x1F9A, 12232 }, + { 0x1F9B, 12164 }, + { 0x1F9C, 12214 }, + { 0x1F9D, 12146 }, + { 0x1F9E, 12250 }, + { 0x1F9F, 12182 }, + { 0x1FA0, 11521 }, + { 0x1FA1, 11453 }, + { 0x1FA2, 11493 }, + { 0x1FA3, 11425 }, + { 0x1FA4, 11475 }, + { 0x1FA5, 11407 }, + { 0x1FA6, 11511 }, + { 0x1FA7, 11443 }, + { 0x1FA8, 12758 }, + { 0x1FA9, 12690 }, + { 0x1FAA, 12730 }, + { 0x1FAB, 12662 }, + { 0x1FAC, 12712 }, + { 0x1FAD, 12644 }, + { 0x1FAE, 12748 }, + { 0x1FAF, 12680 }, + { 0x1FB0, 11324 }, + { 0x1FB1, 11318 }, + { 0x1FB2, 11310 }, + { 0x1FB3, 11344 }, + { 0x1FB4, 11154 }, + { 0x1FB6, 11330 }, + { 0x1FB7, 11336 }, + { 0x1FB8, 12592 }, + { 0x1FB9, 12586 }, + { 0x1FBA, 12580 }, + { 0x1FBB, 12432 }, + { 0x1FBC, 12598 }, + { 0x1FBD, 13025 }, + { 0x1FBE, 13524 }, + { 0x1FBF, 10724 }, + { 0x1FC0, 13372 }, + { 0x1FC1, 13079 }, + { 0x1FC2, 10930 }, + { 0x1FC3, 10952 }, + { 0x1FC4, 10774 }, + { 0x1FC6, 10938 }, + { 0x1FC7, 10944 }, + { 0x1FC8, 12857 }, + { 0x1FC9, 12801 }, + { 0x1FCA, 12274 }, + { 0x1FCB, 12126 }, + { 0x1FCC, 12280 }, + { 0x1FCD, 10730 }, + { 0x1FCE, 10726 }, + { 0x1FCF, 10734 }, + { 0x1FD0, 11090 }, + { 0x1FD1, 11084 }, + { 0x1FD2, 11118 }, + { 0x1FD3, 11102 }, + { 0x1FD6, 11134 }, + { 0x1FD7, 11126 }, + { 0x1FD8, 12412 }, + { 0x1FD9, 12406 }, + { 0x1FDA, 12400 }, + { 0x1FDB, 12328 }, + { 0x1FDD, 10706 }, + { 0x1FDE, 10702 }, + { 0x1FDF, 10710 }, + { 0x1FE0, 11819 }, + { 0x1FE1, 11813 }, + { 0x1FE2, 11847 }, + { 0x1FE3, 11831 }, + { 0x1FE4, 10976 }, + { 0x1FE5, 10970 }, + { 0x1FE6, 11863 }, + { 0x1FE7, 11855 }, + { 0x1FE8, 12987 }, + { 0x1FE9, 12981 }, + { 0x1FEA, 12975 }, + { 0x1FEB, 12933 }, + { 0x1FEC, 12298 }, + { 0x1FED, 13075 }, + { 0x1FEE, 13071 }, + { 0x1FEF, 11900 }, + { 0x1FF2, 11541 }, + { 0x1FF3, 11563 }, + { 0x1FF4, 11385 }, + { 0x1FF6, 11549 }, + { 0x1FF7, 11555 }, + { 0x1FF8, 12923 }, + { 0x1FF9, 12867 }, + { 0x1FFA, 12772 }, + { 0x1FFB, 12624 }, + { 0x1FFC, 12778 }, + { 0x1FFD, 10692 }, + { 0x1FFE, 10700 }, + { 0x2000, 77 }, + { 0x2001, 71 }, + { 0x2002, 79 }, + { 0x2003, 73 }, + { 0x2004, 74478 }, + { 0x2005, 68661 }, + { 0x2006, 68597 }, + { 0x2007, 31771 }, + { 0x2008, 69272 }, + { 0x2009, 10051 }, + { 0x200A, 9123 }, + { 0x200B, 10089 }, + { 0x200C, 10099 }, + { 0x200D, 10092 }, + { 0x200E, 74617 }, + { 0x200F, 75041 }, + { 0x2010, 33424 }, + { 0x2011, 74240 }, + { 0x2012, 31769 }, + { 0x2013, 75 }, + { 0x2014, 69 }, + { 0x2015, 67636 }, + { 0x2016, 31692 }, + { 0x2017, 31548 }, + { 0x2018, 9381 }, + { 0x2019, 21908 }, + { 0x201A, 35854 }, + { 0x201B, 35868 }, + { 0x201C, 9365 }, + { 0x201D, 21892 }, + { 0x201E, 31570 }, + { 0x201F, 31700 }, + { 0x2020, 31169 }, + { 0x2021, 31587 }, + { 0x2022, 30312 }, + { 0x2023, 68599 }, + { 0x2024, 7161 }, + { 0x2025, 7766 }, + { 0x2026, 67661 }, + { 0x2027, 68663 }, + { 0x2028, 9483 }, + { 0x2029, 65751 }, + { 0x202A, 74621 }, + { 0x202B, 75045 }, + { 0x202C, 7173 }, + { 0x202D, 74619 }, + { 0x202E, 75043 }, + { 0x202F, 35576 }, + { 0x2030, 7170 }, + { 0x2031, 7164 }, + { 0x2032, 21742 }, + { 0x2033, 31574 }, + { 0x2034, 37619 }, + { 0x2035, 55468 }, + { 0x2036, 55475 }, + { 0x2037, 55491 }, + { 0x2038, 10441 }, + { 0x2039, 35858 }, + { 0x203A, 35863 }, + { 0x203B, 65808 }, + { 0x203C, 31695 }, + { 0x203D, 69263 }, + { 0x203E, 54945 }, + { 0x203F, 56009 }, + { 0x2040, 57360 }, + { 0x2041, 10442 }, + { 0x2042, 45084 }, + { 0x2043, 33428 }, + { 0x2044, 51779 }, + { 0x2045, 9404 }, + { 0x2046, 21931 }, + { 0x2047, 31668 }, + { 0x2048, 55448 }, + { 0x2049, 68658 }, + { 0x204A, 55895 }, + { 0x204B, 55494 }, + { 0x204C, 10314 }, + { 0x204D, 10331 }, + { 0x204E, 6038 }, + { 0x204F, 55505 }, + { 0x2050, 10452 }, + { 0x2051, 7789 }, + { 0x2052, 66839 }, + { 0x2053, 22751 }, + { 0x2054, 53355 }, + { 0x2055, 31779 }, + { 0x2056, 22989 }, + { 0x2057, 65761 }, + { 0x2058, 9100 }, + { 0x2059, 9094 }, + { 0x205A, 7769 }, + { 0x205B, 9097 }, + { 0x205C, 31529 }, + { 0x205D, 55910 }, + { 0x205E, 56031 }, + { 0x205F, 35557 }, + { 0x2060, 10087 }, + { 0x2061, 51784 }, + { 0x2062, 64310 }, + { 0x2063, 64312 }, + { 0x2064, 64308 }, + { 0x206A, 40633 }, + { 0x206B, 44713 }, + { 0x206C, 40629 }, + { 0x206D, 44709 }, + { 0x206E, 54880 }, + { 0x206F, 42828 }, + { 0x2070, 69298 }, + { 0x2071, 69302 }, + { 0x2074, 69288 }, + { 0x2075, 69286 }, + { 0x2076, 69282 }, + { 0x2077, 69317 }, + { 0x2078, 69300 }, + { 0x2079, 69293 }, + { 0x207A, 69295 }, + { 0x207B, 69312 }, + { 0x207C, 69321 }, + { 0x207D, 69290 }, + { 0x207E, 69314 }, + { 0x207F, 69307 }, + { 0x2080, 65843 }, + { 0x2081, 65825 }, + { 0x2082, 65829 }, + { 0x2083, 65854 }, + { 0x2084, 65833 }, + { 0x2085, 65831 }, + { 0x2086, 65827 }, + { 0x2087, 65852 }, + { 0x2088, 65845 }, + { 0x2089, 65838 }, + { 0x208A, 65840 }, + { 0x208B, 65847 }, + { 0x208C, 65856 }, + { 0x208D, 65835 }, + { 0x208E, 65849 }, + { 0x2090, 20782 }, + { 0x2091, 20787 }, + { 0x2092, 20802 }, + { 0x2093, 20822 }, + { 0x2094, 20827 }, + { 0x20A0, 74597 }, + { 0x20A1, 10456 }, + { 0x20A2, 48519 }, + { 0x20A3, 31787 }, + { 0x20A4, 9505 }, + { 0x20A5, 9596 }, + { 0x20A6, 21269 }, + { 0x20A7, 35651 }, + { 0x20A8, 22442 }, + { 0x20A9, 8709 }, + { 0x20AA, 6507 }, + { 0x20AB, 9068 }, + { 0x20AC, 9089 }, + { 0x20AD, 5797 }, + { 0x20AE, 37669 }, + { 0x20AF, 40498 }, + { 0x20B0, 31791 }, + { 0x20B1, 9631 }, + { 0x20B2, 40560 }, + { 0x20B3, 37779 }, + { 0x20B4, 40627 }, + { 0x20B5, 8727 }, + { 0x20D0, 57472 }, + { 0x20D1, 57795 }, + { 0x20D2, 57497 }, + { 0x20D3, 57829 }, + { 0x20D4, 58327 }, + { 0x20D5, 58236 }, + { 0x20D6, 57454 }, + { 0x20D7, 57787 }, + { 0x20D8, 57512 }, + { 0x20D9, 58232 }, + { 0x20DA, 58323 }, + { 0x20DB, 57837 }, + { 0x20DC, 57423 }, + { 0x20DD, 58245 }, + { 0x20DE, 58258 }, + { 0x20DF, 58266 }, + { 0x20E0, 58248 }, + { 0x20E1, 57462 }, + { 0x20E2, 58255 }, + { 0x20E3, 58252 }, + { 0x20E4, 58261 }, + { 0x20E5, 57987 }, + { 0x20E6, 57928 }, + { 0x20E7, 57980 }, + { 0x20E8, 57967 }, + { 0x20E9, 57515 }, + { 0x20EA, 58269 }, + { 0x20EB, 57484 }, + { 0x20EC, 58296 }, + { 0x20ED, 58273 }, + { 0x20EE, 57458 }, + { 0x20EF, 57791 }, + { 0x20F0, 57998 }, + { 0x2100, 37774 }, + { 0x2101, 56104 }, + { 0x2102, 74558 }, + { 0x2103, 31181 }, + { 0x2104, 30465 }, + { 0x2105, 8725 }, + { 0x2106, 8723 }, + { 0x2107, 10628 }, + { 0x2108, 43021 }, + { 0x2109, 31183 }, + { 0x210A, 35815 }, + { 0x210B, 35833 }, + { 0x210C, 69390 }, + { 0x210D, 74561 }, + { 0x210E, 35654 }, + { 0x210F, 35656 }, + { 0x2110, 35836 }, + { 0x2111, 69393 }, + { 0x2112, 35839 }, + { 0x2113, 35818 }, + { 0x2114, 0 }, + { 0x2115, 74564 }, + { 0x2116, 35635 }, + { 0x2117, 22671 }, + { 0x2118, 35845 }, + { 0x2119, 74567 }, + { 0x211A, 74570 }, + { 0x211B, 35848 }, + { 0x211C, 69396 }, + { 0x211D, 74573 }, + { 0x211E, 74242 }, + { 0x211F, 55455 }, + { 0x2120, 43025 }, + { 0x2121, 66040 }, + { 0x2122, 23055 }, + { 0x2123, 56010 }, + { 0x2124, 74576 }, + { 0x2125, 21731 }, + { 0x2126, 6813 }, + { 0x2127, 53346 }, + { 0x2128, 69399 }, + { 0x2129, 37676 }, + { 0x212A, 34094 }, + { 0x212B, 44717 }, + { 0x212C, 35824 }, + { 0x212D, 69387 }, + { 0x212E, 63380 }, + { 0x212F, 35812 }, + { 0x2130, 35827 }, + { 0x2131, 35830 }, + { 0x2132, 37684 }, + { 0x2133, 35842 }, + { 0x2134, 35821 }, + { 0x2135, 8716 }, + { 0x2136, 4380 }, + { 0x2137, 10636 }, + { 0x2138, 10477 }, + { 0x2139, 69246 }, + { 0x213A, 43017 }, + { 0x213B, 63383 }, + { 0x213C, 74532 }, + { 0x213D, 74535 }, + { 0x213E, 74582 }, + { 0x213F, 74579 }, + { 0x2140, 74529 }, + { 0x2141, 37689 }, + { 0x2142, 37693 }, + { 0x2143, 55507 }, + { 0x2144, 37697 }, + { 0x2145, 74554 }, + { 0x2146, 74538 }, + { 0x2147, 74542 }, + { 0x2148, 74546 }, + { 0x2149, 74550 }, + { 0x214A, 55384 }, + { 0x214B, 37687 }, + { 0x214C, 7168 }, + { 0x214D, 69338 }, + { 0x214E, 37681 }, + { 0x214F, 36848 }, + { 0x2153, 37724 }, + { 0x2154, 37740 }, + { 0x2155, 37716 }, + { 0x2156, 37736 }, + { 0x2157, 37760 }, + { 0x2158, 37752 }, + { 0x2159, 37720 }, + { 0x215A, 37744 }, + { 0x215B, 37728 }, + { 0x215C, 37764 }, + { 0x215D, 37748 }, + { 0x215E, 37756 }, + { 0x215F, 51781 }, + { 0x2160, 22020 }, + { 0x2161, 22057 }, + { 0x2162, 22095 }, + { 0x2163, 22071 }, + { 0x2164, 22060 }, + { 0x2165, 22042 }, + { 0x2166, 22092 }, + { 0x2167, 22077 }, + { 0x2168, 22074 }, + { 0x2169, 22050 }, + { 0x216A, 22098 }, + { 0x216B, 22101 }, + { 0x216C, 22080 }, + { 0x216D, 22023 }, + { 0x216E, 22063 }, + { 0x216F, 22032 }, + { 0x2170, 22521 }, + { 0x2171, 22543 }, + { 0x2172, 22576 }, + { 0x2173, 22556 }, + { 0x2174, 22547 }, + { 0x2175, 22535 }, + { 0x2176, 22572 }, + { 0x2177, 22564 }, + { 0x2178, 22560 }, + { 0x2179, 22539 }, + { 0x217A, 22580 }, + { 0x217B, 22584 }, + { 0x217C, 22568 }, + { 0x217D, 22525 }, + { 0x217E, 22551 }, + { 0x217F, 22530 }, + { 0x2180, 22036 }, + { 0x2181, 22067 }, + { 0x2182, 22053 }, + { 0x2183, 22104 }, + { 0x2184, 17753 }, + { 0x2185, 22045 }, + { 0x2186, 22083 }, + { 0x2187, 22088 }, + { 0x2188, 22027 }, + { 0x2190, 64325 }, + { 0x2191, 44542 }, + { 0x2192, 67992 }, + { 0x2193, 63251 }, + { 0x2194, 9258 }, + { 0x2195, 303 }, + { 0x2196, 21324 }, + { 0x2197, 21277 }, + { 0x2198, 22674 }, + { 0x2199, 22713 }, + { 0x219A, 64414 }, + { 0x219B, 68077 }, + { 0x219C, 64322 }, + { 0x219D, 67989 }, + { 0x219E, 64318 }, + { 0x219F, 44538 }, + { 0x21A0, 67985 }, + { 0x21A1, 63247 }, + { 0x21A2, 64384 }, + { 0x21A3, 68042 }, + { 0x21A4, 64345 }, + { 0x21A5, 44548 }, + { 0x21A6, 68003 }, + { 0x21A7, 63257 }, + { 0x21A8, 306 }, + { 0x21A9, 64371 }, + { 0x21AA, 68029 }, + { 0x21AB, 64375 }, + { 0x21AC, 68033 }, + { 0x21AD, 9254 }, + { 0x21AE, 9268 }, + { 0x21AF, 63312 }, + { 0x21B0, 44552 }, + { 0x21B1, 44557 }, + { 0x21B2, 63261 }, + { 0x21B3, 63266 }, + { 0x21B4, 68061 }, + { 0x21B5, 63271 }, + { 0x21B6, 74484 }, + { 0x21B7, 57362 }, + { 0x21B8, 21327 }, + { 0x21B9, 64331 }, + { 0x21BA, 74488 }, + { 0x21BB, 57366 }, + { 0x21BC, 64592 }, + { 0x21BD, 64597 }, + { 0x21BE, 44689 }, + { 0x21BF, 44684 }, + { 0x21C0, 68257 }, + { 0x21C1, 68262 }, + { 0x21C2, 63370 }, + { 0x21C3, 63365 }, + { 0x21C4, 68014 }, + { 0x21C5, 44572 }, + { 0x21C6, 64356 }, + { 0x21C7, 64500 }, + { 0x21C8, 44628 }, + { 0x21C9, 68165 }, + { 0x21CA, 63306 }, + { 0x21CB, 64510 }, + { 0x21CC, 68175 }, + { 0x21CD, 64486 }, + { 0x21CE, 9297 }, + { 0x21CF, 68151 }, + { 0x21D0, 64478 }, + { 0x21D1, 44625 }, + { 0x21D2, 68143 }, + { 0x21D3, 63303 }, + { 0x21D4, 9293 }, + { 0x21D5, 319 }, + { 0x21D6, 21365 }, + { 0x21D7, 21314 }, + { 0x21D8, 22709 }, + { 0x21D9, 22736 }, + { 0x21DA, 64507 }, + { 0x21DB, 68172 }, + { 0x21DC, 64602 }, + { 0x21DD, 68267 }, + { 0x21DE, 44562 }, + { 0x21DF, 63276 }, + { 0x21E0, 64471 }, + { 0x21E1, 44622 }, + { 0x21E2, 68136 }, + { 0x21E3, 63300 }, + { 0x21E4, 64327 }, + { 0x21E5, 67994 }, + { 0x21E6, 64468 }, + { 0x21E7, 44581 }, + { 0x21E8, 68128 }, + { 0x21E9, 63295 }, + { 0x21EA, 44605 }, + { 0x21EB, 44584 }, + { 0x21EC, 44597 }, + { 0x21ED, 44589 }, + { 0x21EE, 44610 }, + { 0x21EF, 44614 }, + { 0x21F0, 68131 }, + { 0x21F1, 21333 }, + { 0x21F2, 22677 }, + { 0x21F3, 315 }, + { 0x21F4, 21805 }, + { 0x21F5, 63286 }, + { 0x21F6, 22995 }, + { 0x21F7, 64418 }, + { 0x21F8, 68081 }, + { 0x21F9, 9273 }, + { 0x21FA, 64408 }, + { 0x21FB, 68071 }, + { 0x21FC, 9261 }, + { 0x21FD, 64655 }, + { 0x21FE, 68320 }, + { 0x21FF, 9310 }, + { 0x2200, 5791 }, + { 0x2201, 66842 }, + { 0x2202, 42971 }, + { 0x2203, 22987 }, + { 0x2204, 22983 }, + { 0x2205, 10570 }, + { 0x2206, 64305 }, + { 0x2207, 21268 }, + { 0x2208, 40500 }, + { 0x2209, 6719 }, + { 0x220A, 22599 }, + { 0x220B, 48398 }, + { 0x220C, 9033 }, + { 0x220D, 22626 }, + { 0x220E, 5788 }, + { 0x220F, 21260 }, + { 0x2210, 21262 }, + { 0x2211, 21264 }, + { 0x2212, 21178 }, + { 0x2213, 74623 }, + { 0x2214, 5780 }, + { 0x2215, 50310 }, + { 0x2216, 7176 }, + { 0x2217, 45082 }, + { 0x2218, 9706 }, + { 0x2219, 30313 }, + { 0x221A, 36200 }, + { 0x221B, 9013 }, + { 0x221C, 31785 }, + { 0x221D, 74470 }, + { 0x221E, 53300 }, + { 0x221F, 21771 }, + { 0x2220, 10106 }, + { 0x2221, 53732 }, + { 0x2222, 65815 }, + { 0x2223, 40489 }, + { 0x2224, 9023 }, + { 0x2225, 54946 }, + { 0x2226, 6764 }, + { 0x2227, 40959 }, + { 0x2228, 40927 }, + { 0x2229, 69570 }, + { 0x222A, 23058 }, + { 0x222B, 53306 }, + { 0x222C, 31664 }, + { 0x222D, 37633 }, + { 0x222E, 39790 }, + { 0x222F, 43581 }, + { 0x2230, 37710 }, + { 0x2231, 57381 }, + { 0x2232, 57378 }, + { 0x2233, 74500 }, + { 0x2234, 66307 }, + { 0x2235, 37781 }, + { 0x2236, 21746 }, + { 0x2237, 67972 }, + { 0x2238, 5784 }, + { 0x2239, 31766 }, + { 0x223A, 63794 }, + { 0x223B, 67635 }, + { 0x223C, 23021 }, + { 0x223D, 55470 }, + { 0x223E, 53349 }, + { 0x223F, 9708 }, + { 0x2240, 37772 }, + { 0x2241, 6733 }, + { 0x2242, 21204 }, + { 0x2243, 75048 }, + { 0x2244, 6777 }, + { 0x2245, 74516 }, + { 0x2246, 74505 }, + { 0x2247, 42821 }, + { 0x2248, 23692 }, + { 0x2249, 6735 }, + { 0x224A, 23687 }, + { 0x224B, 37621 }, + { 0x224C, 4011 }, + { 0x224D, 67226 }, + { 0x224E, 74602 }, + { 0x224F, 67222 }, + { 0x2250, 66827 }, + { 0x2251, 74599 }, + { 0x2252, 74519 }, + { 0x2253, 13722 }, + { 0x2254, 10458 }, + { 0x2255, 31764 }, + { 0x2256, 9695 }, + { 0x2257, 9701 }, + { 0x2258, 68616 }, + { 0x2259, 63382 }, + { 0x225A, 68654 }, + { 0x225B, 9718 }, + { 0x225C, 10479 }, + { 0x225D, 10596 }, + { 0x225E, 53730 }, + { 0x225F, 67976 }, + { 0x2260, 6730 }, + { 0x2261, 64292 }, + { 0x2262, 6767 }, + { 0x2263, 55525 }, + { 0x2264, 64658 }, + { 0x2265, 69429 }, + { 0x2266, 64722 }, + { 0x2267, 69493 }, + { 0x2268, 64712 }, + { 0x2269, 69483 }, + { 0x226A, 9599 }, + { 0x226B, 9601 }, + { 0x226C, 38099 }, + { 0x226D, 6772 }, + { 0x226E, 6770 }, + { 0x226F, 6775 }, + { 0x2270, 42793 }, + { 0x2271, 42807 }, + { 0x2272, 64692 }, + { 0x2273, 69466 }, + { 0x2274, 42798 }, + { 0x2275, 42816 }, + { 0x2276, 64699 }, + { 0x2277, 69463 }, + { 0x2278, 42803 }, + { 0x2279, 42812 }, + { 0x227A, 55334 }, + { 0x227B, 55528 }, + { 0x227C, 55335 }, + { 0x227D, 55529 }, + { 0x227E, 55339 }, + { 0x227F, 55533 }, + { 0x2280, 9052 }, + { 0x2281, 9060 }, + { 0x2282, 36469 }, + { 0x2283, 55576 }, + { 0x2284, 6711 }, + { 0x2285, 6715 }, + { 0x2286, 36471 }, + { 0x2287, 55578 }, + { 0x2288, 42779 }, + { 0x2289, 42786 }, + { 0x228A, 36484 }, + { 0x228B, 55591 }, + { 0x228C, 54875 }, + { 0x228D, 54878 }, + { 0x228E, 54876 }, + { 0x228F, 36310 }, + { 0x2290, 36425 }, + { 0x2291, 36320 }, + { 0x2292, 36435 }, + { 0x2293, 36092 }, + { 0x2294, 36094 }, + { 0x2295, 38882 }, + { 0x2296, 39182 }, + { 0x2297, 39184 }, + { 0x2298, 39468 }, + { 0x2299, 38871 }, + { 0x229A, 38884 }, + { 0x229B, 39462 }, + { 0x229C, 39194 }, + { 0x229D, 38874 }, + { 0x229E, 43560 }, + { 0x229F, 43562 }, + { 0x22A0, 43567 }, + { 0x22A1, 43553 }, + { 0x22A2, 21769 }, + { 0x22A3, 9202 }, + { 0x22A4, 9073 }, + { 0x22A5, 326 }, + { 0x22A6, 56111 }, + { 0x22A7, 35572 }, + { 0x22A8, 10054 }, + { 0x22A9, 31782 }, + { 0x22AA, 37641 }, + { 0x22AB, 31686 }, + { 0x22AC, 9020 }, + { 0x22AD, 6725 }, + { 0x22AE, 9017 }, + { 0x22AF, 42772 }, + { 0x22B0, 55379 }, + { 0x22B1, 55573 }, + { 0x22B2, 35580 }, + { 0x22B3, 48401 }, + { 0x22B4, 35583 }, + { 0x22B5, 48405 }, + { 0x22B6, 54929 }, + { 0x22B7, 13720 }, + { 0x22B8, 54874 }, + { 0x22B9, 64288 }, + { 0x22BA, 69248 }, + { 0x22BB, 8711 }, + { 0x22BC, 9603 }, + { 0x22BD, 6710 }, + { 0x22BE, 21773 }, + { 0x22BF, 21972 }, + { 0x22C0, 21257 }, + { 0x22C1, 21254 }, + { 0x22C2, 21266 }, + { 0x22C3, 21218 }, + { 0x22C4, 40327 }, + { 0x22C5, 5786 }, + { 0x22C6, 9720 }, + { 0x22C7, 50312 }, + { 0x22C8, 30294 }, + { 0x22C9, 9372 }, + { 0x22CA, 21899 }, + { 0x22CB, 9461 }, + { 0x22CC, 21988 }, + { 0x22CD, 55472 }, + { 0x22CE, 10471 }, + { 0x22CF, 10474 }, + { 0x22D0, 31610 }, + { 0x22D1, 31673 }, + { 0x22D2, 31698 }, + { 0x22D3, 31585 }, + { 0x22D4, 65756 }, + { 0x22D5, 10616 }, + { 0x22D6, 64728 }, + { 0x22D7, 69499 }, + { 0x22D8, 10057 }, + { 0x22D9, 10060 }, + { 0x22DA, 64775 }, + { 0x22DB, 69546 }, + { 0x22DC, 10608 }, + { 0x22DD, 10612 }, + { 0x22DE, 10600 }, + { 0x22DF, 10604 }, + { 0x22E0, 9055 }, + { 0x22E1, 9063 }, + { 0x22E2, 6750 }, + { 0x22E3, 6757 }, + { 0x22E4, 36313 }, + { 0x22E5, 36428 }, + { 0x22E6, 64717 }, + { 0x22E7, 69488 }, + { 0x22E8, 55343 }, + { 0x22E9, 55537 }, + { 0x22EA, 6739 }, + { 0x22EB, 9038 }, + { 0x22EC, 6743 }, + { 0x22ED, 9044 }, + { 0x22EE, 56096 }, + { 0x22EF, 41192 }, + { 0x22F0, 337 }, + { 0x22F1, 9080 }, + { 0x22F2, 40513 }, + { 0x22F3, 40527 }, + { 0x22F4, 22607 }, + { 0x22F5, 40502 }, + { 0x22F6, 40519 }, + { 0x22F7, 22602 }, + { 0x22F8, 40523 }, + { 0x22F9, 40507 }, + { 0x22FA, 48412 }, + { 0x22FB, 48420 }, + { 0x22FC, 22634 }, + { 0x22FD, 48417 }, + { 0x22FE, 22630 }, + { 0x22FF, 12 }, + { 0x2300, 50306 }, + { 0x2301, 50318 }, + { 0x2302, 13719 }, + { 0x2303, 341 }, + { 0x2304, 9084 }, + { 0x2305, 67971 }, + { 0x2306, 69271 }, + { 0x2307, 10080 }, + { 0x2308, 9431 }, + { 0x2309, 21958 }, + { 0x230A, 9249 }, + { 0x230B, 21842 }, + { 0x230C, 30268 }, + { 0x230D, 30255 }, + { 0x230E, 7747 }, + { 0x230F, 7734 }, + { 0x2310, 55456 }, + { 0x2311, 36399 }, + { 0x2312, 4379 }, + { 0x2313, 43024 }, + { 0x2314, 35851 }, + { 0x2315, 66045 }, + { 0x2316, 55332 }, + { 0x2317, 56102 }, + { 0x2318, 21735 }, + { 0x2319, 37671 }, + { 0x231A, 23154 }, + { 0x231B, 64291 }, + { 0x231C, 7741 }, + { 0x231D, 7754 }, + { 0x231E, 30262 }, + { 0x231F, 30275 }, + { 0x2320, 7731 }, + { 0x2321, 30252 }, + { 0x2322, 10635 }, + { 0x2323, 22670 }, + { 0x2324, 343 }, + { 0x2325, 35641 }, + { 0x2326, 10624 }, + { 0x2327, 7 }, + { 0x2328, 53725 }, + { 0x2329, 74605 }, + { 0x232A, 75087 }, + { 0x232B, 10620 }, + { 0x232C, 38093 }, + { 0x232D, 69402 }, + { 0x232E, 4014 }, + { 0x232F, 55656 }, + { 0x2330, 23053 }, + { 0x2331, 63245 }, + { 0x2332, 39788 }, + { 0x2333, 22479 }, + { 0x2334, 68618 }, + { 0x2335, 68619 }, + { 0x2336, 4325 }, + { 0x2337, 4329 }, + { 0x2338, 4159 }, + { 0x2339, 4174 }, + { 0x233A, 4179 }, + { 0x233B, 4132 }, + { 0x233C, 4169 }, + { 0x233D, 4305 }, + { 0x233E, 4295 }, + { 0x233F, 4276 }, + { 0x2340, 4349 }, + { 0x2341, 4164 }, + { 0x2342, 4195 }, + { 0x2343, 4212 }, + { 0x2344, 4223 }, + { 0x2345, 4359 }, + { 0x2346, 4369 }, + { 0x2347, 4206 }, + { 0x2348, 4217 }, + { 0x2349, 4315 }, + { 0x234A, 4090 }, + { 0x234B, 4247 }, + { 0x234C, 4143 }, + { 0x234D, 4154 }, + { 0x234E, 4084 }, + { 0x234F, 4344 }, + { 0x2350, 4184 }, + { 0x2351, 4031 }, + { 0x2352, 4049 }, + { 0x2353, 4121 }, + { 0x2354, 4127 }, + { 0x2355, 4025 }, + { 0x2356, 4354 }, + { 0x2357, 4200 }, + { 0x2358, 4271 }, + { 0x2359, 4252 }, + { 0x235A, 4334 }, + { 0x235B, 4064 }, + { 0x235C, 4310 }, + { 0x235D, 4019 }, + { 0x235E, 4266 }, + { 0x235F, 4300 }, + { 0x2360, 4149 }, + { 0x2361, 4037 }, + { 0x2362, 4059 }, + { 0x2363, 4228 }, + { 0x2364, 4069 }, + { 0x2365, 4320 }, + { 0x2366, 4078 }, + { 0x2367, 4111 }, + { 0x2368, 4286 }, + { 0x2369, 4374 }, + { 0x236A, 4242 }, + { 0x236B, 4054 }, + { 0x236C, 4291 }, + { 0x236D, 4281 }, + { 0x236E, 4364 }, + { 0x236F, 4137 }, + { 0x2370, 4190 }, + { 0x2371, 4096 }, + { 0x2372, 4043 }, + { 0x2373, 4102 }, + { 0x2374, 4074 }, + { 0x2375, 4257 }, + { 0x2376, 4237 }, + { 0x2377, 4339 }, + { 0x2378, 4106 }, + { 0x2379, 4261 }, + { 0x237A, 4233 }, + { 0x237B, 6727 }, + { 0x237C, 21777 }, + { 0x237D, 68594 }, + { 0x237E, 8721 }, + { 0x237F, 56078 }, + { 0x2380, 64306 }, + { 0x2381, 66843 }, + { 0x2382, 74526 }, + { 0x2383, 50320 }, + { 0x2384, 68613 }, + { 0x2385, 23322 }, + { 0x2386, 10594 }, + { 0x2387, 68603 }, + { 0x2388, 9125 }, + { 0x2389, 39769 }, + { 0x238A, 39614 }, + { 0x238B, 30307 }, + { 0x238C, 10055 }, + { 0x238D, 67877 }, + { 0x238E, 67663 }, + { 0x238F, 75142 }, + { 0x2390, 75145 }, + { 0x2391, 75150 }, + { 0x2392, 75148 }, + { 0x2393, 31220 }, + { 0x2394, 75137 }, + { 0x2395, 4117 }, + { 0x2396, 39959 }, + { 0x2397, 55382 }, + { 0x2398, 9604 }, + { 0x2399, 21743 }, + { 0x239A, 10449 }, + { 0x239B, 9470 }, + { 0x239C, 9474 }, + { 0x239D, 9466 }, + { 0x239E, 21997 }, + { 0x239F, 22001 }, + { 0x23A0, 21993 }, + { 0x23A1, 9419 }, + { 0x23A2, 9424 }, + { 0x23A3, 9414 }, + { 0x23A4, 21946 }, + { 0x23A5, 21951 }, + { 0x23A6, 21941 }, + { 0x23A7, 9239 }, + { 0x23A8, 9244 }, + { 0x23A9, 9234 }, + { 0x23AA, 10468 }, + { 0x23AB, 21832 }, + { 0x23AC, 21837 }, + { 0x23AD, 21827 }, + { 0x23AE, 53342 }, + { 0x23AF, 67638 }, + { 0x23B0, 23099 }, + { 0x23B1, 23123 }, + { 0x23B2, 65859 }, + { 0x23B3, 65864 }, + { 0x23B4, 7757 }, + { 0x23B5, 30278 }, + { 0x23B6, 30281 }, + { 0x23B7, 42979 }, + { 0x23B8, 9457 }, + { 0x23B9, 21984 }, + { 0x23BA, 67646 }, + { 0x23BB, 67649 }, + { 0x23BC, 67652 }, + { 0x23BD, 67655 }, + { 0x23BE, 63205 }, + { 0x23BF, 63225 }, + { 0x23C0, 63232 }, + { 0x23C1, 63182 }, + { 0x23C2, 63152 }, + { 0x23C3, 63238 }, + { 0x23C4, 63190 }, + { 0x23C5, 63160 }, + { 0x23C6, 63212 }, + { 0x23C7, 63174 }, + { 0x23C8, 63144 }, + { 0x23C9, 63168 }, + { 0x23CA, 63138 }, + { 0x23CB, 63198 }, + { 0x23CC, 63218 }, + { 0x23CD, 36165 }, + { 0x23CE, 35797 }, + { 0x23CF, 10568 }, + { 0x23D0, 56083 }, + { 0x23D1, 53857 }, + { 0x23D2, 53853 }, + { 0x23D3, 53859 }, + { 0x23D4, 53848 }, + { 0x23D5, 53839 }, + { 0x23D6, 53844 }, + { 0x23D7, 53863 }, + { 0x23D8, 53867 }, + { 0x23D9, 53865 }, + { 0x23DA, 10541 }, + { 0x23DB, 9119 }, + { 0x23DC, 7764 }, + { 0x23DD, 30292 }, + { 0x23DE, 7744 }, + { 0x23DF, 30265 }, + { 0x23E0, 7760 }, + { 0x23E1, 30288 }, + { 0x23E2, 23412 }, + { 0x23E3, 38095 }, + { 0x23E4, 74477 }, + { 0x23E5, 51778 }, + { 0x23E6, 67 }, + { 0x23E7, 67224 }, + { 0x2400, 36757 }, + { 0x2401, 36784 }, + { 0x2402, 36779 }, + { 0x2403, 36716 }, + { 0x2404, 36726 }, + { 0x2405, 36827 }, + { 0x2406, 36864 }, + { 0x2407, 36737 }, + { 0x2408, 36845 }, + { 0x2409, 36852 }, + { 0x240A, 36753 }, + { 0x240B, 36841 }, + { 0x240C, 36749 }, + { 0x240D, 36833 }, + { 0x240E, 36772 }, + { 0x240F, 36768 }, + { 0x2410, 36740 }, + { 0x2411, 36800 }, + { 0x2412, 36805 }, + { 0x2413, 36815 }, + { 0x2414, 36810 }, + { 0x2415, 36837 }, + { 0x2416, 36867 }, + { 0x2417, 36731 }, + { 0x2418, 36789 }, + { 0x2419, 36721 }, + { 0x241A, 36856 }, + { 0x241B, 36820 }, + { 0x241C, 36745 }, + { 0x241D, 36764 }, + { 0x241E, 36823 }, + { 0x241F, 36760 }, + { 0x2420, 36776 }, + { 0x2421, 36792 }, + { 0x2422, 10376 }, + { 0x2423, 9606 }, + { 0x2424, 36830 }, + { 0x2425, 36795 }, + { 0x2426, 36859 }, + { 0x2440, 6791 }, + { 0x2441, 6793 }, + { 0x2442, 6789 }, + { 0x2443, 6810 }, + { 0x2444, 6784 }, + { 0x2445, 6781 }, + { 0x2446, 6799 }, + { 0x2447, 6795 }, + { 0x2448, 6787 }, + { 0x2449, 6806 }, + { 0x244A, 6803 }, + { 0x2460, 38887 }, + { 0x2461, 38893 }, + { 0x2462, 38914 }, + { 0x2463, 38899 }, + { 0x2464, 38896 }, + { 0x2465, 38890 }, + { 0x2466, 38911 }, + { 0x2467, 38908 }, + { 0x2468, 38902 }, + { 0x2469, 39306 }, + { 0x246A, 39351 }, + { 0x246B, 39393 }, + { 0x246C, 39450 }, + { 0x246D, 39444 }, + { 0x246E, 39435 }, + { 0x246F, 39438 }, + { 0x2470, 39453 }, + { 0x2471, 39441 }, + { 0x2472, 39447 }, + { 0x2473, 39396 }, + { 0x2474, 74628 }, + { 0x2475, 74634 }, + { 0x2476, 74652 }, + { 0x2477, 74640 }, + { 0x2478, 74637 }, + { 0x2479, 74631 }, + { 0x247A, 74649 }, + { 0x247B, 74646 }, + { 0x247C, 74643 }, + { 0x247D, 74896 }, + { 0x247E, 74899 }, + { 0x247F, 74902 }, + { 0x2480, 74923 }, + { 0x2481, 74917 }, + { 0x2482, 74908 }, + { 0x2483, 74911 }, + { 0x2484, 74926 }, + { 0x2485, 74914 }, + { 0x2486, 74920 }, + { 0x2487, 74905 }, + { 0x2488, 10484 }, + { 0x2489, 10496 }, + { 0x248A, 10534 }, + { 0x248B, 10508 }, + { 0x248C, 10502 }, + { 0x248D, 10490 }, + { 0x248E, 10528 }, + { 0x248F, 10522 }, + { 0x2490, 10514 }, + { 0x2491, 35589 }, + { 0x2492, 35595 }, + { 0x2493, 35599 }, + { 0x2494, 35627 }, + { 0x2495, 35619 }, + { 0x2496, 35607 }, + { 0x2497, 35611 }, + { 0x2498, 35631 }, + { 0x2499, 35615 }, + { 0x249A, 35623 }, + { 0x249B, 35603 }, + { 0x249C, 74655 }, + { 0x249D, 74660 }, + { 0x249E, 74665 }, + { 0x249F, 74670 }, + { 0x24A0, 74675 }, + { 0x24A1, 74680 }, + { 0x24A2, 74685 }, + { 0x24A3, 74690 }, + { 0x24A4, 74695 }, + { 0x24A5, 74700 }, + { 0x24A6, 74705 }, + { 0x24A7, 74710 }, + { 0x24A8, 74715 }, + { 0x24A9, 74720 }, + { 0x24AA, 74725 }, + { 0x24AB, 74730 }, + { 0x24AC, 74735 }, + { 0x24AD, 74740 }, + { 0x24AE, 74745 }, + { 0x24AF, 74750 }, + { 0x24B0, 74755 }, + { 0x24B1, 74760 }, + { 0x24B2, 74765 }, + { 0x24B3, 74770 }, + { 0x24B4, 74775 }, + { 0x24B5, 74780 }, + { 0x24B6, 39052 }, + { 0x24B7, 39057 }, + { 0x24B8, 39062 }, + { 0x24B9, 39067 }, + { 0x24BA, 39072 }, + { 0x24BB, 39077 }, + { 0x24BC, 39082 }, + { 0x24BD, 39087 }, + { 0x24BE, 39092 }, + { 0x24BF, 39097 }, + { 0x24C0, 39102 }, + { 0x24C1, 39107 }, + { 0x24C2, 39112 }, + { 0x24C3, 39117 }, + { 0x24C4, 39122 }, + { 0x24C5, 39127 }, + { 0x24C6, 39132 }, + { 0x24C7, 39137 }, + { 0x24C8, 39142 }, + { 0x24C9, 39147 }, + { 0x24CA, 39152 }, + { 0x24CB, 39157 }, + { 0x24CC, 39162 }, + { 0x24CD, 39167 }, + { 0x24CE, 39172 }, + { 0x24CF, 39177 }, + { 0x24D0, 38922 }, + { 0x24D1, 38927 }, + { 0x24D2, 38932 }, + { 0x24D3, 38937 }, + { 0x24D4, 38942 }, + { 0x24D5, 38947 }, + { 0x24D6, 38952 }, + { 0x24D7, 38957 }, + { 0x24D8, 38962 }, + { 0x24D9, 38967 }, + { 0x24DA, 38972 }, + { 0x24DB, 38977 }, + { 0x24DC, 38982 }, + { 0x24DD, 38987 }, + { 0x24DE, 38992 }, + { 0x24DF, 38997 }, + { 0x24E0, 39002 }, + { 0x24E1, 39007 }, + { 0x24E2, 39012 }, + { 0x24E3, 39017 }, + { 0x24E4, 39022 }, + { 0x24E5, 39027 }, + { 0x24E6, 39032 }, + { 0x24E7, 39037 }, + { 0x24E8, 39042 }, + { 0x24E9, 39047 }, + { 0x24EA, 38905 }, + { 0x24EB, 54887 }, + { 0x24EC, 54891 }, + { 0x24ED, 54919 }, + { 0x24EE, 54911 }, + { 0x24EF, 54899 }, + { 0x24F0, 54903 }, + { 0x24F1, 54923 }, + { 0x24F2, 54907 }, + { 0x24F3, 54915 }, + { 0x24F4, 54895 }, + { 0x24F5, 31612 }, + { 0x24F6, 31620 }, + { 0x24F7, 31644 }, + { 0x24F8, 31628 }, + { 0x24F9, 31624 }, + { 0x24FA, 31616 }, + { 0x24FB, 31640 }, + { 0x24FC, 31636 }, + { 0x24FD, 31632 }, + { 0x24FE, 31648 }, + { 0x24FF, 54883 }, + { 0x2500, 5020 }, + { 0x2501, 4841 }, + { 0x2502, 4986 }, + { 0x2503, 4807 }, + { 0x2504, 4957 }, + { 0x2505, 4801 }, + { 0x2506, 4951 }, + { 0x2507, 4795 }, + { 0x2508, 5014 }, + { 0x2509, 4835 }, + { 0x250A, 5008 }, + { 0x250B, 4829 }, + { 0x250C, 4912 }, + { 0x250D, 4595 }, + { 0x250E, 4550 }, + { 0x250F, 4756 }, + { 0x2510, 4906 }, + { 0x2511, 4580 }, + { 0x2512, 4535 }, + { 0x2513, 4750 }, + { 0x2514, 4862 }, + { 0x2515, 4463 }, + { 0x2516, 4418 }, + { 0x2517, 4734 }, + { 0x2518, 4849 }, + { 0x2519, 4448 }, + { 0x251A, 4403 }, + { 0x251B, 4721 }, + { 0x251C, 4996 }, + { 0x251D, 5180 }, + { 0x251E, 4410 }, + { 0x251F, 4542 }, + { 0x2520, 5159 }, + { 0x2521, 4587 }, + { 0x2522, 4455 }, + { 0x2523, 4817 }, + { 0x2524, 4990 }, + { 0x2525, 5173 }, + { 0x2526, 4395 }, + { 0x2527, 4527 }, + { 0x2528, 5152 }, + { 0x2529, 4572 }, + { 0x252A, 4440 }, + { 0x252B, 4811 }, + { 0x252C, 4918 }, + { 0x252D, 4677 }, + { 0x252E, 5050 }, + { 0x252F, 4602 }, + { 0x2530, 4557 }, + { 0x2531, 5074 }, + { 0x2532, 4701 }, + { 0x2533, 4762 }, + { 0x2534, 4868 }, + { 0x2535, 4669 }, + { 0x2536, 5042 }, + { 0x2537, 4470 }, + { 0x2538, 4425 }, + { 0x2539, 5066 }, + { 0x253A, 4693 }, + { 0x253B, 4740 }, + { 0x253C, 5002 }, + { 0x253D, 4685 }, + { 0x253E, 5058 }, + { 0x253F, 5187 }, + { 0x2540, 4387 }, + { 0x2541, 4519 }, + { 0x2542, 5166 }, + { 0x2543, 4651 }, + { 0x2544, 5024 }, + { 0x2545, 4660 }, + { 0x2546, 5033 }, + { 0x2547, 4564 }, + { 0x2548, 4432 }, + { 0x2549, 5082 }, + { 0x254A, 4709 }, + { 0x254B, 4823 }, + { 0x254C, 4945 }, + { 0x254D, 4789 }, + { 0x254E, 4939 }, + { 0x254F, 4783 }, + { 0x2550, 5148 }, + { 0x2551, 5126 }, + { 0x2552, 4637 }, + { 0x2553, 4616 }, + { 0x2554, 5114 }, + { 0x2555, 4630 }, + { 0x2556, 4609 }, + { 0x2557, 5108 }, + { 0x2558, 4505 }, + { 0x2559, 4484 }, + { 0x255A, 5096 }, + { 0x255B, 4498 }, + { 0x255C, 4477 }, + { 0x255D, 5090 }, + { 0x255E, 5222 }, + { 0x255F, 5201 }, + { 0x2560, 5136 }, + { 0x2561, 5215 }, + { 0x2562, 5194 }, + { 0x2563, 5130 }, + { 0x2564, 4644 }, + { 0x2565, 4623 }, + { 0x2566, 5120 }, + { 0x2567, 4512 }, + { 0x2568, 4491 }, + { 0x2569, 5102 }, + { 0x256A, 5229 }, + { 0x256B, 5208 }, + { 0x256C, 5142 }, + { 0x256D, 4895 }, + { 0x256E, 4888 }, + { 0x256F, 4874 }, + { 0x2570, 4881 }, + { 0x2571, 4977 }, + { 0x2572, 4968 }, + { 0x2573, 4963 }, + { 0x2574, 4924 }, + { 0x2575, 4845 }, + { 0x2576, 4935 }, + { 0x2577, 4902 }, + { 0x2578, 4768 }, + { 0x2579, 4717 }, + { 0x257A, 4779 }, + { 0x257B, 4746 }, + { 0x257C, 4928 }, + { 0x257D, 4855 }, + { 0x257E, 4772 }, + { 0x257F, 4727 }, + { 0x2580, 23088 }, + { 0x2581, 21094 }, + { 0x2582, 21098 }, + { 0x2583, 21168 }, + { 0x2584, 21106 }, + { 0x2585, 21102 }, + { 0x2586, 21172 }, + { 0x2587, 21164 }, + { 0x2588, 9114 }, + { 0x2589, 9314 }, + { 0x258A, 9322 }, + { 0x258B, 9191 }, + { 0x258C, 9199 }, + { 0x258D, 9318 }, + { 0x258E, 9156 }, + { 0x258F, 9152 }, + { 0x2590, 21766 }, + { 0x2591, 20870 }, + { 0x2592, 35535 }, + { 0x2593, 9015 }, + { 0x2594, 23084 }, + { 0x2595, 21755 }, + { 0x2596, 55386 }, + { 0x2597, 55389 }, + { 0x2598, 55392 }, + { 0x2599, 55395 }, + { 0x259A, 55404 }, + { 0x259B, 55410 }, + { 0x259C, 55419 }, + { 0x259D, 55428 }, + { 0x259E, 55431 }, + { 0x259F, 55437 }, + { 0x25A0, 10270 }, + { 0x25A1, 23296 }, + { 0x25A2, 23328 }, + { 0x25A3, 23349 }, + { 0x25A4, 36279 }, + { 0x25A5, 36271 }, + { 0x25A6, 36283 }, + { 0x25A7, 36231 }, + { 0x25A8, 36246 }, + { 0x25A9, 36266 }, + { 0x25AA, 10212 }, + { 0x25AB, 23225 }, + { 0x25AC, 10317 }, + { 0x25AD, 23408 }, + { 0x25AE, 10309 }, + { 0x25AF, 23403 }, + { 0x25B0, 10361 }, + { 0x25B1, 23461 }, + { 0x25B2, 10341 }, + { 0x25B3, 23421 }, + { 0x25B4, 10337 }, + { 0x25B5, 23417 }, + { 0x25B6, 10373 }, + { 0x25B7, 23473 }, + { 0x25B8, 10363 }, + { 0x25B9, 23463 }, + { 0x25BA, 10367 }, + { 0x25BB, 23467 }, + { 0x25BC, 10348 }, + { 0x25BD, 23448 }, + { 0x25BE, 10344 }, + { 0x25BF, 23444 }, + { 0x25C0, 10358 }, + { 0x25C1, 23458 }, + { 0x25C2, 10351 }, + { 0x25C3, 23451 }, + { 0x25C4, 10355 }, + { 0x25C5, 23455 }, + { 0x25C6, 10272 }, + { 0x25C7, 23355 }, + { 0x25C8, 23365 }, + { 0x25C9, 40556 }, + { 0x25CA, 40990 }, + { 0x25CB, 23236 }, + { 0x25CC, 31533 }, + { 0x25CD, 30518 }, + { 0x25CE, 45864 }, + { 0x25CF, 10238 }, + { 0x25D0, 30485 }, + { 0x25D1, 30495 }, + { 0x25D2, 30490 }, + { 0x25D3, 30507 }, + { 0x25D4, 30512 }, + { 0x25D5, 30469 }, + { 0x25D6, 9195 }, + { 0x25D7, 21762 }, + { 0x25D8, 40639 }, + { 0x25D9, 40636 }, + { 0x25DA, 23094 }, + { 0x25DB, 21112 }, + { 0x25DC, 23112 }, + { 0x25DD, 23134 }, + { 0x25DE, 21141 }, + { 0x25DF, 21117 }, + { 0x25E0, 23091 }, + { 0x25E1, 21109 }, + { 0x25E2, 10198 }, + { 0x25E3, 10194 }, + { 0x25E4, 10224 }, + { 0x25E5, 10228 }, + { 0x25E6, 23234 }, + { 0x25E7, 36207 }, + { 0x25E8, 36226 }, + { 0x25E9, 36239 }, + { 0x25EA, 36219 }, + { 0x25EB, 23333 }, + { 0x25EC, 23424 }, + { 0x25ED, 69326 }, + { 0x25EE, 69332 }, + { 0x25EF, 14464 }, + { 0x25F0, 23310 }, + { 0x25F1, 23298 }, + { 0x25F2, 23304 }, + { 0x25F3, 23316 }, + { 0x25F4, 23265 }, + { 0x25F5, 23253 }, + { 0x25F6, 23259 }, + { 0x25F7, 23271 }, + { 0x25F8, 23117 }, + { 0x25F9, 23144 }, + { 0x25FA, 21122 }, + { 0x25FB, 23284 }, + { 0x25FC, 10261 }, + { 0x25FD, 23280 }, + { 0x25FE, 10257 }, + { 0x25FF, 21151 }, + { 0x2600, 10141 }, + { 0x2601, 10454 }, + { 0x2602, 56004 }, + { 0x2603, 43547 }, + { 0x2604, 10460 }, + { 0x2605, 10161 }, + { 0x2606, 23185 }, + { 0x2607, 64791 }, + { 0x2608, 74480 }, + { 0x2609, 7188 }, + { 0x260A, 56109 }, + { 0x260B, 66846 }, + { 0x260C, 68615 }, + { 0x260D, 67880 }, + { 0x260E, 10319 }, + { 0x260F, 23410 }, + { 0x2610, 30232 }, + { 0x2611, 30238 }, + { 0x2612, 30234 }, + { 0x2613, 43020 }, + { 0x2614, 56005 }, + { 0x2615, 5795 }, + { 0x2616, 23219 }, + { 0x2617, 10206 }, + { 0x2618, 55522 }, + { 0x2619, 55497 }, + { 0x261A, 10154 }, + { 0x261B, 10202 }, + { 0x261C, 23181 }, + { 0x261D, 23158 }, + { 0x261E, 23215 }, + { 0x261F, 23171 }, + { 0x2620, 22476 }, + { 0x2621, 38868 }, + { 0x2622, 69274 }, + { 0x2623, 56112 }, + { 0x2624, 45865 }, + { 0x2625, 8718 }, + { 0x2626, 54931 }, + { 0x2627, 5236 }, + { 0x2628, 10462 }, + { 0x2629, 10465 }, + { 0x262A, 9715 }, + { 0x262B, 10630 }, + { 0x262C, 4009 }, + { 0x262D, 31881 }, + { 0x262E, 21733 }, + { 0x262F, 8714 }, + { 0x2630, 44529 }, + { 0x2631, 44517 }, + { 0x2632, 44514 }, + { 0x2633, 44532 }, + { 0x2634, 44520 }, + { 0x2635, 44526 }, + { 0x2636, 44535 }, + { 0x2637, 44523 }, + { 0x2638, 23155 }, + { 0x2639, 23384 }, + { 0x263A, 23373 }, + { 0x263B, 10291 }, + { 0x263C, 23164 }, + { 0x263D, 10632 }, + { 0x263E, 9132 }, + { 0x263F, 41191 }, + { 0x2640, 31767 }, + { 0x2641, 10540 }, + { 0x2642, 9580 }, + { 0x2643, 40641 }, + { 0x2644, 35810 }, + { 0x2645, 37705 }, + { 0x2646, 42827 }, + { 0x2647, 21739 }, + { 0x2648, 10114 }, + { 0x2649, 37129 }, + { 0x264A, 31790 }, + { 0x264B, 30317 }, + { 0x264C, 6030 }, + { 0x264D, 23153 }, + { 0x264E, 20857 }, + { 0x264F, 55511 }, + { 0x2650, 69278 }, + { 0x2651, 57359 }, + { 0x2652, 44719 }, + { 0x2653, 35653 }, + { 0x2654, 23191 }, + { 0x2655, 23200 }, + { 0x2656, 23197 }, + { 0x2657, 23203 }, + { 0x2658, 23206 }, + { 0x2659, 23194 }, + { 0x265A, 10167 }, + { 0x265B, 10176 }, + { 0x265C, 10173 }, + { 0x265D, 10179 }, + { 0x265E, 10182 }, + { 0x265F, 10170 }, + { 0x2660, 10221 }, + { 0x2661, 23209 }, + { 0x2662, 23357 }, + { 0x2663, 10145 }, + { 0x2664, 23231 }, + { 0x2665, 10185 }, + { 0x2666, 10274 }, + { 0x2667, 23168 }, + { 0x2668, 5793 }, + { 0x2669, 42977 }, + { 0x266A, 31704 }, + { 0x266B, 30242 }, + { 0x266C, 30245 }, + { 0x266D, 21206 }, + { 0x266E, 21212 }, + { 0x266F, 21209 }, + { 0x2670, 10084 }, + { 0x2671, 9086 }, + { 0x2672, 66308 }, + { 0x2673, 65768 }, + { 0x2674, 65773 }, + { 0x2675, 65778 }, + { 0x2676, 65783 }, + { 0x2677, 65788 }, + { 0x2678, 65793 }, + { 0x2679, 65798 }, + { 0x267A, 65803 }, + { 0x267B, 10321 }, + { 0x267C, 55452 }, + { 0x267D, 75139 }, + { 0x267E, 65753 }, + { 0x267F, 68601 }, + { 0x2680, 5768 }, + { 0x2681, 5770 }, + { 0x2682, 5772 }, + { 0x2683, 5774 }, + { 0x2684, 5776 }, + { 0x2685, 5778 }, + { 0x2686, 23238 }, + { 0x2687, 23243 }, + { 0x2688, 10251 }, + { 0x2689, 10240 }, + { 0x268A, 54868 }, + { 0x268B, 54865 }, + { 0x268C, 31212 }, + { 0x268D, 31192 }, + { 0x268E, 31196 }, + { 0x268F, 31208 }, + { 0x2690, 23175 }, + { 0x2691, 10148 }, + { 0x2692, 31878 }, + { 0x2693, 23701 }, + { 0x2694, 39792 }, + { 0x2695, 22748 }, + { 0x2696, 35811 }, + { 0x2697, 37778 }, + { 0x2698, 31778 }, + { 0x2699, 9120 }, + { 0x269A, 22745 }, + { 0x269B, 8719 }, + { 0x269C, 69423 }, + { 0x269D, 54942 }, + { 0x26A0, 44705 }, + { 0x26A1, 9127 }, + { 0x26A2, 40495 }, + { 0x26A3, 40492 }, + { 0x26A4, 69258 }, + { 0x26A5, 9576 }, + { 0x26A6, 9590 }, + { 0x26A7, 9582 }, + { 0x26A8, 56086 }, + { 0x26A9, 67641 }, + { 0x26AA, 35541 }, + { 0x26AB, 35523 }, + { 0x26AC, 35537 }, + { 0x26AD, 53728 }, + { 0x26AE, 40490 }, + { 0x26AF, 66311 }, + { 0x26B0, 30571 }, + { 0x26B1, 40558 }, + { 0x26B2, 35579 }, + { 0x26B3, 10446 }, + { 0x26B4, 35649 }, + { 0x26B5, 9131 }, + { 0x26B6, 23152 }, + { 0x26B7, 30468 }, + { 0x26B8, 10158 }, + { 0x26B9, 43027 }, + { 0x26BA, 69279 }, + { 0x26BB, 55451 }, + { 0x26BC, 75099 }, + { 0x26C0, 23376 }, + { 0x26C1, 23379 }, + { 0x26C2, 10294 }, + { 0x26C3, 10297 }, + { 0x2701, 23120 }, + { 0x2702, 10304 }, + { 0x2703, 21130 }, + { 0x2704, 23389 }, + { 0x2706, 66042 }, + { 0x2707, 9722 }, + { 0x2708, 44716 }, + { 0x2709, 50322 }, + { 0x270C, 44703 }, + { 0x270D, 44707 }, + { 0x270E, 21138 }, + { 0x270F, 35650 }, + { 0x2710, 23131 }, + { 0x2711, 23162 }, + { 0x2712, 10139 }, + { 0x2713, 10447 }, + { 0x2714, 13551 }, + { 0x2715, 75053 }, + { 0x2716, 13671 }, + { 0x2717, 30230 }, + { 0x2718, 13593 }, + { 0x2719, 54936 }, + { 0x271A, 13565 }, + { 0x271B, 9612 }, + { 0x271C, 13530 }, + { 0x271D, 14471 }, + { 0x271E, 55515 }, + { 0x271F, 54939 }, + { 0x2720, 41189 }, + { 0x2721, 9712 }, + { 0x2722, 9109 }, + { 0x2723, 9106 }, + { 0x2724, 13526 }, + { 0x2725, 9103 }, + { 0x2726, 10150 }, + { 0x2727, 23177 }, + { 0x2729, 36465 }, + { 0x272A, 39186 }, + { 0x272B, 9608 }, + { 0x272C, 10234 }, + { 0x272D, 54933 }, + { 0x272E, 13634 }, + { 0x272F, 55330 }, + { 0x2730, 55512 }, + { 0x2731, 13632 }, + { 0x2732, 9615 }, + { 0x2733, 10543 }, + { 0x2734, 10546 }, + { 0x2735, 10550 }, + { 0x2736, 7178 }, + { 0x2737, 10554 }, + { 0x2738, 13554 }, + { 0x2739, 37701 }, + { 0x273A, 43505 }, + { 0x273B, 75114 }, + { 0x273C, 9618 }, + { 0x273D, 13704 }, + { 0x273E, 7182 }, + { 0x273F, 10300 }, + { 0x2740, 23382 }, + { 0x2741, 10559 }, + { 0x2742, 38876 }, + { 0x2743, 13707 }, + { 0x2744, 65814 }, + { 0x2745, 23005 }, + { 0x2746, 13627 }, + { 0x2747, 43552 }, + { 0x2748, 13630 }, + { 0x2749, 75051 }, + { 0x274A, 10564 }, + { 0x274B, 13560 }, + { 0x274D, 55519 }, + { 0x274F, 21159 }, + { 0x2750, 23147 }, + { 0x2751, 21146 }, + { 0x2752, 23139 }, + { 0x2756, 10282 }, + { 0x2758, 20872 }, + { 0x2759, 35544 }, + { 0x275A, 13638 }, + { 0x275B, 13620 }, + { 0x275C, 13614 }, + { 0x275D, 13607 }, + { 0x275E, 13601 }, + { 0x2761, 31164 }, + { 0x2762, 13644 }, + { 0x2763, 13568 }, + { 0x2764, 13534 }, + { 0x2765, 43008 }, + { 0x2766, 31776 }, + { 0x2767, 43013 }, + { 0x2768, 35519 }, + { 0x2769, 35531 }, + { 0x276A, 35547 }, + { 0x276B, 35552 }, + { 0x276C, 35560 }, + { 0x276D, 35565 }, + { 0x276E, 13665 }, + { 0x276F, 13679 }, + { 0x2770, 13660 }, + { 0x2771, 13674 }, + { 0x2772, 20858 }, + { 0x2773, 20864 }, + { 0x2774, 35514 }, + { 0x2775, 35526 }, + { 0x2776, 40379 }, + { 0x2777, 40389 }, + { 0x2778, 40419 }, + { 0x2779, 40399 }, + { 0x277A, 40394 }, + { 0x277B, 40384 }, + { 0x277C, 40414 }, + { 0x277D, 40409 }, + { 0x277E, 40404 }, + { 0x277F, 40424 }, + { 0x2780, 40329 }, + { 0x2781, 40339 }, + { 0x2782, 40369 }, + { 0x2783, 40349 }, + { 0x2784, 40344 }, + { 0x2785, 40334 }, + { 0x2786, 40364 }, + { 0x2787, 40359 }, + { 0x2788, 40354 }, + { 0x2789, 40374 }, + { 0x278A, 40429 }, + { 0x278B, 40441 }, + { 0x278C, 40477 }, + { 0x278D, 40453 }, + { 0x278E, 40447 }, + { 0x278F, 40435 }, + { 0x2790, 40471 }, + { 0x2791, 40465 }, + { 0x2792, 40459 }, + { 0x2793, 40483 }, + { 0x2794, 13648 }, + { 0x2798, 13583 }, + { 0x2799, 13641 }, + { 0x279A, 13579 }, + { 0x279B, 50314 }, + { 0x279C, 13652 }, + { 0x279D, 75116 }, + { 0x279E, 13711 }, + { 0x279F, 31175 }, + { 0x27A0, 13596 }, + { 0x27A1, 10328 }, + { 0x27A2, 43645 }, + { 0x27A3, 43649 }, + { 0x27A4, 10334 }, + { 0x27A5, 13544 }, + { 0x27A6, 13537 }, + { 0x27A7, 22741 }, + { 0x27A8, 13699 }, + { 0x27A9, 74472 }, + { 0x27AA, 69264 }, + { 0x27AB, 68606 }, + { 0x27AC, 69424 }, + { 0x27AD, 13573 }, + { 0x27AE, 13587 }, + { 0x27AF, 42831 }, + { 0x27B1, 42837 }, + { 0x27B2, 38917 }, + { 0x27B3, 75119 }, + { 0x27B4, 75104 }, + { 0x27B5, 75108 }, + { 0x27B6, 75100 }, + { 0x27B7, 13690 }, + { 0x27B8, 13695 }, + { 0x27B9, 13685 }, + { 0x27BA, 75111 }, + { 0x27BB, 13715 }, + { 0x27BC, 74481 }, + { 0x27BD, 13656 }, + { 0x27BE, 74625 }, + { 0x27C0, 23002 }, + { 0x27C1, 23391 }, + { 0x27C2, 75037 }, + { 0x27C3, 9622 }, + { 0x27C4, 9624 }, + { 0x27C5, 9435 }, + { 0x27C6, 21960 }, + { 0x27C7, 271 }, + { 0x27C8, 43004 }, + { 0x27C9, 55653 }, + { 0x27CA, 56011 }, + { 0x27CC, 9530 }, + { 0x27D0, 23360 }, + { 0x27D1, 4016 }, + { 0x27D2, 40537 }, + { 0x27D3, 21133 }, + { 0x27D4, 23107 }, + { 0x27D5, 9251 }, + { 0x27D6, 21844 }, + { 0x27D7, 9116 }, + { 0x27D8, 14454 }, + { 0x27D9, 14457 }, + { 0x27DA, 9139 }, + { 0x27DB, 9135 }, + { 0x27DC, 9433 }, + { 0x27DD, 9527 }, + { 0x27DE, 9515 }, + { 0x27DF, 328 }, + { 0x27E0, 40991 }, + { 0x27E1, 23429 }, + { 0x27E2, 23432 }, + { 0x27E3, 23438 }, + { 0x27E4, 23339 }, + { 0x27E5, 23344 }, + { 0x27E6, 71159 }, + { 0x27E7, 71183 }, + { 0x27E8, 71155 }, + { 0x27E9, 71179 }, + { 0x27EA, 71170 }, + { 0x27EB, 71194 }, + { 0x27EC, 71164 }, + { 0x27ED, 71188 }, + { 0x27EE, 71175 }, + { 0x27EF, 71199 }, + { 0x27F0, 44694 }, + { 0x27F1, 63375 }, + { 0x27F2, 74496 }, + { 0x27F3, 57374 }, + { 0x27F4, 21810 }, + { 0x27F5, 9532 }, + { 0x27F6, 9554 }, + { 0x27F7, 9518 }, + { 0x27F8, 9540 }, + { 0x27F9, 9562 }, + { 0x27FA, 9522 }, + { 0x27FB, 9535 }, + { 0x27FC, 9557 }, + { 0x27FD, 9544 }, + { 0x27FE, 9566 }, + { 0x27FF, 9572 }, + { 0x2800, 38100 }, + { 0x2801, 38103 }, + { 0x2802, 38106 }, + { 0x2803, 38127 }, + { 0x2804, 38109 }, + { 0x2805, 38130 }, + { 0x2806, 38148 }, + { 0x2807, 38211 }, + { 0x2808, 38112 }, + { 0x2809, 38133 }, + { 0x280A, 38151 }, + { 0x280B, 38214 }, + { 0x280C, 38166 }, + { 0x280D, 38229 }, + { 0x280E, 38274 }, + { 0x280F, 38379 }, + { 0x2810, 38115 }, + { 0x2811, 38136 }, + { 0x2812, 38154 }, + { 0x2813, 38217 }, + { 0x2814, 38169 }, + { 0x2815, 38232 }, + { 0x2816, 38277 }, + { 0x2817, 38382 }, + { 0x2818, 38181 }, + { 0x2819, 38244 }, + { 0x281A, 38289 }, + { 0x281B, 38394 }, + { 0x281C, 38319 }, + { 0x281D, 38424 }, + { 0x281E, 38484 }, + { 0x281F, 38589 }, + { 0x2820, 38118 }, + { 0x2821, 38139 }, + { 0x2822, 38157 }, + { 0x2823, 38220 }, + { 0x2824, 38172 }, + { 0x2825, 38235 }, + { 0x2826, 38280 }, + { 0x2827, 38385 }, + { 0x2828, 38184 }, + { 0x2829, 38247 }, + { 0x282A, 38292 }, + { 0x282B, 38397 }, + { 0x282C, 38322 }, + { 0x282D, 38427 }, + { 0x282E, 38487 }, + { 0x282F, 38592 }, + { 0x2830, 38193 }, + { 0x2831, 38256 }, + { 0x2832, 38301 }, + { 0x2833, 38406 }, + { 0x2834, 38331 }, + { 0x2835, 38436 }, + { 0x2836, 38496 }, + { 0x2837, 38601 }, + { 0x2838, 38349 }, + { 0x2839, 38454 }, + { 0x283A, 38514 }, + { 0x283B, 38619 }, + { 0x283C, 38544 }, + { 0x283D, 38649 }, + { 0x283E, 38694 }, + { 0x283F, 38757 }, + { 0x2840, 38121 }, + { 0x2841, 38142 }, + { 0x2842, 38160 }, + { 0x2843, 38223 }, + { 0x2844, 38175 }, + { 0x2845, 38238 }, + { 0x2846, 38283 }, + { 0x2847, 38388 }, + { 0x2848, 38187 }, + { 0x2849, 38250 }, + { 0x284A, 38295 }, + { 0x284B, 38400 }, + { 0x284C, 38325 }, + { 0x284D, 38430 }, + { 0x284E, 38490 }, + { 0x284F, 38595 }, + { 0x2850, 38196 }, + { 0x2851, 38259 }, + { 0x2852, 38304 }, + { 0x2853, 38409 }, + { 0x2854, 38334 }, + { 0x2855, 38439 }, + { 0x2856, 38499 }, + { 0x2857, 38604 }, + { 0x2858, 38352 }, + { 0x2859, 38457 }, + { 0x285A, 38517 }, + { 0x285B, 38622 }, + { 0x285C, 38547 }, + { 0x285D, 38652 }, + { 0x285E, 38697 }, + { 0x285F, 38760 }, + { 0x2860, 38202 }, + { 0x2861, 38265 }, + { 0x2862, 38310 }, + { 0x2863, 38415 }, + { 0x2864, 38340 }, + { 0x2865, 38445 }, + { 0x2866, 38505 }, + { 0x2867, 38610 }, + { 0x2868, 38358 }, + { 0x2869, 38463 }, + { 0x286A, 38523 }, + { 0x286B, 38628 }, + { 0x286C, 38553 }, + { 0x286D, 38658 }, + { 0x286E, 38703 }, + { 0x286F, 38766 }, + { 0x2870, 38367 }, + { 0x2871, 38472 }, + { 0x2872, 38532 }, + { 0x2873, 38637 }, + { 0x2874, 38562 }, + { 0x2875, 38667 }, + { 0x2876, 38712 }, + { 0x2877, 38775 }, + { 0x2878, 38574 }, + { 0x2879, 38679 }, + { 0x287A, 38724 }, + { 0x287B, 38787 }, + { 0x287C, 38739 }, + { 0x287D, 38802 }, + { 0x287E, 38820 }, + { 0x287F, 38841 }, + { 0x2880, 38124 }, + { 0x2881, 38145 }, + { 0x2882, 38163 }, + { 0x2883, 38226 }, + { 0x2884, 38178 }, + { 0x2885, 38241 }, + { 0x2886, 38286 }, + { 0x2887, 38391 }, + { 0x2888, 38190 }, + { 0x2889, 38253 }, + { 0x288A, 38298 }, + { 0x288B, 38403 }, + { 0x288C, 38328 }, + { 0x288D, 38433 }, + { 0x288E, 38493 }, + { 0x288F, 38598 }, + { 0x2890, 38199 }, + { 0x2891, 38262 }, + { 0x2892, 38307 }, + { 0x2893, 38412 }, + { 0x2894, 38337 }, + { 0x2895, 38442 }, + { 0x2896, 38502 }, + { 0x2897, 38607 }, + { 0x2898, 38355 }, + { 0x2899, 38460 }, + { 0x289A, 38520 }, + { 0x289B, 38625 }, + { 0x289C, 38550 }, + { 0x289D, 38655 }, + { 0x289E, 38700 }, + { 0x289F, 38763 }, + { 0x28A0, 38205 }, + { 0x28A1, 38268 }, + { 0x28A2, 38313 }, + { 0x28A3, 38418 }, + { 0x28A4, 38343 }, + { 0x28A5, 38448 }, + { 0x28A6, 38508 }, + { 0x28A7, 38613 }, + { 0x28A8, 38361 }, + { 0x28A9, 38466 }, + { 0x28AA, 38526 }, + { 0x28AB, 38631 }, + { 0x28AC, 38556 }, + { 0x28AD, 38661 }, + { 0x28AE, 38706 }, + { 0x28AF, 38769 }, + { 0x28B0, 38370 }, + { 0x28B1, 38475 }, + { 0x28B2, 38535 }, + { 0x28B3, 38640 }, + { 0x28B4, 38565 }, + { 0x28B5, 38670 }, + { 0x28B6, 38715 }, + { 0x28B7, 38778 }, + { 0x28B8, 38577 }, + { 0x28B9, 38682 }, + { 0x28BA, 38727 }, + { 0x28BB, 38790 }, + { 0x28BC, 38742 }, + { 0x28BD, 38805 }, + { 0x28BE, 38823 }, + { 0x28BF, 38844 }, + { 0x28C0, 38208 }, + { 0x28C1, 38271 }, + { 0x28C2, 38316 }, + { 0x28C3, 38421 }, + { 0x28C4, 38346 }, + { 0x28C5, 38451 }, + { 0x28C6, 38511 }, + { 0x28C7, 38616 }, + { 0x28C8, 38364 }, + { 0x28C9, 38469 }, + { 0x28CA, 38529 }, + { 0x28CB, 38634 }, + { 0x28CC, 38559 }, + { 0x28CD, 38664 }, + { 0x28CE, 38709 }, + { 0x28CF, 38772 }, + { 0x28D0, 38373 }, + { 0x28D1, 38478 }, + { 0x28D2, 38538 }, + { 0x28D3, 38643 }, + { 0x28D4, 38568 }, + { 0x28D5, 38673 }, + { 0x28D6, 38718 }, + { 0x28D7, 38781 }, + { 0x28D8, 38580 }, + { 0x28D9, 38685 }, + { 0x28DA, 38730 }, + { 0x28DB, 38793 }, + { 0x28DC, 38745 }, + { 0x28DD, 38808 }, + { 0x28DE, 38826 }, + { 0x28DF, 38847 }, + { 0x28E0, 38376 }, + { 0x28E1, 38481 }, + { 0x28E2, 38541 }, + { 0x28E3, 38646 }, + { 0x28E4, 38571 }, + { 0x28E5, 38676 }, + { 0x28E6, 38721 }, + { 0x28E7, 38784 }, + { 0x28E8, 38583 }, + { 0x28E9, 38688 }, + { 0x28EA, 38733 }, + { 0x28EB, 38796 }, + { 0x28EC, 38748 }, + { 0x28ED, 38811 }, + { 0x28EE, 38829 }, + { 0x28EF, 38850 }, + { 0x28F0, 38586 }, + { 0x28F1, 38691 }, + { 0x28F2, 38736 }, + { 0x28F3, 38799 }, + { 0x28F4, 38751 }, + { 0x28F5, 38814 }, + { 0x28F6, 38832 }, + { 0x28F7, 38853 }, + { 0x28F8, 38754 }, + { 0x28F9, 38817 }, + { 0x28FA, 38835 }, + { 0x28FB, 38856 }, + { 0x28FC, 38838 }, + { 0x28FD, 38859 }, + { 0x28FE, 38862 }, + { 0x28FF, 38865 }, + { 0x2900, 68309 }, + { 0x2901, 68302 }, + { 0x2902, 64491 }, + { 0x2903, 68156 }, + { 0x2904, 9303 }, + { 0x2905, 68275 }, + { 0x2906, 64481 }, + { 0x2907, 68146 }, + { 0x2908, 63281 }, + { 0x2909, 44567 }, + { 0x290A, 44631 }, + { 0x290B, 63309 }, + { 0x290C, 64474 }, + { 0x290D, 68139 }, + { 0x290E, 64503 }, + { 0x290F, 68168 }, + { 0x2910, 68315 }, + { 0x2911, 68066 }, + { 0x2912, 44544 }, + { 0x2913, 63253 }, + { 0x2914, 68054 }, + { 0x2915, 68046 }, + { 0x2916, 68280 }, + { 0x2917, 68294 }, + { 0x2918, 68285 }, + { 0x2919, 64608 }, + { 0x291A, 68273 }, + { 0x291B, 64497 }, + { 0x291C, 68162 }, + { 0x291D, 64340 }, + { 0x291E, 67998 }, + { 0x291F, 64349 }, + { 0x2920, 68007 }, + { 0x2921, 21318 }, + { 0x2922, 21271 }, + { 0x2923, 21345 }, + { 0x2924, 21287 }, + { 0x2925, 22689 }, + { 0x2926, 22723 }, + { 0x2927, 21338 }, + { 0x2928, 21280 }, + { 0x2929, 22682 }, + { 0x292A, 22716 }, + { 0x292B, 35805 }, + { 0x292C, 40551 }, + { 0x292D, 22694 }, + { 0x292E, 21299 }, + { 0x292F, 40545 }, + { 0x2930, 35799 }, + { 0x2931, 21292 }, + { 0x2932, 21350 }, + { 0x2933, 10070 }, + { 0x2934, 10127 }, + { 0x2935, 10133 }, + { 0x2936, 10115 }, + { 0x2937, 10121 }, + { 0x2938, 67981 }, + { 0x2939, 64314 }, + { 0x293A, 7721 }, + { 0x293B, 30248 }, + { 0x293C, 7715 }, + { 0x293D, 7725 }, + { 0x293E, 21154 }, + { 0x293F, 21125 }, + { 0x2940, 74492 }, + { 0x2941, 57370 }, + { 0x2942, 68086 }, + { 0x2943, 64423 }, + { 0x2944, 22470 }, + { 0x2945, 68037 }, + { 0x2946, 64379 }, + { 0x2947, 68116 }, + { 0x2948, 9279 }, + { 0x2949, 44697 }, + { 0x294A, 9167 }, + { 0x294B, 9174 }, + { 0x294C, 289 }, + { 0x294D, 282 }, + { 0x294E, 9160 }, + { 0x294F, 296 }, + { 0x2950, 9181 }, + { 0x2951, 275 }, + { 0x2952, 64515 }, + { 0x2953, 68180 }, + { 0x2954, 44670 }, + { 0x2955, 63351 }, + { 0x2956, 64559 }, + { 0x2957, 68224 }, + { 0x2958, 44634 }, + { 0x2959, 63315 }, + { 0x295A, 64522 }, + { 0x295B, 68187 }, + { 0x295C, 44677 }, + { 0x295D, 63358 }, + { 0x295E, 64566 }, + { 0x295F, 68231 }, + { 0x2960, 44641 }, + { 0x2961, 63322 }, + { 0x2962, 64537 }, + { 0x2963, 44648 }, + { 0x2964, 68213 }, + { 0x2965, 63340 }, + { 0x2966, 64548 }, + { 0x2967, 64573 }, + { 0x2968, 68202 }, + { 0x2969, 68238 }, + { 0x296A, 64529 }, + { 0x296B, 64584 }, + { 0x296C, 68194 }, + { 0x296D, 68249 }, + { 0x296E, 44659 }, + { 0x296F, 63329 }, + { 0x2970, 21882 }, + { 0x2971, 31756 }, + { 0x2972, 23038 }, + { 0x2973, 64429 }, + { 0x2974, 68092 }, + { 0x2975, 68097 }, + { 0x2976, 64759 }, + { 0x2977, 64461 }, + { 0x2978, 69536 }, + { 0x2979, 36531 }, + { 0x297A, 64457 }, + { 0x297B, 55638 }, + { 0x297C, 9188 }, + { 0x297D, 21759 }, + { 0x297E, 323 }, + { 0x297F, 9070 }, + { 0x2980, 37651 }, + { 0x2981, 26 }, + { 0x2982, 29 }, + { 0x2983, 9326 }, + { 0x2984, 21847 }, + { 0x2985, 9347 }, + { 0x2986, 21868 }, + { 0x2987, 16 }, + { 0x2988, 37 }, + { 0x2989, 21 }, + { 0x298A, 42 }, + { 0x298B, 9409 }, + { 0x298C, 21936 }, + { 0x298D, 9388 }, + { 0x298E, 21923 }, + { 0x298F, 9396 }, + { 0x2990, 21915 }, + { 0x2991, 9207 }, + { 0x2992, 21791 }, + { 0x2993, 9144 }, + { 0x2994, 21747 }, + { 0x2995, 31554 }, + { 0x2996, 31580 }, + { 0x2997, 9222 }, + { 0x2998, 21815 }, + { 0x2999, 31531 }, + { 0x299A, 56093 }, + { 0x299B, 53830 }, + { 0x299C, 21796 }, + { 0x299D, 53834 }, + { 0x299E, 10107 }, + { 0x299F, 10102 }, + { 0x29A0, 65821 }, + { 0x29A1, 65817 }, + { 0x29A2, 37674 }, + { 0x29A3, 55459 }, + { 0x29A4, 10111 }, + { 0x29A5, 55461 }, + { 0x29A6, 42843 }, + { 0x29A7, 42847 }, + { 0x29A8, 53746 }, + { 0x29A9, 53734 }, + { 0x29AA, 53770 }, + { 0x29AB, 53758 }, + { 0x29AC, 53806 }, + { 0x29AD, 53782 }, + { 0x29AE, 53818 }, + { 0x29AF, 53794 }, + { 0x29B0, 55465 }, + { 0x29B1, 10590 }, + { 0x29B2, 10584 }, + { 0x29B3, 10578 }, + { 0x29B4, 10572 }, + { 0x29B5, 30522 }, + { 0x29B6, 39617 }, + { 0x29B7, 39612 }, + { 0x29B8, 39459 }, + { 0x29B9, 39776 }, + { 0x29BA, 30530 }, + { 0x29BB, 30526 }, + { 0x29BC, 39784 }, + { 0x29BD, 333 }, + { 0x29BE, 39189 }, + { 0x29BF, 39192 }, + { 0x29C0, 39767 }, + { 0x29C1, 39774 }, + { 0x29C2, 30500 }, + { 0x29C3, 30477 }, + { 0x29C4, 43569 }, + { 0x29C5, 43575 }, + { 0x29C6, 43579 }, + { 0x29C7, 43564 }, + { 0x29C8, 43573 }, + { 0x29C9, 7778 }, + { 0x29CA, 55898 }, + { 0x29CB, 55907 }, + { 0x29CC, 4 }, + { 0x29CD, 55902 }, + { 0x29CE, 21974 }, + { 0x29CF, 9447 }, + { 0x29D0, 56016 }, + { 0x29D1, 30295 }, + { 0x29D2, 30300 }, + { 0x29D3, 10232 }, + { 0x29D4, 23043 }, + { 0x29D5, 23048 }, + { 0x29D6, 23406 }, + { 0x29D7, 10312 }, + { 0x29D8, 9428 }, + { 0x29D9, 21955 }, + { 0x29DA, 9361 }, + { 0x29DB, 21888 }, + { 0x29DC, 67665 }, + { 0x29DD, 7712 }, + { 0x29DE, 53301 }, + { 0x29DF, 69403 }, + { 0x29E0, 36275 }, + { 0x29E1, 64303 }, + { 0x29E2, 43172 }, + { 0x29E3, 31708 }, + { 0x29E4, 31713 }, + { 0x29E5, 64294 }, + { 0x29E6, 31794 }, + { 0x29E7, 75047 }, + { 0x29E8, 74585 }, + { 0x29E9, 74591 }, + { 0x29EA, 10277 }, + { 0x29EB, 10289 }, + { 0x29EC, 23248 }, + { 0x29ED, 10246 }, + { 0x29EE, 69417 }, + { 0x29EF, 69408 }, + { 0x29F0, 69420 }, + { 0x29F1, 69411 }, + { 0x29F2, 69414 }, + { 0x29F3, 69405 }, + { 0x29F4, 74476 }, + { 0x29F5, 43001 }, + { 0x29F6, 43549 }, + { 0x29F7, 42996 }, + { 0x29F8, 4385 }, + { 0x29F9, 4382 }, + { 0x29FA, 31559 }, + { 0x29FB, 37614 }, + { 0x29FC, 74608 }, + { 0x29FD, 75090 }, + { 0x29FE, 10053 }, + { 0x29FF, 9598 }, + { 0x2A00, 21242 }, + { 0x2A01, 21246 }, + { 0x2A02, 21250 }, + { 0x2A03, 21220 }, + { 0x2A04, 21225 }, + { 0x2A05, 21238 }, + { 0x2A06, 21234 }, + { 0x2A07, 7785 }, + { 0x2A08, 7781 }, + { 0x2A09, 21215 }, + { 0x2A0A, 35573 }, + { 0x2A0B, 65861 }, + { 0x2A0C, 65763 }, + { 0x2A0D, 31773 }, + { 0x2A0E, 53314 }, + { 0x2A0F, 53338 }, + { 0x2A10, 68611 }, + { 0x2A11, 74503 }, + { 0x2A12, 9491 }, + { 0x2A13, 9498 }, + { 0x2A14, 9485 }, + { 0x2A15, 53333 }, + { 0x2A16, 67973 }, + { 0x2A17, 53324 }, + { 0x2A18, 53307 }, + { 0x2A19, 53330 }, + { 0x2A1A, 53311 }, + { 0x2A1B, 53318 }, + { 0x2A1C, 53321 }, + { 0x2A1D, 9130 }, + { 0x2A1E, 14460 }, + { 0x2A1F, 59 }, + { 0x2A20, 51 }, + { 0x2A21, 55 }, + { 0x2A22, 9661 }, + { 0x2A23, 9682 }, + { 0x2A24, 9667 }, + { 0x2A25, 9651 }, + { 0x2A26, 9672 }, + { 0x2A27, 9677 }, + { 0x2A28, 9656 }, + { 0x2A29, 21189 }, + { 0x2A2A, 21184 }, + { 0x2A2B, 21199 }, + { 0x2A2C, 21194 }, + { 0x2A2D, 9635 }, + { 0x2A2E, 9641 }, + { 0x2A2F, 37706 }, + { 0x2A30, 75078 }, + { 0x2A31, 75083 }, + { 0x2A32, 68589 }, + { 0x2A33, 22668 }, + { 0x2A34, 75057 }, + { 0x2A35, 75063 }, + { 0x2A36, 39778 }, + { 0x2A37, 75069 }, + { 0x2A38, 39465 }, + { 0x2A39, 9647 }, + { 0x2A3A, 21180 }, + { 0x2A3B, 75074 }, + { 0x2A3C, 53344 }, + { 0x2A3D, 65810 }, + { 0x2A3E, 63 }, + { 0x2A3F, 69339 }, + { 0x2A40, 69571 }, + { 0x2A41, 23059 }, + { 0x2A42, 23067 }, + { 0x2A43, 69578 }, + { 0x2A44, 69574 }, + { 0x2A45, 23063 }, + { 0x2A46, 23075 }, + { 0x2A47, 69586 }, + { 0x2A48, 23070 }, + { 0x2A49, 69581 }, + { 0x2A4A, 23078 }, + { 0x2A4B, 69589 }, + { 0x2A4C, 30542 }, + { 0x2A4D, 30567 }, + { 0x2A4E, 31603 }, + { 0x2A4F, 31600 }, + { 0x2A50, 30546 }, + { 0x2A51, 40961 }, + { 0x2A52, 40929 }, + { 0x2A53, 31655 }, + { 0x2A54, 31652 }, + { 0x2A55, 7801 }, + { 0x2A56, 7797 }, + { 0x2A57, 43534 }, + { 0x2A58, 43537 }, + { 0x2A59, 40954 }, + { 0x2A5A, 40976 }, + { 0x2A5B, 40944 }, + { 0x2A5C, 40985 }, + { 0x2A5D, 40949 }, + { 0x2A5E, 40966 }, + { 0x2A5F, 40981 }, + { 0x2A60, 40971 }, + { 0x2A61, 22483 }, + { 0x2A62, 40934 }, + { 0x2A63, 40939 }, + { 0x2A64, 47 }, + { 0x2A65, 33 }, + { 0x2A66, 31721 }, + { 0x2A67, 64299 }, + { 0x2A68, 37655 }, + { 0x2A69, 37662 }, + { 0x2A6A, 23023 }, + { 0x2A6B, 23028 }, + { 0x2A6C, 43192 }, + { 0x2A6D, 58345 }, + { 0x2A6E, 31761 }, + { 0x2A6F, 23695 }, + { 0x2A70, 74511 }, + { 0x2A71, 31741 }, + { 0x2A72, 9688 }, + { 0x2A73, 31746 }, + { 0x2A74, 31567 }, + { 0x2A75, 7793 }, + { 0x2A76, 22998 }, + { 0x2A77, 31726 }, + { 0x2A78, 67228 }, + { 0x2A79, 64731 }, + { 0x2A7A, 69502 }, + { 0x2A7B, 64735 }, + { 0x2A7C, 69506 }, + { 0x2A7D, 64662 }, + { 0x2A7E, 69433 }, + { 0x2A7F, 64684 }, + { 0x2A80, 69455 }, + { 0x2A81, 64667 }, + { 0x2A82, 69438 }, + { 0x2A83, 64675 }, + { 0x2A84, 69446 }, + { 0x2A85, 64696 }, + { 0x2A86, 69470 }, + { 0x2A87, 64706 }, + { 0x2A88, 69477 }, + { 0x2A89, 64702 }, + { 0x2A8A, 69473 }, + { 0x2A8B, 64763 }, + { 0x2A8C, 69540 }, + { 0x2A8D, 64740 }, + { 0x2A8E, 69511 }, + { 0x2A8F, 64745 }, + { 0x2A90, 69516 }, + { 0x2A91, 64769 }, + { 0x2A92, 69530 }, + { 0x2A93, 64750 }, + { 0x2A94, 69521 }, + { 0x2A95, 43508 }, + { 0x2A96, 43521 }, + { 0x2A97, 43513 }, + { 0x2A98, 43526 }, + { 0x2A99, 68620 }, + { 0x2A9A, 68625 }, + { 0x2A9B, 68630 }, + { 0x2A9C, 68636 }, + { 0x2A9D, 43174 }, + { 0x2A9E, 43177 }, + { 0x2A9F, 43180 }, + { 0x2AA0, 43186 }, + { 0x2AA1, 31589 }, + { 0x2AA2, 31597 }, + { 0x2AA3, 31592 }, + { 0x2AA4, 69565 }, + { 0x2AA5, 69551 }, + { 0x2AA6, 64780 }, + { 0x2AA7, 69554 }, + { 0x2AA8, 64784 }, + { 0x2AA9, 69558 }, + { 0x2AAA, 43540 }, + { 0x2AAB, 34099 }, + { 0x2AAC, 43542 }, + { 0x2AAD, 34101 }, + { 0x2AAE, 31736 }, + { 0x2AAF, 55374 }, + { 0x2AB0, 55568 }, + { 0x2AB1, 55368 }, + { 0x2AB2, 55562 }, + { 0x2AB3, 55364 }, + { 0x2AB4, 55558 }, + { 0x2AB5, 55348 }, + { 0x2AB6, 55542 }, + { 0x2AB7, 55359 }, + { 0x2AB8, 55553 }, + { 0x2AB9, 55353 }, + { 0x2ABA, 55547 }, + { 0x2ABB, 31666 }, + { 0x2ABC, 31671 }, + { 0x2ABD, 36512 }, + { 0x2ABE, 55619 }, + { 0x2ABF, 36515 }, + { 0x2AC0, 55622 }, + { 0x2AC1, 36520 }, + { 0x2AC2, 55627 }, + { 0x2AC3, 36476 }, + { 0x2AC4, 55583 }, + { 0x2AC5, 36507 }, + { 0x2AC6, 55614 }, + { 0x2AC7, 36496 }, + { 0x2AC8, 55603 }, + { 0x2AC9, 36501 }, + { 0x2ACA, 55608 }, + { 0x2ACB, 36490 }, + { 0x2ACC, 55597 }, + { 0x2ACD, 36177 }, + { 0x2ACE, 36346 }, + { 0x2ACF, 30553 }, + { 0x2AD0, 30560 }, + { 0x2AD1, 30555 }, + { 0x2AD2, 30562 }, + { 0x2AD3, 36528 }, + { 0x2AD4, 55632 }, + { 0x2AD5, 36525 }, + { 0x2AD6, 55635 }, + { 0x2AD7, 55650 }, + { 0x2AD8, 55642 }, + { 0x2AD9, 40541 }, + { 0x2ADA, 65757 }, + { 0x2ADB, 69324 }, + { 0x2ADC, 40557 }, + { 0x2ADD, 67879 }, + { 0x2ADE, 22467 }, + { 0x2ADF, 22459 }, + { 0x2AE0, 22444 }, + { 0x2AE1, 75038 }, + { 0x2AE2, 56026 }, + { 0x2AE3, 31675 }, + { 0x2AE4, 56021 }, + { 0x2AE5, 31680 }, + { 0x2AE6, 9507 }, + { 0x2AE7, 22462 }, + { 0x2AE8, 22447 }, + { 0x2AE9, 22452 }, + { 0x2AEA, 31551 }, + { 0x2AEB, 31545 }, + { 0x2AEC, 31606 }, + { 0x2AED, 55483 }, + { 0x2AEE, 9026 }, + { 0x2AEF, 56068 }, + { 0x2AF0, 56073 }, + { 0x2AF1, 9075 }, + { 0x2AF2, 54952 }, + { 0x2AF3, 54948 }, + { 0x2AF4, 37646 }, + { 0x2AF5, 37635 }, + { 0x2AF6, 37616 }, + { 0x2AF7, 37623 }, + { 0x2AF8, 37626 }, + { 0x2AF9, 68642 }, + { 0x2AFA, 68648 }, + { 0x2AFB, 37629 }, + { 0x2AFC, 14466 }, + { 0x2AFD, 31661 }, + { 0x2AFE, 23397 }, + { 0x2AFF, 21230 }, + { 0x2B00, 21310 }, + { 0x2B01, 21361 }, + { 0x2B02, 22705 }, + { 0x2B03, 22732 }, + { 0x2B04, 9289 }, + { 0x2B05, 64465 }, + { 0x2B06, 44578 }, + { 0x2B07, 63292 }, + { 0x2B08, 21306 }, + { 0x2B09, 21357 }, + { 0x2B0A, 22701 }, + { 0x2B0B, 22728 }, + { 0x2B0C, 9285 }, + { 0x2B0D, 311 }, + { 0x2B0E, 68024 }, + { 0x2B0F, 68019 }, + { 0x2B10, 64366 }, + { 0x2B11, 64361 }, + { 0x2B12, 36202 }, + { 0x2B13, 36261 }, + { 0x2B14, 36254 }, + { 0x2B15, 36212 }, + { 0x2B16, 40312 }, + { 0x2B17, 40317 }, + { 0x2B18, 40307 }, + { 0x2B19, 40322 }, + { 0x2B1A, 31537 }, + { 0x2B1B, 10191 }, + { 0x2B1C, 23212 }, + { 0x2B1D, 10163 }, + { 0x2B1E, 23187 }, + { 0x2B1F, 10302 }, + { 0x2B20, 23387 }, + { 0x2B21, 23371 }, + { 0x2B22, 10287 }, + { 0x2B23, 67658 }, + { 0x2B24, 10188 }, + { 0x2B25, 10264 }, + { 0x2B26, 23287 }, + { 0x2B27, 10267 }, + { 0x2B28, 23290 }, + { 0x2B29, 10215 }, + { 0x2B2A, 10218 }, + { 0x2B2B, 23228 }, + { 0x2B2C, 10325 }, + { 0x2B2D, 23414 }, + { 0x2B2E, 10306 }, + { 0x2B2F, 23400 }, + { 0x2B30, 9212 }, + { 0x2B31, 22992 }, + { 0x2B32, 9217 }, + { 0x2B33, 9550 }, + { 0x2B34, 64644 }, + { 0x2B35, 64637 }, + { 0x2B36, 64610 }, + { 0x2B37, 64650 }, + { 0x2B38, 64403 }, + { 0x2B39, 64396 }, + { 0x2B3A, 64388 }, + { 0x2B3B, 64615 }, + { 0x2B3C, 64629 }, + { 0x2B3D, 64620 }, + { 0x2B3E, 64453 }, + { 0x2B3F, 10065 }, + { 0x2B40, 31751 }, + { 0x2B41, 42982 }, + { 0x2B42, 64446 }, + { 0x2B43, 68124 }, + { 0x2B44, 68120 }, + { 0x2B45, 64605 }, + { 0x2B46, 68270 }, + { 0x2B47, 42988 }, + { 0x2B48, 68109 }, + { 0x2B49, 23033 }, + { 0x2B4A, 64434 }, + { 0x2B4B, 64440 }, + { 0x2B4C, 68103 }, + { 0x2B50, 23277 }, + { 0x2B51, 10209 }, + { 0x2B52, 23222 }, + { 0x2B53, 10370 }, + { 0x2B54, 23470 }, + { 0x2C00, 67450 }, + { 0x2C01, 67479 }, + { 0x2C02, 67503 }, + { 0x2C03, 67579 }, + { 0x2C04, 67519 }, + { 0x2C05, 67555 }, + { 0x2C06, 67621 }, + { 0x2C07, 67523 }, + { 0x2C08, 67575 }, + { 0x2C09, 67491 }, + { 0x2C0A, 67583 }, + { 0x2C0B, 67434 }, + { 0x2C0C, 67563 }, + { 0x2C0D, 67495 }, + { 0x2C0E, 67604 }, + { 0x2C0F, 67608 }, + { 0x2C10, 67531 }, + { 0x2C11, 67459 }, + { 0x2C12, 67567 }, + { 0x2C13, 67535 }, + { 0x2C14, 67539 }, + { 0x2C15, 67571 }, + { 0x2C16, 67475 }, + { 0x2C17, 67527 }, + { 0x2C18, 67487 }, + { 0x2C19, 67463 }, + { 0x2C1A, 67438 }, + { 0x2C1B, 67499 }, + { 0x2C1C, 67471 }, + { 0x2C1D, 67559 }, + { 0x2C1E, 67467 }, + { 0x2C1F, 67515 }, + { 0x2C20, 67511 }, + { 0x2C21, 67507 }, + { 0x2C22, 67616 }, + { 0x2C23, 67446 }, + { 0x2C24, 67543 }, + { 0x2C25, 67548 }, + { 0x2C26, 67442 }, + { 0x2C27, 67594 }, + { 0x2C28, 67454 }, + { 0x2C29, 67588 }, + { 0x2C2A, 67483 }, + { 0x2C2B, 67600 }, + { 0x2C2C, 67612 }, + { 0x2C2D, 67630 }, + { 0x2C2E, 67625 }, + { 0x2C30, 67249 }, + { 0x2C31, 67278 }, + { 0x2C32, 67302 }, + { 0x2C33, 67378 }, + { 0x2C34, 67318 }, + { 0x2C35, 67354 }, + { 0x2C36, 67420 }, + { 0x2C37, 67322 }, + { 0x2C38, 67374 }, + { 0x2C39, 67290 }, + { 0x2C3A, 67382 }, + { 0x2C3B, 67233 }, + { 0x2C3C, 67362 }, + { 0x2C3D, 67294 }, + { 0x2C3E, 67403 }, + { 0x2C3F, 67407 }, + { 0x2C40, 67330 }, + { 0x2C41, 67258 }, + { 0x2C42, 67366 }, + { 0x2C43, 67334 }, + { 0x2C44, 67338 }, + { 0x2C45, 67370 }, + { 0x2C46, 67274 }, + { 0x2C47, 67326 }, + { 0x2C48, 67286 }, + { 0x2C49, 67262 }, + { 0x2C4A, 67237 }, + { 0x2C4B, 67298 }, + { 0x2C4C, 67270 }, + { 0x2C4D, 67358 }, + { 0x2C4E, 67266 }, + { 0x2C4F, 67314 }, + { 0x2C50, 67310 }, + { 0x2C51, 67306 }, + { 0x2C52, 67415 }, + { 0x2C53, 67245 }, + { 0x2C54, 67342 }, + { 0x2C55, 67347 }, + { 0x2C56, 67241 }, + { 0x2C57, 67393 }, + { 0x2C58, 67253 }, + { 0x2C59, 67387 }, + { 0x2C5A, 67282 }, + { 0x2C5B, 67399 }, + { 0x2C5C, 67411 }, + { 0x2C5D, 67429 }, + { 0x2C5E, 67424 }, + { 0x2C60, 19214 }, + { 0x2C61, 15577 }, + { 0x2C62, 19228 }, + { 0x2C63, 19682 }, + { 0x2C64, 19762 }, + { 0x2C65, 14629 }, + { 0x2C66, 16472 }, + { 0x2C67, 18936 }, + { 0x2C68, 15276 }, + { 0x2C69, 19148 }, + { 0x2C6A, 15507 }, + { 0x2C6B, 20410 }, + { 0x2C6C, 17019 }, + { 0x2C6D, 20597 }, + { 0x2C6E, 19272 }, + { 0x2C6F, 20649 }, + { 0x2C71, 16751 }, + { 0x2C72, 20235 }, + { 0x2C73, 16796 }, + { 0x2C74, 16739 }, + { 0x2C75, 20547 }, + { 0x2C76, 17312 }, + { 0x2C77, 17839 }, + { 0x2C78, 14974 }, + { 0x2C79, 17623 }, + { 0x2C7A, 15813 }, + { 0x2C7B, 18125 }, + { 0x2C7C, 20797 }, + { 0x2C7D, 54684 }, + { 0x2C80, 31044 }, + { 0x2C81, 30751 }, + { 0x2C82, 31072 }, + { 0x2C83, 30779 }, + { 0x2C84, 31084 }, + { 0x2C85, 30791 }, + { 0x2C86, 31080 }, + { 0x2C87, 30787 }, + { 0x2C88, 30922 }, + { 0x2C89, 30629 }, + { 0x2C8A, 31036 }, + { 0x2C8B, 30743 }, + { 0x2C8C, 31076 }, + { 0x2C8D, 30783 }, + { 0x2C8E, 31048 }, + { 0x2C8F, 30755 }, + { 0x2C90, 31108 }, + { 0x2C91, 30815 }, + { 0x2C92, 31088 }, + { 0x2C93, 30795 }, + { 0x2C94, 31056 }, + { 0x2C95, 30763 }, + { 0x2C96, 31092 }, + { 0x2C97, 30799 }, + { 0x2C98, 30898 }, + { 0x2C99, 30605 }, + { 0x2C9A, 30902 }, + { 0x2C9B, 30609 }, + { 0x2C9C, 30934 }, + { 0x2C9D, 30641 }, + { 0x2C9E, 30890 }, + { 0x2C9F, 30597 }, + { 0x2CA0, 30906 }, + { 0x2CA1, 30613 }, + { 0x2CA2, 30910 }, + { 0x2CA3, 30617 }, + { 0x2CA4, 31068 }, + { 0x2CA5, 30775 }, + { 0x2CA6, 31040 }, + { 0x2CA7, 30747 }, + { 0x2CA8, 30914 }, + { 0x2CA9, 30621 }, + { 0x2CAA, 30894 }, + { 0x2CAB, 30601 }, + { 0x2CAC, 30930 }, + { 0x2CAD, 30637 }, + { 0x2CAE, 31032 }, + { 0x2CAF, 30739 }, + { 0x2CB0, 31028 }, + { 0x2CB1, 30735 }, + { 0x2CB2, 31132 }, + { 0x2CB3, 30839 }, + { 0x2CB4, 30944 }, + { 0x2CB5, 30651 }, + { 0x2CB6, 31152 }, + { 0x2CB7, 30859 }, + { 0x2CB8, 31142 }, + { 0x2CB9, 30849 }, + { 0x2CBA, 31127 }, + { 0x2CBB, 30834 }, + { 0x2CBC, 31147 }, + { 0x2CBD, 30854 }, + { 0x2CBE, 30974 }, + { 0x2CBF, 30681 }, + { 0x2CC0, 31096 }, + { 0x2CC1, 30803 }, + { 0x2CC2, 31112 }, + { 0x2CC3, 30819 }, + { 0x2CC4, 30986 }, + { 0x2CC5, 30693 }, + { 0x2CC6, 30956 }, + { 0x2CC7, 30663 }, + { 0x2CC8, 31117 }, + { 0x2CC9, 30824 }, + { 0x2CCA, 31137 }, + { 0x2CCB, 30844 }, + { 0x2CCC, 30980 }, + { 0x2CCD, 30687 }, + { 0x2CCE, 30938 }, + { 0x2CCF, 30645 }, + { 0x2CD0, 31122 }, + { 0x2CD1, 30829 }, + { 0x2CD2, 30968 }, + { 0x2CD3, 30675 }, + { 0x2CD4, 30962 }, + { 0x2CD5, 30669 }, + { 0x2CD6, 30998 }, + { 0x2CD7, 30705 }, + { 0x2CD8, 30950 }, + { 0x2CD9, 30657 }, + { 0x2CDA, 30992 }, + { 0x2CDB, 30699 }, + { 0x2CDC, 31022 }, + { 0x2CDD, 30729 }, + { 0x2CDE, 31004 }, + { 0x2CDF, 30711 }, + { 0x2CE0, 31010 }, + { 0x2CE1, 30717 }, + { 0x2CE2, 31016 }, + { 0x2CE3, 30723 }, + { 0x2CE4, 30872 }, + { 0x2CE5, 30864 }, + { 0x2CE6, 30868 }, + { 0x2CE7, 30887 }, + { 0x2CE8, 30879 }, + { 0x2CE9, 30875 }, + { 0x2CEA, 30883 }, + { 0x2CF9, 30572 }, + { 0x2CFA, 30582 }, + { 0x2CFB, 30588 }, + { 0x2CFC, 30577 }, + { 0x2CFD, 31157 }, + { 0x2CFE, 30594 }, + { 0x2CFF, 31161 }, + { 0x2D00, 51786 }, + { 0x2D01, 51814 }, + { 0x2D02, 51830 }, + { 0x2D03, 51826 }, + { 0x2D04, 51790 }, + { 0x2D05, 51894 }, + { 0x2D06, 51902 }, + { 0x2D07, 51886 }, + { 0x2D08, 51798 }, + { 0x2D09, 51854 }, + { 0x2D0A, 51858 }, + { 0x2D0B, 51862 }, + { 0x2D0C, 51866 }, + { 0x2D0D, 51802 }, + { 0x2D0E, 51870 }, + { 0x2D0F, 51934 }, + { 0x2D10, 51878 }, + { 0x2D11, 51882 }, + { 0x2D12, 51890 }, + { 0x2D13, 51806 }, + { 0x2D14, 51926 }, + { 0x2D15, 51922 }, + { 0x2D16, 51914 }, + { 0x2D17, 51874 }, + { 0x2D18, 51930 }, + { 0x2D19, 51910 }, + { 0x2D1A, 51818 }, + { 0x2D1B, 51850 }, + { 0x2D1C, 51822 }, + { 0x2D1D, 51906 }, + { 0x2D1E, 51898 }, + { 0x2D1F, 51918 }, + { 0x2D20, 51834 }, + { 0x2D21, 51794 }, + { 0x2D22, 51842 }, + { 0x2D23, 51810 }, + { 0x2D24, 51838 }, + { 0x2D25, 51846 }, + { 0x2D30, 55713 }, + { 0x2D31, 55725 }, + { 0x2D32, 55789 }, + { 0x2D33, 55734 }, + { 0x2D34, 55834 }, + { 0x2D35, 55845 }, + { 0x2D36, 55740 }, + { 0x2D37, 55728 }, + { 0x2D38, 55798 }, + { 0x2D39, 55795 }, + { 0x2D3A, 55831 }, + { 0x2D3B, 55782 }, + { 0x2D3C, 55731 }, + { 0x2D3D, 55743 }, + { 0x2D3E, 55854 }, + { 0x2D3F, 55837 }, + { 0x2D40, 55737 }, + { 0x2D41, 55840 }, + { 0x2D42, 55850 }, + { 0x2D43, 55804 }, + { 0x2D44, 55722 }, + { 0x2D45, 55807 }, + { 0x2D46, 55870 }, + { 0x2D47, 55758 }, + { 0x2D48, 55858 }, + { 0x2D49, 55716 }, + { 0x2D4A, 55825 }, + { 0x2D4B, 55882 }, + { 0x2D4C, 55878 }, + { 0x2D4D, 55746 }, + { 0x2D4E, 55749 }, + { 0x2D4F, 55752 }, + { 0x2D50, 55866 }, + { 0x2D51, 55874 }, + { 0x2D52, 55755 }, + { 0x2D53, 55719 }, + { 0x2D54, 55761 }, + { 0x2D55, 55810 }, + { 0x2D56, 55801 }, + { 0x2D57, 55862 }, + { 0x2D58, 55785 }, + { 0x2D59, 55764 }, + { 0x2D5A, 55816 }, + { 0x2D5B, 55813 }, + { 0x2D5C, 55767 }, + { 0x2D5D, 55819 }, + { 0x2D5E, 55792 }, + { 0x2D5F, 55822 }, + { 0x2D60, 55770 }, + { 0x2D61, 55773 }, + { 0x2D62, 55776 }, + { 0x2D63, 55779 }, + { 0x2D64, 55886 }, + { 0x2D65, 55828 }, + { 0x2D6F, 55890 }, + { 0x2D80, 50999 }, + { 0x2D81, 51011 }, + { 0x2D82, 51140 }, + { 0x2D83, 51170 }, + { 0x2D84, 51542 }, + { 0x2D85, 50762 }, + { 0x2D86, 51227 }, + { 0x2D87, 50810 }, + { 0x2D88, 51032 }, + { 0x2D89, 51488 }, + { 0x2D8A, 51672 }, + { 0x2D8B, 51344 }, + { 0x2D8C, 50837 }, + { 0x2D8D, 51407 }, + { 0x2D8E, 50939 }, + { 0x2D8F, 51569 }, + { 0x2D90, 51395 }, + { 0x2D91, 51500 }, + { 0x2D92, 51074 }, + { 0x2D93, 51422 }, + { 0x2D94, 51428 }, + { 0x2D95, 51629 }, + { 0x2D96, 51425 }, + { 0x2DA0, 51173 }, + { 0x2DA1, 51185 }, + { 0x2DA2, 51179 }, + { 0x2DA3, 51548 }, + { 0x2DA4, 51551 }, + { 0x2DA5, 51176 }, + { 0x2DA6, 51182 }, + { 0x2DA8, 50777 }, + { 0x2DA9, 50789 }, + { 0x2DAA, 50783 }, + { 0x2DAB, 51368 }, + { 0x2DAC, 51371 }, + { 0x2DAD, 50780 }, + { 0x2DAE, 50786 }, + { 0x2DB0, 51350 }, + { 0x2DB1, 51362 }, + { 0x2DB2, 51356 }, + { 0x2DB3, 51614 }, + { 0x2DB4, 51617 }, + { 0x2DB5, 51353 }, + { 0x2DB6, 51359 }, + { 0x2DB8, 51374 }, + { 0x2DB9, 51386 }, + { 0x2DBA, 51380 }, + { 0x2DBB, 51620 }, + { 0x2DBC, 51623 }, + { 0x2DBD, 51377 }, + { 0x2DBE, 51383 }, + { 0x2DC0, 51119 }, + { 0x2DC1, 51131 }, + { 0x2DC2, 51125 }, + { 0x2DC3, 51530 }, + { 0x2DC4, 51533 }, + { 0x2DC5, 51122 }, + { 0x2DC6, 51128 }, + { 0x2DC8, 50978 }, + { 0x2DC9, 50990 }, + { 0x2DCA, 50984 }, + { 0x2DCB, 51473 }, + { 0x2DCC, 51476 }, + { 0x2DCD, 50981 }, + { 0x2DCE, 50987 }, + { 0x2DD0, 51299 }, + { 0x2DD1, 51311 }, + { 0x2DD2, 51305 }, + { 0x2DD3, 51599 }, + { 0x2DD4, 51602 }, + { 0x2DD5, 51302 }, + { 0x2DD6, 51308 }, + { 0x2DD8, 50894 }, + { 0x2DD9, 50906 }, + { 0x2DDA, 50900 }, + { 0x2DDB, 51437 }, + { 0x2DDC, 51440 }, + { 0x2DDD, 50897 }, + { 0x2DDE, 50903 }, + { 0x2DE0, 58034 }, + { 0x2DE1, 58082 }, + { 0x2DE2, 58103 }, + { 0x2DE3, 58038 }, + { 0x2DE4, 58119 }, + { 0x2DE5, 58090 }, + { 0x2DE6, 58070 }, + { 0x2DE7, 58042 }, + { 0x2DE8, 58046 }, + { 0x2DE9, 58050 }, + { 0x2DEA, 58030 }, + { 0x2DEB, 58074 }, + { 0x2DEC, 58054 }, + { 0x2DED, 58058 }, + { 0x2DEE, 58078 }, + { 0x2DEF, 58062 }, + { 0x2DF0, 58111 }, + { 0x2DF1, 58099 }, + { 0x2DF2, 58107 }, + { 0x2DF3, 58135 }, + { 0x2DF4, 58123 }, + { 0x2DF5, 58131 }, + { 0x2DF6, 58026 }, + { 0x2DF7, 58066 }, + { 0x2DF8, 58127 }, + { 0x2DF9, 58155 }, + { 0x2DFA, 58115 }, + { 0x2DFB, 58086 }, + { 0x2DFC, 58144 }, + { 0x2DFD, 58139 }, + { 0x2DFE, 58094 }, + { 0x2DFF, 58149 }, + { 0x2E00, 21801 }, + { 0x2E01, 21783 }, + { 0x2E02, 9477 }, + { 0x2E03, 22004 }, + { 0x2E04, 9353 }, + { 0x2E05, 21874 }, + { 0x2E06, 35672 }, + { 0x2E07, 35666 }, + { 0x2E08, 31539 }, + { 0x2E09, 9480 }, + { 0x2E0A, 22007 }, + { 0x2E0B, 35670 }, + { 0x2E0C, 9377 }, + { 0x2E0D, 21904 }, + { 0x2E0E, 63378 }, + { 0x2E0F, 69268 }, + { 0x2E10, 31783 }, + { 0x2E11, 55488 }, + { 0x2E12, 69569 }, + { 0x2E13, 31535 }, + { 0x2E14, 63298 }, + { 0x2E15, 44620 }, + { 0x2E16, 31542 }, + { 0x2E17, 31658 }, + { 0x2E18, 53360 }, + { 0x2E19, 9626 }, + { 0x2E1A, 33425 }, + { 0x2E1B, 23017 }, + { 0x2E1C, 9148 }, + { 0x2E1D, 21751 }, + { 0x2E1E, 23009 }, + { 0x2E1F, 23013 }, + { 0x2E20, 9452 }, + { 0x2E21, 21979 }, + { 0x2E22, 7737 }, + { 0x2E23, 7750 }, + { 0x2E24, 30258 }, + { 0x2E25, 30271 }, + { 0x2E26, 9439 }, + { 0x2E27, 21964 }, + { 0x2E28, 9369 }, + { 0x2E29, 21896 }, + { 0x2E2A, 7772 }, + { 0x2E2B, 7155 }, + { 0x2E2C, 43556 }, + { 0x2E2D, 9091 }, + { 0x2E2E, 55502 }, + { 0x2E2F, 56091 }, + { 0x2E30, 9704 }, + { 0x2E80, 5603 }, + { 0x2E81, 5510 }, + { 0x2E82, 5606 }, + { 0x2E83, 5610 }, + { 0x2E84, 5614 }, + { 0x2E85, 5600 }, + { 0x2E86, 5346 }, + { 0x2E87, 5577 }, + { 0x2E88, 5539 }, + { 0x2E89, 5543 }, + { 0x2E8A, 5638 }, + { 0x2E8B, 5477 }, + { 0x2E8C, 5558 }, + { 0x2E8D, 5562 }, + { 0x2E8E, 5441 }, + { 0x2E8F, 5445 }, + { 0x2E90, 5453 }, + { 0x2E91, 5449 }, + { 0x2E92, 5566 }, + { 0x2E93, 5626 }, + { 0x2E94, 5569 }, + { 0x2E95, 5573 }, + { 0x2E96, 5531 }, + { 0x2E97, 5535 }, + { 0x2E98, 5429 }, + { 0x2E99, 5403 }, + { 0x2E9B, 5507 }, + { 0x2E9C, 5406 }, + { 0x2E9D, 5471 }, + { 0x2E9E, 5513 }, + { 0x2E9F, 5597 }, + { 0x2EA0, 5635 }, + { 0x2EA1, 5583 }, + { 0x2EA2, 5587 }, + { 0x2EA3, 5423 }, + { 0x2EA4, 5392 }, + { 0x2EA5, 5396 }, + { 0x2EA6, 5641 }, + { 0x2EA7, 5349 }, + { 0x2EA8, 5352 }, + { 0x2EA9, 5438 }, + { 0x2EAA, 5412 }, + { 0x2EAB, 5370 }, + { 0x2EAC, 5618 }, + { 0x2EAD, 5622 }, + { 0x2EAE, 5591 }, + { 0x2EAF, 5480 }, + { 0x2EB0, 5715 }, + { 0x2EB1, 5373 }, + { 0x2EB2, 5377 }, + { 0x2EB3, 5385 }, + { 0x2EB4, 5381 }, + { 0x2EB5, 5468 }, + { 0x2EB6, 5555 }, + { 0x2EB7, 5400 }, + { 0x2EB8, 5367 }, + { 0x2EB9, 5389 }, + { 0x2EBA, 5499 }, + { 0x2EBB, 5503 }, + { 0x2EBC, 5465 }, + { 0x2EBD, 5594 }, + { 0x2EBE, 5519 }, + { 0x2EBF, 5523 }, + { 0x2EC0, 5527 }, + { 0x2EC1, 5580 }, + { 0x2EC2, 5632 }, + { 0x2EC3, 5491 }, + { 0x2EC4, 5495 }, + { 0x2EC5, 5671 }, + { 0x2EC6, 5647 }, + { 0x2EC7, 5435 }, + { 0x2EC8, 5739 }, + { 0x2EC9, 5727 }, + { 0x2ECA, 5426 }, + { 0x2ECB, 5679 }, + { 0x2ECC, 5651 }, + { 0x2ECD, 5483 }, + { 0x2ECE, 5487 }, + { 0x2ECF, 5420 }, + { 0x2ED0, 5699 }, + { 0x2ED1, 5457 }, + { 0x2ED2, 5461 }, + { 0x2ED3, 5707 }, + { 0x2ED4, 5695 }, + { 0x2ED5, 5547 }, + { 0x2ED6, 5551 }, + { 0x2ED7, 5474 }, + { 0x2ED8, 5409 }, + { 0x2ED9, 5743 }, + { 0x2EDA, 5703 }, + { 0x2EDB, 5719 }, + { 0x2EDC, 5667 }, + { 0x2EDD, 5355 }, + { 0x2EDE, 5359 }, + { 0x2EDF, 5363 }, + { 0x2EE0, 5663 }, + { 0x2EE1, 5432 }, + { 0x2EE2, 5723 }, + { 0x2EE3, 5417 }, + { 0x2EE4, 5516 }, + { 0x2EE5, 5687 }, + { 0x2EE6, 5675 }, + { 0x2EE7, 5711 }, + { 0x2EE8, 5655 }, + { 0x2EE9, 5659 }, + { 0x2EEA, 5691 }, + { 0x2EEB, 5752 }, + { 0x2EEC, 5683 }, + { 0x2EED, 5756 }, + { 0x2EEE, 5731 }, + { 0x2EEF, 5760 }, + { 0x2EF0, 5735 }, + { 0x2EF1, 5629 }, + { 0x2EF2, 5764 }, + { 0x2EF3, 5748 }, + { 0x2F00, 33501 }, + { 0x2F01, 33669 }, + { 0x2F02, 33459 }, + { 0x2F03, 33860 }, + { 0x2F04, 33981 }, + { 0x2F05, 33639 }, + { 0x2F06, 33531 }, + { 0x2F07, 33486 }, + { 0x2F08, 33489 }, + { 0x2F09, 33663 }, + { 0x2F0A, 33792 }, + { 0x2F0B, 33789 }, + { 0x2F0C, 33588 }, + { 0x2F0D, 33780 }, + { 0x2F0E, 33480 }, + { 0x2F0F, 33896 }, + { 0x2F10, 33688 }, + { 0x2F11, 33819 }, + { 0x2F12, 33831 }, + { 0x2F13, 33753 }, + { 0x2F14, 33881 }, + { 0x2F15, 33834 }, + { 0x2F16, 33962 }, + { 0x2F17, 33528 }, + { 0x2F18, 34081 }, + { 0x2F19, 33707 }, + { 0x2F1A, 33774 }, + { 0x2F1B, 34048 }, + { 0x2F1C, 33756 }, + { 0x2F1D, 33828 }, + { 0x2F1E, 34078 }, + { 0x2F1F, 33786 }, + { 0x2F20, 34051 }, + { 0x2F21, 33434 }, + { 0x2F22, 33437 }, + { 0x2F23, 34030 }, + { 0x2F24, 33447 }, + { 0x2F25, 33917 }, + { 0x2F26, 33771 }, + { 0x2F27, 33701 }, + { 0x2F28, 33645 }, + { 0x2F29, 33869 }, + { 0x2F2A, 33654 }, + { 0x2F2B, 33938 }, + { 0x2F2C, 33990 }, + { 0x2F2D, 34066 }, + { 0x2F2E, 33839 }, + { 0x2F2F, 33750 }, + { 0x2F30, 34045 }, + { 0x2F31, 34006 }, + { 0x2F32, 33462 }, + { 0x2F33, 33856 }, + { 0x2F34, 33948 }, + { 0x2F35, 33675 }, + { 0x2F36, 33534 }, + { 0x2F37, 33848 }, + { 0x2F38, 33450 }, + { 0x2F39, 33872 }, + { 0x2F3A, 34021 }, + { 0x2F3B, 33719 }, + { 0x2F3C, 33813 }, + { 0x2F3D, 34036 }, + { 0x2F3E, 33585 }, + { 0x2F3F, 33630 }, + { 0x2F40, 33935 }, + { 0x2F41, 33507 }, + { 0x2F42, 33978 }, + { 0x2F43, 33941 }, + { 0x2F44, 33444 }, + { 0x2F45, 33993 }, + { 0x2F46, 33495 }, + { 0x2F47, 33525 }, + { 0x2F48, 33519 }, + { 0x2F49, 33682 }, + { 0x2F4A, 33731 }, + { 0x2F4B, 33651 }, + { 0x2F4C, 33722 }, + { 0x2F4D, 33783 }, + { 0x2F4E, 34015 }, + { 0x2F4F, 33430 }, + { 0x2F50, 34027 }, + { 0x2F51, 33477 }, + { 0x2F52, 33573 }, + { 0x2F53, 33887 }, + { 0x2F54, 33908 }, + { 0x2F55, 33604 }, + { 0x2F56, 33576 }, + { 0x2F57, 33959 }, + { 0x2F58, 33952 }, + { 0x2F59, 33625 }, + { 0x2F5A, 33866 }, + { 0x2F5B, 33601 }, + { 0x2F5C, 33453 }, + { 0x2F5D, 33456 }, + { 0x2F5E, 34069 }, + { 0x2F5F, 33648 }, + { 0x2F60, 33822 }, + { 0x2F61, 33728 }, + { 0x2F62, 33893 }, + { 0x2F63, 33666 }, + { 0x2F64, 33538 }, + { 0x2F65, 33795 }, + { 0x2F66, 33556 }, + { 0x2F67, 34072 }, + { 0x2F68, 33944 }, + { 0x2F69, 33914 }, + { 0x2F6A, 33716 }, + { 0x2F6B, 33582 }, + { 0x2F6C, 33471 }, + { 0x2F6D, 33878 }, + { 0x2F6E, 33759 }, + { 0x2F6F, 33890 }, + { 0x2F70, 33987 }, + { 0x2F71, 33905 }, + { 0x2F72, 33807 }, + { 0x2F73, 33567 }, + { 0x2F74, 33884 }, + { 0x2F75, 33929 }, + { 0x2F76, 33698 }, + { 0x2F77, 33713 }, + { 0x2F78, 33483 }, + { 0x2F79, 33492 }, + { 0x2F7A, 33842 }, + { 0x2F7B, 34033 }, + { 0x2F7C, 33498 }, + { 0x2F7D, 33441 }, + { 0x2F7E, 33692 }, + { 0x2F7F, 33465 }, + { 0x2F80, 33768 }, + { 0x2F81, 33679 }, + { 0x2F82, 34063 }, + { 0x2F83, 33710 }, + { 0x2F84, 33923 }, + { 0x2F85, 33972 }, + { 0x2F86, 34000 }, + { 0x2F87, 33975 }, + { 0x2F88, 33550 }, + { 0x2F89, 34075 }, + { 0x2F8A, 33777 }, + { 0x2F8B, 33810 }, + { 0x2F8C, 33899 }, + { 0x2F8D, 33966 }, + { 0x2F8E, 33765 }, + { 0x2F8F, 33737 }, + { 0x2F90, 34024 }, + { 0x2F91, 33741 }, + { 0x2F92, 33522 }, + { 0x2F93, 33642 }, + { 0x2F94, 33984 }, + { 0x2F95, 34012 }, + { 0x2F96, 33541 }, + { 0x2F97, 33504 }, + { 0x2F98, 33926 }, + { 0x2F99, 33845 }, + { 0x2F9A, 33513 }, + { 0x2F9B, 33516 }, + { 0x2F9C, 33610 }, + { 0x2F9D, 33553 }, + { 0x2F9E, 33564 }, + { 0x2F9F, 33932 }, + { 0x2FA0, 34042 }, + { 0x2FA1, 33734 }, + { 0x2FA2, 33570 }, + { 0x2FA3, 33747 }, + { 0x2FA4, 34087 }, + { 0x2FA5, 34054 }, + { 0x2FA6, 33619 }, + { 0x2FA7, 33672 }, + { 0x2FA8, 33616 }, + { 0x2FA9, 33825 }, + { 0x2FAA, 33863 }, + { 0x2FAB, 33851 }, + { 0x2FAC, 33695 }, + { 0x2FAD, 33547 }, + { 0x2FAE, 33920 }, + { 0x2FAF, 33598 }, + { 0x2FB0, 34039 }, + { 0x2FB1, 33996 }, + { 0x2FB2, 33660 }, + { 0x2FB3, 33875 }, + { 0x2FB4, 33657 }, + { 0x2FB5, 33744 }, + { 0x2FB6, 33474 }, + { 0x2FB7, 33468 }, + { 0x2FB8, 33633 }, + { 0x2FB9, 34060 }, + { 0x2FBA, 33816 }, + { 0x2FBB, 33561 }, + { 0x2FBC, 33725 }, + { 0x2FBD, 33622 }, + { 0x2FBE, 33798 }, + { 0x2FBF, 34090 }, + { 0x2FC0, 34057 }, + { 0x2FC1, 33804 }, + { 0x2FC2, 33607 }, + { 0x2FC3, 33544 }, + { 0x2FC4, 33704 }, + { 0x2FC5, 33579 }, + { 0x2FC6, 33911 }, + { 0x2FC7, 33636 }, + { 0x2FC8, 34018 }, + { 0x2FC9, 33969 }, + { 0x2FCA, 33762 }, + { 0x2FCB, 34084 }, + { 0x2FCC, 33613 }, + { 0x2FCD, 34003 }, + { 0x2FCE, 33592 }, + { 0x2FCF, 33510 }, + { 0x2FD0, 33685 }, + { 0x2FD1, 33595 }, + { 0x2FD2, 33902 }, + { 0x2FD3, 33956 }, + { 0x2FD4, 34009 }, + { 0x2FD5, 33801 }, + { 0x2FF0, 69175 }, + { 0x2FF1, 69189 }, + { 0x2FF2, 69181 }, + { 0x2FF3, 69195 }, + { 0x2FF4, 69170 }, + { 0x2FF5, 69213 }, + { 0x2FF6, 69219 }, + { 0x2FF7, 69207 }, + { 0x2FF8, 69232 }, + { 0x2FF9, 69239 }, + { 0x2FFA, 69225 }, + { 0x2FFB, 69203 }, + { 0x3000, 68678 }, + { 0x3001, 68672 }, + { 0x3002, 68665 }, + { 0x3003, 10538 }, + { 0x3004, 53362 }, + { 0x3005, 68698 }, + { 0x3006, 68687 }, + { 0x3007, 68680 }, + { 0x3008, 9204 }, + { 0x3009, 21788 }, + { 0x300A, 9357 }, + { 0x300B, 21878 }, + { 0x300C, 9350 }, + { 0x300D, 21871 }, + { 0x300E, 9330 }, + { 0x300F, 21851 }, + { 0x3010, 9227 }, + { 0x3011, 21820 }, + { 0x3012, 35661 }, + { 0x3013, 9121 }, + { 0x3014, 9443 }, + { 0x3015, 21968 }, + { 0x3016, 9343 }, + { 0x3017, 21864 }, + { 0x3018, 9338 }, + { 0x3019, 21859 }, + { 0x301A, 9334 }, + { 0x301B, 21855 }, + { 0x301C, 10063 }, + { 0x301D, 55478 }, + { 0x301E, 31576 }, + { 0x301F, 6033 }, + { 0x3020, 35663 }, + { 0x3021, 52741 }, + { 0x3022, 52750 }, + { 0x3023, 52768 }, + { 0x3024, 52756 }, + { 0x3025, 52753 }, + { 0x3026, 52744 }, + { 0x3027, 52765 }, + { 0x3028, 52762 }, + { 0x3029, 52759 }, + { 0x302A, 68674 }, + { 0x302B, 68683 }, + { 0x302C, 68694 }, + { 0x302D, 68690 }, + { 0x302E, 32170 }, + { 0x302F, 31884 }, + { 0x3030, 10078 }, + { 0x3031, 56034 }, + { 0x3032, 56050 }, + { 0x3033, 56044 }, + { 0x3034, 56057 }, + { 0x3035, 56038 }, + { 0x3036, 39456 }, + { 0x3037, 68701 }, + { 0x3038, 52747 }, + { 0x3039, 52774 }, + { 0x303A, 52771 }, + { 0x303B, 56098 }, + { 0x303C, 9594 }, + { 0x303D, 9628 }, + { 0x303E, 69103 }, + { 0x303F, 68668 }, + { 0x3041, 53242 }, + { 0x3042, 53020 }, + { 0x3043, 53250 }, + { 0x3044, 53026 }, + { 0x3045, 53258 }, + { 0x3046, 53035 }, + { 0x3047, 53246 }, + { 0x3048, 53023 }, + { 0x3049, 53254 }, + { 0x304A, 53032 }, + { 0x304B, 53098 }, + { 0x304C, 53068 }, + { 0x304D, 53104 }, + { 0x304E, 53074 }, + { 0x304F, 53110 }, + { 0x3050, 53080 }, + { 0x3051, 53101 }, + { 0x3052, 53071 }, + { 0x3053, 53107 }, + { 0x3054, 53077 }, + { 0x3055, 53173 }, + { 0x3056, 53227 }, + { 0x3057, 53179 }, + { 0x3058, 53233 }, + { 0x3059, 53185 }, + { 0x305A, 53239 }, + { 0x305B, 53176 }, + { 0x305C, 53230 }, + { 0x305D, 53182 }, + { 0x305E, 53236 }, + { 0x305F, 53188 }, + { 0x3060, 53053 }, + { 0x3061, 53194 }, + { 0x3062, 53059 }, + { 0x3063, 53270 }, + { 0x3064, 53200 }, + { 0x3065, 53065 }, + { 0x3066, 53191 }, + { 0x3067, 53056 }, + { 0x3068, 53197 }, + { 0x3069, 53062 }, + { 0x306A, 53128 }, + { 0x306B, 53134 }, + { 0x306C, 53140 }, + { 0x306D, 53131 }, + { 0x306E, 53137 }, + { 0x306F, 53083 }, + { 0x3070, 53038 }, + { 0x3071, 53143 }, + { 0x3072, 53089 }, + { 0x3073, 53044 }, + { 0x3074, 53149 }, + { 0x3075, 53095 }, + { 0x3076, 53050 }, + { 0x3077, 53155 }, + { 0x3078, 53086 }, + { 0x3079, 53041 }, + { 0x307A, 53146 }, + { 0x307B, 53092 }, + { 0x307C, 53047 }, + { 0x307D, 53152 }, + { 0x307E, 53113 }, + { 0x307F, 53119 }, + { 0x3080, 53125 }, + { 0x3081, 53116 }, + { 0x3082, 53122 }, + { 0x3083, 53278 }, + { 0x3084, 53218 }, + { 0x3085, 53286 }, + { 0x3086, 53224 }, + { 0x3087, 53282 }, + { 0x3088, 53221 }, + { 0x3089, 53158 }, + { 0x308A, 53164 }, + { 0x308B, 53170 }, + { 0x308C, 53161 }, + { 0x308D, 53167 }, + { 0x308E, 53274 }, + { 0x308F, 53206 }, + { 0x3090, 53212 }, + { 0x3091, 53209 }, + { 0x3092, 53215 }, + { 0x3093, 53029 }, + { 0x3094, 53203 }, + { 0x3095, 53262 }, + { 0x3096, 53266 }, + { 0x3099, 58335 }, + { 0x309A, 58340 }, + { 0x309B, 75125 }, + { 0x309C, 75133 }, + { 0x309D, 53297 }, + { 0x309E, 53290 }, + { 0x309F, 53294 }, + { 0x30A0, 75122 }, + { 0x30A1, 53600 }, + { 0x30A2, 53366 }, + { 0x30A3, 53608 }, + { 0x30A4, 53372 }, + { 0x30A5, 53616 }, + { 0x30A6, 53381 }, + { 0x30A7, 53604 }, + { 0x30A8, 53369 }, + { 0x30A9, 53612 }, + { 0x30AA, 53378 }, + { 0x30AB, 53444 }, + { 0x30AC, 53414 }, + { 0x30AD, 53450 }, + { 0x30AE, 53420 }, + { 0x30AF, 53456 }, + { 0x30B0, 53426 }, + { 0x30B1, 53447 }, + { 0x30B2, 53417 }, + { 0x30B3, 53453 }, + { 0x30B4, 53423 }, + { 0x30B5, 53519 }, + { 0x30B6, 53585 }, + { 0x30B7, 53525 }, + { 0x30B8, 53591 }, + { 0x30B9, 53531 }, + { 0x30BA, 53597 }, + { 0x30BB, 53522 }, + { 0x30BC, 53588 }, + { 0x30BD, 53528 }, + { 0x30BE, 53594 }, + { 0x30BF, 53534 }, + { 0x30C0, 53399 }, + { 0x30C1, 53540 }, + { 0x30C2, 53405 }, + { 0x30C3, 53692 }, + { 0x30C4, 53546 }, + { 0x30C5, 53411 }, + { 0x30C6, 53537 }, + { 0x30C7, 53402 }, + { 0x30C8, 53543 }, + { 0x30C9, 53408 }, + { 0x30CA, 53474 }, + { 0x30CB, 53480 }, + { 0x30CC, 53486 }, + { 0x30CD, 53477 }, + { 0x30CE, 53483 }, + { 0x30CF, 53429 }, + { 0x30D0, 53384 }, + { 0x30D1, 53489 }, + { 0x30D2, 53435 }, + { 0x30D3, 53390 }, + { 0x30D4, 53495 }, + { 0x30D5, 53441 }, + { 0x30D6, 53396 }, + { 0x30D7, 53501 }, + { 0x30D8, 53432 }, + { 0x30D9, 53387 }, + { 0x30DA, 53492 }, + { 0x30DB, 53438 }, + { 0x30DC, 53393 }, + { 0x30DD, 53498 }, + { 0x30DE, 53459 }, + { 0x30DF, 53465 }, + { 0x30E0, 53471 }, + { 0x30E1, 53462 }, + { 0x30E2, 53468 }, + { 0x30E3, 53700 }, + { 0x30E4, 53576 }, + { 0x30E5, 53708 }, + { 0x30E6, 53582 }, + { 0x30E7, 53704 }, + { 0x30E8, 53579 }, + { 0x30E9, 53504 }, + { 0x30EA, 53510 }, + { 0x30EB, 53516 }, + { 0x30EC, 53507 }, + { 0x30ED, 53513 }, + { 0x30EE, 53696 }, + { 0x30EF, 53564 }, + { 0x30F0, 53570 }, + { 0x30F1, 53567 }, + { 0x30F2, 53573 }, + { 0x30F3, 53375 }, + { 0x30F4, 53561 }, + { 0x30F5, 53640 }, + { 0x30F6, 53644 }, + { 0x30F7, 53549 }, + { 0x30F8, 53555 }, + { 0x30F9, 53552 }, + { 0x30FA, 53558 }, + { 0x30FB, 53712 }, + { 0x30FC, 75129 }, + { 0x30FD, 53722 }, + { 0x30FE, 53715 }, + { 0x30FF, 53719 }, + { 0x3105, 45589 }, + { 0x3106, 45631 }, + { 0x3107, 45622 }, + { 0x3108, 45601 }, + { 0x3109, 45595 }, + { 0x310A, 45643 }, + { 0x310B, 45625 }, + { 0x310C, 45619 }, + { 0x310D, 45604 }, + { 0x310E, 45616 }, + { 0x310F, 45607 }, + { 0x3110, 45613 }, + { 0x3111, 45634 }, + { 0x3112, 45652 }, + { 0x3113, 45727 }, + { 0x3114, 45673 }, + { 0x3115, 45724 }, + { 0x3116, 45637 }, + { 0x3117, 45655 }, + { 0x3118, 45592 }, + { 0x3119, 45640 }, + { 0x311A, 45586 }, + { 0x311B, 45628 }, + { 0x311C, 45598 }, + { 0x311D, 45679 }, + { 0x311E, 45658 }, + { 0x311F, 45682 }, + { 0x3120, 45667 }, + { 0x3121, 45721 }, + { 0x3122, 45664 }, + { 0x3123, 45685 }, + { 0x3124, 45733 }, + { 0x3125, 45739 }, + { 0x3126, 45688 }, + { 0x3127, 45610 }, + { 0x3128, 45646 }, + { 0x3129, 45706 }, + { 0x312A, 45649 }, + { 0x312B, 45712 }, + { 0x312C, 45691 }, + { 0x312D, 45697 }, + { 0x3131, 31996 }, + { 0x3132, 32095 }, + { 0x3133, 32065 }, + { 0x3134, 31978 }, + { 0x3135, 32071 }, + { 0x3136, 32074 }, + { 0x3137, 31999 }, + { 0x3138, 32098 }, + { 0x3139, 31984 }, + { 0x313A, 32113 }, + { 0x313B, 32083 }, + { 0x313C, 32086 }, + { 0x313D, 32038 }, + { 0x313E, 32140 }, + { 0x313F, 32137 }, + { 0x3140, 32080 }, + { 0x3141, 31975 }, + { 0x3142, 31981 }, + { 0x3143, 32062 }, + { 0x3144, 32035 }, + { 0x3145, 31954 }, + { 0x3146, 32026 }, + { 0x3147, 31972 }, + { 0x3148, 31966 }, + { 0x3149, 32050 }, + { 0x314A, 32008 }, + { 0x314B, 32011 }, + { 0x314C, 32020 }, + { 0x314D, 32017 }, + { 0x314E, 31969 }, + { 0x314F, 31891 }, + { 0x3150, 31906 }, + { 0x3151, 31927 }, + { 0x3152, 31948 }, + { 0x3153, 31909 }, + { 0x3154, 31894 }, + { 0x3155, 31951 }, + { 0x3156, 31930 }, + { 0x3157, 31900 }, + { 0x3158, 31918 }, + { 0x3159, 31942 }, + { 0x315A, 31915 }, + { 0x315B, 31936 }, + { 0x315C, 31903 }, + { 0x315D, 31945 }, + { 0x315E, 31921 }, + { 0x315F, 31924 }, + { 0x3160, 31939 }, + { 0x3161, 31912 }, + { 0x3162, 31933 }, + { 0x3163, 31897 }, + { 0x3164, 31889 }, + { 0x3165, 32059 }, + { 0x3166, 32104 }, + { 0x3167, 32032 }, + { 0x3168, 32128 }, + { 0x3169, 32161 }, + { 0x316A, 32116 }, + { 0x316B, 32149 }, + { 0x316C, 32134 }, + { 0x316D, 32164 }, + { 0x316E, 32068 }, + { 0x316F, 32029 }, + { 0x3170, 32125 }, + { 0x3171, 32119 }, + { 0x3172, 32107 }, + { 0x3173, 32110 }, + { 0x3174, 32155 }, + { 0x3175, 32158 }, + { 0x3176, 32077 }, + { 0x3177, 32131 }, + { 0x3178, 32122 }, + { 0x3179, 32167 }, + { 0x317A, 32089 }, + { 0x317B, 32044 }, + { 0x317C, 32092 }, + { 0x317D, 32047 }, + { 0x317E, 32041 }, + { 0x317F, 32014 }, + { 0x3180, 32056 }, + { 0x3181, 32023 }, + { 0x3182, 32143 }, + { 0x3183, 32152 }, + { 0x3184, 32146 }, + { 0x3185, 32053 }, + { 0x3186, 32101 }, + { 0x3187, 31987 }, + { 0x3188, 32002 }, + { 0x3189, 31957 }, + { 0x318A, 32005 }, + { 0x318B, 31990 }, + { 0x318C, 31960 }, + { 0x318D, 31963 }, + { 0x318E, 31993 }, + { 0x3190, 69162 }, + { 0x3191, 69166 }, + { 0x3192, 69110 }, + { 0x3193, 69118 }, + { 0x3194, 69138 }, + { 0x3195, 69122 }, + { 0x3196, 69114 }, + { 0x3197, 69154 }, + { 0x3198, 69142 }, + { 0x3199, 69130 }, + { 0x319A, 69158 }, + { 0x319B, 69134 }, + { 0x319C, 69146 }, + { 0x319D, 69150 }, + { 0x319E, 69126 }, + { 0x319F, 69106 }, + { 0x31A0, 45670 }, + { 0x31A1, 45730 }, + { 0x31A2, 45709 }, + { 0x31A3, 45694 }, + { 0x31A4, 45676 }, + { 0x31A5, 45742 }, + { 0x31A6, 45718 }, + { 0x31A7, 45754 }, + { 0x31A8, 45703 }, + { 0x31A9, 45736 }, + { 0x31AA, 45745 }, + { 0x31AB, 45757 }, + { 0x31AC, 45700 }, + { 0x31AD, 45748 }, + { 0x31AE, 45760 }, + { 0x31AF, 45763 }, + { 0x31B0, 45661 }, + { 0x31B1, 45715 }, + { 0x31B2, 45751 }, + { 0x31B3, 45766 }, + { 0x31B4, 45578 }, + { 0x31B5, 45582 }, + { 0x31B6, 45574 }, + { 0x31B7, 45570 }, + { 0x31C0, 5256 }, + { 0x31C1, 5295 }, + { 0x31C2, 5298 }, + { 0x31C3, 5301 }, + { 0x31C4, 5286 }, + { 0x31C5, 5313 }, + { 0x31C6, 5304 }, + { 0x31C7, 5262 }, + { 0x31C8, 5331 }, + { 0x31C9, 5340 }, + { 0x31CA, 5307 }, + { 0x31CB, 5334 }, + { 0x31CC, 5325 }, + { 0x31CD, 5310 }, + { 0x31CE, 5337 }, + { 0x31CF, 5244 }, + { 0x31D0, 5241 }, + { 0x31D1, 5253 }, + { 0x31D2, 5247 }, + { 0x31D3, 5280 }, + { 0x31D4, 5238 }, + { 0x31D5, 5265 }, + { 0x31D6, 5259 }, + { 0x31D7, 5289 }, + { 0x31D8, 5319 }, + { 0x31D9, 5283 }, + { 0x31DA, 5277 }, + { 0x31DB, 5268 }, + { 0x31DC, 5274 }, + { 0x31DD, 5292 }, + { 0x31DE, 5322 }, + { 0x31DF, 5316 }, + { 0x31E0, 5328 }, + { 0x31E1, 5343 }, + { 0x31E2, 5271 }, + { 0x31E3, 5250 }, + { 0x31F0, 53648 }, + { 0x31F1, 53680 }, + { 0x31F2, 53684 }, + { 0x31F3, 53688 }, + { 0x31F4, 53656 }, + { 0x31F5, 53620 }, + { 0x31F6, 53628 }, + { 0x31F7, 53636 }, + { 0x31F8, 53624 }, + { 0x31F9, 53632 }, + { 0x31FA, 53652 }, + { 0x31FB, 53660 }, + { 0x31FC, 53668 }, + { 0x31FD, 53676 }, + { 0x31FE, 53664 }, + { 0x31FF, 53672 }, + { 0x3200, 74845 }, + { 0x3201, 74824 }, + { 0x3202, 74852 }, + { 0x3203, 74838 }, + { 0x3204, 74817 }, + { 0x3205, 74831 }, + { 0x3206, 74785 }, + { 0x3207, 74810 }, + { 0x3208, 74792 }, + { 0x3209, 74859 }, + { 0x320A, 74866 }, + { 0x320B, 74880 }, + { 0x320C, 74873 }, + { 0x320D, 74803 }, + { 0x320E, 74848 }, + { 0x320F, 74827 }, + { 0x3210, 74855 }, + { 0x3211, 74841 }, + { 0x3212, 74820 }, + { 0x3213, 74834 }, + { 0x3214, 74788 }, + { 0x3215, 74813 }, + { 0x3216, 74795 }, + { 0x3217, 74862 }, + { 0x3218, 74869 }, + { 0x3219, 74883 }, + { 0x321A, 74876 }, + { 0x321B, 74806 }, + { 0x321C, 74799 }, + { 0x321D, 74892 }, + { 0x321E, 74887 }, + { 0x3220, 74929 }, + { 0x3221, 74941 }, + { 0x3222, 75001 }, + { 0x3223, 74953 }, + { 0x3224, 74950 }, + { 0x3225, 74932 }, + { 0x3226, 74992 }, + { 0x3227, 74980 }, + { 0x3228, 74965 }, + { 0x3229, 74938 }, + { 0x322A, 74959 }, + { 0x322B, 74947 }, + { 0x322C, 75004 }, + { 0x322D, 74974 }, + { 0x322E, 74986 }, + { 0x322F, 74977 }, + { 0x3230, 74935 }, + { 0x3231, 74995 }, + { 0x3232, 74956 }, + { 0x3233, 75007 }, + { 0x3234, 74962 }, + { 0x3235, 75010 }, + { 0x3236, 75022 }, + { 0x3237, 75034 }, + { 0x3238, 74983 }, + { 0x3239, 75025 }, + { 0x323A, 74944 }, + { 0x323B, 74998 }, + { 0x323C, 75028 }, + { 0x323D, 75031 }, + { 0x323E, 75019 }, + { 0x323F, 75013 }, + { 0x3240, 75016 }, + { 0x3241, 74968 }, + { 0x3242, 74971 }, + { 0x3243, 74989 }, + { 0x3250, 69269 }, + { 0x3251, 39399 }, + { 0x3252, 39407 }, + { 0x3253, 39431 }, + { 0x3254, 39415 }, + { 0x3255, 39411 }, + { 0x3256, 39403 }, + { 0x3257, 39427 }, + { 0x3258, 39423 }, + { 0x3259, 39419 }, + { 0x325A, 39354 }, + { 0x325B, 39357 }, + { 0x325C, 39365 }, + { 0x325D, 39389 }, + { 0x325E, 39373 }, + { 0x325F, 39369 }, + { 0x3260, 39256 }, + { 0x3261, 39235 }, + { 0x3262, 39263 }, + { 0x3263, 39249 }, + { 0x3264, 39228 }, + { 0x3265, 39242 }, + { 0x3266, 39196 }, + { 0x3267, 39217 }, + { 0x3268, 39203 }, + { 0x3269, 39270 }, + { 0x326A, 39277 }, + { 0x326B, 39291 }, + { 0x326C, 39284 }, + { 0x326D, 39210 }, + { 0x326E, 39259 }, + { 0x326F, 39238 }, + { 0x3270, 39266 }, + { 0x3271, 39252 }, + { 0x3272, 39231 }, + { 0x3273, 39245 }, + { 0x3274, 39199 }, + { 0x3275, 39220 }, + { 0x3276, 39206 }, + { 0x3277, 39273 }, + { 0x3278, 39280 }, + { 0x3279, 39294 }, + { 0x327A, 39287 }, + { 0x327B, 39213 }, + { 0x327C, 39302 }, + { 0x327D, 39298 }, + { 0x327E, 39224 }, + { 0x327F, 34096 }, + { 0x3280, 39623 }, + { 0x3281, 39635 }, + { 0x3282, 39710 }, + { 0x3283, 39647 }, + { 0x3284, 39644 }, + { 0x3285, 39626 }, + { 0x3286, 39701 }, + { 0x3287, 39683 }, + { 0x3288, 39671 }, + { 0x3289, 39632 }, + { 0x328A, 39665 }, + { 0x328B, 39641 }, + { 0x328C, 39713 }, + { 0x328D, 39677 }, + { 0x328E, 39689 }, + { 0x328F, 39680 }, + { 0x3290, 39629 }, + { 0x3291, 39704 }, + { 0x3292, 39650 }, + { 0x3293, 39728 }, + { 0x3294, 39668 }, + { 0x3295, 39731 }, + { 0x3296, 39755 }, + { 0x3297, 39764 }, + { 0x3298, 39686 }, + { 0x3299, 39722 }, + { 0x329A, 39662 }, + { 0x329B, 39719 }, + { 0x329C, 39746 }, + { 0x329D, 39752 }, + { 0x329E, 39695 }, + { 0x329F, 39749 }, + { 0x32A0, 39656 }, + { 0x32A1, 39674 }, + { 0x32A2, 39638 }, + { 0x32A3, 39725 }, + { 0x32A4, 39653 }, + { 0x32A5, 39716 }, + { 0x32A6, 39620 }, + { 0x32A7, 39659 }, + { 0x32A8, 39698 }, + { 0x32A9, 39737 }, + { 0x32AA, 39740 }, + { 0x32AB, 39707 }, + { 0x32AC, 39758 }, + { 0x32AD, 39761 }, + { 0x32AE, 39743 }, + { 0x32AF, 39734 }, + { 0x32B0, 39692 }, + { 0x32B1, 39361 }, + { 0x32B2, 39385 }, + { 0x32B3, 39381 }, + { 0x32B4, 39377 }, + { 0x32B5, 39312 }, + { 0x32B6, 39315 }, + { 0x32B7, 39323 }, + { 0x32B8, 39347 }, + { 0x32B9, 39331 }, + { 0x32BA, 39327 }, + { 0x32BB, 39319 }, + { 0x32BC, 39343 }, + { 0x32BD, 39339 }, + { 0x32BE, 39335 }, + { 0x32BF, 39309 }, + { 0x32C0, 69073 }, + { 0x32C1, 69088 }, + { 0x32C2, 69063 }, + { 0x32C3, 69058 }, + { 0x32C4, 68893 }, + { 0x32C5, 69053 }, + { 0x32C6, 69048 }, + { 0x32C7, 69068 }, + { 0x32C8, 69098 }, + { 0x32C9, 69078 }, + { 0x32CA, 69093 }, + { 0x32CB, 69083 }, + { 0x32CC, 35949 }, + { 0x32CD, 36112 }, + { 0x32CE, 35939 }, + { 0x32CF, 40924 }, + { 0x32D0, 39471 }, + { 0x32D1, 39477 }, + { 0x32D2, 39483 }, + { 0x32D3, 39474 }, + { 0x32D4, 39480 }, + { 0x32D5, 39501 }, + { 0x32D6, 39507 }, + { 0x32D7, 39513 }, + { 0x32D8, 39504 }, + { 0x32D9, 39510 }, + { 0x32DA, 39561 }, + { 0x32DB, 39567 }, + { 0x32DC, 39573 }, + { 0x32DD, 39564 }, + { 0x32DE, 39570 }, + { 0x32DF, 39576 }, + { 0x32E0, 39582 }, + { 0x32E1, 39588 }, + { 0x32E2, 39579 }, + { 0x32E3, 39585 }, + { 0x32E4, 39531 }, + { 0x32E5, 39537 }, + { 0x32E6, 39543 }, + { 0x32E7, 39534 }, + { 0x32E8, 39540 }, + { 0x32E9, 39486 }, + { 0x32EA, 39492 }, + { 0x32EB, 39498 }, + { 0x32EC, 39489 }, + { 0x32ED, 39495 }, + { 0x32EE, 39516 }, + { 0x32EF, 39522 }, + { 0x32F0, 39528 }, + { 0x32F1, 39519 }, + { 0x32F2, 39525 }, + { 0x32F3, 39603 }, + { 0x32F4, 39609 }, + { 0x32F5, 39606 }, + { 0x32F6, 39546 }, + { 0x32F7, 39552 }, + { 0x32F8, 39558 }, + { 0x32F9, 39549 }, + { 0x32FA, 39555 }, + { 0x32FB, 39591 }, + { 0x32FC, 39597 }, + { 0x32FD, 39594 }, + { 0x32FE, 39600 }, + { 0x3300, 36363 }, + { 0x3301, 36365 }, + { 0x3302, 36290 }, + { 0x3303, 36157 }, + { 0x3304, 36375 }, + { 0x3305, 36171 }, + { 0x3306, 36155 }, + { 0x3307, 36421 }, + { 0x3308, 36296 }, + { 0x3309, 36188 }, + { 0x330A, 36190 }, + { 0x330B, 36326 }, + { 0x330C, 36393 }, + { 0x330D, 36395 }, + { 0x330E, 36300 }, + { 0x330F, 36298 }, + { 0x3310, 36167 }, + { 0x3311, 36302 }, + { 0x3312, 36379 }, + { 0x3313, 36391 }, + { 0x3314, 36175 }, + { 0x3315, 36459 }, + { 0x3316, 36463 }, + { 0x3317, 36451 }, + { 0x3318, 36369 }, + { 0x3319, 36447 }, + { 0x331A, 36453 }, + { 0x331B, 36397 }, + { 0x331C, 36328 }, + { 0x331D, 36377 }, + { 0x331E, 36330 }, + { 0x331F, 36415 }, + { 0x3320, 36445 }, + { 0x3321, 36417 }, + { 0x3322, 36353 }, + { 0x3323, 36355 }, + { 0x3324, 36294 }, + { 0x3325, 36161 }, + { 0x3326, 36163 }, + { 0x3327, 36153 }, + { 0x3328, 36186 }, + { 0x3329, 36336 }, + { 0x332A, 36304 }, + { 0x332B, 36441 }, + { 0x332C, 36338 }, + { 0x332D, 36389 }, + { 0x332E, 36457 }, + { 0x332F, 36385 }, + { 0x3330, 36194 }, + { 0x3331, 36159 }, + { 0x3332, 36423 }, + { 0x3333, 36373 }, + { 0x3334, 36419 }, + { 0x3335, 36308 }, + { 0x3336, 36449 }, + { 0x3337, 36192 }, + { 0x3338, 36383 }, + { 0x3339, 36371 }, + { 0x333A, 36342 }, + { 0x333B, 36340 }, + { 0x333C, 36292 }, + { 0x333D, 36387 }, + { 0x333E, 36367 }, + { 0x333F, 36120 }, + { 0x3340, 36344 }, + { 0x3341, 36306 }, + { 0x3342, 36169 }, + { 0x3343, 36401 }, + { 0x3344, 36334 }, + { 0x3345, 36332 }, + { 0x3346, 36381 }, + { 0x3347, 36403 }, + { 0x3348, 36409 }, + { 0x3349, 36184 }, + { 0x334A, 36455 }, + { 0x334B, 36182 }, + { 0x334C, 36407 }, + { 0x334D, 36405 }, + { 0x334E, 36359 }, + { 0x334F, 36361 }, + { 0x3350, 36288 }, + { 0x3351, 36411 }, + { 0x3352, 36198 }, + { 0x3353, 36351 }, + { 0x3354, 36413 }, + { 0x3355, 36196 }, + { 0x3356, 36443 }, + { 0x3357, 36357 }, + { 0x3358, 68940 }, + { 0x3359, 68898 }, + { 0x335A, 68916 }, + { 0x335B, 68958 }, + { 0x335C, 68928 }, + { 0x335D, 68922 }, + { 0x335E, 68904 }, + { 0x335F, 68952 }, + { 0x3360, 68946 }, + { 0x3361, 68934 }, + { 0x3362, 68910 }, + { 0x3363, 68964 }, + { 0x3364, 68970 }, + { 0x3365, 69012 }, + { 0x3366, 69000 }, + { 0x3367, 68982 }, + { 0x3368, 68988 }, + { 0x3369, 69018 }, + { 0x336A, 68994 }, + { 0x336B, 69006 }, + { 0x336C, 68976 }, + { 0x336D, 69024 }, + { 0x336E, 69030 }, + { 0x336F, 69042 }, + { 0x3370, 69036 }, + { 0x3371, 36122 }, + { 0x3372, 35925 }, + { 0x3373, 35907 }, + { 0x3374, 36088 }, + { 0x3375, 36059 }, + { 0x3376, 36066 }, + { 0x3377, 35931 }, + { 0x3378, 35936 }, + { 0x3379, 35933 }, + { 0x337A, 35957 }, + { 0x337B, 36100 }, + { 0x337C, 36104 }, + { 0x337D, 36108 }, + { 0x337E, 36096 }, + { 0x337F, 36461 }, + { 0x3380, 36063 }, + { 0x3381, 36047 }, + { 0x3382, 36013 }, + { 0x3383, 35992 }, + { 0x3384, 35959 }, + { 0x3385, 35961 }, + { 0x3386, 35994 }, + { 0x3387, 35943 }, + { 0x3388, 36090 }, + { 0x3389, 36173 }, + { 0x338A, 36068 }, + { 0x338B, 36049 }, + { 0x338C, 36016 }, + { 0x338D, 36019 }, + { 0x338E, 35999 }, + { 0x338F, 35963 }, + { 0x3390, 35953 }, + { 0x3391, 36124 }, + { 0x3392, 36130 }, + { 0x3393, 36116 }, + { 0x3394, 36151 }, + { 0x3395, 36022 }, + { 0x3396, 36001 }, + { 0x3397, 35929 }, + { 0x3398, 35967 }, + { 0x3399, 35941 }, + { 0x339A, 36051 }, + { 0x339B, 36025 }, + { 0x339C, 36003 }, + { 0x339D, 35915 }, + { 0x339E, 35969 }, + { 0x339F, 36008 }, + { 0x33A0, 35920 }, + { 0x33A1, 35898 }, + { 0x33A2, 35977 }, + { 0x33A3, 36005 }, + { 0x33A4, 35917 }, + { 0x33A5, 35895 }, + { 0x33A6, 35971 }, + { 0x33A7, 35886 }, + { 0x33A8, 35890 }, + { 0x33A9, 36061 }, + { 0x33AA, 36126 }, + { 0x33AB, 36136 }, + { 0x33AC, 36118 }, + { 0x33AD, 36140 }, + { 0x33AE, 36142 }, + { 0x33AF, 36146 }, + { 0x33B0, 36076 }, + { 0x33B1, 36053 }, + { 0x33B2, 36028 }, + { 0x33B3, 36011 }, + { 0x33B4, 36078 }, + { 0x33B5, 36055 }, + { 0x33B6, 36031 }, + { 0x33B7, 36037 }, + { 0x33B8, 35982 }, + { 0x33B9, 36039 }, + { 0x33BA, 36080 }, + { 0x33BB, 36057 }, + { 0x33BC, 36034 }, + { 0x33BD, 36042 }, + { 0x33BE, 35984 }, + { 0x33BF, 36044 }, + { 0x33C0, 35880 }, + { 0x33C1, 35883 }, + { 0x33C2, 35905 }, + { 0x33C3, 35909 }, + { 0x33C4, 35911 }, + { 0x33C5, 35913 }, + { 0x33C6, 35876 }, + { 0x33C7, 35923 }, + { 0x33C8, 35927 }, + { 0x33C9, 35945 }, + { 0x33CA, 35947 }, + { 0x33CB, 35951 }, + { 0x33CC, 35955 }, + { 0x33CD, 35965 }, + { 0x33CE, 35974 }, + { 0x33CF, 35980 }, + { 0x33D0, 35986 }, + { 0x33D1, 35988 }, + { 0x33D2, 36128 }, + { 0x33D3, 35990 }, + { 0x33D4, 35996 }, + { 0x33D5, 36132 }, + { 0x33D6, 36134 }, + { 0x33D7, 36070 }, + { 0x33D8, 36072 }, + { 0x33D9, 36138 }, + { 0x33DA, 36074 }, + { 0x33DB, 36082 }, + { 0x33DC, 36084 }, + { 0x33DD, 36086 }, + { 0x33DE, 35901 }, + { 0x33DF, 35872 }, + { 0x33E0, 68707 }, + { 0x33E1, 68725 }, + { 0x33E2, 68761 }, + { 0x33E3, 68737 }, + { 0x33E4, 68731 }, + { 0x33E5, 68713 }, + { 0x33E6, 68755 }, + { 0x33E7, 68749 }, + { 0x33E8, 68743 }, + { 0x33E9, 68719 }, + { 0x33EA, 68767 }, + { 0x33EB, 68779 }, + { 0x33EC, 68821 }, + { 0x33ED, 68809 }, + { 0x33EE, 68791 }, + { 0x33EF, 68797 }, + { 0x33F0, 68827 }, + { 0x33F1, 68803 }, + { 0x33F2, 68815 }, + { 0x33F3, 68785 }, + { 0x33F4, 68839 }, + { 0x33F5, 68851 }, + { 0x33F6, 68887 }, + { 0x33F7, 68863 }, + { 0x33F8, 68857 }, + { 0x33F9, 68845 }, + { 0x33FA, 68881 }, + { 0x33FB, 68875 }, + { 0x33FC, 68869 }, + { 0x33FD, 68773 }, + { 0x33FE, 68833 }, + { 0x33FF, 36114 }, + { 0x4DC0, 52824 }, + { 0x4DC1, 52838 }, + { 0x4DC2, 52975 }, + { 0x4DC3, 52945 }, + { 0x4DC4, 52921 }, + { 0x4DC5, 52927 }, + { 0x4DC6, 52777 }, + { 0x4DC7, 52907 }, + { 0x4DC8, 52883 }, + { 0x4DC9, 52942 }, + { 0x4DCA, 52880 }, + { 0x4DCB, 53002 }, + { 0x4DCC, 52987 }, + { 0x4DCD, 52864 }, + { 0x4DCE, 52911 }, + { 0x4DCF, 52984 }, + { 0x4DD0, 52958 }, + { 0x4DD1, 52843 }, + { 0x4DD2, 52924 }, + { 0x4DD3, 53017 }, + { 0x4DD4, 52895 }, + { 0x4DD5, 52853 }, + { 0x4DD6, 52971 }, + { 0x4DD7, 52904 }, + { 0x4DD8, 52968 }, + { 0x4DD9, 52860 }, + { 0x4DDA, 52876 }, + { 0x4DDB, 52868 }, + { 0x4DDC, 52799 }, + { 0x4DDD, 52819 }, + { 0x4DDE, 52965 }, + { 0x4DDF, 52933 }, + { 0x4DE0, 52918 }, + { 0x4DE1, 52856 }, + { 0x4DE2, 52939 }, + { 0x4DE3, 52952 }, + { 0x4DE4, 52785 }, + { 0x4DE5, 52993 }, + { 0x4DE6, 53011 }, + { 0x4DE7, 53005 }, + { 0x4DE8, 52930 }, + { 0x4DE9, 52936 }, + { 0x4DEA, 53014 }, + { 0x4DEB, 52899 }, + { 0x4DEC, 52961 }, + { 0x4DED, 52914 }, + { 0x4DEE, 52996 }, + { 0x4DEF, 52781 }, + { 0x4DF0, 52999 }, + { 0x4DF1, 52815 }, + { 0x4DF2, 52810 }, + { 0x4DF3, 52804 }, + { 0x4DF4, 53008 }, + { 0x4DF5, 52829 }, + { 0x4DF6, 52949 }, + { 0x4DF7, 52834 }, + { 0x4DF8, 52789 }, + { 0x4DF9, 52794 }, + { 0x4DFA, 52981 }, + { 0x4DFB, 52990 }, + { 0x4DFC, 52872 }, + { 0x4DFD, 52887 }, + { 0x4DFE, 52849 }, + { 0x4DFF, 52891 }, + { 0x5000, 634 }, + { 0x5001, 637 }, + { 0x5002, 520 }, + { 0x5003, 631 }, + { 0x5004, 1300 }, + { 0x5005, 1303 }, + { 0x5006, 628 }, + { 0x5007, 1297 }, + { 0x5008, 529 }, + { 0x5009, 532 }, + { 0x500A, 514 }, + { 0x500B, 526 }, + { 0x500C, 2011 }, + { 0x500D, 802 }, + { 0x500E, 2008 }, + { 0x500F, 721 }, + { 0x5010, 724 }, + { 0x5011, 523 }, + { 0x5012, 718 }, + { 0x5013, 586 }, + { 0x5014, 517 }, + { 0x5015, 829 }, + { 0x5016, 910 }, + { 0x5017, 913 }, + { 0x5018, 541 }, + { 0x5019, 907 }, + { 0x501A, 2341 }, + { 0x501B, 2344 }, + { 0x501C, 904 }, + { 0x501D, 2338 }, + { 0x501E, 874 }, + { 0x501F, 877 }, + { 0x5020, 535 }, + { 0x5021, 871 }, + { 0x5022, 2350 }, + { 0x5023, 925 }, + { 0x5024, 2347 }, + { 0x5025, 919 }, + { 0x5026, 922 }, + { 0x5027, 544 }, + { 0x5028, 916 }, + { 0x5029, 901 }, + { 0x502A, 538 }, + { 0x502B, 898 }, + { 0x502C, 934 }, + { 0x502D, 937 }, + { 0x502E, 547 }, + { 0x502F, 928 }, + { 0x5030, 2353 }, + { 0x5031, 931 }, + { 0x5032, 946 }, + { 0x5033, 949 }, + { 0x5034, 550 }, + { 0x5035, 940 }, + { 0x5036, 2356 }, + { 0x5037, 943 }, + { 0x5038, 1705 }, + { 0x5039, 1708 }, + { 0x503A, 730 }, + { 0x503B, 1702 }, + { 0x503C, 3274 }, + { 0x503D, 1699 }, + { 0x503E, 3271 }, + { 0x503F, 1693 }, + { 0x5040, 1696 }, + { 0x5041, 727 }, + { 0x5042, 1690 }, + { 0x5043, 3280 }, + { 0x5044, 1720 }, + { 0x5045, 3277 }, + { 0x5046, 1714 }, + { 0x5047, 1717 }, + { 0x5048, 733 }, + { 0x5049, 1711 }, + { 0x504A, 1729 }, + { 0x504B, 1732 }, + { 0x504C, 736 }, + { 0x504D, 1723 }, + { 0x504E, 3283 }, + { 0x504F, 1726 }, + { 0x5050, 1741 }, + { 0x5051, 1744 }, + { 0x5052, 739 }, + { 0x5053, 1735 }, + { 0x5054, 3286 }, + { 0x5055, 1738 }, + { 0x5056, 2299 }, + { 0x5057, 2302 }, + { 0x5058, 886 }, + { 0x5059, 2296 }, + { 0x505A, 3709 }, + { 0x505B, 3712 }, + { 0x505C, 2293 }, + { 0x505D, 3706 }, + { 0x505E, 2281 }, + { 0x505F, 2284 }, + { 0x5060, 880 }, + { 0x5061, 2278 }, + { 0x5062, 3718 }, + { 0x5063, 2314 }, + { 0x5064, 3715 }, + { 0x5065, 2308 }, + { 0x5066, 2311 }, + { 0x5067, 889 }, + { 0x5068, 2305 }, + { 0x5069, 2290 }, + { 0x506A, 883 }, + { 0x506B, 2287 }, + { 0x506C, 2323 }, + { 0x506D, 2326 }, + { 0x506E, 892 }, + { 0x506F, 2317 }, + { 0x5070, 3721 }, + { 0x5071, 2320 }, + { 0x5072, 2332 }, + { 0x5073, 2335 }, + { 0x5074, 895 }, + { 0x5075, 2329 }, + { 0x5076, 2959 }, + { 0x5077, 2962 }, + { 0x5078, 1561 }, + { 0x5079, 2956 }, + { 0x507A, 3871 }, + { 0x507B, 2953 }, + { 0x507C, 3868 }, + { 0x507D, 2947 }, + { 0x507E, 2950 }, + { 0x507F, 1558 }, + { 0x5080, 2944 }, + { 0x5081, 2968 }, + { 0x5082, 2971 }, + { 0x5083, 1564 }, + { 0x5084, 2965 }, + { 0x5085, 2980 }, + { 0x5086, 2983 }, + { 0x5087, 1567 }, + { 0x5088, 2974 }, + { 0x5089, 3874 }, + { 0x508A, 2977 }, + { 0x508B, 2992 }, + { 0x508C, 2995 }, + { 0x508D, 1570 }, + { 0x508E, 2986 }, + { 0x508F, 3877 }, + { 0x5090, 2989 }, + { 0x5091, 2647 }, + { 0x5092, 2650 }, + { 0x5093, 1252 }, + { 0x5094, 2644 }, + { 0x5095, 3793 }, + { 0x5096, 2641 }, + { 0x5097, 3790 }, + { 0x5098, 2635 }, + { 0x5099, 2638 }, + { 0x509A, 1249 }, + { 0x509B, 2632 }, + { 0x509C, 3799 }, + { 0x509D, 2662 }, + { 0x509E, 3796 }, + { 0x509F, 2656 }, + { 0x50A0, 2659 }, + { 0x50A1, 1255 }, + { 0x50A2, 2653 }, + { 0x50A3, 2671 }, + { 0x50A4, 2674 }, + { 0x50A5, 1258 }, + { 0x50A6, 2665 }, + { 0x50A7, 3802 }, + { 0x50A8, 2668 }, + { 0x50A9, 2683 }, + { 0x50AA, 1261 }, + { 0x50AB, 2677 }, + { 0x50AC, 3805 }, + { 0x50AD, 2680 }, + { 0x50AE, 1513 }, + { 0x50AF, 1516 }, + { 0x50B0, 691 }, + { 0x50B1, 1510 }, + { 0x50B2, 2929 }, + { 0x50B3, 1507 }, + { 0x50B4, 2926 }, + { 0x50B5, 1486 }, + { 0x50B6, 1489 }, + { 0x50B7, 685 }, + { 0x50B8, 1483 }, + { 0x50B9, 2935 }, + { 0x50BA, 2938 }, + { 0x50BB, 1528 }, + { 0x50BC, 2932 }, + { 0x50BD, 1522 }, + { 0x50BE, 1525 }, + { 0x50BF, 694 }, + { 0x50C0, 1519 }, + { 0x50C1, 1492 }, + { 0x50C2, 688 }, + { 0x50C3, 1537 }, + { 0x50C4, 1540 }, + { 0x50C5, 697 }, + { 0x50C6, 1531 }, + { 0x50C7, 2941 }, + { 0x50C8, 1534 }, + { 0x50C9, 1546 }, + { 0x50CA, 1549 }, + { 0x50CB, 700 }, + { 0x50CC, 1543 }, + { 0x50CD, 1108 }, + { 0x50CE, 1111 }, + { 0x50CF, 592 }, + { 0x50D0, 1105 }, + { 0x50D1, 1099 }, + { 0x50D2, 1102 }, + { 0x50D3, 589 }, + { 0x50D4, 1096 }, + { 0x50D5, 1117 }, + { 0x50D6, 595 }, + { 0x50D7, 1114 }, + { 0x50D8, 1126 }, + { 0x50D9, 1129 }, + { 0x50DA, 598 }, + { 0x50DB, 1120 }, + { 0x50DC, 2494 }, + { 0x50DD, 1123 }, + { 0x50DE, 1135 }, + { 0x50DF, 1138 }, + { 0x50E0, 601 }, + { 0x50E1, 1132 }, + { 0x50E2, 2035 }, + { 0x50E3, 2038 }, + { 0x50E4, 808 }, + { 0x50E5, 2032 }, + { 0x50E6, 3523 }, + { 0x50E7, 3526 }, + { 0x50E8, 2029 }, + { 0x50E9, 3520 }, + { 0x50EA, 2017 }, + { 0x50EB, 2020 }, + { 0x50EC, 805 }, + { 0x50ED, 2014 }, + { 0x50EE, 2044 }, + { 0x50EF, 2047 }, + { 0x50F0, 811 }, + { 0x50F1, 2041 }, + { 0x50F2, 2026 }, + { 0x50F3, 2023 }, + { 0x50F4, 2056 }, + { 0x50F5, 2059 }, + { 0x50F6, 814 }, + { 0x50F7, 2050 }, + { 0x50F8, 3529 }, + { 0x50F9, 2053 }, + { 0x50FA, 2068 }, + { 0x50FB, 2071 }, + { 0x50FC, 817 }, + { 0x50FD, 2062 }, + { 0x50FE, 3532 }, + { 0x50FF, 2065 }, + { 0x5100, 1066 }, + { 0x5101, 1069 }, + { 0x5102, 577 }, + { 0x5103, 1063 }, + { 0x5104, 2485 }, + { 0x5105, 1060 }, + { 0x5106, 2482 }, + { 0x5107, 1033 }, + { 0x5108, 1036 }, + { 0x5109, 571 }, + { 0x510A, 1030 }, + { 0x510B, 2488 }, + { 0x510C, 1081 }, + { 0x510D, 1075 }, + { 0x510E, 1078 }, + { 0x510F, 580 }, + { 0x5110, 1072 }, + { 0x5111, 1057 }, + { 0x5112, 574 }, + { 0x5113, 1054 }, + { 0x5114, 1090 }, + { 0x5115, 1093 }, + { 0x5116, 583 }, + { 0x5117, 1084 }, + { 0x5118, 2491 }, + { 0x5119, 1087 }, + { 0x511A, 1978 }, + { 0x511B, 1981 }, + { 0x511C, 793 }, + { 0x511D, 1975 }, + { 0x511E, 3505 }, + { 0x511F, 1972 }, + { 0x5120, 3502 }, + { 0x5121, 1960 }, + { 0x5122, 1963 }, + { 0x5123, 787 }, + { 0x5124, 1957 }, + { 0x5125, 3511 }, + { 0x5126, 3514 }, + { 0x5127, 1993 }, + { 0x5128, 3508 }, + { 0x5129, 1987 }, + { 0x512A, 1990 }, + { 0x512B, 796 }, + { 0x512C, 1984 }, + { 0x512D, 1969 }, + { 0x512E, 790 }, + { 0x512F, 1966 }, + { 0x5130, 2002 }, + { 0x5131, 2005 }, + { 0x5132, 799 }, + { 0x5133, 1996 }, + { 0x5134, 3517 }, + { 0x5135, 1999 }, + { 0x5136, 2452 }, + { 0x5137, 2455 }, + { 0x5138, 1045 }, + { 0x5139, 2449 }, + { 0x513A, 3742 }, + { 0x513B, 2446 }, + { 0x513C, 3739 }, + { 0x513D, 2434 }, + { 0x513E, 2437 }, + { 0x513F, 1039 }, + { 0x5140, 2431 }, + { 0x5141, 3748 }, + { 0x5142, 2467 }, + { 0x5143, 3745 }, + { 0x5144, 2461 }, + { 0x5145, 2464 }, + { 0x5146, 1048 }, + { 0x5147, 2458 }, + { 0x5148, 2443 }, + { 0x5149, 1042 }, + { 0x514A, 2440 }, + { 0x514B, 2476 }, + { 0x514C, 2479 }, + { 0x514D, 1051 }, + { 0x514E, 2470 }, + { 0x514F, 3751 }, + { 0x5150, 2473 }, + { 0x5151, 3019 }, + { 0x5152, 3022 }, + { 0x5153, 1579 }, + { 0x5154, 3016 }, + { 0x5155, 3880 }, + { 0x5156, 3013 }, + { 0x5157, 3001 }, + { 0x5158, 3004 }, + { 0x5159, 1573 }, + { 0x515A, 2998 }, + { 0x515B, 3028 }, + { 0x515C, 3031 }, + { 0x515D, 1582 }, + { 0x515E, 3025 }, + { 0x515F, 3010 }, + { 0x5160, 1576 }, + { 0x5161, 3007 }, + { 0x5162, 3040 }, + { 0x5163, 3043 }, + { 0x5164, 1585 }, + { 0x5165, 3034 }, + { 0x5166, 3883 }, + { 0x5167, 3037 }, + { 0x5168, 2707 }, + { 0x5169, 2710 }, + { 0x516A, 1270 }, + { 0x516B, 2704 }, + { 0x516C, 3811 }, + { 0x516D, 3814 }, + { 0x516E, 2701 }, + { 0x516F, 3808 }, + { 0x5170, 2689 }, + { 0x5171, 2692 }, + { 0x5172, 1264 }, + { 0x5173, 2686 }, + { 0x5174, 3817 }, + { 0x5175, 2722 }, + { 0x5176, 2716 }, + { 0x5177, 2719 }, + { 0x5178, 2713 }, + { 0x5179, 2698 }, + { 0x517A, 1267 }, + { 0x517B, 2695 }, + { 0x517C, 2725 }, + { 0x517D, 1609 }, + { 0x517E, 1612 }, + { 0x517F, 709 }, + { 0x5180, 1606 }, + { 0x5181, 3079 }, + { 0x5182, 1603 }, + { 0x5183, 3076 }, + { 0x5184, 1555 }, + { 0x5185, 703 }, + { 0x5186, 1552 }, + { 0x5187, 3178 }, + { 0x5188, 1651 }, + { 0x5189, 3175 }, + { 0x518A, 1630 }, + { 0x518B, 1633 }, + { 0x518C, 712 }, + { 0x518D, 1627 }, + { 0x518E, 1591 }, + { 0x518F, 706 }, + { 0x5190, 1588 }, + { 0x5191, 1660 }, + { 0x5192, 1663 }, + { 0x5193, 715 }, + { 0x5194, 1654 }, + { 0x5195, 3181 }, + { 0x5196, 1657 }, + { 0x5197, 2593 }, + { 0x5198, 2596 }, + { 0x5199, 1237 }, + { 0x519A, 2590 }, + { 0x519B, 3775 }, + { 0x519C, 2587 }, + { 0x519D, 3772 }, + { 0x519E, 2575 }, + { 0x519F, 2578 }, + { 0x51A0, 1231 }, + { 0x51A1, 2572 }, + { 0x51A2, 3781 }, + { 0x51A3, 2605 }, + { 0x51A4, 3778 }, + { 0x51A5, 2602 }, + { 0x51A6, 1240 }, + { 0x51A7, 2599 }, + { 0x51A8, 2584 }, + { 0x51A9, 1234 }, + { 0x51AA, 2581 }, + { 0x51AB, 2614 }, + { 0x51AC, 2617 }, + { 0x51AD, 1243 }, + { 0x51AE, 2608 }, + { 0x51AF, 3784 }, + { 0x51B0, 2611 }, + { 0x51B1, 2626 }, + { 0x51B2, 2629 }, + { 0x51B3, 1246 }, + { 0x51B4, 2620 }, + { 0x51B5, 3787 }, + { 0x51B6, 2623 }, + { 0x51B7, 1441 }, + { 0x51B8, 1444 }, + { 0x51B9, 673 }, + { 0x51BA, 1438 }, + { 0x51BB, 2863 }, + { 0x51BC, 2866 }, + { 0x51BD, 1435 }, + { 0x51BE, 2860 }, + { 0x51BF, 1423 }, + { 0x51C0, 1426 }, + { 0x51C1, 667 }, + { 0x51C2, 1420 }, + { 0x51C3, 2872 }, + { 0x51C4, 2875 }, + { 0x51C5, 1456 }, + { 0x51C6, 2869 }, + { 0x51C7, 1450 }, + { 0x51C8, 1453 }, + { 0x51C9, 676 }, + { 0x51CA, 1447 }, + { 0x51CB, 1432 }, + { 0x51CC, 670 }, + { 0x51CD, 1429 }, + { 0x51CE, 1465 }, + { 0x51CF, 1468 }, + { 0x51D0, 679 }, + { 0x51D1, 1459 }, + { 0x51D2, 2878 }, + { 0x51D3, 1462 }, + { 0x51D4, 1477 }, + { 0x51D5, 1480 }, + { 0x51D6, 682 }, + { 0x51D7, 1471 }, + { 0x51D8, 2881 }, + { 0x51D9, 1474 }, + { 0x51DA, 1180 }, + { 0x51DB, 1183 }, + { 0x51DC, 610 }, + { 0x51DD, 1177 }, + { 0x51DE, 2551 }, + { 0x51DF, 2554 }, + { 0x51E0, 1174 }, + { 0x51E1, 2548 }, + { 0x51E2, 1144 }, + { 0x51E3, 1147 }, + { 0x51E4, 604 }, + { 0x51E5, 1141 }, + { 0x51E6, 2560 }, + { 0x51E7, 2563 }, + { 0x51E8, 1195 }, + { 0x51E9, 2557 }, + { 0x51EA, 1189 }, + { 0x51EB, 1192 }, + { 0x51EC, 613 }, + { 0x51ED, 1186 }, + { 0x51EE, 1153 }, + { 0x51EF, 1156 }, + { 0x51F0, 607 }, + { 0x51F1, 1150 }, + { 0x51F2, 1204 }, + { 0x51F3, 1207 }, + { 0x51F4, 616 }, + { 0x51F5, 1198 }, + { 0x51F6, 2566 }, + { 0x51F7, 1201 }, + { 0x51F8, 1390 }, + { 0x51F9, 1393 }, + { 0x51FA, 658 }, + { 0x51FB, 1387 }, + { 0x51FC, 2848 }, + { 0x51FD, 1384 }, + { 0x51FE, 2845 }, + { 0x51FF, 1369 }, + { 0x5200, 1372 }, + { 0x5201, 652 }, + { 0x5202, 1366 }, + { 0x5203, 2854 }, + { 0x5204, 1405 }, + { 0x5205, 2851 }, + { 0x5206, 1399 }, + { 0x5207, 1402 }, + { 0x5208, 661 }, + { 0x5209, 1396 }, + { 0x520A, 1378 }, + { 0x520B, 1381 }, + { 0x520C, 655 }, + { 0x520D, 1375 }, + { 0x520E, 1414 }, + { 0x520F, 1417 }, + { 0x5210, 664 }, + { 0x5211, 1408 }, + { 0x5212, 2857 }, + { 0x5213, 1411 }, + { 0x5214, 2518 }, + { 0x5215, 2521 }, + { 0x5216, 1165 }, + { 0x5217, 3757 }, + { 0x5218, 2515 }, + { 0x5219, 3754 }, + { 0x521A, 2500 }, + { 0x521B, 2503 }, + { 0x521C, 1159 }, + { 0x521D, 2497 }, + { 0x521E, 3763 }, + { 0x521F, 3766 }, + { 0x5220, 2533 }, + { 0x5221, 3760 }, + { 0x5222, 2527 }, + { 0x5223, 2530 }, + { 0x5224, 1168 }, + { 0x5225, 2524 }, + { 0x5226, 2509 }, + { 0x5227, 2512 }, + { 0x5228, 1162 }, + { 0x5229, 2506 }, + { 0x522A, 2542 }, + { 0x522B, 2545 }, + { 0x522C, 1171 }, + { 0x522D, 2536 }, + { 0x522E, 3769 }, + { 0x522F, 2539 }, + { 0x5230, 3856 }, + { 0x5231, 2899 }, + { 0x5232, 2887 }, + { 0x5233, 2890 }, + { 0x5234, 1495 }, + { 0x5235, 2884 }, + { 0x5236, 3862 }, + { 0x5237, 2911 }, + { 0x5238, 3859 }, + { 0x5239, 2905 }, + { 0x523A, 2908 }, + { 0x523B, 1501 }, + { 0x523C, 2902 }, + { 0x523D, 2896 }, + { 0x523E, 1498 }, + { 0x523F, 2893 }, + { 0x5240, 2920 }, + { 0x5241, 2923 }, + { 0x5242, 1504 }, + { 0x5243, 2914 }, + { 0x5244, 3865 }, + { 0x5245, 2917 }, + { 0x5246, 2758 }, + { 0x5247, 2761 }, + { 0x5248, 1291 }, + { 0x5249, 2755 }, + { 0x524A, 3823 }, + { 0x524B, 3826 }, + { 0x524C, 2752 }, + { 0x524D, 3820 }, + { 0x524E, 2740 }, + { 0x524F, 2743 }, + { 0x5250, 1285 }, + { 0x5251, 2737 }, + { 0x5252, 3832 }, + { 0x5253, 3835 }, + { 0x5254, 2773 }, + { 0x5255, 3829 }, + { 0x5256, 2767 }, + { 0x5257, 2770 }, + { 0x5258, 1294 }, + { 0x5259, 2764 }, + { 0x525A, 2749 }, + { 0x525B, 1288 }, + { 0x525C, 2746 }, + { 0x525D, 3889 }, + { 0x525E, 3061 }, + { 0x525F, 3886 }, + { 0x5260, 3049 }, + { 0x5261, 3052 }, + { 0x5262, 1594 }, + { 0x5263, 3046 }, + { 0x5264, 3892 }, + { 0x5265, 3895 }, + { 0x5266, 3073 }, + { 0x5267, 3067 }, + { 0x5268, 3070 }, + { 0x5269, 1600 }, + { 0x526A, 3064 }, + { 0x526B, 3058 }, + { 0x526C, 1597 }, + { 0x526D, 3055 }, + { 0x526E, 1228 }, + { 0x526F, 2569 }, + { 0x5270, 1225 }, + { 0x5271, 1213 }, + { 0x5272, 1216 }, + { 0x5273, 619 }, + { 0x5274, 1210 }, + { 0x5275, 2731 }, + { 0x5276, 2734 }, + { 0x5277, 1282 }, + { 0x5278, 2728 }, + { 0x5279, 1276 }, + { 0x527A, 1279 }, + { 0x527B, 625 }, + { 0x527C, 1273 }, + { 0x527D, 1222 }, + { 0x527E, 622 }, + { 0x527F, 1219 }, + { 0x5280, 2077 }, + { 0x5281, 2080 }, + { 0x5282, 820 }, + { 0x5283, 2074 }, + { 0x5284, 3538 }, + { 0x5285, 2095 }, + { 0x5286, 3535 }, + { 0x5287, 2092 }, + { 0x5288, 826 }, + { 0x5289, 2089 }, + { 0x528A, 2086 }, + { 0x528B, 823 }, + { 0x528C, 2083 }, + { 0x528D, 2218 }, + { 0x528E, 2221 }, + { 0x528F, 859 }, + { 0x5290, 2215 }, + { 0x5291, 3637 }, + { 0x5292, 2212 }, + { 0x5293, 3634 }, + { 0x5294, 2185 }, + { 0x5295, 2188 }, + { 0x5296, 853 }, + { 0x5297, 2182 }, + { 0x5298, 3643 }, + { 0x5299, 2233 }, + { 0x529A, 3640 }, + { 0x529B, 2227 }, + { 0x529C, 2230 }, + { 0x529D, 862 }, + { 0x529E, 2224 }, + { 0x529F, 2194 }, + { 0x52A0, 856 }, + { 0x52A1, 2191 }, + { 0x52A2, 2242 }, + { 0x52A3, 2245 }, + { 0x52A4, 865 }, + { 0x52A5, 2236 }, + { 0x52A6, 3646 }, + { 0x52A7, 2239 }, + { 0x52A8, 2254 }, + { 0x52A9, 2257 }, + { 0x52AA, 868 }, + { 0x52AB, 2248 }, + { 0x52AC, 3649 }, + { 0x52AD, 2251 }, + { 0x52AE, 988 }, + { 0x52AF, 991 }, + { 0x52B0, 559 }, + { 0x52B1, 985 }, + { 0x52B2, 2413 }, + { 0x52B3, 2416 }, + { 0x52B4, 982 }, + { 0x52B5, 2410 }, + { 0x52B6, 955 }, + { 0x52B7, 958 }, + { 0x52B8, 553 }, + { 0x52B9, 952 }, + { 0x52BA, 2422 }, + { 0x52BB, 1003 }, + { 0x52BC, 2419 }, + { 0x52BD, 997 }, + { 0x52BE, 1000 }, + { 0x52BF, 562 }, + { 0x52C0, 994 }, + { 0x52C1, 964 }, + { 0x52C2, 556 }, + { 0x52C3, 961 }, + { 0x52C4, 1012 }, + { 0x52C5, 1015 }, + { 0x52C6, 565 }, + { 0x52C7, 1006 }, + { 0x52C8, 2425 }, + { 0x52C9, 1009 }, + { 0x52CA, 1024 }, + { 0x52CB, 1027 }, + { 0x52CC, 568 }, + { 0x52CD, 1018 }, + { 0x52CE, 2428 }, + { 0x52CF, 1021 }, + { 0x52D0, 3673 }, + { 0x52D1, 3676 }, + { 0x52D2, 2266 }, + { 0x52D3, 3670 }, + { 0x52D4, 3997 }, + { 0x52D5, 4000 }, + { 0x52D6, 3667 }, + { 0x52D7, 3994 }, + { 0x52D8, 3655 }, + { 0x52D9, 3658 }, + { 0x52DA, 2260 }, + { 0x52DB, 3652 }, + { 0x52DC, 3682 }, + { 0x52DD, 2269 }, + { 0x52DE, 3679 }, + { 0x52DF, 3664 }, + { 0x52E0, 2263 }, + { 0x52E1, 3661 }, + { 0x52E2, 3691 }, + { 0x52E3, 2272 }, + { 0x52E4, 3685 }, + { 0x52E5, 4003 }, + { 0x52E6, 3688 }, + { 0x52E7, 3700 }, + { 0x52E8, 3703 }, + { 0x52E9, 2275 }, + { 0x52EA, 3694 }, + { 0x52EB, 4006 }, + { 0x52EC, 3697 }, + { 0x52ED, 3235 }, + { 0x52EE, 3238 }, + { 0x52EF, 1681 }, + { 0x52F0, 3232 }, + { 0x52F1, 3940 }, + { 0x52F2, 3229 }, + { 0x52F3, 3937 }, + { 0x52F4, 3220 }, + { 0x52F5, 3223 }, + { 0x52F6, 1675 }, + { 0x52F7, 3217 }, + { 0x52F8, 3943 }, + { 0x52F9, 3247 }, + { 0x52FA, 3244 }, + { 0x52FB, 3241 }, + { 0x52FC, 3226 }, + { 0x52FD, 1678 }, + { 0x52FE, 3256 }, + { 0x52FF, 1684 }, + { 0x5300, 3250 }, + { 0x5301, 3946 }, + { 0x5302, 3253 }, + { 0x5303, 3265 }, + { 0x5304, 3268 }, + { 0x5305, 1687 }, + { 0x5306, 3259 }, + { 0x5307, 3949 }, + { 0x5308, 3262 }, + { 0x5309, 1897 }, + { 0x530A, 1900 }, + { 0x530B, 775 }, + { 0x530C, 1894 }, + { 0x530D, 3430 }, + { 0x530E, 1891 }, + { 0x530F, 3427 }, + { 0x5310, 1864 }, + { 0x5311, 1867 }, + { 0x5312, 769 }, + { 0x5313, 1861 }, + { 0x5314, 3493 }, + { 0x5315, 1930 }, + { 0x5316, 3490 }, + { 0x5317, 1906 }, + { 0x5318, 1909 }, + { 0x5319, 778 }, + { 0x531A, 1903 }, + { 0x531B, 1873 }, + { 0x531C, 772 }, + { 0x531D, 1870 }, + { 0x531E, 1939 }, + { 0x531F, 1942 }, + { 0x5320, 781 }, + { 0x5321, 1933 }, + { 0x5322, 3496 }, + { 0x5323, 1936 }, + { 0x5324, 1951 }, + { 0x5325, 1954 }, + { 0x5326, 784 }, + { 0x5327, 1945 }, + { 0x5328, 3499 }, + { 0x5329, 1948 }, + { 0x532A, 3454 }, + { 0x532B, 3457 }, + { 0x532C, 1918 }, + { 0x532D, 3451 }, + { 0x532E, 3976 }, + { 0x532F, 3448 }, + { 0x5330, 3973 }, + { 0x5331, 3436 }, + { 0x5332, 3439 }, + { 0x5333, 1912 }, + { 0x5334, 3433 }, + { 0x5335, 3463 }, + { 0x5336, 3466 }, + { 0x5337, 1921 }, + { 0x5338, 3460 }, + { 0x5339, 3445 }, + { 0x533A, 1915 }, + { 0x533B, 3442 }, + { 0x533C, 3472 }, + { 0x533D, 3475 }, + { 0x533E, 1924 }, + { 0x533F, 3469 }, + { 0x5340, 3484 }, + { 0x5341, 3487 }, + { 0x5342, 1927 }, + { 0x5343, 3478 }, + { 0x5344, 3979 }, + { 0x5345, 3481 }, + { 0x5346, 3583 }, + { 0x5347, 3586 }, + { 0x5348, 2197 }, + { 0x5349, 3580 }, + { 0x534A, 3985 }, + { 0x534B, 3607 }, + { 0x534C, 3982 }, + { 0x534D, 3601 }, + { 0x534E, 3604 }, + { 0x534F, 2203 }, + { 0x5350, 3598 }, + { 0x5351, 3592 }, + { 0x5352, 3595 }, + { 0x5353, 2200 }, + { 0x5354, 3589 }, + { 0x5355, 3616 }, + { 0x5356, 3619 }, + { 0x5357, 2206 }, + { 0x5358, 3610 }, + { 0x5359, 3988 }, + { 0x535A, 3613 }, + { 0x535B, 3628 }, + { 0x535C, 3631 }, + { 0x535D, 2209 }, + { 0x535E, 3622 }, + { 0x535F, 3991 }, + { 0x5360, 3625 }, + { 0x5361, 2362 }, + { 0x5362, 2365 }, + { 0x5363, 967 }, + { 0x5364, 2359 }, + { 0x5365, 3727 }, + { 0x5366, 3730 }, + { 0x5367, 2386 }, + { 0x5368, 3724 }, + { 0x5369, 2380 }, + { 0x536A, 2383 }, + { 0x536B, 973 }, + { 0x536C, 2377 }, + { 0x536D, 2371 }, + { 0x536E, 2374 }, + { 0x536F, 970 }, + { 0x5370, 2368 }, + { 0x5371, 2395 }, + { 0x5372, 976 }, + { 0x5373, 2389 }, + { 0x5374, 3733 }, + { 0x5375, 2392 }, + { 0x5376, 2404 }, + { 0x5377, 2407 }, + { 0x5378, 979 }, + { 0x5379, 2398 }, + { 0x537A, 3736 }, + { 0x537B, 2401 }, + { 0x537C, 3313 }, + { 0x537D, 1819 }, + { 0x537E, 3952 }, + { 0x537F, 3334 }, + { 0x5380, 3328 }, + { 0x5381, 3331 }, + { 0x5382, 1825 }, + { 0x5383, 3325 }, + { 0x5384, 3319 }, + { 0x5385, 3322 }, + { 0x5386, 1822 }, + { 0x5387, 3316 }, + { 0x5388, 3343 }, + { 0x5389, 3346 }, + { 0x538A, 1828 }, + { 0x538B, 3337 }, + { 0x538C, 3955 }, + { 0x538D, 3340 }, + { 0x538E, 3355 }, + { 0x538F, 3358 }, + { 0x5390, 1831 }, + { 0x5391, 3349 }, + { 0x5392, 3958 }, + { 0x5393, 3352 }, + { 0x5394, 3130 }, + { 0x5395, 3133 }, + { 0x5396, 1636 }, + { 0x5397, 3127 }, + { 0x5398, 3148 }, + { 0x5399, 1642 }, + { 0x539A, 3145 }, + { 0x539B, 3139 }, + { 0x539C, 3142 }, + { 0x539D, 1639 }, + { 0x539E, 3136 }, + { 0x539F, 3157 }, + { 0x53A0, 3160 }, + { 0x53A1, 1645 }, + { 0x53A2, 3151 }, + { 0x53A3, 3916 }, + { 0x53A4, 3154 }, + { 0x53A5, 3169 }, + { 0x53A6, 3172 }, + { 0x53A7, 1648 }, + { 0x53A8, 3163 }, + { 0x53A9, 3919 }, + { 0x53AA, 3166 }, + { 0x53AB, 3376 }, + { 0x53AC, 3379 }, + { 0x53AD, 1876 }, + { 0x53AE, 3373 }, + { 0x53AF, 3964 }, + { 0x53B0, 3400 }, + { 0x53B1, 3961 }, + { 0x53B2, 3394 }, + { 0x53B3, 3397 }, + { 0x53B4, 1882 }, + { 0x53B5, 3391 }, + { 0x53B6, 3385 }, + { 0x53B7, 3388 }, + { 0x53B8, 1879 }, + { 0x53B9, 3382 }, + { 0x53BA, 3409 }, + { 0x53BB, 3412 }, + { 0x53BC, 1885 }, + { 0x53BD, 3403 }, + { 0x53BE, 3967 }, + { 0x53BF, 3406 }, + { 0x53C0, 3421 }, + { 0x53C1, 3424 }, + { 0x53C2, 1888 }, + { 0x53C3, 3415 }, + { 0x53C4, 3970 }, + { 0x53C5, 3418 }, + { 0x53C6, 1798 }, + { 0x53C7, 1801 }, + { 0x53C8, 754 }, + { 0x53C9, 1795 }, + { 0x53CA, 3364 }, + { 0x53CB, 1834 }, + { 0x53CC, 3361 }, + { 0x53CD, 1813 }, + { 0x53CE, 1816 }, + { 0x53CF, 760 }, + { 0x53D0, 1810 }, + { 0x53D1, 1807 }, + { 0x53D2, 757 }, + { 0x53D3, 1804 }, + { 0x53D4, 1843 }, + { 0x53D5, 1846 }, + { 0x53D6, 763 }, + { 0x53D7, 1837 }, + { 0x53D8, 3367 }, + { 0x53D9, 1840 }, + { 0x53DA, 1855 }, + { 0x53DB, 1858 }, + { 0x53DC, 766 }, + { 0x53DD, 1849 }, + { 0x53DE, 3370 }, + { 0x53DF, 1852 }, + { 0x53E0, 1312 }, + { 0x53E1, 1315 }, + { 0x53E2, 640 }, + { 0x53E3, 1309 }, + { 0x53E4, 2779 }, + { 0x53E5, 2782 }, + { 0x53E6, 1306 }, + { 0x53E7, 2776 }, + { 0x53E8, 2833 }, + { 0x53E9, 2836 }, + { 0x53EA, 1339 }, + { 0x53EB, 2830 }, + { 0x53EC, 1333 }, + { 0x53ED, 1336 }, + { 0x53EE, 643 }, + { 0x53EF, 1330 }, + { 0x53F0, 1348 }, + { 0x53F1, 1351 }, + { 0x53F2, 646 }, + { 0x53F3, 1342 }, + { 0x53F4, 2839 }, + { 0x53F5, 1345 }, + { 0x53F6, 1360 }, + { 0x53F7, 1363 }, + { 0x53F8, 649 }, + { 0x53F9, 1354 }, + { 0x53FA, 2842 }, + { 0x53FB, 1357 }, + { 0x53FC, 1753 }, + { 0x53FD, 1756 }, + { 0x53FE, 742 }, + { 0x53FF, 1750 }, + { 0x5400, 3292 }, + { 0x5401, 3295 }, + { 0x5402, 1747 }, + { 0x5403, 3289 }, + { 0x5404, 3301 }, + { 0x5405, 3304 }, + { 0x5406, 1768 }, + { 0x5407, 3298 }, + { 0x5408, 1762 }, + { 0x5409, 1765 }, + { 0x540A, 745 }, + { 0x540B, 1759 }, + { 0x540C, 1777 }, + { 0x540D, 1780 }, + { 0x540E, 748 }, + { 0x540F, 1771 }, + { 0x5410, 3307 }, + { 0x5411, 1774 }, + { 0x5412, 1789 }, + { 0x5413, 1792 }, + { 0x5414, 751 }, + { 0x5415, 1783 }, + { 0x5416, 3310 }, + { 0x5417, 1786 }, + { 0x5418, 2791 }, + { 0x5419, 2794 }, + { 0x541A, 1318 }, + { 0x541B, 2788 }, + { 0x541C, 3841 }, + { 0x541D, 3844 }, + { 0x541E, 2785 }, + { 0x541F, 3838 }, + { 0x5420, 3850 }, + { 0x5421, 2806 }, + { 0x5422, 3847 }, + { 0x5423, 2800 }, + { 0x5424, 2803 }, + { 0x5425, 1321 }, + { 0x5426, 2797 }, + { 0x5427, 2815 }, + { 0x5428, 2818 }, + { 0x5429, 1324 }, + { 0x542A, 2809 }, + { 0x542B, 3853 }, + { 0x542C, 2812 }, + { 0x542D, 2824 }, + { 0x542E, 2827 }, + { 0x542F, 1327 }, + { 0x5430, 2821 }, + { 0x5431, 3088 }, + { 0x5432, 3091 }, + { 0x5433, 1615 }, + { 0x5434, 3085 }, + { 0x5435, 3901 }, + { 0x5436, 3904 }, + { 0x5437, 3082 }, + { 0x5438, 3898 }, + { 0x5439, 3907 }, + { 0x543A, 3103 }, + { 0x543B, 3097 }, + { 0x543C, 3100 }, + { 0x543D, 1618 }, + { 0x543E, 3094 }, + { 0x543F, 3112 }, + { 0x5440, 1621 }, + { 0x5441, 3106 }, + { 0x5442, 3910 }, + { 0x5443, 3109 }, + { 0x5444, 3121 }, + { 0x5445, 3124 }, + { 0x5446, 1624 }, + { 0x5447, 3115 }, + { 0x5448, 3913 }, + { 0x5449, 3118 }, + { 0x544A, 3190 }, + { 0x544B, 3193 }, + { 0x544C, 1666 }, + { 0x544D, 3187 }, + { 0x544E, 3925 }, + { 0x544F, 3928 }, + { 0x5450, 3184 }, + { 0x5451, 3922 }, + { 0x5452, 3934 }, + { 0x5453, 3205 }, + { 0x5454, 3931 }, + { 0x5455, 3199 }, + { 0x5456, 3202 }, + { 0x5457, 1669 }, + { 0x5458, 3196 }, + { 0x5459, 3211 }, + { 0x545A, 3214 }, + { 0x545B, 1672 }, + { 0x545C, 3208 }, + { 0x545D, 2104 }, + { 0x545E, 2107 }, + { 0x545F, 832 }, + { 0x5460, 2101 }, + { 0x5461, 3544 }, + { 0x5462, 3547 }, + { 0x5463, 2098 }, + { 0x5464, 3541 }, + { 0x5465, 3550 }, + { 0x5466, 2119 }, + { 0x5467, 2113 }, + { 0x5468, 2116 }, + { 0x5469, 835 }, + { 0x546A, 2110 }, + { 0x546B, 2128 }, + { 0x546C, 2131 }, + { 0x546D, 838 }, + { 0x546E, 2122 }, + { 0x546F, 3553 }, + { 0x5470, 2125 }, + { 0x5471, 2140 }, + { 0x5472, 2143 }, + { 0x5473, 841 }, + { 0x5474, 2137 }, + { 0x5475, 3559 }, + { 0x5476, 3562 }, + { 0x5477, 2134 }, + { 0x5478, 3556 }, + { 0x5479, 3568 }, + { 0x547A, 3571 }, + { 0x547B, 2155 }, + { 0x547C, 3565 }, + { 0x547D, 2149 }, + { 0x547E, 2152 }, + { 0x547F, 844 }, + { 0x5480, 2146 }, + { 0x5481, 2164 }, + { 0x5482, 2167 }, + { 0x5483, 847 }, + { 0x5484, 2158 }, + { 0x5485, 3574 }, + { 0x5486, 2161 }, + { 0x5487, 2176 }, + { 0x5488, 2179 }, + { 0x5489, 850 }, + { 0x548A, 2170 }, + { 0x548B, 3577 }, + { 0x548C, 2173 }, + { 0x5490, 430 }, + { 0x5491, 364 }, + { 0x5492, 412 }, + { 0x5493, 493 }, + { 0x5494, 394 }, + { 0x5495, 436 }, + { 0x5496, 469 }, + { 0x5497, 400 }, + { 0x5498, 367 }, + { 0x5499, 475 }, + { 0x549A, 418 }, + { 0x549B, 460 }, + { 0x549C, 421 }, + { 0x549D, 379 }, + { 0x549E, 424 }, + { 0x549F, 481 }, + { 0x54A0, 439 }, + { 0x54A1, 355 }, + { 0x54A2, 454 }, + { 0x54A3, 397 }, + { 0x54A4, 466 }, + { 0x54A5, 385 }, + { 0x54A6, 472 }, + { 0x54A7, 496 }, + { 0x54A8, 373 }, + { 0x54A9, 370 }, + { 0x54AA, 487 }, + { 0x54AB, 451 }, + { 0x54AC, 427 }, + { 0x54AD, 406 }, + { 0x54AE, 448 }, + { 0x54AF, 445 }, + { 0x54B0, 433 }, + { 0x54B1, 442 }, + { 0x54B2, 382 }, + { 0x54B3, 358 }, + { 0x54B4, 499 }, + { 0x54B5, 409 }, + { 0x54B6, 403 }, + { 0x54B7, 484 }, + { 0x54B8, 376 }, + { 0x54B9, 352 }, + { 0x54BA, 508 }, + { 0x54BB, 415 }, + { 0x54BC, 349 }, + { 0x54BD, 463 }, + { 0x54BE, 391 }, + { 0x54BF, 478 }, + { 0x54C0, 502 }, + { 0x54C1, 457 }, + { 0x54C2, 505 }, + { 0x54C3, 388 }, + { 0x54C4, 511 }, + { 0x54C5, 490 }, + { 0x54C6, 361 }, + { 0x5500, 7945 }, + { 0x5501, 8254 }, + { 0x5502, 8290 }, + { 0x5503, 8482 }, + { 0x5504, 8653 }, + { 0x5505, 8419 }, + { 0x5506, 8527 }, + { 0x5507, 8206 }, + { 0x5508, 8578 }, + { 0x5509, 8569 }, + { 0x550A, 8671 }, + { 0x550B, 8554 }, + { 0x550C, 8257 }, + { 0x550D, 8473 }, + { 0x550E, 8452 }, + { 0x550F, 8647 }, + { 0x5510, 8533 }, + { 0x5511, 8665 }, + { 0x5512, 8338 }, + { 0x5513, 8425 }, + { 0x5514, 8233 }, + { 0x5515, 8599 }, + { 0x5516, 8431 }, + { 0x5517, 8641 }, + { 0x5518, 8506 }, + { 0x5519, 8659 }, + { 0x551A, 8227 }, + { 0x551B, 8308 }, + { 0x551C, 8629 }, + { 0x551D, 8500 }, + { 0x551E, 8317 }, + { 0x551F, 8697 }, + { 0x5520, 8278 }, + { 0x5521, 8359 }, + { 0x5522, 8380 }, + { 0x5523, 8635 }, + { 0x5524, 7888 }, + { 0x5525, 7996 }, + { 0x5526, 7987 }, + { 0x5527, 8296 }, + { 0x5528, 8167 }, + { 0x5529, 8488 }, + { 0x552A, 8089 }, + { 0x552B, 8215 }, + { 0x552C, 7906 }, + { 0x552D, 8350 }, + { 0x552E, 8329 }, + { 0x552F, 8590 }, + { 0x5530, 8269 }, + { 0x5531, 7957 }, + { 0x5532, 8152 }, + { 0x5533, 8134 }, + { 0x5534, 8461 }, + { 0x5535, 8242 }, + { 0x5536, 8542 }, + { 0x5537, 8035 }, + { 0x5538, 8104 }, + { 0x5539, 7936 }, + { 0x553A, 8371 }, + { 0x553B, 8119 }, + { 0x553C, 8440 }, + { 0x553D, 8197 }, + { 0x553E, 8515 }, + { 0x553F, 7921 }, + { 0x5540, 8005 }, + { 0x5541, 8389 }, + { 0x5542, 8182 }, + { 0x5543, 8020 }, + { 0x5544, 8617 }, + { 0x5545, 7972 }, + { 0x5546, 8050 }, + { 0x5547, 8068 }, + { 0x5548, 8407 }, + { 0x5549, 7882 }, + { 0x554A, 7897 }, + { 0x554B, 8605 }, + { 0x554C, 7981 }, + { 0x554D, 8287 }, + { 0x554E, 8161 }, + { 0x554F, 8479 }, + { 0x5550, 8083 }, + { 0x5551, 8209 }, + { 0x5552, 7900 }, + { 0x5553, 8344 }, + { 0x5554, 8323 }, + { 0x5555, 8566 }, + { 0x5556, 8584 }, + { 0x5557, 8263 }, + { 0x5558, 7951 }, + { 0x5559, 8146 }, + { 0x555A, 8128 }, + { 0x555B, 8455 }, + { 0x555C, 8236 }, + { 0x555D, 8536 }, + { 0x555E, 8029 }, + { 0x555F, 8098 }, + { 0x5560, 7930 }, + { 0x5561, 8365 }, + { 0x5562, 8113 }, + { 0x5563, 8434 }, + { 0x5564, 8191 }, + { 0x5565, 8509 }, + { 0x5566, 7915 }, + { 0x5567, 7999 }, + { 0x5568, 8383 }, + { 0x5569, 8176 }, + { 0x556A, 8014 }, + { 0x556B, 8314 }, + { 0x556C, 8611 }, + { 0x556D, 7966 }, + { 0x556E, 8044 }, + { 0x556F, 8059 }, + { 0x5570, 8401 }, + { 0x5571, 8080 }, + { 0x5572, 8416 }, + { 0x5573, 8302 }, + { 0x5574, 8494 }, + { 0x5575, 8656 }, + { 0x5576, 8422 }, + { 0x5577, 8530 }, + { 0x5578, 8224 }, + { 0x5579, 8581 }, + { 0x557A, 8575 }, + { 0x557B, 8674 }, + { 0x557C, 8563 }, + { 0x557D, 8260 }, + { 0x557E, 8476 }, + { 0x557F, 8470 }, + { 0x5580, 8650 }, + { 0x5581, 8551 }, + { 0x5582, 8668 }, + { 0x5583, 8341 }, + { 0x5584, 8428 }, + { 0x5585, 8251 }, + { 0x5586, 8602 }, + { 0x5587, 8449 }, + { 0x5588, 8644 }, + { 0x5589, 8524 }, + { 0x558A, 8662 }, + { 0x558B, 8230 }, + { 0x558C, 8311 }, + { 0x558D, 8632 }, + { 0x558E, 8503 }, + { 0x558F, 8320 }, + { 0x5590, 8703 }, + { 0x5591, 8284 }, + { 0x5592, 8362 }, + { 0x5593, 8398 }, + { 0x5594, 8638 }, + { 0x5595, 7894 }, + { 0x5596, 8143 }, + { 0x5597, 7993 }, + { 0x5598, 8305 }, + { 0x5599, 8173 }, + { 0x559A, 8497 }, + { 0x559B, 8095 }, + { 0x559C, 8221 }, + { 0x559D, 7912 }, + { 0x559E, 8356 }, + { 0x559F, 8335 }, + { 0x55A0, 8596 }, + { 0x55A1, 8275 }, + { 0x55A2, 7963 }, + { 0x55A3, 8158 }, + { 0x55A4, 8140 }, + { 0x55A5, 8467 }, + { 0x55A6, 8248 }, + { 0x55A7, 8548 }, + { 0x55A8, 8041 }, + { 0x55A9, 8110 }, + { 0x55AA, 7942 }, + { 0x55AB, 8377 }, + { 0x55AC, 8125 }, + { 0x55AD, 8446 }, + { 0x55AE, 8203 }, + { 0x55AF, 8521 }, + { 0x55B0, 7927 }, + { 0x55B1, 8011 }, + { 0x55B2, 8395 }, + { 0x55B3, 8188 }, + { 0x55B4, 8026 }, + { 0x55B5, 8623 }, + { 0x55B6, 7978 }, + { 0x55B7, 8056 }, + { 0x55B8, 8074 }, + { 0x55B9, 8413 }, + { 0x55BA, 7891 }, + { 0x55BB, 8077 }, + { 0x55BC, 8626 }, + { 0x55BD, 7990 }, + { 0x55BE, 8299 }, + { 0x55BF, 8170 }, + { 0x55C0, 8491 }, + { 0x55C1, 8092 }, + { 0x55C2, 8218 }, + { 0x55C3, 7909 }, + { 0x55C4, 8353 }, + { 0x55C5, 8332 }, + { 0x55C6, 8593 }, + { 0x55C7, 8272 }, + { 0x55C8, 8560 }, + { 0x55C9, 7960 }, + { 0x55CA, 8155 }, + { 0x55CB, 8137 }, + { 0x55CC, 8464 }, + { 0x55CD, 8245 }, + { 0x55CE, 8545 }, + { 0x55CF, 8038 }, + { 0x55D0, 8107 }, + { 0x55D1, 7939 }, + { 0x55D2, 8374 }, + { 0x55D3, 8122 }, + { 0x55D4, 8443 }, + { 0x55D5, 8200 }, + { 0x55D6, 8518 }, + { 0x55D7, 7924 }, + { 0x55D8, 8008 }, + { 0x55D9, 8392 }, + { 0x55DA, 8185 }, + { 0x55DB, 8023 }, + { 0x55DC, 8620 }, + { 0x55DD, 7975 }, + { 0x55DE, 8053 }, + { 0x55DF, 8071 }, + { 0x55E0, 8410 }, + { 0x55E1, 7885 }, + { 0x55E2, 7948 }, + { 0x55E3, 8608 }, + { 0x55E4, 7984 }, + { 0x55E5, 8293 }, + { 0x55E6, 8164 }, + { 0x55E7, 8485 }, + { 0x55E8, 8086 }, + { 0x55E9, 8212 }, + { 0x55EA, 7903 }, + { 0x55EB, 8347 }, + { 0x55EC, 8326 }, + { 0x55ED, 8572 }, + { 0x55EE, 8587 }, + { 0x55EF, 8266 }, + { 0x55F0, 8557 }, + { 0x55F1, 7954 }, + { 0x55F2, 8149 }, + { 0x55F3, 8131 }, + { 0x55F4, 8458 }, + { 0x55F5, 8239 }, + { 0x55F6, 8539 }, + { 0x55F7, 8032 }, + { 0x55F8, 8101 }, + { 0x55F9, 7933 }, + { 0x55FA, 8368 }, + { 0x55FB, 8116 }, + { 0x55FC, 8437 }, + { 0x55FD, 8194 }, + { 0x55FE, 8512 }, + { 0x55FF, 7918 }, + { 0x5600, 8002 }, + { 0x5601, 8386 }, + { 0x5602, 8179 }, + { 0x5603, 8017 }, + { 0x5604, 8614 }, + { 0x5605, 8700 }, + { 0x5606, 7969 }, + { 0x5607, 8281 }, + { 0x5608, 8047 }, + { 0x5609, 8062 }, + { 0x560A, 8404 }, + { 0x560B, 8065 }, + { 0x560C, 8706 }, + { 0x560D, 7808 }, + { 0x560E, 7805 }, + { 0x560F, 7879 }, + { 0x5610, 8681 }, + { 0x5611, 8685 }, + { 0x5612, 8693 }, + { 0x5613, 7873 }, + { 0x5614, 7876 }, + { 0x5615, 7864 }, + { 0x5616, 7843 }, + { 0x5617, 7849 }, + { 0x5618, 7840 }, + { 0x5619, 7846 }, + { 0x561A, 7852 }, + { 0x561B, 7870 }, + { 0x561C, 7861 }, + { 0x561D, 7867 }, + { 0x561E, 7855 }, + { 0x561F, 7858 }, + { 0x5620, 7828 }, + { 0x5621, 7810 }, + { 0x5622, 7816 }, + { 0x5623, 7837 }, + { 0x5624, 7822 }, + { 0x5625, 7819 }, + { 0x5626, 7813 }, + { 0x5627, 7834 }, + { 0x5628, 7831 }, + { 0x5629, 7825 }, + { 0x562A, 8689 }, + { 0x562B, 8677 }, + { 0x5640, 50137 }, + { 0x5641, 49239 }, + { 0x5642, 50054 }, + { 0x5643, 49156 }, + { 0x5644, 50212 }, + { 0x5645, 49318 }, + { 0x5646, 49931 }, + { 0x5647, 49033 }, + { 0x5648, 50050 }, + { 0x5649, 49152 }, + { 0x564A, 50266 }, + { 0x564B, 49372 }, + { 0x564C, 50045 }, + { 0x564D, 49147 }, + { 0x564E, 50163 }, + { 0x564F, 49265 }, + { 0x5650, 50023 }, + { 0x5651, 49125 }, + { 0x5652, 50184 }, + { 0x5653, 49286 }, + { 0x5654, 50202 }, + { 0x5655, 49308 }, + { 0x5656, 50168 }, + { 0x5657, 49270 }, + { 0x5658, 50120 }, + { 0x5659, 49222 }, + { 0x565A, 50146 }, + { 0x565B, 49248 }, + { 0x565C, 50189 }, + { 0x565D, 49291 }, + { 0x565E, 49727 }, + { 0x565F, 48829 }, + { 0x5662, 49983 }, + { 0x5663, 49085 }, + { 0x5664, 49988 }, + { 0x5665, 49090 }, + { 0x5666, 49993 }, + { 0x5667, 49095 }, + { 0x5668, 50261 }, + { 0x5669, 49367 }, + { 0x566A, 50256 }, + { 0x566B, 49362 }, + { 0x566C, 50126 }, + { 0x566D, 49228 }, + { 0x566E, 49417 }, + { 0x566F, 58020 }, + { 0x5670, 58004 }, + { 0x5671, 58160 }, + { 0x5672, 58180 }, + { 0x5673, 55523 }, + { 0x567C, 58023 }, + { 0x567D, 58170 }, + { 0x567E, 49407 }, + { 0x567F, 50301 }, + { 0x5680, 49783 }, + { 0x5681, 48885 }, + { 0x5682, 49914 }, + { 0x5683, 49016 }, + { 0x5684, 50036 }, + { 0x5685, 49138 }, + { 0x5686, 49906 }, + { 0x5687, 49008 }, + { 0x5688, 49918 }, + { 0x5689, 49020 }, + { 0x568A, 49694 }, + { 0x568B, 48796 }, + { 0x568C, 49872 }, + { 0x568D, 48974 }, + { 0x568E, 50015 }, + { 0x568F, 49117 }, + { 0x5690, 50011 }, + { 0x5691, 49113 }, + { 0x5692, 50003 }, + { 0x5693, 49105 }, + { 0x5694, 49832 }, + { 0x5695, 48934 }, + { 0x5696, 49979 }, + { 0x5697, 49081 }, + { 0x5700, 54739 }, + { 0x5701, 54763 }, + { 0x5702, 54745 }, + { 0x5703, 54769 }, + { 0x5704, 54727 }, + { 0x5705, 54751 }, + { 0x5706, 54733 }, + { 0x5707, 54757 }, + { 0x5708, 54839 }, + { 0x5709, 54039 }, + { 0x570A, 53996 }, + { 0x570B, 53952 }, + { 0x570C, 54808 }, + { 0x570D, 54845 }, + { 0x570E, 54045 }, + { 0x570F, 54002 }, + { 0x5710, 53958 }, + { 0x5711, 54814 }, + { 0x5712, 54852 }, + { 0x5713, 54052 }, + { 0x5714, 54009 }, + { 0x5715, 53980 }, + { 0x5716, 54821 }, + { 0x5717, 53884 }, + { 0x5718, 53880 }, + { 0x5719, 53889 }, + { 0x571A, 54106 }, + { 0x571B, 54571 }, + { 0x571C, 54576 }, + { 0x571D, 54591 }, + { 0x571E, 54585 }, + { 0x571F, 53969 }, + { 0x5720, 54606 }, + { 0x5721, 54600 }, + { 0x5722, 20769 }, + { 0x5723, 17878 }, + { 0x5724, 20764 }, + { 0x5725, 17873 }, + { 0x5726, 20552 }, + { 0x5727, 17317 }, + { 0x5728, 20503 }, + { 0x5729, 17173 }, + { 0x572A, 20735 }, + { 0x572B, 17844 }, + { 0x572C, 20739 }, + { 0x572D, 17848 }, + { 0x572E, 20743 }, + { 0x572F, 17852 }, + { 0x5730, 17974 }, + { 0x5731, 18048 }, + { 0x5732, 20422 }, + { 0x5733, 17038 }, + { 0x5734, 20442 }, + { 0x5735, 17058 }, + { 0x5736, 20446 }, + { 0x5737, 17062 }, + { 0x5738, 20450 }, + { 0x5739, 17066 }, + { 0x573A, 20454 }, + { 0x573B, 17070 }, + { 0x573C, 20461 }, + { 0x573D, 17077 }, + { 0x573E, 20719 }, + { 0x573F, 17758 }, + { 0x5740, 19120 }, + { 0x5741, 15472 }, + { 0x5742, 19141 }, + { 0x5743, 15500 }, + { 0x5744, 19126 }, + { 0x5745, 15478 }, + { 0x5746, 20644 }, + { 0x5747, 17505 }, + { 0x5748, 19180 }, + { 0x5749, 15551 }, + { 0x574A, 19451 }, + { 0x574B, 15876 }, + { 0x574C, 19459 }, + { 0x574D, 15884 }, + { 0x574E, 20495 }, + { 0x574F, 17142 }, + { 0x5750, 19688 }, + { 0x5751, 16113 }, + { 0x5752, 19696 }, + { 0x5753, 16128 }, + { 0x5754, 19702 }, + { 0x5755, 16134 }, + { 0x5756, 19713 }, + { 0x5757, 16158 }, + { 0x5758, 19721 }, + { 0x5759, 16166 }, + { 0x575A, 19806 }, + { 0x575B, 16287 }, + { 0x575C, 20542 }, + { 0x575D, 17287 }, + { 0x575E, 20210 }, + { 0x575F, 16771 }, + { 0x5760, 20507 }, + { 0x5761, 17185 }, + { 0x5762, 20749 }, + { 0x5763, 17858 }, + { 0x5764, 20630 }, + { 0x5765, 17480 }, + { 0x5766, 20636 }, + { 0x5767, 17486 }, + { 0x5768, 20585 }, + { 0x5769, 17421 }, + { 0x576A, 20475 }, + { 0x576B, 17108 }, + { 0x576C, 20479 }, + { 0x576D, 17116 }, + { 0x576E, 20511 }, + { 0x576F, 17189 }, + { 0x5770, 53877 }, + { 0x5771, 17193 }, + { 0x5772, 17267 }, + { 0x5773, 17271 }, + { 0x5774, 17275 }, + { 0x5775, 17283 }, + { 0x5776, 18108 }, + { 0x5777, 17298 }, + { 0x5778, 17181 }, + { 0x5779, 20685 }, + { 0x577A, 17713 }, + { 0x577B, 20690 }, + { 0x577C, 17718 }, + { 0x577D, 20695 }, + { 0x577E, 20669 }, + { 0x577F, 17676 }, + { 0x5780, 20654 }, + { 0x5781, 17585 }, + { 0x5782, 20700 }, + { 0x5783, 17728 }, + { 0x5784, 20705 }, + { 0x5785, 17733 }, + { 0x5786, 20710 }, + { 0x5787, 17738 }, + { 0x5788, 53986 }, + { 0x5789, 54095 }, + { 0x578A, 54131 }, + { 0x578B, 20731 }, + { 0x578C, 17800 }, + { 0x57FB, 20847 }, + { 0x57FC, 20852 }, + { 0x57FD, 20842 }, + { 0x57FE, 20832 }, + { 0x57FF, 20837 }, + { 0x5800, 36572 }, + { 0x5801, 36580 }, + { 0x5802, 36543 }, + { 0x5803, 36588 }, + { 0x5804, 36576 }, + { 0x5805, 36584 }, + { 0x5806, 36535 }, + { 0x5807, 36616 }, + { 0x5808, 36672 }, + { 0x5809, 36604 }, + { 0x580A, 36664 }, + { 0x580B, 36539 }, + { 0x580C, 36596 }, + { 0x580D, 36652 }, + { 0x580E, 36612 }, + { 0x580F, 36668 }, + { 0x5810, 36688 }, + { 0x5811, 36696 }, + { 0x5812, 36656 }, + { 0x5813, 36692 }, + { 0x5814, 36644 }, + { 0x5815, 36684 }, + { 0x5816, 36600 }, + { 0x5817, 36660 }, + { 0x5818, 36628 }, + { 0x5819, 36632 }, + { 0x581A, 36676 }, + { 0x581B, 36592 }, + { 0x581C, 36648 }, + { 0x581D, 36624 }, + { 0x581E, 36636 }, + { 0x581F, 36620 }, + { 0x5820, 36680 }, + { 0x5821, 36640 }, + { 0x5822, 36608 }, + { 0x5823, 36547 }, + { 0x5824, 36557 }, + { 0x5825, 36562 }, + { 0x5826, 36552 }, + { 0x5827, 36567 }, + { 0x5828, 36700 }, + { 0x5829, 36704 }, + { 0x582A, 36708 }, + { 0x582B, 36712 }, + { 0x5840, 55006 }, + { 0x5841, 55057 }, + { 0x5842, 54997 }, + { 0x5843, 55060 }, + { 0x5844, 54985 }, + { 0x5845, 55045 }, + { 0x5846, 55003 }, + { 0x5847, 55066 }, + { 0x5848, 55030 }, + { 0x5849, 55075 }, + { 0x584A, 54988 }, + { 0x584B, 55015 }, + { 0x584C, 55018 }, + { 0x584D, 55069 }, + { 0x584E, 54982 }, + { 0x584F, 55012 }, + { 0x5850, 55078 }, + { 0x5851, 55087 }, + { 0x5852, 55051 }, + { 0x5853, 55033 }, + { 0x5854, 55084 }, + { 0x5855, 55042 }, + { 0x5856, 55093 }, + { 0x5857, 55039 }, + { 0x5858, 55024 }, + { 0x5859, 55009 }, + { 0x585A, 55072 }, + { 0x585B, 55027 }, + { 0x585C, 55000 }, + { 0x585D, 54967 }, + { 0x585E, 54973 }, + { 0x585F, 54979 }, + { 0x5860, 54970 }, + { 0x5861, 54976 }, + { 0x5862, 55021 }, + { 0x5863, 55036 }, + { 0x5864, 54994 }, + { 0x5865, 55054 }, + { 0x5866, 54991 }, + { 0x5867, 55124 }, + { 0x5868, 55128 }, + { 0x5869, 55081 }, + { 0x586A, 55090 }, + { 0x586B, 55048 }, + { 0x586C, 55063 }, + { 0x586D, 55101 }, + { 0x586E, 55109 }, + { 0x586F, 55097 }, + { 0x5870, 55105 }, + { 0x5871, 55120 }, + { 0x5872, 55132 }, + { 0x5873, 55113 }, + { 0x5874, 55116 }, + { 0x5875, 54963 }, + { 0x5876, 54956 }, + { 0x5877, 54959 }, + { 0x5880, 68329 }, + { 0x5881, 68326 }, + { 0x5882, 68431 }, + { 0x5883, 68446 }, + { 0x5884, 68437 }, + { 0x5885, 68473 }, + { 0x5886, 68443 }, + { 0x5887, 68506 }, + { 0x5888, 68573 }, + { 0x5889, 68581 }, + { 0x588A, 68569 }, + { 0x588B, 68577 }, + { 0x588C, 68434 }, + { 0x588D, 68464 }, + { 0x588E, 68449 }, + { 0x588F, 68440 }, + { 0x5890, 68491 }, + { 0x5891, 68452 }, + { 0x5892, 68479 }, + { 0x5893, 68533 }, + { 0x5894, 68467 }, + { 0x5895, 68527 }, + { 0x5896, 68539 }, + { 0x5897, 68458 }, + { 0x5898, 68518 }, + { 0x5899, 68476 }, + { 0x589A, 68530 }, + { 0x589B, 68545 }, + { 0x589C, 68560 }, + { 0x589D, 68566 }, + { 0x589E, 68521 }, + { 0x589F, 68563 }, + { 0x58A0, 68542 }, + { 0x58A1, 68503 }, + { 0x58A2, 68557 }, + { 0x58A3, 68461 }, + { 0x58A4, 68524 }, + { 0x58A5, 68488 }, + { 0x58A6, 68494 }, + { 0x58A7, 68548 }, + { 0x58A8, 68455 }, + { 0x58A9, 68515 }, + { 0x58AA, 68485 }, + { 0x58AB, 68512 }, + { 0x58AC, 68497 }, + { 0x58AD, 68482 }, + { 0x58AE, 68509 }, + { 0x58AF, 68551 }, + { 0x58B0, 68554 }, + { 0x58B1, 68500 }, + { 0x58B2, 68470 }, + { 0x58B3, 68536 }, + { 0x58B4, 68585 }, + { 0x58B5, 68380 }, + { 0x58B6, 68368 }, + { 0x58B7, 68396 }, + { 0x58B8, 68376 }, + { 0x58B9, 68404 }, + { 0x58BA, 68413 }, + { 0x58BB, 68423 }, + { 0x58BC, 68408 }, + { 0x58BD, 68418 }, + { 0x58BE, 68364 }, + { 0x58BF, 68392 }, + { 0x58C0, 68384 }, + { 0x58C1, 68372 }, + { 0x58C2, 68400 }, + { 0x58C3, 68388 }, + { 0x58C4, 68323 }, + { 0x58CE, 68332 }, + { 0x58CF, 68428 }, + { 0x58D0, 68352 }, + { 0x58D1, 68334 }, + { 0x58D2, 68340 }, + { 0x58D3, 68361 }, + { 0x58D4, 68346 }, + { 0x58D5, 68343 }, + { 0x58D6, 68337 }, + { 0x58D7, 68358 }, + { 0x58D8, 68355 }, + { 0x58D9, 68349 }, + { 0x5900, 13773 }, + { 0x5901, 13749 }, + { 0x5902, 13757 }, + { 0x5903, 13785 }, + { 0x5904, 13765 }, + { 0x5905, 13761 }, + { 0x5906, 13753 }, + { 0x5907, 13781 }, + { 0x5908, 13777 }, + { 0x5909, 13769 }, + { 0x590A, 13837 }, + { 0x590B, 13897 }, + { 0x590C, 13829 }, + { 0x590D, 13901 }, + { 0x590E, 13869 }, + { 0x590F, 13913 }, + { 0x5910, 13889 }, + { 0x5911, 13905 }, + { 0x5912, 13873 }, + { 0x5913, 13893 }, + { 0x5914, 13849 }, + { 0x5915, 13861 }, + { 0x5916, 13909 }, + { 0x5917, 13845 }, + { 0x5918, 13825 }, + { 0x5919, 13817 }, + { 0x591A, 13865 }, + { 0x591B, 13885 }, + { 0x591C, 13841 }, + { 0x591D, 13881 }, + { 0x591E, 13917 }, + { 0x591F, 13833 }, + { 0x5920, 13877 }, + { 0x5921, 13821 }, + { 0x5922, 13809 }, + { 0x5923, 13853 }, + { 0x5924, 13813 }, + { 0x5925, 13857 }, + { 0x5926, 13805 }, + { 0x5927, 13789 }, + { 0x5928, 13797 }, + { 0x5929, 13801 }, + { 0x592A, 13793 }, + { 0x592B, 13745 }, + { 0x592C, 13736 }, + { 0x592D, 13740 }, + { 0x592E, 13728 }, + { 0x592F, 13732 }, + { 0x5930, 35728 }, + { 0x5931, 35719 }, + { 0x5932, 35764 }, + { 0x5933, 35749 }, + { 0x5934, 35716 }, + { 0x5935, 35737 }, + { 0x5936, 35740 }, + { 0x5937, 35710 }, + { 0x5938, 35734 }, + { 0x5939, 35713 }, + { 0x593A, 35725 }, + { 0x593B, 35767 }, + { 0x593C, 35746 }, + { 0x593D, 35743 }, + { 0x593E, 35731 }, + { 0x593F, 35755 }, + { 0x5940, 35752 }, + { 0x5941, 35722 }, + { 0x5942, 35758 }, + { 0x5943, 35770 }, + { 0x5944, 35761 }, + { 0x5945, 35773 }, + { 0x5946, 35707 }, + { 0x5947, 35679 }, + { 0x5948, 35687 }, + { 0x5949, 35675 }, + { 0x594A, 35691 }, + { 0x594B, 35683 }, + { 0x594C, 35695 }, + { 0x594D, 35703 }, + { 0x594E, 35699 }, + { 0x594F, 35793 }, + { 0x5950, 35785 }, + { 0x5951, 35789 }, + { 0x5952, 35781 }, + { 0x5953, 35776 }, + { 0x595F, 35778 }, + { 0x5A00, 8801 }, + { 0x5A01, 8807 }, + { 0x5A02, 8813 }, + { 0x5A03, 8804 }, + { 0x5A04, 8816 }, + { 0x5A05, 8810 }, + { 0x5A06, 8834 }, + { 0x5A07, 8885 }, + { 0x5A08, 8825 }, + { 0x5A09, 8879 }, + { 0x5A0A, 8915 }, + { 0x5A0B, 8891 }, + { 0x5A0C, 8870 }, + { 0x5A0D, 8912 }, + { 0x5A0E, 8831 }, + { 0x5A0F, 8882 }, + { 0x5A10, 8921 }, + { 0x5A11, 8894 }, + { 0x5A12, 8918 }, + { 0x5A13, 8855 }, + { 0x5A14, 8909 }, + { 0x5A15, 8822 }, + { 0x5A16, 8876 }, + { 0x5A17, 8897 }, + { 0x5A18, 8843 }, + { 0x5A19, 8873 }, + { 0x5A1A, 8846 }, + { 0x5A1B, 8903 }, + { 0x5A1C, 8900 }, + { 0x5A1D, 8819 }, + { 0x5A1E, 8867 }, + { 0x5A1F, 8888 }, + { 0x5A20, 8840 }, + { 0x5A21, 8864 }, + { 0x5A22, 8861 }, + { 0x5A23, 8849 }, + { 0x5A24, 8837 }, + { 0x5A25, 8858 }, + { 0x5A26, 8906 }, + { 0x5A27, 8852 }, + { 0x5A28, 8828 }, + { 0x5A29, 8773 }, + { 0x5A2A, 8761 }, + { 0x5A2B, 8789 }, + { 0x5A2C, 8785 }, + { 0x5A2D, 8769 }, + { 0x5A2E, 8793 }, + { 0x5A2F, 8765 }, + { 0x5A30, 8777 }, + { 0x5A31, 8781 }, + { 0x5A32, 8797 }, + { 0x5A33, 8980 }, + { 0x5A34, 8972 }, + { 0x5A35, 8968 }, + { 0x5A36, 8976 }, + { 0x5A40, 8928 }, + { 0x5A41, 8924 }, + { 0x5A42, 8960 }, + { 0x5A43, 8994 }, + { 0x5A44, 8956 }, + { 0x5A45, 8948 }, + { 0x5A46, 8936 }, + { 0x5A47, 8940 }, + { 0x5A48, 8952 }, + { 0x5A49, 8944 }, + { 0x5A4A, 8932 }, + { 0x5A4B, 8964 }, + { 0x5A4C, 8989 }, + { 0x5A4D, 8984 }, + { 0x5A50, 8749 }, + { 0x5A51, 8731 }, + { 0x5A52, 8737 }, + { 0x5A53, 8758 }, + { 0x5A54, 8743 }, + { 0x5A55, 8740 }, + { 0x5A56, 8734 }, + { 0x5A57, 8755 }, + { 0x5A58, 8752 }, + { 0x5A59, 8746 }, + { 0x5A5C, 9006 }, + { 0x5A5D, 8999 }, + { 0x5A5E, 9002 }, + { 0x5A5F, 9009 }, + { 0x6B00, 17897 }, + { 0x6B01, 17901 }, + { 0x6B02, 17905 }, + { 0x6B03, 17921 }, + { 0x6B04, 17925 }, + { 0x6B05, 17929 }, + { 0x6B06, 17917 }, + { 0x6B13, 44892 }, + { 0x6B14, 44882 }, + { 0x6B15, 44887 }, + { 0x6B16, 44902 }, + { 0x6B17, 44897 }, + { 0x6B1D, 33182 }, + { 0x6B1E, 32972 }, + { 0x6B1F, 33388 }, + { 0x6B20, 33370 }, + { 0x6B21, 33269 }, + { 0x6B22, 33277 }, + { 0x6B23, 33257 }, + { 0x6B24, 33261 }, + { 0x6B25, 33286 }, + { 0x6B26, 33281 }, + { 0x6B27, 33273 }, + { 0x6B28, 33265 }, + { 0x6B29, 33374 }, + { 0x6B2A, 33230 }, + { 0x6B2B, 33224 }, + { 0x6B2C, 33249 }, + { 0x6B2D, 33241 }, + { 0x6B2E, 33200 }, + { 0x6B2F, 33205 }, + { 0x6B30, 33195 }, + { 0x6B31, 33105 }, + { 0x6B32, 33333 }, + { 0x6B33, 33293 }, + { 0x6B34, 33079 }, + { 0x6B35, 33174 }, + { 0x6B36, 33357 }, + { 0x6B38, 33161 }, + { 0x6B39, 33187 }, + { 0x6B3A, 33312 }, + { 0x6B3B, 33121 }, + { 0x6B3C, 33341 }, + { 0x6B3E, 33129 }, + { 0x6B40, 33137 }, + { 0x6B41, 33365 }, + { 0x6B43, 33302 }, + { 0x6B44, 33092 }, + { 0x6B46, 33349 }, + { 0x6B47, 33145 }, + { 0x6B48, 33216 }, + { 0x6B49, 33236 }, + { 0x6B4A, 33153 }, + { 0x6B4B, 33169 }, + { 0x6B4C, 33100 }, + { 0x6B4D, 33116 }, + { 0x6B4E, 33087 }, + { 0x6B4F, 33379 }, + { 0x6B50, 25426 }, + { 0x6B51, 25420 }, + { 0x6B52, 25471 }, + { 0x6B53, 25456 }, + { 0x6B54, 25466 }, + { 0x6B55, 25461 }, + { 0x6B56, 24792 }, + { 0x6B57, 24777 }, + { 0x6B58, 24787 }, + { 0x6B59, 24782 }, + { 0x6B5A, 25928 }, + { 0x6B5B, 25913 }, + { 0x6B5C, 25923 }, + { 0x6B5D, 25918 }, + { 0x6B5E, 26308 }, + { 0x6B5F, 26293 }, + { 0x6B60, 26303 }, + { 0x6B61, 26298 }, + { 0x6B62, 26272 }, + { 0x6B63, 26257 }, + { 0x6B64, 26267 }, + { 0x6B65, 26262 }, + { 0x6B66, 25892 }, + { 0x6B67, 25877 }, + { 0x6B68, 25887 }, + { 0x6B69, 25882 }, + { 0x6B6A, 25071 }, + { 0x6B6B, 25056 }, + { 0x6B6C, 25066 }, + { 0x6B6D, 25061 }, + { 0x6B6E, 26164 }, + { 0x6B6F, 26149 }, + { 0x6B70, 26159 }, + { 0x6B71, 26154 }, + { 0x6B72, 25507 }, + { 0x6B73, 25492 }, + { 0x6B74, 25502 }, + { 0x6B75, 25497 }, + { 0x6B76, 25729 }, + { 0x6B77, 25714 }, + { 0x6B78, 25724 }, + { 0x6B79, 25719 }, + { 0x6B7A, 26249 }, + { 0x6B7B, 26234 }, + { 0x6B7C, 26244 }, + { 0x6B7D, 26239 }, + { 0x6B7E, 26393 }, + { 0x6B7F, 26378 }, + { 0x6B80, 26388 }, + { 0x6B81, 26383 }, + { 0x6B82, 26285 }, + { 0x6B83, 26280 }, + { 0x6B84, 25941 }, + { 0x6B85, 25936 }, + { 0x6B86, 24341 }, + { 0x6B87, 24336 }, + { 0x6B88, 25484 }, + { 0x6B89, 25479 }, + { 0x6B8A, 24667 }, + { 0x6B8B, 24662 }, + { 0x6B8C, 25742 }, + { 0x6B8D, 25737 }, + { 0x6B8E, 26118 }, + { 0x6B8F, 26103 }, + { 0x6B90, 26113 }, + { 0x6B91, 26108 }, + { 0x6B92, 24442 }, + { 0x6B93, 24427 }, + { 0x6B94, 24437 }, + { 0x6B95, 24432 }, + { 0x6B96, 25530 }, + { 0x6B97, 25515 }, + { 0x6B98, 25525 }, + { 0x6B99, 25520 }, + { 0x6B9A, 26141 }, + { 0x6B9B, 26126 }, + { 0x6B9C, 26136 }, + { 0x6B9D, 26131 }, + { 0x6B9E, 25690 }, + { 0x6B9F, 25684 }, + { 0x6BA0, 26187 }, + { 0x6BA1, 26172 }, + { 0x6BA2, 26182 }, + { 0x6BA3, 26177 }, + { 0x6BA4, 24597 }, + { 0x6BA5, 24589 }, + { 0x6BA6, 24577 }, + { 0x6BA7, 24559 }, + { 0x6BA8, 24571 }, + { 0x6BA9, 24565 }, + { 0x6BAA, 24653 }, + { 0x6BAB, 24635 }, + { 0x6BAC, 24647 }, + { 0x6BAD, 24641 }, + { 0x6BAE, 25266 }, + { 0x6BAF, 25260 }, + { 0x6BB0, 25231 }, + { 0x6BB1, 25222 }, + { 0x6BD3, 24046 }, + { 0x6BD4, 24031 }, + { 0x6BD5, 24041 }, + { 0x6BD6, 24036 }, + { 0x6BD7, 24020 }, + { 0x6BD8, 24015 }, + { 0x6BD9, 24059 }, + { 0x6BDA, 24054 }, + { 0x6BDB, 24085 }, + { 0x6BDC, 24080 }, + { 0x6BDD, 24007 }, + { 0x6BDE, 24072 }, + { 0x6BDF, 24067 }, + { 0x6BE0, 26353 }, + { 0x6BE1, 26347 }, + { 0x6BE2, 26369 }, + { 0x6BE3, 26363 }, + { 0x6BE4, 23993 }, + { 0x6BE5, 23978 }, + { 0x6BE6, 23988 }, + { 0x6BE7, 23983 }, + { 0x6BE8, 26322 }, + { 0x6BE9, 26313 }, + { 0x6BEA, 28622 }, + { 0x6BEB, 28590 }, + { 0x6BEC, 28450 }, + { 0x6BED, 28440 }, + { 0x6BEE, 28560 }, + { 0x6BEF, 28550 }, + { 0x6BF0, 28430 }, + { 0x6BF1, 28420 }, + { 0x6BF2, 28470 }, + { 0x6BF3, 28460 }, + { 0x6BF4, 28490 }, + { 0x6BF5, 28480 }, + { 0x6BF6, 28410 }, + { 0x6BF7, 28390 }, + { 0x6BF8, 28400 }, + { 0x6BF9, 30178 }, + { 0x6BFA, 30152 }, + { 0x6BFB, 30165 }, + { 0x6BFC, 26021 }, + { 0x6BFD, 26003 }, + { 0x6BFE, 26015 }, + { 0x6BFF, 26009 }, + { 0x6C00, 28642 }, + { 0x6C01, 28510 }, + { 0x6C02, 28692 }, + { 0x6C03, 28611 }, + { 0x6C04, 28580 }, + { 0x6C05, 26665 }, + { 0x6C06, 26600 }, + { 0x6C07, 26688 }, + { 0x6C08, 26716 }, + { 0x6C09, 26650 }, + { 0x6C0A, 26635 }, + { 0x6C0B, 28073 }, + { 0x6C0C, 27980 }, + { 0x6C0D, 28115 }, + { 0x6C0E, 28189 }, + { 0x6C0F, 28030 }, + { 0x6C10, 28015 }, + { 0x6C11, 29671 }, + { 0x6C12, 29699 }, + { 0x6C13, 29663 }, + { 0x6C14, 29648 }, + { 0x6C15, 28801 }, + { 0x6C16, 28882 }, + { 0x6C17, 27033 }, + { 0x6C18, 27066 }, + { 0x6C19, 28933 }, + { 0x6C1A, 28889 }, + { 0x6C1B, 28947 }, + { 0x6C1C, 29506 }, + { 0x6C1D, 29408 }, + { 0x6C1E, 29546 }, + { 0x6C1F, 29612 }, + { 0x6C20, 27755 }, + { 0x6C21, 27838 }, + { 0x6C22, 26821 }, + { 0x6C23, 26763 }, + { 0x6C24, 26853 }, + { 0x6C25, 26867 }, + { 0x6C26, 27852 }, + { 0x6C27, 27939 }, + { 0x6C28, 28736 }, + { 0x6C29, 26526 }, + { 0x6C2A, 26577 }, + { 0x6C2B, 29767 }, + { 0x6C2C, 29809 }, + { 0x6C2D, 26925 }, + { 0x6C2E, 26881 }, + { 0x6C2F, 26957 }, + { 0x6C30, 26980 }, + { 0x6C31, 26910 }, + { 0x6C32, 26895 }, + { 0x6C33, 27626 }, + { 0x6C34, 27706 }, + { 0x6C35, 27655 }, + { 0x6C36, 27640 }, + { 0x6C37, 27221 }, + { 0x6C38, 27235 }, + { 0x6C39, 27149 }, + { 0x6C3A, 27249 }, + { 0x6C3B, 27177 }, + { 0x6C3C, 27304 }, + { 0x6C3D, 27213 }, + { 0x6C3E, 27191 }, + { 0x6C3F, 27525 }, + { 0x6C40, 27355 }, + { 0x6C41, 27557 }, + { 0x6C42, 27612 }, + { 0x6C43, 27458 }, + { 0x6C44, 27376 }, + { 0x6C45, 29060 }, + { 0x6C46, 28988 }, + { 0x6C47, 29101 }, + { 0x6C48, 29131 }, + { 0x6C49, 29009 }, + { 0x6C4A, 28995 }, + { 0x6C4B, 29293 }, + { 0x6C4C, 29173 }, + { 0x6C4D, 29307 }, + { 0x6C4E, 29354 }, + { 0x6C4F, 29223 }, + { 0x6C50, 29208 }, + { 0x6C51, 27095 }, + { 0x6C52, 27127 }, + { 0x6C53, 27080 }, + { 0x6C54, 27073 }, + { 0x6C55, 28300 }, + { 0x6C56, 28226 }, + { 0x6C57, 28314 }, + { 0x6C58, 28369 }, + { 0x6C59, 28276 }, + { 0x6C5A, 28261 }, + { 0x6C5B, 29619 }, + { 0x6C5C, 27713 }, + { 0x6C5D, 28766 }, + { 0x6C5E, 30130 }, + { 0x6C5F, 30137 }, + { 0x6C60, 30109 }, + { 0x6C61, 30095 }, + { 0x6C62, 30123 }, + { 0x6C63, 30144 }, + { 0x6C64, 28540 }, + { 0x6C65, 28712 }, + { 0x6C66, 28662 }, + { 0x6C67, 28702 }, + { 0x6C68, 28600 }, + { 0x6C69, 28570 }, + { 0x6C6A, 26621 }, + { 0x6C6B, 26730 }, + { 0x6C6C, 26695 }, + { 0x6C6D, 26723 }, + { 0x6C6E, 26642 }, + { 0x6C6F, 26628 }, + { 0x6C70, 28001 }, + { 0x6C71, 28203 }, + { 0x6C72, 28168 }, + { 0x6C73, 28196 }, + { 0x6C74, 28022 }, + { 0x6C75, 28008 }, + { 0x6C76, 29634 }, + { 0x6C77, 29713 }, + { 0x6C78, 29678 }, + { 0x6C79, 29706 }, + { 0x6C7A, 29655 }, + { 0x6C7B, 29641 }, + { 0x6C7C, 26902 }, + { 0x6C7D, 26888 }, + { 0x6C7E, 27647 }, + { 0x6C7F, 27633 }, + { 0x6C80, 27198 }, + { 0x6C81, 27156 }, + { 0x6C82, 27283 }, + { 0x6C83, 27205 }, + { 0x6C84, 27184 }, + { 0x6C85, 27591 }, + { 0x6C86, 27450 }, + { 0x6C87, 27369 }, + { 0x6C88, 29002 }, + { 0x6C89, 29117 }, + { 0x6C8A, 29194 }, + { 0x6C8B, 29368 }, + { 0x6C8C, 29333 }, + { 0x6C8D, 29361 }, + { 0x6C8E, 29215 }, + { 0x6C8F, 29201 }, + { 0x6C90, 28757 }, + { 0x6C91, 28247 }, + { 0x6C92, 28383 }, + { 0x6C93, 28348 }, + { 0x6C94, 28376 }, + { 0x6C95, 28268 }, + { 0x6C96, 28254 }, + { 0x6C97, 28632 }, + { 0x6C98, 28500 }, + { 0x6C99, 28652 }, + { 0x6C9A, 28682 }, + { 0x6C9B, 28530 }, + { 0x6C9C, 26658 }, + { 0x6C9D, 26593 }, + { 0x6C9E, 26681 }, + { 0x6C9F, 26709 }, + { 0x6CA0, 26614 }, + { 0x6CA1, 28066 }, + { 0x6CA2, 27973 }, + { 0x6CA3, 28108 }, + { 0x6CA4, 28182 }, + { 0x6CA5, 27994 }, + { 0x6CA6, 29692 }, + { 0x6CA7, 28794 }, + { 0x6CA8, 28875 }, + { 0x6CA9, 27026 }, + { 0x6CAA, 27059 }, + { 0x6CAB, 28926 }, + { 0x6CAC, 28940 }, + { 0x6CAD, 29499 }, + { 0x6CAE, 29401 }, + { 0x6CAF, 29539 }, + { 0x6CB0, 29605 }, + { 0x6CB1, 27748 }, + { 0x6CB2, 27806 }, + { 0x6CB3, 27831 }, + { 0x6CB4, 26814 }, + { 0x6CB5, 26756 }, + { 0x6CB6, 26846 }, + { 0x6CB7, 26860 }, + { 0x6CB8, 27845 }, + { 0x6CB9, 28729 }, + { 0x6CBA, 26519 }, + { 0x6CBB, 26570 }, + { 0x6CBC, 29760 }, + { 0x6CBD, 29802 }, + { 0x6CBE, 26918 }, + { 0x6CBF, 26874 }, + { 0x6CC0, 26950 }, + { 0x6CC1, 26973 }, + { 0x6CC2, 27619 }, + { 0x6CC3, 27699 }, + { 0x6CC4, 27228 }, + { 0x6CC5, 27142 }, + { 0x6CC6, 27242 }, + { 0x6CC7, 27170 }, + { 0x6CC8, 27297 }, + { 0x6CC9, 27518 }, + { 0x6CCA, 27348 }, + { 0x6CCB, 27550 }, + { 0x6CCC, 27605 }, + { 0x6CCD, 27362 }, + { 0x6CCE, 29053 }, + { 0x6CCF, 28981 }, + { 0x6CD0, 29094 }, + { 0x6CD1, 29124 }, + { 0x6CD2, 29286 }, + { 0x6CD3, 29166 }, + { 0x6CD4, 29300 }, + { 0x6CD5, 29347 }, + { 0x6CD6, 29187 }, + { 0x6CD7, 27088 }, + { 0x6CD8, 27120 }, + { 0x6CD9, 27134 }, + { 0x6CDA, 28293 }, + { 0x6CDB, 28219 }, + { 0x6CDC, 28307 }, + { 0x6CDD, 28362 }, + { 0x6CDE, 28240 }, + { 0x6CDF, 28672 }, + { 0x6CE0, 28520 }, + { 0x6CE1, 26702 }, + { 0x6CE2, 26607 }, + { 0x6CE3, 28175 }, + { 0x6CE4, 27987 }, + { 0x6CE5, 29685 }, + { 0x6CE6, 29627 }, + { 0x6CE7, 29598 }, + { 0x6CE8, 29415 }, + { 0x6CE9, 30057 }, + { 0x6CEA, 29891 }, + { 0x6CEB, 27163 }, + { 0x6CEC, 27290 }, + { 0x6CED, 27598 }, + { 0x6CEE, 29340 }, + { 0x6CEF, 29180 }, + { 0x6CF0, 28355 }, + { 0x6CF1, 28233 }, + { 0x6CF2, 30102 }, + { 0x6CF3, 30088 }, + { 0x6CF4, 30116 }, + { 0x6CF5, 27881 }, + { 0x6CF6, 27866 }, + { 0x6CF7, 26493 }, + { 0x6CF8, 26478 }, + { 0x6CF9, 29752 }, + { 0x6CFA, 29737 }, + { 0x6CFB, 29465 }, + { 0x6CFC, 29450 }, + { 0x6CFD, 29941 }, + { 0x6CFE, 29926 }, + { 0x6CFF, 27009 }, + { 0x6D00, 26994 }, + { 0x6D01, 28830 }, + { 0x6D02, 28815 }, + { 0x6D03, 28918 }, + { 0x6D04, 28903 }, + { 0x6D05, 27798 }, + { 0x6D06, 27783 }, + { 0x6D07, 26806 }, + { 0x6D08, 26791 }, + { 0x6D09, 29979 }, + { 0x6D0A, 29884 }, + { 0x6D0B, 30007 }, + { 0x6D0C, 30071 }, + { 0x6D0D, 29912 }, + { 0x6D0E, 29436 }, + { 0x6D0F, 27769 }, + { 0x6D10, 26777 }, + { 0x6D11, 27873 }, + { 0x6D12, 27859 }, + { 0x6D13, 26485 }, + { 0x6D14, 26471 }, + { 0x6D15, 29744 }, + { 0x6D16, 29730 }, + { 0x6D17, 29457 }, + { 0x6D18, 29443 }, + { 0x6D19, 29933 }, + { 0x6D1A, 29919 }, + { 0x6D1B, 27001 }, + { 0x6D1C, 26987 }, + { 0x6D1D, 28822 }, + { 0x6D1E, 28808 }, + { 0x6D1F, 28910 }, + { 0x6D20, 28896 }, + { 0x6D21, 27790 }, + { 0x6D22, 27776 }, + { 0x6D23, 26798 }, + { 0x6D24, 26784 }, + { 0x6D25, 29958 }, + { 0x6D26, 29863 }, + { 0x6D27, 29986 }, + { 0x6D28, 30050 }, + { 0x6D29, 29905 }, + { 0x6D2A, 29429 }, + { 0x6D2B, 27762 }, + { 0x6D2C, 26770 }, + { 0x6D2D, 29972 }, + { 0x6D2E, 29877 }, + { 0x6D2F, 30000 }, + { 0x6D30, 30064 }, + { 0x6D31, 29422 }, + { 0x6D32, 29898 }, + { 0x6D33, 27932 }, + { 0x6D34, 29492 }, + { 0x6D35, 29394 }, + { 0x6D36, 29532 }, + { 0x6D37, 29965 }, + { 0x6D38, 29870 }, + { 0x6D39, 29993 }, + { 0x6D3A, 27925 }, + { 0x6D3B, 28722 }, + { 0x6D3C, 28743 }, + { 0x6D3D, 28750 }, + { 0x6D3E, 35643 }, + { 0x6D3F, 35646 }, + { 0x6D50, 28057 }, + { 0x6D51, 27946 }, + { 0x6D52, 27955 }, + { 0x6D53, 27964 }, + { 0x6D54, 28099 }, + { 0x6D55, 28150 }, + { 0x6D56, 28122 }, + { 0x6D57, 28159 }, + { 0x6D58, 28838 }, + { 0x6D59, 28847 }, + { 0x6D5A, 27040 }, + { 0x6D5B, 27049 }, + { 0x6D5C, 29385 }, + { 0x6D5D, 29473 }, + { 0x6D5E, 29482 }, + { 0x6D5F, 29553 }, + { 0x6D60, 29562 }, + { 0x6D61, 29571 }, + { 0x6D62, 29580 }, + { 0x6D63, 29589 }, + { 0x6D64, 27721 }, + { 0x6D65, 27730 }, + { 0x6D66, 27813 }, + { 0x6D67, 29845 }, + { 0x6D68, 29854 }, + { 0x6D69, 29949 }, + { 0x6D6A, 30014 }, + { 0x6D6B, 30023 }, + { 0x6D6C, 30032 }, + { 0x6D6D, 30041 }, + { 0x6D6E, 26746 }, + { 0x6D6F, 26828 }, + { 0x6D70, 26837 }, + { 0x6D71, 27889 }, + { 0x6D72, 27898 }, + { 0x6D73, 27916 }, + { 0x6D74, 27907 }, + { 0x6D75, 26501 }, + { 0x6D76, 26552 }, + { 0x6D77, 26561 }, + { 0x6D78, 26542 }, + { 0x6D79, 29793 }, + { 0x6D7A, 29774 }, + { 0x6D7B, 29783 }, + { 0x6D7C, 26932 }, + { 0x6D7D, 26941 }, + { 0x6D7E, 27663 }, + { 0x6D7F, 27690 }, + { 0x6D80, 27330 }, + { 0x6D81, 27311 }, + { 0x6D82, 27320 }, + { 0x6D83, 27491 }, + { 0x6D84, 27482 }, + { 0x6D85, 27532 }, + { 0x6D86, 27541 }, + { 0x6D87, 27564 }, + { 0x6D88, 27573 }, + { 0x6D89, 28963 }, + { 0x6D8A, 28972 }, + { 0x6D8B, 28954 }, + { 0x6D8C, 29017 }, + { 0x6D8D, 29044 }, + { 0x6D8E, 29076 }, + { 0x6D8F, 29085 }, + { 0x6D92, 29035 }, + { 0x6D93, 27102 }, + { 0x6D94, 27111 }, + { 0x6D95, 29157 }, + { 0x6D96, 29147 }, + { 0x6D97, 29268 }, + { 0x6D98, 29277 }, + { 0x6D99, 29258 }, + { 0x6D9A, 29314 }, + { 0x6D9B, 29323 }, + { 0x6D9C, 28330 }, + { 0x6D9D, 28339 }, + { 0x6D9E, 26672 }, + { 0x6D9F, 28038 }, + { 0x6DA0, 28047 }, + { 0x6DA1, 28080 }, + { 0x6DA2, 28089 }, + { 0x6DA3, 28131 }, + { 0x6DA4, 28140 }, + { 0x6DA5, 28856 }, + { 0x6DA6, 28784 }, + { 0x6DA7, 28865 }, + { 0x6DA8, 29522 }, + { 0x6DA9, 27739 }, + { 0x6DAA, 29836 }, + { 0x6DAB, 26737 }, + { 0x6DAC, 27473 }, + { 0x6DAD, 27582 }, + { 0x6DAE, 28210 }, + { 0x6DAF, 28284 }, + { 0x6DB0, 28321 }, + { 0x6DB1, 29108 }, + { 0x6DB2, 27681 }, + { 0x6DB3, 29138 }, + { 0x6DB4, 27672 }, + { 0x6DB5, 27339 }, + { 0x6DB6, 26533 }, + { 0x6DB7, 27256 }, + { 0x6DB8, 29240 }, + { 0x6DB9, 29067 }, + { 0x6DBA, 27509 }, + { 0x6DBB, 27265 }, + { 0x6DBC, 27500 }, + { 0x6DBD, 29231 }, + { 0x6DBE, 28775 }, + { 0x6DBF, 27017 }, + { 0x6DC0, 29026 }, + { 0x6DC1, 26964 }, + { 0x6DC2, 26584 }, + { 0x6DC3, 27274 }, + { 0x6DC4, 26510 }, + { 0x6DC5, 27822 }, + { 0x6DC6, 29513 }, + { 0x6DC7, 29249 }, + { 0x6DF0, 29821 }, + { 0x6DF1, 29375 }, + { 0x6DF2, 29725 }, + { 0x6DF3, 29720 }, + { 0x6DF4, 30191 }, + { 0x6DF5, 29816 }, + { 0x6DF6, 30083 }, + { 0x6DF7, 30078 }, + { 0x6DF8, 30196 }, + { 0x6DF9, 29831 }, + { 0x6DFA, 30206 }, + { 0x6DFB, 30211 }, + { 0x6DFC, 9693 }, + { 0x6DFD, 30201 }, + { 0x6E00, 66314 }, + { 0x6E01, 66316 }, + { 0x6E02, 66318 }, + { 0x6E03, 66320 }, + { 0x6E04, 66322 }, + { 0x6E05, 66324 }, + { 0x6E06, 66326 }, + { 0x6E07, 66328 }, + { 0x6E08, 66330 }, + { 0x6E09, 66332 }, + { 0x6E0A, 66334 }, + { 0x6E0B, 66336 }, + { 0x6E0C, 66338 }, + { 0x6E0D, 66340 }, + { 0x6E0E, 66342 }, + { 0x6E0F, 66344 }, + { 0x6E10, 74355 }, + { 0x6E11, 74464 }, + { 0x6E12, 74457 }, + { 0x6E13, 74350 }, + { 0x6E14, 74440 }, + { 0x6E15, 74451 }, + { 0x6E16, 74434 }, + { 0x6E17, 74299 }, + { 0x6E18, 74390 }, + { 0x6E19, 74445 }, + { 0x6E20, 58207 }, + { 0x6E21, 58211 }, + { 0x6E22, 57894 }, + { 0x6E23, 57899 }, + { 0x6E24, 57948 }, + { 0x6E25, 57955 }, + { 0x6E26, 58290 }, + { 0x6E30, 74262 }, + { 0x6E31, 74244 }, + { 0x6E32, 74250 }, + { 0x6E33, 74256 }, + { 0x6E34, 74343 }, + { 0x6E35, 74337 }, + { 0x6E36, 74428 }, + { 0x6E37, 74284 }, + { 0x6E38, 74375 }, + { 0x6E39, 74329 }, + { 0x6E3A, 74420 }, + { 0x6E3B, 74276 }, + { 0x6E3C, 74367 }, + { 0x6E3D, 74314 }, + { 0x6E3E, 74405 }, + { 0x6E3F, 74269 }, + { 0x6E40, 74360 }, + { 0x6E41, 74307 }, + { 0x6E42, 74398 }, + { 0x6E43, 74291 }, + { 0x6E44, 74382 }, + { 0x6E45, 35852 }, + { 0x6E46, 23293 }, + { 0x6E47, 74322 }, + { 0x6E48, 74413 }, + { 0x6E49, 31173 }, + { 0x6E4A, 66833 }, + { 0x6E4B, 10082 }, + { 0x6E4C, 31561 }, + { 0x6E4D, 31170 }, + { 0x6E4E, 66830 }, + { 0x6E4F, 10075 }, + { 0x6E50, 22507 }, + { 0x6E51, 22660 }, + { 0x6E52, 22487 }, + { 0x6E54, 22652 }, + { 0x6E55, 22505 }, + { 0x6E56, 22644 }, + { 0x6E57, 22657 }, + { 0x6E58, 22480 }, + { 0x6E59, 22499 }, + { 0x6E5A, 22518 }, + { 0x6E5B, 22490 }, + { 0x6E5C, 22509 }, + { 0x6E5D, 22494 }, + { 0x6E5E, 22513 }, + { 0x6E5F, 22596 }, + { 0x6E60, 22647 }, + { 0x6E61, 22624 }, + { 0x6E62, 22502 }, + { 0x6E63, 22666 }, + { 0x6E64, 22649 }, + { 0x6E65, 22663 }, + { 0x6E66, 22593 }, + { 0x6E68, 22621 }, + { 0x6E69, 22590 }, + { 0x6E6A, 22618 }, + { 0x6E6B, 22654 }, + { 0x6E70, 26455 }, + { 0x6E71, 26442 }, + { 0x6E72, 26449 }, + { 0x6E73, 23761 }, + { 0x6E74, 26467 }, + { 0x6E76, 23797 }, + { 0x6E77, 23793 }, + { 0x6E78, 23772 }, + { 0x6E79, 23768 }, + { 0x6E7A, 23813 }, + { 0x6E7B, 23809 }, + { 0x6E7C, 26418 }, + { 0x6E7D, 26414 }, + { 0x6E7E, 23953 }, + { 0x6E7F, 23949 }, + { 0x6E80, 26059 }, + { 0x6E81, 25385 }, + { 0x6E82, 25377 }, + { 0x6E83, 25341 }, + { 0x6E84, 25333 }, + { 0x6E85, 25111 }, + { 0x6E86, 25103 }, + { 0x6E87, 25363 }, + { 0x6E88, 25355 }, + { 0x6E89, 25185 }, + { 0x6E8A, 25161 }, + { 0x6E8B, 25177 }, + { 0x6E8C, 25169 }, + { 0x6E8D, 25448 }, + { 0x6E8E, 25411 }, + { 0x6E8F, 24226 }, + { 0x6E90, 24211 }, + { 0x6E91, 24221 }, + { 0x6E92, 24216 }, + { 0x6E93, 25042 }, + { 0x6E94, 25036 }, + { 0x6E95, 25048 }, + { 0x6E96, 25012 }, + { 0x6E97, 25022 }, + { 0x6E98, 25017 }, + { 0x6E99, 25869 }, + { 0x6E9A, 25854 }, + { 0x6E9B, 25864 }, + { 0x6E9C, 25859 }, + { 0x6E9D, 25572 }, + { 0x6E9E, 25557 }, + { 0x6E9F, 25567 }, + { 0x6EA0, 25562 }, + { 0x6EA1, 24540 }, + { 0x6EA2, 24525 }, + { 0x6EA3, 24535 }, + { 0x6EA4, 24530 }, + { 0x6EA5, 25595 }, + { 0x6EA6, 25580 }, + { 0x6EA7, 25590 }, + { 0x6EA8, 25585 }, + { 0x6EA9, 24328 }, + { 0x6EAA, 24323 }, + { 0x6EAB, 25846 }, + { 0x6EAC, 25841 }, + { 0x6EAD, 24924 }, + { 0x6EAE, 24919 }, + { 0x6EAF, 25905 }, + { 0x6EB0, 25900 }, + { 0x6EB1, 25833 }, + { 0x6EB2, 25818 }, + { 0x6EB3, 25828 }, + { 0x6EB4, 25823 }, + { 0x6EB5, 26216 }, + { 0x6EB6, 26201 }, + { 0x6EB7, 26211 }, + { 0x6EB8, 26206 }, + { 0x6EB9, 24961 }, + { 0x6EBA, 24946 }, + { 0x6EBB, 24956 }, + { 0x6EBC, 24951 }, + { 0x6EBD, 24255 }, + { 0x6EBE, 24240 }, + { 0x6EBF, 24250 }, + { 0x6EC0, 24245 }, + { 0x6EC1, 24991 }, + { 0x6EC2, 24976 }, + { 0x6EC3, 24986 }, + { 0x6EC4, 24981 }, + { 0x6EC5, 25305 }, + { 0x6EC6, 25290 }, + { 0x6EC7, 25300 }, + { 0x6EC8, 25295 }, + { 0x6EC9, 24139 }, + { 0x6ECA, 24124 }, + { 0x6ECB, 24134 }, + { 0x6ECC, 24129 }, + { 0x6ECD, 26051 }, + { 0x6ECE, 26036 }, + { 0x6ECF, 26046 }, + { 0x6ED0, 26041 }, + { 0x6ED1, 24400 }, + { 0x6ED2, 24385 }, + { 0x6ED3, 24395 }, + { 0x6ED4, 24390 }, + { 0x6ED5, 24828 }, + { 0x6ED6, 24813 }, + { 0x6ED7, 24823 }, + { 0x6ED8, 24818 }, + { 0x6ED9, 24715 }, + { 0x6EDA, 24700 }, + { 0x6EDB, 24710 }, + { 0x6EDC, 24705 }, + { 0x6EDD, 24769 }, + { 0x6EDE, 24754 }, + { 0x6EDF, 24764 }, + { 0x6EE0, 24759 }, + { 0x6EE1, 25630 }, + { 0x6EE2, 25615 }, + { 0x6EE3, 25625 }, + { 0x6EE4, 25620 }, + { 0x6EE5, 25706 }, + { 0x6EE6, 25675 }, + { 0x6EE7, 25701 }, + { 0x6EE8, 25696 }, + { 0x6EE9, 24626 }, + { 0x6EEA, 24611 }, + { 0x6EEB, 24621 }, + { 0x6EEC, 24616 }, + { 0x6EED, 25142 }, + { 0x6EEE, 25137 }, + { 0x6EEF, 25442 }, + { 0x6EF0, 25436 }, + { 0x6EF1, 25282 }, + { 0x6EF2, 25206 }, + { 0x6EF3, 25277 }, + { 0x6EF4, 25272 }, + { 0x6EF5, 27433 }, + { 0x6EF6, 27423 }, + { 0x6EF7, 27393 }, + { 0x6EF8, 27383 }, + { 0x6EF9, 27413 }, + { 0x6EFA, 27403 }, + { 0x6EFB, 27466 }, + { 0x6EFC, 27443 }, + { 0x6EFF, 10095 }, + { 0x6F01, 63786 }, + { 0x6F02, 63773 }, + { 0x6F03, 63749 }, + { 0x6F04, 63741 }, + { 0x6F05, 63752 }, + { 0x6F06, 63768 }, + { 0x6F07, 63778 }, + { 0x6F08, 63415 }, + { 0x6F09, 63733 }, + { 0x6F0A, 63760 }, + { 0x6F0B, 63418 }, + { 0x6F0C, 63423 }, + { 0x6F0D, 63792 }, + { 0x6F0E, 63400 }, + { 0x6F0F, 63758 }, + { 0x6F10, 63443 }, + { 0x6F11, 63425 }, + { 0x6F12, 63431 }, + { 0x6F13, 63452 }, + { 0x6F14, 63437 }, + { 0x6F15, 63434 }, + { 0x6F16, 63428 }, + { 0x6F17, 63449 }, + { 0x6F18, 63446 }, + { 0x6F19, 63440 }, + { 0x6F1A, 63421 }, + { 0x6F1B, 63776 }, + { 0x6F1C, 63770 }, + { 0x6F1D, 63744 }, + { 0x6F1E, 63789 }, + { 0x6F1F, 63762 }, + { 0x6F20, 63783 }, + { 0x6F21, 63588 }, + { 0x6F22, 63593 }, + { 0x6F23, 63598 }, + { 0x6F24, 63603 }, + { 0x6F25, 63608 }, + { 0x6F26, 63613 }, + { 0x6F27, 63618 }, + { 0x6F28, 63623 }, + { 0x6F29, 63628 }, + { 0x6F2A, 63633 }, + { 0x6F2B, 63638 }, + { 0x6F2C, 63643 }, + { 0x6F2D, 63648 }, + { 0x6F2E, 63653 }, + { 0x6F2F, 63658 }, + { 0x6F30, 63663 }, + { 0x6F31, 63668 }, + { 0x6F32, 63673 }, + { 0x6F33, 63678 }, + { 0x6F34, 63683 }, + { 0x6F35, 63688 }, + { 0x6F36, 63693 }, + { 0x6F37, 63698 }, + { 0x6F38, 63703 }, + { 0x6F39, 63708 }, + { 0x6F3A, 63713 }, + { 0x6F3B, 63411 }, + { 0x6F3C, 63755 }, + { 0x6F3D, 63729 }, + { 0x6F3E, 63780 }, + { 0x6F3F, 63385 }, + { 0x6F40, 63455 }, + { 0x6F41, 63458 }, + { 0x6F42, 63463 }, + { 0x6F43, 63468 }, + { 0x6F44, 63473 }, + { 0x6F45, 63478 }, + { 0x6F46, 63483 }, + { 0x6F47, 63488 }, + { 0x6F48, 63493 }, + { 0x6F49, 63498 }, + { 0x6F4A, 63503 }, + { 0x6F4B, 63508 }, + { 0x6F4C, 63513 }, + { 0x6F4D, 63518 }, + { 0x6F4E, 63523 }, + { 0x6F4F, 63528 }, + { 0x6F50, 63533 }, + { 0x6F51, 63538 }, + { 0x6F52, 63543 }, + { 0x6F53, 63548 }, + { 0x6F54, 63553 }, + { 0x6F55, 63558 }, + { 0x6F56, 63563 }, + { 0x6F57, 63568 }, + { 0x6F58, 63573 }, + { 0x6F59, 63578 }, + { 0x6F5A, 63583 }, + { 0x6F5B, 63403 }, + { 0x6F5C, 63765 }, + { 0x6F5D, 63721 }, + { 0x6F5E, 63736 }, + { 0x6F5F, 63407 }, + { 0x6F60, 63725 }, + { 0x6F61, 64276 }, + { 0x6F62, 63796 }, + { 0x6F63, 63807 }, + { 0x6F64, 64280 }, + { 0x6F65, 64253 }, + { 0x6F66, 64192 }, + { 0x6F67, 64208 }, + { 0x6F68, 64218 }, + { 0x6F69, 64228 }, + { 0x6F6A, 64213 }, + { 0x6F6B, 64223 }, + { 0x6F6C, 64238 }, + { 0x6F6D, 64248 }, + { 0x6F6E, 64243 }, + { 0x6F6F, 64233 }, + { 0x6F70, 64283 }, + { 0x6F71, 64024 }, + { 0x6F72, 64032 }, + { 0x6F73, 64044 }, + { 0x6F74, 64028 }, + { 0x6F75, 64040 }, + { 0x6F76, 64068 }, + { 0x6F77, 64076 }, + { 0x6F78, 64084 }, + { 0x6F79, 64072 }, + { 0x6F7A, 64080 }, + { 0x6F7B, 64148 }, + { 0x6F7C, 64156 }, + { 0x6F7D, 64164 }, + { 0x6F7E, 64152 }, + { 0x6F7F, 64160 }, + { 0x6F80, 64168 }, + { 0x6F81, 64176 }, + { 0x6F82, 64184 }, + { 0x6F83, 64172 }, + { 0x6F84, 64180 }, + { 0x6F85, 64108 }, + { 0x6F86, 64116 }, + { 0x6F87, 64124 }, + { 0x6F88, 64112 }, + { 0x6F89, 64120 }, + { 0x6F8A, 64048 }, + { 0x6F8B, 64056 }, + { 0x6F8C, 64064 }, + { 0x6F8D, 64052 }, + { 0x6F8E, 64060 }, + { 0x6F8F, 64088 }, + { 0x6F90, 64096 }, + { 0x6F91, 64104 }, + { 0x6F92, 64092 }, + { 0x6F93, 64100 }, + { 0x6F94, 64196 }, + { 0x6F95, 64204 }, + { 0x6F96, 64200 }, + { 0x6F97, 64128 }, + { 0x6F98, 64136 }, + { 0x6F99, 64144 }, + { 0x6F9A, 64132 }, + { 0x6F9B, 64140 }, + { 0x6F9C, 64188 }, + { 0x6F9D, 64036 }, + { 0x6F9E, 64257 }, + { 0x6F9F, 64262 }, + { 0x6FA0, 63814 }, + { 0x6FA1, 63933 }, + { 0x6FA2, 64001 }, + { 0x6FA3, 63977 }, + { 0x6FA4, 63921 }, + { 0x6FA5, 63981 }, + { 0x6FA6, 63985 }, + { 0x6FA7, 63937 }, + { 0x6FA8, 64005 }, + { 0x6FA9, 63929 }, + { 0x6FAA, 64009 }, + { 0x6FAB, 63993 }, + { 0x6FAC, 63997 }, + { 0x6FAD, 63965 }, + { 0x6FAE, 64017 }, + { 0x6FAF, 64013 }, + { 0x6FB0, 63989 }, + { 0x6FB1, 63917 }, + { 0x6FB2, 63925 }, + { 0x6FB3, 63973 }, + { 0x6FB4, 63961 }, + { 0x6FB5, 63901 }, + { 0x6FB6, 63957 }, + { 0x6FB7, 63913 }, + { 0x6FB8, 63905 }, + { 0x6FB9, 63969 }, + { 0x6FBA, 63941 }, + { 0x6FBB, 63945 }, + { 0x6FBC, 63953 }, + { 0x6FBD, 63949 }, + { 0x6FBE, 63909 }, + { 0x6FC2, 63817 }, + { 0x6FC3, 63837 }, + { 0x6FC4, 63865 }, + { 0x6FC5, 63893 }, + { 0x6FC6, 63841 }, + { 0x6FC7, 63821 }, + { 0x6FCA, 63897 }, + { 0x6FCB, 63869 }, + { 0x6FCC, 63829 }, + { 0x6FCD, 63853 }, + { 0x6FCE, 63885 }, + { 0x6FCF, 63849 }, + { 0x6FD2, 63877 }, + { 0x6FD3, 63833 }, + { 0x6FD4, 63889 }, + { 0x6FD5, 63857 }, + { 0x6FD6, 63861 }, + { 0x6FD7, 63881 }, + { 0x6FDA, 63845 }, + { 0x6FDB, 63873 }, + { 0x6FDC, 63825 }, + { 0x6FE0, 63397 }, + { 0x6FE1, 63718 }, + { 0x6FE2, 63388 }, + { 0x6FE3, 63747 }, + { 0x6FE4, 63738 }, + { 0x6FE5, 63394 }, + { 0x6FE6, 63391 }, + { 0x6FE8, 63803 }, + { 0x6FE9, 64270 }, + { 0x6FEA, 64021 }, + { 0x6FEB, 64273 }, + { 0x6FEC, 64267 }, + { 0x6FED, 63800 }, + { 0x6FEE, 63811 }, + { 0x6FF9, 69249 }, + { 0x6FFA, 69252 }, + { 0x6FFB, 69255 }, + { 0x6FFC, 35637 }, + { 0x6FFD, 69276 }, + { 0x7000, 35010 }, + { 0x7001, 35135 }, + { 0x7002, 35095 }, + { 0x7003, 35235 }, + { 0x7004, 35020 }, + { 0x7005, 34975 }, + { 0x7006, 35170 }, + { 0x7007, 35005 }, + { 0x7008, 35040 }, + { 0x7009, 35190 }, + { 0x700A, 35215 }, + { 0x700B, 35175 }, + { 0x700D, 35125 }, + { 0x700E, 35245 }, + { 0x700F, 35305 }, + { 0x7010, 35165 }, + { 0x7011, 35255 }, + { 0x7012, 35270 }, + { 0x7013, 35320 }, + { 0x7014, 35315 }, + { 0x7015, 35035 }, + { 0x7016, 35285 }, + { 0x7017, 35045 }, + { 0x7018, 35070 }, + { 0x7019, 35000 }, + { 0x701A, 35075 }, + { 0x701B, 35105 }, + { 0x701C, 35195 }, + { 0x701D, 35210 }, + { 0x701E, 34985 }, + { 0x701F, 35280 }, + { 0x7020, 35140 }, + { 0x7021, 35025 }, + { 0x7022, 35185 }, + { 0x7023, 35050 }, + { 0x7024, 35310 }, + { 0x7025, 35065 }, + { 0x7026, 35115 }, + { 0x7028, 35230 }, + { 0x7029, 35090 }, + { 0x702A, 35200 }, + { 0x702B, 34980 }, + { 0x702C, 35085 }, + { 0x702D, 35110 }, + { 0x702E, 35015 }, + { 0x702F, 35150 }, + { 0x7030, 35030 }, + { 0x7031, 35220 }, + { 0x7032, 35225 }, + { 0x7033, 34990 }, + { 0x7034, 35130 }, + { 0x7035, 34995 }, + { 0x7036, 35265 }, + { 0x7037, 35205 }, + { 0x7038, 35295 }, + { 0x7039, 35145 }, + { 0x703A, 35155 }, + { 0x703C, 35055 }, + { 0x703D, 35290 }, + { 0x703F, 35060 }, + { 0x7040, 35080 }, + { 0x7041, 35160 }, + { 0x7042, 35325 }, + { 0x7043, 35275 }, + { 0x7044, 35335 }, + { 0x7045, 35180 }, + { 0x7046, 35100 }, + { 0x7047, 35240 }, + { 0x7048, 35300 }, + { 0x7049, 35120 }, + { 0x704A, 35260 }, + { 0x704B, 35250 }, + { 0x704C, 35330 }, + { 0x704D, 35340 }, + { 0x7050, 34349 }, + { 0x7051, 34353 }, + { 0x7052, 34357 }, + { 0x7053, 34361 }, + { 0x7054, 34365 }, + { 0x7055, 34369 }, + { 0x7056, 34373 }, + { 0x7057, 34377 }, + { 0x7058, 34381 }, + { 0x7059, 34385 }, + { 0x705A, 34389 }, + { 0x705B, 34393 }, + { 0x705C, 34397 }, + { 0x705D, 34401 }, + { 0x7080, 34405 }, + { 0x7081, 34410 }, + { 0x7082, 34415 }, + { 0x7083, 34420 }, + { 0x7084, 34750 }, + { 0x7085, 34755 }, + { 0x7086, 34760 }, + { 0x7087, 34765 }, + { 0x7088, 34770 }, + { 0x7089, 34775 }, + { 0x708A, 34780 }, + { 0x708B, 34785 }, + { 0x708C, 34790 }, + { 0x708D, 34795 }, + { 0x708E, 34425 }, + { 0x708F, 34430 }, + { 0x7090, 34435 }, + { 0x7091, 34440 }, + { 0x7092, 34445 }, + { 0x7093, 34945 }, + { 0x7094, 34950 }, + { 0x7095, 34450 }, + { 0x7096, 34455 }, + { 0x7097, 34460 }, + { 0x7098, 34955 }, + { 0x7099, 34960 }, + { 0x709A, 34464 }, + { 0x709B, 34469 }, + { 0x709C, 34474 }, + { 0x709D, 34478 }, + { 0x709E, 34483 }, + { 0x709F, 34487 }, + { 0x70A0, 34491 }, + { 0x70A1, 34496 }, + { 0x70A2, 34500 }, + { 0x70A3, 34504 }, + { 0x70A4, 34965 }, + { 0x70A5, 34508 }, + { 0x70A6, 34512 }, + { 0x70A7, 34516 }, + { 0x70A8, 34521 }, + { 0x70A9, 34525 }, + { 0x70AA, 34529 }, + { 0x70AB, 34534 }, + { 0x70AC, 34539 }, + { 0x70AD, 34543 }, + { 0x70AE, 34547 }, + { 0x70AF, 34551 }, + { 0x70B0, 34555 }, + { 0x70B1, 34559 }, + { 0x70B2, 34563 }, + { 0x70B3, 34567 }, + { 0x70B4, 34571 }, + { 0x70B5, 34575 }, + { 0x70B6, 34580 }, + { 0x70B7, 34584 }, + { 0x70B8, 34589 }, + { 0x70B9, 34593 }, + { 0x70BA, 34597 }, + { 0x70BB, 34601 }, + { 0x70BC, 34605 }, + { 0x70BD, 34609 }, + { 0x70BE, 34613 }, + { 0x70BF, 34617 }, + { 0x70C0, 34621 }, + { 0x70C1, 34625 }, + { 0x70C2, 34629 }, + { 0x70C3, 34633 }, + { 0x70C4, 34638 }, + { 0x70C5, 34643 }, + { 0x70C6, 34648 }, + { 0x70C7, 34653 }, + { 0x70C8, 34658 }, + { 0x70C9, 34662 }, + { 0x70CA, 34667 }, + { 0x70CB, 34671 }, + { 0x70CC, 34675 }, + { 0x70CD, 34681 }, + { 0x70CE, 34686 }, + { 0x70CF, 34692 }, + { 0x70D0, 34697 }, + { 0x70D1, 34701 }, + { 0x70D2, 34970 }, + { 0x70D3, 34705 }, + { 0x70D4, 34709 }, + { 0x70D5, 34713 }, + { 0x70D6, 34717 }, + { 0x70D7, 34721 }, + { 0x70D8, 34725 }, + { 0x70D9, 34730 }, + { 0x70DA, 34734 }, + { 0x70DB, 34738 }, + { 0x70DC, 34742 }, + { 0x70DD, 34746 }, + { 0x70DE, 34800 }, + { 0x70DF, 34805 }, + { 0x70E0, 34810 }, + { 0x70E1, 34815 }, + { 0x70E2, 34820 }, + { 0x70E3, 34825 }, + { 0x70E4, 34830 }, + { 0x70E5, 34835 }, + { 0x70E6, 34840 }, + { 0x70E7, 34845 }, + { 0x70E8, 34850 }, + { 0x70E9, 34855 }, + { 0x70EA, 34860 }, + { 0x70EB, 34865 }, + { 0x70EC, 34870 }, + { 0x70ED, 34875 }, + { 0x70EE, 34880 }, + { 0x70EF, 34885 }, + { 0x70F0, 34890 }, + { 0x70F1, 34895 }, + { 0x70F2, 34900 }, + { 0x70F3, 34905 }, + { 0x70F4, 34910 }, + { 0x70F5, 34915 }, + { 0x70F6, 34920 }, + { 0x70F7, 34925 }, + { 0x70F8, 34930 }, + { 0x70F9, 34935 }, + { 0x70FA, 34940 }, + { 0x7100, 23485 }, + { 0x7101, 23481 }, + { 0x7102, 23489 }, + { 0x7107, 23497 }, + { 0x7108, 23526 }, + { 0x7109, 23613 }, + { 0x710A, 23548 }, + { 0x710B, 23537 }, + { 0x710C, 23508 }, + { 0x710D, 23595 }, + { 0x710E, 23570 }, + { 0x710F, 23559 }, + { 0x7110, 23519 }, + { 0x7111, 23645 }, + { 0x7112, 23638 }, + { 0x7113, 23588 }, + { 0x7114, 23581 }, + { 0x7115, 23606 }, + { 0x7116, 23652 }, + { 0x7117, 23624 }, + { 0x7118, 23631 }, + { 0x7119, 23500 }, + { 0x711A, 23529 }, + { 0x711B, 23616 }, + { 0x711C, 23551 }, + { 0x711D, 23540 }, + { 0x711E, 23511 }, + { 0x711F, 23598 }, + { 0x7120, 23573 }, + { 0x7121, 23562 }, + { 0x7122, 23504 }, + { 0x7123, 23533 }, + { 0x7124, 23620 }, + { 0x7125, 23555 }, + { 0x7126, 23544 }, + { 0x7127, 23515 }, + { 0x7128, 23602 }, + { 0x7129, 23577 }, + { 0x712A, 23566 }, + { 0x712B, 23522 }, + { 0x712C, 23648 }, + { 0x712D, 23641 }, + { 0x712E, 23591 }, + { 0x712F, 23584 }, + { 0x7130, 23609 }, + { 0x7131, 23655 }, + { 0x7132, 23627 }, + { 0x7133, 23634 }, + { 0x7137, 23659 }, + { 0x7138, 23663 }, + { 0x7139, 23675 }, + { 0x713A, 23667 }, + { 0x713B, 23671 }, + { 0x713C, 23476 }, + { 0x713D, 23492 }, + { 0x713E, 23683 }, + { 0x713F, 23679 }, + { 0x7140, 13133 }, + { 0x7141, 13111 }, + { 0x7142, 13116 }, + { 0x7143, 13171 }, + { 0x7144, 13213 }, + { 0x7145, 13175 }, + { 0x7146, 13202 }, + { 0x7147, 13227 }, + { 0x7148, 13197 }, + { 0x7149, 13160 }, + { 0x714A, 13222 }, + { 0x714B, 13127 }, + { 0x714C, 13186 }, + { 0x714D, 13144 }, + { 0x714E, 13207 }, + { 0x714F, 13192 }, + { 0x7150, 13155 }, + { 0x7151, 13217 }, + { 0x7152, 13121 }, + { 0x7153, 13180 }, + { 0x7154, 13138 }, + { 0x7155, 13165 }, + { 0x7156, 13232 }, + { 0x7157, 13150 }, + { 0x7158, 13248 }, + { 0x7159, 13263 }, + { 0x715A, 13331 }, + { 0x715B, 13317 }, + { 0x715C, 13281 }, + { 0x715D, 13253 }, + { 0x715E, 13321 }, + { 0x715F, 13353 }, + { 0x7160, 13343 }, + { 0x7161, 13347 }, + { 0x7162, 13335 }, + { 0x7163, 13313 }, + { 0x7164, 13277 }, + { 0x7165, 13304 }, + { 0x7166, 13362 }, + { 0x7167, 13366 }, + { 0x7168, 13339 }, + { 0x7169, 13295 }, + { 0x716A, 13267 }, + { 0x716B, 13299 }, + { 0x716C, 13326 }, + { 0x716D, 13357 }, + { 0x716E, 13285 }, + { 0x716F, 13308 }, + { 0x7170, 13238 }, + { 0x7171, 13272 }, + { 0x7172, 13290 }, + { 0x7173, 13243 }, + { 0x7174, 13258 }, + { 0x7175, 10649 }, + { 0x7176, 10653 }, + { 0x7177, 10674 }, + { 0x7178, 11894 }, + { 0x7179, 10694 }, + { 0x717A, 12082 }, + { 0x717B, 13022 }, + { 0x717C, 10689 }, + { 0x717D, 10670 }, + { 0x717E, 11890 }, + { 0x717F, 10685 }, + { 0x7180, 10681 }, + { 0x7181, 13056 }, + { 0x7182, 13027 }, + { 0x7183, 10717 }, + { 0x7184, 12079 }, + { 0x7185, 12085 }, + { 0x7186, 12021 }, + { 0x7187, 12018 }, + { 0x7188, 12024 }, + { 0x7189, 13067 }, + { 0x718A, 10697 }, + { 0x7190, 22109 }, + { 0x7191, 22013 }, + { 0x7192, 22121 }, + { 0x7193, 22112 }, + { 0x7194, 22016 }, + { 0x7195, 22115 }, + { 0x7196, 22118 }, + { 0x7197, 22130 }, + { 0x7198, 22133 }, + { 0x7199, 22127 }, + { 0x719A, 22010 }, + { 0x719B, 22124 }, + { 0x71D0, 55326 }, + { 0x71D1, 55265 }, + { 0x71D2, 55306 }, + { 0x71D3, 55278 }, + { 0x71D4, 55211 }, + { 0x71D5, 55245 }, + { 0x71D6, 55261 }, + { 0x71D7, 55294 }, + { 0x71D8, 55237 }, + { 0x71D9, 55202 }, + { 0x71DA, 55145 }, + { 0x71DB, 55270 }, + { 0x71DC, 55165 }, + { 0x71DD, 55298 }, + { 0x71DE, 55282 }, + { 0x71DF, 55161 }, + { 0x71E0, 55153 }, + { 0x71E1, 55311 }, + { 0x71E2, 55315 }, + { 0x71E3, 55253 }, + { 0x71E4, 55169 }, + { 0x71E5, 55228 }, + { 0x71E6, 55249 }, + { 0x71E7, 55274 }, + { 0x71E8, 55189 }, + { 0x71E9, 55181 }, + { 0x71EA, 55177 }, + { 0x71EB, 55206 }, + { 0x71EC, 55149 }, + { 0x71ED, 55157 }, + { 0x71EE, 55215 }, + { 0x71EF, 55173 }, + { 0x71F0, 55241 }, + { 0x71F1, 55141 }, + { 0x71F2, 55223 }, + { 0x71F3, 55193 }, + { 0x71F4, 55286 }, + { 0x71F5, 55290 }, + { 0x71F6, 55185 }, + { 0x71F7, 55136 }, + { 0x71F8, 55219 }, + { 0x71F9, 55257 }, + { 0x71FA, 55302 }, + { 0x71FB, 55232 }, + { 0x71FC, 55197 }, + { 0x71FD, 55320 }, + { 0x7280, 35345 }, + { 0x7281, 35354 }, + { 0x7282, 35348 }, + { 0x7283, 35411 }, + { 0x7284, 35357 }, + { 0x7285, 35351 }, + { 0x7286, 35363 }, + { 0x7287, 35399 }, + { 0x7288, 35405 }, + { 0x7289, 35426 }, + { 0x728A, 35366 }, + { 0x728B, 35369 }, + { 0x728C, 35384 }, + { 0x728D, 35372 }, + { 0x728E, 35375 }, + { 0x728F, 35378 }, + { 0x7290, 35420 }, + { 0x7291, 35423 }, + { 0x7292, 35396 }, + { 0x7293, 35381 }, + { 0x7294, 35417 }, + { 0x7295, 35387 }, + { 0x7296, 35390 }, + { 0x7297, 35393 }, + { 0x7298, 35429 }, + { 0x7299, 35408 }, + { 0x729A, 35414 }, + { 0x729B, 35360 }, + { 0x729C, 35402 }, + { 0x72A0, 30318 }, + { 0x72A1, 30405 }, + { 0x72A2, 30324 }, + { 0x72A3, 30339 }, + { 0x72A4, 30447 }, + { 0x72A5, 30357 }, + { 0x72A6, 30390 }, + { 0x72A7, 30372 }, + { 0x72A8, 30354 }, + { 0x72A9, 30321 }, + { 0x72AA, 30342 }, + { 0x72AB, 30348 }, + { 0x72AC, 30375 }, + { 0x72AD, 30363 }, + { 0x72AE, 30411 }, + { 0x72AF, 30438 }, + { 0x72B0, 30360 }, + { 0x72B1, 30450 }, + { 0x72B2, 30366 }, + { 0x72B3, 30402 }, + { 0x72B4, 30369 }, + { 0x72B5, 30345 }, + { 0x72B6, 30444 }, + { 0x72B7, 30351 }, + { 0x72B8, 30414 }, + { 0x72B9, 30333 }, + { 0x72BA, 30327 }, + { 0x72BB, 30462 }, + { 0x72BC, 30336 }, + { 0x72BD, 30387 }, + { 0x72BE, 30396 }, + { 0x72BF, 30423 }, + { 0x72C0, 30330 }, + { 0x72C1, 30381 }, + { 0x72C2, 30417 }, + { 0x72C3, 30441 }, + { 0x72C4, 30399 }, + { 0x72C5, 30384 }, + { 0x72C6, 30453 }, + { 0x72C7, 30420 }, + { 0x72C8, 30456 }, + { 0x72C9, 30408 }, + { 0x72CA, 30393 }, + { 0x72CB, 30429 }, + { 0x72CC, 30432 }, + { 0x72CD, 30435 }, + { 0x72CE, 30426 }, + { 0x72CF, 30378 }, + { 0x72D0, 30459 }, + { 0x7300, 6815 }, + { 0x7301, 6835 }, + { 0x7302, 6879 }, + { 0x7303, 6839 }, + { 0x7304, 6819 }, + { 0x7305, 6899 }, + { 0x7306, 6903 }, + { 0x7307, 6867 }, + { 0x7308, 6935 }, + { 0x7309, 6823 }, + { 0x730A, 6875 }, + { 0x730B, 6847 }, + { 0x730C, 6851 }, + { 0x730D, 6855 }, + { 0x730E, 6919 }, + { 0x730F, 6827 }, + { 0x7310, 6887 }, + { 0x7311, 6931 }, + { 0x7312, 6883 }, + { 0x7313, 6859 }, + { 0x7314, 6863 }, + { 0x7315, 6891 }, + { 0x7316, 6831 }, + { 0x7317, 6911 }, + { 0x7318, 6927 }, + { 0x7319, 6923 }, + { 0x731A, 6843 }, + { 0x731B, 6915 }, + { 0x731C, 6907 }, + { 0x731D, 6871 }, + { 0x731E, 6895 }, + { 0x7320, 6939 }, + { 0x7321, 6947 }, + { 0x7322, 6943 }, + { 0x7323, 6951 }, + { 0x7330, 31802 }, + { 0x7331, 31869 }, + { 0x7332, 31808 }, + { 0x7333, 31805 }, + { 0x7334, 31857 }, + { 0x7335, 31875 }, + { 0x7336, 31814 }, + { 0x7337, 31811 }, + { 0x7338, 31866 }, + { 0x7339, 31796 }, + { 0x733A, 31833 }, + { 0x733B, 31836 }, + { 0x733C, 31839 }, + { 0x733D, 31860 }, + { 0x733E, 31799 }, + { 0x733F, 31821 }, + { 0x7340, 31872 }, + { 0x7341, 31863 }, + { 0x7342, 31845 }, + { 0x7343, 31848 }, + { 0x7344, 31851 }, + { 0x7345, 31854 }, + { 0x7346, 31824 }, + { 0x7347, 31830 }, + { 0x7348, 31827 }, + { 0x7349, 31842 }, + { 0x734A, 31817 }, + { 0x7380, 55959 }, + { 0x7381, 55962 }, + { 0x7382, 55986 }, + { 0x7383, 55941 }, + { 0x7384, 55983 }, + { 0x7385, 55920 }, + { 0x7386, 55929 }, + { 0x7387, 55980 }, + { 0x7388, 55968 }, + { 0x7389, 55953 }, + { 0x738A, 55956 }, + { 0x738B, 55938 }, + { 0x738C, 55977 }, + { 0x738D, 55992 }, + { 0x738E, 55944 }, + { 0x738F, 55965 }, + { 0x7390, 55947 }, + { 0x7391, 55932 }, + { 0x7392, 55998 }, + { 0x7393, 55935 }, + { 0x7394, 55923 }, + { 0x7395, 55974 }, + { 0x7396, 55971 }, + { 0x7397, 55995 }, + { 0x7398, 56001 }, + { 0x7399, 55989 }, + { 0x739A, 55926 }, + { 0x739B, 55914 }, + { 0x739C, 55917 }, + { 0x739D, 55950 }, + { 0x739F, 55911 }, + { 0x73A0, 6955 }, + { 0x73A1, 6959 }, + { 0x73A2, 6963 }, + { 0x73A3, 7011 }, + { 0x73A4, 7015 }, + { 0x73A5, 6991 }, + { 0x73A6, 6995 }, + { 0x73A7, 7075 }, + { 0x73A8, 6971 }, + { 0x73A9, 7003 }, + { 0x73AA, 7007 }, + { 0x73AB, 7059 }, + { 0x73AC, 7063 }, + { 0x73AD, 6975 }, + { 0x73AE, 6979 }, + { 0x73AF, 6983 }, + { 0x73B0, 7095 }, + { 0x73B1, 7043 }, + { 0x73B2, 6967 }, + { 0x73B3, 6987 }, + { 0x73B4, 7035 }, + { 0x73B5, 7039 }, + { 0x73B6, 7023 }, + { 0x73B7, 7027 }, + { 0x73B8, 7031 }, + { 0x73B9, 7079 }, + { 0x73BA, 7067 }, + { 0x73BB, 7071 }, + { 0x73BC, 7047 }, + { 0x73BD, 7051 }, + { 0x73BE, 7019 }, + { 0x73BF, 7055 }, + { 0x73C0, 7083 }, + { 0x73C1, 7087 }, + { 0x73C2, 7091 }, + { 0x73C3, 6999 }, + { 0x73C8, 7111 }, + { 0x73C9, 7119 }, + { 0x73CA, 7123 }, + { 0x73CB, 7127 }, + { 0x73CC, 7107 }, + { 0x73CD, 7115 }, + { 0x73CE, 7099 }, + { 0x73CF, 7103 }, + { 0x73D0, 7131 }, + { 0x73D1, 7135 }, + { 0x73D2, 7143 }, + { 0x73D3, 7139 }, + { 0x73D4, 7147 }, + { 0x73D5, 7151 }, + { 0x7400, 40249 }, + { 0x7401, 40244 }, + { 0x7402, 40239 }, + { 0x7403, 40259 }, + { 0x7404, 40254 }, + { 0x7405, 40264 }, + { 0x7406, 40287 }, + { 0x7407, 40282 }, + { 0x7408, 40277 }, + { 0x7409, 40297 }, + { 0x740A, 40292 }, + { 0x740B, 40302 }, + { 0x740C, 40139 }, + { 0x740D, 40175 }, + { 0x740E, 40179 }, + { 0x740F, 40227 }, + { 0x7410, 40135 }, + { 0x7411, 40215 }, + { 0x7412, 40183 }, + { 0x7413, 40219 }, + { 0x7414, 40187 }, + { 0x7415, 40235 }, + { 0x7416, 40207 }, + { 0x7417, 40211 }, + { 0x7418, 40203 }, + { 0x7419, 40143 }, + { 0x741A, 40223 }, + { 0x741B, 40199 }, + { 0x741C, 40269 }, + { 0x741D, 40163 }, + { 0x741E, 40231 }, + { 0x741F, 40195 }, + { 0x7420, 40273 }, + { 0x7421, 40159 }, + { 0x7422, 40147 }, + { 0x7423, 40151 }, + { 0x7424, 40155 }, + { 0x7425, 40191 }, + { 0x7426, 40171 }, + { 0x7427, 40167 }, + { 0x7428, 40077 }, + { 0x7429, 40072 }, + { 0x742A, 40067 }, + { 0x742B, 40087 }, + { 0x742C, 40082 }, + { 0x742D, 40092 }, + { 0x742E, 40115 }, + { 0x742F, 40110 }, + { 0x7430, 40105 }, + { 0x7431, 40125 }, + { 0x7432, 40120 }, + { 0x7433, 40130 }, + { 0x7434, 39967 }, + { 0x7435, 40003 }, + { 0x7436, 40007 }, + { 0x7437, 40055 }, + { 0x7438, 39963 }, + { 0x7439, 40043 }, + { 0x743A, 40011 }, + { 0x743B, 40047 }, + { 0x743C, 40015 }, + { 0x743D, 40063 }, + { 0x743E, 40035 }, + { 0x743F, 40039 }, + { 0x7440, 40031 }, + { 0x7441, 39971 }, + { 0x7442, 40051 }, + { 0x7443, 40027 }, + { 0x7444, 40097 }, + { 0x7445, 39991 }, + { 0x7446, 40059 }, + { 0x7447, 40023 }, + { 0x7448, 40101 }, + { 0x7449, 39987 }, + { 0x744A, 39975 }, + { 0x744B, 39979 }, + { 0x744C, 39983 }, + { 0x744D, 40019 }, + { 0x744E, 39999 }, + { 0x744F, 39995 }, + { 0x7450, 43139 }, + { 0x7451, 43103 }, + { 0x7452, 43127 }, + { 0x7453, 43079 }, + { 0x7454, 43163 }, + { 0x7455, 43040 }, + { 0x7456, 43145 }, + { 0x7457, 43166 }, + { 0x7458, 43112 }, + { 0x7459, 43124 }, + { 0x745A, 43064 }, + { 0x745B, 43121 }, + { 0x745C, 43082 }, + { 0x745D, 43106 }, + { 0x745E, 43148 }, + { 0x745F, 43118 }, + { 0x7460, 43169 }, + { 0x7461, 43160 }, + { 0x7462, 43109 }, + { 0x7463, 43157 }, + { 0x7464, 43130 }, + { 0x7465, 43133 }, + { 0x7466, 43031 }, + { 0x7467, 43073 }, + { 0x7468, 43058 }, + { 0x7469, 43046 }, + { 0x746A, 43034 }, + { 0x746B, 43151 }, + { 0x746C, 43100 }, + { 0x746D, 43028 }, + { 0x746E, 43142 }, + { 0x746F, 43091 }, + { 0x7470, 43070 }, + { 0x7471, 43049 }, + { 0x7472, 43088 }, + { 0x7473, 43043 }, + { 0x7474, 43094 }, + { 0x7475, 43136 }, + { 0x7476, 43097 }, + { 0x7477, 43061 }, + { 0x7478, 43055 }, + { 0x7479, 43037 }, + { 0x747A, 43052 }, + { 0x747B, 43076 }, + { 0x747C, 43154 }, + { 0x747D, 43067 }, + { 0x747E, 43085 }, + { 0x747F, 43115 }, + { 0x7480, 42944 }, + { 0x7481, 42899 }, + { 0x7482, 42926 }, + { 0x7483, 42914 }, + { 0x7484, 42929 }, + { 0x7485, 42938 }, + { 0x7486, 42950 }, + { 0x7487, 42920 }, + { 0x7488, 42923 }, + { 0x7489, 42968 }, + { 0x748A, 42935 }, + { 0x748B, 42947 }, + { 0x748C, 42908 }, + { 0x748D, 42905 }, + { 0x748E, 42965 }, + { 0x748F, 42953 }, + { 0x7490, 42956 }, + { 0x7491, 42959 }, + { 0x7492, 42962 }, + { 0x7493, 42941 }, + { 0x7494, 42911 }, + { 0x7495, 42932 }, + { 0x7496, 42881 }, + { 0x7497, 42884 }, + { 0x7498, 42887 }, + { 0x7499, 42890 }, + { 0x749A, 42893 }, + { 0x749B, 42896 }, + { 0x749C, 42902 }, + { 0x749D, 42917 }, + { 0x74A0, 42869 }, + { 0x74A1, 42851 }, + { 0x74A2, 42857 }, + { 0x74A3, 42878 }, + { 0x74A4, 42863 }, + { 0x74A5, 42860 }, + { 0x74A6, 42854 }, + { 0x74A7, 42875 }, + { 0x74A8, 42872 }, + { 0x74A9, 42866 }, + { 0x7800, 39794 }, + { 0x7801, 39797 }, + { 0x7802, 39800 }, + { 0x7803, 39803 }, + { 0x7804, 39806 }, + { 0x7805, 39809 }, + { 0x7808, 39812 }, + { 0x780A, 39815 }, + { 0x780B, 39818 }, + { 0x780C, 39821 }, + { 0x780D, 39824 }, + { 0x780E, 39827 }, + { 0x780F, 39830 }, + { 0x7810, 39833 }, + { 0x7811, 39836 }, + { 0x7812, 39839 }, + { 0x7813, 39842 }, + { 0x7814, 39845 }, + { 0x7815, 39848 }, + { 0x7816, 39851 }, + { 0x7817, 39854 }, + { 0x7818, 39857 }, + { 0x7819, 39860 }, + { 0x781A, 39863 }, + { 0x781B, 39866 }, + { 0x781C, 39869 }, + { 0x781D, 39872 }, + { 0x781E, 39875 }, + { 0x781F, 39878 }, + { 0x7820, 39881 }, + { 0x7821, 39884 }, + { 0x7822, 39887 }, + { 0x7823, 39890 }, + { 0x7824, 39893 }, + { 0x7825, 39896 }, + { 0x7826, 39899 }, + { 0x7827, 39902 }, + { 0x7828, 39905 }, + { 0x7829, 39908 }, + { 0x782A, 39911 }, + { 0x782B, 39914 }, + { 0x782C, 39917 }, + { 0x782D, 39920 }, + { 0x782E, 39923 }, + { 0x782F, 39926 }, + { 0x7830, 39929 }, + { 0x7831, 39932 }, + { 0x7832, 39935 }, + { 0x7833, 39938 }, + { 0x7834, 39941 }, + { 0x7835, 39944 }, + { 0x7837, 39947 }, + { 0x7838, 39950 }, + { 0x783C, 39953 }, + { 0x783F, 39956 }, + { 0x7900, 67899 }, + { 0x7901, 67902 }, + { 0x7902, 67938 }, + { 0x7903, 67935 }, + { 0x7904, 67890 }, + { 0x7905, 67926 }, + { 0x7906, 67932 }, + { 0x7907, 67905 }, + { 0x7908, 67923 }, + { 0x7909, 67929 }, + { 0x790A, 67908 }, + { 0x790B, 67941 }, + { 0x790C, 67911 }, + { 0x790D, 67914 }, + { 0x790E, 67950 }, + { 0x790F, 67896 }, + { 0x7910, 67893 }, + { 0x7911, 67947 }, + { 0x7912, 67917 }, + { 0x7913, 67944 }, + { 0x7914, 67953 }, + { 0x7915, 67920 }, + { 0x7916, 67956 }, + { 0x7917, 67963 }, + { 0x7918, 67966 }, + { 0x7919, 67959 }, + { 0x791F, 67887 }, + { 0x7920, 35432 }, + { 0x7921, 35435 }, + { 0x7922, 35450 }, + { 0x7923, 35441 }, + { 0x7924, 35444 }, + { 0x7925, 35486 }, + { 0x7926, 35453 }, + { 0x7927, 35489 }, + { 0x7928, 35456 }, + { 0x7929, 35459 }, + { 0x792A, 35462 }, + { 0x792B, 35465 }, + { 0x792C, 35468 }, + { 0x792D, 35474 }, + { 0x792E, 35504 }, + { 0x792F, 35480 }, + { 0x7930, 35483 }, + { 0x7931, 35447 }, + { 0x7932, 35471 }, + { 0x7933, 35477 }, + { 0x7934, 35507 }, + { 0x7935, 35492 }, + { 0x7936, 35495 }, + { 0x7937, 35498 }, + { 0x7938, 35501 }, + { 0x7939, 35438 }, + { 0x793F, 35510 }, + { 0x7A00, 67726 }, + { 0x7A01, 67705 }, + { 0x7A02, 67713 }, + { 0x7A03, 67717 }, + { 0x7A05, 67701 }, + { 0x7A06, 67709 }, + { 0x7A0C, 67722 }, + { 0x7A0D, 67678 }, + { 0x7A0E, 67686 }, + { 0x7A0F, 67683 }, + { 0x7A10, 67747 }, + { 0x7A11, 67795 }, + { 0x7A12, 67738 }, + { 0x7A13, 67792 }, + { 0x7A15, 67732 }, + { 0x7A16, 67783 }, + { 0x7A17, 67744 }, + { 0x7A19, 67804 }, + { 0x7A1A, 67819 }, + { 0x7A1B, 67825 }, + { 0x7A1C, 67786 }, + { 0x7A1D, 67822 }, + { 0x7A1E, 67801 }, + { 0x7A1F, 67768 }, + { 0x7A20, 67816 }, + { 0x7A21, 67735 }, + { 0x7A22, 67789 }, + { 0x7A23, 67756 }, + { 0x7A24, 67759 }, + { 0x7A25, 67807 }, + { 0x7A26, 67729 }, + { 0x7A27, 67780 }, + { 0x7A28, 67753 }, + { 0x7A29, 67774 }, + { 0x7A2A, 67762 }, + { 0x7A2B, 67750 }, + { 0x7A2C, 67771 }, + { 0x7A2D, 67810 }, + { 0x7A2E, 67813 }, + { 0x7A2F, 67765 }, + { 0x7A30, 67777 }, + { 0x7A31, 67741 }, + { 0x7A32, 67798 }, + { 0x7A33, 67828 }, + { 0x7A38, 67667 }, + { 0x7A39, 67675 }, + { 0x7A3A, 67671 }, + { 0x7A3F, 67845 }, + { 0x7A40, 67689 }, + { 0x7A41, 67692 }, + { 0x7A42, 67698 }, + { 0x7A43, 67695 }, + { 0x7A44, 67839 }, + { 0x7A45, 67842 }, + { 0x7A46, 67831 }, + { 0x7A47, 67835 }, + { 0x7A50, 67847 }, + { 0x7A51, 67859 }, + { 0x7A52, 67863 }, + { 0x7A53, 67870 }, + { 0x7A54, 67874 }, + { 0x7A55, 67856 }, + { 0x7A56, 67850 }, + { 0x7A57, 67866 }, + { 0x7A58, 67853 }, + { 0x8000, 58351 }, + { 0x8001, 58354 }, + { 0x8002, 58364 }, + { 0x8003, 58379 }, + { 0x8004, 58359 }, + { 0x8005, 58369 }, + { 0x8006, 58390 }, + { 0x8007, 58385 }, + { 0x8008, 58374 }, + { 0x8009, 58460 }, + { 0x800A, 58463 }, + { 0x800B, 58495 }, + { 0x800C, 58500 }, + { 0x800D, 58484 }, + { 0x800E, 58506 }, + { 0x800F, 58479 }, + { 0x8010, 58489 }, + { 0x8011, 58512 }, + { 0x8012, 58517 }, + { 0x8013, 58522 }, + { 0x8014, 58470 }, + { 0x8015, 58466 }, + { 0x8016, 59529 }, + { 0x8017, 59555 }, + { 0x8018, 59539 }, + { 0x8019, 59532 }, + { 0x801A, 59545 }, + { 0x801B, 59550 }, + { 0x801C, 58527 }, + { 0x801D, 58530 }, + { 0x801E, 58533 }, + { 0x801F, 58538 }, + { 0x8020, 58545 }, + { 0x8021, 58548 }, + { 0x8022, 58573 }, + { 0x8023, 58578 }, + { 0x8024, 58553 }, + { 0x8025, 58583 }, + { 0x8026, 58558 }, + { 0x8027, 58563 }, + { 0x8028, 58568 }, + { 0x8029, 61180 }, + { 0x802A, 61793 }, + { 0x802B, 61183 }, + { 0x802C, 61186 }, + { 0x802D, 58588 }, + { 0x802E, 58591 }, + { 0x802F, 58611 }, + { 0x8030, 58602 }, + { 0x8031, 58596 }, + { 0x8032, 61796 }, + { 0x8033, 61191 }, + { 0x8034, 61194 }, + { 0x8035, 61197 }, + { 0x8036, 61799 }, + { 0x8037, 61802 }, + { 0x8038, 59560 }, + { 0x8039, 59600 }, + { 0x803A, 59563 }, + { 0x803B, 59588 }, + { 0x803C, 59568 }, + { 0x803D, 59575 }, + { 0x803E, 61202 }, + { 0x803F, 62374 }, + { 0x8040, 58616 }, + { 0x8041, 59605 }, + { 0x8042, 61205 }, + { 0x8043, 62377 }, + { 0x8044, 59608 }, + { 0x8045, 59611 }, + { 0x8046, 61805 }, + { 0x8047, 59616 }, + { 0x8048, 61808 }, + { 0x8049, 58619 }, + { 0x804A, 58622 }, + { 0x804B, 58627 }, + { 0x804C, 58632 }, + { 0x804D, 58638 }, + { 0x804E, 58641 }, + { 0x804F, 58647 }, + { 0x8050, 58653 }, + { 0x8051, 61811 }, + { 0x8052, 61814 }, + { 0x8053, 59619 }, + { 0x8054, 61208 }, + { 0x8055, 58658 }, + { 0x8056, 59622 }, + { 0x8057, 59625 }, + { 0x8058, 59751 }, + { 0x8059, 59769 }, + { 0x805A, 59633 }, + { 0x805B, 59639 }, + { 0x805C, 59645 }, + { 0x805D, 59653 }, + { 0x805E, 59757 }, + { 0x805F, 59719 }, + { 0x8060, 59659 }, + { 0x8061, 59665 }, + { 0x8062, 59671 }, + { 0x8063, 59725 }, + { 0x8064, 59679 }, + { 0x8065, 59685 }, + { 0x8066, 59691 }, + { 0x8067, 59731 }, + { 0x8068, 59699 }, + { 0x8069, 59737 }, + { 0x806A, 59705 }, + { 0x806B, 59763 }, + { 0x806C, 59711 }, + { 0x806D, 59745 }, + { 0x806E, 59775 }, + { 0x806F, 59778 }, + { 0x8070, 61819 }, + { 0x8071, 61822 }, + { 0x8072, 58661 }, + { 0x8073, 59781 }, + { 0x8074, 59784 }, + { 0x8075, 59787 }, + { 0x8076, 61211 }, + { 0x8077, 59792 }, + { 0x8078, 59795 }, + { 0x8079, 61214 }, + { 0x807A, 58664 }, + { 0x807B, 58671 }, + { 0x807C, 58667 }, + { 0x807D, 58676 }, + { 0x807E, 59802 }, + { 0x807F, 59805 }, + { 0x8080, 61217 }, + { 0x8081, 59810 }, + { 0x8082, 61825 }, + { 0x8083, 59813 }, + { 0x8084, 59816 }, + { 0x8085, 61220 }, + { 0x8086, 61223 }, + { 0x8087, 61227 }, + { 0x8088, 61232 }, + { 0x8089, 61235 }, + { 0x808A, 58396 }, + { 0x808B, 58407 }, + { 0x808C, 58399 }, + { 0x808D, 58680 }, + { 0x808E, 58683 }, + { 0x808F, 58702 }, + { 0x8090, 58697 }, + { 0x8091, 58707 }, + { 0x8092, 58712 }, + { 0x8093, 58692 }, + { 0x8094, 61238 }, + { 0x8095, 61241 }, + { 0x8096, 58717 }, + { 0x8097, 58720 }, + { 0x8098, 58728 }, + { 0x8099, 58733 }, + { 0x809A, 58723 }, + { 0x809B, 58743 }, + { 0x809C, 58748 }, + { 0x809D, 58739 }, + { 0x809E, 61244 }, + { 0x809F, 61828 }, + { 0x80A0, 61247 }, + { 0x80A1, 61250 }, + { 0x80A2, 61253 }, + { 0x80A3, 61258 }, + { 0x80A4, 61265 }, + { 0x80A5, 61274 }, + { 0x80A6, 61315 }, + { 0x80A7, 61338 }, + { 0x80A8, 61344 }, + { 0x80A9, 61279 }, + { 0x80AA, 61284 }, + { 0x80AB, 61320 }, + { 0x80AC, 61351 }, + { 0x80AD, 61356 }, + { 0x80AE, 61326 }, + { 0x80AF, 61290 }, + { 0x80B0, 61331 }, + { 0x80B1, 61295 }, + { 0x80B2, 61300 }, + { 0x80B3, 61305 }, + { 0x80B4, 61310 }, + { 0x80B5, 58753 }, + { 0x80B6, 58756 }, + { 0x80B7, 59819 }, + { 0x80B8, 59827 }, + { 0x80B9, 59836 }, + { 0x80BA, 59843 }, + { 0x80BB, 59950 }, + { 0x80BC, 59855 }, + { 0x80BD, 59958 }, + { 0x80BE, 60106 }, + { 0x80BF, 59963 }, + { 0x80C0, 59968 }, + { 0x80C1, 59975 }, + { 0x80C2, 59980 }, + { 0x80C3, 59860 }, + { 0x80C4, 59865 }, + { 0x80C5, 59987 }, + { 0x80C6, 59994 }, + { 0x80C7, 59870 }, + { 0x80C8, 59875 }, + { 0x80C9, 59882 }, + { 0x80CA, 59887 }, + { 0x80CB, 60113 }, + { 0x80CC, 59999 }, + { 0x80CD, 59895 }, + { 0x80CE, 60004 }, + { 0x80CF, 60009 }, + { 0x80D0, 60119 }, + { 0x80D1, 59900 }, + { 0x80D2, 60016 }, + { 0x80D3, 60021 }, + { 0x80D4, 59909 }, + { 0x80D5, 60126 }, + { 0x80D6, 60028 }, + { 0x80D7, 60034 }, + { 0x80D8, 60043 }, + { 0x80D9, 60141 }, + { 0x80DA, 60048 }, + { 0x80DB, 60053 }, + { 0x80DC, 60060 }, + { 0x80DD, 59916 }, + { 0x80DE, 59921 }, + { 0x80DF, 59928 }, + { 0x80E0, 60067 }, + { 0x80E1, 60072 }, + { 0x80E2, 59933 }, + { 0x80E3, 60079 }, + { 0x80E4, 60084 }, + { 0x80E5, 60089 }, + { 0x80E6, 60094 }, + { 0x80E7, 60131 }, + { 0x80E8, 60101 }, + { 0x80E9, 60136 }, + { 0x80EA, 59850 }, + { 0x80EB, 59938 }, + { 0x80EC, 59943 }, + { 0x80ED, 59822 }, + { 0x80EE, 61362 }, + { 0x80EF, 61365 }, + { 0x80F0, 60146 }, + { 0x80F1, 60149 }, + { 0x80F2, 60157 }, + { 0x80F3, 60160 }, + { 0x80F4, 61831 }, + { 0x80F5, 60169 }, + { 0x80F6, 60172 }, + { 0x80F7, 61370 }, + { 0x80F8, 61378 }, + { 0x80F9, 61373 }, + { 0x80FA, 61382 }, + { 0x80FB, 60175 }, + { 0x80FC, 61387 }, + { 0x80FD, 62380 }, + { 0x80FE, 62539 }, + { 0x80FF, 62542 }, + { 0x8100, 58760 }, + { 0x8101, 58763 }, + { 0x8102, 58768 }, + { 0x8103, 58773 }, + { 0x8104, 60178 }, + { 0x8105, 60181 }, + { 0x8106, 60186 }, + { 0x8107, 61834 }, + { 0x8108, 61390 }, + { 0x8109, 61393 }, + { 0x810A, 61397 }, + { 0x810B, 61400 }, + { 0x810C, 61424 }, + { 0x810D, 61419 }, + { 0x810E, 61407 }, + { 0x810F, 61414 }, + { 0x8110, 61837 }, + { 0x8111, 61430 }, + { 0x8112, 61447 }, + { 0x8113, 61437 }, + { 0x8114, 61442 }, + { 0x8115, 61433 }, + { 0x8116, 58778 }, + { 0x8117, 58781 }, + { 0x8118, 60191 }, + { 0x8119, 60198 }, + { 0x811A, 60203 }, + { 0x811B, 60211 }, + { 0x811C, 60216 }, + { 0x811D, 60194 }, + { 0x811E, 60223 }, + { 0x811F, 60232 }, + { 0x8120, 60239 }, + { 0x8121, 60226 }, + { 0x8122, 60244 }, + { 0x8123, 60247 }, + { 0x8124, 60250 }, + { 0x8125, 60255 }, + { 0x8126, 61452 }, + { 0x8127, 61840 }, + { 0x8128, 62383 }, + { 0x8129, 58786 }, + { 0x812A, 58793 }, + { 0x812B, 58789 }, + { 0x812C, 60258 }, + { 0x812D, 58797 }, + { 0x812E, 58805 }, + { 0x812F, 58835 }, + { 0x8130, 58810 }, + { 0x8131, 58840 }, + { 0x8132, 58815 }, + { 0x8133, 58820 }, + { 0x8134, 58825 }, + { 0x8135, 58830 }, + { 0x8136, 58800 }, + { 0x8137, 58845 }, + { 0x8138, 61455 }, + { 0x8139, 61458 }, + { 0x813A, 61468 }, + { 0x813B, 61478 }, + { 0x813C, 61473 }, + { 0x813D, 61463 }, + { 0x813E, 61483 }, + { 0x813F, 58412 }, + { 0x8140, 58415 }, + { 0x8141, 58848 }, + { 0x8142, 61486 }, + { 0x8143, 61489 }, + { 0x8144, 61495 }, + { 0x8145, 58851 }, + { 0x8146, 60261 }, + { 0x8147, 60268 }, + { 0x8148, 60264 }, + { 0x8149, 60276 }, + { 0x814A, 60272 }, + { 0x814B, 58854 }, + { 0x814C, 58857 }, + { 0x814D, 60287 }, + { 0x814E, 58863 }, + { 0x814F, 58866 }, + { 0x8150, 58875 }, + { 0x8151, 58880 }, + { 0x8152, 58871 }, + { 0x8153, 61501 }, + { 0x8154, 58885 }, + { 0x8155, 58888 }, + { 0x8156, 60290 }, + { 0x8157, 58891 }, + { 0x8158, 58894 }, + { 0x8159, 58904 }, + { 0x815A, 58909 }, + { 0x815B, 59113 }, + { 0x815C, 59029 }, + { 0x815D, 59165 }, + { 0x815E, 59034 }, + { 0x815F, 58916 }, + { 0x8160, 59170 }, + { 0x8161, 59118 }, + { 0x8162, 58921 }, + { 0x8163, 59039 }, + { 0x8164, 59123 }, + { 0x8165, 59044 }, + { 0x8166, 59049 }, + { 0x8167, 58926 }, + { 0x8168, 59129 }, + { 0x8169, 59134 }, + { 0x816A, 59141 }, + { 0x816B, 58931 }, + { 0x816C, 59148 }, + { 0x816D, 59058 }, + { 0x816E, 58936 }, + { 0x816F, 59063 }, + { 0x8170, 58941 }, + { 0x8171, 59068 }, + { 0x8172, 58946 }, + { 0x8173, 58951 }, + { 0x8174, 58956 }, + { 0x8175, 58961 }, + { 0x8176, 58968 }, + { 0x8177, 58975 }, + { 0x8178, 58982 }, + { 0x8179, 58987 }, + { 0x817A, 58994 }, + { 0x817B, 59073 }, + { 0x817C, 58999 }, + { 0x817D, 59004 }, + { 0x817E, 59009 }, + { 0x817F, 59078 }, + { 0x8180, 59083 }, + { 0x8181, 59088 }, + { 0x8182, 59153 }, + { 0x8183, 59093 }, + { 0x8184, 59098 }, + { 0x8185, 59175 }, + { 0x8186, 59103 }, + { 0x8187, 58899 }, + { 0x8188, 59014 }, + { 0x8189, 59019 }, + { 0x818A, 59158 }, + { 0x818B, 59108 }, + { 0x818C, 59024 }, + { 0x818D, 60293 }, + { 0x818E, 60296 }, + { 0x818F, 60301 }, + { 0x8190, 61504 }, + { 0x8191, 61507 }, + { 0x8192, 61510 }, + { 0x8193, 61513 }, + { 0x8194, 61516 }, + { 0x8195, 60304 }, + { 0x8196, 60307 }, + { 0x8197, 60313 }, + { 0x8198, 60316 }, + { 0x8199, 60321 }, + { 0x819A, 61521 }, + { 0x819B, 61524 }, + { 0x819C, 62386 }, + { 0x819D, 62401 }, + { 0x819E, 62389 }, + { 0x819F, 61843 }, + { 0x81A0, 59180 }, + { 0x81A1, 59193 }, + { 0x81A2, 59183 }, + { 0x81A3, 59188 }, + { 0x81A4, 60326 }, + { 0x81A5, 60329 }, + { 0x81A6, 61846 }, + { 0x81A7, 61527 }, + { 0x81A8, 62411 }, + { 0x81A9, 62414 }, + { 0x81AA, 59198 }, + { 0x81AB, 59201 }, + { 0x81AC, 60332 }, + { 0x81AD, 60335 }, + { 0x81AE, 60338 }, + { 0x81AF, 60343 }, + { 0x81B0, 60346 }, + { 0x81B1, 60349 }, + { 0x81B2, 60353 }, + { 0x81B3, 60356 }, + { 0x81B4, 60359 }, + { 0x81B5, 62419 }, + { 0x81B6, 62422 }, + { 0x81B7, 59213 }, + { 0x81B8, 61849 }, + { 0x81B9, 61852 }, + { 0x81BA, 61857 }, + { 0x81BB, 61866 }, + { 0x81BC, 61873 }, + { 0x81BD, 61901 }, + { 0x81BE, 61906 }, + { 0x81BF, 62007 }, + { 0x81C0, 62014 }, + { 0x81C1, 61911 }, + { 0x81C2, 62019 }, + { 0x81C3, 61916 }, + { 0x81C4, 61921 }, + { 0x81C5, 62024 }, + { 0x81C6, 62029 }, + { 0x81C7, 62034 }, + { 0x81C8, 61926 }, + { 0x81C9, 62041 }, + { 0x81CA, 61931 }, + { 0x81CB, 62046 }, + { 0x81CC, 61938 }, + { 0x81CD, 61943 }, + { 0x81CE, 61950 }, + { 0x81CF, 61957 }, + { 0x81D0, 62052 }, + { 0x81D1, 62057 }, + { 0x81D2, 62062 }, + { 0x81D3, 62067 }, + { 0x81D4, 62130 }, + { 0x81D5, 62103 }, + { 0x81D6, 61962 }, + { 0x81D7, 62076 }, + { 0x81D8, 61967 }, + { 0x81D9, 61972 }, + { 0x81DA, 62108 }, + { 0x81DB, 61979 }, + { 0x81DC, 62081 }, + { 0x81DD, 62135 }, + { 0x81DE, 62144 }, + { 0x81DF, 62113 }, + { 0x81E0, 62118 }, + { 0x81E1, 62088 }, + { 0x81E2, 62093 }, + { 0x81E3, 62125 }, + { 0x81E4, 61984 }, + { 0x81E5, 61880 }, + { 0x81E6, 61885 }, + { 0x81E7, 61892 }, + { 0x81E8, 61995 }, + { 0x81E9, 62002 }, + { 0x81EA, 62098 }, + { 0x81EB, 62152 }, + { 0x81EC, 62156 }, + { 0x81ED, 62171 }, + { 0x81EE, 62176 }, + { 0x81EF, 62159 }, + { 0x81F0, 62163 }, + { 0x81F1, 62425 }, + { 0x81F2, 60364 }, + { 0x81F3, 60367 }, + { 0x81F4, 60372 }, + { 0x81F5, 60375 }, + { 0x81F6, 60380 }, + { 0x81F7, 59216 }, + { 0x81F8, 60387 }, + { 0x81F9, 62428 }, + { 0x81FA, 61530 }, + { 0x81FB, 59219 }, + { 0x81FC, 59222 }, + { 0x81FD, 60390 }, + { 0x81FE, 60397 }, + { 0x81FF, 60450 }, + { 0x8200, 60455 }, + { 0x8201, 60460 }, + { 0x8202, 60466 }, + { 0x8203, 60402 }, + { 0x8204, 60409 }, + { 0x8205, 60472 }, + { 0x8206, 60477 }, + { 0x8207, 60482 }, + { 0x8208, 60414 }, + { 0x8209, 60419 }, + { 0x820A, 60501 }, + { 0x820B, 60426 }, + { 0x820C, 60433 }, + { 0x820D, 60438 }, + { 0x820E, 60443 }, + { 0x820F, 60489 }, + { 0x8210, 60496 }, + { 0x8211, 60393 }, + { 0x8212, 60514 }, + { 0x8213, 60519 }, + { 0x8214, 60510 }, + { 0x8215, 60506 }, + { 0x8216, 60524 }, + { 0x8217, 62183 }, + { 0x8218, 62186 }, + { 0x8219, 62195 }, + { 0x821A, 62191 }, + { 0x821B, 60527 }, + { 0x821C, 60530 }, + { 0x821D, 60533 }, + { 0x821E, 60536 }, + { 0x821F, 60541 }, + { 0x8220, 59227 }, + { 0x8221, 59234 }, + { 0x8222, 59230 }, + { 0x8223, 60549 }, + { 0x8224, 60552 }, + { 0x8225, 60555 }, + { 0x8226, 61533 }, + { 0x8227, 62200 }, + { 0x8228, 59239 }, + { 0x8229, 60558 }, + { 0x822A, 59242 }, + { 0x822B, 60561 }, + { 0x822C, 59245 }, + { 0x822D, 59248 }, + { 0x822E, 60564 }, + { 0x822F, 60567 }, + { 0x8230, 62431 }, + { 0x8231, 62434 }, + { 0x8232, 61536 }, + { 0x8233, 61553 }, + { 0x8234, 61563 }, + { 0x8235, 61558 }, + { 0x8236, 61539 }, + { 0x8237, 61544 }, + { 0x8238, 61568 }, + { 0x8239, 62203 }, + { 0x823A, 62210 }, + { 0x823B, 62215 }, + { 0x823C, 62222 }, + { 0x823D, 62206 }, + { 0x823E, 59253 }, + { 0x823F, 60571 }, + { 0x8240, 61573 }, + { 0x8241, 61582 }, + { 0x8242, 61576 }, + { 0x8243, 61586 }, + { 0x8244, 62227 }, + { 0x8245, 60577 }, + { 0x8246, 60574 }, + { 0x8247, 61591 }, + { 0x8248, 59256 }, + { 0x8249, 59259 }, + { 0x824A, 59264 }, + { 0x824B, 59269 }, + { 0x824C, 59273 }, + { 0x824D, 59276 }, + { 0x824E, 60581 }, + { 0x824F, 60584 }, + { 0x8250, 60595 }, + { 0x8251, 60587 }, + { 0x8252, 62437 }, + { 0x8253, 62440 }, + { 0x8254, 62465 }, + { 0x8255, 62470 }, + { 0x8256, 62477 }, + { 0x8257, 62445 }, + { 0x8258, 62453 }, + { 0x8259, 62482 }, + { 0x825A, 62487 }, + { 0x825B, 62492 }, + { 0x825C, 62500 }, + { 0x825D, 62507 }, + { 0x825E, 62458 }, + { 0x825F, 62516 }, + { 0x8260, 62230 }, + { 0x8261, 59281 }, + { 0x8262, 61594 }, + { 0x8263, 60601 }, + { 0x8264, 60613 }, + { 0x8265, 60642 }, + { 0x8266, 60619 }, + { 0x8267, 60625 }, + { 0x8268, 60636 }, + { 0x8269, 60609 }, + { 0x826A, 60604 }, + { 0x826B, 60648 }, + { 0x826C, 60653 }, + { 0x826D, 62233 }, + { 0x826E, 62291 }, + { 0x826F, 62236 }, + { 0x8270, 62260 }, + { 0x8271, 62266 }, + { 0x8272, 62272 }, + { 0x8273, 62279 }, + { 0x8274, 62242 }, + { 0x8275, 62248 }, + { 0x8276, 62285 }, + { 0x8277, 62254 }, + { 0x8278, 62297 }, + { 0x8279, 62303 }, + { 0x827A, 59284 }, + { 0x827B, 60661 }, + { 0x827C, 60664 }, + { 0x827D, 60667 }, + { 0x827E, 62310 }, + { 0x827F, 59287 }, + { 0x8280, 59290 }, + { 0x8281, 59310 }, + { 0x8282, 59315 }, + { 0x8283, 59320 }, + { 0x8284, 59295 }, + { 0x8285, 59300 }, + { 0x8286, 59325 }, + { 0x8287, 59305 }, + { 0x8288, 59330 }, + { 0x8289, 59335 }, + { 0x828A, 62313 }, + { 0x828B, 62326 }, + { 0x828C, 62316 }, + { 0x828D, 62321 }, + { 0x828E, 62331 }, + { 0x828F, 59340 }, + { 0x8290, 60670 }, + { 0x8291, 59343 }, + { 0x8292, 59346 }, + { 0x8293, 59349 }, + { 0x8294, 60770 }, + { 0x8295, 60673 }, + { 0x8296, 60685 }, + { 0x8297, 60690 }, + { 0x8298, 60725 }, + { 0x8299, 60695 }, + { 0x829A, 60730 }, + { 0x829B, 60735 }, + { 0x829C, 60740 }, + { 0x829D, 60700 }, + { 0x829E, 60745 }, + { 0x829F, 60750 }, + { 0x82A0, 60765 }, + { 0x82A1, 60755 }, + { 0x82A2, 60705 }, + { 0x82A3, 60710 }, + { 0x82A4, 60715 }, + { 0x82A5, 60720 }, + { 0x82A6, 60760 }, + { 0x82A7, 60680 }, + { 0x82A8, 60676 }, + { 0x82A9, 60774 }, + { 0x82AA, 60777 }, + { 0x82AB, 62521 }, + { 0x82AC, 60783 }, + { 0x82AD, 60786 }, + { 0x82AE, 61597 }, + { 0x82AF, 61600 }, + { 0x82B0, 61622 }, + { 0x82B1, 61632 }, + { 0x82B2, 61617 }, + { 0x82B3, 61637 }, + { 0x82B4, 61627 }, + { 0x82B5, 61605 }, + { 0x82B6, 61610 }, + { 0x82B7, 61642 }, + { 0x82B8, 62336 }, + { 0x82B9, 62339 }, + { 0x82BA, 60789 }, + { 0x82BB, 60792 }, + { 0x82BC, 60796 }, + { 0x82BD, 60807 }, + { 0x82BE, 62342 }, + { 0x82BF, 61645 }, + { 0x82C0, 62345 }, + { 0x82C1, 62524 }, + { 0x82C2, 62547 }, + { 0x82C3, 61648 }, + { 0x82C4, 61651 }, + { 0x82C5, 61656 }, + { 0x82C6, 61661 }, + { 0x82C7, 61664 }, + { 0x82C8, 61669 }, + { 0x82C9, 61710 }, + { 0x82CA, 61674 }, + { 0x82CB, 61679 }, + { 0x82CC, 61684 }, + { 0x82CD, 61689 }, + { 0x82CE, 61715 }, + { 0x82CF, 61695 }, + { 0x82D0, 61700 }, + { 0x82D1, 61705 }, + { 0x82D2, 62527 }, + { 0x82D3, 61720 }, + { 0x82D4, 61731 }, + { 0x82D5, 61723 }, + { 0x82D6, 62348 }, + { 0x82D7, 60818 }, + { 0x82D8, 60821 }, + { 0x82D9, 61735 }, + { 0x82DA, 62530 }, + { 0x82DB, 59352 }, + { 0x82DC, 59355 }, + { 0x82DD, 60827 }, + { 0x82DE, 61738 }, + { 0x82DF, 61741 }, + { 0x82E0, 61747 }, + { 0x82E1, 62351 }, + { 0x82E2, 59359 }, + { 0x82E3, 59362 }, + { 0x82E4, 60830 }, + { 0x82E5, 61750 }, + { 0x82E6, 62354 }, + { 0x82E7, 60833 }, + { 0x82E8, 62533 }, + { 0x82E9, 60836 }, + { 0x82EA, 61753 }, + { 0x82EB, 59367 }, + { 0x82EC, 59384 }, + { 0x82ED, 59374 }, + { 0x82EE, 59379 }, + { 0x82EF, 59370 }, + { 0x82F0, 60839 }, + { 0x82F1, 60842 }, + { 0x82F2, 60853 }, + { 0x82F3, 60857 }, + { 0x82F4, 60860 }, + { 0x82F5, 60870 }, + { 0x82F6, 60875 }, + { 0x82F7, 60880 }, + { 0x82F8, 60885 }, + { 0x82F9, 60865 }, + { 0x82FA, 61756 }, + { 0x82FB, 60890 }, + { 0x82FC, 59388 }, + { 0x82FD, 59391 }, + { 0x82FE, 59395 }, + { 0x82FF, 59398 }, + { 0x8300, 60893 }, + { 0x8301, 60896 }, + { 0x8302, 60915 }, + { 0x8303, 60899 }, + { 0x8304, 60904 }, + { 0x8305, 59402 }, + { 0x8306, 61759 }, + { 0x8307, 60920 }, + { 0x8308, 60923 }, + { 0x8309, 60926 }, + { 0x830A, 60929 }, + { 0x830B, 58419 }, + { 0x830C, 58427 }, + { 0x830D, 58422 }, + { 0x830E, 58441 }, + { 0x830F, 58452 }, + { 0x8310, 58431 }, + { 0x8311, 59405 }, + { 0x8312, 59408 }, + { 0x8313, 59411 }, + { 0x8314, 59447 }, + { 0x8315, 59442 }, + { 0x8316, 59437 }, + { 0x8317, 59418 }, + { 0x8318, 59427 }, + { 0x8319, 59414 }, + { 0x831A, 59451 }, + { 0x831B, 59455 }, + { 0x831C, 61762 }, + { 0x831D, 59461 }, + { 0x831E, 59481 }, + { 0x831F, 59469 }, + { 0x8320, 59476 }, + { 0x8321, 59464 }, + { 0x8322, 62357 }, + { 0x8323, 61765 }, + { 0x8324, 61773 }, + { 0x8325, 61768 }, + { 0x8326, 59486 }, + { 0x8327, 59489 }, + { 0x8328, 59493 }, + { 0x8329, 59500 }, + { 0x832A, 59496 }, + { 0x832B, 60937 }, + { 0x832C, 60940 }, + { 0x832D, 60947 }, + { 0x832E, 60954 }, + { 0x832F, 60959 }, + { 0x8330, 60983 }, + { 0x8331, 60964 }, + { 0x8332, 60976 }, + { 0x8333, 60969 }, + { 0x8334, 60988 }, + { 0x8335, 60991 }, + { 0x8336, 61778 }, + { 0x8337, 60994 }, + { 0x8338, 60997 }, + { 0x8339, 61110 }, + { 0x833A, 61049 }, + { 0x833B, 61054 }, + { 0x833C, 61009 }, + { 0x833D, 61059 }, + { 0x833E, 61094 }, + { 0x833F, 61064 }, + { 0x8340, 61014 }, + { 0x8341, 61019 }, + { 0x8342, 61069 }, + { 0x8343, 61024 }, + { 0x8344, 61074 }, + { 0x8345, 61029 }, + { 0x8346, 61079 }, + { 0x8347, 61084 }, + { 0x8348, 61034 }, + { 0x8349, 61089 }, + { 0x834A, 61100 }, + { 0x834B, 61039 }, + { 0x834C, 61002 }, + { 0x834D, 61044 }, + { 0x834E, 61105 }, + { 0x834F, 62360 }, + { 0x8350, 62363 }, + { 0x8351, 61115 }, + { 0x8352, 61118 }, + { 0x8353, 61123 }, + { 0x8354, 61128 }, + { 0x8355, 61133 }, + { 0x8356, 61784 }, + { 0x8357, 61781 }, + { 0x8358, 62536 }, + { 0x8359, 62368 }, + { 0x835A, 61138 }, + { 0x835B, 61141 }, + { 0x835C, 61146 }, + { 0x835D, 59505 }, + { 0x835E, 59508 }, + { 0x835F, 59512 }, + { 0x8360, 61149 }, + { 0x8361, 61787 }, + { 0x8362, 61152 }, + { 0x8363, 59518 }, + { 0x8364, 59521 }, + { 0x8365, 61155 }, + { 0x8366, 61158 }, + { 0x8367, 61161 }, + { 0x8368, 61166 }, + { 0x8369, 61790 }, + { 0x836A, 59526 }, + { 0x836B, 61169 }, + { 0x836C, 61172 }, + { 0x836D, 62371 }, + { 0x836E, 61177 }, + { 0x8400, 62658 }, + { 0x8401, 63027 }, + { 0x8402, 62787 }, + { 0x8403, 62723 }, + { 0x8404, 62625 }, + { 0x8405, 62968 }, + { 0x8406, 62929 }, + { 0x8407, 62875 }, + { 0x8408, 63055 }, + { 0x8409, 62815 }, + { 0x840A, 62751 }, + { 0x840B, 62636 }, + { 0x840C, 62973 }, + { 0x840D, 62934 }, + { 0x840E, 62880 }, + { 0x840F, 62782 }, + { 0x8410, 62718 }, + { 0x8411, 62620 }, + { 0x8412, 62963 }, + { 0x8413, 62924 }, + { 0x8414, 62870 }, + { 0x8415, 62579 }, + { 0x8416, 62684 }, + { 0x8417, 63060 }, + { 0x8418, 62820 }, + { 0x8419, 62756 }, + { 0x841A, 62641 }, + { 0x841B, 62978 }, + { 0x841C, 62939 }, + { 0x841D, 62885 }, + { 0x841E, 62584 }, + { 0x841F, 62689 }, + { 0x8420, 63065 }, + { 0x8421, 62825 }, + { 0x8422, 62761 }, + { 0x8423, 62694 }, + { 0x8424, 63070 }, + { 0x8425, 63075 }, + { 0x8426, 62830 }, + { 0x8427, 62766 }, + { 0x8428, 62646 }, + { 0x8429, 62983 }, + { 0x842A, 62944 }, + { 0x842B, 62890 }, + { 0x842C, 62589 }, + { 0x842D, 62699 }, + { 0x842E, 63082 }, + { 0x842F, 63087 }, + { 0x8430, 62835 }, + { 0x8431, 62771 }, + { 0x8432, 63019 }, + { 0x8433, 63011 }, + { 0x8434, 62569 }, + { 0x8435, 62674 }, + { 0x8436, 63043 }, + { 0x8437, 63048 }, + { 0x8438, 62810 }, + { 0x8439, 62746 }, + { 0x843A, 63094 }, + { 0x843B, 63101 }, + { 0x843C, 62840 }, + { 0x843D, 62863 }, + { 0x843E, 62847 }, + { 0x843F, 62855 }, + { 0x8440, 62651 }, + { 0x8441, 63004 }, + { 0x8442, 62988 }, + { 0x8443, 62996 }, + { 0x8444, 62949 }, + { 0x8445, 62956 }, + { 0x8446, 62895 }, + { 0x8447, 62910 }, + { 0x8448, 62917 }, + { 0x8449, 62902 }, + { 0x844A, 62663 }, + { 0x844B, 63032 }, + { 0x844C, 62792 }, + { 0x844D, 62728 }, + { 0x844E, 62630 }, + { 0x844F, 62564 }, + { 0x8450, 62669 }, + { 0x8451, 63038 }, + { 0x8452, 62798 }, + { 0x8453, 62803 }, + { 0x8454, 62734 }, + { 0x8455, 62739 }, + { 0x8456, 63112 }, + { 0x8457, 63108 }, + { 0x8458, 62574 }, + { 0x8459, 62679 }, + { 0x845A, 62594 }, + { 0x845B, 62704 }, + { 0x845C, 62776 }, + { 0x845D, 62600 }, + { 0x845E, 62710 }, + { 0x845F, 62608 }, + { 0x8460, 62614 }, + { 0x8461, 62550 }, + { 0x8462, 62557 }, + { 0x8470, 63116 }, + { 0x8471, 63133 }, + { 0x8472, 63123 }, + { 0x8473, 63128 }, + { 0x9000, 56261 }, + { 0x9001, 56295 }, + { 0x9002, 57281 }, + { 0x9003, 56256 }, + { 0x9004, 56251 }, + { 0x9005, 56625 }, + { 0x9006, 56620 }, + { 0x9007, 56920 }, + { 0x9008, 57186 }, + { 0x9009, 57267 }, + { 0x900A, 57194 }, + { 0x900B, 57198 }, + { 0x900C, 56937 }, + { 0x900D, 56209 }, + { 0x900E, 56118 }, + { 0x900F, 56607 }, + { 0x9010, 57136 }, + { 0x9011, 57219 }, + { 0x9012, 57228 }, + { 0x9013, 56812 }, + { 0x9014, 56282 }, + { 0x9015, 56566 }, + { 0x9016, 56484 }, + { 0x9017, 56590 }, + { 0x9018, 56847 }, + { 0x9019, 56286 }, + { 0x901A, 56132 }, + { 0x901B, 56743 }, + { 0x901C, 57158 }, + { 0x901D, 57035 }, + { 0x901E, 57022 }, + { 0x901F, 56791 }, + { 0x9020, 56575 }, + { 0x9021, 56824 }, + { 0x9022, 56838 }, + { 0x9023, 56843 }, + { 0x9024, 56512 }, + { 0x9025, 56265 }, + { 0x9026, 56585 }, + { 0x9027, 56820 }, + { 0x9028, 57295 }, + { 0x9029, 56594 }, + { 0x902A, 56807 }, + { 0x902B, 56801 }, + { 0x902C, 57172 }, + { 0x902D, 56273 }, + { 0x902E, 56242 }, + { 0x902F, 56114 }, + { 0x9030, 56147 }, + { 0x9031, 56816 }, + { 0x9032, 57163 }, + { 0x9033, 56203 }, + { 0x9034, 56400 }, + { 0x9035, 57128 }, + { 0x9036, 57099 }, + { 0x9037, 56507 }, + { 0x9038, 57026 }, + { 0x9039, 57177 }, + { 0x903A, 56924 }, + { 0x903B, 56856 }, + { 0x903C, 56783 }, + { 0x903D, 57262 }, + { 0x903E, 57276 }, + { 0x903F, 56721 }, + { 0x9040, 56137 }, + { 0x9041, 56775 }, + { 0x9042, 56928 }, + { 0x9043, 57094 }, + { 0x9044, 57303 }, + { 0x9045, 57299 }, + { 0x9046, 56127 }, + { 0x9047, 56561 }, + { 0x9048, 56246 }, + { 0x9049, 56779 }, + { 0x904A, 56933 }, + { 0x904B, 57335 }, + { 0x904C, 57327 }, + { 0x904D, 57030 }, + { 0x904E, 57140 }, + { 0x904F, 56725 }, + { 0x9050, 56663 }, + { 0x9051, 57223 }, + { 0x9052, 57213 }, + { 0x9053, 56829 }, + { 0x9054, 57331 }, + { 0x9055, 56710 }, + { 0x9056, 56702 }, + { 0x9057, 56556 }, + { 0x9058, 56615 }, + { 0x9059, 56580 }, + { 0x905A, 57181 }, + { 0x905B, 56571 }, + { 0x905C, 57203 }, + { 0x905D, 56771 }, + { 0x905E, 57271 }, + { 0x905F, 57257 }, + { 0x9060, 56337 }, + { 0x9061, 56767 }, + { 0x9062, 57323 }, + { 0x9063, 57089 }, + { 0x9064, 57233 }, + { 0x9065, 56796 }, + { 0x9066, 56269 }, + { 0x9067, 56851 }, + { 0x9068, 56912 }, + { 0x9069, 56598 }, + { 0x906A, 56290 }, + { 0x906B, 57347 }, + { 0x906C, 57339 }, + { 0x906D, 57315 }, + { 0x906E, 57351 }, + { 0x906F, 57355 }, + { 0x9070, 57319 }, + { 0x9071, 57343 }, + { 0x9072, 57311 }, + { 0x9073, 57307 }, + { 0x9074, 56342 }, + { 0x9075, 57167 }, + { 0x9076, 57285 }, + { 0x9077, 57290 }, + { 0x9078, 56277 }, + { 0x9079, 56141 }, + { 0x907A, 57132 }, + { 0x907B, 57109 }, + { 0x907C, 56156 }, + { 0x907D, 56151 }, + { 0x907E, 56787 }, + { 0x907F, 56516 }, + { 0x9080, 56237 }, + { 0x9081, 56762 }, + { 0x9082, 56757 }, + { 0x9083, 56752 }, + { 0x9084, 56833 }, + { 0x9085, 56123 }, + { 0x9086, 56233 }, + { 0x9087, 56611 }, + { 0x9088, 57085 }, + { 0x9089, 56748 }, + { 0x908A, 56532 }, + { 0x908B, 56526 }, + { 0x908C, 56538 }, + { 0x908D, 56550 }, + { 0x908E, 56544 }, + { 0x908F, 56472 }, + { 0x9090, 56495 }, + { 0x9091, 56489 }, + { 0x9092, 56883 }, + { 0x9093, 56900 }, + { 0x9094, 56893 }, + { 0x9095, 56887 }, + { 0x9096, 57190 }, + { 0x9097, 56214 }, + { 0x9098, 57249 }, + { 0x9099, 56706 }, + { 0x909A, 56171 }, + { 0x909B, 56193 }, + { 0x909C, 56161 }, + { 0x909D, 56188 }, + { 0x909E, 56166 }, + { 0x909F, 56183 }, + { 0x90A0, 56198 }, + { 0x90A1, 56177 }, + { 0x90A2, 56961 }, + { 0x90A3, 56941 }, + { 0x90A4, 56992 }, + { 0x90A5, 56948 }, + { 0x90A6, 56967 }, + { 0x90A7, 57011 }, + { 0x90A8, 56998 }, + { 0x90A9, 57004 }, + { 0x90AA, 56973 }, + { 0x90AB, 56979 }, + { 0x90AC, 56501 }, + { 0x90AD, 57207 }, + { 0x90AE, 57123 }, + { 0x90AF, 57118 }, + { 0x90B0, 57113 }, + { 0x90B1, 56955 }, + { 0x90B2, 57016 }, + { 0x90B3, 56985 }, + { 0x90B4, 57237 }, + { 0x90B5, 57243 }, + { 0x90B6, 56714 }, + { 0x90B7, 56916 }, + { 0x90B8, 57253 }, + { 0x90B9, 56405 }, + { 0x90BA, 56438 }, + { 0x90BB, 56450 }, + { 0x90BC, 56361 }, + { 0x90BD, 56412 }, + { 0x90BE, 56393 }, + { 0x90BF, 56418 }, + { 0x90C0, 56444 }, + { 0x90C1, 56431 }, + { 0x90C2, 56424 }, + { 0x90C3, 56372 }, + { 0x90C4, 56379 }, + { 0x90C5, 56347 }, + { 0x90C6, 56386 }, + { 0x90C7, 56367 }, + { 0x90C8, 56218 }, + { 0x90C9, 56223 }, + { 0x90CA, 56228 }, + { 0x90CB, 56354 }, + { 0x90CC, 56456 }, + { 0x90CD, 56658 }, + { 0x90CE, 56327 }, + { 0x90CF, 56332 }, + { 0x90D0, 56299 }, + { 0x90D1, 56320 }, + { 0x90D2, 56306 }, + { 0x90D3, 56313 }, + { 0x90D4, 56630 }, + { 0x90D5, 56651 }, + { 0x90D6, 56637 }, + { 0x90D7, 56644 }, + { 0x90D8, 56462 }, + { 0x90D9, 56467 }, + { 0x90DA, 56861 }, + { 0x90DB, 56867 }, + { 0x90DC, 56873 }, + { 0x90DD, 56878 }, + { 0x90DE, 57062 }, + { 0x90DF, 57067 }, + { 0x90E0, 57073 }, + { 0x90E1, 57079 }, + { 0x90E2, 57039 }, + { 0x90E3, 57044 }, + { 0x90E4, 57050 }, + { 0x90E5, 57056 }, + { 0x90E6, 56907 }, + { 0x90E7, 57104 }, + { 0x90E8, 56603 }, + { 0x90E9, 56687 }, + { 0x90EA, 56697 }, + { 0x90EB, 56672 }, + { 0x90EC, 56667 }, + { 0x90ED, 56677 }, + { 0x90EE, 56692 }, + { 0x90EF, 56682 }, + { 0x90F0, 57152 }, + { 0x90F1, 56737 }, + { 0x90F2, 57146 }, + { 0x90F3, 56731 }, + { 0x90F4, 56521 }, + { 0x90F5, 56478 }, + { 0x9100, 41562 }, + { 0x9101, 41524 }, + { 0x9102, 41404 }, + { 0x9103, 41695 }, + { 0x9104, 41508 }, + { 0x9105, 41470 }, + { 0x9106, 41337 }, + { 0x9107, 41454 }, + { 0x9108, 41558 }, + { 0x9109, 41249 }, + { 0x910A, 41238 }, + { 0x910B, 41459 }, + { 0x910C, 41290 }, + { 0x910D, 41776 }, + { 0x910E, 41780 }, + { 0x910F, 41784 }, + { 0x9110, 41659 }, + { 0x9111, 41662 }, + { 0x9112, 41485 }, + { 0x9113, 41646 }, + { 0x9114, 41395 }, + { 0x9115, 41643 }, + { 0x9116, 41728 }, + { 0x9117, 41861 }, + { 0x9118, 42079 }, + { 0x9119, 41999 }, + { 0x911A, 41995 }, + { 0x911B, 41788 }, + { 0x911C, 42075 }, + { 0x911D, 42086 }, + { 0x911E, 41215 }, + { 0x911F, 41219 }, + { 0x9120, 41225 }, + { 0x9121, 41195 }, + { 0x9122, 41199 }, + { 0x9123, 41203 }, + { 0x9124, 41209 }, + { 0x9125, 41300 }, + { 0x9126, 41304 }, + { 0x9129, 41719 }, + { 0x912A, 41520 }, + { 0x912B, 41516 }, + { 0x912C, 41308 }, + { 0x912D, 41312 }, + { 0x912E, 41666 }, + { 0x912F, 41670 }, + { 0x9130, 41462 }, + { 0x9131, 41466 }, + { 0x9132, 41690 }, + { 0x9133, 41685 }, + { 0x9134, 41504 }, + { 0x9135, 41245 }, + { 0x9136, 41550 }, + { 0x9137, 41554 }, + { 0x9138, 42103 }, + { 0x9139, 42107 }, + { 0x913A, 41438 }, + { 0x913B, 41481 }, + { 0x913C, 41328 }, + { 0x913D, 41681 }, + { 0x913E, 41532 }, + { 0x913F, 42039 }, + { 0x9140, 42123 }, + { 0x9141, 42115 }, + { 0x9142, 41280 }, + { 0x9143, 41231 }, + { 0x9144, 41356 }, + { 0x9145, 41496 }, + { 0x9146, 41575 }, + { 0x9147, 41570 }, + { 0x9148, 41819 }, + { 0x9149, 41799 }, + { 0x914A, 41843 }, + { 0x914B, 41837 }, + { 0x914C, 41855 }, + { 0x914D, 41849 }, + { 0x914E, 41831 }, + { 0x914F, 41825 }, + { 0x9150, 41812 }, + { 0x9151, 41805 }, + { 0x9152, 41347 }, + { 0x9153, 41342 }, + { 0x9154, 42133 }, + { 0x9155, 42127 }, + { 0x9156, 42096 }, + { 0x9157, 41371 }, + { 0x9158, 41724 }, + { 0x9159, 41352 }, + { 0x915A, 41654 }, + { 0x915B, 41649 }, + { 0x915C, 41398 }, + { 0x915D, 41477 }, + { 0x915E, 41324 }, + { 0x915F, 41677 }, + { 0x9160, 41528 }, + { 0x9161, 42035 }, + { 0x9162, 42119 }, + { 0x9163, 42111 }, + { 0x9164, 41274 }, + { 0x9165, 41896 }, + { 0x9166, 41975 }, + { 0x9167, 41958 }, + { 0x9168, 41962 }, + { 0x9169, 41966 }, + { 0x916A, 41703 }, + { 0x916B, 41707 }, + { 0x916C, 41711 }, + { 0x916D, 41970 }, + { 0x916E, 41917 }, + { 0x916F, 41921 }, + { 0x9170, 41925 }, + { 0x9171, 41929 }, + { 0x9172, 41933 }, + { 0x9173, 41383 }, + { 0x9174, 41262 }, + { 0x9175, 41379 }, + { 0x9176, 41258 }, + { 0x9177, 41387 }, + { 0x9178, 41266 }, + { 0x9179, 41391 }, + { 0x917A, 41270 }, + { 0x917B, 41908 }, + { 0x917C, 41954 }, + { 0x917D, 41937 }, + { 0x917E, 41980 }, + { 0x917F, 41946 }, + { 0x9180, 41988 }, + { 0x9181, 41984 }, + { 0x9182, 41900 }, + { 0x9183, 42043 }, + { 0x9184, 42047 }, + { 0x9185, 41878 }, + { 0x9186, 41870 }, + { 0x9187, 41887 }, + { 0x9188, 41904 }, + { 0x9189, 41874 }, + { 0x918A, 41912 }, + { 0x918B, 41941 }, + { 0x918C, 42100 }, + { 0x918D, 41580 }, + { 0x918E, 41235 }, + { 0x918F, 41451 }, + { 0x9190, 41435 }, + { 0x9191, 41408 }, + { 0x9192, 41992 }, + { 0x9193, 42083 }, + { 0x9194, 41417 }, + { 0x9195, 41411 }, + { 0x9196, 41242 }, + { 0x9197, 41360 }, + { 0x9198, 41715 }, + { 0x9199, 41367 }, + { 0x919A, 41363 }, + { 0x919B, 41732 }, + { 0x919C, 41736 }, + { 0x919D, 41740 }, + { 0x919E, 41744 }, + { 0x919F, 41748 }, + { 0x91A0, 41752 }, + { 0x91A1, 41756 }, + { 0x91A2, 41760 }, + { 0x91A3, 41764 }, + { 0x91A4, 41768 }, + { 0x91A5, 41772 }, + { 0x91A6, 42090 }, + { 0x91A7, 42093 }, + { 0x91A8, 41253 }, + { 0x91A9, 41512 }, + { 0x91AA, 41882 }, + { 0x91AB, 41865 }, + { 0x91AC, 41950 }, + { 0x91AD, 41891 }, + { 0x91AE, 41447 }, + { 0x91AF, 41442 }, + { 0x91B0, 41332 }, + { 0x91B1, 42003 }, + { 0x91B2, 42007 }, + { 0x91B3, 41375 }, + { 0x91B4, 41293 }, + { 0x91B5, 41296 }, + { 0x91B6, 41536 }, + { 0x91B7, 41422 }, + { 0x91B8, 41489 }, + { 0x91B9, 42059 }, + { 0x91BA, 42055 }, + { 0x91BB, 41539 }, + { 0x91BC, 41546 }, + { 0x91BD, 42071 }, + { 0x91BE, 42067 }, + { 0x91BF, 41320 }, + { 0x91C0, 41316 }, + { 0x91C1, 41425 }, + { 0x91C2, 41430 }, + { 0x91C3, 41492 }, + { 0x91C4, 42051 }, + { 0x91C5, 41542 }, + { 0x91C6, 42063 }, + { 0x91C7, 41583 }, + { 0x91C8, 41598 }, + { 0x91C9, 41590 }, + { 0x91CA, 41605 }, + { 0x91CB, 41612 }, + { 0x91CC, 41619 }, + { 0x91CD, 41627 }, + { 0x91CE, 41635 }, + { 0x91CF, 41401 }, + { 0x91D0, 42011 }, + { 0x91D1, 42016 }, + { 0x91D2, 41566 }, + { 0x91D3, 41474 }, + { 0x91D4, 41674 }, + { 0x91D5, 41501 }, + { 0x91D6, 42028 }, + { 0x91D7, 41700 }, + { 0x91D8, 41792 }, + { 0x91D9, 42021 }, + { 0x91DA, 42024 }, + { 0x91DB, 42031 }, + { 0x91DC, 41795 }, + { 0x91DD, 41286 }, + { 0x9200, 11902 }, + { 0x9201, 11906 }, + { 0x9202, 11910 }, + { 0x9203, 11914 }, + { 0x9204, 11918 }, + { 0x9205, 11922 }, + { 0x9206, 11926 }, + { 0x9207, 11930 }, + { 0x9208, 11934 }, + { 0x9209, 11938 }, + { 0x920A, 11942 }, + { 0x920B, 11946 }, + { 0x920C, 11950 }, + { 0x920D, 11954 }, + { 0x920E, 11958 }, + { 0x920F, 11962 }, + { 0x9210, 11966 }, + { 0x9211, 11970 }, + { 0x9212, 11974 }, + { 0x9213, 11978 }, + { 0x9214, 11982 }, + { 0x9215, 11986 }, + { 0x9216, 11990 }, + { 0x9217, 11994 }, + { 0x9218, 11998 }, + { 0x9219, 12002 }, + { 0x921A, 12006 }, + { 0x921B, 12010 }, + { 0x921C, 12014 }, + { 0x921D, 13374 }, + { 0x921E, 13378 }, + { 0x921F, 13382 }, + { 0x9220, 13386 }, + { 0x9221, 13390 }, + { 0x9222, 13394 }, + { 0x9223, 13398 }, + { 0x9224, 13402 }, + { 0x9225, 13406 }, + { 0x9226, 13410 }, + { 0x9227, 13414 }, + { 0x9228, 13418 }, + { 0x9229, 13422 }, + { 0x922A, 13426 }, + { 0x922B, 13430 }, + { 0x922C, 13434 }, + { 0x922D, 13438 }, + { 0x922E, 13442 }, + { 0x922F, 13446 }, + { 0x9230, 13450 }, + { 0x9231, 13454 }, + { 0x9232, 13458 }, + { 0x9233, 13462 }, + { 0x9234, 13466 }, + { 0x9235, 13470 }, + { 0x9236, 13474 }, + { 0x9237, 13478 }, + { 0x9238, 13482 }, + { 0x9239, 13486 }, + { 0x923A, 13490 }, + { 0x923B, 13494 }, + { 0x923C, 13498 }, + { 0x923D, 13502 }, + { 0x923E, 13506 }, + { 0x923F, 13510 }, + { 0x9240, 13514 }, + { 0x9241, 13518 }, + { 0x9242, 57564 }, + { 0x9243, 57572 }, + { 0x9244, 57568 }, + { 0x9245, 13031 }, + { 0x9300, 54871 }, + { 0x9301, 31216 }, + { 0x9302, 31188 }, + { 0x9303, 31204 }, + { 0x9304, 31200 }, + { 0x9305, 31185 }, + { 0x9306, 66100 }, + { 0x9307, 66067 }, + { 0x9308, 66082 }, + { 0x9309, 66128 }, + { 0x930A, 66147 }, + { 0x930B, 66272 }, + { 0x930C, 66097 }, + { 0x930D, 66263 }, + { 0x930E, 66201 }, + { 0x930F, 66299 }, + { 0x9310, 66254 }, + { 0x9311, 66296 }, + { 0x9312, 66184 }, + { 0x9313, 66281 }, + { 0x9314, 66085 }, + { 0x9315, 66134 }, + { 0x9316, 66143 }, + { 0x9317, 66172 }, + { 0x9318, 66220 }, + { 0x9319, 66125 }, + { 0x931A, 66166 }, + { 0x931B, 66266 }, + { 0x931C, 66064 }, + { 0x931D, 66052 }, + { 0x931E, 66251 }, + { 0x931F, 66217 }, + { 0x9320, 66110 }, + { 0x9321, 66103 }, + { 0x9322, 66287 }, + { 0x9323, 66060 }, + { 0x9324, 66160 }, + { 0x9325, 66116 }, + { 0x9326, 66205 }, + { 0x9327, 66151 }, + { 0x9328, 66226 }, + { 0x9329, 66193 }, + { 0x932A, 66119 }, + { 0x932B, 66178 }, + { 0x932C, 66239 }, + { 0x932D, 66055 }, + { 0x932E, 66187 }, + { 0x932F, 66074 }, + { 0x9330, 66257 }, + { 0x9331, 66088 }, + { 0x9332, 66233 }, + { 0x9333, 66275 }, + { 0x9334, 66163 }, + { 0x9335, 66122 }, + { 0x9336, 66113 }, + { 0x9337, 66196 }, + { 0x9338, 66208 }, + { 0x9339, 66157 }, + { 0x933A, 66175 }, + { 0x933B, 66091 }, + { 0x933C, 66293 }, + { 0x933D, 66106 }, + { 0x933E, 66278 }, + { 0x933F, 66229 }, + { 0x9340, 66154 }, + { 0x9341, 66284 }, + { 0x9342, 66304 }, + { 0x9343, 66071 }, + { 0x9344, 66094 }, + { 0x9345, 66169 }, + { 0x9346, 66079 }, + { 0x9347, 66214 }, + { 0x9348, 66211 }, + { 0x9349, 66137 }, + { 0x934A, 66260 }, + { 0x934B, 66242 }, + { 0x934C, 66190 }, + { 0x934D, 66181 }, + { 0x934E, 66245 }, + { 0x934F, 66131 }, + { 0x9350, 66140 }, + { 0x9351, 66269 }, + { 0x9352, 66248 }, + { 0x9353, 66047 }, + { 0x9354, 66290 }, + { 0x9355, 66236 }, + { 0x9356, 66223 }, + { 0x9360, 48474 }, + { 0x9361, 48484 }, + { 0x9362, 48514 }, + { 0x9363, 48494 }, + { 0x9364, 48489 }, + { 0x9365, 48479 }, + { 0x9366, 48509 }, + { 0x9367, 48504 }, + { 0x9368, 48499 }, + { 0x9369, 48429 }, + { 0x936A, 48439 }, + { 0x936B, 48469 }, + { 0x936C, 48449 }, + { 0x936D, 48444 }, + { 0x936E, 48434 }, + { 0x936F, 48464 }, + { 0x9370, 48459 }, + { 0x9371, 48454 }, + { 0x9400, 70678 }, + { 0x9401, 70682 }, + { 0x9402, 70686 }, + { 0x9403, 70690 }, + { 0x9404, 70694 }, + { 0x9405, 70698 }, + { 0x9406, 70702 }, + { 0x9407, 70706 }, + { 0x9408, 70710 }, + { 0x9409, 70714 }, + { 0x940A, 70718 }, + { 0x940B, 70722 }, + { 0x940C, 70726 }, + { 0x940D, 70730 }, + { 0x940E, 70734 }, + { 0x940F, 70738 }, + { 0x9410, 70742 }, + { 0x9411, 70746 }, + { 0x9412, 70750 }, + { 0x9413, 70754 }, + { 0x9414, 70758 }, + { 0x9415, 70762 }, + { 0x9416, 70766 }, + { 0x9417, 70770 }, + { 0x9418, 70774 }, + { 0x9419, 70778 }, + { 0x941A, 69654 }, + { 0x941B, 69658 }, + { 0x941C, 69662 }, + { 0x941D, 69666 }, + { 0x941E, 69670 }, + { 0x941F, 69674 }, + { 0x9420, 69678 }, + { 0x9421, 69682 }, + { 0x9422, 69686 }, + { 0x9423, 69690 }, + { 0x9424, 69694 }, + { 0x9425, 69698 }, + { 0x9426, 69702 }, + { 0x9427, 69706 }, + { 0x9428, 69710 }, + { 0x9429, 69714 }, + { 0x942A, 69718 }, + { 0x942B, 69722 }, + { 0x942C, 69726 }, + { 0x942D, 69730 }, + { 0x942E, 69734 }, + { 0x942F, 69738 }, + { 0x9430, 69742 }, + { 0x9431, 69746 }, + { 0x9432, 69750 }, + { 0x9433, 69754 }, + { 0x9434, 71437 }, + { 0x9435, 71441 }, + { 0x9436, 71445 }, + { 0x9437, 71449 }, + { 0x9438, 71453 }, + { 0x9439, 71457 }, + { 0x943A, 71461 }, + { 0x943B, 71465 }, + { 0x943C, 71469 }, + { 0x943D, 71473 }, + { 0x943E, 71477 }, + { 0x943F, 71481 }, + { 0x9440, 71485 }, + { 0x9441, 71489 }, + { 0x9442, 71493 }, + { 0x9443, 71497 }, + { 0x9444, 71501 }, + { 0x9445, 71505 }, + { 0x9446, 71509 }, + { 0x9447, 71513 }, + { 0x9448, 71517 }, + { 0x9449, 71521 }, + { 0x944A, 71525 }, + { 0x944B, 71529 }, + { 0x944C, 71533 }, + { 0x944D, 71537 }, + { 0x944E, 71222 }, + { 0x944F, 71226 }, + { 0x9450, 71230 }, + { 0x9451, 71234 }, + { 0x9452, 71238 }, + { 0x9453, 71242 }, + { 0x9454, 71246 }, + { 0x9456, 71250 }, + { 0x9457, 71254 }, + { 0x9458, 71258 }, + { 0x9459, 71262 }, + { 0x945A, 71266 }, + { 0x945B, 71270 }, + { 0x945C, 71274 }, + { 0x945D, 71278 }, + { 0x945E, 71282 }, + { 0x945F, 71286 }, + { 0x9460, 71290 }, + { 0x9461, 71294 }, + { 0x9462, 71298 }, + { 0x9463, 71302 }, + { 0x9464, 71306 }, + { 0x9465, 71310 }, + { 0x9466, 71314 }, + { 0x9467, 71318 }, + { 0x9468, 70152 }, + { 0x9469, 70157 }, + { 0x946A, 70162 }, + { 0x946B, 70167 }, + { 0x946C, 70172 }, + { 0x946D, 70177 }, + { 0x946E, 70182 }, + { 0x946F, 70187 }, + { 0x9470, 70192 }, + { 0x9471, 70197 }, + { 0x9472, 70202 }, + { 0x9473, 70207 }, + { 0x9474, 70212 }, + { 0x9475, 70217 }, + { 0x9476, 70222 }, + { 0x9477, 70227 }, + { 0x9478, 70232 }, + { 0x9479, 70237 }, + { 0x947A, 70242 }, + { 0x947B, 70247 }, + { 0x947C, 70252 }, + { 0x947D, 70257 }, + { 0x947E, 70262 }, + { 0x947F, 70267 }, + { 0x9480, 70272 }, + { 0x9481, 70277 }, + { 0x9482, 69891 }, + { 0x9483, 69896 }, + { 0x9484, 69901 }, + { 0x9485, 69906 }, + { 0x9486, 69911 }, + { 0x9487, 69916 }, + { 0x9488, 69921 }, + { 0x9489, 69926 }, + { 0x948A, 69931 }, + { 0x948B, 69936 }, + { 0x948C, 69941 }, + { 0x948D, 69946 }, + { 0x948E, 69951 }, + { 0x948F, 69956 }, + { 0x9490, 69961 }, + { 0x9491, 69966 }, + { 0x9492, 69971 }, + { 0x9493, 69976 }, + { 0x9494, 69981 }, + { 0x9495, 69986 }, + { 0x9496, 69991 }, + { 0x9497, 69996 }, + { 0x9498, 70001 }, + { 0x9499, 70006 }, + { 0x949A, 70011 }, + { 0x949B, 70016 }, + { 0x949C, 71742 }, + { 0x949E, 71746 }, + { 0x949F, 71750 }, + { 0x94A2, 71754 }, + { 0x94A5, 71758 }, + { 0x94A6, 71762 }, + { 0x94A9, 71766 }, + { 0x94AA, 71770 }, + { 0x94AB, 71774 }, + { 0x94AC, 71778 }, + { 0x94AE, 71782 }, + { 0x94AF, 71786 }, + { 0x94B0, 71790 }, + { 0x94B1, 71794 }, + { 0x94B2, 71798 }, + { 0x94B3, 71802 }, + { 0x94B4, 71806 }, + { 0x94B5, 71810 }, + { 0x94B6, 71650 }, + { 0x94B7, 71654 }, + { 0x94B8, 71658 }, + { 0x94B9, 71662 }, + { 0x94BB, 71666 }, + { 0x94BD, 71670 }, + { 0x94BE, 71674 }, + { 0x94BF, 71678 }, + { 0x94C0, 71682 }, + { 0x94C1, 71686 }, + { 0x94C2, 71690 }, + { 0x94C3, 71694 }, + { 0x94C5, 71698 }, + { 0x94C6, 71702 }, + { 0x94C7, 71706 }, + { 0x94C8, 71710 }, + { 0x94C9, 71714 }, + { 0x94CA, 71718 }, + { 0x94CB, 71722 }, + { 0x94CC, 71726 }, + { 0x94CD, 71730 }, + { 0x94CE, 71734 }, + { 0x94CF, 71738 }, + { 0x94D0, 70548 }, + { 0x94D1, 70553 }, + { 0x94D2, 70558 }, + { 0x94D3, 70563 }, + { 0x94D4, 70568 }, + { 0x94D5, 70573 }, + { 0x94D6, 70578 }, + { 0x94D7, 70583 }, + { 0x94D8, 70588 }, + { 0x94D9, 70593 }, + { 0x94DA, 70598 }, + { 0x94DB, 70603 }, + { 0x94DC, 70608 }, + { 0x94DD, 70613 }, + { 0x94DE, 70618 }, + { 0x94DF, 70623 }, + { 0x94E0, 70628 }, + { 0x94E1, 70633 }, + { 0x94E2, 70638 }, + { 0x94E3, 70643 }, + { 0x94E4, 70648 }, + { 0x94E5, 70653 }, + { 0x94E6, 70658 }, + { 0x94E7, 70663 }, + { 0x94E8, 70668 }, + { 0x94E9, 70673 }, + { 0x94EA, 70418 }, + { 0x94EB, 70423 }, + { 0x94EC, 70428 }, + { 0x94ED, 70433 }, + { 0x94EE, 70438 }, + { 0x94EF, 70443 }, + { 0x94F0, 70448 }, + { 0x94F1, 70453 }, + { 0x94F2, 70458 }, + { 0x94F3, 70463 }, + { 0x94F4, 70468 }, + { 0x94F5, 70473 }, + { 0x94F6, 70478 }, + { 0x94F7, 70483 }, + { 0x94F8, 70488 }, + { 0x94F9, 70493 }, + { 0x94FA, 70498 }, + { 0x94FB, 70503 }, + { 0x94FC, 70508 }, + { 0x94FD, 70513 }, + { 0x94FE, 70518 }, + { 0x94FF, 70523 }, + { 0x9500, 70528 }, + { 0x9501, 70533 }, + { 0x9502, 70538 }, + { 0x9503, 70543 }, + { 0x9504, 71918 }, + { 0x9505, 71922 }, + { 0x9507, 71926 }, + { 0x9508, 71930 }, + { 0x9509, 71934 }, + { 0x950A, 71938 }, + { 0x950D, 71942 }, + { 0x950E, 71946 }, + { 0x950F, 71950 }, + { 0x9510, 71954 }, + { 0x9511, 71958 }, + { 0x9512, 71962 }, + { 0x9513, 71966 }, + { 0x9514, 71970 }, + { 0x9516, 71974 }, + { 0x9517, 71978 }, + { 0x9518, 71982 }, + { 0x9519, 71986 }, + { 0x951A, 71990 }, + { 0x951B, 71994 }, + { 0x951C, 71998 }, + { 0x951E, 71814 }, + { 0x951F, 71818 }, + { 0x9520, 71822 }, + { 0x9521, 71826 }, + { 0x9522, 71830 }, + { 0x9523, 71834 }, + { 0x9524, 71838 }, + { 0x9525, 71842 }, + { 0x9526, 71846 }, + { 0x9527, 71850 }, + { 0x9528, 71854 }, + { 0x9529, 71858 }, + { 0x952A, 71862 }, + { 0x952B, 71866 }, + { 0x952C, 71870 }, + { 0x952D, 71874 }, + { 0x952E, 71878 }, + { 0x952F, 71882 }, + { 0x9530, 71886 }, + { 0x9531, 71890 }, + { 0x9532, 71894 }, + { 0x9533, 71898 }, + { 0x9534, 71902 }, + { 0x9535, 71906 }, + { 0x9536, 71910 }, + { 0x9537, 71914 }, + { 0x9538, 74164 }, + { 0x9539, 74168 }, + { 0x953B, 74172 }, + { 0x953C, 74176 }, + { 0x953D, 74180 }, + { 0x953E, 74184 }, + { 0x9540, 74188 }, + { 0x9541, 74192 }, + { 0x9542, 74196 }, + { 0x9543, 74200 }, + { 0x9544, 74204 }, + { 0x9546, 74208 }, + { 0x954A, 74212 }, + { 0x954B, 74216 }, + { 0x954C, 74220 }, + { 0x954D, 74224 }, + { 0x954E, 74228 }, + { 0x954F, 74232 }, + { 0x9550, 74236 }, + { 0x9552, 74060 }, + { 0x9553, 74064 }, + { 0x9554, 74068 }, + { 0x9555, 74072 }, + { 0x9556, 74076 }, + { 0x9557, 74080 }, + { 0x9558, 74084 }, + { 0x9559, 74088 }, + { 0x955A, 74092 }, + { 0x955B, 74096 }, + { 0x955C, 74100 }, + { 0x955D, 74104 }, + { 0x955E, 74108 }, + { 0x955F, 74112 }, + { 0x9560, 74116 }, + { 0x9561, 74120 }, + { 0x9562, 74124 }, + { 0x9563, 74128 }, + { 0x9564, 74132 }, + { 0x9565, 74136 }, + { 0x9566, 74140 }, + { 0x9567, 74144 }, + { 0x9568, 74148 }, + { 0x9569, 74152 }, + { 0x956A, 74156 }, + { 0x956B, 74160 }, + { 0x956C, 71021 }, + { 0x956D, 71026 }, + { 0x956E, 71031 }, + { 0x956F, 71036 }, + { 0x9570, 71041 }, + { 0x9571, 71046 }, + { 0x9572, 71051 }, + { 0x9573, 71056 }, + { 0x9574, 71061 }, + { 0x9575, 71066 }, + { 0x9576, 71071 }, + { 0x9577, 71076 }, + { 0x9578, 71081 }, + { 0x9579, 71086 }, + { 0x957A, 71091 }, + { 0x957B, 71096 }, + { 0x957C, 71101 }, + { 0x957D, 71106 }, + { 0x957E, 71111 }, + { 0x957F, 71116 }, + { 0x9580, 71121 }, + { 0x9581, 71126 }, + { 0x9582, 71131 }, + { 0x9583, 71136 }, + { 0x9584, 71141 }, + { 0x9585, 71146 }, + { 0x9586, 70891 }, + { 0x9587, 70896 }, + { 0x9588, 70901 }, + { 0x9589, 70906 }, + { 0x958A, 70911 }, + { 0x958B, 70916 }, + { 0x958C, 70921 }, + { 0x958D, 70926 }, + { 0x958E, 70931 }, + { 0x958F, 70936 }, + { 0x9590, 70941 }, + { 0x9591, 70946 }, + { 0x9592, 70951 }, + { 0x9593, 70956 }, + { 0x9594, 70961 }, + { 0x9595, 70966 }, + { 0x9596, 70971 }, + { 0x9597, 70976 }, + { 0x9598, 70981 }, + { 0x9599, 70986 }, + { 0x959A, 70991 }, + { 0x959B, 70996 }, + { 0x959C, 71001 }, + { 0x959D, 71006 }, + { 0x959E, 71011 }, + { 0x959F, 71016 }, + { 0x95A0, 73916 }, + { 0x95A1, 73920 }, + { 0x95A2, 73924 }, + { 0x95A3, 73928 }, + { 0x95A4, 73932 }, + { 0x95A5, 73936 }, + { 0x95A6, 73940 }, + { 0x95A7, 73944 }, + { 0x95A8, 73948 }, + { 0x95A9, 73952 }, + { 0x95AA, 73956 }, + { 0x95AB, 73960 }, + { 0x95AC, 73964 }, + { 0x95AD, 73968 }, + { 0x95AE, 73972 }, + { 0x95AF, 73976 }, + { 0x95B0, 73980 }, + { 0x95B1, 73984 }, + { 0x95B2, 73988 }, + { 0x95B3, 73992 }, + { 0x95B4, 73996 }, + { 0x95B5, 74000 }, + { 0x95B6, 74004 }, + { 0x95B7, 74008 }, + { 0x95B8, 74012 }, + { 0x95B9, 74016 }, + { 0x95BA, 73552 }, + { 0x95BB, 73556 }, + { 0x95BC, 73560 }, + { 0x95BD, 73564 }, + { 0x95BE, 73568 }, + { 0x95BF, 73572 }, + { 0x95C0, 73576 }, + { 0x95C1, 73580 }, + { 0x95C2, 73584 }, + { 0x95C3, 73588 }, + { 0x95C4, 73592 }, + { 0x95C5, 73596 }, + { 0x95C6, 73600 }, + { 0x95C7, 73604 }, + { 0x95C8, 73608 }, + { 0x95C9, 73612 }, + { 0x95CA, 73616 }, + { 0x95CB, 73620 }, + { 0x95CC, 73624 }, + { 0x95CD, 73628 }, + { 0x95CE, 73632 }, + { 0x95CF, 73636 }, + { 0x95D0, 73640 }, + { 0x95D1, 73644 }, + { 0x95D2, 73648 }, + { 0x95D3, 73652 }, + { 0x95D4, 73246 }, + { 0x95D5, 73251 }, + { 0x95D6, 73256 }, + { 0x95D7, 73261 }, + { 0x95D8, 73266 }, + { 0x95D9, 73271 }, + { 0x95DA, 73276 }, + { 0x95DB, 73281 }, + { 0x95DC, 73286 }, + { 0x95DD, 73291 }, + { 0x95DE, 73296 }, + { 0x95DF, 73301 }, + { 0x95E0, 73306 }, + { 0x95E1, 73311 }, + { 0x95E2, 73316 }, + { 0x95E3, 73321 }, + { 0x95E4, 73326 }, + { 0x95E5, 73331 }, + { 0x95E6, 73336 }, + { 0x95E7, 73341 }, + { 0x95E8, 73346 }, + { 0x95E9, 73351 }, + { 0x95EA, 73356 }, + { 0x95EB, 73361 }, + { 0x95EC, 73366 }, + { 0x95ED, 73371 }, + { 0x95EE, 72324 }, + { 0x95EF, 72329 }, + { 0x95F0, 72334 }, + { 0x95F1, 72339 }, + { 0x95F2, 72344 }, + { 0x95F3, 72349 }, + { 0x95F4, 72354 }, + { 0x95F5, 72359 }, + { 0x95F6, 72364 }, + { 0x95F7, 72369 }, + { 0x95F8, 72374 }, + { 0x95F9, 72379 }, + { 0x95FA, 72384 }, + { 0x95FB, 72389 }, + { 0x95FC, 72394 }, + { 0x95FD, 72399 }, + { 0x95FE, 72404 }, + { 0x95FF, 72409 }, + { 0x9600, 72414 }, + { 0x9601, 72419 }, + { 0x9602, 72424 }, + { 0x9603, 72429 }, + { 0x9604, 72434 }, + { 0x9605, 72439 }, + { 0x9606, 72444 }, + { 0x9607, 72449 }, + { 0x9608, 73786 }, + { 0x9609, 73791 }, + { 0x960A, 73796 }, + { 0x960B, 73801 }, + { 0x960C, 73806 }, + { 0x960D, 73811 }, + { 0x960E, 73816 }, + { 0x960F, 73821 }, + { 0x9610, 73826 }, + { 0x9611, 73831 }, + { 0x9612, 73836 }, + { 0x9613, 73841 }, + { 0x9614, 73846 }, + { 0x9615, 73851 }, + { 0x9616, 73856 }, + { 0x9617, 73861 }, + { 0x9618, 73866 }, + { 0x9619, 73871 }, + { 0x961A, 73876 }, + { 0x961B, 73881 }, + { 0x961C, 73886 }, + { 0x961D, 73891 }, + { 0x961E, 73896 }, + { 0x961F, 73901 }, + { 0x9620, 73906 }, + { 0x9621, 73911 }, + { 0x9622, 73656 }, + { 0x9623, 73661 }, + { 0x9624, 73666 }, + { 0x9625, 73671 }, + { 0x9626, 73676 }, + { 0x9627, 73681 }, + { 0x9628, 73686 }, + { 0x9629, 73691 }, + { 0x962A, 73696 }, + { 0x962B, 73701 }, + { 0x962C, 73706 }, + { 0x962D, 73711 }, + { 0x962E, 73716 }, + { 0x962F, 73721 }, + { 0x9630, 73726 }, + { 0x9631, 73731 }, + { 0x9632, 73736 }, + { 0x9633, 73741 }, + { 0x9634, 73746 }, + { 0x9635, 73751 }, + { 0x9636, 73756 }, + { 0x9637, 73761 }, + { 0x9638, 73766 }, + { 0x9639, 73771 }, + { 0x963A, 73776 }, + { 0x963B, 73781 }, + { 0x963C, 72927 }, + { 0x963D, 72933 }, + { 0x963E, 72939 }, + { 0x963F, 72945 }, + { 0x9640, 72951 }, + { 0x9641, 72957 }, + { 0x9642, 72963 }, + { 0x9643, 72969 }, + { 0x9644, 72975 }, + { 0x9645, 72981 }, + { 0x9646, 72987 }, + { 0x9647, 72993 }, + { 0x9648, 72999 }, + { 0x9649, 73005 }, + { 0x964A, 73011 }, + { 0x964B, 73017 }, + { 0x964C, 73023 }, + { 0x964D, 73029 }, + { 0x964E, 73035 }, + { 0x964F, 73041 }, + { 0x9650, 73047 }, + { 0x9651, 73053 }, + { 0x9652, 73059 }, + { 0x9653, 73065 }, + { 0x9654, 73071 }, + { 0x9655, 73077 }, + { 0x9656, 72614 }, + { 0x9657, 72620 }, + { 0x9658, 72626 }, + { 0x9659, 72632 }, + { 0x965A, 72638 }, + { 0x965B, 72644 }, + { 0x965C, 72650 }, + { 0x965D, 72656 }, + { 0x965E, 72662 }, + { 0x965F, 72668 }, + { 0x9660, 72674 }, + { 0x9661, 72680 }, + { 0x9662, 72686 }, + { 0x9663, 72692 }, + { 0x9664, 72698 }, + { 0x9665, 72704 }, + { 0x9666, 72710 }, + { 0x9667, 72716 }, + { 0x9668, 72722 }, + { 0x9669, 72728 }, + { 0x966A, 72734 }, + { 0x966B, 72740 }, + { 0x966C, 72746 }, + { 0x966D, 72752 }, + { 0x966E, 72758 }, + { 0x966F, 72764 }, + { 0x9670, 72146 }, + { 0x9671, 72150 }, + { 0x9672, 72154 }, + { 0x9673, 72158 }, + { 0x9674, 72162 }, + { 0x9675, 72166 }, + { 0x9676, 72170 }, + { 0x9677, 72174 }, + { 0x9678, 72178 }, + { 0x9679, 72182 }, + { 0x967A, 72186 }, + { 0x967B, 72190 }, + { 0x967C, 72194 }, + { 0x967D, 72198 }, + { 0x967E, 72202 }, + { 0x967F, 72206 }, + { 0x9680, 72210 }, + { 0x9681, 72214 }, + { 0x9682, 72218 }, + { 0x9683, 72222 }, + { 0x9684, 72226 }, + { 0x9685, 72230 }, + { 0x9686, 72234 }, + { 0x9687, 72238 }, + { 0x9688, 72242 }, + { 0x9689, 72246 }, + { 0x968A, 72042 }, + { 0x968B, 72046 }, + { 0x968C, 72050 }, + { 0x968D, 72054 }, + { 0x968E, 72058 }, + { 0x968F, 72062 }, + { 0x9690, 72066 }, + { 0x9691, 72070 }, + { 0x9692, 72074 }, + { 0x9693, 72078 }, + { 0x9694, 72082 }, + { 0x9695, 72086 }, + { 0x9696, 72090 }, + { 0x9697, 72094 }, + { 0x9698, 72098 }, + { 0x9699, 72102 }, + { 0x969A, 72106 }, + { 0x969B, 72110 }, + { 0x969C, 72114 }, + { 0x969D, 72118 }, + { 0x969E, 72122 }, + { 0x969F, 72126 }, + { 0x96A0, 72130 }, + { 0x96A1, 72134 }, + { 0x96A2, 72138 }, + { 0x96A3, 72142 }, + { 0x96A4, 71411 }, + { 0x96A5, 71416 }, + { 0x96A8, 70834 }, + { 0x96A9, 70822 }, + { 0x96AA, 70842 }, + { 0x96AB, 70838 }, + { 0x96AC, 70875 }, + { 0x96AD, 70830 }, + { 0x96AE, 70802 }, + { 0x96AF, 70862 }, + { 0x96B0, 70826 }, + { 0x96B1, 70846 }, + { 0x96B2, 70850 }, + { 0x96B3, 70782 }, + { 0x96B4, 70786 }, + { 0x96B5, 70794 }, + { 0x96B6, 70879 }, + { 0x96B7, 70790 }, + { 0x96B8, 70814 }, + { 0x96B9, 70866 }, + { 0x96BA, 70858 }, + { 0x96BB, 70818 }, + { 0x96BC, 70883 }, + { 0x96BD, 70806 }, + { 0x96BE, 70798 }, + { 0x96BF, 70810 }, + { 0x96C0, 70854 }, + { 0x96C1, 69651 }, + { 0x96C2, 69810 }, + { 0x96C3, 69798 }, + { 0x96C4, 69823 }, + { 0x96C5, 69814 }, + { 0x96C6, 69851 }, + { 0x96C7, 69806 }, + { 0x96C8, 69778 }, + { 0x96C9, 69843 }, + { 0x96CA, 69802 }, + { 0x96CB, 69827 }, + { 0x96CC, 69831 }, + { 0x96CD, 69758 }, + { 0x96CE, 69762 }, + { 0x96CF, 69770 }, + { 0x96D0, 69855 }, + { 0x96D1, 69766 }, + { 0x96D2, 69790 }, + { 0x96D3, 69818 }, + { 0x96D4, 69839 }, + { 0x96D5, 69794 }, + { 0x96D6, 69859 }, + { 0x96D7, 69782 }, + { 0x96D8, 69774 }, + { 0x96D9, 69786 }, + { 0x96DA, 69835 }, + { 0x96DB, 71151 }, + { 0x96DC, 70887 }, + { 0x96DD, 69863 }, + { 0x96DE, 69647 }, + { 0x96DF, 69599 }, + { 0x96E0, 69603 }, + { 0x96E1, 69595 }, + { 0x96E2, 71593 }, + { 0x96E3, 71581 }, + { 0x96E4, 71601 }, + { 0x96E5, 71597 }, + { 0x96E6, 71630 }, + { 0x96E7, 71589 }, + { 0x96E8, 71561 }, + { 0x96E9, 71621 }, + { 0x96EA, 71585 }, + { 0x96EB, 71605 }, + { 0x96EC, 71609 }, + { 0x96ED, 71541 }, + { 0x96EE, 71545 }, + { 0x96EF, 71553 }, + { 0x96F0, 71634 }, + { 0x96F1, 71549 }, + { 0x96F2, 71573 }, + { 0x96F3, 71625 }, + { 0x96F4, 71617 }, + { 0x96F5, 71577 }, + { 0x96F6, 71638 }, + { 0x96F7, 71565 }, + { 0x96F8, 71557 }, + { 0x96F9, 71569 }, + { 0x96FA, 71613 }, + { 0x96FB, 71219 }, + { 0x96FC, 71374 }, + { 0x96FD, 71362 }, + { 0x96FE, 71387 }, + { 0x96FF, 71378 }, + { 0x9700, 71421 }, + { 0x9701, 71370 }, + { 0x9702, 71342 }, + { 0x9703, 71407 }, + { 0x9704, 71366 }, + { 0x9705, 71391 }, + { 0x9706, 71395 }, + { 0x9707, 71322 }, + { 0x9708, 71326 }, + { 0x9709, 71334 }, + { 0x970A, 71425 }, + { 0x970B, 71330 }, + { 0x970C, 71354 }, + { 0x970D, 71382 }, + { 0x970E, 71403 }, + { 0x970F, 71358 }, + { 0x9710, 71429 }, + { 0x9711, 71346 }, + { 0x9712, 71338 }, + { 0x9713, 71350 }, + { 0x9714, 71399 }, + { 0x9715, 71646 }, + { 0x9716, 71642 }, + { 0x9717, 71433 }, + { 0x9718, 71215 }, + { 0x9719, 71207 }, + { 0x971A, 71211 }, + { 0x971B, 71203 }, + { 0x971C, 70347 }, + { 0x971D, 70332 }, + { 0x971E, 70357 }, + { 0x971F, 70352 }, + { 0x9720, 70393 }, + { 0x9721, 70342 }, + { 0x9722, 70307 }, + { 0x9723, 70382 }, + { 0x9724, 70337 }, + { 0x9725, 70362 }, + { 0x9726, 70367 }, + { 0x9727, 70282 }, + { 0x9728, 70287 }, + { 0x9729, 70297 }, + { 0x972A, 70398 }, + { 0x972B, 70292 }, + { 0x972C, 70322 }, + { 0x972D, 70387 }, + { 0x972E, 70377 }, + { 0x972F, 70327 }, + { 0x9730, 70403 }, + { 0x9731, 70312 }, + { 0x9732, 70302 }, + { 0x9733, 70317 }, + { 0x9734, 70372 }, + { 0x9735, 69887 }, + { 0x9736, 70086 }, + { 0x9737, 70071 }, + { 0x9738, 70102 }, + { 0x9739, 70091 }, + { 0x973A, 70132 }, + { 0x973B, 70081 }, + { 0x973C, 70046 }, + { 0x973D, 70127 }, + { 0x973E, 70076 }, + { 0x973F, 70107 }, + { 0x9740, 70112 }, + { 0x9741, 70021 }, + { 0x9742, 70026 }, + { 0x9743, 70036 }, + { 0x9744, 70137 }, + { 0x9745, 70031 }, + { 0x9746, 70061 }, + { 0x9747, 70096 }, + { 0x9748, 70122 }, + { 0x9749, 70066 }, + { 0x974A, 70142 }, + { 0x974B, 70051 }, + { 0x974C, 70041 }, + { 0x974D, 70056 }, + { 0x974E, 70117 }, + { 0x974F, 70413 }, + { 0x9750, 70408 }, + { 0x9751, 70147 }, + { 0x9752, 69882 }, + { 0x9753, 69872 }, + { 0x9754, 69877 }, + { 0x9755, 69867 }, + { 0x9756, 73441 }, + { 0x9757, 73426 }, + { 0x9758, 73451 }, + { 0x9759, 73446 }, + { 0x975A, 73487 }, + { 0x975B, 73436 }, + { 0x975C, 73401 }, + { 0x975D, 73476 }, + { 0x975E, 73431 }, + { 0x975F, 73456 }, + { 0x9760, 73461 }, + { 0x9761, 73376 }, + { 0x9762, 73381 }, + { 0x9763, 73391 }, + { 0x9764, 73492 }, + { 0x9765, 73386 }, + { 0x9766, 73416 }, + { 0x9767, 73481 }, + { 0x9768, 73471 }, + { 0x9769, 73421 }, + { 0x976A, 73497 }, + { 0x976B, 73406 }, + { 0x976C, 73396 }, + { 0x976D, 73411 }, + { 0x976E, 73466 }, + { 0x976F, 72320 }, + { 0x9770, 72519 }, + { 0x9771, 72504 }, + { 0x9772, 72535 }, + { 0x9773, 72524 }, + { 0x9774, 72565 }, + { 0x9775, 72514 }, + { 0x9776, 72479 }, + { 0x9777, 72560 }, + { 0x9778, 72509 }, + { 0x9779, 72540 }, + { 0x977A, 72545 }, + { 0x977B, 72454 }, + { 0x977C, 72459 }, + { 0x977D, 72469 }, + { 0x977E, 72570 }, + { 0x977F, 72464 }, + { 0x9780, 72494 }, + { 0x9781, 72529 }, + { 0x9782, 72555 }, + { 0x9783, 72499 }, + { 0x9784, 72575 }, + { 0x9785, 72484 }, + { 0x9786, 72474 }, + { 0x9787, 72489 }, + { 0x9788, 72550 }, + { 0x9789, 73507 }, + { 0x978A, 73502 }, + { 0x978B, 72580 }, + { 0x978C, 72315 }, + { 0x978D, 72255 }, + { 0x978E, 72260 }, + { 0x978F, 72250 }, + { 0x9790, 73161 }, + { 0x9791, 73143 }, + { 0x9792, 73173 }, + { 0x9793, 73167 }, + { 0x9794, 73216 }, + { 0x9795, 73155 }, + { 0x9796, 73113 }, + { 0x9797, 73203 }, + { 0x9798, 73149 }, + { 0x9799, 73179 }, + { 0x979A, 73185 }, + { 0x979B, 73083 }, + { 0x979C, 73089 }, + { 0x979D, 73101 }, + { 0x979E, 73222 }, + { 0x979F, 73095 }, + { 0x97A0, 73131 }, + { 0x97A1, 73209 }, + { 0x97A2, 73197 }, + { 0x97A3, 73137 }, + { 0x97A4, 73228 }, + { 0x97A5, 73119 }, + { 0x97A6, 73107 }, + { 0x97A7, 73125 }, + { 0x97A8, 73191 }, + { 0x97A9, 72609 }, + { 0x97AA, 72848 }, + { 0x97AB, 72830 }, + { 0x97AC, 72867 }, + { 0x97AD, 72854 }, + { 0x97AE, 72903 }, + { 0x97AF, 72842 }, + { 0x97B0, 72800 }, + { 0x97B1, 72897 }, + { 0x97B2, 72836 }, + { 0x97B3, 72873 }, + { 0x97B4, 72879 }, + { 0x97B5, 72770 }, + { 0x97B6, 72776 }, + { 0x97B7, 72788 }, + { 0x97B8, 72909 }, + { 0x97B9, 72782 }, + { 0x97BA, 72818 }, + { 0x97BB, 72860 }, + { 0x97BC, 72891 }, + { 0x97BD, 72824 }, + { 0x97BE, 72915 }, + { 0x97BF, 72806 }, + { 0x97C0, 72794 }, + { 0x97C1, 72812 }, + { 0x97C2, 72885 }, + { 0x97C3, 73240 }, + { 0x97C4, 73234 }, + { 0x97C5, 72921 }, + { 0x97C6, 72603 }, + { 0x97C7, 72591 }, + { 0x97C8, 72597 }, + { 0x97C9, 72585 }, + { 0x97CA, 70871 }, + { 0x97CB, 69847 }, + { 0x97CE, 69631 }, + { 0x97CF, 69607 }, + { 0x97D0, 69615 }, + { 0x97D1, 69643 }, + { 0x97D2, 69623 }, + { 0x97D3, 69619 }, + { 0x97D4, 69611 }, + { 0x97D5, 69639 }, + { 0x97D6, 69635 }, + { 0x97D7, 69627 }, + { 0x97D8, 74044 }, + { 0x97D9, 74020 }, + { 0x97DA, 74028 }, + { 0x97DB, 74056 }, + { 0x97DC, 74036 }, + { 0x97DD, 74032 }, + { 0x97DE, 74024 }, + { 0x97DF, 74052 }, + { 0x97E0, 74048 }, + { 0x97E1, 74040 }, + { 0x97E2, 73536 }, + { 0x97E3, 73512 }, + { 0x97E4, 73520 }, + { 0x97E5, 73548 }, + { 0x97E6, 73528 }, + { 0x97E7, 73524 }, + { 0x97E8, 73516 }, + { 0x97E9, 73544 }, + { 0x97EA, 73540 }, + { 0x97EB, 73532 }, + { 0x97EC, 72295 }, + { 0x97ED, 72265 }, + { 0x97EE, 72275 }, + { 0x97EF, 72310 }, + { 0x97F0, 72285 }, + { 0x97F1, 72280 }, + { 0x97F2, 72270 }, + { 0x97F3, 72305 }, + { 0x97F4, 72300 }, + { 0x97F5, 72290 }, + { 0x97F6, 72026 }, + { 0x97F7, 72002 }, + { 0x97F8, 72010 }, + { 0x97F9, 72038 }, + { 0x97FA, 72018 }, + { 0x97FB, 72014 }, + { 0x97FC, 72006 }, + { 0x97FD, 72034 }, + { 0x97FE, 72030 }, + { 0x97FF, 72022 }, + { 0xA000, 41048 }, + { 0xA001, 41145 }, + { 0xA002, 41100 }, + { 0xA003, 41126 }, + { 0xA004, 41011 }, + { 0xA005, 41119 }, + { 0xA006, 41164 }, + { 0xA007, 41006 }, + { 0xA008, 41040 }, + { 0xA009, 41159 }, + { 0xA00A, 41077 }, + { 0xA00B, 41062 }, + { 0xA00C, 41025 }, + { 0xA00D, 41140 }, + { 0xA00E, 41114 }, + { 0xA00F, 41092 }, + { 0xA010, 40996 }, + { 0xA011, 41030 }, + { 0xA012, 41149 }, + { 0xA013, 41067 }, + { 0xA014, 41052 }, + { 0xA015, 41015 }, + { 0xA016, 41130 }, + { 0xA017, 41104 }, + { 0xA018, 41082 }, + { 0xA019, 41001 }, + { 0xA01A, 41035 }, + { 0xA01B, 41154 }, + { 0xA01C, 41072 }, + { 0xA01D, 41057 }, + { 0xA01E, 41020 }, + { 0xA01F, 41135 }, + { 0xA020, 41109 }, + { 0xA021, 41087 }, + { 0xA022, 41097 }, + { 0xA023, 41174 }, + { 0xA024, 41171 }, + { 0xA025, 41186 }, + { 0xA026, 41177 }, + { 0xA027, 41180 }, + { 0xA028, 41168 }, + { 0xA029, 41183 }, + { 0xA02A, 41123 }, + { 0xA02B, 41045 }, + { 0xA030, 31231 }, + { 0xA031, 31382 }, + { 0xA032, 31385 }, + { 0xA033, 31388 }, + { 0xA034, 31391 }, + { 0xA035, 31394 }, + { 0xA036, 31397 }, + { 0xA037, 31400 }, + { 0xA038, 31403 }, + { 0xA039, 31406 }, + { 0xA03A, 31409 }, + { 0xA03B, 31412 }, + { 0xA03C, 31415 }, + { 0xA03D, 31418 }, + { 0xA03E, 31421 }, + { 0xA03F, 31424 }, + { 0xA040, 31427 }, + { 0xA041, 31430 }, + { 0xA042, 31433 }, + { 0xA043, 31436 }, + { 0xA044, 31439 }, + { 0xA045, 31442 }, + { 0xA046, 31445 }, + { 0xA047, 31448 }, + { 0xA048, 31451 }, + { 0xA049, 31454 }, + { 0xA04A, 31457 }, + { 0xA04B, 31460 }, + { 0xA04C, 31463 }, + { 0xA04D, 31466 }, + { 0xA04E, 31469 }, + { 0xA04F, 31472 }, + { 0xA050, 31475 }, + { 0xA051, 31478 }, + { 0xA052, 31481 }, + { 0xA053, 31484 }, + { 0xA054, 31487 }, + { 0xA055, 31490 }, + { 0xA056, 31493 }, + { 0xA057, 31496 }, + { 0xA058, 31499 }, + { 0xA059, 31502 }, + { 0xA05A, 31505 }, + { 0xA05B, 31508 }, + { 0xA05C, 31511 }, + { 0xA05D, 31514 }, + { 0xA05E, 31517 }, + { 0xA05F, 31520 }, + { 0xA060, 31523 }, + { 0xA061, 31526 }, + { 0xA062, 31227 }, + { 0xA063, 31235 }, + { 0xA064, 31238 }, + { 0xA065, 31241 }, + { 0xA066, 31244 }, + { 0xA067, 31247 }, + { 0xA068, 31250 }, + { 0xA069, 31253 }, + { 0xA06A, 31256 }, + { 0xA06B, 31259 }, + { 0xA06C, 31262 }, + { 0xA06D, 31265 }, + { 0xA06E, 31268 }, + { 0xA06F, 31271 }, + { 0xA070, 31274 }, + { 0xA071, 31277 }, + { 0xA072, 31280 }, + { 0xA073, 31283 }, + { 0xA074, 31286 }, + { 0xA075, 31289 }, + { 0xA076, 31292 }, + { 0xA077, 31295 }, + { 0xA078, 31298 }, + { 0xA079, 31301 }, + { 0xA07A, 31304 }, + { 0xA07B, 31307 }, + { 0xA07C, 31310 }, + { 0xA07D, 31313 }, + { 0xA07E, 31316 }, + { 0xA07F, 31319 }, + { 0xA080, 31322 }, + { 0xA081, 31325 }, + { 0xA082, 31328 }, + { 0xA083, 31331 }, + { 0xA084, 31334 }, + { 0xA085, 31337 }, + { 0xA086, 31340 }, + { 0xA087, 31343 }, + { 0xA088, 31346 }, + { 0xA089, 31349 }, + { 0xA08A, 31352 }, + { 0xA08B, 31355 }, + { 0xA08C, 31358 }, + { 0xA08D, 31361 }, + { 0xA08E, 31364 }, + { 0xA08F, 31367 }, + { 0xA090, 31370 }, + { 0xA091, 31373 }, + { 0xA092, 31376 }, + { 0xA093, 31379 }, + { 0xC001, 53726 }, + { 0xC020, 7517 }, + { 0xC021, 7564 }, + { 0xC022, 7551 }, + { 0xC023, 7527 }, + { 0xC024, 7521 }, + { 0xC025, 7530 }, + { 0xC026, 7546 }, + { 0xC027, 7556 }, + { 0xC028, 7203 }, + { 0xC029, 7514 }, + { 0xC02A, 7538 }, + { 0xC02B, 7206 }, + { 0xC02C, 7211 }, + { 0xC02D, 7570 }, + { 0xC02E, 7192 }, + { 0xC02F, 7536 }, + { 0xC030, 7231 }, + { 0xC031, 7213 }, + { 0xC032, 7219 }, + { 0xC033, 7240 }, + { 0xC034, 7225 }, + { 0xC035, 7222 }, + { 0xC036, 7216 }, + { 0xC037, 7237 }, + { 0xC038, 7234 }, + { 0xC039, 7228 }, + { 0xC03A, 7209 }, + { 0xC03B, 7554 }, + { 0xC03C, 7548 }, + { 0xC03D, 7524 }, + { 0xC03E, 7567 }, + { 0xC03F, 7540 }, + { 0xC040, 7561 }, + { 0xC041, 7376 }, + { 0xC042, 7381 }, + { 0xC043, 7386 }, + { 0xC044, 7391 }, + { 0xC045, 7396 }, + { 0xC046, 7401 }, + { 0xC047, 7406 }, + { 0xC048, 7411 }, + { 0xC049, 7416 }, + { 0xC04A, 7421 }, + { 0xC04B, 7426 }, + { 0xC04C, 7431 }, + { 0xC04D, 7436 }, + { 0xC04E, 7441 }, + { 0xC04F, 7446 }, + { 0xC050, 7451 }, + { 0xC051, 7456 }, + { 0xC052, 7461 }, + { 0xC053, 7466 }, + { 0xC054, 7471 }, + { 0xC055, 7476 }, + { 0xC056, 7481 }, + { 0xC057, 7486 }, + { 0xC058, 7491 }, + { 0xC059, 7496 }, + { 0xC05A, 7501 }, + { 0xC05B, 7199 }, + { 0xC05C, 7533 }, + { 0xC05D, 7510 }, + { 0xC05E, 7558 }, + { 0xC05F, 7189 }, + { 0xC060, 7243 }, + { 0xC061, 7246 }, + { 0xC062, 7251 }, + { 0xC063, 7256 }, + { 0xC064, 7261 }, + { 0xC065, 7266 }, + { 0xC066, 7271 }, + { 0xC067, 7276 }, + { 0xC068, 7281 }, + { 0xC069, 7286 }, + { 0xC06A, 7291 }, + { 0xC06B, 7296 }, + { 0xC06C, 7301 }, + { 0xC06D, 7306 }, + { 0xC06E, 7311 }, + { 0xC06F, 7316 }, + { 0xC070, 7321 }, + { 0xC071, 7326 }, + { 0xC072, 7331 }, + { 0xC073, 7336 }, + { 0xC074, 7341 }, + { 0xC075, 7346 }, + { 0xC076, 7351 }, + { 0xC077, 7356 }, + { 0xC078, 7361 }, + { 0xC079, 7366 }, + { 0xC07A, 7371 }, + { 0xC07B, 7195 }, + { 0xC07C, 7543 }, + { 0xC07D, 7506 }, + { 0xC07E, 7519 }, + { 0xC07F, 30315 }, + { 0xC100, 66346 }, + { 0xC101, 66348 }, + { 0xC102, 66350 }, + { 0xC103, 66352 }, + { 0xC104, 66354 }, + { 0xC105, 66356 }, + { 0xC106, 66358 }, + { 0xC107, 66360 }, + { 0xC108, 66362 }, + { 0xC109, 66364 }, + { 0xC10A, 66366 }, + { 0xC10B, 66368 }, + { 0xC10C, 66370 }, + { 0xC10D, 66372 }, + { 0xC10E, 66374 }, + { 0xC10F, 66376 }, + { 0xC110, 66378 }, + { 0xC111, 66380 }, + { 0xC112, 66382 }, + { 0xC113, 66384 }, + { 0xC114, 66386 }, + { 0xC115, 66388 }, + { 0xC116, 66390 }, + { 0xC117, 66392 }, + { 0xC118, 66394 }, + { 0xC119, 66396 }, + { 0xC11A, 66398 }, + { 0xC11B, 66400 }, + { 0xC11C, 66402 }, + { 0xC11D, 66404 }, + { 0xC11E, 66406 }, + { 0xC11F, 66408 }, + { 0xC120, 66410 }, + { 0xC121, 66412 }, + { 0xC122, 66414 }, + { 0xC123, 66416 }, + { 0xC124, 66418 }, + { 0xC125, 66420 }, + { 0xC126, 66422 }, + { 0xC127, 66424 }, + { 0xC128, 66426 }, + { 0xC129, 66428 }, + { 0xC12A, 66430 }, + { 0xC12B, 66432 }, + { 0xC12C, 66434 }, + { 0xC12D, 66436 }, + { 0xC12E, 66438 }, + { 0xC12F, 66440 }, + { 0xC130, 66442 }, + { 0xC131, 66444 }, + { 0xC132, 66446 }, + { 0xC133, 66448 }, + { 0xC134, 66450 }, + { 0xC135, 66452 }, + { 0xC136, 66454 }, + { 0xC137, 66456 }, + { 0xC138, 66458 }, + { 0xC139, 66460 }, + { 0xC13A, 66462 }, + { 0xC13B, 66464 }, + { 0xC13C, 66466 }, + { 0xC13D, 66468 }, + { 0xC13E, 66470 }, + { 0xC13F, 66472 }, + { 0xC140, 66474 }, + { 0xC141, 66476 }, + { 0xC142, 66478 }, + { 0xC143, 66480 }, + { 0xC144, 66482 }, + { 0xC145, 66484 }, + { 0xC146, 66486 }, + { 0xC147, 66488 }, + { 0xC148, 66490 }, + { 0xC149, 66492 }, + { 0xC14A, 66494 }, + { 0xC14B, 66496 }, + { 0xC14C, 66498 }, + { 0xC14D, 66500 }, + { 0xC14E, 66502 }, + { 0xC14F, 66504 }, + { 0xC150, 66506 }, + { 0xC151, 66508 }, + { 0xC152, 66510 }, + { 0xC153, 66512 }, + { 0xC154, 66514 }, + { 0xC155, 66516 }, + { 0xC156, 66518 }, + { 0xC157, 66520 }, + { 0xC158, 66522 }, + { 0xC159, 66524 }, + { 0xC15A, 66526 }, + { 0xC15B, 66528 }, + { 0xC15C, 66530 }, + { 0xC15D, 66532 }, + { 0xC15E, 66534 }, + { 0xC15F, 66536 }, + { 0xC160, 66538 }, + { 0xC161, 66540 }, + { 0xC162, 66542 }, + { 0xC163, 66544 }, + { 0xC164, 66546 }, + { 0xC165, 66548 }, + { 0xC166, 66550 }, + { 0xC167, 66552 }, + { 0xC168, 66554 }, + { 0xC169, 66556 }, + { 0xC16A, 66558 }, + { 0xC16B, 66560 }, + { 0xC16C, 66562 }, + { 0xC16D, 66564 }, + { 0xC16E, 66566 }, + { 0xC16F, 66568 }, + { 0xC170, 66570 }, + { 0xC171, 66572 }, + { 0xC172, 66574 }, + { 0xC173, 66576 }, + { 0xC174, 66578 }, + { 0xC175, 66580 }, + { 0xC176, 66582 }, + { 0xC177, 66584 }, + { 0xC178, 66586 }, + { 0xC179, 66588 }, + { 0xC17A, 66590 }, + { 0xC17B, 66592 }, + { 0xC17C, 66594 }, + { 0xC17D, 66596 }, + { 0xC17E, 66598 }, + { 0xC17F, 66600 }, + { 0xC180, 66602 }, + { 0xC181, 66604 }, + { 0xC182, 66606 }, + { 0xC183, 66608 }, + { 0xC184, 66610 }, + { 0xC185, 66612 }, + { 0xC186, 66614 }, + { 0xC187, 66616 }, + { 0xC188, 66618 }, + { 0xC189, 66620 }, + { 0xC18A, 66622 }, + { 0xC18B, 66624 }, + { 0xC18C, 66626 }, + { 0xC18D, 66628 }, + { 0xC18E, 66630 }, + { 0xC18F, 66632 }, + { 0xC190, 66634 }, + { 0xC191, 66636 }, + { 0xC192, 66638 }, + { 0xC193, 66640 }, + { 0xC194, 66642 }, + { 0xC195, 66644 }, + { 0xC196, 66646 }, + { 0xC197, 66648 }, + { 0xC198, 66650 }, + { 0xC199, 66652 }, + { 0xC19A, 66654 }, + { 0xC19B, 66656 }, + { 0xC19C, 66658 }, + { 0xC19D, 66660 }, + { 0xC19E, 66662 }, + { 0xC19F, 66664 }, + { 0xC1A0, 66666 }, + { 0xC1A1, 66668 }, + { 0xC1A2, 66670 }, + { 0xC1A3, 66672 }, + { 0xC1A4, 66674 }, + { 0xC1A5, 66676 }, + { 0xC1A6, 66678 }, + { 0xC1A7, 66680 }, + { 0xC1A8, 66682 }, + { 0xC1A9, 66684 }, + { 0xC1AA, 66686 }, + { 0xC1AB, 66688 }, + { 0xC1AC, 66690 }, + { 0xC1AD, 66692 }, + { 0xC1AE, 66694 }, + { 0xC1AF, 66696 }, + { 0xC1B0, 66698 }, + { 0xC1B1, 66700 }, + { 0xC1B2, 66702 }, + { 0xC1B3, 66704 }, + { 0xC1B4, 66706 }, + { 0xC1B5, 66708 }, + { 0xC1B6, 66710 }, + { 0xC1B7, 66712 }, + { 0xC1B8, 66714 }, + { 0xC1B9, 66716 }, + { 0xC1BA, 66718 }, + { 0xC1BB, 66720 }, + { 0xC1BC, 66722 }, + { 0xC1BD, 66724 }, + { 0xC1BE, 66726 }, + { 0xC1BF, 66728 }, + { 0xC1C0, 66730 }, + { 0xC1C1, 66732 }, + { 0xC1C2, 66734 }, + { 0xC1C3, 66736 }, + { 0xC1C4, 66738 }, + { 0xC1C5, 66740 }, + { 0xC1C6, 66742 }, + { 0xC1C7, 66744 }, + { 0xC1C8, 66746 }, + { 0xC1C9, 66748 }, + { 0xC1CA, 66750 }, + { 0xC1CB, 66752 }, + { 0xC1CC, 66754 }, + { 0xC1CD, 66756 }, + { 0xC1CE, 66758 }, + { 0xC1CF, 66760 }, + { 0xC1D0, 66762 }, + { 0xC1D1, 66764 }, + { 0xC1D2, 66766 }, + { 0xC1D3, 66768 }, + { 0xC1D4, 66770 }, + { 0xC1D5, 66772 }, + { 0xC1D6, 66774 }, + { 0xC1D7, 66776 }, + { 0xC1D8, 66778 }, + { 0xC1D9, 66780 }, + { 0xC1DA, 66782 }, + { 0xC1DB, 66784 }, + { 0xC1DC, 66786 }, + { 0xC1DD, 66788 }, + { 0xC1DE, 66790 }, + { 0xC1DF, 66792 }, + { 0xC1E0, 66794 }, + { 0xC1E1, 66796 }, + { 0xC1E2, 66798 }, + { 0xC1E3, 66800 }, + { 0xC1E4, 66802 }, + { 0xC1E5, 66804 }, + { 0xC1E6, 66806 }, + { 0xC1E7, 66808 }, + { 0xC1E8, 66810 }, + { 0xC1E9, 66812 }, + { 0xC1EA, 66814 }, + { 0xC1EB, 66816 }, + { 0xC1EC, 66818 }, + { 0xC1ED, 66820 }, + { 0xC1EE, 66822 }, + { 0xC1EF, 66824 }, +}; +#define UNICODE_CHARNAME_MAX_LENGTH 83 +#define UNICODE_CHARNAME_MAX_WORDS 13 diff --git a/gettext-tools/gnulib-lib/unistd--.h b/gettext-tools/gnulib-lib/unistd--.h new file mode 100644 index 0000000..9d0e54d --- /dev/null +++ b/gettext-tools/gnulib-lib/unistd--.h @@ -0,0 +1,32 @@ +/* Like unistd.h, but redefine some names to avoid glitches. + + Copyright (C) 2005, 2009-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Written by Paul Eggert. */ + +#include +#include "unistd-safer.h" + +#undef dup +#define dup dup_safer + +#undef pipe +#define pipe pipe_safer + +#if GNULIB_PIPE2_SAFER +# undef pipe2 +# define pipe2 pipe2_safer +#endif diff --git a/gettext-tools/gnulib-lib/unistd-safer.h b/gettext-tools/gnulib-lib/unistd-safer.h new file mode 100644 index 0000000..4b0ca6a --- /dev/null +++ b/gettext-tools/gnulib-lib/unistd-safer.h @@ -0,0 +1,31 @@ +/* Invoke unistd-like functions, but avoid some glitches. + + Copyright (C) 2001, 2003, 2005, 2009-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Written by Paul Eggert and Eric Blake. */ + +int dup_safer (int); +int fd_safer (int); +int pipe_safer (int[2]); + +#if GNULIB_FD_SAFER_FLAG +int dup_safer_flag (int, int); +int fd_safer_flag (int, int); +#endif + +#if GNULIB_PIPE2_SAFER +int pipe2_safer (int[2], int); +#endif diff --git a/gettext-tools/gnulib-lib/unistd.c b/gettext-tools/gnulib-lib/unistd.c new file mode 100644 index 0000000..6c6a8e2 --- /dev/null +++ b/gettext-tools/gnulib-lib/unistd.c @@ -0,0 +1,3 @@ +#include +#define _GL_UNISTD_INLINE _GL_EXTERN_INLINE +#include "unistd.h" diff --git a/gettext-tools/gnulib-lib/unistd.in.h b/gettext-tools/gnulib-lib/unistd.in.h new file mode 100644 index 0000000..13babfb --- /dev/null +++ b/gettext-tools/gnulib-lib/unistd.in.h @@ -0,0 +1,1590 @@ +/* Substitute for and wrapper around . + Copyright (C) 2003-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . */ + +#ifndef _@GUARD_PREFIX@_UNISTD_H + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +#ifdef _GL_INCLUDING_UNISTD_H +/* Special invocation convention: + - On Mac OS X 10.3.9 we have a sequence of nested includes + -> -> -> + In this situation, the functions are not yet declared, therefore we cannot + provide the C++ aliases. */ + +#@INCLUDE_NEXT@ @NEXT_UNISTD_H@ + +#else +/* Normal invocation convention. */ + +/* The include_next requires a split double-inclusion guard. */ +#if @HAVE_UNISTD_H@ +# define _GL_INCLUDING_UNISTD_H +# @INCLUDE_NEXT@ @NEXT_UNISTD_H@ +# undef _GL_INCLUDING_UNISTD_H +#endif + +/* Get all possible declarations of gethostname(). */ +#if @GNULIB_GETHOSTNAME@ && @UNISTD_H_HAVE_WINSOCK2_H@ \ + && !defined _GL_INCLUDING_WINSOCK2_H +# define _GL_INCLUDING_WINSOCK2_H +# include +# undef _GL_INCLUDING_WINSOCK2_H +#endif + +#if !defined _@GUARD_PREFIX@_UNISTD_H && !defined _GL_INCLUDING_WINSOCK2_H +#define _@GUARD_PREFIX@_UNISTD_H + +/* NetBSD 5.0 mis-defines NULL. Also get size_t. */ +#include + +/* mingw doesn't define the SEEK_* or *_FILENO macros in . */ +/* Cygwin 1.7.1 declares symlinkat in , not in . */ +/* But avoid namespace pollution on glibc systems. */ +#if (!(defined SEEK_CUR && defined SEEK_END && defined SEEK_SET) \ + || ((@GNULIB_SYMLINKAT@ || defined GNULIB_POSIXCHECK) \ + && defined __CYGWIN__)) \ + && ! defined __GLIBC__ +# include +#endif + +/* Cygwin 1.7.1 declares unlinkat in , not in . */ +/* But avoid namespace pollution on glibc systems. */ +#if (@GNULIB_UNLINKAT@ || defined GNULIB_POSIXCHECK) && defined __CYGWIN__ \ + && ! defined __GLIBC__ +# include +#endif + +/* mingw fails to declare _exit in . */ +/* mingw, MSVC, BeOS, Haiku declare environ in , not in + . */ +/* Solaris declares getcwd not only in but also in . */ +/* OSF Tru64 Unix cannot see gnulib rpl_strtod when system is + included here. */ +/* But avoid namespace pollution on glibc systems. */ +#if !defined __GLIBC__ && !defined __osf__ +# define __need_system_stdlib_h +# include +# undef __need_system_stdlib_h +#endif + +/* Native Windows platforms declare chdir, getcwd, rmdir in + and/or , not in . + They also declare access(), chmod(), close(), dup(), dup2(), isatty(), + lseek(), read(), unlink(), write() in . */ +#if ((@GNULIB_CHDIR@ || @GNULIB_GETCWD@ || @GNULIB_RMDIR@ \ + || defined GNULIB_POSIXCHECK) \ + && ((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__)) +# include /* mingw32, mingw64 */ +# include /* mingw64, MSVC 9 */ +#elif (@GNULIB_CLOSE@ || @GNULIB_DUP@ || @GNULIB_DUP2@ || @GNULIB_ISATTY@ \ + || @GNULIB_LSEEK@ || @GNULIB_READ@ || @GNULIB_UNLINK@ || @GNULIB_WRITE@ \ + || defined GNULIB_POSIXCHECK) \ + && ((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__) +# include +#endif + +/* AIX and OSF/1 5.1 declare getdomainname in , not in . + NonStop Kernel declares gethostname in , not in . */ +/* But avoid namespace pollution on glibc systems. */ +#if ((@GNULIB_GETDOMAINNAME@ && (defined _AIX || defined __osf__)) \ + || (@GNULIB_GETHOSTNAME@ && defined __TANDEM)) \ + && !defined __GLIBC__ +# include +#endif + +/* MSVC defines off_t in . + May also define off_t to a 64-bit type on native Windows. */ +#if !@HAVE_UNISTD_H@ || @WINDOWS_64_BIT_OFF_T@ +/* Get off_t. */ +# include +#endif + +#if (@GNULIB_READ@ || @GNULIB_WRITE@ \ + || @GNULIB_READLINK@ || @GNULIB_READLINKAT@ \ + || @GNULIB_PREAD@ || @GNULIB_PWRITE@ || defined GNULIB_POSIXCHECK) +/* Get ssize_t. */ +# include +#endif + +/* Get getopt(), optarg, optind, opterr, optopt. + But avoid namespace pollution on glibc systems. */ +/* Also, don't include inside libgettextpo, because we use + the getopt module only in gettext-tools/gnulib-lib/, not in + gettext-tools/libgettextpo/, but there is only a single + GNULIB_UNISTD_H_GETOPT variable for both. */ +#if @GNULIB_UNISTD_H_GETOPT@ && !defined GTPO_CONFIG_H && !defined __GLIBC__ && !defined _GL_SYSTEM_GETOPT +# define __need_getopt +# include +#endif + +#ifndef _GL_INLINE_HEADER_BEGIN + #error "Please include config.h first." +#endif +_GL_INLINE_HEADER_BEGIN +#ifndef _GL_UNISTD_INLINE +# define _GL_UNISTD_INLINE _GL_INLINE +#endif + +/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ + +/* The definition of _GL_ARG_NONNULL is copied here. */ + +/* The definition of _GL_WARN_ON_USE is copied here. */ + + +/* Hide some function declarations from . */ + +#if @GNULIB_GETHOSTNAME@ && @UNISTD_H_HAVE_WINSOCK2_H@ +# if !defined _@GUARD_PREFIX@_SYS_SOCKET_H +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef socket +# define socket socket_used_without_including_sys_socket_h +# undef connect +# define connect connect_used_without_including_sys_socket_h +# undef accept +# define accept accept_used_without_including_sys_socket_h +# undef bind +# define bind bind_used_without_including_sys_socket_h +# undef getpeername +# define getpeername getpeername_used_without_including_sys_socket_h +# undef getsockname +# define getsockname getsockname_used_without_including_sys_socket_h +# undef getsockopt +# define getsockopt getsockopt_used_without_including_sys_socket_h +# undef listen +# define listen listen_used_without_including_sys_socket_h +# undef recv +# define recv recv_used_without_including_sys_socket_h +# undef send +# define send send_used_without_including_sys_socket_h +# undef recvfrom +# define recvfrom recvfrom_used_without_including_sys_socket_h +# undef sendto +# define sendto sendto_used_without_including_sys_socket_h +# undef setsockopt +# define setsockopt setsockopt_used_without_including_sys_socket_h +# undef shutdown +# define shutdown shutdown_used_without_including_sys_socket_h +# else + _GL_WARN_ON_USE (socket, + "socket() used without including "); + _GL_WARN_ON_USE (connect, + "connect() used without including "); + _GL_WARN_ON_USE (accept, + "accept() used without including "); + _GL_WARN_ON_USE (bind, + "bind() used without including "); + _GL_WARN_ON_USE (getpeername, + "getpeername() used without including "); + _GL_WARN_ON_USE (getsockname, + "getsockname() used without including "); + _GL_WARN_ON_USE (getsockopt, + "getsockopt() used without including "); + _GL_WARN_ON_USE (listen, + "listen() used without including "); + _GL_WARN_ON_USE (recv, + "recv() used without including "); + _GL_WARN_ON_USE (send, + "send() used without including "); + _GL_WARN_ON_USE (recvfrom, + "recvfrom() used without including "); + _GL_WARN_ON_USE (sendto, + "sendto() used without including "); + _GL_WARN_ON_USE (setsockopt, + "setsockopt() used without including "); + _GL_WARN_ON_USE (shutdown, + "shutdown() used without including "); +# endif +# endif +# if !defined _@GUARD_PREFIX@_SYS_SELECT_H +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef select +# define select select_used_without_including_sys_select_h +# else + _GL_WARN_ON_USE (select, + "select() used without including "); +# endif +# endif +#endif + + +/* OS/2 EMX lacks these macros. */ +#ifndef STDIN_FILENO +# define STDIN_FILENO 0 +#endif +#ifndef STDOUT_FILENO +# define STDOUT_FILENO 1 +#endif +#ifndef STDERR_FILENO +# define STDERR_FILENO 2 +#endif + +/* Ensure *_OK macros exist. */ +#ifndef F_OK +# define F_OK 0 +# define X_OK 1 +# define W_OK 2 +# define R_OK 4 +#endif + + +/* Declare overridden functions. */ + + +#if defined GNULIB_POSIXCHECK +/* The access() function is a security risk. */ +_GL_WARN_ON_USE (access, "the access function is a security risk - " + "use the gnulib module faccessat instead"); +#endif + + +#if @GNULIB_CHDIR@ +_GL_CXXALIAS_SYS (chdir, int, (const char *file) _GL_ARG_NONNULL ((1))); +_GL_CXXALIASWARN (chdir); +#elif defined GNULIB_POSIXCHECK +# undef chdir +# if HAVE_RAW_DECL_CHDIR +_GL_WARN_ON_USE (chown, "chdir is not always in - " + "use gnulib module chdir for portability"); +# endif +#endif + + +#if @GNULIB_CHOWN@ +/* Change the owner of FILE to UID (if UID is not -1) and the group of FILE + to GID (if GID is not -1). Follow symbolic links. + Return 0 if successful, otherwise -1 and errno set. + See the POSIX:2008 specification + . */ +# if @REPLACE_DUP2@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define dup2 rpl_dup2 +# endif +_GL_FUNCDECL_RPL (dup2, int, (int oldfd, int newfd)); +_GL_CXXALIAS_RPL (dup2, int, (int oldfd, int newfd)); +# else +# if !@HAVE_DUP2@ +_GL_FUNCDECL_SYS (dup2, int, (int oldfd, int newfd)); +# endif +_GL_CXXALIAS_SYS (dup2, int, (int oldfd, int newfd)); +# endif +_GL_CXXALIASWARN (dup2); +#elif defined GNULIB_POSIXCHECK +# undef dup2 +# if HAVE_RAW_DECL_DUP2 +_GL_WARN_ON_USE (dup2, "dup2 is unportable - " + "use gnulib module dup2 for portability"); +# endif +#endif + + +#if @GNULIB_DUP3@ +/* Copy the file descriptor OLDFD into file descriptor NEWFD, with the + specified flags. + The flags are a bitmask, possibly including O_CLOEXEC (defined in ) + and O_TEXT, O_BINARY (defined in "binary-io.h"). + Close NEWFD first if it is open. + Return newfd if successful, otherwise -1 and errno set. + See the Linux man page at + . */ +# if @HAVE_DUP3@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define dup3 rpl_dup3 +# endif +_GL_FUNCDECL_RPL (dup3, int, (int oldfd, int newfd, int flags)); +_GL_CXXALIAS_RPL (dup3, int, (int oldfd, int newfd, int flags)); +# else +_GL_FUNCDECL_SYS (dup3, int, (int oldfd, int newfd, int flags)); +_GL_CXXALIAS_SYS (dup3, int, (int oldfd, int newfd, int flags)); +# endif +_GL_CXXALIASWARN (dup3); +#elif defined GNULIB_POSIXCHECK +# undef dup3 +# if HAVE_RAW_DECL_DUP3 +_GL_WARN_ON_USE (dup3, "dup3 is unportable - " + "use gnulib module dup3 for portability"); +# endif +#endif + + +#if @GNULIB_ENVIRON@ +# if !@HAVE_DECL_ENVIRON@ +/* Set of environment variables and values. An array of strings of the form + "VARIABLE=VALUE", terminated with a NULL. */ +# if defined __APPLE__ && defined __MACH__ +# include +# if !TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR +# define _GL_USE_CRT_EXTERNS +# endif +# endif +# ifdef _GL_USE_CRT_EXTERNS +# include +# define environ (*_NSGetEnviron ()) +# else +# ifdef __cplusplus +extern "C" { +# endif +extern char **environ; +# ifdef __cplusplus +} +# endif +# endif +# endif +#elif defined GNULIB_POSIXCHECK +# if HAVE_RAW_DECL_ENVIRON +_GL_UNISTD_INLINE char *** +rpl_environ (void) +{ + return &environ; +} +_GL_WARN_ON_USE (rpl_environ, "environ is unportable - " + "use gnulib module environ for portability"); +# undef environ +# define environ (*rpl_environ ()) +# endif +#endif + + +#if @GNULIB_EUIDACCESS@ +/* Like access(), except that it uses the effective user id and group id of + the current process. */ +# if !@HAVE_EUIDACCESS@ +_GL_FUNCDECL_SYS (euidaccess, int, (const char *filename, int mode) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (euidaccess, int, (const char *filename, int mode)); +_GL_CXXALIASWARN (euidaccess); +# if defined GNULIB_POSIXCHECK +/* Like access(), this function is a security risk. */ +_GL_WARN_ON_USE (euidaccess, "the euidaccess function is a security risk - " + "use the gnulib module faccessat instead"); +# endif +#elif defined GNULIB_POSIXCHECK +# undef euidaccess +# if HAVE_RAW_DECL_EUIDACCESS +_GL_WARN_ON_USE (euidaccess, "euidaccess is unportable - " + "use gnulib module euidaccess for portability"); +# endif +#endif + + +#if @GNULIB_FACCESSAT@ +# if !@HAVE_FACCESSAT@ +_GL_FUNCDECL_SYS (faccessat, int, + (int fd, char const *file, int mode, int flag) + _GL_ARG_NONNULL ((2))); +# endif +_GL_CXXALIAS_SYS (faccessat, int, + (int fd, char const *file, int mode, int flag)); +_GL_CXXALIASWARN (faccessat); +#elif defined GNULIB_POSIXCHECK +# undef faccessat +# if HAVE_RAW_DECL_FACCESSAT +_GL_WARN_ON_USE (faccessat, "faccessat is not portable - " + "use gnulib module faccessat for portability"); +# endif +#endif + + +#if @GNULIB_FCHDIR@ +/* Change the process' current working directory to the directory on which + the given file descriptor is open. + Return 0 if successful, otherwise -1 and errno set. + See the POSIX:2008 specification + . */ +# if ! @HAVE_FCHDIR@ +_GL_FUNCDECL_SYS (fchdir, int, (int /*fd*/)); + +/* Gnulib internal hooks needed to maintain the fchdir metadata. */ +_GL_EXTERN_C int _gl_register_fd (int fd, const char *filename) + _GL_ARG_NONNULL ((2)); +_GL_EXTERN_C void _gl_unregister_fd (int fd); +_GL_EXTERN_C int _gl_register_dup (int oldfd, int newfd); +_GL_EXTERN_C const char *_gl_directory_name (int fd); + +# else +# if !@HAVE_DECL_FCHDIR@ +_GL_FUNCDECL_SYS (fchdir, int, (int /*fd*/)); +# endif +# endif +_GL_CXXALIAS_SYS (fchdir, int, (int /*fd*/)); +_GL_CXXALIASWARN (fchdir); +#elif defined GNULIB_POSIXCHECK +# undef fchdir +# if HAVE_RAW_DECL_FCHDIR +_GL_WARN_ON_USE (fchdir, "fchdir is unportable - " + "use gnulib module fchdir for portability"); +# endif +#endif + + +#if @GNULIB_FCHOWNAT@ +# if @REPLACE_FCHOWNAT@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef fchownat +# define fchownat rpl_fchownat +# endif +_GL_FUNCDECL_RPL (fchownat, int, (int fd, char const *file, + uid_t owner, gid_t group, int flag) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (fchownat, int, (int fd, char const *file, + uid_t owner, gid_t group, int flag)); +# else +# if !@HAVE_FCHOWNAT@ +_GL_FUNCDECL_SYS (fchownat, int, (int fd, char const *file, + uid_t owner, gid_t group, int flag) + _GL_ARG_NONNULL ((2))); +# endif +_GL_CXXALIAS_SYS (fchownat, int, (int fd, char const *file, + uid_t owner, gid_t group, int flag)); +# endif +_GL_CXXALIASWARN (fchownat); +#elif defined GNULIB_POSIXCHECK +# undef fchownat +# if HAVE_RAW_DECL_FCHOWNAT +_GL_WARN_ON_USE (fchownat, "fchownat is not portable - " + "use gnulib module openat for portability"); +# endif +#endif + + +#if @GNULIB_FDATASYNC@ +/* Synchronize changes to a file. + Return 0 if successful, otherwise -1 and errno set. + See POSIX:2008 specification + . */ +# if !@HAVE_FDATASYNC@ || !@HAVE_DECL_FDATASYNC@ +_GL_FUNCDECL_SYS (fdatasync, int, (int fd)); +# endif +_GL_CXXALIAS_SYS (fdatasync, int, (int fd)); +_GL_CXXALIASWARN (fdatasync); +#elif defined GNULIB_POSIXCHECK +# undef fdatasync +# if HAVE_RAW_DECL_FDATASYNC +_GL_WARN_ON_USE (fdatasync, "fdatasync is unportable - " + "use gnulib module fdatasync for portability"); +# endif +#endif + + +#if @GNULIB_FSYNC@ +/* Synchronize changes, including metadata, to a file. + Return 0 if successful, otherwise -1 and errno set. + See POSIX:2008 specification + . */ +# if !@HAVE_FSYNC@ +_GL_FUNCDECL_SYS (fsync, int, (int fd)); +# endif +_GL_CXXALIAS_SYS (fsync, int, (int fd)); +_GL_CXXALIASWARN (fsync); +#elif defined GNULIB_POSIXCHECK +# undef fsync +# if HAVE_RAW_DECL_FSYNC +_GL_WARN_ON_USE (fsync, "fsync is unportable - " + "use gnulib module fsync for portability"); +# endif +#endif + + +#if @GNULIB_FTRUNCATE@ +/* Change the size of the file to which FD is opened to become equal to LENGTH. + Return 0 if successful, otherwise -1 and errno set. + See the POSIX:2008 specification + . */ +# if @REPLACE_FTRUNCATE@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef ftruncate +# define ftruncate rpl_ftruncate +# endif +_GL_FUNCDECL_RPL (ftruncate, int, (int fd, off_t length)); +_GL_CXXALIAS_RPL (ftruncate, int, (int fd, off_t length)); +# else +# if !@HAVE_FTRUNCATE@ +_GL_FUNCDECL_SYS (ftruncate, int, (int fd, off_t length)); +# endif +_GL_CXXALIAS_SYS (ftruncate, int, (int fd, off_t length)); +# endif +_GL_CXXALIASWARN (ftruncate); +#elif defined GNULIB_POSIXCHECK +# undef ftruncate +# if HAVE_RAW_DECL_FTRUNCATE +_GL_WARN_ON_USE (ftruncate, "ftruncate is unportable - " + "use gnulib module ftruncate for portability"); +# endif +#endif + + +#if @GNULIB_GETCWD@ +/* Get the name of the current working directory, and put it in SIZE bytes + of BUF. + Return BUF if successful, or NULL if the directory couldn't be determined + or SIZE was too small. + See the POSIX:2008 specification + . + Additionally, the gnulib module 'getcwd' guarantees the following GNU + extension: If BUF is NULL, an array is allocated with 'malloc'; the array + is SIZE bytes long, unless SIZE == 0, in which case it is as big as + necessary. */ +# if @REPLACE_GETCWD@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define getcwd rpl_getcwd +# endif +_GL_FUNCDECL_RPL (getcwd, char *, (char *buf, size_t size)); +_GL_CXXALIAS_RPL (getcwd, char *, (char *buf, size_t size)); +# else +/* Need to cast, because on mingw, the second parameter is + int size. */ +_GL_CXXALIAS_SYS_CAST (getcwd, char *, (char *buf, size_t size)); +# endif +_GL_CXXALIASWARN (getcwd); +#elif defined GNULIB_POSIXCHECK +# undef getcwd +# if HAVE_RAW_DECL_GETCWD +_GL_WARN_ON_USE (getcwd, "getcwd is unportable - " + "use gnulib module getcwd for portability"); +# endif +#endif + + +#if @GNULIB_GETDOMAINNAME@ +/* Return the NIS domain name of the machine. + WARNING! The NIS domain name is unrelated to the fully qualified host name + of the machine. It is also unrelated to email addresses. + WARNING! The NIS domain name is usually the empty string or "(none)" when + not using NIS. + + Put up to LEN bytes of the NIS domain name into NAME. + Null terminate it if the name is shorter than LEN. + If the NIS domain name is longer than LEN, set errno = EINVAL and return -1. + Return 0 if successful, otherwise set errno and return -1. */ +# if @REPLACE_GETDOMAINNAME@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef getdomainname +# define getdomainname rpl_getdomainname +# endif +_GL_FUNCDECL_RPL (getdomainname, int, (char *name, size_t len) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (getdomainname, int, (char *name, size_t len)); +# else +# if !@HAVE_DECL_GETDOMAINNAME@ +_GL_FUNCDECL_SYS (getdomainname, int, (char *name, size_t len) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (getdomainname, int, (char *name, size_t len)); +# endif +_GL_CXXALIASWARN (getdomainname); +#elif defined GNULIB_POSIXCHECK +# undef getdomainname +# if HAVE_RAW_DECL_GETDOMAINNAME +_GL_WARN_ON_USE (getdomainname, "getdomainname is unportable - " + "use gnulib module getdomainname for portability"); +# endif +#endif + + +#if @GNULIB_GETDTABLESIZE@ +/* Return the maximum number of file descriptors in the current process. + In POSIX, this is same as sysconf (_SC_OPEN_MAX). */ +# if @REPLACE_GETDTABLESIZE@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef getdtablesize +# define getdtablesize rpl_getdtablesize +# endif +_GL_FUNCDECL_RPL (getdtablesize, int, (void)); +_GL_CXXALIAS_RPL (getdtablesize, int, (void)); +# else +# if !@HAVE_GETDTABLESIZE@ +_GL_FUNCDECL_SYS (getdtablesize, int, (void)); +# endif +_GL_CXXALIAS_SYS (getdtablesize, int, (void)); +# endif +_GL_CXXALIASWARN (getdtablesize); +#elif defined GNULIB_POSIXCHECK +# undef getdtablesize +# if HAVE_RAW_DECL_GETDTABLESIZE +_GL_WARN_ON_USE (getdtablesize, "getdtablesize is unportable - " + "use gnulib module getdtablesize for portability"); +# endif +#endif + + +#if @GNULIB_GETGROUPS@ +/* Return the supplemental groups that the current process belongs to. + It is unspecified whether the effective group id is in the list. + If N is 0, return the group count; otherwise, N describes how many + entries are available in GROUPS. Return -1 and set errno if N is + not 0 and not large enough. Fails with ENOSYS on some systems. */ +# if @REPLACE_GETGROUPS@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef getgroups +# define getgroups rpl_getgroups +# endif +_GL_FUNCDECL_RPL (getgroups, int, (int n, gid_t *groups)); +_GL_CXXALIAS_RPL (getgroups, int, (int n, gid_t *groups)); +# else +# if !@HAVE_GETGROUPS@ +_GL_FUNCDECL_SYS (getgroups, int, (int n, gid_t *groups)); +# endif +_GL_CXXALIAS_SYS (getgroups, int, (int n, gid_t *groups)); +# endif +_GL_CXXALIASWARN (getgroups); +#elif defined GNULIB_POSIXCHECK +# undef getgroups +# if HAVE_RAW_DECL_GETGROUPS +_GL_WARN_ON_USE (getgroups, "getgroups is unportable - " + "use gnulib module getgroups for portability"); +# endif +#endif + + +#if @GNULIB_GETHOSTNAME@ +/* Return the standard host name of the machine. + WARNING! The host name may or may not be fully qualified. + + Put up to LEN bytes of the host name into NAME. + Null terminate it if the name is shorter than LEN. + If the host name is longer than LEN, set errno = EINVAL and return -1. + Return 0 if successful, otherwise set errno and return -1. */ +# if @UNISTD_H_HAVE_WINSOCK2_H@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef gethostname +# define gethostname rpl_gethostname +# endif +_GL_FUNCDECL_RPL (gethostname, int, (char *name, size_t len) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (gethostname, int, (char *name, size_t len)); +# else +# if !@HAVE_GETHOSTNAME@ +_GL_FUNCDECL_SYS (gethostname, int, (char *name, size_t len) + _GL_ARG_NONNULL ((1))); +# endif +/* Need to cast, because on Solaris 10 and OSF/1 5.1 systems, the second + parameter is + int len. */ +_GL_CXXALIAS_SYS_CAST (gethostname, int, (char *name, size_t len)); +# endif +_GL_CXXALIASWARN (gethostname); +#elif @UNISTD_H_HAVE_WINSOCK2_H@ +# undef gethostname +# define gethostname gethostname_used_without_requesting_gnulib_module_gethostname +#elif defined GNULIB_POSIXCHECK +# undef gethostname +# if HAVE_RAW_DECL_GETHOSTNAME +_GL_WARN_ON_USE (gethostname, "gethostname is unportable - " + "use gnulib module gethostname for portability"); +# endif +#endif + + +#if @GNULIB_GETLOGIN@ +/* Returns the user's login name, or NULL if it cannot be found. Upon error, + returns NULL with errno set. + + See . + + Most programs don't need to use this function, because the information is + available through environment variables: + ${LOGNAME-$USER} on Unix platforms, + $USERNAME on native Windows platforms. + */ +# if !@HAVE_GETLOGIN@ +_GL_FUNCDECL_SYS (getlogin, char *, (void)); +# endif +_GL_CXXALIAS_SYS (getlogin, char *, (void)); +_GL_CXXALIASWARN (getlogin); +#elif defined GNULIB_POSIXCHECK +# undef getlogin +# if HAVE_RAW_DECL_GETLOGIN +_GL_WARN_ON_USE (getlogin, "getlogin is unportable - " + "use gnulib module getlogin for portability"); +# endif +#endif + + +#if @GNULIB_GETLOGIN_R@ +/* Copies the user's login name to NAME. + The array pointed to by NAME has room for SIZE bytes. + + Returns 0 if successful. Upon error, an error number is returned, or -1 in + the case that the login name cannot be found but no specific error is + provided (this case is hopefully rare but is left open by the POSIX spec). + + See . + + Most programs don't need to use this function, because the information is + available through environment variables: + ${LOGNAME-$USER} on Unix platforms, + $USERNAME on native Windows platforms. + */ +# if @REPLACE_GETLOGIN_R@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define getlogin_r rpl_getlogin_r +# endif +_GL_FUNCDECL_RPL (getlogin_r, int, (char *name, size_t size) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (getlogin_r, int, (char *name, size_t size)); +# else +# if !@HAVE_DECL_GETLOGIN_R@ +_GL_FUNCDECL_SYS (getlogin_r, int, (char *name, size_t size) + _GL_ARG_NONNULL ((1))); +# endif +/* Need to cast, because on Solaris 10 systems, the second argument is + int size. */ +_GL_CXXALIAS_SYS_CAST (getlogin_r, int, (char *name, size_t size)); +# endif +_GL_CXXALIASWARN (getlogin_r); +#elif defined GNULIB_POSIXCHECK +# undef getlogin_r +# if HAVE_RAW_DECL_GETLOGIN_R +_GL_WARN_ON_USE (getlogin_r, "getlogin_r is unportable - " + "use gnulib module getlogin_r for portability"); +# endif +#endif + + +#if @GNULIB_GETPAGESIZE@ +# if @REPLACE_GETPAGESIZE@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define getpagesize rpl_getpagesize +# endif +_GL_FUNCDECL_RPL (getpagesize, int, (void)); +_GL_CXXALIAS_RPL (getpagesize, int, (void)); +# else +# if !@HAVE_GETPAGESIZE@ +# if !defined getpagesize +/* This is for POSIX systems. */ +# if !defined _gl_getpagesize && defined _SC_PAGESIZE +# if ! (defined __VMS && __VMS_VER < 70000000) +# define _gl_getpagesize() sysconf (_SC_PAGESIZE) +# endif +# endif +/* This is for older VMS. */ +# if !defined _gl_getpagesize && defined __VMS +# ifdef __ALPHA +# define _gl_getpagesize() 8192 +# else +# define _gl_getpagesize() 512 +# endif +# endif +/* This is for BeOS. */ +# if !defined _gl_getpagesize && @HAVE_OS_H@ +# include +# if defined B_PAGE_SIZE +# define _gl_getpagesize() B_PAGE_SIZE +# endif +# endif +/* This is for AmigaOS4.0. */ +# if !defined _gl_getpagesize && defined __amigaos4__ +# define _gl_getpagesize() 2048 +# endif +/* This is for older Unix systems. */ +# if !defined _gl_getpagesize && @HAVE_SYS_PARAM_H@ +# include +# ifdef EXEC_PAGESIZE +# define _gl_getpagesize() EXEC_PAGESIZE +# else +# ifdef NBPG +# ifndef CLSIZE +# define CLSIZE 1 +# endif +# define _gl_getpagesize() (NBPG * CLSIZE) +# else +# ifdef NBPC +# define _gl_getpagesize() NBPC +# endif +# endif +# endif +# endif +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define getpagesize() _gl_getpagesize () +# else +# if !GNULIB_defined_getpagesize_function +_GL_UNISTD_INLINE int +getpagesize () +{ + return _gl_getpagesize (); +} +# define GNULIB_defined_getpagesize_function 1 +# endif +# endif +# endif +# endif +/* Need to cast, because on Cygwin 1.5.x systems, the return type is size_t. */ +_GL_CXXALIAS_SYS_CAST (getpagesize, int, (void)); +# endif +# if @HAVE_DECL_GETPAGESIZE@ +_GL_CXXALIASWARN (getpagesize); +# endif +#elif defined GNULIB_POSIXCHECK +# undef getpagesize +# if HAVE_RAW_DECL_GETPAGESIZE +_GL_WARN_ON_USE (getpagesize, "getpagesize is unportable - " + "use gnulib module getpagesize for portability"); +# endif +#endif + + +#if @GNULIB_GETUSERSHELL@ +/* Return the next valid login shell on the system, or NULL when the end of + the list has been reached. */ +# if !@HAVE_DECL_GETUSERSHELL@ +_GL_FUNCDECL_SYS (getusershell, char *, (void)); +# endif +_GL_CXXALIAS_SYS (getusershell, char *, (void)); +_GL_CXXALIASWARN (getusershell); +#elif defined GNULIB_POSIXCHECK +# undef getusershell +# if HAVE_RAW_DECL_GETUSERSHELL +_GL_WARN_ON_USE (getusershell, "getusershell is unportable - " + "use gnulib module getusershell for portability"); +# endif +#endif + +#if @GNULIB_GETUSERSHELL@ +/* Rewind to pointer that is advanced at each getusershell() call. */ +# if !@HAVE_DECL_GETUSERSHELL@ +_GL_FUNCDECL_SYS (setusershell, void, (void)); +# endif +_GL_CXXALIAS_SYS (setusershell, void, (void)); +_GL_CXXALIASWARN (setusershell); +#elif defined GNULIB_POSIXCHECK +# undef setusershell +# if HAVE_RAW_DECL_SETUSERSHELL +_GL_WARN_ON_USE (setusershell, "setusershell is unportable - " + "use gnulib module getusershell for portability"); +# endif +#endif + +#if @GNULIB_GETUSERSHELL@ +/* Free the pointer that is advanced at each getusershell() call and + associated resources. */ +# if !@HAVE_DECL_GETUSERSHELL@ +_GL_FUNCDECL_SYS (endusershell, void, (void)); +# endif +_GL_CXXALIAS_SYS (endusershell, void, (void)); +_GL_CXXALIASWARN (endusershell); +#elif defined GNULIB_POSIXCHECK +# undef endusershell +# if HAVE_RAW_DECL_ENDUSERSHELL +_GL_WARN_ON_USE (endusershell, "endusershell is unportable - " + "use gnulib module getusershell for portability"); +# endif +#endif + + +#if @GNULIB_GROUP_MEMBER@ +/* Determine whether group id is in calling user's group list. */ +# if !@HAVE_GROUP_MEMBER@ +_GL_FUNCDECL_SYS (group_member, int, (gid_t gid)); +# endif +_GL_CXXALIAS_SYS (group_member, int, (gid_t gid)); +_GL_CXXALIASWARN (group_member); +#elif defined GNULIB_POSIXCHECK +# undef group_member +# if HAVE_RAW_DECL_GROUP_MEMBER +_GL_WARN_ON_USE (group_member, "group_member is unportable - " + "use gnulib module group-member for portability"); +# endif +#endif + + +#if @GNULIB_ISATTY@ +# if @REPLACE_ISATTY@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef isatty +# define isatty rpl_isatty +# endif +_GL_FUNCDECL_RPL (isatty, int, (int fd)); +_GL_CXXALIAS_RPL (isatty, int, (int fd)); +# else +_GL_CXXALIAS_SYS (isatty, int, (int fd)); +# endif +_GL_CXXALIASWARN (isatty); +#elif defined GNULIB_POSIXCHECK +# undef isatty +# if HAVE_RAW_DECL_ISATTY +_GL_WARN_ON_USE (isatty, "isatty has portability problems on native Windows - " + "use gnulib module isatty for portability"); +# endif +#endif + + +#if @GNULIB_LCHOWN@ +/* Change the owner of FILE to UID (if UID is not -1) and the group of FILE + to GID (if GID is not -1). Do not follow symbolic links. + Return 0 if successful, otherwise -1 and errno set. + See the POSIX:2008 specification + . */ +# if @REPLACE_LCHOWN@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef lchown +# define lchown rpl_lchown +# endif +_GL_FUNCDECL_RPL (lchown, int, (char const *file, uid_t owner, gid_t group) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (lchown, int, (char const *file, uid_t owner, gid_t group)); +# else +# if !@HAVE_LCHOWN@ +_GL_FUNCDECL_SYS (lchown, int, (char const *file, uid_t owner, gid_t group) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (lchown, int, (char const *file, uid_t owner, gid_t group)); +# endif +_GL_CXXALIASWARN (lchown); +#elif defined GNULIB_POSIXCHECK +# undef lchown +# if HAVE_RAW_DECL_LCHOWN +_GL_WARN_ON_USE (lchown, "lchown is unportable to pre-POSIX.1-2001 systems - " + "use gnulib module lchown for portability"); +# endif +#endif + + +#if @GNULIB_LINK@ +/* Create a new hard link for an existing file. + Return 0 if successful, otherwise -1 and errno set. + See POSIX:2008 specification + . */ +# if @REPLACE_LINK@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define link rpl_link +# endif +_GL_FUNCDECL_RPL (link, int, (const char *path1, const char *path2) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (link, int, (const char *path1, const char *path2)); +# else +# if !@HAVE_LINK@ +_GL_FUNCDECL_SYS (link, int, (const char *path1, const char *path2) + _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (link, int, (const char *path1, const char *path2)); +# endif +_GL_CXXALIASWARN (link); +#elif defined GNULIB_POSIXCHECK +# undef link +# if HAVE_RAW_DECL_LINK +_GL_WARN_ON_USE (link, "link is unportable - " + "use gnulib module link for portability"); +# endif +#endif + + +#if @GNULIB_LINKAT@ +/* Create a new hard link for an existing file, relative to two + directories. FLAG controls whether symlinks are followed. + Return 0 if successful, otherwise -1 and errno set. */ +# if @REPLACE_LINKAT@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef linkat +# define linkat rpl_linkat +# endif +_GL_FUNCDECL_RPL (linkat, int, + (int fd1, const char *path1, int fd2, const char *path2, + int flag) + _GL_ARG_NONNULL ((2, 4))); +_GL_CXXALIAS_RPL (linkat, int, + (int fd1, const char *path1, int fd2, const char *path2, + int flag)); +# else +# if !@HAVE_LINKAT@ +_GL_FUNCDECL_SYS (linkat, int, + (int fd1, const char *path1, int fd2, const char *path2, + int flag) + _GL_ARG_NONNULL ((2, 4))); +# endif +_GL_CXXALIAS_SYS (linkat, int, + (int fd1, const char *path1, int fd2, const char *path2, + int flag)); +# endif +_GL_CXXALIASWARN (linkat); +#elif defined GNULIB_POSIXCHECK +# undef linkat +# if HAVE_RAW_DECL_LINKAT +_GL_WARN_ON_USE (linkat, "linkat is unportable - " + "use gnulib module linkat for portability"); +# endif +#endif + + +#if @GNULIB_LSEEK@ +/* Set the offset of FD relative to SEEK_SET, SEEK_CUR, or SEEK_END. + Return the new offset if successful, otherwise -1 and errno set. + See the POSIX:2008 specification + . */ +# if @REPLACE_LSEEK@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define lseek rpl_lseek +# endif +_GL_FUNCDECL_RPL (lseek, off_t, (int fd, off_t offset, int whence)); +_GL_CXXALIAS_RPL (lseek, off_t, (int fd, off_t offset, int whence)); +# else +_GL_CXXALIAS_SYS (lseek, off_t, (int fd, off_t offset, int whence)); +# endif +_GL_CXXALIASWARN (lseek); +#elif defined GNULIB_POSIXCHECK +# undef lseek +# if HAVE_RAW_DECL_LSEEK +_GL_WARN_ON_USE (lseek, "lseek does not fail with ESPIPE on pipes on some " + "systems - use gnulib module lseek for portability"); +# endif +#endif + + +#if @GNULIB_PIPE@ +/* Create a pipe, defaulting to O_BINARY mode. + Store the read-end as fd[0] and the write-end as fd[1]. + Return 0 upon success, or -1 with errno set upon failure. */ +# if !@HAVE_PIPE@ +_GL_FUNCDECL_SYS (pipe, int, (int fd[2]) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (pipe, int, (int fd[2])); +_GL_CXXALIASWARN (pipe); +#elif defined GNULIB_POSIXCHECK +# undef pipe +# if HAVE_RAW_DECL_PIPE +_GL_WARN_ON_USE (pipe, "pipe is unportable - " + "use gnulib module pipe-posix for portability"); +# endif +#endif + + +#if @GNULIB_PIPE2@ +/* Create a pipe, applying the given flags when opening the read-end of the + pipe and the write-end of the pipe. + The flags are a bitmask, possibly including O_CLOEXEC (defined in ) + and O_TEXT, O_BINARY (defined in "binary-io.h"). + Store the read-end as fd[0] and the write-end as fd[1]. + Return 0 upon success, or -1 with errno set upon failure. + See also the Linux man page at + . */ +# if @HAVE_PIPE2@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define pipe2 rpl_pipe2 +# endif +_GL_FUNCDECL_RPL (pipe2, int, (int fd[2], int flags) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (pipe2, int, (int fd[2], int flags)); +# else +_GL_FUNCDECL_SYS (pipe2, int, (int fd[2], int flags) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_SYS (pipe2, int, (int fd[2], int flags)); +# endif +_GL_CXXALIASWARN (pipe2); +#elif defined GNULIB_POSIXCHECK +# undef pipe2 +# if HAVE_RAW_DECL_PIPE2 +_GL_WARN_ON_USE (pipe2, "pipe2 is unportable - " + "use gnulib module pipe2 for portability"); +# endif +#endif + + +#if @GNULIB_PREAD@ +/* Read at most BUFSIZE bytes from FD into BUF, starting at OFFSET. + Return the number of bytes placed into BUF if successful, otherwise + set errno and return -1. 0 indicates EOF. + See the POSIX:2008 specification + . */ +# if @REPLACE_PREAD@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef pread +# define pread rpl_pread +# endif +_GL_FUNCDECL_RPL (pread, ssize_t, + (int fd, void *buf, size_t bufsize, off_t offset) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (pread, ssize_t, + (int fd, void *buf, size_t bufsize, off_t offset)); +# else +# if !@HAVE_PREAD@ +_GL_FUNCDECL_SYS (pread, ssize_t, + (int fd, void *buf, size_t bufsize, off_t offset) + _GL_ARG_NONNULL ((2))); +# endif +_GL_CXXALIAS_SYS (pread, ssize_t, + (int fd, void *buf, size_t bufsize, off_t offset)); +# endif +_GL_CXXALIASWARN (pread); +#elif defined GNULIB_POSIXCHECK +# undef pread +# if HAVE_RAW_DECL_PREAD +_GL_WARN_ON_USE (pread, "pread is unportable - " + "use gnulib module pread for portability"); +# endif +#endif + + +#if @GNULIB_PWRITE@ +/* Write at most BUFSIZE bytes from BUF into FD, starting at OFFSET. + Return the number of bytes written if successful, otherwise + set errno and return -1. 0 indicates nothing written. See the + POSIX:2008 specification + . */ +# if @REPLACE_PWRITE@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef pwrite +# define pwrite rpl_pwrite +# endif +_GL_FUNCDECL_RPL (pwrite, ssize_t, + (int fd, const void *buf, size_t bufsize, off_t offset) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (pwrite, ssize_t, + (int fd, const void *buf, size_t bufsize, off_t offset)); +# else +# if !@HAVE_PWRITE@ +_GL_FUNCDECL_SYS (pwrite, ssize_t, + (int fd, const void *buf, size_t bufsize, off_t offset) + _GL_ARG_NONNULL ((2))); +# endif +_GL_CXXALIAS_SYS (pwrite, ssize_t, + (int fd, const void *buf, size_t bufsize, off_t offset)); +# endif +_GL_CXXALIASWARN (pwrite); +#elif defined GNULIB_POSIXCHECK +# undef pwrite +# if HAVE_RAW_DECL_PWRITE +_GL_WARN_ON_USE (pwrite, "pwrite is unportable - " + "use gnulib module pwrite for portability"); +# endif +#endif + + +#if @GNULIB_READ@ +/* Read up to COUNT bytes from file descriptor FD into the buffer starting + at BUF. See the POSIX:2008 specification + . */ +# if @REPLACE_READ@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef read +# define read rpl_read +# endif +_GL_FUNCDECL_RPL (read, ssize_t, (int fd, void *buf, size_t count) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (read, ssize_t, (int fd, void *buf, size_t count)); +# else +/* Need to cast, because on mingw, the third parameter is + unsigned int count + and the return type is 'int'. */ +_GL_CXXALIAS_SYS_CAST (read, ssize_t, (int fd, void *buf, size_t count)); +# endif +_GL_CXXALIASWARN (read); +#endif + + +#if @GNULIB_READLINK@ +/* Read the contents of the symbolic link FILE and place the first BUFSIZE + bytes of it into BUF. Return the number of bytes placed into BUF if + successful, otherwise -1 and errno set. + See the POSIX:2008 specification + . */ +# if @REPLACE_READLINK@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define readlink rpl_readlink +# endif +_GL_FUNCDECL_RPL (readlink, ssize_t, + (const char *file, char *buf, size_t bufsize) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (readlink, ssize_t, + (const char *file, char *buf, size_t bufsize)); +# else +# if !@HAVE_READLINK@ +_GL_FUNCDECL_SYS (readlink, ssize_t, + (const char *file, char *buf, size_t bufsize) + _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (readlink, ssize_t, + (const char *file, char *buf, size_t bufsize)); +# endif +_GL_CXXALIASWARN (readlink); +#elif defined GNULIB_POSIXCHECK +# undef readlink +# if HAVE_RAW_DECL_READLINK +_GL_WARN_ON_USE (readlink, "readlink is unportable - " + "use gnulib module readlink for portability"); +# endif +#endif + + +#if @GNULIB_READLINKAT@ +# if @REPLACE_READLINKAT@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define readlinkat rpl_readlinkat +# endif +_GL_FUNCDECL_RPL (readlinkat, ssize_t, + (int fd, char const *file, char *buf, size_t len) + _GL_ARG_NONNULL ((2, 3))); +_GL_CXXALIAS_RPL (readlinkat, ssize_t, + (int fd, char const *file, char *buf, size_t len)); +# else +# if !@HAVE_READLINKAT@ +_GL_FUNCDECL_SYS (readlinkat, ssize_t, + (int fd, char const *file, char *buf, size_t len) + _GL_ARG_NONNULL ((2, 3))); +# endif +_GL_CXXALIAS_SYS (readlinkat, ssize_t, + (int fd, char const *file, char *buf, size_t len)); +# endif +_GL_CXXALIASWARN (readlinkat); +#elif defined GNULIB_POSIXCHECK +# undef readlinkat +# if HAVE_RAW_DECL_READLINKAT +_GL_WARN_ON_USE (readlinkat, "readlinkat is not portable - " + "use gnulib module readlinkat for portability"); +# endif +#endif + + +#if @GNULIB_RMDIR@ +/* Remove the directory DIR. */ +# if @REPLACE_RMDIR@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define rmdir rpl_rmdir +# endif +_GL_FUNCDECL_RPL (rmdir, int, (char const *name) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (rmdir, int, (char const *name)); +# else +_GL_CXXALIAS_SYS (rmdir, int, (char const *name)); +# endif +_GL_CXXALIASWARN (rmdir); +#elif defined GNULIB_POSIXCHECK +# undef rmdir +# if HAVE_RAW_DECL_RMDIR +_GL_WARN_ON_USE (rmdir, "rmdir is unportable - " + "use gnulib module rmdir for portability"); +# endif +#endif + + +#if @GNULIB_SETHOSTNAME@ +/* Set the host name of the machine. + The host name may or may not be fully qualified. + + Put LEN bytes of NAME into the host name. + Return 0 if successful, otherwise, set errno and return -1. + + Platforms with no ability to set the hostname return -1 and set + errno = ENOSYS. */ +# if !@HAVE_SETHOSTNAME@ || !@HAVE_DECL_SETHOSTNAME@ +_GL_FUNCDECL_SYS (sethostname, int, (const char *name, size_t len) + _GL_ARG_NONNULL ((1))); +# endif +/* Need to cast, because on Solaris 11 2011-10, Mac OS X 10.5, IRIX 6.5 + and FreeBSD 6.4 the second parameter is int. On Solaris 11 + 2011-10, the first parameter is not const. */ +_GL_CXXALIAS_SYS_CAST (sethostname, int, (const char *name, size_t len)); +_GL_CXXALIASWARN (sethostname); +#elif defined GNULIB_POSIXCHECK +# undef sethostname +# if HAVE_RAW_DECL_SETHOSTNAME +_GL_WARN_ON_USE (sethostname, "sethostname is unportable - " + "use gnulib module sethostname for portability"); +# endif +#endif + + +#if @GNULIB_SLEEP@ +/* Pause the execution of the current thread for N seconds. + Returns the number of seconds left to sleep. + See the POSIX:2008 specification + . */ +# if @REPLACE_SLEEP@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef sleep +# define sleep rpl_sleep +# endif +_GL_FUNCDECL_RPL (sleep, unsigned int, (unsigned int n)); +_GL_CXXALIAS_RPL (sleep, unsigned int, (unsigned int n)); +# else +# if !@HAVE_SLEEP@ +_GL_FUNCDECL_SYS (sleep, unsigned int, (unsigned int n)); +# endif +_GL_CXXALIAS_SYS (sleep, unsigned int, (unsigned int n)); +# endif +_GL_CXXALIASWARN (sleep); +#elif defined GNULIB_POSIXCHECK +# undef sleep +# if HAVE_RAW_DECL_SLEEP +_GL_WARN_ON_USE (sleep, "sleep is unportable - " + "use gnulib module sleep for portability"); +# endif +#endif + + +#if @GNULIB_SYMLINK@ +# if @REPLACE_SYMLINK@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef symlink +# define symlink rpl_symlink +# endif +_GL_FUNCDECL_RPL (symlink, int, (char const *contents, char const *file) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (symlink, int, (char const *contents, char const *file)); +# else +# if !@HAVE_SYMLINK@ +_GL_FUNCDECL_SYS (symlink, int, (char const *contents, char const *file) + _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (symlink, int, (char const *contents, char const *file)); +# endif +_GL_CXXALIASWARN (symlink); +#elif defined GNULIB_POSIXCHECK +# undef symlink +# if HAVE_RAW_DECL_SYMLINK +_GL_WARN_ON_USE (symlink, "symlink is not portable - " + "use gnulib module symlink for portability"); +# endif +#endif + + +#if @GNULIB_SYMLINKAT@ +# if @REPLACE_SYMLINKAT@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef symlinkat +# define symlinkat rpl_symlinkat +# endif +_GL_FUNCDECL_RPL (symlinkat, int, + (char const *contents, int fd, char const *file) + _GL_ARG_NONNULL ((1, 3))); +_GL_CXXALIAS_RPL (symlinkat, int, + (char const *contents, int fd, char const *file)); +# else +# if !@HAVE_SYMLINKAT@ +_GL_FUNCDECL_SYS (symlinkat, int, + (char const *contents, int fd, char const *file) + _GL_ARG_NONNULL ((1, 3))); +# endif +_GL_CXXALIAS_SYS (symlinkat, int, + (char const *contents, int fd, char const *file)); +# endif +_GL_CXXALIASWARN (symlinkat); +#elif defined GNULIB_POSIXCHECK +# undef symlinkat +# if HAVE_RAW_DECL_SYMLINKAT +_GL_WARN_ON_USE (symlinkat, "symlinkat is not portable - " + "use gnulib module symlinkat for portability"); +# endif +#endif + + +#if @GNULIB_TTYNAME_R@ +/* Store at most BUFLEN characters of the pathname of the terminal FD is + open on in BUF. Return 0 on success, otherwise an error number. */ +# if @REPLACE_TTYNAME_R@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef ttyname_r +# define ttyname_r rpl_ttyname_r +# endif +_GL_FUNCDECL_RPL (ttyname_r, int, + (int fd, char *buf, size_t buflen) _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (ttyname_r, int, + (int fd, char *buf, size_t buflen)); +# else +# if !@HAVE_DECL_TTYNAME_R@ +_GL_FUNCDECL_SYS (ttyname_r, int, + (int fd, char *buf, size_t buflen) _GL_ARG_NONNULL ((2))); +# endif +_GL_CXXALIAS_SYS (ttyname_r, int, + (int fd, char *buf, size_t buflen)); +# endif +_GL_CXXALIASWARN (ttyname_r); +#elif defined GNULIB_POSIXCHECK +# undef ttyname_r +# if HAVE_RAW_DECL_TTYNAME_R +_GL_WARN_ON_USE (ttyname_r, "ttyname_r is not portable - " + "use gnulib module ttyname_r for portability"); +# endif +#endif + + +#if @GNULIB_UNLINK@ +# if @REPLACE_UNLINK@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef unlink +# define unlink rpl_unlink +# endif +_GL_FUNCDECL_RPL (unlink, int, (char const *file) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (unlink, int, (char const *file)); +# else +_GL_CXXALIAS_SYS (unlink, int, (char const *file)); +# endif +_GL_CXXALIASWARN (unlink); +#elif defined GNULIB_POSIXCHECK +# undef unlink +# if HAVE_RAW_DECL_UNLINK +_GL_WARN_ON_USE (unlink, "unlink is not portable - " + "use gnulib module unlink for portability"); +# endif +#endif + + +#if @GNULIB_UNLINKAT@ +# if @REPLACE_UNLINKAT@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef unlinkat +# define unlinkat rpl_unlinkat +# endif +_GL_FUNCDECL_RPL (unlinkat, int, (int fd, char const *file, int flag) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (unlinkat, int, (int fd, char const *file, int flag)); +# else +# if !@HAVE_UNLINKAT@ +_GL_FUNCDECL_SYS (unlinkat, int, (int fd, char const *file, int flag) + _GL_ARG_NONNULL ((2))); +# endif +_GL_CXXALIAS_SYS (unlinkat, int, (int fd, char const *file, int flag)); +# endif +_GL_CXXALIASWARN (unlinkat); +#elif defined GNULIB_POSIXCHECK +# undef unlinkat +# if HAVE_RAW_DECL_UNLINKAT +_GL_WARN_ON_USE (unlinkat, "unlinkat is not portable - " + "use gnulib module openat for portability"); +# endif +#endif + + +#if @GNULIB_USLEEP@ +/* Pause the execution of the current thread for N microseconds. + Returns 0 on completion, or -1 on range error. + See the POSIX:2001 specification + . */ +# if @REPLACE_USLEEP@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef usleep +# define usleep rpl_usleep +# endif +_GL_FUNCDECL_RPL (usleep, int, (useconds_t n)); +_GL_CXXALIAS_RPL (usleep, int, (useconds_t n)); +# else +# if !@HAVE_USLEEP@ +_GL_FUNCDECL_SYS (usleep, int, (useconds_t n)); +# endif +_GL_CXXALIAS_SYS (usleep, int, (useconds_t n)); +# endif +_GL_CXXALIASWARN (usleep); +#elif defined GNULIB_POSIXCHECK +# undef usleep +# if HAVE_RAW_DECL_USLEEP +_GL_WARN_ON_USE (usleep, "usleep is unportable - " + "use gnulib module usleep for portability"); +# endif +#endif + + +#if @GNULIB_WRITE@ +/* Write up to COUNT bytes starting at BUF to file descriptor FD. + See the POSIX:2008 specification + . */ +# if @REPLACE_WRITE@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef write +# define write rpl_write +# endif +_GL_FUNCDECL_RPL (write, ssize_t, (int fd, const void *buf, size_t count) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (write, ssize_t, (int fd, const void *buf, size_t count)); +# else +/* Need to cast, because on mingw, the third parameter is + unsigned int count + and the return type is 'int'. */ +_GL_CXXALIAS_SYS_CAST (write, ssize_t, (int fd, const void *buf, size_t count)); +# endif +_GL_CXXALIASWARN (write); +#endif + +_GL_INLINE_HEADER_END + +#endif /* _@GUARD_PREFIX@_UNISTD_H */ +#endif /* _GL_INCLUDING_UNISTD_H */ +#endif /* _@GUARD_PREFIX@_UNISTD_H */ diff --git a/gettext-tools/gnulib-lib/unistr.in.h b/gettext-tools/gnulib-lib/unistr.in.h new file mode 100644 index 0000000..222c959 --- /dev/null +++ b/gettext-tools/gnulib-lib/unistr.in.h @@ -0,0 +1,750 @@ +/* Elementary Unicode string functions. + Copyright (C) 2001-2002, 2005-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _UNISTR_H +#define _UNISTR_H + +#include "unitypes.h" + +/* Get common macros for C. */ +#include "unused-parameter.h" + +/* Get bool. */ +#include + +/* Get size_t. */ +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Conventions: + + All functions prefixed with u8_ operate on UTF-8 encoded strings. + Their unit is an uint8_t (1 byte). + + All functions prefixed with u16_ operate on UTF-16 encoded strings. + Their unit is an uint16_t (a 2-byte word). + + All functions prefixed with u32_ operate on UCS-4 encoded strings. + Their unit is an uint32_t (a 4-byte word). + + All argument pairs (s, n) denote a Unicode string s[0..n-1] with exactly + n units. + + All arguments starting with "str" and the arguments of functions starting + with u8_str/u16_str/u32_str denote a NUL terminated string, i.e. a string + which terminates at the first NUL unit. This termination unit is + considered part of the string for all memory allocation purposes, but + is not considered part of the string for all other logical purposes. + + Functions returning a string result take a (resultbuf, lengthp) argument + pair. If resultbuf is not NULL and the result fits into *lengthp units, + it is put in resultbuf, and resultbuf is returned. Otherwise, a freshly + allocated string is returned. In both cases, *lengthp is set to the + length (number of units) of the returned string. In case of error, + NULL is returned and errno is set. */ + + +/* Elementary string checks. */ + +/* Check whether an UTF-8 string is well-formed. + Return NULL if valid, or a pointer to the first invalid unit otherwise. */ +extern const uint8_t * + u8_check (const uint8_t *s, size_t n) + _UC_ATTRIBUTE_PURE; + +/* Check whether an UTF-16 string is well-formed. + Return NULL if valid, or a pointer to the first invalid unit otherwise. */ +extern const uint16_t * + u16_check (const uint16_t *s, size_t n) + _UC_ATTRIBUTE_PURE; + +/* Check whether an UCS-4 string is well-formed. + Return NULL if valid, or a pointer to the first invalid unit otherwise. */ +extern const uint32_t * + u32_check (const uint32_t *s, size_t n) + _UC_ATTRIBUTE_PURE; + + +/* Elementary string conversions. */ + +/* Convert an UTF-8 string to an UTF-16 string. */ +extern uint16_t * + u8_to_u16 (const uint8_t *s, size_t n, uint16_t *resultbuf, + size_t *lengthp); + +/* Convert an UTF-8 string to an UCS-4 string. */ +extern uint32_t * + u8_to_u32 (const uint8_t *s, size_t n, uint32_t *resultbuf, + size_t *lengthp); + +/* Convert an UTF-16 string to an UTF-8 string. */ +extern uint8_t * + u16_to_u8 (const uint16_t *s, size_t n, uint8_t *resultbuf, + size_t *lengthp); + +/* Convert an UTF-16 string to an UCS-4 string. */ +extern uint32_t * + u16_to_u32 (const uint16_t *s, size_t n, uint32_t *resultbuf, + size_t *lengthp); + +/* Convert an UCS-4 string to an UTF-8 string. */ +extern uint8_t * + u32_to_u8 (const uint32_t *s, size_t n, uint8_t *resultbuf, + size_t *lengthp); + +/* Convert an UCS-4 string to an UTF-16 string. */ +extern uint16_t * + u32_to_u16 (const uint32_t *s, size_t n, uint16_t *resultbuf, + size_t *lengthp); + + +/* Elementary string functions. */ + +/* Return the length (number of units) of the first character in S, which is + no longer than N. Return 0 if it is the NUL character. Return -1 upon + failure. */ +/* Similar to mblen(), except that s must not be NULL. */ +extern int + u8_mblen (const uint8_t *s, size_t n) + _UC_ATTRIBUTE_PURE; +extern int + u16_mblen (const uint16_t *s, size_t n) + _UC_ATTRIBUTE_PURE; +extern int + u32_mblen (const uint32_t *s, size_t n) + _UC_ATTRIBUTE_PURE; + +/* Return the length (number of units) of the first character in S, putting + its 'ucs4_t' representation in *PUC. Upon failure, *PUC is set to 0xfffd, + and an appropriate number of units is returned. + The number of available units, N, must be > 0. */ +/* Similar to mbtowc(), except that puc and s must not be NULL, n must be > 0, + and the NUL character is not treated specially. */ +/* The variants with _safe suffix are safe, even if the library is compiled + without --enable-safety. */ + +#if GNULIB_UNISTR_U8_MBTOUC_UNSAFE || HAVE_LIBUNISTRING +# if !HAVE_INLINE +extern int + u8_mbtouc_unsafe (ucs4_t *puc, const uint8_t *s, size_t n); +# else +extern int + u8_mbtouc_unsafe_aux (ucs4_t *puc, const uint8_t *s, size_t n); +static inline int +u8_mbtouc_unsafe (ucs4_t *puc, const uint8_t *s, size_t n) +{ + uint8_t c = *s; + + if (c < 0x80) + { + *puc = c; + return 1; + } + else + return u8_mbtouc_unsafe_aux (puc, s, n); +} +# endif +#endif + +#if GNULIB_UNISTR_U16_MBTOUC_UNSAFE || HAVE_LIBUNISTRING +# if !HAVE_INLINE +extern int + u16_mbtouc_unsafe (ucs4_t *puc, const uint16_t *s, size_t n); +# else +extern int + u16_mbtouc_unsafe_aux (ucs4_t *puc, const uint16_t *s, size_t n); +static inline int +u16_mbtouc_unsafe (ucs4_t *puc, const uint16_t *s, size_t n) +{ + uint16_t c = *s; + + if (c < 0xd800 || c >= 0xe000) + { + *puc = c; + return 1; + } + else + return u16_mbtouc_unsafe_aux (puc, s, n); +} +# endif +#endif + +#if GNULIB_UNISTR_U32_MBTOUC_UNSAFE || HAVE_LIBUNISTRING +# if !HAVE_INLINE +extern int + u32_mbtouc_unsafe (ucs4_t *puc, const uint32_t *s, size_t n); +# else +static inline int +u32_mbtouc_unsafe (ucs4_t *puc, + const uint32_t *s, size_t n _GL_UNUSED_PARAMETER) +{ + uint32_t c = *s; + +# if CONFIG_UNICODE_SAFETY + if (c < 0xd800 || (c >= 0xe000 && c < 0x110000)) +# endif + *puc = c; +# if CONFIG_UNICODE_SAFETY + else + /* invalid multibyte character */ + *puc = 0xfffd; +# endif + return 1; +} +# endif +#endif + +#if GNULIB_UNISTR_U8_MBTOUC || HAVE_LIBUNISTRING +# if !HAVE_INLINE +extern int + u8_mbtouc (ucs4_t *puc, const uint8_t *s, size_t n); +# else +extern int + u8_mbtouc_aux (ucs4_t *puc, const uint8_t *s, size_t n); +static inline int +u8_mbtouc (ucs4_t *puc, const uint8_t *s, size_t n) +{ + uint8_t c = *s; + + if (c < 0x80) + { + *puc = c; + return 1; + } + else + return u8_mbtouc_aux (puc, s, n); +} +# endif +#endif + +#if GNULIB_UNISTR_U16_MBTOUC || HAVE_LIBUNISTRING +# if !HAVE_INLINE +extern int + u16_mbtouc (ucs4_t *puc, const uint16_t *s, size_t n); +# else +extern int + u16_mbtouc_aux (ucs4_t *puc, const uint16_t *s, size_t n); +static inline int +u16_mbtouc (ucs4_t *puc, const uint16_t *s, size_t n) +{ + uint16_t c = *s; + + if (c < 0xd800 || c >= 0xe000) + { + *puc = c; + return 1; + } + else + return u16_mbtouc_aux (puc, s, n); +} +# endif +#endif + +#if GNULIB_UNISTR_U32_MBTOUC || HAVE_LIBUNISTRING +# if !HAVE_INLINE +extern int + u32_mbtouc (ucs4_t *puc, const uint32_t *s, size_t n); +# else +static inline int +u32_mbtouc (ucs4_t *puc, const uint32_t *s, size_t n _GL_UNUSED_PARAMETER) +{ + uint32_t c = *s; + + if (c < 0xd800 || (c >= 0xe000 && c < 0x110000)) + *puc = c; + else + /* invalid multibyte character */ + *puc = 0xfffd; + return 1; +} +# endif +#endif + +/* Return the length (number of units) of the first character in S, putting + its 'ucs4_t' representation in *PUC. Upon failure, *PUC is set to 0xfffd, + and -1 is returned for an invalid sequence of units, -2 is returned for an + incomplete sequence of units. + The number of available units, N, must be > 0. */ +/* Similar to u*_mbtouc(), except that the return value gives more details + about the failure, similar to mbrtowc(). */ + +#if GNULIB_UNISTR_U8_MBTOUCR || HAVE_LIBUNISTRING +extern int + u8_mbtoucr (ucs4_t *puc, const uint8_t *s, size_t n); +#endif + +#if GNULIB_UNISTR_U16_MBTOUCR || HAVE_LIBUNISTRING +extern int + u16_mbtoucr (ucs4_t *puc, const uint16_t *s, size_t n); +#endif + +#if GNULIB_UNISTR_U32_MBTOUCR || HAVE_LIBUNISTRING +extern int + u32_mbtoucr (ucs4_t *puc, const uint32_t *s, size_t n); +#endif + +/* Put the multibyte character represented by UC in S, returning its + length. Return -1 upon failure, -2 if the number of available units, N, + is too small. The latter case cannot occur if N >= 6/2/1, respectively. */ +/* Similar to wctomb(), except that s must not be NULL, and the argument n + must be specified. */ + +#if GNULIB_UNISTR_U8_UCTOMB || HAVE_LIBUNISTRING +/* Auxiliary function, also used by u8_chr, u8_strchr, u8_strrchr. */ +extern int + u8_uctomb_aux (uint8_t *s, ucs4_t uc, int n); +# if !HAVE_INLINE +extern int + u8_uctomb (uint8_t *s, ucs4_t uc, int n); +# else +static inline int +u8_uctomb (uint8_t *s, ucs4_t uc, int n) +{ + if (uc < 0x80 && n > 0) + { + s[0] = uc; + return 1; + } + else + return u8_uctomb_aux (s, uc, n); +} +# endif +#endif + +#if GNULIB_UNISTR_U16_UCTOMB || HAVE_LIBUNISTRING +/* Auxiliary function, also used by u16_chr, u16_strchr, u16_strrchr. */ +extern int + u16_uctomb_aux (uint16_t *s, ucs4_t uc, int n); +# if !HAVE_INLINE +extern int + u16_uctomb (uint16_t *s, ucs4_t uc, int n); +# else +static inline int +u16_uctomb (uint16_t *s, ucs4_t uc, int n) +{ + if (uc < 0xd800 && n > 0) + { + s[0] = uc; + return 1; + } + else + return u16_uctomb_aux (s, uc, n); +} +# endif +#endif + +#if GNULIB_UNISTR_U32_UCTOMB || HAVE_LIBUNISTRING +# if !HAVE_INLINE +extern int + u32_uctomb (uint32_t *s, ucs4_t uc, int n); +# else +static inline int +u32_uctomb (uint32_t *s, ucs4_t uc, int n) +{ + if (uc < 0xd800 || (uc >= 0xe000 && uc < 0x110000)) + { + if (n > 0) + { + *s = uc; + return 1; + } + else + return -2; + } + else + return -1; +} +# endif +#endif + +/* Copy N units from SRC to DEST. */ +/* Similar to memcpy(). */ +extern uint8_t * + u8_cpy (uint8_t *dest, const uint8_t *src, size_t n); +extern uint16_t * + u16_cpy (uint16_t *dest, const uint16_t *src, size_t n); +extern uint32_t * + u32_cpy (uint32_t *dest, const uint32_t *src, size_t n); + +/* Copy N units from SRC to DEST, guaranteeing correct behavior for + overlapping memory areas. */ +/* Similar to memmove(). */ +extern uint8_t * + u8_move (uint8_t *dest, const uint8_t *src, size_t n); +extern uint16_t * + u16_move (uint16_t *dest, const uint16_t *src, size_t n); +extern uint32_t * + u32_move (uint32_t *dest, const uint32_t *src, size_t n); + +/* Set the first N characters of S to UC. UC should be a character that + occupies only 1 unit. */ +/* Similar to memset(). */ +extern uint8_t * + u8_set (uint8_t *s, ucs4_t uc, size_t n); +extern uint16_t * + u16_set (uint16_t *s, ucs4_t uc, size_t n); +extern uint32_t * + u32_set (uint32_t *s, ucs4_t uc, size_t n); + +/* Compare S1 and S2, each of length N. */ +/* Similar to memcmp(). */ +extern int + u8_cmp (const uint8_t *s1, const uint8_t *s2, size_t n) + _UC_ATTRIBUTE_PURE; +extern int + u16_cmp (const uint16_t *s1, const uint16_t *s2, size_t n) + _UC_ATTRIBUTE_PURE; +extern int + u32_cmp (const uint32_t *s1, const uint32_t *s2, size_t n) + _UC_ATTRIBUTE_PURE; + +/* Compare S1 and S2. */ +/* Similar to the gnulib function memcmp2(). */ +extern int + u8_cmp2 (const uint8_t *s1, size_t n1, const uint8_t *s2, size_t n2) + _UC_ATTRIBUTE_PURE; +extern int + u16_cmp2 (const uint16_t *s1, size_t n1, const uint16_t *s2, size_t n2) + _UC_ATTRIBUTE_PURE; +extern int + u32_cmp2 (const uint32_t *s1, size_t n1, const uint32_t *s2, size_t n2) + _UC_ATTRIBUTE_PURE; + +/* Search the string at S for UC. */ +/* Similar to memchr(). */ +extern uint8_t * + u8_chr (const uint8_t *s, size_t n, ucs4_t uc) + _UC_ATTRIBUTE_PURE; +extern uint16_t * + u16_chr (const uint16_t *s, size_t n, ucs4_t uc) + _UC_ATTRIBUTE_PURE; +extern uint32_t * + u32_chr (const uint32_t *s, size_t n, ucs4_t uc) + _UC_ATTRIBUTE_PURE; + +/* Count the number of Unicode characters in the N units from S. */ +/* Similar to mbsnlen(). */ +extern size_t + u8_mbsnlen (const uint8_t *s, size_t n) + _UC_ATTRIBUTE_PURE; +extern size_t + u16_mbsnlen (const uint16_t *s, size_t n) + _UC_ATTRIBUTE_PURE; +extern size_t + u32_mbsnlen (const uint32_t *s, size_t n) + _UC_ATTRIBUTE_PURE; + +/* Elementary string functions with memory allocation. */ + +/* Make a freshly allocated copy of S, of length N. */ +extern uint8_t * + u8_cpy_alloc (const uint8_t *s, size_t n); +extern uint16_t * + u16_cpy_alloc (const uint16_t *s, size_t n); +extern uint32_t * + u32_cpy_alloc (const uint32_t *s, size_t n); + +/* Elementary string functions on NUL terminated strings. */ + +/* Return the length (number of units) of the first character in S. + Return 0 if it is the NUL character. Return -1 upon failure. */ +extern int + u8_strmblen (const uint8_t *s) + _UC_ATTRIBUTE_PURE; +extern int + u16_strmblen (const uint16_t *s) + _UC_ATTRIBUTE_PURE; +extern int + u32_strmblen (const uint32_t *s) + _UC_ATTRIBUTE_PURE; + +/* Return the length (number of units) of the first character in S, putting + its 'ucs4_t' representation in *PUC. Return 0 if it is the NUL + character. Return -1 upon failure. */ +extern int + u8_strmbtouc (ucs4_t *puc, const uint8_t *s); +extern int + u16_strmbtouc (ucs4_t *puc, const uint16_t *s); +extern int + u32_strmbtouc (ucs4_t *puc, const uint32_t *s); + +/* Forward iteration step. Advances the pointer past the next character, + or returns NULL if the end of the string has been reached. Puts the + character's 'ucs4_t' representation in *PUC. */ +extern const uint8_t * + u8_next (ucs4_t *puc, const uint8_t *s); +extern const uint16_t * + u16_next (ucs4_t *puc, const uint16_t *s); +extern const uint32_t * + u32_next (ucs4_t *puc, const uint32_t *s); + +/* Backward iteration step. Advances the pointer to point to the previous + character, or returns NULL if the beginning of the string had been reached. + Puts the character's 'ucs4_t' representation in *PUC. */ +extern const uint8_t * + u8_prev (ucs4_t *puc, const uint8_t *s, const uint8_t *start); +extern const uint16_t * + u16_prev (ucs4_t *puc, const uint16_t *s, const uint16_t *start); +extern const uint32_t * + u32_prev (ucs4_t *puc, const uint32_t *s, const uint32_t *start); + +/* Return the number of units in S. */ +/* Similar to strlen(), wcslen(). */ +extern size_t + u8_strlen (const uint8_t *s) + _UC_ATTRIBUTE_PURE; +extern size_t + u16_strlen (const uint16_t *s) + _UC_ATTRIBUTE_PURE; +extern size_t + u32_strlen (const uint32_t *s) + _UC_ATTRIBUTE_PURE; + +/* Return the number of units in S, but at most MAXLEN. */ +/* Similar to strnlen(), wcsnlen(). */ +extern size_t + u8_strnlen (const uint8_t *s, size_t maxlen) + _UC_ATTRIBUTE_PURE; +extern size_t + u16_strnlen (const uint16_t *s, size_t maxlen) + _UC_ATTRIBUTE_PURE; +extern size_t + u32_strnlen (const uint32_t *s, size_t maxlen) + _UC_ATTRIBUTE_PURE; + +/* Copy SRC to DEST. */ +/* Similar to strcpy(), wcscpy(). */ +extern uint8_t * + u8_strcpy (uint8_t *dest, const uint8_t *src); +extern uint16_t * + u16_strcpy (uint16_t *dest, const uint16_t *src); +extern uint32_t * + u32_strcpy (uint32_t *dest, const uint32_t *src); + +/* Copy SRC to DEST, returning the address of the terminating NUL in DEST. */ +/* Similar to stpcpy(). */ +extern uint8_t * + u8_stpcpy (uint8_t *dest, const uint8_t *src); +extern uint16_t * + u16_stpcpy (uint16_t *dest, const uint16_t *src); +extern uint32_t * + u32_stpcpy (uint32_t *dest, const uint32_t *src); + +/* Copy no more than N units of SRC to DEST. */ +/* Similar to strncpy(), wcsncpy(). */ +extern uint8_t * + u8_strncpy (uint8_t *dest, const uint8_t *src, size_t n); +extern uint16_t * + u16_strncpy (uint16_t *dest, const uint16_t *src, size_t n); +extern uint32_t * + u32_strncpy (uint32_t *dest, const uint32_t *src, size_t n); + +/* Copy no more than N units of SRC to DEST. Return a pointer past the last + non-NUL unit written into DEST. */ +/* Similar to stpncpy(). */ +extern uint8_t * + u8_stpncpy (uint8_t *dest, const uint8_t *src, size_t n); +extern uint16_t * + u16_stpncpy (uint16_t *dest, const uint16_t *src, size_t n); +extern uint32_t * + u32_stpncpy (uint32_t *dest, const uint32_t *src, size_t n); + +/* Append SRC onto DEST. */ +/* Similar to strcat(), wcscat(). */ +extern uint8_t * + u8_strcat (uint8_t *dest, const uint8_t *src); +extern uint16_t * + u16_strcat (uint16_t *dest, const uint16_t *src); +extern uint32_t * + u32_strcat (uint32_t *dest, const uint32_t *src); + +/* Append no more than N units of SRC onto DEST. */ +/* Similar to strncat(), wcsncat(). */ +extern uint8_t * + u8_strncat (uint8_t *dest, const uint8_t *src, size_t n); +extern uint16_t * + u16_strncat (uint16_t *dest, const uint16_t *src, size_t n); +extern uint32_t * + u32_strncat (uint32_t *dest, const uint32_t *src, size_t n); + +/* Compare S1 and S2. */ +/* Similar to strcmp(), wcscmp(). */ +#ifdef __sun +/* Avoid a collision with the u8_strcmp() function in Solaris 11 libc. */ +extern int + u8_strcmp_gnu (const uint8_t *s1, const uint8_t *s2) + _UC_ATTRIBUTE_PURE; +# define u8_strcmp u8_strcmp_gnu +#else +extern int + u8_strcmp (const uint8_t *s1, const uint8_t *s2) + _UC_ATTRIBUTE_PURE; +#endif +extern int + u16_strcmp (const uint16_t *s1, const uint16_t *s2) + _UC_ATTRIBUTE_PURE; +extern int + u32_strcmp (const uint32_t *s1, const uint32_t *s2) + _UC_ATTRIBUTE_PURE; + +/* Compare S1 and S2 using the collation rules of the current locale. + Return -1 if S1 < S2, 0 if S1 = S2, 1 if S1 > S2. + Upon failure, set errno and return any value. */ +/* Similar to strcoll(), wcscoll(). */ +extern int + u8_strcoll (const uint8_t *s1, const uint8_t *s2); +extern int + u16_strcoll (const uint16_t *s1, const uint16_t *s2); +extern int + u32_strcoll (const uint32_t *s1, const uint32_t *s2); + +/* Compare no more than N units of S1 and S2. */ +/* Similar to strncmp(), wcsncmp(). */ +extern int + u8_strncmp (const uint8_t *s1, const uint8_t *s2, size_t n) + _UC_ATTRIBUTE_PURE; +extern int + u16_strncmp (const uint16_t *s1, const uint16_t *s2, size_t n) + _UC_ATTRIBUTE_PURE; +extern int + u32_strncmp (const uint32_t *s1, const uint32_t *s2, size_t n) + _UC_ATTRIBUTE_PURE; + +/* Duplicate S, returning an identical malloc'd string. */ +/* Similar to strdup(), wcsdup(). */ +extern uint8_t * + u8_strdup (const uint8_t *s); +extern uint16_t * + u16_strdup (const uint16_t *s); +extern uint32_t * + u32_strdup (const uint32_t *s); + +/* Find the first occurrence of UC in STR. */ +/* Similar to strchr(), wcschr(). */ +extern uint8_t * + u8_strchr (const uint8_t *str, ucs4_t uc) + _UC_ATTRIBUTE_PURE; +extern uint16_t * + u16_strchr (const uint16_t *str, ucs4_t uc) + _UC_ATTRIBUTE_PURE; +extern uint32_t * + u32_strchr (const uint32_t *str, ucs4_t uc) + _UC_ATTRIBUTE_PURE; + +/* Find the last occurrence of UC in STR. */ +/* Similar to strrchr(), wcsrchr(). */ +extern uint8_t * + u8_strrchr (const uint8_t *str, ucs4_t uc) + _UC_ATTRIBUTE_PURE; +extern uint16_t * + u16_strrchr (const uint16_t *str, ucs4_t uc) + _UC_ATTRIBUTE_PURE; +extern uint32_t * + u32_strrchr (const uint32_t *str, ucs4_t uc) + _UC_ATTRIBUTE_PURE; + +/* Return the length of the initial segment of STR which consists entirely + of Unicode characters not in REJECT. */ +/* Similar to strcspn(), wcscspn(). */ +extern size_t + u8_strcspn (const uint8_t *str, const uint8_t *reject) + _UC_ATTRIBUTE_PURE; +extern size_t + u16_strcspn (const uint16_t *str, const uint16_t *reject) + _UC_ATTRIBUTE_PURE; +extern size_t + u32_strcspn (const uint32_t *str, const uint32_t *reject) + _UC_ATTRIBUTE_PURE; + +/* Return the length of the initial segment of STR which consists entirely + of Unicode characters in ACCEPT. */ +/* Similar to strspn(), wcsspn(). */ +extern size_t + u8_strspn (const uint8_t *str, const uint8_t *accept) + _UC_ATTRIBUTE_PURE; +extern size_t + u16_strspn (const uint16_t *str, const uint16_t *accept) + _UC_ATTRIBUTE_PURE; +extern size_t + u32_strspn (const uint32_t *str, const uint32_t *accept) + _UC_ATTRIBUTE_PURE; + +/* Find the first occurrence in STR of any character in ACCEPT. */ +/* Similar to strpbrk(), wcspbrk(). */ +extern uint8_t * + u8_strpbrk (const uint8_t *str, const uint8_t *accept) + _UC_ATTRIBUTE_PURE; +extern uint16_t * + u16_strpbrk (const uint16_t *str, const uint16_t *accept) + _UC_ATTRIBUTE_PURE; +extern uint32_t * + u32_strpbrk (const uint32_t *str, const uint32_t *accept) + _UC_ATTRIBUTE_PURE; + +/* Find the first occurrence of NEEDLE in HAYSTACK. */ +/* Similar to strstr(), wcsstr(). */ +extern uint8_t * + u8_strstr (const uint8_t *haystack, const uint8_t *needle) + _UC_ATTRIBUTE_PURE; +extern uint16_t * + u16_strstr (const uint16_t *haystack, const uint16_t *needle) + _UC_ATTRIBUTE_PURE; +extern uint32_t * + u32_strstr (const uint32_t *haystack, const uint32_t *needle) + _UC_ATTRIBUTE_PURE; + +/* Test whether STR starts with PREFIX. */ +extern bool + u8_startswith (const uint8_t *str, const uint8_t *prefix) + _UC_ATTRIBUTE_PURE; +extern bool + u16_startswith (const uint16_t *str, const uint16_t *prefix) + _UC_ATTRIBUTE_PURE; +extern bool + u32_startswith (const uint32_t *str, const uint32_t *prefix) + _UC_ATTRIBUTE_PURE; + +/* Test whether STR ends with SUFFIX. */ +extern bool + u8_endswith (const uint8_t *str, const uint8_t *suffix) + _UC_ATTRIBUTE_PURE; +extern bool + u16_endswith (const uint16_t *str, const uint16_t *suffix) + _UC_ATTRIBUTE_PURE; +extern bool + u32_endswith (const uint32_t *str, const uint32_t *suffix) + _UC_ATTRIBUTE_PURE; + +/* Divide STR into tokens separated by characters in DELIM. + This interface is actually more similar to wcstok than to strtok. */ +/* Similar to strtok_r(), wcstok(). */ +extern uint8_t * + u8_strtok (uint8_t *str, const uint8_t *delim, uint8_t **ptr); +extern uint16_t * + u16_strtok (uint16_t *str, const uint16_t *delim, uint16_t **ptr); +extern uint32_t * + u32_strtok (uint32_t *str, const uint32_t *delim, uint32_t **ptr); + + +#ifdef __cplusplus +} +#endif + +#endif /* _UNISTR_H */ diff --git a/gettext-tools/gnulib-lib/unistr/u16-mbtouc-aux.c b/gettext-tools/gnulib-lib/unistr/u16-mbtouc-aux.c new file mode 100644 index 0000000..9f68c29 --- /dev/null +++ b/gettext-tools/gnulib-lib/unistr/u16-mbtouc-aux.c @@ -0,0 +1,51 @@ +/* Conversion UTF-16 to UCS-4. + Copyright (C) 2001-2002, 2006-2007, 2009-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2001. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include "unistr.h" + +#if defined IN_LIBUNISTRING || HAVE_INLINE + +int +u16_mbtouc_aux (ucs4_t *puc, const uint16_t *s, size_t n) +{ + uint16_t c = *s; + + if (c < 0xdc00) + { + if (n >= 2) + { + if (s[1] >= 0xdc00 && s[1] < 0xe000) + { + *puc = 0x10000 + ((c - 0xd800) << 10) + (s[1] - 0xdc00); + return 2; + } + /* invalid multibyte character */ + } + else + { + /* incomplete multibyte character */ + } + } + /* invalid multibyte character */ + *puc = 0xfffd; + return 1; +} + +#endif diff --git a/gettext-tools/gnulib-lib/unistr/u16-mbtouc.c b/gettext-tools/gnulib-lib/unistr/u16-mbtouc.c new file mode 100644 index 0000000..d0b3dec --- /dev/null +++ b/gettext-tools/gnulib-lib/unistr/u16-mbtouc.c @@ -0,0 +1,61 @@ +/* Look at first character in UTF-16 string. + Copyright (C) 1999-2002, 2006-2007, 2009-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2001. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +#if defined IN_LIBUNISTRING +/* Tell unistr.h to declare u16_mbtouc as 'extern', not 'static inline'. */ +# include "unistring-notinline.h" +#endif + +/* Specification. */ +#include "unistr.h" + +#if !HAVE_INLINE + +int +u16_mbtouc (ucs4_t *puc, const uint16_t *s, size_t n) +{ + uint16_t c = *s; + + if (c < 0xd800 || c >= 0xe000) + { + *puc = c; + return 1; + } + if (c < 0xdc00) + { + if (n >= 2) + { + if (s[1] >= 0xdc00 && s[1] < 0xe000) + { + *puc = 0x10000 + ((c - 0xd800) << 10) + (s[1] - 0xdc00); + return 2; + } + /* invalid multibyte character */ + } + else + { + /* incomplete multibyte character */ + } + } + /* invalid multibyte character */ + *puc = 0xfffd; + return 1; +} + +#endif diff --git a/gettext-tools/gnulib-lib/unistr/u8-check.c b/gettext-tools/gnulib-lib/unistr/u8-check.c new file mode 100644 index 0000000..818b2e1 --- /dev/null +++ b/gettext-tools/gnulib-lib/unistr/u8-check.c @@ -0,0 +1,105 @@ +/* Check UTF-8 string. + Copyright (C) 2002, 2006-2007, 2009-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2002. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include "unistr.h" + +const uint8_t * +u8_check (const uint8_t *s, size_t n) +{ + const uint8_t *s_end = s + n; + + while (s < s_end) + { + /* Keep in sync with unistr.h and u8-mbtouc-aux.c. */ + uint8_t c = *s; + + if (c < 0x80) + { + s++; + continue; + } + if (c >= 0xc2) + { + if (c < 0xe0) + { + if (s + 2 <= s_end + && (s[1] ^ 0x80) < 0x40) + { + s += 2; + continue; + } + } + else if (c < 0xf0) + { + if (s + 3 <= s_end + && (s[1] ^ 0x80) < 0x40 && (s[2] ^ 0x80) < 0x40 + && (c >= 0xe1 || s[1] >= 0xa0) + && (c != 0xed || s[1] < 0xa0)) + { + s += 3; + continue; + } + } + else if (c < 0xf8) + { + if (s + 4 <= s_end + && (s[1] ^ 0x80) < 0x40 && (s[2] ^ 0x80) < 0x40 + && (s[3] ^ 0x80) < 0x40 + && (c >= 0xf1 || s[1] >= 0x90) +#if 1 + && (c < 0xf4 || (c == 0xf4 && s[1] < 0x90)) +#endif + ) + { + s += 4; + continue; + } + } +#if 0 + else if (c < 0xfc) + { + if (s + 5 <= s_end + && (s[1] ^ 0x80) < 0x40 && (s[2] ^ 0x80) < 0x40 + && (s[3] ^ 0x80) < 0x40 && (s[4] ^ 0x80) < 0x40 + && (c >= 0xf9 || s[1] >= 0x88)) + { + s += 5; + continue; + } + } + else if (c < 0xfe) + { + if (s + 6 <= s_end + && (s[1] ^ 0x80) < 0x40 && (s[2] ^ 0x80) < 0x40 + && (s[3] ^ 0x80) < 0x40 && (s[4] ^ 0x80) < 0x40 + && (s[5] ^ 0x80) < 0x40 + && (c >= 0xfd || s[1] >= 0x84)) + { + s += 6; + continue; + } + } +#endif + } + /* invalid or incomplete multibyte character */ + return s; + } + return NULL; +} diff --git a/gettext-tools/gnulib-lib/unistr/u8-mblen.c b/gettext-tools/gnulib-lib/unistr/u8-mblen.c new file mode 100644 index 0000000..05e2cef --- /dev/null +++ b/gettext-tools/gnulib-lib/unistr/u8-mblen.c @@ -0,0 +1,99 @@ +/* Look at first character in UTF-8 string. + Copyright (C) 1999-2000, 2002, 2006-2007, 2009-2014 Free Software + Foundation, Inc. + Written by Bruno Haible , 2002. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include "unistr.h" + +int +u8_mblen (const uint8_t *s, size_t n) +{ + if (n > 0) + { + /* Keep in sync with unistr.h and u8-mbtouc-aux.c. */ + uint8_t c = *s; + + if (c < 0x80) + return (c != 0 ? 1 : 0); + if (c >= 0xc2) + { + if (c < 0xe0) + { + if (n >= 2 +#if CONFIG_UNICODE_SAFETY + && (s[1] ^ 0x80) < 0x40 +#endif + ) + return 2; + } + else if (c < 0xf0) + { + if (n >= 3 +#if CONFIG_UNICODE_SAFETY + && (s[1] ^ 0x80) < 0x40 && (s[2] ^ 0x80) < 0x40 + && (c >= 0xe1 || s[1] >= 0xa0) + && (c != 0xed || s[1] < 0xa0) +#endif + ) + return 3; + } + else if (c < 0xf8) + { + if (n >= 4 +#if CONFIG_UNICODE_SAFETY + && (s[1] ^ 0x80) < 0x40 && (s[2] ^ 0x80) < 0x40 + && (s[3] ^ 0x80) < 0x40 + && (c >= 0xf1 || s[1] >= 0x90) +#if 1 + && (c < 0xf4 || (c == 0xf4 && s[1] < 0x90)) +#endif +#endif + ) + return 4; + } +#if 0 + else if (c < 0xfc) + { + if (n >= 5 +#if CONFIG_UNICODE_SAFETY + && (s[1] ^ 0x80) < 0x40 && (s[2] ^ 0x80) < 0x40 + && (s[3] ^ 0x80) < 0x40 && (s[4] ^ 0x80) < 0x40 + && (c >= 0xf9 || s[1] >= 0x88) +#endif + ) + return 5; + } + else if (c < 0xfe) + { + if (n >= 6 +#if CONFIG_UNICODE_SAFETY + && (s[1] ^ 0x80) < 0x40 && (s[2] ^ 0x80) < 0x40 + && (s[3] ^ 0x80) < 0x40 && (s[4] ^ 0x80) < 0x40 + && (s[5] ^ 0x80) < 0x40 + && (c >= 0xfd || s[1] >= 0x84) +#endif + ) + return 6; + } +#endif + } + } + /* invalid or incomplete multibyte character */ + return -1; +} diff --git a/gettext-tools/gnulib-lib/unistr/u8-mbtouc-aux.c b/gettext-tools/gnulib-lib/unistr/u8-mbtouc-aux.c new file mode 100644 index 0000000..c6f4245 --- /dev/null +++ b/gettext-tools/gnulib-lib/unistr/u8-mbtouc-aux.c @@ -0,0 +1,240 @@ +/* Conversion UTF-8 to UCS-4. + Copyright (C) 2001-2002, 2006-2007, 2009-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2001. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include "unistr.h" + +#if defined IN_LIBUNISTRING || HAVE_INLINE + +int +u8_mbtouc_aux (ucs4_t *puc, const uint8_t *s, size_t n) +{ + uint8_t c = *s; + + if (c >= 0xc2) + { + if (c < 0xe0) + { + if (n >= 2) + { + if ((s[1] ^ 0x80) < 0x40) + { + *puc = ((unsigned int) (c & 0x1f) << 6) + | (unsigned int) (s[1] ^ 0x80); + return 2; + } + /* invalid multibyte character */ + } + else + { + /* incomplete multibyte character */ + *puc = 0xfffd; + return 1; + } + } + else if (c < 0xf0) + { + if (n >= 3) + { + if ((s[1] ^ 0x80) < 0x40) + { + if ((s[2] ^ 0x80) < 0x40) + { + if ((c >= 0xe1 || s[1] >= 0xa0) + && (c != 0xed || s[1] < 0xa0)) + { + *puc = ((unsigned int) (c & 0x0f) << 12) + | ((unsigned int) (s[1] ^ 0x80) << 6) + | (unsigned int) (s[2] ^ 0x80); + return 3; + } + /* invalid multibyte character */ + *puc = 0xfffd; + return 3; + } + /* invalid multibyte character */ + *puc = 0xfffd; + return 2; + } + /* invalid multibyte character */ + } + else + { + /* incomplete multibyte character */ + *puc = 0xfffd; + if (n == 1 || (s[1] ^ 0x80) >= 0x40) + return 1; + else + return 2; + } + } + else if (c < 0xf8) + { + if (n >= 4) + { + if ((s[1] ^ 0x80) < 0x40) + { + if ((s[2] ^ 0x80) < 0x40) + { + if ((s[3] ^ 0x80) < 0x40) + { + if ((c >= 0xf1 || s[1] >= 0x90) +#if 1 + && (c < 0xf4 || (c == 0xf4 && s[1] < 0x90)) +#endif + ) + { + *puc = ((unsigned int) (c & 0x07) << 18) + | ((unsigned int) (s[1] ^ 0x80) << 12) + | ((unsigned int) (s[2] ^ 0x80) << 6) + | (unsigned int) (s[3] ^ 0x80); + return 4; + } + /* invalid multibyte character */ + *puc = 0xfffd; + return 4; + } + /* invalid multibyte character */ + *puc = 0xfffd; + return 3; + } + /* invalid multibyte character */ + *puc = 0xfffd; + return 2; + } + /* invalid multibyte character */ + } + else + { + /* incomplete multibyte character */ + *puc = 0xfffd; + if (n == 1 || (s[1] ^ 0x80) >= 0x40) + return 1; + else if (n == 2 || (s[2] ^ 0x80) >= 0x40) + return 2; + else + return 3; + } + } +#if 0 + else if (c < 0xfc) + { + if (n >= 5) + { + if ((s[1] ^ 0x80) < 0x40) + { + if ((s[2] ^ 0x80) < 0x40) + { + if ((s[3] ^ 0x80) < 0x40) + { + if ((s[4] ^ 0x80) < 0x40) + { + if (c >= 0xf9 || s[1] >= 0x88) + { + *puc = ((unsigned int) (c & 0x03) << 24) + | ((unsigned int) (s[1] ^ 0x80) << 18) + | ((unsigned int) (s[2] ^ 0x80) << 12) + | ((unsigned int) (s[3] ^ 0x80) << 6) + | (unsigned int) (s[4] ^ 0x80); + return 5; + } + /* invalid multibyte character */ + *puc = 0xfffd; + return 5; + } + /* invalid multibyte character */ + *puc = 0xfffd; + return 4; + } + /* invalid multibyte character */ + *puc = 0xfffd; + return 3; + } + /* invalid multibyte character */ + return 2; + } + /* invalid multibyte character */ + } + else + { + /* incomplete multibyte character */ + *puc = 0xfffd; + return n; + } + } + else if (c < 0xfe) + { + if (n >= 6) + { + if ((s[1] ^ 0x80) < 0x40) + { + if ((s[2] ^ 0x80) < 0x40) + { + if ((s[3] ^ 0x80) < 0x40) + { + if ((s[4] ^ 0x80) < 0x40) + { + if ((s[5] ^ 0x80) < 0x40) + { + if (c >= 0xfd || s[1] >= 0x84) + { + *puc = ((unsigned int) (c & 0x01) << 30) + | ((unsigned int) (s[1] ^ 0x80) << 24) + | ((unsigned int) (s[2] ^ 0x80) << 18) + | ((unsigned int) (s[3] ^ 0x80) << 12) + | ((unsigned int) (s[4] ^ 0x80) << 6) + | (unsigned int) (s[5] ^ 0x80); + return 6; + } + /* invalid multibyte character */ + *puc = 0xfffd; + return 6; + } + /* invalid multibyte character */ + *puc = 0xfffd; + return 5; + } + /* invalid multibyte character */ + *puc = 0xfffd; + return 4; + } + /* invalid multibyte character */ + *puc = 0xfffd; + return 3; + } + /* invalid multibyte character */ + return 2; + } + /* invalid multibyte character */ + } + else + { + /* incomplete multibyte character */ + *puc = 0xfffd; + return n; + } + } +#endif + } + /* invalid multibyte character */ + *puc = 0xfffd; + return 1; +} + +#endif diff --git a/gettext-tools/gnulib-lib/unistr/u8-mbtouc-unsafe-aux.c b/gettext-tools/gnulib-lib/unistr/u8-mbtouc-unsafe-aux.c new file mode 100644 index 0000000..f60b37e --- /dev/null +++ b/gettext-tools/gnulib-lib/unistr/u8-mbtouc-unsafe-aux.c @@ -0,0 +1,260 @@ +/* Conversion UTF-8 to UCS-4. + Copyright (C) 2001-2002, 2006-2007, 2009-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2001. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include "unistr.h" + +#if defined IN_LIBUNISTRING || HAVE_INLINE + +int +u8_mbtouc_unsafe_aux (ucs4_t *puc, const uint8_t *s, size_t n) +{ + uint8_t c = *s; + + if (c >= 0xc2) + { + if (c < 0xe0) + { + if (n >= 2) + { +#if CONFIG_UNICODE_SAFETY + if ((s[1] ^ 0x80) < 0x40) +#endif + { + *puc = ((unsigned int) (c & 0x1f) << 6) + | (unsigned int) (s[1] ^ 0x80); + return 2; + } +#if CONFIG_UNICODE_SAFETY + /* invalid multibyte character */ +#endif + } + else + { + /* incomplete multibyte character */ + *puc = 0xfffd; + return 1; + } + } + else if (c < 0xf0) + { + if (n >= 3) + { +#if CONFIG_UNICODE_SAFETY + if ((s[1] ^ 0x80) < 0x40) + { + if ((s[2] ^ 0x80) < 0x40) + { + if ((c >= 0xe1 || s[1] >= 0xa0) + && (c != 0xed || s[1] < 0xa0)) +#endif + { + *puc = ((unsigned int) (c & 0x0f) << 12) + | ((unsigned int) (s[1] ^ 0x80) << 6) + | (unsigned int) (s[2] ^ 0x80); + return 3; + } +#if CONFIG_UNICODE_SAFETY + /* invalid multibyte character */ + *puc = 0xfffd; + return 3; + } + /* invalid multibyte character */ + *puc = 0xfffd; + return 2; + } + /* invalid multibyte character */ +#endif + } + else + { + /* incomplete multibyte character */ + *puc = 0xfffd; + if (n == 1 || (s[1] ^ 0x80) >= 0x40) + return 1; + else + return 2; + } + } + else if (c < 0xf8) + { + if (n >= 4) + { +#if CONFIG_UNICODE_SAFETY + if ((s[1] ^ 0x80) < 0x40) + { + if ((s[2] ^ 0x80) < 0x40) + { + if ((s[3] ^ 0x80) < 0x40) + { + if ((c >= 0xf1 || s[1] >= 0x90) +#if 1 + && (c < 0xf4 || (c == 0xf4 && s[1] < 0x90)) +#endif + ) +#endif + { + *puc = ((unsigned int) (c & 0x07) << 18) + | ((unsigned int) (s[1] ^ 0x80) << 12) + | ((unsigned int) (s[2] ^ 0x80) << 6) + | (unsigned int) (s[3] ^ 0x80); + return 4; + } +#if CONFIG_UNICODE_SAFETY + /* invalid multibyte character */ + *puc = 0xfffd; + return 4; + } + /* invalid multibyte character */ + *puc = 0xfffd; + return 3; + } + /* invalid multibyte character */ + *puc = 0xfffd; + return 2; + } + /* invalid multibyte character */ +#endif + } + else + { + /* incomplete multibyte character */ + *puc = 0xfffd; + if (n == 1 || (s[1] ^ 0x80) >= 0x40) + return 1; + else if (n == 2 || (s[2] ^ 0x80) >= 0x40) + return 2; + else + return 3; + } + } +#if 0 + else if (c < 0xfc) + { + if (n >= 5) + { +#if CONFIG_UNICODE_SAFETY + if ((s[1] ^ 0x80) < 0x40) + { + if ((s[2] ^ 0x80) < 0x40) + { + if ((s[3] ^ 0x80) < 0x40) + { + if ((s[4] ^ 0x80) < 0x40) + { + if (c >= 0xf9 || s[1] >= 0x88) +#endif + { + *puc = ((unsigned int) (c & 0x03) << 24) + | ((unsigned int) (s[1] ^ 0x80) << 18) + | ((unsigned int) (s[2] ^ 0x80) << 12) + | ((unsigned int) (s[3] ^ 0x80) << 6) + | (unsigned int) (s[4] ^ 0x80); + return 5; + } +#if CONFIG_UNICODE_SAFETY + /* invalid multibyte character */ + *puc = 0xfffd; + return 5; + } + /* invalid multibyte character */ + *puc = 0xfffd; + return 4; + } + /* invalid multibyte character */ + *puc = 0xfffd; + return 3; + } + /* invalid multibyte character */ + return 2; + } + /* invalid multibyte character */ +#endif + } + else + { + /* incomplete multibyte character */ + *puc = 0xfffd; + return n; + } + } + else if (c < 0xfe) + { + if (n >= 6) + { +#if CONFIG_UNICODE_SAFETY + if ((s[1] ^ 0x80) < 0x40) + { + if ((s[2] ^ 0x80) < 0x40) + { + if ((s[3] ^ 0x80) < 0x40) + { + if ((s[4] ^ 0x80) < 0x40) + { + if ((s[5] ^ 0x80) < 0x40) + { + if (c >= 0xfd || s[1] >= 0x84) +#endif + { + *puc = ((unsigned int) (c & 0x01) << 30) + | ((unsigned int) (s[1] ^ 0x80) << 24) + | ((unsigned int) (s[2] ^ 0x80) << 18) + | ((unsigned int) (s[3] ^ 0x80) << 12) + | ((unsigned int) (s[4] ^ 0x80) << 6) + | (unsigned int) (s[5] ^ 0x80); + return 6; + } +#if CONFIG_UNICODE_SAFETY + /* invalid multibyte character */ + *puc = 0xfffd; + return 6; + } + /* invalid multibyte character */ + *puc = 0xfffd; + return 5; + } + /* invalid multibyte character */ + *puc = 0xfffd; + return 4; + } + /* invalid multibyte character */ + *puc = 0xfffd; + return 3; + } + /* invalid multibyte character */ + return 2; + } + /* invalid multibyte character */ +#endif + } + else + { + /* incomplete multibyte character */ + *puc = 0xfffd; + return n; + } + } +#endif + } + /* invalid multibyte character */ + *puc = 0xfffd; + return 1; +} + +#endif diff --git a/gettext-tools/gnulib-lib/unistr/u8-mbtouc-unsafe.c b/gettext-tools/gnulib-lib/unistr/u8-mbtouc-unsafe.c new file mode 100644 index 0000000..18040b5 --- /dev/null +++ b/gettext-tools/gnulib-lib/unistr/u8-mbtouc-unsafe.c @@ -0,0 +1,271 @@ +/* Look at first character in UTF-8 string. + Copyright (C) 1999-2002, 2006-2007, 2009-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2001. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +#if defined IN_LIBUNISTRING +/* Tell unistr.h to declare u8_mbtouc_unsafe as 'extern', not + 'static inline'. */ +# include "unistring-notinline.h" +#endif + +/* Specification. */ +#include "unistr.h" + +#if !HAVE_INLINE + +int +u8_mbtouc_unsafe (ucs4_t *puc, const uint8_t *s, size_t n) +{ + uint8_t c = *s; + + if (c < 0x80) + { + *puc = c; + return 1; + } + else if (c >= 0xc2) + { + if (c < 0xe0) + { + if (n >= 2) + { +#if CONFIG_UNICODE_SAFETY + if ((s[1] ^ 0x80) < 0x40) +#endif + { + *puc = ((unsigned int) (c & 0x1f) << 6) + | (unsigned int) (s[1] ^ 0x80); + return 2; + } +#if CONFIG_UNICODE_SAFETY + /* invalid multibyte character */ +#endif + } + else + { + /* incomplete multibyte character */ + *puc = 0xfffd; + return 1; + } + } + else if (c < 0xf0) + { + if (n >= 3) + { +#if CONFIG_UNICODE_SAFETY + if ((s[1] ^ 0x80) < 0x40) + { + if ((s[2] ^ 0x80) < 0x40) + { + if ((c >= 0xe1 || s[1] >= 0xa0) + && (c != 0xed || s[1] < 0xa0)) +#endif + { + *puc = ((unsigned int) (c & 0x0f) << 12) + | ((unsigned int) (s[1] ^ 0x80) << 6) + | (unsigned int) (s[2] ^ 0x80); + return 3; + } +#if CONFIG_UNICODE_SAFETY + /* invalid multibyte character */ + *puc = 0xfffd; + return 3; + } + /* invalid multibyte character */ + *puc = 0xfffd; + return 2; + } + /* invalid multibyte character */ +#endif + } + else + { + /* incomplete multibyte character */ + *puc = 0xfffd; + if (n == 1 || (s[1] ^ 0x80) >= 0x40) + return 1; + else + return 2; + } + } + else if (c < 0xf8) + { + if (n >= 4) + { +#if CONFIG_UNICODE_SAFETY + if ((s[1] ^ 0x80) < 0x40) + { + if ((s[2] ^ 0x80) < 0x40) + { + if ((s[3] ^ 0x80) < 0x40) + { + if ((c >= 0xf1 || s[1] >= 0x90) +#if 1 + && (c < 0xf4 || (c == 0xf4 && s[1] < 0x90)) +#endif + ) +#endif + { + *puc = ((unsigned int) (c & 0x07) << 18) + | ((unsigned int) (s[1] ^ 0x80) << 12) + | ((unsigned int) (s[2] ^ 0x80) << 6) + | (unsigned int) (s[3] ^ 0x80); + return 4; + } +#if CONFIG_UNICODE_SAFETY + /* invalid multibyte character */ + *puc = 0xfffd; + return 4; + } + /* invalid multibyte character */ + *puc = 0xfffd; + return 3; + } + /* invalid multibyte character */ + *puc = 0xfffd; + return 2; + } + /* invalid multibyte character */ +#endif + } + else + { + /* incomplete multibyte character */ + *puc = 0xfffd; + if (n == 1 || (s[1] ^ 0x80) >= 0x40) + return 1; + else if (n == 2 || (s[2] ^ 0x80) >= 0x40) + return 2; + else + return 3; + } + } +#if 0 + else if (c < 0xfc) + { + if (n >= 5) + { +#if CONFIG_UNICODE_SAFETY + if ((s[1] ^ 0x80) < 0x40) + { + if ((s[2] ^ 0x80) < 0x40) + { + if ((s[3] ^ 0x80) < 0x40) + { + if ((s[4] ^ 0x80) < 0x40) + { + if (c >= 0xf9 || s[1] >= 0x88) +#endif + { + *puc = ((unsigned int) (c & 0x03) << 24) + | ((unsigned int) (s[1] ^ 0x80) << 18) + | ((unsigned int) (s[2] ^ 0x80) << 12) + | ((unsigned int) (s[3] ^ 0x80) << 6) + | (unsigned int) (s[4] ^ 0x80); + return 5; + } +#if CONFIG_UNICODE_SAFETY + /* invalid multibyte character */ + *puc = 0xfffd; + return 5; + } + /* invalid multibyte character */ + *puc = 0xfffd; + return 4; + } + /* invalid multibyte character */ + *puc = 0xfffd; + return 3; + } + /* invalid multibyte character */ + return 2; + } + /* invalid multibyte character */ +#endif + } + else + { + /* incomplete multibyte character */ + *puc = 0xfffd; + return n; + } + } + else if (c < 0xfe) + { + if (n >= 6) + { +#if CONFIG_UNICODE_SAFETY + if ((s[1] ^ 0x80) < 0x40) + { + if ((s[2] ^ 0x80) < 0x40) + { + if ((s[3] ^ 0x80) < 0x40) + { + if ((s[4] ^ 0x80) < 0x40) + { + if ((s[5] ^ 0x80) < 0x40) + { + if (c >= 0xfd || s[1] >= 0x84) +#endif + { + *puc = ((unsigned int) (c & 0x01) << 30) + | ((unsigned int) (s[1] ^ 0x80) << 24) + | ((unsigned int) (s[2] ^ 0x80) << 18) + | ((unsigned int) (s[3] ^ 0x80) << 12) + | ((unsigned int) (s[4] ^ 0x80) << 6) + | (unsigned int) (s[5] ^ 0x80); + return 6; + } +#if CONFIG_UNICODE_SAFETY + /* invalid multibyte character */ + *puc = 0xfffd; + return 6; + } + /* invalid multibyte character */ + *puc = 0xfffd; + return 5; + } + /* invalid multibyte character */ + *puc = 0xfffd; + return 4; + } + /* invalid multibyte character */ + *puc = 0xfffd; + return 3; + } + /* invalid multibyte character */ + return 2; + } + /* invalid multibyte character */ +#endif + } + else + { + /* incomplete multibyte character */ + *puc = 0xfffd; + return n; + } + } +#endif + } + /* invalid multibyte character */ + *puc = 0xfffd; + return 1; +} + +#endif diff --git a/gettext-tools/gnulib-lib/unistr/u8-mbtouc.c b/gettext-tools/gnulib-lib/unistr/u8-mbtouc.c new file mode 100644 index 0000000..78c8f0e --- /dev/null +++ b/gettext-tools/gnulib-lib/unistr/u8-mbtouc.c @@ -0,0 +1,250 @@ +/* Look at first character in UTF-8 string. + Copyright (C) 1999-2002, 2006-2007, 2009-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2001. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +#if defined IN_LIBUNISTRING +/* Tell unistr.h to declare u8_mbtouc as 'extern', not 'static inline'. */ +# include "unistring-notinline.h" +#endif + +/* Specification. */ +#include "unistr.h" + +#if !HAVE_INLINE + +int +u8_mbtouc (ucs4_t *puc, const uint8_t *s, size_t n) +{ + uint8_t c = *s; + + if (c < 0x80) + { + *puc = c; + return 1; + } + else if (c >= 0xc2) + { + if (c < 0xe0) + { + if (n >= 2) + { + if ((s[1] ^ 0x80) < 0x40) + { + *puc = ((unsigned int) (c & 0x1f) << 6) + | (unsigned int) (s[1] ^ 0x80); + return 2; + } + /* invalid multibyte character */ + } + else + { + /* incomplete multibyte character */ + *puc = 0xfffd; + return 1; + } + } + else if (c < 0xf0) + { + if (n >= 3) + { + if ((s[1] ^ 0x80) < 0x40) + { + if ((s[2] ^ 0x80) < 0x40) + { + if ((c >= 0xe1 || s[1] >= 0xa0) + && (c != 0xed || s[1] < 0xa0)) + { + *puc = ((unsigned int) (c & 0x0f) << 12) + | ((unsigned int) (s[1] ^ 0x80) << 6) + | (unsigned int) (s[2] ^ 0x80); + return 3; + } + /* invalid multibyte character */ + *puc = 0xfffd; + return 3; + } + /* invalid multibyte character */ + *puc = 0xfffd; + return 2; + } + /* invalid multibyte character */ + } + else + { + /* incomplete multibyte character */ + *puc = 0xfffd; + if (n == 1 || (s[1] ^ 0x80) >= 0x40) + return 1; + else + return 2; + } + } + else if (c < 0xf8) + { + if (n >= 4) + { + if ((s[1] ^ 0x80) < 0x40) + { + if ((s[2] ^ 0x80) < 0x40) + { + if ((s[3] ^ 0x80) < 0x40) + { + if ((c >= 0xf1 || s[1] >= 0x90) +#if 1 + && (c < 0xf4 || (c == 0xf4 && s[1] < 0x90)) +#endif + ) + { + *puc = ((unsigned int) (c & 0x07) << 18) + | ((unsigned int) (s[1] ^ 0x80) << 12) + | ((unsigned int) (s[2] ^ 0x80) << 6) + | (unsigned int) (s[3] ^ 0x80); + return 4; + } + /* invalid multibyte character */ + *puc = 0xfffd; + return 4; + } + /* invalid multibyte character */ + *puc = 0xfffd; + return 3; + } + /* invalid multibyte character */ + *puc = 0xfffd; + return 2; + } + /* invalid multibyte character */ + } + else + { + /* incomplete multibyte character */ + *puc = 0xfffd; + if (n == 1 || (s[1] ^ 0x80) >= 0x40) + return 1; + else if (n == 2 || (s[2] ^ 0x80) >= 0x40) + return 2; + else + return 3; + } + } +#if 0 + else if (c < 0xfc) + { + if (n >= 5) + { + if ((s[1] ^ 0x80) < 0x40) + { + if ((s[2] ^ 0x80) < 0x40) + { + if ((s[3] ^ 0x80) < 0x40) + { + if ((s[4] ^ 0x80) < 0x40) + { + if (c >= 0xf9 || s[1] >= 0x88) + { + *puc = ((unsigned int) (c & 0x03) << 24) + | ((unsigned int) (s[1] ^ 0x80) << 18) + | ((unsigned int) (s[2] ^ 0x80) << 12) + | ((unsigned int) (s[3] ^ 0x80) << 6) + | (unsigned int) (s[4] ^ 0x80); + return 5; + } + /* invalid multibyte character */ + *puc = 0xfffd; + return 5; + } + /* invalid multibyte character */ + *puc = 0xfffd; + return 4; + } + /* invalid multibyte character */ + *puc = 0xfffd; + return 3; + } + /* invalid multibyte character */ + return 2; + } + /* invalid multibyte character */ + } + else + { + /* incomplete multibyte character */ + *puc = 0xfffd; + return n; + } + } + else if (c < 0xfe) + { + if (n >= 6) + { + if ((s[1] ^ 0x80) < 0x40) + { + if ((s[2] ^ 0x80) < 0x40) + { + if ((s[3] ^ 0x80) < 0x40) + { + if ((s[4] ^ 0x80) < 0x40) + { + if ((s[5] ^ 0x80) < 0x40) + { + if (c >= 0xfd || s[1] >= 0x84) + { + *puc = ((unsigned int) (c & 0x01) << 30) + | ((unsigned int) (s[1] ^ 0x80) << 24) + | ((unsigned int) (s[2] ^ 0x80) << 18) + | ((unsigned int) (s[3] ^ 0x80) << 12) + | ((unsigned int) (s[4] ^ 0x80) << 6) + | (unsigned int) (s[5] ^ 0x80); + return 6; + } + /* invalid multibyte character */ + *puc = 0xfffd; + return 6; + } + /* invalid multibyte character */ + *puc = 0xfffd; + return 5; + } + /* invalid multibyte character */ + *puc = 0xfffd; + return 4; + } + /* invalid multibyte character */ + *puc = 0xfffd; + return 3; + } + /* invalid multibyte character */ + return 2; + } + /* invalid multibyte character */ + } + else + { + /* incomplete multibyte character */ + *puc = 0xfffd; + return n; + } + } +#endif + } + /* invalid multibyte character */ + *puc = 0xfffd; + return 1; +} + +#endif diff --git a/gettext-tools/gnulib-lib/unistr/u8-mbtoucr.c b/gettext-tools/gnulib-lib/unistr/u8-mbtoucr.c new file mode 100644 index 0000000..b11543a --- /dev/null +++ b/gettext-tools/gnulib-lib/unistr/u8-mbtoucr.c @@ -0,0 +1,285 @@ +/* Look at first character in UTF-8 string, returning an error code. + Copyright (C) 1999-2002, 2006-2007, 2009-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2001. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include "unistr.h" + +int +u8_mbtoucr (ucs4_t *puc, const uint8_t *s, size_t n) +{ + uint8_t c = *s; + + if (c < 0x80) + { + *puc = c; + return 1; + } + else if (c >= 0xc2) + { + if (c < 0xe0) + { + if (n >= 2) + { + if ((s[1] ^ 0x80) < 0x40) + { + *puc = ((unsigned int) (c & 0x1f) << 6) + | (unsigned int) (s[1] ^ 0x80); + return 2; + } + /* invalid multibyte character */ + } + else + { + /* incomplete multibyte character */ + *puc = 0xfffd; + return -2; + } + } + else if (c < 0xf0) + { + if (n >= 2) + { + if ((s[1] ^ 0x80) < 0x40 + && (c >= 0xe1 || s[1] >= 0xa0) + && (c != 0xed || s[1] < 0xa0)) + { + if (n >= 3) + { + if ((s[2] ^ 0x80) < 0x40) + { + *puc = ((unsigned int) (c & 0x0f) << 12) + | ((unsigned int) (s[1] ^ 0x80) << 6) + | (unsigned int) (s[2] ^ 0x80); + return 3; + } + /* invalid multibyte character */ + } + else + { + /* incomplete multibyte character */ + *puc = 0xfffd; + return -2; + } + } + /* invalid multibyte character */ + } + else + { + /* incomplete multibyte character */ + *puc = 0xfffd; + return -2; + } + } + else if (c < 0xf8) + { + if (n >= 2) + { + if ((s[1] ^ 0x80) < 0x40 + && (c >= 0xf1 || s[1] >= 0x90) +#if 1 + && (c < 0xf4 || (c == 0xf4 && s[1] < 0x90)) +#endif + ) + { + if (n >= 3) + { + if ((s[2] ^ 0x80) < 0x40) + { + if (n >= 4) + { + if ((s[3] ^ 0x80) < 0x40) + { + *puc = ((unsigned int) (c & 0x07) << 18) + | ((unsigned int) (s[1] ^ 0x80) << 12) + | ((unsigned int) (s[2] ^ 0x80) << 6) + | (unsigned int) (s[3] ^ 0x80); + return 4; + } + /* invalid multibyte character */ + } + else + { + /* incomplete multibyte character */ + *puc = 0xfffd; + return -2; + } + } + /* invalid multibyte character */ + } + else + { + /* incomplete multibyte character */ + *puc = 0xfffd; + return -2; + } + } + /* invalid multibyte character */ + } + else + { + /* incomplete multibyte character */ + *puc = 0xfffd; + return -2; + } + } +#if 0 + else if (c < 0xfc) + { + if (n >= 2) + { + if ((s[1] ^ 0x80) < 0x40 + && (c >= 0xf9 || s[1] >= 0x88)) + { + if (n >= 3) + { + if ((s[2] ^ 0x80) < 0x40) + { + if (n >= 4) + { + if ((s[3] ^ 0x80) < 0x40) + { + if (n >= 5) + { + if ((s[4] ^ 0x80) < 0x40) + { + *puc = ((unsigned int) (c & 0x03) << 24) + | ((unsigned int) (s[1] ^ 0x80) << 18) + | ((unsigned int) (s[2] ^ 0x80) << 12) + | ((unsigned int) (s[3] ^ 0x80) << 6) + | (unsigned int) (s[4] ^ 0x80); + return 5; + } + /* invalid multibyte character */ + } + else + { + /* incomplete multibyte character */ + *puc = 0xfffd; + return -2; + } + } + /* invalid multibyte character */ + } + else + { + /* incomplete multibyte character */ + *puc = 0xfffd; + return -2; + } + } + /* invalid multibyte character */ + } + else + { + /* incomplete multibyte character */ + *puc = 0xfffd; + return -2; + } + } + /* invalid multibyte character */ + } + else + { + /* incomplete multibyte character */ + *puc = 0xfffd; + return -2; + } + } + else if (c < 0xfe) + { + if (n >= 2) + { + if ((s[1] ^ 0x80) < 0x40 + && (c >= 0xfd || s[1] >= 0x84)) + { + if (n >= 3) + { + if ((s[2] ^ 0x80) < 0x40) + { + if (n >= 4) + { + if ((s[3] ^ 0x80) < 0x40) + { + if (n >= 5) + { + if ((s[4] ^ 0x80) < 0x40) + { + if (n >= 6) + { + if ((s[5] ^ 0x80) < 0x40) + { + *puc = ((unsigned int) (c & 0x01) << 30) + | ((unsigned int) (s[1] ^ 0x80) << 24) + | ((unsigned int) (s[2] ^ 0x80) << 18) + | ((unsigned int) (s[3] ^ 0x80) << 12) + | ((unsigned int) (s[4] ^ 0x80) << 6) + | (unsigned int) (s[5] ^ 0x80); + return 6; + } + /* invalid multibyte character */ + } + else + { + /* incomplete multibyte character */ + *puc = 0xfffd; + return -2; + } + } + /* invalid multibyte character */ + } + else + { + /* incomplete multibyte character */ + *puc = 0xfffd; + return -2; + } + } + /* invalid multibyte character */ + } + else + { + /* incomplete multibyte character */ + *puc = 0xfffd; + return -2; + } + } + /* invalid multibyte character */ + } + else + { + /* incomplete multibyte character */ + *puc = 0xfffd; + return -2; + } + } + /* invalid multibyte character */ + } + else + { + /* incomplete multibyte character */ + *puc = 0xfffd; + return -2; + } + } +#endif + } + /* invalid multibyte character */ + *puc = 0xfffd; + return -1; +} diff --git a/gettext-tools/gnulib-lib/unistr/u8-prev.c b/gettext-tools/gnulib-lib/unistr/u8-prev.c new file mode 100644 index 0000000..6ccdfbd --- /dev/null +++ b/gettext-tools/gnulib-lib/unistr/u8-prev.c @@ -0,0 +1,93 @@ +/* Iterate over previous character in UTF-8 string. + Copyright (C) 2002, 2006-2007, 2009-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2002. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include "unistr.h" + +const uint8_t * +u8_prev (ucs4_t *puc, const uint8_t *s, const uint8_t *start) +{ + /* Keep in sync with unistr.h and u8-mbtouc-aux.c. */ + if (s != start) + { + uint8_t c_1 = s[-1]; + + if (c_1 < 0x80) + { + *puc = c_1; + return s - 1; + } +#if CONFIG_UNICODE_SAFETY + if ((c_1 ^ 0x80) < 0x40) +#endif + if (s - 1 != start) + { + uint8_t c_2 = s[-2]; + + if (c_2 >= 0xc2 && c_2 < 0xe0) + { + *puc = ((unsigned int) (c_2 & 0x1f) << 6) + | (unsigned int) (c_1 ^ 0x80); + return s - 2; + } +#if CONFIG_UNICODE_SAFETY + if ((c_2 ^ 0x80) < 0x40) +#endif + if (s - 2 != start) + { + uint8_t c_3 = s[-3]; + + if (c_3 >= 0xe0 && c_3 < 0xf0 +#if CONFIG_UNICODE_SAFETY + && (c_3 >= 0xe1 || c_2 >= 0xa0) + && (c_3 != 0xed || c_2 < 0xa0) +#endif + ) + { + *puc = ((unsigned int) (c_3 & 0x0f) << 12) + | ((unsigned int) (c_2 ^ 0x80) << 6) + | (unsigned int) (c_1 ^ 0x80); + return s - 3; + } +#if CONFIG_UNICODE_SAFETY + if ((c_3 ^ 0x80) < 0x40) +#endif + if (s - 3 != start) + { + uint8_t c_4 = s[-4]; + + if (c_4 >= 0xf0 && c_4 < 0xf8 +#if CONFIG_UNICODE_SAFETY + && (c_4 >= 0xf1 || c_3 >= 0x90) + && (c_4 < 0xf4 || (c_4 == 0xf4 && c_3 < 0x90)) +#endif + ) + { + *puc = ((unsigned int) (c_4 & 0x07) << 18) + | ((unsigned int) (c_3 ^ 0x80) << 12) + | ((unsigned int) (c_2 ^ 0x80) << 6) + | (unsigned int) (c_1 ^ 0x80); + return s - 4; + } + } + } + } + } + return NULL; +} diff --git a/gettext-tools/gnulib-lib/unistr/u8-uctomb-aux.c b/gettext-tools/gnulib-lib/unistr/u8-uctomb-aux.c new file mode 100644 index 0000000..8fdd88b --- /dev/null +++ b/gettext-tools/gnulib-lib/unistr/u8-uctomb-aux.c @@ -0,0 +1,69 @@ +/* Conversion UCS-4 to UTF-8. + Copyright (C) 2002, 2006-2007, 2009-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2002. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include "unistr.h" + +int +u8_uctomb_aux (uint8_t *s, ucs4_t uc, int n) +{ + int count; + + if (uc < 0x80) + /* The case n >= 1 is already handled by the caller. */ + return -2; + else if (uc < 0x800) + count = 2; + else if (uc < 0x10000) + { + if (uc < 0xd800 || uc >= 0xe000) + count = 3; + else + return -1; + } +#if 0 + else if (uc < 0x200000) + count = 4; + else if (uc < 0x4000000) + count = 5; + else if (uc <= 0x7fffffff) + count = 6; +#else + else if (uc < 0x110000) + count = 4; +#endif + else + return -1; + + if (n < count) + return -2; + + switch (count) /* note: code falls through cases! */ + { +#if 0 + case 6: s[5] = 0x80 | (uc & 0x3f); uc = uc >> 6; uc |= 0x4000000; + case 5: s[4] = 0x80 | (uc & 0x3f); uc = uc >> 6; uc |= 0x200000; +#endif + case 4: s[3] = 0x80 | (uc & 0x3f); uc = uc >> 6; uc |= 0x10000; + case 3: s[2] = 0x80 | (uc & 0x3f); uc = uc >> 6; uc |= 0x800; + case 2: s[1] = 0x80 | (uc & 0x3f); uc = uc >> 6; uc |= 0xc0; + /*case 1:*/ s[0] = uc; + } + return count; +} diff --git a/gettext-tools/gnulib-lib/unistr/u8-uctomb.c b/gettext-tools/gnulib-lib/unistr/u8-uctomb.c new file mode 100644 index 0000000..df9b227 --- /dev/null +++ b/gettext-tools/gnulib-lib/unistr/u8-uctomb.c @@ -0,0 +1,88 @@ +/* Store a character in UTF-8 string. + Copyright (C) 2002, 2005-2006, 2009-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2002. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +#if defined IN_LIBUNISTRING +/* Tell unistr.h to declare u8_uctomb as 'extern', not 'static inline'. */ +# include "unistring-notinline.h" +#endif + +/* Specification. */ +#include "unistr.h" + +#if !HAVE_INLINE + +int +u8_uctomb (uint8_t *s, ucs4_t uc, int n) +{ + if (uc < 0x80) + { + if (n > 0) + { + s[0] = uc; + return 1; + } + /* else return -2, below. */ + } + else + { + int count; + + if (uc < 0x800) + count = 2; + else if (uc < 0x10000) + { + if (uc < 0xd800 || uc >= 0xe000) + count = 3; + else + return -1; + } +#if 0 + else if (uc < 0x200000) + count = 4; + else if (uc < 0x4000000) + count = 5; + else if (uc <= 0x7fffffff) + count = 6; +#else + else if (uc < 0x110000) + count = 4; +#endif + else + return -1; + + if (n >= count) + { + switch (count) /* note: code falls through cases! */ + { +#if 0 + case 6: s[5] = 0x80 | (uc & 0x3f); uc = uc >> 6; uc |= 0x4000000; + case 5: s[4] = 0x80 | (uc & 0x3f); uc = uc >> 6; uc |= 0x200000; +#endif + case 4: s[3] = 0x80 | (uc & 0x3f); uc = uc >> 6; uc |= 0x10000; + case 3: s[2] = 0x80 | (uc & 0x3f); uc = uc >> 6; uc |= 0x800; + case 2: s[1] = 0x80 | (uc & 0x3f); uc = uc >> 6; uc |= 0xc0; + /*case 1:*/ s[0] = uc; + } + return count; + } + } + return -2; +} + +#endif diff --git a/gettext-tools/gnulib-lib/unitypes.in.h b/gettext-tools/gnulib-lib/unitypes.in.h new file mode 100644 index 0000000..bc302c2 --- /dev/null +++ b/gettext-tools/gnulib-lib/unitypes.in.h @@ -0,0 +1,46 @@ +/* Elementary types and macros for the GNU UniString library. + Copyright (C) 2002, 2005-2006, 2009-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _UNITYPES_H +#define _UNITYPES_H + +/* Get uint8_t, uint16_t, uint32_t. */ +#include + +/* Type representing a Unicode character. */ +typedef uint32_t ucs4_t; + +/* Attribute of a function whose result depends only on the arguments + (not pointers!) and which has no side effects. */ +#ifndef _UC_ATTRIBUTE_CONST +# if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95) +# define _UC_ATTRIBUTE_CONST __attribute__ ((__const__)) +# else +# define _UC_ATTRIBUTE_CONST +# endif +#endif + +/* Attribute of a function whose result depends only on the arguments + (possibly pointers) and global memory, and which has no side effects. */ +#ifndef _UC_ATTRIBUTE_PURE +# if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96) +# define _UC_ATTRIBUTE_PURE __attribute__ ((__pure__)) +# else +# define _UC_ATTRIBUTE_PURE +# endif +#endif + +#endif /* _UNITYPES_H */ diff --git a/gettext-tools/gnulib-lib/uniwidth.in.h b/gettext-tools/gnulib-lib/uniwidth.in.h new file mode 100644 index 0000000..b2fd218 --- /dev/null +++ b/gettext-tools/gnulib-lib/uniwidth.in.h @@ -0,0 +1,72 @@ +/* Display width functions. + Copyright (C) 2001-2002, 2005, 2007, 2009-2014 Free Software Foundation, + Inc. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _UNIWIDTH_H +#define _UNIWIDTH_H + +#include "unitypes.h" + +/* Get size_t. */ +#include + +/* Get locale_charset() declaration. */ +#include "localcharset.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Display width. */ + +/* These functions are locale dependent. The encoding argument identifies + the encoding (e.g. "ISO-8859-2" for Polish). */ + +/* Determine number of column positions required for UC. */ +extern int + uc_width (ucs4_t uc, const char *encoding) + _UC_ATTRIBUTE_PURE; + +/* Determine number of column positions required for first N units + (or fewer if S ends before this) in S. */ +extern int + u8_width (const uint8_t *s, size_t n, const char *encoding) + _UC_ATTRIBUTE_PURE; +extern int + u16_width (const uint16_t *s, size_t n, const char *encoding) + _UC_ATTRIBUTE_PURE; +extern int + u32_width (const uint32_t *s, size_t n, const char *encoding) + _UC_ATTRIBUTE_PURE; + +/* Determine number of column positions required for S. */ +extern int + u8_strwidth (const uint8_t *s, const char *encoding) + _UC_ATTRIBUTE_PURE; +extern int + u16_strwidth (const uint16_t *s, const char *encoding) + _UC_ATTRIBUTE_PURE; +extern int + u32_strwidth (const uint32_t *s, const char *encoding) + _UC_ATTRIBUTE_PURE; + + +#ifdef __cplusplus +} +#endif + +#endif /* _UNIWIDTH_H */ diff --git a/gettext-tools/gnulib-lib/uniwidth/cjk.h b/gettext-tools/gnulib-lib/uniwidth/cjk.h new file mode 100644 index 0000000..71ea0cb --- /dev/null +++ b/gettext-tools/gnulib-lib/uniwidth/cjk.h @@ -0,0 +1,37 @@ +/* Test for CJK encoding. + Copyright (C) 2001-2002, 2005-2007, 2009-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2002. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include "streq.h" + +static int +is_cjk_encoding (const char *encoding) +{ + if (0 + /* Legacy Japanese encodings */ + || STREQ_OPT (encoding, "EUC-JP", 'E', 'U', 'C', '-', 'J', 'P', 0, 0, 0) + /* Legacy Chinese encodings */ + || STREQ_OPT (encoding, "GB2312", 'G', 'B', '2', '3', '1', '2', 0, 0, 0) + || STREQ_OPT (encoding, "GBK", 'G', 'B', 'K', 0, 0, 0, 0, 0, 0) + || STREQ_OPT (encoding, "EUC-TW", 'E', 'U', 'C', '-', 'T', 'W', 0, 0, 0) + || STREQ_OPT (encoding, "BIG5", 'B', 'I', 'G', '5', 0, 0, 0, 0, 0) + /* Legacy Korean encodings */ + || STREQ_OPT (encoding, "EUC-KR", 'E', 'U', 'C', '-', 'K', 'R', 0, 0, 0) + || STREQ_OPT (encoding, "CP949", 'C', 'P', '9', '4', '9', 0, 0, 0, 0) + || STREQ_OPT (encoding, "JOHAB", 'J', 'O', 'H', 'A', 'B', 0, 0, 0, 0)) + return 1; + return 0; +} diff --git a/gettext-tools/gnulib-lib/uniwidth/width.c b/gettext-tools/gnulib-lib/uniwidth/width.c new file mode 100644 index 0000000..2c070c3 --- /dev/null +++ b/gettext-tools/gnulib-lib/uniwidth/width.c @@ -0,0 +1,368 @@ +/* Determine display width of Unicode character. + Copyright (C) 2001-2002, 2006-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2002. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include "uniwidth.h" + +#include "cjk.h" + +/* + * Non-spacing attribute table. + * Consists of: + * - Non-spacing characters; generated from PropList.txt or + * "grep '^[^;]*;[^;]*;[^;]*;[^;]*;NSM;' UnicodeData.txt" + * - Format control characters; generated from + * "grep '^[^;]*;[^;]*;Cf;' UnicodeData.txt" + * - Zero width characters; generated from + * "grep '^[^;]*;ZERO WIDTH ' UnicodeData.txt" + */ +static const unsigned char nonspacing_table_data[27*64] = { + /* 0x0000-0x01ff */ + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, /* 0x0000-0x003f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* 0x0040-0x007f */ + 0xff, 0xff, 0xff, 0xff, 0x00, 0x20, 0x00, 0x00, /* 0x0080-0x00bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00c0-0x00ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0100-0x013f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0140-0x017f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0180-0x01bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x01c0-0x01ff */ + /* 0x0200-0x03ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0200-0x023f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0240-0x027f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0280-0x02bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x02c0-0x02ff */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x0300-0x033f */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, /* 0x0340-0x037f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0380-0x03bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x03c0-0x03ff */ + /* 0x0400-0x05ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0400-0x043f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0440-0x047f */ + 0xf8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0480-0x04bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04c0-0x04ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0500-0x053f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0540-0x057f */ + 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xbf, /* 0x0580-0x05bf */ + 0xb6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x05c0-0x05ff */ + /* 0x0600-0x07ff */ + 0x0f, 0x00, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, /* 0x0600-0x063f */ + 0x00, 0xf8, 0xff, 0xff, 0x00, 0x00, 0x01, 0x00, /* 0x0640-0x067f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0680-0x06bf */ + 0x00, 0x00, 0xc0, 0xbf, 0x9f, 0x3d, 0x00, 0x00, /* 0x06c0-0x06ff */ + 0x00, 0x80, 0x02, 0x00, 0x00, 0x00, 0xff, 0xff, /* 0x0700-0x073f */ + 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0740-0x077f */ + 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0x01, 0x00, /* 0x0780-0x07bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x0f, 0x00, /* 0x07c0-0x07ff */ + /* 0x0800-0x09ff */ + 0x00, 0x00, 0xc0, 0xfb, 0xef, 0x3e, 0x00, 0x00, /* 0x0800-0x083f */ + 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, /* 0x0840-0x087f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0880-0x08bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08c0-0x08ff */ + 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, /* 0x0900-0x093f */ + 0xfe, 0x21, 0xfe, 0x00, 0x0c, 0x00, 0x00, 0x00, /* 0x0940-0x097f */ + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, /* 0x0980-0x09bf */ + 0x1e, 0x20, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, /* 0x09c0-0x09ff */ + /* 0x0a00-0x0bff */ + 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, /* 0x0a00-0x0a3f */ + 0x86, 0x39, 0x02, 0x00, 0x00, 0x00, 0x23, 0x00, /* 0x0a40-0x0a7f */ + 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, /* 0x0a80-0x0abf */ + 0xbe, 0x21, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, /* 0x0ac0-0x0aff */ + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, /* 0x0b00-0x0b3f */ + 0x1e, 0x20, 0x40, 0x00, 0x0c, 0x00, 0x00, 0x00, /* 0x0b40-0x0b7f */ + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0b80-0x0bbf */ + 0x01, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0bc0-0x0bff */ + /* 0x0c00-0x0dff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, /* 0x0c00-0x0c3f */ + 0xc1, 0x3d, 0x60, 0x00, 0x0c, 0x00, 0x00, 0x00, /* 0x0c40-0x0c7f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, /* 0x0c80-0x0cbf */ + 0x00, 0x30, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, /* 0x0cc0-0x0cff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0d00-0x0d3f */ + 0x1e, 0x20, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, /* 0x0d40-0x0d7f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0d80-0x0dbf */ + 0x00, 0x04, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0dc0-0x0dff */ + /* 0x0e00-0x0fff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf2, 0x07, /* 0x0e00-0x0e3f */ + 0x80, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0e40-0x0e7f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf2, 0x1b, /* 0x0e80-0x0ebf */ + 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0ec0-0x0eff */ + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0xa0, 0x02, /* 0x0f00-0x0f3f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x7f, /* 0x0f40-0x0f7f */ + 0xdf, 0xe0, 0xff, 0xfe, 0xff, 0xff, 0xff, 0x1f, /* 0x0f80-0x0fbf */ + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0fc0-0x0fff */ + /* 0x1000-0x11ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xfd, 0x66, /* 0x1000-0x103f */ + 0x00, 0x00, 0x00, 0xc3, 0x01, 0x00, 0x1e, 0x00, /* 0x1040-0x107f */ + 0x64, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, /* 0x1080-0x10bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10c0-0x10ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1100-0x113f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1140-0x117f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1180-0x11bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x11c0-0x11ff */ + /* 0x1200-0x13ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1200-0x123f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1240-0x127f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1280-0x12bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x12c0-0x12ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1300-0x133f */ + 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, /* 0x1340-0x137f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1380-0x13bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x13c0-0x13ff */ + /* 0x1600-0x17ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1600-0x163f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1640-0x167f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1680-0x16bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x16c0-0x16ff */ + 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x1c, 0x00, /* 0x1700-0x173f */ + 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, /* 0x1740-0x177f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x3f, /* 0x1780-0x17bf */ + 0x40, 0xfe, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x00, /* 0x17c0-0x17ff */ + /* 0x1800-0x19ff */ + 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1800-0x183f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1840-0x187f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, /* 0x1880-0x18bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18c0-0x18ff */ + 0x00, 0x00, 0x00, 0x00, 0x87, 0x01, 0x04, 0x0e, /* 0x1900-0x193f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1940-0x197f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1980-0x19bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x19c0-0x19ff */ + /* 0x1a00-0x1bff */ + 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, /* 0x1a00-0x1a3f */ + 0x00, 0x00, 0x40, 0x7f, 0xe5, 0x1f, 0xf8, 0x9f, /* 0x1a40-0x1a7f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1a80-0x1abf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1ac0-0x1aff */ + 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x17, /* 0x1b00-0x1b3f */ + 0x04, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x0f, 0x00, /* 0x1b40-0x1b7f */ + 0x03, 0x00, 0x00, 0x00, 0x3c, 0x03, 0x00, 0x00, /* 0x1b80-0x1bbf */ + 0x00, 0x00, 0x00, 0x00, 0x40, 0xa3, 0x03, 0x00, /* 0x1bc0-0x1bff */ + /* 0x1c00-0x1dff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xcf, 0x00, /* 0x1c00-0x1c3f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1c40-0x1c7f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1c80-0x1cbf */ + 0x00, 0x00, 0xf7, 0xff, 0xfd, 0x21, 0x00, 0x00, /* 0x1cc0-0x1cff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d00-0x1d3f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d40-0x1d7f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d80-0x1dbf */ + 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0xf0, /* 0x1dc0-0x1dff */ + /* 0x2000-0x21ff */ + 0x00, 0xf8, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, /* 0x2000-0x203f */ + 0x00, 0x00, 0x00, 0x00, 0x1f, 0xfc, 0x00, 0x00, /* 0x2040-0x207f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2080-0x20bf */ + 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, /* 0x20c0-0x20ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2100-0x213f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2140-0x217f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2180-0x21bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x21c0-0x21ff */ + /* 0x2c00-0x2dff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2c00-0x2c3f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2c40-0x2c7f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2c80-0x2cbf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, /* 0x2cc0-0x2cff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2d00-0x2d3f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* 0x2d40-0x2d7f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2d80-0x2dbf */ + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, /* 0x2dc0-0x2dff */ + /* 0x3000-0x31ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, /* 0x3000-0x303f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3040-0x307f */ + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, /* 0x3080-0x30bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30c0-0x30ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3100-0x313f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3140-0x317f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3180-0x31bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x31c0-0x31ff */ + /* 0xa600-0xa7ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa600-0xa63f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07, 0x30, /* 0xa640-0xa67f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa680-0xa6bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, /* 0xa6c0-0xa6ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa700-0xa73f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa740-0xa77f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa780-0xa7bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa7c0-0xa7ff */ + /* 0xa800-0xa9ff */ + 0x44, 0x08, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, /* 0xa800-0xa83f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa840-0xa87f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa880-0xa8bf */ + 0x10, 0x00, 0x00, 0x00, 0xff, 0xff, 0x03, 0x00, /* 0xa8c0-0xa8ff */ + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x3f, 0x00, 0x00, /* 0xa900-0xa93f */ + 0x80, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa940-0xa97f */ + 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x13, /* 0xa980-0xa9bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa9c0-0xa9ff */ + /* 0xaa00-0xabff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x66, 0x00, /* 0xaa00-0xaa3f */ + 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xaa40-0xaa7f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9d, 0xc1, /* 0xaa80-0xaabf */ + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xaac0-0xaaff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xab00-0xab3f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xab40-0xab7f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xab80-0xabbf */ + 0x00, 0x00, 0x00, 0x00, 0x20, 0x21, 0x00, 0x00, /* 0xabc0-0xabff */ + /* 0xfa00-0xfbff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfa00-0xfa3f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfa40-0xfa7f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfa80-0xfabf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfac0-0xfaff */ + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, /* 0xfb00-0xfb3f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfb40-0xfb7f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfb80-0xfbbf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfbc0-0xfbff */ + /* 0xfe00-0xffff */ + 0xff, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, /* 0xfe00-0xfe3f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfe40-0xfe7f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfe80-0xfebf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* 0xfec0-0xfeff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xff00-0xff3f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xff40-0xff7f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xff80-0xffbf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, /* 0xffc0-0xffff */ + /* 0x10000-0x101ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10000-0x1003f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10040-0x1007f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10080-0x100bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x100c0-0x100ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10100-0x1013f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10140-0x1017f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10180-0x101bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, /* 0x101c0-0x101ff */ + /* 0x10a00-0x10bff */ + 0x6e, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87, /* 0x10a00-0x10a3f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10a40-0x10a7f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10a80-0x10abf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10ac0-0x10aff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10b00-0x10b3f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10b40-0x10b7f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10b80-0x10bbf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10bc0-0x10bff */ + /* 0x11000-0x111ff */ + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, /* 0x11000-0x1103f */ + 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x11040-0x1107f */ + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x26, /* 0x11080-0x110bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x110c0-0x110ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x11100-0x1113f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x11140-0x1117f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x11180-0x111bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x111c0-0x111ff */ + /* 0x1d000-0x1d1ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d000-0x1d03f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d040-0x1d07f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d080-0x1d0bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d0c0-0x1d0ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d100-0x1d13f */ + 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0xf8, 0xff, /* 0x1d140-0x1d17f */ + 0xe7, 0x0f, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, /* 0x1d180-0x1d1bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d1c0-0x1d1ff */ + /* 0x1d200-0x1d3ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d200-0x1d23f */ + 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d240-0x1d27f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d280-0x1d2bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d2c0-0x1d2ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d300-0x1d33f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d340-0x1d37f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d380-0x1d3bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* 0x1d3c0-0x1d3ff */ +}; +static const signed char nonspacing_table_ind[240] = { + 0, 1, 2, 3, 4, 5, 6, 7, /* 0x0000-0x0fff */ + 8, 9, -1, 10, 11, 12, 13, -1, /* 0x1000-0x1fff */ + 14, -1, -1, -1, -1, -1, 15, -1, /* 0x2000-0x2fff */ + 16, -1, -1, -1, -1, -1, -1, -1, /* 0x3000-0x3fff */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0x4000-0x4fff */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0x5000-0x5fff */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0x6000-0x6fff */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0x7000-0x7fff */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0x8000-0x8fff */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0x9000-0x9fff */ + -1, -1, -1, 17, 18, 19, -1, -1, /* 0xa000-0xafff */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0xb000-0xbfff */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0xc000-0xcfff */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0xd000-0xdfff */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0xe000-0xefff */ + -1, -1, -1, -1, -1, 20, -1, 21, /* 0xf000-0xffff */ + 22, -1, -1, -1, -1, 23, -1, -1, /* 0x10000-0x10fff */ + 24, -1, -1, -1, -1, -1, -1, -1, /* 0x11000-0x11fff */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0x12000-0x12fff */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0x13000-0x13fff */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0x14000-0x14fff */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0x15000-0x15fff */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0x16000-0x16fff */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0x17000-0x17fff */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0x18000-0x18fff */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0x19000-0x19fff */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0x1a000-0x1afff */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0x1b000-0x1bfff */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0x1c000-0x1cfff */ + 25, 26, -1, -1, -1, -1, -1, -1 /* 0x1d000-0x1dfff */ +}; + +/* Determine number of column positions required for UC. */ +int +uc_width (ucs4_t uc, const char *encoding) +{ + /* Test for non-spacing or control character. */ + if ((uc >> 9) < 240) + { + int ind = nonspacing_table_ind[uc >> 9]; + if (ind >= 0) + if ((nonspacing_table_data[64*ind + ((uc >> 3) & 63)] >> (uc & 7)) & 1) + { + if (uc > 0 && uc < 0xa0) + return -1; + else + return 0; + } + } + else if ((uc >> 9) == (0xe0000 >> 9)) + { + if (uc >= 0xe0100) + { + if (uc <= 0xe01ef) + return 0; + } + else + { + if (uc >= 0xe0020 ? uc <= 0xe007f : uc == 0xe0001) + return 0; + } + } + /* Test for double-width character. + * Generated from "grep '^[^;]\{4,5\};[WF]' EastAsianWidth.txt" + * and "grep '^[^;]\{4,5\};[^WF]' EastAsianWidth.txt" + */ + if (uc >= 0x1100 + && ((uc < 0x1160) /* Hangul Jamo */ + || (uc >= 0x2329 && uc < 0x232b) /* Angle Brackets */ + || (uc >= 0x2e80 && uc < 0xa4d0 /* CJK ... Yi */ + && !(uc == 0x303f) && !(uc >= 0x4dc0 && uc < 0x4e00)) + || (uc >= 0xac00 && uc < 0xd7a4) /* Hangul Syllables */ + || (uc >= 0xf900 && uc < 0xfb00) /* CJK Compatibility Ideographs */ + || (uc >= 0xfe10 && uc < 0xfe20) /* Presentation Forms for Vertical */ + || (uc >= 0xfe30 && uc < 0xfe70) /* CJK Compatibility Forms */ + || (uc >= 0xff00 && uc < 0xff61) /* Fullwidth Forms */ + || (uc >= 0xffe0 && uc < 0xffe7) /* Fullwidth Signs */ + || (uc >= 0x20000 && uc <= 0x2ffff) /* Supplementary Ideographic Plane */ + || (uc >= 0x30000 && uc <= 0x3ffff) /* Tertiary Ideographic Plane */ + ) ) + return 2; + /* In ancient CJK encodings, Cyrillic and most other characters are + double-width as well. */ + if (uc >= 0x00A1 && uc < 0xFF61 && uc != 0x20A9 + && is_cjk_encoding (encoding)) + return 2; + return 1; +} diff --git a/gettext-tools/gnulib-lib/unlocked-io.h b/gettext-tools/gnulib-lib/unlocked-io.h new file mode 100644 index 0000000..4b0f3ff --- /dev/null +++ b/gettext-tools/gnulib-lib/unlocked-io.h @@ -0,0 +1,136 @@ +/* Prefer faster, non-thread-safe stdio functions if available. + + Copyright (C) 2001-2004, 2009-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Written by Jim Meyering. */ + +#ifndef UNLOCKED_IO_H +# define UNLOCKED_IO_H 1 + +/* These are wrappers for functions/macros from the GNU C library, and + from other C libraries supporting POSIX's optional thread-safe functions. + + The standard I/O functions are thread-safe. These *_unlocked ones are + more efficient but not thread-safe. That they're not thread-safe is + fine since all of the applications in this package are single threaded. + + Also, some code that is shared with the GNU C library may invoke + the *_unlocked functions directly. On hosts that lack those + functions, invoke the non-thread-safe versions instead. */ + +# include + +# if HAVE_DECL_CLEARERR_UNLOCKED +# undef clearerr +# define clearerr(x) clearerr_unlocked (x) +# else +# define clearerr_unlocked(x) clearerr (x) +# endif + +# if HAVE_DECL_FEOF_UNLOCKED +# undef feof +# define feof(x) feof_unlocked (x) +# else +# define feof_unlocked(x) feof (x) +# endif + +# if HAVE_DECL_FERROR_UNLOCKED +# undef ferror +# define ferror(x) ferror_unlocked (x) +# else +# define ferror_unlocked(x) ferror (x) +# endif + +# if HAVE_DECL_FFLUSH_UNLOCKED +# undef fflush +# define fflush(x) fflush_unlocked (x) +# else +# define fflush_unlocked(x) fflush (x) +# endif + +# if HAVE_DECL_FGETS_UNLOCKED +# undef fgets +# define fgets(x,y,z) fgets_unlocked (x,y,z) +# else +# define fgets_unlocked(x,y,z) fgets (x,y,z) +# endif + +# if HAVE_DECL_FPUTC_UNLOCKED +# undef fputc +# define fputc(x,y) fputc_unlocked (x,y) +# else +# define fputc_unlocked(x,y) fputc (x,y) +# endif + +# if HAVE_DECL_FPUTS_UNLOCKED +# undef fputs +# define fputs(x,y) fputs_unlocked (x,y) +# else +# define fputs_unlocked(x,y) fputs (x,y) +# endif + +# if HAVE_DECL_FREAD_UNLOCKED +# undef fread +# define fread(w,x,y,z) fread_unlocked (w,x,y,z) +# else +# define fread_unlocked(w,x,y,z) fread (w,x,y,z) +# endif + +# if HAVE_DECL_FWRITE_UNLOCKED +# undef fwrite +# define fwrite(w,x,y,z) fwrite_unlocked (w,x,y,z) +# else +# define fwrite_unlocked(w,x,y,z) fwrite (w,x,y,z) +# endif + +# if HAVE_DECL_GETC_UNLOCKED +# undef getc +# define getc(x) getc_unlocked (x) +# else +# define getc_unlocked(x) getc (x) +# endif + +# if HAVE_DECL_GETCHAR_UNLOCKED +# undef getchar +# define getchar() getchar_unlocked () +# else +# define getchar_unlocked() getchar () +# endif + +# if HAVE_DECL_PUTC_UNLOCKED +# undef putc +# define putc(x,y) putc_unlocked (x,y) +# else +# define putc_unlocked(x,y) putc (x,y) +# endif + +# if HAVE_DECL_PUTCHAR_UNLOCKED +# undef putchar +# define putchar(x) putchar_unlocked (x) +# else +# define putchar_unlocked(x) putchar (x) +# endif + +# undef flockfile +# define flockfile(x) ((void) 0) + +# undef ftrylockfile +# define ftrylockfile(x) 0 + +# undef funlockfile +# define funlockfile(x) ((void) 0) + +#endif /* UNLOCKED_IO_H */ diff --git a/gettext-tools/gnulib-lib/unsetenv.c b/gettext-tools/gnulib-lib/unsetenv.c new file mode 100644 index 0000000..53721fc --- /dev/null +++ b/gettext-tools/gnulib-lib/unsetenv.c @@ -0,0 +1,127 @@ +/* Copyright (C) 1992, 1995-2002, 2005-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Don't use __attribute__ __nonnull__ in this compilation unit. Otherwise gcc + optimizes away the name == NULL test below. */ +#define _GL_ARG_NONNULL(params) + +#include + +/* Specification. */ +#include + +#include +#if !_LIBC +# define __set_errno(ev) ((errno) = (ev)) +#endif + +#include +#include + +#if !_LIBC +# define __environ environ +#endif + +#if _LIBC +/* This lock protects against simultaneous modifications of 'environ'. */ +# include +__libc_lock_define_initialized (static, envlock) +# define LOCK __libc_lock_lock (envlock) +# define UNLOCK __libc_lock_unlock (envlock) +#else +# define LOCK +# define UNLOCK +#endif + +/* In the GNU C library we must keep the namespace clean. */ +#ifdef _LIBC +# define unsetenv __unsetenv +#endif + +#if _LIBC || !HAVE_UNSETENV + +int +unsetenv (const char *name) +{ + size_t len; + char **ep; + + if (name == NULL || *name == '\0' || strchr (name, '=') != NULL) + { + __set_errno (EINVAL); + return -1; + } + + len = strlen (name); + + LOCK; + + ep = __environ; + while (*ep != NULL) + if (!strncmp (*ep, name, len) && (*ep)[len] == '=') + { + /* Found it. Remove this pointer by moving later ones back. */ + char **dp = ep; + + do + dp[0] = dp[1]; + while (*dp++); + /* Continue the loop in case NAME appears again. */ + } + else + ++ep; + + UNLOCK; + + return 0; +} + +#ifdef _LIBC +# undef unsetenv +weak_alias (__unsetenv, unsetenv) +#endif + +#else /* HAVE_UNSETENV */ + +# undef unsetenv +# if !HAVE_DECL_UNSETENV +# if VOID_UNSETENV +extern void unsetenv (const char *); +# else +extern int unsetenv (const char *); +# endif +# endif + +/* Call the underlying unsetenv, in case there is hidden bookkeeping + that needs updating beyond just modifying environ. */ +int +rpl_unsetenv (const char *name) +{ + int result = 0; + if (!name || !*name || strchr (name, '=')) + { + errno = EINVAL; + return -1; + } + while (getenv (name)) +# if !VOID_UNSETENV + result = +# endif + unsetenv (name); + return result; +} + +#endif /* HAVE_UNSETENV */ diff --git a/gettext-tools/gnulib-lib/vasnprintf.c b/gettext-tools/gnulib-lib/vasnprintf.c new file mode 100644 index 0000000..ec7302a --- /dev/null +++ b/gettext-tools/gnulib-lib/vasnprintf.c @@ -0,0 +1,5595 @@ +/* vsprintf with automatic memory allocation. + Copyright (C) 1999, 2002-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, see . */ + +/* This file can be parametrized with the following macros: + VASNPRINTF The name of the function being defined. + FCHAR_T The element type of the format string. + DCHAR_T The element type of the destination (result) string. + FCHAR_T_ONLY_ASCII Set to 1 to enable verification that all characters + in the format string are ASCII. MUST be set if + FCHAR_T and DCHAR_T are not the same type. + DIRECTIVE Structure denoting a format directive. + Depends on FCHAR_T. + DIRECTIVES Structure denoting the set of format directives of a + format string. Depends on FCHAR_T. + PRINTF_PARSE Function that parses a format string. + Depends on FCHAR_T. + DCHAR_CPY memcpy like function for DCHAR_T[] arrays. + DCHAR_SET memset like function for DCHAR_T[] arrays. + DCHAR_MBSNLEN mbsnlen like function for DCHAR_T[] arrays. + SNPRINTF The system's snprintf (or similar) function. + This may be either snprintf or swprintf. + TCHAR_T The element type of the argument and result string + of the said SNPRINTF function. This may be either + char or wchar_t. The code exploits that + sizeof (TCHAR_T) | sizeof (DCHAR_T) and + alignof (TCHAR_T) <= alignof (DCHAR_T). + DCHAR_IS_TCHAR Set to 1 if DCHAR_T and TCHAR_T are the same type. + DCHAR_CONV_FROM_ENCODING A function to convert from char[] to DCHAR[]. + DCHAR_IS_UINT8_T Set to 1 if DCHAR_T is uint8_t. + DCHAR_IS_UINT16_T Set to 1 if DCHAR_T is uint16_t. + DCHAR_IS_UINT32_T Set to 1 if DCHAR_T is uint32_t. */ + +/* Tell glibc's to provide a prototype for snprintf(). + This must come before because may include + , and once has been included, it's too late. */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +#endif + +#ifndef VASNPRINTF +# include +#endif +#ifndef IN_LIBINTL +# include +#endif + +/* Specification. */ +#ifndef VASNPRINTF +# if WIDE_CHAR_VERSION +# include "vasnwprintf.h" +# else +# include "vasnprintf.h" +# endif +#endif + +#include /* localeconv() */ +#include /* snprintf(), sprintf() */ +#include /* abort(), malloc(), realloc(), free() */ +#include /* memcpy(), strlen() */ +#include /* errno */ +#include /* CHAR_BIT */ +#include /* DBL_MAX_EXP, LDBL_MAX_EXP */ +#if HAVE_NL_LANGINFO +# include +#endif +#ifndef VASNPRINTF +# if WIDE_CHAR_VERSION +# include "wprintf-parse.h" +# else +# include "printf-parse.h" +# endif +#endif + +/* Checked size_t computations. */ +#include "xsize.h" + +#include "verify.h" + +#if (NEED_PRINTF_DOUBLE || NEED_PRINTF_LONG_DOUBLE) && !defined IN_LIBINTL +# include +# include "float+.h" +#endif + +#if (NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE) && !defined IN_LIBINTL +# include +# include "isnand-nolibm.h" +#endif + +#if (NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE) && !defined IN_LIBINTL +# include +# include "isnanl-nolibm.h" +# include "fpucw.h" +#endif + +#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_DOUBLE) && !defined IN_LIBINTL +# include +# include "isnand-nolibm.h" +# include "printf-frexp.h" +#endif + +#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE) && !defined IN_LIBINTL +# include +# include "isnanl-nolibm.h" +# include "printf-frexpl.h" +# include "fpucw.h" +#endif + +/* Default parameters. */ +#ifndef VASNPRINTF +# if WIDE_CHAR_VERSION +# define VASNPRINTF vasnwprintf +# define FCHAR_T wchar_t +# define DCHAR_T wchar_t +# define TCHAR_T wchar_t +# define DCHAR_IS_TCHAR 1 +# define DIRECTIVE wchar_t_directive +# define DIRECTIVES wchar_t_directives +# define PRINTF_PARSE wprintf_parse +# define DCHAR_CPY wmemcpy +# define DCHAR_SET wmemset +# else +# define VASNPRINTF vasnprintf +# define FCHAR_T char +# define DCHAR_T char +# define TCHAR_T char +# define DCHAR_IS_TCHAR 1 +# define DIRECTIVE char_directive +# define DIRECTIVES char_directives +# define PRINTF_PARSE printf_parse +# define DCHAR_CPY memcpy +# define DCHAR_SET memset +# endif +#endif +#if WIDE_CHAR_VERSION + /* TCHAR_T is wchar_t. */ +# define USE_SNPRINTF 1 +# if HAVE_DECL__SNWPRINTF + /* On Windows, the function swprintf() has a different signature than + on Unix; we use the function _snwprintf() or - on mingw - snwprintf() + instead. The mingw function snwprintf() has fewer bugs than the + MSVCRT function _snwprintf(), so prefer that. */ +# if defined __MINGW32__ +# define SNPRINTF snwprintf +# else +# define SNPRINTF _snwprintf +# endif +# else + /* Unix. */ +# define SNPRINTF swprintf +# endif +#else + /* TCHAR_T is char. */ + /* Use snprintf if it exists under the name 'snprintf' or '_snprintf'. + But don't use it on BeOS, since BeOS snprintf produces no output if the + size argument is >= 0x3000000. + Also don't use it on Linux libc5, since there snprintf with size = 1 + writes any output without bounds, like sprintf. */ +# if (HAVE_DECL__SNPRINTF || HAVE_SNPRINTF) && !defined __BEOS__ && !(__GNU_LIBRARY__ == 1) +# define USE_SNPRINTF 1 +# else +# define USE_SNPRINTF 0 +# endif +# if HAVE_DECL__SNPRINTF + /* Windows. The mingw function snprintf() has fewer bugs than the MSVCRT + function _snprintf(), so prefer that. */ +# if defined __MINGW32__ +# define SNPRINTF snprintf + /* Here we need to call the native snprintf, not rpl_snprintf. */ +# undef snprintf +# else +# define SNPRINTF _snprintf +# endif +# else + /* Unix. */ +# define SNPRINTF snprintf + /* Here we need to call the native snprintf, not rpl_snprintf. */ +# undef snprintf +# endif +#endif +/* Here we need to call the native sprintf, not rpl_sprintf. */ +#undef sprintf + +/* GCC >= 4.0 with -Wall emits unjustified "... may be used uninitialized" + warnings in this file. Use -Dlint to suppress them. */ +#ifdef lint +# define IF_LINT(Code) Code +#else +# define IF_LINT(Code) /* empty */ +#endif + +/* Avoid some warnings from "gcc -Wshadow". + This file doesn't use the exp() and remainder() functions. */ +#undef exp +#define exp expo +#undef remainder +#define remainder rem + +#if (!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99) && !WIDE_CHAR_VERSION +# if (HAVE_STRNLEN && !defined _AIX) +# define local_strnlen strnlen +# else +# ifndef local_strnlen_defined +# define local_strnlen_defined 1 +static size_t +local_strnlen (const char *string, size_t maxlen) +{ + const char *end = memchr (string, '\0', maxlen); + return end ? (size_t) (end - string) : maxlen; +} +# endif +# endif +#endif + +#if (((!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99) && WIDE_CHAR_VERSION) || ((!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || (NEED_PRINTF_DIRECTIVE_LS && !defined IN_LIBINTL)) && !WIDE_CHAR_VERSION && DCHAR_IS_TCHAR)) && HAVE_WCHAR_T +# if HAVE_WCSLEN +# define local_wcslen wcslen +# else + /* Solaris 2.5.1 has wcslen() in a separate library libw.so. To avoid + a dependency towards this library, here is a local substitute. + Define this substitute only once, even if this file is included + twice in the same compilation unit. */ +# ifndef local_wcslen_defined +# define local_wcslen_defined 1 +static size_t +local_wcslen (const wchar_t *s) +{ + const wchar_t *ptr; + + for (ptr = s; *ptr != (wchar_t) 0; ptr++) + ; + return ptr - s; +} +# endif +# endif +#endif + +#if (!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99) && HAVE_WCHAR_T && WIDE_CHAR_VERSION +# if HAVE_WCSNLEN +# define local_wcsnlen wcsnlen +# else +# ifndef local_wcsnlen_defined +# define local_wcsnlen_defined 1 +static size_t +local_wcsnlen (const wchar_t *s, size_t maxlen) +{ + const wchar_t *ptr; + + for (ptr = s; maxlen > 0 && *ptr != (wchar_t) 0; ptr++, maxlen--) + ; + return ptr - s; +} +# endif +# endif +#endif + +#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE || NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE) && !defined IN_LIBINTL +/* Determine the decimal-point character according to the current locale. */ +# ifndef decimal_point_char_defined +# define decimal_point_char_defined 1 +static char +decimal_point_char (void) +{ + const char *point; + /* Determine it in a multithread-safe way. We know nl_langinfo is + multithread-safe on glibc systems and Mac OS X systems, but is not required + to be multithread-safe by POSIX. sprintf(), however, is multithread-safe. + localeconv() is rarely multithread-safe. */ +# if HAVE_NL_LANGINFO && (__GLIBC__ || defined __UCLIBC__ || (defined __APPLE__ && defined __MACH__)) + point = nl_langinfo (RADIXCHAR); +# elif 1 + char pointbuf[5]; + sprintf (pointbuf, "%#.0f", 1.0); + point = &pointbuf[1]; +# else + point = localeconv () -> decimal_point; +# endif + /* The decimal point is always a single byte: either '.' or ','. */ + return (point[0] != '\0' ? point[0] : '.'); +} +# endif +#endif + +#if NEED_PRINTF_INFINITE_DOUBLE && !NEED_PRINTF_DOUBLE && !defined IN_LIBINTL + +/* Equivalent to !isfinite(x) || x == 0, but does not require libm. */ +static int +is_infinite_or_zero (double x) +{ + return isnand (x) || x + x == x; +} + +#endif + +#if NEED_PRINTF_INFINITE_LONG_DOUBLE && !NEED_PRINTF_LONG_DOUBLE && !defined IN_LIBINTL + +/* Equivalent to !isfinite(x) || x == 0, but does not require libm. */ +static int +is_infinite_or_zerol (long double x) +{ + return isnanl (x) || x + x == x; +} + +#endif + +#if (NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_DOUBLE) && !defined IN_LIBINTL + +/* Converting 'long double' to decimal without rare rounding bugs requires + real bignums. We use the naming conventions of GNU gmp, but vastly simpler + (and slower) algorithms. */ + +typedef unsigned int mp_limb_t; +# define GMP_LIMB_BITS 32 +verify (sizeof (mp_limb_t) * CHAR_BIT == GMP_LIMB_BITS); + +typedef unsigned long long mp_twolimb_t; +# define GMP_TWOLIMB_BITS 64 +verify (sizeof (mp_twolimb_t) * CHAR_BIT == GMP_TWOLIMB_BITS); + +/* Representation of a bignum >= 0. */ +typedef struct +{ + size_t nlimbs; + mp_limb_t *limbs; /* Bits in little-endian order, allocated with malloc(). */ +} mpn_t; + +/* Compute the product of two bignums >= 0. + Return the allocated memory in case of success, NULL in case of memory + allocation failure. */ +static void * +multiply (mpn_t src1, mpn_t src2, mpn_t *dest) +{ + const mp_limb_t *p1; + const mp_limb_t *p2; + size_t len1; + size_t len2; + + if (src1.nlimbs <= src2.nlimbs) + { + len1 = src1.nlimbs; + p1 = src1.limbs; + len2 = src2.nlimbs; + p2 = src2.limbs; + } + else + { + len1 = src2.nlimbs; + p1 = src2.limbs; + len2 = src1.nlimbs; + p2 = src1.limbs; + } + /* Now 0 <= len1 <= len2. */ + if (len1 == 0) + { + /* src1 or src2 is zero. */ + dest->nlimbs = 0; + dest->limbs = (mp_limb_t *) malloc (1); + } + else + { + /* Here 1 <= len1 <= len2. */ + size_t dlen; + mp_limb_t *dp; + size_t k, i, j; + + dlen = len1 + len2; + dp = (mp_limb_t *) malloc (dlen * sizeof (mp_limb_t)); + if (dp == NULL) + return NULL; + for (k = len2; k > 0; ) + dp[--k] = 0; + for (i = 0; i < len1; i++) + { + mp_limb_t digit1 = p1[i]; + mp_twolimb_t carry = 0; + for (j = 0; j < len2; j++) + { + mp_limb_t digit2 = p2[j]; + carry += (mp_twolimb_t) digit1 * (mp_twolimb_t) digit2; + carry += dp[i + j]; + dp[i + j] = (mp_limb_t) carry; + carry = carry >> GMP_LIMB_BITS; + } + dp[i + len2] = (mp_limb_t) carry; + } + /* Normalise. */ + while (dlen > 0 && dp[dlen - 1] == 0) + dlen--; + dest->nlimbs = dlen; + dest->limbs = dp; + } + return dest->limbs; +} + +/* Compute the quotient of a bignum a >= 0 and a bignum b > 0. + a is written as a = q * b + r with 0 <= r < b. q is the quotient, r + the remainder. + Finally, round-to-even is performed: If r > b/2 or if r = b/2 and q is odd, + q is incremented. + Return the allocated memory in case of success, NULL in case of memory + allocation failure. */ +static void * +divide (mpn_t a, mpn_t b, mpn_t *q) +{ + /* Algorithm: + First normalise a and b: a=[a[m-1],...,a[0]], b=[b[n-1],...,b[0]] + with m>=0 and n>0 (in base beta = 2^GMP_LIMB_BITS). + If m=n=1, perform a single-precision division: + r:=0, j:=m, + while j>0 do + {Here (q[m-1]*beta^(m-1)+...+q[j]*beta^j) * b[0] + r*beta^j = + = a[m-1]*beta^(m-1)+...+a[j]*beta^j und 0<=r=n>1, perform a multiple-precision division: + We have a/b < beta^(m-n+1). + s:=intDsize-1-(highest bit in b[n-1]), 0<=s=beta/2. + For j=m-n,...,0: {Here 0 <= r < b*beta^(j+1).} + Compute q* : + q* := floor((r[j+n]*beta+r[j+n-1])/b[n-1]). + In case of overflow (q* >= beta) set q* := beta-1. + Compute c2 := ((r[j+n]*beta+r[j+n-1]) - q* * b[n-1])*beta + r[j+n-2] + and c3 := b[n-2] * q*. + {We have 0 <= c2 < 2*beta^2, even 0 <= c2 < beta^2 if no overflow + occurred. Furthermore 0 <= c3 < beta^2. + If there was overflow and + r[j+n]*beta+r[j+n-1] - q* * b[n-1] >= beta, i.e. c2 >= beta^2, + the next test can be skipped.} + While c3 > c2, {Here 0 <= c2 < c3 < beta^2} + Put q* := q* - 1, c2 := c2 + b[n-1]*beta, c3 := c3 - b[n-2]. + If q* > 0: + Put r := r - b * q* * beta^j. In detail: + [r[n+j],...,r[j]] := [r[n+j],...,r[j]] - q* * [b[n-1],...,b[0]]. + hence: u:=0, for i:=0 to n-1 do + u := u + q* * b[i], + r[j+i]:=r[j+i]-(u mod beta) (+ beta, if carry), + u:=u div beta (+ 1, if carry in subtraction) + r[n+j]:=r[n+j]-u. + {Since always u = (q* * [b[i-1],...,b[0]] div beta^i) + 1 + < q* + 1 <= beta, + the carry u does not overflow.} + If a negative carry occurs, put q* := q* - 1 + and [r[n+j],...,r[j]] := [r[n+j],...,r[j]] + [0,b[n-1],...,b[0]]. + Set q[j] := q*. + Normalise [q[m-n],..,q[0]]; this yields the quotient q. + Shift [r[n-1],...,r[0]] right by s bits and normalise; this yields the + rest r. + The room for q[j] can be allocated at the memory location of r[n+j]. + Finally, round-to-even: + Shift r left by 1 bit. + If r > b or if r = b and q[0] is odd, q := q+1. + */ + const mp_limb_t *a_ptr = a.limbs; + size_t a_len = a.nlimbs; + const mp_limb_t *b_ptr = b.limbs; + size_t b_len = b.nlimbs; + mp_limb_t *roomptr; + mp_limb_t *tmp_roomptr = NULL; + mp_limb_t *q_ptr; + size_t q_len; + mp_limb_t *r_ptr; + size_t r_len; + + /* Allocate room for a_len+2 digits. + (Need a_len+1 digits for the real division and 1 more digit for the + final rounding of q.) */ + roomptr = (mp_limb_t *) malloc ((a_len + 2) * sizeof (mp_limb_t)); + if (roomptr == NULL) + return NULL; + + /* Normalise a. */ + while (a_len > 0 && a_ptr[a_len - 1] == 0) + a_len--; + + /* Normalise b. */ + for (;;) + { + if (b_len == 0) + /* Division by zero. */ + abort (); + if (b_ptr[b_len - 1] == 0) + b_len--; + else + break; + } + + /* Here m = a_len >= 0 and n = b_len > 0. */ + + if (a_len < b_len) + { + /* m beta^(m-2) <= a/b < beta^m */ + r_ptr = roomptr; + q_ptr = roomptr + 1; + { + mp_limb_t den = b_ptr[0]; + mp_limb_t remainder = 0; + const mp_limb_t *sourceptr = a_ptr + a_len; + mp_limb_t *destptr = q_ptr + a_len; + size_t count; + for (count = a_len; count > 0; count--) + { + mp_twolimb_t num = + ((mp_twolimb_t) remainder << GMP_LIMB_BITS) | *--sourceptr; + *--destptr = num / den; + remainder = num % den; + } + /* Normalise and store r. */ + if (remainder > 0) + { + r_ptr[0] = remainder; + r_len = 1; + } + else + r_len = 0; + /* Normalise q. */ + q_len = a_len; + if (q_ptr[q_len - 1] == 0) + q_len--; + } + } + else + { + /* n>1: multiple precision division. + beta^(m-1) <= a < beta^m, beta^(n-1) <= b < beta^n ==> + beta^(m-n-1) <= a/b < beta^(m-n+1). */ + /* Determine s. */ + size_t s; + { + mp_limb_t msd = b_ptr[b_len - 1]; /* = b[n-1], > 0 */ + /* Determine s = GMP_LIMB_BITS - integer_length (msd). + Code copied from gnulib's integer_length.c. */ +# if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) + s = __builtin_clz (msd); +# else +# if defined DBL_EXPBIT0_WORD && defined DBL_EXPBIT0_BIT + if (GMP_LIMB_BITS <= DBL_MANT_BIT) + { + /* Use 'double' operations. + Assumes an IEEE 754 'double' implementation. */ +# define DBL_EXP_MASK ((DBL_MAX_EXP - DBL_MIN_EXP) | 7) +# define DBL_EXP_BIAS (DBL_EXP_MASK / 2 - 1) +# define NWORDS \ + ((sizeof (double) + sizeof (unsigned int) - 1) / sizeof (unsigned int)) + union { double value; unsigned int word[NWORDS]; } m; + + /* Use a single integer to floating-point conversion. */ + m.value = msd; + + s = GMP_LIMB_BITS + - (((m.word[DBL_EXPBIT0_WORD] >> DBL_EXPBIT0_BIT) & DBL_EXP_MASK) + - DBL_EXP_BIAS); + } + else +# undef NWORDS +# endif + { + s = 31; + if (msd >= 0x10000) + { + msd = msd >> 16; + s -= 16; + } + if (msd >= 0x100) + { + msd = msd >> 8; + s -= 8; + } + if (msd >= 0x10) + { + msd = msd >> 4; + s -= 4; + } + if (msd >= 0x4) + { + msd = msd >> 2; + s -= 2; + } + if (msd >= 0x2) + { + msd = msd >> 1; + s -= 1; + } + } +# endif + } + /* 0 <= s < GMP_LIMB_BITS. + Copy b, shifting it left by s bits. */ + if (s > 0) + { + tmp_roomptr = (mp_limb_t *) malloc (b_len * sizeof (mp_limb_t)); + if (tmp_roomptr == NULL) + { + free (roomptr); + return NULL; + } + { + const mp_limb_t *sourceptr = b_ptr; + mp_limb_t *destptr = tmp_roomptr; + mp_twolimb_t accu = 0; + size_t count; + for (count = b_len; count > 0; count--) + { + accu += (mp_twolimb_t) *sourceptr++ << s; + *destptr++ = (mp_limb_t) accu; + accu = accu >> GMP_LIMB_BITS; + } + /* accu must be zero, since that was how s was determined. */ + if (accu != 0) + abort (); + } + b_ptr = tmp_roomptr; + } + /* Copy a, shifting it left by s bits, yields r. + Memory layout: + At the beginning: r = roomptr[0..a_len], + at the end: r = roomptr[0..b_len-1], q = roomptr[b_len..a_len] */ + r_ptr = roomptr; + if (s == 0) + { + memcpy (r_ptr, a_ptr, a_len * sizeof (mp_limb_t)); + r_ptr[a_len] = 0; + } + else + { + const mp_limb_t *sourceptr = a_ptr; + mp_limb_t *destptr = r_ptr; + mp_twolimb_t accu = 0; + size_t count; + for (count = a_len; count > 0; count--) + { + accu += (mp_twolimb_t) *sourceptr++ << s; + *destptr++ = (mp_limb_t) accu; + accu = accu >> GMP_LIMB_BITS; + } + *destptr++ = (mp_limb_t) accu; + } + q_ptr = roomptr + b_len; + q_len = a_len - b_len + 1; /* q will have m-n+1 limbs */ + { + size_t j = a_len - b_len; /* m-n */ + mp_limb_t b_msd = b_ptr[b_len - 1]; /* b[n-1] */ + mp_limb_t b_2msd = b_ptr[b_len - 2]; /* b[n-2] */ + mp_twolimb_t b_msdd = /* b[n-1]*beta+b[n-2] */ + ((mp_twolimb_t) b_msd << GMP_LIMB_BITS) | b_2msd; + /* Division loop, traversed m-n+1 times. + j counts down, b is unchanged, beta/2 <= b[n-1] < beta. */ + for (;;) + { + mp_limb_t q_star; + mp_limb_t c1; + if (r_ptr[j + b_len] < b_msd) /* r[j+n] < b[n-1] ? */ + { + /* Divide r[j+n]*beta+r[j+n-1] by b[n-1], no overflow. */ + mp_twolimb_t num = + ((mp_twolimb_t) r_ptr[j + b_len] << GMP_LIMB_BITS) + | r_ptr[j + b_len - 1]; + q_star = num / b_msd; + c1 = num % b_msd; + } + else + { + /* Overflow, hence r[j+n]*beta+r[j+n-1] >= beta*b[n-1]. */ + q_star = (mp_limb_t)~(mp_limb_t)0; /* q* = beta-1 */ + /* Test whether r[j+n]*beta+r[j+n-1] - (beta-1)*b[n-1] >= beta + <==> r[j+n]*beta+r[j+n-1] + b[n-1] >= beta*b[n-1]+beta + <==> b[n-1] < floor((r[j+n]*beta+r[j+n-1]+b[n-1])/beta) + {<= beta !}. + If yes, jump directly to the subtraction loop. + (Otherwise, r[j+n]*beta+r[j+n-1] - (beta-1)*b[n-1] < beta + <==> floor((r[j+n]*beta+r[j+n-1]+b[n-1])/beta) = b[n-1] ) */ + if (r_ptr[j + b_len] > b_msd + || (c1 = r_ptr[j + b_len - 1] + b_msd) < b_msd) + /* r[j+n] >= b[n-1]+1 or + r[j+n] = b[n-1] and the addition r[j+n-1]+b[n-1] gives a + carry. */ + goto subtract; + } + /* q_star = q*, + c1 = (r[j+n]*beta+r[j+n-1]) - q* * b[n-1] (>=0, 0, decrease it by + b[n-1]*beta+b[n-2]. Because of b[n-1]*beta+b[n-2] >= beta^2/2 + this can happen only twice. */ + if (c3 > c2) + { + q_star = q_star - 1; /* q* := q* - 1 */ + if (c3 - c2 > b_msdd) + q_star = q_star - 1; /* q* := q* - 1 */ + } + } + if (q_star > 0) + subtract: + { + /* Subtract r := r - b * q* * beta^j. */ + mp_limb_t cr; + { + const mp_limb_t *sourceptr = b_ptr; + mp_limb_t *destptr = r_ptr + j; + mp_twolimb_t carry = 0; + size_t count; + for (count = b_len; count > 0; count--) + { + /* Here 0 <= carry <= q*. */ + carry = + carry + + (mp_twolimb_t) q_star * (mp_twolimb_t) *sourceptr++ + + (mp_limb_t) ~(*destptr); + /* Here 0 <= carry <= beta*q* + beta-1. */ + *destptr++ = ~(mp_limb_t) carry; + carry = carry >> GMP_LIMB_BITS; /* <= q* */ + } + cr = (mp_limb_t) carry; + } + /* Subtract cr from r_ptr[j + b_len], then forget about + r_ptr[j + b_len]. */ + if (cr > r_ptr[j + b_len]) + { + /* Subtraction gave a carry. */ + q_star = q_star - 1; /* q* := q* - 1 */ + /* Add b back. */ + { + const mp_limb_t *sourceptr = b_ptr; + mp_limb_t *destptr = r_ptr + j; + mp_limb_t carry = 0; + size_t count; + for (count = b_len; count > 0; count--) + { + mp_limb_t source1 = *sourceptr++; + mp_limb_t source2 = *destptr; + *destptr++ = source1 + source2 + carry; + carry = + (carry + ? source1 >= (mp_limb_t) ~source2 + : source1 > (mp_limb_t) ~source2); + } + } + /* Forget about the carry and about r[j+n]. */ + } + } + /* q* is determined. Store it as q[j]. */ + q_ptr[j] = q_star; + if (j == 0) + break; + j--; + } + } + r_len = b_len; + /* Normalise q. */ + if (q_ptr[q_len - 1] == 0) + q_len--; +# if 0 /* Not needed here, since we need r only to compare it with b/2, and + b is shifted left by s bits. */ + /* Shift r right by s bits. */ + if (s > 0) + { + mp_limb_t ptr = r_ptr + r_len; + mp_twolimb_t accu = 0; + size_t count; + for (count = r_len; count > 0; count--) + { + accu = (mp_twolimb_t) (mp_limb_t) accu << GMP_LIMB_BITS; + accu += (mp_twolimb_t) *--ptr << (GMP_LIMB_BITS - s); + *ptr = (mp_limb_t) (accu >> GMP_LIMB_BITS); + } + } +# endif + /* Normalise r. */ + while (r_len > 0 && r_ptr[r_len - 1] == 0) + r_len--; + } + /* Compare r << 1 with b. */ + if (r_len > b_len) + goto increment_q; + { + size_t i; + for (i = b_len;;) + { + mp_limb_t r_i = + (i <= r_len && i > 0 ? r_ptr[i - 1] >> (GMP_LIMB_BITS - 1) : 0) + | (i < r_len ? r_ptr[i] << 1 : 0); + mp_limb_t b_i = (i < b_len ? b_ptr[i] : 0); + if (r_i > b_i) + goto increment_q; + if (r_i < b_i) + goto keep_q; + if (i == 0) + break; + i--; + } + } + if (q_len > 0 && ((q_ptr[0] & 1) != 0)) + /* q is odd. */ + increment_q: + { + size_t i; + for (i = 0; i < q_len; i++) + if (++(q_ptr[i]) != 0) + goto keep_q; + q_ptr[q_len++] = 1; + } + keep_q: + if (tmp_roomptr != NULL) + free (tmp_roomptr); + q->limbs = q_ptr; + q->nlimbs = q_len; + return roomptr; +} + +/* Convert a bignum a >= 0, multiplied with 10^extra_zeroes, to decimal + representation. + Destroys the contents of a. + Return the allocated memory - containing the decimal digits in low-to-high + order, terminated with a NUL character - in case of success, NULL in case + of memory allocation failure. */ +static char * +convert_to_decimal (mpn_t a, size_t extra_zeroes) +{ + mp_limb_t *a_ptr = a.limbs; + size_t a_len = a.nlimbs; + /* 0.03345 is slightly larger than log(2)/(9*log(10)). */ + size_t c_len = 9 * ((size_t)(a_len * (GMP_LIMB_BITS * 0.03345f)) + 1); + char *c_ptr = (char *) malloc (xsum (c_len, extra_zeroes)); + if (c_ptr != NULL) + { + char *d_ptr = c_ptr; + for (; extra_zeroes > 0; extra_zeroes--) + *d_ptr++ = '0'; + while (a_len > 0) + { + /* Divide a by 10^9, in-place. */ + mp_limb_t remainder = 0; + mp_limb_t *ptr = a_ptr + a_len; + size_t count; + for (count = a_len; count > 0; count--) + { + mp_twolimb_t num = + ((mp_twolimb_t) remainder << GMP_LIMB_BITS) | *--ptr; + *ptr = num / 1000000000; + remainder = num % 1000000000; + } + /* Store the remainder as 9 decimal digits. */ + for (count = 9; count > 0; count--) + { + *d_ptr++ = '0' + (remainder % 10); + remainder = remainder / 10; + } + /* Normalize a. */ + if (a_ptr[a_len - 1] == 0) + a_len--; + } + /* Remove leading zeroes. */ + while (d_ptr > c_ptr && d_ptr[-1] == '0') + d_ptr--; + /* But keep at least one zero. */ + if (d_ptr == c_ptr) + *d_ptr++ = '0'; + /* Terminate the string. */ + *d_ptr = '\0'; + } + return c_ptr; +} + +# if NEED_PRINTF_LONG_DOUBLE + +/* Assuming x is finite and >= 0: + write x as x = 2^e * m, where m is a bignum. + Return the allocated memory in case of success, NULL in case of memory + allocation failure. */ +static void * +decode_long_double (long double x, int *ep, mpn_t *mp) +{ + mpn_t m; + int exp; + long double y; + size_t i; + + /* Allocate memory for result. */ + m.nlimbs = (LDBL_MANT_BIT + GMP_LIMB_BITS - 1) / GMP_LIMB_BITS; + m.limbs = (mp_limb_t *) malloc (m.nlimbs * sizeof (mp_limb_t)); + if (m.limbs == NULL) + return NULL; + /* Split into exponential part and mantissa. */ + y = frexpl (x, &exp); + if (!(y >= 0.0L && y < 1.0L)) + abort (); + /* x = 2^exp * y = 2^(exp - LDBL_MANT_BIT) * (y * 2^LDBL_MANT_BIT), and the + latter is an integer. */ + /* Convert the mantissa (y * 2^LDBL_MANT_BIT) to a sequence of limbs. + I'm not sure whether it's safe to cast a 'long double' value between + 2^31 and 2^32 to 'unsigned int', therefore play safe and cast only + 'long double' values between 0 and 2^16 (to 'unsigned int' or 'int', + doesn't matter). */ +# if (LDBL_MANT_BIT % GMP_LIMB_BITS) != 0 +# if (LDBL_MANT_BIT % GMP_LIMB_BITS) > GMP_LIMB_BITS / 2 + { + mp_limb_t hi, lo; + y *= (mp_limb_t) 1 << (LDBL_MANT_BIT % (GMP_LIMB_BITS / 2)); + hi = (int) y; + y -= hi; + if (!(y >= 0.0L && y < 1.0L)) + abort (); + y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2); + lo = (int) y; + y -= lo; + if (!(y >= 0.0L && y < 1.0L)) + abort (); + m.limbs[LDBL_MANT_BIT / GMP_LIMB_BITS] = (hi << (GMP_LIMB_BITS / 2)) | lo; + } +# else + { + mp_limb_t d; + y *= (mp_limb_t) 1 << (LDBL_MANT_BIT % GMP_LIMB_BITS); + d = (int) y; + y -= d; + if (!(y >= 0.0L && y < 1.0L)) + abort (); + m.limbs[LDBL_MANT_BIT / GMP_LIMB_BITS] = d; + } +# endif +# endif + for (i = LDBL_MANT_BIT / GMP_LIMB_BITS; i > 0; ) + { + mp_limb_t hi, lo; + y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2); + hi = (int) y; + y -= hi; + if (!(y >= 0.0L && y < 1.0L)) + abort (); + y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2); + lo = (int) y; + y -= lo; + if (!(y >= 0.0L && y < 1.0L)) + abort (); + m.limbs[--i] = (hi << (GMP_LIMB_BITS / 2)) | lo; + } +# if 0 /* On FreeBSD 6.1/x86, 'long double' numbers sometimes have excess + precision. */ + if (!(y == 0.0L)) + abort (); +# endif + /* Normalise. */ + while (m.nlimbs > 0 && m.limbs[m.nlimbs - 1] == 0) + m.nlimbs--; + *mp = m; + *ep = exp - LDBL_MANT_BIT; + return m.limbs; +} + +# endif + +# if NEED_PRINTF_DOUBLE + +/* Assuming x is finite and >= 0: + write x as x = 2^e * m, where m is a bignum. + Return the allocated memory in case of success, NULL in case of memory + allocation failure. */ +static void * +decode_double (double x, int *ep, mpn_t *mp) +{ + mpn_t m; + int exp; + double y; + size_t i; + + /* Allocate memory for result. */ + m.nlimbs = (DBL_MANT_BIT + GMP_LIMB_BITS - 1) / GMP_LIMB_BITS; + m.limbs = (mp_limb_t *) malloc (m.nlimbs * sizeof (mp_limb_t)); + if (m.limbs == NULL) + return NULL; + /* Split into exponential part and mantissa. */ + y = frexp (x, &exp); + if (!(y >= 0.0 && y < 1.0)) + abort (); + /* x = 2^exp * y = 2^(exp - DBL_MANT_BIT) * (y * 2^DBL_MANT_BIT), and the + latter is an integer. */ + /* Convert the mantissa (y * 2^DBL_MANT_BIT) to a sequence of limbs. + I'm not sure whether it's safe to cast a 'double' value between + 2^31 and 2^32 to 'unsigned int', therefore play safe and cast only + 'double' values between 0 and 2^16 (to 'unsigned int' or 'int', + doesn't matter). */ +# if (DBL_MANT_BIT % GMP_LIMB_BITS) != 0 +# if (DBL_MANT_BIT % GMP_LIMB_BITS) > GMP_LIMB_BITS / 2 + { + mp_limb_t hi, lo; + y *= (mp_limb_t) 1 << (DBL_MANT_BIT % (GMP_LIMB_BITS / 2)); + hi = (int) y; + y -= hi; + if (!(y >= 0.0 && y < 1.0)) + abort (); + y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2); + lo = (int) y; + y -= lo; + if (!(y >= 0.0 && y < 1.0)) + abort (); + m.limbs[DBL_MANT_BIT / GMP_LIMB_BITS] = (hi << (GMP_LIMB_BITS / 2)) | lo; + } +# else + { + mp_limb_t d; + y *= (mp_limb_t) 1 << (DBL_MANT_BIT % GMP_LIMB_BITS); + d = (int) y; + y -= d; + if (!(y >= 0.0 && y < 1.0)) + abort (); + m.limbs[DBL_MANT_BIT / GMP_LIMB_BITS] = d; + } +# endif +# endif + for (i = DBL_MANT_BIT / GMP_LIMB_BITS; i > 0; ) + { + mp_limb_t hi, lo; + y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2); + hi = (int) y; + y -= hi; + if (!(y >= 0.0 && y < 1.0)) + abort (); + y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2); + lo = (int) y; + y -= lo; + if (!(y >= 0.0 && y < 1.0)) + abort (); + m.limbs[--i] = (hi << (GMP_LIMB_BITS / 2)) | lo; + } + if (!(y == 0.0)) + abort (); + /* Normalise. */ + while (m.nlimbs > 0 && m.limbs[m.nlimbs - 1] == 0) + m.nlimbs--; + *mp = m; + *ep = exp - DBL_MANT_BIT; + return m.limbs; +} + +# endif + +/* Assuming x = 2^e * m is finite and >= 0, and n is an integer: + Returns the decimal representation of round (x * 10^n). + Return the allocated memory - containing the decimal digits in low-to-high + order, terminated with a NUL character - in case of success, NULL in case + of memory allocation failure. */ +static char * +scale10_round_decimal_decoded (int e, mpn_t m, void *memory, int n) +{ + int s; + size_t extra_zeroes; + unsigned int abs_n; + unsigned int abs_s; + mp_limb_t *pow5_ptr; + size_t pow5_len; + unsigned int s_limbs; + unsigned int s_bits; + mpn_t pow5; + mpn_t z; + void *z_memory; + char *digits; + + if (memory == NULL) + return NULL; + /* x = 2^e * m, hence + y = round (2^e * 10^n * m) = round (2^(e+n) * 5^n * m) + = round (2^s * 5^n * m). */ + s = e + n; + extra_zeroes = 0; + /* Factor out a common power of 10 if possible. */ + if (s > 0 && n > 0) + { + extra_zeroes = (s < n ? s : n); + s -= extra_zeroes; + n -= extra_zeroes; + } + /* Here y = round (2^s * 5^n * m) * 10^extra_zeroes. + Before converting to decimal, we need to compute + z = round (2^s * 5^n * m). */ + /* Compute 5^|n|, possibly shifted by |s| bits if n and s have the same + sign. 2.322 is slightly larger than log(5)/log(2). */ + abs_n = (n >= 0 ? n : -n); + abs_s = (s >= 0 ? s : -s); + pow5_ptr = (mp_limb_t *) malloc (((int)(abs_n * (2.322f / GMP_LIMB_BITS)) + 1 + + abs_s / GMP_LIMB_BITS + 1) + * sizeof (mp_limb_t)); + if (pow5_ptr == NULL) + { + free (memory); + return NULL; + } + /* Initialize with 1. */ + pow5_ptr[0] = 1; + pow5_len = 1; + /* Multiply with 5^|n|. */ + if (abs_n > 0) + { + static mp_limb_t const small_pow5[13 + 1] = + { + 1, 5, 25, 125, 625, 3125, 15625, 78125, 390625, 1953125, 9765625, + 48828125, 244140625, 1220703125 + }; + unsigned int n13; + for (n13 = 0; n13 <= abs_n; n13 += 13) + { + mp_limb_t digit1 = small_pow5[n13 + 13 <= abs_n ? 13 : abs_n - n13]; + size_t j; + mp_twolimb_t carry = 0; + for (j = 0; j < pow5_len; j++) + { + mp_limb_t digit2 = pow5_ptr[j]; + carry += (mp_twolimb_t) digit1 * (mp_twolimb_t) digit2; + pow5_ptr[j] = (mp_limb_t) carry; + carry = carry >> GMP_LIMB_BITS; + } + if (carry > 0) + pow5_ptr[pow5_len++] = (mp_limb_t) carry; + } + } + s_limbs = abs_s / GMP_LIMB_BITS; + s_bits = abs_s % GMP_LIMB_BITS; + if (n >= 0 ? s >= 0 : s <= 0) + { + /* Multiply with 2^|s|. */ + if (s_bits > 0) + { + mp_limb_t *ptr = pow5_ptr; + mp_twolimb_t accu = 0; + size_t count; + for (count = pow5_len; count > 0; count--) + { + accu += (mp_twolimb_t) *ptr << s_bits; + *ptr++ = (mp_limb_t) accu; + accu = accu >> GMP_LIMB_BITS; + } + if (accu > 0) + { + *ptr = (mp_limb_t) accu; + pow5_len++; + } + } + if (s_limbs > 0) + { + size_t count; + for (count = pow5_len; count > 0;) + { + count--; + pow5_ptr[s_limbs + count] = pow5_ptr[count]; + } + for (count = s_limbs; count > 0;) + { + count--; + pow5_ptr[count] = 0; + } + pow5_len += s_limbs; + } + pow5.limbs = pow5_ptr; + pow5.nlimbs = pow5_len; + if (n >= 0) + { + /* Multiply m with pow5. No division needed. */ + z_memory = multiply (m, pow5, &z); + } + else + { + /* Divide m by pow5 and round. */ + z_memory = divide (m, pow5, &z); + } + } + else + { + pow5.limbs = pow5_ptr; + pow5.nlimbs = pow5_len; + if (n >= 0) + { + /* n >= 0, s < 0. + Multiply m with pow5, then divide by 2^|s|. */ + mpn_t numerator; + mpn_t denominator; + void *tmp_memory; + tmp_memory = multiply (m, pow5, &numerator); + if (tmp_memory == NULL) + { + free (pow5_ptr); + free (memory); + return NULL; + } + /* Construct 2^|s|. */ + { + mp_limb_t *ptr = pow5_ptr + pow5_len; + size_t i; + for (i = 0; i < s_limbs; i++) + ptr[i] = 0; + ptr[s_limbs] = (mp_limb_t) 1 << s_bits; + denominator.limbs = ptr; + denominator.nlimbs = s_limbs + 1; + } + z_memory = divide (numerator, denominator, &z); + free (tmp_memory); + } + else + { + /* n < 0, s > 0. + Multiply m with 2^s, then divide by pow5. */ + mpn_t numerator; + mp_limb_t *num_ptr; + num_ptr = (mp_limb_t *) malloc ((m.nlimbs + s_limbs + 1) + * sizeof (mp_limb_t)); + if (num_ptr == NULL) + { + free (pow5_ptr); + free (memory); + return NULL; + } + { + mp_limb_t *destptr = num_ptr; + { + size_t i; + for (i = 0; i < s_limbs; i++) + *destptr++ = 0; + } + if (s_bits > 0) + { + const mp_limb_t *sourceptr = m.limbs; + mp_twolimb_t accu = 0; + size_t count; + for (count = m.nlimbs; count > 0; count--) + { + accu += (mp_twolimb_t) *sourceptr++ << s_bits; + *destptr++ = (mp_limb_t) accu; + accu = accu >> GMP_LIMB_BITS; + } + if (accu > 0) + *destptr++ = (mp_limb_t) accu; + } + else + { + const mp_limb_t *sourceptr = m.limbs; + size_t count; + for (count = m.nlimbs; count > 0; count--) + *destptr++ = *sourceptr++; + } + numerator.limbs = num_ptr; + numerator.nlimbs = destptr - num_ptr; + } + z_memory = divide (numerator, pow5, &z); + free (num_ptr); + } + } + free (pow5_ptr); + free (memory); + + /* Here y = round (x * 10^n) = z * 10^extra_zeroes. */ + + if (z_memory == NULL) + return NULL; + digits = convert_to_decimal (z, extra_zeroes); + free (z_memory); + return digits; +} + +# if NEED_PRINTF_LONG_DOUBLE + +/* Assuming x is finite and >= 0, and n is an integer: + Returns the decimal representation of round (x * 10^n). + Return the allocated memory - containing the decimal digits in low-to-high + order, terminated with a NUL character - in case of success, NULL in case + of memory allocation failure. */ +static char * +scale10_round_decimal_long_double (long double x, int n) +{ + int e IF_LINT(= 0); + mpn_t m; + void *memory = decode_long_double (x, &e, &m); + return scale10_round_decimal_decoded (e, m, memory, n); +} + +# endif + +# if NEED_PRINTF_DOUBLE + +/* Assuming x is finite and >= 0, and n is an integer: + Returns the decimal representation of round (x * 10^n). + Return the allocated memory - containing the decimal digits in low-to-high + order, terminated with a NUL character - in case of success, NULL in case + of memory allocation failure. */ +static char * +scale10_round_decimal_double (double x, int n) +{ + int e IF_LINT(= 0); + mpn_t m; + void *memory = decode_double (x, &e, &m); + return scale10_round_decimal_decoded (e, m, memory, n); +} + +# endif + +# if NEED_PRINTF_LONG_DOUBLE + +/* Assuming x is finite and > 0: + Return an approximation for n with 10^n <= x < 10^(n+1). + The approximation is usually the right n, but may be off by 1 sometimes. */ +static int +floorlog10l (long double x) +{ + int exp; + long double y; + double z; + double l; + + /* Split into exponential part and mantissa. */ + y = frexpl (x, &exp); + if (!(y >= 0.0L && y < 1.0L)) + abort (); + if (y == 0.0L) + return INT_MIN; + if (y < 0.5L) + { + while (y < (1.0L / (1 << (GMP_LIMB_BITS / 2)) / (1 << (GMP_LIMB_BITS / 2)))) + { + y *= 1.0L * (1 << (GMP_LIMB_BITS / 2)) * (1 << (GMP_LIMB_BITS / 2)); + exp -= GMP_LIMB_BITS; + } + if (y < (1.0L / (1 << 16))) + { + y *= 1.0L * (1 << 16); + exp -= 16; + } + if (y < (1.0L / (1 << 8))) + { + y *= 1.0L * (1 << 8); + exp -= 8; + } + if (y < (1.0L / (1 << 4))) + { + y *= 1.0L * (1 << 4); + exp -= 4; + } + if (y < (1.0L / (1 << 2))) + { + y *= 1.0L * (1 << 2); + exp -= 2; + } + if (y < (1.0L / (1 << 1))) + { + y *= 1.0L * (1 << 1); + exp -= 1; + } + } + if (!(y >= 0.5L && y < 1.0L)) + abort (); + /* Compute an approximation for l = log2(x) = exp + log2(y). */ + l = exp; + z = y; + if (z < 0.70710678118654752444) + { + z *= 1.4142135623730950488; + l -= 0.5; + } + if (z < 0.8408964152537145431) + { + z *= 1.1892071150027210667; + l -= 0.25; + } + if (z < 0.91700404320467123175) + { + z *= 1.0905077326652576592; + l -= 0.125; + } + if (z < 0.9576032806985736469) + { + z *= 1.0442737824274138403; + l -= 0.0625; + } + /* Now 0.95 <= z <= 1.01. */ + z = 1 - z; + /* log2(1-z) = 1/log(2) * (- z - z^2/2 - z^3/3 - z^4/4 - ...) + Four terms are enough to get an approximation with error < 10^-7. */ + l -= 1.4426950408889634074 * z * (1.0 + z * (0.5 + z * ((1.0 / 3) + z * 0.25))); + /* Finally multiply with log(2)/log(10), yields an approximation for + log10(x). */ + l *= 0.30102999566398119523; + /* Round down to the next integer. */ + return (int) l + (l < 0 ? -1 : 0); +} + +# endif + +# if NEED_PRINTF_DOUBLE + +/* Assuming x is finite and > 0: + Return an approximation for n with 10^n <= x < 10^(n+1). + The approximation is usually the right n, but may be off by 1 sometimes. */ +static int +floorlog10 (double x) +{ + int exp; + double y; + double z; + double l; + + /* Split into exponential part and mantissa. */ + y = frexp (x, &exp); + if (!(y >= 0.0 && y < 1.0)) + abort (); + if (y == 0.0) + return INT_MIN; + if (y < 0.5) + { + while (y < (1.0 / (1 << (GMP_LIMB_BITS / 2)) / (1 << (GMP_LIMB_BITS / 2)))) + { + y *= 1.0 * (1 << (GMP_LIMB_BITS / 2)) * (1 << (GMP_LIMB_BITS / 2)); + exp -= GMP_LIMB_BITS; + } + if (y < (1.0 / (1 << 16))) + { + y *= 1.0 * (1 << 16); + exp -= 16; + } + if (y < (1.0 / (1 << 8))) + { + y *= 1.0 * (1 << 8); + exp -= 8; + } + if (y < (1.0 / (1 << 4))) + { + y *= 1.0 * (1 << 4); + exp -= 4; + } + if (y < (1.0 / (1 << 2))) + { + y *= 1.0 * (1 << 2); + exp -= 2; + } + if (y < (1.0 / (1 << 1))) + { + y *= 1.0 * (1 << 1); + exp -= 1; + } + } + if (!(y >= 0.5 && y < 1.0)) + abort (); + /* Compute an approximation for l = log2(x) = exp + log2(y). */ + l = exp; + z = y; + if (z < 0.70710678118654752444) + { + z *= 1.4142135623730950488; + l -= 0.5; + } + if (z < 0.8408964152537145431) + { + z *= 1.1892071150027210667; + l -= 0.25; + } + if (z < 0.91700404320467123175) + { + z *= 1.0905077326652576592; + l -= 0.125; + } + if (z < 0.9576032806985736469) + { + z *= 1.0442737824274138403; + l -= 0.0625; + } + /* Now 0.95 <= z <= 1.01. */ + z = 1 - z; + /* log2(1-z) = 1/log(2) * (- z - z^2/2 - z^3/3 - z^4/4 - ...) + Four terms are enough to get an approximation with error < 10^-7. */ + l -= 1.4426950408889634074 * z * (1.0 + z * (0.5 + z * ((1.0 / 3) + z * 0.25))); + /* Finally multiply with log(2)/log(10), yields an approximation for + log10(x). */ + l *= 0.30102999566398119523; + /* Round down to the next integer. */ + return (int) l + (l < 0 ? -1 : 0); +} + +# endif + +/* Tests whether a string of digits consists of exactly PRECISION zeroes and + a single '1' digit. */ +static int +is_borderline (const char *digits, size_t precision) +{ + for (; precision > 0; precision--, digits++) + if (*digits != '0') + return 0; + if (*digits != '1') + return 0; + digits++; + return *digits == '\0'; +} + +#endif + +#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 + +/* Use a different function name, to make it possible that the 'wchar_t' + parametrization and the 'char' parametrization get compiled in the same + translation unit. */ +# if WIDE_CHAR_VERSION +# define MAX_ROOM_NEEDED wmax_room_needed +# else +# define MAX_ROOM_NEEDED max_room_needed +# endif + +/* Returns the number of TCHAR_T units needed as temporary space for the result + of sprintf or SNPRINTF of a single conversion directive. */ +static size_t +MAX_ROOM_NEEDED (const arguments *ap, size_t arg_index, FCHAR_T conversion, + arg_type type, int flags, size_t width, int has_precision, + size_t precision, int pad_ourselves) +{ + size_t tmp_length; + + switch (conversion) + { + case 'd': case 'i': case 'u': +# if HAVE_LONG_LONG_INT + if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT) + tmp_length = + (unsigned int) (sizeof (unsigned long long) * CHAR_BIT + * 0.30103 /* binary -> decimal */ + ) + + 1; /* turn floor into ceil */ + else +# endif + if (type == TYPE_LONGINT || type == TYPE_ULONGINT) + tmp_length = + (unsigned int) (sizeof (unsigned long) * CHAR_BIT + * 0.30103 /* binary -> decimal */ + ) + + 1; /* turn floor into ceil */ + else + tmp_length = + (unsigned int) (sizeof (unsigned int) * CHAR_BIT + * 0.30103 /* binary -> decimal */ + ) + + 1; /* turn floor into ceil */ + if (tmp_length < precision) + tmp_length = precision; + /* Multiply by 2, as an estimate for FLAG_GROUP. */ + tmp_length = xsum (tmp_length, tmp_length); + /* Add 1, to account for a leading sign. */ + tmp_length = xsum (tmp_length, 1); + break; + + case 'o': +# if HAVE_LONG_LONG_INT + if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT) + tmp_length = + (unsigned int) (sizeof (unsigned long long) * CHAR_BIT + * 0.333334 /* binary -> octal */ + ) + + 1; /* turn floor into ceil */ + else +# endif + if (type == TYPE_LONGINT || type == TYPE_ULONGINT) + tmp_length = + (unsigned int) (sizeof (unsigned long) * CHAR_BIT + * 0.333334 /* binary -> octal */ + ) + + 1; /* turn floor into ceil */ + else + tmp_length = + (unsigned int) (sizeof (unsigned int) * CHAR_BIT + * 0.333334 /* binary -> octal */ + ) + + 1; /* turn floor into ceil */ + if (tmp_length < precision) + tmp_length = precision; + /* Add 1, to account for a leading sign. */ + tmp_length = xsum (tmp_length, 1); + break; + + case 'x': case 'X': +# if HAVE_LONG_LONG_INT + if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT) + tmp_length = + (unsigned int) (sizeof (unsigned long long) * CHAR_BIT + * 0.25 /* binary -> hexadecimal */ + ) + + 1; /* turn floor into ceil */ + else +# endif + if (type == TYPE_LONGINT || type == TYPE_ULONGINT) + tmp_length = + (unsigned int) (sizeof (unsigned long) * CHAR_BIT + * 0.25 /* binary -> hexadecimal */ + ) + + 1; /* turn floor into ceil */ + else + tmp_length = + (unsigned int) (sizeof (unsigned int) * CHAR_BIT + * 0.25 /* binary -> hexadecimal */ + ) + + 1; /* turn floor into ceil */ + if (tmp_length < precision) + tmp_length = precision; + /* Add 2, to account for a leading sign or alternate form. */ + tmp_length = xsum (tmp_length, 2); + break; + + case 'f': case 'F': + if (type == TYPE_LONGDOUBLE) + tmp_length = + (unsigned int) (LDBL_MAX_EXP + * 0.30103 /* binary -> decimal */ + * 2 /* estimate for FLAG_GROUP */ + ) + + 1 /* turn floor into ceil */ + + 10; /* sign, decimal point etc. */ + else + tmp_length = + (unsigned int) (DBL_MAX_EXP + * 0.30103 /* binary -> decimal */ + * 2 /* estimate for FLAG_GROUP */ + ) + + 1 /* turn floor into ceil */ + + 10; /* sign, decimal point etc. */ + tmp_length = xsum (tmp_length, precision); + break; + + case 'e': case 'E': case 'g': case 'G': + tmp_length = + 12; /* sign, decimal point, exponent etc. */ + tmp_length = xsum (tmp_length, precision); + break; + + case 'a': case 'A': + if (type == TYPE_LONGDOUBLE) + tmp_length = + (unsigned int) (LDBL_DIG + * 0.831 /* decimal -> hexadecimal */ + ) + + 1; /* turn floor into ceil */ + else + tmp_length = + (unsigned int) (DBL_DIG + * 0.831 /* decimal -> hexadecimal */ + ) + + 1; /* turn floor into ceil */ + if (tmp_length < precision) + tmp_length = precision; + /* Account for sign, decimal point etc. */ + tmp_length = xsum (tmp_length, 12); + break; + + case 'c': +# if HAVE_WINT_T && !WIDE_CHAR_VERSION + if (type == TYPE_WIDE_CHAR) + tmp_length = MB_CUR_MAX; + else +# endif + tmp_length = 1; + break; + + case 's': +# if HAVE_WCHAR_T + if (type == TYPE_WIDE_STRING) + { +# if WIDE_CHAR_VERSION + /* ISO C says about %ls in fwprintf: + "If the precision is not specified or is greater than the size + of the array, the array shall contain a null wide character." + So if there is a precision, we must not use wcslen. */ + const wchar_t *arg = ap->arg[arg_index].a.a_wide_string; + + if (has_precision) + tmp_length = local_wcsnlen (arg, precision); + else + tmp_length = local_wcslen (arg); +# else + /* ISO C says about %ls in fprintf: + "If a precision is specified, no more than that many bytes are + written (including shift sequences, if any), and the array + shall contain a null wide character if, to equal the multibyte + character sequence length given by the precision, the function + would need to access a wide character one past the end of the + array." + So if there is a precision, we must not use wcslen. */ + /* This case has already been handled separately in VASNPRINTF. */ + abort (); +# endif + } + else +# endif + { +# if WIDE_CHAR_VERSION + /* ISO C says about %s in fwprintf: + "If the precision is not specified or is greater than the size + of the converted array, the converted array shall contain a + null wide character." + So if there is a precision, we must not use strlen. */ + /* This case has already been handled separately in VASNPRINTF. */ + abort (); +# else + /* ISO C says about %s in fprintf: + "If the precision is not specified or greater than the size of + the array, the array shall contain a null character." + So if there is a precision, we must not use strlen. */ + const char *arg = ap->arg[arg_index].a.a_string; + + if (has_precision) + tmp_length = local_strnlen (arg, precision); + else + tmp_length = strlen (arg); +# endif + } + break; + + case 'p': + tmp_length = + (unsigned int) (sizeof (void *) * CHAR_BIT + * 0.25 /* binary -> hexadecimal */ + ) + + 1 /* turn floor into ceil */ + + 2; /* account for leading 0x */ + break; + + default: + abort (); + } + + if (!pad_ourselves) + { +# if ENABLE_UNISTDIO + /* Padding considers the number of characters, therefore the number of + elements after padding may be + > max (tmp_length, width) + but is certainly + <= tmp_length + width. */ + tmp_length = xsum (tmp_length, width); +# else + /* Padding considers the number of elements, says POSIX. */ + if (tmp_length < width) + tmp_length = width; +# endif + } + + tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */ + + return tmp_length; +} + +#endif + +DCHAR_T * +VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, + const FCHAR_T *format, va_list args) +{ + DIRECTIVES d; + arguments a; + + if (PRINTF_PARSE (format, &d, &a) < 0) + /* errno is already set. */ + return NULL; + +#define CLEANUP() \ + if (d.dir != d.direct_alloc_dir) \ + free (d.dir); \ + if (a.arg != a.direct_alloc_arg) \ + free (a.arg); + + if (PRINTF_FETCHARGS (args, &a) < 0) + { + CLEANUP (); + errno = EINVAL; + return NULL; + } + + { + size_t buf_neededlength; + TCHAR_T *buf; + TCHAR_T *buf_malloced; + const FCHAR_T *cp; + size_t i; + DIRECTIVE *dp; + /* Output string accumulator. */ + DCHAR_T *result; + size_t allocated; + size_t length; + + /* Allocate a small buffer that will hold a directive passed to + sprintf or snprintf. */ + buf_neededlength = + xsum4 (7, d.max_width_length, d.max_precision_length, 6); +#if HAVE_ALLOCA + if (buf_neededlength < 4000 / sizeof (TCHAR_T)) + { + buf = (TCHAR_T *) alloca (buf_neededlength * sizeof (TCHAR_T)); + buf_malloced = NULL; + } + else +#endif + { + size_t buf_memsize = xtimes (buf_neededlength, sizeof (TCHAR_T)); + if (size_overflow_p (buf_memsize)) + goto out_of_memory_1; + buf = (TCHAR_T *) malloc (buf_memsize); + if (buf == NULL) + goto out_of_memory_1; + buf_malloced = buf; + } + + if (resultbuf != NULL) + { + result = resultbuf; + allocated = *lengthp; + } + else + { + result = NULL; + allocated = 0; + } + length = 0; + /* Invariants: + result is either == resultbuf or == NULL or malloc-allocated. + If length > 0, then result != NULL. */ + + /* Ensures that allocated >= needed. Aborts through a jump to + out_of_memory if needed is SIZE_MAX or otherwise too big. */ +#define ENSURE_ALLOCATION(needed) \ + if ((needed) > allocated) \ + { \ + size_t memory_size; \ + DCHAR_T *memory; \ + \ + allocated = (allocated > 0 ? xtimes (allocated, 2) : 12); \ + if ((needed) > allocated) \ + allocated = (needed); \ + memory_size = xtimes (allocated, sizeof (DCHAR_T)); \ + if (size_overflow_p (memory_size)) \ + goto out_of_memory; \ + if (result == resultbuf || result == NULL) \ + memory = (DCHAR_T *) malloc (memory_size); \ + else \ + memory = (DCHAR_T *) realloc (result, memory_size); \ + if (memory == NULL) \ + goto out_of_memory; \ + if (result == resultbuf && length > 0) \ + DCHAR_CPY (memory, result, length); \ + result = memory; \ + } + + for (cp = format, i = 0, dp = &d.dir[0]; ; cp = dp->dir_end, i++, dp++) + { + if (cp != dp->dir_start) + { + size_t n = dp->dir_start - cp; + size_t augmented_length = xsum (length, n); + + ENSURE_ALLOCATION (augmented_length); + /* This copies a piece of FCHAR_T[] into a DCHAR_T[]. Here we + need that the format string contains only ASCII characters + if FCHAR_T and DCHAR_T are not the same type. */ + if (sizeof (FCHAR_T) == sizeof (DCHAR_T)) + { + DCHAR_CPY (result + length, (const DCHAR_T *) cp, n); + length = augmented_length; + } + else + { + do + result[length++] = (unsigned char) *cp++; + while (--n > 0); + } + } + if (i == d.count) + break; + + /* Execute a single directive. */ + if (dp->conversion == '%') + { + size_t augmented_length; + + if (!(dp->arg_index == ARG_NONE)) + abort (); + augmented_length = xsum (length, 1); + ENSURE_ALLOCATION (augmented_length); + result[length] = '%'; + length = augmented_length; + } + else + { + if (!(dp->arg_index != ARG_NONE)) + abort (); + + if (dp->conversion == 'n') + { + switch (a.arg[dp->arg_index].type) + { + case TYPE_COUNT_SCHAR_POINTER: + *a.arg[dp->arg_index].a.a_count_schar_pointer = length; + break; + case TYPE_COUNT_SHORT_POINTER: + *a.arg[dp->arg_index].a.a_count_short_pointer = length; + break; + case TYPE_COUNT_INT_POINTER: + *a.arg[dp->arg_index].a.a_count_int_pointer = length; + break; + case TYPE_COUNT_LONGINT_POINTER: + *a.arg[dp->arg_index].a.a_count_longint_pointer = length; + break; +#if HAVE_LONG_LONG_INT + case TYPE_COUNT_LONGLONGINT_POINTER: + *a.arg[dp->arg_index].a.a_count_longlongint_pointer = length; + break; +#endif + default: + abort (); + } + } +#if ENABLE_UNISTDIO + /* The unistdio extensions. */ + else if (dp->conversion == 'U') + { + arg_type type = a.arg[dp->arg_index].type; + int flags = dp->flags; + int has_width; + size_t width; + int has_precision; + size_t precision; + + has_width = 0; + width = 0; + if (dp->width_start != dp->width_end) + { + if (dp->width_arg_index != ARG_NONE) + { + int arg; + + if (!(a.arg[dp->width_arg_index].type == TYPE_INT)) + abort (); + arg = a.arg[dp->width_arg_index].a.a_int; + width = arg; + if (arg < 0) + { + /* "A negative field width is taken as a '-' flag + followed by a positive field width." */ + flags |= FLAG_LEFT; + width = -width; + } + } + else + { + const FCHAR_T *digitp = dp->width_start; + + do + width = xsum (xtimes (width, 10), *digitp++ - '0'); + while (digitp != dp->width_end); + } + has_width = 1; + } + + has_precision = 0; + precision = 0; + if (dp->precision_start != dp->precision_end) + { + if (dp->precision_arg_index != ARG_NONE) + { + int arg; + + if (!(a.arg[dp->precision_arg_index].type == TYPE_INT)) + abort (); + arg = a.arg[dp->precision_arg_index].a.a_int; + /* "A negative precision is taken as if the precision + were omitted." */ + if (arg >= 0) + { + precision = arg; + has_precision = 1; + } + } + else + { + const FCHAR_T *digitp = dp->precision_start + 1; + + precision = 0; + while (digitp != dp->precision_end) + precision = xsum (xtimes (precision, 10), *digitp++ - '0'); + has_precision = 1; + } + } + + switch (type) + { + case TYPE_U8_STRING: + { + const uint8_t *arg = a.arg[dp->arg_index].a.a_u8_string; + const uint8_t *arg_end; + size_t characters; + + if (has_precision) + { + /* Use only PRECISION characters, from the left. */ + arg_end = arg; + characters = 0; + for (; precision > 0; precision--) + { + int count = u8_strmblen (arg_end); + if (count == 0) + break; + if (count < 0) + { + if (!(result == resultbuf || result == NULL)) + free (result); + if (buf_malloced != NULL) + free (buf_malloced); + CLEANUP (); + errno = EILSEQ; + return NULL; + } + arg_end += count; + characters++; + } + } + else if (has_width) + { + /* Use the entire string, and count the number of + characters. */ + arg_end = arg; + characters = 0; + for (;;) + { + int count = u8_strmblen (arg_end); + if (count == 0) + break; + if (count < 0) + { + if (!(result == resultbuf || result == NULL)) + free (result); + if (buf_malloced != NULL) + free (buf_malloced); + CLEANUP (); + errno = EILSEQ; + return NULL; + } + arg_end += count; + characters++; + } + } + else + { + /* Use the entire string. */ + arg_end = arg + u8_strlen (arg); + /* The number of characters doesn't matter. */ + characters = 0; + } + + if (characters < width && !(dp->flags & FLAG_LEFT)) + { + size_t n = width - characters; + ENSURE_ALLOCATION (xsum (length, n)); + DCHAR_SET (result + length, ' ', n); + length += n; + } + +# if DCHAR_IS_UINT8_T + { + size_t n = arg_end - arg; + ENSURE_ALLOCATION (xsum (length, n)); + DCHAR_CPY (result + length, arg, n); + length += n; + } +# else + { /* Convert. */ + DCHAR_T *converted = result + length; + size_t converted_len = allocated - length; +# if DCHAR_IS_TCHAR + /* Convert from UTF-8 to locale encoding. */ + converted = + u8_conv_to_encoding (locale_charset (), + iconveh_question_mark, + arg, arg_end - arg, NULL, + converted, &converted_len); +# else + /* Convert from UTF-8 to UTF-16/UTF-32. */ + converted = + U8_TO_DCHAR (arg, arg_end - arg, + converted, &converted_len); +# endif + if (converted == NULL) + { + int saved_errno = errno; + if (!(result == resultbuf || result == NULL)) + free (result); + if (buf_malloced != NULL) + free (buf_malloced); + CLEANUP (); + errno = saved_errno; + return NULL; + } + if (converted != result + length) + { + ENSURE_ALLOCATION (xsum (length, converted_len)); + DCHAR_CPY (result + length, converted, converted_len); + free (converted); + } + length += converted_len; + } +# endif + + if (characters < width && (dp->flags & FLAG_LEFT)) + { + size_t n = width - characters; + ENSURE_ALLOCATION (xsum (length, n)); + DCHAR_SET (result + length, ' ', n); + length += n; + } + } + break; + + case TYPE_U16_STRING: + { + const uint16_t *arg = a.arg[dp->arg_index].a.a_u16_string; + const uint16_t *arg_end; + size_t characters; + + if (has_precision) + { + /* Use only PRECISION characters, from the left. */ + arg_end = arg; + characters = 0; + for (; precision > 0; precision--) + { + int count = u16_strmblen (arg_end); + if (count == 0) + break; + if (count < 0) + { + if (!(result == resultbuf || result == NULL)) + free (result); + if (buf_malloced != NULL) + free (buf_malloced); + CLEANUP (); + errno = EILSEQ; + return NULL; + } + arg_end += count; + characters++; + } + } + else if (has_width) + { + /* Use the entire string, and count the number of + characters. */ + arg_end = arg; + characters = 0; + for (;;) + { + int count = u16_strmblen (arg_end); + if (count == 0) + break; + if (count < 0) + { + if (!(result == resultbuf || result == NULL)) + free (result); + if (buf_malloced != NULL) + free (buf_malloced); + CLEANUP (); + errno = EILSEQ; + return NULL; + } + arg_end += count; + characters++; + } + } + else + { + /* Use the entire string. */ + arg_end = arg + u16_strlen (arg); + /* The number of characters doesn't matter. */ + characters = 0; + } + + if (characters < width && !(dp->flags & FLAG_LEFT)) + { + size_t n = width - characters; + ENSURE_ALLOCATION (xsum (length, n)); + DCHAR_SET (result + length, ' ', n); + length += n; + } + +# if DCHAR_IS_UINT16_T + { + size_t n = arg_end - arg; + ENSURE_ALLOCATION (xsum (length, n)); + DCHAR_CPY (result + length, arg, n); + length += n; + } +# else + { /* Convert. */ + DCHAR_T *converted = result + length; + size_t converted_len = allocated - length; +# if DCHAR_IS_TCHAR + /* Convert from UTF-16 to locale encoding. */ + converted = + u16_conv_to_encoding (locale_charset (), + iconveh_question_mark, + arg, arg_end - arg, NULL, + converted, &converted_len); +# else + /* Convert from UTF-16 to UTF-8/UTF-32. */ + converted = + U16_TO_DCHAR (arg, arg_end - arg, + converted, &converted_len); +# endif + if (converted == NULL) + { + int saved_errno = errno; + if (!(result == resultbuf || result == NULL)) + free (result); + if (buf_malloced != NULL) + free (buf_malloced); + CLEANUP (); + errno = saved_errno; + return NULL; + } + if (converted != result + length) + { + ENSURE_ALLOCATION (xsum (length, converted_len)); + DCHAR_CPY (result + length, converted, converted_len); + free (converted); + } + length += converted_len; + } +# endif + + if (characters < width && (dp->flags & FLAG_LEFT)) + { + size_t n = width - characters; + ENSURE_ALLOCATION (xsum (length, n)); + DCHAR_SET (result + length, ' ', n); + length += n; + } + } + break; + + case TYPE_U32_STRING: + { + const uint32_t *arg = a.arg[dp->arg_index].a.a_u32_string; + const uint32_t *arg_end; + size_t characters; + + if (has_precision) + { + /* Use only PRECISION characters, from the left. */ + arg_end = arg; + characters = 0; + for (; precision > 0; precision--) + { + int count = u32_strmblen (arg_end); + if (count == 0) + break; + if (count < 0) + { + if (!(result == resultbuf || result == NULL)) + free (result); + if (buf_malloced != NULL) + free (buf_malloced); + CLEANUP (); + errno = EILSEQ; + return NULL; + } + arg_end += count; + characters++; + } + } + else if (has_width) + { + /* Use the entire string, and count the number of + characters. */ + arg_end = arg; + characters = 0; + for (;;) + { + int count = u32_strmblen (arg_end); + if (count == 0) + break; + if (count < 0) + { + if (!(result == resultbuf || result == NULL)) + free (result); + if (buf_malloced != NULL) + free (buf_malloced); + CLEANUP (); + errno = EILSEQ; + return NULL; + } + arg_end += count; + characters++; + } + } + else + { + /* Use the entire string. */ + arg_end = arg + u32_strlen (arg); + /* The number of characters doesn't matter. */ + characters = 0; + } + + if (characters < width && !(dp->flags & FLAG_LEFT)) + { + size_t n = width - characters; + ENSURE_ALLOCATION (xsum (length, n)); + DCHAR_SET (result + length, ' ', n); + length += n; + } + +# if DCHAR_IS_UINT32_T + { + size_t n = arg_end - arg; + ENSURE_ALLOCATION (xsum (length, n)); + DCHAR_CPY (result + length, arg, n); + length += n; + } +# else + { /* Convert. */ + DCHAR_T *converted = result + length; + size_t converted_len = allocated - length; +# if DCHAR_IS_TCHAR + /* Convert from UTF-32 to locale encoding. */ + converted = + u32_conv_to_encoding (locale_charset (), + iconveh_question_mark, + arg, arg_end - arg, NULL, + converted, &converted_len); +# else + /* Convert from UTF-32 to UTF-8/UTF-16. */ + converted = + U32_TO_DCHAR (arg, arg_end - arg, + converted, &converted_len); +# endif + if (converted == NULL) + { + int saved_errno = errno; + if (!(result == resultbuf || result == NULL)) + free (result); + if (buf_malloced != NULL) + free (buf_malloced); + CLEANUP (); + errno = saved_errno; + return NULL; + } + if (converted != result + length) + { + ENSURE_ALLOCATION (xsum (length, converted_len)); + DCHAR_CPY (result + length, converted, converted_len); + free (converted); + } + length += converted_len; + } +# endif + + if (characters < width && (dp->flags & FLAG_LEFT)) + { + size_t n = width - characters; + ENSURE_ALLOCATION (xsum (length, n)); + DCHAR_SET (result + length, ' ', n); + length += n; + } + } + break; + + default: + abort (); + } + } +#endif +#if (!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || (NEED_PRINTF_DIRECTIVE_LS && !defined IN_LIBINTL)) && HAVE_WCHAR_T + else if (dp->conversion == 's' +# if WIDE_CHAR_VERSION + && a.arg[dp->arg_index].type != TYPE_WIDE_STRING +# else + && a.arg[dp->arg_index].type == TYPE_WIDE_STRING +# endif + ) + { + /* The normal handling of the 's' directive below requires + allocating a temporary buffer. The determination of its + length (tmp_length), in the case when a precision is + specified, below requires a conversion between a char[] + string and a wchar_t[] wide string. It could be done, but + we have no guarantee that the implementation of sprintf will + use the exactly same algorithm. Without this guarantee, it + is possible to have buffer overrun bugs. In order to avoid + such bugs, we implement the entire processing of the 's' + directive ourselves. */ + int flags = dp->flags; + int has_width; + size_t width; + int has_precision; + size_t precision; + + has_width = 0; + width = 0; + if (dp->width_start != dp->width_end) + { + if (dp->width_arg_index != ARG_NONE) + { + int arg; + + if (!(a.arg[dp->width_arg_index].type == TYPE_INT)) + abort (); + arg = a.arg[dp->width_arg_index].a.a_int; + width = arg; + if (arg < 0) + { + /* "A negative field width is taken as a '-' flag + followed by a positive field width." */ + flags |= FLAG_LEFT; + width = -width; + } + } + else + { + const FCHAR_T *digitp = dp->width_start; + + do + width = xsum (xtimes (width, 10), *digitp++ - '0'); + while (digitp != dp->width_end); + } + has_width = 1; + } + + has_precision = 0; + precision = 6; + if (dp->precision_start != dp->precision_end) + { + if (dp->precision_arg_index != ARG_NONE) + { + int arg; + + if (!(a.arg[dp->precision_arg_index].type == TYPE_INT)) + abort (); + arg = a.arg[dp->precision_arg_index].a.a_int; + /* "A negative precision is taken as if the precision + were omitted." */ + if (arg >= 0) + { + precision = arg; + has_precision = 1; + } + } + else + { + const FCHAR_T *digitp = dp->precision_start + 1; + + precision = 0; + while (digitp != dp->precision_end) + precision = xsum (xtimes (precision, 10), *digitp++ - '0'); + has_precision = 1; + } + } + +# if WIDE_CHAR_VERSION + /* %s in vasnwprintf. See the specification of fwprintf. */ + { + const char *arg = a.arg[dp->arg_index].a.a_string; + const char *arg_end; + size_t characters; + + if (has_precision) + { + /* Use only as many bytes as needed to produce PRECISION + wide characters, from the left. */ +# if HAVE_MBRTOWC + mbstate_t state; + memset (&state, '\0', sizeof (mbstate_t)); +# endif + arg_end = arg; + characters = 0; + for (; precision > 0; precision--) + { + int count; +# if HAVE_MBRTOWC + count = mbrlen (arg_end, MB_CUR_MAX, &state); +# else + count = mblen (arg_end, MB_CUR_MAX); +# endif + if (count == 0) + /* Found the terminating NUL. */ + break; + if (count < 0) + { + /* Invalid or incomplete multibyte character. */ + if (!(result == resultbuf || result == NULL)) + free (result); + if (buf_malloced != NULL) + free (buf_malloced); + CLEANUP (); + errno = EILSEQ; + return NULL; + } + arg_end += count; + characters++; + } + } + else if (has_width) + { + /* Use the entire string, and count the number of wide + characters. */ +# if HAVE_MBRTOWC + mbstate_t state; + memset (&state, '\0', sizeof (mbstate_t)); +# endif + arg_end = arg; + characters = 0; + for (;;) + { + int count; +# if HAVE_MBRTOWC + count = mbrlen (arg_end, MB_CUR_MAX, &state); +# else + count = mblen (arg_end, MB_CUR_MAX); +# endif + if (count == 0) + /* Found the terminating NUL. */ + break; + if (count < 0) + { + /* Invalid or incomplete multibyte character. */ + if (!(result == resultbuf || result == NULL)) + free (result); + if (buf_malloced != NULL) + free (buf_malloced); + CLEANUP (); + errno = EILSEQ; + return NULL; + } + arg_end += count; + characters++; + } + } + else + { + /* Use the entire string. */ + arg_end = arg + strlen (arg); + /* The number of characters doesn't matter. */ + characters = 0; + } + + if (characters < width && !(dp->flags & FLAG_LEFT)) + { + size_t n = width - characters; + ENSURE_ALLOCATION (xsum (length, n)); + DCHAR_SET (result + length, ' ', n); + length += n; + } + + if (has_precision || has_width) + { + /* We know the number of wide characters in advance. */ + size_t remaining; +# if HAVE_MBRTOWC + mbstate_t state; + memset (&state, '\0', sizeof (mbstate_t)); +# endif + ENSURE_ALLOCATION (xsum (length, characters)); + for (remaining = characters; remaining > 0; remaining--) + { + wchar_t wc; + int count; +# if HAVE_MBRTOWC + count = mbrtowc (&wc, arg, arg_end - arg, &state); +# else + count = mbtowc (&wc, arg, arg_end - arg); +# endif + if (count <= 0) + /* mbrtowc not consistent with mbrlen, or mbtowc + not consistent with mblen. */ + abort (); + result[length++] = wc; + arg += count; + } + if (!(arg == arg_end)) + abort (); + } + else + { +# if HAVE_MBRTOWC + mbstate_t state; + memset (&state, '\0', sizeof (mbstate_t)); +# endif + while (arg < arg_end) + { + wchar_t wc; + int count; +# if HAVE_MBRTOWC + count = mbrtowc (&wc, arg, arg_end - arg, &state); +# else + count = mbtowc (&wc, arg, arg_end - arg); +# endif + if (count <= 0) + /* mbrtowc not consistent with mbrlen, or mbtowc + not consistent with mblen. */ + abort (); + ENSURE_ALLOCATION (xsum (length, 1)); + result[length++] = wc; + arg += count; + } + } + + if (characters < width && (dp->flags & FLAG_LEFT)) + { + size_t n = width - characters; + ENSURE_ALLOCATION (xsum (length, n)); + DCHAR_SET (result + length, ' ', n); + length += n; + } + } +# else + /* %ls in vasnprintf. See the specification of fprintf. */ + { + const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string; + const wchar_t *arg_end; + size_t characters; +# if !DCHAR_IS_TCHAR + /* This code assumes that TCHAR_T is 'char'. */ + verify (sizeof (TCHAR_T) == 1); + TCHAR_T *tmpsrc; + DCHAR_T *tmpdst; + size_t tmpdst_len; +# endif + size_t w; + + if (has_precision) + { + /* Use only as many wide characters as needed to produce + at most PRECISION bytes, from the left. */ +# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t + mbstate_t state; + memset (&state, '\0', sizeof (mbstate_t)); +# endif + arg_end = arg; + characters = 0; + while (precision > 0) + { + char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */ + int count; + + if (*arg_end == 0) + /* Found the terminating null wide character. */ + break; +# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t + count = wcrtomb (cbuf, *arg_end, &state); +# else + count = wctomb (cbuf, *arg_end); +# endif + if (count < 0) + { + /* Cannot convert. */ + if (!(result == resultbuf || result == NULL)) + free (result); + if (buf_malloced != NULL) + free (buf_malloced); + CLEANUP (); + errno = EILSEQ; + return NULL; + } + if (precision < count) + break; + arg_end++; + characters += count; + precision -= count; + } + } +# if DCHAR_IS_TCHAR + else if (has_width) +# else + else +# endif + { + /* Use the entire string, and count the number of + bytes. */ +# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t + mbstate_t state; + memset (&state, '\0', sizeof (mbstate_t)); +# endif + arg_end = arg; + characters = 0; + for (;;) + { + char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */ + int count; + + if (*arg_end == 0) + /* Found the terminating null wide character. */ + break; +# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t + count = wcrtomb (cbuf, *arg_end, &state); +# else + count = wctomb (cbuf, *arg_end); +# endif + if (count < 0) + { + /* Cannot convert. */ + if (!(result == resultbuf || result == NULL)) + free (result); + if (buf_malloced != NULL) + free (buf_malloced); + CLEANUP (); + errno = EILSEQ; + return NULL; + } + arg_end++; + characters += count; + } + } +# if DCHAR_IS_TCHAR + else + { + /* Use the entire string. */ + arg_end = arg + local_wcslen (arg); + /* The number of bytes doesn't matter. */ + characters = 0; + } +# endif + +# if !DCHAR_IS_TCHAR + /* Convert the string into a piece of temporary memory. */ + tmpsrc = (TCHAR_T *) malloc (characters * sizeof (TCHAR_T)); + if (tmpsrc == NULL) + goto out_of_memory; + { + TCHAR_T *tmpptr = tmpsrc; + size_t remaining; +# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t + mbstate_t state; + memset (&state, '\0', sizeof (mbstate_t)); +# endif + for (remaining = characters; remaining > 0; ) + { + char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */ + int count; + + if (*arg == 0) + abort (); +# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t + count = wcrtomb (cbuf, *arg, &state); +# else + count = wctomb (cbuf, *arg); +# endif + if (count <= 0) + /* Inconsistency. */ + abort (); + memcpy (tmpptr, cbuf, count); + tmpptr += count; + arg++; + remaining -= count; + } + if (!(arg == arg_end)) + abort (); + } + + /* Convert from TCHAR_T[] to DCHAR_T[]. */ + tmpdst = + DCHAR_CONV_FROM_ENCODING (locale_charset (), + iconveh_question_mark, + tmpsrc, characters, + NULL, + NULL, &tmpdst_len); + if (tmpdst == NULL) + { + int saved_errno = errno; + free (tmpsrc); + if (!(result == resultbuf || result == NULL)) + free (result); + if (buf_malloced != NULL) + free (buf_malloced); + CLEANUP (); + errno = saved_errno; + return NULL; + } + free (tmpsrc); +# endif + + if (has_width) + { +# if ENABLE_UNISTDIO + /* Outside POSIX, it's preferable to compare the width + against the number of _characters_ of the converted + value. */ + w = DCHAR_MBSNLEN (result + length, characters); +# else + /* The width is compared against the number of _bytes_ + of the converted value, says POSIX. */ + w = characters; +# endif + } + else + /* w doesn't matter. */ + w = 0; + + if (w < width && !(dp->flags & FLAG_LEFT)) + { + size_t n = width - w; + ENSURE_ALLOCATION (xsum (length, n)); + DCHAR_SET (result + length, ' ', n); + length += n; + } + +# if DCHAR_IS_TCHAR + if (has_precision || has_width) + { + /* We know the number of bytes in advance. */ + size_t remaining; +# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t + mbstate_t state; + memset (&state, '\0', sizeof (mbstate_t)); +# endif + ENSURE_ALLOCATION (xsum (length, characters)); + for (remaining = characters; remaining > 0; ) + { + char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */ + int count; + + if (*arg == 0) + abort (); +# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t + count = wcrtomb (cbuf, *arg, &state); +# else + count = wctomb (cbuf, *arg); +# endif + if (count <= 0) + /* Inconsistency. */ + abort (); + memcpy (result + length, cbuf, count); + length += count; + arg++; + remaining -= count; + } + if (!(arg == arg_end)) + abort (); + } + else + { +# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t + mbstate_t state; + memset (&state, '\0', sizeof (mbstate_t)); +# endif + while (arg < arg_end) + { + char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */ + int count; + + if (*arg == 0) + abort (); +# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t + count = wcrtomb (cbuf, *arg, &state); +# else + count = wctomb (cbuf, *arg); +# endif + if (count <= 0) + { + /* Cannot convert. */ + if (!(result == resultbuf || result == NULL)) + free (result); + if (buf_malloced != NULL) + free (buf_malloced); + CLEANUP (); + errno = EILSEQ; + return NULL; + } + ENSURE_ALLOCATION (xsum (length, count)); + memcpy (result + length, cbuf, count); + length += count; + arg++; + } + } +# else + ENSURE_ALLOCATION (xsum (length, tmpdst_len)); + DCHAR_CPY (result + length, tmpdst, tmpdst_len); + free (tmpdst); + length += tmpdst_len; +# endif + + if (w < width && (dp->flags & FLAG_LEFT)) + { + size_t n = width - w; + ENSURE_ALLOCATION (xsum (length, n)); + DCHAR_SET (result + length, ' ', n); + length += n; + } + } +# endif + } +#endif +#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_DOUBLE) && !defined IN_LIBINTL + else if ((dp->conversion == 'a' || dp->conversion == 'A') +# if !(NEED_PRINTF_DIRECTIVE_A || (NEED_PRINTF_LONG_DOUBLE && NEED_PRINTF_DOUBLE)) + && (0 +# if NEED_PRINTF_DOUBLE + || a.arg[dp->arg_index].type == TYPE_DOUBLE +# endif +# if NEED_PRINTF_LONG_DOUBLE + || a.arg[dp->arg_index].type == TYPE_LONGDOUBLE +# endif + ) +# endif + ) + { + arg_type type = a.arg[dp->arg_index].type; + int flags = dp->flags; + size_t width; + int has_precision; + size_t precision; + size_t tmp_length; + size_t count; + DCHAR_T tmpbuf[700]; + DCHAR_T *tmp; + DCHAR_T *pad_ptr; + DCHAR_T *p; + + width = 0; + if (dp->width_start != dp->width_end) + { + if (dp->width_arg_index != ARG_NONE) + { + int arg; + + if (!(a.arg[dp->width_arg_index].type == TYPE_INT)) + abort (); + arg = a.arg[dp->width_arg_index].a.a_int; + width = arg; + if (arg < 0) + { + /* "A negative field width is taken as a '-' flag + followed by a positive field width." */ + flags |= FLAG_LEFT; + width = -width; + } + } + else + { + const FCHAR_T *digitp = dp->width_start; + + do + width = xsum (xtimes (width, 10), *digitp++ - '0'); + while (digitp != dp->width_end); + } + } + + has_precision = 0; + precision = 0; + if (dp->precision_start != dp->precision_end) + { + if (dp->precision_arg_index != ARG_NONE) + { + int arg; + + if (!(a.arg[dp->precision_arg_index].type == TYPE_INT)) + abort (); + arg = a.arg[dp->precision_arg_index].a.a_int; + /* "A negative precision is taken as if the precision + were omitted." */ + if (arg >= 0) + { + precision = arg; + has_precision = 1; + } + } + else + { + const FCHAR_T *digitp = dp->precision_start + 1; + + precision = 0; + while (digitp != dp->precision_end) + precision = xsum (xtimes (precision, 10), *digitp++ - '0'); + has_precision = 1; + } + } + + /* Allocate a temporary buffer of sufficient size. */ + if (type == TYPE_LONGDOUBLE) + tmp_length = + (unsigned int) ((LDBL_DIG + 1) + * 0.831 /* decimal -> hexadecimal */ + ) + + 1; /* turn floor into ceil */ + else + tmp_length = + (unsigned int) ((DBL_DIG + 1) + * 0.831 /* decimal -> hexadecimal */ + ) + + 1; /* turn floor into ceil */ + if (tmp_length < precision) + tmp_length = precision; + /* Account for sign, decimal point etc. */ + tmp_length = xsum (tmp_length, 12); + + if (tmp_length < width) + tmp_length = width; + + tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */ + + if (tmp_length <= sizeof (tmpbuf) / sizeof (DCHAR_T)) + tmp = tmpbuf; + else + { + size_t tmp_memsize = xtimes (tmp_length, sizeof (DCHAR_T)); + + if (size_overflow_p (tmp_memsize)) + /* Overflow, would lead to out of memory. */ + goto out_of_memory; + tmp = (DCHAR_T *) malloc (tmp_memsize); + if (tmp == NULL) + /* Out of memory. */ + goto out_of_memory; + } + + pad_ptr = NULL; + p = tmp; + if (type == TYPE_LONGDOUBLE) + { +# if NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE + long double arg = a.arg[dp->arg_index].a.a_longdouble; + + if (isnanl (arg)) + { + if (dp->conversion == 'A') + { + *p++ = 'N'; *p++ = 'A'; *p++ = 'N'; + } + else + { + *p++ = 'n'; *p++ = 'a'; *p++ = 'n'; + } + } + else + { + int sign = 0; + DECL_LONG_DOUBLE_ROUNDING + + BEGIN_LONG_DOUBLE_ROUNDING (); + + if (signbit (arg)) /* arg < 0.0L or negative zero */ + { + sign = -1; + arg = -arg; + } + + if (sign < 0) + *p++ = '-'; + else if (flags & FLAG_SHOWSIGN) + *p++ = '+'; + else if (flags & FLAG_SPACE) + *p++ = ' '; + + if (arg > 0.0L && arg + arg == arg) + { + if (dp->conversion == 'A') + { + *p++ = 'I'; *p++ = 'N'; *p++ = 'F'; + } + else + { + *p++ = 'i'; *p++ = 'n'; *p++ = 'f'; + } + } + else + { + int exponent; + long double mantissa; + + if (arg > 0.0L) + mantissa = printf_frexpl (arg, &exponent); + else + { + exponent = 0; + mantissa = 0.0L; + } + + if (has_precision + && precision < (unsigned int) ((LDBL_DIG + 1) * 0.831) + 1) + { + /* Round the mantissa. */ + long double tail = mantissa; + size_t q; + + for (q = precision; ; q--) + { + int digit = (int) tail; + tail -= digit; + if (q == 0) + { + if (digit & 1 ? tail >= 0.5L : tail > 0.5L) + tail = 1 - tail; + else + tail = - tail; + break; + } + tail *= 16.0L; + } + if (tail != 0.0L) + for (q = precision; q > 0; q--) + tail *= 0.0625L; + mantissa += tail; + } + + *p++ = '0'; + *p++ = dp->conversion - 'A' + 'X'; + pad_ptr = p; + { + int digit; + + digit = (int) mantissa; + mantissa -= digit; + *p++ = '0' + digit; + if ((flags & FLAG_ALT) + || mantissa > 0.0L || precision > 0) + { + *p++ = decimal_point_char (); + /* This loop terminates because we assume + that FLT_RADIX is a power of 2. */ + while (mantissa > 0.0L) + { + mantissa *= 16.0L; + digit = (int) mantissa; + mantissa -= digit; + *p++ = digit + + (digit < 10 + ? '0' + : dp->conversion - 10); + if (precision > 0) + precision--; + } + while (precision > 0) + { + *p++ = '0'; + precision--; + } + } + } + *p++ = dp->conversion - 'A' + 'P'; +# if WIDE_CHAR_VERSION + { + static const wchar_t decimal_format[] = + { '%', '+', 'd', '\0' }; + SNPRINTF (p, 6 + 1, decimal_format, exponent); + } + while (*p != '\0') + p++; +# else + if (sizeof (DCHAR_T) == 1) + { + sprintf ((char *) p, "%+d", exponent); + while (*p != '\0') + p++; + } + else + { + char expbuf[6 + 1]; + const char *ep; + sprintf (expbuf, "%+d", exponent); + for (ep = expbuf; (*p = *ep) != '\0'; ep++) + p++; + } +# endif + } + + END_LONG_DOUBLE_ROUNDING (); + } +# else + abort (); +# endif + } + else + { +# if NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_DOUBLE + double arg = a.arg[dp->arg_index].a.a_double; + + if (isnand (arg)) + { + if (dp->conversion == 'A') + { + *p++ = 'N'; *p++ = 'A'; *p++ = 'N'; + } + else + { + *p++ = 'n'; *p++ = 'a'; *p++ = 'n'; + } + } + else + { + int sign = 0; + + if (signbit (arg)) /* arg < 0.0 or negative zero */ + { + sign = -1; + arg = -arg; + } + + if (sign < 0) + *p++ = '-'; + else if (flags & FLAG_SHOWSIGN) + *p++ = '+'; + else if (flags & FLAG_SPACE) + *p++ = ' '; + + if (arg > 0.0 && arg + arg == arg) + { + if (dp->conversion == 'A') + { + *p++ = 'I'; *p++ = 'N'; *p++ = 'F'; + } + else + { + *p++ = 'i'; *p++ = 'n'; *p++ = 'f'; + } + } + else + { + int exponent; + double mantissa; + + if (arg > 0.0) + mantissa = printf_frexp (arg, &exponent); + else + { + exponent = 0; + mantissa = 0.0; + } + + if (has_precision + && precision < (unsigned int) ((DBL_DIG + 1) * 0.831) + 1) + { + /* Round the mantissa. */ + double tail = mantissa; + size_t q; + + for (q = precision; ; q--) + { + int digit = (int) tail; + tail -= digit; + if (q == 0) + { + if (digit & 1 ? tail >= 0.5 : tail > 0.5) + tail = 1 - tail; + else + tail = - tail; + break; + } + tail *= 16.0; + } + if (tail != 0.0) + for (q = precision; q > 0; q--) + tail *= 0.0625; + mantissa += tail; + } + + *p++ = '0'; + *p++ = dp->conversion - 'A' + 'X'; + pad_ptr = p; + { + int digit; + + digit = (int) mantissa; + mantissa -= digit; + *p++ = '0' + digit; + if ((flags & FLAG_ALT) + || mantissa > 0.0 || precision > 0) + { + *p++ = decimal_point_char (); + /* This loop terminates because we assume + that FLT_RADIX is a power of 2. */ + while (mantissa > 0.0) + { + mantissa *= 16.0; + digit = (int) mantissa; + mantissa -= digit; + *p++ = digit + + (digit < 10 + ? '0' + : dp->conversion - 10); + if (precision > 0) + precision--; + } + while (precision > 0) + { + *p++ = '0'; + precision--; + } + } + } + *p++ = dp->conversion - 'A' + 'P'; +# if WIDE_CHAR_VERSION + { + static const wchar_t decimal_format[] = + { '%', '+', 'd', '\0' }; + SNPRINTF (p, 6 + 1, decimal_format, exponent); + } + while (*p != '\0') + p++; +# else + if (sizeof (DCHAR_T) == 1) + { + sprintf ((char *) p, "%+d", exponent); + while (*p != '\0') + p++; + } + else + { + char expbuf[6 + 1]; + const char *ep; + sprintf (expbuf, "%+d", exponent); + for (ep = expbuf; (*p = *ep) != '\0'; ep++) + p++; + } +# endif + } + } +# else + abort (); +# endif + } + + /* The generated string now extends from tmp to p, with the + zero padding insertion point being at pad_ptr. */ + count = p - tmp; + + if (count < width) + { + size_t pad = width - count; + DCHAR_T *end = p + pad; + + if (flags & FLAG_LEFT) + { + /* Pad with spaces on the right. */ + for (; pad > 0; pad--) + *p++ = ' '; + } + else if ((flags & FLAG_ZERO) && pad_ptr != NULL) + { + /* Pad with zeroes. */ + DCHAR_T *q = end; + + while (p > pad_ptr) + *--q = *--p; + for (; pad > 0; pad--) + *p++ = '0'; + } + else + { + /* Pad with spaces on the left. */ + DCHAR_T *q = end; + + while (p > tmp) + *--q = *--p; + for (; pad > 0; pad--) + *p++ = ' '; + } + + p = end; + } + + count = p - tmp; + + if (count >= tmp_length) + /* tmp_length was incorrectly calculated - fix the + code above! */ + abort (); + + /* Make room for the result. */ + if (count >= allocated - length) + { + size_t n = xsum (length, count); + + ENSURE_ALLOCATION (n); + } + + /* Append the result. */ + memcpy (result + length, tmp, count * sizeof (DCHAR_T)); + if (tmp != tmpbuf) + free (tmp); + length += count; + } +#endif +#if (NEED_PRINTF_INFINITE_DOUBLE || NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE || NEED_PRINTF_LONG_DOUBLE) && !defined IN_LIBINTL + else if ((dp->conversion == 'f' || dp->conversion == 'F' + || dp->conversion == 'e' || dp->conversion == 'E' + || dp->conversion == 'g' || dp->conversion == 'G' + || dp->conversion == 'a' || dp->conversion == 'A') + && (0 +# if NEED_PRINTF_DOUBLE + || a.arg[dp->arg_index].type == TYPE_DOUBLE +# elif NEED_PRINTF_INFINITE_DOUBLE + || (a.arg[dp->arg_index].type == TYPE_DOUBLE + /* The systems (mingw) which produce wrong output + for Inf, -Inf, and NaN also do so for -0.0. + Therefore we treat this case here as well. */ + && is_infinite_or_zero (a.arg[dp->arg_index].a.a_double)) +# endif +# if NEED_PRINTF_LONG_DOUBLE + || a.arg[dp->arg_index].type == TYPE_LONGDOUBLE +# elif NEED_PRINTF_INFINITE_LONG_DOUBLE + || (a.arg[dp->arg_index].type == TYPE_LONGDOUBLE + /* Some systems produce wrong output for Inf, + -Inf, and NaN. Some systems in this category + (IRIX 5.3) also do so for -0.0. Therefore we + treat this case here as well. */ + && is_infinite_or_zerol (a.arg[dp->arg_index].a.a_longdouble)) +# endif + )) + { +# if (NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE) && (NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE) + arg_type type = a.arg[dp->arg_index].type; +# endif + int flags = dp->flags; + size_t width; + size_t count; + int has_precision; + size_t precision; + size_t tmp_length; + DCHAR_T tmpbuf[700]; + DCHAR_T *tmp; + DCHAR_T *pad_ptr; + DCHAR_T *p; + + width = 0; + if (dp->width_start != dp->width_end) + { + if (dp->width_arg_index != ARG_NONE) + { + int arg; + + if (!(a.arg[dp->width_arg_index].type == TYPE_INT)) + abort (); + arg = a.arg[dp->width_arg_index].a.a_int; + width = arg; + if (arg < 0) + { + /* "A negative field width is taken as a '-' flag + followed by a positive field width." */ + flags |= FLAG_LEFT; + width = -width; + } + } + else + { + const FCHAR_T *digitp = dp->width_start; + + do + width = xsum (xtimes (width, 10), *digitp++ - '0'); + while (digitp != dp->width_end); + } + } + + has_precision = 0; + precision = 0; + if (dp->precision_start != dp->precision_end) + { + if (dp->precision_arg_index != ARG_NONE) + { + int arg; + + if (!(a.arg[dp->precision_arg_index].type == TYPE_INT)) + abort (); + arg = a.arg[dp->precision_arg_index].a.a_int; + /* "A negative precision is taken as if the precision + were omitted." */ + if (arg >= 0) + { + precision = arg; + has_precision = 1; + } + } + else + { + const FCHAR_T *digitp = dp->precision_start + 1; + + precision = 0; + while (digitp != dp->precision_end) + precision = xsum (xtimes (precision, 10), *digitp++ - '0'); + has_precision = 1; + } + } + + /* POSIX specifies the default precision to be 6 for %f, %F, + %e, %E, but not for %g, %G. Implementations appear to use + the same default precision also for %g, %G. But for %a, %A, + the default precision is 0. */ + if (!has_precision) + if (!(dp->conversion == 'a' || dp->conversion == 'A')) + precision = 6; + + /* Allocate a temporary buffer of sufficient size. */ +# if NEED_PRINTF_DOUBLE && NEED_PRINTF_LONG_DOUBLE + tmp_length = (type == TYPE_LONGDOUBLE ? LDBL_DIG + 1 : DBL_DIG + 1); +# elif NEED_PRINTF_INFINITE_DOUBLE && NEED_PRINTF_LONG_DOUBLE + tmp_length = (type == TYPE_LONGDOUBLE ? LDBL_DIG + 1 : 0); +# elif NEED_PRINTF_LONG_DOUBLE + tmp_length = LDBL_DIG + 1; +# elif NEED_PRINTF_DOUBLE + tmp_length = DBL_DIG + 1; +# else + tmp_length = 0; +# endif + if (tmp_length < precision) + tmp_length = precision; +# if NEED_PRINTF_LONG_DOUBLE +# if NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE + if (type == TYPE_LONGDOUBLE) +# endif + if (dp->conversion == 'f' || dp->conversion == 'F') + { + long double arg = a.arg[dp->arg_index].a.a_longdouble; + if (!(isnanl (arg) || arg + arg == arg)) + { + /* arg is finite and nonzero. */ + int exponent = floorlog10l (arg < 0 ? -arg : arg); + if (exponent >= 0 && tmp_length < exponent + precision) + tmp_length = exponent + precision; + } + } +# endif +# if NEED_PRINTF_DOUBLE +# if NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE + if (type == TYPE_DOUBLE) +# endif + if (dp->conversion == 'f' || dp->conversion == 'F') + { + double arg = a.arg[dp->arg_index].a.a_double; + if (!(isnand (arg) || arg + arg == arg)) + { + /* arg is finite and nonzero. */ + int exponent = floorlog10 (arg < 0 ? -arg : arg); + if (exponent >= 0 && tmp_length < exponent + precision) + tmp_length = exponent + precision; + } + } +# endif + /* Account for sign, decimal point etc. */ + tmp_length = xsum (tmp_length, 12); + + if (tmp_length < width) + tmp_length = width; + + tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */ + + if (tmp_length <= sizeof (tmpbuf) / sizeof (DCHAR_T)) + tmp = tmpbuf; + else + { + size_t tmp_memsize = xtimes (tmp_length, sizeof (DCHAR_T)); + + if (size_overflow_p (tmp_memsize)) + /* Overflow, would lead to out of memory. */ + goto out_of_memory; + tmp = (DCHAR_T *) malloc (tmp_memsize); + if (tmp == NULL) + /* Out of memory. */ + goto out_of_memory; + } + + pad_ptr = NULL; + p = tmp; + +# if NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE +# if NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE + if (type == TYPE_LONGDOUBLE) +# endif + { + long double arg = a.arg[dp->arg_index].a.a_longdouble; + + if (isnanl (arg)) + { + if (dp->conversion >= 'A' && dp->conversion <= 'Z') + { + *p++ = 'N'; *p++ = 'A'; *p++ = 'N'; + } + else + { + *p++ = 'n'; *p++ = 'a'; *p++ = 'n'; + } + } + else + { + int sign = 0; + DECL_LONG_DOUBLE_ROUNDING + + BEGIN_LONG_DOUBLE_ROUNDING (); + + if (signbit (arg)) /* arg < 0.0L or negative zero */ + { + sign = -1; + arg = -arg; + } + + if (sign < 0) + *p++ = '-'; + else if (flags & FLAG_SHOWSIGN) + *p++ = '+'; + else if (flags & FLAG_SPACE) + *p++ = ' '; + + if (arg > 0.0L && arg + arg == arg) + { + if (dp->conversion >= 'A' && dp->conversion <= 'Z') + { + *p++ = 'I'; *p++ = 'N'; *p++ = 'F'; + } + else + { + *p++ = 'i'; *p++ = 'n'; *p++ = 'f'; + } + } + else + { +# if NEED_PRINTF_LONG_DOUBLE + pad_ptr = p; + + if (dp->conversion == 'f' || dp->conversion == 'F') + { + char *digits; + size_t ndigits; + + digits = + scale10_round_decimal_long_double (arg, precision); + if (digits == NULL) + { + END_LONG_DOUBLE_ROUNDING (); + goto out_of_memory; + } + ndigits = strlen (digits); + + if (ndigits > precision) + do + { + --ndigits; + *p++ = digits[ndigits]; + } + while (ndigits > precision); + else + *p++ = '0'; + /* Here ndigits <= precision. */ + if ((flags & FLAG_ALT) || precision > 0) + { + *p++ = decimal_point_char (); + for (; precision > ndigits; precision--) + *p++ = '0'; + while (ndigits > 0) + { + --ndigits; + *p++ = digits[ndigits]; + } + } + + free (digits); + } + else if (dp->conversion == 'e' || dp->conversion == 'E') + { + int exponent; + + if (arg == 0.0L) + { + exponent = 0; + *p++ = '0'; + if ((flags & FLAG_ALT) || precision > 0) + { + *p++ = decimal_point_char (); + for (; precision > 0; precision--) + *p++ = '0'; + } + } + else + { + /* arg > 0.0L. */ + int adjusted; + char *digits; + size_t ndigits; + + exponent = floorlog10l (arg); + adjusted = 0; + for (;;) + { + digits = + scale10_round_decimal_long_double (arg, + (int)precision - exponent); + if (digits == NULL) + { + END_LONG_DOUBLE_ROUNDING (); + goto out_of_memory; + } + ndigits = strlen (digits); + + if (ndigits == precision + 1) + break; + if (ndigits < precision + || ndigits > precision + 2) + /* The exponent was not guessed + precisely enough. */ + abort (); + if (adjusted) + /* None of two values of exponent is + the right one. Prevent an endless + loop. */ + abort (); + free (digits); + if (ndigits == precision) + exponent -= 1; + else + exponent += 1; + adjusted = 1; + } + /* Here ndigits = precision+1. */ + if (is_borderline (digits, precision)) + { + /* Maybe the exponent guess was too high + and a smaller exponent can be reached + by turning a 10...0 into 9...9x. */ + char *digits2 = + scale10_round_decimal_long_double (arg, + (int)precision - exponent + 1); + if (digits2 == NULL) + { + free (digits); + END_LONG_DOUBLE_ROUNDING (); + goto out_of_memory; + } + if (strlen (digits2) == precision + 1) + { + free (digits); + digits = digits2; + exponent -= 1; + } + else + free (digits2); + } + /* Here ndigits = precision+1. */ + + *p++ = digits[--ndigits]; + if ((flags & FLAG_ALT) || precision > 0) + { + *p++ = decimal_point_char (); + while (ndigits > 0) + { + --ndigits; + *p++ = digits[ndigits]; + } + } + + free (digits); + } + + *p++ = dp->conversion; /* 'e' or 'E' */ +# if WIDE_CHAR_VERSION + { + static const wchar_t decimal_format[] = + { '%', '+', '.', '2', 'd', '\0' }; + SNPRINTF (p, 6 + 1, decimal_format, exponent); + } + while (*p != '\0') + p++; +# else + if (sizeof (DCHAR_T) == 1) + { + sprintf ((char *) p, "%+.2d", exponent); + while (*p != '\0') + p++; + } + else + { + char expbuf[6 + 1]; + const char *ep; + sprintf (expbuf, "%+.2d", exponent); + for (ep = expbuf; (*p = *ep) != '\0'; ep++) + p++; + } +# endif + } + else if (dp->conversion == 'g' || dp->conversion == 'G') + { + if (precision == 0) + precision = 1; + /* precision >= 1. */ + + if (arg == 0.0L) + /* The exponent is 0, >= -4, < precision. + Use fixed-point notation. */ + { + size_t ndigits = precision; + /* Number of trailing zeroes that have to be + dropped. */ + size_t nzeroes = + (flags & FLAG_ALT ? 0 : precision - 1); + + --ndigits; + *p++ = '0'; + if ((flags & FLAG_ALT) || ndigits > nzeroes) + { + *p++ = decimal_point_char (); + while (ndigits > nzeroes) + { + --ndigits; + *p++ = '0'; + } + } + } + else + { + /* arg > 0.0L. */ + int exponent; + int adjusted; + char *digits; + size_t ndigits; + size_t nzeroes; + + exponent = floorlog10l (arg); + adjusted = 0; + for (;;) + { + digits = + scale10_round_decimal_long_double (arg, + (int)(precision - 1) - exponent); + if (digits == NULL) + { + END_LONG_DOUBLE_ROUNDING (); + goto out_of_memory; + } + ndigits = strlen (digits); + + if (ndigits == precision) + break; + if (ndigits < precision - 1 + || ndigits > precision + 1) + /* The exponent was not guessed + precisely enough. */ + abort (); + if (adjusted) + /* None of two values of exponent is + the right one. Prevent an endless + loop. */ + abort (); + free (digits); + if (ndigits < precision) + exponent -= 1; + else + exponent += 1; + adjusted = 1; + } + /* Here ndigits = precision. */ + if (is_borderline (digits, precision - 1)) + { + /* Maybe the exponent guess was too high + and a smaller exponent can be reached + by turning a 10...0 into 9...9x. */ + char *digits2 = + scale10_round_decimal_long_double (arg, + (int)(precision - 1) - exponent + 1); + if (digits2 == NULL) + { + free (digits); + END_LONG_DOUBLE_ROUNDING (); + goto out_of_memory; + } + if (strlen (digits2) == precision) + { + free (digits); + digits = digits2; + exponent -= 1; + } + else + free (digits2); + } + /* Here ndigits = precision. */ + + /* Determine the number of trailing zeroes + that have to be dropped. */ + nzeroes = 0; + if ((flags & FLAG_ALT) == 0) + while (nzeroes < ndigits + && digits[nzeroes] == '0') + nzeroes++; + + /* The exponent is now determined. */ + if (exponent >= -4 + && exponent < (long)precision) + { + /* Fixed-point notation: + max(exponent,0)+1 digits, then the + decimal point, then the remaining + digits without trailing zeroes. */ + if (exponent >= 0) + { + size_t ecount = exponent + 1; + /* Note: count <= precision = ndigits. */ + for (; ecount > 0; ecount--) + *p++ = digits[--ndigits]; + if ((flags & FLAG_ALT) || ndigits > nzeroes) + { + *p++ = decimal_point_char (); + while (ndigits > nzeroes) + { + --ndigits; + *p++ = digits[ndigits]; + } + } + } + else + { + size_t ecount = -exponent - 1; + *p++ = '0'; + *p++ = decimal_point_char (); + for (; ecount > 0; ecount--) + *p++ = '0'; + while (ndigits > nzeroes) + { + --ndigits; + *p++ = digits[ndigits]; + } + } + } + else + { + /* Exponential notation. */ + *p++ = digits[--ndigits]; + if ((flags & FLAG_ALT) || ndigits > nzeroes) + { + *p++ = decimal_point_char (); + while (ndigits > nzeroes) + { + --ndigits; + *p++ = digits[ndigits]; + } + } + *p++ = dp->conversion - 'G' + 'E'; /* 'e' or 'E' */ +# if WIDE_CHAR_VERSION + { + static const wchar_t decimal_format[] = + { '%', '+', '.', '2', 'd', '\0' }; + SNPRINTF (p, 6 + 1, decimal_format, exponent); + } + while (*p != '\0') + p++; +# else + if (sizeof (DCHAR_T) == 1) + { + sprintf ((char *) p, "%+.2d", exponent); + while (*p != '\0') + p++; + } + else + { + char expbuf[6 + 1]; + const char *ep; + sprintf (expbuf, "%+.2d", exponent); + for (ep = expbuf; (*p = *ep) != '\0'; ep++) + p++; + } +# endif + } + + free (digits); + } + } + else + abort (); +# else + /* arg is finite. */ + if (!(arg == 0.0L)) + abort (); + + pad_ptr = p; + + if (dp->conversion == 'f' || dp->conversion == 'F') + { + *p++ = '0'; + if ((flags & FLAG_ALT) || precision > 0) + { + *p++ = decimal_point_char (); + for (; precision > 0; precision--) + *p++ = '0'; + } + } + else if (dp->conversion == 'e' || dp->conversion == 'E') + { + *p++ = '0'; + if ((flags & FLAG_ALT) || precision > 0) + { + *p++ = decimal_point_char (); + for (; precision > 0; precision--) + *p++ = '0'; + } + *p++ = dp->conversion; /* 'e' or 'E' */ + *p++ = '+'; + *p++ = '0'; + *p++ = '0'; + } + else if (dp->conversion == 'g' || dp->conversion == 'G') + { + *p++ = '0'; + if (flags & FLAG_ALT) + { + size_t ndigits = + (precision > 0 ? precision - 1 : 0); + *p++ = decimal_point_char (); + for (; ndigits > 0; --ndigits) + *p++ = '0'; + } + } + else if (dp->conversion == 'a' || dp->conversion == 'A') + { + *p++ = '0'; + *p++ = dp->conversion - 'A' + 'X'; + pad_ptr = p; + *p++ = '0'; + if ((flags & FLAG_ALT) || precision > 0) + { + *p++ = decimal_point_char (); + for (; precision > 0; precision--) + *p++ = '0'; + } + *p++ = dp->conversion - 'A' + 'P'; + *p++ = '+'; + *p++ = '0'; + } + else + abort (); +# endif + } + + END_LONG_DOUBLE_ROUNDING (); + } + } +# if NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE + else +# endif +# endif +# if NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE + { + double arg = a.arg[dp->arg_index].a.a_double; + + if (isnand (arg)) + { + if (dp->conversion >= 'A' && dp->conversion <= 'Z') + { + *p++ = 'N'; *p++ = 'A'; *p++ = 'N'; + } + else + { + *p++ = 'n'; *p++ = 'a'; *p++ = 'n'; + } + } + else + { + int sign = 0; + + if (signbit (arg)) /* arg < 0.0 or negative zero */ + { + sign = -1; + arg = -arg; + } + + if (sign < 0) + *p++ = '-'; + else if (flags & FLAG_SHOWSIGN) + *p++ = '+'; + else if (flags & FLAG_SPACE) + *p++ = ' '; + + if (arg > 0.0 && arg + arg == arg) + { + if (dp->conversion >= 'A' && dp->conversion <= 'Z') + { + *p++ = 'I'; *p++ = 'N'; *p++ = 'F'; + } + else + { + *p++ = 'i'; *p++ = 'n'; *p++ = 'f'; + } + } + else + { +# if NEED_PRINTF_DOUBLE + pad_ptr = p; + + if (dp->conversion == 'f' || dp->conversion == 'F') + { + char *digits; + size_t ndigits; + + digits = + scale10_round_decimal_double (arg, precision); + if (digits == NULL) + goto out_of_memory; + ndigits = strlen (digits); + + if (ndigits > precision) + do + { + --ndigits; + *p++ = digits[ndigits]; + } + while (ndigits > precision); + else + *p++ = '0'; + /* Here ndigits <= precision. */ + if ((flags & FLAG_ALT) || precision > 0) + { + *p++ = decimal_point_char (); + for (; precision > ndigits; precision--) + *p++ = '0'; + while (ndigits > 0) + { + --ndigits; + *p++ = digits[ndigits]; + } + } + + free (digits); + } + else if (dp->conversion == 'e' || dp->conversion == 'E') + { + int exponent; + + if (arg == 0.0) + { + exponent = 0; + *p++ = '0'; + if ((flags & FLAG_ALT) || precision > 0) + { + *p++ = decimal_point_char (); + for (; precision > 0; precision--) + *p++ = '0'; + } + } + else + { + /* arg > 0.0. */ + int adjusted; + char *digits; + size_t ndigits; + + exponent = floorlog10 (arg); + adjusted = 0; + for (;;) + { + digits = + scale10_round_decimal_double (arg, + (int)precision - exponent); + if (digits == NULL) + goto out_of_memory; + ndigits = strlen (digits); + + if (ndigits == precision + 1) + break; + if (ndigits < precision + || ndigits > precision + 2) + /* The exponent was not guessed + precisely enough. */ + abort (); + if (adjusted) + /* None of two values of exponent is + the right one. Prevent an endless + loop. */ + abort (); + free (digits); + if (ndigits == precision) + exponent -= 1; + else + exponent += 1; + adjusted = 1; + } + /* Here ndigits = precision+1. */ + if (is_borderline (digits, precision)) + { + /* Maybe the exponent guess was too high + and a smaller exponent can be reached + by turning a 10...0 into 9...9x. */ + char *digits2 = + scale10_round_decimal_double (arg, + (int)precision - exponent + 1); + if (digits2 == NULL) + { + free (digits); + goto out_of_memory; + } + if (strlen (digits2) == precision + 1) + { + free (digits); + digits = digits2; + exponent -= 1; + } + else + free (digits2); + } + /* Here ndigits = precision+1. */ + + *p++ = digits[--ndigits]; + if ((flags & FLAG_ALT) || precision > 0) + { + *p++ = decimal_point_char (); + while (ndigits > 0) + { + --ndigits; + *p++ = digits[ndigits]; + } + } + + free (digits); + } + + *p++ = dp->conversion; /* 'e' or 'E' */ +# if WIDE_CHAR_VERSION + { + static const wchar_t decimal_format[] = + /* Produce the same number of exponent digits + as the native printf implementation. */ +# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ + { '%', '+', '.', '3', 'd', '\0' }; +# else + { '%', '+', '.', '2', 'd', '\0' }; +# endif + SNPRINTF (p, 6 + 1, decimal_format, exponent); + } + while (*p != '\0') + p++; +# else + { + static const char decimal_format[] = + /* Produce the same number of exponent digits + as the native printf implementation. */ +# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ + "%+.3d"; +# else + "%+.2d"; +# endif + if (sizeof (DCHAR_T) == 1) + { + sprintf ((char *) p, decimal_format, exponent); + while (*p != '\0') + p++; + } + else + { + char expbuf[6 + 1]; + const char *ep; + sprintf (expbuf, decimal_format, exponent); + for (ep = expbuf; (*p = *ep) != '\0'; ep++) + p++; + } + } +# endif + } + else if (dp->conversion == 'g' || dp->conversion == 'G') + { + if (precision == 0) + precision = 1; + /* precision >= 1. */ + + if (arg == 0.0) + /* The exponent is 0, >= -4, < precision. + Use fixed-point notation. */ + { + size_t ndigits = precision; + /* Number of trailing zeroes that have to be + dropped. */ + size_t nzeroes = + (flags & FLAG_ALT ? 0 : precision - 1); + + --ndigits; + *p++ = '0'; + if ((flags & FLAG_ALT) || ndigits > nzeroes) + { + *p++ = decimal_point_char (); + while (ndigits > nzeroes) + { + --ndigits; + *p++ = '0'; + } + } + } + else + { + /* arg > 0.0. */ + int exponent; + int adjusted; + char *digits; + size_t ndigits; + size_t nzeroes; + + exponent = floorlog10 (arg); + adjusted = 0; + for (;;) + { + digits = + scale10_round_decimal_double (arg, + (int)(precision - 1) - exponent); + if (digits == NULL) + goto out_of_memory; + ndigits = strlen (digits); + + if (ndigits == precision) + break; + if (ndigits < precision - 1 + || ndigits > precision + 1) + /* The exponent was not guessed + precisely enough. */ + abort (); + if (adjusted) + /* None of two values of exponent is + the right one. Prevent an endless + loop. */ + abort (); + free (digits); + if (ndigits < precision) + exponent -= 1; + else + exponent += 1; + adjusted = 1; + } + /* Here ndigits = precision. */ + if (is_borderline (digits, precision - 1)) + { + /* Maybe the exponent guess was too high + and a smaller exponent can be reached + by turning a 10...0 into 9...9x. */ + char *digits2 = + scale10_round_decimal_double (arg, + (int)(precision - 1) - exponent + 1); + if (digits2 == NULL) + { + free (digits); + goto out_of_memory; + } + if (strlen (digits2) == precision) + { + free (digits); + digits = digits2; + exponent -= 1; + } + else + free (digits2); + } + /* Here ndigits = precision. */ + + /* Determine the number of trailing zeroes + that have to be dropped. */ + nzeroes = 0; + if ((flags & FLAG_ALT) == 0) + while (nzeroes < ndigits + && digits[nzeroes] == '0') + nzeroes++; + + /* The exponent is now determined. */ + if (exponent >= -4 + && exponent < (long)precision) + { + /* Fixed-point notation: + max(exponent,0)+1 digits, then the + decimal point, then the remaining + digits without trailing zeroes. */ + if (exponent >= 0) + { + size_t ecount = exponent + 1; + /* Note: ecount <= precision = ndigits. */ + for (; ecount > 0; ecount--) + *p++ = digits[--ndigits]; + if ((flags & FLAG_ALT) || ndigits > nzeroes) + { + *p++ = decimal_point_char (); + while (ndigits > nzeroes) + { + --ndigits; + *p++ = digits[ndigits]; + } + } + } + else + { + size_t ecount = -exponent - 1; + *p++ = '0'; + *p++ = decimal_point_char (); + for (; ecount > 0; ecount--) + *p++ = '0'; + while (ndigits > nzeroes) + { + --ndigits; + *p++ = digits[ndigits]; + } + } + } + else + { + /* Exponential notation. */ + *p++ = digits[--ndigits]; + if ((flags & FLAG_ALT) || ndigits > nzeroes) + { + *p++ = decimal_point_char (); + while (ndigits > nzeroes) + { + --ndigits; + *p++ = digits[ndigits]; + } + } + *p++ = dp->conversion - 'G' + 'E'; /* 'e' or 'E' */ +# if WIDE_CHAR_VERSION + { + static const wchar_t decimal_format[] = + /* Produce the same number of exponent digits + as the native printf implementation. */ +# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ + { '%', '+', '.', '3', 'd', '\0' }; +# else + { '%', '+', '.', '2', 'd', '\0' }; +# endif + SNPRINTF (p, 6 + 1, decimal_format, exponent); + } + while (*p != '\0') + p++; +# else + { + static const char decimal_format[] = + /* Produce the same number of exponent digits + as the native printf implementation. */ +# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ + "%+.3d"; +# else + "%+.2d"; +# endif + if (sizeof (DCHAR_T) == 1) + { + sprintf ((char *) p, decimal_format, exponent); + while (*p != '\0') + p++; + } + else + { + char expbuf[6 + 1]; + const char *ep; + sprintf (expbuf, decimal_format, exponent); + for (ep = expbuf; (*p = *ep) != '\0'; ep++) + p++; + } + } +# endif + } + + free (digits); + } + } + else + abort (); +# else + /* arg is finite. */ + if (!(arg == 0.0)) + abort (); + + pad_ptr = p; + + if (dp->conversion == 'f' || dp->conversion == 'F') + { + *p++ = '0'; + if ((flags & FLAG_ALT) || precision > 0) + { + *p++ = decimal_point_char (); + for (; precision > 0; precision--) + *p++ = '0'; + } + } + else if (dp->conversion == 'e' || dp->conversion == 'E') + { + *p++ = '0'; + if ((flags & FLAG_ALT) || precision > 0) + { + *p++ = decimal_point_char (); + for (; precision > 0; precision--) + *p++ = '0'; + } + *p++ = dp->conversion; /* 'e' or 'E' */ + *p++ = '+'; + /* Produce the same number of exponent digits as + the native printf implementation. */ +# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ + *p++ = '0'; +# endif + *p++ = '0'; + *p++ = '0'; + } + else if (dp->conversion == 'g' || dp->conversion == 'G') + { + *p++ = '0'; + if (flags & FLAG_ALT) + { + size_t ndigits = + (precision > 0 ? precision - 1 : 0); + *p++ = decimal_point_char (); + for (; ndigits > 0; --ndigits) + *p++ = '0'; + } + } + else + abort (); +# endif + } + } + } +# endif + + /* The generated string now extends from tmp to p, with the + zero padding insertion point being at pad_ptr. */ + count = p - tmp; + + if (count < width) + { + size_t pad = width - count; + DCHAR_T *end = p + pad; + + if (flags & FLAG_LEFT) + { + /* Pad with spaces on the right. */ + for (; pad > 0; pad--) + *p++ = ' '; + } + else if ((flags & FLAG_ZERO) && pad_ptr != NULL) + { + /* Pad with zeroes. */ + DCHAR_T *q = end; + + while (p > pad_ptr) + *--q = *--p; + for (; pad > 0; pad--) + *p++ = '0'; + } + else + { + /* Pad with spaces on the left. */ + DCHAR_T *q = end; + + while (p > tmp) + *--q = *--p; + for (; pad > 0; pad--) + *p++ = ' '; + } + + p = end; + } + + count = p - tmp; + + if (count >= tmp_length) + /* tmp_length was incorrectly calculated - fix the + code above! */ + abort (); + + /* Make room for the result. */ + if (count >= allocated - length) + { + size_t n = xsum (length, count); + + ENSURE_ALLOCATION (n); + } + + /* Append the result. */ + memcpy (result + length, tmp, count * sizeof (DCHAR_T)); + if (tmp != tmpbuf) + free (tmp); + length += count; + } +#endif + else + { + arg_type type = a.arg[dp->arg_index].type; + int flags = dp->flags; +#if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION + int has_width; +#endif +#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION + size_t width; +#endif +#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || NEED_PRINTF_UNBOUNDED_PRECISION + int has_precision; + size_t precision; +#endif +#if NEED_PRINTF_UNBOUNDED_PRECISION + int prec_ourselves; +#else +# define prec_ourselves 0 +#endif +#if NEED_PRINTF_FLAG_LEFTADJUST +# define pad_ourselves 1 +#elif !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION + int pad_ourselves; +#else +# define pad_ourselves 0 +#endif + TCHAR_T *fbp; + unsigned int prefix_count; + int prefixes[2] IF_LINT (= { 0 }); + int orig_errno; +#if !USE_SNPRINTF + size_t tmp_length; + TCHAR_T tmpbuf[700]; + TCHAR_T *tmp; +#endif + +#if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION + has_width = 0; +#endif +#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION + width = 0; + if (dp->width_start != dp->width_end) + { + if (dp->width_arg_index != ARG_NONE) + { + int arg; + + if (!(a.arg[dp->width_arg_index].type == TYPE_INT)) + abort (); + arg = a.arg[dp->width_arg_index].a.a_int; + width = arg; + if (arg < 0) + { + /* "A negative field width is taken as a '-' flag + followed by a positive field width." */ + flags |= FLAG_LEFT; + width = -width; + } + } + else + { + const FCHAR_T *digitp = dp->width_start; + + do + width = xsum (xtimes (width, 10), *digitp++ - '0'); + while (digitp != dp->width_end); + } +#if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION + has_width = 1; +#endif + } +#endif + +#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || NEED_PRINTF_UNBOUNDED_PRECISION + has_precision = 0; + precision = 6; + if (dp->precision_start != dp->precision_end) + { + if (dp->precision_arg_index != ARG_NONE) + { + int arg; + + if (!(a.arg[dp->precision_arg_index].type == TYPE_INT)) + abort (); + arg = a.arg[dp->precision_arg_index].a.a_int; + /* "A negative precision is taken as if the precision + were omitted." */ + if (arg >= 0) + { + precision = arg; + has_precision = 1; + } + } + else + { + const FCHAR_T *digitp = dp->precision_start + 1; + + precision = 0; + while (digitp != dp->precision_end) + precision = xsum (xtimes (precision, 10), *digitp++ - '0'); + has_precision = 1; + } + } +#endif + + /* Decide whether to handle the precision ourselves. */ +#if NEED_PRINTF_UNBOUNDED_PRECISION + switch (dp->conversion) + { + case 'd': case 'i': case 'u': + case 'o': + case 'x': case 'X': case 'p': + prec_ourselves = has_precision && (precision > 0); + break; + default: + prec_ourselves = 0; + break; + } +#endif + + /* Decide whether to perform the padding ourselves. */ +#if !NEED_PRINTF_FLAG_LEFTADJUST && (!DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION) + switch (dp->conversion) + { +# if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO + /* If we need conversion from TCHAR_T[] to DCHAR_T[], we need + to perform the padding after this conversion. Functions + with unistdio extensions perform the padding based on + character count rather than element count. */ + case 'c': case 's': +# endif +# if NEED_PRINTF_FLAG_ZERO + case 'f': case 'F': case 'e': case 'E': case 'g': case 'G': + case 'a': case 'A': +# endif + pad_ourselves = 1; + break; + default: + pad_ourselves = prec_ourselves; + break; + } +#endif + +#if !USE_SNPRINTF + /* Allocate a temporary buffer of sufficient size for calling + sprintf. */ + tmp_length = + MAX_ROOM_NEEDED (&a, dp->arg_index, dp->conversion, type, + flags, width, has_precision, precision, + pad_ourselves); + + if (tmp_length <= sizeof (tmpbuf) / sizeof (TCHAR_T)) + tmp = tmpbuf; + else + { + size_t tmp_memsize = xtimes (tmp_length, sizeof (TCHAR_T)); + + if (size_overflow_p (tmp_memsize)) + /* Overflow, would lead to out of memory. */ + goto out_of_memory; + tmp = (TCHAR_T *) malloc (tmp_memsize); + if (tmp == NULL) + /* Out of memory. */ + goto out_of_memory; + } +#endif + + /* Construct the format string for calling snprintf or + sprintf. */ + fbp = buf; + *fbp++ = '%'; +#if NEED_PRINTF_FLAG_GROUPING + /* The underlying implementation doesn't support the ' flag. + Produce no grouping characters in this case; this is + acceptable because the grouping is locale dependent. */ +#else + if (flags & FLAG_GROUP) + *fbp++ = '\''; +#endif + if (flags & FLAG_LEFT) + *fbp++ = '-'; + if (flags & FLAG_SHOWSIGN) + *fbp++ = '+'; + if (flags & FLAG_SPACE) + *fbp++ = ' '; + if (flags & FLAG_ALT) + *fbp++ = '#'; +#if __GLIBC__ >= 2 && !defined __UCLIBC__ + if (flags & FLAG_LOCALIZED) + *fbp++ = 'I'; +#endif + if (!pad_ourselves) + { + if (flags & FLAG_ZERO) + *fbp++ = '0'; + if (dp->width_start != dp->width_end) + { + size_t n = dp->width_end - dp->width_start; + /* The width specification is known to consist only + of standard ASCII characters. */ + if (sizeof (FCHAR_T) == sizeof (TCHAR_T)) + { + memcpy (fbp, dp->width_start, n * sizeof (TCHAR_T)); + fbp += n; + } + else + { + const FCHAR_T *mp = dp->width_start; + do + *fbp++ = (unsigned char) *mp++; + while (--n > 0); + } + } + } + if (!prec_ourselves) + { + if (dp->precision_start != dp->precision_end) + { + size_t n = dp->precision_end - dp->precision_start; + /* The precision specification is known to consist only + of standard ASCII characters. */ + if (sizeof (FCHAR_T) == sizeof (TCHAR_T)) + { + memcpy (fbp, dp->precision_start, n * sizeof (TCHAR_T)); + fbp += n; + } + else + { + const FCHAR_T *mp = dp->precision_start; + do + *fbp++ = (unsigned char) *mp++; + while (--n > 0); + } + } + } + + switch (type) + { +#if HAVE_LONG_LONG_INT + case TYPE_LONGLONGINT: + case TYPE_ULONGLONGINT: +# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ + *fbp++ = 'I'; + *fbp++ = '6'; + *fbp++ = '4'; + break; +# else + *fbp++ = 'l'; + /*FALLTHROUGH*/ +# endif +#endif + case TYPE_LONGINT: + case TYPE_ULONGINT: +#if HAVE_WINT_T + case TYPE_WIDE_CHAR: +#endif +#if HAVE_WCHAR_T + case TYPE_WIDE_STRING: +#endif + *fbp++ = 'l'; + break; + case TYPE_LONGDOUBLE: + *fbp++ = 'L'; + break; + default: + break; + } +#if NEED_PRINTF_DIRECTIVE_F + if (dp->conversion == 'F') + *fbp = 'f'; + else +#endif + *fbp = dp->conversion; +#if USE_SNPRINTF +# if !(((__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3)) && !defined __UCLIBC__) || ((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__)) + fbp[1] = '%'; + fbp[2] = 'n'; + fbp[3] = '\0'; +# else + /* On glibc2 systems from glibc >= 2.3 - probably also older + ones - we know that snprintf's return value conforms to + ISO C 99: the tests gl_SNPRINTF_RETVAL_C99 and + gl_SNPRINTF_TRUNCATION_C99 pass. + Therefore we can avoid using %n in this situation. + On glibc2 systems from 2004-10-18 or newer, the use of %n + in format strings in writable memory may crash the program + (if compiled with _FORTIFY_SOURCE=2), so we should avoid it + in this situation. */ + /* On native Windows systems (such as mingw), we can avoid using + %n because: + - Although the gl_SNPRINTF_TRUNCATION_C99 test fails, + snprintf does not write more than the specified number + of bytes. (snprintf (buf, 3, "%d %d", 4567, 89) writes + '4', '5', '6' into buf, not '4', '5', '\0'.) + - Although the gl_SNPRINTF_RETVAL_C99 test fails, snprintf + allows us to recognize the case of an insufficient + buffer size: it returns -1 in this case. + On native Windows systems (such as mingw) where the OS is + Windows Vista, the use of %n in format strings by default + crashes the program. See + and + + So we should avoid %n in this situation. */ + fbp[1] = '\0'; +# endif +#else + fbp[1] = '\0'; +#endif + + /* Construct the arguments for calling snprintf or sprintf. */ + prefix_count = 0; + if (!pad_ourselves && dp->width_arg_index != ARG_NONE) + { + if (!(a.arg[dp->width_arg_index].type == TYPE_INT)) + abort (); + prefixes[prefix_count++] = a.arg[dp->width_arg_index].a.a_int; + } + if (!prec_ourselves && dp->precision_arg_index != ARG_NONE) + { + if (!(a.arg[dp->precision_arg_index].type == TYPE_INT)) + abort (); + prefixes[prefix_count++] = a.arg[dp->precision_arg_index].a.a_int; + } + +#if USE_SNPRINTF + /* The SNPRINTF result is appended after result[0..length]. + The latter is an array of DCHAR_T; SNPRINTF appends an + array of TCHAR_T to it. This is possible because + sizeof (TCHAR_T) divides sizeof (DCHAR_T) and + alignof (TCHAR_T) <= alignof (DCHAR_T). */ +# define TCHARS_PER_DCHAR (sizeof (DCHAR_T) / sizeof (TCHAR_T)) + /* Ensure that maxlen below will be >= 2. Needed on BeOS, + where an snprintf() with maxlen==1 acts like sprintf(). */ + ENSURE_ALLOCATION (xsum (length, + (2 + TCHARS_PER_DCHAR - 1) + / TCHARS_PER_DCHAR)); + /* Prepare checking whether snprintf returns the count + via %n. */ + *(TCHAR_T *) (result + length) = '\0'; +#endif + + orig_errno = errno; + + for (;;) + { + int count = -1; + +#if USE_SNPRINTF + int retcount = 0; + size_t maxlen = allocated - length; + /* SNPRINTF can fail if its second argument is + > INT_MAX. */ + if (maxlen > INT_MAX / TCHARS_PER_DCHAR) + maxlen = INT_MAX / TCHARS_PER_DCHAR; + maxlen = maxlen * TCHARS_PER_DCHAR; +# define SNPRINTF_BUF(arg) \ + switch (prefix_count) \ + { \ + case 0: \ + retcount = SNPRINTF ((TCHAR_T *) (result + length), \ + maxlen, buf, \ + arg, &count); \ + break; \ + case 1: \ + retcount = SNPRINTF ((TCHAR_T *) (result + length), \ + maxlen, buf, \ + prefixes[0], arg, &count); \ + break; \ + case 2: \ + retcount = SNPRINTF ((TCHAR_T *) (result + length), \ + maxlen, buf, \ + prefixes[0], prefixes[1], arg, \ + &count); \ + break; \ + default: \ + abort (); \ + } +#else +# define SNPRINTF_BUF(arg) \ + switch (prefix_count) \ + { \ + case 0: \ + count = sprintf (tmp, buf, arg); \ + break; \ + case 1: \ + count = sprintf (tmp, buf, prefixes[0], arg); \ + break; \ + case 2: \ + count = sprintf (tmp, buf, prefixes[0], prefixes[1],\ + arg); \ + break; \ + default: \ + abort (); \ + } +#endif + + errno = 0; + switch (type) + { + case TYPE_SCHAR: + { + int arg = a.arg[dp->arg_index].a.a_schar; + SNPRINTF_BUF (arg); + } + break; + case TYPE_UCHAR: + { + unsigned int arg = a.arg[dp->arg_index].a.a_uchar; + SNPRINTF_BUF (arg); + } + break; + case TYPE_SHORT: + { + int arg = a.arg[dp->arg_index].a.a_short; + SNPRINTF_BUF (arg); + } + break; + case TYPE_USHORT: + { + unsigned int arg = a.arg[dp->arg_index].a.a_ushort; + SNPRINTF_BUF (arg); + } + break; + case TYPE_INT: + { + int arg = a.arg[dp->arg_index].a.a_int; + SNPRINTF_BUF (arg); + } + break; + case TYPE_UINT: + { + unsigned int arg = a.arg[dp->arg_index].a.a_uint; + SNPRINTF_BUF (arg); + } + break; + case TYPE_LONGINT: + { + long int arg = a.arg[dp->arg_index].a.a_longint; + SNPRINTF_BUF (arg); + } + break; + case TYPE_ULONGINT: + { + unsigned long int arg = a.arg[dp->arg_index].a.a_ulongint; + SNPRINTF_BUF (arg); + } + break; +#if HAVE_LONG_LONG_INT + case TYPE_LONGLONGINT: + { + long long int arg = a.arg[dp->arg_index].a.a_longlongint; + SNPRINTF_BUF (arg); + } + break; + case TYPE_ULONGLONGINT: + { + unsigned long long int arg = a.arg[dp->arg_index].a.a_ulonglongint; + SNPRINTF_BUF (arg); + } + break; +#endif + case TYPE_DOUBLE: + { + double arg = a.arg[dp->arg_index].a.a_double; + SNPRINTF_BUF (arg); + } + break; + case TYPE_LONGDOUBLE: + { + long double arg = a.arg[dp->arg_index].a.a_longdouble; + SNPRINTF_BUF (arg); + } + break; + case TYPE_CHAR: + { + int arg = a.arg[dp->arg_index].a.a_char; + SNPRINTF_BUF (arg); + } + break; +#if HAVE_WINT_T + case TYPE_WIDE_CHAR: + { + wint_t arg = a.arg[dp->arg_index].a.a_wide_char; + SNPRINTF_BUF (arg); + } + break; +#endif + case TYPE_STRING: + { + const char *arg = a.arg[dp->arg_index].a.a_string; + SNPRINTF_BUF (arg); + } + break; +#if HAVE_WCHAR_T + case TYPE_WIDE_STRING: + { + const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string; + SNPRINTF_BUF (arg); + } + break; +#endif + case TYPE_POINTER: + { + void *arg = a.arg[dp->arg_index].a.a_pointer; + SNPRINTF_BUF (arg); + } + break; + default: + abort (); + } + +#if USE_SNPRINTF + /* Portability: Not all implementations of snprintf() + are ISO C 99 compliant. Determine the number of + bytes that snprintf() has produced or would have + produced. */ + if (count >= 0) + { + /* Verify that snprintf() has NUL-terminated its + result. */ + if (count < maxlen + && ((TCHAR_T *) (result + length)) [count] != '\0') + abort (); + /* Portability hack. */ + if (retcount > count) + count = retcount; + } + else + { + /* snprintf() doesn't understand the '%n' + directive. */ + if (fbp[1] != '\0') + { + /* Don't use the '%n' directive; instead, look + at the snprintf() return value. */ + fbp[1] = '\0'; + continue; + } + else + { + /* Look at the snprintf() return value. */ + if (retcount < 0) + { +# if !HAVE_SNPRINTF_RETVAL_C99 + /* HP-UX 10.20 snprintf() is doubly deficient: + It doesn't understand the '%n' directive, + *and* it returns -1 (rather than the length + that would have been required) when the + buffer is too small. + But a failure at this point can also come + from other reasons than a too small buffer, + such as an invalid wide string argument to + the %ls directive, or possibly an invalid + floating-point argument. */ + size_t tmp_length = + MAX_ROOM_NEEDED (&a, dp->arg_index, + dp->conversion, type, flags, + width, + has_precision, + precision, pad_ourselves); + + if (maxlen < tmp_length) + { + /* Make more room. But try to do through + this reallocation only once. */ + size_t bigger_need = + xsum (length, + xsum (tmp_length, + TCHARS_PER_DCHAR - 1) + / TCHARS_PER_DCHAR); + /* And always grow proportionally. + (There may be several arguments, each + needing a little more room than the + previous one.) */ + size_t bigger_need2 = + xsum (xtimes (allocated, 2), 12); + if (bigger_need < bigger_need2) + bigger_need = bigger_need2; + ENSURE_ALLOCATION (bigger_need); + continue; + } +# endif + } + else + count = retcount; + } + } +#endif + + /* Attempt to handle failure. */ + if (count < 0) + { + /* SNPRINTF or sprintf failed. Save and use the errno + that it has set, if any. */ + int saved_errno = errno; + + if (!(result == resultbuf || result == NULL)) + free (result); + if (buf_malloced != NULL) + free (buf_malloced); + CLEANUP (); + errno = + (saved_errno != 0 + ? saved_errno + : (dp->conversion == 'c' || dp->conversion == 's' + ? EILSEQ + : EINVAL)); + return NULL; + } + +#if USE_SNPRINTF + /* Handle overflow of the allocated buffer. + If such an overflow occurs, a C99 compliant snprintf() + returns a count >= maxlen. However, a non-compliant + snprintf() function returns only count = maxlen - 1. To + cover both cases, test whether count >= maxlen - 1. */ + if ((unsigned int) count + 1 >= maxlen) + { + /* If maxlen already has attained its allowed maximum, + allocating more memory will not increase maxlen. + Instead of looping, bail out. */ + if (maxlen == INT_MAX / TCHARS_PER_DCHAR) + goto overflow; + else + { + /* Need at least (count + 1) * sizeof (TCHAR_T) + bytes. (The +1 is for the trailing NUL.) + But ask for (count + 2) * sizeof (TCHAR_T) + bytes, so that in the next round, we likely get + maxlen > (unsigned int) count + 1 + and so we don't get here again. + And allocate proportionally, to avoid looping + eternally if snprintf() reports a too small + count. */ + size_t n = + xmax (xsum (length, + ((unsigned int) count + 2 + + TCHARS_PER_DCHAR - 1) + / TCHARS_PER_DCHAR), + xtimes (allocated, 2)); + + ENSURE_ALLOCATION (n); + continue; + } + } +#endif + +#if NEED_PRINTF_UNBOUNDED_PRECISION + if (prec_ourselves) + { + /* Handle the precision. */ + TCHAR_T *prec_ptr = +# if USE_SNPRINTF + (TCHAR_T *) (result + length); +# else + tmp; +# endif + size_t prefix_count; + size_t move; + + prefix_count = 0; + /* Put the additional zeroes after the sign. */ + if (count >= 1 + && (*prec_ptr == '-' || *prec_ptr == '+' + || *prec_ptr == ' ')) + prefix_count = 1; + /* Put the additional zeroes after the 0x prefix if + (flags & FLAG_ALT) || (dp->conversion == 'p'). */ + else if (count >= 2 + && prec_ptr[0] == '0' + && (prec_ptr[1] == 'x' || prec_ptr[1] == 'X')) + prefix_count = 2; + + move = count - prefix_count; + if (precision > move) + { + /* Insert zeroes. */ + size_t insert = precision - move; + TCHAR_T *prec_end; + +# if USE_SNPRINTF + size_t n = + xsum (length, + (count + insert + TCHARS_PER_DCHAR - 1) + / TCHARS_PER_DCHAR); + length += (count + TCHARS_PER_DCHAR - 1) / TCHARS_PER_DCHAR; + ENSURE_ALLOCATION (n); + length -= (count + TCHARS_PER_DCHAR - 1) / TCHARS_PER_DCHAR; + prec_ptr = (TCHAR_T *) (result + length); +# endif + + prec_end = prec_ptr + count; + prec_ptr += prefix_count; + + while (prec_end > prec_ptr) + { + prec_end--; + prec_end[insert] = prec_end[0]; + } + + prec_end += insert; + do + *--prec_end = '0'; + while (prec_end > prec_ptr); + + count += insert; + } + } +#endif + +#if !USE_SNPRINTF + if (count >= tmp_length) + /* tmp_length was incorrectly calculated - fix the + code above! */ + abort (); +#endif + +#if !DCHAR_IS_TCHAR + /* Convert from TCHAR_T[] to DCHAR_T[]. */ + if (dp->conversion == 'c' || dp->conversion == 's') + { + /* type = TYPE_CHAR or TYPE_WIDE_CHAR or TYPE_STRING + TYPE_WIDE_STRING. + The result string is not certainly ASCII. */ + const TCHAR_T *tmpsrc; + DCHAR_T *tmpdst; + size_t tmpdst_len; + /* This code assumes that TCHAR_T is 'char'. */ + verify (sizeof (TCHAR_T) == 1); +# if USE_SNPRINTF + tmpsrc = (TCHAR_T *) (result + length); +# else + tmpsrc = tmp; +# endif + tmpdst = + DCHAR_CONV_FROM_ENCODING (locale_charset (), + iconveh_question_mark, + tmpsrc, count, + NULL, + NULL, &tmpdst_len); + if (tmpdst == NULL) + { + int saved_errno = errno; + if (!(result == resultbuf || result == NULL)) + free (result); + if (buf_malloced != NULL) + free (buf_malloced); + CLEANUP (); + errno = saved_errno; + return NULL; + } + ENSURE_ALLOCATION (xsum (length, tmpdst_len)); + DCHAR_CPY (result + length, tmpdst, tmpdst_len); + free (tmpdst); + count = tmpdst_len; + } + else + { + /* The result string is ASCII. + Simple 1:1 conversion. */ +# if USE_SNPRINTF + /* If sizeof (DCHAR_T) == sizeof (TCHAR_T), it's a + no-op conversion, in-place on the array starting + at (result + length). */ + if (sizeof (DCHAR_T) != sizeof (TCHAR_T)) +# endif + { + const TCHAR_T *tmpsrc; + DCHAR_T *tmpdst; + size_t n; + +# if USE_SNPRINTF + if (result == resultbuf) + { + tmpsrc = (TCHAR_T *) (result + length); + /* ENSURE_ALLOCATION will not move tmpsrc + (because it's part of resultbuf). */ + ENSURE_ALLOCATION (xsum (length, count)); + } + else + { + /* ENSURE_ALLOCATION will move the array + (because it uses realloc(). */ + ENSURE_ALLOCATION (xsum (length, count)); + tmpsrc = (TCHAR_T *) (result + length); + } +# else + tmpsrc = tmp; + ENSURE_ALLOCATION (xsum (length, count)); +# endif + tmpdst = result + length; + /* Copy backwards, because of overlapping. */ + tmpsrc += count; + tmpdst += count; + for (n = count; n > 0; n--) + *--tmpdst = (unsigned char) *--tmpsrc; + } + } +#endif + +#if DCHAR_IS_TCHAR && !USE_SNPRINTF + /* Make room for the result. */ + if (count > allocated - length) + { + /* Need at least count elements. But allocate + proportionally. */ + size_t n = + xmax (xsum (length, count), xtimes (allocated, 2)); + + ENSURE_ALLOCATION (n); + } +#endif + + /* Here count <= allocated - length. */ + + /* Perform padding. */ +#if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION + if (pad_ourselves && has_width) + { + size_t w; +# if ENABLE_UNISTDIO + /* Outside POSIX, it's preferable to compare the width + against the number of _characters_ of the converted + value. */ + w = DCHAR_MBSNLEN (result + length, count); +# else + /* The width is compared against the number of _bytes_ + of the converted value, says POSIX. */ + w = count; +# endif + if (w < width) + { + size_t pad = width - w; + + /* Make room for the result. */ + if (xsum (count, pad) > allocated - length) + { + /* Need at least count + pad elements. But + allocate proportionally. */ + size_t n = + xmax (xsum3 (length, count, pad), + xtimes (allocated, 2)); + +# if USE_SNPRINTF + length += count; + ENSURE_ALLOCATION (n); + length -= count; +# else + ENSURE_ALLOCATION (n); +# endif + } + /* Here count + pad <= allocated - length. */ + + { +# if !DCHAR_IS_TCHAR || USE_SNPRINTF + DCHAR_T * const rp = result + length; +# else + DCHAR_T * const rp = tmp; +# endif + DCHAR_T *p = rp + count; + DCHAR_T *end = p + pad; + DCHAR_T *pad_ptr; +# if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO + if (dp->conversion == 'c' + || dp->conversion == 's') + /* No zero-padding for string directives. */ + pad_ptr = NULL; + else +# endif + { + pad_ptr = (*rp == '-' ? rp + 1 : rp); + /* No zero-padding of "inf" and "nan". */ + if ((*pad_ptr >= 'A' && *pad_ptr <= 'Z') + || (*pad_ptr >= 'a' && *pad_ptr <= 'z')) + pad_ptr = NULL; + } + /* The generated string now extends from rp to p, + with the zero padding insertion point being at + pad_ptr. */ + + count = count + pad; /* = end - rp */ + + if (flags & FLAG_LEFT) + { + /* Pad with spaces on the right. */ + for (; pad > 0; pad--) + *p++ = ' '; + } + else if ((flags & FLAG_ZERO) && pad_ptr != NULL) + { + /* Pad with zeroes. */ + DCHAR_T *q = end; + + while (p > pad_ptr) + *--q = *--p; + for (; pad > 0; pad--) + *p++ = '0'; + } + else + { + /* Pad with spaces on the left. */ + DCHAR_T *q = end; + + while (p > rp) + *--q = *--p; + for (; pad > 0; pad--) + *p++ = ' '; + } + } + } + } +#endif + + /* Here still count <= allocated - length. */ + +#if !DCHAR_IS_TCHAR || USE_SNPRINTF + /* The snprintf() result did fit. */ +#else + /* Append the sprintf() result. */ + memcpy (result + length, tmp, count * sizeof (DCHAR_T)); +#endif +#if !USE_SNPRINTF + if (tmp != tmpbuf) + free (tmp); +#endif + +#if NEED_PRINTF_DIRECTIVE_F + if (dp->conversion == 'F') + { + /* Convert the %f result to upper case for %F. */ + DCHAR_T *rp = result + length; + size_t rc; + for (rc = count; rc > 0; rc--, rp++) + if (*rp >= 'a' && *rp <= 'z') + *rp = *rp - 'a' + 'A'; + } +#endif + + length += count; + break; + } + errno = orig_errno; +#undef pad_ourselves +#undef prec_ourselves + } + } + } + + /* Add the final NUL. */ + ENSURE_ALLOCATION (xsum (length, 1)); + result[length] = '\0'; + + if (result != resultbuf && length + 1 < allocated) + { + /* Shrink the allocated memory if possible. */ + DCHAR_T *memory; + + memory = (DCHAR_T *) realloc (result, (length + 1) * sizeof (DCHAR_T)); + if (memory != NULL) + result = memory; + } + + if (buf_malloced != NULL) + free (buf_malloced); + CLEANUP (); + *lengthp = length; + /* Note that we can produce a big string of a length > INT_MAX. POSIX + says that snprintf() fails with errno = EOVERFLOW in this case, but + that's only because snprintf() returns an 'int'. This function does + not have this limitation. */ + return result; + +#if USE_SNPRINTF + overflow: + if (!(result == resultbuf || result == NULL)) + free (result); + if (buf_malloced != NULL) + free (buf_malloced); + CLEANUP (); + errno = EOVERFLOW; + return NULL; +#endif + + out_of_memory: + if (!(result == resultbuf || result == NULL)) + free (result); + if (buf_malloced != NULL) + free (buf_malloced); + out_of_memory_1: + CLEANUP (); + errno = ENOMEM; + return NULL; + } +} + +#undef MAX_ROOM_NEEDED +#undef TCHARS_PER_DCHAR +#undef SNPRINTF +#undef USE_SNPRINTF +#undef DCHAR_SET +#undef DCHAR_CPY +#undef PRINTF_PARSE +#undef DIRECTIVES +#undef DIRECTIVE +#undef DCHAR_IS_TCHAR +#undef TCHAR_T +#undef DCHAR_T +#undef FCHAR_T +#undef VASNPRINTF diff --git a/gettext-tools/gnulib-lib/vasnprintf.h b/gettext-tools/gnulib-lib/vasnprintf.h new file mode 100644 index 0000000..daa946d --- /dev/null +++ b/gettext-tools/gnulib-lib/vasnprintf.h @@ -0,0 +1,79 @@ +/* vsprintf with automatic memory allocation. + Copyright (C) 2002-2004, 2007-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, see . */ + +#ifndef _VASNPRINTF_H +#define _VASNPRINTF_H + +/* Get va_list. */ +#include + +/* Get size_t. */ +#include + +/* The __attribute__ feature is available in gcc versions 2.5 and later. + The __-protected variants of the attributes 'format' and 'printf' are + accepted by gcc versions 2.6.4 (effectively 2.7) and later. + We enable _GL_ATTRIBUTE_FORMAT only if these are supported too, because + gnulib and libintl do '#define printf __printf__' when they override + the 'printf' function. */ +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7) +# define _GL_ATTRIBUTE_FORMAT(spec) __attribute__ ((__format__ spec)) +#else +# define _GL_ATTRIBUTE_FORMAT(spec) /* empty */ +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* Write formatted output to a string dynamically allocated with malloc(). + You can pass a preallocated buffer for the result in RESULTBUF and its + size in *LENGTHP; otherwise you pass RESULTBUF = NULL. + If successful, return the address of the string (this may be = RESULTBUF + if no dynamic memory allocation was necessary) and set *LENGTHP to the + number of resulting bytes, excluding the trailing NUL. Upon error, set + errno and return NULL. + + When dynamic memory allocation occurs, the preallocated buffer is left + alone (with possibly modified contents). This makes it possible to use + a statically allocated or stack-allocated buffer, like this: + + char buf[100]; + size_t len = sizeof (buf); + char *output = vasnprintf (buf, &len, format, args); + if (output == NULL) + ... error handling ...; + else + { + ... use the output string ...; + if (output != buf) + free (output); + } + */ +#if REPLACE_VASNPRINTF +# define asnprintf rpl_asnprintf +# define vasnprintf rpl_vasnprintf +#endif +extern char * asnprintf (char *resultbuf, size_t *lengthp, const char *format, ...) + _GL_ATTRIBUTE_FORMAT ((__printf__, 3, 4)); +extern char * vasnprintf (char *resultbuf, size_t *lengthp, const char *format, va_list args) + _GL_ATTRIBUTE_FORMAT ((__printf__, 3, 0)); + +#ifdef __cplusplus +} +#endif + +#endif /* _VASNPRINTF_H */ diff --git a/gettext-tools/gnulib-lib/vasprintf.c b/gettext-tools/gnulib-lib/vasprintf.c new file mode 100644 index 0000000..eed9037 --- /dev/null +++ b/gettext-tools/gnulib-lib/vasprintf.c @@ -0,0 +1,50 @@ +/* Formatted output to strings. + Copyright (C) 1999, 2002, 2006-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, see . */ + +#include + +/* Specification. */ +#ifdef IN_LIBASPRINTF +# include "vasprintf.h" +#else +# include +#endif + +#include +#include +#include + +#include "vasnprintf.h" + +int +vasprintf (char **resultp, const char *format, va_list args) +{ + size_t length; + char *result = vasnprintf (NULL, &length, format, args); + if (result == NULL) + return -1; + + if (length > INT_MAX) + { + free (result); + errno = EOVERFLOW; + return -1; + } + + *resultp = result; + /* Return the number of resulting bytes, excluding the trailing NUL. */ + return length; +} diff --git a/gettext-tools/gnulib-lib/verify.h b/gettext-tools/gnulib-lib/verify.h new file mode 100644 index 0000000..a25e514 --- /dev/null +++ b/gettext-tools/gnulib-lib/verify.h @@ -0,0 +1,279 @@ +/* Compile-time assert-like macros. + + Copyright (C) 2005-2006, 2009-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Written by Paul Eggert, Bruno Haible, and Jim Meyering. */ + +#ifndef _GL_VERIFY_H +#define _GL_VERIFY_H + + +/* Define _GL_HAVE__STATIC_ASSERT to 1 if _Static_assert works as per C11. + This is supported by GCC 4.6.0 and later, in C mode, and its use + here generates easier-to-read diagnostics when verify (R) fails. + + Define _GL_HAVE_STATIC_ASSERT to 1 if static_assert works as per C++11. + This will likely be supported by future GCC versions, in C++ mode. + + Use this only with GCC. If we were willing to slow 'configure' + down we could also use it with other compilers, but since this + affects only the quality of diagnostics, why bother? */ +#if (4 < __GNUC__ + (6 <= __GNUC_MINOR__) \ + && (201112L <= __STDC_VERSION__ || !defined __STRICT_ANSI__) \ + && !defined __cplusplus) +# define _GL_HAVE__STATIC_ASSERT 1 +#endif +/* The condition (99 < __GNUC__) is temporary, until we know about the + first G++ release that supports static_assert. */ +#if (99 < __GNUC__) && defined __cplusplus +# define _GL_HAVE_STATIC_ASSERT 1 +#endif + +/* FreeBSD 9.1 , included by and lots of other + system headers, defines a conflicting _Static_assert that is no + better than ours; override it. */ +#ifndef _GL_HAVE_STATIC_ASSERT +# include +# undef _Static_assert +#endif + +/* Each of these macros verifies that its argument R is nonzero. To + be portable, R should be an integer constant expression. Unlike + assert (R), there is no run-time overhead. + + If _Static_assert works, verify (R) uses it directly. Similarly, + _GL_VERIFY_TRUE works by packaging a _Static_assert inside a struct + that is an operand of sizeof. + + The code below uses several ideas for C++ compilers, and for C + compilers that do not support _Static_assert: + + * The first step is ((R) ? 1 : -1). Given an expression R, of + integral or boolean or floating-point type, this yields an + expression of integral type, whose value is later verified to be + constant and nonnegative. + + * Next this expression W is wrapped in a type + struct _gl_verify_type { + unsigned int _gl_verify_error_if_negative: W; + }. + If W is negative, this yields a compile-time error. No compiler can + deal with a bit-field of negative size. + + One might think that an array size check would have the same + effect, that is, that the type struct { unsigned int dummy[W]; } + would work as well. However, inside a function, some compilers + (such as C++ compilers and GNU C) allow local parameters and + variables inside array size expressions. With these compilers, + an array size check would not properly diagnose this misuse of + the verify macro: + + void function (int n) { verify (n < 0); } + + * For the verify macro, the struct _gl_verify_type will need to + somehow be embedded into a declaration. To be portable, this + declaration must declare an object, a constant, a function, or a + typedef name. If the declared entity uses the type directly, + such as in + + struct dummy {...}; + typedef struct {...} dummy; + extern struct {...} *dummy; + extern void dummy (struct {...} *); + extern struct {...} *dummy (void); + + two uses of the verify macro would yield colliding declarations + if the entity names are not disambiguated. A workaround is to + attach the current line number to the entity name: + + #define _GL_CONCAT0(x, y) x##y + #define _GL_CONCAT(x, y) _GL_CONCAT0 (x, y) + extern struct {...} * _GL_CONCAT (dummy, __LINE__); + + But this has the problem that two invocations of verify from + within the same macro would collide, since the __LINE__ value + would be the same for both invocations. (The GCC __COUNTER__ + macro solves this problem, but is not portable.) + + A solution is to use the sizeof operator. It yields a number, + getting rid of the identity of the type. Declarations like + + extern int dummy [sizeof (struct {...})]; + extern void dummy (int [sizeof (struct {...})]); + extern int (*dummy (void)) [sizeof (struct {...})]; + + can be repeated. + + * Should the implementation use a named struct or an unnamed struct? + Which of the following alternatives can be used? + + extern int dummy [sizeof (struct {...})]; + extern int dummy [sizeof (struct _gl_verify_type {...})]; + extern void dummy (int [sizeof (struct {...})]); + extern void dummy (int [sizeof (struct _gl_verify_type {...})]); + extern int (*dummy (void)) [sizeof (struct {...})]; + extern int (*dummy (void)) [sizeof (struct _gl_verify_type {...})]; + + In the second and sixth case, the struct type is exported to the + outer scope; two such declarations therefore collide. GCC warns + about the first, third, and fourth cases. So the only remaining + possibility is the fifth case: + + extern int (*dummy (void)) [sizeof (struct {...})]; + + * GCC warns about duplicate declarations of the dummy function if + -Wredundant-decls is used. GCC 4.3 and later have a builtin + __COUNTER__ macro that can let us generate unique identifiers for + each dummy function, to suppress this warning. + + * This implementation exploits the fact that older versions of GCC, + which do not support _Static_assert, also do not warn about the + last declaration mentioned above. + + * GCC warns if -Wnested-externs is enabled and verify() is used + within a function body; but inside a function, you can always + arrange to use verify_expr() instead. + + * In C++, any struct definition inside sizeof is invalid. + Use a template type to work around the problem. */ + +/* Concatenate two preprocessor tokens. */ +#define _GL_CONCAT(x, y) _GL_CONCAT0 (x, y) +#define _GL_CONCAT0(x, y) x##y + +/* _GL_COUNTER is an integer, preferably one that changes each time we + use it. Use __COUNTER__ if it works, falling back on __LINE__ + otherwise. __LINE__ isn't perfect, but it's better than a + constant. */ +#if defined __COUNTER__ && __COUNTER__ != __COUNTER__ +# define _GL_COUNTER __COUNTER__ +#else +# define _GL_COUNTER __LINE__ +#endif + +/* Generate a symbol with the given prefix, making it unique if + possible. */ +#define _GL_GENSYM(prefix) _GL_CONCAT (prefix, _GL_COUNTER) + +/* Verify requirement R at compile-time, as an integer constant expression + that returns 1. If R is false, fail at compile-time, preferably + with a diagnostic that includes the string-literal DIAGNOSTIC. */ + +#define _GL_VERIFY_TRUE(R, DIAGNOSTIC) \ + (!!sizeof (_GL_VERIFY_TYPE (R, DIAGNOSTIC))) + +#ifdef __cplusplus +# if !GNULIB_defined_struct__gl_verify_type +template + struct _gl_verify_type { + unsigned int _gl_verify_error_if_negative: w; + }; +# define GNULIB_defined_struct__gl_verify_type 1 +# endif +# define _GL_VERIFY_TYPE(R, DIAGNOSTIC) \ + _gl_verify_type<(R) ? 1 : -1> +#elif defined _GL_HAVE__STATIC_ASSERT +# define _GL_VERIFY_TYPE(R, DIAGNOSTIC) \ + struct { \ + _Static_assert (R, DIAGNOSTIC); \ + int _gl_dummy; \ + } +#else +# define _GL_VERIFY_TYPE(R, DIAGNOSTIC) \ + struct { unsigned int _gl_verify_error_if_negative: (R) ? 1 : -1; } +#endif + +/* Verify requirement R at compile-time, as a declaration without a + trailing ';'. If R is false, fail at compile-time, preferably + with a diagnostic that includes the string-literal DIAGNOSTIC. + + Unfortunately, unlike C11, this implementation must appear as an + ordinary declaration, and cannot appear inside struct { ... }. */ + +#ifdef _GL_HAVE__STATIC_ASSERT +# define _GL_VERIFY _Static_assert +#else +# define _GL_VERIFY(R, DIAGNOSTIC) \ + extern int (*_GL_GENSYM (_gl_verify_function) (void)) \ + [_GL_VERIFY_TRUE (R, DIAGNOSTIC)] +#endif + +/* _GL_STATIC_ASSERT_H is defined if this code is copied into assert.h. */ +#ifdef _GL_STATIC_ASSERT_H +# if !defined _GL_HAVE__STATIC_ASSERT && !defined _Static_assert +# define _Static_assert(R, DIAGNOSTIC) _GL_VERIFY (R, DIAGNOSTIC) +# endif +# if !defined _GL_HAVE_STATIC_ASSERT && !defined static_assert +# define static_assert _Static_assert /* C11 requires this #define. */ +# endif +#endif + +/* @assert.h omit start@ */ + +/* Each of these macros verifies that its argument R is nonzero. To + be portable, R should be an integer constant expression. Unlike + assert (R), there is no run-time overhead. + + There are two macros, since no single macro can be used in all + contexts in C. verify_true (R) is for scalar contexts, including + integer constant expression contexts. verify (R) is for declaration + contexts, e.g., the top level. */ + +/* Verify requirement R at compile-time, as an integer constant expression. + Return 1. This is equivalent to verify_expr (R, 1). + + verify_true is obsolescent; please use verify_expr instead. */ + +#define verify_true(R) _GL_VERIFY_TRUE (R, "verify_true (" #R ")") + +/* Verify requirement R at compile-time. Return the value of the + expression E. */ + +#define verify_expr(R, E) \ + (_GL_VERIFY_TRUE (R, "verify_expr (" #R ", " #E ")") ? (E) : (E)) + +/* Verify requirement R at compile-time, as a declaration without a + trailing ';'. */ + +#define verify(R) _GL_VERIFY (R, "verify (" #R ")") + +#ifndef __has_builtin +# define __has_builtin(x) 0 +#endif + +/* Assume that R always holds. This lets the compiler optimize + accordingly. R should not have side-effects; it may or may not be + evaluated. Behavior is undefined if R is false. */ + +#if (__has_builtin (__builtin_unreachable) \ + || 4 < __GNUC__ + (5 <= __GNUC_MINOR__)) +# define assume(R) ((R) ? (void) 0 : __builtin_unreachable ()) +#elif 1200 <= _MSC_VER +# define assume(R) __assume (R) +#elif (defined lint \ + && (__has_builtin (__builtin_trap) \ + || 3 < __GNUC__ + (3 < __GNUC_MINOR__ + (4 <= __GNUC_PATCHLEVEL__)))) + /* Doing it this way helps various packages when configured with + --enable-gcc-warnings, which compiles with -Dlint. It's nicer + when 'assume' silences warnings even with older GCCs. */ +# define assume(R) ((R) ? (void) 0 : __builtin_trap ()) +#else +# define assume(R) ((void) (0 && (R))) +#endif + +/* @assert.h omit end@ */ + +#endif diff --git a/gettext-tools/gnulib-lib/vsnprintf.c b/gettext-tools/gnulib-lib/vsnprintf.c new file mode 100644 index 0000000..36346f9 --- /dev/null +++ b/gettext-tools/gnulib-lib/vsnprintf.c @@ -0,0 +1,70 @@ +/* Formatted output to strings. + Copyright (C) 2004, 2006-2014 Free Software Foundation, Inc. + Written by Simon Josefsson and Yoann Vandoorselaere . + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, see . */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +/* Specification. */ +#include + +#include +#include +#include +#include +#include + +#include "vasnprintf.h" + +/* Print formatted output to string STR. Similar to vsprintf, but + additional length SIZE limit how much is written into STR. Returns + string length of formatted string (which may be larger than SIZE). + STR may be NULL, in which case nothing will be written. On error, + return a negative value. */ +int +vsnprintf (char *str, size_t size, const char *format, va_list args) +{ + char *output; + size_t len; + size_t lenbuf = size; + + output = vasnprintf (str, &lenbuf, format, args); + len = lenbuf; + + if (!output) + return -1; + + if (output != str) + { + if (size) + { + size_t pruned_len = (len < size ? len : size - 1); + memcpy (str, output, pruned_len); + str[pruned_len] = '\0'; + } + + free (output); + } + + if (len > INT_MAX) + { + errno = EOVERFLOW; + return -1; + } + + return len; +} diff --git a/gettext-tools/gnulib-lib/w32spawn.h b/gettext-tools/gnulib-lib/w32spawn.h new file mode 100644 index 0000000..0cad232 --- /dev/null +++ b/gettext-tools/gnulib-lib/w32spawn.h @@ -0,0 +1,222 @@ +/* Auxiliary functions for the creation of subprocesses. Native Windows API. + Copyright (C) 2001, 2003-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2003. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Get declarations of the native Windows API functions. */ +#define WIN32_LEAN_AND_MEAN +#include + +/* Get _open_osfhandle(). */ +#include + +#include +#include +#include +#include + +/* Get _get_osfhandle(). */ +#include "msvc-nothrow.h" + +#include "cloexec.h" +#include "xalloc.h" + +/* Duplicates a file handle, making the copy uninheritable. + Returns -1 for a file handle that is equivalent to closed. */ +static int +dup_noinherit (int fd) +{ + fd = dup_cloexec (fd); + if (fd < 0 && errno == EMFILE) + error (EXIT_FAILURE, errno, _("_open_osfhandle failed")); + + return fd; +} + +/* Returns a file descriptor equivalent to FD, except that the resulting file + descriptor is none of STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO. + FD must be open and non-inheritable. The result will be non-inheritable as + well. + If FD < 0, FD itself is returned. */ +static int +fd_safer_noinherit (int fd) +{ + if (STDIN_FILENO <= fd && fd <= STDERR_FILENO) + { + /* The recursion depth is at most 3. */ + int nfd = fd_safer_noinherit (dup_noinherit (fd)); + int saved_errno = errno; + close (fd); + errno = saved_errno; + return nfd; + } + return fd; +} + +/* Duplicates a file handle, making the copy uninheritable and ensuring the + result is none of STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO. + Returns -1 for a file handle that is equivalent to closed. */ +static int +dup_safer_noinherit (int fd) +{ + return fd_safer_noinherit (dup_noinherit (fd)); +} + +/* Undoes the effect of TEMPFD = dup_safer_noinherit (ORIGFD); */ +static void +undup_safer_noinherit (int tempfd, int origfd) +{ + if (tempfd >= 0) + { + if (dup2 (tempfd, origfd) < 0) + error (EXIT_FAILURE, errno, _("cannot restore fd %d: dup2 failed"), + origfd); + close (tempfd); + } + else + { + /* origfd was closed or open to no handle at all. Set it to a closed + state. This is (nearly) equivalent to the original state. */ + close (origfd); + } +} + +/* Prepares an argument vector before calling spawn(). + Note that spawn() does not by itself call the command interpreter + (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") : + ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&v); + v.dwPlatformId == VER_PLATFORM_WIN32_NT; + }) ? "cmd.exe" : "command.com"). + Instead it simply concatenates the arguments, separated by ' ', and calls + CreateProcess(). We must quote the arguments since Windows CreateProcess() + interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a + special way: + - Space and tab are interpreted as delimiters. They are not treated as + delimiters if they are surrounded by double quotes: "...". + - Unescaped double quotes are removed from the input. Their only effect is + that within double quotes, space and tab are treated like normal + characters. + - Backslashes not followed by double quotes are not special. + - But 2*n+1 backslashes followed by a double quote become + n backslashes followed by a double quote (n >= 0): + \" -> " + \\\" -> \" + \\\\\" -> \\" + - '*', '?' characters may get expanded through wildcard expansion in the + callee: By default, in the callee, the initialization code before main() + takes the result of GetCommandLine(), wildcard-expands it, and passes it + to main(). The exceptions to this rule are: + - programs that inspect GetCommandLine() and ignore argv, + - mingw programs that have a global variable 'int _CRT_glob = 0;', + - Cygwin programs, when invoked from a Cygwin program. + */ +#define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037*?" +#define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" +static char ** +prepare_spawn (char **argv) +{ + size_t argc; + char **new_argv; + size_t i; + + /* Count number of arguments. */ + for (argc = 0; argv[argc] != NULL; argc++) + ; + + /* Allocate new argument vector. */ + new_argv = XNMALLOC (1 + argc + 1, char *); + + /* Add an element upfront that can be used when argv[0] turns out to be a + script, not a program. + On Unix, this would be "/bin/sh". On native Windows, "sh" is actually + "sh.exe". We have to omit the directory part and rely on the search in + PATH, because the mingw "mount points" are not visible inside Windows + CreateProcess(). */ + *new_argv++ = "sh.exe"; + + /* Put quoted arguments into the new argument vector. */ + for (i = 0; i < argc; i++) + { + const char *string = argv[i]; + + if (string[0] == '\0') + new_argv[i] = xstrdup ("\"\""); + else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL) + { + bool quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL); + size_t length; + unsigned int backslashes; + const char *s; + char *quoted_string; + char *p; + + length = 0; + backslashes = 0; + if (quote_around) + length++; + for (s = string; *s != '\0'; s++) + { + char c = *s; + if (c == '"') + length += backslashes + 1; + length++; + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + length += backslashes + 1; + + quoted_string = (char *) xmalloc (length + 1); + + p = quoted_string; + backslashes = 0; + if (quote_around) + *p++ = '"'; + for (s = string; *s != '\0'; s++) + { + char c = *s; + if (c == '"') + { + unsigned int j; + for (j = backslashes + 1; j > 0; j--) + *p++ = '\\'; + } + *p++ = c; + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + { + unsigned int j; + for (j = backslashes; j > 0; j--) + *p++ = '\\'; + *p++ = '"'; + } + *p = '\0'; + + new_argv[i] = quoted_string; + } + else + new_argv[i] = (char *) string; + } + new_argv[argc] = NULL; + + return new_argv; +} diff --git a/gettext-tools/gnulib-lib/wait-process.c b/gettext-tools/gnulib-lib/wait-process.c new file mode 100644 index 0000000..a5389fd --- /dev/null +++ b/gettext-tools/gnulib-lib/wait-process.c @@ -0,0 +1,361 @@ +/* Waiting for a subprocess to finish. + Copyright (C) 2001-2003, 2005-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2001. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + + +#include + +/* Specification. */ +#include "wait-process.h" + +#include +#include +#include +#include + +#include +#include + +#include "error.h" +#include "fatal-signal.h" +#include "xalloc.h" +#include "gettext.h" + +#define _(str) gettext (str) + +#define SIZEOF(a) (sizeof(a) / sizeof(a[0])) + + +#if defined _MSC_VER || defined __MINGW32__ + +#define WIN32_LEAN_AND_MEAN +#include + +/* The return value of spawnvp() is really a process handle as returned + by CreateProcess(). Therefore we can kill it using TerminateProcess. */ +#define kill(pid,sig) TerminateProcess ((HANDLE) (pid), sig) + +#endif + + +/* Type of an entry in the slaves array. + The 'used' bit determines whether this entry is currently in use. + (If pid_t was an atomic type like sig_atomic_t, we could just set the + 'child' field to 0 when unregistering a slave process, and wouldn't need + the 'used' field.) + The 'used' and 'child' fields are accessed from within the cleanup_slaves() + action, therefore we mark them as 'volatile'. */ +typedef struct +{ + volatile sig_atomic_t used; + volatile pid_t child; +} +slaves_entry_t; + +/* The registered slave subprocesses. */ +static slaves_entry_t static_slaves[32]; +static slaves_entry_t * volatile slaves = static_slaves; +static sig_atomic_t volatile slaves_count = 0; +static size_t slaves_allocated = SIZEOF (static_slaves); + +/* The termination signal for slave subprocesses. + 2003-10-07: Terminator becomes Governator. */ +#ifdef SIGHUP +# define TERMINATOR SIGHUP +#else +# define TERMINATOR SIGTERM +#endif + +/* The cleanup action. It gets called asynchronously. */ +static void +cleanup_slaves (void) +{ + for (;;) + { + /* Get the last registered slave. */ + size_t n = slaves_count; + if (n == 0) + break; + n--; + slaves_count = n; + /* Skip unused entries in the slaves array. */ + if (slaves[n].used) + { + pid_t slave = slaves[n].child; + + /* Kill the slave. */ + kill (slave, TERMINATOR); + } + } +} + +/* Register a subprocess as being a slave process. This means that the + subprocess will be terminated when its creator receives a catchable fatal + signal or exits normally. Registration ends when wait_subprocess() + notices that the subprocess has exited. */ +void +register_slave_subprocess (pid_t child) +{ + static bool cleanup_slaves_registered = false; + if (!cleanup_slaves_registered) + { + atexit (cleanup_slaves); + at_fatal_signal (cleanup_slaves); + cleanup_slaves_registered = true; + } + + /* Try to store the new slave in an unused entry of the slaves array. */ + { + slaves_entry_t *s = slaves; + slaves_entry_t *s_end = s + slaves_count; + + for (; s < s_end; s++) + if (!s->used) + { + /* The two uses of 'volatile' in the slaves_entry_t type above + (and ISO C 99 section 5.1.2.3.(5)) ensure that we mark the + entry as used only after the child pid has been written to the + memory location s->child. */ + s->child = child; + s->used = 1; + return; + } + } + + if (slaves_count == slaves_allocated) + { + /* Extend the slaves array. Note that we cannot use xrealloc(), + because then the cleanup_slaves() function could access an already + deallocated array. */ + slaves_entry_t *old_slaves = slaves; + size_t new_slaves_allocated = 2 * slaves_allocated; + slaves_entry_t *new_slaves = + (slaves_entry_t *) + malloc (new_slaves_allocated * sizeof (slaves_entry_t)); + if (new_slaves == NULL) + { + /* xalloc_die() will call exit() which will invoke cleanup_slaves(). + Additionally we need to kill child, because it's not yet among + the slaves list. */ + kill (child, TERMINATOR); + xalloc_die (); + } + memcpy (new_slaves, old_slaves, + slaves_allocated * sizeof (slaves_entry_t)); + slaves = new_slaves; + slaves_allocated = new_slaves_allocated; + /* Now we can free the old slaves array. */ + if (old_slaves != static_slaves) + free (old_slaves); + } + /* The three uses of 'volatile' in the types above (and ISO C 99 section + 5.1.2.3.(5)) ensure that we increment the slaves_count only after the + new slave and its 'used' bit have been written to the memory locations + that make up slaves[slaves_count]. */ + slaves[slaves_count].child = child; + slaves[slaves_count].used = 1; + slaves_count++; +} + +/* Unregister a child from the list of slave subprocesses. */ +static void +unregister_slave_subprocess (pid_t child) +{ + /* The easiest way to remove an entry from a list that can be used by + an asynchronous signal handler is just to mark it as unused. For this, + we rely on sig_atomic_t. */ + slaves_entry_t *s = slaves; + slaves_entry_t *s_end = s + slaves_count; + + for (; s < s_end; s++) + if (s->used && s->child == child) + s->used = 0; +} + + +/* Wait for a subprocess to finish. Return its exit code. + If it didn't terminate correctly, exit if exit_on_error is true, otherwise + return 127. */ +int +wait_subprocess (pid_t child, const char *progname, + bool ignore_sigpipe, bool null_stderr, + bool slave_process, bool exit_on_error, + int *termsigp) +{ +#if HAVE_WAITID && defined WNOWAIT && 0 + /* Commented out because waitid() without WEXITED and with WNOWAIT doesn't + work: On Solaris 7 and OSF/1 4.0, it returns -1 and sets errno = ECHILD, + and on HP-UX 10.20 it just hangs. */ + /* Use of waitid() with WNOWAIT avoids a race condition: If slave_process is + true, and this process sleeps a very long time between the return from + waitpid() and the execution of unregister_slave_subprocess(), and + meanwhile another process acquires the same PID as child, and then - still + before unregister_slave_subprocess() - this process gets a fatal signal, + it would kill the other totally unrelated process. */ + siginfo_t info; + + if (termsigp != NULL) + *termsigp = 0; + for (;;) + { + if (waitid (P_PID, child, &info, WEXITED | (slave_process ? WNOWAIT : 0)) + < 0) + { +# ifdef EINTR + if (errno == EINTR) + continue; +# endif + if (exit_on_error || !null_stderr) + error (exit_on_error ? EXIT_FAILURE : 0, errno, + _("%s subprocess"), progname); + return 127; + } + + /* info.si_code is set to one of CLD_EXITED, CLD_KILLED, CLD_DUMPED, + CLD_TRAPPED, CLD_STOPPED, CLD_CONTINUED. Loop until the program + terminates. */ + if (info.si_code == CLD_EXITED + || info.si_code == CLD_KILLED || info.si_code == CLD_DUMPED) + break; + } + + /* The child process has exited or was signalled. */ + + if (slave_process) + { + /* Unregister the child from the list of slave subprocesses, so that + later, when we exit, we don't kill a totally unrelated process which + may have acquired the same pid. */ + unregister_slave_subprocess (child); + + /* Now remove the zombie from the process list. */ + for (;;) + { + if (waitid (P_PID, child, &info, WEXITED) < 0) + { +# ifdef EINTR + if (errno == EINTR) + continue; +# endif + if (exit_on_error || !null_stderr) + error (exit_on_error ? EXIT_FAILURE : 0, errno, + _("%s subprocess"), progname); + return 127; + } + break; + } + } + + switch (info.si_code) + { + case CLD_KILLED: + case CLD_DUMPED: + if (termsigp != NULL) + *termsigp = info.si_status; /* TODO: or info.si_signo? */ +# ifdef SIGPIPE + if (info.si_status == SIGPIPE && ignore_sigpipe) + return 0; +# endif + if (exit_on_error || (!null_stderr && termsigp == NULL)) + error (exit_on_error ? EXIT_FAILURE : 0, 0, + _("%s subprocess got fatal signal %d"), + progname, info.si_status); + return 127; + case CLD_EXITED: + if (info.si_status == 127) + { + if (exit_on_error || !null_stderr) + error (exit_on_error ? EXIT_FAILURE : 0, 0, + _("%s subprocess failed"), progname); + return 127; + } + return info.si_status; + default: + abort (); + } +#else + /* waitpid() is just as portable as wait() nowadays. */ + int status; + + if (termsigp != NULL) + *termsigp = 0; + status = 0; + for (;;) + { + int result = waitpid (child, &status, 0); + + if (result != child) + { +# ifdef EINTR + if (errno == EINTR) + continue; +# endif +# if 0 /* defined ECHILD */ + if (errno == ECHILD) + { + /* Child process nonexistent?! Assume it terminated + successfully. */ + status = 0; + break; + } +# endif + if (exit_on_error || !null_stderr) + error (exit_on_error ? EXIT_FAILURE : 0, errno, + _("%s subprocess"), progname); + return 127; + } + + /* One of WIFSIGNALED (status), WIFEXITED (status), WIFSTOPPED (status) + must always be true, since we did not specify WCONTINUED in the + waitpid() call. Loop until the program terminates. */ + if (!WIFSTOPPED (status)) + break; + } + + /* The child process has exited or was signalled. */ + + if (slave_process) + /* Unregister the child from the list of slave subprocesses, so that + later, when we exit, we don't kill a totally unrelated process which + may have acquired the same pid. */ + unregister_slave_subprocess (child); + + if (WIFSIGNALED (status)) + { + if (termsigp != NULL) + *termsigp = WTERMSIG (status); +# ifdef SIGPIPE + if (WTERMSIG (status) == SIGPIPE && ignore_sigpipe) + return 0; +# endif + if (exit_on_error || (!null_stderr && termsigp == NULL)) + error (exit_on_error ? EXIT_FAILURE : 0, 0, + _("%s subprocess got fatal signal %d"), + progname, (int) WTERMSIG (status)); + return 127; + } + if (!WIFEXITED (status)) + abort (); + if (WEXITSTATUS (status) == 127) + { + if (exit_on_error || !null_stderr) + error (exit_on_error ? EXIT_FAILURE : 0, 0, + _("%s subprocess failed"), progname); + return 127; + } + return WEXITSTATUS (status); +#endif +} diff --git a/gettext-tools/gnulib-lib/wait-process.h b/gettext-tools/gnulib-lib/wait-process.h new file mode 100644 index 0000000..3cb48d0 --- /dev/null +++ b/gettext-tools/gnulib-lib/wait-process.h @@ -0,0 +1,74 @@ +/* Waiting for a subprocess to finish. + Copyright (C) 2001-2003, 2006, 2008-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2001. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _WAIT_PROCESS_H +#define _WAIT_PROCESS_H + +/* Get pid_t. */ +#include +#include +#include + +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Wait for a subprocess to finish. Return its exit code. + If it didn't terminate correctly, exit if exit_on_error is true, otherwise + return 127. + Arguments: + - child is the pid of the subprocess. + - progname is the name of the program executed by the subprocess, used for + error messages. + - If ignore_sigpipe is true, consider a subprocess termination due to + SIGPIPE as equivalent to a success. This is suitable for processes whose + only purpose is to write to standard output. This flag can be safely set + to false when the process' standard output is known to go to DEV_NULL. + - If null_stderr is true, the usual error message to stderr will be omitted. + This is suitable when the subprocess does not fulfill an important task. + - slave_process should be set to true if the process has been launched as a + slave process. + - If exit_on_error is true, any error will cause the main process to exit + with an error status. + - If termsigp is not NULL: *termsig will be set to the signal that + terminated the subprocess (if supported by the platform: not on native + Windows platforms), otherwise 0, and the error message about the signal + that terminated the subprocess will be omitted. + Prerequisites: The signal handler for SIGCHLD should not be set to SIG_IGN, + otherwise this function will not work. */ +extern int wait_subprocess (pid_t child, const char *progname, + bool ignore_sigpipe, bool null_stderr, + bool slave_process, bool exit_on_error, + int *termsigp); + +/* Register a subprocess as being a slave process. This means that the + subprocess will be terminated when its creator receives a catchable fatal + signal or exits normally. Registration ends when wait_subprocess() + notices that the subprocess has exited. */ +extern void register_slave_subprocess (pid_t child); + + +#ifdef __cplusplus +} +#endif + + +#endif /* _WAIT_PROCESS_H */ diff --git a/gettext-tools/gnulib-lib/waitpid.c b/gettext-tools/gnulib-lib/waitpid.c new file mode 100644 index 0000000..ab03853 --- /dev/null +++ b/gettext-tools/gnulib-lib/waitpid.c @@ -0,0 +1,30 @@ +/* Wait for process state change. + Copyright (C) 2001-2003, 2005-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . */ + +#include + +/* Specification. */ +#include + +/* Implementation for native Windows systems. */ + +#include /* for _cwait, WAIT_CHILD */ + +pid_t +waitpid (pid_t pid, int *statusp, int options) +{ + return _cwait (statusp, pid, WAIT_CHILD); +} diff --git a/gettext-tools/gnulib-lib/wchar.in.h b/gettext-tools/gnulib-lib/wchar.in.h new file mode 100644 index 0000000..473285f --- /dev/null +++ b/gettext-tools/gnulib-lib/wchar.in.h @@ -0,0 +1,1028 @@ +/* A substitute for ISO C99 , for platforms that have issues. + + Copyright (C) 2007-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . */ + +/* Written by Eric Blake. */ + +/* + * ISO C 99 for platforms that have issues. + * + * + * For now, this just ensures proper prerequisite inclusion order and + * the declaration of wcwidth(). + */ + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +#if defined __need_mbstate_t || defined __need_wint_t || (defined __hpux && ((defined _INTTYPES_INCLUDED && !defined strtoimax) || defined _GL_JUST_INCLUDE_SYSTEM_WCHAR_H)) || defined _GL_ALREADY_INCLUDING_WCHAR_H +/* Special invocation convention: + - Inside glibc and uClibc header files. + - On HP-UX 11.00 we have a sequence of nested includes + -> -> , and the latter includes , + once indirectly -> -> -> + and once directly. In both situations 'wint_t' is not yet defined, + therefore we cannot provide the function overrides; instead include only + the system's . + - On IRIX 6.5, similarly, we have an include -> , and + the latter includes . But here, we have no way to detect whether + is completely included or is still being included. */ + +#@INCLUDE_NEXT@ @NEXT_WCHAR_H@ + +#else +/* Normal invocation convention. */ + +#ifndef _@GUARD_PREFIX@_WCHAR_H + +#define _GL_ALREADY_INCLUDING_WCHAR_H + +#if @HAVE_FEATURES_H@ +# include /* for __GLIBC__ */ +#endif + +/* Tru64 with Desktop Toolkit C has a bug: must be included before + . + BSD/OS 4.0.1 has a bug: , and must be + included before . + In some builds of uClibc, is nonexistent and wchar_t is defined + by . + But avoid namespace pollution on glibc systems. */ +#if !(defined __GLIBC__ && !defined __UCLIBC__) +# include +#endif +#ifndef __GLIBC__ +# include +# include +#endif + +/* Include the original if it exists. + Some builds of uClibc lack it. */ +/* The include_next requires a split double-inclusion guard. */ +#if @HAVE_WCHAR_H@ +# @INCLUDE_NEXT@ @NEXT_WCHAR_H@ +#endif + +#undef _GL_ALREADY_INCLUDING_WCHAR_H + +#ifndef _@GUARD_PREFIX@_WCHAR_H +#define _@GUARD_PREFIX@_WCHAR_H + +/* The __attribute__ feature is available in gcc versions 2.5 and later. + The attribute __pure__ was added in gcc 2.96. */ +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96) +# define _GL_ATTRIBUTE_PURE __attribute__ ((__pure__)) +#else +# define _GL_ATTRIBUTE_PURE /* empty */ +#endif + +/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ + +/* The definition of _GL_ARG_NONNULL is copied here. */ + +/* The definition of _GL_WARN_ON_USE is copied here. */ + + +/* Define wint_t and WEOF. (Also done in wctype.in.h.) */ +#if !@HAVE_WINT_T@ && !defined wint_t +# define wint_t int +# ifndef WEOF +# define WEOF -1 +# endif +#else +/* MSVC defines wint_t as 'unsigned short' in . + This is too small: ISO C 99 section 7.24.1.(2) says that wint_t must be + "unchanged by default argument promotions". Override it. */ +# if defined _MSC_VER +# if !GNULIB_defined_wint_t +# include +typedef unsigned int rpl_wint_t; +# undef wint_t +# define wint_t rpl_wint_t +# define GNULIB_defined_wint_t 1 +# endif +# endif +# ifndef WEOF +# define WEOF ((wint_t) -1) +# endif +#endif + + +/* Override mbstate_t if it is too small. + On IRIX 6.5, sizeof (mbstate_t) == 1, which is not sufficient for + implementing mbrtowc for encodings like UTF-8. */ +#if !(@HAVE_MBSINIT@ && @HAVE_MBRTOWC@) || @REPLACE_MBSTATE_T@ +# if !GNULIB_defined_mbstate_t +typedef int rpl_mbstate_t; +# undef mbstate_t +# define mbstate_t rpl_mbstate_t +# define GNULIB_defined_mbstate_t 1 +# endif +#endif + + +/* Convert a single-byte character to a wide character. */ +#if @GNULIB_BTOWC@ +# if @REPLACE_BTOWC@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef btowc +# define btowc rpl_btowc +# endif +_GL_FUNCDECL_RPL (btowc, wint_t, (int c) _GL_ATTRIBUTE_PURE); +_GL_CXXALIAS_RPL (btowc, wint_t, (int c)); +# else +# if !@HAVE_BTOWC@ +_GL_FUNCDECL_SYS (btowc, wint_t, (int c) _GL_ATTRIBUTE_PURE); +# endif +_GL_CXXALIAS_SYS (btowc, wint_t, (int c)); +# endif +_GL_CXXALIASWARN (btowc); +#elif defined GNULIB_POSIXCHECK +# undef btowc +# if HAVE_RAW_DECL_BTOWC +_GL_WARN_ON_USE (btowc, "btowc is unportable - " + "use gnulib module btowc for portability"); +# endif +#endif + + +/* Convert a wide character to a single-byte character. */ +#if @GNULIB_WCTOB@ +# if @REPLACE_WCTOB@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef wctob +# define wctob rpl_wctob +# endif +_GL_FUNCDECL_RPL (wctob, int, (wint_t wc) _GL_ATTRIBUTE_PURE); +_GL_CXXALIAS_RPL (wctob, int, (wint_t wc)); +# else +# if !defined wctob && !@HAVE_DECL_WCTOB@ +/* wctob is provided by gnulib, or wctob exists but is not declared. */ +_GL_FUNCDECL_SYS (wctob, int, (wint_t wc) _GL_ATTRIBUTE_PURE); +# endif +_GL_CXXALIAS_SYS (wctob, int, (wint_t wc)); +# endif +_GL_CXXALIASWARN (wctob); +#elif defined GNULIB_POSIXCHECK +# undef wctob +# if HAVE_RAW_DECL_WCTOB +_GL_WARN_ON_USE (wctob, "wctob is unportable - " + "use gnulib module wctob for portability"); +# endif +#endif + + +/* Test whether *PS is in the initial state. */ +#if @GNULIB_MBSINIT@ +# if @REPLACE_MBSINIT@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef mbsinit +# define mbsinit rpl_mbsinit +# endif +_GL_FUNCDECL_RPL (mbsinit, int, (const mbstate_t *ps)); +_GL_CXXALIAS_RPL (mbsinit, int, (const mbstate_t *ps)); +# else +# if !@HAVE_MBSINIT@ +_GL_FUNCDECL_SYS (mbsinit, int, (const mbstate_t *ps)); +# endif +_GL_CXXALIAS_SYS (mbsinit, int, (const mbstate_t *ps)); +# endif +_GL_CXXALIASWARN (mbsinit); +#elif defined GNULIB_POSIXCHECK +# undef mbsinit +# if HAVE_RAW_DECL_MBSINIT +_GL_WARN_ON_USE (mbsinit, "mbsinit is unportable - " + "use gnulib module mbsinit for portability"); +# endif +#endif + + +/* Convert a multibyte character to a wide character. */ +#if @GNULIB_MBRTOWC@ +# if @REPLACE_MBRTOWC@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef mbrtowc +# define mbrtowc rpl_mbrtowc +# endif +_GL_FUNCDECL_RPL (mbrtowc, size_t, + (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps)); +_GL_CXXALIAS_RPL (mbrtowc, size_t, + (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps)); +# else +# if !@HAVE_MBRTOWC@ +_GL_FUNCDECL_SYS (mbrtowc, size_t, + (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps)); +# endif +_GL_CXXALIAS_SYS (mbrtowc, size_t, + (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps)); +# endif +_GL_CXXALIASWARN (mbrtowc); +#elif defined GNULIB_POSIXCHECK +# undef mbrtowc +# if HAVE_RAW_DECL_MBRTOWC +_GL_WARN_ON_USE (mbrtowc, "mbrtowc is unportable - " + "use gnulib module mbrtowc for portability"); +# endif +#endif + + +/* Recognize a multibyte character. */ +#if @GNULIB_MBRLEN@ +# if @REPLACE_MBRLEN@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef mbrlen +# define mbrlen rpl_mbrlen +# endif +_GL_FUNCDECL_RPL (mbrlen, size_t, (const char *s, size_t n, mbstate_t *ps)); +_GL_CXXALIAS_RPL (mbrlen, size_t, (const char *s, size_t n, mbstate_t *ps)); +# else +# if !@HAVE_MBRLEN@ +_GL_FUNCDECL_SYS (mbrlen, size_t, (const char *s, size_t n, mbstate_t *ps)); +# endif +_GL_CXXALIAS_SYS (mbrlen, size_t, (const char *s, size_t n, mbstate_t *ps)); +# endif +_GL_CXXALIASWARN (mbrlen); +#elif defined GNULIB_POSIXCHECK +# undef mbrlen +# if HAVE_RAW_DECL_MBRLEN +_GL_WARN_ON_USE (mbrlen, "mbrlen is unportable - " + "use gnulib module mbrlen for portability"); +# endif +#endif + + +/* Convert a string to a wide string. */ +#if @GNULIB_MBSRTOWCS@ +# if @REPLACE_MBSRTOWCS@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef mbsrtowcs +# define mbsrtowcs rpl_mbsrtowcs +# endif +_GL_FUNCDECL_RPL (mbsrtowcs, size_t, + (wchar_t *dest, const char **srcp, size_t len, mbstate_t *ps) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (mbsrtowcs, size_t, + (wchar_t *dest, const char **srcp, size_t len, + mbstate_t *ps)); +# else +# if !@HAVE_MBSRTOWCS@ +_GL_FUNCDECL_SYS (mbsrtowcs, size_t, + (wchar_t *dest, const char **srcp, size_t len, mbstate_t *ps) + _GL_ARG_NONNULL ((2))); +# endif +_GL_CXXALIAS_SYS (mbsrtowcs, size_t, + (wchar_t *dest, const char **srcp, size_t len, + mbstate_t *ps)); +# endif +_GL_CXXALIASWARN (mbsrtowcs); +#elif defined GNULIB_POSIXCHECK +# undef mbsrtowcs +# if HAVE_RAW_DECL_MBSRTOWCS +_GL_WARN_ON_USE (mbsrtowcs, "mbsrtowcs is unportable - " + "use gnulib module mbsrtowcs for portability"); +# endif +#endif + + +/* Convert a string to a wide string. */ +#if @GNULIB_MBSNRTOWCS@ +# if @REPLACE_MBSNRTOWCS@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef mbsnrtowcs +# define mbsnrtowcs rpl_mbsnrtowcs +# endif +_GL_FUNCDECL_RPL (mbsnrtowcs, size_t, + (wchar_t *dest, const char **srcp, size_t srclen, size_t len, + mbstate_t *ps) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (mbsnrtowcs, size_t, + (wchar_t *dest, const char **srcp, size_t srclen, size_t len, + mbstate_t *ps)); +# else +# if !@HAVE_MBSNRTOWCS@ +_GL_FUNCDECL_SYS (mbsnrtowcs, size_t, + (wchar_t *dest, const char **srcp, size_t srclen, size_t len, + mbstate_t *ps) + _GL_ARG_NONNULL ((2))); +# endif +_GL_CXXALIAS_SYS (mbsnrtowcs, size_t, + (wchar_t *dest, const char **srcp, size_t srclen, size_t len, + mbstate_t *ps)); +# endif +_GL_CXXALIASWARN (mbsnrtowcs); +#elif defined GNULIB_POSIXCHECK +# undef mbsnrtowcs +# if HAVE_RAW_DECL_MBSNRTOWCS +_GL_WARN_ON_USE (mbsnrtowcs, "mbsnrtowcs is unportable - " + "use gnulib module mbsnrtowcs for portability"); +# endif +#endif + + +/* Convert a wide character to a multibyte character. */ +#if @GNULIB_WCRTOMB@ +# if @REPLACE_WCRTOMB@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef wcrtomb +# define wcrtomb rpl_wcrtomb +# endif +_GL_FUNCDECL_RPL (wcrtomb, size_t, (char *s, wchar_t wc, mbstate_t *ps)); +_GL_CXXALIAS_RPL (wcrtomb, size_t, (char *s, wchar_t wc, mbstate_t *ps)); +# else +# if !@HAVE_WCRTOMB@ +_GL_FUNCDECL_SYS (wcrtomb, size_t, (char *s, wchar_t wc, mbstate_t *ps)); +# endif +_GL_CXXALIAS_SYS (wcrtomb, size_t, (char *s, wchar_t wc, mbstate_t *ps)); +# endif +_GL_CXXALIASWARN (wcrtomb); +#elif defined GNULIB_POSIXCHECK +# undef wcrtomb +# if HAVE_RAW_DECL_WCRTOMB +_GL_WARN_ON_USE (wcrtomb, "wcrtomb is unportable - " + "use gnulib module wcrtomb for portability"); +# endif +#endif + + +/* Convert a wide string to a string. */ +#if @GNULIB_WCSRTOMBS@ +# if @REPLACE_WCSRTOMBS@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef wcsrtombs +# define wcsrtombs rpl_wcsrtombs +# endif +_GL_FUNCDECL_RPL (wcsrtombs, size_t, + (char *dest, const wchar_t **srcp, size_t len, mbstate_t *ps) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (wcsrtombs, size_t, + (char *dest, const wchar_t **srcp, size_t len, + mbstate_t *ps)); +# else +# if !@HAVE_WCSRTOMBS@ +_GL_FUNCDECL_SYS (wcsrtombs, size_t, + (char *dest, const wchar_t **srcp, size_t len, mbstate_t *ps) + _GL_ARG_NONNULL ((2))); +# endif +_GL_CXXALIAS_SYS (wcsrtombs, size_t, + (char *dest, const wchar_t **srcp, size_t len, + mbstate_t *ps)); +# endif +_GL_CXXALIASWARN (wcsrtombs); +#elif defined GNULIB_POSIXCHECK +# undef wcsrtombs +# if HAVE_RAW_DECL_WCSRTOMBS +_GL_WARN_ON_USE (wcsrtombs, "wcsrtombs is unportable - " + "use gnulib module wcsrtombs for portability"); +# endif +#endif + + +/* Convert a wide string to a string. */ +#if @GNULIB_WCSNRTOMBS@ +# if @REPLACE_WCSNRTOMBS@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef wcsnrtombs +# define wcsnrtombs rpl_wcsnrtombs +# endif +_GL_FUNCDECL_RPL (wcsnrtombs, size_t, + (char *dest, const wchar_t **srcp, size_t srclen, size_t len, + mbstate_t *ps) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (wcsnrtombs, size_t, + (char *dest, const wchar_t **srcp, size_t srclen, size_t len, + mbstate_t *ps)); +# else +# if !@HAVE_WCSNRTOMBS@ +_GL_FUNCDECL_SYS (wcsnrtombs, size_t, + (char *dest, const wchar_t **srcp, size_t srclen, size_t len, + mbstate_t *ps) + _GL_ARG_NONNULL ((2))); +# endif +_GL_CXXALIAS_SYS (wcsnrtombs, size_t, + (char *dest, const wchar_t **srcp, size_t srclen, size_t len, + mbstate_t *ps)); +# endif +_GL_CXXALIASWARN (wcsnrtombs); +#elif defined GNULIB_POSIXCHECK +# undef wcsnrtombs +# if HAVE_RAW_DECL_WCSNRTOMBS +_GL_WARN_ON_USE (wcsnrtombs, "wcsnrtombs is unportable - " + "use gnulib module wcsnrtombs for portability"); +# endif +#endif + + +/* Return the number of screen columns needed for WC. */ +#if @GNULIB_WCWIDTH@ +# if @REPLACE_WCWIDTH@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef wcwidth +# define wcwidth rpl_wcwidth +# endif +_GL_FUNCDECL_RPL (wcwidth, int, (wchar_t) _GL_ATTRIBUTE_PURE); +_GL_CXXALIAS_RPL (wcwidth, int, (wchar_t)); +# else +# if !@HAVE_DECL_WCWIDTH@ +/* wcwidth exists but is not declared. */ +_GL_FUNCDECL_SYS (wcwidth, int, (wchar_t) _GL_ATTRIBUTE_PURE); +# endif +_GL_CXXALIAS_SYS (wcwidth, int, (wchar_t)); +# endif +_GL_CXXALIASWARN (wcwidth); +#elif defined GNULIB_POSIXCHECK +# undef wcwidth +# if HAVE_RAW_DECL_WCWIDTH +_GL_WARN_ON_USE (wcwidth, "wcwidth is unportable - " + "use gnulib module wcwidth for portability"); +# endif +#endif + + +/* Search N wide characters of S for C. */ +#if @GNULIB_WMEMCHR@ +# if !@HAVE_WMEMCHR@ +_GL_FUNCDECL_SYS (wmemchr, wchar_t *, (const wchar_t *s, wchar_t c, size_t n) + _GL_ATTRIBUTE_PURE); +# endif + /* On some systems, this function is defined as an overloaded function: + extern "C++" { + const wchar_t * std::wmemchr (const wchar_t *, wchar_t, size_t); + wchar_t * std::wmemchr (wchar_t *, wchar_t, size_t); + } */ +_GL_CXXALIAS_SYS_CAST2 (wmemchr, + wchar_t *, (const wchar_t *, wchar_t, size_t), + const wchar_t *, (const wchar_t *, wchar_t, size_t)); +# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \ + && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) +_GL_CXXALIASWARN1 (wmemchr, wchar_t *, (wchar_t *s, wchar_t c, size_t n)); +_GL_CXXALIASWARN1 (wmemchr, const wchar_t *, + (const wchar_t *s, wchar_t c, size_t n)); +# else +_GL_CXXALIASWARN (wmemchr); +# endif +#elif defined GNULIB_POSIXCHECK +# undef wmemchr +# if HAVE_RAW_DECL_WMEMCHR +_GL_WARN_ON_USE (wmemchr, "wmemchr is unportable - " + "use gnulib module wmemchr for portability"); +# endif +#endif + + +/* Compare N wide characters of S1 and S2. */ +#if @GNULIB_WMEMCMP@ +# if !@HAVE_WMEMCMP@ +_GL_FUNCDECL_SYS (wmemcmp, int, + (const wchar_t *s1, const wchar_t *s2, size_t n) + _GL_ATTRIBUTE_PURE); +# endif +_GL_CXXALIAS_SYS (wmemcmp, int, + (const wchar_t *s1, const wchar_t *s2, size_t n)); +_GL_CXXALIASWARN (wmemcmp); +#elif defined GNULIB_POSIXCHECK +# undef wmemcmp +# if HAVE_RAW_DECL_WMEMCMP +_GL_WARN_ON_USE (wmemcmp, "wmemcmp is unportable - " + "use gnulib module wmemcmp for portability"); +# endif +#endif + + +/* Copy N wide characters of SRC to DEST. */ +#if @GNULIB_WMEMCPY@ +# if !@HAVE_WMEMCPY@ +_GL_FUNCDECL_SYS (wmemcpy, wchar_t *, + (wchar_t *dest, const wchar_t *src, size_t n)); +# endif +_GL_CXXALIAS_SYS (wmemcpy, wchar_t *, + (wchar_t *dest, const wchar_t *src, size_t n)); +_GL_CXXALIASWARN (wmemcpy); +#elif defined GNULIB_POSIXCHECK +# undef wmemcpy +# if HAVE_RAW_DECL_WMEMCPY +_GL_WARN_ON_USE (wmemcpy, "wmemcpy is unportable - " + "use gnulib module wmemcpy for portability"); +# endif +#endif + + +/* Copy N wide characters of SRC to DEST, guaranteeing correct behavior for + overlapping memory areas. */ +#if @GNULIB_WMEMMOVE@ +# if !@HAVE_WMEMMOVE@ +_GL_FUNCDECL_SYS (wmemmove, wchar_t *, + (wchar_t *dest, const wchar_t *src, size_t n)); +# endif +_GL_CXXALIAS_SYS (wmemmove, wchar_t *, + (wchar_t *dest, const wchar_t *src, size_t n)); +_GL_CXXALIASWARN (wmemmove); +#elif defined GNULIB_POSIXCHECK +# undef wmemmove +# if HAVE_RAW_DECL_WMEMMOVE +_GL_WARN_ON_USE (wmemmove, "wmemmove is unportable - " + "use gnulib module wmemmove for portability"); +# endif +#endif + + +/* Set N wide characters of S to C. */ +#if @GNULIB_WMEMSET@ +# if !@HAVE_WMEMSET@ +_GL_FUNCDECL_SYS (wmemset, wchar_t *, (wchar_t *s, wchar_t c, size_t n)); +# endif +_GL_CXXALIAS_SYS (wmemset, wchar_t *, (wchar_t *s, wchar_t c, size_t n)); +_GL_CXXALIASWARN (wmemset); +#elif defined GNULIB_POSIXCHECK +# undef wmemset +# if HAVE_RAW_DECL_WMEMSET +_GL_WARN_ON_USE (wmemset, "wmemset is unportable - " + "use gnulib module wmemset for portability"); +# endif +#endif + + +/* Return the number of wide characters in S. */ +#if @GNULIB_WCSLEN@ +# if !@HAVE_WCSLEN@ +_GL_FUNCDECL_SYS (wcslen, size_t, (const wchar_t *s) _GL_ATTRIBUTE_PURE); +# endif +_GL_CXXALIAS_SYS (wcslen, size_t, (const wchar_t *s)); +_GL_CXXALIASWARN (wcslen); +#elif defined GNULIB_POSIXCHECK +# undef wcslen +# if HAVE_RAW_DECL_WCSLEN +_GL_WARN_ON_USE (wcslen, "wcslen is unportable - " + "use gnulib module wcslen for portability"); +# endif +#endif + + +/* Return the number of wide characters in S, but at most MAXLEN. */ +#if @GNULIB_WCSNLEN@ +# if !@HAVE_WCSNLEN@ +_GL_FUNCDECL_SYS (wcsnlen, size_t, (const wchar_t *s, size_t maxlen) + _GL_ATTRIBUTE_PURE); +# endif +_GL_CXXALIAS_SYS (wcsnlen, size_t, (const wchar_t *s, size_t maxlen)); +_GL_CXXALIASWARN (wcsnlen); +#elif defined GNULIB_POSIXCHECK +# undef wcsnlen +# if HAVE_RAW_DECL_WCSNLEN +_GL_WARN_ON_USE (wcsnlen, "wcsnlen is unportable - " + "use gnulib module wcsnlen for portability"); +# endif +#endif + + +/* Copy SRC to DEST. */ +#if @GNULIB_WCSCPY@ +# if !@HAVE_WCSCPY@ +_GL_FUNCDECL_SYS (wcscpy, wchar_t *, (wchar_t *dest, const wchar_t *src)); +# endif +_GL_CXXALIAS_SYS (wcscpy, wchar_t *, (wchar_t *dest, const wchar_t *src)); +_GL_CXXALIASWARN (wcscpy); +#elif defined GNULIB_POSIXCHECK +# undef wcscpy +# if HAVE_RAW_DECL_WCSCPY +_GL_WARN_ON_USE (wcscpy, "wcscpy is unportable - " + "use gnulib module wcscpy for portability"); +# endif +#endif + + +/* Copy SRC to DEST, returning the address of the terminating L'\0' in DEST. */ +#if @GNULIB_WCPCPY@ +# if !@HAVE_WCPCPY@ +_GL_FUNCDECL_SYS (wcpcpy, wchar_t *, (wchar_t *dest, const wchar_t *src)); +# endif +_GL_CXXALIAS_SYS (wcpcpy, wchar_t *, (wchar_t *dest, const wchar_t *src)); +_GL_CXXALIASWARN (wcpcpy); +#elif defined GNULIB_POSIXCHECK +# undef wcpcpy +# if HAVE_RAW_DECL_WCPCPY +_GL_WARN_ON_USE (wcpcpy, "wcpcpy is unportable - " + "use gnulib module wcpcpy for portability"); +# endif +#endif + + +/* Copy no more than N wide characters of SRC to DEST. */ +#if @GNULIB_WCSNCPY@ +# if !@HAVE_WCSNCPY@ +_GL_FUNCDECL_SYS (wcsncpy, wchar_t *, + (wchar_t *dest, const wchar_t *src, size_t n)); +# endif +_GL_CXXALIAS_SYS (wcsncpy, wchar_t *, + (wchar_t *dest, const wchar_t *src, size_t n)); +_GL_CXXALIASWARN (wcsncpy); +#elif defined GNULIB_POSIXCHECK +# undef wcsncpy +# if HAVE_RAW_DECL_WCSNCPY +_GL_WARN_ON_USE (wcsncpy, "wcsncpy is unportable - " + "use gnulib module wcsncpy for portability"); +# endif +#endif + + +/* Copy no more than N characters of SRC to DEST, returning the address of + the last character written into DEST. */ +#if @GNULIB_WCPNCPY@ +# if !@HAVE_WCPNCPY@ +_GL_FUNCDECL_SYS (wcpncpy, wchar_t *, + (wchar_t *dest, const wchar_t *src, size_t n)); +# endif +_GL_CXXALIAS_SYS (wcpncpy, wchar_t *, + (wchar_t *dest, const wchar_t *src, size_t n)); +_GL_CXXALIASWARN (wcpncpy); +#elif defined GNULIB_POSIXCHECK +# undef wcpncpy +# if HAVE_RAW_DECL_WCPNCPY +_GL_WARN_ON_USE (wcpncpy, "wcpncpy is unportable - " + "use gnulib module wcpncpy for portability"); +# endif +#endif + + +/* Append SRC onto DEST. */ +#if @GNULIB_WCSCAT@ +# if !@HAVE_WCSCAT@ +_GL_FUNCDECL_SYS (wcscat, wchar_t *, (wchar_t *dest, const wchar_t *src)); +# endif +_GL_CXXALIAS_SYS (wcscat, wchar_t *, (wchar_t *dest, const wchar_t *src)); +_GL_CXXALIASWARN (wcscat); +#elif defined GNULIB_POSIXCHECK +# undef wcscat +# if HAVE_RAW_DECL_WCSCAT +_GL_WARN_ON_USE (wcscat, "wcscat is unportable - " + "use gnulib module wcscat for portability"); +# endif +#endif + + +/* Append no more than N wide characters of SRC onto DEST. */ +#if @GNULIB_WCSNCAT@ +# if !@HAVE_WCSNCAT@ +_GL_FUNCDECL_SYS (wcsncat, wchar_t *, + (wchar_t *dest, const wchar_t *src, size_t n)); +# endif +_GL_CXXALIAS_SYS (wcsncat, wchar_t *, + (wchar_t *dest, const wchar_t *src, size_t n)); +_GL_CXXALIASWARN (wcsncat); +#elif defined GNULIB_POSIXCHECK +# undef wcsncat +# if HAVE_RAW_DECL_WCSNCAT +_GL_WARN_ON_USE (wcsncat, "wcsncat is unportable - " + "use gnulib module wcsncat for portability"); +# endif +#endif + + +/* Compare S1 and S2. */ +#if @GNULIB_WCSCMP@ +# if !@HAVE_WCSCMP@ +_GL_FUNCDECL_SYS (wcscmp, int, (const wchar_t *s1, const wchar_t *s2) + _GL_ATTRIBUTE_PURE); +# endif +_GL_CXXALIAS_SYS (wcscmp, int, (const wchar_t *s1, const wchar_t *s2)); +_GL_CXXALIASWARN (wcscmp); +#elif defined GNULIB_POSIXCHECK +# undef wcscmp +# if HAVE_RAW_DECL_WCSCMP +_GL_WARN_ON_USE (wcscmp, "wcscmp is unportable - " + "use gnulib module wcscmp for portability"); +# endif +#endif + + +/* Compare no more than N wide characters of S1 and S2. */ +#if @GNULIB_WCSNCMP@ +# if !@HAVE_WCSNCMP@ +_GL_FUNCDECL_SYS (wcsncmp, int, + (const wchar_t *s1, const wchar_t *s2, size_t n) + _GL_ATTRIBUTE_PURE); +# endif +_GL_CXXALIAS_SYS (wcsncmp, int, + (const wchar_t *s1, const wchar_t *s2, size_t n)); +_GL_CXXALIASWARN (wcsncmp); +#elif defined GNULIB_POSIXCHECK +# undef wcsncmp +# if HAVE_RAW_DECL_WCSNCMP +_GL_WARN_ON_USE (wcsncmp, "wcsncmp is unportable - " + "use gnulib module wcsncmp for portability"); +# endif +#endif + + +/* Compare S1 and S2, ignoring case. */ +#if @GNULIB_WCSCASECMP@ +# if !@HAVE_WCSCASECMP@ +_GL_FUNCDECL_SYS (wcscasecmp, int, (const wchar_t *s1, const wchar_t *s2) + _GL_ATTRIBUTE_PURE); +# endif +_GL_CXXALIAS_SYS (wcscasecmp, int, (const wchar_t *s1, const wchar_t *s2)); +_GL_CXXALIASWARN (wcscasecmp); +#elif defined GNULIB_POSIXCHECK +# undef wcscasecmp +# if HAVE_RAW_DECL_WCSCASECMP +_GL_WARN_ON_USE (wcscasecmp, "wcscasecmp is unportable - " + "use gnulib module wcscasecmp for portability"); +# endif +#endif + + +/* Compare no more than N chars of S1 and S2, ignoring case. */ +#if @GNULIB_WCSNCASECMP@ +# if !@HAVE_WCSNCASECMP@ +_GL_FUNCDECL_SYS (wcsncasecmp, int, + (const wchar_t *s1, const wchar_t *s2, size_t n) + _GL_ATTRIBUTE_PURE); +# endif +_GL_CXXALIAS_SYS (wcsncasecmp, int, + (const wchar_t *s1, const wchar_t *s2, size_t n)); +_GL_CXXALIASWARN (wcsncasecmp); +#elif defined GNULIB_POSIXCHECK +# undef wcsncasecmp +# if HAVE_RAW_DECL_WCSNCASECMP +_GL_WARN_ON_USE (wcsncasecmp, "wcsncasecmp is unportable - " + "use gnulib module wcsncasecmp for portability"); +# endif +#endif + + +/* Compare S1 and S2, both interpreted as appropriate to the LC_COLLATE + category of the current locale. */ +#if @GNULIB_WCSCOLL@ +# if !@HAVE_WCSCOLL@ +_GL_FUNCDECL_SYS (wcscoll, int, (const wchar_t *s1, const wchar_t *s2)); +# endif +_GL_CXXALIAS_SYS (wcscoll, int, (const wchar_t *s1, const wchar_t *s2)); +_GL_CXXALIASWARN (wcscoll); +#elif defined GNULIB_POSIXCHECK +# undef wcscoll +# if HAVE_RAW_DECL_WCSCOLL +_GL_WARN_ON_USE (wcscoll, "wcscoll is unportable - " + "use gnulib module wcscoll for portability"); +# endif +#endif + + +/* Transform S2 into array pointed to by S1 such that if wcscmp is applied + to two transformed strings the result is the as applying 'wcscoll' to the + original strings. */ +#if @GNULIB_WCSXFRM@ +# if !@HAVE_WCSXFRM@ +_GL_FUNCDECL_SYS (wcsxfrm, size_t, (wchar_t *s1, const wchar_t *s2, size_t n)); +# endif +_GL_CXXALIAS_SYS (wcsxfrm, size_t, (wchar_t *s1, const wchar_t *s2, size_t n)); +_GL_CXXALIASWARN (wcsxfrm); +#elif defined GNULIB_POSIXCHECK +# undef wcsxfrm +# if HAVE_RAW_DECL_WCSXFRM +_GL_WARN_ON_USE (wcsxfrm, "wcsxfrm is unportable - " + "use gnulib module wcsxfrm for portability"); +# endif +#endif + + +/* Duplicate S, returning an identical malloc'd string. */ +#if @GNULIB_WCSDUP@ +# if !@HAVE_WCSDUP@ +_GL_FUNCDECL_SYS (wcsdup, wchar_t *, (const wchar_t *s)); +# endif +_GL_CXXALIAS_SYS (wcsdup, wchar_t *, (const wchar_t *s)); +_GL_CXXALIASWARN (wcsdup); +#elif defined GNULIB_POSIXCHECK +# undef wcsdup +# if HAVE_RAW_DECL_WCSDUP +_GL_WARN_ON_USE (wcsdup, "wcsdup is unportable - " + "use gnulib module wcsdup for portability"); +# endif +#endif + + +/* Find the first occurrence of WC in WCS. */ +#if @GNULIB_WCSCHR@ +# if !@HAVE_WCSCHR@ +_GL_FUNCDECL_SYS (wcschr, wchar_t *, (const wchar_t *wcs, wchar_t wc) + _GL_ATTRIBUTE_PURE); +# endif + /* On some systems, this function is defined as an overloaded function: + extern "C++" { + const wchar_t * std::wcschr (const wchar_t *, wchar_t); + wchar_t * std::wcschr (wchar_t *, wchar_t); + } */ +_GL_CXXALIAS_SYS_CAST2 (wcschr, + wchar_t *, (const wchar_t *, wchar_t), + const wchar_t *, (const wchar_t *, wchar_t)); +# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \ + && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) +_GL_CXXALIASWARN1 (wcschr, wchar_t *, (wchar_t *wcs, wchar_t wc)); +_GL_CXXALIASWARN1 (wcschr, const wchar_t *, (const wchar_t *wcs, wchar_t wc)); +# else +_GL_CXXALIASWARN (wcschr); +# endif +#elif defined GNULIB_POSIXCHECK +# undef wcschr +# if HAVE_RAW_DECL_WCSCHR +_GL_WARN_ON_USE (wcschr, "wcschr is unportable - " + "use gnulib module wcschr for portability"); +# endif +#endif + + +/* Find the last occurrence of WC in WCS. */ +#if @GNULIB_WCSRCHR@ +# if !@HAVE_WCSRCHR@ +_GL_FUNCDECL_SYS (wcsrchr, wchar_t *, (const wchar_t *wcs, wchar_t wc) + _GL_ATTRIBUTE_PURE); +# endif + /* On some systems, this function is defined as an overloaded function: + extern "C++" { + const wchar_t * std::wcsrchr (const wchar_t *, wchar_t); + wchar_t * std::wcsrchr (wchar_t *, wchar_t); + } */ +_GL_CXXALIAS_SYS_CAST2 (wcsrchr, + wchar_t *, (const wchar_t *, wchar_t), + const wchar_t *, (const wchar_t *, wchar_t)); +# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \ + && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) +_GL_CXXALIASWARN1 (wcsrchr, wchar_t *, (wchar_t *wcs, wchar_t wc)); +_GL_CXXALIASWARN1 (wcsrchr, const wchar_t *, (const wchar_t *wcs, wchar_t wc)); +# else +_GL_CXXALIASWARN (wcsrchr); +# endif +#elif defined GNULIB_POSIXCHECK +# undef wcsrchr +# if HAVE_RAW_DECL_WCSRCHR +_GL_WARN_ON_USE (wcsrchr, "wcsrchr is unportable - " + "use gnulib module wcsrchr for portability"); +# endif +#endif + + +/* Return the length of the initial segmet of WCS which consists entirely + of wide characters not in REJECT. */ +#if @GNULIB_WCSCSPN@ +# if !@HAVE_WCSCSPN@ +_GL_FUNCDECL_SYS (wcscspn, size_t, (const wchar_t *wcs, const wchar_t *reject) + _GL_ATTRIBUTE_PURE); +# endif +_GL_CXXALIAS_SYS (wcscspn, size_t, (const wchar_t *wcs, const wchar_t *reject)); +_GL_CXXALIASWARN (wcscspn); +#elif defined GNULIB_POSIXCHECK +# undef wcscspn +# if HAVE_RAW_DECL_WCSCSPN +_GL_WARN_ON_USE (wcscspn, "wcscspn is unportable - " + "use gnulib module wcscspn for portability"); +# endif +#endif + + +/* Return the length of the initial segmet of WCS which consists entirely + of wide characters in ACCEPT. */ +#if @GNULIB_WCSSPN@ +# if !@HAVE_WCSSPN@ +_GL_FUNCDECL_SYS (wcsspn, size_t, (const wchar_t *wcs, const wchar_t *accept) + _GL_ATTRIBUTE_PURE); +# endif +_GL_CXXALIAS_SYS (wcsspn, size_t, (const wchar_t *wcs, const wchar_t *accept)); +_GL_CXXALIASWARN (wcsspn); +#elif defined GNULIB_POSIXCHECK +# undef wcsspn +# if HAVE_RAW_DECL_WCSSPN +_GL_WARN_ON_USE (wcsspn, "wcsspn is unportable - " + "use gnulib module wcsspn for portability"); +# endif +#endif + + +/* Find the first occurrence in WCS of any character in ACCEPT. */ +#if @GNULIB_WCSPBRK@ +# if !@HAVE_WCSPBRK@ +_GL_FUNCDECL_SYS (wcspbrk, wchar_t *, + (const wchar_t *wcs, const wchar_t *accept) + _GL_ATTRIBUTE_PURE); +# endif + /* On some systems, this function is defined as an overloaded function: + extern "C++" { + const wchar_t * std::wcspbrk (const wchar_t *, const wchar_t *); + wchar_t * std::wcspbrk (wchar_t *, const wchar_t *); + } */ +_GL_CXXALIAS_SYS_CAST2 (wcspbrk, + wchar_t *, (const wchar_t *, const wchar_t *), + const wchar_t *, (const wchar_t *, const wchar_t *)); +# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \ + && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) +_GL_CXXALIASWARN1 (wcspbrk, wchar_t *, + (wchar_t *wcs, const wchar_t *accept)); +_GL_CXXALIASWARN1 (wcspbrk, const wchar_t *, + (const wchar_t *wcs, const wchar_t *accept)); +# else +_GL_CXXALIASWARN (wcspbrk); +# endif +#elif defined GNULIB_POSIXCHECK +# undef wcspbrk +# if HAVE_RAW_DECL_WCSPBRK +_GL_WARN_ON_USE (wcspbrk, "wcspbrk is unportable - " + "use gnulib module wcspbrk for portability"); +# endif +#endif + + +/* Find the first occurrence of NEEDLE in HAYSTACK. */ +#if @GNULIB_WCSSTR@ +# if !@HAVE_WCSSTR@ +_GL_FUNCDECL_SYS (wcsstr, wchar_t *, + (const wchar_t *haystack, const wchar_t *needle) + _GL_ATTRIBUTE_PURE); +# endif + /* On some systems, this function is defined as an overloaded function: + extern "C++" { + const wchar_t * std::wcsstr (const wchar_t *, const wchar_t *); + wchar_t * std::wcsstr (wchar_t *, const wchar_t *); + } */ +_GL_CXXALIAS_SYS_CAST2 (wcsstr, + wchar_t *, (const wchar_t *, const wchar_t *), + const wchar_t *, (const wchar_t *, const wchar_t *)); +# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \ + && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) +_GL_CXXALIASWARN1 (wcsstr, wchar_t *, + (wchar_t *haystack, const wchar_t *needle)); +_GL_CXXALIASWARN1 (wcsstr, const wchar_t *, + (const wchar_t *haystack, const wchar_t *needle)); +# else +_GL_CXXALIASWARN (wcsstr); +# endif +#elif defined GNULIB_POSIXCHECK +# undef wcsstr +# if HAVE_RAW_DECL_WCSSTR +_GL_WARN_ON_USE (wcsstr, "wcsstr is unportable - " + "use gnulib module wcsstr for portability"); +# endif +#endif + + +/* Divide WCS into tokens separated by characters in DELIM. */ +#if @GNULIB_WCSTOK@ +# if !@HAVE_WCSTOK@ +_GL_FUNCDECL_SYS (wcstok, wchar_t *, + (wchar_t *wcs, const wchar_t *delim, wchar_t **ptr)); +# endif +_GL_CXXALIAS_SYS (wcstok, wchar_t *, + (wchar_t *wcs, const wchar_t *delim, wchar_t **ptr)); +_GL_CXXALIASWARN (wcstok); +#elif defined GNULIB_POSIXCHECK +# undef wcstok +# if HAVE_RAW_DECL_WCSTOK +_GL_WARN_ON_USE (wcstok, "wcstok is unportable - " + "use gnulib module wcstok for portability"); +# endif +#endif + + +/* Determine number of column positions required for first N wide + characters (or fewer if S ends before this) in S. */ +#if @GNULIB_WCSWIDTH@ +# if @REPLACE_WCSWIDTH@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef wcswidth +# define wcswidth rpl_wcswidth +# endif +_GL_FUNCDECL_RPL (wcswidth, int, (const wchar_t *s, size_t n) + _GL_ATTRIBUTE_PURE); +_GL_CXXALIAS_RPL (wcswidth, int, (const wchar_t *s, size_t n)); +# else +# if !@HAVE_WCSWIDTH@ +_GL_FUNCDECL_SYS (wcswidth, int, (const wchar_t *s, size_t n) + _GL_ATTRIBUTE_PURE); +# endif +_GL_CXXALIAS_SYS (wcswidth, int, (const wchar_t *s, size_t n)); +# endif +_GL_CXXALIASWARN (wcswidth); +#elif defined GNULIB_POSIXCHECK +# undef wcswidth +# if HAVE_RAW_DECL_WCSWIDTH +_GL_WARN_ON_USE (wcswidth, "wcswidth is unportable - " + "use gnulib module wcswidth for portability"); +# endif +#endif + + +#endif /* _@GUARD_PREFIX@_WCHAR_H */ +#endif /* _@GUARD_PREFIX@_WCHAR_H */ +#endif diff --git a/gettext-tools/gnulib-lib/wctype-h.c b/gettext-tools/gnulib-lib/wctype-h.c new file mode 100644 index 0000000..bb5f847 --- /dev/null +++ b/gettext-tools/gnulib-lib/wctype-h.c @@ -0,0 +1,4 @@ +/* Normally this would be wctype.c, but that name's already taken. */ +#include +#define _GL_WCTYPE_INLINE _GL_EXTERN_INLINE +#include "wctype.h" diff --git a/gettext-tools/gnulib-lib/wctype.in.h b/gettext-tools/gnulib-lib/wctype.in.h new file mode 100644 index 0000000..ab06653 --- /dev/null +++ b/gettext-tools/gnulib-lib/wctype.in.h @@ -0,0 +1,514 @@ +/* A substitute for ISO C99 , for platforms that lack it. + + Copyright (C) 2006-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . */ + +/* Written by Bruno Haible and Paul Eggert. */ + +/* + * ISO C 99 for platforms that lack it. + * + * + * iswctype, towctrans, towlower, towupper, wctrans, wctype, + * wctrans_t, and wctype_t are not yet implemented. + */ + +#ifndef _@GUARD_PREFIX@_WCTYPE_H + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +#if @HAVE_WINT_T@ +/* Solaris 2.5 has a bug: must be included before . + Tru64 with Desktop Toolkit C has a bug: must be included before + . + BSD/OS 4.0.1 has a bug: , and must be + included before . */ +# include +# include +# include +# include +#endif + +/* mingw has declarations of towupper and towlower in as + well . Include in advance to avoid rpl_ prefix + being added to the declarations. */ +#ifdef __MINGW32__ +# include +#endif + +/* Include the original if it exists. + BeOS 5 has the functions but no . */ +/* The include_next requires a split double-inclusion guard. */ +#if @HAVE_WCTYPE_H@ +# @INCLUDE_NEXT@ @NEXT_WCTYPE_H@ +#endif + +#ifndef _@GUARD_PREFIX@_WCTYPE_H +#define _@GUARD_PREFIX@_WCTYPE_H + +#ifndef _GL_INLINE_HEADER_BEGIN + #error "Please include config.h first." +#endif +_GL_INLINE_HEADER_BEGIN +#ifndef _GL_WCTYPE_INLINE +# define _GL_WCTYPE_INLINE _GL_INLINE +#endif + +/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ + +/* The definition of _GL_WARN_ON_USE is copied here. */ + +/* Solaris 2.6 includes which includes which + #defines a number of identifiers in the application namespace. Revert + these #defines. */ +#ifdef __sun +# undef multibyte +# undef eucw1 +# undef eucw2 +# undef eucw3 +# undef scrw1 +# undef scrw2 +# undef scrw3 +#endif + +/* Define wint_t and WEOF. (Also done in wchar.in.h.) */ +#if !@HAVE_WINT_T@ && !defined wint_t +# define wint_t int +# ifndef WEOF +# define WEOF -1 +# endif +#else +/* MSVC defines wint_t as 'unsigned short' in . + This is too small: ISO C 99 section 7.24.1.(2) says that wint_t must be + "unchanged by default argument promotions". Override it. */ +# if defined _MSC_VER +# if !GNULIB_defined_wint_t +# include +typedef unsigned int rpl_wint_t; +# undef wint_t +# define wint_t rpl_wint_t +# define GNULIB_defined_wint_t 1 +# endif +# endif +# ifndef WEOF +# define WEOF ((wint_t) -1) +# endif +#endif + + +#if !GNULIB_defined_wctype_functions + +/* FreeBSD 4.4 to 4.11 has but lacks the functions. + Linux libc5 has and the functions but they are broken. + Assume all 11 functions (all isw* except iswblank) are implemented the + same way, or not at all. */ +# if ! @HAVE_ISWCNTRL@ || @REPLACE_ISWCNTRL@ + +/* IRIX 5.3 has macros but no functions, its isw* macros refer to an + undefined variable _ctmp_ and to macros like _P, and they + refer to system functions like _iswctype that are not in the + standard C library. Rather than try to get ancient buggy + implementations like this to work, just disable them. */ +# undef iswalnum +# undef iswalpha +# undef iswblank +# undef iswcntrl +# undef iswdigit +# undef iswgraph +# undef iswlower +# undef iswprint +# undef iswpunct +# undef iswspace +# undef iswupper +# undef iswxdigit +# undef towlower +# undef towupper + +/* Linux libc5 has and the functions but they are broken. */ +# if @REPLACE_ISWCNTRL@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define iswalnum rpl_iswalnum +# define iswalpha rpl_iswalpha +# define iswblank rpl_iswblank +# define iswcntrl rpl_iswcntrl +# define iswdigit rpl_iswdigit +# define iswgraph rpl_iswgraph +# define iswlower rpl_iswlower +# define iswprint rpl_iswprint +# define iswpunct rpl_iswpunct +# define iswspace rpl_iswspace +# define iswupper rpl_iswupper +# define iswxdigit rpl_iswxdigit +# endif +# endif +# if @REPLACE_TOWLOWER@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define towlower rpl_towlower +# define towupper rpl_towupper +# endif +# endif + +_GL_WCTYPE_INLINE int +# if @REPLACE_ISWCNTRL@ +rpl_iswalnum +# else +iswalnum +# endif + (wint_t wc) +{ + return ((wc >= '0' && wc <= '9') + || ((wc & ~0x20) >= 'A' && (wc & ~0x20) <= 'Z')); +} + +_GL_WCTYPE_INLINE int +# if @REPLACE_ISWCNTRL@ +rpl_iswalpha +# else +iswalpha +# endif + (wint_t wc) +{ + return (wc & ~0x20) >= 'A' && (wc & ~0x20) <= 'Z'; +} + +_GL_WCTYPE_INLINE int +# if @REPLACE_ISWCNTRL@ +rpl_iswblank +# else +iswblank +# endif + (wint_t wc) +{ + return wc == ' ' || wc == '\t'; +} + +_GL_WCTYPE_INLINE int +# if @REPLACE_ISWCNTRL@ +rpl_iswcntrl +# else +iswcntrl +# endif + (wint_t wc) +{ + return (wc & ~0x1f) == 0 || wc == 0x7f; +} + +_GL_WCTYPE_INLINE int +# if @REPLACE_ISWCNTRL@ +rpl_iswdigit +# else +iswdigit +# endif + (wint_t wc) +{ + return wc >= '0' && wc <= '9'; +} + +_GL_WCTYPE_INLINE int +# if @REPLACE_ISWCNTRL@ +rpl_iswgraph +# else +iswgraph +# endif + (wint_t wc) +{ + return wc >= '!' && wc <= '~'; +} + +_GL_WCTYPE_INLINE int +# if @REPLACE_ISWCNTRL@ +rpl_iswlower +# else +iswlower +# endif + (wint_t wc) +{ + return wc >= 'a' && wc <= 'z'; +} + +_GL_WCTYPE_INLINE int +# if @REPLACE_ISWCNTRL@ +rpl_iswprint +# else +iswprint +# endif + (wint_t wc) +{ + return wc >= ' ' && wc <= '~'; +} + +_GL_WCTYPE_INLINE int +# if @REPLACE_ISWCNTRL@ +rpl_iswpunct +# else +iswpunct +# endif + (wint_t wc) +{ + return (wc >= '!' && wc <= '~' + && !((wc >= '0' && wc <= '9') + || ((wc & ~0x20) >= 'A' && (wc & ~0x20) <= 'Z'))); +} + +_GL_WCTYPE_INLINE int +# if @REPLACE_ISWCNTRL@ +rpl_iswspace +# else +iswspace +# endif + (wint_t wc) +{ + return (wc == ' ' || wc == '\t' + || wc == '\n' || wc == '\v' || wc == '\f' || wc == '\r'); +} + +_GL_WCTYPE_INLINE int +# if @REPLACE_ISWCNTRL@ +rpl_iswupper +# else +iswupper +# endif + (wint_t wc) +{ + return wc >= 'A' && wc <= 'Z'; +} + +_GL_WCTYPE_INLINE int +# if @REPLACE_ISWCNTRL@ +rpl_iswxdigit +# else +iswxdigit +# endif + (wint_t wc) +{ + return ((wc >= '0' && wc <= '9') + || ((wc & ~0x20) >= 'A' && (wc & ~0x20) <= 'F')); +} + +_GL_WCTYPE_INLINE wint_t +# if @REPLACE_TOWLOWER@ +rpl_towlower +# else +towlower +# endif + (wint_t wc) +{ + return (wc >= 'A' && wc <= 'Z' ? wc - 'A' + 'a' : wc); +} + +_GL_WCTYPE_INLINE wint_t +# if @REPLACE_TOWLOWER@ +rpl_towupper +# else +towupper +# endif + (wint_t wc) +{ + return (wc >= 'a' && wc <= 'z' ? wc - 'a' + 'A' : wc); +} + +# elif @GNULIB_ISWBLANK@ && (! @HAVE_ISWBLANK@ || @REPLACE_ISWBLANK@) +/* Only the iswblank function is missing. */ + +# if @REPLACE_ISWBLANK@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define iswblank rpl_iswblank +# endif +_GL_FUNCDECL_RPL (iswblank, int, (wint_t wc)); +# else +_GL_FUNCDECL_SYS (iswblank, int, (wint_t wc)); +# endif + +# endif + +# if defined __MINGW32__ + +/* On native Windows, wchar_t is uint16_t, and wint_t is uint32_t. + The functions towlower and towupper are implemented in the MSVCRT library + to take a wchar_t argument and return a wchar_t result. mingw declares + these functions to take a wint_t argument and return a wint_t result. + This means that: + 1. When the user passes an argument outside the range 0x0000..0xFFFF, the + function will look only at the lower 16 bits. This is allowed according + to POSIX. + 2. The return value is returned in the lower 16 bits of the result register. + The upper 16 bits are random: whatever happened to be in that part of the + result register. We need to fix this by adding a zero-extend from + wchar_t to wint_t after the call. */ + +_GL_WCTYPE_INLINE wint_t +rpl_towlower (wint_t wc) +{ + return (wint_t) (wchar_t) towlower (wc); +} +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define towlower rpl_towlower +# endif + +_GL_WCTYPE_INLINE wint_t +rpl_towupper (wint_t wc) +{ + return (wint_t) (wchar_t) towupper (wc); +} +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define towupper rpl_towupper +# endif + +# endif /* __MINGW32__ */ + +# define GNULIB_defined_wctype_functions 1 +#endif + +#if @REPLACE_ISWCNTRL@ +_GL_CXXALIAS_RPL (iswalnum, int, (wint_t wc)); +_GL_CXXALIAS_RPL (iswalpha, int, (wint_t wc)); +_GL_CXXALIAS_RPL (iswcntrl, int, (wint_t wc)); +_GL_CXXALIAS_RPL (iswdigit, int, (wint_t wc)); +_GL_CXXALIAS_RPL (iswgraph, int, (wint_t wc)); +_GL_CXXALIAS_RPL (iswlower, int, (wint_t wc)); +_GL_CXXALIAS_RPL (iswprint, int, (wint_t wc)); +_GL_CXXALIAS_RPL (iswpunct, int, (wint_t wc)); +_GL_CXXALIAS_RPL (iswspace, int, (wint_t wc)); +_GL_CXXALIAS_RPL (iswupper, int, (wint_t wc)); +_GL_CXXALIAS_RPL (iswxdigit, int, (wint_t wc)); +#else +_GL_CXXALIAS_SYS (iswalnum, int, (wint_t wc)); +_GL_CXXALIAS_SYS (iswalpha, int, (wint_t wc)); +_GL_CXXALIAS_SYS (iswcntrl, int, (wint_t wc)); +_GL_CXXALIAS_SYS (iswdigit, int, (wint_t wc)); +_GL_CXXALIAS_SYS (iswgraph, int, (wint_t wc)); +_GL_CXXALIAS_SYS (iswlower, int, (wint_t wc)); +_GL_CXXALIAS_SYS (iswprint, int, (wint_t wc)); +_GL_CXXALIAS_SYS (iswpunct, int, (wint_t wc)); +_GL_CXXALIAS_SYS (iswspace, int, (wint_t wc)); +_GL_CXXALIAS_SYS (iswupper, int, (wint_t wc)); +_GL_CXXALIAS_SYS (iswxdigit, int, (wint_t wc)); +#endif +_GL_CXXALIASWARN (iswalnum); +_GL_CXXALIASWARN (iswalpha); +_GL_CXXALIASWARN (iswcntrl); +_GL_CXXALIASWARN (iswdigit); +_GL_CXXALIASWARN (iswgraph); +_GL_CXXALIASWARN (iswlower); +_GL_CXXALIASWARN (iswprint); +_GL_CXXALIASWARN (iswpunct); +_GL_CXXALIASWARN (iswspace); +_GL_CXXALIASWARN (iswupper); +_GL_CXXALIASWARN (iswxdigit); + +#if @GNULIB_ISWBLANK@ +# if @REPLACE_ISWCNTRL@ || @REPLACE_ISWBLANK@ +_GL_CXXALIAS_RPL (iswblank, int, (wint_t wc)); +# else +_GL_CXXALIAS_SYS (iswblank, int, (wint_t wc)); +# endif +_GL_CXXALIASWARN (iswblank); +#endif + +#if !@HAVE_WCTYPE_T@ +# if !GNULIB_defined_wctype_t +typedef void * wctype_t; +# define GNULIB_defined_wctype_t 1 +# endif +#endif + +/* Get a descriptor for a wide character property. */ +#if @GNULIB_WCTYPE@ +# if !@HAVE_WCTYPE_T@ +_GL_FUNCDECL_SYS (wctype, wctype_t, (const char *name)); +# endif +_GL_CXXALIAS_SYS (wctype, wctype_t, (const char *name)); +_GL_CXXALIASWARN (wctype); +#elif defined GNULIB_POSIXCHECK +# undef wctype +# if HAVE_RAW_DECL_WCTYPE +_GL_WARN_ON_USE (wctype, "wctype is unportable - " + "use gnulib module wctype for portability"); +# endif +#endif + +/* Test whether a wide character has a given property. + The argument WC must be either a wchar_t value or WEOF. + The argument DESC must have been returned by the wctype() function. */ +#if @GNULIB_ISWCTYPE@ +# if !@HAVE_WCTYPE_T@ +_GL_FUNCDECL_SYS (iswctype, int, (wint_t wc, wctype_t desc)); +# endif +_GL_CXXALIAS_SYS (iswctype, int, (wint_t wc, wctype_t desc)); +_GL_CXXALIASWARN (iswctype); +#elif defined GNULIB_POSIXCHECK +# undef iswctype +# if HAVE_RAW_DECL_ISWCTYPE +_GL_WARN_ON_USE (iswctype, "iswctype is unportable - " + "use gnulib module iswctype for portability"); +# endif +#endif + +#if @REPLACE_TOWLOWER@ || defined __MINGW32__ +_GL_CXXALIAS_RPL (towlower, wint_t, (wint_t wc)); +_GL_CXXALIAS_RPL (towupper, wint_t, (wint_t wc)); +#else +_GL_CXXALIAS_SYS (towlower, wint_t, (wint_t wc)); +_GL_CXXALIAS_SYS (towupper, wint_t, (wint_t wc)); +#endif +_GL_CXXALIASWARN (towlower); +_GL_CXXALIASWARN (towupper); + +#if !@HAVE_WCTRANS_T@ +# if !GNULIB_defined_wctrans_t +typedef void * wctrans_t; +# define GNULIB_defined_wctrans_t 1 +# endif +#endif + +/* Get a descriptor for a wide character case conversion. */ +#if @GNULIB_WCTRANS@ +# if !@HAVE_WCTRANS_T@ +_GL_FUNCDECL_SYS (wctrans, wctrans_t, (const char *name)); +# endif +_GL_CXXALIAS_SYS (wctrans, wctrans_t, (const char *name)); +_GL_CXXALIASWARN (wctrans); +#elif defined GNULIB_POSIXCHECK +# undef wctrans +# if HAVE_RAW_DECL_WCTRANS +_GL_WARN_ON_USE (wctrans, "wctrans is unportable - " + "use gnulib module wctrans for portability"); +# endif +#endif + +/* Perform a given case conversion on a wide character. + The argument WC must be either a wchar_t value or WEOF. + The argument DESC must have been returned by the wctrans() function. */ +#if @GNULIB_TOWCTRANS@ +# if !@HAVE_WCTRANS_T@ +_GL_FUNCDECL_SYS (towctrans, wint_t, (wint_t wc, wctrans_t desc)); +# endif +_GL_CXXALIAS_SYS (towctrans, wint_t, (wint_t wc, wctrans_t desc)); +_GL_CXXALIASWARN (towctrans); +#elif defined GNULIB_POSIXCHECK +# undef towctrans +# if HAVE_RAW_DECL_TOWCTRANS +_GL_WARN_ON_USE (towctrans, "towctrans is unportable - " + "use gnulib module towctrans for portability"); +# endif +#endif + +_GL_INLINE_HEADER_END + +#endif /* _@GUARD_PREFIX@_WCTYPE_H */ +#endif /* _@GUARD_PREFIX@_WCTYPE_H */ diff --git a/gettext-tools/gnulib-lib/wcwidth.c b/gettext-tools/gnulib-lib/wcwidth.c new file mode 100644 index 0000000..d7837bb --- /dev/null +++ b/gettext-tools/gnulib-lib/wcwidth.c @@ -0,0 +1,50 @@ +/* Determine the number of screen columns needed for a character. + Copyright (C) 2006-2007, 2010-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include + +/* Get iswprint. */ +#include + +#include "localcharset.h" +#include "streq.h" +#include "uniwidth.h" + +int +wcwidth (wchar_t wc) +#undef wcwidth +{ + /* In UTF-8 locales, use a Unicode aware width function. */ + const char *encoding = locale_charset (); + if (STREQ_OPT (encoding, "UTF-8", 'U', 'T', 'F', '-', '8', 0, 0, 0 ,0)) + { + /* We assume that in a UTF-8 locale, a wide character is the same as a + Unicode character. */ + return uc_width (wc, encoding); + } + else + { + /* Otherwise, fall back to the system's wcwidth function. */ +#if HAVE_WCWIDTH + return wcwidth (wc); +#else + return wc == 0 ? 0 : iswprint (wc) ? 1 : -1; +#endif + } +} diff --git a/gettext-tools/gnulib-lib/write.c b/gettext-tools/gnulib-lib/write.c new file mode 100644 index 0000000..ff31dbb --- /dev/null +++ b/gettext-tools/gnulib-lib/write.c @@ -0,0 +1,145 @@ +/* POSIX compatible write() function. + Copyright (C) 2008-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2008. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include + +/* On native Windows platforms, SIGPIPE does not exist. When write() is + called on a pipe with no readers, WriteFile() fails with error + GetLastError() = ERROR_NO_DATA, and write() in consequence fails with + error EINVAL. */ + +#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ + +# include +# include +# include + +# define WIN32_LEAN_AND_MEAN /* avoid including junk */ +# include + +# include "msvc-inval.h" +# include "msvc-nothrow.h" + +# undef write + +# if HAVE_MSVC_INVALID_PARAMETER_HANDLER +static ssize_t +write_nothrow (int fd, const void *buf, size_t count) +{ + ssize_t result; + + TRY_MSVC_INVAL + { + result = write (fd, buf, count); + } + CATCH_MSVC_INVAL + { + result = -1; + errno = EBADF; + } + DONE_MSVC_INVAL; + + return result; +} +# else +# define write_nothrow write +# endif + +ssize_t +rpl_write (int fd, const void *buf, size_t count) +{ + for (;;) + { + ssize_t ret = write_nothrow (fd, buf, count); + + if (ret < 0) + { +# if GNULIB_NONBLOCKING + if (errno == ENOSPC) + { + HANDLE h = (HANDLE) _get_osfhandle (fd); + if (GetFileType (h) == FILE_TYPE_PIPE) + { + /* h is a pipe or socket. */ + DWORD state; + if (GetNamedPipeHandleState (h, &state, NULL, NULL, NULL, + NULL, 0) + && (state & PIPE_NOWAIT) != 0) + { + /* h is a pipe in non-blocking mode. + We can get here in four situations: + 1. When the pipe buffer is full. + 2. When count <= pipe_buf_size and the number of + free bytes in the pipe buffer is < count. + 3. When count > pipe_buf_size and the number of free + bytes in the pipe buffer is > 0, < pipe_buf_size. + 4. When count > pipe_buf_size and the pipe buffer is + entirely empty. + The cases 1 and 2 are POSIX compliant. In cases 3 and + 4 POSIX specifies that write() must split the request + and succeed with a partial write. We fix case 4. + We don't fix case 3 because it is not essential for + programs. */ + DWORD out_size; /* size of the buffer for outgoing data */ + DWORD in_size; /* size of the buffer for incoming data */ + if (GetNamedPipeInfo (h, NULL, &out_size, &in_size, NULL)) + { + size_t reduced_count = count; + /* In theory we need only one of out_size, in_size. + But I don't know which of the two. The description + is ambiguous. */ + if (out_size != 0 && out_size < reduced_count) + reduced_count = out_size; + if (in_size != 0 && in_size < reduced_count) + reduced_count = in_size; + if (reduced_count < count) + { + /* Attempt to write only the first part. */ + count = reduced_count; + continue; + } + } + /* Change errno from ENOSPC to EAGAIN. */ + errno = EAGAIN; + } + } + } + else +# endif + { +# if GNULIB_SIGPIPE + if (GetLastError () == ERROR_NO_DATA + && GetFileType ((HANDLE) _get_osfhandle (fd)) + == FILE_TYPE_PIPE) + { + /* Try to raise signal SIGPIPE. */ + raise (SIGPIPE); + /* If it is currently blocked or ignored, change errno from + EINVAL to EPIPE. */ + errno = EPIPE; + } +# endif + } + } + return ret; + } +} + +#endif diff --git a/gettext-tools/gnulib-lib/xalloc.h b/gettext-tools/gnulib-lib/xalloc.h new file mode 100644 index 0000000..1ad1009 --- /dev/null +++ b/gettext-tools/gnulib-lib/xalloc.h @@ -0,0 +1,158 @@ +/* malloc with out of memory checking. + Copyright (C) 2001-2004, 2006 Free Software Foundation, Inc. + Written by Bruno Haible , 2001. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _XALLOC_H +#define _XALLOC_H + +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Defined in xmalloc.c. */ + +/* Allocate SIZE bytes of memory dynamically, with error checking. */ +extern void *xmalloc (size_t size); + +/* Allocate memory for NMEMB elements of SIZE bytes, with error checking. + SIZE must be > 0. */ +extern void *xnmalloc (size_t nmemb, size_t size); + +/* Allocate SIZE bytes of memory dynamically, with error checking, + and zero it. */ +extern void *xzalloc (size_t size); + +/* Allocate memory for NMEMB elements of SIZE bytes, with error checking, + and zero it. */ +extern void *xcalloc (size_t nmemb, size_t size); + +/* Change the size of an allocated block of memory PTR to SIZE bytes, + with error checking. If PTR is NULL, run xmalloc. */ +extern void *xrealloc (void *ptr, size_t size); +#ifdef __cplusplus +} +template + inline T * xrealloc (T * ptr, size_t size) + { + return (T *) xrealloc ((void *) ptr, size); + } +extern "C" { +#endif + +/* This function is always triggered when memory is exhausted. It is + in charge of honoring the three previous items. This is the + function to call when one wants the program to die because of a + memory allocation failure. */ +extern void xalloc_die (void) +#if (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5)) && !__STRICT_ANSI__ + __attribute__ ((__noreturn__)) +#endif + ; + +/* In the following macros, T must be an elementary or structure/union or + typedef'ed type, or a pointer to such a type. To apply one of the + following macros to a function pointer or array type, you need to typedef + it first and use the typedef name. */ + +/* Allocate an object of type T dynamically, with error checking. */ +/* extern T *XMALLOC (typename T); */ +#define XMALLOC(T) \ + ((T *) xmalloc (sizeof (T))) + +/* Allocate memory for NMEMB elements of type T, with error checking. */ +/* extern T *XNMALLOC (size_t nmemb, typename T); */ +#if HAVE_INLINE +/* xnmalloc performs a division and multiplication by sizeof (T). Arrange to + perform the division at compile-time and the multiplication with a factor + known at compile-time. */ +# define XNMALLOC(N,T) \ + ((T *) (sizeof (T) == 1 \ + ? xmalloc (N) \ + : xnboundedmalloc(N, (size_t) (sizeof (ptrdiff_t) <= sizeof (size_t) ? -1 : -2) / sizeof (T), sizeof (T)))) +static inline void * +xnboundedmalloc (size_t n, size_t bound, size_t s) +{ + if (n > bound) + xalloc_die (); + return xmalloc (n * s); +} +#else +# define XNMALLOC(N,T) \ + ((T *) (sizeof (T) == 1 ? xmalloc (N) : xnmalloc (N, sizeof (T)))) +#endif + +/* Allocate an object of type T dynamically, with error checking, + and zero it. */ +/* extern T *XZALLOC (typename T); */ +#define XZALLOC(T) \ + ((T *) xzalloc (sizeof (T))) + +/* Allocate memory for NMEMB elements of type T, with error checking, + and zero it. */ +/* extern T *XCALLOC (size_t nmemb, typename T); */ +#define XCALLOC(N,T) \ + ((T *) xcalloc (N, sizeof (T))) + +/* Return a pointer to a new buffer of N bytes. This is like xmalloc, + except it returns char *. */ +#define xcharalloc(N) \ + XNMALLOC (N, char) + + +/* Defined in xstrdup.c. */ + +/* Return a newly allocated copy of the N bytes of memory starting at P. */ +extern void *xmemdup (const void *p, size_t n); +#ifdef __cplusplus +} +template + inline T * xmemdup (const T * p, size_t n) + { + return (T *) xmemdup ((const void *) p, n); + } +extern "C" { +#endif + +/* Return a newly allocated copy of STRING. */ +extern char *xstrdup (const char *string); + + +/* Return 1 if an array of N objects, each of size S, cannot exist due + to size arithmetic overflow. S must be positive and N must be + nonnegative. This is a macro, not an inline function, so that it + works correctly even when SIZE_MAX < N. + + By gnulib convention, SIZE_MAX represents overflow in size + calculations, so the conservative dividend to use here is + SIZE_MAX - 1, since SIZE_MAX might represent an overflowed value. + However, malloc (SIZE_MAX) fails on all known hosts where + sizeof (ptrdiff_t) <= sizeof (size_t), so do not bother to test for + exactly-SIZE_MAX allocations on such hosts; this avoids a test and + branch when S is known to be 1. */ +# define xalloc_oversized(n, s) \ + ((size_t) (sizeof (ptrdiff_t) <= sizeof (size_t) ? -1 : -2) / (s) < (n)) + + +#ifdef __cplusplus +} +#endif + + +#endif /* _XALLOC_H */ diff --git a/gettext-tools/gnulib-lib/xasprintf.c b/gettext-tools/gnulib-lib/xasprintf.c new file mode 100644 index 0000000..4e0b5b1 --- /dev/null +++ b/gettext-tools/gnulib-lib/xasprintf.c @@ -0,0 +1,34 @@ +/* vasprintf and asprintf with out-of-memory checking. + Copyright (C) 1999, 2002-2004, 2006, 2009-2014 Free Software Foundation, + Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include "xvasprintf.h" + +char * +xasprintf (const char *format, ...) +{ + va_list args; + char *result; + + va_start (args, format); + result = xvasprintf (format, args); + va_end (args); + + return result; +} diff --git a/gettext-tools/gnulib-lib/xconcat-filename.c b/gettext-tools/gnulib-lib/xconcat-filename.c new file mode 100644 index 0000000..956f958 --- /dev/null +++ b/gettext-tools/gnulib-lib/xconcat-filename.c @@ -0,0 +1,41 @@ +/* Construct a full filename from a directory and a relative filename. + Copyright (C) 2001-2004, 2006-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 3 of the License, or any + later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Written by Bruno Haible . */ + +#include + +/* Specification. */ +#include "concat-filename.h" + +#include "xalloc.h" + +/* Concatenate a directory filename, a relative filename and an optional + suffix. The directory may end with the directory separator. The second + argument may not start with the directory separator (it is relative). + Return a freshly allocated filename. */ +char * +xconcatenated_filename (const char *directory, const char *filename, + const char *suffix) +{ + char *result; + + result = concatenated_filename (directory, filename, suffix); + if (result == NULL) + xalloc_die (); + + return result; +} diff --git a/gettext-tools/gnulib-lib/xerror.c b/gettext-tools/gnulib-lib/xerror.c new file mode 100644 index 0000000..b803f48 --- /dev/null +++ b/gettext-tools/gnulib-lib/xerror.c @@ -0,0 +1,96 @@ +/* Multiline error-reporting functions. + Copyright (C) 2001-2003, 2006 Free Software Foundation, Inc. + Written by Bruno Haible , 2001. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + + +#include + +/* Specification. */ +#include "xerror.h" + +#include +#include +#include + +#include "error.h" +#include "progname.h" +#include "error-progname.h" +#include "mbswidth.h" + +/* Emit a multiline warning to stderr, consisting of MESSAGE, with the + first line prefixed with PREFIX and the remaining lines prefixed with + the same amount of spaces. Reuse the spaces of the previous call if + PREFIX is NULL. Free the PREFIX and MESSAGE when done. */ +void +multiline_warning (char *prefix, char *message) +{ + static int width; + const char *cp; + int i; + + fflush (stdout); + + cp = message; + + if (prefix != NULL) + { + width = 0; + if (error_with_progname) + { + fprintf (stderr, "%s: ", program_name); + width += mbswidth (program_name, 0) + 2; + } + fputs (prefix, stderr); + width += mbswidth (prefix, 0); + free (prefix); + goto after_indent; + } + + for (;;) + { + const char *np; + + for (i = width; i > 0; i--) + putc (' ', stderr); + + after_indent: + np = strchr (cp, '\n'); + + if (np == NULL || np[1] == '\0') + { + fputs (cp, stderr); + break; + } + + np++; + fwrite (cp, 1, np - cp, stderr); + cp = np; + } + + free (message); +} + +/* Emit a multiline error to stderr, consisting of MESSAGE, with the + first line prefixed with PREFIX and the remaining lines prefixed with + the same amount of spaces. Reuse the spaces of the previous call if + PREFIX is NULL. Free the PREFIX and MESSAGE when done. */ +void +multiline_error (char *prefix, char *message) +{ + if (prefix != NULL) + ++error_message_count; + multiline_warning (prefix, message); +} diff --git a/gettext-tools/gnulib-lib/xerror.h b/gettext-tools/gnulib-lib/xerror.h new file mode 100644 index 0000000..28b39c1 --- /dev/null +++ b/gettext-tools/gnulib-lib/xerror.h @@ -0,0 +1,45 @@ +/* Multiline error-reporting functions. + Copyright (C) 2001-2003, 2006 Free Software Foundation, Inc. + Written by Bruno Haible , 2001. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _XERROR_H +#define _XERROR_H + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Emit a multiline warning to stderr, consisting of MESSAGE, with the + first line prefixed with PREFIX and the remaining lines prefixed with + the same amount of spaces. Reuse the spaces of the previous call if + PREFIX is NULL. Free the PREFIX and MESSAGE when done. */ +extern void multiline_warning (char *prefix, char *message); + +/* Emit a multiline error to stderr, consisting of MESSAGE, with the + first line prefixed with PREFIX and the remaining lines prefixed with + the same amount of spaces. Reuse the spaces of the previous call if + PREFIX is NULL. Free the PREFIX and MESSAGE when done. */ +extern void multiline_error (char *prefix, char *message); + + +#ifdef __cplusplus +} +#endif + + +#endif /* _XERROR_H */ diff --git a/gettext-tools/gnulib-lib/xmalloc.c b/gettext-tools/gnulib-lib/xmalloc.c new file mode 100644 index 0000000..223f994 --- /dev/null +++ b/gettext-tools/gnulib-lib/xmalloc.c @@ -0,0 +1,128 @@ +/* xmalloc.c -- malloc with out of memory checking + Copyright (C) 1990-1996, 2000-2003, 2005-2007, 2012 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include "xalloc.h" + +#include + +#include "error.h" +#include "gettext.h" + +#define _(str) gettext (str) + + +/* Exit value when the requested amount of memory is not available. + The caller may set it to some other value. */ +int xmalloc_exit_failure = EXIT_FAILURE; + +void +xalloc_die () +{ + error (xmalloc_exit_failure, 0, _("memory exhausted")); + /* _Noreturn cannot be given to error, since it may return if + its first argument is 0. To help compilers understand the + xalloc_die does terminate, call exit. */ + exit (EXIT_FAILURE); +} + +static void * +fixup_null_alloc (size_t n) +{ + void *p; + + p = NULL; + if (n == 0) + p = malloc ((size_t) 1); + if (p == NULL) + xalloc_die (); + return p; +} + +/* Allocate N bytes of memory dynamically, with error checking. */ + +void * +xmalloc (size_t n) +{ + void *p; + + p = malloc (n); + if (p == NULL) + p = fixup_null_alloc (n); + return p; +} + +/* Allocate memory for NMEMB elements of SIZE bytes, with error checking. + SIZE must be > 0. */ + +void * +xnmalloc (size_t nmemb, size_t size) +{ + size_t n; + void *p; + + if (xalloc_oversized (nmemb, size)) + xalloc_die (); + n = nmemb * size; + p = malloc (n); + if (p == NULL) + p = fixup_null_alloc (n); + return p; +} + +/* Allocate SIZE bytes of memory dynamically, with error checking, + and zero it. */ + +void * +xzalloc (size_t size) +{ + void *p; + + p = xmalloc (size); + memset (p, 0, size); + return p; +} + +/* Allocate memory for N elements of S bytes, with error checking, + and zero it. */ + +void * +xcalloc (size_t n, size_t s) +{ + void *p; + + p = calloc (n, s); + if (p == NULL) + p = fixup_null_alloc (n); + return p; +} + +/* Change the size of an allocated block of memory P to N bytes, + with error checking. + If P is NULL, run xmalloc. */ + +void * +xrealloc (void *p, size_t n) +{ + if (p == NULL) + return xmalloc (n); + p = realloc (p, n); + if (p == NULL) + p = fixup_null_alloc (n); + return p; +} diff --git a/gettext-tools/gnulib-lib/xmalloca.c b/gettext-tools/gnulib-lib/xmalloca.c new file mode 100644 index 0000000..9861b44 --- /dev/null +++ b/gettext-tools/gnulib-lib/xmalloca.c @@ -0,0 +1,38 @@ +/* Safe automatic memory allocation with out of memory checking. + Copyright (C) 2003, 2006-2007, 2009-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2003. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include "xmalloca.h" + +#include "xalloc.h" + +#if HAVE_ALLOCA + +void * +xmmalloca (size_t n) +{ + void *p; + + p = mmalloca (n); + if (p == NULL) + xalloc_die (); + return p; +} + +#endif diff --git a/gettext-tools/gnulib-lib/xmalloca.h b/gettext-tools/gnulib-lib/xmalloca.h new file mode 100644 index 0000000..a6b98cf --- /dev/null +++ b/gettext-tools/gnulib-lib/xmalloca.h @@ -0,0 +1,64 @@ +/* Safe automatic memory allocation with out of memory checking. + Copyright (C) 2003, 2005, 2007, 2009-2014 Free Software Foundation, Inc. + Written by Bruno Haible , 2003. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _XMALLOCA_H +#define _XMALLOCA_H + +#include "malloca.h" +#include "xalloc.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* xmalloca(N) is a checking safe variant of alloca(N). It allocates N bytes + of memory allocated on the stack, that must be freed using freea() before + the function returns. Upon failure, it exits with an error message. */ +#if HAVE_ALLOCA +# define xmalloca(N) \ + ((N) < 4032 - sa_increment \ + ? (void *) ((char *) alloca ((N) + sa_increment) + sa_increment) \ + : xmmalloca (N)) +extern void * xmmalloca (size_t n); +#else +# define xmalloca(N) \ + xmalloc (N) +#endif + +/* xnmalloca(N,S) is an overflow-safe variant of xmalloca (N * S). + It allocates an array of N objects, each with S bytes of memory, + on the stack. S must be positive and N must be nonnegative. + The array must be freed using freea() before the function returns. + Upon failure, it exits with an error message. */ +#if HAVE_ALLOCA +/* Rely on xmalloca (SIZE_MAX) calling xalloc_die (). */ +# define xnmalloca(n, s) \ + xmalloca (xalloc_oversized ((n), (s)) ? (size_t) (-1) : (n) * (s)) +#else +# define xnmalloca(n, s) \ + xnmalloc ((n), (s)) +#endif + + +#ifdef __cplusplus +} +#endif + + +#endif /* _XMALLOCA_H */ diff --git a/gettext-tools/gnulib-lib/xreadlink.c b/gettext-tools/gnulib-lib/xreadlink.c new file mode 100644 index 0000000..2f3b8a1 --- /dev/null +++ b/gettext-tools/gnulib-lib/xreadlink.c @@ -0,0 +1,44 @@ +/* xreadlink.c -- readlink wrapper to return the link name in malloc'd storage + + Copyright (C) 2001, 2003-2007, 2009-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Written by Jim Meyering + and Bruno Haible . */ + +#include + +/* Specification. */ +#include "xreadlink.h" + +#include + +#include "areadlink.h" +#include "xalloc.h" + +/* Call readlink to get the symbolic link value of FILENAME. + Return a pointer to that NUL-terminated string in malloc'd storage. + If readlink fails, return NULL and set errno. + If realloc fails, or if the link value is longer than SIZE_MAX :-), + give a diagnostic and exit. */ + +char * +xreadlink (char const *filename) +{ + char *result = areadlink (filename); + if (result == NULL && errno == ENOMEM) + xalloc_die (); + return result; +} diff --git a/gettext-tools/gnulib-lib/xreadlink.h b/gettext-tools/gnulib-lib/xreadlink.h new file mode 100644 index 0000000..af80ca4 --- /dev/null +++ b/gettext-tools/gnulib-lib/xreadlink.h @@ -0,0 +1,25 @@ +/* Reading symbolic links without size limitation. + + Copyright (C) 2001, 2003-2004, 2007, 2009-2014 Free Software Foundation, + Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Written by Jim Meyering */ + +extern char *xreadlink (char const *filename); + +#if GNULIB_XREADLINKAT +extern char *xreadlinkat (int fd, char const *filename); +#endif diff --git a/gettext-tools/gnulib-lib/xsetenv.c b/gettext-tools/gnulib-lib/xsetenv.c new file mode 100644 index 0000000..4dcfb24 --- /dev/null +++ b/gettext-tools/gnulib-lib/xsetenv.c @@ -0,0 +1,38 @@ +/* Setting environment variables, with out-of-memory checking. + Copyright (C) 2001-2002, 2005-2007, 2009-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include "xsetenv.h" + +#include + +#include "error.h" +#include "gettext.h" + +#define _(str) gettext (str) + + +/* Set NAME to VALUE in the environment. + If REPLACE is nonzero, overwrite an existing value. + With error checking. */ +void +xsetenv (const char *name, const char *value, int replace) +{ + if (setenv (name, value, replace) < 0) + error (EXIT_FAILURE, 0, _("memory exhausted")); +} diff --git a/gettext-tools/gnulib-lib/xsetenv.h b/gettext-tools/gnulib-lib/xsetenv.h new file mode 100644 index 0000000..b0bf932 --- /dev/null +++ b/gettext-tools/gnulib-lib/xsetenv.h @@ -0,0 +1,31 @@ +/* Setting environment variables, with out-of-memory checking. + Copyright (C) 2001-2002, 2007, 2009-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Get unsetenv(). It can be used without error checking. */ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Set NAME to VALUE in the environment. + If REPLACE is nonzero, overwrite an existing value. + With error checking. */ +extern void xsetenv (const char *name, const char *value, int replace); + +#ifdef __cplusplus +} +#endif diff --git a/gettext-tools/gnulib-lib/xsize.c b/gettext-tools/gnulib-lib/xsize.c new file mode 100644 index 0000000..4b4914c --- /dev/null +++ b/gettext-tools/gnulib-lib/xsize.c @@ -0,0 +1,3 @@ +#include +#define XSIZE_INLINE _GL_EXTERN_INLINE +#include "xsize.h" diff --git a/gettext-tools/gnulib-lib/xsize.h b/gettext-tools/gnulib-lib/xsize.h new file mode 100644 index 0000000..fd12c67 --- /dev/null +++ b/gettext-tools/gnulib-lib/xsize.h @@ -0,0 +1,117 @@ +/* xsize.h -- Checked size_t computations. + + Copyright (C) 2003, 2008-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . */ + +#ifndef _XSIZE_H +#define _XSIZE_H + +/* Get size_t. */ +#include + +/* Get SIZE_MAX. */ +#include +#if HAVE_STDINT_H +# include +#endif + +#ifndef _GL_INLINE_HEADER_BEGIN + #error "Please include config.h first." +#endif +_GL_INLINE_HEADER_BEGIN +#ifndef XSIZE_INLINE +# define XSIZE_INLINE _GL_INLINE +#endif + +/* The size of memory objects is often computed through expressions of + type size_t. Example: + void* p = malloc (header_size + n * element_size). + These computations can lead to overflow. When this happens, malloc() + returns a piece of memory that is way too small, and the program then + crashes while attempting to fill the memory. + To avoid this, the functions and macros in this file check for overflow. + The convention is that SIZE_MAX represents overflow. + malloc (SIZE_MAX) is not guaranteed to fail -- think of a malloc + implementation that uses mmap --, it's recommended to use size_overflow_p() + or size_in_bounds_p() before invoking malloc(). + The example thus becomes: + size_t size = xsum (header_size, xtimes (n, element_size)); + void *p = (size_in_bounds_p (size) ? malloc (size) : NULL); +*/ + +/* Convert an arbitrary value >= 0 to type size_t. */ +#define xcast_size_t(N) \ + ((N) <= SIZE_MAX ? (size_t) (N) : SIZE_MAX) + +/* Sum of two sizes, with overflow check. */ +XSIZE_INLINE size_t +#if __GNUC__ >= 3 +__attribute__ ((__pure__)) +#endif +xsum (size_t size1, size_t size2) +{ + size_t sum = size1 + size2; + return (sum >= size1 ? sum : SIZE_MAX); +} + +/* Sum of three sizes, with overflow check. */ +XSIZE_INLINE size_t +#if __GNUC__ >= 3 +__attribute__ ((__pure__)) +#endif +xsum3 (size_t size1, size_t size2, size_t size3) +{ + return xsum (xsum (size1, size2), size3); +} + +/* Sum of four sizes, with overflow check. */ +XSIZE_INLINE size_t +#if __GNUC__ >= 3 +__attribute__ ((__pure__)) +#endif +xsum4 (size_t size1, size_t size2, size_t size3, size_t size4) +{ + return xsum (xsum (xsum (size1, size2), size3), size4); +} + +/* Maximum of two sizes, with overflow check. */ +XSIZE_INLINE size_t +#if __GNUC__ >= 3 +__attribute__ ((__pure__)) +#endif +xmax (size_t size1, size_t size2) +{ + /* No explicit check is needed here, because for any n: + max (SIZE_MAX, n) == SIZE_MAX and max (n, SIZE_MAX) == SIZE_MAX. */ + return (size1 >= size2 ? size1 : size2); +} + +/* Multiplication of a count with an element size, with overflow check. + The count must be >= 0 and the element size must be > 0. + This is a macro, not a function, so that it works correctly even + when N is of a wider type and N > SIZE_MAX. */ +#define xtimes(N, ELSIZE) \ + ((N) <= SIZE_MAX / (ELSIZE) ? (size_t) (N) * (ELSIZE) : SIZE_MAX) + +/* Check for overflow. */ +#define size_overflow_p(SIZE) \ + ((SIZE) == SIZE_MAX) +/* Check against overflow. */ +#define size_in_bounds_p(SIZE) \ + ((SIZE) != SIZE_MAX) + +_GL_INLINE_HEADER_END + +#endif /* _XSIZE_H */ diff --git a/gettext-tools/gnulib-lib/xstrdup.c b/gettext-tools/gnulib-lib/xstrdup.c new file mode 100644 index 0000000..9ad1b94 --- /dev/null +++ b/gettext-tools/gnulib-lib/xstrdup.c @@ -0,0 +1,40 @@ +/* xstrdup.c -- copy a string with out of memory checking + Copyright (C) 1990, 1996, 2000-2003, 2005-2006 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include "xalloc.h" + +#include + +/* Return a newly allocated copy of the N bytes of memory starting at P. */ + +void * +xmemdup (const void *p, size_t n) +{ + void *q = xmalloc (n); + memcpy (q, p, n); + return q; +} + +/* Return a newly allocated copy of STRING. */ + +char * +xstrdup (const char *string) +{ + return strcpy (XNMALLOC (strlen (string) + 1, char), string); +} diff --git a/gettext-tools/gnulib-lib/xstriconv.c b/gettext-tools/gnulib-lib/xstriconv.c new file mode 100644 index 0000000..be1ef2d --- /dev/null +++ b/gettext-tools/gnulib-lib/xstriconv.c @@ -0,0 +1,62 @@ +/* Charset conversion with out-of-memory checking. + Copyright (C) 2001-2004, 2006, 2009-2014 Free Software Foundation, Inc. + Written by Bruno Haible. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include "xstriconv.h" + +#include + +#include "striconv.h" +#include "xalloc.h" + + +#if HAVE_ICONV + +int +xmem_cd_iconv (const char *src, size_t srclen, iconv_t cd, + char **resultp, size_t *lengthp) +{ + int retval = mem_cd_iconv (src, srclen, cd, resultp, lengthp); + + if (retval < 0 && errno == ENOMEM) + xalloc_die (); + return retval; +} + +char * +xstr_cd_iconv (const char *src, iconv_t cd) +{ + char *result = str_cd_iconv (src, cd); + + if (result == NULL && errno == ENOMEM) + xalloc_die (); + return result; +} + +#endif + +char * +xstr_iconv (const char *src, const char *from_codeset, const char *to_codeset) +{ + char *result = str_iconv (src, from_codeset, to_codeset); + + if (result == NULL && errno == ENOMEM) + xalloc_die (); + return result; +} diff --git a/gettext-tools/gnulib-lib/xstriconv.h b/gettext-tools/gnulib-lib/xstriconv.h new file mode 100644 index 0000000..75f8f83 --- /dev/null +++ b/gettext-tools/gnulib-lib/xstriconv.h @@ -0,0 +1,78 @@ +/* Charset conversion with out-of-memory checking. + Copyright (C) 2001-2004, 2006-2007, 2009-2014 Free Software Foundation, Inc. + Written by Bruno Haible and Simon Josefsson. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _XSTRICONV_H +#define _XSTRICONV_H + +#include +#if HAVE_ICONV +#include +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + + +#if HAVE_ICONV + +/* Convert an entire string from one encoding to another, using iconv. + The original string is at [SRC,...,SRC+SRCLEN-1]. + The conversion descriptor is passed as CD. + *RESULTP and *LENGTH should initially be a scratch buffer and its size, + or *RESULTP can initially be NULL. + May erase the contents of the memory at *RESULTP. + Upon memory allocation failure, report the error and exit. + Return value: 0 if successful, otherwise -1 and errno set. + If successful: The resulting string is stored in *RESULTP and its length + in *LENGTHP. *RESULTP is set to a freshly allocated memory block, or is + unchanged if no dynamic memory allocation was necessary. */ +extern int xmem_cd_iconv (const char *src, size_t srclen, iconv_t cd, + char **resultp, size_t *lengthp); + +/* Convert an entire string from one encoding to another, using iconv. + The original string is the NUL-terminated string starting at SRC. + The conversion descriptor is passed as CD. Both the "from" and the "to" + encoding must use a single NUL byte at the end of the string (i.e. not + UCS-2, UCS-4, UTF-16, UTF-32). + Allocate a malloced memory block for the result. + Upon memory allocation failure, report the error and exit. + Return value: the freshly allocated resulting NUL-terminated string if + successful, otherwise NULL and errno set. */ +extern char * xstr_cd_iconv (const char *src, iconv_t cd); + +#endif + +/* Convert an entire string from one encoding to another, using iconv. + The original string is the NUL-terminated string starting at SRC. + Both the "from" and the "to" encoding must use a single NUL byte at the + end of the string (i.e. not UCS-2, UCS-4, UTF-16, UTF-32). + Allocate a malloced memory block for the result. + Upon memory allocation failure, report the error and exit. + Return value: the freshly allocated resulting NUL-terminated string if + successful, otherwise NULL and errno set. */ +extern char * xstr_iconv (const char *src, + const char *from_codeset, const char *to_codeset); + + +#ifdef __cplusplus +} +#endif + + +#endif /* _XSTRICONV_H */ diff --git a/gettext-tools/gnulib-lib/xstriconveh.c b/gettext-tools/gnulib-lib/xstriconveh.c new file mode 100644 index 0000000..57d3d4c --- /dev/null +++ b/gettext-tools/gnulib-lib/xstriconveh.c @@ -0,0 +1,86 @@ +/* Charset conversion with out-of-memory checking. + Copyright (C) 2009-2014 Free Software Foundation, Inc. + Written by Bruno Haible. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include "xstriconveh.h" + +#include + +#include "striconveh.h" +#include "xalloc.h" + + +#if HAVE_ICONV + +int +xmem_cd_iconveh (const char *src, size_t srclen, + const iconveh_t *cd, + enum iconv_ilseq_handler handler, + size_t *offsets, + char **resultp, size_t *lengthp) +{ + int retval = + mem_cd_iconveh (src, srclen, cd, handler, offsets, resultp, lengthp); + + if (retval < 0 && errno == ENOMEM) + xalloc_die (); + return retval; +} + +char * +xstr_cd_iconveh (const char *src, + const iconveh_t *cd, + enum iconv_ilseq_handler handler) +{ + char *result = str_cd_iconveh (src, cd, handler); + + if (result == NULL && errno == ENOMEM) + xalloc_die (); + return result; +} + +#endif + +int +xmem_iconveh (const char *src, size_t srclen, + const char *from_codeset, const char *to_codeset, + enum iconv_ilseq_handler handler, + size_t *offsets, + char **resultp, size_t *lengthp) +{ + int retval = + mem_iconveh (src, srclen, from_codeset, to_codeset, handler, offsets, + resultp, lengthp); + + if (retval < 0 && errno == ENOMEM) + xalloc_die (); + return retval; +} + +char * +xstr_iconveh (const char *src, + const char *from_codeset, const char *to_codeset, + enum iconv_ilseq_handler handler) +{ + char *result = str_iconveh (src, from_codeset, to_codeset, handler); + + if (result == NULL && errno == ENOMEM) + xalloc_die (); + return result; +} diff --git a/gettext-tools/gnulib-lib/xstriconveh.h b/gettext-tools/gnulib-lib/xstriconveh.h new file mode 100644 index 0000000..761f84a --- /dev/null +++ b/gettext-tools/gnulib-lib/xstriconveh.h @@ -0,0 +1,115 @@ +/* Charset conversion with out-of-memory checking. + Copyright (C) 2001-2007, 2009-2014 Free Software Foundation, Inc. + Written by Bruno Haible and Simon Josefsson. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _XSTRICONVEH_H +#define _XSTRICONVEH_H + +#include + +/* Get the 'enum iconv_ilseq_handler' and iconveh_t types, and the + iconveh_open, iconveh_close declarations. */ +#include "striconveh.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +#if HAVE_ICONV + +/* Convert an entire string from one encoding to another, using iconv. + The original string is at [SRC,...,SRC+SRCLEN-1]. + CD points to the conversion descriptor from FROMCODE to TOCODE, created by + the function iconveh_open(). + If OFFSETS is not NULL, it should point to an array of SRCLEN integers; this + array is filled with offsets into the result, i.e. the character starting + at SRC[i] corresponds to the character starting at (*RESULTP)[OFFSETS[i]], + and other offsets are set to (size_t)(-1). + *RESULTP and *LENGTH should initially be a scratch buffer and its size, + or *RESULTP can initially be NULL. + May erase the contents of the memory at *RESULTP. + Upon memory allocation failure, report the error and exit. + Return value: 0 if successful, otherwise -1 and errno set. + If successful: The resulting string is stored in *RESULTP and its length + in *LENGTHP. *RESULTP is set to a freshly allocated memory block, or is + unchanged if no dynamic memory allocation was necessary. */ +extern int + xmem_cd_iconveh (const char *src, size_t srclen, + const iconveh_t *cd, + enum iconv_ilseq_handler handler, + size_t *offsets, + char **resultp, size_t *lengthp); + +/* Convert an entire string from one encoding to another, using iconv. + The original string is the NUL-terminated string starting at SRC. + CD points to the conversion descriptor from FROMCODE to TOCODE, created by + the function iconveh_open(). + Both the "from" and the "to" encoding must use a single NUL byte at the end + of the string (i.e. not UCS-2, UCS-4, UTF-16, UTF-32). + Allocate a malloced memory block for the result. + Upon memory allocation failure, report the error and exit. + Return value: the freshly allocated resulting NUL-terminated string if + successful, otherwise NULL and errno set. */ +extern char * + xstr_cd_iconveh (const char *src, + const iconveh_t *cd, + enum iconv_ilseq_handler handler); + +#endif + +/* Convert an entire string from one encoding to another, using iconv. + The original string is at [SRC,...,SRC+SRCLEN-1]. + If OFFSETS is not NULL, it should point to an array of SRCLEN integers; this + array is filled with offsets into the result, i.e. the character starting + at SRC[i] corresponds to the character starting at (*RESULTP)[OFFSETS[i]], + and other offsets are set to (size_t)(-1). + *RESULTP and *LENGTH should initially be a scratch buffer and its size, + or *RESULTP can initially be NULL. + May erase the contents of the memory at *RESULTP. + Upon memory allocation failure, report the error and exit. + Return value: 0 if successful, otherwise -1 and errno set. + If successful: The resulting string is stored in *RESULTP and its length + in *LENGTHP. *RESULTP is set to a freshly allocated memory block, or is + unchanged if no dynamic memory allocation was necessary. */ +extern int + xmem_iconveh (const char *src, size_t srclen, + const char *from_codeset, const char *to_codeset, + enum iconv_ilseq_handler handler, + size_t *offsets, + char **resultp, size_t *lengthp); + +/* Convert an entire string from one encoding to another, using iconv. + The original string is the NUL-terminated string starting at SRC. + Both the "from" and the "to" encoding must use a single NUL byte at the + end of the string (i.e. not UCS-2, UCS-4, UTF-16, UTF-32). + Allocate a malloced memory block for the result. + Upon memory allocation failure, report the error and exit. + Return value: the freshly allocated resulting NUL-terminated string if + successful, otherwise NULL and errno set. */ +extern char * + xstr_iconveh (const char *src, + const char *from_codeset, const char *to_codeset, + enum iconv_ilseq_handler handler); + + +#ifdef __cplusplus +} +#endif + + +#endif /* _XSTRICONVEH_H */ diff --git a/gettext-tools/gnulib-lib/xvasprintf.c b/gettext-tools/gnulib-lib/xvasprintf.c new file mode 100644 index 0000000..7a4029e --- /dev/null +++ b/gettext-tools/gnulib-lib/xvasprintf.c @@ -0,0 +1,110 @@ +/* vasprintf and asprintf with out-of-memory checking. + Copyright (C) 1999, 2002-2004, 2006-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include "xvasprintf.h" + +#include +#include +#include +#include + +#include "xalloc.h" + +/* Checked size_t computations. */ +#include "xsize.h" + +static char * +xstrcat (size_t argcount, va_list args) +{ + char *result; + va_list ap; + size_t totalsize; + size_t i; + char *p; + + /* Determine the total size. */ + totalsize = 0; + va_copy (ap, args); + for (i = argcount; i > 0; i--) + { + const char *next = va_arg (ap, const char *); + totalsize = xsum (totalsize, strlen (next)); + } + va_end (ap); + + /* Test for overflow in the summing pass above or in (totalsize + 1) below. + Also, don't return a string longer than INT_MAX, for consistency with + vasprintf(). */ + if (totalsize == SIZE_MAX || totalsize > INT_MAX) + { + errno = EOVERFLOW; + return NULL; + } + + /* Allocate and fill the result string. */ + result = XNMALLOC (totalsize + 1, char); + p = result; + for (i = argcount; i > 0; i--) + { + const char *next = va_arg (args, const char *); + size_t len = strlen (next); + memcpy (p, next, len); + p += len; + } + *p = '\0'; + + return result; +} + +char * +xvasprintf (const char *format, va_list args) +{ + char *result; + + /* Recognize the special case format = "%s...%s". It is a frequently used + idiom for string concatenation and needs to be fast. We don't want to + have a separate function xstrcat() for this purpose. */ + { + size_t argcount = 0; + const char *f; + + for (f = format;;) + { + if (*f == '\0') + /* Recognized the special case of string concatenation. */ + return xstrcat (argcount, args); + if (*f != '%') + break; + f++; + if (*f != 's') + break; + f++; + argcount++; + } + } + + if (vasprintf (&result, format, args) < 0) + { + if (errno == ENOMEM) + xalloc_die (); + return NULL; + } + + return result; +} diff --git a/gettext-tools/gnulib-lib/xvasprintf.h b/gettext-tools/gnulib-lib/xvasprintf.h new file mode 100644 index 0000000..407a5e0 --- /dev/null +++ b/gettext-tools/gnulib-lib/xvasprintf.h @@ -0,0 +1,55 @@ +/* vasprintf and asprintf with out-of-memory checking. + Copyright (C) 2002-2004, 2006-2014 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _XVASPRINTF_H +#define _XVASPRINTF_H + +/* Get va_list. */ +#include + +/* The __attribute__ feature is available in gcc versions 2.5 and later. + The __-protected variants of the attributes 'format' and 'printf' are + accepted by gcc versions 2.6.4 (effectively 2.7) and later. + We enable _GL_ATTRIBUTE_FORMAT only if these are supported too, because + gnulib and libintl do '#define printf __printf__' when they override + the 'printf' function. */ +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7) +# define _GL_ATTRIBUTE_FORMAT(spec) __attribute__ ((__format__ spec)) +#else +# define _GL_ATTRIBUTE_FORMAT(spec) /* empty */ +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* Write formatted output to a string dynamically allocated with malloc(), + and return it. Upon [ENOMEM] memory allocation error, call xalloc_die. + On some other error + - [EOVERFLOW] resulting string length is > INT_MAX, + - [EINVAL] invalid format string, + - [EILSEQ] error during conversion between wide and multibyte characters, + return NULL. */ +extern char *xasprintf (const char *format, ...) + _GL_ATTRIBUTE_FORMAT ((__printf__, 1, 2)); +extern char *xvasprintf (const char *format, va_list args) + _GL_ATTRIBUTE_FORMAT ((__printf__, 1, 0)); + +#ifdef __cplusplus +} +#endif + +#endif /* _XVASPRINTF_H */ -- cgit v1.2.1